ST_FUNC開発日記

建築構造設計Excelアドイン開発の記録

断面性能関数をスピル対応にする secBuilcBox

さて、公開の夢は立たれたが、引き続き開発は続けることにする。

やろうとしたらいろいろ詰まりまくって前回記事のような検証が必要だったけど、あらためてスピル対応をする。

オーバーロードを使ったりするとなかなかややこしいことが分かったので、シンプルに引数と戻り値を配列にした関数を作る。

/**
 * 鉄骨断面の断面性能(複数)
 * @param propertyType 表示したい断面性能のタイプの配列
 * @param section SecSteelを継承した鉄骨断面クラスのインスタンス
 * @returns 断面性能の配列
 */
function getSecSteelPropertys(propertyType: string[][], section: SecSteel): number[][] {
  return propertyType.map((row) => row.map((item) => getSecSteelProperty(item, section)));
}

そして、呼び出す側の関数を複数対応にすればOKかな。

/**
 *  組立角形鋼管の断面性能。
 * @customfunction secBuildBox secBuildBox
 * @param propertyType 表示したい断面性能のタイプ
 * @param a 成 A
 * @param b 幅 B
 * @param t1 成方向の板厚 t1
 * @param t2 幅方向の板厚 t2
 * @returns 断面性能
 */
export function secBuildBox(propertyType: string[][], a: number, b: number, t1: number, t2: number): number[][] {
  const secBuildBox: SecBuildBox = new SecBuildBox();
  secBuildBox.setDimensions(Unit.input(a, "mm"), Unit.input(b, "mm"), Unit.input(t1, "mm"), Unit.input(t2, "mm"));
  return getSecSteelPropertys(propertyType, secBuildBox);
}

さて、これでテストを回してみたら

TS2345: Argument of type 'string' is not assignable to parameter of type 'string[][]'.

のエラーが。

そうだ。引数と戻り値を配列にしたから、テストも配列対応にしないといけないんだ。

これがあるからオーバーロードしたかったんだよな・・・。

とりあえずテストを配列形式で書き換えてみる。

test("SecBuildBox", () => {
  expect(secBuildBox([["A"]], 1000, 800, 19, 25)[0][0]).toBeCloseTo(76100.0, 9);
  expect(secBuildBox([["ZY"]], 1000, 800, 19, 25)[0][0]).toBeCloseTo(24446708.3333333, 7);
  expect(secBuildBox([["ZZ"]], 1000, 800, 19, 25)[0][0]).toBeCloseTo(19098293.4166667, 7);
  expect(secBuildBox([["m"]], 1000, 800, 19, 25)[0][0]).toBeCloseTo(597.385, 12);
  expect(secBuildBox([["iY"]], 1000, 800, 19, 25)[0][0]).toBeCloseTo(400.777073164208, 12);
  expect(secBuildBox([["iZ"]], 1000, 800, 19, 25)[0][0]).toBeCloseTo(316.836310923171, 12);
  expect(secBuildBox([["IY"]], 1000, 800, 19, 25)[0][0]).toBeCloseTo(12223354166.6667, 4);
  expect(secBuildBox([["IZ"]], 1000, 800, 19, 25)[0][0]).toBeCloseTo(7639317366.66666, 4);
});

うん、これで動いた。でも、”A”とか[0][0]とかあまり美しくないんだよなあ・・・。

コードがちょっといまいちに見えるのでChatGPTさんに「上記のコードをもう少しシンプルに書けないでしょうか?」と聞いてみたら、下記回答が。

このテストコードをよりシンプルに書く方法はいくつかあります。まず、テストケースのデータを配列にまとめることで、冗長性を削減できます。また、各テストケースの期待される結果も配列に格納し、ループを使用してテストを実行する方法もあります。以下はその例です:

test("SecBuildBox", () => {
  const testCases = [
    [["A"], 76100.0],
    [["ZY"], 24446708.3333333],
    [["ZZ"], 19098293.4166667],
    [["m"], 597.385],
    [["iY"], 400.777073164208],
    [["iZ"], 316.836310923171],
    [["IY"], 12223354166.6667],
    [["IZ"], 7639317366.66666]
  ];

  testCases.forEach(([input, expected]) => {
    expect(secBuildBox([input], 1000, 800, 19, 25)[0][0]).toBeCloseTo(expected, 9);
  });
});

このように変更することで、テストケースの数が増えても、コードがより読みやすくメンテナンスしやすくなります。

そうか。普通に値を配列にすればいいだけか。

上のコードだと誤差が固定になってしまうので、誤差までを配列に入れることにする。

test("SecBuildBox", () => {
  const testCases = [
    ["A", 76100.0, 9],
    ["ZY", 24446708.3333333, 7],
    ["ZZ", 19098293.4166667, 7],
    ["m", 597.385, 12],
    ["iY", 400.777073164208, 12],
    ["iZ", 316.836310923171, 12],
    ["IY", 12223354166.6667, 4],
    ["IZ", 7639317366.66666, 4],
  ];
  testCases.forEach(([input, expected, numDigits]) => {
    expect(secBuildBox([[input]], 1000, 800, 19, 25)[0][0]).toBeCloseTo(expected, numDigits);
  });

しかし、エラーになってしまった。

Type 'string | number' is not assignable to type 'string'.

とのこと。型の不一致?

えーい、もう全部ChartGPTに聞こう。

申し訳ありません、そのエラーは型の不一致に関連しています。テストケースのデータ配列でinputが文字列であることを TypeScript に伝える必要があります。具体的には、テストケースのデータ配列を次のように定義することで、そのエラーを修正できます。

test("SecBuildBox", () => {
  const testCases: [string, number, number][] = [
    ["A", 76100.0, 9],
    ["ZY", 24446708.3333333, 7],
    ["ZZ", 19098293.4166667, 7],
    ["m", 597.385, 12],
    ["iY", 400.777073164208, 12],
    ["iZ", 316.836310923171, 12],
    ["IY", 12223354166.6667, 4],
    ["IZ", 7639317366.66666, 4],
  ];
  testCases.forEach(([input, expected, numDigits]) => {
    expect(secBuildBox([[input]], 1000, 800, 19, 25)[0][0]).toBeCloseTo(expected, numDigits);
  });
});

こうすることで、TypeScriptはテストケースデータの各要素が最初の要素が文字列、2番目の要素が数値、3番目の要素が数値であることを理解します。

なるほどねー。そういえば型定義してなかったけど、配列の各要素にも型を指定することができるのか。

新しい言語を使うといろいろ新鮮だなあ。

どうしても数値を指定する以上行数はそんなには減らないけど、寸法が1か所で済むようになったし、だいぶすっきりしたかな。

それにしても、ChatGPTが便利すぎてどんどん自分が退化してる気がする。検索能力の低下??

secBuildBox関数を配列出力に対応 · st-func/st_func_addin@b2f3a08 · GitHub