/*
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@BB@@BB@@%8BBB%B&&Md0c|]~l^. ',<[|nLb*W88B%%B%%%@@B%@@BB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B@B%%88#Qt+^.''...... ..............''.'..`~tY#%@B%BBBBB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B@%@%B@W0-;..'' .'-upoW8%BB@@%@@@BB@@BBB@BB#adu-``` ' `"?J*@&@8BB@BB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@B&h[.`.'^^>L%8B%@@B88B8%8MMM#MMooo##MW&%BB%%@B%%@BBBZ+". ' ._bMBB@@@B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@BB%L]"` .;/m8B%@BBBMdCj]ili!ii!!!!>+11-i!!!!i!i!!>[jJkW@8@%%%8dtI.'.'-C8%%B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@Wn"^'."cW8B@8&Boj_i+i!i!!!!!!iil"xo#/>-(hWuIii>ii!!!!i>l;+</a@8@%8%WX:.` :(#B8BB@%@B@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@BBh|^..`)a8B@@Bkj<;+Iii!!il>!l!!!!i!iYWhI>iiiIm8Ziilii!!!i!I!~>;!!~l<udB%8B@#),'`.1hB%BBB@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@%%%BBBj"' ,uMB%B&dn-l![QWa*%av~!i<;>!!!!!i~$%cii>i!>_B%?lil!!!ii!l<!t#%MoWO{!>iuk@%%8Mu"'.`|#B%B%BB@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@BB%Bpl^` tW&8BBO}!l!i<a0:>!i!L%B1!l!!!!!!!l>kB0!!I>liu8*li!ii!!!>!i_W@w_Iii+ZW(;lii?088@%Mr`,.lZBM@B@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@B%%v`^ !k%8&B0-;!i!il+#8[!i!>iIq%hli<li!!!!!l.w%ni~ii/BwIi!!!!!i!l!!bMqili>!i-#&?Ill>l<~Z8&BBa?''`rW%@B@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@B8Wt'''|&B&Bd1I!l>!ii!ilM%cll>l!>!Bpii!!l!!!l>|oUUZoI!wmcUaXl>!!!!i!~IZ@{i!i!<l(@B]!ii!!iiIi[h%%8&v`'`|#%$B@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@BB@M).'`z%*B@Y<!:!i!>!i!i!ic%%f,i!>:Ch!18+>!!i!l;-vzXXr:itXCUL|!!>i!iiihflaZ!<<<l)*8J<i!!!!!!i~:-!xBB%BY,'`]BB%B@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@%%j`^"Y8@MWf!<i!lIiii>i_jrX[rqB8C(l>8&88kt<I>~[/XqM%B@@BBBB%W*mc|]<<>I)p&B@%+~<XM&k/?YQn1;><iil<+l?"j8&B8C,' j&@8BB@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@B%BO,^'xB%BWjiii!i!l<!!ljW&%B8BBBWm*B/l??>(Uh&BB8B@B@@@@@@BBB@BB@@BB%BBBBoCt~_[>1B8Z*8%BB8%8%z!>ilil!Iii>|&%BWU.`,UBB%@@@@@@@@@@@@@@@
@@@@@@@@@@@@%B%@%&<` -&B@#j;+L%B@%@#[l>|B%&Y/jrO&%8%&U0&@@%%BBBBabqO00OO00ZZO0O0QOZqqo%B@BB%%@&Qn*@%8&kYunYW88Ll>>pB@888p!!(MB8B}`.;W@B@%B@@@@@@@@@@@
@@@@@@@@@@@@BB%8J``;m%BBClIvp<+I!!Y%8z<oBBY-_}/ft|CWB8%BB&aqOQQOOOb&B%B@@%BB@@@%BBWhmZ000OmkW@@&8@%pvnvuj)tn8B%~v@80>>iIlwLIizBW8b: "XB%@@@@@@@@@@@@@
@@@@@@@@@@@@B@#+"'/8%%d?I>j%1i!ii!!i*8]BB%!`.'"-|(f/u*%%BkZQ0OOd&@BB&dQJLCUUUYUOdMB@%8kOOOOQd8@%&Ouunu/><<<<#8@fBB]<i!lii~%Xii>b8B%t"^+*%B@@@@@@@@@@@
@@@@@@@@@@@BBw```d8BBnl>l!wBc!il<!>lfbf88B'.'^'':|t/f/c&8@8mmO&@@%&%@%%B@@@@BB@B%%&&@@@MqLZa@B8Zrvunv[<;><>lhB@Q*c!>i!!li[@ol!i;r8%@#"'"ZB@@B@@@@@@@@
@@@@@@@@@B@BC'`i8B8*<>iii!>MBp_l<l>!x&@8@B..`!MW1ltt/t(/0%%@a8%B@BWamXxf/|((|t/cOb#WBB@%Bo%@%*xcxvcx}-o8u<>!0@B@%vllI<I<OBB|>;~Ii<b%@W~^.tB8@%@@@@@@@
@@@@@@@@@B8r`'1%@%J>i!i!!>~:LBWBkd*]:>|%@@  'a@%@Yl//tt)/ja%%B%88%aU/tt/jnnnxr|/|/zh%BB%%BBMUnvnvnz]n&BB@<><wBBq~i?dkpM&80<!i!i!!>lU%8Br `18%%@@@@@@@
@@@@@@@@@&(``v%%&f>!!>!!!ii>"ll>~w@o~|#B@B` .@@%B@#n]r/(/t)U&@%pv&%%BB8B@@B@@@@B&BB&%00%BBqvvuxvvf/#%B@B@~>>aB@WjIhBp~l>!>;!>iii!l<<j&%@z^`?B@B@@@@@@
@@@@@@@BB{^'XB881!!il;l!i!I>lildBo|i*%@@@@;..#%%BB8B%bxx/|/)jp#m|/b%@#Jjt/||/tnUMBBacn0aWJrvuxvvZ%&@@BBBB<>>M%BBB&-1#@L~iiil>!iil!l!i[&%@C^`<BB@@@@@@
@@@@@@BB)''X@BB}l!ii!ii!!!!i!i!>l!cBB@#B@@+  L8B#qwd&@8@%ou/ttt/tf/q&%Cf|//j//tz%BanuuuvnunXh%8@%8akbMBB8>~-W@@#@BBQlli!!!!!!!!!i!!!!!?WB%J''~8%@%@@@
@@@@@@Br.'x%%W1~!!i!ii!!!!!!!iiI>h8@%qOW@@).'Iv,^ ''.LB#X|f||/tf/t/n%88BBBB%B%B%8B0vnnzunnxzcUqW#?<~<<Ir/>>-BB%0w8@&W>l>l!!!!ii!!iii!i>?W@@Y `|%B%B@@
@@@@@B0^ |B@B|!i1w8%bn+liIiliiI/8B@#Z00bBBO... ...^`(Jx|/tttttt////j&B%b0XvnvCq8B8JuuuuuuuuuuxvuLC~;<>i<!i>r@B*ZLZa@%@xi>!I!>>I:f0%#J)I>-8%Bj^ YB%B@@
@@@@Ba. <8@%f!)WmvnU*%8L!oz]l!XBB%aLO00m@@8".'.ij]~|///|///tt//////fM%Bc/|t//tv#B8uxnuuuuuuuuuuvxvx)1z(l<!<o@BkQmQOd%%BL;<[JZin8%&Zvcw#f<t8B&+ '08@@@
@@@B@l^ *%@O>)d-~ili>ln%jJ@Z!UB%Bq0LZOOO@@Bj';#%88v(t|ttt/t////tttt|wB%%BB%@&BWB%oxvuuuuuuuuuunuuvnv*8@8x:)B@%bOOQZQp&@@p!qBUfBJli<I!+Id{!z%%8,.,@@B@
@@%@f''m@%aliqJ+!iliiiiYb%#~L8%8w0OmQO0M%@@aQ@%8qj|/t//////////tttt|U%BW*&%B8oo%BdnvuuuuuuuuuuuuunuuxO88%hw@BB%m00O0Qm%B%dIh%k*~il>li!<f#i>w%BZ''[8@@
@BBW`'+B@B}!iY@cliiiii!!i)>U%8Bw0OQ0O0k@%@@B%8ar/ttttt/////////tt//|x%@M&8B%@%hBBOvunuuuuuuuuuuuuuvuuuxh%B%@BBB&OOOOO0Z8%&m>|>li>ii!i;u8pii]@BB[.`W@@
@BW+ 'W@BJl~Ilq8%&OttZW%p<{BBBmOOOOO0q%BB&BBBO|//tttt///ttt/ttt/f//ffB%B%q1(L8%@%CxcuuuuuuuuuuuuuuuuuuvxCWBBa%B@W0O00OOZB%@Xiq8&o}-0M%Bal!>!u8@* ',B%
@BW''}BB8-iI!;~;XqhkL<o&J<%B@kZOOOOOZ8BB%@B%Q)t//ttttttttt////t//ftC&B8qro#oMzwW%8pxvuuuuuuuuuuuuuuuuuuvxC&%B%BB%kQOZOOOpBB%{n@m<Jb*hc-Ii<li_BBBx'^Z@
@8+.'kB@Yil<!ii!i>;~ro8Qib@@oO00OOO0W@%*Q@Bh/t/ttt/tt/j|/fxUbW&bc|vW8BZtLoYJkk)L8B%CxzpW8#mzvuznuuuuuuunnvZB@km%8Bw0OZ0OO*@BhiZW&vlil>il!>!ilj@@h.'~B
B#" }B@8}!lIii!i!!>ll!~+/%8%w0OOO00hB%&jWBBO/t/ttttttt(xh&8@@BBB%WY(m88&wa8WaJ&88bvn*B%@B@8W8MLvuuuuuuuunuJ8%8|dB%&ZOZ0O0ZB@%X~+I+!;iiiii!>l>!&8@?' h
&Q''UB%p!<!I>ii!i!iil>>l*8%*QOZLOQb%B%L|MB8X/t/ttttttff//08B@B%BBBWcj)bB8&xn#%B*cvrW%%%%@%BB#rvuuuuuuuvvvnz%%&xtMBB#OQ0OZ0k%B*!ll!i!li!!!i!il;p@Bb 'n
B~ .#@B/iilii!iiii!iii~(BB@mZQZZZZ8@B8B&BB8u///////tttftttZMB8%BBB%C||/xd%BBB*Jxuuv%%BB%%B8aYvvunuuuuuuunnu%BB#BB@BBk0OOO0O8@@jl!ii!!!!!!iilli1B@W' ~
W.'~B@B_i!iii>ii!iii!>;OBBMO000O0M@BMh8B8%%t////tt////(/|/|(/r(/nZ*dj(1)(XoaCnvcvvO*dLzcuuxrvvuuunuuuuununu8@%@B*bBBBO0O0O0#%B*!iii!!!!!!!!!il<WBBl.'
b. j@BWlili!?1(_i!jYU}<oB@d00000bB%&nvuQ%B&/tt|t///?l^`''`''`"!+)|t/t/t///t/ruuuuvvnvn(-~i!i>><i>~)nxvnuuuuW%BbcnxpBB&Z000Oq@@&+?UYXiI~{)+i<IilhB%f'.
Q' Q@Bol!-dB%BB%%kiCB/<@B%mQO00q8B%Yj1tn&@8ff/ttt?,'..   . .. '`'l{t/f/tttt/ruuucnnn]<i>>i>ii>>!!<!>1uuuuuu&BB0f|ft*%@o0OOOZ%B@-t%piwBBB$&Ww>>lZ@Bd` 
X  d@@ml-#Z];!>IinWL@}tBB%ZOQZQ8@%@8X(/n8B%j|tj/_`. .           ..`_///ttt//rvnvxvj<>>>>>>>>>>i>>>!+!]urvuvM%8Uj|rp%B%BkQZ0O&%@|)@b%XiI!!l<mW!!C@8&. 
v .b@@Q!u0llIii!l>il]-x@@8O0ZQ#BB&%B%8hUMB%vt|t1^.              . .^_t//////xuuuvf~>>>>>>>>>>>>>i><>>i|nunu%B8Up88BB8%BBmOOQW%%v<_l<~i!l!!i!zX!Y@BB'.
n''bB@Cljw!I!ii!<>[nn!cBB8OOQb@B&JuCM%%@%8%Q(tt~`..             .. .^I)///t/runn}i<i>>>>>>>>>>ii>>>>ii~xvuY8BBBBBWpXuaB%WZZLW@BX-uu)lilii!i!pr!X@@B' 
c''b@%L+~k%UI;!^)&dwB!v@B&00m8B%C)ffcvL&%8@d/|)I. . ... . ..`.    '^"`'!|rf/vuxi<~<!>>>>><!!I!>>>>>>>><rnx0B@@%dzunt(jW%%aQQM@@z}Ba081il,>r%h>IX@BB''
U  w@@bil!rwBB%%*r!dW>1@B8OZWB@8c|/|t/tcUBBWjt/,........!1<'.'.   .'(&8B@%BB%B%B%q-i>>>ii<!_j}i~i>>>>>>xxu*&Bmnutt/||tbBBBqO&@B(]Bh;j*B8&BWzl+lL@@*..
Z..LBBM!!iilii>!!!1fnl<&@BOhBB@@B8pu(t|t/M%%p1(; .......b%Bd`'     -B@@@@@@@@BB@BBQ>>~!>i!X%8%}<ii>>>>>rnJBBBc|(t(tQ*B%B@@8wBBBi!(([l!l!i!l!il!qB%q. 
h  )@@W!!!i!i!l!>i<!><>h@@k%%BJO88%&%qj/*%@%#(/l.     .^ wB%a^     `M%%B@@@@@BB@B@]>!>i<!0B%M_<!~ii>>><jxb%B%&c{LW%%B%kY#@@WB&#~~!<><ilii!!i!iloB%( .
&`.;%@%~i>l!i!ii!il>>IiQB@@%%ptvvcq8%BBB@BBB%Zt~`.. .  '.^OB@0.    'IW%B@@@@@BBB%n<<!>~lu%8#+<!~i>>>>>+vU8BB%BBBB%%*Lrvxv%8BBBh!i>ll!!!ii!!liI~8B%".'
B{..h@@xii!iii!!!!i!!>>]@&@B#ft(/rnvCpB@&bx88%z(`....     "BB%n'.. .'^xW@%%@%B%m-ii<>i~?@8@1l>i>>>i>>>jv&%%zU&B@MUxzjf|t|QB8@%[<i!i!!!!!!!>iiivBB* `1
Bq .cB@&>!ii!!!!!i!!!i!!Z@%B@8Zr|tt(/d@Bo|tX%%&X>.'..     '"WB&<.' '. ^. :]1?!~?+ii!>i~#BBu><i>>>>>>![u*%BO/t08%%/(//|/z#B8%Ba^]:Il!!!!!!ii!iiaB@Q 'Y
@&`.~BB@{i>>i!ii!i!-w%@jWB8W&%%%WCf|L%B#ff/(Y%B*J'..'     ..t&%8Ot[1nw&B%@BBBB%&kQntrq%8%k>!>i>>i~;~iu#88q////b%Bqf|chBB8%*%@%c&8O{I!<i!I>!<;+%@B~.`o
@B/..0@B0iliiI[m#B%MX+&%%%oYvYd&%B%M8B&z/////r&&BQ`''    ' ''iZ&%%BBB%%%%%%%%%%%BBB@B@B#tI>!~i>>><!ic8%BX/(j/jf#8@#&%BBMQvuw8B@&)vo&8#C+l<!!>J@Bp.')B
@@@,'_@@@1l!ip&@q/iI]M%88%jtjnzuco%@@BQ(j||/I: w@M%t.         . .m%B*ZwwwwmmwwqZ0a&B@<I>!ii>>>+i<i]M%B&l^;))j/tuBBBB&LcxXt(jb@8@*{ilthBWQ!!i-%%8).'bB
BB%/'`m8@qi!(8Xi+!ll>I#@%8Jj|//rznwB%atf|t}". ''-#%%q         ..':8%&mOOOOOZZZ0mm#BBx>i!ii>>>il<iC%WWf. ..`_t//|OB%oxUn|tt(vaB@@jlli!!!v@}<Iw88q'`+BB
BB%&I :&@Br;(*iI?ll>IO%B%B8%*U(tfn8B8c/|t+^'..'''.I},         ...`n%%WOZZZZmZZZOo8%k!>i>>i>>>i>i<i/1!". ..."I//ffM%&C1j(xk%8B@@%W_<i<lii@{>j%&@+`^%8@
@BB@U 'rB&&>!p/;~!iI?@%BYUoB%%BacpBBh//|I.'..                    ' w8M8oZ00ZQZdW%##i<>>>i>>>>>>i>><>!>l^  . ."{f1LB%#jZ8B%%&mr&B%OI>~i!}W>~&B@c` z@@@
@@B@B)'`ZBBMiIC%hh8BBW%wtzvuQo88B@8%%%Z<'....                     .`_d%B%BBBBB@@%v>><>>>i>>>>>>i>>ii<ii<!I:^``;J8MB%%%B%Wqzucrj&B&WkqqWq:>q@8o`.-88@@
@@@@B*`.:o%@L!ii{uzd%B&rtf|rvcc0#%%B@B%B#)^`....              .'''....'i)tvcnx?>~!>>i!i><>>>>>>>>>i>>ii>~!~l)hBBB%@BB%bzvcrftf/w8BWLC)+!!U@%M: "#@B@@
@@@@%BM.'!B%%c!!!I_8@B%omn)|j/ncucq8%B@@@8@m,.^ '             '~@8o]'"..''`!~>~<_;]d@%U~<>>>>>>>>>i>>i!<>!Q%BBBB%B8kUucxtr)(jY#&8%8Llliln%@B~^.wBB@@@
@@@@BB%Q'`-%B%n>l!OB%B%88B%B#Ouf/rzxzb8BB%@B&W(^.  .          .`xW8%%d(<:I>i<i_tZ&@8@w-!i>>>>>>>i><i><I/#%BBBB%%*Qzxuj(rJhW%B8BB%BB%_>I/@%%(`.C8@%B@@
@@@B@BB@X^.}%B@ni[%%Br|fuO#%%8B%WqvtvvvYk8@%%B&%w>..'         ..`,)a%&MBBB%%BBB%B%#n~!>>>>>>>>>>>><i~0BBB@%BB*QcxzrfC*&%%8B8pUj/(aB@m;r@MB(''c%B@@@@@
@@@@B@%@@X'']8@%JoB%bfj|){u||Jb&B%%8%U(zvuChBB%&BB@j'          . ^`lI<~nd&W#Wau(<I<>+<>>>>>>>>i<>>tM&%%%%%WOzucjrhBBBB%Mwx|j|{|/fz%@%ZBBB)`.x@@@@@@@@
@@@@@@@@BBU''i8B&%BB88dUn//wO0w/jUh%BB%MXnvcu0*8B@%8Bh<"'   '      'I>i>>>i>>i>>>>i>>iiii<i!>!~_m&BBBBBWqXvzxxb%88%MZx(rkChu/fvmM88%B8@W? 'xB&@@@@@@@
@@@@@@@@@BBw''lW%88#8BB8%%WqJv{|/t|jrb%8%BpxxczuZW%@@8%WJ` '       . "i>>>>>>ii>>>>>>iiiii>!>jM8@%@B8bzrUxjLMB8B&Yj/|(/|rud*8B@%8W&&@Ba<  CB%%@@@@@@@
@@@@@@@@@@@88:.^Z88%rI!r*BBB%%8Zf1coQatY&%%%W)xvcxYO&B8@%Ba+....' .   .I~!<>>>>>>>>>>!~<ll+d@@B@B8oXcvXjrJ%&@WqtwwqCt{v#88%BB#Z~I1B@&0l.'a@@@@@@@@@@@
@@@@@@@@@@B@%W-^'t8%@mi>!>iX%%B8%WOCZU|t)va%%%djtcvcuYp8B%888c;`^... .':iii>>>>>ii>>i>><x#B%B@%#Jvcuzx(J&8%&L||/rZQUa8B88#zdqIiiZB8Mr'"!8BB@@@@@@@@@@
@@@@@@@@@@BBB%BY..;kWBWnI<;f%J>Y&@%&#X(/t/|x*%@W0|tncvcuh%%BB%B#rI>>i>i>i<i>>>>>ii>ii{h&%8%B%8Lvccvn(vWB88Qf//||ta8B%Ba}i;rk>>(%B8aI'.xB8W@@@@@@@@@@@
@@@@@@@@@@@@@@BBhl'.|@@Bo_i>wwl_;~p@8B&m)fxdqc&%&a//fvzca%@#ObB%@%m+I<li><>>!~;~ii>z%@@BoOp%8BYvvnj(Q8%8kvhX((x#8@8%B&@%&&/:_bWB%z.'lb@%@@@@@@@@@@@@@
@@@@@@@@@@@@@BB@8@u^'"Z&B@k~IjMXfup&B%B%&Ymppc(*%%&jjvzzo@@B%8#*&B%8Wrl<ii>><<il1b@8B8*MWB%BB%Ycvu/ZB%8Xfbmkza%BBp-lI!i!!~lm%@&b:'`nB@@BB@@@@@@@@@@@@
@@@@@@@@@@@@@@@BBB8#?'^:aBBBm<!I(fj-~!v%@Baj////dBBWucczaB&&8&%8B%%B%8%b{l~li_X%B%8B&%BB%&o&8BXuYxmBBWv//t|O&B%h_ii!<ii!~U@B%oi''+a8@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@BBB%8!.,<MB8@ki>i>;lIi<dB&%X)t/thB&#vznoB8#(|jJk&%B88@@@Mx1hBBBBBB88*Zu|(n8B8XvvQB%&ut)t/hM&%/IiI~:i<<dBB*&~'^,pB8%%@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@B@B@%q! '~b%B8*j!!~;ii:Y8B8Y/t|f8BBwvvh%B8#put|/(//uYw#B%8%8bUvf/(|/(j0#%BBBXzX%B%C|1tfo%%M-l>ll<l(#8BBa<`.Iw%&B@B%@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@B%8p;'^;0B8@&w+i!!I!u8B%cpZhXBBWcua@@@BB%%%aCx|(tf(rb*c|ft/(/Uk8B%BB&@@BYXmBB#dZpjM@%kI>lii!0%%%%wI`.!O%&@BB@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@8B&%BW-',.)MB@#BC~i!;U%%%Ck0fM%BOvkBB&&8dM@@8&@BWpvzo*ZvO*B@88@&%#%Bk%B8zv8B&JcpwqBB*i;<ic%8BB*`'-h@%B%@8@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@B#L:`';X8WB%8Q?~aB%0/f/kB8hJw%@%&%/v%WLkB8BB&#JwhB@8%%#0WB0/8B*BBMzwB%Bx(tr8B%t_J8BBB&Ji.""c*BB@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@B@8Bo1'''lv&B%B%*@8M/ttz#B%B%BBB88tx&%tXB&c8kx#MmpBZQBp|M%Ot8%8%B@%%%&J|//J&B8W%@&%C>`^ ]k@BB@%@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B@@@Bo]`.'^1oB@&BWx|/j(|08&B@%%Btn8&/U%%o8UhQdowBBp%p/#%Q|&BB@BB8bn()|//kB@88Wx^''.~q@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B@@@%aj:`'`+%%%X(/(Uakvr8@@@%tu88tYB@#%coOwkkMBk%p(#%0/8B@@%p(dbw|j/|W%&c'`',(k%B%B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8@8%%%m];8B88*C/zo#u|oBBBBun88tY%Ba%Xo0q#QB@wBd/*B0f%@@@%ntdod|cb&BB%x+O8%%@%8BB@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@8@$%B@@B@Bonx)dB@%&B%W8bp%W|#M|ZkLo%xO8*q8%%&B&@B%j|rL&@@%BBB@B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B@@@@B@BBBB&hh%B8?Yo@8B@&@B%8%o#%BBB%%%%B@#Q/x8@Wp8&B%@BB@B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@B@@@BB@#I.'`',if&8B@BB@BB@@WX_:'  '`uBB@@B@@B@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
*/

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * Requirements:
     *
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     * - the caller must have allowance for ``sender``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        _transfer(sender, recipient, amount);

        uint256 currentAllowance = _allowances[sender][_msgSender()];
        require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
        unchecked {
            _approve(sender, _msgSender(), currentAllowance - amount);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal virtual {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(sender, recipient, amount);

        uint256 senderBalance = _balances[sender];
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[sender] = senderBalance - amount;
        }
        _balances[recipient] += amount;

        emit Transfer(sender, recipient, amount);

        _afterTokenTransfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }


    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}

