for _k, _v in value.items():
          xvalue[_k] = ResultsCount.create_from_state_dict(_v)

# NAS-Bench-102: Extending the Scope of Reproducible Neural Architecture Search, ICLR 2020 #
# NAS-Bench-102-v1_0-e61699.pth : 6219 architectures are trained once, 1621 architectures are trained twice, 7785 architectures are trained three times. `LESS` only supports CIFAR10-VALID.
import os, sys, copy, random, torch, numpy as np
from collections import OrderedDict, defaultdict

def print_information(information, extra_info=None, show=False):
  dataset_names = information.get_dataset_names()
  strings = [information.arch_str, 'datasets : {:}, extra-info : {:}'.format(dataset_names, extra_info)]
  def metric2str(loss, acc):
    return 'loss = {:.3f}, top1 = {:.2f}%'.format(loss, acc)

  for ida, dataset in enumerate(dataset_names):
    metric = information.get_comput_costs(dataset)
    flop, param, latency = metric['flops'], metric['params'], metric['latency']
    str1 = '{:14s} FLOP={:6.2f} M, Params={:.3f} MB, latency={:} ms.'.format(dataset, flop, param, '{:.2f}'.format(latency*1000) if latency is not None and latency > 0 else None)
    train_info = information.get_metrics(dataset, 'train')
    if dataset == 'cifar10-valid':
      valid_info = information.get_metrics(dataset, 'x-valid')
      str2 = '{:14s} train : [{:}], valid : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy']))
    elif dataset == 'cifar10':
      test__info = information.get_metrics(dataset, 'ori-test')
      str2 = '{:14s} train : [{:}], test  : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy']))
    else:
      valid_info = information.get_metrics(dataset, 'x-valid')
      test__info = information.get_metrics(dataset, 'x-test')
      str2 = '{:14s} train : [{:}], valid : [{:}], test : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy']))
    strings += [str1, str2]
  if show: print('\n'.join(strings))
  return strings

class NASBench102API(object):

  def __init__(self, file_path_or_dict, verbose=True):
    if isinstance(file_path_or_dict, str):
      if verbose: print('try to create the NAS-Bench-102 api from {:}'.format(file_path_or_dict))
      assert os.path.isfile(file_path_or_dict), 'invalid path : {:}'.format(file_path_or_dict)
      file_path_or_dict = torch.load(file_path_or_dict)
    elif isinstance(file_path_or_dict, dict):
      file_path_or_dict = copy.deepcopy( file_path_or_dict )
    else: raise ValueError('invalid type : {:} not in [str, dict]'.format(type(file_path_or_dict)))
    assert isinstance(file_path_or_dict, dict), 'It should be a dict instead of {:}'.format(type(file_path_or_dict))
    keys = ('meta_archs', 'arch2infos', 'evaluated_indexes')
    for key in keys: assert key in file_path_or_dict, 'Can not find key[{:}] in the dict'.format(key)
    self.meta_archs = copy.deepcopy( file_path_or_dict['meta_archs'] )
    self.arch2infos_less = OrderedDict()
    self.arch2infos_full = OrderedDict()
    for xkey in sorted(list(file_path_or_dict['arch2infos'].keys())):
      all_info = file_path_or_dict['arch2infos'][xkey]
      self.arch2infos_less[xkey] = ArchResults.create_from_state_dict( all_info['less'] )
      self.arch2infos_full[xkey] = ArchResults.create_from_state_dict( all_info['full'] )
    self.evaluated_indexes = sorted(list(file_path_or_dict['evaluated_indexes']))
    self.archstr2index = {}
    for idx, arch in enumerate(self.meta_archs):
      assert arch not in self.archstr2index, 'This [{:}]-th arch {:} already in the dict ({:}).'.format(idx, arch, self.archstr2index[arch])
      self.archstr2index[ arch ] = idx

  def __getitem__(self, index):
    return copy.deepcopy( self.meta_archs[index] )

  def __len__(self):
    return len(self.meta_archs)

  def __repr__(self):
    return ('{name}({num}/{total} architectures)'.format(name=self.__class__.__name__, num=len(self.evaluated_indexes), total=len(self.meta_archs)))

  def random(self):
    return random.randint(0, len(self.meta_archs)-1)

  def query_index_by_arch(self, arch):
    if isinstance(arch, str):
      if arch in self.archstr2index: arch_index = self.archstr2index[ arch ]
      else                         : arch_index = -1
    elif hasattr(arch, 'tostr'):
      if arch.tostr() in self.archstr2index: arch_index = self.archstr2index[ arch.tostr() ]
      else                                 : arch_index = -1
    else: arch_index = -1
    return arch_index

  def reload(self, archive_root, index):
    assert os.path.isdir(archive_root), 'invalid directory : {:}'.format(archive_root)
    xfile_path = os.path.join(archive_root, '{:06d}-FULL.pth'.format(index))
    assert 0 <= index < len(self.meta_archs), 'invalid index of {:}'.format(index)
    assert os.path.isfile(xfile_path), 'invalid data path : {:}'.format(xfile_path)
    xdata = torch.load(xfile_path)
    assert isinstance(xdata, dict) and 'full' in xdata and 'less' in xdata, 'invalid format of data in {:}'.format(xfile_path)
    self.arch2infos_less[index] = ArchResults.create_from_state_dict( xdata['less'] )
    self.arch2infos_full[index] = ArchResults.create_from_state_dict( xdata['full'] )

  def query_by_arch(self, arch, use_12epochs_result=False):
    if isinstance(arch, int):
      arch_index = arch
    else:
      arch_index = self.query_index_by_arch(arch)
    if arch_index == -1: return None # the following two lines are used to support few training epochs
    if use_12epochs_result: arch2infos = self.arch2infos_less
    else                  : arch2infos = self.arch2infos_full
    if arch_index in arch2infos:
      strings = print_information(arch2infos[ arch_index ], 'arch-index={:}'.format(arch_index))
      return '\n'.join(strings)
    else:
      print ('Find this arch-index : {:}, but this arch is not evaluated.'.format(arch_index))
      return None

  # query information with the training of 12 epochs or 200 epochs
  # else, return a dict with all trials on that dataset (the key is the seed)
  def query_by_index(self, arch_index, dataname=None, use_12epochs_result=False):
    if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less
    else                  : basestr, arch2infos = '200epochs', self.arch2infos_full
    assert arch_index in arch2infos, 'arch_index [{:}] does not in arch2info with {:}'.format(arch_index, basestr)
    archInfo = copy.deepcopy( arch2infos[ arch_index ] )
    if dataname is None: return archInfo
    else:
      assert dataname in archInfo.get_dataset_names(), 'invalid dataset-name : {:}'.format(dataname)
      info = archInfo.query(dataname)
      return info

  def query_meta_info_by_index(self, arch_index, use_12epochs_result=False):
    if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less
    else                  : basestr, arch2infos = '200epochs', self.arch2infos_full
    assert arch_index in arch2infos, 'arch_index [{:}] does not in arch2info with {:}'.format(arch_index, basestr)
    archInfo = copy.deepcopy( arch2infos[ arch_index ] )
    return archInfo

  def find_best(self, dataset, metric_on_set, FLOP_max=None, Param_max=None, use_12epochs_result=False):
    if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less
    else                  : basestr, arch2infos = '200epochs', self.arch2infos_full
    best_index, highest_accuracy = -1, None
    for i, idx in enumerate(self.evaluated_indexes):
      info = arch2infos[idx].get_comput_costs(dataset)
      flop, param, latency = info['flops'], info['params'], info['latency']
      if FLOP_max  is not None and flop  > FLOP_max : continue
      if Param_max is not None and param > Param_max: continue
      xinfo = arch2infos[idx].get_metrics(dataset, metric_on_set)
      loss, accuracy = xinfo['loss'], xinfo['accuracy']
      if best_index == -1:
        best_index, highest_accuracy = idx, accuracy
      elif highest_accuracy < accuracy:
        best_index, highest_accuracy = idx, accuracy
    return best_index, highest_accuracy

  # return the topology structure of the `index`-th architecture
  def arch(self, index):
    assert 0 <= index < len(self.meta_archs), 'invalid index : {:} vs. {:}.'.format(index, len(self.meta_archs))
    return copy.deepcopy(self.meta_archs[index])

  # obtain the trained weights of the `index`-th architecture on `dataset` with the seed of `seed`
  def get_net_param(self, index, dataset, seed, use_12epochs_result=False):
    if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less
    else                  : basestr, arch2infos = '200epochs', self.arch2infos_full
    archresult = arch2infos[index]
    return archresult.get_net_param(dataset, seed)

  # obtain the metric for the `index`-th architecture
  def get_more_info(self, index, dataset, iepoch=None, use_12epochs_result=False, is_random=True):
    if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less
    else                  : basestr, arch2infos = '200epochs', self.arch2infos_full
    archresult = arch2infos[index]
    if dataset == 'cifar10-valid':
      train_info = archresult.get_metrics(dataset, 'train'   , iepoch=iepoch, is_random=is_random)
      valid_info = archresult.get_metrics(dataset, 'x-valid' , iepoch=iepoch, is_random=is_random)
      try:
        test__info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random)
      except:
        test__info = None
      total      = train_info['iepoch'] + 1
      xifo = {'train-loss'    : train_info['loss'],
              'train-accuracy': train_info['accuracy'],
              'train-all-time': train_info['all_time'],
              'valid-loss'    : valid_info['loss'],
              'valid-accuracy': valid_info['accuracy'],
              'valid-all-time': valid_info['all_time'],
              'valid-per-time': None if valid_info['all_time'] is None else valid_info['all_time'] / total}
      if test__info is not None:
        xifo['test-loss']     = test__info['loss']
        xifo['test-accuracy'] = test__info['accuracy']
      return xifo
    else:
      train_info = archresult.get_metrics(dataset, 'train'   , iepoch=iepoch, is_random=is_random)
      if dataset == 'cifar10':
        test__info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random)
      else:
        test__info = archresult.get_metrics(dataset, 'x-test', iepoch=iepoch, is_random=is_random)
      try:
        valid_info = archresult.get_metrics(dataset, 'x-valid', iepoch=iepoch, is_random=is_random)
      except:
        valid_info = None
      xifo = {'train-loss'    : train_info['loss'],
              'train-accuracy': train_info['accuracy'],
              'test-loss'     : test__info['loss'],
              'test-accuracy' : test__info['accuracy']}
      if valid_info is not None:
        xifo['valid-loss'] = valid_info['loss']
        xifo['valid-accuracy'] = valid_info['accuracy']
      return xifo

  def show(self, index=-1):
    if index < 0: # show all architectures
      print(self)
      for i, idx in enumerate(self.evaluated_indexes):
        print('\n' + '-' * 10 + ' The ({:5d}/{:5d}) {:06d}-th architecture! '.format(i, len(self.evaluated_indexes), idx) + '-'*10)
        print('arch : {:}'.format(self.meta_archs[idx]))
        strings = print_information(self.arch2infos_full[idx])
        print('>' * 40 + ' 200 epochs ' + '>' * 40)
        print('\n'.join(strings))
        strings = print_information(self.arch2infos_less[idx])
        print('>' * 40 + '  12 epochs ' + '>' * 40)
        print('\n'.join(strings))
        print('<' * 40 + '------------' + '<' * 40)
    else:
      if 0 <= index < len(self.meta_archs):
        if index not in self.evaluated_indexes: print('The {:}-th architecture has not been evaluated or not saved.'.format(index))
        else:
          strings = print_information(self.arch2infos_full[index])
          print('>' * 40 + ' 200 epochs ' + '>' * 40)
          print('\n'.join(strings))
          strings = print_information(self.arch2infos_less[index])
          print('>' * 40 + '  12 epochs ' + '>' * 40)
          print('\n'.join(strings))
          print('<' * 40 + '------------' + '<' * 40)
      else:
        print('This index ({:}) is out of range (0~{:}).'.format(index, len(self.meta_archs)))

