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)
{
Checker checker = new DateTimeChecker();
List<Tuple<string, bool>> testCase = new List<Tuple<string, bool>>();
testCase.Add(Tuple.Create("2018/11/16 12:34:56.789", true));
testCase.Add(Tuple.Create("2018/11/16 12:34:56.78", false));
testCase.Add(Tuple.Create("2018/11/16 12:34:56.7", false));
testCase.Add(Tuple.Create("2018/11/16 12:34:56.", false));
testCase.Add(Tuple.Create("2018/11/16 12:34:56", true));
testCase.Add(Tuple.Create("2018/11/16 12:34:5", false));
testCase.Add(Tuple.Create("2018/11/16 12:34:", false));
testCase.Add(Tuple.Create("2018/11/16 12:34", true));
testCase.Add(Tuple.Create("2018/11/16 12:3", false));
testCase.Add(Tuple.Create("2018/11/16 12:", false));
testCase.Add(Tuple.Create("2018/11/16 12", true));
testCase.Add(Tuple.Create("2018/11/16 1", false));
testCase.Add(Tuple.Create("2018/11/16 ", false));
testCase.Add(Tuple.Create("2018/11/16", true));
testCase.Add(Tuple.Create("2018/11/1", false));
testCase.Add(Tuple.Create("2018/11/", false));
testCase.Add(Tuple.Create("2018/11", true));
testCase.Add(Tuple.Create("2018/1", false));
testCase.Add(Tuple.Create("2018/", false));
testCase.Add(Tuple.Create("2018", false));
testCase.Add(Tuple.Create("201", false));
testCase.Add(Tuple.Create("20", false));
testCase.Add(Tuple.Create("2", false));
testCase.Add(Tuple.Create("", false));
TestDateTime(checker, testCase);
checker.Reset();
testCase.Clear();
testCase.Add(Tuple.Create("18/11/16 12:34:56.789", true));
testCase.Add(Tuple.Create("18/11/16 12:34:56.78", false));
testCase.Add(Tuple.Create("18/11/16 12:34:56.7", false));
testCase.Add(Tuple.Create("18/11/16 12:34:56.", false));
testCase.Add(Tuple.Create("18/11/16 12:34:56", true));
testCase.Add(Tuple.Create("18/11/16 12:34:5", false));
testCase.Add(Tuple.Create("18/11/16 12:34:", false));
testCase.Add(Tuple.Create("18/11/16 12:34", true));
testCase.Add(Tuple.Create("18/11/16 12:3", false));
testCase.Add(Tuple.Create("18/11/16 12:", false));
testCase.Add(Tuple.Create("18/11/16 12", true));
testCase.Add(Tuple.Create("18/11/16 1", false));
testCase.Add(Tuple.Create("18/11/16 ", false));
testCase.Add(Tuple.Create("18/11/16", true));
testCase.Add(Tuple.Create("18/11/1", false));
testCase.Add(Tuple.Create("18/11/", false));
testCase.Add(Tuple.Create("18/11", true)); // cannot be distinguished from MM/dd
testCase.Add(Tuple.Create("18/1", false));
testCase.Add(Tuple.Create("18/", false));
testCase.Add(Tuple.Create("18", false));
testCase.Add(Tuple.Create("1", false));
TestDateTime(checker, testCase);
checker.Reset();
testCase.Clear();
testCase.Add(Tuple.Create("11/16 12:34:56.789", true));
testCase.Add(Tuple.Create("11/16 12:34:56.78", false));
testCase.Add(Tuple.Create("11/16 12:34:56.7", false));
testCase.Add(Tuple.Create("11/16 12:34:56.", false));
testCase.Add(Tuple.Create("11/16 12:34:56", true));
testCase.Add(Tuple.Create("11/16 12:34:5", false));
testCase.Add(Tuple.Create("11/16 12:34:", false));
testCase.Add(Tuple.Create("11/16 12:34", true));
testCase.Add(Tuple.Create("11/16 12:3", false));
testCase.Add(Tuple.Create("11/16 12:", false));
testCase.Add(Tuple.Create("11/16 12", true));
testCase.Add(Tuple.Create("11/16 1", false));
testCase.Add(Tuple.Create("11/16 ", false));
testCase.Add(Tuple.Create("11/16", true)); // cannot be distinguished from yy/MM
testCase.Add(Tuple.Create("11/1", false));
testCase.Add(Tuple.Create("11/", false));
testCase.Add(Tuple.Create("11", false));
testCase.Add(Tuple.Create("1", false));
TestDateTime(checker, testCase);
checker.Reset();
testCase.Clear();
testCase.Add(Tuple.Create("12:34:56.789", true));
testCase.Add(Tuple.Create("12:34:56.78", false));
testCase.Add(Tuple.Create("12:34:56.7", false));
testCase.Add(Tuple.Create("12:34:56.", false));
testCase.Add(Tuple.Create("12:34:56", true));
testCase.Add(Tuple.Create("12:34:5", false));
testCase.Add(Tuple.Create("12:34:", false));
testCase.Add(Tuple.Create("12:34", true)); // cannot be distinguished from mm:ss
testCase.Add(Tuple.Create("12:3", false));
testCase.Add(Tuple.Create("12:", false));
testCase.Add(Tuple.Create("12", false));
testCase.Add(Tuple.Create("1", false));
TestDateTime(checker, testCase);
checker.Reset();
testCase.Clear();
testCase.Add(Tuple.Create("34:56.789", true));
testCase.Add(Tuple.Create("34:56.78", false));
testCase.Add(Tuple.Create("34:56.7", false));
testCase.Add(Tuple.Create("34:56.", false));
testCase.Add(Tuple.Create("34:56", true)); // cannot be distinguished from HH:mm
testCase.Add(Tuple.Create("34:5", false));
testCase.Add(Tuple.Create("34:", false));
testCase.Add(Tuple.Create("34", false));
testCase.Add(Tuple.Create("3", false));
TestDateTime(checker, testCase);
checker.Reset();
testCase.Clear();
}
static void TestDateTime(Checker checker, IList<Tuple<string, bool>> testCase)
{
foreach (Tuple<string, bool> 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(!t.Item2, "asersion failed!!");
break;
}
}
if (!checker.IsError())
{
if (checker.IsAcceptable())
{
Console.Write(INDENT);
Console.WriteLine(":OK");
Debug.Assert(t.Item2, t.Item1 + " asersion failed!!");
}
else
{
Console.Write(INDENT);
Console.WriteLine(":NG");
Debug.Assert(!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
{
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;
public DateTimeChecker()
{
_sb = new StringBuilder();
Reset();
}
public void Reset()
{
_state = States.State00;
_sb.Clear();
}
public void MoveNext(char ch)
{
_sb.Append(ch);
_state = GetNext(ch);
}
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;
}
}
}
dXNpbmcgU3lzdGVtOwp1c2luZyBTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYzsKdXNpbmcgU3lzdGVtLkRpYWdub3N0aWNzOwp1c2luZyBTeXN0ZW0uVGV4dDsKCm5hbWVzcGFjZSBBdXRvbWF0b24KewogIGNsYXNzIFByb2dyYW0KICB7CiAgICBjb25zdCBzdHJpbmcgSU5ERU5UID0gIlx0IjsKCiAgICBzdGF0aWMgdm9pZCBNYWluKHN0cmluZ1tdIGFyZ3MpCiAgICB7CiAgICAgIENoZWNrZXIgY2hlY2tlciA9IG5ldyBEYXRlVGltZUNoZWNrZXIoKTsKCiAgICAgIExpc3Q8VHVwbGU8c3RyaW5nLCBib29sPj4gdGVzdENhc2UgPSBuZXcgTGlzdDxUdXBsZTxzdHJpbmcsIGJvb2w+PigpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEyOjM0OjU2Ljc4OSIsIHRydWUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8xNiAxMjozNDo1Ni43OCIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwMTgvMTEvMTYgMTI6MzQ6NTYuNyIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwMTgvMTEvMTYgMTI6MzQ6NTYuIiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8xNiAxMjozNDo1NiIsIHRydWUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8xNiAxMjozNDo1IiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8xNiAxMjozNDoiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEyOjM0IiwgdHJ1ZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEyOjMiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExLzE2IDEyOiIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwMTgvMTEvMTYgMTIiLCB0cnVlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwMTgvMTEvMTYgMSIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwMTgvMTEvMTYgIiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8xNiIsIHRydWUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8xIiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMjAxOC8xMS8iLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzExIiwgdHJ1ZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LzEiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDE4LyIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIwMTgiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMDEiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIyMCIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjIiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIiLCBmYWxzZSkpOwogICAgICBUZXN0RGF0ZVRpbWUoY2hlY2tlciwgdGVzdENhc2UpOwogICAgICBjaGVja2VyLlJlc2V0KCk7CiAgICAgIHRlc3RDYXNlLkNsZWFyKCk7CgogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiAxMjozNDo1Ni43ODkiLCB0cnVlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzExLzE2IDEyOjM0OjU2Ljc4IiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTgvMTEvMTYgMTI6MzQ6NTYuNyIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzExLzE2IDEyOjM0OjU2LiIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzExLzE2IDEyOjM0OjU2IiwgdHJ1ZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiAxMjozNDo1IiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTgvMTEvMTYgMTI6MzQ6IiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTgvMTEvMTYgMTI6MzQiLCB0cnVlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzExLzE2IDEyOjMiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiAxMjoiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xNiAxMiIsIHRydWUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTgvMTEvMTYgMSIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzExLzE2ICIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzExLzE2IiwgdHJ1ZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8xMS8xIiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTgvMTEvIiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTgvMTEiLCB0cnVlKSk7ICAvLyBjYW5ub3QgYmUgZGlzdGluZ3Vpc2hlZCBmcm9tIE1NL2RkCiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjE4LzEiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOC8iLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxOCIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjEiLCBmYWxzZSkpOwogICAgICBUZXN0RGF0ZVRpbWUoY2hlY2tlciwgdGVzdENhc2UpOwogICAgICBjaGVja2VyLlJlc2V0KCk7CiAgICAgIHRlc3RDYXNlLkNsZWFyKCk7CgogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxMjozNDo1Ni43ODkiLCB0cnVlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExLzE2IDEyOjM0OjU2Ljc4IiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTEvMTYgMTI6MzQ6NTYuNyIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExLzE2IDEyOjM0OjU2LiIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExLzE2IDEyOjM0OjU2IiwgdHJ1ZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxMjozNDo1IiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTEvMTYgMTI6MzQ6IiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTEvMTYgMTI6MzQiLCB0cnVlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExLzE2IDEyOjMiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxMjoiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xNiAxMiIsIHRydWUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTEvMTYgMSIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExLzE2ICIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjExLzE2IiwgdHJ1ZSkpOyAgLy8gY2Fubm90IGJlIGRpc3Rpbmd1aXNoZWQgZnJvbSB5eS9NTQogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMS8xIiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTEvIiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTEiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxIiwgZmFsc2UpKTsKICAgICAgVGVzdERhdGVUaW1lKGNoZWNrZXIsIHRlc3RDYXNlKTsKICAgICAgY2hlY2tlci5SZXNldCgpOwogICAgICB0ZXN0Q2FzZS5DbGVhcigpOwoKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTI6MzQ6NTYuNzg5IiwgdHJ1ZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMjozNDo1Ni43OCIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjEyOjM0OjU2LjciLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMjozNDo1Ni4iLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMjozNDo1NiIsIHRydWUpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTI6MzQ6NSIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjEyOjM0OiIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjEyOjM0IiwgdHJ1ZSkpOyAgLy8gY2Fubm90IGJlIGRpc3Rpbmd1aXNoZWQgZnJvbSBtbTpzcwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxMjozIiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTI6IiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMTIiLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIxIiwgZmFsc2UpKTsKICAgICAgVGVzdERhdGVUaW1lKGNoZWNrZXIsIHRlc3RDYXNlKTsKICAgICAgY2hlY2tlci5SZXNldCgpOwogICAgICB0ZXN0Q2FzZS5DbGVhcigpOwoKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMzQ6NTYuNzg5IiwgdHJ1ZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIzNDo1Ni43OCIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjM0OjU2LjciLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIzNDo1Ni4iLCBmYWxzZSkpOwogICAgICB0ZXN0Q2FzZS5BZGQoVHVwbGUuQ3JlYXRlKCIzNDo1NiIsIHRydWUpKTsgIC8vIGNhbm5vdCBiZSBkaXN0aW5ndWlzaGVkIGZyb20gSEg6bW0KICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMzQ6NSIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjM0OiIsIGZhbHNlKSk7CiAgICAgIHRlc3RDYXNlLkFkZChUdXBsZS5DcmVhdGUoIjM0IiwgZmFsc2UpKTsKICAgICAgdGVzdENhc2UuQWRkKFR1cGxlLkNyZWF0ZSgiMyIsIGZhbHNlKSk7CiAgICAgIFRlc3REYXRlVGltZShjaGVja2VyLCB0ZXN0Q2FzZSk7CiAgICAgIGNoZWNrZXIuUmVzZXQoKTsKICAgICAgdGVzdENhc2UuQ2xlYXIoKTsKICAgIH0KCiAgICBzdGF0aWMgdm9pZCBUZXN0RGF0ZVRpbWUoQ2hlY2tlciBjaGVja2VyLCBJTGlzdDxUdXBsZTxzdHJpbmcsIGJvb2w+PiB0ZXN0Q2FzZSkKICAgIHsKICAgICAgZm9yZWFjaCAoVHVwbGU8c3RyaW5nLCBib29sPiB0IGluIHRlc3RDYXNlKQogICAgICB7CiAgICAgICAgQ29uc29sZS5Xcml0ZSgiWyIgKyB0Lkl0ZW0xICsgIl0gIik7CiAgICAgICAgY2hlY2tlci5SZXNldCgpOwogICAgICAgIGZvcmVhY2ggKGNoYXIgY2ggaW4gdC5JdGVtMSkKICAgICAgICB7CiAgICAgICAgICBjaGVja2VyLk1vdmVOZXh0KGNoKTsKICAgICAgICAgIGlmIChjaGVja2VyLklzRXJyb3IoKSkKICAgICAgICAgIHsKICAgICAgICAgICAgQ29uc29sZS5Xcml0ZShJTkRFTlQpOwogICAgICAgICAgICBDb25zb2xlLldyaXRlTGluZSgiOkVSUk9SIik7CiAgICAgICAgICAgIERlYnVnLkFzc2VydCghdC5JdGVtMiwgImFzZXJzaW9uIGZhaWxlZCEhIik7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KCgogICAgICAgIGlmICghY2hlY2tlci5Jc0Vycm9yKCkpCiAgICAgICAgewogICAgICAgICAgaWYgKGNoZWNrZXIuSXNBY2NlcHRhYmxlKCkpCiAgICAgICAgICB7CiAgICAgICAgICAgIENvbnNvbGUuV3JpdGUoSU5ERU5UKTsKICAgICAgICAgICAgQ29uc29sZS5Xcml0ZUxpbmUoIjpPSyIpOwogICAgICAgICAgICBEZWJ1Zy5Bc3NlcnQodC5JdGVtMiwgdC5JdGVtMSArICIgYXNlcnNpb24gZmFpbGVkISEiKTsKICAgICAgICAgIH0KICAgICAgICAgIGVsc2UKICAgICAgICAgIHsKICAgICAgICAgICAgQ29uc29sZS5Xcml0ZShJTkRFTlQpOwogICAgICAgICAgICBDb25zb2xlLldyaXRlTGluZSgiOk5HIik7CiAgICAgICAgICAgIERlYnVnLkFzc2VydCghdC5JdGVtMiwgImFzZXJzaW9uIGZhaWxlZCEhIik7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfQoKICBpbnRlcmZhY2UgQ2hlY2tlcgogIHsKICAgIHZvaWQgUmVzZXQoKTsKICAgIHZvaWQgTW92ZU5leHQoY2hhciBjaCk7CiAgICBib29sIElzQWNjZXB0YWJsZSgpOwogICAgYm9vbCBJc0Vycm9yKCk7CiAgICBib29sIElzTmV4dEVycm9yKGNoYXIgY2gpOwogICAgc3RyaW5nIEN1cnJlbnQoKTsKICB9CgogIGNsYXNzIERhdGVUaW1lQ2hlY2tlciA6IENoZWNrZXIKICB7CiAgICBlbnVtIFN0YXRlcwogICAgewogICAgICBFcnJvciwKICAgICAgU3RhdGUwMCwKICAgICAgU3RhdGUwMSwKICAgICAgU3RhdGUwMiwKICAgICAgU3RhdGUwMywKICAgICAgU3RhdGUwNCwKICAgICAgU3RhdGUwNSwKICAgICAgU3RhdGUwNiwKICAgICAgU3RhdGUwNywKICAgICAgU3RhdGUwOCwKICAgICAgU3RhdGUwOSwKICAgICAgU3RhdGUxMCwKICAgICAgU3RhdGUxMSwKICAgICAgU3RhdGUxMiwKICAgICAgU3RhdGUxMywKICAgICAgU3RhdGUxNCwKICAgICAgU3RhdGUxNSwKICAgICAgU3RhdGUxNiwKICAgICAgU3RhdGUxNywKICAgICAgU3RhdGUxOCwKICAgICAgU3RhdGUxOSwKICAgICAgU3RhdGUyMCwKICAgICAgU3RhdGUyMSwKICAgICAgU3RhdGUyMiwKICAgICAgU3RhdGUyMywKICAgICAgU3RhdGUyNCwKICAgICAgU3RhdGUyNSwKICAgICAgU3RhdGUyNiwKICAgICAgU3RhdGUyNywKICAgICAgU3RhdGUyOCwKICAgICAgU3RhdGUyOSwKICAgIH0KCiAgICBTdHJpbmdCdWlsZGVyIF9zYjsKICAgIFN0YXRlcyBfc3RhdGU7CgogICAgcHVibGljIERhdGVUaW1lQ2hlY2tlcigpCiAgICB7CiAgICAgIF9zYiA9IG5ldyBTdHJpbmdCdWlsZGVyKCk7CiAgICAgIFJlc2V0KCk7CiAgICB9CgogICAgcHVibGljIHZvaWQgUmVzZXQoKQogICAgewogICAgICBfc3RhdGUgPSBTdGF0ZXMuU3RhdGUwMDsKICAgICAgX3NiLkNsZWFyKCk7CiAgICB9CgogICAgcHVibGljIHZvaWQgTW92ZU5leHQoY2hhciBjaCkKICAgIHsKICAgICAgX3NiLkFwcGVuZChjaCk7CiAgICAgIF9zdGF0ZSA9IEdldE5leHQoY2gpOwogICAgfQoKICAgIHB1YmxpYyBib29sIElzQWNjZXB0YWJsZSgpCiAgICB7CiAgICAgIHJldHVybgogICAgICAgIF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUxMAogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUxMQogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUxNwogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyMgogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyMwogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyNAogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyNwogICAgICAgIHx8IF9zdGF0ZSA9PSBTdGF0ZXMuU3RhdGUyOTsKICAgIH0KCiAgICBwdWJsaWMgYm9vbCBJc0Vycm9yKCkKICAgIHsKICAgICAgcmV0dXJuIF9zdGF0ZSA9PSBTdGF0ZXMuRXJyb3I7CiAgICB9CgogICAgcHVibGljIGJvb2wgSXNOZXh0RXJyb3IoY2hhciBjaCkKICAgIHsKICAgICAgU3RhdGVzIG5leHQgPSBHZXROZXh0KGNoKTsKICAgICAgcmV0dXJuIElzRXJyb3IobmV4dCk7CiAgICB9CgogICAgcHVibGljIHN0cmluZyBDdXJyZW50KCkKICAgIHsKICAgICAgcmV0dXJuIF9zYi5Ub1N0cmluZygpOwogICAgfQoKICAgIFN0YXRlcyBHZXROZXh0KGNoYXIgY2gpCiAgICB7CiAgICAgIFN0YXRlcyBuZXh0ID0gU3RhdGVzLkVycm9yOwogICAgICBzd2l0Y2ggKF9zdGF0ZSkKICAgICAgewogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMDA6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMDEsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTAxOgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTAyLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUwMjoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUwMywgU3RhdGVzLlN0YXRlMDQsIFN0YXRlcy5FcnJvciwgU3RhdGVzLlN0YXRlMDUsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTAzOgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTA2LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUwNDoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUwNywgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMDU6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMDgsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTA2OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5FcnJvciwgU3RhdGVzLlN0YXRlMDksIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUwNzoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUxMCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMDg6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMTEsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTA5OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTEyLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUxMDoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5TdGF0ZTEzLCBTdGF0ZXMuU3RhdGUxNCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUxMToKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuU3RhdGUxNSwgU3RhdGVzLlN0YXRlMTYpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUxMjoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUxNywgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMTM6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMTgsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTE0OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTE5LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUxNToKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUyMCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMTY6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMjEsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTE3OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5FcnJvciwgU3RhdGVzLlN0YXRlMTMsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUxODoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUyMiwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMTk6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMjMsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTIwOgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTI0LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUyMToKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuU3RhdGUyNSwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMjI6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5TdGF0ZTE0LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTIzOgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5TdGF0ZTI2LCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUyNDoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5TdGF0ZTE2KTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGNhc2UgU3RhdGVzLlN0YXRlMjU6CiAgICAgICAgICBuZXh0ID0gVHJhbnNpdGlvbihjaCwgU3RhdGVzLlN0YXRlMjcsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTI2OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTI4LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUyNzoKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvcik7CiAgICAgICAgICBicmVhazsKICAgICAgICBjYXNlIFN0YXRlcy5TdGF0ZTI4OgogICAgICAgICAgbmV4dCA9IFRyYW5zaXRpb24oY2gsIFN0YXRlcy5TdGF0ZTI5LCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuRXJyb3IpOwogICAgICAgICAgYnJlYWs7CiAgICAgICAgY2FzZSBTdGF0ZXMuU3RhdGUyOToKICAgICAgICAgIG5leHQgPSBUcmFuc2l0aW9uKGNoLCBTdGF0ZXMuRXJyb3IsIFN0YXRlcy5FcnJvciwgU3RhdGVzLkVycm9yLCBTdGF0ZXMuU3RhdGUxNSwgU3RhdGVzLkVycm9yKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIGRlZmF1bHQ6CiAgICAgICAgICBuZXh0ID0gU3RhdGVzLkVycm9yOwogICAgICAgICAgYnJlYWs7CiAgICAgIH0KICAgICAgcmV0dXJuIG5leHQ7CiAgICB9CgogICAgc3RhdGljIFN0YXRlcyBUcmFuc2l0aW9uKGNoYXIgY2gsIFN0YXRlcyB3aGVuRGlnaXQsIFN0YXRlcyB3aGVuU2xhc2gsIFN0YXRlcyB3aGVuU3BhY2UsIFN0YXRlcyB3aGVuQ29sb24sIFN0YXRlcyB3aGVuRG90KQogICAgewogICAgICBTdGF0ZXMgbmV4dCA9IFN0YXRlcy5FcnJvcjsKCiAgICAgIGlmIChjaGFyLklzRGlnaXQoY2gpKQogICAgICB7CiAgICAgICAgbmV4dCA9IHdoZW5EaWdpdDsKICAgICAgfQogICAgICBlbHNlIGlmIChjaCA9PSAnLycpCiAgICAgIHsKICAgICAgICBuZXh0ID0gd2hlblNsYXNoOwogICAgICB9CiAgICAgIGVsc2UgaWYgKGNoID09ICcgJykKICAgICAgewogICAgICAgIG5leHQgPSB3aGVuU3BhY2U7CiAgICAgIH0KICAgICAgZWxzZSBpZiAoY2ggPT0gJzonKQogICAgICB7CiAgICAgICAgbmV4dCA9IHdoZW5Db2xvbjsKICAgICAgfQogICAgICBlbHNlIGlmIChjaCA9PSAnLicpCiAgICAgIHsKICAgICAgICBuZXh0ID0gd2hlbkRvdDsKICAgICAgfQogICAgICBlbHNlCiAgICAgIHsKICAgICAgICBuZXh0ID0gU3RhdGVzLkVycm9yOwogICAgICB9CgogICAgICByZXR1cm4gbmV4dDsKICAgIH0KCiAgICBzdGF0aWMgYm9vbCBJc0Vycm9yKFN0YXRlcyBzdGF0ZSkKICAgIHsKICAgICAgcmV0dXJuIHN0YXRlID09IFN0YXRlcy5FcnJvcjsKICAgIH0KICB9Cn0K