library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(
        uint256 a,
        uint256 b,
        string memory errorMessage
    ) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

interface IUniswapV2Factory {
    event PairCreated(
        address indexed token0,
        address indexed token1,
        address pair,
        uint256
    );

    function createPair(address tokenA, address tokenB)
        external
        returns (address pair);
}

interface IUniswapV2Router02 {
    function factory() external pure returns (address);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external;
}

contract anubisDAO2POINT0 is ERC20, Ownable {
    using SafeMath for uint256;

    IUniswapV2Router02 public immutable uniswapV2Router;
    address public immutable uniswapV2Pair;
    address public constant deadAddress = address(0xdead);
    address public ETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

    bool private swapping;

    address public devWallet;

    uint256 public maxTransactionAmount;
    uint256 public swapTokensAtAmount;
    uint256 public maxWallet;

    bool public limitsInEffect = true;
    bool public tradingActive = false;
    bool public swapEnabled = false;

    uint256 public buyTotalFees;
    uint256 public buyDevFee;
    uint256 public buyLiquidityFee;

    uint256 public sellTotalFees;
    uint256 public sellDevFee;
    uint256 public sellLiquidityFee;

    /******************/

    // exlcude from fees and max transaction amount
    mapping(address => bool) private _isExcludedFromFees;
    mapping(address => bool) public _isExcludedMaxTransactionAmount;


    event ExcludeFromFees(address indexed account, bool isExcluded);

    event devWalletUpdated(
        address indexed newWallet,
        address indexed oldWallet
    );

    constructor() ERC20("AnubisDAO 2.0", "ANUBISDAO2.0") {
        IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(
            0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
        );

        excludeFromMaxTransaction(address(_uniswapV2Router), true);
        uniswapV2Router = _uniswapV2Router;

        uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
            .createPair(address(this), ETH);
        excludeFromMaxTransaction(address(uniswapV2Pair), true);


        uint256 _buyDevFee = 22;
        uint256 _buyLiquidityFee = 0;

        uint256 _sellDevFee = 22;
        uint256 _sellLiquidityFee = 0;

        uint256 totalSupply = 65_000_000 * 1e18;

        maxTransactionAmount =  totalSupply * 2 / 100; // 2% from total supply maxTransactionAmountTxn
        maxWallet = totalSupply * 2 / 100; // 2% from total supply maxWallet
        swapTokensAtAmount = (totalSupply * 5) / 10000; // 0.05% swap wallet

        buyDevFee = _buyDevFee;
        buyLiquidityFee = _buyLiquidityFee;
        buyTotalFees = buyDevFee + buyLiquidityFee;

        sellDevFee = _sellDevFee;
        sellLiquidityFee = _sellLiquidityFee;
        sellTotalFees = sellDevFee + sellLiquidityFee;

        devWallet = address(0x7E30554266e0a2da9D37Ace672C72fF170e7B905); 

        // exclude from paying fees or having max transaction amount
        excludeFromFees(owner(), true);
        excludeFromFees(address(this), true);
        excludeFromFees(address(0xdead), true);
        excludeFromFees(address(devWallet), true);
        

        excludeFromMaxTransaction(owner(), true);
        excludeFromMaxTransaction(address(this), true);
        excludeFromMaxTransaction(address(0xdead), true);
        excludeFromMaxTransaction(address(devWallet), true);

        /*
            _mint is an internal function in ERC20.sol that is only called here,
            and CANNOT be called ever again
        */
        _mint(msg.sender, totalSupply);
    }

    receive() external payable {}

    // once enabled, can never be turned off
    function enableTrading() external onlyOwner {
        tradingActive = true;
        swapEnabled = true;
    }

    // remove limits after token is stable
    function removeLimits() external onlyOwner returns (bool) {
        limitsInEffect = false;
        return true;
    }

    // change the minimum amount of tokens to sell from fees
    function updateSwapTokensAtAmount(uint256 newAmount)
        external
        onlyOwner
        returns (bool)
    {
        require(
            newAmount >= (totalSupply() * 1) / 100000,
            "Swap amount cannot be lower than 0.001% total supply."
        );
        require(
            newAmount <= (totalSupply() * 5) / 1000,
            "Swap amount cannot be higher than 0.5% total supply."
        );
        swapTokensAtAmount = newAmount;
        return true;
    }

    function updateMaxTxnAmount(uint256 newNum) external onlyOwner {
        require(
            newNum >= ((totalSupply() * 1) / 1000) / 1e18,
            "Cannot set maxTransactionAmount lower than 0.1%"
        );
        maxTransactionAmount = newNum * (10**18);
    }

    function updateMaxWalletAmount(uint256 newNum) external onlyOwner {
        require(
            newNum >= ((totalSupply() * 5) / 1000) / 1e18,
            "Cannot set maxWallet lower than 0.5%"
        );
        maxWallet = newNum * (10**18);
    }

    function excludeFromMaxTransaction(address updAds, bool isEx)
        public
        onlyOwner
    {
        _isExcludedMaxTransactionAmount[updAds] = isEx;
    }

    // only use to disable contract sales if absolutely necessary (emergency use only)
    function updateSwapEnabled(bool enabled) external onlyOwner {
        swapEnabled = enabled;
    }

    function updateBuyFees(
        uint256 _devFee,
        uint256 _liquidityFee
    ) external onlyOwner {
        buyDevFee = _devFee;
        buyLiquidityFee = _liquidityFee;
        buyTotalFees = buyDevFee + buyLiquidityFee;
        require(buyTotalFees <= 45, "Must keep fees at 49% or less ;)" );
    }

    function updateSellFees(
        uint256 _devFee,
        uint256 _liquidityFee
    ) external onlyOwner {
        sellDevFee = _devFee;
        sellLiquidityFee = _liquidityFee;
        sellTotalFees = sellDevFee + sellLiquidityFee;
        require(sellTotalFees <= 45, "Must keep fees at 30% or less ;)");
    }

    function excludeFromFees(address account, bool excluded) public onlyOwner {
        _isExcludedFromFees[account] = excluded;
        emit ExcludeFromFees(account, excluded);
    }

    function updateDevWallet(address newDevWallet)
        external
        onlyOwner
    {
        emit devWalletUpdated(newDevWallet, devWallet);
        devWallet = newDevWallet;
    }


    function isExcludedFromFees(address account) public view returns (bool) {
        return _isExcludedFromFees[account];
    }

    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal override {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        if (amount == 0) {
            super._transfer(from, to, 0);
            return;
        }

        if (limitsInEffect) {
            if (
                from != owner() &&
                to != owner() &&
                to != address(0) &&
                to != address(0xdead) &&
                !swapping
            ) {
                if (!tradingActive) {
                    require(
                        _isExcludedFromFees[from] || _isExcludedFromFees[to],
                        "Trading is not active."
                    );
                }

                // at launch if the transfer delay is enabled, ensure the block timestamps for purchasers is set -- during launch.
                //when buy
                if (
                    from == uniswapV2Pair &&
                    !_isExcludedMaxTransactionAmount[to]
                ) {
                    require(
                        amount <= maxTransactionAmount,
                        "Buy transfer amount exceeds the maxTransactionAmount."
                    );
                    require(
                        amount + balanceOf(to) <= maxWallet,
                        "Max wallet exceeded"
                    );
                }
                else if (!_isExcludedMaxTransactionAmount[to]) {
                    require(
                        amount + balanceOf(to) <= maxWallet,
                        "Max wallet exceeded"
                    );
                }
            }
        }

        uint256 contractTokenBalance = balanceOf(address(this));

        bool canSwap = contractTokenBalance >= swapTokensAtAmount;

        if (
            canSwap &&
            swapEnabled &&
            !swapping &&
            to == uniswapV2Pair &&
            !_isExcludedFromFees[from] &&
            !_isExcludedFromFees[to]
        ) {
            swapping = true;

            swapBack();

            swapping = false;
        }

        bool takeFee = !swapping;

        // if any account belongs to _isExcludedFromFee account then remove the fee
        if (_isExcludedFromFees[from] || _isExcludedFromFees[to]) {
            takeFee = false;
        }

        uint256 fees = 0;
        uint256 tokensForLiquidity = 0;
        uint256 tokensForDev = 0;
        // only take fees on buys/sells, do not take on wallet transfers
        if (takeFee) {
            // on sell
            if (to == uniswapV2Pair && sellTotalFees > 0) {
                fees = amount.mul(sellTotalFees).div(100);
                tokensForLiquidity = (fees * sellLiquidityFee) / sellTotalFees;
                tokensForDev = (fees * sellDevFee) / sellTotalFees;
            }
            // on buy
            else if (from == uniswapV2Pair && buyTotalFees > 0) {
                fees = amount.mul(buyTotalFees).div(100);
                tokensForLiquidity = (fees * buyLiquidityFee) / buyTotalFees; 
                tokensForDev = (fees * buyDevFee) / buyTotalFees;
            }

            if (fees> 0) {
                super._transfer(from, address(this), fees);
            }
            if (tokensForLiquidity > 0) {
                super._transfer(address(this), uniswapV2Pair, tokensForLiquidity);
            }

            amount -= fees;
        }

        super._transfer(from, to, amount);
    }

    function swapTokensForETH(uint256 tokenAmount) private {
        // generate the uniswap pair path of token -> weth
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = ETH;

        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // make the swap
        uniswapV2Router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
            tokenAmount,
            0, // accept any amount of ETH
            path,
            devWallet,
            block.timestamp
        );
    }

    function swapBack() private {
        uint256 contractBalance = balanceOf(address(this));
        if (contractBalance == 0) {
            return;
        }

        if (contractBalance > swapTokensAtAmount * 20) {
            contractBalance = swapTokensAtAmount * 20;
        }

        swapTokensForETH(contractBalance);
    }

}