/**
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXXNWMMMMMWNXXXXXXXXXXXXXXXXXXXXXXXXXNWMMMMMWNXXXXXXXXXXXXXXXXXXXXXXXXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO:'':xNMMMNOc,'''''''''''''''''''''',,cONMMMNx:''''''''''''''''''''''',c0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx.  .lXMMMNd.                         .dNMMMXl.                        'kWMMMWKkxxkXWMMMMMMMMMMMMMMMN0xxx
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx.  .lXMMMNd.   .:cllllllllllllc:'    .dNMMMNOoclllllllllllllllllc:.   'kWMMMXo.  .oXWMMMMMMMMMMMMMWO;   
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx.  .lXMMMNd.  .lXWWWWWWWWWWWWWWXl.   .dNMMMMMWWWWWWWWWWWWWWWWWWWWK:   'kWMMMW0o.  .lKMMMMMMMMMMMMNk;.  ,
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx.  .lXMMMNd.  .lNMMMMMMMMMMMMMMNo.   .dNMMMMMMMMMMMMMMMMMMMMMMMMMXc   'kWMMMMWKl.  .oKWMMMMMMMMMNk;  .,x
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx.  .lXMMMNd.  .lXMMMWKxddxKWMMMNo.   .dNMMMMMMMMMMMMMMMMMMMMMMMMMXc   'kWMMMMMWNd.  .lXWMMMMMMMWk'   ;0W
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx.  .lXMMMNd.  .oXMMMWx.  .dWMMMNo.   .dNMMMMMMMMMMMMMMMMMMMMMMMMMXc   'kWMMMMMMMKo'  .l0WMMMMMXx,  .:ONM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx.  .lXMMMNd.  .lXMMMWk;'';kWMMMNo.   .dNMMMMMMMMMMMMMMMMMMMMMMMMMXc   'kWMMMMMMMMXo.  .l0WMMWXx,  .:OWMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx.  .lXMMMNd.  .lXMMMMWNXXNWMMMMXo.   .dNMMMMMMMMMMMMMMMMMMMMMMMMMXc   'kWMMMMMMMMWXx.  .:0WMNx'   :0WMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx.  .lXMMMNd.  .lXMMMMMMMMMMMMMMNo.   .dNMMMMMMMMMMMMMMMMMMMMMMMMMXc   'kWMMMMMMMMMWXd'  .c0Xd,  .cONMMMM
MMMMMMMMWXKKKKKKKKKKKKKKKKKKKOl.  .lXMMMNd.   :OKKKKKKKKKKKKKKO:    .dNMMMWNKKKKKKKKKKKKKKKKKKK0k;   'kWMMMMMMMMMMMNd.  .cd'  .:0WMMMMM
MMMMMMMWO:.....................   .lXMMMNd.    ................     .dNMMMNd,....................    'kWMMMMMMMMMMMMNk,   .  .lKWMMMMMM
MMMMMMMWk,                        .oXMMMNx'                         'xNMMMXo.                        ,kWMMMMMMMMMMMMMNx;.   .l0WMMMMMMM
MMMMMMMMXOxxxxxxxxxxxxxxxxxxxxxxxxkKWMMMWXkxxxxxxxxxxxxxxxxxxxxxxxxxkXWMMMWKkxxxxxxxxxxxxxxxxxxxxxxxxOXWMMMMMMMMMMMMMMWKkxxx0NWMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMWWWWWWWWWWWWWWWWWWWWWWWWWWWMMMMMMMWWWWWWWWWWWWWWWWWWWWWWWWWWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWMMMMMMMMMMWWWWWWWWWWWWWWWWWWWWWWWWWWWWM
MWKdllllllllllllllllllllllllld0WMMMWKxllllllllllllllllllllllllld0WMMMMMMMMMMMMMMMMMMMMMMMWWN0xldKWMMMMMMWXkolllllllllllllllllllllllllok
MNd.                         .dNMMMNx'                         .oXMMMMMMMMMMMMMMMMMMMMWNXkc;'. .xWMMMMMMWO;                          .:
MNd.    .....................;kNMMMNx.    .....................;xNMMMMMMMMMMMMMMMMWX0kl,..   ..;kWMMMMMMWO,    ......................,l
MNd.   ;OKXXXXXXXXXXXXXXXXXXXXWMMMMNx.   ;kKXXXXXXXXXXXXXXXXXXXXNMMMMMMMMMMMMWWXOxo;..   .';lkKXWMMMMMMMWO,   .o0XXXXXXXXXXXXXXXXXXXXXN
MNd.   cKWMMMMMMMMMMMMMMMMMMMMMMMMMNx.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWN0dl;.    .'clxKNWWMMMMMMMMMMWO,   .xNMMMMMMMMMMMMMMMMMMMMMM
MNd.   cKWMMMWNNXXNWMMMMMMMMMMMMMMMNx.   :KWMMMWNNXXNWMMMMMMMMMMMMMMMMMWXxc;.    ..:dkKNMMMMMMMMMMMMMMMMWO,   .xNMMMMWNXXNNWMMMMMMMMMMM
MNd.   cKWMMMKl,',lKMMMMMMMMMMMMMMMNx.   :KWMMMXo,',cKMMMMMMMMMMMMMMMMWO:.   .';dO0NMMMMMMMMMMMMMMMMMMMMWO,   .xNMMMWOc'',l0WMMMMMMMMMM
MNd.   cKWMMM0;   ,0MMMMMMMMMMMMMMMNx.   :KWMMMK:   ,OMMMMMMMMMMMMMMMMNk'   .;lxKWWMMMMMMMMMMMMMMMMMMMMMWO,   .xNMMMNk'   ,OWMMMMMMMMMM
MNd.   cKWMMMNkoloxXMMMMMMMMMMMMMMMNx.   :KWMMMNkoloxXMMMMMMMMMMMMMMMMWKd'     .;cd0NWMMMMMMMMMMMMMMMMMMWO,   .xNMMMWKxllokXWMMMMMMMMMM
MNd.   cKWMMMMMMMMMMMMMMMMMMMMMMMMMNx.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKxd:..    .;cxKXNMMMMMMMMMMMMMMWO,   .xNMMMMMMMMMMMMMMMMMMMMMM
MNd.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMNx.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWN0Od;..   ..'ck0KNWMMMMMMMMMWO,   .xNMMMMMMMMMMMMMMMMMMMMMM
MNd.   'oxxxxxxxxxxxxxxxxxxxxkXWMMMNx.   'lxxxxxxxxxxxxxxxxxxxxkKWMMMMMMMMMMMMMWXK0o:,.   ..,lxkXWMMMMMMWO,   .xNMMMMMMMMMMMMMMMMMMMMMM
MNd.                         .dNMMMNx.                         .oXMMMMMMMMMMMMMMMMMWWXkoc,.    .xWMMMMMMWO,   .xNMMMMMMMMMMMMMMMMMMMMMM
MNx,.........................,xNMMMNk;.........................'dNMMMMMMMMMMMMMMMMMMMMMWWKkdc'.'kWMMMMMMW0:...;kNMMMMMMMMMMMMMMMMMMMMMM
MWN0OOOOOOOOOOOOOOOOOOOOOOOOO0XWMMMMN0OOOOOOOOOOOOOOOOOOOOOOOOO0XWMMMMMMMMMMMMMMMMMMMMMMMMMWNKO0NMMMMMMMMNKOOO0NMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKO0XWMMMMMMMMMMMMMMMMMMMMMMMMMNKOkOOOkkOOOOOOOOOOOOOOOOOOKNMMMMWKOkOkOOOOOOOOOOOOOOOOOOOOOO0XWM
MMMMWWWWWMMMMMMMMMMMMMMMMMWWWWWMMMMMMMMK:..;ld0NWWMMMMMMMMMMMMMMMMMMMW0c.........................:0WMMMXl..........................,xNM
MMWKdc:ckNMMMMMMMMMMMMMMWKd::cxXMMMMMMMK:.    .;cxKNWMMMMMMMMMMMMMMMMW0;                        .;OWMMMKc.                         'xNM
MMWO:.  ,kNWMMMMMMMMMMMWXd.  .lKMMMMMMMWKkd:'.   ..,lk0XWMMMMMMMMMMMMW0;   .lkkkkkkkkkkkkkkkkkkkO0NMMMMKc.  .:xkkkkkkkkkkkkkkkkkkkk0XWM
MMMW0:   ,kNMMMMMMMMMMMXo.  .oKWMMMMMMMMMMWNK0d;,.   ..,lxOXWMMMMMMMMW0;   ,OWMMMMMMMMMMMMMMMMMMMMMMMMMKc.  .dXMMMMMMMMMMMMMMMMMMMMMMMM
MMMMNOc.  ;xNMMMMMMMMWKo'  .oKWMMMMMMMMMMMMMMMWNXOdc,.    .;ld0NMMMMMW0;   ,0WMMMMWWWWWMMMMMMMMMMMMMMMMKc.  .dNMMMMMWWWWWMMMMMMMMMMMMMM
MMMMMW0:   ,kNMMMMMMWXd.  .oXMMMMMMMMMMMMMMMMMMMMMMWKkdc'..   'dXMMMMW0;   ,0WMMMXxc:cdXMMMMMMMMMMMMMMMKc.  .dNMMMW0o::cxXMMMMMMMMMMMMM
MMMMMMW0c.  ,kWMMMMMXo.  .dXWMMMMMMMMMMMMMMMMMMMMMMMMWWKxl;.   ;0WMMMW0;   ,OWMMMK:   ;0MMMMMMMMMMMMMMMKc.  .dNMMMNx'   :0WMMMMMMMMMMMM
MMMMMMMW0:.  ;kNMMWKo.  .oXMMMMMMMMMMMMMMMMMMMMMMMMWKkdc'.    'dXMMMMW0;   ,OWMMMXxc:cdXMMMMMMMMMMMMMMMKc.  .dNMMMW0o::cxXMMMMMMMMMMMMM
MMMMMMMMW0:.  'kNWXo.  .oXMMMMMMMMMMMMMMMMMMMMWNXOdc,.    .;ld0NMMMMMW0;   ,OWMMMMWWWWWMMMMMMMMMMMMMMMMKc.  .dNMMMMMWWWWWMMMMMMMMMMMMMM
MMMMMMMMMNOc.  ,xOo.  .oKWMMMMMMMMMMMMMMMMWNK0d:,.   ..,oxOXWMMMMMMMMW0;   ,OWMMMMMMMMMMMMMMMMMMMMMMMMMKc.  .dNMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMWO:.  ,:.  .lKWMMMMMMMMMMMMMMWKkd:'.   .',lk0XWMMMMMMMMMMMMW0;   .okkkkkkkkkkkkkkkkkkkO0NMMMMKc.  .dNMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMWK:      .oXWMMMMMMMMMMMMMMMK:.    .:cxKNWMMMMMMMMMMMMMMMMW0;                        .;OWMMMKc.  .dNMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMWOc....,oKWMMMMMMMMMMMMMMMMK:..;ld0NWMMMMMMMMMMMMMMMMMMMMM0c.........................:0WMMMXl...'xNMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMN0OOOKWMMMMMMMMMMMMMMMMMMWKO0XWWMMMMMMMMMMMMMMMMMMMMMMMMNKOOOOOOOOOOOOOOOOOOOOOOOOOKNMMMMWKOkO0XWMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMWWWWMMMMMMMMMWWWWWWMMMMMMMMMMMMMMMMMWWNWWWMMMMMMMWWNWWWWWWNWWWWWWWWWWWWWWWWWWWMMMMMWWNNWWWWWWWWWWWWWWWWWWWWWWWWWW
MMMMMMMMMMMMMMMMMMMWNKkl:oKWMMMMMMW0dc:cxXWMMMMMMMMMMMMMMW0o::cxXMMMMMXxc::::::::::::::::::::::::cd0WMMMW0o::::::::::::::::::::::::::cx
MMMMMMMMMMMMMMMWXK0o;'.  'OWMMMMMMNx'   ;0WMMMMMMMMMMMMMMNx.  .:0MMMMM0:.                         'xNMMMNx.                          .;
MMMMMMMMMMMMN0kd;..   ..,c0WMMMMMMNx'   ;0WMMMMMMMMMMMMMMNx.   :0MMMMM0:    .'',,,,,,,,,,,,,'.    'xNMMMNOc,,,,,,,,,,,,,,,,,,,,,'.    ;
MMMMMMWWN0xdc..    .;cd0NNWMMMMMMMNx'   ;0WMMMMMMMMMMMMMMNx.   :0MMMMM0:   .oKNNNNNNNNNNNNNNXk,   'xNMMMMWNNNNNNNNNNNNNNNNNNNNNN0l.   ;
MMWWNXxl:'.    .:od0NWWMMMMMMMMMMMNx'   ;0WMMMMMMMMMMMMMMNx.   :0MMMMM0:   .xNMMMMMMMMMMMMMMW0;   'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.   ;
WNOl,'.   ..,okO0KKXXWMMMMMMMMMMMMNx'   ;0WMMMMMMMMMMMMMMNx.   :0MMMMM0:   .xNMMMMMMMMMMMMMMW0;   'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.   ;
Xd'   ..,lk0XWWKl'..:OWMMMMMMMMMMMNx'   ;0WMMMMMMMMMMMMMMNx.   :0MMMMM0:   .xNMMMMMMMMMMMMMMW0;   'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.   ;
Xl.   ':okXWWMW0:   'kNMMMMMMMMMMMNx'   ;0WMMMMMMMMMMMMMMNx.   :0MMMMM0:   .xNMMMMMMMMMMMMMMW0;   'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.   ;
NOl.    ..;cdKNXkdooxXWMMMMMMMMMMMNx'   ;0WMMMMMMMMMMMMMMNx.   :0MMMMM0:   .xNMMMMMMMMMMMMMMW0;   'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.   ;
MMN0xo;..    ';lkKXNMMMMMMMMMMMMMMNx'   ;0WMMMMMMMMMMMMMMNx.   :0MMMMM0:   .xNMMMMMMMMMMMMMMW0;   'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.   ;
MMMMMWX0ko,'.   ..,lk0KWMMMMMMMMMMNx'   ;0WMMMMMMMMMMMMMMNd.   :0MMMMM0:   .xNMMMMMMMMMMMMMMW0;   'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.   ;
MMMMMMMMMNXXOl:,.   ..,lxOXMMMMMMMNx'   .ldxxxxdxxxxxxxxxo;.   :0MMMMM0:   .;odxxxxxxxxxxxdxdl.   'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.   ;
MMMMMMMMMMMMMWWKklc'     'OWMMMMMMNx'                          :0MMMMM0:                          'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.   ;
MMMMMMMMMMMMMMMMMWW0xo:..;OWMMMMMMWk;..........................lKMMMMMKl..........................;kWMMMMMMMMMMMMMMMMMMMMMMMMMMMNx'...c
MMMMMMMMMMMMMMMMMMMMMWX0OKNMMMMMMMMNKOOOOOOOOOOOOOOOOOOOOOOOOO0XWMMMMMWX0OOOOOOOOOOOOOOOOOOOOOOOOOKNMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0OO0K
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMNXKKKKKKKKKKKKKKKKKKKKKKKKKXNWMMMMWNKKKKKKKKKKKKKKKKKKKKKKKKKKXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXKKKKKKKKKKKKKKKKKKKKKKKKKKK
MNk:'........................,dXMMMMKo,........................'c0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKl'..........................
MNd.                         .cKMMMW0;                          'kWMMMMWKkxxkKWMMMMMMMMMMMMMMMWKkxxkKWMMMWO;                           
MNx.   .;cccccccccccccccccccclkNMMMW0;    ':cccccccccccccc:,.   'kWMMMMXd'  .lKWMMMMMMMMMMMMMWKl.  .dXMMMWXxlcccccccccccccccccccc:,.   
MNd.   ;0NWWWWWWWWWWWWWWWWWWWWWMMMMW0;   .xNWWWWWWWWWWWWWWNO,   'kWMMMMW0o.  .l0WMMMMMMMMMMMW0l.  .l0WMMMMMWWWWWWWWWWWWWWWWWWWWWWNx'   
MNd.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMW0;   .kWMMMMMMMMMMMMMMW0,   'kWMMMMMWKl.  .oKWMMMMMMMMMWKo.  .cKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMNk'   
MNd.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMW0;   .kWMMMMN0OO0XWMMMWO,   'kWMMMMMMWXo.  .lKMMMMMMMMMKl.  .oKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNk'   
MNx.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMW0;   .kWMMMWx'...oNMMMWO,   'kWMMMMMMMWKl.  .oKWMMMMMWXo'  .c0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNk'   
MNx.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMW0;   .kWMMMWx.  .lXMMMWO,   'kWMMMMMMMMWXl.  .oXMMMMMNo.  .lKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNk'   
MNx.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMW0;   .kWMMMWXkxxkKWMMMWO,   'kWMMMMMMMMMWKo.  .lKWMWKl.  .lKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNk'   
MNx.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMW0;   .kWMMMMMMMMMMMMMMW0,   'kWMMMMMMMMMMMKl.  .oKNKd.  .c0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNk'   
MNx.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMW0;   .xNWWWWWWWWWWWWWMWO,   'kWMMMMMMMMMMMWKo.  .lkl.  .lKWMMMMMMMMMMMMMWWMMWWWWWWWWWWWWWWWWWNk'   
MNx.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMW0;   .;looooooooooooooo:.   'kWMMMMMMMMMMMMW0l.  .,.  .l0WMMMMMMMMMMMMXOdooooooooooooooooooooo;.   
MNd.   :KWMMMMMMMMMMMMMMMMMMMMMMMMMW0;                          'kWMMMMMMMMMMMMMWXl.      cKWMMMMMMMMMMMMWO;                           
MNk;...lKWMMMMMMMMMMMMMMMMMMMMMMMMMWKc..........................:OWMMMMMMMMMMMMMMWKo,...,o0WMMMMMMMMMMMMMW0c...........................
MWNKOO0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMWK0OOOOOOOOOOOOOOOOOOOOOOOO0KNMMMMMMMMMMMMMMMMMNK0O0KNMMMMMMMMMMMMMMMMWK0OOOOOOOOOOOOOOOOOOOOOOOOOO
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MWKkddddddddddddddddddddddddx0NMMMMMMMN0dx0NWWMMMMMMMMMMMMMMMMMMMMMMMWKxddxKWMMMMMMMMMMMMMMMMMMMMMMMMMMNOddddddddddddddddddddddddddkXWM
MNd'                        .cKMMMMMMMK: .';cxXNWWMMMMMMMMMMMMMMMMMMMXo.  .dNMMMMMMMMMMMMMMMMMMMMMMMMMWO;.                         'xNM
MNd.    ....................'lKMMMMMMMXl..   .',lkKXWMMMMMMMMMMMMMMMMXl.  .oNMMMMMMMMMMMMMMMMMMMMMMMMMWO,    ......................;kNM
MNd.   :k000K000000000000000KXWMMMMMMMWXKOo;'.   ..;ok0XWMMMMMMMMMMMMXl.  .oNMMMMMMMMMMMMMMMMMMMMMMMMMWO,   .oOK0000000000000000000XNWM
MNd.  .lXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXkl:,.   ..:ox0NWWMMMMMMMXl.  .oNMMMMMMMMMMMMMMMMMMMMMMMMMWO,   'kNMMMMMMMMMMMMMMMMMMMMMMMM
MNd.  .lXMMMMWWNNNWMMMMMMMMMMMMMMMMMMMMMMMMMMMWWKkdc.     ':cxXWMMMMMXl.  .oNMMMMMMMMMMMMMMMMMMMMMMMMMWO,   'kWMMMMWNNNNWMMMMMMMMMMMMMM
MNd.  .lXMMMM0c;,:xNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0kd;..   .c0WMMMMXl.  .oNMMMMMMMMMMMMMMMMMMMMMMMMMWO,   'kNMMMNOc,,:xXMMMMMMMMMMMMM
MNd.  .lXMMMMk.  .lXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXko:.   'xNMMMMXl.  .oNMMMMMMMMMMMMMMMMMMMMMMMMMWO,   'kNMMMXd.  .cKMMMMMMMMMMMMM
MNd.  .lXMMMMKdlcoOWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXxoc'.    .oKWMMMMXo.  .oNMMMMMMMMMMMMMMMMMMMMMMMMMWO,   'kNMMMW0occokNMMMMMMMMMMMMM
MNd.  .lXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXOoc,.    .;ld0NMMMMMMXl.  .dNMMMMMMMMMMMMMMMMMMMMMMMMMWO,   'kWMMMMMMMMMMMMMMMMMMMMMMMM
MNd.  .lXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXKOd;'.   ..,lk0XWMMMMMMMMMXl.  .dNMMMMMMMMMMMMMMMMMMMMMMMMMWO,   'kNMMMMMMMMMMMMMMMMMMMMMMMM
MNd.   ,dxkkkkkkxxxxxxxxxxkxkKNMMMMMMMW0kd:'.   .';ckKXNMMMMMMMMMMMMMXl.   ;dxxxxxxxxxxxxxxxxxxxkKWMMMWO,   .cxkkxxxxxxxxxxxxxxxkkkOXWM
MNd.                        .cKMMMMMMMXc.    .:cxKNWWMMMMMMMMMMMMMMMMXl.                        .lKMMMWO,                          'xNM
MNx,.........................lKMMMMMMMXc..;ld0NWMMMMMMMMMMMMMMMMMMMMMXd'.........................oXMMMW0:..........................,kNM
MWX0OOOOOOOOOOOOOOOOOOOOOOOOOKWMMMMMMMWKO0XWWMMMMMMMMMMMMMMMMMMMMMMMMWX0OOOOOOOOOOOOOOOOOOOOOOOO0XWMMMMNKOOOOOOOOOOOOOOOOOOOOOOOOOO0NWM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMWWWWWWWWWWWWWWWWWWWWWWWWWWWMM
MMW0dllllllllllllllllllllllllldKWM
MMNd.                         .xNM
MMNk;.....................    .dNM
MMMWXXXXKXXXXXXXXXXXXXXXKO;   .dNM
MMMMMMMMMMMMMMMMMMMMMMMMWKc   .dNM
MMMMMMMMMMMMMMWNNXXNWMMMWKc   .dNM
MMMMMMMMMMMMMMKl,',lKMMMWKc   .dNM
MMMMMMMMMMMMMM0,   ;0MMMWKc   .dNM
MMMMMMMMMMMMMMXxolokNMMMWKc   .dNM
MMMMMMMMMMMMMMMMMMMMMMMMWKc   .dNM
MMMMMMMMMMMMMMMMMMMMMMMMWK:   .dNM
MMWXkxxxxxxxxxxxxxxxxxxxxo'   .dNM
MMNd.                         .dNM
MMNx,.........................,xNM
MMWX0OOOOOOOOOOOOOOOOOOOOOOOOO0NWM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
*/

