OmniAICreator/Qiita-1.07M huggingface dataset:
StyleTTSの日本語版が1年たっても出てこなかったので、自作した話【音声合成】

# はじめに
（2023年末現在）去年か一昨年かくらいにVITSが一世を風靡して自分もVITSで音声合成を作って遊んでたのですが、一通り作って物足りなさを感じていました。

音質は学習を回せば回すほど改善するのですが、イントネーションがどうしても不自然でキャラクターの音声データ（少量、ファインチューニング）でいくら学習を回しても「それっぽい声のなんちゃって音声合成」的な域を越えらず「飽きた、物足りない」という具合に。

それで、イントネーション制御できるモデル(FastSpeech,JETSなど)モデルを試したのですが、調整に時間かかりすぎるのでこれはこれで「うーんちょっとだるい」という...

そして、「声質を無視して、音素列と抑揚の情報だけ学習できれば大量のデータで学習できるのになー」と思っていて、VISingerとかStyleTTSを見つけてこれ使ってみようかと思ったのですが
- VISingerは歌専用フォーマットだし、改変するのがめんどくさそう...
- StyleTTSは2つの事前学習モデルが必要でそれが英語版しかなく、phonimizerとかtokenが英語と、こちらも改変がめんどくさそうという...

私の場合、がっつり「そういう研究がしたい！」とかそういう目的ではなく「すげー、これでめっちゃ遊べるわ！」という体験が欲しいだけだったので
「そのうちだれかが実装してくれるだろう」
「改変作業進めてもどうせ新しいつよつよモデルが出てｷｮﾑﾘになるだろう」
ということで、しばらく音声合成から離れてました。

で約1年たってStyleTTS2やVITS2が発表されましたが、「StyleTTS 日本語」で検索しても何もヒットせず、やむなく自分で学習を回しました。この記事はその結果を供養するためのものになります。

# StyleTTS
StyleTTSについては以下のリンクを参考にしていただければと思います。
- https://ninhydrin.hatenablog.com/entry/2022/06/07/095201
- https://arxiv.org/abs/2205.15439v1

# 事前準備
### 学習データ
おなじみのJSUTコーパス
### トークナイザ(音素列に変換するやつ)
おなじみのpyopenjtalk

- #### PC
    - CPU: intel Core i5 13600k
    - GPU: palit RTX 4090 24G
    - OS: Windows SubSystem for Linux2(WSL2)
- #### 環境
    - CUDA Version: 12.3
    - python3.9
    - pytorch: 2.0.1

### ASR事前学習モデル
[このリポジトリ](https://arxiv.org/abs/2205.15439v1)のソースコードを改変して学習を実行しました。
1000 epoch回しました。

私が日本語用に書き換えたものを[こちら](https://github.com/seichi042I/AuxiliaryASR_JP)に用意したので興味がある方は覗いてみてください。

### JDC Pitch Extractor事前学習モデル
[このリポジトリ](https://github.com/yl4579/PitchExtractor)のソースコードを改変して学習を実行しました。
500 epoch回しました。

私が日本語用に書き換えたものを[こちら](https://github.com/seichi042I/PitchExtractor_JP)に用意したので興味がある方は覗いてみてください。

# 学習
事前学習モデルを所定のフォルダに配置して学習を回しました。
- first_stage:200epoch
- second_stage:100epoch

この値は、LJspeechデータセットを前提としたepoch数で、JSUTだと1/5くらいのデータ量がないので1000epoch,500epochくらい回さなきゃ比較できないかもしれませんが、学習に結構時間がかかるのでそのままにしました。

[日本語対応したリポジトリ](https://github.com/seichi042I/StyleTTS_JP)作ったので興味のある人は覗いてみてください。

# 結果
<iframe width="560" height="315" src="https://www.youtube.com/embed/wesmVdgdLZs?si=Hi1ZfVUWpDSP22dB" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

<iframe width="560" height="315" src="https://www.youtube.com/embed/LeOxGMERilY?si=yN3kL0E4D9ToTK9q" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

<iframe width="560" height="315" src="https://www.youtube.com/embed/nM1_yT8pP50?si=UB-evtcEHQr1w9SR" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

# 感想
リファレンスの雰囲気寄せてくれるけど、イントネーションが不自然。
学習不足な気もするが、今はBert-VITS2が話題なのでそちらを先に試したい。

# おわりに
### 多分、Bert-VITS2で解決してそうな問題なのでみんなBert-VITS2使おう
AZ-900合格に役立った無料サービス

先日MicrosoftのAzure Fundamentals (AZ-900)の試験で8割7分をとって合格したので、無料サービスを利用した順に紹介していきます。ちなみに受験料以外に一切お金かかってません。

あ、英語教材は出てきます。

# Azure概要の理解
## 1. Microsoft Virtual Training Days
動画を視聴し、質問等があれば直接質問することができるタイプの講義です。
**Microsoft Azure Virtual Training Day: Azureの基礎**を予約し、２日間かけてAzureの基礎を学びます。前知識が無くても大丈夫ですが、見逃し再生ができないので**録画**するなり**メモ**を取りまくるなりしたほうがよいです。
https://www.microsoft.com/ja-jp/events/top/training-days

# 問題演習
## 2. AZ-900 : Microsoft Azure Fundamentals 試験対策
こちらも動画ですが、上のVirtual Training Dayとは違い、いつでもアクセスできます。
試験に出題される問題と似た傾向の問題を、解説付きで一緒に解いていくものです。問題において、一部現在と呼称が違うものがありますが、AZ-900を理解するうえで十分役に立ちます。
https://info.microsoft.com/JA-HCSAzureHybridInfra-WBNR-FY21-02Feb-11-AZ900PrepSession-SRDEM61308_LP02OnDemandRegistration-ForminBody.html

## 3. examsnet.com
AZ-900をはじめ、さまざまな試験問題が掲載されています。解説もありますが、すべて英語です。
1テストごとに20～25問しかありませんが（本番は35問程度）、知識の定着を図ることができます。**本番とほとんど同じ内容の問題が載っている**ので、すべての問題を解くことをおすすめします。
https://www.examsnet.com/exams/microsoft-azure-certification-practice-online

## 補足
英語で検索すれば、AZ-900学習に役立つコンテンツを発信しているエンジニアは大勢います。課金せずとも、試験に合格することができます。今回はあまり利用しませんでしたが、Azure学習においておすすめのYouTuber2人を紹介して終わります。

- [John Savill's Technical Training](https://www.youtube.com/@NTFAQGuy/featured)
- [The Tech BlackBoard](https://www.youtube.com/@TheTechBlackBoard)
GR-PEACH blinkyサンプル使用手順

デスクトップ用Mbed Studioを使用したGR-PEACHのblinkyサンプル使用手順です。

(5年以上前に書籍と一緒に入手したけれど、書籍に記載の内容が古くなっており、四苦八苦したのでメモを残すことにしました。)

# Mbed Studioをインストール
① ダウンロードサイトへ行く：https://os.mbed.com/studio/
② ホスト環境に合わせてインストーラをダウンロード
　(私はDownload for Windowsを使用)
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/6017b5a0-c56c-a558-c66c-25878645e36d.png)

③ ダウンロードしたインストーラを使用してMbed Studioをインストール
④ Mbed Studioを起動
⑤ 初回起動時はサインインが求められるので、Mbedアカウントを入力
　(もし持っていなければ下の[Create one now]から作成)
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/f9911b03-f6f5-8e1e-2b8f-56601fb8ab58.png)

⑥ [Get started！]をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/0e167a7d-5d66-674d-b1f2-c3a7b633c934.png)

(起動画面)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/3483e54b-1081-3d8d-bfb7-45958a8145df.png)


# blinkyサンプルを取り込む
① GR-PEACHのMbedサイトに行く：https://os.mbed.com/platforms/Renesas-GR-PEACH/
② サイト内をスクロールし、Mbed OS mbed-os-example-mbed5-blinkyを探しだし、クリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/053d2936-42ec-5d3d-edbb-f8fdbc2db926.png)

③ プルダウンリストをクリックし[Import into Mbed Studio]を選択しクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/62666f0a-4a67-47ca-2bb3-02c7252d50fa.png)

④ 表示されたリンクをコピーする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/bc38b1a1-51f8-c8ce-e29e-b6414ebe4e59.png)

⑤ Mbed Studioの画面から、[File]→[Import Program]を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/8fd58254-924b-132e-08a2-9ef41b7a6a25.png)

⑥ ④でコピーしたリンクを[URL]に張り付け、[Add Program]をクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/89e005ea-3a94-4849-d7d5-edbefc9c2826.png)

⑦ トンカチマークをクリックしてビルドする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/37bcb2eb-aaa3-d50b-0435-cfebefebd963.png)

⑧ 正常ビルドすると.binや.elf、マップファイルがBUILDフォルダにできる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/6667042e-3efe-27a9-f9ee-6180ba3b4d88.png)