class ArchResults(object):

  def __init__(self, arch_index, arch_str):
    self.arch_index   = int(arch_index)
    self.arch_str     = copy.deepcopy(arch_str)
    self.all_results  = dict()
    self.dataset_seed = dict()
    self.clear_net_done = False

  def get_comput_costs(self, dataset):
    x_seeds = self.dataset_seed[dataset]
    results = [self.all_results[ (dataset, seed) ] for seed in x_seeds]

    flops      = [result.flop for result in results]
    params     = [result.params for result in results]
    lantencies = [result.get_latency() for result in results]
    lantencies = [x for x in lantencies if x > 0]
    mean_latency = np.mean(lantencies) if len(lantencies) > 0 else None
    time_infos = defaultdict(list)
    for result in results:
      time_info = result.get_times()
      for key, value in time_info.items(): time_infos[key].append( value )

    info = {'flops'  : np.mean(flops),
            'params' : np.mean(params),
            'latency': mean_latency}
    for key, value in time_infos.items():
      if len(value) > 0 and value[0] is not None:
        info[key] = np.mean(value)
      else: info[key] = None
    return info

  def get_metrics(self, dataset, setname, iepoch=None, is_random=False):
    x_seeds = self.dataset_seed[dataset]
    results = [self.all_results[ (dataset, seed) ] for seed in x_seeds]
    infos   = defaultdict(list)
    for result in results:
      if setname == 'train':
        info = result.get_train(iepoch)
      else:
        info = result.get_eval(setname, iepoch)
      for key, value in info.items(): infos[key].append( value )
    return_info = dict()
    if is_random:
      index = random.randint(0, len(results)-1)
      for key, value in infos.items(): return_info[key] = value[index]
    else:
      for key, value in infos.items():
        if len(value) > 0 and value[0] is not None:
          return_info[key] = np.mean(value)
        else: return_info[key] = None
    return return_info

  def show(self, is_print=False):
    return print_information(self, None, is_print)

  def get_dataset_names(self):
    return list(self.dataset_seed.keys())

  def get_net_param(self, dataset, seed=None):
    if seed is None:
      x_seeds = self.dataset_seed[dataset]
      return {seed: self.all_results[(dataset, seed)].get_net_param() for seed in x_seeds}
    else:
      return self.all_results[(dataset, seed)].get_net_param()

  def query(self, dataset, seed=None):
    if seed is None:
      x_seeds = self.dataset_seed[dataset]
      return {seed: self.all_results[ (dataset, seed) ] for seed in x_seeds}
    else:
      return self.all_results[ (dataset, seed) ]

  def arch_idx_str(self):
    return '{:06d}'.format(self.arch_index)

  def update(self, dataset_name, seed, result):
    if dataset_name not in self.dataset_seed:
      self.dataset_seed[dataset_name] = []
    assert seed not in self.dataset_seed[dataset_name], '{:}-th arch alreadly has this seed ({:}) on {:}'.format(self.arch_index, seed, dataset_name)
    self.dataset_seed[ dataset_name ].append( seed )
    self.dataset_seed[ dataset_name ] = sorted( self.dataset_seed[ dataset_name ] )
    assert (dataset_name, seed) not in self.all_results
    self.all_results[ (dataset_name, seed) ] = result
    self.clear_net_done = False

  def state_dict(self):
    state_dict = dict()
    for key, value in self.__dict__.items():
      if key == 'all_results': # contain the class of ResultsCount
        xvalue = dict()
        assert isinstance(value, dict), 'invalid type of value for {:} : {:}'.format(key, type(value))
        for _k, _v in value.items():
          assert isinstance(_v, ResultsCount), 'invalid type of value for {:}/{:} : {:}'.format(key, _k, type(_v))
          xvalue[_k] = _v.state_dict()
      else:
        xvalue = value
      state_dict[key] = xvalue
    return state_dict

  def load_state_dict(self, state_dict):
    new_state_dict = dict()
    for key, value in state_dict.items():
      if key == 'all_results': # to convert to the class of ResultsCount
        xvalue = dict()
        assert isinstance(value, dict), 'invalid type of value for {:} : {:}'.format(key, type(value))

      else: xvalue = value
      new_state_dict[key] = xvalue
    self.__dict__.update(new_state_dict)

  @staticmethod
  def create_from_state_dict(state_dict_or_file):
    x = ArchResults(-1, -1)
    if isinstance(state_dict_or_file, str): # a file path
      state_dict = torch.load(state_dict_or_file)
    elif isinstance(state_dict_or_file, dict):
      state_dict = state_dict_or_file
    else:
      raise ValueError('invalid type of state_dict_or_file : {:}'.format(type(state_dict_or_file)))
    x.load_state_dict(state_dict)
    return x

  def clear_params(self):
    for key, result in self.all_results.items():
      result.net_state_dict = None
    self.clear_net_done = True

  def __repr__(self):
    return ('{name}(arch-index={index}, arch={arch}, {num} runs, clear={clear})'.format(name=self.__class__.__name__, index=self.arch_index, arch=self.arch_str, num=len(self.all_results), clear=self.clear_net_done))

class ResultsCount(object):

  def __init__(self, name, state_dict, train_accs, train_losses, params, flop, arch_config, seed, epochs, latency):
    self.name           = name
    self.net_state_dict = state_dict
    self.train_acc1es = copy.deepcopy(train_accs)
    self.train_acc5es = None
    self.train_losses = copy.deepcopy(train_losses)
    self.train_times  = None
    self.arch_config  = copy.deepcopy(arch_config)
    self.params     = params
    self.flop       = flop
    self.seed       = seed
    self.epochs     = epochs
    self.latency    = latency
    # evaluation results
    self.reset_eval()

  def update_train_info(self, train_acc1es, train_acc5es, train_losses, train_times):
    self.train_acc1es = train_acc1es
    self.train_acc5es = train_acc5es
    self.train_losses = train_losses
    self.train_times  = train_times

  def reset_eval(self):
    self.eval_names  = []
    self.eval_acc1es = {}
    self.eval_times  = {}
    self.eval_losses = {}

  def update_latency(self, latency):
    self.latency = copy.deepcopy( latency )

  def update_eval(self, accs, losses, times):  # new version
    data_names = set([x.split('@')[0] for x in accs.keys()])
    for data_name in data_names:
      assert data_name not in self.eval_names, '{:} has already been added into eval-names'.format(data_name)
      self.eval_names.append( data_name )
      for iepoch in range(self.epochs):
        xkey = '{:}@{:}'.format(data_name, iepoch)
        self.eval_acc1es[ xkey ] = accs[ xkey ]
        self.eval_losses[ xkey ] = losses[ xkey ]
        self.eval_times [ xkey ] = times[ xkey ]

  def update_OLD_eval(self, name, accs, losses): # old version
    assert name not in self.eval_names, '{:} has already added'.format(name)
    self.eval_names.append( name )
    for iepoch in range(self.epochs):
      if iepoch in accs:
        self.eval_acc1es['{:}@{:}'.format(name,iepoch)] = accs[iepoch]
        self.eval_losses['{:}@{:}'.format(name,iepoch)] = losses[iepoch]

  def __repr__(self):
    num_eval = len(self.eval_names)
    set_name = '[' + ', '.join(self.eval_names) + ']'
    return ('{name}({xname}, arch={arch}, FLOP={flop:.2f}M, Param={param:.3f}MB, seed={seed}, {num_eval} eval-sets: {set_name})'.format(name=self.__class__.__name__, xname=self.name, arch=self.arch_config['arch_str'], flop=self.flop, param=self.params, seed=self.seed, num_eval=num_eval, set_name=set_name))

  def get_latency(self):
    if self.latency is None: return -1
    else: return sum(self.latency) / len(self.latency)

  def get_times(self):
    if self.train_times is not None and isinstance(self.train_times, dict):
      train_times = list( self.train_times.values() )
      time_info = {'T-train@epoch': np.mean(train_times), 'T-train@total': np.sum(train_times)}
      for name in self.eval_names:
        xtimes = [self.eval_times['{:}@{:}'.format(name,i)] for i in range(self.epochs)]
        time_info['T-{:}@epoch'.format(name)] = np.mean(xtimes)
        time_info['T-{:}@total'.format(name)] = np.sum(xtimes)
    else:
      time_info = {'T-train@epoch':                 None, 'T-train@total':               None }
      for name in self.eval_names:
        time_info['T-{:}@epoch'.format(name)] = None
        time_info['T-{:}@total'.format(name)] = None
    return time_info

  def get_eval_set(self):
    return self.eval_names

  def get_train(self, iepoch=None):
    if iepoch is None: iepoch = self.epochs-1
    assert 0 <= iepoch < self.epochs, 'invalid iepoch={:} < {:}'.format(iepoch, self.epochs)
    if self.train_times is not None:
      xtime = self.train_times[iepoch]
      atime = sum([self.train_times[i] for i in range(iepoch+1)])
    else: xtime, atime = None, None
    return {'iepoch'  : iepoch,
            'loss'    : self.train_losses[iepoch],
            'accuracy': self.train_acc1es[iepoch],
            'cur_time': xtime,
            'all_time': atime}

  def get_eval(self, name, iepoch=None):
    if iepoch is None: iepoch = self.epochs-1
    assert 0 <= iepoch < self.epochs, 'invalid iepoch={:} < {:}'.format(iepoch, self.epochs)
    if isinstance(self.eval_times,dict) and len(self.eval_times) > 0:
      xtime = self.eval_times['{:}@{:}'.format(name,iepoch)]
      atime = sum([self.eval_times['{:}@{:}'.format(name,i)] for i in range(iepoch+1)])
    else: xtime, atime = None, None
    return {'iepoch'  : iepoch,
            'loss'    : self.eval_losses['{:}@{:}'.format(name,iepoch)],
            'accuracy': self.eval_acc1es['{:}@{:}'.format(name,iepoch)],
            'cur_time': xtime,
            'all_time': atime}

  def get_net_param(self):
    return self.net_state_dict

  def get_config(self, str2structure):
    return {'name': 'infer.tiny', 'C': self.arch_config['channel'], \
            'N'   : self.arch_config['num_cells'], \
            'genotype': str2structure(self.arch_config['arch_str']), 'num_classes': self.arch_config['class_num']}

  def state_dict(self):
    _state_dict = {key: value for key, value in self.__dict__.items()}
    return _state_dict

  def load_state_dict(self, state_dict):
    self.__dict__.update(state_dict)

  @staticmethod
  def create_from_state_dict(state_dict):
    x = ResultsCount(None, None, None, None, None, None, None, None, None, None)
    x.load_state_dict(state_dict)
    return x


