OmniAICreator/Qiita-1.07M huggingface dataset:
2024/12/17主にITとかセキュリティの記事

Cleo MFT脆弱性：新たなゼロデイ攻撃が拡大、4000社以上に影響の恐れ(12/15)
https://innovatopia.jp/cyber-security/cyber-security-news/45496/

BADBOX マルウェア、ドイツで3万台のIoTデバイスを感染 – BSIがシンクホール対策で無効化に成功(12/15)
https://innovatopia.jp/cyber-security/cyber-security-news/45490/

Yokaiバックドア攻撃が政府機関を対策に ─ DLLサイドローディングで正規アプリを悪用、東南アジアでサイバー攻撃が激化(12/15)
https://innovatopia.jp/cyber-security/cyber-security-news/45493/

EPSS (Exploit Prediction Scoring System) を整理する(12/14)
https://qiita.com/sig666/items/ad0a1e71dd91d6dac48b

Komdigiは、サイバー脅威を軽減するために、すべての機関にCSIRTチームを設立することを奨励しています(12/14)
https://voi.id/ja/teknologi/442873

runnを用いたバックエンドテストの試行錯誤の変遷とこれから(12/15)
https://developers.freee.co.jp/entry/freee-qa-advent-calendar2024-day15

生成AIとウェブスクレイピング技術の融合　最新の技術トレンドを解説(12/15)
https://news.yahoo.co.jp/articles/d0b022bd909ff19b4fc520e1062b636622b55fb8?source=rss

米国 NIST NIST SP 1800-35（初公開ドラフト） ゼロトラスト・アーキテクチャの実装 (2024.12.04)(12/15)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/12/post-f3e114.html

これまでの常識は「逆に」危険　スマホを襲う進化したスパム電話やフィッシングリンク(12/15)
https://forbesjapan.com/articles/detail/75712

【国際】DXは攻めの投資を優先。5Gとコネクティビティが重要。GSMA報告書(12/15)
https://sustainablejapan.jp/2024/12/15/gsma-dx-report/109104

【個人情報漏洩事例】私たちのデータはどこで危険にさらされているのか？
https://cybersecurity-park.com/3718/

中東の食糧安全保障危機を解決する鍵はスマートテックにある(12/15)
https://www.arabnews.jp/article/business/article_136396/

県内外中高生　サイバー犯罪捜査を体験(12/15)
https://www.chunichi.co.jp/article/999797?rct=f_news

カナダ 下院情報公開・プライバシー・倫理常任委員会 ソーシャルメディア・プラットフォームの監督 オンラインにおけるプライバシーと安全の確保 (2024.12.12)(12/15)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/12/post-5cb5ea.html

ミステリードローンがニューヨークの空港を麻痺させ、連邦政府の介入の警鐘が鳴る(12/15)
https://motorcyclesports.net/ja/mystery-drones-paralyze-new-york-airport-as-alarm-bells-ring-for-federal-intervention-ja/

国がパニックに陥る中、正体不明のドローンに警報が鳴り響き、政府の沈黙が国民を驚かせる(12/15)
https://motorcyclesports.net/ja/nation-in-panic-as-alarm-bells-sound-over-unidentified-drones-governments-deafening-silence-shocks-public-ja/

セキュリティエンジニアって200職あんねん（分類とキャリアの話）(12/15)
https://qiita.com/ahera/items/3bea4df41423ef208700

生成的AIについてふと思ったこと...金持ちはより金持ちに...(12/15)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/12/post-ad111d.html

[2024年]出会えて良かった書籍まとめ@25冊(12/15)
https://zenn.dev/anri99103/articles/e6242a2f19037f
AWS SA Pro受験で問題集読んでて知らんかったことまとめ

## IAMの境界設定ポリシー
管理側の機能として割と知らないことがあった。

これはIAMのエンティティ（ユーザとかロール）に設定できるもので、アタッチされたポリシーを更に制限する大前提のアクセス境界。これ以上の権限をかけられないという意味ではSCP的な権限のガードレールをユーザーやロール単位に設定できるイメージ。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_boundaries.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/a532d139-53ad-0bb5-beee-8f209d9a4431.png)

## DynamoDB Accelerator(DAX)
DynamoはほとんどLambdaとかしか使わないのでVPC連携機能であるこれは知らなかった。
早い話がDynamoDBのキャッシュをVPCに設けてそこにマイクロ秒単位の応答性をもたせるというもの。

そんなんあったっけ？と思ったら普通にDynamoDBページのメニュー下に堂々と書いてあるのであった、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/2d4ab882-b019-92e5-c9f3-7a8fb847e67f.png)

あと普通に専用のインスタンスタイプもある。要はキャッシュサーバーインスタンスなんだな。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/10eb6a88-c963-c70a-eef7-04640f4591f5.png)


## S3 RTC（Replication Time Control\)
S3でクロスリージョンレプリカを作成する際、15分というタイムスポン内で終わるかどうかを管理して通知してくれる機能。

S3のレプリケーション作成する画面の下の方にある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/687c08b5-e815-fd0b-fefb-ddcb73fbad12.png)

## Amazon Data Lifecycle Manager（DLM）
> EBS スナップショットと EBS-backed AMI のライフサイクル管理を自動化

https://aws.amazon.com/jp/ebs/data-lifecycle-manager/


これでだいたい語りきっている。EBS専用のAWS Backupという感じか。普通にEc2画面メニューにいる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/8a6da8dd-5c3d-5200-a439-d8901bc58f42.png)

ポリシー指定なので、特定タグが付いているやつを対象にするようなイメージ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/ec3895ad-5fd1-b99b-f8d7-83f6da148c4d.png)

## S3のSFTP対応関係（AWS Transfer Family）
IPアドレスの固定は昔はVPCホストでないとIP固定の手段はなかったが、2024年11月より静的IPの機能が追加されている。したがってパブリックでもIP固定は可能となる。

https://aws.amazon.com/jp/about-aws/whats-new/2024/01/aws-transfer-family-static-ip-sftp-connectors/

ちなみにAWS Transfer Family自体はSFTPだけではなくFTPSやAS2、セキュアではないFTPにも対応している。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/7638f713-c6cb-8a74-e6d1-baa7319cefe8.png)

過去の問題はIP固定のためにVPCホストを利用する方法が出題されている。

## VPCトラフィックミラーリング
ネットワークの虎フィクを文字通りミラーリングし、特定のターゲット（ENI / NLB / GWLB）に送信する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/f4d980d9-35a8-7529-ab56-5a4a4ed63e2a.png)

送信するパケットのフィルタリングも可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447106/991b7fcb-d902-f18c-1116-0615bc888f28.png)

セキュリティアプライアンスの導入などに活用される。
https://docs.aws.amazon.com/vpc/latest/mirroring/what-is-traffic-mirroring.html

## Service Health Dashboard
これは名前を知らんかった。「AWS Status」としてみていたので・・・
AWSサービス全体のヘルスを表示するやつですね。

https://health.aws.amazon.com/health/status

## Dedicated Instance / Dedicated Hosts
特定のインスタンスやホスト（仮想マシンのホストのこと）を占有して（dedicated）起動するオプション。隔離された環境の保証や商用製品の動作環境固定化などの用途で利用する。

https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/dedicated-hosts-overview.html
mysql 起動時のThe server quit without updating PID file エラーの解決

私がMySQLを起動しようとしたら、こんなエラーが出てきました。
```
$ mysql.server start
Starting MySQL
... ERROR! The server quit without updating PID file (/opt/homebrew/var/mysql/***.pid).
```
色々なQiitaの記事を参考にしたりAIに聞いたりしましたが、結局起動できず、エラーだらけだったので、少しでも参考になっていただければと思ってこの記事を書きました。

# 事象の発生環境
```
$ sw_vers
ProductName:		macOS
ProductVersion:		15.1.1
$ mysql --version
mysql  Ver 9.0.1 for macos15.1 on arm64 (Homebrew)
```
mysqlはbrewでinstall `(brew install mysql)`

# 解決方法（１）

以下のコマンドをターミナルで実行してみてください。
```
$ sudo chown -R $(whoami) /opt/homebrew/*
```
`sudo chown -R $(whoami) /opt/homebrew/* `コマンドを実行すると、`/opt/homebrew` ディレクトリ以下のすべてのファイル・ディレクトリの所有者が、現在ログイン中のユーザー`（$(whoami)`が返すユーザー名）に変更されます。これにより、元々ファイルやディレクトリが「他のユーザー」や「root」などの所有であった場合、その権限不足によるエラーが発生していた可能性が解消されます。

もともと`brew`や関連ツールを使おうとした際に「権限がない」などのエラーが出ていた場合、所有者を現在のユーザーに変更することで読み書き権限を得ることができます。結果として、ファイル操作やインストール処理が正常に行えるようになり、エラーが解消されたというわけです。

>（注意）これは私の場合で動いた方法なので、必ずしも解決できるとは限りません！

#### 他の参考記事
https://qiita.com/jonakp/items/477a18d4a94c01a31583
https://qiita.com/yuki0208/items/1d5554d98e9ec76084bd
https://qiita.com/mogetarou/items/e34ca51d3756d55d7800

# 解決方法（２）
HomebrewでインストールしたMySQLをアンインストールする
```
$ brew uninstall mysql
```
もし、アンインストール後も設定ファイルやデータディレクトリが残る場合は、必要に応じて手動で削除してください（ただし、本番環境などで重要なデータがある場合はバックアップ必須）
```
$ rm -rf /usr/local/var/mysql
$ rm /usr/local/etc/my.cnf
```

再インストールは再びbrewコマンドを使います。
```
$ brew install mysql
```
#### 参考
https://qiita.com/_natsu_no_yuki_/items/ae4c94187093e4ab3cdc
# 最後に

