MENU閉じる

HEXA BLOG

プログラム

HEXA BLOGプログラム2017.9.8

敵とか武器とかアイテムとか その3

黒くてしゅわしゅわしてて甘くて美味しいあの飲み物

そう、コーラ

幸せを分け合うときには欠かせないですよね

そんなコーラを毎日2㍑飲む生活をはじめました

こんにちは、だっちです

 

先日プレゼントに貰ったコーラ24㍑があるので、

仕事をしながら飲んでいるといつの間にかペットボトルが空に…なんて日々を送っています。

健康のためには少し自制しないといけませんね

 

 

さて、前回に引き続きExcelで作成したデータから、

ゲーム内で扱いやすい形に変換するためのプログラムを実装していこうと思います。

 

前回は「型を生成するために必要な情報」を読み出すところまで出来たので、

今回は「クラスファイルの生成」をしていきたいと思います。

 

前回作成したプログラムを改良して、クラスファイルを生成していきます。

コードはこんな感じです。

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using NPOI.SS.UserModel;

namespace NPOITest
{
	class Program
	{
		// クラス情報
		private class ClassInfo
		{
			public string						name					{ get; }		//!< クラス名
			public string						desc					{ get; }		//!< クラス説明
			public List		memberVariableInfos		{ get; }		//!< メンバ変数情報

			// @brief	コンストラクタ
			// @param	[in]	name					クラス名
			// @param	[in]	desc					クラス説明
			// @param	[in]	memberVariableInfos		メンバ変数情報
			public ClassInfo(string name, string desc, List memberVariableInfos)
			{
				this.name					= name;
				this.desc					= desc;
				this.memberVariableInfos	= memberVariableInfos;
			}
		}

		// メンバ変数情報
		private class MemberVariableInfo
		{
			public string		name		{ get; }		//!< 変数名
			public string		type		{ get; }		//!< 型
			public string		desc		{ get; }		//!< 変数説明

			// @brief	コンストラクタ
			// @param	[in]	name	変数名
			// @param	[in]	type	型
			// @param	[in]	desc	変数説明
			public MemberVariableInfo(string name, string type, string desc)
			{
				this.name	= name;
				this.type	= type;
				this.desc	= desc;
			}
		}

		private const string	TYPEDEF_SHEET_NAME			= "typedef";		//!< 「型情報定義」シート名

		private const int		DATA_NAME_ROW				= 0;				//!< データ名行
		private const int		DATA_NAME_CELL				= 1;				//!< データ名列

		private const int		DATA_DESC_ROW				= 1;				//!< データ説明行
		private const int		DATA_DESC_CELL				= 1;				//!< データ説明列

		private const int		MEMBER_VARIABLE_START_ROW	= 10;				//!< メンバ変数開始行
		private const int		MEMBER_VARIABLE_NAME_CELL	= 1;				//!< メンバ変数名列
		private const int		MEMBER_VARIABLE_TYPE_CELL	= 2;				//!< メンバ変数型列
		private const int		MEMBER_VARIABLE_DESC_CELL	= 3;				//!< メンバ変数説明列
		private const int		MEMBER_VARIABLE_MAX			= 1024;				//!< メンバ変数最大許容数

		// @brief	エントリポイント
		public static void Main(string[] args)
		{
			// エクセルファイル入力受付
			Console.Write("Please input excel file path : ");
			var srcPath = Console.ReadLine();

			// 読み込み
			ClassInfo classInfo = null;
			readExcelFile(srcPath, out classInfo);

			// クラスファイル書き出し先入力受付
			Console.Write("Please input class file output directory : ");
			var outDirectory = Console.ReadLine();

			// 書き出し
			writeClassFile(outDirectory, classInfo);
		}