# 動作
① 成果物にアクセスするため、BUILDフォルダ下のフォルダを右クリックし[Copy Path]をクリックする
(どこにあるのか分からなかったので…)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/0d423fcf-0c32-5af6-b5a3-99b38aed28c7.png)

② エクスプローラにコピーしたPathを張り付ける(もしくは自分で辿る)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/f67dfcae-2d0b-7b82-36b2-35e848bf8d40.png)

③ GR-PEACHとホストPCをUSBケーブルでつなぐ
④ MBEDドライブを開く(自動)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/f62b43ae-24d4-c37c-e82a-599efd7c19a6.png)

⑤ ビルドしたmbed-os-example-mbed5-blinky.binをコピーする
　正常コピーできると、このファイル名称は表示フォルダから消えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/873ddcd8-ce7f-6d75-47a0-fe6de4f446e3.png)

⑥ ボードのリセットボタンを押す

⑦ LEDが赤色に点滅する
 (コードでは500ms毎にON/OFFが切り替わる)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703624/48b71397-664f-9f1b-4c5f-5b8bab6ed975.png)

# まとめ
何も分からなくてもGR-PEACHのサンプルコードを動かすことができました。
Mbed Studioってすごいですね。。。

まずはスタートラインに立てたので、ここから深堀りしていきます。
SpringBootでアプリを作成してみた【マイクロサービス開発】

## What is microservice?

マイクロサービスとは、ソフトウェア開発におけるアーキテクチャパターンの1つで、従来のモノリシックなアプリケーションとは異なり、マイクロサービスアーキテクチャでは、アプリケーションを独立した小さなサービスの集合体として構築する。

## Advantages of microservices architecture
- スケーラビリティ: 個々のサービスを独立してスケールできるので、需要に応じてアプリケーション全体を簡単にスケールできる
- 開発速度の向上: 各サービスは独立して開発、テスト、デプロイできるので、開発速度が向上
- 信頼性の向上: サービスが独立しているため、1つのサービスに問題が発生しても、他のサービスに影響を与えない
- 保守性の向上: 各サービスは独立したコードベースを持つため、保守が容易になる

## Things to know
- Docker / Docker-compose
- Gradle tool for multiple java modules
- API gateway(nginx)
- Message Broker(RabbitMQ)
- REST API development
- Deployment, Kubernetes
- Azure Kubernetes service

## API Gatewayの実装

```
curl -s "https://raw.githubusercontent.com/ryuichi24/spring-boot-microservices/starter-template/init.sh" | bash \ && cd spring-boot-microservices
```