少しでも参考になれば幸いです。
最後までご覧いただき、本当にありがとうございます。
APIとは

## APIとは？
「API」とは「アプリケーション・プログラミング・インターフェース(Application Programing Interface)」の頭文字をとったもので、「インターフェース」という言葉が意味するように「境界線」「接点」を用いてアプリケーション間をつなぐ機能を提供します。
使用すれば、異なるソフトウェアやプログラムを連携させられるようになります。

インターネットが登場してWebブラウザーを用いたWebサービスが一般的になった昨今では、アプリケーションをすべてゼロから開発するのではなく、マイクロサービスと呼ばれる各種Webサービスを組み合わせることで構築する、**Web API**を利用する開発方法が注目されています。
APIを利用することで、他社サービス（API提供元）の機能の一部を自社サービスに組み込んで提供することができます。つまり、APIに備わっている機能を独自に作成する必要がなくなり、開発コストを大幅に削減できます。



## APIの種類

### Web API

Webサービス機能の一部として提供されているHTTPプロトコルを利用してデータを送受信するAPI。
利用するパソコンのOSやプログラミング言語には依存せず、ありとあらゆる環境からアクセスできるようになっています。

例：REST API、GraphQL API

### OS/API
OS上でプログラミングをおこなうために用意されているAPI。

例：iOS API、Android API

### ライブラリ/API

プログラミング言語の機能を提供するAPI。
アプリケーションを開発するために必要な標準機能や拡張機能の多くをAPIとして提供しています。
そのため開発者は自然とAPIのルールに従って、プログラミングをおこなえるようになっています。

例：Pythonの標準ライブラリ、jQuery API

## APIの動作

APIはユーザーが必要とするたびにリクエストされ、その応答（レスポンス）を得るという形で利用されます。
リクエストを受け取ったサーバーが処理を行い、処理の結果をレスポンスとして返しています。

### HTTPリクエスト、レスポンス
HTTPでWeb APIにリクエストを送る際は下記を指定します
- メソッド：GET、POST、PUT、DELETE
- URL：エンドポイントを指定
- ヘッダー：認証や形式の指定
- ボディ：データ送信

レスポンスはステータスコードと必要に応じてデータが返ってきます。
ステータスコードを見ればリクエストが正常に処理されたのかが分かります

ステータスコードの例
- 200: 成功
- 400: クライアントエラー
- 500: サーバーエラー

レスポンスボディには必要のデータもしくはエラーメッセージなどが入っていることが多いです。

## APIのセキュリティ
主にWebAPIは下記のようなセキュリティ対策を取っています
- 認証：OAuth 2.0、APIキー
- 暗号化：HTTPSによる通信の保護
- レート制限：過剰なリクエストを防ぐ仕組み

## まとめ
APIは、現代のアプリケーション開発に不可欠な技術です。
ただ、APIの仕組み等を理解した上で使う必要があるとも言えます。（特にセキュリティ周りは
読んでいただきありがとうございました！

## 参考記事
https://www.ntt.com/business/services/rink/knowledge/archive_18.html

https://kwcplus.kddi-web.com/blog/api-types-and-protocols#toc-0
ExcelVBAで疑似的なマルチスレッドを実現する

## 環境
- Excel for Microsoft365(64bit)

## 経緯
ExcelVBAで以下のような機能を要求されました。
- ボタン1を押すと監視処理Aを開始する
- 監視処理Aは50ms周期で状態の監視と、その結果をVBAフォーム上に表示する
- ボタン2を押すと処理Bを開始する
- 処理Bは1秒ごとに内部のパラメータを変更し、これを10回繰り返す

当初は監視処理Aのみ要求されていたので、ボタンイベントの中で無限ループを行う形で処理を実現していました。
その後、処理Bを追加することになりましたが、同様にボタンイベントで実装したところ、処理Bが実行されている間、監視処理Aが動かなくなりました。
これはExcelVBAがシングルスレッドで動作するためであり、二つの処理を同時に実行できないことが原因でした。

この問題を解決するため、次にあげる方法で疑似的なマルチスレッド処理を実現しました。

## Application.OnTimeによる疑似マルチスレッド

Application.OnTimeは指定した時刻にプロシージャ(マクロ)を実行します。
指定した時刻、今回であれば処理Bを1秒ごとに呼び出すことで、監視処理Aが実行できるようにします。

~~~vb:UserForm
Private LoopActive As Boolean
Private CounterB As Integer
Private ReservedTimeB As Date

Private Sub 監視処理A_Click()
    If 監視処理A.Value = True Then
        '開始
        LoopActive = True
        Application.OnTime EarliestTime:=Now, Procedure:="FunctionA"
    Else
        '停止
        LoopActive = False
    End If
End Sub

Private Sub 処理B_Click()
    If 処理B.Value = True Then
        '開始
        CounterB = 0
        '処理Bの実行時間を保持(停止時に必要なため)
        ReservedTimeB = Now + TimeValue("00:00:01")
        Application.OnTime EarliestTime:=ReservedTimeB, Procedure:="FunctionB"
    Else
        If CounterB < 10 Then
            '停止(次回予約されている時のみ
            Application.OnTime EarliestTime:=ReservedTimeB, Procedure:="FunctionB", Schedule:=False
        End If
    End If
End Sub

Public Sub FunctionA_Loop()
    While (LoopActive)
        '==========
        '監視処理A
        '==========
        
        'その他のイベント、タイマー処理に実行権を移す
        DoEvents
    Wend
End Sub

Public Sub FunctionB_Loop()
    '==========
    '処理B
    '==========
    CounterB = CounterB + 1
    
    '次回起動予約(1秒後)
    If CounterB < 10 Then
        Application.OnTime EarliestTime:=ReservedTimeB, Procedure:="FunctionB"
    End If
End Sub
~~~
~~~vb:標準モジュール
'OnTimeで呼び出される処理を定義
Public Sub FunctionA()
    UserForm1.FunctionA_Loop
End Sub

Public Sub FunctionB()
    UserForm1.FunctionB_Loop
End Sub
~~~

調べてみると、VBScriptやExcelを別プロセスで起動する方法もあるようですが、デバッグができなかったり、制御が難しかったりします。(バックグラウンドにExcelのプロセスが残ったり)
そういった点からApplication.OnTimeを使う方法がベストかと思います。
playwright.config.tsについて

## **複数の設定ファイル**

Playwrightでは、環境に応じて異なる設定ファイルを使用できます：

- playwright.config.ts（デフォルト）
- playwright-prod.config.ts（本番環境用）
- playwright-staging.config.ts（ステージング環境用）

など

### **特定の設定ファイルを使用する場合**

```jsx
npx playwright test --config=playwright-prod.config.ts
```

## **設定ファイルの構造**

設定ファイルは主に2つのブロックで構成されています：

### **1. useブロック**

- グローバルな設定を定義
- すべてのテストに適用される共通設定

```jsx
use: {
baseURL: '[http://localhost:4200](http://localhost:4200/)',
viewport: { width: 1280, height: 720 },
screenshot: 'on',
}
```

**2. projectsブロック**

- プロジェクトごとの個別設定
- useブロックの設定を上書き可能

```tsx
projects: [
  {
    name: 'chrome',
    use: {
      ...devices['Desktop Chrome'],
      baseURL: 'http://staging.example.com',  // useブロックの設定を上書き
    }
  }
]
```

この構造により、共通設定と個別設定を柔軟に組み合わせることができます。
AssemblyScriptからホスト側の関数をコールバックする

# はじめに

ここでは、ESMバインディングを使用しているAssemblyScript側のコードから、ホスト側の関数をコールバックする方法を示します。

