インスピレーション!
うちのシステム(恒星系のこと)で惑星開発のいい商材作れないかなーとポチポチ眺めていたところ、あるインスピレーションが浮かびました。
- システムにある種別ごとの惑星数を読み込む
- 惑星開発できるキャラクター数と各キャラクターのInterplanetary Consolidationを取得
- 上記2つの情報をもとに作れるものを走査(なお、採掘資源量は考慮しない)し提案
これで楽が出来るかも……
というわけで検証。
各種オブジェクトについて
ソーラーシステム
計画するアプリケーションの最終形態として、どのシステムならどれを作れるかといった情報をCRESTから取得できるようにしたい。
α段階では内包する惑星数を手打ちで入れる
惑星
各種惑星が保有しているP0はXMLドキュメントか別途データソースとして保管
資源
P0はどの惑星から採れるかを示す。
P1以降は回路図をもとに、何から製造されるかを示す。
P4品1個を作るのにP0品はどの種類が何個必要かを求められるようにする。
以下手順、若干省いているところは多いが下に行くほど個数が増える
1.P4品A1はP3品B1~3までで構成されている
2.P3品B1はP2品C1とC2で構成されていて
3.P2品C1はP1品D1とD2で構成されている
4.P1品D1はP0品E1で構成されている
担当するキャラクター情報
計画としては担当キャラクターをAPIで入れることも可能にしたい
α段階としてはキャラクター名とInterplanetary Consolidationを手打ちで入力
ロジックについては今後考えよう。
Collectionを投げ捨てろ!
今回は仕事で使っているVBAについてです。
ツイッターから見た人は既に存じ上げているかとは思いますが、VBAはモダンなパラダイムが無いとか、継承が無くて似たようなクラスを作れないとか、めんどくさいことが多いデス
あとは他言語にあるListとかそういうアレがデフォルトで実装されている(Collection)ものの……欠点が多いです。
連想配列は便利だけどぶっちゃけそこまで求めてないし……
具体的には
- 機能が貧弱(値の追加・削除、コレクションの要素数取得くらい。配列の要素を突っ込めない)
- インデックスが0から始まらない気持ち悪さ(他言語経験故のアレ)
- ジェネリクスがないせいで何でも入っちゃう型安全行方不明
だったら自作すればいいじゃない!
というわけでざっくりとした案。String限定ですけど
- 初期の配列長は1かつインデックス0から開始(Option Base 0)
- 新たに値を追加するとPreserve ReDimで再定義して末端に挿入。
- 配列を突っ込んだ場合は突っ込む分だけ余白を作って再定義
- 配列の要素を削除すると後ろから要素が詰めてきて配列を再定義。
- いっそ特定の区間の要素を削除するとかもやっちゃおうぜ
- Attribute弄らなきゃForEachできない? だったら格納してる配列返せばええねん
- 値が存在するか確認したい? よろしいならばContainsだ(格納してる配列をForEachして値があるかどうか判別してBoolean返すだけー)
- いっそLINQみたいに配列丸ごと文字列操作できるようにしちまおうぜ。(前後に文字列を付け加える、置き換える))
- ポリモーフィズムが存在しないので引数VariantでArray()して変なのが突っ込んで来られてもいいようにVarTypeして判定を取る(多分これが一番重いと思います)
- なお、この結果で数値系だとしても文字列化して捻じ込む可能性があります
ぶっちゃけた話、これぐらいやってもシートに描画しまくるほうが時間かかるわけで大して問題は発生しないと思います(汗
そしてこの自作ライブラリを作ったとして、後任者に変な操作されないように異常検知機構を組み込むわけですが、VBAだとTry-Catchとか例外処理がないからGoToとか事前検証で値が妥当であるかとか検証しないといけないんですよねー(焦
車輪の再生産ですが、車輪を買う場所が無い(外部からデータを入れるための情報媒体持ち込めない)から仕方ないデスねハイ。
asyncってかんたん!?
今回は非同期処理についてです。
C#では処理をバックグラウンドに投げる非同期処理が簡単に…………できました。
サンプルコードは下記のとおりです。
非同期処理にするにはざっくりとして以下の通りです。
- 非同期処理を行うメソッドをasyncで修飾して戻り値をvoid、Task、Task(T)のどれかにする
- メソッド内で非同期にしたい処理をawait Task.Runの中にラムダ式で書き込む。
- 戻り値を持つ場合はタスクを変数に取り込み、Resultプロパティで結果を取り出す。
実用するにはどうやるのかなー、というのはありますけどね(汗
using System; using System.Linq; using System.Threading.Tasks; namespace AsyncExperiment { class Program { static void Main(string[] args) { //戻り値を持つ場合はこのように行う var alpha = AsyncRunner.Factional(1, 10); Console.WriteLine("10の階乗は{0}です", alpha.Result); //戻り値を持たない場合はこんな感じで良い AsyncRunner.AsyncMethod(1, 10); AsyncRunner.AsyncMethod(2, 10); AsyncRunner.AsyncMethod(3, 10); } } /// <summary> /// このクラスでは非同期処理の試験メソッドを提示します。 /// </summary> public class AsyncRunner { /// <summary> /// <para>非同期メソッド1.試験用コール</para> /// <para>このメソッドについては繰り返し処理が非同期的に行われていることを試験するためのものです。</para> /// <para>出力パターンは "CallNumber = {0} Looping = {1}" と出力されます。</para> /// </summary> /// <param name="CallNumber">試験用コールナンバー</param> /// <param name="Looping">ループ回数</param> public static async Task AsyncMethod(int CallNumber,int Looping) { await Task.Run(() => { foreach (int Progress in Enumerable.Range(1, Looping)) { Console.WriteLine("CallNumber = {0} Looping = {1}", CallNumber, Progress); System.Threading.Thread.Sleep(500); } }); } public static async Task<int> Factional(int CallNumber,int Value) { int val; val = await Task.Run(() => { int result=1; foreach(int Progress in Enumerable.Range(1, Value)) { result *= Progress; Console.WriteLine("Method{0} Calcurating... Value = {1}", CallNumber, result); System.Threading.Thread.Sleep(500); } Console.WriteLine("Calcurate Complete Value is {0}", result); return result; }); return val; } } }
Visual Studioの機能を使おう 単体テスト編
色々やってると気が付けばEVE関係なくなってますね。。。
今回は作ってみたクラスが妥当であるかを自分でテストコードを入れて実行するための機能を紹介します。
Visual Studio 2015[以下VS15]では次の手順で単体テストを作成することが出来ます。
あ、もちろん無料のCommunity版でも使用できますよ!
クラスを作成したプログラムファイル(デフォルトならProgram.cs)で右クリックし、「単体テストの作成」を選択します。
その際に出力されるウィンドウは特に変更せずにOKしましょう。
OKしたらソリューションエクスプローラにフラスコマークが付いたテストプロジェクトが作成されます。
そこに正しく実行されているか、そうでないかを判別するテストコードを入力し、走らせることができます。
なお、今回テストを行うプログラムはこちらです。
public class Calcuration { int Value1; int Value2; // コンストラクタ // 初期値を格納します。 public Calcuration(int val1,int val2) { Value1 = val1; Value2 = val2; } // クラス内に格納された2つの値の足し算を実行します。 public int Additional() => Value1 + Value2; }
流石にテストを行うほどじゃねーだろ!と言われたら御仕舞ですが、世の中シンプルなものでやるのが一番です。
というわけでテストコードがこちら。
[TestMethod()] public void CalcurationTestSimple() { int Alpha = 1; int Bravo = 10; int Answer = 11; var Test = new Calcuration(Alpha, Bravo); Assert.AreEqual(Answer, Alpha + Bravo); Assert.IsTrue(Alpha + Bravo == Test.Additional()); }
結果は見りゃわかるだろって? そりゃ言わないお約束です。
ここで注目してほしいのはAssertクラスによるメソッドです。
引数同士で比較したり、bool型を戻り値に持つ式を入れたりして、正しい値が出るならテストが成功しているとテストエクスプローラで通知してくれます。
逆に、こうじゃなかったら失敗だよ!という場所にAssert.Fail()メソッドを入れたりすることで、テストで望む結果が出ていないことを通知してくれます。
なぜ作るのか
私の見解ですけど……テストコードというのは、自分で自分が望む挙動を作成したプログラムが行っているかを見るために作成しているものだと思っています。
作ったコードが正しいものであるという根拠にもなるでしょうし、どういう動作をしているか・させるかを見せるものでもあると思っているので作る意義は十分あると思います。
続・頭の整頓。
何を作ろうかを再度定義し直さないといけなくなってきたので……
ちゃんと設計の勉強すべきだなあと思いつつも。
作りたいもの
EVE ONLINEの交易を補助するためのアプリケーション
色々やったものの、現状の技量(プログラム規模的に)で可能なのは英名を突っ込んだらCentral等で値段を引き出すためのtypeIDを獲得するもの