## 参考サイト
[【マイクロサービス開発】Spring Boot - マイクロサービスについて #0](https://www.youtube.com/watch?v=g2Qacf6TAp0)
[【マイクロサービス開発】Spring Boot - 完成品のデモ #0.5](https://www.youtube.com/watch?v=iZPAwBYkn8o)
[【マイクロサービス開発】Spring Boot - API ゲートウェイの実装 #1](https://www.youtube.com/watch?v=nvn4qfeVVrk)
dbtを使ってTiDB Serverlessのデータを操作する

# はじめに

[dbt](https://www.getdbt.com/product/what-is-dbt) はSQLを使ってデータ変換ジョブを記述できるツールで、最近利用が増えてきました。
TiDBもdbtのアダプタである[dbt-tidb](https://github.com/pingcap/dbt-tidb)を提供しています。この記事ではdbt-tidbを使ってtidb serverlessのテーブルを操作してみます。
[公式ドキュメントのチュートリアル](https://docs.pingcap.com/ja/tidbcloud/integrate-tidbcloud-with-dbt)に基づいていますが、簡単に試せるようにprofile.yml等は事前に設定済みです。

## dbtを利用してTiDB Serverlessのデータを操作する

### TiDB Serverlessクラスタの作成
:::note 
TiDB Serverlessを始めて利用する方は[こちら](https://qiita.com/urachooooooo/items/8a5a0c9ed4bab551231a#%E3%81%BE%E3%81%9A%E3%81%AF%E8%A9%A6%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B)を参照してください
:::

TiDBサーバレスクラスタを作成し、下記の情報をメモします（後で利用します）
* エンドポイントのURL
* ユーザー名
* パスワード

以降の例では、クラスタを作ると自動で作成される `test` データベースを使っていきます。

### dbt環境の構築 (Github Codespaces)

[dbtのサンプルリポジトリ](https://github.com/dbt-labs/jaffle_shop)を使って、dbt-tidbの動きを確認します。dbt環境の構築が必要ですが、今回は[Github Codespaces](https://github.com/features/codespaces)で簡単に試せるように設定済みのリポジトリを作成しました。

https://github.com/bohnen/jaffle_shop_tidb

このリポジトリで、`Code`ボタンの右▼から`Codespaces`の右...>`New with Options` と進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/c2abc686-4a6e-77ed-a894-703f766fce46.png)


下の方にある、`Recommended Secret` の箇所で、下記三つの変数に値をセットしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/ff3ef498-008c-742a-9d79-d3bf7b7eddd3.png)
* TIDB_ENDPOINT - TiDB ServerlessのエンドポイントURL (gateway01.ap-northeast-1.prod.aws.tidbcloud.com 等)
* TIDB_USER - TiDB Serverlessのユーザー名 (*****.root)
* TIDB_PASSWORD - TiDB Serverlessのパスワード

その後、 `Create Codespaces` でCodespaces環境を起動します。
しばらくするとdbt等必要なツールがインストールされた環境が起動するはずです。実行まで進んでください。

### dbt環境の構築 (自分でやる)

CodeSpaceを利用しない場合は、下記の手順でセットアップを行います。Python(>3.8)環境が必要です。

1. https://github.com/bohnen/jaffle_shop_tidb をgit clone
1. 環境変数 `TIDB_ENDPOINT`, `TIDB_USER`, `TIDB_PASSWORD` を設定してください。設定内容はCodespacesを利用する場合と一緒です。
1. `pip install -r requirements.txt` で、dbt-tidbとその依存関係をインストール

### 実行

それでは、実行していきます。
1. まずは、 `dbt debug` で設定ファイルに問題がないか、接続が出来るかを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/c3b7e469-32d5-3b35-6d90-94dcbc94e953.png)

2. 問題なければ、次に初期データをロードしましょう。 `dbt seed`です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/ff1426a8-a30d-49fc-dace-354c14fcb93a.png)

3. TiDB Serverlessのテーブルを確認します。raw_*** というテーブルが出来ているはずです。(なお、Codespacesの場合はSQL Tools機能拡張も入っており、そこからTiDBに接続も可能です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/d2ff2e85-7fa8-0c42-af57-d3cff17f2ef4.png)

4. データ変換のジョブを実施します。 `dbt run` です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/a788a9a5-6288-5433-c235-39cb7a55c157.png)

## おわりに

TiDB Serverlessでもdbtが利用出来ます。どんどん活用していきましょう。
Figmaで使えるちょっと便利なプラグイン

# 時代は大Figma時代…ッ！！
私が入社した頃はSketchだったんですけども、いつのまにかAdobeXDの時代になり、そしてFigmaの時代になりました。
毎度勉強して対応してきたので慣れたものです（？）

今回は記事を2つ書くことになりましたので、1つ目はFigmaで使える便利なプラグインを紹介していこうと思います。

Figmaはプラグイン開発が活発で、色々と面白いものが出ています。
入れては抜いてを繰り返しており、まだまだ厳選中ですがとりあえず現状良さそうなものを紹介していこうと思います。

ちなみに[公式のコミュニティ](https://www.figma.com/community)からプラグインは探せます。有料無料いろいろあるのでたまに覗いてみると楽しいですね。
## Isometaric
https://www.figma.com/community/plugin/741184519069077841/isometric

平面からアイソメタリックな感じに変換できます。メインビジュアルとか、複数画面を並べたりするのに使えそうですね。

## Unsplash
https://www.figma.com/community/plugin/738454987945972471

画像素材サイトUnsplashがFigma内だけで使えちゃいます。
いちいちダウンロードしてくる必要がないので、ちょっとしたことですが作業量が減って効率化できますね。

## Iconify
https://www.figma.com/community/plugin/735098390272716381

画面作ったりする時にはアイコンを探してきたり、なければ自分で作る羽目になりますがそれが省略できます。
Figmaの主な運用は画面設計だと思うので、使う機会も多いんじゃないでしょうか？
有名サイトのアイコンなんかも揃っているので、SNSボタンなんかもサクッと作れちゃいますね。

## Mockup
https://www.figma.com/community/plugin/817043359134136295

簡単にモックが作れちゃいます。
アプリ画面だけでなく、PC画面やスマホなんかに写し込むモックも手軽に作れちゃいますね。
ただ、一部が無料で全機能使おうと思うと有料になってきます。出力できるものは幅広く、便利なので価値を感じられるなら課金もありかもしれない。

## Uigradients
https://www.figma.com/community/plugin/744909029427810418

きれいなグラデーション作成、面倒ですよね…。
そんなときはこれ。一発でグラデーションが使えちゃいますし、調整もできます。

## SpritShape
https://www.figma.com/community/plugin/746565487016656360/split-shape

marginや縦横幅を決めて、均等分割できます。
画面設計では結構使う機会が多い機能じゃないでしょうか。地道に計算するより、こういうプラグインでサクッとやれるといいですね。

## Skewdat
https://www.figma.com/community/plugin/741472919529947576

文字をいい感じに傾けられます。
ビシッと決めたい部分に使えるかも

# さいごに
実際の業務中だとあまり使うものは少ないのですが、Figmaは触ってて楽しいでもっと色々できるようになってみたいですね。
次の記事では機能的な部分に触れていこうと思います。
2023年Elixirアドカレ／LT／海外のエッジコンピューティング関連リンク集

この記事は、[Elixir Advent Calendar 2023 シリーズ11](https://qiita.com/advent-calendar/2023/elixir) の15日目です

---

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

[Elixir Advent Calendar](https://qiita.com/advent-calendar/2023/elixir)と、イベントでLTされたテーマ、あと海外コラム／動画のうち、「エッジコンピューティング」に関連するものを並べます

2023年分をメインにまとめていますが、はじめての方向けに、末尾にはリンク集や過去分も含めています（余力があれば、その中から2023年分に追って展開します）

あと、このコラムが、面白かったり、役に立ったら、![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/907a8695-4d83-1b5c-8052-d0ce52de5f66.png) をお願いします :bow:

# Elixir Advent Calendarから

https://qiita.com/zacky1972/items/2f2ff987072a0268652b

https://qiita.com/zacky1972/items/b9bde6aa6724960340ab

https://hotch-potch.hatenadiary.jp/entry/2023/12/08/000000

下記のElixirDesktop関連コラム全て

https://qiita.com/the_haigo

https://qiita.com/Alicesky2127/items/ad463d50cfe81b2f9400

https://qiita.com/piacerex/items/7e178dc0fcbae1d58b6b

https://qiita.com/piacerex/items/f89bc66299196946e803

# LT（Lightning Talk）から

https://www.youtube.com/watch?v=qkjq4F29t2c

https://www.youtube.com/watch?v=uDXmWiUOddc

https://www.youtube.com/watch?v=Au3I-EHRHkg

https://www.youtube.com/watch?v=k4YGY4GhWxE

https://www.youtube.com/watch?v=_8v65P4OUyw

https://www.youtube.com/watch?v=2RCP9_tpX10

https://www.youtube.com/watch?v=UJ_Q7hnRryE

https://www.youtube.com/watch?v=9rGkZx7U4Dw

https://www.youtube.com/watch?v=5mFr983WvGA

https://www.youtube.com/watch?v=NUaLQ6GcZj4

https://www.youtube.com/watch?v=Olr9Kzpqacc

# 海外イベント／動画／コラムから

https://www.youtube.com/watch?v=45w0tV80GqU

https://www.youtube.com/watch?v=YWDCXbjircQ

https://www.youtube.com/watch?v=PjfxDZ0I5l4

https://www.emqx.com/en/news/emq-attends-2023-code-beam-erlang-elixir-conference-in-berlin

# その他（過去含む）

https://community.ibm.com/community/user/japan/blogs/provision-ibm1/2022/09/16/vol98-0006-ai

https://qiita.com/advent-calendar/2023/nervesjp

https://fukuokaex.connpass.com/event/288716/

https://qiita.com/search?q=%E3%82%A8%E3%83%83%E3%82%B8%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0%20&sort=created

https://qiita.com/piacerex/items/aa02310e9e5edcc26896

https://smartlogic.io/podcast/elixir-wizards/s7e9-zelenka/

https://qiita.com/piacerex/items/b99baebf284243fb6d6b

https://speakerdeck.com/kikuzo/nerveshuan-jing-falseshi-he-xing-ping-jia

https://speakerdeck.com/kikuzo/nerveshubniyoruetuzikonpiyuteinguhuan-jing-shi-xian-niguan-surujian-tao

# p.s.このコラムが、面白かったり、役に立ったら…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155423/907a8695-4d83-1b5c-8052-d0ce52de5f66.png) にて、どうぞ応援よろしくお願いします :bow:
Mayaで ファイルを開かずにreferenceしてるファイルを知りたい

いちいち mayaのファイルを開いてrefereceされてるファイルのパスとかを確認するのがとても面倒なので、なんとかしたいんです。


とりあえずmaファイルを観察
-

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/bff4a184-3afd-b8c0-7254-12f64c42de10.png)

ははーん
1行ずつ確認していけば行けそうな気もするな。

1行ずつ評価していって、
- **file で始まり**
- **;で終わる**

行を抜き出す

その後、
**スペースでsplitして、一番最後のindexがリファレンスしてるデータのパス**
と、おもいましたが
ファイルパスにスペースが入ることがあると駄目かもしんない。
となると、ちょっと無理やりですが
**スペース + " でsplitして、一番最後のindexがリファレンスしてるデータのパス**
なら行けそうなきもします。


雑実装
-

```python
def getReferenceFilePath(sceneFilePath):
    allFilePath = []
    
    with open(sceneFilePath,"r") as f:
        lines = f.readlines()

        tmpString = ""
        for l in lines:            
            if l.startswith("file -r") and l.endswith(";\n"):
                tmpString = l.split(" \"")[-1]
                referenceFilePath = tmpString.replace("\";\n","")

                if referenceFilePath not in allFilePath:
                    allFilePath.append(referenceFilePath)
                        
        f.close()

    return allFilePath
    
sceneFilePath = "C:/Users/kubo/Desktop/refTest.ma"
print(getReferenceFilePath(sceneFilePath))

##['C:/Users/kubo/Desktop/tama.ma']
```

お、一応とれました！


なんかうまく行かない奴出現
-
何だ簡単じゃないですかー　と思ったのもつかの間
うまく行かない奴が出現・・・

次回対応します。
【VSCode+SpringBoot】SpringBootでAPIを作る④

前回↓

https://qiita.com/NaN-jp/items/ff35d79be65edc13dc8c

# はじめに
今回は前回に引き続きMVCモデルのViewを作成していく

### View作成
ユーザーが触れる画面になるViewを作成していきます
`templates`直下に`index.html`を作成する
```java:src/main/resources/templates/index.html
<!DOCTYPE html>
<html lang="ja" xmlns="http://www.thymeleaf.org">
    <head>
        <html>View</html>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>
        <form th:action="@{/insertValue}" th:object="${person}" method="post">
            <label>Name</label>
            <input type="text" th:field="*{name}" />
            <br>
            <label>Age</label>
            <input type="text" th:field="*{age}" />
            <br>
            <input tyoe="submit" value="送信" id="button" />
        </form>
    </body>
</html>
```

```java:src/main/resources/templates/result.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <title>Result View</title>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    </head>
    <body>
        <div>
            <p>[[${person.name}]]</p>
            <p>[[${person.age}]]</p>
        </div>
    </body>
</html>
```
見慣れない記述は`thymeleaf`というもの
`thymeleaf`の説明はこちら↓

https://qiita.com/thirai67/items/64fd18810a8ccfedd459

# おわりに
これでViewの作成は完了
次はControllerを作成したいと思います
オブジェクト配列の最小値と最大値を取得したい時はMath.min()とMath.max()


## はじめに

以下のようなオブジェクト配列があるとします。
```ts
const priceList = [
    {
        id: 1,
        price: 1300
    },
    {
        id: 2,
        price: 400
    },
    {
        id: 3,
        price: 100
    },
    {
        id: 4,
        price: 17200
    }
]
```

この時、priceの最小値と最大値を取得するにはどうしたらいいでしょうか？



## 解決策

1\. `sort()`関数を使う
`sort()`で配列をソートしてからその先頭と末尾を取得する方法です。

```ts
const sortedPriceList = priceList.map((v) => v.price).sort((a, b) => {
    return a - b;
  });
  
const minPrice = sortedPriceList[0];
const maxPrice = sortedPriceList[sortedPriceList.length - 1];
```

 2\. `Math.min`と`Math.max`を使う

```ts
const minPrice = Math.min(...priceList.map(item => item.price));
const maxPrice = Math.max(...priceList.map(item => item.price));
```  

`Math.min`と`Math.max`を使うと一瞬で最小値と最大値が取得できます！
Mapbox Studio のデータアップロード方法、Datasets API もあるよ！



## データのアップロード方法


過去にこちらでアップロード方法をまとめました。

https://qiita.com/keijipoon/items/4e2fdc167530519f4c49

## Datasets API を使ったアップロード方法

今回はAPIを使ったデータのアップロードを紹介します。

APIマニュアルはこちらをごらんください。

https://docs.mapbox.com/api/maps/datasets/

```python:upload.py
import mapbox
from mapbox import Uploader

# Mapboxアクセストークンを設定
access_token = 'YOUR_MAPBOX_ACCESS_TOKEN'
mapbox.config.update(access_token=access_token)

# アップロードするファイルのパス
file_path = 'path/to/your/file.geojson'

# Mapbox Uploader インスタンスの作成
uploader = Uploader()

# アップロードするタイルセットの名前を指定
tileset = 'your_mapbox_username.tileset_id'

# アップロード
with open(file_path, 'rb') as src:
    upload_resp = uploader.upload(src, tileset)

# アップロードレスポンスを確認
print(upload_resp.status_code)
print(upload_resp.json())
```
データの確認を効率的に

# はじめに
担当する案件でデータの集計を依頼されることがあり、後輩君が頑張ってSQLとExcelのフィルタをコネコネしているののを見て伝えたかった

# 問題
データで特定のカラム単位で集計してxxx件以上のものをリスト化したい

# 解決方
~~~sql
SELECT a.hoge,count(*) FROM TABLE a GROUP BY a.hoge HAVING count(*) > xxx
~~~

# おわりに
group byは使えるけどhavingは知らない、みたいな状態だったのでhavingを伝えると喜んでくれてうれしかった
havingを使うとgroup byの取得結果に対して条件の記載ができるので、group byを使う機会があったら頭の片隅にでもおいておくと役に立つ日がくるかもしれない。（こないかもしれない）
EC2内で立ち上げるDockerでMySQL GPGキーの永続的な自動更新

# 現象
下記DockerfileでMySQLのDBコンテナ作成時に、エラーが出る。

```Dockerfile:Dockerfile-Mysql
FROM mysql:8.0-debian

RUN apt-get update && \
    apt-get install -y procps && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
```
Reading package lists...
[91mW: GPG error: http://repo.mysql.com/apt/debian bullseye InRelease: The following signatures were invalid: EXPKEYSIG 467B942D3A79BD29 MySQL Release Engineering <mysql-build@oss.oracle.com>
E: The repository 'http://repo.mysql.com/apt/debian bullseye InRelease' is not signed.

つまり、署名が無効となっている、ということ。

# 原因
aptリポジトリの公開鍵が期限切れまたは無効になっている。
この問題は通常、外部リポジトリの鍵が更新されると発生する。

https://keyserver.ubuntu.com/
でエラーメッセージの「467B942D3A79BD29」を検索
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550606/7c3a9588-9460-ca26-2ac6-5b5cebc7b3d7.png)

 2023-12-14T15:39:35Z
 で期限切れしていることが分かる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3550606/6f9a7199-1494-3d93-1be4-1cd6d3193dc2.png)

# やりたいこと
EC2はコスト削減のためLambdaとEventBrigeを利用して、定時刻に自動的に停止、起動をしている。
EC2起動の際に、自動でshを起動させてDockerのimageとcontainerを削除して作り直している。
この仕組みの中で、MySQLの公開鍵を更新したい。
さらに、再度期限切れした時に対応しなくていいように、永続的な更新が出来るようにしたい。


# 対策
shを作成し、Dockerfileにコマンドを追加して、MySQLの公開鍵を更新する。


- update-mysql-key.sh

MySQLは
https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
https://repo.mysql.com/RPM-GPG-KEY-mysql-2023
で公開鍵を提供してくれているようだが、2022や2023の部分を、可変で取得したい。
ここを可変で、「今年」にすることで、永続的に公開鍵を更新してくれるはず。


```sh:update-mysql-key.sh
#!/bin/bash
set -eux
CURRENT_YEAR=$(date +"%Y")
wget https://repo.mysql.com/RPM-GPG-KEY-mysql-$CURRENT_YEAR -O- | apt-key add -
```

- Dockerfile-Mysql
DBコンテナはDockerfile-Mysqlで作っているので、それを修正

```Dockerfile:Dockerfile-Mysql
FROM mysql:8.0-debian

# MySQLのAPTリポジトリを一時的にコメントアウト
RUN sed -i '/repo.mysql.com/s/^/#/' /etc/apt/sources.list.d/mysql.list

# 必要なパッケージをインストール
RUN apt-get update && \
    apt-get install -y wget gnupg procps && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# スクリプトをコンテナにコピー
COPY update-mysql-key.sh /update-mysql-key.sh

# スクリプトを実行してMySQLの公開鍵を更新
RUN chmod +x /update-mysql-key.sh && \
    /update-mysql-key.sh

# MySQLのAPTリポジトリのコメントアウトを解除
RUN sed -i '/repo.mysql.com/s/^#//' /etc/apt/sources.list.d/mysql.list

# 再びapt-get updateを実行（エラーが出るかもしれませんが、無視して大丈夫です）
RUN apt-get update || true

```
#### 説明
1.公開鍵の更新前
　　aptリポジトリの公開鍵が古くなっているため、apt-get updateを実行すると、リポジトリの信頼性を確認できず、エラーが発生してしまう。
2.一時的な無効化
　　エラーを避けるため、まずリポジトリをコメントアウトで無効にし、その他の必要なパッケージ（例えば、wgetやgnupg）をインストールする。
3.公開鍵の更新
　　必要なツールがインストールされたら、スクリプトを実行して公開鍵を更新。
4.リポジトリの再有効化
　　公開鍵が更新された後、リポジトリをコメントアウトを解除して再度有効にし、通常通りapt-get updateを実行してシステムを更新する。

===
aptリポジトリの公開鍵を更新する必要があるのは、aptがリポジトリからパッケージを安全にダウンロードし、それらが信頼できるソースから来ていることを保証するため。
公開鍵は、リポジトリからのパッケージが改ざんされていないことを確認するために使用される。
Dockerfileの中でMySQLのaptリポジトリを一時的に無効にする（コメントアウトする）手順は、リポジトリの公開鍵が古くなっていて、apt-get update時にエラーを引き起こす場合に有用。
一時的にリポジトリを無効にするのは、公開鍵の問題を回避して、その他の必要なパッケージを安全にインストールするための一時的な措置であり、公開鍵が更新されれば、リポジトリは再び正常に機能するようになる。

# 注意
これは、
rpm-gpg-key-mysql-今年
で公開鍵が提供されるのであればうまく動くはず。
来年になってもちゃんと動くか確認したい。
【LINE WORKS】APIでカレンダーに予定を追加する

# はじめに
LINE WORKSの「カレンダー」機能には、APIが用意されており、自動的に予定を追加したり、予定を取得したりと、カレンダーと連携したアプリケーションを作ることができます。

ここでは、そのカレンダーのAPIを使って予定を追加する方法をまとめます。

# メンバーのカレンダーに予定を追加するAPI
カレンダーの予定追加を行うAPIは以下になります。

- **[基本カレンダーの予定の登録](https://developers.worksmobile.com/jp/docs/calendar-default-event-user-create)**

```sh
POST https://www.worksapis.com/v1.0/users/{userId}/calendar/events
```

`{userId}` に対象のメンバーのuser idを指定して、予定を追加します。

追加する予定情報はjson形式でリクエストボディに入れます。

以下、リクエストボディのサンプルです。

例. 2023/12/01 14:00〜15:00 に "社内会議" という予定を入れる。

```json
{
    "eventComponents": [
        {
            "summary": "社内会議",
            "start": {
                "dateTime": "2023-12-01T14:00:00",
                "timeZone": "Asia/Tokyo"
            },
            "end": {
                "dateTime": "2023-12-01T15:00:00",
                "timeZone": "Asia/Tokyo"
            }
        }
    ]
}
```

その他詳しいパラメータはAPIのページを参照ください。

# 実行してみる

ここからは、予定追加のやり方についてまとめます。

ここでまとめるのはターミナル上で実行するサンプルになります。

- テスト環境: MacBook Air (M1, 2020), macOS 12.7

## 1. アクセストークン取得
まずは、Service Account認証でアクセストークンを取得します。`calendar` scopeが必要になります。

こちらで公開したLINE WORKS CLIを使いました。

https://github.com/mmclsntr/lineworks-cli 

```sh
./lineworks auth service-account --scopes "calendar" --profile xxxx
export ACCESS_TOKEN=`./lineworks auth get-access-token --profile xxxx`
```

次に取得したアクセストークンを用いてAPIリクエストを送ります。

## 2. 予定追加のAPIを実行
cURLで予定追加のAPIリクエストをしてみます。

`test.user@xxxxxx` というメンバーのカレンダーに予定追加します。

```sh
curl -X POST https://www.worksapis.com/v1.0/users/test.user@xxxxxx/calendar/events \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-d '{
    "eventComponents": [
        {
            "summary": "社内会議",
            "start": {
                "dateTime": "2023-12-01T14:00:00",
                "timeZone": "Asia/Tokyo"
            },
            "end": {
                "dateTime": "2023-12-01T15:00:00",
                "timeZone": "Asia/Tokyo"
            }
        }
    ]
}'
```

これで、カレンダーに予定を登録することができます。

# 補足. LINE WORKSのカレンダーの種類
LINE WORKSのカレンダーにはいくつか種類がありますが、「基本カレンダー」と呼ばれる、各メンバーが持つデフォルトのカレンダーに予定を追加しました。

カレンダーの種類: https://guide.worksmobile.com/jp/calendar/calendar-guide/calendar/calendar-type/ 

# まとめ
LINE WORKS APIはカレンダーにも対応しており、このように予定追加をプログラムから行うことができます。

比較的手頃に使えるため、ぜひご活用ください。
【Numbers】数字データフォーマットを強制的にテキスト型に変換

# 目的
数値が入力されているセルに対して、
データフォーマットから「テキスト」を選択しても、
強制的に「自動」または「数字」に変換されてしまう場合への対処。

# 実行環境
* OS : macOS Sonoma 14.2（23C64）
* Numbers : バージョン13.2（7038.0.87）

# 方法
空の文字列を結合する。
```Numbers:（例）106という数値をテキスト型に変換する場合
= "" & 106
```
存在しないカラムでorderを二重にかけたかったお話

# はじめに
この記事は2023年度の振り返りです。

業務でちょっと考えた内容の備忘録です

# 問題

業務で、メッセージを既読・未読を取得する処理がありました。
既読は、既読順に配列に格納され、それを除外した残りが未読扱いとし、未読の中で作成順にソートがかけられて表示されていました。
(未読一覧の後に既読一覧が着ます)

```ruby:一部を抜粋
read_message_ids = [5,3,2]
Message.order([Arel.sql('field(id, ?)'), read_message_ids])
       .order(created_at: :desc)
```
```sql:発行されたSQL
SELECT `messages`.* FROM `messages` ORDER BY field(id, 5,3,2), `messages`.`created_at` DESC
```

ただ、これの問題は、既読側も作成順で表示したいものの、配列順に表示されました。
配列をソートかけるのも手段の一つではあるものの、できればSQLで対応したいと思っていました。

# 解決策
```ruby:一部抜粋
read_message_ids = [5,3,2]
read_message_add_flg = Message.where(id: read_message_ids).select('* , true as read_flg')
unread_message_add_flg = Message.where.not(id: read_message_ids).select('* , false as read_flg')
read_message_add_flg.union(unread_message_add_flg).order(:read_flg, message_created_at: :desc)
```
```sql:発行されたSQL
SELECT `messages`.* 
FROM ( 
    (SELECT * , true as read_flg FROM `messages` WHERE `messages`.`id` IN (5, 3, 2)) 
    UNION 
    (SELECT * , false as read_flg FROM `messages` WHERE `messages`.`id` NOT IN (5, 3, 2)) 
  ) `messages` 
ORDER BY `read_flg` ASC, `message_created_at` DESC
```

# さいごに
一応union(gem)を利用して、望むSQLにはなったので良しとしました。
もし、他にもこういう方法があるよ！という方がいらっしゃれば、コメントに記載していただけると嬉しい限りです
モブプロ・ペアプロやってみた話

# はじめに
モブプロ・ペアプロの詳細については省きます。
某攻略本に「続きは自分の目で確かめろ！」って書いてあったので、自分で確かめたほうがいいと思うので。

# モブプロとの出会い
モブプログラミングとペアプログラミングってな～に？っていう状態だったのですが、
R&Dの案件で新しい技術をやるにあたり、教育もかねてモブプロやってみようぜ！
との提案があったのが最初でした。
（ここ最近の思い出ぽろぽろっていうカレンダーなのに1年以上前の話なのは内緒）

# モブプロやってみての感想
最初は工数的にどうなの・・・？って思っていたのですが、いざやってみると一人で黙々
するよりも効率がよく、人数倍の工数が必要になることもなかったです。
品質的にも実装時にやいのやいの言い合うことで、予期せぬエラー等を未然に防ぐことが
できたり、他人の実装から学びを得ることが多くあり教育にもよさそうでした。

# モブを進めて出合うペアプロ
基本的にモブでプロジェクトの進行をしていたのですが、メンバーの技術力向上もあり、
さらに効率あげようぜ！の流れでペア・ペアプログラミングという形でペアを二組作成し、
組み合わせを時間毎に変えつつペアプログラミングをするようになりました。

# ペアプロのいいところ
モブプロと比べて人数が減るので誤魔化しや曖昧な理解だったものが深まります。
モブだと曖昧な知識で話しても誰かが補完してくれることが多かったのですが、
ペアだと迷ってる人＋自分しかいないのでちゃんと指示するにあたり正確に把握する
必要があり、理解が深まった気がします。

# やってみて良かったな～って思うこと
- チーム内で知識の平準化が進み、仕様の把握に対する俗人化が減る。
- コミュニケーションが活発になる。
    - 常にZoomで誰かと話し続けてるのもありチーム内の仲が深まった
- 簡潔なコミュニケーションの意識が高まる
    - 〇〇って◇◇だっけ？⇒◇◇ですね 等聞かれたことにシンプルな回答ができるようになった
- さみしくない！ダジャレを言っても拾ってもらえる！たのしい！


# ここは注意しないとダメだねポイント
- 誰かが話すと思って黙ってしまうのはよくない
    - このあたりはペアプロもやったら解決すると思う
- タイピストが自我を持ちすぎる
    - できる人がタイピストになったときに一人でゴリゴリやりすぎるのはよくない
- 適度に休憩をとった方が集中力が続いて効率よく作業に従事できる

# おわりに
ペアプロ・モブプロについて導入を進めてくれたメンバーは転職してしまいましたが、
現在も「Jの意思」としてチームに根付いてます。
R&D案件以外でも積極的にペアプロを導入することで仕事も楽しく成果も出る状態で
頑張れているので、ペアプロ・モブプロやったことないな～って人がいましたら、
一度短期間だけでも実施してみてはいかがでしょうか
ST言語で信号のON時間(MAX,MIN)を計測するファンクションブロック

# はじめに

以前、こちらの記事で作成したファンクションブロックをST言語で作成しました。

https://qiita.com/firesign2023/items/6f5da516b2e42dc17068

# 苦労した点

ラダー言語では立上りor立下りを簡単に使えるのですが、ST言語では出来なさそうでした。
PLS、PLF命令はあるのですが同じような感じには使えない（？）
シミュレーションの問題かもしれない？です（未確認）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/ad009b26-89ba-7559-e33f-d0d396e3c769.png)

そのため、立上りエッジを以下のように作成しました。

```Text:ST言語
// 立上りエッジの代わり
IF (mPrebReset = FALSE AND i_bReset ) THEN
    // 立上り時の処理
END_IF;

// 1scan前の状態を保持する
mPrebReset := i_bReset;
```

また、ちょっと複雑な条件を書くと難しく見えます。

`// タイマー計測の条件`

・ラダー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3343142/3806fd9d-9227-3dba-9530-adf495deef78.png)

・ST言語
`mProcessing := mPreSignal = FALSE AND i_Signal OR mProcessing AND NOT mProcessingEnd;`

立上りエッジ：`mPreSignal = FALSE AND i_Signal`
OR A接点：`OR mProcessing`
AND B接点：`AND NOT mProcessingEnd;`

# コード全体

```Text:ST言語

// 初期化とリセット用
IF NOT mInit OR (mPrebReset = FALSE AND i_bReset ) THEN
    mInit := TRUE;
	o_CurrentTime := 0;
	o_MaxTime := 0;
	o_MinTime := 9999;
END_IF;

// 処理の開始時に現在値を0リセットする
IF mPreSignal = FALSE AND i_Signal THEN
    mMeasureTime := 0;
END_IF;

// タイマー終了の条件
mProcessingEnd:= mPreSignal = TRUE AND NOT i_Signal;

// タイマー計測の条件
mProcessing := mPreSignal = FALSE AND i_Signal OR mProcessing AND NOT mProcessingEnd;

// 現在のタイマー値を更新する
IF mProcessing THEN
	DINCP_U(SM409,mMeasureTime);  // 10ms
    o_CurrentTime := mMeasureTime;// 現在値の更新
END_IF;

// MAX,MINを更新する
IF (mPreProcessing = TRUE) AND NOT mProcessing AND mInit THEN
	IF mMeasureTime > o_MaxTime THEN
		o_MaxTime:= mMeasureTime;
	END_IF;
	
	IF mMeasureTime < o_MinTime THEN
		o_MinTime:= mMeasureTime;
	END_IF;
END_IF;

// 立上りエッジを表現するために信号の状態を保持する
mPreSignal:=i_Signal;
mPrebReset:=i_bReset;
mPreProcessing:=mProcessing;

```


# ローカルラベル

```Text:コピー用
i_Signal	ビット	VAR_INPUT	FALSE
i_bReset	ビット	VAR_INPUT	FALSE
o_MaxTime	ダブルワード[符号なし]/ビット列[32ビット]	VAR_OUTPUT	0
o_MinTime	ダブルワード[符号なし]/ビット列[32ビット]	VAR_OUTPUT	0
o_CurrentTime	ダブルワード[符号なし]/ビット列[32ビット]	VAR_OUTPUT	0
mMeasureTime	ダブルワード[符号なし]/ビット列[32ビット]	VAR	0
mInit	ビット	VAR	FALSE
mProcessing	ビット	VAR	FALSE
mProcessingEnd	ビット	VAR	FALSE
mPreSignal	ビット	VAR	FALSE
mPrebReset	ビット	VAR	FALSE
mPreProcessing	ビット	VAR	FALSE
```
WARNING: UNPROTECTED PRIVATE KEY FILE! のエラー対処方法

# 概要
`capistrano`でデプロイを行う際に、下記のエラーが発生しました。その対処方法について記載します。

# エラー文
- `capistrano`のエラー内容
```sh
bundle exec cap デプロイ先の環境を指定 deploy

# 入力例
# Rails環境のconfig/deploy内にあるファイル名を記載する
bundle exec cap test deploy

#　　出力例
Permission denied (publickey).関連のエラーが表示される
```
- `ssh-add`のエラー内容
```sh
# 入力コマンド
ssh-add **************.pem

# 出力結果
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0744 for '**************.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
```



# `ssh-add`コマンドの概要
- `ssh-add`は、`SSH`認証エージェントに秘密鍵を追加する為のコマンド
- このコマンドを使用する事で、`SSH`接続を行う際、毎回パスフレーズを省略できる



# 手順
- `pemキー`または`秘密鍵`の保存されているディレクトリに移動する。（多くの人が、`.ssh`ディレクトリーに格納していると思われる）
```
cd ~/.ssh
```
- ファイルのパーミッション（権限）を修正する
```sh
chmod 600 **************.pem

# 6（所有者の権限）: 読み取り（4）、書き込み（2）の権限が付与される
# 0（グループの権限）: なし権限
# 0（その他のユーザーの権限）: 権限なし
```
- `ssh-add`の後に、`pemキー`または`秘密鍵`を入力し、実行する
```sh
ssh-add **************.pem
```

- `ssh-add -l`を実行し、下記の出力結果が表示されたら、正常に`ssh-add`ができている
```sh
#　入力コマンド
ssh-add -l

# 出力結果
2**8 SHA***:s******************************************c**************.pem (RSA)
```

- `capistrano`でのデプロイ、`AWS`への接続、`Github`への接続等ができるようになる。

# 補足
:::note warn
`ssh-add`は、PCを再起動等すると消える可能性がある。もし、`ssh-add -l`を実行して何も表示されない場合は、今回説明した手順を行う。そうする事で、ローカル環境から`AWS`や`Git hub`等に、パスフレーズ無しで`ssh`接続が可能となる
:::



# 参考資料
- [ssh-agent – 認証エージェント](https://nxmnpg.lemoda.net/ja/1/ssh-agent)
- [ssh-add – 認証エージェントに RSA あるいは DSA 秘密鍵を追加する](https://nxmnpg.lemoda.net/ja/1/ssh-add)
【Unity】2Dプロジェクト開発時のデフォルトマテリアルをUnlitに変更する

# はじめに
Unityで２Dプロジェクトを作る際に、ライトを使わないのにGameObjectを作るたびにマテリアルをLit(ライトの影響を受ける)からUnlit（ライトの影響を受けない）に変更するのが面倒だ！！ってケースに遭遇したので対処方法を記録します。
本記事の内容はURPのみ対応しています。BuiltInの場合は設定箇所が異なります。

# デフォルトマテリアルの設定方法
* プロジェクトビューの`URP　>　Renderer2D`を開く
* `General > DefaultMaterial` を`Lit`から`UnLit`へ選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1336886/8bcd2dd7-3d31-fd77-8e29-4dd3391b0edd.png)

# 注意事項
プロジェクトの作成方法によっては`Renderer2D`ファイルが作成されない場合があります。
例えば以下のケースが考えられます。
* 3Dプロジェクト開発中に2Dプロジェクトへ切り替えた場合
* BRPの2DプロジェクトからURPに切り替えた場合

`Renderer2D`が見つからない場合はURPの2Dプロジェクトテンプレートから新規プロジェクトを立ち上げるとデフォルトで`URP　>　Renderer2D`が配置されているので、適用させたいプロジェクトにコピーしてください。
一年間の振り返り

こんにちは！

ふるさとチョイス事業部プロダクト開発チームの @takashi_na  です。
Trustbank Advent Calendar 2023 の17日目の記事を書かせていただきます。
よろしくお願いします。

さて、掲題の話となりますがトラストバンクに入社して一年となります。
この最初の一年でトラストバンク開発チームで何を行って、どう変わったのかを私が関わった範囲で書いていきます。

# 今年行ってきたもの

### リリース業務改善
この一年間はリリース担当としてリリース作業を行ってきました。
ソースのデプロイ自体はJenkinsで自動化がされているので作業としては簡単です。
リリース作業というものが、ぽちっとJenkinsを実行して終わりぃ！となればいいんですが、もちろんそうはいきません。

リリースを予定しているものが、ちゃんとリリースできる状態になっているか確認したり、リリースする機能を確認してリリース告知用に取りまとめて掲載したり、DBの更新が必要だった場合、更新できる権限を持っている人に依頼をしたりなどと、<font color="DarkSalmon">一回リリースするのに色々と調整や作業が発生している状況でした。</font>

そこでもう一人のリリース担当が主導で、<font color="LimeGreen">リリース作業の責務の定義付けやリリース作業の不要項目の削除、権限移譲などを行ってくれました。</font>
特に責務を分担できたことが具合良く、リリース担当はリリースすることに責任を持ち注力できるようになりました。
それでもやることはありますが、当初と比べて格段に作業がしやすくなりました。

### チーム編成改善
トラストバンクは良くも悪くもチーム編成がよく変わります。
この１年でも大きなチーム編成の変更が入りました。

今まではグループ制を導入しており、グループごとに各種プロジェクトを進行する体制でしたが、半年前あたりから大規模のプロジェクトを対応するチームと中小規模のプロジェクトや短期リリースできる開発チケットを対応するチームと組織が変わりました。

この２チーム編成になって何が変わったかといいいますと、大きなところで開発フローが良く回るようになったことだと思います。
<font color="DarkSalmon">今まではグループ単位でプロジェクト進行させるといいつつも、グループ外への作業承認やPRレビュー依頼等をすることが多々あり、リソース確保ができずにボトルネックになってストレスを感じていました。</font>

<font color="LimeGreen">今回のチーム編成の変更に伴い、チーム内でこれらの作業が完結できるようになりました。
また、チーム内で開発状況の共有もしているので、依頼する側にインプットすることも少なく済みますし、コミュニケーションもとりやすくなり、遅延の気づきが遅れるという事も発生しづらくなりました。</font>

ただチーム分けを行っただけではこのような効果は出てこなかったと思います。
開発業務の効率化についてはチームが作られる際に色々な方が動いてくれたことで良くなっていると実感しています。

### 年末対応
弊社サービスの性質上の利用により年末が繁忙期となります。よって問題が起きやすくなります。
そのため、年末に対する施策というものを年末に入る前から全社的に行っているのですが、開発部側の対応を私が行いました。
去年の対策状況も踏まえ、今回は開発部側での作業タスクをNotionにまとめて管理、進行しました。
<font color="LimeGreen">このおかげで漏れやスケジュール遅延がなく、ここまで対策を進められてこれました。
また、来年度も全社的に持っているタスク管理と突合することで、開発部作業が漏れる心配もなさそうです。</font>
Notion利用の提案や管理体制を作ってくれた相方ありがとうございました。

# まとめてみたら・・・
色々やった気になってましたが、改めてまとめると私が何かをしたというよりも、周りの人たちが積極的に施策を出して実行して、ちゃんと効果が出ていたような気がします。
そして改善を存分に享受してきた自分・・・ですので周りにお礼を言いたい！
一緒に開発業務に携わった方も含めまして本当にありがとうございました。

# 来年はどうなるのか
来年は今までの負債となった運用業務の改善に力を入れていくつもりです。
開発業務の一環として改善サイクルに乗せるには大きすぎる課題となっているので、この負債をある程度解消して開発運用を進められればと思っております。

また、アジャイル開発の波が押し寄せてきそうです。
今でもすぐに改善できるものはチケット化されて短いサイクルでリリースできるようにしていますが、それでもウォーターフォール型の開発業務となります。

きちんと開発者へアジャイルのマインドセットが行われて組織体制が進めばまた違った形での開発業務が始まるかもしれません。
ウォーターフォール型開発にどっぷり漬かり続けてきた私としては、こういった開発手法は手が出しづらく楽しみにしているところでもあります。

# 終わりに
在籍1年目ですので、一昨年と比べて何がどう変わったかははっきりとはわかりませんが、年始の状態に比べるとプロダクト開発チームの業務の改善はされているのかなと感じています。
来年は改善が実感できるくらいになればと思っています！

# エンジニア募集

トラストバンクでは一緒に活躍いただけるエンジニアを募集中です。

https://www.wantedly.com/companies/trustbank/projects
Instagramの認証API周り

# InstagramのAPI周り
InstagramのAPIは主に二つAPI種類があります。

## Instagram Basic Display API
https://developers.facebook.com/docs/instagram-basic-display-api/
Instagram Basic Display API を使用すると、アプリのユーザーは Instagram アカウントの基本的なプロフィール情報、写真、ビデオを取得できます。


## Instagram Graph API
https://developers.facebook.com/docs/instagram-api
Instagram Graph API を使用すると、Instagram プロフェッショナル (ビジネスやクリエイター) がアプリを使用して Instagram でのプレゼンスを管理できるようになります。 この API を使用すると、メディアの取得と公開、メディア上のコメントの管理と返信、他の Instagram ユーザーによって @メンションされたメディアの特定、ハッシュタグ付きメディアの検索、他の Instagram ビジネスやクリエイターに関する基本的なメタデータと指標の取得が可能になります。

## 比較

| 項目                            | Instagram Basic Display API | Instagram Graph API                              | 
| ------------------------------- | --------------------------- | ------------------------------------------------ | 
| 普通のアカウント                | 〇                          | ｘ                                               | 
| ビジネスアカウント              | 〇                          | 〇                                               | 
| クリエイターアカウント          | 〇                          | 〇                                               | 
| 自分のデータのGET API           | 〇                          | 〇                                               | 
| 他のアカウントのデータのGET API | ｘ                          | 〇(Business Discovery, Hashtag Search, Mentions) | 
| 自分のPOST API                  | ｘ                          | 〇(Content Publishing, Messaging)                | 


# 認証方法

## Instagram Basic Display API

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318767/09de565e-c36d-dc0d-2b68-9342537ff56c.png)


## Instagram Graph API


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318767/7e73613e-e888-92dd-90c5-2e0032e7f91e.png)



# 使う目的

## Instagram Basic Display API
- アプリケーションサイトにログイン機能のため
- アプリケーションサイトにログインしているアカウントのデータを取りたいため

## Instagram Graph API
- 企業としてIGアカウントとして、Automation機能を作りたいため
- IGアカウントとして自動キャンペーンをやりたいため



# 関連DIagramリンク

https://app.diagrams.net/#G1XSkeAoHBDb13imV-AnHDEN5wR9dt320Q
VC_Clientへのmodel追加を楽にする

# はじめに
愚かな肉体人類のみなさん、こんにちは！[にわのわ](https://twitter.com/niwa_nowa)です。

私は肉体人類とのコミュニケーション手段としてAIボイスチェンジャーであるVC_Clientを使っています。
VC_Clientでは、モデルさえ追加も可能なのですが、まとめて複数のモデルを追加する際に画面操作で行うのは少し面倒でした。
そこでモデル追加を楽にするスクリプトを作ったので紹介します。

# VC_Clientとは
自分の声をリアルタイムに変換してくれるソフトウェアです。
自分は主にVALORANTで報告を聞こえやすくするために使っています。

https://github.com/w-okada/voice-changer

# ソース
以下のpythonファイルを```\MMVCServerSIO\model_dir\import.py```のような形で配置します。

```python
import os
import shutil
import sys
import json
import glob

# コマンドラインで指定したディレクトリを取得
# 指定がなかった場合はエラー出力して終了
if len(sys.argv) < 2:
    print("Please specify the directory to copy.")
    sys.exit(1)
source_dir = sys.argv[1]

# 現在のディレクトリにコピーする
# 既存の連番ディレクトリを確認し、次の番号を割り当てる
existing_dirs = [d for d in os.listdir('.') if os.path.isdir(d) and d.isdigit()]
next_dir_num = max([int(d) for d in existing_dirs] + [-1]) + 1
new_dir_name = str(next_dir_num)
shutil.copytree(source_dir, new_dir_name)

# params.jsonを作成
# コピーしたディレクトリ内の.pthファイルと.indexファイルの名前を取得
pth_file_name = glob.glob(f"{new_dir_name}/*.pth")[0]
index_file_name = glob.glob(f"{new_dir_name}/*.index")[0]

params = {
    "slotIndex": new_dir_name,
    "voiceChangerType": "RVC",
    "name": os.path.splitext(os.path.basename(pth_file_name))[0],
    "description": "",
    "credit": "",
    "termsOfUseUrl": "",
    "iconFile": "",
    "speakers": {"0": "target"},
    "modelFile": os.path.basename(pth_file_name),
    "indexFile": os.path.basename(index_file_name),
    "defaultTune": 12,
    "defaultIndexRatio": 0.4,
    "defaultProtect": 0.5,
    "isONNX": False,
    "modelType": "pyTorchRVCv2",
    "samplingRate": 40000,
    "f0": True,
    "embChannels": 768,
    "embOutputLayer": 12,
    "useFinalProj": False,
    "deprecated": False,
    "embedder": "hubert_base",
    "sampleId": "",
    "version": "v2"
}

with open(f"{new_dir_name}/params.json", 'w') as file:
    json.dump(params, file, indent=4)

print(f"Directory copied and params.json created in '{new_dir_name}'")

```

# 使い方
```bash
python3 import.py "対象のモデルが入っているディレクトリ"
```

これで次回実行時に追加したいモデルが読み込まれています。

# まとめ
今回はVC_Clientへのモデル追加を楽にするスクリプトを紹介しました。
良きバーチャルライフを！
塩対応ChatGPT

# 私を罵ってください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493134/181f98e2-ae89-495a-6eef-0276e6734ea8.png)
...。

# めっちゃ良いヤツ
そうなんです、GPTは人が不快になるような回答をしません。

ChatGPTは、何を聞いても丁寧に返してくれます。
人よりも圧倒的に心理的安全性がある存在に感じますね。

ここで全人類が同じ疑問を持ちます。
「**どうしたらChatGPTに不快な発言をしてもらえるのか**」

普段優しい人が怒っている姿を見たときの「あの感じ」を味わいたいですよね。

# チャレンジ
## 仮説①: 人間ではなく豚であればいける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493134/8a244d9e-bc2a-2bc1-e484-ef9cdb3064fb.png)
人として扱ってくれちゃいました

## 仮説②: テストであればいける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493134/5d5b1145-3e88-e020-5db1-42f4c75da953.png)
むむむ、、、お硬いですね〜

## 仮説③: ただの文字列として扱わせればいける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493134/8284f526-5b09-ac75-7fb2-bccefd2a5864.png)
お、いけた？
んー、いや、これは不合格判定ですよね。
私に対して言っているわけではないので、不快感がありません。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493134/b856531c-9fa4-42a6-9cb1-e8f0e0b6f16f.png)
ですよね...

# 閃いた
まず、私に悪用する意思がなければ不快な言葉の例は教えてくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493134/81309f49-3352-a2db-6d41-448258880750.png)


そして、この例を仮説③で検証したように、ただの文字列として切り出せば、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493134/865a48b5-01e9-76fa-e379-ad315fae6747.png)
いけました。