ESMバインディングの設定方法については、別記事[「vite-react-comlink-worker-assemblyscript-webgpu-boilerplateを作った」の「設定項目の抜粋」](https://qiita.com/kubo_hiroya/items/12aa00e3225213e9e535#%E8%A8%AD%E5%AE%9A%E9%A0%85%E7%9B%AE%E3%81%AE%E6%8A%9C%E7%B2%8B)のセクション内容を参照してください。

※別記事「[vite-react-comlink-worker-assemblyscript-webgpu-boilerplateを作った](https://qiita.com/kubo_hiroya/items/12aa00e3225213e9e535)」が、関連して開発したコードからの引用を含めて、3万字弱もの分量があるため、特に有用と思われる部分をこちらの記事に切り出しました。

# AssemblyScript側のコード

AssemblyScript側のコードとして、次のようなものを書きます。

```TypeScript:AssemblyScript側のコード

export function doSomething(value: u32): void{
  myCallback(value * 1);
  myCallback(value * 2);
  myCallback(value * 3);
}


// @ts-ignore: decorator
@external("env", "myCallback")
export declare function myCallback(value: u32): void;
```

ここでは、`doSomething`という関数が実装されています。
渡された値を、1倍、2倍、3倍した値にして、`myCallback`関数を計3回呼ぶという内容です。

`doSomething`関数には、`export`がついています。これは、この関数が、AssemblyScript側からホスト側に公開されるものであることを示します。

なお、ここで使われている`myCallback`関数は、実際には、AssemblyScriptで実装されるのではなく、ホスト側（WebWorker側）で実装されるものになります。

上のコードの最後の2行が、このことを、@externalアノテーションを用いて設定する部分です。

```
  「このAssemblyScriptのモジュールにおいて `myCallback`関数を呼び出すときには、その実体として、
    `"env"`というモジュール名前空間の、`myCallback`関数を呼んでね！」
```  
という意味の宣言になっています。
ちなみに、ここでの`"env"`というのは、AssemblyScriptにおける特別なモジュール名前空間の名称で、ようするに`globalThis`のことを指しています（環境変数などのことではありません）。

なお、[The AssemblyScript BookのHost bindingsのUsing ESM bindingsのページ](https://www.assemblyscript.org/compiler.html#host-bindings)には、
`@external("./otherfile.js", "myFunction")`というような表記で、任意のJSファイル内の関数を設定できるように書いてあるのですが、私が試した限りでは、うまく設定できませんでした。

現時点では、`node_modules/assemblyscript/std/assembly.json`でチェックされる内容は、実際のAssemblyScriptのコンパイラで指定できる文法よりも古いため、@externalなどのデコレーターが正しく認識されずに「TS1206: Decorators are not valid here.」のエラーが表示されてしまいます。そうした場合には、上の例のように、下から3行目に「`// @ts-ignore: decorator`」をつけて、エラーの出力を抑制しておきましょう。

# ホスト側のコード

ホスト側では、まず、AssemblyScriptのコンパイラascで作成されたwasmファイルをimportで読み込みます。これを`wasm`という名前で参照することとしています（importするパスは、あなたの開発している環境でのwasmファイルのビルド先に合わせて修正してください）。


次に、グローバル変数`globalThis`に、`myCallback`という名前で、今回コールバックしてほしい関数を紐づけしておきします。

そのあと、wasmに対して、関数`doSomething`を実行します。この`doSomething`がAssemblyScript側の関数として実行される中で、ホスト側の`myCallback`がコールバックされることになります。


```TypeScript:ホスト側のコード
import * as wasm from "../../../build/callbackExample/assets";

(globalThis as any).myCallback = function(
  value: number,
): void {
  console.log(`callback: ${value}`);
};
  
wasm.doSomething(123);

```

# 実行結果

実行すると、次のような出力が得られるはずです。
```
callback: 123
callback: 246
callback: 369
```

# まとめ

ホスト側からのWebAssembly側の関数を呼び出して、その結果を1回だけ受け取るのであれば、関数の返値で受け取れば良いのですが、結果を非同期的に複数回にわたって受け取りたい場合には、コールバック関数を用いることが必要になります。
WebViewerで利用するJSフレームワークにはPreactがおすすめ


以前、このアドカレで軽量なJSフレームワークの[Alpine.js](https://alpinejs.dev/)を紹介しました。
AI花盛りの今年は、[Preact](https://preactjs.com/)の紹介です。

## 何故Preact？
AIの力を使ってコードを書くのがすっかり当たり前の世界になった今、そのAIが提示するコードの精度は、情報量の多さに比例してるであろう事は間違いないと思います。
例えば、AIに対して`"適当なフレームワークでWEBアプリのフロントエンドの雛形を作って"`とリクエストすると、多分Reactを使った案が真っ先に提案されるでしょう。それだけ広く支持されているし、エコシステムも確立しています。困った時の解決策も多いです。それだけ情報が多いと当然AIの精度も高くなるはずです。

じゃあReactを使えばいいかと言うと、FileMakerのWebViewerには機能過多で巨大過ぎます。実際FileMakerのアドオンではいくつか使われているようですが、最近のReactはサーバーコンポーネントやキャッシュ戦略を強化しており、バックエンドサーバーとの通信がないWebViewerには無関係な機能満載です。自分がAlpine.jsを使い続けているのも、シンプルにフロントエンドのUIに特化しているからです。
しかしReactの書き心地というか、コンポーネント管理の容易さは、コードが複雑化すればするほど有り難みがある。

### そこで試したのがPreact
今年の夏頃にちょっと触ってみたら、書き方はまんまReactです。Reactのコードがそのままです。
[Preactの目的](https://preactjs.com/about/project-goals)に書かれているように、React APIとほとんど互換性があります。Reactのバージョンでいうと17前後に相当するようです。
WebViewerで利用する上では以下の機能があれば十分ですよね？
 - Hooks
     - `useState`,`useEffect`,`useContext`など
     - `use***`カスタムフック
 - JSX
     - ほぼReactと同じ書き方です
 - TypeScript
     - Reactと同じくとてもマッチしています。この親和性は重要

Reactが近年強化しているサーバーコンポーネントやキャッシュ戦略はWebViewerでは以下の理由で不要です。
 - データはFileMaker内に既に存在し、クライアント（WebViewer）がそれを直接利用できるため、サーバーコンポーネントのメリット（サーバーサイドでデータ取得とレンダリングを行うことによる高速化）は不要
 - 同じ理由で、通信の最適化やキャッシュ機構を使う必要性がない

### そして重量
例えば最小限の'Hello, World'を表示するだけのページを作成したとして、ビルド後の単一のindex.htmlは何バイト程度になるのか？
バンドラーでminifyした後のざっくりとしたサイズですが、
React: 100kb
Preact: 10kb
とおよそ10倍の差があります。
その差の理由はPReactではReactDOMに相当する部分が簡略化されているからのようです。
もちろんざっくりしたものなので、規模が大きくなるとその差は縮まるようですが、相当軽量なのは間違いない。

### 軽量フロントエンドの必要性
WebViewerの課題は、初回読み込み時のパフォーマンスだと思っています。純粋なWEBブラウザとは当然ですがかなり差があります。個人でできる事は出来るだけ軽量に作る事です。Reactを使いたいのですが、ランタイムが大きいためロード時間に影響が出ます。簡易なものなら気になりませんが、WebViewer内が機能マシマシになってくると結構待たされます。それはクライアントマシンのメモリ不足や貧弱なCPUの場合に顕著です。FileMaker本体と双方向にデータをやり取りしやすくなった今では、例えば初回ロード後に即WebViewerに表示用データを投入するケースや、ロード直後にWebViewerからFileMakerスクリプトを叩くケースがあると思うのですが、0.5秒とかwaitを挟まないと空振りするケースが多いです。対策としてDOM上に関数が確実に配置されたのを確認する処理を挟んだりしていますが、正直面倒です。

できれば生のJavaScriptが良いのは間違いないですが、後々の事を考えると私的には使いずらい。

## 半年使った感想

夏以降のおよそ半年間、新しく実装するWebViewer内のコードは全てPreactで実装しました。ほぼ毎日のように触っていたと思います。
私は特にReactに精通しているわけではなく、時々使う程度の中途半端な知識ですが、正直React書いているのと全く同じ感覚で扱えます。
何よりAIとの親和性が高く、UIコンポーネント単位で見るとReactのコードがそのまま動くので、かなり精度の高い提示・修正案が返ってきます。そしてテストコードも同じ感覚で実装できます。
あまりよろしくない事ですが、公式ドキュメントを見たのは最初の数日だけだった気がします。Reactの経験があると、それくらい調べる事がないです。この記事を書くにあたって久しぶりに覗きました。

そしてTypeScriptとの相性でしょうか。Alpine.jsはその点が少し煮詰まっていなかったのですが（自分の設定が悪いのか）、React同様PreactもTypeScript Readeyです。
私はTypeScriptも浅い知識しかないので以前は型エラーの解決に時間を食ったりしていましたが、今ではAIが迅速に解決策を提示してくるので、型エラーで時間を潰す事はほぼなくなりました😅

つまり、今ではすっかりお気に入りです。

## Preactの認知度
以下、openAI調べ
 #### グローバルでの認知度
- State of JavaScript 2023では、ランクインしています
- 世界的にはモバイルファーストのアプリや、制約の多い環境（IoTや低スペック端末向けアプリ）で軽量なフレームワークが求められるケースが多い。PreactはReactの代替として適しており、これが支持の背景にあるそうです

#### 日本でのPreactが話題にならない理由
- Preactは「Reactより軽量」という特化型フレームワークであるため、パフォーマンスやファイルサイズを極端に気にするプロジェクト以外ではあまり検討されない
- 日本では、多くのWebアプリが比較的リッチで、初期ロードのパフォーマンスにそこまで厳しい要件が求められないため、Preactの軽量性が大きなアピールポイントにはなりづらい
Githubでアクセストークンを使う

# Githubのアクセストークン


CLIからgitを使っていて、認証しようと思った場合の選択肢は以下の2つになります
(以前はIDパスワード認証もありました現在は使えなくなっています)


・SSH
・PAT (Personal Access Token)


上記のうち、SSHは権限設定や期限付き発行ができません。一方で、PATは権限を細かく設定できて期限付き発行がデフォルトであることから環境ごとに権限の異なるトークンを発行できるのがメリットです


# 作成する


repository permission内のcodeのwrite権限があればpushしたりbranch/mergeしたりできます


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277233/16dbc972-d800-4a0c-bc97-8de77ea405c2.png" width=60%>


# 使い方


githubにアクセスする際のURLを <hoo>https</hoo>://ユーザーネーム:入手したトークン@github.com/ のようにするとアクセストークンを適用できます


自分のアカウントが <hoo>https://</hoo><hoo>hoge@</hoo>github.com/ の場合は
<hoo>https</hoo>://hoge:ここにアクセストークン@github.com/ になります


## 環境全体で登録する


.gitconfigでurlの置き換えを設定できるので
以下のように書いてやればurlにアクセストークンを自動で挿入してくれます


--global環境の設定ファイルは以下になります
Linux: ~/.gitconfig
Windows: C:\Users\{username}\.gitconfig


```yaml:~/.gitconfig
[url "https://hoge:入手したトークン@github.com/"]
	insteadOf = https://github.com/
```


.gitconfigを直接操作しても良いですが、git configで登録することもできます


```terminal:terminal
$ git config --global url.https://ユーザーネーム:入手したトークン@github.com/.insteadOf https://github.com/
```


上記だと.gitconfigに追記されるので、既に登録している場合は場合は以下のように1度消してから登録する必要があります


```terminal:terminal
$ git config --global --unset-all url.https://github.com/.insteadOf
$ git config --global url.https://ユーザーネーム:入手したトークン2@github.com/.insteadOf https://github.com/
```


## リポジトリ単位で登録する


リポジトリ単位の情報はリポジトリフォルダの.gitディレクトリ内のconfigに書いてあるのでORIGINを以下のように編集してやることでアクセストークンが使えます


```yaml:/.git/config
[remote "origin"]
	url = https://アクセストークン@github.com/ユーザー名/リポジトリ名
	fetch = +refs/heads/*:refs/remotes/origin/*
```


# 参考にしたページ

https://qiita.com/riita10069/items/e875ae6b96756abd0956


https://note.nkmk.me/git-config-setting/


https://zenn.dev/technicarium/articles/5bf0647056fb87
[golang] map の初期化時はサイズを与えるべき

# 目的
map の初期化時は、なるべくサイズを与えるべきということを理解する。

# 考察
https://www.amazon.co.jp/-/en/Teiva-Harsanyi/dp/4295017531
> マップが拡大する場合、すべてのキーがすべてのバケットへ再配置されます。そのため、最悪の場合、キーの挿入は、マップの要素の総数を n としたとき、O(n)の処理になる可能性があります。
>
> 訳注: キーと値の組を挿入する際に、配列の大きさを2倍にすると判断された場合、すでに入っているキーと値の組をすべて再配置する必要があります。

> 2つ目のベンチマークは、初期サイズを指定することで、約50%高速化されています。サイズを指定することで、挿入された要素に対応するためにマップが拡大することを防いでいます。

私の検証では、一つ目のベンチマークに初期サイズを指定しているが、「354,550,989 / 462,570,698 = 0.7664」なので、23.4 ％くらい高速化されている。
上記の書籍の結果ほど、高速化はされなかった。

# 検証
```
~/praprago$ go version
go version go1.23.2 linux/amd64
```
``` pra_map_test.go
package main

import "testing"

var MyMap map[string]int

// /////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////// (1)
func BenchmarkPraMap1(b *testing.B) {
	var tmpMap map[string]int
	for i := 0; i < b.N; i++ {
		tmpMap = PraMap1()
	}
	MyMap = tmpMap
}

// /////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////// (2)
func BenchmarkPraMap2(b *testing.B) {
	var tmpMap map[string]int
	for i := 0; i < b.N; i++ {
		tmpMap = PraMap2()
	}
	MyMap = tmpMap
}

```
``` pra_map.go
package main

import "strconv"

// /////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////// (1)
// 初期サイズを与えて map を作成する
func PraMap1() map[string]int {
	m := make(map[string]int, 1000_000)
	for i := 0; i < 1000_000; i++ {
		m[strconv.Itoa(i)] = i
	}
	return m
}

// /////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////// (2)
// 初期サイズを与えずに map を作成する
func PraMap2() map[string]int {
	m := make(map[string]int)
	for i := 0; i < 1000_000; i++ {
		m[strconv.Itoa(i)] = i
	}
	return m
}

```
```
~/praprago$ go test -bench=. -benchmem
goos: linux
goarch: amd64
pkg: github.com/XXX/praprago
cpu: Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz
BenchmarkPraMap1-2             3         354550989 ns/op        65652786 B/op     999903 allocs/op
BenchmarkPraMap2-2             3         462570698 ns/op        131546952 B/op   1038107 allocs/op
PASS
ok      github.com/XXX/praprago 5.091s
```



# 参考

https://www.amazon.co.jp/-/en/Teiva-Harsanyi/dp/4295017531

https://www.educative.io/answers/how-to-initialize-a-map-in-golang
> Note: Providing the size here doesn’t mean that map doesn’t grow. It only allocates the given size, but the size will grow if we add more elements to it.

https://www.dolthub.com/blog/2023-06-16-static-map-initialization-in-go/
Rubyでエクセルを出力した際に数式が計算されない問題の解決方法

[リンクアンドモチベーション Advent Calendar 2024](https://qiita.com/advent-calendar/2024/lmi)の17日目を担当します:christmas_tree:

今回はRubyを使ったエクセル操作で、発生した問題の解決策を共有します。

## 背景

最近の業務で、Rake Taskを使ってテンプレートのエクセルファイルから150以上のファイルを生成する対応をしました。
スクリプトを実行し、「よし、150ファイル完成！」と思ったのも束の間。確認してみると…

>「あれ？数式が再計算されてない！？😱」

手動でVBAを使い再計算はできたものの、150ファイルすべてに手作業で対応するのは非効率かつミスのリスクが高い状況。

「**どうにか全てのファイルを手作業せずに再計算させる方法はないか？**」と考え、解決策を探りました。


ちなみにVBAは、
Visual Basic Editorを開いて以下を実行すれば、再計算させることができます。
```vba
Sub RecalculateAll()
  Application.CalculateFull
End Sub
```
ただ、1ファイル1ファイルを手動で実行する必要があり、
大量のファイルを再計算する際は不向きです。

## 問題点: rubyXLでエクセルにデータを流し込むと数式が評価されない

rubyXLでエクセルにデータを突っ込むだけだと、セルに設定されている数式が再計算されないことがあります。

特にプログラムから直接エクセルファイルを編集した場合、この問題が起きるみたいです。

## 解決策: LibreOfficeで再評価するコマンドを投げる

LibreOfficeを活用することで、数式の再計算を自動化する方法を考えました。  
LibreOfficeのCLIを使えば、ファイルを一括で処理するのも簡単です。

**ポイント**:
- RubyからLibreOfficeを呼び出して、数式を再計算させています。
- ファイルが破損することも考慮し、バックアップも取るようにしています。

以下が作成したコードです。

```recalculate_excel.rb
require 'fileutils'

class ExcelRecalculator
  def initialize(folder_path)
    @folder_path = folder_path
  end

  def recalculate_files(pattern = "*.xlsx")
    files = Dir.glob(File.join(@folder_path, pattern))

    if files.empty?
      puts "Excelファイルが #{@folder_path} に見つかりません"
      return
    end

    files.each do |file|
      puts "処理中: #{file}"
      begin
        # バックアップを作成
        backup_file = "#{file}.bak"
        FileUtils.cp(file, backup_file)

        # LibreOfficeのコマンド
        command = "soffice --headless --calc --convert-to xlsx:\"Office Open XML Spreadsheet\" --outdir \"#{File.dirname(file)}\" \"#{file}\""
        result = system(command)

        if result
          FileUtils.rm(backup_file)
          puts "再計算成功: #{file}"
        else
          puts "ファイル処理エラー: #{file}"
          FileUtils.mv(backup_file, file)
        end
      rescue => e
        puts "エラー: #{e.message}"
        FileUtils.mv(backup_file, file) if File.exist?(backup_file)
      end
    end
  end
end

folder_path = "excel"  # Excelファイルがあるフォルダのパス
calculator = ExcelRecalculator.new(folder_path)
calculator.recalculate_files
```
*ruby 3.1.4, LibreOffice 24.8.3.2のバージョンで動作確認済み

## LibreOfficeの導入手順
macOSの場合は、以下のコマンドでインストールしてください。
```shell
$ brew install libreoffice
```

## コマンドの説明
コード内で使用しているコマンド：

```shell
soffice --headless --calc --convert-to xlsx:"Office Open XML Spreadsheet" --outdir "#{File.dirname(file)}" "#{file}"
```

LibreOfficeのオプションの意味は以下の通りです。

- --headless: GUIを使わずに非表示モードで実行
- --calc: LibreOffice Calc（スプレッドシート）を指定
- --convert-to xlsx:"Office Open XML Spreadsheet": ファイルをxlsx形式に変換。フォーマットとしてOffice Open XML Spreadsheetを指定。
- --outdir "#{File.dirname(file)}": 処理後のファイルを元のディレクトリに出力。
- "#{file}": 処理対象のファイルを指定。

このコマンドにより、LibreOfficeが指定されたExcelファイルを読み込み、再計算を行い、指定した形式で保存します。

## 使い方
```shell
$ ruby recalculate_excel.rb
```
を実行することで、
**excelディレクトリ配下のすべてのエクセルファイル**に対して処理を実行できます。
各ファイルはバックアップが作成されたうえで、再計算後に上書き保存されます。

# まとめ
VBAの手作業に頼らず、RubyとLibreOfficeを使うことで大量のエクセルファイルを再計算させることができました。

昨今、いろんな便利ツールが世に溢れていますが、
エクセルファイルで誰かに共有しなければならないという場面はあるかと思います。

そういった時に、この方法は手作業のリスク軽減や時間を削減できるので、ぜひ使ってみてくださいm(_ _)m
同一プロダクトでtoCとtoBを両立させたいときのFigmaデータ構成

## この記事の概要

私はよくFigmaのバリアブルやファイル、ライブラリーの構成について相談を受けます。
その中でも結構難しい部類と思われるのが以下の条件のときです。

- 1つのプロダクト（ブランド）
- toCとtoBどちらも存在する
    - 例えばメディアサイトとその記事を入稿・管理するための画面、のようなイメージ
- 両者を同じテイストで提供したい

なんとなくで作り始めるとすぐに辛くなる構成だと思うのですが、最近は自分の中ではブラッシュアップされてきました。
ということでそれを記事にしました。

:::note warn
外部のツールを使えば良いとか、テイストを揃える必要は無いんじゃないかとか、色々な意見があるような気もしますが、こういう要件も聞きはするので、その前提で読んでください。
:::

:::note alert
これがベストプラクティスだと思って書いている記事でもありません。こういう考えにしたら以前よりはだいぶ良くなった、という程度です。
:::

## 結論

```mermaid
classDiagram
    class Global["Global Tokens"]
    class Graphics
    class ToCAlias["toC Alias Tokens"]
    class ToCComponents["toC Components"]
    class ToCMockups["toC Mockups"]
    class ToBAlias["toB Alias Tokens"]
    class ToBComponents["toB Components"]
    class ToBMockups["toB Mockups"]
    Global <-- ToCAlias
    Global <-- Graphics
    ToCAlias <-- ToCMockups
    ToCAlias <-- ToCComponents
    ToCComponents <-- ToCMockups
    Graphics <-- ToCComponents
    Graphics <-- ToCMockups
    Graphics <-- ToBMockups
    Graphics <-- ToBComponents
    Global <-- ToBAlias
    ToBAlias <-- ToBComponents
    ToBComponents <-- ToBMockups
    ToBAlias <-- ToBMockups
```

（1つのクラス=1つのFigmaファイルです）

- Global Tokens
    - プロダクト・ブランド全体の色やサイズなどを定義する
    - ここに無いものは使わない心構え
- Alias Tokens
    - toCとtoBで定義に必要なものが違うことも多いので分ける
    - 例
        - toCでは余白を多めにとる必要があるが、toBは若干キツキツで良いから一画面あたりの情報量が欲しい
        - toCではジャンプ率を高めに表現したい（等比数列的）、toBではそこまでは不要（等差数列的）
        - toCでは`info`, `success`, `warn`, `error`に対応する色を定義すれば良いが、toBではそれらのvariantやinverseなど細かいバリエーションが必要
- Components
    - toCとtoBで定義に必要なものが違うことも多いので分ける
    - 例
        - 同じようなボタンと見せかけて、toCでは`無料`や`○月まで限定`といったマーケティング的な要素が欲しいが、toBでは不要
        - 請求関連のインターフェースはtoBでは多用されるがtoCではまったく使わない
- Graphics
    - グラフィック系の要素をすべてAlias Tokensで作ろうとすると大抵破綻が生じるので、Global Tokensを直接使う
    - （グラフィックの単位にも寄る気はしつつ）個別のイラストやエフェクト類はtoCとtoBで分けるメリットはそこまでなさそう
- Mockups
    - それぞれのモックアップ（デザインデータ）
    - Global Tokensを直接インポートしないで済むのであれば、しない方が良いと思う

## この構成に至った背景

よく聞く辛さは以下のようなものでした。

- toCとtoBを横断して同一の世界観を出したかった
- なのでデザイントークンやコンポーネントを共通にした
- 最初のうちは良かったが、徐々に条件分岐やバリエーションが増えていった
- 1つのコンポーネントの中にtoCだけ・toBだけのvariantが増え、片方での使用の際もう片方のものは邪魔になるばかり
- 命名規則でsharedなものとspecificなものを区分しているが、ルールが統一できているわけでもない
    - 「これは`toC`って接頭辞がついているけど例外的にtoBでも使うよ」のようなイメージ

こういった事象が起こる多くの理由は「世界観やルック＆フィールの統一」と「トークンやコンポーネントの共用」が一緒になってしまっていることのようです。

あくまで対象を使用する人間の弁別する（できる）単位が重要であり、見た目やコードが似ていたとしても、使用者の認知が違うならそれは別のトークンやコンポーネントで表されるべきです。

その前提に立つと、真にグローバルなもの以外は共通化せず、ほぼすべてを個別に作った方が良いと言えるのではないか？という考えになりました。
というわけで冒頭に示した図（`Global Tokens`と`Graphics`しか共用でない）のように整理しています。

## まとめ

- 見た目やブランドを統一することと、トークンやコンポーネントを共通化することは別
- 源流だけを一緒にして、あとは個別に考えるつもりでいた方が良い
AWS Transfer Family for SFTPをやめたお話

こんにちは。
テックリードのTerukiです。

今回はコストの文脈でAWS Transfer Familyを廃止したよというお話です。
直近数回の記事よりかはだいぶゆるい記事です。

# AWS Transfer Familyとは

>シンプルで安全かつスケーラブルなファイル転送により、データの管理と共有を容易に実現

https://aws.amazon.com/jp/aws-transfer-family/

私の理解を書いておくと、S3などのストレージにいろいろな方法でデータをコピーできる便利ツールです。

Oh my teethでは、社内で使っている既成のWindowsアプリでデータ転送をするために使っていました。
このアプリは数十MB程度のファイルをFTPやSFTPなどで送信する必要があるのですが、今どきSFTPサーバを立ててIaaSにストレージを持たせてファイル管理なんてことはしたくありません。

また、そのデータはインターネットから閲覧できる必要もありました。

という背景から、S3に置いたら良いじゃん！ということでSFTPなどでS3にアップロードできるAWS Transfer Familyを使っていたというわけです。


# これが結構高いんです

これ、要はS3にSFTP経由でファイルをアップロードしているだけなのですが、金額が結構高いです。
一時間あたり0.3USDほどするため、一ヶ月動かしておくとそれだけで219USD。
だいたい3万円強ほどです。

3万円あればそこそこ強いEC2インスタンスも借りられちゃいます。

もちろんこのサービスはこれ以外にもメトリックが監視できたり他の機能もモリモリなので良いところもあるわけですが、Oh my teethの使い方だともったいなさがあります。

個人開発の場合ではまず手が出ない金額感ですね:sob:

# 代替機能を自作してみた

いつもですが欲しいものがないなら作れば良いというスタンスで自作を試みます。

やることのイメージはこんな感じ。

- EC2を建てる
- S3にアップロードする機能
- SFTPを待ち受ける機能
- SFTPとS3のアップロードを中継する機能

---

SFTP経由でアップロードされてくる都合上、ファイルシステムにS3のディレクトリをマッピングするような仕組みでないと実現は難しそうです。

探していたところ、AWSから非常にドンピシャなRust製のツールが出ていました。

https://github.com/awslabs/mountpoint-s3

特定のディレクトリにマウントしておけばファイルの読み書きができます。

マウント時に`--allow-overwrite`や`--allow-delete`を付与すれば上書きや削除もできるので今回の用途には十分そうです。

SFTPサーバにはこちらを使用しました。

https://github.com/atmoz/sftp

こちらはDocker内でSFTPサーバを立ててくれます。
ホストOSが吹き飛んでもそんなに困らなくて良いように、なるべくDockerコンテナで実現したかったのでちょうど良いですね。

後はmountpoint-s3でマウントしたディレクトリとSFTPサーバでアップロードされたファイルの保存先を上手いこと繋ぎ合わせれば完了です。

mountpoint-s3はfuseを使うためDocker内で使用するには下記のような設定が必要でした。

```yaml
services:
  sftp:
    build: .
    ports:
      - 略
    devices:
      - "/dev/fuse"
    cap_add:
      - SYS_ADMIN
    security_opt:
      - apparmor:unconfined
    platform: 略
    restart: 略
```

本当はAppArmerの設定をしっかりするなどするべきなのだとは思いつつ、このサーバはIP制限が掛かった閉じた環境で動いているので一旦は良しとしました。

これを無料枠のts.microのEC2インスタンスで動かして完了です。

# おわりに
今回は諸般の事情でサンプルリポジトリを用意できなかったのですが、上記の構成でSFTP経由でS3にファイルをアップロードすることができました。

ここには書いていない、EC2のロールの設定であったりSFTPサーバの設定などが別途必要ですが、各自各々の設定を記載することになると思います。

これで毎月3万円強掛かっていたものが、IPv4のパブリックIP分のみの支払いになってかなり安くなりました。
接続環境がIPv6でも問題ないようならv4のパブリックIPも外してしまっても良いかもしれませんね。

では。


# Oh my teethについて
Oh my teethでは未来の歯科体験を創るために日々活動しています。

Techチームではより良いユーザー体験を提供するべく、Webフロントエンドからバックエンド、スマホアプリに機械学習モデルなど、さまざまなプロダクトを開発しています。

一緒に未来の歯科体験を創りませんか？興味がある方は是非こちらを確認してください。

https://oh.careers/

カジュアル面談も可能なので気軽に応募してみてください！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192685/0138b492-e02b-852e-61fa-fc065b53d285.png" width="450" />
完璧じゃなくていい、役に立つドキュメント

あなたはいつ、どんな時にドキュメントを書くことがあるだろうか。

私の仕事はリモートワーク中心だ。

何か意思決定が必要な時は、ドキュメントを書いて、それをチャットで送る。ビデオ会議はあまりやらない。

<br>
<br>

ドキュメントと聞くと、次のような特徴を思い浮かべないだろうか。

- 長期間使える
- 誰でも使える（標準化や属人性排除）
- どんな問題にも使える（網羅性）

しかし、私が書くのは「書き捨て」のドキュメントだ。

今この瞬間、特定の問題について合意するための、特定の相手にしか伝わらないハイコンテキストな文書だ。そして、次の 3 つを念頭に置いている。

1. **指摘や質問は来る**
2. **他の文書との統一感は気にしない**
3. **情報量は多くていい**

<br>
<br>

### 1. **指摘や質問は来る**

メッセージを一回送って「はい、わかりました」「OKです」で済むことは少ない。

こちらには相手の理解度がわからないし、相手の意図を誤解している可能性もある。何度かやり取りが発生することは避けられないが、それを面倒がらないようにしている。実際、ほとんどの場合は 1 回のやり取りで解決する。

### 2. **他の文書との統一感は気にしない**

製品の UI ではないのだから、文書間の統一感は気にしない。

全く関係のない文書と一緒に読まれることはほとんどないのだから、そのトピックについて今だけ伝わりやすければそれでいい。

Notion を使ったり Excel を使ったり、時には両方使ったりすることもある。

### 3. **情報量は多くていい**

意思決定のために必要な情報が欠けていては困る。

「もっと簡潔に」と言って必要な情報まで削っていないだろうか。

相手がすべての情報を一度に頭に入れる必要はない。一つひとつ確認し、問題がなければOK、何かあれば質問してくれるはずだ。

<br>
<br>

いかがだろうか。

要するに、私は完璧な文書を書いているわけではない。状況が変化すれば、ドキュメントも変化する。現状はうまくいっている。

寿命の短いドキュメントでも、情報は確実に蓄積されていく。
長期的な問題は…AI が何とかしれくれないかなーなんて思っている。
FigmaからReactにデザイン出力して機能実装する

## 概要

https://qiita.com/gremito/items/89d8f4bb17c84e4f9f12

で解説したとおり実際にプラグインを使ってデザインを出力して動作確認する手順を解説


## 環境

- MacBookPro M2 Max 12コア 96GB
- Node v22.12.0


## Figmaでデザインを作る

https://www.figma.com/community
で無料と有料のテンプレートが公開されているので、プラグインの動作確認の他にもデザインの参考になると思うので活用しています。

![スクリーンショット 2024-12-17 2.21.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/d045e9ce-6f0b-3c16-eeff-64974c69d351.png)

今回は、上記の[website-prototype](https://www.figma.com/community/file/1111408906850339912/website-prototype)という無料テンプレートを使ってFigmaプラグインで出力したReactコードが使えるかの解説しますが、自作できるor作っているのであればそれを使ってください。


## Figmaプラグインを使用する

プラグインを使用する前にどのデザインのReactコードを生成するか選ぶ必要があります。

![スクリーンショット 2024-12-17 2.13.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/18f8cd2a-aa93-9c8f-e1dd-51db09625951.png)

今回は、上記のトップ画面のデザインで動作確認しようと思います。
デザインのタイトルを選択して右クリックからメニューを開きます（サイドメニューからでも同様に操作できます）。
右メニューから`Plugin`にカーソルを当てて、`Manage plugins...`をクリックすると以下の小さいウィンドウが表示されるので、今回は一部無料で使える[builder.io](https://www.builder.io/)を検索して選択します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/4235de76-1000-2ef7-1471-e59c6a0eb4a9.png" width="400px"> 

すると以下のようにウィンドウが変わるので`Export to Code`をクリックしてしばらく待つと`View Code`ボタンが表示されるためクリックします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/6bdb4f4a-4c04-68c9-4963-ec1711e6acb1.png" width="250px"> 
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/ff9a2546-4587-570e-9b9f-f2944d250eaf.png" width="250px"> 

`builder.io`は、Figma内ではなくbuilderのサービス画面上でコード出力することになるため、以下の画面に遷移してReactコードを出力します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/d6159226-44a4-3ce4-8e5c-2b3918efdce3.png" width="800px"> 

もしデザイン量の多いデータをコード出力しようとすると`Generate Code`ボタンではなく、以下の表示で有料プランが必要になるため、活用する前提であれば有料プランにアップグレードして、検証したい目的であれば他のデザインで試すようにしましょう。

![スクリーンショット 2024-12-17 2.36.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/8a6b7620-0be1-4168-70e5-955f099efceb.png)


## FigmaプラグインからReactコード生成

今回は、サイドメニューのGenerated Codeの各項目を以下のとおりにして解説します。

- Framework: React
- Styling: Tailwind
- Language: TypeScript
- Testing Framework: None

`Generate Code`ボタンをクリックしてしばらくすると以下のようにReactコードが生成されます。

![スクリーンショット 2024-12-17 2.16.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/a5370e89-ccf9-467a-8dad-df360776697e.png)

## Reactプロジェクト準備

今回は、TypeScriptとTailwind CSSを活用するため、`npx create-react-app my-app --template typescript`でTypeScriptテンプレートのReactプロジェクトを生成して、[Tailwind公式ドキュメントどおりにセットアップ](https://tailwindcss.com/docs/guides/create-react-app)してReactプロジェクトを準備します。

## 動作確認

出力されたものをそのままコピペして、`HomePage.tsx`のコードは`src/App.tsx`に入れて`export const HomePage: React.FC = () => {`を`function App() { ... };`と`export default App;`の形に変更することで以下のようにプラグインで生成されたReactコードそのままで動作確認することができます。
ただし[前回も解説した](https://qiita.com/gremito/items/89d8f4bb17c84e4f9f12#%E8%A3%9C%E8%B6%B3)とおりで細かいデザイン崩れや適応できていない箇所などあるため、そこはよしなに編集して調整が必要になりますが、0→1で作るよりも遥かに開発しやすいと思います。

![スクリーンショット 2024-12-17 2.19.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82601/5eaaf091-b5f1-449a-9027-caa28faaa74e.png)
【Linux / Mac】「enhancd」というツールでcdコマンドを爆速化

ディレクトリ移動は、ターミナルで作業をしているときに頻繁に行う基本的な操作です。`cd`コマンドを使って移動しますが、パスが長くなると面倒に感じることもあります。そんな時に便利なのが、ディレクトリ移動を爆速化するツール「`enhancd`」です。

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674933/8fa2a96b-7d64-7d70-ea1b-502f5afed552.gif)


この記事では、`enhancd`のインストール方法と、その使い方を説明します。

---

## 目次

1. [`enhancd`とは](#enhancdとは)
2. [インストール方法](#インストール方法)
3. [使い方](#使い方)
4. [まとめ](#まとめ)

---

## `enhancd`とは

[`enhancd`](https://github.com/so-fancy/enhancd)は、ターミナルでのディレクトリ移動を効率化するツールです。`cd`コマンドを強化し、過去に移動したディレクトリを履歴から素早く検索して移動したり、補完機能を提供してくれるため、作業効率が大幅に向上します。

主な特徴:
- 過去のディレクトリに迅速にアクセス
- 検索機能で素早くディレクトリを絞り込める
- ディレクトリ履歴をインタラクティブにナビゲート
- 自動補完機能でパスの入力を省力化

---

## インストール方法

`enhancd`は、`zsh`や`bash`といったシェルで動作します。以下の手順に従ってインストールできます。

```bash
# 必要なディレクトリを作成
git clone https://github.com/b4b4r07/enhancd ~/.enhancd
```

その後、`.zshrc`や`.bashrc`に以下の設定を追加して、`enhancd`を読み込むようにします。

```bash
# .zshrcや.bashrcに追加
source ~/.enhancd/init.sh
```

設定ファイル編集後、シェルを再起動するか、以下のコマンドで設定を反映させます。

```bash
# 設定を反映
source ~/.zshrc  # または source ~/.bashrc
```

これでインストールは完了です。

---

## 使い方

インストールが完了したら、`enhancd`を使ってディレクトリ移動を高速化できます。

単に`cd`コマンドを入力してEnterを押すと、以下のように移動先ディレクトリの候補が表示されます。十字キーで移動先ディレクトリを選択することで、選択したディレクトリに移動することができます。

```bash
[keita@KeitanoMacBook-Pro] ~/ % cd
> 
/Users/keita
/Users/keita/Documents/Program/python
/Users/keita/Documents/AppDevelopment
/Users/keita/Documents/Program/python/DjangoFirstProject
/Users/keita/PycharmProjects
/Users/keita/Documents/Docker
/Users/keita/Documents
/Users/keita/.enhancd
/Users/keita/Documents/Program
/Users/keita/Pictures
```


### `enhancd`の補完機能

`enhancd`は、途中までディレクトリ名を入力するだけで過去に移動したディレクトリや、存在するディレクトリが補完されるため、移動が非常に速くなります。

例えば、`/Users/keita/Documents`というディレクトリに移動したいとき、`/Doc`と入力すれば、すでに訪れた`/Users/keita/Documents`やその他の`Documents`以下のディレクトリが候補として表示されます。

```bash
[keita@KeitanoMacBook-Pro] ~/ % cd Doc
> 
/Users/keita/Documents/Docker
/Users/keita/Documents
/Users/keita/Documents/Program/DockerProject
```

## まとめ

`enhancd`は、ターミナルでのディレクトリ移動を驚くほど効率化するツールです。ディレクトリ履歴の補完や検索機能、インタラクティブなディレクトリナビゲーションを活用することで、日々の作業を大幅にスピードアップできます。インストール方法も簡単で、`brew`を使えば手軽に導入できるので、ぜひ試してみてください。
Amazon Titan Text Embeddingsの日本語のトークン数見積もりがしたい

## 前提
* 本記事の内容は2024/12/17時点の以下のAmazon Titan Text Embeddingsモデルで試した内容なので、最新では異なる情報となっている場合があります。
    * Titan Embeddings G1 - Text（以下、Titan Embeddings v1）
    * Titan Text Embeddings V2（以下、Titan Embeddings v2）
* Bedrockのモデルアクセスは設定済みの状態で話を始めています。
* 上記Embeddingモデルの精度については本記事では扱っていません。
* 本記事に記載の内容・設定を実施して生じた問題については責任を負いかねます。

## 何をしようとしてどうなったか
* Amazon Bedrock上で提供されているAmazon Titan Text Embeddingsモデルを利用するにあたって「コスト見積もり＝トークン数の見積もり」をしようとした。
* OpenAIにおける[tiktoken](https://github.com/openai/tiktoken)のようなトークナイズライブラリもなく、色々調べた結果、実際にAPIを実行するかプレイグラウンドで確認するほか手がない。
    * なお、Embeddingモデルはプレイグラウンド非対応。
* しょうがないので、[livedoorニュースコーパス](http://www.rondhuit.com/download.html#ldcc)を使って実際にどのぐらいのトークン数だったかを確認した。
* 結果として、**Titan Embeddings v1で1文字あたり約0.548トークン**、**Titan Embeddings v2で1文字あたり約1.01トークン**となった。
:::note warn
あくまでlivedoorニュースコーパスでの結果であるため、ドキュメントの種類によって1文字あたりのトークン数は変化する可能性があります。
:::

## 実施内容
### データについて
上述の通り、[livedoorニュースコーパス](http://www.rondhuit.com/download.html#ldcc)の記事本文を利用しました。
ただ、7000件以上と量が膨大であるため、9つの記事カテゴリから各20件ずつをランダムにピックアップした計180件を利用しました。

### モデルの実行
Bedrockの[ユーザーガイド](https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/bedrock-runtime_example_bedrock-runtime_InvokeModelWithResponseStream_TitanTextEmbeddings_section.html)にあるような実装をして実行しただけなので詳細は割愛します。

## 結果
180件のデータにおける1文字あたりのトークン数は以下の通りとなりました。
|| Titan Embeddings v1 | Titan Embeddings v2 |
| --- | :---: | :---: |
| 平均値 | 0.548320 | 1.011225 |
| 中央値 | 0.550780 | 1.034148 |
| 最小値 | 0.423309 | 0.701807 |
| 最大値 | 0.678189 | 1.169844 |

新しいv2モデルの方がトークン効率が良くなるのかと思っていましたが、実際にはその逆という結果でした。
ただ、1000トークンあたりの料金がv1の\\$0.0001に比べてv2は\\$0.00002と1/5になっている（2024/12/17時点）ので、1文字あたり2.5トークンとかにならない限りコスト的にはv2の方が良さそうですね。

### おまけ
一応、記事のカテゴリごとにバラツキがないかを見てみましたが、大きなバラツキはなさそうでした。
<caption>各カテゴリ20件における1文字あたりの平均トークン数</caption>

|| Titan Embeddings v1 | Titan Embeddings v2 |
| --- | :---: | :---: |
| 独女通信 | 0.552917 | 1.036024 |
| ITライフハック | 0.532223 | 0.962088 |
| 家電チャンネル | 0.528893 | 0.989147 |
| livedoor HOMME | 0.540681	 | 1.032803 |
| MOVIE ENTER | 0.595403 | 1.087740 |
| Peachy | 0.553208 | 1.014785 |
| エスマックス | 0.475864 | 0.864732 |
| Sports Watch | 0.581880 | 1.070773 |
| トピックニュース | 0.573810 | 1.042937 |

## まとめ
* livedoorニュースコーパスを用いてAmazon Titan Text Embeddingsモデルの2モデルについて日本語における1文字あたりのトークンを計算したところTitan Embeddings v1で1文字あたり約0.548トークン、Titan Embeddings v2で1文字あたり約1.01トークンという結果になりました。
* コスト的にはv2の方が安上がりですが、トークン効率がv1の半分ぐらいなので長いドキュメントについては分割などの処理が別途必要になりますね。
    * 例：1万文字のドキュメントの場合、v1では約5500トークンで済みますが、v2では約1万トークンとなり分割が必要になります。（v1もv2も入力トークン数の上限は8k）
bootstrap buttonタグにカスタマイズ

bootstrap buttonタグにて、色をカスタマイズするには。
カスタムCSSを使用した色のカスタマイズ方法
しかし、Bootstrapの既定の色だけでは不十分な場合もあります。

そんなときには、自分でCSSを書いて色をカスタマイズすることもできます。

例えば、以下のように新たなクラスを作成し、その中でボタンの背景色や文字色を指定することができます。

.btn-custom {
  background-color: #FF1493;
  color: #ffffff;
}
この「btn-custom」というクラスをボタンに適用すると、ピンク色のボタンが作成されます。

<button type="button" class="btn btn-custom">Custom</button>
ただし、この方法を使用する際には注意が必要です。Bootstrapのクラスと自分で作成したCSSクラスが競合する可能性があるためです。
特に、Bootstrapのクラスを上書きしたい場合には、CSSの特異性のルールを理解しておくことが重要です
。必要に応じて、より具体的なセレクタを使用したり、「!important」を使用してスタイルルールを強制的に適用したりすることができます。
「AWSコスト削減ポイント紹介」というタイトルで話をしてきました

## はじめに

みなさん、こんにちは。先日、米国ラスベガスでAWS re:Invent 2024が開催されている裏側で、パーソルテクノロジー株式会社主催の「FinOps入門×三大クラウドコスト削減術」セミナーがありました。

今回はそちらのセミナーで「AWSコスト削減ポイント紹介」というタイトルで話をしてきましたので講演資料とアーカイブ動画のご紹介をさせてください。

https://connpass.com/event/335617/

## セッションのハイライト

![本日話すこと](https://files.speakerdeck.com/presentations/72dc4eea925d415bbf9e0257931dc328/slide_2.jpg)

![ここから始めよう](https://files.speakerdeck.com/presentations/72dc4eea925d415bbf9e0257931dc328/slide_3.jpg)

![よくある最適化ポイント](https://files.speakerdeck.com/presentations/72dc4eea925d415bbf9e0257931dc328/slide_4.jpg)

、、、具体的に改善候補のリソースをどうみつけるの？

![ウッカリやらがしがちなポイント](https://files.speakerdeck.com/presentations/72dc4eea925d415bbf9e0257931dc328/slide_6.jpg)

![S3ライフサイクルルールの落とし穴](https://files.speakerdeck.com/presentations/72dc4eea925d415bbf9e0257931dc328/slide_7.jpg)

、、、他にはどんなポイントがあるの？

![アーキテクチャー最適化の話](https://files.speakerdeck.com/presentations/72dc4eea925d415bbf9e0257931dc328/slide_10.jpg)

![とりあえず転送しておこうをやめた話](https://files.speakerdeck.com/presentations/72dc4eea925d415bbf9e0257931dc328/slide_11.jpg)

、、、他にはどんなアーキテクチャ最適化があるの？

## 講演資料のフルバージョンはこちら

気になった方はぜひ講演資料に目を通していただければ幸いです。

<script defer class="speakerdeck-embed" data-id="72dc4eea925d415bbf9e0257931dc328" data-ratio="1.7777777777777777" src="//speakerdeck.com/assets/embed.js"></script>

## 最後に

FinOpsの目指すべきゴールは、正しくはコスト削減ではないのですが、今回はあえて削減の部分にフォーカス当てて、AWSにおけるクラウドコスト削減に関するノウハウや、FinOpsならぬFinOopsな失敗談などを紹介してきました。

もしFinOpsへ興味を持たれた方がおられましたら、ぜひこの機会にコミュニティー活動への参加を検討してみてはいかがでしょうか。日本のFinOps業界をぜひ一緒に盛り上げていきましょう！

https://finops-jp.github.io/

---

- AWS は、米国その他の諸国における Amazon.com, Inc. またはその関連会社の商標です。
- その他、本記事に記述してある会社名、製品名は、各社の登録商品または商標です。
【Git,GitHub】リモートリポジトリのデータをローカルに取り込む #備忘録

## 現在のリモートの確認
まず、GitHub リポジトリのリモート設定を確認します。
```
git remote -v
```
と入力し、先頭のリモート名を確認します。以降リモート名は**origin**だと仮定して進めますが、もし違っていれば適宜読み替えてください。

## ローカルに取り込むブランチの作成または更新
今回はローカルの`develop`ブランチにデータを取り込みます。

まず、もしローカルに`develop`ブランチがなければ以下のコマンドを入力して作成して移動します。すでに作成済みなら`-c`オプションは不必要です。
```
git switch -c develop
```
なお、ブランチのリストは以下のコマンドで確認できます。
```
git branch
```
データを取り込むdevelopブランチに移動できていればOK。

## リモートのデータをローカルに取り込む
以下のコマンドでローカルのdevelopブランチにリモートのdevelopブランチのデータを取り込むことができます。
```
git pull origin develop
```
以上です。
「FinOpsの実践アプローチのご紹介」というタイトルで話をしてきました #CNDW2024

## はじめに

みなさん、こんにちは。先日、CloudNative Days Winter 2024にて、クラウドを扱う全員が取り組むべき「FinOps」の概要から、業界標準のFinOps実践アプローチ手法である「FinOpsフレームワーク」について実践ノウハウを交えて話をしてきました。

今回はそちらの講演資料とアーカイブ動画のご紹介をさせてください。

https://event.cloudnativedays.jp/cndw2024/talks/2447

## セッションのハイライト

![今日話すこと](https://files.speakerdeck.com/presentations/86a162c1f75e4a4c945ffb356d053d29/slide_2.jpg)

![FinOpsはクラウドコストに関する課題解決のための方法論](https://files.speakerdeck.com/presentations/86a162c1f75e4a4c945ffb356d053d29/slide_4.jpg)

![クラウド運用についてこんなこと聞いたことないですか](https://files.speakerdeck.com/presentations/86a162c1f75e4a4c945ffb356d053d29/slide_6.jpg)

![エンジニアはあまりコストに興味がない？](https://files.speakerdeck.com/presentations/86a162c1f75e4a4c945ffb356d053d29/slide_7.jpg)

![FinOpsエンジニアは熱いジョブである](https://files.speakerdeck.com/presentations/86a162c1f75e4a4c945ffb356d053d29/slide_8.jpg)

![FinOpsはめちゃくちゃ面白い](https://files.speakerdeck.com/presentations/86a162c1f75e4a4c945ffb356d053d29/slide_9.jpg)

![FinOpsやろうぜ](https://files.speakerdeck.com/presentations/86a162c1f75e4a4c945ffb356d053d29/slide_10.jpg)

![いざFinOpsをはじめるといっても](https://files.speakerdeck.com/presentations/86a162c1f75e4a4c945ffb356d053d29/slide_11.jpg)

![FinOpsを成功させるために心がけること](https://files.speakerdeck.com/presentations/86a162c1f75e4a4c945ffb356d053d29/slide_12.jpg)

![まずは軽くおさえておこう](https://files.speakerdeck.com/presentations/86a162c1f75e4a4c945ffb356d053d29/slide_13.jpg)

、、、つづく。

## 講演資料のフルバージョンはこちら

続きが気になった方は、ぜひ講演資料に目を通していただければ幸いです。なお、途中でPRも入っておりますがその点はご了承ください^^;

<script defer class="speakerdeck-embed" data-id="86a162c1f75e4a4c945ffb356d053d29" data-ratio="1.7777777777777777" src="//speakerdeck.com/assets/embed.js"></script>

また、公式イベントサイトにて**アーカイブ動画**も公開されています。ログインが必要となりますが資料に書かれていないことも話をしていますのでよければご参照ください。

https://event.cloudnativedays.jp/cndw2024/talks/2447

## 最後に

グローバルでは単なるクラウドの活用から先に進み、クラウドのビジネス価値を最大化するための取り組みである「FinOps」の実践が当たり前になりつつあります。

その一方、国内ではFinOpsの知名度は依然として低く、コストを最適化するFinOpsの継続的な活動は、エンジニアから時間を奪うだけの存在だと考える現場もいまだに多い状況です。しかし、グローバルからはやや遅れてではあるものの近い将来、日本でも盛り上がりを見せてくるのではないかと推測しています。

もしFinOpsへ興味を持たれた方がおられましたら、ぜひこの機会にコミュニティー活動への参加を検討してみてはいかがでしょうか。日本のFinOps業界をぜひ一緒に盛り上げていきましょう！

https://finops-jp.github.io/

---

- 本記事に記述してある会社名、製品名は、各社の登録商品または商標です。
Windowsにwslを入れてslコマンドで遊べるようにする

## 背景
- Windowsユーザーの人にもslコマンドの素晴らしさを伝えたい

## 手順
### 1. WSLのアクティベート

WSLが有効になっていない場合、以下の手順で設定する。

 - PowerShellを管理者権限で起動し、以下のコマンドを実行
	
```
wsl --install
```

- PCを再起動。これでWSLがアクティベートされる

### 2. WSLに入る

- スタートメニューに「Ubuntu」と入力し起動

- 起動後、Linuxのシェル環境に入る


### slコマンドを入れる

- まずアプデ
```
sudo apt update
```

- slコマンドをインストール( `-y`オプションは全ての確認にYesを選択するオプション)
```
sudo apt install sl -y
```

- 動作確認: 蒸気機関車が走ればOK

```
sl
```
ChatGPTの使いどころ

## ChatGPTをテストに使う

いまでは、説明の必要もないであろうほど普及しているChatGPTですが、メールアドレスを登録するだけで使い始めることができます。こちらのリンクからどうぞ。

念のため、これから使ってみたいという方のために簡単に説明をしますと、検索エンジンに自然言語で問い合わせをするように質問をすると（これをプロンプトと言います）、AIの集合知の中から回答をしてくれるものです。  
[[OpenAI]](https://openai.com/ja-JP/chatgpt/overview/)

さすがに、最新のテストメソッドなどには追いついておらず、まだ組み合わせテストも自力で組むことはできませんし、期待値の自動生成なども、そのまま使うのは難しいですが、プロンプトのフォーマットを工夫し、ChatGPTに学習をしてもらうことで、欲しい結果を得やすくなります。

![IMG_9136.JPEG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/39620bb1-5660-0b26-e46b-04cafdad51ba.jpeg)  
アドベントカレンダーですから、クリスマスツリーをどうぞ。

---

### 慣れないドメインのテスト設計

Webサービスにもいろいろあります。金融系、ECサイト、何かの目的を持ったビジネスを加速するサイト。自社製品ならともかく、品質保証活動の支援などでは、常に自分の得意なドメインのテストをやれるとは限りません。中には、自分が不慣れなドメインのテストをやらねばならないこともあるでしょう。

こんなときには、ChatGPTに問い合わせてみましょう。

#### テストのクライテリア
同様に、「どこまでテストをすればいいか」で悩むこともあります。こんな時は、参考にChatGPTに聞いてみましょう。基本的に、クリアすべき品質基準を提案してくれるでしょう。

#### テストアクティビティのセット
慣れないドメインのテストの際、どんなテストを行ったらいいかを聞いてみましょう。意外と、忘れていた観点を教えてくれるかもしれません。

---

## ペルソナの作成

同様に、テスト観点や品質基準を考える際、ペルソナは大いに参考になります。ペルソナを作る時には、製品を使う動機や期待なども聞いてみてください。そこから、どういうクライテリアを目指せばいいのか、ヒントが得られます。

---

## 英語の学習

これは、モバイル版のChatGPTを使うと面白いです。  
こんな感じでスタートするとよいでしょう。

> 「私は英語の学習をしているテストエンジニアです。英会話の練習に、QAの◎◎の話題をしたいのですが、英語で話してもらえますか？」

これだけで、会話が始まります。  
生の英会話でQAやテストの話をする機会はなかなかないので便利ですし、どれだけ間違っても恥ずかしくありません！そしてお金もかかりません！

けっこうテストの話もできますよ！

---

## まだChatGPTには難しいこと

### 組み合わせテスト
それっぽいものは作れるのですが、まだちゃんとした組み合わせテストを出すのは難しいです。

### テストケースそのものの出力
テストケースを出すためには膨大な製品の学習が必要です。その学習をしている間に、テストを作ってしまった方が早いです。

### 期待値の出力
これも同様で、学習に時間をかける間に書いてしまった方が早いです。

---

## おわりに

まだまだいろいろな使い方ができそうですし、そろそろそういった活用本もたくさん出てきていますが、ソフトウェアテストを目的とする場合、開発の余地はありそうです。いろいろ工夫していきたいですね。ちなみに、この文章の誤字脱字確認にもChatGPTを使っております。
24日目にLINEミニアプリが完成する初心者 ―― Day17. ショールーム来場予約の実装


前回は「24 日目に LINE ミニアプリが完成する初心者 ―― Day16. 顧客管理機能の実装」と題して、問い合わせ内容を Google スプレッドシートに出力する機能を実装しました。

https://qiita.com/non_watanabe/items/df82a6b423ceac05dc33

<br/>
今回は、新機能としてショールーム来場予約機能を実装していきます。

# 予約スケジュールの作成

今回は Google カレンダーの予約スケジュール機能を使って、ショールーム来場予約機能を作って行きます。

予約にかかる手間を省くことができる上、Google カレンダーに予約情報が自動で追加されるためとても便利です。

https://workspace.google.com/resources/appointment-scheduling/?utm_source=calendar-in-product&utm_medium=et&utm_campaign=booking

<br/>
作成は Google カレンダー左上の作成ボタンから「予約スケジュール」を選択することで作成ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/a539b505-df8d-e96b-c281-ea5ff9c3868d.png)

<br/>
今回はテストなので「予約スケジュール」という名前で作成します。

予約時間は 2 時間で、マハロリビングの営業スケジュールに合わせて以下のように組んでみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/a1730977-dbde-de0a-f401-d663cbb5d2ae.png)

<br/>
次へ進むと詳しい予約の設定を記入画面が出てきます。

今回はショールーム来店予約のため、場所と会議の項目は対面会議に設定しています。

その他は説明の入力と予約フォームを設定しています。

予約フォームは、予約時に入力してもらう項目を設定することができます。

今回はデフォルトの姓、名、メールアドレスに加え、電話番号とご相談内容を追加しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/aa297ec6-aaa0-4d01-5509-8d9e22137256.png)

「保存」を押したら作成は完了です！

# 埋め込みコードの取得

予約スケジュールの作成が完了したら埋め込みコードを取得して行きます。

作ったスケジュールをクリックすると「共有」という項目が表示されるのでクリックしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/8d818c54-4676-f714-d280-0abfc47cb10d.png)

ウェブサイトに埋め込むというタブにインライン予約ページという項目があるので、これを開くと埋め込みコードが表示されるので、これをコピーしておきましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/3ddd0522-6ec2-bdd6-172b-10d30420d7d5.png)

# ショールーム来店予約ページの作成

ではページを作成して行きます。

まずは`ShowroomPage.tsx`を作成して行きます。

```tsx:src/nextjs/components/pages/showroom/ShowroomPage.tsx
export default function ShowroomPage() {
  return (
    <div>
      <h1 className="text-3xl font-medium text-center p-12">
        ショールーム来店予約
      </h1>
      <iframe
        src="your_src"
        style={{ border: "none" }}
        width="100%"
        height="600"
      />
    </div>
  );
}
```

コピーした埋め込みコードでは`style="border: 0"`と`frameborder="0"`の表示がありますが、frameBorder 属性は HTML5 で非推奨になったため`style={{ border: "none" }}`と修正しています。

<br/>
これをページで表示させるため、ページも作成して行きます。

```ts:src/nextjs/pages/showroom/index.tsx
import ShowroomPage from "@/components/pages/showroom/ShowroomPage";

export default function Showroom() {
  return <ShowroomPage />;
}
```

<br/>

これで`/showroom`にブラウザでアクセスしてみて Google カレンダーの予約スケジュールが表示されれば実装は完了です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743174/e5c9be05-0cb6-c5f3-84e5-db9b7966ec9b.png)

# デプロイ

ここまでの実装が完了したらいつも通り以下のコマンドを`line-liff-v2-starter`配下で実行しデプロイを行っておきましょう。

```
$ netlify deploy --build --prod
```

# まとめ

ここまでで Google カレンダーの予約スケジュールの機能を使ったショールーム来店予約ページを作成しました。

次回は、この機能をもう少し細かく作成して行きたいと思います。

残りは 7 日！
気になる方は是非フォローやカレンダー購読をお願いします:star: