diff --git a/.gitignore b/.gitignore index dcf9720..b22d41f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ .sunodo .venv __pycache__ -cartridges \ No newline at end of file +cartridges +cache +data +frontend/app/contracts +!frontend/app/contracts/RivesScoreNFT.sol \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 89a61e5..66a3200 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,8 @@ WORKDIR /opt/tools RUN < bool: def cartridge_info(payload: CartridgePayload) -> bool: cartridge = helpers.select(c for c in Cartridge if c.id == payload.id).first() - LOGGER.info(cartridge) - if cartridge is not None: cartridge_dict = cartridge.to_dict(with_lazy=True) cartridge_dict['cover'] = base64.b64encode(cartridge_dict['cover']) @@ -255,7 +276,10 @@ def create_cartridge(cartridge_data,**metadata): if helpers.count(c for c in Cartridge if c.id == data_hash) > 0: raise Exception(f"Cartridge already exists") - cartridge_file = open(f"{riv_get_cartridges_path()}/{data_hash}",'wb') + cartridges_path = riv_get_cartridges_path() + if not os.path.exists(cartridges_path): + os.makedirs(cartridges_path) + cartridge_file = open(f"{cartridges_path}/{data_hash}",'wb') cartridge_file.write(cartridge_data) cartridge_file.close() @@ -266,16 +290,25 @@ def create_cartridge(cartridge_data,**metadata): Info(**cartridge_info_json) # check if cartridge runs - riv_get_cartridge_outcard(data_hash,0,None,None) + test_replay_file = open('misc/test.rivlog','rb') + test_replay = test_replay_file.read() + test_replay_file.close() + + # TODO: allow one of theses tests + outcard_raw, outhash, screenshot = replay_log(data_hash,test_replay,'',b'') + # riv_get_cartridge_outcard(data_hash,0,None,None) cartridge_cover = riv_get_cover(data_hash) if cartridge_cover is None or len(cartridge_cover) == 0: - cartridge_cover = riv_get_cartridge_screenshot(data_hash,0) + #cartridge_cover = riv_get_cartridge_screenshot(data_hash,0) + cartridge_cover = screenshot + user_address = metadata.get('msg_sender') + if user_address is not None: user_address = user_address.lower() c = Cartridge( id = data_hash, name = cartridge_info_json['name'], - user_address = metadata.get('msg_sender'), + user_address = user_address, created_at = metadata.get('timestamp') or 0, info = cartridge_info_json, cover = cartridge_cover @@ -290,7 +323,7 @@ def delete_cartridge(cartridge_id,**metadata): if cartridge is None: raise Exception(f"Cartridge doesn't exist") - if cartridge.user_address != metadata['msg_sender']: + if cartridge.user_address != metadata['msg_sender'].lower(): raise Exception(f"Sender not allowed") cartridge.delete() diff --git a/app/common.py b/app/common.py new file mode 100644 index 0000000..45fccbf --- /dev/null +++ b/app/common.py @@ -0,0 +1,138 @@ +import os +from enum import Enum +from PIL import Image, ImageFont, ImageDraw +from Crypto.Hash import SHA256 +import base58 +import tempfile +import io +import pickle + +from .protobuf_models import unixfs_pb2, merkle_dag_pb2 +from .settings import STORAGE_PATH + +DEFAULT_HEIGHT = 512 +BG_EXTRA_WIDTH = 400 +# MAIN_FONT_SIZE = 48 +# AUX_FONT_SIZE = 16 +MAIN_FONT_SIZE = 42 +AUX_FONT_SIZE = 28 + +initial_space = 30 +font2_initial_space = 60 +final_space = 10 +total_font_space = 80 + +class ScoreType(Enum): + default = 0 + scoreboard = 1 + tournament = 2 + + +class GameplayHash: + cartridge_replays = {} + cartridge_replays_filename = f"{STORAGE_PATH}/cartridge_replays.pkl" + def __new__(cls): + return cls + + @classmethod + def get_cartridge_replays(cls): + cartridge_replays = {} + if STORAGE_PATH is not None: + if os.path.exists(cls.cartridge_replays_filename): + f = open(cls.cartridge_replays_filename, 'rb') + cartridge_replays = pickle.load(f) + f.close() + else: + cartridge_replays = cls.cartridge_replays + return cartridge_replays + + @classmethod + def store_cartridge_replays(cls,cartridge_replays): + if STORAGE_PATH is not None: + with open(cls.cartridge_replays_filename, 'wb') as f: + pickle.dump(cartridge_replays, f) + else: + cls.cartridge_replays = cartridge_replays + + @classmethod + def add(cls, cartridge_id, replay_hash): + cartridge_replays = cls.get_cartridge_replays() + if cartridge_replays.get(cartridge_id) is None: cartridge_replays[cartridge_id] = {} + cartridge_replays[cartridge_id][replay_hash] = True + cls.store_cartridge_replays(cartridge_replays) + + @classmethod + def check(cls, cartridge_id, replay_hash): + cartridge_replays = cls.get_cartridge_replays() + return cartridge_replays.get(cartridge_id) is None \ + or cartridge_replays[cartridge_id].get(replay_hash) is None \ + or cartridge_replays[cartridge_id][replay_hash] == False + +def get_cid(data: bytes) -> str: + + unixf = unixfs_pb2.Data() + unixf.Type = 2 # file + unixf.Data = data + unixf.filesize = len(unixf.Data) + + mdag = merkle_dag_pb2.MerkleNode() + mdag.Data = unixf.SerializeToString() + + mdag_data = mdag.SerializeToString() + + h = SHA256.new() + h.update(mdag_data) + sha256_code = "12" + size = hex(h.digest_size)[2:] + digest = h.hexdigest() + combined = f"{sha256_code}{size}{digest}" + multihash = base58.b58encode(bytes.fromhex(combined)) + cid = multihash.decode('utf-8') + + return cid + + +def screenshot_add_score(screenshot_data: bytes, game: str, score: int, user: str) -> bytes: + screenshot_temp = tempfile.NamedTemporaryFile() + screenshot_file = screenshot_temp.file + screenshot_file.write(screenshot_data) + screenshot_file.flush() + + img = Image.open(screenshot_temp.name) + + screenshot_temp.close() + + height = int((DEFAULT_HEIGHT // img.size[1]) * img.size[1]) + width = int(height / img.size[1] * img.size[0]) + + space_between = (height - initial_space - final_space - 3 * total_font_space) // 2 + + resized_img = img.resize((width,height)) + + bg_img = Image.new('RGB', ( width + BG_EXTRA_WIDTH, height), color='#202020') + + draw = ImageDraw.Draw(bg_img) + + font28 = ImageFont.truetype('misc/font/Retro Gaming.ttf',size=28) + font42 = ImageFont.truetype('misc/font/Retro Gaming.ttf',size=42) + + draw.text((width + 10, initial_space), f"game",fill='#b3b3b3',font=font28) + draw.text((width + 10, font2_initial_space), f"{game}",fill='#b3b3b3',font=font42) + + draw.text((width + 10, initial_space + total_font_space + space_between), f"score",fill='#b3b3b3',font=font28) # 170 + draw.text((width + 10, font2_initial_space + total_font_space + space_between), f"{score}",fill='#b3b3b3',font=font42) # 200 + + draw.text((width + 10, initial_space + 2*(total_font_space + space_between)), f"user",fill='#b3b3b3',font=font28) # 300 + draw.text((width + 10, font2_initial_space + 2*(total_font_space + space_between)), f"{user}",fill='#b3b3b3',font=font42) # 330 + logo = Image.open('misc/Rives-Logo.png') + + bgc = bg_img.convert('RGBA') + bgc.paste(logo,(width + BG_EXTRA_WIDTH - 100,10),logo.convert('RGBA')) + + bgc.paste(resized_img,(0,0)) + + img_byte_arr = io.BytesIO() + bgc.save(img_byte_arr, format='PNG') + + return img_byte_arr.getvalue() + diff --git a/app/protobuf_models/merkle-dag.proto b/app/protobuf_models/merkle-dag.proto new file mode 100644 index 0000000..cf85e03 --- /dev/null +++ b/app/protobuf_models/merkle-dag.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +//package merkleDag; + +// An IPFS MerkleDAG Link +message MerkleLink { + bytes Hash = 1; // multihash of the target object + string Name = 2; // utf string name + uint64 Tsize = 3; // cumulative size of target object + + // user extensions start at 50 +} + +// An IPFS MerkleDAG Node +message MerkleNode { + repeated MerkleLink Links = 2; // refs to other objects + bytes Data = 1; // opaque user data + + // user extensions start at 50 +} diff --git a/app/protobuf_models/merkle_dag_pb2.py b/app/protobuf_models/merkle_dag_pb2.py new file mode 100644 index 0000000..8af2c49 --- /dev/null +++ b/app/protobuf_models/merkle_dag_pb2.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: protobuf/merkle-dag.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x19protobuf/merkle-dag.proto\"7\n\nMerkleLink\x12\x0c\n\x04Hash\x18\x01 \x01(\x0c\x12\x0c\n\x04Name\x18\x02 \x01(\t\x12\r\n\x05Tsize\x18\x03 \x01(\x04\"6\n\nMerkleNode\x12\x1a\n\x05Links\x18\x02 \x03(\x0b\x32\x0b.MerkleLink\x12\x0c\n\x04\x44\x61ta\x18\x01 \x01(\x0c\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'protobuf.merkle_dag_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _MERKLELINK._serialized_start=29 + _MERKLELINK._serialized_end=84 + _MERKLENODE._serialized_start=86 + _MERKLENODE._serialized_end=140 +# @@protoc_insertion_point(module_scope) diff --git a/app/protobuf_models/unixfs.proto b/app/protobuf_models/unixfs.proto new file mode 100644 index 0000000..ffc059e --- /dev/null +++ b/app/protobuf_models/unixfs.proto @@ -0,0 +1,26 @@ +syntax = "proto2"; + +package unixfs.pb; + +message Data { + enum DataType { + Raw = 0; + Directory = 1; + File = 2; + Metadata = 3; + Symlink = 4; + HAMTShard = 5; + } + + required DataType Type = 1; + optional bytes Data = 2; + optional uint64 filesize = 3; + repeated uint64 blocksizes = 4; + + optional uint64 hashType = 5; + optional uint64 fanout = 6; +} + +message Metadata { + optional string MimeType = 1; +} diff --git a/app/protobuf_models/unixfs_pb2.py b/app/protobuf_models/unixfs_pb2.py new file mode 100644 index 0000000..f69e550 --- /dev/null +++ b/app/protobuf_models/unixfs_pb2.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: unixfs.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0cunixfs.proto\x12\tunixfs.pb\"\xdc\x01\n\x04\x44\x61ta\x12&\n\x04Type\x18\x01 \x02(\x0e\x32\x18.unixfs.pb.Data.DataType\x12\x0c\n\x04\x44\x61ta\x18\x02 \x01(\x0c\x12\x10\n\x08\x66ilesize\x18\x03 \x01(\x04\x12\x12\n\nblocksizes\x18\x04 \x03(\x04\x12\x10\n\x08hashType\x18\x05 \x01(\x04\x12\x0e\n\x06\x66\x61nout\x18\x06 \x01(\x04\"V\n\x08\x44\x61taType\x12\x07\n\x03Raw\x10\x00\x12\r\n\tDirectory\x10\x01\x12\x08\n\x04\x46ile\x10\x02\x12\x0c\n\x08Metadata\x10\x03\x12\x0b\n\x07Symlink\x10\x04\x12\r\n\tHAMTShard\x10\x05\"\x1c\n\x08Metadata\x12\x10\n\x08MimeType\x18\x01 \x01(\t') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'unixfs_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _DATA._serialized_start=28 + _DATA._serialized_end=248 + _DATA_DATATYPE._serialized_start=162 + _DATA_DATATYPE._serialized_end=248 + _METADATA._serialized_start=250 + _METADATA._serialized_end=278 +# @@protoc_insertion_point(module_scope) diff --git a/app/replay.py b/app/replay.py index 69de09a..d7d719d 100644 --- a/app/replay.py +++ b/app/replay.py @@ -6,15 +6,18 @@ import json import re +from cartesi.abi import String, Bytes, Bytes32, Int, UInt, Address -from cartesi.abi import String, Bytes, Bytes32, Int, UInt - -from cartesapp.storage import helpers # TODO: create repo to avoid this relative import hassle -from cartesapp.manager import mutation, get_metadata, add_output, event, emit_event, contract_call # TODO: create repo to avoid this relative import hassle +from cartesapp.storage import helpers +from cartesapp.context import get_metadata +from cartesapp.input import mutation +from cartesapp.output import add_output, event, emit_event, contract_call from cartesapp.utils import bytes2str -from .setup import AppSettings, ScoreType, GameplayHash +from .settings import AppSettings from .riv import replay_log +from .common import ScoreType, GameplayHash, screenshot_add_score, get_cid +from .cartridge import Cartridge LOGGER = logging.getLogger(__name__) @@ -32,6 +35,7 @@ class Replay(BaseModel): args: String in_card: Bytes log: Bytes + user_alias: String # Outputs @@ -39,12 +43,15 @@ class Replay(BaseModel): @event() class ReplayScore(BaseModel): cartridge_id: Bytes32 - user_address: String + user_address: Address timestamp: UInt score: Int # default score score_type: Int = ScoreType.default.value # default, socoreboard, tournaments extra_score: Int = 0 extra: String = '' # extra field to maintain compatibility with socoreboard, tournaments... + user_alias: String = '' + screenshot_cid: String = '' + gameplay_hash: Bytes32 ### @@ -54,17 +61,26 @@ class ReplayScore(BaseModel): def replay(replay: Replay) -> bool: metadata = get_metadata() + gameplay_hash = sha256(replay.log) - if not GameplayHash.check(replay.cartridge_id.hex(),sha256(replay.log).hexdigest()): + if not GameplayHash.check(replay.cartridge_id.hex(),gameplay_hash.hexdigest()): msg = f"Gameplay already submitted" LOGGER.error(msg) add_output(msg,tags=['error']) return False + cartridge = helpers.select(c for c in Cartridge if c.id == replay.cartridge_id.hex()).first() + + if cartridge is None: + msg = f"Game not found" + LOGGER.error(msg) + add_output(msg,tags=['error']) + return False + # process replay LOGGER.info("Replaying cartridge...") try: - outcard_raw, outhash = replay_log(replay.cartridge_id.hex(),replay.log,replay.args,replay.in_card) + outcard_raw, outhash, screenshot = replay_log(replay.cartridge_id.hex(),replay.log,replay.args,replay.in_card) except Exception as e: msg = f"Couldn't replay log: {e}" LOGGER.error(msg) @@ -104,16 +120,26 @@ def replay(replay: Replay) -> bool: except Exception as e: LOGGER.info(f"Couldn't load score from json: {e}") + user_alias = replay.user_alias if len(replay.user_alias) else f"{metadata.msg_sender[:6]}...{metadata.msg_sender[-4:]}" + + final_screenshot = screenshot_add_score(screenshot,cartridge.name,score,user_alias) + + cid = get_cid(final_screenshot) + replay_score = ReplayScore( cartridge_id = replay.cartridge_id, user_address = metadata.msg_sender, + user_alias = user_alias, timestamp = metadata.timestamp, - score = score + score = score, + screenshot_cid = cid, + gameplay_hash = gameplay_hash.digest() ) add_output(replay.log,tags=['replay',replay.cartridge_id.hex()]) + add_output(final_screenshot,tags=['screenshot',replay.cartridge_id.hex()]) emit_event(replay_score,tags=['score','general',replay.cartridge_id.hex()]) - GameplayHash.add(replay.cartridge_id.hex(),sha256(replay.log).hexdigest()) + GameplayHash.add(replay.cartridge_id.hex(),gameplay_hash.hexdigest()) return True diff --git a/app/riv.py b/app/riv.py index ff80cd2..08e51f7 100644 --- a/app/riv.py +++ b/app/riv.py @@ -3,12 +3,12 @@ from pathlib import Path import tempfile -from .setup import AppSettings +from .settings import AppSettings, STORAGE_PATH def riv_get_cartridges_path(): if AppSettings.rivemu_path is None: # use riv os return f"/rivos/{AppSettings.cartridges_path}" - return AppSettings.cartridges_path + return f"{STORAGE_PATH or '.'}/{AppSettings.cartridges_path}" def riv_get_cartridge_info(cartridge_id): @@ -63,13 +63,12 @@ def riv_get_cartridge_screenshot(cartridge_id,frame): # use rivemu screenshot_temp = tempfile.NamedTemporaryFile() - screenshot_file = screenshot_temp.file cwd=str(Path(AppSettings.rivemu_path).parent.parent.absolute()) absolute_cartridge_path = os.path.abspath(f"{AppSettings.cartridges_path}/{cartridge_id}") args.append(AppSettings.rivemu_path) args.append(f"-cartridge={absolute_cartridge_path}") - args.append(f"-save-screenshot={screenshot_file.name}") + args.append(f"-save-screenshot={screenshot_temp.name}") args.append(f"-stop-frame={frame}") # args.append(f"-no-yield=y") result = subprocess.run(args, cwd=cwd) @@ -77,7 +76,7 @@ def riv_get_cartridge_screenshot(cartridge_id,frame): if result.returncode != 0: raise Exception(f"Error getting screenshot: {str(result.stderr)}") - cartridge_screenshot = open(screenshot_file.name,'rb').read() + cartridge_screenshot = open(screenshot_temp.name,'rb').read() screenshot_temp.close() return cartridge_screenshot @@ -88,6 +87,7 @@ def replay_log(cartridge_id,log,riv_args,in_card): outcard_path = "/run/outcard" incard_path = "/run/incard" outhash_path = "/run/outhash" + screenshot_path = "/run/screenshot" replay_file = open(replay_path,'wb') replay_file.write(log) @@ -95,6 +95,7 @@ def replay_log(cartridge_id,log,riv_args,in_card): if os.path.exists(outcard_path): os.remove(outcard_path) if os.path.exists(outhash_path): os.remove(outhash_path) + if os.path.exists(screenshot_path): os.remove(screenshot_path) if in_card is not None and len(in_card) > 0: incard_file = open(incard_path,'wb') @@ -108,6 +109,7 @@ def replay_log(cartridge_id,log,riv_args,in_card): run_args.extend(["--setenv", "RIV_REPLAYLOG", replay_path]) run_args.extend(["--setenv", "RIV_OUTCARD", outcard_path]) run_args.extend(["--setenv", "RIV_OUTHASH", outhash_path]) + run_args.extend(["--setenv", "RIV_SAVE_SCREENSHOT", screenshot_path]) if in_card is not None and len(in_card) > 0: run_args.extend(["--setenv", "RIV_INCARD", incard_path]) run_args.extend(["--setenv", "RIV_NO_YIELD", "y"]) @@ -118,13 +120,16 @@ def replay_log(cartridge_id,log,riv_args,in_card): if result.returncode != 0: raise Exception(f"Error processing replay: {str(result.stderr)}") - outcard_file = open(outcard_path, 'rb') - outcard_raw = outcard_file.read() + outcard_raw = open(outcard_path, 'rb').read() + os.remove(outcard_path) + + outhash = bytes.fromhex(open(outhash_path, 'r').read()) + os.remove(outhash_path) - outhash_file = open(outhash_path, 'r') - outhash = bytes.fromhex(outhash_file.read()) + screenshot = open(screenshot_path,'rb').read() + os.remove(screenshot_path) - return outcard_raw, outhash + return outcard_raw, outhash, screenshot # use rivemu replay_temp = tempfile.NamedTemporaryFile() @@ -132,9 +137,8 @@ def replay_log(cartridge_id,log,riv_args,in_card): incard_temp = tempfile.NamedTemporaryFile() incard_file = incard_temp.file outcard_temp = tempfile.NamedTemporaryFile() - outcard_file = outcard_temp.file outhash_temp = tempfile.NamedTemporaryFile(mode='w+') - outhash_file = outhash_temp.file + screenshot_temp = tempfile.NamedTemporaryFile() replay_file.write(log) replay_file.flush() @@ -154,6 +158,7 @@ def replay_log(cartridge_id,log,riv_args,in_card): run_args.append(f"-save-outcard={outcard_temp.name}") run_args.append(f"-save-outhash={outhash_temp.name}") run_args.append(f"-speed=1000000") + run_args.append(f"-save-screenshot={screenshot_temp.name}") if in_card is not None and len(in_card): run_args.append(f"-load-incard={incard_temp.name}") if riv_args is not None and len(riv_args) > 0: @@ -163,15 +168,17 @@ def replay_log(cartridge_id,log,riv_args,in_card): if result.returncode != 0: raise Exception(f"Error processing replay: {str(result.stderr)}") - outcard_raw = outcard_file.read() - outhash = bytes.fromhex(outhash_file.read()) + outcard_raw = outcard_temp.file.read() + outhash = bytes.fromhex(outhash_temp.file.read()) + screenshot = screenshot_temp.file.read() replay_temp.close() outcard_temp.close() incard_temp.close() outhash_temp.close() + screenshot_temp.close() - return outcard_raw, outhash + return outcard_raw, outhash, screenshot def riv_get_cartridge_outcard(cartridge_id,frame,riv_args,in_card): if AppSettings.rivemu_path is None: # use riv os diff --git a/app/scoreboard.py b/app/scoreboard.py index d9bffdf..f1acef1 100644 --- a/app/scoreboard.py +++ b/app/scoreboard.py @@ -7,15 +7,19 @@ from py_expression_eval import Parser import re -from cartesi.abi import String, Bytes, Bytes32, Int, UInt +from cartesi.abi import String, Bytes, Bytes32, Int, UInt, Address from cartesapp.storage import Entity, helpers, seed -from cartesapp.manager import mutation, query, get_metadata, output, add_output, event, emit_event, contract_call +from cartesapp.context import get_metadata +from cartesapp.input import mutation, query +from cartesapp.output import output, add_output, event, emit_event, contract_call from cartesapp.utils import hex2bytes, str2bytes, bytes2str -from .setup import AppSettings, ScoreType, GameplayHash +from .settings import AppSettings from .riv import replay_log, riv_get_cartridge_outcard from .cartridge import Cartridge +from .common import ScoreType, GameplayHash, screenshot_add_score, get_cid +from .cartridge import Cartridge LOGGER = logging.getLogger(__name__) @@ -28,7 +32,7 @@ class Scoreboard(Entity): id = helpers.PrimaryKey(str, 64) name = helpers.Required(str, index=True, unique=True) cartridge_id = helpers.Required(str, 64, index=True) - created_by = helpers.Required(str, 66) + created_by = helpers.Required(str, 42) created_at = helpers.Required(int) args = helpers.Optional(str) in_card = helpers.Optional(bytes) @@ -38,7 +42,8 @@ class Scoreboard(Entity): class Score(Entity): id = helpers.PrimaryKey(int, auto=True) - user_address = helpers.Required(str, 66, index=True) + user_address = helpers.Required(str, 42, index=True) + user_alias = helpers.Required(str, 42, index=True) timestamp = helpers.Required(int) score = helpers.Required(int) scoreboard = helpers.Required(Scoreboard, index=True) @@ -82,6 +87,7 @@ class ScoreboardReplayPayload(BaseModel): scoreboard_id: Bytes32 outcard_hash: Bytes32 log: Bytes + user_alias: String class ScoreboardsPayload(BaseModel): cartridge_id: str @@ -110,12 +116,15 @@ class ScoreboardRemoved(BaseModel): @event() class ScoreboardReplayScore(BaseModel): cartridge_id: Bytes32 - user_address: String + user_address: Address timestamp: UInt score: Int # default score score_type: Int = ScoreType.scoreboard.value extra_score: Int scoreboard_id: String + user_alias: String = '' + screenshot_cid: String = '' + gameplay_hash: Bytes32 class ScoreboardInfo(BaseModel): id: String @@ -258,16 +267,26 @@ def scoreboard_replay(replay: ScoreboardReplayPayload) -> bool: add_output(msg,tags=['error']) return False - if not GameplayHash.check(scoreboard.cartridge_id,sha256(replay.log).hexdigest()): + gameplay_hash = sha256(replay.log) + + if not GameplayHash.check(scoreboard.cartridge_id,gameplay_hash.hexdigest()): msg = f"Gameplay already submitted" LOGGER.error(msg) add_output(msg,tags=['error']) return False + cartridge = helpers.select(c for c in Cartridge if c.id == scoreboard.cartridge_id).first() + + if cartridge is None: + msg = f"Game not found" + LOGGER.error(msg) + add_output(msg,tags=['error']) + return False + # process replay LOGGER.info(f"Processing scoreboard replay...") try: - outcard_raw, outhash = replay_log(scoreboard.cartridge_id,replay.log,scoreboard.args,scoreboard.in_card) + outcard_raw, outhash, screenshot = replay_log(scoreboard.cartridge_id,replay.log,scoreboard.args,scoreboard.in_card) except Exception as e: msg = f"Couldn't replay log: {e}" LOGGER.error(msg) @@ -313,26 +332,35 @@ def scoreboard_replay(replay: ScoreboardReplayPayload) -> bool: add_output(msg,tags=['error']) return False + user_alias = replay.user_alias if len(replay.user_alias) else f"{metadata.msg_sender[:6]}...{metadata.msg_sender[:-4]}" + s = Score( user_address = metadata.msg_sender, + user_alias = user_alias, timestamp = metadata.timestamp, score = score, scoreboard = scoreboard ) + final_screenshot = screenshot_add_score(screenshot,cartridge.name,score,user_alias) + cid = get_cid(final_screenshot) + replay_score = ScoreboardReplayScore( cartridge_id = hex2bytes(scoreboard.cartridge_id), user_address = metadata.msg_sender, + user_alias = user_alias, timestamp = metadata.timestamp, score = default_score, extra_score = score, scoreboard_id = replay.scoreboard_id.hex(), + gameplay_hash = gameplay_hash.digest() ) add_output(replay.log,tags=['replay',scoreboard.cartridge_id,replay.scoreboard_id.hex()]) + add_output(final_screenshot,tags=['screenshot',replay.cartridge_id.hex()]) emit_event(replay_score,tags=['score',scoreboard.cartridge_id,replay.scoreboard_id.hex()]) - GameplayHash.add(scoreboard.cartridge_id,sha256(replay.log).hexdigest()) + GameplayHash.add(scoreboard.cartridge_id,gameplay_hash.hexdigest()) return True diff --git a/app/settings.py b/app/settings.py new file mode 100644 index 0000000..01c735c --- /dev/null +++ b/app/settings.py @@ -0,0 +1,18 @@ +# App Framework settings + +# Files with definitions to import +FILES = ['setup','cartridge','replay','scoreboard'] # * Required + +# Index outputs in inspect indexer queries +INDEX_OUTPUTS = True # Defaul: False + +ENABLE_DAPP_RELAY = False # Defaul: False + +ENABLE_WALLET = False # Defaul: False (required to set ENABLE_DAPP_RELAY) + +STORAGE_PATH = None + +class AppSettings: + rivemu_path = None + cartridges_path = "cartridges" + scoreboard_ttl = 7776000 # 90 days diff --git a/app/setup.py b/app/setup.py index a661df1..7639af0 100644 --- a/app/setup.py +++ b/app/setup.py @@ -1,40 +1,8 @@ import os -from enum import Enum -from cartesapp.manager import setup, setting - -# TODO: use settings file instead of init -@setting() -class FrameworkSettings: - index_outputs = True - -class AppSettings: - rivemu_path = None - cartridges_path = "cartridges" - scoreboard_ttl = 7776000 # 90 days +from cartesapp.manager import setup +from .settings import AppSettings @setup() def setup_rivemu(): AppSettings.rivemu_path = os.getenv('RIVEMU_PATH') - -class ScoreType(Enum): - default = 0 - scoreboard = 1 - tournament = 2 - - -class GameplayHash: - cartridge_replays = {} - def __new__(cls): - return cls - - @classmethod - def add(cls, cartridge_id, replay_hash): - if cls.cartridge_replays.get(cartridge_id) is None: cls.cartridge_replays[cartridge_id] = {} - cls.cartridge_replays[cartridge_id][replay_hash] = True - - @classmethod - def check(cls, cartridge_id, replay_hash): - return cls.cartridge_replays.get(cartridge_id) is None \ - or cls.cartridge_replays[cartridge_id].get(replay_hash) is None \ - or cls.cartridge_replays[cartridge_id][replay_hash] == False diff --git a/cartesapp/__init__.py b/cartesapp/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/cartesapp/manager.py b/cartesapp/manager.py deleted file mode 100644 index a5e1c9a..0000000 --- a/cartesapp/manager.py +++ /dev/null @@ -1,701 +0,0 @@ -import os -import logging -import importlib -from inspect import getmembers, isfunction, signature -import sys, getopt -from typing import Optional, List, get_type_hints -from pydantic import BaseModel, create_model -from Crypto.Hash import keccak -from enum import Enum -import json -import traceback -import typer - -from cartesi import DApp, Rollup, RollupData, RollupMetadata, ABIRouter, URLRouter, URLParameters, abi -from cartesi.models import ABIFunctionSelectorHeader -from cartesi.abi import encode_model - -from .storage import Storage, helpers, add_output_index, OutputType, get_output_indexes -from .utils import str2bytes, hex2bytes, bytes2hex -from .output import MAX_OUTPUT_SIZE, MAX_AGGREGATED_OUTPUT_SIZE, MAX_SPLITTABLE_OUTPUT_SIZE - -LOGGER = logging.getLogger(__name__) - - -class EmptyClass(BaseModel): - pass - - -### -# Manager - -class Manager(object): - dapp = None - abi_router = None - url_router = None - storage = None - modules_to_add = [] - queries_info = {} - mutations_info = {} - - def __new__(cls): - return cls - - @classmethod - def add_module(cls,mod): - cls.modules_to_add.append(mod) - - @classmethod - def _import_apps(cls): - if len(cls.modules_to_add) == 0: - raise Exception("No modules detected") - - for module_name in cls.modules_to_add: - importlib.import_module(module_name) - - @classmethod - def _register_queries(cls, add_to_router=True): - query_selectors = [] - for func in Query.queries: - func_name = func.__name__ - module_name = func.__module__.split('.')[0] - configs = Query.configs[f"{module_name}.{func_name}"] - - sig = signature(func) - - if len(sig.parameters) > 1: - raise Exception("Queries shouldn't have more than one parameter") - - it = iter(sig.parameters.items()) - param = next(it, None) - if param is not None: - model = param[1].annotation - else: - model = EmptyClass - - # using url router - path = f"{module_name}/{func_name}" - if path in query_selectors: - raise Exception("Duplicate query selector") - query_selectors.append(path) - - original_model = model - func_configs = {} - if configs.get("splittable_output") is not None and configs["splittable_output"]: - model_kwargs = splittable_query_params.copy() - model_kwargs["__base__"] = model - model = create_model(model.__name__+'Splittable',**model_kwargs) - func_configs["extended_model"] = model - - abi_types = [] # abi.get_abi_types_from_model(model) - cls.queries_info[f"{module_name}.{func_name}"] = {"selector":path,"module":module_name,"method":func_name,"abi_types":abi_types,"model":model,"configs":configs} - if add_to_router: - LOGGER.info(f"Adding query {module_name}.{func_name} selector={path}, model={model.__name__}") - cls.url_router.inspect(path=path)(_make_query(func,original_model,param is not None,module_name,**func_configs)) - - @classmethod - def _register_mutations(cls, add_to_router=True): - mutation_selectors = [] - for func in Mutation.mutations: - func_name = func.__name__ - module_name = func.__module__.split('.')[0] - configs = Mutation.configs[f"{module_name}.{func_name}"] - - sig = signature(func) - - if len(sig.parameters) > 1: - raise Exception("Mutations shouldn't have more than one parameter") - - it = iter(sig.parameters.items()) - param = next(it, None) - if param is not None: - model = param[1].annotation - else: - model = EmptyClass - - # using abi router - abi_types = abi.get_abi_types_from_model(model) - header = ABIFunctionSelectorHeader( - function=f"{module_name}.{func_name}", - argument_types=abi_types - ) - header_selector = header.to_bytes().hex() - if header_selector in mutation_selectors: - raise Exception("Duplicate mutation selector") - mutation_selectors.append(header_selector) - cls.mutations_info[f"{module_name}.{func_name}"] = {"selector":header,"module":module_name,"method":func_name,"abi_types":abi_types,"model":model,"configs":configs} - if add_to_router: - LOGGER.info(f"Adding mutation {module_name}.{func_name} selector={header_selector}, model={model.schema()}") - cls.abi_router.advance(header=header)(_make_mut(func,model,param is not None,module_name,**Mutation.configs[f"{module_name}.{func_name}"])) - - @classmethod - def _setup_settings(cls): - add_indexer_query = False - settings = Setting.settings - for module_name in settings: - settings_cls = settings[module_name] - if getattr(settings_cls,'index_outputs'): - add_indexer_query = True - break - if add_indexer_query: - output()(IndexerOutput) - query()(indexer_query) - - @classmethod - def _run_setup_functions(cls): - for app_setup in Setup.setup_functions: - app_setup() - - @classmethod - def run(cls): - cls.dapp = DApp() - cls.abi_router = ABIRouter() - cls.url_router = URLRouter() - cls.storage = Storage - cls.dapp.add_router(cls.abi_router) - cls.dapp.add_router(cls.url_router) - cls._import_apps() - cls._setup_settings() - cls._register_queries() - cls._register_mutations() - cls._run_setup_functions() - cls.storage.initialize_storage() - cls.dapp.run() - - @classmethod - def generate_frontend_lib(cls, lib_path=None): - cls._import_apps() - cls._setup_settings() - cls._register_queries(False) - cls._register_mutations(False) - # generate lib - from .template_frontend_generator import render_templates - params = [ - {"indexer_query":indexer_query,"indexer_output":IndexerOutput}, - Setting.settings, - cls.mutations_info, - cls.queries_info, - Output.notices_info, - Output.reports_info, - cls.modules_to_add] - if lib_path is not None: params.append(lib_path) - render_templates(*params) - - @classmethod - def create_frontend(cls): - from .template_frontend_generator import create_frontend_structure - create_frontend_structure() - -### -# Singletons - -# Query -class Query: - queries = [] - configs = {} - def __new__(cls): - return cls - - @classmethod - def add(cls, func, **kwargs): - cls.queries.append(func) - func_name = func.__name__ - module_name = func.__module__.split('.')[0] - cls.configs[f"{module_name}.{func_name}"] = kwargs - -def query(**kwargs): - def decorator(func): - Query.add(func,**kwargs) - return func - return decorator - -splittable_query_params = {"part":(int,None)} - -# Mutation -class Mutation: - mutations = [] - configs = {} - def __new__(cls): - return cls - - @classmethod - def add(cls, func, **kwargs): - cls.mutations.append(func) - func_name = func.__name__ - module_name = func.__module__.split('.')[0] - cls.configs[f"{module_name}.{func_name}"] = kwargs - -# TODO: decorator params to allow chunked and compressed mutations -def mutation(**kwargs): - if kwargs.get('chunk') is not None: - LOGGER.warning("Chunking inputs is not implemented yet") - if kwargs.get('compress') is not None: - LOGGER.warning("Compressing inputs is not implemented yet") - if kwargs.get('sender_address') is not None: - LOGGER.warning("Sender address filtering is not implemented yet") - def decorator(func): - Mutation.add(func,**kwargs) - return func - return decorator - - -# Settings -class Setting: - settings = {} - def __new__(cls): - return cls - - @classmethod - def add(cls, klass): - cls.settings[klass.__module__.split('.')[0]] = klass - -def setting(**kwargs): - def decorator(klass): - Setting.add(klass) - return klass - return decorator - -class Context(object): - rollup: Rollup | None = None - metadata: RollupMetadata | None = None - module: str | None = None - n_reports: int = 0 - n_notices: int = 0 - n_vouchers: int = 0 - configs = None - - - def __new__(cls): - return cls - - @classmethod - def set_context(cls, rollup: Rollup, metadata: RollupMetadata, module: str, **kwargs): - cls.rollup = rollup - cls.metadata = metadata - cls.module = module - cls.n_reports = 0 - cls.n_notices = 0 - cls.n_vouchers = 0 - cls.configs = kwargs - - @classmethod - def clear_context(cls): - cls.rollup = None - cls.metadata = None - cls.module = None - cls.n_reports: 0 - cls.n_notices = 0 - cls.n_vouchers = 0 - cls.configs = None - -class Setup: - setup_functions = [] - - def __new__(cls): - return cls - - @classmethod - def add_setup(cls, func): - cls.setup_functions.append(_make_setup_function(func)) - -def _make_setup_function(f): - @helpers.db_session - def setup_func(): - f() - return setup_func - -def setup(**kwargs): - def decorator(func): - Setup.add_setup(func) - return func - return decorator - - -### -# Outputs - -class OutputFormat(Enum): - abi = 0 - packed_abi = 1 - json = 2 - -class Output: - notices_info = {} - reports_info = {} - vouchers_info = {} - def __new__(cls): - return cls - - @classmethod - def add_report(cls, klass): - module_name = klass.__module__.split('.')[0] - class_name = klass.__name__ - abi_types = [] # abi.get_abi_types_from_model(klass) - cls.reports_info[f"{module_name}.{class_name}"] = {"module":module_name,"class":class_name,"abi_types":abi_types,"model":klass} - - @classmethod - def add_notice(cls, klass): - module_name = klass.__module__.split('.')[0] - class_name = klass.__name__ - abi_types = abi.get_abi_types_from_model(klass) - cls.notices_info[f"{module_name}.{class_name}"] = {"module":module_name,"class":class_name,"abi_types":abi_types,"model":klass} - - @classmethod - def add_voucher(cls, klass): - module_name = klass.__module__.split('.')[0] - class_name = klass.__name__ - abi_types = abi.get_abi_types_from_model(klass) - cls.vouchers_info[f"{module_name}.{class_name}"] = {"module":module_name,"class":class_name,"abi_types":abi_types,"model":klass} - -def notice(**kwargs): - def decorator(klass): - Output.add_notice(klass) - return klass - return decorator - -event = notice - -def report(**kwargs): - def decorator(klass): - Output.add_report(klass) - return klass - return decorator - -output = report - -def voucher(**kwargs): - def decorator(klass): - Output.add_voucher(klass) - return klass - return decorator - -contract_call = voucher - -def get_metadata() -> RollupMetadata: - return Context.metadata - -def normalize_output(data,encode_format) -> [bytes, str]: - if isinstance(data, bytes): return data,'bytes' - if isinstance(data, int): data.to_bytes(32,byteorder='big'),'int' - if isinstance(data, str): - if data.startswith('0x'): return hex2bytes(data[2:]),'hex' - return str2bytes(data),'str' - class_name = f"{data.__module__.split('.')[0]}.{data.__class__.__name__}" - if isinstance(data, dict) or isinstance(data, list) or isinstance(data, tuple): - return str2bytes(json.dumps(data)),class_name - if issubclass(data.__class__,BaseModel): - if encode_format == OutputFormat.abi: return encode_model(data),class_name - if encode_format == OutputFormat.packed_abi: return encode_model(data,True),class_name - if encode_format == OutputFormat.json: return str2bytes(data.json(exclude_unset=True,exclude_none=True)),class_name - raise Exception("Invalid output format") - -def normalize_voucher(*kargs): - if len(kargs) == 1: - if isinstance(kargs[0], bytes): return kargs[0],'bytes' - if isinstance(kargs[0], str): return hex2bytes(kargs[0]),'hex' - raise Exception("Invalid voucher payload") - if len(kargs) == 2: - if not isinstance(kargs[0], str): raise Exception("Invalid voucher selector") - if not issubclass(kargs[1].__class__,BaseModel): raise Exception("Invalid voucher model") - - sig_hash = keccak.new(digest_bits=256) - sig_hash.update(kargs[0].encode('utf-8')) - - selector = sig_hash.digest()[:4] - data = abi.encode_model(kargs[1]) - - return selector+data,kargs[1].__class__.__name__ - # TODO: 3 is name, classes, and data, - # too many problems: how is model stored in index? how formats are defined: str or abi annotation? - raise Exception("Invalid number of arguments") - -def send_report(payload_data, **kwargs): - ctx = Context - # only one output to allow always chunking - if ctx.n_reports > 0: raise Exception("Can't add multiple reports") - - stg = Setting.settings.get(ctx.module) - - report_format = OutputFormat[getattr(stg,'report_format')] if hasattr(stg,'report_format') else OutputFormat.json - payload,class_name = normalize_output(payload_data,report_format) - - extended_params = ctx.configs.get("extended_params") - if extended_params is not None: - if ctx.metadata is None: # inspect - part = extended_params.part - payload_len = len(payload) - if payload_len > MAX_SPLITTABLE_OUTPUT_SIZE and part is not None: - if part >= 0: - startb = MAX_SPLITTABLE_OUTPUT_SIZE*(part) - endb = MAX_SPLITTABLE_OUTPUT_SIZE*(part+1) - payload = payload[startb:endb] - if endb < payload_len: payload += b'0' - - if len(payload) > MAX_AGGREGATED_OUTPUT_SIZE: - LOGGER.warn("Payload Data exceed maximum length. Truncating") - payload = payload[:MAX_AGGREGATED_OUTPUT_SIZE] - - # Always chunk if len > MAX_OUTPUT_SIZE - # if len(payload) > MAX_OUTPUT_SIZE: raise Exception("Maximum report length violation") - - tags = kwargs.get('tags') - add_idx = ctx.metadata is not None and stg is not None \ - and hasattr(stg,'index_outputs') and getattr(stg,'index_outputs') - - sent_bytes = 0 - while sent_bytes < len(payload): - inds = f" ({ctx.metadata.input_index}, {ctx.n_reports})" if ctx.metadata is not None else "" - top_bytes = sent_bytes + MAX_OUTPUT_SIZE - if top_bytes > len(payload): - top_bytes = len(payload) - - if add_idx: - splited_class_name = class_name.split('.')[-1] - LOGGER.debug(f"Adding index report{inds} {tags=}") - add_output_index(ctx.metadata,OutputType.report,ctx.n_reports,ctx.module,splited_class_name,tags) - - LOGGER.debug(f"Sending report{inds} {top_bytes - sent_bytes} bytes") - ctx.rollup.report(bytes2hex(payload[sent_bytes:top_bytes])) - ctx.n_reports += 1 - sent_bytes = top_bytes - -add_output = send_report - -def send_notice(payload_data, **kwargs): - ctx = Context - stg = Setting.settings.get(ctx.module) - - notice_format = OutputFormat[getattr(stg,'notice_format')] if hasattr(stg,'notice_format') else OutputFormat.abi - payload,class_name = normalize_output(payload_data,notice_format) - - if len(payload) > MAX_OUTPUT_SIZE: raise Exception("Maximum output length violation") - - tags = kwargs.get('tags') - - inds = f" ({ctx.metadata.input_index}, {ctx.n_notices})" if ctx.metadata is not None else "" - if ctx.metadata is not None and stg is not None and hasattr(stg,'index_outputs') and getattr(stg,'index_outputs'): - LOGGER.debug(f"Adding index notice{inds} {tags=}") - splited_class_name = class_name.split('.')[-1] - add_output_index(ctx.metadata,OutputType.notice,ctx.n_notices,ctx.module,splited_class_name,tags) - - LOGGER.debug(f"Sending notice{inds} {len(payload)} bytes") - ctx.rollup.notice(bytes2hex(payload)) - ctx.n_notices += 1 - -emit_event = send_notice - -def send_voucher(destination: str, *kargs, **kwargs): - payload,class_name = normalize_voucher() - - if len(payload) > MAX_OUTPUT_SIZE: raise Exception("Maximum output length violation") - - ctx = Context - stg = Setting.settings.get(ctx.module) - tags = kwargs.get('tags') - inds = f" ({ctx.metadata.input_index}, {ctx.n_vouchers})" if ctx.metadata is not None else "" - if ctx.metadata is not None and stg is not None and hasattr(stg,'index_outputs') and getattr(stg,'index_outputs'): - LOGGER.debug(f"Adding index voucher{inds} {tags=}") - splited_class_name = class_name.split('.')[-1] - add_output_index(ctx.metadata,OutputType.voucher,ctx.n_vouchers,ctx.module,splited_class_name,tags) - - LOGGER.debug(f"Sending voucher{inds}") - ctx.rollup.voucher({destination:destination,payload:bytes2hex(payload)}) - ctx.n_vouchers += 1 - -submit_contract_call = send_voucher - - -### -# Helpers - -def _make_query(func,model,has_param,module,**func_configs): - @helpers.db_session - def query(rollup: Rollup, params: URLParameters) -> bool: - try: - ctx = Context - # TODO: accept abi encode or json (for larger post requests, configured in settings) - # Decoding url parameters - param_list = [] - if has_param: - hints = get_type_hints(model) - fields = [] - values = [] - model_fields = model.__fields__.keys() - for k in model_fields: - if k in params.query_params: - field_str = str(hints[k]) - if field_str.startswith('typing.List') or field_str.startswith('typing.Optional[typing.List'): - fields.append(k) - values.append(params.query_params[k]) - else: - fields.append(k) - values.append(params.query_params[k][0]) - param_list.append(model.parse_obj(dict(zip(fields, values)))) - - extended_model = func_configs.get("extended_model") - if extended_model is not None: - extended_hints = get_type_hints(extended_model) - for k in list(set(extended_model.__fields__.keys()).difference(model_fields)): - if k in params.query_params: - field_str = str(extended_hints[k]) - if field_str.startswith('typing.List') or field_str.startswith('typing.Optional[typing.List'): - fields.append(k) - values.append(params.query_params[k]) - else: - fields.append(k) - values.append(params.query_params[k][0]) - func_configs["extended_params"] = extended_model.parse_obj(dict(zip(fields, values))) - - ctx.set_context(rollup,None,module,**func_configs) - res = func(*param_list) - except Exception as e: - msg = f"Error: {e}" - LOGGER.error(msg) - if logging.root.level <= logging.DEBUG: - traceback.print_exc() - add_output(msg) - return False - finally: - ctx.clear_context() - return res - return query - -def _make_mut(func,model,has_param,module, **kwargs): - @helpers.db_session - def mut(rollup: Rollup, data: RollupData) -> bool: - try: - ctx = Context - ctx.set_context(rollup,data.metadata,module,**kwargs) - payload = data.bytes_payload()[4:] - param_list = [] - if has_param: - param_list.append(abi.decode_to_model(data=payload, model=model)) #,packed=True) - res = func(*param_list) - except Exception as e: - msg = f"Error: {e}" - LOGGER.error(msg) - if logging.root.level <= logging.DEBUG: - traceback.print_exc() - add_output(msg,tags=['error']) - return False - finally: - ctx.clear_context() - return res - return mut - -# TODO add to indexer module and import it on manager - -class IndexerPayload(BaseModel): - tags: Optional[List[str]] - output_type: Optional[str] - msg_sender: Optional[str] - timestamp_gte: Optional[int] - timestamp_lte: Optional[int] - module: Optional[str] - input_index: Optional[int] - -class OutputIndex(BaseModel): - output_type: str - module: str - class_name: str - input_index: int - output_index: int - -class IndexerOutput(BaseModel): - data: List[OutputIndex] - -def indexer_query(payload: IndexerPayload) -> bool: - out = get_output_indexes(**payload.dict()) - - output_inds = [OutputIndex(output_type=r[0],module=r[1],class_name=r[2],input_index=r[3],output_index=r[4]) for r in out] - - add_output(IndexerOutput(data=output_inds)) - - return True - - -### -# CLI - -app = typer.Typer(help="Cartesapp Manager: manage your Cartesi Rollups App") - - -@app.command() -def run(modules: List[str]): - """ - Run backend with MODULES - """ - try: - m = Manager() - for mod in modules: - m.add_module(mod) - m.run() - except Exception as e: - print(e) - traceback.print_exc() - exit(1) - -@app.command() -def generate_fronted_libs(modules: List[str]): - """ - Generate frontend libs for MODULES - """ - try: - m = Manager() - for mod in modules: - m.add_module(mod) - m.generate_frontend_lib() - except Exception as e: - print(e) - traceback.print_exc() - exit(1) - -@app.command() -def create_frontend(force: Optional[bool]): - """ - Create basic frontend - """ - # check if it exists, bypass with force - # create frontend web - # doctor basic reqs (node) - # install packages ["ajv": "^8.12.0","ethers": "^5.7.2","ts-transformer-keys": "^0.4.4"] - print("Not yet Implemented") - exit(1) - -@app.command() -def create(name: str): - """ - Create new Cartesi Rollups App with NAME - """ - print("Not yet Implemented") - exit(1) - -@app.command() -def create_module(name: str, force: Optional[bool]): - """ - Create new MODULE for current Cartesi Rollups App - """ - print("Not yet Implemented") - exit(1) - -@app.command() -def deploy(conf: str): - """ - Deploy App with CONF file - """ - # doctor basic reqs (sunodo) - print("Not yet Implemented") - exit(1) - -@app.command() -def node(dev: Optional[bool] = True): - """ - Deploy App to NETWORK - """ - # doctor basic reqs (sunodo,nonodo) - print("Not yet Implemented") - exit(1) - -if __name__ == '__main__': - app() - \ No newline at end of file diff --git a/cartesapp/output.py b/cartesapp/output.py deleted file mode 100644 index a74ff77..0000000 --- a/cartesapp/output.py +++ /dev/null @@ -1,8 +0,0 @@ - - -MAX_OUTPUT_SIZE = 1048567 # (2097152-17)/2 -MAX_AGGREGATED_OUTPUT_SIZE = 4194248 # 4194248 = 4194304 (4MB) - 56 B (extra 0x and json formating) -MAX_SPLITTABLE_OUTPUT_SIZE = 4194247 # Extra byte meand there's more data - -# TODO add output classes - diff --git a/cartesapp/storage.py b/cartesapp/storage.py deleted file mode 100644 index 7e2011b..0000000 --- a/cartesapp/storage.py +++ /dev/null @@ -1,232 +0,0 @@ -import pony.orm -import logging -from enum import Enum -from typing import Optional, List - -from cartesi.abi import String, Bytes, Int, UInt - - -helpers = pony.orm - - -### -# Models - -class OutputType(Enum): - report = 0 - notice = 1 - voucher = 2 - -### -# Storage - -class Storage: - db = pony.orm.Database() - seeds = [] - - def __new__(cls): - return cls - - @classmethod - def initialize_storage(cls): - if logging.root.level <= logging.DEBUG: - pony.orm.set_sql_debug(True) - cls.db.bind(provider="sqlite", filename=":memory:") - # cls.db.provider.converter_classes.append((Enum, EnumConverter)) - cls.db.generate_mapping(create_tables=True) - for s in cls.seeds: s() - - @classmethod - def add_seed(cls, func): - cls.seeds.append(_make_seed_function(func)) - -def _make_seed_function(f): - @helpers.db_session - def seed_func(): - f() - return seed_func - -# TODO: allow ordering -def seed(**kwargs): - def decorator(func): - Storage.add_seed(func) - return func - return decorator - - -Entity = Storage.db.Entity - - -### -# Indexer model and methods - -class Output(Entity): - id = helpers.PrimaryKey(int, auto=True) - output_type = helpers.Required(str) # helpers.Required(OutputType) - msg_sender = helpers.Required(str, 66, lazy=True, index=True) - block_number = helpers.Required(int, lazy=True) - timestamp = helpers.Required(int, lazy=True, index=True) - epoch_index = helpers.Required(int, lazy=True) - input_index = helpers.Required(int) - output_index = helpers.Required(int) - output_module = helpers.Required(str) - output_class = helpers.Required(str) - tags = helpers.Set("OutputTag") - -class OutputTag(Entity): - id = helpers.PrimaryKey(int, auto=True) - name = helpers.Required(str, index=True) - output = helpers.Required(Output, index=True) - - -def add_output_index(metadata,output_type,output_index,output_module,output_class,tags=None): - o = Output( - output_type = output_type.name.lower(), - output_class = output_class, - output_module = output_module, - msg_sender = metadata.msg_sender.lower(), - block_number = metadata.block_number, - timestamp = metadata.timestamp, - epoch_index = metadata.epoch_index, - input_index = metadata.input_index, - output_index = output_index - ) - if tags is not None: - for tag in tags: - t = OutputTag( - name = tag, - output = o - ) - -def get_output_indexes(**kwargs): - tags = kwargs.get('tags') - - output_query = Output.select() - - tag_query = OutputTag.select() - - if tags is not None and len(tags) > 0: - tag_query = tag_query.filter(lambda t: t.name in tags) - - if kwargs.get('module') is not None: - output_query = output_query.filter(lambda o: o.output_module == kwargs.get('module').lower()) - if kwargs.get('output_type') is not None: - output_query = output_query.filter(lambda o: o.output_type == kwargs.get('output_type').lower()) - if kwargs.get('msg_sender') is not None: - output_query = output_query.filter(lambda o: o.msg_sender == kwargs.get('msg_sender').lower()) - if kwargs.get('timestamp_gte') is not None: - output_query = output_query.filter(lambda o: o.timestamp >= kwargs.get('timestamp_gte')) - if kwargs.get('timestamp_lte') is not None: - output_query = output_query.filter(lambda o: o.timestamp <= kwargs.get('timestamp_lte')) - if kwargs.get('input_index') is not None: - output_query = output_query.filter(lambda o: o.input_index == kwargs.get('input_index')) - - if tags is not None and len(tags) > 0: - query = helpers.distinct( - [o.output_type,o.output_module,o.output_class,o.input_index,o.output_index] - for o in output_query for t in tag_query if t.output == o and helpers.count(t) == len(tags) - ) - else: - query = helpers.distinct( - [o.output_type,o.output_module,o.output_class,o.input_index,o.output_index] - for o in output_query for t in tag_query if t.output == o - ) - - - return query.fetch() - - - - - - - - -# import pony.orm -# from enum import Enum -# from typing import Optional, List - -# from cartesi.abi import String, Bytes, Int, UInt - -# # class EnumConverter(pony.orm.dbapiprovider.Converter): -# # def sql_type(self): -# # return "VARCHAR(30)" -# # def validate(converter, val, obj=None): -# # if isinstance(val, Enum): pass -# # elif isinstance(val, str): val = converter.py_type[val] -# # elif isinstance(val, int): val = converter.py_type(val) -# # else: throw(TypeError, "Attribute %r: expected type is 'Enum'. Got: %r" % (converter.attr, val)) -# # return val -# # def py2sql(converter, val): -# # print(f"py2sql{val=}") -# # return val.name -# # def sql2py(converter, val): -# # print(f"sql2py{val=}") -# # return converter.py_type[val].name -# # # sql2py = validate -# # dbval2val = sql2py -# # val2dbval = py2sql -# # def dbvals_equal(converter, x, y): -# # print(f"dbvals_equal{x=},{y=}") -# # if isinstance(x, Enum): x = x.name -# # elif isinstance(x, int): x = converter.py_type(x).name -# # if isinstance(y, Enum): y = y.name -# # elif isinstance(y, int): y = converter.py_type(y).name -# # return x == y - -# helpers = pony.orm -# pony.orm.set_sql_debug(True) -# db = pony.orm.Database() -# Entity = db.Entity - -# # helpers.Required(OutputType) -# class Output(Entity): -# id = helpers.PrimaryKey(int, auto=True) -# output_type = helpers.Required(str) # helpers.Required(OutputType) -# msg_sender = helpers.Required(str, lazy=True, index=True) -# block_number = helpers.Required(int, lazy=True) -# timestamp = helpers.Required(int, lazy=True, index=True) -# epoch_index = helpers.Required(int, lazy=True) -# input_index = helpers.Required(int) -# output_index = helpers.Required(int) -# output_class = helpers.Required(str) -# tags = helpers.Set("OutputTag") - -# class OutputTag(Entity): -# id = helpers.PrimaryKey(int, auto=True) -# name = helpers.Required(str, index=True) -# output = helpers.Required(Output) - -# db.bind(provider="sqlite", filename=":memory:") -# # db.provider.converter_classes.append((Enum, EnumConverter)) -# db.generate_mapping(create_tables=True) - - -# o = Output(output_type='report',msg_sender="0x0000",timestamp=16000,block_number=0,epoch_index=0,input_index=0,output_index=0,output_class='hex') - -# t1 = OutputTag(name='game',output=o) -# t2 = OutputTag(name='log',output=o) - -# helpers.select(o for o in Output for t in OutputTag if t.output == o and t.name in ['log'] and o.output_type == 'report')[:] - -# output_filter = lambda o: True -# prev_filter = output_filter -# output_filter = lambda o: prev_filter_filter(o) and o.timestamp <= - -# helpers.select(o for o in Output for t in OutputTag if t.output == o and t.name in ['log'] and o.output_type == 'report' and output_filter(o))[:] - -# tags = ['log'] - -# output_query = Output.select() - -# tag_query = OutputTag.select() - -# if tags is not None and len(tags) > 0: -# tag_query = tag_query.filter(lambda t: t.name in tags) - -# output_query = output_query.filter(lambda o: o.msg_sender == '0x0000') - -# q = helpers.distinct( -# [o.output_type,o.output_class,o.input_index,o.output_index] -# for o in output_query for t in tag_query if t.output == o -# ) \ No newline at end of file diff --git a/cartesapp/template_frontend_generator.py b/cartesapp/template_frontend_generator.py deleted file mode 100644 index 4777e44..0000000 --- a/cartesapp/template_frontend_generator.py +++ /dev/null @@ -1,918 +0,0 @@ -from pydantic2ts.cli.script import generate_json_schema -import os -import json -import subprocess -import tempfile -from jinja2 import Template -from packaging.version import Version - -from .output import MAX_SPLITTABLE_OUTPUT_SIZE - -FRONTEND_PATH = 'frontend' -DEFAULT_LIB_PATH = 'src' -PACKAGES_JSON_FILENAME = "package.json" -TSCONFIG_JSON_FILENAME = "tsconfig.json" - -def convert_camel_case(s): - splitted = s.split('_') - return splitted[0] + ''.join(i.title() for i in splitted[1:]) - -def render_templates(conf,settings,mutations_info,queries_info,notices_info,reports_info,modules_to_add,libs_path=DEFAULT_LIB_PATH): - - add_indexer_query = False - for module_name in settings: - if getattr(settings[module_name],'index_outputs'): - add_indexer_query = True - break - - # print(conf,settings,mutations_info,queries_info,notices_info,reports_info,modules_to_add) - - modules = ['cartesapp'] - modules.extend(modules_to_add) - modules_processed = [] - while len(modules_to_add) > 0: - if 'cartesapp' not in modules_processed: - module_name = 'cartesapp' - else: - module_name = modules_to_add.pop() - modules_processed.append(module_name) - - module_notices_info = [i for i in notices_info.values() if i['module'] == module_name] - module_reports_info = [i for i in reports_info.values() if i['module'] == module_name] - module_vouchers_info = [] # TODO: add this (also add voucher info on manager) - module_mutations_info = [i for i in mutations_info.values() if i['module'] == module_name] - module_queries_info = [i for i in queries_info.values() if i['module'] == module_name] - - mutations_payload_info = [dict(p) for p in set([(("abi_types",tuple(i["abi_types"])),("model",i["model"])) for i in module_mutations_info])] - for i in mutations_payload_info: i["abi_types"] = list(i["abi_types"]) - queries_payload_info = [dict(p) for p in set([(("abi_types",tuple(i["abi_types"])),("model",i["model"])) for i in module_queries_info])] - for i in queries_payload_info: i["abi_types"] = list(i["abi_types"]) - - models = [] - models.extend(map(lambda i:i['model'],module_notices_info)) - models.extend(map(lambda i:i['model'],module_reports_info)) - models.extend(map(lambda i:i['model'],module_vouchers_info)) - models.extend(map(lambda i:i['model'],module_mutations_info)) - models.extend(map(lambda i:i['model'],module_queries_info)) - models = list(set(models)) - - frontend_lib_path = f"{FRONTEND_PATH}/{libs_path}/{module_name}" - - if len(models) > 0: - - schema = generate_json_schema(models) - - if not os.path.exists(frontend_lib_path): - os.makedirs(frontend_lib_path) - - output_filepath = f"{frontend_lib_path}/ifaces.d.ts" - - schema_temp = tempfile.NamedTemporaryFile() - schema_file = schema_temp.file - schema_file_path = schema_temp.name - - with open(schema_file_path, "w") as f: - f.write(schema) - - args = ["npx","json2ts"] - args.extend(["-i",schema_file_path]) - args.extend(["-o",output_filepath]) - - result = subprocess.run(args, capture_output=True, text=True) - if result.returncode > 0: - raise Exception("Error generating typescript interfaces") - - schema_temp.close() - - has_indexer_query = False - module_setting = settings.get(module_name) - if module_setting is not None: - has_indexer_query = getattr(module_setting,'index_outputs') - - filepath = f"{frontend_lib_path}/lib.ts" - if module_name == 'cartesapp': - # helper_template_file = open('templates/cartesapp-helpers.j2','r') - # helper_template = helper_template_file.read() - # helper_template_file.close() - - indexer_query_info = None - indexer_output_info = None - if add_indexer_query and not indexer_output_info: - indexer_query_info = queries_info[f"{conf['indexer_query'].__module__.split('.')[0]}.{conf['indexer_query'].__name__}"] - indexer_output_info = reports_info[f"{conf['indexer_output'].__module__.split('.')[0]}.{conf['indexer_output'].__name__}"] - - has_ifaces = add_indexer_query - helper_template_output = Template(helper_template).render({ - "convert_camel_case":convert_camel_case, - "add_indexer_query": add_indexer_query, - "has_ifaces": has_ifaces, - "indexer_query_info": indexer_query_info, - "indexer_output_info": indexer_output_info, - "MAX_SPLITTABLE_OUTPUT_SIZE":MAX_SPLITTABLE_OUTPUT_SIZE - }) - - with open(filepath, "w") as f: - f.write(helper_template_output) - else: - imports_template_output = Template(lib_imports).render({ - "has_indexer_query": has_indexer_query, - "MAX_SPLITTABLE_OUTPUT_SIZE":MAX_SPLITTABLE_OUTPUT_SIZE - }) - - with open(filepath, "w") as f: - f.write(imports_template_output) - - # lib_template_file = open('templates/lib.j2','r') - # lib_template = lib_template_file.read() - # lib_template_file.close() - - lib_template_output = Template(lib_template).render({ - "mutations_info":module_mutations_info, - "queries_info":module_queries_info, - "mutations_payload_info":mutations_payload_info, - "queries_payload_info":queries_payload_info, - "notices_info":module_notices_info, - "reports_info":module_reports_info, - "vouchers_info":module_vouchers_info, - "has_indexer_query": has_indexer_query, - "list":list, - "convert_camel_case":convert_camel_case - }) - - with open(filepath, "a") as f: - f.write(lib_template_output) - -def get_newer_version(pkg_name,req_version,orig_version): - if orig_version is None: return req_version - ov = Version(orig_version.split('~')[-1].split('^')[-1]) - rv = Version(req_version.split('~')[-1].split('^')[-1]) - force_original = False - if req_version.startswith('~') or orig_version.startswith('~'): - if ov.major != rv.major or ov.minor != rv.minor: - force_original = True - if req_version.startswith('^'): - if not orig_version.startswith('^') and ov < rv: - force_original = True - if orig_version.startswith('^'): - if not req_version.startswith('^') and rv < ov: - force_original = True - if force_original: - print(f"WARN: Required package {pkg_name} version is {req_version} but original is {orig_version}: keeping original (fix this manually)") - return orig_version - newer = orig_version - if rv > ov: newer = req_version - return newer - - -def create_frontend_structure(libs_path=DEFAULT_LIB_PATH): - # packages json - pkg_path = f"{FRONTEND_PATH}/{PACKAGES_JSON_FILENAME}" - original_pkg = {} - # merge confs (warn and keep original) - if os.path.exists(pkg_path) and os.path.isfile(pkg_path): - with open(pkg_path, "r") as f: - original_json_str = f.read() - original_pkg = json.loads(original_json_str) - for section in packages_json: - if original_pkg.get(section) is None: original_pkg[section] = {} - for key in packages_json[section]: - if "dependencies" in section.lower(): - original_pkg[section][key] = get_newer_version(key,packages_json[section][key],original_pkg[section].get(key)) - else: - if original_pkg[section].get(key) is not None and original_pkg[section][key] != packages_json[section][key]: - print(f"WARN: Required package {key} section is '{packages_json[section][key]}' but original is '{original_pkg[section][key]}': keeping original (fix this manually)") - original_pkg[section][key] = original_pkg[section].get(key) or packages_json[section][key] - - # tsconfig json - tscfg_path = f"{FRONTEND_PATH}/{TSCONFIG_JSON_FILENAME}" - original_tscfg = {} - # merge confs (warn and keep original) - if os.path.exists(tscfg_path) and os.path.isfile(tscfg_path): - with open(tscfg_path, "r") as f: - original_json_str = f.read() - original_tscfg = json.loads(original_json_str) - # tsconfig_json['include'] = [libs_path] - for section in tsconfig_json: - if type(tsconfig_json[section]) == type({}): - if original_tscfg.get(section) is None: original_tscfg[section] = {} - for key in tsconfig_json[section]: - if original_tscfg[section].get(key) is not None and original_tscfg[section][key] != tsconfig_json[section][key]: - print(f"WARN: Required tsconfig {section} section is '{json.dumps(tsconfig_json[section][key])}' but original is '{json.dumps(original_tscfg[section][key])}': keeping original (fix this manually)") - original_tscfg[section][key] = original_tscfg[section].get(key) or tsconfig_json[section][key] - elif type(tsconfig_json[section]) == type([]): - if original_tscfg.get(section) is None: original_tscfg[section] = [] - for val in tsconfig_json[section]: - if val not in original_tscfg[section]: - original_tscfg[section].append(val) - - - - if not os.path.exists(FRONTEND_PATH): - os.makedirs(FRONTEND_PATH) - - with open(pkg_path, "w") as f: - json_str = json.dumps(original_pkg, indent=2) - f.write(json_str) - - with open(tscfg_path, "w") as f: - json_str = json.dumps(original_tscfg, indent=2) - f.write(json_str) - -packages_json = { - "scripts": { - # "dry-run": "ts-node src/dry-run.ts", - # "prepare": "ts-patch install" - }, - "dependencies": { - "ajv": "^8.12.0", - "ajv-formats": "^2.1.1", - "ethers": "^5.7.2" - }, - "devDependencies": { - "@types/node": "^20", - "typescript": "^5", - # "ts-patch": "^3.1.2", - # "ts-transformer-keys": "^0.4.4", - # "ts-node": "^10.9.2" - } -} - -tsconfig_json = { - # "ts-node": { - # // This can be omitted when using ts-patch - # "compiler": "ts-patch/compiler" - # }, - "compilerOptions": { - # "strict": True, - # "noEmitOnError": True, - # # "suppressImplicitAnyIndexErrors": true, - # "target": "ES5", - # "plugins": [ - # { "transform": "ts-transformer-keys/transformer" } - # ] - } -} - -helper_template = '''/* eslint-disable */ -/** - * This file was automatically generated by cartesapp.template_generator. - * DO NOT MODIFY IT BY HAND. Instead, run the generator, - */ -import { Signer, ethers, ContractReceipt } from "ethers"; -import Ajv, { ValidateFunction } from "ajv" -import addFormats from "ajv-formats" - -import { - advanceInput, inspect, - AdvanceOutput, InspectOptions, AdvanceInputOptions, - Report as CartesiReport, Notice as CartesiNotice, Voucher as CartesiVoucher, - Maybe, Proof, validateNoticeFromParams, wasVoucherExecutedFromParams, executeVoucherFromParams, - queryNotice, queryReport, queryVoucher, GraphqlOptions -} from "cartesi-client"; - -{% if has_ifaces -%} -import * as ifaces from "./ifaces"; -{% endif %} - - -/** - * Configs - */ - -const ajv = new Ajv(); -addFormats(ajv); -ajv.addFormat("biginteger", (data) => { - const dataTovalidate = data.startsWith('-') ? data.substring(1) : data; - return ethers.utils.isHexString(dataTovalidate) && dataTovalidate.length % 2 == 0; -}); -const abiCoder = new ethers.utils.AbiCoder(); -export const CONVENTIONAL_TYPES: Array = ["bytes","hex","str","int","dict","list","tuple","json"]; -const MAX_SPLITTABLE_OUTPUT_SIZE = {{ MAX_SPLITTABLE_OUTPUT_SIZE }}; - - -/** - * Models - */ - -export enum IOType { - report, - notice, - voucher, - mutationPayload, - queryPayload -} - -interface ModelInterface { - ioType: IOType; - abiTypes: Array; - params: Array; - decoder?(data: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport): T; - exporter?(data: T): string; - validator: ValidateFunction; -} - -export interface Models { - [key: string]: ModelInterface; -} - -export interface InspectReportInput { - index?: number; -} - -export interface InspectReport { - payload: string; - input?: InspectReportInput; - index?: number; -} - -export interface OutputGetters { - [key: string]: (o?: GraphqlOptions) => Promise|Promise|Promise; -} - -export const outputGetters: OutputGetters = { - report: queryReport, - notice: queryNotice, - voucher: queryVoucher -} - -export interface MutationOptions extends AdvanceInputOptions { - decode?: boolean; -} - -export interface QueryOptions extends InspectOptions { - decode?: boolean; - decodeModel?: string; -} - -export class IOData { - [key: string]: any; - _model: ModelInterface - - constructor(model: ModelInterface, data: T, validate: boolean = true) { - this._model = model; - for (const key of this._model.params) { - this[key] = (data as any)[key]; - } - if (validate) this.validate(); - } - - get = (): T => { - const data: any = {}; - for (const key of this._model.params) { - data[key] = this[key]; - } - return data; - } - - validate = (): boolean => { - const dataToValidate: any = { ...this.get() }; - for (const k of Object.keys(dataToValidate)) { - if (ethers.BigNumber.isBigNumber(dataToValidate[k])) - dataToValidate[k] = dataToValidate[k].toHexString(); - } - if (!this._model.validator(dataToValidate)) - throw new Error(`Data does not implement interface: ${ajv.errorsText(this._model.validator.errors)}`); - return true; - } - - export(): string { - let payload: string; - switch(this._model.ioType) { - case IOType.mutationPayload: { - // parametrize input to url - const inputData: any = this.get(); - const paramList = Array(); - for (const key of this._model.params) { - paramList.push(inputData[key]); - } - payload = abiCoder.encode(this._model.abiTypes,paramList); - break; - } - case IOType.queryPayload: { - // parametrize input to url - const inputData: T = this.get(); - const paramList = Array(); - for (const key in inputData) { - if (inputData[key] == undefined) continue; - if (Array.isArray(inputData[key])) { - for (const element in inputData[key]) { - paramList.push(`${key}=${inputData[key][element]}`); - } - } else { - paramList.push(`${key}=${inputData[key]}`); - } - } - payload = paramList.length > 0 ? `?${paramList.join('&')}` : ""; - break; - } - default: { - throw new Error(`Invalid payload type ${this._model.ioType}`); - // break; - } - } - return payload; - } -} - -export class BasicOutput extends IOData { - _payload: string - _inputIndex?: number - _outputIndex?: number - - constructor(model: ModelInterface, payload: string, inputIndex?: number, outputIndex?: number) { - super(model,genericDecodeTo(payload,model),false); - this._inputIndex = inputIndex; - this._outputIndex = outputIndex; - this._payload = payload; - } -} - -export class Output extends BasicOutput{ - constructor(model: ModelInterface, report: CartesiReport | InspectReport) { - super(model, report.payload, report.input?.index, report.index); - } -} - -export class OutputWithProof extends BasicOutput{ - _proof: Maybe | undefined - _inputIndex: number - _outputIndex: number - - constructor(model: ModelInterface, payload: string, inputIndex: number, outputIndex: number, proof: Maybe | undefined) { - super(model, payload, inputIndex, outputIndex); - this._inputIndex = inputIndex; - this._outputIndex = outputIndex; - this._proof = proof; - } -} - -export class Event extends OutputWithProof{ - constructor(model: ModelInterface, notice: CartesiNotice) { - super(model, notice.payload, notice.input.index, notice.index, notice.proof); - } - validateOnchain = async (signer: Signer, dappAddress: string): Promise => { - if (this._proof == undefined) - throw new Error("Notice has no proof"); - return await validateNoticeFromParams(signer,dappAddress,this._payload,this._proof); - } -} - -export class ContractCall extends OutputWithProof{ - _destination: string - constructor(model: ModelInterface, voucher: CartesiVoucher) { - super(model, voucher.payload, voucher.input.index, voucher.index, voucher.proof); - this._destination = voucher.destination; - } - wasExecuted = async (signer: Signer, dappAddress: string): Promise => { - return await wasVoucherExecutedFromParams(signer,dappAddress,this._inputIndex,this._outputIndex); - } - execute = async (signer: Signer, dappAddress: string): Promise => { - if (this._proof == undefined) - throw new Error("Voucher has no proof"); - return await executeVoucherFromParams(signer,dappAddress,this._destination,this._payload,this._proof); - } -} - - -/* - * Helpers - */ - -// Advance -export async function genericAdvanceInput( - client:Signer, - dappAddress:string, - selector:string, - inputData: IOData, - options?:AdvanceInputOptions -):Promise { - if (options == undefined) options = {}; - - const payloadHex = inputData.export(); - const output = await advanceInput(client,dappAddress,selector + payloadHex.replace('0x',''),options).catch( - e => { - if (String(e.message).startsWith('0x')) - throw new Error(ethers.utils.toUtf8String(e.message)); - throw new Error(e.message); - }); - - return output; -} - -// Inspect -export async function inspectCall( - payload:string, - options:InspectOptions -):Promise { - options.decodeTo = "no-decode"; - const inspectResult: string = await inspect(payload,options).catch( - e => { - if (String(e.message).startsWith('0x')) - throw new Error(ethers.utils.toUtf8String(e.message)); - throw new Error(e.message); - }) as string; // hex string - return {payload:inspectResult}; -} - -export async function genericInspect( - inputData: IOData, - route: string, - options?:InspectOptions -):Promise { - if (options == undefined) options = {}; - options.aggregate = true; - const payload = `${route}${inputData.export()}` - return await inspectCall(payload,options); -} - -// Decode -export function genericDecodeTo(data: string,model: ModelInterface): T { - let dataObj: any; - switch(model.ioType) { - /*# case mutationPayload: { - break; - } - case queryPayload: { - break; - }*/ - case IOType.report: { - const dataStr = ethers.utils.toUtf8String(data); - try { - dataObj = JSON.parse(dataStr); - } catch(e) { - throw new Error(dataStr); - } - dataObj = JSON.parse(ethers.utils.toUtf8String(data)); - if (!model.validator(dataObj)) - throw new Error(`Data does not implement interface: ${ajv.errorsText(model.validator.errors)}`); - break; - } - case IOType.notice: { - const dataValues = abiCoder.decode(model.abiTypes,data); - dataObj = {}; - let ind = 0; - for (const key of model.params) { - dataObj[key] = dataValues[ind]; - ind++; - } - const dataToValidate = { ...dataObj }; - for (const k of Object.keys(dataToValidate)) { - if (ethers.BigNumber.isBigNumber(dataToValidate[k])) - dataToValidate[k] = dataToValidate[k].toHexString(); - } - if (!model.validator(dataToValidate)) - throw new Error(`Data does not implement interface: ${ajv.errorsText(model.validator.errors)}`); - - break; - } - case IOType.voucher: { - const abiTypes: Array = ["bytes4"].concat(model.abiTypes); - const dataValues = abiCoder.decode(abiTypes,data); - dataObj = {}; - let ind = 0; - for (const key of model.params) { - if (ind == 0) continue; // skip selector - dataObj[key] = dataValues[ind-1]; - ind++; - } - const dataToValidate = { ...dataObj }; - for (const k of Object.keys(dataToValidate)) { - if (ethers.BigNumber.isBigNumber(dataToValidate[k])) - dataToValidate[k] = dataToValidate[k].toHexString(); - } - if (!model.validator(dataToValidate)) - throw new Error(`Data does not implement interface: ${ajv.errorsText(model.validator.errors)}`); - break; - } - default: { - throw new Error(`Cannot convert ${model.ioType}`); - // break; - } - } - return dataObj; -} - -export function decodeToConventionalTypes(data: string,modelName: string): any { - if (!CONVENTIONAL_TYPES.includes(modelName)) - throw new Error(`Cannot decode to ${modelName}`); - switch(modelName) { - case "bytes": { - if (typeof data == "string") { - if (ethers.utils.isHexString(data)) - return ethers.utils.arrayify(data); - else - throw new Error(`Cannot decode to bytes`); - } - return data; - } - case "hex": { - return data; - } - case "str": { - return ethers.utils.toUtf8String(data); - } - case "int": { - if (typeof data == "string") { - if (ethers.utils.isHexString(data)) - return parseInt(data, 16); - else - throw new Error(`Cannot decode to int`); - } - if (ethers.utils.isBytes(data)) - return parseInt(ethers.utils.hexlify(data), 16); - else - throw new Error(`Cannot decode to int`); - } - case "dict": case "list": case "tuple": case "json": { - return JSON.parse(ethers.utils.toUtf8String(data)); - } - } -} - -{% if add_indexer_query -%} - -interface OutMap { - [key: string]: CartesiReport | CartesiNotice | CartesiVoucher; -} -type outType = "report" | "notice" | "voucher"; -type AdvanceOutputMap = Record - -export async function decodeAdvance( - advanceResult: AdvanceOutput, - decoder: (data: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport, modelName:string) => any, - options?:InspectOptions): Promise -{ - let input_index:number; - if (advanceResult.reports.length > 0) { - input_index = advanceResult.reports[0].input.index; - } else if (advanceResult.notices.length > 0) { - input_index = advanceResult.notices[0].input.index; - } else if (advanceResult.vouchers.length > 0) { - input_index = advanceResult.vouchers[0].input.index; - } else { - // Can't decode outputs (no outputs) - return []; - } - const outMap: AdvanceOutputMap = {report:{},notice:{},voucher:{}}; - for (const report of advanceResult.reports) { outMap.report[report.index] = report } - for (const notice of advanceResult.notices) { outMap.notice[notice.index] = notice } - for (const voucher of advanceResult.vouchers) { outMap.voucher[voucher.index] = voucher } - - const indexerOutput: {{ indexer_output_info['model'].__name__ }} = await {{ convert_camel_case(indexer_query_info['method']) }}({input_index:input_index},{...options, decode:true, decodeModel:"{{ indexer_output_info['model'].__name__ }}"}) as {{ indexer_output_info['model'].__name__ }}; - - const outList: any[] = []; - for (const indOut of indexerOutput.data) { - outList.push( decoder(outMap[indOut.output_type as outType][`${indOut.output_index}`],indOut.class_name) ); - } - return outList -} - -// indexer -export async function genericGetOutputs( - inputData: ifaces.{{ indexer_query_info['model'].__name__ }}, - decoder: (data: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport, modelName:string) => any, - options?:InspectOptions -):Promise { - if (options == undefined) options = {}; - const indexerOutput: {{ indexer_output_info['model'].__name__ }} = await {{ convert_camel_case(indexer_query_info['method']) }}(inputData,{...options, decode:true, decodeModel:"{{ indexer_output_info['model'].__name__ }}"}) as {{ indexer_output_info['model'].__name__ }}; - const graphqlQueries: Promise[] = []; - for (const outInd of indexerOutput.data) { - const graphqlOptions: GraphqlOptions = {cartesiNodeUrl: options.cartesiNodeUrl, inputIndex: outInd.input_index, outputIndex: outInd.output_index}; - graphqlQueries.push(outputGetters[outInd.output_type](graphqlOptions).then( - (output: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport) => { - return decoder(output,outInd.class_name); - } - )); - } - return Promise.all(graphqlQueries); -} -{% endif %} -''' - -lib_imports = '''/* eslint-disable */ -/** - * This file was automatically generated by cartesapp.template_generator. - * DO NOT MODIFY IT BY HAND. Instead, run the generator, - */ -import { ethers, Signer, ContractReceipt } from "ethers"; -import Ajv from "ajv" -import addFormats from "ajv-formats" - -import { AdvanceOutput, InspectOptions, - Report as CartesiReport, Notice as CartesiNotice, Voucher as CartesiVoucher -} from "cartesi-client"; - -import { - genericAdvanceInput, genericInspect, IOType, Models, - IOData, Output, Event, ContractCall, InspectReport, - MutationOptions, QueryOptions, - CONVENTIONAL_TYPES, decodeToConventionalTypes{% if has_indexer_query -%}, genericGetOutputs, decodeAdvance{% endif %} -} from "../cartesapp/lib" - -{% if has_indexer_query -%} -import * as cartesappIfaces from "../cartesapp/ifaces" -{% endif -%} - -import * as ifaces from "./ifaces"; - - -/** - * Configs - */ - -const ajv = new Ajv(); -addFormats(ajv); -ajv.addFormat("biginteger", (data) => { - const dataTovalidate = data.startsWith('-') ? data.substring(1) : data; - return ethers.utils.isHexString(dataTovalidate) && dataTovalidate.length % 2 == 0; -}); -const MAX_SPLITTABLE_OUTPUT_SIZE = {{ MAX_SPLITTABLE_OUTPUT_SIZE }}; - -''' -lib_template = ''' -/* - * Mutations/Advances - */ - -{% for info in mutations_info -%} -export async function {{ convert_camel_case(info['method']) }}( - client:Signer, - dappAddress:string, - inputData: ifaces.{{ info['model'].__name__ }}, - options?:MutationOptions -):Promise { - const data: {{ info['model'].__name__ }} = new {{ info['model'].__name__ }}(inputData); - {% if has_indexer_query -%} - if (options?.decode) { options.sync = true; } - const result = await genericAdvanceInput(client,dappAddress,'{{ "0x"+info["selector"].to_bytes().hex() }}',data, options) - if (options?.decode) { - return decodeAdvance(result as AdvanceOutput,decodeToModel,options); - } - return result; -{% else -%} - return genericAdvanceInput(client,dappAddress,'{{ "0x"+info["selector"].to_bytes().hex() }}',data, options); -{% endif -%} -} - -{% endfor %} -/* - * Queries/Inspects - */ - -{% for info in queries_info -%} -export async function {{ convert_camel_case(info['method']) }}( - inputData: ifaces.{{ info['model'].__name__ }}, - options?:QueryOptions -):Promise { - const route = '{{ info["selector"] }}'; - {# return genericInspect(data,route,options); -#} - {% if info["configs"].get("splittable_output") -%} - let part:number = 0; - let hasMoreParts:boolean = false; - const output: InspectReport = {payload: "0x"} - do { - hasMoreParts = false; - let inputDataSplittable = Object.assign({part},inputData); - const data: {{ info['model'].__name__ }} = new {{ info['model'].__name__ }}(inputDataSplittable); - const partOutput: InspectReport = await genericInspect(data,route,options); - let payloadHex = partOutput.payload.substring(2); - if (payloadHex.length/2 > MAX_SPLITTABLE_OUTPUT_SIZE) { - part++; - payloadHex = payloadHex.substring(0, payloadHex.length - 2); - hasMoreParts = true; - } - output.payload += payloadHex; - } while (hasMoreParts) - {% else -%} - const data: {{ info['model'].__name__ }} = new {{ info['model'].__name__ }}(inputData); - const output: InspectReport = await genericInspect(data,route,options); - {% endif -%} - if (options?.decode) { return decodeToModel(output,options.decodeModel || "json"); } - return output; -} - -{% endfor %} -{% if has_indexer_query -%} -/* - * Indexer Query - */ - -export async function getOutputs( - inputData: cartesappIfaces.IndexerPayload, - options?:InspectOptions -):Promise { - return genericGetOutputs(inputData,decodeToModel,options); -} -{% endif %} - -/** - * Models Decoders/Exporters - */ - -export function decodeToModel(data: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport, modelName: string): any { - if (modelName == undefined) - throw new Error("undefined model"); - if (CONVENTIONAL_TYPES.includes(modelName)) - return decodeToConventionalTypes(data.payload,modelName); - const decoder = models[modelName].decoder; - if (decoder == undefined) - throw new Error("undefined decoder"); - return decoder(data); -} - -export function exportToModel(data: any, modelName: string): string { - const exporter = models[modelName].exporter; - if (exporter == undefined) - throw new Error("undefined exporter"); - return exporter(data); -} - -{% for info in mutations_payload_info -%} -export class {{ info['model'].__name__ }} extends IOData { constructor(data: ifaces.{{ info["model"].__name__ }}, validate: boolean = true) { super(models['{{ info["model"].__name__ }}'],data,validate); } } -export function exportTo{{ info['model'].__name__ }}(data: ifaces.{{ info["model"].__name__ }}): string { - const dataToExport: {{ info['model'].__name__ }} = new {{ info['model'].__name__ }}(data); - return dataToExport.export(); -} - -{% endfor -%} -{% for info in queries_payload_info -%} -export class {{ info['model'].__name__ }} extends IOData { constructor(data: ifaces.{{ info["model"].__name__ }}, validate: boolean = true) { super(models['{{ info["model"].__name__ }}'],data,validate); } } -export function exportTo{{ info['model'].__name__ }}(data: ifaces.{{ info["model"].__name__ }}): string { - const dataToExport: {{ info['model'].__name__ }} = new {{ info['model'].__name__ }}(data); - return dataToExport.export(); -} - -{% endfor -%} -{% for info in reports_info -%} -export class {{ info['class'] }} extends Output { constructor(output: CartesiReport | InspectReport) { super(models['{{ info["class"] }}'],output); } } -export function decodeTo{{ info['class'] }}(output: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport): {{ info['class'] }} { - return new {{ info['class'] }}(output as CartesiReport); -} - -{% endfor -%} -{% for info in notices_info -%} -export class {{ info['class'] }} extends Event { constructor(output: CartesiNotice) { super(models['{{ info["class"] }}'],output); } } -export function decodeTo{{ info['class'] }}(output: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport): {{ info['class'] }} { - return new {{ info['class'] }}(output as CartesiNotice); -} - -{% endfor -%} -{% for info in vouchers_info -%} -export class {{ info['class'] }} extends ConrtacCall { constructor(output: CartesiVoucher) { super(models['{{ info["class"] }}'],output); } } -export function decodeTo{{ info['class'] }}(output: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport): {{ info['class'] }} { - return new {{ info['class'] }}(output as CartesiVoucher); -} - -{% endfor %} -/** - * Model - */ - -export const models: Models = { - {% for info in mutations_payload_info -%} - '{{ info["model"].__name__ }}': { - ioType:IOType.mutationPayload, - abiTypes:{{ info['abi_types'] }}, - params:{{ list(info["model"].__fields__.keys()) }}, - exporter: exportTo{{ info["model"].__name__ }}, - validator: ajv.compile(JSON.parse('{{ info["model"].schema_json() }}')) - }, - {% endfor -%} - {% for info in queries_payload_info -%} - '{{ info["model"].__name__ }}': { - ioType:IOType.queryPayload, - abiTypes:{{ info['abi_types'] }}, - params:{{ list(info["model"].__fields__.keys()) }}, - exporter: exportTo{{ info["model"].__name__ }}, - validator: ajv.compile(JSON.parse('{{ info["model"].schema_json() }}')) - }, - {% endfor -%} - {% for info in reports_info -%} - '{{ info["class"] }}': { - ioType:IOType.report, - abiTypes:{{ info['abi_types'] }}, - params:{{ list(info["model"].__fields__.keys()) }}, - decoder: decodeTo{{ info['class'] }}, - validator: ajv.compile(JSON.parse('{{ info["model"].schema_json() }}')) - }, - {% endfor -%} - {% for info in notices_info -%} - '{{ info["class"] }}': { - ioType:IOType.notice, - abiTypes:{{ info['abi_types'] }}, - params:{{ list(info["model"].__fields__.keys()) }}, - decoder: decodeTo{{ info['class'] }}, - validator: ajv.compile(JSON.parse('{{ info["model"].schema_json() }}'.replaceAll('integer','string","format":"biginteger'))) - }, - {% endfor -%} - {% for info in vouchers_info -%} - '{{ info["class"] }}': { - ioType:IOType.voucher, - abiTypes:{{ info['abi_types'] }}, - params:{{ list(info["model"].__fields__.keys()) }}, - decoder: decodeTo{{ info['class'] }}, - validator: ajv.compile(JSON.parse('{{ info["model"].schema_json() }}'.replaceAll('integer','string","format":"biginteger'))) - }, - {% endfor -%} -}; -''' \ No newline at end of file diff --git a/cartesapp/utils.py b/cartesapp/utils.py deleted file mode 100644 index bc4adfd..0000000 --- a/cartesapp/utils.py +++ /dev/null @@ -1,28 +0,0 @@ - - -### -# Conversion Functions - -def hex2bytes(hexstr): - if hexstr.startswith('0x'): - hexstr = hexstr[2:] - return bytes.fromhex(hexstr) - -def bytes2str(binstr): - return binstr.decode("utf-8") - -def hex2str(hexstr): - return bytes2str(hex2bytes(hexstr)) - -def bytes2hex(value): - return "0x" + value.hex() - -def str2bytes(strtxt): - return strtxt.encode("utf-8") - -def str2hex(strtxt): - return bytes2hex(str2bytes(strtxt)) - - -### -# Helpers diff --git a/frontend/.env b/frontend/.env index 2b554d0..c735b6e 100644 --- a/frontend/.env +++ b/frontend/.env @@ -1,3 +1,4 @@ NEXT_PUBLIC_DAPP_ADDR="0x70ac08179605AF2D9e75782b8DEcDD3c22aA4D0C" NEXT_PUBLIC_CARTESI_NODE_URL="http://127.0.0.1:8080" NEXT_PUBLIC_NETWORK_CHAIN_ID="0x7A69" +NEXT_PUBLIC_NFT_ADDR="0xc6e7DF5E7b4f2A278906862b61205850344D4e7d" diff --git a/frontend/.env.sepolia b/frontend/.env.sepolia index ed86e03..085bf07 100644 --- a/frontend/.env.sepolia +++ b/frontend/.env.sepolia @@ -1,3 +1,4 @@ NEXT_PUBLIC_DAPP_ADDR="0x2540D48B63FbC123b819c81eBC4212A0c9E4432f" NEXT_PUBLIC_CARTESI_NODE_URL="https://rives.io" NEXT_PUBLIC_NETWORK_CHAIN_ID="0xAA36A7" +NEXT_PUBLIC_NFT_ADDR="" diff --git a/frontend/app/backend-libs/app/ifaces.d.ts b/frontend/app/backend-libs/app/ifaces.d.ts index 8114209..18e05ad 100644 --- a/frontend/app/backend-libs/app/ifaces.d.ts +++ b/frontend/app/backend-libs/app/ifaces.d.ts @@ -6,41 +6,85 @@ */ export interface _Master_ { - CreateScoreboardPayload: CreateScoreboardPayload; - ScoreboardRemoved: ScoreboardRemoved; + ScoresOutput: ScoresOutput; + ScoreboardCreated: ScoreboardCreated; + CartridgesOutput: CartridgesOutput; RemoveCartridgePayload: RemoveCartridgePayload; + CartridgeInfo: CartridgeInfo; + CartridgePayload: CartridgePayload; + ScoreboardRemoved: ScoreboardRemoved; + CartridgesPayload: CartridgesPayload; ScoreboardsOutput: ScoreboardsOutput; ScoreboardReplayScore: ScoreboardReplayScore; - ReplayScore: ReplayScore; - EmptyClass: EmptyClass; + CreateScoreboardPayload: CreateScoreboardPayload; + CartridgeInserted: CartridgeInserted; Replay: Replay; + ScoresPayload: ScoresPayload; CartridgePayloadSplittable: CartridgePayloadSplittable; + InserCartridgePayload: InserCartridgePayload; ScoreboardsPayload: ScoreboardsPayload; CartridgeRemoved: CartridgeRemoved; - CartridgesPayload: CartridgesPayload; - CartridgeInfo: CartridgeInfo; - CartridgePayload: CartridgePayload; - ScoresOutput: ScoresOutput; - ScoreboardCreated: ScoreboardCreated; - CartridgeInserted: CartridgeInserted; - CartridgesOutput: CartridgesOutput; - ScoresPayload: ScoresPayload; - InserCartridgePayload: InserCartridgePayload; ScoreboardReplayPayload: ScoreboardReplayPayload; + EmptyClass: EmptyClass; + ReplayScore: ReplayScore; } -export interface CreateScoreboardPayload { - cartridge_id: string; +export interface ScoresOutput { + data: ScoreInfo[]; + total: number; + page: number; +} +export interface ScoreInfo { + user_address: string; + timestamp: number; + score: number; +} +export interface ScoreboardCreated { + scoreboard_id: string; + created_by: string; + created_at: number; +} +export interface CartridgesOutput { + data: CartridgeInfo[]; + total: number; + page: number; +} +export interface CartridgeInfo { + id: string; name: string; - args: string; - in_card: string; - score_function: string; + user_address: string; + info?: Info; + created_at: number; + cover?: string; +} +export interface Info { + name: string; + summary?: string; + description?: string; + version?: string; + status?: string; + tags: string[]; + authors?: Author[]; + url?: string; +} +export interface Author { + name: string; + link: string; +} +export interface RemoveCartridgePayload { + id: string; +} +export interface CartridgePayload { + id: string; } export interface ScoreboardRemoved { scoreboard_id: string; timestamp: number; } -export interface RemoveCartridgePayload { - id: string; +export interface CartridgesPayload { + name?: string; + tags?: string[]; + page?: number; + page_size?: number; } export interface ScoreboardsOutput { data: ScoreboardInfo[]; @@ -65,28 +109,42 @@ export interface ScoreboardReplayScore { score_type?: number; extra_score: number; scoreboard_id: string; + user_alias?: string; + screenshot_cid?: string; + gameplay_hash: string; } -export interface ReplayScore { +export interface CreateScoreboardPayload { + cartridge_id: string; + name: string; + args: string; + in_card: string; + score_function: string; +} +export interface CartridgeInserted { cartridge_id: string; user_address: string; timestamp: number; - score: number; - score_type?: number; - extra_score?: number; - extra?: string; } -export interface EmptyClass {} export interface Replay { cartridge_id: string; outcard_hash: string; args: string; in_card: string; log: string; + user_alias: string; +} +export interface ScoresPayload { + scoreboard_id: string; + page?: number; + page_size?: number; } export interface CartridgePayloadSplittable { id: string; part?: number; } +export interface InserCartridgePayload { + data: string; +} export interface ScoreboardsPayload { cartridge_id: string; name?: string; @@ -97,72 +155,22 @@ export interface CartridgeRemoved { cartridge_id: string; timestamp: number; } -export interface CartridgesPayload { - name?: string; - tags?: string[]; - page?: number; - page_size?: number; -} -export interface CartridgeInfo { - id: string; - name: string; - user_address: string; - info?: Info; - created_at: number; - cover?: string; -} -export interface Info { - name: string; - summary?: string; - description?: string; - version?: string; - status?: string; - tags: string[]; - authors?: Author[]; - url?: string; -} -export interface Author { - name: string; - link: string; -} -export interface CartridgePayload { - id: string; -} -export interface ScoresOutput { - data: ScoreInfo[]; - total: number; - page: number; -} -export interface ScoreInfo { - user_address: string; - timestamp: number; - score: number; -} -export interface ScoreboardCreated { +export interface ScoreboardReplayPayload { scoreboard_id: string; - created_by: string; - created_at: number; + outcard_hash: string; + log: string; + user_alias: string; } -export interface CartridgeInserted { +export interface EmptyClass {} +export interface ReplayScore { cartridge_id: string; user_address: string; timestamp: number; -} -export interface CartridgesOutput { - data: CartridgeInfo[]; - total: number; - page: number; -} -export interface ScoresPayload { - scoreboard_id: string; - page?: number; - page_size?: number; -} -export interface InserCartridgePayload { - data: string; -} -export interface ScoreboardReplayPayload { - scoreboard_id: string; - outcard_hash: string; - log: string; + score: number; + score_type?: number; + extra_score?: number; + extra?: string; + user_alias?: string; + screenshot_cid?: string; + gameplay_hash: string; } diff --git a/frontend/app/backend-libs/app/lib.ts b/frontend/app/backend-libs/app/lib.ts index 57bf5a5..1b55d61 100644 --- a/frontend/app/backend-libs/app/lib.ts +++ b/frontend/app/backend-libs/app/lib.ts @@ -4,21 +4,32 @@ * DO NOT MODIFY IT BY HAND. Instead, run the generator, */ import { ethers, Signer, ContractReceipt } from "ethers"; -import Ajv from "ajv" -import addFormats from "ajv-formats" -import { AdvanceOutput, InspectOptions, - Report as CartesiReport, Notice as CartesiNotice, Voucher as CartesiVoucher +import { + advanceInput, inspect, + AdvanceOutput, InspectOptions, AdvanceInputOptions, GraphqlOptions, + EtherDepositOptions, ERC20DepositOptions, ERC721DepositOptions, + Report as CartesiReport, Notice as CartesiNotice, Voucher as CartesiVoucher, + advanceDAppRelay, advanceERC20Deposit, advanceERC721Deposit, advanceEtherDeposit, + queryNotice, queryReport, queryVoucher } from "cartesi-client"; + +import Ajv from "ajv" +import addFormats from "ajv-formats" + import { genericAdvanceInput, genericInspect, IOType, Models, IOData, Output, Event, ContractCall, InspectReport, MutationOptions, QueryOptions, - CONVENTIONAL_TYPES, decodeToConventionalTypes, genericGetOutputs, decodeAdvance + CONVENTIONAL_TYPES, decodeToConventionalTypes +} from "../cartesapp/utils" + +import { + genericGetOutputs, decodeAdvance } from "../cartesapp/lib" -import * as cartesappIfaces from "../cartesapp/ifaces" +import * as indexerIfaces from "../indexer/ifaces" import * as ifaces from "./ifaces"; @@ -76,7 +87,7 @@ export async function replay( ):Promise { const data: Replay = new Replay(inputData); if (options?.decode) { options.sync = true; } - const result = await genericAdvanceInput(client,dappAddress,'0x49ee5e36',data, options) + const result = await genericAdvanceInput(client,dappAddress,'0x456c9a94',data, options) if (options?.decode) { return decodeAdvance(result as AdvanceOutput,decodeToModel,options); } @@ -121,7 +132,7 @@ export async function scoreboardReplay( ):Promise { const data: ScoreboardReplayPayload = new ScoreboardReplayPayload(inputData); if (options?.decode) { options.sync = true; } - const result = await genericAdvanceInput(client,dappAddress,'0xc0b7397c',data, options) + const result = await genericAdvanceInput(client,dappAddress,'0x74add667',data, options) if (options?.decode) { return decodeAdvance(result as AdvanceOutput,decodeToModel,options); } @@ -208,7 +219,7 @@ export async function scores( */ export async function getOutputs( - inputData: cartesappIfaces.IndexerPayload, + inputData: indexerIfaces.IndexerPayload, options?:InspectOptions ):Promise { return genericGetOutputs(inputData,decodeToModel,options); @@ -237,15 +248,9 @@ export function exportToModel(data: any, modelName: string): string { return exporter(data); } -export class CreateScoreboardPayload extends IOData { constructor(data: ifaces.CreateScoreboardPayload, validate: boolean = true) { super(models['CreateScoreboardPayload'],data,validate); } } -export function exportToCreateScoreboardPayload(data: ifaces.CreateScoreboardPayload): string { - const dataToExport: CreateScoreboardPayload = new CreateScoreboardPayload(data); - return dataToExport.export(); -} - -export class ScoreboardReplayPayload extends IOData { constructor(data: ifaces.ScoreboardReplayPayload, validate: boolean = true) { super(models['ScoreboardReplayPayload'],data,validate); } } -export function exportToScoreboardReplayPayload(data: ifaces.ScoreboardReplayPayload): string { - const dataToExport: ScoreboardReplayPayload = new ScoreboardReplayPayload(data); +export class RemoveCartridgePayload extends IOData { constructor(data: ifaces.RemoveCartridgePayload, validate: boolean = true) { super(models['RemoveCartridgePayload'],data,validate); } } +export function exportToRemoveCartridgePayload(data: ifaces.RemoveCartridgePayload): string { + const dataToExport: RemoveCartridgePayload = new RemoveCartridgePayload(data); return dataToExport.export(); } @@ -261,27 +266,21 @@ export function exportToReplay(data: ifaces.Replay): string { return dataToExport.export(); } -export class RemoveCartridgePayload extends IOData { constructor(data: ifaces.RemoveCartridgePayload, validate: boolean = true) { super(models['RemoveCartridgePayload'],data,validate); } } -export function exportToRemoveCartridgePayload(data: ifaces.RemoveCartridgePayload): string { - const dataToExport: RemoveCartridgePayload = new RemoveCartridgePayload(data); - return dataToExport.export(); -} - export class InserCartridgePayload extends IOData { constructor(data: ifaces.InserCartridgePayload, validate: boolean = true) { super(models['InserCartridgePayload'],data,validate); } } export function exportToInserCartridgePayload(data: ifaces.InserCartridgePayload): string { const dataToExport: InserCartridgePayload = new InserCartridgePayload(data); return dataToExport.export(); } -export class CartridgePayloadSplittable extends IOData { constructor(data: ifaces.CartridgePayloadSplittable, validate: boolean = true) { super(models['CartridgePayloadSplittable'],data,validate); } } -export function exportToCartridgePayloadSplittable(data: ifaces.CartridgePayloadSplittable): string { - const dataToExport: CartridgePayloadSplittable = new CartridgePayloadSplittable(data); +export class CreateScoreboardPayload extends IOData { constructor(data: ifaces.CreateScoreboardPayload, validate: boolean = true) { super(models['CreateScoreboardPayload'],data,validate); } } +export function exportToCreateScoreboardPayload(data: ifaces.CreateScoreboardPayload): string { + const dataToExport: CreateScoreboardPayload = new CreateScoreboardPayload(data); return dataToExport.export(); } -export class ScoreboardsPayload extends IOData { constructor(data: ifaces.ScoreboardsPayload, validate: boolean = true) { super(models['ScoreboardsPayload'],data,validate); } } -export function exportToScoreboardsPayload(data: ifaces.ScoreboardsPayload): string { - const dataToExport: ScoreboardsPayload = new ScoreboardsPayload(data); +export class ScoreboardReplayPayload extends IOData { constructor(data: ifaces.ScoreboardReplayPayload, validate: boolean = true) { super(models['ScoreboardReplayPayload'],data,validate); } } +export function exportToScoreboardReplayPayload(data: ifaces.ScoreboardReplayPayload): string { + const dataToExport: ScoreboardReplayPayload = new ScoreboardReplayPayload(data); return dataToExport.export(); } @@ -291,12 +290,24 @@ export function exportToScoresPayload(data: ifaces.ScoresPayload): string { return dataToExport.export(); } +export class ScoreboardsPayload extends IOData { constructor(data: ifaces.ScoreboardsPayload, validate: boolean = true) { super(models['ScoreboardsPayload'],data,validate); } } +export function exportToScoreboardsPayload(data: ifaces.ScoreboardsPayload): string { + const dataToExport: ScoreboardsPayload = new ScoreboardsPayload(data); + return dataToExport.export(); +} + export class CartridgesPayload extends IOData { constructor(data: ifaces.CartridgesPayload, validate: boolean = true) { super(models['CartridgesPayload'],data,validate); } } export function exportToCartridgesPayload(data: ifaces.CartridgesPayload): string { const dataToExport: CartridgesPayload = new CartridgesPayload(data); return dataToExport.export(); } +export class CartridgePayloadSplittable extends IOData { constructor(data: ifaces.CartridgePayloadSplittable, validate: boolean = true) { super(models['CartridgePayloadSplittable'],data,validate); } } +export function exportToCartridgePayloadSplittable(data: ifaces.CartridgePayloadSplittable): string { + const dataToExport: CartridgePayloadSplittable = new CartridgePayloadSplittable(data); + return dataToExport.export(); +} + export class CartridgePayload extends IOData { constructor(data: ifaces.CartridgePayload, validate: boolean = true) { super(models['CartridgePayload'],data,validate); } } export function exportToCartridgePayload(data: ifaces.CartridgePayload): string { const dataToExport: CartridgePayload = new CartridgePayload(data); @@ -359,19 +370,12 @@ export function decodeToScoreboardReplayScore(output: CartesiReport | CartesiNot */ export const models: Models = { - 'CreateScoreboardPayload': { - ioType:IOType.mutationPayload, - abiTypes:['bytes32', 'string', 'string', 'bytes', 'string'], - params:['cartridge_id', 'name', 'args', 'in_card', 'score_function'], - exporter: exportToCreateScoreboardPayload, - validator: ajv.compile(JSON.parse('{"title": "CreateScoreboardPayload", "type": "object", "properties": {"cartridge_id": {"type": "string", "format": "binary"}, "name": {"type": "string"}, "args": {"type": "string"}, "in_card": {"type": "string", "format": "binary"}, "score_function": {"type": "string"}}, "required": ["cartridge_id", "name", "args", "in_card", "score_function"]}')) - }, - 'ScoreboardReplayPayload': { + 'RemoveCartridgePayload': { ioType:IOType.mutationPayload, - abiTypes:['bytes32', 'bytes32', 'bytes'], - params:['scoreboard_id', 'outcard_hash', 'log'], - exporter: exportToScoreboardReplayPayload, - validator: ajv.compile(JSON.parse('{"title": "ScoreboardReplayPayload", "type": "object", "properties": {"scoreboard_id": {"type": "string", "format": "binary"}, "outcard_hash": {"type": "string", "format": "binary"}, "log": {"type": "string", "format": "binary"}}, "required": ["scoreboard_id", "outcard_hash", "log"]}')) + abiTypes:['bytes32'], + params:['id'], + exporter: exportToRemoveCartridgePayload, + validator: ajv.compile(JSON.parse('{"title": "RemoveCartridgePayload", "type": "object", "properties": {"id": {"type": "string", "format": "binary"}}, "required": ["id"]}')) }, 'EmptyClass': { ioType:IOType.mutationPayload, @@ -382,17 +386,10 @@ export const models: Models = { }, 'Replay': { ioType:IOType.mutationPayload, - abiTypes:['bytes32', 'bytes32', 'string', 'bytes', 'bytes'], - params:['cartridge_id', 'outcard_hash', 'args', 'in_card', 'log'], + abiTypes:['bytes32', 'bytes32', 'string', 'bytes', 'bytes', 'string'], + params:['cartridge_id', 'outcard_hash', 'args', 'in_card', 'log', 'user_alias'], exporter: exportToReplay, - validator: ajv.compile(JSON.parse('{"title": "Replay", "type": "object", "properties": {"cartridge_id": {"type": "string", "format": "binary"}, "outcard_hash": {"type": "string", "format": "binary"}, "args": {"type": "string"}, "in_card": {"type": "string", "format": "binary"}, "log": {"type": "string", "format": "binary"}}, "required": ["cartridge_id", "outcard_hash", "args", "in_card", "log"]}')) - }, - 'RemoveCartridgePayload': { - ioType:IOType.mutationPayload, - abiTypes:['bytes32'], - params:['id'], - exporter: exportToRemoveCartridgePayload, - validator: ajv.compile(JSON.parse('{"title": "RemoveCartridgePayload", "type": "object", "properties": {"id": {"type": "string", "format": "binary"}}, "required": ["id"]}')) + validator: ajv.compile(JSON.parse('{"title": "Replay", "type": "object", "properties": {"cartridge_id": {"type": "string", "format": "binary"}, "outcard_hash": {"type": "string", "format": "binary"}, "args": {"type": "string"}, "in_card": {"type": "string", "format": "binary"}, "log": {"type": "string", "format": "binary"}, "user_alias": {"type": "string"}}, "required": ["cartridge_id", "outcard_hash", "args", "in_card", "log", "user_alias"]}')) }, 'InserCartridgePayload': { ioType:IOType.mutationPayload, @@ -401,12 +398,26 @@ export const models: Models = { exporter: exportToInserCartridgePayload, validator: ajv.compile(JSON.parse('{"title": "InserCartridgePayload", "type": "object", "properties": {"data": {"type": "string", "format": "binary"}}, "required": ["data"]}')) }, - 'CartridgePayloadSplittable': { + 'CreateScoreboardPayload': { + ioType:IOType.mutationPayload, + abiTypes:['bytes32', 'string', 'string', 'bytes', 'string'], + params:['cartridge_id', 'name', 'args', 'in_card', 'score_function'], + exporter: exportToCreateScoreboardPayload, + validator: ajv.compile(JSON.parse('{"title": "CreateScoreboardPayload", "type": "object", "properties": {"cartridge_id": {"type": "string", "format": "binary"}, "name": {"type": "string"}, "args": {"type": "string"}, "in_card": {"type": "string", "format": "binary"}, "score_function": {"type": "string"}}, "required": ["cartridge_id", "name", "args", "in_card", "score_function"]}')) + }, + 'ScoreboardReplayPayload': { + ioType:IOType.mutationPayload, + abiTypes:['bytes32', 'bytes32', 'bytes', 'string'], + params:['scoreboard_id', 'outcard_hash', 'log', 'user_alias'], + exporter: exportToScoreboardReplayPayload, + validator: ajv.compile(JSON.parse('{"title": "ScoreboardReplayPayload", "type": "object", "properties": {"scoreboard_id": {"type": "string", "format": "binary"}, "outcard_hash": {"type": "string", "format": "binary"}, "log": {"type": "string", "format": "binary"}, "user_alias": {"type": "string"}}, "required": ["scoreboard_id", "outcard_hash", "log", "user_alias"]}')) + }, + 'ScoresPayload': { ioType:IOType.queryPayload, abiTypes:[], - params:['id', 'part'], - exporter: exportToCartridgePayloadSplittable, - validator: ajv.compile(JSON.parse('{"title": "CartridgePayloadSplittable", "type": "object", "properties": {"id": {"type": "string"}, "part": {"type": "integer"}}, "required": ["id"]}')) + params:['scoreboard_id', 'page', 'page_size'], + exporter: exportToScoresPayload, + validator: ajv.compile(JSON.parse('{"title": "ScoresPayload", "type": "object", "properties": {"scoreboard_id": {"type": "string"}, "page": {"type": "integer"}, "page_size": {"type": "integer"}}, "required": ["scoreboard_id"]}')) }, 'ScoreboardsPayload': { ioType:IOType.queryPayload, @@ -415,13 +426,6 @@ export const models: Models = { exporter: exportToScoreboardsPayload, validator: ajv.compile(JSON.parse('{"title": "ScoreboardsPayload", "type": "object", "properties": {"cartridge_id": {"type": "string"}, "name": {"type": "string"}, "page": {"type": "integer"}, "page_size": {"type": "integer"}}, "required": ["cartridge_id"]}')) }, - 'ScoresPayload': { - ioType:IOType.queryPayload, - abiTypes:[], - params:['scoreboard_id', 'page', 'page_size'], - exporter: exportToScoresPayload, - validator: ajv.compile(JSON.parse('{"title": "ScoresPayload", "type": "object", "properties": {"scoreboard_id": {"type": "string"}, "page": {"type": "integer"}, "page_size": {"type": "integer"}}, "required": ["scoreboard_id"]}')) - }, 'CartridgesPayload': { ioType:IOType.queryPayload, abiTypes:[], @@ -429,6 +433,13 @@ export const models: Models = { exporter: exportToCartridgesPayload, validator: ajv.compile(JSON.parse('{"title": "CartridgesPayload", "type": "object", "properties": {"name": {"type": "string"}, "tags": {"type": "array", "items": {"type": "string"}}, "page": {"type": "integer"}, "page_size": {"type": "integer"}}}')) }, + 'CartridgePayloadSplittable': { + ioType:IOType.queryPayload, + abiTypes:[], + params:['id', 'part'], + exporter: exportToCartridgePayloadSplittable, + validator: ajv.compile(JSON.parse('{"title": "CartridgePayloadSplittable", "type": "object", "properties": {"id": {"type": "string"}, "part": {"type": "integer"}}, "required": ["id"]}')) + }, 'CartridgePayload': { ioType:IOType.queryPayload, abiTypes:[], @@ -480,10 +491,10 @@ export const models: Models = { }, 'ReplayScore': { ioType:IOType.notice, - abiTypes:['bytes32', 'string', 'uint', 'int', 'int', 'int', 'string'], - params:['cartridge_id', 'user_address', 'timestamp', 'score', 'score_type', 'extra_score', 'extra'], + abiTypes:['bytes32', 'address', 'uint', 'int', 'int', 'int', 'string', 'string', 'string', 'bytes32'], + params:['cartridge_id', 'user_address', 'timestamp', 'score', 'score_type', 'extra_score', 'extra', 'user_alias', 'screenshot_cid', 'gameplay_hash'], decoder: decodeToReplayScore, - validator: ajv.compile(JSON.parse('{"title": "ReplayScore", "type": "object", "properties": {"cartridge_id": {"type": "string", "format": "binary"}, "user_address": {"type": "string"}, "timestamp": {"type": "integer"}, "score": {"type": "integer"}, "score_type": {"default": 0, "type": "integer"}, "extra_score": {"default": 0, "type": "integer"}, "extra": {"default": "", "type": "string"}}, "required": ["cartridge_id", "user_address", "timestamp", "score"]}'.replaceAll('integer','string","format":"biginteger'))) + validator: ajv.compile(JSON.parse('{"title": "ReplayScore", "type": "object", "properties": {"cartridge_id": {"type": "string", "format": "binary"}, "user_address": {"type": "string"}, "timestamp": {"type": "integer"}, "score": {"type": "integer"}, "score_type": {"default": 0, "type": "integer"}, "extra_score": {"default": 0, "type": "integer"}, "extra": {"default": "", "type": "string"}, "user_alias": {"default": "", "type": "string"}, "screenshot_cid": {"default": "", "type": "string"}, "gameplay_hash": {"type": "string", "format": "binary"}}, "required": ["cartridge_id", "user_address", "timestamp", "score", "gameplay_hash"]}'.replaceAll('integer','string","format":"biginteger'))) }, 'ScoreboardCreated': { ioType:IOType.notice, @@ -501,9 +512,9 @@ export const models: Models = { }, 'ScoreboardReplayScore': { ioType:IOType.notice, - abiTypes:['bytes32', 'string', 'uint', 'int', 'int', 'int', 'string'], - params:['cartridge_id', 'user_address', 'timestamp', 'score', 'score_type', 'extra_score', 'scoreboard_id'], + abiTypes:['bytes32', 'address', 'uint', 'int', 'int', 'int', 'string', 'string', 'string', 'bytes32'], + params:['cartridge_id', 'user_address', 'timestamp', 'score', 'score_type', 'extra_score', 'scoreboard_id', 'user_alias', 'screenshot_cid', 'gameplay_hash'], decoder: decodeToScoreboardReplayScore, - validator: ajv.compile(JSON.parse('{"title": "ScoreboardReplayScore", "type": "object", "properties": {"cartridge_id": {"type": "string", "format": "binary"}, "user_address": {"type": "string"}, "timestamp": {"type": "integer"}, "score": {"type": "integer"}, "score_type": {"default": 1, "type": "integer"}, "extra_score": {"type": "integer"}, "scoreboard_id": {"type": "string"}}, "required": ["cartridge_id", "user_address", "timestamp", "score", "extra_score", "scoreboard_id"]}'.replaceAll('integer','string","format":"biginteger'))) + validator: ajv.compile(JSON.parse('{"title": "ScoreboardReplayScore", "type": "object", "properties": {"cartridge_id": {"type": "string", "format": "binary"}, "user_address": {"type": "string"}, "timestamp": {"type": "integer"}, "score": {"type": "integer"}, "score_type": {"default": 1, "type": "integer"}, "extra_score": {"type": "integer"}, "scoreboard_id": {"type": "string"}, "user_alias": {"default": "", "type": "string"}, "screenshot_cid": {"default": "", "type": "string"}, "gameplay_hash": {"type": "string", "format": "binary"}}, "required": ["cartridge_id", "user_address", "timestamp", "score", "extra_score", "scoreboard_id", "gameplay_hash"]}'.replaceAll('integer','string","format":"biginteger'))) }, }; \ No newline at end of file diff --git a/frontend/app/backend-libs/cartesapp/lib.ts b/frontend/app/backend-libs/cartesapp/lib.ts index 6f2ccfb..074b7b8 100644 --- a/frontend/app/backend-libs/cartesapp/lib.ts +++ b/frontend/app/backend-libs/cartesapp/lib.ts @@ -1,377 +1,27 @@ + /* eslint-disable */ /** * This file was automatically generated by cartesapp.template_generator. * DO NOT MODIFY IT BY HAND. Instead, run the generator, */ -import { Signer, ethers, ContractReceipt } from "ethers"; -import Ajv, { ValidateFunction } from "ajv" -import addFormats from "ajv-formats" import { advanceInput, inspect, - AdvanceOutput, InspectOptions, AdvanceInputOptions, + AdvanceOutput, InspectOptions, AdvanceInputOptions, GraphqlOptions, Report as CartesiReport, Notice as CartesiNotice, Voucher as CartesiVoucher, - Maybe, Proof, validateNoticeFromParams, wasVoucherExecutedFromParams, executeVoucherFromParams, - queryNotice, queryReport, queryVoucher, GraphqlOptions + advanceDAppRelay, advanceERC20Deposit, advanceERC721Deposit, advanceEtherDeposit, + queryNotice, queryReport, queryVoucher } from "cartesi-client"; -import * as ifaces from "./ifaces"; - - - -/** - * Configs - */ - -const ajv = new Ajv(); -addFormats(ajv); -ajv.addFormat("biginteger", (data) => { - const dataTovalidate = data.startsWith('-') ? data.substring(1) : data; - return ethers.utils.isHexString(dataTovalidate) && dataTovalidate.length % 2 == 0; -}); -const abiCoder = new ethers.utils.AbiCoder(); -export const CONVENTIONAL_TYPES: Array = ["bytes","hex","str","int","dict","list","tuple","json"]; -const MAX_SPLITTABLE_OUTPUT_SIZE = 4194247; - - -/** - * Models - */ - -export enum IOType { - report, - notice, - voucher, - mutationPayload, - queryPayload -} - -interface ModelInterface { - ioType: IOType; - abiTypes: Array; - params: Array; - decoder?(data: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport): T; - exporter?(data: T): string; - validator: ValidateFunction; -} - -export interface Models { - [key: string]: ModelInterface; -} - -export interface InspectReportInput { - index?: number; -} - -export interface InspectReport { - payload: string; - input?: InspectReportInput; - index?: number; -} - -export interface OutputGetters { - [key: string]: (o?: GraphqlOptions) => Promise|Promise|Promise; -} - -export const outputGetters: OutputGetters = { - report: queryReport, - notice: queryNotice, - voucher: queryVoucher -} - -export interface MutationOptions extends AdvanceInputOptions { - decode?: boolean; -} - -export interface QueryOptions extends InspectOptions { - decode?: boolean; - decodeModel?: string; -} - -export class IOData { - [key: string]: any; - _model: ModelInterface - - constructor(model: ModelInterface, data: T, validate: boolean = true) { - this._model = model; - for (const key of this._model.params) { - this[key] = (data as any)[key]; - } - if (validate) this.validate(); - } - - get = (): T => { - const data: any = {}; - for (const key of this._model.params) { - data[key] = this[key]; - } - return data; - } - - validate = (): boolean => { - const dataToValidate: any = { ...this.get() }; - for (const k of Object.keys(dataToValidate)) { - if (ethers.BigNumber.isBigNumber(dataToValidate[k])) - dataToValidate[k] = dataToValidate[k].toHexString(); - } - if (!this._model.validator(dataToValidate)) - throw new Error(`Data does not implement interface: ${ajv.errorsText(this._model.validator.errors)}`); - return true; - } - - export(): string { - let payload: string; - switch(this._model.ioType) { - case IOType.mutationPayload: { - // parametrize input to url - const inputData: any = this.get(); - const paramList = Array(); - for (const key of this._model.params) { - paramList.push(inputData[key]); - } - payload = abiCoder.encode(this._model.abiTypes,paramList); - break; - } - case IOType.queryPayload: { - // parametrize input to url - const inputData: T = this.get(); - const paramList = Array(); - for (const key in inputData) { - if (inputData[key] == undefined) continue; - if (Array.isArray(inputData[key])) { - for (const element in inputData[key]) { - paramList.push(`${key}=${inputData[key][element]}`); - } - } else { - paramList.push(`${key}=${inputData[key]}`); - } - } - payload = paramList.length > 0 ? `?${paramList.join('&')}` : ""; - break; - } - default: { - throw new Error(`Invalid payload type ${this._model.ioType}`); - // break; - } - } - return payload; - } -} - -export class BasicOutput extends IOData { - _payload: string - _inputIndex?: number - _outputIndex?: number - - constructor(model: ModelInterface, payload: string, inputIndex?: number, outputIndex?: number) { - super(model,genericDecodeTo(payload,model),false); - this._inputIndex = inputIndex; - this._outputIndex = outputIndex; - this._payload = payload; - } -} - -export class Output extends BasicOutput{ - constructor(model: ModelInterface, report: CartesiReport | InspectReport) { - super(model, report.payload, report.input?.index, report.index); - } -} - -export class OutputWithProof extends BasicOutput{ - _proof: Maybe | undefined - _inputIndex: number - _outputIndex: number - - constructor(model: ModelInterface, payload: string, inputIndex: number, outputIndex: number, proof: Maybe | undefined) { - super(model, payload, inputIndex, outputIndex); - this._inputIndex = inputIndex; - this._outputIndex = outputIndex; - this._proof = proof; - } -} - -export class Event extends OutputWithProof{ - constructor(model: ModelInterface, notice: CartesiNotice) { - super(model, notice.payload, notice.input.index, notice.index, notice.proof); - } - validateOnchain = async (signer: Signer, dappAddress: string): Promise => { - if (this._proof == undefined) - throw new Error("Notice has no proof"); - return await validateNoticeFromParams(signer,dappAddress,this._payload,this._proof); - } -} - -export class ContractCall extends OutputWithProof{ - _destination: string - constructor(model: ModelInterface, voucher: CartesiVoucher) { - super(model, voucher.payload, voucher.input.index, voucher.index, voucher.proof); - this._destination = voucher.destination; - } - wasExecuted = async (signer: Signer, dappAddress: string): Promise => { - return await wasVoucherExecutedFromParams(signer,dappAddress,this._inputIndex,this._outputIndex); - } - execute = async (signer: Signer, dappAddress: string): Promise => { - if (this._proof == undefined) - throw new Error("Voucher has no proof"); - return await executeVoucherFromParams(signer,dappAddress,this._destination,this._payload,this._proof); - } -} - - -/* - * Helpers - */ - -// Advance -export async function genericAdvanceInput( - client:Signer, - dappAddress:string, - selector:string, - inputData: IOData, - options?:AdvanceInputOptions -):Promise { - if (options == undefined) options = {}; - - const payloadHex = inputData.export(); - const output = await advanceInput(client,dappAddress,selector + payloadHex.replace('0x',''),options).catch( - e => { - if (String(e.message).startsWith('0x')) - throw new Error(ethers.utils.toUtf8String(e.message)); - throw new Error(e.message); - }); +import { + InspectReport, outputGetters +} from "../cartesapp/utils" - return output; -} +import * as indexerIfaces from "../indexer/ifaces"; +import * as indexerLib from "../indexer/lib" -// Inspect -export async function inspectCall( - payload:string, - options:InspectOptions -):Promise { - options.decodeTo = "no-decode"; - const inspectResult: string = await inspect(payload,options).catch( - e => { - if (String(e.message).startsWith('0x')) - throw new Error(ethers.utils.toUtf8String(e.message)); - throw new Error(e.message); - }) as string; // hex string - return {payload:inspectResult}; -} -export async function genericInspect( - inputData: IOData, - route: string, - options?:InspectOptions -):Promise { - if (options == undefined) options = {}; - options.aggregate = true; - const payload = `${route}${inputData.export()}` - return await inspectCall(payload,options); -} -// Decode -export function genericDecodeTo(data: string,model: ModelInterface): T { - let dataObj: any; - switch(model.ioType) { - /*# case mutationPayload: { - break; - } - case queryPayload: { - break; - }*/ - case IOType.report: { - const dataStr = ethers.utils.toUtf8String(data); - try { - dataObj = JSON.parse(dataStr); - } catch(e) { - throw new Error(dataStr); - } - dataObj = JSON.parse(ethers.utils.toUtf8String(data)); - if (!model.validator(dataObj)) - throw new Error(`Data does not implement interface: ${ajv.errorsText(model.validator.errors)}`); - break; - } - case IOType.notice: { - const dataValues = abiCoder.decode(model.abiTypes,data); - dataObj = {}; - let ind = 0; - for (const key of model.params) { - dataObj[key] = dataValues[ind]; - ind++; - } - const dataToValidate = { ...dataObj }; - for (const k of Object.keys(dataToValidate)) { - if (ethers.BigNumber.isBigNumber(dataToValidate[k])) - dataToValidate[k] = dataToValidate[k].toHexString(); - } - if (!model.validator(dataToValidate)) - throw new Error(`Data does not implement interface: ${ajv.errorsText(model.validator.errors)}`); - - break; - } - case IOType.voucher: { - const abiTypes: Array = ["bytes4"].concat(model.abiTypes); - const dataValues = abiCoder.decode(abiTypes,data); - dataObj = {}; - let ind = 0; - for (const key of model.params) { - if (ind == 0) continue; // skip selector - dataObj[key] = dataValues[ind-1]; - ind++; - } - const dataToValidate = { ...dataObj }; - for (const k of Object.keys(dataToValidate)) { - if (ethers.BigNumber.isBigNumber(dataToValidate[k])) - dataToValidate[k] = dataToValidate[k].toHexString(); - } - if (!model.validator(dataToValidate)) - throw new Error(`Data does not implement interface: ${ajv.errorsText(model.validator.errors)}`); - break; - } - default: { - throw new Error(`Cannot convert ${model.ioType}`); - // break; - } - } - return dataObj; -} - -export function decodeToConventionalTypes(data: string,modelName: string): any { - if (!CONVENTIONAL_TYPES.includes(modelName)) - throw new Error(`Cannot decode to ${modelName}`); - switch(modelName) { - case "bytes": { - if (typeof data == "string") { - if (ethers.utils.isHexString(data)) - return ethers.utils.arrayify(data); - else - throw new Error(`Cannot decode to bytes`); - } - return data; - } - case "hex": { - return data; - } - case "str": { - return ethers.utils.toUtf8String(data); - } - case "int": { - if (typeof data == "string") { - if (ethers.utils.isHexString(data)) - return parseInt(data, 16); - else - throw new Error(`Cannot decode to int`); - } - if (ethers.utils.isBytes(data)) - return parseInt(ethers.utils.hexlify(data), 16); - else - throw new Error(`Cannot decode to int`); - } - case "dict": case "list": case "tuple": case "json": { - return JSON.parse(ethers.utils.toUtf8String(data)); - } - } -} interface OutMap { [key: string]: CartesiReport | CartesiNotice | CartesiVoucher; @@ -400,7 +50,7 @@ export async function decodeAdvance( for (const notice of advanceResult.notices) { outMap.notice[notice.index] = notice } for (const voucher of advanceResult.vouchers) { outMap.voucher[voucher.index] = voucher } - const indexerOutput: IndexerOutput = await indexerQuery({input_index:input_index},{...options, decode:true, decodeModel:"IndexerOutput"}) as IndexerOutput; + const indexerOutput: indexerLib.IndexerOutput = await indexerLib.indexerQuery({input_index:input_index},{...options, decode:true, decodeModel:"IndexerOutput"}) as indexerLib.IndexerOutput; const outList: any[] = []; for (const indOut of indexerOutput.data) { @@ -411,12 +61,12 @@ export async function decodeAdvance( // indexer export async function genericGetOutputs( - inputData: ifaces.IndexerPayload, + inputData: indexerIfaces.IndexerPayload, decoder: (data: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport, modelName:string) => any, options?:InspectOptions ):Promise { if (options == undefined) options = {}; - const indexerOutput: IndexerOutput = await indexerQuery(inputData,{...options, decode:true, decodeModel:"IndexerOutput"}) as IndexerOutput; + const indexerOutput: indexerLib.IndexerOutput = await indexerLib.indexerQuery(inputData,{...options, decode:true, decodeModel:"IndexerOutput"}) as indexerLib.IndexerOutput; const graphqlQueries: Promise[] = []; for (const outInd of indexerOutput.data) { const graphqlOptions: GraphqlOptions = {cartesiNodeUrl: options.cartesiNodeUrl, inputIndex: outInd.input_index, outputIndex: outInd.output_index}; @@ -429,80 +79,3 @@ export async function genericGetOutputs( return Promise.all(graphqlQueries); } -/* - * Mutations/Advances - */ - - -/* - * Queries/Inspects - */ - -export async function indexerQuery( - inputData: ifaces.IndexerPayload, - options?:QueryOptions -):Promise { - const route = 'cartesapp/indexer_query'; - const data: IndexerPayload = new IndexerPayload(inputData); - const output: InspectReport = await genericInspect(data,route,options); - if (options?.decode) { return decodeToModel(output,options.decodeModel || "json"); } - return output; -} - - - - -/** - * Models Decoders/Exporters - */ - -export function decodeToModel(data: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport, modelName: string): any { - if (modelName == undefined) - throw new Error("undefined model"); - if (CONVENTIONAL_TYPES.includes(modelName)) - return decodeToConventionalTypes(data.payload,modelName); - const decoder = models[modelName].decoder; - if (decoder == undefined) - throw new Error("undefined decoder"); - return decoder(data); -} - -export function exportToModel(data: any, modelName: string): string { - const exporter = models[modelName].exporter; - if (exporter == undefined) - throw new Error("undefined exporter"); - return exporter(data); -} - -export class IndexerPayload extends IOData { constructor(data: ifaces.IndexerPayload, validate: boolean = true) { super(models['IndexerPayload'],data,validate); } } -export function exportToIndexerPayload(data: ifaces.IndexerPayload): string { - const dataToExport: IndexerPayload = new IndexerPayload(data); - return dataToExport.export(); -} - -export class IndexerOutput extends Output { constructor(output: CartesiReport | InspectReport) { super(models['IndexerOutput'],output); } } -export function decodeToIndexerOutput(output: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport): IndexerOutput { - return new IndexerOutput(output as CartesiReport); -} - - -/** - * Model - */ - -export const models: Models = { - 'IndexerPayload': { - ioType:IOType.queryPayload, - abiTypes:[], - params:['tags', 'output_type', 'msg_sender', 'timestamp_gte', 'timestamp_lte', 'module', 'input_index'], - exporter: exportToIndexerPayload, - validator: ajv.compile(JSON.parse('{"title": "IndexerPayload", "type": "object", "properties": {"tags": {"type": "array", "items": {"type": "string"}}, "output_type": {"type": "string"}, "msg_sender": {"type": "string"}, "timestamp_gte": {"type": "integer"}, "timestamp_lte": {"type": "integer"}, "module": {"type": "string"}, "input_index": {"type": "integer"}}}')) - }, - 'IndexerOutput': { - ioType:IOType.report, - abiTypes:[], - params:['data'], - decoder: decodeToIndexerOutput, - validator: ajv.compile(JSON.parse('{"title": "IndexerOutput", "type": "object", "properties": {"data": {"type": "array", "items": {"$ref": "#/definitions/OutputIndex"}}}, "required": ["data"], "definitions": {"OutputIndex": {"title": "OutputIndex", "type": "object", "properties": {"output_type": {"type": "string"}, "module": {"type": "string"}, "class_name": {"type": "string"}, "input_index": {"type": "integer"}, "output_index": {"type": "integer"}}, "required": ["output_type", "module", "class_name", "input_index", "output_index"]}}}')) - }, - }; \ No newline at end of file diff --git a/frontend/app/backend-libs/cartesapp/utils.ts b/frontend/app/backend-libs/cartesapp/utils.ts new file mode 100644 index 0000000..139884d --- /dev/null +++ b/frontend/app/backend-libs/cartesapp/utils.ts @@ -0,0 +1,377 @@ +/* eslint-disable */ +/** + * This file was automatically generated by cartesapp.template_generator. + * DO NOT MODIFY IT BY HAND. Instead, run the generator, + */ +import { Signer, ethers, ContractReceipt } from "ethers"; +import Ajv, { ValidateFunction } from "ajv" +import addFormats from "ajv-formats" + +import { + advanceInput, inspect, + AdvanceOutput, InspectOptions, AdvanceInputOptions, + Report as CartesiReport, Notice as CartesiNotice, Voucher as CartesiVoucher, + Maybe, Proof, validateNoticeFromParams, wasVoucherExecutedFromParams, executeVoucherFromParams, + queryNotice, queryReport, queryVoucher, GraphqlOptions +} from "cartesi-client"; + +/** + * Configs + */ + +const ajv = new Ajv(); +addFormats(ajv); +ajv.addFormat("biginteger", (data) => { + const dataTovalidate = data.startsWith('-') ? data.substring(1) : data; + return ethers.utils.isHexString(dataTovalidate) && dataTovalidate.length % 2 == 0; +}); +const abiCoder = new ethers.utils.AbiCoder(); +export const CONVENTIONAL_TYPES: Array = ["bytes","hex","str","int","dict","list","tuple","json"]; +const MAX_SPLITTABLE_OUTPUT_SIZE = 4194247; + + +/** + * Models + */ + +export enum IOType { + report, + notice, + voucher, + mutationPayload, + queryPayload +} + +interface ModelInterface { + ioType: IOType; + abiTypes: Array; + params: Array; + decoder?(data: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport): T; + exporter?(data: T): string; + validator: ValidateFunction; +} + +export interface Models { + [key: string]: ModelInterface; +} + +export interface InspectReportInput { + index?: number; +} + +export interface InspectReport { + payload: string; + input?: InspectReportInput; + index?: number; +} + +export interface OutputGetters { + [key: string]: (o?: GraphqlOptions) => Promise|Promise|Promise; +} + +export const outputGetters: OutputGetters = { + report: queryReport, + notice: queryNotice, + voucher: queryVoucher +} + +export interface MutationOptions extends AdvanceInputOptions { + decode?: boolean; +} + +export interface QueryOptions extends InspectOptions { + decode?: boolean; + decodeModel?: string; +} + +export class IOData { + [key: string]: any; + _model: ModelInterface + + constructor(model: ModelInterface, data: T, validate: boolean = true) { + this._model = model; + for (const key of this._model.params) { + this[key] = (data as any)[key]; + } + if (validate) this.validate(); + } + + get = (): T => { + const data: any = {}; + for (const key of this._model.params) { + data[key] = this[key]; + } + return data; + } + + validate = (): boolean => { + const dataToValidate: any = { ...this.get() }; + for (const k of Object.keys(dataToValidate)) { + if (ethers.BigNumber.isBigNumber(dataToValidate[k])) + dataToValidate[k] = dataToValidate[k].toHexString(); + } + if (!this._model.validator(dataToValidate)) + throw new Error(`Data does not implement interface: ${ajv.errorsText(this._model.validator.errors)}`); + return true; + } + + export(excludeParams: string[] = []): string { + let payload: string; + switch(this._model.ioType) { + case IOType.mutationPayload: { + // parametrize input to url + const inputData: any = this.get(); + const paramList = Array(); + for (const key of this._model.params) { + paramList.push(inputData[key]); + } + payload = abiCoder.encode(this._model.abiTypes,paramList); + break; + } + case IOType.queryPayload: { + // parametrize input to url + const inputData: T = this.get(); + const paramList = Array(); + for (const key in inputData) { + if (inputData[key] == undefined) continue; + if (excludeParams.indexOf(key) > -1) continue; + if (Array.isArray(inputData[key])) { + for (const element in inputData[key]) { + paramList.push(`${key}=${inputData[key][element]}`); + } + } else { + paramList.push(`${key}=${inputData[key]}`); + } + } + payload = paramList.length > 0 ? `?${paramList.join('&')}` : ""; + break; + } + default: { + throw new Error(`Invalid payload type ${this._model.ioType}`); + // break; + } + } + return payload; + } +} + +export class BasicOutput extends IOData { + _payload: string + _inputIndex?: number + _outputIndex?: number + + constructor(model: ModelInterface, payload: string, inputIndex?: number, outputIndex?: number) { + super(model,genericDecodeTo(payload,model),false); + this._inputIndex = inputIndex; + this._outputIndex = outputIndex; + this._payload = payload; + } +} + +export class Output extends BasicOutput{ + constructor(model: ModelInterface, report: CartesiReport | InspectReport) { + super(model, report.payload, report.input?.index, report.index); + } +} + +export class OutputWithProof extends BasicOutput{ + _proof: Maybe | undefined + _inputIndex: number + _outputIndex: number + + constructor(model: ModelInterface, payload: string, inputIndex: number, outputIndex: number, proof: Maybe | undefined) { + super(model, payload, inputIndex, outputIndex); + this._inputIndex = inputIndex; + this._outputIndex = outputIndex; + this._proof = proof; + } +} + +export class Event extends OutputWithProof{ + constructor(model: ModelInterface, notice: CartesiNotice) { + super(model, notice.payload, notice.input.index, notice.index, notice.proof); + } + validateOnchain = async (signer: Signer, dappAddress: string): Promise => { + if (this._proof == undefined) + throw new Error("Notice has no proof"); + return await validateNoticeFromParams(signer,dappAddress,this._payload,this._proof); + } +} + +export class ContractCall extends OutputWithProof{ + _destination: string + constructor(model: ModelInterface, voucher: CartesiVoucher) { + super(model, voucher.payload, voucher.input.index, voucher.index, voucher.proof); + this._destination = voucher.destination; + } + wasExecuted = async (signer: Signer, dappAddress: string): Promise => { + return await wasVoucherExecutedFromParams(signer,dappAddress,this._inputIndex,this._outputIndex); + } + execute = async (signer: Signer, dappAddress: string): Promise => { + if (this._proof == undefined) + throw new Error("Voucher has no proof"); + return await executeVoucherFromParams(signer,dappAddress,this._destination,this._payload,this._proof); + } +} + + +/* + * Helpers + */ + +// Advance +export async function genericAdvanceInput( + client:Signer, + dappAddress:string, + selector:string, + inputData: IOData, + options?:AdvanceInputOptions +):Promise { + if (options == undefined) options = {}; + + const payloadHex = inputData.export(); + const output = await advanceInput(client,dappAddress,selector + payloadHex.replace('0x',''),options).catch( + e => { + if (String(e.message).startsWith('0x')) + throw new Error(ethers.utils.toUtf8String(e.message)); + throw new Error(e.message); + }); + + return output; +} + +// Inspect +export async function inspectCall( + payload:string, + options:InspectOptions +):Promise { + options.decodeTo = "no-decode"; + const inspectResult: string = await inspect(payload,options).catch( + e => { + if (String(e.message).startsWith('0x')) + throw new Error(ethers.utils.toUtf8String(e.message)); + throw new Error(e.message); + }) as string; // hex string + return {payload:inspectResult}; +} + +export async function genericInspect( + inputData: IOData, + route: string, + options?:InspectOptions +):Promise { + if (options == undefined) options = {}; + options.aggregate = true; + const excludeParams: string[] = []; + const matchRoute = route.matchAll(/\{(\w+)\}/g); + for (const m of matchRoute) { + route.replace(m[0],inputData[m[0]]); + excludeParams.push(m[1]); + } + const payload = `${route}${inputData.export()}` + return await inspectCall(payload,options); +} + +// Decode +export function genericDecodeTo(data: string,model: ModelInterface): T { + let dataObj: any; + switch(model.ioType) { + /*# case mutationPayload: { + break; + } + case queryPayload: { + break; + }*/ + case IOType.report: { + const dataStr = ethers.utils.toUtf8String(data); + try { + dataObj = JSON.parse(dataStr); + } catch(e) { + throw new Error(dataStr); + } + dataObj = JSON.parse(ethers.utils.toUtf8String(data)); + if (!model.validator(dataObj)) + throw new Error(`Data does not implement interface: ${ajv.errorsText(model.validator.errors)}`); + break; + } + case IOType.notice: { + const dataValues = abiCoder.decode(model.abiTypes,data); + dataObj = {}; + let ind = 0; + for (const key of model.params) { + dataObj[key] = dataValues[ind]; + ind++; + } + const dataToValidate = { ...dataObj }; + for (const k of Object.keys(dataToValidate)) { + if (ethers.BigNumber.isBigNumber(dataToValidate[k])) + dataToValidate[k] = dataToValidate[k].toHexString(); + } + if (!model.validator(dataToValidate)) + throw new Error(`Data does not implement interface: ${ajv.errorsText(model.validator.errors)}`); + + break; + } + case IOType.voucher: { + const abiTypes: Array = ["bytes4"].concat(model.abiTypes); + const dataValues = abiCoder.decode(abiTypes,data); + dataObj = {}; + let ind = 0; + for (const key of model.params) { + if (ind == 0) continue; // skip selector + dataObj[key] = dataValues[ind-1]; + ind++; + } + const dataToValidate = { ...dataObj }; + for (const k of Object.keys(dataToValidate)) { + if (ethers.BigNumber.isBigNumber(dataToValidate[k])) + dataToValidate[k] = dataToValidate[k].toHexString(); + } + if (!model.validator(dataToValidate)) + throw new Error(`Data does not implement interface: ${ajv.errorsText(model.validator.errors)}`); + break; + } + default: { + throw new Error(`Cannot convert ${model.ioType}`); + // break; + } + } + return dataObj; +} + +export function decodeToConventionalTypes(data: string,modelName: string): any { + if (!CONVENTIONAL_TYPES.includes(modelName)) + throw new Error(`Cannot decode to ${modelName}`); + switch(modelName) { + case "bytes": { + if (typeof data == "string") { + if (ethers.utils.isHexString(data)) + return ethers.utils.arrayify(data); + else + throw new Error(`Cannot decode to bytes`); + } + return data; + } + case "hex": { + return data; + } + case "str": { + return ethers.utils.toUtf8String(data); + } + case "int": { + if (typeof data == "string") { + if (ethers.utils.isHexString(data)) + return parseInt(data, 16); + else + throw new Error(`Cannot decode to int`); + } + if (ethers.utils.isBytes(data)) + return parseInt(ethers.utils.hexlify(data), 16); + else + throw new Error(`Cannot decode to int`); + } + case "dict": case "list": case "tuple": case "json": { + return JSON.parse(ethers.utils.toUtf8String(data)); + } + } +} diff --git a/frontend/app/backend-libs/cartesapp/ifaces.d.ts b/frontend/app/backend-libs/indexer/ifaces.d.ts similarity index 100% rename from frontend/app/backend-libs/cartesapp/ifaces.d.ts rename to frontend/app/backend-libs/indexer/ifaces.d.ts index 1078e22..d9f996c 100644 --- a/frontend/app/backend-libs/cartesapp/ifaces.d.ts +++ b/frontend/app/backend-libs/indexer/ifaces.d.ts @@ -6,8 +6,17 @@ */ export interface _Master_ { - IndexerOutput: IndexerOutput; IndexerPayload: IndexerPayload; + IndexerOutput: IndexerOutput; +} +export interface IndexerPayload { + tags?: string[]; + output_type?: string; + msg_sender?: string; + timestamp_gte?: number; + timestamp_lte?: number; + module?: string; + input_index?: number; } export interface IndexerOutput { data: OutputIndex[]; @@ -19,12 +28,3 @@ export interface OutputIndex { input_index: number; output_index: number; } -export interface IndexerPayload { - tags?: string[]; - output_type?: string; - msg_sender?: string; - timestamp_gte?: number; - timestamp_lte?: number; - module?: string; - input_index?: number; -} diff --git a/frontend/app/backend-libs/indexer/lib.ts b/frontend/app/backend-libs/indexer/lib.ts new file mode 100644 index 0000000..5b666df --- /dev/null +++ b/frontend/app/backend-libs/indexer/lib.ts @@ -0,0 +1,119 @@ +/* eslint-disable */ +/** + * This file was automatically generated by cartesapp.template_generator. + * DO NOT MODIFY IT BY HAND. Instead, run the generator, + */ +import { ethers, Signer, ContractReceipt } from "ethers"; + +import { + advanceInput, inspect, + AdvanceOutput, InspectOptions, AdvanceInputOptions, GraphqlOptions, + EtherDepositOptions, ERC20DepositOptions, ERC721DepositOptions, + Report as CartesiReport, Notice as CartesiNotice, Voucher as CartesiVoucher, + advanceDAppRelay, advanceERC20Deposit, advanceERC721Deposit, advanceEtherDeposit, + queryNotice, queryReport, queryVoucher +} from "cartesi-client"; + + +import Ajv from "ajv" +import addFormats from "ajv-formats" + +import { + genericAdvanceInput, genericInspect, IOType, Models, + IOData, Output, Event, ContractCall, InspectReport, + MutationOptions, QueryOptions, + CONVENTIONAL_TYPES, decodeToConventionalTypes +} from "../cartesapp/utils" + +import * as ifaces from "./ifaces"; + + +/** + * Configs + */ + +const ajv = new Ajv(); +addFormats(ajv); +ajv.addFormat("biginteger", (data) => { + const dataTovalidate = data.startsWith('-') ? data.substring(1) : data; + return ethers.utils.isHexString(dataTovalidate) && dataTovalidate.length % 2 == 0; +}); +const MAX_SPLITTABLE_OUTPUT_SIZE = 4194247; + +/* + * Mutations/Advances + */ + + +/* + * Queries/Inspects + */ + +export async function indexerQuery( + inputData: ifaces.IndexerPayload, + options?:QueryOptions +):Promise { + const route = 'indexer/indexer_query'; + const data: IndexerPayload = new IndexerPayload(inputData); + const output: InspectReport = await genericInspect(data,route,options); + if (options?.decode) { return decodeToModel(output,options.decodeModel || "json"); } + return output; +} + + + + +/** + * Models Decoders/Exporters + */ + +export function decodeToModel(data: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport, modelName: string): any { + if (modelName == undefined) + throw new Error("undefined model"); + if (CONVENTIONAL_TYPES.includes(modelName)) + return decodeToConventionalTypes(data.payload,modelName); + const decoder = models[modelName].decoder; + if (decoder == undefined) + throw new Error("undefined decoder"); + return decoder(data); +} + +export function exportToModel(data: any, modelName: string): string { + const exporter = models[modelName].exporter; + if (exporter == undefined) + throw new Error("undefined exporter"); + return exporter(data); +} + +export class IndexerPayload extends IOData { constructor(data: ifaces.IndexerPayload, validate: boolean = true) { super(models['IndexerPayload'],data,validate); } } +export function exportToIndexerPayload(data: ifaces.IndexerPayload): string { + const dataToExport: IndexerPayload = new IndexerPayload(data); + return dataToExport.export(); +} + +export class IndexerOutput extends Output { constructor(output: CartesiReport | InspectReport) { super(models['IndexerOutput'],output); } } +export function decodeToIndexerOutput(output: CartesiReport | CartesiNotice | CartesiVoucher | InspectReport): IndexerOutput { + return new IndexerOutput(output as CartesiReport); +} + + +/** + * Model + */ + +export const models: Models = { + 'IndexerPayload': { + ioType:IOType.queryPayload, + abiTypes:[], + params:['tags', 'output_type', 'msg_sender', 'timestamp_gte', 'timestamp_lte', 'module', 'input_index'], + exporter: exportToIndexerPayload, + validator: ajv.compile(JSON.parse('{"title": "IndexerPayload", "type": "object", "properties": {"tags": {"type": "array", "items": {"type": "string"}}, "output_type": {"type": "string"}, "msg_sender": {"type": "string"}, "timestamp_gte": {"type": "integer"}, "timestamp_lte": {"type": "integer"}, "module": {"type": "string"}, "input_index": {"type": "integer"}}}')) + }, + 'IndexerOutput': { + ioType:IOType.report, + abiTypes:[], + params:['data'], + decoder: decodeToIndexerOutput, + validator: ajv.compile(JSON.parse('{"title": "IndexerOutput", "type": "object", "properties": {"data": {"type": "array", "items": {"$ref": "#/definitions/OutputIndex"}}}, "required": ["data"], "definitions": {"OutputIndex": {"title": "OutputIndex", "type": "object", "properties": {"output_type": {"type": "string"}, "module": {"type": "string"}, "class_name": {"type": "string"}, "input_index": {"type": "integer"}, "output_index": {"type": "integer"}}, "required": ["output_type", "module", "class_name", "input_index", "output_index"]}}}')) + }, + }; \ No newline at end of file diff --git a/frontend/app/cartridges/page.tsx b/frontend/app/cartridges/page.tsx index 3f6cb54..32056ac 100644 --- a/frontend/app/cartridges/page.tsx +++ b/frontend/app/cartridges/page.tsx @@ -29,21 +29,11 @@ export default async function Cartridges() { return (
-
- {/*
- - </div> */} + <Suspense fallback={listLoaderFallback()}> + <CartridgesList /> + </Suspense> - <div className="p-4 break-words overflow-auto custom-scrollbar"> - <Suspense fallback={listLoaderFallback()}> - <CartridgesList /> - </Suspense> - </div> - </div> - - <div className="basis-3/5 rounded-md h-full ms-auto"> - <CartridgeInfo /> - </div> + <CartridgeInfo /> </section> diff --git a/frontend/app/cartridges/selectedCartridgeProvider.tsx b/frontend/app/cartridges/selectedCartridgeProvider.tsx index f856fc3..99739d3 100644 --- a/frontend/app/cartridges/selectedCartridgeProvider.tsx +++ b/frontend/app/cartridges/selectedCartridgeProvider.tsx @@ -6,12 +6,12 @@ import { CartridgeInfo as Cartridge } from "../backend-libs/app/ifaces" export const selectedCartridgeContext = createContext<{ - selectedCartridge: PlayableCartridge|null, changeCartridge:Function, playCartridge:Function, - setReplay:Function, setCartridgeData:Function, setGameParameters:Function, - setGameplay:Function, stopCartridge:Function -}>({selectedCartridge: null, changeCartridge: () => null, playCartridge: () => null, - setReplay: () => null, setCartridgeData: () => null, setGameParameters: () => null, - setGameplay: () => null, stopCartridge: () => null}); + selectedCartridge: PlayableCartridge|null, changeCartridge:Function, playCartridge:Function, + setReplay:Function, setCartridgeData:Function, setGameParameters:Function, + setGameplay:Function, stopCartridge:Function, setDownloadingCartridge:Function +}>({selectedCartridge: null, changeCartridge: () => null, playCartridge: () => null, + setReplay: () => null, setCartridgeData: () => null, setGameParameters: () => null, + setGameplay: () => null, stopCartridge: () => null, setDownloadingCartridge: () => null}); // export type Cartridge = { // id: number, @@ -23,6 +23,7 @@ export const selectedCartridgeContext = createContext<{ export interface PlayableCartridge extends Cartridge { initCanvas: boolean; play: boolean; + downloading: boolean; playToggle: boolean; cartridgeData: Uint8Array | undefined; inCard: Uint8Array | undefined; @@ -38,12 +39,14 @@ export function SelectedCartridgeProvider({ children }:{ children: React.ReactNo const [selectedCartridge, setSelectedCartridge] = useState<PlayableCartridge|null>(null); const changeCartridge = (cartridge:Cartridge) => { - const aux = {...cartridge, play:false, cartridgeData:undefined, inCard:undefined, - args:undefined, scoreFunction:undefined, replay:undefined, gameplayLog:undefined, + if (selectedCartridge?.downloading) return; // change only if download already finished + + const aux = {...cartridge, play:false, downloading:false, cartridgeData:undefined, inCard:undefined, + args:undefined, scoreFunction:undefined, replay:undefined, gameplayLog:undefined, outcard:undefined, outhash:undefined, initCanvas:selectedCartridge?.initCanvas}; setSelectedCartridge(aux as PlayableCartridge); } - + const playCartridge = () => { if (selectedCartridge) { setSelectedCartridge({...selectedCartridge, play:true, gameplayLog:undefined, outcard:undefined, outhash:undefined, replay:undefined, playToggle:!selectedCartridge.playToggle, initCanvas:true}); @@ -52,10 +55,17 @@ export function SelectedCartridgeProvider({ children }:{ children: React.ReactNo const stopCartridge = () => { if (selectedCartridge) { - setSelectedCartridge({...selectedCartridge, play:false}); + setSelectedCartridge({...selectedCartridge, play:false, initCanvas:false}); } } + const setDownloadingCartridge = (download:boolean) => { + if (selectedCartridge) { + setSelectedCartridge({...selectedCartridge, downloading:download}); + } + + } + const setReplay = (replay: Uint8Array) => { if (selectedCartridge) { setSelectedCartridge({...selectedCartridge, play:true, gameplayLog:undefined, outcard:undefined, outhash:undefined, replay, playToggle:!selectedCartridge.playToggle, initCanvas:true}); @@ -64,7 +74,7 @@ export function SelectedCartridgeProvider({ children }:{ children: React.ReactNo const setCartridgeData = (cartridgeData: Uint8Array) => { if (selectedCartridge) { - setSelectedCartridge({...selectedCartridge, cartridgeData}); + setSelectedCartridge({...selectedCartridge, downloading:false, cartridgeData}); } } @@ -73,7 +83,7 @@ export function SelectedCartridgeProvider({ children }:{ children: React.ReactNo setSelectedCartridge({...selectedCartridge, args, inCard, scoreFunction, gameplayLog:undefined, replay:undefined}); } } - + const setGameplay = (gameplayLog: Uint8Array, outcard: Uint8Array, outhash: string) => { if (selectedCartridge) { if (outcard == undefined) @@ -85,11 +95,11 @@ export function SelectedCartridgeProvider({ children }:{ children: React.ReactNo setSelectedCartridge({...selectedCartridge, gameplayLog, outcard, outhash}); } } - + return ( - <selectedCartridgeContext.Provider value={ {selectedCartridge, changeCartridge, playCartridge, - setReplay, setCartridgeData, setGameParameters, - setGameplay, stopCartridge} }> + <selectedCartridgeContext.Provider value={ {selectedCartridge, changeCartridge, playCartridge, + setReplay, setCartridgeData, setGameParameters, + setGameplay, stopCartridge, setDownloadingCartridge} }> { children } </selectedCartridgeContext.Provider> ); diff --git a/frontend/app/components/CartridgeDescription.tsx b/frontend/app/components/CartridgeDescription.tsx index 64b551f..d0554dc 100644 --- a/frontend/app/components/CartridgeDescription.tsx +++ b/frontend/app/components/CartridgeDescription.tsx @@ -13,18 +13,14 @@ function CartridgeDescription() { } return ( - <div> - <fieldset> - <legend className={`font-bold text-xl ${fontPressStart2P.className}`}>Sumary</legend> - <p>{selectedCartridge.info?.summary}</p> - </fieldset> + <div className='p-4 text-xs max-h-96 overflow-auto custom-scrollbar'> + <h2 className='text-lg'>Summary</h2> + <span>{selectedCartridge.info?.summary}</span> - <fieldset> - <legend className={`font-bold text-xl ${fontPressStart2P.className}`}>Description</legend> - <pre style={{whiteSpace: "pre-wrap"}}> - {selectedCartridge.info?.description} - </pre> - </fieldset> + <h2 className='text-lg mt-4'>Description</h2> + <pre className={fontPressStart2P.className} style={{whiteSpace: "pre-wrap"}}> + {selectedCartridge.info?.description} + </pre> </div> ) } diff --git a/frontend/app/components/CartridgeInfo.tsx b/frontend/app/components/CartridgeInfo.tsx index 1f69347..cb6dc9d 100644 --- a/frontend/app/components/CartridgeInfo.tsx +++ b/frontend/app/components/CartridgeInfo.tsx @@ -1,6 +1,6 @@ "use client" -import { ethers } from "ethers"; +import { ContractReceipt, ethers } from "ethers"; import React, { Suspense, useContext, useEffect, useRef, useState } from 'react' import { selectedCartridgeContext } from '../cartridges/selectedCartridgeProvider'; import PowerSettingsNewIcon from '@mui/icons-material/PowerSettingsNew'; @@ -16,6 +16,7 @@ import StadiumIcon from '@mui/icons-material/Stadium'; import CodeIcon from '@mui/icons-material/Code'; import useDownloader from "react-use-downloader"; import { useConnectWallet } from "@web3-onboard/react"; +import QRCode from "react-qr-code"; import Cartridge from "../models/cartridge"; import {SciFiPedestal} from "../models/scifi_pedestal"; @@ -26,52 +27,40 @@ import CartridgeDescription from './CartridgeDescription'; import Link from 'next/link'; import CartridgeScoreboard from './CartridgeScoreboard'; import { envClient } from "../utils/clientEnv"; -import { fontPressStart2P } from '../utils/font'; import { delay } from "../utils/util"; -import CheckIcon from "./svg/CheckIcon"; -import ErrorIcon from "./svg/ErrorIcon"; -import CloseIcon from "./svg/CloseIcon"; +import ErrorIcon from '@mui/icons-material/Error'; +import CloseIcon from "@mui/icons-material/Close"; +import { sha256 } from "js-sha256"; +import nftAbiFile from "../contracts/RivesScoreNFT.sol/RivesScoreNFT.json" +const nftAbi: any = nftAbiFile; enum STATUS { - READY, - VALIDATING, - VALID, - INVALID, + WAITING, + SUBMIT, + SUBMITING, + SIGN, + FINISHED } interface LOG_STATUS { - cartridgeId:string, status:STATUS, error?:string } function logFeedback(logStatus:LOG_STATUS, setLogStatus:Function) { - if (logStatus.status === STATUS.VALID) { - delay(2500).then(() =>{ - setLogStatus({status: STATUS.READY} as LOG_STATUS); - }) - return ( - <div className="fixed flex items-center max-w-xs p-4 space-x-4 text-gray-500 bg-white rounded-lg shadow-lg right-5 bottom-20 dark:text-gray-400 dark:divide-gray-700 space-x dark:bg-gray-800" role="alert"> - <CheckIcon/> - <div className="ms-3 text-sm font-bold">Log Validated</div> - </div> - ) - } else if (logStatus.status === STATUS.INVALID) { - const click = () => { - setLogStatus({status: STATUS.READY} as LOG_STATUS) - } + if (logStatus.error) { + // delay(5000).then(() =>{ + // setLogStatus({status: logStatus.status}); + // }) + return ( - <div className="fixed flex-col items-center max-w-xs p-4 space-x-4 text-gray-500 bg-white rounded-lg shadow right-5 bottom-[20%] dark:text-gray-400 dark:divide-gray-700 space-x dark:bg-gray-800" role="alert"> - <div className="flex items-center pb-1 border-b"> + <div className="fixed text-[10px] flex-col items-center max-w-xs p-4 bg-gray-400 shadow right-5 bottom-5 z-40" role="alert"> + <div className="flex items-end p-1 border-b text-red-500"> <ErrorIcon/> - <div className="ms-3 text-sm font-normal">Invalid Log.</div> - <button onClick={click} type="button" className="ms-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex items-center justify-center h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700" data-dismiss-target="#toast-danger" aria-label="Close"> - <span className="sr-only">Close</span> - <CloseIcon/> - </button> + <div className="ms-2 text-sm font-normal">Error</div> </div> - <div> + <div className="p-1 break-words"> {logStatus.error} </div> </div> @@ -84,19 +73,22 @@ function scoreboardFallback() { const arr = Array.from(Array(3).keys()); return ( - <table className="w-full text-sm text-left"> + <table className="w-full text-xs text-left"> <thead className="text-xsuppercase"> <tr> - <th scope="col" className="px-6 py-3"> + <th scope="col" className="px-2 py-3"> User </th> - <th scope="col" className="px-6 py-3"> + <th scope="col" className="px-2 py-3"> Timestamp </th> - <th scope="col" className="px-6 py-3"> + <th scope="col" className="px-2 py-3"> Score </th> - <th scope="col" className="px-6 py-3"> + <th scope="col" className="px-2 py-3"> + Status + </th> + <th scope="col" className="px-2 py-3"> </th> </tr> @@ -105,25 +97,30 @@ function scoreboardFallback() { { arr.map((num, index) => { return ( - <tr key={index} className='mb-3 h-16'> - <td className="px-6 py-4 break-all"> - <div className='fallback-bg-color rounded-md'> - 0xf39f...2266 + <tr key={index}> + <td className="px-2 py-4 break-all"> + <div className='ps-4 fallback-bg-color rounded-md'> + 0xf39F...2266 </div> </td> - <td className="px-6 py-4"> + <td className="px-2 py-4"> <div className='fallback-bg-color rounded-md'> - 31/12/1969, 21:06:36 + 31/12/1969, 21:06:36 PM </div> </td> - <td className="px-6 py-4"> + <td className="px-2 py-4"> + <div className='fallback-bg-color rounded-md'> + 100 + </div> + </td> + <td className="px-2 py-4"> <div className='fallback-bg-color rounded-md'> 100 </div> </td> - <td className="px-6"> + <td className="w-[50px] h-[56px]"> <div className='fallback-bg-color rounded-md'> 100 </div> @@ -141,18 +138,46 @@ function scoreboardFallback() { function CartridgeInfo() { const {selectedCartridge, playCartridge, setGameplay, setReplay} = useContext(selectedCartridgeContext); const fileRef = useRef<HTMLInputElement | null>(null); - const [{ wallet }] = useConnectWallet(); + const [{ wallet }, connect] = useConnectWallet(); const { download } = useDownloader(); - const [submitLogStatus, setSubmitLogStatus] = useState({status: STATUS.READY} as LOG_STATUS); + const [submitLogStatus, setSubmitLogStatus] = useState({status: STATUS.WAITING} as LOG_STATUS); const [reloadScoreboardCount, setReloadScoreboardCount] = useState(0); + const [mintUrl, setMintUrl] = useState("/mint/1"); + const [userAlias, setUserAlias] = useState(''); + const [bypassSubmitModal, setBypassSubmitModal] = useState(false); + const [operator,setOperator] = useState<String>(); + const [signerAddress,setSignerAddress] = useState<String>(); + + // useEffect(() => { + // // auto reload scoreboard only if + // // gameplay log sent is valid and the selected cartridge is the same of the gameplay sent + // if (submitLogStatus.status === STATUS.VALID && submitLogStatus.cartridgeId === selectedCartridge?.id) { + // setReloadScoreboardCount(reloadScoreboardCount+1); + // } + // }, [submitLogStatus]) + + useEffect(() => { + + console.log("gameplayLog",selectedCartridge?.gameplayLog?.length); + if (selectedCartridge?.gameplayLog) submitLog(); + }, [selectedCartridge?.gameplayLog]) + useEffect(() => { - // auto reload scoreboard only if - // gameplay log sent is valid and the selected cartridge is the same of the gameplay sent - if (submitLogStatus.status === STATUS.VALID && submitLogStatus.cartridgeId === selectedCartridge?.id) { - setReloadScoreboardCount(reloadScoreboardCount+1); + if (!wallet) { + return; } - }, [submitLogStatus]) + const curSigner = new ethers.providers.Web3Provider(wallet.provider, 'any').getSigner(); + const curContract = new ethers.Contract(envClient.NFT_ADDR,nftAbi.abi,curSigner); + curContract.provider.getCode(curContract.address).then((code) => { + if (code == '0x') { + console.log("Couldn't get nft contract") + return; + } + curSigner.getAddress().then((a: String) => setSignerAddress(a.toLowerCase())); + curContract.operator().then((o: String) => setOperator(o.toLowerCase())); + }); + },[wallet]); if (!selectedCartridge) return <></>; @@ -169,12 +194,32 @@ function CartridgeInfo() { return; } if (!wallet) { - alert("Connect first to upload a gameplay log."); - return; + await alert("Connect first to upload a gameplay log."); + await connect(); } + if (bypassSubmitModal) + submitLogWithAlias(userAlias); + else + setSubmitLogStatus({status: STATUS.SUBMIT}); + //setShowSubmitModal(true); + } + + async function submitLogWithAlias(userAliasToSubmit:string = "") { + // replay({car}); + if (!selectedCartridge || !selectedCartridge.gameplayLog){ + return; + } + if (!selectedCartridge.outcard || !selectedCartridge.outhash ){ + return; + } + if (!wallet) { + return; + } + setUserAlias(userAliasToSubmit); const signer = new ethers.providers.Web3Provider(wallet.provider, 'any').getSigner(); const inputData: Replay = { + user_alias:userAliasToSubmit, cartridge_id:"0x"+selectedCartridge.id, outcard_hash: '0x' + selectedCartridge.outhash, args: selectedCartridge.args || "", @@ -189,12 +234,39 @@ function CartridgeInfo() { } console.log("Replay Outcard hash",selectedCartridge.outhash) - setSubmitLogStatus({cartridgeId: selectedCartridge.id, status: STATUS.VALIDATING}); + + // setSubmitLogStatus({status: STATUS.SUBMIT}); try { - await replay(signer, envClient.DAPP_ADDR, inputData, {cartesiNodeUrl: envClient.CARTESI_NODE_URL}); - setSubmitLogStatus({cartridgeId: selectedCartridge.id, status: STATUS.VALID}); + setSubmitLogStatus({status: STATUS.SUBMITING}); + const receipt = await replay(signer, envClient.DAPP_ADDR, inputData, {sync:false, cartesiNodeUrl: envClient.CARTESI_NODE_URL}) as ContractReceipt; + + if (receipt == undefined || receipt.events == undefined) + throw new Error("Couldn't send transaction"); + + const inputEvent = receipt.events[0]; + const inputIndex = inputEvent.args && inputEvent.args[1]; + if (inputIndex == undefined) + throw new Error("Couldn't get input index"); + + let signature = ""; + const nftContract = new ethers.Contract(envClient.NFT_ADDR,nftAbi.abi,signer); + + const code = await nftContract.provider.getCode(nftContract.address); + if (code == '0x') { + setSubmitLogStatus({status: STATUS.WAITING, error: "Couldn't get nft contract"}); + } else if ((await signer.getAddress()).toLowerCase() == (await nftContract.operator()).toLowerCase()) { + const gameplayHash = sha256(selectedCartridge.gameplayLog); + setSubmitLogStatus({status: STATUS.SIGN}); + const signedHash = await signer.signMessage(ethers.utils.arrayify("0x"+gameplayHash)); + signature = `?signature=${signedHash}`; + } + + setMintUrl(`/mint/${Number(inputIndex._hex)}${signature}`) + // setShowNftLinkModal(true); + setSubmitLogStatus({status: STATUS.FINISHED}); + } catch (error) { - setSubmitLogStatus({cartridgeId: selectedCartridge.id, status: STATUS.INVALID, error: (error as Error).message}); + setSubmitLogStatus({...submitLogStatus, error: (error as Error).message}); } } @@ -243,190 +315,294 @@ function CartridgeInfo() { } } } - return ( - <fieldset className='h-full custom-shadow'> - <legend className="ms-2 px-1"> - <span className={`cartridge-title-text ${fontPressStart2P.className}`}>{selectedCartridge.name}</span> - <br/> - <span className='muted-text'> - Uploaded by {selectedCartridge.user_address} on {new Date(selectedCartridge.created_at*1000).toLocaleString()} - </span> - </legend> - <div className="flex flex-row h-full"> - <div className="basis-1/4 h-1/2"> - <Canvas shadows camera={ {near: 0.1, far: 1000, position: [0,0,0]} }> - - <Suspense fallback={<Loader />}> - <ambientLight intensity={1} /> - <pointLight position={[4, -5, -10]} intensity={20} /> - <pointLight position={[-4, -5, -10]} intensity={20} /> - <spotLight - position={[0, -5, -10]} - angle={Math.PI} - penumbra={1} - intensity={80} - /> - <hemisphereLight - color='#b1e1ff' - groundColor='#000000' - intensity={1} - /> - - <Cartridge - rotation={[0, -Math.PI/2, 0]} - key={selectedCartridge.cover} - position={[0,0,-10]} - cover={selectedCartridge.cover? `data:image/png;base64,${selectedCartridge.cover}`:"/cartesi.jpg"} - scale={[1, 1, 1]} - /> - <SciFiPedestal position={[0, -5, -10]} scale={[0.3,0.3,0.3]}/> - - </Suspense> - - </Canvas> - <input type="file" ref={fileRef} onChange={(e) => handleOnChange(e)} style={{ display: 'none' }}/> - <div className="flex flex-wrap place-content-evenly"> - <button className="button-57" onClick={() => {playCartridge()}}> - <span><PowerSettingsNewIcon/></span> - <span>Turn on</span> - </button> - <button className={"button-57"} onClick={() => {submitLog()}} - disabled={!selectedCartridge.gameplayLog == undefined || selectedCartridge?.outcard == undefined || selectedCartridge?.outhash == undefined || !wallet || submitLogStatus.status != STATUS.READY}> - - { - submitLogStatus.status === STATUS.READY || submitLogStatus.cartridgeId !== selectedCartridge.id? - <> - <span><PublishIcon/></span> - <span>Submit Log</span> - </> - : - <> - <span> - <div className='w-5 h-5 border-2 rounded-full border-current animate-spin'> - </div> - </span> - - <span> - Validating - </span> - </> - } - </button> - <button className="button-57" onClick={() => {uploadLog()}}> - <span><UploadIcon/></span> - <span>Upload Log</span> - </button> + function submissionHandler() { + const isOperator = operator == signerAddress; + if (submitLogStatus.status === STATUS.WAITING) return <></>; + + let modalBody; + switch (submitLogStatus.status) { + case STATUS.SUBMIT: + modalBody = <SubmitModal cancelFunction={setSubmitLogStatus} acceptFunction={submitLogWithAlias} bypassModal={setBypassSubmitModal} />; + break; + case STATUS.SUBMITING: + if (submitLogStatus.error) { + setSubmitLogStatus({status: STATUS.SUBMIT}); // goes back to the submission form + } else { + modalBody = <div className="p-6 flex justify-center"><div className='w-12 h-12 border-2 rounded-full border-current border-r-transparent animate-spin'></div></div>; + } - <button className={"button-57"} onClick={() => {downloadLog()}} disabled={!selectedCartridge.gameplayLog}> - <span><DownloadIcon/></span> - <span>Download Gameplay</span> - </button> + break; + case STATUS.SIGN: + modalBody = <div className="p-6 flex justify-center"><div className='w-12 h-12 border-2 rounded-full border-current border-r-transparent animate-spin'></div></div>; + break; + + case STATUS.FINISHED: + modalBody = <NftLinkModal url={mintUrl} />; + break; + } + + return ( + <div + className="justify-center items-center flex overflow-x-hidden overflow-y-auto fixed inset-0 z-30 outline-none focus:outline-none" + > + <div className="relative w-max my-6 mx-auto"> + {/*content*/} + <div className="border-0 shadow-lg relative flex flex-col w-full bg-gray-500 outline-none focus:outline-none p-4"> + {/*header*/} + <div className='relative p-2 text-center mb-6'> + {/* <span>Submiting Gameplay</span> */} + <button className="absolute top-0 end-0 p-1 border border-gray-500 hover:border-black" + onClick={() => setSubmitLogStatus({status: STATUS.WAITING})} + > + <CloseIcon/> + </button> + </div> + <div className="flex space-x-8 justify-center items-end"> + <div className={`flex flex-col items-center p-2 ${submitLogStatus.status < STATUS.SIGN? "bg-black text-white":""}`}> + <span className="text-lg">1</span> + <span>Submit</span> + </div> + {isOperator ? <div className={`flex flex-col items-center p-2 ${submitLogStatus.status == STATUS.SIGN? "bg-black text-white":""}`}> + <span className="text-lg">2</span> + <span>Sign</span> + </div> : <></>} + <div className={`flex flex-col items-center p-2 ${submitLogStatus.status > STATUS.SIGN? "bg-black text-white":""}`}> + <span className="text-lg">{isOperator ? 3 : 2 }</span> + <span>Check NFT</span> + </div> + + </div> + {/*body*/} + { modalBody } </div> + </div> + </div> + ) + } - { - !(selectedCartridge.info?.authors)? - <></> - : - <div className='mt-3'> - <span className={`ms-2 font-bold text-xl ${fontPressStart2P.className}`}> - Creators - </span> + return ( + <div className="flex flex-wrap justify-center h-full w-full"> + <div className="w-64 h-96"> + <Canvas shadows camera={ {near: 0.1, far: 1000, position: [0,0,0]} }> + <Suspense fallback={<Loader />}> + <ambientLight intensity={1} /> + <pointLight position={[4, -5, -10]} intensity={20} /> + <pointLight position={[-4, -5, -10]} intensity={20} /> + <spotLight + position={[0, -5, -10]} + angle={Math.PI} + penumbra={1} + intensity={80} + /> + <hemisphereLight + color='#b1e1ff' + groundColor='#000000' + intensity={1} + /> + + <Cartridge + rotation={[0, -Math.PI/2, 0]} + key={selectedCartridge.cover} + position={[0,0,-10]} + cover={selectedCartridge.cover? `data:image/png;base64,${selectedCartridge.cover}`:"/logo.png"} + scale={[1, 1, 1]} + /> + <SciFiPedestal position={[0, -5, -10]} scale={[0.3,0.3,0.3]}/> + + </Suspense> + </Canvas> + </div> - <ul className='flex flex-col space-y-1'> - {selectedCartridge.info?.authors?.map((author) => ( - <li key={author.name}><Link className='ms-8 font-semibold link-2step-hover' href={author.link}>{author.name}</Link></li> - ))} - </ul> + <div className="md:w-[512px] lg:w-[768px]"> + <div className="text-white mb-2"> + <span className='text-4xl'>{selectedCartridge.name}</span> - </div> + { + !(selectedCartridge.info?.authors)? + <div className='h-6'></div> + : + ( + <div className='flex space-x-2'> + <span>By</span> + <ul> + {selectedCartridge.info?.authors?.map((author, index) => ( + <li key={author.name}> + <Link href={author.link}> + {author.name}{index !== selectedCartridge.info!.authors!.length-1? ",": ""} + </Link> + </li> + ))} + </ul> + + </div> + ) } - </div> - <div className="basis-3/4 flex flex-col py-2 max-h-full"> - <Tab.Group> - <Tab.List className="game-option-tabs-header"> - <Tab - className={({selected}) => {return selected?"game-tabs-option-selected":"game-tabs-option-unselected"}} - > - <span className='game-tabs-option-text'> - <DescriptionIcon/> - <span>Description</span> - </span> - </Tab> - - <Tab - className={({selected}) => {return selected?"game-tabs-option-selected":"game-tabs-option-unselected"}} - > - <span className='game-tabs-option-text'> - <LeaderboardIcon/> - <span>Scoreboards</span> - </span> - </Tab> - - <Tab - className={({selected}) => {return selected?"game-tabs-option-selected":"game-tabs-option-unselected"}} - > - <span className='game-tabs-option-text'> - <StadiumIcon/> - <span>Tournaments</span> - </span> - </Tab> - - <Tab - className={({selected}) => {return selected?"game-tabs-option-selected":"game-tabs-option-unselected"}} - > - <span className='game-tabs-option-text'> - <CodeIcon/> - <span>Mods</span> - </span> - </Tab> - </Tab.List> - - <Tab.Panels className="mt-2 pr-1 overflow-auto custom-scrollbar"> - <Tab.Panel - className="game-tab-content" + <Tab.Group> + <Tab.List className="game-option-tabs-header"> + <Tab + className={({selected}) => {return selected?"game-tabs-option-selected":"game-tabs-option-unselected"}} > - <CartridgeDescription/> - </Tab.Panel> + <span className='game-tabs-option-text'> + <DescriptionIcon/> + <span>Description</span> + </span> + </Tab> - <Tab.Panel - className="game-tab-content" + <Tab + className={({selected}) => {return selected?"game-tabs-option-selected":"game-tabs-option-unselected"}} > - <div className="w-full flex"> - <button className="ms-auto scoreboard-btn" onClick={() => setReloadScoreboardCount(reloadScoreboardCount+1)}><span><CachedIcon/></span></button> - </div> - <Suspense fallback={scoreboardFallback()}> - <CartridgeScoreboard cartridge_id={selectedCartridge.id} reload={reloadScoreboardCount} replay_function={prepareReplay}/> - </Suspense> - - </Tab.Panel> + <span className='game-tabs-option-text'> + <LeaderboardIcon/> + <span>Scoreboard</span> + </span> + </Tab> - <Tab.Panel - className="game-tab-content" + {/* <Tab + className={({selected}) => {return selected?"game-tabs-option-selected":"game-tabs-option-unselected"}} > - <span className={`${fontPressStart2P.className}`}>Coming Soon!</span> - </Tab.Panel> + <span className='game-tabs-option-text'> + <StadiumIcon/> + <span>Tournaments</span> + </span> + </Tab> - <Tab.Panel - className="game-tab-content" + <Tab + className={({selected}) => {return selected?"game-tabs-option-selected":"game-tabs-option-unselected"}} > - <span className={`${fontPressStart2P.className}`}>Coming Soon!</span> - </Tab.Panel> - </Tab.Panels> - </Tab.Group> - </div> + <span className='game-tabs-option-text'> + <CodeIcon/> + <span>Mods</span> + </span> + </Tab> */} + </Tab.List> + + <Tab.Panels className="mt-2 overflow-auto custom-scrollbar"> + <Tab.Panel className="game-tab-content "> + <CartridgeDescription/> + </Tab.Panel> + + {/* lg: width is equal to the max-w-3xl */} + <Tab.Panel className="game-tab-content"> + <div className="w-full flex"> + <button className="ms-auto scoreboard-btn" onClick={() => setReloadScoreboardCount(reloadScoreboardCount+1)}><span><CachedIcon/></span></button> + </div> + <Suspense fallback={scoreboardFallback()}> + <CartridgeScoreboard cartridge_id={selectedCartridge.id} reload={reloadScoreboardCount} replay_function={prepareReplay}/> + </Suspense> + + </Tab.Panel> + + {/* <Tab.Panel className="game-tab-content"> + Coming Soon! + </Tab.Panel> + + <Tab.Panel className="game-tab-content"> + Coming Soon! + </Tab.Panel> */} + </Tab.Panels> + </Tab.Group> + + {/* <div> + <CartridgeDescription/> + </div> */} + + { + selectedCartridge.downloading? + <button className="btn w-full mt-2 flex justify-center"> + <div className='w-5 h-5 border-2 rounded-full border-current border-r-transparent animate-spin'></div> + </button> + : + <button className="btn w-full mt-2" onClick={() => {playCartridge()}}> + PLAY + </button> + + } </div> + { + submissionHandler() + } + + { + submitLogStatus.status !== STATUS.WAITING? + <div className="opacity-25 fixed inset-0 z-20 bg-black"></div> + : + <></> + } + { logFeedback(submitLogStatus, setSubmitLogStatus) } - </fieldset> - ) + </div> + ); } + +function NftLinkModal({url}:{url:String}) { + return ( + <div> + {/*body*/} + <div className="relative p-4 flex justify-center items-center"> + <button className="place-self-center" title='Nft Score Screenshot' onClick={() => window.open(`${url}`, "_blank", "noopener,noreferrer")}> + <div style={{ height: "auto", margin: "0 auto", maxWidth: 200, width: "100%" }} > + <QRCode + size={200} + style={{ height: "auto", maxWidth: "100%", width: "100%" }} + value={`${window.location.origin}${url}`} + viewBox={`0 0 200 200`} + /> + </div> + </button> + </div> + </div> + ); + } + +function SubmitModal({cancelFunction,acceptFunction,bypassModal}:{cancelFunction(s:{ status: STATUS }):void,acceptFunction(s:string):void,bypassModal(s:boolean):void}) { + const [alias, setAlias] = useState(''); + const [bypass, setBypass] = useState(false); + + return ( + <div> + {/*body*/} + <fieldset className={`relative my-6 px-6 flex-auto h-full`}> + <div > + <legend> + user alias + </legend> + <input type="text" maxLength={12} value={alias} onChange={e => setAlias(e.target.value.slice(0, 12))} /> + </div> + <div className="mt-2"> + <input id="bypass-checkbox" type="checkbox" checked={bypass} onChange={e => setBypass(e.target.checked)} > + </input> + <label htmlFor="bypass-checkbox" className="ms-2"> + remember my alias + </label> + </div> + </fieldset> + <div className="flex items-center justify-end pb-2 pr-6"> + <button + className={`bg-red-500 text-white font-bold uppercase text-sm px-6 py-2 border border-red-500 hover:text-red-500 hover:bg-transparent`} + type="button" + onClick={() => cancelFunction({status:STATUS.WAITING})} + > + Cancel + </button> + <button + className={`bg-emerald-500 text-white font-bold uppercase text-sm px-6 py-2 ml-1 border border-emerald-500 hover:text-emerald-500 hover:bg-transparent`} + type="button" + onClick={() => {acceptFunction(alias);bypassModal(bypass);}} + > + Submit + </button> + </div> + </div> + ); + } export default CartridgeInfo \ No newline at end of file diff --git a/frontend/app/components/CartridgeScoreboard.tsx b/frontend/app/components/CartridgeScoreboard.tsx index 15ad325..92357a3 100644 --- a/frontend/app/components/CartridgeScoreboard.tsx +++ b/frontend/app/components/CartridgeScoreboard.tsx @@ -1,6 +1,9 @@ import { getOutputs, ReplayScore } from '../backend-libs/app/lib'; import MilitaryTechIcon from '@mui/icons-material/MilitaryTech'; import OndemandVideoIcon from '@mui/icons-material/OndemandVideo'; +import CheckIcon from '@mui/icons-material/Check'; +import DoneAllIcon from '@mui/icons-material/DoneAll'; +import ImageIcon from '@mui/icons-material/Image'; import { envClient } from '../utils/clientEnv'; import React from 'react'; @@ -40,19 +43,22 @@ async function CartridgeScoreboard({cartridge_id, reload, replay_function}:{ return ( <div className="relative"> - <table className="w-full text-sm text-left"> + <table className="w-full text-xs text-left"> <thead className="text-xsuppercase"> <tr> - <th scope="col" className="px-6 py-3"> + <th scope="col" className="px-2 py-3"> User </th> - <th scope="col" className="px-6 py-3"> + <th scope="col" className="px-2 py-3"> Timestamp </th> - <th scope="col" className="px-6 py-3"> + <th scope="col" className="px-2 py-3"> Score </th> - <th scope="col" className="px-6 py-3"> + <th scope="col" className="px-2 py-3"> + Status + </th> + <th scope="col" className="px-2 py-3"> </th> </tr> @@ -62,17 +68,26 @@ async function CartridgeScoreboard({cartridge_id, reload, replay_function}:{ generalScores.map((scoreInfo, index) => { return ( <tr key={`${scoreInfo.user_address}-${scoreInfo.timestamp}`} className=""> - <td scope="row" className="px-6 py-4 break-all"> - {setMedal(index)} {scoreInfo.user_address.substring(0,6)}...{scoreInfo.user_address.substring(scoreInfo.user_address.length-4,scoreInfo.user_address.length)} + <td title={scoreInfo.user_address.toLowerCase()} scope="row" className="px-2 py-4 break-all"> + {setMedal(index)} {scoreInfo.user_alias? scoreInfo.user_alias:scoreInfo.user_address.substring(0,6)+"..."+scoreInfo.user_address.substring(scoreInfo.user_address.length-4,scoreInfo.user_address.length)} </td> - <td className="px-6 py-4"> + <td className="px-2 py-4"> {new Date(Number(scoreInfo.timestamp)*1000).toLocaleString()} </td> - <td className="px-6 py-4"> + <td className="px-2 py-4"> {scoreInfo.score.toLocaleString()} </td> + <td className="px-2 py-4"> + { + !scoreInfo._proof? + <span title='Validated inside Cartesi Machine'><CheckIcon/></span> + : + <span title='Settled on-chain'><DoneAllIcon/></span> + } + </td> <td className="py-4"> - <button className='scoreboard-btn' onClick={() => playReplay(scoreInfo)}><span><OndemandVideoIcon/></span></button> + <button title='Play Log' className='scoreboard-btn' onClick={() => playReplay(scoreInfo)}><span><OndemandVideoIcon/></span></button> + <button title='Mint Screenshot' className='scoreboard-btn' onClick={() => window.open(`/mint/${scoreInfo._inputIndex}`, "_blank", "noopener,noreferrer")}><span><ImageIcon/></span></button> </td> </tr> ); diff --git a/frontend/app/components/CartridgeSelectButton.tsx b/frontend/app/components/CartridgeSelectButton.tsx index e3e4a51..ed1bd18 100644 --- a/frontend/app/components/CartridgeSelectButton.tsx +++ b/frontend/app/components/CartridgeSelectButton.tsx @@ -4,7 +4,6 @@ import React, { useContext, useEffect } from 'react' import { selectedCartridgeContext } from '../cartridges/selectedCartridgeProvider'; import { CartridgeInfo as Cartridge } from "../backend-libs/app/ifaces" import { cartridgeInfo } from '../backend-libs/app/lib'; -import { fontPressStart2P } from '../utils/font'; import { envClient } from '../utils/clientEnv'; function CartridgeSelectButton({cartridge, index}:{cartridge:Cartridge, index:number}) { @@ -27,9 +26,9 @@ function CartridgeSelectButton({cartridge, index}:{cartridge:Cartridge, index:nu return ( <button className={ selectedCartridge?.id==cartridge.id? - `games-list-item games-list-selected-item ${fontPressStart2P.className}` + `games-list-item games-list-selected-item` : - `games-list-item ${fontPressStart2P.className}` + `games-list-item` } value={cartridge.id} onClick={handleCartridgeSelection}> {cartridge.name} diff --git a/frontend/app/components/CartridgesList.tsx b/frontend/app/components/CartridgesList.tsx index 3ee1a32..e2fa391 100644 --- a/frontend/app/components/CartridgesList.tsx +++ b/frontend/app/components/CartridgesList.tsx @@ -14,11 +14,11 @@ async function CartridgesList() { let cartridges = await getCartridges(); return ( - <ul> + <ul className='games-list'> { cartridges.map((cartridge: any, index: number) => { return ( - <li key={`${cartridge.name}-${index}`} className="flex"> + <li key={index}> <CartridgeSelectButton index={index} cartridge={cartridge} /> </li> ); diff --git a/frontend/app/components/Navbar.tsx b/frontend/app/components/Navbar.tsx index ff003ce..007ef99 100644 --- a/frontend/app/components/Navbar.tsx +++ b/frontend/app/components/Navbar.tsx @@ -3,10 +3,8 @@ import Link from 'next/link' import { usePathname } from "next/navigation"; import React, { useEffect, useState } from 'react' -import ThemeSwitch from "@/app/components/ThemeSwitch"; import { useConnectWallet, useSetChain } from '@web3-onboard/react'; -import rivesLogo from '../../public/rives_logo.png'; -import Image from 'next/image' +import RivesLogo from './svg/RivesLogo'; function Navbar() { const pathname = usePathname(); @@ -38,33 +36,24 @@ function Navbar() { return ( <header className='header'> - {/* <Link href={"/"} className={`font-semibold title-color ${fontPressStart2P.className}`}> - <span>RiVES</span> - </Link> */} - - <Link href={"/"}> - <Image src={rivesLogo} alt='RiVES' width={96} ></Image> + <Link href={"/"} className={`h-full grid grid-cols-1 items-center navbar-item ${pathname === "/" ? "link-active" : "" }`}> + <RivesLogo style={{width:100}}/> </Link> - <nav className='flex gap-7 font-medium'> - <a href={"/cartridges"} className={ pathname === "/cartridges" ? "link-active" : "link-2step-hover" }> - <p>Cartridges</p> - </a> - - <Link href={"/insert-cartridge"} className={ pathname === "/insert-cartridge" ? "link-active" : "link-2step-hover" }> - <p>Insert Cartridge</p> - </Link> - </nav> + <a href={"/cartridges"} className={`invisible md:visible h-full grid grid-cols-1 items-center navbar-item ${pathname === "/cartridges" ? "link-active" : "" }`}> + <p>Cartridges</p> + </a> - <div className='flex space-x-6'> - <ThemeSwitch/> + <Link href={"/insert-cartridge"} className={`invisible md:visible h-full grid grid-cols-1 items-center navbar-item ${pathname === "/insert-cartridge" ? "link-active" : "" }`}> + Insert Cartridge + </Link> - <button className='web3-connect-btn' disabled={connecting} + <div className='flex-1 flex justify-end'> + <button className='navbar-item' disabled={connecting} onClick={() => (wallet ? disconnect(wallet) : connect())} > {connectButtonTxt} </button> - </div> </header> ) diff --git a/frontend/app/components/Rivemu.tsx b/frontend/app/components/Rivemu.tsx index c16a317..97e06f4 100644 --- a/frontend/app/components/Rivemu.tsx +++ b/frontend/app/components/Rivemu.tsx @@ -1,125 +1,92 @@ "use client" -import React, { useContext, useState, useEffect, Suspense } from 'react' +import React, { useContext, useState, useEffect, cache } from 'react' import Script from "next/script"; import Image from 'next/image'; import {Parser} from 'expr-eval'; -import PlayArrowIcon from '@mui/icons-material/PlayArrow'; -import Stop from '@mui/icons-material/Stop'; -import ReplayIcon from '@mui/icons-material/Replay'; -import OndemandVideoIcon from '@mui/icons-material/OndemandVideo'; -import OpenInFullIcon from '@mui/icons-material/OpenInFull'; -import CloseFullscreenIcon from '@mui/icons-material/CloseFullscreen'; +import CloseIcon from '@mui/icons-material/Close'; import { selectedCartridgeContext } from '../cartridges/selectedCartridgeProvider'; import { cartridge } from '../backend-libs/app/lib'; -import { fontPressStart2P } from '../utils/font'; import { envClient } from '../utils/clientEnv'; -import { delay, usePrevious } from '../utils/util'; -// let rivlogData: Uint8Array | undefined = undefined; - -async function movePageToBottom() { - await delay(500); - window.scrollTo({left: 0, top: document.body.scrollHeight, behavior: 'smooth'}); -} - -async function movePageToTop() { - await delay(500); - window.scrollTo({left: 0, top: 0, behavior: 'smooth'}); -} - -function getWindowDimensions() { - const { innerWidth: width, innerHeight: height } = window; - return { width, height }; -} - -const DEFAULT_WIDTH = 640; -const DEFAULT_HEIGTH = 400; +const canvasMinHeight = 400; +const canvasMinWidth = 640; function Rivemu() { - const {selectedCartridge, setCartridgeData, setGameplay } = useContext(selectedCartridgeContext); + const {selectedCartridge, setCartridgeData, setGameplay, stopCartridge, setDownloadingCartridge } = useContext(selectedCartridgeContext); const [overallScore, setOverallScore] = useState(0); - // const [isLoading, setIsLoading] = useState(true); const [isPlaying, setIsPlaying] = useState(false); - const [replayTip, setReplayTip] = useState(false); + // const [replayTip, setReplayTip] = useState(false); const [isReplaying, setIsReplaying] = useState(false); - const [isExpanded, setIsExpanded] = useState(false); + const [cancelled, setCancelled] = useState(false); + // const [isExpanded, setIsExpanded] = useState(false); const [playedOnce, setPlayedOnce] = useState(false); - const [canvasHeight, setCanvasHeight] = useState(DEFAULT_HEIGTH); - const [descHeight, setDescHeight] = useState(100); - const [canvasWidth, setCanvasWidth] = useState(DEFAULT_WIDTH); const [replayLog, setReplayLog] = useState<Uint8Array|undefined>(undefined); - const [gameHeigth, setGameHeigth] = useState(0); + const [freshOpen, setFreshOpen] = useState(true); - useEffect(()=>{ + useEffect(() => { if (!selectedCartridge || !selectedCartridge?.play) return; initialize(); } - ,[selectedCartridge?.playToggle]) - - useEffect(()=>{ - let newHeight = DEFAULT_HEIGTH; - let newWidth = DEFAULT_WIDTH; - const canvas: any = document.getElementById("canvas"); - if (canvas) { - const aspectRatio = canvas ? canvas.width / canvas.height : 640/400; - if (isExpanded) { - const windowSizes = getWindowDimensions(); - newHeight = windowSizes.height - 120; - newWidth = Math.floor(aspectRatio * newHeight); - if (newWidth > windowSizes.width - 10) { - newWidth = windowSizes.height - 10; - newHeight = Math.floor(newWidth / aspectRatio); - } - } + ,[selectedCartridge?.playToggle, selectedCartridge?.replay]) - canvas.height = Math.floor(newHeight / gameHeigth) * gameHeigth; - canvas.width = Math.floor(aspectRatio * canvas.height); + useEffect(() => { + if (!isPlaying) { + rivemuReplay(); } - setCanvasHeight(newHeight); - setCanvasWidth(newWidth); - window.dispatchEvent(new Event("resize")); - movePageToBottom(); - } - ,[isExpanded]) + }, [replayLog]) + + useEffect(() => { + if (cancelled) { + setIsPlaying(false); + rivemuHalt(); + setOverallScore(0); + stopCartridge(); + } + }, [cancelled]) + + // useEffect(() => { + // interface keyboardEvent {key:string} + // const escPressed = (event: keyboardEvent) => { + // console.log(event, isPlaying); + // if (event.key === "Escape" && !isPlaying) { + // stopCartridge(); + // } + // } + + // document.addEventListener("keydown", escPressed); + + // }) async function initialize() { if (!selectedCartridge || selectedCartridge.cartridgeData == undefined) { - setGameHeigth(0); - setCanvasHeight(DEFAULT_HEIGTH); - setCanvasWidth(DEFAULT_WIDTH); setIsPlaying(false); - setIsExpanded(false); + // setIsExpanded(false); setOverallScore(0); setReplayLog(undefined); - const windowSizes = getWindowDimensions(); - setDescHeight(windowSizes.height - 150 - DEFAULT_HEIGTH); - const canvas: any = document.getElementById("canvas"); - if (canvas) { - canvas.height = DEFAULT_HEIGTH; - canvas.width = DEFAULT_HEIGTH; - } } await loadCartridge(); - movePageToBottom(); + setCancelled(false); + setFreshOpen(true); if (selectedCartridge?.replay){ setReplayLog(selectedCartridge.replay); setIsReplaying(true); - setReplayTip(true); + // setReplayTip(true); } if (selectedCartridge?.gameplayLog) { setReplayLog(selectedCartridge.gameplayLog); setIsReplaying(false); - setReplayTip(true); + // setReplayTip(true); } } async function loadCartridge() { if (!selectedCartridge || !selectedCartridge?.play || selectedCartridge.cartridgeData != undefined) return; + setDownloadingCartridge(true); const data = await cartridge({id:selectedCartridge.id},{decode:true,decodeModel:"bytes", cartesiNodeUrl: envClient.CARTESI_NODE_URL, cache:"force-cache"}); - setCartridgeData(data); + setCartridgeData(data); // setCartridgeData also sets downloading to false } if (!selectedCartridge || !selectedCartridge.initCanvas) { @@ -132,19 +99,20 @@ function Rivemu() { function coverFallback() { return ( - <Image alt={"Cover " + selectedCartridge?.name} - id="canvas-cover" className="cartridge-cover" - height={canvasHeight} width={canvasWidth} - src={selectedCartridge?.cover? `data:image/png;base64,${selectedCartridge.cover}`:"/cartesi.jpg"} - style={{ - maxHeight: canvasHeight, - maxWidth: canvasWidth, - objectFit:'contain' - }} - /> + <button className='relative h-full w-full' onClick={rivemuStart}> + {freshOpen ? <Image alt={"Cover " + selectedCartridge?.name} + id="canvas-cover" + layout='fill' + objectFit='contain' + src={selectedCartridge?.cover? `data:image/png;base64,${selectedCartridge.cover}`:"/logo.png"} + /> : <></>} + + <span className='absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-white'>Click to Play!</span> + + </button> ); } - + function waitEvent(name: string) { return new Promise((resolve) => { const listener = (e: any) => { @@ -160,7 +128,7 @@ function Rivemu() { console.log("rivemuStart"); // setIsLoading(true); setIsReplaying(false); - setReplayTip(false); + // setReplayTip(false); // // @ts-ignore:next-line // if (Module.quited) { // // restart wasm when back to page @@ -169,6 +137,7 @@ function Rivemu() { // } await rivemuHalt(); setIsPlaying(true); + setOverallScore(0); if (selectedCartridge.scoreFunction) scoreFunction = parser.parse(selectedCartridge.scoreFunction); @@ -176,11 +145,12 @@ function Rivemu() { let buf = Module._malloc(selectedCartridge.cartridgeData.length); // @ts-ignore:next-line Module.HEAPU8.set(selectedCartridge.cartridgeData, buf); + const inCard = selectedCartridge?.inCard || new Uint8Array([]); // @ts-ignore:next-line - let incardBuf = Module._malloc(selectedCartridge.inCard?.length || 0); + let incardBuf = Module._malloc(inCard.length); // @ts-ignore:next-line - if (selectedCartridge?.inCard) Module.HEAPU8.set(selectedCartridge.inCard, incardBuf); - let params = selectedCartridge?.args || ""; + Module.HEAPU8.set(inCard, incardBuf); + const params = selectedCartridge?.args || ""; // @ts-ignore:next-line Module.ccall( "rivemu_start_record", @@ -191,7 +161,7 @@ function Rivemu() { selectedCartridge.cartridgeData.length, incardBuf, selectedCartridge.inCard?.length || 0, - params + params || '' ] ); // @ts-ignore:next-line @@ -204,9 +174,11 @@ function Rivemu() { // TODO: fix rivemuReplay if (!selectedCartridge?.cartridgeData || !replayLog) return; console.log("rivemuReplay"); - setReplayTip(false); - if (selectedCartridge.cartridgeData == undefined || selectedCartridge.outcard != undefined || selectedCartridge.outhash != undefined) - setIsReplaying(true); + + // setReplayTip(false); + // if (selectedCartridge.cartridgeData == undefined || selectedCartridge.outcard != undefined || selectedCartridge.outhash != undefined) + // setIsReplaying(true); + // // @ts-ignore:next-line // if (Module.quited) { // // restart wasm when back to page @@ -215,6 +187,7 @@ function Rivemu() { // } await rivemuHalt(); setIsPlaying(true); + setOverallScore(0); if (selectedCartridge.scoreFunction) scoreFunction = parser.parse(selectedCartridge.scoreFunction); @@ -226,11 +199,12 @@ function Rivemu() { Module.HEAPU8.set(selectedCartridge.cartridgeData, cartridgeBuf); // @ts-ignore:next-line Module.HEAPU8.set(replayLog, rivlogBuf); + const inCard = selectedCartridge?.inCard || new Uint8Array([]); // @ts-ignore:next-line - let incardBuf = Module._malloc(selectedCartridge.inCard?.length || 0); + let incardBuf = Module._malloc(inCard.length); // @ts-ignore:next-line - if (selectedCartridge?.inCard) Module.HEAPU8.set(selectedCartridge.inCard, incardBuf); - let params = selectedCartridge?.args || ""; + Module.HEAPU8.set(inCard, incardBuf); + const params = selectedCartridge?.args || ""; // @ts-ignore:next-line Module.ccall( "rivemu_start_replay", @@ -240,7 +214,7 @@ function Rivemu() { cartridgeBuf, selectedCartridge.cartridgeData.length, incardBuf, - selectedCartridge.inCard?.length || 0, + inCard.length, params, rivlogBuf, replayLog.length @@ -264,21 +238,24 @@ function Rivemu() { async function rivemuStop() { console.log("rivemuStop"); setIsPlaying(false); - // @ts-ignore:next-line rivemuHalt(); - movePageToTop(); // stopCartridge(); } + async function close() { + if (selectedCartridge?.downloading) return; + setCancelled(true); + } + if (typeof window !== "undefined") { // @ts-ignore:next-line window.rivemu_on_frame = function ( outcard: ArrayBuffer, - frame: number, - fps: number, - mips: number, - cpu_usage: number, + frame: number, + fps: number, + mips: number, + cpu_usage: number, cycles: number ) { let score = 0; @@ -296,16 +273,17 @@ function Rivemu() { // @ts-ignore:next-line window.rivemu_on_begin = function (width: number, height: number, target_fps: number, total_frames: number) { if (!playedOnce) setPlayedOnce(true); - const canvas: any = document.getElementById("canvas"); - setGameHeigth(height); - if (canvas) { - canvas.height = Math.floor(canvasHeight / height) * height; - canvas.width = Math.floor(width / height * canvas.height); - } + if (freshOpen) setFreshOpen(false); + // const canvas: any = document.getElementById("canvas"); + // const maxCanvasHeight = canvas.parentElement.clientHeight; + // const maxCanvasWidth = canvas.parentElement.clientWidth; + // if (canvas) { + // canvas.height = maxCanvasHeight; + // canvas.width = maxCanvasWidth; + // } console.log("rivemu_on_begin"); - // setIsLoading(false); // force canvas resize - window.dispatchEvent(new Event("resize")); + // window.dispatchEvent(new Event("resize")); }; // @ts-ignore:next-line @@ -314,106 +292,68 @@ function Rivemu() { outcard: ArrayBuffer, outhash: string ) { - if (!isReplaying) { + if (!isReplaying && !cancelled) { setGameplay(new Uint8Array(rivlog),new Uint8Array(outcard),outhash); - setReplayLog(new Uint8Array(rivlog)); + // setReplayLog(new Uint8Array(rivlog)); } + rivemuStop(); console.log("rivemu_on_finish") }; } return ( - <section className='h-svh' hidden={selectedCartridge?.cartridgeData==undefined}> - <div className='h-24 grid grid-cols-3 gap-4 content-start'> - <div></div> - <div className="flex flex-wrap place-content-evenly"> - <button className="button-57" - onKeyDown={(e) => e.preventDefault()} - onClick={rivemuStart} - disabled={selectedCartridge?.cartridgeData == undefined} - // loading={isLoading} - // leftSection={ - // isPlaying ? ( - // <TbPlayerSkipBackFilled /> - // ) : ( - // <TbPlayerPlayFilled /> - // ) - // } - > - <span>{isPlaying ? <ReplayIcon/> : <PlayArrowIcon/>}</span> - <span>{isPlaying ? "Restart" : "Start"}</span> - </button> - <button className={`button-57 ${replayTip ? "animate-bounce" : ""}`} - id="replayButton" - onKeyDown={(e) => e.preventDefault()} - onClick={rivemuReplay} - // leftSection={<TbPlayerStopFilled />} - disabled={selectedCartridge?.cartridgeData == undefined || replayLog == undefined} - > - <span><OndemandVideoIcon/></span> - <span>Replay</span> - </button> - <button className="button-57" - onKeyDown={(e) => e.preventDefault()} - onClick={rivemuStop} - // leftSection={<TbPlayerStopFilled />} - > - <span><Stop/></span> - <span>Stop</span> - </button> - <button className="button-57" - onKeyDown={(e) => e.preventDefault()} - onClick={()=>setIsExpanded(!isExpanded)} - // leftSection={<TbPlayerStopFilled />} - disabled={gameHeigth == 0} - > - <span>{isExpanded ? <CloseFullscreenIcon/> : <OpenInFullIcon/>}</span> - <span>{isExpanded ? "Shrink" : "Expand"}</span> - </button> - </div> + <div> + <section className='gameplay-section' hidden={selectedCartridge?.cartridgeData==undefined}> + <div className='relative bg-gray-500 p-2 text-center'> + <span>Score: {overallScore}</span> + <button className="absolute top-1 end-2.5 rounded border border-gray-500 hover:border-black" + onClick={() => close()} + > + <CloseIcon/> + </button> </div> - <div className="flex justify-center"> - {/* <div className="flex justify-center max-h-400"> */} - {/* TODO: fix suspense rivemu canvas */} - {/* <Suspense fallback={coverFallback()}> */} - <div className='relative' - style={{ - height: canvasHeight, - width: canvasWidth - }} - > - <div hidden={!isPlaying && playedOnce} className='flex justify-center'> - <canvas - id="canvas" - onContextMenu={(e) => e.preventDefault()} - tabIndex={1} - /> - </div> - {/* <div hidden={isPlaying} style={{backgroundColor: "black"}}> */} - <div hidden={isPlaying} className='absolute top-0'> - {coverFallback()} - </div> - {/* </Suspense> */} + + <div className='bg-black max-h-full max-w-full' + > + <div hidden={!isPlaying && playedOnce} className='flex justify-center gameplay-screen max-h-full max-w-full'> + <canvas + className='max-h-full max-w-full' + id="canvas" + height={canvasMinHeight} + width={canvasMinWidth} + onContextMenu={(e) => e.preventDefault()} + tabIndex={-1} + style={{ + minHeight: canvasMinHeight, + minWidth: canvasMinWidth + }} + /> </div> - </div> - <div className="text-center d-flex justify-content-center" hidden={selectedCartridge?.cartridgeData == undefined}> - <h3 className={fontPressStart2P.className}>Score: <span>{overallScore}</span></h3> - </div> - <div className="text-left d-flex justify-content-center" hidden={isExpanded}> - <div className='h-4'></div> - <div className='grid grid-cols-3 gap-4 content-start'> - <div></div> - <fieldset className="overflow-auto custom-scrollbar" style={{maxHeight: descHeight}}> - <pre style={{whiteSpace: "pre-wrap"}}> - {selectedCartridge.info?.description} - </pre> - </fieldset> + <div hidden={isPlaying} className='absolute top-[40px] gameplay-screen'> + {coverFallback()} </div> </div> + + <div className='text-center d-flex space-x-1 justify-content-center mt-4'> + { + !isPlaying? + <button className='btn' onClick={rivemuStart}> + Start + </button> + : + // onKeyDown and onKeyUp "null" prevent buttons pressed when playing to trigger "rivemuStop" + <button className='btn' onKeyDown={() => null} onKeyUp={() => null} onClick={rivemuStop}> + Stop + </button> + } + + </div> <Script src="/rivemu.js?" strategy="lazyOnload" /> </section> + <div className="opacity-60 fixed inset-0 z-0 bg-black" onClick={() => close()}></div> + </div> ) } diff --git a/frontend/app/components/ThemeSwitch.tsx b/frontend/app/components/ThemeSwitch.tsx deleted file mode 100644 index a212e83..0000000 --- a/frontend/app/components/ThemeSwitch.tsx +++ /dev/null @@ -1,71 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; - - -import DarkIcon from "@/app/components/svg/DarkIcon"; -import LightIcon from "@/app/components/svg/LightIcon"; -import { setCookieTheme } from "../utils/theme"; - -const LIGHT_TRANSLATE = "-translate-x-2"; -const LIGHT_BTN = "bg-yellow-500"; - -const DARK_TRANSLATE = "translate-x-full" -const DARK_BTN = "bg-gray-700" - -type ThemeButton = { - theme: string; - translate: string; - btnColor: string; -} - - -function ThemeSwitch() { - const [theme, setTheme] = useState<ThemeButton | null>(null); - - // retrieve theme from localStorage - useEffect(() => { - if (document.documentElement.getAttribute("data-theme") == "light") { - setTheme({ - theme: "light", "translate": LIGHT_TRANSLATE, "btnColor": LIGHT_BTN - }); - } else { - setTheme({ - theme: "dark", "translate": DARK_TRANSLATE, "btnColor": DARK_BTN - }); - } - }, []) - - - const changeTheme = () => { - if (theme?.theme! == "dark") { - setTheme({ - theme: "light", "translate": LIGHT_TRANSLATE, "btnColor": LIGHT_BTN - }); - setCookieTheme("light"); - } else { - setTheme({ - theme: "dark", "translate": DARK_TRANSLATE, "btnColor": DARK_BTN - }); - setCookieTheme("dark"); - } - } - - - return ( - <button onClick={changeTheme} - className="w-16 h-8 rounded-full bg-white flex items-center transition duration-300 focus:outline-none shadow"> - <div - className={`w-10 h-10 relative rounded-full transition duration-500 transform ${theme?.btnColor!} ${theme?.translate!} p-1 text-white`}> - { - theme?.theme! == "light"? - <LightIcon /> - : - <DarkIcon /> - } - </div> - </button> - ) -} - -export default ThemeSwitch \ No newline at end of file diff --git a/frontend/app/components/Title.tsx b/frontend/app/components/Title.tsx deleted file mode 100644 index 1b71ab2..0000000 --- a/frontend/app/components/Title.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react' -import { fontPressStart2P } from '../utils/font'; - -import Image from 'next/image' -import rivesLogo from '../../public/logo.png'; - -function Title() { - return ( - // <div className="grid grid-cols-1"> - // <h1 className={`${fontPressStart2P.className} title-text`}> - // <span>RiVES</span> - // </h1> - // <span className="subtitle-text">RiscV Verifiable Entertainment System</span> - // </div> - - <div className="flex space-x-2"> - {/* <h1 className='title-text'> - <span>RiVES</span> - </h1> */} - <Image width={250} src={rivesLogo} alt='RiVES logo'/> - </div> - ) -} - -export default Title \ No newline at end of file diff --git a/frontend/app/components/svg/CloseIcon.tsx b/frontend/app/components/svg/CloseIcon.tsx deleted file mode 100644 index 13fd6ec..0000000 --- a/frontend/app/components/svg/CloseIcon.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' - -function CloseIcon() { - return ( - <svg className="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14"> - <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/> - </svg> - ) -} - -export default CloseIcon \ No newline at end of file diff --git a/frontend/app/components/svg/DarkIcon.tsx b/frontend/app/components/svg/DarkIcon.tsx deleted file mode 100644 index bd64563..0000000 --- a/frontend/app/components/svg/DarkIcon.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' - -function DarkIcon() { - return ( - <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> - <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" /> - </svg> - ) -} - -export default DarkIcon \ No newline at end of file diff --git a/frontend/app/components/svg/LightIcon.tsx b/frontend/app/components/svg/LightIcon.tsx deleted file mode 100644 index fbe6878..0000000 --- a/frontend/app/components/svg/LightIcon.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react' - -function LightIcon() { - return ( - <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor"> - <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" /> - </svg> - ) -} - -export default LightIcon \ No newline at end of file diff --git a/frontend/app/components/svg/RivesLogo.tsx b/frontend/app/components/svg/RivesLogo.tsx new file mode 100644 index 0000000..0a454f5 --- /dev/null +++ b/frontend/app/components/svg/RivesLogo.tsx @@ -0,0 +1,126 @@ +import React, { SVGProps } from 'react' + +function RivesLogo(props: SVGProps<SVGSVGElement>) { + return ( + <svg + xmlns="http://www.w3.org/2000/svg" + xmlnsXlink="http://www.w3.org/1999/xlink" + xmlSpace="preserve" + id="Layer_1" + x={0} + y={0} + // style={{ + // enableBackground: "new 0 0 822.7 349", + // }} + viewBox="0 0 822.7 349" + {...props} + > + <style> + { + ".st3{fill:#fff}.st5{fill:#b5c0c2}.st6{fill:#5e7276}.st7{fill:none;stroke:#b5c0c2;stroke-miterlimit:10}" + } + </style> + <defs> + <path id="SVGID_1_" d="M30.1 118.8h762.6v198.7H30.1z" /> + </defs> + <clipPath id="SVGID_00000037693830967963068360000003242726816333028281_"> + <use + xlinkHref="#SVGID_1_" + style={{ + overflow: "visible", + }} + /> + </clipPath> + <g + style={{ + clipPath: + "url(#SVGID_00000037693830967963068360000003242726816333028281_)", + }} + > + <defs> + <path + id="SVGID_00000140006203920632027650000014793764172332046238_" + d="M72 118.8h678.7c11.1 0 21.8 4.4 29.7 12.3 7.9 7.9 12.3 18.5 12.3 29.7v114.8c0 11.1-4.4 21.8-12.3 29.7-7.9 7.9-18.5 12.3-29.7 12.3H72c-11.1 0-21.8-4.4-29.7-12.3-7.9-7.9-12.3-18.5-12.3-29.7V160.7c0-11.1 4.4-21.8 12.3-29.7 7.9-7.8 18.6-12.2 29.7-12.2z" + /> + </defs> + <clipPath id="SVGID_00000155143499220385971260000010892477155872971919_"> + <use + xlinkHref="#SVGID_00000140006203920632027650000014793764172332046238_" + style={{ + overflow: "visible", + }} + /> + </clipPath> + <g + style={{ + clipPath: + "url(#SVGID_00000155143499220385971260000010892477155872971919_)", + }} + > + <path + d="M30.1 118.8h762.8v198.7H30.1V118.8z" + style={{ + fill: "#0b3037", + }} + /> + </g> + </g> + <path + d="M178.403 295.76v-17h16.8v17h-16.8zm-19.1 0v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-38.8v-17h16.8v17h-16.8zm0-19.1v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm-19 96.7v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.1v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm-19.1 96.7v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.1v-17h16.8v17h-16.8zm0-38.8v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm-19.2 77.3v-17h16.8v17h-16.8zm0-19.1v-17h16.8v17h-16.8zm0-38.8v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm-18.9 135.5v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.1v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm-19.2 135.5v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.1v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zM318.486 295.76v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-96.7v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm-18.9 135.5v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-96.7v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm-19.2 135.5v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.1v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm-19.2 135.5v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.1v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm-18.9 135.5v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-96.7v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm-19.2 135.5v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zm0-96.7v-17h16.8v17h-16.8zm0-19.4v-17h16.8v17h-16.8zM593.587 295.747v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm19.3 137.9v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm-38.9 137.9v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm-19.5 137.9v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm-19.2 137.9v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-19.8v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-19.8v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm-19.6 118.2v-17.3h17.1v17.3h-17.1zm0-19.8v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-19.8v-17.3h17.1v17.3h-17.1zM740.748 276.047v-17.3h17.1v17.3h-17.1zm0-19.8v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm-19.5 137.9v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-19.8v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm-19.5 137.9v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm-19.3 137.9v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-19.8v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm-19.5 137.9v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-39.5v-17.3h17.1v17.3h-17.1zm0-19.5v-17.3h17.1v17.3h-17.1zm0-19.7v-17.3h17.1v17.3h-17.1zm0-19.8v-17.3h17.1v17.3h-17.1z" + className="st3" + /> + <path + d="M352.5 181.6h6.8V176h13v-5.2h19.1v-5.6h26.5v5.6l6 .1v11.2h7.2v-6.2l6 .1v-16.9h6.8v-6.4h6.3v-11.1h7.3v-11.2h6.5v-6.1h6.4v-6.2h6.6v-11h6.4v-5.5h6.3v-6.7h6.4v-5.5h6.6v-5.8h6.4v-5.3h13.7v-5.9h6.5v-6.3h12.9v-5.5h6.5v-5.7h12.9v-5.6h20.1v-5.6H601v-6.1h12.9v-6h14v5.8l-14 .2v5.7h-6.4v5.5h-12.7v6h-6.6v5.7H582v5.4h-6.6v6.5h-6.3v5.8h-7.6v5.4h-6.4v11.2h-6.4v6.4h-6.6v5.6h-6.4v11.3h-6.4v5.5h-6.4v12.3h-6.7v11.2H509V159h-6.5v11.1H496v11.2h-6.4v12.3H483v16.6h-6.2v12.5h-6.2v16.5H464v17.7h-6.4v23.3h-7.7v9.4h-9v7.5h-49.3v-7.4h-6.9v-9.2h-6.1v-12.4H372v-11h-6.3v-11.4h-6.5v-6.6h-6.4v-5.2h-7.7v-5.8h-6v-5.5h-6.6v-5.7h-13v-6.3h6.7v-11.2h6.4V194h6.7v-5.7h13.2z" + className="st3" + /> + <path + d="M470.4 112.6h6.6v5.6h-6.6zM516.5 72.4h6.3v5.8h-6.3zM535.7 60.6h6.5v5.6h-6.5zM575.2 43.7h6.5v5.7h-6.5zM594.6 37.6h6.4v6.1h-6.4zM594.8 48.8h6.3v5.9h-6.3zM555.1 83.6h6.4v5.6h-6.4zM535.7 106.8h6.4v5.8h-6.4zM522.9 123.6h6.4v8.4h-6.4z" + className="st3" + /> + <path + d="M338.8 204.8v-5.5h6.6v-5.6h13.8v-5.4h32.2v5.4h6.1v5.7h7.2v11.2h6.7V234h6.5v-11.3h6.6v-17.9h6.6v-10.9h6V176h6.8v-10.8h6.3v-5.9h7.7v-12.2h5.6v-10.9h7.1v-6.3h6.2v-6.3h6.4v-5.5h6.5v-10.9h6.8v-5.8h6.2v-6.3h6.2v-5.9h13.9v-5.6h6.5v-5.3h6.4v-5.9h13v-6.3h6.4v6.3h-6.4v5.9h-6.5v5.3h-6.5v5.6h-6.4v5.9h-6.5v11.7h-6.3v5.8h-7.1v5.5h-6.2v12h-6.9v11.4h-6.7v11.2h-6.1v6.2H477V176h-6.6v6.1h-6.9v17.3h-5.9v10.9h-7.4v17.9h-6.3v17.6h-6.8v17h-6.4v17.5h-6.1v9.2h-26.8v-2.9h-6.5v-11.8H385v-17.4h-6.8v-5.9h-6.5v-12.3h-5.8v-5.3h-6.7v-5.7h-6.7v-5.5h-7.1v-6h-6.6v-6.1h-6.3v-5.8z" + className="st3" + /> + <path + d="M450.2 210.3h7.4v6.5h-7.4zM470.4 170.4h6.6v5.6h-6.6zM477 158.9h6.5v6.4H477zM483.5 147.1h6.1v5.5h-6.1zM516.5 101.1h6.4v5.7h-6.4zM555.1 60.6h6.4v5.6h-6.4zM450.2 152.7h7.7v6.6h-7.7zM443.9 165.2h6.3v5.2h-6.3zM437.1 176h6.7v6.1h-6.7zM424.5 204.8h6.6v5.5h-6.6zM417.9 222.7h6.6v5.5h-6.6zM391.4 188.3h6v5.4h-6zM404.7 210.6h6.7v6.3h-6.7zM378.2 257.4h6.7v5.4h-6.7zM424.6 280.3h6.1v5.9h-6.1zM503.2 118.1h6.2v5.5h-6.2z" + className="st3" + /> + <path + d="M352.5 181.6h6.8V176h13v-5.2h19.1v-5.6h26.5v5.6l6 .1v11.2h7.2v-6.2l6 .1v-16.9h6.8v-6.4h6.3v-11.1h7.3v-11.2h6.5v-6.1h6.4v-6.2h6.6v-11h6.4v-5.5h6.3v-6.7h6.4v-5.5h6.6v-5.8h6.4v-5.3h13.7v-5.9h6.5v-6.3h12.9v-5.5h6.5v-5.7h12.9v-5.6h20.1v-5.6H601v-6.1h12.9v-6h14v5.8l-14 .2v5.7h-6.4v5.5h-12.7v6h-6.6v5.7H582v5.4h-6.6v6.5h-6.3v5.8h-7.6v5.4h-6.4v11.2h-6.4v6.4h-6.6v5.6h-6.4v11.3h-6.4v5.5h-6.4v12.3h-6.7v11.2H509V159h-6.5v11.1H496v11.2h-6.4v12.3H483v16.6h-6.2v12.5h-6.2v16.5H464v17.7h-6.4v23.3h-7.7v9.4h-9v7.5h-49.3v-7.4h-6.9v-9.2h-6.1v-12.4H372v-11h-6.3v-11.4h-6.5v-6.6h-6.4v-5.2h-7.7v-5.8h-6v-5.5h-6.6v-5.7h-13v-6.3h6.7v-11.2h6.4V194h6.7v-5.7h13.2z" + style={{ + fill: "#0b3033", + }} + /> + <path + d="M470.4 112.6h6.6v5.6h-6.6zM516.5 72.4h6.3v5.8h-6.3zM535.7 60.6h6.5v5.6h-6.5zM575.2 43.7h6.5v5.7h-6.5zM594.6 37.6h6.4v6.1h-6.4zM594.8 48.8h6.3v5.9h-6.3zM555.1 83.6h6.4v5.6h-6.4zM535.7 106.8h6.4v5.8h-6.4zM522.9 123.6h6.4v8.4h-6.4z" + className="st5" + /> + <path + d="M338.8 204.8v-5.5h6.6v-5.6h13.8v-5.4h32.2v5.4h6.1v5.7h7.2v11.2h6.7V234h6.5v-11.3h6.6v-17.9h6.6v-10.9h6V176h6.8v-10.8h6.3v-5.9h7.7v-12.2h5.6v-10.9h7.1v-6.3h6.2v-6.3h6.4v-5.5h6.5v-10.9h6.8v-5.8h6.2v-6.3h6.2v-5.9h13.9v-5.6h6.5v-5.3h6.4v-5.9h13v-6.3h6.4v6.3h-6.4v5.9h-6.5v5.3h-6.5v5.6h-6.4v5.9h-6.5v11.7h-6.3v5.8h-7.1v5.5h-6.2v12h-6.9v11.4h-6.7v11.2h-6.1v6.2H477V176h-6.6v6.1h-6.9v17.3h-5.9v10.9h-7.4v17.9h-6.3v17.6h-6.8v17h-6.4v17.5h-6.1v9.2h-26.8v-2.9h-6.5v-11.8H385v-17.4h-6.8v-5.9h-6.5v-12.3h-5.8v-5.3h-6.7v-5.7h-6.7v-5.5h-7.1v-6h-6.6v-6.1h-6.3v-5.8z" + className="st3" + /> + <path + d="M450.2 210.3h7.4v6.5h-7.4zM470.4 170.4h6.6v5.6h-6.6zM477 158.9h6.5v6.4H477zM483.5 147.1h6.1v5.5h-6.1zM516.5 101.1h6.4v5.7h-6.4zM555.1 60.6h6.4v5.6h-6.4zM450.2 152.7h7.7v6.6h-7.7zM443.9 165.2h6.3v5.2h-6.3zM437.1 176h6.7v6.1h-6.7zM424.5 204.8h6.6v5.5h-6.6zM417.9 222.7h6.6v5.5h-6.6zM391.4 188.3h6v5.4h-6zM404.7 210.6h6.7v6.3h-6.7zM378.2 257.4h6.7v5.4h-6.7zM424.6 280.3h6.1v5.9h-6.1zM503.2 118.1h6.2v5.5h-6.2z" + className="st6" + /> + <path + d="M352.5 181.6h6.8V176h13v-5.2h19.1v-5.6h26.5v5.6l6 .1v11.2h7.2v-6.2l6 .1v-16.9h6.8v-6.4h6.3v-11.1h7.3v-11.2h6.5v-6.1h6.4v-6.2h6.6v-11h6.4v-5.5h6.3v-6.7h6.4v-5.5h6.6v-5.8h6.4v-5.3h13.7v-5.9h6.5v-6.3h12.9v-5.5h6.5v-5.7h12.9v-5.6h20.1v-5.6H601v-6.1h12.9v-6h14v5.8l-14 .2v5.7h-6.4v5.5h-12.7v6h-6.6v5.7H582v5.4h-6.6v6.5h-6.3v5.8h-7.6v5.4h-6.4v11.2h-6.4v6.4h-6.6v5.6h-6.4v11.3h-6.4v5.5h-6.4v12.3h-6.7v11.2H509V159h-6.5v11.1H496v11.2h-6.4v12.3H483v16.6h-6.2v12.5h-6.2v16.5H464v17.7h-6.4v23.3h-7.7v9.4h-9v7.5h-49.3v-7.4h-6.9v-9.2h-6.1v-12.4H372v-11h-6.3v-11.4h-6.5v-6.6h-6.4v-5.2h-7.7v-5.8h-6v-5.5h-6.6v-5.7h-13v-6.3h6.7v-11.2h6.4V194h6.7v-5.7h13.2z" + className="st7" + /> + <path + d="M470.4 112.6h6.6v5.6h-6.6zM516.5 72.4h6.3v5.8h-6.3zM535.7 60.6h6.5v5.6h-6.5zM575.2 43.7h6.5v5.7h-6.5zM594.6 37.6h6.4v6.1h-6.4zM594.8 48.8h6.3v5.9h-6.3zM555.1 83.6h6.4v5.6h-6.4zM535.7 106.8h6.4v5.8h-6.4zM522.9 123.6h6.4v8.4h-6.4z" + className="st7" + /> + <path + d="M338.8 204.8v-5.5h6.6v-5.6h13.8v-5.4h32.2v5.4h6.1v5.7h7.2v11.2h6.7V234h6.5v-11.3h6.6v-17.9h6.6v-10.9h6V176h6.8v-10.8h6.3v-5.9h7.7v-12.2h5.6v-10.9h7.1v-6.3h6.2v-6.3h6.4v-5.5h6.5v-10.9h6.8v-5.8h6.2v-6.3h6.2v-5.9h13.9v-5.6h6.5v-5.3h6.4v-5.9h13v-6.3h6.4v6.3h-6.4v5.9h-6.5v5.3h-6.5v5.6h-6.4v5.9h-6.5v11.7h-6.3v5.8h-7.1v5.5h-6.2v12h-6.9v11.4h-6.7v11.2h-6.1v6.2H477V176h-6.6v6.1h-6.9v17.3h-5.9v10.9h-7.4v17.9h-6.3v17.6h-6.8v17h-6.4v17.5h-6.1v9.2h-26.8v-2.9h-6.5v-11.8H385v-17.4h-6.8v-5.9h-6.5v-12.3h-5.8v-5.3h-6.7v-5.7h-6.7v-5.5h-7.1v-6h-6.6v-6.1h-6.3v-5.8z" + className="st7" + /> + <path + d="M450.2 210.3h7.4v6.5h-7.4zM470.4 170.4h6.6v5.6h-6.6zM477 158.9h6.5v6.4H477zM483.5 147.1h6.1v5.5h-6.1zM516.5 101.1h6.4v5.7h-6.4zM555.1 60.6h6.4v5.6h-6.4zM450.2 152.7h7.7v6.6h-7.7zM443.9 165.2h6.3v5.2h-6.3zM437.1 176h6.7v6.1h-6.7zM424.5 204.8h6.6v5.5h-6.6zM417.9 222.7h6.6v5.5h-6.6zM391.4 188.3h6v5.4h-6zM404.7 210.6h6.7v6.3h-6.7zM378.2 257.4h6.7v5.4h-6.7zM424.6 280.3h6.1v5.9h-6.1zM503.2 118.1h6.2v5.5h-6.2z" + className="st7" + /> + </svg> + ) +} + +export default RivesLogo \ No newline at end of file diff --git a/frontend/app/contracts/RivesScoreNFT.sol/RivesScoreNFT.json b/frontend/app/contracts/RivesScoreNFT.sol/RivesScoreNFT.json new file mode 100644 index 0000000..09d2230 --- /dev/null +++ b/frontend/app/contracts/RivesScoreNFT.sol/RivesScoreNFT.json @@ -0,0 +1,6551 @@ +{ + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_dappAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "approved", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_fromTokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_toTokenId", + "type": "uint256" + } + ], + "name": "BatchMetadataUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + } + ], + "name": "MetadataUpdate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_payload", + "type": "bytes" + }, + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "inputIndexWithinEpoch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "outputIndexWithinInput", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "outputHashesRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "vouchersEpochRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "noticesEpochRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "machineStateHash", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "outputHashInOutputHashesSiblings", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "outputHashesInEpochSiblings", + "type": "bytes32[]" + } + ], + "internalType": "struct OutputValidityProof", + "name": "validity", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + } + ], + "internalType": "struct Proof", + "name": "_v", + "type": "tuple" + } + ], + "name": "ckeckMinted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "dappAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "gamelogOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_payload", + "type": "bytes" + }, + { + "components": [ + { + "components": [ + { + "internalType": "uint64", + "name": "inputIndexWithinEpoch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "outputIndexWithinInput", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "outputHashesRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "vouchersEpochRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "noticesEpochRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "machineStateHash", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "outputHashInOutputHashesSiblings", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "outputHashesInEpochSiblings", + "type": "bytes32[]" + } + ], + "internalType": "struct OutputValidityProof", + "name": "validity", + "type": "tuple" + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + } + ], + "internalType": "struct Proof", + "name": "_v", + "type": "tuple" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "operator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "gameplayHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_s", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "_v", + "type": "uint8" + } + ], + "name": "setGameplayOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOperator", + "type": "address" + } + ], + "name": "setOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "gameplayHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_s", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "_v", + "type": "uint8" + } + ], + "name": "verifySignature", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "bytecode": { + "object": "0x60806040523480156200001157600080fd5b5060405162002751380380620027518339810160408190526200003491620000ca565b6040518060400160405280600d81526020016c149a5d995cd4d8dbdc99539195609a1b815250604051806040016040528060058152602001641494d3919560da1b8152508160009081620000899190620001a1565b506001620000988282620001a1565b5050600980546001600160a01b039093166001600160a01b031993841617905550600a8054909116331790556200026d565b600060208284031215620000dd57600080fd5b81516001600160a01b0381168114620000f557600080fd5b9392505050565b634e487b7160e01b600052604160045260246000fd5b600181811c908216806200012757607f821691505b6020821081036200014857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200019c57600081815260208120601f850160051c81016020861015620001775750805b601f850160051c820191505b81811015620001985782815560010162000183565b5050505b505050565b81516001600160401b03811115620001bd57620001bd620000fc565b620001d581620001ce845462000112565b846200014e565b602080601f8311600181146200020d5760008415620001f45750858301515b600019600386901b1c1916600185901b17855562000198565b600085815260208120601f198616915b828110156200023e578886015182559484019460019091019084016200021d565b50858210156200025d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6124d4806200027d6000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c80636352211e116100b8578063b3ab15fb1161007c578063b3ab15fb1461028d578063b88d4fde146102a0578063c521030a146102b3578063c87b56dd146102c6578063e985e9c5146102d9578063eadc7463146102ec57600080fd5b80636352211e1461022b57806370a082311461023e57806395d89b411461025f5780639da52e2514610267578063a22cb4651461027a57600080fd5b80631926dbe0116100ff5780631926dbe0146101cc5780631a721b7b146101df57806323b872dd146101f257806342842e0e14610205578063570ca7351461021857600080fd5b806301ffc9a71461013c57806306fdde0314610164578063081812fc14610179578063095ea7b3146101a45780630d413d62146101b9575b600080fd5b61014f61014a3660046119d2565b610315565b60405190151581526020015b60405180910390f35b61016c610340565b60405161015b9190611a3f565b61018c610187366004611a52565b6103d2565b6040516001600160a01b03909116815260200161015b565b6101b76101b2366004611a80565b6103f9565b005b61018c6101c7366004611aac565b610513565b61014f6101da366004611af3565b6105c9565b60095461018c906001600160a01b031681565b6101b7610200366004611b8d565b61081a565b6101b7610213366004611b8d565b61084b565b600a5461018c906001600160a01b031681565b61018c610239366004611a52565b610866565b61025161024c366004611bce565b6108c6565b60405190815260200161015b565b61016c61094c565b610251610275366004611af3565b61095b565b6101b7610288366004611bf9565b610d51565b6101b761029b366004611bce565b610d60565b6101b76102ae366004611cbd565b610def565b6101b76102c1366004611aac565b610e27565b61016c6102d4366004611a52565b610f71565b61014f6102e7366004611d3c565b611079565b61018c6102fa366004611a52565b6008602052600090815260409020546001600160a01b031681565b60006001600160e01b03198216632483248360e11b148061033a575061033a826110a7565b92915050565b60606000805461034f90611d6a565b80601f016020809104026020016040519081016040528092919081815260200182805461037b90611d6a565b80156103c85780601f1061039d576101008083540402835291602001916103c8565b820191906000526020600020905b8154815290600101906020018083116103ab57829003601f168201915b5050505050905090565b60006103dd826110f7565b506000908152600460205260409020546001600160a01b031690565b600061040482610866565b9050806001600160a01b0316836001600160a01b0316036104765760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b038216148061049257506104928133611079565b6105045760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161046d565b61050e8383611159565b505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018590526000908190605c0160408051601f1981840301815282825280516020918201206000845290830180835281905260ff8616918301919091526060820187905260808201869052915060019060a0016020604051602081039080840390855afa1580156105b3573d6000803e3d6000fd5b505050602060405103519150505b949350505050565b600954604051634b243ea360e11b81526000916001600160a01b03169081906396487d469061060090889088908890600401611eaf565b602060405180830381865afa15801561061d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106419190611fbe565b506000816001600160a01b031663179e740b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a69190611fdb565b6009546001600160a01b039182169163d79a824091166106c96020880188611ff8565b6040518463ffffffff1660e01b81526004016106e79392919061203e565b606060405180830381865afa158015610704573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610728919061206c565b50915060009050610739858061209a565b6107479060208101906120ba565b61075a906001600160401b0316836120d5565b9050600061079061076b878061209a565b61077c9060408101906020016120ba565b6001600160401b03168360809190911b1790565b6040516303fbaf7360e01b8152600760048201526024810182905290915073f5b2d8c81cde4d6238bbf20d3d77db37df13f735906303fbaf7390604401602060405180830381865af41580156107ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080e9190611fbe565b98975050505050505050565b61082433826111c7565b6108405760405162461bcd60e51b815260040161046d906120f6565b61050e838383611225565b61050e83838360405180602001604052806000815250610def565b6000818152600260205260408120546001600160a01b03168061033a5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161046d565b60006001600160a01b0382166109305760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161046d565b506001600160a01b031660009081526003602052604090205490565b60606001805461034f90611d6a565b600954604051634b243ea360e11b81526000916001600160a01b03169081906396487d469061099290889088908890600401611eaf565b602060405180830381865afa1580156109af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d39190611fbe565b506000816001600160a01b031663179e740b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190611fdb565b6009546001600160a01b039182169163d79a82409116610a5b6020880188611ff8565b6040518463ffffffff1660e01b8152600401610a799392919061203e565b606060405180830381865afa158015610a96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba919061206c565b50915060009050610acb858061209a565b610ad99060208101906120ba565b610aec906001600160401b0316836120d5565b90506000610afd61076b878061209a565b6040516303fbaf7360e01b8152600760048201526024810182905290915073f5b2d8c81cde4d6238bbf20d3d77db37df13f735906303fbaf7390604401602060405180830381865af4158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b9190611fbe565b15610bc85760405162461bcd60e51b815260206004820152601f60248201527f6e6f746963652072652d7375626d6974696e67206e6f7420616c6c6f77656400604482015260640161046d565b60008080610bd88a8c018c61216e565b600a54989c50909a5098508a975050506001600160a01b03948516948616949094039350610c8292505050576000828152600860205260409020546001600160a01b0316610c685760405162461bcd60e51b815260206004820152601960248201527f4e6f2067616d65706c6179206f776e657220646566696e656400000000000000604482015260640161046d565b506000818152600860205260409020546001600160a01b03165b6040516306449da160e41b815260076004820152602481018690526001604482015273f5b2d8c81cde4d6238bbf20d3d77db37df13f73590636449da109060640160006040518083038186803b158015610cdb57600080fd5b505af4158015610cef573d6000803e3d6000fd5b50505050610d01600b80546001019055565b6000610d0c600b5490565b9050610d188282611389565b610d418185604051602001610d2d9190612242565b604051602081830303815290604052611514565b9c9b505050505050505050505050565b610d5c3383836115df565b5050565b600a546001600160a01b03163314610dcd5760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c792063757272656e74206f70657261746f722063616e20736574206e656044820152693b9037b832b930ba37b960b11b606482015260840161046d565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b610df933836111c7565b610e155760405162461bcd60e51b815260040161046d906120f6565b610e21848484846116ad565b50505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101859052600090605c0160408051601f198184030181528282528051602091820120600080855291840180845281905260ff86169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610ec8573d6000803e3d6000fd5b5050604051601f190151600a549092506001600160a01b038084169116149050610f4c5760405162461bcd60e51b815260206004820152602f60248201527f53696e676e6564206d65737361676520646f6573206e6f74206d61746368206360448201526e3ab93932b73a1037b832b930ba37b960891b606482015260840161046d565b5050506000928352505060086020526040902080546001600160a01b03191633179055565b6060610f7c826110f7565b60008281526006602052604081208054610f9590611d6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610fc190611d6a565b801561100e5780601f10610fe35761010080835404028352916020019161100e565b820191906000526020600020905b815481529060010190602001808311610ff157829003601f168201915b50505050509050600061102c60408051602081019091526000815290565b9050805160000361103e575092915050565b815115611070578082604051602001611058929190612271565b60405160208183030381529060405292505050919050565b6105c1846116e0565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60006001600160e01b031982166380ac58cd60e01b14806110d857506001600160e01b03198216635b5e139f60e01b145b8061033a57506301ffc9a760e01b6001600160e01b031983161461033a565b6000818152600260205260409020546001600160a01b03166111565760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161046d565b50565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061118e82610866565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000806111d383610866565b9050806001600160a01b0316846001600160a01b031614806111fa57506111fa8185611079565b806105c15750836001600160a01b0316611213846103d2565b6001600160a01b031614949350505050565b826001600160a01b031661123882610866565b6001600160a01b03161461125e5760405162461bcd60e51b815260040161046d906122a0565b6001600160a01b0382166112c05760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161046d565b826001600160a01b03166112d382610866565b6001600160a01b0316146112f95760405162461bcd60e51b815260040161046d906122a0565b600081815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260038552838620805460001901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6001600160a01b0382166113df5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161046d565b6000818152600260205260409020546001600160a01b0316156114445760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161046d565b6000818152600260205260409020546001600160a01b0316156114a95760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161046d565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000828152600260205260409020546001600160a01b031661158f5760405162461bcd60e51b815260206004820152602e60248201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60448201526d32bc34b9ba32b73a103a37b5b2b760911b606482015260840161046d565b60008281526006602052604090206115a78282612333565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b816001600160a01b0316836001600160a01b0316036116405760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161046d565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6116b8848484611225565b6116c484848484611754565b610e215760405162461bcd60e51b815260040161046d906123f2565b60606116eb826110f7565b600061170260408051602081019091526000815290565b90506000815111611722576040518060200160405280600081525061174d565b8061172c84611852565b60405160200161173d929190612271565b6040516020818303038152906040525b9392505050565b60006001600160a01b0384163b1561184a57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611798903390899088908890600401612444565b6020604051808303816000875af19250505080156117d3575060408051601f3d908101601f191682019092526117d091810190612481565b60015b611830573d808015611801576040519150601f19603f3d011682016040523d82523d6000602084013e611806565b606091505b5080516000036118285760405162461bcd60e51b815260040161046d906123f2565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506105c1565b5060016105c1565b6060600061185f836118e4565b60010190506000816001600160401b0381111561187e5761187e611c32565b6040519080825280601f01601f1916602001820160405280156118a8576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846118b257509392505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106119235772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061194f576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061196d57662386f26fc10000830492506010015b6305f5e1008310611985576305f5e100830492506008015b612710831061199957612710830492506004015b606483106119ab576064830492506002015b600a831061033a5760010192915050565b6001600160e01b03198116811461115657600080fd5b6000602082840312156119e457600080fd5b813561174d816119bc565b60005b83811015611a0a5781810151838201526020016119f2565b50506000910152565b60008151808452611a2b8160208601602086016119ef565b601f01601f19169290920160200192915050565b60208152600061174d6020830184611a13565b600060208284031215611a6457600080fd5b5035919050565b6001600160a01b038116811461115657600080fd5b60008060408385031215611a9357600080fd5b8235611a9e81611a6b565b946020939093013593505050565b60008060008060808587031215611ac257600080fd5b843593506020850135925060408501359150606085013560ff81168114611ae857600080fd5b939692955090935050565b600080600060408486031215611b0857600080fd5b83356001600160401b0380821115611b1f57600080fd5b818601915086601f830112611b3357600080fd5b813581811115611b4257600080fd5b876020828501011115611b5457600080fd5b602092830195509350908501359080821115611b6f57600080fd5b50840160408187031215611b8257600080fd5b809150509250925092565b600080600060608486031215611ba257600080fd5b8335611bad81611a6b565b92506020840135611bbd81611a6b565b929592945050506040919091013590565b600060208284031215611be057600080fd5b813561174d81611a6b565b801515811461115657600080fd5b60008060408385031215611c0c57600080fd5b8235611c1781611a6b565b91506020830135611c2781611beb565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b0380841115611c6257611c62611c32565b604051601f8501601f19908116603f01168101908282118183101715611c8a57611c8a611c32565b81604052809350858152868686011115611ca357600080fd5b858560208301376000602087830101525050509392505050565b60008060008060808587031215611cd357600080fd5b8435611cde81611a6b565b93506020850135611cee81611a6b565b92506040850135915060608501356001600160401b03811115611d1057600080fd5b8501601f81018713611d2157600080fd5b611d3087823560208401611c48565b91505092959194509250565b60008060408385031215611d4f57600080fd5b8235611d5a81611a6b565b91506020830135611c2781611a6b565b600181811c90821680611d7e57607f821691505b602082108103611d9e57634e487b7160e01b600052602260045260246000fd5b50919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b80356001600160401b0381168114611de457600080fd5b919050565b6000808335601e19843603018112611e0057600080fd5b83016020810192503590506001600160401b03811115611e1f57600080fd5b8060051b3603821315611e3157600080fd5b9250929050565b81835260006001600160fb1b03831115611e5157600080fd5b8260051b80836020870137939093016020019392505050565b6000808335601e19843603018112611e8157600080fd5b83016020810192503590506001600160401b03811115611ea057600080fd5b803603821315611e3157600080fd5b604081526000611ec3604083018587611da4565b8281036020840152833560fe19853603018112611edf57600080fd5b6040825284016001600160401b03611ef682611dcd565b166040830152611f0860208201611dcd565b6001600160401b03811660608401525060408101356080830152606081013560a0830152608081013560c083015260a081013560e0830152611f4d60c0820182611de9565b61010084810152611f6361014085018284611e38565b915050611f7360e0830183611de9565b848303603f19016101208601529250611f8d828483611e38565b92505050611f9e6020860186611e6a565b8383036020850152611fb1838284611da4565b9998505050505050505050565b600060208284031215611fd057600080fd5b815161174d81611beb565b600060208284031215611fed57600080fd5b815161174d81611a6b565b6000808335601e1984360301811261200f57600080fd5b8301803591506001600160401b0382111561202957600080fd5b602001915036819003821315611e3157600080fd5b6001600160a01b03841681526040602082018190526000906120639083018486611da4565b95945050505050565b60008060006060848603121561208157600080fd5b8351925060208401519150604084015190509250925092565b6000823560fe198336030181126120b057600080fd5b9190910192915050565b6000602082840312156120cc57600080fd5b61174d82611dcd565b8082018082111561033a57634e487b7160e01b600052601160045260246000fd5b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b8035611de481611a6b565b600082601f83011261215f57600080fd5b61174d83833560208501611c48565b6000806000806000806000806000806101408b8d03121561218e57600080fd5b8a35995061219e60208c01612143565b985060408b0135975060608b0135965060808b0135955060a08b0135945060c08b01356001600160401b03808211156121d657600080fd5b6121e28e838f0161214e565b955060e08d01359150808211156121f857600080fd5b6122048e838f0161214e565b94506101008d013591508082111561221b57600080fd5b506122288d828e0161214e565b9250506101208b013590509295989b9194979a5092959850565b66697066733a2f2f60c81b8152600082516122648160078501602087016119ef565b9190910160070192915050565b600083516122838184602088016119ef565b8351908301906122978183602088016119ef565b01949350505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b601f82111561050e57600081815260208120601f850160051c8101602086101561230c5750805b601f850160051c820191505b8181101561232b57828155600101612318565b505050505050565b81516001600160401b0381111561234c5761234c611c32565b6123608161235a8454611d6a565b846122e5565b602080601f831160018114612395576000841561237d5750858301515b600019600386901b1c1916600185901b17855561232b565b600085815260208120601f198616915b828110156123c4578886015182559484019460019091019084016123a5565b50858210156123e25787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061247790830184611a13565b9695505050505050565b60006020828403121561249357600080fd5b815161174d816119bc56fea26469706673582212209571e6d4419d7f6b3b36bcb667bc69f1132e4904e5b325adaf275dc2cbc220f364736f6c63430008150033", + "sourceMap": "388:3580:0:-:0;;;722:131;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1390:113:12;;;;;;;;;;;;;-1:-1:-1;;;1390:113:12;;;;;;;;;;;;;;;;-1:-1:-1;;;1390:113:12;;;1464:5;1456;:13;;;;;;:::i;:::-;-1:-1:-1;1479:7:12;:17;1489:7;1479;:17;:::i;:::-;-1:-1:-1;;795:11:0::1;:26:::0;;-1:-1:-1;;;;;795:26:0;;::::1;-1:-1:-1::0;;;;;;795:26:0;;::::1;;::::0;;-1:-1:-1;827:8:0::1;:21:::0;;;;::::1;838:10;827:21;::::0;;388:3580;;14:290:25;84:6;137:2;125:9;116:7;112:23;108:32;105:52;;;153:1;150;143:12;105:52;179:16;;-1:-1:-1;;;;;224:31:25;;214:42;;204:70;;270:1;267;260:12;204:70;293:5;14:290;-1:-1:-1;;;14:290:25:o;309:127::-;370:10;365:3;361:20;358:1;351:31;401:4;398:1;391:15;425:4;422:1;415:15;441:380;520:1;516:12;;;;563;;;584:61;;638:4;630:6;626:17;616:27;;584:61;691:2;683:6;680:14;660:18;657:38;654:161;;737:10;732:3;728:20;725:1;718:31;772:4;769:1;762:15;800:4;797:1;790:15;654:161;;441:380;;;:::o;952:545::-;1054:2;1049:3;1046:11;1043:448;;;1090:1;1115:5;1111:2;1104:17;1160:4;1156:2;1146:19;1230:2;1218:10;1214:19;1211:1;1207:27;1201:4;1197:38;1266:4;1254:10;1251:20;1248:47;;;-1:-1:-1;1289:4:25;1248:47;1344:2;1339:3;1335:12;1332:1;1328:20;1322:4;1318:31;1308:41;;1399:82;1417:2;1410:5;1407:13;1399:82;;;1462:17;;;1443:1;1432:13;1399:82;;;1403:3;;;1043:448;952:545;;;:::o;1673:1352::-;1793:10;;-1:-1:-1;;;;;1815:30:25;;1812:56;;;1848:18;;:::i;:::-;1877:97;1967:6;1927:38;1959:4;1953:11;1927:38;:::i;:::-;1921:4;1877:97;:::i;:::-;2029:4;;2093:2;2082:14;;2110:1;2105:663;;;;2812:1;2829:6;2826:89;;;-1:-1:-1;2881:19:25;;;2875:26;2826:89;-1:-1:-1;;1630:1:25;1626:11;;;1622:24;1618:29;1608:40;1654:1;1650:11;;;1605:57;2928:81;;2075:944;;2105:663;899:1;892:14;;;936:4;923:18;;-1:-1:-1;;2141:20:25;;;2259:236;2273:7;2270:1;2267:14;2259:236;;;2362:19;;;2356:26;2341:42;;2454:27;;;;2422:1;2410:14;;;;2289:19;;2259:236;;;2263:3;2523:6;2514:7;2511:19;2508:201;;;2584:19;;;2578:26;-1:-1:-1;;2667:1:25;2663:14;;;2679:3;2659:24;2655:37;2651:42;2636:58;2621:74;;2508:201;-1:-1:-1;;;;;2755:1:25;2739:14;;;2735:22;2722:36;;-1:-1:-1;1673:1352:25:o;:::-;388:3580:0;;;;;;", + "linkReferences": {} + }, + "deployedBytecode": { + "object": "0x608060405234801561001057600080fd5b50600436106101375760003560e01c80636352211e116100b8578063b3ab15fb1161007c578063b3ab15fb1461028d578063b88d4fde146102a0578063c521030a146102b3578063c87b56dd146102c6578063e985e9c5146102d9578063eadc7463146102ec57600080fd5b80636352211e1461022b57806370a082311461023e57806395d89b411461025f5780639da52e2514610267578063a22cb4651461027a57600080fd5b80631926dbe0116100ff5780631926dbe0146101cc5780631a721b7b146101df57806323b872dd146101f257806342842e0e14610205578063570ca7351461021857600080fd5b806301ffc9a71461013c57806306fdde0314610164578063081812fc14610179578063095ea7b3146101a45780630d413d62146101b9575b600080fd5b61014f61014a3660046119d2565b610315565b60405190151581526020015b60405180910390f35b61016c610340565b60405161015b9190611a3f565b61018c610187366004611a52565b6103d2565b6040516001600160a01b03909116815260200161015b565b6101b76101b2366004611a80565b6103f9565b005b61018c6101c7366004611aac565b610513565b61014f6101da366004611af3565b6105c9565b60095461018c906001600160a01b031681565b6101b7610200366004611b8d565b61081a565b6101b7610213366004611b8d565b61084b565b600a5461018c906001600160a01b031681565b61018c610239366004611a52565b610866565b61025161024c366004611bce565b6108c6565b60405190815260200161015b565b61016c61094c565b610251610275366004611af3565b61095b565b6101b7610288366004611bf9565b610d51565b6101b761029b366004611bce565b610d60565b6101b76102ae366004611cbd565b610def565b6101b76102c1366004611aac565b610e27565b61016c6102d4366004611a52565b610f71565b61014f6102e7366004611d3c565b611079565b61018c6102fa366004611a52565b6008602052600090815260409020546001600160a01b031681565b60006001600160e01b03198216632483248360e11b148061033a575061033a826110a7565b92915050565b60606000805461034f90611d6a565b80601f016020809104026020016040519081016040528092919081815260200182805461037b90611d6a565b80156103c85780601f1061039d576101008083540402835291602001916103c8565b820191906000526020600020905b8154815290600101906020018083116103ab57829003601f168201915b5050505050905090565b60006103dd826110f7565b506000908152600460205260409020546001600160a01b031690565b600061040482610866565b9050806001600160a01b0316836001600160a01b0316036104765760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e656044820152603960f91b60648201526084015b60405180910390fd5b336001600160a01b038216148061049257506104928133611079565b6105045760405162461bcd60e51b815260206004820152603d60248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f7420746f60448201527f6b656e206f776e6572206f7220617070726f76656420666f7220616c6c000000606482015260840161046d565b61050e8383611159565b505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c81018590526000908190605c0160408051601f1981840301815282825280516020918201206000845290830180835281905260ff8616918301919091526060820187905260808201869052915060019060a0016020604051602081039080840390855afa1580156105b3573d6000803e3d6000fd5b505050602060405103519150505b949350505050565b600954604051634b243ea360e11b81526000916001600160a01b03169081906396487d469061060090889088908890600401611eaf565b602060405180830381865afa15801561061d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106419190611fbe565b506000816001600160a01b031663179e740b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610682573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a69190611fdb565b6009546001600160a01b039182169163d79a824091166106c96020880188611ff8565b6040518463ffffffff1660e01b81526004016106e79392919061203e565b606060405180830381865afa158015610704573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610728919061206c565b50915060009050610739858061209a565b6107479060208101906120ba565b61075a906001600160401b0316836120d5565b9050600061079061076b878061209a565b61077c9060408101906020016120ba565b6001600160401b03168360809190911b1790565b6040516303fbaf7360e01b8152600760048201526024810182905290915073f5b2d8c81cde4d6238bbf20d3d77db37df13f735906303fbaf7390604401602060405180830381865af41580156107ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061080e9190611fbe565b98975050505050505050565b61082433826111c7565b6108405760405162461bcd60e51b815260040161046d906120f6565b61050e838383611225565b61050e83838360405180602001604052806000815250610def565b6000818152600260205260408120546001600160a01b03168061033a5760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161046d565b60006001600160a01b0382166109305760405162461bcd60e51b815260206004820152602960248201527f4552433732313a2061646472657373207a65726f206973206e6f7420612076616044820152683634b21037bbb732b960b91b606482015260840161046d565b506001600160a01b031660009081526003602052604090205490565b60606001805461034f90611d6a565b600954604051634b243ea360e11b81526000916001600160a01b03169081906396487d469061099290889088908890600401611eaf565b602060405180830381865afa1580156109af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d39190611fbe565b506000816001600160a01b031663179e740b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a389190611fdb565b6009546001600160a01b039182169163d79a82409116610a5b6020880188611ff8565b6040518463ffffffff1660e01b8152600401610a799392919061203e565b606060405180830381865afa158015610a96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aba919061206c565b50915060009050610acb858061209a565b610ad99060208101906120ba565b610aec906001600160401b0316836120d5565b90506000610afd61076b878061209a565b6040516303fbaf7360e01b8152600760048201526024810182905290915073f5b2d8c81cde4d6238bbf20d3d77db37df13f735906303fbaf7390604401602060405180830381865af4158015610b57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b7b9190611fbe565b15610bc85760405162461bcd60e51b815260206004820152601f60248201527f6e6f746963652072652d7375626d6974696e67206e6f7420616c6c6f77656400604482015260640161046d565b60008080610bd88a8c018c61216e565b600a54989c50909a5098508a975050506001600160a01b03948516948616949094039350610c8292505050576000828152600860205260409020546001600160a01b0316610c685760405162461bcd60e51b815260206004820152601960248201527f4e6f2067616d65706c6179206f776e657220646566696e656400000000000000604482015260640161046d565b506000818152600860205260409020546001600160a01b03165b6040516306449da160e41b815260076004820152602481018690526001604482015273f5b2d8c81cde4d6238bbf20d3d77db37df13f73590636449da109060640160006040518083038186803b158015610cdb57600080fd5b505af4158015610cef573d6000803e3d6000fd5b50505050610d01600b80546001019055565b6000610d0c600b5490565b9050610d188282611389565b610d418185604051602001610d2d9190612242565b604051602081830303815290604052611514565b9c9b505050505050505050505050565b610d5c3383836115df565b5050565b600a546001600160a01b03163314610dcd5760405162461bcd60e51b815260206004820152602a60248201527f4f6e6c792063757272656e74206f70657261746f722063616e20736574206e656044820152693b9037b832b930ba37b960b11b606482015260840161046d565b600a80546001600160a01b0319166001600160a01b0392909216919091179055565b610df933836111c7565b610e155760405162461bcd60e51b815260040161046d906120f6565b610e21848484846116ad565b50505050565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101859052600090605c0160408051601f198184030181528282528051602091820120600080855291840180845281905260ff86169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa158015610ec8573d6000803e3d6000fd5b5050604051601f190151600a549092506001600160a01b038084169116149050610f4c5760405162461bcd60e51b815260206004820152602f60248201527f53696e676e6564206d65737361676520646f6573206e6f74206d61746368206360448201526e3ab93932b73a1037b832b930ba37b960891b606482015260840161046d565b5050506000928352505060086020526040902080546001600160a01b03191633179055565b6060610f7c826110f7565b60008281526006602052604081208054610f9590611d6a565b80601f0160208091040260200160405190810160405280929190818152602001828054610fc190611d6a565b801561100e5780601f10610fe35761010080835404028352916020019161100e565b820191906000526020600020905b815481529060010190602001808311610ff157829003601f168201915b50505050509050600061102c60408051602081019091526000815290565b9050805160000361103e575092915050565b815115611070578082604051602001611058929190612271565b60405160208183030381529060405292505050919050565b6105c1846116e0565b6001600160a01b03918216600090815260056020908152604080832093909416825291909152205460ff1690565b60006001600160e01b031982166380ac58cd60e01b14806110d857506001600160e01b03198216635b5e139f60e01b145b8061033a57506301ffc9a760e01b6001600160e01b031983161461033a565b6000818152600260205260409020546001600160a01b03166111565760405162461bcd60e51b8152602060048201526018602482015277115490cdcc8c4e881a5b9d985b1a59081d1bdad95b88125160421b604482015260640161046d565b50565b600081815260046020526040902080546001600160a01b0319166001600160a01b038416908117909155819061118e82610866565b6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000806111d383610866565b9050806001600160a01b0316846001600160a01b031614806111fa57506111fa8185611079565b806105c15750836001600160a01b0316611213846103d2565b6001600160a01b031614949350505050565b826001600160a01b031661123882610866565b6001600160a01b03161461125e5760405162461bcd60e51b815260040161046d906122a0565b6001600160a01b0382166112c05760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f206164646044820152637265737360e01b606482015260840161046d565b826001600160a01b03166112d382610866565b6001600160a01b0316146112f95760405162461bcd60e51b815260040161046d906122a0565b600081815260046020908152604080832080546001600160a01b03199081169091556001600160a01b0387811680865260038552838620805460001901905590871680865283862080546001019055868652600290945282852080549092168417909155905184937fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b6001600160a01b0382166113df5760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f2061646472657373604482015260640161046d565b6000818152600260205260409020546001600160a01b0316156114445760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161046d565b6000818152600260205260409020546001600160a01b0316156114a95760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e74656400000000604482015260640161046d565b6001600160a01b038216600081815260036020908152604080832080546001019055848352600290915280822080546001600160a01b0319168417905551839291907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b6000828152600260205260409020546001600160a01b031661158f5760405162461bcd60e51b815260206004820152602e60248201527f45524337323155524953746f726167653a2055524920736574206f66206e6f6e60448201526d32bc34b9ba32b73a103a37b5b2b760911b606482015260840161046d565b60008281526006602052604090206115a78282612333565b506040518281527ff8e1a15aba9398e019f0b49df1a4fde98ee17ae345cb5f6b5e2c27f5033e8ce79060200160405180910390a15050565b816001600160a01b0316836001600160a01b0316036116405760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c657200000000000000604482015260640161046d565b6001600160a01b03838116600081815260056020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b6116b8848484611225565b6116c484848484611754565b610e215760405162461bcd60e51b815260040161046d906123f2565b60606116eb826110f7565b600061170260408051602081019091526000815290565b90506000815111611722576040518060200160405280600081525061174d565b8061172c84611852565b60405160200161173d929190612271565b6040516020818303038152906040525b9392505050565b60006001600160a01b0384163b1561184a57604051630a85bd0160e11b81526001600160a01b0385169063150b7a0290611798903390899088908890600401612444565b6020604051808303816000875af19250505080156117d3575060408051601f3d908101601f191682019092526117d091810190612481565b60015b611830573d808015611801576040519150601f19603f3d011682016040523d82523d6000602084013e611806565b606091505b5080516000036118285760405162461bcd60e51b815260040161046d906123f2565b805181602001fd5b6001600160e01b031916630a85bd0160e11b1490506105c1565b5060016105c1565b6060600061185f836118e4565b60010190506000816001600160401b0381111561187e5761187e611c32565b6040519080825280601f01601f1916602001820160405280156118a8576020820181803683370190505b5090508181016020015b600019016f181899199a1a9b1b9c1cb0b131b232b360811b600a86061a8153600a85049450846118b257509392505050565b60008072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b83106119235772184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b830492506040015b6d04ee2d6d415b85acef8100000000831061194f576d04ee2d6d415b85acef8100000000830492506020015b662386f26fc10000831061196d57662386f26fc10000830492506010015b6305f5e1008310611985576305f5e100830492506008015b612710831061199957612710830492506004015b606483106119ab576064830492506002015b600a831061033a5760010192915050565b6001600160e01b03198116811461115657600080fd5b6000602082840312156119e457600080fd5b813561174d816119bc565b60005b83811015611a0a5781810151838201526020016119f2565b50506000910152565b60008151808452611a2b8160208601602086016119ef565b601f01601f19169290920160200192915050565b60208152600061174d6020830184611a13565b600060208284031215611a6457600080fd5b5035919050565b6001600160a01b038116811461115657600080fd5b60008060408385031215611a9357600080fd5b8235611a9e81611a6b565b946020939093013593505050565b60008060008060808587031215611ac257600080fd5b843593506020850135925060408501359150606085013560ff81168114611ae857600080fd5b939692955090935050565b600080600060408486031215611b0857600080fd5b83356001600160401b0380821115611b1f57600080fd5b818601915086601f830112611b3357600080fd5b813581811115611b4257600080fd5b876020828501011115611b5457600080fd5b602092830195509350908501359080821115611b6f57600080fd5b50840160408187031215611b8257600080fd5b809150509250925092565b600080600060608486031215611ba257600080fd5b8335611bad81611a6b565b92506020840135611bbd81611a6b565b929592945050506040919091013590565b600060208284031215611be057600080fd5b813561174d81611a6b565b801515811461115657600080fd5b60008060408385031215611c0c57600080fd5b8235611c1781611a6b565b91506020830135611c2781611beb565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60006001600160401b0380841115611c6257611c62611c32565b604051601f8501601f19908116603f01168101908282118183101715611c8a57611c8a611c32565b81604052809350858152868686011115611ca357600080fd5b858560208301376000602087830101525050509392505050565b60008060008060808587031215611cd357600080fd5b8435611cde81611a6b565b93506020850135611cee81611a6b565b92506040850135915060608501356001600160401b03811115611d1057600080fd5b8501601f81018713611d2157600080fd5b611d3087823560208401611c48565b91505092959194509250565b60008060408385031215611d4f57600080fd5b8235611d5a81611a6b565b91506020830135611c2781611a6b565b600181811c90821680611d7e57607f821691505b602082108103611d9e57634e487b7160e01b600052602260045260246000fd5b50919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b80356001600160401b0381168114611de457600080fd5b919050565b6000808335601e19843603018112611e0057600080fd5b83016020810192503590506001600160401b03811115611e1f57600080fd5b8060051b3603821315611e3157600080fd5b9250929050565b81835260006001600160fb1b03831115611e5157600080fd5b8260051b80836020870137939093016020019392505050565b6000808335601e19843603018112611e8157600080fd5b83016020810192503590506001600160401b03811115611ea057600080fd5b803603821315611e3157600080fd5b604081526000611ec3604083018587611da4565b8281036020840152833560fe19853603018112611edf57600080fd5b6040825284016001600160401b03611ef682611dcd565b166040830152611f0860208201611dcd565b6001600160401b03811660608401525060408101356080830152606081013560a0830152608081013560c083015260a081013560e0830152611f4d60c0820182611de9565b61010084810152611f6361014085018284611e38565b915050611f7360e0830183611de9565b848303603f19016101208601529250611f8d828483611e38565b92505050611f9e6020860186611e6a565b8383036020850152611fb1838284611da4565b9998505050505050505050565b600060208284031215611fd057600080fd5b815161174d81611beb565b600060208284031215611fed57600080fd5b815161174d81611a6b565b6000808335601e1984360301811261200f57600080fd5b8301803591506001600160401b0382111561202957600080fd5b602001915036819003821315611e3157600080fd5b6001600160a01b03841681526040602082018190526000906120639083018486611da4565b95945050505050565b60008060006060848603121561208157600080fd5b8351925060208401519150604084015190509250925092565b6000823560fe198336030181126120b057600080fd5b9190910192915050565b6000602082840312156120cc57600080fd5b61174d82611dcd565b8082018082111561033a57634e487b7160e01b600052601160045260246000fd5b6020808252602d908201527f4552433732313a2063616c6c6572206973206e6f7420746f6b656e206f776e6560408201526c1c881bdc88185c1c1c9bdd9959609a1b606082015260800190565b8035611de481611a6b565b600082601f83011261215f57600080fd5b61174d83833560208501611c48565b6000806000806000806000806000806101408b8d03121561218e57600080fd5b8a35995061219e60208c01612143565b985060408b0135975060608b0135965060808b0135955060a08b0135945060c08b01356001600160401b03808211156121d657600080fd5b6121e28e838f0161214e565b955060e08d01359150808211156121f857600080fd5b6122048e838f0161214e565b94506101008d013591508082111561221b57600080fd5b506122288d828e0161214e565b9250506101208b013590509295989b9194979a5092959850565b66697066733a2f2f60c81b8152600082516122648160078501602087016119ef565b9190910160070192915050565b600083516122838184602088016119ef565b8351908301906122978183602088016119ef565b01949350505050565b60208082526025908201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060408201526437bbb732b960d91b606082015260800190565b601f82111561050e57600081815260208120601f850160051c8101602086101561230c5750805b601f850160051c820191505b8181101561232b57828155600101612318565b505050505050565b81516001600160401b0381111561234c5761234c611c32565b6123608161235a8454611d6a565b846122e5565b602080601f831160018114612395576000841561237d5750858301515b600019600386901b1c1916600185901b17855561232b565b600085815260208120601f198616915b828110156123c4578886015182559484019460019091019084016123a5565b50858210156123e25787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60208082526032908201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560408201527131b2b4bb32b91034b6b83632b6b2b73a32b960711b606082015260800190565b6001600160a01b038581168252841660208201526040810183905260806060820181905260009061247790830184611a13565b9695505050505050565b60006020828403121561249357600080fd5b815161174d816119bc56fea26469706673582212209571e6d4419d7f6b3b36bcb667bc69f1132e4904e5b325adaf275dc2cbc220f364736f6c63430008150033", + "sourceMap": "388:3580:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;535:205:15;;;;;;:::i;:::-;;:::i;:::-;;;565:14:25;;558:22;540:41;;528:2;513:18;535:205:15;;;;;;;;2471:98:12;;;:::i;:::-;;;;;;;:::i;3935:167::-;;;;;;:::i;:::-;;:::i;:::-;;;-1:-1:-1;;;;;1697:32:25;;;1679:51;;1667:2;1652:18;3935:167:12;1533:203:25;3468:406:12;;;;;;:::i;:::-;;:::i;:::-;;1027:254:0;;;;;;:::i;:::-;;:::i;3321:645::-;;;;;;:::i;:::-;;:::i;625:26::-;;;;;-1:-1:-1;;;;;625:26:0;;;4612:296:12;;;;;;:::i;:::-;;:::i;4974:149::-;;;;;;:::i;:::-;;:::i;655:23:0:-;;;;;-1:-1:-1;;;;;655:23:0;;;2190:219:12;;;;;;:::i;:::-;;:::i;1929:204::-;;;;;;:::i;:::-;;:::i;:::-;;;4398:25:25;;;4386:2;4371:18;1929:204:12;4252:177:25;2633:102:12;;;:::i;1661:1656:0:-;;;;;;:::i;:::-;;:::i;4169:153:12:-;;;;;;:::i;:::-;;:::i;857:164:0:-;;;;;;:::i;:::-;;:::i;5189:276:12:-;;;;;;:::i;:::-;;:::i;1285:372:0:-;;;;;;:::i;:::-;;:::i;806:608:15:-;;;;;;:::i;:::-;;:::i;4388:162:12:-;;;;;;:::i;:::-;;:::i;570:48:0:-;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;;;570:48:0;;;535:205:15;637:4;-1:-1:-1;;;;;;660:33:15;;-1:-1:-1;;;660:33:15;;:73;;;697:36;721:11;697:23;:36::i;:::-;653:80;535:205;-1:-1:-1;;535:205:15:o;2471:98:12:-;2525:13;2557:5;2550:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2471:98;:::o;3935:167::-;4011:7;4030:23;4045:7;4030:14;:23::i;:::-;-1:-1:-1;4071:24:12;;;;:15;:24;;;;;;-1:-1:-1;;;;;4071:24:12;;3935:167::o;3468:406::-;3548:13;3564:23;3579:7;3564:14;:23::i;:::-;3548:39;;3611:5;-1:-1:-1;;;;;3605:11:12;:2;-1:-1:-1;;;;;3605:11:12;;3597:57;;;;-1:-1:-1;;;3597:57:12;;7676:2:25;3597:57:12;;;7658:21:25;7715:2;7695:18;;;7688:30;7754:34;7734:18;;;7727:62;-1:-1:-1;;;7805:18:25;;;7798:31;7846:19;;3597:57:12;;;;;;;;;719:10:18;-1:-1:-1;;;;;3686:21:12;;;;:62;;-1:-1:-1;3711:37:12;3728:5;719:10:18;4388:162:12;:::i;3711:37::-;3665:170;;;;-1:-1:-1;;;3665:170:12;;8078:2:25;3665:170:12;;;8060:21:25;8117:2;8097:18;;;8090:30;8156:34;8136:18;;;8129:62;8227:31;8207:18;;;8200:59;8276:19;;3665:170:12;7876:425:25;3665:170:12;3846:21;3855:2;3859:7;3846:8;:21::i;:::-;3538:336;3468:406;;:::o;1027:254:0:-;1169:66;;8548::25;1169::0;;;8536:79:25;8631:12;;;8624:28;;;1129:7:0;;;;8668:12:25;;1169:66:0;;;-1:-1:-1;;1169:66:0;;;;;;;;;1159:77;;1169:66;1159:77;;;;1249:27;;;;;;;;;8918:25:25;;;8991:4;8979:17;;8959:18;;;8952:45;;;;9013:18;;;9006:34;;;9056:18;;;9049:34;;;1159:77:0;-1:-1:-1;1249:27:0;;8890:19:25;;1249:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1242:34;;;1027:254;;;;;;;:::o;3321:645::-;3452:11;;3494:32;;-1:-1:-1;;;3494:32:0;;3407:4;;-1:-1:-1;;;;;3452:11:0;;;;3494:19;;:32;;3514:8;;;;3523:2;;3494:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;3593:23;3622:4;-1:-1:-1;;;;;3622:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3651:11;;-1:-1:-1;;;;;3622:28:0;;;;;;3651:11;3663:10;;;;:2;:10;:::i;:::-;3622:52;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;3590:84:0;-1:-1:-1;3681:18:0;;-1:-1:-1;3720:11:0;:2;;:11;:::i;:::-;:33;;;;;;;:::i;:::-;3702:51;;-1:-1:-1;;;;;3702:51:0;:15;:51;:::i;:::-;3681:72;-1:-1:-1;3802:22:0;3827:85;3866:11;:2;;:11;:::i;:::-;:34;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;3827:85:0;3901:10;8244:3:5;8233:14;;;;8232:24;;7887:378;3827:85:0;3925:36;;-1:-1:-1;;;3925:36:0;;:13;:36;;;15537:25:25;15578:18;;;15571:34;;;3802:110:0;;-1:-1:-1;3925:20:0;;;;15510:18:25;;3925:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;3918:43;3321:645;-1:-1:-1;;;;;;;;3321:645:0:o;4612:296:12:-;4771:41;719:10:18;4804:7:12;4771:18;:41::i;:::-;4763:99;;;;-1:-1:-1;;;4763:99:12;;;;;;;:::i;:::-;4873:28;4883:4;4889:2;4893:7;4873:9;:28::i;4974:149::-;5077:39;5094:4;5100:2;5104:7;5077:39;;;;;;;;;;;;:16;:39::i;2190:219::-;2262:7;6794:16;;;:7;:16;;;;;;-1:-1:-1;;;;;6794:16:12;;2324:56;;;;-1:-1:-1;;;2324:56:12;;16232:2:25;2324:56:12;;;16214:21:25;16271:2;16251:18;;;16244:30;-1:-1:-1;;;16290:18:25;;;16283:54;16354:18;;2324:56:12;16030:348:25;1929:204:12;2001:7;-1:-1:-1;;;;;2028:19:12;;2020:73;;;;-1:-1:-1;;;2020:73:12;;16585:2:25;2020:73:12;;;16567:21:25;16624:2;16604:18;;;16597:30;16663:34;16643:18;;;16636:62;-1:-1:-1;;;16714:18:25;;;16707:39;16763:19;;2020:73:12;16383:405:25;2020:73:12;-1:-1:-1;;;;;;2110:16:12;;;;;:9;:16;;;;;;;1929:204::o;2633:102::-;2689:13;2721:7;2714:14;;;;;:::i;1661:1656:0:-;1783:11;;1825:32;;-1:-1:-1;;;1825:32:0;;1735:7;;-1:-1:-1;;;;;1783:11:0;;;;1825:19;;:32;;1845:8;;;;1854:2;;1825:32;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;1924:23;1953:4;-1:-1:-1;;;;;1953:17:0;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1982:11;;-1:-1:-1;;;;;1953:28:0;;;;;;1982:11;1994:10;;;;:2;:10;:::i;:::-;1953:52;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;1921:84:0;-1:-1:-1;2012:18:0;;-1:-1:-1;2051:11:0;:2;;:11;:::i;:::-;:33;;;;;;;:::i;:::-;2033:51;;-1:-1:-1;;;;;2033:51:0;:15;:51;:::i;:::-;2012:72;-1:-1:-1;2133:22:0;2158:85;2197:11;:2;;:11;:::i;2158:85::-;2258:36;;-1:-1:-1;;;2258:36:0;;:13;:36;;;15537:25:25;15578:18;;;15571:34;;;2133:110:0;;-1:-1:-1;2258:20:0;;;;15510:18:25;;2258:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2257:37;2249:80;;;;-1:-1:-1;;;2249:80:0;;16995:2:25;2249:80:0;;;16977:21:25;17034:2;17014:18;;;17007:30;17073:33;17053:18;;;17046:61;17124:18;;2249:80:0;16793:355:25;2249:80:0;2627:19;;;2713:107;;;;2724:8;2713:107;:::i;:::-;2889:8;;2624:196;;-1:-1:-1;2624:196:0;;-1:-1:-1;2624:196:0;-1:-1:-1;2624:196:0;;-1:-1:-1;;;;;;;;2889:8:0;;;2874:23;;;;;;;;-1:-1:-1;2870:167:0;;-1:-1:-1;;;2870:167:0;2953:1;2915:26;;;:12;:26;;;;;;-1:-1:-1;;;;;2915:26:0;2907:77;;;;-1:-1:-1;;;2907:77:0;;18978:2:25;2907:77:0;;;18960:21:25;19017:2;18997:18;;;18990:30;19056:27;19036:18;;;19029:55;19101:18;;2907:77:0;18776:349:25;2907:77:0;-1:-1:-1;3004:26:0;;;;:12;:26;;;;;;-1:-1:-1;;;;;3004:26:0;2870:167;3071:42;;-1:-1:-1;;;3071:42:0;;:13;:42;;;19359:25:25;19400:18;;;19393:34;;;3108:4:0;19443:18:25;;;19436:50;3071:20:0;;;;19332:18:25;;3071:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3119:21;:9;1032:19:19;;1050:1;1032:19;;;945:123;3119:21:0;3147:17;3167:19;:9;918:14:19;;827:112;3167:19:0;3147:39;;3192:27;3198:9;3209;3192:5;:27::i;:::-;3225:64;3238:9;3274:13;3249:39;;;;;;;;:::i;:::-;;;;;;;;;;;;;3225:12;:64::i;:::-;3303:9;1661:1656;-1:-1:-1;;;;;;;;;;;;1661:1656:0:o;4169:153:12:-;4263:52;719:10:18;4296:8:12;4306;4263:18;:52::i;:::-;4169:153;;:::o;857:164:0:-;934:8;;-1:-1:-1;;;;;934:8:0;920:10;:22;912:76;;;;-1:-1:-1;;;912:76:0;;20130:2:25;912:76:0;;;20112:21:25;20169:2;20149:18;;;20142:30;20208:34;20188:18;;;20181:62;-1:-1:-1;;;20259:18:25;;;20252:40;20309:19;;912:76:0;19928:406:25;912:76:0;994:8;:22;;-1:-1:-1;;;;;;994:22:0;-1:-1:-1;;;;;994:22:0;;;;;;;;;;857:164::o;5189:276:12:-;5319:41;719:10:18;5352:7:12;5319:18;:41::i;:::-;5311:99;;;;-1:-1:-1;;;5311:99:12;;;;;;;:::i;:::-;5420:38;5434:4;5440:2;5444:7;5453:4;5420:13;:38::i;:::-;5189:276;;;;:::o;1285:372:0:-;1405:66;;8548::25;1405::0;;;8536:79:25;8631:12;;;8624:28;;;1380:12:0;;8668::25;;1405:66:0;;;-1:-1:-1;;1405:66:0;;;;;;;;;1395:77;;1405:66;1395:77;;;;1478:14;1495:27;;;;;;;;;8918:25:25;;;8991:4;8979:17;;8959:18;;;8952:45;;;;9013:18;;;9006:34;;;9056:18;;;9049:34;;;1395:77:0;;-1:-1:-1;1478:14:0;1495:27;;8890:19:25;;1495:27:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;1495:27:0;;-1:-1:-1;;1495:27:0;;1547:8;;1495:27;;-1:-1:-1;;;;;;1537:18:0;;;1547:8;;1537:18;;-1:-1:-1;1529:77:0;;;;-1:-1:-1;;;1529:77:0;;20541:2:25;1529:77:0;;;20523:21:25;20580:2;20560:18;;;20553:30;20619:34;20599:18;;;20592:62;-1:-1:-1;;;20670:18:25;;;20663:45;20725:19;;1529:77:0;20339:411:25;1529:77:0;-1:-1:-1;;;1613:26:0;;;;-1:-1:-1;;1613:12:0;:26;;;;;:39;;-1:-1:-1;;;;;;1613:39:0;1642:10;1613:39;;;1285:372::o;806:608:15:-;879:13;904:23;919:7;904:14;:23::i;:::-;938;964:19;;;:10;:19;;;;;938:45;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;993:18;1014:10;3395:9:12;;;;;;;;;-1:-1:-1;3395:9:12;;;3319:92;1014:10:15;993:31;;1103:4;1097:18;1119:1;1097:23;1093:70;;-1:-1:-1;1143:9:15;806:608;-1:-1:-1;;806:608:15:o;1093:70::-;1265:23;;:27;1261:106;;1339:4;1345:9;1322:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;1308:48;;;;806:608;;;:::o;1261:106::-;1384:23;1399:7;1384:14;:23::i;4388:162:12:-;-1:-1:-1;;;;;4508:25:12;;;4485:4;4508:25;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;;;4388:162::o;1570:300::-;1672:4;-1:-1:-1;;;;;;1707:40:12;;-1:-1:-1;;;1707:40:12;;:104;;-1:-1:-1;;;;;;;1763:48:12;;-1:-1:-1;;;1763:48:12;1707:104;:156;;;-1:-1:-1;;;;;;;;;;937:40:21;;;1827:36:12;829:155:21;13240:133:12;7185:4;6794:16;;;:7;:16;;;;;;-1:-1:-1;;;;;6794:16:12;13313:53;;;;-1:-1:-1;;;13313:53:12;;16232:2:25;13313:53:12;;;16214:21:25;16271:2;16251:18;;;16244:30;-1:-1:-1;;;16290:18:25;;;16283:54;16354:18;;13313:53:12;16030:348:25;13313:53:12;13240:133;:::o;12572:171::-;12646:24;;;;:15;:24;;;;;:29;;-1:-1:-1;;;;;;12646:29:12;-1:-1:-1;;;;;12646:29:12;;;;;;;;:24;;12699:23;12646:24;12699:14;:23::i;:::-;-1:-1:-1;;;;;12690:46:12;;;;;;;;;;;12572:171;;:::o;7404:261::-;7497:4;7513:13;7529:23;7544:7;7529:14;:23::i;:::-;7513:39;;7581:5;-1:-1:-1;;;;;7570:16:12;:7;-1:-1:-1;;;;;7570:16:12;;:52;;;;7590:32;7607:5;7614:7;7590:16;:32::i;:::-;7570:87;;;;7650:7;-1:-1:-1;;;;;7626:31:12;:20;7638:7;7626:11;:20::i;:::-;-1:-1:-1;;;;;7626:31:12;;7562:96;7404:261;-1:-1:-1;;;;7404:261:12:o;11257:1203::-;11381:4;-1:-1:-1;;;;;11354:31:12;:23;11369:7;11354:14;:23::i;:::-;-1:-1:-1;;;;;11354:31:12;;11346:81;;;;-1:-1:-1;;;11346:81:12;;;;;;;:::i;:::-;-1:-1:-1;;;;;11445:16:12;;11437:65;;;;-1:-1:-1;;;11437:65:12;;21864:2:25;11437:65:12;;;21846:21:25;21903:2;21883:18;;;21876:30;21942:34;21922:18;;;21915:62;-1:-1:-1;;;21993:18:25;;;21986:34;22037:19;;11437:65:12;21662:400:25;11437:65:12;11682:4;-1:-1:-1;;;;;11655:31:12;:23;11670:7;11655:14;:23::i;:::-;-1:-1:-1;;;;;11655:31:12;;11647:81;;;;-1:-1:-1;;;11647:81:12;;;;;;;:::i;:::-;11797:24;;;;:15;:24;;;;;;;;11790:31;;-1:-1:-1;;;;;;11790:31:12;;;;;;-1:-1:-1;;;;;12265:15:12;;;;;;:9;:15;;;;;:20;;-1:-1:-1;;12265:20:12;;;12299:13;;;;;;;;;:18;;11790:31;12299:18;;;12337:16;;;:7;:16;;;;;;:21;;;;;;;;;;12374:27;;11813:7;;12374:27;;;3538:336;3468:406;;:::o;8925:920::-;-1:-1:-1;;;;;9004:16:12;;8996:61;;;;-1:-1:-1;;;8996:61:12;;22269:2:25;8996:61:12;;;22251:21:25;;;22288:18;;;22281:30;22347:34;22327:18;;;22320:62;22399:18;;8996:61:12;22067:356:25;8996:61:12;7185:4;6794:16;;;:7;:16;;;;;;-1:-1:-1;;;;;6794:16:12;7208:31;9067:58;;;;-1:-1:-1;;;9067:58:12;;22630:2:25;9067:58:12;;;22612:21:25;22669:2;22649:18;;;22642:30;22708;22688:18;;;22681:58;22756:18;;9067:58:12;22428:352:25;9067:58:12;7185:4;6794:16;;;:7;:16;;;;;;-1:-1:-1;;;;;6794:16:12;7208:31;9271:58;;;;-1:-1:-1;;;9271:58:12;;22630:2:25;9271:58:12;;;22612:21:25;22669:2;22649:18;;;22642:30;22708;22688:18;;;22681:58;22756:18;;9271:58:12;22428:352:25;9271:58:12;-1:-1:-1;;;;;9671:13:12;;;;;;:9;:13;;;;;;;;:18;;9688:1;9671:18;;;9710:16;;;:7;:16;;;;;;:21;;-1:-1:-1;;;;;;9710:21:12;;;;;9747:33;9718:7;;9671:13;;9747:33;;9671:13;;9747:33;4169:153;;:::o;1599:253:15:-;7185:4:12;6794:16;;;:7;:16;;;;;;-1:-1:-1;;;;;6794:16:12;1690:75:15;;;;-1:-1:-1;;;1690:75:15;;22987:2:25;1690:75:15;;;22969:21:25;23026:2;23006:18;;;22999:30;23065:34;23045:18;;;23038:62;-1:-1:-1;;;23116:18:25;;;23109:44;23170:19;;1690:75:15;22785:410:25;1690:75:15;1775:19;;;;:10;:19;;;;;:31;1797:9;1775:19;:31;:::i;:::-;-1:-1:-1;1822:23:15;;4398:25:25;;;1822:23:15;;4386:2:25;4371:18;1822:23:15;;;;;;;1599:253;;:::o;12879:277:12:-;12999:8;-1:-1:-1;;;;;12990:17:12;:5;-1:-1:-1;;;;;12990:17:12;;12982:55;;;;-1:-1:-1;;;12982:55:12;;25606:2:25;12982:55:12;;;25588:21:25;25645:2;25625:18;;;25618:30;25684:27;25664:18;;;25657:55;25729:18;;12982:55:12;25404:349:25;12982:55:12;-1:-1:-1;;;;;13047:25:12;;;;;;;:18;:25;;;;;;;;:35;;;;;;;;;;;;;:46;;-1:-1:-1;;13047:46:12;;;;;;;;;;13108:41;;540::25;;;13108::12;;513:18:25;13108:41:12;;;;;;;12879:277;;;:::o;6326:267::-;6438:28;6448:4;6454:2;6458:7;6438:9;:28::i;:::-;6484:47;6507:4;6513:2;6517:7;6526:4;6484:22;:47::i;:::-;6476:110;;;;-1:-1:-1;;;6476:110:12;;;;;;;:::i;2801:276::-;2874:13;2899:23;2914:7;2899:14;:23::i;:::-;2933:21;2957:10;3395:9;;;;;;;;;-1:-1:-1;3395:9:12;;;3319:92;2957:10;2933:34;;3008:1;2990:7;2984:21;:25;:86;;;;;;;;;;;;;;;;;3036:7;3045:18;:7;:16;:18::i;:::-;3019:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;2984:86;2977:93;2801:276;-1:-1:-1;;;2801:276:12:o;13925:831::-;14074:4;-1:-1:-1;;;;;14094:13:12;;1702:19:17;:23;14090:660:12;;14129:71;;-1:-1:-1;;;14129:71:12;;-1:-1:-1;;;;;14129:36:12;;;;;:71;;719:10:18;;14180:4:12;;14186:7;;14195:4;;14129:71;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;-1:-1:-1;14129:71:12;;;;;;;;-1:-1:-1;;14129:71:12;;;;;;;;;;;;:::i;:::-;;;14125:573;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14367:6;:13;14384:1;14367:18;14363:321;;14409:60;;-1:-1:-1;;;14409:60:12;;;;;;;:::i;14363:321::-;14636:6;14630:13;14621:6;14617:2;14613:15;14606:38;14125:573;-1:-1:-1;;;;;;14250:51:12;-1:-1:-1;;;14250:51:12;;-1:-1:-1;14243:58:12;;14090:660;-1:-1:-1;14735:4:12;14728:11;;447:696:20;503:13;552:14;569:17;580:5;569:10;:17::i;:::-;589:1;569:21;552:38;;604:20;638:6;-1:-1:-1;;;;;627:18:20;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;627:18:20;-1:-1:-1;604:41:20;-1:-1:-1;765:28:20;;;781:2;765:28;820:280;-1:-1:-1;;851:5:20;-1:-1:-1;;;985:2:20;974:14;;969:30;851:5;956:44;1044:2;1035:11;;;-1:-1:-1;1064:21:20;820:280;1064:21;-1:-1:-1;1120:6:20;447:696;-1:-1:-1;;;447:696:20:o;10139:916:23:-;10192:7;;-1:-1:-1;;;10267:17:23;;10263:103;;-1:-1:-1;;;10304:17:23;;;-1:-1:-1;10349:2:23;10339:12;10263:103;10392:8;10383:5;:17;10379:103;;10429:8;10420:17;;;-1:-1:-1;10465:2:23;10455:12;10379:103;10508:8;10499:5;:17;10495:103;;10545:8;10536:17;;;-1:-1:-1;10581:2:23;10571:12;10495:103;10624:7;10615:5;:16;10611:100;;10660:7;10651:16;;;-1:-1:-1;10695:1:23;10685:11;10611:100;10737:7;10728:5;:16;10724:100;;10773:7;10764:16;;;-1:-1:-1;10808:1:23;10798:11;10724:100;10850:7;10841:5;:16;10837:100;;10886:7;10877:16;;;-1:-1:-1;10921:1:23;10911:11;10837:100;10963:7;10954:5;:16;10950:66;;11000:1;10990:11;11042:6;10139:916;-1:-1:-1;;10139:916:23:o;14:131:25:-;-1:-1:-1;;;;;;88:32:25;;78:43;;68:71;;135:1;132;125:12;150:245;208:6;261:2;249:9;240:7;236:23;232:32;229:52;;;277:1;274;267:12;229:52;316:9;303:23;335:30;359:5;335:30;:::i;592:250::-;677:1;687:113;701:6;698:1;695:13;687:113;;;777:11;;;771:18;758:11;;;751:39;723:2;716:10;687:113;;;-1:-1:-1;;834:1:25;816:16;;809:27;592:250::o;847:271::-;889:3;927:5;921:12;954:6;949:3;942:19;970:76;1039:6;1032:4;1027:3;1023:14;1016:4;1009:5;1005:16;970:76;:::i;:::-;1100:2;1079:15;-1:-1:-1;;1075:29:25;1066:39;;;;1107:4;1062:50;;847:271;-1:-1:-1;;847:271:25:o;1123:220::-;1272:2;1261:9;1254:21;1235:4;1292:45;1333:2;1322:9;1318:18;1310:6;1292:45;:::i;1348:180::-;1407:6;1460:2;1448:9;1439:7;1435:23;1431:32;1428:52;;;1476:1;1473;1466:12;1428:52;-1:-1:-1;1499:23:25;;1348:180;-1:-1:-1;1348:180:25:o;1741:131::-;-1:-1:-1;;;;;1816:31:25;;1806:42;;1796:70;;1862:1;1859;1852:12;1877:315;1945:6;1953;2006:2;1994:9;1985:7;1981:23;1977:32;1974:52;;;2022:1;2019;2012:12;1974:52;2061:9;2048:23;2080:31;2105:5;2080:31;:::i;:::-;2130:5;2182:2;2167:18;;;;2154:32;;-1:-1:-1;;;1877:315:25:o;2197:474::-;2281:6;2289;2297;2305;2358:3;2346:9;2337:7;2333:23;2329:33;2326:53;;;2375:1;2372;2365:12;2326:53;2411:9;2398:23;2388:33;;2468:2;2457:9;2453:18;2440:32;2430:42;;2519:2;2508:9;2504:18;2491:32;2481:42;;2573:2;2562:9;2558:18;2545:32;2617:4;2610:5;2606:16;2599:5;2596:27;2586:55;;2637:1;2634;2627:12;2586:55;2197:474;;;;-1:-1:-1;2197:474:25;;-1:-1:-1;;2197:474:25:o;2676:858::-;2779:6;2787;2795;2848:2;2836:9;2827:7;2823:23;2819:32;2816:52;;;2864:1;2861;2854:12;2816:52;2904:9;2891:23;-1:-1:-1;;;;;2974:2:25;2966:6;2963:14;2960:34;;;2990:1;2987;2980:12;2960:34;3028:6;3017:9;3013:22;3003:32;;3073:7;3066:4;3062:2;3058:13;3054:27;3044:55;;3095:1;3092;3085:12;3044:55;3135:2;3122:16;3161:2;3153:6;3150:14;3147:34;;;3177:1;3174;3167:12;3147:34;3224:7;3217:4;3208:6;3204:2;3200:15;3196:26;3193:39;3190:59;;;3245:1;3242;3235:12;3190:59;3276:4;3268:13;;;;-1:-1:-1;3300:6:25;-1:-1:-1;3344:20:25;;;3331:34;;3377:16;;;3374:36;;;3406:1;3403;3396:12;3374:36;-1:-1:-1;3429:24:25;;3487:2;3469:16;;;3465:25;3462:45;;;3503:1;3500;3493:12;3462:45;3526:2;3516:12;;;2676:858;;;;;:::o;3539:456::-;3616:6;3624;3632;3685:2;3673:9;3664:7;3660:23;3656:32;3653:52;;;3701:1;3698;3691:12;3653:52;3740:9;3727:23;3759:31;3784:5;3759:31;:::i;:::-;3809:5;-1:-1:-1;3866:2:25;3851:18;;3838:32;3879:33;3838:32;3879:33;:::i;:::-;3539:456;;3931:7;;-1:-1:-1;;;3985:2:25;3970:18;;;;3957:32;;3539:456::o;4000:247::-;4059:6;4112:2;4100:9;4091:7;4087:23;4083:32;4080:52;;;4128:1;4125;4118:12;4080:52;4167:9;4154:23;4186:31;4211:5;4186:31;:::i;4434:118::-;4520:5;4513:13;4506:21;4499:5;4496:32;4486:60;;4542:1;4539;4532:12;4557:382;4622:6;4630;4683:2;4671:9;4662:7;4658:23;4654:32;4651:52;;;4699:1;4696;4689:12;4651:52;4738:9;4725:23;4757:31;4782:5;4757:31;:::i;:::-;4807:5;-1:-1:-1;4864:2:25;4849:18;;4836:32;4877:30;4836:32;4877:30;:::i;:::-;4926:7;4916:17;;;4557:382;;;;;:::o;4944:127::-;5005:10;5000:3;4996:20;4993:1;4986:31;5036:4;5033:1;5026:15;5060:4;5057:1;5050:15;5076:631;5140:5;-1:-1:-1;;;;;5211:2:25;5203:6;5200:14;5197:40;;;5217:18;;:::i;:::-;5292:2;5286:9;5260:2;5346:15;;-1:-1:-1;;5342:24:25;;;5368:2;5338:33;5334:42;5322:55;;;5392:18;;;5412:22;;;5389:46;5386:72;;;5438:18;;:::i;:::-;5478:10;5474:2;5467:22;5507:6;5498:15;;5537:6;5529;5522:22;5577:3;5568:6;5563:3;5559:16;5556:25;5553:45;;;5594:1;5591;5584:12;5553:45;5644:6;5639:3;5632:4;5624:6;5620:17;5607:44;5699:1;5692:4;5683:6;5675;5671:19;5667:30;5660:41;;;;5076:631;;;;;:::o;5712:794::-;5807:6;5815;5823;5831;5884:3;5872:9;5863:7;5859:23;5855:33;5852:53;;;5901:1;5898;5891:12;5852:53;5940:9;5927:23;5959:31;5984:5;5959:31;:::i;:::-;6009:5;-1:-1:-1;6066:2:25;6051:18;;6038:32;6079:33;6038:32;6079:33;:::i;:::-;6131:7;-1:-1:-1;6185:2:25;6170:18;;6157:32;;-1:-1:-1;6240:2:25;6225:18;;6212:32;-1:-1:-1;;;;;6256:30:25;;6253:50;;;6299:1;6296;6289:12;6253:50;6322:22;;6375:4;6367:13;;6363:27;-1:-1:-1;6353:55:25;;6404:1;6401;6394:12;6353:55;6427:73;6492:7;6487:2;6474:16;6469:2;6465;6461:11;6427:73;:::i;:::-;6417:83;;;5712:794;;;;;;;:::o;6511:388::-;6579:6;6587;6640:2;6628:9;6619:7;6615:23;6611:32;6608:52;;;6656:1;6653;6646:12;6608:52;6695:9;6682:23;6714:31;6739:5;6714:31;:::i;:::-;6764:5;-1:-1:-1;6821:2:25;6806:18;;6793:32;6834:33;6793:32;6834:33;:::i;7089:380::-;7168:1;7164:12;;;;7211;;;7232:61;;7286:4;7278:6;7274:17;7264:27;;7232:61;7339:2;7331:6;7328:14;7308:18;7305:38;7302:161;;7385:10;7380:3;7376:20;7373:1;7366:31;7420:4;7417:1;7410:15;7448:4;7445:1;7438:15;7302:161;;7089:380;;;:::o;9094:266::-;9182:6;9177:3;9170:19;9234:6;9227:5;9220:4;9215:3;9211:14;9198:43;-1:-1:-1;9286:1:25;9261:16;;;9279:4;9257:27;;;9250:38;;;;9342:2;9321:15;;;-1:-1:-1;;9317:29:25;9308:39;;;9304:50;;9094:266::o;9365:171::-;9432:20;;-1:-1:-1;;;;;9481:30:25;;9471:41;;9461:69;;9526:1;9523;9516:12;9461:69;9365:171;;;:::o;9648:520::-;9718:5;9725:6;9785:3;9772:17;9871:2;9867:7;9856:8;9840:14;9836:29;9832:43;9812:18;9808:68;9798:96;;9890:1;9887;9880:12;9798:96;9918:33;;10022:4;10009:18;;;-1:-1:-1;9970:21:25;;-1:-1:-1;;;;;;10039:30:25;;10036:50;;;10082:1;10079;10072:12;10036:50;10136:6;10133:1;10129:14;10113;10109:35;10102:5;10098:47;10095:67;;;10158:1;10155;10148:12;10095:67;9648:520;;;;;:::o;10173:311::-;10261:19;;;10243:3;-1:-1:-1;;;;;10292:31:25;;10289:51;;;10336:1;10333;10326:12;10289:51;10372:6;10369:1;10365:14;10424:8;10417:5;10410:4;10405:3;10401:14;10388:45;10453:18;;;;10473:4;10449:29;;10173:311;-1:-1:-1;;;10173:311:25:o;10489:500::-;10547:5;10554:6;10614:3;10601:17;10700:2;10696:7;10685:8;10669:14;10665:29;10661:43;10641:18;10637:68;10627:96;;10719:1;10716;10709:12;10627:96;10747:33;;10851:4;10838:18;;;-1:-1:-1;10799:21:25;;-1:-1:-1;;;;;;10868:30:25;;10865:50;;;10911:1;10908;10901:12;10865:50;10958:6;10942:14;10938:27;10931:5;10927:39;10924:59;;;10979:1;10976;10969:12;10994:1867;11225:2;11214:9;11207:21;11188:4;11251:61;11308:2;11297:9;11293:18;11285:6;11277;11251:61;:::i;:::-;11360:9;11352:6;11348:22;11343:2;11332:9;11328:18;11321:50;11419:6;11406:20;11506:3;11502:8;11493:6;11477:14;11473:27;11469:42;11449:18;11445:67;11435:95;;11526:1;11523;11516:12;11435:95;11607:2;11592:18;;11552:31;;-1:-1:-1;;;;;11647:24:25;11552:31;11647:24;:::i;:::-;11643:49;11638:2;11630:6;11626:15;11619:74;11722:33;11751:2;11744:5;11740:14;11722:33;:::i;:::-;-1:-1:-1;;;;;9606:30:25;;11808:2;11796:15;;9594:43;11764:48;11870:2;11863:5;11859:14;11846:28;11840:3;11832:6;11828:16;11821:54;11933:2;11926:5;11922:14;11909:28;11903:3;11895:6;11891:16;11884:54;11996:3;11989:5;11985:15;11972:29;11966:3;11958:6;11954:16;11947:55;12060:3;12053:5;12049:15;12036:29;12030:3;12022:6;12018:16;12011:55;12111:66;12172:3;12165:5;12161:15;12154:5;12111:66;:::i;:::-;12196:6;12218:15;;;12211:27;12261:85;12341:3;12329:16;;12315:12;12299:14;12261:85;:::i;:::-;12247:99;;;12393:66;12454:3;12447:5;12443:15;12436:5;12393:66;:::i;:::-;12497:19;;;-1:-1:-1;;12493:33:25;12487:3;12475:16;;12468:59;12355:104;-1:-1:-1;12547:77:25;12501:6;12355:104;12585:14;12547:77;:::i;:::-;12536:88;;;;12671:55;12722:2;12714:6;12710:15;12702:6;12671:55;:::i;:::-;12768:6;12763:3;12759:16;12754:2;12746:6;12742:15;12735:41;12793:62;12851:3;12835:14;12819;12793:62;:::i;:::-;12785:70;10994:1867;-1:-1:-1;;;;;;;;;10994:1867:25:o;12866:245::-;12933:6;12986:2;12974:9;12965:7;12961:23;12957:32;12954:52;;;13002:1;12999;12992:12;12954:52;13034:9;13028:16;13053:28;13075:5;13053:28;:::i;13116:269::-;13204:6;13257:2;13245:9;13236:7;13232:23;13228:32;13225:52;;;13273:1;13270;13263:12;13225:52;13305:9;13299:16;13324:31;13349:5;13324:31;:::i;13390:521::-;13467:4;13473:6;13533:11;13520:25;13627:2;13623:7;13612:8;13596:14;13592:29;13588:43;13568:18;13564:68;13554:96;;13646:1;13643;13636:12;13554:96;13673:33;;13725:20;;;-1:-1:-1;;;;;;13757:30:25;;13754:50;;;13800:1;13797;13790:12;13754:50;13833:4;13821:17;;-1:-1:-1;13864:14:25;13860:27;;;13850:38;;13847:58;;;13901:1;13898;13891:12;13916:341;-1:-1:-1;;;;;14101:32:25;;14083:51;;14170:2;14165;14150:18;;14143:30;;;-1:-1:-1;;14190:61:25;;14232:18;;14224:6;14216;14190:61;:::i;:::-;14182:69;13916:341;-1:-1:-1;;;;;13916:341:25:o;14262:306::-;14350:6;14358;14366;14419:2;14407:9;14398:7;14394:23;14390:32;14387:52;;;14435:1;14432;14425:12;14387:52;14464:9;14458:16;14448:26;;14514:2;14503:9;14499:18;14493:25;14483:35;;14558:2;14547:9;14543:18;14537:25;14527:35;;14262:306;;;;;:::o;14573:336::-;14677:4;14735:11;14722:25;14829:3;14825:8;14814;14798:14;14794:29;14790:44;14770:18;14766:69;14756:97;;14849:1;14846;14839:12;14756:97;14870:33;;;;;14573:336;-1:-1:-1;;14573:336:25:o;14914:184::-;14972:6;15025:2;15013:9;15004:7;15000:23;14996:32;14993:52;;;15041:1;15038;15031:12;14993:52;15064:28;15082:9;15064:28;:::i;15103:222::-;15168:9;;;15189:10;;;15186:133;;;15241:10;15236:3;15232:20;15229:1;15222:31;15276:4;15273:1;15266:15;15304:4;15301:1;15294:15;15616:409;15818:2;15800:21;;;15857:2;15837:18;;;15830:30;15896:34;15891:2;15876:18;;15869:62;-1:-1:-1;;;15962:2:25;15947:18;;15940:43;16015:3;16000:19;;15616:409::o;17153:142::-;17229:20;;17258:31;17229:20;17258:31;:::i;17300:221::-;17343:5;17396:3;17389:4;17381:6;17377:17;17373:27;17363:55;;17414:1;17411;17404:12;17363:55;17436:79;17511:3;17502:6;17489:20;17482:4;17474:6;17470:17;17436:79;:::i;17526:1245::-;17701:6;17709;17717;17725;17733;17741;17749;17757;17765;17773;17826:3;17814:9;17805:7;17801:23;17797:33;17794:53;;;17843:1;17840;17833:12;17794:53;17879:9;17866:23;17856:33;;17908:46;17950:2;17939:9;17935:18;17908:46;:::i;:::-;17898:56;;18001:2;17990:9;17986:18;17973:32;17963:42;;18052:2;18041:9;18037:18;18024:32;18014:42;;18103:3;18092:9;18088:19;18075:33;18065:43;;18155:3;18144:9;18140:19;18127:33;18117:43;;18211:3;18200:9;18196:19;18183:33;-1:-1:-1;;;;;18276:2:25;18268:6;18265:14;18262:34;;;18292:1;18289;18282:12;18262:34;18315:50;18357:7;18348:6;18337:9;18333:22;18315:50;:::i;:::-;18305:60;;18418:3;18407:9;18403:19;18390:33;18374:49;;18448:2;18438:8;18435:16;18432:36;;;18464:1;18461;18454:12;18432:36;18487:52;18531:7;18520:8;18509:9;18505:24;18487:52;:::i;:::-;18477:62;;18592:3;18581:9;18577:19;18564:33;18548:49;;18622:2;18612:8;18609:16;18606:36;;;18638:1;18635;18628:12;18606:36;;18661:52;18705:7;18694:8;18683:9;18679:24;18661:52;:::i;:::-;18651:62;;;18760:3;18749:9;18745:19;18732:33;18722:43;;17526:1245;;;;;;;;;;;;;:::o;19497:426::-;-1:-1:-1;;;19743:3:25;19736:22;19718:3;19787:6;19781:13;19803:74;19870:6;19866:1;19861:3;19857:11;19850:4;19842:6;19838:17;19803:74;:::i;:::-;19897:16;;;;19915:1;19893:24;;19497:426;-1:-1:-1;;19497:426:25:o;20755:496::-;20934:3;20972:6;20966:13;20988:66;21047:6;21042:3;21035:4;21027:6;21023:17;20988:66;:::i;:::-;21117:13;;21076:16;;;;21139:70;21117:13;21076:16;21186:4;21174:17;;21139:70;:::i;:::-;21225:20;;20755:496;-1:-1:-1;;;;20755:496:25:o;21256:401::-;21458:2;21440:21;;;21497:2;21477:18;;;21470:30;21536:34;21531:2;21516:18;;21509:62;-1:-1:-1;;;21602:2:25;21587:18;;21580:35;21647:3;21632:19;;21256:401::o;23326:545::-;23428:2;23423:3;23420:11;23417:448;;;23464:1;23489:5;23485:2;23478:17;23534:4;23530:2;23520:19;23604:2;23592:10;23588:19;23585:1;23581:27;23575:4;23571:38;23640:4;23628:10;23625:20;23622:47;;;-1:-1:-1;23663:4:25;23622:47;23718:2;23713:3;23709:12;23706:1;23702:20;23696:4;23692:31;23682:41;;23773:82;23791:2;23784:5;23781:13;23773:82;;;23836:17;;;23817:1;23806:13;23773:82;;;23777:3;;;23326:545;;;:::o;24047:1352::-;24173:3;24167:10;-1:-1:-1;;;;;24192:6:25;24189:30;24186:56;;;24222:18;;:::i;:::-;24251:97;24341:6;24301:38;24333:4;24327:11;24301:38;:::i;:::-;24295:4;24251:97;:::i;:::-;24403:4;;24467:2;24456:14;;24484:1;24479:663;;;;25186:1;25203:6;25200:89;;;-1:-1:-1;25255:19:25;;;25249:26;25200:89;-1:-1:-1;;24004:1:25;24000:11;;;23996:24;23992:29;23982:40;24028:1;24024:11;;;23979:57;25302:81;;24449:944;;24479:663;23273:1;23266:14;;;23310:4;23297:18;;-1:-1:-1;;24515:20:25;;;24633:236;24647:7;24644:1;24641:14;24633:236;;;24736:19;;;24730:26;24715:42;;24828:27;;;;24796:1;24784:14;;;;24663:19;;24633:236;;;24637:3;24897:6;24888:7;24885:19;24882:201;;;24958:19;;;24952:26;-1:-1:-1;;25041:1:25;25037:14;;;25053:3;25033:24;25029:37;25025:42;25010:58;24995:74;;24882:201;-1:-1:-1;;;;;25129:1:25;25113:14;;;25109:22;25096:36;;-1:-1:-1;24047:1352:25:o;25758:414::-;25960:2;25942:21;;;25999:2;25979:18;;;25972:30;26038:34;26033:2;26018:18;;26011:62;-1:-1:-1;;;26104:2:25;26089:18;;26082:48;26162:3;26147:19;;25758:414::o;26177:489::-;-1:-1:-1;;;;;26446:15:25;;;26428:34;;26498:15;;26493:2;26478:18;;26471:43;26545:2;26530:18;;26523:34;;;26593:3;26588:2;26573:18;;26566:31;;;26371:4;;26614:46;;26640:19;;26632:6;26614:46;:::i;:::-;26606:54;26177:489;-1:-1:-1;;;;;;26177:489:25:o;26671:249::-;26740:6;26793:2;26781:9;26772:7;26768:23;26764:32;26761:52;;;26809:1;26806;26799:12;26761:52;26841:9;26835:16;26860:30;26884:5;26860:30;:::i", + "linkReferences": {} + }, + "methodIdentifiers": { + "approve(address,uint256)": "095ea7b3", + "balanceOf(address)": "70a08231", + "ckeckMinted(bytes,((uint64,uint64,bytes32,bytes32,bytes32,bytes32,bytes32[],bytes32[]),bytes))": "1926dbe0", + "dappAddress()": "1a721b7b", + "gamelogOwner(bytes32)": "eadc7463", + "getApproved(uint256)": "081812fc", + "isApprovedForAll(address,address)": "e985e9c5", + "mint(bytes,((uint64,uint64,bytes32,bytes32,bytes32,bytes32,bytes32[],bytes32[]),bytes))": "9da52e25", + "name()": "06fdde03", + "operator()": "570ca735", + "ownerOf(uint256)": "6352211e", + "safeTransferFrom(address,address,uint256)": "42842e0e", + "safeTransferFrom(address,address,uint256,bytes)": "b88d4fde", + "setApprovalForAll(address,bool)": "a22cb465", + "setGameplayOwner(bytes32,bytes32,bytes32,uint8)": "c521030a", + "setOperator(address)": "b3ab15fb", + "supportsInterface(bytes4)": "01ffc9a7", + "symbol()": "95d89b41", + "tokenURI(uint256)": "c87b56dd", + "transferFrom(address,address,uint256)": "23b872dd", + "verifySignature(bytes32,bytes32,bytes32,uint8)": "0d413d62" + }, + "rawMetadata": "{\"compiler\":{\"version\":\"0.8.21+commit.d9974bed\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dappAddress\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approved\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_fromTokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_toTokenId\",\"type\":\"uint256\"}],\"name\":\"BatchMetadataUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"MetadataUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_payload\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"inputIndexWithinEpoch\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"outputIndexWithinInput\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"outputHashesRootHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"vouchersEpochRootHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"noticesEpochRootHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"machineStateHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"outputHashInOutputHashesSiblings\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"outputHashesInEpochSiblings\",\"type\":\"bytes32[]\"}],\"internalType\":\"struct OutputValidityProof\",\"name\":\"validity\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"internalType\":\"struct Proof\",\"name\":\"_v\",\"type\":\"tuple\"}],\"name\":\"ckeckMinted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dappAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"gamelogOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_payload\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"uint64\",\"name\":\"inputIndexWithinEpoch\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"outputIndexWithinInput\",\"type\":\"uint64\"},{\"internalType\":\"bytes32\",\"name\":\"outputHashesRootHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"vouchersEpochRootHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"noticesEpochRootHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"machineStateHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"outputHashInOutputHashesSiblings\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"outputHashesInEpochSiblings\",\"type\":\"bytes32[]\"}],\"internalType\":\"struct OutputValidityProof\",\"name\":\"validity\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"internalType\":\"struct Proof\",\"name\":\"_v\",\"type\":\"tuple\"}],\"name\":\"mint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"gameplayHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"}],\"name\":\"setGameplayOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOperator\",\"type\":\"address\"}],\"name\":\"setOperator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"gameplayHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"_s\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_v\",\"type\":\"uint8\"}],\"name\":\"verifySignature\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"Approval(address,address,uint256)\":{\"details\":\"Emitted when `owner` enables `approved` to manage the `tokenId` token.\"},\"ApprovalForAll(address,address,bool)\":{\"details\":\"Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\"},\"BatchMetadataUpdate(uint256,uint256)\":{\"details\":\"This event emits when the metadata of a range of tokens is changed. So that the third-party platforms such as NFT market could timely update the images and related attributes of the NFTs.\"},\"MetadataUpdate(uint256)\":{\"details\":\"This event emits when the metadata of a token is changed. So that the third-party platforms such as NFT market could timely update the images and related attributes of the NFT.\"},\"Transfer(address,address,uint256)\":{\"details\":\"Emitted when `tokenId` token is transferred from `from` to `to`.\"}},\"kind\":\"dev\",\"methods\":{\"approve(address,uint256)\":{\"details\":\"See {IERC721-approve}.\"},\"balanceOf(address)\":{\"details\":\"See {IERC721-balanceOf}.\"},\"getApproved(uint256)\":{\"details\":\"See {IERC721-getApproved}.\"},\"isApprovedForAll(address,address)\":{\"details\":\"See {IERC721-isApprovedForAll}.\"},\"name()\":{\"details\":\"See {IERC721Metadata-name}.\"},\"ownerOf(uint256)\":{\"details\":\"See {IERC721-ownerOf}.\"},\"safeTransferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"safeTransferFrom(address,address,uint256,bytes)\":{\"details\":\"See {IERC721-safeTransferFrom}.\"},\"setApprovalForAll(address,bool)\":{\"details\":\"See {IERC721-setApprovalForAll}.\"},\"supportsInterface(bytes4)\":{\"details\":\"See {IERC165-supportsInterface}\"},\"symbol()\":{\"details\":\"See {IERC721Metadata-symbol}.\"},\"tokenURI(uint256)\":{\"details\":\"See {IERC721Metadata-tokenURI}.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC721-transferFrom}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RivesScoreNFT.sol\":\"RivesScoreNFT\"},\"evmVersion\":\"paris\",\"libraries\":{\"node_modules/@cartesi/util/contracts/Bitmask.sol:Bitmask\":\"0xf5b2d8c81cde4d6238bbf20d3d77db37df13f735\"},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@cartesi/=node_modules/@cartesi/\",\":@openzeppelin/=node_modules/@openzeppelin/\"]},\"sources\":{\"contracts/RivesScoreNFT.sol\":{\"keccak256\":\"0x8d4d2a18874f4098bd889a69bf7dc2395fc2eef52da8fbe5d78068fdc98ddc2f\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://de5305f0c63b98d7030c0cf15e0fc8aa2b8c14dc5a9d629e7d4e853a35bd32df\",\"dweb:/ipfs/QmWBeHgXeRFaUdHhSLzuUH7KrW9nWmzVP5c3rFAx7smJum\"]},\"node_modules/@cartesi/rollups/contracts/common/CanonicalMachine.sol\":{\"keccak256\":\"0x97cdce56cdb4f0b4164e6be3a72e50469a3124e4716e753a1792aa70eac614f5\",\"license\":\"Apache-2.0 (see LICENSE)\",\"urls\":[\"bzz-raw://13fafb8a608e91ccc8ad45ed726653a747230dba68c75c1a703ad97a34d1cab4\",\"dweb:/ipfs/QmcXcodi2AXPonqK4Wq3Nwhdetdb3ekFHyyPnNiGKmaPtp\"]},\"node_modules/@cartesi/rollups/contracts/common/OutputEncoding.sol\":{\"keccak256\":\"0xfbf8bd40a11aeb380c77910ef7a8c3a4b358dddbd8bc795529de39c955dd6f60\",\"license\":\"Apache-2.0 (see LICENSE)\",\"urls\":[\"bzz-raw://5cde345faa3b6e4b03fea0c6dd6cfb253896e4d56275033e40991845de9be482\",\"dweb:/ipfs/QmZJLbZd96zk6iFbiwDJJd86Ba8cGfFELxDEkddyE8pQf6\"]},\"node_modules/@cartesi/rollups/contracts/consensus/IConsensus.sol\":{\"keccak256\":\"0xc9d295fada66eb0602e0f1e2e236708e52f959927abb4ab6b04173a98b92ac16\",\"license\":\"Apache-2.0 (see LICENSE)\",\"urls\":[\"bzz-raw://938b7320d6b5f473aa03fc4869b461f4ecec0521080289e60140387eec230078\",\"dweb:/ipfs/Qmafmt2E67LdTg42GVUREcbtPwpxypNE3oy2fqT6xhq32S\"]},\"node_modules/@cartesi/rollups/contracts/dapp/ICartesiDApp.sol\":{\"keccak256\":\"0x7bb375a4deb593af06955bbf1d88e096f4288f25fa032349796f93705d29386f\",\"license\":\"Apache-2.0 (see LICENSE)\",\"urls\":[\"bzz-raw://cd27b67185529548a4ff6c79d8986c8d4835f11734b22e6428d53418ee419d50\",\"dweb:/ipfs/QmbAugeQFMdar72nhaQ8eYPD5kPueVFZVPNfC535gHdwV9\"]},\"node_modules/@cartesi/rollups/contracts/library/LibOutputValidation.sol\":{\"keccak256\":\"0x874ef478bd265acc94f2480a97191da907f05c6b46dc9e901c534b6acab14e03\",\"license\":\"Apache-2.0 (see LICENSE)\",\"urls\":[\"bzz-raw://90f8f8b21527b0c0a350c149eb63103efb88d26eb5c5661d6900d543ffe309cb\",\"dweb:/ipfs/QmSnGpTvxWXQcrUpc17VJUUDXRexKBDu5L72uTuwVGuReV\"]},\"node_modules/@cartesi/util/contracts/Bitmask.sol\":{\"keccak256\":\"0x606a3967f7444ce1dc07726e6c5cdcf48360000817c65b631e6ebd8fb96f6e1d\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://2dc07191df3d2ed53f604baebc32ce812719c0e1795fb069389d96350657c5e3\",\"dweb:/ipfs/QmQJwpquB7TdxgPJAMzMEiA9RajHrsqCGJMLn9zKSfeb22\"]},\"node_modules/@cartesi/util/contracts/CartesiMathV2.sol\":{\"keccak256\":\"0x98fb8d20c05b7c39c44171b6c524cf023da646749eb90157463538da8b2e13d3\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://35f6eba6b664963e3b4ef20c0428c6a833b6106ca7afcd01d513b3e54ac4a046\",\"dweb:/ipfs/QmaVmZUJEVyG4YupH1dxroJ3m6yaere7JX9BPgP1a8zdeb\"]},\"node_modules/@cartesi/util/contracts/MerkleV2.sol\":{\"keccak256\":\"0x73d86cb2dfa2ca887987c6da8d193d523c6a65ea89e296d1f47f190ebda7fa9b\",\"license\":\"Apache-2.0\",\"urls\":[\"bzz-raw://484b9a86375d8515766fe5b52947c41a5245f53c380f4c78c0bdd079665ae136\",\"dweb:/ipfs/QmeMeKokxHUh5opFpi58otQoHkyA9A3TkWAUbCruZyYZk3\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0xd04b0f06e0666f29cf7cccc82894de541e19bb30a765b107b1e40bb7fe5f7d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7b652499d098e88d8d878374616bb58434301061cae2253298b3f374044e0ddb\",\"dweb:/ipfs/QmbhAzctqo5jrSKU6idHdVyqfmzCcDbNUPvmx4GiXxfA6q\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC4906.sol\":{\"keccak256\":\"0x2a9dadb806be80dd451821f1f1190eb9aa6f6edae85b185db29d60767cc0c5f4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://5c25cac8dbe5bd96320053d23c3dacdb875e629d7c53ac00892eb7aa8500bde6\",\"dweb:/ipfs/Qmaf2oqbxxdJA9DphAoH4UCb8aXEAVM8fnu6qMxHJ5ta4A\"]},\"node_modules/@openzeppelin/contracts/interfaces/IERC721.sol\":{\"keccak256\":\"0xaf297d12d8d4a57fe01a70f0ef38908f208e3faedc577056d0b728fa2f3ccf0c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fbfaf37123958822a2720a4ea29651be00edab787540b770f73d3e025d286ff8\",\"dweb:/ipfs/QmbzgWeTm8hJVUqWrNAwFjshqbYVyeGpQA8D1huzxQdmw6\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol\":{\"keccak256\":\"0x2c309e7df9e05e6ce15bedfe74f3c61b467fc37e0fae9eab496acf5ea0bbd7ff\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7063b5c98711a98018ba4635ac74cee1c1cfa2ea01099498e062699ed9530005\",\"dweb:/ipfs/QmeJ8rGXkcv7RrqLdAW8PCXPAykxVsddfYY6g5NaTwmRFE\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"keccak256\":\"0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7e66dfde185df46104c11bc89d08fa0760737aa59a2b8546a656473d810a8ea4\",\"dweb:/ipfs/QmXvyqtXPaPss2PD7eqPoSao5Szm2n6UMoiG8TZZDjmChR\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6e75cf83beb757b8855791088546b8337e9d4684e169400c20d44a515353b708\",\"dweb:/ipfs/QmYvPafLfoquiDMEj7CKHtvbgHu7TJNPSVPSCjrtjV8HjV\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol\":{\"keccak256\":\"0x7942989e3525aec1672469e4c65fb33fbd19c785c9cadbcb70fcbe1fe8bfdd37\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6c9f260258c2be0e3b75f8ca285872c4bfa3a8fc97fdc2e62366c78abf22b54f\",\"dweb:/ipfs/QmTg1DMNwCDj8NVi6i1noqx7cxuRdPP4VyW4fzDkKAKmH2\"]},\"node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\":{\"keccak256\":\"0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a0a107160525724f9e1bbbab031defc2f298296dd9e331f16a6f7130cec32146\",\"dweb:/ipfs/QmemujxSd7gX8A9M8UwmNbz4Ms3U9FG9QfudUgxwvTmPWf\"]},\"node_modules/@openzeppelin/contracts/utils/Address.sol\":{\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://2455248c8ddd9cc6a7af76a13973cddf222072427e7b0e2a7d1aff345145e931\",\"dweb:/ipfs/QmfYjnjRbWqYpuxurqveE6HtzsY1Xx323J428AKQgtBJZm\"]},\"node_modules/@openzeppelin/contracts/utils/Context.sol\":{\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92\",\"dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3\"]},\"node_modules/@openzeppelin/contracts/utils/Counters.sol\":{\"keccak256\":\"0xf0018c2440fbe238dd3a8732fa8e17a0f9dce84d31451dc8a32f6d62b349c9f1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://59e1c62884d55b70f3ae5432b44bb3166ad71ae3acd19c57ab6ddc3c87c325ee\",\"dweb:/ipfs/QmezuXg5GK5oeA4F91EZhozBFekhq5TD966bHPH18cCqhu\"]},\"node_modules/@openzeppelin/contracts/utils/Strings.sol\":{\"keccak256\":\"0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b81d9ff6559ea5c47fc573e17ece6d9ba5d6839e213e6ebc3b4c5c8fe4199d7f\",\"dweb:/ipfs/QmPCW1bFisUzJkyjroY3yipwfism9RRCigCcK1hbXtVM8n\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://fb0048dee081f6fffa5f74afc3fb328483c2a30504e94a0ddd2a5114d731ec4d\",\"dweb:/ipfs/QmZptt1nmYoA5SgjwnSgWqgUSDgm4q52Yos3xhnMv3MV43\"]},\"node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f\",\"dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy\"]},\"node_modules/@openzeppelin/contracts/utils/math/Math.sol\":{\"keccak256\":\"0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://cc8841b3cd48ad125e2f46323c8bad3aa0e88e399ec62acb9e57efa7e7c8058c\",\"dweb:/ipfs/QmSqE4mXHA2BXW58deDbXE8MTcsL5JSKNDbm23sVQxRLPS\"]},\"node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol\":{\"keccak256\":\"0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c50fcc459e49a9858b6d8ad5f911295cb7c9ab57567845a250bf0153f84a95c7\",\"dweb:/ipfs/QmcEW85JRzvDkQggxiBBLVAasXWdkhEysqypj9EaB6H2g6\"]}},\"version\":1}", + "metadata": { + "compiler": { + "version": "0.8.21+commit.d9974bed" + }, + "language": "Solidity", + "output": { + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_dappAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "approved", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256", + "indexed": true + } + ], + "type": "event", + "name": "Approval", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "operator", + "type": "address", + "indexed": true + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool", + "indexed": false + } + ], + "type": "event", + "name": "ApprovalForAll", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_fromTokenId", + "type": "uint256", + "indexed": false + }, + { + "internalType": "uint256", + "name": "_toTokenId", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "BatchMetadataUpdate", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256", + "indexed": false + } + ], + "type": "event", + "name": "MetadataUpdate", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address", + "indexed": true + }, + { + "internalType": "address", + "name": "to", + "type": "address", + "indexed": true + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256", + "indexed": true + } + ], + "type": "event", + "name": "Transfer", + "anonymous": false + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "approve" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_payload", + "type": "bytes" + }, + { + "internalType": "struct Proof", + "name": "_v", + "type": "tuple", + "components": [ + { + "internalType": "struct OutputValidityProof", + "name": "validity", + "type": "tuple", + "components": [ + { + "internalType": "uint64", + "name": "inputIndexWithinEpoch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "outputIndexWithinInput", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "outputHashesRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "vouchersEpochRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "noticesEpochRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "machineStateHash", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "outputHashInOutputHashesSiblings", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "outputHashesInEpochSiblings", + "type": "bytes32[]" + } + ] + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + } + ] + } + ], + "stateMutability": "view", + "type": "function", + "name": "ckeckMinted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "dappAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function", + "name": "gamelogOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "name": "getApproved", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function", + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_payload", + "type": "bytes" + }, + { + "internalType": "struct Proof", + "name": "_v", + "type": "tuple", + "components": [ + { + "internalType": "struct OutputValidityProof", + "name": "validity", + "type": "tuple", + "components": [ + { + "internalType": "uint64", + "name": "inputIndexWithinEpoch", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "outputIndexWithinInput", + "type": "uint64" + }, + { + "internalType": "bytes32", + "name": "outputHashesRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "vouchersEpochRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "noticesEpochRootHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "machineStateHash", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "outputHashInOutputHashesSiblings", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "outputHashesInEpochSiblings", + "type": "bytes32[]" + } + ] + }, + { + "internalType": "bytes", + "name": "context", + "type": "bytes" + } + ] + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "operator", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "name": "ownerOf", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "safeTransferFrom" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "safeTransferFrom" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setApprovalForAll" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "gameplayHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_s", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "_v", + "type": "uint8" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setGameplayOwner" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOperator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "setOperator" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "stateMutability": "view", + "type": "function", + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ] + }, + { + "inputs": [], + "stateMutability": "view", + "type": "function", + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ] + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function", + "name": "tokenURI", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ] + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function", + "name": "transferFrom" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "gameplayHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "_s", + "type": "bytes32" + }, + { + "internalType": "uint8", + "name": "_v", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function", + "name": "verifySignature", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ] + } + ], + "devdoc": { + "kind": "dev", + "methods": { + "approve(address,uint256)": { + "details": "See {IERC721-approve}." + }, + "balanceOf(address)": { + "details": "See {IERC721-balanceOf}." + }, + "getApproved(uint256)": { + "details": "See {IERC721-getApproved}." + }, + "isApprovedForAll(address,address)": { + "details": "See {IERC721-isApprovedForAll}." + }, + "name()": { + "details": "See {IERC721Metadata-name}." + }, + "ownerOf(uint256)": { + "details": "See {IERC721-ownerOf}." + }, + "safeTransferFrom(address,address,uint256)": { + "details": "See {IERC721-safeTransferFrom}." + }, + "safeTransferFrom(address,address,uint256,bytes)": { + "details": "See {IERC721-safeTransferFrom}." + }, + "setApprovalForAll(address,bool)": { + "details": "See {IERC721-setApprovalForAll}." + }, + "supportsInterface(bytes4)": { + "details": "See {IERC165-supportsInterface}" + }, + "symbol()": { + "details": "See {IERC721Metadata-symbol}." + }, + "tokenURI(uint256)": { + "details": "See {IERC721Metadata-tokenURI}." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC721-transferFrom}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + } + }, + "settings": { + "remappings": [ + "@cartesi/=node_modules/@cartesi/", + "@openzeppelin/=node_modules/@openzeppelin/" + ], + "optimizer": { + "enabled": true, + "runs": 200 + }, + "metadata": { + "bytecodeHash": "ipfs" + }, + "compilationTarget": { + "contracts/RivesScoreNFT.sol": "RivesScoreNFT" + }, + "libraries": { + "node_modules/@cartesi/util/contracts/Bitmask.sol:Bitmask": "0xf5b2d8c81cde4d6238bbf20d3d77db37df13f735" + } + }, + "sources": { + "contracts/RivesScoreNFT.sol": { + "keccak256": "0x8d4d2a18874f4098bd889a69bf7dc2395fc2eef52da8fbe5d78068fdc98ddc2f", + "urls": [ + "bzz-raw://de5305f0c63b98d7030c0cf15e0fc8aa2b8c14dc5a9d629e7d4e853a35bd32df", + "dweb:/ipfs/QmWBeHgXeRFaUdHhSLzuUH7KrW9nWmzVP5c3rFAx7smJum" + ], + "license": "Apache-2.0" + }, + "node_modules/@cartesi/rollups/contracts/common/CanonicalMachine.sol": { + "keccak256": "0x97cdce56cdb4f0b4164e6be3a72e50469a3124e4716e753a1792aa70eac614f5", + "urls": [ + "bzz-raw://13fafb8a608e91ccc8ad45ed726653a747230dba68c75c1a703ad97a34d1cab4", + "dweb:/ipfs/QmcXcodi2AXPonqK4Wq3Nwhdetdb3ekFHyyPnNiGKmaPtp" + ], + "license": "Apache-2.0 (see LICENSE)" + }, + "node_modules/@cartesi/rollups/contracts/common/OutputEncoding.sol": { + "keccak256": "0xfbf8bd40a11aeb380c77910ef7a8c3a4b358dddbd8bc795529de39c955dd6f60", + "urls": [ + "bzz-raw://5cde345faa3b6e4b03fea0c6dd6cfb253896e4d56275033e40991845de9be482", + "dweb:/ipfs/QmZJLbZd96zk6iFbiwDJJd86Ba8cGfFELxDEkddyE8pQf6" + ], + "license": "Apache-2.0 (see LICENSE)" + }, + "node_modules/@cartesi/rollups/contracts/consensus/IConsensus.sol": { + "keccak256": "0xc9d295fada66eb0602e0f1e2e236708e52f959927abb4ab6b04173a98b92ac16", + "urls": [ + "bzz-raw://938b7320d6b5f473aa03fc4869b461f4ecec0521080289e60140387eec230078", + "dweb:/ipfs/Qmafmt2E67LdTg42GVUREcbtPwpxypNE3oy2fqT6xhq32S" + ], + "license": "Apache-2.0 (see LICENSE)" + }, + "node_modules/@cartesi/rollups/contracts/dapp/ICartesiDApp.sol": { + "keccak256": "0x7bb375a4deb593af06955bbf1d88e096f4288f25fa032349796f93705d29386f", + "urls": [ + "bzz-raw://cd27b67185529548a4ff6c79d8986c8d4835f11734b22e6428d53418ee419d50", + "dweb:/ipfs/QmbAugeQFMdar72nhaQ8eYPD5kPueVFZVPNfC535gHdwV9" + ], + "license": "Apache-2.0 (see LICENSE)" + }, + "node_modules/@cartesi/rollups/contracts/library/LibOutputValidation.sol": { + "keccak256": "0x874ef478bd265acc94f2480a97191da907f05c6b46dc9e901c534b6acab14e03", + "urls": [ + "bzz-raw://90f8f8b21527b0c0a350c149eb63103efb88d26eb5c5661d6900d543ffe309cb", + "dweb:/ipfs/QmSnGpTvxWXQcrUpc17VJUUDXRexKBDu5L72uTuwVGuReV" + ], + "license": "Apache-2.0 (see LICENSE)" + }, + "node_modules/@cartesi/util/contracts/Bitmask.sol": { + "keccak256": "0x606a3967f7444ce1dc07726e6c5cdcf48360000817c65b631e6ebd8fb96f6e1d", + "urls": [ + "bzz-raw://2dc07191df3d2ed53f604baebc32ce812719c0e1795fb069389d96350657c5e3", + "dweb:/ipfs/QmQJwpquB7TdxgPJAMzMEiA9RajHrsqCGJMLn9zKSfeb22" + ], + "license": "Apache-2.0" + }, + "node_modules/@cartesi/util/contracts/CartesiMathV2.sol": { + "keccak256": "0x98fb8d20c05b7c39c44171b6c524cf023da646749eb90157463538da8b2e13d3", + "urls": [ + "bzz-raw://35f6eba6b664963e3b4ef20c0428c6a833b6106ca7afcd01d513b3e54ac4a046", + "dweb:/ipfs/QmaVmZUJEVyG4YupH1dxroJ3m6yaere7JX9BPgP1a8zdeb" + ], + "license": "Apache-2.0" + }, + "node_modules/@cartesi/util/contracts/MerkleV2.sol": { + "keccak256": "0x73d86cb2dfa2ca887987c6da8d193d523c6a65ea89e296d1f47f190ebda7fa9b", + "urls": [ + "bzz-raw://484b9a86375d8515766fe5b52947c41a5245f53c380f4c78c0bdd079665ae136", + "dweb:/ipfs/QmeMeKokxHUh5opFpi58otQoHkyA9A3TkWAUbCruZyYZk3" + ], + "license": "Apache-2.0" + }, + "node_modules/@openzeppelin/contracts/interfaces/IERC165.sol": { + "keccak256": "0xd04b0f06e0666f29cf7cccc82894de541e19bb30a765b107b1e40bb7fe5f7d7a", + "urls": [ + "bzz-raw://7b652499d098e88d8d878374616bb58434301061cae2253298b3f374044e0ddb", + "dweb:/ipfs/QmbhAzctqo5jrSKU6idHdVyqfmzCcDbNUPvmx4GiXxfA6q" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/interfaces/IERC4906.sol": { + "keccak256": "0x2a9dadb806be80dd451821f1f1190eb9aa6f6edae85b185db29d60767cc0c5f4", + "urls": [ + "bzz-raw://5c25cac8dbe5bd96320053d23c3dacdb875e629d7c53ac00892eb7aa8500bde6", + "dweb:/ipfs/Qmaf2oqbxxdJA9DphAoH4UCb8aXEAVM8fnu6qMxHJ5ta4A" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/interfaces/IERC721.sol": { + "keccak256": "0xaf297d12d8d4a57fe01a70f0ef38908f208e3faedc577056d0b728fa2f3ccf0c", + "urls": [ + "bzz-raw://fbfaf37123958822a2720a4ea29651be00edab787540b770f73d3e025d286ff8", + "dweb:/ipfs/QmbzgWeTm8hJVUqWrNAwFjshqbYVyeGpQA8D1huzxQdmw6" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol": { + "keccak256": "0x2c309e7df9e05e6ce15bedfe74f3c61b467fc37e0fae9eab496acf5ea0bbd7ff", + "urls": [ + "bzz-raw://7063b5c98711a98018ba4635ac74cee1c1cfa2ea01099498e062699ed9530005", + "dweb:/ipfs/QmeJ8rGXkcv7RrqLdAW8PCXPAykxVsddfYY6g5NaTwmRFE" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol": { + "keccak256": "0x5bce51e11f7d194b79ea59fe00c9e8de9fa2c5530124960f29a24d4c740a3266", + "urls": [ + "bzz-raw://7e66dfde185df46104c11bc89d08fa0760737aa59a2b8546a656473d810a8ea4", + "dweb:/ipfs/QmXvyqtXPaPss2PD7eqPoSao5Szm2n6UMoiG8TZZDjmChR" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { + "keccak256": "0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da", + "urls": [ + "bzz-raw://6e75cf83beb757b8855791088546b8337e9d4684e169400c20d44a515353b708", + "dweb:/ipfs/QmYvPafLfoquiDMEj7CKHtvbgHu7TJNPSVPSCjrtjV8HjV" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol": { + "keccak256": "0x7942989e3525aec1672469e4c65fb33fbd19c785c9cadbcb70fcbe1fe8bfdd37", + "urls": [ + "bzz-raw://6c9f260258c2be0e3b75f8ca285872c4bfa3a8fc97fdc2e62366c78abf22b54f", + "dweb:/ipfs/QmTg1DMNwCDj8NVi6i1noqx7cxuRdPP4VyW4fzDkKAKmH2" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "keccak256": "0x75b829ff2f26c14355d1cba20e16fe7b29ca58eb5fef665ede48bc0f9c6c74b9", + "urls": [ + "bzz-raw://a0a107160525724f9e1bbbab031defc2f298296dd9e331f16a6f7130cec32146", + "dweb:/ipfs/QmemujxSd7gX8A9M8UwmNbz4Ms3U9FG9QfudUgxwvTmPWf" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/utils/Address.sol": { + "keccak256": "0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa", + "urls": [ + "bzz-raw://2455248c8ddd9cc6a7af76a13973cddf222072427e7b0e2a7d1aff345145e931", + "dweb:/ipfs/QmfYjnjRbWqYpuxurqveE6HtzsY1Xx323J428AKQgtBJZm" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/utils/Context.sol": { + "keccak256": "0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7", + "urls": [ + "bzz-raw://6df0ddf21ce9f58271bdfaa85cde98b200ef242a05a3f85c2bc10a8294800a92", + "dweb:/ipfs/QmRK2Y5Yc6BK7tGKkgsgn3aJEQGi5aakeSPZvS65PV8Xp3" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/utils/Counters.sol": { + "keccak256": "0xf0018c2440fbe238dd3a8732fa8e17a0f9dce84d31451dc8a32f6d62b349c9f1", + "urls": [ + "bzz-raw://59e1c62884d55b70f3ae5432b44bb3166ad71ae3acd19c57ab6ddc3c87c325ee", + "dweb:/ipfs/QmezuXg5GK5oeA4F91EZhozBFekhq5TD966bHPH18cCqhu" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/utils/Strings.sol": { + "keccak256": "0x3088eb2868e8d13d89d16670b5f8612c4ab9ff8956272837d8e90106c59c14a0", + "urls": [ + "bzz-raw://b81d9ff6559ea5c47fc573e17ece6d9ba5d6839e213e6ebc3b4c5c8fe4199d7f", + "dweb:/ipfs/QmPCW1bFisUzJkyjroY3yipwfism9RRCigCcK1hbXtVM8n" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "keccak256": "0xd10975de010d89fd1c78dc5e8a9a7e7f496198085c151648f20cba166b32582b", + "urls": [ + "bzz-raw://fb0048dee081f6fffa5f74afc3fb328483c2a30504e94a0ddd2a5114d731ec4d", + "dweb:/ipfs/QmZptt1nmYoA5SgjwnSgWqgUSDgm4q52Yos3xhnMv3MV43" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "keccak256": "0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1", + "urls": [ + "bzz-raw://be161e54f24e5c6fae81a12db1a8ae87bc5ae1b0ddc805d82a1440a68455088f", + "dweb:/ipfs/QmP7C3CHdY9urF4dEMb9wmsp1wMxHF6nhA2yQE5SKiPAdy" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/utils/math/Math.sol": { + "keccak256": "0xe4455ac1eb7fc497bb7402579e7b4d64d928b846fce7d2b6fde06d366f21c2b3", + "urls": [ + "bzz-raw://cc8841b3cd48ad125e2f46323c8bad3aa0e88e399ec62acb9e57efa7e7c8058c", + "dweb:/ipfs/QmSqE4mXHA2BXW58deDbXE8MTcsL5JSKNDbm23sVQxRLPS" + ], + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": { + "keccak256": "0xf92515413956f529d95977adc9b0567d583c6203fc31ab1c23824c35187e3ddc", + "urls": [ + "bzz-raw://c50fcc459e49a9858b6d8ad5f911295cb7c9ab57567845a250bf0153f84a95c7", + "dweb:/ipfs/QmcEW85JRzvDkQggxiBBLVAasXWdkhEysqypj9EaB6H2g6" + ], + "license": "MIT" + } + }, + "version": 1 + }, + "ast": { + "absolutePath": "contracts/RivesScoreNFT.sol", + "id": 364, + "exportedSymbols": { + "Address": [ + 3634 + ], + "Bitmask": [ + 988 + ], + "CanonicalMachine": [ + 468 + ], + "Context": [ + 3656 + ], + "Counters": [ + 3730 + ], + "ERC165": [ + 3983 + ], + "ERC721": [ + 2987 + ], + "ERC721URIStorage": [ + 3277 + ], + "ICartesiDApp": [ + 610 + ], + "IConsensus": [ + 530 + ], + "IERC165": [ + 3995 + ], + "IERC4906": [ + 2057 + ], + "IERC721": [ + 3103 + ], + "IERC721Metadata": [ + 3304 + ], + "IERC721Receiver": [ + 3121 + ], + "LibOutputValidation": [ + 884 + ], + "Math": [ + 4861 + ], + "MerkleV2": [ + 2032 + ], + "OutputEncoding": [ + 503 + ], + "OutputValidityProof": [ + 638 + ], + "Proof": [ + 543 + ], + "RivesScoreNFT": [ + 363 + ], + "SignedMath": [ + 4966 + ], + "Strings": [ + 3959 + ] + }, + "nodeType": "SourceUnit", + "src": "39:3929:0", + "nodes": [ + { + "id": 1, + "nodeType": "PragmaDirective", + "src": "39:23:0", + "nodes": [], + "literals": [ + "solidity", + "^", + "0.8", + ".0" + ] + }, + { + "id": 2, + "nodeType": "ImportDirective", + "src": "64:78:0", + "nodes": [], + "absolutePath": "node_modules/@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + "file": "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol", + "nameLocation": "-1:-1:-1", + "scope": 364, + "sourceUnit": 3278, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 3, + "nodeType": "ImportDirective", + "src": "143:52:0", + "nodes": [], + "absolutePath": "node_modules/@openzeppelin/contracts/utils/Counters.sol", + "file": "@openzeppelin/contracts/utils/Counters.sol", + "nameLocation": "-1:-1:-1", + "scope": 364, + "sourceUnit": 3731, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 5, + "nodeType": "ImportDirective", + "src": "197:60:0", + "nodes": [], + "absolutePath": "node_modules/@cartesi/util/contracts/Bitmask.sol", + "file": "@cartesi/util/contracts/Bitmask.sol", + "nameLocation": "-1:-1:-1", + "scope": 364, + "sourceUnit": 989, + "symbolAliases": [ + { + "foreign": { + "id": 4, + "name": "Bitmask", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 988, + "src": "205:7:0", + "typeDescriptions": {} + }, + "nameLocation": "-1:-1:-1" + } + ], + "unitAlias": "" + }, + { + "id": 6, + "nodeType": "ImportDirective", + "src": "258:58:0", + "nodes": [], + "absolutePath": "node_modules/@cartesi/rollups/contracts/dapp/ICartesiDApp.sol", + "file": "@cartesi/rollups/contracts/dapp/ICartesiDApp.sol", + "nameLocation": "-1:-1:-1", + "scope": 364, + "sourceUnit": 611, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 7, + "nodeType": "ImportDirective", + "src": "317:68:0", + "nodes": [], + "absolutePath": "node_modules/@cartesi/rollups/contracts/library/LibOutputValidation.sol", + "file": "@cartesi/rollups/contracts/library/LibOutputValidation.sol", + "nameLocation": "-1:-1:-1", + "scope": 364, + "sourceUnit": 885, + "symbolAliases": [], + "unitAlias": "" + }, + { + "id": 363, + "nodeType": "ContractDefinition", + "src": "388:3580:0", + "nodes": [ + { + "id": 13, + "nodeType": "UsingForDirective", + "src": "435:36:0", + "nodes": [], + "global": false, + "libraryName": { + "id": 10, + "name": "Counters", + "nameLocations": [ + "441:8:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 3730, + "src": "441:8:0" + }, + "typeName": { + "id": 12, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 11, + "name": "Counters.Counter", + "nameLocations": [ + "454:8:0", + "463:7:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 3662, + "src": "454:16:0" + }, + "referencedDeclaration": 3662, + "src": "454:16:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Counter_$3662_storage_ptr", + "typeString": "struct Counters.Counter" + } + } + }, + { + "id": 18, + "nodeType": "UsingForDirective", + "src": "474:46:0", + "nodes": [], + "global": false, + "libraryName": { + "id": 14, + "name": "Bitmask", + "nameLocations": [ + "480:7:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 988, + "src": "480:7:0" + }, + "typeName": { + "id": 17, + "keyName": "", + "keyNameLocation": "-1:-1:-1", + "keyType": { + "id": 15, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "500:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Mapping", + "src": "492:27:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_uint256_$_t_uint256_$", + "typeString": "mapping(uint256 => uint256)" + }, + "valueName": "", + "valueNameLocation": "-1:-1:-1", + "valueType": { + "id": 16, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "511:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + } + }, + { + "id": 22, + "nodeType": "VariableDeclaration", + "src": "524:41:0", + "nodes": [], + "constant": false, + "mutability": "mutable", + "name": "noticeBitmask", + "nameLocation": "552:13:0", + "scope": 363, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_uint256_$_t_uint256_$", + "typeString": "mapping(uint256 => uint256)" + }, + "typeName": { + "id": 21, + "keyName": "", + "keyNameLocation": "-1:-1:-1", + "keyType": { + "id": 19, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "532:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "Mapping", + "src": "524:27:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_uint256_$_t_uint256_$", + "typeString": "mapping(uint256 => uint256)" + }, + "valueName": "", + "valueNameLocation": "-1:-1:-1", + "valueType": { + "id": 20, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "543:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + }, + "visibility": "internal" + }, + { + "id": 26, + "nodeType": "VariableDeclaration", + "src": "570:48:0", + "nodes": [], + "constant": false, + "functionSelector": "eadc7463", + "mutability": "mutable", + "name": "gamelogOwner", + "nameLocation": "606:12:0", + "scope": 363, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_bytes32_$_t_address_$", + "typeString": "mapping(bytes32 => address)" + }, + "typeName": { + "id": 25, + "keyName": "", + "keyNameLocation": "-1:-1:-1", + "keyType": { + "id": 23, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "579:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "Mapping", + "src": "570:28:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_bytes32_$_t_address_$", + "typeString": "mapping(bytes32 => address)" + }, + "valueName": "", + "valueNameLocation": "-1:-1:-1", + "valueType": { + "id": 24, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "590:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + }, + "visibility": "public" + }, + { + "id": 28, + "nodeType": "VariableDeclaration", + "src": "625:26:0", + "nodes": [], + "constant": false, + "functionSelector": "1a721b7b", + "mutability": "mutable", + "name": "dappAddress", + "nameLocation": "640:11:0", + "scope": 363, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 27, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "625:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "public" + }, + { + "id": 30, + "nodeType": "VariableDeclaration", + "src": "655:23:0", + "nodes": [], + "constant": false, + "functionSelector": "570ca735", + "mutability": "mutable", + "name": "operator", + "nameLocation": "670:8:0", + "scope": 363, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 29, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "655:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "public" + }, + { + "id": 33, + "nodeType": "VariableDeclaration", + "src": "683:34:0", + "nodes": [], + "constant": false, + "mutability": "mutable", + "name": "_tokenIds", + "nameLocation": "708:9:0", + "scope": 363, + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Counter_$3662_storage", + "typeString": "struct Counters.Counter" + }, + "typeName": { + "id": 32, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 31, + "name": "Counters.Counter", + "nameLocations": [ + "683:8:0", + "692:7:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 3662, + "src": "683:16:0" + }, + "referencedDeclaration": 3662, + "src": "683:16:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Counter_$3662_storage_ptr", + "typeString": "struct Counters.Counter" + } + }, + "visibility": "private" + }, + { + "id": 52, + "nodeType": "FunctionDefinition", + "src": "722:131:0", + "nodes": [], + "body": { + "id": 51, + "nodeType": "Block", + "src": "789:64:0", + "nodes": [], + "statements": [ + { + "expression": { + "id": 44, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 42, + "name": "dappAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 28, + "src": "795:11:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 43, + "name": "_dappAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 35, + "src": "809:12:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "795:26:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 45, + "nodeType": "ExpressionStatement", + "src": "795:26:0" + }, + { + "expression": { + "id": 49, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 46, + "name": "operator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 30, + "src": "827:8:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "expression": { + "id": 47, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "838:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 48, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "842:6:0", + "memberName": "sender", + "nodeType": "MemberAccess", + "src": "838:10:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "827:21:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 50, + "nodeType": "ExpressionStatement", + "src": "827:21:0" + } + ] + }, + "implemented": true, + "kind": "constructor", + "modifiers": [ + { + "arguments": [ + { + "hexValue": "526976657353636f72654e4654", + "id": 38, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "763:15:0", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_3e29b3ee037c76cada90e6490b6e95b46665d62c7f9d00f2b1dd6a9d2bd8884c", + "typeString": "literal_string \"RivesScoreNFT\"" + }, + "value": "RivesScoreNFT" + }, + { + "hexValue": "52534e4654", + "id": 39, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "780:7:0", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_45c4fb9434e67ba892286d49aebceeb39c0bb86feed3833b030a3eddb7ca1209", + "typeString": "literal_string \"RSNFT\"" + }, + "value": "RSNFT" + } + ], + "id": 40, + "kind": "baseConstructorSpecifier", + "modifierName": { + "id": 37, + "name": "ERC721", + "nameLocations": [ + "756:6:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 2987, + "src": "756:6:0" + }, + "nodeType": "ModifierInvocation", + "src": "756:32:0" + } + ], + "name": "", + "nameLocation": "-1:-1:-1", + "parameters": { + "id": 36, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 35, + "mutability": "mutable", + "name": "_dappAddress", + "nameLocation": "742:12:0", + "nodeType": "VariableDeclaration", + "scope": 52, + "src": "734:20:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 34, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "734:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "src": "733:22:0" + }, + "returnParameters": { + "id": 41, + "nodeType": "ParameterList", + "parameters": [], + "src": "789:0:0" + }, + "scope": 363, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "id": 70, + "nodeType": "FunctionDefinition", + "src": "857:164:0", + "nodes": [], + "body": { + "id": 69, + "nodeType": "Block", + "src": "906:115:0", + "nodes": [], + "statements": [ + { + "expression": { + "arguments": [ + { + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 61, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "expression": { + "id": 58, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "920:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 59, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "924:6:0", + "memberName": "sender", + "nodeType": "MemberAccess", + "src": "920:10:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "id": 60, + "name": "operator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 30, + "src": "934:8:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "920:22:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "hexValue": "4f6e6c792063757272656e74206f70657261746f722063616e20736574206e6577206f70657261746f72", + "id": 62, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "943:44:0", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_6cfcdc1acd690da82baa06d03e6f72e43929175a800ea84cd480b6bd08e8dd90", + "typeString": "literal_string \"Only current operator can set new operator\"" + }, + "value": "Only current operator can set new operator" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_6cfcdc1acd690da82baa06d03e6f72e43929175a800ea84cd480b6bd08e8dd90", + "typeString": "literal_string \"Only current operator can set new operator\"" + } + ], + "id": 57, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "912:7:0", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 63, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "912:76:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 64, + "nodeType": "ExpressionStatement", + "src": "912:76:0" + }, + { + "expression": { + "id": 67, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 65, + "name": "operator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 30, + "src": "994:8:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "id": 66, + "name": "newOperator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 54, + "src": "1005:11:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "994:22:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 68, + "nodeType": "ExpressionStatement", + "src": "994:22:0" + } + ] + }, + "functionSelector": "b3ab15fb", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "setOperator", + "nameLocation": "866:11:0", + "parameters": { + "id": 55, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 54, + "mutability": "mutable", + "name": "newOperator", + "nameLocation": "886:11:0", + "nodeType": "VariableDeclaration", + "scope": 70, + "src": "878:19:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 53, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "878:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "src": "877:21:0" + }, + "returnParameters": { + "id": 56, + "nodeType": "ParameterList", + "parameters": [], + "src": "906:0:0" + }, + "scope": 363, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "id": 101, + "nodeType": "FunctionDefinition", + "src": "1027:254:0", + "nodes": [], + "body": { + "id": 100, + "nodeType": "Block", + "src": "1138:143:0", + "nodes": [], + "statements": [ + { + "assignments": [ + 84 + ], + "declarations": [ + { + "constant": false, + "id": 84, + "mutability": "mutable", + "name": "hash", + "nameLocation": "1152:4:0", + "nodeType": "VariableDeclaration", + "scope": 100, + "src": "1144:12:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 83, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1144:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + } + ], + "id": 92, + "initialValue": { + "arguments": [ + { + "arguments": [ + { + "hexValue": "19457468657265756d205369676e6564204d6573736167653a0a3332", + "id": 88, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1186:34:0", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_178a2411ab6fbc1ba11064408972259c558d0e82fd48b0aba3ad81d14f065e73", + "typeString": "literal_string hex\"19457468657265756d205369676e6564204d6573736167653a0a3332\"" + }, + "value": "\u0019Ethereum Signed Message:\n32" + }, + { + "id": 89, + "name": "gameplayHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 72, + "src": "1222:12:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_178a2411ab6fbc1ba11064408972259c558d0e82fd48b0aba3ad81d14f065e73", + "typeString": "literal_string hex\"19457468657265756d205369676e6564204d6573736167653a0a3332\"" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "id": 86, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "1169:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 87, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "1173:12:0", + "memberName": "encodePacked", + "nodeType": "MemberAccess", + "src": "1169:16:0", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 90, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1169:66:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 85, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "1159:9:0", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 91, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1159:77:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1144:92:0" + }, + { + "expression": { + "arguments": [ + { + "id": 94, + "name": "hash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 84, + "src": "1259:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + { + "id": 95, + "name": "_v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 78, + "src": "1265:2:0", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + { + "id": 96, + "name": "_r", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 74, + "src": "1269:2:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + { + "id": 97, + "name": "_s", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 76, + "src": "1273:2:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "id": 93, + "name": "ecrecover", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -6, + "src": "1249:9:0", + "typeDescriptions": { + "typeIdentifier": "t_function_ecrecover_pure$_t_bytes32_$_t_uint8_$_t_bytes32_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (bytes32,uint8,bytes32,bytes32) pure returns (address)" + } + }, + "id": 98, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1249:27:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "functionReturnParameters": 82, + "id": 99, + "nodeType": "Return", + "src": "1242:34:0" + } + ] + }, + "functionSelector": "0d413d62", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "verifySignature", + "nameLocation": "1036:15:0", + "parameters": { + "id": 79, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 72, + "mutability": "mutable", + "name": "gameplayHash", + "nameLocation": "1060:12:0", + "nodeType": "VariableDeclaration", + "scope": 101, + "src": "1052:20:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 71, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1052:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 74, + "mutability": "mutable", + "name": "_r", + "nameLocation": "1082:2:0", + "nodeType": "VariableDeclaration", + "scope": 101, + "src": "1074:10:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 73, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1074:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 76, + "mutability": "mutable", + "name": "_s", + "nameLocation": "1094:2:0", + "nodeType": "VariableDeclaration", + "scope": 101, + "src": "1086:10:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 75, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1086:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 78, + "mutability": "mutable", + "name": "_v", + "nameLocation": "1104:2:0", + "nodeType": "VariableDeclaration", + "scope": 101, + "src": "1098:8:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "typeName": { + "id": 77, + "name": "uint8", + "nodeType": "ElementaryTypeName", + "src": "1098:5:0", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "visibility": "internal" + } + ], + "src": "1051:56:0" + }, + "returnParameters": { + "id": 82, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 81, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 101, + "src": "1129:7:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 80, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1129:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "src": "1128:9:0" + }, + "scope": 363, + "stateMutability": "pure", + "virtual": false, + "visibility": "public" + }, + { + "id": 146, + "nodeType": "FunctionDefinition", + "src": "1285:372:0", + "nodes": [], + "body": { + "id": 145, + "nodeType": "Block", + "src": "1374:283:0", + "nodes": [], + "statements": [ + { + "assignments": [ + 113 + ], + "declarations": [ + { + "constant": false, + "id": 113, + "mutability": "mutable", + "name": "hash", + "nameLocation": "1388:4:0", + "nodeType": "VariableDeclaration", + "scope": 145, + "src": "1380:12:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 112, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1380:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + } + ], + "id": 121, + "initialValue": { + "arguments": [ + { + "arguments": [ + { + "hexValue": "19457468657265756d205369676e6564204d6573736167653a0a3332", + "id": 117, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1422:34:0", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_178a2411ab6fbc1ba11064408972259c558d0e82fd48b0aba3ad81d14f065e73", + "typeString": "literal_string hex\"19457468657265756d205369676e6564204d6573736167653a0a3332\"" + }, + "value": "\u0019Ethereum Signed Message:\n32" + }, + { + "id": 118, + "name": "gameplayHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 103, + "src": "1458:12:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_178a2411ab6fbc1ba11064408972259c558d0e82fd48b0aba3ad81d14f065e73", + "typeString": "literal_string hex\"19457468657265756d205369676e6564204d6573736167653a0a3332\"" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "expression": { + "id": 115, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "1405:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 116, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "1409:12:0", + "memberName": "encodePacked", + "nodeType": "MemberAccess", + "src": "1405:16:0", + "typeDescriptions": { + "typeIdentifier": "t_function_abiencodepacked_pure$__$returns$_t_bytes_memory_ptr_$", + "typeString": "function () pure returns (bytes memory)" + } + }, + "id": 119, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1405:66:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_memory_ptr", + "typeString": "bytes memory" + } + ], + "id": 114, + "name": "keccak256", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -8, + "src": "1395:9:0", + "typeDescriptions": { + "typeIdentifier": "t_function_keccak256_pure$_t_bytes_memory_ptr_$returns$_t_bytes32_$", + "typeString": "function (bytes memory) pure returns (bytes32)" + } + }, + "id": 120, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1395:77:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1380:92:0" + }, + { + "assignments": [ + 123 + ], + "declarations": [ + { + "constant": false, + "id": 123, + "mutability": "mutable", + "name": "signer", + "nameLocation": "1486:6:0", + "nodeType": "VariableDeclaration", + "scope": 145, + "src": "1478:14:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 122, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "1478:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "id": 130, + "initialValue": { + "arguments": [ + { + "id": 125, + "name": "hash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 113, + "src": "1505:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + { + "id": 126, + "name": "_v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 109, + "src": "1511:2:0", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + { + "id": 127, + "name": "_r", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 105, + "src": "1515:2:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + { + "id": 128, + "name": "_s", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 107, + "src": "1519:2:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + ], + "id": 124, + "name": "ecrecover", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -6, + "src": "1495:9:0", + "typeDescriptions": { + "typeIdentifier": "t_function_ecrecover_pure$_t_bytes32_$_t_uint8_$_t_bytes32_$_t_bytes32_$returns$_t_address_$", + "typeString": "function (bytes32,uint8,bytes32,bytes32) pure returns (address)" + } + }, + "id": 129, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1495:27:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1478:44:0" + }, + { + "expression": { + "arguments": [ + { + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 134, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "id": 132, + "name": "signer", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 123, + "src": "1537:6:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "id": 133, + "name": "operator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 30, + "src": "1547:8:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1537:18:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "hexValue": "53696e676e6564206d65737361676520646f6573206e6f74206d617463682063757272656e74206f70657261746f72", + "id": 135, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "1556:49:0", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_4174746ed4cf89aead33ddc6fdca6443e79e09c098ae8dc8ca5a89ca772a8525", + "typeString": "literal_string \"Singned message does not match current operator\"" + }, + "value": "Singned message does not match current operator" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_4174746ed4cf89aead33ddc6fdca6443e79e09c098ae8dc8ca5a89ca772a8525", + "typeString": "literal_string \"Singned message does not match current operator\"" + } + ], + "id": 131, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "1529:7:0", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 136, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1529:77:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 137, + "nodeType": "ExpressionStatement", + "src": "1529:77:0" + }, + { + "expression": { + "id": 143, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "baseExpression": { + "id": 138, + "name": "gamelogOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 26, + "src": "1613:12:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_bytes32_$_t_address_$", + "typeString": "mapping(bytes32 => address)" + } + }, + "id": 140, + "indexExpression": { + "id": 139, + "name": "gameplayHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 103, + "src": "1626:12:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": true, + "nodeType": "IndexAccess", + "src": "1613:26:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "expression": { + "id": 141, + "name": "msg", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -15, + "src": "1642:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_message", + "typeString": "msg" + } + }, + "id": 142, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1646:6:0", + "memberName": "sender", + "nodeType": "MemberAccess", + "src": "1642:10:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "1613:39:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 144, + "nodeType": "ExpressionStatement", + "src": "1613:39:0" + } + ] + }, + "functionSelector": "c521030a", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "setGameplayOwner", + "nameLocation": "1294:16:0", + "parameters": { + "id": 110, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 103, + "mutability": "mutable", + "name": "gameplayHash", + "nameLocation": "1319:12:0", + "nodeType": "VariableDeclaration", + "scope": 146, + "src": "1311:20:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 102, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1311:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 105, + "mutability": "mutable", + "name": "_r", + "nameLocation": "1341:2:0", + "nodeType": "VariableDeclaration", + "scope": 146, + "src": "1333:10:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 104, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1333:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 107, + "mutability": "mutable", + "name": "_s", + "nameLocation": "1353:2:0", + "nodeType": "VariableDeclaration", + "scope": 146, + "src": "1345:10:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 106, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "1345:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 109, + "mutability": "mutable", + "name": "_v", + "nameLocation": "1363:2:0", + "nodeType": "VariableDeclaration", + "scope": 146, + "src": "1357:8:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + }, + "typeName": { + "id": 108, + "name": "uint8", + "nodeType": "ElementaryTypeName", + "src": "1357:5:0", + "typeDescriptions": { + "typeIdentifier": "t_uint8", + "typeString": "uint8" + } + }, + "visibility": "internal" + } + ], + "src": "1310:56:0" + }, + "returnParameters": { + "id": 111, + "nodeType": "ParameterList", + "parameters": [], + "src": "1374:0:0" + }, + "scope": 363, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "id": 303, + "nodeType": "FunctionDefinition", + "src": "1661:1656:0", + "nodes": [], + "body": { + "id": 302, + "nodeType": "Block", + "src": "1744:1573:0", + "nodes": [], + "statements": [ + { + "assignments": [ + 158 + ], + "declarations": [ + { + "constant": false, + "id": 158, + "mutability": "mutable", + "name": "dapp", + "nameLocation": "1763:4:0", + "nodeType": "VariableDeclaration", + "scope": 302, + "src": "1750:17:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ICartesiDApp_$610", + "typeString": "contract ICartesiDApp" + }, + "typeName": { + "id": 157, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 156, + "name": "ICartesiDApp", + "nameLocations": [ + "1750:12:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 610, + "src": "1750:12:0" + }, + "referencedDeclaration": 610, + "src": "1750:12:0", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ICartesiDApp_$610", + "typeString": "contract ICartesiDApp" + } + }, + "visibility": "internal" + } + ], + "id": 162, + "initialValue": { + "arguments": [ + { + "id": 160, + "name": "dappAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 28, + "src": "1783:11:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 159, + "name": "ICartesiDApp", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 610, + "src": "1770:12:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ICartesiDApp_$610_$", + "typeString": "type(contract ICartesiDApp)" + } + }, + "id": 161, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1770:25:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ICartesiDApp_$610", + "typeString": "contract ICartesiDApp" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1750:45:0" + }, + { + "expression": { + "arguments": [ + { + "id": 166, + "name": "_payload", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 148, + "src": "1845:8:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + }, + { + "id": 167, + "name": "_v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 151, + "src": "1854:2:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof calldata" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + }, + { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof calldata" + } + ], + "expression": { + "id": 163, + "name": "dapp", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 158, + "src": "1825:4:0", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ICartesiDApp_$610", + "typeString": "contract ICartesiDApp" + } + }, + "id": 165, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1830:14:0", + "memberName": "validateNotice", + "nodeType": "MemberAccess", + "referencedDeclaration": 596, + "src": "1825:19:0", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_bytes_memory_ptr_$_t_struct$_Proof_$543_memory_ptr_$returns$_t_bool_$", + "typeString": "function (bytes memory,struct Proof memory) view external returns (bool)" + } + }, + "id": 168, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1825:32:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 169, + "nodeType": "ExpressionStatement", + "src": "1825:32:0" + }, + { + "assignments": [ + null, + 171, + null + ], + "declarations": [ + null, + { + "constant": false, + "id": 171, + "mutability": "mutable", + "name": "firstInputIndex", + "nameLocation": "1932:15:0", + "nodeType": "VariableDeclaration", + "scope": 302, + "src": "1924:23:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 170, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1924:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + }, + null + ], + "id": 180, + "initialValue": { + "arguments": [ + { + "id": 176, + "name": "dappAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 28, + "src": "1982:11:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "expression": { + "id": 177, + "name": "_v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 151, + "src": "1994:2:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof calldata" + } + }, + "id": 178, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1997:7:0", + "memberName": "context", + "nodeType": "MemberAccess", + "referencedDeclaration": 542, + "src": "1994:10:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + ], + "expression": { + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "id": 172, + "name": "dapp", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 158, + "src": "1953:4:0", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ICartesiDApp_$610", + "typeString": "contract ICartesiDApp" + } + }, + "id": 173, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1958:12:0", + "memberName": "getConsensus", + "nodeType": "MemberAccess", + "referencedDeclaration": 609, + "src": "1953:17:0", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$__$returns$_t_contract$_IConsensus_$530_$", + "typeString": "function () view external returns (contract IConsensus)" + } + }, + "id": 174, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1953:19:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IConsensus_$530", + "typeString": "contract IConsensus" + } + }, + "id": 175, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "1973:8:0", + "memberName": "getClaim", + "nodeType": "MemberAccess", + "referencedDeclaration": 525, + "src": "1953:28:0", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_address_$_t_bytes_memory_ptr_$returns$_t_bytes32_$_t_uint256_$_t_uint256_$", + "typeString": "function (address,bytes memory) view external returns (bytes32,uint256,uint256)" + } + }, + "id": 179, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "1953:52:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$_t_bytes32_$_t_uint256_$_t_uint256_$", + "typeString": "tuple(bytes32,uint256,uint256)" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "1921:84:0" + }, + { + "assignments": [ + 182 + ], + "declarations": [ + { + "constant": false, + "id": 182, + "mutability": "mutable", + "name": "inputIndex", + "nameLocation": "2020:10:0", + "nodeType": "VariableDeclaration", + "scope": 302, + "src": "2012:18:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 181, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2012:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "id": 188, + "initialValue": { + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 187, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "id": 183, + "name": "firstInputIndex", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 171, + "src": "2033:15:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "+", + "rightExpression": { + "expression": { + "expression": { + "id": 184, + "name": "_v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 151, + "src": "2051:2:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof calldata" + } + }, + "id": 185, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "2054:8:0", + "memberName": "validity", + "nodeType": "MemberAccess", + "referencedDeclaration": 540, + "src": "2051:11:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_OutputValidityProof_$638_calldata_ptr", + "typeString": "struct OutputValidityProof calldata" + } + }, + "id": 186, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "2063:21:0", + "memberName": "inputIndexWithinEpoch", + "nodeType": "MemberAccess", + "referencedDeclaration": 621, + "src": "2051:33:0", + "typeDescriptions": { + "typeIdentifier": "t_uint64", + "typeString": "uint64" + } + }, + "src": "2033:51:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2012:72:0" + }, + { + "assignments": [ + 190 + ], + "declarations": [ + { + "constant": false, + "id": 190, + "mutability": "mutable", + "name": "noticePosition", + "nameLocation": "2141:14:0", + "nodeType": "VariableDeclaration", + "scope": 302, + "src": "2133:22:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 189, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "2133:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "id": 198, + "initialValue": { + "arguments": [ + { + "expression": { + "expression": { + "id": 193, + "name": "_v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 151, + "src": "2197:2:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof calldata" + } + }, + "id": 194, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "2200:8:0", + "memberName": "validity", + "nodeType": "MemberAccess", + "referencedDeclaration": 540, + "src": "2197:11:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_OutputValidityProof_$638_calldata_ptr", + "typeString": "struct OutputValidityProof calldata" + } + }, + "id": 195, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "2209:22:0", + "memberName": "outputIndexWithinInput", + "nodeType": "MemberAccess", + "referencedDeclaration": 623, + "src": "2197:34:0", + "typeDescriptions": { + "typeIdentifier": "t_uint64", + "typeString": "uint64" + } + }, + { + "id": 196, + "name": "inputIndex", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 182, + "src": "2232:10:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint64", + "typeString": "uint64" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "id": 191, + "name": "LibOutputValidation", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 884, + "src": "2158:19:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_LibOutputValidation_$884_$", + "typeString": "type(library LibOutputValidation)" + } + }, + "id": 192, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "2178:18:0", + "memberName": "getBitMaskPosition", + "nodeType": "MemberAccess", + "referencedDeclaration": 852, + "src": "2158:38:0", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 197, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "2158:85:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2133:110:0" + }, + { + "expression": { + "arguments": [ + { + "id": 204, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "nodeType": "UnaryOperation", + "operator": "!", + "prefix": true, + "src": "2257:37:0", + "subExpression": { + "arguments": [ + { + "id": 202, + "name": "noticePosition", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 190, + "src": "2279:14:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "id": 200, + "name": "noticeBitmask", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 22, + "src": "2258:13:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_uint256_$_t_uint256_$", + "typeString": "mapping(uint256 => uint256)" + } + }, + "id": 201, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "2272:6:0", + "memberName": "getBit", + "nodeType": "MemberAccess", + "referencedDeclaration": 987, + "src": "2258:20:0", + "typeDescriptions": { + "typeIdentifier": "t_function_delegatecall_view$_t_mapping$_t_uint256_$_t_uint256_$_$_t_uint256_$returns$_t_bool_$attached_to$_t_mapping$_t_uint256_$_t_uint256_$_$", + "typeString": "function (mapping(uint256 => uint256),uint256) view returns (bool)" + } + }, + "id": 203, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "2258:36:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "hexValue": "6e6f746963652072652d7375626d6974696e67206e6f7420616c6c6f776564", + "id": 205, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2295:33:0", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_2e1bf4a8a11f346d92f786e8f6ebb6342a07f07dd08675bf8b7faf52b3bc1ae3", + "typeString": "literal_string \"notice re-submiting not allowed\"" + }, + "value": "notice re-submiting not allowed" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_2e1bf4a8a11f346d92f786e8f6ebb6342a07f07dd08675bf8b7faf52b3bc1ae3", + "typeString": "literal_string \"notice re-submiting not allowed\"" + } + ], + "id": 199, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "2249:7:0", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 206, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "2249:80:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 207, + "nodeType": "ExpressionStatement", + "src": "2249:80:0" + }, + { + "assignments": [ + null, + 209, + null, + null, + null, + null, + null, + null, + 211, + 213 + ], + "declarations": [ + null, + { + "constant": false, + "id": 209, + "mutability": "mutable", + "name": "userAddress", + "nameLocation": "2635:11:0", + "nodeType": "VariableDeclaration", + "scope": 302, + "src": "2627:19:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 208, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2627:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + }, + null, + null, + null, + null, + null, + null, + { + "constant": false, + "id": 211, + "mutability": "mutable", + "name": "screenshotCid", + "nameLocation": "2674:13:0", + "nodeType": "VariableDeclaration", + "scope": 302, + "src": "2660:27:0", + "stateVariable": false, + "storageLocation": "memory", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string" + }, + "typeName": { + "id": 210, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "2660:6:0", + "typeDescriptions": { + "typeIdentifier": "t_string_storage_ptr", + "typeString": "string" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 213, + "mutability": "mutable", + "name": "gameplayHash", + "nameLocation": "2697:12:0", + "nodeType": "VariableDeclaration", + "scope": 302, + "src": "2689:20:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + }, + "typeName": { + "id": 212, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2689:7:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "visibility": "internal" + } + ], + "id": 239, + "initialValue": { + "arguments": [ + { + "id": 216, + "name": "_payload", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 148, + "src": "2724:8:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + }, + { + "components": [ + { + "id": 218, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2743:7:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes32_$", + "typeString": "type(bytes32)" + }, + "typeName": { + "id": 217, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2743:7:0", + "typeDescriptions": {} + } + }, + { + "id": 220, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2752:7:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 219, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2752:7:0", + "typeDescriptions": {} + } + }, + { + "id": 222, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2761:4:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_uint256_$", + "typeString": "type(uint256)" + }, + "typeName": { + "id": 221, + "name": "uint", + "nodeType": "ElementaryTypeName", + "src": "2761:4:0", + "typeDescriptions": {} + } + }, + { + "id": 224, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2767:3:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_int256_$", + "typeString": "type(int256)" + }, + "typeName": { + "id": 223, + "name": "int", + "nodeType": "ElementaryTypeName", + "src": "2767:3:0", + "typeDescriptions": {} + } + }, + { + "id": 226, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2772:3:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_int256_$", + "typeString": "type(int256)" + }, + "typeName": { + "id": 225, + "name": "int", + "nodeType": "ElementaryTypeName", + "src": "2772:3:0", + "typeDescriptions": {} + } + }, + { + "id": 228, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2777:3:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_int256_$", + "typeString": "type(int256)" + }, + "typeName": { + "id": 227, + "name": "int", + "nodeType": "ElementaryTypeName", + "src": "2777:3:0", + "typeDescriptions": {} + } + }, + { + "id": 230, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2782:6:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_string_storage_ptr_$", + "typeString": "type(string storage pointer)" + }, + "typeName": { + "id": 229, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "2782:6:0", + "typeDescriptions": {} + } + }, + { + "id": 232, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2790:6:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_string_storage_ptr_$", + "typeString": "type(string storage pointer)" + }, + "typeName": { + "id": 231, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "2790:6:0", + "typeDescriptions": {} + } + }, + { + "id": 234, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2798:6:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_string_storage_ptr_$", + "typeString": "type(string storage pointer)" + }, + "typeName": { + "id": 233, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "2798:6:0", + "typeDescriptions": {} + } + }, + { + "id": 236, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2806:7:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_bytes32_$", + "typeString": "type(bytes32)" + }, + "typeName": { + "id": 235, + "name": "bytes32", + "nodeType": "ElementaryTypeName", + "src": "2806:7:0", + "typeDescriptions": {} + } + } + ], + "id": 237, + "isConstant": false, + "isInlineArray": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "TupleExpression", + "src": "2733:81:0", + "typeDescriptions": { + "typeIdentifier": "t_tuple$_t_type$_t_bytes32_$_$_t_type$_t_address_$_$_t_type$_t_uint256_$_$_t_type$_t_int256_$_$_t_type$_t_int256_$_$_t_type$_t_int256_$_$_t_type$_t_string_storage_ptr_$_$_t_type$_t_string_storage_ptr_$_$_t_type$_t_string_storage_ptr_$_$_t_type$_t_bytes32_$_$", + "typeString": "tuple(type(bytes32),type(address),type(uint256),type(int256),type(int256),type(int256),type(string storage pointer),type(string storage pointer),type(string storage pointer),type(bytes32))" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + }, + { + "typeIdentifier": "t_tuple$_t_type$_t_bytes32_$_$_t_type$_t_address_$_$_t_type$_t_uint256_$_$_t_type$_t_int256_$_$_t_type$_t_int256_$_$_t_type$_t_int256_$_$_t_type$_t_string_storage_ptr_$_$_t_type$_t_string_storage_ptr_$_$_t_type$_t_string_storage_ptr_$_$_t_type$_t_bytes32_$_$", + "typeString": "tuple(type(bytes32),type(address),type(uint256),type(int256),type(int256),type(int256),type(string storage pointer),type(string storage pointer),type(string storage pointer),type(bytes32))" + } + ], + "expression": { + "id": 214, + "name": "abi", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": -1, + "src": "2713:3:0", + "typeDescriptions": { + "typeIdentifier": "t_magic_abi", + "typeString": "abi" + } + }, + "id": 215, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "memberLocation": "2717:6:0", + "memberName": "decode", + "nodeType": "MemberAccess", + "src": "2713:10:0", + "typeDescriptions": { + "typeIdentifier": "t_function_abidecode_pure$__$returns$__$", + "typeString": "function () pure" + } + }, + "id": 238, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "2713:107:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$_t_bytes32_$_t_address_payable_$_t_uint256_$_t_int256_$_t_int256_$_t_int256_$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_string_memory_ptr_$_t_bytes32_$", + "typeString": "tuple(bytes32,address payable,uint256,int256,int256,int256,string memory,string memory,string memory,bytes32)" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2624:196:0" + }, + { + "assignments": [ + 241 + ], + "declarations": [ + { + "constant": false, + "id": 241, + "mutability": "mutable", + "name": "recipient", + "nameLocation": "2841:9:0", + "nodeType": "VariableDeclaration", + "scope": 302, + "src": "2833:17:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "typeName": { + "id": 240, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2833:7:0", + "stateMutability": "nonpayable", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "visibility": "internal" + } + ], + "id": 243, + "initialValue": { + "id": 242, + "name": "userAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 209, + "src": "2853:11:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "2833:31:0" + }, + { + "condition": { + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 246, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "id": 244, + "name": "userAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 209, + "src": "2874:11:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "BinaryOperation", + "operator": "==", + "rightExpression": { + "id": 245, + "name": "operator", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 30, + "src": "2889:8:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2874:23:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 266, + "nodeType": "IfStatement", + "src": "2870:167:0", + "trueBody": { + "id": 265, + "nodeType": "Block", + "src": "2899:138:0", + "statements": [ + { + "expression": { + "arguments": [ + { + "commonType": { + "typeIdentifier": "t_address", + "typeString": "address" + }, + "id": 255, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "baseExpression": { + "id": 248, + "name": "gamelogOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 26, + "src": "2915:12:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_bytes32_$_t_address_$", + "typeString": "mapping(bytes32 => address)" + } + }, + "id": 250, + "indexExpression": { + "id": 249, + "name": "gameplayHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 213, + "src": "2928:12:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "2915:26:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "BinaryOperation", + "operator": "!=", + "rightExpression": { + "arguments": [ + { + "hexValue": "30", + "id": 253, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "number", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2953:1:0", + "typeDescriptions": { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + }, + "value": "0" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_rational_0_by_1", + "typeString": "int_const 0" + } + ], + "id": 252, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "2945:7:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_address_$", + "typeString": "type(address)" + }, + "typeName": { + "id": 251, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "2945:7:0", + "typeDescriptions": {} + } + }, + "id": 254, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "2945:10:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2915:40:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + { + "hexValue": "4e6f2067616d65706c6179206f776e657220646566696e6564", + "id": 256, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "2956:27:0", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_2f8f2af7e0cea6b2e3fc5cadc1f6598d7c63804aa626b1e02163fc4f3a758800", + "typeString": "literal_string \"No gameplay owner defined\"" + }, + "value": "No gameplay owner defined" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + { + "typeIdentifier": "t_stringliteral_2f8f2af7e0cea6b2e3fc5cadc1f6598d7c63804aa626b1e02163fc4f3a758800", + "typeString": "literal_string \"No gameplay owner defined\"" + } + ], + "id": 247, + "name": "require", + "nodeType": "Identifier", + "overloadedDeclarations": [ + -18, + -18 + ], + "referencedDeclaration": -18, + "src": "2907:7:0", + "typeDescriptions": { + "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (bool,string memory) pure" + } + }, + "id": 257, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "2907:77:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 258, + "nodeType": "ExpressionStatement", + "src": "2907:77:0" + }, + { + "expression": { + "id": 263, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftHandSide": { + "id": 259, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 241, + "src": "2992:9:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Assignment", + "operator": "=", + "rightHandSide": { + "baseExpression": { + "id": 260, + "name": "gamelogOwner", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 26, + "src": "3004:12:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_bytes32_$_t_address_$", + "typeString": "mapping(bytes32 => address)" + } + }, + "id": 262, + "indexExpression": { + "id": 261, + "name": "gameplayHash", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 213, + "src": "3017:12:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes32", + "typeString": "bytes32" + } + }, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "nodeType": "IndexAccess", + "src": "3004:26:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "src": "2992:38:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "id": 264, + "nodeType": "ExpressionStatement", + "src": "2992:38:0" + } + ] + } + }, + { + "expression": { + "arguments": [ + { + "id": 270, + "name": "noticePosition", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 190, + "src": "3092:14:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "hexValue": "74727565", + "id": 271, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "bool", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3108:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "value": "true" + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + ], + "expression": { + "id": 267, + "name": "noticeBitmask", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 22, + "src": "3071:13:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_uint256_$_t_uint256_$", + "typeString": "mapping(uint256 => uint256)" + } + }, + "id": 269, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3085:6:0", + "memberName": "setBit", + "nodeType": "MemberAccess", + "referencedDeclaration": 946, + "src": "3071:20:0", + "typeDescriptions": { + "typeIdentifier": "t_function_delegatecall_nonpayable$_t_mapping$_t_uint256_$_t_uint256_$_$_t_uint256_$_t_bool_$returns$__$attached_to$_t_mapping$_t_uint256_$_t_uint256_$_$", + "typeString": "function (mapping(uint256 => uint256),uint256,bool)" + } + }, + "id": 272, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3071:42:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 273, + "nodeType": "ExpressionStatement", + "src": "3071:42:0" + }, + { + "expression": { + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "id": 274, + "name": "_tokenIds", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33, + "src": "3119:9:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Counter_$3662_storage", + "typeString": "struct Counters.Counter storage ref" + } + }, + "id": 276, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3129:9:0", + "memberName": "increment", + "nodeType": "MemberAccess", + "referencedDeclaration": 3688, + "src": "3119:19:0", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_struct$_Counter_$3662_storage_ptr_$returns$__$attached_to$_t_struct$_Counter_$3662_storage_ptr_$", + "typeString": "function (struct Counters.Counter storage pointer)" + } + }, + "id": 277, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3119:21:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 278, + "nodeType": "ExpressionStatement", + "src": "3119:21:0" + }, + { + "assignments": [ + 280 + ], + "declarations": [ + { + "constant": false, + "id": 280, + "mutability": "mutable", + "name": "newItemId", + "nameLocation": "3155:9:0", + "nodeType": "VariableDeclaration", + "scope": 302, + "src": "3147:17:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 279, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3147:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "id": 284, + "initialValue": { + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "id": 281, + "name": "_tokenIds", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 33, + "src": "3167:9:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Counter_$3662_storage", + "typeString": "struct Counters.Counter storage ref" + } + }, + "id": 282, + "isConstant": false, + "isLValue": true, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3177:7:0", + "memberName": "current", + "nodeType": "MemberAccess", + "referencedDeclaration": 3674, + "src": "3167:17:0", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_view$_t_struct$_Counter_$3662_storage_ptr_$returns$_t_uint256_$attached_to$_t_struct$_Counter_$3662_storage_ptr_$", + "typeString": "function (struct Counters.Counter storage pointer) view returns (uint256)" + } + }, + "id": 283, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3167:19:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3147:39:0" + }, + { + "expression": { + "arguments": [ + { + "id": 286, + "name": "recipient", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 241, + "src": "3198:9:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "id": 287, + "name": "newItemId", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 280, + "src": "3209:9:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "id": 285, + "name": "_mint", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 2661, + "src": "3192:5:0", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_address_$_t_uint256_$returns$__$", + "typeString": "function (address,uint256)" + } + }, + "id": 288, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3192:27:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 289, + "nodeType": "ExpressionStatement", + "src": "3192:27:0" + }, + { + "expression": { + "arguments": [ + { + "id": 291, + "name": "newItemId", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 280, + "src": "3238:9:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + { + "arguments": [ + { + "hexValue": "697066733a2f2f", + "id": 295, + "isConstant": false, + "isLValue": false, + "isPure": true, + "kind": "string", + "lValueRequested": false, + "nodeType": "Literal", + "src": "3263:9:0", + "typeDescriptions": { + "typeIdentifier": "t_stringliteral_66f0790b1cbe0dcac007f07341b00cafe2bda254914729058b5209e04b702afe", + "typeString": "literal_string \"ipfs://\"" + }, + "value": "ipfs://" + }, + { + "id": 296, + "name": "screenshotCid", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 211, + "src": "3274:13:0", + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_stringliteral_66f0790b1cbe0dcac007f07341b00cafe2bda254914729058b5209e04b702afe", + "typeString": "literal_string \"ipfs://\"" + }, + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "expression": { + "id": 293, + "isConstant": false, + "isLValue": false, + "isPure": true, + "lValueRequested": false, + "nodeType": "ElementaryTypeNameExpression", + "src": "3249:6:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_string_storage_ptr_$", + "typeString": "type(string storage pointer)" + }, + "typeName": { + "id": 292, + "name": "string", + "nodeType": "ElementaryTypeName", + "src": "3249:6:0", + "typeDescriptions": {} + } + }, + "id": 294, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3256:6:0", + "memberName": "concat", + "nodeType": "MemberAccess", + "src": "3249:13:0", + "typeDescriptions": { + "typeIdentifier": "t_function_stringconcat_pure$__$returns$_t_string_memory_ptr_$", + "typeString": "function () pure returns (string memory)" + } + }, + "id": 297, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3249:39:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + { + "typeIdentifier": "t_string_memory_ptr", + "typeString": "string memory" + } + ], + "id": 290, + "name": "_setTokenURI", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 3246, + "src": "3225:12:0", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_nonpayable$_t_uint256_$_t_string_memory_ptr_$returns$__$", + "typeString": "function (uint256,string memory)" + } + }, + "id": 298, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3225:64:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$__$", + "typeString": "tuple()" + } + }, + "id": 299, + "nodeType": "ExpressionStatement", + "src": "3225:64:0" + }, + { + "expression": { + "id": 300, + "name": "newItemId", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 280, + "src": "3303:9:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "functionReturnParameters": 155, + "id": 301, + "nodeType": "Return", + "src": "3296:16:0" + } + ] + }, + "functionSelector": "9da52e25", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "mint", + "nameLocation": "1670:4:0", + "parameters": { + "id": 152, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 148, + "mutability": "mutable", + "name": "_payload", + "nameLocation": "1690:8:0", + "nodeType": "VariableDeclaration", + "scope": 303, + "src": "1675:23:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 147, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "1675:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 151, + "mutability": "mutable", + "name": "_v", + "nameLocation": "1715:2:0", + "nodeType": "VariableDeclaration", + "scope": 303, + "src": "1700:17:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof" + }, + "typeName": { + "id": 150, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 149, + "name": "Proof", + "nameLocations": [ + "1700:5:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 543, + "src": "1700:5:0" + }, + "referencedDeclaration": 543, + "src": "1700:5:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_storage_ptr", + "typeString": "struct Proof" + } + }, + "visibility": "internal" + } + ], + "src": "1674:44:0" + }, + "returnParameters": { + "id": 155, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 154, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 303, + "src": "1735:7:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 153, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "1735:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "src": "1734:9:0" + }, + "scope": 363, + "stateMutability": "nonpayable", + "virtual": false, + "visibility": "public" + }, + { + "id": 362, + "nodeType": "FunctionDefinition", + "src": "3321:645:0", + "nodes": [], + "body": { + "id": 361, + "nodeType": "Block", + "src": "3413:553:0", + "nodes": [], + "statements": [ + { + "assignments": [ + 315 + ], + "declarations": [ + { + "constant": false, + "id": 315, + "mutability": "mutable", + "name": "dapp", + "nameLocation": "3432:4:0", + "nodeType": "VariableDeclaration", + "scope": 361, + "src": "3419:17:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ICartesiDApp_$610", + "typeString": "contract ICartesiDApp" + }, + "typeName": { + "id": 314, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 313, + "name": "ICartesiDApp", + "nameLocations": [ + "3419:12:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 610, + "src": "3419:12:0" + }, + "referencedDeclaration": 610, + "src": "3419:12:0", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ICartesiDApp_$610", + "typeString": "contract ICartesiDApp" + } + }, + "visibility": "internal" + } + ], + "id": 319, + "initialValue": { + "arguments": [ + { + "id": 317, + "name": "dappAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 28, + "src": "3452:11:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + } + ], + "id": 316, + "name": "ICartesiDApp", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 610, + "src": "3439:12:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_ICartesiDApp_$610_$", + "typeString": "type(contract ICartesiDApp)" + } + }, + "id": 318, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "typeConversion", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3439:25:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_ICartesiDApp_$610", + "typeString": "contract ICartesiDApp" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3419:45:0" + }, + { + "expression": { + "arguments": [ + { + "id": 323, + "name": "_payload", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 305, + "src": "3514:8:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + }, + { + "id": 324, + "name": "_v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 308, + "src": "3523:2:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof calldata" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + }, + { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof calldata" + } + ], + "expression": { + "id": 320, + "name": "dapp", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 315, + "src": "3494:4:0", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ICartesiDApp_$610", + "typeString": "contract ICartesiDApp" + } + }, + "id": 322, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3499:14:0", + "memberName": "validateNotice", + "nodeType": "MemberAccess", + "referencedDeclaration": 596, + "src": "3494:19:0", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_bytes_memory_ptr_$_t_struct$_Proof_$543_memory_ptr_$returns$_t_bool_$", + "typeString": "function (bytes memory,struct Proof memory) view external returns (bool)" + } + }, + "id": 325, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3494:32:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "id": 326, + "nodeType": "ExpressionStatement", + "src": "3494:32:0" + }, + { + "assignments": [ + null, + 328, + null + ], + "declarations": [ + null, + { + "constant": false, + "id": 328, + "mutability": "mutable", + "name": "firstInputIndex", + "nameLocation": "3601:15:0", + "nodeType": "VariableDeclaration", + "scope": 361, + "src": "3593:23:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 327, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3593:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + }, + null + ], + "id": 337, + "initialValue": { + "arguments": [ + { + "id": 333, + "name": "dappAddress", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 28, + "src": "3651:11:0", + "typeDescriptions": { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + { + "expression": { + "id": 334, + "name": "_v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 308, + "src": "3663:2:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof calldata" + } + }, + "id": 335, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3666:7:0", + "memberName": "context", + "nodeType": "MemberAccess", + "referencedDeclaration": 542, + "src": "3663:10:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_address", + "typeString": "address" + }, + { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes calldata" + } + ], + "expression": { + "arguments": [], + "expression": { + "argumentTypes": [], + "expression": { + "id": 329, + "name": "dapp", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 315, + "src": "3622:4:0", + "typeDescriptions": { + "typeIdentifier": "t_contract$_ICartesiDApp_$610", + "typeString": "contract ICartesiDApp" + } + }, + "id": 330, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3627:12:0", + "memberName": "getConsensus", + "nodeType": "MemberAccess", + "referencedDeclaration": 609, + "src": "3622:17:0", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$__$returns$_t_contract$_IConsensus_$530_$", + "typeString": "function () view external returns (contract IConsensus)" + } + }, + "id": 331, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3622:19:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_contract$_IConsensus_$530", + "typeString": "contract IConsensus" + } + }, + "id": 332, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3642:8:0", + "memberName": "getClaim", + "nodeType": "MemberAccess", + "referencedDeclaration": 525, + "src": "3622:28:0", + "typeDescriptions": { + "typeIdentifier": "t_function_external_view$_t_address_$_t_bytes_memory_ptr_$returns$_t_bytes32_$_t_uint256_$_t_uint256_$", + "typeString": "function (address,bytes memory) view external returns (bytes32,uint256,uint256)" + } + }, + "id": 336, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3622:52:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_tuple$_t_bytes32_$_t_uint256_$_t_uint256_$", + "typeString": "tuple(bytes32,uint256,uint256)" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3590:84:0" + }, + { + "assignments": [ + 339 + ], + "declarations": [ + { + "constant": false, + "id": 339, + "mutability": "mutable", + "name": "inputIndex", + "nameLocation": "3689:10:0", + "nodeType": "VariableDeclaration", + "scope": 361, + "src": "3681:18:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 338, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3681:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "id": 345, + "initialValue": { + "commonType": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "id": 344, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "leftExpression": { + "id": 340, + "name": "firstInputIndex", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 328, + "src": "3702:15:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "BinaryOperation", + "operator": "+", + "rightExpression": { + "expression": { + "expression": { + "id": 341, + "name": "_v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 308, + "src": "3720:2:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof calldata" + } + }, + "id": 342, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3723:8:0", + "memberName": "validity", + "nodeType": "MemberAccess", + "referencedDeclaration": 540, + "src": "3720:11:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_OutputValidityProof_$638_calldata_ptr", + "typeString": "struct OutputValidityProof calldata" + } + }, + "id": 343, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3732:21:0", + "memberName": "inputIndexWithinEpoch", + "nodeType": "MemberAccess", + "referencedDeclaration": 621, + "src": "3720:33:0", + "typeDescriptions": { + "typeIdentifier": "t_uint64", + "typeString": "uint64" + } + }, + "src": "3702:51:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3681:72:0" + }, + { + "assignments": [ + 347 + ], + "declarations": [ + { + "constant": false, + "id": 347, + "mutability": "mutable", + "name": "noticePosition", + "nameLocation": "3810:14:0", + "nodeType": "VariableDeclaration", + "scope": 361, + "src": "3802:22:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + }, + "typeName": { + "id": 346, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "3802:7:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "visibility": "internal" + } + ], + "id": 355, + "initialValue": { + "arguments": [ + { + "expression": { + "expression": { + "id": 350, + "name": "_v", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 308, + "src": "3866:2:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof calldata" + } + }, + "id": 351, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3869:8:0", + "memberName": "validity", + "nodeType": "MemberAccess", + "referencedDeclaration": 540, + "src": "3866:11:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_OutputValidityProof_$638_calldata_ptr", + "typeString": "struct OutputValidityProof calldata" + } + }, + "id": 352, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3878:22:0", + "memberName": "outputIndexWithinInput", + "nodeType": "MemberAccess", + "referencedDeclaration": 623, + "src": "3866:34:0", + "typeDescriptions": { + "typeIdentifier": "t_uint64", + "typeString": "uint64" + } + }, + { + "id": 353, + "name": "inputIndex", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 339, + "src": "3901:10:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint64", + "typeString": "uint64" + }, + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "id": 348, + "name": "LibOutputValidation", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 884, + "src": "3827:19:0", + "typeDescriptions": { + "typeIdentifier": "t_type$_t_contract$_LibOutputValidation_$884_$", + "typeString": "type(library LibOutputValidation)" + } + }, + "id": 349, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3847:18:0", + "memberName": "getBitMaskPosition", + "nodeType": "MemberAccess", + "referencedDeclaration": 852, + "src": "3827:38:0", + "typeDescriptions": { + "typeIdentifier": "t_function_internal_pure$_t_uint256_$_t_uint256_$returns$_t_uint256_$", + "typeString": "function (uint256,uint256) pure returns (uint256)" + } + }, + "id": 354, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3827:85:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + }, + "nodeType": "VariableDeclarationStatement", + "src": "3802:110:0" + }, + { + "expression": { + "arguments": [ + { + "id": 358, + "name": "noticePosition", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 347, + "src": "3946:14:0", + "typeDescriptions": { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + ], + "expression": { + "argumentTypes": [ + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + ], + "expression": { + "id": 356, + "name": "noticeBitmask", + "nodeType": "Identifier", + "overloadedDeclarations": [], + "referencedDeclaration": 22, + "src": "3925:13:0", + "typeDescriptions": { + "typeIdentifier": "t_mapping$_t_uint256_$_t_uint256_$", + "typeString": "mapping(uint256 => uint256)" + } + }, + "id": 357, + "isConstant": false, + "isLValue": false, + "isPure": false, + "lValueRequested": false, + "memberLocation": "3939:6:0", + "memberName": "getBit", + "nodeType": "MemberAccess", + "referencedDeclaration": 987, + "src": "3925:20:0", + "typeDescriptions": { + "typeIdentifier": "t_function_delegatecall_view$_t_mapping$_t_uint256_$_t_uint256_$_$_t_uint256_$returns$_t_bool_$attached_to$_t_mapping$_t_uint256_$_t_uint256_$_$", + "typeString": "function (mapping(uint256 => uint256),uint256) view returns (bool)" + } + }, + "id": 359, + "isConstant": false, + "isLValue": false, + "isPure": false, + "kind": "functionCall", + "lValueRequested": false, + "nameLocations": [], + "names": [], + "nodeType": "FunctionCall", + "src": "3925:36:0", + "tryCall": false, + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "functionReturnParameters": 312, + "id": 360, + "nodeType": "Return", + "src": "3918:43:0" + } + ] + }, + "functionSelector": "1926dbe0", + "implemented": true, + "kind": "function", + "modifiers": [], + "name": "ckeckMinted", + "nameLocation": "3330:11:0", + "parameters": { + "id": 309, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 305, + "mutability": "mutable", + "name": "_payload", + "nameLocation": "3357:8:0", + "nodeType": "VariableDeclaration", + "scope": 362, + "src": "3342:23:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_bytes_calldata_ptr", + "typeString": "bytes" + }, + "typeName": { + "id": 304, + "name": "bytes", + "nodeType": "ElementaryTypeName", + "src": "3342:5:0", + "typeDescriptions": { + "typeIdentifier": "t_bytes_storage_ptr", + "typeString": "bytes" + } + }, + "visibility": "internal" + }, + { + "constant": false, + "id": 308, + "mutability": "mutable", + "name": "_v", + "nameLocation": "3382:2:0", + "nodeType": "VariableDeclaration", + "scope": 362, + "src": "3367:17:0", + "stateVariable": false, + "storageLocation": "calldata", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_calldata_ptr", + "typeString": "struct Proof" + }, + "typeName": { + "id": 307, + "nodeType": "UserDefinedTypeName", + "pathNode": { + "id": 306, + "name": "Proof", + "nameLocations": [ + "3367:5:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 543, + "src": "3367:5:0" + }, + "referencedDeclaration": 543, + "src": "3367:5:0", + "typeDescriptions": { + "typeIdentifier": "t_struct$_Proof_$543_storage_ptr", + "typeString": "struct Proof" + } + }, + "visibility": "internal" + } + ], + "src": "3341:44:0" + }, + "returnParameters": { + "id": 312, + "nodeType": "ParameterList", + "parameters": [ + { + "constant": false, + "id": 311, + "mutability": "mutable", + "name": "", + "nameLocation": "-1:-1:-1", + "nodeType": "VariableDeclaration", + "scope": 362, + "src": "3407:4:0", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + }, + "typeName": { + "id": 310, + "name": "bool", + "nodeType": "ElementaryTypeName", + "src": "3407:4:0", + "typeDescriptions": { + "typeIdentifier": "t_bool", + "typeString": "bool" + } + }, + "visibility": "internal" + } + ], + "src": "3406:6:0" + }, + "scope": 363, + "stateMutability": "view", + "virtual": false, + "visibility": "public" + } + ], + "abstract": false, + "baseContracts": [ + { + "baseName": { + "id": 8, + "name": "ERC721URIStorage", + "nameLocations": [ + "414:16:0" + ], + "nodeType": "IdentifierPath", + "referencedDeclaration": 3277, + "src": "414:16:0" + }, + "id": 9, + "nodeType": "InheritanceSpecifier", + "src": "414:16:0" + } + ], + "canonicalName": "RivesScoreNFT", + "contractDependencies": [], + "contractKind": "contract", + "fullyImplemented": true, + "linearizedBaseContracts": [ + 363, + 3277, + 2987, + 3304, + 2057, + 3103, + 3983, + 3995, + 3656 + ], + "name": "RivesScoreNFT", + "nameLocation": "397:13:0", + "scope": 364, + "usedErrors": [], + "usedEvents": [ + 2049, + 2056, + 3002, + 3011, + 3020 + ] + } + ], + "license": "Apache-2.0" + }, + "id": 0 +} \ No newline at end of file diff --git a/frontend/app/favicon.ico b/frontend/app/favicon.ico index 6c67b13..d72162a 100644 Binary files a/frontend/app/favicon.ico and b/frontend/app/favicon.ico differ diff --git a/frontend/app/globals.css b/frontend/app/globals.css index 35631d7..57cef31 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -34,11 +34,11 @@ body { @layer base { :root { - --foreground-rgb: 0, 0, 0; - --foreground-rgb-muted: rgba(0, 0, 0, 0.6); - --background-start-rgb: 214, 219, 220; - --background-end-rgb: 255, 255, 255; - --background-end-rgba0: rgba(255, 255, 255, 0.4); + --foreground-rgb: 0,0,0; + --foreground-rgb-muted: rgba(241, 245, 249, 0.6); + --background-start-rgb: 36, 36, 36; + --background-end-rgb: 105, 105, 105; + --background-end-rgba0: rgba(100, 100, 100, 0.4); --highlight-text-start-hex: #ed479a; --highlight-text-end-hex: #8b5cf6; --highlight-text-end-rgba0: rgba(139, 92, 246, 0.4); @@ -47,56 +47,11 @@ body { --highlight-text-end-rgba3: rgba(139, 92, 246, 0.1); --highlight-text-end-rgba4: rgba(139, 92, 246, 0.05); } - @media (prefers-color-scheme: dark) { - :root { - --foreground-rgb: 241, 245, 249; - --foreground-rgb-muted: rgba(241, 245, 249, 0.6); - --background-start-rgb: 36, 36, 36; - --background-end-rgb: 105, 105, 105; - --background-end-rgba0: rgba(100, 100, 100, 0.4); - } - } - :root[data-theme="dark"] { - --foreground-rgb: 241, 245, 249; - --foreground-rgb-muted: rgba(241, 245, 249, 0.6); - --background-start-rgb: 36, 36, 36; - --background-end-rgb: 105, 105, 105; - --background-end-rgba0: rgba(100, 100, 100, 0.4); -} } body { color: rgb(var(--foreground-rgb)); - background: linear-gradient( - to bottom, - transparent, - rgb(var(--background-end-rgb)) - ) - rgb(var(--background-start-rgb)) fixed; -} - - -body { - font-family: "Work Sans", sans-serif; -} - -.link-2step-hover { - background-image: linear-gradient(to right, var(--highlight-text-start-hex), var(--highlight-text-end-hex)); - background-size: 200% .1em; /* .08em is our fixed height, use what you want */ - background-position: 200% 100%; - background-repeat: no-repeat; - transition: background-size, background-position .3s; -} -.link-2step-hover:hover { - transition: background-size, background-position .3s; - background-position: 100% 100%; -} - -.link-active { - background-image: linear-gradient(to right, var(--highlight-text-start-hex), var(--highlight-text-end-hex)); - background-size: 200% .1em; /* .08em is our fixed height, use what you want */ - background-repeat: no-repeat; - background-position: 100% 100%; + background-color: rgb(var(--background-start-rgb)); } .hover-2 { @@ -250,18 +205,18 @@ body { transition: all 900ms cubic-bezier(0.48, 0, 0.12, 1); } -@layer utilities { - .max-container { - @apply max-w-5xl mx-auto sm:p-16 pb-12 !pt-[126px] px-8 min-h-[calc(100vh-80px)]; - } +.rainbow-background { + background: linear-gradient(90deg, rgba(255,0,0,1) 0%, rgba(255,154,0,1) 10%, rgba(208,222,33,1) 20%, rgba(79,220,74,1) 30%, rgba(63,218,216,1) 40%, rgba(47,201,226,1) 50%, rgba(28,127,238,1) 60%, rgba(95,21,242,1) 70%, rgba(186,12,248,1) 80%, rgba(251,7,217,1) 90%); +} +@layer utilities { .first-section { - @apply mx-auto md:p-16 pb-12 !pt-[126px] px-8 h-svh flex flex-col items-center max-w-screen-lg; + @apply mx-auto pb-12 !pt-[126px] px-8 h-fit flex flex-col items-center; } .second-section { - @apply mx-auto md:p-16 pb-12 !pt-[126px] px-8 h-svh flex flex-row; + @apply pb-12 !pt-[64px] h-svh flex flex-col; } .custom-scrollbar { @@ -285,12 +240,17 @@ body { @apply font-semibold sm:text-4xl text-xl relative title-color; } + + .games-list { + @apply flex flex-wrap ms-[148px] mb-24; + } + .games-list-item { - @apply sm:w-auto px-4 py-2 grow break-all text-start hover-2; + @apply p-4 text-center bg-gray-400 hover:games-list-selected-item; } .games-list-selected-item { - @apply hover-2-selected; + @apply bg-gradient-to-r from-yellow-100 to-pink-300; } .fallback-bg-color { @@ -306,11 +266,11 @@ body { } .game-option-tabs-header { - @apply flex space-x-1 rounded-xl bg-[rgb(var(--background-start-rgb))] p-1; + @apply flex space-x-1 bg-gray-400 bg-opacity-40 p-1; } .game-tabs-option { - @apply w-full rounded-lg py-2.5 text-sm font-medium leading-5 ring-[var(--highlight-text-end-hex)] focus:ring-4; + @apply w-full py-2.5 text-sm; } .game-tabs-option-text { @@ -322,186 +282,52 @@ body { } .game-tabs-option-unselected { - @apply game-tabs-option text-[rgb(var(--foreground-rgb))] hover:bg-[var(--background-end-rgba0)] hover:text-[var(--highlight-text-end-hex)]; + @apply game-tabs-option hover:bg-gray-400; } .game-tabs-option-selected { - @apply game-tabs-option bg-[rgb(var(--background-end-rgb))] text-[var(--highlight-text-end-hex)] shadow; + @apply game-tabs-option bg-gray-400; } .game-tab-content { - @apply rounded-xl bg-[rgb(var(--background-end-rgb))] p-3; - } - - - .web3-connect-btn { - @apply rounded text-sm p-2 shadow-sm shadow-current;/*bg-gradient-to-r from-[var(--highlight-text-start-hex)] to-[var(--highlight-text-end-hex)];*/ - } - - .web3-connect-btn:hover { - @apply text-[var(--highlight-text-end-hex)] shadow-[var(--highlight-text-end-hex)]; + @apply p-3 bg-gray-400; } .muted-text { @apply text-[var(--foreground-rgb-muted)]; } - .scoreboard-btn { @apply hover:text-[var(--highlight-text-end-hex)]; } - /* .leaderboard-card { - @apply p-2 bg-[rgb(var(--background-start-rgb))] mb-3 rounded-md transition delay-150 duration-300 ease-in-out hover:scale-105; - } */ - - - - - - .blue-gradient_text { - @apply bg-gradient-to-r from-[#00c6ff] to-[#0072ff] bg-clip-text text-transparent; - } - - .input { - @apply bg-white border border-gray-200 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 mt-2.5 font-normal; - } - - .textarea { - @apply block p-2.5 w-full text-sm text-gray-900 bg-white rounded-lg border border-gray-200 focus:ring-blue-500 focus:border-blue-500 mt-2.5 font-normal; - } - - .btn { - @apply text-white bg-gradient-to-r from-[#00c6ff] to-[#0072ff] focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center; - } .header { - @apply max-w-screen-lg sm:px-16 px-8 py-4 mx-auto flex justify-between items-center absolute top-0 bg-transparent z-10 right-0 left-0; + @apply w-full h-16 bg-[var(--highlight-text-end-hex)] flex absolute top-0 z-10; } - .footer { - @apply max-w-5xl mx-auto sm:px-16 pb-6 px-8 flex flex-col gap-7; + .link-active { + @apply bg-[rgb(var(--background-start-rgb))] text-white; } - .footer-container { - @apply flex flex-wrap gap-7 items-center justify-between; + .navbar-item { + @apply px-6 hover:bg-[rgb(var(--background-start-rgb))] hover:text-white; } - .info-box { - @apply mx-5 relative flex text-white flex-col gap-3 max-w-2xl neo-brutalism-blue pt-4 pb-12 px-8; + .btn { + @apply p-3 bg-[var(--highlight-text-end-hex)] border border-[var(--highlight-text-end-hex)] hover:bg-[rgb(var(--background-start-rgb))] hover:text-[var(--highlight-text-end-hex)]; } - .neo-btn { - @apply py-3 px-6 rounded-lg text-blue-500 text-center font-semibold sm:w-1/2 w-[90%] -bottom-5 absolute mx-auto right-0 left-0 flex justify-center items-center gap-3; + .btn:disabled, + .btn[disabled]{ + opacity: 70%; + cursor: not-allowed; } - .cta { - @apply w-full flex items-center md:flex-row flex-col sm:mt-16 mt-8 gap-7; + .gameplay-screen { + @apply w-[640px] h-[400px] md:w-[720px] md:h-[480px] lg:w-[960px] lg:h-[720px]; } - .cta-text { - @apply text-black-500 font-extrabold flex-1 text-3xl max-md:text-center; + .gameplay-section { + @apply gameplay-screen fixed z-10 top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2; } } - -.glassmorphism { - background: rgba(8, 116, 239, 0.07); - backdrop-filter: blur(10px); - -webkit-backdrop-filter: blur(10px); - border-radius: 10px; - border: 1px solid rgba(255, 255, 255, 0.18); -} - -.logo { - border-radius: 8.889px; - background: #fff; - box-shadow: 0px 10px 35px -4px rgba(67, 83, 255, 0.15), - 0px 1.5px 4px -1px rgba(67, 83, 255, 0.2); -} - -.block-container { - position: relative; - transition: 250ms; - perspective: 500px; -} - -.block-container .btn-back { - position: absolute; - inset: 0; - z-index: -1; - width: inherit; - height: inherit; - transition: 250ms; - transform-style: preserve-3d; - transform-origin: bottom right; - transform: rotateZ(15deg); - will-change: transform; - box-shadow: 16px 0 40px #e4e4e4; -} - -.block-container .btn-back-red { - background: linear-gradient(135deg, #ff4b1f -20%, #ff9068 120%); -} - -.block-container .btn-back-green { - background: linear-gradient(135deg, #adfda2 -20%, #11d3f3 120%); -} - -.block-container .btn-back-yellow { - background: linear-gradient(135deg, #f7971e -20%, #ffd200 120%); -} - -.block-container .btn-back-blue { - background: linear-gradient(135deg, #0061ff -20%, #60efff 120%); -} - -.block-container .btn-back-orange { - background: linear-gradient(135deg, #ff0f7b -20%, #f89b29 120%); -} - -.block-container .btn-back-pink { - background: linear-gradient(135deg, #e81cff -20%, #40c9ff 120%); -} - -.block-container .btn-back-black { - background: linear-gradient(135deg, #0a1647 -20%, #e4e7e4 120%); -} - -.block-container .btn-front { - position: absolute; - inset: 0; - z-index: 1; - width: inherit; - height: inherit; - background-color: #ffffff33; - -webkit-backdrop-filter: blur(20px); - backdrop-filter: blur(20px); - transition: 250ms; - transform-style: preserve-3d; - transform-origin: top left; - overflow: hidden; -} - -.block-container:hover > .btn-back { - transform: translateZ(20px) rotateZ(15deg) rotateX(-20deg) rotateY(-20deg); -} - -.block-container:hover > .btn-front { - transform: translateZ(80px) translateY(-5px) rotateX(15deg) rotateY(15deg); -} - -/* Neo Brutalism */ -.neo-brutalism-blue { - background: #2b77e7; - position: relative; - border-radius: 10px; - border: #2b77e7; - box-shadow: 0.6vmin 0.6vmin #336cc1, 1vmin 1vmin #0092db, 1vmin 1vmin #0092db, - 0.65vmin 1vmin #0092db, 1vmin 0.65vmin #0092db; -} - -.neo-brutalism-white { - background: #fff; - border: #fff; - box-shadow: 0.6vmin 0.6vmin #fff, 1vmin 1vmin #d2e4ff, 1vmin 1vmin #d2e4ff, - 0.65vmin 1vmin #d2e4ff, 1vmin 0.65vmin #d2e4ff; -} diff --git a/frontend/app/insert-cartridge/page.tsx b/frontend/app/insert-cartridge/page.tsx index d8ee46e..43cbae5 100644 --- a/frontend/app/insert-cartridge/page.tsx +++ b/frontend/app/insert-cartridge/page.tsx @@ -4,7 +4,7 @@ import { fontPressStart2P } from "../utils/font" export default function InsertCartridge() { return ( <main className="flex items-center justify-center h-lvh"> - <span className={`${fontPressStart2P.className} text-4xl` }>Coming Soon!</span> + <span className={`${fontPressStart2P.className} text-4xl text-white` }>Coming Soon!</span> </main> ) } diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index fdc5901..81cb726 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -2,25 +2,23 @@ import type { Metadata } from 'next' import './globals.css' import Navbar from '@/app/components/Navbar'; import {Web3OnboardProviderClient} from './utils/web3OnboardProvider'; -import { getCookieTheme } from './utils/theme'; +import { fontPressStart2P } from './utils/font'; export const metadata: Metadata = { title: 'RiVES', description: 'RiscV Verifiable Entertainment System', } -export default async function RootLayout({ +export default function RootLayout({ children, }: { children: React.ReactNode }) { - let theme = (await getCookieTheme()) || "light"; - return ( - <html lang="en-US" data-theme={theme}> + <html lang="en-US"> <Web3OnboardProviderClient> - <body> + <body className={fontPressStart2P.className}> <Navbar></Navbar> {children} </body> diff --git a/frontend/app/mint/[input_index]/page.tsx b/frontend/app/mint/[input_index]/page.tsx new file mode 100644 index 0000000..a14870e --- /dev/null +++ b/frontend/app/mint/[input_index]/page.tsx @@ -0,0 +1,361 @@ +"use client" +import { useSearchParams } from 'next/navigation' +import { useState, useEffect, useMemo } from 'react' +import Image from 'next/image'; +import { Contract, ethers } from 'ethers'; +import { useConnectWallet } from "@web3-onboard/react"; + + +import { ReplayScore, getOutputs } from "../../backend-libs/app/lib"; +import { envClient } from '../../utils/clientEnv'; +import { fontPressStart2P } from "../../utils/font" +import nftAbiFile from "../../contracts/RivesScoreNFT.sol/RivesScoreNFT.json" +import { delay } from "../../utils/util"; +import CheckIcon from "../../components/svg/CheckIcon"; +import ErrorIcon from "../../components/svg/ErrorIcon"; +import CloseIcon from "@mui/icons-material/Close"; + +const nftAbi: any = nftAbiFile; + +const BASE64_KEY = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +export function byteToBase64(bytes: Uint8Array): String { + let newBase64 = ''; + let currentChar = 0; + for (let i=0; i<bytes.length; i++) { // Go over three 8-bit bytes to encode four base64 6-bit chars + if (i%3===0) { // First Byte + currentChar = (bytes[i] >> 2); // First 6-bits for first base64 char + newBase64 += BASE64_KEY[currentChar]; // Add the first base64 char to the string + currentChar = (bytes[i] << 4) & 63; // Erase first 6-bits, add first 2 bits for second base64 char + } + if (i%3===1) { // Second Byte + currentChar += (bytes[i] >> 4); // Concat first 4-bits from second byte for second base64 char + newBase64 += BASE64_KEY[currentChar]; // Add the second base64 char to the string + currentChar = (bytes[i] << 2) & 63; // Add two zeros, add 4-bits from second half of second byte + } + if (i%3===2) { // Third Byte + currentChar += (bytes[i] >> 6); // Concat first 2-bits of third byte for the third base64 char + newBase64 += BASE64_KEY[currentChar]; // Add the third base64 char to the string + currentChar = bytes[i] & 63; // Add last 6-bits from third byte for the fourth base64 char + newBase64 += BASE64_KEY[currentChar]; // Add the fourth base64 char to the string + } + } + if (bytes.length%3===1) { // Pad for two missing bytes + newBase64 += `${BASE64_KEY[currentChar]}==`; + } + if (bytes.length%3===2) { // Pad one missing byte + newBase64 += `${BASE64_KEY[currentChar]}=`; + } + return newBase64; +} + +enum STATUS { + READY, + VALID, + INVALID, +} + +interface FEEDBACK_STATUS { + status:STATUS, + message?:string +} + +const Feedback = ({feedback,setFeedback}:{feedback:FEEDBACK_STATUS, setFeedback(s:FEEDBACK_STATUS):void}) => { + if (feedback.status === STATUS.VALID) { + delay(2500).then(() =>{ + setFeedback({status: STATUS.READY} as FEEDBACK_STATUS); + }) + return ( + <div className="fixed flex items-center max-w-xs p-4 space-x-4 text-gray-500 bg-white rounded-lg shadow-lg right-5 bottom-20 dark:text-gray-400 dark:divide-gray-700 space-x dark:bg-gray-800" role="alert"> + <CheckIcon/> + <div className="ms-3 text-sm font-bold">{feedback.message}</div> + </div> + ) + } else if (feedback.status === STATUS.INVALID) { + const click = () => { + setFeedback({status: STATUS.READY} as FEEDBACK_STATUS) + } + return ( + <div className="fixed flex-col items-center max-w-xs p-4 space-x-4 text-gray-500 bg-white rounded-lg shadow right-5 bottom-[20%] dark:text-gray-400 dark:divide-gray-700 space-x dark:bg-gray-800" role="alert"> + <div className="flex items-center pb-1 border-b"> + <ErrorIcon/> + <div className="ms-3 text-sm font-normal">Invalid</div> + <button onClick={click} type="button" className="ms-auto -mx-1.5 -my-1.5 bg-white text-gray-400 hover:text-gray-900 rounded-lg focus:ring-2 focus:ring-gray-300 p-1.5 hover:bg-gray-100 inline-flex items-center justify-center h-8 w-8 dark:text-gray-500 dark:hover:text-white dark:bg-gray-800 dark:hover:bg-gray-700" data-dismiss-target="#toast-danger" aria-label="Close"> + <span className="sr-only">Close</span> + <CloseIcon/> + </button> + </div> + <div> + {feedback.message} + </div> + </div> + ) + } +} + +export default function Page({ params }: { params: { input_index: String } }) { + // const pathname = usePathname(); + const searchParams = useSearchParams(); + const inputIndex = useMemo(() => parseInt(`${params.input_index}`),[]); + + let signature: String | null = null; + + if (searchParams.has("signature") && searchParams.get("signature") != null) + signature = searchParams.get("signature"); + + if (inputIndex == undefined) + return ( + <main className="flex items-center justify-center h-lvh"> + <span className={`${fontPressStart2P.className} text-4xl` }>Nothing to show here!</span> + <span>No input index defined</span> + </main> + ) + + return ( + <main className="flex items-center justify-center h-lvh"> + <Info inputIndex={inputIndex} signature={signature} /> + </main> + ) + +} + +const Info = ({inputIndex,signature}:{inputIndex: number,signature:String|null}) => { + const [{ wallet }] = useConnectWallet(); + const [score,setScore] = useState<ReplayScore>(); + + + const [nftContract,setNftContract] = useState<Contract>(); + const [gamelogOwner,setGamelogOwner] = useState<String>(); + const [operator,setOperator] = useState<String>(); + const [signerAddress,setSignerAddress] = useState<String>(); + const [alreadyMinted,setAlreadyMinted] = useState<boolean>(false); + const [feedback, setFeedback] = useState({status: STATUS.READY} as FEEDBACK_STATUS); + // const score: ReplayScore | undefined = await useMemo( async () => { + // const out = await getOutputs({tags: ["screenshot"],input_index: inputIndex}, {cartesiNodeUrl: envClient.CARTESI_NODE_URL}) + // if (out.length == 0) return undefined; + // return out[0] as ReplayScore; + // }, []); + + useEffect(() => { + if (!wallet) { + setNftContract(undefined); + return; + } + const curSigner = new ethers.providers.Web3Provider(wallet.provider, 'any').getSigner(); + const curContract = new ethers.Contract(envClient.NFT_ADDR,nftAbi.abi,curSigner); + curContract.provider.getCode(curContract.address).then((code) => { + if (code == '0x') { + console.log("Couldn't get nft contract") + return; + } + setNftContract(curContract); + curSigner.getAddress().then((a: String) => setSignerAddress(a.toLowerCase())); + curContract.operator().then((o: String) => setOperator(o.toLowerCase())); + if (score != undefined && score.gameplay_hash != undefined) { + curContract.gamelogOwner(score.gameplay_hash).then((o: String) => setGamelogOwner(o.toLowerCase())); + if (score._proof != undefined) + curContract.ckeckMinted(score._payload,score._proof).then((o: boolean) => {console.log("minted",o);setAlreadyMinted(o)}); + } + }); + },[wallet,score]); + + useEffect(() => getScore(),[]); + + const getScore = () => { + getOutputs({tags: ["score"],input_index: inputIndex}, {cartesiNodeUrl: envClient.CARTESI_NODE_URL}) + .then((out) =>{ + if (out.length == 0) return; + const curScore = out[0] as ReplayScore; + setScore(curScore); + }); + }; + + + const feedbackAndReload = (message: string) => { + setFeedback({status:STATUS.VALID,message:message}); + getScore(); + }; + + if (score == undefined) + return ( + <div className="flex flex-col items-center text-white"> + <span className={`${fontPressStart2P.className} text-1xl` }>Gameplay not processed by the Cartesi Machine Backend (yet)!</span> + <button className="btn mt-5 w-48" onClick={() => {getScore()}}> + Reload Score + </button> + </div> + ); + + return ( + <div className="flex flex-col"> + <Screenshot inputIndex={inputIndex} /> + <NftButtons signature={signature} score={score} nftContract={nftContract} + gamelogOwner={gamelogOwner} operator={operator} signerAddress={signerAddress} + alreadyMinted={alreadyMinted} reload={feedbackAndReload} /> + <Feedback feedback={feedback} setFeedback={setFeedback} /> + + </div> + ); +}; + + +const NftButtons = ({signature,score,nftContract,gamelogOwner,operator,signerAddress,alreadyMinted,reload}: + {signature:String|null,score:ReplayScore,nftContract:Contract|undefined,gamelogOwner:String|undefined, + operator:String|undefined,signerAddress:String|undefined,alreadyMinted:boolean|undefined,reload(s:String):void}) => { + + const userAddress = score.user_address?.toLowerCase(); + + const mint = async () => { + if (score?._proof == undefined) { + alert("No proofs yet."); + return; + } + if (!nftContract) { + alert("Contract not loaded."); + return; + } + if (alreadyMinted) { + alert("Already Minted."); + return; + } + if (operator == userAddress && (!gamelogOwner || gamelogOwner == '0x0000000000000000000000000000000000000000')) { + alert("Operator generated (register first)."); + return; + } + nftContract.mint(score._payload,score._proof). + then((res: any) => { + res.wait(1).then( + (receipt: any) => { + console.log(receipt) + reload("Nft Minted!"); + } + ); + } + ); + }; + + const register = async () => { + if (!signature || signature.length != 132) { + alert("Invalid signature."); + return; + } + if (!nftContract) { + alert("Contract not loaded."); + return; + } + if (alreadyMinted) { + alert("Already Minted."); + return; + } + if (signerAddress == operator){ + alert("Operator can't register."); + return; + } + if (gamelogOwner != '0x0000000000000000000000000000000000000000') { + alert("Already registered."); + return; + } + const r = signature.slice(0, 66); + const s = "0x" + signature.slice(66, 130); + const v = parseInt(signature.slice(130, 132), 16); + + nftContract.setGameplayOwner(score.gameplay_hash,r,s,v). + then((res: any) => { + res.wait(1).then( + (receipt: any) => { + console.log(receipt) + reload("Gameplay Registered"); + } + ); + } + ); + }; + + let mintEnabled = false; + let mintMessage = <></>; + if (score?._proof == undefined) + mintMessage = <span>(check again later, no proofs yet)</span>; + else if (!nftContract) + mintMessage = <span>(connect wallet)</span>; + else if (alreadyMinted) + mintMessage = <span>(already Minted)</span>; + else if (operator == userAddress && (!gamelogOwner || gamelogOwner == '0x0000000000000000000000000000000000000000')) + mintMessage = <span>(operator generated, register first)</span>; + else { + mintEnabled = true; + mintMessage = <span></span>; + } + + const mintButton = + <button className="btn" onClick={() => {mint()}} disabled={!mintEnabled}> + <span>Mint Score Screenshot NFT</span><br/> + {mintMessage} + </button> + ; + + let showRegister = false; + let registerEnabled = false; + let registerMessage = <></>; + if (!nftContract) + registerMessage = <span>(connect wallet)</span>; + else if (alreadyMinted) + mintMessage = <span>(already Minted)</span>; + else if (operator == userAddress) { + showRegister = true; + if (signerAddress == operator) + registerMessage = <span>(operator can't register)</span>; + else if (gamelogOwner != '0x0000000000000000000000000000000000000000') + registerMessage = <span>(already registered)</span>; + else if (!signature) + registerMessage = <span>(no signature)</span>; + else { + registerEnabled = true + registerMessage = <span></span>; + } + } + + const registerButton = !showRegister ? + <></> + : + <button className="btn" onClick={() => {register()}} disabled={!registerEnabled}> + <span>Register Gameplay</span><br/> + {registerMessage} + </button> + ; + + return ( + <div className='flex flex-col space-y-1 mt-1 text-sm'> + {mintButton} + {registerButton} + </div> +); +} +const Screenshot = ({inputIndex}:{inputIndex: number}) => { + const [base64Image,setBase64Image] = useState<String>(); + useEffect(() => { + if (inputIndex == undefined) return; + getOutputs({tags: ["screenshot"],input_index: inputIndex}, {cartesiNodeUrl: envClient.CARTESI_NODE_URL}) + .then((out) => { + if (out.length == 0) return; + setBase64Image(byteToBase64(out[0] as Uint8Array)) + }); + },[inputIndex]); + + if (!base64Image) return ( + <div> + <span className={`${fontPressStart2P.className} text-1m` }>Nothing to show here!</span> + </div> + ); + + return ( + <Image alt={"screenshot " + inputIndex} + height={512} width={1200} + id={"screenshot-" + inputIndex} + src={base64Image ? `data:image/png;base64,${base64Image}`:"/logo.png"} + style={{ + maxHeight: 512, + height: '100%', + width: 'auto' + }} + /> + ); +}; diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index 601282b..741a283 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -1,24 +1,35 @@ -import Title from "./components/Title"; +import Image from 'next/image' import YoutubeVideo from "./components/youtubeVideo"; -import { fontPressStart2P } from './utils/font'; +import rivesLogo from '../public/rives64px.png'; export default function Home() { return ( - <main className=""> + <main> <section id="presentation-section" className="first-section"> - <Title /> - {/* <h2 className={`subtitle-text title-color my-4 ${fontPressStart2P.className}`}>RiSCV Verifiable Entertainment System</h2> */} - <p className="my-6"> - <span className={fontPressStart2P.className}>RiVES</span> (RISC-V Verifiable Entertainment System) is a free and open source verifiable fantasy game console for making and playing small onchain games. - All matches generate an output that can be used by anyone to reproduce and verify the gameplay. - No more lying about that epic speedrun or completing the final stage without taking a hit. - RIVES will enable decentralized trustless tournaments so that no one can deny your bounty after an epic play! + <div className="flex space-x-2"> + <Image src={rivesLogo} alt='RiVES logo'/> + </div> + + <div className=' max-w-[640px] text-center text-white'> + <h2 className='mt-6 text-xl'> + Rives is the World Arcade + </h2> + + <p className="mt-6"> + Own cartridges, prove scores & contribute with infinite creativity </p> + </div> + + <div className='w-11/12 my-16 h-1 rainbow-background'></div> + + <div className="flex items-center justify-center"> + <YoutubeVideo videoId="7y22pdgGIE0" /> + </div> - <div className="w-1/2 flex items-center justify-center"> - <YoutubeVideo videoId="7y22pdgGIE0" /> - </div> + <a className='mt-10 btn' href={"/cartridges"}> + Start Playing + </a> </section> {/* <section id="statistical-section" className="h-svh"> diff --git a/frontend/app/utils/clientEnv.ts b/frontend/app/utils/clientEnv.ts index 542af89..3d453d1 100644 --- a/frontend/app/utils/clientEnv.ts +++ b/frontend/app/utils/clientEnv.ts @@ -13,5 +13,9 @@ export const envClient = envsafe({ NETWORK_CHAIN_ID: str({ input: process.env.NEXT_PUBLIC_NETWORK_CHAIN_ID, desc: "Network ChainId (in hex) where the Cartesi DApp was deployed." + }), + NFT_ADDR: str({ + input: process.env.NEXT_PUBLIC_NFT_ADDR, + desc: "Rives Score NFT ETH address." }) }) \ No newline at end of file diff --git a/frontend/app/utils/web3-onboard.ts b/frontend/app/utils/web3-onboard.ts index a4d42e9..ae2ed80 100644 --- a/frontend/app/utils/web3-onboard.ts +++ b/frontend/app/utils/web3-onboard.ts @@ -29,7 +29,8 @@ const web3Onboard = init({ appMetadata, connect: { autoConnectLastWallet: true - } + }, + accountCenter: {desktop: {enabled: false}, mobile: {enabled: false}} }) export default web3Onboard; \ No newline at end of file diff --git a/frontend/contracts/RivesScoreNFT.sol b/frontend/contracts/RivesScoreNFT.sol new file mode 100644 index 0000000..e37a16b --- /dev/null +++ b/frontend/contracts/RivesScoreNFT.sol @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; +import "@openzeppelin/contracts/utils/Counters.sol"; + +import {Bitmask} from "@cartesi/util/contracts/Bitmask.sol"; +import "@cartesi/rollups/contracts/dapp/ICartesiDApp.sol"; +import "@cartesi/rollups/contracts/library/LibOutputValidation.sol"; + + +contract RivesScoreNFT is ERC721URIStorage { + using Counters for Counters.Counter; + using Bitmask for mapping(uint256 => uint256); + + mapping(uint256 => uint256) noticeBitmask; + + mapping (bytes32 => address) public gamelogOwner; + + address public dappAddress; + address public operator; + + Counters.Counter private _tokenIds; + + constructor(address _dappAddress) ERC721("RivesScoreNFT", "RSNFT") { + dappAddress = _dappAddress; + operator = msg.sender; + } + + function setOperator(address newOperator) public { + require(msg.sender == operator,"Only current operator can set new operator"); + operator = newOperator; + } + + function verifySignature(bytes32 gameplayHash, bytes32 _r, bytes32 _s, uint8 _v) public pure returns (address) { + bytes32 hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", gameplayHash)); + return ecrecover(hash, _v, _r, _s); + } + + function setGameplayOwner(bytes32 gameplayHash, bytes32 _r, bytes32 _s, uint8 _v) public { + bytes32 hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", gameplayHash)); + address signer = ecrecover(hash, _v, _r, _s); + + require(signer == operator,"Singned message does not match current operator"); + + gamelogOwner[gameplayHash] = msg.sender; + } + + function mint(bytes calldata _payload, Proof calldata _v) public returns (uint256) { + ICartesiDApp dapp = ICartesiDApp(dappAddress); + + // validate notice + dapp.validateNotice(_payload,_v); + + // query the current consensus for the desired claim + (, uint256 firstInputIndex, ) = dapp.getConsensus().getClaim(dappAddress,_v.context); + + uint256 inputIndex = firstInputIndex + _v.validity.inputIndexWithinEpoch; + + // check if notice has been processed + uint256 noticePosition = LibOutputValidation.getBitMaskPosition(_v.validity.outputIndexWithinInput,inputIndex); + require(!noticeBitmask.getBit(noticePosition),"notice re-submiting not allowed"); + + // abiTypes:['bytes32', 'string', 'uint', 'int', 'int', 'int', 'string', 'string', 'string', 'bytes32'], + // params:['cartridge_id', 'user_address', 'timestamp', 'score', 'score_type', 'extra_score', 'extra', 'user_alias', 'screenshot_cid', 'gameplay_hash'], + // process notice + (, address userAddress, , , , , , , string memory screenshotCid, bytes32 gameplayHash) = abi.decode(_payload,( + bytes32, address, uint, int, int, int, string, string, string, bytes32) + ); + + address recipient = userAddress; + if (userAddress == operator) { + require(gamelogOwner[gameplayHash] != address(0),"No gameplay owner defined"); + recipient = gamelogOwner[gameplayHash]; + } + + // mark it as processed + noticeBitmask.setBit(noticePosition, true); + _tokenIds.increment(); + + uint256 newItemId = _tokenIds.current(); + _mint(recipient, newItemId); + _setTokenURI(newItemId, string.concat("ipfs://", screenshotCid)); + + return newItemId; + } + + function ckeckMinted(bytes calldata _payload, Proof calldata _v) public view returns (bool) { + ICartesiDApp dapp = ICartesiDApp(dappAddress); + + // validate notice + dapp.validateNotice(_payload,_v); + + // query the current consensus for the desired claim + (, uint256 firstInputIndex, ) = dapp.getConsensus().getClaim(dappAddress,_v.context); + + uint256 inputIndex = firstInputIndex + _v.validity.inputIndexWithinEpoch; + + // check if notice has been processed + uint256 noticePosition = LibOutputValidation.getBitMaskPosition(_v.validity.outputIndexWithinInput,inputIndex); + return noticeBitmask.getBit(noticePosition); + } +} \ No newline at end of file diff --git a/frontend/foundry.toml b/frontend/foundry.toml new file mode 100644 index 0000000..85fc20a --- /dev/null +++ b/frontend/foundry.toml @@ -0,0 +1,4 @@ +[profile.default] +src = "contracts" +out = "app/contracts" +libs = ["node_modules"] diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d03ee62..b8f46d5 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,6 +8,7 @@ "name": "world-arcade-frontend", "version": "0.1.0", "dependencies": { + "@cartesi/rollups": "^1.2.0", "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", "@headlessui/react": "^1.7.18", @@ -27,6 +28,7 @@ "next": "14.0.4", "react": "^18", "react-dom": "^18", + "react-qr-code": "^2.0.12", "react-use-downloader": "^1.2.4", "react-youtube": "^10.1.0", "three": "^0.159.0" @@ -268,6 +270,20 @@ "node": ">=6.9.0" } }, + "node_modules/@cartesi/rollups": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@cartesi/rollups/-/rollups-1.2.0.tgz", + "integrity": "sha512-oLm/JYuRpUD6bg8UKFZjdSJRZ1CWOd5SM6xnjvRKMisGZcJzULYHuuzZMSMONpnFVQhFXrwJF4q0tzcOAK4oDw==", + "dependencies": { + "@cartesi/util": "6.1.0", + "@openzeppelin/contracts": "4.9.2" + } + }, + "node_modules/@cartesi/util": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@cartesi/util/-/util-6.1.0.tgz", + "integrity": "sha512-j92nSoMHCyu6h7nZgn+MeXjkp8oa1Cy6qaImyxVXmPN2Rcqzl/TkWm/RkhbODU9rh4U3OuUteYqKRjefI3/XIQ==" + }, "node_modules/@emotion/babel-plugin": { "version": "11.11.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", @@ -2595,6 +2611,11 @@ "node": ">= 8" } }, + "node_modules/@openzeppelin/contracts": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.2.tgz", + "integrity": "sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg==" + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -7712,6 +7733,11 @@ "node": ">=6" } }, + "node_modules/qr.js": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/qr.js/-/qr.js-0.0.0.tgz", + "integrity": "sha512-c4iYnWb+k2E+vYpRimHqSu575b1/wKl4XFeJGpFmrJQz5I88v9aY2czh7s0w36srfCM1sXgC/xpoJz5dJfq+OQ==" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -7780,6 +7806,24 @@ "url": "https://github.com/sponsors/gregberge" } }, + "node_modules/react-qr-code": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.0.12.tgz", + "integrity": "sha512-k+pzP5CKLEGBRwZsDPp98/CAJeXlsYRHM2iZn1Sd5Th/HnKhIZCSg27PXO58zk8z02RaEryg+60xa4vyywMJwg==", + "dependencies": { + "prop-types": "^15.8.1", + "qr.js": "0.0.0" + }, + "peerDependencies": { + "react": "^16.x || ^17.x || ^18.x", + "react-native-svg": "*" + }, + "peerDependenciesMeta": { + "react-native-svg": { + "optional": true + } + } + }, "node_modules/react-reconciler": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.27.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index ee9ae9c..168bcd0 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,6 +9,7 @@ "lint": "next lint" }, "dependencies": { + "@cartesi/rollups": "^1.2.0", "@emotion/react": "^11.11.3", "@emotion/styled": "^11.11.0", "@headlessui/react": "^1.7.18", @@ -28,6 +29,7 @@ "next": "14.0.4", "react": "^18", "react-dom": "^18", + "react-qr-code": "^2.0.12", "react-use-downloader": "^1.2.4", "react-youtube": "^10.1.0", "three": "^0.159.0" diff --git a/frontend/public/cartesi.jpg b/frontend/public/cartesi.jpg deleted file mode 100644 index 617a7dd..0000000 Binary files a/frontend/public/cartesi.jpg and /dev/null differ diff --git a/frontend/public/rivemu.js b/frontend/public/rivemu.js index 96f4fd1..cee2e0b 100644 --- a/frontend/public/rivemu.js +++ b/frontend/public/rivemu.js @@ -1 +1 @@ -var Module=typeof Module!="undefined"?Module:{};var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort(text)}}var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var wasmBinaryFile;wasmBinaryFile="rivemu.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{if(!response["ok"]){throw"failed to load wasm binary file at '"+binaryFile+"'"}return response["arrayBuffer"]()}).catch(()=>getBinarySync(binaryFile))}}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(instance=>instance).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function createWasm(){var info={"a":wasmImports};function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["xc"];updateMemoryViews();wasmTable=wasmExports["Sc"];addOnInit(wasmExports["yc"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);return false}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}var tempDouble;var tempI64;var ASM_CONSTS={21154130:()=>{window.dispatchEvent(new Event("rivemu_on_startup"))},21154188:($0,$1,$2,$3,$4)=>{if(typeof window==="undefined"||(window.AudioContext||window.webkitAudioContext)===undefined){return 0}if(typeof window.miniaudio==="undefined"){window.miniaudio={referenceCount:0};window.miniaudio.device_type={};window.miniaudio.device_type.playback=$0;window.miniaudio.device_type.capture=$1;window.miniaudio.device_type.duplex=$2;window.miniaudio.device_state={};window.miniaudio.device_state.stopped=$3;window.miniaudio.device_state.started=$4;miniaudio.devices=[];miniaudio.track_device=function(device){for(var iDevice=0;iDevice<miniaudio.devices.length;++iDevice){if(miniaudio.devices[iDevice]==null){miniaudio.devices[iDevice]=device;return iDevice}}miniaudio.devices.push(device);return miniaudio.devices.length-1};miniaudio.untrack_device_by_index=function(deviceIndex){miniaudio.devices[deviceIndex]=null;while(miniaudio.devices.length>0){if(miniaudio.devices[miniaudio.devices.length-1]==null){miniaudio.devices.pop()}else{break}}};miniaudio.untrack_device=function(device){for(var iDevice=0;iDevice<miniaudio.devices.length;++iDevice){if(miniaudio.devices[iDevice]==device){return miniaudio.untrack_device_by_index(iDevice)}}};miniaudio.get_device_by_index=function(deviceIndex){return miniaudio.devices[deviceIndex]};miniaudio.unlock_event_types=function(){return["touchend","click"]}();miniaudio.unlock=function(){for(var i=0;i<miniaudio.devices.length;++i){var device=miniaudio.devices[i];if(device!=null&&device.webaudio!=null&&device.state===window.miniaudio.device_state.started){device.webaudio.resume().then(()=>{Module._ma_device__on_notification_unlocked(device.pDevice)},error=>{console.error("Failed to resume audiocontext",error)})}}miniaudio.unlock_event_types.map(function(event_type){document.removeEventListener(event_type,miniaudio.unlock,true)})};miniaudio.unlock_event_types.map(function(event_type){document.addEventListener(event_type,miniaudio.unlock,true)})}window.miniaudio.referenceCount+=1;return 1},21156346:()=>{if(typeof window.miniaudio!=="undefined"){miniaudio.unlock_event_types.map(function(event_type){document.removeEventListener(event_type,miniaudio.unlock,true)});window.miniaudio.referenceCount-=1;if(window.miniaudio.referenceCount===0){delete window.miniaudio}}},21156636:()=>navigator.mediaDevices!==undefined&&navigator.mediaDevices.getUserMedia!==undefined,21156740:()=>{try{var temp=new(window.AudioContext||window.webkitAudioContext);var sampleRate=temp.sampleRate;temp.close();return sampleRate}catch(e){return 0}},21156911:($0,$1,$2,$3,$4,$5)=>{var deviceType=$0;var channels=$1;var sampleRate=$2;var bufferSize=$3;var pIntermediaryBuffer=$4;var pDevice=$5;if(typeof window.miniaudio==="undefined"){return-1}var device={};var audioContextOptions={};if(deviceType==window.miniaudio.device_type.playback&&sampleRate!=0){audioContextOptions.sampleRate=sampleRate}device.webaudio=new(window.AudioContext||window.webkitAudioContext)(audioContextOptions);device.webaudio.suspend();device.state=window.miniaudio.device_state.stopped;var channelCountIn=0;var channelCountOut=channels;if(deviceType!=window.miniaudio.device_type.playback){channelCountIn=channels}device.scriptNode=device.webaudio.createScriptProcessor(bufferSize,channelCountIn,channelCountOut);device.scriptNode.onaudioprocess=function(e){if(device.intermediaryBufferView==null||device.intermediaryBufferView.length==0){device.intermediaryBufferView=new Float32Array(Module.HEAPF32.buffer,pIntermediaryBuffer,bufferSize*channels)}if(deviceType==miniaudio.device_type.capture||deviceType==miniaudio.device_type.duplex){for(var iChannel=0;iChannel<channels;iChannel+=1){var inputBuffer=e.inputBuffer.getChannelData(iChannel);var intermediaryBuffer=device.intermediaryBufferView;for(var iFrame=0;iFrame<bufferSize;iFrame+=1){intermediaryBuffer[iFrame*channels+iChannel]=inputBuffer[iFrame]}}_ma_device_process_pcm_frames_capture__webaudio(pDevice,bufferSize,pIntermediaryBuffer)}if(deviceType==miniaudio.device_type.playback||deviceType==miniaudio.device_type.duplex){_ma_device_process_pcm_frames_playback__webaudio(pDevice,bufferSize,pIntermediaryBuffer);for(var iChannel=0;iChannel<e.outputBuffer.numberOfChannels;++iChannel){var outputBuffer=e.outputBuffer.getChannelData(iChannel);var intermediaryBuffer=device.intermediaryBufferView;for(var iFrame=0;iFrame<bufferSize;iFrame+=1){outputBuffer[iFrame]=intermediaryBuffer[iFrame*channels+iChannel]}}}else{for(var iChannel=0;iChannel<e.outputBuffer.numberOfChannels;++iChannel){e.outputBuffer.getChannelData(iChannel).fill(0)}}};if(deviceType==miniaudio.device_type.capture||deviceType==miniaudio.device_type.duplex){navigator.mediaDevices.getUserMedia({audio:true,video:false}).then(function(stream){device.streamNode=device.webaudio.createMediaStreamSource(stream);device.streamNode.connect(device.scriptNode);device.scriptNode.connect(device.webaudio.destination)}).catch(function(error){console.log("Failed to get user media: "+error)})}if(deviceType==miniaudio.device_type.playback){device.scriptNode.connect(device.webaudio.destination)}device.pDevice=pDevice;return miniaudio.track_device(device)},21159739:$0=>miniaudio.get_device_by_index($0).webaudio.sampleRate,21159805:$0=>{var device=miniaudio.get_device_by_index($0);if(device.scriptNode!==undefined){device.scriptNode.onaudioprocess=function(e){};device.scriptNode.disconnect();device.scriptNode=undefined}if(device.streamNode!==undefined){device.streamNode.disconnect();device.streamNode=undefined}device.webaudio.close();device.webaudio=undefined;device.pDevice=undefined},21160198:$0=>{miniaudio.untrack_device_by_index($0)},21160241:$0=>{var device=miniaudio.get_device_by_index($0);device.webaudio.resume();device.state=miniaudio.device_state.started},21160366:$0=>{var device=miniaudio.get_device_by_index($0);device.webaudio.suspend();device.state=miniaudio.device_state.stopped},21160492:($0,$1,$2,$3)=>{rivemu_on_begin($0,$1,$2,$3)},21160529:($0,$1,$2,$3,$4,$5,$6)=>{let outcard=HEAPU8.subarray($0,$0+$1);rivemu_on_frame(outcard,$2,$3,$4,$5,$6)},21160623:($0,$1,$2,$3,$4)=>{let rivlog=HEAPU8.subarray($0,$0+$1);let outcard=HEAPU8.subarray($2,$2+$3);let outhash=UTF8ToString($4);rivemu_on_finish(rivlog,outcard,outhash)},21160790:()=>{window.dispatchEvent(new Event("rivemu_on_shutdown"))}};function sapp_js_add_beforeunload_listener(){Module.sokol_beforeunload=event=>{if(__sapp_html5_get_ask_leave_site()!=0){event.preventDefault();event.returnValue=" "}};window.addEventListener("beforeunload",Module.sokol_beforeunload)}function sapp_js_remove_beforeunload_listener(){window.removeEventListener("beforeunload",Module.sokol_beforeunload)}function sapp_js_add_clipboard_listener(){Module.sokol_paste=event=>{const pasted_str=event.clipboardData.getData("text");withStackSave(()=>{const cstr=allocateUTF8OnStack(pasted_str);__sapp_emsc_onpaste(cstr)})};window.addEventListener("paste",Module.sokol_paste)}function sapp_js_remove_clipboard_listener(){window.removeEventListener("paste",Module.sokol_paste)}function sapp_js_add_dragndrop_listeners(canvas_name_cstr){Module.sokol_drop_files=[];const canvas_name=UTF8ToString(canvas_name_cstr);const canvas=document.getElementById(canvas_name);Module.sokol_dragenter=event=>{event.stopPropagation();event.preventDefault()};Module.sokol_dragleave=event=>{event.stopPropagation();event.preventDefault()};Module.sokol_dragover=event=>{event.stopPropagation();event.preventDefault()};Module.sokol_drop=event=>{event.stopPropagation();event.preventDefault();const files=event.dataTransfer.files;Module.sokol_dropped_files=files;__sapp_emsc_begin_drop(files.length);for(let i=0;i<files.length;i++){withStackSave(()=>{const cstr=allocateUTF8OnStack(files[i].name);__sapp_emsc_drop(i,cstr)})}let mods=0;if(event.shiftKey){mods|=1}if(event.ctrlKey){mods|=2}if(event.altKey){mods|=4}if(event.metaKey){mods|=8}__sapp_emsc_end_drop(event.clientX,event.clientY,mods)};canvas.addEventListener("dragenter",Module.sokol_dragenter,false);canvas.addEventListener("dragleave",Module.sokol_dragleave,false);canvas.addEventListener("dragover",Module.sokol_dragover,false);canvas.addEventListener("drop",Module.sokol_drop,false)}function sapp_js_remove_dragndrop_listeners(canvas_name_cstr){const canvas_name=UTF8ToString(canvas_name_cstr);const canvas=document.getElementById(canvas_name);canvas.removeEventListener("dragenter",Module.sokol_dragenter);canvas.removeEventListener("dragleave",Module.sokol_dragleave);canvas.removeEventListener("dragover",Module.sokol_dragover);canvas.removeEventListener("drop",Module.sokol_drop)}function sapp_js_init(c_str_target){const target_str=UTF8ToString(c_str_target);Module.sapp_emsc_target=document.getElementById(target_str);if(!Module.sapp_emsc_target){console.log("sokol_app.h: invalid target:"+target_str)}if(!Module.sapp_emsc_target.requestPointerLock){console.log("sokol_app.h: target doesn't support requestPointerLock:"+target_str)}}function sapp_js_request_pointerlock(){if(Module.sapp_emsc_target){if(Module.sapp_emsc_target.requestPointerLock){Module.sapp_emsc_target.requestPointerLock()}}}function sargs_js_parse_url(){const params=new URLSearchParams(window.location.search).entries();for(let p=params.next();!p.done;p=params.next()){const key=p.value[0];const val=p.value[1];withStackSave(()=>{const key_cstr=allocateUTF8OnStack(key);const val_cstr=allocateUTF8OnStack(val);__sargs_add_kvp(key_cstr,val_cstr)})}}function slog_js_log(level,c_str){const str=UTF8ToString(c_str);switch(level){case 0:console.error(str);break;case 1:console.error(str);break;case 2:console.warn(str);break;default:console.info(str);break}}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var noExitRuntime=Module["noExitRuntime"]||true;var exceptionCaught=[];var uncaughtExceptionCount=0;var ___cxa_begin_catch=ptr=>{var info=new ExceptionInfo(ptr);if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(info);___cxa_increment_exception_refcount(info.excPtr);return info.get_exception_ptr()};var exceptionLast=0;var ___cxa_end_catch=()=>{_setThrew(0,0);var info=exceptionCaught.pop();___cxa_decrement_exception_refcount(info.excPtr);exceptionLast=0};function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var ___resumeException=ptr=>{if(!exceptionLast){exceptionLast=ptr}throw exceptionLast};var findMatchingCatch=args=>{var thrown=exceptionLast;if(!thrown){setTempRet0(0);return 0}var info=new ExceptionInfo(thrown);info.set_adjusted_ptr(thrown);var thrownType=info.get_type();if(!thrownType){setTempRet0(0);return thrown}for(var arg in args){var caughtType=args[arg];if(caughtType===0||caughtType===thrownType){break}var adjusted_ptr_addr=info.ptr+16;if(___cxa_can_catch(caughtType,thrownType,adjusted_ptr_addr)){setTempRet0(caughtType);return thrown}}setTempRet0(thrownType);return thrown};var ___cxa_find_matching_catch_2=()=>findMatchingCatch([]);var ___cxa_find_matching_catch_3=arg0=>findMatchingCatch([arg0]);var ___cxa_rethrow=()=>{var info=exceptionCaught.pop();if(!info){abort("no exception to throw")}var ptr=info.excPtr;if(!info.get_rethrown()){exceptionCaught.push(info);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}exceptionLast=ptr;throw exceptionLast};var ___cxa_rethrow_primary_exception=ptr=>{if(!ptr)return;var info=new ExceptionInfo(ptr);exceptionCaught.push(info);info.set_rethrown(true);___cxa_rethrow()};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var ___cxa_uncaught_exceptions=()=>uncaughtExceptionCount;var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:function(){var paths=Array.prototype.slice.call(arguments);return PATH.normalize(paths.join("/"))},join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else abort("initRandomDevice")};var randomFill=view=>(randomFill=initRandomFill())(view);var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!=="")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push("..")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join("/")}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str};var FS_stdin_getChar_buffer=[];var lengthBytesUTF8=str=>{var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=stream.tty.ops.get_char(stream.tty)}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.put_char){throw new FS.ErrnoError(60)}try{for(var i=0;i<length;i++){stream.tty.ops.put_char(stream.tty,buffer[offset+i])}}catch(e){throw new FS.ErrnoError(29)}if(length){stream.node.timestamp=Date.now()}return i}},default_tty_ops:{get_char(tty){return FS_stdin_getChar()},put_char(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size);return address};var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(!ptr)return 0;return zeroMemory(ptr,size)};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity<CAPACITY_DOUBLING_MAX?2:1.125)>>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp;old_node.parent=new_dir},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key of Object.keys(node.contents)){entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i<size;i++)buffer[offset+i]=contents[position+i]}return size},write(stream,buffer,offset,length,position,canOwn){if(!length)return 0;var node=stream.node;node.timestamp=Date.now();if(buffer.subarray&&(!node.contents||node.contents.subarray)){if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length;return length}else if(node.usedBytes===0&&position===0){node.contents=buffer.slice(offset,offset+length);node.usedBytes=length;return length}else if(position+length<=node.usedBytes){node.contents.set(buffer.subarray(offset,offset+length),position);return length}}MEMFS.expandFileStorage(node,position+length);if(node.contents.subarray&&buffer.subarray){node.contents.set(buffer.subarray(offset,offset+length),position)}else{for(var i=0;i<length;i++){node.contents[position+i]=buffer[offset+i]}}node.usedBytes=Math.max(node.usedBytes,position+length);return length},llseek(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(28)}return position},allocate(stream,offset,length){MEMFS.expandFileStorage(stream.node,offset+length);stream.node.usedBytes=Math.max(stream.node.usedBytes,offset+length)},mmap(stream,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&contents.buffer===HEAP8.buffer){allocated=false;ptr=contents.byteOffset}else{if(position>0||position+length<contents.length){if(contents.subarray){contents=contents.subarray(position,position+length)}else{contents=Array.prototype.slice.call(contents,position,position+length)}}allocated=true;ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}HEAP8.set(contents,ptr)}return{ptr:ptr,allocated:allocated}},msync(stream,buffer,offset,length,mmapFlags){MEMFS.stream_ops.write(stream,buffer,0,length,offset,false);return 0}}};var asyncLoad=(url,onload,onerror,noRunDep)=>{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url,arrayBuffer=>{assert(arrayBuffer,`Loading data file "${url}" failed (no arrayBuffer).`);onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},event=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)};var FS_createDataFile=(parent,name,fileData,canRead,canWrite,canOwn)=>{FS.createDataFile(parent,name,fileData,canRead,canWrite,canOwn)};var preloadPlugins=Module["preloadPlugins"]||[];var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}onload?.();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{onerror?.();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,byteArray=>processData(byteArray),onerror)}else{processData(url)}};var FS_modeStringToFlags=str=>{var flagModes={"r":0,"r+":2,"w":512|64|1,"w+":512|64|2,"a":1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath(path,opts={}){path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i<parts.length;i++){var islast=i===parts.length-1;if(islast&&opts.parent){break}current=FS.lookupNode(current,parts[i]);current_path=PATH.join2(current_path,parts[i]);if(FS.isMountpoint(current)){if(!islast||islast&&opts.follow_mount){current=current.mounted.root}}if(!islast||opts.follow){var count=0;while(FS.isLink(current.mode)){var link=FS.readlink(current_path);current_path=PATH_FS.resolve(PATH.dirname(current_path),link);var lookup=FS.lookupPath(current_path,{recurse_count:opts.recurse_count+1});current=lookup.node;if(count++>40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i<name.length;i++){hash=(hash<<5)-hash+name.charCodeAt(i)|0}return(parentid+hash>>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){if(!FS.FSStream){FS.FSStream=function(){this.shared={}};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get(){return this.node},set(val){this.node=val}},isRead:{get(){return(this.flags&2097155)!==1}},isWrite:{get(){return(this.flags&2097155)!==0}},isAppend:{get(){return this.flags&1024}},flags:{get(){return this.shared.flags},set(val){this.shared.flags=val}},position:{get(){return this.shared.position},set(val){this.shared.position=val}}})}stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;i<dirs.length;++i){if(!dirs[i])continue;d+="/"+dirs[i];try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev(path,mode,dev){if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink(oldpath,newpath){if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(54)}return node.node_ops.readdir(node)},unlink(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return PATH_FS.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))},stat(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(44)}if(!node.node_ops.getattr){throw new FS.ErrnoError(63)}return node.node_ops.getattr(node)},lstat(path){return FS.stat(path,true)},chmod(path,mode,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})},lchmod(path,mode){FS.chmod(path,mode,true)},fchmod(fd,mode){var stream=FS.getStreamChecked(fd);FS.chmod(stream.node,mode)},chown(path,uid,gid,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{timestamp:Date.now()})},lchown(path,uid,gid){FS.chown(path,uid,gid,true)},fchown(fd,uid,gid){var stream=FS.getStreamChecked(fd);FS.chown(stream.node,uid,gid)},truncate(path,len){if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})},ftruncate(fd,len){var stream=FS.getStreamChecked(fd);if((stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.truncate(stream.node,len)},utime(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})},open(path,flags,mode){if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;mode=typeof mode=="undefined"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path=="object"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module["logReadFiles"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed(stream){return stream.fd===null},llseek(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate(stream,offset,length){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:stream=>0,ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams(){if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},ensureErrnoError(){if(FS.ErrnoError)return;FS.ErrnoError=function ErrnoError(errno,node){this.name="ErrnoError";this.node=node;this.setErrno=function(errno){this.errno=errno};this.setErrno(errno);this.message="FS error"};FS.ErrnoError.prototype=new Error;FS.ErrnoError.prototype.constructor=FS.ErrnoError;[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack="<generic error, no stack>"})},staticInit(){FS.ensureErrnoError();FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={"MEMFS":MEMFS}},init(input,output,error){FS.init.initialized=true;FS.ensureErrnoError();Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit(){FS.init.initialized=false;for(var i=0;i<FS.streams.length;i++){var stream=FS.streams[i];if(!stream){continue}FS.close(stream)}},findObject(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath(parent,path,canRead,canWrite){parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current},createFile(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile(parent,name,data,canRead,canWrite,canOwn){var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;i<len;++i)arr[i]=data.charCodeAt(i);data=arr}FS.chmod(node,mode|146);var stream=FS.open(node,577);FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}},createDevice(parent,name,input,output){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open(stream){stream.seekable=false},close(stream){if(output?.buffer?.length){output(10)}},read(stream,buffer,offset,length,pos){var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=input()}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write(stream,buffer,offset,length,pos){for(var i=0;i<length;i++){try{output(buffer[offset+i])}catch(e){throw new FS.ErrnoError(29)}}if(length){stream.node.timestamp=Date.now()}return i}});return FS.mkdev(path,mode,dev)},forceLoadFile(obj){if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;if(typeof XMLHttpRequest!="undefined"){throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")}else if(read_){try{obj.contents=intArrayFromString(read_(obj.url),true);obj.usedBytes=obj.contents.length}catch(e){throw new FS.ErrnoError(29)}}else{throw new Error("Cannot load without read() or XMLHttpRequest.")}},createLazyFile(parent,name,url,canRead,canWrite){function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i<size;i++){buffer[offset+i]=contents[position+i]}}else{for(var i=0;i<size;i++){buffer[offset+i]=contents.get(position+i)}}return size}stream_ops.read=(stream,buffer,offset,length,position)=>{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat(func,path,buf){try{var stat=func(path)}catch(e){if(e&&e.node&&PATH.normalize(path)!==PATH.normalize(FS.getPath(e.node))){return-54}throw e}HEAP32[buf>>2]=stat.dev;HEAP32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAP32[buf+12>>2]=stat.uid;HEAP32[buf+16>>2]=stat.gid;HEAP32[buf+20>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAPU32[buf+48>>2]=atime%1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];HEAPU32[buf+64>>2]=mtime%1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];HEAPU32[buf+80>>2]=ctime%1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},varargs:undefined,get(){var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret},getp(){return SYSCALLS.get()},getStr(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream}};function ___syscall__newselect(nfds,readfds,writefds,exceptfds,timeout){try{var total=0;var srcReadLow=readfds?HEAP32[readfds>>2]:0,srcReadHigh=readfds?HEAP32[readfds+4>>2]:0;var srcWriteLow=writefds?HEAP32[writefds>>2]:0,srcWriteHigh=writefds?HEAP32[writefds+4>>2]:0;var srcExceptLow=exceptfds?HEAP32[exceptfds>>2]:0,srcExceptHigh=exceptfds?HEAP32[exceptfds+4>>2]:0;var dstReadLow=0,dstReadHigh=0;var dstWriteLow=0,dstWriteHigh=0;var dstExceptLow=0,dstExceptHigh=0;var allLow=(readfds?HEAP32[readfds>>2]:0)|(writefds?HEAP32[writefds>>2]:0)|(exceptfds?HEAP32[exceptfds>>2]:0);var allHigh=(readfds?HEAP32[readfds+4>>2]:0)|(writefds?HEAP32[writefds+4>>2]:0)|(exceptfds?HEAP32[exceptfds+4>>2]:0);var check=function(fd,low,high,val){return fd<32?low&val:high&val};for(var fd=0;fd<nfds;fd++){var mask=1<<fd%32;if(!check(fd,allLow,allHigh,mask)){continue}var stream=SYSCALLS.getStreamFromFD(fd);var flags=SYSCALLS.DEFAULT_POLLMASK;if(stream.stream_ops.poll){var timeoutInMillis=-1;if(timeout){var tv_sec=readfds?HEAP32[timeout>>2]:0,tv_usec=readfds?HEAP32[timeout+4>>2]:0;timeoutInMillis=(tv_sec+tv_usec/1e6)*1e3}flags=stream.stream_ops.poll(stream,timeoutInMillis)}if(flags&1&&check(fd,srcReadLow,srcReadHigh,mask)){fd<32?dstReadLow=dstReadLow|mask:dstReadHigh=dstReadHigh|mask;total++}if(flags&4&&check(fd,srcWriteLow,srcWriteHigh,mask)){fd<32?dstWriteLow=dstWriteLow|mask:dstWriteHigh=dstWriteHigh|mask;total++}if(flags&2&&check(fd,srcExceptLow,srcExceptHigh,mask)){fd<32?dstExceptLow=dstExceptLow|mask:dstExceptHigh=dstExceptHigh|mask;total++}}if(readfds){HEAP32[readfds>>2]=dstReadLow;HEAP32[readfds+4>>2]=dstReadHigh}if(writefds){HEAP32[writefds>>2]=dstWriteLow;HEAP32[writefds+4>>2]=dstWriteHigh}if(exceptfds){HEAP32[exceptfds>>2]=dstExceptLow;HEAP32[exceptfds+4>>2]=dstExceptHigh}return total}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var setErrNo=value=>{HEAP32[___errno_location()>>2]=value;return value};function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.createStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 5:{var arg=SYSCALLS.getp();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 6:case 7:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=SYSCALLS.getp();HEAP32[argp>>2]=termios.c_iflag||0;HEAP32[argp+4>>2]=termios.c_oflag||0;HEAP32[argp+8>>2]=termios.c_cflag||0;HEAP32[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){HEAP8[argp+i+17>>0]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=SYSCALLS.getp();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17>>0])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag:c_iflag,c_oflag:c_oflag,c_cflag:c_cflag,c_lflag:c_lflag,c_cc:c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=SYSCALLS.getp();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.getp();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=SYSCALLS.getp();HEAP16[argp>>1]=winsize[0];HEAP16[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?SYSCALLS.get():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);function ___syscall_readlinkat(dirfd,path,buf,bufsize){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __emscripten_fs_load_embedded_files=ptr=>{do{var name_addr=HEAPU32[ptr>>2];ptr+=4;var len=HEAPU32[ptr>>2];ptr+=4;var content=HEAPU32[ptr>>2];ptr+=4;var name=UTF8ToString(name_addr);FS.createPath("/",PATH.dirname(name),true,true);FS.createDataFile(name,null,HEAP8.subarray(content,content+len),true,true,true)}while(HEAPU32[ptr>>2])};var convertI32PairToI53Checked=(lo,hi)=>hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN;function __mmap_js(len,prot,flags,fd,offset_low,offset_high,allocated,addr){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset_low,offset_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}FS.munmap(stream)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var _abort=()=>{abort("")};var readEmAsmArgsArray=[];var readEmAsmArgs=(sigPtr,buf)=>{readEmAsmArgsArray.length=0;var ch;while(ch=HEAPU8[sigPtr++]){var wide=ch!=105;wide&=ch!=112;buf+=wide&&buf%8?4:0;readEmAsmArgsArray.push(ch==112?HEAPU32[buf>>2]:ch==105?HEAP32[buf>>2]:HEAPF64[buf>>3]);buf+=wide?8:4}return readEmAsmArgsArray};var runEmAsmFunction=(code,sigPtr,argbuf)=>{var args=readEmAsmArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)};var _emscripten_asm_const_int=(code,sigPtr,argbuf)=>runEmAsmFunction(code,sigPtr,argbuf);var _emscripten_date_now=()=>Date.now();var _emscripten_get_device_pixel_ratio=()=>devicePixelRatio;var withStackSave=f=>{var stack=stackSave();var ret=f();stackRestore(stack);return ret};var JSEvents={inEventHandler:0,removeAllEventListeners(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i)}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[]},registerRemoveEventListeners(){if(!JSEvents.removeEventListenersRegistered){__ATEXIT__.push(JSEvents.removeAllEventListeners);JSEvents.removeEventListenersRegistered=true}},deferredCalls:[],deferCall(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort((x,y)=>x.precedence<y.precedence)},removeDeferredCalls(targetFunction){for(var i=0;i<JSEvents.deferredCalls.length;++i){if(JSEvents.deferredCalls[i].targetFunction==targetFunction){JSEvents.deferredCalls.splice(i,1);--i}}},canPerformEventHandlerRequests(){if(navigator.userActivation){return navigator.userActivation.isActive}return JSEvents.inEventHandler&&JSEvents.currentEventHandler.allowsDeferredCalls},runDeferredCalls(){if(!JSEvents.canPerformEventHandlerRequests()){return}for(var i=0;i<JSEvents.deferredCalls.length;++i){var call=JSEvents.deferredCalls[i];JSEvents.deferredCalls.splice(i,1);--i;call.targetFunction.apply(null,call.argsList)}},eventHandlers:[],removeAllHandlersOnTarget:(target,eventTypeString)=>{for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==target&&(!eventTypeString||eventTypeString==JSEvents.eventHandlers[i].eventTypeString)){JSEvents._removeHandler(i--)}}},_removeHandler(i){var h=JSEvents.eventHandlers[i];h.target.removeEventListener(h.eventTypeString,h.eventListenerFunc,h.useCapture);JSEvents.eventHandlers.splice(i,1)},registerOrRemoveHandler(eventHandler){if(!eventHandler.target){return-4}var jsEventHandler=function jsEventHandler(event){++JSEvents.inEventHandler;JSEvents.currentEventHandler=eventHandler;JSEvents.runDeferredCalls();eventHandler.handlerFunc(event);JSEvents.runDeferredCalls();--JSEvents.inEventHandler};if(eventHandler.callbackfunc){eventHandler.eventListenerFunc=jsEventHandler;eventHandler.target.addEventListener(eventHandler.eventTypeString,jsEventHandler,eventHandler.useCapture);JSEvents.eventHandlers.push(eventHandler);JSEvents.registerRemoveEventListeners()}else{for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==eventHandler.target&&JSEvents.eventHandlers[i].eventTypeString==eventHandler.eventTypeString){JSEvents._removeHandler(i--)}}}return 0},getNodeNameForTarget(target){if(!target)return"";if(target==window)return"#window";if(target==screen)return"#screen";return target?.nodeName||""},fullscreenEnabled(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};var maybeCStringToJsString=cString=>cString>2?UTF8ToString(cString):cString;var specialHTMLTargets=[0,document,window];var findEventTarget=target=>{target=maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||document.querySelector(target);return domElement};var getBoundingClientRect=e=>specialHTMLTargets.indexOf(e)<0?e.getBoundingClientRect():{"left":0,"top":0};var _emscripten_get_element_css_size=(target,width,height)=>{target=findEventTarget(target);if(!target)return-4;var rect=getBoundingClientRect(target);HEAPF64[width>>3]=rect.width;HEAPF64[height>>3]=rect.height;return 0};var getHeapMax=()=>HEAPU8.length;var _emscripten_get_heap_max=()=>getHeapMax();var _emscripten_get_now;_emscripten_get_now=()=>performance.now();var _emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var _emscripten_request_animation_frame_loop=(cb,userData)=>{function tick(timeStamp){if(getWasmTableEntry(cb)(timeStamp,userData)){requestAnimationFrame(tick)}}return requestAnimationFrame(tick)};var abortOnCannotGrowMemory=requestedSize=>{abort("OOM")};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;abortOnCannotGrowMemory(requestedSize)};var registerFocusEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.focusEvent)JSEvents.focusEvent=_malloc(256);var focusEventHandlerFunc=(e=event)=>{var nodeName=JSEvents.getNodeNameForTarget(e.target);var id=e.target.id?e.target.id:"";var focusEvent=JSEvents.focusEvent;stringToUTF8(nodeName,focusEvent+0,128);stringToUTF8(id,focusEvent+128,128);if(getWasmTableEntry(callbackfunc)(eventTypeId,focusEvent,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:focusEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_blur_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerFocusEventCallback(target,userData,useCapture,callbackfunc,12,"blur",targetThread);var findCanvasEventTarget=target=>findEventTarget(target);var _emscripten_set_canvas_element_size=(target,width,height)=>{var canvas=findCanvasEventTarget(target);if(!canvas)return-4;canvas.width=width;canvas.height=height;return 0};var _emscripten_set_focus_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerFocusEventCallback(target,userData,useCapture,callbackfunc,13,"focus",targetThread);var registerKeyEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.keyEvent)JSEvents.keyEvent=_malloc(176);var keyEventHandlerFunc=e=>{var keyEventData=JSEvents.keyEvent;HEAPF64[keyEventData>>3]=e.timeStamp;var idx=keyEventData>>2;HEAP32[idx+2]=e.location;HEAP32[idx+3]=e.ctrlKey;HEAP32[idx+4]=e.shiftKey;HEAP32[idx+5]=e.altKey;HEAP32[idx+6]=e.metaKey;HEAP32[idx+7]=e.repeat;HEAP32[idx+8]=e.charCode;HEAP32[idx+9]=e.keyCode;HEAP32[idx+10]=e.which;stringToUTF8(e.key||"",keyEventData+44,32);stringToUTF8(e.code||"",keyEventData+76,32);stringToUTF8(e.char||"",keyEventData+108,32);stringToUTF8(e.locale||"",keyEventData+140,32);if(getWasmTableEntry(callbackfunc)(eventTypeId,keyEventData,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:keyEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_keydown_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerKeyEventCallback(target,userData,useCapture,callbackfunc,2,"keydown",targetThread);var _emscripten_set_keypress_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerKeyEventCallback(target,userData,useCapture,callbackfunc,1,"keypress",targetThread);var _emscripten_set_keyup_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerKeyEventCallback(target,userData,useCapture,callbackfunc,3,"keyup",targetThread);var fillMouseEventData=(eventStruct,e,target)=>{HEAPF64[eventStruct>>3]=e.timeStamp;var idx=eventStruct>>2;HEAP32[idx+2]=e.screenX;HEAP32[idx+3]=e.screenY;HEAP32[idx+4]=e.clientX;HEAP32[idx+5]=e.clientY;HEAP32[idx+6]=e.ctrlKey;HEAP32[idx+7]=e.shiftKey;HEAP32[idx+8]=e.altKey;HEAP32[idx+9]=e.metaKey;HEAP16[idx*2+20]=e.button;HEAP16[idx*2+21]=e.buttons;HEAP32[idx+11]=e["movementX"];HEAP32[idx+12]=e["movementY"];var rect=getBoundingClientRect(target);HEAP32[idx+13]=e.clientX-rect.left;HEAP32[idx+14]=e.clientY-rect.top};var registerMouseEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.mouseEvent)JSEvents.mouseEvent=_malloc(72);target=findEventTarget(target);var mouseEventHandlerFunc=(e=event)=>{fillMouseEventData(JSEvents.mouseEvent,e,target);if(getWasmTableEntry(callbackfunc)(eventTypeId,JSEvents.mouseEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString!="mousemove"&&eventTypeString!="mouseenter"&&eventTypeString!="mouseleave",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:mouseEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_mousedown_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerMouseEventCallback(target,userData,useCapture,callbackfunc,5,"mousedown",targetThread);var _emscripten_set_mouseenter_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerMouseEventCallback(target,userData,useCapture,callbackfunc,33,"mouseenter",targetThread);var _emscripten_set_mouseleave_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerMouseEventCallback(target,userData,useCapture,callbackfunc,34,"mouseleave",targetThread);var _emscripten_set_mousemove_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerMouseEventCallback(target,userData,useCapture,callbackfunc,8,"mousemove",targetThread);var _emscripten_set_mouseup_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerMouseEventCallback(target,userData,useCapture,callbackfunc,6,"mouseup",targetThread);var fillPointerlockChangeEventData=eventStruct=>{var pointerLockElement=document.pointerLockElement||document.mozPointerLockElement||document.webkitPointerLockElement||document.msPointerLockElement;var isPointerlocked=!!pointerLockElement;HEAP32[eventStruct>>2]=isPointerlocked;var nodeName=JSEvents.getNodeNameForTarget(pointerLockElement);var id=pointerLockElement?.id||"";stringToUTF8(nodeName,eventStruct+4,128);stringToUTF8(id,eventStruct+132,128)};var registerPointerlockChangeEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.pointerlockChangeEvent)JSEvents.pointerlockChangeEvent=_malloc(260);var pointerlockChangeEventHandlerFunc=(e=event)=>{var pointerlockChangeEvent=JSEvents.pointerlockChangeEvent;fillPointerlockChangeEventData(pointerlockChangeEvent);if(getWasmTableEntry(callbackfunc)(eventTypeId,pointerlockChangeEvent,userData))e.preventDefault()};var eventHandler={target:target,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:pointerlockChangeEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_pointerlockchange_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>{if(!document||!document.body||!document.body.requestPointerLock&&!document.body.mozRequestPointerLock&&!document.body.webkitRequestPointerLock&&!document.body.msRequestPointerLock){return-1}target=findEventTarget(target);if(!target)return-4;registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"mozpointerlockchange",targetThread);registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"webkitpointerlockchange",targetThread);registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"mspointerlockchange",targetThread);return registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"pointerlockchange",targetThread)};var registerPointerlockErrorEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{var pointerlockErrorEventHandlerFunc=(e=event)=>{if(getWasmTableEntry(callbackfunc)(eventTypeId,0,userData))e.preventDefault()};var eventHandler={target:target,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:pointerlockErrorEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_pointerlockerror_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>{if(!document||!document.body.requestPointerLock&&!document.body.mozRequestPointerLock&&!document.body.webkitRequestPointerLock&&!document.body.msRequestPointerLock){return-1}target=findEventTarget(target);if(!target)return-4;registerPointerlockErrorEventCallback(target,userData,useCapture,callbackfunc,38,"mozpointerlockerror",targetThread);registerPointerlockErrorEventCallback(target,userData,useCapture,callbackfunc,38,"webkitpointerlockerror",targetThread);registerPointerlockErrorEventCallback(target,userData,useCapture,callbackfunc,38,"mspointerlockerror",targetThread);return registerPointerlockErrorEventCallback(target,userData,useCapture,callbackfunc,38,"pointerlockerror",targetThread)};var registerUiEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.uiEvent)JSEvents.uiEvent=_malloc(36);target=findEventTarget(target);var uiEventHandlerFunc=(e=event)=>{if(e.target!=target){return}var b=document.body;if(!b){return}var uiEvent=JSEvents.uiEvent;HEAP32[uiEvent>>2]=e.detail;HEAP32[uiEvent+4>>2]=b.clientWidth;HEAP32[uiEvent+8>>2]=b.clientHeight;HEAP32[uiEvent+12>>2]=innerWidth;HEAP32[uiEvent+16>>2]=innerHeight;HEAP32[uiEvent+20>>2]=outerWidth;HEAP32[uiEvent+24>>2]=outerHeight;HEAP32[uiEvent+28>>2]=pageXOffset;HEAP32[uiEvent+32>>2]=pageYOffset;if(getWasmTableEntry(callbackfunc)(eventTypeId,uiEvent,userData))e.preventDefault()};var eventHandler={target:target,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:uiEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_resize_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerUiEventCallback(target,userData,useCapture,callbackfunc,10,"resize",targetThread);var registerTouchEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.touchEvent)JSEvents.touchEvent=_malloc(1696);target=findEventTarget(target);var touchEventHandlerFunc=e=>{var t,touches={},et=e.touches;for(var i=0;i<et.length;++i){t=et[i];t.isChanged=t.onTarget=0;touches[t.identifier]=t}for(var i=0;i<e.changedTouches.length;++i){t=e.changedTouches[i];t.isChanged=1;touches[t.identifier]=t}for(var i=0;i<e.targetTouches.length;++i){touches[e.targetTouches[i].identifier].onTarget=1}var touchEvent=JSEvents.touchEvent;HEAPF64[touchEvent>>3]=e.timeStamp;var idx=touchEvent>>2;HEAP32[idx+3]=e.ctrlKey;HEAP32[idx+4]=e.shiftKey;HEAP32[idx+5]=e.altKey;HEAP32[idx+6]=e.metaKey;idx+=7;var targetRect=getBoundingClientRect(target);var numTouches=0;for(var i in touches){t=touches[i];HEAP32[idx+0]=t.identifier;HEAP32[idx+1]=t.screenX;HEAP32[idx+2]=t.screenY;HEAP32[idx+3]=t.clientX;HEAP32[idx+4]=t.clientY;HEAP32[idx+5]=t.pageX;HEAP32[idx+6]=t.pageY;HEAP32[idx+7]=t.isChanged;HEAP32[idx+8]=t.onTarget;HEAP32[idx+9]=t.clientX-targetRect.left;HEAP32[idx+10]=t.clientY-targetRect.top;idx+=13;if(++numTouches>31){break}}HEAP32[touchEvent+8>>2]=numTouches;if(getWasmTableEntry(callbackfunc)(eventTypeId,touchEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString=="touchstart"||eventTypeString=="touchend",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:touchEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_touchcancel_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerTouchEventCallback(target,userData,useCapture,callbackfunc,25,"touchcancel",targetThread);var _emscripten_set_touchend_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerTouchEventCallback(target,userData,useCapture,callbackfunc,23,"touchend",targetThread);var _emscripten_set_touchmove_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerTouchEventCallback(target,userData,useCapture,callbackfunc,24,"touchmove",targetThread);var _emscripten_set_touchstart_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerTouchEventCallback(target,userData,useCapture,callbackfunc,22,"touchstart",targetThread);var webgl_enable_ANGLE_instanced_arrays=ctx=>{var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=(index,divisor)=>ext["vertexAttribDivisorANGLE"](index,divisor);ctx["drawArraysInstanced"]=(mode,first,count,primcount)=>ext["drawArraysInstancedANGLE"](mode,first,count,primcount);ctx["drawElementsInstanced"]=(mode,count,type,indices,primcount)=>ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);return 1}};var webgl_enable_OES_vertex_array_object=ctx=>{var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=()=>ext["createVertexArrayOES"]();ctx["deleteVertexArray"]=vao=>ext["deleteVertexArrayOES"](vao);ctx["bindVertexArray"]=vao=>ext["bindVertexArrayOES"](vao);ctx["isVertexArray"]=vao=>ext["isVertexArrayOES"](vao);return 1}};var webgl_enable_WEBGL_draw_buffers=ctx=>{var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=(n,bufs)=>ext["drawBuffersWEBGL"](n,bufs);return 1}};var webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance=ctx=>!!(ctx.dibvbi=ctx.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"));var webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance=ctx=>!!(ctx.mdibvbi=ctx.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance"));var webgl_enable_WEBGL_multi_draw=ctx=>!!(ctx.multiDrawWebgl=ctx.getExtension("WEBGL_multi_draw"));var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:table=>{var ret=GL.counter++;for(var i=table.length;i<ret;i++){table[i]=null}return ret},MAX_TEMP_BUFFER_SIZE:2097152,numTempVertexBuffersPerSize:64,log2ceilLookup:i=>32-Math.clz32(i===0?0:i-1),generateTempBuffers:(quads,context)=>{var largestIndex=GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);context.tempVertexBufferCounters1=[];context.tempVertexBufferCounters2=[];context.tempVertexBufferCounters1.length=context.tempVertexBufferCounters2.length=largestIndex+1;context.tempVertexBuffers1=[];context.tempVertexBuffers2=[];context.tempVertexBuffers1.length=context.tempVertexBuffers2.length=largestIndex+1;context.tempIndexBuffers=[];context.tempIndexBuffers.length=largestIndex+1;for(var i=0;i<=largestIndex;++i){context.tempIndexBuffers[i]=null;context.tempVertexBufferCounters1[i]=context.tempVertexBufferCounters2[i]=0;var ringbufferLength=GL.numTempVertexBuffersPerSize;context.tempVertexBuffers1[i]=[];context.tempVertexBuffers2[i]=[];var ringbuffer1=context.tempVertexBuffers1[i];var ringbuffer2=context.tempVertexBuffers2[i];ringbuffer1.length=ringbuffer2.length=ringbufferLength;for(var j=0;j<ringbufferLength;++j){ringbuffer1[j]=ringbuffer2[j]=null}}if(quads){context.tempQuadIndexBuffer=GLctx.createBuffer();context.GLctx.bindBuffer(34963,context.tempQuadIndexBuffer);var numIndexes=GL.MAX_TEMP_BUFFER_SIZE>>1;var quadIndexes=new Uint16Array(numIndexes);var i=0,v=0;while(1){quadIndexes[i++]=v;if(i>=numIndexes)break;quadIndexes[i++]=v+1;if(i>=numIndexes)break;quadIndexes[i++]=v+2;if(i>=numIndexes)break;quadIndexes[i++]=v;if(i>=numIndexes)break;quadIndexes[i++]=v+2;if(i>=numIndexes)break;quadIndexes[i++]=v+3;if(i>=numIndexes)break;v+=4}context.GLctx.bufferData(34963,quadIndexes,35044);context.GLctx.bindBuffer(34963,null)}},getTempVertexBuffer:function getTempVertexBuffer(sizeBytes){var idx=GL.log2ceilLookup(sizeBytes);var ringbuffer=GL.currentContext.tempVertexBuffers1[idx];var nextFreeBufferIndex=GL.currentContext.tempVertexBufferCounters1[idx];GL.currentContext.tempVertexBufferCounters1[idx]=GL.currentContext.tempVertexBufferCounters1[idx]+1&GL.numTempVertexBuffersPerSize-1;var vbo=ringbuffer[nextFreeBufferIndex];if(vbo){return vbo}var prevVBO=GLctx.getParameter(34964);ringbuffer[nextFreeBufferIndex]=GLctx.createBuffer();GLctx.bindBuffer(34962,ringbuffer[nextFreeBufferIndex]);GLctx.bufferData(34962,1<<idx,35048);GLctx.bindBuffer(34962,prevVBO);return ringbuffer[nextFreeBufferIndex]},getTempIndexBuffer:function getTempIndexBuffer(sizeBytes){var idx=GL.log2ceilLookup(sizeBytes);var ibo=GL.currentContext.tempIndexBuffers[idx];if(ibo){return ibo}var prevIBO=GLctx.getParameter(34965);GL.currentContext.tempIndexBuffers[idx]=GLctx.createBuffer();GLctx.bindBuffer(34963,GL.currentContext.tempIndexBuffers[idx]);GLctx.bufferData(34963,1<<idx,35048);GLctx.bindBuffer(34963,prevIBO);return GL.currentContext.tempIndexBuffers[idx]},newRenderingFrameStarted:function newRenderingFrameStarted(){if(!GL.currentContext){return}var vb=GL.currentContext.tempVertexBuffers1;GL.currentContext.tempVertexBuffers1=GL.currentContext.tempVertexBuffers2;GL.currentContext.tempVertexBuffers2=vb;vb=GL.currentContext.tempVertexBufferCounters1;GL.currentContext.tempVertexBufferCounters1=GL.currentContext.tempVertexBufferCounters2;GL.currentContext.tempVertexBufferCounters2=vb;var largestIndex=GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);for(var i=0;i<=largestIndex;++i){GL.currentContext.tempVertexBufferCounters1[i]=0}},getSource:(shader,count,string,length)=>{var source="";for(var i=0;i<count;++i){var len=length?HEAP32[length+i*4>>2]:-1;source+=UTF8ToString(HEAP32[string+i*4>>2],len<0?undefined:len)}return source},calcBufLength:function calcBufLength(size,type,stride,count){if(stride>0){return count*stride}var typeSize=GL.byteSizeByType[type-GL.byteSizeByTypeRoot];return size*typeSize*count},usedTempBuffers:[],preDrawHandleClientVertexAttribBindings:function preDrawHandleClientVertexAttribBindings(count){GL.resetBufferBinding=false;for(var i=0;i<GL.currentContext.maxVertexAttribs;++i){var cb=GL.currentContext.clientBuffers[i];if(!cb.clientside||!cb.enabled)continue;GL.resetBufferBinding=true;var size=GL.calcBufLength(cb.size,cb.type,cb.stride,count);var buf=GL.getTempVertexBuffer(size);GLctx.bindBuffer(34962,buf);GLctx.bufferSubData(34962,0,HEAPU8.subarray(cb.ptr,cb.ptr+size));cb.vertexAttribPointerAdaptor.call(GLctx,i,cb.size,cb.type,cb.normalized,cb.stride,0)}},postDrawHandleClientVertexAttribBindings:function postDrawHandleClientVertexAttribBindings(){if(GL.resetBufferBinding){GLctx.bindBuffer(34962,GL.buffers[GLctx.currentArrayBufferBinding])}},createContext:(canvas,webGLContextAttributes)=>{if(!canvas.getContextSafariWebGL2Fixed){canvas.getContextSafariWebGL2Fixed=canvas.getContext;function fixedGetContext(ver,attrs){var gl=canvas.getContextSafariWebGL2Fixed(ver,attrs);return ver=="webgl"==gl instanceof WebGLRenderingContext?gl:null}canvas.getContext=fixedGetContext}var ctx=webGLContextAttributes.majorVersion>1?canvas.getContext("webgl2",webGLContextAttributes):canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:(ctx,webGLContextAttributes)=>{var handle=GL.getNewId(GL.contexts);var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault=="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context)}context.maxVertexAttribs=context.GLctx.getParameter(34921);context.clientBuffers=[];for(var i=0;i<context.maxVertexAttribs;i++){context.clientBuffers[i]={enabled:false,clientside:false,size:0,type:0,normalized:0,stride:0,ptr:0,vertexAttribPointerAdaptor:null}}GL.generateTempBuffers(false,context);return handle},makeContextCurrent:contextHandle=>{GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext?.GLctx;return!(contextHandle&&!GLctx)},getContext:contextHandle=>GL.contexts[contextHandle],deleteContext:contextHandle=>{if(GL.currentContext===GL.contexts[contextHandle]){GL.currentContext=null}if(typeof JSEvents=="object"){JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas)}if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas){GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined}GL.contexts[contextHandle]=null},initExtensions:context=>{context||=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;webgl_enable_ANGLE_instanced_arrays(GLctx);webgl_enable_OES_vertex_array_object(GLctx);webgl_enable_WEBGL_draw_buffers(GLctx);webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);if(context.version>=2){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query_webgl2")}if(context.version<2||!GLctx.disjointTimerQueryExt){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query")}webgl_enable_WEBGL_multi_draw(GLctx);var exts=GLctx.getSupportedExtensions()||[];exts.forEach(ext=>{if(!ext.includes("lose_context")&&!ext.includes("debug")){GLctx.getExtension(ext)}})},getExtensions(){var exts=GLctx.getSupportedExtensions()||[];exts=exts.concat(exts.map(e=>"GL_"+e));return exts}};var registerWebGlEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{var webGlEventHandlerFunc=(e=event)=>{if(getWasmTableEntry(callbackfunc)(eventTypeId,0,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:webGlEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_webglcontextlost_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>{registerWebGlEventCallback(target,userData,useCapture,callbackfunc,31,"webglcontextlost",targetThread);return 0};var _emscripten_set_webglcontextrestored_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>{registerWebGlEventCallback(target,userData,useCapture,callbackfunc,32,"webglcontextrestored",targetThread);return 0};var registerWheelEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.wheelEvent)JSEvents.wheelEvent=_malloc(104);var wheelHandlerFunc=(e=event)=>{var wheelEvent=JSEvents.wheelEvent;fillMouseEventData(wheelEvent,e,target);HEAPF64[wheelEvent+72>>3]=e["deltaX"];HEAPF64[wheelEvent+80>>3]=e["deltaY"];HEAPF64[wheelEvent+88>>3]=e["deltaZ"];HEAP32[wheelEvent+96>>2]=e["deltaMode"];if(getWasmTableEntry(callbackfunc)(eventTypeId,wheelEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:wheelHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_wheel_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>{target=findEventTarget(target);if(!target)return-4;if(typeof target.onwheel!="undefined"){return registerWheelEventCallback(target,userData,useCapture,callbackfunc,9,"wheel",targetThread)}else{return-1}};var emscripten_webgl_power_preferences=["default","low-power","high-performance"];var _emscripten_webgl_do_create_context=(target,attributes)=>{var a=attributes>>2;var powerPreference=HEAP32[a+(24>>2)];var contextAttributes={"alpha":!!HEAP32[a+(0>>2)],"depth":!!HEAP32[a+(4>>2)],"stencil":!!HEAP32[a+(8>>2)],"antialias":!!HEAP32[a+(12>>2)],"premultipliedAlpha":!!HEAP32[a+(16>>2)],"preserveDrawingBuffer":!!HEAP32[a+(20>>2)],"powerPreference":emscripten_webgl_power_preferences[powerPreference],"failIfMajorPerformanceCaveat":!!HEAP32[a+(28>>2)],majorVersion:HEAP32[a+(32>>2)],minorVersion:HEAP32[a+(36>>2)],enableExtensionsByDefault:HEAP32[a+(40>>2)],explicitSwapControl:HEAP32[a+(44>>2)],proxyContextToMainThread:HEAP32[a+(48>>2)],renderViaOffscreenBackBuffer:HEAP32[a+(52>>2)]};var canvas=findCanvasEventTarget(target);if(!canvas){return 0}if(contextAttributes.explicitSwapControl){return 0}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle};var _emscripten_webgl_create_context=_emscripten_webgl_do_create_context;var _emscripten_webgl_enable_extension=(contextHandle,extension)=>{var context=GL.getContext(contextHandle);var extString=UTF8ToString(extension);if(extString.startsWith("GL_"))extString=extString.substr(3);if(extString=="ANGLE_instanced_arrays")webgl_enable_ANGLE_instanced_arrays(GLctx);if(extString=="OES_vertex_array_object")webgl_enable_OES_vertex_array_object(GLctx);if(extString=="WEBGL_draw_buffers")webgl_enable_WEBGL_draw_buffers(GLctx);if(extString=="WEBGL_draw_instanced_base_vertex_base_instance")webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);if(extString=="WEBGL_multi_draw_instanced_base_vertex_base_instance")webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);if(extString=="WEBGL_multi_draw")webgl_enable_WEBGL_multi_draw(GLctx);var ext=context.GLctx.getExtension(extString);return!!ext};var _emscripten_webgl_init_context_attributes=attributes=>{var a=attributes>>2;for(var i=0;i<56>>2;++i){HEAP32[a+i]=0}HEAP32[a+(0>>2)]=HEAP32[a+(4>>2)]=HEAP32[a+(12>>2)]=HEAP32[a+(16>>2)]=HEAP32[a+(32>>2)]=HEAP32[a+(40>>2)]=1};var _emscripten_webgl_make_context_current=contextHandle=>{var success=GL.makeContextCurrent(contextHandle);return success?0:-5};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":lang,"_":getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}HEAP8[buffer>>0]=0};var _environ_get=(__environ,environ_buf)=>{var bufSize=0;getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1});return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(string=>bufSize+=string.length+1);HEAPU32[penviron_buf_size>>2]=bufSize;return 0};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf>>0]=type;HEAP16[pbuf+2>>1]=flags;tempI64=[rightsBase>>>0,(tempDouble=rightsBase,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+8>>2]=tempI64[0],HEAP32[pbuf+12>>2]=tempI64[1];tempI64=[rightsInheriting>>>0,(tempDouble=rightsInheriting,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+16>>2]=tempI64[0],HEAP32[pbuf+20>>2]=tempI64[1];return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr<len)break;if(typeof offset!=="undefined"){offset+=curr}}return ret};function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!=="undefined"){offset+=curr}}return ret};function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _glActiveTexture(x0){GLctx.activeTexture(x0)}var _glAttachShader=(program,shader)=>{GLctx.attachShader(GL.programs[program],GL.shaders[shader])};var _glBindBuffer=(target,buffer)=>{if(target==34962){GLctx.currentArrayBufferBinding=buffer}else if(target==34963){GLctx.currentElementArrayBufferBinding=buffer}if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,GL.buffers[buffer])};var _glBindFramebuffer=(target,framebuffer)=>{GLctx.bindFramebuffer(target,GL.framebuffers[framebuffer])};var _glBindRenderbuffer=(target,renderbuffer)=>{GLctx.bindRenderbuffer(target,GL.renderbuffers[renderbuffer])};var _glBindSampler=(unit,sampler)=>{GLctx.bindSampler(unit,GL.samplers[sampler])};var _glBindTexture=(target,texture)=>{GLctx.bindTexture(target,GL.textures[texture])};var _glBindVertexArray=vao=>{GLctx.bindVertexArray(GL.vaos[vao]);var ibo=GLctx.getParameter(34965);GLctx.currentElementArrayBufferBinding=ibo?ibo.name|0:0};function _glBlendColor(x0,x1,x2,x3){GLctx.blendColor(x0,x1,x2,x3)}function _glBlendEquationSeparate(x0,x1){GLctx.blendEquationSeparate(x0,x1)}function _glBlendFuncSeparate(x0,x1,x2,x3){GLctx.blendFuncSeparate(x0,x1,x2,x3)}function _glBlitFramebuffer(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9){GLctx.blitFramebuffer(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)}var _glBufferData=(target,size,data,usage)=>{if(GL.currentContext.version>=2){if(data&&size){GLctx.bufferData(target,HEAPU8,usage,data,size)}else{GLctx.bufferData(target,size,usage)}}else{GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)}};var _glBufferSubData=(target,offset,size,data)=>{if(GL.currentContext.version>=2){size&&GLctx.bufferSubData(target,offset,HEAPU8,data,size);return}GLctx.bufferSubData(target,offset,HEAPU8.subarray(data,data+size))};var _glClearBufferfv=(buffer,drawbuffer,value)=>{GLctx.clearBufferfv(buffer,drawbuffer,HEAPF32,value>>2)};var _glColorMask=(red,green,blue,alpha)=>{GLctx.colorMask(!!red,!!green,!!blue,!!alpha)};var _glCompileShader=shader=>{GLctx.compileShader(GL.shaders[shader])};var _glCompressedTexImage2D=(target,level,internalFormat,width,height,border,imageSize,data)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding||!imageSize){GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,imageSize,data)}else{GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,HEAPU8,data,imageSize)}return}GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,data?HEAPU8.subarray(data,data+imageSize):null)};var _glCompressedTexImage3D=(target,level,internalFormat,width,height,depth,border,imageSize,data)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.compressedTexImage3D(target,level,internalFormat,width,height,depth,border,imageSize,data)}else{GLctx.compressedTexImage3D(target,level,internalFormat,width,height,depth,border,HEAPU8,data,imageSize)}};var _glCreateProgram=()=>{var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;program.maxUniformLength=program.maxAttributeLength=program.maxUniformBlockNameLength=0;program.uniformIdCounter=1;GL.programs[id]=program;return id};var _glCreateShader=shaderType=>{var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id};function _glCullFace(x0){GLctx.cullFace(x0)}var _glDeleteBuffers=(n,buffers)=>{for(var i=0;i<n;i++){var id=HEAP32[buffers+i*4>>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GLctx.currentArrayBufferBinding)GLctx.currentArrayBufferBinding=0;if(id==GLctx.currentElementArrayBufferBinding)GLctx.currentElementArrayBufferBinding=0;if(id==GLctx.currentPixelPackBufferBinding)GLctx.currentPixelPackBufferBinding=0;if(id==GLctx.currentPixelUnpackBufferBinding)GLctx.currentPixelUnpackBufferBinding=0}};var _glDeleteFramebuffers=(n,framebuffers)=>{for(var i=0;i<n;++i){var id=HEAP32[framebuffers+i*4>>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}};var _glDeleteProgram=id=>{if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null};var _glDeleteRenderbuffers=(n,renderbuffers)=>{for(var i=0;i<n;i++){var id=HEAP32[renderbuffers+i*4>>2];var renderbuffer=GL.renderbuffers[id];if(!renderbuffer)continue;GLctx.deleteRenderbuffer(renderbuffer);renderbuffer.name=0;GL.renderbuffers[id]=null}};var _glDeleteSamplers=(n,samplers)=>{for(var i=0;i<n;i++){var id=HEAP32[samplers+i*4>>2];var sampler=GL.samplers[id];if(!sampler)continue;GLctx.deleteSampler(sampler);sampler.name=0;GL.samplers[id]=null}};var _glDeleteShader=id=>{if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null};var _glDeleteTextures=(n,textures)=>{for(var i=0;i<n;i++){var id=HEAP32[textures+i*4>>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}};var _glDeleteVertexArrays=(n,vaos)=>{for(var i=0;i<n;i++){var id=HEAP32[vaos+i*4>>2];GLctx.deleteVertexArray(GL.vaos[id]);GL.vaos[id]=null}};function _glDepthFunc(x0){GLctx.depthFunc(x0)}var _glDepthMask=flag=>{GLctx.depthMask(!!flag)};function _glDisable(x0){GLctx.disable(x0)}var _glDisableVertexAttribArray=index=>{var cb=GL.currentContext.clientBuffers[index];cb.enabled=false;GLctx.disableVertexAttribArray(index)};var _glDrawArrays=(mode,first,count)=>{GL.preDrawHandleClientVertexAttribBindings(first+count);GLctx.drawArrays(mode,first,count);GL.postDrawHandleClientVertexAttribBindings()};var _glDrawArraysInstanced=(mode,first,count,primcount)=>{GLctx.drawArraysInstanced(mode,first,count,primcount)};var _glDrawElements=(mode,count,type,indices)=>{var buf;if(!GLctx.currentElementArrayBufferBinding){var size=GL.calcBufLength(1,type,0,count);buf=GL.getTempIndexBuffer(size);GLctx.bindBuffer(34963,buf);GLctx.bufferSubData(34963,0,HEAPU8.subarray(indices,indices+size));indices=0}GL.preDrawHandleClientVertexAttribBindings(count);GLctx.drawElements(mode,count,type,indices);GL.postDrawHandleClientVertexAttribBindings(count);if(!GLctx.currentElementArrayBufferBinding){GLctx.bindBuffer(34963,null)}};var _glDrawElementsInstanced=(mode,count,type,indices,primcount)=>{GLctx.drawElementsInstanced(mode,count,type,indices,primcount)};function _glEnable(x0){GLctx.enable(x0)}var _glEnableVertexAttribArray=index=>{var cb=GL.currentContext.clientBuffers[index];cb.enabled=true;GLctx.enableVertexAttribArray(index)};function _glFrontFace(x0){GLctx.frontFace(x0)}var __glGenObject=(n,buffers,createFunction,objectTable)=>{for(var i=0;i<n;i++){var buffer=GLctx[createFunction]();var id=buffer&&GL.getNewId(objectTable);if(buffer){buffer.name=id;objectTable[id]=buffer}else{GL.recordError(1282)}HEAP32[buffers+i*4>>2]=id}};var _glGenBuffers=(n,buffers)=>{__glGenObject(n,buffers,"createBuffer",GL.buffers)};var _glGenRenderbuffers=(n,renderbuffers)=>{__glGenObject(n,renderbuffers,"createRenderbuffer",GL.renderbuffers)};var _glGenSamplers=(n,samplers)=>{__glGenObject(n,samplers,"createSampler",GL.samplers)};var _glGenTextures=(n,textures)=>{__glGenObject(n,textures,"createTexture",GL.textures)};function _glGenVertexArrays(n,arrays){__glGenObject(n,arrays,"createVertexArray",GL.vaos)}var _glGetAttribLocation=(program,name)=>GLctx.getAttribLocation(GL.programs[program],UTF8ToString(name));var writeI53ToI64=(ptr,num)=>{HEAPU32[ptr>>2]=num;var lower=HEAPU32[ptr>>2];HEAPU32[ptr+4>>2]=(num-lower)/4294967296};var emscriptenWebGLGet=(name_,p,type)=>{if(!p){GL.recordError(1281);return}var ret=undefined;switch(name_){case 36346:ret=1;break;case 36344:if(type!=0&&type!=1){GL.recordError(1280)}return;case 34814:case 36345:ret=0;break;case 34466:var formats=GLctx.getParameter(34467);ret=formats?formats.length:0;break;case 33309:if(GL.currentContext.version<2){GL.recordError(1282);return}var exts=GLctx.getSupportedExtensions()||[];ret=2*exts.length;break;case 33307:case 33308:if(GL.currentContext.version<2){GL.recordError(1280);return}ret=name_==33307?3:0;break}if(ret===undefined){var result=GLctx.getParameter(name_);switch(typeof result){case"number":ret=result;break;case"boolean":ret=result?1:0;break;case"string":GL.recordError(1280);return;case"object":if(result===null){switch(name_){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:{ret=0;break}default:{GL.recordError(1280);return}}}else if(result instanceof Float32Array||result instanceof Uint32Array||result instanceof Int32Array||result instanceof Array){for(var i=0;i<result.length;++i){switch(type){case 0:HEAP32[p+i*4>>2]=result[i];break;case 2:HEAPF32[p+i*4>>2]=result[i];break;case 4:HEAP8[p+i>>0]=result[i]?1:0;break}}return}else{try{ret=result.name|0}catch(e){GL.recordError(1280);err(`GL_INVALID_ENUM in glGet${type}v: Unknown object returned from WebGL getParameter(${name_})! (error: ${e})`);return}}break;default:GL.recordError(1280);err(`GL_INVALID_ENUM in glGet${type}v: Native code calling glGet${type}v(${name_}) and it returns ${result} of type ${typeof result}!`);return}}switch(type){case 1:writeI53ToI64(p,ret);break;case 0:HEAP32[p>>2]=ret;break;case 2:HEAPF32[p>>2]=ret;break;case 4:HEAP8[p>>0]=ret?1:0;break}};var _glGetIntegerv=(name_,p)=>emscriptenWebGLGet(name_,p,0);var _glGetProgramInfoLog=(program,maxLength,length,infoLog)=>{var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull};var _glGetProgramiv=(program,pname,p)=>{if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}program=GL.programs[program];if(pname==35716){var log=GLctx.getProgramInfoLog(program);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35719){if(!program.maxUniformLength){for(var i=0;i<GLctx.getProgramParameter(program,35718);++i){program.maxUniformLength=Math.max(program.maxUniformLength,GLctx.getActiveUniform(program,i).name.length+1)}}HEAP32[p>>2]=program.maxUniformLength}else if(pname==35722){if(!program.maxAttributeLength){for(var i=0;i<GLctx.getProgramParameter(program,35721);++i){program.maxAttributeLength=Math.max(program.maxAttributeLength,GLctx.getActiveAttrib(program,i).name.length+1)}}HEAP32[p>>2]=program.maxAttributeLength}else if(pname==35381){if(!program.maxUniformBlockNameLength){for(var i=0;i<GLctx.getProgramParameter(program,35382);++i){program.maxUniformBlockNameLength=Math.max(program.maxUniformBlockNameLength,GLctx.getActiveUniformBlockName(program,i).length+1)}}HEAP32[p>>2]=program.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(program,pname)}};var _glGetShaderInfoLog=(shader,maxLength,length,infoLog)=>{var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull};var _glGetShaderiv=(shader,pname,p)=>{if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var logLength=log?log.length+1:0;HEAP32[p>>2]=logLength}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source?source.length+1:0;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}};var stringToNewUTF8=str=>{var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8(str,ret,size);return ret};var _glGetStringi=(name,index)=>{if(GL.currentContext.version<2){GL.recordError(1282);return 0}var stringiCache=GL.stringiCache[name];if(stringiCache){if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index]}switch(name){case 7939:var exts=GL.getExtensions().map(e=>stringToNewUTF8(e));stringiCache=GL.stringiCache[name]=exts;if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index];default:GL.recordError(1280);return 0}};var jstoi_q=str=>parseInt(str);var webglGetLeftBracePos=name=>name.slice(-1)=="]"&&name.lastIndexOf("[");var webglPrepareUniformLocationsBeforeFirstUse=program=>{var uniformLocsById=program.uniformLocsById,uniformSizeAndIdsByName=program.uniformSizeAndIdsByName,i,j;if(!uniformLocsById){program.uniformLocsById=uniformLocsById={};program.uniformArrayNamesById={};for(i=0;i<GLctx.getProgramParameter(program,35718);++i){var u=GLctx.getActiveUniform(program,i);var nm=u.name;var sz=u.size;var lb=webglGetLeftBracePos(nm);var arrayName=lb>0?nm.slice(0,lb):nm;var id=program.uniformIdCounter;program.uniformIdCounter+=sz;uniformSizeAndIdsByName[arrayName]=[sz,id];for(j=0;j<sz;++j){uniformLocsById[id]=j;program.uniformArrayNamesById[id++]=arrayName}}}};var _glGetUniformLocation=(program,name)=>{name=UTF8ToString(name);if(program=GL.programs[program]){webglPrepareUniformLocationsBeforeFirstUse(program);var uniformLocsById=program.uniformLocsById;var arrayIndex=0;var uniformBaseName=name;var leftBrace=webglGetLeftBracePos(name);if(leftBrace>0){arrayIndex=jstoi_q(name.slice(leftBrace+1))>>>0;uniformBaseName=name.slice(0,leftBrace)}var sizeAndId=program.uniformSizeAndIdsByName[uniformBaseName];if(sizeAndId&&arrayIndex<sizeAndId[0]){arrayIndex+=sizeAndId[1];if(uniformLocsById[arrayIndex]=uniformLocsById[arrayIndex]||GLctx.getUniformLocation(program,name)){return arrayIndex}}}else{GL.recordError(1281)}return-1};var tempFixedLengthArray=[];var _glInvalidateFramebuffer=(target,numAttachments,attachments)=>{var list=tempFixedLengthArray[numAttachments];for(var i=0;i<numAttachments;i++){list[i]=HEAP32[attachments+i*4>>2]}GLctx.invalidateFramebuffer(target,list)};var _glLinkProgram=program=>{program=GL.programs[program];GLctx.linkProgram(program);program.uniformLocsById=0;program.uniformSizeAndIdsByName={}};var _glPixelStorei=(pname,param)=>{if(pname==3317){GL.unpackAlignment=param}GLctx.pixelStorei(pname,param)};function _glPolygonOffset(x0,x1){GLctx.polygonOffset(x0,x1)}function _glReadBuffer(x0){GLctx.readBuffer(x0)}function _glRenderbufferStorageMultisample(x0,x1,x2,x3,x4){GLctx.renderbufferStorageMultisample(x0,x1,x2,x3,x4)}var _glSamplerParameterf=(sampler,pname,param)=>{GLctx.samplerParameterf(GL.samplers[sampler],pname,param)};var _glSamplerParameteri=(sampler,pname,param)=>{GLctx.samplerParameteri(GL.samplers[sampler],pname,param)};function _glScissor(x0,x1,x2,x3){GLctx.scissor(x0,x1,x2,x3)}var _glShaderSource=(shader,count,string,length)=>{var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)};function _glStencilFunc(x0,x1,x2){GLctx.stencilFunc(x0,x1,x2)}function _glStencilFuncSeparate(x0,x1,x2,x3){GLctx.stencilFuncSeparate(x0,x1,x2,x3)}function _glStencilMask(x0){GLctx.stencilMask(x0)}function _glStencilOp(x0,x1,x2){GLctx.stencilOp(x0,x1,x2)}function _glStencilOpSeparate(x0,x1,x2,x3){GLctx.stencilOpSeparate(x0,x1,x2,x3)}var computeUnpackAlignedImageSize=(width,height,sizePerPixel,alignment)=>{function roundedToNextMultipleOf(x,y){return x+y-1&-y}var plainRowSize=width*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,alignment);return height*alignedRowSize};var colorChannelsInGlTextureFormat=format=>{var colorChannels={5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4};return colorChannels[format-6402]||1};var heapObjectForWebGLType=type=>{type-=5120;if(type==0)return HEAP8;if(type==1)return HEAPU8;if(type==2)return HEAP16;if(type==4)return HEAP32;if(type==6)return HEAPF32;if(type==5||type==28922||type==28520||type==30779||type==30782)return HEAPU32;return HEAPU16};var heapAccessShiftForWebGLHeap=heap=>31-Math.clz32(heap.BYTES_PER_ELEMENT);var emscriptenWebGLGetTexPixelData=(type,format,width,height,pixels,internalFormat)=>{var heap=heapObjectForWebGLType(type);var shift=heapAccessShiftForWebGLHeap(heap);var byteSize=1<<shift;var sizePerPixel=colorChannelsInGlTextureFormat(format)*byteSize;var bytes=computeUnpackAlignedImageSize(width,height,sizePerPixel,GL.unpackAlignment);return heap.subarray(pixels>>shift,pixels+bytes>>shift)};var _glTexImage2D=(target,level,internalFormat,width,height,border,format,type,pixels)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,null)}return}GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null)};var _glTexImage3D=(target,level,internalFormat,width,height,depth,border,format,type,pixels)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,null)}};function _glTexParameteri(x0,x1,x2){GLctx.texParameteri(x0,x1,x2)}var _glTexSubImage2D=(target,level,xoffset,yoffset,width,height,format,type,pixels)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,null)}return}var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)};var _glTexSubImage3D=(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,null)}};var webglGetUniformLocation=location=>{var p=GLctx.currentProgram;if(p){var webglLoc=p.uniformLocsById[location];if(typeof webglLoc=="number"){p.uniformLocsById[location]=webglLoc=GLctx.getUniformLocation(p,p.uniformArrayNamesById[location]+(webglLoc>0?`[${webglLoc}]`:""))}return webglLoc}else{GL.recordError(1282)}};var miniTempWebGLFloatBuffers=[];var _glUniform1fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform1fv(webglGetUniformLocation(location),HEAPF32,value>>2,count);return}if(count<=288){var view=miniTempWebGLFloatBuffers[count-1];for(var i=0;i<count;++i){view[i]=HEAPF32[value+4*i>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1fv(webglGetUniformLocation(location),view)};var _glUniform1i=(location,v0)=>{GLctx.uniform1i(webglGetUniformLocation(location),v0)};var miniTempWebGLIntBuffers=[];var _glUniform1iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform1iv(webglGetUniformLocation(location),HEAP32,value>>2,count);return}if(count<=288){var view=miniTempWebGLIntBuffers[count-1];for(var i=0;i<count;++i){view[i]=HEAP32[value+4*i>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1iv(webglGetUniformLocation(location),view)};var _glUniform2fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform2fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*2);return}if(count<=144){var view=miniTempWebGLFloatBuffers[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(webglGetUniformLocation(location),view)};var _glUniform2iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform2iv(webglGetUniformLocation(location),HEAP32,value>>2,count*2);return}if(count<=144){var view=miniTempWebGLIntBuffers[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2iv(webglGetUniformLocation(location),view)};var _glUniform3fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform3fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*3);return}if(count<=96){var view=miniTempWebGLFloatBuffers[3*count-1];for(var i=0;i<3*count;i+=3){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3fv(webglGetUniformLocation(location),view)};var _glUniform3iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform3iv(webglGetUniformLocation(location),HEAP32,value>>2,count*3);return}if(count<=96){var view=miniTempWebGLIntBuffers[3*count-1];for(var i=0;i<3*count;i+=3){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3iv(webglGetUniformLocation(location),view)};var _glUniform4fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform4fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*4);return}if(count<=72){var view=miniTempWebGLFloatBuffers[4*count-1];var heap=HEAPF32;value>>=2;for(var i=0;i<4*count;i+=4){var dst=value+i;view[i]=heap[dst];view[i+1]=heap[dst+1];view[i+2]=heap[dst+2];view[i+3]=heap[dst+3]}}else{var view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4fv(webglGetUniformLocation(location),view)};var _glUniform4iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform4iv(webglGetUniformLocation(location),HEAP32,value>>2,count*4);return}if(count<=72){var view=miniTempWebGLIntBuffers[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2];view[i+3]=HEAP32[value+(4*i+12)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4iv(webglGetUniformLocation(location),view)};var _glUniformMatrix4fv=(location,count,transpose,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*16);return}if(count<=18){var view=miniTempWebGLFloatBuffers[16*count-1];var heap=HEAPF32;value>>=2;for(var i=0;i<16*count;i+=16){var dst=value+i;view[i]=heap[dst];view[i+1]=heap[dst+1];view[i+2]=heap[dst+2];view[i+3]=heap[dst+3];view[i+4]=heap[dst+4];view[i+5]=heap[dst+5];view[i+6]=heap[dst+6];view[i+7]=heap[dst+7];view[i+8]=heap[dst+8];view[i+9]=heap[dst+9];view[i+10]=heap[dst+10];view[i+11]=heap[dst+11];view[i+12]=heap[dst+12];view[i+13]=heap[dst+13];view[i+14]=heap[dst+14];view[i+15]=heap[dst+15]}}else{var view=HEAPF32.subarray(value>>2,value+count*64>>2)}GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,view)};var _glUseProgram=program=>{program=GL.programs[program];GLctx.useProgram(program);GLctx.currentProgram=program};var _glVertexAttribDivisor=(index,divisor)=>{GLctx.vertexAttribDivisor(index,divisor)};var _glVertexAttribPointer=(index,size,type,normalized,stride,ptr)=>{var cb=GL.currentContext.clientBuffers[index];if(!GLctx.currentArrayBufferBinding){cb.size=size;cb.type=type;cb.normalized=normalized;cb.stride=stride;cb.ptr=ptr;cb.clientside=true;cb.vertexAttribPointerAdaptor=function(index,size,type,normalized,stride,ptr){this.vertexAttribPointer(index,size,type,normalized,stride,ptr)};return}cb.clientside=false;GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)};function _glViewport(x0,x1,x2,x3){GLctx.viewport(x0,x1,x2,x3)}var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var arraySum=(array,index)=>{var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum};var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];var addDays=(date,days)=>{var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var _strftime=(s,maxsize,format,tm)=>{var tm_zone=HEAPU32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value=="number"?value.toString():value||"";while(str.length<digits){str=character[0]+str}return str}function leadingNulls(value,digits){return leadingSomething(value,digits,"0")}function compareByDay(date1,date2){function sgn(value){return value<0?-1:value>0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={"%a":date=>WEEKDAYS[date.tm_wday].substring(0,3),"%A":date=>WEEKDAYS[date.tm_wday],"%b":date=>MONTHS[date.tm_mon].substring(0,3),"%B":date=>MONTHS[date.tm_mon],"%C":date=>{var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":date=>leadingNulls(date.tm_mday,2),"%e":date=>leadingSomething(date.tm_mday,2," "),"%g":date=>getWeekBasedYear(date).toString().substring(2),"%G":date=>getWeekBasedYear(date),"%H":date=>leadingNulls(date.tm_hour,2),"%I":date=>{var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":date=>leadingNulls(date.tm_mday+arraySum(isLeapYear(date.tm_year+1900)?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,date.tm_mon-1),3),"%m":date=>leadingNulls(date.tm_mon+1,2),"%M":date=>leadingNulls(date.tm_min,2),"%n":()=>"\n","%p":date=>{if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}return"PM"},"%S":date=>leadingNulls(date.tm_sec,2),"%t":()=>"\t","%u":date=>date.tm_wday||7,"%U":date=>{var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},"%V":date=>{var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},"%w":date=>date.tm_wday,"%W":date=>{var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},"%y":date=>(date.tm_year+1900).toString().substring(2),"%Y":date=>date.tm_year+1900,"%z":date=>{var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":date=>date.tm_zone,"%%":()=>"%"};pattern=pattern.replace(/%%/g,"\0\0");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\0\0/g,"%");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1};var _strftime_l=(s,maxsize,format,tm,loc)=>_strftime(s,maxsize,format,tm);var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var allocateUTF8OnStack=stringToUTF8OnStack;var getCFunc=ident=>{var func=Module["_"+ident];return func};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={"string":str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},"array":arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);function onDone(ret){if(stack!==0)stackRestore(stack);return convertReturnValue(ret)}ret=onDone(ret);return ret};var cwrap=(ident,returnType,argTypes,opts)=>{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return function(){return ccall(ident,returnType,argTypes,arguments,opts)}};var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_unlink"]=FS.unlink;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;var GLctx;for(var i=0;i<32;++i)tempFixedLengthArray.push(new Array(i));var miniTempWebGLFloatBuffersStorage=new Float32Array(288);for(var i=0;i<288;++i){miniTempWebGLFloatBuffers[i]=miniTempWebGLFloatBuffersStorage.subarray(0,i+1)}var miniTempWebGLIntBuffersStorage=new Int32Array(288);for(var i=0;i<288;++i){miniTempWebGLIntBuffers[i]=miniTempWebGLIntBuffersStorage.subarray(0,i+1)}var wasmImports={o:___cxa_begin_catch,w:___cxa_end_catch,a:___cxa_find_matching_catch_2,g:___cxa_find_matching_catch_3,Ma:___cxa_rethrow,Hb:___cxa_rethrow_primary_exception,b:___cxa_throw,Ib:___cxa_uncaught_exceptions,e:___resumeException,Mb:___syscall__newselect,Ka:___syscall_fcntl64,Rb:___syscall_fstat64,Ja:___syscall_ioctl,Ob:___syscall_lstat64,Nb:___syscall_mkdirat,Pb:___syscall_newfstatat,La:___syscall_openat,Kb:___syscall_readlinkat,Qb:___syscall_stat64,Ub:__emscripten_fs_load_embedded_files,Ab:__mmap_js,Bb:__munmap_js,v:_abort,m:_emscripten_asm_const_int,Sb:_emscripten_date_now,oa:_emscripten_get_device_pixel_ratio,Sa:_emscripten_get_element_css_size,Db:_emscripten_get_heap_max,B:_emscripten_get_now,Tb:_emscripten_memcpy_js,ub:_emscripten_request_animation_frame_loop,Jb:_emscripten_resize_heap,qa:_emscripten_set_blur_callback_on_thread,ma:_emscripten_set_canvas_element_size,ra:_emscripten_set_focus_callback_on_thread,Ga:_emscripten_set_keydown_callback_on_thread,Ba:_emscripten_set_keypress_callback_on_thread,Fa:_emscripten_set_keyup_callback_on_thread,U:_emscripten_set_mousedown_callback_on_thread,Oa:_emscripten_set_mouseenter_callback_on_thread,Na:_emscripten_set_mouseleave_callback_on_thread,Qa:_emscripten_set_mousemove_callback_on_thread,Ra:_emscripten_set_mouseup_callback_on_thread,ta:_emscripten_set_pointerlockchange_callback_on_thread,sa:_emscripten_set_pointerlockerror_callback_on_thread,wa:_emscripten_set_resize_callback_on_thread,ua:_emscripten_set_touchcancel_callback_on_thread,va:_emscripten_set_touchend_callback_on_thread,xa:_emscripten_set_touchmove_callback_on_thread,ya:_emscripten_set_touchstart_callback_on_thread,pa:_emscripten_set_webglcontextlost_callback_on_thread,na:_emscripten_set_webglcontextrestored_callback_on_thread,Ia:_emscripten_set_wheel_callback_on_thread,jb:_emscripten_webgl_create_context,bb:_emscripten_webgl_enable_extension,ob:_emscripten_webgl_init_context_attributes,gb:_emscripten_webgl_make_context_current,Fb:_environ_get,Gb:_environ_sizes_get,sb:_exit,P:_fd_close,Lb:_fd_fdstat_get,Ha:_fd_read,Cb:_fd_seek,O:_fd_write,A:_glActiveTexture,X:_glAttachShader,n:_glBindBuffer,D:_glBindFramebuffer,pc:_glBindRenderbuffer,z:_glBindSampler,q:_glBindTexture,ha:_glBindVertexArray,aa:_glBlendColor,ba:_glBlendEquationSeparate,ca:_glBlendFuncSeparate,sc:_glBlitFramebuffer,eb:_glBufferData,H:_glBufferSubData,Ya:_glClearBufferfv,M:_glColorMask,dc:_glCompileShader,jc:_glCompressedTexImage2D,lc:_glCompressedTexImage3D,cb:_glCreateProgram,fc:_glCreateShader,Z:_glCullFace,gc:_glDeleteBuffers,E:_glDeleteFramebuffers,I:_glDeleteProgram,ka:_glDeleteRenderbuffers,ja:_glDeleteSamplers,L:_glDeleteShader,la:_glDeleteTextures,rb:_glDeleteVertexArrays,fa:_glDepthFunc,ea:_glDepthMask,s:_glDisable,ga:_glDisableVertexAttribArray,uc:_glDrawArrays,vc:_glDrawArraysInstanced,Ta:_glDrawElements,Ua:_glDrawElementsInstanced,x:_glEnable,Va:_glEnableVertexAttribArray,_:_glFrontFace,fb:_glGenBuffers,qc:_glGenRenderbuffers,db:_glGenSamplers,nc:_glGenTextures,lb:_glGenVertexArrays,hc:_glGetAttribLocation,p:_glGetIntegerv,$a:_glGetProgramInfoLog,W:_glGetProgramiv,cc:_glGetShaderInfoLog,Pa:_glGetShaderiv,mb:_glGetStringi,G:_glGetUniformLocation,rc:_glInvalidateFramebuffer,ab:_glLinkProgram,kb:_glPixelStorei,$:_glPolygonOffset,tc:_glReadBuffer,oc:_glRenderbufferStorageMultisample,Y:_glSamplerParameterf,u:_glSamplerParameteri,S:_glScissor,ec:_glShaderSource,ib:_glStencilFunc,R:_glStencilFuncSeparate,da:_glStencilMask,hb:_glStencilOp,Q:_glStencilOpSeparate,ic:_glTexImage2D,kc:_glTexImage3D,mc:_glTexParameteri,Za:_glTexSubImage2D,_a:_glTexSubImage3D,bc:_glUniform1fv,V:_glUniform1i,Zb:_glUniform1iv,ac:_glUniform2fv,Yb:_glUniform2iv,$b:_glUniform3fv,Xb:_glUniform3iv,_b:_glUniform4fv,Wb:_glUniform4iv,Vb:_glUniformMatrix4fv,F:_glUseProgram,Wa:_glVertexAttribDivisor,Xa:_glVertexAttribPointer,T:_glViewport,za:invoke_diii,Aa:invoke_fiii,j:invoke_i,c:invoke_ii,f:invoke_iii,k:invoke_iiii,h:invoke_iiiii,Da:invoke_iiiiii,y:invoke_iiiiiii,Ca:invoke_iiiiiiii,K:invoke_iiiiiiiiiiii,zb:invoke_iiiiij,yb:invoke_jiiii,i:invoke_v,t:invoke_vi,d:invoke_vii,l:invoke_viii,Ea:invoke_viiii,r:invoke_viiiiiii,C:invoke_viiiiiiiiii,J:invoke_viiiiiiiiiiiiiii,xb:sapp_js_add_beforeunload_listener,wb:sapp_js_add_clipboard_listener,vb:sapp_js_add_dragndrop_listeners,wc:sapp_js_init,qb:sapp_js_remove_beforeunload_listener,pb:sapp_js_remove_clipboard_listener,nb:sapp_js_remove_dragndrop_listeners,N:sapp_js_request_pointerlock,tb:sargs_js_parse_url,ia:slog_js_log,Eb:_strftime_l};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["yc"])();var __sapp_emsc_onpaste=Module["__sapp_emsc_onpaste"]=a0=>(__sapp_emsc_onpaste=Module["__sapp_emsc_onpaste"]=wasmExports["zc"])(a0);var __sapp_html5_get_ask_leave_site=Module["__sapp_html5_get_ask_leave_site"]=()=>(__sapp_html5_get_ask_leave_site=Module["__sapp_html5_get_ask_leave_site"]=wasmExports["Ac"])();var __sapp_emsc_begin_drop=Module["__sapp_emsc_begin_drop"]=a0=>(__sapp_emsc_begin_drop=Module["__sapp_emsc_begin_drop"]=wasmExports["Bc"])(a0);var __sapp_emsc_drop=Module["__sapp_emsc_drop"]=(a0,a1)=>(__sapp_emsc_drop=Module["__sapp_emsc_drop"]=wasmExports["Cc"])(a0,a1);var __sapp_emsc_end_drop=Module["__sapp_emsc_end_drop"]=(a0,a1,a2)=>(__sapp_emsc_end_drop=Module["__sapp_emsc_end_drop"]=wasmExports["Dc"])(a0,a1,a2);var __sapp_emsc_invoke_fetch_cb=Module["__sapp_emsc_invoke_fetch_cb"]=(a0,a1,a2,a3,a4,a5,a6,a7)=>(__sapp_emsc_invoke_fetch_cb=Module["__sapp_emsc_invoke_fetch_cb"]=wasmExports["Ec"])(a0,a1,a2,a3,a4,a5,a6,a7);var __sargs_add_kvp=Module["__sargs_add_kvp"]=(a0,a1)=>(__sargs_add_kvp=Module["__sargs_add_kvp"]=wasmExports["Fc"])(a0,a1);var _ma_device__on_notification_unlocked=Module["_ma_device__on_notification_unlocked"]=a0=>(_ma_device__on_notification_unlocked=Module["_ma_device__on_notification_unlocked"]=wasmExports["Gc"])(a0);var _ma_malloc_emscripten=Module["_ma_malloc_emscripten"]=(a0,a1)=>(_ma_malloc_emscripten=Module["_ma_malloc_emscripten"]=wasmExports["Hc"])(a0,a1);var _malloc=Module["_malloc"]=a0=>(_malloc=Module["_malloc"]=wasmExports["Ic"])(a0);var _ma_free_emscripten=Module["_ma_free_emscripten"]=(a0,a1)=>(_ma_free_emscripten=Module["_ma_free_emscripten"]=wasmExports["Jc"])(a0,a1);var _free=Module["_free"]=a0=>(_free=Module["_free"]=wasmExports["Kc"])(a0);var _ma_device_process_pcm_frames_capture__webaudio=Module["_ma_device_process_pcm_frames_capture__webaudio"]=(a0,a1,a2)=>(_ma_device_process_pcm_frames_capture__webaudio=Module["_ma_device_process_pcm_frames_capture__webaudio"]=wasmExports["Lc"])(a0,a1,a2);var _ma_device_process_pcm_frames_playback__webaudio=Module["_ma_device_process_pcm_frames_playback__webaudio"]=(a0,a1,a2)=>(_ma_device_process_pcm_frames_playback__webaudio=Module["_ma_device_process_pcm_frames_playback__webaudio"]=wasmExports["Mc"])(a0,a1,a2);var _rivemu_start_record=Module["_rivemu_start_record"]=(a0,a1,a2,a3,a4)=>(_rivemu_start_record=Module["_rivemu_start_record"]=wasmExports["Nc"])(a0,a1,a2,a3,a4);var ___errno_location=()=>(___errno_location=wasmExports["Oc"])();var _rivemu_start_replay=Module["_rivemu_start_replay"]=(a0,a1,a2,a3,a4,a5,a6)=>(_rivemu_start_replay=Module["_rivemu_start_replay"]=wasmExports["Pc"])(a0,a1,a2,a3,a4,a5,a6);var _rivemu_stop=Module["_rivemu_stop"]=a0=>(_rivemu_stop=Module["_rivemu_stop"]=wasmExports["Qc"])(a0);var _main=Module["_main"]=(a0,a1)=>(_main=Module["_main"]=wasmExports["Rc"])(a0,a1);var _emscripten_builtin_memalign=(a0,a1)=>(_emscripten_builtin_memalign=wasmExports["Tc"])(a0,a1);var _setThrew=(a0,a1)=>(_setThrew=wasmExports["Uc"])(a0,a1);var setTempRet0=a0=>(setTempRet0=wasmExports["Vc"])(a0);var stackSave=()=>(stackSave=wasmExports["Wc"])();var stackRestore=a0=>(stackRestore=wasmExports["Xc"])(a0);var stackAlloc=a0=>(stackAlloc=wasmExports["Yc"])(a0);var ___cxa_decrement_exception_refcount=a0=>(___cxa_decrement_exception_refcount=wasmExports["Zc"])(a0);var ___cxa_increment_exception_refcount=a0=>(___cxa_increment_exception_refcount=wasmExports["_c"])(a0);var ___cxa_free_exception=a0=>(___cxa_free_exception=wasmExports["__cxa_free_exception"])(a0);var ___cxa_can_catch=(a0,a1,a2)=>(___cxa_can_catch=wasmExports["$c"])(a0,a1,a2);var ___cxa_is_pointer_type=a0=>(___cxa_is_pointer_type=wasmExports["ad"])(a0);var dynCall_iiiiij=Module["dynCall_iiiiij"]=(a0,a1,a2,a3,a4,a5,a6)=>(dynCall_iiiiij=Module["dynCall_iiiiij"]=wasmExports["bd"])(a0,a1,a2,a3,a4,a5,a6);var dynCall_jiiii=Module["dynCall_jiiii"]=(a0,a1,a2,a3,a4)=>(dynCall_jiiii=Module["dynCall_jiiii"]=wasmExports["cd"])(a0,a1,a2,a3,a4);var ___emscripten_embedded_file_data=Module["___emscripten_embedded_file_data"]=21116300;var ___start_em_js=Module["___start_em_js"]=21148020;var ___stop_em_js=Module["___stop_em_js"]=21154130;function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiij(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiiiij(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jiiii(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}Module["addRunDependency"]=addRunDependency;Module["removeRunDependency"]=removeRunDependency;Module["FS_createPath"]=FS.createPath;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_unlink"]=FS.unlink;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function callMain(args=[]){var entryFunction=_main;args.unshift(thisProgram);var argc=args.length;var argv=stackAlloc((argc+1)*4);var argv_ptr=argv;args.forEach(arg=>{HEAPU32[argv_ptr>>2]=stringToUTF8OnStack(arg);argv_ptr+=4});HEAPU32[argv_ptr>>2]=0;try{var ret=entryFunction(argc,argv);exitJS(ret,true);return ret}catch(e){return handleException(e)}}function run(args=arguments_){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain(args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;run(); +var Module=typeof Module!="undefined"?Module:{};var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();FS.ignorePermissions=false;TTY.init();callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var wasmBinaryFile;wasmBinaryFile="rivemu.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{if(!response["ok"]){throw`failed to load wasm binary file at '${binaryFile}'`}return response["arrayBuffer"]()}).catch(()=>getBinarySync(binaryFile))}}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(instance=>instance).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function createWasm(){var info={"a":wasmImports};function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["Bc"];updateMemoryViews();wasmTable=wasmExports["Vc"];addOnInit(wasmExports["Cc"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);return false}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult);return{}}var tempDouble;var tempI64;var ASM_CONSTS={24944034:()=>{window.dispatchEvent(new Event("rivemu_on_startup"))},24944092:($0,$1,$2,$3,$4)=>{if(typeof window==="undefined"||(window.AudioContext||window.webkitAudioContext)===undefined){return 0}if(typeof window.miniaudio==="undefined"){window.miniaudio={referenceCount:0};window.miniaudio.device_type={};window.miniaudio.device_type.playback=$0;window.miniaudio.device_type.capture=$1;window.miniaudio.device_type.duplex=$2;window.miniaudio.device_state={};window.miniaudio.device_state.stopped=$3;window.miniaudio.device_state.started=$4;miniaudio.devices=[];miniaudio.track_device=function(device){for(var iDevice=0;iDevice<miniaudio.devices.length;++iDevice){if(miniaudio.devices[iDevice]==null){miniaudio.devices[iDevice]=device;return iDevice}}miniaudio.devices.push(device);return miniaudio.devices.length-1};miniaudio.untrack_device_by_index=function(deviceIndex){miniaudio.devices[deviceIndex]=null;while(miniaudio.devices.length>0){if(miniaudio.devices[miniaudio.devices.length-1]==null){miniaudio.devices.pop()}else{break}}};miniaudio.untrack_device=function(device){for(var iDevice=0;iDevice<miniaudio.devices.length;++iDevice){if(miniaudio.devices[iDevice]==device){return miniaudio.untrack_device_by_index(iDevice)}}};miniaudio.get_device_by_index=function(deviceIndex){return miniaudio.devices[deviceIndex]};miniaudio.unlock_event_types=function(){return["touchend","click"]}();miniaudio.unlock=function(){for(var i=0;i<miniaudio.devices.length;++i){var device=miniaudio.devices[i];if(device!=null&&device.webaudio!=null&&device.state===window.miniaudio.device_state.started){device.webaudio.resume().then(()=>{Module._ma_device__on_notification_unlocked(device.pDevice)},error=>{console.error("Failed to resume audiocontext",error)})}}miniaudio.unlock_event_types.map(function(event_type){document.removeEventListener(event_type,miniaudio.unlock,true)})};miniaudio.unlock_event_types.map(function(event_type){document.addEventListener(event_type,miniaudio.unlock,true)})}window.miniaudio.referenceCount+=1;return 1},24946250:()=>{if(typeof window.miniaudio!=="undefined"){miniaudio.unlock_event_types.map(function(event_type){document.removeEventListener(event_type,miniaudio.unlock,true)});window.miniaudio.referenceCount-=1;if(window.miniaudio.referenceCount===0){delete window.miniaudio}}},24946540:()=>navigator.mediaDevices!==undefined&&navigator.mediaDevices.getUserMedia!==undefined,24946644:()=>{try{var temp=new(window.AudioContext||window.webkitAudioContext);var sampleRate=temp.sampleRate;temp.close();return sampleRate}catch(e){return 0}},24946815:($0,$1,$2,$3,$4,$5)=>{var deviceType=$0;var channels=$1;var sampleRate=$2;var bufferSize=$3;var pIntermediaryBuffer=$4;var pDevice=$5;if(typeof window.miniaudio==="undefined"){return-1}var device={};var audioContextOptions={};if(deviceType==window.miniaudio.device_type.playback&&sampleRate!=0){audioContextOptions.sampleRate=sampleRate}device.webaudio=new(window.AudioContext||window.webkitAudioContext)(audioContextOptions);device.webaudio.suspend();device.state=window.miniaudio.device_state.stopped;var channelCountIn=0;var channelCountOut=channels;if(deviceType!=window.miniaudio.device_type.playback){channelCountIn=channels}device.scriptNode=device.webaudio.createScriptProcessor(bufferSize,channelCountIn,channelCountOut);device.scriptNode.onaudioprocess=function(e){if(device.intermediaryBufferView==null||device.intermediaryBufferView.length==0){device.intermediaryBufferView=new Float32Array(Module.HEAPF32.buffer,pIntermediaryBuffer,bufferSize*channels)}if(deviceType==miniaudio.device_type.capture||deviceType==miniaudio.device_type.duplex){for(var iChannel=0;iChannel<channels;iChannel+=1){var inputBuffer=e.inputBuffer.getChannelData(iChannel);var intermediaryBuffer=device.intermediaryBufferView;for(var iFrame=0;iFrame<bufferSize;iFrame+=1){intermediaryBuffer[iFrame*channels+iChannel]=inputBuffer[iFrame]}}_ma_device_process_pcm_frames_capture__webaudio(pDevice,bufferSize,pIntermediaryBuffer)}if(deviceType==miniaudio.device_type.playback||deviceType==miniaudio.device_type.duplex){_ma_device_process_pcm_frames_playback__webaudio(pDevice,bufferSize,pIntermediaryBuffer);for(var iChannel=0;iChannel<e.outputBuffer.numberOfChannels;++iChannel){var outputBuffer=e.outputBuffer.getChannelData(iChannel);var intermediaryBuffer=device.intermediaryBufferView;for(var iFrame=0;iFrame<bufferSize;iFrame+=1){outputBuffer[iFrame]=intermediaryBuffer[iFrame*channels+iChannel]}}}else{for(var iChannel=0;iChannel<e.outputBuffer.numberOfChannels;++iChannel){e.outputBuffer.getChannelData(iChannel).fill(0)}}};if(deviceType==miniaudio.device_type.capture||deviceType==miniaudio.device_type.duplex){navigator.mediaDevices.getUserMedia({audio:true,video:false}).then(function(stream){device.streamNode=device.webaudio.createMediaStreamSource(stream);device.streamNode.connect(device.scriptNode);device.scriptNode.connect(device.webaudio.destination)}).catch(function(error){console.log("Failed to get user media: "+error)})}if(deviceType==miniaudio.device_type.playback){device.scriptNode.connect(device.webaudio.destination)}device.pDevice=pDevice;return miniaudio.track_device(device)},24949643:$0=>miniaudio.get_device_by_index($0).webaudio.sampleRate,24949709:$0=>{var device=miniaudio.get_device_by_index($0);if(device.scriptNode!==undefined){device.scriptNode.onaudioprocess=function(e){};device.scriptNode.disconnect();device.scriptNode=undefined}if(device.streamNode!==undefined){device.streamNode.disconnect();device.streamNode=undefined}device.webaudio.close();device.webaudio=undefined;device.pDevice=undefined},24950102:$0=>{miniaudio.untrack_device_by_index($0)},24950145:$0=>{var device=miniaudio.get_device_by_index($0);device.webaudio.resume();device.state=miniaudio.device_state.started},24950270:$0=>{var device=miniaudio.get_device_by_index($0);device.webaudio.suspend();device.state=miniaudio.device_state.stopped},24950396:($0,$1,$2,$3)=>{rivemu_on_begin($0,$1,$2,$3)},24950433:($0,$1,$2,$3,$4,$5,$6)=>{let outcard=HEAPU8.subarray($0,$0+$1);rivemu_on_frame(outcard,$2,$3,$4,$5,$6)},24950527:($0,$1,$2,$3,$4)=>{let rivlog=HEAPU8.subarray($0,$0+$1);let outcard=HEAPU8.subarray($2,$2+$3);let outhash=UTF8ToString($4);rivemu_on_finish(rivlog,outcard,outhash)},24950694:()=>{window.dispatchEvent(new Event("rivemu_on_shutdown"))}};function sapp_js_add_beforeunload_listener(){Module.sokol_beforeunload=event=>{if(__sapp_html5_get_ask_leave_site()!=0){event.preventDefault();event.returnValue=" "}};window.addEventListener("beforeunload",Module.sokol_beforeunload)}function sapp_js_remove_beforeunload_listener(){window.removeEventListener("beforeunload",Module.sokol_beforeunload)}function sapp_js_add_clipboard_listener(){Module.sokol_paste=event=>{const pasted_str=event.clipboardData.getData("text");withStackSave(()=>{const cstr=allocateUTF8OnStack(pasted_str);__sapp_emsc_onpaste(cstr)})};window.addEventListener("paste",Module.sokol_paste)}function sapp_js_remove_clipboard_listener(){window.removeEventListener("paste",Module.sokol_paste)}function sapp_js_add_dragndrop_listeners(canvas_name_cstr){Module.sokol_drop_files=[];const canvas_name=UTF8ToString(canvas_name_cstr);const canvas=document.getElementById(canvas_name);Module.sokol_dragenter=event=>{event.stopPropagation();event.preventDefault()};Module.sokol_dragleave=event=>{event.stopPropagation();event.preventDefault()};Module.sokol_dragover=event=>{event.stopPropagation();event.preventDefault()};Module.sokol_drop=event=>{event.stopPropagation();event.preventDefault();const files=event.dataTransfer.files;Module.sokol_dropped_files=files;__sapp_emsc_begin_drop(files.length);for(let i=0;i<files.length;i++){withStackSave(()=>{const cstr=allocateUTF8OnStack(files[i].name);__sapp_emsc_drop(i,cstr)})}let mods=0;if(event.shiftKey){mods|=1}if(event.ctrlKey){mods|=2}if(event.altKey){mods|=4}if(event.metaKey){mods|=8}__sapp_emsc_end_drop(event.clientX,event.clientY,mods)};canvas.addEventListener("dragenter",Module.sokol_dragenter,false);canvas.addEventListener("dragleave",Module.sokol_dragleave,false);canvas.addEventListener("dragover",Module.sokol_dragover,false);canvas.addEventListener("drop",Module.sokol_drop,false)}function sapp_js_remove_dragndrop_listeners(canvas_name_cstr){const canvas_name=UTF8ToString(canvas_name_cstr);const canvas=document.getElementById(canvas_name);canvas.removeEventListener("dragenter",Module.sokol_dragenter);canvas.removeEventListener("dragleave",Module.sokol_dragleave);canvas.removeEventListener("dragover",Module.sokol_dragover);canvas.removeEventListener("drop",Module.sokol_drop)}function sapp_js_init(c_str_target){const target_str=UTF8ToString(c_str_target);Module.sapp_emsc_target=document.getElementById(target_str);if(!Module.sapp_emsc_target){console.log("sokol_app.h: invalid target:"+target_str)}if(!Module.sapp_emsc_target.requestPointerLock){console.log("sokol_app.h: target doesn't support requestPointerLock:"+target_str)}}function sapp_js_request_pointerlock(){if(Module.sapp_emsc_target){if(Module.sapp_emsc_target.requestPointerLock){Module.sapp_emsc_target.requestPointerLock()}}}function sargs_js_parse_url(){const params=new URLSearchParams(window.location.search).entries();for(let p=params.next();!p.done;p=params.next()){const key=p.value[0];const val=p.value[1];withStackSave(()=>{const key_cstr=allocateUTF8OnStack(key);const val_cstr=allocateUTF8OnStack(val);__sargs_add_kvp(key_cstr,val_cstr)})}}function slog_js_log(level,c_str){const str=UTF8ToString(c_str);switch(level){case 0:console.error(str);break;case 1:console.error(str);break;case 2:console.warn(str);break;default:console.info(str);break}}function ExitStatus(status){this.name="ExitStatus";this.message=`Program terminated with exit(${status})`;this.status=status}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var noExitRuntime=Module["noExitRuntime"]||true;var exceptionCaught=[];var uncaughtExceptionCount=0;var ___cxa_begin_catch=ptr=>{var info=new ExceptionInfo(ptr);if(!info.get_caught()){info.set_caught(true);uncaughtExceptionCount--}info.set_rethrown(false);exceptionCaught.push(info);___cxa_increment_exception_refcount(info.excPtr);return info.get_exception_ptr()};var exceptionLast=0;var ___cxa_end_catch=()=>{_setThrew(0,0);var info=exceptionCaught.pop();___cxa_decrement_exception_refcount(info.excPtr);exceptionLast=0};class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught}get_caught(){return HEAP8[this.ptr+12>>0]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown}get_rethrown(){return HEAP8[this.ptr+13>>0]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}get_exception_ptr(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var ___resumeException=ptr=>{if(!exceptionLast){exceptionLast=ptr}throw exceptionLast};var findMatchingCatch=args=>{var thrown=exceptionLast;if(!thrown){setTempRet0(0);return 0}var info=new ExceptionInfo(thrown);info.set_adjusted_ptr(thrown);var thrownType=info.get_type();if(!thrownType){setTempRet0(0);return thrown}for(var arg in args){var caughtType=args[arg];if(caughtType===0||caughtType===thrownType){break}var adjusted_ptr_addr=info.ptr+16;if(___cxa_can_catch(caughtType,thrownType,adjusted_ptr_addr)){setTempRet0(caughtType);return thrown}}setTempRet0(thrownType);return thrown};var ___cxa_find_matching_catch_2=()=>findMatchingCatch([]);var ___cxa_find_matching_catch_3=arg0=>findMatchingCatch([arg0]);var ___cxa_rethrow=()=>{var info=exceptionCaught.pop();if(!info){abort("no exception to throw")}var ptr=info.excPtr;if(!info.get_rethrown()){exceptionCaught.push(info);info.set_rethrown(true);info.set_caught(false);uncaughtExceptionCount++}exceptionLast=ptr;throw exceptionLast};var ___cxa_rethrow_primary_exception=ptr=>{if(!ptr)return;var info=new ExceptionInfo(ptr);exceptionCaught.push(info);info.set_rethrown(true);___cxa_rethrow()};var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var ___cxa_uncaught_exceptions=()=>uncaughtExceptionCount;var PATH={isAbs:path=>path.charAt(0)==="/",splitPath:filename=>{var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:(parts,allowAboveRoot)=>{var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:path=>{var isAbsolute=PATH.isAbs(path),trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(p=>!!p),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:path=>{var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:path=>{if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},join:function(){var paths=Array.prototype.slice.call(arguments);return PATH.normalize(paths.join("/"))},join2:(l,r)=>PATH.normalize(l+"/"+r)};var initRandomFill=()=>{if(typeof crypto=="object"&&typeof crypto["getRandomValues"]=="function"){return view=>crypto.getRandomValues(view)}else abort("initRandomDevice")};var randomFill=view=>(randomFill=initRandomFill())(view);var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=PATH.isAbs(path)}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(p=>!!p),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:(from,to)=>{from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start<arr.length;start++){if(arr[start]!=="")break}var end=arr.length-1;for(;end>=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i<length;i++){if(fromParts[i]!==toParts[i]){samePartsLength=i;break}}var outputParts=[];for(var i=samePartsLength;i<fromParts.length;i++){outputParts.push("..")}outputParts=outputParts.concat(toParts.slice(samePartsLength));return outputParts.join("/")}};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx<endPtr){var u0=heapOrArray[idx++];if(!(u0&128)){str+=String.fromCharCode(u0);continue}var u1=heapOrArray[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}var u2=heapOrArray[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u0=(u0&7)<<18|u1<<12|u2<<6|heapOrArray[idx++]&63}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}return str};var FS_stdin_getChar_buffer=[];var lengthBytesUTF8=str=>{var len=0;for(var i=0;i<str.length;++i){var c=str.charCodeAt(i);if(c<=127){len++}else if(c<=2047){len+=2}else if(c>=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var FS_stdin_getChar=()=>{if(!FS_stdin_getChar_buffer.length){var result=null;if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}FS_stdin_getChar_buffer=intArrayFromString(result,true)}return FS_stdin_getChar_buffer.shift()};var TTY={ttys:[],init(){},shutdown(){},register(dev,ops){TTY.ttys[dev]={input:[],output:[],ops:ops};FS.registerDevice(dev,TTY.stream_ops)},stream_ops:{open(stream){var tty=TTY.ttys[stream.node.rdev];if(!tty){throw new FS.ErrnoError(43)}stream.tty=tty;stream.seekable=false},close(stream){stream.tty.ops.fsync(stream.tty)},fsync(stream){stream.tty.ops.fsync(stream.tty)},read(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.get_char){throw new FS.ErrnoError(60)}var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=stream.tty.ops.get_char(stream.tty)}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write(stream,buffer,offset,length,pos){if(!stream.tty||!stream.tty.ops.put_char){throw new FS.ErrnoError(60)}try{for(var i=0;i<length;i++){stream.tty.ops.put_char(stream.tty,buffer[offset+i])}}catch(e){throw new FS.ErrnoError(29)}if(length){stream.node.timestamp=Date.now()}return i}},default_tty_ops:{get_char(tty){return FS_stdin_getChar()},put_char(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}},ioctl_tcgets(tty){return{c_iflag:25856,c_oflag:5,c_cflag:191,c_lflag:35387,c_cc:[3,28,127,21,4,0,1,0,17,19,26,0,18,15,23,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}},ioctl_tcsets(tty,optional_actions,data){return 0},ioctl_tiocgwinsz(tty){return[24,80]}},default_tty1_ops:{put_char(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},fsync(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};var zeroMemory=(address,size)=>{HEAPU8.fill(0,address,address+size);return address};var alignMemory=(size,alignment)=>Math.ceil(size/alignment)*alignment;var mmapAlloc=size=>{size=alignMemory(size,65536);var ptr=_emscripten_builtin_memalign(65536,size);if(!ptr)return 0;return zeroMemory(ptr,size)};var MEMFS={ops_table:null,mount(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}MEMFS.ops_table||={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}};var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node;parent.timestamp=node.timestamp}return node},getFileDataAsTypedArray(node){if(!node.contents)return new Uint8Array(0);if(node.contents.subarray)return node.contents.subarray(0,node.usedBytes);return new Uint8Array(node.contents)},expandFileStorage(node,newCapacity){var prevCapacity=node.contents?node.contents.length:0;if(prevCapacity>=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity<CAPACITY_DOUBLING_MAX?2:1.125)>>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0)},resizeFileStorage(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0}else{var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize}},node_ops:{getattr(node){var attr={};attr.dev=FS.isChrdev(node.mode)?node.id:1;attr.ino=node.id;attr.mode=node.mode;attr.nlink=1;attr.uid=0;attr.gid=0;attr.rdev=node.rdev;if(FS.isDir(node.mode)){attr.size=4096}else if(FS.isFile(node.mode)){attr.size=node.usedBytes}else if(FS.isLink(node.mode)){attr.size=node.link.length}else{attr.size=0}attr.atime=new Date(node.timestamp);attr.mtime=new Date(node.timestamp);attr.ctime=new Date(node.timestamp);attr.blksize=4096;attr.blocks=Math.ceil(attr.size/attr.blksize);return attr},setattr(node,attr){if(attr.mode!==undefined){node.mode=attr.mode}if(attr.timestamp!==undefined){node.timestamp=attr.timestamp}if(attr.size!==undefined){MEMFS.resizeFileStorage(node,attr.size)}},lookup(parent,name){throw FS.genericErrors[44]},mknod(parent,name,mode,dev){return MEMFS.createNode(parent,name,mode,dev)},rename(old_node,new_dir,new_name){if(FS.isDir(old_node.mode)){var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(new_node){for(var i in new_node.contents){throw new FS.ErrnoError(55)}}}delete old_node.parent.contents[old_node.name];old_node.parent.timestamp=Date.now();old_node.name=new_name;new_dir.contents[new_name]=old_node;new_dir.timestamp=old_node.parent.timestamp;old_node.parent=new_dir},unlink(parent,name){delete parent.contents[name];parent.timestamp=Date.now()},rmdir(parent,name){var node=FS.lookupNode(parent,name);for(var i in node.contents){throw new FS.ErrnoError(55)}delete parent.contents[name];parent.timestamp=Date.now()},readdir(node){var entries=[".",".."];for(var key of Object.keys(node.contents)){entries.push(key)}return entries},symlink(parent,newname,oldpath){var node=MEMFS.createNode(parent,newname,511|40960,0);node.link=oldpath;return node},readlink(node){if(!FS.isLink(node.mode)){throw new FS.ErrnoError(28)}return node.link}},stream_ops:{read(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i<size;i++)buffer[offset+i]=contents[position+i]}return size},write(stream,buffer,offset,length,position,canOwn){if(!length)return 0;var node=stream.node;node.timestamp=Date.now();if(buffer.subarray&&(!node.contents||node.contents.subarray)){if(canOwn){node.contents=buffer.subarray(offset,offset+length);node.usedBytes=length;return length}else if(node.usedBytes===0&&position===0){node.contents=buffer.slice(offset,offset+length);node.usedBytes=length;return length}else if(position+length<=node.usedBytes){node.contents.set(buffer.subarray(offset,offset+length),position);return length}}MEMFS.expandFileStorage(node,position+length);if(node.contents.subarray&&buffer.subarray){node.contents.set(buffer.subarray(offset,offset+length),position)}else{for(var i=0;i<length;i++){node.contents[position+i]=buffer[offset+i]}}node.usedBytes=Math.max(node.usedBytes,position+length);return length},llseek(stream,offset,whence){var position=offset;if(whence===1){position+=stream.position}else if(whence===2){if(FS.isFile(stream.node.mode)){position+=stream.node.usedBytes}}if(position<0){throw new FS.ErrnoError(28)}return position},allocate(stream,offset,length){MEMFS.expandFileStorage(stream.node,offset+length);stream.node.usedBytes=Math.max(stream.node.usedBytes,offset+length)},mmap(stream,length,position,prot,flags){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}var ptr;var allocated;var contents=stream.node.contents;if(!(flags&2)&&contents.buffer===HEAP8.buffer){allocated=false;ptr=contents.byteOffset}else{if(position>0||position+length<contents.length){if(contents.subarray){contents=contents.subarray(position,position+length)}else{contents=Array.prototype.slice.call(contents,position,position+length)}}allocated=true;ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}HEAP8.set(contents,ptr)}return{ptr:ptr,allocated:allocated}},msync(stream,buffer,offset,length,mmapFlags){MEMFS.stream_ops.write(stream,buffer,0,length,offset,false);return 0}}};var asyncLoad=(url,onload,onerror,noRunDep)=>{var dep=!noRunDep?getUniqueRunDependency(`al ${url}`):"";readAsync(url,arrayBuffer=>{onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},event=>{if(onerror){onerror()}else{throw`Loading data file "${url}" failed.`}});if(dep)addRunDependency(dep)};var FS_createDataFile=(parent,name,fileData,canRead,canWrite,canOwn)=>{FS.createDataFile(parent,name,fileData,canRead,canWrite,canOwn)};var preloadPlugins=Module["preloadPlugins"]||[];var FS_handledByPreloadPlugin=(byteArray,fullname,finish,onerror)=>{if(typeof Browser!="undefined")Browser.init();var handled=false;preloadPlugins.forEach(plugin=>{if(handled)return;if(plugin["canHandle"](fullname)){plugin["handle"](byteArray,fullname,finish,onerror);handled=true}});return handled};var FS_createPreloadedFile=(parent,name,url,canRead,canWrite,onload,onerror,dontCreateFile,canOwn,preFinish)=>{var fullname=name?PATH_FS.resolve(PATH.join2(parent,name)):parent;var dep=getUniqueRunDependency(`cp ${fullname}`);function processData(byteArray){function finish(byteArray){preFinish?.();if(!dontCreateFile){FS_createDataFile(parent,name,byteArray,canRead,canWrite,canOwn)}onload?.();removeRunDependency(dep)}if(FS_handledByPreloadPlugin(byteArray,fullname,finish,()=>{onerror?.();removeRunDependency(dep)})){return}finish(byteArray)}addRunDependency(dep);if(typeof url=="string"){asyncLoad(url,processData,onerror)}else{processData(url)}};var FS_modeStringToFlags=str=>{var flagModes={"r":0,"r+":2,"w":512|64|1,"w+":512|64|2,"a":1024|64|1,"a+":1024|64|2};var flags=flagModes[str];if(typeof flags=="undefined"){throw new Error(`Unknown file open mode: ${str}`)}return flags};var FS_getMode=(canRead,canWrite)=>{var mode=0;if(canRead)mode|=292|73;if(canWrite)mode|=146;return mode};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:class{constructor(errno){this.name="ErrnoError";this.errno=errno}},genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath(path,opts={}){path=PATH_FS.resolve(path);if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};opts=Object.assign(defaults,opts);if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=path.split("/").filter(p=>!!p);var current=FS.root;var current_path="/";for(var i=0;i<parts.length;i++){var islast=i===parts.length-1;if(islast&&opts.parent){break}current=FS.lookupNode(current,parts[i]);current_path=PATH.join2(current_path,parts[i]);if(FS.isMountpoint(current)){if(!islast||islast&&opts.follow_mount){current=current.mounted.root}}if(!islast||opts.follow){var count=0;while(FS.isLink(current.mode)){var link=FS.readlink(current_path);current_path=PATH_FS.resolve(PATH.dirname(current_path),link);var lookup=FS.lookupPath(current_path,{recurse_count:opts.recurse_count+1});current=lookup.node;if(count++>40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?`${mount}/${path}`:mount+path}path=path?`${node.name}/${path}`:node.name;node=node.parent}},hashName(parentid,name){var hash=0;for(var i=0;i<name.length;i++){hash=(hash<<5)-hash+name.charCodeAt(i)|0}return(parentid+hash>>>0)%FS.nameTable.length},hashAddNode(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode)}var hash=FS.hashName(parent.id,name);for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode(node){FS.hashRemoveNode(node)},isRoot(node){return node===node.parent},isMountpoint(node){return!!node.mounted},isFile(mode){return(mode&61440)===32768},isDir(mode){return(mode&61440)===16384},isLink(mode){return(mode&61440)===40960},isChrdev(mode){return(mode&61440)===8192},isBlkdev(mode){return(mode&61440)===24576},isFIFO(mode){return(mode&61440)===4096},isSocket(mode){return(mode&49152)===49152},flagsToPermissionString(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions(node,perms){if(FS.ignorePermissions){return 0}if(perms.includes("r")&&!(node.mode&292)){return 2}else if(perms.includes("w")&&!(node.mode&146)){return 2}else if(perms.includes("x")&&!(node.mode&73)){return 2}return 0},mayLookup(dir){if(!FS.isDir(dir.mode))return 54;var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd(){for(var fd=0;fd<=FS.MAX_OPEN_FDS;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStreamChecked(fd){var stream=FS.getStream(fd);if(!stream){throw new FS.ErrnoError(8)}return stream},getStream:fd=>FS.streams[fd],createStream(stream,fd=-1){if(!FS.FSStream){FS.FSStream=function(){this.shared={}};FS.FSStream.prototype={};Object.defineProperties(FS.FSStream.prototype,{object:{get(){return this.node},set(val){this.node=val}},isRead:{get(){return(this.flags&2097155)!==1}},isWrite:{get(){return(this.flags&2097155)!==0}},isAppend:{get(){return this.flags&1024}},flags:{get(){return this.shared.flags},set(val){this.shared.flags=val}},position:{get(){return this.shared.position},set(val){this.shared.position=val}}})}stream=Object.assign(new FS.FSStream,stream);if(fd==-1){fd=FS.nextfd()}stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream(fd){FS.streams[fd]=null},chrdev_stream_ops:{open(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;stream.stream_ops.open?.(stream)},llseek(){throw new FS.ErrnoError(70)}},major:dev=>dev>>8,minor:dev=>dev&255,makedev:(ma,mi)=>ma<<8|mi,registerDevice(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:dev=>FS.devices[dev],getMounts(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs(populate,callback){if(typeof populate=="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err(`warning: ${FS.syncFSRequests} FS.syncfs operations in flight at once, probably just doing extra work`)}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(mount=>{if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(hash=>{var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.includes(current.mount)){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup(parent,name){return parent.node_ops.lookup(parent,name)},mknod(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree(path,mode){var dirs=path.split("/");var d="";for(var i=0;i<dirs.length;++i){if(!dirs[i])continue;d+="/"+dirs[i];try{FS.mkdir(d,mode)}catch(e){if(e.errno!=20)throw e}}},mkdev(path,mode,dev){if(typeof dev=="undefined"){dev=mode;mode=438}mode|=8192;return FS.mknod(path,mode,dev)},symlink(oldpath,newpath){if(!PATH_FS.resolve(oldpath)){throw new FS.ErrnoError(44)}var lookup=FS.lookupPath(newpath,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var newname=PATH.basename(newpath);var errCode=FS.mayCreate(parent,newname);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.symlink){throw new FS.ErrnoError(63)}return parent.node_ops.symlink(parent,newname,oldpath)},rename(old_path,new_path){var old_dirname=PATH.dirname(old_path);var new_dirname=PATH.dirname(new_path);var old_name=PATH.basename(old_path);var new_name=PATH.basename(new_path);var lookup,old_dir,new_dir;lookup=FS.lookupPath(old_path,{parent:true});old_dir=lookup.node;lookup=FS.lookupPath(new_path,{parent:true});new_dir=lookup.node;if(!old_dir||!new_dir)throw new FS.ErrnoError(44);if(old_dir.mount!==new_dir.mount){throw new FS.ErrnoError(75)}var old_node=FS.lookupNode(old_dir,old_name);var relative=PATH_FS.relative(old_path,new_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(28)}relative=PATH_FS.relative(new_path,old_dirname);if(relative.charAt(0)!=="."){throw new FS.ErrnoError(55)}var new_node;try{new_node=FS.lookupNode(new_dir,new_name)}catch(e){}if(old_node===new_node){return}var isdir=FS.isDir(old_node.mode);var errCode=FS.mayDelete(old_dir,old_name,isdir);if(errCode){throw new FS.ErrnoError(errCode)}errCode=new_node?FS.mayDelete(new_dir,new_name,isdir):FS.mayCreate(new_dir,new_name);if(errCode){throw new FS.ErrnoError(errCode)}if(!old_dir.node_ops.rename){throw new FS.ErrnoError(63)}if(FS.isMountpoint(old_node)||new_node&&FS.isMountpoint(new_node)){throw new FS.ErrnoError(10)}if(new_dir!==old_dir){errCode=FS.nodePermissions(old_dir,"w");if(errCode){throw new FS.ErrnoError(errCode)}}FS.hashRemoveNode(old_node);try{old_dir.node_ops.rename(old_node,new_dir,new_name)}catch(e){throw e}finally{FS.hashAddNode(old_node)}},rmdir(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,true);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.rmdir){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.rmdir(parent,name);FS.destroyNode(node)},readdir(path){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;if(!node.node_ops.readdir){throw new FS.ErrnoError(54)}return node.node_ops.readdir(node)},unlink(path){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;if(!parent){throw new FS.ErrnoError(44)}var name=PATH.basename(path);var node=FS.lookupNode(parent,name);var errCode=FS.mayDelete(parent,name,false);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.unlink){throw new FS.ErrnoError(63)}if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}parent.node_ops.unlink(parent,name);FS.destroyNode(node)},readlink(path){var lookup=FS.lookupPath(path);var link=lookup.node;if(!link){throw new FS.ErrnoError(44)}if(!link.node_ops.readlink){throw new FS.ErrnoError(28)}return PATH_FS.resolve(FS.getPath(link.parent),link.node_ops.readlink(link))},stat(path,dontFollow){var lookup=FS.lookupPath(path,{follow:!dontFollow});var node=lookup.node;if(!node){throw new FS.ErrnoError(44)}if(!node.node_ops.getattr){throw new FS.ErrnoError(63)}return node.node_ops.getattr(node)},lstat(path){return FS.stat(path,true)},chmod(path,mode,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{mode:mode&4095|node.mode&~4095,timestamp:Date.now()})},lchmod(path,mode){FS.chmod(path,mode,true)},fchmod(fd,mode){var stream=FS.getStreamChecked(fd);FS.chmod(stream.node,mode)},chown(path,uid,gid,dontFollow){var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:!dontFollow});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}node.node_ops.setattr(node,{timestamp:Date.now()})},lchown(path,uid,gid){FS.chown(path,uid,gid,true)},fchown(fd,uid,gid){var stream=FS.getStreamChecked(fd);FS.chown(stream.node,uid,gid)},truncate(path,len){if(len<0){throw new FS.ErrnoError(28)}var node;if(typeof path=="string"){var lookup=FS.lookupPath(path,{follow:true});node=lookup.node}else{node=path}if(!node.node_ops.setattr){throw new FS.ErrnoError(63)}if(FS.isDir(node.mode)){throw new FS.ErrnoError(31)}if(!FS.isFile(node.mode)){throw new FS.ErrnoError(28)}var errCode=FS.nodePermissions(node,"w");if(errCode){throw new FS.ErrnoError(errCode)}node.node_ops.setattr(node,{size:len,timestamp:Date.now()})},ftruncate(fd,len){var stream=FS.getStreamChecked(fd);if((stream.flags&2097155)===0){throw new FS.ErrnoError(28)}FS.truncate(stream.node,len)},utime(path,atime,mtime){var lookup=FS.lookupPath(path,{follow:true});var node=lookup.node;node.node_ops.setattr(node,{timestamp:Math.max(atime,mtime)})},open(path,flags,mode){if(path===""){throw new FS.ErrnoError(44)}flags=typeof flags=="string"?FS_modeStringToFlags(flags):flags;mode=typeof mode=="undefined"?438:mode;if(flags&64){mode=mode&4095|32768}else{mode=0}var node;if(typeof path=="object"){node=path}else{path=PATH.normalize(path);try{var lookup=FS.lookupPath(path,{follow:!(flags&131072)});node=lookup.node}catch(e){}}var created=false;if(flags&64){if(node){if(flags&128){throw new FS.ErrnoError(20)}}else{node=FS.mknod(path,mode,0);created=true}}if(!node){throw new FS.ErrnoError(44)}if(FS.isChrdev(node.mode)){flags&=~512}if(flags&65536&&!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}if(!created){var errCode=FS.mayOpen(node,flags);if(errCode){throw new FS.ErrnoError(errCode)}}if(flags&512&&!created){FS.truncate(node,0)}flags&=~(128|512|131072);var stream=FS.createStream({node:node,path:FS.getPath(node),flags:flags,seekable:true,position:0,stream_ops:node.stream_ops,ungotten:[],error:false});if(stream.stream_ops.open){stream.stream_ops.open(stream)}if(Module["logReadFiles"]&&!(flags&1)){if(!FS.readFiles)FS.readFiles={};if(!(path in FS.readFiles)){FS.readFiles[path]=1}}return stream},close(stream){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(stream.getdents)stream.getdents=null;try{if(stream.stream_ops.close){stream.stream_ops.close(stream)}}catch(e){throw e}finally{FS.closeStream(stream.fd)}stream.fd=null},isClosed(stream){return stream.fd===null},llseek(stream,offset,whence){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(!stream.seekable||!stream.stream_ops.llseek){throw new FS.ErrnoError(70)}if(whence!=0&&whence!=1&&whence!=2){throw new FS.ErrnoError(28)}stream.position=stream.stream_ops.llseek(stream,offset,whence);stream.ungotten=[];return stream.position},read(stream,buffer,offset,length,position){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.read){throw new FS.ErrnoError(28)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesRead=stream.stream_ops.read(stream,buffer,offset,length,position);if(!seeking)stream.position+=bytesRead;return bytesRead},write(stream,buffer,offset,length,position,canOwn){if(length<0||position<0){throw new FS.ErrnoError(28)}if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(FS.isDir(stream.node.mode)){throw new FS.ErrnoError(31)}if(!stream.stream_ops.write){throw new FS.ErrnoError(28)}if(stream.seekable&&stream.flags&1024){FS.llseek(stream,0,2)}var seeking=typeof position!="undefined";if(!seeking){position=stream.position}else if(!stream.seekable){throw new FS.ErrnoError(70)}var bytesWritten=stream.stream_ops.write(stream,buffer,offset,length,position,canOwn);if(!seeking)stream.position+=bytesWritten;return bytesWritten},allocate(stream,offset,length){if(FS.isClosed(stream)){throw new FS.ErrnoError(8)}if(offset<0||length<=0){throw new FS.ErrnoError(28)}if((stream.flags&2097155)===0){throw new FS.ErrnoError(8)}if(!FS.isFile(stream.node.mode)&&!FS.isDir(stream.node.mode)){throw new FS.ErrnoError(43)}if(!stream.stream_ops.allocate){throw new FS.ErrnoError(138)}stream.stream_ops.allocate(stream,offset,length)},mmap(stream,length,position,prot,flags){if((prot&2)!==0&&(flags&2)===0&&(stream.flags&2097155)!==2){throw new FS.ErrnoError(2)}if((stream.flags&2097155)===1){throw new FS.ErrnoError(2)}if(!stream.stream_ops.mmap){throw new FS.ErrnoError(43)}return stream.stream_ops.mmap(stream,length,position,prot,flags)},msync(stream,buffer,offset,length,mmapFlags){if(!stream.stream_ops.msync){return 0}return stream.stream_ops.msync(stream,buffer,offset,length,mmapFlags)},munmap:stream=>0,ioctl(stream,cmd,arg){if(!stream.stream_ops.ioctl){throw new FS.ErrnoError(59)}return stream.stream_ops.ioctl(stream,cmd,arg)},readFile(path,opts={}){opts.flags=opts.flags||0;opts.encoding=opts.encoding||"binary";if(opts.encoding!=="utf8"&&opts.encoding!=="binary"){throw new Error(`Invalid encoding type "${opts.encoding}"`)}var ret;var stream=FS.open(path,opts.flags);var stat=FS.stat(path);var length=stat.size;var buf=new Uint8Array(length);FS.read(stream,buf,0,length,0);if(opts.encoding==="utf8"){ret=UTF8ArrayToString(buf,0)}else if(opts.encoding==="binary"){ret=buf}FS.close(stream);return ret},writeFile(path,data,opts={}){opts.flags=opts.flags||577;var stream=FS.open(path,opts.flags,opts.mode);if(typeof data=="string"){var buf=new Uint8Array(lengthBytesUTF8(data)+1);var actualNumBytes=stringToUTF8Array(data,buf,0,buf.length);FS.write(stream,buf,0,actualNumBytes,undefined,opts.canOwn)}else if(ArrayBuffer.isView(data)){FS.write(stream,data,0,data.byteLength,undefined,opts.canOwn)}else{throw new Error("Unsupported data type")}FS.close(stream)},cwd:()=>FS.currentPath,chdir(path){var lookup=FS.lookupPath(path,{follow:true});if(lookup.node===null){throw new FS.ErrnoError(44)}if(!FS.isDir(lookup.node.mode)){throw new FS.ErrnoError(54)}var errCode=FS.nodePermissions(lookup.node,"x");if(errCode){throw new FS.ErrnoError(errCode)}FS.currentPath=lookup.path},createDefaultDirectories(){FS.mkdir("/tmp");FS.mkdir("/home");FS.mkdir("/home/web_user")},createDefaultDevices(){FS.mkdir("/dev");FS.registerDevice(FS.makedev(1,3),{read:()=>0,write:(stream,buffer,offset,length,pos)=>length});FS.mkdev("/dev/null",FS.makedev(1,3));TTY.register(FS.makedev(5,0),TTY.default_tty_ops);TTY.register(FS.makedev(6,0),TTY.default_tty1_ops);FS.mkdev("/dev/tty",FS.makedev(5,0));FS.mkdev("/dev/tty1",FS.makedev(6,0));var randomBuffer=new Uint8Array(1024),randomLeft=0;var randomByte=()=>{if(randomLeft===0){randomLeft=randomFill(randomBuffer).byteLength}return randomBuffer[--randomLeft]};FS.createDevice("/dev","random",randomByte);FS.createDevice("/dev","urandom",randomByte);FS.mkdir("/dev/shm");FS.mkdir("/dev/shm/tmp")},createSpecialDirectories(){FS.mkdir("/proc");var proc_self=FS.mkdir("/proc/self");FS.mkdir("/proc/self/fd");FS.mount({mount(){var node=FS.createNode(proc_self,"fd",16384|511,73);node.node_ops={lookup(parent,name){var fd=+name;var stream=FS.getStreamChecked(fd);var ret={parent:null,mount:{mountpoint:"fake"},node_ops:{readlink:()=>stream.path}};ret.parent=ret;return ret}};return node}},{},"/proc/self/fd")},createStandardStreams(){if(Module["stdin"]){FS.createDevice("/dev","stdin",Module["stdin"])}else{FS.symlink("/dev/tty","/dev/stdin")}if(Module["stdout"]){FS.createDevice("/dev","stdout",null,Module["stdout"])}else{FS.symlink("/dev/tty","/dev/stdout")}if(Module["stderr"]){FS.createDevice("/dev","stderr",null,Module["stderr"])}else{FS.symlink("/dev/tty1","/dev/stderr")}var stdin=FS.open("/dev/stdin",0);var stdout=FS.open("/dev/stdout",1);var stderr=FS.open("/dev/stderr",1)},staticInit(){[44].forEach(code=>{FS.genericErrors[code]=new FS.ErrnoError(code);FS.genericErrors[code].stack="<generic error, no stack>"});FS.nameTable=new Array(4096);FS.mount(MEMFS,{},"/");FS.createDefaultDirectories();FS.createDefaultDevices();FS.createSpecialDirectories();FS.filesystems={"MEMFS":MEMFS}},init(input,output,error){FS.init.initialized=true;Module["stdin"]=input||Module["stdin"];Module["stdout"]=output||Module["stdout"];Module["stderr"]=error||Module["stderr"];FS.createStandardStreams()},quit(){FS.init.initialized=false;for(var i=0;i<FS.streams.length;i++){var stream=FS.streams[i];if(!stream){continue}FS.close(stream)}},findObject(path,dontResolveLastLink){var ret=FS.analyzePath(path,dontResolveLastLink);if(!ret.exists){return null}return ret.object},analyzePath(path,dontResolveLastLink){try{var lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});path=lookup.path}catch(e){}var ret={isRoot:false,exists:false,error:0,name:null,path:null,object:null,parentExists:false,parentPath:null,parentObject:null};try{var lookup=FS.lookupPath(path,{parent:true});ret.parentExists=true;ret.parentPath=lookup.path;ret.parentObject=lookup.node;ret.name=PATH.basename(path);lookup=FS.lookupPath(path,{follow:!dontResolveLastLink});ret.exists=true;ret.path=lookup.path;ret.object=lookup.node;ret.name=lookup.node.name;ret.isRoot=lookup.path==="/"}catch(e){ret.error=e.errno}return ret},createPath(parent,path,canRead,canWrite){parent=typeof parent=="string"?parent:FS.getPath(parent);var parts=path.split("/").reverse();while(parts.length){var part=parts.pop();if(!part)continue;var current=PATH.join2(parent,part);try{FS.mkdir(current)}catch(e){}parent=current}return current},createFile(parent,name,properties,canRead,canWrite){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(canRead,canWrite);return FS.create(path,mode)},createDataFile(parent,name,data,canRead,canWrite,canOwn){var path=name;if(parent){parent=typeof parent=="string"?parent:FS.getPath(parent);path=name?PATH.join2(parent,name):parent}var mode=FS_getMode(canRead,canWrite);var node=FS.create(path,mode);if(data){if(typeof data=="string"){var arr=new Array(data.length);for(var i=0,len=data.length;i<len;++i)arr[i]=data.charCodeAt(i);data=arr}FS.chmod(node,mode|146);var stream=FS.open(node,577);FS.write(stream,data,0,data.length,0,canOwn);FS.close(stream);FS.chmod(node,mode)}},createDevice(parent,name,input,output){var path=PATH.join2(typeof parent=="string"?parent:FS.getPath(parent),name);var mode=FS_getMode(!!input,!!output);if(!FS.createDevice.major)FS.createDevice.major=64;var dev=FS.makedev(FS.createDevice.major++,0);FS.registerDevice(dev,{open(stream){stream.seekable=false},close(stream){if(output?.buffer?.length){output(10)}},read(stream,buffer,offset,length,pos){var bytesRead=0;for(var i=0;i<length;i++){var result;try{result=input()}catch(e){throw new FS.ErrnoError(29)}if(result===undefined&&bytesRead===0){throw new FS.ErrnoError(6)}if(result===null||result===undefined)break;bytesRead++;buffer[offset+i]=result}if(bytesRead){stream.node.timestamp=Date.now()}return bytesRead},write(stream,buffer,offset,length,pos){for(var i=0;i<length;i++){try{output(buffer[offset+i])}catch(e){throw new FS.ErrnoError(29)}}if(length){stream.node.timestamp=Date.now()}return i}});return FS.mkdev(path,mode,dev)},forceLoadFile(obj){if(obj.isDevice||obj.isFolder||obj.link||obj.contents)return true;if(typeof XMLHttpRequest!="undefined"){throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.")}else if(read_){try{obj.contents=intArrayFromString(read_(obj.url),true);obj.usedBytes=obj.contents.length}catch(e){throw new FS.ErrnoError(29)}}else{throw new Error("Cannot load without read() or XMLHttpRequest.")}},createLazyFile(parent,name,url,canRead,canWrite){function LazyUint8Array(){this.lengthKnown=false;this.chunks=[]}LazyUint8Array.prototype.get=function LazyUint8Array_get(idx){if(idx>this.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=(from,to)=>{if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}return intArrayFromString(xhr.responseText||"",true)};var lazyArray=this;lazyArray.setDataGetter(chunkNum=>{var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]=="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]=="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(key=>{var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){FS.forceLoadFile(node);return fn.apply(null,arguments)}});function writeChunks(stream,buffer,offset,length,position){var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i<size;i++){buffer[offset+i]=contents[position+i]}}else{for(var i=0;i<size;i++){buffer[offset+i]=contents.get(position+i)}}return size}stream_ops.read=(stream,buffer,offset,length,position)=>{FS.forceLoadFile(node);return writeChunks(stream,buffer,offset,length,position)};stream_ops.mmap=(stream,length,position,prot,flags)=>{FS.forceLoadFile(node);var ptr=mmapAlloc(length);if(!ptr){throw new FS.ErrnoError(48)}writeChunks(stream,HEAP8,ptr,length,position);return{ptr:ptr,allocated:true}};node.stream_ops=stream_ops;return node}};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var SYSCALLS={DEFAULT_POLLMASK:5,calculateAt(dirfd,path,allowEmpty){if(PATH.isAbs(path)){return path}var dir;if(dirfd===-100){dir=FS.cwd()}else{var dirstream=SYSCALLS.getStreamFromFD(dirfd);dir=dirstream.path}if(path.length==0){if(!allowEmpty){throw new FS.ErrnoError(44)}return dir}return PATH.join2(dir,path)},doStat(func,path,buf){var stat=func(path);HEAP32[buf>>2]=stat.dev;HEAP32[buf+4>>2]=stat.mode;HEAPU32[buf+8>>2]=stat.nlink;HEAP32[buf+12>>2]=stat.uid;HEAP32[buf+16>>2]=stat.gid;HEAP32[buf+20>>2]=stat.rdev;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+24>>2]=tempI64[0],HEAP32[buf+28>>2]=tempI64[1];HEAP32[buf+32>>2]=4096;HEAP32[buf+36>>2]=stat.blocks;var atime=stat.atime.getTime();var mtime=stat.mtime.getTime();var ctime=stat.ctime.getTime();tempI64=[Math.floor(atime/1e3)>>>0,(tempDouble=Math.floor(atime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAPU32[buf+48>>2]=atime%1e3*1e3;tempI64=[Math.floor(mtime/1e3)>>>0,(tempDouble=Math.floor(mtime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+56>>2]=tempI64[0],HEAP32[buf+60>>2]=tempI64[1];HEAPU32[buf+64>>2]=mtime%1e3*1e3;tempI64=[Math.floor(ctime/1e3)>>>0,(tempDouble=Math.floor(ctime/1e3),+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+72>>2]=tempI64[0],HEAP32[buf+76>>2]=tempI64[1];HEAPU32[buf+80>>2]=ctime%1e3*1e3;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+88>>2]=tempI64[0],HEAP32[buf+92>>2]=tempI64[1];return 0},doMsync(addr,stream,len,flags,offset){if(!FS.isFile(stream.node.mode)){throw new FS.ErrnoError(43)}if(flags&2){return 0}var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},varargs:undefined,get(){var ret=HEAP32[+SYSCALLS.varargs>>2];SYSCALLS.varargs+=4;return ret},getp(){return SYSCALLS.get()},getStr(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD(fd){var stream=FS.getStreamChecked(fd);return stream}};function ___syscall__newselect(nfds,readfds,writefds,exceptfds,timeout){try{var total=0;var srcReadLow=readfds?HEAP32[readfds>>2]:0,srcReadHigh=readfds?HEAP32[readfds+4>>2]:0;var srcWriteLow=writefds?HEAP32[writefds>>2]:0,srcWriteHigh=writefds?HEAP32[writefds+4>>2]:0;var srcExceptLow=exceptfds?HEAP32[exceptfds>>2]:0,srcExceptHigh=exceptfds?HEAP32[exceptfds+4>>2]:0;var dstReadLow=0,dstReadHigh=0;var dstWriteLow=0,dstWriteHigh=0;var dstExceptLow=0,dstExceptHigh=0;var allLow=(readfds?HEAP32[readfds>>2]:0)|(writefds?HEAP32[writefds>>2]:0)|(exceptfds?HEAP32[exceptfds>>2]:0);var allHigh=(readfds?HEAP32[readfds+4>>2]:0)|(writefds?HEAP32[writefds+4>>2]:0)|(exceptfds?HEAP32[exceptfds+4>>2]:0);var check=function(fd,low,high,val){return fd<32?low&val:high&val};for(var fd=0;fd<nfds;fd++){var mask=1<<fd%32;if(!check(fd,allLow,allHigh,mask)){continue}var stream=SYSCALLS.getStreamFromFD(fd);var flags=SYSCALLS.DEFAULT_POLLMASK;if(stream.stream_ops.poll){var timeoutInMillis=-1;if(timeout){var tv_sec=readfds?HEAP32[timeout>>2]:0,tv_usec=readfds?HEAP32[timeout+4>>2]:0;timeoutInMillis=(tv_sec+tv_usec/1e6)*1e3}flags=stream.stream_ops.poll(stream,timeoutInMillis)}if(flags&1&&check(fd,srcReadLow,srcReadHigh,mask)){fd<32?dstReadLow=dstReadLow|mask:dstReadHigh=dstReadHigh|mask;total++}if(flags&4&&check(fd,srcWriteLow,srcWriteHigh,mask)){fd<32?dstWriteLow=dstWriteLow|mask:dstWriteHigh=dstWriteHigh|mask;total++}if(flags&2&&check(fd,srcExceptLow,srcExceptHigh,mask)){fd<32?dstExceptLow=dstExceptLow|mask:dstExceptHigh=dstExceptHigh|mask;total++}}if(readfds){HEAP32[readfds>>2]=dstReadLow;HEAP32[readfds+4>>2]=dstReadHigh}if(writefds){HEAP32[writefds>>2]=dstWriteLow;HEAP32[writefds+4>>2]=dstWriteHigh}if(exceptfds){HEAP32[exceptfds>>2]=dstExceptLow;HEAP32[exceptfds+4>>2]=dstExceptHigh}return total}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}while(FS.streams[arg]){arg++}var newStream;newStream=FS.createStream(stream,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 12:{var arg=SYSCALLS.getp();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 13:case 14:return 0}return-28}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:{if(!stream.tty)return-59;return 0}case 21505:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcgets){var termios=stream.tty.ops.ioctl_tcgets(stream);var argp=SYSCALLS.getp();HEAP32[argp>>2]=termios.c_iflag||0;HEAP32[argp+4>>2]=termios.c_oflag||0;HEAP32[argp+8>>2]=termios.c_cflag||0;HEAP32[argp+12>>2]=termios.c_lflag||0;for(var i=0;i<32;i++){HEAP8[argp+i+17>>0]=termios.c_cc[i]||0}return 0}return 0}case 21510:case 21511:case 21512:{if(!stream.tty)return-59;return 0}case 21506:case 21507:case 21508:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tcsets){var argp=SYSCALLS.getp();var c_iflag=HEAP32[argp>>2];var c_oflag=HEAP32[argp+4>>2];var c_cflag=HEAP32[argp+8>>2];var c_lflag=HEAP32[argp+12>>2];var c_cc=[];for(var i=0;i<32;i++){c_cc.push(HEAP8[argp+i+17>>0])}return stream.tty.ops.ioctl_tcsets(stream.tty,op,{c_iflag:c_iflag,c_oflag:c_oflag,c_cflag:c_cflag,c_lflag:c_lflag,c_cc:c_cc})}return 0}case 21519:{if(!stream.tty)return-59;var argp=SYSCALLS.getp();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.getp();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;if(stream.tty.ops.ioctl_tiocgwinsz){var winsize=stream.tty.ops.ioctl_tiocgwinsz(stream.tty);var argp=SYSCALLS.getp();HEAP16[argp>>1]=winsize[0];HEAP16[argp+2>>1]=winsize[1]}return 0}case 21524:{if(!stream.tty)return-59;return 0}case 21515:{if(!stream.tty)return-59;return 0}default:return-28}}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_mkdirat(dirfd,path,mode){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_newfstatat(dirfd,path,buf,flags){try{path=SYSCALLS.getStr(path);var nofollow=flags&256;var allowEmpty=flags&4096;flags=flags&~6400;path=SYSCALLS.calculateAt(dirfd,path,allowEmpty);return SYSCALLS.doStat(nofollow?FS.lstat:FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_openat(dirfd,path,flags,varargs){SYSCALLS.varargs=varargs;try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);var mode=varargs?SYSCALLS.get():0;return FS.open(path,flags,mode).fd}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);function ___syscall_readlinkat(dirfd,path,buf,bufsize){try{path=SYSCALLS.getStr(path);path=SYSCALLS.calculateAt(dirfd,path);if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function ___syscall_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var __emscripten_fs_load_embedded_files=ptr=>{do{var name_addr=HEAPU32[ptr>>2];ptr+=4;var len=HEAPU32[ptr>>2];ptr+=4;var content=HEAPU32[ptr>>2];ptr+=4;var name=UTF8ToString(name_addr);FS.createPath("/",PATH.dirname(name),true,true);FS.createDataFile(name,null,HEAP8.subarray(content,content+len),true,true,true)}while(HEAPU32[ptr>>2])};var convertI32PairToI53Checked=(lo,hi)=>hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN;function __mmap_js(len,prot,flags,fd,offset_low,offset_high,allocated,addr){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);var res=FS.mmap(stream,len,offset,prot,flags);var ptr=res.ptr;HEAP32[allocated>>2]=res.allocated;HEAPU32[addr>>2]=ptr;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}function __munmap_js(addr,len,prot,flags,fd,offset_low,offset_high){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);if(prot&2){SYSCALLS.doMsync(addr,stream,len,flags,offset)}FS.munmap(stream)}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return-e.errno}}var _abort=()=>{abort("")};var readEmAsmArgsArray=[];var readEmAsmArgs=(sigPtr,buf)=>{readEmAsmArgsArray.length=0;var ch;while(ch=HEAPU8[sigPtr++]){var wide=ch!=105;wide&=ch!=112;buf+=wide&&buf%8?4:0;readEmAsmArgsArray.push(ch==112?HEAPU32[buf>>2]:ch==105?HEAP32[buf>>2]:HEAPF64[buf>>3]);buf+=wide?8:4}return readEmAsmArgsArray};var runEmAsmFunction=(code,sigPtr,argbuf)=>{var args=readEmAsmArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)};var _emscripten_asm_const_int=(code,sigPtr,argbuf)=>runEmAsmFunction(code,sigPtr,argbuf);var _emscripten_date_now=()=>Date.now();var withStackSave=f=>{var stack=stackSave();var ret=f();stackRestore(stack);return ret};var JSEvents={removeAllEventListeners(){while(JSEvents.eventHandlers.length){JSEvents._removeHandler(JSEvents.eventHandlers.length-1)}JSEvents.deferredCalls=[]},inEventHandler:0,deferredCalls:[],deferCall(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort((x,y)=>x.precedence<y.precedence)},removeDeferredCalls(targetFunction){for(var i=0;i<JSEvents.deferredCalls.length;++i){if(JSEvents.deferredCalls[i].targetFunction==targetFunction){JSEvents.deferredCalls.splice(i,1);--i}}},canPerformEventHandlerRequests(){if(navigator.userActivation){return navigator.userActivation.isActive}return JSEvents.inEventHandler&&JSEvents.currentEventHandler.allowsDeferredCalls},runDeferredCalls(){if(!JSEvents.canPerformEventHandlerRequests()){return}for(var i=0;i<JSEvents.deferredCalls.length;++i){var call=JSEvents.deferredCalls[i];JSEvents.deferredCalls.splice(i,1);--i;call.targetFunction.apply(null,call.argsList)}},eventHandlers:[],removeAllHandlersOnTarget:(target,eventTypeString)=>{for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==target&&(!eventTypeString||eventTypeString==JSEvents.eventHandlers[i].eventTypeString)){JSEvents._removeHandler(i--)}}},_removeHandler(i){var h=JSEvents.eventHandlers[i];h.target.removeEventListener(h.eventTypeString,h.eventListenerFunc,h.useCapture);JSEvents.eventHandlers.splice(i,1)},registerOrRemoveHandler(eventHandler){if(!eventHandler.target){return-4}if(eventHandler.callbackfunc){eventHandler.eventListenerFunc=function(event){++JSEvents.inEventHandler;JSEvents.currentEventHandler=eventHandler;JSEvents.runDeferredCalls();eventHandler.handlerFunc(event);JSEvents.runDeferredCalls();--JSEvents.inEventHandler};eventHandler.target.addEventListener(eventHandler.eventTypeString,eventHandler.eventListenerFunc,eventHandler.useCapture);JSEvents.eventHandlers.push(eventHandler)}else{for(var i=0;i<JSEvents.eventHandlers.length;++i){if(JSEvents.eventHandlers[i].target==eventHandler.target&&JSEvents.eventHandlers[i].eventTypeString==eventHandler.eventTypeString){JSEvents._removeHandler(i--)}}}return 0},getNodeNameForTarget(target){if(!target)return"";if(target==window)return"#window";if(target==screen)return"#screen";return target?.nodeName||""},fullscreenEnabled(){return document.fullscreenEnabled||document.webkitFullscreenEnabled}};var maybeCStringToJsString=cString=>cString>2?UTF8ToString(cString):cString;var specialHTMLTargets=[0,document,window];var findEventTarget=target=>{target=maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||document.querySelector(target);return domElement};var findCanvasEventTarget=findEventTarget;var _emscripten_get_canvas_element_size=(target,width,height)=>{var canvas=findCanvasEventTarget(target);if(!canvas)return-4;HEAP32[width>>2]=canvas.width;HEAP32[height>>2]=canvas.height};var _emscripten_get_device_pixel_ratio=()=>devicePixelRatio;var getBoundingClientRect=e=>specialHTMLTargets.indexOf(e)<0?e.getBoundingClientRect():{"left":0,"top":0};var _emscripten_get_element_css_size=(target,width,height)=>{target=findEventTarget(target);if(!target)return-4;var rect=getBoundingClientRect(target);HEAPF64[width>>3]=rect.width;HEAPF64[height>>3]=rect.height;return 0};var fillGamepadEventData=(eventStruct,e)=>{HEAPF64[eventStruct>>3]=e.timestamp;for(var i=0;i<e.axes.length;++i){HEAPF64[eventStruct+i*8+16>>3]=e.axes[i]}for(var i=0;i<e.buttons.length;++i){if(typeof e.buttons[i]=="object"){HEAPF64[eventStruct+i*8+528>>3]=e.buttons[i].value}else{HEAPF64[eventStruct+i*8+528>>3]=e.buttons[i]}}for(var i=0;i<e.buttons.length;++i){if(typeof e.buttons[i]=="object"){HEAP32[eventStruct+i*4+1040>>2]=e.buttons[i].pressed}else{HEAP32[eventStruct+i*4+1040>>2]=e.buttons[i]==1}}HEAP32[eventStruct+1296>>2]=e.connected;HEAP32[eventStruct+1300>>2]=e.index;HEAP32[eventStruct+8>>2]=e.axes.length;HEAP32[eventStruct+12>>2]=e.buttons.length;stringToUTF8(e.id,eventStruct+1304,64);stringToUTF8(e.mapping,eventStruct+1368,64)};var _emscripten_get_gamepad_status=(index,gamepadState)=>{if(index<0||index>=JSEvents.lastGamepadState.length)return-5;if(!JSEvents.lastGamepadState[index])return-7;fillGamepadEventData(gamepadState,JSEvents.lastGamepadState[index]);return 0};var getHeapMax=()=>HEAPU8.length;var _emscripten_get_heap_max=()=>getHeapMax();var _emscripten_get_now;_emscripten_get_now=()=>performance.now();var _emscripten_get_num_gamepads=()=>JSEvents.lastGamepadState.length;var _emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var _emscripten_request_animation_frame_loop=(cb,userData)=>{function tick(timeStamp){if(getWasmTableEntry(cb)(timeStamp,userData)){requestAnimationFrame(tick)}}return requestAnimationFrame(tick)};var abortOnCannotGrowMemory=requestedSize=>{abort("OOM")};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;abortOnCannotGrowMemory(requestedSize)};var _emscripten_sample_gamepad_data=()=>{try{if(navigator.getGamepads)return(JSEvents.lastGamepadState=navigator.getGamepads())?0:-1}catch(e){navigator.getGamepads=null}return-1};var registerFocusEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.focusEvent)JSEvents.focusEvent=_malloc(256);var focusEventHandlerFunc=(e=event)=>{var nodeName=JSEvents.getNodeNameForTarget(e.target);var id=e.target.id?e.target.id:"";var focusEvent=JSEvents.focusEvent;stringToUTF8(nodeName,focusEvent+0,128);stringToUTF8(id,focusEvent+128,128);if(getWasmTableEntry(callbackfunc)(eventTypeId,focusEvent,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:focusEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_blur_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerFocusEventCallback(target,userData,useCapture,callbackfunc,12,"blur",targetThread);var _emscripten_set_canvas_element_size=(target,width,height)=>{var canvas=findCanvasEventTarget(target);if(!canvas)return-4;canvas.width=width;canvas.height=height;return 0};var _emscripten_set_focus_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerFocusEventCallback(target,userData,useCapture,callbackfunc,13,"focus",targetThread);var registerGamepadEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.gamepadEvent)JSEvents.gamepadEvent=_malloc(1432);var gamepadEventHandlerFunc=(e=event)=>{var gamepadEvent=JSEvents.gamepadEvent;fillGamepadEventData(gamepadEvent,e["gamepad"]);if(getWasmTableEntry(callbackfunc)(eventTypeId,gamepadEvent,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:gamepadEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_gamepadconnected_callback_on_thread=(userData,useCapture,callbackfunc,targetThread)=>{if(_emscripten_sample_gamepad_data())return-1;return registerGamepadEventCallback(2,userData,useCapture,callbackfunc,26,"gamepadconnected",targetThread)};var registerKeyEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.keyEvent)JSEvents.keyEvent=_malloc(176);var keyEventHandlerFunc=e=>{var keyEventData=JSEvents.keyEvent;HEAPF64[keyEventData>>3]=e.timeStamp;var idx=keyEventData>>2;HEAP32[idx+2]=e.location;HEAP32[idx+3]=e.ctrlKey;HEAP32[idx+4]=e.shiftKey;HEAP32[idx+5]=e.altKey;HEAP32[idx+6]=e.metaKey;HEAP32[idx+7]=e.repeat;HEAP32[idx+8]=e.charCode;HEAP32[idx+9]=e.keyCode;HEAP32[idx+10]=e.which;stringToUTF8(e.key||"",keyEventData+44,32);stringToUTF8(e.code||"",keyEventData+76,32);stringToUTF8(e.char||"",keyEventData+108,32);stringToUTF8(e.locale||"",keyEventData+140,32);if(getWasmTableEntry(callbackfunc)(eventTypeId,keyEventData,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:keyEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_keydown_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerKeyEventCallback(target,userData,useCapture,callbackfunc,2,"keydown",targetThread);var _emscripten_set_keypress_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerKeyEventCallback(target,userData,useCapture,callbackfunc,1,"keypress",targetThread);var _emscripten_set_keyup_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerKeyEventCallback(target,userData,useCapture,callbackfunc,3,"keyup",targetThread);var fillMouseEventData=(eventStruct,e,target)=>{HEAPF64[eventStruct>>3]=e.timeStamp;var idx=eventStruct>>2;HEAP32[idx+2]=e.screenX;HEAP32[idx+3]=e.screenY;HEAP32[idx+4]=e.clientX;HEAP32[idx+5]=e.clientY;HEAP32[idx+6]=e.ctrlKey;HEAP32[idx+7]=e.shiftKey;HEAP32[idx+8]=e.altKey;HEAP32[idx+9]=e.metaKey;HEAP16[idx*2+20]=e.button;HEAP16[idx*2+21]=e.buttons;HEAP32[idx+11]=e["movementX"];HEAP32[idx+12]=e["movementY"];var rect=getBoundingClientRect(target);HEAP32[idx+13]=e.clientX-rect.left;HEAP32[idx+14]=e.clientY-rect.top};var registerMouseEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.mouseEvent)JSEvents.mouseEvent=_malloc(72);target=findEventTarget(target);var mouseEventHandlerFunc=(e=event)=>{fillMouseEventData(JSEvents.mouseEvent,e,target);if(getWasmTableEntry(callbackfunc)(eventTypeId,JSEvents.mouseEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString!="mousemove"&&eventTypeString!="mouseenter"&&eventTypeString!="mouseleave",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:mouseEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_mousedown_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerMouseEventCallback(target,userData,useCapture,callbackfunc,5,"mousedown",targetThread);var _emscripten_set_mouseenter_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerMouseEventCallback(target,userData,useCapture,callbackfunc,33,"mouseenter",targetThread);var _emscripten_set_mouseleave_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerMouseEventCallback(target,userData,useCapture,callbackfunc,34,"mouseleave",targetThread);var _emscripten_set_mousemove_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerMouseEventCallback(target,userData,useCapture,callbackfunc,8,"mousemove",targetThread);var _emscripten_set_mouseup_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerMouseEventCallback(target,userData,useCapture,callbackfunc,6,"mouseup",targetThread);var fillPointerlockChangeEventData=eventStruct=>{var pointerLockElement=document.pointerLockElement||document.mozPointerLockElement||document.webkitPointerLockElement||document.msPointerLockElement;var isPointerlocked=!!pointerLockElement;HEAP32[eventStruct>>2]=isPointerlocked;var nodeName=JSEvents.getNodeNameForTarget(pointerLockElement);var id=pointerLockElement?.id||"";stringToUTF8(nodeName,eventStruct+4,128);stringToUTF8(id,eventStruct+132,128)};var registerPointerlockChangeEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.pointerlockChangeEvent)JSEvents.pointerlockChangeEvent=_malloc(260);var pointerlockChangeEventHandlerFunc=(e=event)=>{var pointerlockChangeEvent=JSEvents.pointerlockChangeEvent;fillPointerlockChangeEventData(pointerlockChangeEvent);if(getWasmTableEntry(callbackfunc)(eventTypeId,pointerlockChangeEvent,userData))e.preventDefault()};var eventHandler={target:target,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:pointerlockChangeEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_pointerlockchange_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>{if(!document||!document.body||!document.body.requestPointerLock&&!document.body.mozRequestPointerLock&&!document.body.webkitRequestPointerLock&&!document.body.msRequestPointerLock){return-1}target=findEventTarget(target);if(!target)return-4;registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"mozpointerlockchange",targetThread);registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"webkitpointerlockchange",targetThread);registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"mspointerlockchange",targetThread);return registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"pointerlockchange",targetThread)};var registerPointerlockErrorEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{var pointerlockErrorEventHandlerFunc=(e=event)=>{if(getWasmTableEntry(callbackfunc)(eventTypeId,0,userData))e.preventDefault()};var eventHandler={target:target,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:pointerlockErrorEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_pointerlockerror_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>{if(!document||!document.body.requestPointerLock&&!document.body.mozRequestPointerLock&&!document.body.webkitRequestPointerLock&&!document.body.msRequestPointerLock){return-1}target=findEventTarget(target);if(!target)return-4;registerPointerlockErrorEventCallback(target,userData,useCapture,callbackfunc,38,"mozpointerlockerror",targetThread);registerPointerlockErrorEventCallback(target,userData,useCapture,callbackfunc,38,"webkitpointerlockerror",targetThread);registerPointerlockErrorEventCallback(target,userData,useCapture,callbackfunc,38,"mspointerlockerror",targetThread);return registerPointerlockErrorEventCallback(target,userData,useCapture,callbackfunc,38,"pointerlockerror",targetThread)};var registerUiEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.uiEvent)JSEvents.uiEvent=_malloc(36);target=findEventTarget(target);var uiEventHandlerFunc=(e=event)=>{if(e.target!=target){return}var b=document.body;if(!b){return}var uiEvent=JSEvents.uiEvent;HEAP32[uiEvent>>2]=e.detail;HEAP32[uiEvent+4>>2]=b.clientWidth;HEAP32[uiEvent+8>>2]=b.clientHeight;HEAP32[uiEvent+12>>2]=innerWidth;HEAP32[uiEvent+16>>2]=innerHeight;HEAP32[uiEvent+20>>2]=outerWidth;HEAP32[uiEvent+24>>2]=outerHeight;HEAP32[uiEvent+28>>2]=pageXOffset;HEAP32[uiEvent+32>>2]=pageYOffset;if(getWasmTableEntry(callbackfunc)(eventTypeId,uiEvent,userData))e.preventDefault()};var eventHandler={target:target,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:uiEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_resize_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerUiEventCallback(target,userData,useCapture,callbackfunc,10,"resize",targetThread);var registerTouchEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.touchEvent)JSEvents.touchEvent=_malloc(1696);target=findEventTarget(target);var touchEventHandlerFunc=e=>{var t,touches={},et=e.touches;for(var i=0;i<et.length;++i){t=et[i];t.isChanged=t.onTarget=0;touches[t.identifier]=t}for(var i=0;i<e.changedTouches.length;++i){t=e.changedTouches[i];t.isChanged=1;touches[t.identifier]=t}for(var i=0;i<e.targetTouches.length;++i){touches[e.targetTouches[i].identifier].onTarget=1}var touchEvent=JSEvents.touchEvent;HEAPF64[touchEvent>>3]=e.timeStamp;var idx=touchEvent>>2;HEAP32[idx+3]=e.ctrlKey;HEAP32[idx+4]=e.shiftKey;HEAP32[idx+5]=e.altKey;HEAP32[idx+6]=e.metaKey;idx+=7;var targetRect=getBoundingClientRect(target);var numTouches=0;for(var i in touches){t=touches[i];HEAP32[idx+0]=t.identifier;HEAP32[idx+1]=t.screenX;HEAP32[idx+2]=t.screenY;HEAP32[idx+3]=t.clientX;HEAP32[idx+4]=t.clientY;HEAP32[idx+5]=t.pageX;HEAP32[idx+6]=t.pageY;HEAP32[idx+7]=t.isChanged;HEAP32[idx+8]=t.onTarget;HEAP32[idx+9]=t.clientX-targetRect.left;HEAP32[idx+10]=t.clientY-targetRect.top;idx+=13;if(++numTouches>31){break}}HEAP32[touchEvent+8>>2]=numTouches;if(getWasmTableEntry(callbackfunc)(eventTypeId,touchEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString=="touchstart"||eventTypeString=="touchend",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:touchEventHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_touchcancel_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerTouchEventCallback(target,userData,useCapture,callbackfunc,25,"touchcancel",targetThread);var _emscripten_set_touchend_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerTouchEventCallback(target,userData,useCapture,callbackfunc,23,"touchend",targetThread);var _emscripten_set_touchmove_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerTouchEventCallback(target,userData,useCapture,callbackfunc,24,"touchmove",targetThread);var _emscripten_set_touchstart_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>registerTouchEventCallback(target,userData,useCapture,callbackfunc,22,"touchstart",targetThread);var webgl_enable_ANGLE_instanced_arrays=ctx=>{var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=(index,divisor)=>ext["vertexAttribDivisorANGLE"](index,divisor);ctx["drawArraysInstanced"]=(mode,first,count,primcount)=>ext["drawArraysInstancedANGLE"](mode,first,count,primcount);ctx["drawElementsInstanced"]=(mode,count,type,indices,primcount)=>ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount);return 1}};var webgl_enable_OES_vertex_array_object=ctx=>{var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=()=>ext["createVertexArrayOES"]();ctx["deleteVertexArray"]=vao=>ext["deleteVertexArrayOES"](vao);ctx["bindVertexArray"]=vao=>ext["bindVertexArrayOES"](vao);ctx["isVertexArray"]=vao=>ext["isVertexArrayOES"](vao);return 1}};var webgl_enable_WEBGL_draw_buffers=ctx=>{var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=(n,bufs)=>ext["drawBuffersWEBGL"](n,bufs);return 1}};var webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance=ctx=>!!(ctx.dibvbi=ctx.getExtension("WEBGL_draw_instanced_base_vertex_base_instance"));var webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance=ctx=>!!(ctx.mdibvbi=ctx.getExtension("WEBGL_multi_draw_instanced_base_vertex_base_instance"));var webgl_enable_WEBGL_multi_draw=ctx=>!!(ctx.multiDrawWebgl=ctx.getExtension("WEBGL_multi_draw"));var getEmscriptenSupportedExtensions=function(ctx){var supportedExtensions=["ANGLE_instanced_arrays","EXT_blend_minmax","EXT_disjoint_timer_query","EXT_frag_depth","EXT_shader_texture_lod","EXT_sRGB","OES_element_index_uint","OES_fbo_render_mipmap","OES_standard_derivatives","OES_texture_float","OES_texture_half_float","OES_texture_half_float_linear","OES_vertex_array_object","WEBGL_color_buffer_float","WEBGL_depth_texture","WEBGL_draw_buffers","EXT_color_buffer_float","EXT_disjoint_timer_query_webgl2","EXT_texture_norm16","WEBGL_clip_cull_distance","EXT_color_buffer_half_float","EXT_float_blend","EXT_texture_compression_bptc","EXT_texture_compression_rgtc","EXT_texture_filter_anisotropic","KHR_parallel_shader_compile","OES_texture_float_linear","WEBGL_compressed_texture_s3tc","WEBGL_compressed_texture_s3tc_srgb","WEBGL_debug_renderer_info","WEBGL_debug_shaders","WEBGL_lose_context","WEBGL_multi_draw"];return(ctx.getSupportedExtensions()||[]).filter(ext=>supportedExtensions.includes(ext))};var GL={counter:1,buffers:[],mappedBuffers:{},programs:[],framebuffers:[],renderbuffers:[],textures:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},queries:[],samplers:[],transformFeedbacks:[],syncs:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],stringCache:{},stringiCache:{},unpackAlignment:4,recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:table=>{var ret=GL.counter++;for(var i=table.length;i<ret;i++){table[i]=null}return ret},MAX_TEMP_BUFFER_SIZE:2097152,numTempVertexBuffersPerSize:64,log2ceilLookup:i=>32-Math.clz32(i===0?0:i-1),generateTempBuffers:(quads,context)=>{var largestIndex=GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);context.tempVertexBufferCounters1=[];context.tempVertexBufferCounters2=[];context.tempVertexBufferCounters1.length=context.tempVertexBufferCounters2.length=largestIndex+1;context.tempVertexBuffers1=[];context.tempVertexBuffers2=[];context.tempVertexBuffers1.length=context.tempVertexBuffers2.length=largestIndex+1;context.tempIndexBuffers=[];context.tempIndexBuffers.length=largestIndex+1;for(var i=0;i<=largestIndex;++i){context.tempIndexBuffers[i]=null;context.tempVertexBufferCounters1[i]=context.tempVertexBufferCounters2[i]=0;var ringbufferLength=GL.numTempVertexBuffersPerSize;context.tempVertexBuffers1[i]=[];context.tempVertexBuffers2[i]=[];var ringbuffer1=context.tempVertexBuffers1[i];var ringbuffer2=context.tempVertexBuffers2[i];ringbuffer1.length=ringbuffer2.length=ringbufferLength;for(var j=0;j<ringbufferLength;++j){ringbuffer1[j]=ringbuffer2[j]=null}}if(quads){context.tempQuadIndexBuffer=GLctx.createBuffer();context.GLctx.bindBuffer(34963,context.tempQuadIndexBuffer);var numIndexes=GL.MAX_TEMP_BUFFER_SIZE>>1;var quadIndexes=new Uint16Array(numIndexes);var i=0,v=0;while(1){quadIndexes[i++]=v;if(i>=numIndexes)break;quadIndexes[i++]=v+1;if(i>=numIndexes)break;quadIndexes[i++]=v+2;if(i>=numIndexes)break;quadIndexes[i++]=v;if(i>=numIndexes)break;quadIndexes[i++]=v+2;if(i>=numIndexes)break;quadIndexes[i++]=v+3;if(i>=numIndexes)break;v+=4}context.GLctx.bufferData(34963,quadIndexes,35044);context.GLctx.bindBuffer(34963,null)}},getTempVertexBuffer:function getTempVertexBuffer(sizeBytes){var idx=GL.log2ceilLookup(sizeBytes);var ringbuffer=GL.currentContext.tempVertexBuffers1[idx];var nextFreeBufferIndex=GL.currentContext.tempVertexBufferCounters1[idx];GL.currentContext.tempVertexBufferCounters1[idx]=GL.currentContext.tempVertexBufferCounters1[idx]+1&GL.numTempVertexBuffersPerSize-1;var vbo=ringbuffer[nextFreeBufferIndex];if(vbo){return vbo}var prevVBO=GLctx.getParameter(34964);ringbuffer[nextFreeBufferIndex]=GLctx.createBuffer();GLctx.bindBuffer(34962,ringbuffer[nextFreeBufferIndex]);GLctx.bufferData(34962,1<<idx,35048);GLctx.bindBuffer(34962,prevVBO);return ringbuffer[nextFreeBufferIndex]},getTempIndexBuffer:function getTempIndexBuffer(sizeBytes){var idx=GL.log2ceilLookup(sizeBytes);var ibo=GL.currentContext.tempIndexBuffers[idx];if(ibo){return ibo}var prevIBO=GLctx.getParameter(34965);GL.currentContext.tempIndexBuffers[idx]=GLctx.createBuffer();GLctx.bindBuffer(34963,GL.currentContext.tempIndexBuffers[idx]);GLctx.bufferData(34963,1<<idx,35048);GLctx.bindBuffer(34963,prevIBO);return GL.currentContext.tempIndexBuffers[idx]},newRenderingFrameStarted:function newRenderingFrameStarted(){if(!GL.currentContext){return}var vb=GL.currentContext.tempVertexBuffers1;GL.currentContext.tempVertexBuffers1=GL.currentContext.tempVertexBuffers2;GL.currentContext.tempVertexBuffers2=vb;vb=GL.currentContext.tempVertexBufferCounters1;GL.currentContext.tempVertexBufferCounters1=GL.currentContext.tempVertexBufferCounters2;GL.currentContext.tempVertexBufferCounters2=vb;var largestIndex=GL.log2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);for(var i=0;i<=largestIndex;++i){GL.currentContext.tempVertexBufferCounters1[i]=0}},getSource:(shader,count,string,length)=>{var source="";for(var i=0;i<count;++i){var len=length?HEAPU32[length+i*4>>2]:undefined;source+=UTF8ToString(HEAPU32[string+i*4>>2],len)}return source},calcBufLength:function calcBufLength(size,type,stride,count){if(stride>0){return count*stride}var typeSize=GL.byteSizeByType[type-GL.byteSizeByTypeRoot];return size*typeSize*count},usedTempBuffers:[],preDrawHandleClientVertexAttribBindings:function preDrawHandleClientVertexAttribBindings(count){GL.resetBufferBinding=false;for(var i=0;i<GL.currentContext.maxVertexAttribs;++i){var cb=GL.currentContext.clientBuffers[i];if(!cb.clientside||!cb.enabled)continue;GL.resetBufferBinding=true;var size=GL.calcBufLength(cb.size,cb.type,cb.stride,count);var buf=GL.getTempVertexBuffer(size);GLctx.bindBuffer(34962,buf);GLctx.bufferSubData(34962,0,HEAPU8.subarray(cb.ptr,cb.ptr+size));cb.vertexAttribPointerAdaptor.call(GLctx,i,cb.size,cb.type,cb.normalized,cb.stride,0)}},postDrawHandleClientVertexAttribBindings:function postDrawHandleClientVertexAttribBindings(){if(GL.resetBufferBinding){GLctx.bindBuffer(34962,GL.buffers[GLctx.currentArrayBufferBinding])}},createContext:(canvas,webGLContextAttributes)=>{if(!canvas.getContextSafariWebGL2Fixed){canvas.getContextSafariWebGL2Fixed=canvas.getContext;function fixedGetContext(ver,attrs){var gl=canvas.getContextSafariWebGL2Fixed(ver,attrs);return ver=="webgl"==gl instanceof WebGLRenderingContext?gl:null}canvas.getContext=fixedGetContext}var ctx=webGLContextAttributes.majorVersion>1?canvas.getContext("webgl2",webGLContextAttributes):canvas.getContext("webgl",webGLContextAttributes);if(!ctx)return 0;var handle=GL.registerContext(ctx,webGLContextAttributes);return handle},registerContext:(ctx,webGLContextAttributes)=>{var handle=GL.getNewId(GL.contexts);var context={handle:handle,attributes:webGLContextAttributes,version:webGLContextAttributes.majorVersion,GLctx:ctx};if(ctx.canvas)ctx.canvas.GLctxObject=context;GL.contexts[handle]=context;if(typeof webGLContextAttributes.enableExtensionsByDefault=="undefined"||webGLContextAttributes.enableExtensionsByDefault){GL.initExtensions(context)}context.maxVertexAttribs=context.GLctx.getParameter(34921);context.clientBuffers=[];for(var i=0;i<context.maxVertexAttribs;i++){context.clientBuffers[i]={enabled:false,clientside:false,size:0,type:0,normalized:0,stride:0,ptr:0,vertexAttribPointerAdaptor:null}}GL.generateTempBuffers(false,context);return handle},makeContextCurrent:contextHandle=>{GL.currentContext=GL.contexts[contextHandle];Module.ctx=GLctx=GL.currentContext?.GLctx;return!(contextHandle&&!GLctx)},getContext:contextHandle=>GL.contexts[contextHandle],deleteContext:contextHandle=>{if(GL.currentContext===GL.contexts[contextHandle]){GL.currentContext=null}if(typeof JSEvents=="object"){JSEvents.removeAllHandlersOnTarget(GL.contexts[contextHandle].GLctx.canvas)}if(GL.contexts[contextHandle]&&GL.contexts[contextHandle].GLctx.canvas){GL.contexts[contextHandle].GLctx.canvas.GLctxObject=undefined}GL.contexts[contextHandle]=null},initExtensions:context=>{context||=GL.currentContext;if(context.initExtensionsDone)return;context.initExtensionsDone=true;var GLctx=context.GLctx;webgl_enable_ANGLE_instanced_arrays(GLctx);webgl_enable_OES_vertex_array_object(GLctx);webgl_enable_WEBGL_draw_buffers(GLctx);webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);if(context.version>=2){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query_webgl2")}if(context.version<2||!GLctx.disjointTimerQueryExt){GLctx.disjointTimerQueryExt=GLctx.getExtension("EXT_disjoint_timer_query")}webgl_enable_WEBGL_multi_draw(GLctx);getEmscriptenSupportedExtensions(GLctx).forEach(ext=>{if(!ext.includes("lose_context")&&!ext.includes("debug")){GLctx.getExtension(ext)}})}};var registerWebGlEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{var webGlEventHandlerFunc=(e=event)=>{if(getWasmTableEntry(callbackfunc)(eventTypeId,0,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:webGlEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_webglcontextlost_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>{registerWebGlEventCallback(target,userData,useCapture,callbackfunc,31,"webglcontextlost",targetThread);return 0};var _emscripten_set_webglcontextrestored_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>{registerWebGlEventCallback(target,userData,useCapture,callbackfunc,32,"webglcontextrestored",targetThread);return 0};var registerWheelEventCallback=(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread)=>{if(!JSEvents.wheelEvent)JSEvents.wheelEvent=_malloc(104);var wheelHandlerFunc=(e=event)=>{var wheelEvent=JSEvents.wheelEvent;fillMouseEventData(wheelEvent,e,target);HEAPF64[wheelEvent+72>>3]=e["deltaX"];HEAPF64[wheelEvent+80>>3]=e["deltaY"];HEAPF64[wheelEvent+88>>3]=e["deltaZ"];HEAP32[wheelEvent+96>>2]=e["deltaMode"];if(getWasmTableEntry(callbackfunc)(eventTypeId,wheelEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:wheelHandlerFunc,useCapture:useCapture};return JSEvents.registerOrRemoveHandler(eventHandler)};var _emscripten_set_wheel_callback_on_thread=(target,userData,useCapture,callbackfunc,targetThread)=>{target=findEventTarget(target);if(!target)return-4;if(typeof target.onwheel!="undefined"){return registerWheelEventCallback(target,userData,useCapture,callbackfunc,9,"wheel",targetThread)}else{return-1}};var emscripten_webgl_power_preferences=["default","low-power","high-performance"];var _emscripten_webgl_do_create_context=(target,attributes)=>{var a=attributes>>2;var powerPreference=HEAP32[a+(24>>2)];var contextAttributes={"alpha":!!HEAP32[a+(0>>2)],"depth":!!HEAP32[a+(4>>2)],"stencil":!!HEAP32[a+(8>>2)],"antialias":!!HEAP32[a+(12>>2)],"premultipliedAlpha":!!HEAP32[a+(16>>2)],"preserveDrawingBuffer":!!HEAP32[a+(20>>2)],"powerPreference":emscripten_webgl_power_preferences[powerPreference],"failIfMajorPerformanceCaveat":!!HEAP32[a+(28>>2)],majorVersion:HEAP32[a+(32>>2)],minorVersion:HEAP32[a+(36>>2)],enableExtensionsByDefault:HEAP32[a+(40>>2)],explicitSwapControl:HEAP32[a+(44>>2)],proxyContextToMainThread:HEAP32[a+(48>>2)],renderViaOffscreenBackBuffer:HEAP32[a+(52>>2)]};var canvas=findCanvasEventTarget(target);if(!canvas){return 0}if(contextAttributes.explicitSwapControl){return 0}var contextHandle=GL.createContext(canvas,contextAttributes);return contextHandle};var _emscripten_webgl_create_context=_emscripten_webgl_do_create_context;var _emscripten_webgl_enable_extension=(contextHandle,extension)=>{var context=GL.getContext(contextHandle);var extString=UTF8ToString(extension);if(extString.startsWith("GL_"))extString=extString.substr(3);if(extString=="ANGLE_instanced_arrays")webgl_enable_ANGLE_instanced_arrays(GLctx);if(extString=="OES_vertex_array_object")webgl_enable_OES_vertex_array_object(GLctx);if(extString=="WEBGL_draw_buffers")webgl_enable_WEBGL_draw_buffers(GLctx);if(extString=="WEBGL_draw_instanced_base_vertex_base_instance")webgl_enable_WEBGL_draw_instanced_base_vertex_base_instance(GLctx);if(extString=="WEBGL_multi_draw_instanced_base_vertex_base_instance")webgl_enable_WEBGL_multi_draw_instanced_base_vertex_base_instance(GLctx);if(extString=="WEBGL_multi_draw")webgl_enable_WEBGL_multi_draw(GLctx);var ext=context.GLctx.getExtension(extString);return!!ext};var _emscripten_webgl_make_context_current=contextHandle=>{var success=GL.makeContextCurrent(contextHandle);return success?0:-5};var ENV={};var getExecutableName=()=>thisProgram||"./this.program";var getEnvStrings=()=>{if(!getEnvStrings.strings){var lang=(typeof navigator=="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":lang,"_":getExecutableName()};for(var x in ENV){if(ENV[x]===undefined)delete env[x];else env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(`${x}=${env[x]}`)}getEnvStrings.strings=strings}return getEnvStrings.strings};var stringToAscii=(str,buffer)=>{for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}HEAP8[buffer>>0]=0};var _environ_get=(__environ,environ_buf)=>{var bufSize=0;getEnvStrings().forEach((string,i)=>{var ptr=environ_buf+bufSize;HEAPU32[__environ+i*4>>2]=ptr;stringToAscii(string,ptr);bufSize+=string.length+1});return 0};var _environ_sizes_get=(penviron_count,penviron_buf_size)=>{var strings=getEnvStrings();HEAPU32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(string=>bufSize+=string.length+1);HEAPU32[penviron_buf_size>>2]=bufSize;return 0};var runtimeKeepaliveCounter=0;var keepRuntimeAlive=()=>noExitRuntime||runtimeKeepaliveCounter>0;var _proc_exit=code=>{EXITSTATUS=code;if(!keepRuntimeAlive()){Module["onExit"]?.(code);ABORT=true}quit_(code,new ExitStatus(code))};var exitJS=(status,implicit)=>{EXITSTATUS=status;_proc_exit(status)};var _exit=exitJS;function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var rightsBase=0;var rightsInheriting=0;var flags=0;{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4}HEAP8[pbuf>>0]=type;HEAP16[pbuf+2>>1]=flags;tempI64=[rightsBase>>>0,(tempDouble=rightsBase,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+8>>2]=tempI64[0],HEAP32[pbuf+12>>2]=tempI64[1];tempI64=[rightsInheriting>>>0,(tempDouble=rightsInheriting,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[pbuf+16>>2]=tempI64[0],HEAP32[pbuf+20>>2]=tempI64[1];return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doReadv=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr<len)break;if(typeof offset!=="undefined"){offset+=curr}}return ret};function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doReadv(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);try{if(isNaN(offset))return 61;var stream=SYSCALLS.getStreamFromFD(fd);FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math.abs(tempDouble)>=1?tempDouble>0?+Math.floor(tempDouble/4294967296)>>>0:~~+Math.ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}var doWritev=(stream,iov,iovcnt,offset)=>{var ret=0;for(var i=0;i<iovcnt;i++){var ptr=HEAPU32[iov>>2];var len=HEAPU32[iov+4>>2];iov+=8;var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(typeof offset!=="undefined"){offset+=curr}}return ret};function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=doWritev(stream,iov,iovcnt);HEAPU32[pnum>>2]=num;return 0}catch(e){if(typeof FS=="undefined"||!(e.name==="ErrnoError"))throw e;return e.errno}}function _glActiveTexture(x0){GLctx.activeTexture(x0)}var _glAttachShader=(program,shader)=>{GLctx.attachShader(GL.programs[program],GL.shaders[shader])};var _glBindBuffer=(target,buffer)=>{if(target==34962){GLctx.currentArrayBufferBinding=buffer}else if(target==34963){GLctx.currentElementArrayBufferBinding=buffer}if(target==35051){GLctx.currentPixelPackBufferBinding=buffer}else if(target==35052){GLctx.currentPixelUnpackBufferBinding=buffer}GLctx.bindBuffer(target,GL.buffers[buffer])};var _glBindFramebuffer=(target,framebuffer)=>{GLctx.bindFramebuffer(target,GL.framebuffers[framebuffer])};var _glBindRenderbuffer=(target,renderbuffer)=>{GLctx.bindRenderbuffer(target,GL.renderbuffers[renderbuffer])};var _glBindSampler=(unit,sampler)=>{GLctx.bindSampler(unit,GL.samplers[sampler])};var _glBindTexture=(target,texture)=>{GLctx.bindTexture(target,GL.textures[texture])};var _glBindVertexArray=vao=>{GLctx.bindVertexArray(GL.vaos[vao]);var ibo=GLctx.getParameter(34965);GLctx.currentElementArrayBufferBinding=ibo?ibo.name|0:0};function _glBlendColor(x0,x1,x2,x3){GLctx.blendColor(x0,x1,x2,x3)}function _glBlendEquationSeparate(x0,x1){GLctx.blendEquationSeparate(x0,x1)}function _glBlendFuncSeparate(x0,x1,x2,x3){GLctx.blendFuncSeparate(x0,x1,x2,x3)}function _glBlitFramebuffer(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9){GLctx.blitFramebuffer(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)}var _glBufferData=(target,size,data,usage)=>{if(GL.currentContext.version>=2){if(data&&size){GLctx.bufferData(target,HEAPU8,usage,data,size)}else{GLctx.bufferData(target,size,usage)}}else{GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)}};var _glBufferSubData=(target,offset,size,data)=>{if(GL.currentContext.version>=2){size&&GLctx.bufferSubData(target,offset,HEAPU8,data,size);return}GLctx.bufferSubData(target,offset,HEAPU8.subarray(data,data+size))};var _glClearBufferfv=(buffer,drawbuffer,value)=>{GLctx.clearBufferfv(buffer,drawbuffer,HEAPF32,value>>2)};var _glColorMask=(red,green,blue,alpha)=>{GLctx.colorMask(!!red,!!green,!!blue,!!alpha)};var _glCompileShader=shader=>{GLctx.compileShader(GL.shaders[shader])};var _glCompressedTexImage2D=(target,level,internalFormat,width,height,border,imageSize,data)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding||!imageSize){GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,imageSize,data)}else{GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,HEAPU8,data,imageSize)}return}GLctx.compressedTexImage2D(target,level,internalFormat,width,height,border,data?HEAPU8.subarray(data,data+imageSize):null)};var _glCompressedTexImage3D=(target,level,internalFormat,width,height,depth,border,imageSize,data)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.compressedTexImage3D(target,level,internalFormat,width,height,depth,border,imageSize,data)}else{GLctx.compressedTexImage3D(target,level,internalFormat,width,height,depth,border,HEAPU8,data,imageSize)}};var _glCreateProgram=()=>{var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;program.maxUniformLength=program.maxAttributeLength=program.maxUniformBlockNameLength=0;program.uniformIdCounter=1;GL.programs[id]=program;return id};var _glCreateShader=shaderType=>{var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id};function _glCullFace(x0){GLctx.cullFace(x0)}var _glDeleteBuffers=(n,buffers)=>{for(var i=0;i<n;i++){var id=HEAP32[buffers+i*4>>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GLctx.currentArrayBufferBinding)GLctx.currentArrayBufferBinding=0;if(id==GLctx.currentElementArrayBufferBinding)GLctx.currentElementArrayBufferBinding=0;if(id==GLctx.currentPixelPackBufferBinding)GLctx.currentPixelPackBufferBinding=0;if(id==GLctx.currentPixelUnpackBufferBinding)GLctx.currentPixelUnpackBufferBinding=0}};var _glDeleteFramebuffers=(n,framebuffers)=>{for(var i=0;i<n;++i){var id=HEAP32[framebuffers+i*4>>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}};var _glDeleteProgram=id=>{if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null};var _glDeleteRenderbuffers=(n,renderbuffers)=>{for(var i=0;i<n;i++){var id=HEAP32[renderbuffers+i*4>>2];var renderbuffer=GL.renderbuffers[id];if(!renderbuffer)continue;GLctx.deleteRenderbuffer(renderbuffer);renderbuffer.name=0;GL.renderbuffers[id]=null}};var _glDeleteSamplers=(n,samplers)=>{for(var i=0;i<n;i++){var id=HEAP32[samplers+i*4>>2];var sampler=GL.samplers[id];if(!sampler)continue;GLctx.deleteSampler(sampler);sampler.name=0;GL.samplers[id]=null}};var _glDeleteShader=id=>{if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null};var _glDeleteTextures=(n,textures)=>{for(var i=0;i<n;i++){var id=HEAP32[textures+i*4>>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}};var _glDeleteVertexArrays=(n,vaos)=>{for(var i=0;i<n;i++){var id=HEAP32[vaos+i*4>>2];GLctx.deleteVertexArray(GL.vaos[id]);GL.vaos[id]=null}};function _glDepthFunc(x0){GLctx.depthFunc(x0)}var _glDepthMask=flag=>{GLctx.depthMask(!!flag)};function _glDisable(x0){GLctx.disable(x0)}var _glDisableVertexAttribArray=index=>{var cb=GL.currentContext.clientBuffers[index];cb.enabled=false;GLctx.disableVertexAttribArray(index)};var _glDrawArrays=(mode,first,count)=>{GL.preDrawHandleClientVertexAttribBindings(first+count);GLctx.drawArrays(mode,first,count);GL.postDrawHandleClientVertexAttribBindings()};var _glDrawArraysInstanced=(mode,first,count,primcount)=>{GLctx.drawArraysInstanced(mode,first,count,primcount)};var _glDrawElements=(mode,count,type,indices)=>{var buf;if(!GLctx.currentElementArrayBufferBinding){var size=GL.calcBufLength(1,type,0,count);buf=GL.getTempIndexBuffer(size);GLctx.bindBuffer(34963,buf);GLctx.bufferSubData(34963,0,HEAPU8.subarray(indices,indices+size));indices=0}GL.preDrawHandleClientVertexAttribBindings(count);GLctx.drawElements(mode,count,type,indices);GL.postDrawHandleClientVertexAttribBindings(count);if(!GLctx.currentElementArrayBufferBinding){GLctx.bindBuffer(34963,null)}};var _glDrawElementsInstanced=(mode,count,type,indices,primcount)=>{GLctx.drawElementsInstanced(mode,count,type,indices,primcount)};function _glEnable(x0){GLctx.enable(x0)}var _glEnableVertexAttribArray=index=>{var cb=GL.currentContext.clientBuffers[index];cb.enabled=true;GLctx.enableVertexAttribArray(index)};function _glFrontFace(x0){GLctx.frontFace(x0)}var __glGenObject=(n,buffers,createFunction,objectTable)=>{for(var i=0;i<n;i++){var buffer=GLctx[createFunction]();var id=buffer&&GL.getNewId(objectTable);if(buffer){buffer.name=id;objectTable[id]=buffer}else{GL.recordError(1282)}HEAP32[buffers+i*4>>2]=id}};var _glGenBuffers=(n,buffers)=>{__glGenObject(n,buffers,"createBuffer",GL.buffers)};var _glGenRenderbuffers=(n,renderbuffers)=>{__glGenObject(n,renderbuffers,"createRenderbuffer",GL.renderbuffers)};var _glGenSamplers=(n,samplers)=>{__glGenObject(n,samplers,"createSampler",GL.samplers)};var _glGenTextures=(n,textures)=>{__glGenObject(n,textures,"createTexture",GL.textures)};function _glGenVertexArrays(n,arrays){__glGenObject(n,arrays,"createVertexArray",GL.vaos)}var _glGetAttribLocation=(program,name)=>GLctx.getAttribLocation(GL.programs[program],UTF8ToString(name));var writeI53ToI64=(ptr,num)=>{HEAPU32[ptr>>2]=num;var lower=HEAPU32[ptr>>2];HEAPU32[ptr+4>>2]=(num-lower)/4294967296};var webglGetExtensions=function $webglGetExtensions(){var exts=getEmscriptenSupportedExtensions(GLctx);exts=exts.concat(exts.map(e=>"GL_"+e));return exts};var emscriptenWebGLGet=(name_,p,type)=>{if(!p){GL.recordError(1281);return}var ret=undefined;switch(name_){case 36346:ret=1;break;case 36344:if(type!=0&&type!=1){GL.recordError(1280)}return;case 34814:case 36345:ret=0;break;case 34466:var formats=GLctx.getParameter(34467);ret=formats?formats.length:0;break;case 33309:if(GL.currentContext.version<2){GL.recordError(1282);return}ret=webglGetExtensions().length;break;case 33307:case 33308:if(GL.currentContext.version<2){GL.recordError(1280);return}ret=name_==33307?3:0;break}if(ret===undefined){var result=GLctx.getParameter(name_);switch(typeof result){case"number":ret=result;break;case"boolean":ret=result?1:0;break;case"string":GL.recordError(1280);return;case"object":if(result===null){switch(name_){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 36662:case 36663:case 35053:case 35055:case 36010:case 35097:case 35869:case 32874:case 36389:case 35983:case 35368:case 34068:{ret=0;break}default:{GL.recordError(1280);return}}}else if(result instanceof Float32Array||result instanceof Uint32Array||result instanceof Int32Array||result instanceof Array){for(var i=0;i<result.length;++i){switch(type){case 0:HEAP32[p+i*4>>2]=result[i];break;case 2:HEAPF32[p+i*4>>2]=result[i];break;case 4:HEAP8[p+i>>0]=result[i]?1:0;break}}return}else{try{ret=result.name|0}catch(e){GL.recordError(1280);err(`GL_INVALID_ENUM in glGet${type}v: Unknown object returned from WebGL getParameter(${name_})! (error: ${e})`);return}}break;default:GL.recordError(1280);err(`GL_INVALID_ENUM in glGet${type}v: Native code calling glGet${type}v(${name_}) and it returns ${result} of type ${typeof result}!`);return}}switch(type){case 1:writeI53ToI64(p,ret);break;case 0:HEAP32[p>>2]=ret;break;case 2:HEAPF32[p>>2]=ret;break;case 4:HEAP8[p>>0]=ret?1:0;break}};var _glGetIntegerv=(name_,p)=>emscriptenWebGLGet(name_,p,0);var _glGetProgramInfoLog=(program,maxLength,length,infoLog)=>{var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull};var _glGetProgramiv=(program,pname,p)=>{if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}program=GL.programs[program];if(pname==35716){var log=GLctx.getProgramInfoLog(program);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35719){if(!program.maxUniformLength){for(var i=0;i<GLctx.getProgramParameter(program,35718);++i){program.maxUniformLength=Math.max(program.maxUniformLength,GLctx.getActiveUniform(program,i).name.length+1)}}HEAP32[p>>2]=program.maxUniformLength}else if(pname==35722){if(!program.maxAttributeLength){for(var i=0;i<GLctx.getProgramParameter(program,35721);++i){program.maxAttributeLength=Math.max(program.maxAttributeLength,GLctx.getActiveAttrib(program,i).name.length+1)}}HEAP32[p>>2]=program.maxAttributeLength}else if(pname==35381){if(!program.maxUniformBlockNameLength){for(var i=0;i<GLctx.getProgramParameter(program,35382);++i){program.maxUniformBlockNameLength=Math.max(program.maxUniformBlockNameLength,GLctx.getActiveUniformBlockName(program,i).length+1)}}HEAP32[p>>2]=program.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(program,pname)}};var _glGetShaderInfoLog=(shader,maxLength,length,infoLog)=>{var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull};var _glGetShaderiv=(shader,pname,p)=>{if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var logLength=log?log.length+1:0;HEAP32[p>>2]=logLength}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source?source.length+1:0;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}};var stringToNewUTF8=str=>{var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8(str,ret,size);return ret};var _glGetStringi=(name,index)=>{if(GL.currentContext.version<2){GL.recordError(1282);return 0}var stringiCache=GL.stringiCache[name];if(stringiCache){if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index]}switch(name){case 7939:var exts=webglGetExtensions().map(stringToNewUTF8);stringiCache=GL.stringiCache[name]=exts;if(index<0||index>=stringiCache.length){GL.recordError(1281);return 0}return stringiCache[index];default:GL.recordError(1280);return 0}};var jstoi_q=str=>parseInt(str);var webglGetLeftBracePos=name=>name.slice(-1)=="]"&&name.lastIndexOf("[");var webglPrepareUniformLocationsBeforeFirstUse=program=>{var uniformLocsById=program.uniformLocsById,uniformSizeAndIdsByName=program.uniformSizeAndIdsByName,i,j;if(!uniformLocsById){program.uniformLocsById=uniformLocsById={};program.uniformArrayNamesById={};for(i=0;i<GLctx.getProgramParameter(program,35718);++i){var u=GLctx.getActiveUniform(program,i);var nm=u.name;var sz=u.size;var lb=webglGetLeftBracePos(nm);var arrayName=lb>0?nm.slice(0,lb):nm;var id=program.uniformIdCounter;program.uniformIdCounter+=sz;uniformSizeAndIdsByName[arrayName]=[sz,id];for(j=0;j<sz;++j){uniformLocsById[id]=j;program.uniformArrayNamesById[id++]=arrayName}}}};var _glGetUniformLocation=(program,name)=>{name=UTF8ToString(name);if(program=GL.programs[program]){webglPrepareUniformLocationsBeforeFirstUse(program);var uniformLocsById=program.uniformLocsById;var arrayIndex=0;var uniformBaseName=name;var leftBrace=webglGetLeftBracePos(name);if(leftBrace>0){arrayIndex=jstoi_q(name.slice(leftBrace+1))>>>0;uniformBaseName=name.slice(0,leftBrace)}var sizeAndId=program.uniformSizeAndIdsByName[uniformBaseName];if(sizeAndId&&arrayIndex<sizeAndId[0]){arrayIndex+=sizeAndId[1];if(uniformLocsById[arrayIndex]=uniformLocsById[arrayIndex]||GLctx.getUniformLocation(program,name)){return arrayIndex}}}else{GL.recordError(1281)}return-1};var tempFixedLengthArray=[];var _glInvalidateFramebuffer=(target,numAttachments,attachments)=>{var list=tempFixedLengthArray[numAttachments];for(var i=0;i<numAttachments;i++){list[i]=HEAP32[attachments+i*4>>2]}GLctx.invalidateFramebuffer(target,list)};var _glLinkProgram=program=>{program=GL.programs[program];GLctx.linkProgram(program);program.uniformLocsById=0;program.uniformSizeAndIdsByName={}};var _glPixelStorei=(pname,param)=>{if(pname==3317){GL.unpackAlignment=param}GLctx.pixelStorei(pname,param)};function _glPolygonOffset(x0,x1){GLctx.polygonOffset(x0,x1)}function _glReadBuffer(x0){GLctx.readBuffer(x0)}function _glRenderbufferStorageMultisample(x0,x1,x2,x3,x4){GLctx.renderbufferStorageMultisample(x0,x1,x2,x3,x4)}var _glSamplerParameterf=(sampler,pname,param)=>{GLctx.samplerParameterf(GL.samplers[sampler],pname,param)};var _glSamplerParameteri=(sampler,pname,param)=>{GLctx.samplerParameteri(GL.samplers[sampler],pname,param)};function _glScissor(x0,x1,x2,x3){GLctx.scissor(x0,x1,x2,x3)}var _glShaderSource=(shader,count,string,length)=>{var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)};function _glStencilFunc(x0,x1,x2){GLctx.stencilFunc(x0,x1,x2)}function _glStencilFuncSeparate(x0,x1,x2,x3){GLctx.stencilFuncSeparate(x0,x1,x2,x3)}function _glStencilMask(x0){GLctx.stencilMask(x0)}function _glStencilOp(x0,x1,x2){GLctx.stencilOp(x0,x1,x2)}function _glStencilOpSeparate(x0,x1,x2,x3){GLctx.stencilOpSeparate(x0,x1,x2,x3)}var computeUnpackAlignedImageSize=(width,height,sizePerPixel,alignment)=>{function roundedToNextMultipleOf(x,y){return x+y-1&-y}var plainRowSize=width*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,alignment);return height*alignedRowSize};var colorChannelsInGlTextureFormat=format=>{var colorChannels={5:3,6:4,8:2,29502:3,29504:4,26917:2,26918:2,29846:3,29847:4};return colorChannels[format-6402]||1};var heapObjectForWebGLType=type=>{type-=5120;if(type==0)return HEAP8;if(type==1)return HEAPU8;if(type==2)return HEAP16;if(type==4)return HEAP32;if(type==6)return HEAPF32;if(type==5||type==28922||type==28520||type==30779||type==30782)return HEAPU32;return HEAPU16};var heapAccessShiftForWebGLHeap=heap=>31-Math.clz32(heap.BYTES_PER_ELEMENT);var emscriptenWebGLGetTexPixelData=(type,format,width,height,pixels,internalFormat)=>{var heap=heapObjectForWebGLType(type);var shift=heapAccessShiftForWebGLHeap(heap);var byteSize=1<<shift;var sizePerPixel=colorChannelsInGlTextureFormat(format)*byteSize;var bytes=computeUnpackAlignedImageSize(width,height,sizePerPixel,GL.unpackAlignment);return heap.subarray(pixels>>shift,pixels+bytes>>shift)};var _glTexImage2D=(target,level,internalFormat,width,height,border,format,type,pixels)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,null)}return}GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null)};var _glTexImage3D=(target,level,internalFormat,width,height,depth,border,format,type,pixels)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texImage3D(target,level,internalFormat,width,height,depth,border,format,type,null)}};function _glTexParameteri(x0,x1,x2){GLctx.texParameteri(x0,x1,x2)}var _glTexSubImage2D=(target,level,xoffset,yoffset,width,height,format,type,pixels)=>{if(GL.currentContext.version>=2){if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,null)}return}var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)};var _glTexSubImage3D=(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)=>{if(GLctx.currentPixelUnpackBufferBinding){GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,pixels)}else if(pixels){var heap=heapObjectForWebGLType(type);GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,heap,pixels>>heapAccessShiftForWebGLHeap(heap))}else{GLctx.texSubImage3D(target,level,xoffset,yoffset,zoffset,width,height,depth,format,type,null)}};var webglGetUniformLocation=location=>{var p=GLctx.currentProgram;if(p){var webglLoc=p.uniformLocsById[location];if(typeof webglLoc=="number"){p.uniformLocsById[location]=webglLoc=GLctx.getUniformLocation(p,p.uniformArrayNamesById[location]+(webglLoc>0?`[${webglLoc}]`:""))}return webglLoc}else{GL.recordError(1282)}};var miniTempWebGLFloatBuffers=[];var _glUniform1fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform1fv(webglGetUniformLocation(location),HEAPF32,value>>2,count);return}if(count<=288){var view=miniTempWebGLFloatBuffers[count-1];for(var i=0;i<count;++i){view[i]=HEAPF32[value+4*i>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1fv(webglGetUniformLocation(location),view)};var _glUniform1i=(location,v0)=>{GLctx.uniform1i(webglGetUniformLocation(location),v0)};var miniTempWebGLIntBuffers=[];var _glUniform1iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform1iv(webglGetUniformLocation(location),HEAP32,value>>2,count);return}if(count<=288){var view=miniTempWebGLIntBuffers[count-1];for(var i=0;i<count;++i){view[i]=HEAP32[value+4*i>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1iv(webglGetUniformLocation(location),view)};var _glUniform2fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform2fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*2);return}if(count<=144){var view=miniTempWebGLFloatBuffers[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(webglGetUniformLocation(location),view)};var _glUniform2iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform2iv(webglGetUniformLocation(location),HEAP32,value>>2,count*2);return}if(count<=144){var view=miniTempWebGLIntBuffers[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2iv(webglGetUniformLocation(location),view)};var _glUniform3fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform3fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*3);return}if(count<=96){var view=miniTempWebGLFloatBuffers[3*count-1];for(var i=0;i<3*count;i+=3){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3fv(webglGetUniformLocation(location),view)};var _glUniform3iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform3iv(webglGetUniformLocation(location),HEAP32,value>>2,count*3);return}if(count<=96){var view=miniTempWebGLIntBuffers[3*count-1];for(var i=0;i<3*count;i+=3){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3iv(webglGetUniformLocation(location),view)};var _glUniform4fv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform4fv(webglGetUniformLocation(location),HEAPF32,value>>2,count*4);return}if(count<=72){var view=miniTempWebGLFloatBuffers[4*count-1];var heap=HEAPF32;value>>=2;for(var i=0;i<4*count;i+=4){var dst=value+i;view[i]=heap[dst];view[i+1]=heap[dst+1];view[i+2]=heap[dst+2];view[i+3]=heap[dst+3]}}else{var view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4fv(webglGetUniformLocation(location),view)};var _glUniform4iv=(location,count,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniform4iv(webglGetUniformLocation(location),HEAP32,value>>2,count*4);return}if(count<=72){var view=miniTempWebGLIntBuffers[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2];view[i+3]=HEAP32[value+(4*i+12)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4iv(webglGetUniformLocation(location),view)};var _glUniformMatrix4fv=(location,count,transpose,value)=>{if(GL.currentContext.version>=2){count&&GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,HEAPF32,value>>2,count*16);return}if(count<=18){var view=miniTempWebGLFloatBuffers[16*count-1];var heap=HEAPF32;value>>=2;for(var i=0;i<16*count;i+=16){var dst=value+i;view[i]=heap[dst];view[i+1]=heap[dst+1];view[i+2]=heap[dst+2];view[i+3]=heap[dst+3];view[i+4]=heap[dst+4];view[i+5]=heap[dst+5];view[i+6]=heap[dst+6];view[i+7]=heap[dst+7];view[i+8]=heap[dst+8];view[i+9]=heap[dst+9];view[i+10]=heap[dst+10];view[i+11]=heap[dst+11];view[i+12]=heap[dst+12];view[i+13]=heap[dst+13];view[i+14]=heap[dst+14];view[i+15]=heap[dst+15]}}else{var view=HEAPF32.subarray(value>>2,value+count*64>>2)}GLctx.uniformMatrix4fv(webglGetUniformLocation(location),!!transpose,view)};var _glUseProgram=program=>{program=GL.programs[program];GLctx.useProgram(program);GLctx.currentProgram=program};var _glVertexAttribDivisor=(index,divisor)=>{GLctx.vertexAttribDivisor(index,divisor)};var _glVertexAttribPointer=(index,size,type,normalized,stride,ptr)=>{var cb=GL.currentContext.clientBuffers[index];if(!GLctx.currentArrayBufferBinding){cb.size=size;cb.type=type;cb.normalized=normalized;cb.stride=stride;cb.ptr=ptr;cb.clientside=true;cb.vertexAttribPointerAdaptor=function(index,size,type,normalized,stride,ptr){this.vertexAttribPointer(index,size,type,normalized,stride,ptr)};return}cb.clientside=false;GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)};function _glViewport(x0,x1,x2,x3){GLctx.viewport(x0,x1,x2,x3)}var isLeapYear=year=>year%4===0&&(year%100!==0||year%400===0);var arraySum=(array,index)=>{var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum};var MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];var addDays=(date,days)=>{var newDate=new Date(date.getTime());while(days>0){var leap=isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate};var writeArrayToMemory=(array,buffer)=>{HEAP8.set(array,buffer)};var _strftime=(s,maxsize,format,tm)=>{var tm_zone=HEAPU32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value=="number"?value.toString():value||"";while(str.length<digits){str=character[0]+str}return str}function leadingNulls(value,digits){return leadingSomething(value,digits,"0")}function compareByDay(date1,date2){function sgn(value){return value<0?-1:value>0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}return thisDate.getFullYear()}return thisDate.getFullYear()-1}var EXPANSION_RULES_2={"%a":date=>WEEKDAYS[date.tm_wday].substring(0,3),"%A":date=>WEEKDAYS[date.tm_wday],"%b":date=>MONTHS[date.tm_mon].substring(0,3),"%B":date=>MONTHS[date.tm_mon],"%C":date=>{var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":date=>leadingNulls(date.tm_mday,2),"%e":date=>leadingSomething(date.tm_mday,2," "),"%g":date=>getWeekBasedYear(date).toString().substring(2),"%G":getWeekBasedYear,"%H":date=>leadingNulls(date.tm_hour,2),"%I":date=>{var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":date=>leadingNulls(date.tm_mday+arraySum(isLeapYear(date.tm_year+1900)?MONTH_DAYS_LEAP:MONTH_DAYS_REGULAR,date.tm_mon-1),3),"%m":date=>leadingNulls(date.tm_mon+1,2),"%M":date=>leadingNulls(date.tm_min,2),"%n":()=>"\n","%p":date=>{if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}return"PM"},"%S":date=>leadingNulls(date.tm_sec,2),"%t":()=>"\t","%u":date=>date.tm_wday||7,"%U":date=>{var days=date.tm_yday+7-date.tm_wday;return leadingNulls(Math.floor(days/7),2)},"%V":date=>{var val=Math.floor((date.tm_yday+7-(date.tm_wday+6)%7)/7);if((date.tm_wday+371-date.tm_yday-2)%7<=2){val++}if(!val){val=52;var dec31=(date.tm_wday+7-date.tm_yday-1)%7;if(dec31==4||dec31==5&&isLeapYear(date.tm_year%400-1)){val++}}else if(val==53){var jan1=(date.tm_wday+371-date.tm_yday)%7;if(jan1!=4&&(jan1!=3||!isLeapYear(date.tm_year)))val=1}return leadingNulls(val,2)},"%w":date=>date.tm_wday,"%W":date=>{var days=date.tm_yday+7-(date.tm_wday+6)%7;return leadingNulls(Math.floor(days/7),2)},"%y":date=>(date.tm_year+1900).toString().substring(2),"%Y":date=>date.tm_year+1900,"%z":date=>{var off=date.tm_gmtoff;var ahead=off>=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":date=>date.tm_zone,"%%":()=>"%"};pattern=pattern.replace(/%%/g,"\0\0");for(var rule in EXPANSION_RULES_2){if(pattern.includes(rule)){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}pattern=pattern.replace(/\0\0/g,"%");var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1};var _strftime_l=(s,maxsize,format,tm,loc)=>_strftime(s,maxsize,format,tm);var handleException=e=>{if(e instanceof ExitStatus||e=="unwind"){return EXITSTATUS}quit_(1,e)};var stringToUTF8OnStack=str=>{var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8(str,ret,size);return ret};var allocateUTF8OnStack=stringToUTF8OnStack;var getCFunc=ident=>{var func=Module["_"+ident];return func};var ccall=(ident,returnType,argTypes,args,opts)=>{var toC={"string":str=>{var ret=0;if(str!==null&&str!==undefined&&str!==0){ret=stringToUTF8OnStack(str)}return ret},"array":arr=>{var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string"){return UTF8ToString(ret)}if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);function onDone(ret){if(stack!==0)stackRestore(stack);return convertReturnValue(ret)}ret=onDone(ret);return ret};var cwrap=(ident,returnType,argTypes,opts)=>{var numericArgs=!argTypes||argTypes.every(type=>type==="number"||type==="boolean");var numericRet=returnType!=="string";if(numericRet&&numericArgs&&!opts){return getCFunc(ident)}return function(){return ccall(ident,returnType,argTypes,arguments,opts)}};var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.createPreloadedFile=FS_createPreloadedFile;FS.staticInit();Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_unlink"]=FS.unlink;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;var GLctx;for(var i=0;i<32;++i)tempFixedLengthArray.push(new Array(i));var miniTempWebGLFloatBuffersStorage=new Float32Array(288);for(var i=0;i<288;++i){miniTempWebGLFloatBuffers[i]=miniTempWebGLFloatBuffersStorage.subarray(0,i+1)}var miniTempWebGLIntBuffersStorage=new Int32Array(288);for(var i=0;i<288;++i){miniTempWebGLIntBuffers[i]=miniTempWebGLIntBuffersStorage.subarray(0,i+1)}var wasmImports={o:___cxa_begin_catch,w:___cxa_end_catch,a:___cxa_find_matching_catch_2,g:___cxa_find_matching_catch_3,Qa:___cxa_rethrow,Gb:___cxa_rethrow_primary_exception,b:___cxa_throw,Hb:___cxa_uncaught_exceptions,e:___resumeException,Lb:___syscall__newselect,Na:___syscall_fcntl64,Qb:___syscall_fstat64,R:___syscall_ioctl,Nb:___syscall_lstat64,Mb:___syscall_mkdirat,Ob:___syscall_newfstatat,Oa:___syscall_openat,Jb:___syscall_readlinkat,Pb:___syscall_stat64,Tb:__emscripten_fs_load_embedded_files,zb:__mmap_js,Ab:__munmap_js,v:_abort,m:_emscripten_asm_const_int,Rb:_emscripten_date_now,Ac:_emscripten_get_canvas_element_size,P:_emscripten_get_device_pixel_ratio,Ba:_emscripten_get_element_css_size,qa:_emscripten_get_gamepad_status,Cb:_emscripten_get_heap_max,y:_emscripten_get_now,qb:_emscripten_get_num_gamepads,Sb:_emscripten_memcpy_js,tb:_emscripten_request_animation_frame_loop,Ib:_emscripten_resize_heap,ra:_emscripten_sample_gamepad_data,va:_emscripten_set_blur_callback_on_thread,O:_emscripten_set_canvas_element_size,wa:_emscripten_set_focus_callback_on_thread,pa:_emscripten_set_gamepadconnected_callback_on_thread,La:_emscripten_set_keydown_callback_on_thread,Ja:_emscripten_set_keypress_callback_on_thread,Ka:_emscripten_set_keyup_callback_on_thread,Y:_emscripten_set_mousedown_callback_on_thread,Ta:_emscripten_set_mouseenter_callback_on_thread,Ra:_emscripten_set_mouseleave_callback_on_thread,Ua:_emscripten_set_mousemove_callback_on_thread,Va:_emscripten_set_mouseup_callback_on_thread,ya:_emscripten_set_pointerlockchange_callback_on_thread,xa:_emscripten_set_pointerlockerror_callback_on_thread,ta:_emscripten_set_resize_callback_on_thread,za:_emscripten_set_touchcancel_callback_on_thread,Aa:_emscripten_set_touchend_callback_on_thread,Ca:_emscripten_set_touchmove_callback_on_thread,Da:_emscripten_set_touchstart_callback_on_thread,ua:_emscripten_set_webglcontextlost_callback_on_thread,sa:_emscripten_set_webglcontextrestored_callback_on_thread,Pa:_emscripten_set_wheel_callback_on_thread,jb:_emscripten_webgl_create_context,cb:_emscripten_webgl_enable_extension,fb:_emscripten_webgl_make_context_current,Eb:_environ_get,Fb:_environ_sizes_get,rb:_exit,S:_fd_close,Kb:_fd_fdstat_get,Ma:_fd_read,Bb:_fd_seek,Q:_fd_write,B:_glActiveTexture,_:_glAttachShader,n:_glBindBuffer,D:_glBindFramebuffer,oc:_glBindRenderbuffer,A:_glBindSampler,q:_glBindTexture,ka:_glBindVertexArray,da:_glBlendColor,ea:_glBlendEquationSeparate,fa:_glBlendFuncSeparate,rc:_glBlitFramebuffer,db:_glBufferData,H:_glBufferSubData,Xa:_glClearBufferfv,M:_glColorMask,cc:_glCompileShader,ic:_glCompressedTexImage2D,kc:_glCompressedTexImage3D,ab:_glCreateProgram,ec:_glCreateShader,aa:_glCullFace,fc:_glDeleteBuffers,E:_glDeleteFramebuffers,I:_glDeleteProgram,na:_glDeleteRenderbuffers,ma:_glDeleteSamplers,L:_glDeleteShader,oa:_glDeleteTextures,pb:_glDeleteVertexArrays,ia:_glDepthFunc,ha:_glDepthMask,s:_glDisable,ja:_glDisableVertexAttribArray,tc:_glDrawArrays,uc:_glDrawArraysInstanced,vc:_glDrawElements,wc:_glDrawElementsInstanced,x:_glEnable,xc:_glEnableVertexAttribArray,ba:_glFrontFace,eb:_glGenBuffers,pc:_glGenRenderbuffers,bb:_glGenSamplers,mc:_glGenTextures,kb:_glGenVertexArrays,gc:_glGetAttribLocation,p:_glGetIntegerv,_a:_glGetProgramInfoLog,Z:_glGetProgramiv,bc:_glGetShaderInfoLog,Sa:_glGetShaderiv,lb:_glGetStringi,G:_glGetUniformLocation,qc:_glInvalidateFramebuffer,$a:_glLinkProgram,ib:_glPixelStorei,ca:_glPolygonOffset,sc:_glReadBuffer,nc:_glRenderbufferStorageMultisample,$:_glSamplerParameterf,u:_glSamplerParameteri,V:_glScissor,dc:_glShaderSource,hb:_glStencilFunc,U:_glStencilFuncSeparate,ga:_glStencilMask,gb:_glStencilOp,T:_glStencilOpSeparate,hc:_glTexImage2D,jc:_glTexImage3D,lc:_glTexParameteri,Ya:_glTexSubImage2D,Za:_glTexSubImage3D,ac:_glUniform1fv,X:_glUniform1i,Yb:_glUniform1iv,$b:_glUniform2fv,Xb:_glUniform2iv,_b:_glUniform3fv,Wb:_glUniform3iv,Zb:_glUniform4fv,Vb:_glUniform4iv,Ub:_glUniformMatrix4fv,F:_glUseProgram,yc:_glVertexAttribDivisor,Wa:_glVertexAttribPointer,W:_glViewport,Ea:invoke_diii,Fa:invoke_fiii,j:invoke_i,c:invoke_ii,f:invoke_iii,k:invoke_iiii,h:invoke_iiiii,Ha:invoke_iiiiii,z:invoke_iiiiiii,Ga:invoke_iiiiiiii,K:invoke_iiiiiiiiiiii,yb:invoke_iiiiij,xb:invoke_jiiii,i:invoke_v,t:invoke_vi,d:invoke_vii,l:invoke_viii,Ia:invoke_viiii,r:invoke_viiiiiii,C:invoke_viiiiiiiiii,J:invoke_viiiiiiiiiiiiiii,wb:sapp_js_add_beforeunload_listener,vb:sapp_js_add_clipboard_listener,ub:sapp_js_add_dragndrop_listeners,zc:sapp_js_init,ob:sapp_js_remove_beforeunload_listener,nb:sapp_js_remove_clipboard_listener,mb:sapp_js_remove_dragndrop_listeners,N:sapp_js_request_pointerlock,sb:sargs_js_parse_url,la:slog_js_log,Db:_strftime_l};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["Cc"])();var __sapp_emsc_onpaste=Module["__sapp_emsc_onpaste"]=a0=>(__sapp_emsc_onpaste=Module["__sapp_emsc_onpaste"]=wasmExports["Dc"])(a0);var __sapp_html5_get_ask_leave_site=Module["__sapp_html5_get_ask_leave_site"]=()=>(__sapp_html5_get_ask_leave_site=Module["__sapp_html5_get_ask_leave_site"]=wasmExports["Ec"])();var __sapp_emsc_begin_drop=Module["__sapp_emsc_begin_drop"]=a0=>(__sapp_emsc_begin_drop=Module["__sapp_emsc_begin_drop"]=wasmExports["Fc"])(a0);var __sapp_emsc_drop=Module["__sapp_emsc_drop"]=(a0,a1)=>(__sapp_emsc_drop=Module["__sapp_emsc_drop"]=wasmExports["Gc"])(a0,a1);var __sapp_emsc_end_drop=Module["__sapp_emsc_end_drop"]=(a0,a1,a2)=>(__sapp_emsc_end_drop=Module["__sapp_emsc_end_drop"]=wasmExports["Hc"])(a0,a1,a2);var __sapp_emsc_invoke_fetch_cb=Module["__sapp_emsc_invoke_fetch_cb"]=(a0,a1,a2,a3,a4,a5,a6,a7)=>(__sapp_emsc_invoke_fetch_cb=Module["__sapp_emsc_invoke_fetch_cb"]=wasmExports["Ic"])(a0,a1,a2,a3,a4,a5,a6,a7);var __sargs_add_kvp=Module["__sargs_add_kvp"]=(a0,a1)=>(__sargs_add_kvp=Module["__sargs_add_kvp"]=wasmExports["Jc"])(a0,a1);var _ma_device__on_notification_unlocked=Module["_ma_device__on_notification_unlocked"]=a0=>(_ma_device__on_notification_unlocked=Module["_ma_device__on_notification_unlocked"]=wasmExports["Kc"])(a0);var _ma_malloc_emscripten=Module["_ma_malloc_emscripten"]=(a0,a1)=>(_ma_malloc_emscripten=Module["_ma_malloc_emscripten"]=wasmExports["Lc"])(a0,a1);var _malloc=Module["_malloc"]=a0=>(_malloc=Module["_malloc"]=wasmExports["Mc"])(a0);var _ma_free_emscripten=Module["_ma_free_emscripten"]=(a0,a1)=>(_ma_free_emscripten=Module["_ma_free_emscripten"]=wasmExports["Nc"])(a0,a1);var _free=Module["_free"]=a0=>(_free=Module["_free"]=wasmExports["Oc"])(a0);var _ma_device_process_pcm_frames_capture__webaudio=Module["_ma_device_process_pcm_frames_capture__webaudio"]=(a0,a1,a2)=>(_ma_device_process_pcm_frames_capture__webaudio=Module["_ma_device_process_pcm_frames_capture__webaudio"]=wasmExports["Pc"])(a0,a1,a2);var _ma_device_process_pcm_frames_playback__webaudio=Module["_ma_device_process_pcm_frames_playback__webaudio"]=(a0,a1,a2)=>(_ma_device_process_pcm_frames_playback__webaudio=Module["_ma_device_process_pcm_frames_playback__webaudio"]=wasmExports["Qc"])(a0,a1,a2);var _rivemu_start_record=Module["_rivemu_start_record"]=(a0,a1,a2,a3,a4)=>(_rivemu_start_record=Module["_rivemu_start_record"]=wasmExports["Rc"])(a0,a1,a2,a3,a4);var _rivemu_start_replay=Module["_rivemu_start_replay"]=(a0,a1,a2,a3,a4,a5,a6)=>(_rivemu_start_replay=Module["_rivemu_start_replay"]=wasmExports["Sc"])(a0,a1,a2,a3,a4,a5,a6);var _rivemu_stop=Module["_rivemu_stop"]=a0=>(_rivemu_stop=Module["_rivemu_stop"]=wasmExports["Tc"])(a0);var _main=Module["_main"]=(a0,a1)=>(_main=Module["_main"]=wasmExports["Uc"])(a0,a1);var _emscripten_builtin_memalign=(a0,a1)=>(_emscripten_builtin_memalign=wasmExports["Wc"])(a0,a1);var _setThrew=(a0,a1)=>(_setThrew=wasmExports["Xc"])(a0,a1);var setTempRet0=a0=>(setTempRet0=wasmExports["Yc"])(a0);var stackSave=()=>(stackSave=wasmExports["Zc"])();var stackRestore=a0=>(stackRestore=wasmExports["_c"])(a0);var stackAlloc=a0=>(stackAlloc=wasmExports["$c"])(a0);var ___cxa_decrement_exception_refcount=a0=>(___cxa_decrement_exception_refcount=wasmExports["ad"])(a0);var ___cxa_increment_exception_refcount=a0=>(___cxa_increment_exception_refcount=wasmExports["bd"])(a0);var ___cxa_free_exception=a0=>(___cxa_free_exception=wasmExports["__cxa_free_exception"])(a0);var ___cxa_can_catch=(a0,a1,a2)=>(___cxa_can_catch=wasmExports["cd"])(a0,a1,a2);var ___cxa_is_pointer_type=a0=>(___cxa_is_pointer_type=wasmExports["dd"])(a0);var dynCall_iiiiij=Module["dynCall_iiiiij"]=(a0,a1,a2,a3,a4,a5,a6)=>(dynCall_iiiiij=Module["dynCall_iiiiij"]=wasmExports["ed"])(a0,a1,a2,a3,a4,a5,a6);var dynCall_jiiii=Module["dynCall_jiiii"]=(a0,a1,a2,a3,a4)=>(dynCall_jiiii=Module["dynCall_jiiii"]=wasmExports["fd"])(a0,a1,a2,a3,a4);var ___emscripten_embedded_file_data=Module["___emscripten_embedded_file_data"]=24905596;var ___start_em_js=Module["___start_em_js"]=24937924;var ___stop_em_js=Module["___stop_em_js"]=24944034;function invoke_ii(index,a1){var sp=stackSave();try{return getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{getWasmTableEntry(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{getWasmTableEntry(index)()}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_fiii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15){var sp=stackSave();try{getWasmTableEntry(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_iiiiij(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiiiij(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}function invoke_jiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jiiii(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0)throw e;_setThrew(1,0)}}Module["addRunDependency"]=addRunDependency;Module["removeRunDependency"]=removeRunDependency;Module["FS_createPath"]=FS.createPath;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createDevice"]=FS.createDevice;Module["ccall"]=ccall;Module["cwrap"]=cwrap;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_unlink"]=FS.unlink;var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function callMain(args=[]){var entryFunction=_main;args.unshift(thisProgram);var argc=args.length;var argv=stackAlloc((argc+1)*4);var argv_ptr=argv;args.forEach(arg=>{HEAPU32[argv_ptr>>2]=stringToUTF8OnStack(arg);argv_ptr+=4});HEAPU32[argv_ptr>>2]=0;try{var ret=entryFunction(argc,argv);exitJS(ret,true);return ret}catch(e){return handleException(e)}}function run(args=arguments_){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain(args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;run(); \ No newline at end of file diff --git a/frontend/public/rivemu.wasm b/frontend/public/rivemu.wasm index 7ba7857..87fdb75 100644 Binary files a/frontend/public/rivemu.wasm and b/frontend/public/rivemu.wasm differ diff --git a/frontend/public/rives64px.png b/frontend/public/rives64px.png new file mode 100644 index 0000000..af01b8b Binary files /dev/null and b/frontend/public/rives64px.png differ diff --git a/frontend/public/rives_logo.png b/frontend/public/rives_logo.png deleted file mode 100644 index ad8cda2..0000000 Binary files a/frontend/public/rives_logo.png and /dev/null differ diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index c714696..204de1d 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es5", + "target": "es2015", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, diff --git a/misc/2048.sqfs b/misc/2048.sqfs index 228f203..1ef1fc9 100644 Binary files a/misc/2048.sqfs and b/misc/2048.sqfs differ diff --git a/misc/Rives-Logo.png b/misc/Rives-Logo.png new file mode 100644 index 0000000..9315e62 Binary files /dev/null and b/misc/Rives-Logo.png differ diff --git a/misc/antcopter.sqfs b/misc/antcopter.sqfs index 424d6e7..55e7886 100644 Binary files a/misc/antcopter.sqfs and b/misc/antcopter.sqfs differ diff --git a/misc/font/Retro Gaming.ttf b/misc/font/Retro Gaming.ttf new file mode 100644 index 0000000..0dca996 Binary files /dev/null and b/misc/font/Retro Gaming.ttf differ diff --git a/misc/freedoom.sqfs b/misc/freedoom.sqfs index 3da0798..3051b97 100644 Binary files a/misc/freedoom.sqfs and b/misc/freedoom.sqfs differ diff --git a/misc/monky.sqfs b/misc/monky.sqfs new file mode 100644 index 0000000..39f5485 Binary files /dev/null and b/misc/monky.sqfs differ diff --git a/misc/snake.sqfs b/misc/snake.sqfs index 112f026..4f41487 100644 Binary files a/misc/snake.sqfs and b/misc/snake.sqfs differ diff --git a/misc/test.rivlog b/misc/test.rivlog new file mode 100644 index 0000000..4f03846 Binary files /dev/null and b/misc/test.rivlog differ diff --git a/misc/test_commands.md b/misc/test_commands.md index 22d4cde..57dcdc5 100644 --- a/misc/test_commands.md +++ b/misc/test_commands.md @@ -88,13 +88,13 @@ curl -s "http://localhost:8080/inspect/app/scores?scoreboard_id=a7a39b72f29718e6 indexer queries ```shell -curl -s http://localhost:8080/inspect/cartesapp/indexer_query?tags=score | jq -r '.reports[0].payload' | xxd -r -p -curl -s "http://localhost:8080/inspect/cartesapp/indexer_query?tags=replay&msg_sender=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" | jq -r '.reports[0].payload' | xxd -r -p +curl -s http://localhost:8080/inspect/indexer/indexer_query?tags=score | jq -r '.reports[0].payload' | xxd -r -p +curl -s "http://localhost:8080/inspect/indexer/indexer_query?tags=replay&msg_sender=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" | jq -r '.reports[0].payload' | xxd -r -p ``` Indexer score from scoreboard ```shell -indexer_result=$(curl -s http://localhost:8080/inspect/cartesapp/indexer_query?tags=score | jq -r '.reports[0].payload' | xxd -r -p | jq) +indexer_result=$(curl -s http://localhost:8080/inspect/indexer/indexer_query?tags=score | jq -r '.reports[0].payload' | xxd -r -p | jq) curl -s -H 'Content-Type: application/json' -X POST "http://localhost:8080/graphql" -d "{ \"query\":\"query { notice(inputIndex:$(echo $indexer_result | jq -r '.[0].input_index'),noticeIndex:$(echo $indexer_result | jq -r '.[0].output_index')) { payload}}\"}}" | jq -r '.data.notice.payload' | sed -r 's/^0x//' | tr -d '\n' | xxd -c 32 ``` diff --git a/requirements.txt b/requirements.txt index 2756126..359e14f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,26 +1,34 @@ -cartesi @ git+https://github.com/prototyp3-dev/python-cartesi@f728f18bcf0662873f09104984197106932d365a -certifi==2023.11.17 +base58==2.1.1 +cartesapp @ git+https://github.com/prototyp3-dev/cartesapp@3b2b8f4dcd7ae100474a6df4cb6a8a779dae835a +certifi==2024.2.2 charset-normalizer==3.3.2 -cytoolz==0.12.2 +click==8.1.7 +cytoolz==0.12.3 eth-abi==4.2.1 -eth-hash==0.5.2 -eth-typing==3.5.2 -eth-utils==2.3.1 +eth-hash==0.6.0 +eth-typing==4.0.0 +eth-utils==3.0.0 exceptiongroup==1.2.0 idna==3.6 iniconfig==2.0.0 +Jinja2==3.1.3 +MarkupSafe==2.1.5 packaging==23.2 parsimonious==0.9.0 -pluggy==1.3.0 +pillow==10.2.0 +pluggy==1.4.0 pony==0.7.17 -pycryptodome>=3.19.1 -pydantic==1.10.13 -py_expression_eval == 0.3.14 -pytest==7.4.3 -regex==2023.10.3 +protobuf==4.25.3 +py-expression-eval==0.3.14 +pycryptodome==3.19.1 +pydantic==1.10.14 +pydantic-to-typescript==1.0.10 +pytest==7.4.4 +python-cartesi==0.1.0 +regex==2023.12.25 requests==2.31.0 tomli==2.0.1 -toolz==0.12.0 +toolz==0.12.1 +typer==0.9.0 typing_extensions==4.9.0 -urllib3==2.1.0 -typer==0.9.0 \ No newline at end of file +urllib3==2.2.1