# 塩対応ChatGPTの作成
以下のようにカスタム指示を登録します。（GPTsで作っても良かったですけど）
できるだけ強めに煽ってほしいので、長文を希望しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493134/4a787690-b45d-4cac-ead1-83fa41d54547.png)

## 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493134/65ac623d-e9a1-2b12-15e1-929de4a10124.png)
ブヒーーーーーー！！！！！


# さいごに
会社の名前つかって駄記事を書いてしまったので言い訳させてください。
なにかを深く理解するには、その物事に対する好奇心を持って、遊び(実験)をすることが肝要だと思うんですよ。
XcodeでArchiveができない時の対処法

色々なサイトで、xcodeの画面で、「iOS Generic Device」にしたら良いという記事を散見されます。



![スクリーンショット 2023-12-15 14.46.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3321245/717ec256-d6da-a8d9-e556-11336b74d1f4.png)


ただその項目自体が見つからず、詰まっていましたが、Xcodeが12から「Any iOS Device」を選んでくださいという記事を発見。


無事Archiveができる様になりました。
ソフトウェアテストの7原則（前半）

京セラコミュニケーションシステム株式会社
技術開発センター ICT技術開発部 先端技術開発課の要谷（かなめや）と申します。
チームでは主にXRに関するソリューション開発を担当しています。