		// @brief	エクセルファイルの読み込み
		// @param	[in]	srcPath		読み込みファイル名
		// @param	[out]	classInfo	クラス情報
		// @return	なし
		private static void readExcelFile(string srcPath, out ClassInfo classInfo)
		{
			classInfo = null;

			// ファイル存在確認
			if( !File.Exists(srcPath) ) {
				Console.WriteLine("file not exists.");
				return;
			}

			var className			= string.Empty;
			var classDesc			= string.Empty;
			var memberVariableInfos	= new List();
			using( var fs = new FileStream(srcPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite) ) {
				var workbook = WorkbookFactory.Create(fs);

				// 中にあるシートを順番に取得
				foreach( ISheet sheet in workbook ) {
					if( sheet == null ) continue;

					// シート名表示
					Console.WriteLine("	Name : " + sheet.SheetName);

					// シートの名前が「型情報定義」シート名だったら、型情報を読み込み
					if( sheet.SheetName == TYPEDEF_SHEET_NAME ) {
						Console.WriteLine();

						Console.WriteLine("Data");
						// データ名を取得
						className = getCellValue(sheet, DATA_NAME_ROW, DATA_NAME_CELL);
						if( string.IsNullOrWhiteSpace(className) ) {
							Console.WriteLine("DataName acquisition failed...");
						}
						else {
							Console.WriteLine("	Name : " + className);
						}

						// データ説明を取得
						classDesc = getCellValue(sheet, DATA_DESC_ROW, DATA_DESC_CELL);
						if( string.IsNullOrWhiteSpace(classDesc) ) {
							Console.WriteLine("DataDesc acquisition failed...");
						}
						else {
							Console.WriteLine("	Desc : " + classDesc);
						}

						// メンバ変数を取得
						Console.WriteLine("MemberVariables");
						for( int i = 0, row = MEMBER_VARIABLE_START_ROW; i < MEMBER_VARIABLE_MAX; ++i, ++row ) {
							// メンバ変数名を取得
							var memberName = getCellValue(sheet, row, MEMBER_VARIABLE_NAME_CELL);
							if( string.IsNullOrWhiteSpace(memberName) ) {
								Console.WriteLine("MemberName acquisition failed...");
								// メンバ変数名が空欄だったら終了と判断
								Console.WriteLine("End Of Member Variables");
								break;
							}

							Console.WriteLine("	[" + i + "]");
							Console.WriteLine("		Name : " + memberName);

							// メンバ変数型を取得
							var memberType = getCellValue(sheet, row, MEMBER_VARIABLE_TYPE_CELL);
							if( string.IsNullOrWhiteSpace(memberType) ) {
								// メンバ変数名が空欄だったら終了と判断
								Console.WriteLine("MemberType acquisition failed...");
							}
							else {
								Console.WriteLine("		Type : " + memberType);
							}

							// メンバ変数説明を取得
							var memberDesc = getCellValue(sheet, row, MEMBER_VARIABLE_DESC_CELL);
							if( string.IsNullOrWhiteSpace(memberDesc) ) {
								// メンバ変数名が空欄だったら終了と判断
								Console.WriteLine("MemberDesc acquisition failed...");
							}
							else {
								Console.WriteLine("		Desc : " + memberDesc);
							}

							memberVariableInfos.Add(new MemberVariableInfo(memberName, memberType, memberDesc));
						}
					}
				}
			}

			classInfo = new ClassInfo(className, classDesc, memberVariableInfos);
		}

