// SPDX-License-Identifier: MIT
/**
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNK0kxxkk0KXNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0d:'..     ...,lkKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo;.                .:xXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0l.                      ,dKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXkc.                          'o0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKOkOOOOKNWWMMMMMMMMMMMMMMMMMMMMMMMWNOl'.                              .:xKNMMMMMMMMMMMMMMMMMMMMMMMWNX0OkkkOOOKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo:'.      .',;lx0XNWMMMMMMMMMMMMMWN0xl,.                                    .;okKNWMMMMMMMMMMMMWNNKko:,..       .':d0NWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXd,.                ..,:lodxO000Oxddl:'.                                            .':lodxO0Okxddoc,..                 .;xXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNk,                            ...                                                            .                              ;OWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMKc.                                          ..',,,,,;:cclllcllllccclllc::cc:;,,,'...                                          .dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK:                                 ...,;;:cllccllllllcclccclllccccccccccccccllcclllllccllc:;;,...                                .lXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK:                           ..';ccllllllccccccloodxxkkOO00KKKKKXXXXKKXXKK0000Okkxddolllcccccllllolcc:,..                          .oNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXc                      .',:ccllcccccllodxO0KXNNWWWMMWWWWWWNNNXXXXXXXXXXXXXNNNNWMMMMWWWWNNXK0Oxdollcccllllclc,..                     .dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKc.                 .';cllllccccodkOKXNWWWMMWNNX0Okkdolc:;;;,,''............''';kWMXxlodxkO0KXNWWWWNXKOkdlcccccllll:'.                 .lXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWk,              .';clllc:ccoxOKXNWMMMMMMMMMXd:,'..                              .xWMk.      ...,;:ldkKWMMWWNXKOdoccccllol;'.              :0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo.           .,:cllc::cox0XNWMMMWWWNNNWWMMMMX:                          .;:;;;;,,c0WWd.              .xWMMWWWMMMMWNX0kolccclll:,.           .dXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo'         .,clllc:clxOXNWMWWNX0kdlc;;,,;cd0WMWx'.';:clod;              ..oNWWWWWWNNWMXc               ,KMMMMWNXK000KXNWWWX0xoc:clllc,.         ,dKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXkc.        .;lllc::lx0NWWMWNXOdc;'.           .dNMNKKNWWWMWWx.             ..oNWMMMMMMMMMK;              .dNMMMXo,.......';cox0XNNKkoc:clol:'.       .ckKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKkd:'       .'cllc::lx0XWMMWNKxl;.                  .xWMMMMMMMMMMO'             ..oNWMMMMMMWWMO'              ;KMMMK:              .':okXNNKxl::cooc,.       .;ok0XNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXKOkkkkkkxdoc;'.        .,colc:cdOXWMMWN0xc,.     ...              .oWMMMMMMMMMMX:             ..oNWMMMMMMWWWx.             .dWMMWx.                   .;oONWXOdc::lol;.        ..,;:looxxxxxkO0XNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNKxl;'..                   .,cll::cx0NWMWWKkl,.       .o0KKx.           .c0WMMMMMMMMMWWo.             .oNMMMMMMMWWNl              ;KMWWWO'             .,;'.    .,lONWNKxl::llc,.                    ..,cd0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKd;.                      .'col:;cxKNWMWN0d:.           .oNMMNc        ..;oOXWMMMMMMMMMWWk.             .oNMMMMMMMWMX:             .dWMMMWNO;           .oNWNO,      .,dKWWWKxl::loc,.                      .,oKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXd'                       .;loc:cdKWWMMWWKc.               .o0kc.         .....c0WMMMMMMMMMK,             .lNMMMMMMMWW0,             ;KMMMMWWWXx;.         ;OWWO'         'oKWMWWKxc::lo:.                       'dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK:                      .,coc;:d0NWMMMMMMMNd.                 .                  ;KMMMMMMMMMNl             .lNMMMMMMMWWk.            .xWWWWK0XNWMNOl.        .:kkl'.         ,kWMWMWN0d::col,.                     .cKMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXc                     .;ol:;lkXWWWMMMMMMMMMWk,                  ':l:.            .dNMMMMMMWWWx.            .lNMMMMMMMMWo.            ;KMMWO'..,cox0XKd;.       .;x0Od:.       ,0MMMWNNWNOl;:ooc.                     cXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNo.                   'ldl::o0NMMMWWMMMMMMMMWWWKc                .xWMWk'            ,0WMMMMMWWWO'           .'oNMMMMMMMMXc            .xWMMNl       .':odo;.        ;kNWKxc.    ;KMMNk;;dKWWKd:;loc'                   .xWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK,                  'loc;cxXWMMWKdokKWMMMMMMMMWWXo.               'OWMWx.           .oNMMMMMMMMNxllodxxkkOO000XWMMMMMMWWNklc:;,...    :XMMMNo           .lKOc.       .;OWMWXkc';OWWXl.   .ckNWXkc;col'                  cXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO.                ,loc;ckNWMMNOl.   .:dKWMMMMMMMMNx'               ,0WMNo.        ..'dXWWMMMMMWMMWWMWWWMMMMMMMWWWWMMMWWWMMWWWWNXK0OxooOWMMMMKc.         'OWMNd.        .lKWMMWNNWMWXd,.    .,dKWNOl;cdl,                ,KMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMk.              ,oo:;lONMMMNk:.        .;d0NMMMMMMW0;               ;0MMXc   .,:oxOKNWWMWWWNNXK0OkkkxooollccllllcloddddxkOOKXNNNWWMMMMMMMMMMMNOc.       ;ONWNd.          ;0WMMMMMWMMWNkc.     'oKWN0o;:ol,              'OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMk.            'loc;lONMMWXx;.             .;d0NMMMMWKl.              :KMMKddOXNWWWWNX0kdol:;''..                          ..',;;codk0KNWMMMMMMWNKx:.     .,:;.            :KMMMMWWMMMMMW0o'     .l0NW0o;coc.            .xMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWo.          .cdc;lONWWWXx,                   .;dKWMWWNd.           .'lKWMMWWWNKOxl:,'.             ..................               ..,codOKNWWWWWWXkl,.                  ,KMMMMWWMMMMWMWXl.      .c0WW0l;:lc.           oWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMX:         .:dl;cONWWWNx,                        .:xXWMWO,       .:dOXWWWNKOdc,..        ....,::;;;ccc::::;:::;;;;;:::::::;;::,'..         ..,cox0XWWWWN0xl,.             .dNMMMWWMMMMWWNk,          .l0WNOc,coc.         lNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO'        ,do;:xNWWMNO;.      ..                    .lONWK:. .,oOXWWWXOdc,..       ..';:::c:;;;;'.',,,,;;;;;;;;;;;;;;,,,'''',;;;::;;;;''.        .,cdOXWMMWNKko:'.      .,kNMMWMMMMMMMNO:.             .oKWNk:;ld;.       'OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXc       .ld:;oKWMWW0c.        .cdc.                   .,dXXkx0NWWN0dc'.      ..,;::::,''',;;:ldxxO0KXXNNNNWWWWWWWWWNNXXKK0Okxdl:;,'''',::::;,'.      .'cd0XWWMMWNKOxolloOXWMMMWMMMMMW0l.                 'dXWXd;:ol'       cXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNo.     .:dl,c0WMMWXo.           .oXXkc.                 .:0WMMNKko,.      .,;;:;;''',:cdk0XNWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWNK0kdl:,''';:::;,..     .'ckKNWMMMMMMMMMMMWWWWWMMWXo.                     ;ONW0l,cd:.     .oNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXl.     .lo:;xXWMMMXc              .lXMWKl.            .,o0NWWKxc.      .,;::;'.';cdk0XWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKOdl;''';:::,.      .:dKNWMMMMMMMMWWMMMMXx,                        .lKWNk:;oo'     .oXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKc.    .;dl,c0WMMMMMWk,               :0Ko'           .:kXWWXkc'     .';c:;'.':okKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKOdc,.';:c:'.     .:xKWMMMMMWWMMWNO;.                   .,,.    'xNWKl,cd:.    .:OWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXo'     .ld:;dXMMMMMMMMW0:               ..    .lo:.  'o0WWN0l'.    .':c;,'':oOXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXo::dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOd:'.';cc,.     .lOXWWWWWWWKc.                   .cONNx,    .cKWNx;;dl.     .lKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo'      'do;:OWMMMMMMMMMMWXo.                 .lKWMW0dxXWWKx:.    .':c;'.,lkKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNo.  .dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKkl,.';c:,.    .;dKWWWMMKl.                 'oKWMMWWKl.    ,kNW0c,od,      .lONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMWKx:.       ;dl,lKWMMMMMMMMMMMMMWk,                .xNMMMMWWN0o'     .:c;'.,lkXWMMMMMMMMMMMMMMMMWMMMMMMMMMMMMMMMMWWWNKo.    .dXNWWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOo,.':c:'     'l0NWWMW0l.            .:xXWMMWWMMMNk,  .:kNMWXo,cd:.      .,oONWMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMNXOo;.        .:d:,dXMMMMMMMMMMMMMMMMWKc.               .lXMMWNOc.    .,::,.'ckXWMMMMMMMMMMMMMMMMMMNkd0WMMMMMMMMMMNOolc:,.       .',::coONMMMMMMMMMMNOdONMMMMMMMMMMMMMMMMMMWNOl,.':c;.    .cONWWMW0l.        .l0WMMMMWMMMMMMWKdd0WMMMMWNx;;dl.        .'cdOXWMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMWXkl;.           .cd:;kNMMMMMMMMMMMMMMMMMMMXd.              'xNWNOc.    .:c;..;dKWWWMMMMMMMMMMMMMMMMMMMK: .l0XKOOOKWMMNk;.                .;kNMMW0xkOKKOc. :KMMMMMMMMMMMMMMMMMMMMMWXx:..;c:.    .:kNWMMW0c.   .;dKWMMMMMMMMMMMMMMMMMMMMMMMMMWO:;do.            .:dONMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMNkc.              .ld;:OWMMMMMMMMMMMMMMMMMMMMMW0:           .oKWNOc.    .:c;.'cONWMMMMMMMMMMMMMMMMMMMMMMWO,   .'...,xNMMMWXx;.            .;kNWMMMNx' ....   'OWMMMMMMMMMMMMMMMMMMMMMMWN0l'.,::'    .:ONWWMNO:'cONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0c;oo'              .,xXWMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMNx,                .oo;c0WMMMMMMMMMMMMMMMMMMMMMMMMXd.       .:OWWKl.    .:c;.'l0WMMMMMMMMMMMMMMMMMMMMMWNKkl,        .dNWMMMMMWXl.          .oXWWMMMMMNx.        'ckKNWMMMMMMMMMMMMMMMMMMMMMWKd,.,cc'    .c0NWMWNXWMMMWWMMMMMMMMMMMMMMMMMMMMMMMMMMMWKl,od,                'dXWMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMW0c.                .dd;c0WMMMMMMMMMMMMMMMMMMMMMMMMMMW0:.    'xNWXd'    .:l;.,dKWMMMMMMMMMMMMMMMMMMMMMMMNk;.          ;0WMMMMMMMXl           .oNMMMMMMMW0,          .;kNMMMMMMMMMMMMMMMMMMMMMMMWXx,.,cc'    .oKWMMMWMMWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXl,od'                 ,OWMMMMMMMMMMMMMM
MMMMMMMMMMMMMM0;                 .od;c0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx' .:0WWO:.   .;l;.'oKWMMMMMMMMMMMMMMMWWWMMMWWWMWN0xl,.        :0WMMMMMW0;   .;::;.   ,0MWMMWMWO;         ,lk0XWMWWWWMMWNWMMMMMMMMMMMMMMMWXd,.,c:.    ;kNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXl,od'                 'OWMMMMMMMMMMMMM
MMMMMMMMMMMMMXc                 .oo;c0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKdxNWKo.    ,c:..l0WMMMMMMMMMMMMMMMMWOclkOxclKWMMMMWK:   .,;;,,oXMMMMMW0:,lkKNWWNKko;:0WMMMMMXo,,;:;.   :KWMMMMW0ccdkxl:kNMMMMMMMMMMMMMMMMWKo'.;l;.   .lKWMMWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXl,od'                 :XMMMMMMMMMMMMM
MMMMMMMMMMMMMK,                .od;:0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO;    .cc'.:ONWMMMMMMMMMMMMMMMMMWk.  .  ;0MMMMMMNo..:kNWWNXXWMMMMMMWNNWMMMMMMMMWNNWMMMMMMWNXNWWNOl..dWMMMMMWK:     .xWMMMMMMMMMMMMMMMMMMW0c.'cc.    ,kNMMWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKl,do.                .kMMMMMMMMMMMMM
MMMMMMMMMMMMM0'               .cd;:OWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXd'    ,l:.'dXMMMMMMMMMMMMMMMMMMMNO:.     .oKWMMMMWKxkNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOkKWMMMMW0o.     .:kNMMMMMMMMMMMMMMMMMMMNx,.,l;.   .oXWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKc,ol.               .xWMMMMMMMMMMMM
MMMMMMMMMMMMMK,               :x:;kWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMKl.   .:c'.:0WMMMMMMMMMMMMMMMMMMMW0c'.    ..,oXMMMMMMWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXd;'.    .,l0WMMMMMMMMMMMMMMMMMMMWKl..cc.   .c0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO;;dc.              ,0MMMMMMMMMMMMM
MMMMMMMMMMMMMNl              ,dc,dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0:    .l:..oXWMMMMMMMMMMMMMMMMMMMMMWNX0d. ,xKXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWNXO; .oKNNWMMMMMMMMMMMMMMMMMMMMMMNx'.:l'    ;OWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWk;:d;              lNMMMMMMMMMMMMM
MMMMMMMMMMMMMM0'            .do,lXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO;    'l;.,kNMMMMMMMMMMMMMMMMMMMMMMMMMMMNkd0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKdkNMMMMMMMMMMMMMMMMMMMMMMMMMMMW0:.,l;.   'kNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNd,lx,            'OMMMMMMMMMMMMMM
MMMMMMMMMMMMMMNd.          .lx;:0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO,    ;l,.:0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKl.'l:.   'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXl,dd.          .dWMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMXc          :xc;kWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWk,   .:l'.cKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.'c:.   .xWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0::xc          cXMMMMMMMMMMMMMMM
NNNNNNNNNNWWNNNN0l::::::::lk0dxXNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNXkl::cdOxldKNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNXxlxOxccclkXNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNXOk0Ooc:c:cccco0NWWNNNNNNNNNNNNN
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXKK0kxddooooddxkO0KKXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKKXXXKKKKKKKKKKKKKKKKKKKKKKKXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKXKKKKKKKKKKKKKKKKKKXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKKXXKKKKKKKKKKKKKKKKKXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKKXXXXKKKKKKKKKKKKKKKKKKKKKKKXXXXXXXXXXXXXXXXXXX
XXXXXXXXXX0koc:::ccccllllccccc::cldOKXXXXXXXKx::::::::::::::::::::::::::;ckKkc::::::::::::::::::::::ccclodk0KXXXXKx::::::::::::::::::::::::::::::::::;;coc;:::::::::::::::ckXKd::::::::::::::::::::::::::::oo:::::::::::::::::o0XOl:::::::::::::::::::::::::::dK0o:::::::::::::::::::::::ccllodk0KXXXXXXXXXX
XXXXXXXKxc;:cdk0XNWWWMMMWWWWWNKOxoc;:oOKXXXX0:'o000000000000000000000000l.l0l.l0000000000000000OOOOOkkxdoc:;:dOXX0:'d00000000000000000000000000000000l'...lO0000000000000l.lKO;'x000000000000000000000000x'..'x0000000000000k,'kKd.:O00000000000000000000000x',Ox';k000000000000000OOOOOkkxdolc:::lkKXXXXXXX
XXXXXKx:,lkXWMMMMMMMMMMMMMMMMMMMMMWKx:,ckKXX0:,OMMMMMMMMMMMMMMMMMMMMMMMWx'c0c'xWMMMMMMMMMMMMMMMMMMMMMMMMMWN0o;;o00;,OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx;. .xWMMMMMMMMMMMMWx'cKO;;0MMMMMMMMMMMMMMMMMMMMMMMMK;..;KMMMMMMMMMMMMMX:'xXo'oWMMMMMMMMMMMMMMMMMMMMMMMK;,Ox'cNMMMMMMMMMMMMMMMMMMMMMMMMMMWNKxc,:xKXXXXX
XXXX0l'c0WMMMMMMMMMMMMMMMMMMMMMMMMMMMNk;,xKX0:,OMMMMMMMMMMMMMMMMMMMMMMMWx'c0c'xWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXo':x;,OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx;. .xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMMMMMMMMMMMM0;..;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMMMMMMMMMMMK;,Ox'cNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0c'l0XXXX
XXX0c'oNMMMMMMMMMMMMWXOk0XWMMMMMMMMMMMW0;,kX0:,OMMMMMMMMMMMMMMMMMMMMMMMWx'c0c'xWMMMMMMMMMMMMMWWWMMMMMMMMMMMMMMNd';,,OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx;. .xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMMMMMMMMMMMM0;..;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMMMMMMMMMMMK;,Ox'cNMMMMMMMMMMMMMMWWWMMMMMMMMMMMMMMMXl'oKXXX
XXXd'cXMMMMMMMMMMMMMO;,;'lXMMMMMMMMMMMMWx'c00:,OMMMMMMMMMMMMMMNXXXXXXXXKo.l0c'xWMMMMMMMMMMMMW0lcoONMMMMMMMMMMMMK:..'xXXXXXXXXWMMMMMMMMMMMMMWNXXXXXXXKo,. .xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMWNXXXXXXXXXk,..;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMWXXXXXXXXXk,,Ox'cNMMMMMMMMMMMMMXdcldKWMMMMMMMMMMMMMO,;OXXX
XXKl'dWMMMMMMMMMMMMWo.oO;,0MMMMMMMMMMMMM0;,O0:,OMMMMMMMMMMMMMWx,,:::::::;;x0c'xWMMMMMMMMMMMMWd.',,kWMMMMMMMMMMMWo.';;:::::;';OWMMMMMMMMMMMMWx,,::::::;,;'.xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNo';:::::::;;:';KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMM0:';::::::;;o0x'cNMMMMMMMMMMMMMK;.;.:XMMMMMMMMMMMMMK:'kXXX
XX0:'kMMMMMMMMMMMMMNl'd0:,OMMMMMMMMMMMMMXc'x0:,OMMMMMMMMMMMMMNl.lO0000000KXKc'xWMMMMMMMMMMMMWd'cl.dWMMMMMMMMMMMWd'l0000000k;.kWMMMMMMMMMMMMNl.lO00000000c'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc.o000000000k,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMO';k00000000KXx'cNMMMMMMMMMMMMMK;;d;,0MMMMMMMMMMMMMX:'xXXX
XX0:,OMMMMMMMMMMMMMNl'd0:,OMMMMMMMMMMMMMNl'd0:,OMMMMMMMMMMMMMNl.dXXXXXXXXXXKc'xWMMMMMMMMMMMMWd'cl'dWMMMMMMMMMMMWd'lKXXXXXX0:'kMMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc'xXXXXXXXXXk,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMO':0XXXXXXXXXXx'cNMMMMMMMMMMMMMK;;d;,0MMMMMMMMMMMMMXc.dXXX
XX0;,0MMMMMMMMMMMMMNl'd0:,OMMMMMMMMMMMMMNl'd0:,OMMMMMMMMMMMMMNo.cxxxxxxxOKXKc'xWMMMMMMMMMMMMWd.,,'kWMMMMMMMMMMMNl'dKXXXXXX0:'kMMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc.cxxxxxxkOKk,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMO',dxxxxxxk0KXx'cNMMMMMMMMMMMMMK;;d;,OMMMMMMMMMMMMMXc.dXXX
XXO;,0MMMMMMMMMMMMMNl'd0:,OMMMMMMMMMMMMMNl'd0:,OMMMMMMMMMMMMMWkc:cccccc:,c0Kc'xWMMMMMMMMMMMMWO::cxNMMMMMMMMMMMM0;,kXXXXXXX0:'kMMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNx::cccccc;,ok,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMKo:ccccccc,;kXx'cNMMMMMMMMMMMMMK;;d;,OMMMMMMMMMMMMMXc.dXXX
XXO;,0MMMMMMMMMMMMMNl'd0:'o0000000000000O:.d0:,OMMMMMMMMMMMMMMWWWWWWWWW0;,OKc'xWMMMMMMMMMMMMMWWWWMMMMMMMMMMMMW0:'dKXXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMMWWWWWWWWWk':x,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMMWWWWWWWWNl.oKx'cNMMMMMMMMMMMMMK;;d;,OMMMMMMMMMMMMMXc.dXXX
XXO;,0MMMMMMMMMMMMMNl'dKxc::::::::::::::::lO0:,OMMMMMMMMMMMMMMMMMMMMMMMK;,OKc'xWMMMMMMMMMMMMMMMMMMMMMMMMWX0xl;,:xKXXXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMMMMMMMMMMMk':x,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMMMMMMMMMMWo.oKx'cNMMMMMMMMMMMMMK;;d;,OMMMMMMMMMMMMMXc.dXXX
XXO;,0MMMMMMMMMMMMMNl'dXXKKKKKKKKKKKKKKKKKXX0:,OMMMMMMMMMMMMMMMMMMMMMMMK;,OKc'xWMMMMMMMMMMMMMMMMMMMMMMMMWX0xc,'cOKXXXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMMMMMMMMMMWk':x,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMMMMMMMMMMWo.oKx'cNMMMMMMMMMMMMMK;;d;,OMMMMMMMMMMMMMXc.dXXX
XXO;,0MMMMMMMMMMMMMNl'dXK00OOOOOOOOOOOOOO0KX0:,OMMMMMMMMMMMMMMMMWMMWWWMK;,OKc'xWMMMMMMMMMMMMMXkk0XWMMMMMMMMMWXx;,dKXXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMMMMWWMWWWWk':x,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMMMWWWMWMMNo.oKx'cNMMMMMMMMMMMMMK;;d;,OMMMMMMMMMMMMMXc.dXXX
XXO;,0MMMMMMMMMMMMMNl'dKd;;::::::::::::::;cO0:,OMMMMMMMMMMMMMWOlcllllll:'c0Kc'xWMMMMMMMMMMMMWx..'cKMMMMMMMMMMMW0;,kXXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNklcllllll;.lk,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMXdcclllllc,,xXx'cNMMMMMMMMMMMMMK;;d;,OMMMMMMMMMMMMMXc.dXXX
XXO;,0MMMMMMMMMMMMMNl'd0:'xXXXXXXXXXXXXXKc'd0:,OMMMMMMMMMMMMMNo.;ooooooox0XKc'xWMMMMMMMMMMMMWd.c:'xWMMMMMMMMMMMNo'dXXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc.:oooooodx0k,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMO''loooooodkKXx'cNMMMMMMMMMMMMMK;;d;,OMMMMMMMMMMMMMXc.dXXX
XX0;,OMMMMMMMMMMMMMNl'd0:,OMMMMMMMMMMMMMNl.d0:,OMMMMMMMMMMMMMNl'dKXXXXXXXXXKc'xWMMMMMMMMMMMMWd.cl'dWMMMMMMMMMMMWd'lKXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc'xXXXXXXXXXk,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMO':0XXXXXXXXXXx'cNMMMMMMMMMMMMMK;;d;,0MMMMMMMMMMMMMXc.dXXX
XX0:'OMMMMMMMMMMMMMNl'd0:,OMMMMMMMMMMMMMNc'd0:,OMMMMMMMMMMMMMNo'dKXXXXXXXXXKc'xWMMMMMMMMMMMMWd'cl'dWMMMMMMMMMMMWd'lKXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc'xXXXXXXXXXk,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMO':0XXXXXXXXXXx'cNMMMMMMMMMMMMMK;;d;,0MMMMMMMMMMMMMNc.dXXX
XXKc'xWMMMMMMMMMMMMNl'd0:,0MMMMMMMMMMMMMX:'k0:,OMMMMMMMMMMMMMNo.lOOOOOOOOOK0c'xWMMMMMMMMMMMMWd.cl'dWMMMMMMMMMMMWx'lKXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc'xXXXXXXXXXk,;KMMMMMMMMMMMMMX:'xKd'oNMMMMMMMMMMMMMO';kOOOOOOOO0Kx'cNMMMMMMMMMMMMMK;;d,;KMMMMMMMMMMMMMXc.dXXX
XXXo.lNMMMMMMMMMMMMWo.ok,;KMMMMMMMMMMMMM0,;O0:,OMMMMMMMMMMMMMWx;;::::::::;;dc'xWMMMMMMMMMMMMWd.cl'dWMMMMMMMMMMMWx'lKXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc'xXXXXXXXXXk,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMM0c,:::::::::;lo'cNMMMMMMMMMMMMM0;.,'lNMMMMMMMMMMMMMX:'xXXX
XXXk,;KMMMMMMMMMMMMWO;,;,oNMMMMMMMMMMMMWd'lK0:,OMMMMMMMMMMMMMMWNNNNNNNNNXd.::'xWMMMMMMMMMMMMWd.cl'dWMMMMMMMMMMMWx'lKXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc'xXXXXXXXXXk,;KMMMMMMMMMMMMMX:'xKo'oNMMMMMMMMMMMMMWNNNNNNNXNNO;,c'cNMMMMMMMMMMMMMXxcokXMMMMMMMMMMMMMMK;,kXXX
XXXKo'lNMMMMMMMMMMMMWX00KNMMMMMMMMMMMMWO,;kX0:,OMMMMMMMMMMMMMMMMMMMMMMMMWx'::'xWMMMMMMMMMMMMWd.cl'dWMMMMMMMMMMMWx'lKXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;0MMMMMMMMMMMMMNc'xXXXXXXXXXk,;KMMMMMMMMMMMMMX:'xKd'oNMMMMMMMMMMMMMMMMMMMMMMMMK;,c'cNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWk'c0XXX
XXXX0l'lKWMMMMMMMMMMMMMMMMMMMMMMMMMMWXd,;kKX0:,OMMMMMMMMMMMMMMMMMMMMMMMMWx'::'xWMMMMMMMMMMMMWd'cl'dWMMMMMMMMMMMWx'lKXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc'xXXXXXXXXXO,;KMMMMMMMMMMMMMX:'xKd'oWMMMMMMMMMMMMMMMMMMMMMMMMK;,c'cNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO;,xXXXX
XXXXXKd;,lOXWMMMMMMMMMMMMMMMMMMMMWXOl;;o0XXX0:,OMMMMMMMMMMMMMMMMMMMMMMMMWx'::'xWMMMMMMMMMMMMWd'cl'dWMMMMMMMMMMMWx'lKXXXXXX0:'kWMMMMMMMMMMMMNl.oKXXXXXXXKl'xWMMMMMMMMMMMMWx'cKO,;KMMMMMMMMMMMMMNc'xXXXXXXXXXk,;KMMMMMMMMMMMMMX:'xXd'oWMMMMMMMMMMMMMMMMMMMMMMMMK;,c'cNMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOl,;xKXXXX
XXXXXXX0xc;:cok0KXNWWWWWWWWNNK0koc:;cx0XXXXX0:.oOOOOOOOOOOOOOOOOOOOOOOOOOl.cc.lOOOOOOOOOOOOOOc.ll.:kOOOOOOOOOOOOc.lKXXXXXX0c.lOOOOOOOOOOOOOk:.dKXXXXXXXKl.cOOOOOOOOOOOOOOc.lKO;'dOOOOOOOOOOOOOx;'xXXXXXXXXXO,'dOOOOOOOOOOOOOx,'kXd.:kOOOOOOOOOOOOOOOOOOOOOOOOd,,l';xOOOOOOOOOOOOOOOOOOOOOOkkxdolc:;cx0XXXXXX
XXXXXXXXXK0kdlc:::ccccccccccc:::lok0KXXXXXXXKkc:::::::::::::::::::::::::::lOkl:::::::::::c::::lOOl:::::::::::::::lOXXXXXXXKkl:c::::::::::::::oOXXXXXXXXXOl::::::::::::::::lOXKxc::::::::::::::::d0XXXXXXXXXKdc:::::::::::::c:cd0X0o:::::::::::::::::::::::::::cxOdc::::::::::::::::::::::cccclloxO0XXXXXXXXX
XXXXXXXXXXXXXXKK0OkkxxxdxxkkO0KKXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKKXXXXKKKKKKKKKKKKKKKKXXXXKKKKKKKKKKKKKKKXXXXXXXXXXXXXKKKKKKKKKKKKKKXXXXXXXXXXXXXXKKKKKKKKKKKKKKKXXXXXXXKKKKKKKKKKKKKKKXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKXXXXXXXKKKKKKKKKKKKKKKKKKKKKKKKKKXXXXXKKKKKKKKKKKKKKKKKKKKKKKXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
kkkkkkkkkkkkkkkkdddxddddxxxkOkxOXNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNKkxddxO0kxOKNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNXNX0xxOOxdxxk0XNNN0OKNNNNNNNNNNNNNNNNNNNNNXXXXXXXX0kxOOxddxxddxdxk0000000000000000
dddddooodooooool,.         .l:.;0WWWMMMMMMMMMMMWMMWWWWWNKkxdkKWWMWWWNd.   .lc.'dNWWWMMMMMMMWWMMMMMMMMMMMMMMMMMWMMMMMMMMMMMMMMMMMMMMMWWWMMMMMMMMMMWWWWMMMMMMMMMMMMMMMMMMMMWWMMMMMWWWWMMMMMMMWWWMMMMMMMMMMMMMMWWMMWWWWMMMMMWWNk;.;l,.  .cKWWWKc'oNMMMWMMWWWWWWWMMWWWWWWWWWWWWXl.,l,          'oxdddddddddddddd
dddddddddddddod:.           ,l,.cKWMMMMMMMMMMMMMMMMMMWO:.    .:kNWWWWXd.   .::..oXWWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx'.;l'    :0WMWK:  .oNMMMMMMMMMMMMMMMMMMMMMMMMMWx..l:.           ,xxdoooooooooooo
oddddoddddddddo'             :l..dNMMMMMMMMMMMMMMMMMM0,        .:OWMMMNx'   .;c,.:0WWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXo..:c.   .cKWMMK:    .oNMMMMMMMMMMMMMMMMMMMMMMMWO,.:c.            .o0xoodddddooddo
xdddoddoodoodx:.             .cc.'kWMMMMMMMMW0dcdXMMMO.          .lKWMMWk,    ,l;.,xNMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWNNNNNWWWNWMMMMWNXXKXXNWMMMMMWWNNNNWWWMWWWNWWWWWWNNNWNNNNWMMWWWNNWMMMWWNNWWMMMMMMMMMMMMMMMMMMMMMMMMMMW0:.'c:.   .lXMMW0;      .dNMMMMMMMMMMMMMMMMMMMMMMK:.;l'              ,kOdodddooddodk
KOkddodddodoxx,               .l:.,OWMMMMMMKl.  .lXMM0'            ,kWMMWO:    .cc..lKWMMMMMMMMMMMMMMMMMMMMMMMKc,,,,,,,,,,,,lKW0o:,.....';lkNMWx;,,,,lxKNd;,,,:kXd,,,,,,,,,cKNd,,,,:OWNo,,,,oXMMMMMMMMMMMMMMMMMMMMMMMWXx'.;c,    'dNMMWk'        .xWMMMMMMMMMMMMMMMMMMMMXc.'l;               .dOdodddooddk0X
XXK0Oxdddddoxd'                'l;.;0WMMMMWo.    .cXMNl             .lXWMWKo.   .,:,.'dXWMMMMMMMMMMMMMMMMMMMMM0:'..      .''cOd.    .:'     cXNc     'lko.    cXX:      .'':0X:     'OK;    ;KMMMMMMMMMMMMMMMMMMMMMMNO:..::.    ;OWMMMO'          .kWMMMMMMMMMMMMMMMMMMXl..c;                .dOdoooddxk0XXX
XXXXXX0kxdoddl.                 ,l,.:KWMMMWo       :KWO'              ;OWMMNk,    .::..:ONWMMMMMMMMMMMMMMMMMMMWNNXo.    .dXNNK;     ;Kd.    .kNl     .;;.    :KMX:     ,ONXNWX:      'd;    ;KMMMMMMMMMMMMMMMMMMMMWKo..;c'    .lKWMMMMNo.          ,0MMMMMMMMMMMMMMMMMNo..c:.                .xOddddk0KXXXXX
XXXXXXNNKOxdoo:.                 ,c'.cKWMMWk.       ;0Nl       .okd'   .xNMMW0l.    ,:,..l0WMMMMMMMMMMMMMMMMMMMMMWd.    .xWMMK;     ;Kx.    .kNl            :KMMX:     .;ccxNX:       ..    ;KMMMMMMMMMMMMMMMMMMWXd,.'c:.    ;kNMMMMMMMNx.          :XMMMMMMMMMMMMMMMNd..cc.                 :0Oddk0XXXXXXXX
XXXXXXXXXXX0kkOl.                 'c'.:0WMMNc        ,OO,      :XMM0,   .lXWMWNk;    .,c;.'o0WMMMMMMMMMMMMMMMMMMMWd.    .xWMMK;     ;Kx.    .kNl            ;KMMX:      ...cXX:             ;KMMMMMMMMMMMMMMMMWXx,.'::.    .oKWMWX00XNWMWO,         .cONMMMMMMMMMMMMNx..c:.                 ,OKO0KXXXXXXXXXX
XXXXXXXXXXXNNXNXo.                 ,c'.:0WMM0,        .do.     .xN0c.     ;0WMMWXo'    .;c,.'o0WMMMMMMMMMMMMMMMMMWd.    .xWMMK;     ;Kx.    .kNl     ...     cXMX:     'kKKXWX:    ',       ;KMMMMMMMMMMMMMMWKx;.'::'    .cONMMNx,...,:ldxo'          .,lOXWMMMMMMMNd..cc.                .:0WWNNXXXXXXXXXXX
XXXXXXXNNNNNNWMMWO:.                'c,.;0WMWO'       .o0c      ,kd.       'kWMWWW0l.    .;:;..cONMMMMMMMMMMMMMMMWd.    .xWMMX:     ,Oo.    .ONl     .cl,     lXX:     .dOOOXK:    :k:      ;KMMMMMMMMMMMMWKo,.'c:.    .;kNWMW0:.         .               'cONMMMMXl..c:.               .;kNMMWNNNNNNNNNNNNN
WWWWWWWMMMMMMMMMMMNOl'               'c;.,OWMWk'    .dXWM0,      ;0O:.      'OWMMWWN0l.    .,:;..;xKWMMMMMMMMMMMMWx.    .xWMMWO;.    ..    'dNNl     'lOk.    .o0:         .o0:    :X0;     ;XMMMMMMMMMWNOl'.'::'    .;xXWMWKl.                            .dNMMWKc..c;.             .'lONMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMWXkl;..           .c;.'xNMWO,   .kWMMWo.      cXNx'      :KMMMWWWN0l.    .,::'.'lONWMMMMMMMMMMKdoooodKMMMMMN0xoc:::cldOXWMW0oooooxOXNOoooookKOoooooooooo0NOooooOWWKdooookNMMMMMMWNKd;..;::.    .;kXWMWKo'                             .xNMMW0:.':,           ..:oONWMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMWXOd:'.        .::..lXWW0:   .l0Kk,       .lNWKl.    ,0MMMMMMWWN0o'     ';:;..;o0NWMMMMMMMMMMMMMMMMMMMMMMMMMMWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKxc'.';;'.    .;kXWWWWXd,..                           ;0WMMNk,.;c'         .;dOXWMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOl'       .;:'.:0WMXo.   ..          .oNMW0:. ,kNWMMMMMMWWMWKd;.    .,:;'..;oOXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKxc'.,::;.     'lONWWWKolkXXK0kxdol:;,,''...           .oXMMWXd..:c.       .ckKWMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXx;.      'c,.,xNMWk,               .xWWWNOkXWWWMMWWWWWWMMMWXOc.     .,;;,..,ckKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOo;..';:;.     .,dKWWWNOl.  .:0WMMWMMWWWWNNNXXKOl.       ,kNMMW0:..::.      'oKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNk;      .::..lKWWXo.              ,0WMMMMWMMNOo:;:cox0XWMWWWKx:.     .,::;'..;okKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWXOd:,..,;:;..    .,lONWWWXx;.    .c0WMMMMWWWMMMMMMMMMWKd,.  .lKMMMNk,.;c,      .dXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXd.     .;c,.,kNMW0l.            .dWMMMMWXx;.       .':d0NWMWN0d;.     .';:;,'.';cdOXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWX0ko:,..',;;'.      'ckXWWWNOl'     .l0WMMMMMMMWWWMMMMMMMMMMMNOcckWMMWKl..:c.      :0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWk'      'c:..lKWMW0l'          'OWMMMNk;              .,lkXWWWN0d:.      .',;;;,'.';cdk0XWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWNKOdl:,'',;;;,'.      .,lkKWWWN0d;.     .oKWMMMMMMMMMMMMMMMMMMMMMMMMMWWWMWNx,.,l;.     .lXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO'      .,c,.,dXWWWXx:.      ;kNWWNO:.                   'ckXWWWWXkl,.      ..,;:::,''',::ldkO0XNNWWWMMMMMMMMMMMMMMMMMMMMWWWNNXK0kxoc:,...';;::;'.      ..:d0NWWWN0d;.        .oXWWMMWMMMMMMMMMMMMMMMMMMMMMMWWWO:..::.       lXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWd.       .::..:ONWMMWKkocclkXWMW0c.                 ...    'lONWMWWX0xc,.       .',,:;::,,;,.',;;;:cloddxxxxkkkkxxxddddolc:;,,'.',,,;;;;;,'.       ..;oOXWWMWXOl,.             ;kNMMWWWMMMMMMMMMMMMMMMMMMWWWKo..,c,        ,0MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMX:         ':;..l0NWMMMMMWMMMMNx'                 .lKX0:     .,dKWWWMMWN0ko:'.        ...,::;:cc:;;;:;;,''''''''...'',;;;;,,;::;,;,'..        ..,cdOKNWMWN0d:'                  .lKWMMWWMMMMMMMMMMMMMMMMMWXx;.,c;.        .dWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx.         .,c;.'oKWMMMMMMMMMO'                 'xNMWK:        'oKWWMMWMMWWX0xoc,..          ....',;;;;,,,,;;;,,,,,,;;,,'....           ..;ldOKXWWWWXXKd'.                       ,xNMMMMMMMMMMMMMMMMMWWNk;.'::.          ,0MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMO'           .;c,.,dKWMMMMMMM0,                :0WMWO;           ;OWMMMMMMMWMMWWNKOxdl;,'.                                      ..,;codkKXNWMWWX0xl;',xo.   .;oOk,                .c0WMMMMMMMMMMMMMMWNk:.'::'            cNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM0,             .:c,.'oKWWWMMMNx.             .oXMMWk'             ;KMMMMMMMMWWWWWWWMMWWNXKOkxdl::;;,'................',;;;:coxkk0XNNWWMWNXKkdl;..     ,kxclkKNWMWK:                 .dXMMMMMMMMMMWWNk:..;c,.             lNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMK,               ':c,.'oKWWWMMWk'           ,kWMMNd.              '0MMMWXOdlc:::::clodxO0XNNWWWWWWNNXXKKK00000000KKKXXNNWWWWWMMWNNX0kdoc;'.        .'cdKWWWMMMWWMMXl.                 ;OWMMMMMMMWXk:..;c,.               lNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMX:                 '::,.'l0NWMMWKl.        cKWMWKc.              .oNMMWO;.              ..',:ldk0XWMWWWWWMMWWWNNXXXXXXK0OOOXWMMWx,..           ':ok0NWMMMMWMMMMWWMMNo.                 ;0WMMMMWXx;.'::,.                 oWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx.                  .;:;..:kXWMMWOc.     'kWMWO;                cXMMWO'              ...       .':oOXWMMMMW0d:'''....... .dWMMWk.            .oNWMMWX0xd0WMMWWWWWMMNx.             .,o0NMMMW0o'.'::'.                  .OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM0,                    .,:;..,o0WMWN0l'    .coc.                :KMMM0,             .l0KOl.          'dXMMMWkc.            :XMMMK;             'xOxl:'.  ,0WWMMWWWWWMWk'          'lONWMMWXkc'.';;.                     cXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWk.                     .';;,.'ckXWMWXx:.                     ;0MMMXc              ;KMMWk.           .oNMMWOc.            'OMMMWo.             ..      .,xNWMMWMMMWWMW0;      'ckXWMMWN0o;.';:;.                      ;KMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx'                       .,:;'.,lOXWWWKxc'                 ,0MMMNo.             .xWMMNl             ,KMMMOl'            .dWMMMO'                .';lx0XWMMWWMMMMMMWMWK:..'lkXWMMWNKx:..,::'.                       :0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0:.                       .'::,..;o0NWWWXOo:'.           ;0WMMWk.              ;KMMMXo'...         ,KMMMOl'             cNMMMNc               c0XWWMMMMWN00NMMMMMMMWMXkONWMMMWKxc'.':c;.                        'dXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOl'                        .';;'..;oOXWMMWX0xoc;,''',:dKWMMMX:              .dWMMMWNNX00OkxxdoollkNMMM0l'             ,0WMMWk.              ;KMWWNKko:'..oNMMMMMMWWMMMMWWKkc'..,;;.                        .;xXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOdc;'.                     .';:,..,lkXWWWWWWWNNNNWWWMMMMMK,              ,0MMMW0OO0KXNNWWWWWWMMMMMMOl'             .xWMMMK;               :xo:,.      .xWMMMMMMMMWN0d:'.',;;'.                 ....,;:okKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWXK0OOOOOOkxoc:;..         .,;;,'.':d0XWMMMMMMMWMMMMMMNo.            .oWMMM0,  ...',,;:ccloOWMMM0o'             .oNMMMWo.                      ..;okKWMMMMWNKOo;'.,,;,.         ..,:ldkOO00000KXWWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0kl;.        .';;;'..,lkKNWMMWWMMMMMMMNk;.          .xWMMWd.              oWMMM0o'              :KMMMMO'                 .';lx0XWMMMWWWXOo:'..,;:,.        .':d0XNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNKd;.         .,,;;,'',cx0XWWWMMMMWWMN0o;.        .cooc.              .kMMMM0o'              'OWMMMNc           .';cok0XWWWWWWWNKko:'..,;;,'.         .cONWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOc.          .';::;,..,:okKXWWWMMMWWWKOdc,..                     'dNMMMM0o'              .xWWMMWx.  ..';coxOKXWMMMMMMWNKOxc;'..',;;'.           'oKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0:.            ..,,;;,'.',:ok0XNWWMMMMWNX0kdoc:,'.........';:lkXWMMMMM0o'             ..dNWMMMXkxO0KNWMMMMMMMWWNKOdl:'..',;;,'.             .lKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx'                .';::;,,''';coxOKNNWWWMMMMWWNXXKKKKKXXNWWMMMMMMMMMX0dccclloodddxkO0KNWWMMMMMMWWWMMWWNX0kdl:,'.',;;:;,..                ,OWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO,                    .';:;:;,,'.',;codk0KXNWWWMMWWWWWWMMWWMMMMMMMMMMMWWWMMMMMMWWMMMMMMMWWWWNXK0Okdl:;,'.'';:;;;,..                    ;0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0,                        ..';:;:;'''..',',:clodxkOOO0XXNNNWWWWWWMWWWWWWWWWWNNXXXKK0Okxollc;'','.,;;;:;,;,...                        :KMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO,                              ...,',::;;::;'',,,'..',,;;::::ccccc:ccc:::::;,,'''',,'.,;:,';::,,,'..                              ;0MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWO'                                     ..',,',:::;,'',::cc:;;;:;;;;;::::::::;,,;;:::,'','..                                      ,0MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0;                                                   .........''...''.......                                                  .cKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXo.                          ......                                                        .......                          ;kNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo'.                .,:ldxk0KKKK0Oxdo:,.                                           .,cdxk0KKXXXKOkxoc,..               .;xXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOo:,........,:ldOXNWMMMMMMMMMMMMMMWNKko,.                                   .,oOXNWMMMMMMMMMMMMMMWNX0xl:;'.......;cd0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNX00KK0KXNWMMMMMMMMMMMMMMMMMMMMMMMMMN0o,                              .;o0NMMMMMMMMMMMMMMMMMMMMMMMMMMWNXKKKKKXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXkc.                         .:ONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0l.                     .cONMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKd;.               .;dKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0xl;'.......';lxKNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWNX0000KKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
*/