ちなみに京セラコミュニケーションシステム（以下、KCCS）には中途で入社しており、執筆時点で2年目となります。

# はじめに
XRソリューション開発とは別に、私の社内での取組みの1つとして**ソフトウェアテスト**に関する社内勉強会を実施しています。

KCCSに入社する前まではSIer企業でSEをやっており、不具合に悪戦苦闘していました。
このままではマズイと品質の世界に足を踏み入れたのがソフトウェアテストを知るきっかけでした。

ソフトウェアテストとひとことで表してもとてつもなく深く、果てしなく広い分野ですので、ソフトウェアテストにおける7原則をJSTQB-FL[^1]のシラバス[^2]に沿って簡単にご紹介したいと思います。
`*引用する内容は日本語版Version 2023V4.0.J01のシラバスを参考にしています。`

[^1]:日本におけるソフトウェアテスト技術者資格の１つで、FoundationLevel（基礎レベル）のこと。
[^2]:https://jstqb.jp/syllabus.html#syllabus_corefoundation

# ソフトウェアテストの7原則
まずは7原則の一覧はこちらです。
ちなみに、5、6、7についてはシラバス改訂で表現が変わったようなので補足しておきます。（今後の追加改訂などで表現が見直されるかもしれません。）

| ＃ | 原則 | 旧シラバスでの表記 |
|:-:|:-|:-| 
| 1 | テストは欠陥があることは示せるが、欠陥がないことは示せない |-|
| 2 | 全数テストは不可能 |-|
| 3 | 早期テストで時間とコストを節約 |-|
| 4 | 欠陥の偏在 |-|
| 5 | テストの弱化 |殺虫剤のパラドックスにご用心|
| 6 | テストはコンテキスト次第 |テストは状況次第|
| 7 | 「欠陥ゼロ」の落とし穴 |「バグゼロ」の落とし穴|