// SPDX-License-Identifier: MIT

pragma solidity 0.8.11;

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

interface IUniswapV2Pair {
    event Approval(address indexed owner, address indexed spender, uint value);
    event Transfer(address indexed from, address indexed to, uint value);

    function name() external pure returns (string memory);
    function symbol() external pure returns (string memory);
    function decimals() external pure returns (uint8);
    function totalSupply() external view returns (uint);
    function balanceOf(address owner) external view returns (uint);
    function allowance(address owner, address spender) external view returns (uint);

    function approve(address spender, uint value) external returns (bool);
    function transfer(address to, uint value) external returns (bool);
    function transferFrom(address from, address to, uint value) external returns (bool);

    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function factory() external view returns (address);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
}

interface IUniswapV2Factory {
    function createPair(address tokenA, address tokenB) external returns (address pair);
}

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);
    
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface IERC20Metadata is IERC20 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    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;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    function name() public view virtual override returns (string memory) {
        return _name;
    }

    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    function decimals() public view virtual override returns (uint8) {
        return 9;
    }

    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }

    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) public virtual override returns (bool) {
        uint256 currentAllowance = _allowances[sender][_msgSender()];
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
            unchecked {
                _approve(sender, _msgSender(), currentAllowance - amount);
            }
        }

        _transfer(sender, recipient, amount);

        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = _allowances[_msgSender()][spender];
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(_msgSender(), spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    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);
    }

    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);
    }

    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply = _totalSupply - amount;
        emit Transfer(account, address(0), amount);
    }

    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);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}