try:
        valid_info = archresult.get_metrics(dataset, 'x-valid', iepoch=iepoch, is_random=is_random)
      except:
        valid_info = None

# NAS-Bench-102: Extending the Scope of Reproducible Neural Architecture Search, ICLR 2020 #
# NAS-Bench-102-v1_0-e61699.pth : 6219 architectures are trained once, 1621 architectures are trained twice, 7785 architectures are trained three times. `LESS` only supports CIFAR10-VALID.
import os, sys, copy, random, torch, numpy as np
from collections import OrderedDict, defaultdict

def print_information(information, extra_info=None, show=False):
  dataset_names = information.get_dataset_names()
  strings = [information.arch_str, 'datasets : {:}, extra-info : {:}'.format(dataset_names, extra_info)]
  def metric2str(loss, acc):
    return 'loss = {:.3f}, top1 = {:.2f}%'.format(loss, acc)

  for ida, dataset in enumerate(dataset_names):
    metric = information.get_comput_costs(dataset)
    flop, param, latency = metric['flops'], metric['params'], metric['latency']
    str1 = '{:14s} FLOP={:6.2f} M, Params={:.3f} MB, latency={:} ms.'.format(dataset, flop, param, '{:.2f}'.format(latency*1000) if latency is not None and latency > 0 else None)
    train_info = information.get_metrics(dataset, 'train')
    if dataset == 'cifar10-valid':
      valid_info = information.get_metrics(dataset, 'x-valid')
      str2 = '{:14s} train : [{:}], valid : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy']))
    elif dataset == 'cifar10':
      test__info = information.get_metrics(dataset, 'ori-test')
      str2 = '{:14s} train : [{:}], test  : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy']))
    else:
      valid_info = information.get_metrics(dataset, 'x-valid')
      test__info = information.get_metrics(dataset, 'x-test')
      str2 = '{:14s} train : [{:}], valid : [{:}], test : [{:}]'.format(dataset, metric2str(train_info['loss'], train_info['accuracy']), metric2str(valid_info['loss'], valid_info['accuracy']), metric2str(test__info['loss'], test__info['accuracy']))
    strings += [str1, str2]
  if show: print('\n'.join(strings))
  return strings

class NASBench102API(object):

  def __init__(self, file_path_or_dict, verbose=True):
    if isinstance(file_path_or_dict, str):
      if verbose: print('try to create the NAS-Bench-102 api from {:}'.format(file_path_or_dict))
      assert os.path.isfile(file_path_or_dict), 'invalid path : {:}'.format(file_path_or_dict)
      file_path_or_dict = torch.load(file_path_or_dict)
    elif isinstance(file_path_or_dict, dict):
      file_path_or_dict = copy.deepcopy( file_path_or_dict )
    else: raise ValueError('invalid type : {:} not in [str, dict]'.format(type(file_path_or_dict)))
    assert isinstance(file_path_or_dict, dict), 'It should be a dict instead of {:}'.format(type(file_path_or_dict))
    keys = ('meta_archs', 'arch2infos', 'evaluated_indexes')
    for key in keys: assert key in file_path_or_dict, 'Can not find key[{:}] in the dict'.format(key)
    self.meta_archs = copy.deepcopy( file_path_or_dict['meta_archs'] )
    self.arch2infos_less = OrderedDict()
    self.arch2infos_full = OrderedDict()
    for xkey in sorted(list(file_path_or_dict['arch2infos'].keys())):
      all_info = file_path_or_dict['arch2infos'][xkey]
      self.arch2infos_less[xkey] = ArchResults.create_from_state_dict( all_info['less'] )
      self.arch2infos_full[xkey] = ArchResults.create_from_state_dict( all_info['full'] )
    self.evaluated_indexes = sorted(list(file_path_or_dict['evaluated_indexes']))
    self.archstr2index = {}
    for idx, arch in enumerate(self.meta_archs):
      assert arch not in self.archstr2index, 'This [{:}]-th arch {:} already in the dict ({:}).'.format(idx, arch, self.archstr2index[arch])
      self.archstr2index[ arch ] = idx

  def __getitem__(self, index):
    return copy.deepcopy( self.meta_archs[index] )

  def __len__(self):
    return len(self.meta_archs)

  def __repr__(self):
    return ('{name}({num}/{total} architectures)'.format(name=self.__class__.__name__, num=len(self.evaluated_indexes), total=len(self.meta_archs)))

  def random(self):
    return random.randint(0, len(self.meta_archs)-1)

  def query_index_by_arch(self, arch):
    if isinstance(arch, str):
      if arch in self.archstr2index: arch_index = self.archstr2index[ arch ]
      else                         : arch_index = -1
    elif hasattr(arch, 'tostr'):
      if arch.tostr() in self.archstr2index: arch_index = self.archstr2index[ arch.tostr() ]
      else                                 : arch_index = -1
    else: arch_index = -1
    return arch_index

  def reload(self, archive_root, index):
    assert os.path.isdir(archive_root), 'invalid directory : {:}'.format(archive_root)
    xfile_path = os.path.join(archive_root, '{:06d}-FULL.pth'.format(index))
    assert 0 <= index < len(self.meta_archs), 'invalid index of {:}'.format(index)
    assert os.path.isfile(xfile_path), 'invalid data path : {:}'.format(xfile_path)
    xdata = torch.load(xfile_path)
    assert isinstance(xdata, dict) and 'full' in xdata and 'less' in xdata, 'invalid format of data in {:}'.format(xfile_path)
    self.arch2infos_less[index] = ArchResults.create_from_state_dict( xdata['less'] )
    self.arch2infos_full[index] = ArchResults.create_from_state_dict( xdata['full'] )

  def query_by_arch(self, arch, use_12epochs_result=False):
    if isinstance(arch, int):
      arch_index = arch
    else:
      arch_index = self.query_index_by_arch(arch)
    if arch_index == -1: return None # the following two lines are used to support few training epochs
    if use_12epochs_result: arch2infos = self.arch2infos_less
    else                  : arch2infos = self.arch2infos_full
    if arch_index in arch2infos:
      strings = print_information(arch2infos[ arch_index ], 'arch-index={:}'.format(arch_index))
      return '\n'.join(strings)
    else:
      print ('Find this arch-index : {:}, but this arch is not evaluated.'.format(arch_index))
      return None

  # query information with the training of 12 epochs or 200 epochs
  # else, return a dict with all trials on that dataset (the key is the seed)
  def query_by_index(self, arch_index, dataname=None, use_12epochs_result=False):
    if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less
    else                  : basestr, arch2infos = '200epochs', self.arch2infos_full
    assert arch_index in arch2infos, 'arch_index [{:}] does not in arch2info with {:}'.format(arch_index, basestr)
    archInfo = copy.deepcopy( arch2infos[ arch_index ] )
    if dataname is None: return archInfo
    else:
      assert dataname in archInfo.get_dataset_names(), 'invalid dataset-name : {:}'.format(dataname)
      info = archInfo.query(dataname)
      return info

  def query_meta_info_by_index(self, arch_index, use_12epochs_result=False):
    if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less
    else                  : basestr, arch2infos = '200epochs', self.arch2infos_full
    assert arch_index in arch2infos, 'arch_index [{:}] does not in arch2info with {:}'.format(arch_index, basestr)
    archInfo = copy.deepcopy( arch2infos[ arch_index ] )
    return archInfo

  def find_best(self, dataset, metric_on_set, FLOP_max=None, Param_max=None, use_12epochs_result=False):
    if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less
    else                  : basestr, arch2infos = '200epochs', self.arch2infos_full
    best_index, highest_accuracy = -1, None
    for i, idx in enumerate(self.evaluated_indexes):
      info = arch2infos[idx].get_comput_costs(dataset)
      flop, param, latency = info['flops'], info['params'], info['latency']
      if FLOP_max  is not None and flop  > FLOP_max : continue
      if Param_max is not None and param > Param_max: continue
      xinfo = arch2infos[idx].get_metrics(dataset, metric_on_set)
      loss, accuracy = xinfo['loss'], xinfo['accuracy']
      if best_index == -1:
        best_index, highest_accuracy = idx, accuracy
      elif highest_accuracy < accuracy:
        best_index, highest_accuracy = idx, accuracy
    return best_index, highest_accuracy

  # return the topology structure of the `index`-th architecture
  def arch(self, index):
    assert 0 <= index < len(self.meta_archs), 'invalid index : {:} vs. {:}.'.format(index, len(self.meta_archs))
    return copy.deepcopy(self.meta_archs[index])

  # obtain the trained weights of the `index`-th architecture on `dataset` with the seed of `seed`
  def get_net_param(self, index, dataset, seed, use_12epochs_result=False):
    if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less
    else                  : basestr, arch2infos = '200epochs', self.arch2infos_full
    archresult = arch2infos[index]
    return archresult.get_net_param(dataset, seed)

  # obtain the metric for the `index`-th architecture
  def get_more_info(self, index, dataset, iepoch=None, use_12epochs_result=False, is_random=True):
    if use_12epochs_result: basestr, arch2infos = '12epochs' , self.arch2infos_less
    else                  : basestr, arch2infos = '200epochs', self.arch2infos_full
    archresult = arch2infos[index]
    if dataset == 'cifar10-valid':
      train_info = archresult.get_metrics(dataset, 'train'   , iepoch=iepoch, is_random=is_random)
      valid_info = archresult.get_metrics(dataset, 'x-valid' , iepoch=iepoch, is_random=is_random)
      try:
        test__info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random)
      except:
        test__info = None
      total      = train_info['iepoch'] + 1
      xifo = {'train-loss'    : train_info['loss'],
              'train-accuracy': train_info['accuracy'],
              'train-all-time': train_info['all_time'],
              'valid-loss'    : valid_info['loss'],
              'valid-accuracy': valid_info['accuracy'],
              'valid-all-time': valid_info['all_time'],
              'valid-per-time': None if valid_info['all_time'] is None else valid_info['all_time'] / total}
      if test__info is not None:
        xifo['test-loss']     = test__info['loss']
        xifo['test-accuracy'] = test__info['accuracy']
      return xifo
    else:
      train_info = archresult.get_metrics(dataset, 'train'   , iepoch=iepoch, is_random=is_random)
      if dataset == 'cifar10':
        test__info = archresult.get_metrics(dataset, 'ori-test', iepoch=iepoch, is_random=is_random)
      else:
        test__info = archresult.get_metrics(dataset, 'x-test', iepoch=iepoch, is_random=is_random)

      xifo = {'train-loss'    : train_info['loss'],
              'train-accuracy': train_info['accuracy'],
              'test-loss'     : test__info['loss'],
              'test-accuracy' : test__info['accuracy']}
      if valid_info is not None:
        xifo['valid-loss'] = valid_info['loss']
        xifo['valid-accuracy'] = valid_info['accuracy']
      return xifo

  def show(self, index=-1):
    if index < 0: # show all architectures
      print(self)
      for i, idx in enumerate(self.evaluated_indexes):
        print('\n' + '-' * 10 + ' The ({:5d}/{:5d}) {:06d}-th architecture! '.format(i, len(self.evaluated_indexes), idx) + '-'*10)
        print('arch : {:}'.format(self.meta_archs[idx]))
        strings = print_information(self.arch2infos_full[idx])
        print('>' * 40 + ' 200 epochs ' + '>' * 40)
        print('\n'.join(strings))
        strings = print_information(self.arch2infos_less[idx])
        print('>' * 40 + '  12 epochs ' + '>' * 40)
        print('\n'.join(strings))
        print('<' * 40 + '------------' + '<' * 40)
    else:
      if 0 <= index < len(self.meta_archs):
        if index not in self.evaluated_indexes: print('The {:}-th architecture has not been evaluated or not saved.'.format(index))
        else:
          strings = print_information(self.arch2infos_full[index])
          print('>' * 40 + ' 200 epochs ' + '>' * 40)
          print('\n'.join(strings))
          strings = print_information(self.arch2infos_less[index])
          print('>' * 40 + '  12 epochs ' + '>' * 40)
          print('\n'.join(strings))
          print('<' * 40 + '------------' + '<' * 40)
      else:
        print('This index ({:}) is out of range (0~{:}).'.format(index, len(self.meta_archs)))