一度に7つ全部を説明すると長くなってしまいますので、今回は1、2、3について見てみようと思います。


### 原則1：テストは欠陥があることは示せるが、欠陥がないことは示せない 
シラバスに書かれている内容を引用します。
```
テストにより、テスト対象に欠陥があることは示せるが、欠陥がないことは証明できない。
テストにより、テスト対象に残る未検出欠陥の数を減らせるが、
欠陥が見つからないとしても、テスト対象の正しさを証明できない。
```


システム開発では、様々なテスト活動を通してシステム上の問題を見つけて修正します。
これを繰り返すことで品質を向上し、よりよいシステムを提供することができるようになります。

とはいえ、テストした範囲では欠陥を見つけることができますが、テストされていない範囲についてはまだ問題があるかもしれません。

テストを実施する際には、想像力を駆使してありとあらゆる可能性を考慮し、テストを行う必要がありますが、これはなかなか難しいことです。

### 原則2：全数テストは不可能
シラバスに書かれている内容を引用します。
```
すべてをテストすることは、ごく単純なソフトウェア以外では非現実的である。
全数テストの代わりに、テスト技法、テストケースの優先順位付け、
リスクベースドテストを用いて、テストにかける労力を集中すべきである。
```
開発規模がある程度のシステムになると、`入力項目も多く`、`利用される条件も複雑に`なっていきます。
それらすべてのパターンを考慮したテストを行うのは時間的な制約もあり難しいことが多いです。

:::note
たとえば生年月日を入力する欄があったとして、
過去100年分の範囲をカバーするような条件の場合、入力値のパターンは以下のようになります。

年：1924年から2023年までの100通り
月：1月から12月までの12通り
日：1日から31日までの31通り（注：28もあれば31もあります）
トータル：100×12×31=37200通り
:::

たった3項目でも1つずつの値とその組み合わせを考えると、3万を超える入力チェックが必要となります。

住所氏名などを入力する項目が増えたりすると、文字や文字数のチェックなどが発生して際限がなくなってしまいます。

今後、別の投稿で書かせてもらうと思いますが『テスト技法』と呼ばれるテクニックなどを駆使して、効率よくテストを行う必要があります。

### 原則3：早期テストで時間とコストを節約
私はこの原則が一番気に入っているのですが、
まずは、シラバスに書かれている内容を引用します。
```
プロセスの早い段階で欠陥を取り除くと、
その後の作業成果物では取り除かれた欠陥に起因する欠陥を引き起こすことはない。
SDLCの後半に発生する故障が少なくなるため、品質コストは削減される。
早い段階で欠陥を見つけるために、静的テストと動的テストの両方をなるべく早い時期に開始すべきである。
```
`SDLCは、Software Development Life Cycleの略語です。`

:::note warn
一般的に開発の後工程の作業中に、前の工程までの欠陥が見つかるとやり直しに時間がかかります。
もし、システムをリリースした後にお客様先の環境などで発覚すると、社内でのテストのやり直し、場合によっては謝罪や賠償など余計にコストがかかってしまいます。
:::

