using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace Automaton
{
class Program
{
const string INDENT = "\t";
static void Main(string[] args)
{
DateTimeChecker checker = new DateTimeChecker();
List<Tuple<string, DateTimeChecker.Formats>> testCase = new List<Tuple<string, DateTimeChecker.Formats>>();
testCase.Add(Tuple.Create("2018/11/16 12:34:56.789", DateTimeChecker.Formats.yyyyMMddHHmmssfff));
testCase.Add(Tuple.Create("2018/11/16 12:34:56.78", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11/16 12:34:56.7", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11/16 12:34:56.", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11/16 12:34:56", DateTimeChecker.Formats.yyyyMMddHHmmss));
testCase.Add(Tuple.Create("2018/11/16 12:34:5", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11/16 12:34:", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11/16 12:34", DateTimeChecker.Formats.yyyyMMddHHmm));
testCase.Add(Tuple.Create("2018/11/16 12:3", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11/16 12:", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11/16 12", DateTimeChecker.Formats.yyyyMMddHH));
testCase.Add(Tuple.Create("2018/11/16 1", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11/16 ", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11/16", DateTimeChecker.Formats.yyyyMMdd));
testCase.Add(Tuple.Create("2018/11/1", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11/", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/11", DateTimeChecker.Formats.yyyyMM));
testCase.Add(Tuple.Create("2018/1", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018/", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2018", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("201", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("20", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("2", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("", DateTimeChecker.Formats.None));
TestDateTime(checker, testCase);
checker.Reset();
testCase.Clear();
testCase.Add(Tuple.Create("18/11/16 12:34:56.789", DateTimeChecker.Formats.yyMMddHHmmssfff));
testCase.Add(Tuple.Create("18/11/16 12:34:56.78", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11/16 12:34:56.7", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11/16 12:34:56.", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11/16 12:34:56", DateTimeChecker.Formats.yyMMddHHmmss));
testCase.Add(Tuple.Create("18/11/16 12:34:5", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11/16 12:34:", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11/16 12:34", DateTimeChecker.Formats.yyMMddHHmm));
testCase.Add(Tuple.Create("18/11/16 12:3", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11/16 12:", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11/16 12", DateTimeChecker.Formats.yyMMddHH));
testCase.Add(Tuple.Create("18/11/16 1", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11/16 ", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11/16", DateTimeChecker.Formats.yyMMdd));
testCase.Add(Tuple.Create("18/11/1", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11/", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/11", DateTimeChecker.Formats.MMdd));
testCase.Add(Tuple.Create("18/1", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18/", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("18", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("1", DateTimeChecker.Formats.None));
TestDateTime(checker, testCase);
checker.Reset();
testCase.Clear();
testCase.Add(Tuple.Create("11/16 12:34:56.789", DateTimeChecker.Formats.MMddHHmmssfff));
testCase.Add(Tuple.Create("11/16 12:34:56.78", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11/16 12:34:56.7", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11/16 12:34:56.", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11/16 12:34:56", DateTimeChecker.Formats.MMddHHmmss));
testCase.Add(Tuple.Create("11/16 12:34:5", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11/16 12:34:", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11/16 12:34", DateTimeChecker.Formats.MMddHHmm));
testCase.Add(Tuple.Create("11/16 12:3", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11/16 12:", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11/16 12", DateTimeChecker.Formats.MMddHH));
testCase.Add(Tuple.Create("11/16 1", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11/16 ", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11/16", DateTimeChecker.Formats.MMdd));
testCase.Add(Tuple.Create("11/1", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11/", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("11", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("1", DateTimeChecker.Formats.None));
TestDateTime(checker, testCase);
checker.Reset();
testCase.Clear();
testCase.Add(Tuple.Create("12:34:56.789", DateTimeChecker.Formats.HHmmssfff));
testCase.Add(Tuple.Create("12:34:56.78", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("12:34:56.7", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("12:34:56.", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("12:34:56", DateTimeChecker.Formats.HHmmss));
testCase.Add(Tuple.Create("12:34:5", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("12:34:", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("12:34", DateTimeChecker.Formats.HHmm));
testCase.Add(Tuple.Create("12:3", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("12:", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("12", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("1", DateTimeChecker.Formats.None));
TestDateTime(checker, testCase);
checker.Reset();
testCase.Clear();
testCase.Add(Tuple.Create("34:56.789", DateTimeChecker.Formats.mmssfff));
testCase.Add(Tuple.Create("34:56.78", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("34:56.7", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("34:56.", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("34:56", DateTimeChecker.Formats.HHmm));
testCase.Add(Tuple.Create("34:5", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("34:", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("34", DateTimeChecker.Formats.None));
testCase.Add(Tuple.Create("3", DateTimeChecker.Formats.None));
TestDateTime(checker, testCase);
checker.Reset();
testCase.Clear();
}
static void TestDateTime(DateTimeChecker checker, IList<Tuple<string, DateTimeChecker.Formats>> testCase)
{
foreach (Tuple<string, DateTimeChecker.Formats> t in testCase)
{
Console.Write("[" + t.Item1 + "] ");
checker.Reset();
foreach (char ch in t.Item1)
{
checker.MoveNext(ch);
if (checker.IsError())
{
Console.Write(INDENT);
Console.WriteLine(":ERROR");
Debug.Assert(checker.Format == t.Item2, "asersion failed!!");
break;
}
}
if (!checker.IsError())
{
if (checker.IsAcceptable())
{
Console.Write(INDENT);
Console.Write(":OK");
Console.Write(INDENT);
Console.WriteLine(checker.Format);
Debug.Assert(checker.Format == t.Item2, t.Item1 + " asersion failed!!");
}
else
{
Console.Write(INDENT);
Console.WriteLine(":NG");
Debug.Assert(checker.Format == t.Item2, "asersion failed!!");
}
}
}
}
}
interface Checker
{
void Reset();
void MoveNext(char ch);
bool IsAcceptable();
bool IsError();
bool IsNextError(char ch);
string Current();
}
class DateTimeChecker : Checker
{
/// <summary>formats for date or time</summary>
public enum Formats
{
/// <summary>nether date nor time</summary>
None,
/// <summary>yyyy/MM/dd HH:mm:ss.fff</summary>
yyyyMMddHHmmssfff,
/// <summary>yyyy/MM/dd HH:mm:ss</summary>
yyyyMMddHHmmss,
/// <summary>yyyy/MM/dd HH:mm</summary>
yyyyMMddHHmm,
/// <summary>yyyy/MM/dd HH</summary>
yyyyMMddHH,
/// <summary>yyyy/MM/dd</summary>
yyyyMMdd,
/// <summary>yyyy/MM</summary>
yyyyMM,
/// <summary>yy/MM/dd HH:mm:ss.fff</summary>
yyMMddHHmmssfff,
/// <summary>yy/MM/dd HH:mm:ss</summary>
yyMMddHHmmss,
/// <summary>yy/MM/dd HH:mm</summary>
yyMMddHHmm,
/// <summary>yy/MM/dd HH</summary>
yyMMddHH,
/// <summary>yy/MM/dd</summary>
yyMMdd,
/// <summary>MM/dd HH:mm:ss.fff</summary>
MMddHHmmssfff,
/// <summary>MM/dd HH:mm:ss</summary>
MMddHHmmss,
/// <summary>MM/dd HH:mm</summary>
MMddHHmm,
/// <summary>MM/dd HH</summary>
MMddHH,
/// <summary>MM/dd</summary>
MMdd,
/// <summary>HH:mm:ss.fff</summary>
HHmmssfff,
/// <summary>HH:mm:ss</summary>
HHmmss,
/// <summary>HH:mm</summary>
HHmm,
/// <summary>mm:ss.fff</summary>
mmssfff,
}
enum States
{
Error,
State00,
State01,
State02,
State03,
State04,
State05,
State06,
State07,
State08,
State09,
State10,
State11,
State12,
State13,
State14,
State15,
State16,
State17,
State18,
State19,
State20,
State21,
State22,
State23,
State24,
State25,
State26,
State27,
State28,
State29,
}
StringBuilder _sb;
States _state;
List<States> _breadcrumb;
Formats _format;
public Formats Format
{
get { return _format; }
}
public DateTimeChecker()
{
_sb = new StringBuilder();
_breadcrumb = new List<States>();
Reset();
}
public void Reset()
{
_state = States.State00;
_sb.Clear();
_breadcrumb.Clear();
_format = Formats.None;
}
public void MoveNext(char ch)
{
_sb.Append(ch);
States oldState = _state;
_state = GetNext(ch);
JudgeFormat();
}
void JudgeFormat()
{
if (_state == States.State17)
{
_format = Formats.yyyyMM;
_breadcrumb.Add(_state);
}
else if (_state == States.State10)
{
_format = Formats.MMdd;
_breadcrumb.Add(_state);
}
else if (_state == States.State11)
{
_format = Formats.HHmm;
_breadcrumb.Add(_state);
}
else if (_state == States.State22)
{
// there are two ways to come here.
if (_breadcrumb[_breadcrumb.Count - 1] == States.State17)
{
_format = Formats.yyyyMMdd;
}
else
{
_format = Formats.yyMMdd;
}
_breadcrumb.Add(_state);
}
else if (_state == States.State23)
{
// there are three ways to come here.
if (_breadcrumb[_breadcrumb.Count - 1] == States.State10)
{
_format = Formats.MMddHH;
}
else if (_breadcrumb[_breadcrumb.Count - 2] == States.State10)
{
_format = Formats.yyMMddHH;
}
else
{
_format = Formats.yyyyMMddHH;
}
_breadcrumb.Add(_state);
}
else if (_state == States.State29)
{
// there are three ways to come here.
if (_breadcrumb[_breadcrumb.Count - 2] == States.State10)
{
_format = Formats.MMddHHmm;
}
else if (_breadcrumb[_breadcrumb.Count - 3] == States.State10)
{
_format = Formats.yyMMddHHmm;
}
else
{
_format = Formats.yyyyMMddHHmm;
}
_breadcrumb.Add(_state);
}
else if (_state == States.State24)
{
// there are four ways to come here.
if (_breadcrumb[_breadcrumb.Count - 1] == States.State11)
{
_format = Formats.HHmmss;
}
else if (_breadcrumb[_breadcrumb.Count - 3] == States.State10)
{
_format = Formats.MMddHHmmss;
}
else if (_breadcrumb[_breadcrumb.Count - 4] == States.State10)
{
_format = Formats.yyMMddHHmmss;
}
else
{
_format = Formats.yyyyMMddHHmmss;
}
_breadcrumb.Add(_state);
}
else if (_state == States.State27)
{
// there are five ways to come here.
if (_breadcrumb[_breadcrumb.Count - 1] == States.State11)
{
_format = Formats.mmssfff;
}
else if (_breadcrumb[_breadcrumb.Count - 2] == States.State11)
{
_format = Formats.HHmmssfff;
}
else if (_breadcrumb[_breadcrumb.Count - 4] == States.State10)
{
_format = Formats.MMddHHmmssfff;
}
else if (_breadcrumb[_breadcrumb.Count - 5] == States.State10)
{
_format = Formats.yyMMddHHmmssfff;
}
else
{
_format = Formats.yyyyMMddHHmmssfff;
}
_breadcrumb.Add(_state);
}
else
{
_format = Formats.None;
}
}
public bool IsAcceptable()
{
return
_state == States.State10
|| _state == States.State11
|| _state == States.State17
|| _state == States.State22
|| _state == States.State23
|| _state == States.State24
|| _state == States.State27
|| _state == States.State29;
}
public bool IsError()
{
return _state == States.Error;
}
public bool IsNextError(char ch)
{
States next = GetNext(ch);
return IsError(next);
}
public string Current()
{
return _sb.ToString();
}
States GetNext(char ch)
{
States next = States.Error;
switch (_state)
{
case States.State00:
next = Transition(ch, States.State01, States.Error, States.Error, States.Error, States.Error);
break;
case States.State01:
next = Transition(ch, States.State02, States.Error, States.Error, States.Error, States.Error);
break;
case States.State02:
next = Transition(ch, States.State03, States.State04, States.Error, States.State05, States.Error);
break;
case States.State03:
next = Transition(ch, States.State06, States.Error, States.Error, States.Error, States.Error);
break;
case States.State04:
next = Transition(ch, States.State07, States.Error, States.Error, States.Error, States.Error);
break;
case States.State05:
next = Transition(ch, States.State08, States.Error, States.Error, States.Error, States.Error);
break;
case States.State06:
next = Transition(ch, States.Error, States.State09, States.Error, States.Error, States.Error);
break;
case States.State07:
next = Transition(ch, States.State10, States.Error, States.Error, States.Error, States.Error);
break;
case States.State08:
next = Transition(ch, States.State11, States.Error, States.Error, States.Error, States.Error);
break;
case States.State09:
next = Transition(ch, States.State12, States.Error, States.Error, States.Error, States.Error);
break;
case States.State10:
next = Transition(ch, States.Error, States.State13, States.State14, States.Error, States.Error);
break;
case States.State11:
next = Transition(ch, States.Error, States.Error, States.Error, States.State15, States.State16);
break;
case States.State12:
next = Transition(ch, States.State17, States.Error, States.Error, States.Error, States.Error);
break;
case States.State13:
next = Transition(ch, States.State18, States.Error, States.Error, States.Error, States.Error);
break;
case States.State14:
next = Transition(ch, States.State19, States.Error, States.Error, States.Error, States.Error);
break;
case States.State15:
next = Transition(ch, States.State20, States.Error, States.Error, States.Error, States.Error);
break;
case States.State16:
next = Transition(ch, States.State21, States.Error, States.Error, States.Error, States.Error);
break;
case States.State17:
next = Transition(ch, States.Error, States.State13, States.Error, States.Error, States.Error);
break;
case States.State18:
next = Transition(ch, States.State22, States.Error, States.Error, States.Error, States.Error);
break;
case States.State19:
next = Transition(ch, States.State23, States.Error, States.Error, States.Error, States.Error);
break;
case States.State20:
next = Transition(ch, States.State24, States.Error, States.Error, States.Error, States.Error);
break;
case States.State21:
next = Transition(ch, States.State25, States.Error, States.Error, States.Error, States.Error);
break;
case States.State22:
next = Transition(ch, States.Error, States.Error, States.State14, States.Error, States.Error);
break;
case States.State23:
next = Transition(ch, States.Error, States.Error, States.Error, States.State26, States.Error);
break;
case States.State24:
next = Transition(ch, States.Error, States.Error, States.Error, States.Error, States.State16);
break;
case States.State25:
next = Transition(ch, States.State27, States.Error, States.Error, States.Error, States.Error);
break;
case States.State26:
next = Transition(ch, States.State28, States.Error, States.Error, States.Error, States.Error);
break;
case States.State27:
next = Transition(ch, States.Error, States.Error, States.Error, States.Error, States.Error);
break;
case States.State28:
next = Transition(ch, States.State29, States.Error, States.Error, States.Error, States.Error);
break;
case States.State29:
next = Transition(ch, States.Error, States.Error, States.Error, States.State15, States.Error);
break;
default:
next = States.Error;
break;
}
return next;
}
static States Transition(char ch, States whenDigit, States whenSlash, States whenSpace, States whenColon, States whenDot)
{
States next = States.Error;
if (char.IsDigit(ch))
{
next = whenDigit;
}
else if (ch == '/')
{
next = whenSlash;
}
else if (ch == ' ')
{
next = whenSpace;
}
else if (ch == ':')
{
next = whenColon;
}
else if (ch == '.')
{
next = whenDot;
}
else
{
next = States.Error;
}
return next;
}
static bool IsError(States state)
{
return state == States.Error;
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYzsKdXNpbmcgU3lzdGVtLkRpYWdub3N0aWNzOwp1c2luZyBTeXN0ZW0uVGV4dDsKCm5hbWVzcGFjZSBBdXRvbWF0b24KewogIGNsYXNzIFByb2dyYW0KICB7CiAgICBjb25zdCBzdHJpbmcgSU5ERU5UID0gIlx0IjsKCiAgICBzdGF0aWMgdm9pZCBNYWluKHN0cmluZ1tdIGFyZ3MpCiAgICB7CiAgICAgIERhdGVUaW1lQ2hlY2tlciBjaGVja2VyID0gbmV3IERhdGVUaW1lQ2hlY2tlcigpOwoKICAgICAgTGlzdDxUdXBsZTxzdHJpbmcsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzPj4gdGVzdENhc2UgPSBuZXcgTGlzdDxUdXBsZTxzdHJpbmcsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzPj4oKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8xNiAxMjozNDo1Ni43ODkiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy55eXl5TU1kZEhIbW1zc2ZmZikpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEyOjM0OjU2Ljc4IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEyOjM0OjU2LjciLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwMTgvMTEvMTYgMTI6MzQ6NTYuIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEyOjM0OjU2IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMueXl5eU1NZGRISG1tc3MpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8xNiAxMjozNDo1IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEyOjM0OiIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8xNiAxMjozNCIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLnl5eXlNTWRkSEhtbSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEyOjMiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwMTgvMTEvMTYgMTI6IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEyIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMueXl5eU1NZGRISCkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwMTgvMTEvMTYgIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMueXl5eU1NZGQpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8xIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLyIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMSIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLnl5eXlNTSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzEiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwMTgvIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDEiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIFRlc3REYXRlVGltZShjaGVja2VyLCB0ZXN0Q2FzZSk7CiAgICAgIGNoZWNrZXIuUmVzZXQoKTsKICAgICAgdGVzdENhc2UuQ2xlYXIoKTsKCiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzExLzE2IDEyOjM0OjU2Ljc4OSIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLnl5TU1kZEhIbW1zc2ZmZikpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiAxMjozNDo1Ni43OCIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTgvMTEvMTYgMTI6MzQ6NTYuNyIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTgvMTEvMTYgMTI6MzQ6NTYuIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiAxMjozNDo1NiIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLnl5TU1kZEhIbW1zcykpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiAxMjozNDo1IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiAxMjozNDoiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzExLzE2IDEyOjM0IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMueXlNTWRkSEhtbSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiAxMjozIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiAxMjoiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzExLzE2IDEyIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMueXlNTWRkSEgpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTgvMTEvMTYgMSIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTgvMTEvMTYgIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLnl5TU1kZCkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8iLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzExIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTU1kZCkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8iLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICBUZXN0RGF0ZVRpbWUoY2hlY2tlciwgdGVzdENhc2UpOwogICAgICBjaGVja2VyLlJlc2V0KCk7CiAgICAgIHRlc3RDYXNlLkNsZWFyKCk7CgogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxMjozNDo1Ni43ODkiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5NTWRkSEhtbXNzZmZmKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExLzE2IDEyOjM0OjU2Ljc4IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxMjozNDo1Ni43IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxMjozNDo1Ni4iLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExLzE2IDEyOjM0OjU2IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTU1kZEhIbW1zcykpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxMjozNDo1IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxMjozNDoiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExLzE2IDEyOjM0IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTU1kZEhIbW0pKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTEvMTYgMTI6MyIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTEvMTYgMTI6IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxMiIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk1NZGRISCkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExLzE2IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTU1kZCkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8iLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICBUZXN0RGF0ZVRpbWUoY2hlY2tlciwgdGVzdENhc2UpOwogICAgICBjaGVja2VyLlJlc2V0KCk7CiAgICAgIHRlc3RDYXNlLkNsZWFyKCk7CgogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMjozNDo1Ni43ODkiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5ISG1tc3NmZmYpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTI6MzQ6NTYuNzgiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjEyOjM0OjU2LjciLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5Ob25lKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjEyOjM0OjU2LiIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTI6MzQ6NTYiLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cy5ISG1tc3MpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTI6MzQ6NSIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTI6MzQ6IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMjozNCIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLkhIbW0pKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTI6MyIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTI6IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMiIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMSIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgVGVzdERhdGVUaW1lKGNoZWNrZXIsIHRlc3RDYXNlKTsKICAgICAgY2hlY2tlci5SZXNldCgpOwogICAgICB0ZXN0Q2FzZS5DbGVhcigpOwoKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMzQ6NTYuNzg5IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMubW1zc2ZmZikpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIzNDo1Ni43OCIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMzQ6NTYuNyIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMzQ6NTYuIiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIzNDo1NiIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLkhIbW0pKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMzQ6NSIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMzQ6IiwgRGF0ZVRpbWVDaGVja2VyLkZvcm1hdHMuTm9uZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIzNCIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMyIsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzLk5vbmUpKTsKICAgICAgVGVzdERhdGVUaW1lKGNoZWNrZXIsIHRlc3RDYXNlKTsKICAgICAgY2hlY2tlci5SZXNldCgpOwogICAgICB0ZXN0Q2FzZS5DbGVhcigpOwogICAgfQoKICAgIHN0YXRpYyB2b2lkIFRlc3REYXRlVGltZShEYXRlVGltZUNoZWNrZXIgY2hlY2tlciwgSUxpc3Q8VHVwbGU8c3RyaW5nLCBEYXRlVGltZUNoZWNrZXIuRm9ybWF0cz4+IHRlc3RDYXNlKQogICAgewogICAgICBmb3JlYWNoIChUdXBsZTxzdHJpbmcsIERhdGVUaW1lQ2hlY2tlci5Gb3JtYXRzPiB0IGluIHRlc3RDYXNlKQogICAgICB7CiAgICAgICAgQ29uc29sZS5Xcml0ZSgiWyIgKyB0Lkl0ZW0xICsgIl0gIik7CiAgICAgICAgY2hlY2tlci5SZXNldCgpOwogICAgICAgIGZvcmVhY2ggKGNoYXIgY2ggaW4gdC5JdGVtMSkKICAgICAgICB7CiAgICAgICAgICBjaGVja2VyLk1vdmVOZXh0KGNoKTsKICAgICAgICAgIGlmIChjaGVja2VyLklzRXJyb3IoKSkKICAgICAgICAgIHsKICAgICAgICAgICAgQ29uc29sZS5Xcml0ZShJTkRFTlQpOwogICAgICAgICAgICBDb25zb2xlLldyaXRlTGluZSgiOkVSUk9SIik7CiAgICAgICAgICAgIERlYnVnLkFzc2VydChjaGVja2VyLkZvcm1hdCA9PSB0Lkl0ZW0yLCAiYXNlcnNpb24gZmFpbGVkISEiKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBpZiAoIWNoZWNrZXIuSXNFcnJvcigpKQogICAgICAgIHsKICAgICAgICAgIGlmIChjaGVja2VyLklzQWNjZXB0YWJsZSgpKQogICAgICAgICAgewogICAgICAgICAgICBDb25zb2xlLldyaXRlKElOREVOVCk7CiAgICAgICAgICAgIENvbnNvbGUuV3JpdGUoIjpPSyIpOwogICAgICAgICAgICBDb25zb2xlLldyaXRlKElOREVOVCk7CiAgICAgICAgICAgIENvbnNvbGUuV3JpdGVMaW5lKGNoZWNrZXIuRm9ybWF0KTsKICAgICAgICAgICAgRGVidWcuQXNzZXJ0KGNoZWNrZXIuRm9ybWF0ID09IHQuSXRlbTIsIHQuSXRlbTEgKyAiIGFzZXJzaW9uIGZhaWxlZCEhIik7CiAgICAgICAgICB9CiAgICAgICAgICBlbHNlCiAgICAgICAgICB7CiAgICAgICAgICAgIENvbnNvbGUuV3JpdGUoSU5ERU5UKTsKICAgICAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoIjpORyIpOwogICAgICAgICAgICBEZWJ1Zy5Bc3NlcnQoY2hlY2tlci5Gb3JtYXQgPT0gdC5JdGVtMiwgImFzZXJzaW9uIGZhaWxlZCEhIik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQoKICBpbnRlcmZhY2UgQ2hlY2tlcgogIHsKICAgIHZvaWQgUmVzZXQoKTsKICAgIHZvaWQgTW92ZU5leHQoY2hhciBjaCk7CiAgICBib29sIElzQWNjZXB0YWJsZSgpOwogICAgYm9vbCBJc0Vycm9yKCk7CiAgICBib29sIElzTmV4dEVycm9yKGNoYXIgY2gpOwogICAgc3RyaW5nIEN1cnJlbnQoKTsKICB9CgogIGNsYXNzIERhdGVUaW1lQ2hlY2tlciA6IENoZWNrZXIKICB7CiAgICAvLy8gPHN1bW1hcnk+Zm9ybWF0cyBmb3IgZGF0ZSBvciB0aW1lPC9zdW1tYXJ5PgogICAgcHVibGljIGVudW0gRm9ybWF0cwogICAgewogICAgICAvLy8gPHN1bW1hcnk+bmV0aGVyIGRhdGUgbm9yIHRpbWU8L3N1bW1hcnk+CiAgICAgIE5vbmUsCiAgICAgIC8vLyA8c3VtbWFyeT55eXl5L01NL2RkIEhIOm1tOnNzLmZmZjwvc3VtbWFyeT4KICAgICAgeXl5eU1NZGRISG1tc3NmZmYsCiAgICAgIC8vLyA8c3VtbWFyeT55eXl5L01NL2RkIEhIOm1tOnNzPC9zdW1tYXJ5PgogICAgICB5eXl5TU1kZEhIbW1zcywKICAgICAgLy8vIDxzdW1tYXJ5Pnl5eXkvTU0vZGQgSEg6bW08L3N1bW1hcnk+CiAgICAgIHl5eXlNTWRkSEhtbSwKICAgICAgLy8vIDxzdW1tYXJ5Pnl5eXkvTU0vZGQgSEg8L3N1bW1hcnk+CiAgICAgIHl5eXlNTWRkSEgsCiAgICAgIC8vLyA8c3VtbWFyeT55eXl5L01NL2RkPC9zdW1tYXJ5PgogICAgICB5eXl5TU1kZCwKICAgICAgLy8vIDxzdW1tYXJ5Pnl5eXkvTU08L3N1bW1hcnk+CiAgICAgIHl5eXlNTSwKICAgICAgLy8vIDxzdW1tYXJ5Pnl5L01NL2RkIEhIOm1tOnNzLmZmZjwvc3VtbWFyeT4KICAgICAgeXlNTWRkSEhtbXNzZmZmLAogICAgICAvLy8gPHN1bW1hcnk+eXkvTU0vZGQgSEg6bW06c3M8L3N1bW1hcnk+CiAgICAgIHl5TU1kZEhIbW1zcywKICAgICAgLy8vIDxzdW1tYXJ5Pnl5L01NL2RkIEhIOm1tPC9zdW1tYXJ5PgogICAgICB5eU1NZGRISG1tLAogICAgICAvLy8gPHN1bW1hcnk+eXkvTU0vZGQgSEg8L3N1bW1hcnk+CiAgICAgIHl5TU1kZEhILAogICAgICAvLy8gPHN1bW1hcnk+eXkvTU0vZGQ8L3N1bW1hcnk+CiAgICAgIHl5TU1kZCwKICAgICAgLy8vIDxzdW1tYXJ5Pk1NL2RkIEhIOm1tOnNzLmZmZjwvc3VtbWFyeT4KICAgICAgTU1kZEhIbW1zc2ZmZiwKICAgICAgLy8vIDxzdW1tYXJ5Pk1NL2RkIEhIOm1tOnNzPC9zdW1tYXJ5PgogICAgICBNTWRkSEhtbXNzLAogICAgICAvLy8gPHN1bW1hcnk+TU0vZGQgSEg6bW08L3N1bW1hcnk+CiAgICAgIE1NZGRISG1tLAogICAgICAvLy8gPHN1bW1hcnk+TU0vZGQgSEg8L3N1bW1hcnk+CiAgICAgIE1NZGRISCwKICAgICAgLy8vIDxzdW1tYXJ5Pk1NL2RkPC9zdW1tYXJ5PgogICAgICBNTWRkLAogICAgICAvLy8gPHN1bW1hcnk+SEg6bW06c3MuZmZmPC9zdW1tYXJ5PgogICAgICBISG1tc3NmZmYsCiAgICAgIC8vLyA8c3VtbWFyeT5ISDptbTpzczwvc3VtbWFyeT4KICAgICAgSEhtbXNzLAogICAgICAvLy8gPHN1bW1hcnk+SEg6bW08L3N1bW1hcnk+CiAgICAgIEhIbW0sCiAgICAgIC8vLyA8c3VtbWFyeT5tbTpzcy5mZmY8L3N1bW1hcnk+CiAgICAgIG1tc3NmZmYsCiAgICB9CgogICAgZW51bSBTdGF0ZXMKICAgIHsKICAgICAgRXJyb3IsCiAgICAgIFN0YXRlMDAsCiAgICAgIFN0YXRlMDEsCiAgICAgIFN0YXRlMDIsCiAgICAgIFN0YXRlMDMsCiAgICAgIFN0YXRlMDQsCiAgICAgIFN0YXRlMDUsCiAgICAgIFN0YXRlMDYsCiAgICAgIFN0YXRlMDcsCiAgICAgIFN0YXRlMDgsCiAgICAgIFN0YXRlMDksCiAgICAgIFN0YXRlMTAsCiAgICAgIFN0YXRlMTEsCiAgICAgIFN0YXRlMTIsCiAgICAgIFN0YXRlMTMsCiAgICAgIFN0YXRlMTQsCiAgICAgIFN0YXRlMTUsCiAgICAgIFN0YXRlMTYsCiAgICAgIFN0YXRlMTcsCiAgICAgIFN0YXRlMTgsCiAgICAgIFN0YXRlMTksCiAgICAgIFN0YXRlMjAsCiAgICAgIFN0YXRlMjEsCiAgICAgIFN0YXRlMjIsCiAgICAgIFN0YXRlMjMsCiAgICAgIFN0YXRlMjQsCiAgICAgIFN0YXRlMjUsCiAgICAgIFN0YXRlMjYsCiAgICAgIFN0YXRlMjcsCiAgICAgIFN0YXRlMjgsCiAgICAgIFN0YXRlMjksCiAgICB9CgogICAgU3RyaW5nQnVpbGRlciBfc2I7CiAgICBTdGF0ZXMgX3N0YXRlOwogICAgTGlzdDxTdGF0ZXM+IF9icmVhZGNydW1iOwogICAgRm9ybWF0cyBfZm9ybWF0OwoKICAgIHB1YmxpYyBGb3JtYXRzIEZvcm1hdAogICAgewogICAgICBnZXQgeyByZXR1cm4gX2Zvcm1hdDsgfQogICAgfQoKICAgIHB1YmxpYyBEYXRlVGltZUNoZWNrZXIoKQogICAgewogICAgICBfc2IgPSBuZXcgU3RyaW5nQnVpbGRlcigpOwogICAgICBfYnJlYWRjcnVtYiA9IG5ldyBMaXN0PFN0YXRlcz4oKTsKICAgICAgUmVzZXQoKTsKICAgIH0KCiAgICBwdWJsaWMgdm9pZCBSZXNldCgpCiAgICB7CiAgICAgIF9zdGF0ZSA9IFN0YXRlcy5TdGF0ZTAwOwogICAgICBfc2IuQ2xlYXIoKTsKICAgICAgX2JyZWFkY3J1bWIuQ2xlYXIoKTsKICAgICAgX2Zvcm1hdCA9IEZvcm1hdHMuTm9uZTsKICAgIH0KCiAgICBwdWJsaWMgdm9pZCBNb3ZlTmV4dChjaGFyIGNoKQogICAgewogICAgICBfc2IuQXBwZW5kKGNoKTsKICAgICAgU3RhdGVzIG9sZFN0YXRlID0gX3N0YXRlOwogICAgICBfc3RhdGUgPSBHZXROZXh0KGNoKTsKICAgICAgSnVkZ2VGb3JtYXQoKTsKICAgIH0KCiAgICB2b2lkIEp1ZGdlRm9ybWF0KCkKICAgIHsKICAgICAgaWYgKF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUxNykKICAgICAgewogICAgICAgIF9mb3JtYXQgPSBGb3JtYXRzLnl5eXlNTTsKICAgICAgICBfYnJlYWRjcnVtYi5BZGQoX3N0YXRlKTsKICAgICAgfQogICAgICBlbHNlIGlmIChfc3RhdGUgPT0gU3RhdGVzLlN0YXRlMTApCiAgICAgIHsKICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy5NTWRkOwogICAgICAgIF9icmVhZGNydW1iLkFkZChfc3RhdGUpOwogICAgICB9CiAgICAgIGVsc2UgaWYgKF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUxMSkKICAgICAgewogICAgICAgIF9mb3JtYXQgPSBGb3JtYXRzLkhIbW07CiAgICAgICAgX2JyZWFkY3J1bWIuQWRkKF9zdGF0ZSk7CiAgICAgIH0KICAgICAgZWxzZSBpZiAoX3N0YXRlID09IFN0YXRlcy5TdGF0ZTIyKQogICAgICB7CiAgICAgICAgLy8gdGhlcmUgYXJlIHR3byB3YXlzIHRvIGNvbWUgaGVyZS4KICAgICAgICBpZiAoX2JyZWFkY3J1bWJbX2JyZWFkY3J1bWIuQ291bnQgLSAxXSA9PSBTdGF0ZXMuU3RhdGUxNykKICAgICAgICB7CiAgICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy55eXl5TU1kZDsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgIF9mb3JtYXQgPSBGb3JtYXRzLnl5TU1kZDsKICAgICAgICB9CiAgICAgICAgX2JyZWFkY3J1bWIuQWRkKF9zdGF0ZSk7CiAgICAgIH0KICAgICAgZWxzZSBpZiAoX3N0YXRlID09IFN0YXRlcy5TdGF0ZTIzKQogICAgICB7CiAgICAgICAgLy8gdGhlcmUgYXJlIHRocmVlIHdheXMgdG8gY29tZSBoZXJlLgogICAgICAgIGlmIChfYnJlYWRjcnVtYltfYnJlYWRjcnVtYi5Db3VudCAtIDFdID09IFN0YXRlcy5TdGF0ZTEwKQogICAgICAgIHsKICAgICAgICAgIF9mb3JtYXQgPSBGb3JtYXRzLk1NZGRISDsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoX2JyZWFkY3J1bWJbX2JyZWFkY3J1bWIuQ291bnQgLSAyXSA9PSBTdGF0ZXMuU3RhdGUxMCkKICAgICAgICB7CiAgICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy55eU1NZGRISDsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgIHsKICAgICAgICAgIF9mb3JtYXQgPSBGb3JtYXRzLnl5eXlNTWRkSEg7CiAgICAgICAgfQogICAgICAgIF9icmVhZGNydW1iLkFkZChfc3RhdGUpOwogICAgICB9CiAgICAgIGVsc2UgaWYgKF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyOSkKICAgICAgewogICAgICAgIC8vIHRoZXJlIGFyZSB0aHJlZSB3YXlzIHRvIGNvbWUgaGVyZS4KICAgICAgICBpZiAoX2JyZWFkY3J1bWJbX2JyZWFkY3J1bWIuQ291bnQgLSAyXSA9PSBTdGF0ZXMuU3RhdGUxMCkKICAgICAgICB7CiAgICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy5NTWRkSEhtbTsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoX2JyZWFkY3J1bWJbX2JyZWFkY3J1bWIuQ291bnQgLSAzXSA9PSBTdGF0ZXMuU3RhdGUxMCkKICAgICAgICB7CiAgICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy55eU1NZGRISG1tOwogICAgICAgIH0KICAgICAgICBlbHNlCiAgICAgICAgewogICAgICAgICAgX2Zvcm1hdCA9IEZvcm1hdHMueXl5eU1NZGRISG1tOwogICAgICAgIH0KICAgICAgICBfYnJlYWRjcnVtYi5BZGQoX3N0YXRlKTsKICAgICAgfQogICAgICBlbHNlIGlmIChfc3RhdGUgPT0gU3RhdGVzLlN0YXRlMjQpCiAgICAgIHsKICAgICAgICAvLyB0aGVyZSBhcmUgZm91ciB3YXlzIHRvIGNvbWUgaGVyZS4KICAgICAgICBpZiAoX2JyZWFkY3J1bWJbX2JyZWFkY3J1bWIuQ291bnQgLSAxXSA9PSBTdGF0ZXMuU3RhdGUxMSkKICAgICAgICB7CiAgICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy5ISG1tc3M7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKF9icmVhZGNydW1iW19icmVhZGNydW1iLkNvdW50IC0gM10gPT0gU3RhdGVzLlN0YXRlMTApCiAgICAgICAgewogICAgICAgICAgX2Zvcm1hdCA9IEZvcm1hdHMuTU1kZEhIbW1zczsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoX2JyZWFkY3J1bWJbX2JyZWFkY3J1bWIuQ291bnQgLSA0XSA9PSBTdGF0ZXMuU3RhdGUxMCkKICAgICAgICB7CiAgICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy55eU1NZGRISG1tc3M7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy55eXl5TU1kZEhIbW1zczsKICAgICAgICB9CiAgICAgICAgX2JyZWFkY3J1bWIuQWRkKF9zdGF0ZSk7CiAgICAgIH0KICAgICAgZWxzZSBpZiAoX3N0YXRlID09IFN0YXRlcy5TdGF0ZTI3KQogICAgICB7CiAgICAgICAgLy8gdGhlcmUgYXJlIGZpdmUgd2F5cyB0byBjb21lIGhlcmUuCiAgICAgICAgaWYgKF9icmVhZGNydW1iW19icmVhZGNydW1iLkNvdW50IC0gMV0gPT0gU3RhdGVzLlN0YXRlMTEpCiAgICAgICAgewogICAgICAgICAgX2Zvcm1hdCA9IEZvcm1hdHMubW1zc2ZmZjsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoX2JyZWFkY3J1bWJbX2JyZWFkY3J1bWIuQ291bnQgLSAyXSA9PSBTdGF0ZXMuU3RhdGUxMSkKICAgICAgICB7CiAgICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy5ISG1tc3NmZmY7CiAgICAgICAgfQogICAgICAgIGVsc2UgaWYgKF9icmVhZGNydW1iW19icmVhZGNydW1iLkNvdW50IC0gNF0gPT0gU3RhdGVzLlN0YXRlMTApCiAgICAgICAgewogICAgICAgICAgX2Zvcm1hdCA9IEZvcm1hdHMuTU1kZEhIbW1zc2ZmZjsKICAgICAgICB9CiAgICAgICAgZWxzZSBpZiAoX2JyZWFkY3J1bWJbX2JyZWFkY3J1bWIuQ291bnQgLSA1XSA9PSBTdGF0ZXMuU3RhdGUxMCkKICAgICAgICB7CiAgICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy55eU1NZGRISG1tc3NmZmY7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICBfZm9ybWF0ID0gRm9ybWF0cy55eXl5TU1kZEhIbW1zc2ZmZjsKICAgICAgICB9CiAgICAgICAgX2JyZWFkY3J1bWIuQWRkKF9zdGF0ZSk7CiAgICAgIH0KICAgICAgZWxzZQogICAgICB7CiAgICAgICAgX2Zvcm1hdCA9IEZvcm1hdHMuTm9uZTsKICAgICAgfQogICAgfQoKICAgIHB1YmxpYyBib29sIElzQWNjZXB0YWJsZSgpCiAgICB7CiAgICAgIHJldHVybgogICAgICAgIF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUxMAogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUxMQogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUxNwogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyMgogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyMwogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyNAogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyNwogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyOTsKICAgIH0KCiAgICBwdWJsaWMgYm9vbCBJc0Vycm9yKCkKICAgIHsKICAgICAgcmV0dXJuIF9zdGF0ZSA9PSBTdGF0ZXMuRXJyb3I7CiAgICB9CgogICAgcHVibGljIGJvb2wgSXNOZXh0RXJyb3IoY2hhciBjaCkKICAgIHsKICAgICAgU3RhdGVzIG5leHQgPSBHZXROZXh0KGNoKTsKICAgICAgcmV0dXJuIElzRXJyb3IobmV4dCk7CiAgICB9CgogICAgcHVibGljIHN0cmluZyBDdXJyZW50KCkKICAgIHsKICAgICAgcmV0dXJuIF9zYi5Ub1N0cmluZygpOwogICAgfQoKCgoKCiAgICBTdGF0ZXMgR2V0TmV4dChjaGFyIGNoKQogICAgewogICAgICBTdGF0ZXMgbmV4dCA9IFN0YXRlcy5FcnJvcjsKICAgICAgc3dpdGNoIChfc3RhdGUpCiAgICAgIHsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTAwOgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTAxLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUwMToKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUwMiwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMDI6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMDMsIFN0YXRlcy5TdGF0ZTA0LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5TdGF0ZTA1LCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUwMzoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUwNiwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMDQ6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMDcsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTA1OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTA4LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUwNjoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5TdGF0ZTA5LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMDc6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMTAsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTA4OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTExLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUwOToKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUxMiwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMTA6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuU3RhdGUxMywgU3RhdGVzLlN0YXRlMTQsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMTE6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLlN0YXRlMTUsIFN0YXRlcy5TdGF0ZTE2KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMTI6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMTcsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTEzOgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTE4LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUxNDoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUxOSwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMTU6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMjAsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTE2OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTIxLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUxNzoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5TdGF0ZTEzLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMTg6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMjIsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTE5OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTIzLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUyMDoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUyNCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMjE6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMjUsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTIyOgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuU3RhdGUxNCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUyMzoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuU3RhdGUyNiwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMjQ6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuU3RhdGUxNik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTI1OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTI3LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUyNjoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUyOCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMjc6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUyODoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUyOSwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMjk6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLlN0YXRlMTUsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBkZWZhdWx0OgogICAgICAgICAgbmV4dCA9IFN0YXRlcy5FcnJvcjsKICAgICAgICAgIGJyZWFrOwogICAgICB9CiAgICAgIHJldHVybiBuZXh0OwogICAgfQoKICAgIHN0YXRpYyBTdGF0ZXMgVHJhbnNpdGlvbihjaGFyIGNoLCBTdGF0ZXMgd2hlbkRpZ2l0LCBTdGF0ZXMgd2hlblNsYXNoLCBTdGF0ZXMgd2hlblNwYWNlLCBTdGF0ZXMgd2hlbkNvbG9uLCBTdGF0ZXMgd2hlbkRvdCkKICAgIHsKICAgICAgU3RhdGVzIG5leHQgPSBTdGF0ZXMuRXJyb3I7CgogICAgICBpZiAoY2hhci5Jc0RpZ2l0KGNoKSkKICAgICAgewogICAgICAgIG5leHQgPSB3aGVuRGlnaXQ7CiAgICAgIH0KICAgICAgZWxzZSBpZiAoY2ggPT0gJy8nKQogICAgICB7CiAgICAgICAgbmV4dCA9IHdoZW5TbGFzaDsKICAgICAgfQogICAgICBlbHNlIGlmIChjaCA9PSAnICcpCiAgICAgIHsKICAgICAgICBuZXh0ID0gd2hlblNwYWNlOwogICAgICB9CiAgICAgIGVsc2UgaWYgKGNoID09ICc6JykKICAgICAgewogICAgICAgIG5leHQgPSB3aGVuQ29sb247CiAgICAgIH0KICAgICAgZWxzZSBpZiAoY2ggPT0gJy4nKQogICAgICB7CiAgICAgICAgbmV4dCA9IHdoZW5Eb3Q7CiAgICAgIH0KICAgICAgZWxzZQogICAgICB7CiAgICAgICAgbmV4dCA9IFN0YXRlcy5FcnJvcjsKICAgICAgfQoKICAgICAgcmV0dXJuIG5leHQ7CiAgICB9CgogICAgc3RhdGljIGJvb2wgSXNFcnJvcihTdGF0ZXMgc3RhdGUpCiAgICB7CiAgICAgIHJldHVybiBzdGF0ZSA9PSBTdGF0ZXMuRXJyb3I7CiAgICB9CiAgfQp9