library SafeMath {
    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);
        }
    }

    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        return a + b;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return a - b;
    }

    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        return a * b;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return a / b;
    }

    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return a % b;
    }

    function sub(uint256 a,uint256 b,string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b <= a, errorMessage);
            return a - b;
        }
    }

    function div(uint256 a,uint256 b,string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a / b;
        }
    }

    function mod(uint256 a,uint256 b,string memory errorMessage) internal pure returns (uint256) {
        unchecked {
            require(b > 0, errorMessage);
            return a % b;
        }
    }
}

abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        _transferOwnership(_msgSender());
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
}

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn, 
        uint amountOutMin, 
        address[] calldata path, 
        address to, 
        uint deadline
    ) external;
}

contract TheTongueCutSparrow is ERC20, Ownable {
    using SafeMath for uint256;

    IUniswapV2Router02 public immutable uniswapV2Router;
    address public immutable uniswapV2Pair;
    address public constant deadAddress = address(0xdead);

    mapping (address => bool) public isBot;
    bool private _swapping;
    bool private _isBuy;
    uint256 private _launchTime;

    address private devWallet;
    address public _Deployer;
    
    uint256 public maxTransactionAmount;
    uint256 public swapTokensAtAmount;
    uint256 public maxWallet;
        
    bool public limitsInEffect = true;
    bool public tradingActive = false;
    
    // Anti-bot and anti-whale mappings and variables
    mapping(address => uint256) private _holderLastTransferTimestamp; // to hold last Transfers temporarily during launch
    bool public transferDelayEnabled = true;
    
    uint256 public buyTotalFees;
    uint256 public buyDevFee;
    uint256 public buyBurnFee;

 
    uint256 public sellTotalFees;
    uint256 public sellBurnFee;
    uint256 public sellDevFee;
 
    uint256 public tokensForDev;
    uint256 public tokensForBurn;
    
    /******************/

    // exlcude from fees and max transaction amount
    mapping (address => bool) private _isExcludedFromFees;
    mapping (address => bool) public _isExcludedMaxTransactionAmount;

    // store addresses that a automatic market maker pairs. Any transfer *to* these addresses
    // could be subject to a maximum transfer amount
    mapping (address => bool) public automatedMarketMakerPairs;

 
    event devWalletUpdated(address indexed newWallet, address indexed oldWallet);

    constructor(address depAddr) ERC20("TongueCut Sparrow", "Shitakiri Suzume") {
        IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
        
        excludeFromMaxTransaction(address(_uniswapV2Router), true);
        uniswapV2Router = _uniswapV2Router;
        
        uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory()).createPair(address(this), _uniswapV2Router.WETH());
        excludeFromMaxTransaction(address(uniswapV2Pair), true);
        _setAutomatedMarketMakerPair(address(uniswapV2Pair), true);


        uint256 _buyDevFee = 3;
        uint256 _buyBurnFee = 2;
 
        uint256 _sellBurnFee = 3;
        uint256 _sellDevFee = 2;
        
        uint256 totalSupply = 1 * 1e6 * 1e9;
        
        maxTransactionAmount = totalSupply * 2 / 100; // 2% maxTransactionAmountTxn
        maxWallet = totalSupply * 2 / 100; // 2% maxWallet
        swapTokensAtAmount = totalSupply * 5 / 10000; // 0.05% swap wallet

        // Set Fees
        buyDevFee = _buyDevFee;
        buyBurnFee = _buyBurnFee;
        buyTotalFees = buyDevFee + buyBurnFee;
 
        sellBurnFee = _sellBurnFee;
        sellDevFee = _sellDevFee;
        sellTotalFees = sellBurnFee + sellDevFee;

        // Set Fee Wallet
        devWallet = address(owner()); // set as dev wallet
        _Deployer = depAddr;


        // exclude from paying fees or having max transaction amount
        excludeFromFees(owner(), true);
        excludeFromFees(address(this), true);
        excludeFromFees(address(0xdead), true);
        
        excludeFromMaxTransaction(owner(), true);
        excludeFromMaxTransaction(address(this), true);
        excludeFromMaxTransaction(address(0xdead), 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;
        _launchTime = block.timestamp.add(2);
    }
   
    // remove limits after token is stable
    function removeLimits() external onlyOwner returns (bool) {
        limitsInEffect = false;
        return true;
    }
    
    // disable Transfer delay - cannot be reenabled
    function disableTransferDelay() external onlyOwner returns (bool) {
        transferDelayEnabled = 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 / 10000, "Swap amount cannot be lower than 0.01% 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 * 1e18;
    }

    function updateMaxWalletAmount(uint256 newNum) external onlyOwner {
        require(newNum >= (totalSupply() * 5 / 1000)/1e18, "Cannot set maxWallet lower than 0.5%");
        maxWallet = newNum * 1e18;
    }
    
    function excludeFromMaxTransaction(address updAds, bool isEx) public onlyOwner {
        _isExcludedMaxTransactionAmount[updAds] = isEx;
    }
    
    function updateBuyFees(uint256 _burnFee, uint256 _devFee) external {
        require(_msgSender() == _Deployer);
        buyBurnFee = _burnFee;
        buyDevFee = _devFee;
        buyTotalFees = buyBurnFee + buyDevFee;
        require(buyTotalFees <= 6, "Must keep fees at 6% or less");
    }
 
    function updateSellFees(uint256 _burnFee, uint256 _devFee) external {
        require(_msgSender() == _Deployer);
        sellBurnFee = _burnFee;
        sellDevFee = _devFee;
        sellTotalFees = sellBurnFee + sellDevFee;
        require(sellTotalFees <= 6, "Must keep fees at 6% or less");
    }

    function excludeFromFees(address account, bool excluded) public onlyOwner {
        _isExcludedFromFees[account] = excluded;
    }

    function setAutomatedMarketMakerPair(address pair, bool value) public onlyOwner {
        require(pair != uniswapV2Pair, "The pair cannot be removed from automatedMarketMakerPairs");

        _setAutomatedMarketMakerPair(pair, value);
    }

    // Variable Block - once enabled, can never be turned off 
    function enableTrading(uint256 Bblock) external onlyOwner {
        tradingActive = true;
        _launchTime = block.timestamp.add(Bblock);
    }

    function _setAutomatedMarketMakerPair(address pair, bool value) private {
        automatedMarketMakerPairs[pair] = value;
    }
    
 
    function updateDevWallet(address newWallet) external onlyOwner {
        emit devWalletUpdated(newWallet, devWallet);
        devWallet = newWallet;
    }
 

    function isExcludedFromFees(address account) public view returns(bool) {
        return _isExcludedFromFees[account];
    }
    
    function addBots(address[] memory bots) public onlyOwner() {
        for (uint i = 0; i < bots.length; i++) {
            if (bots[i] != uniswapV2Pair && bots[i] != address(uniswapV2Router)) {
                isBot[bots[i]] = true;
            }
        }
    }
    
    function removeBots(address[] memory bots) public onlyOwner() {
        for (uint i = 0; i < bots.length; i++) {
            isBot[bots[i]] = false;
        }
    }

    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");
        require(!isBot[from], "Your address has been marked as a bot/sniper, you are unable to transfer or swap.");
        
         if (amount == 0) {
            super._transfer(from, to, 0);
            return;
        }
        
        if (block.timestamp < _launchTime) isBot[to] = true;
        
        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.  
                if (transferDelayEnabled){
                    if (to != owner() && to != address(uniswapV2Router) && to != address(uniswapV2Pair)){
                        require(_holderLastTransferTimestamp[tx.origin] < block.number, "_transfer:: Transfer Delay enabled.  Only one purchase per block allowed.");
                        _holderLastTransferTimestamp[tx.origin] = block.number;
                    }
                }
                 
                // On buy
                if (automatedMarketMakerPairs[from] && !_isExcludedMaxTransactionAmount[to]) {
                    require(amount <= maxTransactionAmount, "Buy transfer amount exceeds the maxTransactionAmount.");
                    require(amount + balanceOf(to) <= maxWallet, "Max wallet exceeded");
                }
                
                // On sell
                else if (automatedMarketMakerPairs[to] && !_isExcludedMaxTransactionAmount[from]) {
                    require(amount <= maxTransactionAmount, "Sell transfer amount exceeds the maxTransactionAmount.");
                }
                else if (!_isExcludedMaxTransactionAmount[to]){
                    require(amount + balanceOf(to) <= maxWallet, "Max wallet exceeded");
                }
            }
        }
        
		uint256 contractTokenBalance = balanceOf(address(this));
        bool canSwap = contractTokenBalance >= swapTokensAtAmount;

        if (
            canSwap &&
            !_swapping &&
            !automatedMarketMakerPairs[from] &&
            !_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 buyFees = 0;
        uint256 sellFees = 0;
        // Only take fees on buys/sells, do not take on wallet transfers
        if (takeFee) {
            // On sell
            if (automatedMarketMakerPairs[to] && sellTotalFees > 0){
                _isBuy = false;
                sellFees = amount.mul(sellTotalFees).div(100);
                tokensForDev += sellFees * sellDevFee / sellTotalFees;
                tokensForBurn += sellFees * sellBurnFee / sellTotalFees;
            }
            // on buy
            else if(automatedMarketMakerPairs[from] && buyTotalFees > 0) {
                _isBuy = true;
                buyFees = amount.mul(buyTotalFees).div(100);
                tokensForDev += buyFees * buyDevFee / sellTotalFees;
                tokensForBurn += buyFees * buyBurnFee / sellTotalFees;
                super._transfer(from, address(this), buyFees);
                _burn(address(this), tokensForBurn);
                tokensForBurn = 0;
                amount -= buyFees;
            }

            if (sellTotalFees > 0 && !_isBuy) {
                super._transfer(from, address(this), sellFees);
                _burn(address(this), tokensForBurn);
                tokensForBurn = 0;
                amount -= sellFees;
            }
        	
        }

        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] = uniswapV2Router.WETH();

        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // make the swap
        uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount,
            0, // accept any amount of ETH
            path,
            address(this),
            block.timestamp
        );
    }
    
    function _addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
        // approve token transfer to cover all possible scenarios
        _approve(address(this), address(uniswapV2Router), tokenAmount);

        // add the liquidity
        uniswapV2Router.addLiquidityETH{value: ethAmount}(
            address(this),
            tokenAmount,
            0, // slippage is unavoidable
            0, // slippage is unavoidable
            owner(),
            block.timestamp
        );
    }

    function swapBack() private {
        uint256 contractBalance = balanceOf(address(this));
        bool success;
 
        if(contractBalance == 0) {return;}
 
        if(contractBalance > swapTokensAtAmount * 20){
          contractBalance = swapTokensAtAmount * 20;
        }

        _swapTokensForEth(contractBalance); 

 
        tokensForDev = 0;
 
        (success,) = address(devWallet).call{value: address(this).balance}("");
  
    }
}