// File: @openzeppelin/contracts/utils/introspection/IERC165.sol



// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: contracts/IBytesChunk.sol



// SPDX-License-Identifier: Unlicense

pragma solidity ^0.8.20;

interface IBytesChunk {
  function data() external pure returns (bytes memory);
}

// File: contracts/IDataCompiler.sol



// SPDX-License-Identifier: Unlicense

pragma solidity ^0.8.20;

interface IDataCompiler {
  function BEGIN_JSON() external view returns (string memory);
  function END_JSON() external view returns (string memory);

  function HTML_HEAD_START() external view returns (string memory);
  function HTML_HEAD_END() external view returns (string memory);
  function HTML_FOOT() external view returns (string memory);

  function BEGIN_SCRIPT() external view returns (string memory);
  function END_SCRIPT() external view returns (string memory);

  function BEGIN_SCRIPT_DATA_COMPRESSED() external view returns (string memory);
  function END_SCRIPT_DATA_COMPRESSED() external view returns (string memory);
  function END_SCRIPT_JS_DATA_COMPRESSED() external view returns (string memory);
  function END_SCRIPT_SVG_DATA_COMPRESSED() external view returns (string memory);

  function BEGIN_METADATA_VAR(string memory name, bool omitQuotes) external pure returns (string memory);
  function END_METADATA_VAR(bool omitQuotes, bool last) external pure returns (string memory);

  function SCRIPT_VAR( string memory name, string memory value, bool omitQuotes) external pure returns (string memory);

  function encodeURI(string memory str) external pure returns (string memory);

  function compileDataChunks(address[] memory chunks) external view returns (string memory);
  function compileBytesChunks(address[] memory chunks) external view returns (bytes memory);

  function uint2str(uint256 _i) external pure returns (string memory _uintAsString);
  function toHex32String (bytes32) external pure returns (string memory);
  function toHex16String (bytes16) external pure returns (string memory);
}

// File: contracts/IStringChunk.sol



// SPDX-License-Identifier: Unlicense

pragma solidity ^0.8.20;

interface IStringChunk {
  function data() external pure returns (string memory);
}

// File: contracts/ITokenURISupplier.sol



// SPDX-License-Identifier: Unlicense

pragma solidity ^0.8.19;

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

interface ITokenURISupplier is IERC165 {
  function tokenURI(uint256 id) external view returns (string memory);
}

// File: contracts/RadioactivePunksRenderer.sol



/*

SPDX-License-Identifier: Unlicense

................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
................................................................................
....................,oxddxddddddddddddddddddddddddddddd:........................
..................''ck0OkxxxxxxxxxxxxxxxxxxxxxxxxxxkOOOl,'......................
................'oxxkO0Oc..........................;k0Okkxd;....................
.............',,:xO0kddo;..........................,lddkO0kc,,'.................
.............lkkOO0Ol. .:kOOOOOOOOOOOOOOOOOOOOOOOOOl. .:O0OOkkd,................
.............oO0koll:,',o0KKKKKKKKKKKKKKKKKK0000K00d;'';llok00d,................
.............o00o.  ,k0000KKKKKKKKKKKKKKKK000000KK0000O:  .lO0d,................
.............oO0o.  ,kKKKKKKKKKKKKKKKKKKKK0KKKKKKKKKKK0:  .cO0d,................
.............oO0o.  ,kKKKKKKKKKKKKKKKKKKKKKKKKK0KK0KKK0:  .cO0d,................
.........,cclxO0d.  'kKKKKKKKKKK0000KKK00KKKKKK0KKKKKK0:  .cO0d,................
.........cO0000Oo.  'kK0KK000000KKKKKKKKKKKKKKK00000KK0:  .cO0d,................
.....'cllxO0kl;,.   'kKK0KKOl;,ckKKKKKK00KKKKKKkc,;lOK0:  .cO0d,................
.....;k00OOOx,      ,kKKK0Kk'  .dKKKKKK000KKKKKd.  'kK0:  .cO0d,................
.....;kOOl,',coooooox00KKKKk'  .dKKKKKKKKKK0KKKd.  'kKO:  .cO0d,................
.....;k0O:  .l0KKK0000KK0KKk;  'xKK00KKKKKKKKKKx'  ;kK0:  .cO0d,................
.....;kOO:  .l0K00O000KKKKK0kddx0KKK00KKK00KKKKOxddk0K0:  .cO0d,................
.....:k0Oc...ckkxxxxk0KKK0KKKKK00KKK00000000KKKKKKKKKK0:  .cO0d,................
.....;k0Okxxo,......;OK000KKKKKKK000000000K0KK00KKKKKK0:  .cO0d,................
.....,oxxk00k:...   ,kK00KKK00KKK0000K0kxddddddxOKK0KK0:  .cO0d,................
........'lO0OOkkl.  'kKKKKKKKK00KK0KKK0c..     'xK00KK0:  .cO0d,................
.........;oodkO0o.  'kKKKKKKKK0KKK00KK0o,,''''':kK00KK0:  .cO0d,................
............'oO0o.  'kKKKKKKKKKKKK00KK00000000000KK0KK0:  .cO0d,................
............'oO0o.  ,kKKKKKKK000KKKK00000KKKKK0KK00KKK0:  .cO0d,................
.............oO0o.  ,kKKKKKKKKKKKKKK00000KKKKKKK00K0KK0:  .cO0d,................
.............oO0o.  ,kKKKKK0KKKKKKKK0K0dc::::::lkKKKKK0:  .cO0d,................
.............oO0o.  ,kKKKK00KKKKKK0KKK0:.      .dK0KKK0:  .cO0d,................
.............oO0o.  ,kKKKK0KK0KK0KKKKK0xllcccccoOKKKKK0:  .cO0d,................
.............oO0o.  ,kKKKK0KK000KK0KKKKKKKKKKKKKKKK000O:  .lO0d,................
.............oO0o.  ,kKKKK0KK0KK0KKKKKKKKKKKKKKKKK0d;'';llokOOd,................
.............oO0o.  ,kKKKKKKKKK0OOOOOOOOOOOOOOOOOOOl. .:O0OOkko,................
.............oO0o.  ,kKKKK0K0KKx;..................,lddkO0kc,,'.................
.............oO0o.  ,kKKKKK00KKd.   ...............;k0Okxxd;....................
.............oO0o.  ,kKKKKK00KKd.  .oxxxxxxxxxxxxxxkO0Ol'''.....................
.............oO0o.  ,kKKKKK00KKd.  ,xOOkxxddddddddddddd:........................
.............oO0o.  ,kKKKKK00KKd.  'x0Ol''......................................
.............oO0o.  ,kKKKKK000Kd.  ,x0Oc........................................

THE CRYPTOPOCALYPSE DAWNED
These punks survived.

@art  : pixantle.eth
@tech : whitelights.eth

@dev  : This contract offers a `tokenURI` function that supplies detailed JSON
        and SVG image information for all existing Radioactive Punk NFTs without
        the need for external resources. Users can view the HTML document
        provided as the animation_url in any web browser, and can download their
        punk in 4K resolution as a PNG image through the right-click function.

        The main purpose of this is to serve as the `METADATA_PROVENANCE_HASH`
        feature in the original $RPUNK NFT contract, which aims to securely
        store and preserve Radioactive Punks data for the lifespan of the
        Ethereum network.

        The secondary purpose is to push the boundaries of what is possible with
        on-chain rendering. This contract uses a combination of compressed and
        uncompressed on-chain SVG data, on-chain HTML data, and on-chain JS to
        render a fully responsive and 4k downloadable Radioactive Punk in the
        browser without the need for any external resources.

        Four other contracts are essential for this contract to function:
          - SVG Chunk 1 & 2, contain the SVG data for each punk when
            combined and unzipped with gzip
          - RPUNK Trait Hyperstructure, contains every trait of every RPUNK
            encoded into a single public bytes structure for easy access and
            reuse as arbitrary seed data for other projects on-chain
          - Data Compiler, provides helpful functions for concatenating and
            encoding data into valid Data URI format
*/

pragma solidity ^0.8.20;

import './ITokenURISupplier.sol';
import './IDataCompiler.sol';
import './IStringChunk.sol';
import './IBytesChunk.sol';

