OmniAICreator/Qiita-1.07M huggingface dataset:
Ubuntuのセットアップ

Ubuntu24.04をインストールした際の手順メモ．ほかのバージョンに比べてUIがおしゃれになっているが，基本的に他のUbuntuバージョンも手順は同じ．
右の目次から各手順に飛べます．

# 初期設定手順
初期設定では，インストール開始から完了まで結構時間がかかる

## 1. Try or Install Ubuntu
初回起動すると，以下のような黒い画面が表示されるので，「Try or Install Ubuntu」を選択（カーソル操作はできないので，キーボードの↑↓で選択，Enterで決定）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/5dc99bb6-34af-19b5-946d-bdeceaad90d9.png)

## 2. 言語選択
welcome画面が起動したら，まずは言語選択．日本語も選択できるが，ターミナルは日本語入力不可でファイル名のみ日本語になってしまうため，ファイル移動（cdコマンドの利用）が一苦労...英語設定にするのがおすすめ．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/afeb8d1a-0524-f87f-8efd-53200cbe6224.png)

## 3. Accessibility
24.04で初めて聞かれた．基本何も設定せず，次へ．（お好みでどうぞ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/74f460ff-027e-065b-14f0-53e4d8653f1d.png)

## 4. キーボードレイアウトの設定
キーボードレイアウトはもちろん日本語のものを選ぶ．右上の「Detect」は全く役に立たないので，下にある「Type here...」というところでちゃんと確認して設定すること．（特に記号の位置は要チェック）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/c06367a2-4698-0f07-399f-9f393d138e93.png)

## 5. ネットワーク設定
自分のPC環境に合わせて選択．ここで選択したものに応じて，この後のインストールが行われる．（ここでのネットワーク設定はセットアップ完了後，いつでも変更できる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/2ef509dc-0c29-9436-1e95-fee862dd429b.png)

## 6. InstallかTryか
最後にインストールするorトライする？と聞かれる．多分，Tryだと電源を落とせば元のOSが復活するとかそういうもの．今回はインストールしたいので，素直にインストールを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/3014c3b2-24a2-d17b-3343-f2d4dade6bae.png)

## 7. Install方法の選択
Ubuntu24.04になって初めて聞かれたが，特にyamlとかも用意していないので，「interactive installation」(これが今までのデフォルト)を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/3aaf3668-9f8f-20b2-c4a8-392760218d41.png)

## 8. インストールアプリの設定
基本的には「Default selection」を選択．Extendedはおそらくインターネットに繋がらない環境下でインストールする人向け．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/6409bbfe-5c94-a426-ed7a-d449b133708b.png)

## 9. Additional appの設定
（お好みでどうぞ）
何にも✅を入れないで，後からインストールしてもよいが，wifi関係のthirdpartyパッケージはロボット開発には必要になりがちなので，初めからインストールしてもらう．一方で，動画用アプリはいらないので，✅は入れなかった．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/ccb331ac-4f11-6ab5-89c4-7452a7743318.png)

## 10. ハードディスクを初期化しますか？
ハードディスクの初期化を選ぶ．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/176f1186-8c05-4432-f6a6-7129c0f034aa.png)

## 11. PCのホスト名，login時のユーザー名＆パスワード設定
* your name: なんでもいい
* your computer's name: ホスト名（xxx@yyyの後半部分(yyy)）
* your username: login時のユーザー名（xxx@yyyの前半部分(xxx)）
* password: login時のパスワード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/2840003a-7847-26c8-c62d-cb971b59e929.png)

## 12. 地域の選択
コンピュータの時刻などが，ここで選択した地域のものになる．「Tokyo」を選択（デフォルトで表示されるはず）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/a9ba0629-130f-d5a8-c281-d8cac0992300.png)

## 13. インストール開始
右下のボタンを押してインストール開始
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3250323/eaa90c89-8184-a33c-e108-ea8dc896bd87.png)

## 14. 再起動
インストールが終わったら，再起動を求められる．
「restart」ボタンを押してしばらくすると，「インストールデバイスを抜き，Enterボタンを押せ」と表示されるので，それに従うと，ようやく再起動できる．（放っておくと再起動できないので，注意！）
条件付きフォワーダー設定のせいで業務停止させた話

## はじめに
[本番環境などでやらかしちゃった人 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/yarakashi-production)の18日目になります。

私が新卒2年目の頃のお話です。顧客名や構成などの内容は一部ぼかして記載しています。

**こんな人に読んで欲しい**
- 仕事に慣れてきた若手
- 公式Docsを鵜呑みにしている人

**こんなことが分かります**
- 既存環境を細かく確認をすることの大切さ
- 公式Docsでも安易に信用しない懐疑心

## 何をやらかしたのか
簡単にまとめると、**DNSの条件付きフォワーディングの設定を入れたせいで、オンプレミス環境から既存のAzure SQL Databaseへの接続ができなくなりました**。

