OmniAICreator/Qiita-1.07M huggingface dataset:
要素技術情報について伝えたい

# 要素技術情報について伝えたい

これまで国交DPFはなに？ということや、何ができるか、ということをご紹介してきました。ここで少し趣向を変えまして、国交DPFの要素技術情報についてお伝えさせてください。

この記事は[国交DPFアドベントカレンダー2023](https://qiita.com/advent-calendar/2023/mlit-dpf)に参加しています。本日は12日目です。

さて、要素技術情報をご覧になったことはありますか？[国交DPF](https://www.mlit-data.jp/)のトップページからスクロールしてスクロールして・・・

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629590/c42e2830-90e9-4965-0a91-ce04fc001e23.png" width="500px">

<br>

一番下にそれはあります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629590/dd596223-d1b2-7e45-d75c-56db9308f0fc.png" width="500px">

<br>

[このページ](https://www.mlit-data.jp/#/InfoPage)では、国交DPFでのデータの利活用の促進に向けて研究開発されている要素技術が紹介されています。2023年12月時点で紹介されている技術は2つ。

- 2次元CAD図面から3次元モデルを自動作成する技術
- 電子成果品のメタデータを自動作成する技術

では早速見てみましょう！

## 2次元CAD図面から3次元モデルを自動作成する技術
これまでの公共事業では、たくさんの2次元のCAD図面が作成されてきました。例えば、研究開発で対象とした1つの橋梁の工事では、約200点の2次元図面ファイルが作成されています。

最近では、3次元モデルを活用することで、立体的に分かりやすくなり関係者間での認識共有もスムーズになることが期待されています。ただ、3次元モデルの作成には作業時間が長いことが課題でした。

そこで、2次元の図面から3次元モデルを短時間で簡単に自動作成できるようにしよう！というのがこの技術です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629590/f091195f-f61c-640e-1e06-2bcaab88f7b1.png" width="500px">
<br>

この技術を使って3次元モデルに変換された、橋梁2種類とトンネル1種類のデータが国交DPFに登録されています。試しに鋼橋（鈑桁橋）の「地図を表示する」ボタンを押すと・・・

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629590/013e5cd7-4488-6b34-fec3-bf2f107ae542.png" width="200px">

<br>

国交DPFの地図画面に飛びます。栃木県にある橋ですね。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629590/fad775cc-856d-e4d2-7692-3171bac68421.png" width="500px">

<br>

左側のリストでデータ名をクリックして「IFC」ボタンを押します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629590/db09e301-bc93-448b-a82b-6bddf5498d34.png" width="500px">

<br>

ここで「IFC」ボタンを押すとデータをダウンロードできますが、「プレビューボタン」を押すと・・・

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629590/243a2f05-03e6-4f92-f905-a034c7ab7473.png" width="500px">

<br>

IFCデータがプレビュー表示されました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629590/00cb9968-9f01-6304-9ded-a3ae41c1cf72.png" width="500px">

<br>

このデータが、2次元CAD図面から自動作成されたデータなんです。
[IFCビューアの操作](https://www.mlit-data.jp/#/Help?id=help_ifc)を参考に、ぐるぐると動かして確認することができました。

## 電子成果品のメタデータを自動作成する技術
もう1つが、メタデータの自動作成技術です。
メタデータとは、大量のファイルの検索に必要な情報をまとめたものです。メタデータを利用すると、公共事業の電子成果品に含まれる大量のファイルの中から目的のデータを迅速に検索できるようになりますが、膨大なファイルから情報を抽出してメタデータを作成のは大変な作業です。

そこで、メタデータを自動で簡単に作っちゃおう！というのがこの技術です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3629590/4760075f-c7e3-e072-8802-8553f8686cae.png" width="500px">

<br>

開発プログラムは自動処理を基本に設計されていて、図面や報告書などのファイルから必要な情報を抽出してメタデータを作ります。この技術を活用してメタデータを整備し、電子成果品などの検索で活用することで、業務の効率化に役立つことが期待されています。

## ということで
ちょっと目新しい、できたらいいなの技術が紹介されていました。これらの技術が身近になる日も、もうすぐかもしれません。

そして今後、この[要素技術ページ](https://data-platform-prototype.com/#/InfoPage)にさらに他の技術が紹介されていくかもしれませんね。

それではまた明日、ほっこりと暖かくしてお過ごしください。
アイコンに悩んだらSFSymbolsを使えばいいじゃない

### まえがき

ボタンなどにアイコンを使うとき、何を使えばいいのか非常に迷います。
毎回規約を確認しながらフリー素材をネットの海から拾ってきたり。
自分でiOS標準っぽいアイコンを作ったりしたり。
そんなことをする前に、まずはSF Symbolsに使えそうなアイコンがないか探してみればいいじゃない。

### SF Symbolsとは

SF SymbolsはAppleが提供しているシンボルフォントです。
FontAwesomeみたいなもんです。
UIImageとして使えるのでアイコンを表示させたい様々な場面で活用できます。

### ダウンロード

Xcodeプロジェクトに特別ライブラリなどを導入せずともデフォルトで利用できます。
ただMacのSF Symbolアプリが提供されていますのでこちらをインストールすると
どんなシンボルがあるのか確認しやすくなるので入れておくといいでしょう。

https://developer.apple.com/jp/sf-symbols/

### 使い方

例えばシェアボタンのアイコンであればこんな感じ。
![square.and.arrow.up@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/911364/ab36c514-fac7-b8c5-d285-0a9ebf082471.png)

```
let icon = UIImage(systemName: "square.and.arrow.up")
```

色を変えたい場合はtintで変えられます。

```
let icon = UIImage(systemName: "square.and.arrow.up")?.tint(with: .red)
```

もしくはwithConfiguration引数にUIImage.SymbolConfigurationを渡したり。

```
let icon = UIImage(systemName: "square.and.arrow.up", withConfiguration: UIImage.SymbolConfiguration(paletteColors: [.red])
```

大きさもUIImage.SymbolConfigurationで設定できます。

```
let icon = UIImage(systemName: "square.and.arrow.up", withConfiguration: UIImage.SymbolConfiguration(font: .systemFont(ofSize: 50)))
```

もしくはUIImageにした後、シンボルのアス比を考慮してリサイズ処理を作っても良いでしょう。

### あとがき

アプリ開発はそれなりにやっていましたが、つい最近までSF Symbolsの存在を知りませんでした。
使ってみるとかなり便利で、特殊なものでなければ基本これ使えばいいじゃんって感じで笑いが止まりません。
ただしシンボルの中には特定のサービスを示す時のみ使えるといった表記のものもあります。
例えばiCloudの雲マークのシンボルとかです。
App Storeにリリースするアプリの場合、使ったシンボルが用途に適しているのか気にする必要はありそうです。
ツール作成のプロセスを見直した話

## 1.はじめに
こんにちは！
もうQA歴3年ほどになる新米とは言えなくなってきたテスターです。
今年はツール作成時のプロセスについて苦戦したことが多かったので、そちらの振り返りと改善点についてお話します

##### 自己紹介
学生時代はゲーム関連の専門学校に入学。
2021年にQAの仕事をはじめ、現在QA歴3年
QA業務を可能な限り自動化して、人間の手間を減らしたいと思っています。

#### 反省したきっかけ
去年までは悩む前に行動！止まる時間がもったいない！というスタンスで進めていましたが...

その結果とても痛い目を見ました...

具体的にどのような失敗だったのか。今後どうやってその事態を回避していくのかについて話していきたいと思います。


## 2.ツール作成時に苦戦したこと/反省点
以前の自分は資料などを準備し、仕様や要点などを確認してから、実装に移っていましたが...そのやり方で苦戦したことを書いていきます。

- 自分で資料や仕様などを確認してから実装すると、考慮が足りない部分などもあり、根本的な所が足りず、設計の部分から手直しが発生する場合も
**自動化を行う時は、対象施策に詳しい方に資料等を用意してもらった方が良い**
<br><br>

- 設計をざっくり考えてから、実装中に詳細を考えると、相手と自分の認識のズレが生じ、大幅な変更依頼が飛んでくる可能性がある
**途中で出てくる懸念点を都度調整していくのは効率が悪くなってしまうので、最初の設計時点で実装の仕方まで考えておき、最初のMTGで相手側に伝えられるようにしておくとよい**

## 3.手順の見直し/効果的だったこと

手順を見直してみました。
自動化を行う際には、事前準備が重要だということが分かりました。

#### 1.調査・分析
・仕様書の内容や、確認する範囲の分析を行います。
⇒自動化の調査範囲の確認です。ここで仕様書からどの情報を使うのか、どのマスタを参照するのかを決めます。
この段階で、テスト担当者に資料(ログインボーナスなら開始期間、日数、アイテム等が記載された仕様書と使用されているマスターデータ)を用意してもらいましょう。
そうすることで、相手の想定している確認範囲も確認でき、時間も節約できます。
#### 2.要件定義
・確認すべき内容などを決めます。また、自動化を実装する環境等を決めます。
⇒マスターデータと仕様書を比較するようなツールを作成するのであれば、比較情報を照合する機能や、マスターデータと仕様書の情報を比較する為に、表現がブレている部分を形成する機能等を決めます。
確認内容や実装環境が決まったら、エンジニアやテスト担当者にレビューしてもらいましょう。
要件定義の段階で、自分の認識で間違っている部分があればここで修正しましょう。　
#### 3.設計 
・要件を満たすように、使う関数やツールの作りなどを決めます。
⇒文言の形成をスプレッドシートで行うのであれば、REGEXEXTRACT関数を使う等...あらかじめ決めておくことで、最初と実装後の完成物の認識がブレないようになります。
設計が完了したら内容が問題ないか、エンジニアの方にレビューしてもらいましょう。
この時、何故この関数を使うのか等理由を説明できるようにしておきましょう。
#### 4.仕様+実装
・設計で決めた内容を元に実装していきます。
⇒細かな修正が出た場合は関数や数式を使って修正します。
#### 5.テスト 
・実装した内容が問題なく動作するか確認します。
⇒テストデータなどを使用して、動作のテストを行い、要件を満たしているか確認します。

## 5.まとめ
今回、自動化の工程を分けることによって、
相手との認識のすり合わせを行うタイミングを増やすことができました。

折角ツールを作っても相手の望んでいないものができるのは悲しすぎるので、同じ過ちは繰り返さないよう、心がけていきたいと思います。

また、何よりも独りよがりで実装していくと必ず障害が出てくるので、
色んな方に協力してもらって、より良い効率/品質を目指していきましょう！

来年も自動化作業に取り組む中で何度も躓くとは思いますが、トライ＆エラーで成長していきたいと思います！
Netskope環境下でのJetBrains IDE + github copilot

# 概要
JetBrains社製のIDEでgithub copilotを使用する際に
Netskopeを使っていると証明書エラーが発生したため、その対応をまとめました。

# 環境
Window 10 + phpStorm（及びintelliJ） + Netskope + github copilot

# 症状
GithubCopilotプラグインからGithubにログインしようとすると以下のエラーが表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244191/6ce0f875-fc7c-05d1-7e2d-8859933f3829.png)
または、ブラウザ側でログイン認証が成功したにも関わらず、その結果をIDE側で受け取れない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244191/cb1a3abe-0139-6a42-714a-0aaf99beb739.png)

# 原因
githubのAPIをコールする際に、Netskopeを経由することで、レスポンスの証明書が信頼できないものとなってしまったため、github copilotプラグインが証明書エラーによりログイン失敗となった。


# 切り分け
・VSCodeでは動作すること
・curlでapi.github.comが証明書エラーになること、--insecureで無視すれば動作すること
```
$ curl https://api.github.com/user
curl: (35) schannel: next InitializeSecurityContext failed: Unknown error (0x800
92012) - The revocation function was unable to check revocation for the certific
ate.

$ curl https://api.github.com/user --insecure
{
  "message": "Requires authentication",
  "documentation_url": "https://docs.github.com/rest/users/users#get-the-authent
icated-user"
}
```
・タスクマネージャからNetskopeのプロセスをkillすれば動作すること

# 対応
大きく分けて2通りのやり方があると思います。今回は後者の方法で対応しました。
## 1. NetSkopeの除外リストに追加する
以下にリストアップされているドメインを除外リストに追加すれば、同一ネットワークの全Netskopeユーザがこの問題から開放されるはずです。
今回は権限や影響範囲の都合で対応を見送りました。
https://docs.github.com/ja/copilot/troubleshooting-github-copilot/troubleshooting-firewall-settings-for-github-copilot#urls-to-add-to-an-allowlist

## 2. netskope経由でgithubに接続する証明書を信頼できるものとして追加する
何パターンかやり方がありますが、以下の手順で行いました。
個々のPC全てで個別に対応が必要になります。
```
１．ブラウザでgithub.comを開く
２．URL鍵マークから証明書を開いて、Details > ExportでSave as type: Base64-encoded ASCII, certificates chain(*.pem; *.crt)を選んで、ファイル名適当、拡張子pemで保存。
３．Windowsのsystem＞advanced system settings＞Environment variables...
でユーザ変数にNODE_EXTRA_CA_CERTSという名前で上のpemファイルのパスを保存する。
４．phpStorm再起動
```

# 効果がなかった対応
・phpStormのSettigs>Tools>Server CertificatesでAccept non-trusted certificates automaticallyをチェックする
・phpStormのSettigs>Tools>Server CertificatesでAccepted Certificatesに前述のpemファイルを追加

# 感想
せっかく使える様になったのに、この問題のために利用開始まで数日がかかってしまいました。

github copilotプラグインのソースは公開されていないと思いますので、
non-trusted certificatesであっても有効にするオプションを追加していただけるように要望出しておこうと思います。
googleads/googleads-php-lib でサンプルが動かなくて悩んでるあなたへ

https://developers.google.com/ad-manager/api/start?hl=ja#php

Googleのドキュメントを読んで簡単そうだと思ったら要注意。必ず罠があります。Googleのあくらつなライフハック。

ステップ２まではUIがアップデートされているので説明文と画面の乖離があって若干わかりづらいですが、まあ大丈夫。jsonファイルのダウンロードまでがんばってください。

次、ステップ３ではやらなければいけないことがヌケています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13435/1d1e3a4b-ff9e-9b31-0874-e7b9e41a9c8b.png)

「サービスアカウントユーザーを追加」

を押して、ユーザー追加をしてください。メールアドレスはさっきダウンロードしたサービスアカウントjsonのclient_emailをメールアドレスとして入力します。役割は「管理者」です。

```
$ composer require googleads/googleads-php-lib
```

composerでライブラリをインストールします。が、このとき

```
Installing dependencies from lock file (including require-dev) 
Package operations: 1 install, 0 updates, 0 removals
- Installing googleads/googleads-php-lib (10.1.0): Extracting archive
```
バージョンが10.1.0といった明らかに古い（github上では最新バージョンは63）場合、このままではこれに続くサンプルプログラムは動作しません。

```
error: [Error] Class "Google\AdsApi\Common\OAuth2TokenBuilder" not found
```

うむ。

composerで強制的に最新を入れろと指示をすると

```
Problem 1
- Root composer.json requires googleads/googleads-php-lib ^63.0 -> satisfiable by googleads/googleads-php-lib[63.0.0].
- googleads/googleads-php-lib 63.0.0 requires ext-soap * -> it is missing from your system. Install or enable PHP's soap extension.
```

soap！
こいつのせいか。というわけでインストールします。dockerなのでDockerfileに記述してbuildします。
参考：https://stackoverflow.com/questions/50121641/enable-soap-for-php-in-docker-container

```
docker-php-ext-install soap
```

libxml2-devも必要なので適宜加えてbuildしなおします。
終わったら、composerでライブラリをインストールしなおしましょう。ちゃんと最新版が入ります。
そしらた満を持してサンプルを動作させましょう。

```
[2023-**-**T16:37:08.951082+09:00] DFP_SOAP.INFO: networkCode=************ service=NetworkService method=getCurrentNetwork responseTime=599 requestId=************************* server=ads.google.com isFault=0 faultMessage=
Network with code ********** and display name '**********' was found.
```

動いた！
DFPはSOAPで動く。俺憶えたばい。
【Azure AI Document Intelligence】Custom classification modelsを使ってみる

# はじめに
今年の夏からブログを始めたのですが、Document Intelligenceのカスタムモデルの記事が人気です。
ブログでは、あげたPDFに対して自分で読み取ってほしい項目などを追加することができる「Custom extraction model」を試したのですが、今回は「Custom classification model」をちょっとだけ触ってみました。

Cusom extraction modelを試した記事はこちら

https://usomarutech.com/entry/2023/09/15/175212

# Custom classification modelsとは
ドキュメントがどのモデルの種類に分類されるかを識別できるものです。

例えば、以下の図のように「請求書モデル」「納品書モデル」「注文書モデル」と3つのカスタマイズ作成したモデルが存在しているとします。

ここで、この請求書というPDFはどのモデルに分類できるかを識別できるのがCustom classification modelsです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/f7fe8c3b-49e2-13e8-35e5-37a45b379d91.png)



今回は1つのドキュメントを含む1つのファイルを想定して試しています。

- https://learn.microsoft.com/ja-jp/azure/ai-services/document-intelligence/concept-custom-classifier?view=doc-intel-4.0.0

# やり方
Document Intelligenceリソースの作成方法は割愛させていただきます。

Document Intelligence Studioにアクセスします。

Custom classification modelsを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/f0b1ee6c-cf0c-e149-5d5f-8a529a1182c0.png)

Create a projectをクリックして新しいプロジェクトを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/14a6ebee-700e-3c81-ad72-7c00af78544c.png)

プロジェクトの名前をつけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/06d5fe5f-ea6d-285e-9477-dbfaa7fde4f2.png)

Document Intelligenceのリソースを指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/e1545dbc-b554-bf8a-467a-d41e24aea7f7.png)

Blobの場所を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/7ea346ba-c012-a673-5c4c-925d3903bb21.png)

確認画面が表示されるので、「Create project」を押します。

トレーニングに使うPDFをあげていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/f5c31198-9eb8-6d27-ff78-3bd4aa3269ef.png)

あげたPDFに対して分類タイプの名前をつけていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/7c1dd38f-c2c8-a0df-d977-52b06890b993.png)

PDFをクリックすると付与できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/30622b42-1ce1-61cd-4cca-f43f08973148.png)

同じ分類のPDFが5枚以上ないとTrainできないので足していきます。
同じファイルが5枚もなかったので、一部同じファイルをコピーして試しました。

分類が終了したので、Trainしていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/5ce430da-877e-38fa-1bea-d1f82629f838.png)


時間かかるのかなと思ったら一瞬でTrainが終わりました。

# 試す

テストしてみると、しっかり分類できていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/b3282975-536f-5f13-1922-1210d925a96c.png)

学習させてない形式の請求書をあげても、マイクロソフトサンプル請求書ではなく、寄せ集めで作った請求書ラベルの方をあげてくれました。

# おわりに
精度がとても高くて技術の進歩を感じます。
自分で簡単にカスタマイズしたモデルをトレーニングできるのがいいですね。

次回は以下のようなパターンはどうなるかを実験してみたいと思います。
> 複数のドキュメントを含む 1 つのファイル。 たとえば、ローン申請フォーム、給与明細、銀行明細書を含むローン申請パッケージなどです。
OpenAIのDALLE2を用いて透明に塗りつぶした領域を画像生成でインペイントすーる（Python）

# はじめに
[がちもとさんアドベントカレンダー](https://qiita.com/advent-calendar/2023/gachimoto3)13日目の記事です。
今日は、DALLE2を用いて透明に塗りつぶした領域を画像生成でインペイントしていきます。

# 開発環境
- Windows 11 PC
- Python 3.11

# 導入
1．ライブラリのインストール
pip install openai
pip install requests

2．OpenAIのAPIキーを取得

https://platform.openai.com/api-keys

3．元画像と透明に塗りつぶした画像を用意します

4．プログラムを作成

~~~image_edit.py
from openai import OpenAI
import requests

client = OpenAI(api_key="<INSERT-YOUR-API-KEY>")

response = client.images.edit(
  model="dall-e-2",
  image=open("image_edit_original.png", "rb"),
  mask=open("image_edit_mask.png", "rb"),
  prompt="A sunlit indoor lounge area with a pool containing a flamingo",
  n=1,
  size="1024x1024"
)
image_url = response.data[0].url
print(image_url)

url_parts = image_url.split('?')
file_name = url_parts[0].split('/')[-1]

response = requests.get(image_url)
if response.status_code == 200:
    with open(file_name, 'wb') as file:
        file.write(response.content)
~~~

<details><summary>コード解説</summary><div>

1．APIキーの設定：まず、OpenAIライブラリをインポートし、OpenAIクライアントをAPIキーで初期化します。実際のAPIキーを"<INSERT-YOUR-API-KEY>"の部分に入力する必要があります。

2．画像編集のリクエスト：client.images.editメソッドを使用して、画像の編集をリクエストします。この際、dall-e-2モデルを指定し、編集する元の画像(image_edit_original.png)と編集する部分のマスク(image_edit_mask.png)をアップロードします。また、編集の指示として「日当たりの良い室内のラウンジエリアにフラミンゴがいるプール」というプロンプトを使用し、画像サイズは1024x1024に設定しています。

3．画像URLの取得とダウンロード：リクエストのレスポンスから画像のURLを取得し、そのURLを使用して画像をダウンロードします。URLからファイル名を抽出し、requestsライブラリを使用して画像を取得し、ローカルに保存します。
</div></details>

# 実験結果

|IMAGE|MASK|OUTPUT|
|:--|:--|:--|
|![image_edit_original.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/a6017ee4-0ef1-5742-cde6-61155254142d.png)|![image_edit_mask.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/583655a2-3214-92f0-863b-cf4ee6777d32.png)|![img-7yMuJchkFsBiKb54RVp3xhaL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/c7aba221-180c-ea4c-0c21-647b846c8581.png)|
|![woman-2003647_1280.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/84bed3f8-7aa5-80a3-65da-72d31bf9cf57.png)|![woman-2003647_1280_mask.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/92290b74-710e-6855-302b-9ad0bf7c472a.png)|![img-9KHFlwBefamrijeXmAjUDhNJ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/579b1c6f-f581-128f-db67-fe2a0bed45cb.png)|

女性の画像は「黒いスーツを着ています」というプロンプトでスーツに着せ替えました。
お疲れさまでした。
Null合体演算子がSafariでエラーだった

### Safariでエラー
ViteでビルドしたWebアプリが検証機でエラーになった。
検証機は古めのiPad。動作が非常にもっさりしているが、倹約を良しとするこの企業で検証用デバイスの刷新など最も優先順位が低い。結果、なかなか新しくならない。

### エラーの原因は古いSafariが「Null合体演算子」に対応していないことだった。
古いiPadやiPhoneはiOS12までしか上がらないものがあるらしい。
検証機がまさしくそれだった。

### ほとんどのiOSでは問題とならない。

![スクリーンショット 2023-12-11 16.27.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3587300/6da636a0-af93-82f3-b6d0-d83983aaf944.png)
上記の通り、Safariが14以降であれば対応している。
14未満のシェアは1％を切っているので、要件によっては対応する必要がないかもしれない。

### Null合体演算子

Null合体演算子は、左辺が null または undefined の場合に右の値を返し、それ以外の場合に左の値を返す。

```js
const bar = 55 ?? 125;
console.log(bar); // 55
```

??だからググっても出てこない。
こういうのを**ググラビリティが悪い**と言うらしい。

オプショナルチェイニング演算子も、
```
?.
```
なので、ググラビリティが非常に悪い。


## Viteでの解決策
このようなレガシーブラウザに対応すべきかどうかは要検討だけど、もしViteで対応するのならばプラグインを追加してレガシー用のコンパイルにする。

```js
import legacy from '@vitejs/plugin-legacy'

export default defineConfig({
  plugins: [
    legacy({
      targets: ['defaults', 'not IE 11'],
    }),
  ]
});
```

検証機を新しくしてほしい。。
初転職をしてみた話(業務で開発経験あり)

こんにちは。
文系出身のエンジニアです。
今回は、初めて転職したことについて語っていこうと思います。

#### そもそもなぜ転職をしようと思ったのか？
面接で答えるような転職理由になってしまいますが、
主に2つあります。
1つ目は、「家族の病気とお金」です。
父が、重病を患ってしまい、休職することになりました。
そのため、給料が減ってしまい、減額せざるを得ない状況になってしまいました。。
私しか働いていないので、お金をもっと上げ、両親に少しでもお金をあげることができたらなと考えたためです。
ここが一番転職を決める大きな1つのきっかけになりました。
2つ目は、「開発ができないこと」です。
営業が私の反対を押し切り、開発外の現場に配属されたことです。
今年の4月から今もヘルプデスクの業務に携わっています。
そこでの学びや気づきもあり、大変勉強にはなるのですがやはりどこかでもやもやする部分は正直ありました。
せっかく今まで開発をしたくて新卒で入社したのに、なんでこんなことになっているんだ？と疑問と悲しみでいっぱいになり、転職を決意しました。

#### 選考フロー
会社によってはまちまちですが、基本以下の順番で選考は進みます。
また、①、④についてはある会社もあれば、ない会社もあります。

①カジュアル面談(ない企業もある)
ここはフランクに人事の方と話ができる場です。
疑問点や不安点はカジュアル面談の時にざっくばらんに話すのが一番です。
もちろん選考には影響しないので、聞きにくい質問でも答えてくれるかと思います。

②書類選考
履歴書と職務経歴書を提出します。
書類選考で合格した場合、次の選考の時に人事の方が履歴書と職務経歴書を見ながら面接するので、今までやってきた案件等詳しく記載するとよいです。

③一次面接(人事の方or役職の方)
1on1が多いです。
自分がやってきたこと等をお話しします。
何について聞かれたかの詳細は以下まとめて記載するので、そちらをご覧ください。

④二次面接(役職の方)(ない企業もある)
企業と自身がマッチしているかを見分ける指標になります。

⑤内定
内定通知書と契約書をいただけます。

#### おらの実績
私の実績は以下の通りです。
| 書類選考 | 一次面接 | 内定 |
|:-----------|:-----------|:-----------|
| 15社       | 6社        | 2社         |

結果、内定を2社もらえたことに
やったああという気持ちでいっぱいでした笑
仕事をしながら転職活動していました。
奇跡的に毎日定時で帰宅できていたので、
業務終了後、なんとか平日時間を作って面接をしていました。
幸いオンライン面談が多かったため、時間に余裕があることが大きかったです。

#### 面接どんなことについて聞かれたのか？
主に以下の通りです。

・転職理由
これは確実に聞かれるので、準備しておいた方がいいです。
ネガティブな理由でもポジティブに言い換えたほうが吉です。

・志望理由
聞かれる会社と聞かれない会社がありますが、
準備はある程度しておいた方が良いです。
会社に入って何をしたいのか、何に魅力を惹かれたのか答えると良いです。

・(職務経歴書を見て)どのようなシステムを開発したのか。
開発工程がどこまでできるか、
主な開発言語は何をやっていたのか、聞かれます。
ひとりで開発出来なくても、
2人でペアプログラミングをやっていたことも話してみると良いです。
なぜ話した方がよいかというと、後々内定をもらったとき、
どの案件でどの工程をエンジニアに頼んだらよいかの指標になるからです。
私はこのことについて質問された時、
自信ないですが、ペアプログラミングで開発していましたと答えていました。

#### 転職エージェントについて
転職エージェントは3社契約しました。
そのうちの2社は濃い面接アドバイスを受け、
エージェントの紹介で面接に臨みました。
また、履歴書や職務経歴書の添削もしていただき、
おかげさまで書類選考通過した会社が多いです。
転職エージェントはあくまでサポート役なので、
全部を信じきらなくていいです。
内定が出たら、転職エージェントは内定が出た会社から報酬としてお金を貰うので、色々会社をすすめてきます。
その中で自分に合った選択をしていった方がよいかと思います。
会社で働くのは｢自分｣なので、
自分が会社に入ってどうなりたいか、
ここの会社だと自分が輝けるなと思った方向を
目指していくのがおすすめです。

#### 結果どうなったの？
前職の給与より比較的高めなSESで働くエンジニアの会社に
内定承諾をしました。
案件が比較的自由に決めれるところが決め手のポイントです。

#### 最後に
一応来年の4月から新しい現場にはなりますが、
やっていけるかどうかの不安が一番大きいです。
が、どないかなると思って頑張ります！
開発経験少しでもあるかつ、転職が初めての方は
是非参考にしてみてください。
最後まで読んでくださり、ありがとうございました。。
Saveできなくて、一度は絶望した

3時間ほど、絶望したので（chatGPTでも教えてくれんかった）、ここに記録として残しておく

# 条件
- XcodeでSwiftを使ってMacAppを作っていた。
- Document Base templeteを使っていた。
- 他のテンプレートで起こるかは検証していない　

# 現象
- アプリのSAVEができん

画像は、test プロジェクトのFileメニュー
![231211-0006.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6903/45b8d3ae-b426-740e-2c88-e92ce49fb0f4.jpeg)

# 解決
- window ControllerのIs Initial Controllerのチェックを外す
なぜか、ここにチェックが入っていた

![231211-0003.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6903/eeca6523-cbf2-4fb4-af50-506ba29792ea.jpeg)

外したら、元通り

![231211-0004.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6903/2016758e-2a60-7350-6fb9-1dab51ab90bd.jpeg)

ここにチェックが入っていてもSaveできる方法があるのかもしれんが、俺には解決できんかった。
このチェックボックスを永久に塞ぎたい。
自分に管理者権限がないSPOリストの列名取得方法

いつものフィルタークエリ利用時の障壁乗り越えモノです。

### 経緯・前提条件

<ul>
<li>所属するTeamsチームがグループフォーム（Forms）を持っています。</li>
<li>フローは、Formsで回答した人を所属するTeamsチームにメンバー追加をします。（Teamsチームの所有者権限を私が持っています）</li>
<li>また、別部署が管理しているSPOにあるメンバーリスト（SPOリスト）にアイテム追加を同時にしています。</li>
<li>既に別のTeamsチームでメンバーリストに登録されている人がおり、SPOリストにユニーク設定があり一意制約違反でフローの実行が失敗しました。</li>
<li>複数アイテムの取得アクションでフィルタークエリで表示列名を指定したところエラーになりました（＝表示名と内部名が異なる）</li>
</ul>

:::note alert
SPOリストの列を追加する際に日本語で列名を作成しないでください。フィルタークエリを利用する際にこのような面倒が増えます。
:::

:::note warn
日本語表記にしたい場合は英数字で列名を定義して保存（＝内部名になります）した後に、日本語名に変更して保存してください（＝表示名になります）。
:::

:::note info
フィルタークエリの操作でやはり手間が起こるのでリスト列名は内部名＝表示名で運用をしてくれたら嬉しいです。
:::

### 通常のリスト列の内部名確認方法

自分に管理者権限がないSPOのリストの列名を取得したい場合、

https://jpdynamicscrm.github.io/blog/powerautomate/Look-up-internal-column-names-in-SPO/

のような手順では参照できません（”リストの設定”のメニューが出てきません）



### 経緯・前提条件のような場面でのリスト内部列名取得方法

① SPOコネクタのHTTPの送信アクションを利用します。
![スクリーンショット 2023-12-11 143614.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1469675/ddf53910-b9ad-c8fb-df81-7886ebe932d3.png)

② ①のフローを実行すると、対象のSPOリストの既定の列を含んだすべての列（JSON）が返されます。「EntityPropertyName」から該当の列を探します。

|プロパティ（一部省略）|設定されていた値|補足・考察|
|---|---|---|
|CanBeDeleted|trueかfalse|消せる列か否か|
|EntityPropertyName|"OData_{InternalName}"|フィルタークエリで使いたいのはコレ！|
|Filterable|trueかfalse|フィルターできるか|
|Hidden|trueかfalse|表示列か否か|
|InternalName|内部名！||
|Required|trueかfalse|値が必須か|
|Scope|"/sites/｛サイト名｝/Lists/{リスト名}"||
|StaticName||InternalNameと同値？|
|TypeDisplayName|選択肢、計算値、参照　など|列の種類が設定されている|
|TypeShortDescription||TypeDisplayNameと同値|


今回は「ユーザーまたはグループ」のカスタム列の内部名を取得したかったのであたりをつけることができましたが、対象列が複数候補があったり元々列数が多いリストでは大変なのでもっと上手い取得方法があればフィードバックいただけるとありがたいです。

リスト列名を日本語で定義しない、を徹底していたらこんなことにはならないわけですが。。:triumph:

### 余談（想定外の動き。。）

このメンバーリストは以前サイトの管理者権限、リストの編集（投稿か？）権限を持っていたもので、現在はサイトの管理者権限ははく奪されています。

https://qiita.com/negimijin/items/a56cb3292adcdc2a3a92

こちらに記したとおり、「アイテムの更新アクションで権限がない旨のエラーになるなぁ」と思いながらリランしたところ、正常終了してしまいました（！）
アクションの接続時点の権限が有効なのか？という推察と、うまいこと動いてしまったのでまぁいいかと放置しています。。


### 付録

https://qiita.com/negimijin/items/b32f5cc4d9c51a48bc9e
JavaScript配列の扱い

## はじめに
JavaScriptの勉強を進めています。今は配列のところを勉強しており習ったことをまとめます。
他の言語の勉強も少ししたことがあるのですが、JavaScrptの配列って便利ですね！
自分用のまとめなので間違いなどあるかもしれないのでご了承お願いします

## 　配列の定義
```js 
const　scores　 = [10, 20, 30, 40];
```
今回は配列名をscoresとして記事を書いていきます。[]を使って定義します。中身は「,」で区切ります。

上記では横並びに記述していますが、以下のように縦並びで記述することも可能です。
この記述の場合最後の要素の後に「,」を付けることが可能です(多分)
こっちの記述の方が後から要素を追加する時やりやすいですよね。
```js
const scores =[
    10,
    20,
    30,
    ];
```


## 配列の要素の数を取得する
```js
const score_len = scores.length;
```
配列の要素の数が取得できます。for文にも組み込めるので便利です。
便利ですがfor文として扱うなら以下のように記述します。


## 配列に値を挿入
```js
stores.push(50);
```
配列に対しpush関数を使用することで配列の最後に値の挿入を行えます。


## 配列の値を削除
```js
stores.pop();
```
配列に対しpop関数を使用することで配列の最後の値を削除することができます。


## forEach()を使う
forEach()を使うと配列の要素を1つずつ渡すことができます。forEachメソッドですね。
```js
scores.forEach((score)=>{
    console.log(score);
    });
```
2番目の引数はインデックス番号として扱えます。
```js
scores.forEach((score, index)=>{
    console.log('${index}:${score}');
    });
```


## お礼
お二方から誤字脱字のご指摘をいただきました。
JavaScriptのコードを載せるときの記述方法など詳しく知らず勉強になりました。
また、記事を投稿する前に確認することの大切さが学べました。

ご指摘していただいたお二方、ありがとうございました。
JSConfJP2023 初めてのLT登壇感想と振り返り

この記事はカオナビ AdventCalendar2023(シリーズ1) 14日目です🎉

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

## はじめに
カオナビでフロントエンドエンジニアとして働いている石塚といいます。
22年に新卒でカオナビに入社し、現在２年目のエンジニアです。

今回はJSConfJP2023でスポンサーセッションのLT登壇した際の感想と振り返りを書いていきたいと思います！

初めての技術カンファレンス参加と登壇ということでワクワクと不安でいっぱいでしたが楽しむことができました！

JSConfJPの詳細はこちらになります⇩

https://jsconf.jp

## なぜ登壇しようと思ったか
　自分は人前で話すことがそんなに得意ではないのですが、外部で登壇すること自体をやったことがなかったのでこれはいい成長の機会だ！と思い、登壇してみようと思いました。

## 登壇準備で苦労したこと
### １.発表テーマがなかなか決まらなかった
登壇しようと思ったけれども、何をテーマにして話せば良いんや？と決めるのが大変でした。
ですが、先輩社員の方々に相談に乗っていただき、自分が新卒の時からやってきた取り組みや後悔したことをテーマにして発表資料を作っていくことができました。

### 2.LT(5分)の時間が意外に短くて発表資料をまとめるのが大変だった
発表時間が5分ということもあり、自分が伝えたいことを整理して資料を作っていかなければ時間を超えてしまうので、大変でした。

##  登壇してみて
### 意外に緊張せずにできた
事前に社内でフィードバックをもらったり、社内勉強会で発表したことによって、自信を持って発表することができたと思いました。

### 柔軟に対応できた
直前の二社が急遽発表がスキップになったが、対応することができました。

### 発表に対して前向きになれた
今回登壇したことによって、自分の中での発表へのハードルは下げることができたかなと思います。
他の方々の発表を聞く中で、自分ももっとうまく話せるようになりたいと思いました！

##  反省点
### 発表時間を少し超えてしまった…
話すことに集中し過ぎてしまって、時間を確認する余裕がなかったので、次からは時間を意識して発表していきたいと思いました！

##  さいごに
初めての技術カンファレンス参加と登壇でしたが、行くことができてよかったです！
他の人の発表を聞くことで、自分にとっていい刺激になりましたし、自分自身も登壇することで、自分がやってきたことを発信することの楽しさを知ることができたと思います！

これからも登壇する機会があればまたチャレンジしてみたいと思います！！！

それでは、次回15日目の記事もお楽しみください！！

https://corp.kaonavi.jp/recruit/recruitment/
エンジニアのオンボーディングを受けて

これは [GLOBIS Advent Calendar 2023](https://qiita.com/advent-calendar/2023/globis) 13日目の記事です

# はじめに
　こんにちは
　今年の8月にエンジニアとしてGLOPLAチームにジョインしましたnyagao(にゃがお)と言います
　私の経験上、これまで転職してきた中で、エンジニアのオンボーディングが非常に手厚かったことに感銘を受けました
そのため、今回のアドベントカレンダーでこの経験を共有したいと考え、以下に書かせていただきます
*✳︎オンボーディングとは新しい仲間の順応を促進する取り組みを指す言葉です。*
 

# LMSを使ったタスク管理
　これはGLOPLAチームのプロダクト説明も兼ねるのですがLMS(Learning Management System)を使ってやることリストが用意されていました
　上からstepを進めていけば自動的にオンボーディングが完了します
　残りのタスクも可視化できるし、完了すればチェックがつけられるので「あれやったっけ？」がなくなりました！
![スクリーンショット 2023-12-11 15.59.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117619/c1c876f8-a934-844b-35f2-d540977ddc89.png)



# LMSでの管理者・受講者体験
　GLOPLAはtoB向けのサービスのため、チームにジョインする前は全く触ったことがなくサービスイメージが湧いていませんでしたが、
　実際にLMSの管理者（人事担当者を想定）として様々なコンテンツを設定することによって、開発者としてユーザビリティの向上や、サービス理解にとても役に立ちました
　これまでエンジニアとしての役割に特化していたため、ユーザーとのしての立場が不明瞭な部分もありましたがオンボーディングに明確に組み込まれて体験することが新鮮で楽しかったです
　また、新しくジョインしたメンバーにありがちなデータ構成の理解もここで大幅に向上しました

# オンライン時代のコミュニケーション
　コロナに入りエンジニアは在宅ワークを経験してきたと思います
　そんな中で、メンバーとのコミュニケーションが難しいなと思う場面に何度も遭遇してきました
　常にオフィスにいてすぐ話しかけられる状況というのがオフラインの利点かと思いますが、GLOPLAではBiz・Dev関係なく基本的にGatherTownで過ごしているのでちょっとした質問や雑談へのハードルがほぼなくオフィスに出社しているのと変わりません
　今までバーチャルオフィスの類のサービスは使ったことがあったのですが、ここまで全員に浸透していてちゃんと機能している使い方は初めてだったので驚きました
　詳しくは[昨日のアドカレ](https://note.com/globis_engineers/n/nef1aa5856aee)を読んでください

![kaigi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117619/a843dffd-c29c-e458-fa98-9b202a13a11a.png)


# 気軽な1on1文化
　これはGLOPLAに限ったことではなくグロービス全体に言えることですが、1on1が盛んです
　1on1と聞くと上司or部下と週１でやる、忙しいとスキップしがちで、話題に困るアレといった印象があるかもしれませんが、グロービスの1on1は本当に自由でもちろん定期で入る1on1はあれど、他の社員誰とでも1on1をやっていいという文化があります
　私も数回やっているのですが、同じエンジニアメンバー然り、Biz側メンバー然り、同じ部門のメンバー、はたまた普段接点のない部門以外のメンバー誰であってもカレンダーのスケジュールが空いていれば勝手に設定して　1on1をしていいのです
　内容はまずは自己紹介から始まり、業務内容・業務相談・趣味・特技・住んでいる場所の話・育児相談・キャリア相談・コーチングと本当に多岐にわたります
　これを繰り返すことに自分のチーム内だけでなく他部門とのつながりもでき、横断的な課題に対するアプローチや、勉強会の開催スケジュール、社内部活、社内コミュニティ、ママ友作りなど会社で過ごす上で役立つノウハウを得ました
![bee.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117619/bddee887-92b2-ba75-cd89-093786d241b7.png)


# ペアプロ・モブプロを使ったオンボーディング
　GLOPLAの開発チームではVSCodeのLiveShare機能を使ったペアプロ・モブプロが盛んです
　昨日のアドベントカレンダーで共有があったGatherも使っているので、Gather内で画面共有をして喋りながらコードを書いています
###  進め方
  - ドライバー一人と複数のオペレーターで話しながら指示を出して貰って書いていく
  - 途中意図が伝わらないなどあるときはオベレーターがコードを書いて指示することも可能

### 利点
  - 細かい書き方から、レポジトリ特有の作法などもここで話して同意を得られるので無駄に悩む時間がなくて良い
  - 異なるバックグラウンドや視点を持つチームメンバーとの共同作業によって新しいアイディアやアプローチが生まれやすくなると実感
  - リアルタイムのフィードバックでレビュー時間を大幅に短縮
  - 経験が浅い者と熟練者でやるのが一般的なペアプロの進め方と思いますが、チームメンバーが空いていれば一緒にやっていたので全員のスキルやベストプラクティスの共有が進んだ
  - 単純に喋る機会が多いのでコミュニケーションが強化され、結果的にチームビルディングが自然に出来上がっていた
 - テストデータの用意や、テスト項目の洗い出しなども共同作業中に手が空いたメンバーが話を聞きながら作ってくれたりしていたので一人でやるよりは進捗が早かった 
  - ドライバー１人任せて後の人が見つめるという大プレッシャーモブプロを経験したことがあるのですがそんなことはなく手を動かして覚えていくというのが私にとっては大変合っていました
  - ここでレビュワーになりうる人が入っているとレビュー時間の大幅な短縮になります


# 最後に
　今回GLOPLAにジョインして久しぶりにオンボーディングを受けましたが新たな発見があって総じて楽しかったです
今後は自分が受け入れ側として新たなメンバーとオンボーディングをしてより良いものを築いていくことが楽しみです


 ## GLOBIS**で一緒に働く仲間を募集しています！**
GLOBISの開発組織では、一緒に働けるエンジニアを探しています！
まずは、カジュアル面談を通して、あなたに合う組織かどうか確かめてみませんか？

https://recruiting-tech-globis.wraptas.site/
javascript 動画上のマウス操作のみ検出させる

# はじめに
モーダルで動画を表示するサービスの開発をしています。
画面上のどこで操作しても再生している動画内に停止ボタンが表示されてしまう現象が発生していました。
これを動画上での操作のみを検出してその時だけ停止ボタンが表示されるように修正しました。
その対応方法を記載しております。

# 修正前のソース

document全体に対してEventListenerを追加しているため、どこでマウスを動かしても表示している動画コンテンツの再生ボタンに影響してしまいます。

```javascript

function fadeInOutControl() {

    document.addEventListener('mousemove', () => {
        // マウス操作で再生停止ボタンを表示・非表示処理など
    });
}
```

↓

# 修正後のソース

修正後のソースではvideoを表示しているコンテンツに対してのみEventListenerを追加しました。
それによって動画を表示しているコンテンツ上でのみmousemoveが反応するようになりました。


```javascript

function fadeInOutControl() {
    const video_content = document.getElementsByClassName('video-content')[0];

    // 動画上でのマウス操作でのみアイコンとコントロールバーを表示する
    video_content.addEventListener('mousemove', () => {
        // マウス操作で再生停止ボタンを表示・非表示処理など
    });
}
```

これで以上になります。
[Android] ベースラインプロファイルでパフォーマンスが改善される仕組み

ベースラインプロファイルでパフォーマンスが改善される仕組みについてまとめた。

導入については下記参照。

https://developer.android.com/topic/performance/baselineprofiles/create-baselineprofile?hl=ja

# Androidのコンパイルと実行

1. Androidのソースコードはビルドプロセスの中でコンパイルされ、中間言語であるDexに変換される。
2. DexはAABに格納されPlayConsoleへアップロードされる。
3. PlayStoreはAABを元に各デバイスの構成に最適化したapkファイルを生成し配信する。
4. デバイス上ではapkファイルに含まれたDexのコードをアプリ実行時に機械語へコンパイルして処理を行う。

# ベースラインプロファイル

ベースラインプロファイルとは、ソースコードの中で頻繁に実行されるクラスやメソッドのリストをまとめたもの。

Androidデバイスはベースラインプロファイルを元に頻繫に実行されるコードを事前(AOT)コンパイルすることで起動や実行時の処理を高速化することができる。（機械語へコンパイルするプロセスが短縮される）

事前コンパイルはアプリインストール時に行われる。

# ベースラインプロファイルの生成

ベースラインプロファイルの生成をするにはMacrobenchmarkライブラリを使用してユーザーが実際に行うクリックやスクロールなどの操作をコードで記述する。

```kotlin
// 参考: https://developer.android.com/topic/performance/baselineprofiles/overview?hl=ja#example
@OptIn(ExperimentalBaselineProfilesApi::class)
class BaselineProfileGenerator {
    @get:Rule
    val baselineProfileRule = BaselineProfileRule()

    @Test
    fun appStartupAndUserJourneys() {
        baselineProfileRule.collect(packageName = PACKAGE_NAME) {
            // App startup journey.
            startActivityAndWait()

            device.findObject(By.text("COMPOSE LAZYLIST")).clickAndWait(Until.newWindow(), 1_000)
            device.findObject(By.res("myLazyColumn")).also {
                it.fling(Direction.DOWN)
                it.fling(Direction.UP)
            }
            device.pressBack()
        }
    }

```

Macrobenchmarkによるベンチマークの結果をもとに、頻繫に利用されてパフォーマンスに影響を与えるクラスやメソッドを特定し、ベースラインプロファイルが作成される。

# クラウドプロファイル

GooglePlayが提供する機能で、ユーザーの実際のアプリ使用データに基づいてプロファイルを生成するというもの。ベースラインプロファイルと同様に、利用頻度の高いクラスやメソッドの情報が含まれており、それを元に事前コンパイルを行うことができる。

ベースラインプロファイルと違う点として、開発者はプロファイルを生成する必要はなく、GooglePlayが定期的にデータを更新し、ユーザーの操作に基づいて最適化プロファイルを更新してくれる。

クラウドプロファイルのデメリットとしては、リリースやアップデート直後はデータが集まっていないので事前コンパイルによるパフォーマンス改善が期待できない点がある。その間はベースラインプロファイルによる最適化によってパフォーマンス改善を行う必要がある。

# 全てのコードを事前(AOT)コンパイルしない理由

Android5~6ではアプリケーションのコードをインストール時にコンパイルする方式(AOT)だったが、現在では事前(AOT)コンパイルと実行時(JIT)コンパイルのハイブリッド方式になっている。

その理由としては、インストール時間の増加や、ストレージ、メモリ使用量の増加、実行時の最適化ができない問題などがあったよう。
Python×DAX(DynamoDB Accelerator):初心者向け簡単チュートリアル

## はじめに
AWS DynamoDBは、スケーラブルで柔軟性が高く、パフォーマンスに優れたNoSQLデータベースサービスです。DynamoDB Accelerator(DAX)は、DynamoDBをより高速に扱うことができるサービスです。

しかし、PythonとDAXの組み合わせに関する解説記事は少なく、ハードルが高いかもしれません。

よって本記事ではPythonを使ったDAXの基本的な利用方法をわかりやすく紹介します。

前回の解説記事であるPython×DynamoDBに内容が似ています。

https://qiita.com/sergicalsix/items/74ac10a50aeb2cbc2bdf

また「Python×AWSのDB」の解説記事は全3つを予定しており、最後はPython×Elasticache Redisを予定しています。

## 内容
### 事前準備
まずDynamoDBにアクセスするために、AWSのアカウントのアクセスキーとシークレットキーを環境変数に設定します。

```bash
$ export AWS_ACCESS_KEY_ID={アクセスキー}
$ export AWS_SECRET_ACCESS_KEY={シークレットキー}
```

### DAXとの接続
DAXを扱うために`amazon-dax-client`ライブラリをインストールします。

```bash
(仮想環境)% pip install amazon-dax-client
```
次にDAXとの接続をします。
DynamoDBのテーブル名とDAXのエンドポイントを準備しておきます。
ポートは基本`8111`番のポートが開放されていますが、暗号化している場合は`9111`番のポートが開放されています。

クラスターエンドポイントやポート番号はAWS CLIを用いて以下のように確認することができます。

```bash
% aws dax describe-clusters
```

DAXとの接続のためのプログラムは以下です。

```python 
from amazondax import AmazonDaxClient

dax_endpoint = "エンドポイント"
dax_port = 8111 #暗号化している場合は9111

# DAXクライアントの初期化
dax = AmazonDaxClient.resource(
    endpoint_url=f'daxs://{dax_endpoint}:{dax_port}',
)
table = dax.Table('テーブル名')
```

余談ですが、DynamoDBと同様、EC2からの作業だとVPCエンドポイントが設定されていない場合はインターネットゲートウェイを用いてDynamoDBに接続されるので注意が必要です。

本筋とは離れますが、DAXを扱うためには適切な権限とセキュリティーグループの設定が必要です。以下を参考にしてください。（公式ドキュメントでポート番号が`8111`となっている箇所は、暗号化している場合は`9111`となるので注意してください。）

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.access-control.html

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/DAX.concepts.cluster.html#DAX.concepts.security-groups

## データの書き込み&データの読み込み

https://qiita.com/sergicalsix/items/74ac10a50aeb2cbc2bdf

上記の記事とプログラムや注意事項は同様です。プログラムのみを記載しておきます。

```python 
###
# データの書き込み
###
from decimal import Decimal

def convert_floats_to_decimals(obj):
    """
    float->Decimalに変換する関数
    """
    if isinstance(obj, list):
        return [convert_floats_to_decimals(x) for x in obj]
    elif isinstance(obj, dict):
        return {k: convert_floats_to_decimals(v) for k, v in obj.items()}
    elif isinstance(obj, float):
        return Decimal(str(obj))
    else:
        return obj

data = {'Id':1, 'value': 3.5} #保存したいデータ
data = convert_floats_to_decimals(data) #float->Decimalに変換
table.put_item(Item=value) #DynamoDBへ書き込み

###
# データの読み込み
### 
def convert_decimals_to_floats(obj):
    """
    Decimal->floatに変換する関数
    """
    if isinstance(obj, list):
        return [convert_decimals_to_floats(x) for x in obj]
    elif isinstance(obj, dict):
        return {k: convert_decimals_to_floats(v) for k, v in obj.items()}
    elif isinstance(obj, Decimal):
        return float(obj)
    else:
        return obj

key ={'Id': '1'} #プライマリーキーはId
response = table.get_item(Key=key) #DynamoDBの読み込み
response = convert_decimals_to_floats(response) #Decimal->float変換
```

## おわりに
いかがだったでしょうか。
上記のようにDAXはDynamoDBと同様にPythonで簡単に扱うことができます！

参考になれば幸いです。

次回はElasticache RedisをPythonで使う方法について解説する予定です。
git pushを試みた際にエラーが出てしまう件の備忘録（GnuTLS recv error (-54): Error in the pull function）

昔々あるところに、いつも通り何気なく`github`で遊んでいたこ時期がありました。
`git push`時に以下のようなエラーが出て`push`が失敗します。
（昨日までは元気に動いていたのに、、どうして、、）

```
$ git push
GnuTLS recv error (-54): Error in the pull function
```

検索結果、以下をすると解決した記録があった
（networkエラー、ライブラリ破損、バッファ溢れ、、）

> https://root-forum.cern.ch/t/unable-to-access-https-github-com-vgvassilev-clad-git-gnutls-recv-error-54-error-in-the-pull-function/48574
> The error you posted is an internet connection error. The installation procedure tries to download some dependencies and fails.

> https://programmerah.com/solved-git-error-gnutls-recv-error-54-error-in-the-pull-function-35345/

```
sudo apt-get -y install build-essential nghttp2 libnghttp2-dev libssl-dev
```

> https://tagsqa.com/detail/13617

```
git config --global http.postBuffer 524288000  
git config --global https.postBuffer 524288000
```

解決しない、、さらに調べてみた、、`gnutls-bin`や`openssl`を再インストールしたら解決したという記録もあった、、
（沼の予感、、）

> https://stackoverflow.com/questions/38378914/how-to-fix-git-error-rpc-failed-curl-56-gnutls

```
apt install gnutls-bin
```

> https://stackoverflow.com/questions/38378914/how-to-fix-git-error-rpc-failed-curl-56-gnutls

```
sudo apt install openssl
```

解決しない、、さらに調べてみた、、ダメもとで色々と試す、、

> https://devopscube.com/gnutls-handshake-failed-aws-codecommit/

```
sudo apt-get install build-essential fakeroot dpkg-dev
```

ここまで試して、ふと`git push`したら解決した（`push`成功した）
最後のトライというよりは、前提となるネットワークエラーが解決した可能性もある、。
この辺りはトライ&エラーノウハウがあると今後同じエラーに直面した人の役に立つかもしれないので備忘録として残してみます。

# 参考

https://reject.tokyo/couldnt-work-push-pull/

https://programmerah.com/solved-git-error-gnutls-recv-error-54-error-in-the-pull-function-35345/

https://github.com/curl/curl/issues/1707


https://root-forum.cern.ch/t/unable-to-access-https-github-com-vgvassilev-clad-git-gnutls-recv-error-54-error-in-the-pull-function/48574

https://tagsqa.com/detail/13617
Vue3でこれからアッロードする画像ファイルのプレビューをリアクティブに表示するためのcomposableを作ってみる

# 導入
今回はVue3でこれからアッロードする画像ファイルのプレビューをリアクティブに表示するためのcomposableを作ってみるという話題です。

:::note info
※ 私が株式会社愛宕 Advent Calendar 2023に書く記事は主に社内向けに共有しておきたいけど勉強会をするまでもないちょっとしたTipsにしたいと思います。
:::

アップロード前にブラウザで画像ファイルの内容を一時的に表示したいとします。ローカルファイルは直接`<img>`タグで読み込めないので一旦`FileReader`で読み込んでからData URLに変換して`<img>`タグの`src`に書き込むことになります。

この一連の流れを1つのcomposableとして定義して再利用できるようにしてみましょう。


# 解決

ひとまず、`read`という関数を返すようにします。

```typescript:composables/useFileReader.ts
export const useFileReader = () => {
  const read = () => {} // 未実装
  return {
    read
  }
}
```

この関数は次のように使うことを想定しています。
（ファイルダイアログの扱いは本題とは無関係です。VueUseの[useFileDialog](https://vueuse.org/core/useFileDialog/#usefiledialog)を使って書いています。）

```vue:app.vue
<script setup lang="ts">
import { useFileDialog } from "@vueuse/core"
import { useFileReader } from "./composables/useFileReader"

const src = ref<string>()

const { open, onChange } = useFileDialog({
  accept: "image/*",
  multiple: false
})

const reader = useFileReader()

// ファイルダイアログでファイルが選択されたらファイルの中身を読み込む
onChange((files) => {
  if (files.length > 0) {
    reader.read(files[0])
    // ここで src.value = reader.read(files[0]) のようには書けない
    // FileReaderというのは同期的に読み込んだ内容を得られる仕組みではないので
    // 読み込み処理の呼び出しだけを書く
    // 読み込んだファイルの内容はどこから受け取ればいいだろう・・・
  }
})

</script>

<template>
  <div>
    <button type="button" @click="open">ファイル選択</button>
    <img v-if="src" :src="src" alt=""/>
    <div v-else>画像未選択</div>
  </div>
</template>
```

このままだと、`src`を更新する処理が含まれていません。`FileReader`を使ったファイル読み込みは`addEventListener`で追加できるイベントを使った処理で行います。`useFileReader()`の呼び出し時に`addEventListener`に渡すコールバックを指定しておきましょう。
ここではファイルが読み込まれたら`src`の値をその読み込んだ内容で更新することにします。

```diff_vue:app.vue の一部修正
- const reader = useFileReader()
+ const reader = useFileReader((result) => src.value = result)
```

`useFileReader.ts`側の呼び出し方も書き換えます。


```diff_typescript:composables/useFileReader.ts
- export const useFileReader = () => {
+ export const useFileReader = (onLoad: (result: string) => void) => {
  const read = () => {} // 未実装
  return {
    read
  }
}
```

次に`FileReader`を実際に使った実装を書いていきます。
気をつけないといけないのはイベントリスナーの解除を忘れずに書いておくことです。

```typescript:composables/useFileReader.ts
export const useFileReader = (onLoad: (result: string) => void) => {
  let reader: FileReader

  // onLoadはaddEventListenerに渡すためにもらってきた関数だが、
  // 念の為、読み込み結果がstringであることを確認してから呼び出すことにする
  const handleLoad = () => typeof reader.result === "string" && onLoad(reader.result)

  onMounted(() => {
    // マウントされたらreaderを作成してイベントリスナーを割り当てる
    reader = new FileReader
    reader.addEventListener("load", handleLoad)
  })

  onUnmounted(() => {
    // 忘れずにアンマウントでイベントリスナーを外しておかないとメモリリーク
    // こういうことを利用者が気にかけなくてもいいのがcomposableのいいところかもしれない
    reader?.removeEventListener("load", handleLoad)
  })

  // readAsDataURLを使えば読み込み結果をData URLに変換してくれる
  const read = (blob: Blob) => reader.readAsDataURL(blob)
  
  return {
    read
  }
}
```

# まとめ
今回はアッロードする画像ファイルのプレビューをリアクティブに表示するためのcomposableを作ってみました。
使い方は初めの`useFileReader`で読み込み完了後の動作を指定し、公開した`read`関数で指定されたファイルオブジェクトの中身を読み込むといったものでした。
あまり使い方が直感的ではないので、情報の渡し方を逆にして`useFileReader`でファイルオブジェクトを指定し、公開する関数は`onLoad`にして読み込み完了時の処理を後で書けるようにするのもいいかもしれません。
[AWS]ASG管理下のEC2の死活監視について

ASG管理下のEC2の死活監視についてのメモ書きです。


 
# 要件
- ASG管理下のEC2インスタンスがUnhealthyまたは停止（手動停止や終了を含む）になった際に、通知を受け取りたい

## 前提
- ECS on EC2を使用しており、これらのEC2インスタンスをASGで管理している
- ASG設定
    - desired count: 2
    - max count: 2
    - min count: 2
    - ロードバランシング: -
    - ヘルスチェック: 
        - タイプ: EC2
        - 猶予期間: 60
    - それ以外はデフォルト

# 試したこと


- 実施方法
    - EC2インスタンスの手動終了を実施し、ASGメトリクスの値の変化
を確認する
- 結果
    - 一回目の動作確認（GroupInServiceInstancesとGroupPendingInstancesメトリクスに変化あり）
    ![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/5ad81bc7-c259-72c2-571e-b32c36865979.png)
    ![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/a3921bdf-28dc-0cc3-494c-221ba10f43e6.png)
    - 二回目の動作確認（全てのGroupXXXInstancesメトリクスに変化なし）
    ![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/458b4d49-fd26-3ac9-8513-6c06d6114796.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/0547f42c-933d-64b8-20f8-c7facfa3122a.png)



# Auto Scaling グループメトリクスについて
ASGメトリクスは毎分発行される仕様です。
>Auto Scalingグループメトリクスを有効にすると、Amazon EC2 Auto Scaling は、ベストエフォートベースで毎分、CloudWatch にサンプルデータを送信します。CloudWatch でサービスの中断が発生するまれなケースでは、グループメトリクス履歴のギャップを埋めるためのデータのバックフィルは行われません。

https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/ec2-auto-scaling-metrics.html


GroupXXXInstancesメトリクスは１分間隔で記録されるため、その間にインスタンスの置き換え（古いインスタンスの終了と新しいインスタンスの起動）などが発生しても検知しない可能性があります。


# SNSを使ったアクティビティ通知
漏れなくEC2インスタンスの状態変化（今回はインスタンスの終了）を監視したい場合は、SNSを使ったアクティビティ通知が利用可能です。

https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/ec2-auto-scaling-sns-notifications.html

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/c20d08ed-3fdf-0de8-62cb-5f773115a0f0.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/ca6c46e7-3330-9c44-8210-c344f9bd0fcf.png)
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2954734/5bb66751-cd92-60d6-d420-a1e3374f7faf.png)




# 参考URL
- https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/ec2-auto-scaling-metrics.html
- https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/ec2-auto-scaling-metrics.html#as-group-metrics
- https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/ec2-auto-scaling-sns-notifications.html
obnizのパーツをリモート開発してみた



obnizのパーツライブラリにしたいパーツありますか？って募集をかけたら、
「PLAYBULB candle」を教えてもらいました。

https://x.com/youtoy/status/1722952457263923577?s=20

しかし、教えてもらったものの、デバイスの入手ができないので、@youtoyさんのもってるデバイスを遠隔で開発に使わせてもらいました　

https://x.com/9wick/status/1722953755082309953?s=20




## リモート開発

obnizはインターネット越しでも遠隔操作できるので、遠隔で開発させてもらうのにお願いしたのはこの項目です。

![SS20231210192319.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/9ad0d520-fc60-7a9a-404a-5391850b9f4a.png)


## 事前準備

日程調整して当日を迎えるまでの間に、できるだけMTG時間を短縮しようと、ある程度ベースを作っておきました。

PLAYBULB candleのドキュメント / SDK

- https://codelabs.developers.google.com/codelabs/candle-bluetooth#3
- https://github.com/danielsmith-eu/playbulb-live
- https://github.com/Phhere/Playbulb


上記ドキュメントを見つつ、実機がないので、妄想を膨らませながら下記の関数を実装していきます
- isDevice
- getDeviceNameWait
- setColorWait
- setEffectWait


例えば、peripheralが対象デバイスかどうかを判定するisDeviceはこんな感じ。
```typescript
  static _deviceAdvAnalyzerType = new BleAdvBinaryAnalyzer()
    .addTarget('flag', [0x02, 0x01, 0x06])
    .groupStart('manufacture')
    .addTarget('length', [3])
    .addTarget('type', [3])
    .addTarget('candle_service_uuid', [0x02, 0xff])
    .groupEnd();

  public static isDevice(peripheral: BleRemotePeripheral): boolean {

    const advData = PLAYBULB_candle._deviceAdvAnalyzerType.getAllData(
      peripheral.adv_data
    );

    return advData != null;
  }
```


isDevice以外の関数はすべて接続して行うので、接続チェックをしつつ、numberの配列を書き込むようにします
```typescript
  public setColorWait(r: number, g: number, b: number) {
    if (!this._peripheral.connected) {
      throw new Error(`Device is not connected`);
    }
    if (!this._candleColorCharacteristics) {
      throw new Error(`no characteristic found`);
    }
    const data = [0x00, r, g, b];
    return this._candleColorCharacteristics.writeWait(data, false);
  }
```


作成途中に PLAYBULB candleの仕様を踏まえたコードを出してくるGithubCopilotさん、流石です。
![SS20231210194532@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/a817a09b-8ec9-24aa-e5f2-130ff83f0529.png)



## リモート開発

さて、MTGを繋いでプログラムをデバッグします。

カメラを準備してもらってる姿
![SS20231210211811.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/911d4ae7-a338-9cdf-5d51-ea75e71128e2.png)



obnizIDを教えてもらって、遠隔でBLEのスキャンをすると、あっさり見つかりました。
接続も無事に成功。
１Stepずつエラーになる場所はないかな、と見ていきましたが、エラーは出るものの微修正の範囲で収まりました。


途中、Webカメラがちらつく！とか、ちょっとカメラ的に光がよくわからない！とかもありましたが、
事前準備したプログラムが8割はそのまま使えたので、微修正だけしてそのままスムーズにデバッグ完了。

なんと30分で終わりました笑

↓30分後に動いている姿。光が見にくいよねということで、デバイスを横向きにしてる
![SS20231210213219.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/b2f39906-9a99-3ecd-8645-b372bf97ad1b.gif)






## というわけで
@youtoy さんに協力してもらいながら遠隔でobnizの「PLAYBULB candle」のパーツ対応をしました！
（協力ありがとうございました）


コード全体像はまた１月ぐらいにgithubに上げる予定です。
OpenAIのDALLE2を用いて画像から画像を生成すーる（Python）

# はじめに
[がちもとさんアドベントカレンダー](https://qiita.com/advent-calendar/2023/gachimoto3)12日目の記事です。
今日は、DALLE2を用いて画像から画像を生成（image2image）をやっていきます。

# 開発環境
- Windows 11 PC
- Python 3.11

# 導入
1．ライブラリのインストール
pip install openai
pip install requests

2．openaiのAPIキーを取得

https://platform.openai.com/api-keys

3．プログラムを作成

~~~image_variation.py
from openai import OpenAI
client = OpenAI(api_key="<INSERT-YOUR-API-KEY>")

response = client.images.create_variation(
  image=open("profile.png", "rb"), # Uploaded image must be a PNG and less than 4 MB.
  n=1,
  size="1024x1024"
)

image_url = response.data[0].url
print(image_url)

url_parts = image_url.split('?')
file_name = url_parts[0].split('/')[-1]

response = requests.get(image_url)
if response.status_code == 200:
    with open(file_name, 'wb') as file:
        file.write(response.content)
~~~

<details><summary>コード解説</summary><div>

1．OpenAIのAPIを使用するためにクライアントを設定します。これにはAPIキーが必要です。

2．client.images.create_variation メソッドを使用して、アップロードされた画像に基づいて新しい画像を生成します。このメソッドには画像サイズ（ここでは1024x1024）と生成する画像の数（ここでは1）を指定します。

3．生成された画像のURLを取得し、URLからファイル名を抽出します。

4．requests.get を使用して画像のURLから画像データを取得し、正常に取得できた場合（ステータスコード200）、そのデータをファイルに書き込みます。これにより、画像がローカルにダウンロードされます。

</div></details>

# 実行結果

|INPUT|OUTPUT|
|:--|:--|
|![image_variation_original.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/80c86d78-03f8-05cf-cbc2-fb68852a4f9c.png)|![img-md4ezSgr9yxFL00JRHuvmRmN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/2712fd7f-862b-2d36-6b4f-2408dc7fbfa8.png)|
|![profile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/36d34e0a-14e4-dd86-c568-9da19be6f1b5.png)|![img-MAqcAIytxdS1Mz96Gp9E2S2k.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63863/65ef9b78-0a3c-0149-e15e-7e2b39f23ad3.png)|

やめろｗ

お疲れさまでした。
【映像】UE5を使用したプロジェクトで困ったこと


# 自己紹介
はじめまして、GlitzVisualsという小さなCG会社の代表の江口です。
元々はMVやCMのCG制作を行っておりましたが、ご縁がありゲーム業界入り。
ライティングアーティストとして何本かコンシューマゲームの開発に携わり、映像案件もやりたくなり2022年の4月に起業。
現在10数名の小規模なCG会社を経営しています。
会社の売上はゲーム関連のプロジェクトが7割、CMやMV、ドラマなどが3割で、2030年までに100名規模のデベロッパーになることを目標としています。
これでバズりました。

https://x.com/takuegg_/status/1639221408835465217?s=20

https://nlab.itmedia.co.jp/nl/articles/2305/23/news043.html


# はじめに
弊社で映像案件を行って来た中で、各社ごとにワークフローにばらつきがあって苦しむことが多かったのでその時々の後悔を雑に書いていきます。


## 1. バージョン管理ソフトアレルギー

バージョン管理（リビジョンコントロール）とは、複数人で同一のプロジェクトにアクセスし全員のローカルにあるプロジェクトデータを共通にすることです。
弊社ではSVN、Git、Perforceを使うことが多いです。
リビジョンコントロールについてはAlche代表の川さんがこちらに詳しく書いてくださっています。

https://blog.alche.studio/posts/5N8S3OwbZI6PR2d7WnXKyP/

ゲーム開発だとGitは非常に強力なツールですが"映像プロジェクト"においてのリビジョンコントロールは個人的にSVNかPerforceをおすすめします。
理由は色々あるのですが、Gitはエンジニア向けでアーティストには開発ワークフローを理解するのに少々難易度が高いからです。
コストが許してくれるのであればPerforceが非常に簡単で使いやすかったです。
とはいえなかなかな値段がするので弊社ではSVNを選ぶことが多いです。

とある映像案件のときに弊社含めた4社間でUEのプロジェクトを共有する事がありました。
日本の映像業界では、新しいソフトに対するスピードが比較的遅いです。
UEのMRQも2020年ころから出ているのにも関わらず浸透してきたのは最近です。
従来はプロジェクトデータをFTPでタイムスタンプをつけて毎日更新するという方法が一般的でした。
実際Mayaなどのプロジェクトはそのように管理されていると思います。
Mayaや連番、テクスチャやモデルなどのデータはFTP管理が楽で弊社も利用しています。FTP技術を攻撃しているわけではありません。

しかし、Ueのプロジェクトをそのように管理してしまうと、企業間でプロジェクト構造が独自化、MRQの設定もインポート手順もバラバラとなってしまう上に、データ量だけ肥大化していき毎度プロジェクトを開くときにシェーダーコンパイルが走ります。
ゲーム業界には当たり前のように浸透しているバージョン管理ですが、実際に上記のような地獄の苦しみを味わっている映像プロジェクトが未だに走っていると思います。
弊社はバージョン管理の重要性をうまくクライアントに伝えることができず、実際に上記の方法でプロジェクトを完走しましたが結果として工数が跳ね上がり、大赤字。


これでは全く生産性がなく、誰も幸せにならない案件だったので今後このようなことが無いよう、各社のProducer様にバージョンコントロールの重要性をアーティストサイドから強く説明する必要があると思いました。

実務上で困ったことはシーケンサー、レベルは程よく細分化し、チェックアウトの競合が起きないようにすること。サブシーケンサーはFX　CH　LIT　ANIMくらいあってもいいかもしれないです。


## 2. パフォーマンスの最適化

UE5は美しいグラフィックスを提供しますが、高度なグラフィックスはパフォーマンスに影響を与えることがあります。
映像案件だからといってすべてのライトをMoveableで置いた事を後悔した事が多かったです。
諸悪の根源はLumenでした。

https://docs.unrealengine.com/5.0/ja/lumen-global-illumination-and-reflections-in-unreal-engine/

LumenとはUE5から導入されたライトのシステムです。
簡単に説明すると、UE4ではライトビルドしないと得れなかった結果をリアルタイムに、しかも質を高く描写するで～という機能です。（かなりざっくりです、有識者の方々すみません）
実際触ってみた感想は「すげ～」って感じですが、実務上ではバグだらけでコンポジターの方々に迷惑をかけました。
また、負荷もProbeに焼きつけるより上がるのでGPUの負荷が高くなりがちでプロジェクトの序盤に
「この案件は映像なのでライトビルドなんかしなくてもレンダリングさえできればいいから」
なんて言っていたのを後悔しています。
ライトプローブってなんぞやという人向けの記事をヒストリア様が書いてくださっています。

https://historia.co.jp/archives/13517/

映像だからMRQでEXRが出てくればいい、だからパフォーマンスを気にせずライト置きまくるというのはナンセンスです。プリレンダー的な考えはそうなのですが、なんのためにリアルタイムエンジンを採用しているのかをもう一度考えながらプロジェクトを構成するべきでした。




## 3. リアルタイムレンダリングの活用

UE5はリアルタイムレンダリングに優れています。これを利用することでZoomなどのオンラインMTGで直接監督にレンダリングビューを見ていただけます。
修正もその場でできてしまうので非常に便利です。
MRQのレンダリングプリセットは必ずチーム全体で共有しましょう。
各々の設定で始まると後で色々面倒になります。




## 4. 常に最新情報の追跡

UE5は進化し続けています。新しいアップデートや機能に常に注意を払い、プロジェクトに取り入れるべきものがあれば迅速に導入しましょう。

UE5を使用した映像制作は素晴らしい経験ですが、上記のポイントに留意することでプロジェクトの品質と効率を向上させることができます。成功をお祈りしています！

# さいごに（宣伝）
UEを使用した色々な映像案件をしていきたいのでなにかお手伝いできることありましたらお気軽にお声がけください！



また、弊社は型にとらわれないスタイルで今後さらに拡大していきます！
その拡大を手伝っていただけるCGプロデューサーとCGディレクターを募集しています。

興味を持っていただけた方は、下記のメアドに飲みの誘いでも話を聞いてみたいなんでもいいので送ってください！
info@glitzvisuals.com