commit a92897404acb137e946c10fee6593c894c4ba711 Author: xl3lackout Date: Fri Feb 25 19:44:26 2022 -0500 Reupload diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..dfe077042 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/04 - Shoplist_Balanced_1.7.4.csv b/04 - Shoplist_Balanced_1.7.4.csv new file mode 100644 index 000000000..23e1b2102 --- /dev/null +++ b/04 - Shoplist_Balanced_1.7.4.csv @@ -0,0 +1,911 @@ +10,6,1,2146,25,1,0,0,1,1,0,1,0,0 +10,6,2,2147,25,1,0,0,1,1,0,1,0,0 +10,6,3,2148,25,1,0,0,1,1,0,1,0,0 +10,6,4,2149,25,1,0,0,1,1,0,1,0,0 +10,6,5,2150,25,1,0,0,1,1,0,1,0,0 +10,6,6,2151,25,1,0,0,1,1,0,1,0,0 +10,6,7,2152,25,1,0,0,1,1,0,1,0,0 +10,6,8,2153,25,1,0,0,1,1,0,1,0,0 +10,6,9,2154,25,1,0,0,1,1,0,1,0,0 +10,6,10,2155,25,1,0,0,1,1,0,1,0,0 +10,6,11,4398,25,1,0,0,1,1,0,1,0,0 +10,6,12,12460,25,1,0,0,1,1,0,1,0,0 +10,6,13,12461,25,1,0,0,1,1,0,1,0,0 +10,6,14,12462,25,1,0,0,1,1,0,1,0,0 +10,6,15,12463,25,1,0,0,1,1,0,1,0,0 +10,6,16,12464,25,1,0,0,1,1,0,1,0,0 +10,6,17,12465,25,1,0,0,1,1,0,1,0,0 +10,6,18,12466,25,1,0,0,1,1,0,1,0,0 +10,6,19,12467,25,1,0,0,1,1,0,1,0,0 +10,6,20,12468,25,1,0,0,1,1,0,1,0,0 +10,6,21,12469,25,1,0,0,1,1,0,1,0,0 +10,6,22,15109,1000,1,0,0,1,1,0,1,0,0 +10,6,23,15110,1000,1,0,0,1,1,0,1,0,0 +10,6,24,2158,200,100,0,0,1,1,0,1,0,0 +10,6,25,12306,2,1,0,0,1,1,0,1,80,0 +10,6,26,12306,20000,10000,0,0,1,1,0,1,80,0 +10,4,27,11664,20000,1,0,0,1,1,0,1,0,0 +10,4,28,11665,20000,1,0,0,1,1,0,1,0,0 +10,4,29,11666,20000,1,0,0,1,1,0,1,0,0 +10,4,30,11667,20000,1,0,0,1,1,0,1,0,0 +10,4,31,11668,20000,1,0,0,1,1,0,1,0,0 +10,4,32,11669,20000,1,0,0,1,1,0,1,0,0 +10,4,33,11670,20000,1,0,0,1,1,0,1,0,0 +10,4,34,11671,20000,1,0,0,1,1,0,1,0,0 +10,4,35,11672,20000,1,0,0,1,1,0,1,0,0 +10,4,36,11673,20000,1,0,0,1,1,0,1,0,0 +10,4,37,11674,20000,1,0,0,1,1,0,1,0,0 +10,4,38,11675,20000,1,0,0,1,1,0,1,0,0 +10,4,39,11676,20000,1,0,0,1,1,0,1,0,0 +10,4,40,11677,20000,1,0,0,1,1,0,1,0,0 +10,4,41,11678,20000,1,0,0,1,1,0,1,0,0 +10,4,42,11679,20000,1,0,0,1,1,0,1,0,0 +10,4,43,11680,20000,1,0,0,1,1,0,1,0,0 +10,4,44,11681,20000,1,0,0,1,1,0,1,0,0 +10,4,45,11682,20000,1,0,0,1,1,0,1,0,0 +10,4,46,11683,20000,1,0,0,1,1,0,1,0,0 +10,4,47,11684,20000,1,0,0,1,1,0,1,0,0 +10,4,48,11685,20000,1,0,0,1,1,0,1,0,0 +10,4,49,11686,20000,1,0,0,1,1,0,1,0,0 +10,4,50,11687,20000,1,0,0,1,1,0,1,0,0 +10,4,51,11688,20000,1,0,0,1,1,0,1,0,0 +10,4,52,11689,20000,1,0,0,1,1,0,1,0,0 +10,4,53,11690,20000,1,0,0,1,1,0,1,0,0 +10,4,54,11691,20000,1,0,0,1,1,0,1,0,0 +10,4,55,11692,20000,1,0,0,1,1,0,1,0,0 +10,4,56,11693,20000,1,0,0,1,1,0,1,0,0 +10,4,57,11694,20000,1,0,0,1,1,0,1,0,0 +10,4,58,11695,20000,1,0,0,1,1,0,1,0,0 +10,4,59,11696,20000,1,0,0,1,1,0,1,0,0 +10,4,60,11697,20000,1,0,0,1,1,0,1,0,0 +10,4,61,12893,20000,1,0,0,1,1,0,1,0,0 +10,4,62,12894,20000,1,0,0,1,1,0,1,0,0 +10,4,63,12895,20000,1,0,0,1,1,0,1,0,0 +10,4,64,12896,20000,1,0,0,1,1,0,1,0,0 +10,4,65,12897,20000,1,0,0,1,1,0,1,0,0 +10,4,66,12898,20000,1,0,0,1,1,0,1,0,0 +10,4,67,12899,20000,1,0,0,1,1,0,1,0,0 +10,4,68,14337,20000,1,0,0,1,1,0,1,0,0 +10,4,69,14338,20000,1,0,0,1,1,0,1,0,0 +10,4,70,14339,20000,1,0,0,1,1,0,1,0,0 +10,4,71,14340,20000,1,0,0,1,1,0,1,0,0 +10,4,72,14341,20000,1,0,0,1,1,0,1,0,0 +10,4,73,14342,20000,1,0,0,1,1,0,1,0,0 +10,4,74,14343,20000,1,0,0,1,1,0,1,0,0 +10,4,75,14344,20000,1,0,0,1,1,0,1,0,0 +10,4,76,14345,20000,1,0,0,1,1,0,1,0,0 +10,4,77,9254,10000,1,0,0,1,1,0,1,0,0 +10,4,78,9255,10000,1,0,0,1,1,0,1,0,0 +10,4,79,9256,10000,1,0,0,1,1,0,1,0,0 +10,4,80,9257,10000,1,0,0,1,1,0,1,0,0 +10,4,81,9258,10000,1,0,0,1,1,0,1,0,0 +10,4,82,9259,10000,1,0,0,1,1,0,1,0,0 +10,4,83,9260,10000,1,0,0,1,1,0,1,0,0 +10,4,84,9261,10000,1,0,0,1,1,0,1,0,0 +10,4,85,9262,10000,1,0,0,1,1,0,1,0,0 +10,4,86,9263,10000,1,0,0,1,1,0,1,0,0 +10,4,87,9264,10000,1,0,0,1,1,0,1,0,0 +10,4,88,9265,10000,1,0,0,1,1,0,1,0,0 +10,4,89,9266,10000,1,0,0,1,1,0,1,0,0 +10,4,90,9267,10000,1,0,0,1,1,0,1,0,0 +10,4,91,9268,10000,1,0,0,1,1,0,1,0,0 +10,4,92,9269,10000,1,0,0,1,1,0,1,0,0 +10,4,93,9270,10000,1,0,0,1,1,0,1,0,0 +10,4,94,9271,10000,1,0,0,1,1,0,1,0,0 +10,4,95,9272,10000,1,0,0,1,1,0,1,0,0 +10,4,96,9273,10000,1,0,0,1,1,0,1,0,0 +10,4,97,9274,10000,1,0,0,1,1,0,1,0,0 +10,4,98,9275,10000,1,0,0,1,1,0,1,0,0 +10,4,99,9276,10000,1,0,0,1,1,0,1,0,0 +10,4,100,9277,10000,1,0,0,1,1,0,1,0,0 +10,4,101,9278,10000,1,0,0,1,1,0,1,0,0 +10,4,102,9279,10000,1,0,0,1,1,0,1,0,0 +10,4,103,9280,10000,1,0,0,1,1,0,1,0,0 +10,4,104,9281,10000,1,0,0,1,1,0,1,0,0 +10,4,105,9282,10000,1,0,0,1,1,0,1,0,0 +10,4,106,9283,10000,1,0,0,1,1,0,1,0,0 +10,4,107,9284,10000,1,0,0,1,1,0,1,0,0 +10,4,108,9285,10000,1,0,0,1,1,0,1,0,0 +10,4,109,9286,10000,1,0,0,1,1,0,1,0,0 +10,4,110,9287,10000,1,0,0,1,1,0,1,0,0 +10,4,111,9288,10000,1,0,0,1,1,0,1,0,0 +10,4,112,9289,10000,1,0,0,1,1,0,1,0,0 +10,4,113,9290,10000,1,0,0,1,1,0,1,0,0 +10,4,114,9291,10000,1,0,0,1,1,0,1,0,0 +10,4,115,9292,10000,1,0,0,1,1,0,1,0,0 +10,4,116,9293,10000,1,0,0,1,1,0,1,0,0 +10,4,117,9294,10000,1,0,0,1,1,0,1,0,0 +10,4,118,9295,10000,1,0,0,1,1,0,1,0,0 +10,4,119,9296,10000,1,0,0,1,1,0,1,0,0 +10,4,120,9297,10000,1,0,0,1,1,0,1,0,0 +10,4,121,9298,10000,1,0,0,1,1,0,1,0,0 +10,4,122,9299,10000,1,0,0,1,1,0,1,0,0 +10,4,123,9300,10000,1,0,0,1,1,0,1,0,0 +10,4,124,9301,10000,1,0,0,1,1,0,1,0,0 +10,4,125,13196,10000,1,0,0,1,1,0,1,0,0 +10,4,126,13197,10000,1,0,0,1,1,0,1,0,0 +10,4,127,13198,10000,1,0,0,1,1,0,1,0,0 +10,4,128,13199,10000,1,0,0,1,1,0,1,0,0 +10,4,129,15542,10000,1,0,0,1,1,0,1,0,0 +10,4,130,15543,10000,1,0,0,1,1,0,1,0,0 +10,4,131,15544,10000,1,0,0,1,1,0,1,0,0 +10,4,132,15545,10000,1,0,0,1,1,0,1,0,0 +10,4,133,13640,20000,1,0,0,1,1,0,1,0,0 +10,4,134,13641,20000,1,0,0,1,1,0,1,0,0 +10,4,135,13642,20000,1,0,0,1,1,0,1,0,0 +10,4,136,13643,20000,1,0,0,1,1,0,1,0,0 +10,4,137,13644,20000,1,0,0,1,1,0,1,0,0 +10,4,138,13645,20000,1,0,0,1,1,0,1,0,0 +10,4,139,13646,20000,1,0,0,1,1,0,1,0,0 +10,4,140,13647,20000,1,0,0,1,1,0,1,0,0 +10,4,141,13648,20000,1,0,0,1,1,0,1,0,0 +10,4,142,13649,20000,1,0,0,1,1,0,1,0,0 +10,4,143,13650,20000,1,0,0,1,1,0,1,0,0 +10,4,144,13651,20000,1,0,0,1,1,0,1,0,0 +10,4,145,13652,20000,1,0,0,1,1,0,1,0,0 +10,4,146,13653,20000,1,0,0,1,1,0,1,0,0 +10,4,147,13654,20000,1,0,0,1,1,0,1,0,0 +10,4,148,13655,20000,1,0,0,1,1,0,1,0,0 +10,4,149,13656,20000,1,0,0,1,1,0,1,0,0 +10,4,150,13657,20000,1,0,0,1,1,0,1,0,0 +10,4,151,13658,20000,1,0,0,1,1,0,1,0,0 +10,4,152,13659,20000,1,0,0,1,1,0,1,0,0 +10,4,153,13660,20000,1,0,0,1,1,0,1,0,0 +10,4,154,13661,20000,1,0,0,1,1,0,1,0,0 +10,4,155,13662,20000,1,0,0,1,1,0,1,0,0 +10,4,156,13663,20000,1,0,0,1,1,0,1,0,0 +10,4,157,13664,20000,1,0,0,1,1,0,1,0,0 +10,4,158,13665,20000,1,0,0,1,1,0,1,0,0 +10,4,159,13666,20000,1,0,0,1,1,0,1,0,0 +10,4,160,13667,20000,1,0,0,1,1,0,1,0,0 +10,4,161,13668,20000,1,0,0,1,1,0,1,0,0 +10,4,162,13669,20000,1,0,0,1,1,0,1,0,0 +10,4,163,13670,20000,1,0,0,1,1,0,1,0,0 +10,4,164,13671,20000,1,0,0,1,1,0,1,0,0 +10,4,165,13672,20000,1,0,0,1,1,0,1,0,0 +10,4,166,13673,20000,1,0,0,1,1,0,1,0,0 +10,4,167,13674,20000,1,0,0,1,1,0,1,0,0 +10,4,168,13675,20000,1,0,0,1,1,0,1,0,0 +10,4,169,13676,20000,1,0,0,1,1,0,1,0,0 +10,4,170,13677,20000,1,0,0,1,1,0,1,0,0 +10,4,171,13678,20000,1,0,0,1,1,0,1,0,0 +10,4,172,13679,20000,1,0,0,1,1,0,1,0,0 +10,4,173,13680,20000,1,0,0,1,1,0,1,0,0 +10,4,174,13681,20000,1,0,0,1,1,0,1,0,0 +10,4,175,13682,20000,1,0,0,1,1,0,1,0,0 +10,4,176,13683,20000,1,0,0,1,1,0,1,0,0 +10,4,177,13684,20000,1,0,0,1,1,0,1,0,0 +10,4,178,13685,20000,1,0,0,1,1,0,1,0,0 +10,4,179,13686,20000,1,0,0,1,1,0,1,0,0 +10,4,180,13687,20000,1,0,0,1,1,0,1,0,0 +10,4,181,13688,20000,1,0,0,1,1,0,1,0,0 +10,4,182,13689,20000,1,0,0,1,1,0,1,0,0 +10,4,183,13690,20000,1,0,0,1,1,0,1,0,0 +10,4,184,13691,20000,1,0,0,1,1,0,1,0,0 +10,4,185,15546,20000,1,0,0,1,1,0,1,0,0 +10,4,186,15547,20000,1,0,0,1,1,0,1,0,0 +10,4,187,15548,20000,1,0,0,1,1,0,1,0,0 +10,4,188,15549,20000,1,0,0,1,1,0,1,0,0 +10,4,189,16162,35000,1,0,0,1,1,0,1,0,0 +10,4,190,16163,35000,1,0,0,1,1,0,1,0,0 +10,4,191,16164,35000,1,0,0,1,1,0,1,0,0 +10,4,192,16165,35000,1,0,0,1,1,0,1,0,0 +10,4,193,16166,35000,1,0,0,1,1,0,1,0,0 +10,4,194,16167,35000,1,0,0,1,1,0,1,0,0 +10,4,195,16168,35000,1,0,0,1,1,0,1,0,0 +10,4,196,16169,35000,1,0,0,1,1,0,1,0,0 +10,4,197,16172,35000,1,0,0,1,1,0,1,0,0 +10,4,198,16173,35000,1,0,0,1,1,0,1,0,0 +10,4,199,16174,35000,1,0,0,1,1,0,1,0,0 +10,4,200,16175,35000,1,0,0,1,1,0,1,0,0 +10,4,201,16176,35000,1,0,0,1,1,0,1,0,0 +10,4,202,16177,35000,1,0,0,1,1,0,1,0,0 +10,4,203,16178,35000,1,0,0,1,1,0,1,0,0 +10,4,204,16179,35000,1,0,0,1,1,0,1,0,0 +10,4,205,16182,35000,1,0,0,1,1,0,1,0,0 +10,4,206,16183,35000,1,0,0,1,1,0,1,0,0 +10,4,207,16184,35000,1,0,0,1,1,0,1,0,0 +10,4,208,16185,35000,1,0,0,1,1,0,1,0,0 +10,4,209,16186,35000,1,0,0,1,1,0,1,0,0 +10,4,210,16187,35000,1,0,0,1,1,0,1,0,0 +10,4,211,16188,35000,1,0,0,1,1,0,1,0,0 +10,4,212,16189,35000,1,0,0,1,1,0,1,0,0 +10,4,213,16192,35000,1,0,0,1,1,0,1,0,0 +10,4,214,16193,35000,1,0,0,1,1,0,1,0,0 +10,4,215,16194,35000,1,0,0,1,1,0,1,0,0 +10,4,216,16195,35000,1,0,0,1,1,0,1,0,0 +10,4,217,16196,35000,1,0,0,1,1,0,1,0,0 +10,4,218,16197,35000,1,0,0,1,1,0,1,0,0 +10,4,219,16198,35000,1,0,0,1,1,0,1,0,0 +10,4,220,16199,35000,1,0,0,1,1,0,1,0,0 +10,4,221,16202,35000,1,0,0,1,1,0,1,0,0 +10,4,222,16203,35000,1,0,0,1,1,0,1,0,0 +10,4,223,16204,35000,1,0,0,1,1,0,1,0,0 +10,4,224,16205,35000,1,0,0,1,1,0,1,0,0 +10,4,225,16206,35000,1,0,0,1,1,0,1,0,0 +10,4,226,16207,35000,1,0,0,1,1,0,1,0,0 +10,4,227,16208,35000,1,0,0,1,1,0,1,0,0 +10,4,228,16209,35000,1,0,0,1,1,0,1,0,0 +10,4,229,16212,35000,1,0,0,1,1,0,1,0,0 +10,4,230,16213,35000,1,0,0,1,1,0,1,0,0 +10,4,231,16214,35000,1,0,0,1,1,0,1,0,0 +10,4,232,16215,35000,1,0,0,1,1,0,1,0,0 +10,4,233,16216,35000,1,0,0,1,1,0,1,0,0 +10,4,234,16217,35000,1,0,0,1,1,0,1,0,0 +10,4,235,16218,35000,1,0,0,1,1,0,1,0,0 +10,4,236,16219,35000,1,0,0,1,1,0,1,0,0 +10,4,237,16222,35000,1,0,0,1,1,0,1,0,0 +10,4,238,16223,35000,1,0,0,1,1,0,1,0,0 +10,4,239,16224,35000,1,0,0,1,1,0,1,0,0 +10,4,240,16225,35000,1,0,0,1,1,0,1,0,0 +10,4,241,16226,35000,1,0,0,1,1,0,1,0,0 +10,4,242,16227,35000,1,0,0,1,1,0,1,0,0 +10,4,243,16228,35000,1,0,0,1,1,0,1,0,0 +10,4,244,16229,35000,1,0,0,1,1,0,1,0,0 +10,4,245,16232,35000,1,0,0,1,1,0,1,0,0 +10,4,246,16233,35000,1,0,0,1,1,0,1,0,0 +10,4,247,16234,35000,1,0,0,1,1,0,1,0,0 +10,4,248,16235,35000,1,0,0,1,1,0,1,0,0 +10,4,249,16236,35000,1,0,0,1,1,0,1,0,0 +10,4,250,16237,35000,1,0,0,1,1,0,1,0,0 +10,4,251,16238,35000,1,0,0,1,1,0,1,0,0 +10,4,252,16239,35000,1,0,0,1,1,0,1,0,0 +10,4,253,16242,35000,1,0,0,1,1,0,1,0,0 +10,4,254,16243,35000,1,0,0,1,1,0,1,0,0 +10,4,255,16244,35000,1,0,0,1,1,0,1,0,0 +10,4,256,16245,35000,1,0,0,1,1,0,1,0,0 +10,4,257,16246,35000,1,0,0,1,1,0,1,0,0 +10,4,258,16247,35000,1,0,0,1,1,0,1,0,0 +10,4,259,16248,35000,1,0,0,1,1,0,1,0,0 +10,4,260,16249,35000,1,0,0,1,1,0,1,0,0 +10,4,261,16252,35000,1,0,0,1,1,0,1,0,0 +10,4,262,16253,35000,1,0,0,1,1,0,1,0,0 +10,4,263,16254,35000,1,0,0,1,1,0,1,0,0 +10,4,264,16255,35000,1,0,0,1,1,0,1,0,0 +10,4,265,16256,35000,1,0,0,1,1,0,1,0,0 +10,4,266,16257,35000,1,0,0,1,1,0,1,0,0 +10,4,267,16258,35000,1,0,0,1,1,0,1,0,0 +10,4,268,16259,35000,1,0,0,1,1,0,1,0,0 +10,4,269,16262,35000,1,0,0,1,1,0,1,0,0 +10,4,270,16263,35000,1,0,0,1,1,0,1,0,0 +10,4,271,16264,35000,1,0,0,1,1,0,1,0,0 +10,4,272,16265,35000,1,0,0,1,1,0,1,0,0 +10,4,273,16266,35000,1,0,0,1,1,0,1,0,0 +10,4,274,16267,35000,1,0,0,1,1,0,1,0,0 +10,4,275,16268,35000,1,0,0,1,1,0,1,0,0 +10,4,276,16269,35000,1,0,0,1,1,0,1,0,0 +10,4,277,16272,35000,1,0,0,1,1,0,1,0,0 +10,4,278,16273,35000,1,0,0,1,1,0,1,0,0 +10,4,279,16274,35000,1,0,0,1,1,0,1,0,0 +10,4,280,16275,35000,1,0,0,1,1,0,1,0,0 +10,4,281,16276,35000,1,0,0,1,1,0,1,0,0 +10,4,282,16277,35000,1,0,0,1,1,0,1,0,0 +10,4,283,16278,35000,1,0,0,1,1,0,1,0,0 +10,4,284,16279,35000,1,0,0,1,1,0,1,0,0 +10,4,285,16282,35000,1,0,0,1,1,0,1,0,0 +10,4,286,16283,35000,1,0,0,1,1,0,1,0,0 +10,4,287,16284,35000,1,0,0,1,1,0,1,0,0 +10,4,288,16285,35000,1,0,0,1,1,0,1,0,0 +10,4,289,16286,35000,1,0,0,1,1,0,1,0,0 +10,4,290,16287,35000,1,0,0,1,1,0,1,0,0 +10,4,291,16288,35000,1,0,0,1,1,0,1,0,0 +10,4,292,16289,35000,1,0,0,1,1,0,1,0,0 +10,4,293,16292,35000,1,0,0,1,1,0,1,0,0 +10,4,294,16293,35000,1,0,0,1,1,0,1,0,0 +10,4,295,16294,35000,1,0,0,1,1,0,1,0,0 +10,4,296,16295,35000,1,0,0,1,1,0,1,0,0 +10,4,297,16296,35000,1,0,0,1,1,0,1,0,0 +10,4,298,16297,35000,1,0,0,1,1,0,1,0,0 +10,4,299,16298,35000,1,0,0,1,1,0,1,0,0 +10,4,300,16299,35000,1,0,0,1,1,0,1,0,0 +10,8,301,14136,15000,1,0,0,1,1,0,1,0,0 +10,8,302,14137,15000,1,0,0,1,1,0,1,0,0 +10,8,303,14138,15000,1,0,0,1,1,0,1,0,0 +10,8,304,14139,15000,1,0,0,1,1,0,1,0,0 +10,8,305,14140,15000,1,0,0,1,1,0,1,0,0 +10,8,306,14141,15000,1,0,0,1,1,0,1,0,0 +10,8,307,14142,15000,1,0,0,1,1,0,1,0,0 +10,8,308,14143,15000,1,0,0,1,1,0,1,0,0 +10,8,309,14144,15000,1,0,0,1,1,0,1,0,0 +10,8,310,14145,15000,1,0,0,1,1,0,1,0,0 +10,8,311,14454,30000,1,0,0,1,1,0,1,0,0 +10,8,312,14455,30000,1,0,0,1,1,0,1,0,0 +10,8,313,14456,30000,1,0,0,1,1,0,1,0,0 +10,8,314,14457,30000,1,0,0,1,1,0,1,0,0 +10,8,315,14458,30000,1,0,0,1,1,0,1,0,0 +10,8,316,14459,30000,1,0,0,1,1,0,1,0,0 +10,8,317,14460,30000,1,0,0,1,1,0,1,0,0 +10,8,318,14461,30000,1,0,0,1,1,0,1,0,0 +10,8,319,14462,30000,1,0,0,1,1,0,1,0,0 +10,8,320,14463,30000,1,0,0,1,1,0,1,0,0 +10,8,321,12724,50000,1,0,0,1,1,0,1,0,0 +10,8,322,12725,50000,1,0,0,1,1,0,1,0,0 +10,8,323,12726,50000,1,0,0,1,1,0,1,0,0 +10,8,324,12727,50000,1,0,0,1,1,0,1,0,0 +10,8,325,12728,50000,1,0,0,1,1,0,1,0,0 +10,8,326,12729,50000,1,0,0,1,1,0,1,0,0 +10,8,327,12730,50000,1,0,0,1,1,0,1,0,0 +10,8,328,12731,50000,1,0,0,1,1,0,1,0,0 +10,8,329,12732,50000,1,0,0,1,1,0,1,0,0 +10,8,330,12733,50000,1,0,0,1,1,0,1,0,0 +10,8,331,12734,50000,1,0,0,1,1,0,1,0,0 +10,8,332,12735,50000,1,0,0,1,1,0,1,0,0 +10,8,333,12736,50000,1,0,0,1,1,0,1,0,0 +10,8,334,12737,50000,1,0,0,1,1,0,1,0,0 +10,8,335,12738,50000,1,0,0,1,1,0,1,0,0 +10,8,336,12739,50000,1,0,0,1,1,0,1,0,0 +10,8,337,12740,50000,1,0,0,1,1,0,1,0,0 +10,8,338,12741,50000,1,0,0,1,1,0,1,0,0 +10,8,339,12742,50000,1,0,0,1,1,0,1,0,0 +10,8,340,12743,50000,1,0,0,1,1,0,1,0,0 +10,8,341,12744,50000,1,0,0,1,1,0,1,0,0 +10,8,342,12745,50000,1,0,0,1,1,0,1,0,0 +10,8,343,12746,50000,1,0,0,1,1,0,1,0,0 +10,8,344,12747,50000,1,0,0,1,1,0,1,0,0 +10,8,345,12748,50000,1,0,0,1,1,0,1,0,0 +10,8,346,12749,50000,1,0,0,1,1,0,1,0,0 +10,8,347,12750,50000,1,0,0,1,1,0,1,0,0 +10,8,348,12751,50000,1,0,0,1,1,0,1,0,0 +10,8,349,12752,50000,1,0,0,1,1,0,1,0,0 +10,8,350,12753,50000,1,0,0,1,1,0,1,0,0 +10,8,351,15070,50000,1,0,0,1,1,0,1,0,0 +10,8,352,15071,50000,1,0,0,1,1,0,1,0,0 +10,8,353,15072,50000,1,0,0,1,1,0,1,0,0 +10,8,354,15073,50000,1,0,0,1,1,0,1,0,0 +10,8,355,15074,50000,1,0,0,1,1,0,1,0,0 +10,8,356,15075,50000,1,0,0,1,1,0,1,0,0 +10,8,357,15076,50000,1,0,0,1,1,0,1,0,0 +10,8,358,15077,50000,1,0,0,1,1,0,1,0,0 +10,8,359,15078,50000,1,0,0,1,1,0,1,0,0 +10,8,360,15079,50000,1,0,0,1,1,0,1,0,0 +10,8,361,15567,20000,1,0,0,1,1,0,1,0,0 +10,8,362,15568,20000,1,0,0,1,1,0,1,0,0 +10,8,363,15569,20000,1,0,0,1,1,0,1,0,0 +10,8,364,15570,20000,1,0,0,1,1,0,1,0,0 +10,8,365,15571,20000,1,0,0,1,1,0,1,0,0 +10,8,366,15572,20000,1,0,0,1,1,0,1,0,0 +10,8,367,15573,20000,1,0,0,1,1,0,1,0,0 +10,8,368,15574,20000,1,0,0,1,1,0,1,0,0 +10,8,369,15575,20000,1,0,0,1,1,0,1,0,0 +10,8,370,15576,20000,1,0,0,1,1,0,1,0,0 +10,8,371,15577,20000,1,0,0,1,1,0,1,0,0 +10,8,372,15578,20000,1,0,0,1,1,0,1,0,0 +10,8,373,15579,20000,1,0,0,1,1,0,1,0,0 +10,8,374,15580,20000,1,0,0,1,1,0,1,0,0 +10,8,375,15581,20000,1,0,0,1,1,0,1,0,0 +10,8,376,15582,20000,1,0,0,1,1,0,1,0,0 +10,8,377,15583,20000,1,0,0,1,1,0,1,0,0 +10,8,378,15584,20000,1,0,0,1,1,0,1,0,0 +10,8,379,15585,20000,1,0,0,1,1,0,1,0,0 +10,8,380,15586,20000,1,0,0,1,1,0,1,0,0 +10,8,381,15587,20000,1,0,0,1,1,0,1,0,0 +10,8,382,15588,20000,1,0,0,1,1,0,1,0,0 +10,8,383,15589,20000,1,0,0,1,1,0,1,0,0 +10,8,384,15590,20000,1,0,0,1,1,0,1,0,0 +10,8,385,15591,20000,1,0,0,1,1,0,1,0,0 +10,8,386,15592,20000,1,0,0,1,1,0,1,0,0 +10,8,387,15593,20000,1,0,0,1,1,0,1,0,0 +10,8,388,15594,20000,1,0,0,1,1,0,1,0,0 +10,8,389,15595,20000,1,0,0,1,1,0,1,0,0 +10,8,390,15596,20000,1,0,0,1,1,0,1,0,0 +10,8,391,15597,20000,1,0,0,1,1,0,1,0,0 +10,8,392,15598,20000,1,0,0,1,1,0,1,0,0 +10,8,393,15599,20000,1,0,0,1,1,0,1,0,0 +10,8,394,15600,20000,1,0,0,1,1,0,1,0,0 +10,8,395,15601,20000,1,0,0,1,1,0,1,0,0 +10,8,396,15602,20000,1,0,0,1,1,0,1,0,0 +10,8,397,15603,20000,1,0,0,1,1,0,1,0,0 +10,8,398,15604,20000,1,0,0,1,1,0,1,0,0 +10,8,399,15605,20000,1,0,0,1,1,0,1,0,0 +10,8,400,15606,20000,1,0,0,1,1,0,1,0,0 +10,8,401,15607,20000,1,0,0,1,1,0,1,0,0 +10,8,402,15608,20000,1,0,0,1,1,0,1,0,0 +10,8,403,15609,20000,1,0,0,1,1,0,1,0,0 +10,8,404,15610,20000,1,0,0,1,1,0,1,0,0 +10,8,405,15611,20000,1,0,0,1,1,0,1,0,0 +10,8,406,15612,20000,1,0,0,1,1,0,1,0,0 +10,8,407,15613,20000,1,0,0,1,1,0,1,0,0 +10,8,408,15614,20000,1,0,0,1,1,0,1,0,0 +10,8,409,15615,20000,1,0,0,1,1,0,1,0,0 +10,8,410,15616,20000,1,0,0,1,1,0,1,0,0 +10,8,411,15617,20000,1,0,0,1,1,0,1,0,0 +10,8,412,15618,20000,1,0,0,1,1,0,1,0,0 +10,8,413,15619,20000,1,0,0,1,1,0,1,0,0 +10,8,414,15620,20000,1,0,0,1,1,0,1,0,0 +10,8,415,15621,20000,1,0,0,1,1,0,1,0,0 +10,8,416,15622,20000,1,0,0,1,1,0,1,0,0 +10,8,417,15623,20000,1,0,0,1,1,0,1,0,0 +10,8,418,15624,20000,1,0,0,1,1,0,1,0,0 +10,8,419,15625,20000,1,0,0,1,1,0,1,0,0 +10,8,420,15626,20000,1,0,0,1,1,0,1,0,0 +10,8,421,15627,20000,1,0,0,1,1,0,1,0,0 +10,8,422,15628,20000,1,0,0,1,1,0,1,0,0 +10,8,423,15629,20000,1,0,0,1,1,0,1,0,0 +10,8,424,15630,20000,1,0,0,1,1,0,1,0,0 +10,8,425,15631,20000,1,0,0,1,1,0,1,0,0 +10,8,426,15632,20000,1,0,0,1,1,0,1,0,0 +10,8,427,15633,20000,1,0,0,1,1,0,1,0,0 +10,8,428,15634,20000,1,0,0,1,1,0,1,0,0 +10,8,429,15635,20000,1,0,0,1,1,0,1,0,0 +10,8,430,15636,20000,1,0,0,1,1,0,1,0,0 +10,8,431,15637,20000,1,0,0,1,1,0,1,0,0 +10,8,432,15638,20000,1,0,0,1,1,0,1,0,0 +10,8,433,15639,20000,1,0,0,1,1,0,1,0,0 +10,8,434,15640,20000,1,0,0,1,1,0,1,0,0 +10,8,435,15641,20000,1,0,0,1,1,0,1,0,0 +10,8,436,15642,20000,1,0,0,1,1,0,1,0,0 +10,8,437,15643,20000,1,0,0,1,1,0,1,0,0 +10,8,438,15644,20000,1,0,0,1,1,0,1,0,0 +10,8,439,15645,20000,1,0,0,1,1,0,1,0,0 +10,8,440,15646,20000,1,0,0,1,1,0,1,0,0 +10,8,441,15647,20000,1,0,0,1,1,0,1,0,0 +10,8,442,15648,20000,1,0,0,1,1,0,1,0,0 +10,8,443,15649,20000,1,0,0,1,1,0,1,0,0 +10,8,444,15650,20000,1,0,0,1,1,0,1,0,0 +10,8,445,15651,20000,1,0,0,1,1,0,1,0,0 +10,8,446,15652,20000,1,0,0,1,1,0,1,0,0 +10,8,447,15653,20000,1,0,0,1,1,0,1,0,0 +10,8,448,15654,20000,1,0,0,1,1,0,1,0,0 +10,8,449,15655,20000,1,0,0,1,1,0,1,0,0 +10,8,450,15656,20000,1,0,0,1,1,0,1,0,0 +10,8,451,15657,20000,1,0,0,1,1,0,1,0,0 +10,8,452,15658,20000,1,0,0,1,1,0,1,0,0 +10,8,453,15659,20000,1,0,0,1,1,0,1,0,0 +10,8,454,15660,20000,1,0,0,1,1,0,1,0,0 +10,8,455,15661,20000,1,0,0,1,1,0,1,0,0 +10,8,456,15662,20000,1,0,0,1,1,0,1,0,0 +10,8,457,15663,20000,1,0,0,1,1,0,1,0,0 +10,8,458,15664,20000,1,0,0,1,1,0,1,0,0 +10,8,459,15665,20000,1,0,0,1,1,0,1,0,0 +10,8,460,15666,20000,1,0,0,1,1,0,1,0,0 +10,8,461,15667,20000,1,0,0,1,1,0,1,0,0 +10,8,462,15668,20000,1,0,0,1,1,0,1,0,0 +10,8,463,15669,20000,1,0,0,1,1,0,1,0,0 +10,8,464,15670,20000,1,0,0,1,1,0,1,0,0 +10,8,465,15671,20000,1,0,0,1,1,0,1,0,0 +10,8,466,15672,20000,1,0,0,1,1,0,1,0,0 +10,8,467,15673,20000,1,0,0,1,1,0,1,0,0 +10,8,468,15674,20000,1,0,0,1,1,0,1,0,0 +10,8,469,15675,20000,1,0,0,1,1,0,1,0,0 +10,8,470,15676,20000,1,0,0,1,1,0,1,0,0 +10,8,471,15677,20000,1,0,0,1,1,0,1,0,0 +10,8,472,15678,20000,1,0,0,1,1,0,1,0,0 +10,8,473,15679,20000,1,0,0,1,1,0,1,0,0 +10,8,474,15680,20000,1,0,0,1,1,0,1,0,0 +10,8,475,15681,20000,1,0,0,1,1,0,1,0,0 +10,8,476,15682,20000,1,0,0,1,1,0,1,0,0 +10,8,477,15683,20000,1,0,0,1,1,0,1,0,0 +10,8,478,15684,20000,1,0,0,1,1,0,1,0,0 +10,8,479,15685,20000,1,0,0,1,1,0,1,0,0 +10,8,480,15686,20000,1,0,0,1,1,0,1,0,0 +10,8,481,15687,20000,1,0,0,1,1,0,1,0,0 +10,8,482,15688,20000,1,0,0,1,1,0,1,0,0 +10,8,483,15689,20000,1,0,0,1,1,0,1,0,0 +10,8,484,15690,20000,1,0,0,1,1,0,1,0,0 +10,8,485,15691,20000,1,0,0,1,1,0,1,0,0 +10,8,486,15692,20000,1,0,0,1,1,0,1,0,0 +10,8,487,15693,20000,1,0,0,1,1,0,1,0,0 +10,8,488,15694,20000,1,0,0,1,1,0,1,0,0 +10,8,489,15695,20000,1,0,0,1,1,0,1,0,0 +10,8,490,15696,20000,1,0,0,1,1,0,1,0,0 +10,8,491,15697,20000,1,0,0,1,1,0,1,0,0 +10,8,492,15698,20000,1,0,0,1,1,0,1,0,0 +10,8,493,15699,20000,1,0,0,1,1,0,1,0,0 +10,8,494,15700,20000,1,0,0,1,1,0,1,0,0 +10,8,495,15701,20000,1,0,0,1,1,0,1,0,0 +10,8,496,15702,20000,1,0,0,1,1,0,1,0,0 +10,8,497,15703,20000,1,0,0,1,1,0,1,0,0 +10,8,498,15704,20000,1,0,0,1,1,0,1,0,0 +10,8,499,15705,20000,1,0,0,1,1,0,1,0,0 +10,8,500,15706,20000,1,0,0,1,1,0,1,0,0 +10,8,501,15707,20000,1,0,0,1,1,0,1,0,0 +10,8,502,15708,20000,1,0,0,1,1,0,1,0,0 +10,8,503,15709,20000,1,0,0,1,1,0,1,0,0 +10,8,504,15710,20000,1,0,0,1,1,0,1,0,0 +10,8,505,15711,20000,1,0,0,1,1,0,1,0,0 +10,8,506,15712,20000,1,0,0,1,1,0,1,0,0 +10,8,507,15713,20000,1,0,0,1,1,0,1,0,0 +10,8,508,15714,20000,1,0,0,1,1,0,1,0,0 +10,8,509,15715,20000,1,0,0,1,1,0,1,0,0 +10,8,510,15716,20000,1,0,0,1,1,0,1,0,0 +10,8,511,15717,20000,1,0,0,1,1,0,1,0,0 +10,8,512,15718,20000,1,0,0,1,1,0,1,0,0 +10,8,513,15719,20000,1,0,0,1,1,0,1,0,0 +10,8,514,15720,20000,1,0,0,1,1,0,1,0,0 +10,8,515,15721,20000,1,0,0,1,1,0,1,0,0 +10,8,516,15722,20000,1,0,0,1,1,0,1,0,0 +10,8,517,15723,20000,1,0,0,1,1,0,1,0,0 +10,8,518,15724,20000,1,0,0,1,1,0,1,0,0 +10,8,519,15725,20000,1,0,0,1,1,0,1,0,0 +10,8,520,15726,20000,1,0,0,1,1,0,1,0,0 +10,8,521,15727,20000,1,0,0,1,1,0,1,0,0 +10,8,522,15728,20000,1,0,0,1,1,0,1,0,0 +10,8,523,15729,20000,1,0,0,1,1,0,1,0,0 +10,8,524,15730,20000,1,0,0,1,1,0,1,0,0 +10,8,525,15731,20000,1,0,0,1,1,0,1,0,0 +10,8,526,15732,20000,1,0,0,1,1,0,1,0,0 +10,8,527,15733,20000,1,0,0,1,1,0,1,0,0 +10,8,528,15734,20000,1,0,0,1,1,0,1,0,0 +10,8,529,15735,20000,1,0,0,1,1,0,1,0,0 +10,8,530,15736,20000,1,0,0,1,1,0,1,0,0 +10,8,531,15737,20000,1,0,0,1,1,0,1,0,0 +10,8,532,15738,20000,1,0,0,1,1,0,1,0,0 +10,8,533,15739,20000,1,0,0,1,1,0,1,0,0 +10,8,534,15740,20000,1,0,0,1,1,0,1,0,0 +10,8,535,15741,20000,1,0,0,1,1,0,1,0,0 +10,8,536,15742,20000,1,0,0,1,1,0,1,0,0 +10,8,537,15743,20000,1,0,0,1,1,0,1,0,0 +10,8,538,15744,20000,1,0,0,1,1,0,1,0,0 +10,8,539,15745,20000,1,0,0,1,1,0,1,0,0 +10,8,540,15746,20000,1,0,0,1,1,0,1,0,0 +10,8,541,15747,20000,1,0,0,1,1,0,1,0,0 +10,8,542,15748,20000,1,0,0,1,1,0,1,0,0 +10,8,543,15749,20000,1,0,0,1,1,0,1,0,0 +10,8,544,15750,20000,1,0,0,1,1,0,1,0,0 +10,8,545,15751,20000,1,0,0,1,1,0,1,0,0 +10,8,546,15752,20000,1,0,0,1,1,0,1,0,0 +10,8,547,15753,20000,1,0,0,1,1,0,1,0,0 +10,8,548,15754,20000,1,0,0,1,1,0,1,0,0 +10,8,549,15755,20000,1,0,0,1,1,0,1,0,0 +10,8,550,15756,20000,1,0,0,1,1,0,1,0,0 +10,8,551,15757,20000,1,0,0,1,1,0,1,0,0 +10,8,552,15758,20000,1,0,0,1,1,0,1,0,0 +10,8,553,15759,20000,1,0,0,1,1,0,1,0,0 +10,8,554,15760,20000,1,0,0,1,1,0,1,0,0 +10,8,555,15761,20000,1,0,0,1,1,0,1,0,0 +10,8,556,15762,20000,1,0,0,1,1,0,1,0,0 +10,8,557,15763,20000,1,0,0,1,1,0,1,0,0 +10,8,558,15764,20000,1,0,0,1,1,0,1,0,0 +10,8,559,15765,20000,1,0,0,1,1,0,1,0,0 +10,8,560,15766,20000,1,0,0,1,1,0,1,0,0 +10,8,561,15919,20000,1,0,0,1,1,0,1,0,0 +10,8,562,15920,20000,1,0,0,1,1,0,1,0,0 +10,8,563,15921,20000,1,0,0,1,1,0,1,0,0 +10,8,564,15922,20000,1,0,0,1,1,0,1,0,0 +10,8,565,15923,20000,1,0,0,1,1,0,1,0,0 +10,8,566,15924,20000,1,0,0,1,1,0,1,0,0 +10,8,567,15925,20000,1,0,0,1,1,0,1,0,0 +10,8,568,15926,20000,1,0,0,1,1,0,1,0,0 +10,8,569,15927,20000,1,0,0,1,1,0,1,0,0 +10,8,570,15928,20000,1,0,0,1,1,0,1,0,0 +10,8,571,15929,20000,1,0,0,1,1,0,1,0,0 +10,8,572,15930,20000,1,0,0,1,1,0,1,0,0 +10,8,573,15931,20000,1,0,0,1,1,0,1,0,0 +10,8,574,15932,20000,1,0,0,1,1,0,1,0,0 +10,8,575,15933,20000,1,0,0,1,1,0,1,0,0 +10,8,576,15934,20000,1,0,0,1,1,0,1,0,0 +10,8,577,15935,20000,1,0,0,1,1,0,1,0,0 +10,8,578,15936,20000,1,0,0,1,1,0,1,0,0 +10,8,579,15937,20000,1,0,0,1,1,0,1,0,0 +10,8,580,15938,20000,1,0,0,1,1,0,1,0,0 +10,8,581,15939,20000,1,0,0,1,1,0,1,0,0 +10,8,582,15940,20000,1,0,0,1,1,0,1,0,0 +10,8,583,15941,20000,1,0,0,1,1,0,1,0,0 +10,8,584,15942,20000,1,0,0,1,1,0,1,0,0 +10,8,585,15943,20000,1,0,0,1,1,0,1,0,0 +10,8,586,15944,20000,1,0,0,1,1,0,1,0,0 +10,8,587,15945,20000,1,0,0,1,1,0,1,0,0 +10,8,588,15946,20000,1,0,0,1,1,0,1,0,0 +10,8,589,15947,20000,1,0,0,1,1,0,1,0,0 +10,8,590,15948,20000,1,0,0,1,1,0,1,0,0 +10,8,591,15949,20000,1,0,0,1,1,0,1,0,0 +10,8,592,15950,20000,1,0,0,1,1,0,1,0,0 +10,8,593,15951,20000,1,0,0,1,1,0,1,0,0 +10,8,594,15952,20000,1,0,0,1,1,0,1,0,0 +10,8,595,15953,20000,1,0,0,1,1,0,1,0,0 +10,8,596,15954,20000,1,0,0,1,1,0,1,0,0 +10,8,597,15955,20000,1,0,0,1,1,0,1,0,0 +10,8,598,15956,20000,1,0,0,1,1,0,1,0,0 +10,8,599,15957,20000,1,0,0,1,1,0,1,0,0 +10,8,600,15958,20000,1,0,0,1,1,0,1,0,0 +10,8,601,15959,20000,1,0,0,1,1,0,1,0,0 +10,8,602,15960,20000,1,0,0,1,1,0,1,0,0 +10,8,603,15961,20000,1,0,0,1,1,0,1,0,0 +10,8,604,15962,20000,1,0,0,1,1,0,1,0,0 +10,8,605,15963,20000,1,0,0,1,1,0,1,0,0 +10,8,606,15964,20000,1,0,0,1,1,0,1,0,0 +10,8,607,15965,20000,1,0,0,1,1,0,1,0,0 +10,8,608,15966,20000,1,0,0,1,1,0,1,0,0 +10,8,609,15967,20000,1,0,0,1,1,0,1,0,0 +10,8,610,15968,20000,1,0,0,1,1,0,1,0,0 +10,7,611,13506,250,1,0,0,1,1,0,1,50,0 +10,7,612,15011,250,1,0,0,1,1,0,1,50,0 +10,7,613,13636,250,1,0,0,1,1,0,1,50,0 +10,7,614,1227,250,1,0,0,1,1,0,1,50,0 +10,7,615,15022,250,1,0,0,1,1,0,1,50,0 +10,8,616,4407,1000,1,0,0,1,1,0,1,0,0 +10,8,617,4408,1000,1,0,0,1,1,0,1,0,0 +10,8,618,4409,1000,1,0,0,1,1,0,1,0,0 +10,8,619,4410,1000,1,0,0,1,1,0,1,0,0 +10,8,620,4411,1000,1,0,0,1,1,0,1,0,0 +10,8,621,4412,1000,1,0,0,1,1,0,1,0,0 +10,8,622,4413,1000,1,0,0,1,1,0,1,0,0 +10,8,623,4414,1000,1,0,0,1,1,0,1,0,0 +10,8,624,4823,1000,1,0,0,1,1,0,1,0,0 +10,8,625,4824,1000,1,0,0,1,1,0,1,0,0 +10,8,626,4825,1000,1,0,0,1,1,0,1,0,0 +10,8,627,4826,1000,1,0,0,1,1,0,1,0,0 +10,8,628,4827,1000,1,0,0,1,1,0,1,0,0 +10,8,629,4828,1000,1,0,0,1,1,0,1,0,0 +10,8,630,4829,1000,1,0,0,1,1,0,1,0,0 +10,8,631,4830,1000,1,0,0,1,1,0,1,0,0 +10,8,632,5194,1000,1,0,0,1,1,0,1,0,0 +10,8,633,5195,1000,1,0,0,1,1,0,1,0,0 +10,8,634,5196,1000,1,0,0,1,1,0,1,0,0 +10,8,635,5197,1000,1,0,0,1,1,0,1,0,0 +10,8,636,5198,1000,1,0,0,1,1,0,1,0,0 +10,8,637,5199,1000,1,0,0,1,1,0,1,0,0 +10,8,638,5200,1000,1,0,0,1,1,0,1,0,0 +10,8,639,5201,1000,1,0,0,1,1,0,1,0,0 +10,8,640,13630,1000,1,0,0,1,1,0,1,0,0 +10,8,641,13631,1000,1,0,0,1,1,0,1,0,0 +10,8,642,13632,1000,1,0,0,1,1,0,1,0,0 +10,8,643,13633,1000,1,0,0,1,1,0,1,0,0 +10,8,644,13634,1000,1,0,0,1,1,0,1,0,0 +10,8,645,13635,1000,1,0,0,1,1,0,1,0,0 +10,8,646,15103,1000,1,0,0,1,1,0,1,0,0 +10,8,647,15104,1000,1,0,0,1,1,0,1,0,0 +10,8,648,15105,1000,1,0,0,1,1,0,1,0,0 +10,8,649,15106,1000,1,0,0,1,1,0,1,0,0 +10,8,650,15107,1000,1,0,0,1,1,0,1,0,0 +10,8,651,15108,1000,1,0,0,1,1,0,1,0,0 +10,8,652,16459,1000,1,0,0,1,1,0,1,0,0 +10,8,653,16460,1000,1,0,0,1,1,0,1,0,0 +10,8,654,16461,1000,1,0,0,1,1,0,1,0,0 +10,8,655,16462,1000,1,0,0,1,1,0,1,0,0 +10,8,656,16463,1000,1,0,0,1,1,0,1,0,0 +10,8,657,16464,1000,1,0,0,1,1,0,1,0,0 +10,8,658,16465,1000,1,0,0,1,1,0,1,0,0 +10,8,659,16466,1000,1,0,0,1,1,0,1,0,0 +10,8,660,16467,1000,1,0,0,1,1,0,1,0,0 +10,8,661,16468,1000,1,0,0,1,1,0,1,0,0 +10,8,662,16469,1000,1,0,0,1,1,0,1,0,0 +10,8,663,16470,1000,1,0,0,1,1,0,1,0,0 +10,8,664,16471,1000,1,0,0,1,1,0,1,0,0 +10,8,665,16472,1000,1,0,0,1,1,0,1,0,0 +10,8,666,13416,1000,1,0,0,1,1,0,1,0,0 +10,8,667,13417,1000,1,0,0,1,1,0,1,0,0 +10,8,668,13418,1000,1,0,0,1,1,0,1,0,0 +10,8,669,13419,1000,1,0,0,1,1,0,1,0,0 +10,8,670,13420,1000,1,0,0,1,1,0,1,0,0 +10,8,671,14283,1000,1,0,0,1,1,0,1,0,0 +10,8,672,14284,1000,1,0,0,1,1,0,1,0,0 +10,8,673,14285,1000,1,0,0,1,1,0,1,0,0 +10,8,674,14286,1000,1,0,0,1,1,0,1,0,0 +10,8,675,13182,1000,1,0,0,1,1,0,1,0,0 +10,8,676,13507,1000,1,0,0,1,1,0,1,0,0 +10,8,677,13981,1000,1,0,0,1,1,0,1,0,0 +10,8,678,14744,1000,1,0,0,1,1,0,1,0,0 +10,8,679,14893,1000,1,0,0,1,1,0,1,0,0 +10,8,680,15785,1000,1,0,0,1,1,0,1,0,0 +10,8,681,16419,1000,1,0,0,1,1,0,1,0,0 +10,8,682,11470,1000,1,0,0,1,1,0,1,0,0 +10,8,683,12512,1000,1,0,0,1,1,0,1,0,0 +10,8,684,12884,1000,1,0,0,1,1,0,1,0,0 +10,8,685,12513,1000,1,0,0,1,1,0,1,0,0 +10,8,686,12514,1000,1,0,0,1,1,0,1,0,0 +10,8,687,12515,1000,1,0,0,1,1,0,1,0,0 +10,8,688,12516,1000,1,0,0,1,1,0,1,0,0 +10,8,689,12517,1000,1,0,0,1,1,0,1,0,0 +10,8,690,12518,1000,1,0,0,1,1,0,1,0,0 +10,8,691,12519,1000,1,0,0,1,1,0,1,0,0 +10,8,692,12520,1000,1,0,0,1,1,0,1,0,0 +10,8,693,12521,1000,1,0,0,1,1,0,1,0,0 +10,8,694,8179,1000,1,0,0,1,1,0,1,0,0 +10,8,695,9704,1000,1,0,0,1,1,0,1,0,0 +10,8,696,15448,1000,1,0,0,1,1,0,1,0,0 +10,8,697,11162,1000,1,0,0,1,1,0,1,0,0 +10,8,698,11163,1000,1,0,0,1,1,0,1,0,0 +10,8,699,11164,1000,1,0,0,1,1,0,1,0,0 +10,8,700,11165,1000,1,0,0,1,1,0,1,0,0 +10,8,701,11661,1000,1,0,0,1,1,0,1,0,0 +10,8,702,11662,1000,1,0,0,1,1,0,1,0,0 +10,8,703,14639,1000,1,0,0,1,1,0,1,0,0 +10,8,704,13607,10,1,0,0,1,1,0,1,0,0 +10,7,705,15774,3000,1,0,0,1,1,0,1,100,0 +10,7,706,15775,3000,1,0,0,1,1,0,1,100,0 +10,7,707,11420,3000,1,0,0,1,1,0,1,100,0 +10,7,708,14704,3000,1,0,0,1,1,0,1,100,0 +10,7,709,13177,3000,1,0,0,1,1,0,1,100,0 +10,7,710,14191,3000,1,0,0,1,1,0,1,100,0 +10,7,711,13449,3000,1,0,0,1,1,0,1,100,0 +10,7,712,14192,3000,1,0,0,1,1,0,1,100,0 +10,7,713,15772,3000,1,0,0,1,1,0,1,100,0 +10,7,714,13791,3000,1,0,0,1,1,0,1,100,0 +10,7,715,14006,3000,1,0,0,1,1,0,1,100,0 +10,7,716,15768,3000,1,0,0,1,1,0,1,100,0 +10,7,717,14069,3000,1,0,0,1,1,0,1,100,0 +10,7,718,14124,3000,1,0,0,1,1,0,1,100,0 +10,7,719,15507,3000,1,0,0,1,1,0,1,100,0 +10,7,720,15508,3000,1,0,0,1,1,0,1,100,0 +10,7,721,14855,3000,1,0,0,1,1,0,1,100,0 +10,7,722,14894,3000,1,0,0,1,1,0,1,100,0 +10,7,723,16444,3000,1,0,0,1,1,0,1,100,0 +10,7,724,16445,3000,1,0,0,1,1,0,1,100,0 +10,7,725,12509,3000,1,0,0,1,1,0,1,100,0 +10,7,726,14126,3000,1,0,0,1,1,0,1,100,0 +10,7,727,15062,3000,1,0,0,1,1,0,1,100,0 +10,7,728,15063,3000,1,0,0,1,1,0,1,100,0 +10,7,729,14891,3000,1,0,0,1,1,0,1,100,0 +10,7,730,14895,3000,1,0,0,1,1,0,1,100,0 +10,7,731,14091,3000,1,0,0,1,1,0,1,100,0 +10,7,732,14092,3000,1,0,0,1,1,0,1,100,0 +10,7,733,14501,3000,1,0,0,1,1,0,1,100,0 +10,7,734,14506,3000,1,0,0,1,1,0,1,100,0 +10,7,735,15285,3000,1,0,0,1,1,0,1,100,0 +10,7,736,15286,3000,1,0,0,1,1,0,1,100,0 +10,7,737,16442,3000,1,0,0,1,1,0,1,100,0 +10,7,738,16443,3000,1,0,0,1,1,0,1,100,0 +10,7,739,15027,3000,1,0,0,1,1,0,1,100,0 +10,7,740,15028,3000,1,0,0,1,1,0,1,100,0 +10,7,741,13453,3000,1,0,0,1,1,0,1,100,0 +10,7,742,14193,3000,1,0,0,1,1,0,1,100,0 +10,7,743,13178,3000,1,0,0,1,1,0,1,100,0 +10,7,744,14194,3000,1,0,0,1,1,0,1,100,0 +10,7,745,16454,3000,1,0,0,1,1,0,1,100,0 +10,7,746,16455,3000,1,0,0,1,1,0,1,100,0 +10,7,747,15030,3000,1,0,0,1,1,0,1,100,0 +10,7,748,15031,3000,1,0,0,1,1,0,1,100,0 +10,7,749,13790,3000,1,0,0,1,1,0,1,100,0 +10,7,750,14005,3000,1,0,0,1,1,0,1,100,0 +10,7,751,14406,3000,1,0,0,1,1,0,1,100,0 +10,7,752,14413,3000,1,0,0,1,1,0,1,100,0 +10,7,753,16448,3000,1,0,0,1,1,0,1,100,0 +10,7,754,16449,3000,1,0,0,1,1,0,1,100,0 +10,7,755,12872,3000,1,0,0,1,1,0,1,100,0 +10,7,756,14187,3000,1,0,0,1,1,0,1,100,0 +10,7,757,14125,3000,1,0,0,1,1,0,1,100,0 +10,7,758,14500,3000,1,0,0,1,1,0,1,100,0 +10,7,759,14505,3000,1,0,0,1,1,0,1,100,0 +10,7,760,15118,3000,1,0,0,1,1,0,1,100,0 +10,7,761,15119,3000,1,0,0,1,1,0,1,100,0 +10,7,762,14662,3000,1,0,0,1,1,0,1,100,0 +10,7,763,14663,3000,1,0,0,1,1,0,1,100,0 +10,7,764,15771,3000,1,0,0,1,1,0,1,100,0 +10,7,765,9700,3000,1,0,0,1,1,0,1,100,0 +10,7,766,14498,3000,1,0,0,1,1,0,1,100,0 +10,7,767,14913,3000,1,0,0,1,1,0,1,100,0 +10,7,768,14914,3000,1,0,0,1,1,0,1,100,0 +10,7,769,13508,3000,1,0,0,1,1,0,1,100,0 +10,7,770,15115,3000,1,0,0,1,1,0,1,100,0 +10,7,771,15116,3000,1,0,0,1,1,0,1,100,0 +10,7,772,15113,3000,1,0,0,1,1,0,1,100,0 +10,7,773,15114,3000,1,0,0,1,1,0,1,100,0 +10,7,774,15222,3000,1,0,0,1,1,0,1,100,0 +10,7,775,15223,3000,1,0,0,1,1,0,1,100,0 +10,7,776,10750,3000,1,0,0,1,1,0,1,100,0 +10,7,777,14705,3000,1,0,0,1,1,0,1,100,0 +10,7,778,15027,3000,1,0,0,1,1,0,1,100,0 +10,7,779,15028,3000,1,0,0,1,1,0,1,100,0 +10,7,780,10380,3000,1,0,0,1,1,0,1,100,0 +10,7,781,15060,3000,1,0,0,1,1,0,1,100,0 +10,7,782,13963,3000,1,0,0,1,1,0,1,100,0 +10,7,783,14026,3000,1,0,0,1,1,0,1,100,0 +10,7,784,13964,3000,1,0,0,1,1,0,1,100,0 +10,7,785,14027,3000,1,0,0,1,1,0,1,100,0 +10,7,786,15064,3000,1,0,0,1,1,0,1,100,0 +10,7,787,15065,3000,1,0,0,1,1,0,1,100,0 +10,7,788,15524,3000,1,0,0,1,1,0,1,100,0 +10,7,789,15525,3000,1,0,0,1,1,0,1,100,0 +10,7,790,16450,3000,1,0,0,1,1,0,1,100,0 +10,7,791,16451,3000,1,0,0,1,1,0,1,100,0 +10,7,792,16344,3000,1,0,0,1,1,0,1,100,0 +10,7,793,16345,3000,1,0,0,1,1,0,1,100,0 +10,7,794,16342,3000,1,0,0,1,1,0,1,100,0 +10,7,795,16343,3000,1,0,0,1,1,0,1,100,0 +10,7,796,15220,3000,1,0,0,1,1,0,1,100,0 +10,7,797,15221,3000,1,0,0,1,1,0,1,100,0 +10,7,798,15066,3000,1,0,0,1,1,0,1,100,0 +10,7,799,15067,3000,1,0,0,1,1,0,1,100,0 +10,7,800,14089,3000,1,0,0,1,1,0,1,100,0 +10,7,801,14090,3000,1,0,0,1,1,0,1,100,0 +10,7,802,14195,3000,1,0,0,1,1,0,1,100,0 +10,7,803,14196,3000,1,0,0,1,1,0,1,100,0 +10,7,804,13965,3000,1,0,0,1,1,0,1,100,0 +10,7,805,14028,3000,1,0,0,1,1,0,1,100,0 +10,7,806,13508,3000,1,0,0,1,1,0,1,100,0 +10,7,807,13962,3000,1,0,0,1,1,0,1,100,0 +10,7,808,14314,3000,1,0,0,1,1,0,1,100,0 +10,7,809,13404,3000,1,0,0,1,1,0,1,100,0 +10,7,810,14188,3000,1,0,0,1,1,0,1,100,0 +10,7,811,14032,3000,1,0,0,1,1,0,1,100,0 +10,7,812,13960,3000,1,0,0,1,1,0,1,100,0 +10,7,813,15819,3000,1,0,0,1,1,0,1,100,0 +10,7,814,15820,3000,1,0,0,1,1,0,1,100,0 +10,7,815,10750,3000,1,0,0,1,1,0,1,100,0 +10,7,816,14705,3000,1,0,0,1,1,0,1,100,0 +10,7,817,14407,3000,1,0,0,1,1,0,1,100,0 +10,7,818,14414,3000,1,0,0,1,1,0,1,100,0 +10,7,819,16352,3000,1,0,0,1,1,0,1,100,0 +10,7,820,16353,3000,1,0,0,1,1,0,1,100,0 +10,7,821,14502,3000,1,0,0,1,1,0,1,100,0 +10,7,822,14507,3000,1,0,0,1,1,0,1,100,0 +10,7,823,10811,3000,1,0,0,1,1,0,1,100,0 +10,7,824,15061,3000,1,0,0,1,1,0,1,100,0 +10,7,825,15823,3000,1,0,0,1,1,0,1,100,0 +10,7,826,15824,3000,1,0,0,1,1,0,1,100,0 +10,7,827,15224,3000,1,0,0,1,1,0,1,100,0 +10,7,828,15225,3000,1,0,0,1,1,0,1,100,0 +10,7,829,14503,3000,1,0,0,1,1,0,1,100,0 +10,7,830,14510,3000,1,0,0,1,1,0,1,100,0 +10,7,831,15776,3000,1,0,0,1,1,0,1,100,0 +10,7,832,15777,3000,1,0,0,1,1,0,1,100,0 +10,7,833,15821,3000,1,0,0,1,1,0,1,100,0 +10,7,834,15822,3000,1,0,0,1,1,0,1,100,0 +10,7,835,14198,3000,1,0,0,1,1,0,1,100,0 +10,7,836,14197,3000,1,0,0,1,1,0,1,100,0 +10,7,837,16446,3000,1,0,0,1,1,0,1,100,0 +10,7,838,16447,3000,1,0,0,1,1,0,1,100,0 +10,7,839,14905,3000,1,0,0,1,1,0,1,100,0 +10,7,840,14907,3000,1,0,0,1,1,0,1,100,0 +10,7,841,14904,3000,1,0,0,1,1,0,1,100,0 +10,7,842,14906,3000,1,0,0,1,1,0,1,100,0 +10,7,843,14659,3000,1,0,0,1,1,0,1,100,0 +10,7,844,14660,3000,1,0,0,1,1,0,1,100,0 +10,7,845,13326,3000,1,0,0,1,1,0,1,100,0 +10,7,846,14416,3000,1,0,0,1,1,0,1,100,0 +10,7,847,13450,3000,1,0,0,1,1,0,1,100,0 +10,7,848,14031,3000,1,0,0,1,1,0,1,100,0 +10,7,849,16492,3000,1,0,0,1,1,0,1,100,0 +10,7,850,16493,3000,1,0,0,1,1,0,1,100,0 +10,8,851,1520,1,1,0,0,1,1,0,1,0,0 +10,8,852,7011,1,1,0,0,1,1,0,1,0,0 +10,7,853,14299,500,1,0,0,1,1,0,1,20,0 +10,7,854,14389,500,1,0,0,1,1,0,1,20,0 +10,7,855,15177,500,1,0,0,1,1,0,1,20,0 +10,7,856,14537,500,1,0,0,1,1,0,1,20,0 +10,7,857,14758,500,1,0,0,1,1,0,1,20,0 +10,7,858,14854,500,1,0,0,1,1,0,1,20,0 +10,7,859,13974,500,1,0,0,1,1,0,1,20,0 +10,7,860,15021,500,1,0,0,1,1,0,1,20,0 +10,7,861,15111,500,1,0,0,1,1,0,1,20,0 +10,7,862,15226,500,1,0,0,1,1,0,1,20,0 +10,7,863,15773,500,1,0,0,1,1,0,1,20,0 +10,7,864,15825,500,1,0,0,1,1,0,1,20,0 +10,7,865,15827,500,1,0,0,1,1,0,1,20,0 +10,7,866,16340,500,1,0,0,1,1,0,1,20,0 +10,7,867,16341,500,1,0,0,1,1,0,1,20,0 +10,7,868,16457,500,1,0,0,1,1,0,1,20,0 +10,7,869,16458,500,1,0,0,1,1,0,1,20,0 +10,7,870,11698,250,1,0,0,1,1,0,1,50,0 +10,7,871,11700,250,1,0,0,1,1,0,1,50,0 +10,8,872,4358,10,1,0,0,1,1,0,1,0,0 +10,8,873,7981,1,1,0,0,1,1,0,1,0,0 +10,8,874,7267,20,1,0,0,1,1,0,1,0,0 +10,8,875,9958,20,1,0,0,1,1,0,1,0,999 +10,8,876,1548,20,1,0,0,1,1,0,1,0,0 +10,8,877,1613,20,1,0,0,1,1,0,1,0,0 +10,8,878,1026,1,1,0,0,1,1,0,1,0,0 +10,8,879,5380,1,1,0,0,1,1,0,1,0,0 +10,8,880,11284,15,1,0,0,1,1,0,1,0,0 +10,8,881,11285,15,1,0,0,1,1,0,1,0,0 +10,8,882,11286,15,1,0,0,1,1,0,1,0,0 +10,8,883,10356,500,1,0,0,1,1,0,1,0,0 +10,8,884,12511,500,1,0,0,1,1,0,1,0,0 +10,8,885,13238,500,1,0,0,1,1,0,1,0,0 +10,8,886,1691,1,1,0,0,1,1,0,1,0,0 +10,8,887,9708,1,1,0,0,1,1,0,1,0,0 +10,8,888,11383,10,1,0,0,1,1,0,1,0,0 +10,8,889,11382,10,1,0,0,1,1,0,1,0,0 +10,8,890,11381,10,1,0,0,1,1,0,1,0,0 +10,7,891,16348,3000,1,0,0,1,1,0,1,100,0 +10,8,892,11386,10,1,0,0,1,1,0,1,0,0 +10,8,893,5767,1,10000,0,0,1,1,0,1,0,0 +10,8,894,5765,1,10000,0,0,1,1,0,1,0,0 +10,8,895,5768,1,10000,0,0,1,1,0,1,0,0 +10,8,896,14444,10,1,0,0,1,1,0,1,0,0 +10,8,897,14443,10,1,0,0,1,1,0,1,0,0 +10,8,898,14445,10,1,0,0,1,1,0,1,0,0 +10,8,899,15068,500,1,0,0,1,1,0,1,20,0 +10,7,900,16532,1000,1,0,0,1,1,0,1,0,0 +10,8,901,100,1,10000,0,0,1,1,0,1,0,0 +10,8,902,11243,1,1,0,0,1,1,0,1,0,0 +10,8,903,101,1,10000,0,0,1,1,0,1,0,0 +10,7,904,14368,3000,1,0,0,1,1,0,1,50,0 +10,8,905,8943,1,20,0,0,1,1,0,1,0,0 +10,7,906,1622,3000,1,0,0,1,1,0,1,0,0 +10,8,907,8953,1,20,0,0,1,1,0,1,0,0 +10,8,908,13693,1,20,0,0,1,1,0,1,0,0 +10,8,909,8949,1,20,0,0,1,1,0,1,0,0 +10,8,910,8955,1,20,0,0,1,1,0,1,0,0 +10,7,911,16456,500,1,0,0,1,1,0,1,0,0 \ No newline at end of file diff --git a/Erupe/.gitignore b/Erupe/.gitignore new file mode 100644 index 000000000..45ebda766 --- /dev/null +++ b/Erupe/.gitignore @@ -0,0 +1,13 @@ +www/jp/ + +.idea/ +vendor/ +bin/*.bin +bin/quests/*.bin +bin/questlists/*.bin +bin/scenarios/*.bin +bin/debug/*.bin +savedata/ +Erupe.exe +*.lnk +*.bat \ No newline at end of file diff --git a/Erupe/Event List.txt b/Erupe/Event List.txt new file mode 100644 index 000000000..7c6838e8d --- /dev/null +++ b/Erupe/Event List.txt @@ -0,0 +1 @@ + 0 is no event, 1 is "Week 1 Timestamp (broken), 2 is "Week 2 Timestamp (broken), 3 is Diva Defense \ No newline at end of file diff --git a/Erupe/Gifts/Cadeaux.bin b/Erupe/Gifts/Cadeaux.bin new file mode 100644 index 000000000..2d3e24319 Binary files /dev/null and b/Erupe/Gifts/Cadeaux.bin differ diff --git a/Erupe/Gifts/Description.bin b/Erupe/Gifts/Description.bin new file mode 100644 index 000000000..957f9e111 Binary files /dev/null and b/Erupe/Gifts/Description.bin differ diff --git a/Erupe/LICENSE b/Erupe/LICENSE new file mode 100644 index 000000000..704115aa4 --- /dev/null +++ b/Erupe/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2019 The Erupe Developers from Einherjar Team + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Erupe/README.md b/Erupe/README.md new file mode 100644 index 000000000..15a1fca6c --- /dev/null +++ b/Erupe/README.md @@ -0,0 +1,83 @@ +# Erupe +## WARNING +This project is in its infancy and has no reliable active developer, no documentation, and no support. + +# General info +Currently allows a JP MHF client (with GameGuard removed) to: +* Login and register an account (registration is automatic if account doesn't exist) +* Create a character +* Get ingame to the main city +* See other players walk around +* Do quests +* Use chat* + +# Installation +## Server +1. Clone the repo with `git clone https://github.com/Andoryuuta/Erupe.git` +2. Install PostgreSQL +3. Launch psql shell, `CREATE DATABASE erupe;`. +4. Setup database with golang-migrate: + + Windows: + ``` + > go get -tags 'postgres' -u github.com/golang-migrate/migrate/v4/cmd/migrate/ + + > set POSTGRESQL_URL=postgres://postgres:password@localhost:5432/erupe?sslmode=disable + + > cd erupe + + > migrate -database %POSTGRESQL_URL% -path migrations up + ``` + + Linux: + ``` + > go get -tags 'postgres' -u github.com/golang-migrate/migrate/v4/cmd/migrate/ + + > export POSTGRESQL_URL=postgres://postgres:password@localhost:5432/erupe?sslmode=disable + + > cd erupe + + > migrate -database $POSTGRESQL_URL -path migrations up + ``` + + (Replacing `postgres:password` with your postgres username and password) + +5. Edit the config.json + + Namely: + * Update the database username and password + * Update the `host_ip` and `ip` fields (there are multiple) to your external IP if you are hosting for multiple clients. + +6. Place quest/scenario binaries. + + The quest and scenario binary files should be placed in `bin/quests/` and `bin/scenarios` respectively. + +## Launcher +Erupe ships with a rudimentary custom launcher, so you don't need to obtain the original TW/JP files to simply get ingame. However, it does still support using the original files if you choose to. To set this up, place a copy of the original launcher html/js/css in `./www/tw/`, and `/www/jp/` for the TW and JP files respectively. + +Then, modify the the `/launcher/js/launcher.js` file as such: +* Find the call to `startUpdateProcess();` in a case statement and replace it with `finishUpdateProcess();`. (This disables the file check and updating) +* (JP ONLY): replace all uses of "https://" with "http://" in the file. + +Finally, edit the config.json and set `UseOriginalLauncherFiles` to `true` under the launcher settings. + +# Usage +### Note: If you are switching to/from the custom launcher html, you will have to clear your IE cache @ `C:\Users\\AppData\Local\Microsoft\Windows\INetCache`. + +## Server +``` +cd Erupe +go run . +``` + +## Client +Add to hosts: +``` +127.0.0.1 mhfg.capcom.com.tw +127.0.0.1 mhf-n.capcom.com.tw +127.0.0.1 cog-members.mhf-z.jp +127.0.0.1 www.capcom-onlinegames.jp +127.0.0.1 srv-mhf.capcom-networks.jp +``` + +Run mhf.exe normally (with locale emulator or appropriate timezone). diff --git a/Erupe/bin/questlists/psql.txt b/Erupe/bin/questlists/psql.txt new file mode 100644 index 000000000..7429718e4 --- /dev/null +++ b/Erupe/bin/questlists/psql.txt @@ -0,0 +1,16 @@ +BEGIN; + +CREATE TABLE questlists ( + ind int NOT NULL PRIMARY KEY, + questlist bytea +); + +END; + +INSERT INTO questlists (ind, questlist) VALUES ('0', pg_read_binary_file('c:\save\quest_0_0.bin')); +INSERT INTO questlists (ind, questlist) VALUES ('42', pg_read_binary_file('c:\save\quest_42_2A.bin')); +INSERT INTO questlists (ind, questlist) VALUES ('84', pg_read_binary_file('c:\save\quest_84_54.bin')); +INSERT INTO questlists (ind, questlist) VALUES ('126', pg_read_binary_file('c:\save\quest_126_7E.bin')); +INSERT INTO questlists (ind, questlist) VALUES ('168', pg_read_binary_file('c:\save\quest_168_A8.bin')); + + diff --git a/Erupe/common/bfutil/bfutil.go b/Erupe/common/bfutil/bfutil.go new file mode 100644 index 000000000..066ed78a8 --- /dev/null +++ b/Erupe/common/bfutil/bfutil.go @@ -0,0 +1,8 @@ +package bfutil + +import "bytes" + +// UpToNull returns the given byte slice's data, up to (not including) the first null byte. +func UpToNull(data []byte) []byte { + return bytes.SplitN(data, []byte{0x00}, 2)[0] +} diff --git a/Erupe/common/stringstack/stringstack.go b/Erupe/common/stringstack/stringstack.go new file mode 100644 index 000000000..aff33842e --- /dev/null +++ b/Erupe/common/stringstack/stringstack.go @@ -0,0 +1,40 @@ +package stringstack + +import ( + "errors" + "sync" +) + +// StringStack is a basic LIFO "stack" for storing strings. +type StringStack struct { + sync.Mutex + stack []string +} + +// New creates a new instance of StringStack +func New() *StringStack { + return &StringStack{} +} + +// Push pushes a string onto the stack. +func (s *StringStack) Push(v string) { + s.Lock() + defer s.Unlock() + + s.stack = append(s.stack, v) +} + +// Pop pops a string from the stack. +func (s *StringStack) Pop() (string, error) { + s.Lock() + defer s.Unlock() + + if len(s.stack) == 0 { + return "", errors.New("no items on stack") + } + + x := s.stack[len(s.stack)-1] + s.stack = s.stack[:len(s.stack)-1] + + return x, nil +} diff --git a/Erupe/common/stringsupport/string_convert.go b/Erupe/common/stringsupport/string_convert.go new file mode 100644 index 000000000..dcc78c674 --- /dev/null +++ b/Erupe/common/stringsupport/string_convert.go @@ -0,0 +1,93 @@ +package stringsupport + +import ( + "bytes" + "io/ioutil" + + "golang.org/x/text/encoding" + "golang.org/x/text/encoding/japanese" + "golang.org/x/text/transform" +) + +// StringConverter is a small helper for encoding/decoding strings. +type StringConverter struct { + Encoding encoding.Encoding +} + +// Decode decodes the given bytes as the set encoding. +func (sc *StringConverter) Decode(data []byte) (string, error) { + decoded, err := ioutil.ReadAll(transform.NewReader(bytes.NewBuffer(data), sc.Encoding.NewDecoder())) + + if err != nil { + return "", err + } + + return string(decoded), nil +} + +// MustDecode decodes the given bytes as the set encoding. Panics on decode failure. +func (sc *StringConverter) MustDecode(data []byte) string { + decoded, err := sc.Decode(data) + if err != nil { + panic(err) + } + + return decoded +} + +// Encode encodes the given string as the set encoding. +func (sc *StringConverter) Encode(data string) ([]byte, error) { + encoded, err := ioutil.ReadAll(transform.NewReader(bytes.NewBuffer([]byte(data)), sc.Encoding.NewEncoder())) + + if err != nil { + return nil, err + } + + return encoded, nil +} + +// MustEncode encodes the given string as the set encoding. Panics on encode failure. +func (sc *StringConverter) MustEncode(data string) []byte { + encoded, err := sc.Encode(data) + if err != nil { + panic(err) + } + + return encoded +} + +/* +func MustConvertShiftJISToUTF8(text string) string { + result, err := ConvertShiftJISToUTF8(text) + if err != nil { + panic(err) + } + return result +} +func MustConvertUTF8ToShiftJIS(text string) string { + result, err := ConvertUTF8ToShiftJIS(text) + if err != nil { + panic(err) + } + return result +} +func ConvertShiftJISToUTF8(text string) (string, error) { + r := bytes.NewBuffer([]byte(text)) + decoded, err := ioutil.ReadAll(transform.NewReader(r, japanese.ShiftJIS.NewDecoder())) + if err != nil { + return "", err + } + return string(decoded), nil +} +*/ + +// ConvertUTF8ToShiftJIS converts a UTF8 string to a Shift-JIS []byte. +func ConvertUTF8ToShiftJIS(text string) ([]byte, error) { + r := bytes.NewBuffer([]byte(text)) + encoded, err := ioutil.ReadAll(transform.NewReader(r, japanese.ShiftJIS.NewEncoder())) + if err != nil { + return nil, err + } + + return encoded, nil +} diff --git a/Erupe/config.json b/Erupe/config.json new file mode 100644 index 000000000..7a0ef1183 --- /dev/null +++ b/Erupe/config.json @@ -0,0 +1,153 @@ +{ + "host_ip": "", + "bin_path": "bin", + "devmode": true, + "devmodeoptions": { + "serverName" : "", + "cleandb": false, + "maxlauncherhr": true, + "LogOutboundMessages": false, + "Event": 0, + "OpcodeMessages": false, + "SaveDumps": { + "Enabled": true, + "OutputDir": "savedata" + } + + }, + "discord": { + "enabled": false, + "bottoken": "", + "channelid": "" + }, + "database": { + "host": "localhost", + "port": 5432, + "user": "postgres", + "password": "", + "database": "erupe" + }, + "launcher": { + "port": 80, + "UseOriginalLauncherFiles": false + }, + "sign": { + "port": 53312 + }, + "channel": { + "port1": 54001, + "port2": 54002, + "port3": 54003, + "port4": 54004 + }, + "entrance": { + "port": 53310, + "entries": [ + { + "name": " Server #1", + "ip": "", + "unk2": 0, + "type": 3, + "season": 3, + "unk6": 0, + "allowedclientflags": "4096", + "channels": [ + { + "port": 54001, + "MaxPlayers": 100, + "CurrentPlayers": 0, + "Unk4": 0, + "Unk5": 0, + "Unk6": 0, + "Unk7": 0, + "Unk8": 0, + "Unk9": 0, + "Unk10": 319, + "Unk11": 248, + "Unk12": 159, + "Unk13": 12345 + } + ] + }, + { + "name": " Server #2", + "ip": "", + "unk2": 0, + "type": 1, + "season": 3, + "unk6": 0, + "allowedclientflags": 0, + "channels": [ + { + "port": 54002, + "MaxPlayers": 50, + "CurrentPlayers": 0, + "Unk4": 0, + "Unk5": 0, + "Unk6": 0, + "Unk7": 0, + "Unk8": 0, + "Unk9": 0, + "Unk10": 318, + "Unk11": 251, + "Unk12": 155, + "Unk13": 12345 + } + ] + }, + { + "name": " Server #3", + "ip": "", + "unk2": 0, + "type": 2, + "season": 1, + "unk6": 0, + "allowedclientflags": 0, + "channels": [ + { + "port": 54003, + "MaxPlayers": 50, + "CurrentPlayers": 0, + "Unk4": 0, + "Unk5": 0, + "Unk6": 0, + "Unk7": 0, + "Unk8": 0, + "Unk9": 0, + "Unk10": 318, + "Unk11": 251, + "Unk12": 155, + "Unk13": 12345 + } + ] + }, + { + "name": " Server #4", + "ip": "", + "unk2": 0, + "type": 4, + "season": 0, + "unk6": 0, + "allowedclientflags": 0, + "channels": [ + { + "port": 54004, + "MaxPlayers": 50, + "CurrentPlayers": 0, + "Unk4": 0, + "Unk5": 0, + "Unk6": 0, + "Unk7": 0, + "Unk8": 0, + "Unk9": 0, + "Unk10": 318, + "Unk11": 251, + "Unk12": 155, + "Unk13": 12345 + } + ] + + } + ] + } +} \ No newline at end of file diff --git a/Erupe/config/config.go b/Erupe/config/config.go new file mode 100644 index 000000000..9b6d65165 --- /dev/null +++ b/Erupe/config/config.go @@ -0,0 +1,157 @@ +package config + +import ( + "log" + "net" + + "github.com/spf13/viper" +) + +// Config holds the global server-wide config. +type Config struct { + HostIP string `mapstructure:"host_ip"` + BinPath string `mapstructure:"bin_path"` + DevMode bool + + DevModeOptions DevModeOptions + Discord Discord + Database Database + Launcher Launcher + Sign Sign + Channel Channel + Entrance Entrance +} + +// DevModeOptions holds various debug/temporary options for use while developing Erupe. +type DevModeOptions struct { + ServerName string // To get specific instance server about (Current Players/Event Week) + CleanDB bool // Automatically wipes the DB on server reset. + MaxLauncherHR bool // Sets the HR returned in the launcher to HR9 so that you can join non-beginner worlds. + FixedStageID bool // Causes all move_stage to use the ID sl1Ns200p0a0u0 to get you into all stages + LogOutboundMessages bool // Log all messages sent to the clients + Event int // Changes the current event + OpcodeMessages bool // Get all message for Opcodes + SaveDumps SaveDumpOptions +} + +type SaveDumpOptions struct { + Enabled bool + OutputDir string +} + +// Discord holds the discord integration config. +type Discord struct { + Enabled bool + BotToken string + ChannelID string +} + +// Database holds the postgres database config. +type Database struct { + Host string + Port int + User string + Password string + Database string +} + +// Launcher holds the launcher server config. +type Launcher struct { + Port int + UseOriginalLauncherFiles bool +} + +// Sign holds the sign server config. +type Sign struct { + Port int +} + +// Channel holds the channel server config. +type Channel struct { + Port1 int + Port2 int + Port3 int + Port4 int +} + +// Entrance holds the entrance server config. +type Entrance struct { + Port uint16 + Entries []EntranceServerInfo +} + +// EntranceServerInfo represents an entry in the serverlist. +type EntranceServerInfo struct { + IP string + Unk2 uint16 + Type uint8 // Server type. 0=?, 1=open, 2=cities, 3=newbie, 4=bar + Season uint8 // Server activity. 0 = green, 1 = orange, 2 = blue + Unk6 uint8 // Something to do with server recommendation on 0, 3, and 5. + Name string // Server name, 66 byte null terminated Shift-JIS(JP) or Big5(TW). + + // 4096(PC, PS3/PS4)?, 8258(PC, PS3/PS4)?, 8192 == nothing? + // THIS ONLY EXISTS IF Binary8Header.type == "SV2", NOT "SVR"! + AllowedClientFlags uint32 + + Channels []EntranceChannelInfo +} + +// EntranceChannelInfo represents an entry in a server's channel list. +type EntranceChannelInfo struct { + Port uint16 + MaxPlayers uint16 + CurrentPlayers uint16 + Unk4 uint16 + Unk5 uint16 + Unk6 uint16 + Unk7 uint16 + Unk8 uint16 + Unk9 uint16 + Unk10 uint16 + Unk11 uint16 + Unk12 uint16 + Unk13 uint16 +} + +// getOutboundIP4 gets the preferred outbound ip4 of this machine +// From https://stackoverflow.com/a/37382208 +func getOutboundIP4() net.IP { + conn, err := net.Dial("udp4", "8.8.8.8:80") + if err != nil { + log.Fatal(err) + } + defer conn.Close() + + localAddr := conn.LocalAddr().(*net.UDPAddr) + + return localAddr.IP.To4() +} + +// LoadConfig loads the given config toml file. +func LoadConfig() (*Config, error) { + viper.SetConfigName("config") + viper.AddConfigPath(".") + + viper.SetDefault("DevModeOptions.SaveDumps", SaveDumpOptions{ + Enabled: false, + OutputDir: "savedata", + }) + + err := viper.ReadInConfig() + if err != nil { + return nil, err + } + + c := &Config{} + err = viper.Unmarshal(c) + if err != nil { + return nil, err + } + + if c.HostIP == "" { + c.HostIP = getOutboundIP4().To4().String() + } + + return c, nil +} + diff --git a/Erupe/go.mod b/Erupe/go.mod new file mode 100644 index 000000000..18078b755 --- /dev/null +++ b/Erupe/go.mod @@ -0,0 +1,75 @@ +module github.com/Solenataris/Erupe + +go 1.16 + +require ( + cloud.google.com/go v0.98.0 // indirect + cloud.google.com/go/spanner v1.27.0 // indirect + cloud.google.com/go/storage v1.18.2 // indirect + github.com/Andoryuuta/byteframe v0.0.0-20200114030334-8979c5cc4c4a + github.com/Azure/go-autorest/autorest/adal v0.9.17 // indirect + github.com/ClickHouse/clickhouse-go v1.5.1 // indirect + github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 // indirect + github.com/aws/aws-sdk-go v1.42.19 // indirect + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.4 // indirect + github.com/bwmarrin/discordgo v0.23.2 + github.com/cenkalti/backoff/v4 v4.1.2 // indirect + github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 // indirect + github.com/cockroachdb/cockroach-go/v2 v2.2.4 // indirect + github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect + github.com/denisenkom/go-mssqldb v0.11.0 // indirect + github.com/envoyproxy/go-control-plane v0.10.1 // indirect + github.com/envoyproxy/protoc-gen-validate v0.6.2 // indirect + github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/go-stack/stack v1.8.1 // indirect + github.com/gocql/gocql v0.0.0-20211015133455-b225f9b53fa1 // indirect + github.com/golang-jwt/jwt/v4 v4.2.0 // indirect + github.com/golang-migrate/migrate/v4 v4.15.1 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/mock v1.6.0 // indirect + github.com/google/go-github/v35 v35.3.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/gorilla/handlers v1.5.1 + github.com/gorilla/mux v1.8.0 + github.com/gorilla/websocket v1.4.2 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-retryablehttp v0.7.0 // indirect + github.com/jackc/pgx/v4 v4.14.1 // indirect + github.com/jmoiron/sqlx v1.3.4 + github.com/k0kubun/pp v3.0.1+incompatible // indirect + github.com/ktrysmt/go-bitbucket v0.9.32 // indirect + github.com/lib/pq v1.10.4 + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect + github.com/mitchellh/mapstructure v1.4.3 // indirect + github.com/mutecomm/go-sqlcipher/v4 v4.4.2 // indirect + github.com/nakagami/firebirdsql v0.9.3 // indirect + github.com/neo4j/neo4j-go-driver v1.8.3 // indirect + github.com/pierrec/lz4/v4 v4.1.12 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/sachaos/lottery v0.0.0-20180520074626-61949d99bd96 + github.com/shopspring/decimal v1.3.1 // indirect + github.com/snowflakedb/gosnowflake v1.6.4 // indirect + github.com/spf13/viper v1.8.1 + github.com/xanzy/go-gitlab v0.52.2 // indirect + github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect + go.mongodb.org/mongo-driver v1.8.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.7.0 // indirect + go.uber.org/zap v1.18.1 + golang.org/x/crypto v0.0.0-20211202192323-5770296d904e + golang.org/x/net v0.0.0-20211205041911-012df41ee64c // indirect + golang.org/x/sys v0.0.0-20211205182925-97ca703d548d // indirect + golang.org/x/text v0.3.7 + golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 // indirect + golang.org/x/tools v0.1.8 // indirect + google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0 // indirect + google.golang.org/grpc v1.42.0 // indirect + modernc.org/ccgo/v3 v3.12.86 // indirect + modernc.org/ql v1.4.0 // indirect + modernc.org/sqlite v1.14.2 // indirect +) diff --git a/Erupe/go.sum b/Erupe/go.sum new file mode 100644 index 000000000..989bf53f5 --- /dev/null +++ b/Erupe/go.sum @@ -0,0 +1,1972 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.88.0/go.mod h1:dnKwfYbP9hQhefiUvpbcAyoGSHUrOxR20JVElLiUvEY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.98.0 h1:w6LozQJyDDEyhf64Uusu1LCcnLt0I1VMLiJC2kV+eXk= +cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/spanner v1.24.0/go.mod h1:EZI0yH1D/PrXK0XH9Ba5LGXTXWeqZv0ClOD/19a0Z58= +cloud.google.com/go/spanner v1.27.0 h1:F5CmUC0pc83kigWjG3YfXfV02+ip3G394jLYzbDtoEQ= +cloud.google.com/go/spanner v1.27.0/go.mod h1:/YWC/deZAtNGNmUXUJBjzcprotUO8q0q0AwPISFncwg= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.18.2 h1:5NQw6tOn3eMm0oE8vTkfjau18kjL79FlMjy/CHTpmoY= +cloud.google.com/go/storage v1.18.2/go.mod h1:AiIj7BWXyhO5gGVmYJ+S8tbkCx3yb0IMjua8Aw4naVM= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= +github.com/Andoryuuta/byteframe v0.0.0-20200114030334-8979c5cc4c4a h1:41dzqxDfdVhYjpkr8lxwrBdJe0RE/AXsGV1AGpP6wig= +github.com/Andoryuuta/byteframe v0.0.0-20200114030334-8979c5cc4c4a/go.mod h1:koVyx+gN3TfE70rpOidywETVODk87304YpwW69Y27J4= +github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= +github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-storage-blob-go v0.14.0 h1:1BCg74AmVdYwO3dlKwtFU1V0wU2PZdREkXvAmZJRUlM= +github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.1 h1:eVvIXUKiTgv++6YnWb42DUA1YL7qDugnKP0HljexdnQ= +github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.17 h1:esOPl2dhcz9P3jqBSJ8tPGEj2EqzPPT6zfyuloiogKY= +github.com/Azure/go-autorest/autorest/adal v0.9.17/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= +github.com/ClickHouse/clickhouse-go v1.5.1 h1:I8zVFZTz80crCs0FFEBJooIxsPcV0xfthzK1YrkpJTc= +github.com/ClickHouse/clickhouse-go v1.5.1/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= +github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= +github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn69iY6URG00= +github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= +github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= +github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= +github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/arrow/go/arrow v0.0.0-20210818145353-234c94e4ce64/go.mod h1:2qMFB56yOP3KzkB3PbYZ4AlUFg3a88F67TIx5lB/WwY= +github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= +github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40 h1:q4dksr6ICHXqG5hm0ZW5IHyeEJXoIJSOZeBLmWPNeIQ= +github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.42.19 h1:L/aM1QwsqVia9qIqexTHwYN+lgLYuOtf11VDgz0YIyw= +github.com/aws/aws-sdk-go v1.42.19/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0= +github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= +github.com/aws/aws-sdk-go-v2 v1.11.2 h1:SDiCYqxdIYi6HgQfAWRhgdZrdnOuGyLDJVRSWLeHWvs= +github.com/aws/aws-sdk-go-v2 v1.11.2/go.mod h1:SQfA+m2ltnu1cA0soUkj4dRSsmITiVQUJvBIZjzfPyQ= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0 h1:yVUAwvJC/0WNPbyl0nA3j1L6CW1CN8wBubCRqtG7JLI= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.0.0/go.mod h1:Xn6sxgRuIDflLRJFj5Ev7UxABIkNbccFPV/p8itDReM= +github.com/aws/aws-sdk-go-v2/config v1.6.0/go.mod h1:TNtBVmka80lRPk5+S9ZqVfFszOQAGJJ9KbT3EM3CHNU= +github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw= +github.com/aws/aws-sdk-go-v2/config v1.11.0/go.mod h1:VrQDJGFBM5yZe+IOeenNZ/DWoErdny+k2MHEIpwDsEY= +github.com/aws/aws-sdk-go-v2/credentials v1.3.2/go.mod h1:PACKuTJdt6AlXvEq8rFI4eDmoqDFC5DpVKQbWysaDgM= +github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ= +github.com/aws/aws-sdk-go-v2/credentials v1.6.4 h1:2hvbUoHufns0lDIsaK8FVCMukT1WngtZPavN+W2FkSw= +github.com/aws/aws-sdk-go-v2/credentials v1.6.4/go.mod h1:tTrhvBPHyPde4pdIPSba4Nv7RYr4wP9jxXEDa1bKn/8= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.4.0/go.mod h1:Mj/U8OpDbcVcoctrYwA2bak8k/HFPdcLzI/vaiXMwuM= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.8.2/go.mod h1:dF2F6tXEOgmW5X1ZFO/EPtWrcm7XkW07KNcJUGNtt4s= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.4.0/go.mod h1:eHwXu2+uE/T6gpnYWwBwqoeqRf9IXyCcolyOWDRAErQ= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.5.4/go.mod h1:Ex7XQmbFmgFHrjUX6TN3mApKW5Hglyga+F7wZHTtYhA= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.4 h1:P8dY1eHwdKQtMLTSn4Lg0A+vEHTqBnTkYxgy5kzK4Y0= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.7.4/go.mod h1:FqSlw++zBunV8Kt5rPETKxIPGO8axbW4L8v25oql7ok= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2 h1:XJLnluKuUxQG255zPNe+04izXl7GSyUVafIsgfv9aw4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.2/go.mod h1:SgKKNBIoDC/E1ZCDhhMW3yalWjwuLjMcpLzsM/QQnWo= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2 h1:EauRoYZVNPlidZSZJDscjJBQ22JhVF2+tdteatax2Ak= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.0.2/go.mod h1:xT4XX6w5Sa3dhg50JrYyy3e4WPYo/+WjY/BXtqXVunU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.2.0/go.mod h1:Q5jATQc+f1MfZp3PDMhn6ry18hGvE0i8yvbXoKbnZaE= +github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.2/go.mod h1:VITe/MdW6EMXPb0o0txu/fsonXbMHUU2OC2Qp7ivU4o= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.2.2/go.mod h1:EASdTcM1lGhUe1/p4gkojHwlGJkeoRjjr1sRCzup3Is= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.3.0/go.mod h1:v8ygadNyATSm6elwJ/4gzJwcFhri9RqS8skgHKiwXPU= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0 h1:lPLbw4Gn59uoKqvOfSnkJr54XWk5Ak1NK20ZEiSWb3U= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.5.0/go.mod h1:80NaCIH9YU3rzTTs/J/ECATjXuRqzo/wB6ukO6MZ0XY= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.2/go.mod h1:NXmNI41bdEsJMrD0v9rUvbGCB5GwdBEpKvUvIY3vTFg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2 h1:CKdUNKmuilw/KNmO2Q53Av8u+ZyXMC2M9aX8Z+c/gzg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.5.2/go.mod h1:FgR1tCsn8C6+Hf+N5qkfrE4IXvUL1RgW87sunJ+5J4I= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.5.2/go.mod h1:QuL2Ym8BkrLmN4lUofXYq6000/i5jPjosCNK//t6gak= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.7.2/go.mod h1:np7TMuJNT83O0oDOSF8i4dF3dvGqA6hPYYo6YYkzgRA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.2 h1:GnPGH1FGc4fkn0Jbm/8r2+nPOwSJjYPyHSqFSvY1ii8= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.9.2/go.mod h1:eDUYjOYt4Uio7xfHi5jOsO393ZG8TSfZB92a3ZNadWM= +github.com/aws/aws-sdk-go-v2/service/s3 v1.12.0/go.mod h1:6J++A5xpo7QDsIeSqPK4UHqMSyPOCopa+zKtqAMhqVQ= +github.com/aws/aws-sdk-go-v2/service/s3 v1.16.1/go.mod h1:CQe/KvWV1AqRc65KqeJjrLzr5X2ijnFTTVzJW0VBRCI= +github.com/aws/aws-sdk-go-v2/service/s3 v1.21.0 h1:vUM2P60BI755i35Gyik4s/lXKcnpEbnvw2Vud+soqpI= +github.com/aws/aws-sdk-go-v2/service/s3 v1.21.0/go.mod h1:lQ5AeEW2XWzu8hwQ3dCqZFWORQ3RntO0Kq135Xd9VCo= +github.com/aws/aws-sdk-go-v2/service/sso v1.3.2/go.mod h1:J21I6kF+d/6XHVk7kp/cx9YVD2TMD2TbLwtRGVcinXo= +github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk= +github.com/aws/aws-sdk-go-v2/service/sso v1.6.2/go.mod h1:KnIpszaIdwI33tmc/W/GGXyn22c1USYxA/2KyvoeDY0= +github.com/aws/aws-sdk-go-v2/service/sts v1.6.1/go.mod h1:hLZ/AnkIKHLuPGjEiyghNEdvJ2PP0MgOxcmv9EBJ4xs= +github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g= +github.com/aws/aws-sdk-go-v2/service/sts v1.11.1/go.mod h1:UV2N5HaPfdbDpkgkz4sRzWCvQswZjdO1FfqCWl0t7RA= +github.com/aws/smithy-go v1.7.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.9.0 h1:c7FUdEqrQA1/UVKKCNDFQPNKGp4FQg3YW4Ck5SLTG58= +github.com/aws/smithy-go v1.9.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/bwmarrin/discordgo v0.23.2 h1:BzrtTktixGHIu9Tt7dEE6diysEF9HWnXeHuoJEt2fH4= +github.com/bwmarrin/discordgo v0.23.2/go.mod h1:c1WtWUGN6nREDmzIpyTp/iD3VYt4Fpx+bVyfBG7JE+M= +github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= +github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= +github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk= +github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg= +github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 h1:hzAQntlaYRkVSFEfj9OTWlVV1H155FMD8BTKktLv0QI= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490 h1:KwaoQzs/WeUxxJqiJsZ4euOly1Az/IgZXXSxlD/UBNk= +github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/cockroach-go/v2 v2.1.1/go.mod h1:7NtUnP6eK+l6k483WSYNrq3Kb23bWV10IRV1TyeSpwM= +github.com/cockroachdb/cockroach-go/v2 v2.2.4 h1:VuiBJKut2Imgrzl+TNk+U5+GxLOh3hnIFxU0EzjTCnI= +github.com/cockroachdb/cockroach-go/v2 v2.2.4/go.mod h1:u3MiKYGupPPjkn3ozknpMUpxPaNLTFWAya419/zv6eI= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= +github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= +github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/aufs v1.0.0/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= +github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= +github.com/containerd/btrfs v0.0.0-20210316141732-918d888fb676/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/btrfs v1.0.0/go.mod h1:zMcX3qkXTAi9GI50+0HOeuV8LU2ryCE/V2vG/ZBiTss= +github.com/containerd/cgroups v0.0.0-20190717030353-c4b9ac5c7601/go.mod h1:X9rLEHIqSf/wfK8NsPqxJmeZgW4pcfzdXITDrUSJ6uI= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= +github.com/containerd/cgroups v0.0.0-20210114181951-8a68de567b68/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= +github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/containerd v1.2.10/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.1-0.20191213020239-082f7e3aed57/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.0-beta.2.0.20200729163537-40b22ef07410/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.5.0-beta.1/go.mod h1:5HfvG1V2FsKesEGQ17k5/T7V960Tmcumvqn8Mc+pCYQ= +github.com/containerd/containerd v1.5.0-beta.3/go.mod h1:/wr9AVtEM7x9c+n0+stptlo/uBBoBORwEx6ardVcmKU= +github.com/containerd/containerd v1.5.0-beta.4/go.mod h1:GmdgZd2zA2GYIBZ0w09ZvgqEq8EfBp/m3lcVZIvPHhI= +github.com/containerd/containerd v1.5.0-rc.0/go.mod h1:V/IXoMqNGgBlabz3tHD2TWDoTJseu1FGOKuoA4nNb2s= +github.com/containerd/containerd v1.5.1/go.mod h1:0DOxVqwDy2iZvrZp2JUx/E+hS0UNTVn7dJnIOwtYR4g= +github.com/containerd/containerd v1.5.7/go.mod h1:gyvv6+ugqY25TiXxcZC3L5yOeYgEw0QMhscqVp1AR9c= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20190815185530-f2a389ac0a02/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/continuity v0.0.0-20210208174643-50096c924a4e/go.mod h1:EXlVlkqNba9rJe3j7w3Xa924itAMLgZH4UD/Q4PExuQ= +github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= +github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20201026212402-0724c46b320c/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= +github.com/containerd/fifo v0.0.0-20210316144830-115abcc95a1d/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= +github.com/containerd/go-cni v1.0.1/go.mod h1:+vUpYxKvAF72G9i1WoDOiPGRtQpqsNW/ZHtSlv++smU= +github.com/containerd/go-cni v1.0.2/go.mod h1:nrNABBHzu0ZwCug9Ije8hL2xBCYh/pjfMb1aZGrrohk= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20190911050354-e029b79d8cda/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/go-runc v0.0.0-20200220073739-7016d3ce2328/go.mod h1:PpyHrqVs8FTi9vpyHwPwiNEGaACDxT/N/pLcvMSRA9g= +github.com/containerd/go-runc v0.0.0-20201020171139-16b287bc67d0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= +github.com/containerd/imgcrypt v1.0.1/go.mod h1:mdd8cEPW7TPgNG4FpuP3sGBiQ7Yi/zak9TYCG3juvb0= +github.com/containerd/imgcrypt v1.0.4-0.20210301171431-0ae5c75f59ba/go.mod h1:6TNsg0ctmizkrOgXRNQjAPFWpMYRWuiB6dSF4Pfa5SA= +github.com/containerd/imgcrypt v1.1.1-0.20210312161619-7ed62a527887/go.mod h1:5AZJNI6sLHJljKuI9IHnw1pWqo/F0nGDOuR9zgTs7ow= +github.com/containerd/imgcrypt v1.1.1/go.mod h1:xpLnwiQmEUJPvQoAapeb2SNCxz7Xr6PJrXQb0Dpc4ms= +github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFYfE5+So4M5syatU0N0f0LbWpuqyMi4/BE8c= +github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= +github.com/containerd/ttrpc v1.0.1/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/containerd/typeurl v0.0.0-20190911142611-5eb25027c9fd/go.mod h1:GeKYzf2pQcqv7tJ0AoCuuhtnqhva5LNU3U+OyKxxJpk= +github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg= +github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= +github.com/containerd/zfs v0.0.0-20200918131355-0a33824f23a2/go.mod h1:8IgZOBdv8fAgXddBT4dBXJPtxyRsejFIpXoklgxgEjw= +github.com/containerd/zfs v0.0.0-20210301145711-11e8f1707f62/go.mod h1:A9zfAbMlQwE+/is6hi0Xw8ktpL+6glmqZYtevJgaB8Y= +github.com/containerd/zfs v0.0.0-20210315114300-dde8f0fda960/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v0.0.0-20210324211415-d5c4544f0433/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY= +github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.0/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= +github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= +github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= +github.com/containers/ocicrypt v1.0.1/go.mod h1:MeJDzk1RJHv89LjsH0Sp5KTY3ZYkjXO/C+bKAeWFIrc= +github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgUV4GP9qXPfu4= +github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= +github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20161114122254-48702e0da86b/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso= +github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= +github.com/d2g/dhcp4 v0.0.0-20170904100407-a1d1b6c41b1c/go.mod h1:Ct2BUK8SB0YC1SMSibvLzxjeJLnrYEVLULFNiHY9YfQ= +github.com/d2g/dhcp4client v1.0.0/go.mod h1:j0hNfjhrt2SxUOw55nL0ATM/z4Yt3t2Kd1mW34z5W5s= +github.com/d2g/dhcp4server v0.0.0-20181031114812-7d4a0a7f59a5/go.mod h1:Eo87+Kg/IX2hfWJfwxMzLyuSZyxSoAug2nGa1G2QAi8= +github.com/d2g/hardwareaddr v0.0.0-20190221164911-e7d9fbe030e4/go.mod h1:bMl4RjIciD2oAxI7DmWRx6gbeqrkoLqv3MV0vzNad+I= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL/7ND8HI= +github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dhui/dktest v0.3.7/go.mod h1:nYMOkafiA07WchSwKnKFUSbGMb2hMm5DrCGiXYG6gwM= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-events v0.0.0-20170721190031-9461782956ad/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= +github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.1 h1:cgDRLG7bs59Zd+apAWuzLQL95obVYAymNJek76W3mgw= +github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/envoyproxy/protoc-gen-validate v0.6.2 h1:JiO+kJTpmYGjEodY7O1Zk8oZcNz1+f30UtwtXoFUPzE= +github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.5+incompatible h1:/l4kBbb4/vGSsdtB5nUe8L7B9mImVMaBPw9L/0TBHU8= +github.com/form3tech-oss/jwt-go v3.2.5+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsouza/fake-gcs-server v1.17.0/go.mod h1:D1rTE4YCyHFNa99oyJJ5HyclvN/0uQR+pM/VdlL83bw= +github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= +github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= +github.com/gabriel-vasile/mimetype v1.4.0 h1:Cn9dkdYsMIu56tGho+fqzh7XmvY2YyGU0FnbhiOsEro= +github.com/gabriel-vasile/mimetype v1.4.0/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= +github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= +github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= +github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= +github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= +github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= +github.com/gobuffalo/depgen v0.0.0-20190329151759-d478694a28d3/go.mod h1:3STtPUQYuzV0gBVOY3vy6CfMm/ljR4pABfrTeHNLHUY= +github.com/gobuffalo/depgen v0.1.0/go.mod h1:+ifsuy7fhi15RWncXQQKjWS9JPkdah5sZvtHc2RXGlg= +github.com/gobuffalo/envy v1.6.15/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/flect v0.1.0/go.mod h1:d2ehjJqGOH/Kjqcoz+F7jHTBbmDb38yXA598Hb50EGs= +github.com/gobuffalo/flect v0.1.1/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/flect v0.1.3/go.mod h1:8JCgGVbRjJhVgD6399mQr4fx5rRfGKVzFjbj6RE/9UI= +github.com/gobuffalo/genny v0.0.0-20190329151137-27723ad26ef9/go.mod h1:rWs4Z12d1Zbf19rlsn0nurr75KqhYp52EAGGxTbBhNk= +github.com/gobuffalo/genny v0.0.0-20190403191548-3ca520ef0d9e/go.mod h1:80lIj3kVJWwOrXWWMRzzdhW3DsrdjILVil/SFKBzF28= +github.com/gobuffalo/genny v0.1.0/go.mod h1:XidbUqzak3lHdS//TPu2OgiFB+51Ur5f7CSnXZ/JDvo= +github.com/gobuffalo/genny v0.1.1/go.mod h1:5TExbEyY48pfunL4QSXxlDOmdsD44RRq4mVZ0Ex28Xk= +github.com/gobuffalo/gitgen v0.0.0-20190315122116-cc086187d211/go.mod h1:vEHJk/E9DmhejeLeNt7UVvlSGv3ziL+djtTr3yyzcOw= +github.com/gobuffalo/gogen v0.0.0-20190315121717-8f38393713f5/go.mod h1:V9QVDIxsgKNZs6L2IYiGR8datgMhB577vzTDqypH360= +github.com/gobuffalo/gogen v0.1.0/go.mod h1:8NTelM5qd8RZ15VjQTFkAW6qOMx5wBbW4dSCS3BY8gg= +github.com/gobuffalo/gogen v0.1.1/go.mod h1:y8iBtmHmGc4qa3urIyo1shvOD8JftTtfcKi+71xfDNE= +github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= +github.com/gobuffalo/logger v0.0.0-20190315122211-86e12af44bc2/go.mod h1:QdxcLw541hSGtBnhUc4gaNIXRjiDppFGaDqzbrBd3v8= +github.com/gobuffalo/mapi v1.0.1/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/mapi v1.0.2/go.mod h1:4VAGh89y6rVOvm5A8fKFxYG+wIW6LO1FMTG9hnKStFc= +github.com/gobuffalo/packd v0.0.0-20190315124812-a385830c7fc0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWeG2RIxq4= +github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= +github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= +github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= +github.com/gocql/gocql v0.0.0-20210515062232-b7ef815b4556/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= +github.com/gocql/gocql v0.0.0-20211015133455-b225f9b53fa1 h1:px9qUCy/RNJNsfCam4m2IxWGxNuimkrioEF0vrrbPsg= +github.com/gocql/gocql v0.0.0-20211015133455-b225f9b53fa1/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8= +github.com/godbus/dbus v0.0.0-20151105175453-c7fdd8b5cd55/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= +github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-migrate/migrate/v4 v4.15.1 h1:Sakl3Nm6+wQKq0Q62tpFMi5a503bgGhceo2icrgQ9vM= +github.com/golang-migrate/migrate/v4 v4.15.1/go.mod h1:/CrBenUbcDqsW29jGTR/XFqCfVi/Y6mHXlooCcSOJMQ= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/flatbuffers v2.0.0+incompatible h1:dicJ2oXwypfwUGnB2/TYWYEKiuk9eYQlQO/AnOHl5mI= +github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-github/v35 v35.2.0/go.mod h1:s0515YVTI+IMrDoy9Y4pHt9ShGpzHvHO8rZ7L7acgvs= +github.com/google/go-github/v35 v35.3.0 h1:fU+WBzuukn0VssbayTT+Zo3/ESKX9JYWjbZTLOTEyho= +github.com/google/go-github/v35 v35.3.0/go.mod h1:yWB7uCcVWaUbUP74Aq3whuMySRMatyRmq5U9FTNlbio= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210715191844-86eeefc3e471/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1 h1:dp3bWCh+PPO1zjRRiCSczJav13sBvG4UhNyVTa1KqdU= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= +github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4= +github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6tORTn+6F6j+Jc8TOr5osrynvN6ivFWZ2GA= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= +github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= +github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= +github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= +github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= +github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgconn v1.10.1 h1:DzdIHIjG1AxGwoEEqS+mGsURyjt4enSmqzACXvVzOT8= +github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= +github.com/jackc/pgerrcode v0.0.0-20201024163028-a0d42d470451 h1:WAvSpGf7MsFuzAtK4Vk7R4EVe+liW4x83r4oWu0WHKw= +github.com/jackc/pgerrcode v0.0.0-20201024163028-a0d42d470451/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= +github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.0.7/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= +github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= +github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= +github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= +github.com/jackc/pgtype v1.6.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig= +github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= +github.com/jackc/pgtype v1.9.1 h1:MJc2s0MFS8C3ok1wQTdQxWuXQcB6+HwAm5x1CzW7mf0= +github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= +github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= +github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= +github.com/jackc/pgx/v4 v4.10.1/go.mod h1:QlrWebbs3kqEZPHCTGyxecvzG6tvIsYu+A5b1raylkA= +github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= +github.com/jackc/pgx/v4 v4.14.1 h1:71oo1KAGI6mXhLiTMn6iDFcp3e7+zon/capWjl2OEFU= +github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= +github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= +github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= +github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= +github.com/k0kubun/pp v2.3.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= +github.com/k0kubun/pp v3.0.1+incompatible h1:3tqvf7QgUnZ5tXO6pNAZlrvHgl6DvifjDrd9g2S9Z40= +github.com/k0kubun/pp v3.0.1+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4= +github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= +github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.9.5/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.1/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4= +github.com/ktrysmt/go-bitbucket v0.9.32 h1:IVk0m0gdB4OzRRLgxFnqNsfWKPXNdrcvgdpp9BojTpI= +github.com/ktrysmt/go-bitbucket v0.9.32/go.mod h1:FWxy2UK7GlK5b0NSJGc5hPqnssVlkNnsChvyuOf/Xno= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= +github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= +github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-ieproxy v0.0.1 h1:qiyop7gCflfhwCzGyeT0gro3sF9AIg9HU98JORTkqfI= +github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/gNWuh88E= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-shellwords v1.0.3/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o= +github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= +github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= +github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= +github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= +github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mutecomm/go-sqlcipher/v4 v4.4.0/go.mod h1:PyN04SaWalavxRGH9E8ZftG6Ju7rsPrGmQRjrEaVpiY= +github.com/mutecomm/go-sqlcipher/v4 v4.4.2 h1:eM10bFtI4UvibIsKr10/QT7Yfz+NADfjZYh0GKrXUNc= +github.com/mutecomm/go-sqlcipher/v4 v4.4.2/go.mod h1:mF2UmIpBnzFeBdu/ypTDb/LdbS0nk0dfSN1WUsWTjMA= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA= +github.com/nakagami/firebirdsql v0.9.3 h1:/uNYufsFSRZF6n1xqzQxXY6b2TRD8o4aiPlb+qYGQH8= +github.com/nakagami/firebirdsql v0.9.3/go.mod h1:yU71hYllTfU4JbEysWLY2XovxsFnaLWkraaegJ7GW3M= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/neo4j/neo4j-go-driver v1.8.1-0.20200803113522-b626aa943eba/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI= +github.com/neo4j/neo4j-go-driver v1.8.3 h1:yfuo9YBAlezdIiogu92GwEir/81RD81dNwS5mY/wAIk= +github.com/neo4j/neo4j-go-driver v1.8.3/go.mod h1:ncO5VaFWh0Nrt+4KT4mOZboaczBZcLuHrG+/sUeP8gI= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v0.0.0-20151202141238-7f8ab55aaf3b/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= +github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.0-rc93/go.mod h1:3NOsor4w32B2tC0Zbl8Knk4Wg84SM2ImC1fxBuqJ/H0= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2-0.20190207185410-29686dbc5559/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20200929063507-e6143ca7d51d/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= +github.com/opencontainers/selinux v1.6.0/go.mod h1:VVGKuOLlE7v4PJyT6h7mNWvq1rzqiriPsEqVhc+svHE= +github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3ogry1nUQF8Evvo= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2dXMnm1mY= +github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.12 h1:44l88ehTZAUGW4VlO1QC4zkilL99M6Y9MXNwEs0uzP8= +github.com/pierrec/lz4/v4 v4.1.12/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sachaos/lottery v0.0.0-20180520074626-61949d99bd96 h1:BanNeULiV7hOXjHPUQt3tgF6qVHGZ0uLMnCr0WZ5CTk= +github.com/sachaos/lottery v0.0.0-20180520074626-61949d99bd96/go.mod h1:NuxNqEW5jNyYkZ5WSBB70WQXtRKY1jUPMzX74wr5JFo= +github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/snowflakedb/gosnowflake v1.6.3/go.mod h1:6hLajn6yxuJ4xUHZegMekpq9rnQbGJ7TMwXjgTmA6lg= +github.com/snowflakedb/gosnowflake v1.6.4 h1:yZSk/85ReT7iEOkkbFdlMCH/mQ16nU2+QgJe8aBaXRg= +github.com/snowflakedb/gosnowflake v1.6.4/go.mod h1:6hLajn6yxuJ4xUHZegMekpq9rnQbGJ7TMwXjgTmA6lg= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= +github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= +github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= +github.com/stretchr/objx v0.0.0-20180129172003-8a3f7159479f/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v0.0.0-20180303142811-b89eecf5ca5d/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= +github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= +github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= +github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= +github.com/xanzy/go-gitlab v0.52.2 h1:gkgg1z4ON70sphibtD86Bfmt1qV3mZ0pU0CBBCFAEvQ= +github.com/xanzy/go-gitlab v0.52.2/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKqXVQrUoAE= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.0.2 h1:akYIkZ28e6A96dkWNJQu3nmCzH3YfwMPQExUYDaRv7w= +github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= +github.com/xdg-go/stringprep v1.0.2 h1:6iq84/ryjjeRmMJwxutI51F2GIPlP5BfTvXHeYjyhBc= +github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= +github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b h1:7gd+rd8P3bqcn/96gOZa3F5dpJr/vEiDQYlNb/y2uNs= +gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.mongodb.org/mongo-driver v1.7.0/go.mod h1:Q4oFMbo1+MSNqICAdYMlC/zSTrwCogR4R8NzkI+yfU8= +go.mongodb.org/mongo-driver v1.8.0 h1:R/P/JJzu8LJvJ1lDfph9GLNIKQxEtIHFfnUUUve35zY= +go.mongodb.org/mongo-driver v1.8.0/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY= +go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8= +golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20181106170214-d68db9428509/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20201208152932-35266b937fa6/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210216034530-4410531fe030/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38= +golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190225153610-fe579d43d832/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211013171255-e13a2654a71e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211205041911-012df41ee64c h1:7SfqwP5fxEtl/P02w5IhKc86ziJ+A25yFrkVgoy2FT8= +golang.org/x/net v0.0.0-20211205041911-012df41ee64c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190812073006-9eafafc0a87e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200922070232-aee5d888a860/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201117170446-d9b008d0a637/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210304124612-50617c2ba197/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210818153620-00dd8d7831e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= +golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M= +golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190329151228-23e29df326fe/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190416151739-9c9e1878f421/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w= +golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= +gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= +gonum.org/v1/gonum v0.9.3/go.mod h1:TZumC3NeyVQskjXqmyWt4S3bINhy7B4eYwW69EbyX+0= +gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= +gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +gonum.org/v1/plot v0.9.0/go.mod h1:3Pcqqmp6RHvJI72kgb8fThyUnav364FOsdDo2aGW5lY= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.58.0/go.mod h1:cAbP2FsxoGVNwtgNAmmn3y5G1TWAiVYRmg4yku3lv+E= +google.golang.org/api v0.61.0 h1:TXXKS1slM3b2bZNJwD5DV/Tp6/M2cLzLOLh9PjDhrw8= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190522204451-c2c4e71fbf69/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210630183607-d20f26d13c79/go.mod h1:yiaVoXHpRzHGyxV3o4DktVWY4mSUErTKaeEOq6C3t3U= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210721163202-f1cecdd8b78a/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210726143408-b02e89920bf0/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211016002631-37fc39342514/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211019152133-63b7e35f4404/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0 h1:c7yRRmuQiVMo+YppNj5MUREXUyc2lPo3DrtYMwaWQ28= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/postgres v1.0.8/go.mod h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5dxcAg= +gorm.io/gorm v1.20.12/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= +gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= +gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= +k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= +k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8= +k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc= +k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= +k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM= +k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q= +k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= +k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= +k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0= +k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= +k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= +k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM= +k8s.io/cri-api v0.17.3/go.mod h1:X1sbHmuXhwaHs9xxYffLqJogVsnI+f6cPRcgPel7ywM= +k8s.io/cri-api v0.20.1/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.4/go.mod h1:2JRbKt+BFLTjtrILYVqQK5jqhI+XNdF6UiGMgczeBCI= +k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +lukechampine.com/uint128 v1.1.1 h1:pnxCASz787iMf+02ssImqk6OLt+Z5QHMoZyUXR4z6JU= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg= +modernc.org/b v1.0.2 h1:iPC2u39ebzq12GOC2yXT4mve0HrWcH85cz+midWjzeo= +modernc.org/b v1.0.2/go.mod h1:fVGfCIzkZw5RsuF2A2WHbJmY7FiMIq30nP4s52uWsoY= +modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878= +modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.18 h1:rMZhRcWrba0y3nVmdiQ7kxAgOOSq2m2f2VzjHLgEs6U= +modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo= +modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60= +modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw= +modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI= +modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag= +modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw= +modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ= +modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c= +modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo= +modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg= +modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I= +modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs= +modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8= +modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE= +modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk= +modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w= +modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE= +modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8= +modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc= +modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU= +modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE= +modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk= +modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI= +modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE= +modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg= +modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74= +modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU= +modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU= +modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc= +modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM= +modernc.org/ccgo/v3 v3.12.65/go.mod h1:D6hQtKxPNZiY6wDBtehSGKFKmyXn53F8nGTpH+POmS4= +modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ= +modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84= +modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ= +modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY= +modernc.org/ccgo/v3 v3.12.82/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w= +modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w= +modernc.org/ccgo/v3 v3.12.86 h1:zN0MkWIf1a2SgP6w9V3EG5r30CSrpRunyzJ5wcYRLFM= +modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU= +modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/db v1.0.0/go.mod h1:kYD/cO29L/29RM0hXYl4i3+Q5VojL31kTUVpVJDw0s8= +modernc.org/db v1.0.3 h1:apxOlWU69je04bY22OT6J0RL23mzvUy22EgTAVyw+Yg= +modernc.org/db v1.0.3/go.mod h1:L4ltUg8tu2pkSJk+fKaRrXs/3EdW79ZKYQ5PfVDT53U= +modernc.org/file v1.0.0/go.mod h1:uqEokAEn1u6e+J45e54dsEA/pw4o7zLrA2GwyntZzjw= +modernc.org/file v1.0.3 h1:McYGAMMuqjRp6ptmpcLr3r5yw3gNPsonFCAJ0tNK74U= +modernc.org/file v1.0.3/go.mod h1:CNj/pwOfCtCbqiHcXDUlHBB2vWrzdaDCWdcnjtS1+XY= +modernc.org/fileutil v1.0.0 h1:Z1AFLZwl6BO8A5NldQg/xTSjGLetp+1Ubvl4alfGx8w= +modernc.org/fileutil v1.0.0/go.mod h1:JHsWpkrk/CnVV1H/eGlFf85BEpfkrp56ro8nojIq9Q8= +modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= +modernc.org/golex v1.0.1 h1:EYKY1a3wStt0RzHaH8mdSRNg78Ub0OHxYfCRWw35YtM= +modernc.org/golex v1.0.1/go.mod h1:QCA53QtsT1NdGkaZZkF5ezFwk4IXh4BGNafAARTC254= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/internal v1.0.0/go.mod h1:VUD/+JAkhCpvkUitlEOnhpVxCgsBI90oTzSCRcqQVSM= +modernc.org/internal v1.0.2 h1:Sn3+ojjMRnPaOR6jFISs6KAdRHnR4q9KNuwfKINKmZA= +modernc.org/internal v1.0.2/go.mod h1:bycJAcev709ZU/47nil584PeBD+kbu8nv61ozeMso9E= +modernc.org/lex v1.0.0/go.mod h1:G6rxMTy3cH2iA0iXL/HRRv4Znu8MK4higxph/lE7ypk= +modernc.org/lexer v1.0.0/go.mod h1:F/Dld0YKYdZCLQ7bD0USbWL4YKCyTDRDHiDTOs0q0vk= +modernc.org/libc v1.7.13-0.20210308123627-12f642a52bb8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/libc v1.9.5/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q= +modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg= +modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M= +modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU= +modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE= +modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso= +modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8= +modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8= +modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I= +modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk= +modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY= +modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE= +modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg= +modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM= +modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg= +modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo= +modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8= +modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ= +modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA= +modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM= +modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg= +modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE= +modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM= +modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU= +modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw= +modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M= +modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18= +modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8= +modernc.org/libc v1.11.70/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= +modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= +modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0= +modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI= +modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE= +modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY= +modernc.org/libc v1.11.88 h1:ibbHksDVITfJtBTSCENSXRt/pL4P/QJP+EzJUimW268= +modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ= +modernc.org/lldb v1.0.0/go.mod h1:jcRvJGWfCGodDZz8BPwiKMJxGJngQ/5DrRapkQnLob8= +modernc.org/lldb v1.0.2 h1:LBw58xVFl01OuM5U9++tLy3wmu+PoWok6T3dHuNjcZk= +modernc.org/lldb v1.0.2/go.mod h1:ovbKqyzA9H/iPwHkAOH0qJbIQVT9rlijecenxDwVUi0= +modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= +modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= +modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14= +modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= +modernc.org/opt v0.1.1 h1:/0RX92k9vwVeDXj+Xn23DKp2VJubL7k8qNffND6qn3A= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/ql v1.0.0/go.mod h1:xGVyrLIatPcO2C1JvI/Co8c0sr6y91HKFNy4pt9JXEY= +modernc.org/ql v1.4.0 h1:CqLAho+y4N8JwvqT7NJsYsp7YPwiRv6RE2n0n1ksSCU= +modernc.org/ql v1.4.0/go.mod h1:q4c29Bgdx+iAtxx47ODW5Xo2X0PDkjSCK9NdQl6KFxc= +modernc.org/sortutil v1.1.0 h1:oP3U4uM+NT/qBQcbg/K2iqAX0Nx7B1b6YZtq3Gk/PjM= +modernc.org/sortutil v1.1.0/go.mod h1:ZyL98OQHJgH9IEfN71VsamvJgrtRX9Dj2gX+vH86L1k= +modernc.org/sqlite v1.10.6/go.mod h1:Z9FEjUtZP4qFEg6/SiADg9XCER7aYy9a/j7Pg9P7CPs= +modernc.org/sqlite v1.14.2 h1:ohsW2+e+Qe2To1W6GNezzKGwjXwSax6R+CrhRxVaFbE= +modernc.org/sqlite v1.14.2/go.mod h1:yqfn85u8wVOE6ub5UT8VI9JjhrwBUUCNyTACN0h6Sx8= +modernc.org/strutil v1.1.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= +modernc.org/strutil v1.1.1 h1:xv+J1BXY3Opl2ALrBwyfEikFAj8pmqcpnfmuwUwcozs= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/tcl v1.5.2/go.mod h1:pmJYOLgpiys3oI4AeAafkcUfE+TKKilminxNyU/+Zlo= +modernc.org/tcl v1.8.13/go.mod h1:V+q/Ef0IJaNUSECieLU4o+8IScapxnMyFV6i/7uQlAY= +modernc.org/token v1.0.0 h1:a0jaWiNMDhDUtqOj09wvjWWAqd3q7WpBulmL9H2egsk= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.0.1-0.20210308123920-1f282aa71362/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= +modernc.org/z v1.0.1/go.mod h1:8/SRk5C/HgiQWCgXdfpb+1RvhORdkz5sw72d3jjtyqA= +modernc.org/z v1.2.19/go.mod h1:+ZpP0pc4zz97eukOzW3xagV/lS82IpPN9NGG5pNF9vY= +modernc.org/zappy v1.0.0/go.mod h1:hHe+oGahLVII/aTTyWK/b53VDHMAGCBYYeZ9sn83HC4= +modernc.org/zappy v1.0.3 h1:Tr+P3kclDSrvC6zYBW2hWmOmu5SjG6PtvCt3RCjRmss= +modernc.org/zappy v1.0.3/go.mod h1:w/Akq8ipfols/xZJdR5IYiQNOqC80qz2mVvsEwEbkiI= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/Erupe/main.go b/Erupe/main.go new file mode 100644 index 000000000..89cdf39fb --- /dev/null +++ b/Erupe/main.go @@ -0,0 +1,177 @@ +package main + +import ( + "fmt" + "os" + "os/signal" + "syscall" + "time" + + "github.com/Solenataris/Erupe/config" + "github.com/Solenataris/Erupe/server/channelserver" + "github.com/Solenataris/Erupe/server/entranceserver" + "github.com/Solenataris/Erupe/server/launcherserver" + "github.com/Solenataris/Erupe/server/signserver" + "github.com/jmoiron/sqlx" + _ "github.com/lib/pq" + "go.uber.org/zap" +) + +// Temporary DB auto clean on startup for quick development & testing. +func cleanDB(db *sqlx.DB) { + _ = db.MustExec("DELETE FROM guild_characters") + _ = db.MustExec("DELETE FROM guilds") + _ = db.MustExec("DELETE FROM characters") + _ = db.MustExec("DELETE FROM sign_sessions") + _ = db.MustExec("DELETE FROM users") +} + +func main() { + zapLogger, _ := zap.NewDevelopment() + defer zapLogger.Sync() + logger := zapLogger.Named("main") + + logger.Info("Starting Erupe") + + // Load the configuration. + erupeConfig, err := config.LoadConfig() + if err != nil { + logger.Fatal("Failed to load config", zap.Error(err)) + } + + // Create the postgres DB pool. + connectString := fmt.Sprintf( + "host=%s port=%d user=%s password=%s dbname= %s sslmode=disable", + erupeConfig.Database.Host, + erupeConfig.Database.Port, + erupeConfig.Database.User, + erupeConfig.Database.Password, + erupeConfig.Database.Database, + ) + + db, err := sqlx.Open("postgres", connectString) + if err != nil { + logger.Fatal("Failed to open sql database", zap.Error(err)) + } + + // Test the DB connection. + err = db.Ping() + if err != nil { + logger.Fatal("Failed to ping database", zap.Error(err)) + } + logger.Info("Connected to database") + + // Clean the DB if the option is on. + if erupeConfig.DevMode && erupeConfig.DevModeOptions.CleanDB { + logger.Info("Cleaning DB") + cleanDB(db) + logger.Info("Done cleaning DB") + } + + // Now start our server(s). + + // Launcher HTTP server. + launcherServer := launcherserver.NewServer( + &launcherserver.Config{ + Logger: logger.Named("launcher"), + ErupeConfig: erupeConfig, + DB: db, + UseOriginalLauncherFiles: erupeConfig.Launcher.UseOriginalLauncherFiles, + }) + err = launcherServer.Start() + if err != nil { + logger.Fatal("Failed to start launcher server", zap.Error(err)) + } + logger.Info("Started launcher server.") + + // Entrance server. + entranceServer := entranceserver.NewServer( + &entranceserver.Config{ + Logger: logger.Named("entrance"), + ErupeConfig: erupeConfig, + DB: db, + }) + err = entranceServer.Start() + if err != nil { + logger.Fatal("Failed to start entrance server", zap.Error(err)) + } + logger.Info("Started entrance server.") + + // Sign server. + signServer := signserver.NewServer( + &signserver.Config{ + Logger: logger.Named("sign"), + ErupeConfig: erupeConfig, + DB: db, + }) + err = signServer.Start() + if err != nil { + logger.Fatal("Failed to start sign server", zap.Error(err)) + } + logger.Info("Started sign server.") + + // Channel Server + channelServer1 := channelserver.NewServer( + &channelserver.Config{ + Logger: logger.Named("channel"), + ErupeConfig: erupeConfig, + DB: db, + }) + + err = channelServer1.Start(erupeConfig.Channel.Port1) + if err != nil { + logger.Fatal("Failed to start channel server1", zap.Error(err)) + } + logger.Info("Started channel server.") + // Channel Server + channelServer2 := channelserver.NewServer( + &channelserver.Config{ + Logger: logger.Named("channel"), + ErupeConfig: erupeConfig, + DB: db, + }) + + err = channelServer2.Start(erupeConfig.Channel.Port2) + if err != nil { + logger.Fatal("Failed to start channel server2", zap.Error(err)) + } + // Channel Server + channelServer3 := channelserver.NewServer( + &channelserver.Config{ + Logger: logger.Named("channel"), + ErupeConfig: erupeConfig, + DB: db, + }) + + err = channelServer3.Start(erupeConfig.Channel.Port3) + if err != nil { + logger.Fatal("Failed to start channel server3", zap.Error(err)) + } + // Channel Server + channelServer4 := channelserver.NewServer( + &channelserver.Config{ + Logger: logger.Named("channel"), + ErupeConfig: erupeConfig, + DB: db, + }) + + err = channelServer4.Start(erupeConfig.Channel.Port4) + if err != nil { + logger.Fatal("Failed to start channel server4", zap.Error(err)) + } + // Wait for exit or interrupt with ctrl+C. + c := make(chan os.Signal, 1) + signal.Notify(c, os.Interrupt, syscall.SIGTERM) + <-c + + logger.Info("Trying to shutdown gracefully.") + channelServer4.Shutdown() + channelServer3.Shutdown() + channelServer2.Shutdown() + channelServer1.Shutdown() + signServer.Shutdown() + entranceServer.Shutdown() + launcherServer.Shutdown() + + time.Sleep(1 * time.Second) +} diff --git a/Erupe/migrations/000001_initial_db.down.sql b/Erupe/migrations/000001_initial_db.down.sql new file mode 100644 index 000000000..04f7e46f8 --- /dev/null +++ b/Erupe/migrations/000001_initial_db.down.sql @@ -0,0 +1,10 @@ +BEGIN; + +DROP TABLE IF EXISTS sign_sessions; +DROP TABLE IF EXISTS characters; +DROP TABLE IF EXISTS users; + +DROP DOMAIN IF EXISTS uint8; +DROP DOMAIN IF EXISTS uint16; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000001_initial_db.up.sql b/Erupe/migrations/000001_initial_db.up.sql new file mode 100644 index 000000000..ef8cbc950 --- /dev/null +++ b/Erupe/migrations/000001_initial_db.up.sql @@ -0,0 +1,36 @@ +BEGIN; + +CREATE DOMAIN uint8 AS smallint + CHECK(VALUE >= 0 AND VALUE <= 255); + +CREATE DOMAIN uint16 AS integer + CHECK(VALUE >= 0 AND VALUE <= 65536); + +CREATE TABLE users ( + id serial NOT NULL PRIMARY KEY, + username text UNIQUE NOT NULL, + password text NOT NULL +); + +CREATE TABLE characters ( + id serial NOT NULL PRIMARY KEY, + user_id bigint REFERENCES users(id), + is_female boolean, + is_new_character boolean, + small_gr_level uint8, + gr_override_mode boolean, + name varchar(15), + unk_desc_string varchar(31), + gr_override_level uint16, + gr_override_unk0 uint8, + gr_override_unk1 uint8 +); + +CREATE TABLE sign_sessions ( + id serial NOT NULL PRIMARY KEY, + user_id bigint REFERENCES users(id), + auth_token_num bigint, + auth_token_str text +); + +END; \ No newline at end of file diff --git a/Erupe/migrations/000002_alter_characters.down.sql b/Erupe/migrations/000002_alter_characters.down.sql new file mode 100644 index 000000000..c5eeb425b --- /dev/null +++ b/Erupe/migrations/000002_alter_characters.down.sql @@ -0,0 +1,8 @@ +BEGIN; + +ALTER TABLE characters + DROP COLUMN exp, + DROP COLUMN weapon, + DROP COLUMN last_login; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000002_alter_characters.up.sql b/Erupe/migrations/000002_alter_characters.up.sql new file mode 100644 index 000000000..8e92154dc --- /dev/null +++ b/Erupe/migrations/000002_alter_characters.up.sql @@ -0,0 +1,8 @@ +BEGIN; + +ALTER TABLE characters + ADD COLUMN exp uint16, + ADD COLUMN weapon uint16, + ADD COLUMN last_login integer; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000003_character_savedata.down.sql b/Erupe/migrations/000003_character_savedata.down.sql new file mode 100644 index 000000000..d8d1ca8c6 --- /dev/null +++ b/Erupe/migrations/000003_character_savedata.down.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE characters + DROP COLUMN savedata; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000003_character_savedata.up.sql b/Erupe/migrations/000003_character_savedata.up.sql new file mode 100644 index 000000000..d0f39a223 --- /dev/null +++ b/Erupe/migrations/000003_character_savedata.up.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE characters + ADD COLUMN savedata bytea; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000004_character_additional.down.sql b/Erupe/migrations/000004_character_additional.down.sql new file mode 100644 index 000000000..5229381cb --- /dev/null +++ b/Erupe/migrations/000004_character_additional.down.sql @@ -0,0 +1,13 @@ +BEGIN; + +ALTER TABLE characters + DROP COLUMN decomyset, + DROP COLUMN hunternavi, + DROP COLUMN otomoairou, + DROP COLUMN partner, + DROP COLUMN platebox, + DROP COLUMN platedata, + DROP COLUMN platemyset, + DROP COLUMN rengokudata; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000004_character_additional.up.sql b/Erupe/migrations/000004_character_additional.up.sql new file mode 100644 index 000000000..699351796 --- /dev/null +++ b/Erupe/migrations/000004_character_additional.up.sql @@ -0,0 +1,14 @@ +BEGIN; + +ALTER TABLE characters + ADD COLUMN decomyset bytea, + ADD COLUMN hunternavi bytea, + ADD COLUMN otomoairou bytea, + ADD COLUMN partner bytea, + ADD COLUMN platebox bytea, + ADD COLUMN platedata bytea, + ADD COLUMN platemyset bytea, + ADD COLUMN trophy bytea, + ADD COLUMN rengokudata bytea; + +END; diff --git a/Erupe/migrations/000005_quests.down.sql b/Erupe/migrations/000005_quests.down.sql new file mode 100644 index 000000000..60eff8f22 --- /dev/null +++ b/Erupe/migrations/000005_quests.down.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TABLE IF EXISTS questlists; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000005_quests.up.sql b/Erupe/migrations/000005_quests.up.sql new file mode 100644 index 000000000..26a02f8d1 --- /dev/null +++ b/Erupe/migrations/000005_quests.up.sql @@ -0,0 +1,8 @@ +BEGIN; + +CREATE TABLE questlists ( + ind int NOT NULL PRIMARY KEY, + questlist bytea +); + +END; \ No newline at end of file diff --git a/Erupe/migrations/000006_mercenary.down.sql b/Erupe/migrations/000006_mercenary.down.sql new file mode 100644 index 000000000..54cbd957b --- /dev/null +++ b/Erupe/migrations/000006_mercenary.down.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE characters + DROP COLUMN savemercenary; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000006_mercenary.up.sql b/Erupe/migrations/000006_mercenary.up.sql new file mode 100644 index 000000000..af025dff0 --- /dev/null +++ b/Erupe/migrations/000006_mercenary.up.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE characters + ADD COLUMN savemercenary bytea; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000007_guilds.down.sql b/Erupe/migrations/000007_guilds.down.sql new file mode 100644 index 000000000..344ab854e --- /dev/null +++ b/Erupe/migrations/000007_guilds.down.sql @@ -0,0 +1,6 @@ +BEGIN; + +DROP TABLE guild_characters; +DROP TABLE guilds; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000007_guilds.up.sql b/Erupe/migrations/000007_guilds.up.sql new file mode 100644 index 000000000..e327c7db3 --- /dev/null +++ b/Erupe/migrations/000007_guilds.up.sql @@ -0,0 +1,22 @@ +BEGIN; + +CREATE TABLE guilds +( + id serial NOT NULL PRIMARY KEY, + name varchar(24), + created_at timestamp DEFAULT NOW(), + leader_id int NOT NULL, + main_motto varchar(255) DEFAULT '' +); + +CREATE TABLE guild_characters +( + id serial NOT NULL PRIMARY KEY, + guild_id bigint REFERENCES guilds (id), + character_id bigint REFERENCES characters (id), + joined_at timestamp DEFAULT NOW() +); + +CREATE UNIQUE INDEX guild_character_unique_index ON guild_characters (character_id); + +END; \ No newline at end of file diff --git a/Erupe/migrations/000008_guild_additional.down.sql b/Erupe/migrations/000008_guild_additional.down.sql new file mode 100644 index 000000000..9252a98f2 --- /dev/null +++ b/Erupe/migrations/000008_guild_additional.down.sql @@ -0,0 +1,11 @@ +BEGIN; + +ALTER TABLE guilds + DROP COLUMN rp; + +ALTER TABLE guild_characters + DROP COLUMN is_applicant, + DROP COLUMN is_sub_leader, + DROP COLUMN order_index; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000008_guild_additional.up.sql b/Erupe/migrations/000008_guild_additional.up.sql new file mode 100644 index 000000000..7e16984d3 --- /dev/null +++ b/Erupe/migrations/000008_guild_additional.up.sql @@ -0,0 +1,11 @@ +BEGIN; + +ALTER TABLE guild_characters + ADD COLUMN is_applicant bool NOT NULL DEFAULT false, + ADD COLUMN is_sub_leader bool NOT NULL DEFAULT false, + ADD COLUMN order_index int NOT NULL DEFAULT 1; + +ALTER TABLE guilds + ADD COLUMN rp uint16 NOT NULL DEFAULT 0; + +END; diff --git a/Erupe/migrations/000009_character_social.down.sql b/Erupe/migrations/000009_character_social.down.sql new file mode 100644 index 000000000..243ea6712 --- /dev/null +++ b/Erupe/migrations/000009_character_social.down.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE characters + DROP COLUMN restrict_guild_scout; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000009_character_social.up.sql b/Erupe/migrations/000009_character_social.up.sql new file mode 100644 index 000000000..f94ce2043 --- /dev/null +++ b/Erupe/migrations/000009_character_social.up.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE characters + ADD COLUMN restrict_guild_scout bool NOT NULL DEFAULT false; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000010_guild_comments_festival_hall.down.sql b/Erupe/migrations/000010_guild_comments_festival_hall.down.sql new file mode 100644 index 000000000..c86d1ee5e --- /dev/null +++ b/Erupe/migrations/000010_guild_comments_festival_hall.down.sql @@ -0,0 +1,10 @@ +BEGIN; + +ALTER TABLE guilds + DROP COLUMN comment, + DROP COLUMN festival_colour, + DROP COLUMN guild_hall; + +DROP TYPE festival_colour; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000010_guild_comments_festival_hall.up.sql b/Erupe/migrations/000010_guild_comments_festival_hall.up.sql new file mode 100644 index 000000000..3caec4149 --- /dev/null +++ b/Erupe/migrations/000010_guild_comments_festival_hall.up.sql @@ -0,0 +1,11 @@ +BEGIN; + +CREATE TYPE festival_colour AS ENUM ('none', 'red', 'blue'); + +ALTER TABLE guilds + ADD COLUMN comment varchar(255) NOT NULL DEFAULT '', + ADD COLUMN festival_colour festival_colour DEFAULT 'none', + ADD COLUMN guild_hall int DEFAULT 0; + + +END; \ No newline at end of file diff --git a/Erupe/migrations/000011_character_points_minidata.down.sql b/Erupe/migrations/000011_character_points_minidata.down.sql new file mode 100644 index 000000000..557608be9 --- /dev/null +++ b/Erupe/migrations/000011_character_points_minidata.down.sql @@ -0,0 +1,24 @@ +BEGIN; + +ALTER TABLE characters + DROP COLUMN minidata, + DROP COLUMN gacha_trial, + DROP COLUMN gacha_prem, + DROP COLUMN gacha_items, + DROP COLUMN daily_time, + DROP COLUMN frontier_points, + DROP COLUMN netcafe_points, + DROP COLUMN house_info, + DROP COLUMN login_boost, + DROP COLUMN skin_hist, + DROP COLUMN gcp; + +DROP TABLE fpoint_items; +DROP TABLE gacha_shop; +DROP TABLE gacha_shop_items; +DROP TABLE lucky_box_state; +DROP TABLE stepup_state; +DROP TABLE normal_shop_items; +DROP TABLE shop_item_state; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000011_character_points_minidata.up.sql b/Erupe/migrations/000011_character_points_minidata.up.sql new file mode 100644 index 000000000..29baa0790 --- /dev/null +++ b/Erupe/migrations/000011_character_points_minidata.up.sql @@ -0,0 +1,100 @@ +BEGIN; +ALTER TABLE characters + ADD COLUMN minidata bytea, + ADD COLUMN gacha_trial int, + ADD COLUMN gacha_prem int, + ADD COLUMN gacha_items bytea, + ADD COLUMN daily_time timestamp, + ADD COLUMN frontier_points int, + ADD COLUMN netcafe_points int, + ADD COLUMN house_info bytea, + ADD COLUMN login_boost bytea, + ADD COLUMN skin_hist bytea, + ADD COLUMN kouryou_point int, + ADD COLUMN gcp int; + +CREATE TABLE fpoint_items +( + hash int, + itemType uint8, + itemID uint16, + quant uint16, + itemValue uint16, + tradeType uint8 +); + + +CREATE TABLE gacha_shop +( + hash bigint, + reqGR int, + reqHR int, + gachaName varchar(255), + gachaLink0 varchar(255), + gachaLink1 varchar(255), + gachaLink2 varchar(255), + extraIcon int, + gachaType int, + hideFlag bool +); + +CREATE TABLE gacha_shop_items +( + shophash int, + entryType uint8, + itemhash int UNIQUE NOT NULL, + currType uint8, + currNumber uint16, + currQuant uint16, + percentage uint16, + rarityIcon uint8, + rollsCount uint8, + itemCount uint8, + dailyLimit uint8, + itemType int[], + itemId int[], + quantity int[] +); + +CREATE TABLE lucky_box_state +( + char_id bigint REFERENCES characters (id), + shophash int UNIQUE NOT NULL, + used_itemhash int[] +); + + +CREATE TABLE stepup_state +( + char_id bigint REFERENCES characters (id), + shophash int UNIQUE NOT NULL, + step_progression int, + step_time timestamp +); + +CREATE TABLE normal_shop_items +( + shoptype int, + shopid int, + itemhash int UNIQUE NOT NULL, + itemID uint16, + Points uint16, + TradeQuantity uint16, + rankReqLow uint16, + rankReqHigh uint16, + rankReqG uint16, + storeLevelReq uint16, + maximumQuantity uint16, + boughtQuantity uint16, + roadFloorsRequired uint16, + weeklyFatalisKills uint16 +); + +CREATE TABLE shop_item_state +( + char_id bigint REFERENCES characters (id), + itemhash int UNIQUE NOT NULL, + usedquantity int +); + +END; \ No newline at end of file diff --git a/Erupe/migrations/000012_loginboost_etc.down.sql b/Erupe/migrations/000012_loginboost_etc.down.sql new file mode 100644 index 000000000..13102b0b0 --- /dev/null +++ b/Erupe/migrations/000012_loginboost_etc.down.sql @@ -0,0 +1,5 @@ +BEGIN; + +DROP TABLE login_boost_state; + +END; \ No newline at end of file diff --git a/Erupe/migrations/000012_loginboost_etc.up.sql b/Erupe/migrations/000012_loginboost_etc.up.sql new file mode 100644 index 000000000..4feff1790 --- /dev/null +++ b/Erupe/migrations/000012_loginboost_etc.up.sql @@ -0,0 +1,13 @@ +BEGIN; + +CREATE TABLE login_boost_state +( + char_id bigint REFERENCES characters (id), + week_req uint8, + week_count uint8, + available bool, + end_time int, + CONSTRAINT id_week UNIQUE(char_id, week_req) +); + +END; \ No newline at end of file diff --git a/Erupe/migrations/000013_shop_constraints.down.sql b/Erupe/migrations/000013_shop_constraints.down.sql new file mode 100644 index 000000000..7b5ac1242 --- /dev/null +++ b/Erupe/migrations/000013_shop_constraints.down.sql @@ -0,0 +1,12 @@ +BEGIN; + +ALTER TABLE shop_item_state DROP CONSTRAINT shop_item_state_id_itemhash; +ALTER TABLE shop_item_state ADD CONSTRAINT shop_item_state_itemhash_key UNIQUE (itemhash); + +ALTER TABLE stepup_state DROP CONSTRAINT stepup_state_id_shophash; +ALTER TABLE stepup_state ADD CONSTRAINT stepup_state_shophash_key UNIQUE (shophash); + +ALTER TABLE lucky_box_state DROP CONSTRAINT lucky_box_state_id_shophash; +ALTER TABLE lucky_box_state ADD CONSTRAINT lucky_box_state_shophash_key UNIQUE (shophash); + +END; \ No newline at end of file diff --git a/Erupe/migrations/000013_shop_constraints.up.sql b/Erupe/migrations/000013_shop_constraints.up.sql new file mode 100644 index 000000000..a48e81ac2 --- /dev/null +++ b/Erupe/migrations/000013_shop_constraints.up.sql @@ -0,0 +1,12 @@ +BEGIN; + +ALTER TABLE shop_item_state DROP CONSTRAINT shop_item_state_itemhash_key; +ALTER TABLE shop_item_state ADD CONSTRAINT shop_item_state_id_itemhash UNIQUE(char_id, itemhash); + +ALTER TABLE stepup_state DROP CONSTRAINT stepup_state_shophash_key; +ALTER TABLE stepup_state ADD CONSTRAINT stepup_state_id_shophash UNIQUE(char_id, shophash); + +ALTER TABLE lucky_box_state DROP CONSTRAINT lucky_box_state_shophash_key; +ALTER TABLE lucky_box_state ADD CONSTRAINT lucky_box_state_id_shophash UNIQUE(char_id, shophash); + +END; \ No newline at end of file diff --git a/Erupe/migrations/000014_guild_flags_applications.down.sql b/Erupe/migrations/000014_guild_flags_applications.down.sql new file mode 100644 index 000000000..6cfe86288 --- /dev/null +++ b/Erupe/migrations/000014_guild_flags_applications.down.sql @@ -0,0 +1,18 @@ +BEGIN; +ALTER TABLE guild_characters + RENAME COLUMN avoid_leadership TO is_sub_leader; + +ALTER TABLE guild_characters + ADD COLUMN is_applicant bool NOT NULL DEFAULT false; + +ALTER TABLE guilds + DROP COLUMN icon, + ALTER COLUMN main_motto TYPE varchar USING '', + DROP COLUMN sub_motto; + +ALTER TABLE guilds + ALTER COLUMN main_motto SET DEFAULT ''; + +DROP TABLE guild_applications; +DROP TYPE guild_application_type; +END; \ No newline at end of file diff --git a/Erupe/migrations/000014_guild_flags_applications.up.sql b/Erupe/migrations/000014_guild_flags_applications.up.sql new file mode 100644 index 000000000..4bc09668a --- /dev/null +++ b/Erupe/migrations/000014_guild_flags_applications.up.sql @@ -0,0 +1,30 @@ +BEGIN; +CREATE TYPE guild_application_type AS ENUM ('applied', 'invited'); + +CREATE TABLE guild_applications +( + id serial NOT NULL PRIMARY KEY, + guild_id int NOT NULL REFERENCES guilds (id), + character_id int NOT NULL REFERENCES characters (id), + actor_id int NOT NULL REFERENCES characters (id), + application_type guild_application_type NOT NULL, + created_at timestamp NOT NULL DEFAULT now(), + CONSTRAINT guild_application_character_id UNIQUE (guild_id, character_id) +); + +CREATE INDEX guild_application_type_index ON guild_applications (application_type); + +ALTER TABLE guild_characters + DROP COLUMN is_applicant; + +ALTER TABLE guild_characters + RENAME COLUMN is_sub_leader TO avoid_leadership; + +ALTER TABLE guilds + ALTER COLUMN main_motto SET DEFAULT 0; + +ALTER TABLE guilds + ADD COLUMN icon bytea, + ADD COLUMN sub_motto int DEFAULT 0, + ALTER COLUMN main_motto TYPE int USING 0; +END; \ No newline at end of file diff --git a/Erupe/migrations/000015_mail.down.sql b/Erupe/migrations/000015_mail.down.sql new file mode 100644 index 000000000..8ed5b834f --- /dev/null +++ b/Erupe/migrations/000015_mail.down.sql @@ -0,0 +1,3 @@ +BEGIN; +DROP TABLE mail; +END; \ No newline at end of file diff --git a/Erupe/migrations/000015_mail.up.sql b/Erupe/migrations/000015_mail.up.sql new file mode 100644 index 000000000..ba0dc4edd --- /dev/null +++ b/Erupe/migrations/000015_mail.up.sql @@ -0,0 +1,19 @@ +BEGIN; +CREATE TABLE mail +( + id SERIAL NOT NULL PRIMARY KEY, + sender_id INT NOT NULL REFERENCES characters (id), + recipient_id INT NOT NULL REFERENCES characters (id), + subject VARCHAR NOT NULL DEFAULT '', + body VARCHAR NOT NULL DEFAULT '', + read BOOL NOT NULL DEFAULT FALSE, + attached_item_received BOOL NOT NULL DEFAULT FALSE, + attached_item INT DEFAULT NULL, + attached_item_amount INT NOT NULL DEFAULT 1, + is_guild_invite BOOL NOT NULL DEFAULT FALSE, + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + deleted BOOL NOT NULL DEFAULT FALSE +); + +CREATE INDEX mail_recipient_deleted_created_id_index ON mail (recipient_id, deleted, created_at DESC, id DESC); +END; \ No newline at end of file diff --git a/Erupe/migrations/000016_server.down.sql b/Erupe/migrations/000016_server.down.sql new file mode 100644 index 000000000..a5fb2d6b0 --- /dev/null +++ b/Erupe/migrations/000016_server.down.sql @@ -0,0 +1,3 @@ +BEGIN; +DROP TABLE public.servers; +END; \ No newline at end of file diff --git a/Erupe/migrations/000016_server.up.sql b/Erupe/migrations/000016_server.up.sql new file mode 100644 index 000000000..f6a7798e7 --- /dev/null +++ b/Erupe/migrations/000016_server.up.sql @@ -0,0 +1,21 @@ +BEGIN; +-- Table: public.servers + +-- DROP TABLE IF EXISTS public.servers; + +CREATE TABLE IF NOT EXISTS public.servers +( + server_id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ), + server_name text COLLATE pg_catalog."default", + season integer, + current_players integer, + event_id integer, + event_expiration integer, + CONSTRAINT servers_pkey PRIMARY KEY (server_id) +) + +TABLESPACE pg_default; + +ALTER TABLE IF EXISTS public.servers + OWNER to postgres; +END; \ No newline at end of file diff --git a/Erupe/migrations/000017_account.down.sql b/Erupe/migrations/000017_account.down.sql new file mode 100644 index 000000000..c52957af0 --- /dev/null +++ b/Erupe/migrations/000017_account.down.sql @@ -0,0 +1,6 @@ +BEGIN; +DROP TABLE public.account_ban; +DROP TABLE public.account_history; +DROP TABLE public.account_moderation; +DROP TABLE public.account_sub; +END; \ No newline at end of file diff --git a/Erupe/migrations/000017_account.up.sql b/Erupe/migrations/000017_account.up.sql new file mode 100644 index 000000000..f636d619f --- /dev/null +++ b/Erupe/migrations/000017_account.up.sql @@ -0,0 +1,45 @@ +BEGIN; + +CREATE TABLE IF NOT EXISTS public.account_ban +( + user_id integer NOT NULL, + title text COLLATE pg_catalog."default", + reason text COLLATE pg_catalog."default", + date text COLLATE pg_catalog."default", + pass_origin text COLLATE pg_catalog."default", + pass_block text COLLATE pg_catalog."default", + CONSTRAINT ban_pkey PRIMARY KEY (user_id) +); + +CREATE TABLE IF NOT EXISTS public.account_history +( + report_id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ), + user_id integer, + title text COLLATE pg_catalog."default", + reason text COLLATE pg_catalog."default", + date date, + CONSTRAINT account_history_pkey PRIMARY KEY (report_id) +); + +CREATE TABLE IF NOT EXISTS public.account_moderation +( + id integer NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ), + username text COLLATE pg_catalog."default", + password text COLLATE pg_catalog."default", + type text COLLATE pg_catalog."default", + CONSTRAINT account_moderation_pkey PRIMARY KEY (id) +); + +CREATE TABLE IF NOT EXISTS public.account_sub +( + id integer NOT NULL GENERATED BY DEFAULT AS IDENTITY ( INCREMENT 1 START 1 MINVALUE 1 MAXVALUE 2147483647 CACHE 1 ), + discord_id text COLLATE pg_catalog."default", + erupe_account text COLLATE pg_catalog."default", + erupe_password text COLLATE pg_catalog."default", + date_inscription date, + country text COLLATE pg_catalog."default", + presentation text COLLATE pg_catalog."default", + CONSTRAINT account_auth_pkey PRIMARY KEY (id) +); + +END; \ No newline at end of file diff --git a/Erupe/migrations/000018_event_week.down.sql b/Erupe/migrations/000018_event_week.down.sql new file mode 100644 index 000000000..756df1f22 --- /dev/null +++ b/Erupe/migrations/000018_event_week.down.sql @@ -0,0 +1,3 @@ +BEGIN; +DROP TABLE public.event_week; +END; \ No newline at end of file diff --git a/Erupe/migrations/000018_event_week.up.sql b/Erupe/migrations/000018_event_week.up.sql new file mode 100644 index 000000000..f536871f2 --- /dev/null +++ b/Erupe/migrations/000018_event_week.up.sql @@ -0,0 +1,11 @@ +BEGIN; + +CREATE TABLE IF NOT EXISTS public.event_week +( + id integer NOT NULL, + event_id integer NOT NULL, + date_expiration integer NOT NULL, + CONSTRAINT event_week_pkey PRIMARY KEY (id) +); + +END; \ No newline at end of file diff --git a/Erupe/migrations/000019_gook.down.sql b/Erupe/migrations/000019_gook.down.sql new file mode 100644 index 000000000..a4b544e9a --- /dev/null +++ b/Erupe/migrations/000019_gook.down.sql @@ -0,0 +1,3 @@ +BEGIN; +DROP TABLE public.gook; +END; \ No newline at end of file diff --git a/Erupe/migrations/000019_gook.up.sql b/Erupe/migrations/000019_gook.up.sql new file mode 100644 index 000000000..fe5c051c0 --- /dev/null +++ b/Erupe/migrations/000019_gook.up.sql @@ -0,0 +1,20 @@ +BEGIN; + +CREATE TABLE IF NOT EXISTS public.gook +( + id serial NOT NULL PRIMARY KEY, + gook0 bytea, + gook1 bytea, + gook2 bytea, + gook3 bytea, + gook4 bytea, + gook5 bytea, + gook0status boolean, + gook1status boolean, + gook2status boolean, + gook3status boolean, + gook4status boolean, + gook5status boolean +); + +END; \ No newline at end of file diff --git a/Erupe/migrations/000020_history.down.sql b/Erupe/migrations/000020_history.down.sql new file mode 100644 index 000000000..623bd53c8 --- /dev/null +++ b/Erupe/migrations/000020_history.down.sql @@ -0,0 +1,3 @@ +BEGIN; +DROP TABLE public.history; +END; \ No newline at end of file diff --git a/Erupe/migrations/000020_history.up.sql b/Erupe/migrations/000020_history.up.sql new file mode 100644 index 000000000..96d6b36c8 --- /dev/null +++ b/Erupe/migrations/000020_history.up.sql @@ -0,0 +1,13 @@ +BEGIN; + +CREATE TABLE IF NOT EXISTS public.history +( + user_id integer, + admin_id integer, + report_id integer NOT NULL, + title text COLLATE pg_catalog."default", + reason text COLLATE pg_catalog."default", + CONSTRAINT history_pkey PRIMARY KEY (report_id) +); + +END; \ No newline at end of file diff --git a/Erupe/network/binpacket/msg_bin_chat.go b/Erupe/network/binpacket/msg_bin_chat.go new file mode 100644 index 000000000..8bf79702a --- /dev/null +++ b/Erupe/network/binpacket/msg_bin_chat.go @@ -0,0 +1,60 @@ +package binpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// ChatType represents the chat message type (Thanks to @Alice on discord for identifying these!) +type ChatType uint8 + +// Chat types +const ( + ChatTypeLocal ChatType = 1 + ChatTypeGuild = 2 + ChatTypeAlliance = 3 + ChatTypeParty = 4 + ChatTypeWhisper = 5 +) + +// MsgBinChat is a binpacket for chat messages. +type MsgBinChat struct { + Unk0 uint8 + Type ChatType + Flags uint16 + Message string + SenderName string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgBinChat) Opcode() network.PacketID { + return network.MSG_SYS_CAST_BINARY +} + +// Parse parses the packet from binary +func (m *MsgBinChat) Parse(bf *byteframe.ByteFrame) error { + m.Unk0 = bf.ReadUint8() + m.Type = ChatType(bf.ReadUint8()) + m.Flags = bf.ReadUint16() + senderNameSize := bf.ReadUint16() + messageSize := bf.ReadUint16() + + // TODO(Andoryuuta): Need proper shift-jis and null termination. + m.Message = string(bf.ReadBytes(uint(messageSize))[:messageSize-1]) + m.SenderName = string(bf.ReadBytes(uint(senderNameSize))[:senderNameSize-1]) + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgBinChat) Build(bf *byteframe.ByteFrame) error { + bf.WriteUint8(m.Unk0) + bf.WriteUint8(uint8(m.Type)) + bf.WriteUint16(m.Flags) + bf.WriteUint16(uint16(len(m.SenderName) + 1)) + bf.WriteUint16(uint16(len(m.Message) + 1)) + bf.WriteNullTerminatedBytes([]byte(m.Message)) + bf.WriteNullTerminatedBytes([]byte(m.SenderName)) + + return nil +} diff --git a/Erupe/network/binpacket/msg_bin_mail_notify.go b/Erupe/network/binpacket/msg_bin_mail_notify.go new file mode 100644 index 000000000..bcd3cc077 --- /dev/null +++ b/Erupe/network/binpacket/msg_bin_mail_notify.go @@ -0,0 +1,29 @@ +package binpacket + +import ( + "github.com/Solenataris/Erupe/common/stringsupport" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +type MsgBinMailNotify struct { + SenderName string +} + +func (m MsgBinMailNotify) Parse(bf *byteframe.ByteFrame) error { + panic("implement me") +} + +func (m MsgBinMailNotify) Build(bf *byteframe.ByteFrame) error { + bf.WriteUint8(0x01) // Unk + byteName, _ := stringsupport.ConvertUTF8ToShiftJIS(m.SenderName) + + bf.WriteBytes(byteName) + bf.WriteBytes(make([]byte, 21-len(byteName))) + + return nil +} + +func (m MsgBinMailNotify) Opcode() network.PacketID { + return network.MSG_SYS_CASTED_BINARY +} diff --git a/Erupe/network/binpacket/msg_bin_targeted.go b/Erupe/network/binpacket/msg_bin_targeted.go new file mode 100644 index 000000000..adc855ce0 --- /dev/null +++ b/Erupe/network/binpacket/msg_bin_targeted.go @@ -0,0 +1,46 @@ +package binpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgBinTargeted is a format used for some broadcast types +// to target specific players, instead of groups (world, stage, etc). +// It forwards a normal binpacket in it's RawDataPayload +type MsgBinTargeted struct { + TargetCount uint16 + TargetCharIDs []uint32 + RawDataPayload []byte // The regular binary payload to be forwarded to the targets. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgBinTargeted) Opcode() network.PacketID { + return network.MSG_SYS_CAST_BINARY +} + +// Parse parses the packet from binary +func (m *MsgBinTargeted) Parse(bf *byteframe.ByteFrame) error { + m.TargetCount = bf.ReadUint16() + + m.TargetCharIDs = make([]uint32, m.TargetCount) + for i := uint16(0); i < m.TargetCount; i++ { + m.TargetCharIDs[i] = bf.ReadUint32() + } + + m.RawDataPayload = bf.DataFromCurrent() + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgBinTargeted) Build(bf *byteframe.ByteFrame) error { + bf.WriteUint16(m.TargetCount) + + for i := 0; i < int(m.TargetCount); i++ { + bf.WriteUint32(m.TargetCharIDs[i]) + } + + bf.WriteBytes(m.RawDataPayload) + return nil +} diff --git a/Erupe/network/clientctx/clientcontext.go b/Erupe/network/clientctx/clientcontext.go new file mode 100644 index 000000000..ceb782e92 --- /dev/null +++ b/Erupe/network/clientctx/clientcontext.go @@ -0,0 +1,8 @@ +package clientctx + +import "github.com/Solenataris/Erupe/common/stringsupport" + +// ClientContext holds contextual data required for packet encoding/decoding. +type ClientContext struct { + StrConv *stringsupport.StringConverter +} diff --git a/Erupe/network/crypt_conn.go b/Erupe/network/crypt_conn.go new file mode 100644 index 000000000..4a271de09 --- /dev/null +++ b/Erupe/network/crypt_conn.go @@ -0,0 +1,125 @@ +package network + +import ( + "encoding/hex" + "errors" + "fmt" + "io" + "net" + + "github.com/Solenataris/Erupe/network/crypto" +) + +// CryptConn represents a MHF encrypted two-way connection, +// it automatically handles encryption, decryption, and key rotation via it's methods. +type CryptConn struct { + conn net.Conn + readKeyRot uint32 + sendKeyRot uint32 + sentPackets int32 + prevRecvPacketCombinedCheck uint16 + prevSendPacketCombinedCheck uint16 +} + +// NewCryptConn creates a new CryptConn with proper default values. +func NewCryptConn(conn net.Conn) *CryptConn { + cc := &CryptConn{ + conn: conn, + readKeyRot: 995117, + sendKeyRot: 995117, + } + return cc +} + +// ReadPacket reads an packet from the connection and returns the decrypted data. +func (cc *CryptConn) ReadPacket() ([]byte, error) { + + // Read the raw 14 byte header. + headerData := make([]byte, CryptPacketHeaderLength) + _, err := io.ReadFull(cc.conn, headerData) + if err != nil { + return nil, err + } + + // Parse the data into a usable struct. + cph, err := NewCryptPacketHeader(headerData) + if err != nil { + return nil, err + } + + // Now read the encrypted packet body after getting its size from the header. + encryptedPacketBody := make([]byte, cph.DataSize) + _, err = io.ReadFull(cc.conn, encryptedPacketBody) + if err != nil { + return nil, err + } + + // Update the key rotation before decrypting. + if cph.KeyRotDelta != 0 { + cc.readKeyRot = (uint32(cph.KeyRotDelta) * (cc.readKeyRot + 1)) + } + + out, combinedCheck, check0, check1, check2 := crypto.Decrypt(encryptedPacketBody, cc.readKeyRot, nil) + if cph.Check0 != check0 || cph.Check1 != check1 || cph.Check2 != check2 { + fmt.Printf("got c0 %X, c1 %X, c2 %X\n", check0, check1, check2) + fmt.Printf("want c0 %X, c1 %X, c2 %X\n", cph.Check0, cph.Check1, cph.Check2) + fmt.Printf("headerData:\n%s\n", hex.Dump(headerData)) + fmt.Printf("encryptedPacketBody:\n%s\n", hex.Dump(encryptedPacketBody)) + + // Attempt to bruteforce it. + fmt.Println("Crypto out of sync? Attempting bruteforce") + for key := byte(0); key < 255; key++ { + out, combinedCheck, check0, check1, check2 = crypto.Decrypt(encryptedPacketBody, 0, &key) + //fmt.Printf("Key: 0x%X\n%s\n", key, hex.Dump(out)) + if cph.Check0 == check0 && cph.Check1 == check1 && cph.Check2 == check2 { + fmt.Printf("Bruceforce successful, override key: 0x%X\n", key) + + // Try to fix key for subsequent packets? + //cc.readKeyRot = (uint32(key) << 1) + 999983 + + cc.prevRecvPacketCombinedCheck = combinedCheck + return out, nil + } + } + + return nil, errors.New("decrypted data checksum doesn't match header") + } + + cc.prevRecvPacketCombinedCheck = combinedCheck + return out, nil +} + +// SendPacket encrypts and sends a packet. +func (cc *CryptConn) SendPacket(data []byte) error { + keyRotDelta := byte(3) + + if keyRotDelta != 0 { + cc.sendKeyRot = (uint32(keyRotDelta) * (cc.sendKeyRot + 1)) + } + + // Encrypt the data + encData, combinedCheck, check0, check1, check2 := crypto.Encrypt(data, cc.sendKeyRot, nil) + + header := &CryptPacketHeader{} + header.Pf0 = byte(((uint(len(encData)) >> 12) & 0xF3) | 3) + header.KeyRotDelta = keyRotDelta + header.PacketNum = uint16(cc.sentPackets) + header.DataSize = uint16(len(encData)) + header.PrevPacketCombinedCheck = cc.prevSendPacketCombinedCheck + header.Check0 = check0 + header.Check1 = check1 + header.Check2 = check2 + + headerBytes, err := header.Encode() + if err != nil { + return err + } + + cc.conn.Write(headerBytes) + cc.conn.Write(encData) + + cc.sentPackets++ + cc.prevSendPacketCombinedCheck = combinedCheck + + return nil +} diff --git a/Erupe/network/crypt_packet.go b/Erupe/network/crypt_packet.go new file mode 100644 index 000000000..03ba4a293 --- /dev/null +++ b/Erupe/network/crypt_packet.go @@ -0,0 +1,90 @@ +package network + +import ( + "bytes" + "encoding/binary" +) + +const ( + // CryptPacketHeaderLength represents the byte-length of + // an encrypted packet header. + CryptPacketHeaderLength = 14 +) + +// CryptPacketHeader represents the parsed information of an encrypted packet header. +type CryptPacketHeader struct { + Pf0 byte + KeyRotDelta byte + PacketNum uint16 + DataSize uint16 + PrevPacketCombinedCheck uint16 + Check0 uint16 + Check1 uint16 + Check2 uint16 +} + +// NewCryptPacketHeader parses raw bytes into a CryptPacketHeader +func NewCryptPacketHeader(data []byte) (*CryptPacketHeader, error) { + var c = CryptPacketHeader{} + + r := bytes.NewReader(data) + + var err error + err = binary.Read(r, binary.BigEndian, &c.Pf0) + if err != nil { + return nil, err + } + err = binary.Read(r, binary.BigEndian, &c.KeyRotDelta) + if err != nil { + return nil, err + } + err = binary.Read(r, binary.BigEndian, &c.PacketNum) + if err != nil { + return nil, err + } + err = binary.Read(r, binary.BigEndian, &c.DataSize) + if err != nil { + return nil, err + } + err = binary.Read(r, binary.BigEndian, &c.PrevPacketCombinedCheck) + if err != nil { + return nil, err + } + err = binary.Read(r, binary.BigEndian, &c.Check0) + if err != nil { + return nil, err + } + err = binary.Read(r, binary.BigEndian, &c.Check1) + if err != nil { + return nil, err + } + err = binary.Read(r, binary.BigEndian, &c.Check2) + if err != nil { + return nil, err + } + + return &c, nil +} + +// Encode encodes the CryptPacketHeader into raw bytes. +func (c *CryptPacketHeader) Encode() ([]byte, error) { + buf := bytes.NewBuffer([]byte{}) + var data = []interface{}{ + c.Pf0, + c.KeyRotDelta, + c.PacketNum, + c.DataSize, + c.PrevPacketCombinedCheck, + c.Check0, + c.Check1, + c.Check2, + } + for _, v := range data { + err := binary.Write(buf, binary.BigEndian, v) + if err != nil { + return nil, err + } + } + + return buf.Bytes(), nil +} \ No newline at end of file diff --git a/Erupe/network/crypto/crypto.go b/Erupe/network/crypto/crypto.go new file mode 100644 index 000000000..87746fa90 --- /dev/null +++ b/Erupe/network/crypto/crypto.go @@ -0,0 +1,84 @@ +package crypto + +var ( + _encryptKey = []byte{0x90, 0x51, 0x26, 0x25, 0x04, 0xBF, 0xCF, 0x4C, 0x92, 0x02, 0x52, 0x7A, 0x70, 0x1A, 0x41, 0x88, 0x8C, 0xC2, 0xCE, 0xB8, 0xF6, 0x57, 0x7E, 0xBA, 0x83, 0x63, 0x2C, 0x24, 0x9A, 0x67, 0x86, 0x0C, 0xBE, 0x72, 0xFD, 0xB6, 0x7B, 0x79, 0xB0, 0x22, 0x5A, 0x60, 0x5C, 0x4F, 0x49, 0xE2, 0x0E, 0xF5, 0x3A, 0x81, 0xAE, 0x11, 0x6B, 0xF0, 0xA1, 0x01, 0xE8, 0x65, 0x8D, 0x5B, 0xDC, 0xCC, 0x93, 0x18, 0xB3, 0xAB, 0x77, 0xF7, 0x8E, 0xEC, 0xEF, 0x05, 0x00, 0xCA, 0x4E, 0xA7, 0xBC, 0xB5, 0x10, 0xC6, 0x6C, 0xC0, 0xC4, 0xE5, 0x87, 0x3F, 0xC1, 0x82, 0x29, 0x96, 0x45, 0x73, 0x07, 0xCB, 0x43, 0xF9, 0xF3, 0x08, 0x89, 0xD0, 0x99, 0x6A, 0x3B, 0x37, 0x19, 0xD4, 0x40, 0xEA, 0xD7, 0x85, 0x16, 0x66, 0x1E, 0x9C, 0x39, 0xBB, 0xEE, 0x4A, 0x03, 0x8A, 0x36, 0x2D, 0x13, 0x1D, 0x56, 0x48, 0xC7, 0x0D, 0x59, 0xB2, 0x44, 0xA3, 0xFE, 0x8B, 0x32, 0x1B, 0x84, 0xA0, 0x2E, 0x62, 0x17, 0x42, 0xB9, 0x9B, 0x2B, 0x75, 0xD8, 0x1C, 0x3C, 0x4D, 0x76, 0x27, 0x6E, 0x28, 0xD3, 0x33, 0xC3, 0x21, 0xAF, 0x34, 0x23, 0xDD, 0x68, 0x9F, 0xF1, 0xAD, 0xE1, 0xB4, 0xE7, 0xA6, 0x74, 0x15, 0x4B, 0xFA, 0x3D, 0x5F, 0x7C, 0xDA, 0x2F, 0x0A, 0xE3, 0x7D, 0xC8, 0xB7, 0x12, 0x6F, 0x9E, 0xA9, 0x14, 0x53, 0x97, 0x8F, 0x64, 0xF4, 0xF8, 0xA2, 0xA4, 0x2A, 0xD2, 0x47, 0x9D, 0x71, 0xC5, 0xE9, 0x06, 0x98, 0x20, 0x54, 0x80, 0xAA, 0xF2, 0xAC, 0x50, 0xD6, 0x7F, 0xD9, 0xC9, 0xCD, 0x69, 0x46, 0x6D, 0x30, 0xB1, 0x58, 0x0B, 0x55, 0xD1, 0x5D, 0xD5, 0xBD, 0x31, 0xDE, 0xA5, 0xE4, 0x91, 0x0F, 0x61, 0x38, 0xDF, 0xA8, 0xE6, 0x3E, 0x1F, 0x35, 0xED, 0xDB, 0x94, 0xEB, 0x09, 0x5E, 0x95, 0xFB, 0xFC, 0xE0, 0x78, 0xFF} + _decryptKey = []byte{0x48, 0x37, 0x09, 0x76, 0x04, 0x47, 0xCC, 0x5C, 0x61, 0xF8, 0xB3, 0xE0, 0x1F, 0x7F, 0x2E, 0xEB, 0x4E, 0x33, 0xB8, 0x7A, 0xBC, 0xAB, 0x6E, 0x8C, 0x3F, 0x68, 0x0D, 0x87, 0x93, 0x7B, 0x70, 0xF2, 0xCE, 0x9D, 0x27, 0xA0, 0x1B, 0x03, 0x02, 0x97, 0x99, 0x58, 0xC5, 0x90, 0x1A, 0x79, 0x8A, 0xB2, 0xDD, 0xE6, 0x86, 0x9B, 0x9F, 0xF3, 0x78, 0x67, 0xED, 0x72, 0x30, 0x66, 0x94, 0xAE, 0xF1, 0x55, 0x6A, 0x0E, 0x8D, 0x5E, 0x82, 0x5A, 0xDB, 0xC7, 0x7D, 0x2C, 0x75, 0xAC, 0x07, 0x95, 0x4A, 0x2B, 0xD4, 0x01, 0x0A, 0xBD, 0xCF, 0xE1, 0x7C, 0x15, 0xDF, 0x80, 0x28, 0x3B, 0x2A, 0xE3, 0xF9, 0xAF, 0x29, 0xEC, 0x8B, 0x19, 0xC0, 0x39, 0x6F, 0x1D, 0xA2, 0xDA, 0x65, 0x34, 0x50, 0xDC, 0x98, 0xB9, 0x0C, 0xC9, 0x21, 0x5B, 0xAA, 0x91, 0x96, 0x42, 0xFE, 0x25, 0x0B, 0x24, 0xB0, 0xB5, 0x16, 0xD6, 0xD0, 0x31, 0x57, 0x18, 0x88, 0x6D, 0x1E, 0x54, 0x0F, 0x62, 0x77, 0x85, 0x10, 0x3A, 0x44, 0xBF, 0x00, 0xEA, 0x08, 0x3E, 0xF6, 0xFA, 0x59, 0xBE, 0xCD, 0x64, 0x1C, 0x8F, 0x71, 0xC8, 0xBA, 0xA3, 0x89, 0x36, 0xC3, 0x83, 0xC4, 0xE8, 0xA9, 0x4B, 0xEF, 0xBB, 0xD1, 0x41, 0xD3, 0xA5, 0x32, 0x9E, 0x26, 0xDE, 0x81, 0x40, 0xA7, 0x4D, 0x23, 0xB7, 0x13, 0x8E, 0x17, 0x73, 0x4C, 0xE5, 0x20, 0x05, 0x51, 0x56, 0x11, 0x9C, 0x52, 0xCA, 0x4F, 0x7E, 0xB6, 0xD8, 0x49, 0x5D, 0x3D, 0xD9, 0x12, 0x06, 0x63, 0xE2, 0xC6, 0x9A, 0x69, 0xE4, 0xD5, 0x6C, 0x92, 0xD7, 0xB1, 0xF5, 0x3C, 0xA1, 0xE7, 0xEE, 0xFD, 0xA6, 0x2D, 0xB4, 0xE9, 0x53, 0xF0, 0xA8, 0x38, 0xCB, 0x6B, 0xF7, 0x45, 0xF4, 0x74, 0x46, 0x35, 0xA4, 0xD2, 0x60, 0xC1, 0x2F, 0x14, 0x43, 0xC2, 0x5F, 0xAD, 0xFB, 0xFC, 0x22, 0x84, 0xFF} + _sharedCryptKey = []byte{0xDD, 0xA8, 0x5F, 0x1E, 0x57, 0xAF, 0xC0, 0xCC, 0x43, 0x35, 0x8F, 0xBB, 0x6F, 0xE6, 0xA1, 0xD6, 0x60, 0xB9, 0x1A, 0xAE, 0x20, 0x49, 0x24, 0x81, 0x21, 0xFE, 0x86, 0x2B, 0x98, 0xB7, 0xB3, 0xD2, 0x91, 0x01, 0x3A, 0x4C, 0x65, 0x92, 0x1C, 0xF4, 0xBE, 0xDD, 0xD9, 0x08, 0xE6, 0x81, 0x98, 0x1B, 0x8D, 0x60, 0xF3, 0x6F, 0xA1, 0x47, 0x24, 0xF1, 0x53, 0x45, 0xC8, 0x7B, 0x88, 0x80, 0x4E, 0x36, 0xC3, 0x0D, 0xC9, 0xD6, 0x8B, 0x08, 0x19, 0x0B, 0xA5, 0xC1, 0x11, 0x4C, 0x60, 0xF8, 0x5D, 0xFC, 0x15, 0x68, 0x7E, 0x32, 0xC0, 0x50, 0xAB, 0x64, 0x1F, 0x8A, 0xD4, 0x08, 0x39, 0x7F, 0xC2, 0xFB, 0xBA, 0x6C, 0xF0, 0xE6, 0xB0, 0x31, 0x10, 0xC1, 0xBF, 0x75, 0x43, 0xBB, 0x18, 0x04, 0x0D, 0xD1, 0x97, 0xF7, 0x23, 0x21, 0x83, 0x8B, 0xCA, 0x25, 0x2B, 0xA3, 0x03, 0x13, 0xEA, 0xAE, 0xFE, 0xF0, 0xEB, 0xFD, 0x85, 0x57, 0x53, 0x65, 0x41, 0x2A, 0x40, 0x99, 0xC0, 0x94, 0x65, 0x7E, 0x7C, 0x93, 0x82, 0xB0, 0xB3, 0xE5, 0xC0, 0x21, 0x09, 0x84, 0xD5, 0xEF, 0x9F, 0xD1, 0x7E, 0xDC, 0x4D, 0xF5, 0x7E, 0xCD, 0x45, 0x3C, 0x7F, 0xF5, 0x59, 0x98, 0xC6, 0x55, 0xFC, 0x9F, 0xA3, 0xB7, 0x74, 0xEE, 0x31, 0x98, 0xE6, 0xB7, 0xBE, 0x26, 0xF4, 0x3C, 0x76, 0xF1, 0x23, 0x7E, 0x02, 0x4E, 0x3C, 0xD1, 0xC7, 0x28, 0x23, 0x73, 0xC4, 0xD9, 0x5E, 0x0D, 0xA1, 0x80, 0xA5, 0xAA, 0x26, 0x0A, 0xA3, 0x44, 0x82, 0x74, 0xE6, 0x3C, 0x44, 0x27, 0x51, 0x0D, 0x5F, 0xC7, 0x9C, 0xD6, 0x63, 0x67, 0xA5, 0x27, 0x97, 0x38, 0xFB, 0x2D, 0xD3, 0xD6, 0x60, 0x25, 0x83, 0x4D, 0x37, 0x5B, 0x40, 0x59, 0x11, 0x77, 0x51, 0x11, 0x14, 0x18, 0x07, 0x63, 0xB1, 0x34, 0x3D, 0xB8, 0x60, 0x13, 0xC2, 0xE8, 0x13, 0x82} +) + +// Encrypt encrypts the given data using MHF's custom encryption+checksum method. +// if a overrideByteKey value is supplied (!= nil), it will be used to override the derived/truncated key byte. +func Encrypt(data []byte, key uint32, overrideByteKey *byte) (outputData []byte, combinedCheck uint16, check0 uint16, check1 uint16, check2 uint16) { + return _generalCrypt(data, key, 0, overrideByteKey) +} + +// Decrypt decrypts the given data using MHF's custom decryption+checksum method. +// if a overrideByteKey value is supplied (!= nil), it will be used to override the derived/truncated key byte. +func Decrypt(data []byte, key uint32, overrideByteKey *byte) (outputData []byte, combinedCheck uint16, check0 uint16, check1 uint16, check2 uint16) { + return _generalCrypt(data, key, 1, overrideByteKey) +} + +// _generalCrypt is a generalized MHF crypto function that can perform both encryption and decryption, +// these two crypto operations are combined into a single function because they shared most of their logic. +// encrypt: cryptType==0 +// decrypt: cryptType==1 +func _generalCrypt(data []byte, rotKey uint32, cryptType int, overrideByteKey *byte) ([]byte, uint16, uint16, uint16, uint16) { + cryptKeyTruncByte := byte(((rotKey >> 1) % 999983) & 0xFF) + if overrideByteKey != nil { + cryptKeyTruncByte = *overrideByteKey + } + + derivedCryptKey := int32((uint32(len(data)) * (uint32(cryptKeyTruncByte) + 1)) & 0xFFFFFFFF) + sharedBufIdx := byte(1) + accumulator0 := uint32(0) + accumulator1 := uint32(0) + accumulator2 := uint32(0) + + var outputData []byte + if cryptType == 0 { + for i := 0; i < len(data); i++ { + // Do the encryption for this iteration + encKeyIdx := int32(((uint32(derivedCryptKey) >> 10) ^ uint32(data[i])) & 0xFF) + derivedCryptKey = (0x4FD * (derivedCryptKey + 1)) + encKeyByte := _encryptKey[encKeyIdx] + + // Update the checksum accumulators. + accumulator2 = uint32((accumulator2 + (uint32(sharedBufIdx) * uint32(data[i]))) & 0xFFFFFFFF) + accumulator1 = uint32((accumulator1 + uint32(encKeyIdx)) & 0xFFFFFFFF) + accumulator0 = uint32((accumulator0 + (uint32(encKeyByte)<<(i&7))&0xFFFFFFFF) & 0xFFFFFFFF) + + // Append the output. + outputData = append(outputData, _sharedCryptKey[sharedBufIdx]^encKeyByte) + + // Update the sharedBufIdx for the next iteration. + sharedBufIdx = data[i] + } + + } else if cryptType == 1 { + for i := 0; i < len(data); i++ { + // Do the decryption for this iteration + oldSharedBufIdx := sharedBufIdx + tIdx := data[i] ^ _sharedCryptKey[sharedBufIdx] + decKeyByte := _decryptKey[tIdx] + sharedBufIdx = byte(((uint32(derivedCryptKey) >> 10) ^ uint32(decKeyByte)) & 0xFF) + + // Update the checksum accumulators. + accumulator0 = (accumulator0 + ((uint32(tIdx) << (i & 7)) & 0xFFFFFFFF)) + accumulator1 = (accumulator1 + uint32(decKeyByte)) & 0xFFFFFFFF + accumulator2 = (accumulator2 + ((uint32(oldSharedBufIdx) * uint32(sharedBufIdx)) & 0xFFFFFFFF)) & 0xFFFFFFFF + + // Append the output. + outputData = append(outputData, sharedBufIdx) + + // Update the key pos for next iteration. + derivedCryptKey = (0x4FD * (derivedCryptKey + 1)) + } + } + + combinedCheck := uint16((accumulator1 + (accumulator0 >> 1) + (accumulator2 >> 2)) & 0xFFFF) + check0 := uint16((accumulator0 ^ ((accumulator0 & 0xFFFF0000) >> 16)) & 0xFFFF) + check1 := uint16((accumulator1 ^ ((accumulator1 & 0xFFFF0000) >> 16)) & 0xFFFF) + check2 := uint16((accumulator2 ^ ((accumulator2 & 0xFFFF0000) >> 16)) & 0xFFFF) + + return outputData, combinedCheck, check0, check1, check2 +} diff --git a/Erupe/network/crypto/crypto_test.go b/Erupe/network/crypto/crypto_test.go new file mode 100644 index 000000000..32ff7ee7c --- /dev/null +++ b/Erupe/network/crypto/crypto_test.go @@ -0,0 +1,104 @@ +package crypto + +import ( + "bytes" + "encoding/hex" + "fmt" + "testing" +) + +var commonTestData = []byte{0x74, 0x65, 0x73, 0x74} +var tests = []struct { + decryptedData []byte + key uint32 + encryptedData []byte + ecc, ec0, ec1, ec2 uint16 +}{ + { + commonTestData, + 0, + []byte{0x46, 0x53, 0x28, 0x5E}, + 0x2976, 0x06ea, 0x0215, 0x08FB3, + }, + { + commonTestData, + 3, + []byte{0x46, 0x95, 0x88, 0xEA}, + 0x2AE4, 0x0A56, 0x01CD, 0x08FB3, + }, + /* + // TODO(Andoryuuta): This case fails. Debug the client and figure out if this is valid expected data. + { + commonTestData, + 995117, + []byte{0x46, 0x28, 0xFF, 0xAA}, + 0x2A22, 0x09D4, 0x014C, 0x08FB3, + }, + */ + { + commonTestData, + 0x7FFFFFFF, + []byte{0x46, 0x53, 0x28, 0x5E}, + 0x2976, 0x06ea, 0x0215, 0x08FB3, + }, + { + commonTestData, + 0x80000000, + []byte{0x46, 0x95, 0x88, 0xEA}, + 0x2AE4, 0x0A56, 0x01CD, 0x08FB3, + }, + { + commonTestData, + 0xFFFFFFFF, + []byte{0x46, 0xB5, 0xDC, 0xB2}, + 0x2ADD, 0x09A6, 0x021E, 0x08FB3, + }, + { + []byte{0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x00, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x12, 0x00, 0xDE, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x20, 0x18, 0x46, 0x00, 0x00, 0x80, 0x3F, 0xDC, 0xE4, 0x0A, 0x46, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x67, 0xD3, 0x5B, 0x00, 0x77, 0x01, 0x78, 0x00, 0x77, 0x01, 0x4F, 0x01, 0x5B, 0x6F, 0x76, 0xC5, 0x30, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xDD, 0x17, 0x46, 0x00, 0x00, 0x80, 0x3F, 0x9E, 0x11, 0x0C, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x37, 0x64, 0x00, 0x2C, 0x01, 0x64, 0x00, 0x2C, 0x01, 0x4F, 0x01, 0x5B, 0x6F, 0x76, 0xC5, 0x00, 0x10}, + 2000476, + []byte{0x2E, 0x52, 0x24, 0xE3, 0x05, 0x2B, 0xFC, 0x04, 0x0B, 0x26, 0x90, 0xEA, 0x61, 0xDB, 0x8D, 0x27, 0xCB, 0xB1, 0x69, 0xA1, 0x77, 0x80, 0x4A, 0xC2, 0xA0, 0xBD, 0x50, 0x54, 0xF5, 0xC2, 0x94, 0x66, 0xBB, 0xCE, 0x53, 0x29, 0xEE, 0xB4, 0xFA, 0xF6, 0x5F, 0x8D, 0x80, 0x3E, 0x5D, 0x5F, 0xB0, 0x53, 0xE6, 0x92, 0x17, 0x80, 0xE7, 0xED, 0xE7, 0xDC, 0x61, 0xF0, 0xCD, 0xE4, 0x41, 0x82, 0x21, 0xBA, 0x47, 0xAB, 0x58, 0xFF, 0x30, 0x76, 0x80, 0x2D, 0x38, 0xF4, 0xDF, 0x86, 0x8C, 0x6C, 0x8D, 0x33, 0x4C, 0x37, 0xA3, 0xDA, 0x01, 0x3C, 0x98, 0x66, 0x1F, 0xB9, 0xE2, 0xEA, 0xF0, 0x84, 0xE8, 0xAA, 0x00, 0x3D, 0x4A, 0xB6, 0xF2, 0x3D, 0x91, 0x58, 0x4B, 0x0B, 0xE2, 0xD5, 0xC7, 0x39, 0x4D, 0x59, 0xED, 0xC3, 0x61, 0x6F, 0x6E, 0x69, 0x9B, 0x3C}, + 0xCFF8, 0x086B, 0x3BAE, 0x4057, + }, +} + +func TestEncrypt(t *testing.T) { + for k, tt := range tests { + testname := fmt.Sprintf("encrypt_test_%d", k) + t.Run(testname, func(t *testing.T) { + out, cc, c0, c1, c2 := Encrypt(tt.decryptedData, tt.key, nil) + if cc != tt.ecc { + t.Errorf("got cc 0x%X, want 0x%X", cc, tt.ecc) + } else if c0 != tt.ec0 { + t.Errorf("got c0 0x%X, want 0x%X", c0, tt.ec0) + } else if c1 != tt.ec1 { + t.Errorf("got c1 0x%X, want 0x%X", c1, tt.ec1) + } else if c2 != tt.ec2 { + t.Errorf("got c2 0x%X, want 0x%X", c2, tt.ec2) + } else if !bytes.Equal(out, tt.encryptedData) { + t.Errorf("got out\n\t%s\nwant\n\t%s", hex.Dump(out), hex.Dump(tt.encryptedData)) + } + }) + } + +} + +func TestDecrypt(t *testing.T) { + for k, tt := range tests { + testname := fmt.Sprintf("decrypt_test_%d", k) + t.Run(testname, func(t *testing.T) { + out, cc, c0, c1, c2 := Decrypt(tt.encryptedData, tt.key, nil) + if cc != tt.ecc { + t.Errorf("got cc 0x%X, want 0x%X", cc, tt.ecc) + } else if c0 != tt.ec0 { + t.Errorf("got c0 0x%X, want 0x%X", c0, tt.ec0) + } else if c1 != tt.ec1 { + t.Errorf("got c1 0x%X, want 0x%X", c1, tt.ec1) + } else if c2 != tt.ec2 { + t.Errorf("got c2 0x%X, want 0x%X", c2, tt.ec2) + } else if !bytes.Equal(out, tt.decryptedData) { + t.Errorf("got out\n\t%s\nwant\n\t%s", hex.Dump(out), hex.Dump(tt.decryptedData)) + } + }) + } + +} diff --git a/Erupe/network/mhfpacket/mhfpacket.go b/Erupe/network/mhfpacket/mhfpacket.go new file mode 100644 index 000000000..ddf44ecd9 --- /dev/null +++ b/Erupe/network/mhfpacket/mhfpacket.go @@ -0,0 +1,29 @@ +package mhfpacket + +import ( + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// Parser is the interface that wraps the Parse method. +type Parser interface { + Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error +} + +// Builder is the interface that wraps the Build method. +type Builder interface { + Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error +} + +// Opcoder is the interface that wraps the Opcode method. +type Opcoder interface { + Opcode() network.PacketID +} + +// MHFPacket is the interface that groups the Parse, Build, and Opcode methods. +type MHFPacket interface { + Parser + Builder + Opcoder +} diff --git a/Erupe/network/mhfpacket/msg_ca_exchange_item.go b/Erupe/network/mhfpacket/msg_ca_exchange_item.go new file mode 100644 index 000000000..c5e7a9752 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_ca_exchange_item.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgCaExchangeItem represents the MSG_CA_EXCHANGE_ITEM +type MsgCaExchangeItem struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgCaExchangeItem) Opcode() network.PacketID { + return network.MSG_CA_EXCHANGE_ITEM +} + +// Parse parses the packet from binary +func (m *MsgCaExchangeItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgCaExchangeItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_head.go b/Erupe/network/mhfpacket/msg_head.go new file mode 100644 index 000000000..a8b566f27 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_head.go @@ -0,0 +1,28 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgHead represents the MSG_HEAD +type MsgHead struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgHead) Opcode() network.PacketID { + return network.MSG_HEAD +} + +// Parse parses the packet from binary +func (m *MsgHead) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgHead) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_accept_read_reward.go b/Erupe/network/mhfpacket/msg_mhf_accept_read_reward.go new file mode 100644 index 000000000..175207e38 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_accept_read_reward.go @@ -0,0 +1,28 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcceptReadReward represents the MSG_MHF_ACCEPT_READ_REWARD +type MsgMhfAcceptReadReward struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcceptReadReward) Opcode() network.PacketID { + return network.MSG_MHF_ACCEPT_READ_REWARD +} + +// Parse parses the packet from binary +func (m *MsgMhfAcceptReadReward) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcceptReadReward) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_cafe_item.go b/Erupe/network/mhfpacket/msg_mhf_acquire_cafe_item.go new file mode 100644 index 000000000..6585eb10b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_cafe_item.go @@ -0,0 +1,41 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireCafeItem represents the MSG_MHF_ACQUIRE_CAFE_ITEM +type MsgMhfAcquireCafeItem struct { + AckHandle uint32 + // Valid sizes, not sure if [un]signed. + ItemType uint16 + ItemID uint16 + Quant uint16 + PointCost uint32 + Unk0 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireCafeItem) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_CAFE_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireCafeItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.ItemType = bf.ReadUint16() + m.ItemID = bf.ReadUint16() + m.Quant = bf.ReadUint16() + m.PointCost = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireCafeItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_dist_item.go b/Erupe/network/mhfpacket/msg_mhf_acquire_dist_item.go new file mode 100644 index 000000000..218ea5b17 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_dist_item.go @@ -0,0 +1,35 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireDistItem represents the MSG_MHF_ACQUIRE_DIST_ITEM +type MsgMhfAcquireDistItem struct { + AckHandle uint32 + // Valid field size(s), not sure about the types. + Unk0 uint8 + Unk1 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireDistItem) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_DIST_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireDistItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireDistItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_exchange_shop.go b/Erupe/network/mhfpacket/msg_mhf_acquire_exchange_shop.go new file mode 100644 index 000000000..1d2f9e9af --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_exchange_shop.go @@ -0,0 +1,35 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireExchangeShop represents the MSG_MHF_ACQUIRE_EXCHANGE_SHOP +type MsgMhfAcquireExchangeShop struct { + AckHandle uint32 + DataSize uint16 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireExchangeShop) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_EXCHANGE_SHOP +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireExchangeShop) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireExchangeShop) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint16(m.DataSize) + bf.WriteBytes(m.RawDataPayload) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_festa.go b/Erupe/network/mhfpacket/msg_mhf_acquire_festa.go new file mode 100644 index 000000000..5f060d3e8 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_festa.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireFesta represents the MSG_MHF_ACQUIRE_FESTA +type MsgMhfAcquireFesta struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireFesta) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_FESTA +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireFesta) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireFesta) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_festa_intermediate_prize.go b/Erupe/network/mhfpacket/msg_mhf_acquire_festa_intermediate_prize.go new file mode 100644 index 000000000..b95fd88ff --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_festa_intermediate_prize.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireFestaIntermediatePrize represents the MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE +type MsgMhfAcquireFestaIntermediatePrize struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireFestaIntermediatePrize) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireFestaIntermediatePrize) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireFestaIntermediatePrize) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_festa_personal_prize.go b/Erupe/network/mhfpacket/msg_mhf_acquire_festa_personal_prize.go new file mode 100644 index 000000000..460dc2a77 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_festa_personal_prize.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireFestaPersonalPrize represents the MSG_MHF_ACQUIRE_FESTA_PERSONAL_PRIZE +type MsgMhfAcquireFestaPersonalPrize struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireFestaPersonalPrize) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_FESTA_PERSONAL_PRIZE +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireFestaPersonalPrize) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireFestaPersonalPrize) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_guild_adventure.go b/Erupe/network/mhfpacket/msg_mhf_acquire_guild_adventure.go new file mode 100644 index 000000000..d65bb562d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_guild_adventure.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireGuildAdventure represents the MSG_MHF_ACQUIRE_GUILD_ADVENTURE +type MsgMhfAcquireGuildAdventure struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireGuildAdventure) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_GUILD_ADVENTURE +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireGuildAdventure) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireGuildAdventure) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_guild_tresure.go b/Erupe/network/mhfpacket/msg_mhf_acquire_guild_tresure.go new file mode 100644 index 000000000..2419e4f2b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_guild_tresure.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireGuildTresure represents the MSG_MHF_ACQUIRE_GUILD_TRESURE +type MsgMhfAcquireGuildTresure struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireGuildTresure) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_GUILD_TRESURE +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireGuildTresure) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireGuildTresure) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_guild_tresure_souvenir.go b/Erupe/network/mhfpacket/msg_mhf_acquire_guild_tresure_souvenir.go new file mode 100644 index 000000000..c1dde0b4f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_guild_tresure_souvenir.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireGuildTresureSouvenir represents the MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR +type MsgMhfAcquireGuildTresureSouvenir struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireGuildTresureSouvenir) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireGuildTresureSouvenir) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireGuildTresureSouvenir) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_item.go b/Erupe/network/mhfpacket/msg_mhf_acquire_item.go new file mode 100644 index 000000000..8cd82a899 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_item.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireItem represents the MSG_MHF_ACQUIRE_ITEM +type MsgMhfAcquireItem struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireItem) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_monthly_item.go b/Erupe/network/mhfpacket/msg_mhf_acquire_monthly_item.go new file mode 100644 index 000000000..6b38c63ec --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_monthly_item.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireMonthlyItem represents the MSG_MHF_ACQUIRE_MONTHLY_ITEM +type MsgMhfAcquireMonthlyItem struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireMonthlyItem) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_MONTHLY_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireMonthlyItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireMonthlyItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_monthly_reward.go b/Erupe/network/mhfpacket/msg_mhf_acquire_monthly_reward.go new file mode 100644 index 000000000..c6bce8b06 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_monthly_reward.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireMonthlyReward represents the MSG_MHF_ACQUIRE_MONTHLY_REWARD +type MsgMhfAcquireMonthlyReward struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireMonthlyReward) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_MONTHLY_REWARD +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireMonthlyReward) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireMonthlyReward) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_title.go b/Erupe/network/mhfpacket/msg_mhf_acquire_title.go new file mode 100644 index 000000000..0d88a0d0a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_title.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireTitle represents the MSG_MHF_ACQUIRE_TITLE +type MsgMhfAcquireTitle struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireTitle) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_TITLE +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireTitle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireTitle) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_tournament.go b/Erupe/network/mhfpacket/msg_mhf_acquire_tournament.go new file mode 100644 index 000000000..8ce708a2d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_tournament.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireTournament represents the MSG_MHF_ACQUIRE_TOURNAMENT +type MsgMhfAcquireTournament struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireTournament) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_TOURNAMENT +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireTournament) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireTournament) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_acquire_ud_item.go b/Erupe/network/mhfpacket/msg_mhf_acquire_ud_item.go new file mode 100644 index 000000000..d8e8600dc --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_acquire_ud_item.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAcquireUdItem represents the MSG_MHF_ACQUIRE_UD_ITEM +type MsgMhfAcquireUdItem struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAcquireUdItem) Opcode() network.PacketID { + return network.MSG_MHF_ACQUIRE_UD_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfAcquireUdItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAcquireUdItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_add_achievement.go b/Erupe/network/mhfpacket/msg_mhf_add_achievement.go new file mode 100644 index 000000000..4cd03a73a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_add_achievement.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAddAchievement represents the MSG_MHF_ADD_ACHIEVEMENT +type MsgMhfAddAchievement struct { + Unk0 uint8 + Unk1 uint16 + Unk2 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAddAchievement) Opcode() network.PacketID { + return network.MSG_MHF_ADD_ACHIEVEMENT +} + +// Parse parses the packet from binary +func (m *MsgMhfAddAchievement) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint16() + m.Unk2 = bf.ReadUint16() + // doesn't expect a response + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAddAchievement) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint8(m.Unk0) + bf.WriteUint16(m.Unk1) + bf.WriteUint16(m.Unk2) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_add_guild_mission_count.go b/Erupe/network/mhfpacket/msg_mhf_add_guild_mission_count.go new file mode 100644 index 000000000..64efad5dc --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_add_guild_mission_count.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAddGuildMissionCount represents the MSG_MHF_ADD_GUILD_MISSION_COUNT +type MsgMhfAddGuildMissionCount struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAddGuildMissionCount) Opcode() network.PacketID { + return network.MSG_MHF_ADD_GUILD_MISSION_COUNT +} + +// Parse parses the packet from binary +func (m *MsgMhfAddGuildMissionCount) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAddGuildMissionCount) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_add_guild_weekly_bonus_exceptional_user.go b/Erupe/network/mhfpacket/msg_mhf_add_guild_weekly_bonus_exceptional_user.go new file mode 100644 index 000000000..9b024fef4 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_add_guild_weekly_bonus_exceptional_user.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAddGuildWeeklyBonusExceptionalUser represents the MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER +type MsgMhfAddGuildWeeklyBonusExceptionalUser struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAddGuildWeeklyBonusExceptionalUser) Opcode() network.PacketID { + return network.MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER +} + +// Parse parses the packet from binary +func (m *MsgMhfAddGuildWeeklyBonusExceptionalUser) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAddGuildWeeklyBonusExceptionalUser) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_add_kouryou_point.go b/Erupe/network/mhfpacket/msg_mhf_add_kouryou_point.go new file mode 100644 index 000000000..b3a92a1d2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_add_kouryou_point.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAddKouryouPoint represents the MSG_MHF_ADD_KOURYOU_POINT +type MsgMhfAddKouryouPoint struct { + AckHandle uint32 + KouryouPoints uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAddKouryouPoint) Opcode() network.PacketID { + return network.MSG_MHF_ADD_KOURYOU_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfAddKouryouPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.KouryouPoints = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAddKouryouPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint32(m.KouryouPoints) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_add_reward_song_count.go b/Erupe/network/mhfpacket/msg_mhf_add_reward_song_count.go new file mode 100644 index 000000000..e3752b570 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_add_reward_song_count.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAddRewardSongCount represents the MSG_MHF_ADD_REWARD_SONG_COUNT +type MsgMhfAddRewardSongCount struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAddRewardSongCount) Opcode() network.PacketID { + return network.MSG_MHF_ADD_REWARD_SONG_COUNT +} + +// Parse parses the packet from binary +func (m *MsgMhfAddRewardSongCount) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAddRewardSongCount) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_add_ud_point.go b/Erupe/network/mhfpacket/msg_mhf_add_ud_point.go new file mode 100644 index 000000000..621491c97 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_add_ud_point.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAddUdPoint represents the MSG_MHF_ADD_UD_POINT +type MsgMhfAddUdPoint struct { + AckHandle uint32 + Unk1 uint32 + Unk2 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAddUdPoint) Opcode() network.PacketID { + return network.MSG_MHF_ADD_UD_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfAddUdPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + + return nil + //panic("Not implemented") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAddUdPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_add_ud_tactics_point.go b/Erupe/network/mhfpacket/msg_mhf_add_ud_tactics_point.go new file mode 100644 index 000000000..9beeb90c7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_add_ud_tactics_point.go @@ -0,0 +1,35 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAddUdTacticsPoint represents the MSG_MHF_ADD_UD_TACTICS_POINT +type MsgMhfAddUdTacticsPoint struct { + AckHandle uint32 + Unk0 uint16 + Unk1 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAddUdTacticsPoint) Opcode() network.PacketID { + return network.MSG_MHF_ADD_UD_TACTICS_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfAddUdTacticsPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAddUdTacticsPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint16(m.Unk0) + bf.WriteUint32(m.Unk1) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_announce.go b/Erupe/network/mhfpacket/msg_mhf_announce.go new file mode 100644 index 000000000..5030d5c96 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_announce.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAnnounce represents the MSG_MHF_ANNOUNCE +type MsgMhfAnnounce struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAnnounce) Opcode() network.PacketID { + return network.MSG_MHF_ANNOUNCE +} + +// Parse parses the packet from binary +func (m *MsgMhfAnnounce) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAnnounce) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_answer_guild_scout.go b/Erupe/network/mhfpacket/msg_mhf_answer_guild_scout.go new file mode 100644 index 000000000..099235857 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_answer_guild_scout.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfAnswerGuildScout represents the MSG_MHF_ANSWER_GUILD_SCOUT +type MsgMhfAnswerGuildScout struct { + AckHandle uint32 + LeaderID uint32 + Answer bool +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfAnswerGuildScout) Opcode() network.PacketID { + return network.MSG_MHF_ANSWER_GUILD_SCOUT +} + +// Parse parses the packet from binary +func (m *MsgMhfAnswerGuildScout) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.LeaderID = bf.ReadUint32() + m.Answer = bf.ReadBool() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfAnswerGuildScout) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_apply_bbs_article.go b/Erupe/network/mhfpacket/msg_mhf_apply_bbs_article.go new file mode 100644 index 000000000..2a42d4449 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_apply_bbs_article.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfApplyBbsArticle represents the MSG_MHF_APPLY_BBS_ARTICLE +type MsgMhfApplyBbsArticle struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfApplyBbsArticle) Opcode() network.PacketID { + return network.MSG_MHF_APPLY_BBS_ARTICLE +} + +// Parse parses the packet from binary +func (m *MsgMhfApplyBbsArticle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfApplyBbsArticle) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_apply_campaign.go b/Erupe/network/mhfpacket/msg_mhf_apply_campaign.go new file mode 100644 index 000000000..962278f55 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_apply_campaign.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfApplyCampaign represents the MSG_MHF_APPLY_CAMPAIGN +type MsgMhfApplyCampaign struct { + AckHandle uint32 + Unk0 uint8 + Unk1 uint8 + Unk2 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfApplyCampaign) Opcode() network.PacketID { + return network.MSG_MHF_APPLY_CAMPAIGN +} + +// Parse parses the packet from binary +func (m *MsgMhfApplyCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfApplyCampaign) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint8(m.Unk0) + bf.WriteUint8(m.Unk1) + bf.WriteUint16(m.Unk2) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_apply_dist_item.go b/Erupe/network/mhfpacket/msg_mhf_apply_dist_item.go new file mode 100644 index 000000000..8e5f43558 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_apply_dist_item.go @@ -0,0 +1,41 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfApplyDistItem represents the MSG_MHF_APPLY_DIST_ITEM +type MsgMhfApplyDistItem struct { + AckHandle uint32 + Unk0 uint8 + RequestType uint32 + Unk2 uint32 + Unk3 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfApplyDistItem) Opcode() network.PacketID { + return network.MSG_MHF_APPLY_DIST_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfApplyDistItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.RequestType = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + m.Unk3 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfApplyDistItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint8(m.Unk0) + bf.WriteUint32(m.RequestType) + bf.WriteUint32(m.Unk2) + bf.WriteUint32(m.Unk3) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_arrange_guild_member.go b/Erupe/network/mhfpacket/msg_mhf_arrange_guild_member.go new file mode 100644 index 000000000..8382d4856 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_arrange_guild_member.go @@ -0,0 +1,47 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfArrangeGuildMember represents the MSG_MHF_ARRANGE_GUILD_MEMBER +type MsgMhfArrangeGuildMember struct { + AckHandle uint32 + GuildID uint32 + CharIDs []uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfArrangeGuildMember) Opcode() network.PacketID { + return network.MSG_MHF_ARRANGE_GUILD_MEMBER +} + +// Parse parses the packet from binary +func (m *MsgMhfArrangeGuildMember) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GuildID = bf.ReadUint32() + charCount := bf.ReadUint16() + + m.CharIDs = make([]uint32, charCount) + + for i := uint16(0); i < charCount; i++ { + m.CharIDs[i] = bf.ReadUint32() + } + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfArrangeGuildMember) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint32(m.GuildID) + bf.WriteUint16(uint16(len(m.CharIDs))) + + for _, charID := range m.CharIDs { + bf.WriteUint32(charID) + } + + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_cancel_guild_mission_target.go b/Erupe/network/mhfpacket/msg_mhf_cancel_guild_mission_target.go new file mode 100644 index 000000000..dfe4b5a21 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_cancel_guild_mission_target.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfCancelGuildMissionTarget represents the MSG_MHF_CANCEL_GUILD_MISSION_TARGET +type MsgMhfCancelGuildMissionTarget struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCancelGuildMissionTarget) Opcode() network.PacketID { + return network.MSG_MHF_CANCEL_GUILD_MISSION_TARGET +} + +// Parse parses the packet from binary +func (m *MsgMhfCancelGuildMissionTarget) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfCancelGuildMissionTarget) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_cancel_guild_scout.go b/Erupe/network/mhfpacket/msg_mhf_cancel_guild_scout.go new file mode 100644 index 000000000..784eb453d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_cancel_guild_scout.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfCancelGuildScout represents the MSG_MHF_CANCEL_GUILD_SCOUT +type MsgMhfCancelGuildScout struct { + AckHandle uint32 + InvitationID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCancelGuildScout) Opcode() network.PacketID { + return network.MSG_MHF_CANCEL_GUILD_SCOUT +} + +// Parse parses the packet from binary +func (m *MsgMhfCancelGuildScout) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.InvitationID = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfCancelGuildScout) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_caravan_my_rank.go b/Erupe/network/mhfpacket/msg_mhf_caravan_my_rank.go new file mode 100644 index 000000000..e86495fba --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_caravan_my_rank.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfCaravanMyRank represents the MSG_MHF_CARAVAN_MY_RANK +type MsgMhfCaravanMyRank struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCaravanMyRank) Opcode() network.PacketID { + return network.MSG_MHF_CARAVAN_MY_RANK +} + +// Parse parses the packet from binary +func (m *MsgMhfCaravanMyRank) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfCaravanMyRank) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_caravan_my_score.go b/Erupe/network/mhfpacket/msg_mhf_caravan_my_score.go new file mode 100644 index 000000000..9d749153b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_caravan_my_score.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfCaravanMyScore represents the MSG_MHF_CARAVAN_MY_SCORE +type MsgMhfCaravanMyScore struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCaravanMyScore) Opcode() network.PacketID { + return network.MSG_MHF_CARAVAN_MY_SCORE +} + +// Parse parses the packet from binary +func (m *MsgMhfCaravanMyScore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfCaravanMyScore) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_caravan_ranking.go b/Erupe/network/mhfpacket/msg_mhf_caravan_ranking.go new file mode 100644 index 000000000..cf4097d42 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_caravan_ranking.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfCaravanRanking represents the MSG_MHF_CARAVAN_RANKING +type MsgMhfCaravanRanking struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCaravanRanking) Opcode() network.PacketID { + return network.MSG_MHF_CARAVAN_RANKING +} + +// Parse parses the packet from binary +func (m *MsgMhfCaravanRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfCaravanRanking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_charge_festa.go b/Erupe/network/mhfpacket/msg_mhf_charge_festa.go new file mode 100644 index 000000000..8bef13ad1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_charge_festa.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfChargeFesta represents the MSG_MHF_CHARGE_FESTA +type MsgMhfChargeFesta struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfChargeFesta) Opcode() network.PacketID { + return network.MSG_MHF_CHARGE_FESTA +} + +// Parse parses the packet from binary +func (m *MsgMhfChargeFesta) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfChargeFesta) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_charge_guild_adventure.go b/Erupe/network/mhfpacket/msg_mhf_charge_guild_adventure.go new file mode 100644 index 000000000..aa1875506 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_charge_guild_adventure.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfChargeGuildAdventure represents the MSG_MHF_CHARGE_GUILD_ADVENTURE +type MsgMhfChargeGuildAdventure struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfChargeGuildAdventure) Opcode() network.PacketID { + return network.MSG_MHF_CHARGE_GUILD_ADVENTURE +} + +// Parse parses the packet from binary +func (m *MsgMhfChargeGuildAdventure) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfChargeGuildAdventure) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_check_daily_cafepoint.go b/Erupe/network/mhfpacket/msg_mhf_check_daily_cafepoint.go new file mode 100644 index 000000000..84d8e73ea --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_check_daily_cafepoint.go @@ -0,0 +1,31 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfCheckDailyCafepoint represents the MSG_MHF_CHECK_DAILY_CAFEPOINT +type MsgMhfCheckDailyCafepoint struct { + AckHandle uint32 + Unk uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCheckDailyCafepoint) Opcode() network.PacketID { + return network.MSG_MHF_CHECK_DAILY_CAFEPOINT +} + +// Parse parses the packet from binary +func (m *MsgMhfCheckDailyCafepoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk = bf.ReadUint32() + return nil +} + +func (m *MsgMhfCheckDailyCafepoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint32(m.Unk) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_check_monthly_item.go b/Erupe/network/mhfpacket/msg_mhf_check_monthly_item.go new file mode 100644 index 000000000..5a8222cbb --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_check_monthly_item.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfCheckMonthlyItem represents the MSG_MHF_CHECK_MONTHLY_ITEM +type MsgMhfCheckMonthlyItem struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCheckMonthlyItem) Opcode() network.PacketID { + return network.MSG_MHF_CHECK_MONTHLY_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfCheckMonthlyItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfCheckMonthlyItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_check_weekly_stamp.go b/Erupe/network/mhfpacket/msg_mhf_check_weekly_stamp.go new file mode 100644 index 000000000..b77fbb17e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_check_weekly_stamp.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfCheckWeeklyStamp represents the MSG_MHF_CHECK_WEEKLY_STAMP +type MsgMhfCheckWeeklyStamp struct { + AckHandle uint32 + Unk0 uint8 + Unk1 bool + Unk2 uint16 // Hardcoded 0 in the binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCheckWeeklyStamp) Opcode() network.PacketID { + return network.MSG_MHF_CHECK_WEEKLY_STAMP +} + +// Parse parses the packet from binary +func (m *MsgMhfCheckWeeklyStamp) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadBool() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfCheckWeeklyStamp) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint8(m.Unk0) + bf.WriteBool(m.Unk1) + bf.WriteUint16(m.Unk2) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_contract_mercenary.go b/Erupe/network/mhfpacket/msg_mhf_contract_mercenary.go new file mode 100644 index 000000000..1b295dded --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_contract_mercenary.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfContractMercenary represents the MSG_MHF_CONTRACT_MERCENARY +type MsgMhfContractMercenary struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfContractMercenary) Opcode() network.PacketID { + return network.MSG_MHF_CONTRACT_MERCENARY +} + +// Parse parses the packet from binary +func (m *MsgMhfContractMercenary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfContractMercenary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_create_guild.go b/Erupe/network/mhfpacket/msg_mhf_create_guild.go new file mode 100644 index 000000000..ff2b2a18a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_create_guild.go @@ -0,0 +1,40 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgMhfCreateGuild represents the MSG_MHF_CREATE_GUILD +type MsgMhfCreateGuild struct { + AckHandle uint32 + Unk0 uint8 + Unk1 uint8 + Name string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCreateGuild) Opcode() network.PacketID { + return network.MSG_MHF_CREATE_GUILD +} + +// Parse parses the packet from binary +func (m *MsgMhfCreateGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + nameLength := bf.ReadUint16() + nameBytes := bfutil.UpToNull(bf.ReadBytes(uint(nameLength))) + m.Name = ctx.StrConv.MustDecode(nameBytes) + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfCreateGuild) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_create_joint.go b/Erupe/network/mhfpacket/msg_mhf_create_joint.go new file mode 100644 index 000000000..2436c8895 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_create_joint.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfCreateJoint represents the MSG_MHF_CREATE_JOINT +type MsgMhfCreateJoint struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCreateJoint) Opcode() network.PacketID { + return network.MSG_MHF_CREATE_JOINT +} + +// Parse parses the packet from binary +func (m *MsgMhfCreateJoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfCreateJoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_create_mercenary.go b/Erupe/network/mhfpacket/msg_mhf_create_mercenary.go new file mode 100644 index 000000000..b43ad0580 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_create_mercenary.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfCreateMercenary represents the MSG_MHF_CREATE_MERCENARY +type MsgMhfCreateMercenary struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfCreateMercenary) Opcode() network.PacketID { + return network.MSG_MHF_CREATE_MERCENARY +} + +// Parse parses the packet from binary +func (m *MsgMhfCreateMercenary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfCreateMercenary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_debug_post_value.go b/Erupe/network/mhfpacket/msg_mhf_debug_post_value.go new file mode 100644 index 000000000..00b2d1eb6 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_debug_post_value.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfDebugPostValue represents the MSG_MHF_DEBUG_POST_VALUE +type MsgMhfDebugPostValue struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfDebugPostValue) Opcode() network.PacketID { + return network.MSG_MHF_DEBUG_POST_VALUE +} + +// Parse parses the packet from binary +func (m *MsgMhfDebugPostValue) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfDebugPostValue) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_displayed_achievement.go b/Erupe/network/mhfpacket/msg_mhf_displayed_achievement.go new file mode 100644 index 000000000..3b82a935f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_displayed_achievement.go @@ -0,0 +1,29 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfDisplayedAchievement represents the MSG_MHF_DISPLAYED_ACHIEVEMENT +type MsgMhfDisplayedAchievement struct { + Unk0 uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfDisplayedAchievement) Opcode() network.PacketID { + return network.MSG_MHF_DISPLAYED_ACHIEVEMENT +} + +// Parse parses the packet from binary +func (m *MsgMhfDisplayedAchievement) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.Unk0 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfDisplayedAchievement) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint8(m.Unk0) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enter_tournament_quest.go b/Erupe/network/mhfpacket/msg_mhf_enter_tournament_quest.go new file mode 100644 index 000000000..916daaa08 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enter_tournament_quest.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnterTournamentQuest represents the MSG_MHF_ENTER_TOURNAMENT_QUEST +type MsgMhfEnterTournamentQuest struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnterTournamentQuest) Opcode() network.PacketID { + return network.MSG_MHF_ENTER_TOURNAMENT_QUEST +} + +// Parse parses the packet from binary +func (m *MsgMhfEnterTournamentQuest) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnterTournamentQuest) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_entry_festa.go b/Erupe/network/mhfpacket/msg_mhf_entry_festa.go new file mode 100644 index 000000000..9088f9780 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_entry_festa.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEntryFesta represents the MSG_MHF_ENTRY_FESTA +type MsgMhfEntryFesta struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEntryFesta) Opcode() network.PacketID { + return network.MSG_MHF_ENTRY_FESTA +} + +// Parse parses the packet from binary +func (m *MsgMhfEntryFesta) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEntryFesta) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_entry_rookie_guild.go b/Erupe/network/mhfpacket/msg_mhf_entry_rookie_guild.go new file mode 100644 index 000000000..2c0b2b7bf --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_entry_rookie_guild.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEntryRookieGuild represents the MSG_MHF_ENTRY_ROOKIE_GUILD +type MsgMhfEntryRookieGuild struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEntryRookieGuild) Opcode() network.PacketID { + return network.MSG_MHF_ENTRY_ROOKIE_GUILD +} + +// Parse parses the packet from binary +func (m *MsgMhfEntryRookieGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEntryRookieGuild) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_entry_tournament.go b/Erupe/network/mhfpacket/msg_mhf_entry_tournament.go new file mode 100644 index 000000000..e2f01b219 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_entry_tournament.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEntryTournament represents the MSG_MHF_ENTRY_TOURNAMENT +type MsgMhfEntryTournament struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEntryTournament) Opcode() network.PacketID { + return network.MSG_MHF_ENTRY_TOURNAMENT +} + +// Parse parses the packet from binary +func (m *MsgMhfEntryTournament) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEntryTournament) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_airoulist.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_airoulist.go new file mode 100644 index 000000000..493b581a8 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_airoulist.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateAiroulist represents the MSG_MHF_ENUMERATE_AIROULIST +type MsgMhfEnumerateAiroulist struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateAiroulist) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_AIROULIST +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateAiroulist) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateAiroulist) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_campaign.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_campaign.go new file mode 100644 index 000000000..d2eb7191c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_campaign.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateCampaign represents the MSG_MHF_ENUMERATE_CAMPAIGN +type MsgMhfEnumerateCampaign struct { + AckHandle uint32 + Unk0 uint8 + Unk1 uint8 + Unk2 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateCampaign) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_CAMPAIGN +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateCampaign) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint8(m.Unk0) + bf.WriteUint8(m.Unk1) + bf.WriteUint16(m.Unk2) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_dist_item.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_dist_item.go new file mode 100644 index 000000000..51d163360 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_dist_item.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateDistItem represents the MSG_MHF_ENUMERATE_DIST_ITEM +type MsgMhfEnumerateDistItem struct { + AckHandle uint32 + Unk0 uint8 + Unk1 uint16 + Unk2 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateDistItem) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_DIST_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateDistItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint16() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateDistItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint8(m.Unk0) + bf.WriteUint16(m.Unk1) + bf.WriteUint16(m.Unk2) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_event.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_event.go new file mode 100644 index 000000000..492f2f2a1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_event.go @@ -0,0 +1,35 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateEvent represents the MSG_MHF_ENUMERATE_EVENT +type MsgMhfEnumerateEvent struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 0 in the binary + Unk1 uint16 // Hardcoded 0 in the binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateEvent) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_EVENT +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateEvent) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateEvent) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint16(m.Unk0) + bf.WriteUint16(m.Unk1) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_festa_intermediate_prize.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_festa_intermediate_prize.go new file mode 100644 index 000000000..7dc2e9542 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_festa_intermediate_prize.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateFestaIntermediatePrize represents the MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE +type MsgMhfEnumerateFestaIntermediatePrize struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateFestaIntermediatePrize) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateFestaIntermediatePrize) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateFestaIntermediatePrize) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_festa_member.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_festa_member.go new file mode 100644 index 000000000..15d794712 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_festa_member.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateFestaMember represents the MSG_MHF_ENUMERATE_FESTA_MEMBER +type MsgMhfEnumerateFestaMember struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateFestaMember) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_FESTA_MEMBER +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateFestaMember) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateFestaMember) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_festa_personal_prize.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_festa_personal_prize.go new file mode 100644 index 000000000..fa1a09632 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_festa_personal_prize.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateFestaPersonalPrize represents the MSG_MHF_ENUMERATE_FESTA_PERSONAL_PRIZE +type MsgMhfEnumerateFestaPersonalPrize struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateFestaPersonalPrize) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_FESTA_PERSONAL_PRIZE +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateFestaPersonalPrize) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateFestaPersonalPrize) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_guacot.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_guacot.go new file mode 100644 index 000000000..5682b677b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_guacot.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateGuacot represents the MSG_MHF_ENUMERATE_GUACOT +type MsgMhfEnumerateGuacot struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 0 in binary + Unk1 uint16 // Hardcoded 0 in binary + Unk2 uint16 // Hardcoded 0 in binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateGuacot) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_GUACOT +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateGuacot) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateGuacot) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint16(m.Unk0) + bf.WriteUint16(m.Unk1) + bf.WriteUint16(m.Unk2) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_guild.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_guild.go new file mode 100644 index 000000000..0fb4e4446 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_guild.go @@ -0,0 +1,50 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +type EnumerateGuildType uint8 + +const ( + _ = iota + ENUMERATE_GUILD_TYPE_NAME + //Numbers correspond to order in guild search menu + ENUMERATE_GUILD_TYPE_6 + ENUMERATE_GUILD_TYPE_LEADER_ID + ENUMERATE_GUILD_TYPE_3 + ENUMERATE_GUILD_TYPE_2 + ENUMERATE_GUILD_TYPE_7 + ENUMERATE_GUILD_TYPE_8 + ENUMERATE_GUILD_TYPE_NEW +) + +// MsgMhfEnumerateGuild represents the MSG_MHF_ENUMERATE_GUILD +type MsgMhfEnumerateGuild struct { + AckHandle uint32 + Type uint8 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateGuild) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_GUILD +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Type = bf.ReadUint8() + m.RawDataPayload = bf.DataFromCurrent() + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateGuild) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_guild_item.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_guild_item.go new file mode 100644 index 000000000..9f39b5b79 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_guild_item.go @@ -0,0 +1,31 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateGuildItem represents the MSG_MHF_ENUMERATE_GUILD_ITEM +type MsgMhfEnumerateGuildItem struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateGuildItem) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_GUILD_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateGuildItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateGuildItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_guild_member.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_guild_member.go new file mode 100644 index 000000000..206189acf --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_guild_member.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateGuildMember represents the MSG_MHF_ENUMERATE_GUILD_MEMBER +type MsgMhfEnumerateGuildMember struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 00 01 in the binary + Unk1 uint32 // Alliance related + GuildID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateGuildMember) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_GUILD_MEMBER +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateGuildMember) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint32() + m.GuildID = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateGuildMember) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint16(m.Unk0) + bf.WriteUint32(m.Unk1) + bf.WriteUint32(m.GuildID) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_guild_tresure.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_guild_tresure.go new file mode 100644 index 000000000..198cbee8d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_guild_tresure.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateGuildTresure represents the MSG_MHF_ENUMERATE_GUILD_TRESURE +type MsgMhfEnumerateGuildTresure struct{ + AckHandle uint32 + Unk0 uint16 + Unk1 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateGuildTresure) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_GUILD_TRESURE +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateGuildTresure) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateGuildTresure) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_house.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_house.go new file mode 100644 index 000000000..41653e646 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_house.go @@ -0,0 +1,41 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateHouse represents the MSG_MHF_ENUMERATE_HOUSE +type MsgMhfEnumerateHouse struct { + AckHandle uint32 + Unk0 uint8 + Unk1 uint32 + Player uint8 + Unk2 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateHouse) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_HOUSE +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateHouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint32() + m.Player = bf.ReadUint8() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateHouse) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint8(m.Unk0) + bf.WriteUint32(m.Unk1) + bf.WriteUint8(m.Player) + bf.WriteUint16(m.Unk2) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_inv_guild.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_inv_guild.go new file mode 100644 index 000000000..762c37aa0 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_inv_guild.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateInvGuild represents the MSG_MHF_ENUMERATE_INV_GUILD +type MsgMhfEnumerateInvGuild struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateInvGuild) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_INV_GUILD +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateInvGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateInvGuild) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_item.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_item.go new file mode 100644 index 000000000..069975821 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_item.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateItem represents the MSG_MHF_ENUMERATE_ITEM +type MsgMhfEnumerateItem struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateItem) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_mercenary_log.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_mercenary_log.go new file mode 100644 index 000000000..3a20fecf0 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_mercenary_log.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateMercenaryLog represents the MSG_MHF_ENUMERATE_MERCENARY_LOG +type MsgMhfEnumerateMercenaryLog struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateMercenaryLog) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_MERCENARY_LOG +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateMercenaryLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateMercenaryLog) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_order.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_order.go new file mode 100644 index 000000000..e9a529afa --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_order.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateOrder represents the MSG_MHF_ENUMERATE_ORDER +type MsgMhfEnumerateOrder struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateOrder) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_ORDER +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateOrder) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateOrder) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_price.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_price.go new file mode 100644 index 000000000..af5fa025a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_price.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumeratePrice represents the MSG_MHF_ENUMERATE_PRICE +type MsgMhfEnumeratePrice struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 0 in the binary + Unk1 uint16 // Hardcoded 0 in the binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumeratePrice) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_PRICE +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumeratePrice) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumeratePrice) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_quest.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_quest.go new file mode 100644 index 000000000..77a48a43e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_quest.go @@ -0,0 +1,40 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateQuest represents the MSG_MHF_ENUMERATE_QUEST +type MsgMhfEnumerateQuest struct { + AckHandle uint32 + Unk0 uint8 // Hardcoded 0 in the binary + Unk1 uint8 + Unk2 uint16 + QuestList uint16 // Increments to request following batches of quests + Unk4 uint8 // Hardcoded 0 in the binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateQuest) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_QUEST +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateQuest) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + m.Unk2 = bf.ReadUint16() + m.QuestList = bf.ReadUint16() + m.Unk4 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateQuest) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_ranking.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_ranking.go new file mode 100644 index 000000000..c63e84008 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_ranking.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateRanking represents the MSG_MHF_ENUMERATE_RANKING +type MsgMhfEnumerateRanking struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 0 in the binary + Unk1 uint16 // Hardcoded 0 in the binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateRanking) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_RANKING +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateRanking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_rengoku_ranking.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_rengoku_ranking.go new file mode 100644 index 000000000..a7b895c46 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_rengoku_ranking.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateRengokuRanking represents the MSG_MHF_ENUMERATE_RENGOKU_RANKING +type MsgMhfEnumerateRengokuRanking struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint16 // Hardcoded 0 in the binary + Unk2 uint16 // Hardcoded 00 01 in the binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateRengokuRanking) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_RENGOKU_RANKING +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateRengokuRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint16() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateRengokuRanking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_shop.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_shop.go new file mode 100644 index 000000000..f0d78f637 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_shop.go @@ -0,0 +1,42 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateShop represents the MSG_MHF_ENUMERATE_SHOP +type MsgMhfEnumerateShop struct { + AckHandle uint32 + ShopType uint8 // 1 running gachas, 10 normal shop extensions, 8 Diva Defense shop + ShopID uint32 + Unk2 uint16 // 00 80 running gachas, 00 20 normal shop + Unk3 uint8 + Unk4 uint8 + Unk5 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateShop) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_SHOP +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateShop) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.ShopType = bf.ReadUint8() + m.ShopID = bf.ReadUint32() + m.Unk2 = bf.ReadUint16() + m.Unk3 = bf.ReadUint8() + m.Unk4 = bf.ReadUint8() + m.Unk5 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateShop) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_title.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_title.go new file mode 100644 index 000000000..e68acf55b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_title.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateTitle represents the MSG_MHF_ENUMERATE_TITLE +type MsgMhfEnumerateTitle struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateTitle) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_TITLE +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateTitle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateTitle) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_union_item.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_union_item.go new file mode 100644 index 000000000..92a07935a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_union_item.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateUnionItem represents the MSG_MHF_ENUMERATE_UNION_ITEM +type MsgMhfEnumerateUnionItem struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateUnionItem) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_UNION_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateUnionItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateUnionItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_enumerate_warehouse.go b/Erupe/network/mhfpacket/msg_mhf_enumerate_warehouse.go new file mode 100644 index 000000000..f45365eb8 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_enumerate_warehouse.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfEnumerateWarehouse represents the MSG_MHF_ENUMERATE_WAREHOUSE +type MsgMhfEnumerateWarehouse struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfEnumerateWarehouse) Opcode() network.PacketID { + return network.MSG_MHF_ENUMERATE_WAREHOUSE +} + +// Parse parses the packet from binary +func (m *MsgMhfEnumerateWarehouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfEnumerateWarehouse) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_exchange_fpoint_2_item.go b/Erupe/network/mhfpacket/msg_mhf_exchange_fpoint_2_item.go new file mode 100644 index 000000000..f7075b841 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_exchange_fpoint_2_item.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfExchangeFpoint2Item represents the MSG_MHF_EXCHANGE_FPOINT_2_ITEM +type MsgMhfExchangeFpoint2Item struct{ + AckHandle uint32 + ItemHash uint32 + ItemType uint16 + ItemId uint16 + Quantity byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfExchangeFpoint2Item) Opcode() network.PacketID { + return network.MSG_MHF_EXCHANGE_FPOINT_2_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfExchangeFpoint2Item) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.ItemHash = bf.ReadUint32() + m.ItemType = bf.ReadUint16() + m.ItemId = bf.ReadUint16() + m.Quantity = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfExchangeFpoint2Item) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_exchange_item_2_fpoint.go b/Erupe/network/mhfpacket/msg_mhf_exchange_item_2_fpoint.go new file mode 100644 index 000000000..05c74b957 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_exchange_item_2_fpoint.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfExchangeItem2Fpoint represents the MSG_MHF_EXCHANGE_ITEM_2_FPOINT +type MsgMhfExchangeItem2Fpoint struct{ + AckHandle uint32 + ItemHash uint32 + ItemType uint16 + ItemId uint16 + Quantity byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfExchangeItem2Fpoint) Opcode() network.PacketID { + return network.MSG_MHF_EXCHANGE_ITEM_2_FPOINT +} + +// Parse parses the packet from binary +func (m *MsgMhfExchangeItem2Fpoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.ItemHash = bf.ReadUint32() + m.ItemType = bf.ReadUint16() + m.ItemId = bf.ReadUint16() + m.Quantity = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfExchangeItem2Fpoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_exchange_kouryou_point.go b/Erupe/network/mhfpacket/msg_mhf_exchange_kouryou_point.go new file mode 100644 index 000000000..506d586c8 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_exchange_kouryou_point.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfExchangeKouryouPoint represents the MSG_MHF_EXCHANGE_KOURYOU_POINT +type MsgMhfExchangeKouryouPoint struct{ + AckHandle uint32 + KouryouPoints uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfExchangeKouryouPoint) Opcode() network.PacketID { + return network.MSG_MHF_EXCHANGE_KOURYOU_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfExchangeKouryouPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.KouryouPoints = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfExchangeKouryouPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_exchange_weekly_stamp.go b/Erupe/network/mhfpacket/msg_mhf_exchange_weekly_stamp.go new file mode 100644 index 000000000..718941b2f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_exchange_weekly_stamp.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfExchangeWeeklyStamp represents the MSG_MHF_EXCHANGE_WEEKLY_STAMP +type MsgMhfExchangeWeeklyStamp struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfExchangeWeeklyStamp) Opcode() network.PacketID { + return network.MSG_MHF_EXCHANGE_WEEKLY_STAMP +} + +// Parse parses the packet from binary +func (m *MsgMhfExchangeWeeklyStamp) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfExchangeWeeklyStamp) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_generate_ud_guild_map.go b/Erupe/network/mhfpacket/msg_mhf_generate_ud_guild_map.go new file mode 100644 index 000000000..49cb63c55 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_generate_ud_guild_map.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGenerateUdGuildMap represents the MSG_MHF_GENERATE_UD_GUILD_MAP +type MsgMhfGenerateUdGuildMap struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGenerateUdGuildMap) Opcode() network.PacketID { + return network.MSG_MHF_GENERATE_UD_GUILD_MAP +} + +// Parse parses the packet from binary +func (m *MsgMhfGenerateUdGuildMap) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGenerateUdGuildMap) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_achievement.go b/Erupe/network/mhfpacket/msg_mhf_get_achievement.go new file mode 100644 index 000000000..edba009ea --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_achievement.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetAchievement represents the MSG_MHF_GET_ACHIEVEMENT +type MsgMhfGetAchievement struct{ + AckHandle uint32 + Unk0 uint16 // id? + Unk1 uint32 // char? + Unk2 uint32 // pad? +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetAchievement) Opcode() network.PacketID { + return network.MSG_MHF_GET_ACHIEVEMENT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetAchievement) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetAchievement) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_additional_beat_reward.go b/Erupe/network/mhfpacket/msg_mhf_get_additional_beat_reward.go new file mode 100644 index 000000000..847710b48 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_additional_beat_reward.go @@ -0,0 +1,39 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetAdditionalBeatReward represents the MSG_MHF_GET_ADDITIONAL_BEAT_REWARD +type MsgMhfGetAdditionalBeatReward struct { + // Communicator type, multi-format. This might be valid for only one type. + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 uint32 + Unk3 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetAdditionalBeatReward) Opcode() network.PacketID { + return network.MSG_MHF_GET_ADDITIONAL_BEAT_REWARD +} + +// Parse parses the packet from binary +func (m *MsgMhfGetAdditionalBeatReward) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + m.Unk3 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetAdditionalBeatReward) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_bbs_sns_status.go b/Erupe/network/mhfpacket/msg_mhf_get_bbs_sns_status.go new file mode 100644 index 000000000..170464cf8 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_bbs_sns_status.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetBbsSnsStatus represents the MSG_MHF_GET_BBS_SNS_STATUS +type MsgMhfGetBbsSnsStatus struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetBbsSnsStatus) Opcode() network.PacketID { + return network.MSG_MHF_GET_BBS_SNS_STATUS +} + +// Parse parses the packet from binary +func (m *MsgMhfGetBbsSnsStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetBbsSnsStatus) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_bbs_user_status.go b/Erupe/network/mhfpacket/msg_mhf_get_bbs_user_status.go new file mode 100644 index 000000000..bd2d4e8f4 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_bbs_user_status.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetBbsUserStatus represents the MSG_MHF_GET_BBS_USER_STATUS +type MsgMhfGetBbsUserStatus struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetBbsUserStatus) Opcode() network.PacketID { + return network.MSG_MHF_GET_BBS_USER_STATUS +} + +// Parse parses the packet from binary +func (m *MsgMhfGetBbsUserStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetBbsUserStatus) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_boost_right.go b/Erupe/network/mhfpacket/msg_mhf_get_boost_right.go new file mode 100644 index 000000000..f17ca0c65 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_boost_right.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetBoostRight represents the MSG_MHF_GET_BOOST_RIGHT +type MsgMhfGetBoostRight struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetBoostRight) Opcode() network.PacketID { + return network.MSG_MHF_GET_BOOST_RIGHT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetBoostRight) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetBoostRight) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_boost_time.go b/Erupe/network/mhfpacket/msg_mhf_get_boost_time.go new file mode 100644 index 000000000..d72ee8484 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_boost_time.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetBoostTime represents the MSG_MHF_GET_BOOST_TIME +type MsgMhfGetBoostTime struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetBoostTime) Opcode() network.PacketID { + return network.MSG_MHF_GET_BOOST_TIME +} + +// Parse parses the packet from binary +func (m *MsgMhfGetBoostTime) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetBoostTime) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_boost_time_limit.go b/Erupe/network/mhfpacket/msg_mhf_get_boost_time_limit.go new file mode 100644 index 000000000..4cf0ee503 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_boost_time_limit.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetBoostTimeLimit represents the MSG_MHF_GET_BOOST_TIME_LIMIT +type MsgMhfGetBoostTimeLimit struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetBoostTimeLimit) Opcode() network.PacketID { + return network.MSG_MHF_GET_BOOST_TIME_LIMIT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetBoostTimeLimit) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetBoostTimeLimit) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_box_gacha_info.go b/Erupe/network/mhfpacket/msg_mhf_get_box_gacha_info.go new file mode 100644 index 000000000..2ef6d116f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_box_gacha_info.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetBoxGachaInfo represents the MSG_MHF_GET_BOX_GACHA_INFO +type MsgMhfGetBoxGachaInfo struct{ + AckHandle uint32 + GachaHash uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetBoxGachaInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_BOX_GACHA_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetBoxGachaInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GachaHash = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetBoxGachaInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_break_seibatu_level_reward.go b/Erupe/network/mhfpacket/msg_mhf_get_break_seibatu_level_reward.go new file mode 100644 index 000000000..807a3e5b8 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_break_seibatu_level_reward.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetBreakSeibatuLevelReward represents the MSG_MHF_GET_BREAK_SEIBATU_LEVEL_REWARD +type MsgMhfGetBreakSeibatuLevelReward struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetBreakSeibatuLevelReward) Opcode() network.PacketID { + return network.MSG_MHF_GET_BREAK_SEIBATU_LEVEL_REWARD +} + +// Parse parses the packet from binary +func (m *MsgMhfGetBreakSeibatuLevelReward) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetBreakSeibatuLevelReward) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ca_achievement_hist.go b/Erupe/network/mhfpacket/msg_mhf_get_ca_achievement_hist.go new file mode 100644 index 000000000..e882cab0b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ca_achievement_hist.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetCaAchievementHist represents the MSG_MHF_GET_CA_ACHIEVEMENT_HIST +type MsgMhfGetCaAchievementHist struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetCaAchievementHist) Opcode() network.PacketID { + return network.MSG_MHF_GET_CA_ACHIEVEMENT_HIST +} + +// Parse parses the packet from binary +func (m *MsgMhfGetCaAchievementHist) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetCaAchievementHist) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ca_unique_id.go b/Erupe/network/mhfpacket/msg_mhf_get_ca_unique_id.go new file mode 100644 index 000000000..f7546253a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ca_unique_id.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetCaUniqueID represents the MSG_MHF_GET_CA_UNIQUE_ID +type MsgMhfGetCaUniqueID struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetCaUniqueID) Opcode() network.PacketID { + return network.MSG_MHF_GET_CA_UNIQUE_ID +} + +// Parse parses the packet from binary +func (m *MsgMhfGetCaUniqueID) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetCaUniqueID) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_cafe_duration.go b/Erupe/network/mhfpacket/msg_mhf_get_cafe_duration.go new file mode 100644 index 000000000..7ac3b0f28 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_cafe_duration.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetCafeDuration represents the MSG_MHF_GET_CAFE_DURATION +type MsgMhfGetCafeDuration struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetCafeDuration) Opcode() network.PacketID { + return network.MSG_MHF_GET_CAFE_DURATION +} + +// Parse parses the packet from binary +func (m *MsgMhfGetCafeDuration) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetCafeDuration) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_cafe_duration_bonus_info.go b/Erupe/network/mhfpacket/msg_mhf_get_cafe_duration_bonus_info.go new file mode 100644 index 000000000..73a94d42b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_cafe_duration_bonus_info.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetCafeDurationBonusInfo represents the MSG_MHF_GET_CAFE_DURATION_BONUS_INFO +type MsgMhfGetCafeDurationBonusInfo struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetCafeDurationBonusInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_CAFE_DURATION_BONUS_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetCafeDurationBonusInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetCafeDurationBonusInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_cog_info.go b/Erupe/network/mhfpacket/msg_mhf_get_cog_info.go new file mode 100644 index 000000000..8e5e0164a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_cog_info.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetCogInfo represents the MSG_MHF_GET_COG_INFO +type MsgMhfGetCogInfo struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetCogInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_COG_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetCogInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetCogInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_daily_mission_master.go b/Erupe/network/mhfpacket/msg_mhf_get_daily_mission_master.go new file mode 100644 index 000000000..6bb4b2634 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_daily_mission_master.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetDailyMissionMaster represents the MSG_MHF_GET_DAILY_MISSION_MASTER +type MsgMhfGetDailyMissionMaster struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetDailyMissionMaster) Opcode() network.PacketID { + return network.MSG_MHF_GET_DAILY_MISSION_MASTER +} + +// Parse parses the packet from binary +func (m *MsgMhfGetDailyMissionMaster) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetDailyMissionMaster) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_daily_mission_personal.go b/Erupe/network/mhfpacket/msg_mhf_get_daily_mission_personal.go new file mode 100644 index 000000000..a5a6ace66 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_daily_mission_personal.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetDailyMissionPersonal represents the MSG_MHF_GET_DAILY_MISSION_PERSONAL +type MsgMhfGetDailyMissionPersonal struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetDailyMissionPersonal) Opcode() network.PacketID { + return network.MSG_MHF_GET_DAILY_MISSION_PERSONAL +} + +// Parse parses the packet from binary +func (m *MsgMhfGetDailyMissionPersonal) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetDailyMissionPersonal) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_dist_description.go b/Erupe/network/mhfpacket/msg_mhf_get_dist_description.go new file mode 100644 index 000000000..fd8f664a7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_dist_description.go @@ -0,0 +1,33 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetDistDescription represents the MSG_MHF_GET_DIST_DESCRIPTION +type MsgMhfGetDistDescription struct{ + AckHandle uint32 + Unk0 uint8 + EntryID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetDistDescription) Opcode() network.PacketID { + return network.MSG_MHF_GET_DIST_DESCRIPTION +} + +// Parse parses the packet from binary +func (m *MsgMhfGetDistDescription) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.EntryID = bf.ReadUint32() + return nil +} +// Build builds a binary packet from the current data. +func (m *MsgMhfGetDistDescription) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_earth_status.go b/Erupe/network/mhfpacket/msg_mhf_get_earth_status.go new file mode 100644 index 000000000..fb430853c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_earth_status.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetEarthStatus represents the MSG_MHF_GET_EARTH_STATUS +type MsgMhfGetEarthStatus struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetEarthStatus) Opcode() network.PacketID { + return network.MSG_MHF_GET_EARTH_STATUS +} + +// Parse parses the packet from binary +func (m *MsgMhfGetEarthStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetEarthStatus) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_earth_value.go b/Erupe/network/mhfpacket/msg_mhf_get_earth_value.go new file mode 100644 index 000000000..2d0ce3535 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_earth_value.go @@ -0,0 +1,44 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetEarthValue represents the MSG_MHF_GET_EARTH_VALUE +type MsgMhfGetEarthValue struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + ReqType uint32 + Unk3 uint32 + Unk4 uint32 + Unk5 uint32 + Unk6 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetEarthValue) Opcode() network.PacketID { + return network.MSG_MHF_GET_EARTH_VALUE +} + +// Parse parses the packet from binary +func (m *MsgMhfGetEarthValue) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.ReqType = bf.ReadUint32() + m.Unk3 = bf.ReadUint32() + m.Unk4 = bf.ReadUint32() + m.Unk5 = bf.ReadUint32() + m.Unk6 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetEarthValue) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_enhanced_minidata.go b/Erupe/network/mhfpacket/msg_mhf_get_enhanced_minidata.go new file mode 100644 index 000000000..52a938801 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_enhanced_minidata.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetEnhancedMinidata represents the MSG_MHF_GET_ENHANCED_MINIDATA +type MsgMhfGetEnhancedMinidata struct { + AckHandle uint32 + CharID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetEnhancedMinidata) Opcode() network.PacketID { + return network.MSG_MHF_GET_ENHANCED_MINIDATA +} + +// Parse parses the packet from binary +func (m *MsgMhfGetEnhancedMinidata) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.CharID = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetEnhancedMinidata) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_equip_skin_hist.go b/Erupe/network/mhfpacket/msg_mhf_get_equip_skin_hist.go new file mode 100644 index 000000000..7d0d68c3a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_equip_skin_hist.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetEquipSkinHist represents the MSG_MHF_GET_EQUIP_SKIN_HIST +type MsgMhfGetEquipSkinHist struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetEquipSkinHist) Opcode() network.PacketID { + return network.MSG_MHF_GET_EQUIP_SKIN_HIST +} + +// Parse parses the packet from binary +func (m *MsgMhfGetEquipSkinHist) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetEquipSkinHist) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_etc_points.go b/Erupe/network/mhfpacket/msg_mhf_get_etc_points.go new file mode 100644 index 000000000..3dd1a491f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_etc_points.go @@ -0,0 +1,28 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetEtcPoints represents the MSG_MHF_GET_ETC_POINTS +type MsgMhfGetEtcPoints struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetEtcPoints) Opcode() network.PacketID { + return network.MSG_MHF_GET_ETC_POINTS +} + +// Parse parses the packet from binary +func (m *MsgMhfGetEtcPoints) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetEtcPoints) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_extra_info.go b/Erupe/network/mhfpacket/msg_mhf_get_extra_info.go new file mode 100644 index 000000000..0df1fc722 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_extra_info.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetExtraInfo represents the MSG_MHF_GET_EXTRA_INFO +type MsgMhfGetExtraInfo struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetExtraInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_EXTRA_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetExtraInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetExtraInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_fixed_seibatu_ranking_table.go b/Erupe/network/mhfpacket/msg_mhf_get_fixed_seibatu_ranking_table.go new file mode 100644 index 000000000..45ea68ee8 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_fixed_seibatu_ranking_table.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetFixedSeibatuRankingTable represents the MSG_MHF_GET_FIXED_SEIBATU_RANKING_TABLE +type MsgMhfGetFixedSeibatuRankingTable struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetFixedSeibatuRankingTable) Opcode() network.PacketID { + return network.MSG_MHF_GET_FIXED_SEIBATU_RANKING_TABLE +} + +// Parse parses the packet from binary +func (m *MsgMhfGetFixedSeibatuRankingTable) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetFixedSeibatuRankingTable) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_fpoint_exchange_list.go b/Erupe/network/mhfpacket/msg_mhf_get_fpoint_exchange_list.go new file mode 100644 index 000000000..8ba99d08d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_fpoint_exchange_list.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetFpointExchangeList represents the MSG_MHF_GET_FPOINT_EXCHANGE_LIST +type MsgMhfGetFpointExchangeList struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetFpointExchangeList) Opcode() network.PacketID { + return network.MSG_MHF_GET_FPOINT_EXCHANGE_LIST +} + +// Parse parses the packet from binary +func (m *MsgMhfGetFpointExchangeList) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetFpointExchangeList) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_gacha_play_history.go b/Erupe/network/mhfpacket/msg_mhf_get_gacha_play_history.go new file mode 100644 index 000000000..2cbdd2a72 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_gacha_play_history.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGachaPlayHistory represents the MSG_MHF_GET_GACHA_PLAY_HISTORY +type MsgMhfGetGachaPlayHistory struct{ + AckHandle uint32 + GachaHash uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGachaPlayHistory) Opcode() network.PacketID { + return network.MSG_MHF_GET_GACHA_PLAY_HISTORY +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGachaPlayHistory) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GachaHash = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGachaPlayHistory) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_gacha_point.go b/Erupe/network/mhfpacket/msg_mhf_get_gacha_point.go new file mode 100644 index 000000000..b74d130bb --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_gacha_point.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGachaPoint represents the MSG_MHF_GET_GACHA_POINT +type MsgMhfGetGachaPoint struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGachaPoint) Opcode() network.PacketID { + return network.MSG_MHF_GET_GACHA_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGachaPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGachaPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_gem_info.go b/Erupe/network/mhfpacket/msg_mhf_get_gem_info.go new file mode 100644 index 000000000..216c3effb --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_gem_info.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGemInfo represents the MSG_MHF_GET_GEM_INFO +type MsgMhfGetGemInfo struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGemInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_GEM_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGemInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_guild_manage_right.go b/Erupe/network/mhfpacket/msg_mhf_get_guild_manage_right.go new file mode 100644 index 000000000..7851463c2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_guild_manage_right.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGuildManageRight represents the MSG_MHF_GET_GUILD_MANAGE_RIGHT +type MsgMhfGetGuildManageRight struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGuildManageRight) Opcode() network.PacketID { + return network.MSG_MHF_GET_GUILD_MANAGE_RIGHT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGuildManageRight) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGuildManageRight) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_guild_mission_list.go b/Erupe/network/mhfpacket/msg_mhf_get_guild_mission_list.go new file mode 100644 index 000000000..c90c0ce91 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_guild_mission_list.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGuildMissionList represents the MSG_MHF_GET_GUILD_MISSION_LIST +type MsgMhfGetGuildMissionList struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGuildMissionList) Opcode() network.PacketID { + return network.MSG_MHF_GET_GUILD_MISSION_LIST +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGuildMissionList) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGuildMissionList) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_guild_mission_record.go b/Erupe/network/mhfpacket/msg_mhf_get_guild_mission_record.go new file mode 100644 index 000000000..02950a789 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_guild_mission_record.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGuildMissionRecord represents the MSG_MHF_GET_GUILD_MISSION_RECORD +type MsgMhfGetGuildMissionRecord struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGuildMissionRecord) Opcode() network.PacketID { + return network.MSG_MHF_GET_GUILD_MISSION_RECORD +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGuildMissionRecord) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGuildMissionRecord) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_guild_scout_list.go b/Erupe/network/mhfpacket/msg_mhf_get_guild_scout_list.go new file mode 100644 index 000000000..e1eeee59f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_guild_scout_list.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGuildScoutList represents the MSG_MHF_GET_GUILD_SCOUT_LIST +type MsgMhfGetGuildScoutList struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGuildScoutList) Opcode() network.PacketID { + return network.MSG_MHF_GET_GUILD_SCOUT_LIST +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGuildScoutList) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGuildScoutList) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_guild_target_member_num.go b/Erupe/network/mhfpacket/msg_mhf_get_guild_target_member_num.go new file mode 100644 index 000000000..dd1b2d94c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_guild_target_member_num.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGuildTargetMemberNum represents the MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM +type MsgMhfGetGuildTargetMemberNum struct { + AckHandle uint32 + GuildID uint32 + Unk uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGuildTargetMemberNum) Opcode() network.PacketID { + return network.MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGuildTargetMemberNum) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GuildID = bf.ReadUint32() + m.Unk = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGuildTargetMemberNum) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_guild_tresure_souvenir.go b/Erupe/network/mhfpacket/msg_mhf_get_guild_tresure_souvenir.go new file mode 100644 index 000000000..7c9ac92ab --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_guild_tresure_souvenir.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGuildTresureSouvenir represents the MSG_MHF_GET_GUILD_TRESURE_SOUVENIR +type MsgMhfGetGuildTresureSouvenir struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGuildTresureSouvenir) Opcode() network.PacketID { + return network.MSG_MHF_GET_GUILD_TRESURE_SOUVENIR +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGuildTresureSouvenir) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGuildTresureSouvenir) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_guild_weekly_bonus_active_count.go b/Erupe/network/mhfpacket/msg_mhf_get_guild_weekly_bonus_active_count.go new file mode 100644 index 000000000..4d9eba1d4 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_guild_weekly_bonus_active_count.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGuildWeeklyBonusActiveCount represents the MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT +type MsgMhfGetGuildWeeklyBonusActiveCount struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGuildWeeklyBonusActiveCount) Opcode() network.PacketID { + return network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGuildWeeklyBonusActiveCount) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGuildWeeklyBonusActiveCount) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_guild_weekly_bonus_master.go b/Erupe/network/mhfpacket/msg_mhf_get_guild_weekly_bonus_master.go new file mode 100644 index 000000000..c85415fa3 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_guild_weekly_bonus_master.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetGuildWeeklyBonusMaster represents the MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER +type MsgMhfGetGuildWeeklyBonusMaster struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetGuildWeeklyBonusMaster) Opcode() network.PacketID { + return network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER +} + +// Parse parses the packet from binary +func (m *MsgMhfGetGuildWeeklyBonusMaster) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetGuildWeeklyBonusMaster) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_keep_login_boost_status.go b/Erupe/network/mhfpacket/msg_mhf_get_keep_login_boost_status.go new file mode 100644 index 000000000..ec7625c9c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_keep_login_boost_status.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetKeepLoginBoostStatus represents the MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS +type MsgMhfGetKeepLoginBoostStatus struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetKeepLoginBoostStatus) Opcode() network.PacketID { + return network.MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS +} + +// Parse parses the packet from binary +func (m *MsgMhfGetKeepLoginBoostStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetKeepLoginBoostStatus) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_kiju_info.go b/Erupe/network/mhfpacket/msg_mhf_get_kiju_info.go new file mode 100644 index 000000000..8560af502 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_kiju_info.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetKijuInfo represents the MSG_MHF_GET_KIJU_INFO +type MsgMhfGetKijuInfo struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetKijuInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_KIJU_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetKijuInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetKijuInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_kouryou_point.go b/Erupe/network/mhfpacket/msg_mhf_get_kouryou_point.go new file mode 100644 index 000000000..ce9bfb6ca --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_kouryou_point.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetKouryouPoint represents the MSG_MHF_GET_KOURYOU_POINT +type MsgMhfGetKouryouPoint struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetKouryouPoint) Opcode() network.PacketID { + return network.MSG_MHF_GET_KOURYOU_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetKouryouPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetKouryouPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_lobby_crowd.go b/Erupe/network/mhfpacket/msg_mhf_get_lobby_crowd.go new file mode 100644 index 000000000..b22ae020a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_lobby_crowd.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetLobbyCrowd represents the MSG_MHF_GET_LOBBY_CROWD +type MsgMhfGetLobbyCrowd struct{ + AckHandle uint32 + Server uint32 + Room uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetLobbyCrowd) Opcode() network.PacketID { + return network.MSG_MHF_GET_LOBBY_CROWD +} + +// Parse parses the packet from binary +func (m *MsgMhfGetLobbyCrowd) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Server = bf.ReadUint32() + m.Room = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetLobbyCrowd) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_myhouse_info.go b/Erupe/network/mhfpacket/msg_mhf_get_myhouse_info.go new file mode 100644 index 000000000..bbce0214b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_myhouse_info.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetMyhouseInfo represents the MSG_MHF_GET_MYHOUSE_INFO +type MsgMhfGetMyhouseInfo struct { + AckHandle uint32 + Unk0 uint32 + + // No idea why it would send a buffer of data on a _GET_, but w/e. + DataSize uint8 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetMyhouseInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_MYHOUSE_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetMyhouseInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.DataSize = bf.ReadUint8() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetMyhouseInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_notice.go b/Erupe/network/mhfpacket/msg_mhf_get_notice.go new file mode 100644 index 000000000..8b8cb1097 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_notice.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetNotice represents the MSG_MHF_GET_NOTICE +type MsgMhfGetNotice struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetNotice) Opcode() network.PacketID { + return network.MSG_MHF_GET_NOTICE +} + +// Parse parses the packet from binary +func (m *MsgMhfGetNotice) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetNotice) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_paper_data.go b/Erupe/network/mhfpacket/msg_mhf_get_paper_data.go new file mode 100644 index 000000000..191b283a2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_paper_data.go @@ -0,0 +1,37 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetPaperData represents the MSG_MHF_GET_PAPER_DATA +type MsgMhfGetPaperData struct { + // Communicator type, multi-format. This might be valid for only one type. + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetPaperData) Opcode() network.PacketID { + return network.MSG_MHF_GET_PAPER_DATA +} + +// Parse parses the packet from binary +func (m *MsgMhfGetPaperData) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetPaperData) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_rand_from_table.go b/Erupe/network/mhfpacket/msg_mhf_get_rand_from_table.go new file mode 100644 index 000000000..5ad6ef10a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_rand_from_table.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetRandFromTable represents the MSG_MHF_GET_RAND_FROM_TABLE +type MsgMhfGetRandFromTable struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetRandFromTable) Opcode() network.PacketID { + return network.MSG_MHF_GET_RAND_FROM_TABLE +} + +// Parse parses the packet from binary +func (m *MsgMhfGetRandFromTable) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetRandFromTable) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_reject_guild_scout.go b/Erupe/network/mhfpacket/msg_mhf_get_reject_guild_scout.go new file mode 100644 index 000000000..220f86939 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_reject_guild_scout.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetRejectGuildScout represents the MSG_MHF_GET_REJECT_GUILD_SCOUT +type MsgMhfGetRejectGuildScout struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetRejectGuildScout) Opcode() network.PacketID { + return network.MSG_MHF_GET_REJECT_GUILD_SCOUT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetRejectGuildScout) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetRejectGuildScout) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_rengoku_binary.go b/Erupe/network/mhfpacket/msg_mhf_get_rengoku_binary.go new file mode 100644 index 000000000..708d99651 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_rengoku_binary.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetRengokuBinary represents the MSG_MHF_GET_RENGOKU_BINARY +type MsgMhfGetRengokuBinary struct { + AckHandle uint32 + Unk0 uint8 // Hardcoded 0 in binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetRengokuBinary) Opcode() network.PacketID { + return network.MSG_MHF_GET_RENGOKU_BINARY +} + +// Parse parses the packet from binary +func (m *MsgMhfGetRengokuBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetRengokuBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_rengoku_ranking_rank.go b/Erupe/network/mhfpacket/msg_mhf_get_rengoku_ranking_rank.go new file mode 100644 index 000000000..f24505dc7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_rengoku_ranking_rank.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetRengokuRankingRank represents the MSG_MHF_GET_RENGOKU_RANKING_RANK +type MsgMhfGetRengokuRankingRank struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetRengokuRankingRank) Opcode() network.PacketID { + return network.MSG_MHF_GET_RENGOKU_RANKING_RANK +} + +// Parse parses the packet from binary +func (m *MsgMhfGetRengokuRankingRank) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetRengokuRankingRank) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_restriction_event.go b/Erupe/network/mhfpacket/msg_mhf_get_restriction_event.go new file mode 100644 index 000000000..9abb1d925 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_restriction_event.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetRestrictionEvent represents the MSG_MHF_GET_RESTRICTION_EVENT +type MsgMhfGetRestrictionEvent struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetRestrictionEvent) Opcode() network.PacketID { + return network.MSG_MHF_GET_RESTRICTION_EVENT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetRestrictionEvent) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetRestrictionEvent) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_reward_song.go b/Erupe/network/mhfpacket/msg_mhf_get_reward_song.go new file mode 100644 index 000000000..117b1eb40 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_reward_song.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetRewardSong represents the MSG_MHF_GET_REWARD_SONG +type MsgMhfGetRewardSong struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetRewardSong) Opcode() network.PacketID { + return network.MSG_MHF_GET_REWARD_SONG +} + +// Parse parses the packet from binary +func (m *MsgMhfGetRewardSong) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetRewardSong) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ryoudama.go b/Erupe/network/mhfpacket/msg_mhf_get_ryoudama.go new file mode 100644 index 000000000..ef9466d99 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ryoudama.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetRyoudama represents the MSG_MHF_GET_RYOUDAMA +type MsgMhfGetRyoudama struct{ + AckHandle uint32 + Unk0 uint16 + Unk1 uint32 + Unk2 uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetRyoudama) Opcode() network.PacketID { + return network.MSG_MHF_GET_RYOUDAMA +} + +// Parse parses the packet from binary +func (m *MsgMhfGetRyoudama) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetRyoudama) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_seibattle.go b/Erupe/network/mhfpacket/msg_mhf_get_seibattle.go new file mode 100644 index 000000000..842742442 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_seibattle.go @@ -0,0 +1,41 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetSeibattle represents the MSG_MHF_GET_SEIBATTLE +type MsgMhfGetSeibattle struct { + // Communicator type, multi-format. This might be valid for only one type. + AckHandle uint32 + Unk0 uint8 + Unk1 uint8 + Unk2 uint32 // Some shared ID with MSG_SYS_RECORD_LOG, world ID? + Unk3 uint8 + Unk4 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetSeibattle) Opcode() network.PacketID { + return network.MSG_MHF_GET_SEIBATTLE +} + +// Parse parses the packet from binary +func (m *MsgMhfGetSeibattle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + m.Unk2 = bf.ReadUint32() + m.Unk3 = bf.ReadUint8() + m.Unk4 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetSeibattle) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_senyu_daily_count.go b/Erupe/network/mhfpacket/msg_mhf_get_senyu_daily_count.go new file mode 100644 index 000000000..090b5d082 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_senyu_daily_count.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetSenyuDailyCount represents the MSG_MHF_GET_SENYU_DAILY_COUNT +type MsgMhfGetSenyuDailyCount struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetSenyuDailyCount) Opcode() network.PacketID { + return network.MSG_MHF_GET_SENYU_DAILY_COUNT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetSenyuDailyCount) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetSenyuDailyCount) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_stepup_status.go b/Erupe/network/mhfpacket/msg_mhf_get_stepup_status.go new file mode 100644 index 000000000..3d643d4ee --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_stepup_status.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetStepupStatus represents the MSG_MHF_GET_STEPUP_STATUS +type MsgMhfGetStepupStatus struct{ + AckHandle uint32 + GachaHash uint32 + Unk uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetStepupStatus) Opcode() network.PacketID { + return network.MSG_MHF_GET_STEPUP_STATUS +} + +// Parse parses the packet from binary +func (m *MsgMhfGetStepupStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GachaHash = bf.ReadUint32() + m.Unk = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetStepupStatus) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_tenrouirai.go b/Erupe/network/mhfpacket/msg_mhf_get_tenrouirai.go new file mode 100644 index 000000000..4c6808090 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_tenrouirai.go @@ -0,0 +1,37 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetTenrouirai represents the MSG_MHF_GET_TENROUIRAI +type MsgMhfGetTenrouirai struct { + // Communicator type, multi-format. This might be valid for only one type. + AckHandle uint32 + Unk0 uint16 + Unk1 uint32 + Unk2 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetTenrouirai) Opcode() network.PacketID { + return network.MSG_MHF_GET_TENROUIRAI +} + +// Parse parses the packet from binary +func (m *MsgMhfGetTenrouirai) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetTenrouirai) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_tiny_bin.go b/Erupe/network/mhfpacket/msg_mhf_get_tiny_bin.go new file mode 100644 index 000000000..a1565e260 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_tiny_bin.go @@ -0,0 +1,35 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetTinyBin represents the MSG_MHF_GET_TINY_BIN +type MsgMhfGetTinyBin struct { + // Communicator type, multi-format. This might be valid for only one type. + AckHandle uint32 + Unk0 uint16 + Unk1 uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetTinyBin) Opcode() network.PacketID { + return network.MSG_MHF_GET_TINY_BIN +} + +// Parse parses the packet from binary +func (m *MsgMhfGetTinyBin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetTinyBin) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_tower_info.go b/Erupe/network/mhfpacket/msg_mhf_get_tower_info.go new file mode 100644 index 000000000..fa5c4bdf0 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_tower_info.go @@ -0,0 +1,47 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// The server sends different responses based on these values. +const ( + TowerInfoTypeUnk0 = iota + TowerInfoTypeTowerRankPoint + TowerInfoTypeGetOwnTowerSkill + TowerInfoTypeUnk3 + TowerInfoTypeTowerTouhaHistory + TowerInfoTypeUnk5 +) + +// MsgMhfGetTowerInfo represents the MSG_MHF_GET_TOWER_INFO +type MsgMhfGetTowerInfo struct { + // Communicator type, multi-format. This might be valid for only one type. + AckHandle uint32 + InfoType uint32 // Requested response type + Unk0 uint32 + Unk1 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetTowerInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_TOWER_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetTowerInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.InfoType = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetTowerInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_trend_weapon.go b/Erupe/network/mhfpacket/msg_mhf_get_trend_weapon.go new file mode 100644 index 000000000..5841795da --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_trend_weapon.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetTrendWeapon represents the MSG_MHF_GET_TREND_WEAPON +type MsgMhfGetTrendWeapon struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetTrendWeapon) Opcode() network.PacketID { + return network.MSG_MHF_GET_TREND_WEAPON +} + +// Parse parses the packet from binary +func (m *MsgMhfGetTrendWeapon) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetTrendWeapon) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_bonus_quest_info.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_bonus_quest_info.go new file mode 100644 index 000000000..2103176a4 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_bonus_quest_info.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdBonusQuestInfo represents the MSG_MHF_GET_UD_BONUS_QUEST_INFO +type MsgMhfGetUdBonusQuestInfo struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdBonusQuestInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_BONUS_QUEST_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdBonusQuestInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdBonusQuestInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_daily_present_list.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_daily_present_list.go new file mode 100644 index 000000000..6bc3e1c15 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_daily_present_list.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdDailyPresentList represents the MSG_MHF_GET_UD_DAILY_PRESENT_LIST +type MsgMhfGetUdDailyPresentList struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdDailyPresentList) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_DAILY_PRESENT_LIST +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdDailyPresentList) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdDailyPresentList) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_guild_map_info.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_guild_map_info.go new file mode 100644 index 000000000..2a9121746 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_guild_map_info.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdGuildMapInfo represents the MSG_MHF_GET_UD_GUILD_MAP_INFO +type MsgMhfGetUdGuildMapInfo struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdGuildMapInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_GUILD_MAP_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdGuildMapInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdGuildMapInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_info.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_info.go new file mode 100644 index 000000000..1d5d8103d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_info.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdInfo represents the MSG_MHF_GET_UD_INFO +type MsgMhfGetUdInfo struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_monster_point.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_monster_point.go new file mode 100644 index 000000000..5b1cbc112 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_monster_point.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdMonsterPoint represents the MSG_MHF_GET_UD_MONSTER_POINT +type MsgMhfGetUdMonsterPoint struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdMonsterPoint) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_MONSTER_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdMonsterPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdMonsterPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_my_point.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_my_point.go new file mode 100644 index 000000000..e4712c689 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_my_point.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdMyPoint represents the MSG_MHF_GET_UD_MY_POINT +type MsgMhfGetUdMyPoint struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdMyPoint) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_MY_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdMyPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdMyPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_my_ranking.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_my_ranking.go new file mode 100644 index 000000000..83af4c256 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_my_ranking.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdMyRanking represents the MSG_MHF_GET_UD_MY_RANKING +type MsgMhfGetUdMyRanking struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdMyRanking) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_MY_RANKING +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdMyRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdMyRanking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_norma_present_list.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_norma_present_list.go new file mode 100644 index 000000000..d3322a89b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_norma_present_list.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdNormaPresentList represents the MSG_MHF_GET_UD_NORMA_PRESENT_LIST +type MsgMhfGetUdNormaPresentList struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdNormaPresentList) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_NORMA_PRESENT_LIST +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdNormaPresentList) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdNormaPresentList) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_ranking.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_ranking.go new file mode 100644 index 000000000..33cfdbc1e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_ranking.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdRanking represents the MSG_MHF_GET_UD_RANKING +type MsgMhfGetUdRanking struct{ + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdRanking) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_RANKING +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdRanking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_ranking_reward_list.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_ranking_reward_list.go new file mode 100644 index 000000000..eb8931fde --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_ranking_reward_list.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdRankingRewardList represents the MSG_MHF_GET_UD_RANKING_REWARD_LIST +type MsgMhfGetUdRankingRewardList struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdRankingRewardList) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_RANKING_REWARD_LIST +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdRankingRewardList) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdRankingRewardList) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_schedule.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_schedule.go new file mode 100644 index 000000000..8a02ac866 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_schedule.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdSchedule represents the MSG_MHF_GET_UD_SCHEDULE +type MsgMhfGetUdSchedule struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdSchedule) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_SCHEDULE +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdSchedule) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdSchedule) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_selected_color_info.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_selected_color_info.go new file mode 100644 index 000000000..622d6aaa2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_selected_color_info.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdSelectedColorInfo represents the MSG_MHF_GET_UD_SELECTED_COLOR_INFO +type MsgMhfGetUdSelectedColorInfo struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdSelectedColorInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_SELECTED_COLOR_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdSelectedColorInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdSelectedColorInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_shop_coin.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_shop_coin.go new file mode 100644 index 000000000..af66cfd94 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_shop_coin.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdShopCoin represents the MSG_MHF_GET_UD_SHOP_COIN +type MsgMhfGetUdShopCoin struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdShopCoin) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_SHOP_COIN +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdShopCoin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdShopCoin) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_bonus_quest.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_bonus_quest.go new file mode 100644 index 000000000..49f261ad0 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_bonus_quest.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdTacticsBonusQuest represents the MSG_MHF_GET_UD_TACTICS_BONUS_QUEST +type MsgMhfGetUdTacticsBonusQuest struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdTacticsBonusQuest) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_TACTICS_BONUS_QUEST +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdTacticsBonusQuest) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdTacticsBonusQuest) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_first_quest_bonus.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_first_quest_bonus.go new file mode 100644 index 000000000..8a685dff7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_first_quest_bonus.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdTacticsFirstQuestBonus represents the MSG_MHF_GET_UD_TACTICS_FIRST_QUEST_BONUS +type MsgMhfGetUdTacticsFirstQuestBonus struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdTacticsFirstQuestBonus) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_TACTICS_FIRST_QUEST_BONUS +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdTacticsFirstQuestBonus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdTacticsFirstQuestBonus) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_follower.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_follower.go new file mode 100644 index 000000000..0b8d8dc2b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_follower.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdTacticsFollower represents the MSG_MHF_GET_UD_TACTICS_FOLLOWER +type MsgMhfGetUdTacticsFollower struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdTacticsFollower) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_TACTICS_FOLLOWER +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdTacticsFollower) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdTacticsFollower) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_log.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_log.go new file mode 100644 index 000000000..50edae8da --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_log.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdTacticsLog represents the MSG_MHF_GET_UD_TACTICS_LOG +type MsgMhfGetUdTacticsLog struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdTacticsLog) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_TACTICS_LOG +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdTacticsLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdTacticsLog) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_point.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_point.go new file mode 100644 index 000000000..e688cddf4 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_point.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdTacticsPoint represents the MSG_MHF_GET_UD_TACTICS_POINT +type MsgMhfGetUdTacticsPoint struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdTacticsPoint) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_TACTICS_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdTacticsPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdTacticsPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_ranking.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_ranking.go new file mode 100644 index 000000000..feec60cc1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_ranking.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdTacticsRanking represents the MSG_MHF_GET_UD_TACTICS_RANKING +type MsgMhfGetUdTacticsRanking struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdTacticsRanking) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_TACTICS_RANKING +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdTacticsRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdTacticsRanking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_remaining_point.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_remaining_point.go new file mode 100644 index 000000000..dead858f9 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_remaining_point.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdTacticsRemainingPoint represents the MSG_MHF_GET_UD_TACTICS_REMAINING_POINT +type MsgMhfGetUdTacticsRemainingPoint struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdTacticsRemainingPoint) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_TACTICS_REMAINING_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdTacticsRemainingPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdTacticsRemainingPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_reward_list.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_reward_list.go new file mode 100644 index 000000000..c11fe3960 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_tactics_reward_list.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdTacticsRewardList represents the MSG_MHF_GET_UD_TACTICS_REWARD_LIST +type MsgMhfGetUdTacticsRewardList struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdTacticsRewardList) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_TACTICS_REWARD_LIST +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdTacticsRewardList) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdTacticsRewardList) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_ud_total_point_info.go b/Erupe/network/mhfpacket/msg_mhf_get_ud_total_point_info.go new file mode 100644 index 000000000..76ce686c1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_ud_total_point_info.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetUdTotalPointInfo represents the MSG_MHF_GET_UD_TOTAL_POINT_INFO +type MsgMhfGetUdTotalPointInfo struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetUdTotalPointInfo) Opcode() network.PacketID { + return network.MSG_MHF_GET_UD_TOTAL_POINT_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfGetUdTotalPointInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetUdTotalPointInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_weekly_schedule.go b/Erupe/network/mhfpacket/msg_mhf_get_weekly_schedule.go new file mode 100644 index 000000000..00313db5d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_weekly_schedule.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetWeeklySchedule represents the MSG_MHF_GET_WEEKLY_SCHEDULE +type MsgMhfGetWeeklySchedule struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetWeeklySchedule) Opcode() network.PacketID { + return network.MSG_MHF_GET_WEEKLY_SCHEDULE +} + +// Parse parses the packet from binary +func (m *MsgMhfGetWeeklySchedule) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetWeeklySchedule) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_get_weekly_seibatu_ranking_reward.go b/Erupe/network/mhfpacket/msg_mhf_get_weekly_seibatu_ranking_reward.go new file mode 100644 index 000000000..5e070ecf6 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_get_weekly_seibatu_ranking_reward.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGetWeeklySeibatuRankingReward represents the MSG_MHF_GET_WEEKLY_SEIBATU_RANKING_REWARD +type MsgMhfGetWeeklySeibatuRankingReward struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGetWeeklySeibatuRankingReward) Opcode() network.PacketID { + return network.MSG_MHF_GET_WEEKLY_SEIBATU_RANKING_REWARD +} + +// Parse parses the packet from binary +func (m *MsgMhfGetWeeklySeibatuRankingReward) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGetWeeklySeibatuRankingReward) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_guild_huntdata.go b/Erupe/network/mhfpacket/msg_mhf_guild_huntdata.go new file mode 100644 index 000000000..6123d662f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_guild_huntdata.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfGuildHuntdata represents the MSG_MHF_GUILD_HUNTDATA +type MsgMhfGuildHuntdata struct{ + AckHandle uint32 + Unk0 uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfGuildHuntdata) Opcode() network.PacketID { + return network.MSG_MHF_GUILD_HUNTDATA +} + +// Parse parses the packet from binary +func (m *MsgMhfGuildHuntdata) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfGuildHuntdata) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_info_festa.go b/Erupe/network/mhfpacket/msg_mhf_info_festa.go new file mode 100644 index 000000000..6e85a5bef --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_info_festa.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfInfoFesta represents the MSG_MHF_INFO_FESTA +type MsgMhfInfoFesta struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 0 in the binary + Unk1 uint16 // Hardcoded 0 in the binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfInfoFesta) Opcode() network.PacketID { + return network.MSG_MHF_INFO_FESTA +} + +// Parse parses the packet from binary +func (m *MsgMhfInfoFesta) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfInfoFesta) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_info_guild.go b/Erupe/network/mhfpacket/msg_mhf_info_guild.go new file mode 100644 index 000000000..9a13514dc --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_info_guild.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfInfoGuild represents the MSG_MHF_INFO_GUILD +type MsgMhfInfoGuild struct { + AckHandle uint32 + GuildID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfInfoGuild) Opcode() network.PacketID { + return network.MSG_MHF_INFO_GUILD +} + +// Parse parses the packet from binary +func (m *MsgMhfInfoGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GuildID = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfInfoGuild) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_info_joint.go b/Erupe/network/mhfpacket/msg_mhf_info_joint.go new file mode 100644 index 000000000..cfb19928b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_info_joint.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfInfoJoint represents the MSG_MHF_INFO_JOINT +type MsgMhfInfoJoint struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfInfoJoint) Opcode() network.PacketID { + return network.MSG_MHF_INFO_JOINT +} + +// Parse parses the packet from binary +func (m *MsgMhfInfoJoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfInfoJoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_info_scenario_counter.go b/Erupe/network/mhfpacket/msg_mhf_info_scenario_counter.go new file mode 100644 index 000000000..b34597f40 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_info_scenario_counter.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfInfoScenarioCounter represents the MSG_MHF_INFO_SCENARIO_COUNTER +type MsgMhfInfoScenarioCounter struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfInfoScenarioCounter) Opcode() network.PacketID { + return network.MSG_MHF_INFO_SCENARIO_COUNTER +} + +// Parse parses the packet from binary +func (m *MsgMhfInfoScenarioCounter) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfInfoScenarioCounter) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_info_tournament.go b/Erupe/network/mhfpacket/msg_mhf_info_tournament.go new file mode 100644 index 000000000..af09b5d3d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_info_tournament.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfInfoTournament represents the MSG_MHF_INFO_TOURNAMENT +type MsgMhfInfoTournament struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfInfoTournament) Opcode() network.PacketID { + return network.MSG_MHF_INFO_TOURNAMENT +} + +// Parse parses the packet from binary +func (m *MsgMhfInfoTournament) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfInfoTournament) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_kick_export_force.go b/Erupe/network/mhfpacket/msg_mhf_kick_export_force.go new file mode 100644 index 000000000..98075d7c1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_kick_export_force.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfKickExportForce represents the MSG_MHF_KICK_EXPORT_FORCE +type MsgMhfKickExportForce struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfKickExportForce) Opcode() network.PacketID { + return network.MSG_MHF_KICK_EXPORT_FORCE +} + +// Parse parses the packet from binary +func (m *MsgMhfKickExportForce) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfKickExportForce) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_list_mail.go b/Erupe/network/mhfpacket/msg_mhf_list_mail.go new file mode 100644 index 000000000..6080ecd81 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_list_mail.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfListMail represents the MSG_MHF_LIST_MAIL +type MsgMhfListMail struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfListMail) Opcode() network.PacketID { + return network.MSG_MHF_LIST_MAIL +} + +// Parse parses the packet from binary +func (m *MsgMhfListMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfListMail) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_list_member.go b/Erupe/network/mhfpacket/msg_mhf_list_member.go new file mode 100644 index 000000000..49fdf134e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_list_member.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfListMember represents the MSG_MHF_LIST_MEMBER +type MsgMhfListMember struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 01 00 in the JP client. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfListMember) Opcode() network.PacketID { + return network.MSG_MHF_LIST_MEMBER +} + +// Parse parses the packet from binary +func (m *MsgMhfListMember) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfListMember) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_deco_myset.go b/Erupe/network/mhfpacket/msg_mhf_load_deco_myset.go new file mode 100644 index 000000000..b7ffbd228 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_deco_myset.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadDecoMyset represents the MSG_MHF_LOAD_DECO_MYSET +type MsgMhfLoadDecoMyset struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadDecoMyset) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_DECO_MYSET +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadDecoMyset) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadDecoMyset) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_favorite_quest.go b/Erupe/network/mhfpacket/msg_mhf_load_favorite_quest.go new file mode 100644 index 000000000..43b9082ed --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_favorite_quest.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadFavoriteQuest represents the MSG_MHF_LOAD_FAVORITE_QUEST +type MsgMhfLoadFavoriteQuest struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadFavoriteQuest) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_FAVORITE_QUEST +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadFavoriteQuest) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadFavoriteQuest) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_guild_adventure.go b/Erupe/network/mhfpacket/msg_mhf_load_guild_adventure.go new file mode 100644 index 000000000..4e7086abd --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_guild_adventure.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadGuildAdventure represents the MSG_MHF_LOAD_GUILD_ADVENTURE +type MsgMhfLoadGuildAdventure struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadGuildAdventure) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_GUILD_ADVENTURE +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadGuildAdventure) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadGuildAdventure) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_guild_cooking.go b/Erupe/network/mhfpacket/msg_mhf_load_guild_cooking.go new file mode 100644 index 000000000..9dfa1cdda --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_guild_cooking.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadGuildCooking represents the MSG_MHF_LOAD_GUILD_COOKING +type MsgMhfLoadGuildCooking struct{ + AckHandle uint32 + Unk0 uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadGuildCooking) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_GUILD_COOKING +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadGuildCooking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadGuildCooking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_house.go b/Erupe/network/mhfpacket/msg_mhf_load_house.go new file mode 100644 index 000000000..154a71c77 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_house.go @@ -0,0 +1,42 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadHouse represents the MSG_MHF_LOAD_HOUSE +type MsgMhfLoadHouse struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint8 + Unk2 uint8 + Unk3 uint16 // Hardcoded 0 in binary + DataSize uint8 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadHouse) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_HOUSE +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadHouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint8() + m.Unk2 = bf.ReadUint8() + m.Unk3 = bf.ReadUint16() + m.DataSize = bf.ReadUint8() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadHouse) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_hunter_navi.go b/Erupe/network/mhfpacket/msg_mhf_load_hunter_navi.go new file mode 100644 index 000000000..653b77872 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_hunter_navi.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadHunterNavi represents the MSG_MHF_LOAD_HUNTER_NAVI +type MsgMhfLoadHunterNavi struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadHunterNavi) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_HUNTER_NAVI +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadHunterNavi) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadHunterNavi) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_legend_dispatch.go b/Erupe/network/mhfpacket/msg_mhf_load_legend_dispatch.go new file mode 100644 index 000000000..dbb03d938 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_legend_dispatch.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadLegendDispatch represents the MSG_MHF_LOAD_LEGEND_DISPATCH +type MsgMhfLoadLegendDispatch struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadLegendDispatch) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_LEGEND_DISPATCH +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadLegendDispatch) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadLegendDispatch) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_mezfes_data.go b/Erupe/network/mhfpacket/msg_mhf_load_mezfes_data.go new file mode 100644 index 000000000..7ef04fc67 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_mezfes_data.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadMezfesData represents the MSG_MHF_LOAD_MEZFES_DATA +type MsgMhfLoadMezfesData struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadMezfesData) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_MEZFES_DATA +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadMezfesData) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadMezfesData) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_otomo_airou.go b/Erupe/network/mhfpacket/msg_mhf_load_otomo_airou.go new file mode 100644 index 000000000..c5e7a8098 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_otomo_airou.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadOtomoAirou represents the MSG_MHF_LOAD_OTOMO_AIROU +type MsgMhfLoadOtomoAirou struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadOtomoAirou) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_OTOMO_AIROU +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadOtomoAirou) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadOtomoAirou) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_partner.go b/Erupe/network/mhfpacket/msg_mhf_load_partner.go new file mode 100644 index 000000000..6949b2d0c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_partner.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadPartner represents the MSG_MHF_LOAD_PARTNER +type MsgMhfLoadPartner struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadPartner) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_PARTNER +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadPartner) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadPartner) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_plate_box.go b/Erupe/network/mhfpacket/msg_mhf_load_plate_box.go new file mode 100644 index 000000000..12b9be566 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_plate_box.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadPlateBox represents the MSG_MHF_LOAD_PLATE_BOX +type MsgMhfLoadPlateBox struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadPlateBox) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_PLATE_BOX +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadPlateBox) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadPlateBox) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_plate_data.go b/Erupe/network/mhfpacket/msg_mhf_load_plate_data.go new file mode 100644 index 000000000..6fa5ce9f0 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_plate_data.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadPlateData represents the MSG_MHF_LOAD_PLATE_DATA +type MsgMhfLoadPlateData struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadPlateData) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_PLATE_DATA +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadPlateData) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadPlateData) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_plate_myset.go b/Erupe/network/mhfpacket/msg_mhf_load_plate_myset.go new file mode 100644 index 000000000..08f30beac --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_plate_myset.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadPlateMyset represents the MSG_MHF_LOAD_PLATE_MYSET +type MsgMhfLoadPlateMyset struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadPlateMyset) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_PLATE_MYSET +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadPlateMyset) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadPlateMyset) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_rengoku_data.go b/Erupe/network/mhfpacket/msg_mhf_load_rengoku_data.go new file mode 100644 index 000000000..89793874d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_rengoku_data.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadRengokuData represents the MSG_MHF_LOAD_RENGOKU_DATA +type MsgMhfLoadRengokuData struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadRengokuData) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_RENGOKU_DATA +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadRengokuData) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadRengokuData) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_load_scenario_data.go b/Erupe/network/mhfpacket/msg_mhf_load_scenario_data.go new file mode 100644 index 000000000..2bdc0e8e1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_load_scenario_data.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoadScenarioData represents the MSG_MHF_LOAD_SCENARIO_DATA +type MsgMhfLoadScenarioData struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoadScenarioData) Opcode() network.PacketID { + return network.MSG_MHF_LOAD_SCENARIO_DATA +} + +// Parse parses the packet from binary +func (m *MsgMhfLoadScenarioData) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoadScenarioData) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_loaddata.go b/Erupe/network/mhfpacket/msg_mhf_loaddata.go new file mode 100644 index 000000000..395095f9b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_loaddata.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfLoaddata represents the MSG_MHF_LOADDATA +type MsgMhfLoaddata struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfLoaddata) Opcode() network.PacketID { + return network.MSG_MHF_LOADDATA +} + +// Parse parses the packet from binary +func (m *MsgMhfLoaddata) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfLoaddata) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_mercenary_huntdata.go b/Erupe/network/mhfpacket/msg_mhf_mercenary_huntdata.go new file mode 100644 index 000000000..dc6cd1917 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_mercenary_huntdata.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfMercenaryHuntdata represents the MSG_MHF_MERCENARY_HUNTDATA +type MsgMhfMercenaryHuntdata struct{ + AckHandle uint32 + Unk0 uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfMercenaryHuntdata) Opcode() network.PacketID { + return network.MSG_MHF_MERCENARY_HUNTDATA +} + +// Parse parses the packet from binary +func (m *MsgMhfMercenaryHuntdata) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfMercenaryHuntdata) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_operate_guild.go b/Erupe/network/mhfpacket/msg_mhf_operate_guild.go new file mode 100644 index 000000000..165f51161 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_operate_guild.go @@ -0,0 +1,50 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +type OperateGuildAction uint8 + +const ( + OPERATE_GUILD_ACTION_DISBAND = 0x01 + OPERATE_GUILD_ACTION_APPLY = 0x02 + OPERATE_GUILD_ACTION_LEAVE = 0x03 + OPERATE_GUILD_SET_AVOID_LEADERSHIP_TRUE = 0x07 + OPERATE_GUILD_SET_AVOID_LEADERSHIP_FALSE = 0x08 + OPERATE_GUILD_ACTION_UPDATE_COMMENT = 0x09 + OPERATE_GUILD_ACTION_DONATE = 0x0a + OPERATE_GUILD_ACTION_UPDATE_MOTTO = 0x0b +) + +// MsgMhfOperateGuild represents the MSG_MHF_OPERATE_GUILD +type MsgMhfOperateGuild struct { + AckHandle uint32 + GuildID uint32 + Action OperateGuildAction + UnkData []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfOperateGuild) Opcode() network.PacketID { + return network.MSG_MHF_OPERATE_GUILD +} + +// Parse parses the packet from binary +func (m *MsgMhfOperateGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GuildID = bf.ReadUint32() + m.Action = OperateGuildAction(bf.ReadUint8()) + m.UnkData = bf.DataFromCurrent() + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfOperateGuild) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_operate_guild_member.go b/Erupe/network/mhfpacket/msg_mhf_operate_guild_member.go new file mode 100644 index 000000000..5ba26cce8 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_operate_guild_member.go @@ -0,0 +1,46 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +type OperateGuildMemberAction uint8 + +const ( + _ = iota + OPERATE_GUILD_MEMBER_ACTION_ACCEPT + OPERATE_GUILD_MEMBER_ACTION_REJECT + OPERATE_GUILD_MEMBER_ACTION_KICK +) + +// MsgMhfOperateGuildMember represents the MSG_MHF_OPERATE_GUILD_MEMBER +type MsgMhfOperateGuildMember struct { + AckHandle uint32 + GuildID uint32 + CharID uint32 + Action uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfOperateGuildMember) Opcode() network.PacketID { + return network.MSG_MHF_OPERATE_GUILD_MEMBER +} + +// Parse parses the packet from binary +func (m *MsgMhfOperateGuildMember) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GuildID = bf.ReadUint32() + m.CharID = bf.ReadUint32() + m.Action = bf.ReadUint8() + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfOperateGuildMember) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_operate_guild_tresure_report.go b/Erupe/network/mhfpacket/msg_mhf_operate_guild_tresure_report.go new file mode 100644 index 000000000..56917fba2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_operate_guild_tresure_report.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfOperateGuildTresureReport represents the MSG_MHF_OPERATE_GUILD_TRESURE_REPORT +type MsgMhfOperateGuildTresureReport struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfOperateGuildTresureReport) Opcode() network.PacketID { + return network.MSG_MHF_OPERATE_GUILD_TRESURE_REPORT +} + +// Parse parses the packet from binary +func (m *MsgMhfOperateGuildTresureReport) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfOperateGuildTresureReport) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_operate_joint.go b/Erupe/network/mhfpacket/msg_mhf_operate_joint.go new file mode 100644 index 000000000..34536628a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_operate_joint.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfOperateJoint represents the MSG_MHF_OPERATE_JOINT +type MsgMhfOperateJoint struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfOperateJoint) Opcode() network.PacketID { + return network.MSG_MHF_OPERATE_JOINT +} + +// Parse parses the packet from binary +func (m *MsgMhfOperateJoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfOperateJoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_operate_warehouse.go b/Erupe/network/mhfpacket/msg_mhf_operate_warehouse.go new file mode 100644 index 000000000..d4d242ba3 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_operate_warehouse.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfOperateWarehouse represents the MSG_MHF_OPERATE_WAREHOUSE +type MsgMhfOperateWarehouse struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfOperateWarehouse) Opcode() network.PacketID { + return network.MSG_MHF_OPERATE_WAREHOUSE +} + +// Parse parses the packet from binary +func (m *MsgMhfOperateWarehouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfOperateWarehouse) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_operation_inv_guild.go b/Erupe/network/mhfpacket/msg_mhf_operation_inv_guild.go new file mode 100644 index 000000000..06f74b5c1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_operation_inv_guild.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfOperationInvGuild represents the MSG_MHF_OPERATION_INV_GUILD +type MsgMhfOperationInvGuild struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfOperationInvGuild) Opcode() network.PacketID { + return network.MSG_MHF_OPERATION_INV_GUILD +} + +// Parse parses the packet from binary +func (m *MsgMhfOperationInvGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfOperationInvGuild) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_opr_member.go b/Erupe/network/mhfpacket/msg_mhf_opr_member.go new file mode 100644 index 000000000..cec6f5f22 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_opr_member.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfOprMember represents the MSG_MHF_OPR_MEMBER +type MsgMhfOprMember struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfOprMember) Opcode() network.PacketID { + return network.MSG_MHF_OPR_MEMBER +} + +// Parse parses the packet from binary +func (m *MsgMhfOprMember) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfOprMember) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_oprt_mail.go b/Erupe/network/mhfpacket/msg_mhf_oprt_mail.go new file mode 100644 index 000000000..13fb7557a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_oprt_mail.go @@ -0,0 +1,42 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +type OperateMailOperation uint8 + +const ( + OperateMailOperationDelete OperateMailOperation = 0x01 +) + +// MsgMhfOprtMail represents the MSG_MHF_OPRT_MAIL +type MsgMhfOprtMail struct { + AckHandle uint32 + AccIndex uint8 + Index uint8 + Operation uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfOprtMail) Opcode() network.PacketID { + return network.MSG_MHF_OPRT_MAIL +} + +// Parse parses the packet from binary +func (m *MsgMhfOprtMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.AccIndex = bf.ReadUint8() + m.Index = bf.ReadUint8() + m.Operation = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfOprtMail) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_payment_achievement.go b/Erupe/network/mhfpacket/msg_mhf_payment_achievement.go new file mode 100644 index 000000000..d4bb557d2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_payment_achievement.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPaymentAchievement represents the MSG_MHF_PAYMENT_ACHIEVEMENT +type MsgMhfPaymentAchievement struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPaymentAchievement) Opcode() network.PacketID { + return network.MSG_MHF_PAYMENT_ACHIEVEMENT +} + +// Parse parses the packet from binary +func (m *MsgMhfPaymentAchievement) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPaymentAchievement) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_play_box_gacha.go b/Erupe/network/mhfpacket/msg_mhf_play_box_gacha.go new file mode 100644 index 000000000..ce354e65f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_play_box_gacha.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPlayBoxGacha represents the MSG_MHF_PLAY_BOX_GACHA +type MsgMhfPlayBoxGacha struct{ + AckHandle uint32 + GachaHash uint32 + RollType uint8 + CurrencyMode uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPlayBoxGacha) Opcode() network.PacketID { + return network.MSG_MHF_PLAY_BOX_GACHA +} + +// Parse parses the packet from binary +func (m *MsgMhfPlayBoxGacha) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GachaHash = bf.ReadUint32() + m.RollType = bf.ReadUint8() + m.CurrencyMode = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPlayBoxGacha) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_play_free_gacha.go b/Erupe/network/mhfpacket/msg_mhf_play_free_gacha.go new file mode 100644 index 000000000..f2a59462a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_play_free_gacha.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPlayFreeGacha represents the MSG_MHF_PLAY_FREE_GACHA +type MsgMhfPlayFreeGacha struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPlayFreeGacha) Opcode() network.PacketID { + return network.MSG_MHF_PLAY_FREE_GACHA +} + +// Parse parses the packet from binary +func (m *MsgMhfPlayFreeGacha) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPlayFreeGacha) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_play_normal_gacha.go b/Erupe/network/mhfpacket/msg_mhf_play_normal_gacha.go new file mode 100644 index 000000000..213a781f3 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_play_normal_gacha.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPlayNormalGacha represents the MSG_MHF_PLAY_NORMAL_GACHA +type MsgMhfPlayNormalGacha struct{ + AckHandle uint32 + GachaHash uint32 + RollType uint8 + CurrencyMode uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPlayNormalGacha) Opcode() network.PacketID { + return network.MSG_MHF_PLAY_NORMAL_GACHA +} + +// Parse parses the packet from binary +func (m *MsgMhfPlayNormalGacha) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GachaHash = bf.ReadUint32() + m.RollType = bf.ReadUint8() + m.CurrencyMode = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPlayNormalGacha) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_play_stepup_gacha.go b/Erupe/network/mhfpacket/msg_mhf_play_stepup_gacha.go new file mode 100644 index 000000000..9556479e9 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_play_stepup_gacha.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPlayStepupGacha represents the MSG_MHF_PLAY_STEPUP_GACHA +type MsgMhfPlayStepupGacha struct{ + AckHandle uint32 + GachaHash uint32 + RollType uint8 + CurrencyMode uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPlayStepupGacha) Opcode() network.PacketID { + return network.MSG_MHF_PLAY_STEPUP_GACHA +} + +// Parse parses the packet from binary +func (m *MsgMhfPlayStepupGacha) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GachaHash = bf.ReadUint32() + m.RollType = bf.ReadUint8() + m.CurrencyMode = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPlayStepupGacha) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_boost_time.go b/Erupe/network/mhfpacket/msg_mhf_post_boost_time.go new file mode 100644 index 000000000..133e7f2b3 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_boost_time.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostBoostTime represents the MSG_MHF_POST_BOOST_TIME +type MsgMhfPostBoostTime struct { + AckHandle uint32 + BoostTime uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostBoostTime) Opcode() network.PacketID { + return network.MSG_MHF_POST_BOOST_TIME +} + +// Parse parses the packet from binary +func (m *MsgMhfPostBoostTime) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.BoostTime = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostBoostTime) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_boost_time_limit.go b/Erupe/network/mhfpacket/msg_mhf_post_boost_time_limit.go new file mode 100644 index 000000000..8a01ca987 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_boost_time_limit.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostBoostTimeLimit represents the MSG_MHF_POST_BOOST_TIME_LIMIT +type MsgMhfPostBoostTimeLimit struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostBoostTimeLimit) Opcode() network.PacketID { + return network.MSG_MHF_POST_BOOST_TIME_LIMIT +} + +// Parse parses the packet from binary +func (m *MsgMhfPostBoostTimeLimit) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostBoostTimeLimit) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_boost_time_quest_return.go b/Erupe/network/mhfpacket/msg_mhf_post_boost_time_quest_return.go new file mode 100644 index 000000000..6b8e7ba66 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_boost_time_quest_return.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostBoostTimeQuestReturn represents the MSG_MHF_POST_BOOST_TIME_QUEST_RETURN +type MsgMhfPostBoostTimeQuestReturn struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostBoostTimeQuestReturn) Opcode() network.PacketID { + return network.MSG_MHF_POST_BOOST_TIME_QUEST_RETURN +} + +// Parse parses the packet from binary +func (m *MsgMhfPostBoostTimeQuestReturn) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostBoostTimeQuestReturn) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_cafe_duration_bonus_received.go b/Erupe/network/mhfpacket/msg_mhf_post_cafe_duration_bonus_received.go new file mode 100644 index 000000000..84db3c9d0 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_cafe_duration_bonus_received.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostCafeDurationBonusReceived represents the MSG_MHF_POST_CAFE_DURATION_BONUS_RECEIVED +type MsgMhfPostCafeDurationBonusReceived struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostCafeDurationBonusReceived) Opcode() network.PacketID { + return network.MSG_MHF_POST_CAFE_DURATION_BONUS_RECEIVED +} + +// Parse parses the packet from binary +func (m *MsgMhfPostCafeDurationBonusReceived) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostCafeDurationBonusReceived) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_gem_info.go b/Erupe/network/mhfpacket/msg_mhf_post_gem_info.go new file mode 100644 index 000000000..68409ec30 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_gem_info.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostGemInfo represents the MSG_MHF_POST_GEM_INFO +type MsgMhfPostGemInfo struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostGemInfo) Opcode() network.PacketID { + return network.MSG_MHF_POST_GEM_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfPostGemInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostGemInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_guild_scout.go b/Erupe/network/mhfpacket/msg_mhf_post_guild_scout.go new file mode 100644 index 000000000..1e6a10413 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_guild_scout.go @@ -0,0 +1,33 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostGuildScout represents the MSG_MHF_POST_GUILD_SCOUT +type MsgMhfPostGuildScout struct { + AckHandle uint32 + CharID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostGuildScout) Opcode() network.PacketID { + return network.MSG_MHF_POST_GUILD_SCOUT +} + +// Parse parses the packet from binary +func (m *MsgMhfPostGuildScout) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.CharID = bf.ReadUint32() + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostGuildScout) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_notice.go b/Erupe/network/mhfpacket/msg_mhf_post_notice.go new file mode 100644 index 000000000..30f5f17d8 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_notice.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostNotice represents the MSG_MHF_POST_NOTICE +type MsgMhfPostNotice struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostNotice) Opcode() network.PacketID { + return network.MSG_MHF_POST_NOTICE +} + +// Parse parses the packet from binary +func (m *MsgMhfPostNotice) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostNotice) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_ryoudama.go b/Erupe/network/mhfpacket/msg_mhf_post_ryoudama.go new file mode 100644 index 000000000..4a924599a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_ryoudama.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostRyoudama represents the MSG_MHF_POST_RYOUDAMA +type MsgMhfPostRyoudama struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostRyoudama) Opcode() network.PacketID { + return network.MSG_MHF_POST_RYOUDAMA +} + +// Parse parses the packet from binary +func (m *MsgMhfPostRyoudama) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostRyoudama) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_seibattle.go b/Erupe/network/mhfpacket/msg_mhf_post_seibattle.go new file mode 100644 index 000000000..d3b7c4b79 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_seibattle.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostSeibattle represents the MSG_MHF_POST_SEIBATTLE +type MsgMhfPostSeibattle struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostSeibattle) Opcode() network.PacketID { + return network.MSG_MHF_POST_SEIBATTLE +} + +// Parse parses the packet from binary +func (m *MsgMhfPostSeibattle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostSeibattle) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_tenrouirai.go b/Erupe/network/mhfpacket/msg_mhf_post_tenrouirai.go new file mode 100644 index 000000000..4879e273e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_tenrouirai.go @@ -0,0 +1,42 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostTenrouirai represents the MSG_MHF_POST_TENROUIRAI +type MsgMhfPostTenrouirai struct{ + AckHandle uint32 + Unk0 uint16 + Unk1 uint32 + Unk2 uint32 + Unk3 uint32 + Unk4 uint32 + Unk5 uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostTenrouirai) Opcode() network.PacketID { + return network.MSG_MHF_POST_TENROUIRAI +} + +// Parse parses the packet from binary +func (m *MsgMhfPostTenrouirai) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + m.Unk3 = bf.ReadUint32() + m.Unk4 = bf.ReadUint32() + m.Unk5 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostTenrouirai) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_tiny_bin.go b/Erupe/network/mhfpacket/msg_mhf_post_tiny_bin.go new file mode 100644 index 000000000..a05945f1d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_tiny_bin.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostTinyBin represents the MSG_MHF_POST_TINY_BIN +type MsgMhfPostTinyBin struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostTinyBin) Opcode() network.PacketID { + return network.MSG_MHF_POST_TINY_BIN +} + +// Parse parses the packet from binary +func (m *MsgMhfPostTinyBin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostTinyBin) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_post_tower_info.go b/Erupe/network/mhfpacket/msg_mhf_post_tower_info.go new file mode 100644 index 000000000..8ac9e762b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_post_tower_info.go @@ -0,0 +1,53 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPostTowerInfo represents the MSG_MHF_POST_TOWER_INFO +type MsgMhfPostTowerInfo struct { + // Communicator type, multi-format. This might be valid for only one type. + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 + Unk2 uint32 + Unk3 uint32 + Unk4 uint32 + Unk5 uint32 + Unk6 uint32 + Unk7 uint32 + Unk8 uint32 + Unk9 uint32 + Unk10 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPostTowerInfo) Opcode() network.PacketID { + return network.MSG_MHF_POST_TOWER_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfPostTowerInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + m.Unk3 = bf.ReadUint32() + m.Unk4 = bf.ReadUint32() + m.Unk5 = bf.ReadUint32() + m.Unk6 = bf.ReadUint32() + m.Unk7 = bf.ReadUint32() + m.Unk8 = bf.ReadUint32() + m.Unk9 = bf.ReadUint32() + m.Unk10 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPostTowerInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_present_box.go b/Erupe/network/mhfpacket/msg_mhf_present_box.go new file mode 100644 index 000000000..ea56fa30c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_present_box.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfPresentBox represents the MSG_MHF_PRESENT_BOX +type MsgMhfPresentBox struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfPresentBox) Opcode() network.PacketID { + return network.MSG_MHF_PRESENT_BOX +} + +// Parse parses the packet from binary +func (m *MsgMhfPresentBox) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfPresentBox) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_read_beat_level.go b/Erupe/network/mhfpacket/msg_mhf_read_beat_level.go new file mode 100644 index 000000000..57eb4a899 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_read_beat_level.go @@ -0,0 +1,41 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReadBeatLevel represents the MSG_MHF_READ_BEAT_LEVEL +type MsgMhfReadBeatLevel struct { + AckHandle uint32 + Unk0 uint32 + ValidIDCount uint32 // Valid entries in the array + IDs [16]uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReadBeatLevel) Opcode() network.PacketID { + return network.MSG_MHF_READ_BEAT_LEVEL +} + +// Parse parses the packet from binary +func (m *MsgMhfReadBeatLevel) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // I assume this used to be dynamic, but as of the last JP client version, all of this data is hard-coded literals. + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() // Always 1 + m.ValidIDCount = bf.ReadUint32() // Always 4 + + // Always 0x74, 0x6B, 0x02, 0x24 followed by 12 zero values. + for i := 0; i < len(m.IDs); i++ { + m.IDs[i] = bf.ReadUint32() + } + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReadBeatLevel) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_read_beat_level_all_ranking.go b/Erupe/network/mhfpacket/msg_mhf_read_beat_level_all_ranking.go new file mode 100644 index 000000000..5af74dadc --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_read_beat_level_all_ranking.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReadBeatLevelAllRanking represents the MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING +type MsgMhfReadBeatLevelAllRanking struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReadBeatLevelAllRanking) Opcode() network.PacketID { + return network.MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING +} + +// Parse parses the packet from binary +func (m *MsgMhfReadBeatLevelAllRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReadBeatLevelAllRanking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_read_beat_level_my_ranking.go b/Erupe/network/mhfpacket/msg_mhf_read_beat_level_my_ranking.go new file mode 100644 index 000000000..243b49876 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_read_beat_level_my_ranking.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReadBeatLevelMyRanking represents the MSG_MHF_READ_BEAT_LEVEL_MY_RANKING +type MsgMhfReadBeatLevelMyRanking struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReadBeatLevelMyRanking) Opcode() network.PacketID { + return network.MSG_MHF_READ_BEAT_LEVEL_MY_RANKING +} + +// Parse parses the packet from binary +func (m *MsgMhfReadBeatLevelMyRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReadBeatLevelMyRanking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_read_guildcard.go b/Erupe/network/mhfpacket/msg_mhf_read_guildcard.go new file mode 100644 index 000000000..f2589cdd6 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_read_guildcard.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReadGuildcard represents the MSG_MHF_READ_GUILDCARD +type MsgMhfReadGuildcard struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReadGuildcard) Opcode() network.PacketID { + return network.MSG_MHF_READ_GUILDCARD +} + +// Parse parses the packet from binary +func (m *MsgMhfReadGuildcard) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReadGuildcard) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_read_last_week_beat_ranking.go b/Erupe/network/mhfpacket/msg_mhf_read_last_week_beat_ranking.go new file mode 100644 index 000000000..954c21c26 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_read_last_week_beat_ranking.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReadLastWeekBeatRanking represents the MSG_MHF_READ_LAST_WEEK_BEAT_RANKING +type MsgMhfReadLastWeekBeatRanking struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReadLastWeekBeatRanking) Opcode() network.PacketID { + return network.MSG_MHF_READ_LAST_WEEK_BEAT_RANKING +} + +// Parse parses the packet from binary +func (m *MsgMhfReadLastWeekBeatRanking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReadLastWeekBeatRanking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_read_mail.go b/Erupe/network/mhfpacket/msg_mhf_read_mail.go new file mode 100644 index 000000000..ca0b45889 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_read_mail.go @@ -0,0 +1,40 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReadMail represents the MSG_MHF_READ_MAIL +type MsgMhfReadMail struct { + AckHandle uint32 + + // AccIndex is incremented for each mail in the list + // The index is persistent for game session, reopening the mail list + // will continue from the last index + 1 + AccIndex uint8 + + // This is the index within the current mail list + Index uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReadMail) Opcode() network.PacketID { + return network.MSG_MHF_READ_MAIL +} + +// Parse parses the packet from binary +func (m *MsgMhfReadMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.AccIndex = bf.ReadUint8() + m.Index = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReadMail) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_read_mercenary_m.go b/Erupe/network/mhfpacket/msg_mhf_read_mercenary_m.go new file mode 100644 index 000000000..19df99550 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_read_mercenary_m.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReadMercenaryM represents the MSG_MHF_READ_MERCENARY_M +type MsgMhfReadMercenaryM struct{ + AckHandle uint32 + CharID uint32 + Unk0 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReadMercenaryM) Opcode() network.PacketID { + return network.MSG_MHF_READ_MERCENARY_M +} + +// Parse parses the packet from binary +func (m *MsgMhfReadMercenaryM) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.CharID = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReadMercenaryM) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_read_mercenary_w.go b/Erupe/network/mhfpacket/msg_mhf_read_mercenary_w.go new file mode 100644 index 000000000..3cfca30d6 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_read_mercenary_w.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReadMercenaryW represents the MSG_MHF_READ_MERCENARY_W +type MsgMhfReadMercenaryW struct { + AckHandle uint32 + Unk0 uint8 + Unk1 uint8 + Unk2 uint16 // Hardcoded 0 in the binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReadMercenaryW) Opcode() network.PacketID { + return network.MSG_MHF_READ_MERCENARY_W +} + +// Parse parses the packet from binary +func (m *MsgMhfReadMercenaryW) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReadMercenaryW) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_receive_cafe_duration_bonus.go b/Erupe/network/mhfpacket/msg_mhf_receive_cafe_duration_bonus.go new file mode 100644 index 000000000..77b832c1c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_receive_cafe_duration_bonus.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReceiveCafeDurationBonus represents the MSG_MHF_RECEIVE_CAFE_DURATION_BONUS +type MsgMhfReceiveCafeDurationBonus struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReceiveCafeDurationBonus) Opcode() network.PacketID { + return network.MSG_MHF_RECEIVE_CAFE_DURATION_BONUS +} + +// Parse parses the packet from binary +func (m *MsgMhfReceiveCafeDurationBonus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReceiveCafeDurationBonus) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_receive_gacha_item.go b/Erupe/network/mhfpacket/msg_mhf_receive_gacha_item.go new file mode 100644 index 000000000..cc772896a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_receive_gacha_item.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReceiveGachaItem represents the MSG_MHF_RECEIVE_GACHA_ITEM +type MsgMhfReceiveGachaItem struct{ + AckHandle uint32 + Unk0 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReceiveGachaItem) Opcode() network.PacketID { + return network.MSG_MHF_RECEIVE_GACHA_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfReceiveGachaItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReceiveGachaItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_regist_guild_adventure.go b/Erupe/network/mhfpacket/msg_mhf_regist_guild_adventure.go new file mode 100644 index 000000000..2b3143dd0 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_regist_guild_adventure.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfRegistGuildAdventure represents the MSG_MHF_REGIST_GUILD_ADVENTURE +type MsgMhfRegistGuildAdventure struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfRegistGuildAdventure) Opcode() network.PacketID { + return network.MSG_MHF_REGIST_GUILD_ADVENTURE +} + +// Parse parses the packet from binary +func (m *MsgMhfRegistGuildAdventure) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfRegistGuildAdventure) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_regist_guild_cooking.go b/Erupe/network/mhfpacket/msg_mhf_regist_guild_cooking.go new file mode 100644 index 000000000..af66d74ce --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_regist_guild_cooking.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfRegistGuildCooking represents the MSG_MHF_REGIST_GUILD_COOKING +type MsgMhfRegistGuildCooking struct{ + AckHandle uint32 + Unk0 uint32 + Unk1 uint16 + Unk2 uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfRegistGuildCooking) Opcode() network.PacketID { + return network.MSG_MHF_REGIST_GUILD_COOKING +} + +// Parse parses the packet from binary +func (m *MsgMhfRegistGuildCooking) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint16() + m.Unk2 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfRegistGuildCooking) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_regist_guild_tresure.go b/Erupe/network/mhfpacket/msg_mhf_regist_guild_tresure.go new file mode 100644 index 000000000..fda8dc4cc --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_regist_guild_tresure.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfRegistGuildTresure represents the MSG_MHF_REGIST_GUILD_TRESURE +type MsgMhfRegistGuildTresure struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfRegistGuildTresure) Opcode() network.PacketID { + return network.MSG_MHF_REGIST_GUILD_TRESURE +} + +// Parse parses the packet from binary +func (m *MsgMhfRegistGuildTresure) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfRegistGuildTresure) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_regist_spabi_time.go b/Erupe/network/mhfpacket/msg_mhf_regist_spabi_time.go new file mode 100644 index 000000000..7d15ad4c7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_regist_spabi_time.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfRegistSpabiTime represents the MSG_MHF_REGIST_SPABI_TIME +type MsgMhfRegistSpabiTime struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfRegistSpabiTime) Opcode() network.PacketID { + return network.MSG_MHF_REGIST_SPABI_TIME +} + +// Parse parses the packet from binary +func (m *MsgMhfRegistSpabiTime) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfRegistSpabiTime) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_register_event.go b/Erupe/network/mhfpacket/msg_mhf_register_event.go new file mode 100644 index 000000000..2d77ebbf7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_register_event.go @@ -0,0 +1,40 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfRegisterEvent represents the MSG_MHF_REGISTER_EVENT +type MsgMhfRegisterEvent struct { + AckHandle uint32 + Unk0 uint16 + Unk1 uint8 + Unk2 uint8 + Unk3 uint8 + Unk4 uint8 + Unk5 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfRegisterEvent) Opcode() network.PacketID { + return network.MSG_MHF_REGISTER_EVENT +} + +// Parse parses the packet from binary +func (m *MsgMhfRegisterEvent) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint8() + m.Unk2 = bf.ReadUint8() + m.Unk3 = bf.ReadUint8() + m.Unk4 = bf.ReadUint8() + m.Unk5 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfRegisterEvent) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_release_event.go b/Erupe/network/mhfpacket/msg_mhf_release_event.go new file mode 100644 index 000000000..6b3ec0058 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_release_event.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgMhfReleaseEvent represents the MSG_MHF_RELEASE_EVENT +type MsgMhfReleaseEvent struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReleaseEvent) Opcode() network.PacketID { + return network.MSG_MHF_RELEASE_EVENT +} + +// Parse parses the packet from binary +func (m *MsgMhfReleaseEvent) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReleaseEvent) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_reserve010f.go b/Erupe/network/mhfpacket/msg_mhf_reserve010f.go new file mode 100644 index 000000000..49bdb36e2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_reserve010f.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfReserve010F represents the MSG_MHF_reserve010F +type MsgMhfReserve010F struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfReserve010F) Opcode() network.PacketID { + return network.MSG_MHF_reserve010F +} + +// Parse parses the packet from binary +func (m *MsgMhfReserve010F) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfReserve010F) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_reset_achievement.go b/Erupe/network/mhfpacket/msg_mhf_reset_achievement.go new file mode 100644 index 000000000..71554581f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_reset_achievement.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfResetAchievement represents the MSG_MHF_RESET_ACHIEVEMENT +type MsgMhfResetAchievement struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfResetAchievement) Opcode() network.PacketID { + return network.MSG_MHF_RESET_ACHIEVEMENT +} + +// Parse parses the packet from binary +func (m *MsgMhfResetAchievement) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfResetAchievement) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_reset_box_gacha_info.go b/Erupe/network/mhfpacket/msg_mhf_reset_box_gacha_info.go new file mode 100644 index 000000000..856abd2f2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_reset_box_gacha_info.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfResetBoxGachaInfo represents the MSG_MHF_RESET_BOX_GACHA_INFO +type MsgMhfResetBoxGachaInfo struct{ + AckHandle uint32 + GachaHash uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfResetBoxGachaInfo) Opcode() network.PacketID { + return network.MSG_MHF_RESET_BOX_GACHA_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfResetBoxGachaInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GachaHash = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfResetBoxGachaInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_reset_title.go b/Erupe/network/mhfpacket/msg_mhf_reset_title.go new file mode 100644 index 000000000..1ba19cb3c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_reset_title.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfResetTitle represents the MSG_MHF_RESET_TITLE +type MsgMhfResetTitle struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfResetTitle) Opcode() network.PacketID { + return network.MSG_MHF_RESET_TITLE +} + +// Parse parses the packet from binary +func (m *MsgMhfResetTitle) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfResetTitle) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_deco_myset.go b/Erupe/network/mhfpacket/msg_mhf_save_deco_myset.go new file mode 100644 index 000000000..358b9f261 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_deco_myset.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSaveDecoMyset represents the MSG_MHF_SAVE_DECO_MYSET +type MsgMhfSaveDecoMyset struct { + AckHandle uint32 + DataSize uint32 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSaveDecoMyset) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_DECO_MYSET +} + +// Parse parses the packet from binary +func (m *MsgMhfSaveDecoMyset) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSaveDecoMyset) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_favorite_quest.go b/Erupe/network/mhfpacket/msg_mhf_save_favorite_quest.go new file mode 100644 index 000000000..d398a365f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_favorite_quest.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSaveFavoriteQuest represents the MSG_MHF_SAVE_FAVORITE_QUEST +type MsgMhfSaveFavoriteQuest struct { + AckHandle uint32 + DataSize uint16 + Data []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSaveFavoriteQuest) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_FAVORITE_QUEST +} + +// Parse parses the packet from binary +func (m *MsgMhfSaveFavoriteQuest) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint16() + m.Data = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSaveFavoriteQuest) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_hunter_navi.go b/Erupe/network/mhfpacket/msg_mhf_save_hunter_navi.go new file mode 100644 index 000000000..9945b6173 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_hunter_navi.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSaveHunterNavi represents the MSG_MHF_SAVE_HUNTER_NAVI +type MsgMhfSaveHunterNavi struct { + AckHandle uint32 + DataSize uint32 + IsDataDiff bool + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSaveHunterNavi) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_HUNTER_NAVI +} + +// Parse parses the packet from binary +func (m *MsgMhfSaveHunterNavi) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.IsDataDiff = bf.ReadBool() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSaveHunterNavi) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_mercenary.go b/Erupe/network/mhfpacket/msg_mhf_save_mercenary.go new file mode 100644 index 000000000..b192c0f44 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_mercenary.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSaveMercenary represents the MSG_MHF_SAVE_MERCENARY +type MsgMhfSaveMercenary struct{ + AckHandle uint32 + DataSize uint32 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSaveMercenary) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_MERCENARY +} + +// Parse parses the packet from binary +func (m *MsgMhfSaveMercenary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSaveMercenary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_mezfes_data.go b/Erupe/network/mhfpacket/msg_mhf_save_mezfes_data.go new file mode 100644 index 000000000..c3efec967 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_mezfes_data.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSaveMezfesData represents the MSG_MHF_SAVE_MEZFES_DATA +type MsgMhfSaveMezfesData struct { + AckHandle uint32 + DataSize uint32 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSaveMezfesData) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_MEZFES_DATA +} + +// Parse parses the packet from binary +func (m *MsgMhfSaveMezfesData) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSaveMezfesData) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_otomo_airou.go b/Erupe/network/mhfpacket/msg_mhf_save_otomo_airou.go new file mode 100644 index 000000000..c153073eb --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_otomo_airou.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSaveOtomoAirou represents the MSG_MHF_SAVE_OTOMO_AIROU +type MsgMhfSaveOtomoAirou struct { + AckHandle uint32 + DataSize uint16 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSaveOtomoAirou) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_OTOMO_AIROU +} + +// Parse parses the packet from binary +func (m *MsgMhfSaveOtomoAirou) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSaveOtomoAirou) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_partner.go b/Erupe/network/mhfpacket/msg_mhf_save_partner.go new file mode 100644 index 000000000..e6c262b07 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_partner.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSavePartner represents the MSG_MHF_SAVE_PARTNER +type MsgMhfSavePartner struct { + AckHandle uint32 + DataSize uint16 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSavePartner) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_PARTNER +} + +// Parse parses the packet from binary +func (m *MsgMhfSavePartner) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSavePartner) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_plate_box.go b/Erupe/network/mhfpacket/msg_mhf_save_plate_box.go new file mode 100644 index 000000000..54bcf704f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_plate_box.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSavePlateBox represents the MSG_MHF_SAVE_PLATE_BOX +type MsgMhfSavePlateBox struct { + AckHandle uint32 + DataSize uint32 + IsDataDiff bool + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSavePlateBox) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_PLATE_BOX +} + +// Parse parses the packet from binary +func (m *MsgMhfSavePlateBox) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.IsDataDiff = bf.ReadBool() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSavePlateBox) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_plate_data.go b/Erupe/network/mhfpacket/msg_mhf_save_plate_data.go new file mode 100644 index 000000000..098ceeef7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_plate_data.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSavePlateData represents the MSG_MHF_SAVE_PLATE_DATA +type MsgMhfSavePlateData struct { + AckHandle uint32 + DataSize uint32 + IsDataDiff bool + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSavePlateData) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_PLATE_DATA +} + +// Parse parses the packet from binary +func (m *MsgMhfSavePlateData) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.IsDataDiff = bf.ReadBool() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSavePlateData) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_plate_myset.go b/Erupe/network/mhfpacket/msg_mhf_save_plate_myset.go new file mode 100644 index 000000000..01437611e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_plate_myset.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSavePlateMyset represents the MSG_MHF_SAVE_PLATE_MYSET +type MsgMhfSavePlateMyset struct { + AckHandle uint32 + DataSize uint32 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSavePlateMyset) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_PLATE_MYSET +} + +// Parse parses the packet from binary +func (m *MsgMhfSavePlateMyset) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSavePlateMyset) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_rengoku_data.go b/Erupe/network/mhfpacket/msg_mhf_save_rengoku_data.go new file mode 100644 index 000000000..25f1feacf --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_rengoku_data.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSaveRengokuData represents the MSG_MHF_SAVE_RENGOKU_DATA +type MsgMhfSaveRengokuData struct { + AckHandle uint32 + DataSize uint32 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSaveRengokuData) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_RENGOKU_DATA +} + +// Parse parses the packet from binary +func (m *MsgMhfSaveRengokuData) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSaveRengokuData) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_save_scenario_data.go b/Erupe/network/mhfpacket/msg_mhf_save_scenario_data.go new file mode 100644 index 000000000..27f8bf613 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_save_scenario_data.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSaveScenarioData represents the MSG_MHF_SAVE_SCENARIO_DATA +type MsgMhfSaveScenarioData struct { + AckHandle uint32 + DataSize uint32 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSaveScenarioData) Opcode() network.PacketID { + return network.MSG_MHF_SAVE_SCENARIO_DATA +} + +// Parse parses the packet from binary +func (m *MsgMhfSaveScenarioData) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSaveScenarioData) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_savedata.go b/Erupe/network/mhfpacket/msg_mhf_savedata.go new file mode 100644 index 000000000..9697e2e83 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_savedata.go @@ -0,0 +1,44 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSavedata represents the MSG_MHF_SAVEDATA +type MsgMhfSavedata struct { + AckHandle uint32 + AllocMemSize uint32 + SaveType uint8 // Either 1 or 2, representing a true or false value for some reason. + Unk1 uint32 + DataSize uint32 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSavedata) Opcode() network.PacketID { + return network.MSG_MHF_SAVEDATA +} + +// Parse parses the packet from binary +func (m *MsgMhfSavedata) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.AllocMemSize = bf.ReadUint32() + m.SaveType = bf.ReadUint8() + m.Unk1 = bf.ReadUint32() + m.DataSize = bf.ReadUint32() + if m.DataSize == 0 { // seems to be used when DataSize = 0 rather than on savetype? + m.RawDataPayload = bf.ReadBytes(uint(m.AllocMemSize)) + } else { + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + } + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSavedata) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_send_mail.go b/Erupe/network/mhfpacket/msg_mhf_send_mail.go new file mode 100644 index 000000000..56969a966 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_send_mail.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSendMail represents the MSG_MHF_SEND_MAIL +type MsgMhfSendMail struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSendMail) Opcode() network.PacketID { + return network.MSG_MHF_SEND_MAIL +} + +// Parse parses the packet from binary +func (m *MsgMhfSendMail) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSendMail) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_server_command.go b/Erupe/network/mhfpacket/msg_mhf_server_command.go new file mode 100644 index 000000000..0b87b8953 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_server_command.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfServerCommand represents the MSG_MHF_SERVER_COMMAND +type MsgMhfServerCommand struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfServerCommand) Opcode() network.PacketID { + return network.MSG_MHF_SERVER_COMMAND +} + +// Parse parses the packet from binary +func (m *MsgMhfServerCommand) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfServerCommand) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_ca_achievement.go b/Erupe/network/mhfpacket/msg_mhf_set_ca_achievement.go new file mode 100644 index 000000000..6eb388598 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_ca_achievement.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetCaAchievement represents the MSG_MHF_SET_CA_ACHIEVEMENT +type MsgMhfSetCaAchievement struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetCaAchievement) Opcode() network.PacketID { + return network.MSG_MHF_SET_CA_ACHIEVEMENT +} + +// Parse parses the packet from binary +func (m *MsgMhfSetCaAchievement) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetCaAchievement) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_ca_achievement_hist.go b/Erupe/network/mhfpacket/msg_mhf_set_ca_achievement_hist.go new file mode 100644 index 000000000..053f4d03a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_ca_achievement_hist.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetCaAchievementHist represents the MSG_MHF_SET_CA_ACHIEVEMENT_HIST +type MsgMhfSetCaAchievementHist struct{ + AckHandle uint32 + Unk0 uint32 + Unk1 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetCaAchievementHist) Opcode() network.PacketID { + return network.MSG_MHF_SET_CA_ACHIEVEMENT_HIST +} + +// Parse parses the packet from binary +func (m *MsgMhfSetCaAchievementHist) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetCaAchievementHist) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_daily_mission_personal.go b/Erupe/network/mhfpacket/msg_mhf_set_daily_mission_personal.go new file mode 100644 index 000000000..427ecfa6b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_daily_mission_personal.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetDailyMissionPersonal represents the MSG_MHF_SET_DAILY_MISSION_PERSONAL +type MsgMhfSetDailyMissionPersonal struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetDailyMissionPersonal) Opcode() network.PacketID { + return network.MSG_MHF_SET_DAILY_MISSION_PERSONAL +} + +// Parse parses the packet from binary +func (m *MsgMhfSetDailyMissionPersonal) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetDailyMissionPersonal) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_enhanced_minidata.go b/Erupe/network/mhfpacket/msg_mhf_set_enhanced_minidata.go new file mode 100644 index 000000000..4e5b9901d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_enhanced_minidata.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetEnhancedMinidata represents the MSG_MHF_SET_ENHANCED_MINIDATA +type MsgMhfSetEnhancedMinidata struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 4 in the binary. + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetEnhancedMinidata) Opcode() network.PacketID { + return network.MSG_MHF_SET_ENHANCED_MINIDATA +} + +// Parse parses the packet from binary +func (m *MsgMhfSetEnhancedMinidata) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(0x400) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetEnhancedMinidata) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_guild_manage_right.go b/Erupe/network/mhfpacket/msg_mhf_set_guild_manage_right.go new file mode 100644 index 000000000..373b39952 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_guild_manage_right.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetGuildManageRight represents the MSG_MHF_SET_GUILD_MANAGE_RIGHT +type MsgMhfSetGuildManageRight struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetGuildManageRight) Opcode() network.PacketID { + return network.MSG_MHF_SET_GUILD_MANAGE_RIGHT +} + +// Parse parses the packet from binary +func (m *MsgMhfSetGuildManageRight) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetGuildManageRight) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_guild_mission_target.go b/Erupe/network/mhfpacket/msg_mhf_set_guild_mission_target.go new file mode 100644 index 000000000..55958258d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_guild_mission_target.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetGuildMissionTarget represents the MSG_MHF_SET_GUILD_MISSION_TARGET +type MsgMhfSetGuildMissionTarget struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetGuildMissionTarget) Opcode() network.PacketID { + return network.MSG_MHF_SET_GUILD_MISSION_TARGET +} + +// Parse parses the packet from binary +func (m *MsgMhfSetGuildMissionTarget) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetGuildMissionTarget) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_kiju.go b/Erupe/network/mhfpacket/msg_mhf_set_kiju.go new file mode 100644 index 000000000..c95cffe25 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_kiju.go @@ -0,0 +1,33 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetKiju represents the MSG_MHF_SET_KIJU +type MsgMhfSetKiju struct { + AckHandle uint32 + Unk1 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetKiju) Opcode() network.PacketID { + return network.MSG_MHF_SET_KIJU +} + +// Parse parses the packet from binary +func (m *MsgMhfSetKiju) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk1 = bf.ReadUint16() + return nil + //panic("Not implemented") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetKiju) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_loginwindow.go b/Erupe/network/mhfpacket/msg_mhf_set_loginwindow.go new file mode 100644 index 000000000..a06390c3d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_loginwindow.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetLoginwindow represents the MSG_MHF_SET_LOGINWINDOW +type MsgMhfSetLoginwindow struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetLoginwindow) Opcode() network.PacketID { + return network.MSG_MHF_SET_LOGINWINDOW +} + +// Parse parses the packet from binary +func (m *MsgMhfSetLoginwindow) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetLoginwindow) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_reject_guild_scout.go b/Erupe/network/mhfpacket/msg_mhf_set_reject_guild_scout.go new file mode 100644 index 000000000..0449e0e91 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_reject_guild_scout.go @@ -0,0 +1,33 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetRejectGuildScout represents the MSG_MHF_SET_REJECT_GUILD_SCOUT +type MsgMhfSetRejectGuildScout struct { + AckHandle uint32 + Reject bool +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetRejectGuildScout) Opcode() network.PacketID { + return network.MSG_MHF_SET_REJECT_GUILD_SCOUT +} + +// Parse parses the packet from binary +func (m *MsgMhfSetRejectGuildScout) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Reject = bf.ReadBool() + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetRejectGuildScout) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_restriction_event.go b/Erupe/network/mhfpacket/msg_mhf_set_restriction_event.go new file mode 100644 index 000000000..f5b12a3fd --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_restriction_event.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetRestrictionEvent represents the MSG_MHF_SET_RESTRICTION_EVENT +type MsgMhfSetRestrictionEvent struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetRestrictionEvent) Opcode() network.PacketID { + return network.MSG_MHF_SET_RESTRICTION_EVENT +} + +// Parse parses the packet from binary +func (m *MsgMhfSetRestrictionEvent) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetRestrictionEvent) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_set_ud_tactics_follower.go b/Erupe/network/mhfpacket/msg_mhf_set_ud_tactics_follower.go new file mode 100644 index 000000000..1a530128b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_set_ud_tactics_follower.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSetUdTacticsFollower represents the MSG_MHF_SET_UD_TACTICS_FOLLOWER +type MsgMhfSetUdTacticsFollower struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSetUdTacticsFollower) Opcode() network.PacketID { + return network.MSG_MHF_SET_UD_TACTICS_FOLLOWER +} + +// Parse parses the packet from binary +func (m *MsgMhfSetUdTacticsFollower) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSetUdTacticsFollower) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_sex_changer.go b/Erupe/network/mhfpacket/msg_mhf_sex_changer.go new file mode 100644 index 000000000..d7f247b6d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_sex_changer.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfSexChanger represents the MSG_MHF_SEX_CHANGER +type MsgMhfSexChanger struct { + AckHandle uint32 + Gender uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfSexChanger) Opcode() network.PacketID { + return network.MSG_MHF_SEX_CHANGER +} + +// Parse parses the packet from binary +func (m *MsgMhfSexChanger) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Gender = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfSexChanger) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_shut_client.go b/Erupe/network/mhfpacket/msg_mhf_shut_client.go new file mode 100644 index 000000000..b7f9692d4 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_shut_client.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfShutClient represents the MSG_MHF_SHUT_CLIENT +type MsgMhfShutClient struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfShutClient) Opcode() network.PacketID { + return network.MSG_MHF_SHUT_CLIENT +} + +// Parse parses the packet from binary +func (m *MsgMhfShutClient) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfShutClient) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_stampcard_prize.go b/Erupe/network/mhfpacket/msg_mhf_stampcard_prize.go new file mode 100644 index 000000000..54daadf18 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_stampcard_prize.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfStampcardPrize represents the MSG_MHF_STAMPCARD_PRIZE +type MsgMhfStampcardPrize struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfStampcardPrize) Opcode() network.PacketID { + return network.MSG_MHF_STAMPCARD_PRIZE +} + +// Parse parses the packet from binary +func (m *MsgMhfStampcardPrize) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfStampcardPrize) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_stampcard_stamp.go b/Erupe/network/mhfpacket/msg_mhf_stampcard_stamp.go new file mode 100644 index 000000000..37b468e3a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_stampcard_stamp.go @@ -0,0 +1,51 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfStampcardStamp represents the MSG_MHF_STAMPCARD_STAMP +type MsgMhfStampcardStamp struct { + // Field-size accurate. + AckHandle uint32 + Unk0 uint16 + Unk1 uint16 + Unk2 uint16 + Unk3 uint16 // Hardcoded 0 in binary + Unk4 uint32 + Unk5 uint32 + Unk6 uint32 + Unk7 uint32 + Unk8 uint32 + Unk9 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfStampcardStamp) Opcode() network.PacketID { + return network.MSG_MHF_STAMPCARD_STAMP +} + +// Parse parses the packet from binary +func (m *MsgMhfStampcardStamp) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + m.Unk2 = bf.ReadUint16() + m.Unk3 = bf.ReadUint16() + m.Unk4 = bf.ReadUint32() + m.Unk5 = bf.ReadUint32() + m.Unk6 = bf.ReadUint32() + m.Unk7 = bf.ReadUint32() + m.Unk8 = bf.ReadUint32() + m.Unk9 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfStampcardStamp) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_start_boost_time.go b/Erupe/network/mhfpacket/msg_mhf_start_boost_time.go new file mode 100644 index 000000000..221e46875 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_start_boost_time.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfStartBoostTime represents the MSG_MHF_START_BOOST_TIME +type MsgMhfStartBoostTime struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfStartBoostTime) Opcode() network.PacketID { + return network.MSG_MHF_START_BOOST_TIME +} + +// Parse parses the packet from binary +func (m *MsgMhfStartBoostTime) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfStartBoostTime) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_state_campaign.go b/Erupe/network/mhfpacket/msg_mhf_state_campaign.go new file mode 100644 index 000000000..bb4f3cba9 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_state_campaign.go @@ -0,0 +1,39 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network/clientctx" + + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfStateCampaign represents the MSG_MHF_STATE_CAMPAIGN +type MsgMhfStateCampaign struct { + AckHandle uint32 + Unk0 uint8 + Unk1 uint8 + Unk2 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfStateCampaign) Opcode() network.PacketID { + return network.MSG_MHF_STATE_CAMPAIGN +} + +// Parse parses the packet from binary +func (m *MsgMhfStateCampaign) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfStateCampaign) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint8(m.Unk0) + bf.WriteUint8(m.Unk1) + bf.WriteUint16(m.Unk2) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_mhf_state_festa_g.go b/Erupe/network/mhfpacket/msg_mhf_state_festa_g.go new file mode 100644 index 000000000..c6bce8cb9 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_state_festa_g.go @@ -0,0 +1,37 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfStateFestaG represents the MSG_MHF_STATE_FESTA_G +type MsgMhfStateFestaG struct { + AckHandle uint32 + Unk0 uint32 // Shared ID of something. + Unk1 uint32 + Unk2 uint16 // Hardcoded 0 in the binary. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfStateFestaG) Opcode() network.PacketID { + return network.MSG_MHF_STATE_FESTA_G +} + +// Parse parses the packet from binary +func (m *MsgMhfStateFestaG) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint16() + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfStateFestaG) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_state_festa_u.go b/Erupe/network/mhfpacket/msg_mhf_state_festa_u.go new file mode 100644 index 000000000..a6ed08bb3 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_state_festa_u.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfStateFestaU represents the MSG_MHF_STATE_FESTA_U +type MsgMhfStateFestaU struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfStateFestaU) Opcode() network.PacketID { + return network.MSG_MHF_STATE_FESTA_U +} + +// Parse parses the packet from binary +func (m *MsgMhfStateFestaU) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfStateFestaU) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_transfer_item.go b/Erupe/network/mhfpacket/msg_mhf_transfer_item.go new file mode 100644 index 000000000..1d4dc545a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_transfer_item.go @@ -0,0 +1,39 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfTransferItem represents the MSG_MHF_TRANSFER_ITEM +type MsgMhfTransferItem struct { + AckHandle uint32 + // looking at packets, these were static across sessions and did not actually + // correlate with any item IDs that would make sense to get after quests so + // I have no idea what this actually does + Unk0 uint32 + Unk1 uint16 // Hardcoded + Unk2 uint16 // Hardcoded +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfTransferItem) Opcode() network.PacketID { + return network.MSG_MHF_TRANSFER_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfTransferItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint16() + m.Unk2 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfTransferItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_transit_message.go b/Erupe/network/mhfpacket/msg_mhf_transit_message.go new file mode 100644 index 000000000..da8f0dcaf --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_transit_message.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfTransitMessage represents the MSG_MHF_TRANSIT_MESSAGE +type MsgMhfTransitMessage struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfTransitMessage) Opcode() network.PacketID { + return network.MSG_MHF_TRANSIT_MESSAGE +} + +// Parse parses the packet from binary +func (m *MsgMhfTransitMessage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfTransitMessage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_unreserve_srg.go b/Erupe/network/mhfpacket/msg_mhf_unreserve_srg.go new file mode 100644 index 000000000..f3c2f8164 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_unreserve_srg.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUnreserveSrg represents the MSG_MHF_UNRESERVE_SRG +type MsgMhfUnreserveSrg struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUnreserveSrg) Opcode() network.PacketID { + return network.MSG_MHF_UNRESERVE_SRG +} + +// Parse parses the packet from binary +func (m *MsgMhfUnreserveSrg) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUnreserveSrg) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_beat_level.go b/Erupe/network/mhfpacket/msg_mhf_update_beat_level.go new file mode 100644 index 000000000..71fefa2f0 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_beat_level.go @@ -0,0 +1,108 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgMhfUpdateBeatLevel represents the MSG_MHF_UPDATE_BEAT_LEVEL +type MsgMhfUpdateBeatLevel struct { + AckHandle uint32 + Unk1 uint32 + Unk2 uint32 + Unk3 uint16 + Unk4 uint16 + Unk5 uint32 + Unk6 uint32 + Unk7 uint32 + Unk8 uint16 + Unk9 uint16 + Unk10 uint32 + Unk11 uint32 + Unk12 uint32 + Unk13 uint32 + Unk14 uint32 + Unk15 uint32 + Unk16 uint32 + Unk17 uint32 + Unk18 uint32 + Unk19 uint32 + Unk20 uint32 + Unk21 uint16 + Unk22 uint16 + Unk23 uint16 + Unk24 uint32 + Unk25 uint32 + Unk26 uint16 + Unk27 uint32 + Unk28 uint32 + Unk29 uint32 + Unk30 uint32 + Unk31 uint32 + Unk32 uint32 + Unk33 uint32 + Unk34 uint32 + Unk35 uint32 + Unk36 uint32 + Unk37 uint32 + Unk38 uint16 + Unk39 uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateBeatLevel) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_BEAT_LEVEL +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateBeatLevel) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + m.Unk2 = bf.ReadUint32() + m.Unk3 = bf.ReadUint16() + m.Unk4 = bf.ReadUint16() + m.Unk5 = bf.ReadUint32() + m.Unk6 = bf.ReadUint32() + m.Unk7 = bf.ReadUint32() + m.Unk8 = bf.ReadUint16() + m.Unk9 = bf.ReadUint16() + m.Unk10 = bf.ReadUint32() + m.Unk11 = bf.ReadUint32() + m.Unk12 = bf.ReadUint32() + m.Unk13 = bf.ReadUint32() + m.Unk14 = bf.ReadUint32() + m.Unk15 = bf.ReadUint32() + m.Unk16 = bf.ReadUint32() + m.Unk17 = bf.ReadUint32() + m.Unk18 = bf.ReadUint32() + m.Unk19 = bf.ReadUint32() + m.Unk20 = bf.ReadUint32() + m.Unk21 = bf.ReadUint16() + m.Unk22 = bf.ReadUint16() + m.Unk23 = bf.ReadUint16() + m.Unk24 = bf.ReadUint32() + m.Unk25 = bf.ReadUint32() + m.Unk26 = bf.ReadUint16() + m.Unk27 = bf.ReadUint32() + m.Unk28 = bf.ReadUint32() + m.Unk29 = bf.ReadUint32() + m.Unk30 = bf.ReadUint32() + m.Unk31 = bf.ReadUint32() + m.Unk32 = bf.ReadUint32() + m.Unk33 = bf.ReadUint32() + m.Unk34 = bf.ReadUint32() + m.Unk35 = bf.ReadUint32() + m.Unk36 = bf.ReadUint32() + m.Unk37 = bf.ReadUint32() + m.Unk38 = bf.ReadUint16() + m.Unk39 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateBeatLevel) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_cafepoint.go b/Erupe/network/mhfpacket/msg_mhf_update_cafepoint.go new file mode 100644 index 000000000..7ce3303b9 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_cafepoint.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateCafepoint represents the MSG_MHF_UPDATE_CAFEPOINT +type MsgMhfUpdateCafepoint struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 0 in binary + Unk1 uint16 // Hardcoded 0 in binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateCafepoint) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_CAFEPOINT +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateCafepoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateCafepoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_equip_skin_hist.go b/Erupe/network/mhfpacket/msg_mhf_update_equip_skin_hist.go new file mode 100644 index 000000000..906d72619 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_equip_skin_hist.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateEquipSkinHist represents the MSG_MHF_UPDATE_EQUIP_SKIN_HIST +type MsgMhfUpdateEquipSkinHist struct { + AckHandle uint32 + MogType uint8 + ArmourID uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateEquipSkinHist) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_EQUIP_SKIN_HIST +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateEquipSkinHist) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.MogType = bf.ReadUint8() + m.ArmourID = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateEquipSkinHist) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_etc_point.go b/Erupe/network/mhfpacket/msg_mhf_update_etc_point.go new file mode 100644 index 000000000..1de1ed725 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_etc_point.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateEtcPoint represents the MSG_MHF_UPDATE_ETC_POINT +type MsgMhfUpdateEtcPoint struct { + AckHandle uint32 + Unk0 uint8 + Unk1 uint16 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateEtcPoint) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_ETC_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateEtcPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateEtcPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_force_guild_rank.go b/Erupe/network/mhfpacket/msg_mhf_update_force_guild_rank.go new file mode 100644 index 000000000..b701941a7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_force_guild_rank.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateForceGuildRank represents the MSG_MHF_UPDATE_FORCE_GUILD_RANK +type MsgMhfUpdateForceGuildRank struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateForceGuildRank) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_FORCE_GUILD_RANK +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateForceGuildRank) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateForceGuildRank) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_guacot.go b/Erupe/network/mhfpacket/msg_mhf_update_guacot.go new file mode 100644 index 000000000..664d45747 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_guacot.go @@ -0,0 +1,133 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// GuacotUpdateEntry represents an entry inside the MsgMhfUpdateGuacot packet. +type GuacotUpdateEntry struct { + Unk0 uint32 + Unk1 uint16 + Unk2 uint16 + Unk3 uint16 + Unk4 uint16 + Unk5 uint16 + Unk6 uint16 + Unk7 uint16 + Unk8 uint16 + Unk9 uint16 + Unk10 uint16 + Unk11 uint16 + Unk12 uint16 + Unk13 uint16 + Unk14 uint16 + Unk15 uint16 + Unk16 uint16 + Unk17 uint16 + Unk18 uint16 + Unk19 uint16 + Unk20 uint16 + Unk21 uint16 + Unk22 uint16 + Unk23 uint32 + Unk24 uint32 + DataSize uint8 + RawDataPayload []byte +} + +// MsgMhfUpdateGuacot represents the MSG_MHF_UPDATE_GUACOT +type MsgMhfUpdateGuacot struct { + AckHandle uint32 + EntryCount uint16 + Unk0 uint16 // Hardcoded 0 in binary + Entries []*GuacotUpdateEntry +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateGuacot) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_GUACOT +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateGuacot) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.EntryCount = bf.ReadUint16() + m.Unk0 = bf.ReadUint16() + for i := 0; i < int(m.EntryCount); i++ { + // Yikes. + e := &GuacotUpdateEntry{} + + e.Unk0 = bf.ReadUint32() + e.Unk1 = bf.ReadUint16() + e.Unk2 = bf.ReadUint16() + e.Unk3 = bf.ReadUint16() + e.Unk4 = bf.ReadUint16() + e.Unk5 = bf.ReadUint16() + e.Unk6 = bf.ReadUint16() + e.Unk7 = bf.ReadUint16() + e.Unk8 = bf.ReadUint16() + e.Unk9 = bf.ReadUint16() + e.Unk10 = bf.ReadUint16() + e.Unk11 = bf.ReadUint16() + e.Unk12 = bf.ReadUint16() + e.Unk13 = bf.ReadUint16() + e.Unk14 = bf.ReadUint16() + e.Unk15 = bf.ReadUint16() + e.Unk16 = bf.ReadUint16() + e.Unk17 = bf.ReadUint16() + e.Unk18 = bf.ReadUint16() + e.Unk19 = bf.ReadUint16() + e.Unk20 = bf.ReadUint16() + e.Unk21 = bf.ReadUint16() + e.Unk22 = bf.ReadUint16() + e.Unk23 = bf.ReadUint32() + e.Unk24 = bf.ReadUint32() + e.DataSize = bf.ReadUint8() + e.RawDataPayload = bf.ReadBytes(uint(e.DataSize)) + + m.Entries = append(m.Entries, e) + } + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateGuacot) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +func (m *MsgMhfUpdateGuacot) GuacotUpdateEntryToBytes(Entry *GuacotUpdateEntry) []byte { + resp:= byteframe.NewByteFrame() + resp.WriteUint32(Entry.Unk0) + resp.WriteUint16(Entry.Unk1) + resp.WriteUint16(Entry.Unk1) + resp.WriteUint16(Entry.Unk2) + resp.WriteUint16(Entry.Unk3) + resp.WriteUint16(Entry.Unk4) + resp.WriteUint16(Entry.Unk5) + resp.WriteUint16(Entry.Unk6) + resp.WriteUint16(Entry.Unk7) + resp.WriteUint16(Entry.Unk8) + resp.WriteUint16(Entry.Unk9) + resp.WriteUint16(Entry.Unk10) + resp.WriteUint16(Entry.Unk11) + resp.WriteUint16(Entry.Unk12) + resp.WriteUint16(Entry.Unk13) + resp.WriteUint16(Entry.Unk14) + resp.WriteUint16(Entry.Unk15) + resp.WriteUint16(Entry.Unk16) + resp.WriteUint16(Entry.Unk17) + resp.WriteUint16(Entry.Unk18) + resp.WriteUint16(Entry.Unk19) + resp.WriteUint16(Entry.Unk20) + resp.WriteUint16(Entry.Unk21) + resp.WriteUint16(Entry.Unk22) + resp.WriteUint32(Entry.Unk23) + resp.WriteUint32(Entry.Unk24) + resp.WriteUint8(Entry.DataSize) + resp.WriteBytes(Entry.RawDataPayload) + return resp.Data() +} \ No newline at end of file diff --git a/Erupe/network/mhfpacket/msg_mhf_update_guild.go b/Erupe/network/mhfpacket/msg_mhf_update_guild.go new file mode 100644 index 000000000..47d8a29e3 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_guild.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateGuild represents the MSG_MHF_UPDATE_GUILD +type MsgMhfUpdateGuild struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateGuild) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_GUILD +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateGuild) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateGuild) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_guild_icon.go b/Erupe/network/mhfpacket/msg_mhf_update_guild_icon.go new file mode 100644 index 000000000..cb0758de1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_guild_icon.go @@ -0,0 +1,66 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +type GuildIconMsgPart struct { + Index uint16 + ID uint16 + Unk0 uint8 + Size uint8 + Rotation uint8 + Unk1 uint8 + Unk2 uint16 + PosX uint16 + PosY uint16 +} + +// MsgMhfUpdateGuildIcon represents the MSG_MHF_UPDATE_GUILD_ICON +type MsgMhfUpdateGuildIcon struct { + AckHandle uint32 + GuildID uint32 + PartCount uint16 + Unk1 uint16 + IconParts []GuildIconMsgPart +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateGuildIcon) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_GUILD_ICON +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateGuildIcon) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.GuildID = bf.ReadUint32() + m.PartCount = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + + m.IconParts = make([]GuildIconMsgPart, m.PartCount) + + for i := 0; i < int(m.PartCount); i++ { + m.IconParts[i] = GuildIconMsgPart{ + Index: bf.ReadUint16(), + ID: bf.ReadUint16(), + Unk0: bf.ReadUint8(), + Size: bf.ReadUint8(), + Rotation: bf.ReadUint8(), + Unk1: bf.ReadUint8(), + Unk2: bf.ReadUint16(), + PosX: bf.ReadUint16(), + PosY: bf.ReadUint16(), + } + } + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateGuildIcon) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_guild_item.go b/Erupe/network/mhfpacket/msg_mhf_update_guild_item.go new file mode 100644 index 000000000..02f626629 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_guild_item.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateGuildItem represents the MSG_MHF_UPDATE_GUILD_ITEM +type MsgMhfUpdateGuildItem struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateGuildItem) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_GUILD_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateGuildItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateGuildItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_guildcard.go b/Erupe/network/mhfpacket/msg_mhf_update_guildcard.go new file mode 100644 index 000000000..282f51cb2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_guildcard.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateGuildcard represents the MSG_MHF_UPDATE_GUILDCARD +type MsgMhfUpdateGuildcard struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateGuildcard) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_GUILDCARD +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateGuildcard) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateGuildcard) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_house.go b/Erupe/network/mhfpacket/msg_mhf_update_house.go new file mode 100644 index 000000000..3209f4fbf --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_house.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateHouse represents the MSG_MHF_UPDATE_HOUSE +type MsgMhfUpdateHouse struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateHouse) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_HOUSE +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateHouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateHouse) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_interior.go b/Erupe/network/mhfpacket/msg_mhf_update_interior.go new file mode 100644 index 000000000..7cda7e9bf --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_interior.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateInterior represents the MSG_MHF_UPDATE_INTERIOR +type MsgMhfUpdateInterior struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateInterior) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_INTERIOR +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateInterior) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateInterior) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_myhouse_info.go b/Erupe/network/mhfpacket/msg_mhf_update_myhouse_info.go new file mode 100644 index 000000000..4c96c35b9 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_myhouse_info.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateMyhouseInfo represents the MSG_MHF_UPDATE_MYHOUSE_INFO +type MsgMhfUpdateMyhouseInfo struct { + AckHandle uint32 + Unk0 []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateMyhouseInfo) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_MYHOUSE_INFO +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateMyhouseInfo) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadBytes(0x16A) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateMyhouseInfo) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_union_item.go b/Erupe/network/mhfpacket/msg_mhf_update_union_item.go new file mode 100644 index 000000000..4e1ca8380 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_union_item.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateUnionItem represents the MSG_MHF_UPDATE_UNION_ITEM +type MsgMhfUpdateUnionItem struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateUnionItem) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_UNION_ITEM +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateUnionItem) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateUnionItem) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_use_trend_weapon_log.go b/Erupe/network/mhfpacket/msg_mhf_update_use_trend_weapon_log.go new file mode 100644 index 000000000..480a8c0ca --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_use_trend_weapon_log.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateUseTrendWeaponLog represents the MSG_MHF_UPDATE_USE_TREND_WEAPON_LOG +type MsgMhfUpdateUseTrendWeaponLog struct { + AckHandle uint32 + Unk0 uint8 + Unk1 uint16 // Weapon/item ID probably? +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateUseTrendWeaponLog) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_USE_TREND_WEAPON_LOG +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateUseTrendWeaponLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateUseTrendWeaponLog) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_update_warehouse.go b/Erupe/network/mhfpacket/msg_mhf_update_warehouse.go new file mode 100644 index 000000000..9039c0c42 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_update_warehouse.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUpdateWarehouse represents the MSG_MHF_UPDATE_WAREHOUSE +type MsgMhfUpdateWarehouse struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUpdateWarehouse) Opcode() network.PacketID { + return network.MSG_MHF_UPDATE_WAREHOUSE +} + +// Parse parses the packet from binary +func (m *MsgMhfUpdateWarehouse) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUpdateWarehouse) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_use_gacha_point.go b/Erupe/network/mhfpacket/msg_mhf_use_gacha_point.go new file mode 100644 index 000000000..3000b4e3e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_use_gacha_point.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUseGachaPoint represents the MSG_MHF_USE_GACHA_POINT +type MsgMhfUseGachaPoint struct{ + AckHandle uint32 + Unk0 uint16 // padding? + TrialCoins uint32 + PremiumCoins uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUseGachaPoint) Opcode() network.PacketID { + return network.MSG_MHF_USE_GACHA_POINT +} + +// Parse parses the packet from binary +func (m *MsgMhfUseGachaPoint) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.TrialCoins = bf.ReadUint32() + m.PremiumCoins = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUseGachaPoint) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_use_keep_login_boost.go b/Erupe/network/mhfpacket/msg_mhf_use_keep_login_boost.go new file mode 100644 index 000000000..d5cd3815c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_use_keep_login_boost.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUseKeepLoginBoost represents the MSG_MHF_USE_KEEP_LOGIN_BOOST +type MsgMhfUseKeepLoginBoost struct { + AckHandle uint32 + BoostWeekUsed uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUseKeepLoginBoost) Opcode() network.PacketID { + return network.MSG_MHF_USE_KEEP_LOGIN_BOOST +} + +// Parse parses the packet from binary +func (m *MsgMhfUseKeepLoginBoost) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.BoostWeekUsed = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUseKeepLoginBoost) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_use_reward_song.go b/Erupe/network/mhfpacket/msg_mhf_use_reward_song.go new file mode 100644 index 000000000..3a6c210b7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_use_reward_song.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUseRewardSong represents the MSG_MHF_USE_REWARD_SONG +type MsgMhfUseRewardSong struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUseRewardSong) Opcode() network.PacketID { + return network.MSG_MHF_USE_REWARD_SONG +} + +// Parse parses the packet from binary +func (m *MsgMhfUseRewardSong) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUseRewardSong) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_use_ud_shop_coin.go b/Erupe/network/mhfpacket/msg_mhf_use_ud_shop_coin.go new file mode 100644 index 000000000..9826affab --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_use_ud_shop_coin.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfUseUdShopCoin represents the MSG_MHF_USE_UD_SHOP_COIN +type MsgMhfUseUdShopCoin struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfUseUdShopCoin) Opcode() network.PacketID { + return network.MSG_MHF_USE_UD_SHOP_COIN +} + +// Parse parses the packet from binary +func (m *MsgMhfUseUdShopCoin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfUseUdShopCoin) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_mhf_vote_festa.go b/Erupe/network/mhfpacket/msg_mhf_vote_festa.go new file mode 100644 index 000000000..57b391521 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_mhf_vote_festa.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgMhfVoteFesta represents the MSG_MHF_VOTE_FESTA +type MsgMhfVoteFesta struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgMhfVoteFesta) Opcode() network.PacketID { + return network.MSG_MHF_VOTE_FESTA +} + +// Parse parses the packet from binary +func (m *MsgMhfVoteFesta) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgMhfVoteFesta) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_ack.go b/Erupe/network/mhfpacket/msg_sys_ack.go new file mode 100644 index 000000000..7f321997e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_ack.go @@ -0,0 +1,71 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysAck represents the MSG_SYS_ACK +type MsgSysAck struct { + AckHandle uint32 + IsBufferResponse bool + ErrorCode uint8 + AckData []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysAck) Opcode() network.PacketID { + return network.MSG_SYS_ACK +} + +// Parse parses the packet from binary +func (m *MsgSysAck) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.IsBufferResponse = bf.ReadBool() + m.ErrorCode = bf.ReadUint8() + + payloadSize := uint(bf.ReadUint16()) + // Extended data size field + if payloadSize == 0xFFFF { + payloadSize = uint(bf.ReadUint32()) + } + + if m.IsBufferResponse { + m.AckData = bf.ReadBytes(payloadSize) + } else { + // endian-swapped 4 bytes, could be any type. Unknown purpose. + // Probably a fixed type like (int32 or uint32), but unknown. + m.AckData = bf.ReadBytes(4) + } + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysAck) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteBool(m.IsBufferResponse) + bf.WriteUint8(m.ErrorCode) + + if m.IsBufferResponse { + if len(m.AckData) < 0xFFFF { + bf.WriteUint16(uint16(len(m.AckData))) + } else { + bf.WriteUint16(0xFFFF) + bf.WriteUint32(uint32(len(m.AckData))) + } + } else { + bf.WriteUint16(0x00) + } + + if m.IsBufferResponse { + bf.WriteBytes(m.AckData) + } else if len(m.AckData) >= 4 { + bf.WriteBytes(m.AckData[:4]) + } else { + bf.WriteBytes([]byte{0x00, 0x00, 0x00, 0x00}) + } + + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_acquire_semaphore.go b/Erupe/network/mhfpacket/msg_sys_acquire_semaphore.go new file mode 100644 index 000000000..b3b8170f2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_acquire_semaphore.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysAcquireSemaphore represents the MSG_SYS_ACQUIRE_SEMAPHORE +type MsgSysAcquireSemaphore struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysAcquireSemaphore) Opcode() network.PacketID { + return network.MSG_SYS_ACQUIRE_SEMAPHORE +} + +// Parse parses the packet from binary +func (m *MsgSysAcquireSemaphore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysAcquireSemaphore) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_add_object.go b/Erupe/network/mhfpacket/msg_sys_add_object.go new file mode 100644 index 000000000..94ff7a50c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_add_object.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysAddObject represents the MSG_SYS_ADD_OBJECT +type MsgSysAddObject struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysAddObject) Opcode() network.PacketID { + return network.MSG_SYS_ADD_OBJECT +} + +// Parse parses the packet from binary +func (m *MsgSysAddObject) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysAddObject) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_auth_data.go b/Erupe/network/mhfpacket/msg_sys_auth_data.go new file mode 100644 index 000000000..a71670cf2 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_auth_data.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysAuthData represents the MSG_SYS_AUTH_DATA +type MsgSysAuthData struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysAuthData) Opcode() network.PacketID { + return network.MSG_SYS_AUTH_DATA +} + +// Parse parses the packet from binary +func (m *MsgSysAuthData) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysAuthData) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_auth_query.go b/Erupe/network/mhfpacket/msg_sys_auth_query.go new file mode 100644 index 000000000..9cf50971a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_auth_query.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysAuthQuery represents the MSG_SYS_AUTH_QUERY +type MsgSysAuthQuery struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysAuthQuery) Opcode() network.PacketID { + return network.MSG_SYS_AUTH_QUERY +} + +// Parse parses the packet from binary +func (m *MsgSysAuthQuery) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysAuthQuery) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_auth_terminal.go b/Erupe/network/mhfpacket/msg_sys_auth_terminal.go new file mode 100644 index 000000000..20fb153dd --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_auth_terminal.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysAuthTerminal represents the MSG_SYS_AUTH_TERMINAL +type MsgSysAuthTerminal struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysAuthTerminal) Opcode() network.PacketID { + return network.MSG_SYS_AUTH_TERMINAL +} + +// Parse parses the packet from binary +func (m *MsgSysAuthTerminal) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysAuthTerminal) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_back_stage.go b/Erupe/network/mhfpacket/msg_sys_back_stage.go new file mode 100644 index 000000000..d94eec73a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_back_stage.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysBackStage represents the MSG_SYS_BACK_STAGE +type MsgSysBackStage struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysBackStage) Opcode() network.PacketID { + return network.MSG_SYS_BACK_STAGE +} + +// Parse parses the packet from binary +func (m *MsgSysBackStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysBackStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_cast_binary.go b/Erupe/network/mhfpacket/msg_sys_cast_binary.go new file mode 100644 index 000000000..787135cfa --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_cast_binary.go @@ -0,0 +1,39 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysCastBinary represents the MSG_SYS_CAST_BINARY +type MsgSysCastBinary struct { + Unk0 uint16 + Unk1 uint16 + BroadcastType uint8 + MessageType uint8 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCastBinary) Opcode() network.PacketID { + return network.MSG_SYS_CAST_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysCastBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + m.BroadcastType = bf.ReadUint8() + m.MessageType = bf.ReadUint8() + dataSize := bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(dataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCastBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_casted_binary.go b/Erupe/network/mhfpacket/msg_sys_casted_binary.go new file mode 100644 index 000000000..bd5bb53b6 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_casted_binary.go @@ -0,0 +1,40 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysCastedBinary represents the MSG_SYS_CASTED_BINARY +type MsgSysCastedBinary struct { + CharID uint32 + BroadcastType uint8 + MessageType uint8 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCastedBinary) Opcode() network.PacketID { + return network.MSG_SYS_CASTED_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysCastedBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.CharID = bf.ReadUint32() + m.BroadcastType = bf.ReadUint8() + m.MessageType = bf.ReadUint8() + dataSize := bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(dataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCastedBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.CharID) + bf.WriteUint8(m.BroadcastType) + bf.WriteUint8(m.MessageType) + bf.WriteUint16(uint16(len(m.RawDataPayload))) + bf.WriteBytes(m.RawDataPayload) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_check_semaphore.go b/Erupe/network/mhfpacket/msg_sys_check_semaphore.go new file mode 100644 index 000000000..0355d332d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_check_semaphore.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysCheckSemaphore represents the MSG_SYS_CHECK_SEMAPHORE +type MsgSysCheckSemaphore struct{ + AckHandle uint32 + StageID string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCheckSemaphore) Opcode() network.PacketID { + return network.MSG_SYS_CHECK_SEMAPHORE +} + +// Parse parses the packet from binary +func (m *MsgSysCheckSemaphore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + stageIDLength := bf.ReadUint8() + m.StageID = string(bfutil.UpToNull(bf.ReadBytes(uint(stageIDLength)))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCheckSemaphore) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} \ No newline at end of file diff --git a/Erupe/network/mhfpacket/msg_sys_cleanup_object.go b/Erupe/network/mhfpacket/msg_sys_cleanup_object.go new file mode 100644 index 000000000..e31b8776b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_cleanup_object.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysCleanupObject represents the MSG_SYS_CLEANUP_OBJECT +type MsgSysCleanupObject struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCleanupObject) Opcode() network.PacketID { + return network.MSG_SYS_CLEANUP_OBJECT +} + +// Parse parses the packet from binary +func (m *MsgSysCleanupObject) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // This packet has no data. + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCleanupObject) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // This packet has no data. + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_close_mutex.go b/Erupe/network/mhfpacket/msg_sys_close_mutex.go new file mode 100644 index 000000000..5376081fa --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_close_mutex.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysCloseMutex represents the MSG_SYS_CLOSE_MUTEX +type MsgSysCloseMutex struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCloseMutex) Opcode() network.PacketID { + return network.MSG_SYS_CLOSE_MUTEX +} + +// Parse parses the packet from binary +func (m *MsgSysCloseMutex) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCloseMutex) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_collect_binary.go b/Erupe/network/mhfpacket/msg_sys_collect_binary.go new file mode 100644 index 000000000..b89b4bd03 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_collect_binary.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysCollectBinary represents the MSG_SYS_COLLECT_BINARY +type MsgSysCollectBinary struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCollectBinary) Opcode() network.PacketID { + return network.MSG_SYS_COLLECT_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysCollectBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCollectBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_create_acquire_semaphore.go b/Erupe/network/mhfpacket/msg_sys_create_acquire_semaphore.go new file mode 100644 index 000000000..ea6f4592b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_create_acquire_semaphore.go @@ -0,0 +1,40 @@ +package mhfpacket + +import ( + "errors" + "fmt" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysCreateAcquireSemaphore represents the MSG_SYS_CREATE_ACQUIRE_SEMAPHORE +type MsgSysCreateAcquireSemaphore struct { + AckHandle uint32 + Unk0 uint16 + PlayerCount uint8 + SemaphoreID string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCreateAcquireSemaphore) Opcode() network.PacketID { + return network.MSG_SYS_CREATE_ACQUIRE_SEMAPHORE +} + +// Parse parses the packet from binary +func (m *MsgSysCreateAcquireSemaphore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.PlayerCount = bf.ReadUint8() + fmt.Printf("PLAYER COUNT :: %d", m.PlayerCount) + SemaphoreIDLength := bf.ReadUint8() + m.SemaphoreID = string(bfutil.UpToNull(bf.ReadBytes(uint(SemaphoreIDLength)))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCreateAcquireSemaphore) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_create_mutex.go b/Erupe/network/mhfpacket/msg_sys_create_mutex.go new file mode 100644 index 000000000..fc922191e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_create_mutex.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysCreateMutex represents the MSG_SYS_CREATE_MUTEX +type MsgSysCreateMutex struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCreateMutex) Opcode() network.PacketID { + return network.MSG_SYS_CREATE_MUTEX +} + +// Parse parses the packet from binary +func (m *MsgSysCreateMutex) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCreateMutex) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_create_object.go b/Erupe/network/mhfpacket/msg_sys_create_object.go new file mode 100644 index 000000000..527d7e32b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_create_object.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysCreateObject represents the MSG_SYS_CREATE_OBJECT +type MsgSysCreateObject struct { + AckHandle uint32 + X, Y, Z float32 + Unk0 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCreateObject) Opcode() network.PacketID { + return network.MSG_SYS_CREATE_OBJECT +} + +// Parse parses the packet from binary +func (m *MsgSysCreateObject) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.X = bf.ReadFloat32() + m.Y = bf.ReadFloat32() + m.Z = bf.ReadFloat32() + m.Unk0 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCreateObject) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_create_open_mutex.go b/Erupe/network/mhfpacket/msg_sys_create_open_mutex.go new file mode 100644 index 000000000..6ceff2ac6 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_create_open_mutex.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysCreateOpenMutex represents the MSG_SYS_CREATE_OPEN_MUTEX +type MsgSysCreateOpenMutex struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCreateOpenMutex) Opcode() network.PacketID { + return network.MSG_SYS_CREATE_OPEN_MUTEX +} + +// Parse parses the packet from binary +func (m *MsgSysCreateOpenMutex) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCreateOpenMutex) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_create_semaphore.go b/Erupe/network/mhfpacket/msg_sys_create_semaphore.go new file mode 100644 index 000000000..0fa9bad57 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_create_semaphore.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysCreateSemaphore represents the MSG_SYS_CREATE_SEMAPHORE +type MsgSysCreateSemaphore struct { + AckHandle uint32 + Unk0 uint16 + DataSize uint16 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCreateSemaphore) Opcode() network.PacketID { + return network.MSG_SYS_CREATE_SEMAPHORE +} + +// Parse parses the packet from binary +func (m *MsgSysCreateSemaphore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.DataSize = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCreateSemaphore) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_create_stage.go b/Erupe/network/mhfpacket/msg_sys_create_stage.go new file mode 100644 index 000000000..0a13243d4 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_create_stage.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysCreateStage represents the MSG_SYS_CREATE_STAGE +type MsgSysCreateStage struct { + AckHandle uint32 + Unk0 uint8 // Likely only has 1 and 2 as values. + PlayerCount uint8 + StageID string // NULL terminated string. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysCreateStage) Opcode() network.PacketID { + return network.MSG_SYS_CREATE_STAGE +} + +// Parse parses the packet from binary +func (m *MsgSysCreateStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.PlayerCount = bf.ReadUint8() + stageIDLength := bf.ReadUint8() + m.StageID = string(bfutil.UpToNull(bf.ReadBytes(uint(stageIDLength)))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysCreateStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + panic("Not implemented") +} diff --git a/Erupe/network/mhfpacket/msg_sys_del_object.go b/Erupe/network/mhfpacket/msg_sys_del_object.go new file mode 100644 index 000000000..53890df49 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_del_object.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysDelObject represents the MSG_SYS_DEL_OBJECT +type MsgSysDelObject struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysDelObject) Opcode() network.PacketID { + return network.MSG_SYS_DEL_OBJECT +} + +// Parse parses the packet from binary +func (m *MsgSysDelObject) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysDelObject) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_delete_mutex.go b/Erupe/network/mhfpacket/msg_sys_delete_mutex.go new file mode 100644 index 000000000..09e2e662f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_delete_mutex.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysDeleteMutex represents the MSG_SYS_DELETE_MUTEX +type MsgSysDeleteMutex struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysDeleteMutex) Opcode() network.PacketID { + return network.MSG_SYS_DELETE_MUTEX +} + +// Parse parses the packet from binary +func (m *MsgSysDeleteMutex) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysDeleteMutex) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_delete_object.go b/Erupe/network/mhfpacket/msg_sys_delete_object.go new file mode 100644 index 000000000..ff8bd7693 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_delete_object.go @@ -0,0 +1,29 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysDeleteObject represents the MSG_SYS_DELETE_OBJECT +type MsgSysDeleteObject struct { + ObjID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysDeleteObject) Opcode() network.PacketID { + return network.MSG_SYS_DELETE_OBJECT +} + +// Parse parses the packet from binary +func (m *MsgSysDeleteObject) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.ObjID = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysDeleteObject) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.ObjID) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_delete_semaphore.go b/Erupe/network/mhfpacket/msg_sys_delete_semaphore.go new file mode 100644 index 000000000..c12835eb9 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_delete_semaphore.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysDeleteSemaphore represents the MSG_SYS_DELETE_SEMAPHORE +type MsgSysDeleteSemaphore struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysDeleteSemaphore) Opcode() network.PacketID { + return network.MSG_SYS_DELETE_SEMAPHORE +} + +// Parse parses the packet from binary +func (m *MsgSysDeleteSemaphore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysDeleteSemaphore) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_delete_user.go b/Erupe/network/mhfpacket/msg_sys_delete_user.go new file mode 100644 index 000000000..1e7ee7ab3 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_delete_user.go @@ -0,0 +1,31 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysDeleteUser represents the MSG_SYS_DELETE_USER +type MsgSysDeleteUser struct { + CharID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysDeleteUser) Opcode() network.PacketID { + return network.MSG_SYS_DELETE_USER +} + +// Parse parses the packet from binary +func (m *MsgSysDeleteUser) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysDeleteUser) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.CharID) + + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_disp_object.go b/Erupe/network/mhfpacket/msg_sys_disp_object.go new file mode 100644 index 000000000..c74ca4619 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_disp_object.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysDispObject represents the MSG_SYS_DISP_OBJECT +type MsgSysDispObject struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysDispObject) Opcode() network.PacketID { + return network.MSG_SYS_DISP_OBJECT +} + +// Parse parses the packet from binary +func (m *MsgSysDispObject) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysDispObject) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_duplicate_object.go b/Erupe/network/mhfpacket/msg_sys_duplicate_object.go new file mode 100644 index 000000000..44b1a8d0f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_duplicate_object.go @@ -0,0 +1,42 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysDuplicateObject represents the MSG_SYS_DUPLICATE_OBJECT +type MsgSysDuplicateObject struct { + ObjID uint32 + X, Y, Z float32 + Unk0 uint32 + OwnerCharID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysDuplicateObject) Opcode() network.PacketID { + return network.MSG_SYS_DUPLICATE_OBJECT +} + +// Parse parses the packet from binary +func (m *MsgSysDuplicateObject) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.ObjID = bf.ReadUint32() + m.X = bf.ReadFloat32() + m.Y = bf.ReadFloat32() + m.Z = bf.ReadFloat32() + m.Unk0 = bf.ReadUint32() + m.OwnerCharID = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysDuplicateObject) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.ObjID) + bf.WriteFloat32(m.X) + bf.WriteFloat32(m.Y) + bf.WriteFloat32(m.Z) + bf.WriteUint32(m.Unk0) + bf.WriteUint32(m.OwnerCharID) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_echo.go b/Erupe/network/mhfpacket/msg_sys_echo.go new file mode 100644 index 000000000..5c534db94 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_echo.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysEcho represents the MSG_SYS_ECHO +type MsgSysEcho struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysEcho) Opcode() network.PacketID { + return network.MSG_SYS_ECHO +} + +// Parse parses the packet from binary +func (m *MsgSysEcho) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysEcho) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_end.go b/Erupe/network/mhfpacket/msg_sys_end.go new file mode 100644 index 000000000..9ef80ec9a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_end.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysEnd represents the MSG_SYS_END +type MsgSysEnd struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysEnd) Opcode() network.PacketID { + return network.MSG_SYS_END +} + +// Parse parses the packet from binary +func (m *MsgSysEnd) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // No data aside from opcode. + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysEnd) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // No data aside from opcode. + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_enter_stage.go b/Erupe/network/mhfpacket/msg_sys_enter_stage.go new file mode 100644 index 000000000..f2e29699e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_enter_stage.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysEnterStage represents the MSG_SYS_ENTER_STAGE +type MsgSysEnterStage struct { + AckHandle uint32 + UnkBool uint8 + StageID string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysEnterStage) Opcode() network.PacketID { + return network.MSG_SYS_ENTER_STAGE +} + +// Parse parses the packet from binary +func (m *MsgSysEnterStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.UnkBool = bf.ReadUint8() + stageIDLength := bf.ReadUint8() + m.StageID = string(bfutil.UpToNull(bf.ReadBytes(uint(stageIDLength)))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysEnterStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_enumerate_client.go b/Erupe/network/mhfpacket/msg_sys_enumerate_client.go new file mode 100644 index 000000000..bf7ff0473 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_enumerate_client.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysEnumerateClient represents the MSG_SYS_ENUMERATE_CLIENT +type MsgSysEnumerateClient struct { + AckHandle uint32 + Unk0 uint8 // Hardcoded 1 in the client + Unk1 uint8 + StageID string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysEnumerateClient) Opcode() network.PacketID { + return network.MSG_SYS_ENUMERATE_CLIENT +} + +// Parse parses the packet from binary +func (m *MsgSysEnumerateClient) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + stageIDLength := bf.ReadUint8() + m.StageID = string(bfutil.UpToNull(bf.ReadBytes(uint(stageIDLength)))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysEnumerateClient) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_enumerate_stage.go b/Erupe/network/mhfpacket/msg_sys_enumerate_stage.go new file mode 100644 index 000000000..4864d303d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_enumerate_stage.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysEnumerateStage represents the MSG_SYS_ENUMERATE_STAGE +type MsgSysEnumerateStage struct { + AckHandle uint32 + Unk0 uint8 // Hardcoded 1 in the binary + StageIDLength uint8 + StageID string // NULL terminated string. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysEnumerateStage) Opcode() network.PacketID { + return network.MSG_SYS_ENUMERATE_STAGE +} + +// Parse parses the packet from binary +func (m *MsgSysEnumerateStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.StageIDLength = bf.ReadUint8() + m.StageID = string(bf.ReadBytes(uint(m.StageIDLength))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysEnumerateStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_enumlobby.go b/Erupe/network/mhfpacket/msg_sys_enumlobby.go new file mode 100644 index 000000000..e6e3fccc5 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_enumlobby.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysEnumlobby represents the MSG_SYS_ENUMLOBBY +type MsgSysEnumlobby struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysEnumlobby) Opcode() network.PacketID { + return network.MSG_SYS_ENUMLOBBY +} + +// Parse parses the packet from binary +func (m *MsgSysEnumlobby) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysEnumlobby) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_enumuser.go b/Erupe/network/mhfpacket/msg_sys_enumuser.go new file mode 100644 index 000000000..3129ef1b1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_enumuser.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysEnumuser represents the MSG_SYS_ENUMUSER +type MsgSysEnumuser struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysEnumuser) Opcode() network.PacketID { + return network.MSG_SYS_ENUMUSER +} + +// Parse parses the packet from binary +func (m *MsgSysEnumuser) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysEnumuser) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_extend_threshold.go b/Erupe/network/mhfpacket/msg_sys_extend_threshold.go new file mode 100644 index 000000000..d6f5a98f9 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_extend_threshold.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysExtendThreshold represents the MSG_SYS_EXTEND_THRESHOLD +type MsgSysExtendThreshold struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysExtendThreshold) Opcode() network.PacketID { + return network.MSG_SYS_EXTEND_THRESHOLD +} + +// Parse parses the packet from binary +func (m *MsgSysExtendThreshold) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // No data aside from opcode. + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysExtendThreshold) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // No data aside from opcode. + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_get_file.go b/Erupe/network/mhfpacket/msg_sys_get_file.go new file mode 100644 index 000000000..cd28e79bd --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_get_file.go @@ -0,0 +1,68 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +type scenarioFileIdentifer struct { + CategoryID uint8 + MainID uint32 + ChapterID uint8 + /* + Flags represent the following bit flags: + 11111111 -> Least significant bit on the right. + |||||||| + |||||||0x1: Chunk0-type, recursive chunks, quest name/description + 0x14 byte unk info + ||||||0x2: Chunk1-type, recursive chunks, npc dialog? + 0x2C byte unk info + |||||0x4: UNK NONE FOUND. (Guessing from the following that this might be a chunk2-type) + ||||0x8: Chunk0-type, NO RECURSIVE CHUNKS ([0x1] prefixed?), Episode listing + |||0x10: Chunk1-type, NO RECURSIVE CHUNKS, JKR blob, npc dialog? + ||0x20: Chunk2-type, NO RECURSIVE CHUNKS, JKR blob, Menu options or quest titles? + |0x40: UNK NONE FOUND + 0x80: UNK NONE FOUND + */ + Flags uint8 +} + +// MsgSysGetFile represents the MSG_SYS_GET_FILE +type MsgSysGetFile struct { + AckHandle uint32 + IsScenario bool + Filename string + ScenarioIdentifer scenarioFileIdentifer +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysGetFile) Opcode() network.PacketID { + return network.MSG_SYS_GET_FILE +} + +// Parse parses the packet from binary +func (m *MsgSysGetFile) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.IsScenario = bf.ReadBool() + filenameLength := bf.ReadUint8() + if filenameLength > 0 { + m.Filename = string(bfutil.UpToNull(bf.ReadBytes(uint(filenameLength)))) + } + + if m.IsScenario { + m.ScenarioIdentifer = scenarioFileIdentifer{ + bf.ReadUint8(), + bf.ReadUint32(), + bf.ReadUint8(), + bf.ReadUint8(), + } + } + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysGetFile) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_get_object_binary.go b/Erupe/network/mhfpacket/msg_sys_get_object_binary.go new file mode 100644 index 000000000..c30c629b5 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_get_object_binary.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysGetObjectBinary represents the MSG_SYS_GET_OBJECT_BINARY +type MsgSysGetObjectBinary struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysGetObjectBinary) Opcode() network.PacketID { + return network.MSG_SYS_GET_OBJECT_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysGetObjectBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysGetObjectBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_get_object_owner.go b/Erupe/network/mhfpacket/msg_sys_get_object_owner.go new file mode 100644 index 000000000..d1980991f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_get_object_owner.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysGetObjectOwner represents the MSG_SYS_GET_OBJECT_OWNER +type MsgSysGetObjectOwner struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysGetObjectOwner) Opcode() network.PacketID { + return network.MSG_SYS_GET_OBJECT_OWNER +} + +// Parse parses the packet from binary +func (m *MsgSysGetObjectOwner) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysGetObjectOwner) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_get_stage_binary.go b/Erupe/network/mhfpacket/msg_sys_get_stage_binary.go new file mode 100644 index 000000000..4fed321f8 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_get_stage_binary.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysGetStageBinary represents the MSG_SYS_GET_STAGE_BINARY +type MsgSysGetStageBinary struct { + AckHandle uint32 + BinaryType0 uint8 + BinaryType1 uint8 + Unk0 uint32 // Hardcoded 0 + StageID string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysGetStageBinary) Opcode() network.PacketID { + return network.MSG_SYS_GET_STAGE_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysGetStageBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.BinaryType0 = bf.ReadUint8() + m.BinaryType1 = bf.ReadUint8() + m.Unk0 = bf.ReadUint32() + stageIDLength := bf.ReadUint8() + m.StageID = string(bfutil.UpToNull(bf.ReadBytes(uint(stageIDLength)))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysGetStageBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + panic("Not implemented") +} diff --git a/Erupe/network/mhfpacket/msg_sys_get_state.go b/Erupe/network/mhfpacket/msg_sys_get_state.go new file mode 100644 index 000000000..2485837de --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_get_state.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysGetState represents the MSG_SYS_GET_STATE +type MsgSysGetState struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysGetState) Opcode() network.PacketID { + return network.MSG_SYS_GET_STATE +} + +// Parse parses the packet from binary +func (m *MsgSysGetState) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysGetState) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_get_user_binary.go b/Erupe/network/mhfpacket/msg_sys_get_user_binary.go new file mode 100644 index 000000000..af4cce077 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_get_user_binary.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysGetUserBinary represents the MSG_SYS_GET_USER_BINARY +type MsgSysGetUserBinary struct { + AckHandle uint32 + CharID uint32 + BinaryType uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysGetUserBinary) Opcode() network.PacketID { + return network.MSG_SYS_GET_USER_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysGetUserBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.CharID = bf.ReadUint32() + m.BinaryType = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysGetUserBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_hide_client.go b/Erupe/network/mhfpacket/msg_sys_hide_client.go new file mode 100644 index 000000000..0a1ba3562 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_hide_client.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysHideClient represents the MSG_SYS_HIDE_CLIENT +type MsgSysHideClient struct { + Hide bool + Unk0 uint16 // Hardcoded 0 in binary + Unk1 uint8 // Hardcoded 0 in binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysHideClient) Opcode() network.PacketID { + return network.MSG_SYS_HIDE_CLIENT +} + +// Parse parses the packet from binary +func (m *MsgSysHideClient) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.Hide = bf.ReadBool() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysHideClient) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_hide_object.go b/Erupe/network/mhfpacket/msg_sys_hide_object.go new file mode 100644 index 000000000..7d6a2bd24 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_hide_object.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysHideObject represents the MSG_SYS_HIDE_OBJECT +type MsgSysHideObject struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysHideObject) Opcode() network.PacketID { + return network.MSG_SYS_HIDE_OBJECT +} + +// Parse parses the packet from binary +func (m *MsgSysHideObject) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysHideObject) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_infokyserver.go b/Erupe/network/mhfpacket/msg_sys_infokyserver.go new file mode 100644 index 000000000..10c17cca4 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_infokyserver.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysInfokyserver represents the MSG_SYS_INFOKYSERVER +type MsgSysInfokyserver struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysInfokyserver) Opcode() network.PacketID { + return network.MSG_SYS_INFOKYSERVER +} + +// Parse parses the packet from binary +func (m *MsgSysInfokyserver) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysInfokyserver) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_insert_user.go b/Erupe/network/mhfpacket/msg_sys_insert_user.go new file mode 100644 index 000000000..7c22b2aaf --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_insert_user.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysInsertUser represents the MSG_SYS_INSERT_USER +type MsgSysInsertUser struct { + CharID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysInsertUser) Opcode() network.PacketID { + return network.MSG_SYS_INSERT_USER +} + +// Parse parses the packet from binary +func (m *MsgSysInsertUser) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysInsertUser) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.CharID) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_issue_logkey.go b/Erupe/network/mhfpacket/msg_sys_issue_logkey.go new file mode 100644 index 000000000..f929ec5e6 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_issue_logkey.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysIssueLogkey represents the MSG_SYS_ISSUE_LOGKEY +type MsgSysIssueLogkey struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 00 01 in binary + Unk1 uint16 // Hardcoded 0 in binary. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysIssueLogkey) Opcode() network.PacketID { + return network.MSG_SYS_ISSUE_LOGKEY +} + +// Parse parses the packet from binary +func (m *MsgSysIssueLogkey) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysIssueLogkey) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_leave_stage.go b/Erupe/network/mhfpacket/msg_sys_leave_stage.go new file mode 100644 index 000000000..c22fbe3d5 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_leave_stage.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysLeaveStage represents the MSG_SYS_LEAVE_STAGE +type MsgSysLeaveStage struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysLeaveStage) Opcode() network.PacketID { + return network.MSG_SYS_LEAVE_STAGE +} + +// Parse parses the packet from binary +func (m *MsgSysLeaveStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysLeaveStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_load_register.go b/Erupe/network/mhfpacket/msg_sys_load_register.go new file mode 100644 index 000000000..66d754f1f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_load_register.go @@ -0,0 +1,46 @@ +package mhfpacket + +import ( + "fmt" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysLoadRegister represents the MSG_SYS_LOAD_REGISTER +type MsgSysLoadRegister struct { + AckHandle uint32 + RegisterID uint32 + Unk1 uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysLoadRegister) Opcode() network.PacketID { + return network.MSG_SYS_LOAD_REGISTER +} + +// Parse parses the packet from binary +func (m *MsgSysLoadRegister) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.RegisterID = bf.ReadUint32() + m.Unk1 = bf.ReadUint8() + fixedZero0 := bf.ReadUint16() + fixedZero1 := bf.ReadUint8() + + if fixedZero0 != 0 || fixedZero1 != 0 { + return fmt.Errorf("expected fixed-0 values, got %d %d", fixedZero0, fixedZero1) + } + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysLoadRegister) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint32(m.RegisterID) + bf.WriteUint8(m.Unk1) + bf.WriteUint16(0) + bf.WriteUint8(0) + + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_lock_global_sema.go b/Erupe/network/mhfpacket/msg_sys_lock_global_sema.go new file mode 100644 index 000000000..da9a6b886 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_lock_global_sema.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysLockGlobalSema represents the MSG_SYS_LOCK_GLOBAL_SEMA +type MsgSysLockGlobalSema struct { + AckHandle uint32 + UserIDLength uint16 + ServerChannelIDLength uint16 + UserIDString string + ServerChannelIDString string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysLockGlobalSema) Opcode() network.PacketID { + return network.MSG_SYS_LOCK_GLOBAL_SEMA +} + +// Parse parses the packet from binary +func (m *MsgSysLockGlobalSema) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.UserIDLength = bf.ReadUint16() + m.ServerChannelIDLength = bf.ReadUint16() + m.UserIDString = string(bf.ReadBytes(uint(m.UserIDLength))) + m.ServerChannelIDString = string(bf.ReadBytes(uint(m.ServerChannelIDLength))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysLockGlobalSema) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_lock_stage.go b/Erupe/network/mhfpacket/msg_sys_lock_stage.go new file mode 100644 index 000000000..b83e5305d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_lock_stage.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysLockStage represents the MSG_SYS_LOCK_STAGE +type MsgSysLockStage struct { + AckHandle uint32 + Unk0 uint8 // Hardcoded 1 in the binary + Unk1 uint8 // Hardcoded 1 in the binary + StageIDLength uint8 + StageID string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysLockStage) Opcode() network.PacketID { + return network.MSG_SYS_LOCK_STAGE +} + +// Parse parses the packet from binary +func (m *MsgSysLockStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + m.Unk1 = bf.ReadUint8() + m.StageIDLength = bf.ReadUint8() + m.StageID = string(bf.ReadBytes(uint(m.StageIDLength))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysLockStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_login.go b/Erupe/network/mhfpacket/msg_sys_login.go new file mode 100644 index 000000000..925198283 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_login.go @@ -0,0 +1,47 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysLogin represents the MSG_SYS_LOGIN +type MsgSysLogin struct { + AckHandle uint32 + CharID0 uint32 + LoginTokenNumber uint32 + HardcodedZero0 uint16 + RequestVersion uint16 + CharID1 uint32 + HardcodedZero1 uint16 + LoginTokenStringLength uint16 // Hardcoded to 0x11 + LoginTokenString string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysLogin) Opcode() network.PacketID { + return network.MSG_SYS_LOGIN +} + +// Parse parses the packet from binary +func (m *MsgSysLogin) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.CharID0 = bf.ReadUint32() + m.LoginTokenNumber = bf.ReadUint32() + m.HardcodedZero0 = bf.ReadUint16() + m.RequestVersion = bf.ReadUint16() + m.CharID1 = bf.ReadUint32() + m.HardcodedZero1 = bf.ReadUint16() + m.LoginTokenStringLength = bf.ReadUint16() + m.LoginTokenString = string(bf.ReadBytes(17)) // TODO(Andoryuuta): What encoding is this string? + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysLogin) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_logout.go b/Erupe/network/mhfpacket/msg_sys_logout.go new file mode 100644 index 000000000..d6d9d3bf1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_logout.go @@ -0,0 +1,29 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysLogout represents the MSG_SYS_LOGOUT +type MsgSysLogout struct { + Unk0 uint8 // Hardcoded 1 in binary +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysLogout) Opcode() network.PacketID { + return network.MSG_SYS_LOGOUT +} + +// Parse parses the packet from binary +func (m *MsgSysLogout) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.Unk0 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysLogout) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.Unk0 = bf.ReadUint8() + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_move_stage.go b/Erupe/network/mhfpacket/msg_sys_move_stage.go new file mode 100644 index 000000000..239f92607 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_move_stage.go @@ -0,0 +1,35 @@ +package mhfpacket + +import ( + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysMoveStage represents the MSG_SYS_MOVE_STAGE +type MsgSysMoveStage struct { + AckHandle uint32 + UnkBool uint8 + StageIDLength uint8 + StageID string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysMoveStage) Opcode() network.PacketID { + return network.MSG_SYS_MOVE_STAGE +} + +// Parse parses the packet from binary +func (m *MsgSysMoveStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.UnkBool = bf.ReadUint8() + stageIDLength := bf.ReadUint8() + m.StageID = string(bfutil.UpToNull(bf.ReadBytes(uint(stageIDLength)))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysMoveStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + panic("Not implemented") +} diff --git a/Erupe/network/mhfpacket/msg_sys_nop.go b/Erupe/network/mhfpacket/msg_sys_nop.go new file mode 100644 index 000000000..635fee245 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_nop.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysNop represents the MSG_SYS_NOP +type MsgSysNop struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysNop) Opcode() network.PacketID { + return network.MSG_SYS_NOP +} + +// Parse parses the packet from binary +func (m *MsgSysNop) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // No data aside from opcode. + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysNop) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // No data aside from opcode. + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_notify_register.go b/Erupe/network/mhfpacket/msg_sys_notify_register.go new file mode 100644 index 000000000..b246face9 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_notify_register.go @@ -0,0 +1,29 @@ +package mhfpacket + +import ( + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysNotifyRegister represents the MSG_SYS_NOTIFY_REGISTER +type MsgSysNotifyRegister struct { + RegisterID uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysNotifyRegister) Opcode() network.PacketID { + return network.MSG_SYS_NOTIFY_REGISTER +} + +// Parse parses the packet from binary +func (m *MsgSysNotifyRegister) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.RegisterID = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysNotifyRegister) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.RegisterID) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_notify_user_binary.go b/Erupe/network/mhfpacket/msg_sys_notify_user_binary.go new file mode 100644 index 000000000..a3815bda7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_notify_user_binary.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysNotifyUserBinary represents the MSG_SYS_NOTIFY_USER_BINARY +type MsgSysNotifyUserBinary struct { + CharID uint32 + BinaryType uint8 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysNotifyUserBinary) Opcode() network.PacketID { + return network.MSG_SYS_NOTIFY_USER_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysNotifyUserBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.CharID = bf.ReadUint32() + m.BinaryType = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysNotifyUserBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.CharID) + bf.WriteUint8(m.BinaryType) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_open_mutex.go b/Erupe/network/mhfpacket/msg_sys_open_mutex.go new file mode 100644 index 000000000..3d65c6919 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_open_mutex.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysOpenMutex represents the MSG_SYS_OPEN_MUTEX +type MsgSysOpenMutex struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysOpenMutex) Opcode() network.PacketID { + return network.MSG_SYS_OPEN_MUTEX +} + +// Parse parses the packet from binary +func (m *MsgSysOpenMutex) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysOpenMutex) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_operate_register.go b/Erupe/network/mhfpacket/msg_sys_operate_register.go new file mode 100644 index 000000000..83db33f82 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_operate_register.go @@ -0,0 +1,48 @@ +package mhfpacket + +import ( + "fmt" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysOperateRegister represents the MSG_SYS_OPERATE_REGISTER +type MsgSysOperateRegister struct { + AckHandle uint32 + RegisterID uint32 + fixedZero uint16 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysOperateRegister) Opcode() network.PacketID { + return network.MSG_SYS_OPERATE_REGISTER +} + +// Parse parses the packet from binary +func (m *MsgSysOperateRegister) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.RegisterID = bf.ReadUint32() + m.fixedZero = bf.ReadUint16() + + if m.fixedZero != 0 { + return fmt.Errorf("expected fixed-0 values, got %d", m.fixedZero) + } + + dataSize := bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(dataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysOperateRegister) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + bf.WriteUint32(m.RegisterID) + bf.WriteUint16(0) + bf.WriteUint16(uint16(len(m.RawDataPayload))) + bf.WriteBytes(m.RawDataPayload) + + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_ping.go b/Erupe/network/mhfpacket/msg_sys_ping.go new file mode 100644 index 000000000..544e4833f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_ping.go @@ -0,0 +1,29 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysPing represents the MSG_SYS_PING +type MsgSysPing struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysPing) Opcode() network.PacketID { + return network.MSG_SYS_PING +} + +// Parse parses the packet from binary +func (m *MsgSysPing) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysPing) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_position_object.go b/Erupe/network/mhfpacket/msg_sys_position_object.go new file mode 100644 index 000000000..0e8bc2bbb --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_position_object.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysPositionObject represents the MSG_SYS_POSITION_OBJECT +type MsgSysPositionObject struct { + ObjID uint32 + X, Y, Z float32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysPositionObject) Opcode() network.PacketID { + return network.MSG_SYS_POSITION_OBJECT +} + +// Parse parses the packet from binary +func (m *MsgSysPositionObject) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.ObjID = bf.ReadUint32() + m.X = bf.ReadFloat32() + m.Y = bf.ReadFloat32() + m.Z = bf.ReadFloat32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysPositionObject) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.ObjID) + bf.WriteFloat32(m.X) + bf.WriteFloat32(m.Y) + bf.WriteFloat32(m.Z) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_record_log.go b/Erupe/network/mhfpacket/msg_sys_record_log.go new file mode 100644 index 000000000..0766716f3 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_record_log.go @@ -0,0 +1,41 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysRecordLog represents the MSG_SYS_RECORD_LOG +type MsgSysRecordLog struct { + AckHandle uint32 + Unk0 uint32 + Unk1 uint16 // Hardcoded 0 + HardcodedDataSize uint16 // Hardcoded 0x4AC + Unk3 uint32 // Some shared ID with MSG_MHF_GET_SEIBATTLE. World ID?? + DataBuf []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysRecordLog) Opcode() network.PacketID { + return network.MSG_SYS_RECORD_LOG +} + +// Parse parses the packet from binary +func (m *MsgSysRecordLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint16() + m.HardcodedDataSize = bf.ReadUint16() + m.Unk3 = bf.ReadUint32() + m.DataBuf = bf.ReadBytes(uint(m.HardcodedDataSize)) + return nil + +} + +// Build builds a binary packet from the current data. +func (m *MsgSysRecordLog) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_release_semaphore.go b/Erupe/network/mhfpacket/msg_sys_release_semaphore.go new file mode 100644 index 000000000..37b2c231b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_release_semaphore.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReleaseSemaphore represents the MSG_SYS_RELEASE_SEMAPHORE +type MsgSysReleaseSemaphore struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReleaseSemaphore) Opcode() network.PacketID { + return network.MSG_SYS_RELEASE_SEMAPHORE +} + +// Parse parses the packet from binary +func (m *MsgSysReleaseSemaphore) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReleaseSemaphore) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve01.go b/Erupe/network/mhfpacket/msg_sys_reserve01.go new file mode 100644 index 000000000..adce5392a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve01.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve01 represents the MSG_SYS_reserve01 +type MsgSysReserve01 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve01) Opcode() network.PacketID { + return network.MSG_SYS_reserve01 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve01) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve01) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve02.go b/Erupe/network/mhfpacket/msg_sys_reserve02.go new file mode 100644 index 000000000..09514ee41 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve02.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve02 represents the MSG_SYS_reserve02 +type MsgSysReserve02 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve02) Opcode() network.PacketID { + return network.MSG_SYS_reserve02 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve02) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve02) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve03.go b/Erupe/network/mhfpacket/msg_sys_reserve03.go new file mode 100644 index 000000000..a3f3b5961 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve03.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve03 represents the MSG_SYS_reserve03 +type MsgSysReserve03 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve03) Opcode() network.PacketID { + return network.MSG_SYS_reserve03 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve03) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve03) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve04.go b/Erupe/network/mhfpacket/msg_sys_reserve04.go new file mode 100644 index 000000000..829fdfcc1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve04.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve04 represents the MSG_SYS_reserve04 +type MsgSysReserve04 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve04) Opcode() network.PacketID { + return network.MSG_SYS_reserve04 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve04) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve04) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve05.go b/Erupe/network/mhfpacket/msg_sys_reserve05.go new file mode 100644 index 000000000..4af28f0fd --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve05.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve05 represents the MSG_SYS_reserve05 +type MsgSysReserve05 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve05) Opcode() network.PacketID { + return network.MSG_SYS_reserve05 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve05) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve05) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve06.go b/Erupe/network/mhfpacket/msg_sys_reserve06.go new file mode 100644 index 000000000..7cd992dfd --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve06.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve06 represents the MSG_SYS_reserve06 +type MsgSysReserve06 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve06) Opcode() network.PacketID { + return network.MSG_SYS_reserve06 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve06) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve06) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve07.go b/Erupe/network/mhfpacket/msg_sys_reserve07.go new file mode 100644 index 000000000..5c9c2b8cb --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve07.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve07 represents the MSG_SYS_reserve07 +type MsgSysReserve07 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve07) Opcode() network.PacketID { + return network.MSG_SYS_reserve07 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve07) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve07) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve0c.go b/Erupe/network/mhfpacket/msg_sys_reserve0c.go new file mode 100644 index 000000000..323a4b499 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve0c.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve0C represents the MSG_SYS_reserve0C +type MsgSysReserve0C struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve0C) Opcode() network.PacketID { + return network.MSG_SYS_reserve0C +} + +// Parse parses the packet from binary +func (m *MsgSysReserve0C) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve0C) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve0d.go b/Erupe/network/mhfpacket/msg_sys_reserve0d.go new file mode 100644 index 000000000..3e2ce1127 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve0d.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve0D represents the MSG_SYS_reserve0D +type MsgSysReserve0D struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve0D) Opcode() network.PacketID { + return network.MSG_SYS_reserve0D +} + +// Parse parses the packet from binary +func (m *MsgSysReserve0D) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve0D) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve0e.go b/Erupe/network/mhfpacket/msg_sys_reserve0e.go new file mode 100644 index 000000000..d6bb313b5 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve0e.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve0E represents the MSG_SYS_reserve0E +type MsgSysReserve0E struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve0E) Opcode() network.PacketID { + return network.MSG_SYS_reserve0E +} + +// Parse parses the packet from binary +func (m *MsgSysReserve0E) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve0E) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve180.go b/Erupe/network/mhfpacket/msg_sys_reserve180.go new file mode 100644 index 000000000..180009b53 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve180.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve180 represents the MSG_SYS_reserve180 +type MsgSysReserve180 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve180) Opcode() network.PacketID { + return network.MSG_SYS_reserve180 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve180) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve180) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve188.go b/Erupe/network/mhfpacket/msg_sys_reserve188.go new file mode 100644 index 000000000..e8fb6de20 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve188.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve188 represents the MSG_SYS_reserve188 +type MsgSysReserve188 struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve188) Opcode() network.PacketID { + return network.MSG_SYS_reserve188 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve188) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve188) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve18b.go b/Erupe/network/mhfpacket/msg_sys_reserve18b.go new file mode 100644 index 000000000..7b3f8024d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve18b.go @@ -0,0 +1,30 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve18B represents the MSG_SYS_reserve18B +type MsgSysReserve18B struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve18B) Opcode() network.PacketID { + return network.MSG_SYS_reserve18B +} + +// Parse parses the packet from binary +func (m *MsgSysReserve18B) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve18B) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve18e.go b/Erupe/network/mhfpacket/msg_sys_reserve18e.go new file mode 100644 index 000000000..92629cd9a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve18e.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve18E represents the MSG_SYS_reserve18E +type MsgSysReserve18E struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve18E) Opcode() network.PacketID { + return network.MSG_SYS_reserve18E +} + +// Parse parses the packet from binary +func (m *MsgSysReserve18E) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve18E) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve18f.go b/Erupe/network/mhfpacket/msg_sys_reserve18f.go new file mode 100644 index 000000000..af3dfd394 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve18f.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve18F represents the MSG_SYS_reserve18F +type MsgSysReserve18F struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve18F) Opcode() network.PacketID { + return network.MSG_SYS_reserve18F +} + +// Parse parses the packet from binary +func (m *MsgSysReserve18F) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve18F) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve192.go b/Erupe/network/mhfpacket/msg_sys_reserve192.go new file mode 100644 index 000000000..3244fd84b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve192.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve192 represents the MSG_SYS_reserve192 +type MsgSysReserve192 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve192) Opcode() network.PacketID { + return network.MSG_SYS_reserve192 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve192) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve192) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve193.go b/Erupe/network/mhfpacket/msg_sys_reserve193.go new file mode 100644 index 000000000..966c5f3c1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve193.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve193 represents the MSG_SYS_reserve193 +type MsgSysReserve193 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve193) Opcode() network.PacketID { + return network.MSG_SYS_reserve193 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve193) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve193) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve194.go b/Erupe/network/mhfpacket/msg_sys_reserve194.go new file mode 100644 index 000000000..b61f26405 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve194.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve194 represents the MSG_SYS_reserve194 +type MsgSysReserve194 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve194) Opcode() network.PacketID { + return network.MSG_SYS_reserve194 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve194) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve194) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve19b.go b/Erupe/network/mhfpacket/msg_sys_reserve19b.go new file mode 100644 index 000000000..26855fcda --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve19b.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve19B represents the MSG_SYS_reserve19B +type MsgSysReserve19B struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve19B) Opcode() network.PacketID { + return network.MSG_SYS_reserve19B +} + +// Parse parses the packet from binary +func (m *MsgSysReserve19B) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve19B) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve19e.go b/Erupe/network/mhfpacket/msg_sys_reserve19e.go new file mode 100644 index 000000000..6fb185f15 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve19e.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve19E represents the MSG_SYS_reserve19E +type MsgSysReserve19E struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve19E) Opcode() network.PacketID { + return network.MSG_SYS_reserve19E +} + +// Parse parses the packet from binary +func (m *MsgSysReserve19E) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve19E) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve19f.go b/Erupe/network/mhfpacket/msg_sys_reserve19f.go new file mode 100644 index 000000000..43f2dfa9c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve19f.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve19F represents the MSG_SYS_reserve19F +type MsgSysReserve19F struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve19F) Opcode() network.PacketID { + return network.MSG_SYS_reserve19F +} + +// Parse parses the packet from binary +func (m *MsgSysReserve19F) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve19F) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve202.go b/Erupe/network/mhfpacket/msg_sys_reserve202.go new file mode 100644 index 000000000..f26a17815 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve202.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve202 represents the MSG_SYS_reserve202 +type MsgSysReserve202 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve202) Opcode() network.PacketID { + return network.MSG_SYS_reserve202 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve202) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve202) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve203.go b/Erupe/network/mhfpacket/msg_sys_reserve203.go new file mode 100644 index 000000000..a6dc54408 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve203.go @@ -0,0 +1,36 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// TODO(Andoryuuta): Make up a name for this packet, not reserved anymore. Called "Is_update_guild_msg_board" + +// MsgSysReserve203 represents the MSG_SYS_reserve203 +type MsgSysReserve203 struct { + AckHandle uint32 + Unk0 uint16 // Hardcoded 0x0000 in the binary + Unk1 uint16 // Hardcoded 0x0500 in the binary. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve203) Opcode() network.PacketID { + return network.MSG_SYS_reserve203 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve203) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint16() + m.Unk1 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve203) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve204.go b/Erupe/network/mhfpacket/msg_sys_reserve204.go new file mode 100644 index 000000000..df41a400f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve204.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve204 represents the MSG_SYS_reserve204 +type MsgSysReserve204 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve204) Opcode() network.PacketID { + return network.MSG_SYS_reserve204 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve204) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve204) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve205.go b/Erupe/network/mhfpacket/msg_sys_reserve205.go new file mode 100644 index 000000000..28665324d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve205.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve205 represents the MSG_SYS_reserve205 +type MsgSysReserve205 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve205) Opcode() network.PacketID { + return network.MSG_SYS_reserve205 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve205) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve205) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve206.go b/Erupe/network/mhfpacket/msg_sys_reserve206.go new file mode 100644 index 000000000..86c1895e9 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve206.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve206 represents the MSG_SYS_reserve206 +type MsgSysReserve206 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve206) Opcode() network.PacketID { + return network.MSG_SYS_reserve206 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve206) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve206) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve207.go b/Erupe/network/mhfpacket/msg_sys_reserve207.go new file mode 100644 index 000000000..3eea346fe --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve207.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve207 represents the MSG_SYS_reserve207 +type MsgSysReserve207 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve207) Opcode() network.PacketID { + return network.MSG_SYS_reserve207 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve207) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve207) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve208.go b/Erupe/network/mhfpacket/msg_sys_reserve208.go new file mode 100644 index 000000000..091b1e7c7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve208.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve208 represents the MSG_SYS_reserve208 +type MsgSysReserve208 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve208) Opcode() network.PacketID { + return network.MSG_SYS_reserve208 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve208) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve208) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve209.go b/Erupe/network/mhfpacket/msg_sys_reserve209.go new file mode 100644 index 000000000..95d941692 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve209.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve209 represents the MSG_SYS_reserve209 +type MsgSysReserve209 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve209) Opcode() network.PacketID { + return network.MSG_SYS_reserve209 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve209) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve209) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve20a.go b/Erupe/network/mhfpacket/msg_sys_reserve20a.go new file mode 100644 index 000000000..0a5d53f1c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve20a.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve20A represents the MSG_SYS_reserve20A +type MsgSysReserve20A struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve20A) Opcode() network.PacketID { + return network.MSG_SYS_reserve20A +} + +// Parse parses the packet from binary +func (m *MsgSysReserve20A) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve20A) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve20b.go b/Erupe/network/mhfpacket/msg_sys_reserve20b.go new file mode 100644 index 000000000..fa1c2ce73 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve20b.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve20B represents the MSG_SYS_reserve20B +type MsgSysReserve20B struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve20B) Opcode() network.PacketID { + return network.MSG_SYS_reserve20B +} + +// Parse parses the packet from binary +func (m *MsgSysReserve20B) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve20B) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve20c.go b/Erupe/network/mhfpacket/msg_sys_reserve20c.go new file mode 100644 index 000000000..16eb690b0 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve20c.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve20C represents the MSG_SYS_reserve20C +type MsgSysReserve20C struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve20C) Opcode() network.PacketID { + return network.MSG_SYS_reserve20C +} + +// Parse parses the packet from binary +func (m *MsgSysReserve20C) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve20C) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve20d.go b/Erupe/network/mhfpacket/msg_sys_reserve20d.go new file mode 100644 index 000000000..4fe2ac8a6 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve20d.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve20D represents the MSG_SYS_reserve20D +type MsgSysReserve20D struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve20D) Opcode() network.PacketID { + return network.MSG_SYS_reserve20D +} + +// Parse parses the packet from binary +func (m *MsgSysReserve20D) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve20D) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve20e.go b/Erupe/network/mhfpacket/msg_sys_reserve20e.go new file mode 100644 index 000000000..76c088fe1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve20e.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve20E represents the MSG_SYS_reserve20E +type MsgSysReserve20E struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve20E) Opcode() network.PacketID { + return network.MSG_SYS_reserve20E +} + +// Parse parses the packet from binary +func (m *MsgSysReserve20E) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve20E) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve20f.go b/Erupe/network/mhfpacket/msg_sys_reserve20f.go new file mode 100644 index 000000000..abcfbf64e --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve20f.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve20F represents the MSG_SYS_reserve20F +type MsgSysReserve20F struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve20F) Opcode() network.PacketID { + return network.MSG_SYS_reserve20F +} + +// Parse parses the packet from binary +func (m *MsgSysReserve20F) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve20F) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve4a.go b/Erupe/network/mhfpacket/msg_sys_reserve4a.go new file mode 100644 index 000000000..5854be39b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve4a.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve4A represents the MSG_SYS_reserve4A +type MsgSysReserve4A struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve4A) Opcode() network.PacketID { + return network.MSG_SYS_reserve4A +} + +// Parse parses the packet from binary +func (m *MsgSysReserve4A) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve4A) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve4b.go b/Erupe/network/mhfpacket/msg_sys_reserve4b.go new file mode 100644 index 000000000..440dae89b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve4b.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve4B represents the MSG_SYS_reserve4B +type MsgSysReserve4B struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve4B) Opcode() network.PacketID { + return network.MSG_SYS_reserve4B +} + +// Parse parses the packet from binary +func (m *MsgSysReserve4B) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve4B) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve4c.go b/Erupe/network/mhfpacket/msg_sys_reserve4c.go new file mode 100644 index 000000000..0e106bcaa --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve4c.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve4C represents the MSG_SYS_reserve4C +type MsgSysReserve4C struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve4C) Opcode() network.PacketID { + return network.MSG_SYS_reserve4C +} + +// Parse parses the packet from binary +func (m *MsgSysReserve4C) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve4C) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve4d.go b/Erupe/network/mhfpacket/msg_sys_reserve4d.go new file mode 100644 index 000000000..89bf0d49b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve4d.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve4D represents the MSG_SYS_reserve4D +type MsgSysReserve4D struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve4D) Opcode() network.PacketID { + return network.MSG_SYS_reserve4D +} + +// Parse parses the packet from binary +func (m *MsgSysReserve4D) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve4D) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve4e.go b/Erupe/network/mhfpacket/msg_sys_reserve4e.go new file mode 100644 index 000000000..f8b19cc59 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve4e.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve4E represents the MSG_SYS_reserve4E +type MsgSysReserve4E struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve4E) Opcode() network.PacketID { + return network.MSG_SYS_reserve4E +} + +// Parse parses the packet from binary +func (m *MsgSysReserve4E) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve4E) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve4f.go b/Erupe/network/mhfpacket/msg_sys_reserve4f.go new file mode 100644 index 000000000..b6b820f62 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve4f.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve4F represents the MSG_SYS_reserve4F +type MsgSysReserve4F struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve4F) Opcode() network.PacketID { + return network.MSG_SYS_reserve4F +} + +// Parse parses the packet from binary +func (m *MsgSysReserve4F) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve4F) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve55.go b/Erupe/network/mhfpacket/msg_sys_reserve55.go new file mode 100644 index 000000000..cc849faf1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve55.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve55 represents the MSG_SYS_reserve55 +type MsgSysReserve55 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve55) Opcode() network.PacketID { + return network.MSG_SYS_reserve55 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve55) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve55) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve56.go b/Erupe/network/mhfpacket/msg_sys_reserve56.go new file mode 100644 index 000000000..a5baaff24 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve56.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve56 represents the MSG_SYS_reserve56 +type MsgSysReserve56 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve56) Opcode() network.PacketID { + return network.MSG_SYS_reserve56 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve56) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve56) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve57.go b/Erupe/network/mhfpacket/msg_sys_reserve57.go new file mode 100644 index 000000000..acd145f91 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve57.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve57 represents the MSG_SYS_reserve57 +type MsgSysReserve57 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve57) Opcode() network.PacketID { + return network.MSG_SYS_reserve57 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve57) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve57) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve5c.go b/Erupe/network/mhfpacket/msg_sys_reserve5c.go new file mode 100644 index 000000000..554371b94 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve5c.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve5C represents the MSG_SYS_reserve5C +type MsgSysReserve5C struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve5C) Opcode() network.PacketID { + return network.MSG_SYS_reserve5C +} + +// Parse parses the packet from binary +func (m *MsgSysReserve5C) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve5C) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve5e.go b/Erupe/network/mhfpacket/msg_sys_reserve5e.go new file mode 100644 index 000000000..180a93289 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve5e.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve5E represents the MSG_SYS_reserve5E +type MsgSysReserve5E struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve5E) Opcode() network.PacketID { + return network.MSG_SYS_reserve5E +} + +// Parse parses the packet from binary +func (m *MsgSysReserve5E) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve5E) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve5f.go b/Erupe/network/mhfpacket/msg_sys_reserve5f.go new file mode 100644 index 000000000..e79ae7353 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve5f.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve5F represents the MSG_SYS_reserve5F +type MsgSysReserve5F struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve5F) Opcode() network.PacketID { + return network.MSG_SYS_reserve5F +} + +// Parse parses the packet from binary +func (m *MsgSysReserve5F) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve5F) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve71.go b/Erupe/network/mhfpacket/msg_sys_reserve71.go new file mode 100644 index 000000000..3db26d3bc --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve71.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve71 represents the MSG_SYS_reserve71 +type MsgSysReserve71 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve71) Opcode() network.PacketID { + return network.MSG_SYS_reserve71 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve71) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve71) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve72.go b/Erupe/network/mhfpacket/msg_sys_reserve72.go new file mode 100644 index 000000000..12c5194c4 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve72.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve72 represents the MSG_SYS_reserve72 +type MsgSysReserve72 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve72) Opcode() network.PacketID { + return network.MSG_SYS_reserve72 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve72) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve72) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve73.go b/Erupe/network/mhfpacket/msg_sys_reserve73.go new file mode 100644 index 000000000..f42638978 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve73.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve73 represents the MSG_SYS_reserve73 +type MsgSysReserve73 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve73) Opcode() network.PacketID { + return network.MSG_SYS_reserve73 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve73) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve73) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve74.go b/Erupe/network/mhfpacket/msg_sys_reserve74.go new file mode 100644 index 000000000..6aafb9b8a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve74.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve74 represents the MSG_SYS_reserve74 +type MsgSysReserve74 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve74) Opcode() network.PacketID { + return network.MSG_SYS_reserve74 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve74) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve74) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve75.go b/Erupe/network/mhfpacket/msg_sys_reserve75.go new file mode 100644 index 000000000..513bda5cb --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve75.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve75 represents the MSG_SYS_reserve75 +type MsgSysReserve75 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve75) Opcode() network.PacketID { + return network.MSG_SYS_reserve75 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve75) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve75) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve76.go b/Erupe/network/mhfpacket/msg_sys_reserve76.go new file mode 100644 index 000000000..04fe73162 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve76.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve76 represents the MSG_SYS_reserve76 +type MsgSysReserve76 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve76) Opcode() network.PacketID { + return network.MSG_SYS_reserve76 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve76) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve76) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve77.go b/Erupe/network/mhfpacket/msg_sys_reserve77.go new file mode 100644 index 000000000..edee29f42 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve77.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve77 represents the MSG_SYS_reserve77 +type MsgSysReserve77 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve77) Opcode() network.PacketID { + return network.MSG_SYS_reserve77 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve77) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve77) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve78.go b/Erupe/network/mhfpacket/msg_sys_reserve78.go new file mode 100644 index 000000000..ebac9581a --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve78.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve78 represents the MSG_SYS_reserve78 +type MsgSysReserve78 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve78) Opcode() network.PacketID { + return network.MSG_SYS_reserve78 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve78) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve78) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve79.go b/Erupe/network/mhfpacket/msg_sys_reserve79.go new file mode 100644 index 000000000..e57b5836b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve79.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve79 represents the MSG_SYS_reserve79 +type MsgSysReserve79 struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve79) Opcode() network.PacketID { + return network.MSG_SYS_reserve79 +} + +// Parse parses the packet from binary +func (m *MsgSysReserve79) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve79) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve7a.go b/Erupe/network/mhfpacket/msg_sys_reserve7a.go new file mode 100644 index 000000000..f18c58c63 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve7a.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve7A represents the MSG_SYS_reserve7A +type MsgSysReserve7A struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve7A) Opcode() network.PacketID { + return network.MSG_SYS_reserve7A +} + +// Parse parses the packet from binary +func (m *MsgSysReserve7A) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve7A) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve7b.go b/Erupe/network/mhfpacket/msg_sys_reserve7b.go new file mode 100644 index 000000000..dde617f40 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve7b.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve7B represents the MSG_SYS_reserve7B +type MsgSysReserve7B struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve7B) Opcode() network.PacketID { + return network.MSG_SYS_reserve7B +} + +// Parse parses the packet from binary +func (m *MsgSysReserve7B) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve7B) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve7c.go b/Erupe/network/mhfpacket/msg_sys_reserve7c.go new file mode 100644 index 000000000..c2bdf6d64 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve7c.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve7C represents the MSG_SYS_reserve7C +type MsgSysReserve7C struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve7C) Opcode() network.PacketID { + return network.MSG_SYS_reserve7C +} + +// Parse parses the packet from binary +func (m *MsgSysReserve7C) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve7C) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve7e.go b/Erupe/network/mhfpacket/msg_sys_reserve7e.go new file mode 100644 index 000000000..9a827371b --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve7e.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysReserve7E represents the MSG_SYS_reserve7E +type MsgSysReserve7E struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserve7E) Opcode() network.PacketID { + return network.MSG_SYS_reserve7E +} + +// Parse parses the packet from binary +func (m *MsgSysReserve7E) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserve7E) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_reserve_stage.go b/Erupe/network/mhfpacket/msg_sys_reserve_stage.go new file mode 100644 index 000000000..cada63aae --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_reserve_stage.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysReserveStage represents the MSG_SYS_RESERVE_STAGE +type MsgSysReserveStage struct { + AckHandle uint32 + Unk0 uint8 // Made with: `16 * x | 1;`, unknown `x` values. + StageID string // NULL terminated string. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysReserveStage) Opcode() network.PacketID { + return network.MSG_SYS_RESERVE_STAGE +} + +// Parse parses the packet from binary +func (m *MsgSysReserveStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + stageIDLength := bf.ReadUint8() + m.StageID = string(bfutil.UpToNull(bf.ReadBytes(uint(stageIDLength)))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysReserveStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + panic("Not implemented") +} diff --git a/Erupe/network/mhfpacket/msg_sys_rights_reload.go b/Erupe/network/mhfpacket/msg_sys_rights_reload.go new file mode 100644 index 000000000..6ed24b8f1 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_rights_reload.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysRightsReload represents the MSG_SYS_RIGHTS_RELOAD +type MsgSysRightsReload struct{ + AckHandle uint32 + Unk0 byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysRightsReload) Opcode() network.PacketID { + return network.MSG_SYS_RIGHTS_RELOAD +} + +// Parse parses the packet from binary +func (m *MsgSysRightsReload) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.Unk0 = bf.ReadUint8() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysRightsReload) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_rotate_object.go b/Erupe/network/mhfpacket/msg_sys_rotate_object.go new file mode 100644 index 000000000..e6819eff7 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_rotate_object.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysRotateObject represents the MSG_SYS_ROTATE_OBJECT +type MsgSysRotateObject struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysRotateObject) Opcode() network.PacketID { + return network.MSG_SYS_ROTATE_OBJECT +} + +// Parse parses the packet from binary +func (m *MsgSysRotateObject) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysRotateObject) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_serialize.go b/Erupe/network/mhfpacket/msg_sys_serialize.go new file mode 100644 index 000000000..5c85ff832 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_serialize.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysSerialize represents the MSG_SYS_SERIALIZE +type MsgSysSerialize struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysSerialize) Opcode() network.PacketID { + return network.MSG_SYS_SERIALIZE +} + +// Parse parses the packet from binary +func (m *MsgSysSerialize) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysSerialize) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_set_object_binary.go b/Erupe/network/mhfpacket/msg_sys_set_object_binary.go new file mode 100644 index 000000000..e9309cee0 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_set_object_binary.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysSetObjectBinary represents the MSG_SYS_SET_OBJECT_BINARY +type MsgSysSetObjectBinary struct { + ObjID uint32 + DataSize uint16 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysSetObjectBinary) Opcode() network.PacketID { + return network.MSG_SYS_SET_OBJECT_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysSetObjectBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.ObjID = bf.ReadUint32() + m.DataSize = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysSetObjectBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_set_stage_binary.go b/Erupe/network/mhfpacket/msg_sys_set_stage_binary.go new file mode 100644 index 000000000..6f5142b51 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_set_stage_binary.go @@ -0,0 +1,37 @@ +package mhfpacket + +import ( + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysSetStageBinary represents the MSG_SYS_SET_STAGE_BINARY +type MsgSysSetStageBinary struct { + BinaryType0 uint8 + BinaryType1 uint8 // Index + StageID string + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysSetStageBinary) Opcode() network.PacketID { + return network.MSG_SYS_SET_STAGE_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysSetStageBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.BinaryType0 = bf.ReadUint8() + m.BinaryType1 = bf.ReadUint8() + stageIDLength := bf.ReadUint8() // <= 0x20 + dataSize := bf.ReadUint16() // <= 0x400 + m.StageID = string(bfutil.UpToNull(bf.ReadBytes(uint(stageIDLength)))) + m.RawDataPayload = bf.ReadBytes(uint(dataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysSetStageBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + panic("Not implemented") +} diff --git a/Erupe/network/mhfpacket/msg_sys_set_stage_pass.go b/Erupe/network/mhfpacket/msg_sys_set_stage_pass.go new file mode 100644 index 000000000..d7e953a5d --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_set_stage_pass.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysSetStagePass represents the MSG_SYS_SET_STAGE_PASS +type MsgSysSetStagePass struct { + Unk0 uint8 // Hardcoded 0 in the binary + PasswordLength uint8 + Password string // NULL-terminated string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysSetStagePass) Opcode() network.PacketID { + return network.MSG_SYS_SET_STAGE_PASS +} + +// Parse parses the packet from binary +func (m *MsgSysSetStagePass) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.Unk0 = bf.ReadUint8() + m.PasswordLength = bf.ReadUint8() + m.Password = string(bf.ReadBytes(uint(m.PasswordLength))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysSetStagePass) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_set_status.go b/Erupe/network/mhfpacket/msg_sys_set_status.go new file mode 100644 index 000000000..f99d18a59 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_set_status.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysSetStatus represents the MSG_SYS_SET_STATUS +type MsgSysSetStatus struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysSetStatus) Opcode() network.PacketID { + return network.MSG_SYS_SET_STATUS +} + +// Parse parses the packet from binary +func (m *MsgSysSetStatus) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysSetStatus) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_set_user_binary.go b/Erupe/network/mhfpacket/msg_sys_set_user_binary.go new file mode 100644 index 000000000..0db849a25 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_set_user_binary.go @@ -0,0 +1,34 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysSetUserBinary represents the MSG_SYS_SET_USER_BINARY +type MsgSysSetUserBinary struct { + BinaryType uint8 + DataSize uint16 + RawDataPayload []byte +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysSetUserBinary) Opcode() network.PacketID { + return network.MSG_SYS_SET_USER_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysSetUserBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.BinaryType = bf.ReadUint8() + m.DataSize = bf.ReadUint16() + m.RawDataPayload = bf.ReadBytes(uint(m.DataSize)) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysSetUserBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_stage_destruct.go b/Erupe/network/mhfpacket/msg_sys_stage_destruct.go new file mode 100644 index 000000000..b1df3fe78 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_stage_destruct.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysStageDestruct represents the MSG_SYS_STAGE_DESTRUCT +type MsgSysStageDestruct struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysStageDestruct) Opcode() network.PacketID { + return network.MSG_SYS_STAGE_DESTRUCT +} + +// Parse parses the packet from binary +func (m *MsgSysStageDestruct) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // No data other than opcode + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysStageDestruct) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + // No data other than opcode + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_terminal_log.go b/Erupe/network/mhfpacket/msg_sys_terminal_log.go new file mode 100644 index 000000000..8846cdf50 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_terminal_log.go @@ -0,0 +1,58 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// TerminalLogEntry represents an entry in the MSG_SYS_TERMINAL_LOG packet. +type TerminalLogEntry struct { + // Unknown fields + U0, U1, U2, U3, U4, U5, U6, U7, U8 uint32 +} + +// MsgSysTerminalLog represents the MSG_SYS_TERMINAL_LOG +type MsgSysTerminalLog struct { + AckHandle uint32 + LogID uint32 // 0 on the first packet, and the server sends back a value to use for subsequent requests. + EntryCount uint16 + Unk0 uint16 // Hardcoded 0 in the binary + Entries []*TerminalLogEntry +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysTerminalLog) Opcode() network.PacketID { + return network.MSG_SYS_TERMINAL_LOG +} + +// Parse parses the packet from binary +func (m *MsgSysTerminalLog) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.LogID = bf.ReadUint32() + m.EntryCount = bf.ReadUint16() + m.Unk0 = bf.ReadUint16() + + for i := 0; i < int(m.EntryCount); i++ { + e := &TerminalLogEntry{} + e.U0 = bf.ReadUint32() + e.U1 = bf.ReadUint32() + e.U2 = bf.ReadUint32() + e.U3 = bf.ReadUint32() + e.U4 = bf.ReadUint32() + e.U5 = bf.ReadUint32() + e.U6 = bf.ReadUint32() + e.U7 = bf.ReadUint32() + e.U8 = bf.ReadUint32() + m.Entries = append(m.Entries, e) + } + + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysTerminalLog) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_time.go b/Erupe/network/mhfpacket/msg_sys_time.go new file mode 100644 index 000000000..297cb9b70 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_time.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysTime represents the MSG_SYS_TIME +type MsgSysTime struct { + GetRemoteTime bool // Ask the other end to send it's time as well. + Timestamp uint32 // Unix timestamp, e.g. 1577105879 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysTime) Opcode() network.PacketID { + return network.MSG_SYS_TIME +} + +// Parse parses the packet from binary +func (m *MsgSysTime) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.GetRemoteTime = bf.ReadBool() + m.Timestamp = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysTime) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteBool(m.GetRemoteTime) + bf.WriteUint32(m.Timestamp) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_trans_binary.go b/Erupe/network/mhfpacket/msg_sys_trans_binary.go new file mode 100644 index 000000000..b6c15140f --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_trans_binary.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysTransBinary represents the MSG_SYS_TRANS_BINARY +type MsgSysTransBinary struct{} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysTransBinary) Opcode() network.PacketID { + return network.MSG_SYS_TRANS_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysTransBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysTransBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} diff --git a/Erupe/network/mhfpacket/msg_sys_unlock_global_sema.go b/Erupe/network/mhfpacket/msg_sys_unlock_global_sema.go new file mode 100644 index 000000000..d7b3f802c --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_unlock_global_sema.go @@ -0,0 +1,29 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysUnlockGlobalSema represents the MSG_SYS_UNLOCK_GLOBAL_SEMA +type MsgSysUnlockGlobalSema struct { + AckHandle uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysUnlockGlobalSema) Opcode() network.PacketID { + return network.MSG_SYS_UNLOCK_GLOBAL_SEMA +} + +// Parse parses the packet from binary +func (m *MsgSysUnlockGlobalSema) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysUnlockGlobalSema) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.AckHandle) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_unlock_stage.go b/Erupe/network/mhfpacket/msg_sys_unlock_stage.go new file mode 100644 index 000000000..0b773c463 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_unlock_stage.go @@ -0,0 +1,29 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysUnlockStage represents the MSG_SYS_UNLOCK_STAGE +type MsgSysUnlockStage struct { + Unk0 uint16 // Hardcoded 0 in the binary. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysUnlockStage) Opcode() network.PacketID { + return network.MSG_SYS_UNLOCK_STAGE +} + +// Parse parses the packet from binary +func (m *MsgSysUnlockStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.Unk0 = bf.ReadUint16() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysUnlockStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint16(m.Unk0) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_unreserve_stage.go b/Erupe/network/mhfpacket/msg_sys_unreserve_stage.go new file mode 100644 index 000000000..e4be28dcf --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_unreserve_stage.go @@ -0,0 +1,27 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysUnreserveStage represents the MSG_SYS_UNRESERVE_STAGE +type MsgSysUnreserveStage struct { + // Contains no fields. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysUnreserveStage) Opcode() network.PacketID { + return network.MSG_SYS_UNRESERVE_STAGE +} + +// Parse parses the packet from binary +func (m *MsgSysUnreserveStage) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysUnreserveStage) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_update_object_binary.go b/Erupe/network/mhfpacket/msg_sys_update_object_binary.go new file mode 100644 index 000000000..02e358911 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_update_object_binary.go @@ -0,0 +1,32 @@ +package mhfpacket + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Andoryuuta/byteframe" +) + +// MsgSysUpdateObjectBinary represents the MSG_SYS_UPDATE_OBJECT_BINARY +type MsgSysUpdateObjectBinary struct { + Unk0 uint32 // Object handle ID + Unk1 uint32 +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysUpdateObjectBinary) Opcode() network.PacketID { + return network.MSG_SYS_UPDATE_OBJECT_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysUpdateObjectBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.Unk0 = bf.ReadUint32() + m.Unk1 = bf.ReadUint32() + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysUpdateObjectBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.Unk0) + bf.WriteUint32(m.Unk1) + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_update_right.go b/Erupe/network/mhfpacket/msg_sys_update_right.go new file mode 100644 index 000000000..e20da0963 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_update_right.go @@ -0,0 +1,71 @@ +package mhfpacket + +import ( + "errors" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +/* +00 58 // Opcode + +00 00 00 00 +00 00 00 4e + +00 04 // Count +00 00 // Skipped(padding?) + +00 01 00 00 00 00 00 00 +00 02 00 00 5d fa 14 c0 +00 03 00 00 5d fa 14 c0 +00 06 00 00 5d e7 05 10 + +00 00 // Count of some buf up to 0x800 bytes following it. + +00 10 // Trailer +*/ + +// ClientRight represents a right that the client has. +type ClientRight struct { + ID uint16 + Unk0 uint16 + Timestamp uint32 +} + +// MsgSysUpdateRight represents the MSG_SYS_UPDATE_RIGHT +type MsgSysUpdateRight struct { + ClientRespAckHandle uint32 // If non-0, requests the client to send back a MSG_SYS_ACK packet with this value. + Unk1 uint32 + Rights []ClientRight + UnkSize uint16 // Count of some buf up to 0x800 bytes following it. +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysUpdateRight) Opcode() network.PacketID { + return network.MSG_SYS_UPDATE_RIGHT +} + +// Parse parses the packet from binary +func (m *MsgSysUpdateRight) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + return errors.New("NOT IMPLEMENTED") +} + +// Build builds a binary packet from the current data. +func (m *MsgSysUpdateRight) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + bf.WriteUint32(m.ClientRespAckHandle) + bf.WriteUint32(m.Unk1) + bf.WriteUint16(uint16(len(m.Rights))) + bf.WriteUint16(0) + for _, v := range m.Rights { + bf.WriteUint16(v.ID) + bf.WriteUint16(v.Unk0) + bf.WriteUint32(v.Timestamp) + } + + bf.WriteUint16(m.UnkSize) // String of upto 0x800 bytes, update client login token / password in the game's launcherstate struct. + //bf.WriteBytes(m.UpdatedClientLoginToken) + + return nil +} diff --git a/Erupe/network/mhfpacket/msg_sys_wait_stage_binary.go b/Erupe/network/mhfpacket/msg_sys_wait_stage_binary.go new file mode 100644 index 000000000..f09e3c379 --- /dev/null +++ b/Erupe/network/mhfpacket/msg_sys_wait_stage_binary.go @@ -0,0 +1,38 @@ +package mhfpacket + +import ( + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" +) + +// MsgSysWaitStageBinary represents the MSG_SYS_WAIT_STAGE_BINARY +type MsgSysWaitStageBinary struct { + AckHandle uint32 + BinaryType0 uint8 + BinaryType1 uint8 + Unk0 uint32 // Hardcoded 0 + StageID string +} + +// Opcode returns the ID associated with this packet type. +func (m *MsgSysWaitStageBinary) Opcode() network.PacketID { + return network.MSG_SYS_WAIT_STAGE_BINARY +} + +// Parse parses the packet from binary +func (m *MsgSysWaitStageBinary) Parse(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + m.AckHandle = bf.ReadUint32() + m.BinaryType0 = bf.ReadUint8() + m.BinaryType1 = bf.ReadUint8() + m.Unk0 = bf.ReadUint32() + stageIDLength := bf.ReadUint8() + m.StageID = string(bfutil.UpToNull(bf.ReadBytes(uint(stageIDLength)))) + return nil +} + +// Build builds a binary packet from the current data. +func (m *MsgSysWaitStageBinary) Build(bf *byteframe.ByteFrame, ctx *clientctx.ClientContext) error { + panic("Not implemented") +} diff --git a/Erupe/network/mhfpacket/opcode_to_packet.go b/Erupe/network/mhfpacket/opcode_to_packet.go new file mode 100644 index 000000000..1cc9352ba --- /dev/null +++ b/Erupe/network/mhfpacket/opcode_to_packet.go @@ -0,0 +1,874 @@ +package mhfpacket + +import "github.com/Solenataris/Erupe/network" + +// FromOpcode gets a packet struct that fulfills the MHFPacket interface by it's opcode. +func FromOpcode(opcode network.PacketID) MHFPacket { + switch opcode { + case network.MSG_HEAD: + return &MsgHead{} + case network.MSG_SYS_reserve01: + return &MsgSysReserve01{} + case network.MSG_SYS_reserve02: + return &MsgSysReserve02{} + case network.MSG_SYS_reserve03: + return &MsgSysReserve03{} + case network.MSG_SYS_reserve04: + return &MsgSysReserve04{} + case network.MSG_SYS_reserve05: + return &MsgSysReserve05{} + case network.MSG_SYS_reserve06: + return &MsgSysReserve06{} + case network.MSG_SYS_reserve07: + return &MsgSysReserve07{} + case network.MSG_SYS_ADD_OBJECT: + return &MsgSysAddObject{} + case network.MSG_SYS_DEL_OBJECT: + return &MsgSysDelObject{} + case network.MSG_SYS_DISP_OBJECT: + return &MsgSysDispObject{} + case network.MSG_SYS_HIDE_OBJECT: + return &MsgSysHideObject{} + case network.MSG_SYS_reserve0C: + return &MsgSysReserve0C{} + case network.MSG_SYS_reserve0D: + return &MsgSysReserve0D{} + case network.MSG_SYS_reserve0E: + return &MsgSysReserve0E{} + case network.MSG_SYS_EXTEND_THRESHOLD: + return &MsgSysExtendThreshold{} + case network.MSG_SYS_END: + return &MsgSysEnd{} + case network.MSG_SYS_NOP: + return &MsgSysNop{} + case network.MSG_SYS_ACK: + return &MsgSysAck{} + case network.MSG_SYS_TERMINAL_LOG: + return &MsgSysTerminalLog{} + case network.MSG_SYS_LOGIN: + return &MsgSysLogin{} + case network.MSG_SYS_LOGOUT: + return &MsgSysLogout{} + case network.MSG_SYS_SET_STATUS: + return &MsgSysSetStatus{} + case network.MSG_SYS_PING: + return &MsgSysPing{} + case network.MSG_SYS_CAST_BINARY: + return &MsgSysCastBinary{} + case network.MSG_SYS_HIDE_CLIENT: + return &MsgSysHideClient{} + case network.MSG_SYS_TIME: + return &MsgSysTime{} + case network.MSG_SYS_CASTED_BINARY: + return &MsgSysCastedBinary{} + case network.MSG_SYS_GET_FILE: + return &MsgSysGetFile{} + case network.MSG_SYS_ISSUE_LOGKEY: + return &MsgSysIssueLogkey{} + case network.MSG_SYS_RECORD_LOG: + return &MsgSysRecordLog{} + case network.MSG_SYS_ECHO: + return &MsgSysEcho{} + case network.MSG_SYS_CREATE_STAGE: + return &MsgSysCreateStage{} + case network.MSG_SYS_STAGE_DESTRUCT: + return &MsgSysStageDestruct{} + case network.MSG_SYS_ENTER_STAGE: + return &MsgSysEnterStage{} + case network.MSG_SYS_BACK_STAGE: + return &MsgSysBackStage{} + case network.MSG_SYS_MOVE_STAGE: + return &MsgSysMoveStage{} + case network.MSG_SYS_LEAVE_STAGE: + return &MsgSysLeaveStage{} + case network.MSG_SYS_LOCK_STAGE: + return &MsgSysLockStage{} + case network.MSG_SYS_UNLOCK_STAGE: + return &MsgSysUnlockStage{} + case network.MSG_SYS_RESERVE_STAGE: + return &MsgSysReserveStage{} + case network.MSG_SYS_UNRESERVE_STAGE: + return &MsgSysUnreserveStage{} + case network.MSG_SYS_SET_STAGE_PASS: + return &MsgSysSetStagePass{} + case network.MSG_SYS_WAIT_STAGE_BINARY: + return &MsgSysWaitStageBinary{} + case network.MSG_SYS_SET_STAGE_BINARY: + return &MsgSysSetStageBinary{} + case network.MSG_SYS_GET_STAGE_BINARY: + return &MsgSysGetStageBinary{} + case network.MSG_SYS_ENUMERATE_CLIENT: + return &MsgSysEnumerateClient{} + case network.MSG_SYS_ENUMERATE_STAGE: + return &MsgSysEnumerateStage{} + case network.MSG_SYS_CREATE_MUTEX: + return &MsgSysCreateMutex{} + case network.MSG_SYS_CREATE_OPEN_MUTEX: + return &MsgSysCreateOpenMutex{} + case network.MSG_SYS_DELETE_MUTEX: + return &MsgSysDeleteMutex{} + case network.MSG_SYS_OPEN_MUTEX: + return &MsgSysOpenMutex{} + case network.MSG_SYS_CLOSE_MUTEX: + return &MsgSysCloseMutex{} + case network.MSG_SYS_CREATE_SEMAPHORE: + return &MsgSysCreateSemaphore{} + case network.MSG_SYS_CREATE_ACQUIRE_SEMAPHORE: + return &MsgSysCreateAcquireSemaphore{} + case network.MSG_SYS_DELETE_SEMAPHORE: + return &MsgSysDeleteSemaphore{} + case network.MSG_SYS_ACQUIRE_SEMAPHORE: + return &MsgSysAcquireSemaphore{} + case network.MSG_SYS_RELEASE_SEMAPHORE: + return &MsgSysReleaseSemaphore{} + case network.MSG_SYS_LOCK_GLOBAL_SEMA: + return &MsgSysLockGlobalSema{} + case network.MSG_SYS_UNLOCK_GLOBAL_SEMA: + return &MsgSysUnlockGlobalSema{} + case network.MSG_SYS_CHECK_SEMAPHORE: + return &MsgSysCheckSemaphore{} + case network.MSG_SYS_OPERATE_REGISTER: + return &MsgSysOperateRegister{} + case network.MSG_SYS_LOAD_REGISTER: + return &MsgSysLoadRegister{} + case network.MSG_SYS_NOTIFY_REGISTER: + return &MsgSysNotifyRegister{} + case network.MSG_SYS_CREATE_OBJECT: + return &MsgSysCreateObject{} + case network.MSG_SYS_DELETE_OBJECT: + return &MsgSysDeleteObject{} + case network.MSG_SYS_POSITION_OBJECT: + return &MsgSysPositionObject{} + case network.MSG_SYS_ROTATE_OBJECT: + return &MsgSysRotateObject{} + case network.MSG_SYS_DUPLICATE_OBJECT: + return &MsgSysDuplicateObject{} + case network.MSG_SYS_SET_OBJECT_BINARY: + return &MsgSysSetObjectBinary{} + case network.MSG_SYS_GET_OBJECT_BINARY: + return &MsgSysGetObjectBinary{} + case network.MSG_SYS_GET_OBJECT_OWNER: + return &MsgSysGetObjectOwner{} + case network.MSG_SYS_UPDATE_OBJECT_BINARY: + return &MsgSysUpdateObjectBinary{} + case network.MSG_SYS_CLEANUP_OBJECT: + return &MsgSysCleanupObject{} + case network.MSG_SYS_reserve4A: + return &MsgSysReserve4A{} + case network.MSG_SYS_reserve4B: + return &MsgSysReserve4B{} + case network.MSG_SYS_reserve4C: + return &MsgSysReserve4C{} + case network.MSG_SYS_reserve4D: + return &MsgSysReserve4D{} + case network.MSG_SYS_reserve4E: + return &MsgSysReserve4E{} + case network.MSG_SYS_reserve4F: + return &MsgSysReserve4F{} + case network.MSG_SYS_INSERT_USER: + return &MsgSysInsertUser{} + case network.MSG_SYS_DELETE_USER: + return &MsgSysDeleteUser{} + case network.MSG_SYS_SET_USER_BINARY: + return &MsgSysSetUserBinary{} + case network.MSG_SYS_GET_USER_BINARY: + return &MsgSysGetUserBinary{} + case network.MSG_SYS_NOTIFY_USER_BINARY: + return &MsgSysNotifyUserBinary{} + case network.MSG_SYS_reserve55: + return &MsgSysReserve55{} + case network.MSG_SYS_reserve56: + return &MsgSysReserve56{} + case network.MSG_SYS_reserve57: + return &MsgSysReserve57{} + case network.MSG_SYS_UPDATE_RIGHT: + return &MsgSysUpdateRight{} + case network.MSG_SYS_AUTH_QUERY: + return &MsgSysAuthQuery{} + case network.MSG_SYS_AUTH_DATA: + return &MsgSysAuthData{} + case network.MSG_SYS_AUTH_TERMINAL: + return &MsgSysAuthTerminal{} + case network.MSG_SYS_reserve5C: + return &MsgSysReserve5C{} + case network.MSG_SYS_RIGHTS_RELOAD: + return &MsgSysRightsReload{} + case network.MSG_SYS_reserve5E: + return &MsgSysReserve5E{} + case network.MSG_SYS_reserve5F: + return &MsgSysReserve5F{} + case network.MSG_MHF_SAVEDATA: + return &MsgMhfSavedata{} + case network.MSG_MHF_LOADDATA: + return &MsgMhfLoaddata{} + case network.MSG_MHF_LIST_MEMBER: + return &MsgMhfListMember{} + case network.MSG_MHF_OPR_MEMBER: + return &MsgMhfOprMember{} + case network.MSG_MHF_ENUMERATE_DIST_ITEM: + return &MsgMhfEnumerateDistItem{} + case network.MSG_MHF_APPLY_DIST_ITEM: + return &MsgMhfApplyDistItem{} + case network.MSG_MHF_ACQUIRE_DIST_ITEM: + return &MsgMhfAcquireDistItem{} + case network.MSG_MHF_GET_DIST_DESCRIPTION: + return &MsgMhfGetDistDescription{} + case network.MSG_MHF_SEND_MAIL: + return &MsgMhfSendMail{} + case network.MSG_MHF_READ_MAIL: + return &MsgMhfReadMail{} + case network.MSG_MHF_LIST_MAIL: + return &MsgMhfListMail{} + case network.MSG_MHF_OPRT_MAIL: + return &MsgMhfOprtMail{} + case network.MSG_MHF_LOAD_FAVORITE_QUEST: + return &MsgMhfLoadFavoriteQuest{} + case network.MSG_MHF_SAVE_FAVORITE_QUEST: + return &MsgMhfSaveFavoriteQuest{} + case network.MSG_MHF_REGISTER_EVENT: + return &MsgMhfRegisterEvent{} + case network.MSG_MHF_RELEASE_EVENT: + return &MsgMhfReleaseEvent{} + case network.MSG_MHF_TRANSIT_MESSAGE: + return &MsgMhfTransitMessage{} + case network.MSG_SYS_reserve71: + return &MsgSysReserve71{} + case network.MSG_SYS_reserve72: + return &MsgSysReserve72{} + case network.MSG_SYS_reserve73: + return &MsgSysReserve73{} + case network.MSG_SYS_reserve74: + return &MsgSysReserve74{} + case network.MSG_SYS_reserve75: + return &MsgSysReserve75{} + case network.MSG_SYS_reserve76: + return &MsgSysReserve76{} + case network.MSG_SYS_reserve77: + return &MsgSysReserve77{} + case network.MSG_SYS_reserve78: + return &MsgSysReserve78{} + case network.MSG_SYS_reserve79: + return &MsgSysReserve79{} + case network.MSG_SYS_reserve7A: + return &MsgSysReserve7A{} + case network.MSG_SYS_reserve7B: + return &MsgSysReserve7B{} + case network.MSG_SYS_reserve7C: + return &MsgSysReserve7C{} + case network.MSG_CA_EXCHANGE_ITEM: + return &MsgCaExchangeItem{} + case network.MSG_SYS_reserve7E: + return &MsgSysReserve7E{} + case network.MSG_MHF_PRESENT_BOX: + return &MsgMhfPresentBox{} + case network.MSG_MHF_SERVER_COMMAND: + return &MsgMhfServerCommand{} + case network.MSG_MHF_SHUT_CLIENT: + return &MsgMhfShutClient{} + case network.MSG_MHF_ANNOUNCE: + return &MsgMhfAnnounce{} + case network.MSG_MHF_SET_LOGINWINDOW: + return &MsgMhfSetLoginwindow{} + case network.MSG_SYS_TRANS_BINARY: + return &MsgSysTransBinary{} + case network.MSG_SYS_COLLECT_BINARY: + return &MsgSysCollectBinary{} + case network.MSG_SYS_GET_STATE: + return &MsgSysGetState{} + case network.MSG_SYS_SERIALIZE: + return &MsgSysSerialize{} + case network.MSG_SYS_ENUMLOBBY: + return &MsgSysEnumlobby{} + case network.MSG_SYS_ENUMUSER: + return &MsgSysEnumuser{} + case network.MSG_SYS_INFOKYSERVER: + return &MsgSysInfokyserver{} + case network.MSG_MHF_GET_CA_UNIQUE_ID: + return &MsgMhfGetCaUniqueID{} + case network.MSG_MHF_SET_CA_ACHIEVEMENT: + return &MsgMhfSetCaAchievement{} + case network.MSG_MHF_CARAVAN_MY_SCORE: + return &MsgMhfCaravanMyScore{} + case network.MSG_MHF_CARAVAN_RANKING: + return &MsgMhfCaravanRanking{} + case network.MSG_MHF_CARAVAN_MY_RANK: + return &MsgMhfCaravanMyRank{} + case network.MSG_MHF_CREATE_GUILD: + return &MsgMhfCreateGuild{} + case network.MSG_MHF_OPERATE_GUILD: + return &MsgMhfOperateGuild{} + case network.MSG_MHF_OPERATE_GUILD_MEMBER: + return &MsgMhfOperateGuildMember{} + case network.MSG_MHF_INFO_GUILD: + return &MsgMhfInfoGuild{} + case network.MSG_MHF_ENUMERATE_GUILD: + return &MsgMhfEnumerateGuild{} + case network.MSG_MHF_UPDATE_GUILD: + return &MsgMhfUpdateGuild{} + case network.MSG_MHF_ARRANGE_GUILD_MEMBER: + return &MsgMhfArrangeGuildMember{} + case network.MSG_MHF_ENUMERATE_GUILD_MEMBER: + return &MsgMhfEnumerateGuildMember{} + case network.MSG_MHF_ENUMERATE_CAMPAIGN: + return &MsgMhfEnumerateCampaign{} + case network.MSG_MHF_STATE_CAMPAIGN: + return &MsgMhfStateCampaign{} + case network.MSG_MHF_APPLY_CAMPAIGN: + return &MsgMhfApplyCampaign{} + case network.MSG_MHF_ENUMERATE_ITEM: + return &MsgMhfEnumerateItem{} + case network.MSG_MHF_ACQUIRE_ITEM: + return &MsgMhfAcquireItem{} + case network.MSG_MHF_TRANSFER_ITEM: + return &MsgMhfTransferItem{} + case network.MSG_MHF_MERCENARY_HUNTDATA: + return &MsgMhfMercenaryHuntdata{} + case network.MSG_MHF_ENTRY_ROOKIE_GUILD: + return &MsgMhfEntryRookieGuild{} + case network.MSG_MHF_ENUMERATE_QUEST: + return &MsgMhfEnumerateQuest{} + case network.MSG_MHF_ENUMERATE_EVENT: + return &MsgMhfEnumerateEvent{} + case network.MSG_MHF_ENUMERATE_PRICE: + return &MsgMhfEnumeratePrice{} + case network.MSG_MHF_ENUMERATE_RANKING: + return &MsgMhfEnumerateRanking{} + case network.MSG_MHF_ENUMERATE_ORDER: + return &MsgMhfEnumerateOrder{} + case network.MSG_MHF_ENUMERATE_SHOP: + return &MsgMhfEnumerateShop{} + case network.MSG_MHF_GET_EXTRA_INFO: + return &MsgMhfGetExtraInfo{} + case network.MSG_MHF_UPDATE_INTERIOR: + return &MsgMhfUpdateInterior{} + case network.MSG_MHF_ENUMERATE_HOUSE: + return &MsgMhfEnumerateHouse{} + case network.MSG_MHF_UPDATE_HOUSE: + return &MsgMhfUpdateHouse{} + case network.MSG_MHF_LOAD_HOUSE: + return &MsgMhfLoadHouse{} + case network.MSG_MHF_OPERATE_WAREHOUSE: + return &MsgMhfOperateWarehouse{} + case network.MSG_MHF_ENUMERATE_WAREHOUSE: + return &MsgMhfEnumerateWarehouse{} + case network.MSG_MHF_UPDATE_WAREHOUSE: + return &MsgMhfUpdateWarehouse{} + case network.MSG_MHF_ACQUIRE_TITLE: + return &MsgMhfAcquireTitle{} + case network.MSG_MHF_ENUMERATE_TITLE: + return &MsgMhfEnumerateTitle{} + case network.MSG_MHF_ENUMERATE_GUILD_ITEM: + return &MsgMhfEnumerateGuildItem{} + case network.MSG_MHF_UPDATE_GUILD_ITEM: + return &MsgMhfUpdateGuildItem{} + case network.MSG_MHF_ENUMERATE_UNION_ITEM: + return &MsgMhfEnumerateUnionItem{} + case network.MSG_MHF_UPDATE_UNION_ITEM: + return &MsgMhfUpdateUnionItem{} + case network.MSG_MHF_CREATE_JOINT: + return &MsgMhfCreateJoint{} + case network.MSG_MHF_OPERATE_JOINT: + return &MsgMhfOperateJoint{} + case network.MSG_MHF_INFO_JOINT: + return &MsgMhfInfoJoint{} + case network.MSG_MHF_UPDATE_GUILD_ICON: + return &MsgMhfUpdateGuildIcon{} + case network.MSG_MHF_INFO_FESTA: + return &MsgMhfInfoFesta{} + case network.MSG_MHF_ENTRY_FESTA: + return &MsgMhfEntryFesta{} + case network.MSG_MHF_CHARGE_FESTA: + return &MsgMhfChargeFesta{} + case network.MSG_MHF_ACQUIRE_FESTA: + return &MsgMhfAcquireFesta{} + case network.MSG_MHF_STATE_FESTA_U: + return &MsgMhfStateFestaU{} + case network.MSG_MHF_STATE_FESTA_G: + return &MsgMhfStateFestaG{} + case network.MSG_MHF_ENUMERATE_FESTA_MEMBER: + return &MsgMhfEnumerateFestaMember{} + case network.MSG_MHF_VOTE_FESTA: + return &MsgMhfVoteFesta{} + case network.MSG_MHF_ACQUIRE_CAFE_ITEM: + return &MsgMhfAcquireCafeItem{} + case network.MSG_MHF_UPDATE_CAFEPOINT: + return &MsgMhfUpdateCafepoint{} + case network.MSG_MHF_CHECK_DAILY_CAFEPOINT: + return &MsgMhfCheckDailyCafepoint{} + case network.MSG_MHF_GET_COG_INFO: + return &MsgMhfGetCogInfo{} + case network.MSG_MHF_CHECK_MONTHLY_ITEM: + return &MsgMhfCheckMonthlyItem{} + case network.MSG_MHF_ACQUIRE_MONTHLY_ITEM: + return &MsgMhfAcquireMonthlyItem{} + case network.MSG_MHF_CHECK_WEEKLY_STAMP: + return &MsgMhfCheckWeeklyStamp{} + case network.MSG_MHF_EXCHANGE_WEEKLY_STAMP: + return &MsgMhfExchangeWeeklyStamp{} + case network.MSG_MHF_CREATE_MERCENARY: + return &MsgMhfCreateMercenary{} + case network.MSG_MHF_SAVE_MERCENARY: + return &MsgMhfSaveMercenary{} + case network.MSG_MHF_READ_MERCENARY_W: + return &MsgMhfReadMercenaryW{} + case network.MSG_MHF_READ_MERCENARY_M: + return &MsgMhfReadMercenaryM{} + case network.MSG_MHF_CONTRACT_MERCENARY: + return &MsgMhfContractMercenary{} + case network.MSG_MHF_ENUMERATE_MERCENARY_LOG: + return &MsgMhfEnumerateMercenaryLog{} + case network.MSG_MHF_ENUMERATE_GUACOT: + return &MsgMhfEnumerateGuacot{} + case network.MSG_MHF_UPDATE_GUACOT: + return &MsgMhfUpdateGuacot{} + case network.MSG_MHF_INFO_TOURNAMENT: + return &MsgMhfInfoTournament{} + case network.MSG_MHF_ENTRY_TOURNAMENT: + return &MsgMhfEntryTournament{} + case network.MSG_MHF_ENTER_TOURNAMENT_QUEST: + return &MsgMhfEnterTournamentQuest{} + case network.MSG_MHF_ACQUIRE_TOURNAMENT: + return &MsgMhfAcquireTournament{} + case network.MSG_MHF_GET_ACHIEVEMENT: + return &MsgMhfGetAchievement{} + case network.MSG_MHF_RESET_ACHIEVEMENT: + return &MsgMhfResetAchievement{} + case network.MSG_MHF_ADD_ACHIEVEMENT: + return &MsgMhfAddAchievement{} + case network.MSG_MHF_PAYMENT_ACHIEVEMENT: + return &MsgMhfPaymentAchievement{} + case network.MSG_MHF_DISPLAYED_ACHIEVEMENT: + return &MsgMhfDisplayedAchievement{} + case network.MSG_MHF_INFO_SCENARIO_COUNTER: + return &MsgMhfInfoScenarioCounter{} + case network.MSG_MHF_SAVE_SCENARIO_DATA: + return &MsgMhfSaveScenarioData{} + case network.MSG_MHF_LOAD_SCENARIO_DATA: + return &MsgMhfLoadScenarioData{} + case network.MSG_MHF_GET_BBS_SNS_STATUS: + return &MsgMhfGetBbsSnsStatus{} + case network.MSG_MHF_APPLY_BBS_ARTICLE: + return &MsgMhfApplyBbsArticle{} + case network.MSG_MHF_GET_ETC_POINTS: + return &MsgMhfGetEtcPoints{} + case network.MSG_MHF_UPDATE_ETC_POINT: + return &MsgMhfUpdateEtcPoint{} + case network.MSG_MHF_GET_MYHOUSE_INFO: + return &MsgMhfGetMyhouseInfo{} + case network.MSG_MHF_UPDATE_MYHOUSE_INFO: + return &MsgMhfUpdateMyhouseInfo{} + case network.MSG_MHF_GET_WEEKLY_SCHEDULE: + return &MsgMhfGetWeeklySchedule{} + case network.MSG_MHF_ENUMERATE_INV_GUILD: + return &MsgMhfEnumerateInvGuild{} + case network.MSG_MHF_OPERATION_INV_GUILD: + return &MsgMhfOperationInvGuild{} + case network.MSG_MHF_STAMPCARD_STAMP: + return &MsgMhfStampcardStamp{} + case network.MSG_MHF_STAMPCARD_PRIZE: + return &MsgMhfStampcardPrize{} + case network.MSG_MHF_UNRESERVE_SRG: + return &MsgMhfUnreserveSrg{} + case network.MSG_MHF_LOAD_PLATE_DATA: + return &MsgMhfLoadPlateData{} + case network.MSG_MHF_SAVE_PLATE_DATA: + return &MsgMhfSavePlateData{} + case network.MSG_MHF_LOAD_PLATE_BOX: + return &MsgMhfLoadPlateBox{} + case network.MSG_MHF_SAVE_PLATE_BOX: + return &MsgMhfSavePlateBox{} + case network.MSG_MHF_READ_GUILDCARD: + return &MsgMhfReadGuildcard{} + case network.MSG_MHF_UPDATE_GUILDCARD: + return &MsgMhfUpdateGuildcard{} + case network.MSG_MHF_READ_BEAT_LEVEL: + return &MsgMhfReadBeatLevel{} + case network.MSG_MHF_UPDATE_BEAT_LEVEL: + return &MsgMhfUpdateBeatLevel{} + case network.MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING: + return &MsgMhfReadBeatLevelAllRanking{} + case network.MSG_MHF_READ_BEAT_LEVEL_MY_RANKING: + return &MsgMhfReadBeatLevelMyRanking{} + case network.MSG_MHF_READ_LAST_WEEK_BEAT_RANKING: + return &MsgMhfReadLastWeekBeatRanking{} + case network.MSG_MHF_ACCEPT_READ_REWARD: + return &MsgMhfAcceptReadReward{} + case network.MSG_MHF_GET_ADDITIONAL_BEAT_REWARD: + return &MsgMhfGetAdditionalBeatReward{} + case network.MSG_MHF_GET_FIXED_SEIBATU_RANKING_TABLE: + return &MsgMhfGetFixedSeibatuRankingTable{} + case network.MSG_MHF_GET_BBS_USER_STATUS: + return &MsgMhfGetBbsUserStatus{} + case network.MSG_MHF_KICK_EXPORT_FORCE: + return &MsgMhfKickExportForce{} + case network.MSG_MHF_GET_BREAK_SEIBATU_LEVEL_REWARD: + return &MsgMhfGetBreakSeibatuLevelReward{} + case network.MSG_MHF_GET_WEEKLY_SEIBATU_RANKING_REWARD: + return &MsgMhfGetWeeklySeibatuRankingReward{} + case network.MSG_MHF_GET_EARTH_STATUS: + return &MsgMhfGetEarthStatus{} + case network.MSG_MHF_LOAD_PARTNER: + return &MsgMhfLoadPartner{} + case network.MSG_MHF_SAVE_PARTNER: + return &MsgMhfSavePartner{} + case network.MSG_MHF_GET_GUILD_MISSION_LIST: + return &MsgMhfGetGuildMissionList{} + case network.MSG_MHF_GET_GUILD_MISSION_RECORD: + return &MsgMhfGetGuildMissionRecord{} + case network.MSG_MHF_ADD_GUILD_MISSION_COUNT: + return &MsgMhfAddGuildMissionCount{} + case network.MSG_MHF_SET_GUILD_MISSION_TARGET: + return &MsgMhfSetGuildMissionTarget{} + case network.MSG_MHF_CANCEL_GUILD_MISSION_TARGET: + return &MsgMhfCancelGuildMissionTarget{} + case network.MSG_MHF_LOAD_OTOMO_AIROU: + return &MsgMhfLoadOtomoAirou{} + case network.MSG_MHF_SAVE_OTOMO_AIROU: + return &MsgMhfSaveOtomoAirou{} + case network.MSG_MHF_ENUMERATE_GUILD_TRESURE: + return &MsgMhfEnumerateGuildTresure{} + case network.MSG_MHF_ENUMERATE_AIROULIST: + return &MsgMhfEnumerateAiroulist{} + case network.MSG_MHF_REGIST_GUILD_TRESURE: + return &MsgMhfRegistGuildTresure{} + case network.MSG_MHF_ACQUIRE_GUILD_TRESURE: + return &MsgMhfAcquireGuildTresure{} + case network.MSG_MHF_OPERATE_GUILD_TRESURE_REPORT: + return &MsgMhfOperateGuildTresureReport{} + case network.MSG_MHF_GET_GUILD_TRESURE_SOUVENIR: + return &MsgMhfGetGuildTresureSouvenir{} + case network.MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR: + return &MsgMhfAcquireGuildTresureSouvenir{} + case network.MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE: + return &MsgMhfEnumerateFestaIntermediatePrize{} + case network.MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE: + return &MsgMhfAcquireFestaIntermediatePrize{} + case network.MSG_MHF_LOAD_DECO_MYSET: + return &MsgMhfLoadDecoMyset{} + case network.MSG_MHF_SAVE_DECO_MYSET: + return &MsgMhfSaveDecoMyset{} + case network.MSG_MHF_reserve010F: + return &MsgMhfReserve010F{} + case network.MSG_MHF_LOAD_GUILD_COOKING: + return &MsgMhfLoadGuildCooking{} + case network.MSG_MHF_REGIST_GUILD_COOKING: + return &MsgMhfRegistGuildCooking{} + case network.MSG_MHF_LOAD_GUILD_ADVENTURE: + return &MsgMhfLoadGuildAdventure{} + case network.MSG_MHF_REGIST_GUILD_ADVENTURE: + return &MsgMhfRegistGuildAdventure{} + case network.MSG_MHF_ACQUIRE_GUILD_ADVENTURE: + return &MsgMhfAcquireGuildAdventure{} + case network.MSG_MHF_CHARGE_GUILD_ADVENTURE: + return &MsgMhfChargeGuildAdventure{} + case network.MSG_MHF_LOAD_LEGEND_DISPATCH: + return &MsgMhfLoadLegendDispatch{} + case network.MSG_MHF_LOAD_HUNTER_NAVI: + return &MsgMhfLoadHunterNavi{} + case network.MSG_MHF_SAVE_HUNTER_NAVI: + return &MsgMhfSaveHunterNavi{} + case network.MSG_MHF_REGIST_SPABI_TIME: + return &MsgMhfRegistSpabiTime{} + case network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER: + return &MsgMhfGetGuildWeeklyBonusMaster{} + case network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT: + return &MsgMhfGetGuildWeeklyBonusActiveCount{} + case network.MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER: + return &MsgMhfAddGuildWeeklyBonusExceptionalUser{} + case network.MSG_MHF_GET_TOWER_INFO: + return &MsgMhfGetTowerInfo{} + case network.MSG_MHF_POST_TOWER_INFO: + return &MsgMhfPostTowerInfo{} + case network.MSG_MHF_GET_GEM_INFO: + return &MsgMhfGetGemInfo{} + case network.MSG_MHF_POST_GEM_INFO: + return &MsgMhfPostGemInfo{} + case network.MSG_MHF_GET_EARTH_VALUE: + return &MsgMhfGetEarthValue{} + case network.MSG_MHF_DEBUG_POST_VALUE: + return &MsgMhfDebugPostValue{} + case network.MSG_MHF_GET_PAPER_DATA: + return &MsgMhfGetPaperData{} + case network.MSG_MHF_GET_NOTICE: + return &MsgMhfGetNotice{} + case network.MSG_MHF_POST_NOTICE: + return &MsgMhfPostNotice{} + case network.MSG_MHF_GET_BOOST_TIME: + return &MsgMhfGetBoostTime{} + case network.MSG_MHF_POST_BOOST_TIME: + return &MsgMhfPostBoostTime{} + case network.MSG_MHF_GET_BOOST_TIME_LIMIT: + return &MsgMhfGetBoostTimeLimit{} + case network.MSG_MHF_POST_BOOST_TIME_LIMIT: + return &MsgMhfPostBoostTimeLimit{} + case network.MSG_MHF_ENUMERATE_FESTA_PERSONAL_PRIZE: + return &MsgMhfEnumerateFestaPersonalPrize{} + case network.MSG_MHF_ACQUIRE_FESTA_PERSONAL_PRIZE: + return &MsgMhfAcquireFestaPersonalPrize{} + case network.MSG_MHF_GET_RAND_FROM_TABLE: + return &MsgMhfGetRandFromTable{} + case network.MSG_MHF_GET_CAFE_DURATION: + return &MsgMhfGetCafeDuration{} + case network.MSG_MHF_GET_CAFE_DURATION_BONUS_INFO: + return &MsgMhfGetCafeDurationBonusInfo{} + case network.MSG_MHF_RECEIVE_CAFE_DURATION_BONUS: + return &MsgMhfReceiveCafeDurationBonus{} + case network.MSG_MHF_POST_CAFE_DURATION_BONUS_RECEIVED: + return &MsgMhfPostCafeDurationBonusReceived{} + case network.MSG_MHF_GET_GACHA_POINT: + return &MsgMhfGetGachaPoint{} + case network.MSG_MHF_USE_GACHA_POINT: + return &MsgMhfUseGachaPoint{} + case network.MSG_MHF_EXCHANGE_FPOINT_2_ITEM: + return &MsgMhfExchangeFpoint2Item{} + case network.MSG_MHF_EXCHANGE_ITEM_2_FPOINT: + return &MsgMhfExchangeItem2Fpoint{} + case network.MSG_MHF_GET_FPOINT_EXCHANGE_LIST: + return &MsgMhfGetFpointExchangeList{} + case network.MSG_MHF_PLAY_STEPUP_GACHA: + return &MsgMhfPlayStepupGacha{} + case network.MSG_MHF_RECEIVE_GACHA_ITEM: + return &MsgMhfReceiveGachaItem{} + case network.MSG_MHF_GET_STEPUP_STATUS: + return &MsgMhfGetStepupStatus{} + case network.MSG_MHF_PLAY_FREE_GACHA: + return &MsgMhfPlayFreeGacha{} + case network.MSG_MHF_GET_TINY_BIN: + return &MsgMhfGetTinyBin{} + case network.MSG_MHF_POST_TINY_BIN: + return &MsgMhfPostTinyBin{} + case network.MSG_MHF_GET_SENYU_DAILY_COUNT: + return &MsgMhfGetSenyuDailyCount{} + case network.MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM: + return &MsgMhfGetGuildTargetMemberNum{} + case network.MSG_MHF_GET_BOOST_RIGHT: + return &MsgMhfGetBoostRight{} + case network.MSG_MHF_START_BOOST_TIME: + return &MsgMhfStartBoostTime{} + case network.MSG_MHF_POST_BOOST_TIME_QUEST_RETURN: + return &MsgMhfPostBoostTimeQuestReturn{} + case network.MSG_MHF_GET_BOX_GACHA_INFO: + return &MsgMhfGetBoxGachaInfo{} + case network.MSG_MHF_PLAY_BOX_GACHA: + return &MsgMhfPlayBoxGacha{} + case network.MSG_MHF_RESET_BOX_GACHA_INFO: + return &MsgMhfResetBoxGachaInfo{} + case network.MSG_MHF_GET_SEIBATTLE: + return &MsgMhfGetSeibattle{} + case network.MSG_MHF_POST_SEIBATTLE: + return &MsgMhfPostSeibattle{} + case network.MSG_MHF_GET_RYOUDAMA: + return &MsgMhfGetRyoudama{} + case network.MSG_MHF_POST_RYOUDAMA: + return &MsgMhfPostRyoudama{} + case network.MSG_MHF_GET_TENROUIRAI: + return &MsgMhfGetTenrouirai{} + case network.MSG_MHF_POST_TENROUIRAI: + return &MsgMhfPostTenrouirai{} + case network.MSG_MHF_POST_GUILD_SCOUT: + return &MsgMhfPostGuildScout{} + case network.MSG_MHF_CANCEL_GUILD_SCOUT: + return &MsgMhfCancelGuildScout{} + case network.MSG_MHF_ANSWER_GUILD_SCOUT: + return &MsgMhfAnswerGuildScout{} + case network.MSG_MHF_GET_GUILD_SCOUT_LIST: + return &MsgMhfGetGuildScoutList{} + case network.MSG_MHF_GET_GUILD_MANAGE_RIGHT: + return &MsgMhfGetGuildManageRight{} + case network.MSG_MHF_SET_GUILD_MANAGE_RIGHT: + return &MsgMhfSetGuildManageRight{} + case network.MSG_MHF_PLAY_NORMAL_GACHA: + return &MsgMhfPlayNormalGacha{} + case network.MSG_MHF_GET_DAILY_MISSION_MASTER: + return &MsgMhfGetDailyMissionMaster{} + case network.MSG_MHF_GET_DAILY_MISSION_PERSONAL: + return &MsgMhfGetDailyMissionPersonal{} + case network.MSG_MHF_SET_DAILY_MISSION_PERSONAL: + return &MsgMhfSetDailyMissionPersonal{} + case network.MSG_MHF_GET_GACHA_PLAY_HISTORY: + return &MsgMhfGetGachaPlayHistory{} + case network.MSG_MHF_GET_REJECT_GUILD_SCOUT: + return &MsgMhfGetRejectGuildScout{} + case network.MSG_MHF_SET_REJECT_GUILD_SCOUT: + return &MsgMhfSetRejectGuildScout{} + case network.MSG_MHF_GET_CA_ACHIEVEMENT_HIST: + return &MsgMhfGetCaAchievementHist{} + case network.MSG_MHF_SET_CA_ACHIEVEMENT_HIST: + return &MsgMhfSetCaAchievementHist{} + case network.MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS: + return &MsgMhfGetKeepLoginBoostStatus{} + case network.MSG_MHF_USE_KEEP_LOGIN_BOOST: + return &MsgMhfUseKeepLoginBoost{} + case network.MSG_MHF_GET_UD_SCHEDULE: + return &MsgMhfGetUdSchedule{} + case network.MSG_MHF_GET_UD_INFO: + return &MsgMhfGetUdInfo{} + case network.MSG_MHF_GET_KIJU_INFO: + return &MsgMhfGetKijuInfo{} + case network.MSG_MHF_SET_KIJU: + return &MsgMhfSetKiju{} + case network.MSG_MHF_ADD_UD_POINT: + return &MsgMhfAddUdPoint{} + case network.MSG_MHF_GET_UD_MY_POINT: + return &MsgMhfGetUdMyPoint{} + case network.MSG_MHF_GET_UD_TOTAL_POINT_INFO: + return &MsgMhfGetUdTotalPointInfo{} + case network.MSG_MHF_GET_UD_BONUS_QUEST_INFO: + return &MsgMhfGetUdBonusQuestInfo{} + case network.MSG_MHF_GET_UD_SELECTED_COLOR_INFO: + return &MsgMhfGetUdSelectedColorInfo{} + case network.MSG_MHF_GET_UD_MONSTER_POINT: + return &MsgMhfGetUdMonsterPoint{} + case network.MSG_MHF_GET_UD_DAILY_PRESENT_LIST: + return &MsgMhfGetUdDailyPresentList{} + case network.MSG_MHF_GET_UD_NORMA_PRESENT_LIST: + return &MsgMhfGetUdNormaPresentList{} + case network.MSG_MHF_GET_UD_RANKING_REWARD_LIST: + return &MsgMhfGetUdRankingRewardList{} + case network.MSG_MHF_ACQUIRE_UD_ITEM: + return &MsgMhfAcquireUdItem{} + case network.MSG_MHF_GET_REWARD_SONG: + return &MsgMhfGetRewardSong{} + case network.MSG_MHF_USE_REWARD_SONG: + return &MsgMhfUseRewardSong{} + case network.MSG_MHF_ADD_REWARD_SONG_COUNT: + return &MsgMhfAddRewardSongCount{} + case network.MSG_MHF_GET_UD_RANKING: + return &MsgMhfGetUdRanking{} + case network.MSG_MHF_GET_UD_MY_RANKING: + return &MsgMhfGetUdMyRanking{} + case network.MSG_MHF_ACQUIRE_MONTHLY_REWARD: + return &MsgMhfAcquireMonthlyReward{} + case network.MSG_MHF_GET_UD_GUILD_MAP_INFO: + return &MsgMhfGetUdGuildMapInfo{} + case network.MSG_MHF_GENERATE_UD_GUILD_MAP: + return &MsgMhfGenerateUdGuildMap{} + case network.MSG_MHF_GET_UD_TACTICS_POINT: + return &MsgMhfGetUdTacticsPoint{} + case network.MSG_MHF_ADD_UD_TACTICS_POINT: + return &MsgMhfAddUdTacticsPoint{} + case network.MSG_MHF_GET_UD_TACTICS_RANKING: + return &MsgMhfGetUdTacticsRanking{} + case network.MSG_MHF_GET_UD_TACTICS_REWARD_LIST: + return &MsgMhfGetUdTacticsRewardList{} + case network.MSG_MHF_GET_UD_TACTICS_LOG: + return &MsgMhfGetUdTacticsLog{} + case network.MSG_MHF_GET_EQUIP_SKIN_HIST: + return &MsgMhfGetEquipSkinHist{} + case network.MSG_MHF_UPDATE_EQUIP_SKIN_HIST: + return &MsgMhfUpdateEquipSkinHist{} + case network.MSG_MHF_GET_UD_TACTICS_FOLLOWER: + return &MsgMhfGetUdTacticsFollower{} + case network.MSG_MHF_SET_UD_TACTICS_FOLLOWER: + return &MsgMhfSetUdTacticsFollower{} + case network.MSG_MHF_GET_UD_SHOP_COIN: + return &MsgMhfGetUdShopCoin{} + case network.MSG_MHF_USE_UD_SHOP_COIN: + return &MsgMhfUseUdShopCoin{} + case network.MSG_MHF_GET_ENHANCED_MINIDATA: + return &MsgMhfGetEnhancedMinidata{} + case network.MSG_MHF_SET_ENHANCED_MINIDATA: + return &MsgMhfSetEnhancedMinidata{} + case network.MSG_MHF_SEX_CHANGER: + return &MsgMhfSexChanger{} + case network.MSG_MHF_GET_LOBBY_CROWD: + return &MsgMhfGetLobbyCrowd{} + case network.MSG_SYS_reserve180: + return &MsgSysReserve180{} + case network.MSG_MHF_GUILD_HUNTDATA: + return &MsgMhfGuildHuntdata{} + case network.MSG_MHF_ADD_KOURYOU_POINT: + return &MsgMhfAddKouryouPoint{} + case network.MSG_MHF_GET_KOURYOU_POINT: + return &MsgMhfGetKouryouPoint{} + case network.MSG_MHF_EXCHANGE_KOURYOU_POINT: + return &MsgMhfExchangeKouryouPoint{} + case network.MSG_MHF_GET_UD_TACTICS_BONUS_QUEST: + return &MsgMhfGetUdTacticsBonusQuest{} + case network.MSG_MHF_GET_UD_TACTICS_FIRST_QUEST_BONUS: + return &MsgMhfGetUdTacticsFirstQuestBonus{} + case network.MSG_MHF_GET_UD_TACTICS_REMAINING_POINT: + return &MsgMhfGetUdTacticsRemainingPoint{} + case network.MSG_SYS_reserve188: + return &MsgSysReserve188{} + case network.MSG_MHF_LOAD_PLATE_MYSET: + return &MsgMhfLoadPlateMyset{} + case network.MSG_MHF_SAVE_PLATE_MYSET: + return &MsgMhfSavePlateMyset{} + case network.MSG_SYS_reserve18B: + return &MsgSysReserve18B{} + case network.MSG_MHF_GET_RESTRICTION_EVENT: + return &MsgMhfGetRestrictionEvent{} + case network.MSG_MHF_SET_RESTRICTION_EVENT: + return &MsgMhfSetRestrictionEvent{} + case network.MSG_SYS_reserve18E: + return &MsgSysReserve18E{} + case network.MSG_SYS_reserve18F: + return &MsgSysReserve18F{} + case network.MSG_MHF_GET_TREND_WEAPON: + return &MsgMhfGetTrendWeapon{} + case network.MSG_MHF_UPDATE_USE_TREND_WEAPON_LOG: + return &MsgMhfUpdateUseTrendWeaponLog{} + case network.MSG_SYS_reserve192: + return &MsgSysReserve192{} + case network.MSG_SYS_reserve193: + return &MsgSysReserve193{} + case network.MSG_SYS_reserve194: + return &MsgSysReserve194{} + case network.MSG_MHF_SAVE_RENGOKU_DATA: + return &MsgMhfSaveRengokuData{} + case network.MSG_MHF_LOAD_RENGOKU_DATA: + return &MsgMhfLoadRengokuData{} + case network.MSG_MHF_GET_RENGOKU_BINARY: + return &MsgMhfGetRengokuBinary{} + case network.MSG_MHF_ENUMERATE_RENGOKU_RANKING: + return &MsgMhfEnumerateRengokuRanking{} + case network.MSG_MHF_GET_RENGOKU_RANKING_RANK: + return &MsgMhfGetRengokuRankingRank{} + case network.MSG_MHF_ACQUIRE_EXCHANGE_SHOP: + return &MsgMhfAcquireExchangeShop{} + case network.MSG_SYS_reserve19B: + return &MsgSysReserve19B{} + case network.MSG_MHF_SAVE_MEZFES_DATA: + return &MsgMhfSaveMezfesData{} + case network.MSG_MHF_LOAD_MEZFES_DATA: + return &MsgMhfLoadMezfesData{} + case network.MSG_SYS_reserve19E: + return &MsgSysReserve19E{} + case network.MSG_SYS_reserve19F: + return &MsgSysReserve19F{} + case network.MSG_MHF_UPDATE_FORCE_GUILD_RANK: + return &MsgMhfUpdateForceGuildRank{} + case network.MSG_MHF_RESET_TITLE: + return &MsgMhfResetTitle{} + case network.MSG_SYS_reserve202: + return &MsgSysReserve202{} + case network.MSG_SYS_reserve203: + return &MsgSysReserve203{} + case network.MSG_SYS_reserve204: + return &MsgSysReserve204{} + case network.MSG_SYS_reserve205: + return &MsgSysReserve205{} + case network.MSG_SYS_reserve206: + return &MsgSysReserve206{} + case network.MSG_SYS_reserve207: + return &MsgSysReserve207{} + case network.MSG_SYS_reserve208: + return &MsgSysReserve208{} + case network.MSG_SYS_reserve209: + return &MsgSysReserve209{} + case network.MSG_SYS_reserve20A: + return &MsgSysReserve20A{} + case network.MSG_SYS_reserve20B: + return &MsgSysReserve20B{} + case network.MSG_SYS_reserve20C: + return &MsgSysReserve20C{} + case network.MSG_SYS_reserve20D: + return &MsgSysReserve20D{} + case network.MSG_SYS_reserve20E: + return &MsgSysReserve20E{} + case network.MSG_SYS_reserve20F: + return &MsgSysReserve20F{} + } + return nil +} diff --git a/Erupe/network/packetid.go b/Erupe/network/packetid.go new file mode 100644 index 000000000..7f9ee4d6c --- /dev/null +++ b/Erupe/network/packetid.go @@ -0,0 +1,442 @@ +package network + +//revive:disable +type PacketID uint16 + +//go:generate stringer -type=PacketID +const ( + MSG_HEAD PacketID = iota + MSG_SYS_reserve01 + MSG_SYS_reserve02 + MSG_SYS_reserve03 + MSG_SYS_reserve04 + MSG_SYS_reserve05 + MSG_SYS_reserve06 + MSG_SYS_reserve07 + MSG_SYS_ADD_OBJECT + MSG_SYS_DEL_OBJECT + MSG_SYS_DISP_OBJECT + MSG_SYS_HIDE_OBJECT + MSG_SYS_reserve0C + MSG_SYS_reserve0D + MSG_SYS_reserve0E + MSG_SYS_EXTEND_THRESHOLD + MSG_SYS_END + MSG_SYS_NOP + MSG_SYS_ACK + MSG_SYS_TERMINAL_LOG + MSG_SYS_LOGIN + MSG_SYS_LOGOUT + MSG_SYS_SET_STATUS + MSG_SYS_PING + MSG_SYS_CAST_BINARY + MSG_SYS_HIDE_CLIENT + MSG_SYS_TIME + MSG_SYS_CASTED_BINARY + MSG_SYS_GET_FILE + MSG_SYS_ISSUE_LOGKEY + MSG_SYS_RECORD_LOG + MSG_SYS_ECHO + MSG_SYS_CREATE_STAGE + MSG_SYS_STAGE_DESTRUCT + MSG_SYS_ENTER_STAGE + MSG_SYS_BACK_STAGE + MSG_SYS_MOVE_STAGE + MSG_SYS_LEAVE_STAGE + MSG_SYS_LOCK_STAGE + MSG_SYS_UNLOCK_STAGE + MSG_SYS_RESERVE_STAGE + MSG_SYS_UNRESERVE_STAGE + MSG_SYS_SET_STAGE_PASS + MSG_SYS_WAIT_STAGE_BINARY + MSG_SYS_SET_STAGE_BINARY + MSG_SYS_GET_STAGE_BINARY + MSG_SYS_ENUMERATE_CLIENT + MSG_SYS_ENUMERATE_STAGE + MSG_SYS_CREATE_MUTEX + MSG_SYS_CREATE_OPEN_MUTEX + MSG_SYS_DELETE_MUTEX + MSG_SYS_OPEN_MUTEX + MSG_SYS_CLOSE_MUTEX + MSG_SYS_CREATE_SEMAPHORE + MSG_SYS_CREATE_ACQUIRE_SEMAPHORE + MSG_SYS_DELETE_SEMAPHORE + MSG_SYS_ACQUIRE_SEMAPHORE + MSG_SYS_RELEASE_SEMAPHORE + MSG_SYS_LOCK_GLOBAL_SEMA + MSG_SYS_UNLOCK_GLOBAL_SEMA + MSG_SYS_CHECK_SEMAPHORE + MSG_SYS_OPERATE_REGISTER + MSG_SYS_LOAD_REGISTER + MSG_SYS_NOTIFY_REGISTER + MSG_SYS_CREATE_OBJECT + MSG_SYS_DELETE_OBJECT + MSG_SYS_POSITION_OBJECT + MSG_SYS_ROTATE_OBJECT + MSG_SYS_DUPLICATE_OBJECT + MSG_SYS_SET_OBJECT_BINARY + MSG_SYS_GET_OBJECT_BINARY + MSG_SYS_GET_OBJECT_OWNER + MSG_SYS_UPDATE_OBJECT_BINARY + MSG_SYS_CLEANUP_OBJECT + MSG_SYS_reserve4A + MSG_SYS_reserve4B + MSG_SYS_reserve4C + MSG_SYS_reserve4D + MSG_SYS_reserve4E + MSG_SYS_reserve4F + MSG_SYS_INSERT_USER + MSG_SYS_DELETE_USER + MSG_SYS_SET_USER_BINARY + MSG_SYS_GET_USER_BINARY + MSG_SYS_NOTIFY_USER_BINARY + MSG_SYS_reserve55 + MSG_SYS_reserve56 + MSG_SYS_reserve57 + MSG_SYS_UPDATE_RIGHT + MSG_SYS_AUTH_QUERY + MSG_SYS_AUTH_DATA + MSG_SYS_AUTH_TERMINAL + MSG_SYS_reserve5C + MSG_SYS_RIGHTS_RELOAD + MSG_SYS_reserve5E + MSG_SYS_reserve5F + MSG_MHF_SAVEDATA + MSG_MHF_LOADDATA + MSG_MHF_LIST_MEMBER + MSG_MHF_OPR_MEMBER + MSG_MHF_ENUMERATE_DIST_ITEM + MSG_MHF_APPLY_DIST_ITEM + MSG_MHF_ACQUIRE_DIST_ITEM + MSG_MHF_GET_DIST_DESCRIPTION + MSG_MHF_SEND_MAIL + MSG_MHF_READ_MAIL + MSG_MHF_LIST_MAIL + MSG_MHF_OPRT_MAIL + MSG_MHF_LOAD_FAVORITE_QUEST + MSG_MHF_SAVE_FAVORITE_QUEST + MSG_MHF_REGISTER_EVENT + MSG_MHF_RELEASE_EVENT + MSG_MHF_TRANSIT_MESSAGE + MSG_SYS_reserve71 + MSG_SYS_reserve72 + MSG_SYS_reserve73 + MSG_SYS_reserve74 + MSG_SYS_reserve75 + MSG_SYS_reserve76 + MSG_SYS_reserve77 + MSG_SYS_reserve78 + MSG_SYS_reserve79 + MSG_SYS_reserve7A + MSG_SYS_reserve7B + MSG_SYS_reserve7C + MSG_CA_EXCHANGE_ITEM + MSG_SYS_reserve7E + MSG_MHF_PRESENT_BOX + MSG_MHF_SERVER_COMMAND + MSG_MHF_SHUT_CLIENT + MSG_MHF_ANNOUNCE + MSG_MHF_SET_LOGINWINDOW + MSG_SYS_TRANS_BINARY + MSG_SYS_COLLECT_BINARY + MSG_SYS_GET_STATE + MSG_SYS_SERIALIZE + MSG_SYS_ENUMLOBBY + MSG_SYS_ENUMUSER + MSG_SYS_INFOKYSERVER + MSG_MHF_GET_CA_UNIQUE_ID + MSG_MHF_SET_CA_ACHIEVEMENT + MSG_MHF_CARAVAN_MY_SCORE + MSG_MHF_CARAVAN_RANKING + MSG_MHF_CARAVAN_MY_RANK + MSG_MHF_CREATE_GUILD + MSG_MHF_OPERATE_GUILD + MSG_MHF_OPERATE_GUILD_MEMBER + MSG_MHF_INFO_GUILD + MSG_MHF_ENUMERATE_GUILD + MSG_MHF_UPDATE_GUILD + MSG_MHF_ARRANGE_GUILD_MEMBER + MSG_MHF_ENUMERATE_GUILD_MEMBER + MSG_MHF_ENUMERATE_CAMPAIGN + MSG_MHF_STATE_CAMPAIGN + MSG_MHF_APPLY_CAMPAIGN + MSG_MHF_ENUMERATE_ITEM + MSG_MHF_ACQUIRE_ITEM + MSG_MHF_TRANSFER_ITEM + MSG_MHF_MERCENARY_HUNTDATA + MSG_MHF_ENTRY_ROOKIE_GUILD + MSG_MHF_ENUMERATE_QUEST + MSG_MHF_ENUMERATE_EVENT + MSG_MHF_ENUMERATE_PRICE + MSG_MHF_ENUMERATE_RANKING + MSG_MHF_ENUMERATE_ORDER + MSG_MHF_ENUMERATE_SHOP + MSG_MHF_GET_EXTRA_INFO + MSG_MHF_UPDATE_INTERIOR + MSG_MHF_ENUMERATE_HOUSE + MSG_MHF_UPDATE_HOUSE + MSG_MHF_LOAD_HOUSE + MSG_MHF_OPERATE_WAREHOUSE + MSG_MHF_ENUMERATE_WAREHOUSE + MSG_MHF_UPDATE_WAREHOUSE + MSG_MHF_ACQUIRE_TITLE + MSG_MHF_ENUMERATE_TITLE + MSG_MHF_ENUMERATE_GUILD_ITEM + MSG_MHF_UPDATE_GUILD_ITEM + MSG_MHF_ENUMERATE_UNION_ITEM + MSG_MHF_UPDATE_UNION_ITEM + MSG_MHF_CREATE_JOINT + MSG_MHF_OPERATE_JOINT + MSG_MHF_INFO_JOINT + MSG_MHF_UPDATE_GUILD_ICON + MSG_MHF_INFO_FESTA + MSG_MHF_ENTRY_FESTA + MSG_MHF_CHARGE_FESTA + MSG_MHF_ACQUIRE_FESTA + MSG_MHF_STATE_FESTA_U + MSG_MHF_STATE_FESTA_G + MSG_MHF_ENUMERATE_FESTA_MEMBER + MSG_MHF_VOTE_FESTA + MSG_MHF_ACQUIRE_CAFE_ITEM + MSG_MHF_UPDATE_CAFEPOINT + MSG_MHF_CHECK_DAILY_CAFEPOINT + MSG_MHF_GET_COG_INFO + MSG_MHF_CHECK_MONTHLY_ITEM + MSG_MHF_ACQUIRE_MONTHLY_ITEM + MSG_MHF_CHECK_WEEKLY_STAMP + MSG_MHF_EXCHANGE_WEEKLY_STAMP + MSG_MHF_CREATE_MERCENARY + MSG_MHF_SAVE_MERCENARY + MSG_MHF_READ_MERCENARY_W + MSG_MHF_READ_MERCENARY_M + MSG_MHF_CONTRACT_MERCENARY + MSG_MHF_ENUMERATE_MERCENARY_LOG + MSG_MHF_ENUMERATE_GUACOT + MSG_MHF_UPDATE_GUACOT + MSG_MHF_INFO_TOURNAMENT + MSG_MHF_ENTRY_TOURNAMENT + MSG_MHF_ENTER_TOURNAMENT_QUEST + MSG_MHF_ACQUIRE_TOURNAMENT + MSG_MHF_GET_ACHIEVEMENT + MSG_MHF_RESET_ACHIEVEMENT + MSG_MHF_ADD_ACHIEVEMENT + MSG_MHF_PAYMENT_ACHIEVEMENT + MSG_MHF_DISPLAYED_ACHIEVEMENT + MSG_MHF_INFO_SCENARIO_COUNTER + MSG_MHF_SAVE_SCENARIO_DATA + MSG_MHF_LOAD_SCENARIO_DATA + MSG_MHF_GET_BBS_SNS_STATUS + MSG_MHF_APPLY_BBS_ARTICLE + MSG_MHF_GET_ETC_POINTS + MSG_MHF_UPDATE_ETC_POINT + MSG_MHF_GET_MYHOUSE_INFO + MSG_MHF_UPDATE_MYHOUSE_INFO + MSG_MHF_GET_WEEKLY_SCHEDULE + MSG_MHF_ENUMERATE_INV_GUILD + MSG_MHF_OPERATION_INV_GUILD + MSG_MHF_STAMPCARD_STAMP + MSG_MHF_STAMPCARD_PRIZE + MSG_MHF_UNRESERVE_SRG + MSG_MHF_LOAD_PLATE_DATA + MSG_MHF_SAVE_PLATE_DATA + MSG_MHF_LOAD_PLATE_BOX + MSG_MHF_SAVE_PLATE_BOX + MSG_MHF_READ_GUILDCARD + MSG_MHF_UPDATE_GUILDCARD + MSG_MHF_READ_BEAT_LEVEL + MSG_MHF_UPDATE_BEAT_LEVEL + MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING + MSG_MHF_READ_BEAT_LEVEL_MY_RANKING + MSG_MHF_READ_LAST_WEEK_BEAT_RANKING + MSG_MHF_ACCEPT_READ_REWARD + MSG_MHF_GET_ADDITIONAL_BEAT_REWARD + MSG_MHF_GET_FIXED_SEIBATU_RANKING_TABLE + MSG_MHF_GET_BBS_USER_STATUS + MSG_MHF_KICK_EXPORT_FORCE + MSG_MHF_GET_BREAK_SEIBATU_LEVEL_REWARD + MSG_MHF_GET_WEEKLY_SEIBATU_RANKING_REWARD + MSG_MHF_GET_EARTH_STATUS + MSG_MHF_LOAD_PARTNER + MSG_MHF_SAVE_PARTNER + MSG_MHF_GET_GUILD_MISSION_LIST + MSG_MHF_GET_GUILD_MISSION_RECORD + MSG_MHF_ADD_GUILD_MISSION_COUNT + MSG_MHF_SET_GUILD_MISSION_TARGET + MSG_MHF_CANCEL_GUILD_MISSION_TARGET + MSG_MHF_LOAD_OTOMO_AIROU + MSG_MHF_SAVE_OTOMO_AIROU + MSG_MHF_ENUMERATE_GUILD_TRESURE + MSG_MHF_ENUMERATE_AIROULIST + MSG_MHF_REGIST_GUILD_TRESURE + MSG_MHF_ACQUIRE_GUILD_TRESURE + MSG_MHF_OPERATE_GUILD_TRESURE_REPORT + MSG_MHF_GET_GUILD_TRESURE_SOUVENIR + MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR + MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE + MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE + MSG_MHF_LOAD_DECO_MYSET + MSG_MHF_SAVE_DECO_MYSET + MSG_MHF_reserve010F + MSG_MHF_LOAD_GUILD_COOKING + MSG_MHF_REGIST_GUILD_COOKING + MSG_MHF_LOAD_GUILD_ADVENTURE + MSG_MHF_REGIST_GUILD_ADVENTURE + MSG_MHF_ACQUIRE_GUILD_ADVENTURE + MSG_MHF_CHARGE_GUILD_ADVENTURE + MSG_MHF_LOAD_LEGEND_DISPATCH + MSG_MHF_LOAD_HUNTER_NAVI + MSG_MHF_SAVE_HUNTER_NAVI + MSG_MHF_REGIST_SPABI_TIME + MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER + MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT + MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER + MSG_MHF_GET_TOWER_INFO + MSG_MHF_POST_TOWER_INFO + MSG_MHF_GET_GEM_INFO + MSG_MHF_POST_GEM_INFO + MSG_MHF_GET_EARTH_VALUE + MSG_MHF_DEBUG_POST_VALUE + MSG_MHF_GET_PAPER_DATA + MSG_MHF_GET_NOTICE + MSG_MHF_POST_NOTICE + MSG_MHF_GET_BOOST_TIME + MSG_MHF_POST_BOOST_TIME + MSG_MHF_GET_BOOST_TIME_LIMIT + MSG_MHF_POST_BOOST_TIME_LIMIT + MSG_MHF_ENUMERATE_FESTA_PERSONAL_PRIZE + MSG_MHF_ACQUIRE_FESTA_PERSONAL_PRIZE + MSG_MHF_GET_RAND_FROM_TABLE + MSG_MHF_GET_CAFE_DURATION + MSG_MHF_GET_CAFE_DURATION_BONUS_INFO + MSG_MHF_RECEIVE_CAFE_DURATION_BONUS + MSG_MHF_POST_CAFE_DURATION_BONUS_RECEIVED + MSG_MHF_GET_GACHA_POINT + MSG_MHF_USE_GACHA_POINT + MSG_MHF_EXCHANGE_FPOINT_2_ITEM + MSG_MHF_EXCHANGE_ITEM_2_FPOINT + MSG_MHF_GET_FPOINT_EXCHANGE_LIST + MSG_MHF_PLAY_STEPUP_GACHA + MSG_MHF_RECEIVE_GACHA_ITEM + MSG_MHF_GET_STEPUP_STATUS + MSG_MHF_PLAY_FREE_GACHA + MSG_MHF_GET_TINY_BIN + MSG_MHF_POST_TINY_BIN + MSG_MHF_GET_SENYU_DAILY_COUNT + MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM + MSG_MHF_GET_BOOST_RIGHT + MSG_MHF_START_BOOST_TIME + MSG_MHF_POST_BOOST_TIME_QUEST_RETURN + MSG_MHF_GET_BOX_GACHA_INFO + MSG_MHF_PLAY_BOX_GACHA + MSG_MHF_RESET_BOX_GACHA_INFO + MSG_MHF_GET_SEIBATTLE + MSG_MHF_POST_SEIBATTLE + MSG_MHF_GET_RYOUDAMA + MSG_MHF_POST_RYOUDAMA + MSG_MHF_GET_TENROUIRAI + MSG_MHF_POST_TENROUIRAI + MSG_MHF_POST_GUILD_SCOUT + MSG_MHF_CANCEL_GUILD_SCOUT + MSG_MHF_ANSWER_GUILD_SCOUT + MSG_MHF_GET_GUILD_SCOUT_LIST + MSG_MHF_GET_GUILD_MANAGE_RIGHT + MSG_MHF_SET_GUILD_MANAGE_RIGHT + MSG_MHF_PLAY_NORMAL_GACHA + MSG_MHF_GET_DAILY_MISSION_MASTER + MSG_MHF_GET_DAILY_MISSION_PERSONAL + MSG_MHF_SET_DAILY_MISSION_PERSONAL + MSG_MHF_GET_GACHA_PLAY_HISTORY + MSG_MHF_GET_REJECT_GUILD_SCOUT + MSG_MHF_SET_REJECT_GUILD_SCOUT + MSG_MHF_GET_CA_ACHIEVEMENT_HIST + MSG_MHF_SET_CA_ACHIEVEMENT_HIST + MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS + MSG_MHF_USE_KEEP_LOGIN_BOOST + MSG_MHF_GET_UD_SCHEDULE + MSG_MHF_GET_UD_INFO + MSG_MHF_GET_KIJU_INFO + MSG_MHF_SET_KIJU + MSG_MHF_ADD_UD_POINT + MSG_MHF_GET_UD_MY_POINT + MSG_MHF_GET_UD_TOTAL_POINT_INFO + MSG_MHF_GET_UD_BONUS_QUEST_INFO + MSG_MHF_GET_UD_SELECTED_COLOR_INFO + MSG_MHF_GET_UD_MONSTER_POINT + MSG_MHF_GET_UD_DAILY_PRESENT_LIST + MSG_MHF_GET_UD_NORMA_PRESENT_LIST + MSG_MHF_GET_UD_RANKING_REWARD_LIST + MSG_MHF_ACQUIRE_UD_ITEM + MSG_MHF_GET_REWARD_SONG + MSG_MHF_USE_REWARD_SONG + MSG_MHF_ADD_REWARD_SONG_COUNT + MSG_MHF_GET_UD_RANKING + MSG_MHF_GET_UD_MY_RANKING + MSG_MHF_ACQUIRE_MONTHLY_REWARD + MSG_MHF_GET_UD_GUILD_MAP_INFO + MSG_MHF_GENERATE_UD_GUILD_MAP + MSG_MHF_GET_UD_TACTICS_POINT + MSG_MHF_ADD_UD_TACTICS_POINT + MSG_MHF_GET_UD_TACTICS_RANKING + MSG_MHF_GET_UD_TACTICS_REWARD_LIST + MSG_MHF_GET_UD_TACTICS_LOG + MSG_MHF_GET_EQUIP_SKIN_HIST + MSG_MHF_UPDATE_EQUIP_SKIN_HIST + MSG_MHF_GET_UD_TACTICS_FOLLOWER + MSG_MHF_SET_UD_TACTICS_FOLLOWER + MSG_MHF_GET_UD_SHOP_COIN + MSG_MHF_USE_UD_SHOP_COIN + MSG_MHF_GET_ENHANCED_MINIDATA + MSG_MHF_SET_ENHANCED_MINIDATA + MSG_MHF_SEX_CHANGER + MSG_MHF_GET_LOBBY_CROWD + MSG_SYS_reserve180 + MSG_MHF_GUILD_HUNTDATA + MSG_MHF_ADD_KOURYOU_POINT + MSG_MHF_GET_KOURYOU_POINT + MSG_MHF_EXCHANGE_KOURYOU_POINT + MSG_MHF_GET_UD_TACTICS_BONUS_QUEST + MSG_MHF_GET_UD_TACTICS_FIRST_QUEST_BONUS + MSG_MHF_GET_UD_TACTICS_REMAINING_POINT + MSG_SYS_reserve188 + MSG_MHF_LOAD_PLATE_MYSET + MSG_MHF_SAVE_PLATE_MYSET + MSG_SYS_reserve18B + MSG_MHF_GET_RESTRICTION_EVENT + MSG_MHF_SET_RESTRICTION_EVENT + MSG_SYS_reserve18E + MSG_SYS_reserve18F + MSG_MHF_GET_TREND_WEAPON + MSG_MHF_UPDATE_USE_TREND_WEAPON_LOG + MSG_SYS_reserve192 + MSG_SYS_reserve193 + MSG_SYS_reserve194 + MSG_MHF_SAVE_RENGOKU_DATA + MSG_MHF_LOAD_RENGOKU_DATA + MSG_MHF_GET_RENGOKU_BINARY + MSG_MHF_ENUMERATE_RENGOKU_RANKING + MSG_MHF_GET_RENGOKU_RANKING_RANK + MSG_MHF_ACQUIRE_EXCHANGE_SHOP + MSG_SYS_reserve19B + MSG_MHF_SAVE_MEZFES_DATA + MSG_MHF_LOAD_MEZFES_DATA + MSG_SYS_reserve19E + MSG_SYS_reserve19F + MSG_MHF_UPDATE_FORCE_GUILD_RANK + MSG_MHF_RESET_TITLE + MSG_SYS_reserve202 + MSG_SYS_reserve203 + MSG_SYS_reserve204 + MSG_SYS_reserve205 + MSG_SYS_reserve206 + MSG_SYS_reserve207 + MSG_SYS_reserve208 + MSG_SYS_reserve209 + MSG_SYS_reserve20A + MSG_SYS_reserve20B + MSG_SYS_reserve20C + MSG_SYS_reserve20D + MSG_SYS_reserve20E + MSG_SYS_reserve20F +) + +//revive:enable diff --git a/Erupe/network/packetid_string.go b/Erupe/network/packetid_string.go new file mode 100644 index 000000000..def56d278 --- /dev/null +++ b/Erupe/network/packetid_string.go @@ -0,0 +1,454 @@ +// Code generated by "stringer -type=PacketID"; DO NOT EDIT. + +package network + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[MSG_HEAD-0] + _ = x[MSG_SYS_reserve01-1] + _ = x[MSG_SYS_reserve02-2] + _ = x[MSG_SYS_reserve03-3] + _ = x[MSG_SYS_reserve04-4] + _ = x[MSG_SYS_reserve05-5] + _ = x[MSG_SYS_reserve06-6] + _ = x[MSG_SYS_reserve07-7] + _ = x[MSG_SYS_ADD_OBJECT-8] + _ = x[MSG_SYS_DEL_OBJECT-9] + _ = x[MSG_SYS_DISP_OBJECT-10] + _ = x[MSG_SYS_HIDE_OBJECT-11] + _ = x[MSG_SYS_reserve0C-12] + _ = x[MSG_SYS_reserve0D-13] + _ = x[MSG_SYS_reserve0E-14] + _ = x[MSG_SYS_EXTEND_THRESHOLD-15] + _ = x[MSG_SYS_END-16] + _ = x[MSG_SYS_NOP-17] + _ = x[MSG_SYS_ACK-18] + _ = x[MSG_SYS_TERMINAL_LOG-19] + _ = x[MSG_SYS_LOGIN-20] + _ = x[MSG_SYS_LOGOUT-21] + _ = x[MSG_SYS_SET_STATUS-22] + _ = x[MSG_SYS_PING-23] + _ = x[MSG_SYS_CAST_BINARY-24] + _ = x[MSG_SYS_HIDE_CLIENT-25] + _ = x[MSG_SYS_TIME-26] + _ = x[MSG_SYS_CASTED_BINARY-27] + _ = x[MSG_SYS_GET_FILE-28] + _ = x[MSG_SYS_ISSUE_LOGKEY-29] + _ = x[MSG_SYS_RECORD_LOG-30] + _ = x[MSG_SYS_ECHO-31] + _ = x[MSG_SYS_CREATE_STAGE-32] + _ = x[MSG_SYS_STAGE_DESTRUCT-33] + _ = x[MSG_SYS_ENTER_STAGE-34] + _ = x[MSG_SYS_BACK_STAGE-35] + _ = x[MSG_SYS_MOVE_STAGE-36] + _ = x[MSG_SYS_LEAVE_STAGE-37] + _ = x[MSG_SYS_LOCK_STAGE-38] + _ = x[MSG_SYS_UNLOCK_STAGE-39] + _ = x[MSG_SYS_RESERVE_STAGE-40] + _ = x[MSG_SYS_UNRESERVE_STAGE-41] + _ = x[MSG_SYS_SET_STAGE_PASS-42] + _ = x[MSG_SYS_WAIT_STAGE_BINARY-43] + _ = x[MSG_SYS_SET_STAGE_BINARY-44] + _ = x[MSG_SYS_GET_STAGE_BINARY-45] + _ = x[MSG_SYS_ENUMERATE_CLIENT-46] + _ = x[MSG_SYS_ENUMERATE_STAGE-47] + _ = x[MSG_SYS_CREATE_MUTEX-48] + _ = x[MSG_SYS_CREATE_OPEN_MUTEX-49] + _ = x[MSG_SYS_DELETE_MUTEX-50] + _ = x[MSG_SYS_OPEN_MUTEX-51] + _ = x[MSG_SYS_CLOSE_MUTEX-52] + _ = x[MSG_SYS_CREATE_SEMAPHORE-53] + _ = x[MSG_SYS_CREATE_ACQUIRE_SEMAPHORE-54] + _ = x[MSG_SYS_DELETE_SEMAPHORE-55] + _ = x[MSG_SYS_ACQUIRE_SEMAPHORE-56] + _ = x[MSG_SYS_RELEASE_SEMAPHORE-57] + _ = x[MSG_SYS_LOCK_GLOBAL_SEMA-58] + _ = x[MSG_SYS_UNLOCK_GLOBAL_SEMA-59] + _ = x[MSG_SYS_CHECK_SEMAPHORE-60] + _ = x[MSG_SYS_OPERATE_REGISTER-61] + _ = x[MSG_SYS_LOAD_REGISTER-62] + _ = x[MSG_SYS_NOTIFY_REGISTER-63] + _ = x[MSG_SYS_CREATE_OBJECT-64] + _ = x[MSG_SYS_DELETE_OBJECT-65] + _ = x[MSG_SYS_POSITION_OBJECT-66] + _ = x[MSG_SYS_ROTATE_OBJECT-67] + _ = x[MSG_SYS_DUPLICATE_OBJECT-68] + _ = x[MSG_SYS_SET_OBJECT_BINARY-69] + _ = x[MSG_SYS_GET_OBJECT_BINARY-70] + _ = x[MSG_SYS_GET_OBJECT_OWNER-71] + _ = x[MSG_SYS_UPDATE_OBJECT_BINARY-72] + _ = x[MSG_SYS_CLEANUP_OBJECT-73] + _ = x[MSG_SYS_reserve4A-74] + _ = x[MSG_SYS_reserve4B-75] + _ = x[MSG_SYS_reserve4C-76] + _ = x[MSG_SYS_reserve4D-77] + _ = x[MSG_SYS_reserve4E-78] + _ = x[MSG_SYS_reserve4F-79] + _ = x[MSG_SYS_INSERT_USER-80] + _ = x[MSG_SYS_DELETE_USER-81] + _ = x[MSG_SYS_SET_USER_BINARY-82] + _ = x[MSG_SYS_GET_USER_BINARY-83] + _ = x[MSG_SYS_NOTIFY_USER_BINARY-84] + _ = x[MSG_SYS_reserve55-85] + _ = x[MSG_SYS_reserve56-86] + _ = x[MSG_SYS_reserve57-87] + _ = x[MSG_SYS_UPDATE_RIGHT-88] + _ = x[MSG_SYS_AUTH_QUERY-89] + _ = x[MSG_SYS_AUTH_DATA-90] + _ = x[MSG_SYS_AUTH_TERMINAL-91] + _ = x[MSG_SYS_reserve5C-92] + _ = x[MSG_SYS_RIGHTS_RELOAD-93] + _ = x[MSG_SYS_reserve5E-94] + _ = x[MSG_SYS_reserve5F-95] + _ = x[MSG_MHF_SAVEDATA-96] + _ = x[MSG_MHF_LOADDATA-97] + _ = x[MSG_MHF_LIST_MEMBER-98] + _ = x[MSG_MHF_OPR_MEMBER-99] + _ = x[MSG_MHF_ENUMERATE_DIST_ITEM-100] + _ = x[MSG_MHF_APPLY_DIST_ITEM-101] + _ = x[MSG_MHF_ACQUIRE_DIST_ITEM-102] + _ = x[MSG_MHF_GET_DIST_DESCRIPTION-103] + _ = x[MSG_MHF_SEND_MAIL-104] + _ = x[MSG_MHF_READ_MAIL-105] + _ = x[MSG_MHF_LIST_MAIL-106] + _ = x[MSG_MHF_OPRT_MAIL-107] + _ = x[MSG_MHF_LOAD_FAVORITE_QUEST-108] + _ = x[MSG_MHF_SAVE_FAVORITE_QUEST-109] + _ = x[MSG_MHF_REGISTER_EVENT-110] + _ = x[MSG_MHF_RELEASE_EVENT-111] + _ = x[MSG_MHF_TRANSIT_MESSAGE-112] + _ = x[MSG_SYS_reserve71-113] + _ = x[MSG_SYS_reserve72-114] + _ = x[MSG_SYS_reserve73-115] + _ = x[MSG_SYS_reserve74-116] + _ = x[MSG_SYS_reserve75-117] + _ = x[MSG_SYS_reserve76-118] + _ = x[MSG_SYS_reserve77-119] + _ = x[MSG_SYS_reserve78-120] + _ = x[MSG_SYS_reserve79-121] + _ = x[MSG_SYS_reserve7A-122] + _ = x[MSG_SYS_reserve7B-123] + _ = x[MSG_SYS_reserve7C-124] + _ = x[MSG_CA_EXCHANGE_ITEM-125] + _ = x[MSG_SYS_reserve7E-126] + _ = x[MSG_MHF_PRESENT_BOX-127] + _ = x[MSG_MHF_SERVER_COMMAND-128] + _ = x[MSG_MHF_SHUT_CLIENT-129] + _ = x[MSG_MHF_ANNOUNCE-130] + _ = x[MSG_MHF_SET_LOGINWINDOW-131] + _ = x[MSG_SYS_TRANS_BINARY-132] + _ = x[MSG_SYS_COLLECT_BINARY-133] + _ = x[MSG_SYS_GET_STATE-134] + _ = x[MSG_SYS_SERIALIZE-135] + _ = x[MSG_SYS_ENUMLOBBY-136] + _ = x[MSG_SYS_ENUMUSER-137] + _ = x[MSG_SYS_INFOKYSERVER-138] + _ = x[MSG_MHF_GET_CA_UNIQUE_ID-139] + _ = x[MSG_MHF_SET_CA_ACHIEVEMENT-140] + _ = x[MSG_MHF_CARAVAN_MY_SCORE-141] + _ = x[MSG_MHF_CARAVAN_RANKING-142] + _ = x[MSG_MHF_CARAVAN_MY_RANK-143] + _ = x[MSG_MHF_CREATE_GUILD-144] + _ = x[MSG_MHF_OPERATE_GUILD-145] + _ = x[MSG_MHF_OPERATE_GUILD_MEMBER-146] + _ = x[MSG_MHF_INFO_GUILD-147] + _ = x[MSG_MHF_ENUMERATE_GUILD-148] + _ = x[MSG_MHF_UPDATE_GUILD-149] + _ = x[MSG_MHF_ARRANGE_GUILD_MEMBER-150] + _ = x[MSG_MHF_ENUMERATE_GUILD_MEMBER-151] + _ = x[MSG_MHF_ENUMERATE_CAMPAIGN-152] + _ = x[MSG_MHF_STATE_CAMPAIGN-153] + _ = x[MSG_MHF_APPLY_CAMPAIGN-154] + _ = x[MSG_MHF_ENUMERATE_ITEM-155] + _ = x[MSG_MHF_ACQUIRE_ITEM-156] + _ = x[MSG_MHF_TRANSFER_ITEM-157] + _ = x[MSG_MHF_MERCENARY_HUNTDATA-158] + _ = x[MSG_MHF_ENTRY_ROOKIE_GUILD-159] + _ = x[MSG_MHF_ENUMERATE_QUEST-160] + _ = x[MSG_MHF_ENUMERATE_EVENT-161] + _ = x[MSG_MHF_ENUMERATE_PRICE-162] + _ = x[MSG_MHF_ENUMERATE_RANKING-163] + _ = x[MSG_MHF_ENUMERATE_ORDER-164] + _ = x[MSG_MHF_ENUMERATE_SHOP-165] + _ = x[MSG_MHF_GET_EXTRA_INFO-166] + _ = x[MSG_MHF_UPDATE_INTERIOR-167] + _ = x[MSG_MHF_ENUMERATE_HOUSE-168] + _ = x[MSG_MHF_UPDATE_HOUSE-169] + _ = x[MSG_MHF_LOAD_HOUSE-170] + _ = x[MSG_MHF_OPERATE_WAREHOUSE-171] + _ = x[MSG_MHF_ENUMERATE_WAREHOUSE-172] + _ = x[MSG_MHF_UPDATE_WAREHOUSE-173] + _ = x[MSG_MHF_ACQUIRE_TITLE-174] + _ = x[MSG_MHF_ENUMERATE_TITLE-175] + _ = x[MSG_MHF_ENUMERATE_GUILD_ITEM-176] + _ = x[MSG_MHF_UPDATE_GUILD_ITEM-177] + _ = x[MSG_MHF_ENUMERATE_UNION_ITEM-178] + _ = x[MSG_MHF_UPDATE_UNION_ITEM-179] + _ = x[MSG_MHF_CREATE_JOINT-180] + _ = x[MSG_MHF_OPERATE_JOINT-181] + _ = x[MSG_MHF_INFO_JOINT-182] + _ = x[MSG_MHF_UPDATE_GUILD_ICON-183] + _ = x[MSG_MHF_INFO_FESTA-184] + _ = x[MSG_MHF_ENTRY_FESTA-185] + _ = x[MSG_MHF_CHARGE_FESTA-186] + _ = x[MSG_MHF_ACQUIRE_FESTA-187] + _ = x[MSG_MHF_STATE_FESTA_U-188] + _ = x[MSG_MHF_STATE_FESTA_G-189] + _ = x[MSG_MHF_ENUMERATE_FESTA_MEMBER-190] + _ = x[MSG_MHF_VOTE_FESTA-191] + _ = x[MSG_MHF_ACQUIRE_CAFE_ITEM-192] + _ = x[MSG_MHF_UPDATE_CAFEPOINT-193] + _ = x[MSG_MHF_CHECK_DAILY_CAFEPOINT-194] + _ = x[MSG_MHF_GET_COG_INFO-195] + _ = x[MSG_MHF_CHECK_MONTHLY_ITEM-196] + _ = x[MSG_MHF_ACQUIRE_MONTHLY_ITEM-197] + _ = x[MSG_MHF_CHECK_WEEKLY_STAMP-198] + _ = x[MSG_MHF_EXCHANGE_WEEKLY_STAMP-199] + _ = x[MSG_MHF_CREATE_MERCENARY-200] + _ = x[MSG_MHF_SAVE_MERCENARY-201] + _ = x[MSG_MHF_READ_MERCENARY_W-202] + _ = x[MSG_MHF_READ_MERCENARY_M-203] + _ = x[MSG_MHF_CONTRACT_MERCENARY-204] + _ = x[MSG_MHF_ENUMERATE_MERCENARY_LOG-205] + _ = x[MSG_MHF_ENUMERATE_GUACOT-206] + _ = x[MSG_MHF_UPDATE_GUACOT-207] + _ = x[MSG_MHF_INFO_TOURNAMENT-208] + _ = x[MSG_MHF_ENTRY_TOURNAMENT-209] + _ = x[MSG_MHF_ENTER_TOURNAMENT_QUEST-210] + _ = x[MSG_MHF_ACQUIRE_TOURNAMENT-211] + _ = x[MSG_MHF_GET_ACHIEVEMENT-212] + _ = x[MSG_MHF_RESET_ACHIEVEMENT-213] + _ = x[MSG_MHF_ADD_ACHIEVEMENT-214] + _ = x[MSG_MHF_PAYMENT_ACHIEVEMENT-215] + _ = x[MSG_MHF_DISPLAYED_ACHIEVEMENT-216] + _ = x[MSG_MHF_INFO_SCENARIO_COUNTER-217] + _ = x[MSG_MHF_SAVE_SCENARIO_DATA-218] + _ = x[MSG_MHF_LOAD_SCENARIO_DATA-219] + _ = x[MSG_MHF_GET_BBS_SNS_STATUS-220] + _ = x[MSG_MHF_APPLY_BBS_ARTICLE-221] + _ = x[MSG_MHF_GET_ETC_POINTS-222] + _ = x[MSG_MHF_UPDATE_ETC_POINT-223] + _ = x[MSG_MHF_GET_MYHOUSE_INFO-224] + _ = x[MSG_MHF_UPDATE_MYHOUSE_INFO-225] + _ = x[MSG_MHF_GET_WEEKLY_SCHEDULE-226] + _ = x[MSG_MHF_ENUMERATE_INV_GUILD-227] + _ = x[MSG_MHF_OPERATION_INV_GUILD-228] + _ = x[MSG_MHF_STAMPCARD_STAMP-229] + _ = x[MSG_MHF_STAMPCARD_PRIZE-230] + _ = x[MSG_MHF_UNRESERVE_SRG-231] + _ = x[MSG_MHF_LOAD_PLATE_DATA-232] + _ = x[MSG_MHF_SAVE_PLATE_DATA-233] + _ = x[MSG_MHF_LOAD_PLATE_BOX-234] + _ = x[MSG_MHF_SAVE_PLATE_BOX-235] + _ = x[MSG_MHF_READ_GUILDCARD-236] + _ = x[MSG_MHF_UPDATE_GUILDCARD-237] + _ = x[MSG_MHF_READ_BEAT_LEVEL-238] + _ = x[MSG_MHF_UPDATE_BEAT_LEVEL-239] + _ = x[MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING-240] + _ = x[MSG_MHF_READ_BEAT_LEVEL_MY_RANKING-241] + _ = x[MSG_MHF_READ_LAST_WEEK_BEAT_RANKING-242] + _ = x[MSG_MHF_ACCEPT_READ_REWARD-243] + _ = x[MSG_MHF_GET_ADDITIONAL_BEAT_REWARD-244] + _ = x[MSG_MHF_GET_FIXED_SEIBATU_RANKING_TABLE-245] + _ = x[MSG_MHF_GET_BBS_USER_STATUS-246] + _ = x[MSG_MHF_KICK_EXPORT_FORCE-247] + _ = x[MSG_MHF_GET_BREAK_SEIBATU_LEVEL_REWARD-248] + _ = x[MSG_MHF_GET_WEEKLY_SEIBATU_RANKING_REWARD-249] + _ = x[MSG_MHF_GET_EARTH_STATUS-250] + _ = x[MSG_MHF_LOAD_PARTNER-251] + _ = x[MSG_MHF_SAVE_PARTNER-252] + _ = x[MSG_MHF_GET_GUILD_MISSION_LIST-253] + _ = x[MSG_MHF_GET_GUILD_MISSION_RECORD-254] + _ = x[MSG_MHF_ADD_GUILD_MISSION_COUNT-255] + _ = x[MSG_MHF_SET_GUILD_MISSION_TARGET-256] + _ = x[MSG_MHF_CANCEL_GUILD_MISSION_TARGET-257] + _ = x[MSG_MHF_LOAD_OTOMO_AIROU-258] + _ = x[MSG_MHF_SAVE_OTOMO_AIROU-259] + _ = x[MSG_MHF_ENUMERATE_GUILD_TRESURE-260] + _ = x[MSG_MHF_ENUMERATE_AIROULIST-261] + _ = x[MSG_MHF_REGIST_GUILD_TRESURE-262] + _ = x[MSG_MHF_ACQUIRE_GUILD_TRESURE-263] + _ = x[MSG_MHF_OPERATE_GUILD_TRESURE_REPORT-264] + _ = x[MSG_MHF_GET_GUILD_TRESURE_SOUVENIR-265] + _ = x[MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR-266] + _ = x[MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE-267] + _ = x[MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE-268] + _ = x[MSG_MHF_LOAD_DECO_MYSET-269] + _ = x[MSG_MHF_SAVE_DECO_MYSET-270] + _ = x[MSG_MHF_reserve010F-271] + _ = x[MSG_MHF_LOAD_GUILD_COOKING-272] + _ = x[MSG_MHF_REGIST_GUILD_COOKING-273] + _ = x[MSG_MHF_LOAD_GUILD_ADVENTURE-274] + _ = x[MSG_MHF_REGIST_GUILD_ADVENTURE-275] + _ = x[MSG_MHF_ACQUIRE_GUILD_ADVENTURE-276] + _ = x[MSG_MHF_CHARGE_GUILD_ADVENTURE-277] + _ = x[MSG_MHF_LOAD_LEGEND_DISPATCH-278] + _ = x[MSG_MHF_LOAD_HUNTER_NAVI-279] + _ = x[MSG_MHF_SAVE_HUNTER_NAVI-280] + _ = x[MSG_MHF_REGIST_SPABI_TIME-281] + _ = x[MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER-282] + _ = x[MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT-283] + _ = x[MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER-284] + _ = x[MSG_MHF_GET_TOWER_INFO-285] + _ = x[MSG_MHF_POST_TOWER_INFO-286] + _ = x[MSG_MHF_GET_GEM_INFO-287] + _ = x[MSG_MHF_POST_GEM_INFO-288] + _ = x[MSG_MHF_GET_EARTH_VALUE-289] + _ = x[MSG_MHF_DEBUG_POST_VALUE-290] + _ = x[MSG_MHF_GET_PAPER_DATA-291] + _ = x[MSG_MHF_GET_NOTICE-292] + _ = x[MSG_MHF_POST_NOTICE-293] + _ = x[MSG_MHF_GET_BOOST_TIME-294] + _ = x[MSG_MHF_POST_BOOST_TIME-295] + _ = x[MSG_MHF_GET_BOOST_TIME_LIMIT-296] + _ = x[MSG_MHF_POST_BOOST_TIME_LIMIT-297] + _ = x[MSG_MHF_ENUMERATE_FESTA_PERSONAL_PRIZE-298] + _ = x[MSG_MHF_ACQUIRE_FESTA_PERSONAL_PRIZE-299] + _ = x[MSG_MHF_GET_RAND_FROM_TABLE-300] + _ = x[MSG_MHF_GET_CAFE_DURATION-301] + _ = x[MSG_MHF_GET_CAFE_DURATION_BONUS_INFO-302] + _ = x[MSG_MHF_RECEIVE_CAFE_DURATION_BONUS-303] + _ = x[MSG_MHF_POST_CAFE_DURATION_BONUS_RECEIVED-304] + _ = x[MSG_MHF_GET_GACHA_POINT-305] + _ = x[MSG_MHF_USE_GACHA_POINT-306] + _ = x[MSG_MHF_EXCHANGE_FPOINT_2_ITEM-307] + _ = x[MSG_MHF_EXCHANGE_ITEM_2_FPOINT-308] + _ = x[MSG_MHF_GET_FPOINT_EXCHANGE_LIST-309] + _ = x[MSG_MHF_PLAY_STEPUP_GACHA-310] + _ = x[MSG_MHF_RECEIVE_GACHA_ITEM-311] + _ = x[MSG_MHF_GET_STEPUP_STATUS-312] + _ = x[MSG_MHF_PLAY_FREE_GACHA-313] + _ = x[MSG_MHF_GET_TINY_BIN-314] + _ = x[MSG_MHF_POST_TINY_BIN-315] + _ = x[MSG_MHF_GET_SENYU_DAILY_COUNT-316] + _ = x[MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM-317] + _ = x[MSG_MHF_GET_BOOST_RIGHT-318] + _ = x[MSG_MHF_START_BOOST_TIME-319] + _ = x[MSG_MHF_POST_BOOST_TIME_QUEST_RETURN-320] + _ = x[MSG_MHF_GET_BOX_GACHA_INFO-321] + _ = x[MSG_MHF_PLAY_BOX_GACHA-322] + _ = x[MSG_MHF_RESET_BOX_GACHA_INFO-323] + _ = x[MSG_MHF_GET_SEIBATTLE-324] + _ = x[MSG_MHF_POST_SEIBATTLE-325] + _ = x[MSG_MHF_GET_RYOUDAMA-326] + _ = x[MSG_MHF_POST_RYOUDAMA-327] + _ = x[MSG_MHF_GET_TENROUIRAI-328] + _ = x[MSG_MHF_POST_TENROUIRAI-329] + _ = x[MSG_MHF_POST_GUILD_SCOUT-330] + _ = x[MSG_MHF_CANCEL_GUILD_SCOUT-331] + _ = x[MSG_MHF_ANSWER_GUILD_SCOUT-332] + _ = x[MSG_MHF_GET_GUILD_SCOUT_LIST-333] + _ = x[MSG_MHF_GET_GUILD_MANAGE_RIGHT-334] + _ = x[MSG_MHF_SET_GUILD_MANAGE_RIGHT-335] + _ = x[MSG_MHF_PLAY_NORMAL_GACHA-336] + _ = x[MSG_MHF_GET_DAILY_MISSION_MASTER-337] + _ = x[MSG_MHF_GET_DAILY_MISSION_PERSONAL-338] + _ = x[MSG_MHF_SET_DAILY_MISSION_PERSONAL-339] + _ = x[MSG_MHF_GET_GACHA_PLAY_HISTORY-340] + _ = x[MSG_MHF_GET_REJECT_GUILD_SCOUT-341] + _ = x[MSG_MHF_SET_REJECT_GUILD_SCOUT-342] + _ = x[MSG_MHF_GET_CA_ACHIEVEMENT_HIST-343] + _ = x[MSG_MHF_SET_CA_ACHIEVEMENT_HIST-344] + _ = x[MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS-345] + _ = x[MSG_MHF_USE_KEEP_LOGIN_BOOST-346] + _ = x[MSG_MHF_GET_UD_SCHEDULE-347] + _ = x[MSG_MHF_GET_UD_INFO-348] + _ = x[MSG_MHF_GET_KIJU_INFO-349] + _ = x[MSG_MHF_SET_KIJU-350] + _ = x[MSG_MHF_ADD_UD_POINT-351] + _ = x[MSG_MHF_GET_UD_MY_POINT-352] + _ = x[MSG_MHF_GET_UD_TOTAL_POINT_INFO-353] + _ = x[MSG_MHF_GET_UD_BONUS_QUEST_INFO-354] + _ = x[MSG_MHF_GET_UD_SELECTED_COLOR_INFO-355] + _ = x[MSG_MHF_GET_UD_MONSTER_POINT-356] + _ = x[MSG_MHF_GET_UD_DAILY_PRESENT_LIST-357] + _ = x[MSG_MHF_GET_UD_NORMA_PRESENT_LIST-358] + _ = x[MSG_MHF_GET_UD_RANKING_REWARD_LIST-359] + _ = x[MSG_MHF_ACQUIRE_UD_ITEM-360] + _ = x[MSG_MHF_GET_REWARD_SONG-361] + _ = x[MSG_MHF_USE_REWARD_SONG-362] + _ = x[MSG_MHF_ADD_REWARD_SONG_COUNT-363] + _ = x[MSG_MHF_GET_UD_RANKING-364] + _ = x[MSG_MHF_GET_UD_MY_RANKING-365] + _ = x[MSG_MHF_ACQUIRE_MONTHLY_REWARD-366] + _ = x[MSG_MHF_GET_UD_GUILD_MAP_INFO-367] + _ = x[MSG_MHF_GENERATE_UD_GUILD_MAP-368] + _ = x[MSG_MHF_GET_UD_TACTICS_POINT-369] + _ = x[MSG_MHF_ADD_UD_TACTICS_POINT-370] + _ = x[MSG_MHF_GET_UD_TACTICS_RANKING-371] + _ = x[MSG_MHF_GET_UD_TACTICS_REWARD_LIST-372] + _ = x[MSG_MHF_GET_UD_TACTICS_LOG-373] + _ = x[MSG_MHF_GET_EQUIP_SKIN_HIST-374] + _ = x[MSG_MHF_UPDATE_EQUIP_SKIN_HIST-375] + _ = x[MSG_MHF_GET_UD_TACTICS_FOLLOWER-376] + _ = x[MSG_MHF_SET_UD_TACTICS_FOLLOWER-377] + _ = x[MSG_MHF_GET_UD_SHOP_COIN-378] + _ = x[MSG_MHF_USE_UD_SHOP_COIN-379] + _ = x[MSG_MHF_GET_ENHANCED_MINIDATA-380] + _ = x[MSG_MHF_SET_ENHANCED_MINIDATA-381] + _ = x[MSG_MHF_SEX_CHANGER-382] + _ = x[MSG_MHF_GET_LOBBY_CROWD-383] + _ = x[MSG_SYS_reserve180-384] + _ = x[MSG_MHF_GUILD_HUNTDATA-385] + _ = x[MSG_MHF_ADD_KOURYOU_POINT-386] + _ = x[MSG_MHF_GET_KOURYOU_POINT-387] + _ = x[MSG_MHF_EXCHANGE_KOURYOU_POINT-388] + _ = x[MSG_MHF_GET_UD_TACTICS_BONUS_QUEST-389] + _ = x[MSG_MHF_GET_UD_TACTICS_FIRST_QUEST_BONUS-390] + _ = x[MSG_MHF_GET_UD_TACTICS_REMAINING_POINT-391] + _ = x[MSG_SYS_reserve188-392] + _ = x[MSG_MHF_LOAD_PLATE_MYSET-393] + _ = x[MSG_MHF_SAVE_PLATE_MYSET-394] + _ = x[MSG_SYS_reserve18B-395] + _ = x[MSG_MHF_GET_RESTRICTION_EVENT-396] + _ = x[MSG_MHF_SET_RESTRICTION_EVENT-397] + _ = x[MSG_SYS_reserve18E-398] + _ = x[MSG_SYS_reserve18F-399] + _ = x[MSG_MHF_GET_TREND_WEAPON-400] + _ = x[MSG_MHF_UPDATE_USE_TREND_WEAPON_LOG-401] + _ = x[MSG_SYS_reserve192-402] + _ = x[MSG_SYS_reserve193-403] + _ = x[MSG_SYS_reserve194-404] + _ = x[MSG_MHF_SAVE_RENGOKU_DATA-405] + _ = x[MSG_MHF_LOAD_RENGOKU_DATA-406] + _ = x[MSG_MHF_GET_RENGOKU_BINARY-407] + _ = x[MSG_MHF_ENUMERATE_RENGOKU_RANKING-408] + _ = x[MSG_MHF_GET_RENGOKU_RANKING_RANK-409] + _ = x[MSG_MHF_ACQUIRE_EXCHANGE_SHOP-410] + _ = x[MSG_SYS_reserve19B-411] + _ = x[MSG_MHF_SAVE_MEZFES_DATA-412] + _ = x[MSG_MHF_LOAD_MEZFES_DATA-413] + _ = x[MSG_SYS_reserve19E-414] + _ = x[MSG_SYS_reserve19F-415] + _ = x[MSG_MHF_UPDATE_FORCE_GUILD_RANK-416] + _ = x[MSG_MHF_RESET_TITLE-417] + _ = x[MSG_SYS_reserve202-418] + _ = x[MSG_SYS_reserve203-419] + _ = x[MSG_SYS_reserve204-420] + _ = x[MSG_SYS_reserve205-421] + _ = x[MSG_SYS_reserve206-422] + _ = x[MSG_SYS_reserve207-423] + _ = x[MSG_SYS_reserve208-424] + _ = x[MSG_SYS_reserve209-425] + _ = x[MSG_SYS_reserve20A-426] + _ = x[MSG_SYS_reserve20B-427] + _ = x[MSG_SYS_reserve20C-428] + _ = x[MSG_SYS_reserve20D-429] + _ = x[MSG_SYS_reserve20E-430] + _ = x[MSG_SYS_reserve20F-431] +} + +const _PacketID_name = "MSG_HEADMSG_SYS_reserve01MSG_SYS_reserve02MSG_SYS_reserve03MSG_SYS_reserve04MSG_SYS_reserve05MSG_SYS_reserve06MSG_SYS_reserve07MSG_SYS_ADD_OBJECTMSG_SYS_DEL_OBJECTMSG_SYS_DISP_OBJECTMSG_SYS_HIDE_OBJECTMSG_SYS_reserve0CMSG_SYS_reserve0DMSG_SYS_reserve0EMSG_SYS_EXTEND_THRESHOLDMSG_SYS_ENDMSG_SYS_NOPMSG_SYS_ACKMSG_SYS_TERMINAL_LOGMSG_SYS_LOGINMSG_SYS_LOGOUTMSG_SYS_SET_STATUSMSG_SYS_PINGMSG_SYS_CAST_BINARYMSG_SYS_HIDE_CLIENTMSG_SYS_TIMEMSG_SYS_CASTED_BINARYMSG_SYS_GET_FILEMSG_SYS_ISSUE_LOGKEYMSG_SYS_RECORD_LOGMSG_SYS_ECHOMSG_SYS_CREATE_STAGEMSG_SYS_STAGE_DESTRUCTMSG_SYS_ENTER_STAGEMSG_SYS_BACK_STAGEMSG_SYS_MOVE_STAGEMSG_SYS_LEAVE_STAGEMSG_SYS_LOCK_STAGEMSG_SYS_UNLOCK_STAGEMSG_SYS_RESERVE_STAGEMSG_SYS_UNRESERVE_STAGEMSG_SYS_SET_STAGE_PASSMSG_SYS_WAIT_STAGE_BINARYMSG_SYS_SET_STAGE_BINARYMSG_SYS_GET_STAGE_BINARYMSG_SYS_ENUMERATE_CLIENTMSG_SYS_ENUMERATE_STAGEMSG_SYS_CREATE_MUTEXMSG_SYS_CREATE_OPEN_MUTEXMSG_SYS_DELETE_MUTEXMSG_SYS_OPEN_MUTEXMSG_SYS_CLOSE_MUTEXMSG_SYS_CREATE_SEMAPHOREMSG_SYS_CREATE_ACQUIRE_SEMAPHOREMSG_SYS_DELETE_SEMAPHOREMSG_SYS_ACQUIRE_SEMAPHOREMSG_SYS_RELEASE_SEMAPHOREMSG_SYS_LOCK_GLOBAL_SEMAMSG_SYS_UNLOCK_GLOBAL_SEMAMSG_SYS_CHECK_SEMAPHOREMSG_SYS_OPERATE_REGISTERMSG_SYS_LOAD_REGISTERMSG_SYS_NOTIFY_REGISTERMSG_SYS_CREATE_OBJECTMSG_SYS_DELETE_OBJECTMSG_SYS_POSITION_OBJECTMSG_SYS_ROTATE_OBJECTMSG_SYS_DUPLICATE_OBJECTMSG_SYS_SET_OBJECT_BINARYMSG_SYS_GET_OBJECT_BINARYMSG_SYS_GET_OBJECT_OWNERMSG_SYS_UPDATE_OBJECT_BINARYMSG_SYS_CLEANUP_OBJECTMSG_SYS_reserve4AMSG_SYS_reserve4BMSG_SYS_reserve4CMSG_SYS_reserve4DMSG_SYS_reserve4EMSG_SYS_reserve4FMSG_SYS_INSERT_USERMSG_SYS_DELETE_USERMSG_SYS_SET_USER_BINARYMSG_SYS_GET_USER_BINARYMSG_SYS_NOTIFY_USER_BINARYMSG_SYS_reserve55MSG_SYS_reserve56MSG_SYS_reserve57MSG_SYS_UPDATE_RIGHTMSG_SYS_AUTH_QUERYMSG_SYS_AUTH_DATAMSG_SYS_AUTH_TERMINALMSG_SYS_reserve5CMSG_SYS_RIGHTS_RELOADMSG_SYS_reserve5EMSG_SYS_reserve5FMSG_MHF_SAVEDATAMSG_MHF_LOADDATAMSG_MHF_LIST_MEMBERMSG_MHF_OPR_MEMBERMSG_MHF_ENUMERATE_DIST_ITEMMSG_MHF_APPLY_DIST_ITEMMSG_MHF_ACQUIRE_DIST_ITEMMSG_MHF_GET_DIST_DESCRIPTIONMSG_MHF_SEND_MAILMSG_MHF_READ_MAILMSG_MHF_LIST_MAILMSG_MHF_OPRT_MAILMSG_MHF_LOAD_FAVORITE_QUESTMSG_MHF_SAVE_FAVORITE_QUESTMSG_MHF_REGISTER_EVENTMSG_MHF_RELEASE_EVENTMSG_MHF_TRANSIT_MESSAGEMSG_SYS_reserve71MSG_SYS_reserve72MSG_SYS_reserve73MSG_SYS_reserve74MSG_SYS_reserve75MSG_SYS_reserve76MSG_SYS_reserve77MSG_SYS_reserve78MSG_SYS_reserve79MSG_SYS_reserve7AMSG_SYS_reserve7BMSG_SYS_reserve7CMSG_CA_EXCHANGE_ITEMMSG_SYS_reserve7EMSG_MHF_PRESENT_BOXMSG_MHF_SERVER_COMMANDMSG_MHF_SHUT_CLIENTMSG_MHF_ANNOUNCEMSG_MHF_SET_LOGINWINDOWMSG_SYS_TRANS_BINARYMSG_SYS_COLLECT_BINARYMSG_SYS_GET_STATEMSG_SYS_SERIALIZEMSG_SYS_ENUMLOBBYMSG_SYS_ENUMUSERMSG_SYS_INFOKYSERVERMSG_MHF_GET_CA_UNIQUE_IDMSG_MHF_SET_CA_ACHIEVEMENTMSG_MHF_CARAVAN_MY_SCOREMSG_MHF_CARAVAN_RANKINGMSG_MHF_CARAVAN_MY_RANKMSG_MHF_CREATE_GUILDMSG_MHF_OPERATE_GUILDMSG_MHF_OPERATE_GUILD_MEMBERMSG_MHF_INFO_GUILDMSG_MHF_ENUMERATE_GUILDMSG_MHF_UPDATE_GUILDMSG_MHF_ARRANGE_GUILD_MEMBERMSG_MHF_ENUMERATE_GUILD_MEMBERMSG_MHF_ENUMERATE_CAMPAIGNMSG_MHF_STATE_CAMPAIGNMSG_MHF_APPLY_CAMPAIGNMSG_MHF_ENUMERATE_ITEMMSG_MHF_ACQUIRE_ITEMMSG_MHF_TRANSFER_ITEMMSG_MHF_MERCENARY_HUNTDATAMSG_MHF_ENTRY_ROOKIE_GUILDMSG_MHF_ENUMERATE_QUESTMSG_MHF_ENUMERATE_EVENTMSG_MHF_ENUMERATE_PRICEMSG_MHF_ENUMERATE_RANKINGMSG_MHF_ENUMERATE_ORDERMSG_MHF_ENUMERATE_SHOPMSG_MHF_GET_EXTRA_INFOMSG_MHF_UPDATE_INTERIORMSG_MHF_ENUMERATE_HOUSEMSG_MHF_UPDATE_HOUSEMSG_MHF_LOAD_HOUSEMSG_MHF_OPERATE_WAREHOUSEMSG_MHF_ENUMERATE_WAREHOUSEMSG_MHF_UPDATE_WAREHOUSEMSG_MHF_ACQUIRE_TITLEMSG_MHF_ENUMERATE_TITLEMSG_MHF_ENUMERATE_GUILD_ITEMMSG_MHF_UPDATE_GUILD_ITEMMSG_MHF_ENUMERATE_UNION_ITEMMSG_MHF_UPDATE_UNION_ITEMMSG_MHF_CREATE_JOINTMSG_MHF_OPERATE_JOINTMSG_MHF_INFO_JOINTMSG_MHF_UPDATE_GUILD_ICONMSG_MHF_INFO_FESTAMSG_MHF_ENTRY_FESTAMSG_MHF_CHARGE_FESTAMSG_MHF_ACQUIRE_FESTAMSG_MHF_STATE_FESTA_UMSG_MHF_STATE_FESTA_GMSG_MHF_ENUMERATE_FESTA_MEMBERMSG_MHF_VOTE_FESTAMSG_MHF_ACQUIRE_CAFE_ITEMMSG_MHF_UPDATE_CAFEPOINTMSG_MHF_CHECK_DAILY_CAFEPOINTMSG_MHF_GET_COG_INFOMSG_MHF_CHECK_MONTHLY_ITEMMSG_MHF_ACQUIRE_MONTHLY_ITEMMSG_MHF_CHECK_WEEKLY_STAMPMSG_MHF_EXCHANGE_WEEKLY_STAMPMSG_MHF_CREATE_MERCENARYMSG_MHF_SAVE_MERCENARYMSG_MHF_READ_MERCENARY_WMSG_MHF_READ_MERCENARY_MMSG_MHF_CONTRACT_MERCENARYMSG_MHF_ENUMERATE_MERCENARY_LOGMSG_MHF_ENUMERATE_GUACOTMSG_MHF_UPDATE_GUACOTMSG_MHF_INFO_TOURNAMENTMSG_MHF_ENTRY_TOURNAMENTMSG_MHF_ENTER_TOURNAMENT_QUESTMSG_MHF_ACQUIRE_TOURNAMENTMSG_MHF_GET_ACHIEVEMENTMSG_MHF_RESET_ACHIEVEMENTMSG_MHF_ADD_ACHIEVEMENTMSG_MHF_PAYMENT_ACHIEVEMENTMSG_MHF_DISPLAYED_ACHIEVEMENTMSG_MHF_INFO_SCENARIO_COUNTERMSG_MHF_SAVE_SCENARIO_DATAMSG_MHF_LOAD_SCENARIO_DATAMSG_MHF_GET_BBS_SNS_STATUSMSG_MHF_APPLY_BBS_ARTICLEMSG_MHF_GET_ETC_POINTSMSG_MHF_UPDATE_ETC_POINTMSG_MHF_GET_MYHOUSE_INFOMSG_MHF_UPDATE_MYHOUSE_INFOMSG_MHF_GET_WEEKLY_SCHEDULEMSG_MHF_ENUMERATE_INV_GUILDMSG_MHF_OPERATION_INV_GUILDMSG_MHF_STAMPCARD_STAMPMSG_MHF_STAMPCARD_PRIZEMSG_MHF_UNRESERVE_SRGMSG_MHF_LOAD_PLATE_DATAMSG_MHF_SAVE_PLATE_DATAMSG_MHF_LOAD_PLATE_BOXMSG_MHF_SAVE_PLATE_BOXMSG_MHF_READ_GUILDCARDMSG_MHF_UPDATE_GUILDCARDMSG_MHF_READ_BEAT_LEVELMSG_MHF_UPDATE_BEAT_LEVELMSG_MHF_READ_BEAT_LEVEL_ALL_RANKINGMSG_MHF_READ_BEAT_LEVEL_MY_RANKINGMSG_MHF_READ_LAST_WEEK_BEAT_RANKINGMSG_MHF_ACCEPT_READ_REWARDMSG_MHF_GET_ADDITIONAL_BEAT_REWARDMSG_MHF_GET_FIXED_SEIBATU_RANKING_TABLEMSG_MHF_GET_BBS_USER_STATUSMSG_MHF_KICK_EXPORT_FORCEMSG_MHF_GET_BREAK_SEIBATU_LEVEL_REWARDMSG_MHF_GET_WEEKLY_SEIBATU_RANKING_REWARDMSG_MHF_GET_EARTH_STATUSMSG_MHF_LOAD_PARTNERMSG_MHF_SAVE_PARTNERMSG_MHF_GET_GUILD_MISSION_LISTMSG_MHF_GET_GUILD_MISSION_RECORDMSG_MHF_ADD_GUILD_MISSION_COUNTMSG_MHF_SET_GUILD_MISSION_TARGETMSG_MHF_CANCEL_GUILD_MISSION_TARGETMSG_MHF_LOAD_OTOMO_AIROUMSG_MHF_SAVE_OTOMO_AIROUMSG_MHF_ENUMERATE_GUILD_TRESUREMSG_MHF_ENUMERATE_AIROULISTMSG_MHF_REGIST_GUILD_TRESUREMSG_MHF_ACQUIRE_GUILD_TRESUREMSG_MHF_OPERATE_GUILD_TRESURE_REPORTMSG_MHF_GET_GUILD_TRESURE_SOUVENIRMSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIRMSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZEMSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZEMSG_MHF_LOAD_DECO_MYSETMSG_MHF_SAVE_DECO_MYSETMSG_MHF_reserve010FMSG_MHF_LOAD_GUILD_COOKINGMSG_MHF_REGIST_GUILD_COOKINGMSG_MHF_LOAD_GUILD_ADVENTUREMSG_MHF_REGIST_GUILD_ADVENTUREMSG_MHF_ACQUIRE_GUILD_ADVENTUREMSG_MHF_CHARGE_GUILD_ADVENTUREMSG_MHF_LOAD_LEGEND_DISPATCHMSG_MHF_LOAD_HUNTER_NAVIMSG_MHF_SAVE_HUNTER_NAVIMSG_MHF_REGIST_SPABI_TIMEMSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTERMSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNTMSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USERMSG_MHF_GET_TOWER_INFOMSG_MHF_POST_TOWER_INFOMSG_MHF_GET_GEM_INFOMSG_MHF_POST_GEM_INFOMSG_MHF_GET_EARTH_VALUEMSG_MHF_DEBUG_POST_VALUEMSG_MHF_GET_PAPER_DATAMSG_MHF_GET_NOTICEMSG_MHF_POST_NOTICEMSG_MHF_GET_BOOST_TIMEMSG_MHF_POST_BOOST_TIMEMSG_MHF_GET_BOOST_TIME_LIMITMSG_MHF_POST_BOOST_TIME_LIMITMSG_MHF_ENUMERATE_FESTA_PERSONAL_PRIZEMSG_MHF_ACQUIRE_FESTA_PERSONAL_PRIZEMSG_MHF_GET_RAND_FROM_TABLEMSG_MHF_GET_CAFE_DURATIONMSG_MHF_GET_CAFE_DURATION_BONUS_INFOMSG_MHF_RECEIVE_CAFE_DURATION_BONUSMSG_MHF_POST_CAFE_DURATION_BONUS_RECEIVEDMSG_MHF_GET_GACHA_POINTMSG_MHF_USE_GACHA_POINTMSG_MHF_EXCHANGE_FPOINT_2_ITEMMSG_MHF_EXCHANGE_ITEM_2_FPOINTMSG_MHF_GET_FPOINT_EXCHANGE_LISTMSG_MHF_PLAY_STEPUP_GACHAMSG_MHF_RECEIVE_GACHA_ITEMMSG_MHF_GET_STEPUP_STATUSMSG_MHF_PLAY_FREE_GACHAMSG_MHF_GET_TINY_BINMSG_MHF_POST_TINY_BINMSG_MHF_GET_SENYU_DAILY_COUNTMSG_MHF_GET_GUILD_TARGET_MEMBER_NUMMSG_MHF_GET_BOOST_RIGHTMSG_MHF_START_BOOST_TIMEMSG_MHF_POST_BOOST_TIME_QUEST_RETURNMSG_MHF_GET_BOX_GACHA_INFOMSG_MHF_PLAY_BOX_GACHAMSG_MHF_RESET_BOX_GACHA_INFOMSG_MHF_GET_SEIBATTLEMSG_MHF_POST_SEIBATTLEMSG_MHF_GET_RYOUDAMAMSG_MHF_POST_RYOUDAMAMSG_MHF_GET_TENROUIRAIMSG_MHF_POST_TENROUIRAIMSG_MHF_POST_GUILD_SCOUTMSG_MHF_CANCEL_GUILD_SCOUTMSG_MHF_ANSWER_GUILD_SCOUTMSG_MHF_GET_GUILD_SCOUT_LISTMSG_MHF_GET_GUILD_MANAGE_RIGHTMSG_MHF_SET_GUILD_MANAGE_RIGHTMSG_MHF_PLAY_NORMAL_GACHAMSG_MHF_GET_DAILY_MISSION_MASTERMSG_MHF_GET_DAILY_MISSION_PERSONALMSG_MHF_SET_DAILY_MISSION_PERSONALMSG_MHF_GET_GACHA_PLAY_HISTORYMSG_MHF_GET_REJECT_GUILD_SCOUTMSG_MHF_SET_REJECT_GUILD_SCOUTMSG_MHF_GET_CA_ACHIEVEMENT_HISTMSG_MHF_SET_CA_ACHIEVEMENT_HISTMSG_MHF_GET_KEEP_LOGIN_BOOST_STATUSMSG_MHF_USE_KEEP_LOGIN_BOOSTMSG_MHF_GET_UD_SCHEDULEMSG_MHF_GET_UD_INFOMSG_MHF_GET_KIJU_INFOMSG_MHF_SET_KIJUMSG_MHF_ADD_UD_POINTMSG_MHF_GET_UD_MY_POINTMSG_MHF_GET_UD_TOTAL_POINT_INFOMSG_MHF_GET_UD_BONUS_QUEST_INFOMSG_MHF_GET_UD_SELECTED_COLOR_INFOMSG_MHF_GET_UD_MONSTER_POINTMSG_MHF_GET_UD_DAILY_PRESENT_LISTMSG_MHF_GET_UD_NORMA_PRESENT_LISTMSG_MHF_GET_UD_RANKING_REWARD_LISTMSG_MHF_ACQUIRE_UD_ITEMMSG_MHF_GET_REWARD_SONGMSG_MHF_USE_REWARD_SONGMSG_MHF_ADD_REWARD_SONG_COUNTMSG_MHF_GET_UD_RANKINGMSG_MHF_GET_UD_MY_RANKINGMSG_MHF_ACQUIRE_MONTHLY_REWARDMSG_MHF_GET_UD_GUILD_MAP_INFOMSG_MHF_GENERATE_UD_GUILD_MAPMSG_MHF_GET_UD_TACTICS_POINTMSG_MHF_ADD_UD_TACTICS_POINTMSG_MHF_GET_UD_TACTICS_RANKINGMSG_MHF_GET_UD_TACTICS_REWARD_LISTMSG_MHF_GET_UD_TACTICS_LOGMSG_MHF_GET_EQUIP_SKIN_HISTMSG_MHF_UPDATE_EQUIP_SKIN_HISTMSG_MHF_GET_UD_TACTICS_FOLLOWERMSG_MHF_SET_UD_TACTICS_FOLLOWERMSG_MHF_GET_UD_SHOP_COINMSG_MHF_USE_UD_SHOP_COINMSG_MHF_GET_ENHANCED_MINIDATAMSG_MHF_SET_ENHANCED_MINIDATAMSG_MHF_SEX_CHANGERMSG_MHF_GET_LOBBY_CROWDMSG_SYS_reserve180MSG_MHF_GUILD_HUNTDATAMSG_MHF_ADD_KOURYOU_POINTMSG_MHF_GET_KOURYOU_POINTMSG_MHF_EXCHANGE_KOURYOU_POINTMSG_MHF_GET_UD_TACTICS_BONUS_QUESTMSG_MHF_GET_UD_TACTICS_FIRST_QUEST_BONUSMSG_MHF_GET_UD_TACTICS_REMAINING_POINTMSG_SYS_reserve188MSG_MHF_LOAD_PLATE_MYSETMSG_MHF_SAVE_PLATE_MYSETMSG_SYS_reserve18BMSG_MHF_GET_RESTRICTION_EVENTMSG_MHF_SET_RESTRICTION_EVENTMSG_SYS_reserve18EMSG_SYS_reserve18FMSG_MHF_GET_TREND_WEAPONMSG_MHF_UPDATE_USE_TREND_WEAPON_LOGMSG_SYS_reserve192MSG_SYS_reserve193MSG_SYS_reserve194MSG_MHF_SAVE_RENGOKU_DATAMSG_MHF_LOAD_RENGOKU_DATAMSG_MHF_GET_RENGOKU_BINARYMSG_MHF_ENUMERATE_RENGOKU_RANKINGMSG_MHF_GET_RENGOKU_RANKING_RANKMSG_MHF_ACQUIRE_EXCHANGE_SHOPMSG_SYS_reserve19BMSG_MHF_SAVE_MEZFES_DATAMSG_MHF_LOAD_MEZFES_DATAMSG_SYS_reserve19EMSG_SYS_reserve19FMSG_MHF_UPDATE_FORCE_GUILD_RANKMSG_MHF_RESET_TITLEMSG_SYS_reserve202MSG_SYS_reserve203MSG_SYS_reserve204MSG_SYS_reserve205MSG_SYS_reserve206MSG_SYS_reserve207MSG_SYS_reserve208MSG_SYS_reserve209MSG_SYS_reserve20AMSG_SYS_reserve20BMSG_SYS_reserve20CMSG_SYS_reserve20DMSG_SYS_reserve20EMSG_SYS_reserve20F" + +var _PacketID_index = [...]uint16{0, 8, 25, 42, 59, 76, 93, 110, 127, 145, 163, 182, 201, 218, 235, 252, 276, 287, 298, 309, 329, 342, 356, 374, 386, 405, 424, 436, 457, 473, 493, 511, 523, 543, 565, 584, 602, 620, 639, 657, 677, 698, 721, 743, 768, 792, 816, 840, 863, 883, 908, 928, 946, 965, 989, 1021, 1045, 1070, 1095, 1119, 1145, 1168, 1192, 1213, 1236, 1257, 1278, 1301, 1322, 1346, 1371, 1396, 1420, 1448, 1470, 1487, 1504, 1521, 1538, 1555, 1572, 1591, 1610, 1633, 1656, 1682, 1699, 1716, 1733, 1753, 1771, 1788, 1809, 1826, 1847, 1864, 1881, 1897, 1913, 1932, 1950, 1977, 2000, 2025, 2053, 2070, 2087, 2104, 2121, 2148, 2175, 2197, 2218, 2241, 2258, 2275, 2292, 2309, 2326, 2343, 2360, 2377, 2394, 2411, 2428, 2445, 2465, 2482, 2501, 2523, 2542, 2558, 2581, 2601, 2623, 2640, 2657, 2674, 2690, 2710, 2734, 2760, 2784, 2807, 2830, 2850, 2871, 2899, 2917, 2940, 2960, 2988, 3018, 3044, 3066, 3088, 3110, 3130, 3151, 3177, 3203, 3226, 3249, 3272, 3297, 3320, 3342, 3364, 3387, 3410, 3430, 3448, 3473, 3500, 3524, 3545, 3568, 3596, 3621, 3649, 3674, 3694, 3715, 3733, 3758, 3776, 3795, 3815, 3836, 3857, 3878, 3908, 3926, 3951, 3975, 4004, 4024, 4050, 4078, 4104, 4133, 4157, 4179, 4203, 4227, 4253, 4284, 4308, 4329, 4352, 4376, 4406, 4432, 4455, 4480, 4503, 4530, 4559, 4588, 4614, 4640, 4666, 4691, 4713, 4737, 4761, 4788, 4815, 4842, 4869, 4892, 4915, 4936, 4959, 4982, 5004, 5026, 5048, 5072, 5095, 5120, 5155, 5189, 5224, 5250, 5284, 5323, 5350, 5375, 5413, 5454, 5478, 5498, 5518, 5548, 5580, 5611, 5643, 5678, 5702, 5726, 5757, 5784, 5812, 5841, 5877, 5911, 5949, 5991, 6031, 6054, 6077, 6096, 6122, 6150, 6178, 6208, 6239, 6269, 6297, 6321, 6345, 6370, 6407, 6450, 6497, 6519, 6542, 6562, 6583, 6606, 6630, 6652, 6670, 6689, 6711, 6734, 6762, 6791, 6829, 6865, 6892, 6917, 6953, 6988, 7029, 7052, 7075, 7105, 7135, 7167, 7192, 7218, 7243, 7266, 7286, 7307, 7336, 7371, 7394, 7418, 7454, 7480, 7502, 7530, 7551, 7573, 7593, 7614, 7636, 7659, 7683, 7709, 7735, 7763, 7793, 7823, 7848, 7880, 7914, 7948, 7978, 8008, 8038, 8069, 8100, 8135, 8163, 8186, 8205, 8226, 8242, 8262, 8285, 8316, 8347, 8381, 8409, 8442, 8475, 8509, 8532, 8555, 8578, 8607, 8629, 8654, 8684, 8713, 8742, 8770, 8798, 8828, 8862, 8888, 8915, 8945, 8976, 9007, 9031, 9055, 9084, 9113, 9132, 9155, 9173, 9195, 9220, 9245, 9275, 9309, 9349, 9387, 9405, 9429, 9453, 9471, 9500, 9529, 9547, 9565, 9589, 9624, 9642, 9660, 9678, 9703, 9728, 9754, 9787, 9819, 9848, 9866, 9890, 9914, 9932, 9950, 9981, 10000, 10018, 10036, 10054, 10072, 10090, 10108, 10126, 10144, 10162, 10180, 10198, 10216, 10234, 10252} + +func (i PacketID) String() string { + if i >= PacketID(len(_PacketID_index)-1) { + return "PacketID(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _PacketID_name[_PacketID_index[i]:_PacketID_index[i+1]] +} diff --git a/Erupe/server/channelserver/compression/deltacomp/deltacomp.go b/Erupe/server/channelserver/compression/deltacomp/deltacomp.go new file mode 100644 index 000000000..9760e86a0 --- /dev/null +++ b/Erupe/server/channelserver/compression/deltacomp/deltacomp.go @@ -0,0 +1,107 @@ +package deltacomp + +import ( + "bytes" + "io" + "fmt" +) + +func checkReadUint8(r *bytes.Reader) (uint8, error) { + b, err := r.ReadByte() + if err != nil { + return 0, err + } + return b, nil +} + +func checkReadUint16(r *bytes.Reader) (uint16, error) { + data := make([]byte, 2) + n, err := r.Read(data) + if err != nil { + return 0, err + } else if n != len(data) { + return 0, io.EOF + } + + return uint16(data[0])<<8 | uint16(data[1]), nil +} + +func readCount(r *bytes.Reader) (int, error) { + var count int + + count8, err := checkReadUint8(r) + if err != nil { + return 0, err + } + count = int(count8) + + if count == 0 { + count16, err := checkReadUint16(r) + if err != nil { + return 0, err + } + count = int(count16) + } + + return int(count), nil +} + +// ApplyDataDiff applies a delta data diff patch onto given base data. +func ApplyDataDiff(diff []byte, baseData []byte) []byte { + // Make a copy of the base data to return, + // (probably just make this modify the given slice in the future). + baseCopy := make([]byte, len(baseData)) + copy(baseCopy, baseData) + + patch := bytes.NewReader(diff) + + // The very first matchCount is +1 more than it should be, so we start at -1. + dataOffset := -1 + for { + // Read the amount of matching bytes. + matchCount, err := readCount(patch) + if err != nil { + // No more data + break + } + + dataOffset += matchCount + + // Read the amount of differing bytes. + differentCount, err := readCount(patch) + if err != nil { + // No more data + break + } + differentCount-- + + // Grow slice if it's required + if(len(baseCopy) < dataOffset){ + fmt.Printf("Slice smaller than data offset, growing slice...") + baseCopy = append(baseCopy, make([]byte, (dataOffset + differentCount) - len(baseData))...) + } else { + length := len(baseCopy[dataOffset:]) + if length < differentCount { + length -= differentCount + baseCopy = append(baseCopy, make([]byte, length)...) + } + } + + + // Apply the patch bytes. + for i := 0; i < differentCount; i++ { + b, err := checkReadUint8(patch) + if err != nil { + panic("Invalid or misunderstood patch format!") + } + + + baseCopy[dataOffset+i] = b + } + + dataOffset += differentCount - 1 + + } + + return baseCopy +} diff --git a/Erupe/server/channelserver/compression/deltacomp/deltacomp_test.go b/Erupe/server/channelserver/compression/deltacomp/deltacomp_test.go new file mode 100644 index 000000000..da1a6c871 --- /dev/null +++ b/Erupe/server/channelserver/compression/deltacomp/deltacomp_test.go @@ -0,0 +1,113 @@ +package deltacomp + +import ( + "bytes" + "encoding/hex" + "fmt" + "io/ioutil" + "testing" + + "github.com/Solenataris/Erupe/server/channelserver/compression/nullcomp" +) + +var tests = []struct { + before string + patches []string + after string +}{ + { + "hunternavi_0_before.bin", + []string{ + "hunternavi_0_patch_0.bin", + "hunternavi_0_patch_1.bin", + }, + "hunternavi_0_after.bin", + }, + { + // From "Character Progression 1 Creation-NPCs-Tours" + "hunternavi_1_before.bin", + []string{ + "hunternavi_1_patch_0.bin", + "hunternavi_1_patch_1.bin", + "hunternavi_1_patch_2.bin", + "hunternavi_1_patch_3.bin", + "hunternavi_1_patch_4.bin", + "hunternavi_1_patch_5.bin", + "hunternavi_1_patch_6.bin", + "hunternavi_1_patch_7.bin", + "hunternavi_1_patch_8.bin", + "hunternavi_1_patch_9.bin", + "hunternavi_1_patch_10.bin", + "hunternavi_1_patch_11.bin", + "hunternavi_1_patch_12.bin", + "hunternavi_1_patch_13.bin", + "hunternavi_1_patch_14.bin", + "hunternavi_1_patch_15.bin", + "hunternavi_1_patch_16.bin", + "hunternavi_1_patch_17.bin", + "hunternavi_1_patch_18.bin", + "hunternavi_1_patch_19.bin", + "hunternavi_1_patch_20.bin", + "hunternavi_1_patch_21.bin", + "hunternavi_1_patch_22.bin", + "hunternavi_1_patch_23.bin", + "hunternavi_1_patch_24.bin", + }, + "hunternavi_1_after.bin", + }, + { + // From "Progress Gogo GRP Grind 9 and Armor Upgrades and Partner Equip and Lost Cat and Manager talk and Pugi Order" + // Not really sure this one counts as a valid test as the input and output are exactly the same. The patches cancel each other out. + "platedata_0_before.bin", + []string{ + "platedata_0_patch_0.bin", + "platedata_0_patch_1.bin", + }, + "platedata_0_after.bin", + }, +} + +func readTestDataFile(filename string) []byte { + data, err := ioutil.ReadFile(fmt.Sprintf("./test_data/%s", filename)) + if err != nil { + panic(err) + } + return data +} + +func TestDeltaPatch(t *testing.T) { + for k, tt := range tests { + testname := fmt.Sprintf("delta_patch_test_%d", k) + t.Run(testname, func(t *testing.T) { + // Load the test binary data. + beforeData, err := nullcomp.Decompress(readTestDataFile(tt.before)) + if err != nil { + t.Error(err) + } + + var patches [][]byte + for _, patchName := range tt.patches { + patchData := readTestDataFile(patchName) + patches = append(patches, patchData) + } + + afterData, err := nullcomp.Decompress(readTestDataFile(tt.after)) + if err != nil { + t.Error(err) + } + + // Now actually test calling ApplyDataDiff. + data := beforeData + + // Apply the patches in order. + for i, patch := range patches { + fmt.Println("patch index: ", i) + data = ApplyDataDiff(patch, data) + } + + if !bytes.Equal(data, afterData) { + t.Errorf("got out\n\t%s\nwant\n\t%s", hex.Dump(data), hex.Dump(afterData)) + } + }) + } +} diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_after.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_after.bin new file mode 100644 index 000000000..d4de4341b Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_after.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_before.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_before.bin new file mode 100644 index 000000000..3268f9834 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_before.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_patch_0.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_patch_0.bin new file mode 100644 index 000000000..0d460ec60 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_patch_0.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_patch_1.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_patch_1.bin new file mode 100644 index 000000000..86b68677a Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_0_patch_1.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_after.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_after.bin new file mode 100644 index 000000000..a16e230f0 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_after.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_before.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_before.bin new file mode 100644 index 000000000..a3a35949d Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_before.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_0.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_0.bin new file mode 100644 index 000000000..4d4087792 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_0.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_1.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_1.bin new file mode 100644 index 000000000..ebe6eadcb Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_1.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_10.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_10.bin new file mode 100644 index 000000000..2ede80181 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_10.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_11.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_11.bin new file mode 100644 index 000000000..291775a3b Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_11.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_12.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_12.bin new file mode 100644 index 000000000..28b1ab96c Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_12.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_13.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_13.bin new file mode 100644 index 000000000..f524a87c7 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_13.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_14.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_14.bin new file mode 100644 index 000000000..d5a804b15 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_14.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_15.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_15.bin new file mode 100644 index 000000000..1f5144f5c Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_15.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_16.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_16.bin new file mode 100644 index 000000000..29bbc5268 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_16.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_17.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_17.bin new file mode 100644 index 000000000..e524310b4 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_17.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_18.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_18.bin new file mode 100644 index 000000000..8559f21c8 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_18.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_19.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_19.bin new file mode 100644 index 000000000..81745fbf7 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_19.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_2.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_2.bin new file mode 100644 index 000000000..ab4f9a69f Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_2.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_20.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_20.bin new file mode 100644 index 000000000..9c0d8cace Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_20.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_21.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_21.bin new file mode 100644 index 000000000..4f0d5a3b0 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_21.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_22.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_22.bin new file mode 100644 index 000000000..274523f37 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_22.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_23.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_23.bin new file mode 100644 index 000000000..7e1cf8667 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_23.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_24.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_24.bin new file mode 100644 index 000000000..f6796439a Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_24.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_3.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_3.bin new file mode 100644 index 000000000..830eae49f Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_3.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_4.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_4.bin new file mode 100644 index 000000000..a034700bc Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_4.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_5.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_5.bin new file mode 100644 index 000000000..342f05115 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_5.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_6.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_6.bin new file mode 100644 index 000000000..982996700 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_6.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_7.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_7.bin new file mode 100644 index 000000000..05ea1cc75 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_7.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_8.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_8.bin new file mode 100644 index 000000000..a96085c82 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_8.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_9.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_9.bin new file mode 100644 index 000000000..3844e747c Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/hunternavi_1_patch_9.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_after.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_after.bin new file mode 100644 index 000000000..008e412a8 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_after.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_before.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_before.bin new file mode 100644 index 000000000..008e412a8 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_before.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_patch_0.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_patch_0.bin new file mode 100644 index 000000000..444b62e6b Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_patch_0.bin differ diff --git a/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_patch_1.bin b/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_patch_1.bin new file mode 100644 index 000000000..d113e5e47 Binary files /dev/null and b/Erupe/server/channelserver/compression/deltacomp/test_data/platedata_0_patch_1.bin differ diff --git a/Erupe/server/channelserver/compression/nullcomp/nullcomp.go b/Erupe/server/channelserver/compression/nullcomp/nullcomp.go new file mode 100644 index 000000000..ed62e99ca --- /dev/null +++ b/Erupe/server/channelserver/compression/nullcomp/nullcomp.go @@ -0,0 +1,93 @@ +package nullcomp + +import ( + "bytes" + "io" +) + +// Decompress decompresses null-compressesed data. +func Decompress(compData []byte) ([]byte, error) { + r := bytes.NewReader(compData) + + header := make([]byte, 16) + n, err := r.Read(header) + if err != nil { + return nil, err + } else if n != len(header) { + return nil, err + } + + // Just return the data if it doesn't contain the cmp header. + if !bytes.Equal(header, []byte("cmp\x2020110113\x20\x20\x20\x00")) { + return compData, nil + } + + var output []byte + for { + b, err := r.ReadByte() + if err == io.EOF { + break + } else if err != nil { + return nil, err + } + + if b == 0 { + // If it's a null byte, then the next byte is how many nulls to add. + nullCount, err := r.ReadByte() + if err == io.EOF { + break + } else if err != nil { + return nil, err + } + + output = append(output, make([]byte, int(nullCount))...) + } else { + output = append(output, b) + } + } + + return output, nil +} + +// Compress null compresses give given data. +func Compress(rawData []byte) ([]byte, error) { + r := bytes.NewReader(rawData) + var output []byte + output = append(output, []byte("cmp\x2020110113\x20\x20\x20\x00")...) + for { + b, err := r.ReadByte() + if err == io.EOF { + break + } else if err != nil { + return nil, err + } + if b == 0 { + output = append(output, []byte{0x00}...) + // read to get null count + nullCount := 1 + for { + i, err := r.ReadByte() + if err == io.EOF { + output = append(output, []byte{byte(nullCount)}...) + break + } else if i != 0 { + r.UnreadByte() + output = append(output, []byte{byte(nullCount)}...) + break + } else if err != nil { + return nil, err + } + nullCount++ + + // Flush the null-count if it gets to 255, start on the next null count. + if nullCount == 255 { + output = append(output, []byte{0xFF, 0x00}...) + nullCount = 0 + } + } + } else { + output = append(output, b) + } + } + return output, nil +} diff --git a/Erupe/server/channelserver/handlers.go b/Erupe/server/channelserver/handlers.go new file mode 100644 index 000000000..038be1154 --- /dev/null +++ b/Erupe/server/channelserver/handlers.go @@ -0,0 +1,1138 @@ +package channelserver + +import ( + "bytes" + "encoding/hex" + "io/ioutil" + "math/bits" + "math/rand" + "fmt" + "time" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network/mhfpacket" + "go.uber.org/zap" + "golang.org/x/text/encoding/japanese" + "golang.org/x/text/transform" +) + +// Temporary function to just return no results for a MSG_MHF_ENUMERATE* packet +func stubEnumerateNoResults(s *Session, ackHandle uint32) { + enumBf := byteframe.NewByteFrame() + enumBf.WriteUint32(0) // Entry count (count for quests, rankings, events, etc.) + + doAckBufSucceed(s, ackHandle, enumBf.Data()) +} + +// Temporary function to just return no results for many MSG_MHF_GET* packets. +func stubGetNoResults(s *Session, ackHandle uint32) { + resp := byteframe.NewByteFrame() + resp.WriteUint32(0x0A218EAD) // Unk shared ID. Sent in response of MSG_MHF_GET_TOWER_INFO, MSG_MHF_GET_PAPER_DATA etc. (World ID?) + resp.WriteUint32(0) // Unk + resp.WriteUint32(0) // Unk + resp.WriteUint32(0) // Entry count + + doAckBufSucceed(s, ackHandle, resp.Data()) +} + +func doAckBufSucceed(s *Session, ackHandle uint32, data []byte) { + s.QueueSendMHF(&mhfpacket.MsgSysAck{ + AckHandle: ackHandle, + IsBufferResponse: true, + ErrorCode: 0, + AckData: data, + }) +} + +func doAckBufFail(s *Session, ackHandle uint32, data []byte) { + s.QueueSendMHF(&mhfpacket.MsgSysAck{ + AckHandle: ackHandle, + IsBufferResponse: true, + ErrorCode: 1, + AckData: data, + }) +} + +func doAckSimpleSucceed(s *Session, ackHandle uint32, data []byte) { + s.QueueSendMHF(&mhfpacket.MsgSysAck{ + AckHandle: ackHandle, + IsBufferResponse: false, + ErrorCode: 0, + AckData: data, + }) +} + +func doAckSimpleFail(s *Session, ackHandle uint32, data []byte) { + s.QueueSendMHF(&mhfpacket.MsgSysAck{ + AckHandle: ackHandle, + IsBufferResponse: false, + ErrorCode: 1, + AckData: data, + }) +} + +func updateRights(s *Session) { + update := &mhfpacket.MsgSysUpdateRight{ + ClientRespAckHandle: 0, + Unk1: 0x0E, //0e with normal sub 4e when having premium it's probably a bitfield? + // 01 = Character can take quests at allows + // 02 = Hunter Life, normal quests core sub + // 03 = Extra Course, extra quests, town boxes, QOL course, core sub + // 06 = Premium Course, standard 'premium' which makes ranking etc. faster + // some connection to unk1 above for these maybe? + // 06 0A 0B = Boost Course, just actually 3 subs combined + // 08 09 1E = N Course, gives you the benefits of being in a netcafe (extra quests, N Points, daily freebies etc.) minimal and pointless + // no timestamp after 08 or 1E while active + // 0C = N Boost course, ultra luxury course that ruins the game if in use but also gives a + Rights: []mhfpacket.ClientRight{ + { + ID: 1, + Timestamp: 0, + }, + { + ID: 2, + Timestamp: 0x5FEA1781, + }, + { + ID: 3, + Timestamp: 0x5FEA1781, + }, + }, + UnkSize: 0, + } + s.QueueSendMHF(update) +} + +func fixedSizeShiftJIS(text string, size int) []byte { + r := bytes.NewBuffer([]byte(text)) + encoded, err := ioutil.ReadAll(transform.NewReader(r, japanese.ShiftJIS.NewEncoder())) + if err != nil { + panic(err) + } + + out := make([]byte, size) + copy(out, encoded) + out[len(out)-1] = 0 + return out +} +func handleMsgHead(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysExtendThreshold(s *Session, p mhfpacket.MHFPacket) { + // No data aside from header, no resp required. +} + +func handleMsgSysEnd(s *Session, p mhfpacket.MHFPacket) { + // No data aside from header, no resp required. +} + +func handleMsgSysNop(s *Session, p mhfpacket.MHFPacket) { + // No data aside from header, no resp required. +} + +func handleMsgSysAck(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysTerminalLog(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysTerminalLog) + resp := byteframe.NewByteFrame() + + resp.WriteUint32(0x98bd51a9) // LogID to use for requests after this. + doAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgSysLogin(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysLogin) + name := "" + + s.server.db.QueryRow("SELECT name FROM characters WHERE id = $1", pkt.CharID0).Scan(&name) + s.Lock() + s.Name = name + s.charID = pkt.CharID0 + s.Unlock() + bf := byteframe.NewByteFrame() + bf.WriteUint32(uint32(Time_Current_Adjusted().Unix())) // Unix timestamp + + if s.server.erupeConfig.DevModeOptions.ServerName != "" { + _, err := s.server.db.Exec("UPDATE servers SET current_players=$1 WHERE server_name=$2", uint32(len(s.server.sessions)), s.server.erupeConfig.DevModeOptions.ServerName) + if err != nil { + panic(err) + } + } + + doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgSysLogout(s *Session, p mhfpacket.MHFPacket) { + logoutPlayer(s) +} + +func logoutPlayer(s *Session) { + if s.stage == nil { + return + } + + s.stage.RLock() + for client := range s.stage.clients { + client.QueueSendMHF(&mhfpacket.MsgSysDeleteUser{ + CharID: s.charID, + }) + } + s.stage.RUnlock() + + if s.server.erupeConfig.DevModeOptions.ServerName != "" { + _, err := s.server.db.Exec("UPDATE servers SET current_players=$1 WHERE server_name=$2", uint32(len(s.server.sessions)), s.server.erupeConfig.DevModeOptions.ServerName) + if err != nil { + panic(err) + } + } + + removeSessionFromStage(s) +} + +func handleMsgSysSetStatus(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysPing(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysPing) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgSysTime(s *Session, p mhfpacket.MHFPacket) { + //pkt := p.(*mhfpacket.MsgSysTime) + + resp := &mhfpacket.MsgSysTime{ + GetRemoteTime: false, + Timestamp: uint32(Time_Current_Adjusted().Unix()), // JP timezone + } + s.QueueSendMHF(resp) +} + +func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysIssueLogkey) + + // Make a random log key for this session. + logKey := make([]byte, 16) + _, err := rand.Read(logKey) + if err != nil { + panic(err) + } + + // TODO(Andoryuuta): In the offical client, the log key index is off by one, + // cutting off the last byte in _most uses_. Find and document these accordingly. + s.Lock() + s.logKey = logKey + s.Unlock() + + // Issue it. + resp := byteframe.NewByteFrame() + resp.WriteBytes(logKey) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgSysRecordLog(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysRecordLog) + // remove a client returning to town from reserved slots to make sure the stage is hidden from board + delete(s.stage.reservedClientSlots, s.charID) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgSysEcho(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysLockGlobalSema(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysLockGlobalSema) + + bf := byteframe.NewByteFrame() + // Unk + // 0x00 when no ID sent + // 0x02 when ID sent + if pkt.ServerChannelIDLength == 1 { + bf.WriteBytes([]byte{0x00, 0x00, 0x00, 0x01, 0x00}) + } else { + bf.WriteUint8(0x02) + bf.WriteUint8(0x00) // Unk + bf.WriteUint16(uint16(pkt.ServerChannelIDLength)) + bf.WriteBytes([]byte(pkt.ServerChannelIDString)) + } + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgSysUnlockGlobalSema(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysUnlockGlobalSema) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 8)) +} + +func handleMsgSysUpdateRight(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysAuthQuery(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysAuthTerminal(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysRightsReload(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysRightsReload) + updateRights(s) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgCaExchangeItem(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfResetTitle(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfPresentBox(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfServerCommand(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAnnounce(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfSetLoginwindow(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysTransBinary(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysCollectBinary(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysGetState(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysSerialize(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysEnumlobby(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysEnumuser(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysInfokyserver(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetCaUniqueID(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEnumerateItem(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireItem(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfTransferItem(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfTransferItem) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfEnumeratePrice(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumeratePrice) + //resp := byteframe.NewByteFrame() + //resp.WriteUint16(0) // Entry type 1 count + //resp.WriteUint16(0) // Entry type 2 count + // directly lifted for now because lacking it crashes the counter on having actual events present + data, _ := hex.DecodeString("0000000066000003E800000000007300640100000320000000000006006401000003200000000000300064010000044C00000000007200640100000384000000000034006401000003840000000000140064010000051400000000006E006401000003E8000000000016006401000003E8000000000001006401000003200000000000430064010000057800000000006F006401000003840000000000330064010000044C00000000000B006401000003E800000000000F006401000006400000000000700064010000044C0000000000110064010000057800000000004C006401000003E8000000000059006401000006A400000000006D006401000005DC00000000004B006401000005DC000000000050006401000006400000000000350064010000070800000000006C0064010000044C000000000028006401000005DC00000000005300640100000640000000000060006401000005DC00000000005E0064010000051400000000007B006401000003E80000000000740064010000070800000000006B0064010000025800000000001B0064010000025800000000001C006401000002BC00000000001F006401000006A400000000007900640100000320000000000008006401000003E80000000000150064010000070800000000007A0064010000044C00000000000E00640100000640000000000055006401000007D0000000000002006401000005DC00000000002F0064010000064000000000002A0064010000076C00000000007E006401000002BC0000000000440064010000038400000000005C0064010000064000000000005B006401000006A400000000007D0064010000076C00000000007F006401000005DC0000000000540064010000064000000000002900640100000960000000000024006401000007D0000000000081006401000008340000000000800064010000038400000000001A006401000003E800000000002D0064010000038400000000004A006401000006A400000000005A00640100000384000000000027006401000007080000000000830064010000076C000000000040006401000006400000000000690064010000044C000000000025006401000004B000000000003100640100000708000000000082006401000003E800000000006500640100000640000000000051006401000007D000000000008C0064010000070800000000004D0064010000038400000000004E0064010000089800000000008B006401000004B000000000002E006401000009600000000000920064010000076C00000000008E00640100000514000000000068006401000004B000000000002B006401000003E800000000002C00640100000BB8000000000093006401000008FC00000000009000640100000AF0000000000094006401000006A400000000008D0064010000044C000000000052006401000005DC00000000004F006401000008980000000000970064010000070800000000006A0064010000064000000000005F00640100000384000000000026006401000008FC000000000096006401000007D00000000000980064010000076C000000000041006401000006A400000000003B006401000007080000000000360064010000083400000000009F00640100000A2800000000009A0064010000076C000000000021006401000007D000000000006300640100000A8C0000000000990064010000089800000000009E006401000007080000000000A100640100000C1C0000000000A200640100000C800000000000A400640100000DAC0000000000A600640100000C800000000000A50064010010") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfEnumerateRanking(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateRanking) + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint8(0) + resp.WriteUint8(0) // Some string length following this field. + resp.WriteUint16(0) // Entry type 1 count + resp.WriteUint8(0) // Entry type 2 count + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + + // Update the client's rights as well: + updateRights(s) +} + +func handleMsgMhfEnumerateOrder(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateOrder) + stubEnumerateNoResults(s, pkt.AckHandle) +} + +func handleMsgMhfGetExtraInfo(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireTitle(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEnumerateTitle(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEnumerateUnionItem(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfUpdateUnionItem(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfCreateJoint(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfOperateJoint(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfInfoJoint(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireCafeItem(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfAcquireCafeItem) + var netcafe_points int + err := s.server.db.QueryRow("UPDATE characters SET netcafe_points = netcafe_points - $1 WHERE id = $2 RETURNING netcafe_points", pkt.PointCost, s.charID).Scan(&netcafe_points) + if err != nil { + s.logger.Fatal("Failed to get plate data savedata from db", zap.Error(err)) + } + resp := byteframe.NewByteFrame() + resp.WriteUint32(uint32(netcafe_points)) + doAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfUpdateCafepoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfUpdateCafepoint) + var netcafe_points int + err := s.server.db.QueryRow("SELECT COALESCE(netcafe_points, 0) FROM characters WHERE id = $1", s.charID).Scan(&netcafe_points) + if err != nil { + s.logger.Fatal("Failed to get plate data savedata from db", zap.Error(err)) + } + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + resp.WriteUint32(uint32(netcafe_points)) + doAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfCheckDailyCafepoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfCheckDailyCafepoint) + + // I am not sure exactly what this does, but all responses I have seen include this exact sequence of bytes + // 1 daily, 5 daily halk pots, 3 point boosted quests, also adds 5 netcafe points but not sent to client + // available once after midday every day + + // get next midday + var t = Time_static() + year, month, day := t.Date() + midday := time.Date(year, month, day, 12, 0, 0, 0, t.Location()) + if t.After(midday) { + midday = midday.Add(24 * time.Hour) + } + + // get time after which daily claiming would be valid from db + var dailyTime time.Time + err := s.server.db.QueryRow("SELECT COALESCE(daily_time, $2) FROM characters WHERE id = $1", s.charID, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)).Scan(&dailyTime) + if err != nil { + s.logger.Fatal("Failed to get daily_time savedata from db", zap.Error(err)) + } + + if t.After(dailyTime) { + // +5 netcafe points and setting next valid window + _, err := s.server.db.Exec("UPDATE characters SET daily_time=$1, netcafe_points=netcafe_points::int + 5 WHERE id=$2", midday, s.charID) + if err != nil { + s.logger.Fatal("Failed to update daily_time and netcafe_points savedata in db", zap.Error(err)) + } + doAckBufSucceed(s, pkt.AckHandle, []byte{0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01}) + } else { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + } +} + +func handleMsgMhfGetCogInfo(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfCheckMonthlyItem(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireMonthlyItem(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfCheckWeeklyStamp(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfCheckWeeklyStamp) + + resp := byteframe.NewByteFrame() + resp.WriteUint16(0x000E) + resp.WriteUint16(0x0001) + resp.WriteUint16(0x0000) + resp.WriteUint16(0x0000) // 0x0000 stops the vaguely annoying log in pop up + resp.WriteUint32(0) + resp.WriteUint32(0x5dddcbb3) // Timestamp + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfExchangeWeeklyStamp(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEnumerateGuacot(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateGuacot) + var data bool + err := s.server.db.QueryRow("SELECT gook0status FROM gook WHERE id = $1",s.charID).Scan(&data) + if err ==nil { + tempresp := byteframe.NewByteFrame() + count := uint16(0) + var gook0 []byte + var gook1 []byte + var gook2 []byte + var gook3 []byte + var gook4 []byte + var gook5 []byte + var gook0status bool + var gook1status bool + var gook2status bool + var gook3status bool + var gook4status bool + var gook5status bool + _ = s.server.db.QueryRow("SELECT gook0 FROM gook WHERE id = $1",s.charID).Scan(&gook0) + _ = s.server.db.QueryRow("SELECT gook1 FROM gook WHERE id = $1",s.charID).Scan(&gook1) + _ = s.server.db.QueryRow("SELECT gook2 FROM gook WHERE id = $1",s.charID).Scan(&gook2) + _ = s.server.db.QueryRow("SELECT gook3 FROM gook WHERE id = $1",s.charID).Scan(&gook3) + _ = s.server.db.QueryRow("SELECT gook4 FROM gook WHERE id = $1",s.charID).Scan(&gook4) + _ = s.server.db.QueryRow("SELECT gook5 FROM gook WHERE id = $1",s.charID).Scan(&gook5) + _ = s.server.db.QueryRow("SELECT gook0status FROM gook WHERE id = $1",s.charID).Scan(&gook0status) + _ = s.server.db.QueryRow("SELECT gook1status FROM gook WHERE id = $1",s.charID).Scan(&gook1status) + _ = s.server.db.QueryRow("SELECT gook2status FROM gook WHERE id = $1",s.charID).Scan(&gook2status) + _ = s.server.db.QueryRow("SELECT gook3status FROM gook WHERE id = $1",s.charID).Scan(&gook3status) + _ = s.server.db.QueryRow("SELECT gook4status FROM gook WHERE id = $1",s.charID).Scan(&gook4status) + _ = s.server.db.QueryRow("SELECT gook5status FROM gook WHERE id = $1",s.charID).Scan(&gook5status) + if gook0status == true { + count++ + tempresp.WriteBytes(gook0) + } + if gook1status == true { + count++ + tempresp.WriteBytes(gook1) + } + if gook2status == true { + count++ + tempresp.WriteBytes(gook2) + } + if gook3status == true { + count++ + tempresp.WriteBytes(gook3) + } + if gook4status == true { + count++ + tempresp.WriteBytes(gook4) + } + if gook5status == true { + count++ + tempresp.WriteBytes(gook5) + } + if count == uint16(0) { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + } else { + resp:= byteframe.NewByteFrame() + resp.WriteUint16(count) + resp.WriteBytes(tempresp.Data()) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + } + } else { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + } +} + +func handleMsgMhfUpdateGuacot(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfUpdateGuacot) + count := int(pkt.EntryCount) + fmt.Printf("handleMsgMhfUpdateGuacot:%d\n", count) + if count == 0 { + _,err := s.server.db.Exec("INSERT INTO gook(id,gook0status,gook1status,gook2status,gook3status,gook4status,gook5status) VALUES($1,bool(false),bool(false),bool(false),bool(false),bool(false),bool(false))", s.charID) + if err!=nil { + fmt.Printf("INSERT INTO gook failure\n") + } + } else { + for i := 0; i < int(pkt.EntryCount); i++ { + gookindex := int(pkt.Entries[i].Unk0) + buf := pkt.GuacotUpdateEntryToBytes(pkt.Entries[i]) + //fmt.Printf("gookindex:%d\n", gookindex) + switch gookindex { + case 0: + s.server.db.Exec("UPDATE gook SET gook0 = $1 WHERE id = $2", buf, s.charID) + if pkt.Entries[i].Unk1 != uint16(0) { + s.server.db.Exec("UPDATE gook SET gook0status = $1 WHERE id = $2", bool(true), s.charID) + } else { + s.server.db.Exec("UPDATE gook SET gook0status = $1 WHERE id = $2", bool(false), s.charID) + } + case 1: + s.server.db.Exec("UPDATE gook SET gook1 = $1 WHERE id = $2", buf, s.charID) + if pkt.Entries[i].Unk1 != uint16(0) { + s.server.db.Exec("UPDATE gook SET gook1status = $1 WHERE id = $2", bool(true), s.charID) + } else { + s.server.db.Exec("UPDATE gook SET gook1status = $1 WHERE id = $2", bool(false), s.charID) + } + case 2: + s.server.db.Exec("UPDATE gook SET gook2 = $1 WHERE id = $2", buf, s.charID) + if pkt.Entries[i].Unk1 != uint16(0) { + s.server.db.Exec("UPDATE gook SET gook2status = $1 WHERE id = $2", bool(true), s.charID) + } else { + s.server.db.Exec("UPDATE gook SET gook2status = $1 WHERE id = $2", bool(false), s.charID) + } + case 3: + s.server.db.Exec("UPDATE gook SET gook3 = $1 WHERE id = $2", buf, s.charID) + if pkt.Entries[i].Unk1 != uint16(0) { + s.server.db.Exec("UPDATE gook SET gook3status = $1 WHERE id = $2", bool(true), s.charID) + } else { + s.server.db.Exec("UPDATE gook SET gook3status = $1 WHERE id = $2", bool(false), s.charID) + } + case 4: + s.server.db.Exec("UPDATE gook SET gook4 = $1 WHERE id = $2", buf,s.charID) + if pkt.Entries[i].Unk1 != uint16(0) { + s.server.db.Exec("UPDATE gook SET gook4status = $1 WHERE id = $2", bool(true), s.charID) + } else { + s.server.db.Exec("UPDATE gook SET gook4status = $1 WHERE id = $2", bool(false), s.charID) + } + } + } + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfInfoScenarioCounter(s *Session, p mhfpacket.MHFPacket) { + + pkt := p.(*mhfpacket.MsgMhfInfoScenarioCounter) + + scenarioCounter := []struct { + Unk0 uint32 // Main ID? + Unk1 uint8 + Unk2 uint8 + }{ + { + Unk0: 0x00000000, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x00000001, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x00000002, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x00000003, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x00000004, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x00000005, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x00000006, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x00000007, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x00000008, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x00000009, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x0000000A, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x0000000B, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x0000000C, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x0000000D, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x0000000E, + Unk1: 1, + Unk2: 4, + }, + { + Unk0: 0x00000032, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000033, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000034, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000035, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000036, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000037, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000038, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x0000003A, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x0000003F, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000040, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000041, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000047, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x0000004B, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x0000003D, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000044, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000042, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x0000004C, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000046, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x0000004D, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000048, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x0000004A, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000049, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x0000004E, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x00000045, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x0000003E, + Unk1: 1, + Unk2: 5, + }, + { + Unk0: 0x0000004F, + Unk1: 1, + Unk2: 5, + }, + } + + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(len(scenarioCounter))) // Entry count + for _, entry := range scenarioCounter { + resp.WriteUint32(entry.Unk0) + resp.WriteUint8(entry.Unk1) + resp.WriteUint8(entry.Unk2) + } + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + + // DEBUG, DELETE ME! + /* + data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "debug/info_scenario_counter_resp.bin")) + if err != nil { + panic(err) + } + + doAckBufSucceed(s, pkt.AckHandle, data) + */ + +} + +func handleMsgMhfGetBbsSnsStatus(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfApplyBbsArticle(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetEtcPoints(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetEtcPoints) + + resp := byteframe.NewByteFrame() + resp.WriteUint8(0x3) // Maybe a count of uint32(s)? + resp.WriteUint32(0) + resp.WriteUint32(14) + resp.WriteUint32(14) + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfUpdateEtcPoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfUpdateEtcPoint) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfStampcardStamp(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfStampcardStamp) + // TODO: Work out where it gets existing stamp count from, its format and then + // update the actual sent values to be correct + doAckBufSucceed(s, pkt.AckHandle, []byte{0x03, 0xe7, 0x03, 0xe7, 0x02, 0x99, 0x02, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x14, 0xf8, 0x69, 0x54}) +} + +func handleMsgMhfStampcardPrize(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfUnreserveSrg(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfReadBeatLevel(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadBeatLevel) + + // This response is fixed and will never change on JP, + // but I've left it dynamic for possible other client differences. + resp := byteframe.NewByteFrame() + for i := 0; i < int(pkt.ValidIDCount); i++ { + resp.WriteUint32(pkt.IDs[i]) + resp.WriteUint32(1) + resp.WriteUint32(1) + resp.WriteUint32(1) + } + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfUpdateBeatLevel(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfUpdateBeatLevel) + + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfReadBeatLevelAllRanking(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfReadBeatLevelMyRanking(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfReadLastWeekBeatRanking(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetFixedSeibatuRankingTable(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfKickExportForce(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetEarthStatus(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetEarthStatus) + + // TODO(Andoryuuta): Track down format for this data, + // it can somehow be parsed as 8*uint32 chunks if the header is right. + /* + BEFORE ack-refactor: + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + resp.WriteUint32(0) + + s.QueueAck(pkt.AckHandle, resp.Data()) + */ + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfRegistSpabiTime(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetEarthValue(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetEarthValue) + var earthValues []struct{ Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 } + if pkt.ReqType == 3 { + earthValues = []struct { + Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 + }{ + // TW identical to JP + { + Unk0: 0x03E9, + Unk1: 0x24, + }, + { + Unk0: 0x2329, + Unk1: 0x03, + }, + { + Unk0: 0x232A, + Unk1: 0x0A, + Unk2: 0x012C, + }, + } + } else if pkt.ReqType == 2 { + earthValues = []struct { + Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 + }{ + // JP response was empty + { + Unk0: 0x01, + Unk1: 0x168B, + }, + { + Unk0: 0x02, + Unk1: 0x0737, + }, + } + } else if pkt.ReqType == 1 { + earthValues = []struct { + Unk0, Unk1, Unk2, Unk3, Unk4, Unk5 uint32 + }{ + // JP simply sent 01 and 02 respectively + { + Unk0: 0x01, + Unk1: 0x0138, + }, + { + Unk0: 0x02, + Unk1: 0x63, + }, + } + } + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0x0A218EAD) // Unk shared ID. Sent in response of MSG_MHF_GET_TOWER_INFO, MSG_MHF_GET_PAPER_DATA etc. + resp.WriteUint32(0) // Unk + resp.WriteUint32(0) // Unk + resp.WriteUint32(uint32(len(earthValues))) // value count + for _, v := range earthValues { + resp.WriteUint32(v.Unk0) + resp.WriteUint32(v.Unk1) + resp.WriteUint32(v.Unk2) + resp.WriteUint32(v.Unk3) + resp.WriteUint32(v.Unk4) + resp.WriteUint32(v.Unk5) + } + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfDebugPostValue(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetNotice(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfPostNotice(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetRandFromTable(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetTinyBin(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetTinyBin) + // requested after conquest quests + doAckBufSucceed(s, pkt.AckHandle, []byte{}) +} + +func handleMsgMhfPostTinyBin(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetSenyuDailyCount(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetSeibattle(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetSeibattle) + stubGetNoResults(s, pkt.AckHandle) +} + +func handleMsgMhfPostSeibattle(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetRyoudama(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetRyoudama) + // likely guild related + // REQ: 00 04 13 53 8F 18 00 + // RSP: 0A 21 8E AD 00 00 00 00 00 00 00 00 00 00 00 01 00 01 FE 4E + // REQ: 00 06 13 53 8F 18 00 + // RSP: 0A 21 8E AD 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 + // REQ: 00 05 13 53 8F 18 00 + // RSP: 0A 21 8E AD 00 00 00 00 00 00 00 00 00 00 00 0E 2A 15 9E CC 00 00 00 01 82 79 83 4E 83 8A 81 5B 83 69 00 00 00 00 1E 55 B0 2F 00 00 00 01 8D F7 00 00 00 00 00 00 00 00 00 00 00 00 2A 15 9E CC 00 00 00 02 82 79 83 4E 83 8A 81 5B 83 69 00 00 00 00 03 D5 30 56 00 00 00 02 95 BD 91 F2 97 42 00 00 00 00 00 00 00 00 3F 57 76 9F 00 00 00 03 93 56 92 6E 96 B3 97 70 00 00 00 00 00 00 38 D9 0E C4 00 00 00 03 87 64 83 78 83 42 00 00 00 00 00 00 00 00 23 F3 B9 77 00 00 00 04 82 B3 82 CC 82 DC 82 E9 81 99 00 00 00 00 3F 1B 17 9C 00 00 00 04 82 B1 82 A4 82 BD 00 00 00 00 00 00 00 00 00 B9 F9 C0 00 00 00 05 82 CD 82 E9 82 A9 00 00 00 00 00 00 00 00 23 9F 9A EA 00 00 00 05 83 70 83 62 83 4C 83 83 83 49 00 00 00 00 38 D9 0E C4 00 00 00 06 87 64 83 78 83 42 00 00 00 00 00 00 00 00 1E 55 B0 2F 00 00 00 06 8D F7 00 00 00 00 00 00 00 00 00 00 00 00 03 D5 30 56 00 00 00 07 95 BD 91 F2 97 42 00 00 00 00 00 00 00 00 02 D3 B8 77 00 00 00 07 6F 77 6C 32 35 32 35 00 00 00 00 00 00 00 + data, _ := hex.DecodeString("0A218EAD0000000000000000000000010000000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfPostRyoudama(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetTenrouirai(s *Session, p mhfpacket.MHFPacket) { + // if the game gets bad responses for this it breaks the ability to save + pkt := p.(*mhfpacket.MsgMhfGetTenrouirai) + var data []byte + var err error + if pkt.Unk0 == 1 { + data, err = hex.DecodeString("0A218EAD000000000000000000000001010000000000060010") + } else if pkt.Unk2 == 4 { + data, err = hex.DecodeString("0A218EAD0000000000000000000000210101005000000202010102020104001000000202010102020106003200000202010002020104000C003202020101020201030032000002020101020202059C4000000202010002020105C35000320202010102020201003C00000202010102020203003200000201010001020203002800320201010101020204000C00000201010101020206002800000201010001020101003C00320201020101020105C35000000301020101020106003200000301020001020104001000320301020101020105C350000003010201010202030028000003010200010201030032003203010201010202059C4000000301020101010206002800000301020001010201003C00320301020101010206003200000301020101010204000C000003010200010101010050003203010201010101059C40000003010201010101030032000003010200010101040010003203010001010101060032000003010001010102030028000003010001010101010050003203010000010102059C4000000301000001010206002800000301000001010010") + } else { + data = []byte{0x00, 0x00, 0x00, 0x00} + s.logger.Info("GET_TENROUIRAI request for unknown type") + } + if err != nil { + panic(err) + } + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfPostTenrouirai(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPostTenrouirai) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetDailyMissionMaster(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetDailyMissionPersonal(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfSetDailyMissionPersonal(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetEquipSkinHist(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetEquipSkinHist) + // Transmog / reskin system, bitmask of 3200 bytes length + // presumably divided by 5 sections for 5120 armour IDs covered + // +10,000 for actual ID to be unlocked by each bit + // Returning 3200 bytes of FF just unlocks everything for now + var data []byte + err := s.server.db.QueryRow("SELECT COALESCE(skin_hist::bytea, $2::bytea) FROM characters WHERE id = $1", s.charID, make([]byte, 0xC80)).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get skin_hist savedata from db", zap.Error(err)) + } + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfUpdateEquipSkinHist(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfUpdateEquipSkinHist) + // sends a raw armour ID back that needs to be mapped into the persistent bitmask above (-10,000) + var data []byte + err := s.server.db.QueryRow("SELECT COALESCE(skin_hist, $2) FROM characters WHERE id = $1", s.charID, make([]byte, 0xC80)).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get skin_hist from db", zap.Error(err)) + } + + var bit int + var startByte int + switch pkt.MogType { + case 0: // legs + bit = int(pkt.ArmourID) - 10000 + startByte = 0 + case 1: + bit = int(pkt.ArmourID) - 10000 + startByte = 640 + case 2: + bit = int(pkt.ArmourID) - 10000 + startByte = 1280 + case 3: + bit = int(pkt.ArmourID) - 10000 + startByte = 1920 + case 4: + bit = int(pkt.ArmourID) - 10000 + startByte = 2560 + } + // psql set_bit could also work but I couldn't get it working + byteInd := (bit / 8) + bitInByte := bit % 8 + data[startByte+byteInd] |= bits.Reverse8((1 << uint(bitInByte))) + _, err = s.server.db.Exec("UPDATE characters SET skin_hist=$1 WHERE id=$2", data, s.charID) + if err != nil { + panic(err) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetUdShopCoin(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdShopCoin) + data, _ := hex.DecodeString("0000000000000001") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfUseUdShopCoin(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetEnhancedMinidata(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetEnhancedMinidata) + // this looks to be the detailed chunk of information you can pull up on players in town + var data []byte + err := s.server.db.QueryRow("SELECT minidata FROM characters WHERE id = $1", pkt.CharID).Scan(&data) + if err != nil { + data = make([]byte, 0x400) // returning empty might avoid a client softlock + //s.logger.Fatal("Failed to get minidata from db", zap.Error(err)) + } + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfSetEnhancedMinidata(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSetEnhancedMinidata) + _, err := s.server.db.Exec("UPDATE characters SET minidata=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + if err != nil { + s.logger.Fatal("Failed to update minidata in db", zap.Error(err)) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetLobbyCrowd(s *Session, p mhfpacket.MHFPacket) { + // this requests a specific server's population but seems to have been + // broken at some point on live as every example response across multiple + // servers sends back the exact same information? + // It can be worried about later if we ever get to the point where there are + // full servers to actually need to migrate people from and empty ones to + pkt := p.(*mhfpacket.MsgMhfGetLobbyCrowd) + blankData := make([]byte, 0x320) + doAckBufSucceed(s, pkt.AckHandle, blankData) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetTrendWeapon(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetTrendWeapon) + // TODO (Fist): Work out actual format limitations, seems to be final upgrade + // for weapons and it traverses its upgrade tree to recommend base as final + // 423C correlates with most popular magnet spike in use on JP + // 2A 00 3C 44 00 3C 76 00 3F EA 01 0F 20 01 0F 50 01 0F F8 02 3C 7E 02 3D + // F3 02 40 2A 03 3D 65 03 3F 2A 03 40 36 04 3D 59 04 41 E7 04 43 3E 05 0A + // ED 05 0F 4C 05 0F F2 06 3A FE 06 41 E8 06 41 FA 07 3B 02 07 3F ED 07 40 + // 24 08 3D 37 08 3F 66 08 41 EC 09 3D 38 09 3F 8A 09 41 EE 0A 0E 78 0A 0F + // AA 0A 0F F9 0B 3E 2E 0B 41 EF 0B 42 FB 0C 41 F0 0C 43 3F 0C 43 EE 0D 41 F1 0D 42 10 0D 42 3C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0xA9)) +} + +func handleMsgMhfUpdateUseTrendWeaponLog(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfUpdateUseTrendWeaponLog) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} diff --git a/Erupe/server/channelserver/handlers_achievement.go b/Erupe/server/channelserver/handlers_achievement.go new file mode 100644 index 000000000..ccafb826c --- /dev/null +++ b/Erupe/server/channelserver/handlers_achievement.go @@ -0,0 +1,104 @@ +package channelserver + +import ( + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network/mhfpacket" +) + +func handleMsgMhfGetAchievement(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetAchievement) + + achievementStruct := []struct { + ID uint8 // Main ID + Unk0 uint8 // always FF + Unk1 uint16 // 0x05 0x00 + Unk2 uint32 // 0x01 0x0A 0x05 0x00 + }{ + {ID: 0, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 1, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 2, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 3, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 4, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 5, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 6, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 7, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 8, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 9, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 10, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 11, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 12, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 13, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 14, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 15, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 16, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 17, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 18, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 19, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 20, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 21, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 22, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 23, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 24, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 25, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 26, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 27, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 28, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 29, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 30, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 31, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 32, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 33, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 34, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 35, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 36, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 37, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 38, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 39, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 40, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 41, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 42, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 43, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 44, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 45, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 46, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 47, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 48, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 49, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 50, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 51, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 52, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 53, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 54, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 55, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 56, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 57, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 58, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + {ID: 59, Unk0: 0xFF, Unk1: 0, Unk2: 0}, + } + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(len(achievementStruct))) // Entry count + for _, entry := range achievementStruct { + resp.WriteUint8(entry.ID) + resp.WriteUint8(entry.Unk0) + resp.WriteUint16(entry.Unk1) + resp.WriteUint32(entry.Unk2) + } + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfSetCaAchievementHist(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSetCaAchievementHist) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfResetAchievement(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAddAchievement(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfPaymentAchievement(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfDisplayedAchievement(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetCaAchievementHist(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfSetCaAchievement(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_campaign.go b/Erupe/server/channelserver/handlers_campaign.go new file mode 100644 index 000000000..e1a8be1c6 --- /dev/null +++ b/Erupe/server/channelserver/handlers_campaign.go @@ -0,0 +1,18 @@ +package channelserver + +import "github.com/Solenataris/Erupe/network/mhfpacket" + +func handleMsgMhfEnumerateCampaign(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateCampaign) + doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfStateCampaign(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfStateCampaign) + doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfApplyCampaign(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfApplyCampaign) + doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} diff --git a/Erupe/server/channelserver/handlers_caravan.go b/Erupe/server/channelserver/handlers_caravan.go new file mode 100644 index 000000000..29fbb841d --- /dev/null +++ b/Erupe/server/channelserver/handlers_caravan.go @@ -0,0 +1,11 @@ +package channelserver + +import ( + "github.com/Solenataris/Erupe/network/mhfpacket" +) + +func handleMsgMhfCaravanMyScore(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfCaravanRanking(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfCaravanMyRank(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_cast_binary.go b/Erupe/server/channelserver/handlers_cast_binary.go new file mode 100644 index 000000000..0d2d3f37e --- /dev/null +++ b/Erupe/server/channelserver/handlers_cast_binary.go @@ -0,0 +1,146 @@ +package channelserver + +import ( + "fmt" + "strings" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network/binpacket" + "github.com/Solenataris/Erupe/network/mhfpacket" +) + +// MSG_SYS_CAST[ED]_BINARY types enum +const ( + BinaryMessageTypeState = 0 + BinaryMessageTypeChat = 1 + BinaryMessageTypeMailNotify = 4 + BinaryMessageTypeEmote = 6 +) + +// MSG_SYS_CAST[ED]_BINARY broadcast types enum +const ( + BroadcastTypeTargeted = 0x01 + BroadcastTypeStage = 0x03 + BroadcastTypeWorld = 0x0a +) + +func sendServerChatMessage(s *Session, message string) { + // Make the inside of the casted binary + bf := byteframe.NewByteFrame() + bf.SetLE() + msgBinChat := &binpacket.MsgBinChat{ + Unk0: 0, + Type: 5, + Flags: 0x80, + Message: message, + SenderName: "Erupe", + } + msgBinChat.Build(bf) + + castedBin := &mhfpacket.MsgSysCastedBinary{ + CharID: s.charID, + MessageType: BinaryMessageTypeChat, + RawDataPayload: bf.Data(), + } + + s.QueueSendMHF(castedBin) +} + +func handleMsgSysCastBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysCastBinary) + + // Parse out the real casted binary payload + var realPayload []byte + var msgBinTargeted *binpacket.MsgBinTargeted + if pkt.BroadcastType == BroadcastTypeTargeted { + bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload) + msgBinTargeted = &binpacket.MsgBinTargeted{} + err := msgBinTargeted.Parse(bf) + + if err != nil { + s.logger.Warn("Failed to parse targeted cast binary") + return + } + + realPayload = msgBinTargeted.RawDataPayload + } else { + realPayload = pkt.RawDataPayload + } + + // Make the response to forward to the other client(s). + resp := &mhfpacket.MsgSysCastedBinary{ + CharID: s.charID, + BroadcastType: pkt.BroadcastType, // (The client never uses Type0 upon receiving) + MessageType: pkt.MessageType, + RawDataPayload: realPayload, + } + + // Send to the proper recipients. + switch pkt.BroadcastType { + case BroadcastTypeWorld: + s.server.BroadcastMHF(resp, s) + case BroadcastTypeStage: + s.stage.BroadcastMHF(resp, s) + case BroadcastTypeTargeted: + for _, targetID := range (*msgBinTargeted).TargetCharIDs { + char := s.server.FindSessionByCharID(targetID) + + if char != nil { + char.QueueSendMHF(resp) + } + } + default: + s.Lock() + haveStage := s.stage != nil + if haveStage { + s.stage.BroadcastMHF(resp, s) + } + s.Unlock() + } + + // Handle chat + if pkt.MessageType == BinaryMessageTypeChat { + bf := byteframe.NewByteFrameFromBytes(realPayload) + + // IMPORTANT! Casted binary objects are sent _as they are in memory_, + // this means little endian for LE CPUs, might be different for PS3/PS4/PSP/XBOX. + bf.SetLE() + + chatMessage := &binpacket.MsgBinChat{} + chatMessage.Parse(bf) + + fmt.Printf("Got chat message: %+v\n", chatMessage) + + // Discord integration + if s.server.erupeConfig.Discord.Enabled { + message := fmt.Sprintf("%s: %s", chatMessage.SenderName, chatMessage.Message) + s.server.discordSession.ChannelMessageSend(s.server.erupeConfig.Discord.ChannelID, message) + } + + if strings.HasPrefix(chatMessage.Message, "!tele ") { + var x, y int16 + n, err := fmt.Sscanf(chatMessage.Message, "!tele %d %d", &x, &y) + if err != nil || n != 2 { + sendServerChatMessage(s, "Invalid command. Usage:\"!tele 500 500\"") + } else { + sendServerChatMessage(s, fmt.Sprintf("Teleporting to %d %d", x, y)) + + // Make the inside of the casted binary + payload := byteframe.NewByteFrame() + payload.SetLE() + payload.WriteUint8(2) // SetState type(position == 2) + payload.WriteInt16(x) // X + payload.WriteInt16(y) // Y + payloadBytes := payload.Data() + + s.QueueSendMHF(&mhfpacket.MsgSysCastedBinary{ + CharID: s.charID, + MessageType: BinaryMessageTypeState, + RawDataPayload: payloadBytes, + }) + } + } + } +} + +func handleMsgSysCastedBinary(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_character.go b/Erupe/server/channelserver/handlers_character.go new file mode 100644 index 000000000..e8a83ee2b --- /dev/null +++ b/Erupe/server/channelserver/handlers_character.go @@ -0,0 +1,143 @@ +package channelserver + +import ( + "database/sql" + "encoding/binary" + + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Solenataris/Erupe/server/channelserver/compression/nullcomp" + "go.uber.org/zap" +) + +const ( + CharacterSaveRPPointer = 0x22D16 +) + +type CharacterSaveData struct { + CharID uint32 + Name string + RP uint16 + IsNewCharacter bool + + // Use provided setter/getter + baseSaveData []byte +} + +func GetCharacterSaveData(s *Session, charID uint32) (*CharacterSaveData, error) { + result, err := s.server.db.Query("SELECT id, savedata, is_new_character, name FROM characters WHERE id = $1", charID) + + if err != nil { + s.logger.Error("failed to retrieve save data for character", zap.Error(err), zap.Uint32("charID", charID)) + return nil, err + } + + defer result.Close() + + saveData := &CharacterSaveData{} + var compressedBaseSave []byte + + if !result.Next() { + s.logger.Error("no results found for character save data", zap.Uint32("charID", charID)) + return nil, err + } + + err = result.Scan(&saveData.CharID, &compressedBaseSave, &saveData.IsNewCharacter, &saveData.Name) + + if err != nil { + s.logger.Error( + "failed to retrieve save data for character", + zap.Error(err), + zap.Uint32("charID", charID), + ) + + return nil, err + } + + if compressedBaseSave == nil { + return saveData, nil + } + + decompressedBaseSave, err := nullcomp.Decompress(compressedBaseSave) + + if err != nil { + s.logger.Error("Failed to decompress savedata from db", zap.Error(err)) + return nil, err + } + + saveData.SetBaseSaveData(decompressedBaseSave) + + return saveData, nil +} + +func (save *CharacterSaveData) Save(s *Session, transaction *sql.Tx) error { + // We need to update the save data byte array before we save it back to the DB + save.updateSaveDataWithStruct() + + compressedData, err := save.CompressedBaseData(s) + + if err != nil { + return err + } + + updateSQL := "UPDATE characters SET savedata=$1, is_new_character=$3 WHERE id=$2" + + if transaction != nil { + _, err = transaction.Exec(updateSQL, compressedData, save.CharID, save.IsNewCharacter) + } else { + _, err = s.server.db.Exec(updateSQL, compressedData, save.CharID, save.IsNewCharacter) + } + if err != nil { + s.logger.Error("failed to save character data", zap.Error(err), zap.Uint32("charID", save.CharID)) + return err + } + return nil +} + +func (save *CharacterSaveData) CompressedBaseData(s *Session) ([]byte, error) { + compressedData, err := nullcomp.Compress(save.baseSaveData) + + if err != nil { + s.logger.Error("failed to compress saveData", zap.Error(err), zap.Uint32("charID", save.CharID)) + return nil, err + } + return compressedData, nil +} + +func (save *CharacterSaveData) BaseSaveData() []byte { + return save.baseSaveData +} + +func (save *CharacterSaveData) SetBaseSaveData(data []byte) { + save.baseSaveData = data + // After setting the new save byte array, we can extract the values to update our struct + // This will be useful when we save it back, we use the struct values to overwrite the saveData + save.updateStructWithSaveData() +} + +// This will update the save struct with the values stored in the raw savedata arrays +func (save *CharacterSaveData) updateSaveDataWithStruct() { + rpBytes := make([]byte, 2) + binary.LittleEndian.PutUint16(rpBytes, save.RP) + copy(save.baseSaveData[CharacterSaveRPPointer:CharacterSaveRPPointer+2], rpBytes) +} + +// This will update the character save struct with the values stored in the raw savedata arrays +func (save *CharacterSaveData) updateStructWithSaveData() { + save.RP = binary.LittleEndian.Uint16(save.baseSaveData[CharacterSaveRPPointer : CharacterSaveRPPointer+2]) +} + +func handleMsgMhfSexChanger(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSexChanger) + if pkt.Gender == 0 { + _, err := s.server.db.Exec("UPDATE characters SET is_female=true WHERE id=$1", s.charID) + if err != nil { + s.logger.Fatal("Failed to update gender in db", zap.Error(err)) + } + } else { + _, err := s.server.db.Exec("UPDATE characters SET is_female=false WHERE id=$1", s.charID) + if err != nil { + s.logger.Fatal("Failed to update gender in db", zap.Error(err)) + } + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} diff --git a/Erupe/server/channelserver/handlers_clients.go b/Erupe/server/channelserver/handlers_clients.go new file mode 100644 index 000000000..c9eb206ad --- /dev/null +++ b/Erupe/server/channelserver/handlers_clients.go @@ -0,0 +1,66 @@ +package channelserver + +import ( + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" +) + +func handleMsgSysEnumerateClient(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysEnumerateClient) + + // Read-lock the stages map. + s.server.stagesLock.RLock() + + stage, ok := s.server.stages[pkt.StageID] + if !ok { + s.logger.Fatal("Can't enumerate clients for stage that doesn't exist!", zap.String("stageID", pkt.StageID)) + } + + // Unlock the stages map. + s.server.stagesLock.RUnlock() + + // Read-lock the stage and make the response with all of the charID's in the stage. + resp := byteframe.NewByteFrame() + stage.RLock() + + // TODO(Andoryuuta): Is only the reservations needed? Do clients send this packet for mezeporta as well? + + // Make a map to deduplicate the charIDs between the unreserved clients and the reservations. + deduped := make(map[uint32]interface{}) + + // Add the charIDs + for session := range stage.clients { + deduped[session.charID] = nil + } + + for charid := range stage.reservedClientSlots { + deduped[charid] = nil + } + + // Write the deduplicated response + resp.WriteUint16(uint16(len(deduped))) // Client count + for charid := range deduped { + resp.WriteUint32(charid) + } + + stage.RUnlock() + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + s.logger.Debug("MsgSysEnumerateClient Done!") +} + +func handleMsgMhfListMember(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfListMember) + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) // Members count. (Unsure of what kind of members these actually are, guild, party, COG subscribers, etc.) + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfOprMember(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfShutClient(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysHideClient(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_data.go b/Erupe/server/channelserver/handlers_data.go new file mode 100644 index 000000000..0727809e2 --- /dev/null +++ b/Erupe/server/channelserver/handlers_data.go @@ -0,0 +1,177 @@ +package channelserver + +import ( + "encoding/hex" + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Solenataris/Erupe/server/channelserver/compression/deltacomp" + "github.com/Solenataris/Erupe/server/channelserver/compression/nullcomp" + "go.uber.org/zap" +) + +func handleMsgMhfSavedata(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSavedata) + characterSaveData, err := GetCharacterSaveData(s, s.charID) + if err != nil { + s.logger.Error("failed to retrieve character save data from db", zap.Error(err), zap.Uint32("charID", s.charID)) + return + } + // Var to hold the decompressed savedata for updating the launcher response fields. + var decompressedData []byte + if pkt.SaveType == 1 { + // Diff-based update. + // diffs themselves are also potentially compressed + diff, err := nullcomp.Decompress(pkt.RawDataPayload) + if err != nil { + s.logger.Fatal("Failed to decompress diff", zap.Error(err)) + } + // Perform diff. + characterSaveData.SetBaseSaveData(deltacomp.ApplyDataDiff(diff, characterSaveData.BaseSaveData())) + s.logger.Info("Diffing...") + } else { + // Regular blob update. + saveData, err := nullcomp.Decompress(pkt.RawDataPayload) + + characterSaveData.SetBaseSaveData(saveData) + if err != nil { + s.logger.Fatal("Failed to decompress savedata from packet", zap.Error(err)) + } + s.logger.Info("Updating save with blob") + } + characterSaveData.IsNewCharacter = false + characterBaseSaveData := characterSaveData.BaseSaveData() + // Make a copy for updating the launcher fields. + decompressedData = make([]byte, len(characterBaseSaveData)) + copy(decompressedData, characterBaseSaveData) + err = characterSaveData.Save(s, nil) + if err != nil { + s.logger.Fatal("Failed to update savedata in db", zap.Error(err)) + } + s.logger.Info("Wrote recompressed savedata back to DB.") + dumpSaveData(s, pkt.RawDataPayload, "") + // Temporary server launcher response stuff + // 0x1F715 Weapon Class + // 0x1FDF6 HR (small_gr_level) + // 0x88 Character Name + _, err = s.server.db.Exec("UPDATE characters SET weapon=$1 WHERE id=$2", uint16(decompressedData[128789]), s.charID) + if err != nil { + s.logger.Fatal("Failed to character weapon in db", zap.Error(err)) + } + gr := uint16(decompressedData[130550])<<8 | uint16(decompressedData[130551]) + s.logger.Info("Setting db field", zap.Uint16("gr_override_level", gr)) + // We have to use `gr_override_level` (uint16), not `small_gr_level` (uint8) to store this. + _, err = s.server.db.Exec("UPDATE characters SET gr_override_mode=true, gr_override_level=$1 WHERE id=$2", gr, s.charID) + if err != nil { + s.logger.Fatal("Failed to update character gr_override_level in db", zap.Error(err)) + } + characterName := s.clientContext.StrConv.MustDecode(bfutil.UpToNull(decompressedData[88:100])) + _, err = s.server.db.Exec("UPDATE characters SET name=$1 WHERE id=$2", characterName, s.charID) + if err != nil { + s.logger.Fatal("Failed to update character name in db", zap.Error(err)) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func dumpSaveData(s *Session, data []byte, suffix string) { + if !s.server.erupeConfig.DevModeOptions.SaveDumps.Enabled { + return + } else { + dir := filepath.Join(s.server.erupeConfig.DevModeOptions.SaveDumps.OutputDir, fmt.Sprintf("%s_",s.Name)) + path := filepath.Join(s.server.erupeConfig.DevModeOptions.SaveDumps.OutputDir, fmt.Sprintf("%s_",s.Name), fmt.Sprintf("%d_%s_%s%s.bin", s.charID, s.Name, Time_Current().Format("2006-01-02_15.04.05"), suffix)) + + if _, err := os.Stat(dir); os.IsNotExist(err) { + os.Mkdir(dir, os.ModeDir) + } + err := ioutil.WriteFile(path, data, 0644) + if err != nil { + s.logger.Fatal("Error dumping savedata", zap.Error(err)) + } + } +} + +func handleMsgMhfLoaddata(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoaddata) + overrideFile := filepath.Join(".", "bin", "save_override.bin") + var data []byte + + if _, err := os.Stat(overrideFile); err == nil { + file, err := os.Open(overrideFile) + if err != nil { + panic(err) + } + data, err := ioutil.ReadAll(file) + if err != nil { + panic(err) + } + doAckBufSucceed(s, pkt.AckHandle, data) + } + + err := s.server.db.QueryRow("SELECT savedata FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get savedata from db", zap.Error(err)) + } + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfSaveScenarioData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSaveScenarioData) + + // Do this ack manually because it uses a non-(0|1) error code + s.QueueSendMHF(&mhfpacket.MsgSysAck{ + AckHandle: pkt.AckHandle, + IsBufferResponse: false, + ErrorCode: 0x40, + AckData: []byte{0x00, 0x00, 0x00, 0x40}, + }) +} + +func handleMsgMhfLoadScenarioData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadScenarioData) + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetPaperData(s *Session, p mhfpacket.MHFPacket) { + // if the game gets bad responses for this it breaks the ability to save + pkt := p.(*mhfpacket.MsgMhfGetPaperData) + var data []byte + var err error + if pkt.Unk2 == 4 { + data, err = hex.DecodeString("0A218EAD000000000000000000000000") + } else if pkt.Unk2 == 5 { + data, err = hex.DecodeString("0A218EAD00000000000000000000003403E900010000000000000000000003E900020000000000000000000003EB00010064006400C80064000003EB00020096006400F00064000003EC000A270F002800000000000003ED000A01F4000000000000000003EF00010000000000000000000003F000C801900BB801900BB8000003F200010FA0000000000000000003F200020FA0000000000000000003F3000117703A984E2061A8753003F3000217703A984E2061A8753003F400011F40445C57E46B6C791803F400021F40445C57E46B6C791803F700010010001000100000000003F7000200100010001000000000044D000107E001F4000000000000044D000207E001F4000000000000044F0001000000000BB800000BB8044F0002000000000BB800000BB804500001000A270F00280000000004500002000A270F00280000000004510001000A01F400000000000004510002000A01F400000000000007D100010011003A0000000602BC07D100010014003A0000000300C807D100010016003A0000000700FA07D10001001B003A00000001006407D100010035003A0000000803E807D100010043003A0000000901F407D100010044003A00000002009607D10001004A003A0000000400C807D10001004B003A0000000501F407D10001004C003A0000000A032007D100010050003A0000000B038407D100010059003A0000000C025807D100020011003C0000000602BC07D100020014003C0000000300C807D100020016003C00000007015E07D10002001B003C00000001006407D100020027003C0000000D00C807D100020028003C0000000F025807D100020035003C0000000803E807D100020043003C0000000201F407D100020044003C00000009009607D10002004A003C0000000400C807D10002004B003C0000000501F407D10002004C003C0000000A032007D100020050003C0000000B038407D100020051003C0000000E038407D100020059003C0000000C025807D10002005E003C0000001003E8") + } else if pkt.Unk2 == 6 { + data, err = hex.DecodeString("0A218EAD0000000000000000000001A503EA00640000000000000000000003EE00012710271000000000000003EE000227104E2000000000000003F100140000000000000000000003F5000100010001006400C8012C03F5000100010002006400C8012C03F5000100020001012C006400C803F5000100020002012C006400C803F500010003000100C8012C006403F500010003000200C8012C006403F5000200010001012C006400C803F5000200010002012C006400C803F500020002000100C8012C006403F500020002000200C8012C006403F5000200030001006400C8012C03F5000200030002006400C8012C03F500030001000100C8012C006403F500030001000200C8012C006403F5000300020001006400C8012C03F5000300020002006400C8012C03F5000300030001012C006400C803F5000300030002012C006400C803F800010001005000000000000003F800010002005000000000000003F800010003005000000000000003F800020001005000000000000003F800020002005000000000000003F800020003005000000000000004B10001003C003200000000000004B10002003C003200000000000004B200010000000500320000000004B2000100060014003C0000000004B200010015002800460000000004B200010029007800500000000004B20001007900A0005A0000000004B2000100A100FA00640000000004B2000100FB01F400640000000004B2000101F5270F00640000000004B200020000006400640000000004B20002006500C800640000000004B2000200C901F400960000000004B2000201F5270F00960000000004B3000100000005000A0000000004B300010006000A00140000000004B30001000B001E001E0000000004B30001001F003C00280000000004B30001003D007800320000000004B3000100790082003C0000000004B300010083008C00460000000004B30001008D009600500000000004B30001009700A000550000000004B3000100A100C800640000000004B3000100C901F400640000000004B3000101F5270F00640000000004B300020000007800460000000004B30002007901F400780000000004B3000201F5270F00780000000004B4000100000005000F0000000004B400010006000A00140000000004B40001000B000F00190000000004B4000100100014001B0000000004B4000100150019001E0000000004B40001001A001E00200000000004B40001001F002800230000000004B400010029003200250000000004B400010033003C00280000000004B40001003D0046002B0000000004B4000100470050002D0000000004B400010051005A002F0000000004B40001005B006400320000000004B400010065006E003C0000000004B40001006F007800460000000004B4000100790082004B0000000004B400010083008C00520000000004B40001008D00A000550000000004B4000100A100C800640000000004B4000100C901F400640000000004B4000101F5270F00640000000004B400020000007800460000000004B40002007901F400780000000004B4000201F5270F0078000000000FA10001000000000000000000000FA10002000029AB0005000000010FA10002000029AB0005000000010FA10002000029AB0005000000010FA10002000029AB0005000000010FA10002000029AC0002000000010FA10002000029AC0002000000010FA10002000029AC0002000000010FA10002000029AC0002000000010FA10002000029AD0001000000010FA10002000029AD0001000000010FA10002000029AD0001000000010FA10002000029AD0001000000010FA10002000029AF0003000000010FA10002000029AF0003000000010FA10002000029AF0003000000010FA10002000029AF0003000000010FA10002000028900001000000010FA10002000028900001000000010FA10002000029AE0002000000010FA10002000029AE0002000000010FA10002000029BA0002000000010FA10002000029BB0002000000010FA10002000029B60001000000010FA10002000029B60001000000010FA5000100002B970001138800010FA5000100002B9800010D1600010FA5000100002B99000105DC00010FA5000100002B9A0001006400010FA5000100002B9B0001003200010FA5000200002B970002070800010FA5000200002B98000204B000010FA5000200002B99000201F400010FA5000200002B9A0001003200010FA5000200002B1D0001009600010FA5000200002B1E0001009600010FA5000200002B240001009600010FA5000200002B310001009600010FA5000200002B330001009600010FA5000200002B470001009600010FA5000200002B5A0001009600010FA5000200002B600001009600010FA5000200002B6D0001009600010FA5000200002B780001009600010FA5000200002B7D0001009600010FA5000200002B810001009600010FA5000200002B870001009600010FA5000200002B7C0001009600010FA5000200002B1F0001009600010FA5000200002B200001009600010FA5000200002B290001009600010FA5000200002B350001009600010FA5000200002B370001009600010FA5000200002B450001009600010FA5000200002B5B0001009600010FA5000200002B610001009600010FA5000200002B790001009600010FA5000200002B7A0001009600010FA5000200002B7B0001009600010FA5000200002B830001009600010FA5000200002B890001009600010FA5000200002B580001009600010FA5000200002B210001009600010FA5000200002B270001009600010FA5000200002B2E0001009600010FA5000200002B390001009600010FA5000200002B3C0001009600010FA5000200002B430001009600010FA5000200002B5C0001009600010FA5000200002B620001009600010FA5000200002B6F0001009600010FA5000200002B7F0001009600010FA5000200002B800001009600010FA5000200002B820001009600010FA5000200002B500001009600010FA50002000028820001009600010FA50002000028800001009600010FA6000100002B970001138800010FA6000100002B9800010D1600010FA6000100002B99000105DC00010FA6000100002B9A0001006400010FA6000100002B9B0001003200010FA6000200002B970002070800010FA6000200002B98000204B000010FA6000200002B99000201F400010FA6000200002B9A0001003200010FA6000200002B1D0001009600010FA6000200002B1E0001009600010FA6000200002B240001009600010FA6000200002B310001009600010FA6000200002B330001009600010FA6000200002B470001009600010FA6000200002B5A0001009600010FA6000200002B600001009600010FA6000200002B6D0001009600010FA6000200002B780001009600010FA6000200002B7D0001009600010FA6000200002B810001009600010FA6000200002B870001009600010FA6000200002B7C0001009600010FA6000200002B1F0001009600010FA6000200002B200001009600010FA6000200002B290001009600010FA6000200002B350001009600010FA6000200002B370001009600010FA6000200002B450001009600010FA6000200002B5B0001009600010FA6000200002B610001009600010FA6000200002B790001009600010FA6000200002B7A0001009600010FA6000200002B7B0001009600010FA6000200002B830001009600010FA6000200002B890001009600010FA6000200002B580001009600010FA6000200002B210001009600010FA6000200002B270001009600010FA6000200002B2E0001009600010FA6000200002B390001009600010FA6000200002B3C0001009600010FA6000200002B430001009600010FA6000200002B5C0001009600010FA6000200002B620001009600010FA6000200002B6F0001009600010FA6000200002B7F0001009600010FA6000200002B800001009600010FA6000200002B820001009600010FA6000200002B500001009600010FA60002000028820001009600010FA60002000028800001009600010FA7000100002B320001004600010FA7000100002B340001004600010FA7000100002B360001004600010FA7000100002B380001004600010FA7000100002B3A0001004600010FA7000100002B6E0001004600010FA7000100002B700001004600010FA7000100002B660001004600010FA7000100002B680001004600010FA7000100002B6A0001004600010FA7000100002B220001004600010FA7000100002B230001004600010FA7000100002B420001004600010FA7000100002B840001004600010FA7000100002B3B0001004600010FA7000100002B280001004600010FA7000100002B260001004600010FA7000100002B5F0001004600010FA7000100002B630001004600010FA7000100002B640001004600010FA7000100002B710001004600010FA7000100002B7E0001004600010FA7000100002B4C0001004600010FA7000100002B4D0001004600010FA7000100002B4E0001004600010FA7000100002B4F0001004600010FA7000100002B560001004600010FA7000100002B570001004600010FA70001000028860001004600010FA70001000028870001004600010FA70001000028880001004600010FA70001000028890001004600010FA700010000288A0001004600010FA7000100002B3D0001002D00010FA7000100002B3F0001002D00010FA7000100002B410001002D00010FA7000100002B440001002D00010FA7000100002B460001002D00010FA7000100002B6C0001002D00010FA7000100002B730001002D00010FA7000100002B770001002D00010FA7000100002B860001002D00010FA7000100002B300001002D00010FA7000100002B520001002D00010FA7000100002B590001002D00010FA700010000287F0001002D00010FA70001000028830001002D00010FA70001000028850001002D00010FA7000100002B480001000F00010FA7000100002B490001000F00010FA7000100002B4B0001000F00010FA7000100002B750001000F00010FA7000100002B550001000E00010FA7000100002B2D0001000A00010FA7000100002B8B0001000A00010FA70001000028840001000500010FA70001000028810001000100010FA7000100002B9B0001009600010FA7000100002CC90001003200010FA7000100002CCA0001001900010FA7000100002CCB000100C800010FA7000100002CCC0001019000010FA7000100002CCD0001009600010FA7000100002B1D0001005C00010FA7000100002B1E0001005C00010FA7000100002B240001005C00010FA7000100002B310001005C00010FA7000100002B330001005C00010FA7000100002B470001005C00010FA7000100002B5A0001005C00010FA7000100002B600001005C00010FA7000100002B6D0001005C00010FA7000100002B7D0001005C00010FA7000100002B810001005C00010FA7000100002B870001005C00010FA7000100002B7C0001005C00010FA7000100002B1F0001005C00010FA7000100002B200001005C00010FA7000100002B290001005C00010FA7000100002B350001005C00010FA7000100002B370001005C00010FA7000100002B450001005C00010FA7000100002B5B0001005C00010FA7000100002B610001005C00010FA7000100002B790001005C00010FA7000100002B7A0001005C00010FA7000100002B7B0001005C00010FA7000100002B830001005C00010FA7000100002B890001005B00010FA7000100002B580001005B00010FA7000100002B210001005B00010FA7000100002B270001005B00010FA7000100002B2E0001005B00010FA7000100002B390001005B00010FA7000100002B3C0001005B00010FA7000100002B430001005B00010FA7000100002B5C0001005B00010FA7000100002B620001005B00010FA7000100002B6F0001005B00010FA7000100002B7F0001005B00010FA7000100002B800001005B00010FA7000100002B820001005B00010FA7000100002B500001005B00010FA70001000028820001005B00010FA70001000028800001005B00010FA7000100002B250001005B00010FA7000100002B3E0001005B00010FA7000100002B5D0001005B00010FA7000100002B650001005B00010FA7000100002B720001005B00010FA7000100002B850001005B00010FA7000100002B2B0001005B00010FA7000100002B5E0001005B00010FA7000100002B740001005B00010FA7000100002B400001005B00010FA7000100002B4A0001005B00010FA7000100002B6B0001005B00010FA7000100002B880001005B00010FA7000100002B510001005B00010FA7000100002B530001005B00010FA7000100002B540001005B00010FA7000100002B2A0001005B00010FA7000100002B670001005B00010FA7000100002B690001005B00010FA7000100002B760001005B00010FA7000100002B2F0001005B00010FA7000100002B2C0001005B00010FA7000100002B8A0001005B00010FA7000200002B320001005A00010FA7000200002B340001005A00010FA7000200002B360001005A00010FA7000200002B380001005A00010FA7000200002B3A0001005A00010FA7000200002B6E0001005A00010FA7000200002B700001005A00010FA7000200002B660001005A00010FA7000200002B680001005A00010FA7000200002B6A0001005A00010FA7000200002B220001005A00010FA7000200002B230001005A00010FA7000200002B420001005A00010FA7000200002B840001005A00010FA7000200002B3B0001005A00010FA7000200002B280001005A00010FA7000200002B260001005A00010FA7000200002B5F0001005A00010FA7000200002B630001005A00010FA7000200002B640001005A00010FA7000200002B710001005A00010FA7000200002B7E0001005A00010FA7000200002B4C0001005A00010FA7000200002B4D0001005A00010FA7000200002B4E0001005A00010FA7000200002B4F0001005A00010FA7000200002B560001005A00010FA7000200002B570001005A00010FA70002000028860001005A00010FA70002000028870001005A00010FA70002000028880001005A00010FA70002000028890001005A00010FA700020000288A0001005A00010FA7000200002B3D0001005000010FA7000200002B3F0001005000010FA7000200002B410001005000010FA7000200002B440001005000010FA7000200002B460001005000010FA7000200002B6C0001005000010FA7000200002B730001005000010FA7000200002B770001005000010FA7000200002B860001005000010FA7000200002B300001005000010FA7000200002B520001005000010FA7000200002B590001005000010FA700020000287F0001005000010FA70002000028830001005000010FA70002000028850001005000010FA7000200002B480001001600010FA7000200002B490001001600010FA7000200002B4B0001001600010FA7000200002B750001001600010FA7000200002B550001001600010FA7000200002B2D0001000F00010FA7000200002B8B0001000F00010FA70002000028840001000800010FA70002000028810001000200010FA7000200002B97000304C400010FA7000200002B980003028A00010FA7000200002B99000300A000010FA7000200002D8D0001032000010FA7000200002D8E0001032000010FA7000200002B9B000101F400010FA7000200002B9A0001022600010FA7000200002CC90001003200010FA7000200002CCA0001001900010FA7000200002CCB000100FA00010FA7000200002CCC000101F400010FA7000200002CCD000100AF0001106A000100002B9B000117700001106A000100002CC9000100C80001106A000100002CCA000100640001106A000100002CCB000103E80001106A000100002CCC000107D00001106A000100002CCD000102BC0001106A000200002D8D000103200001106A000200002D8E000103200001106A000200002B9B000101900001106A000200002CC9000101900001106A000200002CCA000100C80001106A000200002CCB000107D00001106A000200002CCC00010FA00001106A000200002CCD000105780001") + } else if pkt.Unk2 == 6001 { + data, err = hex.DecodeString("0A218EAD0000000000000000000000052B97010113882B9801010D162B99010105DC2B9A010100642B9B01010032") + } else if pkt.Unk2 == 6002 { + data, err = hex.DecodeString("0A218EAD00000000000000000000002F2B97020107082B98020104B02B99020101F42B9A010100322B1D010100962B1E010100962B24010100962B31010100962B33010100962B47010100962B5A010100962B60010100962B6D010100962B78010100962B7D010100962B81010100962B87010100962B7C010100962B1F010100962B20010100962B29010100962B35010100962B37010100962B45010100962B5B010100962B61010100962B79010100962B7A010100962B7B010100962B83010100962B89010100962B58010100962B21010100962B27010100962B2E010100962B39010100962B3C010100962B43010100962B5C010100962B62010100962B6F010100962B7F010100962B80010100962B82010100962B5001010096288201010096288001010096") + } else if pkt.Unk2 == 6010 { + data, err = hex.DecodeString("0A218EAD00000000000000000000000B2B9701010E742B9801010B542B99010105142CBD010100FA2CBE010100FA2F17010100FA2F21010100FA2F1A010100FA2F24010100FA2DFE010100C82DFD01010190") + } else if pkt.Unk2 == 6011 { + data, err = hex.DecodeString("0A218EAD00000000000000000000000B2B9701010E742B9801010B542B99010105142CBD010100FA2CBE010100FA2F17010100FA2F21010100FA2F1A010100FA2F24010100FA2DFE010100C82DFD01010190") + } else if pkt.Unk2 == 6012 { + data, err = hex.DecodeString("0A218EAD00000000000000000000000D2B9702010DAC2B9802010B542B990201051430DC010101902CBD010100C82CBE010100C82F17010100C82F21010100C82F1A010100C82F24010100C82DFF010101902E00010100C82E0101010064") + } else if pkt.Unk2 == 7001 { + data, err = hex.DecodeString("0A218EAD00000000000000000000009D2B1D010101222B1E0101010E2B240101010E2B31010101222B33010101222B47010101222B5A010101182B600101012C2B6D010101182B78010101222B7D010101222B810101012C2B87010101222B7C0101010E2B220101002F2B250101002F2B380101002F2B360101002F2B3E010100302B5D0101002F2B640101002F2B650101002F2B700101002F2B720101002F2B7E0101002F2B850101002F2B4C0101002F2B4F0101002F2B560101002F28860101002F28870101002F2B2B010100112B3F010100102B44010100102B5E010100112B74010100112B52010100112B97010104B02B970201028A2B98010103202B980201012C2B99010100642B99020100322B9C010100642B9A010100642B9B010100642B960101012C2CC70101012C2C5C0101012C2CC80101012C2C5D010101F42B1F0102012C2B200102010E2B290102012C2B35010201222B37010201222B45010201222B5B010201182B610102012C2B79010200FA2B7A0102012C2B7B010201182B83010201222B89010201042B580102012C2B260102002F2B3A0102002F2B3B0102002F2B400102002F2B4A0102002F2B5F0102002F2B660102002F2B680102002F2B6A0102002F2B6B0102002F2B710102002F2B88010200302B4D0102002F2B510102002F2B530102002F28880102002F28890102002F2B77010200112B3D010200112B86010200112B46010200112B30010200102B54010200102B97010204B02B970202028A2B98010203202B980202012C2B99010200642B99020200322B9C010200642B9A010200642B9B010200642B960102012C2CC70102012C2C5C0102012C2CC80102012C2C5D010201F42B210103010A2B270103010A2B2E0103010A2B390103010A2B3C0103010A2B430103010A2B5C0103010A2B620103010A2B6F0103010A2B7F0103010C2B800103010C2B820103010C2B500103010C28820103010A28800103010C2B23010300322B28010300322B2A010300322B32010300322B34010300322B42010300322B63010300322B67010300322B69010300322B6E010300322B76010300322B84010300322B4E010300322B57010300322B2F01030032288A010300322B2C0103000F2B410103000F2B8A0103000F2B6C0103000F2B730103000F2B590103000F287F0103000F28830103000F28850103000F2A1A010301772BC9010301772A3D010301772C7D010301772B97010303E82B97020300FA2B98010302BC2B98020300AF2B990103012C2B990203004B2CC9010300352CCA0103001B2CCB0103010A2CCC010302152CCD010300BA") + } else if pkt.Unk2 == 7002 { + data, err = hex.DecodeString("0A218EAD0000000000000000000000B92B1D010100642B1E010100642B24010100642B31010100642B33010100642B47010100642B5A010100642B60010100642B6D010100642B78010100642B7D010100642B81010100642B87010100642B7C010100642B220101003C2B250101003C2B380101003C2B360101003C2B3E0101003C2B5D0101003C2B640101003C2B650101003C2B700101003C2B720101003C2B7E0101003C2B850101003C2B4C0101003C2B4F0101003C2B560101003C28860101003C28870101003C2B2B010100142B3F010100142B44010100142B5E010100142B74010100142B52010100142B9C010101902B9A010100C82B9B010100C82CC7010100642CC80101009628730101009630DA010100C830DB0101012C30DC01010384353D0101015E353C010100C82C5C010100642C5D010100962EEE010100FA2EF0010101902EEF0101019A2B97020101F42B97040101F42B97060101F42B98020101902B98040101902B98060101902B99020100642B99040100642B99060100642B1F010200642B20010200642B29010200642B35010200642B37010200642B45010200642B5B010200642B61010200642B79010200642B7A010200642B7B010200642B83010200642B89010200642B58010200642B260102003C2B3A0102003C2B3B0102003C2B400102003C2B4A0102003C2B5F0102003C2B660102003C2B680102003C2B6A0102003C2B6B0102003C2B710102003C2B880102003C2B4D0102003C2B510102003C2B530102003C28880102003C28890102003C2B77010200142B3D010200142B86010200142B46010200142B30010200142B54010200142B9C010201902B9A010200C82B9B010200C82CC7010200FA2CC80102015E30DA0102009630DB010200C830DC0102015E353D010200FA353C010200C82873010201902B96010200642C5C010200642C5D010200642EEE0102012C2EF0010201C22EEF010201CC2B97020201F42B97040201F42B97060201F42B98020201902B98040201902B98060201902B99020200642B99040200642B99060200642B21010300782B27010300782B2E010300782B39010300782B3C010300782B43010300782B5C010300782B62010300782B6F010300782B7F010300782B80010300782B82010300782B50010300782882010300782880010300782B23010300412B28010300412B2A010300412B32010300412B34010300412B42010300412B63010300412B67010300412B69010300412B6E010300412B76010300412B84010300412B4E010300412B57010300412B2F01030041288A010300412B2C0103000F2B410103000F2B8A0103000F2B6C0103000F2B730103000F2B590103000F287F0103000F28830103000F28850103000F2A1A030301EA2BC9030301EA2A3D030301EA2C7D030301EA2F0E030301F430D7030301F42B97020301F42B97040301F42B97060301F42B98020301902B98040301902B98060301902B99020300642B99040300642B99060300642CC9010300352CCA0103001B2CCB0103010A2CCC010302152CCD010300BA") + } else if pkt.Unk2 == 7011 { + data, err = hex.DecodeString("0A218EAD00000000000000000000009D2B1D010101222B1E0101010E2B240101010E2B31010101222B33010101222B47010101222B5A010101182B600101012C2B6D010101182B78010101222B7D010101222B810101012C2B87010101222B7C0101010E2B220101002F2B250101002F2B380101002F2B360101002F2B3E010100302B5D0101002F2B640101002F2B650101002F2B700101002F2B720101002F2B7E0101002F2B850101002F2B4C0101002F2B4F0101002F2B560101002F28860101002F28870101002F2B2B010100112B3F010100102B44010100102B5E010100112B74010100112B52010100112B97010104B02B970201028A2B98010103202B980201012C2B99010100642B99020100322B9C010100642B9A010100642B9B010100642B960101012C2CC70101012C2C5C0101012C2CC80101012C2C5D010101F42B1F0102012C2B200102010E2B290102012C2B35010201222B37010201222B45010201222B5B010201182B610102012C2B79010200FA2B7A0102012C2B7B010201182B83010201222B89010201042B580102012C2B260102002F2B3A0102002F2B3B0102002F2B400102002F2B4A0102002F2B5F0102002F2B660102002F2B680102002F2B6A0102002F2B6B0102002F2B710102002F2B88010200302B4D0102002F2B510102002F2B530102002F28880102002F28890102002F2B77010200112B3D010200112B86010200112B46010200112B30010200102B54010200102B97010204B02B970202028A2B98010203202B980202012C2B99010200642B99020200322B9C010200642B9A010200642B9B010200642B960102012C2CC70102012C2C5C0102012C2CC80102012C2C5D010201F42B210103010A2B270103010A2B2E0103010A2B390103010A2B3C0103010A2B430103010A2B5C0103010A2B620103010A2B6F0103010A2B7F0103010C2B800103010C2B820103010C2B500103010C28820103010A28800103010C2B23010300322B28010300322B2A010300322B32010300322B34010300322B42010300322B63010300322B67010300322B69010300322B6E010300322B76010300322B84010300322B4E010300322B57010300322B2F01030032288A010300322B2C0103000F2B410103000F2B8A0103000F2B6C0103000F2B730103000F2B590103000F287F0103000F28830103000F28850103000F2A1A010301772BC9010301772A3D010301772C7D010301772B97010303E82B97020300FA2B98010302BC2B98020300AF2B990103012C2B990203004B2CC9010300352CCA0103001B2CCB0103010A2CCC010302152CCD010300BA") + } else if pkt.Unk2 == 7012 { + data, err = hex.DecodeString("0A218EAD00000000000000000000009D2B1D010101222B1E0101010E2B240101010E2B31010101222B33010101222B47010101222B5A010101182B600101012C2B6D010101182B78010101222B7D010101222B810101012C2B87010101222B7C0101010E2B220101002F2B250101002F2B380101002F2B360101002F2B3E010100302B5D0101002F2B640101002F2B650101002F2B700101002F2B720101002F2B7E0101002F2B850101002F2B4C0101002F2B4F0101002F2B560101002F28860101002F28870101002F2B2B010100112B3F010100102B44010100102B5E010100112B74010100112B52010100112B97010104B02B970201028A2B98010103202B980201012C2B99010100642B99020100322B9C010100642B9A010100642B9B010100642B960101012C2CC70101012C2C5C0101012C2CC80101012C2C5D010101F42B1F0102012C2B200102010E2B290102012C2B35010201222B37010201222B45010201222B5B010201182B610102012C2B79010200FA2B7A0102012C2B7B010201182B83010201222B89010201042B580102012C2B260102002F2B3A0102002F2B3B0102002F2B400102002F2B4A0102002F2B5F0102002F2B660102002F2B680102002F2B6A0102002F2B6B0102002F2B710102002F2B88010200302B4D0102002F2B510102002F2B530102002F28880102002F28890102002F2B77010200112B3D010200112B86010200112B46010200112B30010200102B54010200102B97010204B02B970202028A2B98010203202B980202012C2B99010200642B99020200322B9C010200642B9A010200642B9B010200642B960102012C2CC70102012C2C5C0102012C2CC80102012C2C5D010201F42B210103010A2B270103010A2B2E0103010A2B390103010A2B3C0103010A2B430103010A2B5C0103010A2B620103010A2B6F0103010A2B7F0103010C2B800103010C2B820103010C2B500103010C28820103010A28800103010C2B23010300322B28010300322B2A010300322B32010300322B34010300322B42010300322B63010300322B67010300322B69010300322B6E010300322B76010300322B84010300322B4E010300322B57010300322B2F01030032288A010300322B2C0103000F2B410103000F2B8A0103000F2B6C0103000F2B730103000F2B590103000F287F0103000F28830103000F28850103000F2A1A010301772BC9010301772A3D010301772C7D010301772B97010303E82B97020300FA2B98010302BC2B98020300AF2B990103012C2B990203004B2CC9010300352CCA0103001B2CCB0103010A2CCC010302152CCD010300BA") + } else { + data = []byte{0x00, 0x00, 0x00, 0x00} + s.logger.Info("GET_PAPER request for unknown type") + } + if err != nil { + panic(err) + } + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgSysAuthData(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_discord.go b/Erupe/server/channelserver/handlers_discord.go new file mode 100644 index 000000000..aaad2472a --- /dev/null +++ b/Erupe/server/channelserver/handlers_discord.go @@ -0,0 +1,163 @@ +package channelserver + +import ( + "fmt" + "os" + "strings" + "time" + + "github.com/bwmarrin/discordgo" +) + +// onDiscordMessage handles receiving messages from discord and forwarding them ingame. +func (s *Server) onDiscordMessage(ds *discordgo.Session, m *discordgo.MessageCreate) { + // Ignore messages from our bot, or ones that are not in the correct channel. + if m.Author.ID == ds.State.User.ID || m.ChannelID != s.erupeConfig.Discord.ChannelID { + return + } + + // Broadcast to the game clients. + data := m.Content + + // Split on comma. + result := strings.Split(data, " ") + + if result[0] == "!maintenancedate" && m.Author.ID == "836027554628370492" { + replaceDays := dayConvert(result[1]) + replaceMonth := MonthConvert(result[3]) + + s.BroadcastChatMessage("MAINTENANCE EXCEPTIONNELLE :") + s.BroadcastChatMessage("Les serveurs seront temporairement inaccessibles le") + s.BroadcastChatMessage(fmt.Sprintf("%s %s %s %s a partir de %s heures et %s minutes.", replaceDays, result[2], replaceMonth, result[4], result[5], result[6])) // Jour Mois Année Heures Minutes + s.BroadcastChatMessage("Evitez de vous connecter durant cette periode. Veuillez nous") + s.BroadcastChatMessage("excuser pour la gene occasionee. Merci de votre cooperation.") + return + } else if result[0] == "!maintenance" && m.Author.ID == "836027554628370492" { + s.BroadcastChatMessage("RAPPEL DE MAINTENANCE DU MARDI (18H-22H): Les serveurs seront") + s.BroadcastChatMessage("temporairement inaccessibles dans 15 minutes. Veuillez ne pas") + s.BroadcastChatMessage("vous connecter ou deconnectez-vous maintenant, afin de ne pas") + s.BroadcastChatMessage("perturber les operations de maintenance. Veuillez nous") + s.BroadcastChatMessage("excuser pour la gene occasionnee. Merci de votre cooperation.") + s.TimerUpdate(15, 0, true) + return + } else if result[0] == "!Rmaintenancedate" && m.Author.ID == "836027554628370492" { + s.BroadcastChatMessage("RAPPEL DE MAINTENANCE EXCEPTIONNELLE: Les serveurs seront") + s.BroadcastChatMessage("temporairement inaccessibles dans 15 minutes. Veuillez ne pas") + s.BroadcastChatMessage("vous connecter ou deconnectez-vous maintenant, afin de ne pas") + s.BroadcastChatMessage("perturber les operations de maintenance. Veuillez nous") + s.BroadcastChatMessage("excuser pour la gene occasionnee. Merci de votre cooperation.") + s.TimerUpdate(15, 1, true) + return + } else if result[0] == "!maintenanceStop" && m.Author.ID == "836027554628370492" { + s.BroadcastChatMessage("INFORMATION: A titre exceptionnel, il n'y aura pas de") + s.BroadcastChatMessage("maintenance de 18h a 22h, vous pouvez continuer de jouer") + s.BroadcastChatMessage("librement jusqu'a la prochaine annonce de maintenance !") + s.BroadcastChatMessage("Bonne chasse !") + s.TimerUpdate(0, 0, false) + return + } else if result[0] == "!maintenanceStopExec" && m.Author.ID == "836027554628370492" { + replaceDays := dayConvert(result[1]) + replaceMonth := MonthConvert(result[3]) + + s.BroadcastChatMessage("INFORMATION: A titre exceptionnel, il n'y aura pas de") + s.BroadcastChatMessage(fmt.Sprintf("maintenance le %s %s %s %s a partir de", replaceDays, result[2], replaceMonth, result[4])) // Jour Mois Année + s.BroadcastChatMessage(fmt.Sprintf("%s heures et %s minutes, vous pouvez continuer de jouer", result[5], result[6])) // Heures Minutes + s.BroadcastChatMessage("librement jusqu'a la prochaine annonce de maintenance !") + s.BroadcastChatMessage("Bonne chasse !") + s.TimerUpdate(0, 1, false) + return + } + + message := fmt.Sprintf("[DISCORD] %s: %s", m.Author.Username, m.Content) + s.BroadcastChatMessage(message) +} + +func dayConvert(result string) string { + var replaceDays string + + if result == "1" { + replaceDays = "Lundi" + } else if result == "2" { + replaceDays = "Mardi" + } else if result == "3" { + replaceDays = "Mercredi" + } else if result == "4" { + replaceDays = "Jeudi" + } else if result == "5" { + replaceDays = "Vendredi" + } else if result == "6" { + replaceDays = "Samedi" + } else if result == "7" { + replaceDays = "Dimanche" + } else { + replaceDays = "NULL" + } + + return replaceDays +} + +func MonthConvert(result string) string { + var replaceMonth string + + if result == "01" { + replaceMonth = "Janvier" + } else if result == "02" { + replaceMonth = "Fevrier" + } else if result == "03" { + replaceMonth = "Mars" + } else if result == "04" { + replaceMonth = "Avril" + } else if result == "05" { + replaceMonth = "Mai" + } else if result == "06" { + replaceMonth = "Juin" + } else if result == "07" { + replaceMonth = "Juillet" + } else if result == "08" { + replaceMonth = "Aout" + } else if result == "09" { + replaceMonth = "Septembre" + } else if result == "10" { + replaceMonth = "Octobre" + } else if result == "11" { + replaceMonth = "Novembre" + } else if result == "12" { + replaceMonth = "Decembre" + } else { + replaceMonth = "NULL" + } + + return replaceMonth +} + +func (s *Server) TimerUpdate(timer int, typeStop int, disableAutoOff bool) { + timertotal := 0 + for timer > 0 { + time.Sleep(1 * time.Minute) + timer -= 1 + timertotal += 1 + if disableAutoOff { + // Un message s'affiche toutes les 10 minutes pour prévenir de la maintenance. + if timertotal == 10 { + timertotal = 0 + if typeStop == 0 { + s.BroadcastChatMessage("RAPPEL DE MAINTENANCE DU MARDI (18H-22H): Les serveurs seront") + s.BroadcastChatMessage(fmt.Sprintf("temporairement inaccessibles dans %d minutes. Veuillez ne pas", timer)) + s.BroadcastChatMessage("vous connecter ou deconnectez-vous maintenant, afin de ne pas") + s.BroadcastChatMessage("perturber les operations de maintenance. Veuillez nous excuser") + s.BroadcastChatMessage("pour la gene occasionnee. Merci de votre cooperation.") + } else { + s.BroadcastChatMessage("RAPPEL DE MAINTENANCE EXCEPTIONNELLE: Les serveurs seront") + s.BroadcastChatMessage(fmt.Sprintf("temporairement inaccessibles dans %d minutes. Veuillez ne pas", timer)) + s.BroadcastChatMessage("vous connecter ou deconnectez-vous maintenant, afin de ne pas") + s.BroadcastChatMessage("perturber les operations de maintenance. Veuillez nous excuser") + s.BroadcastChatMessage("pour la gene occasionnee. Merci de votre cooperation.") + } + } + // Déconnecter tous les joueurs du serveur. + if timer == 0 { + os.Exit(-1) + } + } + } +} diff --git a/Erupe/server/channelserver/handlers_distitem.go b/Erupe/server/channelserver/handlers_distitem.go new file mode 100644 index 000000000..aeefc4a41 --- /dev/null +++ b/Erupe/server/channelserver/handlers_distitem.go @@ -0,0 +1,67 @@ +package channelserver + +import ( + "encoding/hex" + // "io/ioutil" + // "path/filepath" + + "github.com/Solenataris/Erupe/network/mhfpacket" +) + +func handleMsgMhfEnumerateDistItem(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateDistItem) + // uint16 number of entries + // 446 entry block + // uint32 claimID + // 00 00 00 00 00 00 + // uint16 timesClaimable + // 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 00 + // uint8 stringLength + // string nullTermString + data, _ := hex.DecodeString("0001000000010000000000000000002000000000FFFFFFFFFFFFFFFFFFFFFFFF0000000000000000002F323020426F7820457870616E73696F6E73000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) + +} + +func handleMsgMhfApplyDistItem(s *Session, p mhfpacket.MHFPacket) { + // 0052a49100011f00000000000000010274db99 equipment box page + // 0052a48f00011e0000000000000001195dda5c item box page + // 0052a49400010700003ae30000000132d3a4d6 Item ID 3AE3 + // HEADER: + // int32: Unique item hash for tracking server side purchases? Swapping across items didn't change image/cost/function etc. + // int16: Number of distributed item types + // ITEM ENTRY + // int8: distribution type + // 00 = legs, 01 = Head, 02 = Chest, 03 = Arms, 04 = Waist, 05 = Melee, 06 = Ranged, 07 = Item, 08 == furniture + // ids are wrong shop displays in random order + // 09 = Nothing, 10 = Null Point, 11 = Festi Point, 12 = Zeny, 13 = Null, 14 = Null Points, 15 = My Tore points + // 16 = Restyle Point, 17 = N Points, 18 = Nothing, 19 = Gacha Coins, 20 = Trial Gacha Coins, 21 = Frontier points + // 22 = ?, 23 = Guild Points, 30 = Item Box Page, 31 = Equipment Box Page + // int16: Unk + // int16: Item when type 07 + // int16: Unk + // int16: Number delivered in batch + // int32: Unique item hash for tracking server side purchases? Swapping across items didn't change image/cost/function etc. + pkt := p.(*mhfpacket.MsgMhfApplyDistItem) + if pkt.RequestType == 0 { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + } else if pkt.RequestType == 0x00000001 { + data, _ := hex.DecodeString("0052a494001e0f000000010000000132d3a4d60f000000020000000132d3a4d60f000000030000000132d3a4d60f000000040000000132d3a4d60f000000050000000132d3a4d60f000000060000000132d3a4d60f000000070000000132d3a4d60f000000080000000132d3a4d60f000000090000000132d3a4d60f0000000a0000000132d3a4d60f0000000b0000000132d3a4d60f0000000c0000000132d3a4d60f0000000d0000000132d3a4d60f0000000e0000000132d3a4d60f0000000f0000000132d3a4d60f000000100000000132d3a4d60f000000110000000132d3a4d60f000000120000000132d3a4d60f000000130000000132d3a4d60f000000140000000132d3a4d60f000000150000000132d3a4d60f000000160000000132d3a4d60f000000170000000132d3a4d60f000000180000000132d3a4d60f000000190000000132d3a4d60f0000001a0000000132d3a4d60f0000001b0000000132d3a4d60f0000001c0000000132d3a4d60f0000001d0000000132d3a4d60f0000001e0000000132d3a4d6") + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + } +} + +func handleMsgMhfAcquireDistItem(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfAcquireDistItem) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetDistDescription(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetDistDescription) + // string for the associated message + data, _ := hex.DecodeString("007E43303547656E65726963204974656D20436C61696D204D6573736167657E4330300D0A596F752067657420736F6D65206B696E64206F66206974656D732070726F6261626C792E00000100") + //data, _ := hex.DecodeString("0075b750c1c2b17ac1cab652a1757e433035b8cbb3c6bd63c258b169aa41b0c87e433030a1760a0aa175b8cbb3c6bd63c258b169aa41b0c8a176a843c1caa44a31a6b8a141a569c258b169a2b0add30aa8a4a6e2aabaa175b8cbb3c6bd63a176a2b0adb6a143b3cca668a569c258b169a2b4adb6a14300000100") + doAckBufSucceed(s, pkt.AckHandle, data) +} diff --git a/Erupe/server/channelserver/handlers_diva.go b/Erupe/server/channelserver/handlers_diva.go new file mode 100644 index 000000000..99318d5b7 --- /dev/null +++ b/Erupe/server/channelserver/handlers_diva.go @@ -0,0 +1,203 @@ +package channelserver + +import ( + "encoding/hex" + + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" +) + +func handleMsgMhfGetKijuInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetKijuInfo) + // Temporary canned response + data, _ := hex.DecodeString("04965C959782CC8B468EEC00000000000000000000000000000000000000000000815C82A082E782B582DC82A982BA82CC82AB82B682E3815C0A965C959782C682CD96D282E98E7682A281420A95B782AD8ED282C997458B4382F0975E82A682E98142000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001018BAD8C8282CC8B468EEC00000000000000000000000000000000000000000000815C82AB82E582A482B082AB82CC82AB82B682E3815C0A8BAD8C8282C682CD8BAD82A290BA904681420A95B782AD8ED282CC97CD82F08CA482AC909F82DC82B78142200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003138C8B8F5782CC8B468EEC00000000000000000000000000000000000000000000815C82AF82C182B582E382A482CC82AB82B682E3815C0A8C8B8F5782C682CD8A6D8CC582BD82E9904D978A81420A8F5782DF82E982D982C782C98EEB906C82BD82BF82CC90B8905F97CD82C682C882E9814200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041189CC8CEC82CC8B468EEC00000000000000000000000000000000000000000000815C82A482BD82DC82E082E882CC82AB82B682E3815C0A89CC8CEC82C682CD89CC955082CC8CEC82E881420A8F5782DF82E982D982C782C98EEB906C82BD82BF82CC8E7882A682C682C882E9814220000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000212") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfSetKiju(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSetKiju) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfAddUdPoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfAddUdPoint) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetUdMyPoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdMyPoint) + // Temporary canned response + data, _ := hex.DecodeString("00040000013C000000FA000000000000000000040000007E0000003C02000000000000000000000000000000000000000000000000000002000004CC00000438000000000000000000000000000000000000000000000000000000020000026E00000230000000000000000000020000007D0000007D000000000000000000000000000000000000000000000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetUdTotalPointInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdTotalPointInfo) + // Temporary canned response + data, _ := hex.DecodeString("00000000000007A12000000000000F424000000000001E848000000000002DC6C000000000003D090000000000004C4B4000000000005B8D8000000000006ACFC000000000007A1200000000000089544000000000009896800000000000E4E1C00000000001312D0000000000017D78400000000001C9C3800000000002160EC00000000002625A000000000002AEA5400000000002FAF0800000000003473BC0000000000393870000000000042C1D800000000004C4B40000000000055D4A800000000005F5E10000000000008954400000000001C9C3800000000003473BC00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001020300000000000000000000000000000000000000000000000000000000000000000000000000000000101F1420") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetUdSelectedColorInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdSelectedColorInfo) + + // Unk + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x01, 0x01, 0x01, 0x02, 0x03, 0x02, 0x00, 0x00}) +} + +func handleMsgMhfGetUdMonsterPoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdMonsterPoint) + + monsterPoints := []struct { + MID uint8 + Points uint16 + }{ + {MID: 0x01, Points: 0x3C}, // em1 Rathian + {MID: 0x02, Points: 0x5A}, // em2 Fatalis + {MID: 0x06, Points: 0x14}, // em6 Yian Kut-Ku + {MID: 0x07, Points: 0x50}, // em7 Lao-Shan Lung + {MID: 0x08, Points: 0x28}, // em8 Cephadrome + {MID: 0x0B, Points: 0x3C}, // em11 Rathalos + {MID: 0x0E, Points: 0x3C}, // em14 Diablos + {MID: 0x0F, Points: 0x46}, // em15 Khezu + {MID: 0x11, Points: 0x46}, // em17 Gravios + {MID: 0x14, Points: 0x28}, // em20 Gypceros + {MID: 0x15, Points: 0x3C}, // em21 Plesioth + {MID: 0x16, Points: 0x32}, // em22 Basarios + {MID: 0x1A, Points: 0x32}, // em26 Monoblos + {MID: 0x1B, Points: 0x0A}, // em27 Velocidrome + {MID: 0x1C, Points: 0x0A}, // em28 Gendrome + {MID: 0x1F, Points: 0x0A}, // em31 Iodrome + {MID: 0x21, Points: 0x50}, // em33 Kirin + {MID: 0x24, Points: 0x64}, // em36 Crimson Fatalis + {MID: 0x25, Points: 0x3C}, // em37 Pink Rathian + {MID: 0x26, Points: 0x1E}, // em38 Blue Yian Kut-Ku + {MID: 0x27, Points: 0x28}, // em39 Purple Gypceros + {MID: 0x28, Points: 0x50}, // em40 Yian Garuga + {MID: 0x29, Points: 0x5A}, // em41 Silver Rathalos + {MID: 0x2A, Points: 0x50}, // em42 Gold Rathian + {MID: 0x2B, Points: 0x3C}, // em43 Black Diablos + {MID: 0x2C, Points: 0x3C}, // em44 White Monoblos + {MID: 0x2D, Points: 0x46}, // em45 Red Khezu + {MID: 0x2E, Points: 0x3C}, // em46 Green Plesioth + {MID: 0x2F, Points: 0x50}, // em47 Black Gravios + {MID: 0x30, Points: 0x1E}, // em48 Daimyo Hermitaur + {MID: 0x31, Points: 0x3C}, // em49 Azure Rathalos + {MID: 0x32, Points: 0x50}, // em50 Ashen Lao-Shan Lung + {MID: 0x33, Points: 0x3C}, // em51 Blangonga + {MID: 0x34, Points: 0x28}, // em52 Congalala + {MID: 0x35, Points: 0x50}, // em53 Rajang + {MID: 0x36, Points: 0x6E}, // em54 Kushala Daora + {MID: 0x37, Points: 0x50}, // em55 Shen Gaoren + {MID: 0x3A, Points: 0x50}, // em58 Yama Tsukami + {MID: 0x3B, Points: 0x6E}, // em59 Chameleos + {MID: 0x40, Points: 0x64}, // em64 Lunastra + {MID: 0x41, Points: 0x6E}, // em65 Teostra + {MID: 0x43, Points: 0x28}, // em67 Shogun Ceanataur + {MID: 0x44, Points: 0x0A}, // em68 Bulldrome + {MID: 0x47, Points: 0x6E}, // em71 White Fatalis + {MID: 0x4A, Points: 0xFA}, // em74 Hypnocatrice + {MID: 0x4B, Points: 0xFA}, // em75 Lavasioth + {MID: 0x4C, Points: 0x46}, // em76 Tigrex + {MID: 0x4D, Points: 0x64}, // em77 Akantor + {MID: 0x4E, Points: 0xFA}, // em78 Bright Hypnoc + {MID: 0x4F, Points: 0xFA}, // em79 Lavasioth Subspecies + {MID: 0x50, Points: 0xFA}, // em80 Espinas + {MID: 0x51, Points: 0xFA}, // em81 Orange Espinas + {MID: 0x52, Points: 0xFA}, // em82 White Hypnoc + {MID: 0x53, Points: 0xFA}, // em83 Akura Vashimu + {MID: 0x54, Points: 0xFA}, // em84 Akura Jebia + {MID: 0x55, Points: 0xFA}, // em85 Berukyurosu + {MID: 0x59, Points: 0xFA}, // em89 Pariapuria + {MID: 0x5A, Points: 0xFA}, // em90 White Espinas + {MID: 0x5B, Points: 0xFA}, // em91 Kamu Orugaron + {MID: 0x5C, Points: 0xFA}, // em92 Nono Orugaron + {MID: 0x5E, Points: 0xFA}, // em94 Dyuragaua + {MID: 0x5F, Points: 0xFA}, // em95 Doragyurosu + {MID: 0x60, Points: 0xFA}, // em96 Gurenzeburu + {MID: 0x63, Points: 0xFA}, // em99 Rukodiora + {MID: 0x65, Points: 0xFA}, // em101 Gogomoa + {MID: 0x67, Points: 0xFA}, // em103 Taikun Zamuza + {MID: 0x68, Points: 0xFA}, // em104 Abiorugu + {MID: 0x69, Points: 0xFA}, // em105 Kuarusepusu + {MID: 0x6A, Points: 0xFA}, // em106 Odibatorasu + {MID: 0x6B, Points: 0xFA}, // em107 Disufiroa + {MID: 0x6C, Points: 0xFA}, // em108 Rebidiora + {MID: 0x6D, Points: 0xFA}, // em109 Anorupatisu + {MID: 0x6E, Points: 0xFA}, // em110 Hyujikiki + {MID: 0x6F, Points: 0xFA}, // em111 Midogaron + {MID: 0x70, Points: 0xFA}, // em112 Giaorugu + {MID: 0x72, Points: 0xFA}, // em114 Farunokku + {MID: 0x73, Points: 0xFA}, // em115 Pokaradon + {MID: 0x74, Points: 0xFA}, // em116 Shantien + {MID: 0x77, Points: 0xFA}, // em119 Goruganosu + {MID: 0x78, Points: 0xFA}, // em120 Aruganosu + {MID: 0x79, Points: 0xFA}, // em121 Baruragaru + {MID: 0x7A, Points: 0xFA}, // em122 Zerureusu + {MID: 0x7B, Points: 0xFA}, // em123 Gougarf + {MID: 0x7D, Points: 0xFA}, // em125 Forokururu + {MID: 0x7E, Points: 0xFA}, // em126 Meraginasu + {MID: 0x7F, Points: 0xFA}, // em127 Diorekkusu + {MID: 0x80, Points: 0xFA}, // em128 Garuba Daora + {MID: 0x81, Points: 0xFA}, // em129 Inagami + {MID: 0x82, Points: 0xFA}, // em130 Varusaburosu + {MID: 0x83, Points: 0xFA}, // em131 Poborubarumu + {MID: 0x8B, Points: 0xFA}, // em139 Gureadomosu + {MID: 0x8C, Points: 0xFA}, // em140 Harudomerugu + {MID: 0x8D, Points: 0xFA}, // em141 Toridcless + {MID: 0x8E, Points: 0xFA}, // em142 Gasurabazura + {MID: 0x90, Points: 0xFA}, // em144 Yama Kurai + {MID: 0x92, Points: 0x78}, // em146 Zinogre + {MID: 0x93, Points: 0x78}, // em147 Deviljho + {MID: 0x94, Points: 0x78}, // em148 Brachydios + {MID: 0x96, Points: 0xFA}, // em150 Toa Tesukatora + {MID: 0x97, Points: 0x78}, // em151 Barioth + {MID: 0x98, Points: 0x78}, // em152 Uragaan + {MID: 0x99, Points: 0x78}, // em153 Stygian Zinogre + {MID: 0x9A, Points: 0xFA}, // em154 Guanzorumu + {MID: 0x9E, Points: 0xFA}, // em158 Voljang + {MID: 0x9F, Points: 0x78}, // em159 Nargacuga + {MID: 0xA0, Points: 0xFA}, // em160 Keoaruboru + {MID: 0xA1, Points: 0xFA}, // em161 Zenaserisu + {MID: 0xA2, Points: 0x78}, // em162 Gore Magala + {MID: 0xA4, Points: 0x78}, // em164 Shagaru Magala + {MID: 0xA5, Points: 0x78}, // em165 Amatsu + {MID: 0xA6, Points: 0xFA}, // em166 Elzelion + {MID: 0xA9, Points: 0x78}, // em169 Seregios + {MID: 0xAA, Points: 0xFA}, // em170 Bogabadorumu + } + + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(len(monsterPoints))) + for _, mp := range monsterPoints { + resp.WriteUint8(mp.MID) + resp.WriteUint16(mp.Points) + } + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfGetUdDailyPresentList(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdDailyPresentList) + // Temporary canned response + data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetUdNormaPresentList(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdNormaPresentList) + // Temporary canned response + data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfAcquireUdItem(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetUdRanking(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetUdMyRanking(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdMyRanking) + // Temporary canned response + data, _ := hex.DecodeString("00000515000005150000CEB4000003CE000003CE0000CEB44D49444E494748542D414E47454C0000000000000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) +} diff --git a/Erupe/server/channelserver/handlers_event.go b/Erupe/server/channelserver/handlers_event.go new file mode 100644 index 000000000..8a54b80db --- /dev/null +++ b/Erupe/server/channelserver/handlers_event.go @@ -0,0 +1,422 @@ +package channelserver + +import ( + "fmt" + "math/rand" + "time" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network/mhfpacket" + timeServerFix "github.com/Solenataris/Erupe/server/channelserver/timeserver" +) + +func handleMsgMhfRegisterEvent(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfRegisterEvent) + bf := byteframe.NewByteFrame() + bf.WriteUint8(pkt.Unk2) + bf.WriteUint8(pkt.Unk4) + bf.WriteUint16(0x1142) + doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfReleaseEvent(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReleaseEvent) + + // Do this ack manually because it uses a non-(0|1) error code + /* + _ACK_SUCCESS = 0 + _ACK_ERROR = 1 + + _ACK_EINPROGRESS = 16 + _ACK_ENOENT = 17 + _ACK_ENOSPC = 18 + _ACK_ETIMEOUT = 19 + + _ACK_EINVALID = 64 + _ACK_EFAILED = 65 + _ACK_ENOMEM = 66 + _ACK_ENOTEXIT = 67 + _ACK_ENOTREADY = 68 + _ACK_EALREADY = 69 + _ACK_DISABLE_WORK = 71 + */ + s.QueueSendMHF(&mhfpacket.MsgSysAck{ + AckHandle: pkt.AckHandle, + IsBufferResponse: false, + ErrorCode: 0x41, + AckData: []byte{0x00, 0x00, 0x00, 0x00}, + }) +} + +func handleMsgMhfEnumerateEvent(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateEvent) + stubEnumerateNoResults(s, pkt.AckHandle) +} + +var persistentEventSchedule []activeFeature + +type activeFeature struct { + StartTime time.Time + ActiveFeatures uint32 + Unk1 uint16 +} + +func handleMsgMhfGetWeeklySchedule(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetWeeklySchedule) + // ActiveFeatures is a bit field, 0x3FFF is all 14 active features. + // Long term it should probably be made persistent and simply cycle a couple daily + // Times seem to need to be timeServerFix.midnight which is likely why matching timezone was required originally + if len(persistentEventSchedule) == 0 { + if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.OpcodeMessages { + s.logger.Info("\nGenerating active feature...") + } + persistentEventSchedule = make([]activeFeature, 8) + //weapons := generateRandomNumber(1, 14, 8) + for x := -1; x < 7; x++ { + var feat uint32 + feat |= 65535 + persistentEventSchedule[x+1] = activeFeature{ + StartTime: Time_Current_Midnight().Add(time.Duration(24*x) * time.Hour), + ActiveFeatures: feat, + Unk1: 0, + } + fmt.Println(feat) + } + } + + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(len(persistentEventSchedule))) // Entry count, client only parses the first 7 or 8. + resp.WriteUint32(uint32(Time_Current_Adjusted().Add(-5 * time.Minute).Unix())) // 5 minutes ago server time + + for _, es := range persistentEventSchedule { + resp.WriteUint32(uint32(es.StartTime.Unix())) + resp.WriteUint32(es.ActiveFeatures) + resp.WriteUint16(es.Unk1) + } + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func generateRandomNumber(start int, end int, count int) []int { + if end < start || (end-start) < count { + return nil + } + nums := make([]int, 0) + r := rand.New(rand.NewSource(time.Now().UnixNano())) + for len(nums) < count { + num := r.Intn((end - start)) + start + exist := false + for _, v := range nums { + if v == num { + exist = true + break + } + } + if !exist { + nums = append(nums, num) + } + } + return nums +} + +type loginBoost struct { + WeekReq, WeekCount uint8 + Available bool + Expiration uint32 +} + +func handleMsgMhfGetKeepLoginBoostStatus(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetKeepLoginBoostStatus) + + var loginBoostStatus []loginBoost + insert := false + boostState, err := s.server.db.Query("SELECT week_req, week_count, available, end_time FROM login_boost_state WHERE char_id=$1 ORDER BY week_req ASC", s.charID) + if err != nil { + panic(err) + } + for boostState.Next() { + var boost loginBoost + err = boostState.Scan(&boost.WeekReq, &boost.WeekCount, &boost.Available, &boost.Expiration) + if err != nil { + panic(err) + } + loginBoostStatus = append(loginBoostStatus, boost) + } + if len(loginBoostStatus) == 0 { + // create default Entries (should only been week 1 with ) + insert = true + loginBoostStatus = []loginBoost{ + { + WeekReq: 1, // weeks needed + WeekCount: 0, // weeks passed + Available: true, // available + Expiration: 0, //uint32(t.Add(120 * time.Minute).Unix()), // uncomment to enable permanently + }, + { + WeekReq: 2, + WeekCount: 0, + Available: true, + Expiration: 0, + }, + { + WeekReq: 3, + WeekCount: 0, + Available: true, + Expiration: 0, + }, + { + WeekReq: 4, + WeekCount: 0, + Available: true, + Expiration: 0, + }, + { + WeekReq: 5, + WeekCount: 0, + Available: true, + Expiration: 0, + }, + } + } + resp := byteframe.NewByteFrame() + CurrentWeek := Time_Current_Week_uint8() + for d := range loginBoostStatus { + if CurrentWeek == 1 && loginBoostStatus[d].WeekCount <= 5 { + loginBoostStatus[d].WeekCount = 0 + } + if loginBoostStatus[d].WeekReq == CurrentWeek || loginBoostStatus[d].WeekCount != 0 { + loginBoostStatus[d].WeekCount = CurrentWeek + } + if !loginBoostStatus[d].Available && loginBoostStatus[d].WeekCount >= loginBoostStatus[d].WeekReq && uint32(time.Now().In(time.FixedZone("UTC+1", 1*60*60)).Unix()) >= loginBoostStatus[d].Expiration { + loginBoostStatus[d].Expiration = 1 + } + if !insert { + _, err := s.server.db.Exec(`UPDATE login_boost_state SET week_count=$1, end_time=$2 WHERE char_id=$3 AND week_req=$4`, loginBoostStatus[d].WeekCount, loginBoostStatus[d].Expiration, s.charID, loginBoostStatus[d].WeekReq) + if err != nil { + panic(err) + } + } + } + for _, v := range loginBoostStatus { + if insert { + _, err := s.server.db.Exec(`INSERT INTO login_boost_state (char_id, week_req, week_count, available, end_time) VALUES ($1,$2,$3,$4,$5)`, s.charID, v.WeekReq, v.WeekCount, v.Available, v.Expiration) + if err != nil { + panic(err) + } + } + resp.WriteUint8(v.WeekReq) + resp.WriteUint8(v.WeekCount) + resp.WriteBool(v.Available) + resp.WriteUint32(v.Expiration) + } + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfUseKeepLoginBoost(s *Session, p mhfpacket.MHFPacket) { + // Directly interacts with MhfGetKeepLoginBoostStatus + // TODO: make these states persistent on a per character basis + pkt := p.(*mhfpacket.MsgMhfUseKeepLoginBoost) + var t = time.Now().In(time.FixedZone("UTC+1", 1*60*60)) + resp := byteframe.NewByteFrame() + resp.WriteUint8(0) + + // response is end timestamp based on input + switch pkt.BoostWeekUsed { + case 1: + t = t.Add(120 * time.Minute) + resp.WriteUint32(uint32(t.Unix())) + case 2: + t = t.Add(240 * time.Minute) + resp.WriteUint32(uint32(t.Unix())) + case 3: + t = t.Add(120 * time.Minute) + resp.WriteUint32(uint32(t.Unix())) + case 4: + t = t.Add(180 * time.Minute) + resp.WriteUint32(uint32(t.Unix())) + case 5: + t = t.Add(240 * time.Minute) + resp.WriteUint32(uint32(t.Unix())) + } + _, err := s.server.db.Exec(`UPDATE login_boost_state SET available='false', end_time=$1 WHERE char_id=$2 AND week_req=$3`, uint32(t.Unix()), s.charID, pkt.BoostWeekUsed) + if err != nil { + panic(err) + } + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdSchedule) + var t = timeServerFix.Tstatic_midnight() + var event int = s.server.erupeConfig.DevModeOptions.Event + + year, month, day := t.Date() + midnight := time.Date(year, month, day, 0, 0, 0, 0, t.Location()) + // Events with time limits are Festival with Sign up, Soul Week and Winners Weeks + // Diva Defense with Prayer, Interception and Song weeks + // Mezeporta Festival with simply 'available' being a weekend thing + resp := byteframe.NewByteFrame() + resp.WriteUint32(0x1d5fda5c) // Unk (1d5fda5c, 0b5397df) + + if event == 1 { + resp.WriteUint32(uint32(midnight.Add(24 * 21 * time.Hour).Unix())) // Week 1 Timestamp, Festi start? + } else { + resp.WriteUint32(uint32(midnight.Add(-24 * 21 * time.Hour).Unix())) // Week 1 Timestamp, Festi start? + } + + if event == 2 { + resp.WriteUint32(uint32(midnight.Add(24 * 14 * time.Hour).Unix())) // Week 2 Timestamp + resp.WriteUint32(uint32(midnight.Add(24 * 14 * time.Hour).Unix())) // Week 2 Timestamp + } else { + resp.WriteUint32(uint32(midnight.Add(-24 * 14 * time.Hour).Unix())) // Week 2 Timestamp + resp.WriteUint32(uint32(midnight.Add(-24 * 14 * time.Hour).Unix())) // Week 2 Timestamp + } + + if event == 3 { + resp.WriteUint32(uint32(midnight.Add((24) * 7 * time.Hour).Unix())) // Diva Defense Interception + resp.WriteUint32(uint32(midnight.Add((24) * 14 * time.Hour).Unix())) // Diva Defense Greeting Song + } else { + resp.WriteUint32(uint32(midnight.Add((-24) * 7 * time.Hour).Unix())) // Diva Defense Interception + resp.WriteUint32(uint32(midnight.Add((-24) * 14 * time.Hour).Unix())) // Diva Defense Greeting Song + } + + resp.WriteUint16(0x19) // Unk 00011001 + resp.WriteUint16(0x2d) // Unk 00101101 + resp.WriteUint16(0x02) // Unk 00000010 + resp.WriteUint16(0x02) // Unk 00000010 + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +/* +func handleMsgMhfGetUdSchedule(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdSchedule) + resp := byteframe.NewByteFrame() + + resp.WriteUint32(0x1d5fda5c) // Unk (1d5fda5c, 0b5397df) + resp.WriteUint32(uint32(ScheduleEvent(s, 1))) // Week 1 Timestamp, Festi start? + resp.WriteUint32(uint32(ScheduleEvent(s, 2))) // Diva Defense Interception 1 + resp.WriteUint32(uint32(ScheduleEvent(s, 3))) // Week 2 Timestamp + resp.WriteUint32(uint32(ScheduleEvent(s, 4))) // Diva Defense Interception 2 + resp.WriteUint32(uint32(ScheduleEvent(s, 5))) // Week 3 Timestamp + resp.WriteUint32(uint32(ScheduleEvent(s, 6))) // Diva Defense Greeting Song 3 + resp.WriteUint16(0x19) // Unk 00011001 + resp.WriteUint16(0x2d) // Unk 00101101 + resp.WriteUint16(0x02) // Unk 00000010 + resp.WriteUint16(0x02) // Unk 00000010 + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +var timedb int64 +var countEvent int = 1 +var BlockSchedulEvent bool +var t_Next_SchedulEvent = Time_Current_Adjusted() +var t_curr_SchedulEvent = Time_Current_Adjusted().Unix() + +func ScheduleEvent(s *Session, fixWeek int) uint32 { + if !BlockSchedulEvent { + if s.server.erupeConfig.DevModeOptions.ServerName != "" { // IF (SERVERNAME == NAME) + err := s.server.db.QueryRow("SELECT event_id FROM servers WHERE server_name=$1", s.server.erupeConfig.DevModeOptions.ServerName).Scan(&countEvent) + if err != nil { + panic(err) + } + s.server.db.QueryRow("SELECT date_expiration FROM servers server_name=$1", s.server.erupeConfig.DevModeOptions.ServerName).Scan(&timedb) + if t_curr_SchedulEvent >= timedb { + countEvent += 1 + if countEvent == 7 { + countEvent = 1 + } + var t_Add_Next_SchedulEvent = t_Next_SchedulEvent.Add(7 * 24 * time.Hour).Unix() + _, err := s.server.db.Exec("UPDATE servers SET event_id=$1, event_expiration=$2 WHERE server_name=$3", countEvent, t_Add_Next_SchedulEvent, s.server.erupeConfig.DevModeOptions.ServerName) + if err == nil { + s.server.db.QueryRow("SELECT event_id FROM servers WHERE id=$1").Scan(&countEvent) + } + } + BlockSchedulEvent = fixWeek == countEvent + } else { // ELSE (SERVERNAME == NULL) + err := s.server.db.QueryRow("SELECT event_id FROM event_week WHERE id=1").Scan(&countEvent) + if err != nil { + var t_Add_Next_SchedulEvent = t_Next_SchedulEvent.Add(7 * 24 * time.Hour).Unix() + s.server.db.Exec("INSERT INTO event_week (id, event_id, date_expiration) VALUES (1, $1, $2)", countEvent, t_Add_Next_SchedulEvent) + s.server.db.QueryRow("SELECT event_id FROM event_week WHERE id=1").Scan(&countEvent) + } + s.server.db.QueryRow("SELECT date_expiration FROM event_week WHERE id=1").Scan(&timedb) + if t_curr_SchedulEvent >= timedb { + countEvent += 1 + if countEvent == 7 { + countEvent = 1 + } + var t_Add_Next_SchedulEvent = t_Next_SchedulEvent.Add(7 * 24 * time.Hour).Unix() + _, err := s.server.db.Exec("UPDATE event_week SET event_id=$1, date_expiration=$2 WHERE id=1", countEvent, t_Add_Next_SchedulEvent) + if err == nil { + s.server.db.QueryRow("SELECT event_id FROM event_week WHERE id=1").Scan(&countEvent) + } + } + BlockSchedulEvent = fixWeek == countEvent + } + } + if fixWeek == countEvent { + return uint32(Time_Current_Midnight().Add(7 * 24 * time.Hour).Unix()) + } else { + return uint32(Time_Current_Midnight().Add(-24 * 21 * time.Hour).Unix()) + } +} +*/ + +func handleMsgMhfGetUdInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdInfo) + // Message that appears on the Diva Defense NPC and triggers the green exclamation mark + udInfos := []struct { + Text string + StartTime time.Time + EndTime time.Time + }{ + /*{ + Text: " ~C17【Erupe】 is dead event!\n\n■Features\n~C18 Dont bother walking around!\n~C17 Take down your DB by doing \n~C17 nearly anything!", + StartTime: Time_static().Add(time.Duration(-5) * time.Minute), // Event started 5 minutes ago, + EndTime: Time_static().Add(time.Duration(24) * time.Hour), // Event ends in 5 minutes, + }, */ + } + + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(len(udInfos))) + for _, udInfo := range udInfos { + resp.WriteBytes(fixedSizeShiftJIS(udInfo.Text, 1024)) + resp.WriteUint32(uint32(udInfo.StartTime.Unix())) + resp.WriteUint32(uint32(udInfo.EndTime.Unix())) + } + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfGetBoostTime(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetBoostTime) + + doAckBufSucceed(s, pkt.AckHandle, []byte{}) + updateRights(s) +} + +func handleMsgMhfGetBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetBoostTimeLimit) + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetBoostRight(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetBoostRight) + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfPostBoostTimeQuestReturn(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPostBoostTimeQuestReturn) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfStartBoostTime(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfPostBoostTime(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfPostBoostTimeLimit(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetRestrictionEvent(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfSetRestrictionEvent(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_festa.go b/Erupe/server/channelserver/handlers_festa.go new file mode 100644 index 000000000..7fd845ba2 --- /dev/null +++ b/Erupe/server/channelserver/handlers_festa.go @@ -0,0 +1,69 @@ +package channelserver + +import ( + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" +) + +func handleMsgMhfSaveMezfesData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSaveMezfesData) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfLoadMezfesData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadMezfesData) + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) // Unk + + resp.WriteUint8(2) // Count of the next 2 uint32s + resp.WriteUint32(0) + resp.WriteUint32(0) + + resp.WriteUint32(0) // Unk + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfInfoFesta(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfInfoFesta) + + // REALLY large/complex format... stubbing it out here for simplicity. + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +// state festa (U)ser +func handleMsgMhfStateFestaU(s *Session, p mhfpacket.MHFPacket) {} + +// state festa (G)uild +func handleMsgMhfStateFestaG(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfStateFestaG) + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0xFFFFFFFF) + resp.WriteUint32(0) + resp.WriteBytes([]byte{0x00, 0x00, 0x00}) // Not parsed. + resp.WriteUint8(0) + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfVoteFesta(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEntryFesta(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfChargeFesta(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireFesta(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEnumerateFestaMember(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEnumerateFestaPersonalPrize(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEnumerateFestaIntermediatePrize(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_guild.go b/Erupe/server/channelserver/handlers_guild.go new file mode 100644 index 000000000..13601a6b5 --- /dev/null +++ b/Erupe/server/channelserver/handlers_guild.go @@ -0,0 +1,1480 @@ +package channelserver + +import ( + "database/sql" + "database/sql/driver" + "encoding/binary" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "sort" + "time" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/bfutil" + "github.com/Solenataris/Erupe/common/stringsupport" + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/jmoiron/sqlx" + "go.uber.org/zap" +) + +type FestivalColour string + +const ( + FestivalColourNone FestivalColour = "none" + FestivalColourRed FestivalColour = "red" + FestivalColourBlue FestivalColour = "blue" +) + +var FestivalColourCodes = map[FestivalColour]uint8{ + FestivalColourBlue: 0x00, + FestivalColourRed: 0x01, + FestivalColourNone: 0xFF, +} + +type GuildApplicationType string + +const ( + GuildApplicationTypeApplied GuildApplicationType = "applied" + GuildApplicationTypeInvited GuildApplicationType = "invited" +) + +type Guild struct { + ID uint32 `db:"id"` + Name string `db:"name"` + MainMotto uint8 `db:"main_motto"` + SubMotto uint8 `db:"sub_motto"` + CreatedAt time.Time `db:"created_at"` + MemberCount uint16 `db:"member_count"` + RP uint32 `db:"rp"` + Comment string `db:"comment"` + FestivalColour FestivalColour `db:"festival_colour"` + GuildHallType uint16 `db:"guild_hall"` + Icon *GuildIcon `db:"icon"` + + GuildLeader +} + +type GuildLeader struct { + LeaderCharID uint32 `db:"leader_id"` + LeaderName string `db:"leader_name"` +} + +type GuildIconPart struct { + Index uint16 + ID uint16 + Size uint8 + Rotation uint8 + PosX uint16 + PosY uint16 +} + +type GuildApplication struct { + ID int `db:"id"` + GuildID uint32 `db:"guild_id"` + CharID uint32 `db:"character_id"` + ActorID uint32 `db:"actor_id"` + ApplicationType GuildApplicationType `db:"application_type"` + CreatedAt time.Time `db:"created_at"` +} + +type GuildIcon struct { + Parts []GuildIconPart +} + +func (gi *GuildIcon) Scan(val interface{}) (err error) { + switch v := val.(type) { + case []byte: + err = json.Unmarshal(v, &gi) + case string: + err = json.Unmarshal([]byte(v), &gi) + } + + return +} + +func (gi *GuildIcon) Value() (valuer driver.Value, err error) { + return json.Marshal(gi) +} + +const guildInfoSelectQuery = ` +SELECT g.id, + g.name, + g.rp, + g.main_motto, + g.sub_motto, + created_at, + leader_id, + lc.name as leader_name, + comment, + festival_colour, + guild_hall, + icon, + ( + SELECT count(1) FROM guild_characters gc WHERE gc.guild_id = g.id + ) AS member_count +FROM guilds g + JOIN guild_characters lgc ON lgc.character_id = leader_id + JOIN characters lc on leader_id = lc.id +` + +func (guild *Guild) Save(s *Session) error { + _, err := s.server.db.Exec(` + UPDATE guilds SET main_motto=$1, sub_motto=$6, comment=$3, festival_colour=$4, icon=$5 WHERE id=$2 + `, guild.MainMotto, guild.ID, guild.Comment, guild.FestivalColour, guild.Icon, guild.SubMotto) + + if err != nil { + s.logger.Error("failed to update guild data", zap.Error(err), zap.Uint32("guildID", guild.ID)) + return err + } + + return nil +} + +func (guild *Guild) CreateApplication(s *Session, charID uint32, applicationType GuildApplicationType, transaction *sql.Tx) error { + + sql := ` + INSERT INTO guild_applications (guild_id, character_id, actor_id, application_type) + VALUES ($1, $2, $3, $4) + ` + + var err error + + if transaction == nil { + _, err = s.server.db.Exec(sql, guild.ID, charID, s.charID, applicationType) + } else { + _, err = transaction.Exec(sql, guild.ID, charID, s.charID, applicationType) + } + + if err != nil { + s.logger.Error( + "failed to add guild application", + zap.Error(err), + zap.Uint32("guildID", guild.ID), + zap.Uint32("charID", charID), + ) + return err + } + + return nil +} + +func (guild *Guild) Disband(s *Session) error { + transaction, err := s.server.db.Begin() + + if err != nil { + s.logger.Error("failed to begin transaction", zap.Error(err)) + return err + } + + _, err = transaction.Exec("DELETE FROM guild_characters WHERE guild_id = $1", guild.ID) + + if err != nil { + s.logger.Error("failed to remove guild characters", zap.Error(err), zap.Uint32("guildId", guild.ID)) + rollbackTransaction(s, transaction) + return err + } + + _, err = transaction.Exec("DELETE FROM guilds WHERE id = $1", guild.ID) + + if err != nil { + s.logger.Error("failed to remove guild", zap.Error(err), zap.Uint32("guildID", guild.ID)) + rollbackTransaction(s, transaction) + return err + } + + err = transaction.Commit() + + if err != nil { + s.logger.Error("failed to commit transaction", zap.Error(err)) + return err + } + + s.logger.Info("Character disbanded guild", zap.Uint32("charID", s.charID), zap.Uint32("guildID", guild.ID)) + + return nil +} + +func (guild *Guild) RemoveCharacter(s *Session, charID uint32) error { + _, err := s.server.db.Exec("DELETE FROM guild_characters WHERE character_id=$1", charID) + + if err != nil { + s.logger.Error( + "failed to remove character from guild", + zap.Error(err), + zap.Uint32("charID", charID), + zap.Uint32("guildID", guild.ID), + ) + + return err + } + + return nil +} + +func (guild *Guild) AcceptApplication(s *Session, charID uint32) error { + transaction, err := s.server.db.Begin() + + if err != nil { + s.logger.Error("failed to start db transaction", zap.Error(err)) + return err + } + + _, err = transaction.Exec(`DELETE FROM guild_applications WHERE character_id = $1`, charID) + + if err != nil { + s.logger.Error("failed to accept character's guild application", zap.Error(err)) + rollbackTransaction(s, transaction) + return err + } + + _, err = transaction.Exec(` + INSERT INTO guild_characters (guild_id, character_id, order_index) + VALUES ($1, $2, (SELECT MAX(order_index) + 1 FROM guild_characters WHERE guild_id = $1)) + `, guild.ID, charID) + + if err != nil { + s.logger.Error( + "failed to add applicant to guild", + zap.Error(err), + zap.Uint32("guildID", guild.ID), + zap.Uint32("charID", charID), + ) + rollbackTransaction(s, transaction) + return err + } + + err = transaction.Commit() + + if err != nil { + s.logger.Error("failed to commit db transaction", zap.Error(err)) + rollbackTransaction(s, transaction) + return err + } + + return nil +} + +// This is relying on the fact that invitation ID is also character ID right now +// if invitation ID changes, this will break. +func (guild *Guild) CancelInvitation(s *Session, charID uint32) error { + _, err := s.server.db.Exec( + `DELETE FROM guild_applications WHERE character_id = $1 AND guild_id = $2 AND application_type = 'invited'`, + charID, guild.ID, + ) + + if err != nil { + s.logger.Error( + "failed to cancel guild invitation", + zap.Error(err), + zap.Uint32("guildID", guild.ID), + zap.Uint32("charID", charID), + ) + return err + } + + return nil +} + +func (guild *Guild) RejectApplication(s *Session, charID uint32) error { + _, err := s.server.db.Exec( + `DELETE FROM guild_applications WHERE character_id = $1 AND guild_id = $2 AND application_type = 'applied'`, + charID, guild.ID, + ) + + if err != nil { + s.logger.Error( + "failed to reject guild application", + zap.Error(err), + zap.Uint32("guildID", guild.ID), + zap.Uint32("charID", charID), + ) + return err + } + + return nil +} + +func (guild *Guild) ArrangeCharacters(s *Session, charIDs []uint32) error { + transaction, err := s.server.db.Begin() + + if err != nil { + s.logger.Error("failed to start db transaction", zap.Error(err)) + return err + } + + for i, id := range charIDs { + _, err := transaction.Exec("UPDATE guild_characters SET order_index = $1 WHERE character_id = $2", 2+i, id) + + if err != nil { + err = transaction.Rollback() + + if err != nil { + s.logger.Error("failed to rollback db transaction", zap.Error(err)) + } + + return err + } + } + + err = transaction.Commit() + + if err != nil { + s.logger.Error("failed to commit db transaction", zap.Error(err)) + return err + } + + return nil +} + +func (guild *Guild) DonateRP(s *Session, rp uint16, transaction *sql.Tx) (err error) { + updateSQL := "UPDATE guilds SET rp = rp + $1 WHERE id = $2" + + if transaction != nil { + _, err = transaction.Exec(updateSQL, rp, guild.ID) + } else { + _, err = s.server.db.Exec(updateSQL, rp, guild.ID) + } + + if err != nil { + s.logger.Error( + "failed to donate RP to guild", + zap.Error(err), + zap.Uint32("guildID", guild.ID), + ) + + return err + } + + return nil +} + +func (guild *Guild) GetApplicationForCharID(s *Session, charID uint32, applicationType GuildApplicationType) (*GuildApplication, error) { + row := s.server.db.QueryRowx(` + SELECT * from guild_applications WHERE character_id = $1 AND guild_id = $2 AND application_type = $3 + `, charID, guild.ID, applicationType) + + application := &GuildApplication{} + + err := row.StructScan(application) + + if errors.Is(err, sql.ErrNoRows) { + return nil, nil + } + + if err != nil { + s.logger.Error( + "failed to retrieve guild application for character", + zap.Error(err), + zap.Uint32("charID", charID), + zap.Uint32("guildID", guild.ID), + ) + return nil, err + } + + return application, nil +} + +func (guild *Guild) HasApplicationForCharID(s *Session, charID uint32) (bool, error) { + row := s.server.db.QueryRowx(` + SELECT 1 from guild_applications WHERE character_id = $1 AND guild_id = $2 + `, charID, guild.ID) + + num := 0 + + err := row.Scan(&num) + + if errors.Is(err, sql.ErrNoRows) { + return false, nil + } + + if err != nil { + s.logger.Error( + "failed to retrieve guild applications for character", + zap.Error(err), + zap.Uint32("charID", charID), + zap.Uint32("guildID", guild.ID), + ) + return false, err + } + + return true, nil +} + +func CreateGuild(s *Session, guildName string) (int32, error) { + transaction, err := s.server.db.Begin() + + if err != nil { + s.logger.Error("failed to start db transaction", zap.Error(err)) + return 0, err + } + + if err != nil { + panic(err) + } + + guildResult, err := transaction.Query( + "INSERT INTO guilds (name, leader_id) VALUES ($1, $2) RETURNING id", + guildName, s.charID, + ) + + if err != nil { + s.logger.Error("failed to create guild", zap.Error(err)) + rollbackTransaction(s, transaction) + return 0, err + } + + var guildId int32 + + guildResult.Next() + + err = guildResult.Scan(&guildId) + + if err != nil { + s.logger.Error("failed to retrieve guild ID", zap.Error(err)) + rollbackTransaction(s, transaction) + return 0, err + } + + err = guildResult.Close() + + if err != nil { + s.logger.Error("failed to finalise query", zap.Error(err)) + rollbackTransaction(s, transaction) + return 0, err + } + + _, err = transaction.Exec(` + INSERT INTO guild_characters (guild_id, character_id) + VALUES ($1, $2) + `, guildId, s.charID) + + if err != nil { + s.logger.Error("failed to add character to guild", zap.Error(err)) + rollbackTransaction(s, transaction) + return 0, err + } + + err = transaction.Commit() + + if err != nil { + s.logger.Error("failed to commit guild creation", zap.Error(err)) + return 0, err + } + + return guildId, nil +} + +func rollbackTransaction(s *Session, transaction *sql.Tx) { + err := transaction.Rollback() + + if err != nil { + s.logger.Error("failed to rollback transaction", zap.Error(err)) + } +} + +func FindGuildsByName(s *Session, name string) ([]*Guild, error) { + searchTerm := fmt.Sprintf("%%%s%%", name) + + rows, err := s.server.db.Queryx(fmt.Sprintf(` + %s + WHERE g.name ILIKE $1 + `, guildInfoSelectQuery), searchTerm) + + if err != nil { + s.logger.Error("failed to find guilds for search term", zap.Error(err), zap.String("searchTerm", name)) + return nil, err + } + + defer rows.Close() + + guilds := make([]*Guild, 0) + + for rows.Next() { + guild, err := buildGuildObjectFromDbResult(rows, err, s) + + if err != nil { + return nil, err + } + + guilds = append(guilds, guild) + } + + return guilds, nil +} + +func GetGuildInfoByID(s *Session, guildID uint32) (*Guild, error) { + rows, err := s.server.db.Queryx(fmt.Sprintf(` + %s + WHERE g.id = $1 + LIMIT 1 + `, guildInfoSelectQuery), guildID) + + if err != nil { + s.logger.Error("failed to retrieve guild", zap.Error(err), zap.Uint32("guildID", guildID)) + return nil, err + } + + defer rows.Close() + + hasRow := rows.Next() + + if !hasRow { + return nil, nil + } + + return buildGuildObjectFromDbResult(rows, err, s) +} + +func GetGuildInfoByCharacterId(s *Session, charID uint32) (*Guild, error) { + rows, err := s.server.db.Queryx(fmt.Sprintf(` + %s + WHERE EXISTS( + SELECT 1 + FROM guild_characters gc1 + WHERE gc1.character_id = $1 + AND gc1.guild_id = g.id + ) + OR EXISTS( + SELECT 1 + FROM guild_applications ga + WHERE ga.character_id = $1 + AND ga.guild_id = g.id + AND ga.application_type = 'applied' + ) + LIMIT 1 + `, guildInfoSelectQuery), charID) + + if err != nil { + s.logger.Error("failed to retrieve guild for character", zap.Error(err), zap.Uint32("charID", charID)) + return nil, err + } + + defer rows.Close() + + hasRow := rows.Next() + + if !hasRow { + return nil, nil + } + + return buildGuildObjectFromDbResult(rows, err, s) +} + +func buildGuildObjectFromDbResult(result *sqlx.Rows, err error, s *Session) (*Guild, error) { + guild := &Guild{} + + err = result.StructScan(guild) + + if err != nil { + s.logger.Error("failed to retrieve guild data from database", zap.Error(err)) + return nil, err + } + + return guild, nil +} + +func handleMsgMhfCreateGuild(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfCreateGuild) + + guildId, err := CreateGuild(s, pkt.Name) + + if err != nil { + bf := byteframe.NewByteFrame() + + // No reasoning behind these values other than they cause a 'failed to create' + // style message, it's better than nothing for now. + bf.WriteUint32(0x01010101) + + doAckSimpleFail(s, pkt.AckHandle, bf.Data()) + return + } + + bf := byteframe.NewByteFrame() + + bf.WriteUint32(uint32(guildId)) + + doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfOperateGuild(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfOperateGuild) + + guild, err := GetGuildInfoByID(s, pkt.GuildID) + + if err != nil { + return + } + + characterGuildInfo, err := GetCharacterGuildData(s, s.charID) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + bf := byteframe.NewByteFrame() + + switch pkt.Action { + case mhfpacket.OPERATE_GUILD_ACTION_DISBAND: + if guild.LeaderCharID != s.charID { + s.logger.Warn(fmt.Sprintf("character '%d' is attempting to manage guild '%d' without permission", s.charID, guild.ID)) + return + } + + err = guild.Disband(s) + response := 0x01 + + if err != nil { + // All successful acks return 0x01, assuming 0x00 is failure + response = 0x00 + } + + bf.WriteUint32(uint32(response)) + case mhfpacket.OPERATE_GUILD_ACTION_APPLY: + err = guild.CreateApplication(s, s.charID, GuildApplicationTypeApplied, nil) + + if err != nil { + // All successful acks return 0x01, assuming 0x00 is failure + bf.WriteUint32(0x00) + } else { + bf.WriteUint32(guild.LeaderCharID) + } + case mhfpacket.OPERATE_GUILD_ACTION_LEAVE: + var err error + + if characterGuildInfo.IsApplicant { + err = guild.RejectApplication(s, s.charID) + } else { + err = guild.RemoveCharacter(s, s.charID) + } + + response := 0x01 + + if err != nil { + // All successful acks return 0x01, assuming 0x00 is failure + response = 0x00 + } + + bf.WriteUint32(uint32(response)) + case mhfpacket.OPERATE_GUILD_ACTION_DONATE: + err := handleOperateGuildActionDonate(s, guild, pkt, bf) + + if err != nil { + return + } + case mhfpacket.OPERATE_GUILD_SET_AVOID_LEADERSHIP_TRUE: + handleAvoidLeadershipUpdate(s, pkt, true) + case mhfpacket.OPERATE_GUILD_SET_AVOID_LEADERSHIP_FALSE: + handleAvoidLeadershipUpdate(s, pkt, false) + case mhfpacket.OPERATE_GUILD_ACTION_UPDATE_COMMENT: + pbf := byteframe.NewByteFrameFromBytes(pkt.UnkData) + + if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + commentLength := pbf.ReadUint8() + _ = pbf.ReadUint32() + + guild.Comment, err = s.clientContext.StrConv.Decode(bfutil.UpToNull(pbf.ReadBytes(uint(commentLength)))) + + if err != nil { + s.logger.Warn("failed to convert guild comment to UTF8", zap.Error(err)) + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + break + } + + err = guild.Save(s) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + bf.WriteUint32(0x00) + case mhfpacket.OPERATE_GUILD_ACTION_UPDATE_MOTTO: + if !characterGuildInfo.IsLeader && !characterGuildInfo.IsSubLeader() { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + guild.SubMotto = pkt.UnkData[3] + guild.MainMotto = pkt.UnkData[4] + + err := guild.Save(s) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + default: + panic(fmt.Sprintf("unhandled operate guild action '%d'", pkt.Action)) + } + + doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleAvoidLeadershipUpdate(s *Session, pkt *mhfpacket.MsgMhfOperateGuild, avoidLeadership bool) { + characterGuildData, err := GetCharacterGuildData(s, s.charID) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + characterGuildData.AvoidLeadership = avoidLeadership + + err = characterGuildData.Save(s) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} + +func handleOperateGuildActionDonate(s *Session, guild *Guild, pkt *mhfpacket.MsgMhfOperateGuild, bf *byteframe.ByteFrame) error { + + var rpDB uint16 + var guildHallLvl uint16 + + rp := binary.BigEndian.Uint16(pkt.UnkData[3:5]) + + saveData, err := GetCharacterSaveData(s, s.charID) + + if err != nil { + return err + } + + if saveData.RP < rp { + s.logger.Warn( + "character attempting to donate more RP than they own", + zap.Uint32("charID", s.charID), + zap.Uint16("rp", rp), + ) + return err + } + + saveData.RP -= rp + + transaction, err := s.server.db.Begin() + + if err != nil { + s.logger.Error("failed to start db transaction", zap.Error(err)) + return err + } + + err = saveData.Save(s, transaction) + + if err != nil { + err = transaction.Rollback() + + if err != nil { + s.logger.Error("failed to rollback transaction", zap.Error(err)) + } + + return err + } + + err = guild.DonateRP(s, rp, transaction) + + if err != nil { + err = transaction.Rollback() + + if err != nil { + s.logger.Error("failed to rollback transaction", zap.Error(err)) + } + + return err + } + + err = transaction.Commit() + + if err != nil { + s.logger.Error("failed to commit transaction", zap.Error(err)) + return err + } + + bf.WriteUint32(uint32(saveData.RP)) // Points remaining + + errSelectSQL := s.server.db.QueryRow("SELECT rp FROM guilds WHERE id=$1", guild.ID).Scan(&rpDB) + + if errSelectSQL != nil { + s.logger.Fatal("Failed to get rp from db", zap.Error(errSelectSQL)) + } + + guildHallLvl = rpDB / 70 + + if guildHallLvl >= 17 { + guildHallLvl = 17 + } + fmt.Printf("\n\nrpDB = %d\n", rpDB) + fmt.Printf("guildHallLvl = %d\n", guildHallLvl) + + _, errUpdateSQL := s.server.db.Exec("UPDATE guilds SET guild_hall=$1 WHERE id=$2", guildHallLvl, guild.ID) + if errUpdateSQL == nil { + s.logger.Error("failed to donate RP to guild", zap.Error(errUpdateSQL), zap.Uint32("guildID", guild.ID)) + return err + } + + return nil +} + +func handleMsgMhfOperateGuildMember(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfOperateGuildMember) + + guild, err := GetGuildInfoByCharacterId(s, pkt.CharID) + + if err != nil || guild == nil { + doAckSimpleFail(s, pkt.AckHandle, nil) + return + } + + actorCharacter, err := GetCharacterGuildData(s, s.charID) + + if err != nil || (!actorCharacter.IsSubLeader() && guild.LeaderCharID != s.charID) { + doAckSimpleFail(s, pkt.AckHandle, nil) + return + } + + if pkt.Action == mhfpacket.OPERATE_GUILD_MEMBER_ACTION_ACCEPT || pkt.Action == mhfpacket.OPERATE_GUILD_MEMBER_ACTION_REJECT { + switch pkt.Action { + case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_ACCEPT: + err = guild.AcceptApplication(s, pkt.CharID) + case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_REJECT: + err = guild.RejectApplication(s, pkt.CharID) + } + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, nil) + } + + doAckSimpleSucceed(s, pkt.AckHandle, nil) + return + } + + character, err := GetCharacterGuildData(s, pkt.CharID) + + if err != nil || character == nil { + doAckSimpleFail(s, pkt.AckHandle, nil) + return + } + + switch pkt.Action { + case mhfpacket.OPERATE_GUILD_MEMBER_ACTION_KICK: + err = guild.RemoveCharacter(s, pkt.CharID) + default: + doAckSimpleFail(s, pkt.AckHandle, nil) + panic(fmt.Sprintf("unhandled operateGuildMember action '%d'", pkt.Action)) + } + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, nil) + return + } + + doAckSimpleSucceed(s, pkt.AckHandle, nil) +} + +func handleMsgMhfInfoGuild(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfInfoGuild) + + var guild *Guild + var err error + + if pkt.GuildID > 0 { + guild, err = GetGuildInfoByID(s, pkt.GuildID) + } else { + guild, err = GetGuildInfoByCharacterId(s, s.charID) + } + + if err == nil && guild != nil { + guildName, err1 := stringsupport.ConvertUTF8ToShiftJIS(guild.Name) + if err1 != nil { + s.server.logger.Info("ERROR GUILD NAME !") + } + + guildComment, err2 := stringsupport.ConvertUTF8ToShiftJIS(guild.Comment) + if err2 != nil { + s.server.logger.Info("ERROR GUILD COMMENT !") + } + + characterGuildData, err := GetCharacterGuildData(s, s.charID) + + characterJoinedAt := uint32(0xFFFFFFFF) + + if characterGuildData != nil && characterGuildData.JoinedAt != nil { + characterJoinedAt = uint32(characterGuildData.JoinedAt.Unix()) + } + + if err != nil { + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) // Count + resp.WriteUint8(0) // Unk, read if count == 0. + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + return + } + + bf := byteframe.NewByteFrame() + + bf.WriteUint32(guild.ID) + bf.WriteUint32(guild.LeaderCharID) + // Unk 0x09 = Guild Hall available, maybe guild hall type? + // Guild hall available on at least + // 0x09 0x08 0x02 + // Should just be outright guild level for guild hall features, 17 gives everything + bf.WriteUint16(guild.GuildHallType) + bf.WriteUint16(guild.MemberCount) + + bf.WriteUint8(guild.MainMotto) + bf.WriteUint8(guild.SubMotto) + + // Unk appears to be static + bf.WriteBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + + if characterGuildData == nil || characterGuildData.IsApplicant { + bf.WriteUint16(0x00) + } else if characterGuildData.IsSubLeader() || guild.LeaderCharID == s.charID { + bf.WriteUint16(0x01) + } else { + bf.WriteUint16(0x02) + } + + leaderName := s.clientContext.StrConv.MustEncode(guild.LeaderName) + + bf.WriteUint32(uint32(guild.CreatedAt.Unix())) + bf.WriteUint32(characterJoinedAt) + bf.WriteUint8(uint8(len(guildName))) + bf.WriteUint8(uint8(len(guildComment))) + bf.WriteUint8(uint8(5)) // Length of unknown string below + bf.WriteUint8(uint8(len(leaderName) + 1)) + bf.WriteBytes(guildName) + bf.WriteBytes(guildComment) + + bf.WriteUint8(FestivalColourCodes[guild.FestivalColour]) + + bf.WriteUint32(guild.RP) + bf.WriteNullTerminatedBytes(leaderName) + //bf.WriteBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00}) // Unk + bf.WriteBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x18, 0xBD}) // Level 17 guild's version + + // Pugi's names, probably expected as null until you have them with levels? Null gives them a default japanese name + for i := 0; i < 3; i++ { + bf.WriteUint8(0x1) // Name Length - 1 minimum due to null byte + bf.WriteUint8(0x0) // Name string + } + + // probably guild pugi properties, should be status, stamina and luck outfits + bf.WriteBytes([]byte{ + 0x04, 0x02, 0x03, 0x04, 0x02, 0x03, 0x00, 0x00, 0x00, 0x4E, + }) + + // Unk flags + bf.WriteUint8(0x3C) // also seen as 0x32 on JP and 0x64 on TW + + bf.WriteBytes([]byte{ + 0x00, 0x00, 0xD6, 0xD8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }) + + bf.WriteUint32(0x00) // Alliance ID + + // TODO add alliance parts here + // + //if (AllianceID != 0) { + // uint16 AllianceDataUnk; + // uint16 AllianceDataUnk; + // uint16 AllianceNameLength; + // char AllianceName[AllianceNameLength]; + // + // byte NumAllianceMembers; + // + // struct AllianceMember { + // uint32 Unk; + // uint32 Unk; + // uint16 Unk; + // uint16 Unk; + // uint16 Unk; + // uint16 GuildNameLength; + // char GuildName[GuildNameLength]; + // uint16 GuildLeaderNameLength; + // char GuildLeaderName[GuildLeaderNameLength]; + // + // } member[NumAllianceMembers] ; + //} + + applicants, err := GetGuildMembers(s, guild.ID, true) + + if err != nil { + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) // Count + resp.WriteUint8(5) // Unk, read if count == 0. + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + } + + bf.WriteUint16(uint16(len(applicants))) + + for _, applicant := range applicants { + applicantName := s.clientContext.StrConv.MustEncode(applicant.Name) + bf.WriteUint32(applicant.CharID) + bf.WriteUint32(0x05) + bf.WriteUint32(0x00320000) + bf.WriteUint8(uint8(len(applicantName) + 1)) + bf.WriteNullTerminatedBytes(applicantName) + } + + // This is guild icon data + // temp canned bytes to avoid crashing when a guild has more than 1-2 members and a guild hall + //bf.WriteBytes([]byte{0x00, 0x05, 0x00, 0x03, 0x00, 0x38, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x04, 0x00, 0x03, + // 0x00, 0x02, 0x00, 0x38, 0x01, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0x00, 0x69, 0x00, 0x60, 0x00, 0x01, + // 0x00, 0x38, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x6A, 0x00, 0x03, 0x00, 0x00, 0x00, 0x38, + // 0x01, 0x00, 0x02, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x63, 0x00, 0x06, 0x00, 0x35, 0x01, 0x03, + // 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x11, 0x00, 0x01, 0x00, + //}) + + // Unk bool? if true +3 bytes after this + bf.WriteUint8(0x00) + + if guild.Icon != nil { + bf.WriteUint16(uint16(len(guild.Icon.Parts))) + + for _, p := range guild.Icon.Parts { + bf.WriteUint16(p.Index) + bf.WriteUint16(p.ID) + bf.WriteUint8(0x01) + bf.WriteUint8(p.Size) + bf.WriteUint8(p.Rotation) + bf.WriteUint8(0xFF) + bf.WriteUint16(0xFFFF) + bf.WriteUint16(p.PosX) + bf.WriteUint16(p.PosY) + } + } else { + bf.WriteUint16(0x00) + } + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + } else { + //// REALLY large/complex format... stubbing it out here for simplicity. + //resp := byteframe.NewByteFrame() + //resp.WriteUint32(0) // Count + //resp.WriteUint8(0) // Unk, read if count == 0. + + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 8)) + } +} + +func handleMsgMhfEnumerateGuild(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateGuild) + + var guilds []*Guild + var err error + + switch pkt.Type { + case mhfpacket.ENUMERATE_GUILD_TYPE_NAME: + // I have no idea if is really little endian, but it seems too weird to have a random static + // 0x00 before the string + searchTermLength := binary.LittleEndian.Uint16(pkt.RawDataPayload[9:11]) + searchTerm := pkt.RawDataPayload[11 : 11+searchTermLength] + + var searchTermSafe string + + searchTermSafe, err = s.clientContext.StrConv.Decode(bfutil.UpToNull(searchTerm)) + + if err != nil { + panic(err) + } + + guilds, err = FindGuildsByName(s, searchTermSafe) + default: + panic(fmt.Sprintf("no handler for guild search type '%d'", pkt.Type)) + } + + if err != nil || guilds == nil { + stubEnumerateNoResults(s, pkt.AckHandle) + return + } + + bf := byteframe.NewByteFrame() + bf.WriteUint16(uint16(len(guilds))) + + for _, guild := range guilds { + guildName := s.clientContext.StrConv.MustEncode(guild.Name) + leaderName := s.clientContext.StrConv.MustEncode(guild.LeaderName) + + bf.WriteUint8(0x00) // Unk + bf.WriteUint32(guild.ID) + bf.WriteUint32(guild.LeaderCharID) + bf.WriteUint16(guild.MemberCount) + bf.WriteUint8(0x00) // Unk + bf.WriteUint8(0x00) // Unk + bf.WriteUint16(0x00) // Rank + bf.WriteUint32(uint32(guild.CreatedAt.Unix())) + bf.WriteUint8(uint8(len(guildName))) + bf.WriteBytes(guildName) + bf.WriteUint8(uint8(len(leaderName))) + bf.WriteBytes(leaderName) + bf.WriteUint8(0x01) // Unk + } + + bf.WriteUint8(0x01) // Unk + bf.WriteUint8(0x00) // Unk + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfArrangeGuildMember(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfArrangeGuildMember) + + guild, err := GetGuildInfoByID(s, pkt.GuildID) + + if err != nil { + s.logger.Error( + "failed to respond to ArrangeGuildMember message", + zap.Uint32("charID", s.charID), + ) + return + } + + if guild.LeaderCharID != s.charID { + s.logger.Error("non leader attempting to rearrange guild members!", + zap.Uint32("charID", s.charID), + zap.Uint32("guildID", guild.ID), + ) + return + } + + err = guild.ArrangeCharacters(s, pkt.CharIDs) + + if err != nil { + s.logger.Error( + "failed to respond to ArrangeGuildMember message", + zap.Uint32("charID", s.charID), + zap.Uint32("guildID", guild.ID), + ) + return + } + + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} + +func handleMsgMhfEnumerateGuildMember(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateGuildMember) + + var guild *Guild + var err error + + if pkt.GuildID > 0 { + guild, err = GetGuildInfoByID(s, pkt.GuildID) + } else { + guild, err = GetGuildInfoByCharacterId(s, s.charID) + } + + if err != nil { + s.logger.Warn("failed to retrieve guild sending no result message") + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) + return + } else if guild == nil { + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 2)) + return + } + + guildMembers, err := GetGuildMembers(s, guild.ID, false) + + if err != nil { + s.logger.Error("failed to retrieve guild") + return + } + + bf := byteframe.NewByteFrame() + + bf.WriteUint16(guild.MemberCount) + + sort.Slice(guildMembers[:], func(i, j int) bool { + return guildMembers[i].OrderIndex < guildMembers[j].OrderIndex + }) + + for _, member := range guildMembers { + name := s.clientContext.StrConv.MustEncode(member.Name) + + bf.WriteUint32(member.CharID) + + // Exp, HR[x] is split by 0, 1, 30, 50, 99, 299, 998, 999 + bf.WriteUint16(member.Exp) // Rank flags + bf.WriteUint16(0x00) // Grank + bf.WriteUint16(0x00) // Unk + bf.WriteUint16(0x00) // Some rank? + bf.WriteUint8(member.OrderIndex) + bf.WriteUint16(uint16(len(name) + 1)) + bf.WriteNullTerminatedBytes(name) + } + + for _, member := range guildMembers { + bf.WriteUint32(member.LastLogin) + } + + bf.WriteBytes([]byte{0x00, 0x00}) // Unk, might be to do with alliance, 0x00 == no alliance + + for range guildMembers { + bf.WriteUint32(0x00) // Unk + } + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfGetGuildManageRight(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetGuildManageRight) + + guild, err := GetGuildInfoByCharacterId(s, s.charID) + + if err != nil { + s.logger.Warn("failed to respond to manage rights message") + return + } else if guild == nil { + bf := byteframe.NewByteFrame() + bf.WriteUint16(0x00) // Unk + bf.WriteUint16(0x00) // Member count + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) + return + } + + bf := byteframe.NewByteFrame() + + bf.WriteUint16(0x00) // Unk + bf.WriteUint16(guild.MemberCount) + + members, _ := GetGuildMembers(s, guild.ID, false) + + for _, member := range members { + bf.WriteUint32(member.CharID) + bf.WriteUint32(0x0) + } + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfGetUdGuildMapInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdGuildMapInfo) + + data, _ := hex.DecodeString("00050000013600000137013500000000E2DF000000000204000000640100000001019901350000E2DF0000000001000000044C000000000001FE01FF00000000000000000D0000001036000000000001FC01FD00000000000000000B0000000F0A000000000001FB01FC00000000000000000A0000000E740000000000019B013700000000000000000F00000011620000000000019601FB0000000000000000090000000DDE0000000000013700D400000000000000001000000011F80000000000013201960000000000000000080000000D48000000000000D40070000000000000000011000000128E000000000000CE01320000000000000000070000000CB200000000000070006F00000000000000001200000013240000000000006F006E00000000000000001300000013BA0000000000006E006D00000000000000001400000014500000000000006D0000000000000000000015020000157C0000000000006A00CE0000000000000000060000000C1C00000000000069006A0000000000000000050000000B860000000000006800690000000000000000040000000AF00000000000006700680000000000000000030000000A5A00000000000066006700000000000000000200000009C4000000000001FD01FE01990000000000000C0300000FA00000000000006500660000000000000000010100000000000000000001FF019B00000000000000000E00000010CC0000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013700000138013200000000E2E0000000000204000000640100000002019701320000E2E00000000001000000044C00000000000193012E00000000000000000E000000319C0000000000013701360000000000000000060000001EDC00000000000136019900000000000000000700000021340000000000012E012D00000000000000000F00000033F40000000000019801FB01970000000000000903000025E4000000000001F9019400000000000000000C0000002CEC0000000000012D00C9000000000000000010000000364C000000000000D401370000000000000000050000001C84000000000000C9006600000000000000001100000036B00000000000007000D40000000000000000040000001A2C000000000001FA01F900000000000000000B0000002A940000000000006F007000000000000000000300000017D40000000000006E006F000000000000000002000000157C0000000000006D006E00000000000000000101000000000000000000006900000000000000000000150200004362000000000001FB01FA00000000000000000A000000283C0000000000006800690000000000000000140000003B6000000000000067006800000000000000001300000039D0000000000001990198000000000000000008000000238C000000000000660067000000000000000012000000390800000000000194019300000000000000000D0000002F44000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001380000013901FF00000000E2E10000000001040000044C0000000003019B013601FF0000000000000D0300003BC4000000000001FA000000000000000000001502000055F0000000000001F901FA00000000000000001400000051A400000000000199013400000000000000000F00000042040000000000019501F90000000000000000130000004E8400000000000138019B00000000000000000C00000038A400000000000136019900000000000000000E0000003EE4000000000001340133000000000000000010000000452400000000000133013200000000000000001100000048440000000000013201950000000000000000120000004B64000000000000D4013800000000000000000B0000003584000000000000D1006E0000000000000000070000002904000000000000CD006A0000000000000000030000001C840000000000007000D400000000000000000A00000032640000000000006F00700000000000000000090000002F440000000000006E006F0000000000000000080000002C240000000000006C00D100000000000000000600000025E40000000000006B006C00000000000000000500000022C40000000000006A006B0000000000000000040000001FA40000000000006800CD000000000000000002000000196400000000000067006800000000000000000101000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001390000013A006500000000E2E200000000020400000064010000000500C900650000E2E20000000001000000044C00000000000133019700000000000000000C040000445C0000000004013700D20000000000000000130000005FB4000000000000CA00CB00C9000000000000060300002CEC000000000001FF019B00000000000000001100000057E4000000000001FE01FF00000000000000001000000053FC000000000001FD01FE00000000000000000F0000005014000000000001FA01F90000000000000000010100000000000000000001F901940000000000000000020000001D4C0000000000019B01370000000000000000120000005BCC0000000000019801FD00000000000000000E0000004C2C00000000000197019800000000000000000D0000004844000000000001940193000000000000000003000000213400000000000193012E000000000000000004000000251C0000000000012E00CA0000000000000000050000002904000000000000D2006E000000000000000014000000639C000000000000CF013300000000000000000B0000004074000000000000CB006800000000000000000700000030D40000000000006E000000000000000000001502000075300000000000006A00CF00000000000000000A0000003C8C00000000000069006A00000000000000000900000038A400000000000068006900000000000000000800000034BC0000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000013A0000013701F800000000E2E30000000001040000044C000000000601FD01FC00000000000000000700000034BC000000000001FC01FB00000000000000000800000038A4000000000001FB01FA0000000000000000090000003C8C000000000001FA01F900000000000000000A00000040740000000000019B019A0000000000000000050000002CEC0000000000019A01FD00000000000000000600000030D400000000000195013200000000000000000C000000484400000000000138019B00000000000000000400000029040000000000013300CF00000000000000000E000000501400000000000132013300000000000000000D0000004C2C000000000000D40138000000000000000003000000251C000000000000D300D40000000000000000020000002134000000000000CF006A00000000000000000F00000053FC000000000000CD00CC0000000000000000110000005BCC000000000000CC00CB0000000000000000120000005FB4000000000000CB00CA000000000000000013000000639C000000000000CA00C90000000000000000140000006784000000000000C90000000000000000000015020000FDE80000000000006E00D30000000000000000010100000000000000000001F9019501F80000000000000B030000445C0000000000006A00CD00000000000000001000000057E400000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009000000010738AD00010001000102000000011A000007D00002006302000000020738AD00020001000102000000021A000007D00002006302000000031A000003E80001006301000000041A000003E80001006301000000050738AD00020001000102000000051A000007D00002006302000000061A000003E800010063010100000136000117000000000000044C019901350000E2DF000000000100000000000000000064013500000000E2DF00000000020400000000000000000000650066000000000000000001010100000000000009C40066006700000000000000000200000000000000000A5A0067006800000000000000000300000000000000000AF00068006900000000000000000400000000000000000B860069006A00000000000000000500000000000000000C1C006A00CE00000000000000000600000000000000000CB200CE013200000000000000000700000000000000000D480132019600000000000000000800000000000000000DDE019601FB00000000000000000900000000000000000E7401FB01FC00000000000000000A00000000000000000F0A01FC01FD00000000000000000B00000000000000000FA001FD01FE01990000000000000C0300000000000000103601FE01FF00000000000000000D000000000000000010CC01FF019B00000000000000000E00000000000000001162019B013700000000000000000F000000000000000011F8013700D40000000000000000100000000000000000128E00D40070000000000000000011000000000000000013240070006F000000000000000012000000000000000013BA006F006E00000000000000001300000000000000001450006E006D0000000000000000140000000000000000157C006D000000000000000000001502000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetGuildTargetMemberNum(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetGuildTargetMemberNum) + + var guild *Guild + var err error + + if pkt.GuildID == 0x0 { + guild, err = GetGuildInfoByCharacterId(s, s.charID) + } else { + guild, err = GetGuildInfoByID(s, pkt.GuildID) + } + + if err != nil { + s.logger.Warn("failed to find guild", zap.Error(err), zap.Uint32("guildID", pkt.GuildID)) + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + return + } else if guild == nil { + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) + return + } + + bf := byteframe.NewByteFrame() + + bf.WriteUint16(0x0) + bf.WriteUint16(guild.MemberCount - 1) + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfEnumerateGuildItem(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateGuildItem) + + data, _ := hex.DecodeString("000100004cfa00010017000300000000") + + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfUpdateGuildIcon(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfUpdateGuildIcon) + + guild, err := GetGuildInfoByID(s, pkt.GuildID) + + if err != nil { + panic(err) + } + + characterInfo, err := GetCharacterGuildData(s, s.charID) + + if err != nil { + panic(err) + } + + if !characterInfo.IsSubLeader() && !characterInfo.IsLeader { + s.logger.Warn( + "character without leadership attempting to update guild icon", + zap.Uint32("guildID", guild.ID), + zap.Uint32("charID", s.charID), + ) + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + icon := &GuildIcon{} + + icon.Parts = make([]GuildIconPart, pkt.PartCount) + + for i, p := range pkt.IconParts { + icon.Parts[i] = GuildIconPart{ + Index: p.Index, + ID: p.ID, + Size: p.Size, + Rotation: p.Rotation, + PosX: p.PosX, + PosY: p.PosY, + } + } + + guild.Icon = icon + + err = guild.Save(s) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} + +func handleMsgMhfReadGuildcard(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadGuildcard) + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfGetGuildMissionList(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetGuildMissionList) + + decoded, err := hex.DecodeString("000694610000023E000112990023000100000200015DDD232100069462000002F30000005F000C000200000300025DDD232100069463000002EA0000005F0006000100000100015DDD23210006946400000245000000530010000200000400025DDD232100069465000002B60001129B0019000100000200015DDD232100069466000003DC0000001B0010000100000600015DDD232100069467000002DA000112A00019000100000400015DDD232100069468000002A800010DEF0032000200000200025DDD2321000694690000045500000022003C000200000600025DDD23210006946A00000080000122D90046000200000300025DDD23210006946B000001960000003B000A000100000100015DDD23210006946C0000049200000046005A000300000600035DDD23210006946D000000A4000000260018000200000600025DDD23210006946E0000017A00010DE40096000300000100035DDD23210006946F000001BE0000005E0014000200000400025DDD2355000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + + if err != nil { + panic(err) + } + + doAckBufSucceed(s, pkt.AckHandle, decoded) +} + +func handleMsgMhfGetGuildMissionRecord(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetGuildMissionRecord) + + // No guild mission records = 0x190 empty bytes + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x190)) +} + +func handleMsgMhfLoadGuildCooking(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadGuildCooking) + // MealData + // uint16 meal count + // Meal + // uint32 hash? + // uint32 unk + // uint32 success level + // uint32 expiration timestamp + + // encourage food + data := []byte{0x00, 0x01, 0x0F, 0x51, 0x97, 0xFF, 0x00, 0x00, 0x02, 0xC4, 0x00, 0x00, 0x00, 0x03, 0x5F, 0xFC, 0x0B, 0x51} + doAckBufSucceed(s, pkt.AckHandle, data) + //data := []byte{0x00, 0x01, 0x1C, 0x72, 0x54, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x5F, 0xF8, 0x2F, 0xE1} + //doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfRegistGuildCooking(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfRegistGuildCooking) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x01, 0x00}) +} + +func handleMsgMhfLoadGuildAdventure(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadGuildAdventure) + data := []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetGuildWeeklyBonusMaster(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetGuildWeeklyBonusMaster) + + // Values taken from brand new guild capture + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x28)) +} +func handleMsgMhfGetGuildWeeklyBonusActiveCount(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetGuildWeeklyBonusActiveCount) + + // Values taken from brand new guild capture + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x03)) +} + +func handleMsgMhfGuildHuntdata(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGuildHuntdata) + data := []byte{0x01, 0xFE} + doAckBufSucceed(s, pkt.AckHandle, data) +} + +// "Enumrate_guild_msg_board" +func handleMsgSysReserve202(s *Session, p mhfpacket.MHFPacket) {} + +// "Is_update_guild_msg_board" +func handleMsgSysReserve203(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysReserve203) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfEntryRookieGuild(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfUpdateForceGuildRank(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAddGuildWeeklyBonusExceptionalUser(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfRegistGuildAdventure(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireGuildAdventure(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfChargeGuildAdventure(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAddGuildMissionCount(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfSetGuildMissionTarget(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfCancelGuildMissionTarget(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGenerateUdGuildMap(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfUpdateGuild(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfSetGuildManageRight(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEnumerateInvGuild(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfOperationInvGuild(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfUpdateGuildcard(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfUpdateGuildItem(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_guild_member.go b/Erupe/server/channelserver/handlers_guild_member.go new file mode 100644 index 000000000..fae27ec69 --- /dev/null +++ b/Erupe/server/channelserver/handlers_guild_member.go @@ -0,0 +1,130 @@ +package channelserver + +import ( + "fmt" + "time" + + "github.com/jmoiron/sqlx" + "go.uber.org/zap" +) + +type GuildMember struct { + GuildID uint32 `db:"guild_id"` + CharID uint32 `db:"character_id"` + JoinedAt *time.Time `db:"joined_at"` + Name string `db:"name"` + IsApplicant bool `db:"is_applicant"` + OrderIndex uint8 `db:"order_index"` + LastLogin uint32 `db:"last_login"` + AvoidLeadership bool `db:"avoid_leadership"` + IsLeader bool `db:"is_leader"` + Exp uint16 `db:"exp"` +} + +func (gm *GuildMember) IsSubLeader() bool { + return gm.OrderIndex <= 3 && !gm.AvoidLeadership +} + +func (gm *GuildMember) Save(s *Session) error { + _, err := s.server.db.Exec("UPDATE guild_characters SET avoid_leadership=$1 WHERE character_id=$2", gm.AvoidLeadership, gm.CharID) + + if err != nil { + s.logger.Error( + "failed to update guild member data", + zap.Error(err), + zap.Uint32("charID", gm.CharID), + zap.Uint32("guildID", gm.GuildID), + ) + return err + } + return nil +} + +//TODO add the recruiter permission to this check when it exists +func (gm *GuildMember) IsRecruiter() bool { + return gm.IsLeader || gm.IsSubLeader() +} + +const guildMembersSelectSQL = ` +SELECT g.id as guild_id, + joined_at, + c.name, + character.character_id, + coalesce(gc.order_index, 0) as order_index, + c.last_login, + coalesce(gc.avoid_leadership, false) as avoid_leadership, + c.exp, + character.is_applicant, + CASE WHEN g.leader_id = c.id THEN 1 ELSE 0 END as is_leader +FROM ( + SELECT character_id, true as is_applicant, guild_id + FROM guild_applications ga + WHERE ga.application_type = 'applied' + UNION + SELECT character_id, false as is_applicant, guild_id + FROM guild_characters gc + ) character + JOIN characters c on character.character_id = c.id + LEFT JOIN guild_characters gc ON gc.character_id = character.character_id + JOIN guilds g ON g.id = character.guild_id +` + +func GetGuildMembers(s *Session, guildID uint32, applicants bool) ([]*GuildMember, error) { + rows, err := s.server.db.Queryx(fmt.Sprintf(` + %s + WHERE character.guild_id = $1 AND is_applicant = $2 + `, guildMembersSelectSQL), guildID, applicants) + + if err != nil { + s.logger.Error("failed to retrieve membership data for guild", zap.Error(err), zap.Uint32("guildID", guildID)) + return nil, err + } + + defer rows.Close() + + members := make([]*GuildMember, 0) + + for rows.Next() { + member, err := buildGuildMemberObjectFromDBResult(rows, err, s) + + if err != nil { + return nil, err + } + + members = append(members, member) + } + + return members, nil +} + +func GetCharacterGuildData(s *Session, charID uint32) (*GuildMember, error) { + rows, err := s.server.db.Queryx(fmt.Sprintf("%s WHERE character.character_id=$1", guildMembersSelectSQL), charID) + + if err != nil { + s.logger.Error(fmt.Sprintf("failed to retrieve membership data for character '%d'", charID)) + return nil, err + } + + defer rows.Close() + + hasRow := rows.Next() + + if !hasRow { + return nil, nil + } + + return buildGuildMemberObjectFromDBResult(rows, err, s) +} + +func buildGuildMemberObjectFromDBResult(rows *sqlx.Rows, err error, s *Session) (*GuildMember, error) { + memberData := &GuildMember{} + + err = rows.StructScan(&memberData) + + if err != nil { + s.logger.Error("failed to retrieve guild data from database", zap.Error(err)) + return nil, err + } + + return memberData, nil +} diff --git a/Erupe/server/channelserver/handlers_guild_scout.go b/Erupe/server/channelserver/handlers_guild_scout.go new file mode 100644 index 000000000..ad6cf0006 --- /dev/null +++ b/Erupe/server/channelserver/handlers_guild_scout.go @@ -0,0 +1,310 @@ +package channelserver + +import ( + "fmt" + "io" + "time" + + "github.com/Solenataris/Erupe/common/stringsupport" + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" +) + +func handleMsgMhfPostGuildScout(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPostGuildScout) + + actorCharGuildData, err := GetCharacterGuildData(s, s.charID) + + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + panic(err) + } + + if actorCharGuildData == nil || !actorCharGuildData.IsRecruiter() { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + guildInfo, err := GetGuildInfoByID(s, actorCharGuildData.GuildID) + + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + panic(err) + } + + hasApplication, err := guildInfo.HasApplicationForCharID(s, pkt.CharID) + + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + panic(err) + } + + if hasApplication { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x04}) + return + } + + transaction, err := s.server.db.Begin() + + if err != nil { + panic(err) + } + + err = guildInfo.CreateApplication(s, pkt.CharID, GuildApplicationTypeInvited, transaction) + + if err != nil { + rollbackTransaction(s, transaction) + doAckBufFail(s, pkt.AckHandle, nil) + panic(err) + } + + senderName, err := getCharacterName(s, s.charID) + + if err != nil { + panic(err) + } + + mail := &Mail{ + SenderID: s.charID, + RecipientID: pkt.CharID, + Subject: "Guild! ヽ(・∀・)ノ", + Body: fmt.Sprintf( + "%s has invited you to join the wonderful guild %s, do you accept this challenge?", + senderName, + guildInfo.Name, + ), + IsGuildInvite: true, + } + + err = mail.Send(s, transaction) + + if err != nil { + rollbackTransaction(s, transaction) + doAckBufFail(s, pkt.AckHandle, nil) + return + } + + err = transaction.Commit() + + if err != nil { + doAckBufFail(s, pkt.AckHandle, nil) + panic(err) + } + + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfCancelGuildScout(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfCancelGuildScout) + + guildCharData, err := GetCharacterGuildData(s, s.charID) + + if err != nil { + panic(err) + } + + if guildCharData == nil || !guildCharData.IsRecruiter() { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + guild, err := GetGuildInfoByID(s, guildCharData.GuildID) + + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + err = guild.CancelInvitation(s, pkt.InvitationID) + + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) +} + +func handleMsgMhfAnswerGuildScout(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfAnswerGuildScout) + + guild, err := GetGuildInfoByCharacterId(s, pkt.LeaderID) + + if err != nil { + panic(err) + } + + _, err = guild.GetApplicationForCharID(s, s.charID, GuildApplicationTypeInvited) + + if err != nil { + s.logger.Warn( + "could not retrieve guild invitation", + zap.Error(err), + zap.Uint32("guildID", guild.ID), + zap.Uint32("charID", s.charID), + ) + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + if pkt.Answer { + err = guild.AcceptApplication(s, s.charID) + } else { + err = guild.RejectApplication(s, s.charID) + } + + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + return + } + + senderName, err := getCharacterName(s, pkt.LeaderID) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, nil) + panic(err) + } + + successMail := Mail{ + SenderID: pkt.LeaderID, + RecipientID: s.charID, + Subject: "Happy days!", + Body: fmt.Sprintf("You successfully joined %s and should be proud of all you have accomplished.", guild.Name), + IsGuildInvite: false, + SenderName: senderName, + } + + err = successMail.Send(s, nil) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, nil) + panic(err) + } + + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x81, 0x7e}) +} + +func handleMsgMhfGetGuildScoutList(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetGuildScoutList) + + guildInfo, err := GetGuildInfoByCharacterId(s, s.charID) + + if err != nil { + panic(err) + } + + if guildInfo == nil { + doAckSimpleFail(s, pkt.AckHandle, nil) + return + } + + rows, err := s.server.db.Queryx(` + SELECT c.id, c.name, ga.actor_id + FROM guild_applications ga + JOIN characters c ON c.id = ga.character_id + WHERE ga.guild_id = $1 AND ga.application_type = 'invited' + `, guildInfo.ID) + + if err != nil { + s.logger.Error("failed to retrieve scouted characters", zap.Error(err)) + doAckSimpleFail(s, pkt.AckHandle, nil) + return + } + + defer rows.Close() + + bf := byteframe.NewByteFrame() + + bf.SetBE() + + // Result count, we will overwrite this later + bf.WriteUint32(0x00) + + count := uint32(0) + + for rows.Next() { + var charName string + var charID uint32 + var actorID uint32 + + err = rows.Scan(&charID, &charName, &actorID) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, nil) + panic(err) + } + + // This seems to be used as a unique ID for the invitation sent + // we can just use the charID and then filter on guild_id+charID when performing operations + // this might be a problem later with mails sent referencing IDs but we'll see. + bf.WriteUint32(charID) + bf.WriteUint32(actorID) + bf.WriteUint32(charID) + bf.WriteUint32(uint32(time.Now().Unix())) + bf.WriteUint16(0x00) // HR? + bf.WriteUint16(0x00) // GR? + + charNameBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(charName) + + bf.WriteBytes(charNameBytes) + bf.WriteBytes(make([]byte, 32-len(charNameBytes))) // Fixed length string + count++ + } + + _, err = bf.Seek(0, io.SeekStart) + + if err != nil { + panic(err) + } + + bf.WriteUint32(count) + + doAckBufSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfGetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetRejectGuildScout) + + row := s.server.db.QueryRow("SELECT restrict_guild_scout FROM characters WHERE id=$1", s.charID) + + var currentStatus bool + + err := row.Scan(¤tStatus) + + if err != nil { + s.logger.Error( + "failed to retrieve character guild scout status", + zap.Error(err), + zap.Uint32("charID", s.charID), + ) + doAckSimpleFail(s, pkt.AckHandle, nil) + return + } + + response := uint8(0x00) + + if currentStatus { + response = 0x01 + } + + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, response}) +} + +func handleMsgMhfSetRejectGuildScout(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSetRejectGuildScout) + + _, err := s.server.db.Exec("UPDATE characters SET restrict_guild_scout=$1 WHERE id=$2", pkt.Reject, s.charID) + + if err != nil { + s.logger.Error( + "failed to update character guild scout status", + zap.Error(err), + zap.Uint32("charID", s.charID), + ) + doAckSimpleFail(s, pkt.AckHandle, nil) + return + } + + doAckSimpleSucceed(s, pkt.AckHandle, nil) +} diff --git a/Erupe/server/channelserver/handlers_guild_tresure.go b/Erupe/server/channelserver/handlers_guild_tresure.go new file mode 100644 index 000000000..fe8d77161 --- /dev/null +++ b/Erupe/server/channelserver/handlers_guild_tresure.go @@ -0,0 +1,23 @@ +package channelserver + +import "github.com/Solenataris/Erupe/network/mhfpacket" + +func handleMsgMhfEnumerateGuildTresure(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateGuildTresure) + + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 4)) +} + +func handleMsgMhfRegistGuildTresure(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireGuildTresure(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfOperateGuildTresureReport(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetGuildTresureSouvenir) + + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 6)) +} + +func handleMsgMhfAcquireGuildTresureSouvenir(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_house.go b/Erupe/server/channelserver/handlers_house.go new file mode 100644 index 000000000..af74fd70e --- /dev/null +++ b/Erupe/server/channelserver/handlers_house.go @@ -0,0 +1,133 @@ +package channelserver + +import ( + "encoding/hex" + + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" +) + +func handleMsgMhfUpdateInterior(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEnumerateHouse(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateHouse) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfUpdateHouse(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfLoadHouse(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadHouse) + // Seems to generate same response regardless of upgrade tier + data, _ := hex.DecodeString("0000000000000000000000000000000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetMyhouseInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetMyhouseInfo) + + var data []byte + err := s.server.db.QueryRow("SELECT trophy FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + panic(err) + } + if len(data) > 0 { + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + } +} + +func handleMsgMhfUpdateMyhouseInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfUpdateMyhouseInfo) + + _, err := s.server.db.Exec("UPDATE characters SET trophy=$1 WHERE id=$2", pkt.Unk0, s.charID) + if err != nil { + panic(err) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfLoadDecoMyset(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadDecoMyset) + var data []byte + err := s.server.db.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get preset decorations savedata from db", zap.Error(err)) + } + + if len(data) > 0 { + doAckBufSucceed(s, pkt.AckHandle, data) + //doAckBufSucceed(s, pkt.AckHandle, data) + } else { + // set first byte to 1 to avoid pop up every time without save + body := make([]byte, 0x226) + body[0] = 1 + doAckBufSucceed(s, pkt.AckHandle, body) + } +} + +func handleMsgMhfSaveDecoMyset(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSaveDecoMyset) + // https://gist.github.com/Andoryuuta/9c524da7285e4b5ca7e52e0fc1ca1daf + var loadData []byte + bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload[1:]) // skip first unk byte + err := s.server.db.QueryRow("SELECT decomyset FROM characters WHERE id = $1", s.charID).Scan(&loadData) + if err != nil { + s.logger.Fatal("Failed to get preset decorations savedata from db", zap.Error(err)) + } else { + numSets := bf.ReadUint8() // sets being written + // empty save + if len(loadData) == 0 { + loadData = []byte{0x01, 0x00} + } + + savedSets := loadData[1] // existing saved sets + // no sets, new slice with just first 2 bytes for appends later + if savedSets == 0 { + loadData = []byte{0x01, 0x00} + } + for i := 0; i < int(numSets); i++ { + writeSet := bf.ReadUint16() + dataChunk := bf.ReadBytes(76) + setBytes := append([]byte{uint8(writeSet >> 8), uint8(writeSet & 0xff)}, dataChunk...) + for x := 0; true; x++ { + if x == int(savedSets) { + // appending set + if loadData[len(loadData)-1] == 0x10 { + // sanity check for if there was a messy manual import + loadData = append(loadData[:len(loadData)-2], setBytes...) + } else { + loadData = append(loadData, setBytes...) + } + savedSets++ + break + } + currentSet := loadData[3+(x*78)] + if int(currentSet) == int(writeSet) { + // replacing a set + loadData = append(loadData[:2+(x*78)], append(setBytes, loadData[2+((x+1)*78):]...)...) + break + } else if int(currentSet) > int(writeSet) { + // inserting before current set + loadData = append(loadData[:2+((x)*78)], append(setBytes, loadData[2+((x)*78):]...)...) + savedSets++ + break + } + } + loadData[1] = savedSets // update set count + } + _, err := s.server.db.Exec("UPDATE characters SET decomyset=$1 WHERE id=$2", loadData, s.charID) + if err != nil { + s.logger.Fatal("Failed to update decomyset savedata in db", zap.Error(err)) + } + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfOperateWarehouse(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEnumerateWarehouse(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfUpdateWarehouse(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_kouryou.go b/Erupe/server/channelserver/handlers_kouryou.go new file mode 100644 index 000000000..c3f78bd64 --- /dev/null +++ b/Erupe/server/channelserver/handlers_kouryou.go @@ -0,0 +1,45 @@ +package channelserver + +import ( + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" +) + +func handleMsgMhfAddKouryouPoint(s *Session, p mhfpacket.MHFPacket) { + // hunting with both ranks maxed gets you these + pkt := p.(*mhfpacket.MsgMhfAddKouryouPoint) + var points int + err := s.server.db.QueryRow("UPDATE characters SET kouryou_point=COALESCE(kouryou_point + $1, $1) WHERE id=$2 RETURNING kouryou_point", pkt.KouryouPoints, s.charID).Scan(&points) + if err != nil { + s.logger.Fatal("Failed to update KouryouPoint in db", zap.Error(err)) + } + resp := byteframe.NewByteFrame() + resp.WriteUint32(uint32(points)) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfGetKouryouPoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetKouryouPoint) + var points int + err := s.server.db.QueryRow("SELECT COALESCE(kouryou_point, 0) FROM characters WHERE id = $1", s.charID).Scan(&points) + if err != nil { + s.logger.Fatal("Failed to get kouryou_point savedata from db", zap.Error(err)) + } + resp := byteframe.NewByteFrame() + resp.WriteUint32(uint32(points)) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfExchangeKouryouPoint(s *Session, p mhfpacket.MHFPacket) { + // spent at the guildmaster, 10000 a roll + var points int + pkt := p.(*mhfpacket.MsgMhfExchangeKouryouPoint) + err := s.server.db.QueryRow("UPDATE characters SET kouryou_point=kouryou_point - $1 WHERE id=$2 RETURNING kouryou_point", pkt.KouryouPoints, s.charID).Scan(&points) + if err != nil { + s.logger.Fatal("Failed to update platemyset savedata in db", zap.Error(err)) + } + resp := byteframe.NewByteFrame() + resp.WriteUint32(uint32(points)) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} diff --git a/Erupe/server/channelserver/handlers_mail.go b/Erupe/server/channelserver/handlers_mail.go new file mode 100644 index 000000000..fb81fff22 --- /dev/null +++ b/Erupe/server/channelserver/handlers_mail.go @@ -0,0 +1,335 @@ +package channelserver + +import ( + "database/sql" + "time" + + "github.com/Solenataris/Erupe/common/stringsupport" + "github.com/Solenataris/Erupe/network/binpacket" + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" +) + +type Mail struct { + ID int `db:"id"` + SenderID uint32 `db:"sender_id"` + RecipientID uint32 `db:"recipient_id"` + Subject string `db:"subject"` + Body string `db:"body"` + Read bool `db:"read"` + Deleted bool `db:"deleted"` + AttachedItemReceived bool `db:"attached_item_received"` + AttachedItemID *uint16 `db:"attached_item"` + AttachedItemAmount int16 `db:"attached_item_amount"` + CreatedAt time.Time `db:"created_at"` + IsGuildInvite bool `db:"is_guild_invite"` + SenderName string `db:"sender_name"` +} + +func (m *Mail) Send(s *Session, transaction *sql.Tx) error { + query := ` + INSERT INTO mail (sender_id, recipient_id, subject, body, attached_item, attached_item_amount, is_guild_invite) + VALUES ($1, $2, $3, $4, $5, $6, $7) + ` + + var err error + + if transaction == nil { + _, err = s.server.db.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite) + } else { + _, err = transaction.Exec(query, m.SenderID, m.RecipientID, m.Subject, m.Body, m.AttachedItemID, m.AttachedItemAmount, m.IsGuildInvite) + } + + if err != nil { + s.logger.Error( + "failed to send mail", + zap.Error(err), + zap.Uint32("senderID", m.SenderID), + zap.Uint32("recipientID", m.RecipientID), + zap.String("subject", m.Subject), + zap.String("body", m.Body), + zap.Uint16p("itemID", m.AttachedItemID), + zap.Int16("itemAmount", m.AttachedItemAmount), + zap.Bool("isGuildInvite", m.IsGuildInvite), + ) + return err + } + + return nil +} + +func (m *Mail) MarkRead(s *Session) error { + _, err := s.server.db.Exec(` + UPDATE mail SET read = true WHERE id = $1 + `, m.ID) + + if err != nil { + s.logger.Error( + "failed to mark mail as read", + zap.Error(err), + zap.Int("mailID", m.ID), + ) + return err + } + + return nil +} + +func (m *Mail) MarkDeleted(s *Session) error { + _, err := s.server.db.Exec(` + UPDATE mail SET deleted = true WHERE id = $1 + `, m.ID) + + if err != nil { + s.logger.Error( + "failed to mark mail as deleted", + zap.Error(err), + zap.Int("mailID", m.ID), + ) + return err + } + + return nil +} + +func GetMailListForCharacter(s *Session, charID uint32) ([]Mail, error) { + rows, err := s.server.db.Queryx(` + SELECT + m.id, + m.sender_id, + m.recipient_id, + m.subject, + m.read, + m.attached_item, + m.attached_item_amount, + m.created_at, + m.is_guild_invite, + m.deleted, + c.name as sender_name + FROM mail m + JOIN characters c ON c.id = m.sender_id + WHERE recipient_id = $1 AND deleted = false + ORDER BY m.created_at DESC, id DESC + LIMIT 32 + `, charID) + + if err != nil { + s.logger.Error("failed to get mail for character", zap.Error(err), zap.Uint32("charID", charID)) + return nil, err + } + + defer rows.Close() + + allMail := make([]Mail, 0) + + for rows.Next() { + mail := Mail{} + + err := rows.StructScan(&mail) + + if err != nil { + return nil, err + } + + allMail = append(allMail, mail) + } + + return allMail, nil +} + +func GetMailByID(s *Session, ID int) (*Mail, error) { + row := s.server.db.QueryRowx(` + SELECT + m.id, + m.sender_id, + m.recipient_id, + m.subject, + m.read, + m.body, + m.attached_item, + m.attached_item_amount, + m.created_at, + m.is_guild_invite, + m.deleted, + c.name as sender_name + FROM mail m + JOIN characters c ON c.id = m.sender_id + WHERE m.id = $1 + LIMIT 1 + `, ID) + + mail := &Mail{} + + err := row.StructScan(mail) + + if err != nil { + s.logger.Error( + "failed to retrieve mail", + zap.Error(err), + zap.Int("mailID", ID), + ) + return nil, err + } + + return mail, nil +} + +func SendMailNotification(s *Session, m *Mail, recipient *Session) { + senderName, err := getCharacterName(s, m.SenderID) + + if err != nil { + panic(err) + } + + bf := byteframe.NewByteFrame() + + notification := &binpacket.MsgBinMailNotify{ + SenderName: senderName, + } + + notification.Build(bf) + + castedBinary := &mhfpacket.MsgSysCastedBinary{ + CharID: m.SenderID, + BroadcastType: 0x00, + MessageType: BinaryMessageTypeMailNotify, + RawDataPayload: bf.Data(), + } + + castedBinary.Build(bf, s.clientContext) + + recipient.QueueSendMHF(castedBinary) +} + +func getCharacterName(s *Session, charID uint32) (string, error) { + row := s.server.db.QueryRow("SELECT name FROM characters WHERE id = $1", charID) + + charName := "" + + err := row.Scan(&charName) + + if err != nil { + return "", err + } + + return charName, nil +} + +func handleMsgMhfReadMail(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadMail) + + mailId := s.mailList[pkt.AccIndex] + + if mailId == 0 { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + panic("attempting to read mail that doesn't exist in session map") + } + + mail, err := GetMailByID(s, mailId) + + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + panic(err) + } + + _ = mail.MarkRead(s) + + bodyBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(mail.Body) + + doAckBufSucceed(s, pkt.AckHandle, bodyBytes) +} + +func handleMsgMhfListMail(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfListMail) + + mail, err := GetMailListForCharacter(s, s.charID) + + if err != nil { + doAckBufFail(s, pkt.AckHandle, make([]byte, 4)) + panic(err) + } + + if s.mailList == nil { + s.mailList = make([]int, 256) + } + + msg := byteframe.NewByteFrame() + + msg.WriteUint32(uint32(len(mail))) + + startIndex := s.mailAccIndex + + for i, m := range mail { + accIndex := startIndex + uint8(i) + s.mailList[accIndex] = m.ID + s.mailAccIndex++ + + itemAttached := m.AttachedItemID != nil + subjectBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(m.Subject) + senderNameBytes, _ := stringsupport.ConvertUTF8ToShiftJIS(m.SenderName) + + msg.WriteUint32(m.SenderID) + msg.WriteUint32(uint32(m.CreatedAt.Unix())) + + msg.WriteUint8(uint8(accIndex)) + msg.WriteUint8(uint8(i)) + + flags := uint8(0x00) + + if m.Read { + flags |= 0x01 + } + + if m.AttachedItemReceived { + flags |= 0x08 + } + + if m.IsGuildInvite { + // Guild Invite + flags |= 0x10 + + // System message? + flags |= 0x04 + } + + msg.WriteUint8(flags) + msg.WriteBool(itemAttached) + msg.WriteUint8(uint8(len(subjectBytes))) + msg.WriteUint8(uint8(len(senderNameBytes))) + msg.WriteBytes(subjectBytes) + msg.WriteBytes(senderNameBytes) + + if itemAttached { + msg.WriteInt16(m.AttachedItemAmount) + msg.WriteUint16(*m.AttachedItemID) + } + } + + doAckBufSucceed(s, pkt.AckHandle, msg.Data()) +} + +func handleMsgMhfOprtMail(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfOprtMail) + + mail, err := GetMailByID(s, s.mailList[pkt.AccIndex]) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, nil) + panic(err) + } + + switch mhfpacket.OperateMailOperation(pkt.Operation) { + case mhfpacket.OperateMailOperationDelete: + err = mail.MarkDeleted(s) + + if err != nil { + doAckSimpleFail(s, pkt.AckHandle, nil) + panic(err) + } + } + + doAckSimpleSucceed(s, pkt.AckHandle, nil) +} + +func handleMsgMhfSendMail(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_mercenary.go b/Erupe/server/channelserver/handlers_mercenary.go new file mode 100644 index 000000000..fced4e99e --- /dev/null +++ b/Erupe/server/channelserver/handlers_mercenary.go @@ -0,0 +1,369 @@ +package channelserver + +import ( + "fmt" + "math/rand" + "os" + "io" + "io/ioutil" + "path/filepath" + + + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Solenataris/Erupe/server/channelserver/compression/deltacomp" + "github.com/Solenataris/Erupe/server/channelserver/compression/nullcomp" + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" +) + + +// THERE ARE [PARTENER] [MERCENARY] [OTOMO AIRU] + +/////////////////////////////////////////// +/// PARTENER // +/////////////////////////////////////////// + +func handleMsgMhfLoadPartner(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadPartner) + // load partner from database + var data []byte + err := s.server.db.QueryRow("SELECT partner FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get partner savedata from db", zap.Error(err)) + } + if len(data) > 0 { + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + } + // TODO(Andoryuuta): Figure out unusual double ack. One sized, one not. + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfSavePartner(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSavePartner) + + dumpSaveData(s, pkt.RawDataPayload, "_partner") + + _, err := s.server.db.Exec("UPDATE characters SET partner=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + if err != nil { + s.logger.Fatal("Failed to update partner savedata in db", zap.Error(err)) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfLoadLegendDispatch(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadLegendDispatch) + data := []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x01, 0x8d, 0x40, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x02, 0xde, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x5e, 0x04, 0x30, 0x40} + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfLoadHunterNavi(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadHunterNavi) + var data []byte + err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get hunter navigation savedata from db", zap.Error(err)) + } + + if len(data) > 0 { + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + // set first byte to 1 to avoid pop up every time without save + body := make([]byte, 0x226) + body[0] = 1 + doAckBufSucceed(s, pkt.AckHandle, body) + } +} + +func handleMsgMhfSaveHunterNavi(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSaveHunterNavi) + + dumpSaveData(s, pkt.RawDataPayload, "_hunternavi") + + if pkt.IsDataDiff { + var data []byte + + // Load existing save + err := s.server.db.QueryRow("SELECT hunternavi FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get hunternavi savedata from db", zap.Error(err)) + } + + // Check if we actually had any hunternavi data, using a blank buffer if not. + // This is requried as the client will try to send a diff after character creation without a prior MsgMhfSaveHunterNavi packet. + if len(data) == 0 { + data = make([]byte, 0x226) + data[0] = 1 // set first byte to 1 to avoid pop up every time without save + } + + // Perform diff and compress it to write back to db + s.logger.Info("Diffing...") + saveOutput := deltacomp.ApplyDataDiff(pkt.RawDataPayload, data) + + _, err = s.server.db.Exec("UPDATE characters SET hunternavi=$1 WHERE id=$2", saveOutput, s.charID) + if err != nil { + s.logger.Fatal("Failed to update hunternavi savedata in db", zap.Error(err)) + } + + s.logger.Info("Wrote recompressed hunternavi back to DB.") + } else { + // simply update database, no extra processing + _, err := s.server.db.Exec("UPDATE characters SET hunternavi=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + if err != nil { + s.logger.Fatal("Failed to update hunternavi savedata in db", zap.Error(err)) + } + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +/////////////////////////////////////////// + +/////////////////////////////////////////// +/// MERCENARY // +/////////////////////////////////////////// + +func handleMsgMhfMercenaryHuntdata(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfMercenaryHuntdata) + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x0A)) +} + +func handleMsgMhfEnumerateMercenaryLog(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfCreateMercenary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfCreateMercenary) + + bf := byteframe.NewByteFrame() + + bf.WriteUint32(0x00) // Unk + bf.WriteUint32(rand.Uint32()) // Partner ID? + + doAckSimpleSucceed(s, pkt.AckHandle, bf.Data()) +} + +func handleMsgMhfSaveMercenary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSaveMercenary) + bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload) + GCPValue := bf.ReadUint32() + _ = bf.ReadUint32() // unk + MercDataSize := bf.ReadUint32() + MercData := bf.ReadBytes(uint(MercDataSize)) + _ = bf.ReadUint32() // unk + + if MercDataSize > 0 { + // the save packet has an extra null byte after its size + _, err := s.server.db.Exec("UPDATE characters SET savemercenary=$1 WHERE id=$2", MercData[:MercDataSize], s.charID) + if err != nil { + s.logger.Fatal("Failed to update savemercenary and gcp in db", zap.Error(err)) + } + } + // gcp value is always present regardless + _, err := s.server.db.Exec("UPDATE characters SET gcp=$1 WHERE id=$2", GCPValue, s.charID) + if err != nil { + s.logger.Fatal("Failed to update savemercenary and gcp in db", zap.Error(err)) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfReadMercenaryW(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadMercenaryW) + var data []byte + var gcp uint32 + // still has issues + err := s.server.db.QueryRow("SELECT savemercenary FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get savemercenary data from db", zap.Error(err)) + } + + err = s.server.db.QueryRow("SELECT COALESCE(gcp, 0) FROM characters WHERE id = $1", s.charID).Scan(&gcp) + if err != nil { + panic(err) + } + if len(data) == 0 { + data = []byte{0x00} + } + + resp := byteframe.NewByteFrame() + resp.WriteBytes(data) + resp.WriteUint16(0) + resp.WriteUint32(gcp) + fmt.Printf("% x", resp.Data()) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfReadMercenaryM(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReadMercenaryM) + // accessing actual rasta data of someone else still unsure of the formatting of this + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfContractMercenary(s *Session, p mhfpacket.MHFPacket) {} + +/////////////////////////////////////////// + +/////////////////////////////////////////// +/// OTOMO AIRU // +/////////////////////////////////////////// + +func handleMsgMhfLoadOtomoAirou(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadOtomoAirou) + // load partnyaa from database + var data []byte + err := s.server.db.QueryRow("SELECT otomoairou FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get partnyaa savedata from db", zap.Error(err)) + } + + if len(data) > 0 { + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + } +} + +func handleMsgMhfSaveOtomoAirou(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSaveOtomoAirou) + dumpSaveData(s, pkt.RawDataPayload, "_otomoairou") + + _, err := s.server.db.Exec("UPDATE characters SET otomoairou=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + if err != nil { + s.logger.Fatal("Failed to update partnyaa savedata in db", zap.Error(err)) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfEnumerateAiroulist(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateAiroulist) + resp := byteframe.NewByteFrame() + if _, err := os.Stat(filepath.Join(s.server.erupeConfig.BinPath, "airoulist.bin")); err == nil { + data, _ := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "airoulist.bin")) + resp.WriteBytes(data) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + return + } + + // Guild's Palico count. It seems we have to put the value on both ¯\_(ツ)_/¯ + airouList := getGuildAirouList(s) + resp.WriteUint16(uint16(len(airouList))) + resp.WriteUint16(uint16(len(airouList))) + for k, cat := range airouList { + // an id of 0 breaks everything pretty badly + // erupe does not currently ever assign cats IDs + // these presumably need to be added for the fatigue expiration for the final uint32 + // seems like it should happen in MSG_MHF_LOAD_OTOMO_AIROU requests as the initial creation operation is saving straight into a load + // and the client is obviously not aware of global ID availability + if cat.CatID == 0 { + resp.WriteUint32(uint32(k + 1)) + } else { + resp.WriteUint32(cat.CatID) + } + resp.WriteBytes(cat.CatName) + resp.WriteUint32(cat.Experience) + resp.WriteUint8(cat.Personality) + resp.WriteUint8(cat.Class) + resp.WriteUint8(cat.WeaponType) + resp.WriteUint16(cat.WeaponID) + resp.WriteUint32(0) // 32 bit unix timestamp, either time at which the cat stops being fatigued or the time at which it started + } + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +// CatDefinition holds values needed to populate the guild cat list +type CatDefinition struct { + CatID uint32 + CatName []byte + CurrentTask uint8 + Personality uint8 + Class uint8 + Experience uint32 + WeaponType uint8 + WeaponID uint16 + // there is a unix timestamp at the end of the cat for fatigue status + // it's -probably- not pulled from cat saves as that would allow someone other than the owner to actively manipulate a save for another session +} + +func getGuildAirouList(s *Session) []CatDefinition { + var guild *Guild + var err error + var guildCats []CatDefinition + + // returning 0 cats on any guild issues + // can probably optimise all of the guild queries pretty heavily + guild, err = GetGuildInfoByCharacterId(s, s.charID) + if err != nil { + return guildCats + } + + // ellie's GetGuildMembers didn't seem to pull leader? + rows, err := s.server.db.Query(`SELECT c.otomoairou, c.name + FROM characters c + INNER JOIN guild_characters gc + ON gc.character_id = c.id + WHERE gc.guild_id = $1 AND c.otomoairou IS NOT NULL + ORDER BY c.id ASC + LIMIT 60;`, guild.ID) + if err != nil { + s.logger.Warn("Selecting otomoairou based on guild failed", zap.Error(err)) + return guildCats + } + + for rows.Next() { + var data []byte + var charName string + err = rows.Scan(&data, &charName) + if err != nil { + s.logger.Warn("select failure", zap.Error(err)) + continue + } else if len(data) == 0 { + // non extant cats that aren't null in DB + continue + } + // first byte has cat existence in general, can skip if 0 + if data[0] == 1 { + decomp, err := nullcomp.Decompress(data[1:]) + if err != nil { + s.logger.Warn("decomp failure", zap.Error(err)) + continue + } + bf := byteframe.NewByteFrameFromBytes(decomp) + cats := GetCatDetails(bf) + for _, cat := range cats { + if cat.CurrentTask == 4 { + guildCats = append(guildCats, cat) + } + } + } + } + return guildCats +} + +func GetCatDetails(bf *byteframe.ByteFrame) []CatDefinition { + catCount := bf.ReadUint8() + cats := make([]CatDefinition, catCount) + for x := 0; x < int(catCount); x++ { + var catDef CatDefinition + // cat sometimes has additional bytes for whatever reason, gift items? timestamp? + // until actual variance is known we can just seek to end based on start + catDefLen := bf.ReadUint32() + catStart, _ := bf.Seek(0, io.SeekCurrent) + + catDef.CatID = bf.ReadUint32() + bf.Seek(1, io.SeekCurrent) // unknown value, probably a bool + catDef.CatName = bf.ReadBytes(18) // always 18 len, reads first null terminated string out of section and discards rest + catDef.CurrentTask = bf.ReadUint8() + bf.Seek(16, io.SeekCurrent) // appearance data and what is seemingly null bytes + catDef.Personality = bf.ReadUint8() + catDef.Class = bf.ReadUint8() + bf.Seek(5, io.SeekCurrent) // affection and colour sliders + catDef.Experience = bf.ReadUint32() // raw cat rank points, doesn't have a rank + bf.Seek(1, io.SeekCurrent) // bool for weapon being equipped + catDef.WeaponType = bf.ReadUint8() // weapon type, presumably always 6 for melee? + catDef.WeaponID = bf.ReadUint16() // weapon id + bf.Seek(catStart+int64(catDefLen), io.SeekStart) + cats[x] = catDef + } + return cats +} + + +/////////////////////////////////////////// diff --git a/Erupe/server/channelserver/handlers_mutex.go b/Erupe/server/channelserver/handlers_mutex.go new file mode 100644 index 000000000..c908926f3 --- /dev/null +++ b/Erupe/server/channelserver/handlers_mutex.go @@ -0,0 +1,13 @@ +package channelserver + +import "github.com/Solenataris/Erupe/network/mhfpacket" + +func handleMsgSysCreateMutex(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysCreateOpenMutex(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysDeleteMutex(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysOpenMutex(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysCloseMutex(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_object.go b/Erupe/server/channelserver/handlers_object.go new file mode 100644 index 000000000..42360bf29 --- /dev/null +++ b/Erupe/server/channelserver/handlers_object.go @@ -0,0 +1,85 @@ +package channelserver + +import ( + "fmt" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network/mhfpacket" +) + +func handleMsgSysCreateObject(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysCreateObject) + + // Lock the stage. + s.server.Lock() + + // Make a new stage object and insert it into the stage. + objID := s.stage.GetNewObjectID(s.charID) + newObj := &StageObject{ + id: objID, + ownerCharID: s.charID, + x: pkt.X, + y: pkt.Y, + z: pkt.Z, + } + + s.stage.objects[s.charID] = newObj + + // Unlock the stage. + s.server.Unlock() + // Response to our requesting client. + resp := byteframe.NewByteFrame() + resp.WriteUint32(objID) // New local obj handle. + doAckSimpleSucceed(s, pkt.AckHandle, resp.Data()) + // Duplicate the object creation to all sessions in the same stage. + dupObjUpdate := &mhfpacket.MsgSysDuplicateObject{ + ObjID: objID, + X: pkt.X, + Y: pkt.Y, + Z: pkt.Z, + OwnerCharID: s.charID, + } + s.logger.Info("Duplicate a new characters to others clients") + s.stage.BroadcastMHF(dupObjUpdate, s) +} + +func handleMsgSysDeleteObject(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysPositionObject(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysPositionObject) + if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.OpcodeMessages { + fmt.Printf("[%s] with objectID [%d] move to (%f,%f,%f)\n\n", s.Name, pkt.ObjID, pkt.X, pkt.Y, pkt.Z) + } + s.stage.Lock() + object, ok := s.stage.objects[s.charID] + if ok { + object.x = pkt.X + object.y = pkt.Y + object.z = pkt.Z + } + s.stage.Unlock() + // One of the few packets we can just re-broadcast directly. + s.stage.BroadcastMHF(pkt, s) +} + +func handleMsgSysRotateObject(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysDuplicateObject(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysSetObjectBinary(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysGetObjectBinary(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysGetObjectOwner(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysUpdateObjectBinary(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysCleanupObject(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysAddObject(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysDelObject(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysDispObject(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysHideObject(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_plate.go b/Erupe/server/channelserver/handlers_plate.go new file mode 100644 index 000000000..4988930bf --- /dev/null +++ b/Erupe/server/channelserver/handlers_plate.go @@ -0,0 +1,165 @@ +package channelserver + +import ( + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Solenataris/Erupe/server/channelserver/compression/deltacomp" + "github.com/Solenataris/Erupe/server/channelserver/compression/nullcomp" + "go.uber.org/zap" +) + +func handleMsgMhfLoadPlateData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadPlateData) + var data []byte + err := s.server.db.QueryRow("SELECT platedata FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get plate data savedata from db", zap.Error(err)) + } + + if len(data) > 0 { + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + doAckBufSucceed(s, pkt.AckHandle, []byte{}) + } +} + +func handleMsgMhfSavePlateData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSavePlateData) + + dumpSaveData(s, pkt.RawDataPayload, "_platedata") + + if pkt.IsDataDiff { + var data []byte + + // Load existing save + err := s.server.db.QueryRow("SELECT platedata FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get platedata savedata from db", zap.Error(err)) + } + + if len(data) > 0 { + // Decompress + s.logger.Info("Decompressing...") + data, err = nullcomp.Decompress(data) + if err != nil { + s.logger.Fatal("Failed to decompress savedata from db", zap.Error(err)) + } + } else { + // create empty save if absent + data = make([]byte, 0x1AF20) + } + + // Perform diff and compress it to write back to db + s.logger.Info("Diffing...") + saveOutput, err := nullcomp.Compress(deltacomp.ApplyDataDiff(pkt.RawDataPayload, data)) + if err != nil { + s.logger.Fatal("Failed to diff and compress platedata savedata", zap.Error(err)) + } + + _, err = s.server.db.Exec("UPDATE characters SET platedata=$1 WHERE id=$2", saveOutput, s.charID) + if err != nil { + s.logger.Fatal("Failed to update platedata savedata in db", zap.Error(err)) + } + + s.logger.Info("Wrote recompressed platedata back to DB.") + } else { + // simply update database, no extra processing + _, err := s.server.db.Exec("UPDATE characters SET platedata=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + if err != nil { + s.logger.Fatal("Failed to update platedata savedata in db", zap.Error(err)) + } + } + + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfLoadPlateBox(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadPlateBox) + var data []byte + err := s.server.db.QueryRow("SELECT platebox FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get sigil box savedata from db", zap.Error(err)) + } + + if len(data) > 0 { + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + doAckBufSucceed(s, pkt.AckHandle, []byte{}) + } +} + +func handleMsgMhfSavePlateBox(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSavePlateBox) + + dumpSaveData(s, pkt.RawDataPayload, "_platebox") + + if pkt.IsDataDiff { + var data []byte + + // Load existing save + err := s.server.db.QueryRow("SELECT platebox FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get sigil box savedata from db", zap.Error(err)) + } + + // Decompress + if len(data) > 0 { + // Decompress + s.logger.Info("Decompressing...") + data, err = nullcomp.Decompress(data) + if err != nil { + s.logger.Fatal("Failed to decompress savedata from db", zap.Error(err)) + } + } else { + // create empty save if absent + data = make([]byte, 0x820) + } + + // Perform diff and compress it to write back to db + s.logger.Info("Diffing...") + saveOutput, err := nullcomp.Compress(deltacomp.ApplyDataDiff(pkt.RawDataPayload, data)) + if err != nil { + s.logger.Fatal("Failed to diff and compress savedata", zap.Error(err)) + } + + _, err = s.server.db.Exec("UPDATE characters SET platebox=$1 WHERE id=$2", saveOutput, s.charID) + if err != nil { + s.logger.Fatal("Failed to update platebox savedata in db", zap.Error(err)) + } + + s.logger.Info("Wrote recompressed platebox back to DB.") + } else { + // simply update database, no extra processing + _, err := s.server.db.Exec("UPDATE characters SET platebox=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + if err != nil { + s.logger.Fatal("Failed to update platedata savedata in db", zap.Error(err)) + } + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfLoadPlateMyset(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadPlateMyset) + var data []byte + err := s.server.db.QueryRow("SELECT platemyset FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get presets sigil savedata from db", zap.Error(err)) + } + + if len(data) > 0 { + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + blankData := make([]byte, 0x780) + doAckBufSucceed(s, pkt.AckHandle, blankData) + } +} + +func handleMsgMhfSavePlateMyset(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSavePlateMyset) + // looks to always return the full thing, simply update database, no extra processing + + _, err := s.server.db.Exec("UPDATE characters SET platemyset=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + if err != nil { + s.logger.Fatal("Failed to update platemyset savedata in db", zap.Error(err)) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} diff --git a/Erupe/server/channelserver/handlers_quest.go b/Erupe/server/channelserver/handlers_quest.go new file mode 100644 index 000000000..36afb1c5f --- /dev/null +++ b/Erupe/server/channelserver/handlers_quest.go @@ -0,0 +1,99 @@ +package channelserver + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" +) + +func handleMsgSysGetFile(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysGetFile) + + // Debug print the request. + if pkt.IsScenario { + fmt.Printf("%+v\n", pkt.ScenarioIdentifer) + filename := fmt.Sprintf("%d_0_0_0_S%d_T%d_C%d", pkt.ScenarioIdentifer.CategoryID, pkt.ScenarioIdentifer.MainID, pkt.ScenarioIdentifer.Flags, pkt.ScenarioIdentifer.ChapterID) + // Read the scenario file. + data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("scenarios/%s.bin", filename))) + if err != nil { + panic(err) + } + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + if _, err := os.Stat(filepath.Join(s.server.erupeConfig.BinPath, "quest_override.bin")); err == nil { + data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "quest_override.bin")) + if err != nil { + panic(err) + } + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + // Get quest file. + data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("quests/%s.bin", pkt.Filename))) + if err != nil { + panic(err) + } + doAckBufSucceed(s, pkt.AckHandle, data) + } + } +} + +func handleMsgMhfLoadFavoriteQuest(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadFavoriteQuest) + // TODO(Andoryuuta): Save data from MsgMhfSaveFavoriteQuest and resend it here. + // Fist: Using a no favourites placeholder to avoid an in game error message + // being sent every time you use a counter when it fails to load + doAckBufSucceed(s, pkt.AckHandle, []byte{0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfSaveFavoriteQuest(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfSaveFavoriteQuest) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfEnumerateQuest(s *Session, p mhfpacket.MHFPacket) { + // local files are easier for now, probably best would be to generate dynamically + pkt := p.(*mhfpacket.MsgMhfEnumerateQuest) + data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, fmt.Sprintf("questlists/list_%d.bin", pkt.QuestList))) + if err != nil { + fmt.Printf("questlists/list_%d.bin", pkt.QuestList) + stubEnumerateNoResults(s, pkt.AckHandle) + } else { + doAckBufSucceed(s, pkt.AckHandle, data) + } + // Update the client's rights as well: + updateRights(s) +} + +func handleMsgMhfEnterTournamentQuest(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetUdBonusQuestInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdBonusQuestInfo) + + udBonusQuestInfos := []struct { + Unk0 uint8 + Unk1 uint8 + StartTime uint32 // Unix timestamp (seconds) + EndTime uint32 // Unix timestamp (seconds) + Unk4 uint32 + Unk5 uint8 + Unk6 uint8 + }{} // Blank stub array. + + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(len(udBonusQuestInfos))) + for _, q := range udBonusQuestInfos { + resp.WriteUint8(q.Unk0) + resp.WriteUint8(q.Unk1) + resp.WriteUint32(q.StartTime) + resp.WriteUint32(q.EndTime) + resp.WriteUint32(q.Unk4) + resp.WriteUint8(q.Unk5) + resp.WriteUint8(q.Unk6) + } + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} diff --git a/Erupe/server/channelserver/handlers_register.go b/Erupe/server/channelserver/handlers_register.go new file mode 100644 index 000000000..c48bdec76 --- /dev/null +++ b/Erupe/server/channelserver/handlers_register.go @@ -0,0 +1,26 @@ +package channelserver + +import ( + "encoding/hex" + + "github.com/Solenataris/Erupe/network/mhfpacket" +) + +func handleMsgSysOperateRegister(s *Session, p mhfpacket.MHFPacket) { // RAVIENTE USE THIS + // RAVI EVENT + pkt := p.(*mhfpacket.MsgSysOperateRegister) + + doAckSimpleSucceed(s, pkt.AckHandle, pkt.RawDataPayload) +} + +func handleMsgSysLoadRegister(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysLoadRegister) + + // ORION TEMPORARY DISABLE (IN WORK) + // ravi response + data, _ := hex.DecodeString("000C000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + //data, _ := hex.DecodeString("00000076001d0001b2c4000227d1000221040000a959000000000000000000000000000000000000000000532d1c0010ee8e001fe0010007f463000000000017e53e00072e250053937a0000194a00002d5a000000000000000000004eb300004cd700000000000008a90000be400001bb16000005dd00000014") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgSysNotifyRegister(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_rengoku.go b/Erupe/server/channelserver/handlers_rengoku.go new file mode 100644 index 000000000..d6280bc92 --- /dev/null +++ b/Erupe/server/channelserver/handlers_rengoku.go @@ -0,0 +1,96 @@ +package channelserver + +import ( + "io/ioutil" + "path/filepath" + + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" +) + +func handleMsgMhfSaveRengokuData(s *Session, p mhfpacket.MHFPacket) { + // saved every floor on road, holds values such as floors progressed, points etc. + // can be safely handled by the client + pkt := p.(*mhfpacket.MsgMhfSaveRengokuData) + _, err := s.server.db.Exec("UPDATE characters SET rengokudata=$1 WHERE id=$2", pkt.RawDataPayload, s.charID) + if err != nil { + s.logger.Fatal("Failed to update rengokudata savedata in db", zap.Error(err)) + } + + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfLoadRengokuData(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfLoadRengokuData) + var data []byte + err := s.server.db.QueryRow("SELECT rengokudata FROM characters WHERE id = $1", s.charID).Scan(&data) + if err != nil { + s.logger.Fatal("Failed to get rengokudata savedata from db", zap.Error(err)) + } + if len(data) > 0 { + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint16(0) + resp.WriteUint32(0) + resp.WriteUint16(0) + resp.WriteUint16(0) + resp.WriteUint32(0) + resp.WriteUint32(0) // an extra 4 bytes were missing based on pcaps + + resp.WriteUint8(3) // Count of next 3 + resp.WriteUint16(0) + resp.WriteUint16(0) + resp.WriteUint16(0) + + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + resp.WriteUint8(3) // Count of next 3 + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + resp.WriteUint8(3) // Count of next 3 + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + resp.WriteUint32(0) + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + } +} + +func handleMsgMhfGetRengokuBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetRengokuBinary) + // a (massively out of date) version resides in the game's /dat/ folder or up to date can be pulled from packets + data, err := ioutil.ReadFile(filepath.Join(s.server.erupeConfig.BinPath, "rengoku_data.bin")) + if err != nil { + panic(err) + } + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfEnumerateRengokuRanking(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateRengokuRanking) + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetRengokuRankingRank(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetRengokuRankingRank) + + resp := byteframe.NewByteFrame() + resp.WriteBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} diff --git a/Erupe/server/channelserver/handlers_reserve.go b/Erupe/server/channelserver/handlers_reserve.go new file mode 100644 index 000000000..4baa6d4d7 --- /dev/null +++ b/Erupe/server/channelserver/handlers_reserve.go @@ -0,0 +1,131 @@ +package channelserver + +import "github.com/Solenataris/Erupe/network/mhfpacket" + +func handleMsgSysReserve188(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysReserve188) + + // Left as raw bytes because I couldn't easily find the request or resp parser function in the binary. + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgSysReserve18B(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysReserve18B) + + // Left as raw bytes because I couldn't easily find the request or resp parser function in the binary. + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x3C}) +} + +func handleMsgSysReserve55(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve56(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve57(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve01(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve02(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve03(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve04(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve05(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve06(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve07(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve0C(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve0D(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve0E(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve4A(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve4B(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve4C(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve4D(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve4E(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve4F(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve5C(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve5E(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve5F(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve71(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve72(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve73(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve74(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve75(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve76(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve77(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve78(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve79(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve7A(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve7B(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve7C(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve7E(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfReserve010F(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve180(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve18E(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve18F(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve19E(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve19F(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve204(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve205(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve206(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve207(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve208(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve209(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve20A(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve20B(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve20C(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve20D(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve20E(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve20F(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve19B(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve192(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve193(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysReserve194(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_reward.go b/Erupe/server/channelserver/handlers_reward.go new file mode 100644 index 000000000..568d22d2f --- /dev/null +++ b/Erupe/server/channelserver/handlers_reward.go @@ -0,0 +1,49 @@ +package channelserver + +import ( + "encoding/hex" + + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" +) + +func handleMsgMhfGetAdditionalBeatReward(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetAdditionalBeatReward) + // Actual response in packet captures are all just giant batches of null bytes + // I'm assuming this is because it used to be tied to an actual event and + // they never bothered killing off the packet when they made it static + doAckBufSucceed(s, pkt.AckHandle, make([]byte, 0x104)) +} + +func handleMsgMhfGetUdRankingRewardList(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdRankingRewardList) + // Temporary canned response + data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetRewardSong(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetRewardSong) + // Temporary canned response + data, _ := hex.DecodeString("0100001600000A5397DF00000000000000000000000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfUseRewardSong(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAddRewardSongCount(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireMonthlyReward(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfAcquireMonthlyReward) + + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfAcceptReadReward(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetBreakSeibatuLevelReward(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetWeeklySeibatuRankingReward(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_semaphore.go b/Erupe/server/channelserver/handlers_semaphore.go new file mode 100644 index 000000000..38c91f4c8 --- /dev/null +++ b/Erupe/server/channelserver/handlers_semaphore.go @@ -0,0 +1,82 @@ +package channelserver + +import ( + "fmt" + + "github.com/Solenataris/Erupe/network/mhfpacket" +) + +func handleMsgSysCreateSemaphore(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysCreateSemaphore) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x03, 0x00, 0x0d}) +} + +func handleMsgSysDeleteSemaphore(s *Session, p mhfpacket.MHFPacket) { + //pkt := p.(*mhfpacket.MsgSysDeleteSemaphore) + + s.semaphore.Lock() + for id := range s.server.semaphore { + delete(s.server.semaphore[id].reservedClientSlots, s.charID) + } + s.semaphore.Unlock() +} + +func handleMsgSysCreateAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysCreateAcquireSemaphore) + SemaphoreID := pkt.SemaphoreID + + newSemaphore, gotNewStage := s.server.semaphore[SemaphoreID] + + fmt.Printf("Got reserve stage req, StageID: %v\n\n", SemaphoreID) + if !gotNewStage { + s.server.semaphoreLock.Lock() + if SemaphoreID == "hs_l0u3B51J9k1" || + SemaphoreID == "hs_l0u3B51J9k2" || + SemaphoreID == "hs_l0u3B51J9k3" || + SemaphoreID == "hs_l0u3B51J9k4" || + SemaphoreID == "hs_l0u3B51J9k5" { + s.server.semaphore[SemaphoreID] = NewSemaphore(SemaphoreID, 32) + } else { + s.server.semaphore[SemaphoreID] = NewSemaphore(SemaphoreID, 1) + } + newSemaphore = s.server.semaphore[SemaphoreID] + s.server.semaphoreLock.Unlock() + } + + newSemaphore.Lock() + defer newSemaphore.Unlock() + if _, exists := newSemaphore.reservedClientSlots[s.charID]; exists { + s.logger.Info("IS ALREADY EXIST !") + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0F, 0x00, 0x1D}) + } else if uint16(len(newSemaphore.reservedClientSlots)) < newSemaphore.maxPlayers { + newSemaphore.reservedClientSlots[s.charID] = nil + s.Lock() + s.semaphore = newSemaphore + s.Unlock() + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x0F, 0x00, 0x1D}) + } else { + doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + } +} + +func handleMsgSysAcquireSemaphore(s *Session, p mhfpacket.MHFPacket) { + //pkt := p.(*mhfpacket.MsgSysAcquireSemaphore) +} + +func handleMsgSysReleaseSemaphore(s *Session, p mhfpacket.MHFPacket) { + //pkt := p.(*mhfpacket.MsgSysReleaseSemaphore) + for _, session := range s.server.sessions { + session.semaphore.Lock() + for id := range session.server.semaphore { + delete(s.server.semaphore[id].reservedClientSlots, s.charID) + } + session.semaphore.Unlock() + } + //data, _ := hex.DecodeString("000180e703000d443b37ff006d00131809000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010627426400a936a93600000100cf330600cc31cc31d431000025000000000000000000010218330600bd3cbd3cbd3c01032c280600ee3dee3da9360104f3300600d231a936a93601054a310600e23ae23ae23a00000d0000000000004d814c0000000003008501d723b7334001e7038b3fd437d516113505000000e7030001000002000203000000000000fafafafafafafafafafafafafafa000000000000ecb2000060da0000000000000000000000000000000000000000000000000000000000000000000000000000181818187e2d00003b31702d662d402e000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000") + //doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgSysCheckSemaphore(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysCheckSemaphore) + doAckSimpleSucceed(s, pkt.AckHandle, make([]byte, 4)) +} diff --git a/Erupe/server/channelserver/handlers_shop_gacha.go b/Erupe/server/channelserver/handlers_shop_gacha.go new file mode 100644 index 000000000..be0ec9e04 --- /dev/null +++ b/Erupe/server/channelserver/handlers_shop_gacha.go @@ -0,0 +1,706 @@ +package channelserver + +import ( + "encoding/hex" + "time" + + //"github.com/Solenataris/Erupe/common/stringsupport" + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" + "github.com/lib/pq" + "github.com/sachaos/lottery" + "go.uber.org/zap" +) + +func handleMsgMhfEnumerateShop(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfEnumerateShop) + // SHOP TYPES: + // 01 = Running Gachas, 02 = actual gacha, 04 = N Points, 05 = GCP, 07 = Item to GCP, 08 = Diva Defense, 10 = Hunter's Road + + // GACHA FORMAT: + // int32: gacha id + + // STORE FORMAT: + // Int16: total item count + // Int16: total item count + + // ITEM FORMAT: + // int32: Unique item hash for tracking purchases + // int16: padding? + // int16: Item ID + // int16: padding? + // int16: GCP returns + // int16: Number traded at once + // int16: HR or SR Requirement + // int16: Whichever of the above it isn't + // int16: GR Requirement + // int16: Store level requirement + // int16: Maximum quantity purchasable + // int16: Unk + // int16: Road floors cleared requirement + // int16: Road White Fatalis weekly kills + if pkt.ShopType == 2 { + shopEntries, err := s.server.db.Query("SELECT entryType, itemhash, currType, currNumber, currQuant, percentage, rarityIcon, rollsCount, itemCount, dailyLimit, itemType, itemId, quantity FROM gacha_shop_items WHERE shophash=$1", pkt.ShopID) + if err != nil { + panic(err) + } + var entryType, currType, rarityIcon, rollsCount, itemCount, dailyLimit byte + var currQuant, currNumber, percentage uint16 + var itemhash uint32 + var itemType, itemId, quantity pq.Int64Array + var entryCount int + resp := byteframe.NewByteFrame() + resp.WriteUint32(pkt.ShopID) + resp.WriteUint16(0) // total defs + for shopEntries.Next() { + err = shopEntries.Scan(&entryType, &itemhash, &currType, &currNumber, &currQuant, &percentage, &rarityIcon, &rollsCount, &itemCount, &dailyLimit, (*pq.Int64Array)(&itemType), (*pq.Int64Array)(&itemId), (*pq.Int64Array)(&quantity)) + if err != nil { + panic(err) + } + resp.WriteUint8(entryType) + resp.WriteUint32(itemhash) + resp.WriteUint8(currType) + resp.WriteUint16(0) // unk, always 0 in existing packets + resp.WriteUint16(currNumber) // it's either item ID or quantity for gacha coins + resp.WriteUint16(currQuant) // only for item ID + resp.WriteUint16(percentage) + resp.WriteUint8(rarityIcon) + resp.WriteUint8(rollsCount) + resp.WriteUint8(itemCount) + resp.WriteUint16(0) // unk, always 0 in existing packets + resp.WriteUint8(dailyLimit) + resp.WriteUint8(0) // unk, always 0 in existing packets + for i := 0; i < int(itemCount); i++ { + resp.WriteUint16(uint16(itemType[i])) // unk, always 0 in existing packets + resp.WriteUint16(uint16(itemId[i])) // unk, always 0 in existing packets + resp.WriteUint16(uint16(quantity[i])) // unk, always 0 in existing packets + } + entryCount++ + } + if entryCount == 0 { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + return + } + resp.Seek(4, 0) + resp.WriteUint16(uint16(entryCount)) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + } else if pkt.ShopType == 1 { + gachaCount := 0 + shopEntries, err := s.server.db.Query("SELECT hash, reqGR, reqHR, gachaName, gachaLink0, gachaLink1, COALESCE(gachaLink2, ''), extraIcon, gachaType, hideFlag FROM gacha_shop") + if err != nil { + panic(err) + } + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + var gachaName, gachaLink0, gachaLink1, gachaLink2 string + var hash, reqGR, reqHR, extraIcon, gachaType int + var hideFlag bool + for shopEntries.Next() { + err = shopEntries.Scan(&hash, &reqGR, &reqHR, &gachaName, &gachaLink0, &gachaLink1, &gachaLink2, &extraIcon, &gachaType, &hideFlag) + if err != nil { + panic(err) + } + resp.WriteUint32(uint32(hash)) + resp.WriteUint32(0) // only 0 in known packets + resp.WriteUint32(0) // all of these seem to trigger the 'rank restriction' + resp.WriteUint32(0) // message so they are presumably placeholders for a + resp.WriteUint32(0) // Z Rank or similar that never turned up? + resp.WriteUint32(uint32(reqGR)) + resp.WriteUint32(uint32(reqHR)) + resp.WriteUint32(0) // only 0 in known packet + stringBytes := append([]byte(gachaName), 0x00) + resp.WriteUint8(byte(len(stringBytes))) + resp.WriteBytes(stringBytes) + stringBytes = append([]byte(gachaLink0), 0x00) + resp.WriteUint8(byte(len(stringBytes))) + resp.WriteBytes(stringBytes) + stringBytes = append([]byte(gachaLink1), 0x00) + resp.WriteUint8(byte(len(stringBytes))) + resp.WriteBytes(stringBytes) + stringBytes = append([]byte(gachaLink2), 0x00) + resp.WriteBool(hideFlag) + resp.WriteUint8(uint8(len(stringBytes))) + resp.WriteBytes(stringBytes) + resp.WriteUint16(uint16(extraIcon)) + resp.WriteUint16(uint16(gachaType)) + gachaCount++ + } + resp.Seek(0, 0) + resp.WriteUint16(uint16(gachaCount)) + resp.WriteUint16(uint16(gachaCount)) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + + } else if pkt.ShopType == 7 { + // GCP conversion store + if pkt.ShopID == 0 { + // Items to GCP exchange. Gou Tickets, Shiten Tickets, GP Tickets + data, _ := hex.DecodeString("000300033a9186fb000033860000000a000100000000000000000000000000000000097fdb1c0000067e0000000a0001000000000000000000000000000000001374db29000027c300000064000100000000000000000000000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + } + } else if pkt.ShopType == 8 { + // Dive Defense sections + // 00 = normal level limited exchange store, 05 = GCP skill store, 07 = limited quantity exchange + if pkt.ShopID == 5 { + // diva defense skill level limited store + data, _ := hex.DecodeString("001f001f2c9365c1000000010000001e000a0000000000000000000a0000000000001979f1c2000000020000003c000a0000000000000000000a0000000000003e5197df000000030000003c000a0000000000000000000a000000000000219337c0000000040000001e000a0000000000000000000a00000000000009b24c9d000000140000001e000a0000000000000000000a0000000000001f1d496e000000150000001e000a0000000000000000000a0000000000003b918fcb000000160000003c000a0000000000000000000a0000000000000b7fd81c000000170000003c000a0000000000000000000a0000000000001374f239000000180000003c000a0000000000000000000a00000000000026950cba0000001c0000003c000a0000000000000000000a0000000000003797eae70000001d0000003c000a012b000000000000000a00000000000015758ad8000000050000003c00000000000000000000000a0000000000003c7035050000000600000050000a0000000000000001000a00000000000024f3b5560000000700000050000a0000000000000001000a00000000000000b600330000000800000050000a0000000000000001000a0000000000002efdce840000001900000050000a0000000000000001000a0000000000002d9365f10000001a00000050000a0000000000000001000a0000000000001979f3420000001f00000050000a012b000000000001000a0000000000003f5397cf0000002000000050000a012b000000000001000a000000000000319337c00000002100000050000a012b000000000001000a00000000000008b04cbd0000000900000064000a0000000000000002000a0000000000000b1d4b6e0000000a00000064000a0000000000000002000a0000000000003b918feb0000000b00000064000a0000000000000002000a0000000000001b7fd81c0000000c00000064000a0000000000000002000a0000000000001276f2290000000d00000064000a0000000000000002000a00000000000022950cba0000000e000000c8000a0000000000000002000a0000000000003697ead70000000f000001f4000a0000000000000003000a00000000000005758a5800000010000003e8000a0000000000000003000a0000000000003c7035250000001b000001f4000a0000000000010003000a00000000000034f3b5d60000001e00000064000a012b000000000003000a00000000000000b600030000002200000064000a0000000000010003000a000000000000") + doAckBufSucceed(s, pkt.AckHandle, data) + } else { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + } + } else { + shopEntries, err := s.server.db.Query("SELECT itemhash,itemID,Points,TradeQuantity,rankReqLow,rankReqHigh,rankReqG,storeLevelReq,maximumQuantity,boughtQuantity,roadFloorsRequired,weeklyFatalisKills FROM normal_shop_items WHERE shoptype=$1 AND shopid=$2", pkt.ShopType, pkt.ShopID) + if err != nil { + panic(err) + } + var ItemHash, entryCount int + var itemID, Points, TradeQuantity, rankReqLow, rankReqHigh, rankReqG, storeLevelReq, maximumQuantity, boughtQuantity, roadFloorsRequired, weeklyFatalisKills, charQuantity uint16 + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) // total defs + for shopEntries.Next() { + err = shopEntries.Scan(&ItemHash, &itemID, &Points, &TradeQuantity, &rankReqLow, &rankReqHigh, &rankReqG, &storeLevelReq, &maximumQuantity, &boughtQuantity, &roadFloorsRequired, &weeklyFatalisKills) + if err != nil { + panic(err) + } + resp.WriteUint32(uint32(ItemHash)) + resp.WriteUint16(0) // unk, always 0 in existing packets + resp.WriteUint16(itemID) + resp.WriteUint16(0) // unk, always 0 in existing packets + resp.WriteUint16(Points) // it's either item ID or quantity for gacha coins + resp.WriteUint16(TradeQuantity) // only for item ID + resp.WriteUint16(rankReqLow) + resp.WriteUint16(rankReqHigh) + resp.WriteUint16(rankReqG) + resp.WriteUint16(storeLevelReq) + resp.WriteUint16(maximumQuantity) + if maximumQuantity > 0 { + err = s.server.db.QueryRow("SELECT COALESCE(usedquantity,0) FROM shop_item_state WHERE itemhash=$1 AND char_id=$2", ItemHash, s.charID).Scan(&charQuantity) + if err != nil { + resp.WriteUint16(0) + } else { + resp.WriteUint16(charQuantity) + } + } else { + resp.WriteUint16(boughtQuantity) + } + resp.WriteUint16(roadFloorsRequired) + resp.WriteUint16(weeklyFatalisKills) + entryCount++ + } + if entryCount == 0 { + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + return + } + resp.Seek(0, 0) + resp.WriteUint16(uint16(entryCount)) + resp.WriteUint16(uint16(entryCount)) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + } +} + +func handleMsgMhfAcquireExchangeShop(s *Session, p mhfpacket.MHFPacket) { + // writing out to an editable shop enumeration + pkt := p.(*mhfpacket.MsgMhfAcquireExchangeShop) + if pkt.DataSize == 10 { + bf := byteframe.NewByteFrameFromBytes(pkt.RawDataPayload) + _ = bf.ReadUint16() // unk, always 1 in examples + itemHash := bf.ReadUint32() + buyCount := bf.ReadUint32() + _, err := s.server.db.Exec(`INSERT INTO shop_item_state (char_id, itemhash, usedquantity) + VALUES ($1,$2,$3) ON CONFLICT (char_id, itemhash) + DO UPDATE SET usedquantity = shop_item_state.usedquantity + $3 + WHERE EXCLUDED.char_id=$1 AND EXCLUDED.itemhash=$2`, s.charID, itemHash, buyCount) + if err != nil { + s.logger.Fatal("Failed to update shop_item_state in db", zap.Error(err)) + } + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetGachaPlayHistory(s *Session, p mhfpacket.MHFPacket) { + // returns number of times the gacha was played, will need persistent db stuff + pkt := p.(*mhfpacket.MsgMhfGetGachaPlayHistory) + doAckBufSucceed(s, pkt.AckHandle, []byte{0x0A}) +} + +func handleMsgMhfGetGachaPoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetGachaPoint) + var fp, gp, gt uint32 + _ = s.server.db.QueryRow("SELECT COALESCE(frontier_points, 0), COALESCE(gacha_prem, 0), COALESCE(gacha_trial,0) FROM characters WHERE id=$1", s.charID).Scan(&fp, &gp, >) + resp := byteframe.NewByteFrame() + resp.WriteUint32(gp) // Real Gacha Points? + resp.WriteUint32(gt) // Trial Gacha Point? + resp.WriteUint32(fp) // Frontier Points? + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +type gachaItem struct { + itemhash uint32 + percentage uint16 + rarityIcon byte + itemCount byte + itemType pq.Int64Array + itemId pq.Int64Array + quantity pq.Int64Array +} + +func (i gachaItem) Weight() int { + return int(i.percentage) +} + +func handleMsgMhfPlayNormalGacha(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPlayNormalGacha) + // needs to query db for input gacha and return a result or number of results + // uint8 number of results + // uint8 item type + // uint16 item id + // uint16 quantity + + var currType, rarityIcon, rollsCount, itemCount byte + var currQuant, currNumber, percentage uint16 + var itemhash uint32 + var itemType, itemId, quantity pq.Int64Array + var items []lottery.Weighter + // get info for updating data and calculating costs + err := s.server.db.QueryRow("SELECT currType, currNumber, currQuant, rollsCount FROM gacha_shop_items WHERE shophash=$1 AND entryType=$2", pkt.GachaHash, pkt.RollType).Scan(&currType, &currNumber, &currQuant, &rollsCount) + if err != nil { + panic(err) + } + // get existing items in storage if any + var data []byte + _ = s.server.db.QueryRow("SELECT gacha_items FROM characters WHERE id = $1", s.charID).Scan(&data) + if len(data) == 0 { + data = []byte{0x00} + } + // get gacha items and iterate through them for gacha roll + shopEntries, err := s.server.db.Query("SELECT itemhash, percentage, rarityIcon, itemCount, itemType, itemId, quantity FROM gacha_shop_items WHERE shophash=$1 AND entryType=100", pkt.GachaHash) + if err != nil { + panic(err) + } + for shopEntries.Next() { + err = shopEntries.Scan(&itemhash, &percentage, &rarityIcon, &itemCount, (*pq.Int64Array)(&itemType), (*pq.Int64Array)(&itemId), (*pq.Int64Array)(&quantity)) + if err != nil { + panic(err) + } + items = append(items, &gachaItem{itemhash: itemhash, percentage: percentage, rarityIcon: rarityIcon, itemCount: itemCount, itemType: itemType, itemId: itemId, quantity: quantity}) + } + // execute rolls, build response and update database + results := byte(0) + resp := byteframe.NewByteFrame() + dbUpdate := byteframe.NewByteFrame() + resp.WriteUint8(0) // results go here later + l := lottery.NewDefaultLottery() + for x := 0; x < int(rollsCount); x++ { + ind := l.Draw(items) + results += items[ind].(*gachaItem).itemCount + for y := 0; y < int(items[ind].(*gachaItem).itemCount); y++ { + // items in storage don't get rarity + dbUpdate.WriteUint8(uint8(items[ind].(*gachaItem).itemType[y])) + dbUpdate.WriteUint16(uint16(items[ind].(*gachaItem).itemId[y])) + dbUpdate.WriteUint16(uint16(items[ind].(*gachaItem).quantity[y])) + data = append(data, dbUpdate.Data()...) + dbUpdate.Seek(0, 0) + // response needs all item info and the rarity + resp.WriteBytes(dbUpdate.Data()) + resp.WriteUint8(uint8(items[ind].(*gachaItem).rarityIcon)) + } + } + resp.Seek(0, 0) + resp.WriteUint8(uint8(results)) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + + // add claimables to DB + data[0] = data[0] + results + _, err = s.server.db.Exec("UPDATE characters SET gacha_items = $1 WHERE id = $2", data, s.charID) + if err != nil { + s.logger.Fatal("Failed to update minidata in db", zap.Error(err)) + } + // deduct gacha coins if relevant, items are handled fine by the standard savedata packet immediately afterwards + if currType == 19 { + _, err = s.server.db.Exec("UPDATE characters SET gacha_trial = CASE WHEN (gacha_trial > $1) then gacha_trial - $1 else gacha_trial end, gacha_prem = CASE WHEN NOT (gacha_trial > $1) then gacha_prem - $1 else gacha_prem end WHERE id=$2", currNumber, s.charID) + } + if err != nil { + s.logger.Fatal("Failed to update gacha_items in db", zap.Error(err)) + } +} + +func handleMsgMhfUseGachaPoint(s *Session, p mhfpacket.MHFPacket) { + // should write to database when that's set up + pkt := p.(*mhfpacket.MsgMhfUseGachaPoint) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfExchangeFpoint2Item(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfExchangeFpoint2Item) + + var itemValue, quant int + _ = s.server.db.QueryRow("SELECT quant, itemValue FROM fpoint_items WHERE hash=$1", pkt.ItemHash).Scan(&quant, &itemValue) + itemCost := (int(pkt.Quantity) * quant) * itemValue + + // also update frontierpoints entry in database + _, err := s.server.db.Exec("UPDATE characters SET frontier_points=frontier_points::int - $1 WHERE id=$2", itemCost, s.charID) + if err != nil { + s.logger.Fatal("Failed to update minidata in db", zap.Error(err)) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfExchangeItem2Fpoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfExchangeItem2Fpoint) + + var itemValue, quant int + _ = s.server.db.QueryRow("SELECT quant, itemValue FROM fpoint_items WHERE hash=$1", pkt.ItemHash).Scan(&quant, &itemValue) + itemCost := (int(pkt.Quantity) / quant) * itemValue + // also update frontierpoints entry in database + _, err := s.server.db.Exec("UPDATE characters SET frontier_points=COALESCE(frontier_points::int + $1, $1) WHERE id=$2", itemCost, s.charID) + if err != nil { + s.logger.Fatal("Failed to update minidata in db", zap.Error(err)) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetFpointExchangeList(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetFpointExchangeList) + //absurd, probably lists every single item to trade to FP? + + var buyables int + var sellables int + + buyRows, err := s.server.db.Query("SELECT hash,itemType,itemID,quant,itemValue FROM fpoint_items WHERE tradeType=0") + if err != nil { + panic(err) + } + resp := byteframe.NewByteFrame() + resp.WriteUint32(0) + var hash, itemType, itemID, quant, itemValue int + for buyRows.Next() { + err = buyRows.Scan(&hash, &itemType, &itemID, &quant, &itemValue) + if err != nil { + panic("Error in fpoint_items") + } + resp.WriteUint32(uint32(hash)) + resp.WriteUint32(0) // this and following only 0 in known packets + resp.WriteUint16(0) + resp.WriteUint8(byte(itemType)) + resp.WriteUint16(uint16(itemID)) + resp.WriteUint16(uint16(quant)) + resp.WriteUint16(uint16(itemValue)) + buyables++ + } + + sellRows, err := s.server.db.Query("SELECT hash,itemType,itemID,quant,itemValue FROM fpoint_items WHERE tradeType=1") + if err != nil { + panic(err) + } + for sellRows.Next() { + err = sellRows.Scan(&hash, &itemType, &itemID, &quant, &itemValue) + if err != nil { + panic("Error in fpoint_items") + } + resp.WriteUint32(uint32(hash)) + resp.WriteUint32(0) // this and following only 0 in known packets + resp.WriteUint16(0) + resp.WriteUint8(byte(itemType)) + resp.WriteUint16(uint16(itemID)) + resp.WriteUint16(uint16(quant)) + resp.WriteUint16(uint16(itemValue)) + sellables++ + } + resp.Seek(0, 0) + resp.WriteUint16(uint16(sellables)) + resp.WriteUint16(uint16(buyables)) + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfPlayStepupGacha(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPlayStepupGacha) + results := byte(0) + stepResults := byte(0) + resp := byteframe.NewByteFrame() + rollFrame := byteframe.NewByteFrame() + stepFrame := byteframe.NewByteFrame() + stepData := []byte{} + var currType, rarityIcon, rollsCount, itemCount byte + var currQuant, currNumber, percentage uint16 + var itemhash uint32 + var itemType, itemId, quantity pq.Int64Array + var items []lottery.Weighter + // get info for updating data and calculating costs + err := s.server.db.QueryRow("SELECT currType, currNumber, currQuant, rollsCount, itemCount, itemType, itemId, quantity FROM gacha_shop_items WHERE shophash=$1 AND entryType=$2", pkt.GachaHash, pkt.RollType).Scan(&currType, &currNumber, &currQuant, &rollsCount, &itemCount, (*pq.Int64Array)(&itemType), (*pq.Int64Array)(&itemId), (*pq.Int64Array)(&quantity)) + if err != nil { + panic(err) + } + // get existing items in storage if any + var data []byte + _ = s.server.db.QueryRow("SELECT gacha_items FROM characters WHERE id = $1", s.charID).Scan(&data) + if len(data) == 0 { + data = []byte{0x00} + } + // roll definition includes items with step up gachas that are appended last + for x := 0; x < int(itemCount); x++ { + stepFrame.WriteUint8(uint8(itemType[x])) + stepFrame.WriteUint16(uint16(itemId[x])) + stepFrame.WriteUint16(uint16(quantity[x])) + stepData = append(stepData, stepFrame.Data()...) + stepFrame.WriteUint8(0) // rarity still defined + stepResults++ + } + // get gacha items and iterate through them for gacha roll + shopEntries, err := s.server.db.Query("SELECT itemhash, percentage, rarityIcon, itemCount, itemType, itemId, quantity FROM gacha_shop_items WHERE shophash=$1 AND entryType=100", pkt.GachaHash) + if err != nil { + panic(err) + } + for shopEntries.Next() { + err = shopEntries.Scan(&itemhash, &percentage, &rarityIcon, &itemCount, (*pq.Int64Array)(&itemType), (*pq.Int64Array)(&itemId), (*pq.Int64Array)(&quantity)) + if err != nil { + panic(err) + } + items = append(items, &gachaItem{itemhash: itemhash, percentage: percentage, rarityIcon: rarityIcon, itemCount: itemCount, itemType: itemType, itemId: itemId, quantity: quantity}) + } + // execute rolls, build response and update database + resp.WriteUint16(0) // results count goes here later + l := lottery.NewDefaultLottery() + for x := 0; x < int(rollsCount); x++ { + ind := l.Draw(items) + results += items[ind].(*gachaItem).itemCount + for y := 0; y < int(items[ind].(*gachaItem).itemCount); y++ { + // items in storage don't get rarity + rollFrame.WriteUint8(uint8(items[ind].(*gachaItem).itemType[y])) + rollFrame.WriteUint16(uint16(items[ind].(*gachaItem).itemId[y])) + rollFrame.WriteUint16(uint16(items[ind].(*gachaItem).quantity[y])) + data = append(data, rollFrame.Data()...) + rollFrame.Seek(0, 0) + // response needs all item info and the rarity + resp.WriteBytes(rollFrame.Data()) + resp.WriteUint8(uint8(items[ind].(*gachaItem).rarityIcon)) + } + } + resp.WriteBytes(stepFrame.Data()) + resp.Seek(0, 0) + resp.WriteUint8(uint8(results + stepResults)) + resp.WriteUint8(uint8(results)) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + + // add claimables to DB + data = append(data, stepData...) + data[0] = data[0] + results + stepResults + _, err = s.server.db.Exec("UPDATE characters SET gacha_items = $1 WHERE id = $2", data, s.charID) + if err != nil { + s.logger.Fatal("Failed to update gacha_items in db", zap.Error(err)) + } + // deduct gacha coins if relevant, items are handled fine by the standard savedata packet immediately afterwards + // reduce real if trial don't cover cost + if currType == 19 { + _, err = s.server.db.Exec(`UPDATE characters + SET gacha_trial = CASE WHEN (gacha_trial > $1) then gacha_trial - $1 else gacha_trial end, + gacha_prem = CASE WHEN NOT (gacha_trial > $1) then gacha_prem - $1 else gacha_prem end + WHERE id=$2`, currNumber, s.charID) + + } + if err != nil { + s.logger.Fatal("Failed to update gacha_items in db", zap.Error(err)) + } + // update step progression + _, err = s.server.db.Exec("UPDATE stepup_state SET step_progression = $1 WHERE char_id = $2", pkt.RollType+1, s.charID) + if err != nil { + s.logger.Fatal("Failed to update step_progression in db", zap.Error(err)) + } + +} + +func handleMsgMhfReceiveGachaItem(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfReceiveGachaItem) + // persistent for claimable items on cat + var data []byte + err := s.server.db.QueryRow("SELECT COALESCE(gacha_items, $2) FROM characters WHERE id = $1", s.charID, []byte{0x00}).Scan(&data) + if err != nil { + panic("Failed to get gacha_items") + } + // limit of 36 items are returned + if data[0] > 36 { + outData := make([]byte, 181) + copy(outData, data[0:181]) + outData[0] = byte(36) + saveData := append(data[:1], data[181:]...) + saveData[0] = saveData[0] - 36 + doAckBufSucceed(s, pkt.AckHandle, outData) + if pkt.Unk0 != 0x2401 { + _, err := s.server.db.Exec("UPDATE characters SET gacha_items = $2 WHERE id = $1", s.charID, saveData) + if err != nil { + s.logger.Fatal("Failed to update gacha_items in db", zap.Error(err)) + } + } + } else { + doAckBufSucceed(s, pkt.AckHandle, data) + if pkt.Unk0 != 0x2401 { + _, err := s.server.db.Exec("UPDATE characters SET gacha_items = null WHERE id = $1", s.charID) + if err != nil { + s.logger.Fatal("Failed to update gacha_items in db", zap.Error(err)) + } + } + } +} + +func handleMsgMhfGetStepupStatus(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetStepupStatus) + // get the reset time from db + var step_progression int + var step_time time.Time + err := s.server.db.QueryRow(`SELECT COALESCE(step_progression, 0), COALESCE(step_time, $1) FROM stepup_state WHERE char_id = $2 AND shophash = $3`, time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), s.charID, pkt.GachaHash).Scan(&step_progression, &step_time) + if err != nil { + s.logger.Fatal("Failed to Select coalesce in db", zap.Error(err)) + } + + // calculate next midday + var t = time.Now().In(time.FixedZone("UTC+9", 9*60*60)) + year, month, day := t.Date() + midday := time.Date(year, month, day, 12, 0, 0, 0, t.Location()) + if t.After(midday) { + midday = midday.Add(24 * time.Hour) + } + // after midday or not set + if t.After(step_time) { + step_progression = 0 + } + _, err = s.server.db.Exec(`INSERT INTO stepup_state (shophash, step_progression, step_time, char_id) + VALUES ($1,$2,$3,$4) ON CONFLICT (shophash, char_id) + DO UPDATE SET step_progression=$2, step_time=$3 + WHERE EXCLUDED.char_id=$4 AND EXCLUDED.shophash=$1`, pkt.GachaHash, step_progression, midday, s.charID) + if err != nil { + s.logger.Fatal("Failed to update platedata savedata in db", zap.Error(err)) + } + resp := byteframe.NewByteFrame() + resp.WriteUint8(uint8(step_progression)) + resp.WriteUint32(uint32(time.Now().In(time.FixedZone("UTC+9", 9*60*60)).Unix())) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfPlayFreeGacha(s *Session, p mhfpacket.MHFPacket) { + // not sure this is used anywhere, free gachas use the MSG_MHF_PLAY_NORMAL_GACHA method in captures +} + +func handleMsgMhfGetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetBoxGachaInfo) + count := 0 + var used_itemhash pq.Int64Array + // pull array of used values + // single sized respone with 0x00 is a valid with no items present + _ = s.server.db.QueryRow("SELECT used_itemhash FROM lucky_box_state WHERE shophash=$1 AND char_id=$2", pkt.GachaHash, s.charID).Scan((*pq.Int64Array)(&used_itemhash)) + resp := byteframe.NewByteFrame() + resp.WriteUint8(0) + for ind := range used_itemhash { + resp.WriteUint32(uint32(used_itemhash[ind])) + resp.WriteUint8(1) + count++ + } + resp.Seek(0, 0) + resp.WriteUint8(uint8(count)) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgMhfPlayBoxGacha(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPlayBoxGacha) + // needs to query db for input gacha and return a result or number of results + // uint8 number of results + // uint8 item type + // uint16 item id + // uint16 quantity + + var currType, rarityIcon, rollsCount, itemCount byte + var currQuant, currNumber, percentage uint16 + var itemhash uint32 + var itemType, itemId, quantity, usedItemHash pq.Int64Array + var items []lottery.Weighter + // get info for updating data and calculating costs + err := s.server.db.QueryRow("SELECT currType, currNumber, currQuant, rollsCount FROM gacha_shop_items WHERE shophash=$1 AND entryType=$2", pkt.GachaHash, pkt.RollType).Scan(&currType, &currNumber, &currQuant, &rollsCount) + if err != nil { + panic(err) + } + // get existing items in storage if any + var data []byte + _ = s.server.db.QueryRow("SELECT gacha_items FROM characters WHERE id = $1", s.charID).Scan(&data) + if len(data) == 0 { + data = []byte{0x00} + } + // get gacha items and iterate through them for gacha roll + shopEntries, err := s.server.db.Query(`SELECT itemhash, percentage, rarityIcon, itemCount, itemType, itemId, quantity + FROM gacha_shop_items + WHERE shophash=$1 AND entryType=100 + EXCEPT ALL SELECT itemhash, percentage, rarityIcon, itemCount, itemType, itemId, quantity + FROM gacha_shop_items gsi JOIN lucky_box_state lbs ON gsi.itemhash = ANY(lbs.used_itemhash) + WHERE lbs.char_id=$2`, pkt.GachaHash, s.charID) + if err != nil { + panic(err) + } + for shopEntries.Next() { + err = shopEntries.Scan(&itemhash, &percentage, &rarityIcon, &itemCount, (*pq.Int64Array)(&itemType), (*pq.Int64Array)(&itemId), (*pq.Int64Array)(&quantity)) + if err != nil { + panic(err) + } + items = append(items, &gachaItem{itemhash: itemhash, percentage: percentage, rarityIcon: rarityIcon, itemCount: itemCount, itemType: itemType, itemId: itemId, quantity: quantity}) + } + // execute rolls, build response and update database + results := byte(0) + resp := byteframe.NewByteFrame() + dbUpdate := byteframe.NewByteFrame() + resp.WriteUint8(0) // results go here later + l := lottery.NewDefaultLottery() + for x := 0; x < int(rollsCount); x++ { + ind := l.Draw(items) + results += items[ind].(*gachaItem).itemCount + for y := 0; y < int(items[ind].(*gachaItem).itemCount); y++ { + // items in storage don't get rarity + dbUpdate.WriteUint8(uint8(items[ind].(*gachaItem).itemType[y])) + dbUpdate.WriteUint16(uint16(items[ind].(*gachaItem).itemId[y])) + dbUpdate.WriteUint16(uint16(items[ind].(*gachaItem).quantity[y])) + data = append(data, dbUpdate.Data()...) + dbUpdate.Seek(0, 0) + // response needs all item info and the rarity + resp.WriteBytes(dbUpdate.Data()) + resp.WriteUint8(uint8(items[ind].(*gachaItem).rarityIcon)) + + usedItemHash = append(usedItemHash, int64(items[ind].(*gachaItem).itemhash)) + } + // remove rolled + items = append(items[:ind], items[ind+1:]...) + } + resp.Seek(0, 0) + resp.WriteUint8(uint8(results)) + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) + + // add claimables to DB + data[0] = data[0] + results + _, err = s.server.db.Exec("UPDATE characters SET gacha_items = $1 WHERE id = $2", data, s.charID) + if err != nil { + s.logger.Fatal("Failed to update gacha_items in db", zap.Error(err)) + } + // update lucky_box_state + _, err = s.server.db.Exec(` INSERT INTO lucky_box_state (char_id, shophash, used_itemhash) + VALUES ($1,$2,$3) ON CONFLICT (char_id, shophash) + DO UPDATE SET used_itemhash = COALESCE(lucky_box_state.used_itemhash::int[] || $3::int[], $3::int[]) + WHERE EXCLUDED.char_id=$1 AND EXCLUDED.shophash=$2`, s.charID, pkt.GachaHash, usedItemHash) + if err != nil { + s.logger.Fatal("Failed to update lucky box state in db", zap.Error(err)) + } + // deduct gacha coins if relevant, items are handled fine by the standard savedata packet immediately afterwards + if currType == 19 { + _, err = s.server.db.Exec(` UPDATE characters + SET gacha_trial = CASE WHEN (gacha_trial > $1) then gacha_trial - $1 else gacha_trial end, gacha_prem = CASE WHEN NOT (gacha_trial > $1) then gacha_prem - $1 else gacha_prem end + WHERE id=$2`, currNumber, s.charID) + } + if err != nil { + s.logger.Fatal("Failed to update gacha_trial in db", zap.Error(err)) + } +} + +func handleMsgMhfResetBoxGachaInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfResetBoxGachaInfo) + _, err := s.server.db.Exec("DELETE FROM lucky_box_state WHERE shophash=$1 AND char_id=$2", pkt.GachaHash, s.charID) + if err != nil { + panic(err) + } + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} diff --git a/Erupe/server/channelserver/handlers_stage.go b/Erupe/server/channelserver/handlers_stage.go new file mode 100644 index 000000000..3e00f9973 --- /dev/null +++ b/Erupe/server/channelserver/handlers_stage.go @@ -0,0 +1,453 @@ +package channelserver + +import ( + "fmt" + "time" + + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" +) + +func handleMsgSysCreateStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysCreateStage) + + s.server.stagesLock.Lock() + stage := NewStage(pkt.StageID) + stage.maxPlayers = uint16(pkt.PlayerCount) + s.server.stages[stage.id] = stage + s.server.stagesLock.Unlock() + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgSysStageDestruct(s *Session, p mhfpacket.MHFPacket) {} + +func doStageTransfer(s *Session, ackHandle uint32, stageID string) { + // Remove this session from old stage clients list and put myself in the new one. + s.server.stagesLock.Lock() + newStage, gotNewStage := s.server.stages[stageID] + s.server.stagesLock.Unlock() + + if s.stage != nil { + removeSessionFromStage(s) + } + + // Add the new stage. + if gotNewStage { + newStage.Lock() + newStage.clients[s] = s.charID + newStage.Unlock() + } else { + // Fix stages + s.logger.Info("Fix Map Appliqued") + s.server.stagesLock.Lock() + s.server.stages[stageID] = NewStage(stageID) + newStage = s.server.stages[stageID] + s.server.stagesLock.Unlock() + newStage.Lock() + newStage.clients[s] = s.charID + newStage.Unlock() + } + + // Save our new stage ID and pointer to the new stage itself. + s.Lock() + s.stageID = string(stageID) + s.stage = newStage + s.Unlock() + + // Tell the client to cleanup its current stage objects. + s.QueueSendMHF(&mhfpacket.MsgSysCleanupObject{}) + + // Confirm the stage entry. + doAckSimpleSucceed(s, ackHandle, []byte{0x00, 0x00, 0x00, 0x00}) + + // Notify existing stage clients that this new client has entered. + s.logger.Info("Sending MsgSysInsertUser") + if s.stage != nil { // avoids lock up when using bed for dream quests + s.stage.BroadcastMHF(&mhfpacket.MsgSysInsertUser{ + CharID: s.charID, + }, s) + + // It seems to be acceptable to recast all MSG_SYS_SET_USER_BINARY messages so far, + // players are still notified when a new player has joined the stage. + // These extra messages may not be needed + //s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{ + // CharID: s.charID, + // BinaryType: 1, + //}, s) + //s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{ + // CharID: s.charID, + // BinaryType: 2, + //}, s) + //s.stage.BroadcastMHF(&mhfpacket.MsgSysNotifyUserBinary{ + // CharID: s.charID, + // BinaryType: 3, + //}, s) + + //Notify the entree client about all of the existing clients in the stage. + s.logger.Info("Notifying entree about existing stage clients") + s.stage.RLock() + clientNotif := byteframe.NewByteFrame() + for session := range s.stage.clients { + var cur mhfpacket.MHFPacket + cur = &mhfpacket.MsgSysInsertUser{ + CharID: session.charID, + } + clientNotif.WriteUint16(uint16(cur.Opcode())) + cur.Build(clientNotif, session.clientContext) + + cur = &mhfpacket.MsgSysNotifyUserBinary{ + CharID: session.charID, + BinaryType: 1, + } + clientNotif.WriteUint16(uint16(cur.Opcode())) + cur.Build(clientNotif, session.clientContext) + + cur = &mhfpacket.MsgSysNotifyUserBinary{ + CharID: session.charID, + BinaryType: 2, + } + clientNotif.WriteUint16(uint16(cur.Opcode())) + cur.Build(clientNotif, session.clientContext) + + cur = &mhfpacket.MsgSysNotifyUserBinary{ + CharID: session.charID, + BinaryType: 3, + } + clientNotif.WriteUint16(uint16(cur.Opcode())) + cur.Build(clientNotif, session.clientContext) + } + s.stage.RUnlock() + clientNotif.WriteUint16(0x0010) // End it. + s.QueueSend(clientNotif.Data()) + + // Notify the client to duplicate the existing objects. + s.logger.Info("Notifying entree about existing stage objects") + clientDupObjNotif := byteframe.NewByteFrame() + s.stage.RLock() + for _, obj := range s.stage.objects { + cur := &mhfpacket.MsgSysDuplicateObject{ + ObjID: obj.id, + X: obj.x, + Y: obj.y, + Z: obj.z, + Unk0: 0, + OwnerCharID: obj.ownerCharID, + } + clientDupObjNotif.WriteUint16(uint16(cur.Opcode())) + cur.Build(clientDupObjNotif, s.clientContext) + } + s.stage.RUnlock() + clientDupObjNotif.WriteUint16(0x0010) // End it. + s.QueueSend(clientDupObjNotif.Data()) + } +} + +func removeSessionFromStage(s *Session) { + s.stage.Lock() + defer s.stage.Unlock() + + // Remove client from old stage. + delete(s.stage.clients, s) + delete(s.stage.reservedClientSlots, s.charID) + + // Delete old stage objects owned by the client. + s.logger.Info("Sending MsgSysDeleteObject to old stage clients") + for objID, stageObject := range s.stage.objects { + if stageObject.ownerCharID == s.charID { + // Broadcast the deletion to clients in the stage. + s.stage.BroadcastMHF(&mhfpacket.MsgSysDeleteObject{ + ObjID: stageObject.id, + }, s) + // TODO(Andoryuuta): Should this be sent to the owner's client as well? it currently isn't. + // Actually delete it form the objects map. + delete(s.stage.objects, objID) + } +} + for objListID, stageObjectList := range s.stage.objectList { + if stageObjectList.charid == s.charID { + //Added to prevent duplicates from flooding ObjectMap and causing server hangs + s.stage.objectList[objListID].status=false + s.stage.objectList[objListID].charid=0 + } + } +} + + +func handleMsgSysEnterStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysEnterStage) + fmt.Printf("The Stage is %s\n",pkt.StageID) + // Push our current stage ID to the movement stack before entering another one. + s.Lock() + s.stageMoveStack.Push(s.stageID) + s.Unlock() + + doStageTransfer(s, pkt.AckHandle, pkt.StageID) +} + +func handleMsgSysBackStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysBackStage) + + if s.stage != nil { + removeSessionFromStage(s) + } + + // Transfer back to the saved stage ID before the previous move or enter. + s.Lock() + backStage, err := s.stageMoveStack.Pop() + s.Unlock() + + if err != nil { + panic(err) + } + + doStageTransfer(s, pkt.AckHandle, backStage) +} + +func handleMsgSysMoveStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysMoveStage) + + // Push our current stage ID to the movement stack before entering another one. + s.Lock() + s.stageMoveStack.Push(s.stageID) + s.Unlock() + + doStageTransfer(s, pkt.AckHandle, pkt.StageID) +} + +func handleMsgSysLeaveStage(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysLockStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysLockStage) + // TODO(Andoryuuta): What does this packet _actually_ do? + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgSysUnlockStage(s *Session, p mhfpacket.MHFPacket) { + s.reservationStage.RLock() + defer s.reservationStage.RUnlock() + + destructMessage := &mhfpacket.MsgSysStageDestruct{} + + for charID := range s.reservationStage.reservedClientSlots { + session := s.server.FindSessionByCharID(charID) + session.QueueSendMHF(destructMessage) + } + + s.server.Lock() + defer s.server.Unlock() + + delete(s.server.stages, s.reservationStage.id) +} + +func handleMsgSysReserveStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysReserveStage) + + stageID := pkt.StageID + fmt.Printf("Got reserve stage req, TargetCount:%v, StageID:%v\n", pkt.Unk0, stageID) + + // Try to get the stage + s.server.stagesLock.Lock() + stage, gotStage := s.server.stages[stageID] + s.server.stagesLock.Unlock() + + if !gotStage { + s.logger.Fatal("Failed to get stage", zap.String("StageID", stageID)) + } + + // Try to reserve a slot, fail if full. + stage.Lock() + defer stage.Unlock() + + // Quick fix to allow readying up while party is full, more investigation needed + // Reserve stage is also sent when a player is ready, probably need to parse the + // request a little more thoroughly. + if _, exists := stage.reservedClientSlots[s.charID]; exists { + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + } else if uint16(len(stage.reservedClientSlots)) < stage.maxPlayers { + // Add the charID to the stage's reservation map + stage.reservedClientSlots[s.charID] = nil + + // Save the reservation stage in the session for later use in MsgSysUnreserveStage. + s.Lock() + s.reservationStage = stage + s.Unlock() + + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + } else { + doAckSimpleFail(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) + } +} + +func handleMsgSysUnreserveStage(s *Session, p mhfpacket.MHFPacket) { + // Clear the saved reservation stage + s.Lock() + stage := s.reservationStage + if stage != nil { + s.reservationStage = nil + } + s.Unlock() + + // Remove the charID from the stage's reservation map + if stage != nil { + stage.Lock() + _, exists := stage.reservedClientSlots[s.charID] + if exists { + delete(stage.reservedClientSlots, s.charID) + } + stage.Unlock() + } +} + +func handleMsgSysSetStagePass(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysWaitStageBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysWaitStageBinary) + defer s.logger.Debug("MsgSysWaitStageBinary Done!") + + // Try to get the stage + stageID := pkt.StageID + s.server.stagesLock.Lock() + stage, gotStage := s.server.stages[stageID] + s.server.stagesLock.Unlock() + + // TODO(Andoryuuta): This is a hack for a binary part that none of the clients set, figure out what it represents. + // In the packet captures, it seemingly comes out of nowhere, so presumably the server makes it. + if pkt.BinaryType0 == 1 && pkt.BinaryType1 == 12 { + // This might contain the hunter count, or max player count? + doAckBufSucceed(s, pkt.AckHandle, []byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) + return + } + + // If we got the stage, lock and try to get the data. + var stageBinary []byte + var gotBinary bool + if gotStage { + for { + s.logger.Debug("MsgSysWaitStageBinary before lock and get stage") + stage.Lock() + stageBinary, gotBinary = stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] + stage.Unlock() + s.logger.Debug("MsgSysWaitStageBinary after lock and get stage") + + if gotBinary { + doAckBufSucceed(s, pkt.AckHandle, stageBinary) + break + } else { + s.logger.Debug("Waiting stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1)) + + // Couldn't get binary, sleep for some time and try again. + time.Sleep(2 * time.Second) + continue + } + + // TODO(Andoryuuta): Figure out what the game sends on timeout and implement it! + /* + if timeout { + s.logger.Warn("Failed to get stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1)) + s.logger.Warn("Sending blank stage binary") + doAckBufSucceed(s, pkt.AckHandle, []byte{}) + return + } + */ + } + } else { + s.logger.Warn("Failed to get stage", zap.String("StageID", stageID)) + } +} + +func handleMsgSysSetStageBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysSetStageBinary) + + // Try to get the stage + stageID := pkt.StageID + s.server.stagesLock.Lock() + stage, gotStage := s.server.stages[stageID] + s.server.stagesLock.Unlock() + + // If we got the stage, lock and set the data. + if gotStage { + stage.Lock() + stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] = pkt.RawDataPayload + stage.Unlock() + } else { + s.logger.Warn("Failed to get stage", zap.String("StageID", stageID)) + } + s.logger.Debug("handleMsgSysSetStageBinary Done!") +} + +func handleMsgSysGetStageBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysGetStageBinary) + + // Try to get the stage + stageID := pkt.StageID + s.server.stagesLock.Lock() + stage, gotStage := s.server.stages[stageID] + s.server.stagesLock.Unlock() + + // If we got the stage, lock and try to get the data. + var stageBinary []byte + var gotBinary bool + if gotStage { + stage.Lock() + stageBinary, gotBinary = stage.rawBinaryData[stageBinaryKey{pkt.BinaryType0, pkt.BinaryType1}] + stage.Unlock() + } else { + s.logger.Warn("Failed to get stage", zap.String("StageID", stageID)) + } + + if gotBinary { + doAckBufSucceed(s, pkt.AckHandle, stageBinary) + + } else if pkt.BinaryType1 == 4 { + // This particular type seems to be expecting data that isn't set + // is it required before the party joining can be completed + //s.QueueAck(pkt.AckHandle, []byte{0x01, 0x00, 0x00, 0x00, 0x10}) + + // TODO(Andoryuuta): This doesn't fit a normal ack packet? where is this from? + // This would be a buffered(0x01), non-error(0x00), with no data payload (size 0x00, 0x00) packet. + // but for some reason has a 0x10 on the end that the client shouldn't parse? + + doAckBufSucceed(s, pkt.AckHandle, []byte{}) // Without the previous 0x10 suffix + } else { + s.logger.Warn("Failed to get stage binary", zap.Uint8("BinaryType0", pkt.BinaryType0), zap.Uint8("pkt.BinaryType1", pkt.BinaryType1)) + s.logger.Warn("Sending blank stage binary") + doAckBufSucceed(s, pkt.AckHandle, []byte{}) + } + + s.logger.Debug("MsgSysGetStageBinary Done!") +} + +func handleMsgSysEnumerateStage(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysEnumerateStage) + + // Read-lock the server stage map. + s.server.stagesLock.RLock() + defer s.server.stagesLock.RUnlock() + + // Build the response + resp := byteframe.NewByteFrame() + resp.WriteUint16(uint16(len(s.server.stages))) + for sid, stage := range s.server.stages { + stage.RLock() + defer stage.RUnlock() + if len(stage.reservedClientSlots)+len(stage.clients) == 0 { + continue + } + + resp.WriteUint16(uint16(len(stage.reservedClientSlots))) // Current players. + resp.WriteUint16(0) // Unknown value + + var hasDeparted uint16 + if stage.hasDeparted { + hasDeparted = 1 + } + resp.WriteUint16(hasDeparted) // HasDeparted. + resp.WriteUint16(stage.maxPlayers) // Max players. + resp.WriteBool(len(stage.password) > 0) // Password protected. + resp.WriteUint8(uint8(len(sid))) + resp.WriteBytes([]byte(sid)) + } + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} diff --git a/Erupe/server/channelserver/handlers_table.go b/Erupe/server/channelserver/handlers_table.go new file mode 100644 index 000000000..0e7039552 --- /dev/null +++ b/Erupe/server/channelserver/handlers_table.go @@ -0,0 +1,446 @@ +package channelserver + +import ( + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/mhfpacket" +) + +type handlerFunc func(s *Session, p mhfpacket.MHFPacket) + +var handlerTable map[network.PacketID]handlerFunc + +func init() { + handlerTable = make(map[network.PacketID]handlerFunc) + handlerTable[network.MSG_HEAD] = handleMsgHead + handlerTable[network.MSG_SYS_reserve01] = handleMsgSysReserve01 + handlerTable[network.MSG_SYS_reserve02] = handleMsgSysReserve02 + handlerTable[network.MSG_SYS_reserve03] = handleMsgSysReserve03 + handlerTable[network.MSG_SYS_reserve04] = handleMsgSysReserve04 + handlerTable[network.MSG_SYS_reserve05] = handleMsgSysReserve05 + handlerTable[network.MSG_SYS_reserve06] = handleMsgSysReserve06 + handlerTable[network.MSG_SYS_reserve07] = handleMsgSysReserve07 + handlerTable[network.MSG_SYS_ADD_OBJECT] = handleMsgSysAddObject + handlerTable[network.MSG_SYS_DEL_OBJECT] = handleMsgSysDelObject + handlerTable[network.MSG_SYS_DISP_OBJECT] = handleMsgSysDispObject + handlerTable[network.MSG_SYS_HIDE_OBJECT] = handleMsgSysHideObject + handlerTable[network.MSG_SYS_reserve0C] = handleMsgSysReserve0C + handlerTable[network.MSG_SYS_reserve0D] = handleMsgSysReserve0D + handlerTable[network.MSG_SYS_reserve0E] = handleMsgSysReserve0E + handlerTable[network.MSG_SYS_EXTEND_THRESHOLD] = handleMsgSysExtendThreshold + handlerTable[network.MSG_SYS_END] = handleMsgSysEnd + handlerTable[network.MSG_SYS_NOP] = handleMsgSysNop + handlerTable[network.MSG_SYS_ACK] = handleMsgSysAck + handlerTable[network.MSG_SYS_TERMINAL_LOG] = handleMsgSysTerminalLog + handlerTable[network.MSG_SYS_LOGIN] = handleMsgSysLogin + handlerTable[network.MSG_SYS_LOGOUT] = handleMsgSysLogout + handlerTable[network.MSG_SYS_SET_STATUS] = handleMsgSysSetStatus + handlerTable[network.MSG_SYS_PING] = handleMsgSysPing + handlerTable[network.MSG_SYS_CAST_BINARY] = handleMsgSysCastBinary + handlerTable[network.MSG_SYS_HIDE_CLIENT] = handleMsgSysHideClient + handlerTable[network.MSG_SYS_TIME] = handleMsgSysTime + handlerTable[network.MSG_SYS_CASTED_BINARY] = handleMsgSysCastedBinary + handlerTable[network.MSG_SYS_GET_FILE] = handleMsgSysGetFile + handlerTable[network.MSG_SYS_ISSUE_LOGKEY] = handleMsgSysIssueLogkey + handlerTable[network.MSG_SYS_RECORD_LOG] = handleMsgSysRecordLog + handlerTable[network.MSG_SYS_ECHO] = handleMsgSysEcho + handlerTable[network.MSG_SYS_CREATE_STAGE] = handleMsgSysCreateStage + handlerTable[network.MSG_SYS_STAGE_DESTRUCT] = handleMsgSysStageDestruct + handlerTable[network.MSG_SYS_ENTER_STAGE] = handleMsgSysEnterStage + handlerTable[network.MSG_SYS_BACK_STAGE] = handleMsgSysBackStage + handlerTable[network.MSG_SYS_MOVE_STAGE] = handleMsgSysMoveStage + handlerTable[network.MSG_SYS_LEAVE_STAGE] = handleMsgSysLeaveStage + handlerTable[network.MSG_SYS_LOCK_STAGE] = handleMsgSysLockStage + handlerTable[network.MSG_SYS_UNLOCK_STAGE] = handleMsgSysUnlockStage + handlerTable[network.MSG_SYS_RESERVE_STAGE] = handleMsgSysReserveStage + handlerTable[network.MSG_SYS_UNRESERVE_STAGE] = handleMsgSysUnreserveStage + handlerTable[network.MSG_SYS_SET_STAGE_PASS] = handleMsgSysSetStagePass + handlerTable[network.MSG_SYS_WAIT_STAGE_BINARY] = handleMsgSysWaitStageBinary + handlerTable[network.MSG_SYS_SET_STAGE_BINARY] = handleMsgSysSetStageBinary + handlerTable[network.MSG_SYS_GET_STAGE_BINARY] = handleMsgSysGetStageBinary + handlerTable[network.MSG_SYS_ENUMERATE_CLIENT] = handleMsgSysEnumerateClient + handlerTable[network.MSG_SYS_ENUMERATE_STAGE] = handleMsgSysEnumerateStage + handlerTable[network.MSG_SYS_CREATE_MUTEX] = handleMsgSysCreateMutex + handlerTable[network.MSG_SYS_CREATE_OPEN_MUTEX] = handleMsgSysCreateOpenMutex + handlerTable[network.MSG_SYS_DELETE_MUTEX] = handleMsgSysDeleteMutex + handlerTable[network.MSG_SYS_OPEN_MUTEX] = handleMsgSysOpenMutex + handlerTable[network.MSG_SYS_CLOSE_MUTEX] = handleMsgSysCloseMutex + handlerTable[network.MSG_SYS_CREATE_SEMAPHORE] = handleMsgSysCreateSemaphore + handlerTable[network.MSG_SYS_CREATE_ACQUIRE_SEMAPHORE] = handleMsgSysCreateAcquireSemaphore + handlerTable[network.MSG_SYS_DELETE_SEMAPHORE] = handleMsgSysDeleteSemaphore + handlerTable[network.MSG_SYS_ACQUIRE_SEMAPHORE] = handleMsgSysAcquireSemaphore + handlerTable[network.MSG_SYS_RELEASE_SEMAPHORE] = handleMsgSysReleaseSemaphore + handlerTable[network.MSG_SYS_LOCK_GLOBAL_SEMA] = handleMsgSysLockGlobalSema + handlerTable[network.MSG_SYS_UNLOCK_GLOBAL_SEMA] = handleMsgSysUnlockGlobalSema + handlerTable[network.MSG_SYS_CHECK_SEMAPHORE] = handleMsgSysCheckSemaphore + handlerTable[network.MSG_SYS_OPERATE_REGISTER] = handleMsgSysOperateRegister + handlerTable[network.MSG_SYS_LOAD_REGISTER] = handleMsgSysLoadRegister + handlerTable[network.MSG_SYS_NOTIFY_REGISTER] = handleMsgSysNotifyRegister + handlerTable[network.MSG_SYS_CREATE_OBJECT] = handleMsgSysCreateObject + handlerTable[network.MSG_SYS_DELETE_OBJECT] = handleMsgSysDeleteObject + handlerTable[network.MSG_SYS_POSITION_OBJECT] = handleMsgSysPositionObject + handlerTable[network.MSG_SYS_ROTATE_OBJECT] = handleMsgSysRotateObject + handlerTable[network.MSG_SYS_DUPLICATE_OBJECT] = handleMsgSysDuplicateObject + handlerTable[network.MSG_SYS_SET_OBJECT_BINARY] = handleMsgSysSetObjectBinary + handlerTable[network.MSG_SYS_GET_OBJECT_BINARY] = handleMsgSysGetObjectBinary + handlerTable[network.MSG_SYS_GET_OBJECT_OWNER] = handleMsgSysGetObjectOwner + handlerTable[network.MSG_SYS_UPDATE_OBJECT_BINARY] = handleMsgSysUpdateObjectBinary + handlerTable[network.MSG_SYS_CLEANUP_OBJECT] = handleMsgSysCleanupObject + handlerTable[network.MSG_SYS_reserve4A] = handleMsgSysReserve4A + handlerTable[network.MSG_SYS_reserve4B] = handleMsgSysReserve4B + handlerTable[network.MSG_SYS_reserve4C] = handleMsgSysReserve4C + handlerTable[network.MSG_SYS_reserve4D] = handleMsgSysReserve4D + handlerTable[network.MSG_SYS_reserve4E] = handleMsgSysReserve4E + handlerTable[network.MSG_SYS_reserve4F] = handleMsgSysReserve4F + handlerTable[network.MSG_SYS_INSERT_USER] = handleMsgSysInsertUser + handlerTable[network.MSG_SYS_DELETE_USER] = handleMsgSysDeleteUser + handlerTable[network.MSG_SYS_SET_USER_BINARY] = handleMsgSysSetUserBinary + handlerTable[network.MSG_SYS_GET_USER_BINARY] = handleMsgSysGetUserBinary + handlerTable[network.MSG_SYS_NOTIFY_USER_BINARY] = handleMsgSysNotifyUserBinary + handlerTable[network.MSG_SYS_reserve55] = handleMsgSysReserve55 + handlerTable[network.MSG_SYS_reserve56] = handleMsgSysReserve56 + handlerTable[network.MSG_SYS_reserve57] = handleMsgSysReserve57 + handlerTable[network.MSG_SYS_UPDATE_RIGHT] = handleMsgSysUpdateRight + handlerTable[network.MSG_SYS_AUTH_QUERY] = handleMsgSysAuthQuery + handlerTable[network.MSG_SYS_AUTH_DATA] = handleMsgSysAuthData + handlerTable[network.MSG_SYS_AUTH_TERMINAL] = handleMsgSysAuthTerminal + handlerTable[network.MSG_SYS_reserve5C] = handleMsgSysReserve5C + handlerTable[network.MSG_SYS_RIGHTS_RELOAD] = handleMsgSysRightsReload + handlerTable[network.MSG_SYS_reserve5E] = handleMsgSysReserve5E + handlerTable[network.MSG_SYS_reserve5F] = handleMsgSysReserve5F + handlerTable[network.MSG_MHF_SAVEDATA] = handleMsgMhfSavedata + handlerTable[network.MSG_MHF_LOADDATA] = handleMsgMhfLoaddata + handlerTable[network.MSG_MHF_LIST_MEMBER] = handleMsgMhfListMember + handlerTable[network.MSG_MHF_OPR_MEMBER] = handleMsgMhfOprMember + handlerTable[network.MSG_MHF_ENUMERATE_DIST_ITEM] = handleMsgMhfEnumerateDistItem + handlerTable[network.MSG_MHF_APPLY_DIST_ITEM] = handleMsgMhfApplyDistItem + handlerTable[network.MSG_MHF_ACQUIRE_DIST_ITEM] = handleMsgMhfAcquireDistItem + handlerTable[network.MSG_MHF_GET_DIST_DESCRIPTION] = handleMsgMhfGetDistDescription + handlerTable[network.MSG_MHF_SEND_MAIL] = handleMsgMhfSendMail + handlerTable[network.MSG_MHF_READ_MAIL] = handleMsgMhfReadMail + handlerTable[network.MSG_MHF_LIST_MAIL] = handleMsgMhfListMail + handlerTable[network.MSG_MHF_OPRT_MAIL] = handleMsgMhfOprtMail + handlerTable[network.MSG_MHF_LOAD_FAVORITE_QUEST] = handleMsgMhfLoadFavoriteQuest + handlerTable[network.MSG_MHF_SAVE_FAVORITE_QUEST] = handleMsgMhfSaveFavoriteQuest + handlerTable[network.MSG_MHF_REGISTER_EVENT] = handleMsgMhfRegisterEvent + handlerTable[network.MSG_MHF_RELEASE_EVENT] = handleMsgMhfReleaseEvent + handlerTable[network.MSG_MHF_TRANSIT_MESSAGE] = handleMsgMhfTransitMessage + handlerTable[network.MSG_SYS_reserve71] = handleMsgSysReserve71 + handlerTable[network.MSG_SYS_reserve72] = handleMsgSysReserve72 + handlerTable[network.MSG_SYS_reserve73] = handleMsgSysReserve73 + handlerTable[network.MSG_SYS_reserve74] = handleMsgSysReserve74 + handlerTable[network.MSG_SYS_reserve75] = handleMsgSysReserve75 + handlerTable[network.MSG_SYS_reserve76] = handleMsgSysReserve76 + handlerTable[network.MSG_SYS_reserve77] = handleMsgSysReserve77 + handlerTable[network.MSG_SYS_reserve78] = handleMsgSysReserve78 + handlerTable[network.MSG_SYS_reserve79] = handleMsgSysReserve79 + handlerTable[network.MSG_SYS_reserve7A] = handleMsgSysReserve7A + handlerTable[network.MSG_SYS_reserve7B] = handleMsgSysReserve7B + handlerTable[network.MSG_SYS_reserve7C] = handleMsgSysReserve7C + handlerTable[network.MSG_CA_EXCHANGE_ITEM] = handleMsgCaExchangeItem + handlerTable[network.MSG_SYS_reserve7E] = handleMsgSysReserve7E + handlerTable[network.MSG_MHF_PRESENT_BOX] = handleMsgMhfPresentBox + handlerTable[network.MSG_MHF_SERVER_COMMAND] = handleMsgMhfServerCommand + handlerTable[network.MSG_MHF_SHUT_CLIENT] = handleMsgMhfShutClient + handlerTable[network.MSG_MHF_ANNOUNCE] = handleMsgMhfAnnounce + handlerTable[network.MSG_MHF_SET_LOGINWINDOW] = handleMsgMhfSetLoginwindow + handlerTable[network.MSG_SYS_TRANS_BINARY] = handleMsgSysTransBinary + handlerTable[network.MSG_SYS_COLLECT_BINARY] = handleMsgSysCollectBinary + handlerTable[network.MSG_SYS_GET_STATE] = handleMsgSysGetState + handlerTable[network.MSG_SYS_SERIALIZE] = handleMsgSysSerialize + handlerTable[network.MSG_SYS_ENUMLOBBY] = handleMsgSysEnumlobby + handlerTable[network.MSG_SYS_ENUMUSER] = handleMsgSysEnumuser + handlerTable[network.MSG_SYS_INFOKYSERVER] = handleMsgSysInfokyserver + handlerTable[network.MSG_MHF_GET_CA_UNIQUE_ID] = handleMsgMhfGetCaUniqueID + handlerTable[network.MSG_MHF_SET_CA_ACHIEVEMENT] = handleMsgMhfSetCaAchievement + handlerTable[network.MSG_MHF_CARAVAN_MY_SCORE] = handleMsgMhfCaravanMyScore + handlerTable[network.MSG_MHF_CARAVAN_RANKING] = handleMsgMhfCaravanRanking + handlerTable[network.MSG_MHF_CARAVAN_MY_RANK] = handleMsgMhfCaravanMyRank + handlerTable[network.MSG_MHF_CREATE_GUILD] = handleMsgMhfCreateGuild + handlerTable[network.MSG_MHF_OPERATE_GUILD] = handleMsgMhfOperateGuild + handlerTable[network.MSG_MHF_OPERATE_GUILD_MEMBER] = handleMsgMhfOperateGuildMember + handlerTable[network.MSG_MHF_INFO_GUILD] = handleMsgMhfInfoGuild + handlerTable[network.MSG_MHF_ENUMERATE_GUILD] = handleMsgMhfEnumerateGuild + handlerTable[network.MSG_MHF_UPDATE_GUILD] = handleMsgMhfUpdateGuild + handlerTable[network.MSG_MHF_ARRANGE_GUILD_MEMBER] = handleMsgMhfArrangeGuildMember + handlerTable[network.MSG_MHF_ENUMERATE_GUILD_MEMBER] = handleMsgMhfEnumerateGuildMember + handlerTable[network.MSG_MHF_ENUMERATE_CAMPAIGN] = handleMsgMhfEnumerateCampaign + handlerTable[network.MSG_MHF_STATE_CAMPAIGN] = handleMsgMhfStateCampaign + handlerTable[network.MSG_MHF_APPLY_CAMPAIGN] = handleMsgMhfApplyCampaign + handlerTable[network.MSG_MHF_ENUMERATE_ITEM] = handleMsgMhfEnumerateItem + handlerTable[network.MSG_MHF_ACQUIRE_ITEM] = handleMsgMhfAcquireItem + handlerTable[network.MSG_MHF_TRANSFER_ITEM] = handleMsgMhfTransferItem + handlerTable[network.MSG_MHF_MERCENARY_HUNTDATA] = handleMsgMhfMercenaryHuntdata + handlerTable[network.MSG_MHF_ENTRY_ROOKIE_GUILD] = handleMsgMhfEntryRookieGuild + handlerTable[network.MSG_MHF_ENUMERATE_QUEST] = handleMsgMhfEnumerateQuest + handlerTable[network.MSG_MHF_ENUMERATE_EVENT] = handleMsgMhfEnumerateEvent + handlerTable[network.MSG_MHF_ENUMERATE_PRICE] = handleMsgMhfEnumeratePrice + handlerTable[network.MSG_MHF_ENUMERATE_RANKING] = handleMsgMhfEnumerateRanking + handlerTable[network.MSG_MHF_ENUMERATE_ORDER] = handleMsgMhfEnumerateOrder + handlerTable[network.MSG_MHF_ENUMERATE_SHOP] = handleMsgMhfEnumerateShop + handlerTable[network.MSG_MHF_GET_EXTRA_INFO] = handleMsgMhfGetExtraInfo + handlerTable[network.MSG_MHF_UPDATE_INTERIOR] = handleMsgMhfUpdateInterior + handlerTable[network.MSG_MHF_ENUMERATE_HOUSE] = handleMsgMhfEnumerateHouse + handlerTable[network.MSG_MHF_UPDATE_HOUSE] = handleMsgMhfUpdateHouse + handlerTable[network.MSG_MHF_LOAD_HOUSE] = handleMsgMhfLoadHouse + handlerTable[network.MSG_MHF_OPERATE_WAREHOUSE] = handleMsgMhfOperateWarehouse + handlerTable[network.MSG_MHF_ENUMERATE_WAREHOUSE] = handleMsgMhfEnumerateWarehouse + handlerTable[network.MSG_MHF_UPDATE_WAREHOUSE] = handleMsgMhfUpdateWarehouse + handlerTable[network.MSG_MHF_ACQUIRE_TITLE] = handleMsgMhfAcquireTitle + handlerTable[network.MSG_MHF_ENUMERATE_TITLE] = handleMsgMhfEnumerateTitle + handlerTable[network.MSG_MHF_ENUMERATE_GUILD_ITEM] = handleMsgMhfEnumerateGuildItem + handlerTable[network.MSG_MHF_UPDATE_GUILD_ITEM] = handleMsgMhfUpdateGuildItem + handlerTable[network.MSG_MHF_ENUMERATE_UNION_ITEM] = handleMsgMhfEnumerateUnionItem + handlerTable[network.MSG_MHF_UPDATE_UNION_ITEM] = handleMsgMhfUpdateUnionItem + handlerTable[network.MSG_MHF_CREATE_JOINT] = handleMsgMhfCreateJoint + handlerTable[network.MSG_MHF_OPERATE_JOINT] = handleMsgMhfOperateJoint + handlerTable[network.MSG_MHF_INFO_JOINT] = handleMsgMhfInfoJoint + handlerTable[network.MSG_MHF_UPDATE_GUILD_ICON] = handleMsgMhfUpdateGuildIcon + handlerTable[network.MSG_MHF_INFO_FESTA] = handleMsgMhfInfoFesta + handlerTable[network.MSG_MHF_ENTRY_FESTA] = handleMsgMhfEntryFesta + handlerTable[network.MSG_MHF_CHARGE_FESTA] = handleMsgMhfChargeFesta + handlerTable[network.MSG_MHF_ACQUIRE_FESTA] = handleMsgMhfAcquireFesta + handlerTable[network.MSG_MHF_STATE_FESTA_U] = handleMsgMhfStateFestaU + handlerTable[network.MSG_MHF_STATE_FESTA_G] = handleMsgMhfStateFestaG + handlerTable[network.MSG_MHF_ENUMERATE_FESTA_MEMBER] = handleMsgMhfEnumerateFestaMember + handlerTable[network.MSG_MHF_VOTE_FESTA] = handleMsgMhfVoteFesta + handlerTable[network.MSG_MHF_ACQUIRE_CAFE_ITEM] = handleMsgMhfAcquireCafeItem + handlerTable[network.MSG_MHF_UPDATE_CAFEPOINT] = handleMsgMhfUpdateCafepoint + handlerTable[network.MSG_MHF_CHECK_DAILY_CAFEPOINT] = handleMsgMhfCheckDailyCafepoint + handlerTable[network.MSG_MHF_GET_COG_INFO] = handleMsgMhfGetCogInfo + handlerTable[network.MSG_MHF_CHECK_MONTHLY_ITEM] = handleMsgMhfCheckMonthlyItem + handlerTable[network.MSG_MHF_ACQUIRE_MONTHLY_ITEM] = handleMsgMhfAcquireMonthlyItem + handlerTable[network.MSG_MHF_CHECK_WEEKLY_STAMP] = handleMsgMhfCheckWeeklyStamp + handlerTable[network.MSG_MHF_EXCHANGE_WEEKLY_STAMP] = handleMsgMhfExchangeWeeklyStamp + handlerTable[network.MSG_MHF_CREATE_MERCENARY] = handleMsgMhfCreateMercenary + handlerTable[network.MSG_MHF_SAVE_MERCENARY] = handleMsgMhfSaveMercenary + handlerTable[network.MSG_MHF_READ_MERCENARY_W] = handleMsgMhfReadMercenaryW + handlerTable[network.MSG_MHF_READ_MERCENARY_M] = handleMsgMhfReadMercenaryM + handlerTable[network.MSG_MHF_CONTRACT_MERCENARY] = handleMsgMhfContractMercenary + handlerTable[network.MSG_MHF_ENUMERATE_MERCENARY_LOG] = handleMsgMhfEnumerateMercenaryLog + handlerTable[network.MSG_MHF_ENUMERATE_GUACOT] = handleMsgMhfEnumerateGuacot + handlerTable[network.MSG_MHF_UPDATE_GUACOT] = handleMsgMhfUpdateGuacot + handlerTable[network.MSG_MHF_INFO_TOURNAMENT] = handleMsgMhfInfoTournament + handlerTable[network.MSG_MHF_ENTRY_TOURNAMENT] = handleMsgMhfEntryTournament + handlerTable[network.MSG_MHF_ENTER_TOURNAMENT_QUEST] = handleMsgMhfEnterTournamentQuest + handlerTable[network.MSG_MHF_ACQUIRE_TOURNAMENT] = handleMsgMhfAcquireTournament + handlerTable[network.MSG_MHF_GET_ACHIEVEMENT] = handleMsgMhfGetAchievement + handlerTable[network.MSG_MHF_RESET_ACHIEVEMENT] = handleMsgMhfResetAchievement + handlerTable[network.MSG_MHF_ADD_ACHIEVEMENT] = handleMsgMhfAddAchievement + handlerTable[network.MSG_MHF_PAYMENT_ACHIEVEMENT] = handleMsgMhfPaymentAchievement + handlerTable[network.MSG_MHF_DISPLAYED_ACHIEVEMENT] = handleMsgMhfDisplayedAchievement + handlerTable[network.MSG_MHF_INFO_SCENARIO_COUNTER] = handleMsgMhfInfoScenarioCounter + handlerTable[network.MSG_MHF_SAVE_SCENARIO_DATA] = handleMsgMhfSaveScenarioData + handlerTable[network.MSG_MHF_LOAD_SCENARIO_DATA] = handleMsgMhfLoadScenarioData + handlerTable[network.MSG_MHF_GET_BBS_SNS_STATUS] = handleMsgMhfGetBbsSnsStatus + handlerTable[network.MSG_MHF_APPLY_BBS_ARTICLE] = handleMsgMhfApplyBbsArticle + handlerTable[network.MSG_MHF_GET_ETC_POINTS] = handleMsgMhfGetEtcPoints + handlerTable[network.MSG_MHF_UPDATE_ETC_POINT] = handleMsgMhfUpdateEtcPoint + handlerTable[network.MSG_MHF_GET_MYHOUSE_INFO] = handleMsgMhfGetMyhouseInfo + handlerTable[network.MSG_MHF_UPDATE_MYHOUSE_INFO] = handleMsgMhfUpdateMyhouseInfo + handlerTable[network.MSG_MHF_GET_WEEKLY_SCHEDULE] = handleMsgMhfGetWeeklySchedule + handlerTable[network.MSG_MHF_ENUMERATE_INV_GUILD] = handleMsgMhfEnumerateInvGuild + handlerTable[network.MSG_MHF_OPERATION_INV_GUILD] = handleMsgMhfOperationInvGuild + handlerTable[network.MSG_MHF_STAMPCARD_STAMP] = handleMsgMhfStampcardStamp + handlerTable[network.MSG_MHF_STAMPCARD_PRIZE] = handleMsgMhfStampcardPrize + handlerTable[network.MSG_MHF_UNRESERVE_SRG] = handleMsgMhfUnreserveSrg + handlerTable[network.MSG_MHF_LOAD_PLATE_DATA] = handleMsgMhfLoadPlateData + handlerTable[network.MSG_MHF_SAVE_PLATE_DATA] = handleMsgMhfSavePlateData + handlerTable[network.MSG_MHF_LOAD_PLATE_BOX] = handleMsgMhfLoadPlateBox + handlerTable[network.MSG_MHF_SAVE_PLATE_BOX] = handleMsgMhfSavePlateBox + handlerTable[network.MSG_MHF_READ_GUILDCARD] = handleMsgMhfReadGuildcard + handlerTable[network.MSG_MHF_UPDATE_GUILDCARD] = handleMsgMhfUpdateGuildcard + handlerTable[network.MSG_MHF_READ_BEAT_LEVEL] = handleMsgMhfReadBeatLevel + handlerTable[network.MSG_MHF_UPDATE_BEAT_LEVEL] = handleMsgMhfUpdateBeatLevel + handlerTable[network.MSG_MHF_READ_BEAT_LEVEL_ALL_RANKING] = handleMsgMhfReadBeatLevelAllRanking + handlerTable[network.MSG_MHF_READ_BEAT_LEVEL_MY_RANKING] = handleMsgMhfReadBeatLevelMyRanking + handlerTable[network.MSG_MHF_READ_LAST_WEEK_BEAT_RANKING] = handleMsgMhfReadLastWeekBeatRanking + handlerTable[network.MSG_MHF_ACCEPT_READ_REWARD] = handleMsgMhfAcceptReadReward + handlerTable[network.MSG_MHF_GET_ADDITIONAL_BEAT_REWARD] = handleMsgMhfGetAdditionalBeatReward + handlerTable[network.MSG_MHF_GET_FIXED_SEIBATU_RANKING_TABLE] = handleMsgMhfGetFixedSeibatuRankingTable + handlerTable[network.MSG_MHF_GET_BBS_USER_STATUS] = handleMsgMhfGetBbsUserStatus + handlerTable[network.MSG_MHF_KICK_EXPORT_FORCE] = handleMsgMhfKickExportForce + handlerTable[network.MSG_MHF_GET_BREAK_SEIBATU_LEVEL_REWARD] = handleMsgMhfGetBreakSeibatuLevelReward + handlerTable[network.MSG_MHF_GET_WEEKLY_SEIBATU_RANKING_REWARD] = handleMsgMhfGetWeeklySeibatuRankingReward + handlerTable[network.MSG_MHF_GET_EARTH_STATUS] = handleMsgMhfGetEarthStatus + handlerTable[network.MSG_MHF_LOAD_PARTNER] = handleMsgMhfLoadPartner + handlerTable[network.MSG_MHF_SAVE_PARTNER] = handleMsgMhfSavePartner + handlerTable[network.MSG_MHF_GET_GUILD_MISSION_LIST] = handleMsgMhfGetGuildMissionList + handlerTable[network.MSG_MHF_GET_GUILD_MISSION_RECORD] = handleMsgMhfGetGuildMissionRecord + handlerTable[network.MSG_MHF_ADD_GUILD_MISSION_COUNT] = handleMsgMhfAddGuildMissionCount + handlerTable[network.MSG_MHF_SET_GUILD_MISSION_TARGET] = handleMsgMhfSetGuildMissionTarget + handlerTable[network.MSG_MHF_CANCEL_GUILD_MISSION_TARGET] = handleMsgMhfCancelGuildMissionTarget + handlerTable[network.MSG_MHF_LOAD_OTOMO_AIROU] = handleMsgMhfLoadOtomoAirou + handlerTable[network.MSG_MHF_SAVE_OTOMO_AIROU] = handleMsgMhfSaveOtomoAirou + handlerTable[network.MSG_MHF_ENUMERATE_GUILD_TRESURE] = handleMsgMhfEnumerateGuildTresure + handlerTable[network.MSG_MHF_ENUMERATE_AIROULIST] = handleMsgMhfEnumerateAiroulist + handlerTable[network.MSG_MHF_REGIST_GUILD_TRESURE] = handleMsgMhfRegistGuildTresure + handlerTable[network.MSG_MHF_ACQUIRE_GUILD_TRESURE] = handleMsgMhfAcquireGuildTresure + handlerTable[network.MSG_MHF_OPERATE_GUILD_TRESURE_REPORT] = handleMsgMhfOperateGuildTresureReport + handlerTable[network.MSG_MHF_GET_GUILD_TRESURE_SOUVENIR] = handleMsgMhfGetGuildTresureSouvenir + handlerTable[network.MSG_MHF_ACQUIRE_GUILD_TRESURE_SOUVENIR] = handleMsgMhfAcquireGuildTresureSouvenir + handlerTable[network.MSG_MHF_ENUMERATE_FESTA_INTERMEDIATE_PRIZE] = handleMsgMhfEnumerateFestaIntermediatePrize + handlerTable[network.MSG_MHF_ACQUIRE_FESTA_INTERMEDIATE_PRIZE] = handleMsgMhfAcquireFestaIntermediatePrize + handlerTable[network.MSG_MHF_LOAD_DECO_MYSET] = handleMsgMhfLoadDecoMyset + handlerTable[network.MSG_MHF_SAVE_DECO_MYSET] = handleMsgMhfSaveDecoMyset + handlerTable[network.MSG_MHF_reserve010F] = handleMsgMhfReserve010F + handlerTable[network.MSG_MHF_LOAD_GUILD_COOKING] = handleMsgMhfLoadGuildCooking + handlerTable[network.MSG_MHF_REGIST_GUILD_COOKING] = handleMsgMhfRegistGuildCooking + handlerTable[network.MSG_MHF_LOAD_GUILD_ADVENTURE] = handleMsgMhfLoadGuildAdventure + handlerTable[network.MSG_MHF_REGIST_GUILD_ADVENTURE] = handleMsgMhfRegistGuildAdventure + handlerTable[network.MSG_MHF_ACQUIRE_GUILD_ADVENTURE] = handleMsgMhfAcquireGuildAdventure + handlerTable[network.MSG_MHF_CHARGE_GUILD_ADVENTURE] = handleMsgMhfChargeGuildAdventure + handlerTable[network.MSG_MHF_LOAD_LEGEND_DISPATCH] = handleMsgMhfLoadLegendDispatch + handlerTable[network.MSG_MHF_LOAD_HUNTER_NAVI] = handleMsgMhfLoadHunterNavi + handlerTable[network.MSG_MHF_SAVE_HUNTER_NAVI] = handleMsgMhfSaveHunterNavi + handlerTable[network.MSG_MHF_REGIST_SPABI_TIME] = handleMsgMhfRegistSpabiTime + handlerTable[network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_MASTER] = handleMsgMhfGetGuildWeeklyBonusMaster + handlerTable[network.MSG_MHF_GET_GUILD_WEEKLY_BONUS_ACTIVE_COUNT] = handleMsgMhfGetGuildWeeklyBonusActiveCount + handlerTable[network.MSG_MHF_ADD_GUILD_WEEKLY_BONUS_EXCEPTIONAL_USER] = handleMsgMhfAddGuildWeeklyBonusExceptionalUser + handlerTable[network.MSG_MHF_GET_TOWER_INFO] = handleMsgMhfGetTowerInfo + handlerTable[network.MSG_MHF_POST_TOWER_INFO] = handleMsgMhfPostTowerInfo + handlerTable[network.MSG_MHF_GET_GEM_INFO] = handleMsgMhfGetGemInfo + handlerTable[network.MSG_MHF_POST_GEM_INFO] = handleMsgMhfPostGemInfo + handlerTable[network.MSG_MHF_GET_EARTH_VALUE] = handleMsgMhfGetEarthValue + handlerTable[network.MSG_MHF_DEBUG_POST_VALUE] = handleMsgMhfDebugPostValue + handlerTable[network.MSG_MHF_GET_PAPER_DATA] = handleMsgMhfGetPaperData + handlerTable[network.MSG_MHF_GET_NOTICE] = handleMsgMhfGetNotice + handlerTable[network.MSG_MHF_POST_NOTICE] = handleMsgMhfPostNotice + handlerTable[network.MSG_MHF_GET_BOOST_TIME] = handleMsgMhfGetBoostTime + handlerTable[network.MSG_MHF_POST_BOOST_TIME] = handleMsgMhfPostBoostTime + handlerTable[network.MSG_MHF_GET_BOOST_TIME_LIMIT] = handleMsgMhfGetBoostTimeLimit + handlerTable[network.MSG_MHF_POST_BOOST_TIME_LIMIT] = handleMsgMhfPostBoostTimeLimit + handlerTable[network.MSG_MHF_ENUMERATE_FESTA_PERSONAL_PRIZE] = handleMsgMhfEnumerateFestaPersonalPrize + handlerTable[network.MSG_MHF_ACQUIRE_FESTA_PERSONAL_PRIZE] = handleMsgMhfAcquireFestaPersonalPrize + handlerTable[network.MSG_MHF_GET_RAND_FROM_TABLE] = handleMsgMhfGetRandFromTable + handlerTable[network.MSG_MHF_GET_CAFE_DURATION] = handleMsgMhfGetCafeDuration + handlerTable[network.MSG_MHF_GET_CAFE_DURATION_BONUS_INFO] = handleMsgMhfGetCafeDurationBonusInfo + handlerTable[network.MSG_MHF_RECEIVE_CAFE_DURATION_BONUS] = handleMsgMhfReceiveCafeDurationBonus + handlerTable[network.MSG_MHF_POST_CAFE_DURATION_BONUS_RECEIVED] = handleMsgMhfPostCafeDurationBonusReceived + handlerTable[network.MSG_MHF_GET_GACHA_POINT] = handleMsgMhfGetGachaPoint + handlerTable[network.MSG_MHF_USE_GACHA_POINT] = handleMsgMhfUseGachaPoint + handlerTable[network.MSG_MHF_EXCHANGE_FPOINT_2_ITEM] = handleMsgMhfExchangeFpoint2Item + handlerTable[network.MSG_MHF_EXCHANGE_ITEM_2_FPOINT] = handleMsgMhfExchangeItem2Fpoint + handlerTable[network.MSG_MHF_GET_FPOINT_EXCHANGE_LIST] = handleMsgMhfGetFpointExchangeList + handlerTable[network.MSG_MHF_PLAY_STEPUP_GACHA] = handleMsgMhfPlayStepupGacha + handlerTable[network.MSG_MHF_RECEIVE_GACHA_ITEM] = handleMsgMhfReceiveGachaItem + handlerTable[network.MSG_MHF_GET_STEPUP_STATUS] = handleMsgMhfGetStepupStatus + handlerTable[network.MSG_MHF_PLAY_FREE_GACHA] = handleMsgMhfPlayFreeGacha + handlerTable[network.MSG_MHF_GET_TINY_BIN] = handleMsgMhfGetTinyBin + handlerTable[network.MSG_MHF_POST_TINY_BIN] = handleMsgMhfPostTinyBin + handlerTable[network.MSG_MHF_GET_SENYU_DAILY_COUNT] = handleMsgMhfGetSenyuDailyCount + handlerTable[network.MSG_MHF_GET_GUILD_TARGET_MEMBER_NUM] = handleMsgMhfGetGuildTargetMemberNum + handlerTable[network.MSG_MHF_GET_BOOST_RIGHT] = handleMsgMhfGetBoostRight + handlerTable[network.MSG_MHF_START_BOOST_TIME] = handleMsgMhfStartBoostTime + handlerTable[network.MSG_MHF_POST_BOOST_TIME_QUEST_RETURN] = handleMsgMhfPostBoostTimeQuestReturn + handlerTable[network.MSG_MHF_GET_BOX_GACHA_INFO] = handleMsgMhfGetBoxGachaInfo + handlerTable[network.MSG_MHF_PLAY_BOX_GACHA] = handleMsgMhfPlayBoxGacha + handlerTable[network.MSG_MHF_RESET_BOX_GACHA_INFO] = handleMsgMhfResetBoxGachaInfo + handlerTable[network.MSG_MHF_GET_SEIBATTLE] = handleMsgMhfGetSeibattle + handlerTable[network.MSG_MHF_POST_SEIBATTLE] = handleMsgMhfPostSeibattle + handlerTable[network.MSG_MHF_GET_RYOUDAMA] = handleMsgMhfGetRyoudama + handlerTable[network.MSG_MHF_POST_RYOUDAMA] = handleMsgMhfPostRyoudama + handlerTable[network.MSG_MHF_GET_TENROUIRAI] = handleMsgMhfGetTenrouirai + handlerTable[network.MSG_MHF_POST_TENROUIRAI] = handleMsgMhfPostTenrouirai + handlerTable[network.MSG_MHF_POST_GUILD_SCOUT] = handleMsgMhfPostGuildScout + handlerTable[network.MSG_MHF_CANCEL_GUILD_SCOUT] = handleMsgMhfCancelGuildScout + handlerTable[network.MSG_MHF_ANSWER_GUILD_SCOUT] = handleMsgMhfAnswerGuildScout + handlerTable[network.MSG_MHF_GET_GUILD_SCOUT_LIST] = handleMsgMhfGetGuildScoutList + handlerTable[network.MSG_MHF_GET_GUILD_MANAGE_RIGHT] = handleMsgMhfGetGuildManageRight + handlerTable[network.MSG_MHF_SET_GUILD_MANAGE_RIGHT] = handleMsgMhfSetGuildManageRight + handlerTable[network.MSG_MHF_PLAY_NORMAL_GACHA] = handleMsgMhfPlayNormalGacha + handlerTable[network.MSG_MHF_GET_DAILY_MISSION_MASTER] = handleMsgMhfGetDailyMissionMaster + handlerTable[network.MSG_MHF_GET_DAILY_MISSION_PERSONAL] = handleMsgMhfGetDailyMissionPersonal + handlerTable[network.MSG_MHF_SET_DAILY_MISSION_PERSONAL] = handleMsgMhfSetDailyMissionPersonal + handlerTable[network.MSG_MHF_GET_GACHA_PLAY_HISTORY] = handleMsgMhfGetGachaPlayHistory + handlerTable[network.MSG_MHF_GET_REJECT_GUILD_SCOUT] = handleMsgMhfGetRejectGuildScout + handlerTable[network.MSG_MHF_SET_REJECT_GUILD_SCOUT] = handleMsgMhfSetRejectGuildScout + handlerTable[network.MSG_MHF_GET_CA_ACHIEVEMENT_HIST] = handleMsgMhfGetCaAchievementHist + handlerTable[network.MSG_MHF_SET_CA_ACHIEVEMENT_HIST] = handleMsgMhfSetCaAchievementHist + handlerTable[network.MSG_MHF_GET_KEEP_LOGIN_BOOST_STATUS] = handleMsgMhfGetKeepLoginBoostStatus + handlerTable[network.MSG_MHF_USE_KEEP_LOGIN_BOOST] = handleMsgMhfUseKeepLoginBoost + handlerTable[network.MSG_MHF_GET_UD_SCHEDULE] = handleMsgMhfGetUdSchedule + handlerTable[network.MSG_MHF_GET_UD_INFO] = handleMsgMhfGetUdInfo + handlerTable[network.MSG_MHF_GET_KIJU_INFO] = handleMsgMhfGetKijuInfo + handlerTable[network.MSG_MHF_SET_KIJU] = handleMsgMhfSetKiju + handlerTable[network.MSG_MHF_ADD_UD_POINT] = handleMsgMhfAddUdPoint + handlerTable[network.MSG_MHF_GET_UD_MY_POINT] = handleMsgMhfGetUdMyPoint + handlerTable[network.MSG_MHF_GET_UD_TOTAL_POINT_INFO] = handleMsgMhfGetUdTotalPointInfo + handlerTable[network.MSG_MHF_GET_UD_BONUS_QUEST_INFO] = handleMsgMhfGetUdBonusQuestInfo + handlerTable[network.MSG_MHF_GET_UD_SELECTED_COLOR_INFO] = handleMsgMhfGetUdSelectedColorInfo + handlerTable[network.MSG_MHF_GET_UD_MONSTER_POINT] = handleMsgMhfGetUdMonsterPoint + handlerTable[network.MSG_MHF_GET_UD_DAILY_PRESENT_LIST] = handleMsgMhfGetUdDailyPresentList + handlerTable[network.MSG_MHF_GET_UD_NORMA_PRESENT_LIST] = handleMsgMhfGetUdNormaPresentList + handlerTable[network.MSG_MHF_GET_UD_RANKING_REWARD_LIST] = handleMsgMhfGetUdRankingRewardList + handlerTable[network.MSG_MHF_ACQUIRE_UD_ITEM] = handleMsgMhfAcquireUdItem + handlerTable[network.MSG_MHF_GET_REWARD_SONG] = handleMsgMhfGetRewardSong + handlerTable[network.MSG_MHF_USE_REWARD_SONG] = handleMsgMhfUseRewardSong + handlerTable[network.MSG_MHF_ADD_REWARD_SONG_COUNT] = handleMsgMhfAddRewardSongCount + handlerTable[network.MSG_MHF_GET_UD_RANKING] = handleMsgMhfGetUdRanking + handlerTable[network.MSG_MHF_GET_UD_MY_RANKING] = handleMsgMhfGetUdMyRanking + handlerTable[network.MSG_MHF_ACQUIRE_MONTHLY_REWARD] = handleMsgMhfAcquireMonthlyReward + handlerTable[network.MSG_MHF_GET_UD_GUILD_MAP_INFO] = handleMsgMhfGetUdGuildMapInfo + handlerTable[network.MSG_MHF_GENERATE_UD_GUILD_MAP] = handleMsgMhfGenerateUdGuildMap + handlerTable[network.MSG_MHF_GET_UD_TACTICS_POINT] = handleMsgMhfGetUdTacticsPoint + handlerTable[network.MSG_MHF_ADD_UD_TACTICS_POINT] = handleMsgMhfAddUdTacticsPoint + handlerTable[network.MSG_MHF_GET_UD_TACTICS_RANKING] = handleMsgMhfGetUdTacticsRanking + handlerTable[network.MSG_MHF_GET_UD_TACTICS_REWARD_LIST] = handleMsgMhfGetUdTacticsRewardList + handlerTable[network.MSG_MHF_GET_UD_TACTICS_LOG] = handleMsgMhfGetUdTacticsLog + handlerTable[network.MSG_MHF_GET_EQUIP_SKIN_HIST] = handleMsgMhfGetEquipSkinHist + handlerTable[network.MSG_MHF_UPDATE_EQUIP_SKIN_HIST] = handleMsgMhfUpdateEquipSkinHist + handlerTable[network.MSG_MHF_GET_UD_TACTICS_FOLLOWER] = handleMsgMhfGetUdTacticsFollower + handlerTable[network.MSG_MHF_SET_UD_TACTICS_FOLLOWER] = handleMsgMhfSetUdTacticsFollower + handlerTable[network.MSG_MHF_GET_UD_SHOP_COIN] = handleMsgMhfGetUdShopCoin + handlerTable[network.MSG_MHF_USE_UD_SHOP_COIN] = handleMsgMhfUseUdShopCoin + handlerTable[network.MSG_MHF_GET_ENHANCED_MINIDATA] = handleMsgMhfGetEnhancedMinidata + handlerTable[network.MSG_MHF_SET_ENHANCED_MINIDATA] = handleMsgMhfSetEnhancedMinidata + handlerTable[network.MSG_MHF_SEX_CHANGER] = handleMsgMhfSexChanger + handlerTable[network.MSG_MHF_GET_LOBBY_CROWD] = handleMsgMhfGetLobbyCrowd + handlerTable[network.MSG_SYS_reserve180] = handleMsgSysReserve180 + handlerTable[network.MSG_MHF_GUILD_HUNTDATA] = handleMsgMhfGuildHuntdata + handlerTable[network.MSG_MHF_ADD_KOURYOU_POINT] = handleMsgMhfAddKouryouPoint + handlerTable[network.MSG_MHF_GET_KOURYOU_POINT] = handleMsgMhfGetKouryouPoint + handlerTable[network.MSG_MHF_EXCHANGE_KOURYOU_POINT] = handleMsgMhfExchangeKouryouPoint + handlerTable[network.MSG_MHF_GET_UD_TACTICS_BONUS_QUEST] = handleMsgMhfGetUdTacticsBonusQuest + handlerTable[network.MSG_MHF_GET_UD_TACTICS_FIRST_QUEST_BONUS] = handleMsgMhfGetUdTacticsFirstQuestBonus + handlerTable[network.MSG_MHF_GET_UD_TACTICS_REMAINING_POINT] = handleMsgMhfGetUdTacticsRemainingPoint + handlerTable[network.MSG_SYS_reserve188] = handleMsgSysReserve188 + handlerTable[network.MSG_MHF_LOAD_PLATE_MYSET] = handleMsgMhfLoadPlateMyset + handlerTable[network.MSG_MHF_SAVE_PLATE_MYSET] = handleMsgMhfSavePlateMyset + handlerTable[network.MSG_SYS_reserve18B] = handleMsgSysReserve18B + handlerTable[network.MSG_MHF_GET_RESTRICTION_EVENT] = handleMsgMhfGetRestrictionEvent + handlerTable[network.MSG_MHF_SET_RESTRICTION_EVENT] = handleMsgMhfSetRestrictionEvent + handlerTable[network.MSG_SYS_reserve18E] = handleMsgSysReserve18E + handlerTable[network.MSG_SYS_reserve18F] = handleMsgSysReserve18F + handlerTable[network.MSG_MHF_GET_TREND_WEAPON] = handleMsgMhfGetTrendWeapon + handlerTable[network.MSG_MHF_UPDATE_USE_TREND_WEAPON_LOG] = handleMsgMhfUpdateUseTrendWeaponLog + handlerTable[network.MSG_SYS_reserve192] = handleMsgSysReserve192 + handlerTable[network.MSG_SYS_reserve193] = handleMsgSysReserve193 + handlerTable[network.MSG_SYS_reserve194] = handleMsgSysReserve194 + handlerTable[network.MSG_MHF_SAVE_RENGOKU_DATA] = handleMsgMhfSaveRengokuData + handlerTable[network.MSG_MHF_LOAD_RENGOKU_DATA] = handleMsgMhfLoadRengokuData + handlerTable[network.MSG_MHF_GET_RENGOKU_BINARY] = handleMsgMhfGetRengokuBinary + handlerTable[network.MSG_MHF_ENUMERATE_RENGOKU_RANKING] = handleMsgMhfEnumerateRengokuRanking + handlerTable[network.MSG_MHF_GET_RENGOKU_RANKING_RANK] = handleMsgMhfGetRengokuRankingRank + handlerTable[network.MSG_MHF_ACQUIRE_EXCHANGE_SHOP] = handleMsgMhfAcquireExchangeShop + handlerTable[network.MSG_SYS_reserve19B] = handleMsgSysReserve19B + handlerTable[network.MSG_MHF_SAVE_MEZFES_DATA] = handleMsgMhfSaveMezfesData + handlerTable[network.MSG_MHF_LOAD_MEZFES_DATA] = handleMsgMhfLoadMezfesData + handlerTable[network.MSG_SYS_reserve19E] = handleMsgSysReserve19E + handlerTable[network.MSG_SYS_reserve19F] = handleMsgSysReserve19F + handlerTable[network.MSG_MHF_UPDATE_FORCE_GUILD_RANK] = handleMsgMhfUpdateForceGuildRank + handlerTable[network.MSG_MHF_RESET_TITLE] = handleMsgMhfResetTitle + handlerTable[network.MSG_SYS_reserve202] = handleMsgSysReserve202 + handlerTable[network.MSG_SYS_reserve203] = handleMsgSysReserve203 + handlerTable[network.MSG_SYS_reserve204] = handleMsgSysReserve204 + handlerTable[network.MSG_SYS_reserve205] = handleMsgSysReserve205 + handlerTable[network.MSG_SYS_reserve206] = handleMsgSysReserve206 + handlerTable[network.MSG_SYS_reserve207] = handleMsgSysReserve207 + handlerTable[network.MSG_SYS_reserve208] = handleMsgSysReserve208 + handlerTable[network.MSG_SYS_reserve209] = handleMsgSysReserve209 + handlerTable[network.MSG_SYS_reserve20A] = handleMsgSysReserve20A + handlerTable[network.MSG_SYS_reserve20B] = handleMsgSysReserve20B + handlerTable[network.MSG_SYS_reserve20C] = handleMsgSysReserve20C + handlerTable[network.MSG_SYS_reserve20D] = handleMsgSysReserve20D + handlerTable[network.MSG_SYS_reserve20E] = handleMsgSysReserve20E + handlerTable[network.MSG_SYS_reserve20F] = handleMsgSysReserve20F +} diff --git a/Erupe/server/channelserver/handlers_tactics.go b/Erupe/server/channelserver/handlers_tactics.go new file mode 100644 index 000000000..827ac6856 --- /dev/null +++ b/Erupe/server/channelserver/handlers_tactics.go @@ -0,0 +1,63 @@ +package channelserver + +import ( + "encoding/hex" + + "github.com/Solenataris/Erupe/network/mhfpacket" +) + +func handleMsgMhfGetUdTacticsPoint(s *Session, p mhfpacket.MHFPacket) { + // Diva defense interception points + pkt := p.(*mhfpacket.MsgMhfGetUdTacticsPoint) + // Temporary canned response + data, _ := hex.DecodeString("000000A08F0BE2DAE30BE30AE2EAE2E9E2E8E2F5E2F3E2F2E2F1E2BB") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfAddUdTacticsPoint(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfAddUdTacticsPoint) + stubEnumerateNoResults(s, pkt.AckHandle) +} + +func handleMsgMhfGetUdTacticsRewardList(s *Session, p mhfpacket.MHFPacket) { + // Diva defense interception + pkt := p.(*mhfpacket.MsgMhfGetUdTacticsRewardList) + // Temporary canned response + data, _ := hex.DecodeString("000094000000010732DD00010000000000010732DD00010100000000C8071F2800050100000000C80705C000050000000001901A000001F40000000001901A000001F40100000002580705C00005000000000258071F2800050100000003201A000003E80100000003201A000003E80000000003E81A000004B00100000003E81A000004B00000000004B01A000005DC0100000004B01A000005DC0000000005781A000008FC0100000005781A000008FC0000000006401A000009C40000000006401A000009C40100000007081A00000BB80100000007081A00000BB80000000007D00725FA00010000000007D01A00000CE40000000007D00725FC00010100000007D00725FB00010100000007D00725FA00010100000007D01A00000CE40100000007D00725FC00010000000007D00725FB0001000000000BB80705C00005000000000BB8071F280005010000000FA01A00000DAC000000000FA01A00000DAC0100000013880705C00005000000001388071F2800050100000017700725FE00010100000017700725FD00010100000017700725FF00010100000017700725FD00010000000017700725FE00010000000017700725FF0001000000001B581A00000E74000000001B581A00000E74010000001F400727D00005010000001F400727D000050000000023281A00000FA00000000023281A00000FA00100000027100736EF000100000000271007369600010100000027100736EF00010100000027100736EF0001000000002EE00727D10005010000002EE00727D100050000000036B01D000000010100000036B01D00000001000000003A980737DB0001010000003A980736EF00010000000046500725E600010100000046500725E60001000000004E200738C90001010000004E200736EF00010000000055F01A000010680100000055F01A000010680000000061A80736EF00010000000061A80739A600010100000065900727D200050000000065900727D20005010000007530073A0600010100000075300736EF00010000000075300736EF00010000000075300736EF00010100000084D01D000000020000000084D01D00000002010000009C400727D30005010000009C400727D3000500000000B3B01A0000119400000000B3B01A0000119401000000C3500727D4000500000000C3500727D4000501000000D2F01D0000000300000000D2F01D0000000301000000EA600736EF000100000000EA600736EF000101000000F6181A0000125C00000000F6181A0000125C0100000111700727D500050000000111700727D500050100000119400727D600050100000119400727D600050000000121101D000000040000000121101D000000040100000130B01A000013880000000130B01A000013880100000140500727D700050000000140500727D700050100000148201D000000050000000148201D00000005010000014FF01A000014B4000000014FF01A000014B4010000015F900736EF0001000000015F900736EF00010100000167600729EA00050000000167600729EA0005010000016F301D00000006010000016F301D00000006000000017ED00729EB0005000000017ED00729EB0005010000018E701A0000157C010000018E701A0000157C0000000196401D000000070000000196401D00000007010000019E100729EC0005000000019E100729EC000501000001ADB00727CD000100000001ADB00727CD000101000001BD501D0000000800000001BD501D0000000801000001CCF01A0000164401000001CCF01A0000164400000001E4601D0000000901000001E4601D0000000900000001EC300727CC000101000001EC300727CC0001000000020B701D0000000A000000020B701D0000000A010000023A501A0000170C010000023A501A0000170C0000000249F00736EF00010100000249F00736EF00010000000271001A000017D40100000271001A000017D400000002A7B01A0000189C01000002A7B01A0000189C00000002BF200736EF000100000002BF200736EF000101000002D6901A0000196401000002D6901A00001964000000030D400727CB0001000000030D400727CB00010100000343F01A00001A2C0100000343F01A00001A2C0000000372D0072CB0000F0000000372D0072CB0000F01000003A9801A00001BBC00000003A9801A00001BBC01000003F7A01A000003E800010003F7A01A000003E80101000445C01A000003E80101000445C01A000003E80001005E000000020704020005010000000002070402000500000000000307040200140000000000030704020014010000000005071D200003010000000005071D20000300000000000607040200140100000000060704020014000000000008071D210003010000000008071D21000300000000000A070402001401000000000A070402001400000000000C0722EC000501000000000C0722ED000500000000000C0722F2000500000000000C0722EC000500000000000C0722EF000500000000000C0722ED000501000000000C0722F2000501000000000C0722EF000501000000000D1A000003E801000000000D1A000003E800000000000F07357C000501000000000F07357D000501000000000F07357C000500000000000F07357D00050000000000111A000007D00000000000111A000007D00100000000141C00000001000000000014071D2200030000000000141C00000001010000000014071D22000301000000001607357D000701000000001607357C00070000000000160704020028000000000016070402002801000000001607357C000701000000001607357D0007000000000018071D270003000000000018071D27000301000000001A1A00000BB800000000001A1A00000BB801000000001C07357D000701000000001C070402002801000000001C07357D000700000000001C07357C000700000000001C070402002800000000001C07357C000701000000001E070402003C01000000001E070402003C000000000020071D26000301000000002007357C000700000000002007357D000700000000002007357C000701000000002007357D0007010000000020071D260003000000000023071D280003010000000023071D28000300000000002A070402003C00000000002A070402003C01000000002C0725EE000100000000002C0725EE000101000000002E070402005001000000002E07357D000A01000000002E070402005000000000002E07357C000A00000000002E07357D000A00000000002E07357C000A0100000000300725ED00010000000000300725ED0001010000000032071D200003010000000032071D200003000000000034072C7B0001000000000034072C7B0001010000000037071D210003000000000037071D21000301000000003C0722F1000A00000000003C0722F1000A01000000004107040200500000000000410704020050010000000046071D220003010000000046071D22000300000000004B071D27000301000000004B071D2700030000000000500722F1000F0100000000500722F1000F0000000000550704020050010000000055070402005000000000005A071D26000301000000005A071D26000300000000005F071D28000300000000005F071D2800030100000000641A0000C3500100000000641A0000C3500000002607000E00C8000000010000000307000F0032000000010000000307001000320000000100000003070011003200000001000000030700120032000000010000000307000E0096000000040000000A07000F0028000000040000000A0700100028000000040000000A0700110028000000040000000A0700120028000000040000000A07000E00640000000B0000001907000F001E0000000B00000019070010001E0000000B00000019070011001E0000000B00000019070012001E0000000B0000001907000E00320000001A0000002807000F00140000001A0000002807001000140000001A0000002807001100140000001A0000002807001200140000001A0000002807000E001E000000290000004607000F000A0000002900000046070010000A000000290000004607001100010000002900000046070012000A000000290000004607000E0019000000470000006407000F0008000000470000006407001000080000004700000064070011000100000047000000640700120008000000470000006407000E000F000000650000009607000F0006000000650000009607001000010000006500000096070011000600000065000000960700120006000000650000009607000E000500000097000001F407000F000500000097000001F4070010000500000097000001F4") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetUdTacticsFollower(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdTacticsFollower) + doAckBufSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetUdTacticsBonusQuest(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdTacticsBonusQuest) + // Temporary canned response + data, _ := hex.DecodeString("14E2F55DCBFE505DCC1A7003E8E2C55DCC6ED05DCC8AF00258E2CE5DCCDF505DCCFB700279E3075DCD4FD05DCD6BF0041AE2F15DCDC0505DCDDC700258E2C45DCE30D05DCE4CF00258E2F55DCEA1505DCEBD7003E8E2C25DCF11D05DCF2DF00258E2CE5DCF82505DCF9E700279E3075DCFF2D05DD00EF0041AE2CE5DD063505DD07F700279E2F35DD0D3D05DD0EFF0028AE2C35DD144505DD160700258E2F05DD1B4D05DD1D0F00258E2CE5DD225505DD241700279E2F55DD295D05DD2B1F003E8E2F25DD306505DD3227002EEE2CA5DD376D05DD392F00258E3075DD3E7505DD40370041AE2F55DD457D05DD473F003E82027313220686F757273273A3A696E74657276616C29202B2027313220686F757273273A3A696E74657276616C2047524F5550204259206D6170204F52444552204259206D61703B2000C7312B000032") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetUdTacticsFirstQuestBonus(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetUdTacticsFirstQuestBonus) + // Temporary canned response + data, _ := hex.DecodeString("0500000005DC01000007D002000009C40300000BB80400001194") + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfGetUdTacticsRemainingPoint(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetUdTacticsRanking(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfSetUdTacticsFollower(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetUdTacticsLog(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetCafeDuration(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetCafeDurationBonusInfo(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfReceiveCafeDurationBonus(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfPostCafeDurationBonusReceived(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_tournament.go b/Erupe/server/channelserver/handlers_tournament.go new file mode 100644 index 000000000..495eed202 --- /dev/null +++ b/Erupe/server/channelserver/handlers_tournament.go @@ -0,0 +1,9 @@ +package channelserver + +import "github.com/Solenataris/Erupe/network/mhfpacket" + +func handleMsgMhfInfoTournament(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfEntryTournament(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfAcquireTournament(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/handlers_tower.go b/Erupe/server/channelserver/handlers_tower.go new file mode 100644 index 000000000..5a5b58895 --- /dev/null +++ b/Erupe/server/channelserver/handlers_tower.go @@ -0,0 +1,63 @@ +package channelserver + +import ( + "github.com/Solenataris/Erupe/network/mhfpacket" + "encoding/hex" +) + +func handleMsgMhfGetTowerInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfGetTowerInfo) + var data []byte + var err error + /* + type: + 1 == TOWER_RANK_POINT, + 2 == GET_OWN_TOWER_SKILL + 3 == ? + 4 == TOWER_TOUHA_HISTORY + 5 = ? + + [] = type + req + resp + + 01 1d 01 fc 00 09 [00 00 00 01] 00 00 00 02 00 00 00 00 + 00 12 01 fc 00 09 01 00 00 18 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 + + 01 1d 01 fc 00 0a [00 00 00 02] 00 00 00 00 00 00 00 00 + 00 12 01 fc 00 0a 01 00 00 94 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 01 1d 01 ff 00 0f [00 00 00 04] 00 00 00 00 00 00 00 00 + 00 12 01 ff 00 0f 01 00 00 24 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + 01 1d 01 fc 00 0b [00 00 00 05] 00 00 00 00 00 00 00 00 + 00 12 01 fc 00 0b 01 00 00 10 0a 21 8e ad 00 00 00 00 00 00 00 00 00 00 00 00 + */ + switch pkt.InfoType { + case mhfpacket.TowerInfoTypeTowerRankPoint: + data, err = hex.DecodeString("0A218EAD0000000000000000000000010000000000000000") + case mhfpacket.TowerInfoTypeGetOwnTowerSkill: + //data, err = hex.DecodeString("0A218EAD000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + data, err = hex.DecodeString("0A218EAD0000000000000000000000010000001C0000000500050000000000020000000000000000000000000000000000030003000000000003000500050000000300030003000300030003000200030001000300020002000300010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") + case mhfpacket.TowerInfoTypeUnk3: + panic("No known response values for TowerInfoTypeUnk3") + case mhfpacket.TowerInfoTypeTowerTouhaHistory: + data, err = hex.DecodeString("0A218EAD0000000000000000000000010000000000000000000000000000000000000000") + case mhfpacket.TowerInfoTypeUnk5: + data, err = hex.DecodeString("0A218EAD000000000000000000000000") + } + + if err != nil { + stubGetNoResults(s, pkt.AckHandle) + } + doAckBufSucceed(s, pkt.AckHandle, data) +} + +func handleMsgMhfPostTowerInfo(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgMhfPostTowerInfo) + doAckSimpleSucceed(s, pkt.AckHandle, []byte{0x00, 0x00, 0x00, 0x00}) +} + +func handleMsgMhfGetGemInfo(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfPostGemInfo(s *Session, p mhfpacket.MHFPacket) {} \ No newline at end of file diff --git a/Erupe/server/channelserver/handlers_users.go b/Erupe/server/channelserver/handlers_users.go new file mode 100644 index 000000000..24531fde8 --- /dev/null +++ b/Erupe/server/channelserver/handlers_users.go @@ -0,0 +1,66 @@ +package channelserver + +import ( + "encoding/base64" + "fmt" + + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/Andoryuuta/byteframe" +) + +func handleMsgSysInsertUser(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysDeleteUser(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgSysSetUserBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysSetUserBinary) + s.server.userBinaryPartsLock.Lock() + s.server.userBinaryParts[userBinaryPartID{charID: s.charID, index: pkt.BinaryType}] = pkt.RawDataPayload + s.server.userBinaryPartsLock.Unlock() + + msg := &mhfpacket.MsgSysNotifyUserBinary{ + CharID: s.charID, + BinaryType: pkt.BinaryType, + } + + s.stage.BroadcastMHF(msg, s) +} + +func handleMsgSysGetUserBinary(s *Session, p mhfpacket.MHFPacket) { + pkt := p.(*mhfpacket.MsgSysGetUserBinary) + + // Try to get the data. + s.server.userBinaryPartsLock.RLock() + defer s.server.userBinaryPartsLock.RUnlock() + data, ok := s.server.userBinaryParts[userBinaryPartID{charID: pkt.CharID, index: pkt.BinaryType}] + resp := byteframe.NewByteFrame() + + // If we can't get the real data, use a placeholder. + if !ok { + if pkt.BinaryType == 1 { + // Stub name response with character ID + resp.WriteBytes([]byte(fmt.Sprintf("CID%d", s.charID))) + resp.WriteUint8(0) // NULL terminator. + } else if pkt.BinaryType == 2 { + data, err := base64.StdEncoding.DecodeString("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBn8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAwAAAAAAAAAAAAAABAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==") + if err != nil { + panic(err) + } + resp.WriteBytes(data) + } else if pkt.BinaryType == 3 { + data, err := base64.StdEncoding.DecodeString("AQAAA2ea5P8ATgEA/wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBn8AAAAAAAAAAAABAKAMAAAAAAAAAAAAACgAAAAAAAAAAAABAsQOAAAAAAAAAAABA6UMAAAAAAAAAAABBKAMAAAAAAAAAAABBToNAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAgACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA") + if err != nil { + panic(err) + } + resp.WriteBytes(data) + } + } else { + resp.WriteBytes(data) + } + + doAckBufSucceed(s, pkt.AckHandle, resp.Data()) +} + +func handleMsgSysNotifyUserBinary(s *Session, p mhfpacket.MHFPacket) {} + +func handleMsgMhfGetBbsUserStatus(s *Session, p mhfpacket.MHFPacket) {} diff --git a/Erupe/server/channelserver/sys_channel_server.go b/Erupe/server/channelserver/sys_channel_server.go new file mode 100644 index 000000000..ea179e1ee --- /dev/null +++ b/Erupe/server/channelserver/sys_channel_server.go @@ -0,0 +1,261 @@ +package channelserver + +import ( + "fmt" + "net" + "sync" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/config" + "github.com/Solenataris/Erupe/network/binpacket" + "github.com/Solenataris/Erupe/network/mhfpacket" + "github.com/bwmarrin/discordgo" + "github.com/jmoiron/sqlx" + "go.uber.org/zap" +) + +// Config struct allows configuring the server. +type Config struct { + Logger *zap.Logger + DB *sqlx.DB + ErupeConfig *config.Config +} + +// Map key type for a user binary part. +type userBinaryPartID struct { + charID uint32 + index uint8 +} + +// Server is a MHF channel server. +type Server struct { + sync.Mutex + logger *zap.Logger + db *sqlx.DB + erupeConfig *config.Config + acceptConns chan net.Conn + deleteConns chan net.Conn + sessions map[net.Conn]*Session + listener net.Listener // Listener that is created when Server.Start is called. + + isShuttingDown bool + + stagesLock sync.RWMutex + stages map[string]*Stage + + // UserBinary + userBinaryPartsLock sync.RWMutex + userBinaryParts map[userBinaryPartID][]byte + + // Semaphore + semaphoreLock sync.RWMutex + semaphore map[string]*Semaphore + + // Discord chat integration + discordSession *discordgo.Session +} + +// NewServer creates a new Server type. +func NewServer(config *Config) *Server { + s := &Server{ + logger: config.Logger, + db: config.DB, + erupeConfig: config.ErupeConfig, + acceptConns: make(chan net.Conn), + deleteConns: make(chan net.Conn), + sessions: make(map[net.Conn]*Session), + stages: make(map[string]*Stage), + userBinaryParts: make(map[userBinaryPartID][]byte), + semaphore: make(map[string]*Semaphore), + discordSession: nil, + } + + // Mezeporta + s.stages["sl1Ns200p0a0u0"] = NewStage("sl1Ns200p0a0u0") + + // Guild Hall LV1 + s.stages["sl1Ns202p0a0u0"] = NewStage("sl1Ns202p0a0u0") + + // Guild Hall LV2 + s.stages["sl1Ns203p0a0u0"] = NewStage("sl1Ns203p0a0u0") + + // Guild Hall LV3 + s.stages["sl1Ns204p0a0u0"] = NewStage("sl1Ns204p0a0u0") + + // Pugi Farm + s.stages["sl1Ns205p0a0u0"] = NewStage("sl1Ns205p0a0u0") + + // Rasta bar stage + s.stages["sl1Ns211p0a0u0"] = NewStage("sl1Ns211p0a0u0") + + // Carvane + s.stages["sl1Ns260p0a0u0"] = NewStage("sl1Ns260p0a0u0") + + // Gook Farm + s.stages["sl1Ns265p0a0u0"] = NewStage("sl1Ns265p0a0u0") + + // Diva fountain / prayer fountain. + s.stages["sl2Ns379p0a0u0"] = NewStage("sl2Ns379p0a0u0") + + // Diva Hall + s.stages["sl1Ns445p0a0u0"] = NewStage("sl1Ns445p0a0u0") + + // MezFes + s.stages["sl1Ns462p0a0u0"] = NewStage("sl1Ns462p0a0u0") + + // Create the discord session, (not actually connecting to discord servers yet). + if s.erupeConfig.Discord.Enabled { + ds, err := discordgo.New("Bot " + s.erupeConfig.Discord.BotToken) + if err != nil { + s.logger.Fatal("Error creating Discord session.", zap.Error(err)) + } + ds.AddHandler(s.onDiscordMessage) + s.discordSession = ds + } + + return s +} + +// Start starts the server in a new goroutine. +func (s *Server) Start(port int) error { + l, err := net.Listen("tcp", fmt.Sprintf(":%d", port)) + if err != nil { + return err + } + s.listener = l + + go s.acceptClients() + go s.manageSessions() + + // Start the discord bot for chat integration. + if s.erupeConfig.Discord.Enabled { + err = s.discordSession.Open() + if err != nil { + s.logger.Warn("Error opening Discord session.", zap.Error(err)) + return err + } + } + + return nil +} + +// Shutdown tries to shut down the server gracefully. +func (s *Server) Shutdown() { + s.Lock() + s.isShuttingDown = true + s.Unlock() + + s.listener.Close() + close(s.acceptConns) + + if s.erupeConfig.Discord.Enabled { + s.discordSession.Close() + } +} + +func (s *Server) acceptClients() { + for { + conn, err := s.listener.Accept() + if err != nil { + s.Lock() + shutdown := s.isShuttingDown + s.Unlock() + + if shutdown { + break + } else { + s.logger.Warn("Error accepting client", zap.Error(err)) + continue + } + } + s.acceptConns <- conn + } +} + +func (s *Server) manageSessions() { + for { + select { + case newConn := <-s.acceptConns: + // Gracefully handle acceptConns channel closing. + if newConn == nil { + s.Lock() + shutdown := s.isShuttingDown + s.Unlock() + + if shutdown { + return + } + } + + session := NewSession(s, newConn) + + s.Lock() + s.sessions[newConn] = session + s.Unlock() + + session.Start() + + case delConn := <-s.deleteConns: + s.Lock() + delete(s.sessions, delConn) + s.Unlock() + } + } +} + +// BroadcastMHF queues a MHFPacket to be sent to all sessions. +func (s *Server) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { + // Broadcast the data. + for _, session := range s.sessions { + if session == ignoredSession { + continue + } + + // Make the header + bf := byteframe.NewByteFrame() + bf.WriteUint16(uint16(pkt.Opcode())) + + // Build the packet onto the byteframe. + pkt.Build(bf, session.clientContext) + + // Enqueue in a non-blocking way that drops the packet if the connections send buffer channel is full. + session.QueueSendNonBlocking(bf.Data()) + } +} + +// BroadcastChatMessage broadcasts a simple chat message to all the sessions. +func (s *Server) BroadcastChatMessage(message string) { + bf := byteframe.NewByteFrame() + bf.SetLE() + msgBinChat := &binpacket.MsgBinChat{ + Unk0: 0, + Type: 5, + Flags: 0x80, + Message: message, + SenderName: "Erupe", + } + msgBinChat.Build(bf) + + s.BroadcastMHF(&mhfpacket.MsgSysCastedBinary{ + CharID: 0xFFFFFFFF, + MessageType: BinaryMessageTypeChat, + RawDataPayload: bf.Data(), + }, nil) +} + +func (s *Server) FindSessionByCharID(charID uint32) *Session { + s.stagesLock.RLock() + defer s.stagesLock.RUnlock() + for _, stage := range s.stages { + stage.RLock() + for client := range stage.clients { + if client.charID == charID { + stage.RUnlock() + return client + } + } + stage.RUnlock() + } + + return nil +} diff --git a/Erupe/server/channelserver/sys_semaphore.go b/Erupe/server/channelserver/sys_semaphore.go new file mode 100644 index 000000000..1e653cdbc --- /dev/null +++ b/Erupe/server/channelserver/sys_semaphore.go @@ -0,0 +1,29 @@ +package channelserver + +import ( + "sync" +) + +// Stage holds stage-specific information +type Semaphore struct { + sync.RWMutex + + // Stage ID string + id_semaphore string + + // Map of charID -> interface{}, only the key is used, value is always nil. + reservedClientSlots map[uint32]interface{} + + // Max Players for Semaphore + maxPlayers uint16 +} + +// NewStage creates a new stage with intialized values. +func NewSemaphore(ID string, MaxPlayers uint16) *Semaphore { + s := &Semaphore{ + id_semaphore: ID, + reservedClientSlots: make(map[uint32]interface{}), + maxPlayers: MaxPlayers, + } + return s +} diff --git a/Erupe/server/channelserver/sys_session.go b/Erupe/server/channelserver/sys_session.go new file mode 100644 index 000000000..ffb5d5e05 --- /dev/null +++ b/Erupe/server/channelserver/sys_session.go @@ -0,0 +1,208 @@ +package channelserver + +import ( + "encoding/hex" + "fmt" + "io" + "net" + "sync" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/common/stringstack" + "github.com/Solenataris/Erupe/common/stringsupport" + "github.com/Solenataris/Erupe/network" + "github.com/Solenataris/Erupe/network/clientctx" + "github.com/Solenataris/Erupe/network/mhfpacket" + "go.uber.org/zap" + "golang.org/x/text/encoding/japanese" +) + +// Session holds state for the channel server connection. +type Session struct { + sync.Mutex + logger *zap.Logger + server *Server + rawConn net.Conn + cryptConn *network.CryptConn + sendPackets chan []byte + clientContext *clientctx.ClientContext + + stageID string + stage *Stage + reservationStage *Stage // Required for the stateful MsgSysUnreserveStage packet. + charID uint32 + logKey []byte + + semaphore *Semaphore // Required for the stateful MsgSysUnreserveStage packet. + + // A stack containing the stage movement history (push on enter/move, pop on back) + stageMoveStack *stringstack.StringStack + + // Accumulated index used for identifying mail for a client + // I'm not certain why this is used, but since the client is sending it + // I want to rely on it for now as it might be important later. + mailAccIndex uint8 + // Contains the mail list that maps accumulated indexes to mail IDs + mailList []int + + // For Debuging + Name string +} + +// NewSession creates a new Session type. +func NewSession(server *Server, conn net.Conn) *Session { + s := &Session{ + logger: server.logger.Named(conn.RemoteAddr().String()), + server: server, + rawConn: conn, + cryptConn: network.NewCryptConn(conn), + sendPackets: make(chan []byte, 20), + clientContext: &clientctx.ClientContext{ + StrConv: &stringsupport.StringConverter{ + Encoding: japanese.ShiftJIS, + }, + }, + stageMoveStack: stringstack.New(), + } + return s +} + +// Start starts the session packet send and recv loop(s). +func (s *Session) Start() { + go func() { + s.logger.Info("Channel server got connection!", zap.String("remoteaddr", s.rawConn.RemoteAddr().String())) + // Unlike the sign and entrance server, + // the client DOES NOT initalize the channel connection with 8 NULL bytes. + go s.sendLoop() + s.recvLoop() + }() +} + +// QueueSend queues a packet (raw []byte) to be sent. +func (s *Session) QueueSend(data []byte) { + if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.LogOutboundMessages { + fmt.Printf("Server send to [%s]\n", s.Name) + fmt.Printf("Sent Data:\n%s\n", hex.Dump(data)) + } + s.sendPackets <- data +} + +// QueueSendNonBlocking queues a packet (raw []byte) to be sent, dropping the packet entirely if the queue is full. +func (s *Session) QueueSendNonBlocking(data []byte) { + select { + case s.sendPackets <- data: + // Enqueued properly. + default: + // Couldn't enqueue, likely something wrong with the connection. + s.logger.Warn("Dropped packet for session because of full send buffer, something is probably wrong") + } +} + +// QueueSendMHF queues a MHFPacket to be sent. +func (s *Session) QueueSendMHF(pkt mhfpacket.MHFPacket) { + // Make the header + bf := byteframe.NewByteFrame() + bf.WriteUint16(uint16(pkt.Opcode())) + + // Build the packet onto the byteframe. + pkt.Build(bf, s.clientContext) + + // Queue it. + s.QueueSend(bf.Data()) +} + +// QueueAck is a helper function to queue an MSG_SYS_ACK with the given ack handle and data. +func (s *Session) QueueAck(ackHandle uint32, data []byte) { + bf := byteframe.NewByteFrame() + bf.WriteUint16(uint16(network.MSG_SYS_ACK)) + bf.WriteUint32(ackHandle) + bf.WriteBytes(data) + s.QueueSend(bf.Data()) +} + +func (s *Session) sendLoop() { + for { + // TODO(Andoryuuta): Test making this into a buffered channel and grouping the packet together before sending. + rawPacket := <-s.sendPackets + + if rawPacket == nil { + s.logger.Debug("Got nil from s.SendPackets, exiting send loop") + return + } + + // Make a copy of the data. + terminatedPacket := make([]byte, len(rawPacket)) + copy(terminatedPacket, rawPacket) + + // Append the MSG_SYS_END tailing opcode. + terminatedPacket = append(terminatedPacket, []byte{0x00, 0x10}...) + + s.cryptConn.SendPacket(terminatedPacket) + } +} + +func (s *Session) recvLoop() { + for { + pkt, err := s.cryptConn.ReadPacket() + + if err == io.EOF { + s.logger.Info(fmt.Sprintf("[%s] Disconnected", s.Name)) + logoutPlayer(s) + return + } + if err != nil { + s.logger.Warn("Error on ReadPacket, exiting recv loop", zap.Error(err)) + logoutPlayer(s) + return + } + s.handlePacketGroup(pkt) + } +} + +func (s *Session) handlePacketGroup(pktGroup []byte) { + bf := byteframe.NewByteFrameFromBytes(pktGroup) + opcode := network.PacketID(bf.ReadUint16()) + + // This shouldn't be needed, but it's better to recover and let the connection die than to panic the server. + defer func() { + if r := recover(); r != nil { + fmt.Printf("[%s]", s.Name) + fmt.Println("Recovered from panic", r) + } + }() + + // Print any (non-common spam) packet opcodes and data. + if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.OpcodeMessages { + if opcode != network.MSG_SYS_END && + opcode != network.MSG_SYS_PING && + opcode != network.MSG_SYS_NOP && + opcode != network.MSG_SYS_TIME && + opcode != network.MSG_SYS_EXTEND_THRESHOLD { + fmt.Printf("[%s] send to Server\n", s.Name) + fmt.Printf("Opcode: %s\n", opcode) + fmt.Printf("Data [%d bytes]:\n%s\n", len(pktGroup), hex.Dump(pktGroup)) + } + } + if opcode == network.MSG_SYS_LOGOUT { + s.rawConn.Close() + } + // Get the packet parser and handler for this opcode. + mhfPkt := mhfpacket.FromOpcode(opcode) + if mhfPkt == nil { + fmt.Println("Got opcode which we don't know how to parse, can't parse anymore for this group") + return + } + // Parse the packet. + err := mhfPkt.Parse(bf, s.clientContext) + if err != nil { + fmt.Printf("\n!!! [%s] %s NOT IMPLEMENTED !!! \n\n\n", s.Name, opcode) + return + } + // Handle the packet. + handlerTable[opcode](s, mhfPkt) + // If there is more data on the stream that the .Parse method didn't read, then read another packet off it. + remainingData := bf.DataFromCurrent() + if len(remainingData) >= 2 { + s.handlePacketGroup(remainingData) + } +} diff --git a/Erupe/server/channelserver/sys_stage.go b/Erupe/server/channelserver/sys_stage.go new file mode 100644 index 000000000..9887c7e17 --- /dev/null +++ b/Erupe/server/channelserver/sys_stage.go @@ -0,0 +1,123 @@ +package channelserver + +import ( + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/network/mhfpacket" + "sync" +) + +// StageObject holds infomation about a specific stage object. +type StageObject struct { + sync.RWMutex + id uint32 + ownerCharID uint32 + x, y, z float32 +} + +type ObjectMap struct { + id uint8 + charid uint32 + status bool +} + +// stageBinaryKey is a struct used as a map key for identifying a stage binary part. +type stageBinaryKey struct { + id0 uint8 + id1 uint8 +} + +// Stage holds stage-specific information +type Stage struct { + sync.RWMutex + + // Stage ID string + id string + + // Total count of objects ever created for this stage. Used for ObjID generation. + gameObjectCount uint32 + + // Save all object in stage + objects map[uint32]*StageObject + + objectList map[uint8]*ObjectMap + // Map of session -> charID. + // These are clients that are CURRENTLY in the stage + clients map[*Session]uint32 + + // Map of charID -> interface{}, only the key is used, value is always nil. + // These are clients that aren't in the stage, but have reserved a slot (for quests, etc). + reservedClientSlots map[uint32]interface{} + + // These are raw binary blobs that the stage owner sets, + // other clients expect the server to echo them back in the exact same format. + rawBinaryData map[stageBinaryKey][]byte + + maxPlayers uint16 + hasDeparted bool + password string +} + +// NewStage creates a new stage with intialized values. +func NewStage(ID string) *Stage { + s := &Stage{ + id: ID, + clients: make(map[*Session]uint32), + reservedClientSlots: make(map[uint32]interface{}), + objects: make(map[uint32]*StageObject), + rawBinaryData: make(map[stageBinaryKey][]byte), + maxPlayers: 4, + gameObjectCount: 1, + objectList: make(map[uint8]*ObjectMap), + } + s.InitObjectList() + return s +} + +// BroadcastMHF queues a MHFPacket to be sent to all sessions in the stage. +func (s *Stage) BroadcastMHF(pkt mhfpacket.MHFPacket, ignoredSession *Session) { + // Broadcast the data. + for session := range s.clients { + if session == ignoredSession { + continue + } + + // Make the header + bf := byteframe.NewByteFrame() + bf.WriteUint16(uint16(pkt.Opcode())) + + // Build the packet onto the byteframe. + pkt.Build(bf, session.clientContext) + + // Enqueue in a non-blocking way that drops the packet if the connections send buffer channel is full. + session.QueueSendNonBlocking(bf.Data()) + } +} + +func (s *Stage) InitObjectList() { + for seq:=uint8(0x7f);seq>uint8(0);seq-- { + newObj := &ObjectMap{ + id: seq, + charid: uint32(0), + status: false, + } + s.objectList[seq] = newObj + } +} + +func (s *Stage) GetNewObjectID(CharID uint32) uint32 { + ObjId:=uint8(0) + for seq:=uint8(0x7f);seq>uint8(0);seq--{ + if s.objectList[seq].status == false { + ObjId=seq + break + } + } + s.objectList[ObjId].status=true + s.objectList[ObjId].charid=CharID + bf := byteframe.NewByteFrame() + bf.WriteUint8(uint8(0)) + bf.WriteUint8(ObjId) + bf.WriteUint16(uint16(0)) + obj :=uint32(bf.Data()[3]) | uint32(bf.Data()[2])<<8 | uint32(bf.Data()[1])<<16 | uint32(bf.Data()[0])<<32 + return obj +} \ No newline at end of file diff --git a/Erupe/server/channelserver/sys_timefix.go b/Erupe/server/channelserver/sys_timefix.go new file mode 100644 index 000000000..839382053 --- /dev/null +++ b/Erupe/server/channelserver/sys_timefix.go @@ -0,0 +1,48 @@ +package channelserver + +import ( + "fmt" + "time" +) + +var ( + Offset = 9 + YearAdjust = -7 + MonthAdjust = 0 + DayAdjust = 0 +) + +var ( + TimeStatic = time.Time{} +) + +func Time_Current() time.Time { + baseTime := time.Now().In(time.FixedZone(fmt.Sprintf("UTC+%d", Offset), Offset*60*60)) + return baseTime +} + +func Time_Current_Adjusted() time.Time { + baseTime := time.Now().In(time.FixedZone(fmt.Sprintf("UTC+%d", Offset), Offset*60*60)).AddDate(YearAdjust, MonthAdjust, DayAdjust) + return time.Date(baseTime.Year(), baseTime.Month(), baseTime.Day(), baseTime.Hour(), baseTime.Minute(), baseTime.Second(), baseTime.Nanosecond(), baseTime.Location()) +} + +func Time_Current_Midnight() time.Time { + baseTime := time.Now().In(time.FixedZone(fmt.Sprintf("UTC+%d", Offset), Offset*60*60)).AddDate(YearAdjust, MonthAdjust, DayAdjust) + return time.Date(baseTime.Year(), baseTime.Month(), baseTime.Day(), 0, 0, 0, 0, baseTime.Location()) +} + +func Time_Current_Week_uint8() uint8 { + baseTime := time.Now().In(time.FixedZone(fmt.Sprintf("UTC+%d", Offset), Offset*60*60)).AddDate(YearAdjust, MonthAdjust, DayAdjust) + + _, thisWeek := baseTime.ISOWeek() + _, beginningOfTheMonth := time.Date(baseTime.Year(), baseTime.Month(), 1, 0, 0, 0, 0, baseTime.Location()).ISOWeek() + + return uint8(1 + thisWeek - beginningOfTheMonth) +} + +func Time_static() time.Time { + if TimeStatic.IsZero() { + TimeStatic = Time_Current_Adjusted() + } + return TimeStatic +} diff --git a/Erupe/server/channelserver/timeserver/time_mode.go b/Erupe/server/channelserver/timeserver/time_mode.go new file mode 100644 index 000000000..e335b814a --- /dev/null +++ b/Erupe/server/channelserver/timeserver/time_mode.go @@ -0,0 +1,87 @@ +package timeserver + +import ( + "time" +) + +var DoOnce_midnight = false +var DoOnce_t2 = false +var DoOnce_t = false +var Fix_midnight = time.Time{} +var Fix_t2 = time.Time{} +var Fix_t = time.Time{} +var Pfixtimer time.Duration +var Pnewtime = 0 +var yearsFixed = -7 + +func PFadd_time() time.Duration { + Pnewtime = Pnewtime + 24 + Pfixtimer = time.Duration(Pnewtime) + return Pfixtimer +} + +func Time_static() time.Time { + if !DoOnce_t { + DoOnce_t = true + // Force to 201x + tFix1 := time.Now() + tFix2 := tFix1.AddDate(yearsFixed, 0, 0) + Fix_t = tFix2.In(time.FixedZone("UTC+1", 1*60*60)) + } + return Fix_t +} + +func Tstatic_midnight() time.Time { + if !DoOnce_midnight { + DoOnce_midnight = true + // Force to 201x + tFix1 := time.Now() + tFix2 := tFix1.AddDate(yearsFixed, 0, 0) + var tFix = tFix2.In(time.FixedZone("UTC+1", 1*60*60)) + yearFix, monthFix, dayFix := tFix2.Date() + Fix_midnight = time.Date(yearFix, monthFix, dayFix, 0, 0, 0, 0, tFix.Location()).Add(time.Hour) + } + return Fix_midnight +} + +func Time_midnight() time.Time { + // Force to 201x + t1 := time.Now() + t2 := t1.AddDate(yearsFixed, 0, 0) + var t = t2.In(time.FixedZone("UTC+1", 1*60*60)) + year, month, day := t2.Date() + midnight := time.Date(year, month, day, 0, 0, 0, 0, t.Location()).Add(time.Hour) + return midnight +} + +func TimeCurrent() time.Time { + // Force to 201x + t1 := time.Now() + t2 := t1.AddDate(yearsFixed, 0, 0) + var t = t2.In(time.FixedZone("UTC+1", 1*60*60)) + return t +} + +func Time_Current_Week_uint8() uint8 { + beginningOfTheMonth := time.Date(TimeCurrent().Year(), TimeCurrent().Month(), 1, 1, 1, 1, 1, time.UTC) + _, thisWeek := TimeCurrent().ISOWeek() + _, beginningWeek := beginningOfTheMonth.ISOWeek() + + return uint8(1 + thisWeek - beginningWeek) +} + +func Time_Current_Week_uint32() uint32 { + beginningOfTheMonth := time.Date(TimeCurrent().Year(), TimeCurrent().Month(), 1, 1, 1, 1, 1, time.UTC) + _, thisWeek := TimeCurrent().ISOWeek() + _, beginningWeek := beginningOfTheMonth.ISOWeek() + result := 1 + thisWeek - beginningWeek + return uint32(result) +} + +func Detect_Day() bool { + switch time.Now().Weekday() { + case time.Wednesday: + return true + } + return false +} diff --git a/Erupe/server/entranceserver/crypto.go b/Erupe/server/entranceserver/crypto.go new file mode 100644 index 000000000..20a361e7e --- /dev/null +++ b/Erupe/server/entranceserver/crypto.go @@ -0,0 +1,56 @@ +package entranceserver + +import ( + "encoding/binary" +) + +var ( + _bin8Key = []byte{0x01, 0x23, 0x34, 0x45, 0x56, 0xAB, 0xCD, 0xEF} + _sum32Table0 = []byte{0x35, 0x7A, 0xAA, 0x97, 0x53, 0x66, 0x12} + _sum32Table1 = []byte{0x7A, 0xAA, 0x97, 0x53, 0x66, 0x12, 0xDE, 0xDE, 0x35} +) + +// CalcSum32 calculates the custom MHF "sum32" checksum of the given data. +func CalcSum32(data []byte) uint32 { + tableIdx0 := int(len(data) & 0xFF) + tableIdx1 := int(data[len(data)>>1] & 0xFF) + + out := make([]byte, 4) + for i := 0; i < len(data); i++ { + tableIdx0++ + tableIdx1++ + + tmp := byte((_sum32Table1[tableIdx1%9] ^ _sum32Table0[tableIdx0%7]) ^ data[i]) + out[i&3] = (out[i&3] + tmp) & 0xFF + } + + return binary.BigEndian.Uint32(out) +} + +// EncryptBin8 encrypts the given data using MHF's "binary8" encryption. +func EncryptBin8(data []byte, key byte) []byte { + curKey := uint32(((54323 * uint(key)) + 1) & 0xFFFFFFFF) + + var output []byte + for i := 0; i < len(data); i++ { + tmp := (_bin8Key[i&7] ^ byte((curKey>>13)&0xFF)) + output = append(output, data[i]^tmp) + curKey = uint32(((54323 * uint(curKey)) + 1) & 0xFFFFFFFF) + } + + return output +} + +// DecryptBin8 decrypts the given MHF "binary8" data. +func DecryptBin8(data []byte, key byte) []byte { + curKey := uint32(((54323 * uint(key)) + 1) & 0xFFFFFFFF) + + var output []byte + for i := 0; i < len(data); i++ { + tmp := (data[i] ^ byte((curKey>>13)&0xFF)) + output = append(output, tmp^_bin8Key[i&7]) + curKey = uint32(((54323 * uint(curKey)) + 1) & 0xFFFFFFFF) + } + + return output +} diff --git a/Erupe/server/entranceserver/crypto_test.go b/Erupe/server/entranceserver/crypto_test.go new file mode 100644 index 000000000..c89baf231 --- /dev/null +++ b/Erupe/server/entranceserver/crypto_test.go @@ -0,0 +1,73 @@ +package entranceserver + +import ( + "bytes" + "encoding/hex" + "fmt" + "testing" +) + +var tests = []struct { + data []byte + sum uint32 + encryptedData []byte + encryptionKey byte +}{ + { + []byte{0x4C, 0x6F, 0x72, 0x65, 0x6D, 0x20}, + 0xAE6CA2C, + []byte{0x7E, 0x4C, 0x1D, 0x16, 0x9D, 0x46}, + 0x55, + }, + { + []byte{0x69, 0x70, 0x73, 0x75, 0x6D, 0x20, 0x64, 0x6F, 0x6C, 0x6F, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6D, 0x65, 0x74, 0x2C, 0x20}, + 0xCE5F1E96, + []byte{0x41, 0x65, 0xFF, 0x74, 0x64, 0x45, 0xB8, 0xB1, 0x18, 0xB0, 0x94, 0xA3, 0xF8, 0xD, 0xBF, 0x3C, 0xC8, 0x24, 0xE2, 0xEC, 0x3B, 0xCE}, + 0x7A, + }, + { + []byte{0x63, 0x6F, 0x6E, 0x73, 0x65, 0x63, 0x74, 0x65, 0x74, 0x75, 0x72, 0x20, 0x61, 0x64, 0x69, 0x70, 0x69, 0x73, 0x63, 0x69, 0x6E, 0x67, 0x20, 0x65, 0x6C, 0x69, 0x74, 0x2C, 0x20}, + 0xF3EECEBB, + []byte{0xE, 0xBB, 0x19, 0xA5, 0xB9, 0x34, 0xFE, 0x51, 0x0, 0x61, 0x2D, 0x38, 0xB2, 0x98, 0xC2, 0xE0, 0x17, 0xDE, 0x6E, 0xE3, 0x6C, 0x1E, 0x19, 0xB6, 0x8C, 0x57, 0x32, 0x32, 0xD8}, + 0xF8, + }, +} + +func TestSum32(t *testing.T) { + for k, test := range tests { + testname := fmt.Sprintf("sum32_test_%d", k) + t.Run(testname, func(t *testing.T) { + gotSum := CalcSum32(test.data) + + if gotSum != test.sum { + t.Errorf("got sum32 0x%X, want 0x%X", gotSum, test.sum) + } + }) + } +} + +func TestEncryptBin8(t *testing.T) { + for k, test := range tests { + testname := fmt.Sprintf("encrypt_bin8_test_%d", k) + t.Run(testname, func(t *testing.T) { + gotEncData := EncryptBin8(test.data, test.encryptionKey) + + if !bytes.Equal(gotEncData, test.encryptedData) { + t.Errorf("got\n\t%s\nwant\n\t%s", hex.Dump(gotEncData), hex.Dump(test.encryptedData)) + } + }) + } +} + +func TestDecryptBin8(t *testing.T) { + for k, test := range tests { + testname := fmt.Sprintf("decrypt_bin8_test_%d", k) + t.Run(testname, func(t *testing.T) { + gotDecData := DecryptBin8(test.encryptedData, test.encryptionKey) + + if !bytes.Equal(gotDecData, test.data) { + t.Errorf("got\n\t%s\nwant\n\t%s", hex.Dump(gotDecData), hex.Dump(test.data)) + } + }) + } +} diff --git a/Erupe/server/entranceserver/entrance_server.go b/Erupe/server/entranceserver/entrance_server.go new file mode 100644 index 000000000..1d83d3fb3 --- /dev/null +++ b/Erupe/server/entranceserver/entrance_server.go @@ -0,0 +1,122 @@ +package entranceserver + +import ( + "encoding/hex" + "fmt" + "io" + "net" + "sync" + + "github.com/Solenataris/Erupe/config" + "github.com/Solenataris/Erupe/network" + "github.com/jmoiron/sqlx" + "go.uber.org/zap" +) + +// Server is a MHF entrance server. +type Server struct { + sync.Mutex + logger *zap.Logger + erupeConfig *config.Config + db *sqlx.DB + listener net.Listener + isShuttingDown bool +} + +// Config struct allows configuring the server. +type Config struct { + Logger *zap.Logger + DB *sqlx.DB + ErupeConfig *config.Config +} + +// NewServer creates a new Server type. +func NewServer(config *Config) *Server { + s := &Server{ + logger: config.Logger, + erupeConfig: config.ErupeConfig, + db: config.DB, + } + return s +} + +// Start starts the server in a new goroutine. +func (s *Server) Start() error { + + l, err := net.Listen("tcp", fmt.Sprintf(":%d", s.erupeConfig.Entrance.Port)) + if err != nil { + return err + } + + s.listener = l + + go s.acceptClients() + + return nil +} + +// Shutdown exits the server gracefully. +func (s *Server) Shutdown() { + s.logger.Debug("Shutting down") + + s.Lock() + s.isShuttingDown = true + s.Unlock() + + // This will cause the acceptor goroutine to error and exit gracefully. + s.listener.Close() +} + +//acceptClients handles accepting new clients in a loop. +func (s *Server) acceptClients() { + for { + conn, err := s.listener.Accept() + if err != nil { + // Check if we are shutting down and exit gracefully if so. + s.Lock() + shutdown := s.isShuttingDown + s.Unlock() + + if shutdown { + break + } else { + continue + } + } + + // Start a new goroutine for the connection so that we don't block other incoming connections. + go s.handleEntranceServerConnection(conn) + } +} + +func (s *Server) handleEntranceServerConnection(conn net.Conn) { + // Client initalizes the connection with a one-time buffer of 8 NULL bytes. + nullInit := make([]byte, 8) + n, err := io.ReadFull(conn, nullInit) + if err != nil { + s.logger.Warn("Failed to read 8 NULL init", zap.Error(err)) + return + } else if n != len(nullInit) { + s.logger.Warn("io.ReadFull couldn't read the full 8 byte init.") + return + } + + // Create a new encrypted connection handler and read a packet from it. + cc := network.NewCryptConn(conn) + pkt, err := cc.ReadPacket() + if err != nil { + s.logger.Warn("Error reading packet", zap.Error(err)) + return + } + + s.logger.Debug("Got entrance server command:\n", zap.String("raw", hex.Dump(pkt))) + + data := makeSv2Resp(s.erupeConfig.Entrance.Entries, s) + if len(pkt) > 5 { + data = append(data, makeUsrResp(pkt)...) + } + cc.SendPacket(data) + // Close because we only need to send the response once. + // Any further requests from the client will come from a new connection. + conn.Close() +} diff --git a/Erupe/server/entranceserver/make_resp.go b/Erupe/server/entranceserver/make_resp.go new file mode 100644 index 000000000..de4a71eac --- /dev/null +++ b/Erupe/server/entranceserver/make_resp.go @@ -0,0 +1,131 @@ +package entranceserver + +import ( + "encoding/binary" + "net" + + "github.com/Solenataris/Erupe/common/stringsupport" + + "github.com/Andoryuuta/byteframe" + "github.com/Solenataris/Erupe/config" + "github.com/Solenataris/Erupe/server/channelserver" +) + +func paddedString(x string, size uint) []byte { + out := make([]byte, size) + copy(out, x) + + // Null terminate it. + out[len(out)-1] = 0 + return out +} + +// Server Entries +var name string +var season uint8 + +// Server Channels +var currentplayers uint16 + +func encodeServerInfo(serverInfos []config.EntranceServerInfo, s *Server) []byte { + bf := byteframe.NewByteFrame() + + for serverIdx, si := range serverInfos { + err := s.db.QueryRow("SELECT server_name FROM servers WHERE server_name=$1", si.Name).Scan(&name) + if err != nil { + _, err := s.db.Exec("INSERT INTO servers (server_name, season, current_players, event_id, event_expiration) VALUES ($1, $2, 0, 0, 0)", si.Name, si.Season) + if err != nil { + panic(err) + } + } else { + err := s.db.QueryRow("SELECT season FROM servers WHERE server_name=$1", si.Name).Scan(&season) + if err != nil { + panic(err) + } + } + bf.WriteUint32(binary.LittleEndian.Uint32(net.ParseIP(si.IP).To4())) + bf.WriteUint16(16 + uint16(serverIdx)) + bf.WriteUint16(si.Unk2) + bf.WriteUint16(uint16(len(si.Channels))) + bf.WriteUint8(si.Type) + bf.WriteUint8(season) + bf.WriteUint8(si.Unk6) + shiftjisName, err := stringsupport.ConvertUTF8ToShiftJIS(si.Name) + if err != nil { + panic(err) + } + bf.WriteBytes(paddedString(string(shiftjisName), 66)) + bf.WriteUint32(si.AllowedClientFlags) + + for channelIdx, ci := range si.Channels { + bf.WriteUint16(ci.Port) + bf.WriteUint16(16 + uint16(channelIdx)) + bf.WriteUint16(ci.MaxPlayers) + err := s.db.QueryRow("SELECT current_players FROM servers WHERE server_name=$1", si.Name).Scan(¤tplayers) + if err != nil { + panic(err) + } + bf.WriteUint16(currentplayers) + bf.WriteUint16(ci.Unk4) + bf.WriteUint16(ci.Unk5) + bf.WriteUint16(ci.Unk6) + bf.WriteUint16(ci.Unk7) + bf.WriteUint16(ci.Unk8) + bf.WriteUint16(ci.Unk9) + bf.WriteUint16(ci.Unk10) + bf.WriteUint16(ci.Unk11) + bf.WriteUint16(ci.Unk12) + bf.WriteUint16(ci.Unk13) + } + } + bf.WriteUint32(uint32(channelserver.Time_Current_Adjusted().Unix())) + bf.WriteUint32(0x0000003C) + return bf.Data() +} + +func makeHeader(data []byte, respType string, entryCount uint16, key byte) []byte { + bf := byteframe.NewByteFrame() + bf.WriteBytes([]byte(respType)) + bf.WriteUint16(entryCount) + bf.WriteUint16(uint16(len(data))) + if len(data) > 0 { + bf.WriteUint32(CalcSum32(data)) + bf.WriteBytes(data) + } + + dataToEncrypt := bf.Data() + + bf = byteframe.NewByteFrame() + bf.WriteUint8(key) + bf.WriteBytes(EncryptBin8(dataToEncrypt, key)) + return bf.Data() +} + +func makeSv2Resp(servers []config.EntranceServerInfo, s *Server) []byte { + rawServerData := encodeServerInfo(servers, s) + bf := byteframe.NewByteFrame() + bf.WriteBytes(makeHeader(rawServerData, "SV2", uint16(len(servers)), 0x00)) + return bf.Data() +} + +func makeUsrResp(pkt []byte) []byte { + // TODO(Andoryuuta): Figure out what this user data is. + // Is it for the friends list at the world selection screen? + // If so, how does it work without the entrance server connection being authenticated? + + // uint16 for number of requested ids + // uint32 for each id + // response seems to be server number starting from 10 10 00 00 for server 1 channel 1? + bf := byteframe.NewByteFrameFromBytes(pkt) + _ = bf.ReadUint32() // ALL+ + _ = bf.ReadUint8() // 0x00 + + userEntries := bf.ReadUint16() + // actual process will be reading all ids and returning real server, just returning all in server 1 for now + bf = byteframe.NewByteFrame() + for i := 0; i < int(userEntries); i++ { + bf.WriteBytes([]byte{0x10, 0x10, 0x00, 0x00}) + } + return makeHeader(bf.Data(), "USR", userEntries, 0x00) + +} diff --git a/Erupe/server/launcherserver/handler.go b/Erupe/server/launcherserver/handler.go new file mode 100644 index 000000000..d1cad4f3c --- /dev/null +++ b/Erupe/server/launcherserver/handler.go @@ -0,0 +1,20 @@ +package launcherserver + +import ( + "net/http" +) + +// ServerHandler is a handler function akin to http.Handler's ServeHTTP, +// but has an additional *Server argument. +type ServerHandler func(*Server, http.ResponseWriter, *http.Request) + +// ServerHandlerFunc is a small type that implements http.Handler and +// wraps a calling ServerHandler with a *Server argument. +type ServerHandlerFunc struct { + server *Server + f ServerHandler +} + +func (shf ServerHandlerFunc) ServeHTTP(w http.ResponseWriter, r *http.Request) { + shf.f(shf.server, w, r) +} diff --git a/Erupe/server/launcherserver/launcher_server.go b/Erupe/server/launcherserver/launcher_server.go new file mode 100644 index 000000000..fb108edaf --- /dev/null +++ b/Erupe/server/launcherserver/launcher_server.go @@ -0,0 +1,98 @@ +package launcherserver + +import ( + "context" + "fmt" + "net/http" + "os" + "sync" + "time" + + "github.com/Solenataris/Erupe/config" + "github.com/gorilla/handlers" + "github.com/gorilla/mux" + "github.com/jmoiron/sqlx" + "go.uber.org/zap" +) + +// Config struct allows configuring the server. +type Config struct { + Logger *zap.Logger + DB *sqlx.DB + ErupeConfig *config.Config + UseOriginalLauncherFiles bool +} + +// Server is the MHF launcher HTTP server. +type Server struct { + sync.Mutex + logger *zap.Logger + erupeConfig *config.Config + db *sqlx.DB + httpServer *http.Server + useOriginalLauncherFiles bool + isShuttingDown bool +} + +// NewServer creates a new Server type. +func NewServer(config *Config) *Server { + s := &Server{ + logger: config.Logger, + erupeConfig: config.ErupeConfig, + db: config.DB, + useOriginalLauncherFiles: config.UseOriginalLauncherFiles, + httpServer: &http.Server{}, + } + return s +} + +// Start starts the server in a new goroutine. +func (s *Server) Start() error { + // Set up the routes responsible for serving the launcher HTML, serverlist, unique name check, and JP auth. + r := mux.NewRouter() + + // Universal serverlist.xml route + s.setupServerlistRoutes(r) + + // Change the launcher HTML routes if we are using the custom launcher instead of the original. + if s.useOriginalLauncherFiles { + s.setupOriginalLauncherRotues(r) + } else { + s.setupCustomLauncherRotues(r) + } + + s.httpServer.Addr = fmt.Sprintf(":%d", s.erupeConfig.Launcher.Port) + s.httpServer.Handler = handlers.LoggingHandler(os.Stdout, r) + + serveError := make(chan error, 1) + go func() { + if err := s.httpServer.ListenAndServe(); err != nil { + // Send error if any. + serveError <- err + } + }() + + // Get the error from calling ListenAndServe, otherwise assume it's good after 250 milliseconds. + select { + case err := <-serveError: + return err + case <-time.After(250 * time.Millisecond): + return nil + } +} + +// Shutdown exits the server gracefully. +func (s *Server) Shutdown() { + s.logger.Debug("Shutting down") + + s.Lock() + s.isShuttingDown = true + s.Unlock() + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := s.httpServer.Shutdown(ctx); err != nil { + // Just warn because we are shutting down the server anyway. + s.logger.Warn("Got error on httpServer shutdown", zap.Error(err)) + } +} diff --git a/Erupe/server/launcherserver/routes.go b/Erupe/server/launcherserver/routes.go new file mode 100644 index 000000000..c951bf08a --- /dev/null +++ b/Erupe/server/launcherserver/routes.go @@ -0,0 +1,79 @@ +package launcherserver + +import ( + "fmt" + "html" + "net/http" + + "github.com/gorilla/mux" + //"github.com/julienschmidt/httprouter" +) + +func serverList(s *Server, w http.ResponseWriter, r *http.Request) { + fmt.Fprintf(w, + ``, + s.erupeConfig.HostIP, + s.erupeConfig.Sign.Port, + ) +} + +func serverUniqueName(w http.ResponseWriter, r *http.Request) { + // TODO(Andoryuuta): Implement checking for unique character name. + fmt.Fprintf(w, `OK`) +} + +func jpLogin(w http.ResponseWriter, r *http.Request) { + // HACK(Andoryuuta): Return the given password back as the `skey` to defer the login logic to the sign server. + resultJSON := fmt.Sprintf(`{"result": "Ok", "skey": "%s", "code": "000", "msg": ""}`, r.FormValue("pw")) + + fmt.Fprintf(w, + ` + + + + + + `, html.EscapeString(resultJSON)) + +} + +func (s *Server) setupServerlistRoutes(r *mux.Router) { + // TW + twServerList := r.Host("mhf-n.capcom.com.tw").Subrouter() + twServerList.HandleFunc("/server/unique.php", serverUniqueName) // Name checking is also done on this host. + twServerList.Handle("/server/serverlist.xml", ServerHandlerFunc{s, serverList}) + + // JP + jpServerList := r.Host("srv-mhf.capcom-networks.jp").Subrouter() + jpServerList.Handle("/serverlist.xml", ServerHandlerFunc{s, serverList}) +} + +func (s *Server) setupOriginalLauncherRotues(r *mux.Router) { + // TW + twMain := r.Host("mhfg.capcom.com.tw").Subrouter() + twMain.PathPrefix("/").Handler(http.FileServer(http.Dir("./www/tw/"))) + + // JP + jpMain := r.Host("cog-members.mhf-z.jp").Subrouter() + jpMain.PathPrefix("/").Handler(http.FileServer(http.Dir("./www/jp/"))) + + // JP Launcher does additional auth over HTTP that the TW launcher doesn't. + jpAuth := r.Host("www.capcom-onlinegames.jp").Subrouter() + jpAuth.HandleFunc("/auth/launcher/login", jpLogin) //.Methods("POST") + jpAuth.PathPrefix("/auth/").Handler(http.StripPrefix("/auth/", http.FileServer(http.Dir("./www/jp/auth/")))) + +} + +func (s *Server) setupCustomLauncherRotues(r *mux.Router) { + // TW + twMain := r.Host("mhfg.capcom.com.tw").Subrouter() + twMain.PathPrefix("/g6_launcher/").Handler(http.StripPrefix("/g6_launcher/", http.FileServer(http.Dir("./www/erupe/")))) + + // JP + jpMain := r.Host("cog-members.mhf-z.jp").Subrouter() + jpMain.PathPrefix("/launcher/").Handler(http.StripPrefix("/launcher/", http.FileServer(http.Dir("./www/erupe")))) +} diff --git a/Erupe/server/signserver/dbutils.go b/Erupe/server/signserver/dbutils.go new file mode 100644 index 000000000..5055dfdd9 --- /dev/null +++ b/Erupe/server/signserver/dbutils.go @@ -0,0 +1,66 @@ +package signserver + +import ( + "time" + + "golang.org/x/crypto/bcrypt" +) + +func (s *Server) registerDBAccount(username string, password string) error { + // Create salted hash of user password + passwordHash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) + if err != nil { + return err + } + + _, err = s.db.Exec("INSERT INTO users (username, password) VALUES ($1, $2)", username, string(passwordHash)) + if err != nil { + return err + } + + var id int + err = s.db.QueryRow("SELECT id FROM users WHERE username = $1", username).Scan(&id) + if err != nil { + return err + } + + // Create a base new character. + _, err = s.db.Exec(` + INSERT INTO characters ( + user_id, is_female, is_new_character, small_gr_level, gr_override_mode, name, unk_desc_string, + gr_override_level, gr_override_unk0, gr_override_unk1, exp, weapon, last_login) + VALUES($1, False, True, 0, True, '', '', 0, 0, 0, 0, 0, $2)`, + id, + uint32(time.Now().Unix()), + ) + if err != nil { + return err + } + + return nil +} + +type character struct { + ID uint32 `db:"id"` + IsFemale bool `db:"is_female"` + IsNewCharacter bool `db:"is_new_character"` + SmallGRLevel uint8 `db:"small_gr_level"` + GROverrideMode bool `db:"gr_override_mode"` + Name string `db:"name"` + UnkDescString string `db:"unk_desc_string"` + GROverrideLevel uint16 `db:"gr_override_level"` + GROverrideUnk0 uint8 `db:"gr_override_unk0"` + GROverrideUnk1 uint8 `db:"gr_override_unk1"` + Exp uint16 `db:"exp"` + Weapon uint16 `db:"weapon"` + LastLogin uint32 `db:"last_login"` +} + +func (s *Server) getCharactersForUser(uid int) ([]character, error) { + characters := []character{} + err := s.db.Select(&characters, "SELECT id, is_female, is_new_character, small_gr_level, gr_override_mode, name, unk_desc_string, gr_override_level, gr_override_unk0, gr_override_unk1, exp, weapon, last_login FROM characters WHERE user_id = $1", uid) + if err != nil { + return nil, err + } + return characters, nil +} \ No newline at end of file diff --git a/Erupe/server/signserver/dsgn_resp.go b/Erupe/server/signserver/dsgn_resp.go new file mode 100644 index 000000000..3980656a6 --- /dev/null +++ b/Erupe/server/signserver/dsgn_resp.go @@ -0,0 +1,105 @@ +package signserver + +import ( + "fmt" + + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" +) + +func paddedString(x string, size uint) []byte { + out := make([]byte, size) + copy(out, x) + + // Null terminate it. + out[len(out)-1] = 0 + return out +} + +func uint8PascalString(bf *byteframe.ByteFrame, x string) { + bf.WriteUint8(uint8(len(x) + 1)) + bf.WriteNullTerminatedBytes([]byte(x)) +} + +func uint16PascalString(bf *byteframe.ByteFrame, x string) { + bf.WriteUint16(uint16(len(x) + 1)) + bf.WriteNullTerminatedBytes([]byte(x)) +} + +func makeSignInFailureResp(respID RespID) []byte { + bf := byteframe.NewByteFrame() + bf.WriteUint8(uint8(respID)) + return bf.Data() +} + +func (s *Session) makeSignInResp(uid int) []byte { + // Get the characters from the DB. + chars, err := s.server.getCharactersForUser(uid) + if err != nil { + s.logger.Warn("Error getting characters from DB", zap.Error(err)) + } + + bf := byteframe.NewByteFrame() + + bf.WriteUint8(1) // resp_code + bf.WriteUint8(0) // file/patch server count + bf.WriteUint8(4) // entrance server count + bf.WriteUint8(uint8(len(chars))) // character count + bf.WriteUint32(0xFFFFFFFF) // login_token_number + bf.WriteBytes(paddedString("logintokenstrng", 16)) // login_token (16 byte padded string) + bf.WriteUint32(1576761190) + uint8PascalString(bf, fmt.Sprintf("%s:%d", s.server.erupeConfig.HostIP, s.server.erupeConfig.Entrance.Port)) + uint8PascalString(bf, "") + uint8PascalString(bf, "") + uint8PascalString(bf, "mhf-n.capcom.com.tw") + + for _, char := range chars { + bf.WriteUint32(char.ID) // character ID 469153291 + + // Exp, HR[x] is split by 0, 1, 30, 50, 99, 299, 998, 999 + if s.server.erupeConfig.DevMode && s.server.erupeConfig.DevModeOptions.MaxLauncherHR { + bf.WriteUint16(999) + } else { + bf.WriteUint16(char.Exp) + } + + bf.WriteUint16(char.Weapon) // Weapon, 0-13. + bf.WriteUint32(char.LastLogin) // Last login date, unix timestamp in seconds. + bf.WriteBool(char.IsFemale) // Sex, 0=male, 1=female. + bf.WriteBool(char.IsNewCharacter) // Is new character, 1 replaces character name with ?????. + bf.WriteUint8(char.SmallGRLevel) // GR level if grMode == 0 + bf.WriteBool(char.GROverrideMode) // GR mode. + bf.WriteBytes(paddedString(char.Name, 16)) // Character name + bf.WriteBytes(paddedString(char.UnkDescString, 32)) // unk str + if char.GROverrideMode { + bf.SetLE() + bf.WriteUint16(char.GROverrideLevel) // GR level override. + bf.SetBE() + bf.WriteUint8(char.GROverrideUnk0) // unk + bf.WriteUint8(char.GROverrideUnk1) // unk + } + } + + bf.WriteUint8(0) // friends_list_count + bf.WriteUint8(0) // guild_members_count + bf.WriteUint8(0) // notice_count + bf.WriteUint32(0xDEADBEEF) // some_last_played_character_id + bf.WriteUint32(14) // unk_flags + uint8PascalString(bf, "") // unk_data_blob PascalString + + bf.WriteUint16(51728) + bf.WriteUint16(20000) + uint16PascalString(bf, "1000672925") + + bf.WriteUint8(0) + + bf.WriteUint16(51729) + bf.WriteUint16(1) + bf.WriteUint16(20000) + uint16PascalString(bf, "203.191.249.36:8080") + + bf.WriteUint32(1578905116) + bf.WriteUint32(0) + + return bf.Data() +} diff --git a/Erupe/server/signserver/respid.go b/Erupe/server/signserver/respid.go new file mode 100644 index 000000000..47e7683d4 --- /dev/null +++ b/Erupe/server/signserver/respid.go @@ -0,0 +1,51 @@ +package signserver + +//revive:disable + +type RespID uint16 + +//go:generate stringer -type=RespID +const ( + SIGN_UNKNOWN RespID = iota + SIGN_SUCCESS + SIGN_EFAILED // Authentication server communication failed + SIGN_EILLEGAL // Incorrect input, authentication has been suspended + SIGN_EALERT // Authentication server process error + SIGN_EABORT // The internal procedure of the authentication server ended abnormally + SIGN_ERESPONSE // Procedure terminated due to abnormal certification report + SIGN_EDATABASE // Database connection failed + SIGN_EABSENCE + SIGN_ERESIGN + SIGN_ESUSPEND_D + SIGN_ELOCK + SIGN_EPASS + SIGN_ERIGHT + SIGN_EAUTH + SIGN_ESUSPEND // This account is temporarily suspended. Please contact customer service for details + SIGN_EELIMINATE // This account is permanently suspended. Please contact customer service for details + SIGN_ECLOSE + SIGN_ECLOSE_EX // Login process is congested.
Please try to sign in again later + SIGN_EINTERVAL + SIGN_EMOVED + SIGN_ENOTREADY + SIGN_EALREADY + SIGN_EIPADDR // Region block because of IP address. + SIGN_EHANGAME + SIGN_UPD_ONLY + SIGN_EMBID + SIGN_ECOGCODE + SIGN_ETOKEN + SIGN_ECOGLINK + SIGN_EMAINTE + SIGN_EMAINTE_NOUPDATE + + // Couldn't find names for the following: + UNK_32 + UNK_33 + UNK_34 + UNK_35 + + SIGN_XBRESPONSE + SIGN_EPSI + SIGN_EMBID_PSI +) diff --git a/Erupe/server/signserver/session.go b/Erupe/server/signserver/session.go new file mode 100644 index 000000000..0854d8892 --- /dev/null +++ b/Erupe/server/signserver/session.go @@ -0,0 +1,140 @@ +package signserver + +import ( + "database/sql" + "encoding/hex" + "net" + "sync" + + "github.com/Solenataris/Erupe/network" + "github.com/Andoryuuta/byteframe" + "go.uber.org/zap" + "golang.org/x/crypto/bcrypt" +) + +// Session holds state for the sign server connection. +type Session struct { + sync.Mutex + logger *zap.Logger + sid int + server *Server + rawConn *net.Conn + cryptConn *network.CryptConn +} + +func (s *Session) fail() { + s.server.Lock() + delete(s.server.sessions, s.sid) + s.server.Unlock() + +} + +func (s *Session) work() { + for { + pkt, err := s.cryptConn.ReadPacket() + if err != nil { + s.fail() + return + } + + err = s.handlePacket(pkt) + if err != nil { + s.fail() + return + } + } +} + +func (s *Session) handlePacket(pkt []byte) error { + sugar := s.logger.Sugar() + + bf := byteframe.NewByteFrameFromBytes(pkt) + reqType := string(bf.ReadNullTerminatedBytes()) + switch reqType { + case "DLTSKEYSIGN:100": + fallthrough + case "DSGN:100": + err := s.handleDSGNRequest(bf) + if err != nil { + return nil + } + case "DELETE:100": + loginTokenString := string(bf.ReadNullTerminatedBytes()) + _ = loginTokenString + characterID := bf.ReadUint32() + + sugar.Infof("Got delete request for character ID: %v\n", characterID) + sugar.Infof("remaining unknown data:\n%s\n", hex.Dump(bf.DataFromCurrent())) + default: + sugar.Infof("Got unknown request type %s, data:\n%s\n", reqType, hex.Dump(bf.DataFromCurrent())) + } + + return nil +} + +func (s *Session) handleDSGNRequest(bf *byteframe.ByteFrame) error { + + reqUsername := string(bf.ReadNullTerminatedBytes()) + reqPassword := string(bf.ReadNullTerminatedBytes()) + reqUnk := string(bf.ReadNullTerminatedBytes()) + + s.server.logger.Info( + "Got sign in request", + zap.String("reqUsername", reqUsername), + zap.String("reqPassword", reqPassword), + zap.String("reqUnk", reqUnk), + ) + + // TODO(Andoryuuta): remove plaintext password storage if this ever becomes more than a toy project. + var ( + id int + password string + ) + err := s.server.db.QueryRow("SELECT id, password FROM users WHERE username = $1", reqUsername).Scan(&id, &password) + var serverRespBytes []byte + switch { + case err == sql.ErrNoRows: + s.logger.Info("Account not found", zap.String("reqUsername", reqUsername)) + serverRespBytes = makeSignInFailureResp(SIGN_EAUTH) + + // HACK(Andoryuuta): Create a new account if it doesn't exit. + s.logger.Info("Creating account", zap.String("reqUsername", reqUsername), zap.String("reqPassword", reqPassword)) + err = s.server.registerDBAccount(reqUsername, reqPassword) + if err != nil { + s.logger.Info("Error on creating new account", zap.Error(err)) + serverRespBytes = makeSignInFailureResp(SIGN_EABORT) + break + } + + var id int + err = s.server.db.QueryRow("SELECT id FROM users WHERE username = $1", reqUsername).Scan(&id) + if err != nil { + s.logger.Info("Error on querying account id", zap.Error(err)) + serverRespBytes = makeSignInFailureResp(SIGN_EABORT) + break + } + + serverRespBytes = s.makeSignInResp(id) + break + case err != nil: + serverRespBytes = makeSignInFailureResp(SIGN_EABORT) + s.logger.Warn("Got error on SQL query", zap.Error(err)) + break + default: + if bcrypt.CompareHashAndPassword([]byte(password), []byte(reqPassword)) == nil { + s.logger.Info("Passwords match!") + serverRespBytes = s.makeSignInResp(id) + } else { + s.logger.Info("Passwords don't match!") + serverRespBytes = makeSignInFailureResp(SIGN_EPASS) + } + + } + + err = s.cryptConn.SendPacket(serverRespBytes) + if err != nil { + return err + } + + return nil +} diff --git a/Erupe/server/signserver/sign_server.go b/Erupe/server/signserver/sign_server.go new file mode 100644 index 000000000..db419cc39 --- /dev/null +++ b/Erupe/server/signserver/sign_server.go @@ -0,0 +1,119 @@ +package signserver + +import ( + "fmt" + "io" + "net" + "sync" + + "github.com/Solenataris/Erupe/config" + "github.com/Solenataris/Erupe/network" + "github.com/jmoiron/sqlx" + "go.uber.org/zap" +) + +// Config struct allows configuring the server. +type Config struct { + Logger *zap.Logger + DB *sqlx.DB + ErupeConfig *config.Config +} + +// Server is a MHF sign server. +type Server struct { + sync.Mutex + logger *zap.Logger + erupeConfig *config.Config + sid int + sessions map[int]*Session + db *sqlx.DB + listener net.Listener + isShuttingDown bool +} + +// NewServer creates a new Server type. +func NewServer(config *Config) *Server { + s := &Server{ + logger: config.Logger, + erupeConfig: config.ErupeConfig, + sid: 0, + sessions: make(map[int]*Session), + db: config.DB, + } + return s +} + +// Start starts the server in a new goroutine. +func (s *Server) Start() error { + l, err := net.Listen("tcp", fmt.Sprintf(":%d", s.erupeConfig.Sign.Port)) + if err != nil { + return err + } + s.listener = l + + go s.acceptClients() + + return nil +} + +// Shutdown exits the server gracefully. +func (s *Server) Shutdown() { + s.logger.Debug("Shutting down") + + s.Lock() + s.isShuttingDown = true + s.Unlock() + + // This will cause the acceptor goroutine to error and exit gracefully. + s.listener.Close() +} + +func (s *Server) acceptClients() { + for { + conn, err := s.listener.Accept() + if err != nil { + // Check if we are shutting down and exit gracefully if so. + s.Lock() + shutdown := s.isShuttingDown + s.Unlock() + + if shutdown { + break + } else { + panic(err) + } + } + + go s.handleConnection(s.sid, conn) + s.sid++ + } +} + +func (s *Server) handleConnection(sid int, conn net.Conn) { + s.logger.Info("Got connection to sign server", zap.String("remoteaddr", conn.RemoteAddr().String())) + + // Client initalizes the connection with a one-time buffer of 8 NULL bytes. + nullInit := make([]byte, 8) + _, err := io.ReadFull(conn, nullInit) + if err != nil { + fmt.Println(err) + conn.Close() + return + } + + // Create a new session. + session := &Session{ + logger: s.logger, + server: s, + rawConn: &conn, + cryptConn: network.NewCryptConn(conn), + } + + // Add the session to the server's sessions map. + s.Lock() + s.sessions[sid] = session + s.Unlock() + + // Do the session's work. + session.work() +} diff --git a/Erupe/www/erupe/audio/sys_confirm.mp3 b/Erupe/www/erupe/audio/sys_confirm.mp3 new file mode 100644 index 000000000..a940c4027 Binary files /dev/null and b/Erupe/www/erupe/audio/sys_confirm.mp3 differ diff --git a/Erupe/www/erupe/audio/sys_cursor.mp3 b/Erupe/www/erupe/audio/sys_cursor.mp3 new file mode 100644 index 000000000..ffab513ff Binary files /dev/null and b/Erupe/www/erupe/audio/sys_cursor.mp3 differ diff --git a/Erupe/www/erupe/audio/sys_select.mp3 b/Erupe/www/erupe/audio/sys_select.mp3 new file mode 100644 index 000000000..60a30214b Binary files /dev/null and b/Erupe/www/erupe/audio/sys_select.mp3 differ diff --git a/Erupe/www/erupe/audio/sys_starting.mp3 b/Erupe/www/erupe/audio/sys_starting.mp3 new file mode 100644 index 000000000..42cee4316 Binary files /dev/null and b/Erupe/www/erupe/audio/sys_starting.mp3 differ diff --git a/Erupe/www/erupe/charsel.html b/Erupe/www/erupe/charsel.html new file mode 100644 index 000000000..228c2157e --- /dev/null +++ b/Erupe/www/erupe/charsel.html @@ -0,0 +1,42 @@ + + + + + + + + + + MHFZZ launcher + + + + + + + + +
+
+
+
+
+
+
+
+
+ + + +
+
+ + +
+ + + + diff --git a/Erupe/www/erupe/css/charsel.css b/Erupe/www/erupe/css/charsel.css new file mode 100644 index 000000000..6939ffcf0 --- /dev/null +++ b/Erupe/www/erupe/css/charsel.css @@ -0,0 +1,281 @@ +@font-face { + font-family: 'ms-pgothic'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(./font/ms-pgothic.woff2) format('woff2'); + unicode-range: U+25ee8, U+25f23, U+25f5c, U+25fd4, U+25fe0, U+25ffb, U+2600c, U+26017, U+26060, U+260ed, U+26222, U+2626a, U+26270, U+26286, U+2634c, U+26402, U+2667e, U+266b0, U+2671d, U+268dd, U+268ea, U+26951, U+2696f, U+26999, U+269dd, U+26a1e, U+26a58, U+26a8c, U+26ab7, U+26aff, U+26c29, U+26c73, U+26c9e, U+26cdd, U+26e40, U+26e65, U+26f94, U+26ff6-26ff8, U+270f4, U+2710d, U+27139, U+273da-273db, U+273fe, U+27410, U+27449, U+27614-27615, U+27631, U+27684, U+27693, U+2770e, U+27723, U+27752, U+278b2, U+27985, U+279b4, U+27a84, U+27bb3, U+27bbe, U+27bc7, U+27c3c, U+27cb8, U+27d73, U+27da0, U+27e10, U+27eaf, U+27fb7, U+2808a, U+280bb, U+28277, U+28282, U+282f3, U+283cd, U+2840c, U+28455, U+284dc, U+2856b, U+285c8-285c9, U+286d7, U+286fa, U+28946, U+28949, U+2896b, U+28987-28988, U+289ba-289bb, U+28a1e, U+28a29, U+28a43, U+28a71, U+28a99, U+28acd, U+28add, U+28ae4, U+28bc1, U+28bef, U+28cdd, U+28d10, U+28d71, U+28dfb, U+28e0f, U+28e17, U+28e1f, U+28e36, U+28e89, U+28eeb, U+28ef6, U+28f32, U+28ff8, U+292a0, U+292b1, U+29490, U+295cf, U+2967f, U+296f0, U+29719, U+29750, U+29810, U+298c6, U+29a72, U+29d4b, U+29ddb, U+29e15, U+29e3d, U+29e49, U+29e8a, U+29ec4, U+29edb, U+29ee9, U+29fce, U+29fd7, U+2a01a, U+2a02f, U+2a082, U+2a0f9, U+2a190, U+2a2b2, U+2a38c, U+2a437, U+2a5f1, U+2a602, U+2a61a, U+2a6b2, U+2a9e6, U+2b746, U+2b751, U+2b753, U+2b75a, U+2b75c, U+2b765, U+2b776-2b777, U+2b77c, U+2b782, U+2b789, U+2b78b, U+2b78e, U+2b794, U+2b7ac, U+2b7af, U+2b7bd, U+2b7c9, U+2b7cf, U+2b7d2, U+2b7d8, U+2b7f0, U+2b80d, U+2b817, U+2b81a, U+2d544, U+2e278, U+2e569, U+2e6ea, U+2f804, U+2f80f, U+2f815, U+2f818, U+2f81a, U+2f822, U+2f828, U+2f82c, U+2f833, U+2f83f, U+2f846, U+2f852, U+2f862, U+2f86d, U+2f873, U+2f877, U+2f884, U+2f899-2f89a, U+2f8a6, U+2f8ac, U+2f8b2, U+2f8b6, U+2f8d3, U+2f8db-2f8dc, U+2f8e1, U+2f8e5, U+2f8ea, U+2f8ed, U+2f8fc, U+2f903, U+2f90b, U+2f90f, U+2f91a, U+2f920-2f921, U+2f945, U+2f947, U+2f96c, U+2f995, U+2f9d0, U+2f9de-2f9df, U+2f9f4; +} + +body { +background-color: rgba(0, 0, 0, 0); +} + +html,body { + height: 100%; + overflow:hidden; +} + +.Name_Player { + position: relative; + bottom: 11px; + text-align: center; + width: 100%; +} + +.h1, h1 { + font-size: 30px; +} + +.list-group-item.active { + z-index: 2; + color: rgba(255,255,255,1); + background-color: rgba(0,0,0,0); + border-color: rgba(0,0,0,0); +} + +#icon_weapon { + position: relative; + top:1px; + left: 10px; + width: 48px; + height: 48px; +} + +#weapon_title { + position: relative; + left: 70px; + bottom: 46px; + width: 130px; + font-weight: bold; + font-size: 16px; +} + +#weapon_name { + text-align: center; + position: relative; + left: 66px; + bottom: 50px; + width: 130px; + font-size: 16px; + font-weight: bold; +} + +#hr_lvl { + position: relative; + bottom: 97px; + left: 225px; + width: 50px; +} + +#gr_lvl { + position: relative; + bottom: 116.5px; + left: 270px; + width: 50px; +} + +#sex{ + position: relative; + bottom: 136px; + left: 315px; + width: 14px; +} + +#uid { + position: relative; + bottom: 140px; + left: 225px; + width: 135px; +} + +#lastlogin { + display: block; + width: 200px; + position: relative; + bottom: 145px; + left: 225px; +} + +.Info { + position: relative; + bottom: 10px; + right: 8px; + width: 377px; + height: 49px; + font-size:13px; +} + +#BlockNull{ + height:50px; +} + +.char-select-list { + display:block; + margin-left: 61px; + width: 25em; + height: 100px; + overflow-y: hidden; +} + +.char-list-entry { +background-image: url(../ressources/bt_charsel.jpg); + overflow: hidden!important; + background-color: rgba(0,0,0,0); + Height: 100px; + width: 398px; +} + +input[readonly] { + pointer-events: none; +} + +:-ms-input-placeholder.form-control { + color: rgba(255,255,255,0.9); +} + +input, select, textarea{ + color: #ff0000; +} + +.btn-primary{ + color: #fff; + border-color: rgba(0,0,0,0)!important;; + background-color: rgba(0,0,0,0)!important; + box-shadow:0px 0px 0px rgba(0,0,0,0)!important; + height: 100%; + width: 100%; +} + +.btn-primary.focus, .btn-primary:focus{ + color: #fff; + border-color: rgba(0,0,0,0); + background-color: rgba(0,0,0,0); + height: 100%; + width: 100%; + box-shadow:0px 0px 0px rgba(0,0,0,0); +} + +.btn-primary:active{ + background-color: rgba(0,0,0,0); +} + +.btn-primary:hover { + color: #fff; + border-color: rgba(0,0,0,0); + background-color: rgba(0,0,0,0); + height: 100%; + width: 100%; +} + +#bt_confirm { + background: url(../ressources/bt_launch.png) no-repeat scroll 0 0 transparent; + position: relative; + top: 10px; + left: 102px; + color: rgba(200,200,200,1); + cursor: pointer; + font-weight: bold; + height: 74px; + width: 308px; +} + +#bt_confirm:hover{ +background: url(../ressources/bt_launch_hover.png) no-repeat scroll 0 0 transparent; + position: relative; + top: 10px; + left: 102px; + color: rgba(255,255,255,1); + cursor: pointer; + font-weight: bold; + height: 74px; + width: 308px; +} + +#bt_new_char { + background: url(../ressources/bt_sub.png) no-repeat scroll 0 0 transparent; + background-size: 167px 33px; + position: relative; + top: 6px; + right: 81px; + color: rgba(200,200,200,1); + cursor: pointer; + font-size: 11px; + height: 33px; + width: 167px; +} + +#bt_new_char:hover{ +background: url(../ressources/bt_sub_hover.png) no-repeat scroll 0 0 transparent; + background-size: 167px 33px; + position: relative; + top: 6px; + right: 81px; + color: rgba(255,255,255,1); + cursor: pointer; + font-size: 11px; + height: 33px; + width: 167px; +} + +#bt_delete_char { + background: url(../ressources/bt_sub.png) no-repeat scroll 0 0 transparent; + background-size: 167px 33px; + position: relative; + top: 6px; + left: 262px; + color: rgba(200,200,200,1); + cursor: pointer; + font-size: 11px; + height: 33px; + width: 167px; +} + +#bt_delete_char:hover{ + background: url(../ressources/bt_sub_hover.png) no-repeat scroll 0 0 transparent; + background-size: 167px 33px; + position: relative; + top: 6px; + left: 262px; + color: rgba(255,255,255,1); + cursor: pointer; + font-size: 11px; + height: 33px; + width: 167px; +} + +#bt_up_char_list { + background: url(../ressources/bt_up_charsel.png) no-repeat scroll 0 0 transparent; + position: absolute; + top: 0px; + left: 232px; + width: 91px; + height: 25px; +} + +#bt_up_char_list:hover { + background: url(../ressources/bt_up_charsel_hover.png) no-repeat scroll 0 0 transparent; + position: absolute; + top: 0px; + left: 232px; + width: 91px; + height: 25px; +} + +#bt_down_char_list { + background: url(../ressources/bt_down_charsel.png) no-repeat scroll 0 0 transparent; + position: absolute; + top: 133px; + left: 230px; + width: 91px; + height: 25px; +} + +#bt_down_char_list:hover { + background: url(../ressources/bt_down_charsel_hover.png) no-repeat scroll 0 0 transparent; + position: absolute; + top: 133px; + left: 230px; + width: 91px; + height: 25px; +} \ No newline at end of file diff --git a/Erupe/www/erupe/css/dependencies/.DS_Store b/Erupe/www/erupe/css/dependencies/.DS_Store new file mode 100644 index 000000000..3cbbb78ab Binary files /dev/null and b/Erupe/www/erupe/css/dependencies/.DS_Store differ diff --git a/Erupe/www/erupe/css/dependencies/bootstrap-grid.css b/Erupe/www/erupe/css/dependencies/bootstrap-grid.css new file mode 100644 index 000000000..a36cd328d --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap-grid.css @@ -0,0 +1,1912 @@ +/*! + * Bootstrap Grid v4.1.3 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +@-ms-viewport { + width: device-width; +} + +html { + box-sizing: border-box; + -ms-overflow-style: scrollbar; +} + +*, +*::before, +*::after { + box-sizing: inherit; +} + +.container { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1140px; + } +} + +.container-fluid { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +.row { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -15px; + margin-left: -15px; +} + +.no-gutters { + margin-right: 0; + margin-left: 0; +} + +.no-gutters > .col, +.no-gutters > [class*="col-"] { + padding-right: 0; + padding-left: 0; +} + +.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, +.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, +.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, +.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, +.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, +.col-xl-auto { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} + +.col { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; +} + +.col-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; +} + +.col-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; +} + +.col-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; +} + +.col-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; +} + +.col-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; +} + +.col-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; +} + +.col-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; +} + +.col-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; +} + +.col-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; +} + +.col-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; +} + +.col-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; +} + +.col-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; +} + +.col-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; +} + +.order-first { + -ms-flex-order: -1; + order: -1; +} + +.order-last { + -ms-flex-order: 13; + order: 13; +} + +.order-0 { + -ms-flex-order: 0; + order: 0; +} + +.order-1 { + -ms-flex-order: 1; + order: 1; +} + +.order-2 { + -ms-flex-order: 2; + order: 2; +} + +.order-3 { + -ms-flex-order: 3; + order: 3; +} + +.order-4 { + -ms-flex-order: 4; + order: 4; +} + +.order-5 { + -ms-flex-order: 5; + order: 5; +} + +.order-6 { + -ms-flex-order: 6; + order: 6; +} + +.order-7 { + -ms-flex-order: 7; + order: 7; +} + +.order-8 { + -ms-flex-order: 8; + order: 8; +} + +.order-9 { + -ms-flex-order: 9; + order: 9; +} + +.order-10 { + -ms-flex-order: 10; + order: 10; +} + +.order-11 { + -ms-flex-order: 11; + order: 11; +} + +.order-12 { + -ms-flex-order: 12; + order: 12; +} + +.offset-1 { + margin-left: 8.333333%; +} + +.offset-2 { + margin-left: 16.666667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.333333%; +} + +.offset-5 { + margin-left: 41.666667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.333333%; +} + +.offset-8 { + margin-left: 66.666667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.333333%; +} + +.offset-11 { + margin-left: 91.666667%; +} + +@media (min-width: 576px) { + .col-sm { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-sm-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-sm-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-sm-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-sm-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-sm-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-sm-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-sm-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-sm-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-sm-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-sm-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-sm-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-sm-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-sm-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-sm-first { + -ms-flex-order: -1; + order: -1; + } + .order-sm-last { + -ms-flex-order: 13; + order: 13; + } + .order-sm-0 { + -ms-flex-order: 0; + order: 0; + } + .order-sm-1 { + -ms-flex-order: 1; + order: 1; + } + .order-sm-2 { + -ms-flex-order: 2; + order: 2; + } + .order-sm-3 { + -ms-flex-order: 3; + order: 3; + } + .order-sm-4 { + -ms-flex-order: 4; + order: 4; + } + .order-sm-5 { + -ms-flex-order: 5; + order: 5; + } + .order-sm-6 { + -ms-flex-order: 6; + order: 6; + } + .order-sm-7 { + -ms-flex-order: 7; + order: 7; + } + .order-sm-8 { + -ms-flex-order: 8; + order: 8; + } + .order-sm-9 { + -ms-flex-order: 9; + order: 9; + } + .order-sm-10 { + -ms-flex-order: 10; + order: 10; + } + .order-sm-11 { + -ms-flex-order: 11; + order: 11; + } + .order-sm-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-sm-0 { + margin-left: 0; + } + .offset-sm-1 { + margin-left: 8.333333%; + } + .offset-sm-2 { + margin-left: 16.666667%; + } + .offset-sm-3 { + margin-left: 25%; + } + .offset-sm-4 { + margin-left: 33.333333%; + } + .offset-sm-5 { + margin-left: 41.666667%; + } + .offset-sm-6 { + margin-left: 50%; + } + .offset-sm-7 { + margin-left: 58.333333%; + } + .offset-sm-8 { + margin-left: 66.666667%; + } + .offset-sm-9 { + margin-left: 75%; + } + .offset-sm-10 { + margin-left: 83.333333%; + } + .offset-sm-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 768px) { + .col-md { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-md-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-md-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-md-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-md-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-md-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-md-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-md-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-md-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-md-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-md-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-md-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-md-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-md-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-md-first { + -ms-flex-order: -1; + order: -1; + } + .order-md-last { + -ms-flex-order: 13; + order: 13; + } + .order-md-0 { + -ms-flex-order: 0; + order: 0; + } + .order-md-1 { + -ms-flex-order: 1; + order: 1; + } + .order-md-2 { + -ms-flex-order: 2; + order: 2; + } + .order-md-3 { + -ms-flex-order: 3; + order: 3; + } + .order-md-4 { + -ms-flex-order: 4; + order: 4; + } + .order-md-5 { + -ms-flex-order: 5; + order: 5; + } + .order-md-6 { + -ms-flex-order: 6; + order: 6; + } + .order-md-7 { + -ms-flex-order: 7; + order: 7; + } + .order-md-8 { + -ms-flex-order: 8; + order: 8; + } + .order-md-9 { + -ms-flex-order: 9; + order: 9; + } + .order-md-10 { + -ms-flex-order: 10; + order: 10; + } + .order-md-11 { + -ms-flex-order: 11; + order: 11; + } + .order-md-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-md-0 { + margin-left: 0; + } + .offset-md-1 { + margin-left: 8.333333%; + } + .offset-md-2 { + margin-left: 16.666667%; + } + .offset-md-3 { + margin-left: 25%; + } + .offset-md-4 { + margin-left: 33.333333%; + } + .offset-md-5 { + margin-left: 41.666667%; + } + .offset-md-6 { + margin-left: 50%; + } + .offset-md-7 { + margin-left: 58.333333%; + } + .offset-md-8 { + margin-left: 66.666667%; + } + .offset-md-9 { + margin-left: 75%; + } + .offset-md-10 { + margin-left: 83.333333%; + } + .offset-md-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 992px) { + .col-lg { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-lg-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-lg-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-lg-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-lg-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-lg-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-lg-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-lg-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-lg-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-lg-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-lg-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-lg-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-lg-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-lg-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-lg-first { + -ms-flex-order: -1; + order: -1; + } + .order-lg-last { + -ms-flex-order: 13; + order: 13; + } + .order-lg-0 { + -ms-flex-order: 0; + order: 0; + } + .order-lg-1 { + -ms-flex-order: 1; + order: 1; + } + .order-lg-2 { + -ms-flex-order: 2; + order: 2; + } + .order-lg-3 { + -ms-flex-order: 3; + order: 3; + } + .order-lg-4 { + -ms-flex-order: 4; + order: 4; + } + .order-lg-5 { + -ms-flex-order: 5; + order: 5; + } + .order-lg-6 { + -ms-flex-order: 6; + order: 6; + } + .order-lg-7 { + -ms-flex-order: 7; + order: 7; + } + .order-lg-8 { + -ms-flex-order: 8; + order: 8; + } + .order-lg-9 { + -ms-flex-order: 9; + order: 9; + } + .order-lg-10 { + -ms-flex-order: 10; + order: 10; + } + .order-lg-11 { + -ms-flex-order: 11; + order: 11; + } + .order-lg-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-lg-0 { + margin-left: 0; + } + .offset-lg-1 { + margin-left: 8.333333%; + } + .offset-lg-2 { + margin-left: 16.666667%; + } + .offset-lg-3 { + margin-left: 25%; + } + .offset-lg-4 { + margin-left: 33.333333%; + } + .offset-lg-5 { + margin-left: 41.666667%; + } + .offset-lg-6 { + margin-left: 50%; + } + .offset-lg-7 { + margin-left: 58.333333%; + } + .offset-lg-8 { + margin-left: 66.666667%; + } + .offset-lg-9 { + margin-left: 75%; + } + .offset-lg-10 { + margin-left: 83.333333%; + } + .offset-lg-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 1200px) { + .col-xl { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-xl-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-xl-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-xl-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-xl-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-xl-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-xl-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-xl-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-xl-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-xl-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-xl-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-xl-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-xl-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-xl-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-xl-first { + -ms-flex-order: -1; + order: -1; + } + .order-xl-last { + -ms-flex-order: 13; + order: 13; + } + .order-xl-0 { + -ms-flex-order: 0; + order: 0; + } + .order-xl-1 { + -ms-flex-order: 1; + order: 1; + } + .order-xl-2 { + -ms-flex-order: 2; + order: 2; + } + .order-xl-3 { + -ms-flex-order: 3; + order: 3; + } + .order-xl-4 { + -ms-flex-order: 4; + order: 4; + } + .order-xl-5 { + -ms-flex-order: 5; + order: 5; + } + .order-xl-6 { + -ms-flex-order: 6; + order: 6; + } + .order-xl-7 { + -ms-flex-order: 7; + order: 7; + } + .order-xl-8 { + -ms-flex-order: 8; + order: 8; + } + .order-xl-9 { + -ms-flex-order: 9; + order: 9; + } + .order-xl-10 { + -ms-flex-order: 10; + order: 10; + } + .order-xl-11 { + -ms-flex-order: 11; + order: 11; + } + .order-xl-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-xl-0 { + margin-left: 0; + } + .offset-xl-1 { + margin-left: 8.333333%; + } + .offset-xl-2 { + margin-left: 16.666667%; + } + .offset-xl-3 { + margin-left: 25%; + } + .offset-xl-4 { + margin-left: 33.333333%; + } + .offset-xl-5 { + margin-left: 41.666667%; + } + .offset-xl-6 { + margin-left: 50%; + } + .offset-xl-7 { + margin-left: 58.333333%; + } + .offset-xl-8 { + margin-left: 66.666667%; + } + .offset-xl-9 { + margin-left: 75%; + } + .offset-xl-10 { + margin-left: 83.333333%; + } + .offset-xl-11 { + margin-left: 91.666667%; + } +} + +.d-none { + display: none !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: -ms-flexbox !important; + display: flex !important; +} + +.d-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; +} + +@media (min-width: 576px) { + .d-sm-none { + display: none !important; + } + .d-sm-inline { + display: inline !important; + } + .d-sm-inline-block { + display: inline-block !important; + } + .d-sm-block { + display: block !important; + } + .d-sm-table { + display: table !important; + } + .d-sm-table-row { + display: table-row !important; + } + .d-sm-table-cell { + display: table-cell !important; + } + .d-sm-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-sm-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 768px) { + .d-md-none { + display: none !important; + } + .d-md-inline { + display: inline !important; + } + .d-md-inline-block { + display: inline-block !important; + } + .d-md-block { + display: block !important; + } + .d-md-table { + display: table !important; + } + .d-md-table-row { + display: table-row !important; + } + .d-md-table-cell { + display: table-cell !important; + } + .d-md-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-md-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 992px) { + .d-lg-none { + display: none !important; + } + .d-lg-inline { + display: inline !important; + } + .d-lg-inline-block { + display: inline-block !important; + } + .d-lg-block { + display: block !important; + } + .d-lg-table { + display: table !important; + } + .d-lg-table-row { + display: table-row !important; + } + .d-lg-table-cell { + display: table-cell !important; + } + .d-lg-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-lg-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 1200px) { + .d-xl-none { + display: none !important; + } + .d-xl-inline { + display: inline !important; + } + .d-xl-inline-block { + display: inline-block !important; + } + .d-xl-block { + display: block !important; + } + .d-xl-table { + display: table !important; + } + .d-xl-table-row { + display: table-row !important; + } + .d-xl-table-cell { + display: table-cell !important; + } + .d-xl-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-xl-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media print { + .d-print-none { + display: none !important; + } + .d-print-inline { + display: inline !important; + } + .d-print-inline-block { + display: inline-block !important; + } + .d-print-block { + display: block !important; + } + .d-print-table { + display: table !important; + } + .d-print-table-row { + display: table-row !important; + } + .d-print-table-cell { + display: table-cell !important; + } + .d-print-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-print-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +.flex-row { + -ms-flex-direction: row !important; + flex-direction: row !important; +} + +.flex-column { + -ms-flex-direction: column !important; + flex-direction: column !important; +} + +.flex-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; +} + +.flex-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; +} + +.flex-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; +} + +.flex-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; +} + +.flex-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; +} + +.flex-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; +} + +.flex-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; +} + +.flex-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; +} + +.justify-content-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; +} + +.justify-content-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; +} + +.justify-content-center { + -ms-flex-pack: center !important; + justify-content: center !important; +} + +.justify-content-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; +} + +.justify-content-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; +} + +.align-items-start { + -ms-flex-align: start !important; + align-items: flex-start !important; +} + +.align-items-end { + -ms-flex-align: end !important; + align-items: flex-end !important; +} + +.align-items-center { + -ms-flex-align: center !important; + align-items: center !important; +} + +.align-items-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; +} + +.align-items-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; +} + +.align-content-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; +} + +.align-content-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; +} + +.align-content-center { + -ms-flex-line-pack: center !important; + align-content: center !important; +} + +.align-content-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; +} + +.align-content-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; +} + +.align-content-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; +} + +.align-self-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; +} + +.align-self-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; +} + +.align-self-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; +} + +.align-self-center { + -ms-flex-item-align: center !important; + align-self: center !important; +} + +.align-self-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; +} + +.align-self-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; +} + +@media (min-width: 576px) { + .flex-sm-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-sm-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-sm-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-sm-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-sm-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-sm-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-sm-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-sm-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-sm-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-sm-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-sm-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-sm-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-sm-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-sm-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-sm-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-sm-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-sm-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-sm-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-sm-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-sm-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-sm-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-sm-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-sm-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-sm-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-sm-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-sm-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-sm-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-sm-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-sm-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-sm-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-sm-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-sm-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-sm-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-sm-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 768px) { + .flex-md-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-md-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-md-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-md-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-md-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-md-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-md-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-md-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-md-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-md-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-md-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-md-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-md-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-md-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-md-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-md-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-md-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-md-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-md-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-md-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-md-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-md-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-md-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-md-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-md-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-md-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-md-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-md-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-md-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-md-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-md-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-md-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-md-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-md-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 992px) { + .flex-lg-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-lg-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-lg-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-lg-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-lg-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-lg-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-lg-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-lg-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-lg-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-lg-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-lg-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-lg-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-lg-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-lg-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-lg-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-lg-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-lg-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-lg-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-lg-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-lg-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-lg-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-lg-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-lg-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-lg-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-lg-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-lg-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-lg-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-lg-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-lg-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-lg-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-lg-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-lg-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-lg-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-lg-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 1200px) { + .flex-xl-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-xl-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-xl-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-xl-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-xl-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-xl-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-xl-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-xl-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-xl-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-xl-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-xl-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-xl-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-xl-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-xl-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-xl-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-xl-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-xl-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-xl-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-xl-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-xl-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-xl-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-xl-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-xl-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-xl-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-xl-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-xl-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-xl-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-xl-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-xl-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-xl-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-xl-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-xl-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-xl-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-xl-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} +/*# sourceMappingURL=bootstrap-grid.css.map */ \ No newline at end of file diff --git a/Erupe/www/erupe/css/dependencies/bootstrap-grid.css.map b/Erupe/www/erupe/css/dependencies/bootstrap-grid.css.map new file mode 100644 index 000000000..a636ccee5 --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap-grid.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-grid.scss","bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/_variables.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGD;EAAgB,oBAAmB;CCApC;;ADGD;EACE,uBAAsB;EACtB,8BAA6B;CAC9B;;AAED;;;EAGE,oBAAmB;CACpB;;AEfC;ECAA,YAAW;EACX,oBAAuC;EACvC,mBAAsC;EACtC,mBAAkB;EAClB,kBAAiB;CDDhB;;AEoDC;EFvDF;ICYI,iBEwLK;GHjMR;CDyBF;;AG2BG;EFvDF;ICYI,iBEyLK;GHlMR;CD+BF;;AGqBG;EFvDF;ICYI,iBE0LK;GHnMR;CDqCF;;AGeG;EFvDF;ICYI,kBE2LM;GHpMT;CD2CF;;AClCC;ECZA,YAAW;EACX,oBAAuC;EACvC,mBAAsC;EACtC,mBAAkB;EAClB,kBAAiB;CDUhB;;AAQD;ECJA,qBAAa;EAAb,cAAa;EACb,oBAAe;EAAf,gBAAe;EACf,oBAAuC;EACvC,mBAAsC;CDGrC;;AAID;EACE,gBAAe;EACf,eAAc;CAOf;;AATD;;EAMI,iBAAgB;EAChB,gBAAe;CAChB;;AIlCH;;;;;;EACE,mBAAkB;EAClB,YAAW;EACX,gBAAe;EACf,oBAA4B;EAC5B,mBAA2B;CAC5B;;AAkBG;EACE,2BAAa;EAAb,cAAa;EACb,qBAAY;EAAZ,aAAY;EACZ,gBAAe;CAChB;;AACD;EACE,mBAAc;EAAd,eAAc;EACd,YAAW;EACX,gBAAe;CAChB;;AAGC;EHFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;CGAhC;;AAFD;EHFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CGAhC;;AAFD;EHFN,kBAAsC;EAAtC,cAAsC;EAItC,eAAuC;CGAhC;;AAFD;EHFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CGAhC;;AAFD;EHFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CGAhC;;AAFD;EHFN,kBAAsC;EAAtC,cAAsC;EAItC,eAAuC;CGAhC;;AAFD;EHFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CGAhC;;AAFD;EHFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CGAhC;;AAFD;EHFN,kBAAsC;EAAtC,cAAsC;EAItC,eAAuC;CGAhC;;AAFD;EHFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CGAhC;;AAFD;EHFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CGAhC;;AAFD;EHFN,mBAAsC;EAAtC,eAAsC;EAItC,gBAAuC;CGAhC;;AAGH;EAAwB,mBAAS;EAAT,UAAS;CAAI;;AAErC;EAAuB,mBDoKG;ECpKH,UDoKG;CCpKoB;;AAG5C;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,mBADZ;EACY,UADZ;CACyB;;AAArC;EAAwB,mBADZ;EACY,UADZ;CACyB;;AAArC;EAAwB,mBADZ;EACY,UADZ;CACyB;;AAMnC;EHTR,uBAA8C;CGWrC;;AAFD;EHTR,wBAA8C;CGWrC;;AAFD;EHTR,iBAA8C;CGWrC;;AAFD;EHTR,wBAA8C;CGWrC;;AAFD;EHTR,wBAA8C;CGWrC;;AAFD;EHTR,iBAA8C;CGWrC;;AAFD;EHTR,wBAA8C;CGWrC;;AAFD;EHTR,wBAA8C;CGWrC;;AAFD;EHTR,iBAA8C;CGWrC;;AAFD;EHTR,wBAA8C;CGWrC;;AAFD;EHTR,wBAA8C;CGWrC;;AFDP;EE7BE;IACE,2BAAa;IAAb,cAAa;IACb,qBAAY;IAAZ,aAAY;IACZ,gBAAe;GAChB;EACD;IACE,mBAAc;IAAd,eAAc;IACd,YAAW;IACX,gBAAe;GAChB;EAGC;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,mBAAsC;IAAtC,eAAsC;IAItC,gBAAuC;GGAhC;EAGH;IAAwB,mBAAS;IAAT,UAAS;GAAI;EAErC;IAAuB,mBDoKG;ICpKH,UDoKG;GCpKoB;EAG5C;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAMnC;IHTR,eAA4B;GGWnB;EAFD;IHTR,uBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;CL2VV;;AG5VG;EE7BE;IACE,2BAAa;IAAb,cAAa;IACb,qBAAY;IAAZ,aAAY;IACZ,gBAAe;GAChB;EACD;IACE,mBAAc;IAAd,eAAc;IACd,YAAW;IACX,gBAAe;GAChB;EAGC;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,mBAAsC;IAAtC,eAAsC;IAItC,gBAAuC;GGAhC;EAGH;IAAwB,mBAAS;IAAT,UAAS;GAAI;EAErC;IAAuB,mBDoKG;ICpKH,UDoKG;GCpKoB;EAG5C;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAMnC;IHTR,eAA4B;GGWnB;EAFD;IHTR,uBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;CLyeV;;AG1eG;EE7BE;IACE,2BAAa;IAAb,cAAa;IACb,qBAAY;IAAZ,aAAY;IACZ,gBAAe;GAChB;EACD;IACE,mBAAc;IAAd,eAAc;IACd,YAAW;IACX,gBAAe;GAChB;EAGC;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,mBAAsC;IAAtC,eAAsC;IAItC,gBAAuC;GGAhC;EAGH;IAAwB,mBAAS;IAAT,UAAS;GAAI;EAErC;IAAuB,mBDoKG;ICpKH,UDoKG;GCpKoB;EAG5C;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAMnC;IHTR,eAA4B;GGWnB;EAFD;IHTR,uBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;CLunBV;;AGxnBG;EE7BE;IACE,2BAAa;IAAb,cAAa;IACb,qBAAY;IAAZ,aAAY;IACZ,gBAAe;GAChB;EACD;IACE,mBAAc;IAAd,eAAc;IACd,YAAW;IACX,gBAAe;GAChB;EAGC;IHFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GGAhC;EAFD;IHFN,mBAAsC;IAAtC,eAAsC;IAItC,gBAAuC;GGAhC;EAGH;IAAwB,mBAAS;IAAT,UAAS;GAAI;EAErC;IAAuB,mBDoKG;ICpKH,UDoKG;GCpKoB;EAG5C;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAMnC;IHTR,eAA4B;GGWnB;EAFD;IHTR,uBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,iBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;EAFD;IHTR,wBAA8C;GGWrC;CLqwBV;;AMxzBG;EAA2B,yBAAwB;CAAI;;AACvD;EAA2B,2BAA0B;CAAI;;AACzD;EAA2B,iCAAgC;CAAI;;AAC/D;EAA2B,0BAAyB;CAAI;;AACxD;EAA2B,0BAAyB;CAAI;;AACxD;EAA2B,8BAA6B;CAAI;;AAC5D;EAA2B,+BAA8B;CAAI;;AAC7D;EAA2B,gCAAwB;EAAxB,yBAAwB;CAAI;;AACvD;EAA2B,uCAA+B;EAA/B,gCAA+B;CAAI;;AH0C9D;EGlDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CNk3BjE;;AGx0BG;EGlDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CNg5BjE;;AGt2BG;EGlDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CN86BjE;;AGp4BG;EGlDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CN48BjE;;AMn8BD;EACE;IAAwB,yBAAwB;GAAI;EACpD;IAAwB,2BAA0B;GAAI;EACtD;IAAwB,iCAAgC;GAAI;EAC5D;IAAwB,0BAAyB;GAAI;EACrD;IAAwB,0BAAyB;GAAI;EACrD;IAAwB,8BAA6B;GAAI;EACzD;IAAwB,+BAA8B;GAAI;EAC1D;IAAwB,gCAAwB;IAAxB,yBAAwB;GAAI;EACpD;IAAwB,uCAA+B;IAA/B,gCAA+B;GAAI;CNw9B5D;;AOl/BG;EAAgC,mCAA8B;EAA9B,+BAA8B;CAAI;;AAClE;EAAgC,sCAAiC;EAAjC,kCAAiC;CAAI;;AACrE;EAAgC,2CAAsC;EAAtC,uCAAsC;CAAI;;AAC1E;EAAgC,8CAAyC;EAAzC,0CAAyC;CAAI;;AAE7E;EAA8B,+BAA0B;EAA1B,2BAA0B;CAAI;;AAC5D;EAA8B,iCAA4B;EAA5B,6BAA4B;CAAI;;AAC9D;EAA8B,uCAAkC;EAAlC,mCAAkC;CAAI;;AACpE;EAA8B,8BAAyB;EAAzB,0BAAyB;CAAI;;AAC3D;EAA8B,gCAAuB;EAAvB,wBAAuB;CAAI;;AACzD;EAA8B,gCAAuB;EAAvB,wBAAuB;CAAI;;AACzD;EAA8B,gCAAyB;EAAzB,0BAAyB;CAAI;;AAC3D;EAA8B,gCAAyB;EAAzB,0BAAyB;CAAI;;AAE3D;EAAoC,gCAAsC;EAAtC,uCAAsC;CAAI;;AAC9E;EAAoC,8BAAoC;EAApC,qCAAoC;CAAI;;AAC5E;EAAoC,iCAAkC;EAAlC,mCAAkC;CAAI;;AAC1E;EAAoC,kCAAyC;EAAzC,0CAAyC;CAAI;;AACjF;EAAoC,qCAAwC;EAAxC,yCAAwC;CAAI;;AAEhF;EAAiC,iCAAkC;EAAlC,mCAAkC;CAAI;;AACvE;EAAiC,+BAAgC;EAAhC,iCAAgC;CAAI;;AACrE;EAAiC,kCAA8B;EAA9B,+BAA8B;CAAI;;AACnE;EAAiC,oCAAgC;EAAhC,iCAAgC;CAAI;;AACrE;EAAiC,mCAA+B;EAA/B,gCAA+B;CAAI;;AAEpE;EAAkC,qCAAoC;EAApC,qCAAoC;CAAI;;AAC1E;EAAkC,mCAAkC;EAAlC,mCAAkC;CAAI;;AACxE;EAAkC,sCAAgC;EAAhC,iCAAgC;CAAI;;AACtE;EAAkC,uCAAuC;EAAvC,wCAAuC;CAAI;;AAC7E;EAAkC,0CAAsC;EAAtC,uCAAsC;CAAI;;AAC5E;EAAkC,uCAAiC;EAAjC,kCAAiC;CAAI;;AAEvE;EAAgC,qCAA2B;EAA3B,4BAA2B;CAAI;;AAC/D;EAAgC,sCAAiC;EAAjC,kCAAiC;CAAI;;AACrE;EAAgC,oCAA+B;EAA/B,gCAA+B;CAAI;;AACnE;EAAgC,uCAA6B;EAA7B,8BAA6B;CAAI;;AACjE;EAAgC,yCAA+B;EAA/B,gCAA+B;CAAI;;AACnE;EAAgC,wCAA8B;EAA9B,+BAA8B;CAAI;;AJYlE;EIlDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CP6rCrE;;AGjrCG;EIlDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CPsyCrE;;AG1xCG;EIlDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CP+4CrE;;AGn4CG;EIlDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CPw/CrE","file":"bootstrap-grid.css","sourcesContent":["/*!\n * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n@at-root {\n @-ms-viewport { width: device-width; } // stylelint-disable-line at-rule-no-vendor-prefix\n}\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n","/*!\n * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n@-ms-viewport {\n width: device-width;\n}\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n}\n\n.col-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n order: -1;\n}\n\n.order-last {\n order: 13;\n}\n\n.order-0 {\n order: 0;\n}\n\n.order-1 {\n order: 1;\n}\n\n.order-2 {\n order: 2;\n}\n\n.order-3 {\n order: 3;\n}\n\n.order-4 {\n order: 4;\n}\n\n.order-5 {\n order: 5;\n}\n\n.order-6 {\n order: 6;\n}\n\n.order-7 {\n order: 7;\n}\n\n.order-8 {\n order: 8;\n}\n\n.order-9 {\n order: 9;\n}\n\n.order-10 {\n order: 10;\n}\n\n.order-11 {\n order: 11;\n}\n\n.order-12 {\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-sm-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n order: -1;\n }\n .order-sm-last {\n order: 13;\n }\n .order-sm-0 {\n order: 0;\n }\n .order-sm-1 {\n order: 1;\n }\n .order-sm-2 {\n order: 2;\n }\n .order-sm-3 {\n order: 3;\n }\n .order-sm-4 {\n order: 4;\n }\n .order-sm-5 {\n order: 5;\n }\n .order-sm-6 {\n order: 6;\n }\n .order-sm-7 {\n order: 7;\n }\n .order-sm-8 {\n order: 8;\n }\n .order-sm-9 {\n order: 9;\n }\n .order-sm-10 {\n order: 10;\n }\n .order-sm-11 {\n order: 11;\n }\n .order-sm-12 {\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-md-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n order: -1;\n }\n .order-md-last {\n order: 13;\n }\n .order-md-0 {\n order: 0;\n }\n .order-md-1 {\n order: 1;\n }\n .order-md-2 {\n order: 2;\n }\n .order-md-3 {\n order: 3;\n }\n .order-md-4 {\n order: 4;\n }\n .order-md-5 {\n order: 5;\n }\n .order-md-6 {\n order: 6;\n }\n .order-md-7 {\n order: 7;\n }\n .order-md-8 {\n order: 8;\n }\n .order-md-9 {\n order: 9;\n }\n .order-md-10 {\n order: 10;\n }\n .order-md-11 {\n order: 11;\n }\n .order-md-12 {\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-lg-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n order: -1;\n }\n .order-lg-last {\n order: 13;\n }\n .order-lg-0 {\n order: 0;\n }\n .order-lg-1 {\n order: 1;\n }\n .order-lg-2 {\n order: 2;\n }\n .order-lg-3 {\n order: 3;\n }\n .order-lg-4 {\n order: 4;\n }\n .order-lg-5 {\n order: 5;\n }\n .order-lg-6 {\n order: 6;\n }\n .order-lg-7 {\n order: 7;\n }\n .order-lg-8 {\n order: 8;\n }\n .order-lg-9 {\n order: 9;\n }\n .order-lg-10 {\n order: 10;\n }\n .order-lg-11 {\n order: 11;\n }\n .order-lg-12 {\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-xl-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n order: -1;\n }\n .order-xl-last {\n order: 13;\n }\n .order-xl-0 {\n order: 0;\n }\n .order-xl-1 {\n order: 1;\n }\n .order-xl-2 {\n order: 2;\n }\n .order-xl-3 {\n order: 3;\n }\n .order-xl-4 {\n order: 4;\n }\n .order-xl-5 {\n order: 5;\n }\n .order-xl-6 {\n order: 6;\n }\n .order-xl-7 {\n order: 7;\n }\n .order-xl-8 {\n order: 8;\n }\n .order-xl-9 {\n order: 9;\n }\n .order-xl-10 {\n order: 10;\n }\n .order-xl-11 {\n order: 11;\n }\n .order-xl-12 {\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-inline-flex {\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: flex !important;\n }\n .d-md-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: flex !important;\n }\n .d-print-inline-flex {\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n justify-content: center !important;\n}\n\n.justify-content-between {\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n justify-content: space-around !important;\n}\n\n.align-items-start {\n align-items: flex-start !important;\n}\n\n.align-items-end {\n align-items: flex-end !important;\n}\n\n.align-items-center {\n align-items: center !important;\n}\n\n.align-items-baseline {\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n align-items: stretch !important;\n}\n\n.align-content-start {\n align-content: flex-start !important;\n}\n\n.align-content-end {\n align-content: flex-end !important;\n}\n\n.align-content-center {\n align-content: center !important;\n}\n\n.align-content-between {\n align-content: space-between !important;\n}\n\n.align-content-around {\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n align-content: stretch !important;\n}\n\n.align-self-auto {\n align-self: auto !important;\n}\n\n.align-self-start {\n align-self: flex-start !important;\n}\n\n.align-self-end {\n align-self: flex-end !important;\n}\n\n.align-self-center {\n align-self: center !important;\n}\n\n.align-self-baseline {\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important;\n }\n .flex-sm-column {\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n justify-content: center !important;\n }\n .justify-content-sm-between {\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n align-items: center !important;\n }\n .align-items-sm-baseline {\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n align-items: stretch !important;\n }\n .align-content-sm-start {\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n align-content: center !important;\n }\n .align-content-sm-between {\n align-content: space-between !important;\n }\n .align-content-sm-around {\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n align-self: auto !important;\n }\n .align-self-sm-start {\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n align-self: center !important;\n }\n .align-self-sm-baseline {\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important;\n }\n .flex-md-column {\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n justify-content: center !important;\n }\n .justify-content-md-between {\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n justify-content: space-around !important;\n }\n .align-items-md-start {\n align-items: flex-start !important;\n }\n .align-items-md-end {\n align-items: flex-end !important;\n }\n .align-items-md-center {\n align-items: center !important;\n }\n .align-items-md-baseline {\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n align-items: stretch !important;\n }\n .align-content-md-start {\n align-content: flex-start !important;\n }\n .align-content-md-end {\n align-content: flex-end !important;\n }\n .align-content-md-center {\n align-content: center !important;\n }\n .align-content-md-between {\n align-content: space-between !important;\n }\n .align-content-md-around {\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n align-content: stretch !important;\n }\n .align-self-md-auto {\n align-self: auto !important;\n }\n .align-self-md-start {\n align-self: flex-start !important;\n }\n .align-self-md-end {\n align-self: flex-end !important;\n }\n .align-self-md-center {\n align-self: center !important;\n }\n .align-self-md-baseline {\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important;\n }\n .flex-lg-column {\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n justify-content: center !important;\n }\n .justify-content-lg-between {\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n align-items: center !important;\n }\n .align-items-lg-baseline {\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n align-items: stretch !important;\n }\n .align-content-lg-start {\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n align-content: center !important;\n }\n .align-content-lg-between {\n align-content: space-between !important;\n }\n .align-content-lg-around {\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n align-self: auto !important;\n }\n .align-self-lg-start {\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n align-self: center !important;\n }\n .align-self-lg-baseline {\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important;\n }\n .flex-xl-column {\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n justify-content: center !important;\n }\n .justify-content-xl-between {\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n align-items: center !important;\n }\n .align-items-xl-baseline {\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n align-items: stretch !important;\n }\n .align-content-xl-start {\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n align-content: center !important;\n }\n .align-content-xl-between {\n align-content: space-between !important;\n }\n .align-content-xl-around {\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n align-self: auto !important;\n }\n .align-self-xl-start {\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n align-self: center !important;\n }\n .align-self-xl-baseline {\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n align-self: stretch !important;\n }\n}\n\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container() {\n width: 100%;\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row() {\n display: flex;\n flex-wrap: wrap;\n margin-right: ($grid-gutter-width / -2);\n margin-left: ($grid-gutter-width / -2);\n}\n\n@mixin make-col-ready() {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n min-height: 1px; // Prevent collapsing\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02px, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n\n//\n// Color system\n//\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-print-styles: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints);\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n\n// Fonts\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: ($font-size-base * 1.25) !default;\n$font-size-sm: ($font-size-base * .875) !default;\n\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: ($spacer / 2) !default;\n$headings-font-family: inherit !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: inherit !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: ($font-size-base * 1.25) !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-font-size: ($font-size-base * 1.25) !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-bg: transparent !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $gray-300 !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-bg: $gray-900 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($gray-900, 7.5%) !default;\n$table-dark-color: $body-bg !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;\n$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default;\n\n$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;\n$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;\n\n$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;\n$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: 1.5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $gray-300 !default;\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-control-indicator-disabled-bg: $gray-200 !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n\n$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-select-padding-y: .375rem !default;\n$custom-select-padding-x: .75rem !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-line-height: $input-btn-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-select-border-width: $input-btn-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-btn-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width rgba($custom-select-focus-border-color, .5) !default;\n\n$custom-select-font-size-sm: 75% !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-font-size-lg: 125% !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-btn-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-btn-padding-y !default;\n$custom-file-padding-x: $input-btn-padding-x !default;\n$custom-file-line-height: $input-btn-line-height !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-btn-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: ($spacer / 2) !default;\n\n// Navbar\n\n$navbar-padding-y: ($spacer / 2) !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: ($grid-gutter-width / 2) !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $gray-200 !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding: 1rem !default;\n\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: ($font-size-base * .75) !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n// List group\n\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$carousel-transition: transform .6s ease !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Printing\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n min-height: 1px; // Prevent columns from collapsing when empty\n padding-right: ($gutter / 2);\n padding-left: ($gutter / 2);\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .d#{$infix}-none { display: none !important; }\n .d#{$infix}-inline { display: inline !important; }\n .d#{$infix}-inline-block { display: inline-block !important; }\n .d#{$infix}-block { display: block !important; }\n .d#{$infix}-table { display: table !important; }\n .d#{$infix}-table-row { display: table-row !important; }\n .d#{$infix}-table-cell { display: table-cell !important; }\n .d#{$infix}-flex { display: flex !important; }\n .d#{$infix}-inline-flex { display: inline-flex !important; }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n .d-print-none { display: none !important; }\n .d-print-inline { display: inline !important; }\n .d-print-inline-block { display: inline-block !important; }\n .d-print-block { display: block !important; }\n .d-print-table { display: table !important; }\n .d-print-table-row { display: table-row !important; }\n .d-print-table-cell { display: table-cell !important; }\n .d-print-flex { display: flex !important; }\n .d-print-inline-flex { display: inline-flex !important; }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n"]} \ No newline at end of file diff --git a/Erupe/www/erupe/css/dependencies/bootstrap-grid.min.css b/Erupe/www/erupe/css/dependencies/bootstrap-grid.min.css new file mode 100644 index 000000000..63e1bc6b0 --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap-grid.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap Grid v4.1.3 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */@-ms-viewport{width:device-width}html{box-sizing:border-box;-ms-overflow-style:scrollbar}*,::after,::before{box-sizing:inherit}.container{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}@media (min-width:576px){.container{max-width:540px}}@media (min-width:768px){.container{max-width:720px}}@media (min-width:992px){.container{max-width:960px}}@media (min-width:1200px){.container{max-width:1140px}}.container-fluid{width:100%;padding-right:15px;padding-left:15px;margin-right:auto;margin-left:auto}.row{display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:-15px;margin-left:-15px}.no-gutters{margin-right:0;margin-left:0}.no-gutters>.col,.no-gutters>[class*=col-]{padding-right:0;padding-left:0}.col,.col-1,.col-10,.col-11,.col-12,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-auto,.col-lg,.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-auto,.col-md,.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-auto,.col-sm,.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-auto,.col-xl,.col-xl-1,.col-xl-10,.col-xl-11,.col-xl-12,.col-xl-2,.col-xl-3,.col-xl-4,.col-xl-5,.col-xl-6,.col-xl-7,.col-xl-8,.col-xl-9,.col-xl-auto{position:relative;width:100%;min-height:1px;padding-right:15px;padding-left:15px}.col{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-first{-ms-flex-order:-1;order:-1}.order-last{-ms-flex-order:13;order:13}.order-0{-ms-flex-order:0;order:0}.order-1{-ms-flex-order:1;order:1}.order-2{-ms-flex-order:2;order:2}.order-3{-ms-flex-order:3;order:3}.order-4{-ms-flex-order:4;order:4}.order-5{-ms-flex-order:5;order:5}.order-6{-ms-flex-order:6;order:6}.order-7{-ms-flex-order:7;order:7}.order-8{-ms-flex-order:8;order:8}.order-9{-ms-flex-order:9;order:9}.order-10{-ms-flex-order:10;order:10}.order-11{-ms-flex-order:11;order:11}.order-12{-ms-flex-order:12;order:12}.offset-1{margin-left:8.333333%}.offset-2{margin-left:16.666667%}.offset-3{margin-left:25%}.offset-4{margin-left:33.333333%}.offset-5{margin-left:41.666667%}.offset-6{margin-left:50%}.offset-7{margin-left:58.333333%}.offset-8{margin-left:66.666667%}.offset-9{margin-left:75%}.offset-10{margin-left:83.333333%}.offset-11{margin-left:91.666667%}@media (min-width:576px){.col-sm{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-sm-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-sm-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-sm-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-sm-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-sm-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-sm-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-sm-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-sm-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-sm-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-sm-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-sm-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-sm-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-sm-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-sm-first{-ms-flex-order:-1;order:-1}.order-sm-last{-ms-flex-order:13;order:13}.order-sm-0{-ms-flex-order:0;order:0}.order-sm-1{-ms-flex-order:1;order:1}.order-sm-2{-ms-flex-order:2;order:2}.order-sm-3{-ms-flex-order:3;order:3}.order-sm-4{-ms-flex-order:4;order:4}.order-sm-5{-ms-flex-order:5;order:5}.order-sm-6{-ms-flex-order:6;order:6}.order-sm-7{-ms-flex-order:7;order:7}.order-sm-8{-ms-flex-order:8;order:8}.order-sm-9{-ms-flex-order:9;order:9}.order-sm-10{-ms-flex-order:10;order:10}.order-sm-11{-ms-flex-order:11;order:11}.order-sm-12{-ms-flex-order:12;order:12}.offset-sm-0{margin-left:0}.offset-sm-1{margin-left:8.333333%}.offset-sm-2{margin-left:16.666667%}.offset-sm-3{margin-left:25%}.offset-sm-4{margin-left:33.333333%}.offset-sm-5{margin-left:41.666667%}.offset-sm-6{margin-left:50%}.offset-sm-7{margin-left:58.333333%}.offset-sm-8{margin-left:66.666667%}.offset-sm-9{margin-left:75%}.offset-sm-10{margin-left:83.333333%}.offset-sm-11{margin-left:91.666667%}}@media (min-width:768px){.col-md{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-md-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-md-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-md-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-md-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-md-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-md-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-md-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-md-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-md-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-md-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-md-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-md-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-md-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-md-first{-ms-flex-order:-1;order:-1}.order-md-last{-ms-flex-order:13;order:13}.order-md-0{-ms-flex-order:0;order:0}.order-md-1{-ms-flex-order:1;order:1}.order-md-2{-ms-flex-order:2;order:2}.order-md-3{-ms-flex-order:3;order:3}.order-md-4{-ms-flex-order:4;order:4}.order-md-5{-ms-flex-order:5;order:5}.order-md-6{-ms-flex-order:6;order:6}.order-md-7{-ms-flex-order:7;order:7}.order-md-8{-ms-flex-order:8;order:8}.order-md-9{-ms-flex-order:9;order:9}.order-md-10{-ms-flex-order:10;order:10}.order-md-11{-ms-flex-order:11;order:11}.order-md-12{-ms-flex-order:12;order:12}.offset-md-0{margin-left:0}.offset-md-1{margin-left:8.333333%}.offset-md-2{margin-left:16.666667%}.offset-md-3{margin-left:25%}.offset-md-4{margin-left:33.333333%}.offset-md-5{margin-left:41.666667%}.offset-md-6{margin-left:50%}.offset-md-7{margin-left:58.333333%}.offset-md-8{margin-left:66.666667%}.offset-md-9{margin-left:75%}.offset-md-10{margin-left:83.333333%}.offset-md-11{margin-left:91.666667%}}@media (min-width:992px){.col-lg{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-lg-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-lg-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-lg-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-lg-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-lg-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-lg-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-lg-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-lg-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-lg-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-lg-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-lg-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-lg-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-lg-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-lg-first{-ms-flex-order:-1;order:-1}.order-lg-last{-ms-flex-order:13;order:13}.order-lg-0{-ms-flex-order:0;order:0}.order-lg-1{-ms-flex-order:1;order:1}.order-lg-2{-ms-flex-order:2;order:2}.order-lg-3{-ms-flex-order:3;order:3}.order-lg-4{-ms-flex-order:4;order:4}.order-lg-5{-ms-flex-order:5;order:5}.order-lg-6{-ms-flex-order:6;order:6}.order-lg-7{-ms-flex-order:7;order:7}.order-lg-8{-ms-flex-order:8;order:8}.order-lg-9{-ms-flex-order:9;order:9}.order-lg-10{-ms-flex-order:10;order:10}.order-lg-11{-ms-flex-order:11;order:11}.order-lg-12{-ms-flex-order:12;order:12}.offset-lg-0{margin-left:0}.offset-lg-1{margin-left:8.333333%}.offset-lg-2{margin-left:16.666667%}.offset-lg-3{margin-left:25%}.offset-lg-4{margin-left:33.333333%}.offset-lg-5{margin-left:41.666667%}.offset-lg-6{margin-left:50%}.offset-lg-7{margin-left:58.333333%}.offset-lg-8{margin-left:66.666667%}.offset-lg-9{margin-left:75%}.offset-lg-10{margin-left:83.333333%}.offset-lg-11{margin-left:91.666667%}}@media (min-width:1200px){.col-xl{-ms-flex-preferred-size:0;flex-basis:0;-ms-flex-positive:1;flex-grow:1;max-width:100%}.col-xl-auto{-ms-flex:0 0 auto;flex:0 0 auto;width:auto;max-width:none}.col-xl-1{-ms-flex:0 0 8.333333%;flex:0 0 8.333333%;max-width:8.333333%}.col-xl-2{-ms-flex:0 0 16.666667%;flex:0 0 16.666667%;max-width:16.666667%}.col-xl-3{-ms-flex:0 0 25%;flex:0 0 25%;max-width:25%}.col-xl-4{-ms-flex:0 0 33.333333%;flex:0 0 33.333333%;max-width:33.333333%}.col-xl-5{-ms-flex:0 0 41.666667%;flex:0 0 41.666667%;max-width:41.666667%}.col-xl-6{-ms-flex:0 0 50%;flex:0 0 50%;max-width:50%}.col-xl-7{-ms-flex:0 0 58.333333%;flex:0 0 58.333333%;max-width:58.333333%}.col-xl-8{-ms-flex:0 0 66.666667%;flex:0 0 66.666667%;max-width:66.666667%}.col-xl-9{-ms-flex:0 0 75%;flex:0 0 75%;max-width:75%}.col-xl-10{-ms-flex:0 0 83.333333%;flex:0 0 83.333333%;max-width:83.333333%}.col-xl-11{-ms-flex:0 0 91.666667%;flex:0 0 91.666667%;max-width:91.666667%}.col-xl-12{-ms-flex:0 0 100%;flex:0 0 100%;max-width:100%}.order-xl-first{-ms-flex-order:-1;order:-1}.order-xl-last{-ms-flex-order:13;order:13}.order-xl-0{-ms-flex-order:0;order:0}.order-xl-1{-ms-flex-order:1;order:1}.order-xl-2{-ms-flex-order:2;order:2}.order-xl-3{-ms-flex-order:3;order:3}.order-xl-4{-ms-flex-order:4;order:4}.order-xl-5{-ms-flex-order:5;order:5}.order-xl-6{-ms-flex-order:6;order:6}.order-xl-7{-ms-flex-order:7;order:7}.order-xl-8{-ms-flex-order:8;order:8}.order-xl-9{-ms-flex-order:9;order:9}.order-xl-10{-ms-flex-order:10;order:10}.order-xl-11{-ms-flex-order:11;order:11}.order-xl-12{-ms-flex-order:12;order:12}.offset-xl-0{margin-left:0}.offset-xl-1{margin-left:8.333333%}.offset-xl-2{margin-left:16.666667%}.offset-xl-3{margin-left:25%}.offset-xl-4{margin-left:33.333333%}.offset-xl-5{margin-left:41.666667%}.offset-xl-6{margin-left:50%}.offset-xl-7{margin-left:58.333333%}.offset-xl-8{margin-left:66.666667%}.offset-xl-9{margin-left:75%}.offset-xl-10{margin-left:83.333333%}.offset-xl-11{margin-left:91.666667%}}.d-none{display:none!important}.d-inline{display:inline!important}.d-inline-block{display:inline-block!important}.d-block{display:block!important}.d-table{display:table!important}.d-table-row{display:table-row!important}.d-table-cell{display:table-cell!important}.d-flex{display:-ms-flexbox!important;display:flex!important}.d-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}@media (min-width:576px){.d-sm-none{display:none!important}.d-sm-inline{display:inline!important}.d-sm-inline-block{display:inline-block!important}.d-sm-block{display:block!important}.d-sm-table{display:table!important}.d-sm-table-row{display:table-row!important}.d-sm-table-cell{display:table-cell!important}.d-sm-flex{display:-ms-flexbox!important;display:flex!important}.d-sm-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:768px){.d-md-none{display:none!important}.d-md-inline{display:inline!important}.d-md-inline-block{display:inline-block!important}.d-md-block{display:block!important}.d-md-table{display:table!important}.d-md-table-row{display:table-row!important}.d-md-table-cell{display:table-cell!important}.d-md-flex{display:-ms-flexbox!important;display:flex!important}.d-md-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:992px){.d-lg-none{display:none!important}.d-lg-inline{display:inline!important}.d-lg-inline-block{display:inline-block!important}.d-lg-block{display:block!important}.d-lg-table{display:table!important}.d-lg-table-row{display:table-row!important}.d-lg-table-cell{display:table-cell!important}.d-lg-flex{display:-ms-flexbox!important;display:flex!important}.d-lg-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media (min-width:1200px){.d-xl-none{display:none!important}.d-xl-inline{display:inline!important}.d-xl-inline-block{display:inline-block!important}.d-xl-block{display:block!important}.d-xl-table{display:table!important}.d-xl-table-row{display:table-row!important}.d-xl-table-cell{display:table-cell!important}.d-xl-flex{display:-ms-flexbox!important;display:flex!important}.d-xl-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}@media print{.d-print-none{display:none!important}.d-print-inline{display:inline!important}.d-print-inline-block{display:inline-block!important}.d-print-block{display:block!important}.d-print-table{display:table!important}.d-print-table-row{display:table-row!important}.d-print-table-cell{display:table-cell!important}.d-print-flex{display:-ms-flexbox!important;display:flex!important}.d-print-inline-flex{display:-ms-inline-flexbox!important;display:inline-flex!important}}.flex-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-center{-ms-flex-align:center!important;align-items:center!important}.align-items-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}@media (min-width:576px){.flex-sm-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-sm-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-sm-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-sm-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-sm-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-sm-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-sm-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-sm-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-sm-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-sm-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-sm-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-sm-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-sm-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-sm-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-sm-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-sm-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-sm-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-sm-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-sm-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-sm-center{-ms-flex-align:center!important;align-items:center!important}.align-items-sm-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-sm-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-sm-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-sm-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-sm-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-sm-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-sm-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-sm-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-sm-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-sm-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-sm-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-sm-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-sm-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-sm-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:768px){.flex-md-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-md-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-md-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-md-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-md-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-md-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-md-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-md-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-md-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-md-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-md-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-md-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-md-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-md-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-md-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-md-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-md-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-md-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-md-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-md-center{-ms-flex-align:center!important;align-items:center!important}.align-items-md-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-md-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-md-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-md-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-md-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-md-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-md-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-md-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-md-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-md-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-md-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-md-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-md-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-md-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:992px){.flex-lg-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-lg-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-lg-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-lg-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-lg-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-lg-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-lg-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-lg-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-lg-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-lg-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-lg-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-lg-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-lg-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-lg-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-lg-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-lg-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-lg-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-lg-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-lg-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-lg-center{-ms-flex-align:center!important;align-items:center!important}.align-items-lg-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-lg-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-lg-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-lg-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-lg-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-lg-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-lg-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-lg-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-lg-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-lg-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-lg-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-lg-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-lg-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-lg-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}}@media (min-width:1200px){.flex-xl-row{-ms-flex-direction:row!important;flex-direction:row!important}.flex-xl-column{-ms-flex-direction:column!important;flex-direction:column!important}.flex-xl-row-reverse{-ms-flex-direction:row-reverse!important;flex-direction:row-reverse!important}.flex-xl-column-reverse{-ms-flex-direction:column-reverse!important;flex-direction:column-reverse!important}.flex-xl-wrap{-ms-flex-wrap:wrap!important;flex-wrap:wrap!important}.flex-xl-nowrap{-ms-flex-wrap:nowrap!important;flex-wrap:nowrap!important}.flex-xl-wrap-reverse{-ms-flex-wrap:wrap-reverse!important;flex-wrap:wrap-reverse!important}.flex-xl-fill{-ms-flex:1 1 auto!important;flex:1 1 auto!important}.flex-xl-grow-0{-ms-flex-positive:0!important;flex-grow:0!important}.flex-xl-grow-1{-ms-flex-positive:1!important;flex-grow:1!important}.flex-xl-shrink-0{-ms-flex-negative:0!important;flex-shrink:0!important}.flex-xl-shrink-1{-ms-flex-negative:1!important;flex-shrink:1!important}.justify-content-xl-start{-ms-flex-pack:start!important;justify-content:flex-start!important}.justify-content-xl-end{-ms-flex-pack:end!important;justify-content:flex-end!important}.justify-content-xl-center{-ms-flex-pack:center!important;justify-content:center!important}.justify-content-xl-between{-ms-flex-pack:justify!important;justify-content:space-between!important}.justify-content-xl-around{-ms-flex-pack:distribute!important;justify-content:space-around!important}.align-items-xl-start{-ms-flex-align:start!important;align-items:flex-start!important}.align-items-xl-end{-ms-flex-align:end!important;align-items:flex-end!important}.align-items-xl-center{-ms-flex-align:center!important;align-items:center!important}.align-items-xl-baseline{-ms-flex-align:baseline!important;align-items:baseline!important}.align-items-xl-stretch{-ms-flex-align:stretch!important;align-items:stretch!important}.align-content-xl-start{-ms-flex-line-pack:start!important;align-content:flex-start!important}.align-content-xl-end{-ms-flex-line-pack:end!important;align-content:flex-end!important}.align-content-xl-center{-ms-flex-line-pack:center!important;align-content:center!important}.align-content-xl-between{-ms-flex-line-pack:justify!important;align-content:space-between!important}.align-content-xl-around{-ms-flex-line-pack:distribute!important;align-content:space-around!important}.align-content-xl-stretch{-ms-flex-line-pack:stretch!important;align-content:stretch!important}.align-self-xl-auto{-ms-flex-item-align:auto!important;align-self:auto!important}.align-self-xl-start{-ms-flex-item-align:start!important;align-self:flex-start!important}.align-self-xl-end{-ms-flex-item-align:end!important;align-self:flex-end!important}.align-self-xl-center{-ms-flex-item-align:center!important;align-self:center!important}.align-self-xl-baseline{-ms-flex-item-align:baseline!important;align-self:baseline!important}.align-self-xl-stretch{-ms-flex-item-align:stretch!important;align-self:stretch!important}} +/*# sourceMappingURL=bootstrap-grid.min.css.map */ \ No newline at end of file diff --git a/Erupe/www/erupe/css/dependencies/bootstrap-grid.min.css.map b/Erupe/www/erupe/css/dependencies/bootstrap-grid.min.css.map new file mode 100644 index 000000000..4cc3aa658 --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap-grid.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-grid.scss","dist/css/bootstrap-grid.css","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/utilities/_display.scss","../../scss/utilities/_flex.scss"],"names":[],"mappings":"AAAA;;;;;AAQE,cAAgB,MAAA,aAGlB,KACE,WAAA,WACA,mBAAA,UAGF,ECCA,QADA,SDGE,WAAA,QEdA,WCAA,MAAA,KACA,cAAA,KACA,aAAA,KACA,aAAA,KACA,YAAA,KCmDE,yBFvDF,WCYI,UAAA,OC2CF,yBFvDF,WCYI,UAAA,OC2CF,yBFvDF,WCYI,UAAA,OC2CF,0BFvDF,WCYI,UAAA,QDAJ,iBCZA,MAAA,KACA,cAAA,KACA,aAAA,KACA,aAAA,KACA,YAAA,KDkBA,KCJA,QAAA,YAAA,QAAA,KACA,cAAA,KAAA,UAAA,KACA,aAAA,MACA,YAAA,MDOA,YACE,aAAA,EACA,YAAA,EAFF,iBD2CF,0BCrCM,cAAA,EACA,aAAA,EGjCJ,KAAA,OAAA,QAAA,QAAA,QAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OAAA,OJ2EF,UAEqJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACtG,aAFqJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACtG,aAFkJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACnG,aAEqJ,QAAvI,UAAmG,WAAY,WAAY,WAAhH,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UAAW,UACtG,aI9EI,SAAA,SACA,MAAA,KACA,WAAA,IACA,cAAA,KACA,aAAA,KAmBE,KACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,UACE,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KAIA,OFFN,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEFM,OFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,OFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,OFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,OFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,OFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,OFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,OFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,OFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,QFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,QFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,QFFN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEGI,aAAwB,eAAA,GAAA,MAAA,GAExB,YAAuB,eAAA,GAAA,MAAA,GAGrB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,SAAwB,eAAA,EAAA,MAAA,EAAxB,UAAwB,eAAA,GAAA,MAAA,GAAxB,UAAwB,eAAA,GAAA,MAAA,GAAxB,UAAwB,eAAA,GAAA,MAAA,GAMtB,UFTR,YAAA,UESQ,UFTR,YAAA,WESQ,UFTR,YAAA,IESQ,UFTR,YAAA,WESQ,UFTR,YAAA,WESQ,UFTR,YAAA,IESQ,UFTR,YAAA,WESQ,UFTR,YAAA,WESQ,UFTR,YAAA,IESQ,WFTR,YAAA,WESQ,WFTR,YAAA,WCUE,yBC7BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KAIA,UFFN,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEGI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAMtB,aFTR,YAAA,EESQ,aFTR,YAAA,UESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,cFTR,YAAA,WESQ,cFTR,YAAA,YCUE,yBC7BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KAIA,UFFN,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEGI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAMtB,aFTR,YAAA,EESQ,aFTR,YAAA,UESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,cFTR,YAAA,WESQ,cFTR,YAAA,YCUE,yBC7BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KAIA,UFFN,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEGI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAMtB,aFTR,YAAA,EESQ,aFTR,YAAA,UESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,cFTR,YAAA,WESQ,cFTR,YAAA,YCUE,0BC7BE,QACE,wBAAA,EAAA,WAAA,EACA,kBAAA,EAAA,UAAA,EACA,UAAA,KAEF,aACE,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KACA,MAAA,KACA,UAAA,KAIA,UFFN,SAAA,EAAA,EAAA,UAAA,KAAA,EAAA,EAAA,UAIA,UAAA,UEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,UFFN,SAAA,EAAA,EAAA,IAAA,KAAA,EAAA,EAAA,IAIA,UAAA,IEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,WAAA,KAAA,EAAA,EAAA,WAIA,UAAA,WEFM,WFFN,SAAA,EAAA,EAAA,KAAA,KAAA,EAAA,EAAA,KAIA,UAAA,KEGI,gBAAwB,eAAA,GAAA,MAAA,GAExB,eAAuB,eAAA,GAAA,MAAA,GAGrB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,YAAwB,eAAA,EAAA,MAAA,EAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAAxB,aAAwB,eAAA,GAAA,MAAA,GAMtB,aFTR,YAAA,EESQ,aFTR,YAAA,UESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,aFTR,YAAA,WESQ,aFTR,YAAA,WESQ,aFTR,YAAA,IESQ,cFTR,YAAA,WESQ,cFTR,YAAA,YGxCE,QAA2B,QAAA,eAC3B,UAA2B,QAAA,iBAC3B,gBAA2B,QAAA,uBAC3B,SAA2B,QAAA,gBAC3B,SAA2B,QAAA,gBAC3B,aAA2B,QAAA,oBAC3B,cAA2B,QAAA,qBAC3B,QAA2B,QAAA,sBAAA,QAAA,eAC3B,eAA2B,QAAA,6BAAA,QAAA,sBF0C3B,yBElDA,WAA2B,QAAA,eAC3B,aAA2B,QAAA,iBAC3B,mBAA2B,QAAA,uBAC3B,YAA2B,QAAA,gBAC3B,YAA2B,QAAA,gBAC3B,gBAA2B,QAAA,oBAC3B,iBAA2B,QAAA,qBAC3B,WAA2B,QAAA,sBAAA,QAAA,eAC3B,kBAA2B,QAAA,6BAAA,QAAA,uBF0C3B,yBElDA,WAA2B,QAAA,eAC3B,aAA2B,QAAA,iBAC3B,mBAA2B,QAAA,uBAC3B,YAA2B,QAAA,gBAC3B,YAA2B,QAAA,gBAC3B,gBAA2B,QAAA,oBAC3B,iBAA2B,QAAA,qBAC3B,WAA2B,QAAA,sBAAA,QAAA,eAC3B,kBAA2B,QAAA,6BAAA,QAAA,uBF0C3B,yBElDA,WAA2B,QAAA,eAC3B,aAA2B,QAAA,iBAC3B,mBAA2B,QAAA,uBAC3B,YAA2B,QAAA,gBAC3B,YAA2B,QAAA,gBAC3B,gBAA2B,QAAA,oBAC3B,iBAA2B,QAAA,qBAC3B,WAA2B,QAAA,sBAAA,QAAA,eAC3B,kBAA2B,QAAA,6BAAA,QAAA,uBF0C3B,0BElDA,WAA2B,QAAA,eAC3B,aAA2B,QAAA,iBAC3B,mBAA2B,QAAA,uBAC3B,YAA2B,QAAA,gBAC3B,YAA2B,QAAA,gBAC3B,gBAA2B,QAAA,oBAC3B,iBAA2B,QAAA,qBAC3B,WAA2B,QAAA,sBAAA,QAAA,eAC3B,kBAA2B,QAAA,6BAAA,QAAA,uBAS/B,aACE,cAAwB,QAAA,eACxB,gBAAwB,QAAA,iBACxB,sBAAwB,QAAA,uBACxB,eAAwB,QAAA,gBACxB,eAAwB,QAAA,gBACxB,mBAAwB,QAAA,oBACxB,oBAAwB,QAAA,qBACxB,cAAwB,QAAA,sBAAA,QAAA,eACxB,qBAAwB,QAAA,6BAAA,QAAA,uBC1BtB,UAAgC,mBAAA,cAAA,eAAA,cAChC,aAAgC,mBAAA,iBAAA,eAAA,iBAChC,kBAAgC,mBAAA,sBAAA,eAAA,sBAChC,qBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,WAA8B,cAAA,eAAA,UAAA,eAC9B,aAA8B,cAAA,iBAAA,UAAA,iBAC9B,mBAA8B,cAAA,uBAAA,UAAA,uBAC9B,WAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,aAA8B,kBAAA,YAAA,UAAA,YAC9B,aAA8B,kBAAA,YAAA,UAAA,YAC9B,eAA8B,kBAAA,YAAA,YAAA,YAC9B,eAA8B,kBAAA,YAAA,YAAA,YAE9B,uBAAoC,cAAA,gBAAA,gBAAA,qBACpC,qBAAoC,cAAA,cAAA,gBAAA,mBACpC,wBAAoC,cAAA,iBAAA,gBAAA,iBACpC,yBAAoC,cAAA,kBAAA,gBAAA,wBACpC,wBAAoC,cAAA,qBAAA,gBAAA,uBAEpC,mBAAiC,eAAA,gBAAA,YAAA,qBACjC,iBAAiC,eAAA,cAAA,YAAA,mBACjC,oBAAiC,eAAA,iBAAA,YAAA,iBACjC,sBAAiC,eAAA,mBAAA,YAAA,mBACjC,qBAAiC,eAAA,kBAAA,YAAA,kBAEjC,qBAAkC,mBAAA,gBAAA,cAAA,qBAClC,mBAAkC,mBAAA,cAAA,cAAA,mBAClC,sBAAkC,mBAAA,iBAAA,cAAA,iBAClC,uBAAkC,mBAAA,kBAAA,cAAA,wBAClC,sBAAkC,mBAAA,qBAAA,cAAA,uBAClC,uBAAkC,mBAAA,kBAAA,cAAA,kBAElC,iBAAgC,oBAAA,eAAA,WAAA,eAChC,kBAAgC,oBAAA,gBAAA,WAAA,qBAChC,gBAAgC,oBAAA,cAAA,WAAA,mBAChC,mBAAgC,oBAAA,iBAAA,WAAA,iBAChC,qBAAgC,oBAAA,mBAAA,WAAA,mBAChC,oBAAgC,oBAAA,kBAAA,WAAA,kBHYhC,yBGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBHYhC,yBGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBHYhC,yBGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA,mBHYhC,0BGlDA,aAAgC,mBAAA,cAAA,eAAA,cAChC,gBAAgC,mBAAA,iBAAA,eAAA,iBAChC,qBAAgC,mBAAA,sBAAA,eAAA,sBAChC,wBAAgC,mBAAA,yBAAA,eAAA,yBAEhC,cAA8B,cAAA,eAAA,UAAA,eAC9B,gBAA8B,cAAA,iBAAA,UAAA,iBAC9B,sBAA8B,cAAA,uBAAA,UAAA,uBAC9B,cAA8B,SAAA,EAAA,EAAA,eAAA,KAAA,EAAA,EAAA,eAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,gBAA8B,kBAAA,YAAA,UAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAC9B,kBAA8B,kBAAA,YAAA,YAAA,YAE9B,0BAAoC,cAAA,gBAAA,gBAAA,qBACpC,wBAAoC,cAAA,cAAA,gBAAA,mBACpC,2BAAoC,cAAA,iBAAA,gBAAA,iBACpC,4BAAoC,cAAA,kBAAA,gBAAA,wBACpC,2BAAoC,cAAA,qBAAA,gBAAA,uBAEpC,sBAAiC,eAAA,gBAAA,YAAA,qBACjC,oBAAiC,eAAA,cAAA,YAAA,mBACjC,uBAAiC,eAAA,iBAAA,YAAA,iBACjC,yBAAiC,eAAA,mBAAA,YAAA,mBACjC,wBAAiC,eAAA,kBAAA,YAAA,kBAEjC,wBAAkC,mBAAA,gBAAA,cAAA,qBAClC,sBAAkC,mBAAA,cAAA,cAAA,mBAClC,yBAAkC,mBAAA,iBAAA,cAAA,iBAClC,0BAAkC,mBAAA,kBAAA,cAAA,wBAClC,yBAAkC,mBAAA,qBAAA,cAAA,uBAClC,0BAAkC,mBAAA,kBAAA,cAAA,kBAElC,oBAAgC,oBAAA,eAAA,WAAA,eAChC,qBAAgC,oBAAA,gBAAA,WAAA,qBAChC,mBAAgC,oBAAA,cAAA,WAAA,mBAChC,sBAAgC,oBAAA,iBAAA,WAAA,iBAChC,wBAAgC,oBAAA,mBAAA,WAAA,mBAChC,uBAAgC,oBAAA,kBAAA,WAAA","sourcesContent":["/*!\n * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n@at-root {\n @-ms-viewport { width: device-width; } // stylelint-disable-line at-rule-no-vendor-prefix\n}\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n@import \"functions\";\n@import \"variables\";\n\n@import \"mixins/breakpoints\";\n@import \"mixins/grid-framework\";\n@import \"mixins/grid\";\n\n@import \"grid\";\n@import \"utilities/display\";\n@import \"utilities/flex\";\n","/*!\n * Bootstrap Grid v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n@-ms-viewport {\n width: device-width;\n}\n\nhtml {\n box-sizing: border-box;\n -ms-overflow-style: scrollbar;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: -ms-flexbox;\n display: flex;\n -ms-flex-wrap: wrap;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n}\n\n.col-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n -ms-flex-order: -1;\n order: -1;\n}\n\n.order-last {\n -ms-flex-order: 13;\n order: 13;\n}\n\n.order-0 {\n -ms-flex-order: 0;\n order: 0;\n}\n\n.order-1 {\n -ms-flex-order: 1;\n order: 1;\n}\n\n.order-2 {\n -ms-flex-order: 2;\n order: 2;\n}\n\n.order-3 {\n -ms-flex-order: 3;\n order: 3;\n}\n\n.order-4 {\n -ms-flex-order: 4;\n order: 4;\n}\n\n.order-5 {\n -ms-flex-order: 5;\n order: 5;\n}\n\n.order-6 {\n -ms-flex-order: 6;\n order: 6;\n}\n\n.order-7 {\n -ms-flex-order: 7;\n order: 7;\n}\n\n.order-8 {\n -ms-flex-order: 8;\n order: 8;\n}\n\n.order-9 {\n -ms-flex-order: 9;\n order: 9;\n}\n\n.order-10 {\n -ms-flex-order: 10;\n order: 10;\n}\n\n.order-11 {\n -ms-flex-order: 11;\n order: 11;\n}\n\n.order-12 {\n -ms-flex-order: 12;\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-sm-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-sm-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-sm-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-sm-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-sm-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-sm-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-sm-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-sm-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-sm-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-sm-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-sm-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-sm-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-sm-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-sm-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-sm-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-md-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-md-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-md-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-md-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-md-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-md-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-md-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-md-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-md-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-md-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-md-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-md-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-md-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-md-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-md-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-lg-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-lg-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-lg-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-lg-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-lg-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-lg-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-lg-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-lg-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-lg-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-lg-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-lg-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-lg-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-lg-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-lg-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-lg-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n -ms-flex-preferred-size: 0;\n flex-basis: 0;\n -ms-flex-positive: 1;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n -ms-flex: 0 0 auto;\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-xl-1 {\n -ms-flex: 0 0 8.333333%;\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n -ms-flex: 0 0 16.666667%;\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n -ms-flex: 0 0 25%;\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n -ms-flex: 0 0 33.333333%;\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n -ms-flex: 0 0 41.666667%;\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n -ms-flex: 0 0 50%;\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n -ms-flex: 0 0 58.333333%;\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n -ms-flex: 0 0 66.666667%;\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n -ms-flex: 0 0 75%;\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n -ms-flex: 0 0 83.333333%;\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n -ms-flex: 0 0 91.666667%;\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n -ms-flex: 0 0 100%;\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n -ms-flex-order: -1;\n order: -1;\n }\n .order-xl-last {\n -ms-flex-order: 13;\n order: 13;\n }\n .order-xl-0 {\n -ms-flex-order: 0;\n order: 0;\n }\n .order-xl-1 {\n -ms-flex-order: 1;\n order: 1;\n }\n .order-xl-2 {\n -ms-flex-order: 2;\n order: 2;\n }\n .order-xl-3 {\n -ms-flex-order: 3;\n order: 3;\n }\n .order-xl-4 {\n -ms-flex-order: 4;\n order: 4;\n }\n .order-xl-5 {\n -ms-flex-order: 5;\n order: 5;\n }\n .order-xl-6 {\n -ms-flex-order: 6;\n order: 6;\n }\n .order-xl-7 {\n -ms-flex-order: 7;\n order: 7;\n }\n .order-xl-8 {\n -ms-flex-order: 8;\n order: 8;\n }\n .order-xl-9 {\n -ms-flex-order: 9;\n order: 9;\n }\n .order-xl-10 {\n -ms-flex-order: 10;\n order: 10;\n }\n .order-xl-11 {\n -ms-flex-order: 11;\n order: 11;\n }\n .order-xl-12 {\n -ms-flex-order: 12;\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n}\n\n.d-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-md-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: -ms-flexbox !important;\n display: flex !important;\n }\n .d-print-inline-flex {\n display: -ms-inline-flexbox !important;\n display: inline-flex !important;\n }\n}\n\n.flex-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n}\n\n.flex-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n}\n\n.justify-content-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n}\n\n.align-items-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n}\n\n.align-items-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n}\n\n.align-items-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n}\n\n.align-items-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n}\n\n.align-content-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n}\n\n.align-content-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n}\n\n.align-content-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n}\n\n.align-content-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n}\n\n.align-content-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n}\n\n.align-self-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n}\n\n.align-self-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n}\n\n.align-self-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n}\n\n.align-self-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n}\n\n.align-self-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-sm-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-sm-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-sm-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-sm-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-sm-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-sm-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-sm-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-sm-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-md-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-md-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-md-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-md-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-md-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-md-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-md-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-md-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-md-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-md-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-md-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-md-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-md-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-md-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-md-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-md-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-lg-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-lg-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-lg-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-lg-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-lg-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-lg-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-lg-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-lg-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n -ms-flex-direction: row !important;\n flex-direction: row !important;\n }\n .flex-xl-column {\n -ms-flex-direction: column !important;\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n -ms-flex-direction: row-reverse !important;\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n -ms-flex-direction: column-reverse !important;\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n -ms-flex-wrap: wrap !important;\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n -ms-flex-wrap: nowrap !important;\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n -ms-flex-wrap: wrap-reverse !important;\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n -ms-flex: 1 1 auto !important;\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n -ms-flex-positive: 0 !important;\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n -ms-flex-positive: 1 !important;\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n -ms-flex-negative: 0 !important;\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n -ms-flex-negative: 1 !important;\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n -ms-flex-pack: start !important;\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n -ms-flex-pack: end !important;\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n -ms-flex-pack: center !important;\n justify-content: center !important;\n }\n .justify-content-xl-between {\n -ms-flex-pack: justify !important;\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n -ms-flex-pack: distribute !important;\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n -ms-flex-align: start !important;\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n -ms-flex-align: end !important;\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n -ms-flex-align: center !important;\n align-items: center !important;\n }\n .align-items-xl-baseline {\n -ms-flex-align: baseline !important;\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n -ms-flex-align: stretch !important;\n align-items: stretch !important;\n }\n .align-content-xl-start {\n -ms-flex-line-pack: start !important;\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n -ms-flex-line-pack: end !important;\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n -ms-flex-line-pack: center !important;\n align-content: center !important;\n }\n .align-content-xl-between {\n -ms-flex-line-pack: justify !important;\n align-content: space-between !important;\n }\n .align-content-xl-around {\n -ms-flex-line-pack: distribute !important;\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n -ms-flex-line-pack: stretch !important;\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n -ms-flex-item-align: auto !important;\n align-self: auto !important;\n }\n .align-self-xl-start {\n -ms-flex-item-align: start !important;\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n -ms-flex-item-align: end !important;\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n -ms-flex-item-align: center !important;\n align-self: center !important;\n }\n .align-self-xl-baseline {\n -ms-flex-item-align: baseline !important;\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n -ms-flex-item-align: stretch !important;\n align-self: stretch !important;\n }\n}\n/*# sourceMappingURL=bootstrap-grid.css.map */","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container() {\n width: 100%;\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row() {\n display: flex;\n flex-wrap: wrap;\n margin-right: ($grid-gutter-width / -2);\n margin-left: ($grid-gutter-width / -2);\n}\n\n@mixin make-col-ready() {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n min-height: 1px; // Prevent collapsing\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02px, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n min-height: 1px; // Prevent columns from collapsing when empty\n padding-right: ($gutter / 2);\n padding-left: ($gutter / 2);\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","// stylelint-disable declaration-no-important\n\n//\n// Utilities for common `display` values\n//\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .d#{$infix}-none { display: none !important; }\n .d#{$infix}-inline { display: inline !important; }\n .d#{$infix}-inline-block { display: inline-block !important; }\n .d#{$infix}-block { display: block !important; }\n .d#{$infix}-table { display: table !important; }\n .d#{$infix}-table-row { display: table-row !important; }\n .d#{$infix}-table-cell { display: table-cell !important; }\n .d#{$infix}-flex { display: flex !important; }\n .d#{$infix}-inline-flex { display: inline-flex !important; }\n }\n}\n\n\n//\n// Utilities for toggling `display` in print\n//\n\n@media print {\n .d-print-none { display: none !important; }\n .d-print-inline { display: inline !important; }\n .d-print-inline-block { display: inline-block !important; }\n .d-print-block { display: block !important; }\n .d-print-table { display: table !important; }\n .d-print-table-row { display: table-row !important; }\n .d-print-table-cell { display: table-cell !important; }\n .d-print-flex { display: flex !important; }\n .d-print-inline-flex { display: inline-flex !important; }\n}\n","// stylelint-disable declaration-no-important\n\n// Flex variation\n//\n// Custom styles for additional flex alignment options.\n\n@each $breakpoint in map-keys($grid-breakpoints) {\n @include media-breakpoint-up($breakpoint) {\n $infix: breakpoint-infix($breakpoint, $grid-breakpoints);\n\n .flex#{$infix}-row { flex-direction: row !important; }\n .flex#{$infix}-column { flex-direction: column !important; }\n .flex#{$infix}-row-reverse { flex-direction: row-reverse !important; }\n .flex#{$infix}-column-reverse { flex-direction: column-reverse !important; }\n\n .flex#{$infix}-wrap { flex-wrap: wrap !important; }\n .flex#{$infix}-nowrap { flex-wrap: nowrap !important; }\n .flex#{$infix}-wrap-reverse { flex-wrap: wrap-reverse !important; }\n .flex#{$infix}-fill { flex: 1 1 auto !important; }\n .flex#{$infix}-grow-0 { flex-grow: 0 !important; }\n .flex#{$infix}-grow-1 { flex-grow: 1 !important; }\n .flex#{$infix}-shrink-0 { flex-shrink: 0 !important; }\n .flex#{$infix}-shrink-1 { flex-shrink: 1 !important; }\n\n .justify-content#{$infix}-start { justify-content: flex-start !important; }\n .justify-content#{$infix}-end { justify-content: flex-end !important; }\n .justify-content#{$infix}-center { justify-content: center !important; }\n .justify-content#{$infix}-between { justify-content: space-between !important; }\n .justify-content#{$infix}-around { justify-content: space-around !important; }\n\n .align-items#{$infix}-start { align-items: flex-start !important; }\n .align-items#{$infix}-end { align-items: flex-end !important; }\n .align-items#{$infix}-center { align-items: center !important; }\n .align-items#{$infix}-baseline { align-items: baseline !important; }\n .align-items#{$infix}-stretch { align-items: stretch !important; }\n\n .align-content#{$infix}-start { align-content: flex-start !important; }\n .align-content#{$infix}-end { align-content: flex-end !important; }\n .align-content#{$infix}-center { align-content: center !important; }\n .align-content#{$infix}-between { align-content: space-between !important; }\n .align-content#{$infix}-around { align-content: space-around !important; }\n .align-content#{$infix}-stretch { align-content: stretch !important; }\n\n .align-self#{$infix}-auto { align-self: auto !important; }\n .align-self#{$infix}-start { align-self: flex-start !important; }\n .align-self#{$infix}-end { align-self: flex-end !important; }\n .align-self#{$infix}-center { align-self: center !important; }\n .align-self#{$infix}-baseline { align-self: baseline !important; }\n .align-self#{$infix}-stretch { align-self: stretch !important; }\n }\n}\n"]} \ No newline at end of file diff --git a/Erupe/www/erupe/css/dependencies/bootstrap-ie8.css b/Erupe/www/erupe/css/dependencies/bootstrap-ie8.css new file mode 100644 index 000000000..335f88066 --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap-ie8.css @@ -0,0 +1,1797 @@ +/*! Bootstrap 4 for IE8 - v4.3.1 */ +/*! https://github.com/coliff/bootstrap-ie8/ */ + +* { + box-sizing: border-box; +} +*:before, +*:after { + box-sizing: border-box; +} + +body { + margin-left: auto; + margin-right: auto; + min-width: 998px; + font-size: 16px; +} +h1, +h2, +h3, +h4, +h5, +h6 { + margin-bottom: 8px; +} +p { + margin-bottom: 16px; +} +address { + margin-bottom: 16px; +} +ol, +ul, +dl { + margin-bottom: 16px; +} +dd { + margin-bottom: 8px; +} +blockquote { + margin: 0 0 16px; +} +pre { + margin-bottom: 16px; +} +figure { + margin: 0 0 16px; +} +button .disabled { + filter: alpha(opacity=65); +} +caption { + padding-top: 12px; + padding-bottom: 12px; +} +label { + margin-bottom: 8px; +} +legend { + margin-bottom: 8px; + font-size: 24px; +} +code { + padding: 3px 6px; +} +kbd { + padding: 3px 6px; +} +hr { + margin-top: 16px; + margin-bottom: 16px; + border-top: 1px solid #eee; + filter: alpha(opacity=65); +} +h1, +.h1 { + font-size: 40px; +} +h2, +.h2 { + font-size: 32px; +} +h3, +.h3 { + font-size: 28px; +} +h4, +.h4 { + font-size: 24px; +} +h5, +.h5 { + font-size: 20px; +} +h6, +.h6 { + font-size: 16px; +} + +.alert { + margin-bottom: 16px; + padding: 12px; +} +.alert-dismissible { + padding-right: 40px; +} +.alert-dismissible .close { + top: -2px; +} +.blockquote { + padding: 8px 16px; + margin-bottom: 16px; + font-size: 20px; +} +.blockquote-footer:before { + content: "\2014 \00A0"; +} + +.breadcrumb { + padding: 12px 16px; + margin-bottom: 16px; +} +.breadcrumb-item { + display: inline-block; +} +.breadcrumb-item + li:before { + padding: 0 5px; + color: #ccc; + content: "/\00a0"; +} +.breadcrumb-item + .breadcrumb-item:before { + display: inline-block; + padding-right: 8px; + padding-left: 8px; + color: #868e96; +} +.breadcrumb-item + .breadcrumb-item:hover:before { + text-decoration: underline; + text-decoration: none; +} + +/** Buttons **/ +.btn { + cursor: pointer; + padding: 6px 12px; + font-size: 16px; +} +.btn-sm, +.btn-group-sm > .btn { + font-size: 14px; + padding: 4px 8px; +} +.btn-lg, +.btn-group-lg > .btn { + font-size: 20px; + padding: 8px 16px; +} +.dropdown-toggle-split { + padding-right: 9px; + padding-left: 9px; +} +.btn + .dropdown-toggle-split { + padding-right: 9px; + padding-left: 9px; +} +.btn-sm + .dropdown-toggle-split, +.btn-group-sm > .btn + .dropdown-toggle-split { + padding-right: 6px; + padding-left: 6px; +} +.btn-lg + .dropdown-toggle-split, +.btn-group-lg > .btn + .dropdown-toggle-split { + padding-right: 12px; + padding-left: 12px; +} +.btn.disabled, +.btn[disabled], +fieldset[disabled] .btn { + cursor: auto; + filter: alpha(opacity=65); +} +.bs-component > .disabled { + filter: alpha(opacity=65); +} +.btn-toolbar { + margin-left: -8px; +} +.btn-group-vertical > .btn { + display: block; +} +.btn-group-vertical .btn { + width: initial; +} +.btn-primary.disabled { + color: #fff; + background-color: #007bff; + border-color: #007bff; +} +.btn-secondary.disabled { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} +.btn-success.disabled { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} +.btn-info.disabled { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} +.btn-warning.disabled { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} +.btn-danger.disabled { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} +.btn-light.disabled { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} +.btn-dark.disabled { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} +.btn-outline-primary.disabled { + color: #007bff; + background-color: transparent; +} +.btn-outline-secondary.disabled { + color: #6c757d; + background-color: transparent; +} +.btn-outline-success.disabled { + color: #28a745; + background-color: transparent; +} +.btn-outline-info.disabled { + color: #17a2b8; + background-color: transparent; +} +.btn-outline-warning.disabled { + color: #ffc107; + background-color: transparent; +} +.btn-outline-danger.disabled { + color: #dc3545; + background-color: transparent; +} +.btn-outline-light.disabled { + color: #f8f9fa; + background-color: transparent; +} +.btn-outline-dark.disabled { + color: #343a40; + background-color: transparent; +} +.btn-link.disabled { + color: #6c757d; + text-decoration: none; +} +.btn-block + .btn-block { + margin-top: 8px; +} +.btn-group, +.btn-group-vertical { + display: inline; + vertical-align: baseline; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group, +.btn-group-vertical .btn + .btn, +.btn-group-vertical .btn + .btn-group, +.btn-group-vertical .btn-group + .btn, +.btn-group-vertical .btn-group + .btn-group { + margin-left: -5px; +} + +/* cards */ +.card { + margin-bottom: 12px; + border: 1px solid #ddd; +} +.card-block { + padding: 20px; +} +.card-body { + padding: 20px; +} +.card-footer { + padding: 12px 20px; + border-top: 1px solid #ddd; + background-color: #f7f7f7; +} +.card-header { + padding: 12px 20px; + background-color: #f7f7f7; + border-bottom: 1px solid #ddd; +} +.card-header-tabs { + margin-right: -10px; + margin-bottom: -12px; + margin-left: -10px; + border-bottom: 0; +} +.card-header-pills { + margin-right: -10px; + margin-left: -10px; +} +.card-img-overlay { + padding: 20px; +} +.card-subtitle { + margin-top: -6px; +} +.card-title { + margin-bottom: 12px; +} +.card-link + .card-link { + margin-left: 20px; +} + +.caret { + border-top: 4px solid; +} +/** Carousel - Hide indicators and controls as the carousel doesn't work **/ +.carousel-indicators, +.carousel-control-prev, +.carousel-control-next { + display: none; +} +.checkbox input[type="checkbox"], +.checkbox-inline input[type="checkbox"], +.radio input[type="radio"], +.radio-inline input[type="radio"] { + margin-top: 4px; +} +.clearfix:after { + content: ""; + display: table; + clear: both; +} +.close { + cursor: pointer; + font-size: 24px; + filter: alpha(opacity=50); +} +.close:focus, +.close:hover { + filter: alpha(opacity=75); +} +.close.disabled { + cursor: auto; +} +.col-form-label { + padding-top: 8px; + padding-bottom: 8px; + margin-bottom: 0; +} +.col-form-label-lg { + padding-top: 12px; + padding-bottom: 12px; + font-size: 20px; +} +.col-form-label-sm { + padding-top: 4px; + padding-bottom: 4px; + font-size: 14px; +} + +.container { + padding-right: 15px; + padding-left: 15px; +} +.custom-control { + min-height: 24px; + padding-left: 0; + margin-right: 16px; + margin-left: 16px; +} +.custom-control-indicator { + top: 0; + width: 0; + height: 0; + background-color: transparent; +} +.custom-control-input { + position: relative; +} +.custom-controls-stacked .custom-control { + margin-bottom: 4px; +} +.custom-file { + height: 40px; +} +.custom-file-control { + height: 40px; + padding: 8px 16px; + border: 1px solid #ddd; +} +.custom-file-control:before { + height: 40px; + padding: 8px 16px; + border: 1px solid #ddd; +} +.custom-file-input { + min-width: 224px; + height: 40px; +} +.custom-select { + padding: 6px 28px 6px 12px; + border: 1px solid #ddd; + background-image: none; + padding-right: 12px; +} +.custom-select-sm { + padding-top: 6px; + padding-bottom: 6px; +} +.display-1 { + font-size: 96px; +} +.display-2 { + font-size: 88px; +} +.display-3 { + font-size: 72px; +} +.display-4 { + font-size: 56px; +} +.dl-horizontal { + margin-right: -30px; + margin-left: -30px; +} +.dropdown-divider { + margin: 8px 0; +} +.dropdown-header { + font-size: 14px; + padding: 8px 24px; +} +.dropdown-item { + padding: 3px 24px; +} +.dropdown-item-text { + padding: 4px 24px; +} +.dropdown-menu { + font-size: 16px; + min-width: 160px; + padding: 8px 0; + margin: 2px 0 0; + border: 1px solid #ddd; +} +.dropdown-toggle:after { + margin-right: 4px; + margin-left: 4px; + content: "▼"; +} +.dropup .caret, +.navbar-fixed-bottom .dropdown .caret { + border-bottom: 4px solid; +} +.fade.show { + filter: alpha(opacity=100); +} +.fade { + filter: alpha(opacity=0); +} +.figure-img { + margin-bottom: 8px; +} +.img-thumbnail { + padding: 4px; +} + +/* forms */ +.form-check { + margin-bottom: 12px; +} +.form-check-inline { + padding-left: 20px; +} +.form-check-input { + margin-top: 4px; + margin-left: -20px; +} +.form-check-label { + padding-left: 20px; +} +.form-control { + padding: 8px 12px; + font-size: 16px; + border: 1px solid #ddd; +} +.form-control-lg { + padding: 8px 16px; + font-size: 20px; +} +.form-control-sm { + padding: 4px 8px; + font-size: 14px; +} +.form-group > .is-valid { + border-color: #28a745 !important; +} +.form-group > .is-invalid { + border-color: #dc3545 !important; +} +.form-control.is-valid ~ .valid-feedback, +.custom-select.is-valid ~ .valid-feedback, +.form-control-file.is-valid ~ .valid-feedback, +.form-check-input.is-valid ~ .valid-feedback, +.custom-control-input.is-valid ~ .valid-feedback, +.form-control.is-invalid ~ .invalid-feedback, +.custom-select.is-invalid ~ .invalid-feedback, +.form-control-file.is-invalid ~ .invalid-feedback, +.form-check-input.is-invalid ~ .invalid-feedback, +.custom-file-input.is-invalid ~ .invalid-feedback { + display: block; +} +.form-control-feedback { + margin-top: 4px; +} +.form-control-plaintext { + padding-top: 8px; + padding-bottom: 8px; +} +.form-control-static { + padding-top: 8px; + padding-bottom: 8px; +} +.form-group { + margin-bottom: 16px; +} +.form-text { + margin-top: 4px; +} +.input-group-addon { + padding: 8px 12px; + font-size: 16px; + border: 1px solid #ddd; +} +.input-group-addon, +.input-group-btn, +.input-group .form-control { + display: table-cell; +} +.input-group-addon, +.input-group-btn { + width: 1%; + white-space: nowrap; + vertical-align: middle; +} +.invalid-feedback { + margin-top: 4px; + font-size: 14px; +} +.invalid-tooltip { + padding: 8px; + margin-top: 2px; + font-size: 14px; + background-color: #dc3545; +} +.valid-feedback { + margin-top: 4px; +} + +.jumbotron { + padding: 64px 32px; + margin-bottom: 32px; +} +.lead { + font-size: 20px; +} +.list-group-item { + padding: 12px 20px; + border: 1px solid #ddd; +} + +.modal-backdrop.fade { + filter: alpha(opacity=0); +} +.modal-backdrop.show { + filter: alpha(opacity=50); +} +.modal-content { + border: 1px solid #ddd; +} +.modal-body { + padding: 16px; +} +.modal-footer { + padding: 16px; + text-align: right; +} +.modal-header { + padding: 16px; +} +.modal-header .close { + padding: 16px; + margin: -48px -16px -16px auto; + filter: none; +} + +/* margin */ +.m-1 { + margin: 4px !important; +} + +.mt-1, +.my-1 { + margin-top: 4px !important; +} + +.mr-1, +.mx-1 { + margin-right: 4px !important; +} + +.mb-1, +.my-1 { + margin-bottom: 4px !important; +} + +.ml-1, +.mx-1 { + margin-left: 4px !important; +} + +.m-2 { + margin: 8px !important; +} + +.mt-2, +.my-2 { + margin-top: 8px !important; +} + +.mr-2, +.mx-2 { + margin-right: 8px !important; +} + +.mb-2, +.my-2 { + margin-bottom: 8px !important; +} + +.ml-2, +.mx-2 { + margin-left: 8px !important; +} + +.m-3 { + margin: 16px !important; +} + +.mt-3, +.my-3 { + margin-top: 16px !important; +} + +.mr-3, +.mx-3 { + margin-right: 16px !important; +} + +.mb-3, +.my-3 { + margin-bottom: 16px !important; +} + +.ml-3, +.mx-3 { + margin-left: 16px !important; +} + +.m-4 { + margin: 24px !important; +} + +.mt-4, +.my-4 { + margin-top: 24px !important; +} + +.mr-4, +.mx-4 { + margin-right: 24px !important; +} + +.mb-4, +.my-4 { + margin-bottom: 24px !important; +} + +.ml-4, +.mx-4 { + margin-left: 24px !important; +} + +.m-5 { + margin: 48px !important; +} + +.mt-5, +.my-5 { + margin-top: 48px !important; +} + +.mr-5, +.mx-5 { + margin-right: 48px !important; +} + +.mb-5, +.my-5 { + margin-bottom: 48px !important; +} + +.ml-5, +.mx-5 { + margin-left: 48px !important; +} + +/* padding */ +.p-1 { + padding: 4px !important; +} + +.pt-1, +.py-1 { + padding-top: 4px !important; +} + +.pr-1, +.px-1 { + padding-right: 4px !important; +} + +.pb-1, +.py-1 { + padding-bottom: 4px !important; +} + +.pl-1, +.px-1 { + padding-left: 4px !important; +} + +.p-2 { + padding: 8px !important; +} + +.pt-2, +.py-2 { + padding-top: 8px !important; +} + +.pr-2, +.px-2 { + padding-right: 8px !important; +} + +.pb-2, +.py-2 { + padding-bottom: 8px !important; +} + +.pl-2, +.px-2 { + padding-left: 8px !important; +} + +.p-3 { + padding: 16px !important; +} + +.pt-3, +.py-3 { + padding-top: 16px !important; +} + +.pr-3, +.px-3 { + padding-right: 16px !important; +} + +.pb-3, +.py-3 { + padding-bottom: 16px !important; +} + +.pl-3, +.px-3 { + padding-left: 16px !important; +} + +.p-4 { + padding: 24px !important; +} + +.pt-4, +.py-4 { + padding-top: 24px !important; +} + +.pr-4, +.px-4 { + padding-right: 24px !important; +} + +.pb-4, +.py-4 { + padding-bottom: 24px !important; +} + +.pl-4, +.px-4 { + padding-left: 24px !important; +} + +.p-5 { + padding: 48px !important; +} + +.pt-5, +.py-5 { + padding-top: 48px !important; +} + +.pr-5, +.px-5 { + padding-right: 48px !important; +} + +.pb-5, +.py-5 { + padding-bottom: 48px !important; +} + +.pl-5, +.px-5 { + padding-left: 48px !important; +} + +.nav-link { + padding: 8px 16px; +} +.navbar { + padding: 8px 16px; +} +.navbar-brand { + padding-top: 5px; + padding-bottom: 5px; + margin-right: 16px; + font-size: 20px; + float: left; +} +.navbar-dark .navbar-divider { + background-color: #fff; +} +.navbar-dark .navbar-nav .nav-link, +.navbar-dark .navbar-nav .nav-link:focus { + color: #bbb; +} +.navbar-dark .navbar-nav .nav-link:hover { + color: #ddd; +} +.navbar-dark .active .nav-link { + color: #fff; +} + +.navbar-light .navbar-nav .nav-link { + color: #555; +} +.navbar-light .navbar-nav .nav-link:hover { + color: #111; +} + +.navbar-divider { + padding-top: 6.8px; + padding-bottom: 6.8px; + margin-right: 16px; + margin-left: 16px; +} +.navbar-nav .nav-link { + padding-top: 6.8px; + padding-bottom: 6.8px; +} +.navbar-text { + padding-top: 8px; + padding-bottom: 8px; +} +.navbar-toggler { + padding: 8px 12px; + font-size: 20px; +} +.navbar-toggleable-xl .navbar-nav .nav-link { + padding-right: 8px; + padding-left: 8px; +} + +.page-link { + padding: 8px 12px; + max-width: 40px; + float: left; +} +.pagination { + margin-top: 16px; + margin-bottom: 16px; +} + +.pagnination:after { + content: ""; + display: table; + clear: both; +} + +.pagination-lg .page-link { + padding: 12px 24px; + font-size: 20px; +} +.pagination-sm .page-link { + padding: 4.4px 12px; + font-size: 14px; +} + +.popover { + font-size: 14px; + border: 1px solid #ddd; +} +.popover-body { + padding: 8px 12px; +} +.popover-header { + font-size: 16px; +} + +.progress { + height: 16px; + margin-bottom: 16px; +} +.progress-bar { + float: left; + font-size: 12px; + line-height: 20px; + width: 0; + text-align: center; + height: 100%; +} + +/** tables **/ +.table { + margin-bottom: 16px; +} +.table th, +.table td { + padding: 12px; +} +.table-active > th, +.table-active > td { + background-color: #dadada; +} +.table-sm th, +.table-sm td { + padding: 5px; +} +.table-responsive { + min-height: 0%; +} + +.tooltip { + font-size: 14px; + filter: alpha(opacity=0); +} +.tooltip.show { + filter: alpha(opacity=90); +} + +.text-black-50 { + color: #000 !important; + filter: alpha(opacity=50) !important; +} +.text-white-50 { + color: #fff !important; + filter: alpha(opacity=50) !important; +} + +/** columns **/ +.col-1, +.col-sm-1, +.col-md-1, +.col-lg-1 { + width: 8.333333%; +} +.col-2, +.col-sm-2, +.col-md-2, +.col-lg-2 { + width: 16.666667%; +} +.col-3, +.col-sm-3, +.col-md-3, +.col-lg-3 { + width: 25%; +} +.col-4, +.col-sm-4, +.col-md-4, +.col-lg-4 { + width: 33.333333%; +} +.col-5, +.col-sm-5, +.col-md-5, +.col-lg-5 { + width: 41.666667%; +} +.col-6, +.col-sm-6, +.col-md-6, +.col-lg-6 { + width: 50%; +} +.col-7, +.col-sm-7, +.col-md-7, +.col-lg-7 { + width: 58.333333%; +} +.col-8, +.col-sm-8, +.col-md-8, +.col-lg-8 { + width: 66.666667%; +} +.col-9, +.col-sm-9, +.col-md-9, +.col-lg-9 { + width: 75%; +} +.col-10, +.col-sm-10, +.col-md-10, +.col-lg-10 { + width: 83.333333%; +} +.col-11, +.col-sm-11, +.col-md-11, +.col-lg-11 { + width: 91.666667%; +} +.col-12, +.col-sm-12, +.col-md-12, +.col-lg-12 { + width: 100%; +} + +.col-md-1 { + max-width: 8.333333% !important; +} + +.col-md-2 { + max-width: 16.666667% !important; +} + +.col-md-3 { + max-width: 25% !important; +} + +.col-md-4 { + max-width: 33.333333% !important; +} + +.col-md-5 { + max-width: 41.666667% !important; +} + +.col-md-6 { + max-width: 50% !important; +} + +.col-md-7 { + max-width: 58.333333% !important; +} + +.col-md-8 { + max-width: 66.666667% !important; +} + +.col-md-9 { + max-width: 75% !important; +} + +.col-md-10 { + max-width: 83.333333% !important; +} + +.col-md-11 { + max-width: 91.666667% !important; +} + +/** embed responsive **/ +.embed-responsive:before { + display: block; + content: ""; +} +.embed-responsive-21by9:before { + padding-top: 42.857143%; +} + +.embed-responsive-16by9:before { + padding-top: 56.25%; +} + +.embed-responsive-4by3:before { + padding-top: 75%; +} + +.embed-responsive-1by1:before { + padding-top: 100%; +} + +/** Flexbox fallback **/ +.card-group .card, +.col-1, +.col-2, +.col-3, +.col-4, +.col-5, +.col-6, +.col-7, +.col-8, +.col-9, +.col-10, +.col-11, +.col-12, +.col-sm-1, +.col-sm-2, +.col-sm-3, +.col-sm-4, +.col-sm-5, +.col-sm-6, +.col-sm-7, +.col-sm-8, +.col-sm-9, +.col-sm-10, +.col-sm-11, +.col-sm-12, +.col-md-1, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-md-10, +.col-md-11, +.col-md-12, +.col-lg-1, +.col-lg-2, +.col-lg-3, +.col-lg-4, +.col-lg-5, +.col-lg-6, +.col-lg-7, +.col-lg-8, +.col-lg-9, +.col-lg-10, +.col-lg-11, +.col-lg-12, +.col-xl-1, +.col-xl-2, +.col-xl-3, +.col-xl-4, +.col-xl-5, +.col-xl-6, +.col-xl-7, +.col-xl-8, +.col-xl-9, +.col-xl-10, +.col-xl-11, +.col-xl-12, +.nav-link, +.list-group-horizontal, +.list-group-horizontal .list-group-item { + float: left; +} + +.row, +.container-fluid, +.container, +section, +footer, +aside { + clear: both; + display: block; + max-width: 992px; +} + +/** All media-queries (min-width:576px) **/ +.float-sm-left { + float: left !important; +} +.float-sm-right { + float: right !important; +} +.float-sm-none { + float: none !important; +} +.d-sm-none { + display: none !important; +} +.d-sm-inline { + display: inline !important; +} +.d-sm-inline-block { + display: inline-block !important; +} +.d-sm-block { + display: block !important; +} +.d-sm-table { + display: table !important; +} +.d-sm-table-cell { + display: table-cell !important; +} +.card-deck { + margin-right: -15px; + margin-left: -15px; +} +.card-deck .card { + margin-right: 15px; + margin-left: 15px; +} +.card-columns .card { + display: inline-block; + width: 100%; +} +.col-sm { + max-width: 100%; +} +.col-sm-auto { + width: auto; + max-width: none; +} +.d-flex, +.d-sm-flex, +.d-md-flex, +.d-lg-flex, +.d-xl-flex, +.d-print-flex { + display: block !important; +} +.d-inline-flex, +.d-sm-inline-flex, +.d-md-inline-flex, +.d-lg-inline-flex, +.d-xl-inline-flex, +.d-print-inline-flex { + display: inline-block !important; +} + +/** All media-queries (min-width:768px) **/ +.d-md-none { + display: none !important; +} +.d-md-inline { + display: inline !important; +} +.d-md-inline-block { + display: inline-block !important; +} +.d-md-block { + display: block !important; +} +.d-md-table { + display: table !important; +} +.d-md-table-cell { + display: table-cell !important; +} +.float-md-left { + float: left !important; +} +.float-md-right { + float: right !important; +} +.float-md-none { + float: none !important; +} +.col-md { + max-width: 100%; +} +.col-md-auto { + width: auto; + max-width: none; +} + +.m-md-1 { + margin: 4px !important; +} + +.mt-md-1, +.my-md-1 { + margin-top: 4px !important; +} + +.mr-md-1, +.mx-md-1 { + margin-right: 4px !important; +} + +.mb-md-1, +.my-md-1 { + margin-bottom: 4px !important; +} + +.ml-md-1, +.mx-md-1 { + margin-left: 4px !important; +} + +.m-md-2 { + margin: 8px !important; +} + +.mt-md-2, +.my-md-2 { + margin-top: 8px !important; +} + +.mr-md-2, +.mx-md-2 { + margin-right: 8px !important; +} + +.mb-md-2, +.my-md-2 { + margin-bottom: 8px !important; +} + +.ml-md-2, +.mx-md-2 { + margin-left: 8px !important; +} + +.m-md-3 { + margin: 16px !important; +} + +.mt-md-3, +.my-md-3 { + margin-top: 16px !important; +} + +.mr-md-3, +.mx-md-3 { + margin-right: 16px !important; +} + +.mb-md-3, +.my-md-3 { + margin-bottom: 16px !important; +} + +.ml-md-3, +.mx-md-3 { + margin-left: 16px !important; +} + +.m-md-4 { + margin: 24px !important; +} + +.mt-md-4, +.my-md-4 { + margin-top: 24px !important; +} + +.mr-md-4, +.mx-md-4 { + margin-right: 24px !important; +} + +.mb-md-4, +.my-md-4 { + margin-bottom: 24px !important; +} + +.ml-md-4, +.mx-md-4 { + margin-left: 24px !important; +} + +.m-md-5 { + margin: 48px !important; +} + +.mt-md-5, +.my-md-5 { + margin-top: 48px !important; +} + +.mr-md-5, +.mx-md-5 { + margin-right: 48px !important; +} + +.mb-md-5, +.my-md-5 { + margin-bottom: 48px !important; +} + +.ml-md-5, +.mx-md-5 { + margin-left: 48px !important; +} + +/** All media-queries (min-width:992px) **/ +.container { + max-width: 960px; +} +.col-lg { + max-width: 100%; +} +.col-lg-auto { + width: auto; + max-width: none; +} +.navbar-expand .navbar-nav .dropdown-menu, +.navbar-expand-xl .navbar-nav .dropdown-menu, +.navbar-expand-lg .navbar-nav .dropdown-menu, +.navbar-expand-md .navbar-nav .dropdown-menu, +.navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute; +} +.navbar-expand .navbar-nav .dropdown-menu-right, +.navbar-expand-xl .navbar-nav .dropdown-menu-right, +.navbar-expand-lg .navbar-nav .dropdown-menu-right, +.navbar-expand-md .navbar-nav .dropdown-menu-right, +.navbar-expand-sm .navbar-nav .dropdown-menu-right { + right: 0; + left: auto; +} +.navbar-expand .navbar-nav .nav-link, +.navbar-expand-xl .navbar-nav .nav-link, +.navbar-expand-lg .navbar-nav .nav-link, +.navbar-expand-md .navbar-nav .nav-link, +.navbar-expand-sm .navbar-nav .nav-link { + padding-right: 8px; + padding-left: 8px; +} +.navbar-expand .navbar-toggler, +.navbar-expand-xl .navbar-toggler, +.navbar-expand-lg .navbar-toggler, +.navbar-expand-md .navbar-toggler, +.navbar-expand-sm .navbar-toggler { + display: none; +} +.modal-dialog { + max-width: 500px; + margin: 28px auto; +} +.modal-lg { + max-width: 800px; +} +.modal-sm { + max-width: 300px; +} +.modal-xl { + max-width: 978px; +} +.d-lg-none { + display: none !important; +} +.d-lg-inline { + display: inline !important; +} +.d-lg-inline-block { + display: inline-block !important; +} +.d-lg-block { + display: block !important; +} +.d-lg-table { + display: table !important; +} +.d-lg-table-cell { + display: table-cell !important; +} +.float-lg-left { + float: left !important; +} +.float-lg-right { + float: right !important; +} +.float-lg-none { + float: none !important; +} +.m-lg-1 { + margin: 4px !important; +} +.mt-lg-1 { + margin-top: 4px !important; +} +.mr-lg-1 { + margin-right: 4px !important; +} +.mb-lg-1 { + margin-bottom: 4px !important; +} +.ml-lg-1 { + margin-left: 4px !important; +} +.mx-lg-1 { + margin-right: 4px !important; + margin-left: 4px !important; +} +.my-lg-1 { + margin-top: 4px !important; + margin-bottom: 4px !important; +} +.m-lg-2 { + margin: 8px !important; +} +.mt-lg-2 { + margin-top: 8px !important; +} +.mr-lg-2 { + margin-right: 8px !important; +} +.mb-lg-2 { + margin-bottom: 8px !important; +} +.ml-lg-2 { + margin-left: 8px !important; +} +.mx-lg-2 { + margin-right: 8px !important; + margin-left: 8px !important; +} +.my-lg-2 { + margin-top: 8px !important; + margin-bottom: 8px !important; +} +.m-lg-3 { + margin: 16px !important; +} +.mt-lg-3 { + margin-top: 16px !important; +} +.mr-lg-3 { + margin-right: 16px !important; +} +.mb-lg-3 { + margin-bottom: 16px !important; +} +.ml-lg-3 { + margin-left: 16px !important; +} +.mx-lg-3 { + margin-right: 16px !important; + margin-left: 16px !important; +} +.my-lg-3 { + margin-top: 16px !important; + margin-bottom: 16px !important; +} +.m-lg-4 { + margin: 24px !important; +} +.mt-lg-4 { + margin-top: 24px !important; +} +.mr-lg-4 { + margin-right: 24px !important; +} +.mb-lg-4 { + margin-bottom: 24px !important; +} +.ml-lg-4 { + margin-left: 24px !important; +} +.mx-lg-4 { + margin-right: 24px !important; + margin-left: 24px !important; +} +.my-lg-4 { + margin-top: 24px !important; + margin-bottom: 24px !important; +} +.m-lg-5 { + margin: 48px !important; +} +.mt-lg-5 { + margin-top: 48px !important; +} +.mr-lg-5 { + margin-right: 48px !important; +} +.mb-lg-5 { + margin-bottom: 48px !important; +} +.ml-lg-5 { + margin-left: 48px !important; +} +.mx-lg-5 { + margin-right: 48px !important; + margin-left: 48px !important; +} +.my-lg-5 { + margin-top: 48px !important; + margin-bottom: 48px !important; +} +.p-lg-1 { + padding: 4px !important; +} +.pt-lg-1 { + padding-top: 4px !important; +} +.pr-lg-1 { + padding-right: 4px !important; +} +.pb-lg-1 { + padding-bottom: 4px !important; +} +.pl-lg-1 { + padding-left: 4px !important; +} +.px-lg-1 { + padding-right: 4px !important; + padding-left: 4px !important; +} +.py-lg-1 { + padding-top: 4px !important; + padding-bottom: 4px !important; +} +.p-lg-2 { + padding: 8px !important; +} +.pt-lg-2 { + padding-top: 8px !important; +} +.pr-lg-2 { + padding-right: 8px !important; +} +.pb-lg-2 { + padding-bottom: 8px !important; +} +.pl-lg-2 { + padding-left: 8px !important; +} +.px-lg-2 { + padding-right: 8px !important; + padding-left: 8px !important; +} +.py-lg-2 { + padding-top: 8px !important; + padding-bottom: 8px !important; +} +.p-lg-3 { + padding: 16px !important; +} +.pt-lg-3 { + padding-top: 16px !important; +} +.pr-lg-3 { + padding-right: 16px !important; +} +.pb-lg-3 { + padding-bottom: 16px !important; +} +.pl-lg-3 { + padding-left: 16px !important; +} +.px-lg-3 { + padding-right: 16px !important; + padding-left: 16px !important; +} +.py-lg-3 { + padding-top: 16px !important; + padding-bottom: 16px !important; +} +.p-lg-4 { + padding: 24px !important; +} +.pt-lg-4 { + padding-top: 24px !important; +} +.pr-lg-4 { + padding-right: 24px !important; +} +.pb-lg-4 { + padding-bottom: 24px !important; +} +.pl-lg-4 { + padding-left: 24px !important; +} +.px-lg-4 { + padding-right: 24px !important; + padding-left: 24px !important; +} +.py-lg-4 { + padding-top: 24px !important; + padding-bottom: 24px !important; +} +.p-lg-5 { + padding: 48px !important; +} +.pt-lg-5 { + padding-top: 48px !important; +} +.pr-lg-5 { + padding-right: 48px !important; +} +.pb-lg-5 { + padding-bottom: 48px !important; +} +.pl-lg-5 { + padding-left: 48px !important; +} +.px-lg-5 { + padding-right: 48px !important; + padding-left: 48px !important; +} +.py-lg-5 { + padding-top: 48px !important; + padding-bottom: 48px !important; +} +.m-lg-auto { + margin: auto !important; +} +.mt-lg-auto { + margin-top: auto !important; +} +.mr-lg-auto { + margin-right: auto !important; +} +.mb-lg-auto { + margin-bottom: auto !important; +} +.ml-lg-auto { + margin-left: auto !important; +} +.mx-lg-auto { + margin-right: auto !important; + margin-left: auto !important; +} +.my-lg-auto { + margin-top: auto !important; + margin-bottom: auto !important; +} +.text-lg-left { + text-align: left !important; +} +.text-lg-right { + text-align: right !important; +} +.text-lg-center { + text-align: center !important; +} + +.navbar-expand-sm .navbar-collapse, +.navbar-expand-md .navbar-collapse, +.navbar-expand-lg .navbar-collapse, +.navbar-expand-xl .navbar-collapse, +.navbar-expand .navbar-collapse { + display: block !important; +} + +.navbar > .container, +.navbar > .container-fluid, +.nav, +.navbar { + display: block; +} diff --git a/Erupe/www/erupe/css/dependencies/bootstrap-ie9.css b/Erupe/www/erupe/css/dependencies/bootstrap-ie9.css new file mode 100644 index 000000000..6f4bef5d5 --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap-ie9.css @@ -0,0 +1,258 @@ +/*! Bootstrap 4 for IE8 - v4.3.1 */ +/*! https://github.com/coliff/bootstrap-ie8 */ + +.card-group .card, +.col-1, +.col-2, +.col-3, +.col-4, +.col-5, +.col-6, +.col-7, +.col-8, +.col-9, +.col-10, +.col-11, +.col-12, +.col-sm-1, +.col-sm-2, +.col-sm-3, +.col-sm-4, +.col-sm-5, +.col-sm-6, +.col-sm-7, +.col-sm-8, +.col-sm-9, +.col-sm-10, +.col-sm-11, +.col-sm-12, +.col-md-1, +.col-md-2, +.col-md-3, +.col-md-4, +.col-md-5, +.col-md-6, +.col-md-7, +.col-md-8, +.col-md-9, +.col-md-10, +.col-md-11, +.col-md-12, +.col-lg-1, +.col-lg-2, +.col-lg-3, +.col-lg-4, +.col-lg-5, +.col-lg-6, +.col-lg-7, +.col-lg-8, +.col-lg-9, +.col-lg-10, +.col-lg-11, +.col-lg-12, +.col-xl-1, +.col-xl-2, +.col-xl-3, +.col-xl-4, +.col-xl-5, +.col-xl-6, +.col-xl-7, +.col-xl-8, +.col-xl-9, +.col-xl-10, +.col-xl-11, +.col-xl-12, +.nav-link, +.list-group-horizontal, +.list-group-horizontal .list-group-item { + float: left; +} +.row, +.container-fluid, +.container, +section, +footer, +main, +aside, +.navbar-nav, +.navbar-collapse { + display: block; +} + +.modal.fade .modal-dialog { + -ms-transform: translate(0, -25%); +} +.modal.show .modal-dialog { + -ms-transform: translate(0, 0); +} +.custom-select { + background-image: none; + padding-right: .75rem; +} +.img-fluid[src$=".svg"] { + width: 100%; +} +.table-responsive { + min-height: 0%; +} /* see https://github.com/twbs/bootstrap/issues/14837 */ +.progress { + display: block; +} +.progress-bar { + float: left; + font-size: 12px; + line-height: 20px; + width: 0; + height: 100%; +} +.d-flex, +.d-sm-flex, +.d-md-flex, +.d-lg-flex, +.d-xl-flex, +.d-print-flex { + display: block !important; +} +.d-inline-flex, +.d-sm-inline-flex, +.d-md-inline-flex, +.d-lg-inline-flex, +.d-xl-inline-flex, +.d-print-inline-flex { + display: inline-block !important; +} +.flex-row .div { + display: inline-block; +} +.flex-row-reverse { + text-align: right; +} +.flex-row-reverse .div { + display: inline-block; + float: right; +} +.justify-content-start div { + display: inline-block; +} +.justify-content-end { + text-align: right; +} +.justify-content-end div { + display: inline-block; + margin-right: 0; + float: right; +} +.justify-content-center { + text-align: center; +} +.justify-content-center div { + display: inline-block; + margin-right: auto; + margin-left: auto; + text-align: center; +} +.justify-content-between { + text-justify: distribute-all-lines; +} +.justify-content-between div { + display: inline-block; + margin-right: auto; + margin-left: auto; + text-align: justify; +} + /* see https://stackoverflow.com/questions/6865194/fluid-width-with-equally-spaced-divs */ +.justify-content-around { + text-align: justify; + text-justify: distribute-all-lines; +} +.justify-content-around div { + display: inline-block; + margin-right: auto; + margin-left: auto; + text-align: justify; +} +[class^="justify-content-"] div { + display: inline-block; +} +/** Carousel - Hide indicators and controls as the carousel doesn't work **/ +.carousel-indicators, +.carousel-control-prev, +.carousel-control-next { + display: none; +} +.btn-link.disabled, +.btn-link:disabled { + text-decoration: none; +} +.modal-header .close { + margin: -48px -16px -16px auto; +} +.btn-group, +.btn-group-vertical { + display: inline; + vertical-align: baseline; +} +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group, +.btn-group-vertical .btn + .btn, +.btn-group-vertical .btn + .btn-group, +.btn-group-vertical .btn-group + .btn, +.btn-group-vertical .btn-group + .btn-group { + margin-left: -5px; +} +.navbar-expand-sm .navbar-collapse, +.navbar-expand-md .navbar-collapse, +.navbar-expand-lg .navbar-collapse, +.navbar-expand-xl .navbar-collapse, +.navbar-expand .navbar-collapse { + display: block !important; +} +.navbar > .container, +.navbar > .container-fluid, +.nav, +.navbar { + display: block; +} +.nav-link { + padding: 8px 16px; +} +.navbar-brand { + padding-top: 5px; + padding-bottom: 5px; + margin-right: 16px; + font-size: 20px; + float: left; +} +.navbar:not(.navbar-expand-sm):not(.navbar-expand-md):not(.navbar-expand-lg):not(.navbar-expand-xl):not(.navbar-expand) + .nav-link { + float: none; +} +.form-group > .is-valid { + border-color: #28a745 !important; +} +.form-group > .is-invalid { + border-color: #dc3545 !important; +} +.form-control.is-valid ~ .valid-feedback, +.custom-select.is-valid ~ .valid-feedback, +.form-control-file.is-valid ~ .valid-feedback, +.form-check-input.is-valid ~ .valid-feedback, +.custom-control-input.is-valid ~ .valid-feedback, +.form-control.is-invalid ~ .invalid-feedback, +.custom-select.is-invalid ~ .invalid-feedback, +.form-control-file.is-invalid ~ .invalid-feedback, +.form-check-input.is-invalid ~ .invalid-feedback, +.custom-file-input.is-invalid ~ .invalid-feedback { + display: block; +} +.form-group > .is-valid:focus { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} +.form-group > .is-invalid:focus { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} +.custom-switch .custom-control-input:checked ~ .custom-control-label:after { + -ms-transform: translateX(0.75rem); +} diff --git a/Erupe/www/erupe/css/dependencies/bootstrap-reboot.css b/Erupe/www/erupe/css/dependencies/bootstrap-reboot.css new file mode 100644 index 000000000..b3d7f4c6a --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap-reboot.css @@ -0,0 +1,331 @@ +/*! + * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) + */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + line-height: 1.15; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + -ms-overflow-style: scrollbar; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +@-ms-viewport { + width: device-width; +} + +article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { + display: block; +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: left; + background-color: #fff; +} + +[tabindex="-1"]:focus { + outline: 0 !important; +} + +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0.5rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title], +abbr[data-original-title] { + text-decoration: underline; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + border-bottom: 0; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: .5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +dfn { + font-style: italic; +} + +b, +strong { + font-weight: bolder; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -.25em; +} + +sup { + top: -.5em; +} + +a { + color: #007bff; + text-decoration: none; + background-color: transparent; + -webkit-text-decoration-skip: objects; +} + +a:hover { + color: #0056b3; + text-decoration: underline; +} + +a:not([href]):not([tabindex]) { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):focus { + outline: 0; +} + +pre, +code, +kbd, +samp { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + font-size: 1em; +} + +pre { + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + -ms-overflow-style: scrollbar; +} + +figure { + margin: 0 0 1rem; +} + +img { + vertical-align: middle; + border-style: none; +} + +svg { + overflow: hidden; + vertical-align: middle; +} + +table { + border-collapse: collapse; +} + +caption { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + color: #6c757d; + text-align: left; + caption-side: bottom; +} + +th { + text-align: inherit; +} + +label { + display: inline-block; + margin-bottom: 0.5rem; +} + +button { + border-radius: 0; +} + +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +input { + overflow: visible; +} + +button, +select { + text-transform: none; +} + +button, +html [type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + padding: 0; + border-style: none; +} + +input[type="radio"], +input[type="checkbox"] { + box-sizing: border-box; + padding: 0; +} + +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + -webkit-appearance: listbox; +} + +textarea { + overflow: auto; + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + max-width: 100%; + padding: 0; + margin-bottom: .5rem; + font-size: 1.5rem; + line-height: inherit; + color: inherit; + white-space: normal; +} + +progress { + vertical-align: baseline; +} + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +[type="search"] { + outline-offset: -2px; + -webkit-appearance: none; +} + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +summary { + display: list-item; + cursor: pointer; +} + +template { + display: none; +} + +[hidden] { + display: none !important; +} +/*# sourceMappingURL=bootstrap-reboot.css.map */ \ No newline at end of file diff --git a/Erupe/www/erupe/css/dependencies/bootstrap-reboot.css.map b/Erupe/www/erupe/css/dependencies/bootstrap-reboot.css.map new file mode 100644 index 000000000..3a17ed962 --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap-reboot.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-reboot.scss","../../scss/_reboot.scss","../../scss/_variables.scss","bootstrap-reboot.css","../../scss/mixins/_hover.scss"],"names":[],"mappings":"AAAA;;;;;;GAMG;ACcH;;;EAGE,uBAAsB;CACvB;;AAED;EACE,wBAAuB;EACvB,kBAAiB;EACjB,+BAA8B;EAC9B,2BAA0B;EAC1B,8BAA6B;EAC7B,8CCZa;CDad;;AAIC;EACE,oBAAmB;CEdtB;;AFoBD;EACE,eAAc;CACf;;AAUD;EACE,UAAS;EACT,sLCgMoM;ED/LpM,gBCoMgC;EDnMhC,iBCwM+B;EDvM/B,iBC2M+B;ED1M/B,eC3CgB;ED4ChB,iBAAgB;EAChB,uBCtDa;CDuDd;;AExBD;EFgCE,sBAAqB;CACtB;;AAQD;EACE,wBAAuB;EACvB,UAAS;EACT,kBAAiB;CAClB;;AAYD;EACE,cAAa;EACb,sBC6KyC;CD5K1C;;AAOD;EACE,cAAa;EACb,oBCkE8B;CDjE/B;;AASD;;EAEE,2BAA0B;EAC1B,0CAAiC;EAAjC,kCAAiC;EACjC,aAAY;EACZ,iBAAgB;CACjB;;AAED;EACE,oBAAmB;EACnB,mBAAkB;EAClB,qBAAoB;CACrB;;AAED;;;EAGE,cAAa;EACb,oBAAmB;CACpB;;AAED;;;;EAIE,iBAAgB;CACjB;;AAED;EACE,iBCgH+B;CD/GhC;;AAED;EACE,qBAAoB;EACpB,eAAc;CACf;;AAED;EACE,iBAAgB;CACjB;;AAED;EACE,mBAAkB;CACnB;;AAGD;;EAEE,oBAAmB;CACpB;;AAGD;EACE,eAAc;CACf;;AAOD;;EAEE,mBAAkB;EAClB,eAAc;EACd,eAAc;EACd,yBAAwB;CACzB;;AAED;EAAM,eAAc;CAAI;;AACxB;EAAM,WAAU;CAAI;;AAOpB;EACE,eC9Je;ED+Jf,sBC/B8B;EDgC9B,8BAA6B;EAC7B,sCAAqC;CAMtC;;AGnMC;EHgME,eCnCgD;EDoChD,2BCnCiC;CE9Jb;;AH2MxB;EACE,eAAc;EACd,sBAAqB;CAUtB;;AGnNC;EH4ME,eAAc;EACd,sBAAqB;CG1MtB;;AHoMH;EAUI,WAAU;CACX;;AAQH;;;;EAIE,kGCagH;EDZhH,eAAc;CACf;;AAED;EAEE,cAAa;EAEb,oBAAmB;EAEnB,eAAc;EAGd,8BAA6B;CAC9B;;AAOD;EAEE,iBAAgB;CACjB;;AAOD;EACE,uBAAsB;EACtB,mBAAkB;CACnB;;AAED;EAGE,iBAAgB;EAChB,uBAAsB;CACvB;;AAOD;EACE,0BAAyB;CAC1B;;AAED;EACE,qBC8BkC;ED7BlC,wBC6BkC;ED5BlC,eCrRgB;EDsRhB,iBAAgB;EAChB,qBAAoB;CACrB;;AAED;EAGE,oBAAmB;CACpB;;AAOD;EAEE,sBAAqB;EACrB,sBC+F2C;CD9F5C;;AAKD;EACE,iBAAgB;CACjB;;AAMD;EACE,oBAAmB;EACnB,2CAA0C;CAC3C;;AAED;;;;;EAKE,UAAS;EACT,qBAAoB;EACpB,mBAAkB;EAClB,qBAAoB;CACrB;;AAED;;EAEE,kBAAiB;CAClB;;AAED;;EAEE,qBAAoB;CACrB;;AAKD;;;;EAIE,2BAA0B;CAC3B;;AAGD;;;;EAIE,WAAU;EACV,mBAAkB;CACnB;;AAED;;EAEE,uBAAsB;EACtB,WAAU;CACX;;AAGD;;;;EASE,4BAA2B;CAC5B;;AAED;EACE,eAAc;EAEd,iBAAgB;CACjB;;AAED;EAME,aAAY;EAEZ,WAAU;EACV,UAAS;EACT,UAAS;CACV;;AAID;EACE,eAAc;EACd,YAAW;EACX,gBAAe;EACf,WAAU;EACV,qBAAoB;EACpB,kBAAiB;EACjB,qBAAoB;EACpB,eAAc;EACd,oBAAmB;CACpB;;AAED;EACE,yBAAwB;CACzB;;AEpID;;EFyIE,aAAY;CACb;;AErID;EF4IE,qBAAoB;EACpB,yBAAwB;CACzB;;AEzID;;EFiJE,yBAAwB;CACzB;;AAOD;EACE,cAAa;EACb,2BAA0B;CAC3B;;AAMD;EACE,sBAAqB;CACtB;;AAED;EACE,mBAAkB;EAClB,gBAAe;CAChB;;AAED;EACE,cAAa;CACd;;AEtJD;EF2JE,yBAAwB;CACzB","file":"bootstrap-reboot.css","sourcesContent":["/*!\n * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so\n// we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n// 6. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -ms-text-size-adjust: 100%; // 4\n -ms-overflow-style: scrollbar; // 5\n -webkit-tap-highlight-color: rgba($black, 0); // 6\n}\n\n// IE10+ doesn't honor `` in some cases.\n@at-root {\n @-ms-viewport {\n width: device-width;\n }\n}\n\n// stylelint-disable selector-list-comma-newline-after\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use the\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n font-size: $font-size-base;\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Remove the bottom border in Firefox 39-.\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Duplicate behavior to the data-* attribute for our tooltip plugin\n\nabbr[title],\nabbr[data-original-title] { // 4\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 1\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic; // Add the correct font style in Android 4.3-\n}\n\n// stylelint-disable font-weight-notation\nb,\nstrong {\n font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n// stylelint-enable font-weight-notation\n\nsmall {\n font-size: 80%; // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n font-size: 1em; // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so\n // we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\nhtml [type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

`s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding and cancel buttons in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n\n//\n// Color system\n//\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-print-styles: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints);\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n\n// Fonts\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: ($font-size-base * 1.25) !default;\n$font-size-sm: ($font-size-base * .875) !default;\n\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: ($spacer / 2) !default;\n$headings-font-family: inherit !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: inherit !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: ($font-size-base * 1.25) !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-font-size: ($font-size-base * 1.25) !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-bg: transparent !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $gray-300 !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-bg: $gray-900 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($gray-900, 7.5%) !default;\n$table-dark-color: $body-bg !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;\n$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default;\n\n$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;\n$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;\n\n$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;\n$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: 1.5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $gray-300 !default;\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-control-indicator-disabled-bg: $gray-200 !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n\n$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-select-padding-y: .375rem !default;\n$custom-select-padding-x: .75rem !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-line-height: $input-btn-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-select-border-width: $input-btn-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-btn-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width rgba($custom-select-focus-border-color, .5) !default;\n\n$custom-select-font-size-sm: 75% !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-font-size-lg: 125% !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-btn-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-btn-padding-y !default;\n$custom-file-padding-x: $input-btn-padding-x !default;\n$custom-file-line-height: $input-btn-line-height !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-btn-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: ($spacer / 2) !default;\n\n// Navbar\n\n$navbar-padding-y: ($spacer / 2) !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: ($grid-gutter-width / 2) !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $gray-200 !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding: 1rem !default;\n\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: ($font-size-base * .75) !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n// List group\n\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$carousel-transition: transform .6s ease !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Printing\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","/*!\n * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -ms-overflow-style: scrollbar;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n@-ms-viewport {\n width: device-width;\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n -webkit-text-decoration-skip: objects;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n"]} \ No newline at end of file diff --git a/Erupe/www/erupe/css/dependencies/bootstrap-reboot.min.css b/Erupe/www/erupe/css/dependencies/bootstrap-reboot.min.css new file mode 100644 index 000000000..402715d5d --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap-reboot.min.css @@ -0,0 +1,8 @@ +/*! + * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) + */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} +/*# sourceMappingURL=bootstrap-reboot.min.css.map */ \ No newline at end of file diff --git a/Erupe/www/erupe/css/dependencies/bootstrap-reboot.min.css.map b/Erupe/www/erupe/css/dependencies/bootstrap-reboot.min.css.map new file mode 100644 index 000000000..2d7932cdb --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap-reboot.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap-reboot.scss","../../scss/_reboot.scss","dist/css/bootstrap-reboot.css","bootstrap-reboot.css","../../scss/mixins/_hover.scss"],"names":[],"mappings":"AAAA;;;;;;ACoBA,ECXA,QADA,SDeE,WAAA,WAGF,KACE,YAAA,WACA,YAAA,KACA,yBAAA,KACA,qBAAA,KACA,mBAAA,UACA,4BAAA,YAKA,cACE,MAAA,aAMJ,QAAA,MAAA,WAAA,OAAA,OAAA,OAAA,OAAA,KAAA,IAAA,QACE,QAAA,MAWF,KACE,OAAA,EACA,YAAA,aAAA,CAAA,kBAAA,CAAA,UAAA,CAAA,MAAA,CAAA,gBAAA,CAAA,KAAA,CAAA,UAAA,CAAA,mBAAA,CAAA,gBAAA,CAAA,iBAAA,CAAA,mBACA,UAAA,KACA,YAAA,IACA,YAAA,IACA,MAAA,QACA,WAAA,KACA,iBAAA,KEvBF,sBFgCE,QAAA,YASF,GACE,WAAA,YACA,OAAA,EACA,SAAA,QAaF,GAAA,GAAA,GAAA,GAAA,GAAA,GACE,WAAA,EACA,cAAA,MAQF,EACE,WAAA,EACA,cAAA,KChDF,0BD0DA,YAEE,gBAAA,UACA,wBAAA,UAAA,OAAA,gBAAA,UAAA,OACA,OAAA,KACA,cAAA,EAGF,QACE,cAAA,KACA,WAAA,OACA,YAAA,QCrDF,GDwDA,GCzDA,GD4DE,WAAA,EACA,cAAA,KAGF,MCxDA,MACA,MAFA,MD6DE,cAAA,EAGF,GACE,YAAA,IAGF,GACE,cAAA,MACA,YAAA,EAGF,WACE,OAAA,EAAA,EAAA,KAGF,IACE,WAAA,OAIF,EC1DA,OD4DE,YAAA,OAIF,MACE,UAAA,IAQF,IChEA,IDkEE,SAAA,SACA,UAAA,IACA,YAAA,EACA,eAAA,SAGF,IAAM,OAAA,OACN,IAAM,IAAA,MAON,EACE,MAAA,QACA,gBAAA,KACA,iBAAA,YACA,6BAAA,QG7LA,QHgME,MAAA,QACA,gBAAA,UAUJ,8BACE,MAAA,QACA,gBAAA,KGzMA,oCAAA,oCH4ME,MAAA,QACA,gBAAA,KANJ,oCAUI,QAAA,EClEJ,KACA,ID0EA,ICzEA,KD6EE,YAAA,cAAA,CAAA,KAAA,CAAA,MAAA,CAAA,QAAA,CAAA,iBAAA,CAAA,aAAA,CAAA,UACA,UAAA,IAGF,IAEE,WAAA,EAEA,cAAA,KAEA,SAAA,KAGA,mBAAA,UAQF,OAEE,OAAA,EAAA,EAAA,KAQF,IACE,eAAA,OACA,aAAA,KAGF,IAGE,SAAA,OACA,eAAA,OAQF,MACE,gBAAA,SAGF,QACE,YAAA,OACA,eAAA,OACA,MAAA,QACA,WAAA,KACA,aAAA,OAGF,GAGE,WAAA,QAQF,MAEE,QAAA,aACA,cAAA,MAMF,OACE,cAAA,EAOF,aACE,QAAA,IAAA,OACA,QAAA,IAAA,KAAA,yBC9GF,ODiHA,MC/GA,SADA,OAEA,SDmHE,OAAA,EACA,YAAA,QACA,UAAA,QACA,YAAA,QAGF,OCjHA,MDmHE,SAAA,QAGF,OCjHA,ODmHE,eAAA,KC7GF,aACA,cDkHA,OCpHA,mBDwHE,mBAAA,OCjHF,gCACA,+BACA,gCDmHA,yBAIE,QAAA,EACA,aAAA,KClHF,qBDqHA,kBAEE,WAAA,WACA,QAAA,EAIF,iBCrHA,2BACA,kBAFA,iBD+HE,mBAAA,QAGF,SACE,SAAA,KAEA,OAAA,SAGF,SAME,UAAA,EAEA,QAAA,EACA,OAAA,EACA,OAAA,EAKF,OACE,QAAA,MACA,MAAA,KACA,UAAA,KACA,QAAA,EACA,cAAA,MACA,UAAA,OACA,YAAA,QACA,MAAA,QACA,YAAA,OAGF,SACE,eAAA,SEnIF,yCDEA,yCDuIE,OAAA,KEpIF,cF4IE,eAAA,KACA,mBAAA,KExIF,4CDEA,yCD+IE,mBAAA,KAQF,6BACE,KAAA,QACA,mBAAA,OAOF,OACE,QAAA,aAGF,QACE,QAAA,UACA,OAAA,QAGF,SACE,QAAA,KErJF,SF2JE,QAAA","sourcesContent":["/*!\n * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"reboot\";\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so\n// we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n// 6. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -ms-text-size-adjust: 100%; // 4\n -ms-overflow-style: scrollbar; // 5\n -webkit-tap-highlight-color: rgba($black, 0); // 6\n}\n\n// IE10+ doesn't honor `` in some cases.\n@at-root {\n @-ms-viewport {\n width: device-width;\n }\n}\n\n// stylelint-disable selector-list-comma-newline-after\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use the\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n font-size: $font-size-base;\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Remove the bottom border in Firefox 39-.\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Duplicate behavior to the data-* attribute for our tooltip plugin\n\nabbr[title],\nabbr[data-original-title] { // 4\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 1\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic; // Add the correct font style in Android 4.3-\n}\n\n// stylelint-disable font-weight-notation\nb,\nstrong {\n font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n// stylelint-enable font-weight-notation\n\nsmall {\n font-size: 80%; // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n font-size: 1em; // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so\n // we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\nhtml [type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

`s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding and cancel buttons in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","/*!\n * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -ms-overflow-style: scrollbar;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n@-ms-viewport {\n width: device-width;\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n -webkit-text-decoration-skip: objects;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n/*# sourceMappingURL=bootstrap-reboot.css.map */","/*!\n * Bootstrap Reboot v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)\n */\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -ms-overflow-style: scrollbar;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n@-ms-viewport {\n width: device-width;\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n -webkit-text-decoration-skip: objects;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\n/*# sourceMappingURL=bootstrap-reboot.css.map */","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n"]} \ No newline at end of file diff --git a/Erupe/www/erupe/css/dependencies/bootstrap.css b/Erupe/www/erupe/css/dependencies/bootstrap.css new file mode 100644 index 000000000..943532db5 --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap.css @@ -0,0 +1,9030 @@ +/*! + * Bootstrap v4.1.3 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors + * Copyright 2011-2018 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +:root { + --blue: #007bff; + --indigo: #6610f2; + --purple: #6f42c1; + --pink: #e83e8c; + --red: #dc3545; + --orange: #fd7e14; + --yellow: #ffc107; + --green: #28a745; + --teal: #20c997; + --cyan: #17a2b8; + --white: #fff; + --gray: #6c757d; + --gray-dark: #343a40; + --primary: #007bff; + --secondary: #6c757d; + --success: #28a745; + --info: #17a2b8; + --warning: #ffc107; + --danger: #dc3545; + --light: #f8f9fa; + --dark: #343a40; + --breakpoint-xs: 0; + --breakpoint-sm: 576px; + --breakpoint-md: 768px; + --breakpoint-lg: 992px; + --breakpoint-xl: 1200px; + --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + line-height: 1.15; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; + -ms-overflow-style: scrollbar; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +@-ms-viewport { + width: device-width; +} + +article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { + display: block; +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: left; + background-color: #fff; +} + +[tabindex="-1"]:focus { + outline: 0 !important; +} + +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 0; + margin-bottom: 0.5rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title], +abbr[data-original-title] { + text-decoration: underline; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + border-bottom: 0; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: .5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +dfn { + font-style: italic; +} + +b, +strong { + font-weight: bolder; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -.25em; +} + +sup { + top: -.5em; +} + +a { + color: #007bff; + text-decoration: none; + background-color: transparent; + -webkit-text-decoration-skip: objects; +} + +a:hover { + color: #0056b3; + text-decoration: underline; +} + +a:not([href]):not([tabindex]) { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):focus { + outline: 0; +} + +pre, +code, +kbd, +samp { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + font-size: 1em; +} + +pre { + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; + -ms-overflow-style: scrollbar; +} + +figure { + margin: 0 0 1rem; +} + +img { + vertical-align: middle; + border-style: none; +} + +svg { + overflow: hidden; + vertical-align: middle; +} + +table { + border-collapse: collapse; +} + +caption { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + color: #6c757d; + text-align: left; + caption-side: bottom; +} + +th { + text-align: inherit; +} + +label { + display: inline-block; + margin-bottom: 0.5rem; +} + +button { + border-radius: 0; +} + +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +input { + overflow: visible; +} + +button, +select { + text-transform: none; +} + +button, +html [type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + padding: 0; + border-style: none; +} + +input[type="radio"], +input[type="checkbox"] { + box-sizing: border-box; + padding: 0; +} + +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + -webkit-appearance: listbox; +} + +textarea { + overflow: auto; + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + max-width: 100%; + padding: 0; + margin-bottom: .5rem; + font-size: 1.5rem; + line-height: inherit; + color: inherit; + white-space: normal; +} + +progress { + vertical-align: baseline; +} + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +[type="search"] { + outline-offset: -2px; + -webkit-appearance: none; +} + +[type="search"]::-webkit-search-cancel-button, +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +summary { + display: list-item; + cursor: pointer; +} + +template { + display: none; +} + +[hidden] { + display: none !important; +} + +h1, h2, h3, h4, h5, h6, +.h1, .h2, .h3, .h4, .h5, .h6 { + margin-bottom: 0.5rem; + font-family: inherit; + font-weight: 500; + line-height: 1.2; + color: inherit; +} + +h1, .h1 { + font-size: 2.5rem; +} + +h2, .h2 { + font-size: 2rem; +} + +h3, .h3 { + font-size: 1.75rem; +} + +h4, .h4 { + font-size: 1.5rem; +} + +h5, .h5 { + font-size: 1.25rem; +} + +h6, .h6 { + font-size: 1rem; +} + +.lead { + font-size: 1.25rem; + font-weight: 300; +} + +.display-1 { + font-size: 6rem; + font-weight: 300; + line-height: 1.2; +} + +.display-2 { + font-size: 5.5rem; + font-weight: 300; + line-height: 1.2; +} + +.display-3 { + font-size: 4.5rem; + font-weight: 300; + line-height: 1.2; +} + +.display-4 { + font-size: 3.5rem; + font-weight: 300; + line-height: 1.2; +} + +hr { + margin-top: 1rem; + margin-bottom: 1rem; + border: 0; + border-top: 1px solid rgba(0, 0, 0, 0.1); +} + +small, +.small { + font-size: 80%; + font-weight: 400; +} + +mark, +.mark { + padding: 0.2em; + background-color: #fcf8e3; +} + +.list-unstyled { + padding-left: 0; + list-style: none; +} + +.list-inline { + padding-left: 0; + list-style: none; +} + +.list-inline-item { + display: inline-block; +} + +.list-inline-item:not(:last-child) { + margin-right: 0.5rem; +} + +.initialism { + font-size: 90%; + text-transform: uppercase; +} + +.blockquote { + margin-bottom: 1rem; + font-size: 1.25rem; +} + +.blockquote-footer { + display: block; + font-size: 80%; + color: #6c757d; +} + +.blockquote-footer::before { + content: "\2014 \00A0"; +} + +.img-fluid { + max-width: 100%; + height: auto; +} + +.img-thumbnail { + padding: 0.25rem; + background-color: #fff; + border: 1px solid #dee2e6; + border-radius: 0.25rem; + max-width: 100%; + height: auto; +} + +.figure { + display: inline-block; +} + +.figure-img { + margin-bottom: 0.5rem; + line-height: 1; +} + +.figure-caption { + font-size: 90%; + color: #6c757d; +} + +code { + font-size: 87.5%; + color: #e83e8c; + word-break: break-word; +} + +a > code { + color: inherit; +} + +kbd { + padding: 0.2rem 0.4rem; + font-size: 87.5%; + color: #fff; + background-color: #212529; + border-radius: 0.2rem; +} + +kbd kbd { + padding: 0; + font-size: 100%; + font-weight: 700; +} + +pre { + display: block; + font-size: 87.5%; + color: #212529; +} + +pre code { + font-size: inherit; + color: inherit; + word-break: normal; +} + +.pre-scrollable { + max-height: 340px; + overflow-y: scroll; +} + +.container { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +@media (min-width: 576px) { + .container { + max-width: 540px; + } +} + +@media (min-width: 768px) { + .container { + max-width: 720px; + } +} + +@media (min-width: 992px) { + .container { + max-width: 960px; + } +} + +@media (min-width: 1200px) { + .container { + max-width: 1140px; + } +} + +.container-fluid { + width: 100%; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; +} + +.row { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -15px; + margin-left: -15px; +} + +.no-gutters { + margin-right: 0; + margin-left: 0; +} + +.no-gutters > .col, +.no-gutters > [class*="col-"] { + padding-right: 0; + padding-left: 0; +} + +.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col, +.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm, +.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md, +.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg, +.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl, +.col-xl-auto { + position: relative; + width: 100%; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; +} + +.col { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; +} + +.col-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; +} + +.col-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; +} + +.col-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; +} + +.col-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; +} + +.col-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; +} + +.col-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; +} + +.col-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; +} + +.col-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; +} + +.col-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; +} + +.col-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; +} + +.col-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; +} + +.col-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; +} + +.col-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; +} + +.order-first { + -ms-flex-order: -1; + order: -1; +} + +.order-last { + -ms-flex-order: 13; + order: 13; +} + +.order-0 { + -ms-flex-order: 0; + order: 0; +} + +.order-1 { + -ms-flex-order: 1; + order: 1; +} + +.order-2 { + -ms-flex-order: 2; + order: 2; +} + +.order-3 { + -ms-flex-order: 3; + order: 3; +} + +.order-4 { + -ms-flex-order: 4; + order: 4; +} + +.order-5 { + -ms-flex-order: 5; + order: 5; +} + +.order-6 { + -ms-flex-order: 6; + order: 6; +} + +.order-7 { + -ms-flex-order: 7; + order: 7; +} + +.order-8 { + -ms-flex-order: 8; + order: 8; +} + +.order-9 { + -ms-flex-order: 9; + order: 9; +} + +.order-10 { + -ms-flex-order: 10; + order: 10; +} + +.order-11 { + -ms-flex-order: 11; + order: 11; +} + +.order-12 { + -ms-flex-order: 12; + order: 12; +} + +.offset-1 { + margin-left: 8.333333%; +} + +.offset-2 { + margin-left: 16.666667%; +} + +.offset-3 { + margin-left: 25%; +} + +.offset-4 { + margin-left: 33.333333%; +} + +.offset-5 { + margin-left: 41.666667%; +} + +.offset-6 { + margin-left: 50%; +} + +.offset-7 { + margin-left: 58.333333%; +} + +.offset-8 { + margin-left: 66.666667%; +} + +.offset-9 { + margin-left: 75%; +} + +.offset-10 { + margin-left: 83.333333%; +} + +.offset-11 { + margin-left: 91.666667%; +} + +@media (min-width: 576px) { + .col-sm { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-sm-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-sm-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-sm-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-sm-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-sm-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-sm-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-sm-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-sm-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-sm-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-sm-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-sm-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-sm-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-sm-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-sm-first { + -ms-flex-order: -1; + order: -1; + } + .order-sm-last { + -ms-flex-order: 13; + order: 13; + } + .order-sm-0 { + -ms-flex-order: 0; + order: 0; + } + .order-sm-1 { + -ms-flex-order: 1; + order: 1; + } + .order-sm-2 { + -ms-flex-order: 2; + order: 2; + } + .order-sm-3 { + -ms-flex-order: 3; + order: 3; + } + .order-sm-4 { + -ms-flex-order: 4; + order: 4; + } + .order-sm-5 { + -ms-flex-order: 5; + order: 5; + } + .order-sm-6 { + -ms-flex-order: 6; + order: 6; + } + .order-sm-7 { + -ms-flex-order: 7; + order: 7; + } + .order-sm-8 { + -ms-flex-order: 8; + order: 8; + } + .order-sm-9 { + -ms-flex-order: 9; + order: 9; + } + .order-sm-10 { + -ms-flex-order: 10; + order: 10; + } + .order-sm-11 { + -ms-flex-order: 11; + order: 11; + } + .order-sm-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-sm-0 { + margin-left: 0; + } + .offset-sm-1 { + margin-left: 8.333333%; + } + .offset-sm-2 { + margin-left: 16.666667%; + } + .offset-sm-3 { + margin-left: 25%; + } + .offset-sm-4 { + margin-left: 33.333333%; + } + .offset-sm-5 { + margin-left: 41.666667%; + } + .offset-sm-6 { + margin-left: 50%; + } + .offset-sm-7 { + margin-left: 58.333333%; + } + .offset-sm-8 { + margin-left: 66.666667%; + } + .offset-sm-9 { + margin-left: 75%; + } + .offset-sm-10 { + margin-left: 83.333333%; + } + .offset-sm-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 768px) { + .col-md { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-md-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-md-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-md-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-md-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-md-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-md-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-md-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-md-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-md-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-md-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-md-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-md-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-md-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-md-first { + -ms-flex-order: -1; + order: -1; + } + .order-md-last { + -ms-flex-order: 13; + order: 13; + } + .order-md-0 { + -ms-flex-order: 0; + order: 0; + } + .order-md-1 { + -ms-flex-order: 1; + order: 1; + } + .order-md-2 { + -ms-flex-order: 2; + order: 2; + } + .order-md-3 { + -ms-flex-order: 3; + order: 3; + } + .order-md-4 { + -ms-flex-order: 4; + order: 4; + } + .order-md-5 { + -ms-flex-order: 5; + order: 5; + } + .order-md-6 { + -ms-flex-order: 6; + order: 6; + } + .order-md-7 { + -ms-flex-order: 7; + order: 7; + } + .order-md-8 { + -ms-flex-order: 8; + order: 8; + } + .order-md-9 { + -ms-flex-order: 9; + order: 9; + } + .order-md-10 { + -ms-flex-order: 10; + order: 10; + } + .order-md-11 { + -ms-flex-order: 11; + order: 11; + } + .order-md-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-md-0 { + margin-left: 0; + } + .offset-md-1 { + margin-left: 8.333333%; + } + .offset-md-2 { + margin-left: 16.666667%; + } + .offset-md-3 { + margin-left: 25%; + } + .offset-md-4 { + margin-left: 33.333333%; + } + .offset-md-5 { + margin-left: 41.666667%; + } + .offset-md-6 { + margin-left: 50%; + } + .offset-md-7 { + margin-left: 58.333333%; + } + .offset-md-8 { + margin-left: 66.666667%; + } + .offset-md-9 { + margin-left: 75%; + } + .offset-md-10 { + margin-left: 83.333333%; + } + .offset-md-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 992px) { + .col-lg { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-lg-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-lg-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-lg-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-lg-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-lg-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-lg-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-lg-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-lg-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-lg-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-lg-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-lg-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-lg-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-lg-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-lg-first { + -ms-flex-order: -1; + order: -1; + } + .order-lg-last { + -ms-flex-order: 13; + order: 13; + } + .order-lg-0 { + -ms-flex-order: 0; + order: 0; + } + .order-lg-1 { + -ms-flex-order: 1; + order: 1; + } + .order-lg-2 { + -ms-flex-order: 2; + order: 2; + } + .order-lg-3 { + -ms-flex-order: 3; + order: 3; + } + .order-lg-4 { + -ms-flex-order: 4; + order: 4; + } + .order-lg-5 { + -ms-flex-order: 5; + order: 5; + } + .order-lg-6 { + -ms-flex-order: 6; + order: 6; + } + .order-lg-7 { + -ms-flex-order: 7; + order: 7; + } + .order-lg-8 { + -ms-flex-order: 8; + order: 8; + } + .order-lg-9 { + -ms-flex-order: 9; + order: 9; + } + .order-lg-10 { + -ms-flex-order: 10; + order: 10; + } + .order-lg-11 { + -ms-flex-order: 11; + order: 11; + } + .order-lg-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-lg-0 { + margin-left: 0; + } + .offset-lg-1 { + margin-left: 8.333333%; + } + .offset-lg-2 { + margin-left: 16.666667%; + } + .offset-lg-3 { + margin-left: 25%; + } + .offset-lg-4 { + margin-left: 33.333333%; + } + .offset-lg-5 { + margin-left: 41.666667%; + } + .offset-lg-6 { + margin-left: 50%; + } + .offset-lg-7 { + margin-left: 58.333333%; + } + .offset-lg-8 { + margin-left: 66.666667%; + } + .offset-lg-9 { + margin-left: 75%; + } + .offset-lg-10 { + margin-left: 83.333333%; + } + .offset-lg-11 { + margin-left: 91.666667%; + } +} + +@media (min-width: 1200px) { + .col-xl { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + max-width: 100%; + } + .col-xl-auto { + -ms-flex: 0 0 auto; + flex: 0 0 auto; + width: auto; + max-width: none; + } + .col-xl-1 { + -ms-flex: 0 0 8.333333%; + flex: 0 0 8.333333%; + max-width: 8.333333%; + } + .col-xl-2 { + -ms-flex: 0 0 16.666667%; + flex: 0 0 16.666667%; + max-width: 16.666667%; + } + .col-xl-3 { + -ms-flex: 0 0 25%; + flex: 0 0 25%; + max-width: 25%; + } + .col-xl-4 { + -ms-flex: 0 0 33.333333%; + flex: 0 0 33.333333%; + max-width: 33.333333%; + } + .col-xl-5 { + -ms-flex: 0 0 41.666667%; + flex: 0 0 41.666667%; + max-width: 41.666667%; + } + .col-xl-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; + } + .col-xl-7 { + -ms-flex: 0 0 58.333333%; + flex: 0 0 58.333333%; + max-width: 58.333333%; + } + .col-xl-8 { + -ms-flex: 0 0 66.666667%; + flex: 0 0 66.666667%; + max-width: 66.666667%; + } + .col-xl-9 { + -ms-flex: 0 0 75%; + flex: 0 0 75%; + max-width: 75%; + } + .col-xl-10 { + -ms-flex: 0 0 83.333333%; + flex: 0 0 83.333333%; + max-width: 83.333333%; + } + .col-xl-11 { + -ms-flex: 0 0 91.666667%; + flex: 0 0 91.666667%; + max-width: 91.666667%; + } + .col-xl-12 { + -ms-flex: 0 0 100%; + flex: 0 0 100%; + max-width: 100%; + } + .order-xl-first { + -ms-flex-order: -1; + order: -1; + } + .order-xl-last { + -ms-flex-order: 13; + order: 13; + } + .order-xl-0 { + -ms-flex-order: 0; + order: 0; + } + .order-xl-1 { + -ms-flex-order: 1; + order: 1; + } + .order-xl-2 { + -ms-flex-order: 2; + order: 2; + } + .order-xl-3 { + -ms-flex-order: 3; + order: 3; + } + .order-xl-4 { + -ms-flex-order: 4; + order: 4; + } + .order-xl-5 { + -ms-flex-order: 5; + order: 5; + } + .order-xl-6 { + -ms-flex-order: 6; + order: 6; + } + .order-xl-7 { + -ms-flex-order: 7; + order: 7; + } + .order-xl-8 { + -ms-flex-order: 8; + order: 8; + } + .order-xl-9 { + -ms-flex-order: 9; + order: 9; + } + .order-xl-10 { + -ms-flex-order: 10; + order: 10; + } + .order-xl-11 { + -ms-flex-order: 11; + order: 11; + } + .order-xl-12 { + -ms-flex-order: 12; + order: 12; + } + .offset-xl-0 { + margin-left: 0; + } + .offset-xl-1 { + margin-left: 8.333333%; + } + .offset-xl-2 { + margin-left: 16.666667%; + } + .offset-xl-3 { + margin-left: 25%; + } + .offset-xl-4 { + margin-left: 33.333333%; + } + .offset-xl-5 { + margin-left: 41.666667%; + } + .offset-xl-6 { + margin-left: 50%; + } + .offset-xl-7 { + margin-left: 58.333333%; + } + .offset-xl-8 { + margin-left: 66.666667%; + } + .offset-xl-9 { + margin-left: 75%; + } + .offset-xl-10 { + margin-left: 83.333333%; + } + .offset-xl-11 { + margin-left: 91.666667%; + } +} + +.table { + width: 100%; + margin-bottom: 1rem; + background-color: transparent; +} + +.table th, +.table td { + padding: 0.75rem; + vertical-align: top; + border-top: 1px solid #dee2e6; +} + +.table thead th { + vertical-align: bottom; + border-bottom: 2px solid #dee2e6; +} + +.table tbody + tbody { + border-top: 2px solid #dee2e6; +} + +.table .table { + background-color: #fff; +} + +.table-sm th, +.table-sm td { + padding: 0.3rem; +} + +.table-bordered { + border: 1px solid #dee2e6; +} + +.table-bordered th, +.table-bordered td { + border: 1px solid #dee2e6; +} + +.table-bordered thead th, +.table-bordered thead td { + border-bottom-width: 2px; +} + +.table-borderless th, +.table-borderless td, +.table-borderless thead th, +.table-borderless tbody + tbody { + border: 0; +} + +.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(0, 0, 0, 0.05); +} + +.table-hover tbody tr:hover { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-primary, +.table-primary > th, +.table-primary > td { + background-color: #b8daff; +} + +.table-hover .table-primary:hover { + background-color: #9fcdff; +} + +.table-hover .table-primary:hover > td, +.table-hover .table-primary:hover > th { + background-color: #9fcdff; +} + +.table-secondary, +.table-secondary > th, +.table-secondary > td { + background-color: #d6d8db; +} + +.table-hover .table-secondary:hover { + background-color: #c8cbcf; +} + +.table-hover .table-secondary:hover > td, +.table-hover .table-secondary:hover > th { + background-color: #c8cbcf; +} + +.table-success, +.table-success > th, +.table-success > td { + background-color: #c3e6cb; +} + +.table-hover .table-success:hover { + background-color: #b1dfbb; +} + +.table-hover .table-success:hover > td, +.table-hover .table-success:hover > th { + background-color: #b1dfbb; +} + +.table-info, +.table-info > th, +.table-info > td { + background-color: #bee5eb; +} + +.table-hover .table-info:hover { + background-color: #abdde5; +} + +.table-hover .table-info:hover > td, +.table-hover .table-info:hover > th { + background-color: #abdde5; +} + +.table-warning, +.table-warning > th, +.table-warning > td { + background-color: #ffeeba; +} + +.table-hover .table-warning:hover { + background-color: #ffe8a1; +} + +.table-hover .table-warning:hover > td, +.table-hover .table-warning:hover > th { + background-color: #ffe8a1; +} + +.table-danger, +.table-danger > th, +.table-danger > td { + background-color: #f5c6cb; +} + +.table-hover .table-danger:hover { + background-color: #f1b0b7; +} + +.table-hover .table-danger:hover > td, +.table-hover .table-danger:hover > th { + background-color: #f1b0b7; +} + +.table-light, +.table-light > th, +.table-light > td { + background-color: #fdfdfe; +} + +.table-hover .table-light:hover { + background-color: #ececf6; +} + +.table-hover .table-light:hover > td, +.table-hover .table-light:hover > th { + background-color: #ececf6; +} + +.table-dark, +.table-dark > th, +.table-dark > td { + background-color: #c6c8ca; +} + +.table-hover .table-dark:hover { + background-color: #b9bbbe; +} + +.table-hover .table-dark:hover > td, +.table-hover .table-dark:hover > th { + background-color: #b9bbbe; +} + +.table-active, +.table-active > th, +.table-active > td { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-hover .table-active:hover { + background-color: rgba(0, 0, 0, 0.075); +} + +.table-hover .table-active:hover > td, +.table-hover .table-active:hover > th { + background-color: rgba(0, 0, 0, 0.075); +} + +.table .thead-dark th { + color: #fff; + background-color: #212529; + border-color: #32383e; +} + +.table .thead-light th { + color: #495057; + background-color: #e9ecef; + border-color: #dee2e6; +} + +.table-dark { + color: #fff; + background-color: #212529; +} + +.table-dark th, +.table-dark td, +.table-dark thead th { + border-color: #32383e; +} + +.table-dark.table-bordered { + border: 0; +} + +.table-dark.table-striped tbody tr:nth-of-type(odd) { + background-color: rgba(255, 255, 255, 0.05); +} + +.table-dark.table-hover tbody tr:hover { + background-color: rgba(255, 255, 255, 0.075); +} + +@media (max-width: 575.98px) { + .table-responsive-sm { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .table-responsive-sm > .table-bordered { + border: 0; + } +} + +@media (max-width: 767.98px) { + .table-responsive-md { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .table-responsive-md > .table-bordered { + border: 0; + } +} + +@media (max-width: 991.98px) { + .table-responsive-lg { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .table-responsive-lg > .table-bordered { + border: 0; + } +} + +@media (max-width: 1199.98px) { + .table-responsive-xl { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + } + .table-responsive-xl > .table-bordered { + border: 0; + } +} + +.table-responsive { + display: block; + width: 100%; + overflow-x: auto; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; +} + +.table-responsive > .table-bordered { + border: 0; +} + +.form-control { + display: block; + width: 100%; + height: calc(2.25rem + 2px); + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + color: #495057; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ced4da; + border-radius: 0.25rem; + transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media screen and (prefers-reduced-motion: reduce) { + .form-control { + transition: none; + } +} + +.form-control::-ms-expand { + background-color: transparent; + border: 0; +} + +.form-control:focus { + color: #495057; + background-color: #fff; + border-color: #80bdff; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.form-control::-webkit-input-placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control::-moz-placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control:-ms-input-placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control::-ms-input-placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control::placeholder { + color: #6c757d; + opacity: 1; +} + +.form-control:disabled, .form-control[readonly] { + background-color: #e9ecef; + opacity: 1; +} + +select.form-control:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.form-control-file, +.form-control-range { + display: block; + width: 100%; +} + +.col-form-label { + padding-top: calc(0.375rem + 1px); + padding-bottom: calc(0.375rem + 1px); + margin-bottom: 0; + font-size: inherit; + line-height: 1.5; +} + +.col-form-label-lg { + padding-top: calc(0.5rem + 1px); + padding-bottom: calc(0.5rem + 1px); + font-size: 1.25rem; + line-height: 1.5; +} + +.col-form-label-sm { + padding-top: calc(0.25rem + 1px); + padding-bottom: calc(0.25rem + 1px); + font-size: 0.875rem; + line-height: 1.5; +} + +.form-control-plaintext { + display: block; + width: 100%; + padding-top: 0.375rem; + padding-bottom: 0.375rem; + margin-bottom: 0; + line-height: 1.5; + color: #212529; + background-color: transparent; + border: solid transparent; + border-width: 1px 0; +} + +.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg { + padding-right: 0; + padding-left: 0; +} + +.form-control-sm { + height: calc(1.8125rem + 2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.form-control-lg { + height: calc(2.875rem + 2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +select.form-control[size], select.form-control[multiple] { + height: auto; +} + +textarea.form-control { + height: auto; +} + +.form-group { + margin-bottom: 1rem; +} + +.form-text { + display: block; + margin-top: 0.25rem; +} + +.form-row { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + margin-right: -5px; + margin-left: -5px; +} + +.form-row > .col, +.form-row > [class*="col-"] { + padding-right: 5px; + padding-left: 5px; +} + +.form-check { + position: relative; + display: block; + padding-left: 1.25rem; +} + +.form-check-input { + position: absolute; + margin-top: 0.3rem; + margin-left: -1.25rem; +} + +.form-check-input:disabled ~ .form-check-label { + color: #6c757d; +} + +.form-check-label { + margin-bottom: 0; +} + +.form-check-inline { + display: -ms-inline-flexbox; + display: inline-flex; + -ms-flex-align: center; + align-items: center; + padding-left: 0; + margin-right: 0.75rem; +} + +.form-check-inline .form-check-input { + position: static; + margin-top: 0; + margin-right: 0.3125rem; + margin-left: 0; +} + +.valid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 80%; + color: #28a745; +} + +.valid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: .1rem; + font-size: 0.875rem; + line-height: 1.5; + color: #fff; + background-color: rgba(40, 167, 69, 0.9); + border-radius: 0.25rem; +} + +.was-validated .form-control:valid, .form-control.is-valid, .was-validated +.custom-select:valid, +.custom-select.is-valid { + border-color: #28a745; +} + +.was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated +.custom-select:valid:focus, +.custom-select.is-valid:focus { + border-color: #28a745; + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.was-validated .form-control:valid ~ .valid-feedback, +.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback, +.form-control.is-valid ~ .valid-tooltip, .was-validated +.custom-select:valid ~ .valid-feedback, +.was-validated +.custom-select:valid ~ .valid-tooltip, +.custom-select.is-valid ~ .valid-feedback, +.custom-select.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-control-file:valid ~ .valid-feedback, +.was-validated .form-control-file:valid ~ .valid-tooltip, .form-control-file.is-valid ~ .valid-feedback, +.form-control-file.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label { + color: #28a745; +} + +.was-validated .form-check-input:valid ~ .valid-feedback, +.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback, +.form-check-input.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label { + color: #28a745; +} + +.was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before { + background-color: #71dd8a; +} + +.was-validated .custom-control-input:valid ~ .valid-feedback, +.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback, +.custom-control-input.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before { + background-color: #34ce57; +} + +.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label { + border-color: #28a745; +} + +.was-validated .custom-file-input:valid ~ .custom-file-label::after, .custom-file-input.is-valid ~ .custom-file-label::after { + border-color: inherit; +} + +.was-validated .custom-file-input:valid ~ .valid-feedback, +.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback, +.custom-file-input.is-valid ~ .valid-tooltip { + display: block; +} + +.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25); +} + +.invalid-feedback { + display: none; + width: 100%; + margin-top: 0.25rem; + font-size: 80%; + color: #dc3545; +} + +.invalid-tooltip { + position: absolute; + top: 100%; + z-index: 5; + display: none; + max-width: 100%; + padding: 0.25rem 0.5rem; + margin-top: .1rem; + font-size: 0.875rem; + line-height: 1.5; + color: #fff; + background-color: rgba(220, 53, 69, 0.9); + border-radius: 0.25rem; +} + +.was-validated .form-control:invalid, .form-control.is-invalid, .was-validated +.custom-select:invalid, +.custom-select.is-invalid { + border-color: #dc3545; +} + +.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated +.custom-select:invalid:focus, +.custom-select.is-invalid:focus { + border-color: #dc3545; + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.was-validated .form-control:invalid ~ .invalid-feedback, +.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback, +.form-control.is-invalid ~ .invalid-tooltip, .was-validated +.custom-select:invalid ~ .invalid-feedback, +.was-validated +.custom-select:invalid ~ .invalid-tooltip, +.custom-select.is-invalid ~ .invalid-feedback, +.custom-select.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-control-file:invalid ~ .invalid-feedback, +.was-validated .form-control-file:invalid ~ .invalid-tooltip, .form-control-file.is-invalid ~ .invalid-feedback, +.form-control-file.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label { + color: #dc3545; +} + +.was-validated .form-check-input:invalid ~ .invalid-feedback, +.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback, +.form-check-input.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label { + color: #dc3545; +} + +.was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before { + background-color: #efa2a9; +} + +.was-validated .custom-control-input:invalid ~ .invalid-feedback, +.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback, +.custom-control-input.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before { + background-color: #e4606d; +} + +.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label { + border-color: #dc3545; +} + +.was-validated .custom-file-input:invalid ~ .custom-file-label::after, .custom-file-input.is-invalid ~ .custom-file-label::after { + border-color: inherit; +} + +.was-validated .custom-file-input:invalid ~ .invalid-feedback, +.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback, +.custom-file-input.is-invalid ~ .invalid-tooltip { + display: block; +} + +.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25); +} + +.form-inline { + display: -ms-flexbox; + display: flex; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -ms-flex-align: center; + align-items: center; +} + +.form-inline .form-check { + width: 100%; +} + +@media (min-width: 576px) { + .form-inline label { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + margin-bottom: 0; + } + .form-inline .form-group { + display: -ms-flexbox; + display: flex; + -ms-flex: 0 0 auto; + flex: 0 0 auto; + -ms-flex-flow: row wrap; + flex-flow: row wrap; + -ms-flex-align: center; + align-items: center; + margin-bottom: 0; + } + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + .form-inline .form-control-plaintext { + display: inline-block; + } + .form-inline .input-group, + .form-inline .custom-select { + width: auto; + } + .form-inline .form-check { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + width: auto; + padding-left: 0; + } + .form-inline .form-check-input { + position: relative; + margin-top: 0; + margin-right: 0.25rem; + margin-left: 0; + } + .form-inline .custom-control { + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + } + .form-inline .custom-control-label { + margin-bottom: 0; + } +} + +.btn { + display: inline-block; + font-weight: 400; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + border: 1px solid transparent; + padding: 0.375rem 0.75rem; + font-size: 1rem; + line-height: 1.5; + border-radius: 0.25rem; + transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media screen and (prefers-reduced-motion: reduce) { + .btn { + transition: none; + } +} + +.btn:hover, .btn:focus { + text-decoration: none; +} + +.btn:focus, .btn.focus { + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.btn.disabled, .btn:disabled { + opacity: 0.65; +} + +.btn:not(:disabled):not(.disabled) { + cursor: pointer; +} + +a.btn.disabled, +fieldset:disabled a.btn { + pointer-events: none; +} + +.btn-primary { + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.btn-primary:hover { + color: #fff; + background-color: #0069d9; + border-color: #0062cc; +} + +.btn-primary:focus, .btn-primary.focus { + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); +} + +.btn-primary.disabled, .btn-primary:disabled { + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active, +.show > .btn-primary.dropdown-toggle { + color: #fff; + background-color: #0062cc; + border-color: #005cbf; +} + +.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-primary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); +} + +.btn-secondary { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-secondary:hover { + color: #fff; + background-color: #5a6268; + border-color: #545b62; +} + +.btn-secondary:focus, .btn-secondary.focus { + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); +} + +.btn-secondary.disabled, .btn-secondary:disabled { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active, +.show > .btn-secondary.dropdown-toggle { + color: #fff; + background-color: #545b62; + border-color: #4e555b; +} + +.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-secondary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); +} + +.btn-success { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:hover { + color: #fff; + background-color: #218838; + border-color: #1e7e34; +} + +.btn-success:focus, .btn-success.focus { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-success.disabled, .btn-success:disabled { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active, +.show > .btn-success.dropdown-toggle { + color: #fff; + background-color: #1e7e34; + border-color: #1c7430; +} + +.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-success.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-info { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:hover { + color: #fff; + background-color: #138496; + border-color: #117a8b; +} + +.btn-info:focus, .btn-info.focus { + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-info.disabled, .btn-info:disabled { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active, +.show > .btn-info.dropdown-toggle { + color: #fff; + background-color: #117a8b; + border-color: #10707f; +} + +.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-info.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-warning { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:hover { + color: #212529; + background-color: #e0a800; + border-color: #d39e00; +} + +.btn-warning:focus, .btn-warning.focus { + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-warning.disabled, .btn-warning:disabled { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active, +.show > .btn-warning.dropdown-toggle { + color: #212529; + background-color: #d39e00; + border-color: #c69500; +} + +.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-warning.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-danger { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:hover { + color: #fff; + background-color: #c82333; + border-color: #bd2130; +} + +.btn-danger:focus, .btn-danger.focus { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-danger.disabled, .btn-danger:disabled { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active, +.show > .btn-danger.dropdown-toggle { + color: #fff; + background-color: #bd2130; + border-color: #b21f2d; +} + +.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-danger.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-light { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:hover { + color: #212529; + background-color: #e2e6ea; + border-color: #dae0e5; +} + +.btn-light:focus, .btn-light.focus { + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-light.disabled, .btn-light:disabled { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active, +.show > .btn-light.dropdown-toggle { + color: #212529; + background-color: #dae0e5; + border-color: #d3d9df; +} + +.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-light.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-dark { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:hover { + color: #fff; + background-color: #23272b; + border-color: #1d2124; +} + +.btn-dark:focus, .btn-dark.focus { + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-dark.disabled, .btn-dark:disabled { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active, +.show > .btn-dark.dropdown-toggle { + color: #fff; + background-color: #1d2124; + border-color: #171a1d; +} + +.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-dark.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-outline-primary { + color: #007bff; + background-color: transparent; + background-image: none; + border-color: #007bff; +} + +.btn-outline-primary:hover { + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.btn-outline-primary:focus, .btn-outline-primary.focus { + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); +} + +.btn-outline-primary.disabled, .btn-outline-primary:disabled { + color: #007bff; + background-color: transparent; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active, +.show > .btn-outline-primary.dropdown-toggle { + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-primary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5); +} + +.btn-outline-secondary { + color: #6c757d; + background-color: transparent; + background-image: none; + border-color: #6c757d; +} + +.btn-outline-secondary:hover { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-outline-secondary:focus, .btn-outline-secondary.focus { + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); +} + +.btn-outline-secondary.disabled, .btn-outline-secondary:disabled { + color: #6c757d; + background-color: transparent; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active, +.show > .btn-outline-secondary.dropdown-toggle { + color: #fff; + background-color: #6c757d; + border-color: #6c757d; +} + +.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-secondary.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5); +} + +.btn-outline-success { + color: #28a745; + background-color: transparent; + background-image: none; + border-color: #28a745; +} + +.btn-outline-success:hover { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:focus, .btn-outline-success.focus { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-success.disabled, .btn-outline-success:disabled { + color: #28a745; + background-color: transparent; +} + +.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active, +.show > .btn-outline-success.dropdown-toggle { + color: #fff; + background-color: #28a745; + border-color: #28a745; +} + +.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-success.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5); +} + +.btn-outline-info { + color: #17a2b8; + background-color: transparent; + background-image: none; + border-color: #17a2b8; +} + +.btn-outline-info:hover { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:focus, .btn-outline-info.focus { + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-info.disabled, .btn-outline-info:disabled { + color: #17a2b8; + background-color: transparent; +} + +.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active, +.show > .btn-outline-info.dropdown-toggle { + color: #fff; + background-color: #17a2b8; + border-color: #17a2b8; +} + +.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-info.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5); +} + +.btn-outline-warning { + color: #ffc107; + background-color: transparent; + background-image: none; + border-color: #ffc107; +} + +.btn-outline-warning:hover { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:focus, .btn-outline-warning.focus { + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-warning.disabled, .btn-outline-warning:disabled { + color: #ffc107; + background-color: transparent; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active, +.show > .btn-outline-warning.dropdown-toggle { + color: #212529; + background-color: #ffc107; + border-color: #ffc107; +} + +.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-warning.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5); +} + +.btn-outline-danger { + color: #dc3545; + background-color: transparent; + background-image: none; + border-color: #dc3545; +} + +.btn-outline-danger:hover { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:focus, .btn-outline-danger.focus { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-danger.disabled, .btn-outline-danger:disabled { + color: #dc3545; + background-color: transparent; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active, +.show > .btn-outline-danger.dropdown-toggle { + color: #fff; + background-color: #dc3545; + border-color: #dc3545; +} + +.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-danger.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5); +} + +.btn-outline-light { + color: #f8f9fa; + background-color: transparent; + background-image: none; + border-color: #f8f9fa; +} + +.btn-outline-light:hover { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:focus, .btn-outline-light.focus { + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-light.disabled, .btn-outline-light:disabled { + color: #f8f9fa; + background-color: transparent; +} + +.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active, +.show > .btn-outline-light.dropdown-toggle { + color: #212529; + background-color: #f8f9fa; + border-color: #f8f9fa; +} + +.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-light.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5); +} + +.btn-outline-dark { + color: #343a40; + background-color: transparent; + background-image: none; + border-color: #343a40; +} + +.btn-outline-dark:hover { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:focus, .btn-outline-dark.focus { + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-outline-dark.disabled, .btn-outline-dark:disabled { + color: #343a40; + background-color: transparent; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active, +.show > .btn-outline-dark.dropdown-toggle { + color: #fff; + background-color: #343a40; + border-color: #343a40; +} + +.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus, +.show > .btn-outline-dark.dropdown-toggle:focus { + box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5); +} + +.btn-link { + font-weight: 400; + color: #007bff; + background-color: transparent; +} + +.btn-link:hover { + color: #0056b3; + text-decoration: underline; + background-color: transparent; + border-color: transparent; +} + +.btn-link:focus, .btn-link.focus { + text-decoration: underline; + border-color: transparent; + box-shadow: none; +} + +.btn-link:disabled, .btn-link.disabled { + color: #6c757d; + pointer-events: none; +} + +.btn-lg, .btn-group-lg > .btn { + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.btn-sm, .btn-group-sm > .btn { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.btn-block { + display: block; + width: 100%; +} + +.btn-block + .btn-block { + margin-top: 0.5rem; +} + +input[type="submit"].btn-block, +input[type="reset"].btn-block, +input[type="button"].btn-block { + width: 100%; +} + +.fade { + transition: opacity 0.15s linear; +} + +@media screen and (prefers-reduced-motion: reduce) { + .fade { + transition: none; + } +} + +.fade:not(.show) { + opacity: 0; +} + +.collapse:not(.show) { + display: none; +} + +.collapsing { + position: relative; + height: 0; + overflow: hidden; + transition: height 0.35s ease; +} + +@media screen and (prefers-reduced-motion: reduce) { + .collapsing { + transition: none; + } +} + +.dropup, +.dropright, +.dropdown, +.dropleft { + position: relative; +} + +.dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; +} + +.dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropdown-menu { + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 10rem; + padding: 0.5rem 0; + margin: 0.125rem 0 0; + font-size: 1rem; + color: #212529; + text-align: left; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.15); + border-radius: 0.25rem; +} + +.dropdown-menu-right { + right: 0; + left: auto; +} + +.dropup .dropdown-menu { + top: auto; + bottom: 100%; + margin-top: 0; + margin-bottom: 0.125rem; +} + +.dropup .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0; + border-right: 0.3em solid transparent; + border-bottom: 0.3em solid; + border-left: 0.3em solid transparent; +} + +.dropup .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropright .dropdown-menu { + top: 0; + right: auto; + left: 100%; + margin-top: 0; + margin-left: 0.125rem; +} + +.dropright .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0; + border-bottom: 0.3em solid transparent; + border-left: 0.3em solid; +} + +.dropright .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropright .dropdown-toggle::after { + vertical-align: 0; +} + +.dropleft .dropdown-menu { + top: 0; + right: 100%; + left: auto; + margin-top: 0; + margin-right: 0.125rem; +} + +.dropleft .dropdown-toggle::after { + display: inline-block; + width: 0; + height: 0; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; +} + +.dropleft .dropdown-toggle::after { + display: none; +} + +.dropleft .dropdown-toggle::before { + display: inline-block; + width: 0; + height: 0; + margin-right: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid transparent; + border-right: 0.3em solid; + border-bottom: 0.3em solid transparent; +} + +.dropleft .dropdown-toggle:empty::after { + margin-left: 0; +} + +.dropleft .dropdown-toggle::before { + vertical-align: 0; +} + +.dropdown-menu[x-placement^="top"], .dropdown-menu[x-placement^="right"], .dropdown-menu[x-placement^="bottom"], .dropdown-menu[x-placement^="left"] { + right: auto; + bottom: auto; +} + +.dropdown-divider { + height: 0; + margin: 0.5rem 0; + overflow: hidden; + border-top: 1px solid #e9ecef; +} + +.dropdown-item { + display: block; + width: 100%; + padding: 0.25rem 1.5rem; + clear: both; + font-weight: 400; + color: #212529; + text-align: inherit; + white-space: nowrap; + background-color: transparent; + border: 0; +} + +.dropdown-item:hover, .dropdown-item:focus { + color: #16181b; + text-decoration: none; + background-color: #f8f9fa; +} + +.dropdown-item.active, .dropdown-item:active { + color: #fff; + text-decoration: none; + background-color: #007bff; +} + +.dropdown-item.disabled, .dropdown-item:disabled { + color: #6c757d; + background-color: transparent; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-header { + display: block; + padding: 0.5rem 1.5rem; + margin-bottom: 0; + font-size: 0.875rem; + color: #6c757d; + white-space: nowrap; +} + +.dropdown-item-text { + display: block; + padding: 0.25rem 1.5rem; + color: #212529; +} + +.btn-group, +.btn-group-vertical { + position: relative; + display: -ms-inline-flexbox; + display: inline-flex; + vertical-align: middle; +} + +.btn-group > .btn, +.btn-group-vertical > .btn { + position: relative; + -ms-flex: 0 1 auto; + flex: 0 1 auto; +} + +.btn-group > .btn:hover, +.btn-group-vertical > .btn:hover { + z-index: 1; +} + +.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active, +.btn-group-vertical > .btn:focus, +.btn-group-vertical > .btn:active, +.btn-group-vertical > .btn.active { + z-index: 1; +} + +.btn-group .btn + .btn, +.btn-group .btn + .btn-group, +.btn-group .btn-group + .btn, +.btn-group .btn-group + .btn-group, +.btn-group-vertical .btn + .btn, +.btn-group-vertical .btn + .btn-group, +.btn-group-vertical .btn-group + .btn, +.btn-group-vertical .btn-group + .btn-group { + margin-left: -1px; +} + +.btn-toolbar { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.btn-toolbar .input-group { + width: auto; +} + +.btn-group > .btn:first-child { + margin-left: 0; +} + +.btn-group > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group > .btn-group:not(:last-child) > .btn { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.btn-group > .btn:not(:first-child), +.btn-group > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.dropdown-toggle-split { + padding-right: 0.5625rem; + padding-left: 0.5625rem; +} + +.dropdown-toggle-split::after, +.dropup .dropdown-toggle-split::after, +.dropright .dropdown-toggle-split::after { + margin-left: 0; +} + +.dropleft .dropdown-toggle-split::before { + margin-right: 0; +} + +.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split { + padding-right: 0.375rem; + padding-left: 0.375rem; +} + +.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split { + padding-right: 0.75rem; + padding-left: 0.75rem; +} + +.btn-group-vertical { + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-align: start; + align-items: flex-start; + -ms-flex-pack: center; + justify-content: center; +} + +.btn-group-vertical .btn, +.btn-group-vertical .btn-group { + width: 100%; +} + +.btn-group-vertical > .btn + .btn, +.btn-group-vertical > .btn + .btn-group, +.btn-group-vertical > .btn-group + .btn, +.btn-group-vertical > .btn-group + .btn-group { + margin-top: -1px; + margin-left: 0; +} + +.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle), +.btn-group-vertical > .btn-group:not(:last-child) > .btn { + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.btn-group-vertical > .btn:not(:first-child), +.btn-group-vertical > .btn-group:not(:first-child) > .btn { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.btn-group-toggle > .btn, +.btn-group-toggle > .btn-group > .btn { + margin-bottom: 0; +} + +.btn-group-toggle > .btn input[type="radio"], +.btn-group-toggle > .btn input[type="checkbox"], +.btn-group-toggle > .btn-group > .btn input[type="radio"], +.btn-group-toggle > .btn-group > .btn input[type="checkbox"] { + position: absolute; + clip: rect(0, 0, 0, 0); + pointer-events: none; +} + +.input-group { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: stretch; + align-items: stretch; + width: 100%; +} + +.input-group > .form-control, +.input-group > .custom-select, +.input-group > .custom-file { + position: relative; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + width: 1%; + margin-bottom: 0; +} + +.input-group > .form-control + .form-control, +.input-group > .form-control + .custom-select, +.input-group > .form-control + .custom-file, +.input-group > .custom-select + .form-control, +.input-group > .custom-select + .custom-select, +.input-group > .custom-select + .custom-file, +.input-group > .custom-file + .form-control, +.input-group > .custom-file + .custom-select, +.input-group > .custom-file + .custom-file { + margin-left: -1px; +} + +.input-group > .form-control:focus, +.input-group > .custom-select:focus, +.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label { + z-index: 3; +} + +.input-group > .custom-file .custom-file-input:focus { + z-index: 4; +} + +.input-group > .form-control:not(:last-child), +.input-group > .custom-select:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > .form-control:not(:first-child), +.input-group > .custom-select:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.input-group > .custom-file { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; +} + +.input-group > .custom-file:not(:last-child) .custom-file-label, +.input-group > .custom-file:not(:last-child) .custom-file-label::after { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > .custom-file:not(:first-child) .custom-file-label { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.input-group-prepend, +.input-group-append { + display: -ms-flexbox; + display: flex; +} + +.input-group-prepend .btn, +.input-group-append .btn { + position: relative; + z-index: 2; +} + +.input-group-prepend .btn + .btn, +.input-group-prepend .btn + .input-group-text, +.input-group-prepend .input-group-text + .input-group-text, +.input-group-prepend .input-group-text + .btn, +.input-group-append .btn + .btn, +.input-group-append .btn + .input-group-text, +.input-group-append .input-group-text + .input-group-text, +.input-group-append .input-group-text + .btn { + margin-left: -1px; +} + +.input-group-prepend { + margin-right: -1px; +} + +.input-group-append { + margin-left: -1px; +} + +.input-group-text { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + padding: 0.375rem 0.75rem; + margin-bottom: 0; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #495057; + text-align: center; + white-space: nowrap; + background-color: #e9ecef; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} + +.input-group-text input[type="radio"], +.input-group-text input[type="checkbox"] { + margin-top: 0; +} + +.input-group-lg > .form-control, +.input-group-lg > .input-group-prepend > .input-group-text, +.input-group-lg > .input-group-append > .input-group-text, +.input-group-lg > .input-group-prepend > .btn, +.input-group-lg > .input-group-append > .btn { + height: calc(2.875rem + 2px); + padding: 0.5rem 1rem; + font-size: 1.25rem; + line-height: 1.5; + border-radius: 0.3rem; +} + +.input-group-sm > .form-control, +.input-group-sm > .input-group-prepend > .input-group-text, +.input-group-sm > .input-group-append > .input-group-text, +.input-group-sm > .input-group-prepend > .btn, +.input-group-sm > .input-group-append > .btn { + height: calc(1.8125rem + 2px); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; + border-radius: 0.2rem; +} + +.input-group > .input-group-prepend > .btn, +.input-group > .input-group-prepend > .input-group-text, +.input-group > .input-group-append:not(:last-child) > .btn, +.input-group > .input-group-append:not(:last-child) > .input-group-text, +.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle), +.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.input-group > .input-group-append > .btn, +.input-group > .input-group-append > .input-group-text, +.input-group > .input-group-prepend:not(:first-child) > .btn, +.input-group > .input-group-prepend:not(:first-child) > .input-group-text, +.input-group > .input-group-prepend:first-child > .btn:not(:first-child), +.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.custom-control { + position: relative; + display: block; + min-height: 1.5rem; + padding-left: 1.5rem; +} + +.custom-control-inline { + display: -ms-inline-flexbox; + display: inline-flex; + margin-right: 1rem; +} + +.custom-control-input { + position: absolute; + z-index: -1; + opacity: 0; +} + +.custom-control-input:checked ~ .custom-control-label::before { + color: #fff; + background-color: #007bff; +} + +.custom-control-input:focus ~ .custom-control-label::before { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-control-input:active ~ .custom-control-label::before { + color: #fff; + background-color: #b3d7ff; +} + +.custom-control-input:disabled ~ .custom-control-label { + color: #6c757d; +} + +.custom-control-input:disabled ~ .custom-control-label::before { + background-color: #e9ecef; +} + +.custom-control-label { + position: relative; + margin-bottom: 0; +} + +.custom-control-label::before { + position: absolute; + top: 0.25rem; + left: -1.5rem; + display: block; + width: 1rem; + height: 1rem; + pointer-events: none; + content: ""; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-color: #dee2e6; +} + +.custom-control-label::after { + position: absolute; + top: 0.25rem; + left: -1.5rem; + display: block; + width: 1rem; + height: 1rem; + content: ""; + background-repeat: no-repeat; + background-position: center center; + background-size: 50% 50%; +} + +.custom-checkbox .custom-control-label::before { + border-radius: 0.25rem; +} + +.custom-checkbox .custom-control-input:checked ~ .custom-control-label::before { + background-color: #007bff; +} + +.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E"); +} + +.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before { + background-color: #007bff; +} + +.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E"); +} + +.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(0, 123, 255, 0.5); +} + +.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before { + background-color: rgba(0, 123, 255, 0.5); +} + +.custom-radio .custom-control-label::before { + border-radius: 50%; +} + +.custom-radio .custom-control-input:checked ~ .custom-control-label::before { + background-color: #007bff; +} + +.custom-radio .custom-control-input:checked ~ .custom-control-label::after { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E"); +} + +.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before { + background-color: rgba(0, 123, 255, 0.5); +} + +.custom-select { + display: inline-block; + width: 100%; + height: calc(2.25rem + 2px); + padding: 0.375rem 1.75rem 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + vertical-align: middle; + background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center; + background-size: 8px 10px; + border: 1px solid #ced4da; + border-radius: 0.25rem; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.custom-select:focus { + border-color: #80bdff; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(128, 189, 255, 0.5); +} + +.custom-select:focus::-ms-value { + color: #495057; + background-color: #fff; +} + +.custom-select[multiple], .custom-select[size]:not([size="1"]) { + height: auto; + padding-right: 0.75rem; + background-image: none; +} + +.custom-select:disabled { + color: #6c757d; + background-color: #e9ecef; +} + +.custom-select::-ms-expand { + opacity: 0; +} + +.custom-select-sm { + height: calc(1.8125rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 75%; +} + +.custom-select-lg { + height: calc(2.875rem + 2px); + padding-top: 0.375rem; + padding-bottom: 0.375rem; + font-size: 125%; +} + +.custom-file { + position: relative; + display: inline-block; + width: 100%; + height: calc(2.25rem + 2px); + margin-bottom: 0; +} + +.custom-file-input { + position: relative; + z-index: 2; + width: 100%; + height: calc(2.25rem + 2px); + margin: 0; + opacity: 0; +} + +.custom-file-input:focus ~ .custom-file-label { + border-color: #80bdff; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-file-input:focus ~ .custom-file-label::after { + border-color: #80bdff; +} + +.custom-file-input:disabled ~ .custom-file-label { + background-color: #e9ecef; +} + +.custom-file-input:lang(en) ~ .custom-file-label::after { + content: "Browse"; +} + +.custom-file-label { + position: absolute; + top: 0; + right: 0; + left: 0; + z-index: 1; + height: calc(2.25rem + 2px); + padding: 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + background-color: #fff; + border: 1px solid #ced4da; + border-radius: 0.25rem; +} + +.custom-file-label::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + z-index: 3; + display: block; + height: 2.25rem; + padding: 0.375rem 0.75rem; + line-height: 1.5; + color: #495057; + content: "Browse"; + background-color: #e9ecef; + border-left: 1px solid #ced4da; + border-radius: 0 0.25rem 0.25rem 0; +} + +.custom-range { + width: 100%; + padding-left: 0; + background-color: transparent; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; +} + +.custom-range:focus { + outline: none; +} + +.custom-range:focus::-webkit-slider-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-range:focus::-moz-range-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-range:focus::-ms-thumb { + box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.custom-range::-moz-focus-outer { + border: 0; +} + +.custom-range::-webkit-slider-thumb { + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background-color: #007bff; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -webkit-appearance: none; + appearance: none; +} + +@media screen and (prefers-reduced-motion: reduce) { + .custom-range::-webkit-slider-thumb { + transition: none; + } +} + +.custom-range::-webkit-slider-thumb:active { + background-color: #b3d7ff; +} + +.custom-range::-webkit-slider-runnable-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} + +.custom-range::-moz-range-thumb { + width: 1rem; + height: 1rem; + background-color: #007bff; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + -moz-appearance: none; + appearance: none; +} + +@media screen and (prefers-reduced-motion: reduce) { + .custom-range::-moz-range-thumb { + transition: none; + } +} + +.custom-range::-moz-range-thumb:active { + background-color: #b3d7ff; +} + +.custom-range::-moz-range-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: #dee2e6; + border-color: transparent; + border-radius: 1rem; +} + +.custom-range::-ms-thumb { + width: 1rem; + height: 1rem; + margin-top: 0; + margin-right: 0.2rem; + margin-left: 0.2rem; + background-color: #007bff; + border: 0; + border-radius: 1rem; + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; + appearance: none; +} + +@media screen and (prefers-reduced-motion: reduce) { + .custom-range::-ms-thumb { + transition: none; + } +} + +.custom-range::-ms-thumb:active { + background-color: #b3d7ff; +} + +.custom-range::-ms-track { + width: 100%; + height: 0.5rem; + color: transparent; + cursor: pointer; + background-color: transparent; + border-color: transparent; + border-width: 0.5rem; +} + +.custom-range::-ms-fill-lower { + background-color: #dee2e6; + border-radius: 1rem; +} + +.custom-range::-ms-fill-upper { + margin-right: 15px; + background-color: #dee2e6; + border-radius: 1rem; +} + +.custom-control-label::before, +.custom-file-label, +.custom-select { + transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; +} + +@media screen and (prefers-reduced-motion: reduce) { + .custom-control-label::before, + .custom-file-label, + .custom-select { + transition: none; + } +} + +.nav { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.nav-link { + display: block; + padding: 0.5rem 1rem; +} + +.nav-link:hover, .nav-link:focus { + text-decoration: none; +} + +.nav-link.disabled { + color: #6c757d; +} + +.nav-tabs { + border-bottom: 1px solid #dee2e6; +} + +.nav-tabs .nav-item { + margin-bottom: -1px; +} + +.nav-tabs .nav-link { + border: 1px solid transparent; + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus { + border-color: #e9ecef #e9ecef #dee2e6; +} + +.nav-tabs .nav-link.disabled { + color: #6c757d; + background-color: transparent; + border-color: transparent; +} + +.nav-tabs .nav-link.active, +.nav-tabs .nav-item.show .nav-link { + color: #495057; + background-color: #fff; + border-color: #dee2e6 #dee2e6 #fff; +} + +.nav-tabs .dropdown-menu { + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.nav-pills .nav-link { + border-radius: 0.25rem; +} + +.nav-pills .nav-link.active, +.nav-pills .show > .nav-link { + color: #fff; + background-color: #007bff; +} + +.nav-fill .nav-item { + -ms-flex: 1 1 auto; + flex: 1 1 auto; + text-align: center; +} + +.nav-justified .nav-item { + -ms-flex-preferred-size: 0; + flex-basis: 0; + -ms-flex-positive: 1; + flex-grow: 1; + text-align: center; +} + +.tab-content > .tab-pane { + display: none; +} + +.tab-content > .active { + display: block; +} + +.navbar { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 0.5rem 1rem; +} + +.navbar > .container, +.navbar > .container-fluid { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: justify; + justify-content: space-between; +} + +.navbar-brand { + display: inline-block; + padding-top: 0.3125rem; + padding-bottom: 0.3125rem; + margin-right: 1rem; + font-size: 1.25rem; + line-height: inherit; + white-space: nowrap; +} + +.navbar-brand:hover, .navbar-brand:focus { + text-decoration: none; +} + +.navbar-nav { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; + list-style: none; +} + +.navbar-nav .nav-link { + padding-right: 0; + padding-left: 0; +} + +.navbar-nav .dropdown-menu { + position: static; + float: none; +} + +.navbar-text { + display: inline-block; + padding-top: 0.5rem; + padding-bottom: 0.5rem; +} + +.navbar-collapse { + -ms-flex-preferred-size: 100%; + flex-basis: 100%; + -ms-flex-positive: 1; + flex-grow: 1; + -ms-flex-align: center; + align-items: center; +} + +.navbar-toggler { + padding: 0.25rem 0.75rem; + font-size: 1.25rem; + line-height: 1; + background-color: transparent; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.navbar-toggler:hover, .navbar-toggler:focus { + text-decoration: none; +} + +.navbar-toggler:not(:disabled):not(.disabled) { + cursor: pointer; +} + +.navbar-toggler-icon { + display: inline-block; + width: 1.5em; + height: 1.5em; + vertical-align: middle; + content: ""; + background: no-repeat center center; + background-size: 100% 100%; +} + +@media (max-width: 575.98px) { + .navbar-expand-sm > .container, + .navbar-expand-sm > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 576px) { + .navbar-expand-sm { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-sm .navbar-nav { + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-sm .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-sm .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-sm > .container, + .navbar-expand-sm > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-sm .navbar-collapse { + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-sm .navbar-toggler { + display: none; + } +} + +@media (max-width: 767.98px) { + .navbar-expand-md > .container, + .navbar-expand-md > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 768px) { + .navbar-expand-md { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-md .navbar-nav { + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-md .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-md .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-md > .container, + .navbar-expand-md > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-md .navbar-collapse { + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-md .navbar-toggler { + display: none; + } +} + +@media (max-width: 991.98px) { + .navbar-expand-lg > .container, + .navbar-expand-lg > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 992px) { + .navbar-expand-lg { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-lg .navbar-nav { + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-lg .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-lg .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-lg > .container, + .navbar-expand-lg > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-lg .navbar-collapse { + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-lg .navbar-toggler { + display: none; + } +} + +@media (max-width: 1199.98px) { + .navbar-expand-xl > .container, + .navbar-expand-xl > .container-fluid { + padding-right: 0; + padding-left: 0; + } +} + +@media (min-width: 1200px) { + .navbar-expand-xl { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; + } + .navbar-expand-xl .navbar-nav { + -ms-flex-direction: row; + flex-direction: row; + } + .navbar-expand-xl .navbar-nav .dropdown-menu { + position: absolute; + } + .navbar-expand-xl .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; + } + .navbar-expand-xl > .container, + .navbar-expand-xl > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; + } + .navbar-expand-xl .navbar-collapse { + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; + } + .navbar-expand-xl .navbar-toggler { + display: none; + } +} + +.navbar-expand { + -ms-flex-flow: row nowrap; + flex-flow: row nowrap; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.navbar-expand > .container, +.navbar-expand > .container-fluid { + padding-right: 0; + padding-left: 0; +} + +.navbar-expand .navbar-nav { + -ms-flex-direction: row; + flex-direction: row; +} + +.navbar-expand .navbar-nav .dropdown-menu { + position: absolute; +} + +.navbar-expand .navbar-nav .nav-link { + padding-right: 0.5rem; + padding-left: 0.5rem; +} + +.navbar-expand > .container, +.navbar-expand > .container-fluid { + -ms-flex-wrap: nowrap; + flex-wrap: nowrap; +} + +.navbar-expand .navbar-collapse { + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-preferred-size: auto; + flex-basis: auto; +} + +.navbar-expand .navbar-toggler { + display: none; +} + +.navbar-light .navbar-brand { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-nav .nav-link { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus { + color: rgba(0, 0, 0, 0.7); +} + +.navbar-light .navbar-nav .nav-link.disabled { + color: rgba(0, 0, 0, 0.3); +} + +.navbar-light .navbar-nav .show > .nav-link, +.navbar-light .navbar-nav .active > .nav-link, +.navbar-light .navbar-nav .nav-link.show, +.navbar-light .navbar-nav .nav-link.active { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-toggler { + color: rgba(0, 0, 0, 0.5); + border-color: rgba(0, 0, 0, 0.1); +} + +.navbar-light .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} + +.navbar-light .navbar-text { + color: rgba(0, 0, 0, 0.5); +} + +.navbar-light .navbar-text a { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus { + color: rgba(0, 0, 0, 0.9); +} + +.navbar-dark .navbar-brand { + color: #fff; +} + +.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus { + color: #fff; +} + +.navbar-dark .navbar-nav .nav-link { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus { + color: rgba(255, 255, 255, 0.75); +} + +.navbar-dark .navbar-nav .nav-link.disabled { + color: rgba(255, 255, 255, 0.25); +} + +.navbar-dark .navbar-nav .show > .nav-link, +.navbar-dark .navbar-nav .active > .nav-link, +.navbar-dark .navbar-nav .nav-link.show, +.navbar-dark .navbar-nav .nav-link.active { + color: #fff; +} + +.navbar-dark .navbar-toggler { + color: rgba(255, 255, 255, 0.5); + border-color: rgba(255, 255, 255, 0.1); +} + +.navbar-dark .navbar-toggler-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E"); +} + +.navbar-dark .navbar-text { + color: rgba(255, 255, 255, 0.5); +} + +.navbar-dark .navbar-text a { + color: #fff; +} + +.navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus { + color: #fff; +} + +.card { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + min-width: 0; + word-wrap: break-word; + background-color: #fff; + background-clip: border-box; + border: 1px solid rgba(0, 0, 0, 0.125); + border-radius: 0.25rem; +} + +.card > hr { + margin-right: 0; + margin-left: 0; +} + +.card > .list-group:first-child .list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.card > .list-group:last-child .list-group-item:last-child { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.card-body { + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1.25rem; +} + +.card-title { + margin-bottom: 0.75rem; +} + +.card-subtitle { + margin-top: -0.375rem; + margin-bottom: 0; +} + +.card-text:last-child { + margin-bottom: 0; +} + +.card-link:hover { + text-decoration: none; +} + +.card-link + .card-link { + margin-left: 1.25rem; +} + +.card-header { + padding: 0.75rem 1.25rem; + margin-bottom: 0; + background-color: rgba(0, 0, 0, 0.03); + border-bottom: 1px solid rgba(0, 0, 0, 0.125); +} + +.card-header:first-child { + border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0; +} + +.card-header + .list-group .list-group-item:first-child { + border-top: 0; +} + +.card-footer { + padding: 0.75rem 1.25rem; + background-color: rgba(0, 0, 0, 0.03); + border-top: 1px solid rgba(0, 0, 0, 0.125); +} + +.card-footer:last-child { + border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px); +} + +.card-header-tabs { + margin-right: -0.625rem; + margin-bottom: -0.75rem; + margin-left: -0.625rem; + border-bottom: 0; +} + +.card-header-pills { + margin-right: -0.625rem; + margin-left: -0.625rem; +} + +.card-img-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + padding: 1.25rem; +} + +.card-img { + width: 100%; + border-radius: calc(0.25rem - 1px); +} + +.card-img-top { + width: 100%; + border-top-left-radius: calc(0.25rem - 1px); + border-top-right-radius: calc(0.25rem - 1px); +} + +.card-img-bottom { + width: 100%; + border-bottom-right-radius: calc(0.25rem - 1px); + border-bottom-left-radius: calc(0.25rem - 1px); +} + +.card-deck { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; +} + +.card-deck .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-deck { + -ms-flex-flow: row wrap; + flex-flow: row wrap; + margin-right: -15px; + margin-left: -15px; + } + .card-deck .card { + display: -ms-flexbox; + display: flex; + -ms-flex: 1 0 0%; + flex: 1 0 0%; + -ms-flex-direction: column; + flex-direction: column; + margin-right: 15px; + margin-bottom: 0; + margin-left: 15px; + } +} + +.card-group { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; +} + +.card-group > .card { + margin-bottom: 15px; +} + +@media (min-width: 576px) { + .card-group { + -ms-flex-flow: row wrap; + flex-flow: row wrap; + } + .card-group > .card { + -ms-flex: 1 0 0%; + flex: 1 0 0%; + margin-bottom: 0; + } + .card-group > .card + .card { + margin-left: 0; + border-left: 0; + } + .card-group > .card:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + .card-group > .card:first-child .card-img-top, + .card-group > .card:first-child .card-header { + border-top-right-radius: 0; + } + .card-group > .card:first-child .card-img-bottom, + .card-group > .card:first-child .card-footer { + border-bottom-right-radius: 0; + } + .card-group > .card:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + .card-group > .card:last-child .card-img-top, + .card-group > .card:last-child .card-header { + border-top-left-radius: 0; + } + .card-group > .card:last-child .card-img-bottom, + .card-group > .card:last-child .card-footer { + border-bottom-left-radius: 0; + } + .card-group > .card:only-child { + border-radius: 0.25rem; + } + .card-group > .card:only-child .card-img-top, + .card-group > .card:only-child .card-header { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; + } + .card-group > .card:only-child .card-img-bottom, + .card-group > .card:only-child .card-footer { + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; + } + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) { + border-radius: 0; + } + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top, + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom, + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-header, + .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-footer { + border-radius: 0; + } +} + +.card-columns .card { + margin-bottom: 0.75rem; +} + +@media (min-width: 576px) { + .card-columns { + -webkit-column-count: 3; + -moz-column-count: 3; + column-count: 3; + -webkit-column-gap: 1.25rem; + -moz-column-gap: 1.25rem; + column-gap: 1.25rem; + orphans: 1; + widows: 1; + } + .card-columns .card { + display: inline-block; + width: 100%; + } +} + +.accordion .card:not(:first-of-type):not(:last-of-type) { + border-bottom: 0; + border-radius: 0; +} + +.accordion .card:not(:first-of-type) .card-header:first-child { + border-radius: 0; +} + +.accordion .card:first-of-type { + border-bottom: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} + +.accordion .card:last-of-type { + border-top-left-radius: 0; + border-top-right-radius: 0; +} + +.breadcrumb { + display: -ms-flexbox; + display: flex; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + padding: 0.75rem 1rem; + margin-bottom: 1rem; + list-style: none; + background-color: #e9ecef; + border-radius: 0.25rem; +} + +.breadcrumb-item + .breadcrumb-item { + padding-left: 0.5rem; +} + +.breadcrumb-item + .breadcrumb-item::before { + display: inline-block; + padding-right: 0.5rem; + color: #6c757d; + content: "/"; +} + +.breadcrumb-item + .breadcrumb-item:hover::before { + text-decoration: underline; +} + +.breadcrumb-item + .breadcrumb-item:hover::before { + text-decoration: none; +} + +.breadcrumb-item.active { + color: #6c757d; +} + +.pagination { + display: -ms-flexbox; + display: flex; + padding-left: 0; + list-style: none; + border-radius: 0.25rem; +} + +.page-link { + position: relative; + display: block; + padding: 0.5rem 0.75rem; + margin-left: -1px; + line-height: 1.25; + color: #007bff; + background-color: #fff; + border: 1px solid #dee2e6; +} + +.page-link:hover { + z-index: 2; + color: #0056b3; + text-decoration: none; + background-color: #e9ecef; + border-color: #dee2e6; +} + +.page-link:focus { + z-index: 2; + outline: 0; + box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25); +} + +.page-link:not(:disabled):not(.disabled) { + cursor: pointer; +} + +.page-item:first-child .page-link { + margin-left: 0; + border-top-left-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.page-item:last-child .page-link { + border-top-right-radius: 0.25rem; + border-bottom-right-radius: 0.25rem; +} + +.page-item.active .page-link { + z-index: 1; + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.page-item.disabled .page-link { + color: #6c757d; + pointer-events: none; + cursor: auto; + background-color: #fff; + border-color: #dee2e6; +} + +.pagination-lg .page-link { + padding: 0.75rem 1.5rem; + font-size: 1.25rem; + line-height: 1.5; +} + +.pagination-lg .page-item:first-child .page-link { + border-top-left-radius: 0.3rem; + border-bottom-left-radius: 0.3rem; +} + +.pagination-lg .page-item:last-child .page-link { + border-top-right-radius: 0.3rem; + border-bottom-right-radius: 0.3rem; +} + +.pagination-sm .page-link { + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.5; +} + +.pagination-sm .page-item:first-child .page-link { + border-top-left-radius: 0.2rem; + border-bottom-left-radius: 0.2rem; +} + +.pagination-sm .page-item:last-child .page-link { + border-top-right-radius: 0.2rem; + border-bottom-right-radius: 0.2rem; +} + +.badge { + display: inline-block; + padding: 0.25em 0.4em; + font-size: 75%; + font-weight: 700; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: 0.25rem; +} + +.badge:empty { + display: none; +} + +.btn .badge { + position: relative; + top: -1px; +} + +.badge-pill { + padding-right: 0.6em; + padding-left: 0.6em; + border-radius: 10rem; +} + +.badge-primary { + color: #fff; + background-color: #007bff; +} + +.badge-primary[href]:hover, .badge-primary[href]:focus { + color: #fff; + text-decoration: none; + background-color: #0062cc; +} + +.badge-secondary { + color: #fff; + background-color: #6c757d; +} + +.badge-secondary[href]:hover, .badge-secondary[href]:focus { + color: #fff; + text-decoration: none; + background-color: #545b62; +} + +.badge-success { + color: #fff; + background-color: #28a745; +} + +.badge-success[href]:hover, .badge-success[href]:focus { + color: #fff; + text-decoration: none; + background-color: #1e7e34; +} + +.badge-info { + color: #fff; + background-color: #17a2b8; +} + +.badge-info[href]:hover, .badge-info[href]:focus { + color: #fff; + text-decoration: none; + background-color: #117a8b; +} + +.badge-warning { + color: #212529; + background-color: #ffc107; +} + +.badge-warning[href]:hover, .badge-warning[href]:focus { + color: #212529; + text-decoration: none; + background-color: #d39e00; +} + +.badge-danger { + color: #fff; + background-color: #dc3545; +} + +.badge-danger[href]:hover, .badge-danger[href]:focus { + color: #fff; + text-decoration: none; + background-color: #bd2130; +} + +.badge-light { + color: #212529; + background-color: #f8f9fa; +} + +.badge-light[href]:hover, .badge-light[href]:focus { + color: #212529; + text-decoration: none; + background-color: #dae0e5; +} + +.badge-dark { + color: #fff; + background-color: #343a40; +} + +.badge-dark[href]:hover, .badge-dark[href]:focus { + color: #fff; + text-decoration: none; + background-color: #1d2124; +} + +.jumbotron { + padding: 2rem 1rem; + margin-bottom: 2rem; + background-color: #e9ecef; + border-radius: 0.3rem; +} + +@media (min-width: 576px) { + .jumbotron { + padding: 4rem 2rem; + } +} + +.jumbotron-fluid { + padding-right: 0; + padding-left: 0; + border-radius: 0; +} + +.alert { + position: relative; + padding: 0.75rem 1.25rem; + margin-bottom: 1rem; + border: 1px solid transparent; + border-radius: 0.25rem; +} + +.alert-heading { + color: inherit; +} + +.alert-link { + font-weight: 700; +} + +.alert-dismissible { + padding-right: 4rem; +} + +.alert-dismissible .close { + position: absolute; + top: 0; + right: 0; + padding: 0.75rem 1.25rem; + color: inherit; +} + +.alert-primary { + color: #004085; + background-color: #cce5ff; + border-color: #b8daff; +} + +.alert-primary hr { + border-top-color: #9fcdff; +} + +.alert-primary .alert-link { + color: #002752; +} + +.alert-secondary { + color: #383d41; + background-color: #e2e3e5; + border-color: #d6d8db; +} + +.alert-secondary hr { + border-top-color: #c8cbcf; +} + +.alert-secondary .alert-link { + color: #202326; +} + +.alert-success { + color: #155724; + background-color: #d4edda; + border-color: #c3e6cb; +} + +.alert-success hr { + border-top-color: #b1dfbb; +} + +.alert-success .alert-link { + color: #0b2e13; +} + +.alert-info { + color: #0c5460; + background-color: #d1ecf1; + border-color: #bee5eb; +} + +.alert-info hr { + border-top-color: #abdde5; +} + +.alert-info .alert-link { + color: #062c33; +} + +.alert-warning { + color: #856404; + background-color: #fff3cd; + border-color: #ffeeba; +} + +.alert-warning hr { + border-top-color: #ffe8a1; +} + +.alert-warning .alert-link { + color: #533f03; +} + +.alert-danger { + color: #721c24; + background-color: #f8d7da; + border-color: #f5c6cb; +} + +.alert-danger hr { + border-top-color: #f1b0b7; +} + +.alert-danger .alert-link { + color: #491217; +} + +.alert-light { + color: #818182; + background-color: #fefefe; + border-color: #fdfdfe; +} + +.alert-light hr { + border-top-color: #ececf6; +} + +.alert-light .alert-link { + color: #686868; +} + +.alert-dark { + color: #1b1e21; + background-color: #d6d8d9; + border-color: #c6c8ca; +} + +.alert-dark hr { + border-top-color: #b9bbbe; +} + +.alert-dark .alert-link { + color: #040505; +} + +@-webkit-keyframes progress-bar-stripes { + from { + background-position: 1rem 0; + } + to { + background-position: 0 0; + } +} + +@keyframes progress-bar-stripes { + from { + background-position: 1rem 0; + } + to { + background-position: 0 0; + } +} + +.progress { + display: -ms-flexbox; + display: flex; + height: 1rem; + overflow: hidden; + font-size: 0.75rem; + background-color: #e9ecef; + border-radius: 0.25rem; +} + +.progress-bar { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + -ms-flex-pack: center; + justify-content: center; + color: #fff; + text-align: center; + white-space: nowrap; + background-color: #007bff; + transition: width 0.6s ease; +} + +@media screen and (prefers-reduced-motion: reduce) { + .progress-bar { + transition: none; + } +} + +.progress-bar-striped { + background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent); + background-size: 1rem 1rem; +} + +.progress-bar-animated { + -webkit-animation: progress-bar-stripes 1s linear infinite; + animation: progress-bar-stripes 1s linear infinite; +} + +.media { + display: -ms-flexbox; + display: flex; + -ms-flex-align: start; + align-items: flex-start; +} + +.media-body { + -ms-flex: 1; + flex: 1; +} + +.list-group { + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + padding-left: 0; + margin-bottom: 0; +} + +.list-group-item-action { + width: 100%; + color: #495057; + text-align: inherit; +} + +.list-group-item-action:hover, .list-group-item-action:focus { + color: #495057; + text-decoration: none; + background-color: #f8f9fa; +} + +.list-group-item-action:active { + color: #212529; + background-color: #e9ecef; +} + +.list-group-item { + position: relative; + display: block; + padding: 0.75rem 1.25rem; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid rgba(0, 0, 0, 0.125); +} + +.list-group-item:first-child { + border-top-left-radius: 0.25rem; + border-top-right-radius: 0.25rem; +} + +.list-group-item:last-child { + margin-bottom: 0; + border-bottom-right-radius: 0.25rem; + border-bottom-left-radius: 0.25rem; +} + +.list-group-item:hover, .list-group-item:focus { + z-index: 1; + text-decoration: none; +} + +.list-group-item.disabled, .list-group-item:disabled { + color: #6c757d; + background-color: #fff; +} + +.list-group-item.active { + z-index: 2; + color: #fff; + background-color: #007bff; + border-color: #007bff; +} + +.list-group-flush .list-group-item { + border-right: 0; + border-left: 0; + border-radius: 0; +} + +.list-group-flush:first-child .list-group-item:first-child { + border-top: 0; +} + +.list-group-flush:last-child .list-group-item:last-child { + border-bottom: 0; +} + +.list-group-item-primary { + color: #004085; + background-color: #b8daff; +} + +.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus { + color: #004085; + background-color: #9fcdff; +} + +.list-group-item-primary.list-group-item-action.active { + color: #fff; + background-color: #004085; + border-color: #004085; +} + +.list-group-item-secondary { + color: #383d41; + background-color: #d6d8db; +} + +.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus { + color: #383d41; + background-color: #c8cbcf; +} + +.list-group-item-secondary.list-group-item-action.active { + color: #fff; + background-color: #383d41; + border-color: #383d41; +} + +.list-group-item-success { + color: #155724; + background-color: #c3e6cb; +} + +.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus { + color: #155724; + background-color: #b1dfbb; +} + +.list-group-item-success.list-group-item-action.active { + color: #fff; + background-color: #155724; + border-color: #155724; +} + +.list-group-item-info { + color: #0c5460; + background-color: #bee5eb; +} + +.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus { + color: #0c5460; + background-color: #abdde5; +} + +.list-group-item-info.list-group-item-action.active { + color: #fff; + background-color: #0c5460; + border-color: #0c5460; +} + +.list-group-item-warning { + color: #856404; + background-color: #ffeeba; +} + +.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus { + color: #856404; + background-color: #ffe8a1; +} + +.list-group-item-warning.list-group-item-action.active { + color: #fff; + background-color: #856404; + border-color: #856404; +} + +.list-group-item-danger { + color: #721c24; + background-color: #f5c6cb; +} + +.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus { + color: #721c24; + background-color: #f1b0b7; +} + +.list-group-item-danger.list-group-item-action.active { + color: #fff; + background-color: #721c24; + border-color: #721c24; +} + +.list-group-item-light { + color: #818182; + background-color: #fdfdfe; +} + +.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus { + color: #818182; + background-color: #ececf6; +} + +.list-group-item-light.list-group-item-action.active { + color: #fff; + background-color: #818182; + border-color: #818182; +} + +.list-group-item-dark { + color: #1b1e21; + background-color: #c6c8ca; +} + +.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus { + color: #1b1e21; + background-color: #b9bbbe; +} + +.list-group-item-dark.list-group-item-action.active { + color: #fff; + background-color: #1b1e21; + border-color: #1b1e21; +} + +.close { + float: right; + font-size: 1.5rem; + font-weight: 700; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + opacity: .5; +} + +.close:not(:disabled):not(.disabled) { + cursor: pointer; +} + +.close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus { + color: #000; + text-decoration: none; + opacity: .75; +} + +button.close { + padding: 0; + background-color: transparent; + border: 0; + -webkit-appearance: none; +} + +.modal-open { + overflow: hidden; +} + +.modal-open .modal { + overflow-x: hidden; + overflow-y: auto; +} + +.modal { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: hidden; + outline: 0; +} + +.modal-dialog { + position: relative; + width: auto; + margin: 0.5rem; + pointer-events: none; +} + +.modal.fade .modal-dialog { + transition: -webkit-transform 0.3s ease-out; + transition: transform 0.3s ease-out; + transition: transform 0.3s ease-out, -webkit-transform 0.3s ease-out; + -webkit-transform: translate(0, -25%); + transform: translate(0, -25%); +} + +@media screen and (prefers-reduced-motion: reduce) { + .modal.fade .modal-dialog { + transition: none; + } +} + +.modal.show .modal-dialog { + -webkit-transform: translate(0, 0); + transform: translate(0, 0); +} + +.modal-dialog-centered { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + min-height: calc(100% - (0.5rem * 2)); +} + +.modal-dialog-centered::before { + display: block; + height: calc(100vh - (0.5rem * 2)); + content: ""; +} + +.modal-content { + position: relative; + display: -ms-flexbox; + display: flex; + -ms-flex-direction: column; + flex-direction: column; + width: 100%; + pointer-events: auto; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; + outline: 0; +} + +.modal-backdrop { + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; +} + +.modal-backdrop.fade { + opacity: 0; +} + +.modal-backdrop.show { + opacity: 0.5; +} + +.modal-header { + display: -ms-flexbox; + display: flex; + -ms-flex-align: start; + align-items: flex-start; + -ms-flex-pack: justify; + justify-content: space-between; + padding: 1rem; + border-bottom: 1px solid #e9ecef; + border-top-left-radius: 0.3rem; + border-top-right-radius: 0.3rem; +} + +.modal-header .close { + padding: 1rem; + margin: -1rem -1rem -1rem auto; +} + +.modal-title { + margin-bottom: 0; + line-height: 1.5; +} + +.modal-body { + position: relative; + -ms-flex: 1 1 auto; + flex: 1 1 auto; + padding: 1rem; +} + +.modal-footer { + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: end; + justify-content: flex-end; + padding: 1rem; + border-top: 1px solid #e9ecef; +} + +.modal-footer > :not(:first-child) { + margin-left: .25rem; +} + +.modal-footer > :not(:last-child) { + margin-right: .25rem; +} + +.modal-scrollbar-measure { + position: absolute; + top: -9999px; + width: 50px; + height: 50px; + overflow: scroll; +} + +@media (min-width: 576px) { + .modal-dialog { + max-width: 500px; + margin: 1.75rem auto; + } + .modal-dialog-centered { + min-height: calc(100% - (1.75rem * 2)); + } + .modal-dialog-centered::before { + height: calc(100vh - (1.75rem * 2)); + } + .modal-sm { + max-width: 300px; + } +} + +@media (min-width: 992px) { + .modal-lg { + max-width: 800px; + } +} + +.tooltip { + position: absolute; + z-index: 1070; + display: block; + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + opacity: 0; +} + +.tooltip.show { + opacity: 0.9; +} + +.tooltip .arrow { + position: absolute; + display: block; + width: 0.8rem; + height: 0.4rem; +} + +.tooltip .arrow::before { + position: absolute; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-tooltip-top, .bs-tooltip-auto[x-placement^="top"] { + padding: 0.4rem 0; +} + +.bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^="top"] .arrow { + bottom: 0; +} + +.bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^="top"] .arrow::before { + top: 0; + border-width: 0.4rem 0.4rem 0; + border-top-color: #000; +} + +.bs-tooltip-right, .bs-tooltip-auto[x-placement^="right"] { + padding: 0 0.4rem; +} + +.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^="right"] .arrow { + left: 0; + width: 0.4rem; + height: 0.8rem; +} + +.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^="right"] .arrow::before { + right: 0; + border-width: 0.4rem 0.4rem 0.4rem 0; + border-right-color: #000; +} + +.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^="bottom"] { + padding: 0.4rem 0; +} + +.bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^="bottom"] .arrow { + top: 0; +} + +.bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^="bottom"] .arrow::before { + bottom: 0; + border-width: 0 0.4rem 0.4rem; + border-bottom-color: #000; +} + +.bs-tooltip-left, .bs-tooltip-auto[x-placement^="left"] { + padding: 0 0.4rem; +} + +.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^="left"] .arrow { + right: 0; + width: 0.4rem; + height: 0.8rem; +} + +.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^="left"] .arrow::before { + left: 0; + border-width: 0.4rem 0 0.4rem 0.4rem; + border-left-color: #000; +} + +.tooltip-inner { + max-width: 200px; + padding: 0.25rem 0.5rem; + color: #fff; + text-align: center; + background-color: #000; + border-radius: 0.25rem; +} + +.popover { + position: absolute; + top: 0; + left: 0; + z-index: 1060; + display: block; + max-width: 276px; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-style: normal; + font-weight: 400; + line-height: 1.5; + text-align: left; + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + letter-spacing: normal; + word-break: normal; + word-spacing: normal; + white-space: normal; + line-break: auto; + font-size: 0.875rem; + word-wrap: break-word; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 0.3rem; +} + +.popover .arrow { + position: absolute; + display: block; + width: 1rem; + height: 0.5rem; + margin: 0 0.3rem; +} + +.popover .arrow::before, .popover .arrow::after { + position: absolute; + display: block; + content: ""; + border-color: transparent; + border-style: solid; +} + +.bs-popover-top, .bs-popover-auto[x-placement^="top"] { + margin-bottom: 0.5rem; +} + +.bs-popover-top .arrow, .bs-popover-auto[x-placement^="top"] .arrow { + bottom: calc((0.5rem + 1px) * -1); +} + +.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before, +.bs-popover-top .arrow::after, +.bs-popover-auto[x-placement^="top"] .arrow::after { + border-width: 0.5rem 0.5rem 0; +} + +.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^="top"] .arrow::before { + bottom: 0; + border-top-color: rgba(0, 0, 0, 0.25); +} + + +.bs-popover-top .arrow::after, +.bs-popover-auto[x-placement^="top"] .arrow::after { + bottom: 1px; + border-top-color: #fff; +} + +.bs-popover-right, .bs-popover-auto[x-placement^="right"] { + margin-left: 0.5rem; +} + +.bs-popover-right .arrow, .bs-popover-auto[x-placement^="right"] .arrow { + left: calc((0.5rem + 1px) * -1); + width: 0.5rem; + height: 1rem; + margin: 0.3rem 0; +} + +.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before, +.bs-popover-right .arrow::after, +.bs-popover-auto[x-placement^="right"] .arrow::after { + border-width: 0.5rem 0.5rem 0.5rem 0; +} + +.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^="right"] .arrow::before { + left: 0; + border-right-color: rgba(0, 0, 0, 0.25); +} + + +.bs-popover-right .arrow::after, +.bs-popover-auto[x-placement^="right"] .arrow::after { + left: 1px; + border-right-color: #fff; +} + +.bs-popover-bottom, .bs-popover-auto[x-placement^="bottom"] { + margin-top: 0.5rem; +} + +.bs-popover-bottom .arrow, .bs-popover-auto[x-placement^="bottom"] .arrow { + top: calc((0.5rem + 1px) * -1); +} + +.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before, +.bs-popover-bottom .arrow::after, +.bs-popover-auto[x-placement^="bottom"] .arrow::after { + border-width: 0 0.5rem 0.5rem 0.5rem; +} + +.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^="bottom"] .arrow::before { + top: 0; + border-bottom-color: rgba(0, 0, 0, 0.25); +} + + +.bs-popover-bottom .arrow::after, +.bs-popover-auto[x-placement^="bottom"] .arrow::after { + top: 1px; + border-bottom-color: #fff; +} + +.bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^="bottom"] .popover-header::before { + position: absolute; + top: 0; + left: 50%; + display: block; + width: 1rem; + margin-left: -0.5rem; + content: ""; + border-bottom: 1px solid #f7f7f7; +} + +.bs-popover-left, .bs-popover-auto[x-placement^="left"] { + margin-right: 0.5rem; +} + +.bs-popover-left .arrow, .bs-popover-auto[x-placement^="left"] .arrow { + right: calc((0.5rem + 1px) * -1); + width: 0.5rem; + height: 1rem; + margin: 0.3rem 0; +} + +.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before, +.bs-popover-left .arrow::after, +.bs-popover-auto[x-placement^="left"] .arrow::after { + border-width: 0.5rem 0 0.5rem 0.5rem; +} + +.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^="left"] .arrow::before { + right: 0; + border-left-color: rgba(0, 0, 0, 0.25); +} + + +.bs-popover-left .arrow::after, +.bs-popover-auto[x-placement^="left"] .arrow::after { + right: 1px; + border-left-color: #fff; +} + +.popover-header { + padding: 0.5rem 0.75rem; + margin-bottom: 0; + font-size: 1rem; + color: inherit; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-top-left-radius: calc(0.3rem - 1px); + border-top-right-radius: calc(0.3rem - 1px); +} + +.popover-header:empty { + display: none; +} + +.popover-body { + padding: 0.5rem 0.75rem; + color: #212529; +} + +.carousel { + position: relative; +} + +.carousel-inner { + position: relative; + width: 100%; + overflow: hidden; +} + +.carousel-item { + position: relative; + display: none; + -ms-flex-align: center; + align-items: center; + width: 100%; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-perspective: 1000px; + perspective: 1000px; +} + +.carousel-item.active, +.carousel-item-next, +.carousel-item-prev { + display: block; + transition: -webkit-transform 0.6s ease; + transition: transform 0.6s ease; + transition: transform 0.6s ease, -webkit-transform 0.6s ease; +} + +@media screen and (prefers-reduced-motion: reduce) { + .carousel-item.active, + .carousel-item-next, + .carousel-item-prev { + transition: none; + } +} + +.carousel-item-next, +.carousel-item-prev { + position: absolute; + top: 0; +} + +.carousel-item-next.carousel-item-left, +.carousel-item-prev.carousel-item-right { + -webkit-transform: translateX(0); + transform: translateX(0); +} + +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-item-next.carousel-item-left, + .carousel-item-prev.carousel-item-right { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.carousel-item-next, +.active.carousel-item-right { + -webkit-transform: translateX(100%); + transform: translateX(100%); +} + +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-item-next, + .active.carousel-item-right { + -webkit-transform: translate3d(100%, 0, 0); + transform: translate3d(100%, 0, 0); + } +} + +.carousel-item-prev, +.active.carousel-item-left { + -webkit-transform: translateX(-100%); + transform: translateX(-100%); +} + +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-item-prev, + .active.carousel-item-left { + -webkit-transform: translate3d(-100%, 0, 0); + transform: translate3d(-100%, 0, 0); + } +} + +.carousel-fade .carousel-item { + opacity: 0; + transition-duration: .6s; + transition-property: opacity; +} + +.carousel-fade .carousel-item.active, +.carousel-fade .carousel-item-next.carousel-item-left, +.carousel-fade .carousel-item-prev.carousel-item-right { + opacity: 1; +} + +.carousel-fade .active.carousel-item-left, +.carousel-fade .active.carousel-item-right { + opacity: 0; +} + +.carousel-fade .carousel-item-next, +.carousel-fade .carousel-item-prev, +.carousel-fade .carousel-item.active, +.carousel-fade .active.carousel-item-left, +.carousel-fade .active.carousel-item-prev { + -webkit-transform: translateX(0); + transform: translateX(0); +} + +@supports ((-webkit-transform-style: preserve-3d) or (transform-style: preserve-3d)) { + .carousel-fade .carousel-item-next, + .carousel-fade .carousel-item-prev, + .carousel-fade .carousel-item.active, + .carousel-fade .active.carousel-item-left, + .carousel-fade .active.carousel-item-prev { + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); + } +} + +.carousel-control-prev, +.carousel-control-next { + position: absolute; + top: 0; + bottom: 0; + display: -ms-flexbox; + display: flex; + -ms-flex-align: center; + align-items: center; + -ms-flex-pack: center; + justify-content: center; + width: 15%; + color: #fff; + text-align: center; + opacity: 0.5; +} + +.carousel-control-prev:hover, .carousel-control-prev:focus, +.carousel-control-next:hover, +.carousel-control-next:focus { + color: #fff; + text-decoration: none; + outline: 0; + opacity: .9; +} + +.carousel-control-prev { + left: 0; +} + +.carousel-control-next { + right: 0; +} + +.carousel-control-prev-icon, +.carousel-control-next-icon { + display: inline-block; + width: 20px; + height: 20px; + background: transparent no-repeat center center; + background-size: 100% 100%; +} + +.carousel-control-prev-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E"); +} + +.carousel-control-next-icon { + background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E"); +} + +.carousel-indicators { + position: absolute; + right: 0; + bottom: 10px; + left: 0; + z-index: 15; + display: -ms-flexbox; + display: flex; + -ms-flex-pack: center; + justify-content: center; + padding-left: 0; + margin-right: 15%; + margin-left: 15%; + list-style: none; +} + +.carousel-indicators li { + position: relative; + -ms-flex: 0 1 auto; + flex: 0 1 auto; + width: 30px; + height: 3px; + margin-right: 3px; + margin-left: 3px; + text-indent: -999px; + cursor: pointer; + background-color: rgba(255, 255, 255, 0.5); +} + +.carousel-indicators li::before { + position: absolute; + top: -10px; + left: 0; + display: inline-block; + width: 100%; + height: 10px; + content: ""; +} + +.carousel-indicators li::after { + position: absolute; + bottom: -10px; + left: 0; + display: inline-block; + width: 100%; + height: 10px; + content: ""; +} + +.carousel-indicators .active { + background-color: #fff; +} + +.carousel-caption { + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; +} + +.align-baseline { + vertical-align: baseline !important; +} + +.align-top { + vertical-align: top !important; +} + +.align-middle { + vertical-align: middle !important; +} + +.align-bottom { + vertical-align: bottom !important; +} + +.align-text-bottom { + vertical-align: text-bottom !important; +} + +.align-text-top { + vertical-align: text-top !important; +} + +.bg-primary { + background-color: #007bff !important; +} + +a.bg-primary:hover, a.bg-primary:focus, +button.bg-primary:hover, +button.bg-primary:focus { + background-color: #0062cc !important; +} + +.bg-secondary { + background-color: #6c757d !important; +} + +a.bg-secondary:hover, a.bg-secondary:focus, +button.bg-secondary:hover, +button.bg-secondary:focus { + background-color: #545b62 !important; +} + +.bg-success { + background-color: #28a745 !important; +} + +a.bg-success:hover, a.bg-success:focus, +button.bg-success:hover, +button.bg-success:focus { + background-color: #1e7e34 !important; +} + +.bg-info { + background-color: #17a2b8 !important; +} + +a.bg-info:hover, a.bg-info:focus, +button.bg-info:hover, +button.bg-info:focus { + background-color: #117a8b !important; +} + +.bg-warning { + background-color: #ffc107 !important; +} + +a.bg-warning:hover, a.bg-warning:focus, +button.bg-warning:hover, +button.bg-warning:focus { + background-color: #d39e00 !important; +} + +.bg-danger { + background-color: #dc3545 !important; +} + +a.bg-danger:hover, a.bg-danger:focus, +button.bg-danger:hover, +button.bg-danger:focus { + background-color: #bd2130 !important; +} + +.bg-light { + background-color: #f8f9fa !important; +} + +a.bg-light:hover, a.bg-light:focus, +button.bg-light:hover, +button.bg-light:focus { + background-color: #dae0e5 !important; +} + +.bg-dark { + background-color: #343a40 !important; +} + +a.bg-dark:hover, a.bg-dark:focus, +button.bg-dark:hover, +button.bg-dark:focus { + background-color: #1d2124 !important; +} + +.bg-white { + background-color: #fff !important; +} + +.bg-transparent { + background-color: transparent !important; +} + +.border { + border: 1px solid #dee2e6 !important; +} + +.border-top { + border-top: 1px solid #dee2e6 !important; +} + +.border-right { + border-right: 1px solid #dee2e6 !important; +} + +.border-bottom { + border-bottom: 1px solid #dee2e6 !important; +} + +.border-left { + border-left: 1px solid #dee2e6 !important; +} + +.border-0 { + border: 0 !important; +} + +.border-top-0 { + border-top: 0 !important; +} + +.border-right-0 { + border-right: 0 !important; +} + +.border-bottom-0 { + border-bottom: 0 !important; +} + +.border-left-0 { + border-left: 0 !important; +} + +.border-primary { + border-color: #007bff !important; +} + +.border-secondary { + border-color: #6c757d !important; +} + +.border-success { + border-color: #28a745 !important; +} + +.border-info { + border-color: #17a2b8 !important; +} + +.border-warning { + border-color: #ffc107 !important; +} + +.border-danger { + border-color: #dc3545 !important; +} + +.border-light { + border-color: #f8f9fa !important; +} + +.border-dark { + border-color: #343a40 !important; +} + +.border-white { + border-color: #fff !important; +} + +.rounded { + border-radius: 0.25rem !important; +} + +.rounded-top { + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; +} + +.rounded-right { + border-top-right-radius: 0.25rem !important; + border-bottom-right-radius: 0.25rem !important; +} + +.rounded-bottom { + border-bottom-right-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-left { + border-top-left-radius: 0.25rem !important; + border-bottom-left-radius: 0.25rem !important; +} + +.rounded-circle { + border-radius: 50% !important; +} + +.rounded-0 { + border-radius: 0 !important; +} + +.clearfix::after { + display: block; + clear: both; + content: ""; +} + +.d-none { + display: none !important; +} + +.d-inline { + display: inline !important; +} + +.d-inline-block { + display: inline-block !important; +} + +.d-block { + display: block !important; +} + +.d-table { + display: table !important; +} + +.d-table-row { + display: table-row !important; +} + +.d-table-cell { + display: table-cell !important; +} + +.d-flex { + display: -ms-flexbox !important; + display: flex !important; +} + +.d-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; +} + +@media (min-width: 576px) { + .d-sm-none { + display: none !important; + } + .d-sm-inline { + display: inline !important; + } + .d-sm-inline-block { + display: inline-block !important; + } + .d-sm-block { + display: block !important; + } + .d-sm-table { + display: table !important; + } + .d-sm-table-row { + display: table-row !important; + } + .d-sm-table-cell { + display: table-cell !important; + } + .d-sm-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-sm-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 768px) { + .d-md-none { + display: none !important; + } + .d-md-inline { + display: inline !important; + } + .d-md-inline-block { + display: inline-block !important; + } + .d-md-block { + display: block !important; + } + .d-md-table { + display: table !important; + } + .d-md-table-row { + display: table-row !important; + } + .d-md-table-cell { + display: table-cell !important; + } + .d-md-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-md-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 992px) { + .d-lg-none { + display: none !important; + } + .d-lg-inline { + display: inline !important; + } + .d-lg-inline-block { + display: inline-block !important; + } + .d-lg-block { + display: block !important; + } + .d-lg-table { + display: table !important; + } + .d-lg-table-row { + display: table-row !important; + } + .d-lg-table-cell { + display: table-cell !important; + } + .d-lg-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-lg-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media (min-width: 1200px) { + .d-xl-none { + display: none !important; + } + .d-xl-inline { + display: inline !important; + } + .d-xl-inline-block { + display: inline-block !important; + } + .d-xl-block { + display: block !important; + } + .d-xl-table { + display: table !important; + } + .d-xl-table-row { + display: table-row !important; + } + .d-xl-table-cell { + display: table-cell !important; + } + .d-xl-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-xl-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +@media print { + .d-print-none { + display: none !important; + } + .d-print-inline { + display: inline !important; + } + .d-print-inline-block { + display: inline-block !important; + } + .d-print-block { + display: block !important; + } + .d-print-table { + display: table !important; + } + .d-print-table-row { + display: table-row !important; + } + .d-print-table-cell { + display: table-cell !important; + } + .d-print-flex { + display: -ms-flexbox !important; + display: flex !important; + } + .d-print-inline-flex { + display: -ms-inline-flexbox !important; + display: inline-flex !important; + } +} + +.embed-responsive { + position: relative; + display: block; + width: 100%; + padding: 0; + overflow: hidden; +} + +.embed-responsive::before { + display: block; + content: ""; +} + +.embed-responsive .embed-responsive-item, +.embed-responsive iframe, +.embed-responsive embed, +.embed-responsive object, +.embed-responsive video { + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 100%; + height: 100%; + border: 0; +} + +.embed-responsive-21by9::before { + padding-top: 42.857143%; +} + +.embed-responsive-16by9::before { + padding-top: 56.25%; +} + +.embed-responsive-4by3::before { + padding-top: 75%; +} + +.embed-responsive-1by1::before { + padding-top: 100%; +} + +.flex-row { + -ms-flex-direction: row !important; + flex-direction: row !important; +} + +.flex-column { + -ms-flex-direction: column !important; + flex-direction: column !important; +} + +.flex-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; +} + +.flex-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; +} + +.flex-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; +} + +.flex-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; +} + +.flex-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; +} + +.flex-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; +} + +.flex-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; +} + +.flex-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; +} + +.flex-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; +} + +.flex-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; +} + +.justify-content-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; +} + +.justify-content-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; +} + +.justify-content-center { + -ms-flex-pack: center !important; + justify-content: center !important; +} + +.justify-content-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; +} + +.justify-content-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; +} + +.align-items-start { + -ms-flex-align: start !important; + align-items: flex-start !important; +} + +.align-items-end { + -ms-flex-align: end !important; + align-items: flex-end !important; +} + +.align-items-center { + -ms-flex-align: center !important; + align-items: center !important; +} + +.align-items-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; +} + +.align-items-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; +} + +.align-content-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; +} + +.align-content-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; +} + +.align-content-center { + -ms-flex-line-pack: center !important; + align-content: center !important; +} + +.align-content-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; +} + +.align-content-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; +} + +.align-content-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; +} + +.align-self-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; +} + +.align-self-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; +} + +.align-self-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; +} + +.align-self-center { + -ms-flex-item-align: center !important; + align-self: center !important; +} + +.align-self-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; +} + +.align-self-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; +} + +@media (min-width: 576px) { + .flex-sm-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-sm-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-sm-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-sm-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-sm-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-sm-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-sm-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-sm-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-sm-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-sm-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-sm-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-sm-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-sm-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-sm-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-sm-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-sm-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-sm-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-sm-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-sm-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-sm-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-sm-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-sm-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-sm-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-sm-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-sm-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-sm-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-sm-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-sm-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-sm-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-sm-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-sm-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-sm-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-sm-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-sm-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 768px) { + .flex-md-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-md-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-md-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-md-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-md-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-md-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-md-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-md-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-md-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-md-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-md-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-md-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-md-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-md-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-md-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-md-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-md-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-md-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-md-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-md-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-md-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-md-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-md-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-md-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-md-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-md-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-md-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-md-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-md-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-md-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-md-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-md-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-md-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-md-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 992px) { + .flex-lg-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-lg-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-lg-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-lg-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-lg-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-lg-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-lg-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-lg-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-lg-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-lg-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-lg-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-lg-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-lg-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-lg-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-lg-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-lg-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-lg-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-lg-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-lg-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-lg-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-lg-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-lg-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-lg-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-lg-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-lg-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-lg-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-lg-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-lg-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-lg-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-lg-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-lg-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-lg-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-lg-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-lg-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +@media (min-width: 1200px) { + .flex-xl-row { + -ms-flex-direction: row !important; + flex-direction: row !important; + } + .flex-xl-column { + -ms-flex-direction: column !important; + flex-direction: column !important; + } + .flex-xl-row-reverse { + -ms-flex-direction: row-reverse !important; + flex-direction: row-reverse !important; + } + .flex-xl-column-reverse { + -ms-flex-direction: column-reverse !important; + flex-direction: column-reverse !important; + } + .flex-xl-wrap { + -ms-flex-wrap: wrap !important; + flex-wrap: wrap !important; + } + .flex-xl-nowrap { + -ms-flex-wrap: nowrap !important; + flex-wrap: nowrap !important; + } + .flex-xl-wrap-reverse { + -ms-flex-wrap: wrap-reverse !important; + flex-wrap: wrap-reverse !important; + } + .flex-xl-fill { + -ms-flex: 1 1 auto !important; + flex: 1 1 auto !important; + } + .flex-xl-grow-0 { + -ms-flex-positive: 0 !important; + flex-grow: 0 !important; + } + .flex-xl-grow-1 { + -ms-flex-positive: 1 !important; + flex-grow: 1 !important; + } + .flex-xl-shrink-0 { + -ms-flex-negative: 0 !important; + flex-shrink: 0 !important; + } + .flex-xl-shrink-1 { + -ms-flex-negative: 1 !important; + flex-shrink: 1 !important; + } + .justify-content-xl-start { + -ms-flex-pack: start !important; + justify-content: flex-start !important; + } + .justify-content-xl-end { + -ms-flex-pack: end !important; + justify-content: flex-end !important; + } + .justify-content-xl-center { + -ms-flex-pack: center !important; + justify-content: center !important; + } + .justify-content-xl-between { + -ms-flex-pack: justify !important; + justify-content: space-between !important; + } + .justify-content-xl-around { + -ms-flex-pack: distribute !important; + justify-content: space-around !important; + } + .align-items-xl-start { + -ms-flex-align: start !important; + align-items: flex-start !important; + } + .align-items-xl-end { + -ms-flex-align: end !important; + align-items: flex-end !important; + } + .align-items-xl-center { + -ms-flex-align: center !important; + align-items: center !important; + } + .align-items-xl-baseline { + -ms-flex-align: baseline !important; + align-items: baseline !important; + } + .align-items-xl-stretch { + -ms-flex-align: stretch !important; + align-items: stretch !important; + } + .align-content-xl-start { + -ms-flex-line-pack: start !important; + align-content: flex-start !important; + } + .align-content-xl-end { + -ms-flex-line-pack: end !important; + align-content: flex-end !important; + } + .align-content-xl-center { + -ms-flex-line-pack: center !important; + align-content: center !important; + } + .align-content-xl-between { + -ms-flex-line-pack: justify !important; + align-content: space-between !important; + } + .align-content-xl-around { + -ms-flex-line-pack: distribute !important; + align-content: space-around !important; + } + .align-content-xl-stretch { + -ms-flex-line-pack: stretch !important; + align-content: stretch !important; + } + .align-self-xl-auto { + -ms-flex-item-align: auto !important; + align-self: auto !important; + } + .align-self-xl-start { + -ms-flex-item-align: start !important; + align-self: flex-start !important; + } + .align-self-xl-end { + -ms-flex-item-align: end !important; + align-self: flex-end !important; + } + .align-self-xl-center { + -ms-flex-item-align: center !important; + align-self: center !important; + } + .align-self-xl-baseline { + -ms-flex-item-align: baseline !important; + align-self: baseline !important; + } + .align-self-xl-stretch { + -ms-flex-item-align: stretch !important; + align-self: stretch !important; + } +} + +.float-left { + float: left !important; +} + +.float-right { + float: right !important; +} + +.float-none { + float: none !important; +} + +@media (min-width: 576px) { + .float-sm-left { + float: left !important; + } + .float-sm-right { + float: right !important; + } + .float-sm-none { + float: none !important; + } +} + +@media (min-width: 768px) { + .float-md-left { + float: left !important; + } + .float-md-right { + float: right !important; + } + .float-md-none { + float: none !important; + } +} + +@media (min-width: 992px) { + .float-lg-left { + float: left !important; + } + .float-lg-right { + float: right !important; + } + .float-lg-none { + float: none !important; + } +} + +@media (min-width: 1200px) { + .float-xl-left { + float: left !important; + } + .float-xl-right { + float: right !important; + } + .float-xl-none { + float: none !important; + } +} + +.position-static { + position: static !important; +} + +.position-relative { + position: relative !important; +} + +.position-absolute { + position: absolute !important; +} + +.position-fixed { + position: fixed !important; +} + +.position-sticky { + position: -webkit-sticky !important; + position: sticky !important; +} + +.fixed-top { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1030; +} + +.fixed-bottom { + position: fixed; + right: 0; + bottom: 0; + left: 0; + z-index: 1030; +} + +@supports ((position: -webkit-sticky) or (position: sticky)) { + .sticky-top { + position: -webkit-sticky; + position: sticky; + top: 0; + z-index: 1020; + } +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} + +.sr-only-focusable:active, .sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + overflow: visible; + clip: auto; + white-space: normal; +} + +.shadow-sm { + box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important; +} + +.shadow { + box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important; +} + +.shadow-lg { + box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important; +} + +.shadow-none { + box-shadow: none !important; +} + +.w-25 { + width: 25% !important; +} + +.w-50 { + width: 50% !important; +} + +.w-75 { + width: 75% !important; +} + +.w-100 { + width: 100% !important; +} + +.w-auto { + width: auto !important; +} + +.h-25 { + height: 25% !important; +} + +.h-50 { + height: 50% !important; +} + +.h-75 { + height: 75% !important; +} + +.h-100 { + height: 100% !important; +} + +.h-auto { + height: auto !important; +} + +.mw-100 { + max-width: 100% !important; +} + +.mh-100 { + max-height: 100% !important; +} + +.m-0 { + margin: 0 !important; +} + +.mt-0, +.my-0 { + margin-top: 0 !important; +} + +.mr-0, +.mx-0 { + margin-right: 0 !important; +} + +.mb-0, +.my-0 { + margin-bottom: 0 !important; +} + +.ml-0, +.mx-0 { + margin-left: 0 !important; +} + +.m-1 { + margin: 0.25rem !important; +} + +.mt-1, +.my-1 { + margin-top: 0.25rem !important; +} + +.mr-1, +.mx-1 { + margin-right: 0.25rem !important; +} + +.mb-1, +.my-1 { + margin-bottom: 0.25rem !important; +} + +.ml-1, +.mx-1 { + margin-left: 0.25rem !important; +} + +.m-2 { + margin: 0.5rem !important; +} + +.mt-2, +.my-2 { + margin-top: 0.5rem !important; +} + +.mr-2, +.mx-2 { + margin-right: 0.5rem !important; +} + +.mb-2, +.my-2 { + margin-bottom: 0.5rem !important; +} + +.ml-2, +.mx-2 { + margin-left: 0.5rem !important; +} + +.m-3 { + margin: 1rem !important; +} + +.mt-3, +.my-3 { + margin-top: 1rem !important; +} + +.mr-3, +.mx-3 { + margin-right: 1rem !important; +} + +.mb-3, +.my-3 { + margin-bottom: 1rem !important; +} + +.ml-3, +.mx-3 { + margin-left: 1rem !important; +} + +.m-4 { + margin: 1.5rem !important; +} + +.mt-4, +.my-4 { + margin-top: 1.5rem !important; +} + +.mr-4, +.mx-4 { + margin-right: 1.5rem !important; +} + +.mb-4, +.my-4 { + margin-bottom: 1.5rem !important; +} + +.ml-4, +.mx-4 { + margin-left: 1.5rem !important; +} + +.m-5 { + margin: 3rem !important; +} + +.mt-5, +.my-5 { + margin-top: 3rem !important; +} + +.mr-5, +.mx-5 { + margin-right: 3rem !important; +} + +.mb-5, +.my-5 { + margin-bottom: 3rem !important; +} + +.ml-5, +.mx-5 { + margin-left: 3rem !important; +} + +.p-0 { + padding: 0 !important; +} + +.pt-0, +.py-0 { + padding-top: 0 !important; +} + +.pr-0, +.px-0 { + padding-right: 0 !important; +} + +.pb-0, +.py-0 { + padding-bottom: 0 !important; +} + +.pl-0, +.px-0 { + padding-left: 0 !important; +} + +.p-1 { + padding: 0.25rem !important; +} + +.pt-1, +.py-1 { + padding-top: 0.25rem !important; +} + +.pr-1, +.px-1 { + padding-right: 0.25rem !important; +} + +.pb-1, +.py-1 { + padding-bottom: 0.25rem !important; +} + +.pl-1, +.px-1 { + padding-left: 0.25rem !important; +} + +.p-2 { + padding: 0.5rem !important; +} + +.pt-2, +.py-2 { + padding-top: 0.5rem !important; +} + +.pr-2, +.px-2 { + padding-right: 0.5rem !important; +} + +.pb-2, +.py-2 { + padding-bottom: 0.5rem !important; +} + +.pl-2, +.px-2 { + padding-left: 0.5rem !important; +} + +.p-3 { + padding: 1rem !important; +} + +.pt-3, +.py-3 { + padding-top: 1rem !important; +} + +.pr-3, +.px-3 { + padding-right: 1rem !important; +} + +.pb-3, +.py-3 { + padding-bottom: 1rem !important; +} + +.pl-3, +.px-3 { + padding-left: 1rem !important; +} + +.p-4 { + padding: 1.5rem !important; +} + +.pt-4, +.py-4 { + padding-top: 1.5rem !important; +} + +.pr-4, +.px-4 { + padding-right: 1.5rem !important; +} + +.pb-4, +.py-4 { + padding-bottom: 1.5rem !important; +} + +.pl-4, +.px-4 { + padding-left: 1.5rem !important; +} + +.p-5 { + padding: 3rem !important; +} + +.pt-5, +.py-5 { + padding-top: 3rem !important; +} + +.pr-5, +.px-5 { + padding-right: 3rem !important; +} + +.pb-5, +.py-5 { + padding-bottom: 3rem !important; +} + +.pl-5, +.px-5 { + padding-left: 3rem !important; +} + +.m-auto { + margin: auto !important; +} + +.mt-auto, +.my-auto { + margin-top: auto !important; +} + +.mr-auto, +.mx-auto { + margin-right: auto !important; +} + +.mb-auto, +.my-auto { + margin-bottom: auto !important; +} + +.ml-auto, +.mx-auto { + margin-left: auto !important; +} + +@media (min-width: 576px) { + .m-sm-0 { + margin: 0 !important; + } + .mt-sm-0, + .my-sm-0 { + margin-top: 0 !important; + } + .mr-sm-0, + .mx-sm-0 { + margin-right: 0 !important; + } + .mb-sm-0, + .my-sm-0 { + margin-bottom: 0 !important; + } + .ml-sm-0, + .mx-sm-0 { + margin-left: 0 !important; + } + .m-sm-1 { + margin: 0.25rem !important; + } + .mt-sm-1, + .my-sm-1 { + margin-top: 0.25rem !important; + } + .mr-sm-1, + .mx-sm-1 { + margin-right: 0.25rem !important; + } + .mb-sm-1, + .my-sm-1 { + margin-bottom: 0.25rem !important; + } + .ml-sm-1, + .mx-sm-1 { + margin-left: 0.25rem !important; + } + .m-sm-2 { + margin: 0.5rem !important; + } + .mt-sm-2, + .my-sm-2 { + margin-top: 0.5rem !important; + } + .mr-sm-2, + .mx-sm-2 { + margin-right: 0.5rem !important; + } + .mb-sm-2, + .my-sm-2 { + margin-bottom: 0.5rem !important; + } + .ml-sm-2, + .mx-sm-2 { + margin-left: 0.5rem !important; + } + .m-sm-3 { + margin: 1rem !important; + } + .mt-sm-3, + .my-sm-3 { + margin-top: 1rem !important; + } + .mr-sm-3, + .mx-sm-3 { + margin-right: 1rem !important; + } + .mb-sm-3, + .my-sm-3 { + margin-bottom: 1rem !important; + } + .ml-sm-3, + .mx-sm-3 { + margin-left: 1rem !important; + } + .m-sm-4 { + margin: 1.5rem !important; + } + .mt-sm-4, + .my-sm-4 { + margin-top: 1.5rem !important; + } + .mr-sm-4, + .mx-sm-4 { + margin-right: 1.5rem !important; + } + .mb-sm-4, + .my-sm-4 { + margin-bottom: 1.5rem !important; + } + .ml-sm-4, + .mx-sm-4 { + margin-left: 1.5rem !important; + } + .m-sm-5 { + margin: 3rem !important; + } + .mt-sm-5, + .my-sm-5 { + margin-top: 3rem !important; + } + .mr-sm-5, + .mx-sm-5 { + margin-right: 3rem !important; + } + .mb-sm-5, + .my-sm-5 { + margin-bottom: 3rem !important; + } + .ml-sm-5, + .mx-sm-5 { + margin-left: 3rem !important; + } + .p-sm-0 { + padding: 0 !important; + } + .pt-sm-0, + .py-sm-0 { + padding-top: 0 !important; + } + .pr-sm-0, + .px-sm-0 { + padding-right: 0 !important; + } + .pb-sm-0, + .py-sm-0 { + padding-bottom: 0 !important; + } + .pl-sm-0, + .px-sm-0 { + padding-left: 0 !important; + } + .p-sm-1 { + padding: 0.25rem !important; + } + .pt-sm-1, + .py-sm-1 { + padding-top: 0.25rem !important; + } + .pr-sm-1, + .px-sm-1 { + padding-right: 0.25rem !important; + } + .pb-sm-1, + .py-sm-1 { + padding-bottom: 0.25rem !important; + } + .pl-sm-1, + .px-sm-1 { + padding-left: 0.25rem !important; + } + .p-sm-2 { + padding: 0.5rem !important; + } + .pt-sm-2, + .py-sm-2 { + padding-top: 0.5rem !important; + } + .pr-sm-2, + .px-sm-2 { + padding-right: 0.5rem !important; + } + .pb-sm-2, + .py-sm-2 { + padding-bottom: 0.5rem !important; + } + .pl-sm-2, + .px-sm-2 { + padding-left: 0.5rem !important; + } + .p-sm-3 { + padding: 1rem !important; + } + .pt-sm-3, + .py-sm-3 { + padding-top: 1rem !important; + } + .pr-sm-3, + .px-sm-3 { + padding-right: 1rem !important; + } + .pb-sm-3, + .py-sm-3 { + padding-bottom: 1rem !important; + } + .pl-sm-3, + .px-sm-3 { + padding-left: 1rem !important; + } + .p-sm-4 { + padding: 1.5rem !important; + } + .pt-sm-4, + .py-sm-4 { + padding-top: 1.5rem !important; + } + .pr-sm-4, + .px-sm-4 { + padding-right: 1.5rem !important; + } + .pb-sm-4, + .py-sm-4 { + padding-bottom: 1.5rem !important; + } + .pl-sm-4, + .px-sm-4 { + padding-left: 1.5rem !important; + } + .p-sm-5 { + padding: 3rem !important; + } + .pt-sm-5, + .py-sm-5 { + padding-top: 3rem !important; + } + .pr-sm-5, + .px-sm-5 { + padding-right: 3rem !important; + } + .pb-sm-5, + .py-sm-5 { + padding-bottom: 3rem !important; + } + .pl-sm-5, + .px-sm-5 { + padding-left: 3rem !important; + } + .m-sm-auto { + margin: auto !important; + } + .mt-sm-auto, + .my-sm-auto { + margin-top: auto !important; + } + .mr-sm-auto, + .mx-sm-auto { + margin-right: auto !important; + } + .mb-sm-auto, + .my-sm-auto { + margin-bottom: auto !important; + } + .ml-sm-auto, + .mx-sm-auto { + margin-left: auto !important; + } +} + +@media (min-width: 768px) { + .m-md-0 { + margin: 0 !important; + } + .mt-md-0, + .my-md-0 { + margin-top: 0 !important; + } + .mr-md-0, + .mx-md-0 { + margin-right: 0 !important; + } + .mb-md-0, + .my-md-0 { + margin-bottom: 0 !important; + } + .ml-md-0, + .mx-md-0 { + margin-left: 0 !important; + } + .m-md-1 { + margin: 0.25rem !important; + } + .mt-md-1, + .my-md-1 { + margin-top: 0.25rem !important; + } + .mr-md-1, + .mx-md-1 { + margin-right: 0.25rem !important; + } + .mb-md-1, + .my-md-1 { + margin-bottom: 0.25rem !important; + } + .ml-md-1, + .mx-md-1 { + margin-left: 0.25rem !important; + } + .m-md-2 { + margin: 0.5rem !important; + } + .mt-md-2, + .my-md-2 { + margin-top: 0.5rem !important; + } + .mr-md-2, + .mx-md-2 { + margin-right: 0.5rem !important; + } + .mb-md-2, + .my-md-2 { + margin-bottom: 0.5rem !important; + } + .ml-md-2, + .mx-md-2 { + margin-left: 0.5rem !important; + } + .m-md-3 { + margin: 1rem !important; + } + .mt-md-3, + .my-md-3 { + margin-top: 1rem !important; + } + .mr-md-3, + .mx-md-3 { + margin-right: 1rem !important; + } + .mb-md-3, + .my-md-3 { + margin-bottom: 1rem !important; + } + .ml-md-3, + .mx-md-3 { + margin-left: 1rem !important; + } + .m-md-4 { + margin: 1.5rem !important; + } + .mt-md-4, + .my-md-4 { + margin-top: 1.5rem !important; + } + .mr-md-4, + .mx-md-4 { + margin-right: 1.5rem !important; + } + .mb-md-4, + .my-md-4 { + margin-bottom: 1.5rem !important; + } + .ml-md-4, + .mx-md-4 { + margin-left: 1.5rem !important; + } + .m-md-5 { + margin: 3rem !important; + } + .mt-md-5, + .my-md-5 { + margin-top: 3rem !important; + } + .mr-md-5, + .mx-md-5 { + margin-right: 3rem !important; + } + .mb-md-5, + .my-md-5 { + margin-bottom: 3rem !important; + } + .ml-md-5, + .mx-md-5 { + margin-left: 3rem !important; + } + .p-md-0 { + padding: 0 !important; + } + .pt-md-0, + .py-md-0 { + padding-top: 0 !important; + } + .pr-md-0, + .px-md-0 { + padding-right: 0 !important; + } + .pb-md-0, + .py-md-0 { + padding-bottom: 0 !important; + } + .pl-md-0, + .px-md-0 { + padding-left: 0 !important; + } + .p-md-1 { + padding: 0.25rem !important; + } + .pt-md-1, + .py-md-1 { + padding-top: 0.25rem !important; + } + .pr-md-1, + .px-md-1 { + padding-right: 0.25rem !important; + } + .pb-md-1, + .py-md-1 { + padding-bottom: 0.25rem !important; + } + .pl-md-1, + .px-md-1 { + padding-left: 0.25rem !important; + } + .p-md-2 { + padding: 0.5rem !important; + } + .pt-md-2, + .py-md-2 { + padding-top: 0.5rem !important; + } + .pr-md-2, + .px-md-2 { + padding-right: 0.5rem !important; + } + .pb-md-2, + .py-md-2 { + padding-bottom: 0.5rem !important; + } + .pl-md-2, + .px-md-2 { + padding-left: 0.5rem !important; + } + .p-md-3 { + padding: 1rem !important; + } + .pt-md-3, + .py-md-3 { + padding-top: 1rem !important; + } + .pr-md-3, + .px-md-3 { + padding-right: 1rem !important; + } + .pb-md-3, + .py-md-3 { + padding-bottom: 1rem !important; + } + .pl-md-3, + .px-md-3 { + padding-left: 1rem !important; + } + .p-md-4 { + padding: 1.5rem !important; + } + .pt-md-4, + .py-md-4 { + padding-top: 1.5rem !important; + } + .pr-md-4, + .px-md-4 { + padding-right: 1.5rem !important; + } + .pb-md-4, + .py-md-4 { + padding-bottom: 1.5rem !important; + } + .pl-md-4, + .px-md-4 { + padding-left: 1.5rem !important; + } + .p-md-5 { + padding: 3rem !important; + } + .pt-md-5, + .py-md-5 { + padding-top: 3rem !important; + } + .pr-md-5, + .px-md-5 { + padding-right: 3rem !important; + } + .pb-md-5, + .py-md-5 { + padding-bottom: 3rem !important; + } + .pl-md-5, + .px-md-5 { + padding-left: 3rem !important; + } + .m-md-auto { + margin: auto !important; + } + .mt-md-auto, + .my-md-auto { + margin-top: auto !important; + } + .mr-md-auto, + .mx-md-auto { + margin-right: auto !important; + } + .mb-md-auto, + .my-md-auto { + margin-bottom: auto !important; + } + .ml-md-auto, + .mx-md-auto { + margin-left: auto !important; + } +} + +@media (min-width: 992px) { + .m-lg-0 { + margin: 0 !important; + } + .mt-lg-0, + .my-lg-0 { + margin-top: 0 !important; + } + .mr-lg-0, + .mx-lg-0 { + margin-right: 0 !important; + } + .mb-lg-0, + .my-lg-0 { + margin-bottom: 0 !important; + } + .ml-lg-0, + .mx-lg-0 { + margin-left: 0 !important; + } + .m-lg-1 { + margin: 0.25rem !important; + } + .mt-lg-1, + .my-lg-1 { + margin-top: 0.25rem !important; + } + .mr-lg-1, + .mx-lg-1 { + margin-right: 0.25rem !important; + } + .mb-lg-1, + .my-lg-1 { + margin-bottom: 0.25rem !important; + } + .ml-lg-1, + .mx-lg-1 { + margin-left: 0.25rem !important; + } + .m-lg-2 { + margin: 0.5rem !important; + } + .mt-lg-2, + .my-lg-2 { + margin-top: 0.5rem !important; + } + .mr-lg-2, + .mx-lg-2 { + margin-right: 0.5rem !important; + } + .mb-lg-2, + .my-lg-2 { + margin-bottom: 0.5rem !important; + } + .ml-lg-2, + .mx-lg-2 { + margin-left: 0.5rem !important; + } + .m-lg-3 { + margin: 1rem !important; + } + .mt-lg-3, + .my-lg-3 { + margin-top: 1rem !important; + } + .mr-lg-3, + .mx-lg-3 { + margin-right: 1rem !important; + } + .mb-lg-3, + .my-lg-3 { + margin-bottom: 1rem !important; + } + .ml-lg-3, + .mx-lg-3 { + margin-left: 1rem !important; + } + .m-lg-4 { + margin: 1.5rem !important; + } + .mt-lg-4, + .my-lg-4 { + margin-top: 1.5rem !important; + } + .mr-lg-4, + .mx-lg-4 { + margin-right: 1.5rem !important; + } + .mb-lg-4, + .my-lg-4 { + margin-bottom: 1.5rem !important; + } + .ml-lg-4, + .mx-lg-4 { + margin-left: 1.5rem !important; + } + .m-lg-5 { + margin: 3rem !important; + } + .mt-lg-5, + .my-lg-5 { + margin-top: 3rem !important; + } + .mr-lg-5, + .mx-lg-5 { + margin-right: 3rem !important; + } + .mb-lg-5, + .my-lg-5 { + margin-bottom: 3rem !important; + } + .ml-lg-5, + .mx-lg-5 { + margin-left: 3rem !important; + } + .p-lg-0 { + padding: 0 !important; + } + .pt-lg-0, + .py-lg-0 { + padding-top: 0 !important; + } + .pr-lg-0, + .px-lg-0 { + padding-right: 0 !important; + } + .pb-lg-0, + .py-lg-0 { + padding-bottom: 0 !important; + } + .pl-lg-0, + .px-lg-0 { + padding-left: 0 !important; + } + .p-lg-1 { + padding: 0.25rem !important; + } + .pt-lg-1, + .py-lg-1 { + padding-top: 0.25rem !important; + } + .pr-lg-1, + .px-lg-1 { + padding-right: 0.25rem !important; + } + .pb-lg-1, + .py-lg-1 { + padding-bottom: 0.25rem !important; + } + .pl-lg-1, + .px-lg-1 { + padding-left: 0.25rem !important; + } + .p-lg-2 { + padding: 0.5rem !important; + } + .pt-lg-2, + .py-lg-2 { + padding-top: 0.5rem !important; + } + .pr-lg-2, + .px-lg-2 { + padding-right: 0.5rem !important; + } + .pb-lg-2, + .py-lg-2 { + padding-bottom: 0.5rem !important; + } + .pl-lg-2, + .px-lg-2 { + padding-left: 0.5rem !important; + } + .p-lg-3 { + padding: 1rem !important; + } + .pt-lg-3, + .py-lg-3 { + padding-top: 1rem !important; + } + .pr-lg-3, + .px-lg-3 { + padding-right: 1rem !important; + } + .pb-lg-3, + .py-lg-3 { + padding-bottom: 1rem !important; + } + .pl-lg-3, + .px-lg-3 { + padding-left: 1rem !important; + } + .p-lg-4 { + padding: 1.5rem !important; + } + .pt-lg-4, + .py-lg-4 { + padding-top: 1.5rem !important; + } + .pr-lg-4, + .px-lg-4 { + padding-right: 1.5rem !important; + } + .pb-lg-4, + .py-lg-4 { + padding-bottom: 1.5rem !important; + } + .pl-lg-4, + .px-lg-4 { + padding-left: 1.5rem !important; + } + .p-lg-5 { + padding: 3rem !important; + } + .pt-lg-5, + .py-lg-5 { + padding-top: 3rem !important; + } + .pr-lg-5, + .px-lg-5 { + padding-right: 3rem !important; + } + .pb-lg-5, + .py-lg-5 { + padding-bottom: 3rem !important; + } + .pl-lg-5, + .px-lg-5 { + padding-left: 3rem !important; + } + .m-lg-auto { + margin: auto !important; + } + .mt-lg-auto, + .my-lg-auto { + margin-top: auto !important; + } + .mr-lg-auto, + .mx-lg-auto { + margin-right: auto !important; + } + .mb-lg-auto, + .my-lg-auto { + margin-bottom: auto !important; + } + .ml-lg-auto, + .mx-lg-auto { + margin-left: auto !important; + } +} + +@media (min-width: 1200px) { + .m-xl-0 { + margin: 0 !important; + } + .mt-xl-0, + .my-xl-0 { + margin-top: 0 !important; + } + .mr-xl-0, + .mx-xl-0 { + margin-right: 0 !important; + } + .mb-xl-0, + .my-xl-0 { + margin-bottom: 0 !important; + } + .ml-xl-0, + .mx-xl-0 { + margin-left: 0 !important; + } + .m-xl-1 { + margin: 0.25rem !important; + } + .mt-xl-1, + .my-xl-1 { + margin-top: 0.25rem !important; + } + .mr-xl-1, + .mx-xl-1 { + margin-right: 0.25rem !important; + } + .mb-xl-1, + .my-xl-1 { + margin-bottom: 0.25rem !important; + } + .ml-xl-1, + .mx-xl-1 { + margin-left: 0.25rem !important; + } + .m-xl-2 { + margin: 0.5rem !important; + } + .mt-xl-2, + .my-xl-2 { + margin-top: 0.5rem !important; + } + .mr-xl-2, + .mx-xl-2 { + margin-right: 0.5rem !important; + } + .mb-xl-2, + .my-xl-2 { + margin-bottom: 0.5rem !important; + } + .ml-xl-2, + .mx-xl-2 { + margin-left: 0.5rem !important; + } + .m-xl-3 { + margin: 1rem !important; + } + .mt-xl-3, + .my-xl-3 { + margin-top: 1rem !important; + } + .mr-xl-3, + .mx-xl-3 { + margin-right: 1rem !important; + } + .mb-xl-3, + .my-xl-3 { + margin-bottom: 1rem !important; + } + .ml-xl-3, + .mx-xl-3 { + margin-left: 1rem !important; + } + .m-xl-4 { + margin: 1.5rem !important; + } + .mt-xl-4, + .my-xl-4 { + margin-top: 1.5rem !important; + } + .mr-xl-4, + .mx-xl-4 { + margin-right: 1.5rem !important; + } + .mb-xl-4, + .my-xl-4 { + margin-bottom: 1.5rem !important; + } + .ml-xl-4, + .mx-xl-4 { + margin-left: 1.5rem !important; + } + .m-xl-5 { + margin: 3rem !important; + } + .mt-xl-5, + .my-xl-5 { + margin-top: 3rem !important; + } + .mr-xl-5, + .mx-xl-5 { + margin-right: 3rem !important; + } + .mb-xl-5, + .my-xl-5 { + margin-bottom: 3rem !important; + } + .ml-xl-5, + .mx-xl-5 { + margin-left: 3rem !important; + } + .p-xl-0 { + padding: 0 !important; + } + .pt-xl-0, + .py-xl-0 { + padding-top: 0 !important; + } + .pr-xl-0, + .px-xl-0 { + padding-right: 0 !important; + } + .pb-xl-0, + .py-xl-0 { + padding-bottom: 0 !important; + } + .pl-xl-0, + .px-xl-0 { + padding-left: 0 !important; + } + .p-xl-1 { + padding: 0.25rem !important; + } + .pt-xl-1, + .py-xl-1 { + padding-top: 0.25rem !important; + } + .pr-xl-1, + .px-xl-1 { + padding-right: 0.25rem !important; + } + .pb-xl-1, + .py-xl-1 { + padding-bottom: 0.25rem !important; + } + .pl-xl-1, + .px-xl-1 { + padding-left: 0.25rem !important; + } + .p-xl-2 { + padding: 0.5rem !important; + } + .pt-xl-2, + .py-xl-2 { + padding-top: 0.5rem !important; + } + .pr-xl-2, + .px-xl-2 { + padding-right: 0.5rem !important; + } + .pb-xl-2, + .py-xl-2 { + padding-bottom: 0.5rem !important; + } + .pl-xl-2, + .px-xl-2 { + padding-left: 0.5rem !important; + } + .p-xl-3 { + padding: 1rem !important; + } + .pt-xl-3, + .py-xl-3 { + padding-top: 1rem !important; + } + .pr-xl-3, + .px-xl-3 { + padding-right: 1rem !important; + } + .pb-xl-3, + .py-xl-3 { + padding-bottom: 1rem !important; + } + .pl-xl-3, + .px-xl-3 { + padding-left: 1rem !important; + } + .p-xl-4 { + padding: 1.5rem !important; + } + .pt-xl-4, + .py-xl-4 { + padding-top: 1.5rem !important; + } + .pr-xl-4, + .px-xl-4 { + padding-right: 1.5rem !important; + } + .pb-xl-4, + .py-xl-4 { + padding-bottom: 1.5rem !important; + } + .pl-xl-4, + .px-xl-4 { + padding-left: 1.5rem !important; + } + .p-xl-5 { + padding: 3rem !important; + } + .pt-xl-5, + .py-xl-5 { + padding-top: 3rem !important; + } + .pr-xl-5, + .px-xl-5 { + padding-right: 3rem !important; + } + .pb-xl-5, + .py-xl-5 { + padding-bottom: 3rem !important; + } + .pl-xl-5, + .px-xl-5 { + padding-left: 3rem !important; + } + .m-xl-auto { + margin: auto !important; + } + .mt-xl-auto, + .my-xl-auto { + margin-top: auto !important; + } + .mr-xl-auto, + .mx-xl-auto { + margin-right: auto !important; + } + .mb-xl-auto, + .my-xl-auto { + margin-bottom: auto !important; + } + .ml-xl-auto, + .mx-xl-auto { + margin-left: auto !important; + } +} + +.text-monospace { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +.text-justify { + text-align: justify !important; +} + +.text-nowrap { + white-space: nowrap !important; +} + +.text-truncate { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.text-left { + text-align: left !important; +} + +.text-right { + text-align: right !important; +} + +.text-center { + text-align: center !important; +} + +@media (min-width: 576px) { + .text-sm-left { + text-align: left !important; + } + .text-sm-right { + text-align: right !important; + } + .text-sm-center { + text-align: center !important; + } +} + +@media (min-width: 768px) { + .text-md-left { + text-align: left !important; + } + .text-md-right { + text-align: right !important; + } + .text-md-center { + text-align: center !important; + } +} + +@media (min-width: 992px) { + .text-lg-left { + text-align: left !important; + } + .text-lg-right { + text-align: right !important; + } + .text-lg-center { + text-align: center !important; + } +} + +@media (min-width: 1200px) { + .text-xl-left { + text-align: left !important; + } + .text-xl-right { + text-align: right !important; + } + .text-xl-center { + text-align: center !important; + } +} + +.text-lowercase { + text-transform: lowercase !important; +} + +.text-uppercase { + text-transform: uppercase !important; +} + +.text-capitalize { + text-transform: capitalize !important; +} + +.font-weight-light { + font-weight: 300 !important; +} + +.font-weight-normal { + font-weight: 400 !important; +} + +.font-weight-bold { + font-weight: 700 !important; +} + +.font-italic { + font-style: italic !important; +} + +.text-white { + color: #fff !important; +} + +.text-primary { + color: #007bff !important; +} + +a.text-primary:hover, a.text-primary:focus { + color: #0062cc !important; +} + +.text-secondary { + color: #6c757d !important; +} + +a.text-secondary:hover, a.text-secondary:focus { + color: #545b62 !important; +} + +.text-success { + color: #28a745 !important; +} + +a.text-success:hover, a.text-success:focus { + color: #1e7e34 !important; +} + +.text-info { + color: #17a2b8 !important; +} + +a.text-info:hover, a.text-info:focus { + color: #117a8b !important; +} + +.text-warning { + color: #ffc107 !important; +} + +a.text-warning:hover, a.text-warning:focus { + color: #d39e00 !important; +} + +.text-danger { + color: #dc3545 !important; +} + +a.text-danger:hover, a.text-danger:focus { + color: #bd2130 !important; +} + +.text-light { + color: #f8f9fa !important; +} + +a.text-light:hover, a.text-light:focus { + color: #dae0e5 !important; +} + +.text-dark { + color: #343a40 !important; +} + +a.text-dark:hover, a.text-dark:focus { + color: #1d2124 !important; +} + +.text-body { + color: #212529 !important; +} + +.text-muted { + color: #6c757d !important; +} + +.text-black-50 { + color: rgba(0, 0, 0, 0.5) !important; +} + +.text-white-50 { + color: rgba(255, 255, 255, 0.5) !important; +} + +.text-hide { + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; +} + +.visible { + visibility: visible !important; +} + +.invisible { + visibility: hidden !important; +} + +@media print { + *, + *::before, + *::after { + text-shadow: none !important; + box-shadow: none !important; + } + a:not(.btn) { + text-decoration: underline; + } + abbr[title]::after { + content: " (" attr(title) ")"; + } + pre { + white-space: pre-wrap !important; + } + pre, + blockquote { + border: 1px solid #adb5bd; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + @page { + size: a3; + } + body { + min-width: 992px !important; + } + .container { + min-width: 992px !important; + } + .navbar { + display: none; + } + .badge { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table td, + .table th { + background-color: #fff !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #dee2e6 !important; + } + .table-dark { + color: inherit; + } + .table-dark th, + .table-dark td, + .table-dark thead th, + .table-dark tbody + tbody { + border-color: #dee2e6; + } + .table .thead-dark th { + color: inherit; + border-color: #dee2e6; + } +} +/*# sourceMappingURL=bootstrap.css.map */ \ No newline at end of file diff --git a/Erupe/www/erupe/css/dependencies/bootstrap.css.map b/Erupe/www/erupe/css/dependencies/bootstrap.css.map new file mode 100644 index 000000000..cd35b271d --- /dev/null +++ b/Erupe/www/erupe/css/dependencies/bootstrap.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_root.scss","../../scss/_reboot.scss","../../scss/_variables.scss","bootstrap.css","../../scss/mixins/_hover.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_breakpoints.scss","../../scss/mixins/_grid-framework.scss","../../scss/_tables.scss","../../scss/mixins/_table-row.scss","../../scss/_functions.scss","../../scss/_forms.scss","../../scss/mixins/_transition.scss","../../scss/mixins/_forms.scss","../../scss/mixins/_gradients.scss","../../scss/_buttons.scss","../../scss/mixins/_buttons.scss","../../scss/_transitions.scss","../../scss/_dropdown.scss","../../scss/mixins/_caret.scss","../../scss/mixins/_nav-divider.scss","../../scss/_button-group.scss","../../scss/_input-group.scss","../../scss/_custom-forms.scss","../../scss/_nav.scss","../../scss/_navbar.scss","../../scss/_card.scss","../../scss/_breadcrumb.scss","../../scss/_pagination.scss","../../scss/mixins/_pagination.scss","../../scss/_badge.scss","../../scss/mixins/_badge.scss","../../scss/_jumbotron.scss","../../scss/_alert.scss","../../scss/mixins/_alert.scss","../../scss/_progress.scss","../../scss/_media.scss","../../scss/_list-group.scss","../../scss/mixins/_list-group.scss","../../scss/_close.scss","../../scss/_modal.scss","../../scss/_tooltip.scss","../../scss/mixins/_reset-text.scss","../../scss/_popover.scss","../../scss/_carousel.scss","../../scss/utilities/_align.scss","../../scss/mixins/_background-variant.scss","../../scss/utilities/_background.scss","../../scss/utilities/_borders.scss","../../scss/mixins/_clearfix.scss","../../scss/utilities/_display.scss","../../scss/utilities/_embed.scss","../../scss/utilities/_flex.scss","../../scss/utilities/_float.scss","../../scss/mixins/_float.scss","../../scss/utilities/_position.scss","../../scss/utilities/_screenreaders.scss","../../scss/mixins/_screen-reader.scss","../../scss/utilities/_shadows.scss","../../scss/utilities/_sizing.scss","../../scss/utilities/_spacing.scss","../../scss/utilities/_text.scss","../../scss/mixins/_text-truncate.scss","../../scss/mixins/_text-emphasis.scss","../../scss/mixins/_text-hide.scss","../../scss/utilities/_visibility.scss","../../scss/mixins/_visibility.scss","../../scss/_print.scss"],"names":[],"mappings":"AAAA;;;;;GAKG;ACLH;EAGI,gBAAc;EAAd,kBAAc;EAAd,kBAAc;EAAd,gBAAc;EAAd,eAAc;EAAd,kBAAc;EAAd,kBAAc;EAAd,iBAAc;EAAd,gBAAc;EAAd,gBAAc;EAAd,cAAc;EAAd,gBAAc;EAAd,qBAAc;EAId,mBAAc;EAAd,qBAAc;EAAd,mBAAc;EAAd,gBAAc;EAAd,mBAAc;EAAd,kBAAc;EAAd,iBAAc;EAAd,gBAAc;EAId,mBAAiC;EAAjC,uBAAiC;EAAjC,uBAAiC;EAAjC,uBAAiC;EAAjC,wBAAiC;EAKnC,mMAAyB;EACzB,8GAAwB;CACzB;;ACED;;;EAGE,uBAAsB;CACvB;;AAED;EACE,wBAAuB;EACvB,kBAAiB;EACjB,+BAA8B;EAC9B,2BAA0B;EAC1B,8BAA6B;EAC7B,8CCZa;CDad;;AAIC;EACE,oBAAmB;CEgBtB;;AFVD;EACE,eAAc;CACf;;AAUD;EACE,UAAS;EACT,sLCgMoM;ED/LpM,gBCoMgC;EDnMhC,iBCwM+B;EDvM/B,iBC2M+B;ED1M/B,eC3CgB;ED4ChB,iBAAgB;EAChB,uBCtDa;CDuDd;;AEMD;EFEE,sBAAqB;CACtB;;AAQD;EACE,wBAAuB;EACvB,UAAS;EACT,kBAAiB;CAClB;;AAYD;EACE,cAAa;EACb,sBC6KyC;CD5K1C;;AAOD;EACE,cAAa;EACb,oBCkE8B;CDjE/B;;AASD;;EAEE,2BAA0B;EAC1B,0CAAiC;EAAjC,kCAAiC;EACjC,aAAY;EACZ,iBAAgB;CACjB;;AAED;EACE,oBAAmB;EACnB,mBAAkB;EAClB,qBAAoB;CACrB;;AAED;;;EAGE,cAAa;EACb,oBAAmB;CACpB;;AAED;;;;EAIE,iBAAgB;CACjB;;AAED;EACE,iBCgH+B;CD/GhC;;AAED;EACE,qBAAoB;EACpB,eAAc;CACf;;AAED;EACE,iBAAgB;CACjB;;AAED;EACE,mBAAkB;CACnB;;AAGD;;EAEE,oBAAmB;CACpB;;AAGD;EACE,eAAc;CACf;;AAOD;;EAEE,mBAAkB;EAClB,eAAc;EACd,eAAc;EACd,yBAAwB;CACzB;;AAED;EAAM,eAAc;CAAI;;AACxB;EAAM,WAAU;CAAI;;AAOpB;EACE,eC9Je;ED+Jf,sBC/B8B;EDgC9B,8BAA6B;EAC7B,sCAAqC;CAMtC;;AGnMC;EHgME,eCnCgD;EDoChD,2BCnCiC;CE9Jb;;AH2MxB;EACE,eAAc;EACd,sBAAqB;CAUtB;;AGnNC;EH4ME,eAAc;EACd,sBAAqB;CG1MtB;;AHoMH;EAUI,WAAU;CACX;;AAQH;;;;EAIE,kGCagH;EDZhH,eAAc;CACf;;AAED;EAEE,cAAa;EAEb,oBAAmB;EAEnB,eAAc;EAGd,8BAA6B;CAC9B;;AAOD;EAEE,iBAAgB;CACjB;;AAOD;EACE,uBAAsB;EACtB,mBAAkB;CACnB;;AAED;EAGE,iBAAgB;EAChB,uBAAsB;CACvB;;AAOD;EACE,0BAAyB;CAC1B;;AAED;EACE,qBC8BkC;ED7BlC,wBC6BkC;ED5BlC,eCrRgB;EDsRhB,iBAAgB;EAChB,qBAAoB;CACrB;;AAED;EAGE,oBAAmB;CACpB;;AAOD;EAEE,sBAAqB;EACrB,sBC+F2C;CD9F5C;;AAKD;EACE,iBAAgB;CACjB;;AAMD;EACE,oBAAmB;EACnB,2CAA0C;CAC3C;;AAED;;;;;EAKE,UAAS;EACT,qBAAoB;EACpB,mBAAkB;EAClB,qBAAoB;CACrB;;AAED;;EAEE,kBAAiB;CAClB;;AAED;;EAEE,qBAAoB;CACrB;;AAKD;;;;EAIE,2BAA0B;CAC3B;;AAGD;;;;EAIE,WAAU;EACV,mBAAkB;CACnB;;AAED;;EAEE,uBAAsB;EACtB,WAAU;CACX;;AAGD;;;;EASE,4BAA2B;CAC5B;;AAED;EACE,eAAc;EAEd,iBAAgB;CACjB;;AAED;EAME,aAAY;EAEZ,WAAU;EACV,UAAS;EACT,UAAS;CACV;;AAID;EACE,eAAc;EACd,YAAW;EACX,gBAAe;EACf,WAAU;EACV,qBAAoB;EACpB,kBAAiB;EACjB,qBAAoB;EACpB,eAAc;EACd,oBAAmB;CACpB;;AAED;EACE,yBAAwB;CACzB;;AEtGD;;EF2GE,aAAY;CACb;;AEvGD;EF8GE,qBAAoB;EACpB,yBAAwB;CACzB;;AE3GD;;EFmHE,yBAAwB;CACzB;;AAOD;EACE,cAAa;EACb,2BAA0B;CAC3B;;AAMD;EACE,sBAAqB;CACtB;;AAED;EACE,mBAAkB;EAClB,gBAAe;CAChB;;AAED;EACE,cAAa;CACd;;AExHD;EF6HE,yBAAwB;CACzB;;AI5dD;;EAEE,sBHyQyC;EGxQzC,qBHyQmC;EGxQnC,iBHyQ+B;EGxQ/B,iBHyQ+B;EGxQ/B,eHyQmC;CGxQpC;;AAED;EAAU,kBH2PyC;CG3Pb;;AACtC;EAAU,gBH2PuC;CG3PX;;AACtC;EAAU,mBH2P0C;CG3Pd;;AACtC;EAAU,kBH2PyC;CG3Pb;;AACtC;EAAU,mBH2P0C;CG3Pd;;AACtC;EAAU,gBH2OwB;CG3OI;;AAEtC;EACE,mBH2QoD;EG1QpD,iBH2Q+B;CG1QhC;;AAGD;EACE,gBH0PgC;EGzPhC,iBH8P+B;EG7P/B,iBHqP+B;CGpPhC;;AACD;EACE,kBHsPkC;EGrPlC,iBH0P+B;EGzP/B,iBHgP+B;CG/OhC;;AACD;EACE,kBHkPkC;EGjPlC,iBHsP+B;EGrP/B,iBH2O+B;CG1OhC;;AACD;EACE,kBH8OkC;EG7OlC,iBHkP+B;EGjP/B,iBHsO+B;CGrOhC;;AJmCD;EI3BE,iBHwEW;EGvEX,oBHuEW;EGtEX,UAAS;EACT,yCHtCa;CGuCd;;AAOD;;EAEE,eHiO+B;EGhO/B,iBH+L+B;CG9LhC;;AAED;;EAEE,eHqOgC;EGpOhC,0BH6OmC;CG5OpC;;AAOD;EC/EE,gBAAe;EACf,iBAAgB;CDgFjB;;AAGD;ECpFE,gBAAe;EACf,iBAAgB;CDqFjB;;AACD;EACE,sBAAqB;CAKtB;;AAND;EAII,qBHuN+B;CGtNhC;;AASH;EACE,eAAc;EACd,0BAAyB;CAC1B;;AAGD;EACE,oBHeW;EGdX,mBHyLoD;CGxLrD;;AAED;EACE,eAAc;EACd,eAAc;EACd,eHvGgB;CG4GjB;;AARD;EAMI,uBAAsB;CACvB;;AEpHH;ECIE,gBAAe;EAGf,aAAY;CDLb;;AAID;EACE,iBL61BwC;EK51BxC,uBLLa;EKMb,0BLHgB;EOTd,uBP+NgC;EMxNlC,gBAAe;EAGf,aAAY;CDQb;;AAMD;EAEE,sBAAqB;CACtB;;AAED;EACE,sBAA4B;EAC5B,eAAc;CACf;;AAED;EACE,eL80BqC;EK70BrC,eLxBgB;CKyBjB;;AGxCD;EACE,iBRs6BuC;EQr6BvC,eRwCe;EQvCf,uBAAsB;CAMvB;;AAHC;EACE,eAAc;CACf;;AAIH;EACE,uBR85BuC;EQ75BvC,iBRy5BuC;EQx5BvC,YRNa;EQOb,0BREgB;EOfd,sBPiO+B;CQ1MlC;;AAdD;EASI,WAAU;EACV,gBAAe;EACf,iBR6O6B;CQ3O9B;;ATwNH;ESnNE,eAAc;EACd,iBRw4BuC;EQv4BvC,eRdgB;CQsBjB;;AAXD;EAOI,mBAAkB;EAClB,eAAc;EACd,mBAAkB;CACnB;;AAIH;EACE,kBRq4BuC;EQp4BvC,mBAAkB;CACnB;;AC1CC;ECAA,YAAW;EACX,oBAAuC;EACvC,mBAAsC;EACtC,mBAAkB;EAClB,kBAAiB;CDDhB;;AEoDC;EFvDF;ICYI,iBVwLK;GSjMR;CRwiBF;;AUpfG;EFvDF;ICYI,iBVyLK;GSlMR;CR8iBF;;AU1fG;EFvDF;ICYI,iBV0LK;GSnMR;CRojBF;;AUhgBG;EFvDF;ICYI,kBV2LM;GSpMT;CR0jBF;;AQjjBC;ECZA,YAAW;EACX,oBAAuC;EACvC,mBAAsC;EACtC,mBAAkB;EAClB,kBAAiB;CDUhB;;AAQD;ECJA,qBAAa;EAAb,cAAa;EACb,oBAAe;EAAf,gBAAe;EACf,oBAAuC;EACvC,mBAAsC;CDGrC;;AAID;EACE,gBAAe;EACf,eAAc;CAOf;;AATD;;EAMI,iBAAgB;EAChB,gBAAe;CAChB;;AGlCH;;;;;;EACE,mBAAkB;EAClB,YAAW;EACX,gBAAe;EACf,oBAA4B;EAC5B,mBAA2B;CAC5B;;AAkBG;EACE,2BAAa;EAAb,cAAa;EACb,qBAAY;EAAZ,aAAY;EACZ,gBAAe;CAChB;;AACD;EACE,mBAAc;EAAd,eAAc;EACd,YAAW;EACX,gBAAe;CAChB;;AAGC;EFFN,wBAAsC;EAAtC,oBAAsC;EAItC,qBAAuC;CEAhC;;AAFD;EFFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CEAhC;;AAFD;EFFN,kBAAsC;EAAtC,cAAsC;EAItC,eAAuC;CEAhC;;AAFD;EFFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CEAhC;;AAFD;EFFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CEAhC;;AAFD;EFFN,kBAAsC;EAAtC,cAAsC;EAItC,eAAuC;CEAhC;;AAFD;EFFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CEAhC;;AAFD;EFFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CEAhC;;AAFD;EFFN,kBAAsC;EAAtC,cAAsC;EAItC,eAAuC;CEAhC;;AAFD;EFFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CEAhC;;AAFD;EFFN,yBAAsC;EAAtC,qBAAsC;EAItC,sBAAuC;CEAhC;;AAFD;EFFN,mBAAsC;EAAtC,eAAsC;EAItC,gBAAuC;CEAhC;;AAGH;EAAwB,mBAAS;EAAT,UAAS;CAAI;;AAErC;EAAuB,mBZoKG;EYpKH,UZoKG;CYpKoB;;AAG5C;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,kBADZ;EACY,SADZ;CACyB;;AAArC;EAAwB,mBADZ;EACY,UADZ;CACyB;;AAArC;EAAwB,mBADZ;EACY,UADZ;CACyB;;AAArC;EAAwB,mBADZ;EACY,UADZ;CACyB;;AAMnC;EFTR,uBAA8C;CEWrC;;AAFD;EFTR,wBAA8C;CEWrC;;AAFD;EFTR,iBAA8C;CEWrC;;AAFD;EFTR,wBAA8C;CEWrC;;AAFD;EFTR,wBAA8C;CEWrC;;AAFD;EFTR,iBAA8C;CEWrC;;AAFD;EFTR,wBAA8C;CEWrC;;AAFD;EFTR,wBAA8C;CEWrC;;AAFD;EFTR,iBAA8C;CEWrC;;AAFD;EFTR,wBAA8C;CEWrC;;AAFD;EFTR,wBAA8C;CEWrC;;ADDP;EC7BE;IACE,2BAAa;IAAb,cAAa;IACb,qBAAY;IAAZ,aAAY;IACZ,gBAAe;GAChB;EACD;IACE,mBAAc;IAAd,eAAc;IACd,YAAW;IACX,gBAAe;GAChB;EAGC;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,mBAAsC;IAAtC,eAAsC;IAItC,gBAAuC;GEAhC;EAGH;IAAwB,mBAAS;IAAT,UAAS;GAAI;EAErC;IAAuB,mBZoKG;IYpKH,UZoKG;GYpKoB;EAG5C;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAMnC;IFTR,eAA4B;GEWnB;EAFD;IFTR,uBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;CX02BV;;AU32BG;EC7BE;IACE,2BAAa;IAAb,cAAa;IACb,qBAAY;IAAZ,aAAY;IACZ,gBAAe;GAChB;EACD;IACE,mBAAc;IAAd,eAAc;IACd,YAAW;IACX,gBAAe;GAChB;EAGC;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,mBAAsC;IAAtC,eAAsC;IAItC,gBAAuC;GEAhC;EAGH;IAAwB,mBAAS;IAAT,UAAS;GAAI;EAErC;IAAuB,mBZoKG;IYpKH,UZoKG;GYpKoB;EAG5C;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAMnC;IFTR,eAA4B;GEWnB;EAFD;IFTR,uBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;CXw/BV;;AUz/BG;EC7BE;IACE,2BAAa;IAAb,cAAa;IACb,qBAAY;IAAZ,aAAY;IACZ,gBAAe;GAChB;EACD;IACE,mBAAc;IAAd,eAAc;IACd,YAAW;IACX,gBAAe;GAChB;EAGC;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,mBAAsC;IAAtC,eAAsC;IAItC,gBAAuC;GEAhC;EAGH;IAAwB,mBAAS;IAAT,UAAS;GAAI;EAErC;IAAuB,mBZoKG;IYpKH,UZoKG;GYpKoB;EAG5C;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAMnC;IFTR,eAA4B;GEWnB;EAFD;IFTR,uBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;CXsoCV;;AUvoCG;EC7BE;IACE,2BAAa;IAAb,cAAa;IACb,qBAAY;IAAZ,aAAY;IACZ,gBAAe;GAChB;EACD;IACE,mBAAc;IAAd,eAAc;IACd,YAAW;IACX,gBAAe;GAChB;EAGC;IFFN,wBAAsC;IAAtC,oBAAsC;IAItC,qBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,kBAAsC;IAAtC,cAAsC;IAItC,eAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,yBAAsC;IAAtC,qBAAsC;IAItC,sBAAuC;GEAhC;EAFD;IFFN,mBAAsC;IAAtC,eAAsC;IAItC,gBAAuC;GEAhC;EAGH;IAAwB,mBAAS;IAAT,UAAS;GAAI;EAErC;IAAuB,mBZoKG;IYpKH,UZoKG;GYpKoB;EAG5C;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,kBADZ;IACY,SADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAArC;IAAwB,mBADZ;IACY,UADZ;GACyB;EAMnC;IFTR,eAA4B;GEWnB;EAFD;IFTR,uBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,iBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;EAFD;IFTR,wBAA8C;GEWrC;CXoxCV;;AY70CD;EACE,YAAW;EACX,oBbyHW;EaxHX,8Bb6TuC;CaxSxC;;AAxBD;;EAOI,iBbsTgC;EarThC,oBAAmB;EACnB,8BbAc;CaCf;;AAVH;EAaI,uBAAsB;EACtB,iCbLc;CaMf;;AAfH;EAkBI,8BbTc;CaUf;;AAnBH;EAsBI,uBbhBW;CaiBZ;;AAQH;;EAGI,gBb4R+B;Ca3RhC;;AAQH;EACE,0BbnCgB;CagDjB;;AAdD;;EAKI,0BbvCc;CawCf;;AANH;;EAWM,yBAA8C;CAC/C;;AAIL;;;;EAKI,UAAS;CACV;;AAOH;EAEI,sCb1DW;Ca2DZ;;AXnED;EW8EI,uCbtES;CERS;;AYPtB;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,0BC2E4D;CD1E7D;;AZEH;EYQM,0BAJsC;CZJtB;;AYGtB;;EASQ,0BARoC;CASrC;;AApBP;;;EAII,uCdWS;CcVV;;AZEH;EYQM,uCAJsC;CZJtB;;AYGtB;;EASQ,uCARoC;CASrC;;ADwFT;EAGM,Yb1GS;Ea2GT,0BblGY;EamGZ,sBb4NgD;Ca3NjD;;AANL;EAWM,eb3GY;Ea4GZ,0BbjHY;EakHZ,sBbjHY;CakHb;;AAIL;EACE,Yb1Ha;Ea2Hb,0BblHgB;Ca2IjB;;AA3BD;;;EAOI,sBbwMkD;CavMnD;;AARH;EAWI,UAAS;CACV;;AAZH;EAgBM,4CbzIS;Ca0IV;;AXxIH;EW8IM,6CbhJO;CEES;;AS6DpB;EEkGA;IAEI,eAAc;IACd,YAAW;IACX,iBAAgB;IAChB,kCAAiC;IACjC,6CAA4C;GAO/C;EAbA;IAUK,UAAS;GACV;CZ84CR;;AU3/CG;EEkGA;IAEI,eAAc;IACd,YAAW;IACX,iBAAgB;IAChB,kCAAiC;IACjC,6CAA4C;GAO/C;EAbA;IAUK,UAAS;GACV;CZ25CR;;AUxgDG;EEkGA;IAEI,eAAc;IACd,YAAW;IACX,iBAAgB;IAChB,kCAAiC;IACjC,6CAA4C;GAO/C;EAbA;IAUK,UAAS;GACV;CZw6CR;;AUrhDG;EEkGA;IAEI,eAAc;IACd,YAAW;IACX,iBAAgB;IAChB,kCAAiC;IACjC,6CAA4C;GAO/C;EAbA;IAUK,UAAS;GACV;CZq7CR;;AYr8CD;EAOQ,eAAc;EACd,YAAW;EACX,iBAAgB;EAChB,kCAAiC;EACjC,6CAA4C;CAO/C;;AAlBL;EAeU,UAAS;CACV;;AGhLT;EACE,eAAc;EACd,YAAW;EACX,4BhBob4F;EgBnb5F,0BhBoVkC;EgBnVlC,gBhBoPgC;EgBnPhC,iBhB4P+B;EgB3P/B,ehBIgB;EgBHhB,uBhBJa;EgBKb,6BAA4B;EAC5B,0BhBFgB;EgBOd,uBhB8MgC;EiB9N9B,yEjBgc4F;CgB5YjG;;AChDC;EDHF;ICII,iBAAgB;GD+CnB;CfmlDA;;AetoDD;EA0BI,8BAA6B;EAC7B,UAAS;CACV;;AErBD;EACE,elBGc;EkBFd,uBlBLW;EkBMX,sBlBkasE;EkBjatE,WAAU;EAKR,iDlBkBW;CkBhBd;;AFlBH;EAmCI,ehBzBc;EgB2Bd,WAAU;CACX;;AAtCH;EAmCI,ehBzBc;EgB2Bd,WAAU;CACX;;AAtCH;EAmCI,ehBzBc;EgB2Bd,WAAU;CACX;;AAtCH;EAmCI,ehBzBc;EgB2Bd,WAAU;CACX;;AAtCH;EAmCI,ehBzBc;EgB2Bd,WAAU;CACX;;AAtCH;EA+CI,0BhBzCc;EgB2Cd,WAAU;CACX;;AAGH;EAOI,ehBjDc;EgBkDd,uBhBzDW;CgB0DZ;;AAIH;;EAEE,eAAc;EACd,YAAW;CACZ;;AASD;EACE,kCAA+D;EAC/D,qCAAkE;EAClE,iBAAgB;EAChB,mBAAkB;EAClB,iBhB8K+B;CgB7KhC;;AAED;EACE,gCAAkE;EAClE,mCAAqE;EACrE,mBhBgKoD;EgB/JpD,iBhB4H+B;CgB3HhC;;AAED;EACE,iCAAkE;EAClE,oCAAqE;EACrE,oBhB0JoD;EgBzJpD,iBhBsH+B;CgBrHhC;;AAQD;EACE,eAAc;EACd,YAAW;EACX,sBhByOmC;EgBxOnC,yBhBwOmC;EgBvOnC,iBAAgB;EAChB,iBhBiJ+B;EgBhJ/B,ehBrGgB;EgBsGhB,8BAA6B;EAC7B,0BAAyB;EACzB,oBAAmC;CAOpC;;AAjBD;EAcI,iBAAgB;EAChB,gBAAe;CAChB;;AAWH;EACE,8BhBmT+F;EgBlT/F,wBhBwNiC;EgBvNjC,oBhBkHoD;EgBjHpD,iBhB8E+B;EO1N7B,sBPiO+B;CgBnFlC;;AAED;EACE,6BhB8S+F;EgB7S/F,qBhBoNgC;EgBnNhC,mBhByGoD;EgBxGpD,iBhBqE+B;EOzN7B,sBPgO+B;CgB1ElC;;AAGD;EAGI,aAAY;CACb;;AAGH;EACE,aAAY;CACb;;AAQD;EACE,oBhBiS0C;CgBhS3C;;AAED;EACE,eAAc;EACd,oBhBmR4C;CgBlR7C;;AAOD;EACE,qBAAa;EAAb,cAAa;EACb,oBAAe;EAAf,gBAAe;EACf,mBAAkB;EAClB,kBAAiB;CAOlB;;AAXD;;EAQI,mBAAkB;EAClB,kBAAiB;CAClB;;AAQH;EACE,mBAAkB;EAClB,eAAc;EACd,sBhBwP6C;CgBvP9C;;AAED;EACE,mBAAkB;EAClB,mBhBoP2C;EgBnP3C,sBhBkP6C;CgB7O9C;;AARD;EAMI,ehB1Mc;CgB2Mf;;AAGH;EACE,iBAAgB;CACjB;;AAED;EACE,4BAAoB;EAApB,qBAAoB;EACpB,uBAAmB;EAAnB,oBAAmB;EACnB,gBAAe;EACf,sBhBuO4C;CgB9N7C;;AAbD;EAQI,iBAAgB;EAChB,cAAa;EACb,wBhBkO4C;EgBjO5C,eAAc;CACf;;AEjND;EACE,cAAa;EACb,YAAW;EACX,oBlBua0C;EkBta1C,elBoQ6B;EkBnQ7B,elBaa;CkBZd;;AAED;EACE,mBAAkB;EAClB,UAAS;EACT,WAAU;EACV,cAAa;EACb,gBAAe;EACf,wBlByrBqC;EkBxrBrC,kBAAiB;EACjB,oBlBoNkD;EkBnNlD,iBlB0N6B;EkBzN7B,YlBrCW;EkBsCX,yClBDa;EO3Cb,uBP+NgC;CkBjLjC;;AAIC;;;EAEE,sBlBTW;CkBoBZ;;AAbD;;;EAKI,sBlBZS;EkBaT,iDlBbS;CkBcV;;AAPH;;;;;;;;EAWI,eAAc;CACf;;AAKH;;;EAII,eAAc;CACf;;AAKH;EAGI,elBrCS;CkBsCV;;AAJH;;;EAQI,eAAc;CACf;;AAKH;EAGI,elBnDS;CkBwDV;;AARH;EAMM,0BAAsC;CACvC;;AAPL;;;EAYI,eAAc;CACf;;AAbH;ECzFA,0BD0G+C;CAC1C;;AAlBL;EAuBM,iElBvEO;CkBwER;;AAOL;EAGI,sBlBlFS;CkBqFV;;AANH;EAKe,sBAAqB;CAAI;;AALxC;;;EAUI,eAAc;CACf;;AAXH;EAeM,iDlB9FO;CkB+FR;;AAjHP;EACE,cAAa;EACb,YAAW;EACX,oBlBua0C;EkBta1C,elBoQ6B;EkBnQ7B,elBUa;CkBTd;;AAED;EACE,mBAAkB;EAClB,UAAS;EACT,WAAU;EACV,cAAa;EACb,gBAAe;EACf,wBlByrBqC;EkBxrBrC,kBAAiB;EACjB,oBlBoNkD;EkBnNlD,iBlB0N6B;EkBzN7B,YlBrCW;EkBsCX,yClBJa;EOxCb,uBP+NgC;CkBjLjC;;AAIC;;;EAEE,sBlBZW;CkBuBZ;;AAbD;;;EAKI,sBlBfS;EkBgBT,iDlBhBS;CkBiBV;;AAPH;;;;;;;;EAWI,eAAc;CACf;;AAKH;;;EAII,eAAc;CACf;;AAKH;EAGI,elBxCS;CkByCV;;AAJH;;;EAQI,eAAc;CACf;;AAKH;EAGI,elBtDS;CkB2DV;;AARH;EAMM,0BAAsC;CACvC;;AAPL;;;EAYI,eAAc;CACf;;AAbH;ECzFA,0BD0G+C;CAC1C;;AAlBL;EAuBM,iElB1EO;CkB2ER;;AAOL;EAGI,sBlBrFS;CkBwFV;;AANH;EAKe,sBAAqB;CAAI;;AALxC;;;EAUI,eAAc;CACf;;AAXH;EAeM,iDlBjGO;CkBkGR;;AFuHT;EACE,qBAAa;EAAb,cAAa;EACb,wBAAmB;EAAnB,oBAAmB;EACnB,uBAAmB;EAAnB,oBAAmB;CAoEpB;;AAvED;EASI,YAAW;CACZ;;ALnNC;EKyMJ;IAeM,qBAAa;IAAb,cAAa;IACb,uBAAmB;IAAnB,oBAAmB;IACnB,sBAAuB;IAAvB,wBAAuB;IACvB,iBAAgB;GACjB;EAnBL;IAuBM,qBAAa;IAAb,cAAa;IACb,mBAAc;IAAd,eAAc;IACd,wBAAmB;IAAnB,oBAAmB;IACnB,uBAAmB;IAAnB,oBAAmB;IACnB,iBAAgB;GACjB;EA5BL;IAgCM,sBAAqB;IACrB,YAAW;IACX,uBAAsB;GACvB;EAnCL;IAuCM,sBAAqB;GACtB;EAxCL;;IA4CM,YAAW;GACZ;EA7CL;IAkDM,qBAAa;IAAb,cAAa;IACb,uBAAmB;IAAnB,oBAAmB;IACnB,sBAAuB;IAAvB,wBAAuB;IACvB,YAAW;IACX,gBAAe;GAChB;EAvDL;IAyDM,mBAAkB;IAClB,cAAa;IACb,sBhB2IwC;IgB1IxC,eAAc;GACf;EA7DL;IAgEM,uBAAmB;IAAnB,oBAAmB;IACnB,sBAAuB;IAAvB,wBAAuB;GACxB;EAlEL;IAoEM,iBAAgB;GACjB;CfouDJ;;AmBxiED;EACE,sBAAqB;EACrB,iBpB4P+B;EoB3P/B,mBAAkB;EAClB,oBAAmB;EACnB,uBAAsB;EACtB,0BAAiB;EAAjB,uBAAiB;EAAjB,sBAAiB;EAAjB,kBAAiB;EACjB,8BAA2C;ECsF3C,0BrB2PkC;EqB1PlC,gBrB2JgC;EqB1JhC,iBrBmK+B;EqBhK7B,uBrB2HgC;EiB9N9B,sIjB6Y6I;CoBlWlJ;;AHvCC;EGHF;IHII,iBAAgB;GGsCnB;CnBmhEA;;ACnjEC;EkBGE,sBAAqB;ClBAtB;;AkBbH;EAkBI,WAAU;EACV,iDpBea;CoBdd;;AApBH;EAyBI,cpBuW6B;CoBrW9B;;AA3BH;EA+BI,gBAAe;CAChB;;AAaH;;EAEE,qBAAoB;CACrB;;AAQC;ECxDA,YrBIa;EmBJX,0BnBkCa;EqBhCf,sBrBgCe;CoBwBd;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,gDrBiBW;CqBfd;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBSa;EqBRb,sBrBQa;CqBPd;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,gDrBVS;CqBYZ;;ADUH;ECxDA,YrBIa;EmBJX,0BnBUc;EqBRhB,sBrBQgB;CoBgDf;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,kDrBPY;CqBSf;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBfc;EqBgBd,sBrBhBc;CqBiBf;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,kDrBlCU;CqBoCb;;ADUH;ECxDA,YrBIa;EmBJX,0BnByCa;EqBvCf,sBrBuCe;CoBiBd;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,gDrBwBW;CqBtBd;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBgBa;EqBfb,sBrBea;CqBdd;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,gDrBHS;CqBKZ;;ADUH;ECxDA,YrBIa;EmBJX,0BnB2Ca;EqBzCf,sBrByCe;CoBed;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,iDrB0BW;CqBxBd;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBkBa;EqBjBb,sBrBiBa;CqBhBd;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,iDrBDS;CqBGZ;;ADUH;ECxDA,erBagB;EmBbd,0BnBwCa;EqBtCf,sBrBsCe;CoBkBd;;AlBpDD;EmBAE,erBOc;EmBbd,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,gDrBuBW;CqBrBd;;AAGD;EAEE,erBXc;EqBYd,0BrBea;EqBdb,sBrBca;CqBbd;;AAED;;EAGE,erBnBc;EqBoBd,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,gDrBJS;CqBMZ;;ADUH;ECxDA,YrBIa;EmBJX,0BnBsCa;EqBpCf,sBrBoCe;CoBoBd;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,gDrBqBW;CqBnBd;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBaa;EqBZb,sBrBYa;CqBXd;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,gDrBNS;CqBQZ;;ADUH;ECxDA,erBagB;EmBbd,0BnBKc;EqBHhB,sBrBGgB;CoBqDf;;AlBpDD;EmBAE,erBOc;EmBbd,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,kDrBZY;CqBcf;;AAGD;EAEE,erBXc;EqBYd,0BrBpBc;EqBqBd,sBrBrBc;CqBsBf;;AAED;;EAGE,erBnBc;EqBoBd,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,kDrBvCU;CqByCb;;ADUH;ECxDA,YrBIa;EmBJX,0BnBYc;EqBVhB,sBrBUgB;CoB8Cf;;AlBpDD;EmBAE,YrBFW;EmBJX,0BEDoF;EASpF,sBATyH;CnBOrG;;AmBKtB;EAMI,+CrBLY;CqBOf;;AAGD;EAEE,YrBpBW;EqBqBX,0BrBbc;EqBcd,sBrBdc;CqBef;;AAED;;EAGE,YrB5BW;EqB6BX,0BAlCuK;EAsCvK,sBAtC+M;CAgDhN;;AARC;;EAKI,+CrBhCU;CqBkCb;;ADgBH;ECXA,erBjBe;EqBkBf,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBpBe;CoB8Bd;;ACRD;EACE,YrBrDW;EqBsDX,0BrBxBa;EqByBb,sBrBzBa;CqB0Bd;;AAED;EAEE,gDrB9Ba;CqB+Bd;;AAED;EAEE,erBnCa;EqBoCb,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrB3Ca;EqB4Cb,sBrB5Ca;CqBsDd;;AARC;;EAKI,gDrBnDS;CqBqDZ;;ADzBH;ECXA,erBzCgB;EqB0ChB,8BAA6B;EAC7B,uBAAsB;EACtB,sBrB5CgB;CoBsDf;;ACRD;EACE,YrBrDW;EqBsDX,0BrBhDc;EqBiDd,sBrBjDc;CqBkDf;;AAED;EAEE,kDrBtDc;CqBuDf;;AAED;EAEE,erB3Dc;EqB4Dd,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrBnEc;EqBoEd,sBrBpEc;CqB8Ef;;AARC;;EAKI,kDrB3EU;CqB6Eb;;ADzBH;ECXA,erBVe;EqBWf,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBbe;CoBuBd;;ACRD;EACE,YrBrDW;EqBsDX,0BrBjBa;EqBkBb,sBrBlBa;CqBmBd;;AAED;EAEE,gDrBvBa;CqBwBd;;AAED;EAEE,erB5Ba;EqB6Bb,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrBpCa;EqBqCb,sBrBrCa;CqB+Cd;;AARC;;EAKI,gDrB5CS;CqB8CZ;;ADzBH;ECXA,erBRe;EqBSf,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBXe;CoBqBd;;ACRD;EACE,YrBrDW;EqBsDX,0BrBfa;EqBgBb,sBrBhBa;CqBiBd;;AAED;EAEE,iDrBrBa;CqBsBd;;AAED;EAEE,erB1Ba;EqB2Bb,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrBlCa;EqBmCb,sBrBnCa;CqB6Cd;;AARC;;EAKI,iDrB1CS;CqB4CZ;;ADzBH;ECXA,erBXe;EqBYf,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBde;CoBwBd;;ACRD;EACE,erB5Cc;EqB6Cd,0BrBlBa;EqBmBb,sBrBnBa;CqBoBd;;AAED;EAEE,gDrBxBa;CqByBd;;AAED;EAEE,erB7Ba;EqB8Bb,8BAA6B;CAC9B;;AAED;;EAGE,erB/Dc;EqBgEd,0BrBrCa;EqBsCb,sBrBtCa;CqBgDd;;AARC;;EAKI,gDrB7CS;CqB+CZ;;ADzBH;ECXA,erBbe;EqBcf,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBhBe;CoB0Bd;;ACRD;EACE,YrBrDW;EqBsDX,0BrBpBa;EqBqBb,sBrBrBa;CqBsBd;;AAED;EAEE,gDrB1Ba;CqB2Bd;;AAED;EAEE,erB/Ba;EqBgCb,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrBvCa;EqBwCb,sBrBxCa;CqBkDd;;AARC;;EAKI,gDrB/CS;CqBiDZ;;ADzBH;ECXA,erB9CgB;EqB+ChB,8BAA6B;EAC7B,uBAAsB;EACtB,sBrBjDgB;CoB2Df;;ACRD;EACE,erB5Cc;EqB6Cd,0BrBrDc;EqBsDd,sBrBtDc;CqBuDf;;AAED;EAEE,kDrB3Dc;CqB4Df;;AAED;EAEE,erBhEc;EqBiEd,8BAA6B;CAC9B;;AAED;;EAGE,erB/Dc;EqBgEd,0BrBxEc;EqByEd,sBrBzEc;CqBmFf;;AARC;;EAKI,kDrBhFU;CqBkFb;;ADzBH;ECXA,erBvCgB;EqBwChB,8BAA6B;EAC7B,uBAAsB;EACtB,sBrB1CgB;CoBoDf;;ACRD;EACE,YrBrDW;EqBsDX,0BrB9Cc;EqB+Cd,sBrB/Cc;CqBgDf;;AAED;EAEE,+CrBpDc;CqBqDf;;AAED;EAEE,erBzDc;EqB0Dd,8BAA6B;CAC9B;;AAED;;EAGE,YrBxEW;EqByEX,0BrBjEc;EqBkEd,sBrBlEc;CqB4Ef;;AARC;;EAKI,+CrBzEU;CqB2Eb;;ADdL;EACE,iBpBoL+B;EoBnL/B,epBzCe;EoB0Cf,8BAA6B;CAuB9B;;AlB7FC;EkByEE,epBoFgD;EoBnFhD,2BpBoFiC;EoBnFjC,8BAA6B;EAC7B,0BAAyB;ClB5EL;;AkBmExB;EAcI,2BpB6EiC;EoB5EjC,0BAAyB;EACzB,iBAAgB;CACjB;;AAjBH;EAqBI,epBpFc;EoBqFd,qBAAoB;CACrB;;AAUH;ECbE,qBrBuQgC;EqBtQhC,mBrB4JoD;EqB3JpD,iBrBwH+B;EqBrH7B,sBrB4H+B;CoBlHlC;;AAED;ECjBE,wBrBmQiC;EqBlQjC,oBrB6JoD;EqB5JpD,iBrByH+B;EqBtH7B,sBrB6H+B;CoB/GlC;;AAOD;EACE,eAAc;EACd,YAAW;CAMZ;;AARD;EAMI,mBpBwQ+B;CoBvQhC;;AAIH;;;EAII,YAAW;CACZ;;AE3IH;ELGM,iCjB4O2C;CsBzOhD;;ALCC;EKPF;ILQI,iBAAgB;GKFnB;CrBgrFA;;AqBtrFD;EAII,WAAU;CACX;;AAGH;EAEI,cAAa;CACd;;AAGH;EACE,mBAAkB;EAClB,UAAS;EACT,iBAAgB;ELdZ,8BjB6OwC;CsB7N7C;;ALZC;EKOF;ILNI,iBAAgB;GKWnB;CrBwrFA;;AsB5sFD;;;;EAIE,mBAAkB;CACnB;;ACuBG;EACE,sBAAqB;EACrB,SAAQ;EACR,UAAS;EACT,qBAA+B;EAC/B,wBAAkC;EAClC,YAAW;EAlCf,wBAA8B;EAC9B,sCAA4C;EAC5C,iBAAgB;EAChB,qCAA2C;CAuCxC;;AAkBD;EACE,eAAc;CACf;;ADjDL;EACE,mBAAkB;EAClB,UAAS;EACT,QAAO;EACP,cvBklBsC;EuBjlBtC,cAAa;EACb,YAAW;EACX,iBvBijBuC;EuBhjBvC,kBAA8B;EAC9B,qBAA4B;EAC5B,gBvBuOgC;EuBtOhC,evBNgB;EuBOhB,iBAAgB;EAChB,iBAAgB;EAChB,uBvBlBa;EuBmBb,6BAA4B;EAC5B,sCvBVa;EOhBX,uBP+NgC;CuBlMnC;;AAED;EACE,SAAQ;EACR,WAAU;CACX;;AAID;EAEI,UAAS;EACT,aAAY;EACZ,cAAa;EACb,wBvByhBuC;CuBxhBxC;;ACnBC;EACE,sBAAqB;EACrB,SAAQ;EACR,UAAS;EACT,qBAA+B;EAC/B,wBAAkC;EAClC,YAAW;EA3Bf,cAAa;EACb,sCAA4C;EAC5C,2BAAiC;EACjC,qCAA2C;CAgCxC;;AAkBD;EACE,eAAc;CACf;;ADRL;EAEI,OAAM;EACN,YAAW;EACX,WAAU;EACV,cAAa;EACb,sBvB2gBuC;CuB1gBxC;;ACjCC;EACE,sBAAqB;EACrB,SAAQ;EACR,UAAS;EACT,qBAA+B;EAC/B,wBAAkC;EAClC,YAAW;EApBf,oCAA0C;EAC1C,gBAAe;EACf,uCAA6C;EAC7C,yBAA+B;CAyB5B;;AAkBD;EACE,eAAc;CACf;;AAlCD;EDsCE,kBAAiB;CAClB;;AAIL;EAEI,OAAM;EACN,YAAW;EACX,WAAU;EACV,cAAa;EACb,uBvB0fuC;CuBzfxC;;AClDC;EACE,sBAAqB;EACrB,SAAQ;EACR,UAAS;EACT,qBAA+B;EAC/B,wBAAkC;EAClC,YAAW;CAQZ;;AAdD;EAkBI,cAAa;CACd;;AAED;EACE,sBAAqB;EACrB,SAAQ;EACR,UAAS;EACT,sBAAgC;EAChC,wBAAkC;EAClC,YAAW;EAlCjB,oCAA0C;EAC1C,0BAAgC;EAChC,uCAA6C;CAkCxC;;AAGH;EACE,eAAc;CACf;;AAbC;EDkCA,kBAAiB;CAClB;;AAML;EAKI,YAAW;EACX,aAAY;CACb;;AAKH;EElGE,UAAS;EACT,iBAAmB;EACnB,iBAAgB;EAChB,8BzBIgB;CuB6FjB;;AAKD;EACE,eAAc;EACd,YAAW;EACX,wBvByewC;EuBxexC,YAAW;EACX,iBvBiJ+B;EuBhJ/B,evBjGgB;EuBkGhB,oBAAmB;EACnB,oBAAmB;EACnB,8BAA6B;EAC7B,UAAS;CAwBV;;ArBhIC;EqB2GE,evBsdqD;EuBrdrD,sBAAqB;EJtHrB,0BnBKc;CEQf;;AqB2FH;EAoBI,YvBxHW;EuByHX,sBAAqB;EJ7HrB,0BnBkCa;CuB6Fd;;AAvBH;EA2BI,evBzHc;EuB0Hd,8BAA6B;CAK9B;;AAGH;EACE,eAAc;CACf;;AAGD;EACE,eAAc;EACd,uBvBicwC;EuBhcxC,iBAAgB;EAChB,oBvBsGoD;EuBrGpD,evB5IgB;EuB6IhB,oBAAmB;CACpB;;AAGD;EACE,eAAc;EACd,wBvBubwC;EuBtbxC,evBjJgB;CuBkJjB;;AGlKD;;EAEE,mBAAkB;EAClB,4BAAoB;EAApB,qBAAoB;EACpB,uBAAsB;CAyBvB;;AA7BD;;EAOI,mBAAkB;EAClB,mBAAc;EAAd,eAAc;CAYf;;AxBXD;;EwBII,WAAU;CxBJQ;;AwBTxB;;;;EAkBM,WAAU;CACX;;AAnBL;;;;;;;;EA2BI,kB1BkM6B;C0BjM9B;;AAIH;EACE,qBAAa;EAAb,cAAa;EACb,oBAAe;EAAf,gBAAe;EACf,qBAA2B;EAA3B,4BAA2B;CAK5B;;AARD;EAMI,YAAW;CACZ;;AAGH;EAEI,eAAc;CACf;;AAHH;;EnB5BI,2BmBoC8B;EnBnC9B,8BmBmC8B;CAC/B;;AATH;;EnBdI,0BmB2B6B;EnB1B7B,6BmB0B6B;CAC9B;;AAeH;EACE,yBAAmC;EACnC,wBAAkC;CAWnC;;AAbD;;;EAOI,eAAc;CACf;;AAED;EACE,gBAAe;CAChB;;AAGH;EACE,wBAAsC;EACtC,uBAAqC;CACtC;;AAED;EACE,uBAAsC;EACtC,sBAAqC;CACtC;;AAmBD;EACE,2BAAsB;EAAtB,uBAAsB;EACtB,sBAAuB;EAAvB,wBAAuB;EACvB,sBAAuB;EAAvB,wBAAuB;CAyBxB;;AA5BD;;EAOI,YAAW;CACZ;;AARH;;;;EAcI,iB1B8F6B;E0B7F7B,eAAc;CACf;;AAhBH;;EnB5FI,8BmBiH+B;EnBhH/B,6BmBgH+B;CAChC;;AAtBH;;EnB1GI,0BmBoI4B;EnBnI5B,2BmBmI4B;CAC7B;;AAgBH;;EAGI,iBAAgB;CAQjB;;AAXH;;;;EAOM,mBAAkB;EAClB,uBAAsB;EACtB,qBAAoB;CACrB;;ACnKL;EACE,mBAAkB;EAClB,qBAAa;EAAb,cAAa;EACb,oBAAe;EAAf,gBAAe;EACf,wBAAoB;EAApB,qBAAoB;EACpB,YAAW;CA+CZ;;AApDD;;;EAUI,mBAAkB;EAClB,mBAAc;EAAd,eAAc;EAGd,UAAS;EACT,iBAAgB;CAOjB;;AAtBH;;;;;;;;;EAoBM,kB3BsM2B;C2BrM5B;;AArBL;;;EA4BI,WAAU;CACX;;AA7BH;EAiCI,WAAU;CACX;;AAlCH;;EpBWI,2BoB2BmD;EpB1BnD,8BoB0BmD;CAAK;;AAtC5D;;EpByBI,0BoBcmD;EpBbnD,6BoBamD;CAAK;;AAvC5D;EA6CI,qBAAa;EAAb,cAAa;EACb,uBAAmB;EAAnB,oBAAmB;CAKpB;;AAnDH;;EpBWI,2BoBsC6E;EpBrC7E,8BoBqC6E;CAAK;;AAjDtF;EpByBI,0BoByBsE;EpBxBtE,6BoBwBsE;CAAK;;AAW/E;;EAEE,qBAAa;EAAb,cAAa;CAgBd;;AAlBD;;EAQI,mBAAkB;EAClB,WAAU;CACX;;AAVH;;;;;;;;EAgBI,kB3B6I6B;C2B5I9B;;AAGH;EAAuB,mB3ByIU;C2BzI4B;;AAC7D;EAAsB,kB3BwIW;C2BxI0B;;AAQ3D;EACE,qBAAa;EAAb,cAAa;EACb,uBAAmB;EAAnB,oBAAmB;EACnB,0B3B2PkC;E2B1PlC,iBAAgB;EAChB,gB3B0JgC;E2BzJhC,iB3B8J+B;E2B7J/B,iB3BiK+B;E2BhK/B,e3BvFgB;E2BwFhB,mBAAkB;EAClB,oBAAmB;EACnB,0B3B/FgB;E2BgGhB,0B3B9FgB;EOVd,uBP+NgC;C2B/GnC;;AApBD;;EAkBI,cAAa;CACd;;AASH;;;;;EAKE,6B3BkU+F;E2BjU/F,qB3BwOgC;E2BvOhC,mB3B6HoD;E2B5HpD,iB3ByF+B;EOzN7B,sBPgO+B;C2B9FlC;;AAED;;;;;EAKE,8B3BmT+F;E2BlT/F,wB3BwNiC;E2BvNjC,oB3BkHoD;E2BjHpD,iB3B8E+B;EO1N7B,sBPiO+B;C2BnFlC;;AAUD;;;;;;EpB3II,2BoBiJ4B;EpBhJ5B,8BoBgJ4B;CAC/B;;AAED;;;;;;EpBtII,0BoB4I2B;EpB3I3B,6BoB2I2B;CAC9B;;ACnKD;EACE,mBAAkB;EAClB,eAAc;EACd,mBAAiD;EACjD,qB5B2c4C;C4B1c7C;;AAED;EACE,4BAAoB;EAApB,qBAAoB;EACpB,mB5Buc0C;C4Btc3C;;AAED;EACE,mBAAkB;EAClB,YAAW;EACX,WAAU;CA4BX;;AA/BD;EAMI,Y5BjBW;EmBJX,0BnBkCa;C4BVd;;AATH;EAaI,iE5BMa;C4BLd;;AAdH;EAiBI,Y5B5BW;E4B6BX,0B5Boc8E;C4Blc/E;;AApBH;EAwBM,e5B7BY;C4BkCb;;AA7BL;EA2BQ,0B5BpCU;C4BqCX;;AASP;EACE,mBAAkB;EAClB,iBAAgB;CA8BjB;;AAhCD;EAMI,mBAAkB;EAClB,aAAiF;EACjF,c5BsZ0C;E4BrZ1C,eAAc;EACd,Y5BuZwC;E4BtZxC,a5BsZwC;E4BrZxC,qBAAoB;EACpB,YAAW;EACX,0BAAiB;EAAjB,uBAAiB;EAAjB,sBAAiB;EAAjB,kBAAiB;EACjB,0B5B5Dc;C4B8Df;;AAjBH;EAqBI,mBAAkB;EAClB,aAAiF;EACjF,c5BuY0C;E4BtY1C,eAAc;EACd,Y5BwYwC;E4BvYxC,a5BuYwC;E4BtYxC,YAAW;EACX,6BAA4B;EAC5B,mCAAkC;EAClC,yB5BqY2C;C4BpY5C;;AAQH;ErB7FI,uBP+NgC;C4B/HjC;;AAHH;ET3FI,0BnBkCa;C4BiEZ;;AARL;EAUM,2Nb/DqI;CagEtI;;AAXL;ET3FI,0BnBkCa;C4B2EZ;;AAlBL;EAoBM,wKbzEqI;Ca0EtI;;AArBL;EA0BM,yC5BnFW;C4BoFZ;;AA3BL;EA6BM,yC5BtFW;C4BuFZ;;AAQL;EAEI,mB5B6W+C;C4B5WhD;;AAHH;ETjII,0BnBkCa;C4BuGZ;;AARL;EAUM,qKbrGqI;CasGtI;;AAXL;EAgBM,yC5B/GW;C4BgHZ;;AAWL;EACE,sBAAqB;EACrB,YAAW;EACX,4B5BuR4F;E4BtR5F,2C5BmVwC;E4BlVxC,iB5BgG+B;E4B/F/B,e5BxJgB;E4ByJhB,uBAAsB;EACtB,uNAAsG;EACtG,0B5BsV0C;E4BrV1C,0B5B/JgB;E4BiKd,uB5BoDgC;E4B/ClC,yBAAgB;EAAhB,sBAAgB;EAAhB,iBAAgB;CAsCjB;;AAvDD;EAoBI,sB5B2PsE;E4B1PtE,WAAU;EAIR,kD5BsPoE;C4B1OvE;;AArCH;EAkCM,e5BpLY;E4BqLZ,uB5B5LS;C4B6LV;;AApCL;EAyCI,aAAY;EACZ,uB5B6SsC;E4B5StC,uBAAsB;CACvB;;AA5CH;EA+CI,e5BlMc;E4BmMd,0B5BvMc;C4BwMf;;AAjDH;EAqDI,WAAU;CACX;;AAGH;EACE,8B5BmO+F;E4BlO/F,sB5B2RyC;E4B1RzC,yB5B0RyC;E4BzRzC,e5B8SqC;C4B7StC;;AAED;EACE,6B5B+N+F;E4B9N/F,sB5BoRyC;E4BnRzC,yB5BmRyC;E4BlRzC,gB5B0SsC;C4BzSvC;;AAOD;EACE,mBAAkB;EAClB,sBAAqB;EACrB,YAAW;EACX,4B5B0M4F;E4BzM5F,iBAAgB;CACjB;;AAED;EACE,mBAAkB;EAClB,WAAU;EACV,YAAW;EACX,4B5BkM4F;E4BjM5F,UAAS;EACT,WAAU;CAoBX;;AA1BD;EASI,sB5BkLsE;E4BjLtE,iD5BzNa;C4B8Nd;;AAfH;EAaM,sB5B8KoE;C4B7KrE;;AAdL;EAkBI,0B5B7Pc;C4B8Pf;;AAnBH;EAuBM,kB5BySQ;C4BxST;;AAIL;EACE,mBAAkB;EAClB,OAAM;EACN,SAAQ;EACR,QAAO;EACP,WAAU;EACV,4B5BoK4F;E4BnK5F,0B5BoEkC;E4BnElC,iB5BnB+B;E4BoB/B,e5B3QgB;E4B4QhB,uB5BnRa;E4BoRb,0B5BhRgB;EOVd,uBP+NgC;C4B+EnC;;AA/BD;EAgBI,mBAAkB;EAClB,OAAM;EACN,SAAQ;EACR,UAAS;EACT,WAAU;EACV,eAAc;EACd,gB5BmJ2G;E4BlJ3G,0B5BoDgC;E4BnDhC,iB5BnC6B;E4BoC7B,e5B3Rc;E4B4Rd,kBAAiB;ETvSjB,0BnBMc;E4BmSd,+B5BjSc;EOVd,mCqB4SgF;CACjF;;AASH;EACE,YAAW;EACX,gBAAe;EACf,8BAA6B;EAC7B,yBAAgB;EAAhB,sBAAgB;EAAhB,iBAAgB;CA4GjB;;AAhHD;EAOI,cAAa;CAOd;;AAdH;EAW8B,iE5B7Rb;C4B6RiE;;AAXlF;EAY8B,iE5B9Rb;C4B8RiE;;AAZlF;EAa8B,iE5B/Rb;C4B+RiE;;AAblF;EAiBI,UAAS;CACV;;AAlBH;EAqBI,Y5B4M6C;E4B3M7C,a5B2M6C;E4B1M7C,qBAA2E;ET3U3E,0BnBkCa;E4B2Sb,U5B2M0C;EO1hB1C,oBP2hB6C;EiB1hB3C,6GjBid+H;E4B/HjI,yBAAgB;EAAhB,iBAAgB;CAKjB;;AXnVD;EWiTF;IXhTI,iBAAgB;GWkVjB;C3B2nGF;;A2B7pGD;ETpTI,0BnB6hB2E;C4BxM1E;;AAjCL;EAqCI,Y5BqLoC;E4BpLpC,e5BqLqC;E4BpLrC,mBAAkB;EAClB,gB5BoLuC;E4BnLvC,0B5BtVc;E4BuVd,0BAAyB;ErBhWzB,oBPohBoC;C4BjLrC;;AA7CH;EAgDI,Y5BiL6C;E4BhL7C,a5BgL6C;EmBrhB7C,0BnBkCa;E4BqUb,U5BiL0C;EO1hB1C,oBP2hB6C;EiB1hB3C,6GjBid+H;E4BrGjI,sBAAgB;EAAhB,iBAAgB;CAKjB;;AX7WD;EWiTF;IXhTI,iBAAgB;GW4WjB;C3B+nGF;;A2B3rGD;ETpTI,0BnB6hB2E;C4B9K1E;;AA3DL;EA+DI,Y5B2JoC;E4B1JpC,e5B2JqC;E4B1JrC,mBAAkB;EAClB,gB5B0JuC;E4BzJvC,0B5BhXc;E4BiXd,0BAAyB;ErB1XzB,oBPohBoC;C4BvJrC;;AAvEH;EA0EI,Y5BuJ6C;E4BtJ7C,a5BsJ6C;E4BrJ7C,cAAa;EACb,qB5BtC+B;E4BuC/B,oB5BvC+B;EmB3V/B,0BnBkCa;E4BkWb,U5BoJ0C;EO1hB1C,oBP2hB6C;EiB1hB3C,6GjBid+H;E4BxEjI,iBAAgB;CAKjB;;AX1YD;EWiTF;IXhTI,iBAAgB;GWyYjB;C3BmoGF;;A2B5tGD;ETpTI,0BnB6hB2E;C4BjJ1E;;AAxFL;EA4FI,Y5B8HoC;E4B7HpC,e5B8HqC;E4B7HrC,mBAAkB;EAClB,gB5B6HuC;E4B5HvC,8BAA6B;EAC7B,0BAAyB;EACzB,qBAA+C;CAEhD;;AApGH;EAuGI,0B5BpZc;EOTd,oBPohBoC;C4BrHrC;;AAzGH;EA4GI,mBAAkB;EAClB,0B5B1Zc;EOTd,oBPohBoC;C4B/GrC;;AAGH;;;EXvaM,6GjBid+H;C4BtCpI;;AXvaC;EWmaF;;;IXlaI,iBAAgB;GWsanB;C3B6oGA;;A4BxjHD;EACE,qBAAa;EAAb,cAAa;EACb,oBAAe;EAAf,gBAAe;EACf,gBAAe;EACf,iBAAgB;EAChB,iBAAgB;CACjB;;AAED;EACE,eAAc;EACd,qB7BgmBsC;C6BtlBvC;;A3BTC;E2BEE,sBAAqB;C3BCtB;;A2BNH;EAUI,e7BPc;C6BQf;;AAOH;EACE,iC7BnBgB;C6BqDjB;;AAnCD;EAII,oB7B6L6B;C6B5L9B;;AALH;EAQI,8BAAgD;EtB7BhD,gCPyNgC;EOxNhC,iCPwNgC;C6BhLjC;;A3BnCD;E2B2BI,sC7B9BY;CEMf;;A2BYH;EAgBM,e7B/BY;E6BgCZ,8BAA6B;EAC7B,0BAAyB;CAC1B;;AAnBL;;EAwBI,e7BtCc;E6BuCd,uB7B9CW;E6B+CX,mC7B/CW;C6BgDZ;;AA3BH;EA+BI,iB7BkK6B;EOtN7B,0BsBsD4B;EtBrD5B,2BsBqD4B;CAC7B;;AAQH;EtBrEI,uBP+NgC;C6BvJjC;;AAHH;;EAOI,Y7BtEW;E6BuEX,0B7BzCa;C6B0Cd;;AAQH;EAEI,mBAAc;EAAd,eAAc;EACd,mBAAkB;CACnB;;AAGH;EAEI,2BAAa;EAAb,cAAa;EACb,qBAAY;EAAZ,aAAY;EACZ,mBAAkB;CACnB;;AAQH;EAEI,cAAa;CACd;;AAHH;EAKI,eAAc;CACf;;ACnGH;EACE,mBAAkB;EAClB,qBAAa;EAAb,cAAa;EACb,oBAAe;EAAf,gBAAe;EACf,uBAAmB;EAAnB,oBAAmB;EACnB,uBAA8B;EAA9B,+BAA8B;EAC9B,qB9BwGW;C8B7FZ;;AAjBD;;EAYI,qBAAa;EAAb,cAAa;EACb,oBAAe;EAAf,gBAAe;EACf,uBAAmB;EAAnB,oBAAmB;EACnB,uBAA8B;EAA9B,+BAA8B;CAC/B;;AAQH;EACE,sBAAqB;EACrB,uB9BimB+E;E8BhmB/E,0B9BgmB+E;E8B/lB/E,mB9BkFW;E8BjFX,mB9BkNoD;E8BjNpD,qBAAoB;EACpB,oBAAmB;CAKpB;;A5BrCC;E4BmCE,sBAAqB;C5BhCtB;;A4ByCH;EACE,qBAAa;EAAb,cAAa;EACb,2BAAsB;EAAtB,uBAAsB;EACtB,gBAAe;EACf,iBAAgB;EAChB,iBAAgB;CAWjB;;AAhBD;EAQI,iBAAgB;EAChB,gBAAe;CAChB;;AAVH;EAaI,iBAAgB;EAChB,YAAW;CACZ;;AAQH;EACE,sBAAqB;EACrB,oB9ByhBuC;E8BxhBvC,uB9BwhBuC;C8BvhBxC;;AAWD;EACE,8BAAgB;EAAhB,iBAAgB;EAChB,qBAAY;EAAZ,aAAY;EAGZ,uBAAmB;EAAnB,oBAAmB;CACpB;;AAGD;EACE,yB9BmiBwC;E8BliBxC,mB9BmJoD;E8BlJpD,eAAc;EACd,8BAA6B;EAC7B,8BAAuC;EvB5GrC,uBP+NgC;C8BxGnC;;A5B3GC;E4BoGE,sBAAqB;C5BjGtB;;A4BwFH;EAcI,gBAAe;CAChB;;AAKH;EACE,sBAAqB;EACrB,aAAY;EACZ,cAAa;EACb,uBAAsB;EACtB,YAAW;EACX,oCAAmC;EACnC,2BAA0B;CAC3B;;AnB9DG;EmBuEC;;IAIK,iBAAgB;IAChB,gBAAe;GAChB;C7B8lHR;;AUxrHG;EmBoFA;IAUI,0BAAqB;IAArB,sBAAqB;IACrB,qBAA2B;IAA3B,4BAA2B;GAgC9B;EA3CA;IAcK,wBAAmB;IAAnB,oBAAmB;GAUpB;EAxBJ;IAiBO,mBAAkB;GACnB;EAlBN;IAqBO,sB9Bie6B;I8Bhe7B,qB9Bge6B;G8B/d9B;EAvBN;;IA6BK,sBAAiB;IAAjB,kBAAiB;GAClB;EA9BJ;IAiCK,gCAAwB;IAAxB,yBAAwB;IAGxB,8BAAgB;IAAhB,iBAAgB;GACjB;EArCJ;IAwCK,cAAa;GACd;C7BulHR;;AUvsHG;EmBuEC;;IAIK,iBAAgB;IAChB,gBAAe;GAChB;C7BkoHR;;AU5tHG;EmBoFA;IAUI,0BAAqB;IAArB,sBAAqB;IACrB,qBAA2B;IAA3B,4BAA2B;GAgC9B;EA3CA;IAcK,wBAAmB;IAAnB,oBAAmB;GAUpB;EAxBJ;IAiBO,mBAAkB;GACnB;EAlBN;IAqBO,sB9Bie6B;I8Bhe7B,qB9Bge6B;G8B/d9B;EAvBN;;IA6BK,sBAAiB;IAAjB,kBAAiB;GAClB;EA9BJ;IAiCK,gCAAwB;IAAxB,yBAAwB;IAGxB,8BAAgB;IAAhB,iBAAgB;GACjB;EArCJ;IAwCK,cAAa;GACd;C7B2nHR;;AU3uHG;EmBuEC;;IAIK,iBAAgB;IAChB,gBAAe;GAChB;C7BsqHR;;AUhwHG;EmBoFA;IAUI,0BAAqB;IAArB,sBAAqB;IACrB,qBAA2B;IAA3B,4BAA2B;GAgC9B;EA3CA;IAcK,wBAAmB;IAAnB,oBAAmB;GAUpB;EAxBJ;IAiBO,mBAAkB;GACnB;EAlBN;IAqBO,sB9Bie6B;I8Bhe7B,qB9Bge6B;G8B/d9B;EAvBN;;IA6BK,sBAAiB;IAAjB,kBAAiB;GAClB;EA9BJ;IAiCK,gCAAwB;IAAxB,yBAAwB;IAGxB,8BAAgB;IAAhB,iBAAgB;GACjB;EArCJ;IAwCK,cAAa;GACd;C7B+pHR;;AU/wHG;EmBuEC;;IAIK,iBAAgB;IAChB,gBAAe;GAChB;C7B0sHR;;AUpyHG;EmBoFA;IAUI,0BAAqB;IAArB,sBAAqB;IACrB,qBAA2B;IAA3B,4BAA2B;GAgC9B;EA3CA;IAcK,wBAAmB;IAAnB,oBAAmB;GAUpB;EAxBJ;IAiBO,mBAAkB;GACnB;EAlBN;IAqBO,sB9Bie6B;I8Bhe7B,qB9Bge6B;G8B/d9B;EAvBN;;IA6BK,sBAAiB;IAAjB,kBAAiB;GAClB;EA9BJ;IAiCK,gCAAwB;IAAxB,yBAAwB;IAGxB,8BAAgB;IAAhB,iBAAgB;GACjB;EArCJ;IAwCK,cAAa;GACd;C7BmsHR;;A6BjvHD;EAeQ,0BAAqB;EAArB,sBAAqB;EACrB,qBAA2B;EAA3B,4BAA2B;CAgC9B;;AAhDL;;EASU,iBAAgB;EAChB,gBAAe;CAChB;;AAXT;EAmBU,wBAAmB;EAAnB,oBAAmB;CAUpB;;AA7BT;EAsBY,mBAAkB;CACnB;;AAvBX;EA0BY,sB9Bie6B;E8Bhe7B,qB9Bge6B;C8B/d9B;;AA5BX;;EAkCU,sBAAiB;EAAjB,kBAAiB;CAClB;;AAnCT;EAsCU,gCAAwB;EAAxB,yBAAwB;EAGxB,8BAAgB;EAAhB,iBAAgB;CACjB;;AA1CT;EA6CU,cAAa;CACd;;AAYT;EAEI,0B9BnLW;C8BwLZ;;A5B5LD;E4B0LI,0B9BtLS;CEDZ;;A4BkLH;EAWM,0B9B5LS;C8BqMV;;A5BzMH;E4BmMM,0B9B/LO;CEDZ;;A4BkLH;EAkBQ,0B9BnMO;C8BoMR;;AAnBP;;;;EA0BM,0B9B3MS;C8B4MV;;AA3BL;EA+BI,0B9BhNW;E8BiNX,iC9BjNW;C8BkNZ;;AAjCH;EAoCI,sQ9BqbmS;C8BpbpS;;AArCH;EAwCI,0B9BzNW;C8BiOZ;;AAhDH;EA0CM,0B9B3NS;C8BgOV;;A5BpOH;E4BkOM,0B9B9NO;CEDZ;;A4BsOH;EAEI,Y9BjPW;C8BsPZ;;A5BhPD;E4B8OI,Y9BpPS;CESZ;;A4BsOH;EAWM,gC9B1PS;C8BmQV;;A5B7PH;E4BuPM,iC9B7PO;CESZ;;A4BsOH;EAkBQ,iC9BjQO;C8BkQR;;AAnBP;;;;EA0BM,Y9BzQS;C8B0QV;;AA3BL;EA+BI,gC9B9QW;E8B+QX,uC9B/QW;C8BgRZ;;AAjCH;EAoCI,4Q9B0XkS;C8BzXnS;;AArCH;EAwCI,gC9BvRW;C8B+RZ;;AAhDH;EA0CM,Y9BzRS;C8B8RV;;A5BxRH;E4BsRM,Y9B5RO;CESZ;;A6BfH;EACE,mBAAkB;EAClB,qBAAa;EAAb,cAAa;EACb,2BAAsB;EAAtB,uBAAsB;EACtB,aAAY;EACZ,sBAAqB;EACrB,uB/BAa;E+BCb,4BAA2B;EAC3B,uC/BQa;EOhBX,uBP+NgC;C+BpMnC;;AA3BD;EAYI,gBAAe;EACf,eAAc;CACf;;AAdH;ExBMI,gCPyNgC;EOxNhC,iCPwNgC;C+B5M/B;;AAnBL;ExBoBI,oCP2MgC;EO1MhC,mCP0MgC;C+BtM/B;;AAIL;EAGE,mBAAc;EAAd,eAAc;EACd,iB/BoqByC;C+BnqB1C;;AAED;EACE,uB/B+pBwC;C+B9pBzC;;AAED;EACE,sBAAgC;EAChC,iBAAgB;CACjB;;AAED;EACE,iBAAgB;CACjB;;A7BvCC;E6B2CE,sBAAqB;C7B3CD;;A6ByCxB;EAMI,qB/B8oBuC;C+B7oBxC;;AAOH;EACE,yB/BqoByC;E+BpoBzC,iBAAgB;EAChB,sC/BlDa;E+BmDb,8C/BnDa;C+B8Dd;;AAfD;ExB/DI,2DwBsE8E;CAC/E;;AARH;EAYM,cAAa;CACd;;AAIL;EACE,yB/BonByC;E+BnnBzC,sC/BlEa;E+BmEb,2C/BnEa;C+BwEd;;AARD;ExBhFI,2DPysBoF;C+BlnBrF;;AAQH;EACE,wBAAkC;EAClC,wB/BmmBwC;E+BlmBxC,uBAAiC;EACjC,iBAAgB;CACjB;;AAED;EACE,wBAAkC;EAClC,uBAAiC;CAClC;;AAGD;EACE,mBAAkB;EAClB,OAAM;EACN,SAAQ;EACR,UAAS;EACT,QAAO;EACP,iB/B2lByC;C+B1lB1C;;AAED;EACE,YAAW;ExBtHT,mCPysBoF;C+BjlBvF;;AAGD;EACE,YAAW;ExBtHT,4CPmsBoF;EOlsBpF,6CPksBoF;C+B3kBvF;;AAED;EACE,YAAW;ExB7GT,gDPqrBoF;EOprBpF,+CPorBoF;C+BtkBvF;;AAKD;EACE,qBAAa;EAAb,cAAa;EACb,2BAAsB;EAAtB,uBAAsB;CAqBvB;;AAvBD;EAKI,oB/BkkBwD;C+BjkBzD;;ApBtFC;EoBgFJ;IASI,wBAAmB;IAAnB,oBAAmB;IACnB,oB/B6jBwD;I+B5jBxD,mB/B4jBwD;G+BhjB3D;EAvBD;IAcM,qBAAa;IAAb,cAAa;IAEb,iBAAY;IAAZ,aAAY;IACZ,2BAAsB;IAAtB,uBAAsB;IACtB,mB/BqjBsD;I+BpjBtD,iBAAgB;IAChB,kB/BmjBsD;G+BljBvD;C9B8+HJ;;A8Br+HD;EACE,qBAAa;EAAb,cAAa;EACb,2BAAsB;EAAtB,uBAAsB;CA4EvB;;AA9ED;EAOI,oB/BkiBwD;C+BjiBzD;;ApBtHC;EoB8GJ;IAWI,wBAAmB;IAAnB,oBAAmB;GAmEtB;EA9ED;IAgBM,iBAAY;IAAZ,aAAY;IACZ,iBAAgB;GA2DjB;EA5EL;IAoBQ,eAAc;IACd,eAAc;GACf;EAtBP;IxBzJI,2BwBoLoC;IxBnLpC,8BwBmLoC;GAU/B;EArCT;;IA+BY,2BAA0B;GAC3B;EAhCX;;IAmCY,8BAA6B;GAC9B;EApCX;IxB3II,0BwBmLmC;IxBlLnC,6BwBkLmC;GAU9B;EAlDT;;IA4CY,0BAAyB;GAC1B;EA7CX;;IAgDY,6BAA4B;GAC7B;EAjDX;IxBtKI,uBP+NgC;G+BM3B;EA/DT;;IxBhKI,gCPyNgC;IOxNhC,iCPwNgC;G+BCzB;EA1DX;;IxBlJI,oCP2MgC;IO1MhC,mCP0MgC;G+BKzB;EA9DX;IxBtKI,iBwBwO8B;GAQzB;EA1ET;;;;IxBtKI,iBwB8OgC;GACzB;C9Bi+HV;;A8Br9HD;EAEI,uB/BucsC;C+BtcvC;;ApBtMC;EoBmMJ;IAMI,wB/BidiC;I+BjdjC,qB/BidiC;I+BjdjC,gB/BidiC;I+BhdjC,4B/BiduC;I+BjdvC,yB/BiduC;I+BjdvC,oB/BiduC;I+BhdvC,WAAU;IACV,UAAS;GAOZ;EAhBD;IAYM,sBAAqB;IACrB,YAAW;GACZ;C9Bw9HJ;;A8B/8HD;EAEI,iBAAgB;EAChB,iBAAgB;CACjB;;AAJH;EAQM,iBAAgB;CACjB;;AATL;EAaI,iBAAgB;EAChB,8BAA6B;EAC7B,6BAA4B;CAC7B;;AAhBH;EAmBI,0BAAyB;EACzB,2BAA0B;CAC3B;;AC3SH;EACE,qBAAa;EAAb,cAAa;EACb,oBAAe;EAAf,gBAAe;EACf,sBhCy3BsC;EgCx3BtC,oBhC23BsC;EgC13BtC,iBAAgB;EAChB,0BhCMgB;EORd,uBP+NgC;CgC3NnC;;AAED;EAGI,qBhCg3BqC;CgCx2BtC;;AAXH;EAMM,sBAAqB;EACrB,sBhC42BmC;EgC32BnC,ehCFY;EgCGZ,ahCi3BuC;CgCh3BxC;;AAVL;EAoBI,2BAA0B;CAC3B;;AArBH;EAwBI,sBAAqB;CACtB;;AAzBH;EA4BI,ehCtBc;CgCuBf;;ACvCH;EACE,qBAAa;EAAb,cAAa;E7BGb,gBAAe;EACf,iBAAgB;EGDd,uBP+NgC;CiC/NnC;;AAED;EACE,mBAAkB;EAClB,eAAc;EACd,wBjC2pBwC;EiC1pBxC,kBjCsN+B;EiCrN/B,kBjC8pBsC;EiC7pBtC,ejC4Be;EiC3Bf,uBjCHa;EiCIb,0BjCDgB;CiCqBjB;;AA5BD;EAWI,WAAU;EACV,ejCuJgD;EiCtJhD,sBAAqB;EACrB,0BjCRc;EiCSd,sBjCRc;CiCSf;;AAhBH;EAmBI,WAAU;EACV,WjCupBiC;EiCtpBjC,iDjCaa;CiCZd;;AAtBH;EA0BI,gBAAe;CAChB;;AAGH;EAGM,eAAc;E1BRhB,gCPoMgC;EOnMhC,mCPmMgC;CiC1L/B;;AALL;E1BnBI,iCPkNgC;EOjNhC,oCPiNgC;CiCrL/B;;AAVL;EAcI,WAAU;EACV,YjCzCW;EiC0CX,0BjCZa;EiCab,sBjCba;CiCcd;;AAlBH;EAqBI,ejCzCc;EiC0Cd,qBAAoB;EAEpB,aAAY;EACZ,uBjCnDW;EiCoDX,sBjCjDc;CiCkDf;;AC5DD;EACE,wBlCoqBsC;EkCnqBtC,mBlC2PkD;EkC1PlD,iBlCuN6B;CkCtN9B;;AAIG;E3BoBF,+BPqM+B;EOpM/B,kCPoM+B;CkCvN5B;;AAGD;E3BCF,gCPmN+B;EOlN/B,mCPkN+B;CkClN5B;;AAfL;EACE,wBlCkqBqC;EkCjqBrC,oBlC4PkD;EkC3PlD,iBlCwN6B;CkCvN9B;;AAIG;E3BoBF,+BPsM+B;EOrM/B,kCPqM+B;CkCxN5B;;AAGD;E3BCF,gCPoN+B;EOnN/B,mCPmN+B;CkCnN5B;;ACbP;EACE,sBAAqB;EACrB,sBnCowBsC;EmCnwBtC,enCgwBqC;EmC/vBrC,iBnC4P+B;EmC3P/B,eAAc;EACd,mBAAkB;EAClB,oBAAmB;EACnB,yBAAwB;E5BTtB,uBP+NgC;CmC/MnC;;AAfD;EAaI,cAAa;CACd;;AAIH;EACE,mBAAkB;EAClB,UAAS;CACV;;AAMD;EACE,qBnC6uBsC;EmC5uBtC,oBnC4uBsC;EO1wBpC,qBP6wBqC;CmC7uBxC;;AAOC;EC1CA,YpCSa;EoCRb,0BpCsCe;CmCKd;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,YpCSa;EoCRb,0BpCcgB;CmC6Bf;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,YpCSa;EoCRb,0BpC6Ce;CmCFd;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,YpCSa;EoCRb,0BpC+Ce;CmCJd;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,epCkBgB;EoCjBhB,0BpC4Ce;CmCDd;;AjC7BD;EkCVI,epCaY;EoCZZ,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,YpCSa;EoCRb,0BpC0Ce;CmCCd;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,epCkBgB;EoCjBhB,0BpCSgB;CmCkCf;;AjC7BD;EkCVI,epCaY;EoCZZ,sBAAqB;EACrB,0BAAkC;ClCWrC;;AiCwBD;EC1CA,YpCSa;EoCRb,0BpCgBgB;CmC2Bf;;AjC7BD;EkCVI,YpCIS;EoCHT,sBAAqB;EACrB,0BAAkC;ClCWrC;;AmCnBH;EACE,mBAAoD;EACpD,oBrCgsBsC;EqC/rBtC,0BrCSgB;EORd,sBPgO+B;CqC3NlC;;A1BmDG;E0B5DJ;IAOI,mBrC2rBoC;GqCzrBvC;CpC++IA;;AoC7+ID;EACE,iBAAgB;EAChB,gBAAe;E9BTb,iB8BUsB;CACzB;;ACXD;EACE,mBAAkB;EAClB,yBtCmzByC;EsClzBzC,oBtCmzBsC;EsClzBtC,8BAA6C;E/BJ3C,uBP+NgC;CsCzNnC;;AAGD;EAEE,eAAc;CACf;;AAGD;EACE,iBtCiP+B;CsChPhC;;AAOD;EACE,oBAAwD;CAUzD;;AAXD;EAKI,mBAAkB;EAClB,OAAM;EACN,SAAQ;EACR,yBtCqxBuC;EsCpxBvC,eAAc;CACf;;AASD;EC9CA,exBmFgE;EI9E9D,0BJ8E8D;EwBjFhE,sBxBiFgE;CuBnC/D;;AC5CD;EACE,0BAAqC;CACtC;;AAED;EACE,eAA0B;CAC3B;;ADoCD;EC9CA,exBmFgE;EI9E9D,0BJ8E8D;EwBjFhE,sBxBiFgE;CuBnC/D;;AC5CD;EACE,0BAAqC;CACtC;;AAED;EACE,eAA0B;CAC3B;;ADoCD;EC9CA,exBmFgE;EI9E9D,0BJ8E8D;EwBjFhE,sBxBiFgE;CuBnC/D;;AC5CD;EACE,0BAAqC;CACtC;;AAED;EACE,eAA0B;CAC3B;;ADoCD;EC9CA,exBmFgE;EI9E9D,0BJ8E8D;EwBjFhE,sBxBiFgE;CuBnC/D;;AC5CD;EACE,0BAAqC;CACtC;;AAED;EACE,eAA0B;CAC3B;;ADoCD;EC9CA,exBmFgE;EI9E9D,0BJ8E8D;EwBjFhE,sBxBiFgE;CuBnC/D;;AC5CD;EACE,0BAAqC;CACtC;;AAED;EACE,eAA0B;CAC3B;;ADoCD;EC9CA,exBmFgE;EI9E9D,0BJ8E8D;EwBjFhE,sBxBiFgE;CuBnC/D;;AC5CD;EACE,0BAAqC;CACtC;;AAED;EACE,eAA0B;CAC3B;;ADoCD;EC9CA,exBmFgE;EI9E9D,0BJ8E8D;EwBjFhE,sBxBiFgE;CuBnC/D;;AC5CD;EACE,0BAAqC;CACtC;;AAED;EACE,eAA0B;CAC3B;;ADoCD;EC9CA,exBmFgE;EI9E9D,0BJ8E8D;EwBjFhE,sBxBiFgE;CuBnC/D;;AC5CD;EACE,0BAAqC;CACtC;;AAED;EACE,eAA0B;CAC3B;;ACXH;EACE;IAAO,4BAAuC;GvC8oJ7C;EuC7oJD;IAAK,yBAAwB;GvCgpJ5B;CACF;;AuCnpJD;EACE;IAAO,4BAAuC;GvC8oJ7C;EuC7oJD;IAAK,yBAAwB;GvCgpJ5B;CACF;;AuC9oJD;EACE,qBAAa;EAAb,cAAa;EACb,axC+zBsC;EwC9zBtC,iBAAgB;EAChB,mBxC8zByD;EwC7zBzD,0BxCEgB;EORd,uBP+NgC;CwCtNnC;;AAED;EACE,qBAAa;EAAb,cAAa;EACb,2BAAsB;EAAtB,uBAAsB;EACtB,sBAAuB;EAAvB,wBAAuB;EACvB,YxCTa;EwCUb,mBAAkB;EAClB,oBAAmB;EACnB,0BxCkBe;EiBnCX,4BjBy0B4C;CwCtzBjD;;AvBfC;EuBMF;IvBLI,iBAAgB;GuBcnB;CvCqpJA;;AuCnpJD;ErBiBE,sMAA6I;EqBf7I,2BxC0yBsC;CwCzyBvC;;AAED;EACE,2DxC6yBoD;EwC7yBpD,mDxC6yBoD;CwC5yBrD;;ACjCD;EACE,qBAAa;EAAb,cAAa;EACb,sBAAuB;EAAvB,wBAAuB;CACxB;;AAED;EACE,YAAO;EAAP,QAAO;CACR;;ACHD;EACE,qBAAa;EAAb,cAAa;EACb,2BAAsB;EAAtB,uBAAsB;EAGtB,gBAAe;EACf,iBAAgB;CACjB;;AAQD;EACE,YAAW;EACX,e1CJgB;E0CKhB,oBAAmB;CAapB;;AxCnBC;EwCUE,e1CTc;E0CUd,sBAAqB;EACrB,0B1CjBc;CEQf;;AwCAH;EAaI,e1Cbc;E0Ccd,0B1CrBc;C0CsBf;;AAQH;EACE,mBAAkB;EAClB,eAAc;EACd,yB1C2yByC;E0CzyBzC,oB1CiL+B;E0ChL/B,uB1CtCa;E0CuCb,uC1C7Ba;C0C0Dd;;AApCD;EnChCI,gCPyNgC;EOxNhC,iCPwNgC;C0C9KjC;;AAXH;EAcI,iBAAgB;EnChChB,oCP2MgC;EO1MhC,mCP0MgC;C0CzKjC;;AxC1CD;EwC6CE,WAAU;EACV,sBAAqB;CxC3CtB;;AwCuBH;EAyBI,e1CnDc;E0CoDd,uB1C1DW;C0C2DZ;;AA3BH;EA+BI,WAAU;EACV,Y1ChEW;E0CiEX,0B1CnCa;E0CoCb,sB1CpCa;C0CqCd;;AASH;EAEI,gBAAe;EACf,eAAc;EnCrFd,iBmCsFwB;CACzB;;AALH;EASM,cAAa;CACd;;AAVL;EAeM,iBAAgB;CACjB;;ACnGH;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;AAdL;EACE,e5BgF8D;E4B/E9D,0B5B+E8D;C4BjE/D;;AzCHD;EyCPM,e5B2E0D;E4B1E1D,0BAAyC;CzCS9C;;AyChBD;EAWM,Y3CJO;E2CKP,0B5BqE0D;E4BpE1D,sB5BoE0D;C4BnE3D;;ACjBP;EACE,aAAY;EACZ,kB5C+5BuD;E4C95BvD,iB5CkQ+B;E4CjQ/B,eAAc;EACd,Y5Cea;E4Cdb,0B5CIa;E4CHb,YAAW;CAaZ;;AApBD;EAkBI,gBAAe;CAChB;;A1CHD;E0CJI,Y5CQS;E4CPT,sBAAqB;EACrB,aAAY;C1CKf;;A0CSH;EACE,WAAU;EACV,8BAA6B;EAC7B,UAAS;EACT,yBAAwB;CACzB;;AC3BD;EAEE,iBAAgB;CAMjB;;AARD;EAKI,mBAAkB;EAClB,iBAAgB;CACjB;;AAIH;EACE,gBAAe;EACf,OAAM;EACN,SAAQ;EACR,UAAS;EACT,QAAO;EACP,c7CilBsC;E6ChlBtC,cAAa;EACb,iBAAgB;EAGhB,WAAU;CAIX;;AAGD;EACE,mBAAkB;EAClB,YAAW;EACX,e7CmvBuC;E6CjvBvC,qBAAoB;CAUrB;;AAPC;E5BtCI,4CjB4yBoD;EiB5yBpD,oCjB4yBoD;EiB5yBpD,qEjB4yBoD;E6CpwBtD,sCAA6B;EAA7B,8BAA6B;CAC9B;;A5BrCD;E4BkCA;I5BjCE,iBAAgB;G4BoCjB;C5C85JF;;A4C75JC;EACE,mCAA0B;EAA1B,2BAA0B;CAC3B;;AAGH;EACE,qBAAa;EAAb,cAAa;EACb,uBAAmB;EAAnB,oBAAmB;EACnB,sCAAsD;CAQvD;;AAXD;EAOI,eAAc;EACd,mCAAmD;EACnD,YAAW;CACZ;;AAIH;EACE,mBAAkB;EAClB,qBAAa;EAAb,cAAa;EACb,2BAAsB;EAAtB,uBAAsB;EACtB,YAAW;EAEX,qBAAoB;EACpB,uB7C/Da;E6CgEb,6BAA4B;EAC5B,qC7CvDa;EOhBX,sBPgO+B;E6CrJjC,WAAU;CACX;;AAGD;EACE,gBAAe;EACf,OAAM;EACN,SAAQ;EACR,UAAS;EACT,QAAO;EACP,c7C8gBsC;E6C7gBtC,uB7CtEa;C6C2Ed;;AAZD;EAUW,WAAU;CAAI;;AAVzB;EAWW,a7CwsB2B;C6CxsBS;;AAK/C;EACE,qBAAa;EAAb,cAAa;EACb,sBAAuB;EAAvB,wBAAuB;EACvB,uBAA8B;EAA9B,+BAA8B;EAC9B,c7CosBsC;E6CnsBtC,iC7C5FgB;EOFd,+BP0N+B;EOzN/B,gCPyN+B;C6CpHlC;;AAbD;EASI,c7C+rBoC;E6C7rBpC,+BAAuF;CACxF;;AAIH;EACE,iBAAgB;EAChB,iB7CmJ+B;C6ClJhC;;AAID;EACE,mBAAkB;EAGlB,mBAAc;EAAd,eAAc;EACd,c7CwpBsC;C6CvpBvC;;AAGD;EACE,qBAAa;EAAb,cAAa;EACb,uBAAmB;EAAnB,oBAAmB;EACnB,mBAAyB;EAAzB,0BAAyB;EACzB,c7CgpBsC;E6C/oBtC,8B7C5HgB;C6CiIjB;;AAVD;EAQyB,oBAAmB;CAAI;;AARhD;EASwB,qBAAoB;CAAI;;AAIhD;EACE,mBAAkB;EAClB,aAAY;EACZ,YAAW;EACX,aAAY;EACZ,iBAAgB;CACjB;;AlC1FG;EkCzBJ;IAyHI,iB7CkpBqC;I6CjpBrC,qBAAyC;GAC1C;EA1GH;IA6GI,uCAA8D;GAM/D;EAnHH;IAgHM,oCAA2D;GAC5D;EAQH;IAAY,iB7CkoB2B;G6CloBH;C5Cg5JrC;;AUjgKG;EkCsHF;IAAY,iB7C2nB2B;G6C3nBH;C5Ci5JrC;;A6ClkKD;EACE,mBAAkB;EAClB,c9CumBsC;E8CtmBtC,eAAc;EACd,U9CguBmC;E+CpuBnC,sL/CyPoM;E+CvPpM,mBAAkB;EAClB,iB/CgQ+B;E+C/P/B,iB/CmQ+B;E+ClQ/B,iBAAgB;EAChB,kBAAiB;EACjB,sBAAqB;EACrB,kBAAiB;EACjB,qBAAoB;EACpB,uBAAsB;EACtB,mBAAkB;EAClB,qBAAoB;EACpB,oBAAmB;EACnB,iBAAgB;EDNhB,oB9CwPoD;E8CtPpD,sBAAqB;EACrB,WAAU;CAiBX;;AA5BD;EAaW,a9CotB2B;C8CptBE;;AAbxC;EAgBI,mBAAkB;EAClB,eAAc;EACd,c9CotBqC;E8CntBrC,e9CotBqC;C8C5sBtC;;AA3BH;EAsBM,mBAAkB;EAClB,YAAW;EACX,0BAAyB;EACzB,oBAAmB;CACpB;;AAIL;EACE,kBAAgC;CAWjC;;AAZD;EAII,UAAS;CAOV;;AAXH;EAOM,OAAM;EACN,8BAAgE;EAChE,uB9CpBS;C8CqBV;;AAIL;EACE,kB9C0rBuC;C8C7qBxC;;AAdD;EAII,QAAO;EACP,c9CsrBqC;E8CrrBrC,e9CorBqC;C8C7qBtC;;AAbH;EASM,SAAQ;EACR,qCAA2F;EAC3F,yB9CpCS;C8CqCV;;AAIL;EACE,kBAAgC;CAWjC;;AAZD;EAII,OAAM;CAOP;;AAXH;EAOM,UAAS;EACT,8B9CmqBmC;E8ClqBnC,0B9ClDS;C8CmDV;;AAIL;EACE,kB9C4pBuC;C8C/oBxC;;AAdD;EAII,SAAQ;EACR,c9CwpBqC;E8CvpBrC,e9CspBqC;C8C/oBtC;;AAbH;EASM,QAAO;EACP,qC9CmpBmC;E8ClpBnC,wB9ClES;C8CmEV;;AAoBL;EACE,iB9CknBuC;E8CjnBvC,wB9CunBuC;E8CtnBvC,Y9CpGa;E8CqGb,mBAAkB;EAClB,uB9C5Fa;EOhBX,uBP+NgC;C8CjHnC;;AElHD;EACE,mBAAkB;EAClB,OAAM;EACN,QAAO;EACP,chDqmBsC;EgDpmBtC,eAAc;EACd,iBhD0uBuC;E+C/uBvC,sL/CyPoM;E+CvPpM,mBAAkB;EAClB,iB/CgQ+B;E+C/P/B,iB/CmQ+B;E+ClQ/B,iBAAgB;EAChB,kBAAiB;EACjB,sBAAqB;EACrB,kBAAiB;EACjB,qBAAoB;EACpB,uBAAsB;EACtB,mBAAkB;EAClB,qBAAoB;EACpB,oBAAmB;EACnB,iBAAgB;ECLhB,oBhDuPoD;EgDrPpD,sBAAqB;EACrB,uBhDHa;EgDIb,6BAA4B;EAC5B,qChDKa;EOhBX,sBPgO+B;CgDjMlC;;AAnCD;EAoBI,mBAAkB;EAClB,eAAc;EACd,YhDyuBoC;EgDxuBpC,ehDyuBqC;EgDxuBrC,iBhD4M+B;CgDlMhC;;AAlCH;EA4BM,mBAAkB;EAClB,eAAc;EACd,YAAW;EACX,0BAAyB;EACzB,oBAAmB;CACpB;;AAIL;EACE,sBhD0tBuC;CgDtsBxC;;AArBD;EAII,kCAAwE;CACzE;;AALH;;;EASI,8BAAgE;CACjE;;AAVH;EAaI,UAAS;EACT,sChDgtBmE;CgD/sBpE;;;AAfH;;EAkBI,YhDyK6B;EgDxK7B,uBhD9CW;CgD+CZ;;AAGH;EACE,oBhDmsBuC;CgD5qBxC;;AAxBD;EAII,gCAAsE;EACtE,chD+rBqC;EgD9rBrC,ahD6rBoC;EgD5rBpC,iBAA2B;CAC5B;;AARH;;;EAYI,qCAA2F;CAC5F;;AAbH;EAgBI,QAAO;EACP,wChDsrBmE;CgDrrBpE;;;AAlBH;;EAqBI,UhD+I6B;EgD9I7B,yBhDxEW;CgDyEZ;;AAGH;EACE,mBhDyqBuC;CgDzoBxC;;AAjCD;EAII,+BAAqE;CACtE;;AALH;;;EASI,qCAA2F;CAC5F;;AAVH;EAaI,OAAM;EACN,yChD+pBmE;CgD9pBpE;;;AAfH;;EAkBI,ShDwH6B;EgDvH7B,0BhD/FW;CgDgGZ;;AApBH;EAwBI,mBAAkB;EAClB,OAAM;EACN,UAAS;EACT,eAAc;EACd,YhD6oBoC;EgD5oBpC,qBAAwC;EACxC,YAAW;EACX,iChDioBuD;CgDhoBxD;;AAGH;EACE,qBhDsoBuC;CgD/mBxC;;AAxBD;EAII,iCAAuE;EACvE,chDkoBqC;EgDjoBrC,ahDgoBoC;EgD/nBpC,iBAA2B;CAC5B;;AARH;;;EAYI,qChD2nBqC;CgD1nBtC;;AAbH;EAgBI,SAAQ;EACR,uChDynBmE;CgDxnBpE;;;AAlBH;;EAqBI,WhDkF6B;EgDjF7B,wBhDrIW;CgDsIZ;;AAoBH;EACE,wBhDolBwC;EgDnlBxC,iBAAgB;EAChB,gBhDwFgC;EgDvFhC,ehD6GmC;EgD5GnC,0BhD6kByD;EgD5kBzD,iCAAyE;EzChKvE,2CyCiKyE;EzChKzE,4CyCgKyE;CAM5E;;AAbD;EAWI,cAAa;CACd;;AAGH;EACE,wBhDqkBwC;EgDpkBxC,ehDlKgB;CgDmKjB;;AC5KD;EACE,mBAAkB;CACnB;;AAED;EACE,mBAAkB;EAClB,YAAW;EACX,iBAAgB;CACjB;;AAED;EACE,mBAAkB;EAClB,cAAa;EACb,uBAAmB;EAAnB,oBAAmB;EACnB,YAAW;EACX,oCAA2B;EAA3B,4BAA2B;EAC3B,4BAAmB;EAAnB,oBAAmB;CACpB;;AAED;;;EAGE,eAAc;EhC3BV,wCjBu5BgD;EiBv5BhD,gCjBu5BgD;EiBv5BhD,6DjBu5BgD;CiD13BrD;;AhCzBC;EgCoBF;;;IhCnBI,iBAAgB;GgCwBnB;ChD42KA;;AgD12KD;;EAEE,mBAAkB;EAClB,OAAM;CACP;;AAED;;EAEE,iCAAwB;EAAxB,yBAAwB;CAKzB;;AAHyC;EAJ1C;;IAKI,wCAA+B;IAA/B,gCAA+B;GAElC;ChD+2KA;;AgD72KD;;EAEE,oCAA2B;EAA3B,4BAA2B;CAK5B;;AAHyC;EAJ1C;;IAKI,2CAAkC;IAAlC,mCAAkC;GAErC;ChDk3KA;;AgDh3KD;;EAEE,qCAA4B;EAA5B,6BAA4B;CAK7B;;AAHyC;EAJ1C;;IAKI,4CAAmC;IAAnC,oCAAmC;GAEtC;ChDq3KA;;AgD92KD;EAEI,WAAU;EACV,yBAAwB;EACxB,6BAA4B;CAC7B;;AALH;;;EAUI,WAAU;CACX;;AAXH;;EAeI,WAAU;CACX;;AAhBH;;;;;EAuBI,iCAAwB;EAAxB,yBAAwB;CAKzB;;AAHyC;EAzB5C;;;;;IA0BM,wCAA+B;IAA/B,gCAA+B;GAElC;ChDq3KF;;AgD72KD;;EAEE,mBAAkB;EAClB,OAAM;EACN,UAAS;EAET,qBAAa;EAAb,cAAa;EACb,uBAAmB;EAAnB,oBAAmB;EACnB,sBAAuB;EAAvB,wBAAuB;EACvB,WjDqxBqC;EiDpxBrC,YjD9Ga;EiD+Gb,mBAAkB;EAClB,ajDmxBoC;CiDxwBrC;;A/CrHC;;;E+CgHE,YjDtHW;EiDuHX,sBAAqB;EACrB,WAAU;EACV,YAAW;C/ChHZ;;A+CmHH;EACE,QAAO;CAIR;;AACD;EACE,SAAQ;CAIT;;AAGD;;EAEE,sBAAqB;EACrB,YjDgwBsC;EiD/vBtC,ajD+vBsC;EiD9vBtC,gDAA+C;EAC/C,2BAA0B;CAC3B;;AACD;EACE,iNlCjHyI;CkCkH1I;;AACD;EACE,iNlCpHyI;CkCqH1I;;AAQD;EACE,mBAAkB;EAClB,SAAQ;EACR,aAAY;EACZ,QAAO;EACP,YAAW;EACX,qBAAa;EAAb,cAAa;EACb,sBAAuB;EAAvB,wBAAuB;EACvB,gBAAe;EAEf,kBjDytBqC;EiDxtBrC,iBjDwtBqC;EiDvtBrC,iBAAgB;CAqCjB;;AAjDD;EAeI,mBAAkB;EAClB,mBAAc;EAAd,eAAc;EACd,YjDqtBoC;EiDptBpC,YjDqtBmC;EiDptBnC,kBjDqtBmC;EiDptBnC,iBjDotBmC;EiDntBnC,oBAAmB;EACnB,gBAAe;EACf,2CjDtLW;CiD2MZ;;AA5CH;EA2BM,mBAAkB;EAClB,WAAU;EACV,QAAO;EACP,sBAAqB;EACrB,YAAW;EACX,aAAY;EACZ,YAAW;CACZ;;AAlCL;EAoCM,mBAAkB;EAClB,cAAa;EACb,QAAO;EACP,sBAAqB;EACrB,YAAW;EACX,aAAY;EACZ,YAAW;CACZ;;AA3CL;EA+CI,uBjD9MW;CiD+MZ;;AAQH;EACE,mBAAkB;EAClB,WAA6C;EAC7C,aAAY;EACZ,UAA4C;EAC5C,YAAW;EACX,kBAAiB;EACjB,qBAAoB;EACpB,YjD/Na;EiDgOb,mBAAkB;CACnB;;ACzOD;EAAqB,oCAAmC;CAAI;;AAC5D;EAAqB,+BAA8B;CAAI;;AACvD;EAAqB,kCAAiC;CAAI;;AAC1D;EAAqB,kCAAiC;CAAI;;AAC1D;EAAqB,uCAAsC;CAAI;;AAC/D;EAAqB,oCAAmC;CAAI;;ACF1D;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AiDdD;EACE,qCAAmC;CACpC;;AjDSD;;;EiDLI,qCAAgD;CjDQnD;;AkDPH;EACE,kCAAmC;CACpC;;AAED;EACE,yCAAwC;CACzC;;ACZD;EAAkB,qCAAoD;CAAI;;AAC1E;EAAkB,yCAAwD;CAAI;;AAC9E;EAAkB,2CAA0D;CAAI;;AAChF;EAAkB,4CAA2D;CAAI;;AACjF;EAAkB,0CAAyD;CAAI;;AAE/E;EAAmB,qBAAoB;CAAI;;AAC3C;EAAmB,yBAAwB;CAAI;;AAC/C;EAAmB,2BAA0B;CAAI;;AACjD;EAAmB,4BAA2B;CAAI;;AAClD;EAAmB,0BAAyB;CAAI;;AAG9C;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAFD;EACE,iCAA+B;CAChC;;AAGH;EACE,8BAA+B;CAChC;;AAMD;EACE,kCAAwC;CACzC;;AACD;EACE,2CAAiD;EACjD,4CAAkD;CACnD;;AACD;EACE,4CAAkD;EAClD,+CAAqD;CACtD;;AACD;EACE,+CAAqD;EACrD,8CAAoD;CACrD;;AACD;EACE,2CAAiD;EACjD,8CAAoD;CACrD;;AAED;EACE,8BAA6B;CAC9B;;AAED;EACE,4BAA2B;CAC5B;;ACzDC;EACE,eAAc;EACd,YAAW;EACX,YAAW;CACZ;;ACKC;EAA2B,yBAAwB;CAAI;;AACvD;EAA2B,2BAA0B;CAAI;;AACzD;EAA2B,iCAAgC;CAAI;;AAC/D;EAA2B,0BAAyB;CAAI;;AACxD;EAA2B,0BAAyB;CAAI;;AACxD;EAA2B,8BAA6B;CAAI;;AAC5D;EAA2B,+BAA8B;CAAI;;AAC7D;EAA2B,gCAAwB;EAAxB,yBAAwB;CAAI;;AACvD;EAA2B,uCAA+B;EAA/B,gCAA+B;CAAI;;A5C0C9D;E4ClDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CtD21LjE;;AUjzLG;E4ClDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CtDy3LjE;;AU/0LG;E4ClDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CtDu5LjE;;AU72LG;E4ClDA;IAA2B,yBAAwB;GAAI;EACvD;IAA2B,2BAA0B;GAAI;EACzD;IAA2B,iCAAgC;GAAI;EAC/D;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,0BAAyB;GAAI;EACxD;IAA2B,8BAA6B;GAAI;EAC5D;IAA2B,+BAA8B;GAAI;EAC7D;IAA2B,gCAAwB;IAAxB,yBAAwB;GAAI;EACvD;IAA2B,uCAA+B;IAA/B,gCAA+B;GAAI;CtDq7LjE;;AsD56LD;EACE;IAAwB,yBAAwB;GAAI;EACpD;IAAwB,2BAA0B;GAAI;EACtD;IAAwB,iCAAgC;GAAI;EAC5D;IAAwB,0BAAyB;GAAI;EACrD;IAAwB,0BAAyB;GAAI;EACrD;IAAwB,8BAA6B;GAAI;EACzD;IAAwB,+BAA8B;GAAI;EAC1D;IAAwB,gCAAwB;IAAxB,yBAAwB;GAAI;EACpD;IAAwB,uCAA+B;IAA/B,gCAA+B;GAAI;CtDi8L5D;;AuDn+LD;EACE,mBAAkB;EAClB,eAAc;EACd,YAAW;EACX,WAAU;EACV,iBAAgB;CAoBjB;;AAzBD;EAQI,eAAc;EACd,YAAW;CACZ;;AAVH;;;;;EAiBI,mBAAkB;EAClB,OAAM;EACN,UAAS;EACT,QAAO;EACP,YAAW;EACX,aAAY;EACZ,UAAS;CACV;;AAGH;EAEI,wBAA+B;CAChC;;AAGH;EAEI,oBAA+B;CAChC;;AAGH;EAEI,iBAA8B;CAC/B;;AAGH;EAEI,kBAA8B;CAC/B;;ACxCC;EAAgC,mCAA8B;EAA9B,+BAA8B;CAAI;;AAClE;EAAgC,sCAAiC;EAAjC,kCAAiC;CAAI;;AACrE;EAAgC,2CAAsC;EAAtC,uCAAsC;CAAI;;AAC1E;EAAgC,8CAAyC;EAAzC,0CAAyC;CAAI;;AAE7E;EAA8B,+BAA0B;EAA1B,2BAA0B;CAAI;;AAC5D;EAA8B,iCAA4B;EAA5B,6BAA4B;CAAI;;AAC9D;EAA8B,uCAAkC;EAAlC,mCAAkC;CAAI;;AACpE;EAA8B,8BAAyB;EAAzB,0BAAyB;CAAI;;AAC3D;EAA8B,gCAAuB;EAAvB,wBAAuB;CAAI;;AACzD;EAA8B,gCAAuB;EAAvB,wBAAuB;CAAI;;AACzD;EAA8B,gCAAyB;EAAzB,0BAAyB;CAAI;;AAC3D;EAA8B,gCAAyB;EAAzB,0BAAyB;CAAI;;AAE3D;EAAoC,gCAAsC;EAAtC,uCAAsC;CAAI;;AAC9E;EAAoC,8BAAoC;EAApC,qCAAoC;CAAI;;AAC5E;EAAoC,iCAAkC;EAAlC,mCAAkC;CAAI;;AAC1E;EAAoC,kCAAyC;EAAzC,0CAAyC;CAAI;;AACjF;EAAoC,qCAAwC;EAAxC,yCAAwC;CAAI;;AAEhF;EAAiC,iCAAkC;EAAlC,mCAAkC;CAAI;;AACvE;EAAiC,+BAAgC;EAAhC,iCAAgC;CAAI;;AACrE;EAAiC,kCAA8B;EAA9B,+BAA8B;CAAI;;AACnE;EAAiC,oCAAgC;EAAhC,iCAAgC;CAAI;;AACrE;EAAiC,mCAA+B;EAA/B,gCAA+B;CAAI;;AAEpE;EAAkC,qCAAoC;EAApC,qCAAoC;CAAI;;AAC1E;EAAkC,mCAAkC;EAAlC,mCAAkC;CAAI;;AACxE;EAAkC,sCAAgC;EAAhC,iCAAgC;CAAI;;AACtE;EAAkC,uCAAuC;EAAvC,wCAAuC;CAAI;;AAC7E;EAAkC,0CAAsC;EAAtC,uCAAsC;CAAI;;AAC5E;EAAkC,uCAAiC;EAAjC,kCAAiC;CAAI;;AAEvE;EAAgC,qCAA2B;EAA3B,4BAA2B;CAAI;;AAC/D;EAAgC,sCAAiC;EAAjC,kCAAiC;CAAI;;AACrE;EAAgC,oCAA+B;EAA/B,gCAA+B;CAAI;;AACnE;EAAgC,uCAA6B;EAA7B,8BAA6B;CAAI;;AACjE;EAAgC,yCAA+B;EAA/B,gCAA+B;CAAI;;AACnE;EAAgC,wCAA8B;EAA9B,+BAA8B;CAAI;;A9CYlE;E8ClDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CxDitMrE;;AUrsMG;E8ClDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CxD0zMrE;;AU9yMG;E8ClDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CxDm6MrE;;AUv5MG;E8ClDA;IAAgC,mCAA8B;IAA9B,+BAA8B;GAAI;EAClE;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,2CAAsC;IAAtC,uCAAsC;GAAI;EAC1E;IAAgC,8CAAyC;IAAzC,0CAAyC;GAAI;EAE7E;IAA8B,+BAA0B;IAA1B,2BAA0B;GAAI;EAC5D;IAA8B,iCAA4B;IAA5B,6BAA4B;GAAI;EAC9D;IAA8B,uCAAkC;IAAlC,mCAAkC;GAAI;EACpE;IAA8B,8BAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAuB;IAAvB,wBAAuB;GAAI;EACzD;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAC3D;IAA8B,gCAAyB;IAAzB,0BAAyB;GAAI;EAE3D;IAAoC,gCAAsC;IAAtC,uCAAsC;GAAI;EAC9E;IAAoC,8BAAoC;IAApC,qCAAoC;GAAI;EAC5E;IAAoC,iCAAkC;IAAlC,mCAAkC;GAAI;EAC1E;IAAoC,kCAAyC;IAAzC,0CAAyC;GAAI;EACjF;IAAoC,qCAAwC;IAAxC,yCAAwC;GAAI;EAEhF;IAAiC,iCAAkC;IAAlC,mCAAkC;GAAI;EACvE;IAAiC,+BAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,kCAA8B;IAA9B,+BAA8B;GAAI;EACnE;IAAiC,oCAAgC;IAAhC,iCAAgC;GAAI;EACrE;IAAiC,mCAA+B;IAA/B,gCAA+B;GAAI;EAEpE;IAAkC,qCAAoC;IAApC,qCAAoC;GAAI;EAC1E;IAAkC,mCAAkC;IAAlC,mCAAkC;GAAI;EACxE;IAAkC,sCAAgC;IAAhC,iCAAgC;GAAI;EACtE;IAAkC,uCAAuC;IAAvC,wCAAuC;GAAI;EAC7E;IAAkC,0CAAsC;IAAtC,uCAAsC;GAAI;EAC5E;IAAkC,uCAAiC;IAAjC,kCAAiC;GAAI;EAEvE;IAAgC,qCAA2B;IAA3B,4BAA2B;GAAI;EAC/D;IAAgC,sCAAiC;IAAjC,kCAAiC;GAAI;EACrE;IAAgC,oCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,uCAA6B;IAA7B,8BAA6B;GAAI;EACjE;IAAgC,yCAA+B;IAA/B,gCAA+B;GAAI;EACnE;IAAgC,wCAA8B;IAA9B,+BAA8B;GAAI;CxD4gNrE;;AyDxjNG;ECDF,uBAAsB;CDC2B;;AAC/C;ECCF,wBAAuB;CDD2B;;AAChD;ECGF,uBAAsB;CDH2B;;A/CsD/C;E+CxDA;ICDF,uBAAsB;GDC2B;EAC/C;ICCF,wBAAuB;GDD2B;EAChD;ICGF,uBAAsB;GDH2B;CzD8kNlD;;AUxhNG;E+CxDA;ICDF,uBAAsB;GDC2B;EAC/C;ICCF,wBAAuB;GDD2B;EAChD;ICGF,uBAAsB;GDH2B;CzD0lNlD;;AUpiNG;E+CxDA;ICDF,uBAAsB;GDC2B;EAC/C;ICCF,wBAAuB;GDD2B;EAChD;ICGF,uBAAsB;GDH2B;CzDsmNlD;;AUhjNG;E+CxDA;ICDF,uBAAsB;GDC2B;EAC/C;ICCF,wBAAuB;GDD2B;EAChD;ICGF,uBAAsB;GDH2B;CzDknNlD;;A2D/mNC;EAAyB,4BAA8B;CAAI;;AAA3D;EAAyB,8BAA8B;CAAI;;AAA3D;EAAyB,8BAA8B;CAAI;;AAA3D;EAAyB,2BAA8B;CAAI;;AAA3D;EAAyB,oCAA8B;EAA9B,4BAA8B;CAAI;;AAK7D;EACE,gBAAe;EACf,OAAM;EACN,SAAQ;EACR,QAAO;EACP,c5DmlBsC;C4DllBvC;;AAED;EACE,gBAAe;EACf,SAAQ;EACR,UAAS;EACT,QAAO;EACP,c5D2kBsC;C4D1kBvC;;AAG6B;EAD9B;IAEI,yBAAgB;IAAhB,iBAAgB;IAChB,OAAM;IACN,c5DmkBoC;G4DjkBvC;C3DgoNA;;A4DhqND;ECEE,mBAAkB;EAClB,WAAU;EACV,YAAW;EACX,WAAU;EACV,iBAAgB;EAChB,uBAAsB;EACtB,oBAAmB;EACnB,UAAS;CDPV;;ACiBC;EAEE,iBAAgB;EAChB,YAAW;EACX,aAAY;EACZ,kBAAiB;EACjB,WAAU;EACV,oBAAmB;CACpB;;AC7BH;EAAa,+DAAqC;CAAI;;AACtD;EAAU,yDAAkC;CAAI;;AAChD;EAAa,wDAAqC;CAAI;;AACtD;EAAe,4BAA2B;CAAI;;ACC1C;EAAuB,sBAA4B;CAAI;;AAAvD;EAAuB,sBAA4B;CAAI;;AAAvD;EAAuB,sBAA4B;CAAI;;AAAvD;EAAuB,uBAA4B;CAAI;;AAAvD;EAAuB,uBAA4B;CAAI;;AAAvD;EAAuB,uBAA4B;CAAI;;AAAvD;EAAuB,uBAA4B;CAAI;;AAAvD;EAAuB,uBAA4B;CAAI;;AAAvD;EAAuB,wBAA4B;CAAI;;AAAvD;EAAuB,wBAA4B;CAAI;;AAI3D;EAAU,2BAA0B;CAAI;;AACxC;EAAU,4BAA2B;CAAI;;ACAjC;EAAgC,qBAA4B;CAAI;;AAChE;;EAEE,yBAAoC;CACrC;;AACD;;EAEE,2BAAwC;CACzC;;AACD;;EAEE,4BAA0C;CAC3C;;AACD;;EAEE,0BAAsC;CACvC;;AAhBD;EAAgC,2BAA4B;CAAI;;AAChE;;EAEE,+BAAoC;CACrC;;AACD;;EAEE,iCAAwC;CACzC;;AACD;;EAEE,kCAA0C;CAC3C;;AACD;;EAEE,gCAAsC;CACvC;;AAhBD;EAAgC,0BAA4B;CAAI;;AAChE;;EAEE,8BAAoC;CACrC;;AACD;;EAEE,gCAAwC;CACzC;;AACD;;EAEE,iCAA0C;CAC3C;;AACD;;EAEE,+BAAsC;CACvC;;AAhBD;EAAgC,wBAA4B;CAAI;;AAChE;;EAEE,4BAAoC;CACrC;;AACD;;EAEE,8BAAwC;CACzC;;AACD;;EAEE,+BAA0C;CAC3C;;AACD;;EAEE,6BAAsC;CACvC;;AAhBD;EAAgC,0BAA4B;CAAI;;AAChE;;EAEE,8BAAoC;CACrC;;AACD;;EAEE,gCAAwC;CACzC;;AACD;;EAEE,iCAA0C;CAC3C;;AACD;;EAEE,+BAAsC;CACvC;;AAhBD;EAAgC,wBAA4B;CAAI;;AAChE;;EAEE,4BAAoC;CACrC;;AACD;;EAEE,8BAAwC;CACzC;;AACD;;EAEE,+BAA0C;CAC3C;;AACD;;EAEE,6BAAsC;CACvC;;AAhBD;EAAgC,sBAA4B;CAAI;;AAChE;;EAEE,0BAAoC;CACrC;;AACD;;EAEE,4BAAwC;CACzC;;AACD;;EAEE,6BAA0C;CAC3C;;AACD;;EAEE,2BAAsC;CACvC;;AAhBD;EAAgC,4BAA4B;CAAI;;AAChE;;EAEE,gCAAoC;CACrC;;AACD;;EAEE,kCAAwC;CACzC;;AACD;;EAEE,mCAA0C;CAC3C;;AACD;;EAEE,iCAAsC;CACvC;;AAhBD;EAAgC,2BAA4B;CAAI;;AAChE;;EAEE,+BAAoC;CACrC;;AACD;;EAEE,iCAAwC;CACzC;;AACD;;EAEE,kCAA0C;CAC3C;;AACD;;EAEE,gCAAsC;CACvC;;AAhBD;EAAgC,yBAA4B;CAAI;;AAChE;;EAEE,6BAAoC;CACrC;;AACD;;EAEE,+BAAwC;CACzC;;AACD;;EAEE,gCAA0C;CAC3C;;AACD;;EAEE,8BAAsC;CACvC;;AAhBD;EAAgC,2BAA4B;CAAI;;AAChE;;EAEE,+BAAoC;CACrC;;AACD;;EAEE,iCAAwC;CACzC;;AACD;;EAEE,kCAA0C;CAC3C;;AACD;;EAEE,gCAAsC;CACvC;;AAhBD;EAAgC,yBAA4B;CAAI;;AAChE;;EAEE,6BAAoC;CACrC;;AACD;;EAEE,+BAAwC;CACzC;;AACD;;EAEE,gCAA0C;CAC3C;;AACD;;EAEE,8BAAsC;CACvC;;AAKL;EAAmB,wBAAuB;CAAI;;AAC9C;;EAEE,4BAA2B;CAC5B;;AACD;;EAEE,8BAA6B;CAC9B;;AACD;;EAEE,+BAA8B;CAC/B;;AACD;;EAEE,6BAA4B;CAC7B;;AtDYD;EsDjDI;IAAgC,qBAA4B;GAAI;EAChE;;IAEE,yBAAoC;GACrC;EACD;;IAEE,2BAAwC;GACzC;EACD;;IAEE,4BAA0C;GAC3C;EACD;;IAEE,0BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,sBAA4B;GAAI;EAChE;;IAEE,0BAAoC;GACrC;EACD;;IAEE,4BAAwC;GACzC;EACD;;IAEE,6BAA0C;GAC3C;EACD;;IAEE,2BAAsC;GACvC;EAhBD;IAAgC,4BAA4B;GAAI;EAChE;;IAEE,gCAAoC;GACrC;EACD;;IAEE,kCAAwC;GACzC;EACD;;IAEE,mCAA0C;GAC3C;EACD;;IAEE,iCAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAKL;IAAmB,wBAAuB;GAAI;EAC9C;;IAEE,4BAA2B;GAC5B;EACD;;IAEE,8BAA6B;GAC9B;EACD;;IAEE,+BAA8B;GAC/B;EACD;;IAEE,6BAA4B;GAC7B;ChE0vOJ;;AU9uOG;EsDjDI;IAAgC,qBAA4B;GAAI;EAChE;;IAEE,yBAAoC;GACrC;EACD;;IAEE,2BAAwC;GACzC;EACD;;IAEE,4BAA0C;GAC3C;EACD;;IAEE,0BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,sBAA4B;GAAI;EAChE;;IAEE,0BAAoC;GACrC;EACD;;IAEE,4BAAwC;GACzC;EACD;;IAEE,6BAA0C;GAC3C;EACD;;IAEE,2BAAsC;GACvC;EAhBD;IAAgC,4BAA4B;GAAI;EAChE;;IAEE,gCAAoC;GACrC;EACD;;IAEE,kCAAwC;GACzC;EACD;;IAEE,mCAA0C;GAC3C;EACD;;IAEE,iCAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAKL;IAAmB,wBAAuB;GAAI;EAC9C;;IAEE,4BAA2B;GAC5B;EACD;;IAEE,8BAA6B;GAC9B;EACD;;IAEE,+BAA8B;GAC/B;EACD;;IAEE,6BAA4B;GAC7B;ChEo/OJ;;AUx+OG;EsDjDI;IAAgC,qBAA4B;GAAI;EAChE;;IAEE,yBAAoC;GACrC;EACD;;IAEE,2BAAwC;GACzC;EACD;;IAEE,4BAA0C;GAC3C;EACD;;IAEE,0BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,sBAA4B;GAAI;EAChE;;IAEE,0BAAoC;GACrC;EACD;;IAEE,4BAAwC;GACzC;EACD;;IAEE,6BAA0C;GAC3C;EACD;;IAEE,2BAAsC;GACvC;EAhBD;IAAgC,4BAA4B;GAAI;EAChE;;IAEE,gCAAoC;GACrC;EACD;;IAEE,kCAAwC;GACzC;EACD;;IAEE,mCAA0C;GAC3C;EACD;;IAEE,iCAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAKL;IAAmB,wBAAuB;GAAI;EAC9C;;IAEE,4BAA2B;GAC5B;EACD;;IAEE,8BAA6B;GAC9B;EACD;;IAEE,+BAA8B;GAC/B;EACD;;IAEE,6BAA4B;GAC7B;ChE8uPJ;;AUluPG;EsDjDI;IAAgC,qBAA4B;GAAI;EAChE;;IAEE,yBAAoC;GACrC;EACD;;IAEE,2BAAwC;GACzC;EACD;;IAEE,4BAA0C;GAC3C;EACD;;IAEE,0BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,0BAA4B;GAAI;EAChE;;IAEE,8BAAoC;GACrC;EACD;;IAEE,gCAAwC;GACzC;EACD;;IAEE,iCAA0C;GAC3C;EACD;;IAEE,+BAAsC;GACvC;EAhBD;IAAgC,wBAA4B;GAAI;EAChE;;IAEE,4BAAoC;GACrC;EACD;;IAEE,8BAAwC;GACzC;EACD;;IAEE,+BAA0C;GAC3C;EACD;;IAEE,6BAAsC;GACvC;EAhBD;IAAgC,sBAA4B;GAAI;EAChE;;IAEE,0BAAoC;GACrC;EACD;;IAEE,4BAAwC;GACzC;EACD;;IAEE,6BAA0C;GAC3C;EACD;;IAEE,2BAAsC;GACvC;EAhBD;IAAgC,4BAA4B;GAAI;EAChE;;IAEE,gCAAoC;GACrC;EACD;;IAEE,kCAAwC;GACzC;EACD;;IAEE,mCAA0C;GAC3C;EACD;;IAEE,iCAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAhBD;IAAgC,2BAA4B;GAAI;EAChE;;IAEE,+BAAoC;GACrC;EACD;;IAEE,iCAAwC;GACzC;EACD;;IAEE,kCAA0C;GAC3C;EACD;;IAEE,gCAAsC;GACvC;EAhBD;IAAgC,yBAA4B;GAAI;EAChE;;IAEE,6BAAoC;GACrC;EACD;;IAEE,+BAAwC;GACzC;EACD;;IAEE,gCAA0C;GAC3C;EACD;;IAEE,8BAAsC;GACvC;EAKL;IAAmB,wBAAuB;GAAI;EAC9C;;IAEE,4BAA2B;GAC5B;EACD;;IAEE,8BAA6B;GAC9B;EACD;;IAEE,+BAA8B;GAC/B;EACD;;IAEE,6BAA4B;GAC7B;ChEw+PJ;;AiElhQD;EAAkB,kGlEqPgG;CkErPzD;;AAIzD;EAAiB,+BAA8B;CAAI;;AACnD;EAAiB,+BAA8B;CAAI;;AACnD;ECRE,iBAAgB;EAChB,wBAAuB;EACvB,oBAAmB;CDMsB;;AAQvC;EAAwB,4BAA2B;CAAI;;AACvD;EAAwB,6BAA4B;CAAI;;AACxD;EAAwB,8BAA6B;CAAI;;AvDsCzD;EuDxCA;IAAwB,4BAA2B;GAAI;EACvD;IAAwB,6BAA4B;GAAI;EACxD;IAAwB,8BAA6B;GAAI;CjE4iQ5D;;AUtgQG;EuDxCA;IAAwB,4BAA2B;GAAI;EACvD;IAAwB,6BAA4B;GAAI;EACxD;IAAwB,8BAA6B;GAAI;CjEwjQ5D;;AUlhQG;EuDxCA;IAAwB,4BAA2B;GAAI;EACvD;IAAwB,6BAA4B;GAAI;EACxD;IAAwB,8BAA6B;GAAI;CjEokQ5D;;AU9hQG;EuDxCA;IAAwB,4BAA2B;GAAI;EACvD;IAAwB,6BAA4B;GAAI;EACxD;IAAwB,8BAA6B;GAAI;CjEglQ5D;;AiE1kQD;EAAmB,qCAAoC;CAAI;;AAC3D;EAAmB,qCAAoC;CAAI;;AAC3D;EAAmB,sCAAqC;CAAI;;AAI5D;EAAsB,4BAA0C;CAAI;;AACpE;EAAsB,4BAA2C;CAAI;;AACrE;EAAsB,4BAAyC;CAAI;;AACnE;EAAsB,8BAA6B;CAAI;;AAIvD;EAAc,uBAAwB;CAAI;;AEpCxC;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AkEdD;EACE,0BAAwB;CACzB;;AlESD;EkENI,0BAAqC;ClESxC;;AgE4BH;EAAa,0BAA6B;CAAI;;AAC9C;EAAc,0BAA6B;CAAI;;AAE/C;EAAiB,qCAAkC;CAAI;;AACvD;EAAiB,2CAAkC;CAAI;;AAIvD;EGpDE,YAAW;EACX,mBAAkB;EAClB,kBAAiB;EACjB,8BAA6B;EAC7B,UAAS;CHkDV;;AIrDD;ECCE,+BAAkC;CDCnC;;AAED;ECHE,8BAAkC;CDKnC;;AECC;EzESF;;;IyEHM,6BAA4B;IAE5B,4BAA2B;GAC5B;EAED;IAEI,2BAA0B;GAC3B;EAQH;IACE,8BAA6B;GAC9B;EzE+ML;IyEjMM,iCAAgC;GACjC;EACD;;IAEE,0BxEtCY;IwEuCZ,yBAAwB;GACzB;EAOD;IACE,4BAA2B;GAC5B;EAED;;IAEE,yBAAwB;GACzB;EAED;;;IAGE,WAAU;IACV,UAAS;GACV;EAED;;IAEE,wBAAuB;GACxB;EAOD;IACE,SxE61BgC;GC01OnC;EFxtQH;IyEoCM,4BAA2C;GAC5C;E/DxFH;I+D0FI,4BAA2C;GAC5C;E1C/EL;I0CmFM,cAAa;GACd;ErChGL;IqCkGM,uBxEnFS;GwEoFV;E3DpGL;I2DuGM,qCAAoC;GAMrC;EAPD;;IAKI,kCAAmC;GACpC;E3DjEP;;I2DuEQ,qCAAsC;GACvC;E3DYP;I2DRM,eAAc;GAQf;EATD;;;;IAOI,sBxEpHU;GwEqHX;E3DjBP;I2DqBM,eAAc;IACd,sBxE1HY;GwE2Hb;CvE6qQJ","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n@import \"functions\";\n@import \"variables\";\n@import \"mixins\";\n@import \"root\";\n@import \"reboot\";\n@import \"type\";\n@import \"images\";\n@import \"code\";\n@import \"grid\";\n@import \"tables\";\n@import \"forms\";\n@import \"buttons\";\n@import \"transitions\";\n@import \"dropdown\";\n@import \"button-group\";\n@import \"input-group\";\n@import \"custom-forms\";\n@import \"nav\";\n@import \"navbar\";\n@import \"card\";\n@import \"breadcrumb\";\n@import \"pagination\";\n@import \"badge\";\n@import \"jumbotron\";\n@import \"alert\";\n@import \"progress\";\n@import \"media\";\n@import \"list-group\";\n@import \"close\";\n@import \"modal\";\n@import \"tooltip\";\n@import \"popover\";\n@import \"carousel\";\n@import \"utilities\";\n@import \"print\";\n",":root {\n // Custom variable values only support SassScript inside `#{}`.\n @each $color, $value in $colors {\n --#{$color}: #{$value};\n }\n\n @each $color, $value in $theme-colors {\n --#{$color}: #{$value};\n }\n\n @each $bp, $value in $grid-breakpoints {\n --breakpoint-#{$bp}: #{$value};\n }\n\n // Use `inspect` for lists so that quoted items keep the quotes.\n // See https://github.com/sass/sass/issues/2383#issuecomment-336349172\n --font-family-sans-serif: #{inspect($font-family-sans-serif)};\n --font-family-monospace: #{inspect($font-family-monospace)};\n}\n","// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix\n\n// Reboot\n//\n// Normalization of HTML elements, manually forked from Normalize.css to remove\n// styles targeting irrelevant browsers while applying new styles.\n//\n// Normalize is licensed MIT. https://github.com/necolas/normalize.css\n\n\n// Document\n//\n// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.\n// 2. Change the default font family in all browsers.\n// 3. Correct the line height in all browsers.\n// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.\n// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so\n// we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n// 6. Change the default tap highlight to be completely transparent in iOS.\n\n*,\n*::before,\n*::after {\n box-sizing: border-box; // 1\n}\n\nhtml {\n font-family: sans-serif; // 2\n line-height: 1.15; // 3\n -webkit-text-size-adjust: 100%; // 4\n -ms-text-size-adjust: 100%; // 4\n -ms-overflow-style: scrollbar; // 5\n -webkit-tap-highlight-color: rgba($black, 0); // 6\n}\n\n// IE10+ doesn't honor `` in some cases.\n@at-root {\n @-ms-viewport {\n width: device-width;\n }\n}\n\n// stylelint-disable selector-list-comma-newline-after\n// Shim for \"new\" HTML5 structural elements to display correctly (IE10, older browsers)\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Body\n//\n// 1. Remove the margin in all browsers.\n// 2. As a best practice, apply a default `background-color`.\n// 3. Set an explicit initial text-align value so that we can later use the\n// the `inherit` value on things like `` elements.\n\nbody {\n margin: 0; // 1\n font-family: $font-family-base;\n font-size: $font-size-base;\n font-weight: $font-weight-base;\n line-height: $line-height-base;\n color: $body-color;\n text-align: left; // 3\n background-color: $body-bg; // 2\n}\n\n// Suppress the focus outline on elements that cannot be accessed via keyboard.\n// This prevents an unwanted focus outline from appearing around elements that\n// might still respond to pointer events.\n//\n// Credit: https://github.com/suitcss/base\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\n\n// Content grouping\n//\n// 1. Add the correct box sizing in Firefox.\n// 2. Show the overflow in Edge and IE.\n\nhr {\n box-sizing: content-box; // 1\n height: 0; // 1\n overflow: visible; // 2\n}\n\n\n//\n// Typography\n//\n\n// Remove top margins from headings\n//\n// By default, `

`-`

` all receive top and bottom margins. We nuke the top\n// margin for easier control within type scales as it avoids margin collapsing.\n// stylelint-disable selector-list-comma-newline-after\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: $headings-margin-bottom;\n}\n// stylelint-enable selector-list-comma-newline-after\n\n// Reset margins on paragraphs\n//\n// Similarly, the top margin on `

`s get reset. However, we also reset the\n// bottom margin to use `rem` units instead of `em`.\np {\n margin-top: 0;\n margin-bottom: $paragraph-margin-bottom;\n}\n\n// Abbreviations\n//\n// 1. Remove the bottom border in Firefox 39-.\n// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.\n// 3. Add explicit cursor to indicate changed behavior.\n// 4. Duplicate behavior to the data-* attribute for our tooltip plugin\n\nabbr[title],\nabbr[data-original-title] { // 4\n text-decoration: underline; // 2\n text-decoration: underline dotted; // 2\n cursor: help; // 3\n border-bottom: 0; // 1\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: $dt-font-weight;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0; // Undo browser default\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic; // Add the correct font style in Android 4.3-\n}\n\n// stylelint-disable font-weight-notation\nb,\nstrong {\n font-weight: bolder; // Add the correct font weight in Chrome, Edge, and Safari\n}\n// stylelint-enable font-weight-notation\n\nsmall {\n font-size: 80%; // Add the correct font size in all browsers\n}\n\n//\n// Prevent `sub` and `sup` elements from affecting the line height in\n// all browsers.\n//\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub { bottom: -.25em; }\nsup { top: -.5em; }\n\n\n//\n// Links\n//\n\na {\n color: $link-color;\n text-decoration: $link-decoration;\n background-color: transparent; // Remove the gray background on active links in IE 10.\n -webkit-text-decoration-skip: objects; // Remove gaps in links underline in iOS 8+ and Safari 8+.\n\n @include hover {\n color: $link-hover-color;\n text-decoration: $link-hover-decoration;\n }\n}\n\n// And undo these styles for placeholder links/named anchors (without href)\n// which have not been made explicitly keyboard-focusable (without tabindex).\n// It would be more straightforward to just use a[href] in previous block, but that\n// causes specificity issues in many other styles that are too complex to fix.\n// See https://github.com/twbs/bootstrap/issues/19402\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n\n @include hover-focus {\n color: inherit;\n text-decoration: none;\n }\n\n &:focus {\n outline: 0;\n }\n}\n\n\n//\n// Code\n//\n\npre,\ncode,\nkbd,\nsamp {\n font-family: $font-family-monospace;\n font-size: 1em; // Correct the odd `em` font sizing in all browsers.\n}\n\npre {\n // Remove browser default top margin\n margin-top: 0;\n // Reset browser default of `1em` to use `rem`s\n margin-bottom: 1rem;\n // Don't allow content to break outside\n overflow: auto;\n // We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so\n // we force a non-overlapping, non-auto-hiding scrollbar to counteract.\n -ms-overflow-style: scrollbar;\n}\n\n\n//\n// Figures\n//\n\nfigure {\n // Apply a consistent margin strategy (matches our type styles).\n margin: 0 0 1rem;\n}\n\n\n//\n// Images and content\n//\n\nimg {\n vertical-align: middle;\n border-style: none; // Remove the border on images inside links in IE 10-.\n}\n\nsvg {\n // Workaround for the SVG overflow bug in IE10/11 is still required.\n // See https://github.com/twbs/bootstrap/issues/26878\n overflow: hidden;\n vertical-align: middle;\n}\n\n\n//\n// Tables\n//\n\ntable {\n border-collapse: collapse; // Prevent double borders\n}\n\ncaption {\n padding-top: $table-cell-padding;\n padding-bottom: $table-cell-padding;\n color: $table-caption-color;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n // Matches default `` alignment by inheriting from the ``, or the\n // closest parent with a set `text-align`.\n text-align: inherit;\n}\n\n\n//\n// Forms\n//\n\nlabel {\n // Allow labels to use `margin` for spacing.\n display: inline-block;\n margin-bottom: $label-margin-bottom;\n}\n\n// Remove the default `border-radius` that macOS Chrome adds.\n//\n// Details at https://github.com/twbs/bootstrap/issues/24093\nbutton {\n border-radius: 0;\n}\n\n// Work around a Firefox/IE bug where the transparent `button` background\n// results in a loss of the default `button` focus styles.\n//\n// Credit: https://github.com/suitcss/base/\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0; // Remove the margin in Firefox and Safari\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible; // Show the overflow in Edge\n}\n\nbutton,\nselect {\n text-transform: none; // Remove the inheritance of text transform in Firefox\n}\n\n// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`\n// controls in Android 4.\n// 2. Correct the inability to style clickable types in iOS and Safari.\nbutton,\nhtml [type=\"button\"], // 1\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button; // 2\n}\n\n// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box; // 1. Add the correct box sizing in IE 10-\n padding: 0; // 2. Remove the padding in IE 10-\n}\n\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n // Remove the default appearance of temporal inputs to avoid a Mobile Safari\n // bug where setting a custom line-height prevents text from being vertically\n // centered within the input.\n // See https://bugs.webkit.org/show_bug.cgi?id=139848\n // and https://github.com/twbs/bootstrap/issues/11266\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto; // Remove the default vertical scrollbar in IE.\n // Textareas should really only resize vertically so they don't break their (horizontal) containers.\n resize: vertical;\n}\n\nfieldset {\n // Browsers set a default `min-width: min-content;` on fieldsets,\n // unlike e.g. `

`s, which have `min-width: 0;` by default.\n // So we reset that to ensure fieldsets behave more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359\n // and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements\n min-width: 0;\n // Reset the default outline behavior of fieldsets so they don't affect page layout.\n padding: 0;\n margin: 0;\n border: 0;\n}\n\n// 1. Correct the text wrapping in Edge and IE.\n// 2. Correct the color inheritance from `fieldset` elements in IE.\nlegend {\n display: block;\n width: 100%;\n max-width: 100%; // 1\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit; // 2\n white-space: normal; // 1\n}\n\nprogress {\n vertical-align: baseline; // Add the correct vertical alignment in Chrome, Firefox, and Opera.\n}\n\n// Correct the cursor style of increment and decrement buttons in Chrome.\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n // This overrides the extra rounded corners on search inputs in iOS so that our\n // `.form-control` class can properly style them. Note that this cannot simply\n // be added to `.form-control` as it's not specific enough. For details, see\n // https://github.com/twbs/bootstrap/issues/11586.\n outline-offset: -2px; // 2. Correct the outline style in Safari.\n -webkit-appearance: none;\n}\n\n//\n// Remove the inner padding and cancel buttons in Chrome and Safari on macOS.\n//\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// 1. Correct the inability to style clickable types in iOS and Safari.\n// 2. Change font properties to `inherit` in Safari.\n//\n\n::-webkit-file-upload-button {\n font: inherit; // 2\n -webkit-appearance: button; // 1\n}\n\n//\n// Correct element displays\n//\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item; // Add the correct display in all browsers\n cursor: pointer;\n}\n\ntemplate {\n display: none; // Add the correct display in IE\n}\n\n// Always hide an element with the `hidden` HTML attribute (from PureCSS).\n// Needed for proper display in IE 10-.\n[hidden] {\n display: none !important;\n}\n","// Variables\n//\n// Variables should follow the `$component-state-property-size` formula for\n// consistent naming. Ex: $nav-link-disabled-color and $modal-content-box-shadow-xs.\n\n\n//\n// Color system\n//\n\n$white: #fff !default;\n$gray-100: #f8f9fa !default;\n$gray-200: #e9ecef !default;\n$gray-300: #dee2e6 !default;\n$gray-400: #ced4da !default;\n$gray-500: #adb5bd !default;\n$gray-600: #6c757d !default;\n$gray-700: #495057 !default;\n$gray-800: #343a40 !default;\n$gray-900: #212529 !default;\n$black: #000 !default;\n\n$grays: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$grays: map-merge(\n (\n \"100\": $gray-100,\n \"200\": $gray-200,\n \"300\": $gray-300,\n \"400\": $gray-400,\n \"500\": $gray-500,\n \"600\": $gray-600,\n \"700\": $gray-700,\n \"800\": $gray-800,\n \"900\": $gray-900\n ),\n $grays\n);\n\n\n$blue: #007bff !default;\n$indigo: #6610f2 !default;\n$purple: #6f42c1 !default;\n$pink: #e83e8c !default;\n$red: #dc3545 !default;\n$orange: #fd7e14 !default;\n$yellow: #ffc107 !default;\n$green: #28a745 !default;\n$teal: #20c997 !default;\n$cyan: #17a2b8 !default;\n\n$colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$colors: map-merge(\n (\n \"blue\": $blue,\n \"indigo\": $indigo,\n \"purple\": $purple,\n \"pink\": $pink,\n \"red\": $red,\n \"orange\": $orange,\n \"yellow\": $yellow,\n \"green\": $green,\n \"teal\": $teal,\n \"cyan\": $cyan,\n \"white\": $white,\n \"gray\": $gray-600,\n \"gray-dark\": $gray-800\n ),\n $colors\n);\n\n$primary: $blue !default;\n$secondary: $gray-600 !default;\n$success: $green !default;\n$info: $cyan !default;\n$warning: $yellow !default;\n$danger: $red !default;\n$light: $gray-100 !default;\n$dark: $gray-800 !default;\n\n$theme-colors: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$theme-colors: map-merge(\n (\n \"primary\": $primary,\n \"secondary\": $secondary,\n \"success\": $success,\n \"info\": $info,\n \"warning\": $warning,\n \"danger\": $danger,\n \"light\": $light,\n \"dark\": $dark\n ),\n $theme-colors\n);\n\n// Set a specific jump point for requesting color jumps\n$theme-color-interval: 8% !default;\n\n// The yiq lightness value that determines when the lightness of color changes from \"dark\" to \"light\". Acceptable values are between 0 and 255.\n$yiq-contrasted-threshold: 150 !default;\n\n// Customize the light and dark text colors for use in our YIQ color contrast function.\n$yiq-text-dark: $gray-900 !default;\n$yiq-text-light: $white !default;\n\n// Options\n//\n// Quickly modify global styling by enabling or disabling optional features.\n\n$enable-caret: true !default;\n$enable-rounded: true !default;\n$enable-shadows: false !default;\n$enable-gradients: false !default;\n$enable-transitions: true !default;\n$enable-hover-media-query: false !default; // Deprecated, no longer affects any compiled CSS\n$enable-grid-classes: true !default;\n$enable-print-styles: true !default;\n\n\n// Spacing\n//\n// Control the default styling of most Bootstrap elements by modifying these\n// variables. Mostly focused on spacing.\n// You can add more entries to the $spacers map, should you need more variation.\n\n$spacer: 1rem !default;\n$spacers: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$spacers: map-merge(\n (\n 0: 0,\n 1: ($spacer * .25),\n 2: ($spacer * .5),\n 3: $spacer,\n 4: ($spacer * 1.5),\n 5: ($spacer * 3)\n ),\n $spacers\n);\n\n// This variable affects the `.h-*` and `.w-*` classes.\n$sizes: () !default;\n// stylelint-disable-next-line scss/dollar-variable-default\n$sizes: map-merge(\n (\n 25: 25%,\n 50: 50%,\n 75: 75%,\n 100: 100%,\n auto: auto\n ),\n $sizes\n);\n\n// Body\n//\n// Settings for the `` element.\n\n$body-bg: $white !default;\n$body-color: $gray-900 !default;\n\n// Links\n//\n// Style anchor elements.\n\n$link-color: theme-color(\"primary\") !default;\n$link-decoration: none !default;\n$link-hover-color: darken($link-color, 15%) !default;\n$link-hover-decoration: underline !default;\n\n// Paragraphs\n//\n// Style p element.\n\n$paragraph-margin-bottom: 1rem !default;\n\n\n// Grid breakpoints\n//\n// Define the minimum dimensions at which your layout will change,\n// adapting to different screen sizes, for use in media queries.\n\n$grid-breakpoints: (\n xs: 0,\n sm: 576px,\n md: 768px,\n lg: 992px,\n xl: 1200px\n) !default;\n\n@include _assert-ascending($grid-breakpoints, \"$grid-breakpoints\");\n@include _assert-starts-at-zero($grid-breakpoints);\n\n\n// Grid containers\n//\n// Define the maximum width of `.container` for different screen sizes.\n\n$container-max-widths: (\n sm: 540px,\n md: 720px,\n lg: 960px,\n xl: 1140px\n) !default;\n\n@include _assert-ascending($container-max-widths, \"$container-max-widths\");\n\n\n// Grid columns\n//\n// Set the number of columns and specify the width of the gutters.\n\n$grid-columns: 12 !default;\n$grid-gutter-width: 30px !default;\n\n// Components\n//\n// Define common padding and border radius sizes and more.\n\n$line-height-lg: 1.5 !default;\n$line-height-sm: 1.5 !default;\n\n$border-width: 1px !default;\n$border-color: $gray-300 !default;\n\n$border-radius: .25rem !default;\n$border-radius-lg: .3rem !default;\n$border-radius-sm: .2rem !default;\n\n$box-shadow-sm: 0 .125rem .25rem rgba($black, .075) !default;\n$box-shadow: 0 .5rem 1rem rgba($black, .15) !default;\n$box-shadow-lg: 0 1rem 3rem rgba($black, .175) !default;\n\n$component-active-color: $white !default;\n$component-active-bg: theme-color(\"primary\") !default;\n\n$caret-width: .3em !default;\n\n$transition-base: all .2s ease-in-out !default;\n$transition-fade: opacity .15s linear !default;\n$transition-collapse: height .35s ease !default;\n\n\n// Fonts\n//\n// Font, line-height, and color for body text, headings, and more.\n\n// stylelint-disable value-keyword-case\n$font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\" !default;\n$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace !default;\n$font-family-base: $font-family-sans-serif !default;\n// stylelint-enable value-keyword-case\n\n$font-size-base: 1rem !default; // Assumes the browser default, typically `16px`\n$font-size-lg: ($font-size-base * 1.25) !default;\n$font-size-sm: ($font-size-base * .875) !default;\n\n$font-weight-light: 300 !default;\n$font-weight-normal: 400 !default;\n$font-weight-bold: 700 !default;\n\n$font-weight-base: $font-weight-normal !default;\n$line-height-base: 1.5 !default;\n\n$h1-font-size: $font-size-base * 2.5 !default;\n$h2-font-size: $font-size-base * 2 !default;\n$h3-font-size: $font-size-base * 1.75 !default;\n$h4-font-size: $font-size-base * 1.5 !default;\n$h5-font-size: $font-size-base * 1.25 !default;\n$h6-font-size: $font-size-base !default;\n\n$headings-margin-bottom: ($spacer / 2) !default;\n$headings-font-family: inherit !default;\n$headings-font-weight: 500 !default;\n$headings-line-height: 1.2 !default;\n$headings-color: inherit !default;\n\n$display1-size: 6rem !default;\n$display2-size: 5.5rem !default;\n$display3-size: 4.5rem !default;\n$display4-size: 3.5rem !default;\n\n$display1-weight: 300 !default;\n$display2-weight: 300 !default;\n$display3-weight: 300 !default;\n$display4-weight: 300 !default;\n$display-line-height: $headings-line-height !default;\n\n$lead-font-size: ($font-size-base * 1.25) !default;\n$lead-font-weight: 300 !default;\n\n$small-font-size: 80% !default;\n\n$text-muted: $gray-600 !default;\n\n$blockquote-small-color: $gray-600 !default;\n$blockquote-font-size: ($font-size-base * 1.25) !default;\n\n$hr-border-color: rgba($black, .1) !default;\n$hr-border-width: $border-width !default;\n\n$mark-padding: .2em !default;\n\n$dt-font-weight: $font-weight-bold !default;\n\n$kbd-box-shadow: inset 0 -.1rem 0 rgba($black, .25) !default;\n$nested-kbd-font-weight: $font-weight-bold !default;\n\n$list-inline-padding: .5rem !default;\n\n$mark-bg: #fcf8e3 !default;\n\n$hr-margin-y: $spacer !default;\n\n\n// Tables\n//\n// Customizes the `.table` component with basic values, each used across all table variations.\n\n$table-cell-padding: .75rem !default;\n$table-cell-padding-sm: .3rem !default;\n\n$table-bg: transparent !default;\n$table-accent-bg: rgba($black, .05) !default;\n$table-hover-bg: rgba($black, .075) !default;\n$table-active-bg: $table-hover-bg !default;\n\n$table-border-width: $border-width !default;\n$table-border-color: $gray-300 !default;\n\n$table-head-bg: $gray-200 !default;\n$table-head-color: $gray-700 !default;\n\n$table-dark-bg: $gray-900 !default;\n$table-dark-accent-bg: rgba($white, .05) !default;\n$table-dark-hover-bg: rgba($white, .075) !default;\n$table-dark-border-color: lighten($gray-900, 7.5%) !default;\n$table-dark-color: $body-bg !default;\n\n$table-striped-order: odd !default;\n\n$table-caption-color: $text-muted !default;\n\n// Buttons + Forms\n//\n// Shared variables that are reassigned to `$input-` and `$btn-` specific variables.\n\n$input-btn-padding-y: .375rem !default;\n$input-btn-padding-x: .75rem !default;\n$input-btn-line-height: $line-height-base !default;\n\n$input-btn-focus-width: .2rem !default;\n$input-btn-focus-color: rgba($component-active-bg, .25) !default;\n$input-btn-focus-box-shadow: 0 0 0 $input-btn-focus-width $input-btn-focus-color !default;\n\n$input-btn-padding-y-sm: .25rem !default;\n$input-btn-padding-x-sm: .5rem !default;\n$input-btn-line-height-sm: $line-height-sm !default;\n\n$input-btn-padding-y-lg: .5rem !default;\n$input-btn-padding-x-lg: 1rem !default;\n$input-btn-line-height-lg: $line-height-lg !default;\n\n$input-btn-border-width: $border-width !default;\n\n\n// Buttons\n//\n// For each of Bootstrap's buttons, define text, background, and border color.\n\n$btn-padding-y: $input-btn-padding-y !default;\n$btn-padding-x: $input-btn-padding-x !default;\n$btn-line-height: $input-btn-line-height !default;\n\n$btn-padding-y-sm: $input-btn-padding-y-sm !default;\n$btn-padding-x-sm: $input-btn-padding-x-sm !default;\n$btn-line-height-sm: $input-btn-line-height-sm !default;\n\n$btn-padding-y-lg: $input-btn-padding-y-lg !default;\n$btn-padding-x-lg: $input-btn-padding-x-lg !default;\n$btn-line-height-lg: $input-btn-line-height-lg !default;\n\n$btn-border-width: $input-btn-border-width !default;\n\n$btn-font-weight: $font-weight-normal !default;\n$btn-box-shadow: inset 0 1px 0 rgba($white, .15), 0 1px 1px rgba($black, .075) !default;\n$btn-focus-width: $input-btn-focus-width !default;\n$btn-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$btn-disabled-opacity: .65 !default;\n$btn-active-box-shadow: inset 0 3px 5px rgba($black, .125) !default;\n\n$btn-link-disabled-color: $gray-600 !default;\n\n$btn-block-spacing-y: .5rem !default;\n\n// Allows for customizing button radius independently from global border radius\n$btn-border-radius: $border-radius !default;\n$btn-border-radius-lg: $border-radius-lg !default;\n$btn-border-radius-sm: $border-radius-sm !default;\n\n$btn-transition: color .15s ease-in-out, background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n\n// Forms\n\n$label-margin-bottom: .5rem !default;\n\n$input-padding-y: $input-btn-padding-y !default;\n$input-padding-x: $input-btn-padding-x !default;\n$input-line-height: $input-btn-line-height !default;\n\n$input-padding-y-sm: $input-btn-padding-y-sm !default;\n$input-padding-x-sm: $input-btn-padding-x-sm !default;\n$input-line-height-sm: $input-btn-line-height-sm !default;\n\n$input-padding-y-lg: $input-btn-padding-y-lg !default;\n$input-padding-x-lg: $input-btn-padding-x-lg !default;\n$input-line-height-lg: $input-btn-line-height-lg !default;\n\n$input-bg: $white !default;\n$input-disabled-bg: $gray-200 !default;\n\n$input-color: $gray-700 !default;\n$input-border-color: $gray-400 !default;\n$input-border-width: $input-btn-border-width !default;\n$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;\n\n$input-border-radius: $border-radius !default;\n$input-border-radius-lg: $border-radius-lg !default;\n$input-border-radius-sm: $border-radius-sm !default;\n\n$input-focus-bg: $input-bg !default;\n$input-focus-border-color: lighten($component-active-bg, 25%) !default;\n$input-focus-color: $input-color !default;\n$input-focus-width: $input-btn-focus-width !default;\n$input-focus-box-shadow: $input-btn-focus-box-shadow !default;\n\n$input-placeholder-color: $gray-600 !default;\n$input-plaintext-color: $body-color !default;\n\n$input-height-border: $input-border-width * 2 !default;\n\n$input-height-inner: ($font-size-base * $input-btn-line-height) + ($input-btn-padding-y * 2) !default;\n$input-height: calc(#{$input-height-inner} + #{$input-height-border}) !default;\n\n$input-height-inner-sm: ($font-size-sm * $input-btn-line-height-sm) + ($input-btn-padding-y-sm * 2) !default;\n$input-height-sm: calc(#{$input-height-inner-sm} + #{$input-height-border}) !default;\n\n$input-height-inner-lg: ($font-size-lg * $input-btn-line-height-lg) + ($input-btn-padding-y-lg * 2) !default;\n$input-height-lg: calc(#{$input-height-inner-lg} + #{$input-height-border}) !default;\n\n$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$form-text-margin-top: .25rem !default;\n\n$form-check-input-gutter: 1.25rem !default;\n$form-check-input-margin-y: .3rem !default;\n$form-check-input-margin-x: .25rem !default;\n\n$form-check-inline-margin-x: .75rem !default;\n$form-check-inline-input-margin-x: .3125rem !default;\n\n$form-group-margin-bottom: 1rem !default;\n\n$input-group-addon-color: $input-color !default;\n$input-group-addon-bg: $gray-200 !default;\n$input-group-addon-border-color: $input-border-color !default;\n\n$custom-forms-transition: background-color .15s ease-in-out, border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;\n\n$custom-control-gutter: 1.5rem !default;\n$custom-control-spacer-x: 1rem !default;\n\n$custom-control-indicator-size: 1rem !default;\n$custom-control-indicator-bg: $gray-300 !default;\n$custom-control-indicator-bg-size: 50% 50% !default;\n$custom-control-indicator-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-control-indicator-disabled-bg: $gray-200 !default;\n$custom-control-label-disabled-color: $gray-600 !default;\n\n$custom-control-indicator-checked-color: $component-active-color !default;\n$custom-control-indicator-checked-bg: $component-active-bg !default;\n$custom-control-indicator-checked-disabled-bg: rgba(theme-color(\"primary\"), .5) !default;\n$custom-control-indicator-checked-box-shadow: none !default;\n\n$custom-control-indicator-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n\n$custom-control-indicator-active-color: $component-active-color !default;\n$custom-control-indicator-active-bg: lighten($component-active-bg, 35%) !default;\n$custom-control-indicator-active-box-shadow: none !default;\n\n$custom-checkbox-indicator-border-radius: $border-radius !default;\n$custom-checkbox-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#{$custom-control-indicator-checked-color}' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;\n$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;\n$custom-checkbox-indicator-icon-indeterminate: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#{$custom-checkbox-indicator-indeterminate-color}' d='M0 2h4'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-checkbox-indicator-indeterminate-box-shadow: none !default;\n\n$custom-radio-indicator-border-radius: 50% !default;\n$custom-radio-indicator-icon-checked: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#{$custom-control-indicator-checked-color}'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$custom-select-padding-y: .375rem !default;\n$custom-select-padding-x: .75rem !default;\n$custom-select-height: $input-height !default;\n$custom-select-indicator-padding: 1rem !default; // Extra padding to account for the presence of the background-image based indicator\n$custom-select-line-height: $input-btn-line-height !default;\n$custom-select-color: $input-color !default;\n$custom-select-disabled-color: $gray-600 !default;\n$custom-select-bg: $input-bg !default;\n$custom-select-disabled-bg: $gray-200 !default;\n$custom-select-bg-size: 8px 10px !default; // In pixels because image dimensions\n$custom-select-indicator-color: $gray-800 !default;\n$custom-select-indicator: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#{$custom-select-indicator-color}' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$custom-select-border-width: $input-btn-border-width !default;\n$custom-select-border-color: $input-border-color !default;\n$custom-select-border-radius: $border-radius !default;\n$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;\n\n$custom-select-focus-border-color: $input-focus-border-color !default;\n$custom-select-focus-width: $input-btn-focus-width !default;\n$custom-select-focus-box-shadow: 0 0 0 $custom-select-focus-width rgba($custom-select-focus-border-color, .5) !default;\n\n$custom-select-font-size-sm: 75% !default;\n$custom-select-height-sm: $input-height-sm !default;\n\n$custom-select-font-size-lg: 125% !default;\n$custom-select-height-lg: $input-height-lg !default;\n\n$custom-range-track-width: 100% !default;\n$custom-range-track-height: .5rem !default;\n$custom-range-track-cursor: pointer !default;\n$custom-range-track-bg: $gray-300 !default;\n$custom-range-track-border-radius: 1rem !default;\n$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;\n\n$custom-range-thumb-width: 1rem !default;\n$custom-range-thumb-height: $custom-range-thumb-width !default;\n$custom-range-thumb-bg: $component-active-bg !default;\n$custom-range-thumb-border: 0 !default;\n$custom-range-thumb-border-radius: 1rem !default;\n$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;\n$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-btn-focus-box-shadow !default;\n$custom-range-thumb-focus-box-shadow-width: $input-btn-focus-width !default; // For focus box shadow issue in IE/Edge\n$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;\n\n$custom-file-height: $input-height !default;\n$custom-file-height-inner: $input-height-inner !default;\n$custom-file-focus-border-color: $input-focus-border-color !default;\n$custom-file-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$custom-file-disabled-bg: $input-disabled-bg !default;\n\n$custom-file-padding-y: $input-btn-padding-y !default;\n$custom-file-padding-x: $input-btn-padding-x !default;\n$custom-file-line-height: $input-btn-line-height !default;\n$custom-file-color: $input-color !default;\n$custom-file-bg: $input-bg !default;\n$custom-file-border-width: $input-btn-border-width !default;\n$custom-file-border-color: $input-border-color !default;\n$custom-file-border-radius: $input-border-radius !default;\n$custom-file-box-shadow: $input-box-shadow !default;\n$custom-file-button-color: $custom-file-color !default;\n$custom-file-button-bg: $input-group-addon-bg !default;\n$custom-file-text: (\n en: \"Browse\"\n) !default;\n\n\n// Form validation\n$form-feedback-margin-top: $form-text-margin-top !default;\n$form-feedback-font-size: $small-font-size !default;\n$form-feedback-valid-color: theme-color(\"success\") !default;\n$form-feedback-invalid-color: theme-color(\"danger\") !default;\n\n\n// Dropdowns\n//\n// Dropdown menu container and contents.\n\n$dropdown-min-width: 10rem !default;\n$dropdown-padding-y: .5rem !default;\n$dropdown-spacer: .125rem !default;\n$dropdown-bg: $white !default;\n$dropdown-border-color: rgba($black, .15) !default;\n$dropdown-border-radius: $border-radius !default;\n$dropdown-border-width: $border-width !default;\n$dropdown-divider-bg: $gray-200 !default;\n$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;\n\n$dropdown-link-color: $gray-900 !default;\n$dropdown-link-hover-color: darken($gray-900, 5%) !default;\n$dropdown-link-hover-bg: $gray-100 !default;\n\n$dropdown-link-active-color: $component-active-color !default;\n$dropdown-link-active-bg: $component-active-bg !default;\n\n$dropdown-link-disabled-color: $gray-600 !default;\n\n$dropdown-item-padding-y: .25rem !default;\n$dropdown-item-padding-x: 1.5rem !default;\n\n$dropdown-header-color: $gray-600 !default;\n\n\n// Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n\n$zindex-dropdown: 1000 !default;\n$zindex-sticky: 1020 !default;\n$zindex-fixed: 1030 !default;\n$zindex-modal-backdrop: 1040 !default;\n$zindex-modal: 1050 !default;\n$zindex-popover: 1060 !default;\n$zindex-tooltip: 1070 !default;\n\n// Navs\n\n$nav-link-padding-y: .5rem !default;\n$nav-link-padding-x: 1rem !default;\n$nav-link-disabled-color: $gray-600 !default;\n\n$nav-tabs-border-color: $gray-300 !default;\n$nav-tabs-border-width: $border-width !default;\n$nav-tabs-border-radius: $border-radius !default;\n$nav-tabs-link-hover-border-color: $gray-200 $gray-200 $nav-tabs-border-color !default;\n$nav-tabs-link-active-color: $gray-700 !default;\n$nav-tabs-link-active-bg: $body-bg !default;\n$nav-tabs-link-active-border-color: $gray-300 $gray-300 $nav-tabs-link-active-bg !default;\n\n$nav-pills-border-radius: $border-radius !default;\n$nav-pills-link-active-color: $component-active-color !default;\n$nav-pills-link-active-bg: $component-active-bg !default;\n\n$nav-divider-color: $gray-200 !default;\n$nav-divider-margin-y: ($spacer / 2) !default;\n\n// Navbar\n\n$navbar-padding-y: ($spacer / 2) !default;\n$navbar-padding-x: $spacer !default;\n\n$navbar-nav-link-padding-x: .5rem !default;\n\n$navbar-brand-font-size: $font-size-lg !default;\n// Compute the navbar-brand padding-y so the navbar-brand will have the same height as navbar-text and nav-link\n$nav-link-height: ($font-size-base * $line-height-base + $nav-link-padding-y * 2) !default;\n$navbar-brand-height: $navbar-brand-font-size * $line-height-base !default;\n$navbar-brand-padding-y: ($nav-link-height - $navbar-brand-height) / 2 !default;\n\n$navbar-toggler-padding-y: .25rem !default;\n$navbar-toggler-padding-x: .75rem !default;\n$navbar-toggler-font-size: $font-size-lg !default;\n$navbar-toggler-border-radius: $btn-border-radius !default;\n\n$navbar-dark-color: rgba($white, .5) !default;\n$navbar-dark-hover-color: rgba($white, .75) !default;\n$navbar-dark-active-color: $white !default;\n$navbar-dark-disabled-color: rgba($white, .25) !default;\n$navbar-dark-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-dark-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-dark-toggler-border-color: rgba($white, .1) !default;\n\n$navbar-light-color: rgba($black, .5) !default;\n$navbar-light-hover-color: rgba($black, .7) !default;\n$navbar-light-active-color: rgba($black, .9) !default;\n$navbar-light-disabled-color: rgba($black, .3) !default;\n$navbar-light-toggler-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='#{$navbar-light-color}' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$navbar-light-toggler-border-color: rgba($black, .1) !default;\n\n// Pagination\n\n$pagination-padding-y: .5rem !default;\n$pagination-padding-x: .75rem !default;\n$pagination-padding-y-sm: .25rem !default;\n$pagination-padding-x-sm: .5rem !default;\n$pagination-padding-y-lg: .75rem !default;\n$pagination-padding-x-lg: 1.5rem !default;\n$pagination-line-height: 1.25 !default;\n\n$pagination-color: $link-color !default;\n$pagination-bg: $white !default;\n$pagination-border-width: $border-width !default;\n$pagination-border-color: $gray-300 !default;\n\n$pagination-focus-box-shadow: $input-btn-focus-box-shadow !default;\n$pagination-focus-outline: 0 !default;\n\n$pagination-hover-color: $link-hover-color !default;\n$pagination-hover-bg: $gray-200 !default;\n$pagination-hover-border-color: $gray-300 !default;\n\n$pagination-active-color: $component-active-color !default;\n$pagination-active-bg: $component-active-bg !default;\n$pagination-active-border-color: $pagination-active-bg !default;\n\n$pagination-disabled-color: $gray-600 !default;\n$pagination-disabled-bg: $white !default;\n$pagination-disabled-border-color: $gray-300 !default;\n\n\n// Jumbotron\n\n$jumbotron-padding: 2rem !default;\n$jumbotron-bg: $gray-200 !default;\n\n\n// Cards\n\n$card-spacer-y: .75rem !default;\n$card-spacer-x: 1.25rem !default;\n$card-border-width: $border-width !default;\n$card-border-radius: $border-radius !default;\n$card-border-color: rgba($black, .125) !default;\n$card-inner-border-radius: calc(#{$card-border-radius} - #{$card-border-width}) !default;\n$card-cap-bg: rgba($black, .03) !default;\n$card-bg: $white !default;\n\n$card-img-overlay-padding: 1.25rem !default;\n\n$card-group-margin: ($grid-gutter-width / 2) !default;\n$card-deck-margin: $card-group-margin !default;\n\n$card-columns-count: 3 !default;\n$card-columns-gap: 1.25rem !default;\n$card-columns-margin: $card-spacer-y !default;\n\n\n// Tooltips\n\n$tooltip-font-size: $font-size-sm !default;\n$tooltip-max-width: 200px !default;\n$tooltip-color: $white !default;\n$tooltip-bg: $black !default;\n$tooltip-border-radius: $border-radius !default;\n$tooltip-opacity: .9 !default;\n$tooltip-padding-y: .25rem !default;\n$tooltip-padding-x: .5rem !default;\n$tooltip-margin: 0 !default;\n\n$tooltip-arrow-width: .8rem !default;\n$tooltip-arrow-height: .4rem !default;\n$tooltip-arrow-color: $tooltip-bg !default;\n\n\n// Popovers\n\n$popover-font-size: $font-size-sm !default;\n$popover-bg: $white !default;\n$popover-max-width: 276px !default;\n$popover-border-width: $border-width !default;\n$popover-border-color: rgba($black, .2) !default;\n$popover-border-radius: $border-radius-lg !default;\n$popover-box-shadow: 0 .25rem .5rem rgba($black, .2) !default;\n\n$popover-header-bg: darken($popover-bg, 3%) !default;\n$popover-header-color: $headings-color !default;\n$popover-header-padding-y: .5rem !default;\n$popover-header-padding-x: .75rem !default;\n\n$popover-body-color: $body-color !default;\n$popover-body-padding-y: $popover-header-padding-y !default;\n$popover-body-padding-x: $popover-header-padding-x !default;\n\n$popover-arrow-width: 1rem !default;\n$popover-arrow-height: .5rem !default;\n$popover-arrow-color: $popover-bg !default;\n\n$popover-arrow-outer-color: fade-in($popover-border-color, .05) !default;\n\n\n// Badges\n\n$badge-font-size: 75% !default;\n$badge-font-weight: $font-weight-bold !default;\n$badge-padding-y: .25em !default;\n$badge-padding-x: .4em !default;\n$badge-border-radius: $border-radius !default;\n\n$badge-pill-padding-x: .6em !default;\n// Use a higher than normal value to ensure completely rounded edges when\n// customizing padding or font-size on labels.\n$badge-pill-border-radius: 10rem !default;\n\n\n// Modals\n\n// Padding applied to the modal body\n$modal-inner-padding: 1rem !default;\n\n$modal-dialog-margin: .5rem !default;\n$modal-dialog-margin-y-sm-up: 1.75rem !default;\n\n$modal-title-line-height: $line-height-base !default;\n\n$modal-content-bg: $white !default;\n$modal-content-border-color: rgba($black, .2) !default;\n$modal-content-border-width: $border-width !default;\n$modal-content-border-radius: $border-radius-lg !default;\n$modal-content-box-shadow-xs: 0 .25rem .5rem rgba($black, .5) !default;\n$modal-content-box-shadow-sm-up: 0 .5rem 1rem rgba($black, .5) !default;\n\n$modal-backdrop-bg: $black !default;\n$modal-backdrop-opacity: .5 !default;\n$modal-header-border-color: $gray-200 !default;\n$modal-footer-border-color: $modal-header-border-color !default;\n$modal-header-border-width: $modal-content-border-width !default;\n$modal-footer-border-width: $modal-header-border-width !default;\n$modal-header-padding: 1rem !default;\n\n$modal-lg: 800px !default;\n$modal-md: 500px !default;\n$modal-sm: 300px !default;\n\n$modal-transition: transform .3s ease-out !default;\n\n\n// Alerts\n//\n// Define alert colors, border radius, and padding.\n\n$alert-padding-y: .75rem !default;\n$alert-padding-x: 1.25rem !default;\n$alert-margin-bottom: 1rem !default;\n$alert-border-radius: $border-radius !default;\n$alert-link-font-weight: $font-weight-bold !default;\n$alert-border-width: $border-width !default;\n\n$alert-bg-level: -10 !default;\n$alert-border-level: -9 !default;\n$alert-color-level: 6 !default;\n\n\n// Progress bars\n\n$progress-height: 1rem !default;\n$progress-font-size: ($font-size-base * .75) !default;\n$progress-bg: $gray-200 !default;\n$progress-border-radius: $border-radius !default;\n$progress-box-shadow: inset 0 .1rem .1rem rgba($black, .1) !default;\n$progress-bar-color: $white !default;\n$progress-bar-bg: theme-color(\"primary\") !default;\n$progress-bar-animation-timing: 1s linear infinite !default;\n$progress-bar-transition: width .6s ease !default;\n\n// List group\n\n$list-group-bg: $white !default;\n$list-group-border-color: rgba($black, .125) !default;\n$list-group-border-width: $border-width !default;\n$list-group-border-radius: $border-radius !default;\n\n$list-group-item-padding-y: .75rem !default;\n$list-group-item-padding-x: 1.25rem !default;\n\n$list-group-hover-bg: $gray-100 !default;\n$list-group-active-color: $component-active-color !default;\n$list-group-active-bg: $component-active-bg !default;\n$list-group-active-border-color: $list-group-active-bg !default;\n\n$list-group-disabled-color: $gray-600 !default;\n$list-group-disabled-bg: $list-group-bg !default;\n\n$list-group-action-color: $gray-700 !default;\n$list-group-action-hover-color: $list-group-action-color !default;\n\n$list-group-action-active-color: $body-color !default;\n$list-group-action-active-bg: $gray-200 !default;\n\n\n// Image thumbnails\n\n$thumbnail-padding: .25rem !default;\n$thumbnail-bg: $body-bg !default;\n$thumbnail-border-width: $border-width !default;\n$thumbnail-border-color: $gray-300 !default;\n$thumbnail-border-radius: $border-radius !default;\n$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;\n\n\n// Figures\n\n$figure-caption-font-size: 90% !default;\n$figure-caption-color: $gray-600 !default;\n\n\n// Breadcrumbs\n\n$breadcrumb-padding-y: .75rem !default;\n$breadcrumb-padding-x: 1rem !default;\n$breadcrumb-item-padding: .5rem !default;\n\n$breadcrumb-margin-bottom: 1rem !default;\n\n$breadcrumb-bg: $gray-200 !default;\n$breadcrumb-divider-color: $gray-600 !default;\n$breadcrumb-active-color: $gray-600 !default;\n$breadcrumb-divider: quote(\"/\") !default;\n\n$breadcrumb-border-radius: $border-radius !default;\n\n\n// Carousel\n\n$carousel-control-color: $white !default;\n$carousel-control-width: 15% !default;\n$carousel-control-opacity: .5 !default;\n\n$carousel-indicator-width: 30px !default;\n$carousel-indicator-height: 3px !default;\n$carousel-indicator-spacer: 3px !default;\n$carousel-indicator-active-bg: $white !default;\n\n$carousel-caption-width: 70% !default;\n$carousel-caption-color: $white !default;\n\n$carousel-control-icon-width: 20px !default;\n\n$carousel-control-prev-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n$carousel-control-next-icon-bg: str-replace(url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#{$carousel-control-color}' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\"), \"#\", \"%23\") !default;\n\n$carousel-transition: transform .6s ease !default; // Define transform transition first if using multiple transitions (e.g., `transform 2s ease, opacity .5s ease-out`)\n\n\n// Close\n\n$close-font-size: $font-size-base * 1.5 !default;\n$close-font-weight: $font-weight-bold !default;\n$close-color: $black !default;\n$close-text-shadow: 0 1px 0 $white !default;\n\n// Code\n\n$code-font-size: 87.5% !default;\n$code-color: $pink !default;\n\n$kbd-padding-y: .2rem !default;\n$kbd-padding-x: .4rem !default;\n$kbd-font-size: $code-font-size !default;\n$kbd-color: $white !default;\n$kbd-bg: $gray-900 !default;\n\n$pre-color: $gray-900 !default;\n$pre-scrollable-max-height: 340px !default;\n\n\n// Printing\n$print-page-size: a3 !default;\n$print-body-min-width: map-get($grid-breakpoints, \"lg\") !default;\n","/*!\n * Bootstrap v4.1.3 (https://getbootstrap.com/)\n * Copyright 2011-2018 The Bootstrap Authors\n * Copyright 2011-2018 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n:root {\n --blue: #007bff;\n --indigo: #6610f2;\n --purple: #6f42c1;\n --pink: #e83e8c;\n --red: #dc3545;\n --orange: #fd7e14;\n --yellow: #ffc107;\n --green: #28a745;\n --teal: #20c997;\n --cyan: #17a2b8;\n --white: #fff;\n --gray: #6c757d;\n --gray-dark: #343a40;\n --primary: #007bff;\n --secondary: #6c757d;\n --success: #28a745;\n --info: #17a2b8;\n --warning: #ffc107;\n --danger: #dc3545;\n --light: #f8f9fa;\n --dark: #343a40;\n --breakpoint-xs: 0;\n --breakpoint-sm: 576px;\n --breakpoint-md: 768px;\n --breakpoint-lg: 992px;\n --breakpoint-xl: 1200px;\n --font-family-sans-serif: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nhtml {\n font-family: sans-serif;\n line-height: 1.15;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n -ms-overflow-style: scrollbar;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n@-ms-viewport {\n width: device-width;\n}\n\narticle, aside, figcaption, figure, footer, header, hgroup, main, nav, section {\n display: block;\n}\n\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #212529;\n text-align: left;\n background-color: #fff;\n}\n\n[tabindex=\"-1\"]:focus {\n outline: 0 !important;\n}\n\nhr {\n box-sizing: content-box;\n height: 0;\n overflow: visible;\n}\n\nh1, h2, h3, h4, h5, h6 {\n margin-top: 0;\n margin-bottom: 0.5rem;\n}\n\np {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nabbr[title],\nabbr[data-original-title] {\n text-decoration: underline;\n text-decoration: underline dotted;\n cursor: help;\n border-bottom: 0;\n}\n\naddress {\n margin-bottom: 1rem;\n font-style: normal;\n line-height: inherit;\n}\n\nol,\nul,\ndl {\n margin-top: 0;\n margin-bottom: 1rem;\n}\n\nol ol,\nul ul,\nol ul,\nul ol {\n margin-bottom: 0;\n}\n\ndt {\n font-weight: 700;\n}\n\ndd {\n margin-bottom: .5rem;\n margin-left: 0;\n}\n\nblockquote {\n margin: 0 0 1rem;\n}\n\ndfn {\n font-style: italic;\n}\n\nb,\nstrong {\n font-weight: bolder;\n}\n\nsmall {\n font-size: 80%;\n}\n\nsub,\nsup {\n position: relative;\n font-size: 75%;\n line-height: 0;\n vertical-align: baseline;\n}\n\nsub {\n bottom: -.25em;\n}\n\nsup {\n top: -.5em;\n}\n\na {\n color: #007bff;\n text-decoration: none;\n background-color: transparent;\n -webkit-text-decoration-skip: objects;\n}\n\na:hover {\n color: #0056b3;\n text-decoration: underline;\n}\n\na:not([href]):not([tabindex]) {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus {\n color: inherit;\n text-decoration: none;\n}\n\na:not([href]):not([tabindex]):focus {\n outline: 0;\n}\n\npre,\ncode,\nkbd,\nsamp {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n font-size: 1em;\n}\n\npre {\n margin-top: 0;\n margin-bottom: 1rem;\n overflow: auto;\n -ms-overflow-style: scrollbar;\n}\n\nfigure {\n margin: 0 0 1rem;\n}\n\nimg {\n vertical-align: middle;\n border-style: none;\n}\n\nsvg {\n overflow: hidden;\n vertical-align: middle;\n}\n\ntable {\n border-collapse: collapse;\n}\n\ncaption {\n padding-top: 0.75rem;\n padding-bottom: 0.75rem;\n color: #6c757d;\n text-align: left;\n caption-side: bottom;\n}\n\nth {\n text-align: inherit;\n}\n\nlabel {\n display: inline-block;\n margin-bottom: 0.5rem;\n}\n\nbutton {\n border-radius: 0;\n}\n\nbutton:focus {\n outline: 1px dotted;\n outline: 5px auto -webkit-focus-ring-color;\n}\n\ninput,\nbutton,\nselect,\noptgroup,\ntextarea {\n margin: 0;\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\nbutton,\ninput {\n overflow: visible;\n}\n\nbutton,\nselect {\n text-transform: none;\n}\n\nbutton,\nhtml [type=\"button\"],\n[type=\"reset\"],\n[type=\"submit\"] {\n -webkit-appearance: button;\n}\n\nbutton::-moz-focus-inner,\n[type=\"button\"]::-moz-focus-inner,\n[type=\"reset\"]::-moz-focus-inner,\n[type=\"submit\"]::-moz-focus-inner {\n padding: 0;\n border-style: none;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n box-sizing: border-box;\n padding: 0;\n}\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n -webkit-appearance: listbox;\n}\n\ntextarea {\n overflow: auto;\n resize: vertical;\n}\n\nfieldset {\n min-width: 0;\n padding: 0;\n margin: 0;\n border: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n max-width: 100%;\n padding: 0;\n margin-bottom: .5rem;\n font-size: 1.5rem;\n line-height: inherit;\n color: inherit;\n white-space: normal;\n}\n\nprogress {\n vertical-align: baseline;\n}\n\n[type=\"number\"]::-webkit-inner-spin-button,\n[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n[type=\"search\"] {\n outline-offset: -2px;\n -webkit-appearance: none;\n}\n\n[type=\"search\"]::-webkit-search-cancel-button,\n[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n::-webkit-file-upload-button {\n font: inherit;\n -webkit-appearance: button;\n}\n\noutput {\n display: inline-block;\n}\n\nsummary {\n display: list-item;\n cursor: pointer;\n}\n\ntemplate {\n display: none;\n}\n\n[hidden] {\n display: none !important;\n}\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n margin-bottom: 0.5rem;\n font-family: inherit;\n font-weight: 500;\n line-height: 1.2;\n color: inherit;\n}\n\nh1, .h1 {\n font-size: 2.5rem;\n}\n\nh2, .h2 {\n font-size: 2rem;\n}\n\nh3, .h3 {\n font-size: 1.75rem;\n}\n\nh4, .h4 {\n font-size: 1.5rem;\n}\n\nh5, .h5 {\n font-size: 1.25rem;\n}\n\nh6, .h6 {\n font-size: 1rem;\n}\n\n.lead {\n font-size: 1.25rem;\n font-weight: 300;\n}\n\n.display-1 {\n font-size: 6rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-2 {\n font-size: 5.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-3 {\n font-size: 4.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\n.display-4 {\n font-size: 3.5rem;\n font-weight: 300;\n line-height: 1.2;\n}\n\nhr {\n margin-top: 1rem;\n margin-bottom: 1rem;\n border: 0;\n border-top: 1px solid rgba(0, 0, 0, 0.1);\n}\n\nsmall,\n.small {\n font-size: 80%;\n font-weight: 400;\n}\n\nmark,\n.mark {\n padding: 0.2em;\n background-color: #fcf8e3;\n}\n\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n.list-inline {\n padding-left: 0;\n list-style: none;\n}\n\n.list-inline-item {\n display: inline-block;\n}\n\n.list-inline-item:not(:last-child) {\n margin-right: 0.5rem;\n}\n\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n.blockquote {\n margin-bottom: 1rem;\n font-size: 1.25rem;\n}\n\n.blockquote-footer {\n display: block;\n font-size: 80%;\n color: #6c757d;\n}\n\n.blockquote-footer::before {\n content: \"\\2014 \\00A0\";\n}\n\n.img-fluid {\n max-width: 100%;\n height: auto;\n}\n\n.img-thumbnail {\n padding: 0.25rem;\n background-color: #fff;\n border: 1px solid #dee2e6;\n border-radius: 0.25rem;\n max-width: 100%;\n height: auto;\n}\n\n.figure {\n display: inline-block;\n}\n\n.figure-img {\n margin-bottom: 0.5rem;\n line-height: 1;\n}\n\n.figure-caption {\n font-size: 90%;\n color: #6c757d;\n}\n\ncode {\n font-size: 87.5%;\n color: #e83e8c;\n word-break: break-word;\n}\n\na > code {\n color: inherit;\n}\n\nkbd {\n padding: 0.2rem 0.4rem;\n font-size: 87.5%;\n color: #fff;\n background-color: #212529;\n border-radius: 0.2rem;\n}\n\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: 700;\n}\n\npre {\n display: block;\n font-size: 87.5%;\n color: #212529;\n}\n\npre code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n}\n\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n\n.container {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n@media (min-width: 576px) {\n .container {\n max-width: 540px;\n }\n}\n\n@media (min-width: 768px) {\n .container {\n max-width: 720px;\n }\n}\n\n@media (min-width: 992px) {\n .container {\n max-width: 960px;\n }\n}\n\n@media (min-width: 1200px) {\n .container {\n max-width: 1140px;\n }\n}\n\n.container-fluid {\n width: 100%;\n padding-right: 15px;\n padding-left: 15px;\n margin-right: auto;\n margin-left: auto;\n}\n\n.row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -15px;\n margin-left: -15px;\n}\n\n.no-gutters {\n margin-right: 0;\n margin-left: 0;\n}\n\n.no-gutters > .col,\n.no-gutters > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n}\n\n.col-1, .col-2, .col-3, .col-4, .col-5, .col-6, .col-7, .col-8, .col-9, .col-10, .col-11, .col-12, .col,\n.col-auto, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-sm,\n.col-sm-auto, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-md,\n.col-md-auto, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12, .col-lg,\n.col-lg-auto, .col-xl-1, .col-xl-2, .col-xl-3, .col-xl-4, .col-xl-5, .col-xl-6, .col-xl-7, .col-xl-8, .col-xl-9, .col-xl-10, .col-xl-11, .col-xl-12, .col-xl,\n.col-xl-auto {\n position: relative;\n width: 100%;\n min-height: 1px;\n padding-right: 15px;\n padding-left: 15px;\n}\n\n.col {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n}\n\n.col-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n}\n\n.col-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n}\n\n.col-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n}\n\n.col-3 {\n flex: 0 0 25%;\n max-width: 25%;\n}\n\n.col-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n}\n\n.col-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n}\n\n.col-6 {\n flex: 0 0 50%;\n max-width: 50%;\n}\n\n.col-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n}\n\n.col-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n}\n\n.col-9 {\n flex: 0 0 75%;\n max-width: 75%;\n}\n\n.col-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n}\n\n.col-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n}\n\n.col-12 {\n flex: 0 0 100%;\n max-width: 100%;\n}\n\n.order-first {\n order: -1;\n}\n\n.order-last {\n order: 13;\n}\n\n.order-0 {\n order: 0;\n}\n\n.order-1 {\n order: 1;\n}\n\n.order-2 {\n order: 2;\n}\n\n.order-3 {\n order: 3;\n}\n\n.order-4 {\n order: 4;\n}\n\n.order-5 {\n order: 5;\n}\n\n.order-6 {\n order: 6;\n}\n\n.order-7 {\n order: 7;\n}\n\n.order-8 {\n order: 8;\n}\n\n.order-9 {\n order: 9;\n}\n\n.order-10 {\n order: 10;\n}\n\n.order-11 {\n order: 11;\n}\n\n.order-12 {\n order: 12;\n}\n\n.offset-1 {\n margin-left: 8.333333%;\n}\n\n.offset-2 {\n margin-left: 16.666667%;\n}\n\n.offset-3 {\n margin-left: 25%;\n}\n\n.offset-4 {\n margin-left: 33.333333%;\n}\n\n.offset-5 {\n margin-left: 41.666667%;\n}\n\n.offset-6 {\n margin-left: 50%;\n}\n\n.offset-7 {\n margin-left: 58.333333%;\n}\n\n.offset-8 {\n margin-left: 66.666667%;\n}\n\n.offset-9 {\n margin-left: 75%;\n}\n\n.offset-10 {\n margin-left: 83.333333%;\n}\n\n.offset-11 {\n margin-left: 91.666667%;\n}\n\n@media (min-width: 576px) {\n .col-sm {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-sm-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-sm-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-sm-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-sm-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-sm-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-sm-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-sm-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-sm-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-sm-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-sm-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-sm-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-sm-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-sm-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-sm-first {\n order: -1;\n }\n .order-sm-last {\n order: 13;\n }\n .order-sm-0 {\n order: 0;\n }\n .order-sm-1 {\n order: 1;\n }\n .order-sm-2 {\n order: 2;\n }\n .order-sm-3 {\n order: 3;\n }\n .order-sm-4 {\n order: 4;\n }\n .order-sm-5 {\n order: 5;\n }\n .order-sm-6 {\n order: 6;\n }\n .order-sm-7 {\n order: 7;\n }\n .order-sm-8 {\n order: 8;\n }\n .order-sm-9 {\n order: 9;\n }\n .order-sm-10 {\n order: 10;\n }\n .order-sm-11 {\n order: 11;\n }\n .order-sm-12 {\n order: 12;\n }\n .offset-sm-0 {\n margin-left: 0;\n }\n .offset-sm-1 {\n margin-left: 8.333333%;\n }\n .offset-sm-2 {\n margin-left: 16.666667%;\n }\n .offset-sm-3 {\n margin-left: 25%;\n }\n .offset-sm-4 {\n margin-left: 33.333333%;\n }\n .offset-sm-5 {\n margin-left: 41.666667%;\n }\n .offset-sm-6 {\n margin-left: 50%;\n }\n .offset-sm-7 {\n margin-left: 58.333333%;\n }\n .offset-sm-8 {\n margin-left: 66.666667%;\n }\n .offset-sm-9 {\n margin-left: 75%;\n }\n .offset-sm-10 {\n margin-left: 83.333333%;\n }\n .offset-sm-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 768px) {\n .col-md {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-md-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-md-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-md-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-md-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-md-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-md-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-md-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-md-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-md-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-md-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-md-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-md-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-md-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-md-first {\n order: -1;\n }\n .order-md-last {\n order: 13;\n }\n .order-md-0 {\n order: 0;\n }\n .order-md-1 {\n order: 1;\n }\n .order-md-2 {\n order: 2;\n }\n .order-md-3 {\n order: 3;\n }\n .order-md-4 {\n order: 4;\n }\n .order-md-5 {\n order: 5;\n }\n .order-md-6 {\n order: 6;\n }\n .order-md-7 {\n order: 7;\n }\n .order-md-8 {\n order: 8;\n }\n .order-md-9 {\n order: 9;\n }\n .order-md-10 {\n order: 10;\n }\n .order-md-11 {\n order: 11;\n }\n .order-md-12 {\n order: 12;\n }\n .offset-md-0 {\n margin-left: 0;\n }\n .offset-md-1 {\n margin-left: 8.333333%;\n }\n .offset-md-2 {\n margin-left: 16.666667%;\n }\n .offset-md-3 {\n margin-left: 25%;\n }\n .offset-md-4 {\n margin-left: 33.333333%;\n }\n .offset-md-5 {\n margin-left: 41.666667%;\n }\n .offset-md-6 {\n margin-left: 50%;\n }\n .offset-md-7 {\n margin-left: 58.333333%;\n }\n .offset-md-8 {\n margin-left: 66.666667%;\n }\n .offset-md-9 {\n margin-left: 75%;\n }\n .offset-md-10 {\n margin-left: 83.333333%;\n }\n .offset-md-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 992px) {\n .col-lg {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-lg-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-lg-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-lg-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-lg-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-lg-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-lg-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-lg-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-lg-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-lg-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-lg-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-lg-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-lg-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-lg-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-lg-first {\n order: -1;\n }\n .order-lg-last {\n order: 13;\n }\n .order-lg-0 {\n order: 0;\n }\n .order-lg-1 {\n order: 1;\n }\n .order-lg-2 {\n order: 2;\n }\n .order-lg-3 {\n order: 3;\n }\n .order-lg-4 {\n order: 4;\n }\n .order-lg-5 {\n order: 5;\n }\n .order-lg-6 {\n order: 6;\n }\n .order-lg-7 {\n order: 7;\n }\n .order-lg-8 {\n order: 8;\n }\n .order-lg-9 {\n order: 9;\n }\n .order-lg-10 {\n order: 10;\n }\n .order-lg-11 {\n order: 11;\n }\n .order-lg-12 {\n order: 12;\n }\n .offset-lg-0 {\n margin-left: 0;\n }\n .offset-lg-1 {\n margin-left: 8.333333%;\n }\n .offset-lg-2 {\n margin-left: 16.666667%;\n }\n .offset-lg-3 {\n margin-left: 25%;\n }\n .offset-lg-4 {\n margin-left: 33.333333%;\n }\n .offset-lg-5 {\n margin-left: 41.666667%;\n }\n .offset-lg-6 {\n margin-left: 50%;\n }\n .offset-lg-7 {\n margin-left: 58.333333%;\n }\n .offset-lg-8 {\n margin-left: 66.666667%;\n }\n .offset-lg-9 {\n margin-left: 75%;\n }\n .offset-lg-10 {\n margin-left: 83.333333%;\n }\n .offset-lg-11 {\n margin-left: 91.666667%;\n }\n}\n\n@media (min-width: 1200px) {\n .col-xl {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col-xl-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none;\n }\n .col-xl-1 {\n flex: 0 0 8.333333%;\n max-width: 8.333333%;\n }\n .col-xl-2 {\n flex: 0 0 16.666667%;\n max-width: 16.666667%;\n }\n .col-xl-3 {\n flex: 0 0 25%;\n max-width: 25%;\n }\n .col-xl-4 {\n flex: 0 0 33.333333%;\n max-width: 33.333333%;\n }\n .col-xl-5 {\n flex: 0 0 41.666667%;\n max-width: 41.666667%;\n }\n .col-xl-6 {\n flex: 0 0 50%;\n max-width: 50%;\n }\n .col-xl-7 {\n flex: 0 0 58.333333%;\n max-width: 58.333333%;\n }\n .col-xl-8 {\n flex: 0 0 66.666667%;\n max-width: 66.666667%;\n }\n .col-xl-9 {\n flex: 0 0 75%;\n max-width: 75%;\n }\n .col-xl-10 {\n flex: 0 0 83.333333%;\n max-width: 83.333333%;\n }\n .col-xl-11 {\n flex: 0 0 91.666667%;\n max-width: 91.666667%;\n }\n .col-xl-12 {\n flex: 0 0 100%;\n max-width: 100%;\n }\n .order-xl-first {\n order: -1;\n }\n .order-xl-last {\n order: 13;\n }\n .order-xl-0 {\n order: 0;\n }\n .order-xl-1 {\n order: 1;\n }\n .order-xl-2 {\n order: 2;\n }\n .order-xl-3 {\n order: 3;\n }\n .order-xl-4 {\n order: 4;\n }\n .order-xl-5 {\n order: 5;\n }\n .order-xl-6 {\n order: 6;\n }\n .order-xl-7 {\n order: 7;\n }\n .order-xl-8 {\n order: 8;\n }\n .order-xl-9 {\n order: 9;\n }\n .order-xl-10 {\n order: 10;\n }\n .order-xl-11 {\n order: 11;\n }\n .order-xl-12 {\n order: 12;\n }\n .offset-xl-0 {\n margin-left: 0;\n }\n .offset-xl-1 {\n margin-left: 8.333333%;\n }\n .offset-xl-2 {\n margin-left: 16.666667%;\n }\n .offset-xl-3 {\n margin-left: 25%;\n }\n .offset-xl-4 {\n margin-left: 33.333333%;\n }\n .offset-xl-5 {\n margin-left: 41.666667%;\n }\n .offset-xl-6 {\n margin-left: 50%;\n }\n .offset-xl-7 {\n margin-left: 58.333333%;\n }\n .offset-xl-8 {\n margin-left: 66.666667%;\n }\n .offset-xl-9 {\n margin-left: 75%;\n }\n .offset-xl-10 {\n margin-left: 83.333333%;\n }\n .offset-xl-11 {\n margin-left: 91.666667%;\n }\n}\n\n.table {\n width: 100%;\n margin-bottom: 1rem;\n background-color: transparent;\n}\n\n.table th,\n.table td {\n padding: 0.75rem;\n vertical-align: top;\n border-top: 1px solid #dee2e6;\n}\n\n.table thead th {\n vertical-align: bottom;\n border-bottom: 2px solid #dee2e6;\n}\n\n.table tbody + tbody {\n border-top: 2px solid #dee2e6;\n}\n\n.table .table {\n background-color: #fff;\n}\n\n.table-sm th,\n.table-sm td {\n padding: 0.3rem;\n}\n\n.table-bordered {\n border: 1px solid #dee2e6;\n}\n\n.table-bordered th,\n.table-bordered td {\n border: 1px solid #dee2e6;\n}\n\n.table-bordered thead th,\n.table-bordered thead td {\n border-bottom-width: 2px;\n}\n\n.table-borderless th,\n.table-borderless td,\n.table-borderless thead th,\n.table-borderless tbody + tbody {\n border: 0;\n}\n\n.table-striped tbody tr:nth-of-type(odd) {\n background-color: rgba(0, 0, 0, 0.05);\n}\n\n.table-hover tbody tr:hover {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-primary,\n.table-primary > th,\n.table-primary > td {\n background-color: #b8daff;\n}\n\n.table-hover .table-primary:hover {\n background-color: #9fcdff;\n}\n\n.table-hover .table-primary:hover > td,\n.table-hover .table-primary:hover > th {\n background-color: #9fcdff;\n}\n\n.table-secondary,\n.table-secondary > th,\n.table-secondary > td {\n background-color: #d6d8db;\n}\n\n.table-hover .table-secondary:hover {\n background-color: #c8cbcf;\n}\n\n.table-hover .table-secondary:hover > td,\n.table-hover .table-secondary:hover > th {\n background-color: #c8cbcf;\n}\n\n.table-success,\n.table-success > th,\n.table-success > td {\n background-color: #c3e6cb;\n}\n\n.table-hover .table-success:hover {\n background-color: #b1dfbb;\n}\n\n.table-hover .table-success:hover > td,\n.table-hover .table-success:hover > th {\n background-color: #b1dfbb;\n}\n\n.table-info,\n.table-info > th,\n.table-info > td {\n background-color: #bee5eb;\n}\n\n.table-hover .table-info:hover {\n background-color: #abdde5;\n}\n\n.table-hover .table-info:hover > td,\n.table-hover .table-info:hover > th {\n background-color: #abdde5;\n}\n\n.table-warning,\n.table-warning > th,\n.table-warning > td {\n background-color: #ffeeba;\n}\n\n.table-hover .table-warning:hover {\n background-color: #ffe8a1;\n}\n\n.table-hover .table-warning:hover > td,\n.table-hover .table-warning:hover > th {\n background-color: #ffe8a1;\n}\n\n.table-danger,\n.table-danger > th,\n.table-danger > td {\n background-color: #f5c6cb;\n}\n\n.table-hover .table-danger:hover {\n background-color: #f1b0b7;\n}\n\n.table-hover .table-danger:hover > td,\n.table-hover .table-danger:hover > th {\n background-color: #f1b0b7;\n}\n\n.table-light,\n.table-light > th,\n.table-light > td {\n background-color: #fdfdfe;\n}\n\n.table-hover .table-light:hover {\n background-color: #ececf6;\n}\n\n.table-hover .table-light:hover > td,\n.table-hover .table-light:hover > th {\n background-color: #ececf6;\n}\n\n.table-dark,\n.table-dark > th,\n.table-dark > td {\n background-color: #c6c8ca;\n}\n\n.table-hover .table-dark:hover {\n background-color: #b9bbbe;\n}\n\n.table-hover .table-dark:hover > td,\n.table-hover .table-dark:hover > th {\n background-color: #b9bbbe;\n}\n\n.table-active,\n.table-active > th,\n.table-active > td {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table-hover .table-active:hover > td,\n.table-hover .table-active:hover > th {\n background-color: rgba(0, 0, 0, 0.075);\n}\n\n.table .thead-dark th {\n color: #fff;\n background-color: #212529;\n border-color: #32383e;\n}\n\n.table .thead-light th {\n color: #495057;\n background-color: #e9ecef;\n border-color: #dee2e6;\n}\n\n.table-dark {\n color: #fff;\n background-color: #212529;\n}\n\n.table-dark th,\n.table-dark td,\n.table-dark thead th {\n border-color: #32383e;\n}\n\n.table-dark.table-bordered {\n border: 0;\n}\n\n.table-dark.table-striped tbody tr:nth-of-type(odd) {\n background-color: rgba(255, 255, 255, 0.05);\n}\n\n.table-dark.table-hover tbody tr:hover {\n background-color: rgba(255, 255, 255, 0.075);\n}\n\n@media (max-width: 575.98px) {\n .table-responsive-sm {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n }\n .table-responsive-sm > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 767.98px) {\n .table-responsive-md {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n }\n .table-responsive-md > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 991.98px) {\n .table-responsive-lg {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n }\n .table-responsive-lg > .table-bordered {\n border: 0;\n }\n}\n\n@media (max-width: 1199.98px) {\n .table-responsive-xl {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n }\n .table-responsive-xl > .table-bordered {\n border: 0;\n }\n}\n\n.table-responsive {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n}\n\n.table-responsive > .table-bordered {\n border: 0;\n}\n\n.form-control {\n display: block;\n width: 100%;\n height: calc(2.25rem + 2px);\n padding: 0.375rem 0.75rem;\n font-size: 1rem;\n line-height: 1.5;\n color: #495057;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .form-control {\n transition: none;\n }\n}\n\n.form-control::-ms-expand {\n background-color: transparent;\n border: 0;\n}\n\n.form-control:focus {\n color: #495057;\n background-color: #fff;\n border-color: #80bdff;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.form-control::placeholder {\n color: #6c757d;\n opacity: 1;\n}\n\n.form-control:disabled, .form-control[readonly] {\n background-color: #e9ecef;\n opacity: 1;\n}\n\nselect.form-control:focus::-ms-value {\n color: #495057;\n background-color: #fff;\n}\n\n.form-control-file,\n.form-control-range {\n display: block;\n width: 100%;\n}\n\n.col-form-label {\n padding-top: calc(0.375rem + 1px);\n padding-bottom: calc(0.375rem + 1px);\n margin-bottom: 0;\n font-size: inherit;\n line-height: 1.5;\n}\n\n.col-form-label-lg {\n padding-top: calc(0.5rem + 1px);\n padding-bottom: calc(0.5rem + 1px);\n font-size: 1.25rem;\n line-height: 1.5;\n}\n\n.col-form-label-sm {\n padding-top: calc(0.25rem + 1px);\n padding-bottom: calc(0.25rem + 1px);\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n.form-control-plaintext {\n display: block;\n width: 100%;\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n margin-bottom: 0;\n line-height: 1.5;\n color: #212529;\n background-color: transparent;\n border: solid transparent;\n border-width: 1px 0;\n}\n\n.form-control-plaintext.form-control-sm, .form-control-plaintext.form-control-lg {\n padding-right: 0;\n padding-left: 0;\n}\n\n.form-control-sm {\n height: calc(1.8125rem + 2px);\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.form-control-lg {\n height: calc(2.875rem + 2px);\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\nselect.form-control[size], select.form-control[multiple] {\n height: auto;\n}\n\ntextarea.form-control {\n height: auto;\n}\n\n.form-group {\n margin-bottom: 1rem;\n}\n\n.form-text {\n display: block;\n margin-top: 0.25rem;\n}\n\n.form-row {\n display: flex;\n flex-wrap: wrap;\n margin-right: -5px;\n margin-left: -5px;\n}\n\n.form-row > .col,\n.form-row > [class*=\"col-\"] {\n padding-right: 5px;\n padding-left: 5px;\n}\n\n.form-check {\n position: relative;\n display: block;\n padding-left: 1.25rem;\n}\n\n.form-check-input {\n position: absolute;\n margin-top: 0.3rem;\n margin-left: -1.25rem;\n}\n\n.form-check-input:disabled ~ .form-check-label {\n color: #6c757d;\n}\n\n.form-check-label {\n margin-bottom: 0;\n}\n\n.form-check-inline {\n display: inline-flex;\n align-items: center;\n padding-left: 0;\n margin-right: 0.75rem;\n}\n\n.form-check-inline .form-check-input {\n position: static;\n margin-top: 0;\n margin-right: 0.3125rem;\n margin-left: 0;\n}\n\n.valid-feedback {\n display: none;\n width: 100%;\n margin-top: 0.25rem;\n font-size: 80%;\n color: #28a745;\n}\n\n.valid-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%;\n padding: 0.25rem 0.5rem;\n margin-top: .1rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: #fff;\n background-color: rgba(40, 167, 69, 0.9);\n border-radius: 0.25rem;\n}\n\n.was-validated .form-control:valid, .form-control.is-valid, .was-validated\n.custom-select:valid,\n.custom-select.is-valid {\n border-color: #28a745;\n}\n\n.was-validated .form-control:valid:focus, .form-control.is-valid:focus, .was-validated\n.custom-select:valid:focus,\n.custom-select.is-valid:focus {\n border-color: #28a745;\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .form-control:valid ~ .valid-feedback,\n.was-validated .form-control:valid ~ .valid-tooltip, .form-control.is-valid ~ .valid-feedback,\n.form-control.is-valid ~ .valid-tooltip, .was-validated\n.custom-select:valid ~ .valid-feedback,\n.was-validated\n.custom-select:valid ~ .valid-tooltip,\n.custom-select.is-valid ~ .valid-feedback,\n.custom-select.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .form-control-file:valid ~ .valid-feedback,\n.was-validated .form-control-file:valid ~ .valid-tooltip, .form-control-file.is-valid ~ .valid-feedback,\n.form-control-file.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .form-check-input:valid ~ .form-check-label, .form-check-input.is-valid ~ .form-check-label {\n color: #28a745;\n}\n\n.was-validated .form-check-input:valid ~ .valid-feedback,\n.was-validated .form-check-input:valid ~ .valid-tooltip, .form-check-input.is-valid ~ .valid-feedback,\n.form-check-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-label, .custom-control-input.is-valid ~ .custom-control-label {\n color: #28a745;\n}\n\n.was-validated .custom-control-input:valid ~ .custom-control-label::before, .custom-control-input.is-valid ~ .custom-control-label::before {\n background-color: #71dd8a;\n}\n\n.was-validated .custom-control-input:valid ~ .valid-feedback,\n.was-validated .custom-control-input:valid ~ .valid-tooltip, .custom-control-input.is-valid ~ .valid-feedback,\n.custom-control-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:valid:checked ~ .custom-control-label::before, .custom-control-input.is-valid:checked ~ .custom-control-label::before {\n background-color: #34ce57;\n}\n\n.was-validated .custom-control-input:valid:focus ~ .custom-control-label::before, .custom-control-input.is-valid:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.was-validated .custom-file-input:valid ~ .custom-file-label, .custom-file-input.is-valid ~ .custom-file-label {\n border-color: #28a745;\n}\n\n.was-validated .custom-file-input:valid ~ .custom-file-label::after, .custom-file-input.is-valid ~ .custom-file-label::after {\n border-color: inherit;\n}\n\n.was-validated .custom-file-input:valid ~ .valid-feedback,\n.was-validated .custom-file-input:valid ~ .valid-tooltip, .custom-file-input.is-valid ~ .valid-feedback,\n.custom-file-input.is-valid ~ .valid-tooltip {\n display: block;\n}\n\n.was-validated .custom-file-input:valid:focus ~ .custom-file-label, .custom-file-input.is-valid:focus ~ .custom-file-label {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.25);\n}\n\n.invalid-feedback {\n display: none;\n width: 100%;\n margin-top: 0.25rem;\n font-size: 80%;\n color: #dc3545;\n}\n\n.invalid-tooltip {\n position: absolute;\n top: 100%;\n z-index: 5;\n display: none;\n max-width: 100%;\n padding: 0.25rem 0.5rem;\n margin-top: .1rem;\n font-size: 0.875rem;\n line-height: 1.5;\n color: #fff;\n background-color: rgba(220, 53, 69, 0.9);\n border-radius: 0.25rem;\n}\n\n.was-validated .form-control:invalid, .form-control.is-invalid, .was-validated\n.custom-select:invalid,\n.custom-select.is-invalid {\n border-color: #dc3545;\n}\n\n.was-validated .form-control:invalid:focus, .form-control.is-invalid:focus, .was-validated\n.custom-select:invalid:focus,\n.custom-select.is-invalid:focus {\n border-color: #dc3545;\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .form-control:invalid ~ .invalid-feedback,\n.was-validated .form-control:invalid ~ .invalid-tooltip, .form-control.is-invalid ~ .invalid-feedback,\n.form-control.is-invalid ~ .invalid-tooltip, .was-validated\n.custom-select:invalid ~ .invalid-feedback,\n.was-validated\n.custom-select:invalid ~ .invalid-tooltip,\n.custom-select.is-invalid ~ .invalid-feedback,\n.custom-select.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .form-control-file:invalid ~ .invalid-feedback,\n.was-validated .form-control-file:invalid ~ .invalid-tooltip, .form-control-file.is-invalid ~ .invalid-feedback,\n.form-control-file.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .form-check-input:invalid ~ .form-check-label, .form-check-input.is-invalid ~ .form-check-label {\n color: #dc3545;\n}\n\n.was-validated .form-check-input:invalid ~ .invalid-feedback,\n.was-validated .form-check-input:invalid ~ .invalid-tooltip, .form-check-input.is-invalid ~ .invalid-feedback,\n.form-check-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label, .custom-control-input.is-invalid ~ .custom-control-label {\n color: #dc3545;\n}\n\n.was-validated .custom-control-input:invalid ~ .custom-control-label::before, .custom-control-input.is-invalid ~ .custom-control-label::before {\n background-color: #efa2a9;\n}\n\n.was-validated .custom-control-input:invalid ~ .invalid-feedback,\n.was-validated .custom-control-input:invalid ~ .invalid-tooltip, .custom-control-input.is-invalid ~ .invalid-feedback,\n.custom-control-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-control-input:invalid:checked ~ .custom-control-label::before, .custom-control-input.is-invalid:checked ~ .custom-control-label::before {\n background-color: #e4606d;\n}\n\n.was-validated .custom-control-input:invalid:focus ~ .custom-control-label::before, .custom-control-input.is-invalid:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.was-validated .custom-file-input:invalid ~ .custom-file-label, .custom-file-input.is-invalid ~ .custom-file-label {\n border-color: #dc3545;\n}\n\n.was-validated .custom-file-input:invalid ~ .custom-file-label::after, .custom-file-input.is-invalid ~ .custom-file-label::after {\n border-color: inherit;\n}\n\n.was-validated .custom-file-input:invalid ~ .invalid-feedback,\n.was-validated .custom-file-input:invalid ~ .invalid-tooltip, .custom-file-input.is-invalid ~ .invalid-feedback,\n.custom-file-input.is-invalid ~ .invalid-tooltip {\n display: block;\n}\n\n.was-validated .custom-file-input:invalid:focus ~ .custom-file-label, .custom-file-input.is-invalid:focus ~ .custom-file-label {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);\n}\n\n.form-inline {\n display: flex;\n flex-flow: row wrap;\n align-items: center;\n}\n\n.form-inline .form-check {\n width: 100%;\n}\n\n@media (min-width: 576px) {\n .form-inline label {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-bottom: 0;\n }\n .form-inline .form-group {\n display: flex;\n flex: 0 0 auto;\n flex-flow: row wrap;\n align-items: center;\n margin-bottom: 0;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-plaintext {\n display: inline-block;\n }\n .form-inline .input-group,\n .form-inline .custom-select {\n width: auto;\n }\n .form-inline .form-check {\n display: flex;\n align-items: center;\n justify-content: center;\n width: auto;\n padding-left: 0;\n }\n .form-inline .form-check-input {\n position: relative;\n margin-top: 0;\n margin-right: 0.25rem;\n margin-left: 0;\n }\n .form-inline .custom-control {\n align-items: center;\n justify-content: center;\n }\n .form-inline .custom-control-label {\n margin-bottom: 0;\n }\n}\n\n.btn {\n display: inline-block;\n font-weight: 400;\n text-align: center;\n white-space: nowrap;\n vertical-align: middle;\n user-select: none;\n border: 1px solid transparent;\n padding: 0.375rem 0.75rem;\n font-size: 1rem;\n line-height: 1.5;\n border-radius: 0.25rem;\n transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .btn {\n transition: none;\n }\n}\n\n.btn:hover, .btn:focus {\n text-decoration: none;\n}\n\n.btn:focus, .btn.focus {\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.btn.disabled, .btn:disabled {\n opacity: 0.65;\n}\n\n.btn:not(:disabled):not(.disabled) {\n cursor: pointer;\n}\n\na.btn.disabled,\nfieldset:disabled a.btn {\n pointer-events: none;\n}\n\n.btn-primary {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-primary:hover {\n color: #fff;\n background-color: #0069d9;\n border-color: #0062cc;\n}\n\n.btn-primary:focus, .btn-primary.focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-primary.disabled, .btn-primary:disabled {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-primary:not(:disabled):not(.disabled):active, .btn-primary:not(:disabled):not(.disabled).active,\n.show > .btn-primary.dropdown-toggle {\n color: #fff;\n background-color: #0062cc;\n border-color: #005cbf;\n}\n\n.btn-primary:not(:disabled):not(.disabled):active:focus, .btn-primary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-primary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-secondary {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-secondary:hover {\n color: #fff;\n background-color: #5a6268;\n border-color: #545b62;\n}\n\n.btn-secondary:focus, .btn-secondary.focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-secondary.disabled, .btn-secondary:disabled {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-secondary:not(:disabled):not(.disabled):active, .btn-secondary:not(:disabled):not(.disabled).active,\n.show > .btn-secondary.dropdown-toggle {\n color: #fff;\n background-color: #545b62;\n border-color: #4e555b;\n}\n\n.btn-secondary:not(:disabled):not(.disabled):active:focus, .btn-secondary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-secondary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-success {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-success:hover {\n color: #fff;\n background-color: #218838;\n border-color: #1e7e34;\n}\n\n.btn-success:focus, .btn-success.focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-success.disabled, .btn-success:disabled {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-success:not(:disabled):not(.disabled):active, .btn-success:not(:disabled):not(.disabled).active,\n.show > .btn-success.dropdown-toggle {\n color: #fff;\n background-color: #1e7e34;\n border-color: #1c7430;\n}\n\n.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled).active:focus,\n.show > .btn-success.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-info {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-info:hover {\n color: #fff;\n background-color: #138496;\n border-color: #117a8b;\n}\n\n.btn-info:focus, .btn-info.focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-info.disabled, .btn-info:disabled {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-info:not(:disabled):not(.disabled):active, .btn-info:not(:disabled):not(.disabled).active,\n.show > .btn-info.dropdown-toggle {\n color: #fff;\n background-color: #117a8b;\n border-color: #10707f;\n}\n\n.btn-info:not(:disabled):not(.disabled):active:focus, .btn-info:not(:disabled):not(.disabled).active:focus,\n.show > .btn-info.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-warning {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-warning:hover {\n color: #212529;\n background-color: #e0a800;\n border-color: #d39e00;\n}\n\n.btn-warning:focus, .btn-warning.focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-warning.disabled, .btn-warning:disabled {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-warning:not(:disabled):not(.disabled):active, .btn-warning:not(:disabled):not(.disabled).active,\n.show > .btn-warning.dropdown-toggle {\n color: #212529;\n background-color: #d39e00;\n border-color: #c69500;\n}\n\n.btn-warning:not(:disabled):not(.disabled):active:focus, .btn-warning:not(:disabled):not(.disabled).active:focus,\n.show > .btn-warning.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-danger {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-danger:hover {\n color: #fff;\n background-color: #c82333;\n border-color: #bd2130;\n}\n\n.btn-danger:focus, .btn-danger.focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-danger.disabled, .btn-danger:disabled {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-danger:not(:disabled):not(.disabled):active, .btn-danger:not(:disabled):not(.disabled).active,\n.show > .btn-danger.dropdown-toggle {\n color: #fff;\n background-color: #bd2130;\n border-color: #b21f2d;\n}\n\n.btn-danger:not(:disabled):not(.disabled):active:focus, .btn-danger:not(:disabled):not(.disabled).active:focus,\n.show > .btn-danger.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-light {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-light:hover {\n color: #212529;\n background-color: #e2e6ea;\n border-color: #dae0e5;\n}\n\n.btn-light:focus, .btn-light.focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-light.disabled, .btn-light:disabled {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-light:not(:disabled):not(.disabled):active, .btn-light:not(:disabled):not(.disabled).active,\n.show > .btn-light.dropdown-toggle {\n color: #212529;\n background-color: #dae0e5;\n border-color: #d3d9df;\n}\n\n.btn-light:not(:disabled):not(.disabled):active:focus, .btn-light:not(:disabled):not(.disabled).active:focus,\n.show > .btn-light.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-dark {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-dark:hover {\n color: #fff;\n background-color: #23272b;\n border-color: #1d2124;\n}\n\n.btn-dark:focus, .btn-dark.focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-dark.disabled, .btn-dark:disabled {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-dark:not(:disabled):not(.disabled):active, .btn-dark:not(:disabled):not(.disabled).active,\n.show > .btn-dark.dropdown-toggle {\n color: #fff;\n background-color: #1d2124;\n border-color: #171a1d;\n}\n\n.btn-dark:not(:disabled):not(.disabled):active:focus, .btn-dark:not(:disabled):not(.disabled).active:focus,\n.show > .btn-dark.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-outline-primary {\n color: #007bff;\n background-color: transparent;\n background-image: none;\n border-color: #007bff;\n}\n\n.btn-outline-primary:hover {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-outline-primary:focus, .btn-outline-primary.focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-primary.disabled, .btn-outline-primary:disabled {\n color: #007bff;\n background-color: transparent;\n}\n\n.btn-outline-primary:not(:disabled):not(.disabled):active, .btn-outline-primary:not(:disabled):not(.disabled).active,\n.show > .btn-outline-primary.dropdown-toggle {\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.btn-outline-primary:not(:disabled):not(.disabled):active:focus, .btn-outline-primary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-primary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.5);\n}\n\n.btn-outline-secondary {\n color: #6c757d;\n background-color: transparent;\n background-image: none;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:hover {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:focus, .btn-outline-secondary.focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-outline-secondary.disabled, .btn-outline-secondary:disabled {\n color: #6c757d;\n background-color: transparent;\n}\n\n.btn-outline-secondary:not(:disabled):not(.disabled):active, .btn-outline-secondary:not(:disabled):not(.disabled).active,\n.show > .btn-outline-secondary.dropdown-toggle {\n color: #fff;\n background-color: #6c757d;\n border-color: #6c757d;\n}\n\n.btn-outline-secondary:not(:disabled):not(.disabled):active:focus, .btn-outline-secondary:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-secondary.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(108, 117, 125, 0.5);\n}\n\n.btn-outline-success {\n color: #28a745;\n background-color: transparent;\n background-image: none;\n border-color: #28a745;\n}\n\n.btn-outline-success:hover {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-outline-success:focus, .btn-outline-success.focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-success.disabled, .btn-outline-success:disabled {\n color: #28a745;\n background-color: transparent;\n}\n\n.btn-outline-success:not(:disabled):not(.disabled):active, .btn-outline-success:not(:disabled):not(.disabled).active,\n.show > .btn-outline-success.dropdown-toggle {\n color: #fff;\n background-color: #28a745;\n border-color: #28a745;\n}\n\n.btn-outline-success:not(:disabled):not(.disabled):active:focus, .btn-outline-success:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-success.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(40, 167, 69, 0.5);\n}\n\n.btn-outline-info {\n color: #17a2b8;\n background-color: transparent;\n background-image: none;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:hover {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:focus, .btn-outline-info.focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-info.disabled, .btn-outline-info:disabled {\n color: #17a2b8;\n background-color: transparent;\n}\n\n.btn-outline-info:not(:disabled):not(.disabled):active, .btn-outline-info:not(:disabled):not(.disabled).active,\n.show > .btn-outline-info.dropdown-toggle {\n color: #fff;\n background-color: #17a2b8;\n border-color: #17a2b8;\n}\n\n.btn-outline-info:not(:disabled):not(.disabled):active:focus, .btn-outline-info:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-info.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(23, 162, 184, 0.5);\n}\n\n.btn-outline-warning {\n color: #ffc107;\n background-color: transparent;\n background-image: none;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:hover {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:focus, .btn-outline-warning.focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-warning.disabled, .btn-outline-warning:disabled {\n color: #ffc107;\n background-color: transparent;\n}\n\n.btn-outline-warning:not(:disabled):not(.disabled):active, .btn-outline-warning:not(:disabled):not(.disabled).active,\n.show > .btn-outline-warning.dropdown-toggle {\n color: #212529;\n background-color: #ffc107;\n border-color: #ffc107;\n}\n\n.btn-outline-warning:not(:disabled):not(.disabled):active:focus, .btn-outline-warning:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-warning.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(255, 193, 7, 0.5);\n}\n\n.btn-outline-danger {\n color: #dc3545;\n background-color: transparent;\n background-image: none;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:hover {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:focus, .btn-outline-danger.focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-danger.disabled, .btn-outline-danger:disabled {\n color: #dc3545;\n background-color: transparent;\n}\n\n.btn-outline-danger:not(:disabled):not(.disabled):active, .btn-outline-danger:not(:disabled):not(.disabled).active,\n.show > .btn-outline-danger.dropdown-toggle {\n color: #fff;\n background-color: #dc3545;\n border-color: #dc3545;\n}\n\n.btn-outline-danger:not(:disabled):not(.disabled):active:focus, .btn-outline-danger:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-danger.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.5);\n}\n\n.btn-outline-light {\n color: #f8f9fa;\n background-color: transparent;\n background-image: none;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:hover {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:focus, .btn-outline-light.focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-light.disabled, .btn-outline-light:disabled {\n color: #f8f9fa;\n background-color: transparent;\n}\n\n.btn-outline-light:not(:disabled):not(.disabled):active, .btn-outline-light:not(:disabled):not(.disabled).active,\n.show > .btn-outline-light.dropdown-toggle {\n color: #212529;\n background-color: #f8f9fa;\n border-color: #f8f9fa;\n}\n\n.btn-outline-light:not(:disabled):not(.disabled):active:focus, .btn-outline-light:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-light.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(248, 249, 250, 0.5);\n}\n\n.btn-outline-dark {\n color: #343a40;\n background-color: transparent;\n background-image: none;\n border-color: #343a40;\n}\n\n.btn-outline-dark:hover {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-outline-dark:focus, .btn-outline-dark.focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-outline-dark.disabled, .btn-outline-dark:disabled {\n color: #343a40;\n background-color: transparent;\n}\n\n.btn-outline-dark:not(:disabled):not(.disabled):active, .btn-outline-dark:not(:disabled):not(.disabled).active,\n.show > .btn-outline-dark.dropdown-toggle {\n color: #fff;\n background-color: #343a40;\n border-color: #343a40;\n}\n\n.btn-outline-dark:not(:disabled):not(.disabled):active:focus, .btn-outline-dark:not(:disabled):not(.disabled).active:focus,\n.show > .btn-outline-dark.dropdown-toggle:focus {\n box-shadow: 0 0 0 0.2rem rgba(52, 58, 64, 0.5);\n}\n\n.btn-link {\n font-weight: 400;\n color: #007bff;\n background-color: transparent;\n}\n\n.btn-link:hover {\n color: #0056b3;\n text-decoration: underline;\n background-color: transparent;\n border-color: transparent;\n}\n\n.btn-link:focus, .btn-link.focus {\n text-decoration: underline;\n border-color: transparent;\n box-shadow: none;\n}\n\n.btn-link:disabled, .btn-link.disabled {\n color: #6c757d;\n pointer-events: none;\n}\n\n.btn-lg, .btn-group-lg > .btn {\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\n.btn-sm, .btn-group-sm > .btn {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n.btn-block + .btn-block {\n margin-top: 0.5rem;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n\n.fade {\n transition: opacity 0.15s linear;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .fade {\n transition: none;\n }\n}\n\n.fade:not(.show) {\n opacity: 0;\n}\n\n.collapse:not(.show) {\n display: none;\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n transition: height 0.35s ease;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .collapsing {\n transition: none;\n }\n}\n\n.dropup,\n.dropright,\n.dropdown,\n.dropleft {\n position: relative;\n}\n\n.dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid;\n border-right: 0.3em solid transparent;\n border-bottom: 0;\n border-left: 0.3em solid transparent;\n}\n\n.dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 10rem;\n padding: 0.5rem 0;\n margin: 0.125rem 0 0;\n font-size: 1rem;\n color: #212529;\n text-align: left;\n list-style: none;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 0.25rem;\n}\n\n.dropdown-menu-right {\n right: 0;\n left: auto;\n}\n\n.dropup .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-top: 0;\n margin-bottom: 0.125rem;\n}\n\n.dropup .dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0;\n border-right: 0.3em solid transparent;\n border-bottom: 0.3em solid;\n border-left: 0.3em solid transparent;\n}\n\n.dropup .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropright .dropdown-menu {\n top: 0;\n right: auto;\n left: 100%;\n margin-top: 0;\n margin-left: 0.125rem;\n}\n\n.dropright .dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid transparent;\n border-right: 0;\n border-bottom: 0.3em solid transparent;\n border-left: 0.3em solid;\n}\n\n.dropright .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropright .dropdown-toggle::after {\n vertical-align: 0;\n}\n\n.dropleft .dropdown-menu {\n top: 0;\n right: 100%;\n left: auto;\n margin-top: 0;\n margin-right: 0.125rem;\n}\n\n.dropleft .dropdown-toggle::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n}\n\n.dropleft .dropdown-toggle::after {\n display: none;\n}\n\n.dropleft .dropdown-toggle::before {\n display: inline-block;\n width: 0;\n height: 0;\n margin-right: 0.255em;\n vertical-align: 0.255em;\n content: \"\";\n border-top: 0.3em solid transparent;\n border-right: 0.3em solid;\n border-bottom: 0.3em solid transparent;\n}\n\n.dropleft .dropdown-toggle:empty::after {\n margin-left: 0;\n}\n\n.dropleft .dropdown-toggle::before {\n vertical-align: 0;\n}\n\n.dropdown-menu[x-placement^=\"top\"], .dropdown-menu[x-placement^=\"right\"], .dropdown-menu[x-placement^=\"bottom\"], .dropdown-menu[x-placement^=\"left\"] {\n right: auto;\n bottom: auto;\n}\n\n.dropdown-divider {\n height: 0;\n margin: 0.5rem 0;\n overflow: hidden;\n border-top: 1px solid #e9ecef;\n}\n\n.dropdown-item {\n display: block;\n width: 100%;\n padding: 0.25rem 1.5rem;\n clear: both;\n font-weight: 400;\n color: #212529;\n text-align: inherit;\n white-space: nowrap;\n background-color: transparent;\n border: 0;\n}\n\n.dropdown-item:hover, .dropdown-item:focus {\n color: #16181b;\n text-decoration: none;\n background-color: #f8f9fa;\n}\n\n.dropdown-item.active, .dropdown-item:active {\n color: #fff;\n text-decoration: none;\n background-color: #007bff;\n}\n\n.dropdown-item.disabled, .dropdown-item:disabled {\n color: #6c757d;\n background-color: transparent;\n}\n\n.dropdown-menu.show {\n display: block;\n}\n\n.dropdown-header {\n display: block;\n padding: 0.5rem 1.5rem;\n margin-bottom: 0;\n font-size: 0.875rem;\n color: #6c757d;\n white-space: nowrap;\n}\n\n.dropdown-item-text {\n display: block;\n padding: 0.25rem 1.5rem;\n color: #212529;\n}\n\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-flex;\n vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n flex: 0 1 auto;\n}\n\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover {\n z-index: 1;\n}\n\n.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,\n.btn-group-vertical > .btn:focus,\n.btn-group-vertical > .btn:active,\n.btn-group-vertical > .btn.active {\n z-index: 1;\n}\n\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group,\n.btn-group-vertical .btn + .btn,\n.btn-group-vertical .btn + .btn-group,\n.btn-group-vertical .btn-group + .btn,\n.btn-group-vertical .btn-group + .btn-group {\n margin-left: -1px;\n}\n\n.btn-toolbar {\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-start;\n}\n\n.btn-toolbar .input-group {\n width: auto;\n}\n\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n\n.btn-group > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group > .btn-group:not(:last-child) > .btn {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.btn-group > .btn:not(:first-child),\n.btn-group > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.dropdown-toggle-split {\n padding-right: 0.5625rem;\n padding-left: 0.5625rem;\n}\n\n.dropdown-toggle-split::after,\n.dropup .dropdown-toggle-split::after,\n.dropright .dropdown-toggle-split::after {\n margin-left: 0;\n}\n\n.dropleft .dropdown-toggle-split::before {\n margin-right: 0;\n}\n\n.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {\n padding-right: 0.375rem;\n padding-left: 0.375rem;\n}\n\n.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {\n padding-right: 0.75rem;\n padding-left: 0.75rem;\n}\n\n.btn-group-vertical {\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n}\n\n.btn-group-vertical .btn,\n.btn-group-vertical .btn-group {\n width: 100%;\n}\n\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n\n.btn-group-vertical > .btn:not(:last-child):not(.dropdown-toggle),\n.btn-group-vertical > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn:not(:first-child),\n.btn-group-vertical > .btn-group:not(:first-child) > .btn {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.btn-group-toggle > .btn,\n.btn-group-toggle > .btn-group > .btn {\n margin-bottom: 0;\n}\n\n.btn-group-toggle > .btn input[type=\"radio\"],\n.btn-group-toggle > .btn input[type=\"checkbox\"],\n.btn-group-toggle > .btn-group > .btn input[type=\"radio\"],\n.btn-group-toggle > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n\n.input-group {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: stretch;\n width: 100%;\n}\n\n.input-group > .form-control,\n.input-group > .custom-select,\n.input-group > .custom-file {\n position: relative;\n flex: 1 1 auto;\n width: 1%;\n margin-bottom: 0;\n}\n\n.input-group > .form-control + .form-control,\n.input-group > .form-control + .custom-select,\n.input-group > .form-control + .custom-file,\n.input-group > .custom-select + .form-control,\n.input-group > .custom-select + .custom-select,\n.input-group > .custom-select + .custom-file,\n.input-group > .custom-file + .form-control,\n.input-group > .custom-file + .custom-select,\n.input-group > .custom-file + .custom-file {\n margin-left: -1px;\n}\n\n.input-group > .form-control:focus,\n.input-group > .custom-select:focus,\n.input-group > .custom-file .custom-file-input:focus ~ .custom-file-label {\n z-index: 3;\n}\n\n.input-group > .custom-file .custom-file-input:focus {\n z-index: 4;\n}\n\n.input-group > .form-control:not(:last-child),\n.input-group > .custom-select:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .form-control:not(:first-child),\n.input-group > .custom-select:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.input-group > .custom-file {\n display: flex;\n align-items: center;\n}\n\n.input-group > .custom-file:not(:last-child) .custom-file-label,\n.input-group > .custom-file:not(:last-child) .custom-file-label::after {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .custom-file:not(:first-child) .custom-file-label {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.input-group-prepend,\n.input-group-append {\n display: flex;\n}\n\n.input-group-prepend .btn,\n.input-group-append .btn {\n position: relative;\n z-index: 2;\n}\n\n.input-group-prepend .btn + .btn,\n.input-group-prepend .btn + .input-group-text,\n.input-group-prepend .input-group-text + .input-group-text,\n.input-group-prepend .input-group-text + .btn,\n.input-group-append .btn + .btn,\n.input-group-append .btn + .input-group-text,\n.input-group-append .input-group-text + .input-group-text,\n.input-group-append .input-group-text + .btn {\n margin-left: -1px;\n}\n\n.input-group-prepend {\n margin-right: -1px;\n}\n\n.input-group-append {\n margin-left: -1px;\n}\n\n.input-group-text {\n display: flex;\n align-items: center;\n padding: 0.375rem 0.75rem;\n margin-bottom: 0;\n font-size: 1rem;\n font-weight: 400;\n line-height: 1.5;\n color: #495057;\n text-align: center;\n white-space: nowrap;\n background-color: #e9ecef;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n}\n\n.input-group-text input[type=\"radio\"],\n.input-group-text input[type=\"checkbox\"] {\n margin-top: 0;\n}\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-prepend > .input-group-text,\n.input-group-lg > .input-group-append > .input-group-text,\n.input-group-lg > .input-group-prepend > .btn,\n.input-group-lg > .input-group-append > .btn {\n height: calc(2.875rem + 2px);\n padding: 0.5rem 1rem;\n font-size: 1.25rem;\n line-height: 1.5;\n border-radius: 0.3rem;\n}\n\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-prepend > .input-group-text,\n.input-group-sm > .input-group-append > .input-group-text,\n.input-group-sm > .input-group-prepend > .btn,\n.input-group-sm > .input-group-append > .btn {\n height: calc(1.8125rem + 2px);\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n border-radius: 0.2rem;\n}\n\n.input-group > .input-group-prepend > .btn,\n.input-group > .input-group-prepend > .input-group-text,\n.input-group > .input-group-append:not(:last-child) > .btn,\n.input-group > .input-group-append:not(:last-child) > .input-group-text,\n.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group > .input-group-append:last-child > .input-group-text:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.input-group > .input-group-append > .btn,\n.input-group > .input-group-append > .input-group-text,\n.input-group > .input-group-prepend:not(:first-child) > .btn,\n.input-group > .input-group-prepend:not(:first-child) > .input-group-text,\n.input-group > .input-group-prepend:first-child > .btn:not(:first-child),\n.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.custom-control {\n position: relative;\n display: block;\n min-height: 1.5rem;\n padding-left: 1.5rem;\n}\n\n.custom-control-inline {\n display: inline-flex;\n margin-right: 1rem;\n}\n\n.custom-control-input {\n position: absolute;\n z-index: -1;\n opacity: 0;\n}\n\n.custom-control-input:checked ~ .custom-control-label::before {\n color: #fff;\n background-color: #007bff;\n}\n\n.custom-control-input:focus ~ .custom-control-label::before {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-control-input:active ~ .custom-control-label::before {\n color: #fff;\n background-color: #b3d7ff;\n}\n\n.custom-control-input:disabled ~ .custom-control-label {\n color: #6c757d;\n}\n\n.custom-control-input:disabled ~ .custom-control-label::before {\n background-color: #e9ecef;\n}\n\n.custom-control-label {\n position: relative;\n margin-bottom: 0;\n}\n\n.custom-control-label::before {\n position: absolute;\n top: 0.25rem;\n left: -1.5rem;\n display: block;\n width: 1rem;\n height: 1rem;\n pointer-events: none;\n content: \"\";\n user-select: none;\n background-color: #dee2e6;\n}\n\n.custom-control-label::after {\n position: absolute;\n top: 0.25rem;\n left: -1.5rem;\n display: block;\n width: 1rem;\n height: 1rem;\n content: \"\";\n background-repeat: no-repeat;\n background-position: center center;\n background-size: 50% 50%;\n}\n\n.custom-checkbox .custom-control-label::before {\n border-radius: 0.25rem;\n}\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-label::before {\n background-color: #007bff;\n}\n\n.custom-checkbox .custom-control-input:checked ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='%23fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E\");\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::before {\n background-color: #007bff;\n}\n\n.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='%23fff' d='M0 2h4'/%3E%3C/svg%3E\");\n}\n\n.custom-checkbox .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-checkbox .custom-control-input:disabled:indeterminate ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-radio .custom-control-label::before {\n border-radius: 50%;\n}\n\n.custom-radio .custom-control-input:checked ~ .custom-control-label::before {\n background-color: #007bff;\n}\n\n.custom-radio .custom-control-input:checked ~ .custom-control-label::after {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='%23fff'/%3E%3C/svg%3E\");\n}\n\n.custom-radio .custom-control-input:disabled:checked ~ .custom-control-label::before {\n background-color: rgba(0, 123, 255, 0.5);\n}\n\n.custom-select {\n display: inline-block;\n width: 100%;\n height: calc(2.25rem + 2px);\n padding: 0.375rem 1.75rem 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n vertical-align: middle;\n background: #fff url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E\") no-repeat right 0.75rem center;\n background-size: 8px 10px;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n appearance: none;\n}\n\n.custom-select:focus {\n border-color: #80bdff;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(128, 189, 255, 0.5);\n}\n\n.custom-select:focus::-ms-value {\n color: #495057;\n background-color: #fff;\n}\n\n.custom-select[multiple], .custom-select[size]:not([size=\"1\"]) {\n height: auto;\n padding-right: 0.75rem;\n background-image: none;\n}\n\n.custom-select:disabled {\n color: #6c757d;\n background-color: #e9ecef;\n}\n\n.custom-select::-ms-expand {\n opacity: 0;\n}\n\n.custom-select-sm {\n height: calc(1.8125rem + 2px);\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n font-size: 75%;\n}\n\n.custom-select-lg {\n height: calc(2.875rem + 2px);\n padding-top: 0.375rem;\n padding-bottom: 0.375rem;\n font-size: 125%;\n}\n\n.custom-file {\n position: relative;\n display: inline-block;\n width: 100%;\n height: calc(2.25rem + 2px);\n margin-bottom: 0;\n}\n\n.custom-file-input {\n position: relative;\n z-index: 2;\n width: 100%;\n height: calc(2.25rem + 2px);\n margin: 0;\n opacity: 0;\n}\n\n.custom-file-input:focus ~ .custom-file-label {\n border-color: #80bdff;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-file-input:focus ~ .custom-file-label::after {\n border-color: #80bdff;\n}\n\n.custom-file-input:disabled ~ .custom-file-label {\n background-color: #e9ecef;\n}\n\n.custom-file-input:lang(en) ~ .custom-file-label::after {\n content: \"Browse\";\n}\n\n.custom-file-label {\n position: absolute;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1;\n height: calc(2.25rem + 2px);\n padding: 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n background-color: #fff;\n border: 1px solid #ced4da;\n border-radius: 0.25rem;\n}\n\n.custom-file-label::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n z-index: 3;\n display: block;\n height: 2.25rem;\n padding: 0.375rem 0.75rem;\n line-height: 1.5;\n color: #495057;\n content: \"Browse\";\n background-color: #e9ecef;\n border-left: 1px solid #ced4da;\n border-radius: 0 0.25rem 0.25rem 0;\n}\n\n.custom-range {\n width: 100%;\n padding-left: 0;\n background-color: transparent;\n appearance: none;\n}\n\n.custom-range:focus {\n outline: none;\n}\n\n.custom-range:focus::-webkit-slider-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range:focus::-moz-range-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range:focus::-ms-thumb {\n box-shadow: 0 0 0 1px #fff, 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.custom-range::-moz-focus-outer {\n border: 0;\n}\n\n.custom-range::-webkit-slider-thumb {\n width: 1rem;\n height: 1rem;\n margin-top: -0.25rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .custom-range::-webkit-slider-thumb {\n transition: none;\n }\n}\n\n.custom-range::-webkit-slider-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-webkit-slider-runnable-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: #dee2e6;\n border-color: transparent;\n border-radius: 1rem;\n}\n\n.custom-range::-moz-range-thumb {\n width: 1rem;\n height: 1rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .custom-range::-moz-range-thumb {\n transition: none;\n }\n}\n\n.custom-range::-moz-range-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-moz-range-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: #dee2e6;\n border-color: transparent;\n border-radius: 1rem;\n}\n\n.custom-range::-ms-thumb {\n width: 1rem;\n height: 1rem;\n margin-top: 0;\n margin-right: 0.2rem;\n margin-left: 0.2rem;\n background-color: #007bff;\n border: 0;\n border-radius: 1rem;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n appearance: none;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .custom-range::-ms-thumb {\n transition: none;\n }\n}\n\n.custom-range::-ms-thumb:active {\n background-color: #b3d7ff;\n}\n\n.custom-range::-ms-track {\n width: 100%;\n height: 0.5rem;\n color: transparent;\n cursor: pointer;\n background-color: transparent;\n border-color: transparent;\n border-width: 0.5rem;\n}\n\n.custom-range::-ms-fill-lower {\n background-color: #dee2e6;\n border-radius: 1rem;\n}\n\n.custom-range::-ms-fill-upper {\n margin-right: 15px;\n background-color: #dee2e6;\n border-radius: 1rem;\n}\n\n.custom-control-label::before,\n.custom-file-label,\n.custom-select {\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .custom-control-label::before,\n .custom-file-label,\n .custom-select {\n transition: none;\n }\n}\n\n.nav {\n display: flex;\n flex-wrap: wrap;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n\n.nav-link {\n display: block;\n padding: 0.5rem 1rem;\n}\n\n.nav-link:hover, .nav-link:focus {\n text-decoration: none;\n}\n\n.nav-link.disabled {\n color: #6c757d;\n}\n\n.nav-tabs {\n border-bottom: 1px solid #dee2e6;\n}\n\n.nav-tabs .nav-item {\n margin-bottom: -1px;\n}\n\n.nav-tabs .nav-link {\n border: 1px solid transparent;\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.nav-tabs .nav-link:hover, .nav-tabs .nav-link:focus {\n border-color: #e9ecef #e9ecef #dee2e6;\n}\n\n.nav-tabs .nav-link.disabled {\n color: #6c757d;\n background-color: transparent;\n border-color: transparent;\n}\n\n.nav-tabs .nav-link.active,\n.nav-tabs .nav-item.show .nav-link {\n color: #495057;\n background-color: #fff;\n border-color: #dee2e6 #dee2e6 #fff;\n}\n\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.nav-pills .nav-link {\n border-radius: 0.25rem;\n}\n\n.nav-pills .nav-link.active,\n.nav-pills .show > .nav-link {\n color: #fff;\n background-color: #007bff;\n}\n\n.nav-fill .nav-item {\n flex: 1 1 auto;\n text-align: center;\n}\n\n.nav-justified .nav-item {\n flex-basis: 0;\n flex-grow: 1;\n text-align: center;\n}\n\n.tab-content > .tab-pane {\n display: none;\n}\n\n.tab-content > .active {\n display: block;\n}\n\n.navbar {\n position: relative;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n padding: 0.5rem 1rem;\n}\n\n.navbar > .container,\n.navbar > .container-fluid {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n}\n\n.navbar-brand {\n display: inline-block;\n padding-top: 0.3125rem;\n padding-bottom: 0.3125rem;\n margin-right: 1rem;\n font-size: 1.25rem;\n line-height: inherit;\n white-space: nowrap;\n}\n\n.navbar-brand:hover, .navbar-brand:focus {\n text-decoration: none;\n}\n\n.navbar-nav {\n display: flex;\n flex-direction: column;\n padding-left: 0;\n margin-bottom: 0;\n list-style: none;\n}\n\n.navbar-nav .nav-link {\n padding-right: 0;\n padding-left: 0;\n}\n\n.navbar-nav .dropdown-menu {\n position: static;\n float: none;\n}\n\n.navbar-text {\n display: inline-block;\n padding-top: 0.5rem;\n padding-bottom: 0.5rem;\n}\n\n.navbar-collapse {\n flex-basis: 100%;\n flex-grow: 1;\n align-items: center;\n}\n\n.navbar-toggler {\n padding: 0.25rem 0.75rem;\n font-size: 1.25rem;\n line-height: 1;\n background-color: transparent;\n border: 1px solid transparent;\n border-radius: 0.25rem;\n}\n\n.navbar-toggler:hover, .navbar-toggler:focus {\n text-decoration: none;\n}\n\n.navbar-toggler:not(:disabled):not(.disabled) {\n cursor: pointer;\n}\n\n.navbar-toggler-icon {\n display: inline-block;\n width: 1.5em;\n height: 1.5em;\n vertical-align: middle;\n content: \"\";\n background: no-repeat center center;\n background-size: 100% 100%;\n}\n\n@media (max-width: 575.98px) {\n .navbar-expand-sm > .container,\n .navbar-expand-sm > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 576px) {\n .navbar-expand-sm {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-sm .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-sm .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-sm .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-sm > .container,\n .navbar-expand-sm > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-sm .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-sm .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 767.98px) {\n .navbar-expand-md > .container,\n .navbar-expand-md > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 768px) {\n .navbar-expand-md {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-md .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-md .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-md .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-md > .container,\n .navbar-expand-md > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-md .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-md .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 991.98px) {\n .navbar-expand-lg > .container,\n .navbar-expand-lg > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 992px) {\n .navbar-expand-lg {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-lg .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-lg .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-lg .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-lg > .container,\n .navbar-expand-lg > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-lg .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-lg .navbar-toggler {\n display: none;\n }\n}\n\n@media (max-width: 1199.98px) {\n .navbar-expand-xl > .container,\n .navbar-expand-xl > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n }\n}\n\n@media (min-width: 1200px) {\n .navbar-expand-xl {\n flex-flow: row nowrap;\n justify-content: flex-start;\n }\n .navbar-expand-xl .navbar-nav {\n flex-direction: row;\n }\n .navbar-expand-xl .navbar-nav .dropdown-menu {\n position: absolute;\n }\n .navbar-expand-xl .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n }\n .navbar-expand-xl > .container,\n .navbar-expand-xl > .container-fluid {\n flex-wrap: nowrap;\n }\n .navbar-expand-xl .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n }\n .navbar-expand-xl .navbar-toggler {\n display: none;\n }\n}\n\n.navbar-expand {\n flex-flow: row nowrap;\n justify-content: flex-start;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n padding-right: 0;\n padding-left: 0;\n}\n\n.navbar-expand .navbar-nav {\n flex-direction: row;\n}\n\n.navbar-expand .navbar-nav .dropdown-menu {\n position: absolute;\n}\n\n.navbar-expand .navbar-nav .nav-link {\n padding-right: 0.5rem;\n padding-left: 0.5rem;\n}\n\n.navbar-expand > .container,\n.navbar-expand > .container-fluid {\n flex-wrap: nowrap;\n}\n\n.navbar-expand .navbar-collapse {\n display: flex !important;\n flex-basis: auto;\n}\n\n.navbar-expand .navbar-toggler {\n display: none;\n}\n\n.navbar-light .navbar-brand {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-brand:hover, .navbar-light .navbar-brand:focus {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-nav .nav-link {\n color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-nav .nav-link:hover, .navbar-light .navbar-nav .nav-link:focus {\n color: rgba(0, 0, 0, 0.7);\n}\n\n.navbar-light .navbar-nav .nav-link.disabled {\n color: rgba(0, 0, 0, 0.3);\n}\n\n.navbar-light .navbar-nav .show > .nav-link,\n.navbar-light .navbar-nav .active > .nav-link,\n.navbar-light .navbar-nav .nav-link.show,\n.navbar-light .navbar-nav .nav-link.active {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-toggler {\n color: rgba(0, 0, 0, 0.5);\n border-color: rgba(0, 0, 0, 0.1);\n}\n\n.navbar-light .navbar-toggler-icon {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\");\n}\n\n.navbar-light .navbar-text {\n color: rgba(0, 0, 0, 0.5);\n}\n\n.navbar-light .navbar-text a {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-light .navbar-text a:hover, .navbar-light .navbar-text a:focus {\n color: rgba(0, 0, 0, 0.9);\n}\n\n.navbar-dark .navbar-brand {\n color: #fff;\n}\n\n.navbar-dark .navbar-brand:hover, .navbar-dark .navbar-brand:focus {\n color: #fff;\n}\n\n.navbar-dark .navbar-nav .nav-link {\n color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-nav .nav-link:hover, .navbar-dark .navbar-nav .nav-link:focus {\n color: rgba(255, 255, 255, 0.75);\n}\n\n.navbar-dark .navbar-nav .nav-link.disabled {\n color: rgba(255, 255, 255, 0.25);\n}\n\n.navbar-dark .navbar-nav .show > .nav-link,\n.navbar-dark .navbar-nav .active > .nav-link,\n.navbar-dark .navbar-nav .nav-link.show,\n.navbar-dark .navbar-nav .nav-link.active {\n color: #fff;\n}\n\n.navbar-dark .navbar-toggler {\n color: rgba(255, 255, 255, 0.5);\n border-color: rgba(255, 255, 255, 0.1);\n}\n\n.navbar-dark .navbar-toggler-icon {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 30 30' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 7h22M4 15h22M4 23h22'/%3E%3C/svg%3E\");\n}\n\n.navbar-dark .navbar-text {\n color: rgba(255, 255, 255, 0.5);\n}\n\n.navbar-dark .navbar-text a {\n color: #fff;\n}\n\n.navbar-dark .navbar-text a:hover, .navbar-dark .navbar-text a:focus {\n color: #fff;\n}\n\n.card {\n position: relative;\n display: flex;\n flex-direction: column;\n min-width: 0;\n word-wrap: break-word;\n background-color: #fff;\n background-clip: border-box;\n border: 1px solid rgba(0, 0, 0, 0.125);\n border-radius: 0.25rem;\n}\n\n.card > hr {\n margin-right: 0;\n margin-left: 0;\n}\n\n.card > .list-group:first-child .list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.card > .list-group:last-child .list-group-item:last-child {\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.card-body {\n flex: 1 1 auto;\n padding: 1.25rem;\n}\n\n.card-title {\n margin-bottom: 0.75rem;\n}\n\n.card-subtitle {\n margin-top: -0.375rem;\n margin-bottom: 0;\n}\n\n.card-text:last-child {\n margin-bottom: 0;\n}\n\n.card-link:hover {\n text-decoration: none;\n}\n\n.card-link + .card-link {\n margin-left: 1.25rem;\n}\n\n.card-header {\n padding: 0.75rem 1.25rem;\n margin-bottom: 0;\n background-color: rgba(0, 0, 0, 0.03);\n border-bottom: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-header:first-child {\n border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;\n}\n\n.card-header + .list-group .list-group-item:first-child {\n border-top: 0;\n}\n\n.card-footer {\n padding: 0.75rem 1.25rem;\n background-color: rgba(0, 0, 0, 0.03);\n border-top: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.card-footer:last-child {\n border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);\n}\n\n.card-header-tabs {\n margin-right: -0.625rem;\n margin-bottom: -0.75rem;\n margin-left: -0.625rem;\n border-bottom: 0;\n}\n\n.card-header-pills {\n margin-right: -0.625rem;\n margin-left: -0.625rem;\n}\n\n.card-img-overlay {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n padding: 1.25rem;\n}\n\n.card-img {\n width: 100%;\n border-radius: calc(0.25rem - 1px);\n}\n\n.card-img-top {\n width: 100%;\n border-top-left-radius: calc(0.25rem - 1px);\n border-top-right-radius: calc(0.25rem - 1px);\n}\n\n.card-img-bottom {\n width: 100%;\n border-bottom-right-radius: calc(0.25rem - 1px);\n border-bottom-left-radius: calc(0.25rem - 1px);\n}\n\n.card-deck {\n display: flex;\n flex-direction: column;\n}\n\n.card-deck .card {\n margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n .card-deck {\n flex-flow: row wrap;\n margin-right: -15px;\n margin-left: -15px;\n }\n .card-deck .card {\n display: flex;\n flex: 1 0 0%;\n flex-direction: column;\n margin-right: 15px;\n margin-bottom: 0;\n margin-left: 15px;\n }\n}\n\n.card-group {\n display: flex;\n flex-direction: column;\n}\n\n.card-group > .card {\n margin-bottom: 15px;\n}\n\n@media (min-width: 576px) {\n .card-group {\n flex-flow: row wrap;\n }\n .card-group > .card {\n flex: 1 0 0%;\n margin-bottom: 0;\n }\n .card-group > .card + .card {\n margin-left: 0;\n border-left: 0;\n }\n .card-group > .card:first-child {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n .card-group > .card:first-child .card-img-top,\n .card-group > .card:first-child .card-header {\n border-top-right-radius: 0;\n }\n .card-group > .card:first-child .card-img-bottom,\n .card-group > .card:first-child .card-footer {\n border-bottom-right-radius: 0;\n }\n .card-group > .card:last-child {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n .card-group > .card:last-child .card-img-top,\n .card-group > .card:last-child .card-header {\n border-top-left-radius: 0;\n }\n .card-group > .card:last-child .card-img-bottom,\n .card-group > .card:last-child .card-footer {\n border-bottom-left-radius: 0;\n }\n .card-group > .card:only-child {\n border-radius: 0.25rem;\n }\n .card-group > .card:only-child .card-img-top,\n .card-group > .card:only-child .card-header {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n }\n .card-group > .card:only-child .card-img-bottom,\n .card-group > .card:only-child .card-footer {\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n }\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) {\n border-radius: 0;\n }\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-top,\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-img-bottom,\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-header,\n .card-group > .card:not(:first-child):not(:last-child):not(:only-child) .card-footer {\n border-radius: 0;\n }\n}\n\n.card-columns .card {\n margin-bottom: 0.75rem;\n}\n\n@media (min-width: 576px) {\n .card-columns {\n column-count: 3;\n column-gap: 1.25rem;\n orphans: 1;\n widows: 1;\n }\n .card-columns .card {\n display: inline-block;\n width: 100%;\n }\n}\n\n.accordion .card:not(:first-of-type):not(:last-of-type) {\n border-bottom: 0;\n border-radius: 0;\n}\n\n.accordion .card:not(:first-of-type) .card-header:first-child {\n border-radius: 0;\n}\n\n.accordion .card:first-of-type {\n border-bottom: 0;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n\n.accordion .card:last-of-type {\n border-top-left-radius: 0;\n border-top-right-radius: 0;\n}\n\n.breadcrumb {\n display: flex;\n flex-wrap: wrap;\n padding: 0.75rem 1rem;\n margin-bottom: 1rem;\n list-style: none;\n background-color: #e9ecef;\n border-radius: 0.25rem;\n}\n\n.breadcrumb-item + .breadcrumb-item {\n padding-left: 0.5rem;\n}\n\n.breadcrumb-item + .breadcrumb-item::before {\n display: inline-block;\n padding-right: 0.5rem;\n color: #6c757d;\n content: \"/\";\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n text-decoration: underline;\n}\n\n.breadcrumb-item + .breadcrumb-item:hover::before {\n text-decoration: none;\n}\n\n.breadcrumb-item.active {\n color: #6c757d;\n}\n\n.pagination {\n display: flex;\n padding-left: 0;\n list-style: none;\n border-radius: 0.25rem;\n}\n\n.page-link {\n position: relative;\n display: block;\n padding: 0.5rem 0.75rem;\n margin-left: -1px;\n line-height: 1.25;\n color: #007bff;\n background-color: #fff;\n border: 1px solid #dee2e6;\n}\n\n.page-link:hover {\n z-index: 2;\n color: #0056b3;\n text-decoration: none;\n background-color: #e9ecef;\n border-color: #dee2e6;\n}\n\n.page-link:focus {\n z-index: 2;\n outline: 0;\n box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);\n}\n\n.page-link:not(:disabled):not(.disabled) {\n cursor: pointer;\n}\n\n.page-item:first-child .page-link {\n margin-left: 0;\n border-top-left-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.page-item:last-child .page-link {\n border-top-right-radius: 0.25rem;\n border-bottom-right-radius: 0.25rem;\n}\n\n.page-item.active .page-link {\n z-index: 1;\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.page-item.disabled .page-link {\n color: #6c757d;\n pointer-events: none;\n cursor: auto;\n background-color: #fff;\n border-color: #dee2e6;\n}\n\n.pagination-lg .page-link {\n padding: 0.75rem 1.5rem;\n font-size: 1.25rem;\n line-height: 1.5;\n}\n\n.pagination-lg .page-item:first-child .page-link {\n border-top-left-radius: 0.3rem;\n border-bottom-left-radius: 0.3rem;\n}\n\n.pagination-lg .page-item:last-child .page-link {\n border-top-right-radius: 0.3rem;\n border-bottom-right-radius: 0.3rem;\n}\n\n.pagination-sm .page-link {\n padding: 0.25rem 0.5rem;\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n.pagination-sm .page-item:first-child .page-link {\n border-top-left-radius: 0.2rem;\n border-bottom-left-radius: 0.2rem;\n}\n\n.pagination-sm .page-item:last-child .page-link {\n border-top-right-radius: 0.2rem;\n border-bottom-right-radius: 0.2rem;\n}\n\n.badge {\n display: inline-block;\n padding: 0.25em 0.4em;\n font-size: 75%;\n font-weight: 700;\n line-height: 1;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: 0.25rem;\n}\n\n.badge:empty {\n display: none;\n}\n\n.btn .badge {\n position: relative;\n top: -1px;\n}\n\n.badge-pill {\n padding-right: 0.6em;\n padding-left: 0.6em;\n border-radius: 10rem;\n}\n\n.badge-primary {\n color: #fff;\n background-color: #007bff;\n}\n\n.badge-primary[href]:hover, .badge-primary[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #0062cc;\n}\n\n.badge-secondary {\n color: #fff;\n background-color: #6c757d;\n}\n\n.badge-secondary[href]:hover, .badge-secondary[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #545b62;\n}\n\n.badge-success {\n color: #fff;\n background-color: #28a745;\n}\n\n.badge-success[href]:hover, .badge-success[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #1e7e34;\n}\n\n.badge-info {\n color: #fff;\n background-color: #17a2b8;\n}\n\n.badge-info[href]:hover, .badge-info[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #117a8b;\n}\n\n.badge-warning {\n color: #212529;\n background-color: #ffc107;\n}\n\n.badge-warning[href]:hover, .badge-warning[href]:focus {\n color: #212529;\n text-decoration: none;\n background-color: #d39e00;\n}\n\n.badge-danger {\n color: #fff;\n background-color: #dc3545;\n}\n\n.badge-danger[href]:hover, .badge-danger[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #bd2130;\n}\n\n.badge-light {\n color: #212529;\n background-color: #f8f9fa;\n}\n\n.badge-light[href]:hover, .badge-light[href]:focus {\n color: #212529;\n text-decoration: none;\n background-color: #dae0e5;\n}\n\n.badge-dark {\n color: #fff;\n background-color: #343a40;\n}\n\n.badge-dark[href]:hover, .badge-dark[href]:focus {\n color: #fff;\n text-decoration: none;\n background-color: #1d2124;\n}\n\n.jumbotron {\n padding: 2rem 1rem;\n margin-bottom: 2rem;\n background-color: #e9ecef;\n border-radius: 0.3rem;\n}\n\n@media (min-width: 576px) {\n .jumbotron {\n padding: 4rem 2rem;\n }\n}\n\n.jumbotron-fluid {\n padding-right: 0;\n padding-left: 0;\n border-radius: 0;\n}\n\n.alert {\n position: relative;\n padding: 0.75rem 1.25rem;\n margin-bottom: 1rem;\n border: 1px solid transparent;\n border-radius: 0.25rem;\n}\n\n.alert-heading {\n color: inherit;\n}\n\n.alert-link {\n font-weight: 700;\n}\n\n.alert-dismissible {\n padding-right: 4rem;\n}\n\n.alert-dismissible .close {\n position: absolute;\n top: 0;\n right: 0;\n padding: 0.75rem 1.25rem;\n color: inherit;\n}\n\n.alert-primary {\n color: #004085;\n background-color: #cce5ff;\n border-color: #b8daff;\n}\n\n.alert-primary hr {\n border-top-color: #9fcdff;\n}\n\n.alert-primary .alert-link {\n color: #002752;\n}\n\n.alert-secondary {\n color: #383d41;\n background-color: #e2e3e5;\n border-color: #d6d8db;\n}\n\n.alert-secondary hr {\n border-top-color: #c8cbcf;\n}\n\n.alert-secondary .alert-link {\n color: #202326;\n}\n\n.alert-success {\n color: #155724;\n background-color: #d4edda;\n border-color: #c3e6cb;\n}\n\n.alert-success hr {\n border-top-color: #b1dfbb;\n}\n\n.alert-success .alert-link {\n color: #0b2e13;\n}\n\n.alert-info {\n color: #0c5460;\n background-color: #d1ecf1;\n border-color: #bee5eb;\n}\n\n.alert-info hr {\n border-top-color: #abdde5;\n}\n\n.alert-info .alert-link {\n color: #062c33;\n}\n\n.alert-warning {\n color: #856404;\n background-color: #fff3cd;\n border-color: #ffeeba;\n}\n\n.alert-warning hr {\n border-top-color: #ffe8a1;\n}\n\n.alert-warning .alert-link {\n color: #533f03;\n}\n\n.alert-danger {\n color: #721c24;\n background-color: #f8d7da;\n border-color: #f5c6cb;\n}\n\n.alert-danger hr {\n border-top-color: #f1b0b7;\n}\n\n.alert-danger .alert-link {\n color: #491217;\n}\n\n.alert-light {\n color: #818182;\n background-color: #fefefe;\n border-color: #fdfdfe;\n}\n\n.alert-light hr {\n border-top-color: #ececf6;\n}\n\n.alert-light .alert-link {\n color: #686868;\n}\n\n.alert-dark {\n color: #1b1e21;\n background-color: #d6d8d9;\n border-color: #c6c8ca;\n}\n\n.alert-dark hr {\n border-top-color: #b9bbbe;\n}\n\n.alert-dark .alert-link {\n color: #040505;\n}\n\n@keyframes progress-bar-stripes {\n from {\n background-position: 1rem 0;\n }\n to {\n background-position: 0 0;\n }\n}\n\n.progress {\n display: flex;\n height: 1rem;\n overflow: hidden;\n font-size: 0.75rem;\n background-color: #e9ecef;\n border-radius: 0.25rem;\n}\n\n.progress-bar {\n display: flex;\n flex-direction: column;\n justify-content: center;\n color: #fff;\n text-align: center;\n white-space: nowrap;\n background-color: #007bff;\n transition: width 0.6s ease;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .progress-bar {\n transition: none;\n }\n}\n\n.progress-bar-striped {\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 1rem 1rem;\n}\n\n.progress-bar-animated {\n animation: progress-bar-stripes 1s linear infinite;\n}\n\n.media {\n display: flex;\n align-items: flex-start;\n}\n\n.media-body {\n flex: 1;\n}\n\n.list-group {\n display: flex;\n flex-direction: column;\n padding-left: 0;\n margin-bottom: 0;\n}\n\n.list-group-item-action {\n width: 100%;\n color: #495057;\n text-align: inherit;\n}\n\n.list-group-item-action:hover, .list-group-item-action:focus {\n color: #495057;\n text-decoration: none;\n background-color: #f8f9fa;\n}\n\n.list-group-item-action:active {\n color: #212529;\n background-color: #e9ecef;\n}\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 0.75rem 1.25rem;\n margin-bottom: -1px;\n background-color: #fff;\n border: 1px solid rgba(0, 0, 0, 0.125);\n}\n\n.list-group-item:first-child {\n border-top-left-radius: 0.25rem;\n border-top-right-radius: 0.25rem;\n}\n\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 0.25rem;\n border-bottom-left-radius: 0.25rem;\n}\n\n.list-group-item:hover, .list-group-item:focus {\n z-index: 1;\n text-decoration: none;\n}\n\n.list-group-item.disabled, .list-group-item:disabled {\n color: #6c757d;\n background-color: #fff;\n}\n\n.list-group-item.active {\n z-index: 2;\n color: #fff;\n background-color: #007bff;\n border-color: #007bff;\n}\n\n.list-group-flush .list-group-item {\n border-right: 0;\n border-left: 0;\n border-radius: 0;\n}\n\n.list-group-flush:first-child .list-group-item:first-child {\n border-top: 0;\n}\n\n.list-group-flush:last-child .list-group-item:last-child {\n border-bottom: 0;\n}\n\n.list-group-item-primary {\n color: #004085;\n background-color: #b8daff;\n}\n\n.list-group-item-primary.list-group-item-action:hover, .list-group-item-primary.list-group-item-action:focus {\n color: #004085;\n background-color: #9fcdff;\n}\n\n.list-group-item-primary.list-group-item-action.active {\n color: #fff;\n background-color: #004085;\n border-color: #004085;\n}\n\n.list-group-item-secondary {\n color: #383d41;\n background-color: #d6d8db;\n}\n\n.list-group-item-secondary.list-group-item-action:hover, .list-group-item-secondary.list-group-item-action:focus {\n color: #383d41;\n background-color: #c8cbcf;\n}\n\n.list-group-item-secondary.list-group-item-action.active {\n color: #fff;\n background-color: #383d41;\n border-color: #383d41;\n}\n\n.list-group-item-success {\n color: #155724;\n background-color: #c3e6cb;\n}\n\n.list-group-item-success.list-group-item-action:hover, .list-group-item-success.list-group-item-action:focus {\n color: #155724;\n background-color: #b1dfbb;\n}\n\n.list-group-item-success.list-group-item-action.active {\n color: #fff;\n background-color: #155724;\n border-color: #155724;\n}\n\n.list-group-item-info {\n color: #0c5460;\n background-color: #bee5eb;\n}\n\n.list-group-item-info.list-group-item-action:hover, .list-group-item-info.list-group-item-action:focus {\n color: #0c5460;\n background-color: #abdde5;\n}\n\n.list-group-item-info.list-group-item-action.active {\n color: #fff;\n background-color: #0c5460;\n border-color: #0c5460;\n}\n\n.list-group-item-warning {\n color: #856404;\n background-color: #ffeeba;\n}\n\n.list-group-item-warning.list-group-item-action:hover, .list-group-item-warning.list-group-item-action:focus {\n color: #856404;\n background-color: #ffe8a1;\n}\n\n.list-group-item-warning.list-group-item-action.active {\n color: #fff;\n background-color: #856404;\n border-color: #856404;\n}\n\n.list-group-item-danger {\n color: #721c24;\n background-color: #f5c6cb;\n}\n\n.list-group-item-danger.list-group-item-action:hover, .list-group-item-danger.list-group-item-action:focus {\n color: #721c24;\n background-color: #f1b0b7;\n}\n\n.list-group-item-danger.list-group-item-action.active {\n color: #fff;\n background-color: #721c24;\n border-color: #721c24;\n}\n\n.list-group-item-light {\n color: #818182;\n background-color: #fdfdfe;\n}\n\n.list-group-item-light.list-group-item-action:hover, .list-group-item-light.list-group-item-action:focus {\n color: #818182;\n background-color: #ececf6;\n}\n\n.list-group-item-light.list-group-item-action.active {\n color: #fff;\n background-color: #818182;\n border-color: #818182;\n}\n\n.list-group-item-dark {\n color: #1b1e21;\n background-color: #c6c8ca;\n}\n\n.list-group-item-dark.list-group-item-action:hover, .list-group-item-dark.list-group-item-action:focus {\n color: #1b1e21;\n background-color: #b9bbbe;\n}\n\n.list-group-item-dark.list-group-item-action.active {\n color: #fff;\n background-color: #1b1e21;\n border-color: #1b1e21;\n}\n\n.close {\n float: right;\n font-size: 1.5rem;\n font-weight: 700;\n line-height: 1;\n color: #000;\n text-shadow: 0 1px 0 #fff;\n opacity: .5;\n}\n\n.close:not(:disabled):not(.disabled) {\n cursor: pointer;\n}\n\n.close:not(:disabled):not(.disabled):hover, .close:not(:disabled):not(.disabled):focus {\n color: #000;\n text-decoration: none;\n opacity: .75;\n}\n\nbutton.close {\n padding: 0;\n background-color: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n\n.modal-open {\n overflow: hidden;\n}\n\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n.modal {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n display: none;\n overflow: hidden;\n outline: 0;\n}\n\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 0.5rem;\n pointer-events: none;\n}\n\n.modal.fade .modal-dialog {\n transition: transform 0.3s ease-out;\n transform: translate(0, -25%);\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .modal.fade .modal-dialog {\n transition: none;\n }\n}\n\n.modal.show .modal-dialog {\n transform: translate(0, 0);\n}\n\n.modal-dialog-centered {\n display: flex;\n align-items: center;\n min-height: calc(100% - (0.5rem * 2));\n}\n\n.modal-dialog-centered::before {\n display: block;\n height: calc(100vh - (0.5rem * 2));\n content: \"\";\n}\n\n.modal-content {\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n pointer-events: auto;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 0.3rem;\n outline: 0;\n}\n\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000;\n}\n\n.modal-backdrop.fade {\n opacity: 0;\n}\n\n.modal-backdrop.show {\n opacity: 0.5;\n}\n\n.modal-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n padding: 1rem;\n border-bottom: 1px solid #e9ecef;\n border-top-left-radius: 0.3rem;\n border-top-right-radius: 0.3rem;\n}\n\n.modal-header .close {\n padding: 1rem;\n margin: -1rem -1rem -1rem auto;\n}\n\n.modal-title {\n margin-bottom: 0;\n line-height: 1.5;\n}\n\n.modal-body {\n position: relative;\n flex: 1 1 auto;\n padding: 1rem;\n}\n\n.modal-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n padding: 1rem;\n border-top: 1px solid #e9ecef;\n}\n\n.modal-footer > :not(:first-child) {\n margin-left: .25rem;\n}\n\n.modal-footer > :not(:last-child) {\n margin-right: .25rem;\n}\n\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n@media (min-width: 576px) {\n .modal-dialog {\n max-width: 500px;\n margin: 1.75rem auto;\n }\n .modal-dialog-centered {\n min-height: calc(100% - (1.75rem * 2));\n }\n .modal-dialog-centered::before {\n height: calc(100vh - (1.75rem * 2));\n }\n .modal-sm {\n max-width: 300px;\n }\n}\n\n@media (min-width: 992px) {\n .modal-lg {\n max-width: 800px;\n }\n}\n\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-style: normal;\n font-weight: 400;\n line-height: 1.5;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n font-size: 0.875rem;\n word-wrap: break-word;\n opacity: 0;\n}\n\n.tooltip.show {\n opacity: 0.9;\n}\n\n.tooltip .arrow {\n position: absolute;\n display: block;\n width: 0.8rem;\n height: 0.4rem;\n}\n\n.tooltip .arrow::before {\n position: absolute;\n content: \"\";\n border-color: transparent;\n border-style: solid;\n}\n\n.bs-tooltip-top, .bs-tooltip-auto[x-placement^=\"top\"] {\n padding: 0.4rem 0;\n}\n\n.bs-tooltip-top .arrow, .bs-tooltip-auto[x-placement^=\"top\"] .arrow {\n bottom: 0;\n}\n\n.bs-tooltip-top .arrow::before, .bs-tooltip-auto[x-placement^=\"top\"] .arrow::before {\n top: 0;\n border-width: 0.4rem 0.4rem 0;\n border-top-color: #000;\n}\n\n.bs-tooltip-right, .bs-tooltip-auto[x-placement^=\"right\"] {\n padding: 0 0.4rem;\n}\n\n.bs-tooltip-right .arrow, .bs-tooltip-auto[x-placement^=\"right\"] .arrow {\n left: 0;\n width: 0.4rem;\n height: 0.8rem;\n}\n\n.bs-tooltip-right .arrow::before, .bs-tooltip-auto[x-placement^=\"right\"] .arrow::before {\n right: 0;\n border-width: 0.4rem 0.4rem 0.4rem 0;\n border-right-color: #000;\n}\n\n.bs-tooltip-bottom, .bs-tooltip-auto[x-placement^=\"bottom\"] {\n padding: 0.4rem 0;\n}\n\n.bs-tooltip-bottom .arrow, .bs-tooltip-auto[x-placement^=\"bottom\"] .arrow {\n top: 0;\n}\n\n.bs-tooltip-bottom .arrow::before, .bs-tooltip-auto[x-placement^=\"bottom\"] .arrow::before {\n bottom: 0;\n border-width: 0 0.4rem 0.4rem;\n border-bottom-color: #000;\n}\n\n.bs-tooltip-left, .bs-tooltip-auto[x-placement^=\"left\"] {\n padding: 0 0.4rem;\n}\n\n.bs-tooltip-left .arrow, .bs-tooltip-auto[x-placement^=\"left\"] .arrow {\n right: 0;\n width: 0.4rem;\n height: 0.8rem;\n}\n\n.bs-tooltip-left .arrow::before, .bs-tooltip-auto[x-placement^=\"left\"] .arrow::before {\n left: 0;\n border-width: 0.4rem 0 0.4rem 0.4rem;\n border-left-color: #000;\n}\n\n.tooltip-inner {\n max-width: 200px;\n padding: 0.25rem 0.5rem;\n color: #fff;\n text-align: center;\n background-color: #000;\n border-radius: 0.25rem;\n}\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: block;\n max-width: 276px;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\";\n font-style: normal;\n font-weight: 400;\n line-height: 1.5;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n letter-spacing: normal;\n word-break: normal;\n word-spacing: normal;\n white-space: normal;\n line-break: auto;\n font-size: 0.875rem;\n word-wrap: break-word;\n background-color: #fff;\n background-clip: padding-box;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 0.3rem;\n}\n\n.popover .arrow {\n position: absolute;\n display: block;\n width: 1rem;\n height: 0.5rem;\n margin: 0 0.3rem;\n}\n\n.popover .arrow::before, .popover .arrow::after {\n position: absolute;\n display: block;\n content: \"\";\n border-color: transparent;\n border-style: solid;\n}\n\n.bs-popover-top, .bs-popover-auto[x-placement^=\"top\"] {\n margin-bottom: 0.5rem;\n}\n\n.bs-popover-top .arrow, .bs-popover-auto[x-placement^=\"top\"] .arrow {\n bottom: calc((0.5rem + 1px) * -1);\n}\n\n.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^=\"top\"] .arrow::before,\n.bs-popover-top .arrow::after,\n.bs-popover-auto[x-placement^=\"top\"] .arrow::after {\n border-width: 0.5rem 0.5rem 0;\n}\n\n.bs-popover-top .arrow::before, .bs-popover-auto[x-placement^=\"top\"] .arrow::before {\n bottom: 0;\n border-top-color: rgba(0, 0, 0, 0.25);\n}\n\n\n.bs-popover-top .arrow::after,\n.bs-popover-auto[x-placement^=\"top\"] .arrow::after {\n bottom: 1px;\n border-top-color: #fff;\n}\n\n.bs-popover-right, .bs-popover-auto[x-placement^=\"right\"] {\n margin-left: 0.5rem;\n}\n\n.bs-popover-right .arrow, .bs-popover-auto[x-placement^=\"right\"] .arrow {\n left: calc((0.5rem + 1px) * -1);\n width: 0.5rem;\n height: 1rem;\n margin: 0.3rem 0;\n}\n\n.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^=\"right\"] .arrow::before,\n.bs-popover-right .arrow::after,\n.bs-popover-auto[x-placement^=\"right\"] .arrow::after {\n border-width: 0.5rem 0.5rem 0.5rem 0;\n}\n\n.bs-popover-right .arrow::before, .bs-popover-auto[x-placement^=\"right\"] .arrow::before {\n left: 0;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n\n\n.bs-popover-right .arrow::after,\n.bs-popover-auto[x-placement^=\"right\"] .arrow::after {\n left: 1px;\n border-right-color: #fff;\n}\n\n.bs-popover-bottom, .bs-popover-auto[x-placement^=\"bottom\"] {\n margin-top: 0.5rem;\n}\n\n.bs-popover-bottom .arrow, .bs-popover-auto[x-placement^=\"bottom\"] .arrow {\n top: calc((0.5rem + 1px) * -1);\n}\n\n.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^=\"bottom\"] .arrow::before,\n.bs-popover-bottom .arrow::after,\n.bs-popover-auto[x-placement^=\"bottom\"] .arrow::after {\n border-width: 0 0.5rem 0.5rem 0.5rem;\n}\n\n.bs-popover-bottom .arrow::before, .bs-popover-auto[x-placement^=\"bottom\"] .arrow::before {\n top: 0;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n}\n\n\n.bs-popover-bottom .arrow::after,\n.bs-popover-auto[x-placement^=\"bottom\"] .arrow::after {\n top: 1px;\n border-bottom-color: #fff;\n}\n\n.bs-popover-bottom .popover-header::before, .bs-popover-auto[x-placement^=\"bottom\"] .popover-header::before {\n position: absolute;\n top: 0;\n left: 50%;\n display: block;\n width: 1rem;\n margin-left: -0.5rem;\n content: \"\";\n border-bottom: 1px solid #f7f7f7;\n}\n\n.bs-popover-left, .bs-popover-auto[x-placement^=\"left\"] {\n margin-right: 0.5rem;\n}\n\n.bs-popover-left .arrow, .bs-popover-auto[x-placement^=\"left\"] .arrow {\n right: calc((0.5rem + 1px) * -1);\n width: 0.5rem;\n height: 1rem;\n margin: 0.3rem 0;\n}\n\n.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^=\"left\"] .arrow::before,\n.bs-popover-left .arrow::after,\n.bs-popover-auto[x-placement^=\"left\"] .arrow::after {\n border-width: 0.5rem 0 0.5rem 0.5rem;\n}\n\n.bs-popover-left .arrow::before, .bs-popover-auto[x-placement^=\"left\"] .arrow::before {\n right: 0;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n\n\n.bs-popover-left .arrow::after,\n.bs-popover-auto[x-placement^=\"left\"] .arrow::after {\n right: 1px;\n border-left-color: #fff;\n}\n\n.popover-header {\n padding: 0.5rem 0.75rem;\n margin-bottom: 0;\n font-size: 1rem;\n color: inherit;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-top-left-radius: calc(0.3rem - 1px);\n border-top-right-radius: calc(0.3rem - 1px);\n}\n\n.popover-header:empty {\n display: none;\n}\n\n.popover-body {\n padding: 0.5rem 0.75rem;\n color: #212529;\n}\n\n.carousel {\n position: relative;\n}\n\n.carousel-inner {\n position: relative;\n width: 100%;\n overflow: hidden;\n}\n\n.carousel-item {\n position: relative;\n display: none;\n align-items: center;\n width: 100%;\n backface-visibility: hidden;\n perspective: 1000px;\n}\n\n.carousel-item.active,\n.carousel-item-next,\n.carousel-item-prev {\n display: block;\n transition: transform 0.6s ease;\n}\n\n@media screen and (prefers-reduced-motion: reduce) {\n .carousel-item.active,\n .carousel-item-next,\n .carousel-item-prev {\n transition: none;\n }\n}\n\n.carousel-item-next,\n.carousel-item-prev {\n position: absolute;\n top: 0;\n}\n\n.carousel-item-next.carousel-item-left,\n.carousel-item-prev.carousel-item-right {\n transform: translateX(0);\n}\n\n@supports (transform-style: preserve-3d) {\n .carousel-item-next.carousel-item-left,\n .carousel-item-prev.carousel-item-right {\n transform: translate3d(0, 0, 0);\n }\n}\n\n.carousel-item-next,\n.active.carousel-item-right {\n transform: translateX(100%);\n}\n\n@supports (transform-style: preserve-3d) {\n .carousel-item-next,\n .active.carousel-item-right {\n transform: translate3d(100%, 0, 0);\n }\n}\n\n.carousel-item-prev,\n.active.carousel-item-left {\n transform: translateX(-100%);\n}\n\n@supports (transform-style: preserve-3d) {\n .carousel-item-prev,\n .active.carousel-item-left {\n transform: translate3d(-100%, 0, 0);\n }\n}\n\n.carousel-fade .carousel-item {\n opacity: 0;\n transition-duration: .6s;\n transition-property: opacity;\n}\n\n.carousel-fade .carousel-item.active,\n.carousel-fade .carousel-item-next.carousel-item-left,\n.carousel-fade .carousel-item-prev.carousel-item-right {\n opacity: 1;\n}\n\n.carousel-fade .active.carousel-item-left,\n.carousel-fade .active.carousel-item-right {\n opacity: 0;\n}\n\n.carousel-fade .carousel-item-next,\n.carousel-fade .carousel-item-prev,\n.carousel-fade .carousel-item.active,\n.carousel-fade .active.carousel-item-left,\n.carousel-fade .active.carousel-item-prev {\n transform: translateX(0);\n}\n\n@supports (transform-style: preserve-3d) {\n .carousel-fade .carousel-item-next,\n .carousel-fade .carousel-item-prev,\n .carousel-fade .carousel-item.active,\n .carousel-fade .active.carousel-item-left,\n .carousel-fade .active.carousel-item-prev {\n transform: translate3d(0, 0, 0);\n }\n}\n\n.carousel-control-prev,\n.carousel-control-next {\n position: absolute;\n top: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 15%;\n color: #fff;\n text-align: center;\n opacity: 0.5;\n}\n\n.carousel-control-prev:hover, .carousel-control-prev:focus,\n.carousel-control-next:hover,\n.carousel-control-next:focus {\n color: #fff;\n text-decoration: none;\n outline: 0;\n opacity: .9;\n}\n\n.carousel-control-prev {\n left: 0;\n}\n\n.carousel-control-next {\n right: 0;\n}\n\n.carousel-control-prev-icon,\n.carousel-control-next-icon {\n display: inline-block;\n width: 20px;\n height: 20px;\n background: transparent no-repeat center center;\n background-size: 100% 100%;\n}\n\n.carousel-control-prev-icon {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M5.25 0l-4 4 4 4 1.5-1.5-2.5-2.5 2.5-2.5-1.5-1.5z'/%3E%3C/svg%3E\");\n}\n\n.carousel-control-next-icon {\n background-image: url(\"data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 8 8'%3E%3Cpath d='M2.75 0l-1.5 1.5 2.5 2.5-2.5 2.5 1.5 1.5 4-4-4-4z'/%3E%3C/svg%3E\");\n}\n\n.carousel-indicators {\n position: absolute;\n right: 0;\n bottom: 10px;\n left: 0;\n z-index: 15;\n display: flex;\n justify-content: center;\n padding-left: 0;\n margin-right: 15%;\n margin-left: 15%;\n list-style: none;\n}\n\n.carousel-indicators li {\n position: relative;\n flex: 0 1 auto;\n width: 30px;\n height: 3px;\n margin-right: 3px;\n margin-left: 3px;\n text-indent: -999px;\n cursor: pointer;\n background-color: rgba(255, 255, 255, 0.5);\n}\n\n.carousel-indicators li::before {\n position: absolute;\n top: -10px;\n left: 0;\n display: inline-block;\n width: 100%;\n height: 10px;\n content: \"\";\n}\n\n.carousel-indicators li::after {\n position: absolute;\n bottom: -10px;\n left: 0;\n display: inline-block;\n width: 100%;\n height: 10px;\n content: \"\";\n}\n\n.carousel-indicators .active {\n background-color: #fff;\n}\n\n.carousel-caption {\n position: absolute;\n right: 15%;\n bottom: 20px;\n left: 15%;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #fff;\n text-align: center;\n}\n\n.align-baseline {\n vertical-align: baseline !important;\n}\n\n.align-top {\n vertical-align: top !important;\n}\n\n.align-middle {\n vertical-align: middle !important;\n}\n\n.align-bottom {\n vertical-align: bottom !important;\n}\n\n.align-text-bottom {\n vertical-align: text-bottom !important;\n}\n\n.align-text-top {\n vertical-align: text-top !important;\n}\n\n.bg-primary {\n background-color: #007bff !important;\n}\n\na.bg-primary:hover, a.bg-primary:focus,\nbutton.bg-primary:hover,\nbutton.bg-primary:focus {\n background-color: #0062cc !important;\n}\n\n.bg-secondary {\n background-color: #6c757d !important;\n}\n\na.bg-secondary:hover, a.bg-secondary:focus,\nbutton.bg-secondary:hover,\nbutton.bg-secondary:focus {\n background-color: #545b62 !important;\n}\n\n.bg-success {\n background-color: #28a745 !important;\n}\n\na.bg-success:hover, a.bg-success:focus,\nbutton.bg-success:hover,\nbutton.bg-success:focus {\n background-color: #1e7e34 !important;\n}\n\n.bg-info {\n background-color: #17a2b8 !important;\n}\n\na.bg-info:hover, a.bg-info:focus,\nbutton.bg-info:hover,\nbutton.bg-info:focus {\n background-color: #117a8b !important;\n}\n\n.bg-warning {\n background-color: #ffc107 !important;\n}\n\na.bg-warning:hover, a.bg-warning:focus,\nbutton.bg-warning:hover,\nbutton.bg-warning:focus {\n background-color: #d39e00 !important;\n}\n\n.bg-danger {\n background-color: #dc3545 !important;\n}\n\na.bg-danger:hover, a.bg-danger:focus,\nbutton.bg-danger:hover,\nbutton.bg-danger:focus {\n background-color: #bd2130 !important;\n}\n\n.bg-light {\n background-color: #f8f9fa !important;\n}\n\na.bg-light:hover, a.bg-light:focus,\nbutton.bg-light:hover,\nbutton.bg-light:focus {\n background-color: #dae0e5 !important;\n}\n\n.bg-dark {\n background-color: #343a40 !important;\n}\n\na.bg-dark:hover, a.bg-dark:focus,\nbutton.bg-dark:hover,\nbutton.bg-dark:focus {\n background-color: #1d2124 !important;\n}\n\n.bg-white {\n background-color: #fff !important;\n}\n\n.bg-transparent {\n background-color: transparent !important;\n}\n\n.border {\n border: 1px solid #dee2e6 !important;\n}\n\n.border-top {\n border-top: 1px solid #dee2e6 !important;\n}\n\n.border-right {\n border-right: 1px solid #dee2e6 !important;\n}\n\n.border-bottom {\n border-bottom: 1px solid #dee2e6 !important;\n}\n\n.border-left {\n border-left: 1px solid #dee2e6 !important;\n}\n\n.border-0 {\n border: 0 !important;\n}\n\n.border-top-0 {\n border-top: 0 !important;\n}\n\n.border-right-0 {\n border-right: 0 !important;\n}\n\n.border-bottom-0 {\n border-bottom: 0 !important;\n}\n\n.border-left-0 {\n border-left: 0 !important;\n}\n\n.border-primary {\n border-color: #007bff !important;\n}\n\n.border-secondary {\n border-color: #6c757d !important;\n}\n\n.border-success {\n border-color: #28a745 !important;\n}\n\n.border-info {\n border-color: #17a2b8 !important;\n}\n\n.border-warning {\n border-color: #ffc107 !important;\n}\n\n.border-danger {\n border-color: #dc3545 !important;\n}\n\n.border-light {\n border-color: #f8f9fa !important;\n}\n\n.border-dark {\n border-color: #343a40 !important;\n}\n\n.border-white {\n border-color: #fff !important;\n}\n\n.rounded {\n border-radius: 0.25rem !important;\n}\n\n.rounded-top {\n border-top-left-radius: 0.25rem !important;\n border-top-right-radius: 0.25rem !important;\n}\n\n.rounded-right {\n border-top-right-radius: 0.25rem !important;\n border-bottom-right-radius: 0.25rem !important;\n}\n\n.rounded-bottom {\n border-bottom-right-radius: 0.25rem !important;\n border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-left {\n border-top-left-radius: 0.25rem !important;\n border-bottom-left-radius: 0.25rem !important;\n}\n\n.rounded-circle {\n border-radius: 50% !important;\n}\n\n.rounded-0 {\n border-radius: 0 !important;\n}\n\n.clearfix::after {\n display: block;\n clear: both;\n content: \"\";\n}\n\n.d-none {\n display: none !important;\n}\n\n.d-inline {\n display: inline !important;\n}\n\n.d-inline-block {\n display: inline-block !important;\n}\n\n.d-block {\n display: block !important;\n}\n\n.d-table {\n display: table !important;\n}\n\n.d-table-row {\n display: table-row !important;\n}\n\n.d-table-cell {\n display: table-cell !important;\n}\n\n.d-flex {\n display: flex !important;\n}\n\n.d-inline-flex {\n display: inline-flex !important;\n}\n\n@media (min-width: 576px) {\n .d-sm-none {\n display: none !important;\n }\n .d-sm-inline {\n display: inline !important;\n }\n .d-sm-inline-block {\n display: inline-block !important;\n }\n .d-sm-block {\n display: block !important;\n }\n .d-sm-table {\n display: table !important;\n }\n .d-sm-table-row {\n display: table-row !important;\n }\n .d-sm-table-cell {\n display: table-cell !important;\n }\n .d-sm-flex {\n display: flex !important;\n }\n .d-sm-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 768px) {\n .d-md-none {\n display: none !important;\n }\n .d-md-inline {\n display: inline !important;\n }\n .d-md-inline-block {\n display: inline-block !important;\n }\n .d-md-block {\n display: block !important;\n }\n .d-md-table {\n display: table !important;\n }\n .d-md-table-row {\n display: table-row !important;\n }\n .d-md-table-cell {\n display: table-cell !important;\n }\n .d-md-flex {\n display: flex !important;\n }\n .d-md-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 992px) {\n .d-lg-none {\n display: none !important;\n }\n .d-lg-inline {\n display: inline !important;\n }\n .d-lg-inline-block {\n display: inline-block !important;\n }\n .d-lg-block {\n display: block !important;\n }\n .d-lg-table {\n display: table !important;\n }\n .d-lg-table-row {\n display: table-row !important;\n }\n .d-lg-table-cell {\n display: table-cell !important;\n }\n .d-lg-flex {\n display: flex !important;\n }\n .d-lg-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media (min-width: 1200px) {\n .d-xl-none {\n display: none !important;\n }\n .d-xl-inline {\n display: inline !important;\n }\n .d-xl-inline-block {\n display: inline-block !important;\n }\n .d-xl-block {\n display: block !important;\n }\n .d-xl-table {\n display: table !important;\n }\n .d-xl-table-row {\n display: table-row !important;\n }\n .d-xl-table-cell {\n display: table-cell !important;\n }\n .d-xl-flex {\n display: flex !important;\n }\n .d-xl-inline-flex {\n display: inline-flex !important;\n }\n}\n\n@media print {\n .d-print-none {\n display: none !important;\n }\n .d-print-inline {\n display: inline !important;\n }\n .d-print-inline-block {\n display: inline-block !important;\n }\n .d-print-block {\n display: block !important;\n }\n .d-print-table {\n display: table !important;\n }\n .d-print-table-row {\n display: table-row !important;\n }\n .d-print-table-cell {\n display: table-cell !important;\n }\n .d-print-flex {\n display: flex !important;\n }\n .d-print-inline-flex {\n display: inline-flex !important;\n }\n}\n\n.embed-responsive {\n position: relative;\n display: block;\n width: 100%;\n padding: 0;\n overflow: hidden;\n}\n\n.embed-responsive::before {\n display: block;\n content: \"\";\n}\n\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n bottom: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border: 0;\n}\n\n.embed-responsive-21by9::before {\n padding-top: 42.857143%;\n}\n\n.embed-responsive-16by9::before {\n padding-top: 56.25%;\n}\n\n.embed-responsive-4by3::before {\n padding-top: 75%;\n}\n\n.embed-responsive-1by1::before {\n padding-top: 100%;\n}\n\n.flex-row {\n flex-direction: row !important;\n}\n\n.flex-column {\n flex-direction: column !important;\n}\n\n.flex-row-reverse {\n flex-direction: row-reverse !important;\n}\n\n.flex-column-reverse {\n flex-direction: column-reverse !important;\n}\n\n.flex-wrap {\n flex-wrap: wrap !important;\n}\n\n.flex-nowrap {\n flex-wrap: nowrap !important;\n}\n\n.flex-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n}\n\n.flex-fill {\n flex: 1 1 auto !important;\n}\n\n.flex-grow-0 {\n flex-grow: 0 !important;\n}\n\n.flex-grow-1 {\n flex-grow: 1 !important;\n}\n\n.flex-shrink-0 {\n flex-shrink: 0 !important;\n}\n\n.flex-shrink-1 {\n flex-shrink: 1 !important;\n}\n\n.justify-content-start {\n justify-content: flex-start !important;\n}\n\n.justify-content-end {\n justify-content: flex-end !important;\n}\n\n.justify-content-center {\n justify-content: center !important;\n}\n\n.justify-content-between {\n justify-content: space-between !important;\n}\n\n.justify-content-around {\n justify-content: space-around !important;\n}\n\n.align-items-start {\n align-items: flex-start !important;\n}\n\n.align-items-end {\n align-items: flex-end !important;\n}\n\n.align-items-center {\n align-items: center !important;\n}\n\n.align-items-baseline {\n align-items: baseline !important;\n}\n\n.align-items-stretch {\n align-items: stretch !important;\n}\n\n.align-content-start {\n align-content: flex-start !important;\n}\n\n.align-content-end {\n align-content: flex-end !important;\n}\n\n.align-content-center {\n align-content: center !important;\n}\n\n.align-content-between {\n align-content: space-between !important;\n}\n\n.align-content-around {\n align-content: space-around !important;\n}\n\n.align-content-stretch {\n align-content: stretch !important;\n}\n\n.align-self-auto {\n align-self: auto !important;\n}\n\n.align-self-start {\n align-self: flex-start !important;\n}\n\n.align-self-end {\n align-self: flex-end !important;\n}\n\n.align-self-center {\n align-self: center !important;\n}\n\n.align-self-baseline {\n align-self: baseline !important;\n}\n\n.align-self-stretch {\n align-self: stretch !important;\n}\n\n@media (min-width: 576px) {\n .flex-sm-row {\n flex-direction: row !important;\n }\n .flex-sm-column {\n flex-direction: column !important;\n }\n .flex-sm-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-sm-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-sm-wrap {\n flex-wrap: wrap !important;\n }\n .flex-sm-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-sm-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-sm-fill {\n flex: 1 1 auto !important;\n }\n .flex-sm-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-sm-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-sm-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-sm-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-sm-start {\n justify-content: flex-start !important;\n }\n .justify-content-sm-end {\n justify-content: flex-end !important;\n }\n .justify-content-sm-center {\n justify-content: center !important;\n }\n .justify-content-sm-between {\n justify-content: space-between !important;\n }\n .justify-content-sm-around {\n justify-content: space-around !important;\n }\n .align-items-sm-start {\n align-items: flex-start !important;\n }\n .align-items-sm-end {\n align-items: flex-end !important;\n }\n .align-items-sm-center {\n align-items: center !important;\n }\n .align-items-sm-baseline {\n align-items: baseline !important;\n }\n .align-items-sm-stretch {\n align-items: stretch !important;\n }\n .align-content-sm-start {\n align-content: flex-start !important;\n }\n .align-content-sm-end {\n align-content: flex-end !important;\n }\n .align-content-sm-center {\n align-content: center !important;\n }\n .align-content-sm-between {\n align-content: space-between !important;\n }\n .align-content-sm-around {\n align-content: space-around !important;\n }\n .align-content-sm-stretch {\n align-content: stretch !important;\n }\n .align-self-sm-auto {\n align-self: auto !important;\n }\n .align-self-sm-start {\n align-self: flex-start !important;\n }\n .align-self-sm-end {\n align-self: flex-end !important;\n }\n .align-self-sm-center {\n align-self: center !important;\n }\n .align-self-sm-baseline {\n align-self: baseline !important;\n }\n .align-self-sm-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 768px) {\n .flex-md-row {\n flex-direction: row !important;\n }\n .flex-md-column {\n flex-direction: column !important;\n }\n .flex-md-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-md-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-md-wrap {\n flex-wrap: wrap !important;\n }\n .flex-md-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-md-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-md-fill {\n flex: 1 1 auto !important;\n }\n .flex-md-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-md-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-md-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-md-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-md-start {\n justify-content: flex-start !important;\n }\n .justify-content-md-end {\n justify-content: flex-end !important;\n }\n .justify-content-md-center {\n justify-content: center !important;\n }\n .justify-content-md-between {\n justify-content: space-between !important;\n }\n .justify-content-md-around {\n justify-content: space-around !important;\n }\n .align-items-md-start {\n align-items: flex-start !important;\n }\n .align-items-md-end {\n align-items: flex-end !important;\n }\n .align-items-md-center {\n align-items: center !important;\n }\n .align-items-md-baseline {\n align-items: baseline !important;\n }\n .align-items-md-stretch {\n align-items: stretch !important;\n }\n .align-content-md-start {\n align-content: flex-start !important;\n }\n .align-content-md-end {\n align-content: flex-end !important;\n }\n .align-content-md-center {\n align-content: center !important;\n }\n .align-content-md-between {\n align-content: space-between !important;\n }\n .align-content-md-around {\n align-content: space-around !important;\n }\n .align-content-md-stretch {\n align-content: stretch !important;\n }\n .align-self-md-auto {\n align-self: auto !important;\n }\n .align-self-md-start {\n align-self: flex-start !important;\n }\n .align-self-md-end {\n align-self: flex-end !important;\n }\n .align-self-md-center {\n align-self: center !important;\n }\n .align-self-md-baseline {\n align-self: baseline !important;\n }\n .align-self-md-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 992px) {\n .flex-lg-row {\n flex-direction: row !important;\n }\n .flex-lg-column {\n flex-direction: column !important;\n }\n .flex-lg-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-lg-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-lg-wrap {\n flex-wrap: wrap !important;\n }\n .flex-lg-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-lg-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-lg-fill {\n flex: 1 1 auto !important;\n }\n .flex-lg-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-lg-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-lg-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-lg-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-lg-start {\n justify-content: flex-start !important;\n }\n .justify-content-lg-end {\n justify-content: flex-end !important;\n }\n .justify-content-lg-center {\n justify-content: center !important;\n }\n .justify-content-lg-between {\n justify-content: space-between !important;\n }\n .justify-content-lg-around {\n justify-content: space-around !important;\n }\n .align-items-lg-start {\n align-items: flex-start !important;\n }\n .align-items-lg-end {\n align-items: flex-end !important;\n }\n .align-items-lg-center {\n align-items: center !important;\n }\n .align-items-lg-baseline {\n align-items: baseline !important;\n }\n .align-items-lg-stretch {\n align-items: stretch !important;\n }\n .align-content-lg-start {\n align-content: flex-start !important;\n }\n .align-content-lg-end {\n align-content: flex-end !important;\n }\n .align-content-lg-center {\n align-content: center !important;\n }\n .align-content-lg-between {\n align-content: space-between !important;\n }\n .align-content-lg-around {\n align-content: space-around !important;\n }\n .align-content-lg-stretch {\n align-content: stretch !important;\n }\n .align-self-lg-auto {\n align-self: auto !important;\n }\n .align-self-lg-start {\n align-self: flex-start !important;\n }\n .align-self-lg-end {\n align-self: flex-end !important;\n }\n .align-self-lg-center {\n align-self: center !important;\n }\n .align-self-lg-baseline {\n align-self: baseline !important;\n }\n .align-self-lg-stretch {\n align-self: stretch !important;\n }\n}\n\n@media (min-width: 1200px) {\n .flex-xl-row {\n flex-direction: row !important;\n }\n .flex-xl-column {\n flex-direction: column !important;\n }\n .flex-xl-row-reverse {\n flex-direction: row-reverse !important;\n }\n .flex-xl-column-reverse {\n flex-direction: column-reverse !important;\n }\n .flex-xl-wrap {\n flex-wrap: wrap !important;\n }\n .flex-xl-nowrap {\n flex-wrap: nowrap !important;\n }\n .flex-xl-wrap-reverse {\n flex-wrap: wrap-reverse !important;\n }\n .flex-xl-fill {\n flex: 1 1 auto !important;\n }\n .flex-xl-grow-0 {\n flex-grow: 0 !important;\n }\n .flex-xl-grow-1 {\n flex-grow: 1 !important;\n }\n .flex-xl-shrink-0 {\n flex-shrink: 0 !important;\n }\n .flex-xl-shrink-1 {\n flex-shrink: 1 !important;\n }\n .justify-content-xl-start {\n justify-content: flex-start !important;\n }\n .justify-content-xl-end {\n justify-content: flex-end !important;\n }\n .justify-content-xl-center {\n justify-content: center !important;\n }\n .justify-content-xl-between {\n justify-content: space-between !important;\n }\n .justify-content-xl-around {\n justify-content: space-around !important;\n }\n .align-items-xl-start {\n align-items: flex-start !important;\n }\n .align-items-xl-end {\n align-items: flex-end !important;\n }\n .align-items-xl-center {\n align-items: center !important;\n }\n .align-items-xl-baseline {\n align-items: baseline !important;\n }\n .align-items-xl-stretch {\n align-items: stretch !important;\n }\n .align-content-xl-start {\n align-content: flex-start !important;\n }\n .align-content-xl-end {\n align-content: flex-end !important;\n }\n .align-content-xl-center {\n align-content: center !important;\n }\n .align-content-xl-between {\n align-content: space-between !important;\n }\n .align-content-xl-around {\n align-content: space-around !important;\n }\n .align-content-xl-stretch {\n align-content: stretch !important;\n }\n .align-self-xl-auto {\n align-self: auto !important;\n }\n .align-self-xl-start {\n align-self: flex-start !important;\n }\n .align-self-xl-end {\n align-self: flex-end !important;\n }\n .align-self-xl-center {\n align-self: center !important;\n }\n .align-self-xl-baseline {\n align-self: baseline !important;\n }\n .align-self-xl-stretch {\n align-self: stretch !important;\n }\n}\n\n.float-left {\n float: left !important;\n}\n\n.float-right {\n float: right !important;\n}\n\n.float-none {\n float: none !important;\n}\n\n@media (min-width: 576px) {\n .float-sm-left {\n float: left !important;\n }\n .float-sm-right {\n float: right !important;\n }\n .float-sm-none {\n float: none !important;\n }\n}\n\n@media (min-width: 768px) {\n .float-md-left {\n float: left !important;\n }\n .float-md-right {\n float: right !important;\n }\n .float-md-none {\n float: none !important;\n }\n}\n\n@media (min-width: 992px) {\n .float-lg-left {\n float: left !important;\n }\n .float-lg-right {\n float: right !important;\n }\n .float-lg-none {\n float: none !important;\n }\n}\n\n@media (min-width: 1200px) {\n .float-xl-left {\n float: left !important;\n }\n .float-xl-right {\n float: right !important;\n }\n .float-xl-none {\n float: none !important;\n }\n}\n\n.position-static {\n position: static !important;\n}\n\n.position-relative {\n position: relative !important;\n}\n\n.position-absolute {\n position: absolute !important;\n}\n\n.position-fixed {\n position: fixed !important;\n}\n\n.position-sticky {\n position: sticky !important;\n}\n\n.fixed-top {\n position: fixed;\n top: 0;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n\n.fixed-bottom {\n position: fixed;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1030;\n}\n\n@supports (position: sticky) {\n .sticky-top {\n position: sticky;\n top: 0;\n z-index: 1020;\n }\n}\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n}\n\n.sr-only-focusable:active, .sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n overflow: visible;\n clip: auto;\n white-space: normal;\n}\n\n.shadow-sm {\n box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075) !important;\n}\n\n.shadow {\n box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;\n}\n\n.shadow-lg {\n box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.175) !important;\n}\n\n.shadow-none {\n box-shadow: none !important;\n}\n\n.w-25 {\n width: 25% !important;\n}\n\n.w-50 {\n width: 50% !important;\n}\n\n.w-75 {\n width: 75% !important;\n}\n\n.w-100 {\n width: 100% !important;\n}\n\n.w-auto {\n width: auto !important;\n}\n\n.h-25 {\n height: 25% !important;\n}\n\n.h-50 {\n height: 50% !important;\n}\n\n.h-75 {\n height: 75% !important;\n}\n\n.h-100 {\n height: 100% !important;\n}\n\n.h-auto {\n height: auto !important;\n}\n\n.mw-100 {\n max-width: 100% !important;\n}\n\n.mh-100 {\n max-height: 100% !important;\n}\n\n.m-0 {\n margin: 0 !important;\n}\n\n.mt-0,\n.my-0 {\n margin-top: 0 !important;\n}\n\n.mr-0,\n.mx-0 {\n margin-right: 0 !important;\n}\n\n.mb-0,\n.my-0 {\n margin-bottom: 0 !important;\n}\n\n.ml-0,\n.mx-0 {\n margin-left: 0 !important;\n}\n\n.m-1 {\n margin: 0.25rem !important;\n}\n\n.mt-1,\n.my-1 {\n margin-top: 0.25rem !important;\n}\n\n.mr-1,\n.mx-1 {\n margin-right: 0.25rem !important;\n}\n\n.mb-1,\n.my-1 {\n margin-bottom: 0.25rem !important;\n}\n\n.ml-1,\n.mx-1 {\n margin-left: 0.25rem !important;\n}\n\n.m-2 {\n margin: 0.5rem !important;\n}\n\n.mt-2,\n.my-2 {\n margin-top: 0.5rem !important;\n}\n\n.mr-2,\n.mx-2 {\n margin-right: 0.5rem !important;\n}\n\n.mb-2,\n.my-2 {\n margin-bottom: 0.5rem !important;\n}\n\n.ml-2,\n.mx-2 {\n margin-left: 0.5rem !important;\n}\n\n.m-3 {\n margin: 1rem !important;\n}\n\n.mt-3,\n.my-3 {\n margin-top: 1rem !important;\n}\n\n.mr-3,\n.mx-3 {\n margin-right: 1rem !important;\n}\n\n.mb-3,\n.my-3 {\n margin-bottom: 1rem !important;\n}\n\n.ml-3,\n.mx-3 {\n margin-left: 1rem !important;\n}\n\n.m-4 {\n margin: 1.5rem !important;\n}\n\n.mt-4,\n.my-4 {\n margin-top: 1.5rem !important;\n}\n\n.mr-4,\n.mx-4 {\n margin-right: 1.5rem !important;\n}\n\n.mb-4,\n.my-4 {\n margin-bottom: 1.5rem !important;\n}\n\n.ml-4,\n.mx-4 {\n margin-left: 1.5rem !important;\n}\n\n.m-5 {\n margin: 3rem !important;\n}\n\n.mt-5,\n.my-5 {\n margin-top: 3rem !important;\n}\n\n.mr-5,\n.mx-5 {\n margin-right: 3rem !important;\n}\n\n.mb-5,\n.my-5 {\n margin-bottom: 3rem !important;\n}\n\n.ml-5,\n.mx-5 {\n margin-left: 3rem !important;\n}\n\n.p-0 {\n padding: 0 !important;\n}\n\n.pt-0,\n.py-0 {\n padding-top: 0 !important;\n}\n\n.pr-0,\n.px-0 {\n padding-right: 0 !important;\n}\n\n.pb-0,\n.py-0 {\n padding-bottom: 0 !important;\n}\n\n.pl-0,\n.px-0 {\n padding-left: 0 !important;\n}\n\n.p-1 {\n padding: 0.25rem !important;\n}\n\n.pt-1,\n.py-1 {\n padding-top: 0.25rem !important;\n}\n\n.pr-1,\n.px-1 {\n padding-right: 0.25rem !important;\n}\n\n.pb-1,\n.py-1 {\n padding-bottom: 0.25rem !important;\n}\n\n.pl-1,\n.px-1 {\n padding-left: 0.25rem !important;\n}\n\n.p-2 {\n padding: 0.5rem !important;\n}\n\n.pt-2,\n.py-2 {\n padding-top: 0.5rem !important;\n}\n\n.pr-2,\n.px-2 {\n padding-right: 0.5rem !important;\n}\n\n.pb-2,\n.py-2 {\n padding-bottom: 0.5rem !important;\n}\n\n.pl-2,\n.px-2 {\n padding-left: 0.5rem !important;\n}\n\n.p-3 {\n padding: 1rem !important;\n}\n\n.pt-3,\n.py-3 {\n padding-top: 1rem !important;\n}\n\n.pr-3,\n.px-3 {\n padding-right: 1rem !important;\n}\n\n.pb-3,\n.py-3 {\n padding-bottom: 1rem !important;\n}\n\n.pl-3,\n.px-3 {\n padding-left: 1rem !important;\n}\n\n.p-4 {\n padding: 1.5rem !important;\n}\n\n.pt-4,\n.py-4 {\n padding-top: 1.5rem !important;\n}\n\n.pr-4,\n.px-4 {\n padding-right: 1.5rem !important;\n}\n\n.pb-4,\n.py-4 {\n padding-bottom: 1.5rem !important;\n}\n\n.pl-4,\n.px-4 {\n padding-left: 1.5rem !important;\n}\n\n.p-5 {\n padding: 3rem !important;\n}\n\n.pt-5,\n.py-5 {\n padding-top: 3rem !important;\n}\n\n.pr-5,\n.px-5 {\n padding-right: 3rem !important;\n}\n\n.pb-5,\n.py-5 {\n padding-bottom: 3rem !important;\n}\n\n.pl-5,\n.px-5 {\n padding-left: 3rem !important;\n}\n\n.m-auto {\n margin: auto !important;\n}\n\n.mt-auto,\n.my-auto {\n margin-top: auto !important;\n}\n\n.mr-auto,\n.mx-auto {\n margin-right: auto !important;\n}\n\n.mb-auto,\n.my-auto {\n margin-bottom: auto !important;\n}\n\n.ml-auto,\n.mx-auto {\n margin-left: auto !important;\n}\n\n@media (min-width: 576px) {\n .m-sm-0 {\n margin: 0 !important;\n }\n .mt-sm-0,\n .my-sm-0 {\n margin-top: 0 !important;\n }\n .mr-sm-0,\n .mx-sm-0 {\n margin-right: 0 !important;\n }\n .mb-sm-0,\n .my-sm-0 {\n margin-bottom: 0 !important;\n }\n .ml-sm-0,\n .mx-sm-0 {\n margin-left: 0 !important;\n }\n .m-sm-1 {\n margin: 0.25rem !important;\n }\n .mt-sm-1,\n .my-sm-1 {\n margin-top: 0.25rem !important;\n }\n .mr-sm-1,\n .mx-sm-1 {\n margin-right: 0.25rem !important;\n }\n .mb-sm-1,\n .my-sm-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-sm-1,\n .mx-sm-1 {\n margin-left: 0.25rem !important;\n }\n .m-sm-2 {\n margin: 0.5rem !important;\n }\n .mt-sm-2,\n .my-sm-2 {\n margin-top: 0.5rem !important;\n }\n .mr-sm-2,\n .mx-sm-2 {\n margin-right: 0.5rem !important;\n }\n .mb-sm-2,\n .my-sm-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-sm-2,\n .mx-sm-2 {\n margin-left: 0.5rem !important;\n }\n .m-sm-3 {\n margin: 1rem !important;\n }\n .mt-sm-3,\n .my-sm-3 {\n margin-top: 1rem !important;\n }\n .mr-sm-3,\n .mx-sm-3 {\n margin-right: 1rem !important;\n }\n .mb-sm-3,\n .my-sm-3 {\n margin-bottom: 1rem !important;\n }\n .ml-sm-3,\n .mx-sm-3 {\n margin-left: 1rem !important;\n }\n .m-sm-4 {\n margin: 1.5rem !important;\n }\n .mt-sm-4,\n .my-sm-4 {\n margin-top: 1.5rem !important;\n }\n .mr-sm-4,\n .mx-sm-4 {\n margin-right: 1.5rem !important;\n }\n .mb-sm-4,\n .my-sm-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-sm-4,\n .mx-sm-4 {\n margin-left: 1.5rem !important;\n }\n .m-sm-5 {\n margin: 3rem !important;\n }\n .mt-sm-5,\n .my-sm-5 {\n margin-top: 3rem !important;\n }\n .mr-sm-5,\n .mx-sm-5 {\n margin-right: 3rem !important;\n }\n .mb-sm-5,\n .my-sm-5 {\n margin-bottom: 3rem !important;\n }\n .ml-sm-5,\n .mx-sm-5 {\n margin-left: 3rem !important;\n }\n .p-sm-0 {\n padding: 0 !important;\n }\n .pt-sm-0,\n .py-sm-0 {\n padding-top: 0 !important;\n }\n .pr-sm-0,\n .px-sm-0 {\n padding-right: 0 !important;\n }\n .pb-sm-0,\n .py-sm-0 {\n padding-bottom: 0 !important;\n }\n .pl-sm-0,\n .px-sm-0 {\n padding-left: 0 !important;\n }\n .p-sm-1 {\n padding: 0.25rem !important;\n }\n .pt-sm-1,\n .py-sm-1 {\n padding-top: 0.25rem !important;\n }\n .pr-sm-1,\n .px-sm-1 {\n padding-right: 0.25rem !important;\n }\n .pb-sm-1,\n .py-sm-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-sm-1,\n .px-sm-1 {\n padding-left: 0.25rem !important;\n }\n .p-sm-2 {\n padding: 0.5rem !important;\n }\n .pt-sm-2,\n .py-sm-2 {\n padding-top: 0.5rem !important;\n }\n .pr-sm-2,\n .px-sm-2 {\n padding-right: 0.5rem !important;\n }\n .pb-sm-2,\n .py-sm-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-sm-2,\n .px-sm-2 {\n padding-left: 0.5rem !important;\n }\n .p-sm-3 {\n padding: 1rem !important;\n }\n .pt-sm-3,\n .py-sm-3 {\n padding-top: 1rem !important;\n }\n .pr-sm-3,\n .px-sm-3 {\n padding-right: 1rem !important;\n }\n .pb-sm-3,\n .py-sm-3 {\n padding-bottom: 1rem !important;\n }\n .pl-sm-3,\n .px-sm-3 {\n padding-left: 1rem !important;\n }\n .p-sm-4 {\n padding: 1.5rem !important;\n }\n .pt-sm-4,\n .py-sm-4 {\n padding-top: 1.5rem !important;\n }\n .pr-sm-4,\n .px-sm-4 {\n padding-right: 1.5rem !important;\n }\n .pb-sm-4,\n .py-sm-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-sm-4,\n .px-sm-4 {\n padding-left: 1.5rem !important;\n }\n .p-sm-5 {\n padding: 3rem !important;\n }\n .pt-sm-5,\n .py-sm-5 {\n padding-top: 3rem !important;\n }\n .pr-sm-5,\n .px-sm-5 {\n padding-right: 3rem !important;\n }\n .pb-sm-5,\n .py-sm-5 {\n padding-bottom: 3rem !important;\n }\n .pl-sm-5,\n .px-sm-5 {\n padding-left: 3rem !important;\n }\n .m-sm-auto {\n margin: auto !important;\n }\n .mt-sm-auto,\n .my-sm-auto {\n margin-top: auto !important;\n }\n .mr-sm-auto,\n .mx-sm-auto {\n margin-right: auto !important;\n }\n .mb-sm-auto,\n .my-sm-auto {\n margin-bottom: auto !important;\n }\n .ml-sm-auto,\n .mx-sm-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 768px) {\n .m-md-0 {\n margin: 0 !important;\n }\n .mt-md-0,\n .my-md-0 {\n margin-top: 0 !important;\n }\n .mr-md-0,\n .mx-md-0 {\n margin-right: 0 !important;\n }\n .mb-md-0,\n .my-md-0 {\n margin-bottom: 0 !important;\n }\n .ml-md-0,\n .mx-md-0 {\n margin-left: 0 !important;\n }\n .m-md-1 {\n margin: 0.25rem !important;\n }\n .mt-md-1,\n .my-md-1 {\n margin-top: 0.25rem !important;\n }\n .mr-md-1,\n .mx-md-1 {\n margin-right: 0.25rem !important;\n }\n .mb-md-1,\n .my-md-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-md-1,\n .mx-md-1 {\n margin-left: 0.25rem !important;\n }\n .m-md-2 {\n margin: 0.5rem !important;\n }\n .mt-md-2,\n .my-md-2 {\n margin-top: 0.5rem !important;\n }\n .mr-md-2,\n .mx-md-2 {\n margin-right: 0.5rem !important;\n }\n .mb-md-2,\n .my-md-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-md-2,\n .mx-md-2 {\n margin-left: 0.5rem !important;\n }\n .m-md-3 {\n margin: 1rem !important;\n }\n .mt-md-3,\n .my-md-3 {\n margin-top: 1rem !important;\n }\n .mr-md-3,\n .mx-md-3 {\n margin-right: 1rem !important;\n }\n .mb-md-3,\n .my-md-3 {\n margin-bottom: 1rem !important;\n }\n .ml-md-3,\n .mx-md-3 {\n margin-left: 1rem !important;\n }\n .m-md-4 {\n margin: 1.5rem !important;\n }\n .mt-md-4,\n .my-md-4 {\n margin-top: 1.5rem !important;\n }\n .mr-md-4,\n .mx-md-4 {\n margin-right: 1.5rem !important;\n }\n .mb-md-4,\n .my-md-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-md-4,\n .mx-md-4 {\n margin-left: 1.5rem !important;\n }\n .m-md-5 {\n margin: 3rem !important;\n }\n .mt-md-5,\n .my-md-5 {\n margin-top: 3rem !important;\n }\n .mr-md-5,\n .mx-md-5 {\n margin-right: 3rem !important;\n }\n .mb-md-5,\n .my-md-5 {\n margin-bottom: 3rem !important;\n }\n .ml-md-5,\n .mx-md-5 {\n margin-left: 3rem !important;\n }\n .p-md-0 {\n padding: 0 !important;\n }\n .pt-md-0,\n .py-md-0 {\n padding-top: 0 !important;\n }\n .pr-md-0,\n .px-md-0 {\n padding-right: 0 !important;\n }\n .pb-md-0,\n .py-md-0 {\n padding-bottom: 0 !important;\n }\n .pl-md-0,\n .px-md-0 {\n padding-left: 0 !important;\n }\n .p-md-1 {\n padding: 0.25rem !important;\n }\n .pt-md-1,\n .py-md-1 {\n padding-top: 0.25rem !important;\n }\n .pr-md-1,\n .px-md-1 {\n padding-right: 0.25rem !important;\n }\n .pb-md-1,\n .py-md-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-md-1,\n .px-md-1 {\n padding-left: 0.25rem !important;\n }\n .p-md-2 {\n padding: 0.5rem !important;\n }\n .pt-md-2,\n .py-md-2 {\n padding-top: 0.5rem !important;\n }\n .pr-md-2,\n .px-md-2 {\n padding-right: 0.5rem !important;\n }\n .pb-md-2,\n .py-md-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-md-2,\n .px-md-2 {\n padding-left: 0.5rem !important;\n }\n .p-md-3 {\n padding: 1rem !important;\n }\n .pt-md-3,\n .py-md-3 {\n padding-top: 1rem !important;\n }\n .pr-md-3,\n .px-md-3 {\n padding-right: 1rem !important;\n }\n .pb-md-3,\n .py-md-3 {\n padding-bottom: 1rem !important;\n }\n .pl-md-3,\n .px-md-3 {\n padding-left: 1rem !important;\n }\n .p-md-4 {\n padding: 1.5rem !important;\n }\n .pt-md-4,\n .py-md-4 {\n padding-top: 1.5rem !important;\n }\n .pr-md-4,\n .px-md-4 {\n padding-right: 1.5rem !important;\n }\n .pb-md-4,\n .py-md-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-md-4,\n .px-md-4 {\n padding-left: 1.5rem !important;\n }\n .p-md-5 {\n padding: 3rem !important;\n }\n .pt-md-5,\n .py-md-5 {\n padding-top: 3rem !important;\n }\n .pr-md-5,\n .px-md-5 {\n padding-right: 3rem !important;\n }\n .pb-md-5,\n .py-md-5 {\n padding-bottom: 3rem !important;\n }\n .pl-md-5,\n .px-md-5 {\n padding-left: 3rem !important;\n }\n .m-md-auto {\n margin: auto !important;\n }\n .mt-md-auto,\n .my-md-auto {\n margin-top: auto !important;\n }\n .mr-md-auto,\n .mx-md-auto {\n margin-right: auto !important;\n }\n .mb-md-auto,\n .my-md-auto {\n margin-bottom: auto !important;\n }\n .ml-md-auto,\n .mx-md-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 992px) {\n .m-lg-0 {\n margin: 0 !important;\n }\n .mt-lg-0,\n .my-lg-0 {\n margin-top: 0 !important;\n }\n .mr-lg-0,\n .mx-lg-0 {\n margin-right: 0 !important;\n }\n .mb-lg-0,\n .my-lg-0 {\n margin-bottom: 0 !important;\n }\n .ml-lg-0,\n .mx-lg-0 {\n margin-left: 0 !important;\n }\n .m-lg-1 {\n margin: 0.25rem !important;\n }\n .mt-lg-1,\n .my-lg-1 {\n margin-top: 0.25rem !important;\n }\n .mr-lg-1,\n .mx-lg-1 {\n margin-right: 0.25rem !important;\n }\n .mb-lg-1,\n .my-lg-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-lg-1,\n .mx-lg-1 {\n margin-left: 0.25rem !important;\n }\n .m-lg-2 {\n margin: 0.5rem !important;\n }\n .mt-lg-2,\n .my-lg-2 {\n margin-top: 0.5rem !important;\n }\n .mr-lg-2,\n .mx-lg-2 {\n margin-right: 0.5rem !important;\n }\n .mb-lg-2,\n .my-lg-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-lg-2,\n .mx-lg-2 {\n margin-left: 0.5rem !important;\n }\n .m-lg-3 {\n margin: 1rem !important;\n }\n .mt-lg-3,\n .my-lg-3 {\n margin-top: 1rem !important;\n }\n .mr-lg-3,\n .mx-lg-3 {\n margin-right: 1rem !important;\n }\n .mb-lg-3,\n .my-lg-3 {\n margin-bottom: 1rem !important;\n }\n .ml-lg-3,\n .mx-lg-3 {\n margin-left: 1rem !important;\n }\n .m-lg-4 {\n margin: 1.5rem !important;\n }\n .mt-lg-4,\n .my-lg-4 {\n margin-top: 1.5rem !important;\n }\n .mr-lg-4,\n .mx-lg-4 {\n margin-right: 1.5rem !important;\n }\n .mb-lg-4,\n .my-lg-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-lg-4,\n .mx-lg-4 {\n margin-left: 1.5rem !important;\n }\n .m-lg-5 {\n margin: 3rem !important;\n }\n .mt-lg-5,\n .my-lg-5 {\n margin-top: 3rem !important;\n }\n .mr-lg-5,\n .mx-lg-5 {\n margin-right: 3rem !important;\n }\n .mb-lg-5,\n .my-lg-5 {\n margin-bottom: 3rem !important;\n }\n .ml-lg-5,\n .mx-lg-5 {\n margin-left: 3rem !important;\n }\n .p-lg-0 {\n padding: 0 !important;\n }\n .pt-lg-0,\n .py-lg-0 {\n padding-top: 0 !important;\n }\n .pr-lg-0,\n .px-lg-0 {\n padding-right: 0 !important;\n }\n .pb-lg-0,\n .py-lg-0 {\n padding-bottom: 0 !important;\n }\n .pl-lg-0,\n .px-lg-0 {\n padding-left: 0 !important;\n }\n .p-lg-1 {\n padding: 0.25rem !important;\n }\n .pt-lg-1,\n .py-lg-1 {\n padding-top: 0.25rem !important;\n }\n .pr-lg-1,\n .px-lg-1 {\n padding-right: 0.25rem !important;\n }\n .pb-lg-1,\n .py-lg-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-lg-1,\n .px-lg-1 {\n padding-left: 0.25rem !important;\n }\n .p-lg-2 {\n padding: 0.5rem !important;\n }\n .pt-lg-2,\n .py-lg-2 {\n padding-top: 0.5rem !important;\n }\n .pr-lg-2,\n .px-lg-2 {\n padding-right: 0.5rem !important;\n }\n .pb-lg-2,\n .py-lg-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-lg-2,\n .px-lg-2 {\n padding-left: 0.5rem !important;\n }\n .p-lg-3 {\n padding: 1rem !important;\n }\n .pt-lg-3,\n .py-lg-3 {\n padding-top: 1rem !important;\n }\n .pr-lg-3,\n .px-lg-3 {\n padding-right: 1rem !important;\n }\n .pb-lg-3,\n .py-lg-3 {\n padding-bottom: 1rem !important;\n }\n .pl-lg-3,\n .px-lg-3 {\n padding-left: 1rem !important;\n }\n .p-lg-4 {\n padding: 1.5rem !important;\n }\n .pt-lg-4,\n .py-lg-4 {\n padding-top: 1.5rem !important;\n }\n .pr-lg-4,\n .px-lg-4 {\n padding-right: 1.5rem !important;\n }\n .pb-lg-4,\n .py-lg-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-lg-4,\n .px-lg-4 {\n padding-left: 1.5rem !important;\n }\n .p-lg-5 {\n padding: 3rem !important;\n }\n .pt-lg-5,\n .py-lg-5 {\n padding-top: 3rem !important;\n }\n .pr-lg-5,\n .px-lg-5 {\n padding-right: 3rem !important;\n }\n .pb-lg-5,\n .py-lg-5 {\n padding-bottom: 3rem !important;\n }\n .pl-lg-5,\n .px-lg-5 {\n padding-left: 3rem !important;\n }\n .m-lg-auto {\n margin: auto !important;\n }\n .mt-lg-auto,\n .my-lg-auto {\n margin-top: auto !important;\n }\n .mr-lg-auto,\n .mx-lg-auto {\n margin-right: auto !important;\n }\n .mb-lg-auto,\n .my-lg-auto {\n margin-bottom: auto !important;\n }\n .ml-lg-auto,\n .mx-lg-auto {\n margin-left: auto !important;\n }\n}\n\n@media (min-width: 1200px) {\n .m-xl-0 {\n margin: 0 !important;\n }\n .mt-xl-0,\n .my-xl-0 {\n margin-top: 0 !important;\n }\n .mr-xl-0,\n .mx-xl-0 {\n margin-right: 0 !important;\n }\n .mb-xl-0,\n .my-xl-0 {\n margin-bottom: 0 !important;\n }\n .ml-xl-0,\n .mx-xl-0 {\n margin-left: 0 !important;\n }\n .m-xl-1 {\n margin: 0.25rem !important;\n }\n .mt-xl-1,\n .my-xl-1 {\n margin-top: 0.25rem !important;\n }\n .mr-xl-1,\n .mx-xl-1 {\n margin-right: 0.25rem !important;\n }\n .mb-xl-1,\n .my-xl-1 {\n margin-bottom: 0.25rem !important;\n }\n .ml-xl-1,\n .mx-xl-1 {\n margin-left: 0.25rem !important;\n }\n .m-xl-2 {\n margin: 0.5rem !important;\n }\n .mt-xl-2,\n .my-xl-2 {\n margin-top: 0.5rem !important;\n }\n .mr-xl-2,\n .mx-xl-2 {\n margin-right: 0.5rem !important;\n }\n .mb-xl-2,\n .my-xl-2 {\n margin-bottom: 0.5rem !important;\n }\n .ml-xl-2,\n .mx-xl-2 {\n margin-left: 0.5rem !important;\n }\n .m-xl-3 {\n margin: 1rem !important;\n }\n .mt-xl-3,\n .my-xl-3 {\n margin-top: 1rem !important;\n }\n .mr-xl-3,\n .mx-xl-3 {\n margin-right: 1rem !important;\n }\n .mb-xl-3,\n .my-xl-3 {\n margin-bottom: 1rem !important;\n }\n .ml-xl-3,\n .mx-xl-3 {\n margin-left: 1rem !important;\n }\n .m-xl-4 {\n margin: 1.5rem !important;\n }\n .mt-xl-4,\n .my-xl-4 {\n margin-top: 1.5rem !important;\n }\n .mr-xl-4,\n .mx-xl-4 {\n margin-right: 1.5rem !important;\n }\n .mb-xl-4,\n .my-xl-4 {\n margin-bottom: 1.5rem !important;\n }\n .ml-xl-4,\n .mx-xl-4 {\n margin-left: 1.5rem !important;\n }\n .m-xl-5 {\n margin: 3rem !important;\n }\n .mt-xl-5,\n .my-xl-5 {\n margin-top: 3rem !important;\n }\n .mr-xl-5,\n .mx-xl-5 {\n margin-right: 3rem !important;\n }\n .mb-xl-5,\n .my-xl-5 {\n margin-bottom: 3rem !important;\n }\n .ml-xl-5,\n .mx-xl-5 {\n margin-left: 3rem !important;\n }\n .p-xl-0 {\n padding: 0 !important;\n }\n .pt-xl-0,\n .py-xl-0 {\n padding-top: 0 !important;\n }\n .pr-xl-0,\n .px-xl-0 {\n padding-right: 0 !important;\n }\n .pb-xl-0,\n .py-xl-0 {\n padding-bottom: 0 !important;\n }\n .pl-xl-0,\n .px-xl-0 {\n padding-left: 0 !important;\n }\n .p-xl-1 {\n padding: 0.25rem !important;\n }\n .pt-xl-1,\n .py-xl-1 {\n padding-top: 0.25rem !important;\n }\n .pr-xl-1,\n .px-xl-1 {\n padding-right: 0.25rem !important;\n }\n .pb-xl-1,\n .py-xl-1 {\n padding-bottom: 0.25rem !important;\n }\n .pl-xl-1,\n .px-xl-1 {\n padding-left: 0.25rem !important;\n }\n .p-xl-2 {\n padding: 0.5rem !important;\n }\n .pt-xl-2,\n .py-xl-2 {\n padding-top: 0.5rem !important;\n }\n .pr-xl-2,\n .px-xl-2 {\n padding-right: 0.5rem !important;\n }\n .pb-xl-2,\n .py-xl-2 {\n padding-bottom: 0.5rem !important;\n }\n .pl-xl-2,\n .px-xl-2 {\n padding-left: 0.5rem !important;\n }\n .p-xl-3 {\n padding: 1rem !important;\n }\n .pt-xl-3,\n .py-xl-3 {\n padding-top: 1rem !important;\n }\n .pr-xl-3,\n .px-xl-3 {\n padding-right: 1rem !important;\n }\n .pb-xl-3,\n .py-xl-3 {\n padding-bottom: 1rem !important;\n }\n .pl-xl-3,\n .px-xl-3 {\n padding-left: 1rem !important;\n }\n .p-xl-4 {\n padding: 1.5rem !important;\n }\n .pt-xl-4,\n .py-xl-4 {\n padding-top: 1.5rem !important;\n }\n .pr-xl-4,\n .px-xl-4 {\n padding-right: 1.5rem !important;\n }\n .pb-xl-4,\n .py-xl-4 {\n padding-bottom: 1.5rem !important;\n }\n .pl-xl-4,\n .px-xl-4 {\n padding-left: 1.5rem !important;\n }\n .p-xl-5 {\n padding: 3rem !important;\n }\n .pt-xl-5,\n .py-xl-5 {\n padding-top: 3rem !important;\n }\n .pr-xl-5,\n .px-xl-5 {\n padding-right: 3rem !important;\n }\n .pb-xl-5,\n .py-xl-5 {\n padding-bottom: 3rem !important;\n }\n .pl-xl-5,\n .px-xl-5 {\n padding-left: 3rem !important;\n }\n .m-xl-auto {\n margin: auto !important;\n }\n .mt-xl-auto,\n .my-xl-auto {\n margin-top: auto !important;\n }\n .mr-xl-auto,\n .mx-xl-auto {\n margin-right: auto !important;\n }\n .mb-xl-auto,\n .my-xl-auto {\n margin-bottom: auto !important;\n }\n .ml-xl-auto,\n .mx-xl-auto {\n margin-left: auto !important;\n }\n}\n\n.text-monospace {\n font-family: SFMono-Regular, Menlo, Monaco, Consolas, \"Liberation Mono\", \"Courier New\", monospace;\n}\n\n.text-justify {\n text-align: justify !important;\n}\n\n.text-nowrap {\n white-space: nowrap !important;\n}\n\n.text-truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.text-left {\n text-align: left !important;\n}\n\n.text-right {\n text-align: right !important;\n}\n\n.text-center {\n text-align: center !important;\n}\n\n@media (min-width: 576px) {\n .text-sm-left {\n text-align: left !important;\n }\n .text-sm-right {\n text-align: right !important;\n }\n .text-sm-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 768px) {\n .text-md-left {\n text-align: left !important;\n }\n .text-md-right {\n text-align: right !important;\n }\n .text-md-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 992px) {\n .text-lg-left {\n text-align: left !important;\n }\n .text-lg-right {\n text-align: right !important;\n }\n .text-lg-center {\n text-align: center !important;\n }\n}\n\n@media (min-width: 1200px) {\n .text-xl-left {\n text-align: left !important;\n }\n .text-xl-right {\n text-align: right !important;\n }\n .text-xl-center {\n text-align: center !important;\n }\n}\n\n.text-lowercase {\n text-transform: lowercase !important;\n}\n\n.text-uppercase {\n text-transform: uppercase !important;\n}\n\n.text-capitalize {\n text-transform: capitalize !important;\n}\n\n.font-weight-light {\n font-weight: 300 !important;\n}\n\n.font-weight-normal {\n font-weight: 400 !important;\n}\n\n.font-weight-bold {\n font-weight: 700 !important;\n}\n\n.font-italic {\n font-style: italic !important;\n}\n\n.text-white {\n color: #fff !important;\n}\n\n.text-primary {\n color: #007bff !important;\n}\n\na.text-primary:hover, a.text-primary:focus {\n color: #0062cc !important;\n}\n\n.text-secondary {\n color: #6c757d !important;\n}\n\na.text-secondary:hover, a.text-secondary:focus {\n color: #545b62 !important;\n}\n\n.text-success {\n color: #28a745 !important;\n}\n\na.text-success:hover, a.text-success:focus {\n color: #1e7e34 !important;\n}\n\n.text-info {\n color: #17a2b8 !important;\n}\n\na.text-info:hover, a.text-info:focus {\n color: #117a8b !important;\n}\n\n.text-warning {\n color: #ffc107 !important;\n}\n\na.text-warning:hover, a.text-warning:focus {\n color: #d39e00 !important;\n}\n\n.text-danger {\n color: #dc3545 !important;\n}\n\na.text-danger:hover, a.text-danger:focus {\n color: #bd2130 !important;\n}\n\n.text-light {\n color: #f8f9fa !important;\n}\n\na.text-light:hover, a.text-light:focus {\n color: #dae0e5 !important;\n}\n\n.text-dark {\n color: #343a40 !important;\n}\n\na.text-dark:hover, a.text-dark:focus {\n color: #1d2124 !important;\n}\n\n.text-body {\n color: #212529 !important;\n}\n\n.text-muted {\n color: #6c757d !important;\n}\n\n.text-black-50 {\n color: rgba(0, 0, 0, 0.5) !important;\n}\n\n.text-white-50 {\n color: rgba(255, 255, 255, 0.5) !important;\n}\n\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n\n.visible {\n visibility: visible !important;\n}\n\n.invisible {\n visibility: hidden !important;\n}\n\n@media print {\n *,\n *::before,\n *::after {\n text-shadow: none !important;\n box-shadow: none !important;\n }\n a:not(.btn) {\n text-decoration: underline;\n }\n abbr[title]::after {\n content: \" (\" attr(title) \")\";\n }\n pre {\n white-space: pre-wrap !important;\n }\n pre,\n blockquote {\n border: 1px solid #adb5bd;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n @page {\n size: a3;\n }\n body {\n min-width: 992px !important;\n }\n .container {\n min-width: 992px !important;\n }\n .navbar {\n display: none;\n }\n .badge {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #dee2e6 !important;\n }\n .table-dark {\n color: inherit;\n }\n .table-dark th,\n .table-dark td,\n .table-dark thead th,\n .table-dark tbody + tbody {\n border-color: #dee2e6;\n }\n .table .thead-dark th {\n color: inherit;\n border-color: #dee2e6;\n }\n}\n\n/*# sourceMappingURL=bootstrap.css.map */","// Hover mixin and `$enable-hover-media-query` are deprecated.\n//\n// Originally added during our alphas and maintained during betas, this mixin was\n// designed to prevent `:hover` stickiness on iOS-an issue where hover styles\n// would persist after initial touch.\n//\n// For backward compatibility, we've kept these mixins and updated them to\n// always return their regular pseudo-classes instead of a shimmed media query.\n//\n// Issue: https://github.com/twbs/bootstrap/issues/25195\n\n@mixin hover {\n &:hover { @content; }\n}\n\n@mixin hover-focus {\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin plain-hover-focus {\n &,\n &:hover,\n &:focus {\n @content;\n }\n}\n\n@mixin hover-focus-active {\n &:hover,\n &:focus,\n &:active {\n @content;\n }\n}\n","// stylelint-disable declaration-no-important, selector-list-comma-newline-after\n\n//\n// Headings\n//\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n margin-bottom: $headings-margin-bottom;\n font-family: $headings-font-family;\n font-weight: $headings-font-weight;\n line-height: $headings-line-height;\n color: $headings-color;\n}\n\nh1, .h1 { font-size: $h1-font-size; }\nh2, .h2 { font-size: $h2-font-size; }\nh3, .h3 { font-size: $h3-font-size; }\nh4, .h4 { font-size: $h4-font-size; }\nh5, .h5 { font-size: $h5-font-size; }\nh6, .h6 { font-size: $h6-font-size; }\n\n.lead {\n font-size: $lead-font-size;\n font-weight: $lead-font-weight;\n}\n\n// Type display classes\n.display-1 {\n font-size: $display1-size;\n font-weight: $display1-weight;\n line-height: $display-line-height;\n}\n.display-2 {\n font-size: $display2-size;\n font-weight: $display2-weight;\n line-height: $display-line-height;\n}\n.display-3 {\n font-size: $display3-size;\n font-weight: $display3-weight;\n line-height: $display-line-height;\n}\n.display-4 {\n font-size: $display4-size;\n font-weight: $display4-weight;\n line-height: $display-line-height;\n}\n\n\n//\n// Horizontal rules\n//\n\nhr {\n margin-top: $hr-margin-y;\n margin-bottom: $hr-margin-y;\n border: 0;\n border-top: $hr-border-width solid $hr-border-color;\n}\n\n\n//\n// Emphasis\n//\n\nsmall,\n.small {\n font-size: $small-font-size;\n font-weight: $font-weight-normal;\n}\n\nmark,\n.mark {\n padding: $mark-padding;\n background-color: $mark-bg;\n}\n\n\n//\n// Lists\n//\n\n.list-unstyled {\n @include list-unstyled;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n @include list-unstyled;\n}\n.list-inline-item {\n display: inline-block;\n\n &:not(:last-child) {\n margin-right: $list-inline-padding;\n }\n}\n\n\n//\n// Misc\n//\n\n// Builds on `abbr`\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n// Blockquotes\n.blockquote {\n margin-bottom: $spacer;\n font-size: $blockquote-font-size;\n}\n\n.blockquote-footer {\n display: block;\n font-size: 80%; // back to default font-size\n color: $blockquote-small-color;\n\n &::before {\n content: \"\\2014 \\00A0\"; // em dash, nbsp\n }\n}\n","// Lists\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n@mixin list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n","// Responsive images (ensure images don't scale beyond their parents)\n//\n// This is purposefully opt-in via an explicit class rather than being the default for all ``s.\n// We previously tried the \"images are responsive by default\" approach in Bootstrap v2,\n// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)\n// which weren't expecting the images within themselves to be involuntarily resized.\n// See also https://github.com/twbs/bootstrap/issues/18178\n.img-fluid {\n @include img-fluid;\n}\n\n\n// Image thumbnails\n.img-thumbnail {\n padding: $thumbnail-padding;\n background-color: $thumbnail-bg;\n border: $thumbnail-border-width solid $thumbnail-border-color;\n @include border-radius($thumbnail-border-radius);\n @include box-shadow($thumbnail-box-shadow);\n\n // Keep them at most 100% wide\n @include img-fluid;\n}\n\n//\n// Figures\n//\n\n.figure {\n // Ensures the caption's text aligns with the image.\n display: inline-block;\n}\n\n.figure-img {\n margin-bottom: ($spacer / 2);\n line-height: 1;\n}\n\n.figure-caption {\n font-size: $figure-caption-font-size;\n color: $figure-caption-color;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n\n@mixin img-fluid {\n // Part 1: Set a maximum relative to the parent\n max-width: 100%;\n // Part 2: Override the height to auto, otherwise images will be stretched\n // when setting a width and height attribute on the img element.\n height: auto;\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size.\n\n// stylelint-disable indentation, media-query-list-comma-newline-after\n@mixin img-retina($file-1x, $file-2x, $width-1x, $height-1x) {\n background-image: url($file-1x);\n\n // Autoprefixer takes care of adding -webkit-min-device-pixel-ratio and -o-min-device-pixel-ratio,\n // but doesn't convert dppx=>dpi.\n // There's no such thing as unprefixed min-device-pixel-ratio since it's nonstandard.\n // Compatibility info: https://caniuse.com/#feat=css-media-resolution\n @media only screen and (min-resolution: 192dpi), // IE9-11 don't support dppx\n only screen and (min-resolution: 2dppx) { // Standardized\n background-image: url($file-2x);\n background-size: $width-1x $height-1x;\n }\n}\n","// Single side border-radius\n\n@mixin border-radius($radius: $border-radius) {\n @if $enable-rounded {\n border-radius: $radius;\n }\n}\n\n@mixin border-top-radius($radius) {\n @if $enable-rounded {\n border-top-left-radius: $radius;\n border-top-right-radius: $radius;\n }\n}\n\n@mixin border-right-radius($radius) {\n @if $enable-rounded {\n border-top-right-radius: $radius;\n border-bottom-right-radius: $radius;\n }\n}\n\n@mixin border-bottom-radius($radius) {\n @if $enable-rounded {\n border-bottom-right-radius: $radius;\n border-bottom-left-radius: $radius;\n }\n}\n\n@mixin border-left-radius($radius) {\n @if $enable-rounded {\n border-top-left-radius: $radius;\n border-bottom-left-radius: $radius;\n }\n}\n","// Inline code\ncode {\n font-size: $code-font-size;\n color: $code-color;\n word-break: break-word;\n\n // Streamline the style when inside anchors to avoid broken underline and more\n a > & {\n color: inherit;\n }\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: $kbd-padding-y $kbd-padding-x;\n font-size: $kbd-font-size;\n color: $kbd-color;\n background-color: $kbd-bg;\n @include border-radius($border-radius-sm);\n @include box-shadow($kbd-box-shadow);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: $nested-kbd-font-weight;\n @include box-shadow(none);\n }\n}\n\n// Blocks of code\npre {\n display: block;\n font-size: $code-font-size;\n color: $pre-color;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n font-size: inherit;\n color: inherit;\n word-break: normal;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: $pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n@if $enable-grid-classes {\n .container {\n @include make-container();\n @include make-container-max-widths();\n }\n}\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but with 100% width for\n// fluid, full width layouts.\n\n@if $enable-grid-classes {\n .container-fluid {\n @include make-container();\n }\n}\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n@if $enable-grid-classes {\n .row {\n @include make-row();\n }\n\n // Remove the negative margin from default .row, then the horizontal padding\n // from all immediate children columns (to prevent runaway style inheritance).\n .no-gutters {\n margin-right: 0;\n margin-left: 0;\n\n > .col,\n > [class*=\"col-\"] {\n padding-right: 0;\n padding-left: 0;\n }\n }\n}\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n@if $enable-grid-classes {\n @include make-grid-columns();\n}\n","/// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n@mixin make-container() {\n width: 100%;\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n margin-right: auto;\n margin-left: auto;\n}\n\n\n// For each breakpoint, define the maximum width of the container in a media query\n@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {\n @each $breakpoint, $container-max-width in $max-widths {\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n max-width: $container-max-width;\n }\n }\n}\n\n@mixin make-row() {\n display: flex;\n flex-wrap: wrap;\n margin-right: ($grid-gutter-width / -2);\n margin-left: ($grid-gutter-width / -2);\n}\n\n@mixin make-col-ready() {\n position: relative;\n // Prevent columns from becoming too narrow when at smaller grid tiers by\n // always setting `width: 100%;`. This works because we use `flex` values\n // later on to override this initial width.\n width: 100%;\n min-height: 1px; // Prevent collapsing\n padding-right: ($grid-gutter-width / 2);\n padding-left: ($grid-gutter-width / 2);\n}\n\n@mixin make-col($size, $columns: $grid-columns) {\n flex: 0 0 percentage($size / $columns);\n // Add a `max-width` to ensure content within each column does not blow out\n // the width of the column. Applies to IE10+ and Firefox. Chrome and Safari\n // do not appear to require this.\n max-width: percentage($size / $columns);\n}\n\n@mixin make-col-offset($size, $columns: $grid-columns) {\n $num: $size / $columns;\n margin-left: if($num == 0, 0, percentage($num));\n}\n","// Breakpoint viewport sizes and media queries.\n//\n// Breakpoints are defined as a map of (name: minimum width), order from small to large:\n//\n// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)\n//\n// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.\n\n// Name of the next breakpoint, or null for the last breakpoint.\n//\n// >> breakpoint-next(sm)\n// md\n// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// md\n// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))\n// md\n@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {\n $n: index($breakpoint-names, $name);\n @return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);\n}\n\n// Minimum breakpoint width. Null for the smallest (first) breakpoint.\n//\n// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 576px\n@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {\n $min: map-get($breakpoints, $name);\n @return if($min != 0, $min, null);\n}\n\n// Maximum breakpoint width. Null for the largest (last) breakpoint.\n// The maximum value is calculated as the minimum of the next one less 0.02px\n// to work around the limitations of `min-` and `max-` prefixes and viewports with fractional widths.\n// See https://www.w3.org/TR/mediaqueries-4/#mq-min-max\n// Uses 0.02px rather than 0.01px to work around a current rounding bug in Safari.\n// See https://bugs.webkit.org/show_bug.cgi?id=178261\n//\n// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// 767.98px\n@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {\n $next: breakpoint-next($name, $breakpoints);\n @return if($next, breakpoint-min($next, $breakpoints) - .02px, null);\n}\n\n// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash in front.\n// Useful for making responsive utilities.\n//\n// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"\" (Returns a blank string)\n// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))\n// \"-sm\"\n@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {\n @return if(breakpoint-min($name, $breakpoints) == null, \"\", \"-#{$name}\");\n}\n\n// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.\n// Makes the @content apply to the given breakpoint and wider.\n@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n @if $min {\n @media (min-width: $min) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media of at most the maximum breakpoint width. No query for the largest breakpoint.\n// Makes the @content apply to the given breakpoint and narrower.\n@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {\n $max: breakpoint-max($name, $breakpoints);\n @if $max {\n @media (max-width: $max) {\n @content;\n }\n } @else {\n @content;\n }\n}\n\n// Media that spans multiple breakpoint widths.\n// Makes the @content apply between the min and max breakpoints\n@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($lower, $breakpoints);\n $max: breakpoint-max($upper, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($lower, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($upper, $breakpoints) {\n @content;\n }\n }\n}\n\n// Media between the breakpoint's minimum and maximum widths.\n// No minimum for the smallest breakpoint, and no maximum for the largest one.\n// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.\n@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {\n $min: breakpoint-min($name, $breakpoints);\n $max: breakpoint-max($name, $breakpoints);\n\n @if $min != null and $max != null {\n @media (min-width: $min) and (max-width: $max) {\n @content;\n }\n } @else if $max == null {\n @include media-breakpoint-up($name, $breakpoints) {\n @content;\n }\n } @else if $min == null {\n @include media-breakpoint-down($name, $breakpoints) {\n @content;\n }\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `$grid-columns`.\n\n@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {\n // Common properties for all breakpoints\n %grid-column {\n position: relative;\n width: 100%;\n min-height: 1px; // Prevent columns from collapsing when empty\n padding-right: ($gutter / 2);\n padding-left: ($gutter / 2);\n }\n\n @each $breakpoint in map-keys($breakpoints) {\n $infix: breakpoint-infix($breakpoint, $breakpoints);\n\n // Allow columns to stretch full width below their breakpoints\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @extend %grid-column;\n }\n }\n .col#{$infix},\n .col#{$infix}-auto {\n @extend %grid-column;\n }\n\n @include media-breakpoint-up($breakpoint, $breakpoints) {\n // Provide basic `.col-{bp}` classes for equal-width flexbox columns\n .col#{$infix} {\n flex-basis: 0;\n flex-grow: 1;\n max-width: 100%;\n }\n .col#{$infix}-auto {\n flex: 0 0 auto;\n width: auto;\n max-width: none; // Reset earlier grid tiers\n }\n\n @for $i from 1 through $columns {\n .col#{$infix}-#{$i} {\n @include make-col($i, $columns);\n }\n }\n\n .order#{$infix}-first { order: -1; }\n\n .order#{$infix}-last { order: $columns + 1; }\n\n @for $i from 0 through $columns {\n .order#{$infix}-#{$i} { order: $i; }\n }\n\n // `$columns - 1` because offsetting by the width of an entire row isn't possible\n @for $i from 0 through ($columns - 1) {\n @if not ($infix == \"\" and $i == 0) { // Avoid emitting useless .offset-0\n .offset#{$infix}-#{$i} {\n @include make-col-offset($i, $columns);\n }\n }\n }\n }\n }\n}\n","//\n// Basic Bootstrap table\n//\n\n.table {\n width: 100%;\n margin-bottom: $spacer;\n background-color: $table-bg; // Reset for nesting within parents with `background-color`.\n\n th,\n td {\n padding: $table-cell-padding;\n vertical-align: top;\n border-top: $table-border-width solid $table-border-color;\n }\n\n thead th {\n vertical-align: bottom;\n border-bottom: (2 * $table-border-width) solid $table-border-color;\n }\n\n tbody + tbody {\n border-top: (2 * $table-border-width) solid $table-border-color;\n }\n\n .table {\n background-color: $body-bg;\n }\n}\n\n\n//\n// Condensed table w/ half padding\n//\n\n.table-sm {\n th,\n td {\n padding: $table-cell-padding-sm;\n }\n}\n\n\n// Border versions\n//\n// Add or remove borders all around the table and between all the columns.\n\n.table-bordered {\n border: $table-border-width solid $table-border-color;\n\n th,\n td {\n border: $table-border-width solid $table-border-color;\n }\n\n thead {\n th,\n td {\n border-bottom-width: (2 * $table-border-width);\n }\n }\n}\n\n.table-borderless {\n th,\n td,\n thead th,\n tbody + tbody {\n border: 0;\n }\n}\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n tbody tr:nth-of-type(#{$table-striped-order}) {\n background-color: $table-accent-bg;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n tbody tr {\n @include hover {\n background-color: $table-hover-bg;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n@each $color, $value in $theme-colors {\n @include table-row-variant($color, theme-color-level($color, -9));\n}\n\n@include table-row-variant(active, $table-active-bg);\n\n\n// Dark styles\n//\n// Same table markup, but inverted color scheme: dark background and light text.\n\n// stylelint-disable-next-line no-duplicate-selectors\n.table {\n .thead-dark {\n th {\n color: $table-dark-color;\n background-color: $table-dark-bg;\n border-color: $table-dark-border-color;\n }\n }\n\n .thead-light {\n th {\n color: $table-head-color;\n background-color: $table-head-bg;\n border-color: $table-border-color;\n }\n }\n}\n\n.table-dark {\n color: $table-dark-color;\n background-color: $table-dark-bg;\n\n th,\n td,\n thead th {\n border-color: $table-dark-border-color;\n }\n\n &.table-bordered {\n border: 0;\n }\n\n &.table-striped {\n tbody tr:nth-of-type(odd) {\n background-color: $table-dark-accent-bg;\n }\n }\n\n &.table-hover {\n tbody tr {\n @include hover {\n background-color: $table-dark-hover-bg;\n }\n }\n }\n}\n\n\n// Responsive tables\n//\n// Generate series of `.table-responsive-*` classes for configuring the screen\n// size of where your table will overflow.\n\n.table-responsive {\n @each $breakpoint in map-keys($grid-breakpoints) {\n $next: breakpoint-next($breakpoint, $grid-breakpoints);\n $infix: breakpoint-infix($next, $grid-breakpoints);\n\n &#{$infix} {\n @include media-breakpoint-down($breakpoint) {\n display: block;\n width: 100%;\n overflow-x: auto;\n -webkit-overflow-scrolling: touch;\n -ms-overflow-style: -ms-autohiding-scrollbar; // See https://github.com/twbs/bootstrap/pull/10057\n\n // Prevent double border on horizontal scroll due to use of `display: block;`\n > .table-bordered {\n border: 0;\n }\n }\n }\n }\n}\n","// Tables\n\n@mixin table-row-variant($state, $background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table-#{$state} {\n &,\n > th,\n > td {\n background-color: $background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover {\n $hover-background: darken($background, 5%);\n\n .table-#{$state} {\n @include hover {\n background-color: $hover-background;\n\n > td,\n > th {\n background-color: $hover-background;\n }\n }\n }\n }\n}\n","// Bootstrap functions\n//\n// Utility mixins and functions for evaluating source code across our variables, maps, and mixins.\n\n// Ascending\n// Used to evaluate Sass maps like our grid breakpoints.\n@mixin _assert-ascending($map, $map-name) {\n $prev-key: null;\n $prev-num: null;\n @each $key, $num in $map {\n @if $prev-num == null {\n // Do nothing\n } @else if not comparable($prev-num, $num) {\n @warn \"Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !\";\n } @else if $prev-num >= $num {\n @warn \"Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !\";\n }\n $prev-key: $key;\n $prev-num: $num;\n }\n}\n\n// Starts at zero\n// Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0.\n@mixin _assert-starts-at-zero($map) {\n $values: map-values($map);\n $first-value: nth($values, 1);\n @if $first-value != 0 {\n @warn \"First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}.\";\n }\n}\n\n// Replace `$search` with `$replace` in `$string`\n// Used on our SVG icon backgrounds for custom forms.\n//\n// @author Hugo Giraudel\n// @param {String} $string - Initial string\n// @param {String} $search - Substring to replace\n// @param {String} $replace ('') - New value\n// @return {String} - Updated string\n@function str-replace($string, $search, $replace: \"\") {\n $index: str-index($string, $search);\n\n @if $index {\n @return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);\n }\n\n @return $string;\n}\n\n// Color contrast\n@function color-yiq($color) {\n $r: red($color);\n $g: green($color);\n $b: blue($color);\n\n $yiq: (($r * 299) + ($g * 587) + ($b * 114)) / 1000;\n\n @if ($yiq >= $yiq-contrasted-threshold) {\n @return $yiq-text-dark;\n } @else {\n @return $yiq-text-light;\n }\n}\n\n// Retrieve color Sass maps\n@function color($key: \"blue\") {\n @return map-get($colors, $key);\n}\n\n@function theme-color($key: \"primary\") {\n @return map-get($theme-colors, $key);\n}\n\n@function gray($key: \"100\") {\n @return map-get($grays, $key);\n}\n\n// Request a theme color level\n@function theme-color-level($color-name: \"primary\", $level: 0) {\n $color: theme-color($color-name);\n $color-base: if($level > 0, $black, $white);\n $level: abs($level);\n\n @return mix($color-base, $color, $level * $theme-color-interval);\n}\n","// stylelint-disable selector-no-qualifying-type\n\n//\n// Textual form controls\n//\n\n.form-control {\n display: block;\n width: 100%;\n height: $input-height;\n padding: $input-padding-y $input-padding-x;\n font-size: $font-size-base;\n line-height: $input-line-height;\n color: $input-color;\n background-color: $input-bg;\n background-clip: padding-box;\n border: $input-border-width solid $input-border-color;\n\n // Note: This has no effect on `s in CSS.\n @if $enable-rounded {\n // Manually use the if/else instead of the mixin to account for iOS override\n border-radius: $input-border-radius;\n } @else {\n // Otherwise undo the iOS default\n border-radius: 0;\n }\n\n @include box-shadow($input-box-shadow);\n @include transition($input-transition);\n\n // Unstyle the caret on ` receives focus\n // in IE and (under certain conditions) Edge, as it looks bad and cannot be made to\n // match the appearance of the native widget.\n // See https://github.com/twbs/bootstrap/issues/19398.\n color: $input-color;\n background-color: $input-bg;\n }\n}\n\n// Make file inputs better match text inputs by forcing them to new lines.\n.form-control-file,\n.form-control-range {\n display: block;\n width: 100%;\n}\n\n\n//\n// Labels\n//\n\n// For use with horizontal and inline forms, when you need the label (or legend)\n// text to align with the form controls.\n.col-form-label {\n padding-top: calc(#{$input-padding-y} + #{$input-border-width});\n padding-bottom: calc(#{$input-padding-y} + #{$input-border-width});\n margin-bottom: 0; // Override the `
+
+
+
+
+
+
+ +
+ +
+
+
+ + + diff --git a/Erupe/www/erupe/js/charsel.js b/Erupe/www/erupe/js/charsel.js new file mode 100644 index 000000000..3023d0312 --- /dev/null +++ b/Erupe/www/erupe/js/charsel.js @@ -0,0 +1,230 @@ +var DoOnceActive = true; +function createNormalAlert(message) { + parent.postMessage(message, "*"); +} +function createGoodAlert(message) { + parent.postMessage(message, "*"); +} +function createErrorAlert(message) { + parent.postMessage(message, "*"); +} +function createCharListItem(name, uid, weapon, HR, GR, lastLogin, sex) { + var icon; + var active = "active"; + const unixTimestamp = lastLogin; + const milliseconds = unixTimestamp * 1000; + const dateObject = new Date(milliseconds); + const humanDateFormat = dateObject.toLocaleString(); + dateObject.toLocaleString("en-US", {weekday: "long"}); + dateObject.toLocaleString("en-US", {month: "long"}); + dateObject.toLocaleString("en-US", {day: "numeric"}); + dateObject.toLocaleString("en-US", {year: "numeric"}); + dateObject.toLocaleString("en-US", {timeZoneName: "short"}); + lastLogin = humanDateFormat; + lastLogin = lastLogin.split(' ')[0]; + if (sex == "M"){ + sex = "♂"; + } + else{ + sex = "♀"; + } + if (HR > 999){ + HR = 999; + } + if (GR > 999){ + GR = "999"; + } + + if (weapon == "片手剣"){ + weapon = "Sword & Shield"; + icon = "./ressources/icons/SS.png"; + } + else if (weapon == "双剣"){ + weapon = "Dual Swords"; + icon = "./ressources/icons/DS.png"; + } + else if (weapon == "大剣"){ + weapon = "Great Sword"; + icon = "./ressources/icons/GS.png"; + } + else if (weapon == "太刀"){ + weapon = "Long Sword"; + icon = "./ressources/icons/LS.png"; + } + else if (weapon == "ハンマー"){ + weapon = "Hammer"; + icon = "./ressources/icons/H.png"; + } + else if (weapon == "狩猟笛"){ + weapon = "Hunting Horn"; + icon = "./ressources/icons/HH.png"; + } + else if (weapon == "ランス"){ + weapon = "Lance"; + icon = "./ressources/icons/L.png"; + } + else if (weapon == "ガンランス"){ + weapon = "Gunlance"; + icon = "./ressources/icons/GL.png"; + } + else if (weapon == "穿龍棍"){ + weapon = "Tonfa"; + icon = "./ressources/icons/T.png"; + } + else if (weapon == "スラッシュアックスF"){ + weapon = "Switch Axe F"; + icon = "./ressources/icons/SAF.png"; + } + else if (weapon == "マグネットスパイク"){ + weapon = "Magnet Spike"; + icon = "./ressources/icons/MS.png"; + } + else if (weapon == "ヘビィボウガン"){ + weapon = "Heavy Bowgun"; + icon = "./ressources/icons/HS.png"; + } + else if (weapon == "ライトボウガン"){ + weapon = "Light Bowgun"; + icon = "./ressources/icons/LB.png"; + } + else if (weapon == "弓"){ + weapon = "Bow"; + icon = "./ressources/icons/B.png"; + } + else{ + weapon = "Unknown" + icon = "./ressources/icons/null.png"; + } + + if (DoOnceActive){ + DoOnceActive = false; + var topDiv = $('
') + .attr("href", "#") + .attr("uid", uid) + .addClass("char-list-entry list-group-item list-group-item-action flex-column align-items-start active"); + } + else{ + var topDiv = $('
') + .attr("href", "#") + .attr("uid", uid) + .addClass("char-list-entry list-group-item list-group-item-action flex-column align-items-start"); + } + var topLine = $('
') + .addClass("Name_Player") + .append($('

').addClass("mb-1").text(name) + ); + var bottomLine = $('
') + .addClass("Info") + .append($('
').prepend($('',{id:'theImg',src:icon}))) + .append($('
').text('Current Weapon')) + .append($('
').text(weapon)) + .append($('
').text('HR' + HR)) + .append($('
').text('GR' + GR)) + .append($('
').text(sex)) + .append($('
').text('ID: ' + uid)) + .append($('
').text('LastLogin ' + lastLogin)); + topDiv.append(topLine); + topDiv.append(bottomLine); + $("#characterlist").append(topDiv); +} +$(function () { + try { + var charInfo = window.external.getCharacterInfo(); + } catch (e) { + createErrorAlert("Error on getCharacterInfo!"); + } + try { + $xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); + $xmlDoc.async = "false"; + $xmlDoc.loadXML(charInfo); + $xml = $($xmlDoc); + } catch (e) { + createErrorAlert("Error parsing character info xml!" + e); + } + + try { + $($xml).find("Character").each(function () { + createCharListItem( + $(this).attr('name'), + $(this).attr('uid'), + $(this).attr('weapon'), + $(this).attr('HR'), + $(this).attr('GR'), + $(this).attr('lastLogin'), + $(this).attr('sex') + ); + }); + } catch (e) { + createErrorAlert("Error searching character info xml!"); + } + + $(".char-list-entry").click(function () { + if (!$(this).hasClass("active")) { + $(".char-list-entry.active").removeClass("active"); + $(this).addClass("active"); + } + }); + +$(function() { + var selectedUid = $(".char-list-entry.active").attr("uid"); + $("#bt_new_char").on("click", function(e) { + alert("NOT WORK"); + }); + $("#bt_delete_char").on("click", function(e) { + alert("NOT WORK"); + }); +}); + +$("#bt_confirm").on("click", function () { + try{ + elementID = parent.document.getElementById("BlockGlobal"); + elementID.style.display = "block"; + } catch(e) { + alert(e); + } + var selectedUid = $(".char-list-entry.active").attr("uid"); + try { + window.external.selectCharacter(selectedUid, selectedUid) + } catch (e) { + createErrorAlert("Error on select character!"); + try{ + elementID = parent.document.getElementById("BlockGlobal"); + elementID.style.display = "none"; + } catch(e) { + alert(e); + } + } + setTimeout(function () { + window.external.exitLauncher(); + }, 3000); + }); +}); + +// Enable to read JP text +function isKanji(ch) { + return (ch >= "\u4e00" && ch <= "\u9faf") || + (ch >= "\u3400" && ch <= "\u4dbf"); +} + +function accumulativeParser(str, condition) { + let accumulations = []; + let accumulator = ""; + + for (let i = 0; i < str.length; ++i) { + let ch = str[i]; + + if (condition(x)) { + accumulator += ch; + } else if (accumulator !== "") { + accumulations.push(accumulator); + accumulator = ""; + } + } + return accumulations; +} + +function parseKanjiCompounds(str) { + return accumulativeParser(str, isKanji); +} + + diff --git a/Erupe/www/erupe/js/dependencies/bootstrap.bundle.js b/Erupe/www/erupe/js/dependencies/bootstrap.bundle.js new file mode 100644 index 000000000..e8b832da6 --- /dev/null +++ b/Erupe/www/erupe/js/dependencies/bootstrap.bundle.js @@ -0,0 +1,6461 @@ +/*! + * Bootstrap v4.1.3 (https://getbootstrap.com/) + * Copyright 2011-2018 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jquery')) : + typeof define === 'function' && define.amd ? define(['exports', 'jquery'], factory) : + (factory((global.bootstrap = {}),global.jQuery)); +}(this, (function (exports,$) { 'use strict'; + + $ = $ && $.hasOwnProperty('default') ? $['default'] : $; + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; + } + + function _objectSpread(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + var ownKeys = Object.keys(source); + + if (typeof Object.getOwnPropertySymbols === 'function') { + ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { + return Object.getOwnPropertyDescriptor(source, sym).enumerable; + })); + } + + ownKeys.forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } + + return target; + } + + function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + subClass.__proto__ = superClass; + } + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): util.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Util = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Private TransitionEnd Helpers + * ------------------------------------------------------------------------ + */ + var TRANSITION_END = 'transitionend'; + var MAX_UID = 1000000; + var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp) + + function toType(obj) { + return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); + } + + function getSpecialTransitionEndEvent() { + return { + bindType: TRANSITION_END, + delegateType: TRANSITION_END, + handle: function handle(event) { + if ($$$1(event.target).is(this)) { + return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params + } + + return undefined; // eslint-disable-line no-undefined + } + }; + } + + function transitionEndEmulator(duration) { + var _this = this; + + var called = false; + $$$1(this).one(Util.TRANSITION_END, function () { + called = true; + }); + setTimeout(function () { + if (!called) { + Util.triggerTransitionEnd(_this); + } + }, duration); + return this; + } + + function setTransitionEndSupport() { + $$$1.fn.emulateTransitionEnd = transitionEndEmulator; + $$$1.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); + } + /** + * -------------------------------------------------------------------------- + * Public Util Api + * -------------------------------------------------------------------------- + */ + + + var Util = { + TRANSITION_END: 'bsTransitionEnd', + getUID: function getUID(prefix) { + do { + // eslint-disable-next-line no-bitwise + prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here + } while (document.getElementById(prefix)); + + return prefix; + }, + getSelectorFromElement: function getSelectorFromElement(element) { + var selector = element.getAttribute('data-target'); + + if (!selector || selector === '#') { + selector = element.getAttribute('href') || ''; + } + + try { + return document.querySelector(selector) ? selector : null; + } catch (err) { + return null; + } + }, + getTransitionDurationFromElement: function getTransitionDurationFromElement(element) { + if (!element) { + return 0; + } // Get transition-duration of the element + + + var transitionDuration = $$$1(element).css('transition-duration'); + var floatTransitionDuration = parseFloat(transitionDuration); // Return 0 if element or transition duration is not found + + if (!floatTransitionDuration) { + return 0; + } // If multiple durations are defined, take the first + + + transitionDuration = transitionDuration.split(',')[0]; + return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER; + }, + reflow: function reflow(element) { + return element.offsetHeight; + }, + triggerTransitionEnd: function triggerTransitionEnd(element) { + $$$1(element).trigger(TRANSITION_END); + }, + // TODO: Remove in v5 + supportsTransitionEnd: function supportsTransitionEnd() { + return Boolean(TRANSITION_END); + }, + isElement: function isElement(obj) { + return (obj[0] || obj).nodeType; + }, + typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) { + for (var property in configTypes) { + if (Object.prototype.hasOwnProperty.call(configTypes, property)) { + var expectedTypes = configTypes[property]; + var value = config[property]; + var valueType = value && Util.isElement(value) ? 'element' : toType(value); + + if (!new RegExp(expectedTypes).test(valueType)) { + throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); + } + } + } + } + }; + setTransitionEndSupport(); + return Util; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): alert.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Alert = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'alert'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.alert'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var Selector = { + DISMISS: '[data-dismiss="alert"]' + }; + var Event = { + CLOSE: "close" + EVENT_KEY, + CLOSED: "closed" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + ALERT: 'alert', + FADE: 'fade', + SHOW: 'show' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Alert = + /*#__PURE__*/ + function () { + function Alert(element) { + this._element = element; + } // Getters + + + var _proto = Alert.prototype; + + // Public + _proto.close = function close(element) { + var rootElement = this._element; + + if (element) { + rootElement = this._getRootElement(element); + } + + var customEvent = this._triggerCloseEvent(rootElement); + + if (customEvent.isDefaultPrevented()) { + return; + } + + this._removeElement(rootElement); + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + this._element = null; + }; // Private + + + _proto._getRootElement = function _getRootElement(element) { + var selector = Util.getSelectorFromElement(element); + var parent = false; + + if (selector) { + parent = document.querySelector(selector); + } + + if (!parent) { + parent = $$$1(element).closest("." + ClassName.ALERT)[0]; + } + + return parent; + }; + + _proto._triggerCloseEvent = function _triggerCloseEvent(element) { + var closeEvent = $$$1.Event(Event.CLOSE); + $$$1(element).trigger(closeEvent); + return closeEvent; + }; + + _proto._removeElement = function _removeElement(element) { + var _this = this; + + $$$1(element).removeClass(ClassName.SHOW); + + if (!$$$1(element).hasClass(ClassName.FADE)) { + this._destroyElement(element); + + return; + } + + var transitionDuration = Util.getTransitionDurationFromElement(element); + $$$1(element).one(Util.TRANSITION_END, function (event) { + return _this._destroyElement(element, event); + }).emulateTransitionEnd(transitionDuration); + }; + + _proto._destroyElement = function _destroyElement(element) { + $$$1(element).detach().trigger(Event.CLOSED).remove(); + }; // Static + + + Alert._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var $element = $$$1(this); + var data = $element.data(DATA_KEY); + + if (!data) { + data = new Alert(this); + $element.data(DATA_KEY, data); + } + + if (config === 'close') { + data[config](this); + } + }); + }; + + Alert._handleDismiss = function _handleDismiss(alertInstance) { + return function (event) { + if (event) { + event.preventDefault(); + } + + alertInstance.close(this); + }; + }; + + _createClass(Alert, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }]); + + return Alert; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert())); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Alert._jQueryInterface; + $$$1.fn[NAME].Constructor = Alert; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Alert._jQueryInterface; + }; + + return Alert; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): button.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Button = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'button'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.button'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ClassName = { + ACTIVE: 'active', + BUTTON: 'btn', + FOCUS: 'focus' + }; + var Selector = { + DATA_TOGGLE_CARROT: '[data-toggle^="button"]', + DATA_TOGGLE: '[data-toggle="buttons"]', + INPUT: 'input', + ACTIVE: '.active', + BUTTON: '.btn' + }; + var Event = { + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, + FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY + DATA_API_KEY + " " + ("blur" + EVENT_KEY + DATA_API_KEY) + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Button = + /*#__PURE__*/ + function () { + function Button(element) { + this._element = element; + } // Getters + + + var _proto = Button.prototype; + + // Public + _proto.toggle = function toggle() { + var triggerChangeEvent = true; + var addAriaPressed = true; + var rootElement = $$$1(this._element).closest(Selector.DATA_TOGGLE)[0]; + + if (rootElement) { + var input = this._element.querySelector(Selector.INPUT); + + if (input) { + if (input.type === 'radio') { + if (input.checked && this._element.classList.contains(ClassName.ACTIVE)) { + triggerChangeEvent = false; + } else { + var activeElement = rootElement.querySelector(Selector.ACTIVE); + + if (activeElement) { + $$$1(activeElement).removeClass(ClassName.ACTIVE); + } + } + } + + if (triggerChangeEvent) { + if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) { + return; + } + + input.checked = !this._element.classList.contains(ClassName.ACTIVE); + $$$1(input).trigger('change'); + } + + input.focus(); + addAriaPressed = false; + } + } + + if (addAriaPressed) { + this._element.setAttribute('aria-pressed', !this._element.classList.contains(ClassName.ACTIVE)); + } + + if (triggerChangeEvent) { + $$$1(this._element).toggleClass(ClassName.ACTIVE); + } + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + this._element = null; + }; // Static + + + Button._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + if (!data) { + data = new Button(this); + $$$1(this).data(DATA_KEY, data); + } + + if (config === 'toggle') { + data[config](); + } + }); + }; + + _createClass(Button, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }]); + + return Button; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { + event.preventDefault(); + var button = event.target; + + if (!$$$1(button).hasClass(ClassName.BUTTON)) { + button = $$$1(button).closest(Selector.BUTTON); + } + + Button._jQueryInterface.call($$$1(button), 'toggle'); + }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) { + var button = $$$1(event.target).closest(Selector.BUTTON)[0]; + $$$1(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Button._jQueryInterface; + $$$1.fn[NAME].Constructor = Button; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Button._jQueryInterface; + }; + + return Button; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): carousel.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Carousel = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'carousel'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.carousel'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key + + var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key + + var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch + + var Default = { + interval: 5000, + keyboard: true, + slide: false, + pause: 'hover', + wrap: true + }; + var DefaultType = { + interval: '(number|boolean)', + keyboard: 'boolean', + slide: '(boolean|string)', + pause: '(string|boolean)', + wrap: 'boolean' + }; + var Direction = { + NEXT: 'next', + PREV: 'prev', + LEFT: 'left', + RIGHT: 'right' + }; + var Event = { + SLIDE: "slide" + EVENT_KEY, + SLID: "slid" + EVENT_KEY, + KEYDOWN: "keydown" + EVENT_KEY, + MOUSEENTER: "mouseenter" + EVENT_KEY, + MOUSELEAVE: "mouseleave" + EVENT_KEY, + TOUCHEND: "touchend" + EVENT_KEY, + LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + CAROUSEL: 'carousel', + ACTIVE: 'active', + SLIDE: 'slide', + RIGHT: 'carousel-item-right', + LEFT: 'carousel-item-left', + NEXT: 'carousel-item-next', + PREV: 'carousel-item-prev', + ITEM: 'carousel-item' + }; + var Selector = { + ACTIVE: '.active', + ACTIVE_ITEM: '.active.carousel-item', + ITEM: '.carousel-item', + NEXT_PREV: '.carousel-item-next, .carousel-item-prev', + INDICATORS: '.carousel-indicators', + DATA_SLIDE: '[data-slide], [data-slide-to]', + DATA_RIDE: '[data-ride="carousel"]' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Carousel = + /*#__PURE__*/ + function () { + function Carousel(element, config) { + this._items = null; + this._interval = null; + this._activeElement = null; + this._isPaused = false; + this._isSliding = false; + this.touchTimeout = null; + this._config = this._getConfig(config); + this._element = $$$1(element)[0]; + this._indicatorsElement = this._element.querySelector(Selector.INDICATORS); + + this._addEventListeners(); + } // Getters + + + var _proto = Carousel.prototype; + + // Public + _proto.next = function next() { + if (!this._isSliding) { + this._slide(Direction.NEXT); + } + }; + + _proto.nextWhenVisible = function nextWhenVisible() { + // Don't call next when the page isn't visible + // or the carousel or its parent isn't visible + if (!document.hidden && $$$1(this._element).is(':visible') && $$$1(this._element).css('visibility') !== 'hidden') { + this.next(); + } + }; + + _proto.prev = function prev() { + if (!this._isSliding) { + this._slide(Direction.PREV); + } + }; + + _proto.pause = function pause(event) { + if (!event) { + this._isPaused = true; + } + + if (this._element.querySelector(Selector.NEXT_PREV)) { + Util.triggerTransitionEnd(this._element); + this.cycle(true); + } + + clearInterval(this._interval); + this._interval = null; + }; + + _proto.cycle = function cycle(event) { + if (!event) { + this._isPaused = false; + } + + if (this._interval) { + clearInterval(this._interval); + this._interval = null; + } + + if (this._config.interval && !this._isPaused) { + this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval); + } + }; + + _proto.to = function to(index) { + var _this = this; + + this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM); + + var activeIndex = this._getItemIndex(this._activeElement); + + if (index > this._items.length - 1 || index < 0) { + return; + } + + if (this._isSliding) { + $$$1(this._element).one(Event.SLID, function () { + return _this.to(index); + }); + return; + } + + if (activeIndex === index) { + this.pause(); + this.cycle(); + return; + } + + var direction = index > activeIndex ? Direction.NEXT : Direction.PREV; + + this._slide(direction, this._items[index]); + }; + + _proto.dispose = function dispose() { + $$$1(this._element).off(EVENT_KEY); + $$$1.removeData(this._element, DATA_KEY); + this._items = null; + this._config = null; + this._element = null; + this._interval = null; + this._isPaused = null; + this._isSliding = null; + this._activeElement = null; + this._indicatorsElement = null; + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, config); + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._addEventListeners = function _addEventListeners() { + var _this2 = this; + + if (this._config.keyboard) { + $$$1(this._element).on(Event.KEYDOWN, function (event) { + return _this2._keydown(event); + }); + } + + if (this._config.pause === 'hover') { + $$$1(this._element).on(Event.MOUSEENTER, function (event) { + return _this2.pause(event); + }).on(Event.MOUSELEAVE, function (event) { + return _this2.cycle(event); + }); + + if ('ontouchstart' in document.documentElement) { + // If it's a touch-enabled device, mouseenter/leave are fired as + // part of the mouse compatibility events on first tap - the carousel + // would stop cycling until user tapped out of it; + // here, we listen for touchend, explicitly pause the carousel + // (as if it's the second time we tap on it, mouseenter compat event + // is NOT fired) and after a timeout (to allow for mouse compatibility + // events to fire) we explicitly restart cycling + $$$1(this._element).on(Event.TOUCHEND, function () { + _this2.pause(); + + if (_this2.touchTimeout) { + clearTimeout(_this2.touchTimeout); + } + + _this2.touchTimeout = setTimeout(function (event) { + return _this2.cycle(event); + }, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval); + }); + } + } + }; + + _proto._keydown = function _keydown(event) { + if (/input|textarea/i.test(event.target.tagName)) { + return; + } + + switch (event.which) { + case ARROW_LEFT_KEYCODE: + event.preventDefault(); + this.prev(); + break; + + case ARROW_RIGHT_KEYCODE: + event.preventDefault(); + this.next(); + break; + + default: + } + }; + + _proto._getItemIndex = function _getItemIndex(element) { + this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM)) : []; + return this._items.indexOf(element); + }; + + _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) { + var isNextDirection = direction === Direction.NEXT; + var isPrevDirection = direction === Direction.PREV; + + var activeIndex = this._getItemIndex(activeElement); + + var lastItemIndex = this._items.length - 1; + var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex; + + if (isGoingToWrap && !this._config.wrap) { + return activeElement; + } + + var delta = direction === Direction.PREV ? -1 : 1; + var itemIndex = (activeIndex + delta) % this._items.length; + return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex]; + }; + + _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) { + var targetIndex = this._getItemIndex(relatedTarget); + + var fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM)); + + var slideEvent = $$$1.Event(Event.SLIDE, { + relatedTarget: relatedTarget, + direction: eventDirectionName, + from: fromIndex, + to: targetIndex + }); + $$$1(this._element).trigger(slideEvent); + return slideEvent; + }; + + _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) { + if (this._indicatorsElement) { + var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE)); + $$$1(indicators).removeClass(ClassName.ACTIVE); + + var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)]; + + if (nextIndicator) { + $$$1(nextIndicator).addClass(ClassName.ACTIVE); + } + } + }; + + _proto._slide = function _slide(direction, element) { + var _this3 = this; + + var activeElement = this._element.querySelector(Selector.ACTIVE_ITEM); + + var activeElementIndex = this._getItemIndex(activeElement); + + var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement); + + var nextElementIndex = this._getItemIndex(nextElement); + + var isCycling = Boolean(this._interval); + var directionalClassName; + var orderClassName; + var eventDirectionName; + + if (direction === Direction.NEXT) { + directionalClassName = ClassName.LEFT; + orderClassName = ClassName.NEXT; + eventDirectionName = Direction.LEFT; + } else { + directionalClassName = ClassName.RIGHT; + orderClassName = ClassName.PREV; + eventDirectionName = Direction.RIGHT; + } + + if (nextElement && $$$1(nextElement).hasClass(ClassName.ACTIVE)) { + this._isSliding = false; + return; + } + + var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); + + if (slideEvent.isDefaultPrevented()) { + return; + } + + if (!activeElement || !nextElement) { + // Some weirdness is happening, so we bail + return; + } + + this._isSliding = true; + + if (isCycling) { + this.pause(); + } + + this._setActiveIndicatorElement(nextElement); + + var slidEvent = $$$1.Event(Event.SLID, { + relatedTarget: nextElement, + direction: eventDirectionName, + from: activeElementIndex, + to: nextElementIndex + }); + + if ($$$1(this._element).hasClass(ClassName.SLIDE)) { + $$$1(nextElement).addClass(orderClassName); + Util.reflow(nextElement); + $$$1(activeElement).addClass(directionalClassName); + $$$1(nextElement).addClass(directionalClassName); + var transitionDuration = Util.getTransitionDurationFromElement(activeElement); + $$$1(activeElement).one(Util.TRANSITION_END, function () { + $$$1(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(ClassName.ACTIVE); + $$$1(activeElement).removeClass(ClassName.ACTIVE + " " + orderClassName + " " + directionalClassName); + _this3._isSliding = false; + setTimeout(function () { + return $$$1(_this3._element).trigger(slidEvent); + }, 0); + }).emulateTransitionEnd(transitionDuration); + } else { + $$$1(activeElement).removeClass(ClassName.ACTIVE); + $$$1(nextElement).addClass(ClassName.ACTIVE); + this._isSliding = false; + $$$1(this._element).trigger(slidEvent); + } + + if (isCycling) { + this.cycle(); + } + }; // Static + + + Carousel._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = _objectSpread({}, Default, $$$1(this).data()); + + if (typeof config === 'object') { + _config = _objectSpread({}, _config, config); + } + + var action = typeof config === 'string' ? config : _config.slide; + + if (!data) { + data = new Carousel(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'number') { + data.to(config); + } else if (typeof action === 'string') { + if (typeof data[action] === 'undefined') { + throw new TypeError("No method named \"" + action + "\""); + } + + data[action](); + } else if (_config.interval) { + data.pause(); + data.cycle(); + } + }); + }; + + Carousel._dataApiClickHandler = function _dataApiClickHandler(event) { + var selector = Util.getSelectorFromElement(this); + + if (!selector) { + return; + } + + var target = $$$1(selector)[0]; + + if (!target || !$$$1(target).hasClass(ClassName.CAROUSEL)) { + return; + } + + var config = _objectSpread({}, $$$1(target).data(), $$$1(this).data()); + + var slideIndex = this.getAttribute('data-slide-to'); + + if (slideIndex) { + config.interval = false; + } + + Carousel._jQueryInterface.call($$$1(target), config); + + if (slideIndex) { + $$$1(target).data(DATA_KEY).to(slideIndex); + } + + event.preventDefault(); + }; + + _createClass(Carousel, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }]); + + return Carousel; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler); + $$$1(window).on(Event.LOAD_DATA_API, function () { + var carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE)); + + for (var i = 0, len = carousels.length; i < len; i++) { + var $carousel = $$$1(carousels[i]); + + Carousel._jQueryInterface.call($carousel, $carousel.data()); + } + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Carousel._jQueryInterface; + $$$1.fn[NAME].Constructor = Carousel; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Carousel._jQueryInterface; + }; + + return Carousel; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): collapse.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Collapse = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'collapse'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.collapse'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var Default = { + toggle: true, + parent: '' + }; + var DefaultType = { + toggle: 'boolean', + parent: '(string|element)' + }; + var Event = { + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + SHOW: 'show', + COLLAPSE: 'collapse', + COLLAPSING: 'collapsing', + COLLAPSED: 'collapsed' + }; + var Dimension = { + WIDTH: 'width', + HEIGHT: 'height' + }; + var Selector = { + ACTIVES: '.show, .collapsing', + DATA_TOGGLE: '[data-toggle="collapse"]' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Collapse = + /*#__PURE__*/ + function () { + function Collapse(element, config) { + this._isTransitioning = false; + this._element = element; + this._config = this._getConfig(config); + this._triggerArray = $$$1.makeArray(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]"))); + var toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); + + for (var i = 0, len = toggleList.length; i < len; i++) { + var elem = toggleList[i]; + var selector = Util.getSelectorFromElement(elem); + var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) { + return foundElem === element; + }); + + if (selector !== null && filterElement.length > 0) { + this._selector = selector; + + this._triggerArray.push(elem); + } + } + + this._parent = this._config.parent ? this._getParent() : null; + + if (!this._config.parent) { + this._addAriaAndCollapsedClass(this._element, this._triggerArray); + } + + if (this._config.toggle) { + this.toggle(); + } + } // Getters + + + var _proto = Collapse.prototype; + + // Public + _proto.toggle = function toggle() { + if ($$$1(this._element).hasClass(ClassName.SHOW)) { + this.hide(); + } else { + this.show(); + } + }; + + _proto.show = function show() { + var _this = this; + + if (this._isTransitioning || $$$1(this._element).hasClass(ClassName.SHOW)) { + return; + } + + var actives; + var activesData; + + if (this._parent) { + actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES)).filter(function (elem) { + return elem.getAttribute('data-parent') === _this._config.parent; + }); + + if (actives.length === 0) { + actives = null; + } + } + + if (actives) { + activesData = $$$1(actives).not(this._selector).data(DATA_KEY); + + if (activesData && activesData._isTransitioning) { + return; + } + } + + var startEvent = $$$1.Event(Event.SHOW); + $$$1(this._element).trigger(startEvent); + + if (startEvent.isDefaultPrevented()) { + return; + } + + if (actives) { + Collapse._jQueryInterface.call($$$1(actives).not(this._selector), 'hide'); + + if (!activesData) { + $$$1(actives).data(DATA_KEY, null); + } + } + + var dimension = this._getDimension(); + + $$$1(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING); + this._element.style[dimension] = 0; + + if (this._triggerArray.length) { + $$$1(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true); + } + + this.setTransitioning(true); + + var complete = function complete() { + $$$1(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW); + _this._element.style[dimension] = ''; + + _this.setTransitioning(false); + + $$$1(_this._element).trigger(Event.SHOWN); + }; + + var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); + var scrollSize = "scroll" + capitalizedDimension; + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + this._element.style[dimension] = this._element[scrollSize] + "px"; + }; + + _proto.hide = function hide() { + var _this2 = this; + + if (this._isTransitioning || !$$$1(this._element).hasClass(ClassName.SHOW)) { + return; + } + + var startEvent = $$$1.Event(Event.HIDE); + $$$1(this._element).trigger(startEvent); + + if (startEvent.isDefaultPrevented()) { + return; + } + + var dimension = this._getDimension(); + + this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px"; + Util.reflow(this._element); + $$$1(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW); + var triggerArrayLength = this._triggerArray.length; + + if (triggerArrayLength > 0) { + for (var i = 0; i < triggerArrayLength; i++) { + var trigger = this._triggerArray[i]; + var selector = Util.getSelectorFromElement(trigger); + + if (selector !== null) { + var $elem = $$$1([].slice.call(document.querySelectorAll(selector))); + + if (!$elem.hasClass(ClassName.SHOW)) { + $$$1(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false); + } + } + } + } + + this.setTransitioning(true); + + var complete = function complete() { + _this2.setTransitioning(false); + + $$$1(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN); + }; + + this._element.style[dimension] = ''; + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + }; + + _proto.setTransitioning = function setTransitioning(isTransitioning) { + this._isTransitioning = isTransitioning; + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + this._config = null; + this._parent = null; + this._element = null; + this._triggerArray = null; + this._isTransitioning = null; + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, config); + config.toggle = Boolean(config.toggle); // Coerce string values + + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._getDimension = function _getDimension() { + var hasWidth = $$$1(this._element).hasClass(Dimension.WIDTH); + return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT; + }; + + _proto._getParent = function _getParent() { + var _this3 = this; + + var parent = null; + + if (Util.isElement(this._config.parent)) { + parent = this._config.parent; // It's a jQuery object + + if (typeof this._config.parent.jquery !== 'undefined') { + parent = this._config.parent[0]; + } + } else { + parent = document.querySelector(this._config.parent); + } + + var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]"; + var children = [].slice.call(parent.querySelectorAll(selector)); + $$$1(children).each(function (i, element) { + _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]); + }); + return parent; + }; + + _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) { + if (element) { + var isOpen = $$$1(element).hasClass(ClassName.SHOW); + + if (triggerArray.length) { + $$$1(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen); + } + } + }; // Static + + + Collapse._getTargetFromElement = function _getTargetFromElement(element) { + var selector = Util.getSelectorFromElement(element); + return selector ? document.querySelector(selector) : null; + }; + + Collapse._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var $this = $$$1(this); + var data = $this.data(DATA_KEY); + + var _config = _objectSpread({}, Default, $this.data(), typeof config === 'object' && config ? config : {}); + + if (!data && _config.toggle && /show|hide/.test(config)) { + _config.toggle = false; + } + + if (!data) { + data = new Collapse(this, _config); + $this.data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + _createClass(Collapse, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }]); + + return Collapse; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + // preventDefault only for elements (which change the URL) not inside the collapsible element + if (event.currentTarget.tagName === 'A') { + event.preventDefault(); + } + + var $trigger = $$$1(this); + var selector = Util.getSelectorFromElement(this); + var selectors = [].slice.call(document.querySelectorAll(selector)); + $$$1(selectors).each(function () { + var $target = $$$1(this); + var data = $target.data(DATA_KEY); + var config = data ? 'toggle' : $trigger.data(); + + Collapse._jQueryInterface.call($target, config); + }); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Collapse._jQueryInterface; + $$$1.fn[NAME].Constructor = Collapse; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Collapse._jQueryInterface; + }; + + return Collapse; + }($); + + /**! + * @fileOverview Kickass library to create and place poppers near their reference elements. + * @version 1.14.3 + * @license + * Copyright (c) 2016 Federico Zivolo and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined'; + + var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox']; + var timeoutDuration = 0; + for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) { + if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) { + timeoutDuration = 1; + break; + } + } + + function microtaskDebounce(fn) { + var called = false; + return function () { + if (called) { + return; + } + called = true; + window.Promise.resolve().then(function () { + called = false; + fn(); + }); + }; + } + + function taskDebounce(fn) { + var scheduled = false; + return function () { + if (!scheduled) { + scheduled = true; + setTimeout(function () { + scheduled = false; + fn(); + }, timeoutDuration); + } + }; + } + + var supportsMicroTasks = isBrowser && window.Promise; + + /** + * Create a debounced version of a method, that's asynchronously deferred + * but called in the minimum time possible. + * + * @method + * @memberof Popper.Utils + * @argument {Function} fn + * @returns {Function} + */ + var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce; + + /** + * Check if the given variable is a function + * @method + * @memberof Popper.Utils + * @argument {Any} functionToCheck - variable to check + * @returns {Boolean} answer to: is a function? + */ + function isFunction(functionToCheck) { + var getType = {}; + return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]'; + } + + /** + * Get CSS computed property of the given element + * @method + * @memberof Popper.Utils + * @argument {Eement} element + * @argument {String} property + */ + function getStyleComputedProperty(element, property) { + if (element.nodeType !== 1) { + return []; + } + // NOTE: 1 DOM access here + var css = getComputedStyle(element, null); + return property ? css[property] : css; + } + + /** + * Returns the parentNode or the host of the element + * @method + * @memberof Popper.Utils + * @argument {Element} element + * @returns {Element} parent + */ + function getParentNode(element) { + if (element.nodeName === 'HTML') { + return element; + } + return element.parentNode || element.host; + } + + /** + * Returns the scrolling parent of the given element + * @method + * @memberof Popper.Utils + * @argument {Element} element + * @returns {Element} scroll parent + */ + function getScrollParent(element) { + // Return body, `getScroll` will take care to get the correct `scrollTop` from it + if (!element) { + return document.body; + } + + switch (element.nodeName) { + case 'HTML': + case 'BODY': + return element.ownerDocument.body; + case '#document': + return element.body; + } + + // Firefox want us to check `-x` and `-y` variations as well + + var _getStyleComputedProp = getStyleComputedProperty(element), + overflow = _getStyleComputedProp.overflow, + overflowX = _getStyleComputedProp.overflowX, + overflowY = _getStyleComputedProp.overflowY; + + if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) { + return element; + } + + return getScrollParent(getParentNode(element)); + } + + var isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode); + var isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent); + + /** + * Determines if the browser is Internet Explorer + * @method + * @memberof Popper.Utils + * @param {Number} version to check + * @returns {Boolean} isIE + */ + function isIE(version) { + if (version === 11) { + return isIE11; + } + if (version === 10) { + return isIE10; + } + return isIE11 || isIE10; + } + + /** + * Returns the offset parent of the given element + * @method + * @memberof Popper.Utils + * @argument {Element} element + * @returns {Element} offset parent + */ + function getOffsetParent(element) { + if (!element) { + return document.documentElement; + } + + var noOffsetParent = isIE(10) ? document.body : null; + + // NOTE: 1 DOM access here + var offsetParent = element.offsetParent; + // Skip hidden elements which don't have an offsetParent + while (offsetParent === noOffsetParent && element.nextElementSibling) { + offsetParent = (element = element.nextElementSibling).offsetParent; + } + + var nodeName = offsetParent && offsetParent.nodeName; + + if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') { + return element ? element.ownerDocument.documentElement : document.documentElement; + } + + // .offsetParent will return the closest TD or TABLE in case + // no offsetParent is present, I hate this job... + if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') { + return getOffsetParent(offsetParent); + } + + return offsetParent; + } + + function isOffsetContainer(element) { + var nodeName = element.nodeName; + + if (nodeName === 'BODY') { + return false; + } + return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element; + } + + /** + * Finds the root node (document, shadowDOM root) of the given element + * @method + * @memberof Popper.Utils + * @argument {Element} node + * @returns {Element} root node + */ + function getRoot(node) { + if (node.parentNode !== null) { + return getRoot(node.parentNode); + } + + return node; + } + + /** + * Finds the offset parent common to the two provided nodes + * @method + * @memberof Popper.Utils + * @argument {Element} element1 + * @argument {Element} element2 + * @returns {Element} common offset parent + */ + function findCommonOffsetParent(element1, element2) { + // This check is needed to avoid errors in case one of the elements isn't defined for any reason + if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) { + return document.documentElement; + } + + // Here we make sure to give as "start" the element that comes first in the DOM + var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING; + var start = order ? element1 : element2; + var end = order ? element2 : element1; + + // Get common ancestor container + var range = document.createRange(); + range.setStart(start, 0); + range.setEnd(end, 0); + var commonAncestorContainer = range.commonAncestorContainer; + + // Both nodes are inside #document + + if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) { + if (isOffsetContainer(commonAncestorContainer)) { + return commonAncestorContainer; + } + + return getOffsetParent(commonAncestorContainer); + } + + // one of the nodes is inside shadowDOM, find which one + var element1root = getRoot(element1); + if (element1root.host) { + return findCommonOffsetParent(element1root.host, element2); + } else { + return findCommonOffsetParent(element1, getRoot(element2).host); + } + } + + /** + * Gets the scroll value of the given element in the given side (top and left) + * @method + * @memberof Popper.Utils + * @argument {Element} element + * @argument {String} side `top` or `left` + * @returns {number} amount of scrolled pixels + */ + function getScroll(element) { + var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top'; + + var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft'; + var nodeName = element.nodeName; + + if (nodeName === 'BODY' || nodeName === 'HTML') { + var html = element.ownerDocument.documentElement; + var scrollingElement = element.ownerDocument.scrollingElement || html; + return scrollingElement[upperSide]; + } + + return element[upperSide]; + } + + /* + * Sum or subtract the element scroll values (left and top) from a given rect object + * @method + * @memberof Popper.Utils + * @param {Object} rect - Rect object you want to change + * @param {HTMLElement} element - The element from the function reads the scroll values + * @param {Boolean} subtract - set to true if you want to subtract the scroll values + * @return {Object} rect - The modifier rect object + */ + function includeScroll(rect, element) { + var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + var scrollTop = getScroll(element, 'top'); + var scrollLeft = getScroll(element, 'left'); + var modifier = subtract ? -1 : 1; + rect.top += scrollTop * modifier; + rect.bottom += scrollTop * modifier; + rect.left += scrollLeft * modifier; + rect.right += scrollLeft * modifier; + return rect; + } + + /* + * Helper to detect borders of a given element + * @method + * @memberof Popper.Utils + * @param {CSSStyleDeclaration} styles + * Result of `getStyleComputedProperty` on the given element + * @param {String} axis - `x` or `y` + * @return {number} borders - The borders size of the given axis + */ + + function getBordersSize(styles, axis) { + var sideA = axis === 'x' ? 'Left' : 'Top'; + var sideB = sideA === 'Left' ? 'Right' : 'Bottom'; + + return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10); + } + + function getSize(axis, body, html, computedStyle) { + return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0); + } + + function getWindowSizes() { + var body = document.body; + var html = document.documentElement; + var computedStyle = isIE(10) && getComputedStyle(html); + + return { + height: getSize('Height', body, html, computedStyle), + width: getSize('Width', body, html, computedStyle) + }; + } + + var classCallCheck = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } + }; + + var createClass = function () { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + return function (Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); + if (staticProps) defineProperties(Constructor, staticProps); + return Constructor; + }; + }(); + + + + + + var defineProperty = function (obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + + return obj; + }; + + var _extends = Object.assign || function (target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i]; + + for (var key in source) { + if (Object.prototype.hasOwnProperty.call(source, key)) { + target[key] = source[key]; + } + } + } + + return target; + }; + + /** + * Given element offsets, generate an output similar to getBoundingClientRect + * @method + * @memberof Popper.Utils + * @argument {Object} offsets + * @returns {Object} ClientRect like output + */ + function getClientRect(offsets) { + return _extends({}, offsets, { + right: offsets.left + offsets.width, + bottom: offsets.top + offsets.height + }); + } + + /** + * Get bounding client rect of given element + * @method + * @memberof Popper.Utils + * @param {HTMLElement} element + * @return {Object} client rect + */ + function getBoundingClientRect(element) { + var rect = {}; + + // IE10 10 FIX: Please, don't ask, the element isn't + // considered in DOM in some circumstances... + // This isn't reproducible in IE10 compatibility mode of IE11 + try { + if (isIE(10)) { + rect = element.getBoundingClientRect(); + var scrollTop = getScroll(element, 'top'); + var scrollLeft = getScroll(element, 'left'); + rect.top += scrollTop; + rect.left += scrollLeft; + rect.bottom += scrollTop; + rect.right += scrollLeft; + } else { + rect = element.getBoundingClientRect(); + } + } catch (e) {} + + var result = { + left: rect.left, + top: rect.top, + width: rect.right - rect.left, + height: rect.bottom - rect.top + }; + + // subtract scrollbar size from sizes + var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {}; + var width = sizes.width || element.clientWidth || result.right - result.left; + var height = sizes.height || element.clientHeight || result.bottom - result.top; + + var horizScrollbar = element.offsetWidth - width; + var vertScrollbar = element.offsetHeight - height; + + // if an hypothetical scrollbar is detected, we must be sure it's not a `border` + // we make this check conditional for performance reasons + if (horizScrollbar || vertScrollbar) { + var styles = getStyleComputedProperty(element); + horizScrollbar -= getBordersSize(styles, 'x'); + vertScrollbar -= getBordersSize(styles, 'y'); + + result.width -= horizScrollbar; + result.height -= vertScrollbar; + } + + return getClientRect(result); + } + + function getOffsetRectRelativeToArbitraryNode(children, parent) { + var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + var isIE10 = isIE(10); + var isHTML = parent.nodeName === 'HTML'; + var childrenRect = getBoundingClientRect(children); + var parentRect = getBoundingClientRect(parent); + var scrollParent = getScrollParent(children); + + var styles = getStyleComputedProperty(parent); + var borderTopWidth = parseFloat(styles.borderTopWidth, 10); + var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10); + + // In cases where the parent is fixed, we must ignore negative scroll in offset calc + if (fixedPosition && parent.nodeName === 'HTML') { + parentRect.top = Math.max(parentRect.top, 0); + parentRect.left = Math.max(parentRect.left, 0); + } + var offsets = getClientRect({ + top: childrenRect.top - parentRect.top - borderTopWidth, + left: childrenRect.left - parentRect.left - borderLeftWidth, + width: childrenRect.width, + height: childrenRect.height + }); + offsets.marginTop = 0; + offsets.marginLeft = 0; + + // Subtract margins of documentElement in case it's being used as parent + // we do this only on HTML because it's the only element that behaves + // differently when margins are applied to it. The margins are included in + // the box of the documentElement, in the other cases not. + if (!isIE10 && isHTML) { + var marginTop = parseFloat(styles.marginTop, 10); + var marginLeft = parseFloat(styles.marginLeft, 10); + + offsets.top -= borderTopWidth - marginTop; + offsets.bottom -= borderTopWidth - marginTop; + offsets.left -= borderLeftWidth - marginLeft; + offsets.right -= borderLeftWidth - marginLeft; + + // Attach marginTop and marginLeft because in some circumstances we may need them + offsets.marginTop = marginTop; + offsets.marginLeft = marginLeft; + } + + if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') { + offsets = includeScroll(offsets, parent); + } + + return offsets; + } + + function getViewportOffsetRectRelativeToArtbitraryNode(element) { + var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + var html = element.ownerDocument.documentElement; + var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html); + var width = Math.max(html.clientWidth, window.innerWidth || 0); + var height = Math.max(html.clientHeight, window.innerHeight || 0); + + var scrollTop = !excludeScroll ? getScroll(html) : 0; + var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0; + + var offset = { + top: scrollTop - relativeOffset.top + relativeOffset.marginTop, + left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft, + width: width, + height: height + }; + + return getClientRect(offset); + } + + /** + * Check if the given element is fixed or is inside a fixed parent + * @method + * @memberof Popper.Utils + * @argument {Element} element + * @argument {Element} customContainer + * @returns {Boolean} answer to "isFixed?" + */ + function isFixed(element) { + var nodeName = element.nodeName; + if (nodeName === 'BODY' || nodeName === 'HTML') { + return false; + } + if (getStyleComputedProperty(element, 'position') === 'fixed') { + return true; + } + return isFixed(getParentNode(element)); + } + + /** + * Finds the first parent of an element that has a transformed property defined + * @method + * @memberof Popper.Utils + * @argument {Element} element + * @returns {Element} first transformed parent or documentElement + */ + + function getFixedPositionOffsetParent(element) { + // This check is needed to avoid errors in case one of the elements isn't defined for any reason + if (!element || !element.parentElement || isIE()) { + return document.documentElement; + } + var el = element.parentElement; + while (el && getStyleComputedProperty(el, 'transform') === 'none') { + el = el.parentElement; + } + return el || document.documentElement; + } + + /** + * Computed the boundaries limits and return them + * @method + * @memberof Popper.Utils + * @param {HTMLElement} popper + * @param {HTMLElement} reference + * @param {number} padding + * @param {HTMLElement} boundariesElement - Element used to define the boundaries + * @param {Boolean} fixedPosition - Is in fixed position mode + * @returns {Object} Coordinates of the boundaries + */ + function getBoundaries(popper, reference, padding, boundariesElement) { + var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + + // NOTE: 1 DOM access here + + var boundaries = { top: 0, left: 0 }; + var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference); + + // Handle viewport case + if (boundariesElement === 'viewport') { + boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition); + } else { + // Handle other cases based on DOM element used as boundaries + var boundariesNode = void 0; + if (boundariesElement === 'scrollParent') { + boundariesNode = getScrollParent(getParentNode(reference)); + if (boundariesNode.nodeName === 'BODY') { + boundariesNode = popper.ownerDocument.documentElement; + } + } else if (boundariesElement === 'window') { + boundariesNode = popper.ownerDocument.documentElement; + } else { + boundariesNode = boundariesElement; + } + + var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition); + + // In case of HTML, we need a different computation + if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) { + var _getWindowSizes = getWindowSizes(), + height = _getWindowSizes.height, + width = _getWindowSizes.width; + + boundaries.top += offsets.top - offsets.marginTop; + boundaries.bottom = height + offsets.top; + boundaries.left += offsets.left - offsets.marginLeft; + boundaries.right = width + offsets.left; + } else { + // for all the other DOM elements, this one is good + boundaries = offsets; + } + } + + // Add paddings + boundaries.left += padding; + boundaries.top += padding; + boundaries.right -= padding; + boundaries.bottom -= padding; + + return boundaries; + } + + function getArea(_ref) { + var width = _ref.width, + height = _ref.height; + + return width * height; + } + + /** + * Utility used to transform the `auto` placement to the placement with more + * available space. + * @method + * @memberof Popper.Utils + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) { + var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; + + if (placement.indexOf('auto') === -1) { + return placement; + } + + var boundaries = getBoundaries(popper, reference, padding, boundariesElement); + + var rects = { + top: { + width: boundaries.width, + height: refRect.top - boundaries.top + }, + right: { + width: boundaries.right - refRect.right, + height: boundaries.height + }, + bottom: { + width: boundaries.width, + height: boundaries.bottom - refRect.bottom + }, + left: { + width: refRect.left - boundaries.left, + height: boundaries.height + } + }; + + var sortedAreas = Object.keys(rects).map(function (key) { + return _extends({ + key: key + }, rects[key], { + area: getArea(rects[key]) + }); + }).sort(function (a, b) { + return b.area - a.area; + }); + + var filteredAreas = sortedAreas.filter(function (_ref2) { + var width = _ref2.width, + height = _ref2.height; + return width >= popper.clientWidth && height >= popper.clientHeight; + }); + + var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key; + + var variation = placement.split('-')[1]; + + return computedPlacement + (variation ? '-' + variation : ''); + } + + /** + * Get offsets to the reference element + * @method + * @memberof Popper.Utils + * @param {Object} state + * @param {Element} popper - the popper element + * @param {Element} reference - the reference element (the popper will be relative to this) + * @param {Element} fixedPosition - is in fixed position mode + * @returns {Object} An object containing the offsets which will be applied to the popper + */ + function getReferenceOffsets(state, popper, reference) { + var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + + var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference); + return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition); + } + + /** + * Get the outer sizes of the given element (offset size + margins) + * @method + * @memberof Popper.Utils + * @argument {Element} element + * @returns {Object} object containing width and height properties + */ + function getOuterSizes(element) { + var styles = getComputedStyle(element); + var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom); + var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight); + var result = { + width: element.offsetWidth + y, + height: element.offsetHeight + x + }; + return result; + } + + /** + * Get the opposite placement of the given one + * @method + * @memberof Popper.Utils + * @argument {String} placement + * @returns {String} flipped placement + */ + function getOppositePlacement(placement) { + var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; + return placement.replace(/left|right|bottom|top/g, function (matched) { + return hash[matched]; + }); + } + + /** + * Get offsets to the popper + * @method + * @memberof Popper.Utils + * @param {Object} position - CSS position the Popper will get applied + * @param {HTMLElement} popper - the popper element + * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this) + * @param {String} placement - one of the valid placement options + * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper + */ + function getPopperOffsets(popper, referenceOffsets, placement) { + placement = placement.split('-')[0]; + + // Get popper node sizes + var popperRect = getOuterSizes(popper); + + // Add position, width and height to our offsets object + var popperOffsets = { + width: popperRect.width, + height: popperRect.height + }; + + // depending by the popper placement we have to compute its offsets slightly differently + var isHoriz = ['right', 'left'].indexOf(placement) !== -1; + var mainSide = isHoriz ? 'top' : 'left'; + var secondarySide = isHoriz ? 'left' : 'top'; + var measurement = isHoriz ? 'height' : 'width'; + var secondaryMeasurement = !isHoriz ? 'height' : 'width'; + + popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2; + if (placement === secondarySide) { + popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement]; + } else { + popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)]; + } + + return popperOffsets; + } + + /** + * Mimics the `find` method of Array + * @method + * @memberof Popper.Utils + * @argument {Array} arr + * @argument prop + * @argument value + * @returns index or -1 + */ + function find(arr, check) { + // use native find if supported + if (Array.prototype.find) { + return arr.find(check); + } + + // use `filter` to obtain the same behavior of `find` + return arr.filter(check)[0]; + } + + /** + * Return the index of the matching object + * @method + * @memberof Popper.Utils + * @argument {Array} arr + * @argument prop + * @argument value + * @returns index or -1 + */ + function findIndex(arr, prop, value) { + // use native findIndex if supported + if (Array.prototype.findIndex) { + return arr.findIndex(function (cur) { + return cur[prop] === value; + }); + } + + // use `find` + `indexOf` if `findIndex` isn't supported + var match = find(arr, function (obj) { + return obj[prop] === value; + }); + return arr.indexOf(match); + } + + /** + * Loop trough the list of modifiers and run them in order, + * each of them will then edit the data object. + * @method + * @memberof Popper.Utils + * @param {dataObject} data + * @param {Array} modifiers + * @param {String} ends - Optional modifier name used as stopper + * @returns {dataObject} + */ + function runModifiers(modifiers, data, ends) { + var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends)); + + modifiersToRun.forEach(function (modifier) { + if (modifier['function']) { + // eslint-disable-line dot-notation + console.warn('`modifier.function` is deprecated, use `modifier.fn`!'); + } + var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation + if (modifier.enabled && isFunction(fn)) { + // Add properties to offsets to make them a complete clientRect object + // we do this before each modifier to make sure the previous one doesn't + // mess with these values + data.offsets.popper = getClientRect(data.offsets.popper); + data.offsets.reference = getClientRect(data.offsets.reference); + + data = fn(data, modifier); + } + }); + + return data; + } + + /** + * Updates the position of the popper, computing the new offsets and applying + * the new style.
+ * Prefer `scheduleUpdate` over `update` because of performance reasons. + * @method + * @memberof Popper + */ + function update() { + // if popper is destroyed, don't perform any further update + if (this.state.isDestroyed) { + return; + } + + var data = { + instance: this, + styles: {}, + arrowStyles: {}, + attributes: {}, + flipped: false, + offsets: {} + }; + + // compute reference element offsets + data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed); + + // compute auto placement, store placement inside the data object, + // modifiers will be able to edit `placement` if needed + // and refer to originalPlacement to know the original value + data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding); + + // store the computed placement inside `originalPlacement` + data.originalPlacement = data.placement; + + data.positionFixed = this.options.positionFixed; + + // compute the popper offsets + data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement); + + data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute'; + + // run the modifiers + data = runModifiers(this.modifiers, data); + + // the first `update` will call `onCreate` callback + // the other ones will call `onUpdate` callback + if (!this.state.isCreated) { + this.state.isCreated = true; + this.options.onCreate(data); + } else { + this.options.onUpdate(data); + } + } + + /** + * Helper used to know if the given modifier is enabled. + * @method + * @memberof Popper.Utils + * @returns {Boolean} + */ + function isModifierEnabled(modifiers, modifierName) { + return modifiers.some(function (_ref) { + var name = _ref.name, + enabled = _ref.enabled; + return enabled && name === modifierName; + }); + } + + /** + * Get the prefixed supported property name + * @method + * @memberof Popper.Utils + * @argument {String} property (camelCase) + * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix) + */ + function getSupportedPropertyName(property) { + var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O']; + var upperProp = property.charAt(0).toUpperCase() + property.slice(1); + + for (var i = 0; i < prefixes.length; i++) { + var prefix = prefixes[i]; + var toCheck = prefix ? '' + prefix + upperProp : property; + if (typeof document.body.style[toCheck] !== 'undefined') { + return toCheck; + } + } + return null; + } + + /** + * Destroy the popper + * @method + * @memberof Popper + */ + function destroy() { + this.state.isDestroyed = true; + + // touch DOM only if `applyStyle` modifier is enabled + if (isModifierEnabled(this.modifiers, 'applyStyle')) { + this.popper.removeAttribute('x-placement'); + this.popper.style.position = ''; + this.popper.style.top = ''; + this.popper.style.left = ''; + this.popper.style.right = ''; + this.popper.style.bottom = ''; + this.popper.style.willChange = ''; + this.popper.style[getSupportedPropertyName('transform')] = ''; + } + + this.disableEventListeners(); + + // remove the popper if user explicity asked for the deletion on destroy + // do not use `remove` because IE11 doesn't support it + if (this.options.removeOnDestroy) { + this.popper.parentNode.removeChild(this.popper); + } + return this; + } + + /** + * Get the window associated with the element + * @argument {Element} element + * @returns {Window} + */ + function getWindow(element) { + var ownerDocument = element.ownerDocument; + return ownerDocument ? ownerDocument.defaultView : window; + } + + function attachToScrollParents(scrollParent, event, callback, scrollParents) { + var isBody = scrollParent.nodeName === 'BODY'; + var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent; + target.addEventListener(event, callback, { passive: true }); + + if (!isBody) { + attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents); + } + scrollParents.push(target); + } + + /** + * Setup needed event listeners used to update the popper position + * @method + * @memberof Popper.Utils + * @private + */ + function setupEventListeners(reference, options, state, updateBound) { + // Resize event listener on window + state.updateBound = updateBound; + getWindow(reference).addEventListener('resize', state.updateBound, { passive: true }); + + // Scroll event listener on scroll parents + var scrollElement = getScrollParent(reference); + attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents); + state.scrollElement = scrollElement; + state.eventsEnabled = true; + + return state; + } + + /** + * It will add resize/scroll events and start recalculating + * position of the popper element when they are triggered. + * @method + * @memberof Popper + */ + function enableEventListeners() { + if (!this.state.eventsEnabled) { + this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate); + } + } + + /** + * Remove event listeners used to update the popper position + * @method + * @memberof Popper.Utils + * @private + */ + function removeEventListeners(reference, state) { + // Remove resize event listener on window + getWindow(reference).removeEventListener('resize', state.updateBound); + + // Remove scroll event listener on scroll parents + state.scrollParents.forEach(function (target) { + target.removeEventListener('scroll', state.updateBound); + }); + + // Reset state + state.updateBound = null; + state.scrollParents = []; + state.scrollElement = null; + state.eventsEnabled = false; + return state; + } + + /** + * It will remove resize/scroll events and won't recalculate popper position + * when they are triggered. It also won't trigger onUpdate callback anymore, + * unless you call `update` method manually. + * @method + * @memberof Popper + */ + function disableEventListeners() { + if (this.state.eventsEnabled) { + cancelAnimationFrame(this.scheduleUpdate); + this.state = removeEventListeners(this.reference, this.state); + } + } + + /** + * Tells if a given input is a number + * @method + * @memberof Popper.Utils + * @param {*} input to check + * @return {Boolean} + */ + function isNumeric(n) { + return n !== '' && !isNaN(parseFloat(n)) && isFinite(n); + } + + /** + * Set the style to the given popper + * @method + * @memberof Popper.Utils + * @argument {Element} element - Element to apply the style to + * @argument {Object} styles + * Object with a list of properties and values which will be applied to the element + */ + function setStyles(element, styles) { + Object.keys(styles).forEach(function (prop) { + var unit = ''; + // add unit if the value is numeric and is one of the following + if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) { + unit = 'px'; + } + element.style[prop] = styles[prop] + unit; + }); + } + + /** + * Set the attributes to the given popper + * @method + * @memberof Popper.Utils + * @argument {Element} element - Element to apply the attributes to + * @argument {Object} styles + * Object with a list of properties and values which will be applied to the element + */ + function setAttributes(element, attributes) { + Object.keys(attributes).forEach(function (prop) { + var value = attributes[prop]; + if (value !== false) { + element.setAttribute(prop, attributes[prop]); + } else { + element.removeAttribute(prop); + } + }); + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by `update` method + * @argument {Object} data.styles - List of style properties - values to apply to popper element + * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The same data object + */ + function applyStyle(data) { + // any property present in `data.styles` will be applied to the popper, + // in this way we can make the 3rd party modifiers add custom styles to it + // Be aware, modifiers could override the properties defined in the previous + // lines of this modifier! + setStyles(data.instance.popper, data.styles); + + // any property present in `data.attributes` will be applied to the popper, + // they will be set as HTML attributes of the element + setAttributes(data.instance.popper, data.attributes); + + // if arrowElement is defined and arrowStyles has some properties + if (data.arrowElement && Object.keys(data.arrowStyles).length) { + setStyles(data.arrowElement, data.arrowStyles); + } + + return data; + } + + /** + * Set the x-placement attribute before everything else because it could be used + * to add margins to the popper margins needs to be calculated to get the + * correct popper offsets. + * @method + * @memberof Popper.modifiers + * @param {HTMLElement} reference - The reference element used to position the popper + * @param {HTMLElement} popper - The HTML element used as popper + * @param {Object} options - Popper.js options + */ + function applyStyleOnLoad(reference, popper, options, modifierOptions, state) { + // compute reference element offsets + var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed); + + // compute auto placement, store placement inside the data object, + // modifiers will be able to edit `placement` if needed + // and refer to originalPlacement to know the original value + var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding); + + popper.setAttribute('x-placement', placement); + + // Apply `position` to popper before anything else because + // without the position applied we can't guarantee correct computations + setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' }); + + return options; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by `update` method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function computeStyle(data, options) { + var x = options.x, + y = options.y; + var popper = data.offsets.popper; + + // Remove this legacy support in Popper.js v2 + + var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) { + return modifier.name === 'applyStyle'; + }).gpuAcceleration; + if (legacyGpuAccelerationOption !== undefined) { + console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!'); + } + var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration; + + var offsetParent = getOffsetParent(data.instance.popper); + var offsetParentRect = getBoundingClientRect(offsetParent); + + // Styles + var styles = { + position: popper.position + }; + + // Avoid blurry text by using full pixel integers. + // For pixel-perfect positioning, top/bottom prefers rounded + // values, while left/right prefers floored values. + var offsets = { + left: Math.floor(popper.left), + top: Math.round(popper.top), + bottom: Math.round(popper.bottom), + right: Math.floor(popper.right) + }; + + var sideA = x === 'bottom' ? 'top' : 'bottom'; + var sideB = y === 'right' ? 'left' : 'right'; + + // if gpuAcceleration is set to `true` and transform is supported, + // we use `translate3d` to apply the position to the popper we + // automatically use the supported prefixed version if needed + var prefixedProperty = getSupportedPropertyName('transform'); + + // now, let's make a step back and look at this code closely (wtf?) + // If the content of the popper grows once it's been positioned, it + // may happen that the popper gets misplaced because of the new content + // overflowing its reference element + // To avoid this problem, we provide two options (x and y), which allow + // the consumer to define the offset origin. + // If we position a popper on top of a reference element, we can set + // `x` to `top` to make the popper grow towards its top instead of + // its bottom. + var left = void 0, + top = void 0; + if (sideA === 'bottom') { + top = -offsetParentRect.height + offsets.bottom; + } else { + top = offsets.top; + } + if (sideB === 'right') { + left = -offsetParentRect.width + offsets.right; + } else { + left = offsets.left; + } + if (gpuAcceleration && prefixedProperty) { + styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)'; + styles[sideA] = 0; + styles[sideB] = 0; + styles.willChange = 'transform'; + } else { + // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties + var invertTop = sideA === 'bottom' ? -1 : 1; + var invertLeft = sideB === 'right' ? -1 : 1; + styles[sideA] = top * invertTop; + styles[sideB] = left * invertLeft; + styles.willChange = sideA + ', ' + sideB; + } + + // Attributes + var attributes = { + 'x-placement': data.placement + }; + + // Update `data` attributes, styles and arrowStyles + data.attributes = _extends({}, attributes, data.attributes); + data.styles = _extends({}, styles, data.styles); + data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles); + + return data; + } + + /** + * Helper used to know if the given modifier depends from another one.
+ * It checks if the needed modifier is listed and enabled. + * @method + * @memberof Popper.Utils + * @param {Array} modifiers - list of modifiers + * @param {String} requestingName - name of requesting modifier + * @param {String} requestedName - name of requested modifier + * @returns {Boolean} + */ + function isModifierRequired(modifiers, requestingName, requestedName) { + var requesting = find(modifiers, function (_ref) { + var name = _ref.name; + return name === requestingName; + }); + + var isRequired = !!requesting && modifiers.some(function (modifier) { + return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order; + }); + + if (!isRequired) { + var _requesting = '`' + requestingName + '`'; + var requested = '`' + requestedName + '`'; + console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!'); + } + return isRequired; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function arrow(data, options) { + var _data$offsets$arrow; + + // arrow depends on keepTogether in order to work + if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) { + return data; + } + + var arrowElement = options.element; + + // if arrowElement is a string, suppose it's a CSS selector + if (typeof arrowElement === 'string') { + arrowElement = data.instance.popper.querySelector(arrowElement); + + // if arrowElement is not found, don't run the modifier + if (!arrowElement) { + return data; + } + } else { + // if the arrowElement isn't a query selector we must check that the + // provided DOM node is child of its popper node + if (!data.instance.popper.contains(arrowElement)) { + console.warn('WARNING: `arrow.element` must be child of its popper element!'); + return data; + } + } + + var placement = data.placement.split('-')[0]; + var _data$offsets = data.offsets, + popper = _data$offsets.popper, + reference = _data$offsets.reference; + + var isVertical = ['left', 'right'].indexOf(placement) !== -1; + + var len = isVertical ? 'height' : 'width'; + var sideCapitalized = isVertical ? 'Top' : 'Left'; + var side = sideCapitalized.toLowerCase(); + var altSide = isVertical ? 'left' : 'top'; + var opSide = isVertical ? 'bottom' : 'right'; + var arrowElementSize = getOuterSizes(arrowElement)[len]; + + // + // extends keepTogether behavior making sure the popper and its + // reference have enough pixels in conjuction + // + + // top/left side + if (reference[opSide] - arrowElementSize < popper[side]) { + data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize); + } + // bottom/right side + if (reference[side] + arrowElementSize > popper[opSide]) { + data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide]; + } + data.offsets.popper = getClientRect(data.offsets.popper); + + // compute center of the popper + var center = reference[side] + reference[len] / 2 - arrowElementSize / 2; + + // Compute the sideValue using the updated popper offsets + // take popper margin in account because we don't have this info available + var css = getStyleComputedProperty(data.instance.popper); + var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10); + var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10); + var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide; + + // prevent arrowElement from being placed not contiguously to its popper + sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0); + + data.arrowElement = arrowElement; + data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow); + + return data; + } + + /** + * Get the opposite placement variation of the given one + * @method + * @memberof Popper.Utils + * @argument {String} placement variation + * @returns {String} flipped placement variation + */ + function getOppositeVariation(variation) { + if (variation === 'end') { + return 'start'; + } else if (variation === 'start') { + return 'end'; + } + return variation; + } + + /** + * List of accepted placements to use as values of the `placement` option.
+ * Valid placements are: + * - `auto` + * - `top` + * - `right` + * - `bottom` + * - `left` + * + * Each placement can have a variation from this list: + * - `-start` + * - `-end` + * + * Variations are interpreted easily if you think of them as the left to right + * written languages. Horizontally (`top` and `bottom`), `start` is left and `end` + * is right.
+ * Vertically (`left` and `right`), `start` is top and `end` is bottom. + * + * Some valid examples are: + * - `top-end` (on top of reference, right aligned) + * - `right-start` (on right of reference, top aligned) + * - `bottom` (on bottom, centered) + * - `auto-right` (on the side with more space available, alignment depends by placement) + * + * @static + * @type {Array} + * @enum {String} + * @readonly + * @method placements + * @memberof Popper + */ + var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start']; + + // Get rid of `auto` `auto-start` and `auto-end` + var validPlacements = placements.slice(3); + + /** + * Given an initial placement, returns all the subsequent placements + * clockwise (or counter-clockwise). + * + * @method + * @memberof Popper.Utils + * @argument {String} placement - A valid placement (it accepts variations) + * @argument {Boolean} counter - Set to true to walk the placements counterclockwise + * @returns {Array} placements including their variations + */ + function clockwise(placement) { + var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + var index = validPlacements.indexOf(placement); + var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index)); + return counter ? arr.reverse() : arr; + } + + var BEHAVIORS = { + FLIP: 'flip', + CLOCKWISE: 'clockwise', + COUNTERCLOCKWISE: 'counterclockwise' + }; + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function flip(data, options) { + // if `inner` modifier is enabled, we can't use the `flip` modifier + if (isModifierEnabled(data.instance.modifiers, 'inner')) { + return data; + } + + if (data.flipped && data.placement === data.originalPlacement) { + // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides + return data; + } + + var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed); + + var placement = data.placement.split('-')[0]; + var placementOpposite = getOppositePlacement(placement); + var variation = data.placement.split('-')[1] || ''; + + var flipOrder = []; + + switch (options.behavior) { + case BEHAVIORS.FLIP: + flipOrder = [placement, placementOpposite]; + break; + case BEHAVIORS.CLOCKWISE: + flipOrder = clockwise(placement); + break; + case BEHAVIORS.COUNTERCLOCKWISE: + flipOrder = clockwise(placement, true); + break; + default: + flipOrder = options.behavior; + } + + flipOrder.forEach(function (step, index) { + if (placement !== step || flipOrder.length === index + 1) { + return data; + } + + placement = data.placement.split('-')[0]; + placementOpposite = getOppositePlacement(placement); + + var popperOffsets = data.offsets.popper; + var refOffsets = data.offsets.reference; + + // using floor because the reference offsets may contain decimals we are not going to consider here + var floor = Math.floor; + var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom); + + var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left); + var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right); + var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top); + var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom); + + var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom; + + // flip the variation if required + var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; + var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom); + + if (overlapsRef || overflowsBoundaries || flippedVariation) { + // this boolean to detect any flip loop + data.flipped = true; + + if (overlapsRef || overflowsBoundaries) { + placement = flipOrder[index + 1]; + } + + if (flippedVariation) { + variation = getOppositeVariation(variation); + } + + data.placement = placement + (variation ? '-' + variation : ''); + + // this object contains `position`, we want to preserve it along with + // any additional property we may add in the future + data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement)); + + data = runModifiers(data.instance.modifiers, data, 'flip'); + } + }); + return data; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function keepTogether(data) { + var _data$offsets = data.offsets, + popper = _data$offsets.popper, + reference = _data$offsets.reference; + + var placement = data.placement.split('-')[0]; + var floor = Math.floor; + var isVertical = ['top', 'bottom'].indexOf(placement) !== -1; + var side = isVertical ? 'right' : 'bottom'; + var opSide = isVertical ? 'left' : 'top'; + var measurement = isVertical ? 'width' : 'height'; + + if (popper[side] < floor(reference[opSide])) { + data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement]; + } + if (popper[opSide] > floor(reference[side])) { + data.offsets.popper[opSide] = floor(reference[side]); + } + + return data; + } + + /** + * Converts a string containing value + unit into a px value number + * @function + * @memberof {modifiers~offset} + * @private + * @argument {String} str - Value + unit string + * @argument {String} measurement - `height` or `width` + * @argument {Object} popperOffsets + * @argument {Object} referenceOffsets + * @returns {Number|String} + * Value in pixels, or original string if no values were extracted + */ + function toValue(str, measurement, popperOffsets, referenceOffsets) { + // separate value from unit + var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/); + var value = +split[1]; + var unit = split[2]; + + // If it's not a number it's an operator, I guess + if (!value) { + return str; + } + + if (unit.indexOf('%') === 0) { + var element = void 0; + switch (unit) { + case '%p': + element = popperOffsets; + break; + case '%': + case '%r': + default: + element = referenceOffsets; + } + + var rect = getClientRect(element); + return rect[measurement] / 100 * value; + } else if (unit === 'vh' || unit === 'vw') { + // if is a vh or vw, we calculate the size based on the viewport + var size = void 0; + if (unit === 'vh') { + size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); + } else { + size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0); + } + return size / 100 * value; + } else { + // if is an explicit pixel unit, we get rid of the unit and keep the value + // if is an implicit unit, it's px, and we return just the value + return value; + } + } + + /** + * Parse an `offset` string to extrapolate `x` and `y` numeric offsets. + * @function + * @memberof {modifiers~offset} + * @private + * @argument {String} offset + * @argument {Object} popperOffsets + * @argument {Object} referenceOffsets + * @argument {String} basePlacement + * @returns {Array} a two cells array with x and y offsets in numbers + */ + function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) { + var offsets = [0, 0]; + + // Use height if placement is left or right and index is 0 otherwise use width + // in this way the first offset will use an axis and the second one + // will use the other one + var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1; + + // Split the offset string to obtain a list of values and operands + // The regex addresses values with the plus or minus sign in front (+10, -20, etc) + var fragments = offset.split(/(\+|\-)/).map(function (frag) { + return frag.trim(); + }); + + // Detect if the offset string contains a pair of values or a single one + // they could be separated by comma or space + var divider = fragments.indexOf(find(fragments, function (frag) { + return frag.search(/,|\s/) !== -1; + })); + + if (fragments[divider] && fragments[divider].indexOf(',') === -1) { + console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.'); + } + + // If divider is found, we divide the list of values and operands to divide + // them by ofset X and Y. + var splitRegex = /\s*,\s*|\s+/; + var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments]; + + // Convert the values with units to absolute pixels to allow our computations + ops = ops.map(function (op, index) { + // Most of the units rely on the orientation of the popper + var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width'; + var mergeWithPrevious = false; + return op + // This aggregates any `+` or `-` sign that aren't considered operators + // e.g.: 10 + +5 => [10, +, +5] + .reduce(function (a, b) { + if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) { + a[a.length - 1] = b; + mergeWithPrevious = true; + return a; + } else if (mergeWithPrevious) { + a[a.length - 1] += b; + mergeWithPrevious = false; + return a; + } else { + return a.concat(b); + } + }, []) + // Here we convert the string values into number values (in px) + .map(function (str) { + return toValue(str, measurement, popperOffsets, referenceOffsets); + }); + }); + + // Loop trough the offsets arrays and execute the operations + ops.forEach(function (op, index) { + op.forEach(function (frag, index2) { + if (isNumeric(frag)) { + offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1); + } + }); + }); + return offsets; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @argument {Number|String} options.offset=0 + * The offset value as described in the modifier description + * @returns {Object} The data object, properly modified + */ + function offset(data, _ref) { + var offset = _ref.offset; + var placement = data.placement, + _data$offsets = data.offsets, + popper = _data$offsets.popper, + reference = _data$offsets.reference; + + var basePlacement = placement.split('-')[0]; + + var offsets = void 0; + if (isNumeric(+offset)) { + offsets = [+offset, 0]; + } else { + offsets = parseOffset(offset, popper, reference, basePlacement); + } + + if (basePlacement === 'left') { + popper.top += offsets[0]; + popper.left -= offsets[1]; + } else if (basePlacement === 'right') { + popper.top += offsets[0]; + popper.left += offsets[1]; + } else if (basePlacement === 'top') { + popper.left += offsets[0]; + popper.top -= offsets[1]; + } else if (basePlacement === 'bottom') { + popper.left += offsets[0]; + popper.top += offsets[1]; + } + + data.popper = popper; + return data; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by `update` method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function preventOverflow(data, options) { + var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper); + + // If offsetParent is the reference element, we really want to + // go one step up and use the next offsetParent as reference to + // avoid to make this modifier completely useless and look like broken + if (data.instance.reference === boundariesElement) { + boundariesElement = getOffsetParent(boundariesElement); + } + + // NOTE: DOM access here + // resets the popper's position so that the document size can be calculated excluding + // the size of the popper element itself + var transformProp = getSupportedPropertyName('transform'); + var popperStyles = data.instance.popper.style; // assignment to help minification + var top = popperStyles.top, + left = popperStyles.left, + transform = popperStyles[transformProp]; + + popperStyles.top = ''; + popperStyles.left = ''; + popperStyles[transformProp] = ''; + + var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed); + + // NOTE: DOM access here + // restores the original style properties after the offsets have been computed + popperStyles.top = top; + popperStyles.left = left; + popperStyles[transformProp] = transform; + + options.boundaries = boundaries; + + var order = options.priority; + var popper = data.offsets.popper; + + var check = { + primary: function primary(placement) { + var value = popper[placement]; + if (popper[placement] < boundaries[placement] && !options.escapeWithReference) { + value = Math.max(popper[placement], boundaries[placement]); + } + return defineProperty({}, placement, value); + }, + secondary: function secondary(placement) { + var mainSide = placement === 'right' ? 'left' : 'top'; + var value = popper[mainSide]; + if (popper[placement] > boundaries[placement] && !options.escapeWithReference) { + value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height)); + } + return defineProperty({}, mainSide, value); + } + }; + + order.forEach(function (placement) { + var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary'; + popper = _extends({}, popper, check[side](placement)); + }); + + data.offsets.popper = popper; + + return data; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by `update` method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function shift(data) { + var placement = data.placement; + var basePlacement = placement.split('-')[0]; + var shiftvariation = placement.split('-')[1]; + + // if shift shiftvariation is specified, run the modifier + if (shiftvariation) { + var _data$offsets = data.offsets, + reference = _data$offsets.reference, + popper = _data$offsets.popper; + + var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1; + var side = isVertical ? 'left' : 'top'; + var measurement = isVertical ? 'width' : 'height'; + + var shiftOffsets = { + start: defineProperty({}, side, reference[side]), + end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement]) + }; + + data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]); + } + + return data; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by update method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function hide(data) { + if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) { + return data; + } + + var refRect = data.offsets.reference; + var bound = find(data.instance.modifiers, function (modifier) { + return modifier.name === 'preventOverflow'; + }).boundaries; + + if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) { + // Avoid unnecessary DOM access if visibility hasn't changed + if (data.hide === true) { + return data; + } + + data.hide = true; + data.attributes['x-out-of-boundaries'] = ''; + } else { + // Avoid unnecessary DOM access if visibility hasn't changed + if (data.hide === false) { + return data; + } + + data.hide = false; + data.attributes['x-out-of-boundaries'] = false; + } + + return data; + } + + /** + * @function + * @memberof Modifiers + * @argument {Object} data - The data object generated by `update` method + * @argument {Object} options - Modifiers configuration and options + * @returns {Object} The data object, properly modified + */ + function inner(data) { + var placement = data.placement; + var basePlacement = placement.split('-')[0]; + var _data$offsets = data.offsets, + popper = _data$offsets.popper, + reference = _data$offsets.reference; + + var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1; + + var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1; + + popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0); + + data.placement = getOppositePlacement(placement); + data.offsets.popper = getClientRect(popper); + + return data; + } + + /** + * Modifier function, each modifier can have a function of this type assigned + * to its `fn` property.
+ * These functions will be called on each update, this means that you must + * make sure they are performant enough to avoid performance bottlenecks. + * + * @function ModifierFn + * @argument {dataObject} data - The data object generated by `update` method + * @argument {Object} options - Modifiers configuration and options + * @returns {dataObject} The data object, properly modified + */ + + /** + * Modifiers are plugins used to alter the behavior of your poppers.
+ * Popper.js uses a set of 9 modifiers to provide all the basic functionalities + * needed by the library. + * + * Usually you don't want to override the `order`, `fn` and `onLoad` props. + * All the other properties are configurations that could be tweaked. + * @namespace modifiers + */ + var modifiers = { + /** + * Modifier used to shift the popper on the start or end of its reference + * element.
+ * It will read the variation of the `placement` property.
+ * It can be one either `-end` or `-start`. + * @memberof modifiers + * @inner + */ + shift: { + /** @prop {number} order=100 - Index used to define the order of execution */ + order: 100, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: shift + }, + + /** + * The `offset` modifier can shift your popper on both its axis. + * + * It accepts the following units: + * - `px` or unitless, interpreted as pixels + * - `%` or `%r`, percentage relative to the length of the reference element + * - `%p`, percentage relative to the length of the popper element + * - `vw`, CSS viewport width unit + * - `vh`, CSS viewport height unit + * + * For length is intended the main axis relative to the placement of the popper.
+ * This means that if the placement is `top` or `bottom`, the length will be the + * `width`. In case of `left` or `right`, it will be the height. + * + * You can provide a single value (as `Number` or `String`), or a pair of values + * as `String` divided by a comma or one (or more) white spaces.
+ * The latter is a deprecated method because it leads to confusion and will be + * removed in v2.
+ * Additionally, it accepts additions and subtractions between different units. + * Note that multiplications and divisions aren't supported. + * + * Valid examples are: + * ``` + * 10 + * '10%' + * '10, 10' + * '10%, 10' + * '10 + 10%' + * '10 - 5vh + 3%' + * '-10px + 5vh, 5px - 6%' + * ``` + * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap + * > with their reference element, unfortunately, you will have to disable the `flip` modifier. + * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373) + * + * @memberof modifiers + * @inner + */ + offset: { + /** @prop {number} order=200 - Index used to define the order of execution */ + order: 200, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: offset, + /** @prop {Number|String} offset=0 + * The offset value as described in the modifier description + */ + offset: 0 + }, + + /** + * Modifier used to prevent the popper from being positioned outside the boundary. + * + * An scenario exists where the reference itself is not within the boundaries.
+ * We can say it has "escaped the boundaries" — or just "escaped".
+ * In this case we need to decide whether the popper should either: + * + * - detach from the reference and remain "trapped" in the boundaries, or + * - if it should ignore the boundary and "escape with its reference" + * + * When `escapeWithReference` is set to`true` and reference is completely + * outside its boundaries, the popper will overflow (or completely leave) + * the boundaries in order to remain attached to the edge of the reference. + * + * @memberof modifiers + * @inner + */ + preventOverflow: { + /** @prop {number} order=300 - Index used to define the order of execution */ + order: 300, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: preventOverflow, + /** + * @prop {Array} [priority=['left','right','top','bottom']] + * Popper will try to prevent overflow following these priorities by default, + * then, it could overflow on the left and on top of the `boundariesElement` + */ + priority: ['left', 'right', 'top', 'bottom'], + /** + * @prop {number} padding=5 + * Amount of pixel used to define a minimum distance between the boundaries + * and the popper this makes sure the popper has always a little padding + * between the edges of its container + */ + padding: 5, + /** + * @prop {String|HTMLElement} boundariesElement='scrollParent' + * Boundaries used by the modifier, can be `scrollParent`, `window`, + * `viewport` or any DOM element. + */ + boundariesElement: 'scrollParent' + }, + + /** + * Modifier used to make sure the reference and its popper stay near eachothers + * without leaving any gap between the two. Expecially useful when the arrow is + * enabled and you want to assure it to point to its reference element. + * It cares only about the first axis, you can still have poppers with margin + * between the popper and its reference element. + * @memberof modifiers + * @inner + */ + keepTogether: { + /** @prop {number} order=400 - Index used to define the order of execution */ + order: 400, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: keepTogether + }, + + /** + * This modifier is used to move the `arrowElement` of the popper to make + * sure it is positioned between the reference element and its popper element. + * It will read the outer size of the `arrowElement` node to detect how many + * pixels of conjuction are needed. + * + * It has no effect if no `arrowElement` is provided. + * @memberof modifiers + * @inner + */ + arrow: { + /** @prop {number} order=500 - Index used to define the order of execution */ + order: 500, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: arrow, + /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */ + element: '[x-arrow]' + }, + + /** + * Modifier used to flip the popper's placement when it starts to overlap its + * reference element. + * + * Requires the `preventOverflow` modifier before it in order to work. + * + * **NOTE:** this modifier will interrupt the current update cycle and will + * restart it if it detects the need to flip the placement. + * @memberof modifiers + * @inner + */ + flip: { + /** @prop {number} order=600 - Index used to define the order of execution */ + order: 600, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: flip, + /** + * @prop {String|Array} behavior='flip' + * The behavior used to change the popper's placement. It can be one of + * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid + * placements (with optional variations). + */ + behavior: 'flip', + /** + * @prop {number} padding=5 + * The popper will flip if it hits the edges of the `boundariesElement` + */ + padding: 5, + /** + * @prop {String|HTMLElement} boundariesElement='viewport' + * The element which will define the boundaries of the popper position, + * the popper will never be placed outside of the defined boundaries + * (except if keepTogether is enabled) + */ + boundariesElement: 'viewport' + }, + + /** + * Modifier used to make the popper flow toward the inner of the reference element. + * By default, when this modifier is disabled, the popper will be placed outside + * the reference element. + * @memberof modifiers + * @inner + */ + inner: { + /** @prop {number} order=700 - Index used to define the order of execution */ + order: 700, + /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */ + enabled: false, + /** @prop {ModifierFn} */ + fn: inner + }, + + /** + * Modifier used to hide the popper when its reference element is outside of the + * popper boundaries. It will set a `x-out-of-boundaries` attribute which can + * be used to hide with a CSS selector the popper when its reference is + * out of boundaries. + * + * Requires the `preventOverflow` modifier before it in order to work. + * @memberof modifiers + * @inner + */ + hide: { + /** @prop {number} order=800 - Index used to define the order of execution */ + order: 800, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: hide + }, + + /** + * Computes the style that will be applied to the popper element to gets + * properly positioned. + * + * Note that this modifier will not touch the DOM, it just prepares the styles + * so that `applyStyle` modifier can apply it. This separation is useful + * in case you need to replace `applyStyle` with a custom implementation. + * + * This modifier has `850` as `order` value to maintain backward compatibility + * with previous versions of Popper.js. Expect the modifiers ordering method + * to change in future major versions of the library. + * + * @memberof modifiers + * @inner + */ + computeStyle: { + /** @prop {number} order=850 - Index used to define the order of execution */ + order: 850, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: computeStyle, + /** + * @prop {Boolean} gpuAcceleration=true + * If true, it uses the CSS 3d transformation to position the popper. + * Otherwise, it will use the `top` and `left` properties. + */ + gpuAcceleration: true, + /** + * @prop {string} [x='bottom'] + * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin. + * Change this if your popper should grow in a direction different from `bottom` + */ + x: 'bottom', + /** + * @prop {string} [x='left'] + * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin. + * Change this if your popper should grow in a direction different from `right` + */ + y: 'right' + }, + + /** + * Applies the computed styles to the popper element. + * + * All the DOM manipulations are limited to this modifier. This is useful in case + * you want to integrate Popper.js inside a framework or view library and you + * want to delegate all the DOM manipulations to it. + * + * Note that if you disable this modifier, you must make sure the popper element + * has its position set to `absolute` before Popper.js can do its work! + * + * Just disable this modifier and define you own to achieve the desired effect. + * + * @memberof modifiers + * @inner + */ + applyStyle: { + /** @prop {number} order=900 - Index used to define the order of execution */ + order: 900, + /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */ + enabled: true, + /** @prop {ModifierFn} */ + fn: applyStyle, + /** @prop {Function} */ + onLoad: applyStyleOnLoad, + /** + * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier + * @prop {Boolean} gpuAcceleration=true + * If true, it uses the CSS 3d transformation to position the popper. + * Otherwise, it will use the `top` and `left` properties. + */ + gpuAcceleration: undefined + } + }; + + /** + * The `dataObject` is an object containing all the informations used by Popper.js + * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks. + * @name dataObject + * @property {Object} data.instance The Popper.js instance + * @property {String} data.placement Placement applied to popper + * @property {String} data.originalPlacement Placement originally defined on init + * @property {Boolean} data.flipped True if popper has been flipped by flip modifier + * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper. + * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier + * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`) + * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`) + * @property {Object} data.boundaries Offsets of the popper boundaries + * @property {Object} data.offsets The measurements of popper, reference and arrow elements. + * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values + * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values + * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0 + */ + + /** + * Default options provided to Popper.js constructor.
+ * These can be overriden using the `options` argument of Popper.js.
+ * To override an option, simply pass as 3rd argument an object with the same + * structure of this object, example: + * ``` + * new Popper(ref, pop, { + * modifiers: { + * preventOverflow: { enabled: false } + * } + * }) + * ``` + * @type {Object} + * @static + * @memberof Popper + */ + var Defaults = { + /** + * Popper's placement + * @prop {Popper.placements} placement='bottom' + */ + placement: 'bottom', + + /** + * Set this to true if you want popper to position it self in 'fixed' mode + * @prop {Boolean} positionFixed=false + */ + positionFixed: false, + + /** + * Whether events (resize, scroll) are initially enabled + * @prop {Boolean} eventsEnabled=true + */ + eventsEnabled: true, + + /** + * Set to true if you want to automatically remove the popper when + * you call the `destroy` method. + * @prop {Boolean} removeOnDestroy=false + */ + removeOnDestroy: false, + + /** + * Callback called when the popper is created.
+ * By default, is set to no-op.
+ * Access Popper.js instance with `data.instance`. + * @prop {onCreate} + */ + onCreate: function onCreate() {}, + + /** + * Callback called when the popper is updated, this callback is not called + * on the initialization/creation of the popper, but only on subsequent + * updates.
+ * By default, is set to no-op.
+ * Access Popper.js instance with `data.instance`. + * @prop {onUpdate} + */ + onUpdate: function onUpdate() {}, + + /** + * List of modifiers used to modify the offsets before they are applied to the popper. + * They provide most of the functionalities of Popper.js + * @prop {modifiers} + */ + modifiers: modifiers + }; + + /** + * @callback onCreate + * @param {dataObject} data + */ + + /** + * @callback onUpdate + * @param {dataObject} data + */ + + // Utils + // Methods + var Popper = function () { + /** + * Create a new Popper.js instance + * @class Popper + * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper + * @param {HTMLElement} popper - The HTML element used as popper. + * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults) + * @return {Object} instance - The generated Popper.js instance + */ + function Popper(reference, popper) { + var _this = this; + + var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; + classCallCheck(this, Popper); + + this.scheduleUpdate = function () { + return requestAnimationFrame(_this.update); + }; + + // make update() debounced, so that it only runs at most once-per-tick + this.update = debounce(this.update.bind(this)); + + // with {} we create a new object with the options inside it + this.options = _extends({}, Popper.Defaults, options); + + // init state + this.state = { + isDestroyed: false, + isCreated: false, + scrollParents: [] + }; + + // get reference and popper elements (allow jQuery wrappers) + this.reference = reference && reference.jquery ? reference[0] : reference; + this.popper = popper && popper.jquery ? popper[0] : popper; + + // Deep merge modifiers options + this.options.modifiers = {}; + Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) { + _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {}); + }); + + // Refactoring modifiers' list (Object => Array) + this.modifiers = Object.keys(this.options.modifiers).map(function (name) { + return _extends({ + name: name + }, _this.options.modifiers[name]); + }) + // sort the modifiers by order + .sort(function (a, b) { + return a.order - b.order; + }); + + // modifiers have the ability to execute arbitrary code when Popper.js get inited + // such code is executed in the same order of its modifier + // they could add new properties to their options configuration + // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`! + this.modifiers.forEach(function (modifierOptions) { + if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) { + modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state); + } + }); + + // fire the first update to position the popper in the right place + this.update(); + + var eventsEnabled = this.options.eventsEnabled; + if (eventsEnabled) { + // setup event listeners, they will take care of update the position in specific situations + this.enableEventListeners(); + } + + this.state.eventsEnabled = eventsEnabled; + } + + // We can't use class properties because they don't get listed in the + // class prototype and break stuff like Sinon stubs + + + createClass(Popper, [{ + key: 'update', + value: function update$$1() { + return update.call(this); + } + }, { + key: 'destroy', + value: function destroy$$1() { + return destroy.call(this); + } + }, { + key: 'enableEventListeners', + value: function enableEventListeners$$1() { + return enableEventListeners.call(this); + } + }, { + key: 'disableEventListeners', + value: function disableEventListeners$$1() { + return disableEventListeners.call(this); + } + + /** + * Schedule an update, it will run on the next UI update available + * @method scheduleUpdate + * @memberof Popper + */ + + + /** + * Collection of utilities useful when writing custom modifiers. + * Starting from version 1.7, this method is available only if you + * include `popper-utils.js` before `popper.js`. + * + * **DEPRECATION**: This way to access PopperUtils is deprecated + * and will be removed in v2! Use the PopperUtils module directly instead. + * Due to the high instability of the methods contained in Utils, we can't + * guarantee them to follow semver. Use them at your own risk! + * @static + * @private + * @type {Object} + * @deprecated since version 1.8 + * @member Utils + * @memberof Popper + */ + + }]); + return Popper; + }(); + + /** + * The `referenceObject` is an object that provides an interface compatible with Popper.js + * and lets you use it as replacement of a real DOM node.
+ * You can use this method to position a popper relatively to a set of coordinates + * in case you don't have a DOM node to use as reference. + * + * ``` + * new Popper(referenceObject, popperNode); + * ``` + * + * NB: This feature isn't supported in Internet Explorer 10 + * @name referenceObject + * @property {Function} data.getBoundingClientRect + * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method. + * @property {number} data.clientWidth + * An ES6 getter that will return the width of the virtual reference element. + * @property {number} data.clientHeight + * An ES6 getter that will return the height of the virtual reference element. + */ + + + Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils; + Popper.placements = placements; + Popper.Defaults = Defaults; + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): dropdown.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Dropdown = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'dropdown'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.dropdown'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key + + var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key + + var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key + + var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key + + var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key + + var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse) + + var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE); + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + CLICK: "click" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY, + KEYDOWN_DATA_API: "keydown" + EVENT_KEY + DATA_API_KEY, + KEYUP_DATA_API: "keyup" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + DISABLED: 'disabled', + SHOW: 'show', + DROPUP: 'dropup', + DROPRIGHT: 'dropright', + DROPLEFT: 'dropleft', + MENURIGHT: 'dropdown-menu-right', + MENULEFT: 'dropdown-menu-left', + POSITION_STATIC: 'position-static' + }; + var Selector = { + DATA_TOGGLE: '[data-toggle="dropdown"]', + FORM_CHILD: '.dropdown form', + MENU: '.dropdown-menu', + NAVBAR_NAV: '.navbar-nav', + VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' + }; + var AttachmentMap = { + TOP: 'top-start', + TOPEND: 'top-end', + BOTTOM: 'bottom-start', + BOTTOMEND: 'bottom-end', + RIGHT: 'right-start', + RIGHTEND: 'right-end', + LEFT: 'left-start', + LEFTEND: 'left-end' + }; + var Default = { + offset: 0, + flip: true, + boundary: 'scrollParent', + reference: 'toggle', + display: 'dynamic' + }; + var DefaultType = { + offset: '(number|string|function)', + flip: 'boolean', + boundary: '(string|element)', + reference: '(string|element)', + display: 'string' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Dropdown = + /*#__PURE__*/ + function () { + function Dropdown(element, config) { + this._element = element; + this._popper = null; + this._config = this._getConfig(config); + this._menu = this._getMenuElement(); + this._inNavbar = this._detectNavbar(); + + this._addEventListeners(); + } // Getters + + + var _proto = Dropdown.prototype; + + // Public + _proto.toggle = function toggle() { + if (this._element.disabled || $$$1(this._element).hasClass(ClassName.DISABLED)) { + return; + } + + var parent = Dropdown._getParentFromElement(this._element); + + var isActive = $$$1(this._menu).hasClass(ClassName.SHOW); + + Dropdown._clearMenus(); + + if (isActive) { + return; + } + + var relatedTarget = { + relatedTarget: this._element + }; + var showEvent = $$$1.Event(Event.SHOW, relatedTarget); + $$$1(parent).trigger(showEvent); + + if (showEvent.isDefaultPrevented()) { + return; + } // Disable totally Popper.js for Dropdown in Navbar + + + if (!this._inNavbar) { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)'); + } + + var referenceElement = this._element; + + if (this._config.reference === 'parent') { + referenceElement = parent; + } else if (Util.isElement(this._config.reference)) { + referenceElement = this._config.reference; // Check if it's jQuery element + + if (typeof this._config.reference.jquery !== 'undefined') { + referenceElement = this._config.reference[0]; + } + } // If boundary is not `scrollParent`, then set position to `static` + // to allow the menu to "escape" the scroll parent's boundaries + // https://github.com/twbs/bootstrap/issues/24251 + + + if (this._config.boundary !== 'scrollParent') { + $$$1(parent).addClass(ClassName.POSITION_STATIC); + } + + this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()); + } // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + + + if ('ontouchstart' in document.documentElement && $$$1(parent).closest(Selector.NAVBAR_NAV).length === 0) { + $$$1(document.body).children().on('mouseover', null, $$$1.noop); + } + + this._element.focus(); + + this._element.setAttribute('aria-expanded', true); + + $$$1(this._menu).toggleClass(ClassName.SHOW); + $$$1(parent).toggleClass(ClassName.SHOW).trigger($$$1.Event(Event.SHOWN, relatedTarget)); + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + $$$1(this._element).off(EVENT_KEY); + this._element = null; + this._menu = null; + + if (this._popper !== null) { + this._popper.destroy(); + + this._popper = null; + } + }; + + _proto.update = function update() { + this._inNavbar = this._detectNavbar(); + + if (this._popper !== null) { + this._popper.scheduleUpdate(); + } + }; // Private + + + _proto._addEventListeners = function _addEventListeners() { + var _this = this; + + $$$1(this._element).on(Event.CLICK, function (event) { + event.preventDefault(); + event.stopPropagation(); + + _this.toggle(); + }); + }; + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, this.constructor.Default, $$$1(this._element).data(), config); + Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); + return config; + }; + + _proto._getMenuElement = function _getMenuElement() { + if (!this._menu) { + var parent = Dropdown._getParentFromElement(this._element); + + if (parent) { + this._menu = parent.querySelector(Selector.MENU); + } + } + + return this._menu; + }; + + _proto._getPlacement = function _getPlacement() { + var $parentDropdown = $$$1(this._element.parentNode); + var placement = AttachmentMap.BOTTOM; // Handle dropup + + if ($parentDropdown.hasClass(ClassName.DROPUP)) { + placement = AttachmentMap.TOP; + + if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) { + placement = AttachmentMap.TOPEND; + } + } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) { + placement = AttachmentMap.RIGHT; + } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) { + placement = AttachmentMap.LEFT; + } else if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) { + placement = AttachmentMap.BOTTOMEND; + } + + return placement; + }; + + _proto._detectNavbar = function _detectNavbar() { + return $$$1(this._element).closest('.navbar').length > 0; + }; + + _proto._getPopperConfig = function _getPopperConfig() { + var _this2 = this; + + var offsetConf = {}; + + if (typeof this._config.offset === 'function') { + offsetConf.fn = function (data) { + data.offsets = _objectSpread({}, data.offsets, _this2._config.offset(data.offsets) || {}); + return data; + }; + } else { + offsetConf.offset = this._config.offset; + } + + var popperConfig = { + placement: this._getPlacement(), + modifiers: { + offset: offsetConf, + flip: { + enabled: this._config.flip + }, + preventOverflow: { + boundariesElement: this._config.boundary + } + } // Disable Popper.js if we have a static display + + }; + + if (this._config.display === 'static') { + popperConfig.modifiers.applyStyle = { + enabled: false + }; + } + + return popperConfig; + }; // Static + + + Dropdown._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = typeof config === 'object' ? config : null; + + if (!data) { + data = new Dropdown(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + Dropdown._clearMenus = function _clearMenus(event) { + if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) { + return; + } + + var toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE)); + + for (var i = 0, len = toggles.length; i < len; i++) { + var parent = Dropdown._getParentFromElement(toggles[i]); + + var context = $$$1(toggles[i]).data(DATA_KEY); + var relatedTarget = { + relatedTarget: toggles[i] + }; + + if (event && event.type === 'click') { + relatedTarget.clickEvent = event; + } + + if (!context) { + continue; + } + + var dropdownMenu = context._menu; + + if (!$$$1(parent).hasClass(ClassName.SHOW)) { + continue; + } + + if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $$$1.contains(parent, event.target)) { + continue; + } + + var hideEvent = $$$1.Event(Event.HIDE, relatedTarget); + $$$1(parent).trigger(hideEvent); + + if (hideEvent.isDefaultPrevented()) { + continue; + } // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + + + if ('ontouchstart' in document.documentElement) { + $$$1(document.body).children().off('mouseover', null, $$$1.noop); + } + + toggles[i].setAttribute('aria-expanded', 'false'); + $$$1(dropdownMenu).removeClass(ClassName.SHOW); + $$$1(parent).removeClass(ClassName.SHOW).trigger($$$1.Event(Event.HIDDEN, relatedTarget)); + } + }; + + Dropdown._getParentFromElement = function _getParentFromElement(element) { + var parent; + var selector = Util.getSelectorFromElement(element); + + if (selector) { + parent = document.querySelector(selector); + } + + return parent || element.parentNode; + }; // eslint-disable-next-line complexity + + + Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) { + // If not input/textarea: + // - And not a key in REGEXP_KEYDOWN => not a dropdown command + // If input/textarea: + // - If space key => not a dropdown command + // - If key is other than escape + // - If key is not up or down => not a dropdown command + // - If trigger inside the menu => not a dropdown command + if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $$$1(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + + if (this.disabled || $$$1(this).hasClass(ClassName.DISABLED)) { + return; + } + + var parent = Dropdown._getParentFromElement(this); + + var isActive = $$$1(parent).hasClass(ClassName.SHOW); + + if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { + if (event.which === ESCAPE_KEYCODE) { + var toggle = parent.querySelector(Selector.DATA_TOGGLE); + $$$1(toggle).trigger('focus'); + } + + $$$1(this).trigger('click'); + return; + } + + var items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS)); + + if (items.length === 0) { + return; + } + + var index = items.indexOf(event.target); + + if (event.which === ARROW_UP_KEYCODE && index > 0) { + // Up + index--; + } + + if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { + // Down + index++; + } + + if (index < 0) { + index = 0; + } + + items[index].focus(); + }; + + _createClass(Dropdown, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }, { + key: "DefaultType", + get: function get() { + return DefaultType; + } + }]); + + return Dropdown; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + " " + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + event.preventDefault(); + event.stopPropagation(); + + Dropdown._jQueryInterface.call($$$1(this), 'toggle'); + }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) { + e.stopPropagation(); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Dropdown._jQueryInterface; + $$$1.fn[NAME].Constructor = Dropdown; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Dropdown._jQueryInterface; + }; + + return Dropdown; + }($, Popper); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): modal.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Modal = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'modal'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.modal'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key + + var Default = { + backdrop: true, + keyboard: true, + focus: true, + show: true + }; + var DefaultType = { + backdrop: '(boolean|string)', + keyboard: 'boolean', + focus: 'boolean', + show: 'boolean' + }; + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + FOCUSIN: "focusin" + EVENT_KEY, + RESIZE: "resize" + EVENT_KEY, + CLICK_DISMISS: "click.dismiss" + EVENT_KEY, + KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY, + MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY, + MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + SCROLLBAR_MEASURER: 'modal-scrollbar-measure', + BACKDROP: 'modal-backdrop', + OPEN: 'modal-open', + FADE: 'fade', + SHOW: 'show' + }; + var Selector = { + DIALOG: '.modal-dialog', + DATA_TOGGLE: '[data-toggle="modal"]', + DATA_DISMISS: '[data-dismiss="modal"]', + FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', + STICKY_CONTENT: '.sticky-top' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Modal = + /*#__PURE__*/ + function () { + function Modal(element, config) { + this._config = this._getConfig(config); + this._element = element; + this._dialog = element.querySelector(Selector.DIALOG); + this._backdrop = null; + this._isShown = false; + this._isBodyOverflowing = false; + this._ignoreBackdropClick = false; + this._scrollbarWidth = 0; + } // Getters + + + var _proto = Modal.prototype; + + // Public + _proto.toggle = function toggle(relatedTarget) { + return this._isShown ? this.hide() : this.show(relatedTarget); + }; + + _proto.show = function show(relatedTarget) { + var _this = this; + + if (this._isTransitioning || this._isShown) { + return; + } + + if ($$$1(this._element).hasClass(ClassName.FADE)) { + this._isTransitioning = true; + } + + var showEvent = $$$1.Event(Event.SHOW, { + relatedTarget: relatedTarget + }); + $$$1(this._element).trigger(showEvent); + + if (this._isShown || showEvent.isDefaultPrevented()) { + return; + } + + this._isShown = true; + + this._checkScrollbar(); + + this._setScrollbar(); + + this._adjustDialog(); + + $$$1(document.body).addClass(ClassName.OPEN); + + this._setEscapeEvent(); + + this._setResizeEvent(); + + $$$1(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) { + return _this.hide(event); + }); + $$$1(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () { + $$$1(_this._element).one(Event.MOUSEUP_DISMISS, function (event) { + if ($$$1(event.target).is(_this._element)) { + _this._ignoreBackdropClick = true; + } + }); + }); + + this._showBackdrop(function () { + return _this._showElement(relatedTarget); + }); + }; + + _proto.hide = function hide(event) { + var _this2 = this; + + if (event) { + event.preventDefault(); + } + + if (this._isTransitioning || !this._isShown) { + return; + } + + var hideEvent = $$$1.Event(Event.HIDE); + $$$1(this._element).trigger(hideEvent); + + if (!this._isShown || hideEvent.isDefaultPrevented()) { + return; + } + + this._isShown = false; + var transition = $$$1(this._element).hasClass(ClassName.FADE); + + if (transition) { + this._isTransitioning = true; + } + + this._setEscapeEvent(); + + this._setResizeEvent(); + + $$$1(document).off(Event.FOCUSIN); + $$$1(this._element).removeClass(ClassName.SHOW); + $$$1(this._element).off(Event.CLICK_DISMISS); + $$$1(this._dialog).off(Event.MOUSEDOWN_DISMISS); + + if (transition) { + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._element).one(Util.TRANSITION_END, function (event) { + return _this2._hideModal(event); + }).emulateTransitionEnd(transitionDuration); + } else { + this._hideModal(); + } + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + $$$1(window, document, this._element, this._backdrop).off(EVENT_KEY); + this._config = null; + this._element = null; + this._dialog = null; + this._backdrop = null; + this._isShown = null; + this._isBodyOverflowing = null; + this._ignoreBackdropClick = null; + this._scrollbarWidth = null; + }; + + _proto.handleUpdate = function handleUpdate() { + this._adjustDialog(); + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, config); + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._showElement = function _showElement(relatedTarget) { + var _this3 = this; + + var transition = $$$1(this._element).hasClass(ClassName.FADE); + + if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { + // Don't move modal's DOM position + document.body.appendChild(this._element); + } + + this._element.style.display = 'block'; + + this._element.removeAttribute('aria-hidden'); + + this._element.scrollTop = 0; + + if (transition) { + Util.reflow(this._element); + } + + $$$1(this._element).addClass(ClassName.SHOW); + + if (this._config.focus) { + this._enforceFocus(); + } + + var shownEvent = $$$1.Event(Event.SHOWN, { + relatedTarget: relatedTarget + }); + + var transitionComplete = function transitionComplete() { + if (_this3._config.focus) { + _this3._element.focus(); + } + + _this3._isTransitioning = false; + $$$1(_this3._element).trigger(shownEvent); + }; + + if (transition) { + var transitionDuration = Util.getTransitionDurationFromElement(this._element); + $$$1(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration); + } else { + transitionComplete(); + } + }; + + _proto._enforceFocus = function _enforceFocus() { + var _this4 = this; + + $$$1(document).off(Event.FOCUSIN) // Guard against infinite focus loop + .on(Event.FOCUSIN, function (event) { + if (document !== event.target && _this4._element !== event.target && $$$1(_this4._element).has(event.target).length === 0) { + _this4._element.focus(); + } + }); + }; + + _proto._setEscapeEvent = function _setEscapeEvent() { + var _this5 = this; + + if (this._isShown && this._config.keyboard) { + $$$1(this._element).on(Event.KEYDOWN_DISMISS, function (event) { + if (event.which === ESCAPE_KEYCODE) { + event.preventDefault(); + + _this5.hide(); + } + }); + } else if (!this._isShown) { + $$$1(this._element).off(Event.KEYDOWN_DISMISS); + } + }; + + _proto._setResizeEvent = function _setResizeEvent() { + var _this6 = this; + + if (this._isShown) { + $$$1(window).on(Event.RESIZE, function (event) { + return _this6.handleUpdate(event); + }); + } else { + $$$1(window).off(Event.RESIZE); + } + }; + + _proto._hideModal = function _hideModal() { + var _this7 = this; + + this._element.style.display = 'none'; + + this._element.setAttribute('aria-hidden', true); + + this._isTransitioning = false; + + this._showBackdrop(function () { + $$$1(document.body).removeClass(ClassName.OPEN); + + _this7._resetAdjustments(); + + _this7._resetScrollbar(); + + $$$1(_this7._element).trigger(Event.HIDDEN); + }); + }; + + _proto._removeBackdrop = function _removeBackdrop() { + if (this._backdrop) { + $$$1(this._backdrop).remove(); + this._backdrop = null; + } + }; + + _proto._showBackdrop = function _showBackdrop(callback) { + var _this8 = this; + + var animate = $$$1(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : ''; + + if (this._isShown && this._config.backdrop) { + this._backdrop = document.createElement('div'); + this._backdrop.className = ClassName.BACKDROP; + + if (animate) { + this._backdrop.classList.add(animate); + } + + $$$1(this._backdrop).appendTo(document.body); + $$$1(this._element).on(Event.CLICK_DISMISS, function (event) { + if (_this8._ignoreBackdropClick) { + _this8._ignoreBackdropClick = false; + return; + } + + if (event.target !== event.currentTarget) { + return; + } + + if (_this8._config.backdrop === 'static') { + _this8._element.focus(); + } else { + _this8.hide(); + } + }); + + if (animate) { + Util.reflow(this._backdrop); + } + + $$$1(this._backdrop).addClass(ClassName.SHOW); + + if (!callback) { + return; + } + + if (!animate) { + callback(); + return; + } + + var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); + $$$1(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration); + } else if (!this._isShown && this._backdrop) { + $$$1(this._backdrop).removeClass(ClassName.SHOW); + + var callbackRemove = function callbackRemove() { + _this8._removeBackdrop(); + + if (callback) { + callback(); + } + }; + + if ($$$1(this._element).hasClass(ClassName.FADE)) { + var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); + + $$$1(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration); + } else { + callbackRemove(); + } + } else if (callback) { + callback(); + } + }; // ---------------------------------------------------------------------- + // the following methods are used to handle overflowing modals + // todo (fat): these should probably be refactored out of modal.js + // ---------------------------------------------------------------------- + + + _proto._adjustDialog = function _adjustDialog() { + var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; + + if (!this._isBodyOverflowing && isModalOverflowing) { + this._element.style.paddingLeft = this._scrollbarWidth + "px"; + } + + if (this._isBodyOverflowing && !isModalOverflowing) { + this._element.style.paddingRight = this._scrollbarWidth + "px"; + } + }; + + _proto._resetAdjustments = function _resetAdjustments() { + this._element.style.paddingLeft = ''; + this._element.style.paddingRight = ''; + }; + + _proto._checkScrollbar = function _checkScrollbar() { + var rect = document.body.getBoundingClientRect(); + this._isBodyOverflowing = rect.left + rect.right < window.innerWidth; + this._scrollbarWidth = this._getScrollbarWidth(); + }; + + _proto._setScrollbar = function _setScrollbar() { + var _this9 = this; + + if (this._isBodyOverflowing) { + // Note: DOMNode.style.paddingRight returns the actual value or '' if not set + // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set + var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)); + var stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT)); // Adjust fixed content padding + + $$$1(fixedContent).each(function (index, element) { + var actualPadding = element.style.paddingRight; + var calculatedPadding = $$$1(element).css('padding-right'); + $$$1(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px"); + }); // Adjust sticky content margin + + $$$1(stickyContent).each(function (index, element) { + var actualMargin = element.style.marginRight; + var calculatedMargin = $$$1(element).css('margin-right'); + $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px"); + }); // Adjust body padding + + var actualPadding = document.body.style.paddingRight; + var calculatedPadding = $$$1(document.body).css('padding-right'); + $$$1(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px"); + } + }; + + _proto._resetScrollbar = function _resetScrollbar() { + // Restore fixed content padding + var fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT)); + $$$1(fixedContent).each(function (index, element) { + var padding = $$$1(element).data('padding-right'); + $$$1(element).removeData('padding-right'); + element.style.paddingRight = padding ? padding : ''; + }); // Restore sticky content + + var elements = [].slice.call(document.querySelectorAll("" + Selector.STICKY_CONTENT)); + $$$1(elements).each(function (index, element) { + var margin = $$$1(element).data('margin-right'); + + if (typeof margin !== 'undefined') { + $$$1(element).css('margin-right', margin).removeData('margin-right'); + } + }); // Restore body padding + + var padding = $$$1(document.body).data('padding-right'); + $$$1(document.body).removeData('padding-right'); + document.body.style.paddingRight = padding ? padding : ''; + }; + + _proto._getScrollbarWidth = function _getScrollbarWidth() { + // thx d.walsh + var scrollDiv = document.createElement('div'); + scrollDiv.className = ClassName.SCROLLBAR_MEASURER; + document.body.appendChild(scrollDiv); + var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + return scrollbarWidth; + }; // Static + + + Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = _objectSpread({}, Default, $$$1(this).data(), typeof config === 'object' && config ? config : {}); + + if (!data) { + data = new Modal(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](relatedTarget); + } else if (_config.show) { + data.show(relatedTarget); + } + }); + }; + + _createClass(Modal, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }]); + + return Modal; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + + $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) { + var _this10 = this; + + var target; + var selector = Util.getSelectorFromElement(this); + + if (selector) { + target = document.querySelector(selector); + } + + var config = $$$1(target).data(DATA_KEY) ? 'toggle' : _objectSpread({}, $$$1(target).data(), $$$1(this).data()); + + if (this.tagName === 'A' || this.tagName === 'AREA') { + event.preventDefault(); + } + + var $target = $$$1(target).one(Event.SHOW, function (showEvent) { + if (showEvent.isDefaultPrevented()) { + // Only register focus restorer if modal will actually get shown + return; + } + + $target.one(Event.HIDDEN, function () { + if ($$$1(_this10).is(':visible')) { + _this10.focus(); + } + }); + }); + + Modal._jQueryInterface.call($$$1(target), config, this); + }); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $$$1.fn[NAME] = Modal._jQueryInterface; + $$$1.fn[NAME].Constructor = Modal; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Modal._jQueryInterface; + }; + + return Modal; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): tooltip.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Tooltip = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'tooltip'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.tooltip'; + var EVENT_KEY = "." + DATA_KEY; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var CLASS_PREFIX = 'bs-tooltip'; + var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); + var DefaultType = { + animation: 'boolean', + template: 'string', + title: '(string|element|function)', + trigger: 'string', + delay: '(number|object)', + html: 'boolean', + selector: '(string|boolean)', + placement: '(string|function)', + offset: '(number|string)', + container: '(string|element|boolean)', + fallbackPlacement: '(string|array)', + boundary: '(string|element)' + }; + var AttachmentMap = { + AUTO: 'auto', + TOP: 'top', + RIGHT: 'right', + BOTTOM: 'bottom', + LEFT: 'left' + }; + var Default = { + animation: true, + template: '', + trigger: 'hover focus', + title: '', + delay: 0, + html: false, + selector: false, + placement: 'top', + offset: 0, + container: false, + fallbackPlacement: 'flip', + boundary: 'scrollParent' + }; + var HoverState = { + SHOW: 'show', + OUT: 'out' + }; + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + INSERTED: "inserted" + EVENT_KEY, + CLICK: "click" + EVENT_KEY, + FOCUSIN: "focusin" + EVENT_KEY, + FOCUSOUT: "focusout" + EVENT_KEY, + MOUSEENTER: "mouseenter" + EVENT_KEY, + MOUSELEAVE: "mouseleave" + EVENT_KEY + }; + var ClassName = { + FADE: 'fade', + SHOW: 'show' + }; + var Selector = { + TOOLTIP: '.tooltip', + TOOLTIP_INNER: '.tooltip-inner', + ARROW: '.arrow' + }; + var Trigger = { + HOVER: 'hover', + FOCUS: 'focus', + CLICK: 'click', + MANUAL: 'manual' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Tooltip = + /*#__PURE__*/ + function () { + function Tooltip(element, config) { + /** + * Check for Popper dependency + * Popper - https://popper.js.org + */ + if (typeof Popper === 'undefined') { + throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)'); + } // private + + + this._isEnabled = true; + this._timeout = 0; + this._hoverState = ''; + this._activeTrigger = {}; + this._popper = null; // Protected + + this.element = element; + this.config = this._getConfig(config); + this.tip = null; + + this._setListeners(); + } // Getters + + + var _proto = Tooltip.prototype; + + // Public + _proto.enable = function enable() { + this._isEnabled = true; + }; + + _proto.disable = function disable() { + this._isEnabled = false; + }; + + _proto.toggleEnabled = function toggleEnabled() { + this._isEnabled = !this._isEnabled; + }; + + _proto.toggle = function toggle(event) { + if (!this._isEnabled) { + return; + } + + if (event) { + var dataKey = this.constructor.DATA_KEY; + var context = $$$1(event.currentTarget).data(dataKey); + + if (!context) { + context = new this.constructor(event.currentTarget, this._getDelegateConfig()); + $$$1(event.currentTarget).data(dataKey, context); + } + + context._activeTrigger.click = !context._activeTrigger.click; + + if (context._isWithActiveTrigger()) { + context._enter(null, context); + } else { + context._leave(null, context); + } + } else { + if ($$$1(this.getTipElement()).hasClass(ClassName.SHOW)) { + this._leave(null, this); + + return; + } + + this._enter(null, this); + } + }; + + _proto.dispose = function dispose() { + clearTimeout(this._timeout); + $$$1.removeData(this.element, this.constructor.DATA_KEY); + $$$1(this.element).off(this.constructor.EVENT_KEY); + $$$1(this.element).closest('.modal').off('hide.bs.modal'); + + if (this.tip) { + $$$1(this.tip).remove(); + } + + this._isEnabled = null; + this._timeout = null; + this._hoverState = null; + this._activeTrigger = null; + + if (this._popper !== null) { + this._popper.destroy(); + } + + this._popper = null; + this.element = null; + this.config = null; + this.tip = null; + }; + + _proto.show = function show() { + var _this = this; + + if ($$$1(this.element).css('display') === 'none') { + throw new Error('Please use show on visible elements'); + } + + var showEvent = $$$1.Event(this.constructor.Event.SHOW); + + if (this.isWithContent() && this._isEnabled) { + $$$1(this.element).trigger(showEvent); + var isInTheDom = $$$1.contains(this.element.ownerDocument.documentElement, this.element); + + if (showEvent.isDefaultPrevented() || !isInTheDom) { + return; + } + + var tip = this.getTipElement(); + var tipId = Util.getUID(this.constructor.NAME); + tip.setAttribute('id', tipId); + this.element.setAttribute('aria-describedby', tipId); + this.setContent(); + + if (this.config.animation) { + $$$1(tip).addClass(ClassName.FADE); + } + + var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement; + + var attachment = this._getAttachment(placement); + + this.addAttachmentClass(attachment); + var container = this.config.container === false ? document.body : $$$1(document).find(this.config.container); + $$$1(tip).data(this.constructor.DATA_KEY, this); + + if (!$$$1.contains(this.element.ownerDocument.documentElement, this.tip)) { + $$$1(tip).appendTo(container); + } + + $$$1(this.element).trigger(this.constructor.Event.INSERTED); + this._popper = new Popper(this.element, tip, { + placement: attachment, + modifiers: { + offset: { + offset: this.config.offset + }, + flip: { + behavior: this.config.fallbackPlacement + }, + arrow: { + element: Selector.ARROW + }, + preventOverflow: { + boundariesElement: this.config.boundary + } + }, + onCreate: function onCreate(data) { + if (data.originalPlacement !== data.placement) { + _this._handlePopperPlacementChange(data); + } + }, + onUpdate: function onUpdate(data) { + _this._handlePopperPlacementChange(data); + } + }); + $$$1(tip).addClass(ClassName.SHOW); // If this is a touch-enabled device we add extra + // empty mouseover listeners to the body's immediate children; + // only needed because of broken event delegation on iOS + // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + + if ('ontouchstart' in document.documentElement) { + $$$1(document.body).children().on('mouseover', null, $$$1.noop); + } + + var complete = function complete() { + if (_this.config.animation) { + _this._fixTransition(); + } + + var prevHoverState = _this._hoverState; + _this._hoverState = null; + $$$1(_this.element).trigger(_this.constructor.Event.SHOWN); + + if (prevHoverState === HoverState.OUT) { + _this._leave(null, _this); + } + }; + + if ($$$1(this.tip).hasClass(ClassName.FADE)) { + var transitionDuration = Util.getTransitionDurationFromElement(this.tip); + $$$1(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + } else { + complete(); + } + } + }; + + _proto.hide = function hide(callback) { + var _this2 = this; + + var tip = this.getTipElement(); + var hideEvent = $$$1.Event(this.constructor.Event.HIDE); + + var complete = function complete() { + if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) { + tip.parentNode.removeChild(tip); + } + + _this2._cleanTipClass(); + + _this2.element.removeAttribute('aria-describedby'); + + $$$1(_this2.element).trigger(_this2.constructor.Event.HIDDEN); + + if (_this2._popper !== null) { + _this2._popper.destroy(); + } + + if (callback) { + callback(); + } + }; + + $$$1(this.element).trigger(hideEvent); + + if (hideEvent.isDefaultPrevented()) { + return; + } + + $$$1(tip).removeClass(ClassName.SHOW); // If this is a touch-enabled device we remove the extra + // empty mouseover listeners we added for iOS support + + if ('ontouchstart' in document.documentElement) { + $$$1(document.body).children().off('mouseover', null, $$$1.noop); + } + + this._activeTrigger[Trigger.CLICK] = false; + this._activeTrigger[Trigger.FOCUS] = false; + this._activeTrigger[Trigger.HOVER] = false; + + if ($$$1(this.tip).hasClass(ClassName.FADE)) { + var transitionDuration = Util.getTransitionDurationFromElement(tip); + $$$1(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); + } else { + complete(); + } + + this._hoverState = ''; + }; + + _proto.update = function update() { + if (this._popper !== null) { + this._popper.scheduleUpdate(); + } + }; // Protected + + + _proto.isWithContent = function isWithContent() { + return Boolean(this.getTitle()); + }; + + _proto.addAttachmentClass = function addAttachmentClass(attachment) { + $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); + }; + + _proto.getTipElement = function getTipElement() { + this.tip = this.tip || $$$1(this.config.template)[0]; + return this.tip; + }; + + _proto.setContent = function setContent() { + var tip = this.getTipElement(); + this.setElementContent($$$1(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle()); + $$$1(tip).removeClass(ClassName.FADE + " " + ClassName.SHOW); + }; + + _proto.setElementContent = function setElementContent($element, content) { + var html = this.config.html; + + if (typeof content === 'object' && (content.nodeType || content.jquery)) { + // Content is a DOM node or a jQuery + if (html) { + if (!$$$1(content).parent().is($element)) { + $element.empty().append(content); + } + } else { + $element.text($$$1(content).text()); + } + } else { + $element[html ? 'html' : 'text'](content); + } + }; + + _proto.getTitle = function getTitle() { + var title = this.element.getAttribute('data-original-title'); + + if (!title) { + title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title; + } + + return title; + }; // Private + + + _proto._getAttachment = function _getAttachment(placement) { + return AttachmentMap[placement.toUpperCase()]; + }; + + _proto._setListeners = function _setListeners() { + var _this3 = this; + + var triggers = this.config.trigger.split(' '); + triggers.forEach(function (trigger) { + if (trigger === 'click') { + $$$1(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) { + return _this3.toggle(event); + }); + } else if (trigger !== Trigger.MANUAL) { + var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN; + var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT; + $$$1(_this3.element).on(eventIn, _this3.config.selector, function (event) { + return _this3._enter(event); + }).on(eventOut, _this3.config.selector, function (event) { + return _this3._leave(event); + }); + } + + $$$1(_this3.element).closest('.modal').on('hide.bs.modal', function () { + return _this3.hide(); + }); + }); + + if (this.config.selector) { + this.config = _objectSpread({}, this.config, { + trigger: 'manual', + selector: '' + }); + } else { + this._fixTitle(); + } + }; + + _proto._fixTitle = function _fixTitle() { + var titleType = typeof this.element.getAttribute('data-original-title'); + + if (this.element.getAttribute('title') || titleType !== 'string') { + this.element.setAttribute('data-original-title', this.element.getAttribute('title') || ''); + this.element.setAttribute('title', ''); + } + }; + + _proto._enter = function _enter(event, context) { + var dataKey = this.constructor.DATA_KEY; + context = context || $$$1(event.currentTarget).data(dataKey); + + if (!context) { + context = new this.constructor(event.currentTarget, this._getDelegateConfig()); + $$$1(event.currentTarget).data(dataKey, context); + } + + if (event) { + context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true; + } + + if ($$$1(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) { + context._hoverState = HoverState.SHOW; + return; + } + + clearTimeout(context._timeout); + context._hoverState = HoverState.SHOW; + + if (!context.config.delay || !context.config.delay.show) { + context.show(); + return; + } + + context._timeout = setTimeout(function () { + if (context._hoverState === HoverState.SHOW) { + context.show(); + } + }, context.config.delay.show); + }; + + _proto._leave = function _leave(event, context) { + var dataKey = this.constructor.DATA_KEY; + context = context || $$$1(event.currentTarget).data(dataKey); + + if (!context) { + context = new this.constructor(event.currentTarget, this._getDelegateConfig()); + $$$1(event.currentTarget).data(dataKey, context); + } + + if (event) { + context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false; + } + + if (context._isWithActiveTrigger()) { + return; + } + + clearTimeout(context._timeout); + context._hoverState = HoverState.OUT; + + if (!context.config.delay || !context.config.delay.hide) { + context.hide(); + return; + } + + context._timeout = setTimeout(function () { + if (context._hoverState === HoverState.OUT) { + context.hide(); + } + }, context.config.delay.hide); + }; + + _proto._isWithActiveTrigger = function _isWithActiveTrigger() { + for (var trigger in this._activeTrigger) { + if (this._activeTrigger[trigger]) { + return true; + } + } + + return false; + }; + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, this.constructor.Default, $$$1(this.element).data(), typeof config === 'object' && config ? config : {}); + + if (typeof config.delay === 'number') { + config.delay = { + show: config.delay, + hide: config.delay + }; + } + + if (typeof config.title === 'number') { + config.title = config.title.toString(); + } + + if (typeof config.content === 'number') { + config.content = config.content.toString(); + } + + Util.typeCheckConfig(NAME, config, this.constructor.DefaultType); + return config; + }; + + _proto._getDelegateConfig = function _getDelegateConfig() { + var config = {}; + + if (this.config) { + for (var key in this.config) { + if (this.constructor.Default[key] !== this.config[key]) { + config[key] = this.config[key]; + } + } + } + + return config; + }; + + _proto._cleanTipClass = function _cleanTipClass() { + var $tip = $$$1(this.getTipElement()); + var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); + + if (tabClass !== null && tabClass.length) { + $tip.removeClass(tabClass.join('')); + } + }; + + _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) { + var popperInstance = popperData.instance; + this.tip = popperInstance.popper; + + this._cleanTipClass(); + + this.addAttachmentClass(this._getAttachment(popperData.placement)); + }; + + _proto._fixTransition = function _fixTransition() { + var tip = this.getTipElement(); + var initConfigAnimation = this.config.animation; + + if (tip.getAttribute('x-placement') !== null) { + return; + } + + $$$1(tip).removeClass(ClassName.FADE); + this.config.animation = false; + this.hide(); + this.show(); + this.config.animation = initConfigAnimation; + }; // Static + + + Tooltip._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = typeof config === 'object' && config; + + if (!data && /dispose|hide/.test(config)) { + return; + } + + if (!data) { + data = new Tooltip(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + _createClass(Tooltip, null, [{ + key: "VERSION", + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }, { + key: "NAME", + get: function get() { + return NAME; + } + }, { + key: "DATA_KEY", + get: function get() { + return DATA_KEY; + } + }, { + key: "Event", + get: function get() { + return Event; + } + }, { + key: "EVENT_KEY", + get: function get() { + return EVENT_KEY; + } + }, { + key: "DefaultType", + get: function get() { + return DefaultType; + } + }]); + + return Tooltip; + }(); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + + $$$1.fn[NAME] = Tooltip._jQueryInterface; + $$$1.fn[NAME].Constructor = Tooltip; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Tooltip._jQueryInterface; + }; + + return Tooltip; + }($, Popper); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): popover.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var Popover = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'popover'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.popover'; + var EVENT_KEY = "." + DATA_KEY; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var CLASS_PREFIX = 'bs-popover'; + var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); + + var Default = _objectSpread({}, Tooltip.Default, { + placement: 'right', + trigger: 'click', + content: '', + template: '' + }); + + var DefaultType = _objectSpread({}, Tooltip.DefaultType, { + content: '(string|element|function)' + }); + + var ClassName = { + FADE: 'fade', + SHOW: 'show' + }; + var Selector = { + TITLE: '.popover-header', + CONTENT: '.popover-body' + }; + var Event = { + HIDE: "hide" + EVENT_KEY, + HIDDEN: "hidden" + EVENT_KEY, + SHOW: "show" + EVENT_KEY, + SHOWN: "shown" + EVENT_KEY, + INSERTED: "inserted" + EVENT_KEY, + CLICK: "click" + EVENT_KEY, + FOCUSIN: "focusin" + EVENT_KEY, + FOCUSOUT: "focusout" + EVENT_KEY, + MOUSEENTER: "mouseenter" + EVENT_KEY, + MOUSELEAVE: "mouseleave" + EVENT_KEY + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var Popover = + /*#__PURE__*/ + function (_Tooltip) { + _inheritsLoose(Popover, _Tooltip); + + function Popover() { + return _Tooltip.apply(this, arguments) || this; + } + + var _proto = Popover.prototype; + + // Overrides + _proto.isWithContent = function isWithContent() { + return this.getTitle() || this._getContent(); + }; + + _proto.addAttachmentClass = function addAttachmentClass(attachment) { + $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); + }; + + _proto.getTipElement = function getTipElement() { + this.tip = this.tip || $$$1(this.config.template)[0]; + return this.tip; + }; + + _proto.setContent = function setContent() { + var $tip = $$$1(this.getTipElement()); // We use append for html objects to maintain js events + + this.setElementContent($tip.find(Selector.TITLE), this.getTitle()); + + var content = this._getContent(); + + if (typeof content === 'function') { + content = content.call(this.element); + } + + this.setElementContent($tip.find(Selector.CONTENT), content); + $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW); + }; // Private + + + _proto._getContent = function _getContent() { + return this.element.getAttribute('data-content') || this.config.content; + }; + + _proto._cleanTipClass = function _cleanTipClass() { + var $tip = $$$1(this.getTipElement()); + var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); + + if (tabClass !== null && tabClass.length > 0) { + $tip.removeClass(tabClass.join('')); + } + }; // Static + + + Popover._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $$$1(this).data(DATA_KEY); + + var _config = typeof config === 'object' ? config : null; + + if (!data && /destroy|hide/.test(config)) { + return; + } + + if (!data) { + data = new Popover(this, _config); + $$$1(this).data(DATA_KEY, data); + } + + if (typeof config === 'string') { + if (typeof data[config] === 'undefined') { + throw new TypeError("No method named \"" + config + "\""); + } + + data[config](); + } + }); + }; + + _createClass(Popover, null, [{ + key: "VERSION", + // Getters + get: function get() { + return VERSION; + } + }, { + key: "Default", + get: function get() { + return Default; + } + }, { + key: "NAME", + get: function get() { + return NAME; + } + }, { + key: "DATA_KEY", + get: function get() { + return DATA_KEY; + } + }, { + key: "Event", + get: function get() { + return Event; + } + }, { + key: "EVENT_KEY", + get: function get() { + return EVENT_KEY; + } + }, { + key: "DefaultType", + get: function get() { + return DefaultType; + } + }]); + + return Popover; + }(Tooltip); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + + $$$1.fn[NAME] = Popover._jQueryInterface; + $$$1.fn[NAME].Constructor = Popover; + + $$$1.fn[NAME].noConflict = function () { + $$$1.fn[NAME] = JQUERY_NO_CONFLICT; + return Popover._jQueryInterface; + }; + + return Popover; + }($); + + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.1.3): scrollspy.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + + var ScrollSpy = function ($$$1) { + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + var NAME = 'scrollspy'; + var VERSION = '4.1.3'; + var DATA_KEY = 'bs.scrollspy'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $$$1.fn[NAME]; + var Default = { + offset: 10, + method: 'auto', + target: '' + }; + var DefaultType = { + offset: 'number', + method: 'string', + target: '(string|element)' + }; + var Event = { + ACTIVATE: "activate" + EVENT_KEY, + SCROLL: "scroll" + EVENT_KEY, + LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + DROPDOWN_ITEM: 'dropdown-item', + DROPDOWN_MENU: 'dropdown-menu', + ACTIVE: 'active' + }; + var Selector = { + DATA_SPY: '[data-spy="scroll"]', + ACTIVE: '.active', + NAV_LIST_GROUP: '.nav, .list-group', + NAV_LINKS: '.nav-link', + NAV_ITEMS: '.nav-item', + LIST_ITEMS: '.list-group-item', + DROPDOWN: '.dropdown', + DROPDOWN_ITEMS: '.dropdown-item', + DROPDOWN_TOGGLE: '.dropdown-toggle' + }; + var OffsetMethod = { + OFFSET: 'offset', + POSITION: 'position' + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + }; + + var ScrollSpy = + /*#__PURE__*/ + function () { + function ScrollSpy(element, config) { + var _this = this; + + this._element = element; + this._scrollElement = element.tagName === 'BODY' ? window : element; + this._config = this._getConfig(config); + this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS); + this._offsets = []; + this._targets = []; + this._activeTarget = null; + this._scrollHeight = 0; + $$$1(this._scrollElement).on(Event.SCROLL, function (event) { + return _this._process(event); + }); + this.refresh(); + + this._process(); + } // Getters + + + var _proto = ScrollSpy.prototype; + + // Public + _proto.refresh = function refresh() { + var _this2 = this; + + var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION; + var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method; + var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0; + this._offsets = []; + this._targets = []; + this._scrollHeight = this._getScrollHeight(); + var targets = [].slice.call(document.querySelectorAll(this._selector)); + targets.map(function (element) { + var target; + var targetSelector = Util.getSelectorFromElement(element); + + if (targetSelector) { + target = document.querySelector(targetSelector); + } + + if (target) { + var targetBCR = target.getBoundingClientRect(); + + if (targetBCR.width || targetBCR.height) { + // TODO (fat): remove sketch reliance on jQuery position/offset + return [$$$1(target)[offsetMethod]().top + offsetBase, targetSelector]; + } + } + + return null; + }).filter(function (item) { + return item; + }).sort(function (a, b) { + return a[0] - b[0]; + }).forEach(function (item) { + _this2._offsets.push(item[0]); + + _this2._targets.push(item[1]); + }); + }; + + _proto.dispose = function dispose() { + $$$1.removeData(this._element, DATA_KEY); + $$$1(this._scrollElement).off(EVENT_KEY); + this._element = null; + this._scrollElement = null; + this._config = null; + this._selector = null; + this._offsets = null; + this._targets = null; + this._activeTarget = null; + this._scrollHeight = null; + }; // Private + + + _proto._getConfig = function _getConfig(config) { + config = _objectSpread({}, Default, typeof config === 'object' && config ? config : {}); + + if (typeof config.target !== 'string') { + var id = $$$1(config.target).attr('id'); + + if (!id) { + id = Util.getUID(NAME); + $$$1(config.target).attr('id', id); + } + + config.target = "#" + id; + } + + Util.typeCheckConfig(NAME, config, DefaultType); + return config; + }; + + _proto._getScrollTop = function _getScrollTop() { + return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop; + }; + + _proto._getScrollHeight = function _getScrollHeight() { + return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); + }; + + _proto._getOffsetHeight = function _getOffsetHeight() { + return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height; + }; + + _proto._process = function _process() { + var scrollTop = this._getScrollTop() + this._config.offset; + + var scrollHeight = this._getScrollHeight(); + + var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight(); + + if (this._scrollHeight !== scrollHeight) { + this.refresh(); + } + + if (scrollTop >= maxScroll) { + var target = this._targets[this._targets.length - 1]; + + if (this._activeTarget !== target) { + this._activate(target); + } + + return; + } + + if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { + this._activeTarget = null; + + this._clear(); + + return; + } + + var offsetLength = this._offsets.length; + + for (var i = offsetLength; i--;) { + var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]); + + if (isActiveTarget) { + this._activate(this._targets[i]); + } + } + }; + + _proto._activate = function _activate(target) { + this._activeTarget = target; + + this._clear(); + + var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style + + + queries = queries.map(function (selector) { + return selector + "[data-target=\"" + target + "\"]," + (selector + "[href=\"" + target + "\"]"); + }); + var $link = $$$1([].slice.call(document.querySelectorAll(queries.join(',')))); + + if ($link.hasClass(ClassName.DROPDOWN_ITEM)) { + $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE); + $link.addClass(ClassName.ACTIVE); + } else { + // Set triggered link as active + $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active + // With both
',trigger:"hover focus",title:"",delay:0,html:!(An={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"}),selector:!(Dn={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)"}),placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent"},Nn="out",kn={HIDE:"hide"+wn,HIDDEN:"hidden"+wn,SHOW:(On="show")+wn,SHOWN:"shown"+wn,INSERTED:"inserted"+wn,CLICK:"click"+wn,FOCUSIN:"focusin"+wn,FOCUSOUT:"focusout"+wn,MOUSEENTER:"mouseenter"+wn,MOUSELEAVE:"mouseleave"+wn},xn="fade",Pn="show",Ln=".tooltip-inner",jn=".arrow",Hn="hover",Mn="focus",Fn="click",Wn="manual",Rn=function(){function i(e,t){if("undefined"==typeof Ct)throw new TypeError("Bootstrap tooltips require Popper.js (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=e,this.config=this._getConfig(t),this.tip=null,this._setListeners()}var e=i.prototype;return e.enable=function(){this._isEnabled=!0},e.disable=function(){this._isEnabled=!1},e.toggleEnabled=function(){this._isEnabled=!this._isEnabled},e.toggle=function(e){if(this._isEnabled)if(e){var t=this.constructor.DATA_KEY,n=yn(e.currentTarget).data(t);n||(n=new this.constructor(e.currentTarget,this._getDelegateConfig()),yn(e.currentTarget).data(t,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(yn(this.getTipElement()).hasClass(Pn))return void this._leave(null,this);this._enter(null,this)}},e.dispose=function(){clearTimeout(this._timeout),yn.removeData(this.element,this.constructor.DATA_KEY),yn(this.element).off(this.constructor.EVENT_KEY),yn(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&yn(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},e.show=function(){var t=this;if("none"===yn(this.element).css("display"))throw new Error("Please use show on visible elements");var e=yn.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){yn(this.element).trigger(e);var n=yn.contains(this.element.ownerDocument.documentElement,this.element);if(e.isDefaultPrevented()||!n)return;var i=this.getTipElement(),r=we.getUID(this.constructor.NAME);i.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&yn(i).addClass(xn);var o="function"==typeof this.config.placement?this.config.placement.call(this,i,this.element):this.config.placement,s=this._getAttachment(o);this.addAttachmentClass(s);var a=!1===this.config.container?document.body:yn(document).find(this.config.container);yn(i).data(this.constructor.DATA_KEY,this),yn.contains(this.element.ownerDocument.documentElement,this.tip)||yn(i).appendTo(a),yn(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new Ct(this.element,i,{placement:s,modifiers:{offset:{offset:this.config.offset},flip:{behavior:this.config.fallbackPlacement},arrow:{element:jn},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(e){e.originalPlacement!==e.placement&&t._handlePopperPlacementChange(e)},onUpdate:function(e){t._handlePopperPlacementChange(e)}}),yn(i).addClass(Pn),"ontouchstart"in document.documentElement&&yn(document.body).children().on("mouseover",null,yn.noop);var l=function(){t.config.animation&&t._fixTransition();var e=t._hoverState;t._hoverState=null,yn(t.element).trigger(t.constructor.Event.SHOWN),e===Nn&&t._leave(null,t)};if(yn(this.tip).hasClass(xn)){var c=we.getTransitionDurationFromElement(this.tip);yn(this.tip).one(we.TRANSITION_END,l).emulateTransitionEnd(c)}else l()}},e.hide=function(e){var t=this,n=this.getTipElement(),i=yn.Event(this.constructor.Event.HIDE),r=function(){t._hoverState!==On&&n.parentNode&&n.parentNode.removeChild(n),t._cleanTipClass(),t.element.removeAttribute("aria-describedby"),yn(t.element).trigger(t.constructor.Event.HIDDEN),null!==t._popper&&t._popper.destroy(),e&&e()};if(yn(this.element).trigger(i),!i.isDefaultPrevented()){if(yn(n).removeClass(Pn),"ontouchstart"in document.documentElement&&yn(document.body).children().off("mouseover",null,yn.noop),this._activeTrigger[Fn]=!1,this._activeTrigger[Mn]=!1,this._activeTrigger[Hn]=!1,yn(this.tip).hasClass(xn)){var o=we.getTransitionDurationFromElement(n);yn(n).one(we.TRANSITION_END,r).emulateTransitionEnd(o)}else r();this._hoverState=""}},e.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},e.isWithContent=function(){return Boolean(this.getTitle())},e.addAttachmentClass=function(e){yn(this.getTipElement()).addClass(Tn+"-"+e)},e.getTipElement=function(){return this.tip=this.tip||yn(this.config.template)[0],this.tip},e.setContent=function(){var e=this.getTipElement();this.setElementContent(yn(e.querySelectorAll(Ln)),this.getTitle()),yn(e).removeClass(xn+" "+Pn)},e.setElementContent=function(e,t){var n=this.config.html;"object"==typeof t&&(t.nodeType||t.jquery)?n?yn(t).parent().is(e)||e.empty().append(t):e.text(yn(t).text()):e[n?"html":"text"](t)},e.getTitle=function(){var e=this.element.getAttribute("data-original-title");return e||(e="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),e},e._getAttachment=function(e){return An[e.toUpperCase()]},e._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(e){if("click"===e)yn(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(e){return i.toggle(e)});else if(e!==Wn){var t=e===Hn?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=e===Hn?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;yn(i.element).on(t,i.config.selector,function(e){return i._enter(e)}).on(n,i.config.selector,function(e){return i._leave(e)})}yn(i.element).closest(".modal").on("hide.bs.modal",function(){return i.hide()})}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},e._fixTitle=function(){var e=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==e)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},e._enter=function(e,t){var n=this.constructor.DATA_KEY;(t=t||yn(e.currentTarget).data(n))||(t=new this.constructor(e.currentTarget,this._getDelegateConfig()),yn(e.currentTarget).data(n,t)),e&&(t._activeTrigger["focusin"===e.type?Mn:Hn]=!0),yn(t.getTipElement()).hasClass(Pn)||t._hoverState===On?t._hoverState=On:(clearTimeout(t._timeout),t._hoverState=On,t.config.delay&&t.config.delay.show?t._timeout=setTimeout(function(){t._hoverState===On&&t.show()},t.config.delay.show):t.show())},e._leave=function(e,t){var n=this.constructor.DATA_KEY;(t=t||yn(e.currentTarget).data(n))||(t=new this.constructor(e.currentTarget,this._getDelegateConfig()),yn(e.currentTarget).data(n,t)),e&&(t._activeTrigger["focusout"===e.type?Mn:Hn]=!1),t._isWithActiveTrigger()||(clearTimeout(t._timeout),t._hoverState=Nn,t.config.delay&&t.config.delay.hide?t._timeout=setTimeout(function(){t._hoverState===Nn&&t.hide()},t.config.delay.hide):t.hide())},e._isWithActiveTrigger=function(){for(var e in this._activeTrigger)if(this._activeTrigger[e])return!0;return!1},e._getConfig=function(e){return"number"==typeof(e=l({},this.constructor.Default,yn(this.element).data(),"object"==typeof e&&e?e:{})).delay&&(e.delay={show:e.delay,hide:e.delay}),"number"==typeof e.title&&(e.title=e.title.toString()),"number"==typeof e.content&&(e.content=e.content.toString()),we.typeCheckConfig(En,e,this.constructor.DefaultType),e},e._getDelegateConfig=function(){var e={};if(this.config)for(var t in this.config)this.constructor.Default[t]!==this.config[t]&&(e[t]=this.config[t]);return e},e._cleanTipClass=function(){var e=yn(this.getTipElement()),t=e.attr("class").match(Sn);null!==t&&t.length&&e.removeClass(t.join(""))},e._handlePopperPlacementChange=function(e){var t=e.instance;this.tip=t.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(e.placement))},e._fixTransition=function(){var e=this.getTipElement(),t=this.config.animation;null===e.getAttribute("x-placement")&&(yn(e).removeClass(xn),this.config.animation=!1,this.hide(),this.show(),this.config.animation=t)},i._jQueryInterface=function(n){return this.each(function(){var e=yn(this).data(bn),t="object"==typeof n&&n;if((e||!/dispose|hide/.test(n))&&(e||(e=new i(this,t),yn(this).data(bn,e)),"string"==typeof n)){if("undefined"==typeof e[n])throw new TypeError('No method named "'+n+'"');e[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.1.3"}},{key:"Default",get:function(){return In}},{key:"NAME",get:function(){return En}},{key:"DATA_KEY",get:function(){return bn}},{key:"Event",get:function(){return kn}},{key:"EVENT_KEY",get:function(){return wn}},{key:"DefaultType",get:function(){return Dn}}]),i}(),yn.fn[En]=Rn._jQueryInterface,yn.fn[En].Constructor=Rn,yn.fn[En].noConflict=function(){return yn.fn[En]=Cn,Rn._jQueryInterface},Rn),Qi=(Bn="popover",Kn="."+(qn="bs.popover"),Qn=(Un=t).fn[Bn],Yn="bs-popover",Vn=new RegExp("(^|\\s)"+Yn+"\\S+","g"),zn=l({},Ki.Default,{placement:"right",trigger:"click",content:"",template:''}),Gn=l({},Ki.DefaultType,{content:"(string|element|function)"}),Jn="fade",Xn=".popover-header",$n=".popover-body",ei={HIDE:"hide"+Kn,HIDDEN:"hidden"+Kn,SHOW:(Zn="show")+Kn,SHOWN:"shown"+Kn,INSERTED:"inserted"+Kn,CLICK:"click"+Kn,FOCUSIN:"focusin"+Kn,FOCUSOUT:"focusout"+Kn,MOUSEENTER:"mouseenter"+Kn,MOUSELEAVE:"mouseleave"+Kn},ti=function(e){var t,n;function i(){return e.apply(this,arguments)||this}n=e,(t=i).prototype=Object.create(n.prototype),(t.prototype.constructor=t).__proto__=n;var r=i.prototype;return r.isWithContent=function(){return this.getTitle()||this._getContent()},r.addAttachmentClass=function(e){Un(this.getTipElement()).addClass(Yn+"-"+e)},r.getTipElement=function(){return this.tip=this.tip||Un(this.config.template)[0],this.tip},r.setContent=function(){var e=Un(this.getTipElement());this.setElementContent(e.find(Xn),this.getTitle());var t=this._getContent();"function"==typeof t&&(t=t.call(this.element)),this.setElementContent(e.find($n),t),e.removeClass(Jn+" "+Zn)},r._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},r._cleanTipClass=function(){var e=Un(this.getTipElement()),t=e.attr("class").match(Vn);null!==t&&0=this._offsets[r]&&("undefined"==typeof this._offsets[r+1]||e= 0) {\n timeoutDuration = 1;\n break;\n }\n}\n\nfunction microtaskDebounce(fn) {\n var called = false;\n return function () {\n if (called) {\n return;\n }\n called = true;\n window.Promise.resolve().then(function () {\n called = false;\n fn();\n });\n };\n}\n\nfunction taskDebounce(fn) {\n var scheduled = false;\n return function () {\n if (!scheduled) {\n scheduled = true;\n setTimeout(function () {\n scheduled = false;\n fn();\n }, timeoutDuration);\n }\n };\n}\n\nvar supportsMicroTasks = isBrowser && window.Promise;\n\n/**\n* Create a debounced version of a method, that's asynchronously deferred\n* but called in the minimum time possible.\n*\n* @method\n* @memberof Popper.Utils\n* @argument {Function} fn\n* @returns {Function}\n*/\nvar debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;\n\n/**\n * Check if the given variable is a function\n * @method\n * @memberof Popper.Utils\n * @argument {Any} functionToCheck - variable to check\n * @returns {Boolean} answer to: is a function?\n */\nfunction isFunction(functionToCheck) {\n var getType = {};\n return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';\n}\n\n/**\n * Get CSS computed property of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Eement} element\n * @argument {String} property\n */\nfunction getStyleComputedProperty(element, property) {\n if (element.nodeType !== 1) {\n return [];\n }\n // NOTE: 1 DOM access here\n var css = getComputedStyle(element, null);\n return property ? css[property] : css;\n}\n\n/**\n * Returns the parentNode or the host of the element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} parent\n */\nfunction getParentNode(element) {\n if (element.nodeName === 'HTML') {\n return element;\n }\n return element.parentNode || element.host;\n}\n\n/**\n * Returns the scrolling parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} scroll parent\n */\nfunction getScrollParent(element) {\n // Return body, `getScroll` will take care to get the correct `scrollTop` from it\n if (!element) {\n return document.body;\n }\n\n switch (element.nodeName) {\n case 'HTML':\n case 'BODY':\n return element.ownerDocument.body;\n case '#document':\n return element.body;\n }\n\n // Firefox want us to check `-x` and `-y` variations as well\n\n var _getStyleComputedProp = getStyleComputedProperty(element),\n overflow = _getStyleComputedProp.overflow,\n overflowX = _getStyleComputedProp.overflowX,\n overflowY = _getStyleComputedProp.overflowY;\n\n if (/(auto|scroll|overlay)/.test(overflow + overflowY + overflowX)) {\n return element;\n }\n\n return getScrollParent(getParentNode(element));\n}\n\nvar isIE11 = isBrowser && !!(window.MSInputMethodContext && document.documentMode);\nvar isIE10 = isBrowser && /MSIE 10/.test(navigator.userAgent);\n\n/**\n * Determines if the browser is Internet Explorer\n * @method\n * @memberof Popper.Utils\n * @param {Number} version to check\n * @returns {Boolean} isIE\n */\nfunction isIE(version) {\n if (version === 11) {\n return isIE11;\n }\n if (version === 10) {\n return isIE10;\n }\n return isIE11 || isIE10;\n}\n\n/**\n * Returns the offset parent of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} offset parent\n */\nfunction getOffsetParent(element) {\n if (!element) {\n return document.documentElement;\n }\n\n var noOffsetParent = isIE(10) ? document.body : null;\n\n // NOTE: 1 DOM access here\n var offsetParent = element.offsetParent;\n // Skip hidden elements which don't have an offsetParent\n while (offsetParent === noOffsetParent && element.nextElementSibling) {\n offsetParent = (element = element.nextElementSibling).offsetParent;\n }\n\n var nodeName = offsetParent && offsetParent.nodeName;\n\n if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {\n return element ? element.ownerDocument.documentElement : document.documentElement;\n }\n\n // .offsetParent will return the closest TD or TABLE in case\n // no offsetParent is present, I hate this job...\n if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {\n return getOffsetParent(offsetParent);\n }\n\n return offsetParent;\n}\n\nfunction isOffsetContainer(element) {\n var nodeName = element.nodeName;\n\n if (nodeName === 'BODY') {\n return false;\n }\n return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;\n}\n\n/**\n * Finds the root node (document, shadowDOM root) of the given element\n * @method\n * @memberof Popper.Utils\n * @argument {Element} node\n * @returns {Element} root node\n */\nfunction getRoot(node) {\n if (node.parentNode !== null) {\n return getRoot(node.parentNode);\n }\n\n return node;\n}\n\n/**\n * Finds the offset parent common to the two provided nodes\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element1\n * @argument {Element} element2\n * @returns {Element} common offset parent\n */\nfunction findCommonOffsetParent(element1, element2) {\n // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {\n return document.documentElement;\n }\n\n // Here we make sure to give as \"start\" the element that comes first in the DOM\n var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;\n var start = order ? element1 : element2;\n var end = order ? element2 : element1;\n\n // Get common ancestor container\n var range = document.createRange();\n range.setStart(start, 0);\n range.setEnd(end, 0);\n var commonAncestorContainer = range.commonAncestorContainer;\n\n // Both nodes are inside #document\n\n if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {\n if (isOffsetContainer(commonAncestorContainer)) {\n return commonAncestorContainer;\n }\n\n return getOffsetParent(commonAncestorContainer);\n }\n\n // one of the nodes is inside shadowDOM, find which one\n var element1root = getRoot(element1);\n if (element1root.host) {\n return findCommonOffsetParent(element1root.host, element2);\n } else {\n return findCommonOffsetParent(element1, getRoot(element2).host);\n }\n}\n\n/**\n * Gets the scroll value of the given element in the given side (top and left)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {String} side `top` or `left`\n * @returns {number} amount of scrolled pixels\n */\nfunction getScroll(element) {\n var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';\n\n var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';\n var nodeName = element.nodeName;\n\n if (nodeName === 'BODY' || nodeName === 'HTML') {\n var html = element.ownerDocument.documentElement;\n var scrollingElement = element.ownerDocument.scrollingElement || html;\n return scrollingElement[upperSide];\n }\n\n return element[upperSide];\n}\n\n/*\n * Sum or subtract the element scroll values (left and top) from a given rect object\n * @method\n * @memberof Popper.Utils\n * @param {Object} rect - Rect object you want to change\n * @param {HTMLElement} element - The element from the function reads the scroll values\n * @param {Boolean} subtract - set to true if you want to subtract the scroll values\n * @return {Object} rect - The modifier rect object\n */\nfunction includeScroll(rect, element) {\n var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n var scrollTop = getScroll(element, 'top');\n var scrollLeft = getScroll(element, 'left');\n var modifier = subtract ? -1 : 1;\n rect.top += scrollTop * modifier;\n rect.bottom += scrollTop * modifier;\n rect.left += scrollLeft * modifier;\n rect.right += scrollLeft * modifier;\n return rect;\n}\n\n/*\n * Helper to detect borders of a given element\n * @method\n * @memberof Popper.Utils\n * @param {CSSStyleDeclaration} styles\n * Result of `getStyleComputedProperty` on the given element\n * @param {String} axis - `x` or `y`\n * @return {number} borders - The borders size of the given axis\n */\n\nfunction getBordersSize(styles, axis) {\n var sideA = axis === 'x' ? 'Left' : 'Top';\n var sideB = sideA === 'Left' ? 'Right' : 'Bottom';\n\n return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);\n}\n\nfunction getSize(axis, body, html, computedStyle) {\n return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE(10) ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0);\n}\n\nfunction getWindowSizes() {\n var body = document.body;\n var html = document.documentElement;\n var computedStyle = isIE(10) && getComputedStyle(html);\n\n return {\n height: getSize('Height', body, html, computedStyle),\n width: getSize('Width', body, html, computedStyle)\n };\n}\n\nvar classCallCheck = function (instance, Constructor) {\n if (!(instance instanceof Constructor)) {\n throw new TypeError(\"Cannot call a class as a function\");\n }\n};\n\nvar createClass = function () {\n function defineProperties(target, props) {\n for (var i = 0; i < props.length; i++) {\n var descriptor = props[i];\n descriptor.enumerable = descriptor.enumerable || false;\n descriptor.configurable = true;\n if (\"value\" in descriptor) descriptor.writable = true;\n Object.defineProperty(target, descriptor.key, descriptor);\n }\n }\n\n return function (Constructor, protoProps, staticProps) {\n if (protoProps) defineProperties(Constructor.prototype, protoProps);\n if (staticProps) defineProperties(Constructor, staticProps);\n return Constructor;\n };\n}();\n\n\n\n\n\nvar defineProperty = function (obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n};\n\nvar _extends = Object.assign || function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n};\n\n/**\n * Given element offsets, generate an output similar to getBoundingClientRect\n * @method\n * @memberof Popper.Utils\n * @argument {Object} offsets\n * @returns {Object} ClientRect like output\n */\nfunction getClientRect(offsets) {\n return _extends({}, offsets, {\n right: offsets.left + offsets.width,\n bottom: offsets.top + offsets.height\n });\n}\n\n/**\n * Get bounding client rect of given element\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} element\n * @return {Object} client rect\n */\nfunction getBoundingClientRect(element) {\n var rect = {};\n\n // IE10 10 FIX: Please, don't ask, the element isn't\n // considered in DOM in some circumstances...\n // This isn't reproducible in IE10 compatibility mode of IE11\n try {\n if (isIE(10)) {\n rect = element.getBoundingClientRect();\n var scrollTop = getScroll(element, 'top');\n var scrollLeft = getScroll(element, 'left');\n rect.top += scrollTop;\n rect.left += scrollLeft;\n rect.bottom += scrollTop;\n rect.right += scrollLeft;\n } else {\n rect = element.getBoundingClientRect();\n }\n } catch (e) {}\n\n var result = {\n left: rect.left,\n top: rect.top,\n width: rect.right - rect.left,\n height: rect.bottom - rect.top\n };\n\n // subtract scrollbar size from sizes\n var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {};\n var width = sizes.width || element.clientWidth || result.right - result.left;\n var height = sizes.height || element.clientHeight || result.bottom - result.top;\n\n var horizScrollbar = element.offsetWidth - width;\n var vertScrollbar = element.offsetHeight - height;\n\n // if an hypothetical scrollbar is detected, we must be sure it's not a `border`\n // we make this check conditional for performance reasons\n if (horizScrollbar || vertScrollbar) {\n var styles = getStyleComputedProperty(element);\n horizScrollbar -= getBordersSize(styles, 'x');\n vertScrollbar -= getBordersSize(styles, 'y');\n\n result.width -= horizScrollbar;\n result.height -= vertScrollbar;\n }\n\n return getClientRect(result);\n}\n\nfunction getOffsetRectRelativeToArbitraryNode(children, parent) {\n var fixedPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n var isIE10 = isIE(10);\n var isHTML = parent.nodeName === 'HTML';\n var childrenRect = getBoundingClientRect(children);\n var parentRect = getBoundingClientRect(parent);\n var scrollParent = getScrollParent(children);\n\n var styles = getStyleComputedProperty(parent);\n var borderTopWidth = parseFloat(styles.borderTopWidth, 10);\n var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);\n\n // In cases where the parent is fixed, we must ignore negative scroll in offset calc\n if (fixedPosition && parent.nodeName === 'HTML') {\n parentRect.top = Math.max(parentRect.top, 0);\n parentRect.left = Math.max(parentRect.left, 0);\n }\n var offsets = getClientRect({\n top: childrenRect.top - parentRect.top - borderTopWidth,\n left: childrenRect.left - parentRect.left - borderLeftWidth,\n width: childrenRect.width,\n height: childrenRect.height\n });\n offsets.marginTop = 0;\n offsets.marginLeft = 0;\n\n // Subtract margins of documentElement in case it's being used as parent\n // we do this only on HTML because it's the only element that behaves\n // differently when margins are applied to it. The margins are included in\n // the box of the documentElement, in the other cases not.\n if (!isIE10 && isHTML) {\n var marginTop = parseFloat(styles.marginTop, 10);\n var marginLeft = parseFloat(styles.marginLeft, 10);\n\n offsets.top -= borderTopWidth - marginTop;\n offsets.bottom -= borderTopWidth - marginTop;\n offsets.left -= borderLeftWidth - marginLeft;\n offsets.right -= borderLeftWidth - marginLeft;\n\n // Attach marginTop and marginLeft because in some circumstances we may need them\n offsets.marginTop = marginTop;\n offsets.marginLeft = marginLeft;\n }\n\n if (isIE10 && !fixedPosition ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {\n offsets = includeScroll(offsets, parent);\n }\n\n return offsets;\n}\n\nfunction getViewportOffsetRectRelativeToArtbitraryNode(element) {\n var excludeScroll = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n var html = element.ownerDocument.documentElement;\n var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);\n var width = Math.max(html.clientWidth, window.innerWidth || 0);\n var height = Math.max(html.clientHeight, window.innerHeight || 0);\n\n var scrollTop = !excludeScroll ? getScroll(html) : 0;\n var scrollLeft = !excludeScroll ? getScroll(html, 'left') : 0;\n\n var offset = {\n top: scrollTop - relativeOffset.top + relativeOffset.marginTop,\n left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,\n width: width,\n height: height\n };\n\n return getClientRect(offset);\n}\n\n/**\n * Check if the given element is fixed or is inside a fixed parent\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @argument {Element} customContainer\n * @returns {Boolean} answer to \"isFixed?\"\n */\nfunction isFixed(element) {\n var nodeName = element.nodeName;\n if (nodeName === 'BODY' || nodeName === 'HTML') {\n return false;\n }\n if (getStyleComputedProperty(element, 'position') === 'fixed') {\n return true;\n }\n return isFixed(getParentNode(element));\n}\n\n/**\n * Finds the first parent of an element that has a transformed property defined\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Element} first transformed parent or documentElement\n */\n\nfunction getFixedPositionOffsetParent(element) {\n // This check is needed to avoid errors in case one of the elements isn't defined for any reason\n if (!element || !element.parentElement || isIE()) {\n return document.documentElement;\n }\n var el = element.parentElement;\n while (el && getStyleComputedProperty(el, 'transform') === 'none') {\n el = el.parentElement;\n }\n return el || document.documentElement;\n}\n\n/**\n * Computed the boundaries limits and return them\n * @method\n * @memberof Popper.Utils\n * @param {HTMLElement} popper\n * @param {HTMLElement} reference\n * @param {number} padding\n * @param {HTMLElement} boundariesElement - Element used to define the boundaries\n * @param {Boolean} fixedPosition - Is in fixed position mode\n * @returns {Object} Coordinates of the boundaries\n */\nfunction getBoundaries(popper, reference, padding, boundariesElement) {\n var fixedPosition = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;\n\n // NOTE: 1 DOM access here\n\n var boundaries = { top: 0, left: 0 };\n var offsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);\n\n // Handle viewport case\n if (boundariesElement === 'viewport') {\n boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent, fixedPosition);\n } else {\n // Handle other cases based on DOM element used as boundaries\n var boundariesNode = void 0;\n if (boundariesElement === 'scrollParent') {\n boundariesNode = getScrollParent(getParentNode(reference));\n if (boundariesNode.nodeName === 'BODY') {\n boundariesNode = popper.ownerDocument.documentElement;\n }\n } else if (boundariesElement === 'window') {\n boundariesNode = popper.ownerDocument.documentElement;\n } else {\n boundariesNode = boundariesElement;\n }\n\n var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent, fixedPosition);\n\n // In case of HTML, we need a different computation\n if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {\n var _getWindowSizes = getWindowSizes(),\n height = _getWindowSizes.height,\n width = _getWindowSizes.width;\n\n boundaries.top += offsets.top - offsets.marginTop;\n boundaries.bottom = height + offsets.top;\n boundaries.left += offsets.left - offsets.marginLeft;\n boundaries.right = width + offsets.left;\n } else {\n // for all the other DOM elements, this one is good\n boundaries = offsets;\n }\n }\n\n // Add paddings\n boundaries.left += padding;\n boundaries.top += padding;\n boundaries.right -= padding;\n boundaries.bottom -= padding;\n\n return boundaries;\n}\n\nfunction getArea(_ref) {\n var width = _ref.width,\n height = _ref.height;\n\n return width * height;\n}\n\n/**\n * Utility used to transform the `auto` placement to the placement with more\n * available space.\n * @method\n * @memberof Popper.Utils\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {\n var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;\n\n if (placement.indexOf('auto') === -1) {\n return placement;\n }\n\n var boundaries = getBoundaries(popper, reference, padding, boundariesElement);\n\n var rects = {\n top: {\n width: boundaries.width,\n height: refRect.top - boundaries.top\n },\n right: {\n width: boundaries.right - refRect.right,\n height: boundaries.height\n },\n bottom: {\n width: boundaries.width,\n height: boundaries.bottom - refRect.bottom\n },\n left: {\n width: refRect.left - boundaries.left,\n height: boundaries.height\n }\n };\n\n var sortedAreas = Object.keys(rects).map(function (key) {\n return _extends({\n key: key\n }, rects[key], {\n area: getArea(rects[key])\n });\n }).sort(function (a, b) {\n return b.area - a.area;\n });\n\n var filteredAreas = sortedAreas.filter(function (_ref2) {\n var width = _ref2.width,\n height = _ref2.height;\n return width >= popper.clientWidth && height >= popper.clientHeight;\n });\n\n var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;\n\n var variation = placement.split('-')[1];\n\n return computedPlacement + (variation ? '-' + variation : '');\n}\n\n/**\n * Get offsets to the reference element\n * @method\n * @memberof Popper.Utils\n * @param {Object} state\n * @param {Element} popper - the popper element\n * @param {Element} reference - the reference element (the popper will be relative to this)\n * @param {Element} fixedPosition - is in fixed position mode\n * @returns {Object} An object containing the offsets which will be applied to the popper\n */\nfunction getReferenceOffsets(state, popper, reference) {\n var fixedPosition = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;\n\n var commonOffsetParent = fixedPosition ? getFixedPositionOffsetParent(popper) : findCommonOffsetParent(popper, reference);\n return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent, fixedPosition);\n}\n\n/**\n * Get the outer sizes of the given element (offset size + margins)\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element\n * @returns {Object} object containing width and height properties\n */\nfunction getOuterSizes(element) {\n var styles = getComputedStyle(element);\n var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);\n var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);\n var result = {\n width: element.offsetWidth + y,\n height: element.offsetHeight + x\n };\n return result;\n}\n\n/**\n * Get the opposite placement of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement\n * @returns {String} flipped placement\n */\nfunction getOppositePlacement(placement) {\n var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };\n return placement.replace(/left|right|bottom|top/g, function (matched) {\n return hash[matched];\n });\n}\n\n/**\n * Get offsets to the popper\n * @method\n * @memberof Popper.Utils\n * @param {Object} position - CSS position the Popper will get applied\n * @param {HTMLElement} popper - the popper element\n * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)\n * @param {String} placement - one of the valid placement options\n * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper\n */\nfunction getPopperOffsets(popper, referenceOffsets, placement) {\n placement = placement.split('-')[0];\n\n // Get popper node sizes\n var popperRect = getOuterSizes(popper);\n\n // Add position, width and height to our offsets object\n var popperOffsets = {\n width: popperRect.width,\n height: popperRect.height\n };\n\n // depending by the popper placement we have to compute its offsets slightly differently\n var isHoriz = ['right', 'left'].indexOf(placement) !== -1;\n var mainSide = isHoriz ? 'top' : 'left';\n var secondarySide = isHoriz ? 'left' : 'top';\n var measurement = isHoriz ? 'height' : 'width';\n var secondaryMeasurement = !isHoriz ? 'height' : 'width';\n\n popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;\n if (placement === secondarySide) {\n popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];\n } else {\n popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];\n }\n\n return popperOffsets;\n}\n\n/**\n * Mimics the `find` method of Array\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction find(arr, check) {\n // use native find if supported\n if (Array.prototype.find) {\n return arr.find(check);\n }\n\n // use `filter` to obtain the same behavior of `find`\n return arr.filter(check)[0];\n}\n\n/**\n * Return the index of the matching object\n * @method\n * @memberof Popper.Utils\n * @argument {Array} arr\n * @argument prop\n * @argument value\n * @returns index or -1\n */\nfunction findIndex(arr, prop, value) {\n // use native findIndex if supported\n if (Array.prototype.findIndex) {\n return arr.findIndex(function (cur) {\n return cur[prop] === value;\n });\n }\n\n // use `find` + `indexOf` if `findIndex` isn't supported\n var match = find(arr, function (obj) {\n return obj[prop] === value;\n });\n return arr.indexOf(match);\n}\n\n/**\n * Loop trough the list of modifiers and run them in order,\n * each of them will then edit the data object.\n * @method\n * @memberof Popper.Utils\n * @param {dataObject} data\n * @param {Array} modifiers\n * @param {String} ends - Optional modifier name used as stopper\n * @returns {dataObject}\n */\nfunction runModifiers(modifiers, data, ends) {\n var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));\n\n modifiersToRun.forEach(function (modifier) {\n if (modifier['function']) {\n // eslint-disable-line dot-notation\n console.warn('`modifier.function` is deprecated, use `modifier.fn`!');\n }\n var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation\n if (modifier.enabled && isFunction(fn)) {\n // Add properties to offsets to make them a complete clientRect object\n // we do this before each modifier to make sure the previous one doesn't\n // mess with these values\n data.offsets.popper = getClientRect(data.offsets.popper);\n data.offsets.reference = getClientRect(data.offsets.reference);\n\n data = fn(data, modifier);\n }\n });\n\n return data;\n}\n\n/**\n * Updates the position of the popper, computing the new offsets and applying\n * the new style.
\n * Prefer `scheduleUpdate` over `update` because of performance reasons.\n * @method\n * @memberof Popper\n */\nfunction update() {\n // if popper is destroyed, don't perform any further update\n if (this.state.isDestroyed) {\n return;\n }\n\n var data = {\n instance: this,\n styles: {},\n arrowStyles: {},\n attributes: {},\n flipped: false,\n offsets: {}\n };\n\n // compute reference element offsets\n data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference, this.options.positionFixed);\n\n // compute auto placement, store placement inside the data object,\n // modifiers will be able to edit `placement` if needed\n // and refer to originalPlacement to know the original value\n data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);\n\n // store the computed placement inside `originalPlacement`\n data.originalPlacement = data.placement;\n\n data.positionFixed = this.options.positionFixed;\n\n // compute the popper offsets\n data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);\n\n data.offsets.popper.position = this.options.positionFixed ? 'fixed' : 'absolute';\n\n // run the modifiers\n data = runModifiers(this.modifiers, data);\n\n // the first `update` will call `onCreate` callback\n // the other ones will call `onUpdate` callback\n if (!this.state.isCreated) {\n this.state.isCreated = true;\n this.options.onCreate(data);\n } else {\n this.options.onUpdate(data);\n }\n}\n\n/**\n * Helper used to know if the given modifier is enabled.\n * @method\n * @memberof Popper.Utils\n * @returns {Boolean}\n */\nfunction isModifierEnabled(modifiers, modifierName) {\n return modifiers.some(function (_ref) {\n var name = _ref.name,\n enabled = _ref.enabled;\n return enabled && name === modifierName;\n });\n}\n\n/**\n * Get the prefixed supported property name\n * @method\n * @memberof Popper.Utils\n * @argument {String} property (camelCase)\n * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)\n */\nfunction getSupportedPropertyName(property) {\n var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];\n var upperProp = property.charAt(0).toUpperCase() + property.slice(1);\n\n for (var i = 0; i < prefixes.length; i++) {\n var prefix = prefixes[i];\n var toCheck = prefix ? '' + prefix + upperProp : property;\n if (typeof document.body.style[toCheck] !== 'undefined') {\n return toCheck;\n }\n }\n return null;\n}\n\n/**\n * Destroy the popper\n * @method\n * @memberof Popper\n */\nfunction destroy() {\n this.state.isDestroyed = true;\n\n // touch DOM only if `applyStyle` modifier is enabled\n if (isModifierEnabled(this.modifiers, 'applyStyle')) {\n this.popper.removeAttribute('x-placement');\n this.popper.style.position = '';\n this.popper.style.top = '';\n this.popper.style.left = '';\n this.popper.style.right = '';\n this.popper.style.bottom = '';\n this.popper.style.willChange = '';\n this.popper.style[getSupportedPropertyName('transform')] = '';\n }\n\n this.disableEventListeners();\n\n // remove the popper if user explicity asked for the deletion on destroy\n // do not use `remove` because IE11 doesn't support it\n if (this.options.removeOnDestroy) {\n this.popper.parentNode.removeChild(this.popper);\n }\n return this;\n}\n\n/**\n * Get the window associated with the element\n * @argument {Element} element\n * @returns {Window}\n */\nfunction getWindow(element) {\n var ownerDocument = element.ownerDocument;\n return ownerDocument ? ownerDocument.defaultView : window;\n}\n\nfunction attachToScrollParents(scrollParent, event, callback, scrollParents) {\n var isBody = scrollParent.nodeName === 'BODY';\n var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;\n target.addEventListener(event, callback, { passive: true });\n\n if (!isBody) {\n attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);\n }\n scrollParents.push(target);\n}\n\n/**\n * Setup needed event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction setupEventListeners(reference, options, state, updateBound) {\n // Resize event listener on window\n state.updateBound = updateBound;\n getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });\n\n // Scroll event listener on scroll parents\n var scrollElement = getScrollParent(reference);\n attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);\n state.scrollElement = scrollElement;\n state.eventsEnabled = true;\n\n return state;\n}\n\n/**\n * It will add resize/scroll events and start recalculating\n * position of the popper element when they are triggered.\n * @method\n * @memberof Popper\n */\nfunction enableEventListeners() {\n if (!this.state.eventsEnabled) {\n this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);\n }\n}\n\n/**\n * Remove event listeners used to update the popper position\n * @method\n * @memberof Popper.Utils\n * @private\n */\nfunction removeEventListeners(reference, state) {\n // Remove resize event listener on window\n getWindow(reference).removeEventListener('resize', state.updateBound);\n\n // Remove scroll event listener on scroll parents\n state.scrollParents.forEach(function (target) {\n target.removeEventListener('scroll', state.updateBound);\n });\n\n // Reset state\n state.updateBound = null;\n state.scrollParents = [];\n state.scrollElement = null;\n state.eventsEnabled = false;\n return state;\n}\n\n/**\n * It will remove resize/scroll events and won't recalculate popper position\n * when they are triggered. It also won't trigger onUpdate callback anymore,\n * unless you call `update` method manually.\n * @method\n * @memberof Popper\n */\nfunction disableEventListeners() {\n if (this.state.eventsEnabled) {\n cancelAnimationFrame(this.scheduleUpdate);\n this.state = removeEventListeners(this.reference, this.state);\n }\n}\n\n/**\n * Tells if a given input is a number\n * @method\n * @memberof Popper.Utils\n * @param {*} input to check\n * @return {Boolean}\n */\nfunction isNumeric(n) {\n return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);\n}\n\n/**\n * Set the style to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the style to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setStyles(element, styles) {\n Object.keys(styles).forEach(function (prop) {\n var unit = '';\n // add unit if the value is numeric and is one of the following\n if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {\n unit = 'px';\n }\n element.style[prop] = styles[prop] + unit;\n });\n}\n\n/**\n * Set the attributes to the given popper\n * @method\n * @memberof Popper.Utils\n * @argument {Element} element - Element to apply the attributes to\n * @argument {Object} styles\n * Object with a list of properties and values which will be applied to the element\n */\nfunction setAttributes(element, attributes) {\n Object.keys(attributes).forEach(function (prop) {\n var value = attributes[prop];\n if (value !== false) {\n element.setAttribute(prop, attributes[prop]);\n } else {\n element.removeAttribute(prop);\n }\n });\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} data.styles - List of style properties - values to apply to popper element\n * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The same data object\n */\nfunction applyStyle(data) {\n // any property present in `data.styles` will be applied to the popper,\n // in this way we can make the 3rd party modifiers add custom styles to it\n // Be aware, modifiers could override the properties defined in the previous\n // lines of this modifier!\n setStyles(data.instance.popper, data.styles);\n\n // any property present in `data.attributes` will be applied to the popper,\n // they will be set as HTML attributes of the element\n setAttributes(data.instance.popper, data.attributes);\n\n // if arrowElement is defined and arrowStyles has some properties\n if (data.arrowElement && Object.keys(data.arrowStyles).length) {\n setStyles(data.arrowElement, data.arrowStyles);\n }\n\n return data;\n}\n\n/**\n * Set the x-placement attribute before everything else because it could be used\n * to add margins to the popper margins needs to be calculated to get the\n * correct popper offsets.\n * @method\n * @memberof Popper.modifiers\n * @param {HTMLElement} reference - The reference element used to position the popper\n * @param {HTMLElement} popper - The HTML element used as popper\n * @param {Object} options - Popper.js options\n */\nfunction applyStyleOnLoad(reference, popper, options, modifierOptions, state) {\n // compute reference element offsets\n var referenceOffsets = getReferenceOffsets(state, popper, reference, options.positionFixed);\n\n // compute auto placement, store placement inside the data object,\n // modifiers will be able to edit `placement` if needed\n // and refer to originalPlacement to know the original value\n var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);\n\n popper.setAttribute('x-placement', placement);\n\n // Apply `position` to popper before anything else because\n // without the position applied we can't guarantee correct computations\n setStyles(popper, { position: options.positionFixed ? 'fixed' : 'absolute' });\n\n return options;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction computeStyle(data, options) {\n var x = options.x,\n y = options.y;\n var popper = data.offsets.popper;\n\n // Remove this legacy support in Popper.js v2\n\n var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {\n return modifier.name === 'applyStyle';\n }).gpuAcceleration;\n if (legacyGpuAccelerationOption !== undefined) {\n console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');\n }\n var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;\n\n var offsetParent = getOffsetParent(data.instance.popper);\n var offsetParentRect = getBoundingClientRect(offsetParent);\n\n // Styles\n var styles = {\n position: popper.position\n };\n\n // Avoid blurry text by using full pixel integers.\n // For pixel-perfect positioning, top/bottom prefers rounded\n // values, while left/right prefers floored values.\n var offsets = {\n left: Math.floor(popper.left),\n top: Math.round(popper.top),\n bottom: Math.round(popper.bottom),\n right: Math.floor(popper.right)\n };\n\n var sideA = x === 'bottom' ? 'top' : 'bottom';\n var sideB = y === 'right' ? 'left' : 'right';\n\n // if gpuAcceleration is set to `true` and transform is supported,\n // we use `translate3d` to apply the position to the popper we\n // automatically use the supported prefixed version if needed\n var prefixedProperty = getSupportedPropertyName('transform');\n\n // now, let's make a step back and look at this code closely (wtf?)\n // If the content of the popper grows once it's been positioned, it\n // may happen that the popper gets misplaced because of the new content\n // overflowing its reference element\n // To avoid this problem, we provide two options (x and y), which allow\n // the consumer to define the offset origin.\n // If we position a popper on top of a reference element, we can set\n // `x` to `top` to make the popper grow towards its top instead of\n // its bottom.\n var left = void 0,\n top = void 0;\n if (sideA === 'bottom') {\n top = -offsetParentRect.height + offsets.bottom;\n } else {\n top = offsets.top;\n }\n if (sideB === 'right') {\n left = -offsetParentRect.width + offsets.right;\n } else {\n left = offsets.left;\n }\n if (gpuAcceleration && prefixedProperty) {\n styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';\n styles[sideA] = 0;\n styles[sideB] = 0;\n styles.willChange = 'transform';\n } else {\n // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties\n var invertTop = sideA === 'bottom' ? -1 : 1;\n var invertLeft = sideB === 'right' ? -1 : 1;\n styles[sideA] = top * invertTop;\n styles[sideB] = left * invertLeft;\n styles.willChange = sideA + ', ' + sideB;\n }\n\n // Attributes\n var attributes = {\n 'x-placement': data.placement\n };\n\n // Update `data` attributes, styles and arrowStyles\n data.attributes = _extends({}, attributes, data.attributes);\n data.styles = _extends({}, styles, data.styles);\n data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);\n\n return data;\n}\n\n/**\n * Helper used to know if the given modifier depends from another one.
\n * It checks if the needed modifier is listed and enabled.\n * @method\n * @memberof Popper.Utils\n * @param {Array} modifiers - list of modifiers\n * @param {String} requestingName - name of requesting modifier\n * @param {String} requestedName - name of requested modifier\n * @returns {Boolean}\n */\nfunction isModifierRequired(modifiers, requestingName, requestedName) {\n var requesting = find(modifiers, function (_ref) {\n var name = _ref.name;\n return name === requestingName;\n });\n\n var isRequired = !!requesting && modifiers.some(function (modifier) {\n return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;\n });\n\n if (!isRequired) {\n var _requesting = '`' + requestingName + '`';\n var requested = '`' + requestedName + '`';\n console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');\n }\n return isRequired;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction arrow(data, options) {\n var _data$offsets$arrow;\n\n // arrow depends on keepTogether in order to work\n if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {\n return data;\n }\n\n var arrowElement = options.element;\n\n // if arrowElement is a string, suppose it's a CSS selector\n if (typeof arrowElement === 'string') {\n arrowElement = data.instance.popper.querySelector(arrowElement);\n\n // if arrowElement is not found, don't run the modifier\n if (!arrowElement) {\n return data;\n }\n } else {\n // if the arrowElement isn't a query selector we must check that the\n // provided DOM node is child of its popper node\n if (!data.instance.popper.contains(arrowElement)) {\n console.warn('WARNING: `arrow.element` must be child of its popper element!');\n return data;\n }\n }\n\n var placement = data.placement.split('-')[0];\n var _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var isVertical = ['left', 'right'].indexOf(placement) !== -1;\n\n var len = isVertical ? 'height' : 'width';\n var sideCapitalized = isVertical ? 'Top' : 'Left';\n var side = sideCapitalized.toLowerCase();\n var altSide = isVertical ? 'left' : 'top';\n var opSide = isVertical ? 'bottom' : 'right';\n var arrowElementSize = getOuterSizes(arrowElement)[len];\n\n //\n // extends keepTogether behavior making sure the popper and its\n // reference have enough pixels in conjuction\n //\n\n // top/left side\n if (reference[opSide] - arrowElementSize < popper[side]) {\n data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);\n }\n // bottom/right side\n if (reference[side] + arrowElementSize > popper[opSide]) {\n data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];\n }\n data.offsets.popper = getClientRect(data.offsets.popper);\n\n // compute center of the popper\n var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;\n\n // Compute the sideValue using the updated popper offsets\n // take popper margin in account because we don't have this info available\n var css = getStyleComputedProperty(data.instance.popper);\n var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);\n var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);\n var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;\n\n // prevent arrowElement from being placed not contiguously to its popper\n sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);\n\n data.arrowElement = arrowElement;\n data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);\n\n return data;\n}\n\n/**\n * Get the opposite placement variation of the given one\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement variation\n * @returns {String} flipped placement variation\n */\nfunction getOppositeVariation(variation) {\n if (variation === 'end') {\n return 'start';\n } else if (variation === 'start') {\n return 'end';\n }\n return variation;\n}\n\n/**\n * List of accepted placements to use as values of the `placement` option.
\n * Valid placements are:\n * - `auto`\n * - `top`\n * - `right`\n * - `bottom`\n * - `left`\n *\n * Each placement can have a variation from this list:\n * - `-start`\n * - `-end`\n *\n * Variations are interpreted easily if you think of them as the left to right\n * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`\n * is right.
\n * Vertically (`left` and `right`), `start` is top and `end` is bottom.\n *\n * Some valid examples are:\n * - `top-end` (on top of reference, right aligned)\n * - `right-start` (on right of reference, top aligned)\n * - `bottom` (on bottom, centered)\n * - `auto-right` (on the side with more space available, alignment depends by placement)\n *\n * @static\n * @type {Array}\n * @enum {String}\n * @readonly\n * @method placements\n * @memberof Popper\n */\nvar placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];\n\n// Get rid of `auto` `auto-start` and `auto-end`\nvar validPlacements = placements.slice(3);\n\n/**\n * Given an initial placement, returns all the subsequent placements\n * clockwise (or counter-clockwise).\n *\n * @method\n * @memberof Popper.Utils\n * @argument {String} placement - A valid placement (it accepts variations)\n * @argument {Boolean} counter - Set to true to walk the placements counterclockwise\n * @returns {Array} placements including their variations\n */\nfunction clockwise(placement) {\n var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n var index = validPlacements.indexOf(placement);\n var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));\n return counter ? arr.reverse() : arr;\n}\n\nvar BEHAVIORS = {\n FLIP: 'flip',\n CLOCKWISE: 'clockwise',\n COUNTERCLOCKWISE: 'counterclockwise'\n};\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction flip(data, options) {\n // if `inner` modifier is enabled, we can't use the `flip` modifier\n if (isModifierEnabled(data.instance.modifiers, 'inner')) {\n return data;\n }\n\n if (data.flipped && data.placement === data.originalPlacement) {\n // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides\n return data;\n }\n\n var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement, data.positionFixed);\n\n var placement = data.placement.split('-')[0];\n var placementOpposite = getOppositePlacement(placement);\n var variation = data.placement.split('-')[1] || '';\n\n var flipOrder = [];\n\n switch (options.behavior) {\n case BEHAVIORS.FLIP:\n flipOrder = [placement, placementOpposite];\n break;\n case BEHAVIORS.CLOCKWISE:\n flipOrder = clockwise(placement);\n break;\n case BEHAVIORS.COUNTERCLOCKWISE:\n flipOrder = clockwise(placement, true);\n break;\n default:\n flipOrder = options.behavior;\n }\n\n flipOrder.forEach(function (step, index) {\n if (placement !== step || flipOrder.length === index + 1) {\n return data;\n }\n\n placement = data.placement.split('-')[0];\n placementOpposite = getOppositePlacement(placement);\n\n var popperOffsets = data.offsets.popper;\n var refOffsets = data.offsets.reference;\n\n // using floor because the reference offsets may contain decimals we are not going to consider here\n var floor = Math.floor;\n var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);\n\n var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);\n var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);\n var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);\n var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);\n\n var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;\n\n // flip the variation if required\n var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);\n\n if (overlapsRef || overflowsBoundaries || flippedVariation) {\n // this boolean to detect any flip loop\n data.flipped = true;\n\n if (overlapsRef || overflowsBoundaries) {\n placement = flipOrder[index + 1];\n }\n\n if (flippedVariation) {\n variation = getOppositeVariation(variation);\n }\n\n data.placement = placement + (variation ? '-' + variation : '');\n\n // this object contains `position`, we want to preserve it along with\n // any additional property we may add in the future\n data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));\n\n data = runModifiers(data.instance.modifiers, data, 'flip');\n }\n });\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction keepTogether(data) {\n var _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var placement = data.placement.split('-')[0];\n var floor = Math.floor;\n var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;\n var side = isVertical ? 'right' : 'bottom';\n var opSide = isVertical ? 'left' : 'top';\n var measurement = isVertical ? 'width' : 'height';\n\n if (popper[side] < floor(reference[opSide])) {\n data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];\n }\n if (popper[opSide] > floor(reference[side])) {\n data.offsets.popper[opSide] = floor(reference[side]);\n }\n\n return data;\n}\n\n/**\n * Converts a string containing value + unit into a px value number\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} str - Value + unit string\n * @argument {String} measurement - `height` or `width`\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @returns {Number|String}\n * Value in pixels, or original string if no values were extracted\n */\nfunction toValue(str, measurement, popperOffsets, referenceOffsets) {\n // separate value from unit\n var split = str.match(/((?:\\-|\\+)?\\d*\\.?\\d*)(.*)/);\n var value = +split[1];\n var unit = split[2];\n\n // If it's not a number it's an operator, I guess\n if (!value) {\n return str;\n }\n\n if (unit.indexOf('%') === 0) {\n var element = void 0;\n switch (unit) {\n case '%p':\n element = popperOffsets;\n break;\n case '%':\n case '%r':\n default:\n element = referenceOffsets;\n }\n\n var rect = getClientRect(element);\n return rect[measurement] / 100 * value;\n } else if (unit === 'vh' || unit === 'vw') {\n // if is a vh or vw, we calculate the size based on the viewport\n var size = void 0;\n if (unit === 'vh') {\n size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);\n } else {\n size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);\n }\n return size / 100 * value;\n } else {\n // if is an explicit pixel unit, we get rid of the unit and keep the value\n // if is an implicit unit, it's px, and we return just the value\n return value;\n }\n}\n\n/**\n * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.\n * @function\n * @memberof {modifiers~offset}\n * @private\n * @argument {String} offset\n * @argument {Object} popperOffsets\n * @argument {Object} referenceOffsets\n * @argument {String} basePlacement\n * @returns {Array} a two cells array with x and y offsets in numbers\n */\nfunction parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {\n var offsets = [0, 0];\n\n // Use height if placement is left or right and index is 0 otherwise use width\n // in this way the first offset will use an axis and the second one\n // will use the other one\n var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;\n\n // Split the offset string to obtain a list of values and operands\n // The regex addresses values with the plus or minus sign in front (+10, -20, etc)\n var fragments = offset.split(/(\\+|\\-)/).map(function (frag) {\n return frag.trim();\n });\n\n // Detect if the offset string contains a pair of values or a single one\n // they could be separated by comma or space\n var divider = fragments.indexOf(find(fragments, function (frag) {\n return frag.search(/,|\\s/) !== -1;\n }));\n\n if (fragments[divider] && fragments[divider].indexOf(',') === -1) {\n console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');\n }\n\n // If divider is found, we divide the list of values and operands to divide\n // them by ofset X and Y.\n var splitRegex = /\\s*,\\s*|\\s+/;\n var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];\n\n // Convert the values with units to absolute pixels to allow our computations\n ops = ops.map(function (op, index) {\n // Most of the units rely on the orientation of the popper\n var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';\n var mergeWithPrevious = false;\n return op\n // This aggregates any `+` or `-` sign that aren't considered operators\n // e.g.: 10 + +5 => [10, +, +5]\n .reduce(function (a, b) {\n if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {\n a[a.length - 1] = b;\n mergeWithPrevious = true;\n return a;\n } else if (mergeWithPrevious) {\n a[a.length - 1] += b;\n mergeWithPrevious = false;\n return a;\n } else {\n return a.concat(b);\n }\n }, [])\n // Here we convert the string values into number values (in px)\n .map(function (str) {\n return toValue(str, measurement, popperOffsets, referenceOffsets);\n });\n });\n\n // Loop trough the offsets arrays and execute the operations\n ops.forEach(function (op, index) {\n op.forEach(function (frag, index2) {\n if (isNumeric(frag)) {\n offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);\n }\n });\n });\n return offsets;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @argument {Number|String} options.offset=0\n * The offset value as described in the modifier description\n * @returns {Object} The data object, properly modified\n */\nfunction offset(data, _ref) {\n var offset = _ref.offset;\n var placement = data.placement,\n _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var basePlacement = placement.split('-')[0];\n\n var offsets = void 0;\n if (isNumeric(+offset)) {\n offsets = [+offset, 0];\n } else {\n offsets = parseOffset(offset, popper, reference, basePlacement);\n }\n\n if (basePlacement === 'left') {\n popper.top += offsets[0];\n popper.left -= offsets[1];\n } else if (basePlacement === 'right') {\n popper.top += offsets[0];\n popper.left += offsets[1];\n } else if (basePlacement === 'top') {\n popper.left += offsets[0];\n popper.top -= offsets[1];\n } else if (basePlacement === 'bottom') {\n popper.left += offsets[0];\n popper.top += offsets[1];\n }\n\n data.popper = popper;\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction preventOverflow(data, options) {\n var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);\n\n // If offsetParent is the reference element, we really want to\n // go one step up and use the next offsetParent as reference to\n // avoid to make this modifier completely useless and look like broken\n if (data.instance.reference === boundariesElement) {\n boundariesElement = getOffsetParent(boundariesElement);\n }\n\n // NOTE: DOM access here\n // resets the popper's position so that the document size can be calculated excluding\n // the size of the popper element itself\n var transformProp = getSupportedPropertyName('transform');\n var popperStyles = data.instance.popper.style; // assignment to help minification\n var top = popperStyles.top,\n left = popperStyles.left,\n transform = popperStyles[transformProp];\n\n popperStyles.top = '';\n popperStyles.left = '';\n popperStyles[transformProp] = '';\n\n var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement, data.positionFixed);\n\n // NOTE: DOM access here\n // restores the original style properties after the offsets have been computed\n popperStyles.top = top;\n popperStyles.left = left;\n popperStyles[transformProp] = transform;\n\n options.boundaries = boundaries;\n\n var order = options.priority;\n var popper = data.offsets.popper;\n\n var check = {\n primary: function primary(placement) {\n var value = popper[placement];\n if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {\n value = Math.max(popper[placement], boundaries[placement]);\n }\n return defineProperty({}, placement, value);\n },\n secondary: function secondary(placement) {\n var mainSide = placement === 'right' ? 'left' : 'top';\n var value = popper[mainSide];\n if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {\n value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));\n }\n return defineProperty({}, mainSide, value);\n }\n };\n\n order.forEach(function (placement) {\n var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';\n popper = _extends({}, popper, check[side](placement));\n });\n\n data.offsets.popper = popper;\n\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction shift(data) {\n var placement = data.placement;\n var basePlacement = placement.split('-')[0];\n var shiftvariation = placement.split('-')[1];\n\n // if shift shiftvariation is specified, run the modifier\n if (shiftvariation) {\n var _data$offsets = data.offsets,\n reference = _data$offsets.reference,\n popper = _data$offsets.popper;\n\n var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;\n var side = isVertical ? 'left' : 'top';\n var measurement = isVertical ? 'width' : 'height';\n\n var shiftOffsets = {\n start: defineProperty({}, side, reference[side]),\n end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])\n };\n\n data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);\n }\n\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by update method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction hide(data) {\n if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {\n return data;\n }\n\n var refRect = data.offsets.reference;\n var bound = find(data.instance.modifiers, function (modifier) {\n return modifier.name === 'preventOverflow';\n }).boundaries;\n\n if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {\n // Avoid unnecessary DOM access if visibility hasn't changed\n if (data.hide === true) {\n return data;\n }\n\n data.hide = true;\n data.attributes['x-out-of-boundaries'] = '';\n } else {\n // Avoid unnecessary DOM access if visibility hasn't changed\n if (data.hide === false) {\n return data;\n }\n\n data.hide = false;\n data.attributes['x-out-of-boundaries'] = false;\n }\n\n return data;\n}\n\n/**\n * @function\n * @memberof Modifiers\n * @argument {Object} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {Object} The data object, properly modified\n */\nfunction inner(data) {\n var placement = data.placement;\n var basePlacement = placement.split('-')[0];\n var _data$offsets = data.offsets,\n popper = _data$offsets.popper,\n reference = _data$offsets.reference;\n\n var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;\n\n var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;\n\n popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);\n\n data.placement = getOppositePlacement(placement);\n data.offsets.popper = getClientRect(popper);\n\n return data;\n}\n\n/**\n * Modifier function, each modifier can have a function of this type assigned\n * to its `fn` property.
\n * These functions will be called on each update, this means that you must\n * make sure they are performant enough to avoid performance bottlenecks.\n *\n * @function ModifierFn\n * @argument {dataObject} data - The data object generated by `update` method\n * @argument {Object} options - Modifiers configuration and options\n * @returns {dataObject} The data object, properly modified\n */\n\n/**\n * Modifiers are plugins used to alter the behavior of your poppers.
\n * Popper.js uses a set of 9 modifiers to provide all the basic functionalities\n * needed by the library.\n *\n * Usually you don't want to override the `order`, `fn` and `onLoad` props.\n * All the other properties are configurations that could be tweaked.\n * @namespace modifiers\n */\nvar modifiers = {\n /**\n * Modifier used to shift the popper on the start or end of its reference\n * element.
\n * It will read the variation of the `placement` property.
\n * It can be one either `-end` or `-start`.\n * @memberof modifiers\n * @inner\n */\n shift: {\n /** @prop {number} order=100 - Index used to define the order of execution */\n order: 100,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: shift\n },\n\n /**\n * The `offset` modifier can shift your popper on both its axis.\n *\n * It accepts the following units:\n * - `px` or unitless, interpreted as pixels\n * - `%` or `%r`, percentage relative to the length of the reference element\n * - `%p`, percentage relative to the length of the popper element\n * - `vw`, CSS viewport width unit\n * - `vh`, CSS viewport height unit\n *\n * For length is intended the main axis relative to the placement of the popper.
\n * This means that if the placement is `top` or `bottom`, the length will be the\n * `width`. In case of `left` or `right`, it will be the height.\n *\n * You can provide a single value (as `Number` or `String`), or a pair of values\n * as `String` divided by a comma or one (or more) white spaces.
\n * The latter is a deprecated method because it leads to confusion and will be\n * removed in v2.
\n * Additionally, it accepts additions and subtractions between different units.\n * Note that multiplications and divisions aren't supported.\n *\n * Valid examples are:\n * ```\n * 10\n * '10%'\n * '10, 10'\n * '10%, 10'\n * '10 + 10%'\n * '10 - 5vh + 3%'\n * '-10px + 5vh, 5px - 6%'\n * ```\n * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap\n * > with their reference element, unfortunately, you will have to disable the `flip` modifier.\n * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373)\n *\n * @memberof modifiers\n * @inner\n */\n offset: {\n /** @prop {number} order=200 - Index used to define the order of execution */\n order: 200,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: offset,\n /** @prop {Number|String} offset=0\n * The offset value as described in the modifier description\n */\n offset: 0\n },\n\n /**\n * Modifier used to prevent the popper from being positioned outside the boundary.\n *\n * An scenario exists where the reference itself is not within the boundaries.
\n * We can say it has \"escaped the boundaries\" — or just \"escaped\".
\n * In this case we need to decide whether the popper should either:\n *\n * - detach from the reference and remain \"trapped\" in the boundaries, or\n * - if it should ignore the boundary and \"escape with its reference\"\n *\n * When `escapeWithReference` is set to`true` and reference is completely\n * outside its boundaries, the popper will overflow (or completely leave)\n * the boundaries in order to remain attached to the edge of the reference.\n *\n * @memberof modifiers\n * @inner\n */\n preventOverflow: {\n /** @prop {number} order=300 - Index used to define the order of execution */\n order: 300,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: preventOverflow,\n /**\n * @prop {Array} [priority=['left','right','top','bottom']]\n * Popper will try to prevent overflow following these priorities by default,\n * then, it could overflow on the left and on top of the `boundariesElement`\n */\n priority: ['left', 'right', 'top', 'bottom'],\n /**\n * @prop {number} padding=5\n * Amount of pixel used to define a minimum distance between the boundaries\n * and the popper this makes sure the popper has always a little padding\n * between the edges of its container\n */\n padding: 5,\n /**\n * @prop {String|HTMLElement} boundariesElement='scrollParent'\n * Boundaries used by the modifier, can be `scrollParent`, `window`,\n * `viewport` or any DOM element.\n */\n boundariesElement: 'scrollParent'\n },\n\n /**\n * Modifier used to make sure the reference and its popper stay near eachothers\n * without leaving any gap between the two. Expecially useful when the arrow is\n * enabled and you want to assure it to point to its reference element.\n * It cares only about the first axis, you can still have poppers with margin\n * between the popper and its reference element.\n * @memberof modifiers\n * @inner\n */\n keepTogether: {\n /** @prop {number} order=400 - Index used to define the order of execution */\n order: 400,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: keepTogether\n },\n\n /**\n * This modifier is used to move the `arrowElement` of the popper to make\n * sure it is positioned between the reference element and its popper element.\n * It will read the outer size of the `arrowElement` node to detect how many\n * pixels of conjuction are needed.\n *\n * It has no effect if no `arrowElement` is provided.\n * @memberof modifiers\n * @inner\n */\n arrow: {\n /** @prop {number} order=500 - Index used to define the order of execution */\n order: 500,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: arrow,\n /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */\n element: '[x-arrow]'\n },\n\n /**\n * Modifier used to flip the popper's placement when it starts to overlap its\n * reference element.\n *\n * Requires the `preventOverflow` modifier before it in order to work.\n *\n * **NOTE:** this modifier will interrupt the current update cycle and will\n * restart it if it detects the need to flip the placement.\n * @memberof modifiers\n * @inner\n */\n flip: {\n /** @prop {number} order=600 - Index used to define the order of execution */\n order: 600,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: flip,\n /**\n * @prop {String|Array} behavior='flip'\n * The behavior used to change the popper's placement. It can be one of\n * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid\n * placements (with optional variations).\n */\n behavior: 'flip',\n /**\n * @prop {number} padding=5\n * The popper will flip if it hits the edges of the `boundariesElement`\n */\n padding: 5,\n /**\n * @prop {String|HTMLElement} boundariesElement='viewport'\n * The element which will define the boundaries of the popper position,\n * the popper will never be placed outside of the defined boundaries\n * (except if keepTogether is enabled)\n */\n boundariesElement: 'viewport'\n },\n\n /**\n * Modifier used to make the popper flow toward the inner of the reference element.\n * By default, when this modifier is disabled, the popper will be placed outside\n * the reference element.\n * @memberof modifiers\n * @inner\n */\n inner: {\n /** @prop {number} order=700 - Index used to define the order of execution */\n order: 700,\n /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */\n enabled: false,\n /** @prop {ModifierFn} */\n fn: inner\n },\n\n /**\n * Modifier used to hide the popper when its reference element is outside of the\n * popper boundaries. It will set a `x-out-of-boundaries` attribute which can\n * be used to hide with a CSS selector the popper when its reference is\n * out of boundaries.\n *\n * Requires the `preventOverflow` modifier before it in order to work.\n * @memberof modifiers\n * @inner\n */\n hide: {\n /** @prop {number} order=800 - Index used to define the order of execution */\n order: 800,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: hide\n },\n\n /**\n * Computes the style that will be applied to the popper element to gets\n * properly positioned.\n *\n * Note that this modifier will not touch the DOM, it just prepares the styles\n * so that `applyStyle` modifier can apply it. This separation is useful\n * in case you need to replace `applyStyle` with a custom implementation.\n *\n * This modifier has `850` as `order` value to maintain backward compatibility\n * with previous versions of Popper.js. Expect the modifiers ordering method\n * to change in future major versions of the library.\n *\n * @memberof modifiers\n * @inner\n */\n computeStyle: {\n /** @prop {number} order=850 - Index used to define the order of execution */\n order: 850,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: computeStyle,\n /**\n * @prop {Boolean} gpuAcceleration=true\n * If true, it uses the CSS 3d transformation to position the popper.\n * Otherwise, it will use the `top` and `left` properties.\n */\n gpuAcceleration: true,\n /**\n * @prop {string} [x='bottom']\n * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.\n * Change this if your popper should grow in a direction different from `bottom`\n */\n x: 'bottom',\n /**\n * @prop {string} [x='left']\n * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.\n * Change this if your popper should grow in a direction different from `right`\n */\n y: 'right'\n },\n\n /**\n * Applies the computed styles to the popper element.\n *\n * All the DOM manipulations are limited to this modifier. This is useful in case\n * you want to integrate Popper.js inside a framework or view library and you\n * want to delegate all the DOM manipulations to it.\n *\n * Note that if you disable this modifier, you must make sure the popper element\n * has its position set to `absolute` before Popper.js can do its work!\n *\n * Just disable this modifier and define you own to achieve the desired effect.\n *\n * @memberof modifiers\n * @inner\n */\n applyStyle: {\n /** @prop {number} order=900 - Index used to define the order of execution */\n order: 900,\n /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */\n enabled: true,\n /** @prop {ModifierFn} */\n fn: applyStyle,\n /** @prop {Function} */\n onLoad: applyStyleOnLoad,\n /**\n * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier\n * @prop {Boolean} gpuAcceleration=true\n * If true, it uses the CSS 3d transformation to position the popper.\n * Otherwise, it will use the `top` and `left` properties.\n */\n gpuAcceleration: undefined\n }\n};\n\n/**\n * The `dataObject` is an object containing all the informations used by Popper.js\n * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks.\n * @name dataObject\n * @property {Object} data.instance The Popper.js instance\n * @property {String} data.placement Placement applied to popper\n * @property {String} data.originalPlacement Placement originally defined on init\n * @property {Boolean} data.flipped True if popper has been flipped by flip modifier\n * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper.\n * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier\n * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`)\n * @property {Object} data.boundaries Offsets of the popper boundaries\n * @property {Object} data.offsets The measurements of popper, reference and arrow elements.\n * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values\n * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0\n */\n\n/**\n * Default options provided to Popper.js constructor.
\n * These can be overriden using the `options` argument of Popper.js.
\n * To override an option, simply pass as 3rd argument an object with the same\n * structure of this object, example:\n * ```\n * new Popper(ref, pop, {\n * modifiers: {\n * preventOverflow: { enabled: false }\n * }\n * })\n * ```\n * @type {Object}\n * @static\n * @memberof Popper\n */\nvar Defaults = {\n /**\n * Popper's placement\n * @prop {Popper.placements} placement='bottom'\n */\n placement: 'bottom',\n\n /**\n * Set this to true if you want popper to position it self in 'fixed' mode\n * @prop {Boolean} positionFixed=false\n */\n positionFixed: false,\n\n /**\n * Whether events (resize, scroll) are initially enabled\n * @prop {Boolean} eventsEnabled=true\n */\n eventsEnabled: true,\n\n /**\n * Set to true if you want to automatically remove the popper when\n * you call the `destroy` method.\n * @prop {Boolean} removeOnDestroy=false\n */\n removeOnDestroy: false,\n\n /**\n * Callback called when the popper is created.
\n * By default, is set to no-op.
\n * Access Popper.js instance with `data.instance`.\n * @prop {onCreate}\n */\n onCreate: function onCreate() {},\n\n /**\n * Callback called when the popper is updated, this callback is not called\n * on the initialization/creation of the popper, but only on subsequent\n * updates.
\n * By default, is set to no-op.
\n * Access Popper.js instance with `data.instance`.\n * @prop {onUpdate}\n */\n onUpdate: function onUpdate() {},\n\n /**\n * List of modifiers used to modify the offsets before they are applied to the popper.\n * They provide most of the functionalities of Popper.js\n * @prop {modifiers}\n */\n modifiers: modifiers\n};\n\n/**\n * @callback onCreate\n * @param {dataObject} data\n */\n\n/**\n * @callback onUpdate\n * @param {dataObject} data\n */\n\n// Utils\n// Methods\nvar Popper = function () {\n /**\n * Create a new Popper.js instance\n * @class Popper\n * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper\n * @param {HTMLElement} popper - The HTML element used as popper.\n * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)\n * @return {Object} instance - The generated Popper.js instance\n */\n function Popper(reference, popper) {\n var _this = this;\n\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};\n classCallCheck(this, Popper);\n\n this.scheduleUpdate = function () {\n return requestAnimationFrame(_this.update);\n };\n\n // make update() debounced, so that it only runs at most once-per-tick\n this.update = debounce(this.update.bind(this));\n\n // with {} we create a new object with the options inside it\n this.options = _extends({}, Popper.Defaults, options);\n\n // init state\n this.state = {\n isDestroyed: false,\n isCreated: false,\n scrollParents: []\n };\n\n // get reference and popper elements (allow jQuery wrappers)\n this.reference = reference && reference.jquery ? reference[0] : reference;\n this.popper = popper && popper.jquery ? popper[0] : popper;\n\n // Deep merge modifiers options\n this.options.modifiers = {};\n Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {\n _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});\n });\n\n // Refactoring modifiers' list (Object => Array)\n this.modifiers = Object.keys(this.options.modifiers).map(function (name) {\n return _extends({\n name: name\n }, _this.options.modifiers[name]);\n })\n // sort the modifiers by order\n .sort(function (a, b) {\n return a.order - b.order;\n });\n\n // modifiers have the ability to execute arbitrary code when Popper.js get inited\n // such code is executed in the same order of its modifier\n // they could add new properties to their options configuration\n // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!\n this.modifiers.forEach(function (modifierOptions) {\n if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {\n modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);\n }\n });\n\n // fire the first update to position the popper in the right place\n this.update();\n\n var eventsEnabled = this.options.eventsEnabled;\n if (eventsEnabled) {\n // setup event listeners, they will take care of update the position in specific situations\n this.enableEventListeners();\n }\n\n this.state.eventsEnabled = eventsEnabled;\n }\n\n // We can't use class properties because they don't get listed in the\n // class prototype and break stuff like Sinon stubs\n\n\n createClass(Popper, [{\n key: 'update',\n value: function update$$1() {\n return update.call(this);\n }\n }, {\n key: 'destroy',\n value: function destroy$$1() {\n return destroy.call(this);\n }\n }, {\n key: 'enableEventListeners',\n value: function enableEventListeners$$1() {\n return enableEventListeners.call(this);\n }\n }, {\n key: 'disableEventListeners',\n value: function disableEventListeners$$1() {\n return disableEventListeners.call(this);\n }\n\n /**\n * Schedule an update, it will run on the next UI update available\n * @method scheduleUpdate\n * @memberof Popper\n */\n\n\n /**\n * Collection of utilities useful when writing custom modifiers.\n * Starting from version 1.7, this method is available only if you\n * include `popper-utils.js` before `popper.js`.\n *\n * **DEPRECATION**: This way to access PopperUtils is deprecated\n * and will be removed in v2! Use the PopperUtils module directly instead.\n * Due to the high instability of the methods contained in Utils, we can't\n * guarantee them to follow semver. Use them at your own risk!\n * @static\n * @private\n * @type {Object}\n * @deprecated since version 1.8\n * @member Utils\n * @memberof Popper\n */\n\n }]);\n return Popper;\n}();\n\n/**\n * The `referenceObject` is an object that provides an interface compatible with Popper.js\n * and lets you use it as replacement of a real DOM node.
\n * You can use this method to position a popper relatively to a set of coordinates\n * in case you don't have a DOM node to use as reference.\n *\n * ```\n * new Popper(referenceObject, popperNode);\n * ```\n *\n * NB: This feature isn't supported in Internet Explorer 10\n * @name referenceObject\n * @property {Function} data.getBoundingClientRect\n * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.\n * @property {number} data.clientWidth\n * An ES6 getter that will return the width of the virtual reference element.\n * @property {number} data.clientHeight\n * An ES6 getter that will return the height of the virtual reference element.\n */\n\n\nPopper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;\nPopper.placements = placements;\nPopper.Defaults = Defaults;\n\nexport default Popper;\n//# sourceMappingURL=popper.js.map\n","import $ from 'jquery'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): util.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Util = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Private TransitionEnd Helpers\n * ------------------------------------------------------------------------\n */\n\n const TRANSITION_END = 'transitionend'\n const MAX_UID = 1000000\n const MILLISECONDS_MULTIPLIER = 1000\n\n // Shoutout AngusCroll (https://goo.gl/pxwQGp)\n function toType(obj) {\n return {}.toString.call(obj).match(/\\s([a-z]+)/i)[1].toLowerCase()\n }\n\n function getSpecialTransitionEndEvent() {\n return {\n bindType: TRANSITION_END,\n delegateType: TRANSITION_END,\n handle(event) {\n if ($(event.target).is(this)) {\n return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params\n }\n return undefined // eslint-disable-line no-undefined\n }\n }\n }\n\n function transitionEndEmulator(duration) {\n let called = false\n\n $(this).one(Util.TRANSITION_END, () => {\n called = true\n })\n\n setTimeout(() => {\n if (!called) {\n Util.triggerTransitionEnd(this)\n }\n }, duration)\n\n return this\n }\n\n function setTransitionEndSupport() {\n $.fn.emulateTransitionEnd = transitionEndEmulator\n $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()\n }\n\n /**\n * --------------------------------------------------------------------------\n * Public Util Api\n * --------------------------------------------------------------------------\n */\n\n const Util = {\n\n TRANSITION_END: 'bsTransitionEnd',\n\n getUID(prefix) {\n do {\n // eslint-disable-next-line no-bitwise\n prefix += ~~(Math.random() * MAX_UID) // \"~~\" acts like a faster Math.floor() here\n } while (document.getElementById(prefix))\n return prefix\n },\n\n getSelectorFromElement(element) {\n let selector = element.getAttribute('data-target')\n if (!selector || selector === '#') {\n selector = element.getAttribute('href') || ''\n }\n\n try {\n return document.querySelector(selector) ? selector : null\n } catch (err) {\n return null\n }\n },\n\n getTransitionDurationFromElement(element) {\n if (!element) {\n return 0\n }\n\n // Get transition-duration of the element\n let transitionDuration = $(element).css('transition-duration')\n const floatTransitionDuration = parseFloat(transitionDuration)\n\n // Return 0 if element or transition duration is not found\n if (!floatTransitionDuration) {\n return 0\n }\n\n // If multiple durations are defined, take the first\n transitionDuration = transitionDuration.split(',')[0]\n\n return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER\n },\n\n reflow(element) {\n return element.offsetHeight\n },\n\n triggerTransitionEnd(element) {\n $(element).trigger(TRANSITION_END)\n },\n\n // TODO: Remove in v5\n supportsTransitionEnd() {\n return Boolean(TRANSITION_END)\n },\n\n isElement(obj) {\n return (obj[0] || obj).nodeType\n },\n\n typeCheckConfig(componentName, config, configTypes) {\n for (const property in configTypes) {\n if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n const expectedTypes = configTypes[property]\n const value = config[property]\n const valueType = value && Util.isElement(value)\n ? 'element' : toType(value)\n\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new Error(\n `${componentName.toUpperCase()}: ` +\n `Option \"${property}\" provided type \"${valueType}\" ` +\n `but expected type \"${expectedTypes}\".`)\n }\n }\n }\n }\n }\n\n setTransitionEndSupport()\n\n return Util\n})($)\n\nexport default Util\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Alert = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'alert'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.alert'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Selector = {\n DISMISS : '[data-dismiss=\"alert\"]'\n }\n\n const Event = {\n CLOSE : `close${EVENT_KEY}`,\n CLOSED : `closed${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n ALERT : 'alert',\n FADE : 'fade',\n SHOW : 'show'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Alert {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n close(element) {\n let rootElement = this._element\n if (element) {\n rootElement = this._getRootElement(element)\n }\n\n const customEvent = this._triggerCloseEvent(rootElement)\n\n if (customEvent.isDefaultPrevented()) {\n return\n }\n\n this._removeElement(rootElement)\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Private\n\n _getRootElement(element) {\n const selector = Util.getSelectorFromElement(element)\n let parent = false\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n if (!parent) {\n parent = $(element).closest(`.${ClassName.ALERT}`)[0]\n }\n\n return parent\n }\n\n _triggerCloseEvent(element) {\n const closeEvent = $.Event(Event.CLOSE)\n\n $(element).trigger(closeEvent)\n return closeEvent\n }\n\n _removeElement(element) {\n $(element).removeClass(ClassName.SHOW)\n\n if (!$(element).hasClass(ClassName.FADE)) {\n this._destroyElement(element)\n return\n }\n\n const transitionDuration = Util.getTransitionDurationFromElement(element)\n\n $(element)\n .one(Util.TRANSITION_END, (event) => this._destroyElement(element, event))\n .emulateTransitionEnd(transitionDuration)\n }\n\n _destroyElement(element) {\n $(element)\n .detach()\n .trigger(Event.CLOSED)\n .remove()\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $element = $(this)\n let data = $element.data(DATA_KEY)\n\n if (!data) {\n data = new Alert(this)\n $element.data(DATA_KEY, data)\n }\n\n if (config === 'close') {\n data[config](this)\n }\n })\n }\n\n static _handleDismiss(alertInstance) {\n return function (event) {\n if (event) {\n event.preventDefault()\n }\n\n alertInstance.close(this)\n }\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(\n Event.CLICK_DATA_API,\n Selector.DISMISS,\n Alert._handleDismiss(new Alert())\n )\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Alert._jQueryInterface\n $.fn[NAME].Constructor = Alert\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Alert._jQueryInterface\n }\n\n return Alert\n})($)\n\nexport default Alert\n","import $ from 'jquery'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Button = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'button'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.button'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const ClassName = {\n ACTIVE : 'active',\n BUTTON : 'btn',\n FOCUS : 'focus'\n }\n\n const Selector = {\n DATA_TOGGLE_CARROT : '[data-toggle^=\"button\"]',\n DATA_TOGGLE : '[data-toggle=\"buttons\"]',\n INPUT : 'input',\n ACTIVE : '.active',\n BUTTON : '.btn'\n }\n\n const Event = {\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,\n FOCUS_BLUR_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY} ` +\n `blur${EVENT_KEY}${DATA_API_KEY}`\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Button {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n toggle() {\n let triggerChangeEvent = true\n let addAriaPressed = true\n const rootElement = $(this._element).closest(\n Selector.DATA_TOGGLE\n )[0]\n\n if (rootElement) {\n const input = this._element.querySelector(Selector.INPUT)\n\n if (input) {\n if (input.type === 'radio') {\n if (input.checked &&\n this._element.classList.contains(ClassName.ACTIVE)) {\n triggerChangeEvent = false\n } else {\n const activeElement = rootElement.querySelector(Selector.ACTIVE)\n\n if (activeElement) {\n $(activeElement).removeClass(ClassName.ACTIVE)\n }\n }\n }\n\n if (triggerChangeEvent) {\n if (input.hasAttribute('disabled') ||\n rootElement.hasAttribute('disabled') ||\n input.classList.contains('disabled') ||\n rootElement.classList.contains('disabled')) {\n return\n }\n input.checked = !this._element.classList.contains(ClassName.ACTIVE)\n $(input).trigger('change')\n }\n\n input.focus()\n addAriaPressed = false\n }\n }\n\n if (addAriaPressed) {\n this._element.setAttribute('aria-pressed',\n !this._element.classList.contains(ClassName.ACTIVE))\n }\n\n if (triggerChangeEvent) {\n $(this._element).toggleClass(ClassName.ACTIVE)\n }\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n\n if (!data) {\n data = new Button(this)\n $(this).data(DATA_KEY, data)\n }\n\n if (config === 'toggle') {\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {\n event.preventDefault()\n\n let button = event.target\n\n if (!$(button).hasClass(ClassName.BUTTON)) {\n button = $(button).closest(Selector.BUTTON)\n }\n\n Button._jQueryInterface.call($(button), 'toggle')\n })\n .on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {\n const button = $(event.target).closest(Selector.BUTTON)[0]\n $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type))\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Button._jQueryInterface\n $.fn[NAME].Constructor = Button\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Button._jQueryInterface\n }\n\n return Button\n})($)\n\nexport default Button\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Carousel = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'carousel'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.carousel'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key\n const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key\n const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch\n\n const Default = {\n interval : 5000,\n keyboard : true,\n slide : false,\n pause : 'hover',\n wrap : true\n }\n\n const DefaultType = {\n interval : '(number|boolean)',\n keyboard : 'boolean',\n slide : '(boolean|string)',\n pause : '(string|boolean)',\n wrap : 'boolean'\n }\n\n const Direction = {\n NEXT : 'next',\n PREV : 'prev',\n LEFT : 'left',\n RIGHT : 'right'\n }\n\n const Event = {\n SLIDE : `slide${EVENT_KEY}`,\n SLID : `slid${EVENT_KEY}`,\n KEYDOWN : `keydown${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`,\n TOUCHEND : `touchend${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n CAROUSEL : 'carousel',\n ACTIVE : 'active',\n SLIDE : 'slide',\n RIGHT : 'carousel-item-right',\n LEFT : 'carousel-item-left',\n NEXT : 'carousel-item-next',\n PREV : 'carousel-item-prev',\n ITEM : 'carousel-item'\n }\n\n const Selector = {\n ACTIVE : '.active',\n ACTIVE_ITEM : '.active.carousel-item',\n ITEM : '.carousel-item',\n NEXT_PREV : '.carousel-item-next, .carousel-item-prev',\n INDICATORS : '.carousel-indicators',\n DATA_SLIDE : '[data-slide], [data-slide-to]',\n DATA_RIDE : '[data-ride=\"carousel\"]'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Carousel {\n constructor(element, config) {\n this._items = null\n this._interval = null\n this._activeElement = null\n\n this._isPaused = false\n this._isSliding = false\n\n this.touchTimeout = null\n\n this._config = this._getConfig(config)\n this._element = $(element)[0]\n this._indicatorsElement = this._element.querySelector(Selector.INDICATORS)\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n next() {\n if (!this._isSliding) {\n this._slide(Direction.NEXT)\n }\n }\n\n nextWhenVisible() {\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden &&\n ($(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden')) {\n this.next()\n }\n }\n\n prev() {\n if (!this._isSliding) {\n this._slide(Direction.PREV)\n }\n }\n\n pause(event) {\n if (!event) {\n this._isPaused = true\n }\n\n if (this._element.querySelector(Selector.NEXT_PREV)) {\n Util.triggerTransitionEnd(this._element)\n this.cycle(true)\n }\n\n clearInterval(this._interval)\n this._interval = null\n }\n\n cycle(event) {\n if (!event) {\n this._isPaused = false\n }\n\n if (this._interval) {\n clearInterval(this._interval)\n this._interval = null\n }\n\n if (this._config.interval && !this._isPaused) {\n this._interval = setInterval(\n (document.visibilityState ? this.nextWhenVisible : this.next).bind(this),\n this._config.interval\n )\n }\n }\n\n to(index) {\n this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n\n const activeIndex = this._getItemIndex(this._activeElement)\n\n if (index > this._items.length - 1 || index < 0) {\n return\n }\n\n if (this._isSliding) {\n $(this._element).one(Event.SLID, () => this.to(index))\n return\n }\n\n if (activeIndex === index) {\n this.pause()\n this.cycle()\n return\n }\n\n const direction = index > activeIndex\n ? Direction.NEXT\n : Direction.PREV\n\n this._slide(direction, this._items[index])\n }\n\n dispose() {\n $(this._element).off(EVENT_KEY)\n $.removeData(this._element, DATA_KEY)\n\n this._items = null\n this._config = null\n this._element = null\n this._interval = null\n this._isPaused = null\n this._isSliding = null\n this._activeElement = null\n this._indicatorsElement = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _addEventListeners() {\n if (this._config.keyboard) {\n $(this._element)\n .on(Event.KEYDOWN, (event) => this._keydown(event))\n }\n\n if (this._config.pause === 'hover') {\n $(this._element)\n .on(Event.MOUSEENTER, (event) => this.pause(event))\n .on(Event.MOUSELEAVE, (event) => this.cycle(event))\n if ('ontouchstart' in document.documentElement) {\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n $(this._element).on(Event.TOUCHEND, () => {\n this.pause()\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout)\n }\n this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)\n })\n }\n }\n }\n\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return\n }\n\n switch (event.which) {\n case ARROW_LEFT_KEYCODE:\n event.preventDefault()\n this.prev()\n break\n case ARROW_RIGHT_KEYCODE:\n event.preventDefault()\n this.next()\n break\n default:\n }\n }\n\n _getItemIndex(element) {\n this._items = element && element.parentNode\n ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM))\n : []\n return this._items.indexOf(element)\n }\n\n _getItemByDirection(direction, activeElement) {\n const isNextDirection = direction === Direction.NEXT\n const isPrevDirection = direction === Direction.PREV\n const activeIndex = this._getItemIndex(activeElement)\n const lastItemIndex = this._items.length - 1\n const isGoingToWrap = isPrevDirection && activeIndex === 0 ||\n isNextDirection && activeIndex === lastItemIndex\n\n if (isGoingToWrap && !this._config.wrap) {\n return activeElement\n }\n\n const delta = direction === Direction.PREV ? -1 : 1\n const itemIndex = (activeIndex + delta) % this._items.length\n\n return itemIndex === -1\n ? this._items[this._items.length - 1] : this._items[itemIndex]\n }\n\n _triggerSlideEvent(relatedTarget, eventDirectionName) {\n const targetIndex = this._getItemIndex(relatedTarget)\n const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM))\n const slideEvent = $.Event(Event.SLIDE, {\n relatedTarget,\n direction: eventDirectionName,\n from: fromIndex,\n to: targetIndex\n })\n\n $(this._element).trigger(slideEvent)\n\n return slideEvent\n }\n\n _setActiveIndicatorElement(element) {\n if (this._indicatorsElement) {\n const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE))\n $(indicators)\n .removeClass(ClassName.ACTIVE)\n\n const nextIndicator = this._indicatorsElement.children[\n this._getItemIndex(element)\n ]\n\n if (nextIndicator) {\n $(nextIndicator).addClass(ClassName.ACTIVE)\n }\n }\n }\n\n _slide(direction, element) {\n const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n const activeElementIndex = this._getItemIndex(activeElement)\n const nextElement = element || activeElement &&\n this._getItemByDirection(direction, activeElement)\n const nextElementIndex = this._getItemIndex(nextElement)\n const isCycling = Boolean(this._interval)\n\n let directionalClassName\n let orderClassName\n let eventDirectionName\n\n if (direction === Direction.NEXT) {\n directionalClassName = ClassName.LEFT\n orderClassName = ClassName.NEXT\n eventDirectionName = Direction.LEFT\n } else {\n directionalClassName = ClassName.RIGHT\n orderClassName = ClassName.PREV\n eventDirectionName = Direction.RIGHT\n }\n\n if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {\n this._isSliding = false\n return\n }\n\n const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)\n if (slideEvent.isDefaultPrevented()) {\n return\n }\n\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n return\n }\n\n this._isSliding = true\n\n if (isCycling) {\n this.pause()\n }\n\n this._setActiveIndicatorElement(nextElement)\n\n const slidEvent = $.Event(Event.SLID, {\n relatedTarget: nextElement,\n direction: eventDirectionName,\n from: activeElementIndex,\n to: nextElementIndex\n })\n\n if ($(this._element).hasClass(ClassName.SLIDE)) {\n $(nextElement).addClass(orderClassName)\n\n Util.reflow(nextElement)\n\n $(activeElement).addClass(directionalClassName)\n $(nextElement).addClass(directionalClassName)\n\n const transitionDuration = Util.getTransitionDurationFromElement(activeElement)\n\n $(activeElement)\n .one(Util.TRANSITION_END, () => {\n $(nextElement)\n .removeClass(`${directionalClassName} ${orderClassName}`)\n .addClass(ClassName.ACTIVE)\n\n $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`)\n\n this._isSliding = false\n\n setTimeout(() => $(this._element).trigger(slidEvent), 0)\n })\n .emulateTransitionEnd(transitionDuration)\n } else {\n $(activeElement).removeClass(ClassName.ACTIVE)\n $(nextElement).addClass(ClassName.ACTIVE)\n\n this._isSliding = false\n $(this._element).trigger(slidEvent)\n }\n\n if (isCycling) {\n this.cycle()\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n let _config = {\n ...Default,\n ...$(this).data()\n }\n\n if (typeof config === 'object') {\n _config = {\n ..._config,\n ...config\n }\n }\n\n const action = typeof config === 'string' ? config : _config.slide\n\n if (!data) {\n data = new Carousel(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'number') {\n data.to(config)\n } else if (typeof action === 'string') {\n if (typeof data[action] === 'undefined') {\n throw new TypeError(`No method named \"${action}\"`)\n }\n data[action]()\n } else if (_config.interval) {\n data.pause()\n data.cycle()\n }\n })\n }\n\n static _dataApiClickHandler(event) {\n const selector = Util.getSelectorFromElement(this)\n\n if (!selector) {\n return\n }\n\n const target = $(selector)[0]\n\n if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {\n return\n }\n\n const config = {\n ...$(target).data(),\n ...$(this).data()\n }\n const slideIndex = this.getAttribute('data-slide-to')\n\n if (slideIndex) {\n config.interval = false\n }\n\n Carousel._jQueryInterface.call($(target), config)\n\n if (slideIndex) {\n $(target).data(DATA_KEY).to(slideIndex)\n }\n\n event.preventDefault()\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler)\n\n $(window).on(Event.LOAD_DATA_API, () => {\n const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE))\n for (let i = 0, len = carousels.length; i < len; i++) {\n const $carousel = $(carousels[i])\n Carousel._jQueryInterface.call($carousel, $carousel.data())\n }\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Carousel._jQueryInterface\n $.fn[NAME].Constructor = Carousel\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Carousel._jQueryInterface\n }\n\n return Carousel\n})($)\n\nexport default Carousel\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Collapse = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'collapse'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.collapse'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Default = {\n toggle : true,\n parent : ''\n }\n\n const DefaultType = {\n toggle : 'boolean',\n parent : '(string|element)'\n }\n\n const Event = {\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n SHOW : 'show',\n COLLAPSE : 'collapse',\n COLLAPSING : 'collapsing',\n COLLAPSED : 'collapsed'\n }\n\n const Dimension = {\n WIDTH : 'width',\n HEIGHT : 'height'\n }\n\n const Selector = {\n ACTIVES : '.show, .collapsing',\n DATA_TOGGLE : '[data-toggle=\"collapse\"]'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Collapse {\n constructor(element, config) {\n this._isTransitioning = false\n this._element = element\n this._config = this._getConfig(config)\n this._triggerArray = $.makeArray(document.querySelectorAll(\n `[data-toggle=\"collapse\"][href=\"#${element.id}\"],` +\n `[data-toggle=\"collapse\"][data-target=\"#${element.id}\"]`\n ))\n const toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n for (let i = 0, len = toggleList.length; i < len; i++) {\n const elem = toggleList[i]\n const selector = Util.getSelectorFromElement(elem)\n const filterElement = [].slice.call(document.querySelectorAll(selector))\n .filter((foundElem) => foundElem === element)\n\n if (selector !== null && filterElement.length > 0) {\n this._selector = selector\n this._triggerArray.push(elem)\n }\n }\n\n this._parent = this._config.parent ? this._getParent() : null\n\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._element, this._triggerArray)\n }\n\n if (this._config.toggle) {\n this.toggle()\n }\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle() {\n if ($(this._element).hasClass(ClassName.SHOW)) {\n this.hide()\n } else {\n this.show()\n }\n }\n\n show() {\n if (this._isTransitioning ||\n $(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n let actives\n let activesData\n\n if (this._parent) {\n actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES))\n .filter((elem) => elem.getAttribute('data-parent') === this._config.parent)\n\n if (actives.length === 0) {\n actives = null\n }\n }\n\n if (actives) {\n activesData = $(actives).not(this._selector).data(DATA_KEY)\n if (activesData && activesData._isTransitioning) {\n return\n }\n }\n\n const startEvent = $.Event(Event.SHOW)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n if (actives) {\n Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide')\n if (!activesData) {\n $(actives).data(DATA_KEY, null)\n }\n }\n\n const dimension = this._getDimension()\n\n $(this._element)\n .removeClass(ClassName.COLLAPSE)\n .addClass(ClassName.COLLAPSING)\n\n this._element.style[dimension] = 0\n\n if (this._triggerArray.length) {\n $(this._triggerArray)\n .removeClass(ClassName.COLLAPSED)\n .attr('aria-expanded', true)\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .addClass(ClassName.SHOW)\n\n this._element.style[dimension] = ''\n\n this.setTransitioning(false)\n\n $(this._element).trigger(Event.SHOWN)\n }\n\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)\n const scrollSize = `scroll${capitalizedDimension}`\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n\n this._element.style[dimension] = `${this._element[scrollSize]}px`\n }\n\n hide() {\n if (this._isTransitioning ||\n !$(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n const startEvent = $.Event(Event.HIDE)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n const dimension = this._getDimension()\n\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`\n\n Util.reflow(this._element)\n\n $(this._element)\n .addClass(ClassName.COLLAPSING)\n .removeClass(ClassName.COLLAPSE)\n .removeClass(ClassName.SHOW)\n\n const triggerArrayLength = this._triggerArray.length\n if (triggerArrayLength > 0) {\n for (let i = 0; i < triggerArrayLength; i++) {\n const trigger = this._triggerArray[i]\n const selector = Util.getSelectorFromElement(trigger)\n if (selector !== null) {\n const $elem = $([].slice.call(document.querySelectorAll(selector)))\n if (!$elem.hasClass(ClassName.SHOW)) {\n $(trigger).addClass(ClassName.COLLAPSED)\n .attr('aria-expanded', false)\n }\n }\n }\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n this.setTransitioning(false)\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .trigger(Event.HIDDEN)\n }\n\n this._element.style[dimension] = ''\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n }\n\n setTransitioning(isTransitioning) {\n this._isTransitioning = isTransitioning\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n this._config = null\n this._parent = null\n this._element = null\n this._triggerArray = null\n this._isTransitioning = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n config.toggle = Boolean(config.toggle) // Coerce string values\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _getDimension() {\n const hasWidth = $(this._element).hasClass(Dimension.WIDTH)\n return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT\n }\n\n _getParent() {\n let parent = null\n if (Util.isElement(this._config.parent)) {\n parent = this._config.parent\n\n // It's a jQuery object\n if (typeof this._config.parent.jquery !== 'undefined') {\n parent = this._config.parent[0]\n }\n } else {\n parent = document.querySelector(this._config.parent)\n }\n\n const selector =\n `[data-toggle=\"collapse\"][data-parent=\"${this._config.parent}\"]`\n\n const children = [].slice.call(parent.querySelectorAll(selector))\n $(children).each((i, element) => {\n this._addAriaAndCollapsedClass(\n Collapse._getTargetFromElement(element),\n [element]\n )\n })\n\n return parent\n }\n\n _addAriaAndCollapsedClass(element, triggerArray) {\n if (element) {\n const isOpen = $(element).hasClass(ClassName.SHOW)\n\n if (triggerArray.length) {\n $(triggerArray)\n .toggleClass(ClassName.COLLAPSED, !isOpen)\n .attr('aria-expanded', isOpen)\n }\n }\n }\n\n // Static\n\n static _getTargetFromElement(element) {\n const selector = Util.getSelectorFromElement(element)\n return selector ? document.querySelector(selector) : null\n }\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $this = $(this)\n let data = $this.data(DATA_KEY)\n const _config = {\n ...Default,\n ...$this.data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data && _config.toggle && /show|hide/.test(config)) {\n _config.toggle = false\n }\n\n if (!data) {\n data = new Collapse(this, _config)\n $this.data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n // preventDefault only for
elements (which change the URL) not inside the collapsible element\n if (event.currentTarget.tagName === 'A') {\n event.preventDefault()\n }\n\n const $trigger = $(this)\n const selector = Util.getSelectorFromElement(this)\n const selectors = [].slice.call(document.querySelectorAll(selector))\n $(selectors).each(function () {\n const $target = $(this)\n const data = $target.data(DATA_KEY)\n const config = data ? 'toggle' : $trigger.data()\n Collapse._jQueryInterface.call($target, config)\n })\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Collapse._jQueryInterface\n $.fn[NAME].Constructor = Collapse\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Collapse._jQueryInterface\n }\n\n return Collapse\n})($)\n\nexport default Collapse\n","import $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Dropdown = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'dropdown'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.dropdown'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n const SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key\n const TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key\n const ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key\n const ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key\n const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse)\n const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`)\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,\n KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`,\n KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n DISABLED : 'disabled',\n SHOW : 'show',\n DROPUP : 'dropup',\n DROPRIGHT : 'dropright',\n DROPLEFT : 'dropleft',\n MENURIGHT : 'dropdown-menu-right',\n MENULEFT : 'dropdown-menu-left',\n POSITION_STATIC : 'position-static'\n }\n\n const Selector = {\n DATA_TOGGLE : '[data-toggle=\"dropdown\"]',\n FORM_CHILD : '.dropdown form',\n MENU : '.dropdown-menu',\n NAVBAR_NAV : '.navbar-nav',\n VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'\n }\n\n const AttachmentMap = {\n TOP : 'top-start',\n TOPEND : 'top-end',\n BOTTOM : 'bottom-start',\n BOTTOMEND : 'bottom-end',\n RIGHT : 'right-start',\n RIGHTEND : 'right-end',\n LEFT : 'left-start',\n LEFTEND : 'left-end'\n }\n\n const Default = {\n offset : 0,\n flip : true,\n boundary : 'scrollParent',\n reference : 'toggle',\n display : 'dynamic'\n }\n\n const DefaultType = {\n offset : '(number|string|function)',\n flip : 'boolean',\n boundary : '(string|element)',\n reference : '(string|element)',\n display : 'string'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Dropdown {\n constructor(element, config) {\n this._element = element\n this._popper = null\n this._config = this._getConfig(config)\n this._menu = this._getMenuElement()\n this._inNavbar = this._detectNavbar()\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n toggle() {\n if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this._element)\n const isActive = $(this._menu).hasClass(ClassName.SHOW)\n\n Dropdown._clearMenus()\n\n if (isActive) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n const showEvent = $.Event(Event.SHOW, relatedTarget)\n\n $(parent).trigger(showEvent)\n\n if (showEvent.isDefaultPrevented()) {\n return\n }\n\n // Disable totally Popper.js for Dropdown in Navbar\n if (!this._inNavbar) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)')\n }\n\n let referenceElement = this._element\n\n if (this._config.reference === 'parent') {\n referenceElement = parent\n } else if (Util.isElement(this._config.reference)) {\n referenceElement = this._config.reference\n\n // Check if it's jQuery element\n if (typeof this._config.reference.jquery !== 'undefined') {\n referenceElement = this._config.reference[0]\n }\n }\n\n // If boundary is not `scrollParent`, then set position to `static`\n // to allow the menu to \"escape\" the scroll parent's boundaries\n // https://github.com/twbs/bootstrap/issues/24251\n if (this._config.boundary !== 'scrollParent') {\n $(parent).addClass(ClassName.POSITION_STATIC)\n }\n this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig())\n }\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement &&\n $(parent).closest(Selector.NAVBAR_NAV).length === 0) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n this._element.focus()\n this._element.setAttribute('aria-expanded', true)\n\n $(this._menu).toggleClass(ClassName.SHOW)\n $(parent)\n .toggleClass(ClassName.SHOW)\n .trigger($.Event(Event.SHOWN, relatedTarget))\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._element).off(EVENT_KEY)\n this._element = null\n this._menu = null\n if (this._popper !== null) {\n this._popper.destroy()\n this._popper = null\n }\n }\n\n update() {\n this._inNavbar = this._detectNavbar()\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Private\n\n _addEventListeners() {\n $(this._element).on(Event.CLICK, (event) => {\n event.preventDefault()\n event.stopPropagation()\n this.toggle()\n })\n }\n\n _getConfig(config) {\n config = {\n ...this.constructor.Default,\n ...$(this._element).data(),\n ...config\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n return config\n }\n\n _getMenuElement() {\n if (!this._menu) {\n const parent = Dropdown._getParentFromElement(this._element)\n if (parent) {\n this._menu = parent.querySelector(Selector.MENU)\n }\n }\n return this._menu\n }\n\n _getPlacement() {\n const $parentDropdown = $(this._element.parentNode)\n let placement = AttachmentMap.BOTTOM\n\n // Handle dropup\n if ($parentDropdown.hasClass(ClassName.DROPUP)) {\n placement = AttachmentMap.TOP\n if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n placement = AttachmentMap.TOPEND\n }\n } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {\n placement = AttachmentMap.RIGHT\n } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {\n placement = AttachmentMap.LEFT\n } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n placement = AttachmentMap.BOTTOMEND\n }\n return placement\n }\n\n _detectNavbar() {\n return $(this._element).closest('.navbar').length > 0\n }\n\n _getPopperConfig() {\n const offsetConf = {}\n if (typeof this._config.offset === 'function') {\n offsetConf.fn = (data) => {\n data.offsets = {\n ...data.offsets,\n ...this._config.offset(data.offsets) || {}\n }\n return data\n }\n } else {\n offsetConf.offset = this._config.offset\n }\n\n const popperConfig = {\n placement: this._getPlacement(),\n modifiers: {\n offset: offsetConf,\n flip: {\n enabled: this._config.flip\n },\n preventOverflow: {\n boundariesElement: this._config.boundary\n }\n }\n }\n\n // Disable Popper.js if we have a static display\n if (this._config.display === 'static') {\n popperConfig.modifiers.applyStyle = {\n enabled: false\n }\n }\n return popperConfig\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data) {\n data = new Dropdown(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n\n static _clearMenus(event) {\n if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH ||\n event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n return\n }\n\n const toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n for (let i = 0, len = toggles.length; i < len; i++) {\n const parent = Dropdown._getParentFromElement(toggles[i])\n const context = $(toggles[i]).data(DATA_KEY)\n const relatedTarget = {\n relatedTarget: toggles[i]\n }\n\n if (event && event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n if (!context) {\n continue\n }\n\n const dropdownMenu = context._menu\n if (!$(parent).hasClass(ClassName.SHOW)) {\n continue\n }\n\n if (event && (event.type === 'click' &&\n /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) &&\n $.contains(parent, event.target)) {\n continue\n }\n\n const hideEvent = $.Event(Event.HIDE, relatedTarget)\n $(parent).trigger(hideEvent)\n if (hideEvent.isDefaultPrevented()) {\n continue\n }\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n toggles[i].setAttribute('aria-expanded', 'false')\n\n $(dropdownMenu).removeClass(ClassName.SHOW)\n $(parent)\n .removeClass(ClassName.SHOW)\n .trigger($.Event(Event.HIDDEN, relatedTarget))\n }\n }\n\n static _getParentFromElement(element) {\n let parent\n const selector = Util.getSelectorFromElement(element)\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n return parent || element.parentNode\n }\n\n // eslint-disable-next-line complexity\n static _dataApiKeydownHandler(event) {\n // If not input/textarea:\n // - And not a key in REGEXP_KEYDOWN => not a dropdown command\n // If input/textarea:\n // - If space key => not a dropdown command\n // - If key is other than escape\n // - If key is not up or down => not a dropdown command\n // - If trigger inside the menu => not a dropdown command\n if (/input|textarea/i.test(event.target.tagName)\n ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE &&\n (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE ||\n $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n\n if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this)\n const isActive = $(parent).hasClass(ClassName.SHOW)\n\n if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) ||\n isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {\n if (event.which === ESCAPE_KEYCODE) {\n const toggle = parent.querySelector(Selector.DATA_TOGGLE)\n $(toggle).trigger('focus')\n }\n\n $(this).trigger('click')\n return\n }\n\n const items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS))\n\n if (items.length === 0) {\n return\n }\n\n let index = items.indexOf(event.target)\n\n if (event.which === ARROW_UP_KEYCODE && index > 0) { // Up\n index--\n }\n\n if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // Down\n index++\n }\n\n if (index < 0) {\n index = 0\n }\n\n items[index].focus()\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)\n .on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler)\n .on(`${Event.CLICK_DATA_API} ${Event.KEYUP_DATA_API}`, Dropdown._clearMenus)\n .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n event.preventDefault()\n event.stopPropagation()\n Dropdown._jQueryInterface.call($(this), 'toggle')\n })\n .on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => {\n e.stopPropagation()\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Dropdown._jQueryInterface\n $.fn[NAME].Constructor = Dropdown\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Dropdown._jQueryInterface\n }\n\n return Dropdown\n})($, Popper)\n\nexport default Dropdown\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Modal = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'modal'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.modal'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n\n const Default = {\n backdrop : true,\n keyboard : true,\n focus : true,\n show : true\n }\n\n const DefaultType = {\n backdrop : '(boolean|string)',\n keyboard : 'boolean',\n focus : 'boolean',\n show : 'boolean'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n RESIZE : `resize${EVENT_KEY}`,\n CLICK_DISMISS : `click.dismiss${EVENT_KEY}`,\n KEYDOWN_DISMISS : `keydown.dismiss${EVENT_KEY}`,\n MOUSEUP_DISMISS : `mouseup.dismiss${EVENT_KEY}`,\n MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n SCROLLBAR_MEASURER : 'modal-scrollbar-measure',\n BACKDROP : 'modal-backdrop',\n OPEN : 'modal-open',\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n DIALOG : '.modal-dialog',\n DATA_TOGGLE : '[data-toggle=\"modal\"]',\n DATA_DISMISS : '[data-dismiss=\"modal\"]',\n FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',\n STICKY_CONTENT : '.sticky-top'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Modal {\n constructor(element, config) {\n this._config = this._getConfig(config)\n this._element = element\n this._dialog = element.querySelector(Selector.DIALOG)\n this._backdrop = null\n this._isShown = false\n this._isBodyOverflowing = false\n this._ignoreBackdropClick = false\n this._scrollbarWidth = 0\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isTransitioning || this._isShown) {\n return\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n this._isTransitioning = true\n }\n\n const showEvent = $.Event(Event.SHOW, {\n relatedTarget\n })\n\n $(this._element).trigger(showEvent)\n\n if (this._isShown || showEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = true\n\n this._checkScrollbar()\n this._setScrollbar()\n\n this._adjustDialog()\n\n $(document.body).addClass(ClassName.OPEN)\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(this._element).on(\n Event.CLICK_DISMISS,\n Selector.DATA_DISMISS,\n (event) => this.hide(event)\n )\n\n $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => {\n $(this._element).one(Event.MOUSEUP_DISMISS, (event) => {\n if ($(event.target).is(this._element)) {\n this._ignoreBackdropClick = true\n }\n })\n })\n\n this._showBackdrop(() => this._showElement(relatedTarget))\n }\n\n hide(event) {\n if (event) {\n event.preventDefault()\n }\n\n if (this._isTransitioning || !this._isShown) {\n return\n }\n\n const hideEvent = $.Event(Event.HIDE)\n\n $(this._element).trigger(hideEvent)\n\n if (!this._isShown || hideEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = false\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (transition) {\n this._isTransitioning = true\n }\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(document).off(Event.FOCUSIN)\n\n $(this._element).removeClass(ClassName.SHOW)\n\n $(this._element).off(Event.CLICK_DISMISS)\n $(this._dialog).off(Event.MOUSEDOWN_DISMISS)\n\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, (event) => this._hideModal(event))\n .emulateTransitionEnd(transitionDuration)\n } else {\n this._hideModal()\n }\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n $(window, document, this._element, this._backdrop).off(EVENT_KEY)\n\n this._config = null\n this._element = null\n this._dialog = null\n this._backdrop = null\n this._isShown = null\n this._isBodyOverflowing = null\n this._ignoreBackdropClick = null\n this._scrollbarWidth = null\n }\n\n handleUpdate() {\n this._adjustDialog()\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _showElement(relatedTarget) {\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (!this._element.parentNode ||\n this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n // Don't move modal's DOM position\n document.body.appendChild(this._element)\n }\n\n this._element.style.display = 'block'\n this._element.removeAttribute('aria-hidden')\n this._element.scrollTop = 0\n\n if (transition) {\n Util.reflow(this._element)\n }\n\n $(this._element).addClass(ClassName.SHOW)\n\n if (this._config.focus) {\n this._enforceFocus()\n }\n\n const shownEvent = $.Event(Event.SHOWN, {\n relatedTarget\n })\n\n const transitionComplete = () => {\n if (this._config.focus) {\n this._element.focus()\n }\n this._isTransitioning = false\n $(this._element).trigger(shownEvent)\n }\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._dialog)\n .one(Util.TRANSITION_END, transitionComplete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n transitionComplete()\n }\n }\n\n _enforceFocus() {\n $(document)\n .off(Event.FOCUSIN) // Guard against infinite focus loop\n .on(Event.FOCUSIN, (event) => {\n if (document !== event.target &&\n this._element !== event.target &&\n $(this._element).has(event.target).length === 0) {\n this._element.focus()\n }\n })\n }\n\n _setEscapeEvent() {\n if (this._isShown && this._config.keyboard) {\n $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {\n if (event.which === ESCAPE_KEYCODE) {\n event.preventDefault()\n this.hide()\n }\n })\n } else if (!this._isShown) {\n $(this._element).off(Event.KEYDOWN_DISMISS)\n }\n }\n\n _setResizeEvent() {\n if (this._isShown) {\n $(window).on(Event.RESIZE, (event) => this.handleUpdate(event))\n } else {\n $(window).off(Event.RESIZE)\n }\n }\n\n _hideModal() {\n this._element.style.display = 'none'\n this._element.setAttribute('aria-hidden', true)\n this._isTransitioning = false\n this._showBackdrop(() => {\n $(document.body).removeClass(ClassName.OPEN)\n this._resetAdjustments()\n this._resetScrollbar()\n $(this._element).trigger(Event.HIDDEN)\n })\n }\n\n _removeBackdrop() {\n if (this._backdrop) {\n $(this._backdrop).remove()\n this._backdrop = null\n }\n }\n\n _showBackdrop(callback) {\n const animate = $(this._element).hasClass(ClassName.FADE)\n ? ClassName.FADE : ''\n\n if (this._isShown && this._config.backdrop) {\n this._backdrop = document.createElement('div')\n this._backdrop.className = ClassName.BACKDROP\n\n if (animate) {\n this._backdrop.classList.add(animate)\n }\n\n $(this._backdrop).appendTo(document.body)\n\n $(this._element).on(Event.CLICK_DISMISS, (event) => {\n if (this._ignoreBackdropClick) {\n this._ignoreBackdropClick = false\n return\n }\n if (event.target !== event.currentTarget) {\n return\n }\n if (this._config.backdrop === 'static') {\n this._element.focus()\n } else {\n this.hide()\n }\n })\n\n if (animate) {\n Util.reflow(this._backdrop)\n }\n\n $(this._backdrop).addClass(ClassName.SHOW)\n\n if (!callback) {\n return\n }\n\n if (!animate) {\n callback()\n return\n }\n\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callback)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else if (!this._isShown && this._backdrop) {\n $(this._backdrop).removeClass(ClassName.SHOW)\n\n const callbackRemove = () => {\n this._removeBackdrop()\n if (callback) {\n callback()\n }\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callbackRemove)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else {\n callbackRemove()\n }\n } else if (callback) {\n callback()\n }\n }\n\n // ----------------------------------------------------------------------\n // the following methods are used to handle overflowing modals\n // todo (fat): these should probably be refactored out of modal.js\n // ----------------------------------------------------------------------\n\n _adjustDialog() {\n const isModalOverflowing =\n this._element.scrollHeight > document.documentElement.clientHeight\n\n if (!this._isBodyOverflowing && isModalOverflowing) {\n this._element.style.paddingLeft = `${this._scrollbarWidth}px`\n }\n\n if (this._isBodyOverflowing && !isModalOverflowing) {\n this._element.style.paddingRight = `${this._scrollbarWidth}px`\n }\n }\n\n _resetAdjustments() {\n this._element.style.paddingLeft = ''\n this._element.style.paddingRight = ''\n }\n\n _checkScrollbar() {\n const rect = document.body.getBoundingClientRect()\n this._isBodyOverflowing = rect.left + rect.right < window.innerWidth\n this._scrollbarWidth = this._getScrollbarWidth()\n }\n\n _setScrollbar() {\n if (this._isBodyOverflowing) {\n // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT))\n\n // Adjust fixed content padding\n $(fixedContent).each((index, element) => {\n const actualPadding = element.style.paddingRight\n const calculatedPadding = $(element).css('padding-right')\n $(element)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n })\n\n // Adjust sticky content margin\n $(stickyContent).each((index, element) => {\n const actualMargin = element.style.marginRight\n const calculatedMargin = $(element).css('margin-right')\n $(element)\n .data('margin-right', actualMargin)\n .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`)\n })\n\n // Adjust body padding\n const actualPadding = document.body.style.paddingRight\n const calculatedPadding = $(document.body).css('padding-right')\n $(document.body)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n }\n }\n\n _resetScrollbar() {\n // Restore fixed content padding\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n $(fixedContent).each((index, element) => {\n const padding = $(element).data('padding-right')\n $(element).removeData('padding-right')\n element.style.paddingRight = padding ? padding : ''\n })\n\n // Restore sticky content\n const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`))\n $(elements).each((index, element) => {\n const margin = $(element).data('margin-right')\n if (typeof margin !== 'undefined') {\n $(element).css('margin-right', margin).removeData('margin-right')\n }\n })\n\n // Restore body padding\n const padding = $(document.body).data('padding-right')\n $(document.body).removeData('padding-right')\n document.body.style.paddingRight = padding ? padding : ''\n }\n\n _getScrollbarWidth() { // thx d.walsh\n const scrollDiv = document.createElement('div')\n scrollDiv.className = ClassName.SCROLLBAR_MEASURER\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n }\n\n // Static\n\n static _jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = {\n ...Default,\n ...$(this).data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data) {\n data = new Modal(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config](relatedTarget)\n } else if (_config.show) {\n data.show(relatedTarget)\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n let target\n const selector = Util.getSelectorFromElement(this)\n\n if (selector) {\n target = document.querySelector(selector)\n }\n\n const config = $(target).data(DATA_KEY)\n ? 'toggle' : {\n ...$(target).data(),\n ...$(this).data()\n }\n\n if (this.tagName === 'A' || this.tagName === 'AREA') {\n event.preventDefault()\n }\n\n const $target = $(target).one(Event.SHOW, (showEvent) => {\n if (showEvent.isDefaultPrevented()) {\n // Only register focus restorer if modal will actually get shown\n return\n }\n\n $target.one(Event.HIDDEN, () => {\n if ($(this).is(':visible')) {\n this.focus()\n }\n })\n })\n\n Modal._jQueryInterface.call($(target), config, this)\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Modal._jQueryInterface\n $.fn[NAME].Constructor = Modal\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Modal._jQueryInterface\n }\n\n return Modal\n})($)\n\nexport default Modal\n","import $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Tooltip = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'tooltip'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.tooltip'\n const EVENT_KEY = `.${DATA_KEY}`\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const CLASS_PREFIX = 'bs-tooltip'\n const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\n\n const DefaultType = {\n animation : 'boolean',\n template : 'string',\n title : '(string|element|function)',\n trigger : 'string',\n delay : '(number|object)',\n html : 'boolean',\n selector : '(string|boolean)',\n placement : '(string|function)',\n offset : '(number|string)',\n container : '(string|element|boolean)',\n fallbackPlacement : '(string|array)',\n boundary : '(string|element)'\n }\n\n const AttachmentMap = {\n AUTO : 'auto',\n TOP : 'top',\n RIGHT : 'right',\n BOTTOM : 'bottom',\n LEFT : 'left'\n }\n\n const Default = {\n animation : true,\n template : '
' +\n '
' +\n '
',\n trigger : 'hover focus',\n title : '',\n delay : 0,\n html : false,\n selector : false,\n placement : 'top',\n offset : 0,\n container : false,\n fallbackPlacement : 'flip',\n boundary : 'scrollParent'\n }\n\n const HoverState = {\n SHOW : 'show',\n OUT : 'out'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n INSERTED : `inserted${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n FOCUSOUT : `focusout${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`\n }\n\n const ClassName = {\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n TOOLTIP : '.tooltip',\n TOOLTIP_INNER : '.tooltip-inner',\n ARROW : '.arrow'\n }\n\n const Trigger = {\n HOVER : 'hover',\n FOCUS : 'focus',\n CLICK : 'click',\n MANUAL : 'manual'\n }\n\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Tooltip {\n constructor(element, config) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)')\n }\n\n // private\n this._isEnabled = true\n this._timeout = 0\n this._hoverState = ''\n this._activeTrigger = {}\n this._popper = null\n\n // Protected\n this.element = element\n this.config = this._getConfig(config)\n this.tip = null\n\n this._setListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n enable() {\n this._isEnabled = true\n }\n\n disable() {\n this._isEnabled = false\n }\n\n toggleEnabled() {\n this._isEnabled = !this._isEnabled\n }\n\n toggle(event) {\n if (!this._isEnabled) {\n return\n }\n\n if (event) {\n const dataKey = this.constructor.DATA_KEY\n let context = $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n context._activeTrigger.click = !context._activeTrigger.click\n\n if (context._isWithActiveTrigger()) {\n context._enter(null, context)\n } else {\n context._leave(null, context)\n }\n } else {\n if ($(this.getTipElement()).hasClass(ClassName.SHOW)) {\n this._leave(null, this)\n return\n }\n\n this._enter(null, this)\n }\n }\n\n dispose() {\n clearTimeout(this._timeout)\n\n $.removeData(this.element, this.constructor.DATA_KEY)\n\n $(this.element).off(this.constructor.EVENT_KEY)\n $(this.element).closest('.modal').off('hide.bs.modal')\n\n if (this.tip) {\n $(this.tip).remove()\n }\n\n this._isEnabled = null\n this._timeout = null\n this._hoverState = null\n this._activeTrigger = null\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n this._popper = null\n this.element = null\n this.config = null\n this.tip = null\n }\n\n show() {\n if ($(this.element).css('display') === 'none') {\n throw new Error('Please use show on visible elements')\n }\n\n const showEvent = $.Event(this.constructor.Event.SHOW)\n if (this.isWithContent() && this._isEnabled) {\n $(this.element).trigger(showEvent)\n\n const isInTheDom = $.contains(\n this.element.ownerDocument.documentElement,\n this.element\n )\n\n if (showEvent.isDefaultPrevented() || !isInTheDom) {\n return\n }\n\n const tip = this.getTipElement()\n const tipId = Util.getUID(this.constructor.NAME)\n\n tip.setAttribute('id', tipId)\n this.element.setAttribute('aria-describedby', tipId)\n\n this.setContent()\n\n if (this.config.animation) {\n $(tip).addClass(ClassName.FADE)\n }\n\n const placement = typeof this.config.placement === 'function'\n ? this.config.placement.call(this, tip, this.element)\n : this.config.placement\n\n const attachment = this._getAttachment(placement)\n this.addAttachmentClass(attachment)\n\n const container = this.config.container === false ? document.body : $(document).find(this.config.container)\n\n $(tip).data(this.constructor.DATA_KEY, this)\n\n if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {\n $(tip).appendTo(container)\n }\n\n $(this.element).trigger(this.constructor.Event.INSERTED)\n\n this._popper = new Popper(this.element, tip, {\n placement: attachment,\n modifiers: {\n offset: {\n offset: this.config.offset\n },\n flip: {\n behavior: this.config.fallbackPlacement\n },\n arrow: {\n element: Selector.ARROW\n },\n preventOverflow: {\n boundariesElement: this.config.boundary\n }\n },\n onCreate: (data) => {\n if (data.originalPlacement !== data.placement) {\n this._handlePopperPlacementChange(data)\n }\n },\n onUpdate: (data) => {\n this._handlePopperPlacementChange(data)\n }\n })\n\n $(tip).addClass(ClassName.SHOW)\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n const complete = () => {\n if (this.config.animation) {\n this._fixTransition()\n }\n const prevHoverState = this._hoverState\n this._hoverState = null\n\n $(this.element).trigger(this.constructor.Event.SHOWN)\n\n if (prevHoverState === HoverState.OUT) {\n this._leave(null, this)\n }\n }\n\n if ($(this.tip).hasClass(ClassName.FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(this.tip)\n\n $(this.tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n }\n }\n\n hide(callback) {\n const tip = this.getTipElement()\n const hideEvent = $.Event(this.constructor.Event.HIDE)\n const complete = () => {\n if (this._hoverState !== HoverState.SHOW && tip.parentNode) {\n tip.parentNode.removeChild(tip)\n }\n\n this._cleanTipClass()\n this.element.removeAttribute('aria-describedby')\n $(this.element).trigger(this.constructor.Event.HIDDEN)\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n if (callback) {\n callback()\n }\n }\n\n $(this.element).trigger(hideEvent)\n\n if (hideEvent.isDefaultPrevented()) {\n return\n }\n\n $(tip).removeClass(ClassName.SHOW)\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n this._activeTrigger[Trigger.CLICK] = false\n this._activeTrigger[Trigger.FOCUS] = false\n this._activeTrigger[Trigger.HOVER] = false\n\n if ($(this.tip).hasClass(ClassName.FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(tip)\n\n $(tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n\n this._hoverState = ''\n }\n\n update() {\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Protected\n\n isWithContent() {\n return Boolean(this.getTitle())\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const tip = this.getTipElement()\n this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle())\n $(tip).removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)\n }\n\n setElementContent($element, content) {\n const html = this.config.html\n if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n // Content is a DOM node or a jQuery\n if (html) {\n if (!$(content).parent().is($element)) {\n $element.empty().append(content)\n }\n } else {\n $element.text($(content).text())\n }\n } else {\n $element[html ? 'html' : 'text'](content)\n }\n }\n\n getTitle() {\n let title = this.element.getAttribute('data-original-title')\n\n if (!title) {\n title = typeof this.config.title === 'function'\n ? this.config.title.call(this.element)\n : this.config.title\n }\n\n return title\n }\n\n // Private\n\n _getAttachment(placement) {\n return AttachmentMap[placement.toUpperCase()]\n }\n\n _setListeners() {\n const triggers = this.config.trigger.split(' ')\n\n triggers.forEach((trigger) => {\n if (trigger === 'click') {\n $(this.element).on(\n this.constructor.Event.CLICK,\n this.config.selector,\n (event) => this.toggle(event)\n )\n } else if (trigger !== Trigger.MANUAL) {\n const eventIn = trigger === Trigger.HOVER\n ? this.constructor.Event.MOUSEENTER\n : this.constructor.Event.FOCUSIN\n const eventOut = trigger === Trigger.HOVER\n ? this.constructor.Event.MOUSELEAVE\n : this.constructor.Event.FOCUSOUT\n\n $(this.element)\n .on(\n eventIn,\n this.config.selector,\n (event) => this._enter(event)\n )\n .on(\n eventOut,\n this.config.selector,\n (event) => this._leave(event)\n )\n }\n\n $(this.element).closest('.modal').on(\n 'hide.bs.modal',\n () => this.hide()\n )\n })\n\n if (this.config.selector) {\n this.config = {\n ...this.config,\n trigger: 'manual',\n selector: ''\n }\n } else {\n this._fixTitle()\n }\n }\n\n _fixTitle() {\n const titleType = typeof this.element.getAttribute('data-original-title')\n if (this.element.getAttribute('title') ||\n titleType !== 'string') {\n this.element.setAttribute(\n 'data-original-title',\n this.element.getAttribute('title') || ''\n )\n this.element.setAttribute('title', '')\n }\n }\n\n _enter(event, context) {\n const dataKey = this.constructor.DATA_KEY\n\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER\n ] = true\n }\n\n if ($(context.getTipElement()).hasClass(ClassName.SHOW) ||\n context._hoverState === HoverState.SHOW) {\n context._hoverState = HoverState.SHOW\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HoverState.SHOW\n\n if (!context.config.delay || !context.config.delay.show) {\n context.show()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HoverState.SHOW) {\n context.show()\n }\n }, context.config.delay.show)\n }\n\n _leave(event, context) {\n const dataKey = this.constructor.DATA_KEY\n\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER\n ] = false\n }\n\n if (context._isWithActiveTrigger()) {\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HoverState.OUT\n\n if (!context.config.delay || !context.config.delay.hide) {\n context.hide()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HoverState.OUT) {\n context.hide()\n }\n }, context.config.delay.hide)\n }\n\n _isWithActiveTrigger() {\n for (const trigger in this._activeTrigger) {\n if (this._activeTrigger[trigger]) {\n return true\n }\n }\n\n return false\n }\n\n _getConfig(config) {\n config = {\n ...this.constructor.Default,\n ...$(this.element).data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.delay === 'number') {\n config.delay = {\n show: config.delay,\n hide: config.delay\n }\n }\n\n if (typeof config.title === 'number') {\n config.title = config.title.toString()\n }\n\n if (typeof config.content === 'number') {\n config.content = config.content.toString()\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n return config\n }\n\n _getDelegateConfig() {\n const config = {}\n\n if (this.config) {\n for (const key in this.config) {\n if (this.constructor.Default[key] !== this.config[key]) {\n config[key] = this.config[key]\n }\n }\n }\n\n return config\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n _handlePopperPlacementChange(popperData) {\n const popperInstance = popperData.instance\n this.tip = popperInstance.popper\n this._cleanTipClass()\n this.addAttachmentClass(this._getAttachment(popperData.placement))\n }\n\n _fixTransition() {\n const tip = this.getTipElement()\n const initConfigAnimation = this.config.animation\n if (tip.getAttribute('x-placement') !== null) {\n return\n }\n $(tip).removeClass(ClassName.FADE)\n this.config.animation = false\n this.hide()\n this.show()\n this.config.animation = initConfigAnimation\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' && config\n\n if (!data && /dispose|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Tooltip(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Tooltip._jQueryInterface\n $.fn[NAME].Constructor = Tooltip\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Tooltip._jQueryInterface\n }\n\n return Tooltip\n})($, Popper)\n\nexport default Tooltip\n","import $ from 'jquery'\nimport Tooltip from './tooltip'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Popover = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'popover'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.popover'\n const EVENT_KEY = `.${DATA_KEY}`\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const CLASS_PREFIX = 'bs-popover'\n const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\n\n const Default = {\n ...Tooltip.Default,\n placement : 'right',\n trigger : 'click',\n content : '',\n template : '
' +\n '
' +\n '

' +\n '
'\n }\n\n const DefaultType = {\n ...Tooltip.DefaultType,\n content : '(string|element|function)'\n }\n\n const ClassName = {\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n TITLE : '.popover-header',\n CONTENT : '.popover-body'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n INSERTED : `inserted${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n FOCUSOUT : `focusout${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Popover extends Tooltip {\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Overrides\n\n isWithContent() {\n return this.getTitle() || this._getContent()\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const $tip = $(this.getTipElement())\n\n // We use append for html objects to maintain js events\n this.setElementContent($tip.find(Selector.TITLE), this.getTitle())\n let content = this._getContent()\n if (typeof content === 'function') {\n content = content.call(this.element)\n }\n this.setElementContent($tip.find(Selector.CONTENT), content)\n\n $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)\n }\n\n // Private\n\n _getContent() {\n return this.element.getAttribute('data-content') ||\n this.config.content\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length > 0) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data && /destroy|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Popover(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Popover._jQueryInterface\n $.fn[NAME].Constructor = Popover\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Popover._jQueryInterface\n }\n\n return Popover\n})($)\n\nexport default Popover\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst ScrollSpy = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'scrollspy'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.scrollspy'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Default = {\n offset : 10,\n method : 'auto',\n target : ''\n }\n\n const DefaultType = {\n offset : 'number',\n method : 'string',\n target : '(string|element)'\n }\n\n const Event = {\n ACTIVATE : `activate${EVENT_KEY}`,\n SCROLL : `scroll${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n DROPDOWN_ITEM : 'dropdown-item',\n DROPDOWN_MENU : 'dropdown-menu',\n ACTIVE : 'active'\n }\n\n const Selector = {\n DATA_SPY : '[data-spy=\"scroll\"]',\n ACTIVE : '.active',\n NAV_LIST_GROUP : '.nav, .list-group',\n NAV_LINKS : '.nav-link',\n NAV_ITEMS : '.nav-item',\n LIST_ITEMS : '.list-group-item',\n DROPDOWN : '.dropdown',\n DROPDOWN_ITEMS : '.dropdown-item',\n DROPDOWN_TOGGLE : '.dropdown-toggle'\n }\n\n const OffsetMethod = {\n OFFSET : 'offset',\n POSITION : 'position'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class ScrollSpy {\n constructor(element, config) {\n this._element = element\n this._scrollElement = element.tagName === 'BODY' ? window : element\n this._config = this._getConfig(config)\n this._selector = `${this._config.target} ${Selector.NAV_LINKS},` +\n `${this._config.target} ${Selector.LIST_ITEMS},` +\n `${this._config.target} ${Selector.DROPDOWN_ITEMS}`\n this._offsets = []\n this._targets = []\n this._activeTarget = null\n this._scrollHeight = 0\n\n $(this._scrollElement).on(Event.SCROLL, (event) => this._process(event))\n\n this.refresh()\n this._process()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n refresh() {\n const autoMethod = this._scrollElement === this._scrollElement.window\n ? OffsetMethod.OFFSET : OffsetMethod.POSITION\n\n const offsetMethod = this._config.method === 'auto'\n ? autoMethod : this._config.method\n\n const offsetBase = offsetMethod === OffsetMethod.POSITION\n ? this._getScrollTop() : 0\n\n this._offsets = []\n this._targets = []\n\n this._scrollHeight = this._getScrollHeight()\n\n const targets = [].slice.call(document.querySelectorAll(this._selector))\n\n targets\n .map((element) => {\n let target\n const targetSelector = Util.getSelectorFromElement(element)\n\n if (targetSelector) {\n target = document.querySelector(targetSelector)\n }\n\n if (target) {\n const targetBCR = target.getBoundingClientRect()\n if (targetBCR.width || targetBCR.height) {\n // TODO (fat): remove sketch reliance on jQuery position/offset\n return [\n $(target)[offsetMethod]().top + offsetBase,\n targetSelector\n ]\n }\n }\n return null\n })\n .filter((item) => item)\n .sort((a, b) => a[0] - b[0])\n .forEach((item) => {\n this._offsets.push(item[0])\n this._targets.push(item[1])\n })\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._scrollElement).off(EVENT_KEY)\n\n this._element = null\n this._scrollElement = null\n this._config = null\n this._selector = null\n this._offsets = null\n this._targets = null\n this._activeTarget = null\n this._scrollHeight = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.target !== 'string') {\n let id = $(config.target).attr('id')\n if (!id) {\n id = Util.getUID(NAME)\n $(config.target).attr('id', id)\n }\n config.target = `#${id}`\n }\n\n Util.typeCheckConfig(NAME, config, DefaultType)\n\n return config\n }\n\n _getScrollTop() {\n return this._scrollElement === window\n ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop\n }\n\n _getScrollHeight() {\n return this._scrollElement.scrollHeight || Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight\n )\n }\n\n _getOffsetHeight() {\n return this._scrollElement === window\n ? window.innerHeight : this._scrollElement.getBoundingClientRect().height\n }\n\n _process() {\n const scrollTop = this._getScrollTop() + this._config.offset\n const scrollHeight = this._getScrollHeight()\n const maxScroll = this._config.offset +\n scrollHeight -\n this._getOffsetHeight()\n\n if (this._scrollHeight !== scrollHeight) {\n this.refresh()\n }\n\n if (scrollTop >= maxScroll) {\n const target = this._targets[this._targets.length - 1]\n\n if (this._activeTarget !== target) {\n this._activate(target)\n }\n return\n }\n\n if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n this._activeTarget = null\n this._clear()\n return\n }\n\n const offsetLength = this._offsets.length\n for (let i = offsetLength; i--;) {\n const isActiveTarget = this._activeTarget !== this._targets[i] &&\n scrollTop >= this._offsets[i] &&\n (typeof this._offsets[i + 1] === 'undefined' ||\n scrollTop < this._offsets[i + 1])\n\n if (isActiveTarget) {\n this._activate(this._targets[i])\n }\n }\n }\n\n _activate(target) {\n this._activeTarget = target\n\n this._clear()\n\n let queries = this._selector.split(',')\n // eslint-disable-next-line arrow-body-style\n queries = queries.map((selector) => {\n return `${selector}[data-target=\"${target}\"],` +\n `${selector}[href=\"${target}\"]`\n })\n\n const $link = $([].slice.call(document.querySelectorAll(queries.join(','))))\n\n if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {\n $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE)\n $link.addClass(ClassName.ACTIVE)\n } else {\n // Set triggered link as active\n $link.addClass(ClassName.ACTIVE)\n // Set triggered links parents as active\n // With both
',trigger:"hover focus",title:"",delay:0,html:!(Ie={AUTO:"auto",TOP:"top",RIGHT:"right",BOTTOM:"bottom",LEFT:"left"}),selector:!(Se={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(number|string)",container:"(string|element|boolean)",fallbackPlacement:"(string|array)",boundary:"(string|element)"}),placement:"top",offset:0,container:!1,fallbackPlacement:"flip",boundary:"scrollParent"},we="out",Ne={HIDE:"hide"+Ee,HIDDEN:"hidden"+Ee,SHOW:(De="show")+Ee,SHOWN:"shown"+Ee,INSERTED:"inserted"+Ee,CLICK:"click"+Ee,FOCUSIN:"focusin"+Ee,FOCUSOUT:"focusout"+Ee,MOUSEENTER:"mouseenter"+Ee,MOUSELEAVE:"mouseleave"+Ee},Oe="fade",ke="show",Pe=".tooltip-inner",je=".arrow",He="hover",Le="focus",Re="click",xe="manual",We=function(){function i(t,e){if("undefined"==typeof h)throw new TypeError("Bootstrap tooltips require Popper.js (https://popper.js.org)");this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this.element=t,this.config=this._getConfig(e),this.tip=null,this._setListeners()}var t=i.prototype;return t.enable=function(){this._isEnabled=!0},t.disable=function(){this._isEnabled=!1},t.toggleEnabled=function(){this._isEnabled=!this._isEnabled},t.toggle=function(t){if(this._isEnabled)if(t){var e=this.constructor.DATA_KEY,n=pe(t.currentTarget).data(e);n||(n=new this.constructor(t.currentTarget,this._getDelegateConfig()),pe(t.currentTarget).data(e,n)),n._activeTrigger.click=!n._activeTrigger.click,n._isWithActiveTrigger()?n._enter(null,n):n._leave(null,n)}else{if(pe(this.getTipElement()).hasClass(ke))return void this._leave(null,this);this._enter(null,this)}},t.dispose=function(){clearTimeout(this._timeout),pe.removeData(this.element,this.constructor.DATA_KEY),pe(this.element).off(this.constructor.EVENT_KEY),pe(this.element).closest(".modal").off("hide.bs.modal"),this.tip&&pe(this.tip).remove(),this._isEnabled=null,this._timeout=null,this._hoverState=null,(this._activeTrigger=null)!==this._popper&&this._popper.destroy(),this._popper=null,this.element=null,this.config=null,this.tip=null},t.show=function(){var e=this;if("none"===pe(this.element).css("display"))throw new Error("Please use show on visible elements");var t=pe.Event(this.constructor.Event.SHOW);if(this.isWithContent()&&this._isEnabled){pe(this.element).trigger(t);var n=pe.contains(this.element.ownerDocument.documentElement,this.element);if(t.isDefaultPrevented()||!n)return;var i=this.getTipElement(),r=Fn.getUID(this.constructor.NAME);i.setAttribute("id",r),this.element.setAttribute("aria-describedby",r),this.setContent(),this.config.animation&&pe(i).addClass(Oe);var o="function"==typeof this.config.placement?this.config.placement.call(this,i,this.element):this.config.placement,s=this._getAttachment(o);this.addAttachmentClass(s);var a=!1===this.config.container?document.body:pe(document).find(this.config.container);pe(i).data(this.constructor.DATA_KEY,this),pe.contains(this.element.ownerDocument.documentElement,this.tip)||pe(i).appendTo(a),pe(this.element).trigger(this.constructor.Event.INSERTED),this._popper=new h(this.element,i,{placement:s,modifiers:{offset:{offset:this.config.offset},flip:{behavior:this.config.fallbackPlacement},arrow:{element:je},preventOverflow:{boundariesElement:this.config.boundary}},onCreate:function(t){t.originalPlacement!==t.placement&&e._handlePopperPlacementChange(t)},onUpdate:function(t){e._handlePopperPlacementChange(t)}}),pe(i).addClass(ke),"ontouchstart"in document.documentElement&&pe(document.body).children().on("mouseover",null,pe.noop);var l=function(){e.config.animation&&e._fixTransition();var t=e._hoverState;e._hoverState=null,pe(e.element).trigger(e.constructor.Event.SHOWN),t===we&&e._leave(null,e)};if(pe(this.tip).hasClass(Oe)){var c=Fn.getTransitionDurationFromElement(this.tip);pe(this.tip).one(Fn.TRANSITION_END,l).emulateTransitionEnd(c)}else l()}},t.hide=function(t){var e=this,n=this.getTipElement(),i=pe.Event(this.constructor.Event.HIDE),r=function(){e._hoverState!==De&&n.parentNode&&n.parentNode.removeChild(n),e._cleanTipClass(),e.element.removeAttribute("aria-describedby"),pe(e.element).trigger(e.constructor.Event.HIDDEN),null!==e._popper&&e._popper.destroy(),t&&t()};if(pe(this.element).trigger(i),!i.isDefaultPrevented()){if(pe(n).removeClass(ke),"ontouchstart"in document.documentElement&&pe(document.body).children().off("mouseover",null,pe.noop),this._activeTrigger[Re]=!1,this._activeTrigger[Le]=!1,this._activeTrigger[He]=!1,pe(this.tip).hasClass(Oe)){var o=Fn.getTransitionDurationFromElement(n);pe(n).one(Fn.TRANSITION_END,r).emulateTransitionEnd(o)}else r();this._hoverState=""}},t.update=function(){null!==this._popper&&this._popper.scheduleUpdate()},t.isWithContent=function(){return Boolean(this.getTitle())},t.addAttachmentClass=function(t){pe(this.getTipElement()).addClass(Te+"-"+t)},t.getTipElement=function(){return this.tip=this.tip||pe(this.config.template)[0],this.tip},t.setContent=function(){var t=this.getTipElement();this.setElementContent(pe(t.querySelectorAll(Pe)),this.getTitle()),pe(t).removeClass(Oe+" "+ke)},t.setElementContent=function(t,e){var n=this.config.html;"object"==typeof e&&(e.nodeType||e.jquery)?n?pe(e).parent().is(t)||t.empty().append(e):t.text(pe(e).text()):t[n?"html":"text"](e)},t.getTitle=function(){var t=this.element.getAttribute("data-original-title");return t||(t="function"==typeof this.config.title?this.config.title.call(this.element):this.config.title),t},t._getAttachment=function(t){return Ie[t.toUpperCase()]},t._setListeners=function(){var i=this;this.config.trigger.split(" ").forEach(function(t){if("click"===t)pe(i.element).on(i.constructor.Event.CLICK,i.config.selector,function(t){return i.toggle(t)});else if(t!==xe){var e=t===He?i.constructor.Event.MOUSEENTER:i.constructor.Event.FOCUSIN,n=t===He?i.constructor.Event.MOUSELEAVE:i.constructor.Event.FOCUSOUT;pe(i.element).on(e,i.config.selector,function(t){return i._enter(t)}).on(n,i.config.selector,function(t){return i._leave(t)})}pe(i.element).closest(".modal").on("hide.bs.modal",function(){return i.hide()})}),this.config.selector?this.config=l({},this.config,{trigger:"manual",selector:""}):this._fixTitle()},t._fixTitle=function(){var t=typeof this.element.getAttribute("data-original-title");(this.element.getAttribute("title")||"string"!==t)&&(this.element.setAttribute("data-original-title",this.element.getAttribute("title")||""),this.element.setAttribute("title",""))},t._enter=function(t,e){var n=this.constructor.DATA_KEY;(e=e||pe(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),pe(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusin"===t.type?Le:He]=!0),pe(e.getTipElement()).hasClass(ke)||e._hoverState===De?e._hoverState=De:(clearTimeout(e._timeout),e._hoverState=De,e.config.delay&&e.config.delay.show?e._timeout=setTimeout(function(){e._hoverState===De&&e.show()},e.config.delay.show):e.show())},t._leave=function(t,e){var n=this.constructor.DATA_KEY;(e=e||pe(t.currentTarget).data(n))||(e=new this.constructor(t.currentTarget,this._getDelegateConfig()),pe(t.currentTarget).data(n,e)),t&&(e._activeTrigger["focusout"===t.type?Le:He]=!1),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=we,e.config.delay&&e.config.delay.hide?e._timeout=setTimeout(function(){e._hoverState===we&&e.hide()},e.config.delay.hide):e.hide())},t._isWithActiveTrigger=function(){for(var t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1},t._getConfig=function(t){return"number"==typeof(t=l({},this.constructor.Default,pe(this.element).data(),"object"==typeof t&&t?t:{})).delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),Fn.typeCheckConfig(ve,t,this.constructor.DefaultType),t},t._getDelegateConfig=function(){var t={};if(this.config)for(var e in this.config)this.constructor.Default[e]!==this.config[e]&&(t[e]=this.config[e]);return t},t._cleanTipClass=function(){var t=pe(this.getTipElement()),e=t.attr("class").match(be);null!==e&&e.length&&t.removeClass(e.join(""))},t._handlePopperPlacementChange=function(t){var e=t.instance;this.tip=e.popper,this._cleanTipClass(),this.addAttachmentClass(this._getAttachment(t.placement))},t._fixTransition=function(){var t=this.getTipElement(),e=this.config.animation;null===t.getAttribute("x-placement")&&(pe(t).removeClass(Oe),this.config.animation=!1,this.hide(),this.show(),this.config.animation=e)},i._jQueryInterface=function(n){return this.each(function(){var t=pe(this).data(ye),e="object"==typeof n&&n;if((t||!/dispose|hide/.test(n))&&(t||(t=new i(this,e),pe(this).data(ye,t)),"string"==typeof n)){if("undefined"==typeof t[n])throw new TypeError('No method named "'+n+'"');t[n]()}})},s(i,null,[{key:"VERSION",get:function(){return"4.1.3"}},{key:"Default",get:function(){return Ae}},{key:"NAME",get:function(){return ve}},{key:"DATA_KEY",get:function(){return ye}},{key:"Event",get:function(){return Ne}},{key:"EVENT_KEY",get:function(){return Ee}},{key:"DefaultType",get:function(){return Se}}]),i}(),pe.fn[ve]=We._jQueryInterface,pe.fn[ve].Constructor=We,pe.fn[ve].noConflict=function(){return pe.fn[ve]=Ce,We._jQueryInterface},We),Jn=(qe="popover",Ke="."+(Fe="bs.popover"),Me=(Ue=e).fn[qe],Qe="bs-popover",Be=new RegExp("(^|\\s)"+Qe+"\\S+","g"),Ve=l({},zn.Default,{placement:"right",trigger:"click",content:"",template:''}),Ye=l({},zn.DefaultType,{content:"(string|element|function)"}),ze="fade",Ze=".popover-header",Ge=".popover-body",$e={HIDE:"hide"+Ke,HIDDEN:"hidden"+Ke,SHOW:(Je="show")+Ke,SHOWN:"shown"+Ke,INSERTED:"inserted"+Ke,CLICK:"click"+Ke,FOCUSIN:"focusin"+Ke,FOCUSOUT:"focusout"+Ke,MOUSEENTER:"mouseenter"+Ke,MOUSELEAVE:"mouseleave"+Ke},Xe=function(t){var e,n;function i(){return t.apply(this,arguments)||this}n=t,(e=i).prototype=Object.create(n.prototype),(e.prototype.constructor=e).__proto__=n;var r=i.prototype;return r.isWithContent=function(){return this.getTitle()||this._getContent()},r.addAttachmentClass=function(t){Ue(this.getTipElement()).addClass(Qe+"-"+t)},r.getTipElement=function(){return this.tip=this.tip||Ue(this.config.template)[0],this.tip},r.setContent=function(){var t=Ue(this.getTipElement());this.setElementContent(t.find(Ze),this.getTitle());var e=this._getContent();"function"==typeof e&&(e=e.call(this.element)),this.setElementContent(t.find(Ge),e),t.removeClass(ze+" "+Je)},r._getContent=function(){return this.element.getAttribute("data-content")||this.config.content},r._cleanTipClass=function(){var t=Ue(this.getTipElement()),e=t.attr("class").match(Be);null!==e&&0=this._offsets[r]&&("undefined"==typeof this._offsets[r+1]||t {\n /**\n * ------------------------------------------------------------------------\n * Private TransitionEnd Helpers\n * ------------------------------------------------------------------------\n */\n\n const TRANSITION_END = 'transitionend'\n const MAX_UID = 1000000\n const MILLISECONDS_MULTIPLIER = 1000\n\n // Shoutout AngusCroll (https://goo.gl/pxwQGp)\n function toType(obj) {\n return {}.toString.call(obj).match(/\\s([a-z]+)/i)[1].toLowerCase()\n }\n\n function getSpecialTransitionEndEvent() {\n return {\n bindType: TRANSITION_END,\n delegateType: TRANSITION_END,\n handle(event) {\n if ($(event.target).is(this)) {\n return event.handleObj.handler.apply(this, arguments) // eslint-disable-line prefer-rest-params\n }\n return undefined // eslint-disable-line no-undefined\n }\n }\n }\n\n function transitionEndEmulator(duration) {\n let called = false\n\n $(this).one(Util.TRANSITION_END, () => {\n called = true\n })\n\n setTimeout(() => {\n if (!called) {\n Util.triggerTransitionEnd(this)\n }\n }, duration)\n\n return this\n }\n\n function setTransitionEndSupport() {\n $.fn.emulateTransitionEnd = transitionEndEmulator\n $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent()\n }\n\n /**\n * --------------------------------------------------------------------------\n * Public Util Api\n * --------------------------------------------------------------------------\n */\n\n const Util = {\n\n TRANSITION_END: 'bsTransitionEnd',\n\n getUID(prefix) {\n do {\n // eslint-disable-next-line no-bitwise\n prefix += ~~(Math.random() * MAX_UID) // \"~~\" acts like a faster Math.floor() here\n } while (document.getElementById(prefix))\n return prefix\n },\n\n getSelectorFromElement(element) {\n let selector = element.getAttribute('data-target')\n if (!selector || selector === '#') {\n selector = element.getAttribute('href') || ''\n }\n\n try {\n return document.querySelector(selector) ? selector : null\n } catch (err) {\n return null\n }\n },\n\n getTransitionDurationFromElement(element) {\n if (!element) {\n return 0\n }\n\n // Get transition-duration of the element\n let transitionDuration = $(element).css('transition-duration')\n const floatTransitionDuration = parseFloat(transitionDuration)\n\n // Return 0 if element or transition duration is not found\n if (!floatTransitionDuration) {\n return 0\n }\n\n // If multiple durations are defined, take the first\n transitionDuration = transitionDuration.split(',')[0]\n\n return parseFloat(transitionDuration) * MILLISECONDS_MULTIPLIER\n },\n\n reflow(element) {\n return element.offsetHeight\n },\n\n triggerTransitionEnd(element) {\n $(element).trigger(TRANSITION_END)\n },\n\n // TODO: Remove in v5\n supportsTransitionEnd() {\n return Boolean(TRANSITION_END)\n },\n\n isElement(obj) {\n return (obj[0] || obj).nodeType\n },\n\n typeCheckConfig(componentName, config, configTypes) {\n for (const property in configTypes) {\n if (Object.prototype.hasOwnProperty.call(configTypes, property)) {\n const expectedTypes = configTypes[property]\n const value = config[property]\n const valueType = value && Util.isElement(value)\n ? 'element' : toType(value)\n\n if (!new RegExp(expectedTypes).test(valueType)) {\n throw new Error(\n `${componentName.toUpperCase()}: ` +\n `Option \"${property}\" provided type \"${valueType}\" ` +\n `but expected type \"${expectedTypes}\".`)\n }\n }\n }\n }\n }\n\n setTransitionEndSupport()\n\n return Util\n})($)\n\nexport default Util\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): alert.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Alert = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'alert'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.alert'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Selector = {\n DISMISS : '[data-dismiss=\"alert\"]'\n }\n\n const Event = {\n CLOSE : `close${EVENT_KEY}`,\n CLOSED : `closed${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n ALERT : 'alert',\n FADE : 'fade',\n SHOW : 'show'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Alert {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n close(element) {\n let rootElement = this._element\n if (element) {\n rootElement = this._getRootElement(element)\n }\n\n const customEvent = this._triggerCloseEvent(rootElement)\n\n if (customEvent.isDefaultPrevented()) {\n return\n }\n\n this._removeElement(rootElement)\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Private\n\n _getRootElement(element) {\n const selector = Util.getSelectorFromElement(element)\n let parent = false\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n if (!parent) {\n parent = $(element).closest(`.${ClassName.ALERT}`)[0]\n }\n\n return parent\n }\n\n _triggerCloseEvent(element) {\n const closeEvent = $.Event(Event.CLOSE)\n\n $(element).trigger(closeEvent)\n return closeEvent\n }\n\n _removeElement(element) {\n $(element).removeClass(ClassName.SHOW)\n\n if (!$(element).hasClass(ClassName.FADE)) {\n this._destroyElement(element)\n return\n }\n\n const transitionDuration = Util.getTransitionDurationFromElement(element)\n\n $(element)\n .one(Util.TRANSITION_END, (event) => this._destroyElement(element, event))\n .emulateTransitionEnd(transitionDuration)\n }\n\n _destroyElement(element) {\n $(element)\n .detach()\n .trigger(Event.CLOSED)\n .remove()\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $element = $(this)\n let data = $element.data(DATA_KEY)\n\n if (!data) {\n data = new Alert(this)\n $element.data(DATA_KEY, data)\n }\n\n if (config === 'close') {\n data[config](this)\n }\n })\n }\n\n static _handleDismiss(alertInstance) {\n return function (event) {\n if (event) {\n event.preventDefault()\n }\n\n alertInstance.close(this)\n }\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(\n Event.CLICK_DATA_API,\n Selector.DISMISS,\n Alert._handleDismiss(new Alert())\n )\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Alert._jQueryInterface\n $.fn[NAME].Constructor = Alert\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Alert._jQueryInterface\n }\n\n return Alert\n})($)\n\nexport default Alert\n","import $ from 'jquery'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): button.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Button = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'button'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.button'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const ClassName = {\n ACTIVE : 'active',\n BUTTON : 'btn',\n FOCUS : 'focus'\n }\n\n const Selector = {\n DATA_TOGGLE_CARROT : '[data-toggle^=\"button\"]',\n DATA_TOGGLE : '[data-toggle=\"buttons\"]',\n INPUT : 'input',\n ACTIVE : '.active',\n BUTTON : '.btn'\n }\n\n const Event = {\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,\n FOCUS_BLUR_DATA_API : `focus${EVENT_KEY}${DATA_API_KEY} ` +\n `blur${EVENT_KEY}${DATA_API_KEY}`\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Button {\n constructor(element) {\n this._element = element\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n // Public\n\n toggle() {\n let triggerChangeEvent = true\n let addAriaPressed = true\n const rootElement = $(this._element).closest(\n Selector.DATA_TOGGLE\n )[0]\n\n if (rootElement) {\n const input = this._element.querySelector(Selector.INPUT)\n\n if (input) {\n if (input.type === 'radio') {\n if (input.checked &&\n this._element.classList.contains(ClassName.ACTIVE)) {\n triggerChangeEvent = false\n } else {\n const activeElement = rootElement.querySelector(Selector.ACTIVE)\n\n if (activeElement) {\n $(activeElement).removeClass(ClassName.ACTIVE)\n }\n }\n }\n\n if (triggerChangeEvent) {\n if (input.hasAttribute('disabled') ||\n rootElement.hasAttribute('disabled') ||\n input.classList.contains('disabled') ||\n rootElement.classList.contains('disabled')) {\n return\n }\n input.checked = !this._element.classList.contains(ClassName.ACTIVE)\n $(input).trigger('change')\n }\n\n input.focus()\n addAriaPressed = false\n }\n }\n\n if (addAriaPressed) {\n this._element.setAttribute('aria-pressed',\n !this._element.classList.contains(ClassName.ACTIVE))\n }\n\n if (triggerChangeEvent) {\n $(this._element).toggleClass(ClassName.ACTIVE)\n }\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n this._element = null\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n\n if (!data) {\n data = new Button(this)\n $(this).data(DATA_KEY, data)\n }\n\n if (config === 'toggle') {\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {\n event.preventDefault()\n\n let button = event.target\n\n if (!$(button).hasClass(ClassName.BUTTON)) {\n button = $(button).closest(Selector.BUTTON)\n }\n\n Button._jQueryInterface.call($(button), 'toggle')\n })\n .on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, (event) => {\n const button = $(event.target).closest(Selector.BUTTON)[0]\n $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type))\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Button._jQueryInterface\n $.fn[NAME].Constructor = Button\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Button._jQueryInterface\n }\n\n return Button\n})($)\n\nexport default Button\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): carousel.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Carousel = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'carousel'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.carousel'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ARROW_LEFT_KEYCODE = 37 // KeyboardEvent.which value for left arrow key\n const ARROW_RIGHT_KEYCODE = 39 // KeyboardEvent.which value for right arrow key\n const TOUCHEVENT_COMPAT_WAIT = 500 // Time for mouse compat events to fire after touch\n\n const Default = {\n interval : 5000,\n keyboard : true,\n slide : false,\n pause : 'hover',\n wrap : true\n }\n\n const DefaultType = {\n interval : '(number|boolean)',\n keyboard : 'boolean',\n slide : '(boolean|string)',\n pause : '(string|boolean)',\n wrap : 'boolean'\n }\n\n const Direction = {\n NEXT : 'next',\n PREV : 'prev',\n LEFT : 'left',\n RIGHT : 'right'\n }\n\n const Event = {\n SLIDE : `slide${EVENT_KEY}`,\n SLID : `slid${EVENT_KEY}`,\n KEYDOWN : `keydown${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`,\n TOUCHEND : `touchend${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n CAROUSEL : 'carousel',\n ACTIVE : 'active',\n SLIDE : 'slide',\n RIGHT : 'carousel-item-right',\n LEFT : 'carousel-item-left',\n NEXT : 'carousel-item-next',\n PREV : 'carousel-item-prev',\n ITEM : 'carousel-item'\n }\n\n const Selector = {\n ACTIVE : '.active',\n ACTIVE_ITEM : '.active.carousel-item',\n ITEM : '.carousel-item',\n NEXT_PREV : '.carousel-item-next, .carousel-item-prev',\n INDICATORS : '.carousel-indicators',\n DATA_SLIDE : '[data-slide], [data-slide-to]',\n DATA_RIDE : '[data-ride=\"carousel\"]'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Carousel {\n constructor(element, config) {\n this._items = null\n this._interval = null\n this._activeElement = null\n\n this._isPaused = false\n this._isSliding = false\n\n this.touchTimeout = null\n\n this._config = this._getConfig(config)\n this._element = $(element)[0]\n this._indicatorsElement = this._element.querySelector(Selector.INDICATORS)\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n next() {\n if (!this._isSliding) {\n this._slide(Direction.NEXT)\n }\n }\n\n nextWhenVisible() {\n // Don't call next when the page isn't visible\n // or the carousel or its parent isn't visible\n if (!document.hidden &&\n ($(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden')) {\n this.next()\n }\n }\n\n prev() {\n if (!this._isSliding) {\n this._slide(Direction.PREV)\n }\n }\n\n pause(event) {\n if (!event) {\n this._isPaused = true\n }\n\n if (this._element.querySelector(Selector.NEXT_PREV)) {\n Util.triggerTransitionEnd(this._element)\n this.cycle(true)\n }\n\n clearInterval(this._interval)\n this._interval = null\n }\n\n cycle(event) {\n if (!event) {\n this._isPaused = false\n }\n\n if (this._interval) {\n clearInterval(this._interval)\n this._interval = null\n }\n\n if (this._config.interval && !this._isPaused) {\n this._interval = setInterval(\n (document.visibilityState ? this.nextWhenVisible : this.next).bind(this),\n this._config.interval\n )\n }\n }\n\n to(index) {\n this._activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n\n const activeIndex = this._getItemIndex(this._activeElement)\n\n if (index > this._items.length - 1 || index < 0) {\n return\n }\n\n if (this._isSliding) {\n $(this._element).one(Event.SLID, () => this.to(index))\n return\n }\n\n if (activeIndex === index) {\n this.pause()\n this.cycle()\n return\n }\n\n const direction = index > activeIndex\n ? Direction.NEXT\n : Direction.PREV\n\n this._slide(direction, this._items[index])\n }\n\n dispose() {\n $(this._element).off(EVENT_KEY)\n $.removeData(this._element, DATA_KEY)\n\n this._items = null\n this._config = null\n this._element = null\n this._interval = null\n this._isPaused = null\n this._isSliding = null\n this._activeElement = null\n this._indicatorsElement = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _addEventListeners() {\n if (this._config.keyboard) {\n $(this._element)\n .on(Event.KEYDOWN, (event) => this._keydown(event))\n }\n\n if (this._config.pause === 'hover') {\n $(this._element)\n .on(Event.MOUSEENTER, (event) => this.pause(event))\n .on(Event.MOUSELEAVE, (event) => this.cycle(event))\n if ('ontouchstart' in document.documentElement) {\n // If it's a touch-enabled device, mouseenter/leave are fired as\n // part of the mouse compatibility events on first tap - the carousel\n // would stop cycling until user tapped out of it;\n // here, we listen for touchend, explicitly pause the carousel\n // (as if it's the second time we tap on it, mouseenter compat event\n // is NOT fired) and after a timeout (to allow for mouse compatibility\n // events to fire) we explicitly restart cycling\n $(this._element).on(Event.TOUCHEND, () => {\n this.pause()\n if (this.touchTimeout) {\n clearTimeout(this.touchTimeout)\n }\n this.touchTimeout = setTimeout((event) => this.cycle(event), TOUCHEVENT_COMPAT_WAIT + this._config.interval)\n })\n }\n }\n }\n\n _keydown(event) {\n if (/input|textarea/i.test(event.target.tagName)) {\n return\n }\n\n switch (event.which) {\n case ARROW_LEFT_KEYCODE:\n event.preventDefault()\n this.prev()\n break\n case ARROW_RIGHT_KEYCODE:\n event.preventDefault()\n this.next()\n break\n default:\n }\n }\n\n _getItemIndex(element) {\n this._items = element && element.parentNode\n ? [].slice.call(element.parentNode.querySelectorAll(Selector.ITEM))\n : []\n return this._items.indexOf(element)\n }\n\n _getItemByDirection(direction, activeElement) {\n const isNextDirection = direction === Direction.NEXT\n const isPrevDirection = direction === Direction.PREV\n const activeIndex = this._getItemIndex(activeElement)\n const lastItemIndex = this._items.length - 1\n const isGoingToWrap = isPrevDirection && activeIndex === 0 ||\n isNextDirection && activeIndex === lastItemIndex\n\n if (isGoingToWrap && !this._config.wrap) {\n return activeElement\n }\n\n const delta = direction === Direction.PREV ? -1 : 1\n const itemIndex = (activeIndex + delta) % this._items.length\n\n return itemIndex === -1\n ? this._items[this._items.length - 1] : this._items[itemIndex]\n }\n\n _triggerSlideEvent(relatedTarget, eventDirectionName) {\n const targetIndex = this._getItemIndex(relatedTarget)\n const fromIndex = this._getItemIndex(this._element.querySelector(Selector.ACTIVE_ITEM))\n const slideEvent = $.Event(Event.SLIDE, {\n relatedTarget,\n direction: eventDirectionName,\n from: fromIndex,\n to: targetIndex\n })\n\n $(this._element).trigger(slideEvent)\n\n return slideEvent\n }\n\n _setActiveIndicatorElement(element) {\n if (this._indicatorsElement) {\n const indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector.ACTIVE))\n $(indicators)\n .removeClass(ClassName.ACTIVE)\n\n const nextIndicator = this._indicatorsElement.children[\n this._getItemIndex(element)\n ]\n\n if (nextIndicator) {\n $(nextIndicator).addClass(ClassName.ACTIVE)\n }\n }\n }\n\n _slide(direction, element) {\n const activeElement = this._element.querySelector(Selector.ACTIVE_ITEM)\n const activeElementIndex = this._getItemIndex(activeElement)\n const nextElement = element || activeElement &&\n this._getItemByDirection(direction, activeElement)\n const nextElementIndex = this._getItemIndex(nextElement)\n const isCycling = Boolean(this._interval)\n\n let directionalClassName\n let orderClassName\n let eventDirectionName\n\n if (direction === Direction.NEXT) {\n directionalClassName = ClassName.LEFT\n orderClassName = ClassName.NEXT\n eventDirectionName = Direction.LEFT\n } else {\n directionalClassName = ClassName.RIGHT\n orderClassName = ClassName.PREV\n eventDirectionName = Direction.RIGHT\n }\n\n if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {\n this._isSliding = false\n return\n }\n\n const slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName)\n if (slideEvent.isDefaultPrevented()) {\n return\n }\n\n if (!activeElement || !nextElement) {\n // Some weirdness is happening, so we bail\n return\n }\n\n this._isSliding = true\n\n if (isCycling) {\n this.pause()\n }\n\n this._setActiveIndicatorElement(nextElement)\n\n const slidEvent = $.Event(Event.SLID, {\n relatedTarget: nextElement,\n direction: eventDirectionName,\n from: activeElementIndex,\n to: nextElementIndex\n })\n\n if ($(this._element).hasClass(ClassName.SLIDE)) {\n $(nextElement).addClass(orderClassName)\n\n Util.reflow(nextElement)\n\n $(activeElement).addClass(directionalClassName)\n $(nextElement).addClass(directionalClassName)\n\n const transitionDuration = Util.getTransitionDurationFromElement(activeElement)\n\n $(activeElement)\n .one(Util.TRANSITION_END, () => {\n $(nextElement)\n .removeClass(`${directionalClassName} ${orderClassName}`)\n .addClass(ClassName.ACTIVE)\n\n $(activeElement).removeClass(`${ClassName.ACTIVE} ${orderClassName} ${directionalClassName}`)\n\n this._isSliding = false\n\n setTimeout(() => $(this._element).trigger(slidEvent), 0)\n })\n .emulateTransitionEnd(transitionDuration)\n } else {\n $(activeElement).removeClass(ClassName.ACTIVE)\n $(nextElement).addClass(ClassName.ACTIVE)\n\n this._isSliding = false\n $(this._element).trigger(slidEvent)\n }\n\n if (isCycling) {\n this.cycle()\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n let _config = {\n ...Default,\n ...$(this).data()\n }\n\n if (typeof config === 'object') {\n _config = {\n ..._config,\n ...config\n }\n }\n\n const action = typeof config === 'string' ? config : _config.slide\n\n if (!data) {\n data = new Carousel(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'number') {\n data.to(config)\n } else if (typeof action === 'string') {\n if (typeof data[action] === 'undefined') {\n throw new TypeError(`No method named \"${action}\"`)\n }\n data[action]()\n } else if (_config.interval) {\n data.pause()\n data.cycle()\n }\n })\n }\n\n static _dataApiClickHandler(event) {\n const selector = Util.getSelectorFromElement(this)\n\n if (!selector) {\n return\n }\n\n const target = $(selector)[0]\n\n if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {\n return\n }\n\n const config = {\n ...$(target).data(),\n ...$(this).data()\n }\n const slideIndex = this.getAttribute('data-slide-to')\n\n if (slideIndex) {\n config.interval = false\n }\n\n Carousel._jQueryInterface.call($(target), config)\n\n if (slideIndex) {\n $(target).data(DATA_KEY).to(slideIndex)\n }\n\n event.preventDefault()\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler)\n\n $(window).on(Event.LOAD_DATA_API, () => {\n const carousels = [].slice.call(document.querySelectorAll(Selector.DATA_RIDE))\n for (let i = 0, len = carousels.length; i < len; i++) {\n const $carousel = $(carousels[i])\n Carousel._jQueryInterface.call($carousel, $carousel.data())\n }\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Carousel._jQueryInterface\n $.fn[NAME].Constructor = Carousel\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Carousel._jQueryInterface\n }\n\n return Carousel\n})($)\n\nexport default Carousel\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): collapse.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Collapse = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'collapse'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.collapse'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Default = {\n toggle : true,\n parent : ''\n }\n\n const DefaultType = {\n toggle : 'boolean',\n parent : '(string|element)'\n }\n\n const Event = {\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n SHOW : 'show',\n COLLAPSE : 'collapse',\n COLLAPSING : 'collapsing',\n COLLAPSED : 'collapsed'\n }\n\n const Dimension = {\n WIDTH : 'width',\n HEIGHT : 'height'\n }\n\n const Selector = {\n ACTIVES : '.show, .collapsing',\n DATA_TOGGLE : '[data-toggle=\"collapse\"]'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Collapse {\n constructor(element, config) {\n this._isTransitioning = false\n this._element = element\n this._config = this._getConfig(config)\n this._triggerArray = $.makeArray(document.querySelectorAll(\n `[data-toggle=\"collapse\"][href=\"#${element.id}\"],` +\n `[data-toggle=\"collapse\"][data-target=\"#${element.id}\"]`\n ))\n const toggleList = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n for (let i = 0, len = toggleList.length; i < len; i++) {\n const elem = toggleList[i]\n const selector = Util.getSelectorFromElement(elem)\n const filterElement = [].slice.call(document.querySelectorAll(selector))\n .filter((foundElem) => foundElem === element)\n\n if (selector !== null && filterElement.length > 0) {\n this._selector = selector\n this._triggerArray.push(elem)\n }\n }\n\n this._parent = this._config.parent ? this._getParent() : null\n\n if (!this._config.parent) {\n this._addAriaAndCollapsedClass(this._element, this._triggerArray)\n }\n\n if (this._config.toggle) {\n this.toggle()\n }\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle() {\n if ($(this._element).hasClass(ClassName.SHOW)) {\n this.hide()\n } else {\n this.show()\n }\n }\n\n show() {\n if (this._isTransitioning ||\n $(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n let actives\n let activesData\n\n if (this._parent) {\n actives = [].slice.call(this._parent.querySelectorAll(Selector.ACTIVES))\n .filter((elem) => elem.getAttribute('data-parent') === this._config.parent)\n\n if (actives.length === 0) {\n actives = null\n }\n }\n\n if (actives) {\n activesData = $(actives).not(this._selector).data(DATA_KEY)\n if (activesData && activesData._isTransitioning) {\n return\n }\n }\n\n const startEvent = $.Event(Event.SHOW)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n if (actives) {\n Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide')\n if (!activesData) {\n $(actives).data(DATA_KEY, null)\n }\n }\n\n const dimension = this._getDimension()\n\n $(this._element)\n .removeClass(ClassName.COLLAPSE)\n .addClass(ClassName.COLLAPSING)\n\n this._element.style[dimension] = 0\n\n if (this._triggerArray.length) {\n $(this._triggerArray)\n .removeClass(ClassName.COLLAPSED)\n .attr('aria-expanded', true)\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .addClass(ClassName.SHOW)\n\n this._element.style[dimension] = ''\n\n this.setTransitioning(false)\n\n $(this._element).trigger(Event.SHOWN)\n }\n\n const capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1)\n const scrollSize = `scroll${capitalizedDimension}`\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n\n this._element.style[dimension] = `${this._element[scrollSize]}px`\n }\n\n hide() {\n if (this._isTransitioning ||\n !$(this._element).hasClass(ClassName.SHOW)) {\n return\n }\n\n const startEvent = $.Event(Event.HIDE)\n $(this._element).trigger(startEvent)\n if (startEvent.isDefaultPrevented()) {\n return\n }\n\n const dimension = this._getDimension()\n\n this._element.style[dimension] = `${this._element.getBoundingClientRect()[dimension]}px`\n\n Util.reflow(this._element)\n\n $(this._element)\n .addClass(ClassName.COLLAPSING)\n .removeClass(ClassName.COLLAPSE)\n .removeClass(ClassName.SHOW)\n\n const triggerArrayLength = this._triggerArray.length\n if (triggerArrayLength > 0) {\n for (let i = 0; i < triggerArrayLength; i++) {\n const trigger = this._triggerArray[i]\n const selector = Util.getSelectorFromElement(trigger)\n if (selector !== null) {\n const $elem = $([].slice.call(document.querySelectorAll(selector)))\n if (!$elem.hasClass(ClassName.SHOW)) {\n $(trigger).addClass(ClassName.COLLAPSED)\n .attr('aria-expanded', false)\n }\n }\n }\n }\n\n this.setTransitioning(true)\n\n const complete = () => {\n this.setTransitioning(false)\n $(this._element)\n .removeClass(ClassName.COLLAPSING)\n .addClass(ClassName.COLLAPSE)\n .trigger(Event.HIDDEN)\n }\n\n this._element.style[dimension] = ''\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n }\n\n setTransitioning(isTransitioning) {\n this._isTransitioning = isTransitioning\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n this._config = null\n this._parent = null\n this._element = null\n this._triggerArray = null\n this._isTransitioning = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n config.toggle = Boolean(config.toggle) // Coerce string values\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _getDimension() {\n const hasWidth = $(this._element).hasClass(Dimension.WIDTH)\n return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT\n }\n\n _getParent() {\n let parent = null\n if (Util.isElement(this._config.parent)) {\n parent = this._config.parent\n\n // It's a jQuery object\n if (typeof this._config.parent.jquery !== 'undefined') {\n parent = this._config.parent[0]\n }\n } else {\n parent = document.querySelector(this._config.parent)\n }\n\n const selector =\n `[data-toggle=\"collapse\"][data-parent=\"${this._config.parent}\"]`\n\n const children = [].slice.call(parent.querySelectorAll(selector))\n $(children).each((i, element) => {\n this._addAriaAndCollapsedClass(\n Collapse._getTargetFromElement(element),\n [element]\n )\n })\n\n return parent\n }\n\n _addAriaAndCollapsedClass(element, triggerArray) {\n if (element) {\n const isOpen = $(element).hasClass(ClassName.SHOW)\n\n if (triggerArray.length) {\n $(triggerArray)\n .toggleClass(ClassName.COLLAPSED, !isOpen)\n .attr('aria-expanded', isOpen)\n }\n }\n }\n\n // Static\n\n static _getTargetFromElement(element) {\n const selector = Util.getSelectorFromElement(element)\n return selector ? document.querySelector(selector) : null\n }\n\n static _jQueryInterface(config) {\n return this.each(function () {\n const $this = $(this)\n let data = $this.data(DATA_KEY)\n const _config = {\n ...Default,\n ...$this.data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data && _config.toggle && /show|hide/.test(config)) {\n _config.toggle = false\n }\n\n if (!data) {\n data = new Collapse(this, _config)\n $this.data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n // preventDefault only for elements (which change the URL) not inside the collapsible element\n if (event.currentTarget.tagName === 'A') {\n event.preventDefault()\n }\n\n const $trigger = $(this)\n const selector = Util.getSelectorFromElement(this)\n const selectors = [].slice.call(document.querySelectorAll(selector))\n $(selectors).each(function () {\n const $target = $(this)\n const data = $target.data(DATA_KEY)\n const config = data ? 'toggle' : $trigger.data()\n Collapse._jQueryInterface.call($target, config)\n })\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Collapse._jQueryInterface\n $.fn[NAME].Constructor = Collapse\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Collapse._jQueryInterface\n }\n\n return Collapse\n})($)\n\nexport default Collapse\n","import $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): dropdown.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Dropdown = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'dropdown'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.dropdown'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n const SPACE_KEYCODE = 32 // KeyboardEvent.which value for space key\n const TAB_KEYCODE = 9 // KeyboardEvent.which value for tab key\n const ARROW_UP_KEYCODE = 38 // KeyboardEvent.which value for up arrow key\n const ARROW_DOWN_KEYCODE = 40 // KeyboardEvent.which value for down arrow key\n const RIGHT_MOUSE_BUTTON_WHICH = 3 // MouseEvent.which value for the right button (assuming a right-handed mouse)\n const REGEXP_KEYDOWN = new RegExp(`${ARROW_UP_KEYCODE}|${ARROW_DOWN_KEYCODE}|${ESCAPE_KEYCODE}`)\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`,\n KEYDOWN_DATA_API : `keydown${EVENT_KEY}${DATA_API_KEY}`,\n KEYUP_DATA_API : `keyup${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n DISABLED : 'disabled',\n SHOW : 'show',\n DROPUP : 'dropup',\n DROPRIGHT : 'dropright',\n DROPLEFT : 'dropleft',\n MENURIGHT : 'dropdown-menu-right',\n MENULEFT : 'dropdown-menu-left',\n POSITION_STATIC : 'position-static'\n }\n\n const Selector = {\n DATA_TOGGLE : '[data-toggle=\"dropdown\"]',\n FORM_CHILD : '.dropdown form',\n MENU : '.dropdown-menu',\n NAVBAR_NAV : '.navbar-nav',\n VISIBLE_ITEMS : '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)'\n }\n\n const AttachmentMap = {\n TOP : 'top-start',\n TOPEND : 'top-end',\n BOTTOM : 'bottom-start',\n BOTTOMEND : 'bottom-end',\n RIGHT : 'right-start',\n RIGHTEND : 'right-end',\n LEFT : 'left-start',\n LEFTEND : 'left-end'\n }\n\n const Default = {\n offset : 0,\n flip : true,\n boundary : 'scrollParent',\n reference : 'toggle',\n display : 'dynamic'\n }\n\n const DefaultType = {\n offset : '(number|string|function)',\n flip : 'boolean',\n boundary : '(string|element)',\n reference : '(string|element)',\n display : 'string'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Dropdown {\n constructor(element, config) {\n this._element = element\n this._popper = null\n this._config = this._getConfig(config)\n this._menu = this._getMenuElement()\n this._inNavbar = this._detectNavbar()\n\n this._addEventListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n toggle() {\n if (this._element.disabled || $(this._element).hasClass(ClassName.DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this._element)\n const isActive = $(this._menu).hasClass(ClassName.SHOW)\n\n Dropdown._clearMenus()\n\n if (isActive) {\n return\n }\n\n const relatedTarget = {\n relatedTarget: this._element\n }\n const showEvent = $.Event(Event.SHOW, relatedTarget)\n\n $(parent).trigger(showEvent)\n\n if (showEvent.isDefaultPrevented()) {\n return\n }\n\n // Disable totally Popper.js for Dropdown in Navbar\n if (!this._inNavbar) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap dropdown require Popper.js (https://popper.js.org)')\n }\n\n let referenceElement = this._element\n\n if (this._config.reference === 'parent') {\n referenceElement = parent\n } else if (Util.isElement(this._config.reference)) {\n referenceElement = this._config.reference\n\n // Check if it's jQuery element\n if (typeof this._config.reference.jquery !== 'undefined') {\n referenceElement = this._config.reference[0]\n }\n }\n\n // If boundary is not `scrollParent`, then set position to `static`\n // to allow the menu to \"escape\" the scroll parent's boundaries\n // https://github.com/twbs/bootstrap/issues/24251\n if (this._config.boundary !== 'scrollParent') {\n $(parent).addClass(ClassName.POSITION_STATIC)\n }\n this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig())\n }\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement &&\n $(parent).closest(Selector.NAVBAR_NAV).length === 0) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n this._element.focus()\n this._element.setAttribute('aria-expanded', true)\n\n $(this._menu).toggleClass(ClassName.SHOW)\n $(parent)\n .toggleClass(ClassName.SHOW)\n .trigger($.Event(Event.SHOWN, relatedTarget))\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._element).off(EVENT_KEY)\n this._element = null\n this._menu = null\n if (this._popper !== null) {\n this._popper.destroy()\n this._popper = null\n }\n }\n\n update() {\n this._inNavbar = this._detectNavbar()\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Private\n\n _addEventListeners() {\n $(this._element).on(Event.CLICK, (event) => {\n event.preventDefault()\n event.stopPropagation()\n this.toggle()\n })\n }\n\n _getConfig(config) {\n config = {\n ...this.constructor.Default,\n ...$(this._element).data(),\n ...config\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n return config\n }\n\n _getMenuElement() {\n if (!this._menu) {\n const parent = Dropdown._getParentFromElement(this._element)\n if (parent) {\n this._menu = parent.querySelector(Selector.MENU)\n }\n }\n return this._menu\n }\n\n _getPlacement() {\n const $parentDropdown = $(this._element.parentNode)\n let placement = AttachmentMap.BOTTOM\n\n // Handle dropup\n if ($parentDropdown.hasClass(ClassName.DROPUP)) {\n placement = AttachmentMap.TOP\n if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n placement = AttachmentMap.TOPEND\n }\n } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {\n placement = AttachmentMap.RIGHT\n } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {\n placement = AttachmentMap.LEFT\n } else if ($(this._menu).hasClass(ClassName.MENURIGHT)) {\n placement = AttachmentMap.BOTTOMEND\n }\n return placement\n }\n\n _detectNavbar() {\n return $(this._element).closest('.navbar').length > 0\n }\n\n _getPopperConfig() {\n const offsetConf = {}\n if (typeof this._config.offset === 'function') {\n offsetConf.fn = (data) => {\n data.offsets = {\n ...data.offsets,\n ...this._config.offset(data.offsets) || {}\n }\n return data\n }\n } else {\n offsetConf.offset = this._config.offset\n }\n\n const popperConfig = {\n placement: this._getPlacement(),\n modifiers: {\n offset: offsetConf,\n flip: {\n enabled: this._config.flip\n },\n preventOverflow: {\n boundariesElement: this._config.boundary\n }\n }\n }\n\n // Disable Popper.js if we have a static display\n if (this._config.display === 'static') {\n popperConfig.modifiers.applyStyle = {\n enabled: false\n }\n }\n return popperConfig\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data) {\n data = new Dropdown(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n\n static _clearMenus(event) {\n if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH ||\n event.type === 'keyup' && event.which !== TAB_KEYCODE)) {\n return\n }\n\n const toggles = [].slice.call(document.querySelectorAll(Selector.DATA_TOGGLE))\n for (let i = 0, len = toggles.length; i < len; i++) {\n const parent = Dropdown._getParentFromElement(toggles[i])\n const context = $(toggles[i]).data(DATA_KEY)\n const relatedTarget = {\n relatedTarget: toggles[i]\n }\n\n if (event && event.type === 'click') {\n relatedTarget.clickEvent = event\n }\n\n if (!context) {\n continue\n }\n\n const dropdownMenu = context._menu\n if (!$(parent).hasClass(ClassName.SHOW)) {\n continue\n }\n\n if (event && (event.type === 'click' &&\n /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) &&\n $.contains(parent, event.target)) {\n continue\n }\n\n const hideEvent = $.Event(Event.HIDE, relatedTarget)\n $(parent).trigger(hideEvent)\n if (hideEvent.isDefaultPrevented()) {\n continue\n }\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n toggles[i].setAttribute('aria-expanded', 'false')\n\n $(dropdownMenu).removeClass(ClassName.SHOW)\n $(parent)\n .removeClass(ClassName.SHOW)\n .trigger($.Event(Event.HIDDEN, relatedTarget))\n }\n }\n\n static _getParentFromElement(element) {\n let parent\n const selector = Util.getSelectorFromElement(element)\n\n if (selector) {\n parent = document.querySelector(selector)\n }\n\n return parent || element.parentNode\n }\n\n // eslint-disable-next-line complexity\n static _dataApiKeydownHandler(event) {\n // If not input/textarea:\n // - And not a key in REGEXP_KEYDOWN => not a dropdown command\n // If input/textarea:\n // - If space key => not a dropdown command\n // - If key is other than escape\n // - If key is not up or down => not a dropdown command\n // - If trigger inside the menu => not a dropdown command\n if (/input|textarea/i.test(event.target.tagName)\n ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE &&\n (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE ||\n $(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {\n return\n }\n\n event.preventDefault()\n event.stopPropagation()\n\n if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {\n return\n }\n\n const parent = Dropdown._getParentFromElement(this)\n const isActive = $(parent).hasClass(ClassName.SHOW)\n\n if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) ||\n isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {\n if (event.which === ESCAPE_KEYCODE) {\n const toggle = parent.querySelector(Selector.DATA_TOGGLE)\n $(toggle).trigger('focus')\n }\n\n $(this).trigger('click')\n return\n }\n\n const items = [].slice.call(parent.querySelectorAll(Selector.VISIBLE_ITEMS))\n\n if (items.length === 0) {\n return\n }\n\n let index = items.indexOf(event.target)\n\n if (event.which === ARROW_UP_KEYCODE && index > 0) { // Up\n index--\n }\n\n if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { // Down\n index++\n }\n\n if (index < 0) {\n index = 0\n }\n\n items[index].focus()\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document)\n .on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler)\n .on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler)\n .on(`${Event.CLICK_DATA_API} ${Event.KEYUP_DATA_API}`, Dropdown._clearMenus)\n .on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n event.preventDefault()\n event.stopPropagation()\n Dropdown._jQueryInterface.call($(this), 'toggle')\n })\n .on(Event.CLICK_DATA_API, Selector.FORM_CHILD, (e) => {\n e.stopPropagation()\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Dropdown._jQueryInterface\n $.fn[NAME].Constructor = Dropdown\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Dropdown._jQueryInterface\n }\n\n return Dropdown\n})($, Popper)\n\nexport default Dropdown\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): modal.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Modal = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'modal'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.modal'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const ESCAPE_KEYCODE = 27 // KeyboardEvent.which value for Escape (Esc) key\n\n const Default = {\n backdrop : true,\n keyboard : true,\n focus : true,\n show : true\n }\n\n const DefaultType = {\n backdrop : '(boolean|string)',\n keyboard : 'boolean',\n focus : 'boolean',\n show : 'boolean'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n RESIZE : `resize${EVENT_KEY}`,\n CLICK_DISMISS : `click.dismiss${EVENT_KEY}`,\n KEYDOWN_DISMISS : `keydown.dismiss${EVENT_KEY}`,\n MOUSEUP_DISMISS : `mouseup.dismiss${EVENT_KEY}`,\n MOUSEDOWN_DISMISS : `mousedown.dismiss${EVENT_KEY}`,\n CLICK_DATA_API : `click${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n SCROLLBAR_MEASURER : 'modal-scrollbar-measure',\n BACKDROP : 'modal-backdrop',\n OPEN : 'modal-open',\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n DIALOG : '.modal-dialog',\n DATA_TOGGLE : '[data-toggle=\"modal\"]',\n DATA_DISMISS : '[data-dismiss=\"modal\"]',\n FIXED_CONTENT : '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',\n STICKY_CONTENT : '.sticky-top'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Modal {\n constructor(element, config) {\n this._config = this._getConfig(config)\n this._element = element\n this._dialog = element.querySelector(Selector.DIALOG)\n this._backdrop = null\n this._isShown = false\n this._isBodyOverflowing = false\n this._ignoreBackdropClick = false\n this._scrollbarWidth = 0\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n toggle(relatedTarget) {\n return this._isShown ? this.hide() : this.show(relatedTarget)\n }\n\n show(relatedTarget) {\n if (this._isTransitioning || this._isShown) {\n return\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n this._isTransitioning = true\n }\n\n const showEvent = $.Event(Event.SHOW, {\n relatedTarget\n })\n\n $(this._element).trigger(showEvent)\n\n if (this._isShown || showEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = true\n\n this._checkScrollbar()\n this._setScrollbar()\n\n this._adjustDialog()\n\n $(document.body).addClass(ClassName.OPEN)\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(this._element).on(\n Event.CLICK_DISMISS,\n Selector.DATA_DISMISS,\n (event) => this.hide(event)\n )\n\n $(this._dialog).on(Event.MOUSEDOWN_DISMISS, () => {\n $(this._element).one(Event.MOUSEUP_DISMISS, (event) => {\n if ($(event.target).is(this._element)) {\n this._ignoreBackdropClick = true\n }\n })\n })\n\n this._showBackdrop(() => this._showElement(relatedTarget))\n }\n\n hide(event) {\n if (event) {\n event.preventDefault()\n }\n\n if (this._isTransitioning || !this._isShown) {\n return\n }\n\n const hideEvent = $.Event(Event.HIDE)\n\n $(this._element).trigger(hideEvent)\n\n if (!this._isShown || hideEvent.isDefaultPrevented()) {\n return\n }\n\n this._isShown = false\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (transition) {\n this._isTransitioning = true\n }\n\n this._setEscapeEvent()\n this._setResizeEvent()\n\n $(document).off(Event.FOCUSIN)\n\n $(this._element).removeClass(ClassName.SHOW)\n\n $(this._element).off(Event.CLICK_DISMISS)\n $(this._dialog).off(Event.MOUSEDOWN_DISMISS)\n\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._element)\n .one(Util.TRANSITION_END, (event) => this._hideModal(event))\n .emulateTransitionEnd(transitionDuration)\n } else {\n this._hideModal()\n }\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n\n $(window, document, this._element, this._backdrop).off(EVENT_KEY)\n\n this._config = null\n this._element = null\n this._dialog = null\n this._backdrop = null\n this._isShown = null\n this._isBodyOverflowing = null\n this._ignoreBackdropClick = null\n this._scrollbarWidth = null\n }\n\n handleUpdate() {\n this._adjustDialog()\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...config\n }\n Util.typeCheckConfig(NAME, config, DefaultType)\n return config\n }\n\n _showElement(relatedTarget) {\n const transition = $(this._element).hasClass(ClassName.FADE)\n\n if (!this._element.parentNode ||\n this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {\n // Don't move modal's DOM position\n document.body.appendChild(this._element)\n }\n\n this._element.style.display = 'block'\n this._element.removeAttribute('aria-hidden')\n this._element.scrollTop = 0\n\n if (transition) {\n Util.reflow(this._element)\n }\n\n $(this._element).addClass(ClassName.SHOW)\n\n if (this._config.focus) {\n this._enforceFocus()\n }\n\n const shownEvent = $.Event(Event.SHOWN, {\n relatedTarget\n })\n\n const transitionComplete = () => {\n if (this._config.focus) {\n this._element.focus()\n }\n this._isTransitioning = false\n $(this._element).trigger(shownEvent)\n }\n\n if (transition) {\n const transitionDuration = Util.getTransitionDurationFromElement(this._element)\n\n $(this._dialog)\n .one(Util.TRANSITION_END, transitionComplete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n transitionComplete()\n }\n }\n\n _enforceFocus() {\n $(document)\n .off(Event.FOCUSIN) // Guard against infinite focus loop\n .on(Event.FOCUSIN, (event) => {\n if (document !== event.target &&\n this._element !== event.target &&\n $(this._element).has(event.target).length === 0) {\n this._element.focus()\n }\n })\n }\n\n _setEscapeEvent() {\n if (this._isShown && this._config.keyboard) {\n $(this._element).on(Event.KEYDOWN_DISMISS, (event) => {\n if (event.which === ESCAPE_KEYCODE) {\n event.preventDefault()\n this.hide()\n }\n })\n } else if (!this._isShown) {\n $(this._element).off(Event.KEYDOWN_DISMISS)\n }\n }\n\n _setResizeEvent() {\n if (this._isShown) {\n $(window).on(Event.RESIZE, (event) => this.handleUpdate(event))\n } else {\n $(window).off(Event.RESIZE)\n }\n }\n\n _hideModal() {\n this._element.style.display = 'none'\n this._element.setAttribute('aria-hidden', true)\n this._isTransitioning = false\n this._showBackdrop(() => {\n $(document.body).removeClass(ClassName.OPEN)\n this._resetAdjustments()\n this._resetScrollbar()\n $(this._element).trigger(Event.HIDDEN)\n })\n }\n\n _removeBackdrop() {\n if (this._backdrop) {\n $(this._backdrop).remove()\n this._backdrop = null\n }\n }\n\n _showBackdrop(callback) {\n const animate = $(this._element).hasClass(ClassName.FADE)\n ? ClassName.FADE : ''\n\n if (this._isShown && this._config.backdrop) {\n this._backdrop = document.createElement('div')\n this._backdrop.className = ClassName.BACKDROP\n\n if (animate) {\n this._backdrop.classList.add(animate)\n }\n\n $(this._backdrop).appendTo(document.body)\n\n $(this._element).on(Event.CLICK_DISMISS, (event) => {\n if (this._ignoreBackdropClick) {\n this._ignoreBackdropClick = false\n return\n }\n if (event.target !== event.currentTarget) {\n return\n }\n if (this._config.backdrop === 'static') {\n this._element.focus()\n } else {\n this.hide()\n }\n })\n\n if (animate) {\n Util.reflow(this._backdrop)\n }\n\n $(this._backdrop).addClass(ClassName.SHOW)\n\n if (!callback) {\n return\n }\n\n if (!animate) {\n callback()\n return\n }\n\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callback)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else if (!this._isShown && this._backdrop) {\n $(this._backdrop).removeClass(ClassName.SHOW)\n\n const callbackRemove = () => {\n this._removeBackdrop()\n if (callback) {\n callback()\n }\n }\n\n if ($(this._element).hasClass(ClassName.FADE)) {\n const backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop)\n\n $(this._backdrop)\n .one(Util.TRANSITION_END, callbackRemove)\n .emulateTransitionEnd(backdropTransitionDuration)\n } else {\n callbackRemove()\n }\n } else if (callback) {\n callback()\n }\n }\n\n // ----------------------------------------------------------------------\n // the following methods are used to handle overflowing modals\n // todo (fat): these should probably be refactored out of modal.js\n // ----------------------------------------------------------------------\n\n _adjustDialog() {\n const isModalOverflowing =\n this._element.scrollHeight > document.documentElement.clientHeight\n\n if (!this._isBodyOverflowing && isModalOverflowing) {\n this._element.style.paddingLeft = `${this._scrollbarWidth}px`\n }\n\n if (this._isBodyOverflowing && !isModalOverflowing) {\n this._element.style.paddingRight = `${this._scrollbarWidth}px`\n }\n }\n\n _resetAdjustments() {\n this._element.style.paddingLeft = ''\n this._element.style.paddingRight = ''\n }\n\n _checkScrollbar() {\n const rect = document.body.getBoundingClientRect()\n this._isBodyOverflowing = rect.left + rect.right < window.innerWidth\n this._scrollbarWidth = this._getScrollbarWidth()\n }\n\n _setScrollbar() {\n if (this._isBodyOverflowing) {\n // Note: DOMNode.style.paddingRight returns the actual value or '' if not set\n // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n const stickyContent = [].slice.call(document.querySelectorAll(Selector.STICKY_CONTENT))\n\n // Adjust fixed content padding\n $(fixedContent).each((index, element) => {\n const actualPadding = element.style.paddingRight\n const calculatedPadding = $(element).css('padding-right')\n $(element)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n })\n\n // Adjust sticky content margin\n $(stickyContent).each((index, element) => {\n const actualMargin = element.style.marginRight\n const calculatedMargin = $(element).css('margin-right')\n $(element)\n .data('margin-right', actualMargin)\n .css('margin-right', `${parseFloat(calculatedMargin) - this._scrollbarWidth}px`)\n })\n\n // Adjust body padding\n const actualPadding = document.body.style.paddingRight\n const calculatedPadding = $(document.body).css('padding-right')\n $(document.body)\n .data('padding-right', actualPadding)\n .css('padding-right', `${parseFloat(calculatedPadding) + this._scrollbarWidth}px`)\n }\n }\n\n _resetScrollbar() {\n // Restore fixed content padding\n const fixedContent = [].slice.call(document.querySelectorAll(Selector.FIXED_CONTENT))\n $(fixedContent).each((index, element) => {\n const padding = $(element).data('padding-right')\n $(element).removeData('padding-right')\n element.style.paddingRight = padding ? padding : ''\n })\n\n // Restore sticky content\n const elements = [].slice.call(document.querySelectorAll(`${Selector.STICKY_CONTENT}`))\n $(elements).each((index, element) => {\n const margin = $(element).data('margin-right')\n if (typeof margin !== 'undefined') {\n $(element).css('margin-right', margin).removeData('margin-right')\n }\n })\n\n // Restore body padding\n const padding = $(document.body).data('padding-right')\n $(document.body).removeData('padding-right')\n document.body.style.paddingRight = padding ? padding : ''\n }\n\n _getScrollbarWidth() { // thx d.walsh\n const scrollDiv = document.createElement('div')\n scrollDiv.className = ClassName.SCROLLBAR_MEASURER\n document.body.appendChild(scrollDiv)\n const scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth\n document.body.removeChild(scrollDiv)\n return scrollbarWidth\n }\n\n // Static\n\n static _jQueryInterface(config, relatedTarget) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = {\n ...Default,\n ...$(this).data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (!data) {\n data = new Modal(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config](relatedTarget)\n } else if (_config.show) {\n data.show(relatedTarget)\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * Data Api implementation\n * ------------------------------------------------------------------------\n */\n\n $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {\n let target\n const selector = Util.getSelectorFromElement(this)\n\n if (selector) {\n target = document.querySelector(selector)\n }\n\n const config = $(target).data(DATA_KEY)\n ? 'toggle' : {\n ...$(target).data(),\n ...$(this).data()\n }\n\n if (this.tagName === 'A' || this.tagName === 'AREA') {\n event.preventDefault()\n }\n\n const $target = $(target).one(Event.SHOW, (showEvent) => {\n if (showEvent.isDefaultPrevented()) {\n // Only register focus restorer if modal will actually get shown\n return\n }\n\n $target.one(Event.HIDDEN, () => {\n if ($(this).is(':visible')) {\n this.focus()\n }\n })\n })\n\n Modal._jQueryInterface.call($(target), config, this)\n })\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Modal._jQueryInterface\n $.fn[NAME].Constructor = Modal\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Modal._jQueryInterface\n }\n\n return Modal\n})($)\n\nexport default Modal\n","import $ from 'jquery'\nimport Popper from 'popper.js'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): tooltip.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Tooltip = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'tooltip'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.tooltip'\n const EVENT_KEY = `.${DATA_KEY}`\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const CLASS_PREFIX = 'bs-tooltip'\n const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\n\n const DefaultType = {\n animation : 'boolean',\n template : 'string',\n title : '(string|element|function)',\n trigger : 'string',\n delay : '(number|object)',\n html : 'boolean',\n selector : '(string|boolean)',\n placement : '(string|function)',\n offset : '(number|string)',\n container : '(string|element|boolean)',\n fallbackPlacement : '(string|array)',\n boundary : '(string|element)'\n }\n\n const AttachmentMap = {\n AUTO : 'auto',\n TOP : 'top',\n RIGHT : 'right',\n BOTTOM : 'bottom',\n LEFT : 'left'\n }\n\n const Default = {\n animation : true,\n template : '
' +\n '
' +\n '
',\n trigger : 'hover focus',\n title : '',\n delay : 0,\n html : false,\n selector : false,\n placement : 'top',\n offset : 0,\n container : false,\n fallbackPlacement : 'flip',\n boundary : 'scrollParent'\n }\n\n const HoverState = {\n SHOW : 'show',\n OUT : 'out'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n INSERTED : `inserted${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n FOCUSOUT : `focusout${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`\n }\n\n const ClassName = {\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n TOOLTIP : '.tooltip',\n TOOLTIP_INNER : '.tooltip-inner',\n ARROW : '.arrow'\n }\n\n const Trigger = {\n HOVER : 'hover',\n FOCUS : 'focus',\n CLICK : 'click',\n MANUAL : 'manual'\n }\n\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Tooltip {\n constructor(element, config) {\n /**\n * Check for Popper dependency\n * Popper - https://popper.js.org\n */\n if (typeof Popper === 'undefined') {\n throw new TypeError('Bootstrap tooltips require Popper.js (https://popper.js.org)')\n }\n\n // private\n this._isEnabled = true\n this._timeout = 0\n this._hoverState = ''\n this._activeTrigger = {}\n this._popper = null\n\n // Protected\n this.element = element\n this.config = this._getConfig(config)\n this.tip = null\n\n this._setListeners()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Public\n\n enable() {\n this._isEnabled = true\n }\n\n disable() {\n this._isEnabled = false\n }\n\n toggleEnabled() {\n this._isEnabled = !this._isEnabled\n }\n\n toggle(event) {\n if (!this._isEnabled) {\n return\n }\n\n if (event) {\n const dataKey = this.constructor.DATA_KEY\n let context = $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n context._activeTrigger.click = !context._activeTrigger.click\n\n if (context._isWithActiveTrigger()) {\n context._enter(null, context)\n } else {\n context._leave(null, context)\n }\n } else {\n if ($(this.getTipElement()).hasClass(ClassName.SHOW)) {\n this._leave(null, this)\n return\n }\n\n this._enter(null, this)\n }\n }\n\n dispose() {\n clearTimeout(this._timeout)\n\n $.removeData(this.element, this.constructor.DATA_KEY)\n\n $(this.element).off(this.constructor.EVENT_KEY)\n $(this.element).closest('.modal').off('hide.bs.modal')\n\n if (this.tip) {\n $(this.tip).remove()\n }\n\n this._isEnabled = null\n this._timeout = null\n this._hoverState = null\n this._activeTrigger = null\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n this._popper = null\n this.element = null\n this.config = null\n this.tip = null\n }\n\n show() {\n if ($(this.element).css('display') === 'none') {\n throw new Error('Please use show on visible elements')\n }\n\n const showEvent = $.Event(this.constructor.Event.SHOW)\n if (this.isWithContent() && this._isEnabled) {\n $(this.element).trigger(showEvent)\n\n const isInTheDom = $.contains(\n this.element.ownerDocument.documentElement,\n this.element\n )\n\n if (showEvent.isDefaultPrevented() || !isInTheDom) {\n return\n }\n\n const tip = this.getTipElement()\n const tipId = Util.getUID(this.constructor.NAME)\n\n tip.setAttribute('id', tipId)\n this.element.setAttribute('aria-describedby', tipId)\n\n this.setContent()\n\n if (this.config.animation) {\n $(tip).addClass(ClassName.FADE)\n }\n\n const placement = typeof this.config.placement === 'function'\n ? this.config.placement.call(this, tip, this.element)\n : this.config.placement\n\n const attachment = this._getAttachment(placement)\n this.addAttachmentClass(attachment)\n\n const container = this.config.container === false ? document.body : $(document).find(this.config.container)\n\n $(tip).data(this.constructor.DATA_KEY, this)\n\n if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) {\n $(tip).appendTo(container)\n }\n\n $(this.element).trigger(this.constructor.Event.INSERTED)\n\n this._popper = new Popper(this.element, tip, {\n placement: attachment,\n modifiers: {\n offset: {\n offset: this.config.offset\n },\n flip: {\n behavior: this.config.fallbackPlacement\n },\n arrow: {\n element: Selector.ARROW\n },\n preventOverflow: {\n boundariesElement: this.config.boundary\n }\n },\n onCreate: (data) => {\n if (data.originalPlacement !== data.placement) {\n this._handlePopperPlacementChange(data)\n }\n },\n onUpdate: (data) => {\n this._handlePopperPlacementChange(data)\n }\n })\n\n $(tip).addClass(ClassName.SHOW)\n\n // If this is a touch-enabled device we add extra\n // empty mouseover listeners to the body's immediate children;\n // only needed because of broken event delegation on iOS\n // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().on('mouseover', null, $.noop)\n }\n\n const complete = () => {\n if (this.config.animation) {\n this._fixTransition()\n }\n const prevHoverState = this._hoverState\n this._hoverState = null\n\n $(this.element).trigger(this.constructor.Event.SHOWN)\n\n if (prevHoverState === HoverState.OUT) {\n this._leave(null, this)\n }\n }\n\n if ($(this.tip).hasClass(ClassName.FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(this.tip)\n\n $(this.tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n }\n }\n\n hide(callback) {\n const tip = this.getTipElement()\n const hideEvent = $.Event(this.constructor.Event.HIDE)\n const complete = () => {\n if (this._hoverState !== HoverState.SHOW && tip.parentNode) {\n tip.parentNode.removeChild(tip)\n }\n\n this._cleanTipClass()\n this.element.removeAttribute('aria-describedby')\n $(this.element).trigger(this.constructor.Event.HIDDEN)\n if (this._popper !== null) {\n this._popper.destroy()\n }\n\n if (callback) {\n callback()\n }\n }\n\n $(this.element).trigger(hideEvent)\n\n if (hideEvent.isDefaultPrevented()) {\n return\n }\n\n $(tip).removeClass(ClassName.SHOW)\n\n // If this is a touch-enabled device we remove the extra\n // empty mouseover listeners we added for iOS support\n if ('ontouchstart' in document.documentElement) {\n $(document.body).children().off('mouseover', null, $.noop)\n }\n\n this._activeTrigger[Trigger.CLICK] = false\n this._activeTrigger[Trigger.FOCUS] = false\n this._activeTrigger[Trigger.HOVER] = false\n\n if ($(this.tip).hasClass(ClassName.FADE)) {\n const transitionDuration = Util.getTransitionDurationFromElement(tip)\n\n $(tip)\n .one(Util.TRANSITION_END, complete)\n .emulateTransitionEnd(transitionDuration)\n } else {\n complete()\n }\n\n this._hoverState = ''\n }\n\n update() {\n if (this._popper !== null) {\n this._popper.scheduleUpdate()\n }\n }\n\n // Protected\n\n isWithContent() {\n return Boolean(this.getTitle())\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const tip = this.getTipElement()\n this.setElementContent($(tip.querySelectorAll(Selector.TOOLTIP_INNER)), this.getTitle())\n $(tip).removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)\n }\n\n setElementContent($element, content) {\n const html = this.config.html\n if (typeof content === 'object' && (content.nodeType || content.jquery)) {\n // Content is a DOM node or a jQuery\n if (html) {\n if (!$(content).parent().is($element)) {\n $element.empty().append(content)\n }\n } else {\n $element.text($(content).text())\n }\n } else {\n $element[html ? 'html' : 'text'](content)\n }\n }\n\n getTitle() {\n let title = this.element.getAttribute('data-original-title')\n\n if (!title) {\n title = typeof this.config.title === 'function'\n ? this.config.title.call(this.element)\n : this.config.title\n }\n\n return title\n }\n\n // Private\n\n _getAttachment(placement) {\n return AttachmentMap[placement.toUpperCase()]\n }\n\n _setListeners() {\n const triggers = this.config.trigger.split(' ')\n\n triggers.forEach((trigger) => {\n if (trigger === 'click') {\n $(this.element).on(\n this.constructor.Event.CLICK,\n this.config.selector,\n (event) => this.toggle(event)\n )\n } else if (trigger !== Trigger.MANUAL) {\n const eventIn = trigger === Trigger.HOVER\n ? this.constructor.Event.MOUSEENTER\n : this.constructor.Event.FOCUSIN\n const eventOut = trigger === Trigger.HOVER\n ? this.constructor.Event.MOUSELEAVE\n : this.constructor.Event.FOCUSOUT\n\n $(this.element)\n .on(\n eventIn,\n this.config.selector,\n (event) => this._enter(event)\n )\n .on(\n eventOut,\n this.config.selector,\n (event) => this._leave(event)\n )\n }\n\n $(this.element).closest('.modal').on(\n 'hide.bs.modal',\n () => this.hide()\n )\n })\n\n if (this.config.selector) {\n this.config = {\n ...this.config,\n trigger: 'manual',\n selector: ''\n }\n } else {\n this._fixTitle()\n }\n }\n\n _fixTitle() {\n const titleType = typeof this.element.getAttribute('data-original-title')\n if (this.element.getAttribute('title') ||\n titleType !== 'string') {\n this.element.setAttribute(\n 'data-original-title',\n this.element.getAttribute('title') || ''\n )\n this.element.setAttribute('title', '')\n }\n }\n\n _enter(event, context) {\n const dataKey = this.constructor.DATA_KEY\n\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER\n ] = true\n }\n\n if ($(context.getTipElement()).hasClass(ClassName.SHOW) ||\n context._hoverState === HoverState.SHOW) {\n context._hoverState = HoverState.SHOW\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HoverState.SHOW\n\n if (!context.config.delay || !context.config.delay.show) {\n context.show()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HoverState.SHOW) {\n context.show()\n }\n }, context.config.delay.show)\n }\n\n _leave(event, context) {\n const dataKey = this.constructor.DATA_KEY\n\n context = context || $(event.currentTarget).data(dataKey)\n\n if (!context) {\n context = new this.constructor(\n event.currentTarget,\n this._getDelegateConfig()\n )\n $(event.currentTarget).data(dataKey, context)\n }\n\n if (event) {\n context._activeTrigger[\n event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER\n ] = false\n }\n\n if (context._isWithActiveTrigger()) {\n return\n }\n\n clearTimeout(context._timeout)\n\n context._hoverState = HoverState.OUT\n\n if (!context.config.delay || !context.config.delay.hide) {\n context.hide()\n return\n }\n\n context._timeout = setTimeout(() => {\n if (context._hoverState === HoverState.OUT) {\n context.hide()\n }\n }, context.config.delay.hide)\n }\n\n _isWithActiveTrigger() {\n for (const trigger in this._activeTrigger) {\n if (this._activeTrigger[trigger]) {\n return true\n }\n }\n\n return false\n }\n\n _getConfig(config) {\n config = {\n ...this.constructor.Default,\n ...$(this.element).data(),\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.delay === 'number') {\n config.delay = {\n show: config.delay,\n hide: config.delay\n }\n }\n\n if (typeof config.title === 'number') {\n config.title = config.title.toString()\n }\n\n if (typeof config.content === 'number') {\n config.content = config.content.toString()\n }\n\n Util.typeCheckConfig(\n NAME,\n config,\n this.constructor.DefaultType\n )\n\n return config\n }\n\n _getDelegateConfig() {\n const config = {}\n\n if (this.config) {\n for (const key in this.config) {\n if (this.constructor.Default[key] !== this.config[key]) {\n config[key] = this.config[key]\n }\n }\n }\n\n return config\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n _handlePopperPlacementChange(popperData) {\n const popperInstance = popperData.instance\n this.tip = popperInstance.popper\n this._cleanTipClass()\n this.addAttachmentClass(this._getAttachment(popperData.placement))\n }\n\n _fixTransition() {\n const tip = this.getTipElement()\n const initConfigAnimation = this.config.animation\n if (tip.getAttribute('x-placement') !== null) {\n return\n }\n $(tip).removeClass(ClassName.FADE)\n this.config.animation = false\n this.hide()\n this.show()\n this.config.animation = initConfigAnimation\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' && config\n\n if (!data && /dispose|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Tooltip(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Tooltip._jQueryInterface\n $.fn[NAME].Constructor = Tooltip\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Tooltip._jQueryInterface\n }\n\n return Tooltip\n})($, Popper)\n\nexport default Tooltip\n","import $ from 'jquery'\nimport Tooltip from './tooltip'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): popover.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst Popover = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'popover'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.popover'\n const EVENT_KEY = `.${DATA_KEY}`\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n const CLASS_PREFIX = 'bs-popover'\n const BSCLS_PREFIX_REGEX = new RegExp(`(^|\\\\s)${CLASS_PREFIX}\\\\S+`, 'g')\n\n const Default = {\n ...Tooltip.Default,\n placement : 'right',\n trigger : 'click',\n content : '',\n template : '
' +\n '
' +\n '

' +\n '
'\n }\n\n const DefaultType = {\n ...Tooltip.DefaultType,\n content : '(string|element|function)'\n }\n\n const ClassName = {\n FADE : 'fade',\n SHOW : 'show'\n }\n\n const Selector = {\n TITLE : '.popover-header',\n CONTENT : '.popover-body'\n }\n\n const Event = {\n HIDE : `hide${EVENT_KEY}`,\n HIDDEN : `hidden${EVENT_KEY}`,\n SHOW : `show${EVENT_KEY}`,\n SHOWN : `shown${EVENT_KEY}`,\n INSERTED : `inserted${EVENT_KEY}`,\n CLICK : `click${EVENT_KEY}`,\n FOCUSIN : `focusin${EVENT_KEY}`,\n FOCUSOUT : `focusout${EVENT_KEY}`,\n MOUSEENTER : `mouseenter${EVENT_KEY}`,\n MOUSELEAVE : `mouseleave${EVENT_KEY}`\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class Popover extends Tooltip {\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n static get NAME() {\n return NAME\n }\n\n static get DATA_KEY() {\n return DATA_KEY\n }\n\n static get Event() {\n return Event\n }\n\n static get EVENT_KEY() {\n return EVENT_KEY\n }\n\n static get DefaultType() {\n return DefaultType\n }\n\n // Overrides\n\n isWithContent() {\n return this.getTitle() || this._getContent()\n }\n\n addAttachmentClass(attachment) {\n $(this.getTipElement()).addClass(`${CLASS_PREFIX}-${attachment}`)\n }\n\n getTipElement() {\n this.tip = this.tip || $(this.config.template)[0]\n return this.tip\n }\n\n setContent() {\n const $tip = $(this.getTipElement())\n\n // We use append for html objects to maintain js events\n this.setElementContent($tip.find(Selector.TITLE), this.getTitle())\n let content = this._getContent()\n if (typeof content === 'function') {\n content = content.call(this.element)\n }\n this.setElementContent($tip.find(Selector.CONTENT), content)\n\n $tip.removeClass(`${ClassName.FADE} ${ClassName.SHOW}`)\n }\n\n // Private\n\n _getContent() {\n return this.element.getAttribute('data-content') ||\n this.config.content\n }\n\n _cleanTipClass() {\n const $tip = $(this.getTipElement())\n const tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX)\n if (tabClass !== null && tabClass.length > 0) {\n $tip.removeClass(tabClass.join(''))\n }\n }\n\n // Static\n\n static _jQueryInterface(config) {\n return this.each(function () {\n let data = $(this).data(DATA_KEY)\n const _config = typeof config === 'object' ? config : null\n\n if (!data && /destroy|hide/.test(config)) {\n return\n }\n\n if (!data) {\n data = new Popover(this, _config)\n $(this).data(DATA_KEY, data)\n }\n\n if (typeof config === 'string') {\n if (typeof data[config] === 'undefined') {\n throw new TypeError(`No method named \"${config}\"`)\n }\n data[config]()\n }\n })\n }\n }\n\n /**\n * ------------------------------------------------------------------------\n * jQuery\n * ------------------------------------------------------------------------\n */\n\n $.fn[NAME] = Popover._jQueryInterface\n $.fn[NAME].Constructor = Popover\n $.fn[NAME].noConflict = function () {\n $.fn[NAME] = JQUERY_NO_CONFLICT\n return Popover._jQueryInterface\n }\n\n return Popover\n})($)\n\nexport default Popover\n","import $ from 'jquery'\nimport Util from './util'\n\n/**\n * --------------------------------------------------------------------------\n * Bootstrap (v4.1.3): scrollspy.js\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * --------------------------------------------------------------------------\n */\n\nconst ScrollSpy = (($) => {\n /**\n * ------------------------------------------------------------------------\n * Constants\n * ------------------------------------------------------------------------\n */\n\n const NAME = 'scrollspy'\n const VERSION = '4.1.3'\n const DATA_KEY = 'bs.scrollspy'\n const EVENT_KEY = `.${DATA_KEY}`\n const DATA_API_KEY = '.data-api'\n const JQUERY_NO_CONFLICT = $.fn[NAME]\n\n const Default = {\n offset : 10,\n method : 'auto',\n target : ''\n }\n\n const DefaultType = {\n offset : 'number',\n method : 'string',\n target : '(string|element)'\n }\n\n const Event = {\n ACTIVATE : `activate${EVENT_KEY}`,\n SCROLL : `scroll${EVENT_KEY}`,\n LOAD_DATA_API : `load${EVENT_KEY}${DATA_API_KEY}`\n }\n\n const ClassName = {\n DROPDOWN_ITEM : 'dropdown-item',\n DROPDOWN_MENU : 'dropdown-menu',\n ACTIVE : 'active'\n }\n\n const Selector = {\n DATA_SPY : '[data-spy=\"scroll\"]',\n ACTIVE : '.active',\n NAV_LIST_GROUP : '.nav, .list-group',\n NAV_LINKS : '.nav-link',\n NAV_ITEMS : '.nav-item',\n LIST_ITEMS : '.list-group-item',\n DROPDOWN : '.dropdown',\n DROPDOWN_ITEMS : '.dropdown-item',\n DROPDOWN_TOGGLE : '.dropdown-toggle'\n }\n\n const OffsetMethod = {\n OFFSET : 'offset',\n POSITION : 'position'\n }\n\n /**\n * ------------------------------------------------------------------------\n * Class Definition\n * ------------------------------------------------------------------------\n */\n\n class ScrollSpy {\n constructor(element, config) {\n this._element = element\n this._scrollElement = element.tagName === 'BODY' ? window : element\n this._config = this._getConfig(config)\n this._selector = `${this._config.target} ${Selector.NAV_LINKS},` +\n `${this._config.target} ${Selector.LIST_ITEMS},` +\n `${this._config.target} ${Selector.DROPDOWN_ITEMS}`\n this._offsets = []\n this._targets = []\n this._activeTarget = null\n this._scrollHeight = 0\n\n $(this._scrollElement).on(Event.SCROLL, (event) => this._process(event))\n\n this.refresh()\n this._process()\n }\n\n // Getters\n\n static get VERSION() {\n return VERSION\n }\n\n static get Default() {\n return Default\n }\n\n // Public\n\n refresh() {\n const autoMethod = this._scrollElement === this._scrollElement.window\n ? OffsetMethod.OFFSET : OffsetMethod.POSITION\n\n const offsetMethod = this._config.method === 'auto'\n ? autoMethod : this._config.method\n\n const offsetBase = offsetMethod === OffsetMethod.POSITION\n ? this._getScrollTop() : 0\n\n this._offsets = []\n this._targets = []\n\n this._scrollHeight = this._getScrollHeight()\n\n const targets = [].slice.call(document.querySelectorAll(this._selector))\n\n targets\n .map((element) => {\n let target\n const targetSelector = Util.getSelectorFromElement(element)\n\n if (targetSelector) {\n target = document.querySelector(targetSelector)\n }\n\n if (target) {\n const targetBCR = target.getBoundingClientRect()\n if (targetBCR.width || targetBCR.height) {\n // TODO (fat): remove sketch reliance on jQuery position/offset\n return [\n $(target)[offsetMethod]().top + offsetBase,\n targetSelector\n ]\n }\n }\n return null\n })\n .filter((item) => item)\n .sort((a, b) => a[0] - b[0])\n .forEach((item) => {\n this._offsets.push(item[0])\n this._targets.push(item[1])\n })\n }\n\n dispose() {\n $.removeData(this._element, DATA_KEY)\n $(this._scrollElement).off(EVENT_KEY)\n\n this._element = null\n this._scrollElement = null\n this._config = null\n this._selector = null\n this._offsets = null\n this._targets = null\n this._activeTarget = null\n this._scrollHeight = null\n }\n\n // Private\n\n _getConfig(config) {\n config = {\n ...Default,\n ...typeof config === 'object' && config ? config : {}\n }\n\n if (typeof config.target !== 'string') {\n let id = $(config.target).attr('id')\n if (!id) {\n id = Util.getUID(NAME)\n $(config.target).attr('id', id)\n }\n config.target = `#${id}`\n }\n\n Util.typeCheckConfig(NAME, config, DefaultType)\n\n return config\n }\n\n _getScrollTop() {\n return this._scrollElement === window\n ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop\n }\n\n _getScrollHeight() {\n return this._scrollElement.scrollHeight || Math.max(\n document.body.scrollHeight,\n document.documentElement.scrollHeight\n )\n }\n\n _getOffsetHeight() {\n return this._scrollElement === window\n ? window.innerHeight : this._scrollElement.getBoundingClientRect().height\n }\n\n _process() {\n const scrollTop = this._getScrollTop() + this._config.offset\n const scrollHeight = this._getScrollHeight()\n const maxScroll = this._config.offset +\n scrollHeight -\n this._getOffsetHeight()\n\n if (this._scrollHeight !== scrollHeight) {\n this.refresh()\n }\n\n if (scrollTop >= maxScroll) {\n const target = this._targets[this._targets.length - 1]\n\n if (this._activeTarget !== target) {\n this._activate(target)\n }\n return\n }\n\n if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {\n this._activeTarget = null\n this._clear()\n return\n }\n\n const offsetLength = this._offsets.length\n for (let i = offsetLength; i--;) {\n const isActiveTarget = this._activeTarget !== this._targets[i] &&\n scrollTop >= this._offsets[i] &&\n (typeof this._offsets[i + 1] === 'undefined' ||\n scrollTop < this._offsets[i + 1])\n\n if (isActiveTarget) {\n this._activate(this._targets[i])\n }\n }\n }\n\n _activate(target) {\n this._activeTarget = target\n\n this._clear()\n\n let queries = this._selector.split(',')\n // eslint-disable-next-line arrow-body-style\n queries = queries.map((selector) => {\n return `${selector}[data-target=\"${target}\"],` +\n `${selector}[href=\"${target}\"]`\n })\n\n const $link = $([].slice.call(document.querySelectorAll(queries.join(','))))\n\n if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {\n $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE)\n $link.addClass(ClassName.ACTIVE)\n } else {\n // Set triggered link as active\n $link.addClass(ClassName.ACTIVE)\n // Set triggered links parents as active\n // With both
    and