contract RadioactivePunksRenderer is ITokenURISupplier {
  address public immutable owner;

  string private constant name = "Radioactive Punk #";
  string private constant script = '<script>const getByteAsInt=(t,n)=>{const e=t*2;const o=n.charAt(e)+n.charAt(e+1);return parseInt(o,16)};const render=(t,i)=>{const n=document.querySelectorAll(".icon");n.forEach(t=>{t.remove()});if(i==="00000000000000000000000000000000"){return}const c=[698,2536,60,370,528,246,420,201,1360,878,201];const s=getByteAsInt(0,i);const a=getByteAsInt(1,i);const e=getByteAsInt(2,i);const d=getByteAsInt(3,i);for(let o=3;o<i.length/2;o++){if(o==15){continue}let n=getByteAsInt(o,i);if(o===7){continue}if(o===12&&n===0){continue}let e=`${o}-${n}`;if(o===6){let t=getByteAsInt(o+1,i);if(n===1){e=`${e}-${t}-${s}`}if(n===2){e=`${e}-${t}`}}if(o===13&&n!==12){e=`${e}-${s}`}if(o===11){e=`${e}-${s}`}if(o===9){e=`${e}-${s}`}if(o==3&&a===0){e=`${e}-${a}`}if(o===12&&a===0){e=`${o}-${d}`;e=`${e}-${a}`}else if(o===12&&a===1){e=`${o}-${d}`}if(o===10&&n===4){e=`${e}-${s}`}if(o===14){e=`${o+1}-${n}`}if(c.includes(parseInt(t))){e=t}const $=document.createElementNS("http://www.w3.org/2000/svg","svg");$.classList.add("icon");$.innerHTML=`<use href="#${e}"></use>`;document.querySelector(".c").appendChild($)}};window.addEventListener("contextmenu",t=>{t.preventDefault();const n=`data:image/svg+xml;base64,${btoa((new XMLSerializer).serializeToString(document.querySelector(".c")))}`;const o=new Image;o.src=n;o.onload=()=>{const t=document.createElement("canvas");t.width=t.height=4e3;const n=t.getContext("2d");n.drawImage(o,0,0,t.width,t.height);const e=document.createElement("a");e.href=t.toDataURL("image/png",1);e.download=`Radioactive-Punk-${tid}.png`;e.append(t);e.click();e.remove()}});const onResize=t=>{var n=document.querySelector(".c");let e=window.innerWidth;if(window.innerHeight<=window.innerWidth){e=window.innerHeight}const o=Math.floor(e/12)*12;n.setAttribute("width",o);n.setAttribute("height",o)};document.body.style="margin: 0;padding: 0;text-align: center;width: 100%;height: 100%;background: #1E2E3D";document.querySelector(".c").style="background: #1D2E3D;position: absolute;margin: auto;top: 0;left: 0;bottom: 0;right: 0;aspect-ratio: 1;margin: auto;";render(tid,p);onResize();window.addEventListener("resize",onResize);</script>';
  address private compilerAddress = address(0);
  address private encodedPunksAddress = address(0);
  address[2] private rpunksSVGDataAddresses = [address(0), address(0)];

  error DNE();

  constructor() {
    owner = msg.sender;
  }

  function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165) returns (bool) {
    return interfaceId == type(ITokenURISupplier).interfaceId;
  }

  function setCompilerAddress(address newAddress) public {
    require(msg.sender == owner);
    compilerAddress = newAddress;
  }

  function setEncodedPunksAddress(address chunk) public {
    require(msg.sender == owner);
    encodedPunksAddress = chunk;
  }

  function setRPunksSVGDataAddresses(address chunk1, address chunk2) public {
    require(msg.sender == owner);
    rpunksSVGDataAddresses[0] = chunk1;
    rpunksSVGDataAddresses[1] = chunk2;
  }

  function tokenURI(uint256 tokenId) public view returns (string memory) {
    IStringChunk rpunkSVGData1 = IStringChunk(rpunksSVGDataAddresses[0]);
    IStringChunk rpunkSVGData2 = IStringChunk(rpunksSVGDataAddresses[1]);
    IDataCompiler compiler = IDataCompiler(compilerAddress);

    /**
     * @dev: Since the indexing of punks within our Hyperstructure is not the
     *       same as tokenByIndex on the original contract, we iterate over
     *       this array to find the token ID's offset within the Hyperstructure
     */
    uint16 offset;
    for (; offset <= 1614;) {
      if (offset == 1614)
        revert DNE();

      if (TOKEN_ID_TO_BYTES_LOOKUP[offset] == tokenId) {
        break;
      }
      unchecked { offset++; }
    }
    string memory tokenIdStr = compiler.uint2str(tokenId);

    /**
     *
     * @dev We break up calls to string.concat() in order to avoid stack too
     *      deep errors and avoid inflating the contract size.
     */

    string memory theAttributes = "";

    {
      theAttributes = string.concat(
        compiler.BEGIN_METADATA_VAR("attributes", true),
        '['
      );
    }

    IBytesChunk punkByteData1 = IBytesChunk(encodedPunksAddress);
    bytes memory allPunks = punkByteData1.data();
    bytes16 punkBytes;
    for (uint i = 0; i < 15; i++) {
      punkBytes |= bytes16(allPunks[offset * 15 + i] & 0xFF) >> (i * 8);
      theAttributes =
          string.concat(
            theAttributes,
            '{"trait_type":"',
              compiler.encodeURI(string(TRAIT_NAMES[i])),
            '","value":"',
              compiler.encodeURI(string(TRAIT_VALUES[i][uint256(uint8(punkBytes[i]))])),
            i == 14 ? '"}' : '"},'
          );
    }

    {
      theAttributes = string.concat(
        theAttributes,
        ']',
        compiler.END_METADATA_VAR(true, false)
      );
    }

    string memory theJSON = compiler.BEGIN_JSON();

    {
      theJSON =
        string.concat(
          theJSON,
          compiler.BEGIN_METADATA_VAR("name", false),
          compiler.encodeURI(name),
          tokenIdStr,
          compiler.END_METADATA_VAR(false, false)
        );
    }

    {
      theJSON =
        string.concat(
          theJSON,
          compiler.BEGIN_METADATA_VAR("artist", false),
          "Pixantle",
          compiler.END_METADATA_VAR(false, false)
        );
    }

    {
      theJSON =
        string.concat(
          theJSON,
          compiler.BEGIN_METADATA_VAR("technologist", false),
          "White Lights",
          compiler.END_METADATA_VAR(false, false)
        );
    }

    {
      theJSON =
        string.concat(
          theJSON,
          theAttributes
        );
    }

    /**
     *
     * @dev for the animation URL we break up calls to compiler functions and
     *      string.concat in order to avoid hitting the max call stack size as
     *      well as inflating this contract's size
     */
    {
      theJSON =
        string.concat(
          theJSON,
          string.concat(
            compiler.BEGIN_METADATA_VAR("animation_url", false),
            compiler.HTML_HEAD_START(),
            compiler.HTML_HEAD_END(),
            compiler.BEGIN_SCRIPT_DATA_COMPRESSED(),
            string(abi.encodePacked(rpunkSVGData1.data(), rpunkSVGData2.data()))
          ),
          string.concat(
            compiler.END_SCRIPT_DATA_COMPRESSED(),
            compiler.END_SCRIPT_SVG_DATA_COMPRESSED(),
            compiler.BEGIN_SCRIPT(),
            compiler.SCRIPT_VAR(
              "tid",
              tokenIdStr,
              true
            ),
            compiler.SCRIPT_VAR(
              "p",
              string(abi.encodePacked(compiler.toHex16String(punkBytes))),
              false
            )
          ),
          string.concat(
            compiler.END_SCRIPT(),
            compiler.encodeURI(compiler.encodeURI(script)),
            compiler.HTML_FOOT(),
            compiler.END_METADATA_VAR(false, true)
          )
        );
    }

    {
      theJSON =
        string.concat(
          theJSON,
          compiler.END_JSON()
        );
    }

    return theJSON;
  }

  function getPunkDataAtOffset(uint punkIndex) public view returns (bytes16) {
    IBytesChunk punkByteData1 = IBytesChunk(encodedPunksAddress);
    bytes memory allPunks = punkByteData1.data();
    bytes16 result;
    // @dev: 16th byte is just padding of 00 as we have only 15 traits to parse
    for (uint i = 0; i < 15; i++) {
      result |= bytes16(allPunks[punkIndex * 15 + i] & 0xFF) >> (i * 8);
    }
    return result;
  }

  string[] public RADIOACTIVE_GLOW = [
    'Blue',
    'Radioactive Green',
    'Luminescent Green',
    'Glow In The Dark Green',
    'Pink',
    'Red',
    'Royal Blue',
    'Blue Glow',
    'Pink Glow',
    'Dangerous Green',
    'Dangerous Red',
    'Shiny Blue'
  ];

  string[] public MORTALITY = [
    'Dead',
    'Alive'
  ];

  string[] public CLONE = [
    'Unique',
    'Clone'
  ];

  string[] public HEAD = [
    'White',
    'Black',
    'Aquatic',
    'Pink',
    'Lizard',
    'Glow In The Dark',
    'Demon',
    'Rainbow',
    'Blue',
    'Clown',
    'Deep Blue',
    'Red',
    '100% Radioactive',
    'Purple'
  ];

  string[] public EYES = [
    'None',
    'Red',
    'Oaf',
    'Cute',
    'Coin Slot',
    'Scared',
    'Stoned',
    'Wide',
    'Derp',
    'Dot',
    'Explosive',
    'Shifty',
    'Small'
  ];

  string[] public GLASSES = [
    'None',
    'Nerd Glasses',
    'Old School Glasses',
    'Lazer Beam Visor',
    'Gold Visor',
    'Mini Shades',
    'Rockstar Shades',
    'Holiday Glasses',
    'Nipple Glasses',
    'Scientist Goggles',
    'Shades',
    'Lazer Visor'
  ];

  string[] public BEARD = [
    'None',
    'Bushy',
    'Scruffy',
    'Short'
  ];

  string[] public BEARD_COLOR = [
    'None',
    'Purple',
    'Red',
    'Green',
    'Blue',
    'Brown'
  ];

  string[] public MOUTH = [
    'Tiny',
    'Smile',
    'Normal',
    'Small',
    'Long',
    'Big',
    'Buck Tooth',
    'Big Grin',
    'Confused Smile',
    'Fangs',
    'Red'
  ];

  string[] public SMOKE = [
    'None',
    'Radioactive Blunt',
    'Hand Rolled',
    'Vape',
    'Cigarette'
  ];

  string[] public NOSE = [
    'Clown',
    'Long',
    'Button',
    'Nostrils',
    'Pokey',
    'Medium',
    'Small',
    'Royal Nose',
    'Dot'
  ];

  string[] public HAIR = [
    'None',
    'Marimo Moss Ball',
    'Rocket Red',
    'Brunette',
    'Jolly Rancher',
    'Palette Punk',
    'Purple',
    'Messy Brunette',
    'Dot'
  ];

  string[] public HORNS = [
    'None',
    'True'
  ];

  string[] public HAT = [
    'None',
    'Trucker Cap',
    'Party Hat',
    'Big Money',
    'Red Beanie',
    'Teal Beanie',
    'Purple Beanie',
    'Green Beanie',
    'Miners Helmet',
    'Red Baseball Cap',
    'Viking Helmet',
    'Strawberry',
    'Big Brain',
    'Royal Crown',
    'Sweat Band',
    'Sheriff',
    'Purple Wig',
    'Dunce Cap',
    'Blue Bowler'
  ];

  string[] public GUN = [
    'None',
    'Pistol',
    'Gold AK47',
    'Pink AK47',
    'Aqua AK47',
    'Classic AK47',
    'AK420'
  ];

  string[][15] private TRAIT_VALUES = [
    RADIOACTIVE_GLOW,
    MORTALITY,
    CLONE,
    HEAD,
    EYES,
    GLASSES,
    BEARD,
    BEARD_COLOR,
    MOUTH,
    SMOKE,
    NOSE,
    HAIR,
    HORNS,
    HAT,
    GUN
  ];

  string[15] public TRAIT_NAMES = [
    'Radioactive Glow',
    'Mortality',
    'Clone',
    'Head',
    'Eyes',
    'Glasses',
    'Beard',
    'Beard Color',
    'Mouth',
    'Smoke',
    'Nose',
    'Hair',
    'Horns',
    'Hat',
    'Gun'
  ];

  uint16[1614] private TOKEN_ID_TO_BYTES_LOOKUP = [
    0,
    4,
    5,
    6,
    9,
    10,
    11,
    15,
    16,
    17,
    21,
    22,
    23,
    26,
    27,
    28,
    32,
    33,
    34,
    37,
    38,
    39,
    43,
    44,
    45,
    49,
    50,
    51,
    54,
    55,
    56,
    60,
    61,
    62,
    66,
    67,
    68,
    71,
    72,
    73,
    77,
    78,
    79,
    82,
    83,
    84,
    88,
    89,
    90,
    94,
    95,
    96,
    99,
    100,
    101,
    105,
    106,
    107,
    111,
    112,
    113,
    116,
    117,
    118,
    122,
    123,
    124,
    127,
    128,
    129,
    133,
    134,
    135,
    139,
    140,
    141,
    144,
    145,
    146,
    150,
    151,
    152,
    156,
    157,
    158,
    161,
    162,
    163,
    167,
    168,
    169,
    172,
    173,
    174,
    175,
    178,
    179,
    180,
    184,
    185,
    186,
    189,
    190,
    191,
    195,
    196,
    197,
    201,
    202,
    203,
    206,
    207,
    208,
    212,
    213,
    214,
    218,
    219,
    220,
    223,
    224,
    225,
    229,
    230,
    231,
    234,
    235,
    236,
    240,
    241,
    242,
    246,
    247,
    248,
    251,
    252,
    253,
    257,
    258,
    259,
    263,
    264,
    265,
    268,
    269,
    270,
    274,
    275,
    276,
    279,
    280,
    281,
    285,
    286,
    287,
    291,
    292,
    293,
    296,
    297,
    298,
    302,
    303,
    304,
    308,
    309,
    310,
    313,
    314,
    315,
    319,
    320,
    321,
    324,
    325,
    326,
    330,
    331,
    332,
    336,
    337,
    338,
    341,
    342,
    343,
    347,
    348,
    349,
    353,
    354,
    355,
    358,
    359,
    360,
    364,
    365,
    366,
    369,
    370,
    371,
    372,
    375,
    376,
    377,
    381,
    382,
    383,
    386,
    387,
    388,
    392,
    393,
    394,
    398,
    399,
    400,
    403,
    404,
    405,
    409,
    410,
    411,
    415,
    416,
    417,
    420,
    421,
    422,
    426,
    427,
    428,
    431,
    432,
    433,
    437,
    438,
    439,
    443,
    444,
    445,
    448,
    449,
    450,
    454,
    455,
    456,
    460,
    461,
    462,
    465,
    466,
    467,
    471,
    472,
    473,
    476,
    477,
    478,
    482,
    483,
    484,
    488,
    489,
    490,
    493,
    494,
    495,
    499,
    500,
    501,
    505,
    506,
    507,
    510,
    511,
    512,
    516,
    517,
    518,
    521,
    522,
    523,
    527,
    528,
    529,
    533,
    534,
    535,
    538,
    539,
    540,
    544,
    545,
    546,
    550,
    551,
    552,
    555,
    556,
    557,
    561,
    562,
    563,
    566,
    567,
    568,
    572,
    573,
    574,
    578,
    579,
    580,
    583,
    584,
    585,
    589,
    590,
    591,
    595,
    596,
    597,
    600,
    601,
    602,
    606,
    607,
    608,
    611,
    612,
    613,
    614,
    617,
    618,
    619,
    623,
    624,
    625,
    628,
    629,
    630,
    634,
    635,
    636,
    640,
    641,
    642,
    645,
    646,
    647,
    651,
    652,
    653,
    657,
    658,
    659,
    662,
    663,
    664,
    668,
    669,
    670,
    673,
    674,
    675,
    679,
    680,
    681,
    685,
    686,
    687,
    690,
    691,
    692,
    696,
    697,
    698,
    702,
    703,
    704,
    707,
    708,
    709,
    713,
    714,
    715,
    718,
    719,
    720,
    724,
    725,
    726,
    730,
    731,
    732,
    735,
    736,
    737,
    741,
    742,
    743,
    747,
    748,
    749,
    752,
    753,
    754,
    758,
    759,
    760,
    763,
    764,
    765,
    769,
    770,
    771,
    775,
    776,
    777,
    780,
    781,
    782,
    786,
    787,
    788,
    792,
    793,
    794,
    797,
    798,
    799,
    803,
    804,
    805,
    808,
    809,
    810,
    811,
    814,
    815,
    816,
    820,
    821,
    822,
    825,
    826,
    827,
    831,
    832,
    833,
    837,
    838,
    839,
    842,
    843,
    844,
    848,
    849,
    850,
    854,
    855,
    856,
    859,
    860,
    861,
    865,
    866,
    867,
    870,
    871,
    872,
    876,
    877,
    878,
    882,
    883,
    884,
    887,
    888,
    889,
    893,
    894,
    895,
    899,
    900,
    901,
    904,
    905,
    906,
    910,
    911,
    912,
    915,
    916,
    917,
    921,
    922,
    923,
    927,
    928,
    929,
    932,
    933,
    934,
    938,
    939,
    940,
    944,
    945,
    946,
    949,
    950,
    951,
    955,
    956,
    957,
    960,
    961,
    962,
    966,
    967,
    968,
    972,
    973,
    974,
    977,
    978,
    979,
    983,
    984,
    985,
    989,
    990,
    991,
    994,
    995,
    996,
    1000,
    1001,
    1002,
    1005,
    1006,
    1007,
    1008,
    1011,
    1012,
    1013,
    1017,
    1018,
    1019,
    1022,
    1023,
    1024,
    1028,
    1029,
    1030,
    1034,
    1035,
    1036,
    1039,
    1040,
    1041,
    1045,
    1046,
    1047,
    1051,
    1052,
    1053,
    1056,
    1057,
    1058,
    1062,
    1063,
    1064,
    1067,
    1068,
    1069,
    1073,
    1074,
    1075,
    1079,
    1080,
    1081,
    1084,
    1085,
    1086,
    1090,
    1091,
    1092,
    1096,
    1097,
    1098,
    1101,
    1102,
    1103,
    1107,
    1108,
    1109,
    1112,
    1113,
    1114,
    1118,
    1119,
    1120,
    1124,
    1125,
    1126,
    1129,
    1130,
    1131,
    1135,
    1136,
    1137,
    1141,
    1142,
    1143,
    1146,
    1147,
    1148,
    1152,
    1153,
    1154,
    1157,
    1158,
    1159,
    1163,
    1164,
    1165,
    1169,
    1170,
    1171,
    1174,
    1175,
    1176,
    1180,
    1181,
    1182,
    1186,
    1187,
    1188,
    1191,
    1192,
    1193,
    1197,
    1198,
    1199,
    1202,
    1203,
    1204,
    1205,
    1208,
    1209,
    1210,
    1214,
    1215,
    1216,
    1219,
    1220,
    1221,
    1225,
    1226,
    1227,
    1231,
    1232,
    1233,
    1236,
    1237,
    1238,
    1242,
    1243,
    1244,
    1248,
    1249,
    1250,
    1253,
    1254,
    1255,
    1259,
    1260,
    1261,
    1264,
    1265,
    1266,
    1270,
    1271,
    1272,
    1276,
    1277,
    1278,
    1281,
    1282,
    1283,
    1287,
    1288,
    1289,
    1293,
    1294,
    1295,
    1298,
    1299,
    1300,
    1304,
    1305,
    1306,
    1309,
    1310,
    1311,
    1315,
    1316,
    1317,
    1321,
    1322,
    1323,
    1326,
    1327,
    1328,
    1332,
    1333,
    1334,
    1338,
    1339,
    1340,
    1343,
    1344,
    1345,
    1349,
    1350,
    1351,
    1354,
    1355,
    1356,
    1360,
    1361,
    1362,
    1366,
    1367,
    1368,
    1371,
    1372,
    1373,
    1377,
    1378,
    1379,
    1383,
    1384,
    1385,
    1388,
    1389,
    1390,
    1394,
    1395,
    1396,
    1399,
    1400,
    1401,
    1402,
    1405,
    1406,
    1407,
    1411,
    1412,
    1413,
    1416,
    1417,
    1418,
    1422,
    1423,
    1424,
    1428,
    1429,
    1430,
    1433,
    1434,
    1435,
    1439,
    1440,
    1441,
    1445,
    1446,
    1447,
    1450,
    1451,
    1452,
    1456,
    1457,
    1458,
    1461,
    1462,
    1463,
    1467,
    1468,
    1469,
    1473,
    1474,
    1475,
    1478,
    1479,
    1480,
    1484,
    1485,
    1486,
    1490,
    1491,
    1492,
    1495,
    1496,
    1497,
    1501,
    1502,
    1503,
    1506,
    1507,
    1508,
    1512,
    1513,
    1514,
    1518,
    1519,
    1520,
    1523,
    1524,
    1525,
    1529,
    1530,
    1531,
    1535,
    1536,
    1537,
    1540,
    1541,
    1542,
    1546,
    1547,
    1548,
    1551,
    1552,
    1553,
    1557,
    1558,
    1559,
    1563,
    1564,
    1565,
    1568,
    1569,
    1570,
    1574,
    1575,
    1576,
    1580,
    1581,
    1582,
    1585,
    1586,
    1587,
    1591,
    1592,
    1593,
    1596,
    1597,
    1598,
    1599,
    1602,
    1603,
    1604,
    1608,
    1609,
    1610,
    1613,
    1614,
    1615,
    1619,
    1620,
    1621,
    1625,
    1626,
    1627,
    1630,
    1631,
    1632,
    1636,
    1637,
    1638,
    1642,
    1643,
    1644,
    1647,
    1648,
    1649,
    1653,
    1654,
    1655,
    1658,
    1659,
    1660,
    1664,
    1665,
    1666,
    1670,
    1671,
    1672,
    1675,
    1676,
    1677,
    1681,
    1682,
    1683,
    1687,
    1688,
    1689,
    1692,
    1693,
    1694,
    1698,
    1699,
    1700,
    1703,
    1704,
    1705,
    1709,
    1710,
    1711,
    1715,
    1716,
    1717,
    1720,
    1721,
    1722,
    1726,
    1727,
    1728,
    1732,
    1733,
    1734,
    1737,
    1738,
    1739,
    1743,
    1744,
    1745,
    1748,
    1749,
    1750,
    1754,
    1755,
    1756,
    1760,
    1761,
    1762,
    1765,
    1766,
    1767,
    1771,
    1772,
    1773,
    1777,
    1778,
    1779,
    1782,
    1783,
    1784,
    1788,
    1789,
    1790,
    1793,
    1794,
    1795,
    1796,
    1799,
    1800,
    1801,
    1805,
    1806,
    1807,
    1810,
    1811,
    1812,
    1816,
    1817,
    1818,
    1822,
    1823,
    1824,
    1827,
    1828,
    1829,
    1833,
    1834,
    1835,
    1839,
    1840,
    1841,
    1844,
    1845,
    1846,
    1850,
    1851,
    1852,
    1855,
    1856,
    1857,
    1861,
    1862,
    1863,
    1867,
    1868,
    1869,
    1872,
    1873,
    1874,
    1878,
    1879,
    1880,
    1884,
    1885,
    1886,
    1889,
    1890,
    1891,
    1895,
    1896,
    1897,
    1900,
    1901,
    1902,
    1906,
    1907,
    1908,
    1912,
    1913,
    1914,
    1917,
    1918,
    1919,
    1923,
    1924,
    1925,
    1929,
    1930,
    1931,
    1934,
    1935,
    1936,
    1940,
    1941,
    1942,
    1945,
    1946,
    1947,
    1951,
    1952,
    1953,
    1957,
    1958,
    1959,
    1962,
    1963,
    1964,
    1968,
    1969,
    1970,
    1974,
    1975,
    1976,
    1979,
    1980,
    1981,
    1985,
    1986,
    1987,
    1990,
    1991,
    1992,
    1993,
    1996,
    1997,
    1998,
    2002,
    2003,
    2004,
    2007,
    2008,
    2009,
    2013,
    2014,
    2015,
    2019,
    2020,
    2021,
    2024,
    2025,
    2026,
    2030,
    2031,
    2032,
    2036,
    2037,
    2038,
    2041,
    2042,
    2043,
    2047,
    2048,
    2049,
    2052,
    2053,
    2054,
    2058,
    2059,
    2060,
    2064,
    2065,
    2066,
    2069,
    2070,
    2071,
    2075,
    2076,
    2077,
    2081,
    2082,
    2083,
    2086,
    2087,
    2088,
    2092,
    2093,
    2094,
    2097,
    2098,
    2099,
    2103,
    2104,
    2105,
    2109,
    2110,
    2111,
    2114,
    2115,
    2116,
    2120,
    2121,
    2122,
    2126,
    2127,
    2128,
    2131,
    2132,
    2133,
    2137,
    2138,
    2139,
    2142,
    2143,
    2144,
    2148,
    2149,
    2150,
    2154,
    2155,
    2156,
    2159,
    2160,
    2161,
    2165,
    2166,
    2167,
    2171,
    2172,
    2173,
    2176,
    2177,
    2178,
    2182,
    2183,
    2184,
    2187,
    2188,
    2189,
    2190,
    2193,
    2194,
    2195,
    2199,
    2200,
    2201,
    2204,
    2205,
    2206,
    2210,
    2211,
    2212,
    2216,
    2217,
    2218,
    2221,
    2222,
    2223,
    2227,
    2228,
    2229,
    2233,
    2234,
    2235,
    2238,
    2239,
    2240,
    2244,
    2245,
    2246,
    2249,
    2250,
    2251,
    2255,
    2256,
    2257,
    2261,
    2262,
    2263,
    2266,
    2267,
    2268,
    2272,
    2273,
    2274,
    2278,
    2279,
    2280,
    2283,
    2284,
    2285,
    2289,
    2290,
    2291,
    2294,
    2295,
    2296,
    2300,
    2301,
    2302,
    2306,
    2307,
    2308,
    2311,
    2312,
    2313,
    2317,
    2318,
    2319,
    2323,
    2324,
    2325,
    2328,
    2329,
    2330,
    2334,
    2335,
    2336,
    2339,
    2340,
    2341,
    2345,
    2346,
    2347,
    2351,
    2352,
    2353,
    2356,
    2357,
    2358,
    2362,
    2363,
    2364,
    2368,
    2369,
    2370,
    2373,
    2374,
    2375,
    2379,
    2380,
    2381,
    2384,
    2385,
    2386,
    2387,
    2390,
    2391,
    2392,
    2396,
    2397,
    2398,
    2401,
    2402,
    2403,
    2407,
    2408,
    2409,
    2413,
    2414,
    2415,
    2418,
    2419,
    2420,
    2424,
    2425,
    2426,
    2430,
    2431,
    2432,
    2435,
    2436,
    2437,
    2441,
    2442,
    2443,
    2446,
    2447,
    2448,
    2452,
    2453,
    2454,
    2458,
    2459,
    2460,
    2463,
    2464,
    2465,
    2469,
    2470,
    2471,
    2475,
    2476,
    2477,
    2480,
    2481,
    2482,
    2486,
    2487,
    2488,
    2491,
    2492,
    2493,
    2497,
    2498,
    2499,
    2503,
    2504,
    2505,
    2508,
    2509,
    2510,
    2514,
    2515,
    2516,
    2520,
    2521,
    2522,
    2525,
    2526,
    2527,
    2531,
    2532,
    2533,
    2536,
    2537,
    2538,
    2542,
    2543,
    2544,
    2548,
    2549,
    2550,
    2553,
    2554,
    2555,
    2559,
    2560,
    2561,
    2565,
    2566,
    2567,
    2570,
    2571,
    2572,
    2576,
    2577,
    2578,
    2581,
    2582,
    2583,
    2584,
    2587,
    2588,
    2589,
    2593,
    2594,
    2595,
    2598,
    2599,
    2600,
    2604,
    2605,
    2606,
    2610,
    2611,
    2612,
    2615,
    2616,
    2617,
    2621,
    2622,
    2623,
    2627,
    2628,
    2629,
    2632,
    2633,
    2634,
    2638,
    2639,
    2640,
    2643,
    2644,
    2645,
    2649,
    2650,
    2651,
    2655,
    2656,
    2657,
    2660,
    2661,
    2662,
    2666,
    2667,
    2668,
    2672,
    2673,
    2674,
    2677,
    2678,
    2679,
    2683,
    2684,
    2685,
    2688,
    2689,
    2690,
    2694,
    2695,
    2696,
    2700,
    2701,
    2702,
    2705,
    2706,
    2707,
    2711,
    2712,
    2713,
    2717,
    2718,
    2719,
    2722,
    2723,
    2724,
    2728,
    2729,
    2730,
    2733,
    2734,
    2735,
    2739,
    2740,
    2741,
    2745,
    2746,
    2747,
    2750,
    2751,
    2752,
    2756,
    2757,
    2758,
    2762,
    2763,
    2764,
    2767,
    2768,
    2769,
    2773,
    2774,
    2775,
    2778,
    2779,
    2780,
    2781,
    2784,
    2785,
    2786,
    2790,
    2791,
    2792,
    2795,
    2796,
    2797,
    2801,
    2802,
    2803,
    2807,
    2808,
    2809,
    2812,
    2813,
    2814,
    2818,
    2819,
    2820,
    2824,
    2825,
    2826,
    2829,
    2830,
    2831,
    2835,
    2836,
    2837,
    2840,
    2841,
    2842,
    2846,
    2847,
    2848,
    2852,
    2853,
    2854,
    2857,
    2858,
    2859,
    2863,
    2864,
    2865,
    2869,
    2870,
    2871,
    2874,
    2875,
    2876,
    2880,
    2881,
    2882,
    2885,
    2886,
    2887,
    2891,
    2892,
    2893,
    2897,
    2898,
    2899,
    2902,
    2903,
    2904,
    2908,
    2909,
    2910,
    2914,
    2915,
    2916,
    2919,
    2920,
    2921,
    2925,
    2926,
    2927,
    2930,
    2931,
    2932,
    2936,
    2937,
    2938,
    2942,
    2943,
    2944,
    2947,
    2948,
    2949,
    2953,
    2954,
    2955,
    2959,
    2960,
    2961,
    2964,
    2965,
    2966,
    2970,
    2971,
    2972,
    2975,
    2976,
    2977,
    2978,
    2981,
    2982,
    2983,
    2987,
    2988,
    2989,
    2992,
    2993,
    2994,
    2998,
    2999
  ];
}