## 構成図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3964479/8d2c9d2d-524f-fe8c-9853-55b2197eef11.png)
※引用元は[こちらの公式Docs](https://learn.microsoft.com/ja-jp/azure/architecture/networking/architecture/azure-dns-private-resolver#use-a-dns-forwarder-vm)

## インシデント発生までの経緯
既にAzureを利用されているクライアントの環境に、新たにAzure SQL Databaseを導入するプロジェクトのリーダーをしていました。

DBにはオンプレミスから接続するのですが、クライアント端末からプライベートリンク（リソースにプライベートIPを付与するサービス）経由でのDBへは、構成図のようなプロセスを経て接続します。

ここで肝心なポイントは、オンプレミスのDNSサーバー（構成図のInternal DNS）です。

クライアント端末はオンプレミスのDNSサーバーで名前解決をしますが、このDNSサーバーはリソースのプライベートIPなんて知りません。このままではパブリックIPで名前解決されてしまいます。

「なら、DNSに無理やりAレコードを書けばいいのでは？」と思われるかもしれませんが、Azureは仕様上「**Private DNS Zoneと呼ばれるリソースが紐づけられた仮想ネットワークからのみプライベートIPでの名前解決が可能**」になります。

つまり、構成図のVNet-hub-001上に存在するDNS Forwarder経由で名前解決を行う必要があります。

既存環境にはこのDNS Forwarderに該当するDNSサーバーがあったので、あとはInternal DNS→DNS Forwarderへの再問い合わせ処理を実現するだけです。

これを実現する技術が**条件付きフォワーディング**です。簡単に言えば

```
ドメイン：database.windows.net
問い合わせ先：DNS ForwarderのIPアドレス
```
のような設定をすることで、**database.windows.netをドメイン名に含む名前解決をDNS ForwarderというDNSサーバーに丸投げ**するようになります。

ここで考えてみてほしいのですが、もしも今回新たにデプロイするDB以外のAzure SQL Databaseにオンプレミスから接続する場合はどうなるでしょうか。

はい、**ドメインにdatabase.windows.netが含まれるのでDNS Forwarderに丸投げ**です。

この設定を入れた直後、クライアントから「既存DBに接続できなくなりました。」という連絡を受けました。別サブスクリプションで管理するDBに接続できなくなってしまったのです。

このDBでは、業務にかなり密接に関わるデータを管理しており、時期的にデータの棚卸しをしていたので、結果的にクライアントの業務を止めてしまいました。

DBへの接続については、接続元IPを制限して、管理者がオンプレミスからパブリックIPで接続するという運用を行っていました。

この問い合わせを受けて、条件付きフォワーディングのドメイン条件に**リソースのFQDN**を設定することで事なきを得ました。

## なぜこのようなミスが発生したのか
プロジェクト自体は単純なものですが、気を付けるべきポイントがいくつかありました。

- 既存のAzure環境についての知見がない
- プロジェクト自体の開始が遅れてスケジュールがギリギリ
- 私がコロナに感染して出勤停止で大幅な遅延

スケジュール遅れもありますが、特に1つ目が今回のインシデントを発生させてしまった要因になります。既存環境や運用方法の知見が十分にないことで引き起こしたインシデントです。

既存のDBやその運用方法を知っていれば、安易に条件付きフォワーディングの設定を入れずに、初めからFQDNで対処できていました。

また公式のDocsではドメインを指定してましたが、今後リソースが増えることを考慮してFQDNを採用することもできました。

## 同じミスを引き起こさないためには
- 既存環境については前もってヒアリングを徹底する
- 「公式のDocsに書かれているから」と安易に信用しない

この2つに尽きます。

ここまで読んでいただきありがとうございます。

Xではエンジニアに有益な発信をしていますので、ぜひフォローよろしくお願いします！！

https://twitter.com/satan_engineer
良いエラーメッセージvs悪いエラーメッセージ

この記事は クラウドワークス グループ [Advent Calendar 2024](https://qiita.com/advent-calendar/2024/crowdworks) シリーズ1の19日目の記事です。

## はじめに
エラーメッセージの内容を考える際、個人的に既存の例を参考にすることが多いですが、もしその既存のメッセージが「悪いエラーメッセージ」であった場合、それを無意識に流用してしまうリスクがあります。

常に疑いを持ち、エラーメッセージの設計を見直すことが重要です。そのためには、改めて **「エラーメッセージとはこうあるべき」という基本的な概念を定期的に見直す必要がある** と考えました。特に、普段はわかっているつもりでも、見返してみることで、よりユーザーに寄り添ったメッセージを意識することで様々なメリットを得ることが可能です。

「当たり前だけど、見返してみたらもっとよくできるのでは」と思う場面で参考となる記事があればと思い、この内容を書くに至りました。

## エラーメッセージの基本
以下はエラーメッセージの重要な観点となります。

- **問題の原因を明示しているか**
- **解決策を提供しているか**
- **安心感を与えられているか**

## 悪いエラーメッセージの例
エラーメッセージの内容が不十分・不適切だと、ユーザーのフラストレーションが増す原因となってしまいます。

- **曖昧な表現**
    - 例：`エラーが発生しました`
    - 問題点: 原因も解決策も不明で、ユーザーのフラストレーションを助長する
- **専門用語の多用**
    - 例：`StackOverflowException`
    - 問題点: 一般ユーザーには内容が理解できない
- **無責任な態度**
    - 例：`予期しないエラーが発生しました。もう一度試してください。`
    - 問題点: 問題解決の責任をユーザーに丸投げしている印象を与えます。


## 良いエラーメッセージの条件
以下の条件を意識することが重要と考えます。

- **具体性**： 何が問題であるのかを具体的に伝える。※
    - 例: `10文字以内で入力してください`
- **親切である**：ユーザーに対して配慮のある言葉を選ぶ。
    - 例: `処理中に問題が発生しました。お手数ですが、もう一度お試しください。それでも解決しない場合はサポートまでお問い合わせください。`
- **解決策の提示**：解決方法を明確に案内し、必要に応じてリンクを設置する。
    - 例: `ネットワーク接続が切れています。Wi-Fiまたはモバイルデータ通信を確認してください。`




![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3924929/ebf39dbb-6cdf-cde0-797c-ceec679ac31d.png)


よく見るメッセージですが、改めて見るとこんなに簡潔的な内容でも、上記条件をすべて満たしていることがわかります。
### ※例外　[セキュリティに配慮]

場合によっては、攻撃者にヒントを与えてしまい、攻撃を容易にしてしまうため、**具体的な内容を避けること=良いエラーメッセージとなる場合もあります。** 
例えば、以下のようなケースです：

**NG**：`パスワードが違います`、 `ユーザーIDが違います`
 **OK**：`メールアドレスまたはパスワードが正しくありません`
 
 参考：[体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践](https://www.sbcr.jp/product/4797393163/)


## 結論
エラーメッセージとは、**ユーザー体験の向上やサービスの信頼性を高める上で欠かせない要素** です。
適切なエラーメッセージは、以下のようなポジティブな影響をもたらします。

- **ユーザー満足度の向上**
- **サポート工数の削減**
- **システムの信頼性向上**

一方で、**内容の具体性については、セキュリティリスクを慎重に考慮し、適切なバランスを取ることが求められます。**

今後も、日常的に他のサービスのエラーメッセージを観察し、良い例や改善のヒントを学びながら、自身の設計に反映していきたいと考えています。ユーザー目線を忘れず、使いやすく信頼されるサービスを提供できるよう、継続的に改善を重ねていきます。

## おまけ
ChatGPT様に大喜利を仕掛けてみました。
#### 「こんなエラーメッセージは嫌だ！」

```
「おっと、またやっちゃったね！君、ほんとドジだなぁ」
「エラー発生！でも君、もう気にしないんだろ？勝手にやって！」
「システムが混乱してます。私も君の状態が理解できません」
「プログラムが暴走中。あなたも一緒に逃げて！」
「エラー！あれ、もう一度試す？それとも諦める？」
「データが壊れてます。でも大丈夫、だって人生も壊れてるでしょ？」
```

#### 「こんなエラーメッセージがあったら面白いのになあ〜」

```
「エラー発生！でも、君がどうしても直したいなら、ちょっとだけ魔法をかけてあげようか？」
「うーん、うまくいかなかったか。でも大丈夫、君にはまだ未来がある！」
「システムが停止しました。でも、君はまだ働き続けてるから、がんばれ！」
「なんと、エラーの原因は未解決。まるで人生みたいだね！」
「エラー発生！でも心配しないで、私たちは一緒にいられるから」
「接続エラー！まるで君の友達のように、いつもこんな時だけ現れるんだ」
```
MacOS SequoiaにFortranの環境を構築する

## この記事でわかること
- MacOS SequoiaにVScodeを用いたFortranの実行環境構築
- 主要な計算ライブラリの導入

## 下準備
まずはじめに、MacOS用パッケージマネージャのHomebrewのインストールを行います。

すでにインストールされている場合は飛ばしてください。
#### 手順
・ターミナルを開く
・以下のコマンドを入力
~~~ 
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh
~~~
・バージョン確認
~~~
brew -v
~~~
・無事にインストールできている場合は、以下のようにバージョンが出るはず
~~~
-> Homebrew 4.4.5
~~~

・これでHomebrewのインストールが完了

## gfortranのインストール
Fortranを実行する場合, コンパイラをインストールする必要があります。
gfortranはコンパイラの一つでスタンダードなので今回はgfortranを用います。

#### 手順
- ターミナルを開く
- 以下のコマンドを実行
~~~
brew install gcc
~~~
- バージョンを確認
~~~
gfortran --version
~~~
→実行結果として
~~~
GNU Fortran (Homebrew GCC 14.2.0_1) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
~~~
のように表示されればOKです。

・次に実行するためにパスが通っているか確認します。
・以下を実行
~~~
which gfortran
~~~
→実行結果として
~~~
/opt/homebrew/bin/gfortran
~~~
のように表示されればOKです。

## VScodeをインストール
Fortranを記述するためのエディタをインストールします。

今回はVisual Studio codeをします。[Visual Studio Code公式サイト](https://code.visualstudio.com)にアクセス。

**Download for macOS**を選択してください。

インストールしたzipファイルをダブルクリックしてアプリをインストールしてください。

## VScodeに諸々の拡張機能をインストール
VScodeはそのままではただのメモ帳です。

拡張機能をインストールして使いやすくしましょう。

#### インストールする拡張機能一覧
- Japanese Language Pack...日本語化
- Modern Fortran...Fortranに関する全般

#### 手順
- Japanese Language Packのインストール

VScodeの拡張機能欄から以下を検索してインストール
~~~
Japanese Language Pack
~~~
インストール終了後右下に有効化するボタンが出るので押す。

- Modern Fortranのインストール
同様に以下を検索
~~~
Modern Fortran
~~~
インストールが終了したら終わり！おつかれさまでした。

## 実行手順
試しにHello Fortranを表示させてみます。

#### 手順
- VScodeで任意のフォルダを開く。
- 以下のファイル名で新しいファイルをつくる。
~~~
hello.f90
~~~

- 作成したファイルにコードを書く。
~~~
program hello
    print *, "Hello, Fortran!"
end program hello
~~~
- メニューバーから新しいターミナルを起動する。
- ターミナルで以下を実行
~~~
gfortran hello.f90 -o hello
~~~
→コンパイル完了
- コンパイルが完了すると同じディレクトリに実行ファイルが作成されます。
~~~
./hello
~~~
・作成された実行ファイルを実行します。
~~~
 Hello, Fortran!
~~~
と表示されれば成功です。

## もっと便利にするには....
ボタン一つで実行できればもっと便利ですよね？？
新しい拡張機能をインストールしましょう！

#### 手順
- 拡張機能欄で以下を検索
~~~
Code Runner
~~~
一番上に出てくる、`Jun Han`による拡張機能をインストールしてください。

- ファイルタブに戻ると、右上に再生ボタンが出ていると思います。再生ボタンを押すと実行されます。

## 蛇足
主要な計算ライブラリを入れていきましょう。蛇足なので必要ない場合は飛ばしてください。

#### インストールする拡張機能一覧
1. BLAS---------線形代数の計算
2. FFTW---------高速フーリエ変換
3. NetCDF-------科学データ解析のための多次元配列の格納

 手順
---
##### 1.BLAS
- ターミナルで以下を実行します。
~~~
brew install openblas lapack
~~~
終わったらつぎ！

#### 2.FFTW
- ターミナルで以下を実行
~~~
brew install fftw
~~~

どんどんいくよ〜

#### 3.NetCDF
- ターミナルで以下を実行します。
~~~
brew install netcdf
~~~
ここまでできたら一旦確認しましょう。
- ターミナルで以下を実行
~~~
brew list
~~~
ここで、以下があればOK！
~~~
openblas

lapack

fftw

netcdf
~~~

全部あればおわり！おつかれさまでした。

## さいごに
ここで説明しているものはすべて備忘録的に記録しているものです。
実行は自己責任でお願いいたします。
【ML初心者アドベントカレンダー】データのバイアスと品質について


# この記事の目的

トレーニングに安心して使用できるデータを用意するため、バイアスやデータ品質について学ぶ

# トレーニング前のバイアスメトリクス

https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/clarify-measure-data-bias.html

## クラス不均衡

データのクラスが不均衡であること。
10人分のデータが存在しているのに、10人中7人が20代で3人が40代、という場合。40代のデータが十分ではないため、年齢に偏ったバイアスが検出される可能性がある。

https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/clarify-bias-metric-class-imbalance.html


## ラベルの割合の差 (DPL）

異なる属性に生じた正の結果の不均衡のこと。
前述した10人分のデータのうち、40代3人は全員持病を持っているが、20代7人は2人しか持っていないとき。偏ったラベル付けが原因で、年齢ベースのバイアスが生じる可能性がある。

https://docs.aws.amazon.com/ja_jp/sagemaker/latest/dg/clarify-data-bias-metric-true-label-imbalance.html

---

モデルのバイアスについては**SageMaker Clarify**で検出、評価、レポートの作成が行える。

https://aws.amazon.com/jp/sagemaker/clarify/


# 画像データセット等のクラス不均衡に対応するための手法

クラス不均衡に対応するためには、データを増やす、あるいは減らす等の対策をとる必要がある。
（上にあげた例でいえば、40代のデータをもっと増やしたり、20代を減らしたりしてバランスをとる。）

## 合成データ作成

https://aws.amazon.com/jp/what-is/synthetic-data/


 > 基になる実際のデータと同じ数学的特性がありますが、同じ情報は含まれていません。

 つまり、元になったデータとよく似た、けれど一致しないデータを作成すること。
 作成手法もいくつかある。

 ### 敵対的生成ネットワーク(GAN)

二つのニューラルネットワークを用意し、片方に元となったデータからオリジナルのデータを作成させ、もう片方に作成したデータがオリジナルに存在するかどうかを予測させる。
二つのニューラルネットワークを競わせるため「敵対的」と言う。

 https://aws.amazon.com/what-is/gan/
 

## リサンプリング

SageMaker Data Wrangler でできちゃう。

https://aws.amazon.com/jp/blogs/machine-learning/balance-your-data-for-machine-learning-with-amazon-sagemaker-data-wrangler/


### オーバーサンプリング

少ないデータをランダムに複製して増やすこと。

#### SMOTE (Synthetic Minority Oversampling Technique)

少ないデータを補間する形で合成データを生成すること。
オーバーサンプリングの手法の一つ。

### アンダーサンプリング

多いデータをランダムに削除して減らすこと。


# データ準備の段階で気を付けること

データが偏らないよう、準備の段階で工夫することもできる。

## データセットの分割

トレーニング、テスト、推論につかうデータセットをきちんと分け、同じものは使用しないようにすることで、バイアスを軽減できる他、過学習の予防にもなる。

## シャッフル

データの順序をランダムにしておくこと。
例えば犬と猫の画像データなら、前半に犬、後半に猫、ではなく、順番がランダムになるよう処理をしておくことで、モデルが順序に依存しない。


## データ拡張

画像データセットに手を加え、データの数を増やすこと。
たとえば元の画像を回転させたり、反転させたり、明るさや色を調整することで、特定の状況や照明に偏らないデータを作成することができる。

テキストデータの場合は、同義語を置き換えたりする。

# データ品質について


## AWS Glue Data Quality

データの品質を自動的に監視・評価するためのサービス。
レポートの作成や、データが定められた品質を下回った場合にアラートを飛ばすことができる。AWS Glue DataBrewでデータの前処理をした後に、Data Qualityで加工したデータが一定の品質を保っているかを確認する、などの併用ができる。

https://aws.amazon.com/jp/glue/features/data-quality/
AdobeのAI動画生成器はOpenAIのものに匹敵するかもしれない

本記事では https://lifehacker.com/ より翻訳します。

AIによって生成された動画は未来の産物ではなく、今ここに存在し、驚異的です。AI企業は、簡単なテキストプロンプトからリアルな動画を生成できる技術を次々と導入しています。Adobeもその最新の一例であり、同社のAIによる動画生成技術は、短いデモであっても素晴らしいものです。

Adobe Firefly動画モデル

Firefly動画モデルは、これまで見てきた他の生成モデルとは少し異なります。多くのAI動画生成器は、AI画像生成器と同様の仕組みで機能します。つまり、希望する内容をテキストとして書き出し、そのプロンプトに基づいてモデルが出力を生み出します。

この仕組みもここで行われており、特定の動画を生成するようモデルに依頼することが可能です。しかし、AdobeはOpenAIのSoraなどとは異なり、より多くのAI動画編集ツールを統合しています。たとえば、Adobeはカメラ制御（角度、動き、ズームなど）を使用して「微調整」した動画を作成できるとしています。デモでは「ドラマティックなドリー・ズームカメラ効果」を生成するように指示し、サイドバーにはショットサイズやカメラアングル、動作制御などの複数のカメラコントロールが表示されました。理論的には、動画を生成した後、「手持ちカメラ」オプションをクリックすることで、製品に揺れのある見た目を追加し、その揺れの強さをスライダーで調整することができます。

また、この技術が実際の動画コンテンツにどのように追加できるかの例も示されています。Adobeによれば、Premiere Proベータ版を通じて、タイムライン内の既存のクリップをAI生成動画で延長できるとのことです。会社の目標は、タイムラインの隙間を埋めることであり、たとえばショットが十分に長くない場合、AIがそれを人工的に長くすることができます。このモデルは画像を動画に変換する能力も持っているとされています。参照として使用したい写真や絵がある場合、それをテキストプロンプトの代わりに使用できます。

さらに、このツールを使って2Dおよび3Dアニメーション効果を動画に加えることもできます。デモ動画では、実際のダンスをしている人の動画に2Dのモーションエフェクトが適用されている様子が確認でき、別の例では「TIGER」という文字が風に揺れる草原の上に毛皮で作られているシーンが示されています。

Adobeは、この動画モデルがパブリックドメインの作品でトレーニングされており、「商業的に安全」な設計がなされていることを強調しています。これは、OpenAI、Midjourney、Stability AIなど、AIの分野で著作権侵害の疑いで訴えられている多くの企業とは対照的です。

ただし、Adobeがこの決定により得たかもしれない善意は、同社がCreative Cloudに保存された作品にアクセスし、非生成AIプログラムのトレーニング目的で利用できると示唆するポリシーに対する反発によって相殺される可能性があります。Fireflyがアーティストから盗用せず、商業的なトラブルに巻き込まれるリスクがないのは素晴らしいことですが、自分の創造的プライバシーを放棄する必要がある場合、それは本当に価値があるのでしょうか？

これらのツールは、Creative Cloud、Experience Cloud、Adobe Express、さらにはfirely.adobe.comを通じて利用可能になります。Adobeは、Firefly動画モデルがベータ版で利用可能になった際に通知を受け取るためのウェイトリストを用意しており、こちらからサインアップできます。

一つ確かなことは、Adobeの動画の製品は見栄えが良いということです。動画を文脈なしに見ている場合、提示されたデモショットのほとんどが完全に人工的に生成されたものであると気づかないかもしれません。

しかし、Adobeは巧妙にも、ほとんどのクリップを一瞬か二瞬しか表示せず、生成器が実際にどれほど機能しているのかを正確に把握するのが難しい状態にしています。被写体の質はしっかりとしていて説得力がありますが、モデルがどれだけ動きを再現できるか、または出力が1分間にわたってどれほどリアルであるかを見ることができなければ、他のモデルとの比較が難しいです。

Adobeから見た中で最も長いクリップは、4〜5秒のトナカイの動画です。とてもリアルで、広角レンズを使用した手持ち感がその効果をさらに引き立てています。

AdobeがAI生成動画の品質においていくつかの突破口を開いた可能性があります。しかし、これらの動画が既存の生成器と同じ欠陥に苦しむ可能性もあり、時間とともに色褪せてしまうかもしれません。Adobeがより長いデモ動画を提供したり、ベータ版を発表したりすれば、より明確なアイデアが得られるでしょう。

AI動画生成・編集に興味があるなら[UniFab オールインワン](URL "https://ja.unifab.ai/unifab.htm")をおすすめです。UniFabは、動画の高画質化も簡単に実現することもできます。
【Laravel】－初学者向け　コントローラーについて



今回はコントローラーについて記事を書いていこうと思います。

# コントローラーとは？
⇒…ルーティング⇒コントローラ⇒ビューを返すといった流れとなっております。
ルーティングの次にコントローラがくるため、処理の中核を担う特徴をもっております。

# コントローラーの作り方

コントローラーの作り方は、コマンドプロントを開き、下記のコマンドを入力します。
※〇〇Controllerとつけるのが一般的です！
```
php artisan make:controller コントローラー名
```

下記パスの配下に生成されます。
```
app/Http/Controllers
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929458/d817b6d7-09e4-cb28-1c92-24a461fc186c.png)

上記で生成されたコントローラーのファイルの中身はすでにひな形として用意されております。
■コントローラークラス
```
<?php

namespace App\Http\Controllers;

use lluminate\Http\Request;

class コントローラー名 extends Controller
{
    //
    }

```

# リソースコントローラとは？
Laravelには、よく使うメソッドをまとめて生成できる機能があります。
この機能のことをリソースコントローラと言います。
CRUD（クラッド）という考え方があり、下記の頭文字を取ってCRUD（クラッド）と呼ばれています。


C	create	新規作成
R	read	表示
U	update	更新
D	delete	削除

# よく使うメソッドをまとめて生成
```
php artisan make:controller ContactFormController ̶--resource
```
    
■リソースコントローラーの表
下記が一気に作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929458/10d92563-df2a-eb82-3496-6e1a1b8ecd13.png)

上記一気に作成後、リソースコントローラーにも設定が必要です。

```
routes/web.php
```
上記のファイル名に以下のコードを記載します。

```
use App\Http\Controllers\コントローラー名

Route::resource('contacts', コントローラー名::class) ->middleware(['auth']);
// ルート名もまとめて作成される  
```
コマンドプロンプトを開き、「php artisan route:list」
で7つのルートが追加されているのが 確認できます。
Pythonの配列の添え字の[-3:-1]がわからなかったので調べたメモ

あるコードを書いていて、

```python
html_url = "https://example.com/aaa/bbb/db/item/123456/"
url_parts_name = "-".join(html_url.split("/")[-3:-1])
print(url_parts_name)
```

で、

```
item-123456
```

が、表示されました。

でも、わからない。

この`[-3:-1]`とはなんぞやと。

勉強中の身のため、公式ドキュメントを参照したいのですが、こういう記号含みの文字列だと、適切な検索ワードもわかりません。

この記事は、その「わからない」を調べた冗長な記録です。

「わたしはこんな思考をして調べている」の記録のようなものですので、ふつうにPythonの困りごとを解決するために、この記事に迷いこんできた方は、他を探しましょう。

# 筆者の技術レベル

はじめてのプログラミング言語はC言語。今も仕事でC言語。

趣味では、HTML/CSS/JavaScriptのWeb系をふんわりと使っている。

ということで、Pythonは入門したてです。

C言語は教科書から体系的に学びましたが、Pythonは必要なことを必要なときに必要なだけ（言い換えれば行き当たりばったり）式で勉強しているため、わからないことが多いです。

これは、そこから始まる、調査記録です。

# はじめに書籍を見る

`python array colon`や、なんとなく聞き覚えのある`slice`で検索してみましたが、空振りしたところで、我が家に唯一あるPythonの教本の存在を思い出したため、それを参照しました。

「独習Python」です。

https://www.shoeisha.co.jp/book/detail/9784798163642

（教本としての善し悪しは知りません。なんとなく他のシリーズにも聞き覚えがあったため、通販で購入しました）

まずは、目次を眺めて、「配列」の項目を探しました。

ここで、Pythonでは「リスト」という用語が使われていることを知ります。

（JavaScriptみたいに、配列の最後の要素にカンマをつけていいことも、ついでに知ります）

ひととおり目を通して、知りたい用法（添え字にマイナスがつくもの）はでてこなかったため、ついでに続く項目で「演算子」を確認し、この項目の範囲での演算子の一覧にはないことを確認しました。

次に、「文字列」の項目を眺め始めます。

文字列も配列もリストも、私の頭の中では似たようなものとして区分しているからです。

ここで、ようやく、「インデックス/スライス構文」という言葉に出会います。

なんとなくこれっぽい。

詳細を読んでいくと、それっぽく納得しました。

つまり、

```python
html_url = "https://example.com/aaa/bbb/db/item/123456/"
url_parts_name = "-".join(html_url.split("/")[-3:-1])
# html_url.split("/") --> ["https:", (略), "db", "item", "123456", ""]
#                                        -4    -3      -2       -1  (0)
# マイナスで現す添え字は上記の境界を示していて、
# html_url.split("/")[-3:-1]　--> ["item", "123456"]
```

こういうことのように考えると、納得できます。

でも、これはあくまで、「文字列」に対するものだからなあ、と考えながら、書籍の続きを読んでいくと、「リスト」にも「スライス構文」があるらしいという記述が、標準ライブラリのシーケンス型のリストの説明にありました。

「標準ライブラリ」「シーケンス型」「スライス構文」「リスト」というワードがひとまず、脳内にインプットされたところで、Pythonの公式ドキュメントへ戻ります。

# Pythonの公式ドキュメントへ

https://docs.python.org/ja/3/contents.html

ここから、「list」でページ内検索すると、以下がそれっぽくヒットしました。

https://docs.python.org/ja/3/library/stdtypes.html#sequence-types-list-tuple-range

「シーケンス型」というのはさっき知ったワードです。

ここで出てきた演算の表を見ていくと、ようやくありました。

> s[i:j:k]  --> s の i から j まで、 k 毎のスライス

さらに、注釈に

> i または j が負の数の場合、インデックスはシーケンスの末端からの相対インデックスになります: len(s) + i または len(s) + j が代わりに使われます。 ただし -0 はやはり 0 であることに注意してください。

このように書かれていて、先ほど書籍で確認した構文の理解と一致しました。

なるほど。

ついでに、step(k)のことも知ることができました。

ひとまず、当初の目的が達成できたため、調査はここでストップです。


# 終わりに

所感は「新しい言語の勉強は体系的にやったほうがよさそう」です。

言葉を知らないと、検索もままなりません。

ドキュメントを確認したくとも、どこの章の、どの項目を読んだらいいかわかりません。

時間がないときや、それよりも開発進めたいときは、ネットでググって出てきたコードを試すので終わってしまうし、それで（当座は）問題ないことが多いのが実際ではあります。

ですが、少しでも知識を増やすために、今後も時間があるときは公式ドキュメントを確認していきたいなと思いました。

以上です。

丸めただけの乾いた綿みたいな文章をここまで読んでいただき、ありがとうございました。
Mysqlのインデックスが効かないパターン

## はじめに
エアークローゼット　アドベントカレンダー8日目の記事です。
最近、データベースのパフォーマンスが遅いと感じている方への一助になれば嬉しいです。

https://qiita.com/advent-calendar/2024/air-closet

## インデックスとは
データベースのインデックスは、テーブル内のデータを効率的に検索・取得するためによく使用していると思います。
主な目的はこちらが挙げられます。
1. クエリの高速化
2. データの並び替えの効率化
3. 一意性の保証

MysqlのInnoDBではインデックスにB+Treeを採用していますが、その仕様については今回は触れず、インデックスが効いていない主なパターンと簡単な改善策について挙げますので参考にしてみてください。

## インデックスが効かない
#### where句にORを使用している
改善策：簡単な方法はUNIONをORの代わりにUNIONを使用する

``` sql
-- 悪い例
SELECT * FROM users WHERE department = 'Marketing' OR status = 'Active';

-- 改善策
SELECT * FROM users WHERE department = 'Marketing'
UNION
SELECT * FROM users WHERE status = 'Active';
```

#### 検索時のデータタイプとテーブルカラムのデータタイプが異なる
改善策：データタイプを合わせる

``` sql
CREATE TABLE orders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    customer_id INT NOT NULL
);

-- 悪い例
SELECT * FROM orders WHERE customer_id = '12345';

-- 改善策
SELECT * FROM orders WHERE customer_id = 12345;
```

#### 検索時のデータタイプとテーブルカラムのデータタイプが異なる
改善策：データタイプを合わせる

``` sql
CREATE TABLE orders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    customer_id INT NOT NULL
);

-- 悪い例
SELECT * FROM orders WHERE customer_id = '12345';

-- 改善策
SELECT * FROM orders WHERE customer_id = 12345;
```

#### データを変更する関数を使用する（YEARやMONTHなど）
改善策：関数を使用しないクエリにする

``` sql
-- 悪い例
SELECT * FROM users WHERE YEAR(birth_date) = 1990;

-- 改善策
SELECT * FROM users WHERE birth_date BETWEEN '1990-01-01' AND '1990-12-31';
```

#### LIKEで後方一致、部分一致の検索をする
改善策：前方一致で検索する

``` sql
-- 悪い例
SELECT * FROM users WHERE username LIKE '%tanaka';

-- 改善策
SELECT * FROM users WHERE username LIKE 'tanaka%';
```

## 最後に
本記事をご覧いただきありがとうございます。
[エアークローゼット Advent Calendar 2024](https://qiita.com/advent-calendar/2024/air-closet)はまだまだ続きますので、他のエンジニア、PMの記事もご覧ください。
また、エアークロゼットでは採用活動も行っておりますので、興味のある方はこちらのリンクまで！！

https://corp.air-closet.com/recruiting/developers/
今日から使える！1on1カルテのすすめ

## みなさん、1on1やってますか？

>1on1とは、上司（マネージャー）と部下が1対1で行う、定期的な面談のことです。上司は1on1を通して、部下が抱えている悩みや将来的なビジョン等を理解し、対話を繰り返すことで問題解決や気づきによる部下の成長をサポートします。  
参考：[1on1とは？実施の目的・流れから、効果を最大化するコツまで](https://www.persol-pt.co.jp/miteras/column/1on1/)

弊社はかなり1on1文化が盛んなほうじゃないかなと思うのですが、上司と部下以外にも、同期同士や他部署の人とも1on1している様子を見受けられます。  
私自身ほぼテレワークということもあり、誰かと話したいな～というときは気軽に1on1を申し込むこともあります。風通しのいい会社なので初対面の方ともお話させてもらえてありがたい限りです。

## 質の高い1on1を継続するって難しい
ですが定期的に1on1をしているとどうしても話題がなくなったり、先週何話してたっけ…なんか続きは来週ね、みたいなこと言ったような気がするけど…といったことありませんか？  
そして忘れてしまうことはあっても、自分にとって大事なことを相手の方が忘れてしまっているとついさみしい気持ちになってしまったり…:worried:
1on1のアジェンダ作りや自己開示の方法論などはいろいろな本が出ているかと思うのですが、まずは第一歩目として「聞いた話をちゃんとメモしておく！」を実行してみるのはいかがでしょうか。

## カルテご紹介
というわけで今日は私が普段使っている1on1カルテをご紹介させていただきます！  
内容はずばり…こんな感じ！

![1on1カルテ 2024-12-18 183408.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827898/d7169341-c27d-0f9b-1ba6-121f8d3734c1.png)



私はGoogleのスプレッドシートを使用していますが、ツールはなんでもいいかなと思います。

### 意識していることは下記のとおり。

- 話を聞きながら「どこに書こうかな」と迷って聞き逃した…とならないよう、記入欄を無駄に細かく分けないこと
- とはいえいったんメモしてあとで整理しよう…と思っても絶対やらないのでその場で作業が完結できる形であること
- 相手が話したいと言ってくれたことは必ずメモして、その日の1on1で話しきることができなくても「次回話そうね」といったフォローを行うこと
- 解決が必要な課題には特に注視できるよう、欄を分けて赤文字変更などを行う
- 体調は必ず確認し、毎週1on1していたのに相手が「ガクッとメンタルを崩した」とならないようしっかり目を配ること

特に自分のチームの後輩や頼ってくれる子の信頼は失いたくないものです。  
「先週話したのに全然覚えてない…興味ないのかな:cry:」となるともう一度心を開いてもらうのはなかなか難しくなってしまいます。
そうなる前に、もしよろしければカルテ作成をしてみてくださいね。
Git アーカイブを一時的ディレクトリに展開し、そのディレクトリのパスを出力するエイリアス

```ini
[alias]
	# ArchiveをExtractするのでax
	ax = ! "f() { T=$(mktemp -d); git archive $1 | tar -x -C $T; echo $T; }; f"
```

## Usage

```sh
code $(git ax <リビジョンハッシュ>)
```

`$()` で囲うのが億劫と感じたなら$EDITORまたは指定したプログラムで開くようなエイリアスを追加したって構わない。

```ini
[alias]
	# RevisionをOpenするのでor
	or = ! "f() { ${2:-$EDITOR} $(git ax $1); }; f"
```

```sh
git or <リビジョンハッシュ> # open with $EDITOR
git or <リビジョンハッシュ> code # open with code
git or <リビジョンハッシュ> open # open with open (Linux)
```
レトロPCのためのBASIC講座５　データおよび変数の型

# 前回のおさらい
" で囲んだデータは文字列を意味し、変数名の後ろに＄のついた変数は文字列型を覚えることのできる変数という話をしました。

[レトロPCのためのBASIC講座４](https://qiita.com/kawamo55/items/6caf0b16d133f4e9c419)

# 他の型
このように、コンピュータの中では変数にもデータにも型があり
%がつく数値と変数は整数型

#がつくと倍精度浮動小数点型、
何もつかないものは単精度浮動小数点
となっています。

# リテラル
ダブルクオート（”）で囲まれた文字列や直に書かれている数値をリテラルといいます。
例えば1.1は何もついていないので単精度浮動小数点のリテラルということになりますが
1.1#と書くと倍精度浮動小数点の1.1ということになります。

# 今回の動画
今回は、動画はありません。
【UiPath】既存のデータテーブルに特定の列だけ値を入れた行を追加する

## やりたいこと
既存のデータテーブルに特定の列だけ値を入れた行を追加したい。
つまり、以下のような表に、
| Col1 | Col2 | Col3 | Col4 |
|:-:|:-:|:-:|:-:|
| A | B | C | D |
| E | F | G | H |

特定の列（Col3列）だけに値を入れた以下のような行を追加して、

| Col1 | Col2 | Col3 | Col4 |
|:-:|:-:|:-:|:-:|
|  |  | L |  |

以下のような形にしたい。

| Col1 | Col2 | Col3 | Col4 |
|:-:|:-:|:-:|:-:|
| A | B | C | D |
| E | F | G | H |
|  |  | L |  |

## 実装
「データ行を追加」アクティビティを使用する。
列配列のプロパティに直接配列で記載してもよいが、値を入れたい列以外も全て指定する必要が多くため、列が多くなると手間であるし、列順での指定になるので間違いやすい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/0a2e3d22-4376-12e5-bda1-78011ed98a45.png)

この場合、DataRow変数を使い以下のように処理すれば、入れたい列だけ列名で指定できるようになる。
- DataRow変数`rowValue`に、DataTable変数`dtValue`の`NewRow`メソッドを代入する。
- `rowValue`の列名`Col3`列に`L`を代入する。
- 「データ行を追加」で`dtValue`に`rowValue`を追加する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/8bf7b742-2227-7e9b-88b5-4b05bb6226e5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/4d5621bf-a97e-e8c2-b0e5-a1256a12c869.png)


# 動作環境
UiPath.System.Activities 24.10.7
AWS Cloud Practitioner取ってみた

## 背景
現在私が所属している会社では、インフラにAWSを使用しているのですが、AWSの知見のある方が少なく（自分も含め）、取得すればサーバーエラーが起きた際に自分も力になれるのではと思い取ることにしました。

私自身、これまでAWSのインフラ構築から通信のHTTPS化、WAF設定などデプロイに必要なサービスは一通り使用した経験はありますが、使用したサービス内の知識やアーキテクチャについては知識としてまばらだったことも今回網羅的に学ぼうと思うきっかけになりました。


## 勉強方法
### AWS Skill Builder
最初はAWSが提供するAWS Skill Builderにて[AWS Cloud Practitioner Essentials](https://explore.skillbuilder.aws/learn/signin)を受講しました。

ここではAWSの認定インストラクターの方がAWSサービスの概要についてカフェを例にわかりやすく解説してくれます。
全てを順番に見るのではなく特に理解しづらい箇所のみ学習の補助的に見るようにしました。

### 書籍
#### AWS教科書 AWS認定クラウドプラクティショナー テキスト＆問題集
映像だけでは網羅的な知識をつけるのは難しいと感じていたため、書籍を購入しほぼこの書籍を使って学習を進めました。
各章ごとに基本的な概念とAWSでどのように使うことができるかを体系的に学ぶことができると思います。
また、テスト例題が結構な数収録されており（表紙にもある通りですが、、、）、問題の難易度も実際の試験よりやや難しいレベルのため、例題に答えられるようになれば概ね問題ないように感じました。

### WEB問題集
#### [AWS認定資格 WEB問題集＆徹底解説](https://aws-exam.net/clf/clf_question.php)
WEB問題集も活用しました。
上記サイトでは100問までであれば無料で例題を解くことができます。
この問題集にでてくるレベルの問題が最も本番に近いように感じました。

とはいえ、本番の問題では先ほどの書籍に出てきたような少し長文の問題（3~4行程度）も出てくるので、まずは書籍で1通り学習を進め、ある程度書籍の問題が解けるようになってきたら学習するのが効率的なように感じます。

## 試験結果
試験に落ちてたらそもそもこの記事を書いてないので受かったのですが、得点は700点台で結構ギリギリでした。
AWS認定試験は試験結果が終了後すぐに出るのでそこは非常に嬉しい点だなと思います。あんまり試験結果発表までドキドキしたくないタイプなので、、、

## 感想
事前知識も多少あったものの、今回改めて網羅的にAWSのサービスを理解できたためとって良かったと思います。
次はAWS 認定デベロッパー – アソシエイトの取得を2月中に取ることが目標です。

資格を取ったからといって、業務にすぐ活かせる！というわけではないですが、よりよい設計やソリューションの一助になることは間違い無いと思うので引き続き勉強を続けていきつつ、自分でもAWSインフラを使った個人開発も進めていこうかなと思います。
Next.jsでAPIエンドポイントが見つからずつまづいた話

Web系初心者がNext.jsでお問い合わせフォームを作ろうとして2時間くらいつまづいたときの忘備録です。

---

## 背景
自社のコーポレートサイトをシングルページアプリケーション（SPA）化しようと取り組んでいました。
実装が簡単らしいということでNext.jsを採用しました。

その中で、「お問い合わせフォーム」の送信データを処理するためにNext.jsのAPIルートを活用しようとしました。
しかし、うまく動作せず2時間くらい原因がわからずつまづきました。

---

## 何が問題だったか
APIエンドポイント（`/api/submitContact`）にリクエストを送信すると、常に **404エラー** が返ってきました。

具体的には、フォーム送信後にブラウザのコンソールに以下のエラーが表示されていました。

```
POST http://localhost:3000/api/submitContact 404 (Not Found)
```

一方、`pages/api/submitContact.js` ファイルはプロジェクト内の正しいディレクトリに存在しており、ローカルサーバーで開発時には正常に動作していました。

---

## 試したアプローチ
問題の原因を探るため、以下のアプローチを試しました。

1. **APIルートのパス確認**
   - `pages/api/submitContact.js` が正しい場所にあることを確認。
   - URLのパスにタイポやスペルミスがないことを確認。

2. **APIエンドポイントの直接アクセス**
   - ブラウザで `http://localhost:3000/api/submitContact` に直接アクセス。
   - 開発環境では期待通りに動作し、404エラーは発生しませんでした。

3. **ビルド後の動作確認**
   - `npm run build && npm start` で本番環境に近い状態を再現。
   - この状態でも、404エラーは発生しませんでした。

4. **デプロイ後の動作確認**
   - 実際のレンタルサーバー上にデプロイし、フォームを送信。
   - **再び404エラーが発生**。

---

## 原因究明
最終的に、**Next.jsの`output: export`設定**が問題の原因であることが判明しました。

```javascript
// next.config.mjs
const nextConfig = {
    output: 'export', // 静的HTMLとしてエクスポートする設定
};

export default nextConfig;
```

デプロイとかの学習コストを下げるため静的HTMLで実装していたのですが、APIエンドポイントは静的エクスポートには含まれず、動作しなくなる仕様となっていました。

## どう対応したか
以下の2つの対応策を検討しました。

**APIルートを使用しない方法への切り替え**
Next.jsのAPIルートの代わりに、従来のPHPスクリプトをサーバー上に配置してフォームデータを処理することにしました。

```php
// submit_contact.php
<?php
$to = "info@example.com";
$subject = "お問い合わせ";
$message = "お名前: {$_POST['name']}\nメールアドレス: {$_POST['email']}\n内容: {$_POST['details']}";
$headers = "From: no-reply@example.com";

if (mail($to, $subject, $message, $headers)) {
    header("Location: /thankyou.html");
    exit();
} else {
    header("Location: /error.html");
    exit();
}
?>
```
Next.js側のフォーム送信コードの修正例:

```jsx
<form action="/submit_contact.php" method="post">
    <input type="text" name="name" required placeholder="お名前" />
    <input type="email" name="email" required placeholder="メールアドレス" />
    <textarea name="details" required placeholder="お問い合わせ内容"></textarea>
    <button type="submit">送信</button>
</form>
```

**別案：SSRへの切り替えを断念**
静的エクスポート（output: export）をやめて、APIルートをサポートするSSRに切り替えることも検討しました。しかし、現行のホスティング環境がSSRをサポートしていないため、今回は断念しました。

## 結果
PHPスクリプトを使用したフォーム送信に切り替えた結果、レンタルサーバー上でもフォームデータを正しく処理できるようになりました。

## まとめ
静的エクスポートを使用する場合、Next.jsのAPIルートは利用できなくなるという仕様に気づかず原因究明に時間がかかりました。
【Salesforce】Hyperforce移行前の参照リンクハードコード確認方法

## はじめに
Salesforce組織をHyperforceへ移行する場合、以下3つのステップを踏む必要があります。

1. ハードコードされた参照の削除
2. Hyperforceへの接続を確認
3. Hyperforceへのアクセスを維持するための確認

この記事では、ステップ1のハードコードされた参照の削除について解説します。

[Hyperforceの概要と移行について](https://successjp.salesforce.com/article/NAI-000186)

## ハードコードされた参照とは
以下[Salesforce公式ヘルプ](https://help.salesforce.com/s/articleView?id=000387070&type=1&language=ja)より引用

>たとえば、次のようなハードコード化された参照「https://na1.salesforce.com/{Case.Id}」があるとします。
これを相対参照にするには「na1.salesforce.com」を削除して「/{Case.Id}」にします。

## ハードコードを見つける方法

#### 1. Salesforce設定画面のクイック検索に「Hyperforce」と入力し、「Hyperforceアシスタント」をクリック

![スクリーンショット 2024-12-18 11.00.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/f4086375-d337-ac75-65f3-fc8c3ffc8e0e.png)

#### 2. Salesforce Optimizer へのアクセスを許可を有効化し、検証をクリック

![スクリーンショット 2024-12-18 10.47.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/c0270577-a493-aaa7-ea3c-473f5c02650b.png)

参照リンクハードコードが組織に存在する場合、メールとHyperforceアシスタント画面で警告が表示されます。

![スクリーンショット 2024-12-18 10.48.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/f232bd79-eb93-5b26-23d9-2adc222a89f1.png)

#### 3. Salesforce Optimizerへアクセス

警告文にもある通り、どこに参照リンクハードコードが存在するか確認するには、アプリケーションランチャーより「Salesforce Optimizer」へアクセスすれば可能なようです。

しかし、現状Salesforce Optimizerへアクセスしても何も出てこない状態となっています。
[公式Help](https://help.salesforce.com/s/articleView?id=release-notes.rn_general_optimizer_new_features.htm&release=228&type=5&language=ja)より、Salesforce Optimizerを使用するユーザーに必要な以下3つの権限を付与しているユーザーでアプリケーションを開いています。

- アプリケーションのカスタマイズ
- すべてのデータの編集
- ユーザの管理

![スクリーンショット 2024-12-18 10.50.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/774544f9-f5f0-ec5f-a849-701c7d931ad0.png)

この問題は[Issue](https://issues.salesforce.com/issue/a028c00000zJHu1AAG/unable-to-access-salesforce-optimizer)としても登録されているため、現時点では使えないものとして、他の方法で参照リンクハードコードを見つけます。

※Salesforce Optimizerを正常に動作させる方法をご存知の方は、ご指摘お願いいたします。

:::note info
2025/5/28 現在
Salesforce Optimizerが正常に動作することを確認できました
:::

![スクリーンショット 2025-05-28 12.45.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/24c06b04-30d0-4d70-98b5-ac499fc2b9a8.png)
 
#### 4. VSCodeを使用して参照リンクハードコードを検索

公式Helpに従いSalesforce環境のメタデータを取得し、ハードコードの検索を行う。

![スクリーンショット 2024-12-18 17.48.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718267/0e0a1037-cf1e-ab01-f996-b8daa23c3108.png)

#### 5. 参照リンクハードコードの削除・編集を行い、環境へアップロード

削除を行うか、必要な場合は相対参照に変更を行う。
Apexコードへハードコードが存在する場合、カスタムメタデータなどを使用してハードコードを削除する。

以下[公式ヘルプ](https://help.salesforce.com/s/articleView?id=000387070&type=1&language=ja)より

>ハードコードされた参照は、URL にインスタンス名が含まれる URL です (例: na1 .salesforce.com)。
これらのハードコードされた参照を、汎用のインスタンス固有ではない URL または相対 URL (<mydomain>.my.salesforce.com) に置き換えます。

## 注意点

Salesforce Optimizerが正常に動作しない以上、VSCodeで検索するしか方法がありません。
VSCodeで検索を行う場合、すべてのメタデータをローカルに落とし検索を行う必要があります。

Salesforce Optimizerの動作が確認でき次第、記事の編集を行います。
Laravelでテストを書く：RailsのRSpecとPHPUnitの違い

### はじめに
LaravelやRailsを使ったWebアプリケーション開発に挑戦している方も多いのではないでしょうか？今回はLaravelのテストフレームワーク—PHPUnit—とRailsのRSpecの違いについて解説します。

### PHPUnitとRSpecの基本的な役割

どちらのフレームワークも、アプリケーションが期待どおりに動作することを確認するためのテストを書くツールです。

|比較項目|PHPUnit|RSpec
|:------|-------|-----
|言語|PHP|Ruby
|テストの種類|ユニットテスト、機能テスト、統合テスト|ユニットテスト、機能テスト、統合テスト
|記述スタイル|クラスベース|DSL（Domain Specific Language）
|実行方法|`php artisan test`|`bundle exec rspec`

### PHPUnitでのテスト例

Laravelのプロジェクトを新規作成したとき、PHPUnitはデフォルトでインストールされています。以下に、簡単なテスト例を示します。

#### 1. ユニットテスト

Laravelでは、`tests/Unit`ディレクトリにユニットテストを作成します。例えば、シンプルな加算処理をテストするとします。

```php
namespace Tests\Unit;

use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    /** @test */
    public function addition_works_correctly()
    {
        $this->assertEquals(4, 2 + 2);
    }
}
```

#### 2. フィーチャーテスト

フィーチャーテストは、アプリケーションのルートやコントローラーが正しく動作するかを確認するものです。以下は、HTTPリクエストをテストする例です。

```php
namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /** @test */
    public function the_home_page_returns_a_successful_response()
    {
        $response = $this->get('/');

        $response->assertStatus(200);
    }
}
```

### RSpecでのテスト例

RailsではRSpecを使用してテストを書きます。RSpecはDSLによって直感的にテストを書くことができる点が特徴です。

#### 1. モデルスペック

以下は、Userモデルにバリデーションがあるかを確認する例です。

```ruby
require 'rails_helper'

describe User, type: :model do
  it "is invalid without a name" do
    user = User.new(name: nil)
    expect(user).not_to be_valid
  end
end
```

#### 2. リクエストスペック

Railsのリクエストスペックでは、特定のルートやコントローラーの挙動をテストします。

```ruby
require 'rails_helper'

describe "GET /", type: :request do
  it "returns a successful response" do
    get "/"
    expect(response).to have_http_status(:ok)
  end
end
```

### PHPUnitとRSpecの違い

#### 記述スタイル

PHPUnitはクラスベースの記述が中心です。PHPのオブジェクト指向の特性を活かしてテストを書きます。

RSpecはDSLを採用しており、人間が読んでも分かりやすい構文になっています。

#### テスト実行方法

Laravelでは、`php artisan test`コマンドを使用してテストを実行します。このコマンドは、カバレッジの表示や並列実行にも対応しています。

Railsでは、`bundle exec rspec`を使用します。並列実行には`parallel_tests`などのGemを活用します。

#### エコシステム

LaravelはPHPUnitをデフォルトで採用しており、`php artisan make:test`コマンドで簡単にテストファイルを作成できます。

RailsはRSpecを選択肢として提供しますが、`rails generate rspec:install`を実行して設定を追加する必要があります。

### 公式ドキュメントの参照

詳細な使い方については公式ドキュメントを参照することをおすすめします。

[PHPUnit公式サイト](https://phpunit.de/documentation.html)

[Laravel Testing公式ドキュメント](https://laravel.com/docs/11.x/testing)

[RSpec公式サイト](https://rspec.info/documentation/)

[Rails Testing公式ドキュメント](https://railsguides.jp/testing.html)

### まとめ

LaravelのPHPUnitとRailsのRSpecは、どちらも強力なテストフレームワークです。どちらを使うかはプロジェクトの言語や要件によりますが、公式ドキュメントをしっかり確認し、テストの再現性と信頼性を高めることが重要です。
callメソッド


>call(*arg) -> ()
self === *arg -> ()
yield(*arg) -> ()
手続きオブジェクトを実行してその結果を返します。

https://docs.ruby-lang.org/ja/latest/class/Proc.html#I_--3D--3D--3D:~:text=call(*arg)%20%2D%3E%20(),%E3%82%92%E8%BF%94%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

```rb
irb(main):050> a = Proc.new { "fafa".is_a?(String) }
=> #<Proc:0x0000000105288830 (irb):50>
irb(main):051> a.call
=> true
irb(main):052> a.nil?
=> false
irb(main):053> a = Proc.new { :far.is_a?(String) }
=> #<Proc:0x0000000104f5a7d0 (irb):53>
irb(main):054> a.call
=> false
irb(main):055> a.nil?
=> false
```
>callメソッドとはyieldメソッドと同じような使われ方をします。

>procメソッドにブロックを与えられたprocオブジェクトやdo~endで囲んだブロックなどを呼び出せるメソッドです。

>callメソッドで呼ばれるまではそのオブジェクトは実行されないため、ブロックを実行するまでは処理されません。

https://magazine.techacademy.jp/magazine/36816#:~:text=call%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%A8%E3%81%AFyield,%E5%87%A6%E7%90%86%E3%81%95%E3%82%8C%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82
【Flutter】Retrofit使用時のContent-Type:html/textの対応

# はじめに
APIレスポンスのHeaderのContent-Typeが`text/html`形式で、レスポンス内容がJSON形式だったときにretrofit(JsonSerializable)の自動パースを適用したかった時の対処法のメモです。

retrofitではJsonSerializableと組み合わせることでパースしたクラスを返すFutureクラスを自動生成してくれます。

## 問題の状況
APIのレスポンスがJson形式のテキストなのにも関わらず、仕様によりContent-Typeが`text/html`でした。

- レスポンス
```
{
    data:{
        name : "hoge",
        age : 20
    }
}
```

Freezedを用いて上記のレスポンスに対するモデルおよびAPIサービスクラスを作成していたのですが、Content-Typeが`json/aplication`でなかったため、自動パースが行えませんでした。

- モデル

```
@freezed
class UserModel with _$UserModel {
    const factory UserModel({
      required String name,
      required int age,
    }) = _UserModel;
    factory UserModel.fromJson(Map<String, dynamic> json) => _$UserModelFromJson(json);
}
```

- APIサービスクラス
```
@RestApi(baseUrl: 'http://...')
abstract class ApiService {
    factory ApiService(Dio dio) = _ApiService;

    @GET('/user')
    Future<UserModel> getUser();
}
```

# 解決方法
**dioの`interceptor`でJsonデコードを行う**

`InterceptorWrapper`クラスに`onResponse`プロパティがあるので、そこでretrofitに渡されるレスポンスを変換します。
statusコードが200番の時にJsonDecodeを行い、`handler.next`でResponseを渡します。

```
final apiServiceProvider = Provider((ref) {
  final dio = Dio();

  // content-typeをtext/htmlに設定
  dio.options.headers['Content-Type'] = 'text/html; charset=UTF-8';

  // text/html形式のレスポンスをjson形式に変換
  dio.interceptors.add(
    InterceptorsWrapper(
      onResponse: (response, handler) {
        if (response.statusCode == 200) {
          final data = response.data.toString();
          try {
            final jsonData = jsonDecode(data);
            handler.next(
              Response(
                data: jsonData,
                requestOptions: response.requestOptions,
                statusCode: response.statusCode,
                statusMessage: response.statusMessage,
                isRedirect: response.isRedirect,
                redirects: response.redirects,
                extra: response.extra,
                headers: response.headers,
              ),
            );
          } on Exception catch (_) {
            // エラーが発生した場合はそのまま返す
            handler.next(response);
          }
        }
      },
    ),
  );

  return apiService(dio);
});
```

# 終わりに
Json形式なのにtextという特殊な状況ですがこのような形で対処できました。

もっとスマートな方法あればコメント等お願いします！
Reactで神経衰弱アプリ作ってみた（決起編）

Reactを使ってアプリを作ってみたい！ということで神経衰弱アプリを作成しました。

開発メンバ集めからアプリ開発までの工程を全6回にわけて紹介していきます。

 - 決起編　★本記事
 - Front環境構築編
 - フロントエンド構築編
 - コンポーネント作成編
 - バックエンド編
 - リファクタリング編

本記事では決起編となる、背景やプロダクト選定のプロセスについて紹介していきます。

 

## 【背景】

今アツいReact。とはいえ、実際にはあまり触ったことないので勉強を兼ねて何かしらアプリを作成してみたい！というがスタート地点でした。そこでメンバー4人が集まり、「初学者でも楽しみながら作れる」、「Reactの基本を学びつつ形のあるものを作る」ということをベースに開発を始めました。

 

## 【プロダクト選定】

作成するアプリを検討するにあたり、以下の候補があがりました。

 - 神経衰弱
 - オセロ
 - スケジュール調整
 - ルーレット・あみだアプリ

今回は全員がReactを扱った経験が浅い、かつ開発に割く時間が限られているため、ロジックがシンプルな神経衰弱を採用することになりました。他の候補に比べI/Oも少ないので分担がしやすそうだな、という淡い期待もありました。

 

## 【開発期間】

チームメンバーがそれぞれ片手間に開発作業を行い、設計から動くものが完成するまでに約3ヶ月かかりました。最初はシンプルなアプリだと思っていたものの、設計当初に無駄に複雑な処理や機能を検討していたため開発期間後半で余分な機能を削除するといった下方修正を行うこともしばしばありました。それでもこまめに進捗を共有し、無事に完成にこぎつけることができました。

 

## 【関連記事】

開発過程で生じた学びや、Reactを使っていく中で気づいたTipsなど、今後順次投稿していく予定です。初めてのReact開発だったので、つまずいた点や工夫した点も多々あり、それらも含めて詳しくお伝えしていきます。同じようにこれからReactに挑戦したいと考えている方や、神経衰弱のようなシンプルなゲームを作ってみたい方には、きっと役立つ内容になると思います。是非ご覧ください！（URLは随時追加予定）

 - Front環境構築編
 - フロントエンド構築編
 - コンポーネント作成編
 - バックエンド編
 - リファクタリング編
Switch文はもう古い！Switch式でコンパクトに書こう！

# Switch式とは？

C#8.0で導入された**Switch式**は、従来の**Switch文**をより簡潔に記述できる構文です。

具体的には、以下のような違いがあります。

|相違点　|Switch文　|Switch式　|
|:-:|:-:|:-:|
|用途　|複雑な処理　|簡潔な処理|
|書き方　|詳細な構文　|簡潔な式|
|網羅性の確認　|手動で行う　|コンパイラが自動的に行う　|

用途と書き方については、実際のコードを例に説明します。

以下は、int型の変数（number）の値に応じて異なる内容を出力するコードです。

```cs
// Switch文の場合
int number = 0;

switch (number)
{
    case 1:
        Console.WriteLine("One");
        break;
    case 2:
        Console.WriteLine("Two");
        break;
    case 3:
        Console.WriteLine("Three");
        break;
        
    default:
        Console.WritrLine("Other number");
        break;
}
```

```cs
// Switch式の場合
int number = 0;

string result = number switch
{
    1 => "One",
    2 => "Two",
    3 => "Three",
    _ => "Other number"
};

Console.WriteLine(result);
```

どうでしょうか？
**Switch式**の場合は、かなり簡潔にまとめられていると思います。
このように、**Switch式**は**Switch文**と比較して簡潔な処理に向いているといえます。

また、**Switch式**のコードでdefaultとして扱っている「 _ 」は、
**ディスカード**と呼ばれているもので、「値を破棄するための特別な変数」を意味します。

**Switch式**では**Switch文**の「default」にあたる「その他すべて」を表し、
下記のような場合にも使用することが出来ます。

```cs
// タプルから特定の値だけを取り出し、不要な値を無視する場合
var (x, _, z) = (1, 2, 3);
Console.WriteLine(x);
Console.WriteLine(z);

// メソッドのoutパラメーターに用いて、不要な値を破棄する場合
if (int.TryParse("123", out _))
{
    Console.WriteLine("Success!.")
}
```

話が逸れましたが、**Switch文**と**Switch式**の違いに戻ります。
最後に網羅性の確認についてですが、以下のような違いがあります。

:::note warn
**Switch文**の場合は、コンパイラが自動的に確認しないため、
漏れがあった場合は実行時エラーになる可能性があります。
:::

:::note info
**Switch式**の場合は、コンパイラが全ての条件を確認するので、
漏れがあった場合はエラーや警告を表示してくれます。
:::

以上が**Switch文**と**Switch式**の違いになります。
CUDAを使った準同型暗号ライブラリ phantom-fheの環境構築

### 0. はじめに
本記事では準同型暗号ライブラリのphantom-fheについて
1. 環境構築
2. サンプルコードの実行

この2点について説明します。

### 1. 環境
今回はdockerのコンテナ上での環境構築を行います。

使用したコンテナイメージは`nvcr.io/nvidia/cuda:12.4.0-devel-ubuntu22.04`です。phantom-fheが動作するOSは**Linuxのみ**となっているので注意して下さい。

事前に準備しておくものは以下の通りです。

| ソフトウェア名 | バージョン |
|:-------------:|:---------:|
|CUDA Toolkit   |11.0以上(推奨)|
|CMake          |3.20以上(**ベンチマークを実行する場合は3.23以上**)|
|GCC            |9.0(推奨)   |
|Python         |3.7以上(pybind11で使用)|

### 2. インストール方法
1. まず初めにphantom-fheのリポジトリをクローンします。どのディレクトリにクローンしても問題ありませんが、今回はホームディレクトリにクローンします。
   ```
   cd
   git clone --recurse-submodules https://github.com/encryptorion-lab/phantom-fhe.git
   ```
   phantom-fheではサブモジュールとして管理されているものがあるのでそれも一緒にクローンします。もし`--recurse-submodules`をつけ忘れた場合は以下のコマンドを実行してください。
   ```
   cd ~/phantom-fhe
   git submodule update --init --recursive
   ```
2. 次にクローンしてきたリポジトリに移動してcmakeコマンドを実行します。
   #### ベンチマークを実行しない場合
   ```
   cd ~/phantom-fhe
   cmake -S . -B build
   cmake --build build -j$(nproc)
   # システムにインストールする場合のみ実行(管理者権限が必要)
   cmake --install build
   ```
   #### ベンチマークを実行する場合
   ```
   cd ~/phantom-fhe
   cmake -S . -B build -DPHANTOM_ENABLE_BENCH=ON
   cmake --build build -j$(nproc)
   # システムにインストールする場合のみ実行(管理者権限が必要)
   cmake --install build
   ```
以上でphantom-fheの環境構築は完了です。次に、サンプルコードを実行して動作確認をしていきます。
### 3. サンプルコードの実行
cmakeコマンドを使ってビルドしたディレクトリに移動します。
```
cd ~/phantom-fhe/build/bin
```
このディレクトリにはコンパイルされた実行ファイルが置かれています。ベンチマークも同様です。

では、試しに`example_context`を実行してみましょう。
```
./example_context
```
このファイルを実行すると、スキームの選択ができます。任意のスキームを選択して問題なく実行できればphantom-fheのインストールは成功です。
TerraformでNew Relicプロバイダを指定しても正しいレジストリを読み込んでくれない

# エラー内容

```
╷
│ Error: Failed to query available provider packages
│ 
│ Could not retrieve the list of available versions for provider hashicorp/newrelic: provider registry registry.terraform.io does not have a provider named
│ registry.terraform.io/hashicorp/newrelic
│ 
│ Did you intend to use newrelic/newrelic? If so, you must specify that source address in each module which requires that provider. To see which modules are currently depending on
│ hashicorp/newrelic, run the following command:
│     terraform providers
╵
```


# 原因

`required_providers`を省略した場合、`registry.terraform.io/hashicorp/`を参照するそうです。
そのため、New Relicのプロバイダーとして`newrelic/newrelic`を使いたくても正しく指定されていない場合は`hashicorp/newrelic`が使われます。

以下のようなディレクトリ構造で`main.tf`に`required_providers`が指定されていれも`main.tf`から読み込まれている`example.tf`には影響が与えられません。

```
.
├── environment
│     └── dev
│          └── main.tf : ../../modules/example.tfを読み込んでいる。
└── modules
     └── example.tf

```


# 対応

modules ディレクトリに `required_providers`を記述したファイルを配置する。
example.tf に`required_providers`を追記しても構わない。

```
terraform {
  required_providers {
    newrelic = {
      source = "newrelic/newrelic"
    }
  }
}
```
NestedScrollViewのスクロール位置が復元されない

## 事象
NestedScrollViewを利用したFragmentから、別のFragmentに遷移して`popBack`したとき、スクロール位置が復元されず、一番上に戻ってしまう。

## 解決方法
NestedScrollViewに(xmlレイアウトファイル内で)`id`を指定する。

たったこれだけです。

なお、本アプリは、1Activity上で複数のFragment遷移だけを行う構成になっています。

```xml
        <androidx.core.widget.NestedScrollView
            android:id="@+id/nested_scroll_view"  <!-- これを追加 -->
```

## 補足
当初は、わざわざ`onPause`で`scrollY`をViewModelに保存して(※)、`onViewCreated`で値が設定されていれば`scrollY`に再セットして無理矢理スクロールさせる、なんてことをしていましたが、それを通過しないフローがあったにもかかわらず復元できるようになっていることに気づき、最終的に「idを追加してやると保存/復元フローが自動で走るようになるらしい」との結論に至りました。

コードから利用する必要が無く、constraintの対象にもならないようなViewだとidは付けないままにしてしまうことが多いと思いますが、意外にそれが盲点になることがあるようですね。

※FragmentAからFragmentBに遷移するとき、FragmentA自体は破棄され、戻ったときに再作成されますが、ViewModelはメモリ上に残っているようだったのでこのようにしていました。
Angular18でZurb Foundation 6を動作させる方法

# 概要
CSSフレームワーク、Zurb Foundation6で動いているサイトをデザインそのままでAngularに移行したい場合もあると思います。
AngularJSを使ったサイトからAngular18へ移行に成功したのでその手順を載せたいと思います。
一通り検索しましたが解決した方法が書いてある記事が無かったため書くことにしました。

## 環境
- フロントエンド
移行前: AngularJS+Foundation6+jQuery3.7.1
移行後: Angular18(SSR)+Foundation6+jQuery3.7.1
- サーバーサイド
SpringBoot3(RESTfulAPI)
- httpサーバー
Nginx

## 手順
### jQueryとFoundationはHTML上で読み込む。

```index.html
<!-- jquery -->
<script src="/assets/js/lib/jquery/jquery-3.7.1.min.js"></script>

<!-- foundertion -->
<script src="/assets/js/lib/foundation/foundation.min.js"></script>
```
色々な読み込み方法がありますがHTML上で読み込む方法に最終的に落ち着きました。

### TypeScript上で読めるようにする。
declareで宣言をし、コンポーネント上で$が使えるようにしておきましょう。
これで基本的にはjQueryがつかえるようになります。

```example.ts
declare var $ :any
```

### ページの切り替えタイミングでfoundationを実行する
ページ全体をルーティングしているTOPページの切り替えタイミングを利用しFoundationを有効化させます。
具体的にはngOnChangesメソッドの実行時に有効化させます。
これで大半のページはFoundationのデザインで動作しました。

```app.component.ts
import {OnChanges} from '@angular/core';
//...
declare var $ :any
export class AppComponent implements OnChanges {
  ngOnChanges(changes:any) {
    $(document).foundation();
  }
//...
}
```
こんな感じ

### ngOnChangesで動作しないネストされたテンプレートページにも対応させる
routerで切り替えて表示させているページの更に下層にあるテンプレートhtmlはページ切り替えタイミングでfoundationを動作させることができません。
例えば特定ジャンルにだけ表示するheader等は画面が表示される前にfoundationが実行されているっぽいです。
テンプレートページ表示時（ngOnInit）に自分から読み込ませればいいじゃないかと思うのですがbuildするときは構文しか見ていない為、HTMLを読み込まず宣言しているjQueryにエラーが出てしまいます。
そこでisPlatformBrowserを使うことでHTML上で展開しているときのみjQueryを実行させるように分別させます。
```header.component.ts
import { isPlatformBrowser } from '@angular/common';
declare var $ :any;
//...
export class HeaderComponent { 
  public isBrowser: boolean = false
//...
  constructor(
    @Inject(PLATFORM_ID) private platformId: Object,
    @Inject(DOCUMENT) private document: Document
  ) {
    this.isBrowser = isPlatformBrowser(platformId);
  }
//...
  ngOnInit() {
    if(typeof $ !== undefined){
      if (this.isBrowser) {
        $(this.document).foundation();
      }
    }
  }
//...
}
```
これでngOnInit時でもテンプレートに対してfoundationを実行してくれるようになりました。

## 二重実行で挙動がおかしくなる。
オーバーレイページなどがどんどん増えてしまうことがあります。
部分的にjQueryのremoveなどを入れて対処しました。

```etc.component.ts
  ngOnInit() {
    if(typeof $ !== undefined){
      if (this.isBrowser) {
        if($('.reveal-overlay').length){
          $('.reveal-overlay').remove();
        }
        $(this.document).foundation();
      }
    }
  }
```

## jQueryで動かしているアニメーション等
@Componentのanimations: []ですべて代替できました。
jQueryはあくまでFoundationを動作させるため以外には使わないほうが良いと思います。

# 対応後の感想
対症療法のようなプログラムですがAngularは柔軟に対応できることに驚きました。
AngularJSがEOLである為、実務でAngular2+へ再構築しなければいけなかったのですが、プログラムは組みなおすにしてもデザインもそのままで移行できるのか？という課題がありました。
デザインの問題で古いフレームワークから離れられないWebページもあると思います。
今回のちょっとした調査でFoundationはAngular18でも完全動作させることができました。
全ての状況下に対応できるかはわかりませんが参考になれば幸いです。
WordsAPIについて

# はじめに
無料で使用できるAPIのついて、個人的に調べていた際に見つけた「Words API」について紹介します。
Words APIの名前からも想像がつくように、「言葉」に関するデータを取得することができ、
150,000語以上の言葉で検索ができる辞書のようなAPIです。ですが、日本語には対応しておらず、英単語限定で使用することができます。

https://www.wordsapi.com/

# 使い方
使い方としては、4つのプランから選択することができます。
`※注意点として、Basicプランでも利用するためには支払い方法を選択する必要があります。`

<table>
  <caption>各プランの内容</caption>
  <thead>
    <tr>
      <th>名前</th> <th>金額</th> <th>リクエスト上限</th>
    </tr>
  </thead>
  <tr>
    <td> Basic </td> <td> Free </td> <td>2,500 件</td>
  </tr>
  <tr>
    <td> PRO </td> <td>$10</td> <td>25,000 件</td>
  </tr>
    <tr>
    <td> Ultra </td> <td>$49</td> <td>250,000 件</td>
  </tr>
    <tr>
    <td> Mega </td> <td>$89</td> <td>500,000 件</td>
  </tr>
</table>

また、データをローカル環境で使用したい方向けに、$629でデータを販売しています。
価格は変更される可能性があるので公式サイトでの確認をお願いします。

# Webサイトで試してみる
公式Webサイト上で試すことができます。
**Enter a Word**に英単語を入力し、**Call the API**をクリックすることで、データを取得することができます。

![Enter a Word](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3952253/3814e48f-f163-f760-c17a-be6fd9ce2ce6.png)

# 取得できるデータ項目の説明
取得できるデータ項目を以下にまとめました。
`※個人的な解釈が含まれていることに留意してください`
#### definitions（定義）
　単語の意味、品名
#### synonyms（類義語）
　同じ意味またはほぼ同じ意味を持つ言葉
#### antonyms（反対語）
　元の単語とは正反対の意味を持つ単語
###  examples（例）
　単語を使った例文
#### typeOf
　より一般的な単語、上位語
####  hasTypes
　より具体的な単語、下位語
####  partOf
　上位概念、ホロニム
####  hasParts
　下位概念、メロニム
####  instanceOf
　単語の属している上位概念
####  hasInstances
　単語に属する下位概念
####  similarTo
　類義語ではないが、意味が合い近く関連性の高い単語
####  also
　単語が含まれる語句
####  entails
　連語、複合動詞、派生語
####  memberOf
　単語の属するグループ（生物の分類など）
####  hasMembers
　単語と同じグループに属する単語
####  substanceOf
　単語が属する物質、複合体、化合物
####  hasSubstances
　単語の一部である物質
####  inCategory
　単語が属すカテゴリ
####  hasCategories
　単語のカテゴリ
####  usageOf
　専門分野での単語
####  hasUsages
　単語と同じカテゴリに属する単語
####  inRegion
　単語が使用されている地域
####  regionOf
　単語が使用される言語圏
####  pertainsTo
　単語に関連する単語

## 最後に
今回は「WoedsApi」についてまとめてみました。興味のある方はぜひ、公式Webサイト上で試すことができるので、一度試してみてください。AIなどの幅広い分野で活用できるのではないかと思います。
興味のある方は公式サイトにある開発者の方のBlogも読んでみてください。