class ArchResults(object):

  def __init__(self, arch_index, arch_str):
    self.arch_index   = int(arch_index)
    self.arch_str     = copy.deepcopy(arch_str)
    self.all_results  = dict()
    self.dataset_seed = dict()
    self.clear_net_done = False

  def get_comput_costs(self, dataset):
    x_seeds = self.dataset_seed[dataset]
    results = [self.all_results[ (dataset, seed) ] for seed in x_seeds]

    flops      = [result.flop for result in results]
    params     = [result.params for result in results]
    lantencies = [result.get_latency() for result in results]
    lantencies = [x for x in lantencies if x > 0]
    mean_latency = np.mean(lantencies) if len(lantencies) > 0 else None
    time_infos = defaultdict(list)
    for result in results:
      time_info = result.get_times()
      for key, value in time_info.items(): time_infos[key].append( value )

    info = {'flops'  : np.mean(flops),
            'params' : np.mean(params),
            'latency': mean_latency}
    for key, value in time_infos.items():
      if len(value) > 0 and value[0] is not None:
        info[key] = np.mean(value)
      else: info[key] = None
    return info

  def get_metrics(self, dataset, setname, iepoch=None, is_random=False):
    x_seeds = self.dataset_seed[dataset]
    results = [self.all_results[ (dataset, seed) ] for seed in x_seeds]
    infos   = defaultdict(list)
    for result in results:
      if setname == 'train':
        info = result.get_train(iepoch)
      else:
        info = result.get_eval(setname, iepoch)
      for key, value in info.items(): infos[key].append( value )
    return_info = dict()
    if is_random:
      index = random.randint(0, len(results)-1)
      for key, value in infos.items(): return_info[key] = value[index]
    else:
      for key, value in infos.items():
        if len(value) > 0 and value[0] is not None:
          return_info[key] = np.mean(value)
        else: return_info[key] = None
    return return_info

  def show(self, is_print=False):
    return print_information(self, None, is_print)

  def get_dataset_names(self):
    return list(self.dataset_seed.keys())

  def get_net_param(self, dataset, seed=None):
    if seed is None:
      x_seeds = self.dataset_seed[dataset]
      return {seed: self.all_results[(dataset, seed)].get_net_param() for seed in x_seeds}
    else:
      return self.all_results[(dataset, seed)].get_net_param()

  def query(self, dataset, seed=None):
    if seed is None:
      x_seeds = self.dataset_seed[dataset]
      return {seed: self.all_results[ (dataset, seed) ] for seed in x_seeds}
    else:
      return self.all_results[ (dataset, seed) ]

  def arch_idx_str(self):
    return '{:06d}'.format(self.arch_index)

  def update(self, dataset_name, seed, result):
    if dataset_name not in self.dataset_seed:
      self.dataset_seed[dataset_name] = []
    assert seed not in self.dataset_seed[dataset_name], '{:}-th arch alreadly has this seed ({:}) on {:}'.format(self.arch_index, seed, dataset_name)
    self.dataset_seed[ dataset_name ].append( seed )
    self.dataset_seed[ dataset_name ] = sorted( self.dataset_seed[ dataset_name ] )
    assert (dataset_name, seed) not in self.all_results
    self.all_results[ (dataset_name, seed) ] = result
    self.clear_net_done = False

  def state_dict(self):
    state_dict = dict()
    for key, value in self.__dict__.items():
      if key == 'all_results': # contain the class of ResultsCount
        xvalue = dict()
        assert isinstance(value, dict), 'invalid type of value for {:} : {:}'.format(key, type(value))
        for _k, _v in value.items():
          assert isinstance(_v, ResultsCount), 'invalid type of value for {:}/{:} : {:}'.format(key, _k, type(_v))
          xvalue[_k] = _v.state_dict()
      else:
        xvalue = value
      state_dict[key] = xvalue
    return state_dict

  def load_state_dict(self, state_dict):
    new_state_dict = dict()
    for key, value in state_dict.items():
      if key == 'all_results': # to convert to the class of ResultsCount
        xvalue = dict()
        assert isinstance(value, dict), 'invalid type of value for {:} : {:}'.format(key, type(value))
        for _k, _v in value.items():
          xvalue[_k] = ResultsCount.create_from_state_dict(_v)
      else: xvalue = value
      new_state_dict[key] = xvalue
    self.__dict__.update(new_state_dict)

  @staticmethod
  def create_from_state_dict(state_dict_or_file):
    x = ArchResults(-1, -1)
    if isinstance(state_dict_or_file, str): # a file path
      state_dict = torch.load(state_dict_or_file)
    elif isinstance(state_dict_or_file, dict):
      state_dict = state_dict_or_file
    else:
      raise ValueError('invalid type of state_dict_or_file : {:}'.format(type(state_dict_or_file)))
    x.load_state_dict(state_dict)
    return x

  def clear_params(self):
    for key, result in self.all_results.items():
      result.net_state_dict = None
    self.clear_net_done = True

  def __repr__(self):
    return ('{name}(arch-index={index}, arch={arch}, {num} runs, clear={clear})'.format(name=self.__class__.__name__, index=self.arch_index, arch=self.arch_str, num=len(self.all_results), clear=self.clear_net_done))

class ResultsCount(object):

  def __init__(self, name, state_dict, train_accs, train_losses, params, flop, arch_config, seed, epochs, latency):
    self.name           = name
    self.net_state_dict = state_dict
    self.train_acc1es = copy.deepcopy(train_accs)
    self.train_acc5es = None
    self.train_losses = copy.deepcopy(train_losses)
    self.train_times  = None
    self.arch_config  = copy.deepcopy(arch_config)
    self.params     = params
    self.flop       = flop
    self.seed       = seed
    self.epochs     = epochs
    self.latency    = latency
    # evaluation results
    self.reset_eval()

  def update_train_info(self, train_acc1es, train_acc5es, train_losses, train_times):
    self.train_acc1es = train_acc1es
    self.train_acc5es = train_acc5es
    self.train_losses = train_losses
    self.train_times  = train_times

  def reset_eval(self):
    self.eval_names  = []
    self.eval_acc1es = {}
    self.eval_times  = {}
    self.eval_losses = {}

  def update_latency(self, latency):
    self.latency = copy.deepcopy( latency )

  def update_eval(self, accs, losses, times):  # new version
    data_names = set([x.split('@')[0] for x in accs.keys()])
    for data_name in data_names:
      assert data_name not in self.eval_names, '{:} has already been added into eval-names'.format(data_name)
      self.eval_names.append( data_name )
      for iepoch in range(self.epochs):
        xkey = '{:}@{:}'.format(data_name, iepoch)
        self.eval_acc1es[ xkey ] = accs[ xkey ]
        self.eval_losses[ xkey ] = losses[ xkey ]
        self.eval_times [ xkey ] = times[ xkey ]

  def update_OLD_eval(self, name, accs, losses): # old version
    assert name not in self.eval_names, '{:} has already added'.format(name)
    self.eval_names.append( name )
    for iepoch in range(self.epochs):
      if iepoch in accs:
        self.eval_acc1es['{:}@{:}'.format(name,iepoch)] = accs[iepoch]
        self.eval_losses['{:}@{:}'.format(name,iepoch)] = losses[iepoch]

  def __repr__(self):
    num_eval = len(self.eval_names)
    set_name = '[' + ', '.join(self.eval_names) + ']'
    return ('{name}({xname}, arch={arch}, FLOP={flop:.2f}M, Param={param:.3f}MB, seed={seed}, {num_eval} eval-sets: {set_name})'.format(name=self.__class__.__name__, xname=self.name, arch=self.arch_config['arch_str'], flop=self.flop, param=self.params, seed=self.seed, num_eval=num_eval, set_name=set_name))

  def get_latency(self):
    if self.latency is None: return -1
    else: return sum(self.latency) / len(self.latency)

  def get_times(self):
    if self.train_times is not None and isinstance(self.train_times, dict):
      train_times = list( self.train_times.values() )
      time_info = {'T-train@epoch': np.mean(train_times), 'T-train@total': np.sum(train_times)}
      for name in self.eval_names:
        xtimes = [self.eval_times['{:}@{:}'.format(name,i)] for i in range(self.epochs)]
        time_info['T-{:}@epoch'.format(name)] = np.mean(xtimes)
        time_info['T-{:}@total'.format(name)] = np.sum(xtimes)
    else:
      time_info = {'T-train@epoch':                 None, 'T-train@total':               None }
      for name in self.eval_names:
        time_info['T-{:}@epoch'.format(name)] = None
        time_info['T-{:}@total'.format(name)] = None
    return time_info

  def get_eval_set(self):
    return self.eval_names

  def get_train(self, iepoch=None):
    if iepoch is None: iepoch = self.epochs-1
    assert 0 <= iepoch < self.epochs, 'invalid iepoch={:} < {:}'.format(iepoch, self.epochs)
    if self.train_times is not None:
      xtime = self.train_times[iepoch]
      atime = sum([self.train_times[i] for i in range(iepoch+1)])
    else: xtime, atime = None, None
    return {'iepoch'  : iepoch,
            'loss'    : self.train_losses[iepoch],
            'accuracy': self.train_acc1es[iepoch],
            'cur_time': xtime,
            'all_time': atime}

  def get_eval(self, name, iepoch=None):
    if iepoch is None: iepoch = self.epochs-1
    assert 0 <= iepoch < self.epochs, 'invalid iepoch={:} < {:}'.format(iepoch, self.epochs)
    if isinstance(self.eval_times,dict) and len(self.eval_times) > 0:
      xtime = self.eval_times['{:}@{:}'.format(name,iepoch)]
      atime = sum([self.eval_times['{:}@{:}'.format(name,i)] for i in range(iepoch+1)])
    else: xtime, atime = None, None
    return {'iepoch'  : iepoch,
            'loss'    : self.eval_losses['{:}@{:}'.format(name,iepoch)],
            'accuracy': self.eval_acc1es['{:}@{:}'.format(name,iepoch)],
            'cur_time': xtime,
            'all_time': atime}

  def get_net_param(self):
    return self.net_state_dict

  def get_config(self, str2structure):
    return {'name': 'infer.tiny', 'C': self.arch_config['channel'], \
            'N'   : self.arch_config['num_cells'], \
            'genotype': str2structure(self.arch_config['arch_str']), 'num_classes': self.arch_config['class_num']}

  def state_dict(self):
    _state_dict = {key: value for key, value in self.__dict__.items()}
    return _state_dict

  def load_state_dict(self, state_dict):
    self.__dict__.update(state_dict)

  @staticmethod
  def create_from_state_dict(state_dict):
    x = ResultsCount(None, None, None, None, None, None, None, None, None, None)
    x.load_state_dict(state_dict)
    return x