		// @brief	クラスファイルの書き出し
		// @param	[in]	outDirectory	書き出し先ディレクトリ
		// @param	[in]	classInfo		クラス情報
		// @return	なし
		private static void writeClassFile(string outDirectory, ClassInfo classInfo)
		{
			// 入力情報が不正なら終了
			if( string.IsNullOrWhiteSpace(outDirectory) ) {
				Console.WriteLine("outDirectory is invalid....");
				return;
			}
			if( classInfo == null ||
				string.IsNullOrWhiteSpace(classInfo.name) ||
				string.IsNullOrWhiteSpace(classInfo.desc) ||
				classInfo.memberVariableInfos == null ) {
				Console.WriteLine("classInfo is invalid...");
				return;
			}

			// 指定ディレクトリがなければ作成
			if( Directory.Exists(outDirectory) ) {
				Directory.CreateDirectory(outDirectory);
			}

			// ソースコード作成
			var sourceCode = new StringBuilder();

			// クラス開始
			sourceCode.AppendLine("// @class	" + classInfo.name);
			sourceCode.AppendLine("// @brief	" + classInfo.desc);
			sourceCode.AppendLine("public class " + classInfo.name);
			sourceCode.AppendLine("{");

			// プロパティ開始
			foreach( var memberVariableInfo in classInfo.memberVariableInfos ) {
				if( memberVariableInfo == null ||
					string.IsNullOrWhiteSpace(memberVariableInfo.name) ||
					string.IsNullOrWhiteSpace(memberVariableInfo.type) ||
					string.IsNullOrWhiteSpace(memberVariableInfo.desc) ) continue;

				sourceCode.AppendLine("	public " + memberVariableInfo.type + " " + memberVariableInfo.name + " { get; } //!< " + memberVariableInfo.desc);
			}
			sourceCode.AppendLine();
			// プロパティ終了

			// コンストラクタ開始
			sourceCode.AppendLine("	// @brief	コンストラクタ");
			// コンストラクタコメント
			foreach( var memberVariableInfo in classInfo.memberVariableInfos ) {
				if( memberVariableInfo == null ||
					string.IsNullOrWhiteSpace(memberVariableInfo.name) ||
					string.IsNullOrWhiteSpace(memberVariableInfo.type) ||
					string.IsNullOrWhiteSpace(memberVariableInfo.desc) ) continue;

				sourceCode.AppendLine("	// @param	[in]	" + memberVariableInfo.name + "	" + memberVariableInfo.desc);
			}
			// 引数
			var constructorArgs = new StringBuilder();
			foreach( var memberVariableInfo in classInfo.memberVariableInfos ) {
				if( memberVariableInfo == null ||
					string.IsNullOrWhiteSpace(memberVariableInfo.name) ||
					string.IsNullOrWhiteSpace(memberVariableInfo.type) ||
					string.IsNullOrWhiteSpace(memberVariableInfo.desc) ) continue;

				constructorArgs.Append(memberVariableInfo.type + " " + memberVariableInfo.name + ", ");
			}
			// 最後の不要な「, 」削除
			constructorArgs.Remove(constructorArgs.Length - 2, 2);
			sourceCode.AppendLine("	public " + classInfo.name + "(" + constructorArgs.ToString() + ")");
			sourceCode.AppendLine("	{");
			foreach( var memberVariableInfo in classInfo.memberVariableInfos ) {
				if( memberVariableInfo == null ||
					string.IsNullOrWhiteSpace(memberVariableInfo.name) ||
					string.IsNullOrWhiteSpace(memberVariableInfo.type) ||
					string.IsNullOrWhiteSpace(memberVariableInfo.desc) ) continue;

				sourceCode.AppendLine("		this." + memberVariableInfo.name + " = " + memberVariableInfo.name + ";");
			}
			sourceCode.AppendLine("	}");
			// コンストラクタ終了

			sourceCode.AppendLine("}");
			// クラス終了

			// 書き出し
			using( var sw = new StreamWriter(outDirectory + classInfo.name + ".cs", false, new UTF8Encoding(true)) ) {
				sw.Write(sourceCode.ToString());
			}
		}

		// @brief	セルの値を取得
		// @param	[in]	sheet		シート
		// @param	[in]	rowIndex	行インデックス
		// @param	[in]	cellIndex	列インデックス
		// @return	セルの値
		private static string getCellValue(ISheet sheet, int rowIndex, int cellIndex)
		{
			if( sheet == null ) return string.Empty;

			// 行を取得
			var row = sheet.GetRow(rowIndex);
			if( row == null ) return string.Empty;

			// 行からセルを取得
			var cell = row.GetCell(cellIndex);
			if( cell == null ) return string.Empty;

			// セルが取得できたら中身を文字列化
			return cell.ToString();
		}
	}
}

 

実際に生成されたコードはこんな感じです。

// @class	Weapon
// @brief	武器
public class Weapon
{
	public uint id { get; } //!< ID
	public string name { get; } //!< 名前
	public string desc { get; } //!< 説明
	public int attack { get; } //!< 攻撃力

	// @brief	コンストラクタ
	// @param	[in]	id	ID
	// @param	[in]	name	名前
	// @param	[in]	desc	説明
	// @param	[in]	attack	攻撃力
	public Weapon(uint id, string name, string desc, int attack)
	{
		this.id = id;
		this.name = name;
		this.desc = desc;
		this.attack = attack;
	}
}

 

これで、「クラスファイル」を生成するところまで完成しました

 

 

次回は、実際にデータファイルの書き出しをしていきたいと思います。

ではでは~

RECRUIT

大阪・東京共にスタッフを募集しています。
特にキャリア採用のプログラマー・アーティストに興味がある方は下のボタンをクリックしてください

RECRUIT SITE