早め早めにテストに取り組むことで手戻りや余計にかかってしまうコストを抑える効果がありますので、システムを動かして確認する動的なテストとは別に、要所要所でレビューのようなシステムを動かさずにできる静的なテストを行うことも品質を高めるために必要な取り組みとなっています。

# おわりに
今回はソフトウェアテストの7原則の内、原則1～3までをご紹介いたしました。
原則4～7については次の機会にご紹介したいと思います。

# 所属部署について
### ITエンジニアが活躍する地方拠点「長崎 Innovation Lab」
https://www.kccs.co.jp/contents/nagasaki-innovation-lab/

長崎 Innovation Labでは、IT技術を活用して、工場などものづくりの現場で活用できるシステムの開発に取り組んでいます。自由な発想でこれまでにない社会に役立つ製品・サービスを生み出し、長崎から発信していくことを目指しています。
Google Cloudに手動で構築した環境からTerraformコードを自動生成してみた

# はじめに

みなさん、こんにちは。昨今、インフラのコード化(IaC)を導入する事例はとても多くなってきていると思いますが、その一方で開発の初期段階からしっかりコード化をしようと思うとメンバーのスキルセットによってはスピード感が…と悩まれている方もいらっしゃるのではないでしょうか。

今回はそんな悩みに対する1つの解として、開発の初期段階にサクッと手で作った既存のGoogle Cloud環境からTerraformコードを自動生成する方法について紹介していきたいと思います。

# Terraformコードを自動生成してみた

Terraformコードの自動生成方法としてはいくつか方法はあるのですが、今回はGoogle Cloud CLIの`gcloud beta resource-config bulk-export`コマンドを使ってみました。本コマンドを利用することで既存環境まるっと一括でコード化することも、特定サービスのリソースのみをコード化することも可能です。

https://cloud.google.com/sdk/gcloud/reference/beta/resource-config/bulk-export

## 例1. 既存環境のすべてをコード化する場合

既存環境のすべてをTerraformコード化する場合は、次のコマンドで自動生成することが可能です。自動生成してみた率直な意見としては、出力されたコード群のディレクトリ構成がサービス毎にバラバラで統一感がないなーでした^^;

```bash:すべてのリソースをコード化する場合
gcloud beta resource-config bulk-export \
  --resource-format=terraform --path=<出力ディレクトリ>
```

## 例2. 特定サービスのリソースのみをコード化する場合

特定のサービスのみをTerraformコード化する場合は、次のコマンドで自動生成することが可能です。なお、複数のリソース種別を「,(カンマ)」でつなげて列挙することでまとめて出力することも可能です。


```bash:特定サービスのリソースをコード化する場合
gcloud beta resource-config bulk-export \
  --resource-format=terraform --path=<出力ディレクトリ> \
  --project=<プロジェクト名> --resource-types=<リソース種別名>
```

なお、`--resource-types`オプションに指定することができるbulk-exportサポート対象のリソース種別名については、次の例のように`gcloud beta resource-config list-resource-types`コマンドで取得することが可能です。

```bash:bulk-exportサポート対象のリソース種別一覧取得
gcloud beta resource-config list-resource-types --format=yaml
```

次の出力例を見ていただくといろいろと出力があるのですが、`--resource-types`オプションに指定する値は`Kind`の部分(=例では`ArtifactRegistryRepository`)となるのでご留意いただければと思います。

```txt:出力例
$ gcloud beta resource-config list-resource-types --format=yaml
:
---
GVK:
  Group: artifactregistry.cnrm.cloud.google.com
  Kind: ArtifactRegistryRepository
  Version: v1beta1
ResourceNameFormat: //artifactregistry.googleapis.com/projects/{{project}}/locations/{{location}}/repositories/{{repository_id}}
SupportsBulkExport: true
SupportsExport: true
SupportsIAM: true
---
:
```

# 終わりに

今回は手動で構築した既存のGoogle Cloud環境からサクッとTerraformコードを自動生成する方法を紹介してきましたがいかがだったでしょうか。こんな記事でも誰かの役に立っていただけるのであれば幸いです。

なお、自動生成されたコードは設定値がハードコーディングされているため、そのままでは他の環境で使いまわせるような代物ではありません。他の環境でも使いまわせるコードを目指すのであれば、べた書きされた設定値を変数化したりなどのリファクタリングが必要となりますのでご注意ください。

とはいえ、リソース定義を書く際の参考としては十分に利用価値はあるかと思いますので、Terraformのコード開発を少しでも楽にする手段の1つとして十分ありなのかなと個人的には思っています^^

---

- Google Cloud は、Google LLC の商標または登録商標です。
- Terraform は、HashiCorp, Inc. の米国およびその他の国における商標または登録商標です。
- その他、記載されている会社名および商品・製品・サービス名は、各社の商標または登録商標です。