def __init__(self, func, proto):  # type: (Callable[..., Any], List[Optional[Union[ModelProto, NodeProto]]]) -> None

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from typing import Callable, Any, Union, List, Optional
from onnx import NodeProto, ModelProto

# A container that hosts the test function and the associated
# test item (ModelProto)

class TestItem(object):

self.func = func
        self.proto = proto


self.func = func
        self.proto = proto

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from typing import Callable, Any, Union, List, Optional
from onnx import NodeProto, ModelProto

# A container that hosts the test function and the associated
# test item (ModelProto)

class TestItem(object):
    def __init__(self, func, proto):  # type: (Callable[..., Any], List[Optional[Union[ModelProto, NodeProto]]]) -> None


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from typing import Callable, Any, Union, List, Optional
from onnx import NodeProto, ModelProto

# A container that hosts the test function and the associated
# test item (ModelProto)

class TestItem(object):
    def __init__(self, func, proto):  # type: (Callable[..., Any], List[Optional[Union[ModelProto, NodeProto]]]) -> None
        self.fu


from aliyunsdkcore.request import RpcRequest
from aliyunsdkhbase.endpoint import endpoint_data

class RenewInstanceRequest(RpcRequest):

RpcRequest.__init__(self, 'HBase', '2019-01-01', 'RenewInstance','hbase')
		self.set_method('POST')
		if hasattr(self, "endpoint_map"):
			setattr(self, "endpoint_map", endpoint_data.getEndpointMap())
		if hasattr(self, "endpoint_regional"):
			setattr(self, "endpoint_regional", endpoint_data.getEndpointRegional())

	def get_ClusterId(self):
		return self.get_query_params().get('ClusterId')

	def set_ClusterId(self,ClusterId):
		self.add_query_param('ClusterId',ClusterId)

	def get_Duration(self):
		return self.get_query_params().get('Duration')

	def set_Duration(self,Duration):
		self.add_query_param('Duration',Duration)

	def get_PricingCycle(self):
		return self.get_query_params().get('PricingCycle')

	def set_PricingCycle(self,PricingCycle):
		self.add_query_param('PricingCycle',PricingCycle)


from aliyunsdkcore.request import RpcRequest
from aliyunsdkhbase.endpoint import endpoint_data

class RenewInstanceRequest(RpcRequest):

	def __init__(self):
		RpcRequest.__init__(self, 'HBase', '2019-01-01', 'RenewInstance','hbase')
		self.set_method('POST')
		if hasattr(self, "endpoint_map"):
			setattr(self, "endpoint_map", endpoint_data.getEndpointMap())
		if hasattr(self, "endpoint_regional"):
			setattr(self, "endpoint_regional", endpoint_data.getEndpointRegional())

	def get_ClusterId(self):

	def set_ClusterId(self,ClusterId):
		self.add_query_param('ClusterId',ClusterId)

	def get_Duration(self):
		return self.get_query_params().get('Duration')

	def set_Duration(self,Duration):
		self.add_query_param('Duration',Duration)

	def get_PricingCycle(self):
		return self.get_query_params().get('PricingCycle')

	def set_PricingCycle(self,PricingCycle):
		self.add_query_param('PricingCycle',PricingCycle)


from aliyunsdkcore.request import RpcRequest
from aliyunsdkhbase.endpoint import endpoint_data

class RenewInstanceRequest(RpcRequest):

	def __init__(self):
		RpcRequest.__init__(self, 'HBase', '2019-01-01', 'RenewInstance','hbase')
		self.set_

		if hasattr(self, "endpoint_map"):
			setattr(self, "endpoint_map", endpoint_data.getEndpointMap())
		if hasattr(self, "endpoint_regional"):
			setattr(self, "endpoint_regional", endpoint_data.getEndpointRegional())

	def get_ClusterId(self):
		return self.get_query_params().get('ClusterId')

	def set_ClusterId(self,ClusterId):
		self.add_query_param('ClusterId',ClusterId)

	def get_Duration(self):
		return self.get_query_params().get('Duration')

	def set_Duration(self,Duration):
		self.add_query_param('Duration',Duration)

	def get_PricingCycle(self):
		return self.get_query_params().get('PricingCycle')

	def set_PricingCycle(self,PricingCycle):
		self.add_query_param('PricingCycle',PricingCycle)


"""
Tests for the test tools.
"""

from ..testtools import FakeDockerServer, AdderPlugin
from treq.client import HTTPClient
from twisted.internet import reactor
from twisted.trial.unittest import TestCase
from twisted.web.client import Agent
import json
import treq

class TestFakeDockerServer(TestCase):
    def setUp(self):
        self.dockerAPI = FakeDockerServer()
        self.dockerServer = reactor.listenTCP(0, self.dockerAPI)
        self.dockerPort = self.dockerServer.getHost().port
        self.agent = Agent(reactor) # no connectionpool
        self.client = HTTPClient(self.agent)

    def tearDown(self):
        return self.dockerServer.stopListening()

    def test_douglas_adams_would_be_proud(self):
        d = self.client.post('http://127.0.0.1:%d/towel' % (self.dockerPort,),
                      json.dumps({"hiding": "things"}),
                      headers={'Content-Type': ['application/json']})
        d.addCallback(treq.json_content)
        def verify(response):
            self.assertEqual(response,
                    {"hiding": "things", "SeenByFakeDocker": 42})
        d.addCallback(verify)
        return d

class TestAdderPlugin(TestCase):
    def _getAdder(self, *args, **kw):
        self.adderAPI = AdderPlugin(*args, **kw)
        self.adderServer = reactor.listenTCP(0, self.adderAPI)
        self.adderPort = self.adderServer.getHost().port

    def setUp(self):
        self.agent = Agent(reactor) # no connectionpool
        self.client = HTTPClient(self.agent)

    def tearDown(self):
        return self.adderServer.stopListening()

    def test_adder_explode(self):
        """
        The adder adapter blows up (sends an HTTP 500) when asked to.
        """
        self._getAdder(explode=True)
        d = self.client.post('http://127.0.0.1:%d/adapter' % (self.adderPort,),
                      json.dumps({}),
                      headers={'Content-Type': ['application/json']})
        def verifyResponseCode(response):
            self.assertEqual(response.code, 500)
            return response
        d.addCallback(verifyResponseCode)
        d.addCallback(treq.content)
        def verify(body):
            self.assertEqual(body, "sadness for you, today.")
        d.addCallback(verify)
        return d

    def test_adder_pre(self):
        """
        The adder pre-hook increments an integer according to the protocol
        defined in the README.
        """
        self._getAdder(pre=True)
        d = self.client.post('http://127.0.0.1:%d/adapter' % (self.adderPort,),
                      json.dumps({
                          "PowerstripProtocolVersion": 1,
                          "Type": "pre-hook",
                          "ClientRequest": {
                              "Method": "POST",
                              "Request": "/fictional",
                              "Body": json.dumps({"Number": 7})}}),
                      headers={'Content-Type': ['application/json']})
        def verifyResponseCode(response):
            self.assertEqual(response.code, 200)
            return response
        d.addCallback(verifyResponseCode)
        d.addCallback(treq.json_content)

self.assertEqual(json.loads(body["ModifiedClientRequest"]["Body"])["Number"], 8)
        d.addCallback(verify)
        return d

    def test_adder_post(self):
        """
        The adder post-hook increments an integer according to the protocol
        defined in the README.
        """
        self._getAdder(post=True)
        d = self.client.post('http://127.0.0.1:%d/adapter' % (self.adderPort,),
                      json.dumps({
                          "Type": "post-hook",
                          "ClientRequest": {
                              "Method": "POST",
                              "Request": "/fictional",
                              "Body": json.dumps({}),},
                          "ServerResponse": {
                              "ContentType": "application/json",
                              "Body": json.dumps({"Number": 7}),
                              "Code": 200,},
                          }),
                      headers={'Content-Type': ['application/json']})
        def verifyResponseCode(response):
            self.assertEqual(response.code, 200)
            return response
        d.addCallback(verifyResponseCode)
        d.addCallback(treq.json_content)
        def verify(body):
            self.assertEqual(json.loads(body["ModifiedServerResponse"]["Body"])["Number"], 8)
        d.addCallback(verify)
        return d


self.dockerAPI = FakeDockerServer()
        self.dockerServer = reactor.listenTCP(0, self.dockerAPI)
        self.dockerPort = self.dockerServer.getHost().port
        self.agent = Agent(reactor) # no connectionpool
        self.client = HTTPClient(self.agent)

"""
Tests for the test tools.
"""

from ..testtools import FakeDockerServer, AdderPlugin
from treq.client import HTTPClient
from twisted.internet import reactor
from twisted.trial.unittest import TestCase
from twisted.web.client import Agent
import json
import treq

class TestFakeDockerServer(TestCase):
    def setUp(self):

    def tearDown(self):
        return self.dockerServer.stopListening()

    def test_douglas_adams_would_be_proud(self):
        d = self.client.post('http://127.0.0.1:%d/towel' % (self.dockerPort,),
                      json.dumps({"hiding": "things"}),
                      headers={'Content-Type': ['application/json']})
        d.addCallback(treq.json_content)
        def verify(response):
            self.assertEqual(response,
                    {"hiding": "things", "SeenByFakeDocker": 42})
        d.addCallback(verify)
        return d

