text: #! /usr/bin/env python
  # -*- coding: utf-8 -*-
  
  ###################################################################
  # *.cdb から YAML形式の定数ファイルと Godotの定数スクリプトを生成する
  # code-snippetsも出力する
  ###################################################################
  
  import os
  import sys
  import re
  import glob
  import json
  
  ROOT = os.path.abspath(os.path.dirname(__file__)).replace("¥¥", "/")
  # 定数スクリプトのパス
  PATH_CONST_SCRIPT = ROOT + "/../../TestAdv/src/common/adv/Adv.gd"
  # code-snippetsのパス
  PATH_CONST_SNIPPETS = ROOT + "/../.vscode/consts.code-snippets"
  
  def usage():
  	print("Usage: _convCdbHeader.py [dat.cdb]")
  
  DEFTYPE_CONST = 0
  DEFTYPE_ENUM  = 1
  DEFTYPE_MACRO = 2
  
  # 定数データ (code-snippets用).
  class ConstData:
  	def __init__(self, name, comment):
  		# コンストラクタ
  		self.name    = name    # 関数名
  		self.comment = comment # コメント
  		
  	def to_body(self):
  		str = self.name
  		
  		return str
  	
  	def to_string(self):
  		# JSON文字列に変換する
  		body = self.to_body()
  		name = self.comment
  		if name == "":
  			name = self.name
  		
  		str = """	"%s":
  	{
  		"prefix": "%s",
  		"body": "%s",
  		"description": "%s",
  	},"""%(name, self.name, body, self.comment)
  		return str
  
  # 定数のデータ.
  class DefineData:
  	def __init__(self, key, value, comment):
  			self.key     = key
  			self.value   = value
  			self.comment = comment
  
  # 定数データのマップ.
  class DefineMap:
  	def __init__(self, deftype, name, enum, comment, is_snippets):
  		self.deftype = deftype
  		self.name = name # CDB・YAMLでの名称
  		self.enum = enum # GMLでの enum名
  		self.comment = comment
  		self.is_snippets = is_snippets # code-snippets に名前空間を出力するかどうか
  		self.data = {}
  	
  	def set(self, json, idx):
  		key = json["id"]
  		value = idx
  		if "value" in json:
  			value = json["value"] # "value" が存在すればその値を使う
  		comment = ""
  		if "comment" in json:
  			comment = json["comment"] # コメントは存在する場合のみ取得
  		elif "name" in json:
  			comment = json["name"] # "name" コメント対応
  		d = DefineData(key, value, comment)
  		self.data[key] = d
  		
  	def get(self, key):
  		return self.data[key]
  
  # 定数データ管理.
  class DefineMgr:
  	def __init__(self, cdb, root):
  		self.cdb  = cdb
  		self.root = root
  		self.pool = {}
  	def add(self, deftype, name, enum, comment, is_snippets=False):
  		map = DefineMap(deftype, name, enum, comment, is_snippets)
  		self.pool[name] = map
  		return map
  	def has(self, key):
  		return key in self.pool
  	def get(self, key):
  		return self.pool[key]
  		
  	def write(self):
  		self.writeYAML()
  		self.writeGD()
  		self.writeSnippets()
  	
  	def writeYAML(self):
  		fOut = self.root + "/common/const_header.txt"
  		
  		writer = Writer()
  		# 注意書き
  		writer.write("############################")
  		writer.write("# Generated by '%s'"%os.path.basename(self.cdb))
  		writer.write("# This file is READ-ONLY")
  		writer.write("############################")
  		writer.write("")
  		
  		for k, v in self.pool.items():
  			if v.deftype == DEFTYPE_MACRO:
  				continue # マクロ場合は YAML に書き出さない
  			
  			writer.write("# %s"%v.comment)
  			writer.write("%s:"%v.name)
  			for k2, v2 in v.data.items():
  				s = "%s: %s"%(k2, v2.value)
  				if len(v2.comment):
  					# コメントあり
  					s += " # %s"%v2.comment
  				writer.write(s, 1)
  			writer.write("")
  		
  		f = open(fOut, "w", encoding='utf_8')
  		f.write(writer.buf)
  		f.close()
  		
  	def writeGD(self):
  		fOut = PATH_CONST_SCRIPT
  		
  		# GML自動生成.
  		writer = Writer()
  		writer.write("############################")
  		writer.write("# Generated by '%s'"%os.path.basename(self.cdb))
  		writer.write("# This file is READ-ONLY")
  		writer.write("############################")
  		writer.write("extends Node")
  		writer.write("class_name Adv")
  		
  		for k, v in self.pool.items():
  			writer.write("# %s"%v.comment)
  			is_macro = (v.deftype == DEFTYPE_MACRO) # マクロかどうか
  			
  			if is_macro:
  				# macro
  				for k2, v2 in v.data.items():
  					s = "const %s = %s"%(k2, v2.value)
  					if len(v2.comment) > 0:
  						# コメントあり
  						s += " # %s"%v2.comment
  					writer.write(s)
  				
  			else:
  				# enum
  				writer.write("enum %s {"%v.enum)
  			
  				# データ書き出し
  				for k2, v2 in v.data.items():
  					s = "%s = %s,"%(k2, v2.value)
  					if len(v2.comment) > 0:
  						# コメントあり
  						s += " # %s"%v2.comment
  					writer.write(s, 1)
  				
  				# enum終了
  				writer.write("}")
  				
  			writer.write("")
  		
  		f = open(fOut, "w", encoding='utf_8')
  		f.write(writer.buf)
  		f.close()
  
  	def writeSnippets(self):
  		# code-snippetsの出力.
  		fOut = PATH_CONST_SNIPPETS
  		writer = Writer()
  		writer.write("{", 0)
  
  		for k, v in self.pool.items():
  			if v.deftype == DEFTYPE_MACRO:
  				continue # マクロ場合は code-snippets に書き出さない
  
  			for k2, v2 in v.data.items():
  				name = k2
  				if v.is_snippets: # 名前空間をつけて出力する.
  					name = v.enum + "." + name # 名前空間追加.
  
  				comment = ""
  				if len(v2.comment) > 0:
  					# コメントあり
  					comment = v2.comment
  				const = ConstData(name, comment)
  				writer.write(const.to_string())
  		writer.write("}\n", 0)
  		f = open(fOut, "w", encoding='utf_8')
  		f.write(writer.buf)
  		f.close()
  
  # ファイル書き込み.
  class Writer:
  	def __init__(self):
  		self.buf = ""
  	def write(self, line, tab=0):
  		for i in range(tab):
  			self.buf += "  "
  		self.buf += "%s\n"%line
  	def writeKeyValue(self, key, value, comment, tab=0):
  		self.write("%s: %s # %s"%(key, value, comment), tab)
  
  def execute(cdb, root):
  	f = open(cdb, "r", encoding='utf_8')
  	jsonStr = f.read()
  	f.close()
  	jsonDict = json.loads(jsonStr)
  	
  	mgr = DefineMgr(cdb, root)
  	mgr.add(DEFTYPE_MACRO, "macros", "", "マクロ")
  	mgr.add(DEFTYPE_CONST, "consts", "eConst", "定数")
  	mgr.add(DEFTYPE_CONST, "sysbits", "eSys", "システムフラグ", True)
  	mgr.add(DEFTYPE_CONST, "bits", "eBit", "フラグ")
  	mgr.add(DEFTYPE_CONST, "vars", "eVar", "変数")
  	mgr.add(DEFTYPE_CONST, "items", "eItem", "アイテム")
  	mgr.add(DEFTYPE_CONST, "scenes", "eScene", "シーン", True)
  	#mgr.add(DEFTYPE_ENUM, "ability", "eAbility", "能力")
  	
  	for dat in jsonDict["sheets"]:
  		name = dat["name"]
  		if mgr.has(name):
  			defines = mgr.get(name)
  			for idx, line in enumerate(dat["lines"]):
  				defines.set(line, idx)
  	
  	mgr.write()
  	
  	print("************************")
  	print("output: item_header.txt")
  	print("************************")
  
  def main(cdb):
  	# ルートディレクトリ取得
  	root = os.path.dirname(os.path.abspath(__file__))
  	execute(cdb, root)
  
  if __name__ == '__main__':
  	args = sys.argv
  	argc = len(sys.argv)
  	if argc < 2:
  		# 引数が足りない
  		print(args)
  		print("Error: Not enough parameter. given=%d require=%d"%(argc, 2))
  		usage()
  		quit()
  
  	# アイテム.cdb
  	cdb = args[1]
  
  	main(cdb)
  