pragma solidity ^0.8.0;
pragma solidity ^0.8.0;
interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
pragma solidity ^0.8.0;
interface IERC721Receiver {
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}
pragma solidity ^0.8.0;
interface IERC721 is IERC165 {
    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );
    event Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );
    function balanceOf(address owner) external view returns (uint256 balance);
    function ownerOf(uint256 tokenId) external view returns (address owner);
    
    function approve(address to, uint256 tokenId) external;
    function getApproved(uint256 tokenId)
        external
        view
        returns (address operator);
    function setApprovalForAll(address operator, bool _approved) external;
    function isApprovedForAll(address owner, address operator)
        external
        view
        returns (bool);
    
}
pragma solidity ^0.8.0;
interface IERC721Metadata is IERC721 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function tokenURI(uint256 tokenId) external view returns (string memory);
}
pragma solidity ^0.8.0;
interface IERC721Enumerable is IERC721 {
    function totalSupply() external view returns (uint256);
    function tokenOfOwnerByIndex(address owner, uint256 index)
        external
        view
        returns (uint256);
    function tokenByIndex(uint256 index) external view returns (uint256);
}
pragma solidity ^0.8.1;
library Address {
    function isContract(address account) internal view returns (bool) {

        return account.code.length > 0;
    }
    function sendValue(address payable recipient, uint256 amount) internal {
        require(
            address(this).balance >= amount,
            "Address: insufficient balance"
        );

        (bool success, ) = recipient.call{value: amount}("");
        require(
            success,
            "Address: unable to send value, recipient may have reverted"
        );
    }
    function functionCall(address target, bytes memory data)
        internal
        returns (bytes memory)
    {
        return functionCall(target, data, "Address: low-level call failed");
    }
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return
            functionCallWithValue(
                target,
                data,
                value,
                "Address: low-level call with value failed"
            );
    }
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(
            address(this).balance >= value,
            "Address: insufficient balance for call"
        );
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(
            data
        );
        return verifyCallResult(success, returndata, errorMessage);
    }
    function functionStaticCall(address target, bytes memory data)
        internal
        view
        returns (bytes memory)
    {
        return
            functionStaticCall(
                target,
                data,
                "Address: low-level static call failed"
            );
    }
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }
    function functionDelegateCall(address target, bytes memory data)
        internal
        returns (bytes memory)
    {
        return
            functionDelegateCall(
                target,
                data,
                "Address: low-level delegate call failed"
            );
    }
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            if (returndata.length > 0) {

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

pragma solidity ^0.8.0;

abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );
    constructor() {
        _setOwner(_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 {
        _setOwner(address(0));
    }
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(
            newOwner != address(0),
            "Ownable: new owner is the zero address"
        );
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
    function toString(uint256 value) internal pure returns (string memory) {
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }
    function toHexString(uint256 value, uint256 length)
        internal
        pure
        returns (string memory)
    {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
abstract contract ERC165 is IERC165 {
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override
        returns (bool)
    {
        return interfaceId == type(IERC165).interfaceId;
    }
}

pragma solidity ^0.8.0;

abstract contract ReentrancyGuard {
    // word because each write operation emits an extra SLOAD to first read the
    // back. This is the compiler's defense against contract upgrades and

    // but in exchange the refund on every call to nonReentrant will be lower in
    // transaction's gas, it is best to keep them low in cases like this one, to
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }
    modifier nonReentrant() {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
        _status = _ENTERED;

        _;
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

pragma solidity ^0.8.0;
contract ERC721A is
    Context,
    ERC165,
    IERC721,
    IERC721Metadata,
    IERC721Enumerable
{
    using Address for address;
    using Strings for uint256;

    struct TokenOwnership {
        address addr;
        uint64 startTimestamp;
    }

    struct AddressData {
        uint128 balance;
        uint128 numberMinted;
    }

    uint256 private currentIndex = 0;

    uint256 internal immutable collectionSize;
    uint256 internal immutable maxBatchSize;
    string private _name;
    string private _symbol;
    // An empty struct value does not necessarily mean the token is unowned. See ownershipOf implementation for details.
    mapping(uint256 => TokenOwnership) private _ownerships;
    mapping(address => AddressData) private _addressData;
    mapping(uint256 => address) private _tokenApprovals;
    mapping(address => mapping(address => bool)) private _operatorApprovals;
    constructor(
        string memory name_,
        string memory symbol_,
        uint256 maxBatchSize_,
        uint256 collectionSize_
    ) {
        require(
            collectionSize_ > 0,
            "ERC721A: collection must have a nonzero supply"
        );
        require(maxBatchSize_ > 0, "ERC721A: max batch size must be nonzero");
        _name = name_;
        _symbol = symbol_;
        maxBatchSize = maxBatchSize_;
        collectionSize = collectionSize_;
    }
    function totalSupply() public view override returns (uint256) {
        return currentIndex;
    }
    function tokenByIndex(uint256 index)
        public
        view
        override
        returns (uint256)
    {
        require(index < totalSupply(), "ERC721A: global index out of bounds");
        return index;
    }
    function tokenOfOwnerByIndex(address owner, uint256 index)
        public
        view
        override
        returns (uint256)
    {
        require(index < balanceOf(owner), "ERC721A: owner index out of bounds");
        uint256 numMintedSoFar = totalSupply();
        uint256 tokenIdsIdx = 0;
        address currOwnershipAddr = address(0);
        for (uint256 i = 0; i < numMintedSoFar; i++) {
            TokenOwnership memory ownership = _ownerships[i];
            if (ownership.addr != address(0)) {
                currOwnershipAddr = ownership.addr;
            }
            if (currOwnershipAddr == owner) {
                if (tokenIdsIdx == index) {
                    return i;
                }
                tokenIdsIdx++;
            }
        }
        revert("ERC721A: unable to get token of owner by index");
    }
    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC165, IERC165)
        returns (bool)
    {
        return
            interfaceId == type(IERC721).interfaceId ||
            interfaceId == type(IERC721Metadata).interfaceId ||
            interfaceId == type(IERC721Enumerable).interfaceId ||
            super.supportsInterface(interfaceId);
    }
    function balanceOf(address owner) public view override returns (uint256) {
        require(
            owner != address(0),
            "ERC721A: balance query for the zero address"
        );
        return uint256(_addressData[owner].balance);
    }

    function _numberMinted(address owner) internal view returns (uint256) {
        require(
            owner != address(0),
            "ERC721A: number minted query for the zero address"
        );
        return uint256(_addressData[owner].numberMinted);
    }

    function ownershipOf(uint256 tokenId)
        internal
        view
        returns (TokenOwnership memory)
    {
        require(_exists(tokenId), "ERC721A: owner query for nonexistent token");

        uint256 lowestTokenToCheck;
        if (tokenId >= maxBatchSize) {
            lowestTokenToCheck = tokenId - maxBatchSize + 1;
        }

        for (uint256 curr = tokenId; curr >= lowestTokenToCheck; curr--) {
            TokenOwnership memory ownership = _ownerships[curr];
            if (ownership.addr != address(0)) {
                return ownership;
            }
        }

        revert("ERC721A: unable to determine the owner of token");
    }
    function ownerOf(uint256 tokenId) public view override returns (address) {
        return ownershipOf(tokenId).addr;
    }
    function name() public view virtual override returns (string memory) {
        return _name;
    }
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }
    function tokenURI(uint256 tokenId)
        public
        view
        virtual
        override
        returns (string memory)
    {
        require(
            _exists(tokenId),
            "ERC721Metadata: URI query for nonexistent token"
        );

        string memory baseURI = _baseURI();
        return
            bytes(baseURI).length > 0
                ? string(abi.encodePacked(baseURI, tokenId.toString()))
                : "";
    }
    function _baseURI() internal view virtual returns (string memory) {
        return "";
    }
    function approve(address to, uint256 tokenId) public override {
        address owner = ERC721A.ownerOf(tokenId);
        require(to != owner, "ERC721A: approval to current owner");

        require(
            _msgSender() == owner || isApprovedForAll(owner, _msgSender()),
            "ERC721A: approve caller is not owner nor approved for all"
        );

        _approve(to, tokenId, owner);
    }
    function getApproved(uint256 tokenId)
        public
        view
        override
        returns (address)
    {
        require(
            _exists(tokenId),
            "ERC721A: approved query for nonexistent token"
        );

        return _tokenApprovals[tokenId];
    }
    function setApprovalForAll(address operator, bool approved)
        public
        override
    {
        require(operator != _msgSender(), "ERC721A: approve to caller");

        _operatorApprovals[_msgSender()][operator] = approved;
        emit ApprovalForAll(_msgSender(), operator, approved);
    }
    function isApprovedForAll(address owner, address operator)
        public
        view
        virtual
        override
        returns (bool)
    {
        return _operatorApprovals[owner][operator];
    }
    
    function _exists(uint256 tokenId) internal view returns (bool) {
        return tokenId < currentIndex;
    }

    function _safeMint(address to, uint256 quantity) internal {
        _safeMint(to, quantity, "");
    }
    function _safeMint(
        address to,
        uint256 quantity,
        bytes memory _data
    ) internal {
        uint256 startTokenId = currentIndex;
        require(to != address(0), "ERC721A: mint to the zero address");
        require(!_exists(startTokenId), "ERC721A: token already minted");
        require(quantity <= maxBatchSize, "ERC721A: quantity to mint too high");

        _beforeTokenTransfers(address(0), to, startTokenId, quantity);

        AddressData memory addressData = _addressData[to];
        _addressData[to] = AddressData(
            addressData.balance + uint128(quantity),
            addressData.numberMinted + uint128(quantity)
        );
        _ownerships[startTokenId] = TokenOwnership(to, uint64(block.timestamp));

        uint256 updatedIndex = startTokenId;

        for (uint256 i = 0; i < quantity; i++) {
            emit Transfer(address(0), to, updatedIndex);
            require(
                _checkOnERC721Received(address(0), to, updatedIndex, _data),
                "ERC721A: transfer to non ERC721Receiver implementer"
            );
            updatedIndex++;
        }

        currentIndex = updatedIndex;
        _afterTokenTransfers(address(0), to, startTokenId, quantity);
    }
    function _transfer(
        address from,
        address to,
        uint256 tokenId
    ) internal {
        TokenOwnership memory prevOwnership = ownershipOf(tokenId);


        require(
            prevOwnership.addr == from,
            "ERC721A: transfer from incorrect owner"
        );
        require(to != address(0), "ERC721A: transfer to the zero address");

        _beforeTokenTransfers(from, to, tokenId, 1);
        _approve(address(0), tokenId, prevOwnership.addr);

        _addressData[from].balance -= 1;
        _addressData[to].balance += 1;
        _ownerships[tokenId] = TokenOwnership(to, uint64(block.timestamp));
        // Set the slot of tokenId+1 explicitly in storage to maintain correctness for ownerOf(tokenId+1) calls.
        uint256 nextTokenId = tokenId + 1;
        if (_ownerships[nextTokenId].addr == address(0)) {
            if (_exists(nextTokenId)) {
                _ownerships[nextTokenId] = TokenOwnership(
                    prevOwnership.addr,
                    prevOwnership.startTimestamp
                );
            }
        }

        emit Transfer(from, to, tokenId);
        _afterTokenTransfers(from, to, tokenId, 1);
    }
    function _approve(
        address to,
        uint256 tokenId,
        address owner
    ) private {
        _tokenApprovals[tokenId] = to;
        emit Approval(owner, to, tokenId);
    }

    uint256 public nextOwnerToExplicitlySet = 0;
    function _setOwnersExplicit(uint256 quantity) internal {
        uint256 oldNextOwnerToSet = nextOwnerToExplicitlySet;
        require(quantity > 0, "quantity must be nonzero");
        uint256 endIndex = oldNextOwnerToSet + quantity - 1;
        if (endIndex > collectionSize - 1) {
            endIndex = collectionSize - 1;
        }
        require(_exists(endIndex), "not enough minted yet for this cleanup");
        for (uint256 i = oldNextOwnerToSet; i <= endIndex; i++) {
            if (_ownerships[i].addr == address(0)) {
                TokenOwnership memory ownership = ownershipOf(i);
                _ownerships[i] = TokenOwnership(
                    ownership.addr,
                    ownership.startTimestamp
                );
            }
        }
        nextOwnerToExplicitlySet = endIndex + 1;
    }
    function _checkOnERC721Received(
        address from,
        address to,
        uint256 tokenId,
        bytes memory _data
    ) private returns (bool) {
        if (to.isContract()) {
            try
                IERC721Receiver(to).onERC721Received(
                    _msgSender(),
                    from,
                    tokenId,
                    _data
                )
            returns (bytes4 retval) {
                return retval == IERC721Receiver(to).onERC721Received.selector;
            } catch (bytes memory reason) {
                if (reason.length == 0) {
                    revert(
                        "ERC721A: transfer to non ERC721Receiver implementer"
                    );
                } else {
                    assembly {
                        revert(add(32, reason), mload(reason))
                    }
                }
            }
        } else {
            return true;
        }
    }
    function _beforeTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}
    function _afterTokenTransfers(
        address from,
        address to,
        uint256 startTokenId,
        uint256 quantity
    ) internal virtual {}
}
//Membership is not transferable asset but can get revoked if not paid annually

contract CATSMembership is Ownable, ERC721A, ReentrancyGuard {
    bool public publicSale = false;
    uint256 public maxPerTx = 1; 
    uint256 public maxPerAddress = 1;
    uint256 public maxToken = 10000000000; 
    uint256 public price = 0.25 ether;
    uint256 public charterPrice = 0.15 ether;
    uint256 public contractOwns = 0;
    string private _baseTokenURI;
    address private contractAddress = address(this);
    mapping(address=>bool) public Admin;
    mapping(address=>bool) public charterMember;
    

    constructor() ERC721A("CATS Membership", "CATSM", maxPerTx, maxToken){ 
        Admin[msg.sender] = true;
    }

    event charterMemberUpdated(address _charterMember);
    
    event AdminUpdated(address indexed admin);

    modifier callerIsUser() {
        require(tx.origin == msg.sender, "The caller is another contract");
        _;
    }
    modifier isAdmin() {
        require(Admin[msg.sender], "You are not an Admin");
        _;
    }
     modifier isCharterMember() {
        require(charterMember[msg.sender], "You are not a Charter Member");
        _;
    }

    function numberMinted(address owner) public view returns (uint256) {
        return _numberMinted(owner);
    }

    //Contract token owned from revokes. 

    function contractTokenId() public view returns (uint256) {
        return ERC721A.tokenOfOwnerByIndex(contractAddress, 0);
    }
 
    //Transfer Functions. If not paid annually, membership can get revoked or if member is involved in suspicious activity.

    function adminTransfer(address from, uint256 tokenId) external isAdmin{
        contractTransfer( from, tokenId);
    }

    function transfer( address from, address to, uint256 tokenId) private{
        ERC721A._transfer(from, to, tokenId);
         
    }
    function contractTransfer( address from, uint256 tokenId) private{
        ERC721A._transfer(from, contractAddress, tokenId);
        contractOwns ++;
        
    }

    function getOwnershipData(uint256 tokenId) external view returns (TokenOwnership memory){
        return ownershipOf(tokenId);
    }

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory){
        require( _exists(tokenId), "ERC721Metadata: URI query for nonexistent token");
        string memory _tokenURI = super.tokenURI(tokenId);
        return
            bytes(_tokenURI).length > 0
                ? string(abi.encodePacked(_tokenURI, ".json"))
                : "";
    }
    
    //Mint Functions Prices may change

    function mint() external payable callerIsUser{
        require(publicSale, "SALE_HAS_NOT_STARTED_YET");
        require(numberMinted(msg.sender) + maxPerTx <= maxPerAddress, "PER_WALLET_LIMIT_REACHED");
        require(totalSupply() + maxPerTx <= maxToken, "NOT_ENOUGH_SUPPLY_TO_MINT_DESIRED_AMOUNT");
        require(balanceOf(msg.sender) + maxPerTx <= maxPerAddress, "PER_WALLET_LIMIT_REACHED");
        require(msg.value == (price), "INVALID_ETH");
        if(contractOwns  >= maxPerTx ){
            
            transfer(contractAddress, msg.sender, contractTokenId() );
          contractOwns --;
        }
        else{
            _safeMint(msg.sender, maxPerTx);
            
        }
        
    }

    function chartermint() external payable callerIsUser isCharterMember{
        require(publicSale, "SALE_HAS_NOT_STARTED_YET");
        require(numberMinted(msg.sender) + maxPerTx <= maxPerAddress, "PER_WALLET_LIMIT_REACHED");
        require(totalSupply() + maxPerTx <= maxToken, "NOT_ENOUGH_SUPPLY_TO_MINT_DESIRED_AMOUNT");
        require(balanceOf(msg.sender) + maxPerTx <= maxPerAddress, "PER_WALLET_LIMIT_REACHED");
        require(msg.value == (charterPrice), "INVALID_ETH");
        if(contractOwns  >= maxPerTx ){
            
            transfer(contractAddress, msg.sender, contractTokenId() );
          contractOwns --;
        }
        else{
            _safeMint(msg.sender, maxPerTx);
            
        }
    }

    function ownerMint(address _address, uint256 quantity) external onlyOwner {
        _safeMint(_address, quantity);
    }

    //Base uri will be updated frequently as new members join and leave.

    function _baseURI() internal view virtual override returns (string memory) {
        return _baseTokenURI;
    }

    //Members update
  
    function _setAdmin(address admin) private{
    Admin[admin] = !Admin[admin];
    }

    function updateAdmin(address admin ) public virtual onlyOwner{
    require( admin != address(0), "Admin: new Admin is the zero address");
    _setAdmin(admin);
    emit AdminUpdated(admin);
    }

    function _setCharterMember(address _charterMember) private{
    charterMember[_charterMember] = !charterMember[_charterMember];
    }

    function updateCharterMember(address _charterMember ) public virtual onlyOwner{
    require( _charterMember != address(0), "Charter: new Charter is the zero address");
    _setCharterMember(_charterMember);
    emit charterMemberUpdated(_charterMember);
    }

    //Price Update

    function setPrice(uint256 _NewPrice, uint256 _NewCharterPrice) external onlyOwner {
        price = _NewPrice;
        charterPrice = _NewCharterPrice;
    }

    function flipPublicSaleState() external onlyOwner {
        publicSale = !publicSale;
    }

    function setBaseURI(string calldata baseURI) external onlyOwner {
        _baseTokenURI = baseURI;
    }

    function withdraw() external onlyOwner {
        payable(msg.sender).transfer(address(this).balance);
    }
}