class TestAdderPlugin(TestCase):
    def _getAdder(self, *args, **kw):
        self.adderAPI = AdderPlugin(*args, **kw)
        self.adderServer = reactor.listenTCP(0, self.adderAPI)
        self.adderPort = self.adderServer.getHost().port

    def setUp(self):
        self.agent = Agent(reactor) # no connectionpool
        self.client = HTTPClient(self.agent)

    def tearDown(self):
        return self.adderServer.stopListening()

    def test_adder_explode(self):
        """
        The adder adapter blows up (sends an HTTP 500) when asked to.
        """
        self._getAdder(explode=True)
        d = self.client.post('http://127.0.0.1:%d/adapter' % (self.adderPort,),
                      json.dumps({}),
                      headers={'Content-Type': ['application/json']})
        def verifyResponseCode(response):
            self.assertEqual(response.code, 500)
            return response
        d.addCallback(verifyResponseCode)
        d.addCallback(treq.content)
        def verify(body):
            self.assertEqual(body, "sadness for you, today.")
        d.addCallback(verify)
        return d

    def test_adder_pre(self):
        """
        The adder pre-hook increments an integer according to the protocol
        defined in the README.
        """
        self._getAdder(pre=True)
        d = self.client.post('http://127.0.0.1:%d/adapter' % (self.adderPort,),
                      json.dumps({
                          "PowerstripProtocolVersion": 1,
                          "Type": "pre-hook",
                          "ClientRequest": {
                              "Method": "POST",
                              "Request": "/fictional",
                              "Body": json.dumps({"Number": 7})}}),
                      headers={'Content-Type': ['application/json']})
        def verifyResponseCode(response):
            self.assertEqual(response.code, 200)
            return response
        d.addCallback(verifyResponseCode)
        d.addCallback(treq.json_content)
        def verify(body):
            self.assertEqual(json.loads(body["ModifiedClientRequest"]["Body"])["Number"], 8)
        d.addCallback(verify)
        return d

    def test_adder_post(self):
        """
        The adder post-hook increments an integer according to the protocol
        defined in the README.
        """
        self._getAdder(post=True)
        d = self.client.post('http://127.0.0.1:%d/adapter' % (self.adderPort,),
                      json.dumps({
                          "Type": "post-hook",
                          "ClientRequest": {
                              "Method": "POST",
                              "Request": "/fictional",
                              "Body": json.dumps({}),},
                          "ServerResponse": {
                              "ContentType": "application/json",
                              "Body": json.dumps({"Number": 7}),
                              "Code": 200,},
                          }),
                      headers={'Content-Type': ['application/json']})
        def verifyResponseCode(response):
            self.assertEqual(response.code, 200)
            return response
        d.addCallback(verifyResponseCode)
        d.addCallback(treq.json_content)
        def verify(body):
            self.assertEqual(json.loads(body["ModifiedServerResponse"]["Body"])["Number"], 8)
        d.addCallback(verify)
        return d


"""
Tests for the test tools.
"""

from ..testtools import FakeDockerServer, AdderPlugin
from treq.client import HTTPClient
from twisted.internet import reactor
from twisted.trial.unittest import TestCase
from twisted.web.client import Agent
import json
import treq

class TestFakeDockerServer(TestCase):
    def setUp(self):
        self.dockerAPI = FakeDockerServer()
        self.dockerServer = reactor.listenTCP(0, self.dockerAPI)
        self.dockerPort = self.dockerServer.getHost().port
        self.agent = Agent(reactor) # no connectionpool
        self.client = HTTPClient(self.agent)

    def tearDown(self):
        return self.dockerServer.stopListening()

    def test_douglas_adams_would_be_proud(self):
        d = self.client.post('http://127.0.0.1:%d/towel' % (self.dockerPort,),
                      json.dumps({"hiding": "things"}),
                      headers={'Content-Type': ['application/json']})
        d.addCallback(treq.json_content)
        def verify(response):
            self.assertEqual(response,
                    {"hiding": "things", "SeenByFakeDocker": 42})
        d.addCallback(verify)
        return d

class TestAdderPlugin(TestCase):
    def _getAdder(self, *args, **kw):
        self.adderAPI = AdderPlugin(*args, **kw)
        self.adderServer = reactor.listenTCP(0, self.adderAPI)
        self.adderPort = self.adderServer.getHost().port

    def setUp(self):
        self.agent = Agent(reactor) # no connectionpool
        self.client = HTTPClient(self.agent)

    def tearDown(self):
        return self.adderServer.stopListening()

    def test_adder_explode(self):
        """
        The adder adapter blows up (sends an HTTP 500) when asked to.
        """
        self._getAdder(explode=True)
        d = self.client.post('http://127.0.0.1:%d/adapter' % (self.adderPort,),
                      json.dumps({}),
                      headers={'Content-Type': ['application/json']})
        def verifyResponseCode(response):
            self.assertEqual(response.code, 500)
            return response
        d.addCallback(verifyResponseCode)
        d.addCallback(treq.content)
        def verify(body):
            self.assertEqual(body, "sadness for you, today.")
        d.addCallback(verify)
        return d

    def test_adder_pre(self):
        """
        The adder pre-hook increments an integer according to the protocol
        defined in the README.
        """
        self._getAdder(pre=True)
        d = self.client.post('http://127.0.0.1:%d/adapter' % (self.adderPort,),
                      json.dumps({
                          "PowerstripProtocolVersion": 1,
                          "Type": "pre-hook",
                          "ClientRequest": {
                              "Method": "POST",
                              "Request": "/fictional",
                              "Body": json.dumps({"Number": 7})}}),
                      headers={'Content-Type': ['application/json']})
        def verifyResponseCode(response):
            self.assertEqual(response.code, 200)
            return response
        d.addCallback(verifyResponseCode)
        d.addCallback(treq.json_content)
        def verify(body):
            self.assertEqual(json.loads(body["ModifiedClientRequest"]["Body"])["Number"], 8)
        d.addCallback(verify)
        return d

    def test_adder_post(self):
        """
        The adder post-hook increments an integer according to the protocol
        defined in the README.
        """
        self._getAdder(post=True)
        d = self.client.post('http://127.0.0.1:%d/adapter' % (self.adderPort,),
                      json.dumps({
                          "Type": "post-hook",
                          "ClientRequest": {
                              "Method": "POST",
                              "Request": "/fictional",
                              "Body": json.dumps({}),},
                          "ServerResponse": {
                              "ContentType": "application/json",
                              "Body": json.dumps({"Number": 7}),
                              "Code": 200,},
                          }),
                      headers={'Content-Type': ['application/json']})
        def verifyResponseCode(response):
            self.assertEqual(res

            return response
        d.addCallback(verifyResponseCode)
        d.addCallback(treq.json_content)
        def verify(body):
            self.assertEqual(json.loads(body["ModifiedServerResponse"]["Body"])["Number"], 8)
        d.addCallback(verify)
        return d


import numpy as np

from ... import opcodes as OperandDef
from ..utils import infer_dtype
from .core import TensorBinOp
from .utils import arithmetic_operand

@arithmetic_operand
class TensorFloorDiv(TensorBinOp):
    _op_type_ = OperandDef.FLOORDIV
    _func_name = "floor_divide"

    @classmethod
    def _is_sparse(cls, x1, x2):
        if hasattr(x1, "issparse") and x1.issparse():
            if x2 != 0:
                return True
            else:
                raise ZeroDivisionError("float division by zero")
        return False

@infer_dtype(np.floor_divide)
def floordiv(x1, x2, out=None, where=None, **kwargs):
    """
    Return the largest integer smaller or equal to the division of the inputs.
    It is equivalent to the Python ``//`` operator and pairs with the
    Python ``%`` (`remainder`), function so that ``b = a % b + b * (a // b)``
    up to roundoff.

    Parameters
    ----------
    x1 : array_like
        Numerator.
    x2 : array_like
        Denominator.
    out : Tensor, None, or tuple of Tensor and None, optional
        A location into which the result is stored. If provided, it must have
        a shape that the inputs broadcast to. If not provided or `None`,
        a freshly-allocated array is returned. A tuple (possible only as a
        keyword argument) must have length equal to the number of outputs.
    where : array_like, optional
        Values of True indicate to calculate the ufunc at that position, values
        of False indicate to leave the value in the output alone.
    **kwargs

    Returns
    -------
    y : Tensor
        y = floor(`x1`/`x2`)

    See Also
    --------
    remainder : Remainder complementary to floor_divide.
    divmod : Simultaneous floor division and remainder.
    divide : Standard division.
    floor : Round a number to the nearest integer toward minus infinity.
    ceil : Round a number to the nearest integer toward infinity.

    Examples
    --------
    >>> import mars.tensor as mt

    >>> mt.floor_divide(7,3).execute()
    2
    >>> mt.floor_divide([1., 2., 3., 4.], 2.5).execute()
    array([ 0.,  0.,  1.,  1.])
    """
    op = TensorFloorDiv(**kwargs)
    return op(x1, x2, out=out, where=where)

@infer_dtype(np.floor_divide, reverse=True)

op = TensorFloorDiv(**kwargs)
    return op.rcall(x1, x2)


op = TensorFloorDiv(**kwargs)
    return op.rcall(x1, x2)

import numpy as np

from ... import opcodes as OperandDef
from ..utils import infer_dtype
from .core import TensorBinOp
from .utils import arithmetic_operand

@arithmetic_operand
class TensorFloorDiv(TensorBinOp):
    _op_type_ = OperandDef.FLOORDIV
    _func_name = "floor_divide"

    @classmethod
    def _is_sparse(cls, x1, x2):
        if hasattr(x1, "issparse") and x1.issparse():
            if x2 != 0:
                return True
            else:
                raise ZeroDivisionError("float division by zero")
        return False

@infer_dtype(np.floor_divide)
def floordiv(x1, x2, out=None, where=None, **kwargs):
    """
    Return the largest integer smaller or equal to the division of the inputs.
    It is equivalent to the Python ``//`` operator and pairs with the
    Python ``%`` (`remainder`), function so that ``b = a % b + b * (a // b)``
    up to roundoff.

    Parameters
    ----------
    x1 : array_like
        Numerator.
    x2 : array_like
        Denominator.
    out : Tensor, None, or tuple of Tensor and None, optional
        A location into which the result is stored. If provided, it must have
        a shape that the inputs broadcast to. If not provided or `None`,
        a freshly-allocated array is returned. A tuple (possible only as a
        keyword argument) must have length equal to the number of outputs.
    where : array_like, optional
        Values of True indicate to calculate the ufunc at that position, values
        of False indicate to leave the value in the output alone.
    **kwargs

    Returns
    -------
    y : Tensor
        y = floor(`x1`/`x2`)

    See Also
    --------
    remainder : Remainder complementary to floor_divide.
    divmod : Simultaneous floor division and remainder.
    divide : Standard division.
    floor : Round a number to the nearest integer toward minus infinity.
    ceil : Round a number to the nearest integer toward infinity.

    Examples
    --------
    >>> import mars.tensor as mt

    >>> mt.floor_divide(7,3).execute()
    2
    >>> mt.floor_divide([1., 2., 3., 4.], 2.5).execute()
    array([ 0.,  0.,  1.,  1.])
    """
    op = TensorFloorDiv(**kwargs)
    return op(x1, x2, out=out, where=where)

@infer_dtype(np.floor_divide, reverse=True)
def rfloordiv(x1, x2, **kwargs):


import numpy as np

from ... import opcodes as OperandDef
from ..utils import infer_dtype
from .core import TensorBinOp
from .utils import arithmetic_operand

@arithmetic_operand
class TensorFloorDiv(TensorBinOp):
    _op_type_ = OperandDef.FLOORDIV
    _func_name = "floor_divide"

    @classmethod
    def _is_sparse(cls, x1, x2):
        if hasattr(x1, "issparse") and x1.issparse():
            if x2 != 0:
                return True
            else:
                raise ZeroDivisionError("float division by zero")
        return False

@infer_dtype(np.floor_divide)
def floordiv(x1, x2, out=None, where=None, **kwargs):
    """
    Return the largest integer smaller or equal to the division of the inputs.
    It is equivalent to the Python ``//`` operator and pairs with the
    Python ``%`` (`remainder`), function so that ``b = a % b + b * (a // b)``
    up to roundoff.

    Parameters
    ----------
    x1 : array_like
        Numerator.
    x2 : array_like
        Denominator.
    out : Tensor, None, or tuple of Tensor and None, optional
        A location into which the result is stored. If provided, it must have
        a shape that the inputs broadcast to. If not provided or `None`,
        a freshly-allocated array is returned. A tuple (possible only as a
        keyword argument) must have length equal to the number of outputs.
    where : array_like, optional
        Values of True indicate to calculate the ufunc at that position, values
        of False indicate to leave the value in the output alone.
    **kwargs

    Returns
    -------
    y : Tensor
        y = floor(`x1`/`x2`)

    See Also
    --------
    remainder : Remainder complementary to floor_divide.
    divmod : Simultaneous floor division and remainder.
    divide : Standard division.
    floor : Round a number to the nearest integer toward minus infinity.
    ceil : Round a number to the nearest integer toward infinity.

    Examples
    --------
    >>> import mars.tensor as mt

    >>> mt.floor_divide(7,3).execute()
    2
    >>> mt.floor_divide([1., 2., 3., 4.], 2.5).execute()
    array([ 0.,  0.,  1.,  1.])
    """
    op = TensorFloorDiv(**kwargs)
    return op(x1, x2, out=out, where=where)

@infer_dtype(np.floor_divide, reverse=True)
def rfloordiv(x1, x2, **kwargs):
    op = TensorFloorDiv(*


    op = TensorFloorDiv(**kwargs)
    return op(x1, x2, out=out, where=where)

import numpy as np

from ... import opcodes as OperandDef
from ..utils import infer_dtype
from .core import TensorBinOp
from .utils import arithmetic_operand

@arithmetic_operand
class TensorFloorDiv(TensorBinOp):
    _op_type_ = OperandDef.FLOORDIV
    _func_name = "floor_divide"

    @classmethod
    def _is_sparse(cls, x1, x2):
        if hasattr(x1, "issparse") and x1.issparse():
            if x2 != 0:
                return True
            else:
                raise ZeroDivisionError("float division by zero")
        return False

@infer_dtype(np.floor_divide)
def floordiv(x1, x2, out=None, where=None, **kwargs):
    """
    Return the largest integer smaller or equal to the division of the inputs.
    It is equivalent to the Python ``//`` operator and pairs with the
    Python ``%`` (`remainder`), function so that ``b = a % b + b * (a // b)``
    up to roundoff.

    Parameters
    ----------
    x1 : array_like
        Numerator.
    x2 : array_like
        Denominator.
    out : Tensor, None, or tuple of Tensor and None, optional
        A location into which the result is stored. If provided, it must have
        a shape that the inputs broadcast to. If not provided or `None`,
        a freshly-allocated array is returned. A tuple (possible only as a
        keyword argument) must have length equal to the number of outputs.
    where : array_like, optional
        Values of True indicate to calculate the ufunc at that position, values
        of False indicate to leave the value in the output alone.
    **kwargs

    Returns
    -------
    y : Tensor
        y = floor(`x1`/`x2`)

    See Also
    --------
    remainder : Remainder complementary to floor_divide.
    divmod : Simultaneous floor division and remainder.
    divide : Standard division.
    floor : Round a number to the nearest integer toward minus infinity.
    ceil : Round a number to the nearest integer toward infinity.

    Examples
    --------
    >>> import mars.tensor as mt

    >>> mt.floor_divide(7,3).execute()
    2
    >>> mt.floor_divide([1., 2., 3., 4.], 2.5).execute()
    array([ 0.,  0.,  1.,  1.])
    """

@infer_dtype(np.floor_divide, reverse=True)
def rfloordiv(x1, x2, **kwargs):
    op = TensorFloorDiv(**kwargs)
    return op.rcall(x1, x2)


from ED6ScenarioHelper import *

def main():
    SetCodePage("ms932")

    # 柏斯

    CreateScenaFile(
        FileName            = 'T1511   ._SN',
        MapName             = 'Bose',
        Location            = 'T1511.x',
        MapIndex            = 1,
        MapDefaultBGM       = "ed60084",
        Flags               = 0,
        EntryFunctionIndex  = 0xFFFF,
        Reserved            = 0,
        IncludedScenario    = [
            '',
            '',
            '',
            '',
            '',
            '',
            '',
            ''
        ],
    )

    BuildStringList(
        '@FileName',                            # 8
        'Lenard',                               # 9
        'Sophina',                              # 10
        'Lloyd',                                # 11
        'Elke',                                 # 12
        'Anette',                               # 13
        'Olivier',                              # 14
        'Olivier',                              # 15
    )

    DeclEntryPoint(
        Unknown_00              = 0,
        Unknown_04              = 0,
        Unknown_08              = 6000,
        Unknown_0C              = 4,
        Unknown_0E              = 0,
        Unknown_10              = 0,
        Unknown_14              = 9500,
        Unknown_18              = -10000,
        Unknown_1C              = 0,
        Unknown_20              = 0,
        Unknown_24              = 0,
        Unknown_28              = 2800,
        Unknown_2C              = 262,
        Unknown_30              = 225,
        Unknown_32              = 0,
        Unknown_34              = 360,
        Unknown_36              = 0,
        Unknown_38              = 0,
        Unknown_3A              = 0,
        InitScenaIndex          = 0,
        InitFunctionIndex       = 0,
        EntryScenaIndex         = 0,
        EntryFunctionIndex      = 1,
    )

    AddCharChip(
        'ED6_DT07/CH01270 ._CH',             # 00
        'ED6_DT07/CH01690 ._CH',             # 01
        'ED6_DT07/CH01023 ._CH',             # 02
        'ED6_DT07/CH01180 ._CH',             # 03
        'ED6_DT07/CH01210 ._CH',             # 04
        'ED6_DT06/CH20050 ._CH',             # 05
    )

    AddCharChipPat(
        'ED6_DT07/CH01270P._CP',             # 00
        'ED6_DT07/CH01690P._CP',             # 01
        'ED6_DT07/CH01023P._CP',             # 02
        'ED6_DT07/CH01180P._CP',             # 03
        'ED6_DT07/CH01210P._CP',             # 04
        'ED6_DT06/CH20050P._CP',             # 05
    )

    DeclNpc(
        X                   = 24400,
        Z                   = 0,
        Y                   = 9200,
        Direction           = 0,
        Unknown2            = 0,
        Unknown3            = 0,
        ChipIndex           = 0x0,
        NpcIndex            = 0x101,
        InitFunctionIndex   = 0,
        InitScenaIndex      = 2,
        TalkFunctionIndex   = 0,
        TalkScenaIndex      = 4,
    )

    DeclNpc(
        X                   = 14000,
        Z                   = 0,
        Y                   = 3600,
        Direction           = 180,
        Unknown2            = 0,
        Unknown3            = 1,
        ChipIndex           = 0x1,
        NpcIndex            = 0x101,
        InitFunctionIndex   = 0,
        InitScenaIndex      = 2,
        TalkFunctionIndex   = 0,
        TalkScenaIndex      = 5,
    )

    DeclNpc(
        X                   = 49500,
        Z                   = 200,
        Y                   = 26230,
        Direction           = 90,
        Unknown2            = 0,
        Unknown3            = 2,
        ChipIndex           = 0x2,
        NpcIndex            = 0x155,
        InitFunctionIndex   = -1,
        InitScenaIndex      = -1,
        TalkFunctionIndex   = 0,
        TalkScenaIndex      = 8,
    )

    DeclNpc(
        X                   = 54500,
        Z                   = 0,
        Y                   = 3400,
        Direction           = 180,
        Unknown2            = 0,
        Unknown3            = 3,
        ChipIndex           = 0x3,
        NpcIndex            = 0x101,
        InitFunctionIndex   = 0,
        InitScenaIndex      = 2,
        TalkFunctionIndex   = 0,
        TalkScenaIndex      = 6,
    )

    DeclNpc(
        X                   = 49900,
        Z                   = 0,
        Y                   = 5800,
        Direction           = 135,
        Unknown2            = 0,
        Unknown3            = 4,
        ChipIndex           = 0x4,
        NpcIndex            = 0x101,
        InitFunctionIndex   = 0,
        InitScenaIndex      = 3,
        TalkFunctionIndex   = 0,
        TalkScenaIndex      = 7,
    )

    DeclNpc(
        X                   = 109100,
        Z                   = 600,
        Y                   = 5100,
        Direction           = 270,
        Unknown2            = 0,
        Unknown3            = 5,
        ChipIndex           = 0x5,
        NpcIndex            = 0x156,
        InitFunctionIndex   = -1,
        InitScenaIndex      = -1,
        TalkFunctionIndex   = -1,
        TalkScenaIndex      = -1,
    )

    DeclNpc(
        X                   = 110010,
        Z                   = -500,
        Y                   = 5150,
        Direction           = 0,
        Unknown2            = 0,
        Unknown3            = 5,
        ChipIndex           = 0x5,
        NpcIndex            = 0x156,
        InitFunctionIndex   = -1,
        InitScenaIndex      = -1,
        TalkFunctionIndex   = 0,
        TalkScenaIndex      = 9,
    )

    DeclActor(
        TriggerX            = 80610,
        TriggerZ            = 0,
        TriggerY            = 9100,
        TriggerRange        = 1400,
        ActorX              = 80610,
        ActorZ              = 1500,
        ActorY              = 9100,
        Flags               = 0x7C,
        TalkScenaIndex      = 0,
        TalkFunctionIndex   = 11,
        Unknown_22          = 0,
    )

    ScpFunction(
        "Function_0_1DE",          # 00, 0
        "Function_1_1ED",          # 01, 1
        "Function_2_1EE",          # 02, 2
        "Function_3_204",          # 03, 3
        "Function_4_228",          # 04, 4
        "Function_5_2B1",          # 05, 5
        "Function_6_341",          # 06, 6
        "Function_7_3D9",          # 07, 7
        "Function_8_48E",          # 08, 8
        "Function_9_67B",          # 09, 9
        "Function_10_6B9",         # 0A, 10
        "Function_11_EA8",         # 0B, 11
    )

    def Function_0_1DE(): pass

    label("Function_0_1DE")

    Jc((scpexpr(EXPR_TEST_SCENA_FLAGS, MakeScenarioFlags(0x7F, 2)), scpexpr(EXPR_END)), "loc_1EC")
    OP_A3(0x3FA)
    Event(0, 10)

    label("loc_1EC")

    Return()

    # Function_0_1DE end

    def Function_1_1ED(): pass

    label("Function_1_1ED")

    Return()

    # Function_1_1ED end

    def Function_2_1EE(): pass

    label("Function_2_1EE")

    Jc((scpexpr(EXPR_PUSH_LONG, 0x1), scpexpr(EXPR_END)), "loc_203")
    OP_99(0xFE, 0x0, 0x7, 0x5DC)
    Jump("Function_2_1EE")

    label("loc_203")

    Return()

    # Function_2_1EE end

    def Function_3_204(): pass

    label("Function_3_204")

    Jc((scpexpr(EXPR_PUSH_LONG, 0x1), scpexpr(EXPR_END)), "loc_227")
    OP_8D(0xFE, 50200, 5000, 54800, 6300, 2000)
    Jump("Function_3_204")

    label("loc_227")

    Return()

    # Function_3_204 end

    def Function_4_228(): pass

    label("Function_4_228")

    TalkBegin(0x8)

    ChrTalk(    #0
        0xFE,
        "Are you going out?\x02",
    )

    CloseMessageWindow()

    ChrTalk(    #1
        0xFE,
        (
            "If you're going to fish at night,\x01",
            "you're going to need an orbment\x01",
            "light or you won't be able to see.\x02",
        )
    )

    CloseMessageWindow()
    TalkEnd(0x8)
    Return()

    # Function_4_228 end

    def Function_5_2B1(): pass

    label("Function_5_2B1")

    TalkBegin(0x9)

    ChrTalk(    #2
        0xFE,
        (
            "That gentleman with you seems\x01",
            "to have drunk a lot. Is he going\x01",
            "to be all right?\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #3
        0xFE,
        (
            "If you would like, I can bring\x01",
            "you some water.\x02",
        )
    )

    CloseMessageWindow()
    TalkEnd(0x9)
    Return()

    # Function_5_2B1 end

    def Function_6_341(): pass

    label("Function_6_341")

    TalkBegin(0xB)

    ChrTalk(    #4
        0xFE,
        "Good evening.\x02",
    )

    CloseMessageWindow()

    ChrTalk(    #5
        0xFE,
        (
            "Seeing another group of lodgers\x01",
            "is something I enjoy.\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #6
        0xFE,
        (
            "I'd love to keep company with\x01",
            "you if that would be all right.\x02",
        )
    )

    CloseMessageWindow()
    TalkEnd(0xB)
    Return()

    # Function_6_341 end

pass

    label("Function_7_3D9")

    TalkBegin(0xC)

    ChrTalk(    #7
        0xFE,
        (
            "My mother seems to be\x01",
            "enjoying the atmosphere.\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #8
        0xFE,
        (
            "I was the first person to recommend\x01",
            "this inn to my mother.\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #9
        0xFE,
        (
            "Now she invites me to come\x01",
            "here with her every year.\x02",
        )
    )

    CloseMessageWindow()
    TalkEnd(0xC)
    Return()

    # Function_7_3D9 end

    def Function_8_48E(): pass

    label("Function_8_48E")

    TalkBegin(0xA)
    Jc((scpexpr(EXPR_TEST_SCENA_FLAGS, MakeScenarioFlags(0x0, 0)), scpexpr(EXPR_EQUZ), scpexpr(EXPR_END)), "loc_63C")
    OP_A2(0x0)
    SetMessageWindowPos(72, 320, 56, 3)
    FadeToDark(300, 0, 100)

    AnonymousTalk(    #10
        "\x07\x05Lloyd is staring at an open map. It appears to be a map of Valleria Lake.\x02",
    )

    CloseMessageWindow()
    OP_56(0x0)
    FadeToBright(300, 0)

    ChrTalk(    #11
        0xFE,
        (
            "There are hardly any structures\x01",
            "on the west side, and I didn't get\x01",
            "many bites either.\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #12
        0xFE,
        (
            "And all I'm getting on the east\x01",
            "side are small sized fish.\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #13
        0xFE,
        (
            "The Guardian probably won't appear\x01",
            "in either of these two places...\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #14
        0xFE,
        (
            "I guess the best thing I can\x01",
            "do is to continue fishing\x01",
            "from the shore.\x02",
        )
    )

    CloseMessageWindow()
    Jump("loc_677")

    label("loc_63C")

    ChrTalk(    #15
        0xFE,
        (
            "I'm going to catch the Guardian this\x01",
            "time for sure...\x02",
        )
    )

    CloseMessageWindow()

    label("loc_677")

    TalkEnd(0xA)
    Return()

    # Function_8_48E end

    def Function_9_67B(): pass

    label("Function_9_67B")

    TalkBegin(0xD)

    ChrTalk(    #16
        0xFE,
        (
            "Ugh... Schera...please...\x01",
            "I can't take another...\x02",
        )
    )

    CloseMessageWindow()
    TalkEnd(0xD)
    Return()

    # Function_9_67B end

    def Function_10_6B9(): pass

    label("Function_10_6B9")

    ClearMapFlags(0x1)
    EventBegin(0x0)
    AddParty(0x2, 0xFF)
    SetChrPos(0x101, 107680, 0, 5310, 90)
    SetChrPos(0x103, 109180, 0, 6400, 180)
    SetChrPos(0x102, 107620, 0, 6630, 135)
    OP_6D(107890, 0, 13120, 0)
    OP_A2(0x34E)
    OP_28(0x38, 0x1, 0x80)
    FadeToBright(2000, 0)
    OP_6D(109120, 0, 5740, 3000)

    ChrTalk(    #17
        0xE,
        (
            "#038F#6POhhh... Uggghhh...\x02\x03",

            "Uhhh... Gehhh...\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #18
        0x101,
        (
            "#007F#6POh, he's totally plastered.\x02\x03",

            "It looks like even a guy who takes his\x01",
            "sweet time for everything couldn't stand\x01",
            "up to a drunken Schera.\x02",
        )
    )

    CloseMessageWindow()
    OP_62(0x103, 0x0, 2000, 0x26, 0x27, 0xFA, 0x2)
    Sleep(1200)

    ChrTalk(    #19
        0x103,
        (
            "#021F#6POh, wow. What a night of drinking.\x02\x03",

            "I've been so busy lately I haven't\x01",
            "been able to enjoy myself like\x01",
            "this for a while.\x02",
        )
    )

    CloseMessageWindow()
    TurnDirection(0x102, 0x103, 200)

    ChrTalk(    #20
        0x102,
        (
            "#017FAnd you're not even red in the\x01",
            "face either from all that alcohol...\x02\x03",

            "#018FAre you sure you haven't had\x01",
            "some special kind of training,\x01",
            "Schera?\x02",
        )
    )

    CloseMessageWindow()
    TurnDirection(0x103, 0x102, 400)

    ChrTalk(    #21
        0x103,
        (
            "#020F#6PUm, it could have been all the\x01",
            "bizarre liquors I drank while\x01",
            "I was in the troupe.\x02\x03",

            "You know, like the ones with\x01",
            "scorpions and asps in them.\x02\x03",

            "#021FI might have built up my resistance\x01",
            "that way, but who knows.\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #22
        0x102,
        (
            "#017FSomehow...I don't think that that's\x01",
            "the case.\x02",
        )
    )

    CloseMessageWindow()
    TurnDirection(0x101, 0x103, 400)

    ChrTalk(    #23
        0x101,
        (
            "#009F#6PBy the way, what do you plan on\x01",
            "doing with him? He's pretty much\x01",
            "useless as he is.\x02",
        )
    )

    CloseMessageWindow()
    TurnDirection(0x103, 0x101, 400)

    ChrTalk(    #24
        0x103,
        (
            "#026F#6PLet's just let him sleep. He looks\x01",
            "so peaceful now, and we wouldn't\x01",
            "want to disturb him.\x02\x03",

            "#022FThere's a very high possibility\x01",
            "that we'll have a direct encounter\x01",
            "with the sky bandits tonight.\x02\x03",

            "And getting a civilian wrapped up\x01",
            "in the middle of it all wouldn't\x01",
            "be a good idea.\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #25
        0x101,
        (
            "#004F#6PDon't tell me you...\x02\x03",

            "You got Olivier drunk so he wouldn't\x01",
            "be able to come along, didn't you?\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #26
        0x103,
        (
            "#023F#6PWell...\x02\x03",

            "...\x02\x03",

            "#021FOf course I did. And he'll thank\x01",
            "me in the long run, too. After\x01",
            "his raging hangover, anyway...\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #27
        0x101,
        "#509F#6PAnd so that whole time...\x02",
    )

    CloseMessageWindow()

    ChrTalk(    #28
        0x102,
        (
            "#018FYou were just toying with him,\x01",
            "weren't you?\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #29
        0x103,
        (
            "#026F#6PLet's see... It's getting late.\x02\x03",

            "Let's hurry and begin our stakeout\x01",
            "around the inn.\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #30
        0x101,
        (
            "#507F#6PDon't skirt around the issue,\x01",
            "Schera.\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #31
        0x103,
        (
            "#022F#6PQuiet, you!\x02\x03",

            "For the time being, we're going\x01",
            "to circle up to the far pier.\x02",
        )
    )

    CloseMessageWindow()

    ChrTalk(    #32
        0x102,
        "#010FUnderstood.\x02",
    )

    CloseMessageWindow()

    ChrTalk(    #33
        0x101,
        "#006F#6PAll right then, let's go!\x02",
    )

    CloseMessageWindow()
    FadeToDark(1000, 0, -1)
    OP_0D()
    SetChrPos(0x101, 107480, 0, 9560, 0)
    SetChrPos(0x103, 107480, 0, 9560, 0)
    SetChrPos(0x102, 107480, 0, 9560, 0)
    OP_6D(107480, 0, 9560, 0)
    Sleep(500)
    FadeToBright(1000, 0)
    EventEnd(0x0)
    ClearMapFlags(0x10000000)
    Return()

    # Function_10_6B9 end

    def Function_11_EA8(): pass

    label("Function_11_EA8")

    FadeToDark(300, 0, 100)
    SetMessageWindowPos(72, 320, 56, 3)
    SetChrName("")

    AnonymousTalk(    #34
        "\x07\x05There are some fishing rods propped against the rack.\x02",
    )

    CloseMessageWindow()
    OP_56(0x0)
    SetMessageWindowPos(72, 320, 56, 3)
    FadeToBright(300, 0)
    TalkEnd(0xFF)
    Return()

    # Function_11_EA8 end

    SaveToFile()

Try(main)