OmniAICreator/Qiita-1.07M huggingface dataset:
TerraformでIAMを設定してEC2にセッションマネージャー経由で接続してみる

# はじめに
Terraformの勉強を始めたので備忘録を兼ねて行ったことを投稿しようと思います。
これは[前回の投稿](https://qiita.com/kakita-yzrh/items/1357a219b4a891a441ff)の続きです。
前回の投稿ではTerraformでEC2の作成を行いました。
今回は作成したEC2にロールを付与してセッションマネージャー経由で接続できるようにしてみます。

# TerraformでIAMの定義を行う
### 信頼ポリシーを定義
まず、信頼ポリシーを定義して何のリソースに何ができるかを定義します。
今回はセッションマネージャー経由でEC2に接続したいので、
AssumeRoleを許可して対象はEC2になるようにします。

```terraform:iam.tf
data "aws_iam_policy_document" "instance-assume-role-policy" {
  statement {
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}
```
※`data`は外部リソースの情報を取得してTerraform上での利用を可能に

### IAMロールを定義
`assume_role_policy`に定義した信頼ポリシーの情報を参照します。
```terraform:iam.tf
resource "aws_iam_role" "test" {
  name               = "test_role"
  assume_role_policy = data.aws_iam_policy_document.instance-assume-role-policy.json
}
```

### IAMポリシーを定義
dataを使ってAWSの`AmazonSSMManagedInstanceCore`を参照しARNを取得してロールに紐付けます。
先ほど定義したロールにアタッチされるようにします。
```terraform:iam.tf
data "aws_iam_policy" "ssm_core" {
  name = "AmazonSSMManagedInstanceCore"
}

resource "aws_iam_role_policy_attachment" "test" {
  role       = aws_iam_role.test.name
  policy_arn = data.aws_iam_policy.ssm_core.arn
}
```

### インスタンスプロファイルを定義
IAMロールをEC2に設定するにはインスタンスプロファイルを定義する必要があります。
```terraform:iam.tf
resource "aws_iam_instance_profile" "test" {
  name = "test_role"
  role = aws_iam_role.test.name
}
```

### EC2に定義したロールを設定
前回作成した`ec2.tf`に定義したインスタンスプロファイル追加します。
```terraform:ec2.tf
resource "aws_instance" "test" {
  ami           = "ami-0404778e217f54308"
  instance_type = "t3.micro"

  # 以下を追加
  iam_instance_profile = aws_iam_instance_profile.test.name

  tags = {
    Name = "tf_test"
  }
}
```

# TerraformでIAMロールを付与してEC2を作成

### Terraformの`plan` `apply`を実行
前回と同様、terraform　の `plan` `apply`を実行して、AWS上にリソースを作成します。
```bash
terraform plan
terraform apply
```

### セッションマネージャーで作成したEC2に接続する
AWS マネジメントコンソールを開いて、AWS Systems ManagerのSession Managerを開きます。
`セッションの開始`を押すと作成されたインスタンスが表示され、EC2に接続することができます。

# 作成したリソースの削除
前回と同様、terraform　の `destroy`を実行して、AWS上のリソースを削除します。
```bash
terraform destroy
```

# さいごに
今回は作成したEC2にセッションマネジャー経由でアクセスできるようにIAMの定義を行いました。
次回はブラウザでhttp接続するための設定をTerraformで行いたいと思います。
Payment検証 Web決済のクレジットカードの検証について

■はじめに
---
　Payment検証のWeb決済の決済手段クレジットカードで準備段階や検証時に注意している内容をお話していければと思います。

■クレジットカードって何を使うの？
---
　普段使用しているクレジットカードは状況によって様々なステータスに変動する部分があります。
クレジットカードのテストカードを用いて検証することで、それぞれの種類やパラメータの細かい部分を確認することができます。

　開発環境で検証する際に、決済プラットフォーム毎に使用できるテストカード情報が異なります。
一部は共通で使用できるものもありますが、カード番号によってそれぞれのパラメータが異なるため、担当者にテストカード情報を確認してみてください。
カードについては本人認証サービス(3Dセキュア)に対応したもの、非対応なものがあります。
本人認証サービスについては3Dセキュア2.0認証が必須となっておりますが、こちらについては非対応カードでも決済できる、できないというどちらの認証方式を選択しているかで異なるため注意してください。

上記を基に、3Dセキュア対応しているクレジットカード(1.0認証、2.0認証)、3Dセキュア非対応のクレジットカードの各パラメータで決済できるかできないかを確認しております。
ブランドについては、対象外のブランドでは決済できないことを確認、対象のブランドについては網掛けでパラメータ毎に確認しております。
※リリース時に確認する際は商用環境向きになっているため、テストカードは使用しないように注意が必要です。

実際のクレジットカードも全ブランドを用意することが困難なのでテストカードで基本的に動作確認を行う方が望ましいです。

■クレジットカードの保存について
---
　案件によって異なりますが、クレジットカードのカード情報入力画面にカードを保存するのチェックボックスがある、決済成立時に自動的に保存される等があります。
こちらについては、カード情報入力後に決済失敗した際や途中離脱(導線上のキャンセル)時にカード情報が保存されていないこと等も確認しております。
また、登録したカード情報の上限がある場合、上限まで登録後に関わりのある画面の表示確認が決済できるかなどといった動作回りの確認も行います。

■決済について
---
　決済時にそのまま購入になることも多いですが、3Dセキュア認証により本人確認が入るとその画面上でキャンセルやID・パスワードの入力規定回数を超えて失敗することにより、購入失敗になるケースがあります。　
そのため、カードで決済できることを確認する以外に認証画面に遷移するパターンでは画面上にどのボタンやリンクがあるのかの考慮が必要です。
※購入中止などの動作により決済できなかった場合、購入キャンセル等の画面が表示されるのか

■検証時に確認できないこと
---
　カード情報入力画面でセキュリコードや有効期限については任意になっており、実際のクレジットカードを想定した内容の確認ができないため、こちらについてはテストカードのエラーパターンで有効期限切れやセキュリコード誤りのカード情報を使用することになります。
※この有効期限やセキュリティコードですが、リリース時にしか確認できないからリリースでやってしまうとカードが停止する場合がありますので注意してください。

■イレギュラー操作周りについて
---
　ユーザー操作で起きそうなところをメインに主に決済時に下記の内容を確認します。
ただ、実際にやってみないと決済ができるのかできないのかが分からないのとタイミングによって処理が進むので複数回実施したりして1つ1つ決済処理をメモして報告しております。
この際、サポートツール上での購入履歴上の確認も一緒にまとめております。

　・機内モード(通信不良)で決済を行う
　・決済完了後にブラウザバック(戻るキー含む)を行う
　・決済処理中にブラウザバック(戻るキー含む)を行う
　・ブラウザの別タブや別ブラウザでの同時決済処理
　・NativeAppとWeb上での同時決済処理
　・ボタン連打
　・画面遷移中に画面内のボタンがタップできるか
　・上限額設定が有る場合上限超過できる方法があるか
　・一定時間放置後に決済する
　・各画面のブラウザのURLをブックマークしてアクセスする
　※上記以外は検証しながら遷移状況や画面表示回りをみて決済時に気になる要素があれば確認するという方法を取っております。

■最後に
---
　今回はクレジットカード決済についてお話しましたが、依頼段階でリリース時にどこまで確認するのかも考慮して動かないと準備できるできないがあるためそこが一番重要と思っております。
今後、Payment検証する機会があった際に参考になれば幸いです。
ソシャゲの長期運用で感じた教訓

[QualiArts Advent Calendar 2022](https://qiita.com/advent-calendar/2022/qualiarts "QualiArts Advent Calendar 2022")、5日目の記事です。

ガールフレンド（仮）でフロントエンドエンジニアをしている鈴木です。

ガールフレンド（仮）は
2012年よりサービスが開始されたブラウザで遊べるソーシャルゲームで、
今年の10月で10周年を迎えた長寿タイトルです。
私自身もガールフレンド（仮）に従事して7年目に突入しました。

今回はガールフレンド（仮）を長期運用してきた中での教訓を紹介したいと思います。

# 最新の仕様の全容が追えるようにしよう
ユーザー様に長く遊んでいただくために、
運用の過程でイベントなどの機能に対して仕様が付け足されていくわけですが、
運用を重ねれば重ねるほど、その付け足しも重なっていくので、
長期運用タイトルでは最終的に仕様がとても複雑になりがちだと思います。

私はガールフレンド（仮）にジョインする前は別のソシャゲプロジェクトを
３件渡り歩いていたのでソシャゲの知識はありましたが、
ジョインした時点でも既に仕様は複雑化していたので、
その複雑さに驚愕したのを覚えています。

また、仕様追加の過程で、追加分の仕様書が作成されていきますが、
これがまとまって管理されていなかったので、
資料からは正確な仕様を把握することは困難な状況でした。
（古い機能については資料自体が行方不明ということもありました...。）

このような状況ですと、実際のコードを読むことでしか仕様把握が出来ないので、
時間がかかるのはもちろん、仕様把握漏れによる不具合にも繋がる恐れがあります。

ですので、機能ごとに資料をまとめた場所に置いておくなど、
仕様を追いやすいようにする観点を持っておくと良いと思います。

# 定期的に機能の断捨離をしよう
定期的にゲームのアップデートを行い、機能を追加していくことになると思いますが、
長期運用しているとその機能の数も膨大になっていきます。

そして、共通モジュールに手を入れないといけないような改修案件だったり、
導入しているライブラリなどのサポート切れによる移行対応など、
影響範囲の広い対応が必要な機会も少なからず発生します。

そうなると、影響範囲の調査、実装、テストが必要になるわけですが、
機能の数に比例してこれらのコストも膨れ上がっていきます。

ですので、定期的に機能の断捨離をした方が良いと思っています。

とはいえ、一度追加してしまった機能を削除するというのは、
提供するサービス面から見ればマイナスでしかないので、
提案しても中々受理されないかもしれません。

なので、アップデートで機能が追加される際に
削除を提案出来れば受理されやすいように思います。

その際に削除対象の機能が不要だという評価材料を
添えることが出来ると良いと思うので、あらかじめその計測が出来る
仕組みを盛り込んでおけると良いと思います。

# 安易に新技術を取り入れてはいけない
長期に運用をしていると、周囲では新しい技術が流行していくので
それをゲームにも取り入れたくなるのは珍しくないと思います。

ただ、安易にこれを取り入れてしまうと、多くの技術がゲーム内に
内在することになり、カオスな状態になってしまいます。

なので、既存の技術を新技術で置き換えるのが良いと思いますが、
常に運用が走っているソーシャルゲームでは中々難しいと思います。

現に、ガールフレンド（仮）では、過去に新技術で取り入れようとして
頓挫した痕跡があり、技術の異なる基盤が複数存在する状況となっています。

私がジョインした時点でプロジェクト内でこの基盤は廃れており、
新たに機能を追加する際は元の基盤が採用されていました。

廃れた原因は、学習コストが必要な他、
開発の効率面でメリットが享受出来ていなかったので、
当時のタイトなスケジュール下においては
チーム内に浸透しなかったのではないかと推測します。

結果、機能ごとに基盤が異なるので、無駄に学習コストがかかるので
完全に負の遺産と化してしまいました。
（採用した技術自体も世間的に廃れてしまいました...。）

こうならないためにも新技術の安易な導入は避け、
導入する場合はチーム内に浸透させる道筋を立てた上で導入するべきです。

ただ、長期的に新技術に触れられない期間が続くと技術成長の機会が無く、
精神衛生的に良くないので新技術に触れる機会を設けるのも大事です。

そこで、保守が不要な単発の施策においては
積極的に新技術を取り入れることをお勧めします。

# あとがき
今回は長期運用だからこそ出てくる問題点について書かせていただきました。

ガールフレンド（仮）はブラウザゲームですので、ネイティブアプリが主流の昨今では
多少事情が異なることはあると思いますが、長期に運用を続ける際の参考になれば幸いです。

最後までお読みいただき、ありがとうございました。
Javaで何か作ってみる(2022/12/04 Day45)

## 今日やった事
- 何もしなかった。
## 参考にしたもの
- 特になし。
## 所感
- 今日は本当何も勉強しなかった、ただただ反省。。。しかも2日連続
## 明日の予定
- 引き続き、Springの勉強を進めていく。明日こそは。。。
Javaで何か作ってみる(2022/12/03 Day44)

## 今日やった事
- 何もしなかった。
## 参考にしたもの
- 特になし。
## 所感
- 今日は本当何も勉強しなかった、ただただ反省。。。
## 明日の予定
- 引き続き、Springの勉強を進めていく。
NGINXがさばける秒間あたりのリクエスト数を計測してみた

### はじめに

NGINXのリクエスト処理性能が一定条件下でApacheを超えたとの検証結果を目にするようになりました。
NGINXが実際秒間どれぐらいリクエストを処理可能か、自分の貧弱な仮想環境で計測してみました。

### 関連用語のおさらい

#### NGINX(エンジンエックス)とは

Wikipediaから抜粋

https://ja.wikipedia.org/wiki/Nginx

- フリーかつオープンソースなWebサーバである
- 処理性能・高い並行性・メモリ使用量の小ささに焦点を当てて開発されている
- HTTP, HTTPS, SMTP, POP3, IMAPのリバースプロキシの機能を持つ
- ロードバランサ、HTTPキャッシュなどの機能も持つ


#### RPS(Requests per second) for HTTP Requests

1秒間に処理可能なHTTPリクエスト数を表します。
Webサーバーの処理能力を評価する指標として使用されます。

### NGINXパフォーマンスのベンチマーク情報

NGINXの公式サイトに、2017年のブログ記事で若干古いですが、検証結果が記載されていました。

https://www.nginx.com/blog/testing-the-performance-of-nginx-and-nginx-plus-web-servers/

各種CPUコア数とリクエストサイズ(KB)による、RPS値が記載されていました。
CPUコアが1つのみで、リクエストサイズが10KBのケースを見ると、なんと`54684`を達成できています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/0bc59012-2fdd-e73e-f5b0-24b3a0d88f9d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/e2116814-5e5e-7ce8-5293-4d50dc805dfc.png)

本当にここまでパフォーマンス出せるの?
と、少し半信半疑だったので、自分の仮想環境でも計測してみることに。

### NGINXのリクエスト処理性能を計測してみました

#### 検証環境

- NGINX導入サーバー
    - Hyper-Vの仮想マシン
        - CPU: 2コア
        - メモリ: 2GB
- OS
    - AlmaLinux 8.6
- NGINX
    - Version: 1.22.0
    - NGINXの設定: デフォルトのまま(チューニング未実施の状態)

#### 検証内容

- ベンチマークツールを使用
    - [wrk2](https://github.com/giltene/wrk2)を使用し負荷テスト
        - スレッド数: 2
        - 接続数: 10
- HTTPリクエスト
    - HTTPS POSTを大量発行
    - ペイロードのサイズは2KB

#### 計測結果

結論から、秒間`3万～4万`のリクエストさばけました。
仮想環境でここまでパフォーマンス出せるのはすごい!

wrk2を使って3回計測した結果を共有します。

- 一回目

```shell
$ wrk2/wrk -s ./test.lua -t2 -c10 -d10s -R50000 https://NGINXサーバーのIPアドレス/index.htm
l
Running 10s test @ https://wrk2実行サーバーのIPアドレス/index.html
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   559.56ms  372.83ms   1.27s    57.32%
    Req/Sec       -nan      -nan   0.00      0.00%
  437416 requests in 10.00s, 770.06MB read
Requests/sec:  43742.32
Transfer/sec:     77.01MB
```

- 二回目

```shell
$ wrk2/wrk -s ./test.lua -t2 -c10 -d10s -R50000 https://NGINXサーバーのIPアドレス/index.html
Running 10s test @ https://wrk2実行サーバーのIPアドレス/index.html
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.29s   859.93ms   3.01s    58.13%
    Req/Sec       -nan      -nan   0.00      0.00%
  353727 requests in 10.00s, 622.73MB read
Requests/sec:  35373.34
Transfer/sec:     62.27MB
```

- 三回目
```shell
$ wrk2/wrk -s ./test.lua -t2 -c10 -d10s -R50000 https://NGINXサーバーのIPアドレス/index.html
Running 10s test @ https://wrk2実行サーバーのIPアドレス/index.html
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.57s     1.12s    4.09s    62.77%
    Req/Sec       -nan      -nan   0.00      0.00%
  296447 requests in 10.00s, 521.89MB read
Requests/sec:  29644.94
Transfer/sec:     52.19MB
```    

### おわりに

NGINXのリクエスト処理性能を計測してみました。
自分の貧弱な仮想環境でも、予想を上回るパフォーマンスを出せました。
ワテとはじプロ

「注意」
なんかqiitaって色々な難しい機能がありますね…僕はちんぷんかんぷんなので
書くだけで精一杯です。
どうかご了承ください


「序章」
まずは私がはじプロをやる前のことから話す
僕がTwitterを始めた理由はサウスパークのとあるゲームで繋がりたかったからである。
その時僕はまだ色々な事を知らなかった
当時たくさんの人々に迷惑をかけてしまった。

「認証欲求の怖さ」
人はたまに認識欲求に溺れる。
死んだ親戚の隣で踊ってsnsにあげたり
身長170cm以下の男は人権がないと言い出したりしてしまう。
これらに共通して言えることは
[後々を何も考えない]と言う事だ。
私はサウスパーク界隈でとある方の
創作物にケチをつけたりしていたことがある
それで少し炎上してしまった。
※ケチの内容については詳しく言ってしまうと個人が特定される恐れがあるので割愛します


「自覚と恐れ」
ある日サウスパーク界隈で名のある人(僕がケチつけた人とは違う人)にブロックされた。
おそらくサウスパーク界隈で私は悪な存在だと
みんなが断定したのだろう。
それを見た時正直ビビった。
その時私は自分が間違ってると自覚した。
それからと言うものの自分は鍵垢で
しばらく過ごした。
自分はでしゃばってはいけない存在だと
気付かされた。
自分の日頃の行いもとても
良いものとは思えない、
思った事をすぐに言ってしまう癖が
あり周りの人をドン引きさせるそして人が
離れていく事を何度も経験した。
それでもスパム垢からフォローリクエストが
来るばかり
やはり認証欲求が満たされたい！と思った

「認証欲求」
どうしても認識欲求が欲しいと思い鍵を外したらフォローリクエストで来たスパム垢が
勝手にフォローするだけに変わってしまった。
ただそれだけでは意味がない
みんなに見てもらうには
彼らの様に何かを作らねばと思った。

「はじプロの初作品マコ見切り」
これが私の初作品である
どうやらはじプロを利用して
サウスパーク界隈で成り上がろうとしたらしい。
まずマコ見切りってなんぞや？と簡単に言うと
ケニーの見切りゲームである。
カービィの刹那の見切りとサウスパークを出して
2で割った様なゲームを作って
ツイッターに投稿してしばらくすると
いいねが6件もあった。
今まで鍵垢を経験していた私にとって
6件と言うのはバズりの様なものだった
しかし問題が起きた。

「出会い」
良いねをもらったのは、はじプロ関連の人々が多かった。
サウスパーク界隈の人々は少しかいなかった。
私はサウスパーク界隈だけではなく
はじプロ界隈の人々と繋がることが
出来るのでは？
私はとりあえずはじプロを利用して
サウスパーク界隈で成り上がるのではなく
はじプロ界隈でみんなと仲良くする事を
目標にした
でもどうすればいいかわからなくなってしまった取り敢えず2作品目を作る事にした

「バタモン」
バタモンとはカービィのそっくりさんである
私は彼のゲームを作ろうとした。
初めはクリッカーゲームを作ろうとした
しかしながら途中で行き詰まった。
なんとか案を変えて連打型の対戦ゲームを作ったその名も、もぐもぐ…じゃない

「ペチャクチャバタモン」
正直言ってしまうと自分の好きなキャラクターのバタモンのゲームを作りたかった。
流行りの物なんてどうでも良いと思った。
その時に僕の作品に引用リツイートをしている
ユーザーがいた。
その人は私の作品について語っていた。
私は見ず知らずの人にリプを送るのにとっても
勇気が必要だった。
でも簡単に送る事が出来た。

「アドバイス的なやつ」
簡単に送ることができたのは正しい選択肢を選べたからである。
自分はその当時とある施設で実習生として学んでいた。
思った事を言う自分にとってかなり難しい物だった。
たくさんの人を怒らせた。
たくさんの人々を失望させた。
私はその経験から学び、思った事をすぐ言うのではなく言う前に選択肢として捉えることを心がける事にした。
例えば…

ワイ:疲れたなぁー
相手1:どしたん？
ワイ:いや最近な車の免許取ろうと思って頑張ってんねんけど中々技能が進まないねん
相手2:そうなの？てか1って免許あるよな？
相手1:うん、取るのすごい苦労した技能もしんどいし座学覚えるの大変だったよ
ワイ:すごいな1…あれ？2って免許あるの？
相手2:そもそも俺は教習所行ってない
けどでも記憶力いいし座学は余裕としてあとは
技能だよなぁ
ワイ:(調子乗んな車の運転舐めるなよって言いたいけどいったら周りの空気が悪くなるな
実際に2は頭が良いけどちょっと
見栄っ張りなところあるからなぁ
せや！座学のひっかけ問題に気をつけた方が良いって言っとくか)


と言うふうに直感で思った事を言ってしまうと
どうなるかを考える事にした
直感的に思った選択肢
[調子乗んな車の運転舐めるなよ]
直感的に思った後で考えて出てきた選択肢
[座学も色々難しいのあるよひっかけとか]
それを選択肢の一つとして捉らえる事にして
別の選択肢もあるかも知れないと考える
言ってしまうと恋愛ゲームの選択肢みたいなものを現実でやろうとしているのである
これを使って現実で思った事を直ぐに言う癖を
治す事を努力しているしかしながら
[調子乗んな車の運転舐めるなよ]
と言う選択肢を使ったらどうなるのかも知りたい
恋愛ゲームなら2周目で別の選択肢が選べるので
どうなるのか知れるでも現実は違う……
みんなの中に思った事を直ぐに言ってしまい
空気を苦した事のある人は是非使って欲しい
(でも私は選択肢が出てくる前に話が終わってたり
思ったことも直ぐに言ってしまうこともあるが…)

「成長」
はじプロを初めて色々な人と繋がることが出来た
前の私だったらもしかすると他人の作品に
ケチをつけて人が離れていったかも知れない
私ははじプロにチャンスをもらった
前と比べると成長出来たと思う
(僕の前の事は知らない人もいるけど)
そして色々なアドバイスをもらった
でもまだ人として成長出来ていないと感じる
私は失敗して人をイラつかせます
私はセンスもないし空気も読めません
でも僕は日々精進していると思う
こんな終わり方ですが大丈夫でしょうかね？

おわり
FastAPI と Strawberry GraphQL を使って REST と GraphQL を共存させる際にしたこと

正確には"REST エンドポイントで運用するための実装をしていたところに、GraphQL エンドポイントを差し込む際にしたこと"です。

🚧この対応はまだプロダクションにのっておらず、より良い方法や他にも考慮すべきことが出てくるかもしれません🚧
🚧　共存に対することのみに絞った話です　🚧 

共存に対する考慮が必要なのは REST エンドポイント と GraphQL エンドポイント の例外時のレスポンスのお作法が異なるためです。(以下の対応はREST 作法に基づいた機能を使っていたり、FastAPIの特定の使い方をしていた場合のみに発生する話なのであしからず。)  

## Bearer Token のチェックをする OAuth2AuthorizationCodeBearer の調整

OAuth2AuthorizationCodeBearer はこんな感じ↓で Bearer Token に不備があった場合に、フレームワークが代わりに 401 を投げていてくれたのを、RESTに対するリクエストとGraphQLに対するリクエストでそれぞれの返し方を実装する必要がありました。

![スクリーンショット 2022-12-03 15.33.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/838dc7a8-cb1d-d422-df86-65344c4b1645.png)


## Router Level で depends を使ってチェックしていた処理を GraphQL 用に用意

REST だけの時はチェック処理で例外を発生させた場合、exception_handlers を使ってインターセプトして HTTP レスポンスを返していました。GraphQL が追加になった場合に、チェック処理はどのエンドポイントから来たリクエストなのかを判定する材料を持ったインターフェースになっていなかったので、depends を使ってチェックしていた処理を GraphQL 用に用意しました。(少量だったのでインターフェース拡張よりこちらが良いと判断)
 
![スクリーンショット 2022-12-03 14.36.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/0a59795d-ae43-6304-1cb8-2e130a82a046.png)



以上です。

# 感想
進めていく上で、FastAP Iが面倒なことを色々と肩替わりしてくれていたことに気が付ける良い機会になりました。

# 宣伝
最後まで読んで頂きありがとうございました。

先日、 Strawberry GraphQL にコミットできました。
Strawberry GraphQL を使っていく皆様、フォローをお願いします。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">PRマージされた🎉<br>文化圏が全く違う方とのやりとりめっちゃ緊張した。<br>例外を足しただけだが、良い経験させてもらった。 <a href="https://t.co/fiCkyNbkAe">https://t.co/fiCkyNbkAe</a></p>&mdash; nassy@PythonとAzure (@n_nassy20) <a href="https://twitter.com/n_nassy20/status/1598600173307191297?ref_src=twsrc%5Etfw">December 2, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


また、弊社別プロダクトで絶賛採用中です :muscle: :muscle:
皆んなの応募待ってるぜ!!
https://www.wantedly.com/projects/1181162
x-dataの中身を切り出していく試み

# x-dataのコード量が多くなりすぎた場合に使えます。
おぬぬめ。
# 前回の続きです

https://qiita.com/yowatsuyoengineer/items/4b91ff506559e139d049

今回はx-dataの中身を<b><font color="red">scriptタグで囲んで定義する方法</font></b>で書いてみます。

### 前回書いたコード
ぽちぽちして表示非表示するヤツ。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="oNyQreK" data-user="gorimatyan" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/gorimatyan/pen/oNyQreK">
  Untitled</a> by gorimatyan (<a href="https://codepen.io/gorimatyan">@gorimatyan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

今回はここを切り出して別のところで定義してみます。
```html
<div x-data="{
    open: false,
    toggle() {
        this.open = ! this.open
    },
}">
```

# x-dataを切り出して定義する
```html
# x-dataの中身をtoggleText()で定義する
<div x-data="toggleText()">
    <button @click="toggle">表示</button>
 
    <div x-show="open">
        やっほー
    </div>
</div>

<script>
// toggleTextではreturnを忘れてはならない
const toggleText = () => {
    return {
        open: false,
        toggle() {
            this.open = ! this.open
        },
    }
}
</script>
```
同じ挙動をします。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="oNyQreK" data-user="gorimatyan" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/gorimatyan/pen/oNyQreK">
  Untitled</a> by gorimatyan (<a href="https://codepen.io/gorimatyan">@gorimatyan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# まとめ
これで<b><font color="red">単一のファイルでx-dataが増えても管理しやすくなりました。</font></b>
toggle○○とかdropdownみたいなx-dataが増えてもそれぞれ関数で定義してやればいいだけなんす。

次回はx-dataをファイル単位で定義するのではなく、<b>他ファイルをまたいで再利用可能にしていきます。
AIで絵を描いてみた(Midjourney ミッドジャーニー)

Midjourney（ミッドジャーニー)は単語で説明した絵を描いてくれるAIです。

*Midjourneyは試すだけなら無料で使えますが、回数制限がありますし商用利用も出来ません。

<details><summary>無料利用できる範囲</summary>

```
登録完了後に、Discordサーバーを通じて画像を作成することができるようになり、IMAGINEコマンドの使用は約25回までが無料ですが、それ以上だと有料で課金になります。

なぜ約25回なのかというと、Midjourneyで画像を生成した際に消費されるのは「回数」ではなく「時間」です。

Midjourneyは1枚当たり1分ほどで作品が完成すると目安の時間がいわれてます。

となると、1枚生成するのに1分かかった場合、25枚の作品が作れるということで、無料利用では約25回分利用できるといわれてます。
```

</details>

まずMidjourneyはDiscord内で使うのでDiscordのアカウントを作成し、アプリをインストールします。
https://discord.com/

次にDiscordを起動した状態でMidjourneyのサイトのJoin the betaを押します。
https://www.midjourney.com/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3014485/3783601e-d756-de89-b1a3-7f1e0d028192.png)

これでMidjourneyのサーバーに入れるのでnewbies-○○というルームを表示します。

後はメッセージ欄に/imagineと入力してEnterを押した後、好きな単語を,区切り指定して再度Enterを押すと画像生成が始まります。

https://togetter.com/li/1927061

今回は下記の呪文で絵を描いてみました。
[hdri panorama, steampunk city, 8k, photo real --w 2048 --h 1024]

![yamazaki_hdri_panorama_steampunk_city_8k_photo_real_db2ee818-848a-4f40-9235-56c850f96715.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3014485/b128e872-577a-8a5a-b471-84c311e7a1eb.png)

下にある「U」ボタンの1〜4のどれかを押すとアップスケールした画像を生成します。この時、更にディティールも付与されます。
「V」ボタンの1〜4を押すとその番号の画像をベースに、別パターンを作成してくれます。
画像は、
①　②
③　④
の順番になります。
Stripe CLIをCircle CI上で実行する方法

この記事は、[CircleCI Advent Calendar 2022](https://qiita.com/advent-calendar/2022/circleci) 5日目の記事です。

Stripe CLIを利用すると、Stripe上でのさまざまなイベント（決済完了・サブスクリプションの新規契約・キャンセルなど）をシミュレートすることができます。

CI上でStripe CLIを利用することで、Stripeのイベントがかかわるシステムの結合テストや、バッチジョブの実行などが可能です。

この記事では、Circle CI上でStripe CLIを実行するためのTipsを簡単に紹介します。

## Stripe CLIをDockerから利用する

Stripe CLIはDockerコマンドで実行できます。

```bash
$ docker run --rm -it stripe/stripe-cli help --api-key sk_test_xxxx
```

https://stripe.com/docs/cli/docker

Stripe CLIをDockerで実行する場合、`--api-key`でStripeのAPIキーを都度渡す必要がある点に注意が必要です。

## Circle CIに制限付きAPIキーを設定する

Circle CIでは、環境変数でAPIキーなどを安全に保存することができます。

そしてStripeの「制限付きAPIキー」を利用すると、「CI実行専用のAPIキー」を作ることが可能です。

https://stripe.com/docs/keys#limit-access

制限付きAPIキーは、ダッシュボードの[開発者 > APIキー]で、[制限付きのキーを作成]ボタンをクリックすると、作成できます。

![スクリーンショット 2022-10-07 19.25.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/1aac1f08-e753-5c49-1081-339ff42425cb.png)

ここでは、リソースごとにAPIへのアクセス権限を[なし][読み取り][書き込み]の３つから選択できます。

![スクリーンショット 2022-10-07 19.27.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/5824784b-1202-d4a1-1e51-3155a9f2f011.png)

Connectで作られた子アカウントに対する権限についても設定が可能です。

作成した制限付きAPIキーを、Circle CIの[Project Settings > Environment Variable]から設定しましょう。

![スクリーンショット 2022-11-08 11.41.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/fa2bb8cf-7810-8a78-c4b8-f2b23bc704fd.png)

Webhookのテストを行いたい場合は、同様の方法で`whsec_`からはじまるWebhook用の署名シークレットを環境変数に設定しましょう。


![スクリーンショット 2022-10-28 15.34.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/b159dc0f-e441-4de7-5f79-d8db627db3d3.png)

## `.circleci/config.yml`でStripe CLIを実行する

必要な環境変数の設定が終われば、Circle CI上で実行する設定を行いましょう。

`run`で先ほどのDockerコマンドを実行するだけOKです。

```yaml
jobs:
  stripe-demo:
    executor: node/default
    steps:
      - checkout
      - setup_remote_docker
      - run:
          name: "Stripe CLI"
          command: docker run --rm -it stripe/stripe-cli trigger customer.created --api-key ${STRIPE_SECRET_API_KEY}
```

## [Tips] `exec /bin/stripe: exec format error `が発生する場合

Stripe CLIのDockerイメージが一部バージョンでうまく動作しないケースが存在する様子です。

https://github.com/stripe/stripe-cli/issues/993

もし上記のエラーがジョブで発生した場合は、問題のないバージョン番号を明示的に指定して再度お試しください。

```diff_yaml
      - run:
          name: "Stripe CLI"
-          command: docker run --rm -it stripe/stripe-cli trigger customer.created --api-key ${STRIPE_SECRET_API_KEY}
+          command: docker run --rm -it stripe/stripe-cli:v1.12.4 trigger customer.created --api-key ${STRIPE_SECRET_API_KEY}

```
graphql-rubyを2.0.14より前のバージョンでinstallしている場合、validate_max_errorsを設定しよう！

バージョン2.0.14から`rails generate graphql:install`した時に生成される`app_schema.rb`に`validate_max_errors(100)`が追加されるようになりました。

下記がその時のCHANGELOGです。
![スクリーンショット 2022-11-24 22.34.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83424/2b413c02-dc47-8ec4-0af9-43236cd364c6.png)
関連する差分は下記です。[[プルリク](https://github.com/rmosolgo/graphql-ruby/pull/4179/files#diff-d3a195a6075da040bb95d191bce5ec24d2d26b24949e858ce09d1c3754e59e60R28)]

```diff:lib/generators/graphql/templates/schema.erb
+
+  # Stop validating when it encounters this many errors:
+  validate_max_errors(100)
 end
```

上記の変更により、バージョン2.0.14から使い始めてた場合は`validate_max_errors`が自動的に設定されているのですが、それ以前から使っている場合は自主的に設定しない限り`validate_max_errors`は設定されていません。
もしvalidate_max_errorsを設定していない場合、ほとんどの場合は設定した方が良いので紹介するためにこの記事を書くことにしました！

# validate_max_errorsを設定すると何が嬉しいのか？

graphql-rubyでは、argumentsにエラーがある場合でも全てのargumentsを検証してからエラーを返却します。

例えば、idの配列をargumentsに指定してbook_typeのconnectionを返却するクエリーを考えます。

```graphql
query Books($ids: [Int!]!) {
  books(ids: $ids) {
    nodes {
      id
    }
  }
}
```

これに下記のvariablesを指定します。

```json
{
  "ids": ["a", "b", "c"]
}
```

結果は下記のようにargumentsの全エラーが`errors`に設定されて返却されます。

```json
{
  "errors": [
    {
      "message": "Variable $ids of type [Int!]! was provided invalid value for 0 (Could not coerce value \"a\" to Int), 1 (Could not coerce value \"b\" to Int), 2 (Could not coerce value \"c\" to Int)",
      "locations": [
        {
          "line": 1,
          "column": 13
        }
      ],
      "extensions": {
        "value": [
          "a",
          "b",
          "c"
        ],
        "problems": [
          {
            "path": [
              0
            ],
            "explanation": "Could not coerce value \"a\" to Int"
          },
          {
            "path": [
              1
            ],
            "explanation": "Could not coerce value \"b\" to Int"
          },
          {
            "path": [
              2
            ],
            "explanation": "Could not coerce value \"c\" to Int"
          }
        ]
      }
    }
  ]
}
```

今回は3つだったから良いですが、上記クエリーはidの配列を受け取るので下記のように大量のargumentsを指定することもできます。
下記のように100万個の不正なargumentsが指定されれば100万個のエラーを全て検証して、全エラー内容を返却するということです。

```json
{
  "ids": [
    "a1",
    "a2"
    ...(省略)
    "a1000000"
  ]
}
```

ではどうするか？
そこで役に立つのが、`validate_max_errors`です！
テンプレートのように`validate_max_errors(100)`と指定して、大量の不正なargumentsを指定します。
すると、下記のようにvalidate_max_errorsで指定して100個エラーになるまでは今まで通り検証されるのですが、100を超えると検証が中断されて、"Too many errors processing list variable, max validation error limit reached. Execution aborted"というエラーが返却されます。

```json
          {
            "path": [
              99
            ],
            "explanation": "Could not coerce value \"a100\" to Int"
          },
          {
            "path": [
              null
            ],
            "explanation": "Too many errors processing list variable, max validation error limit reached. Execution aborted"
          }
```

argumentsの検証で重い処理をすることはほとんどないと思いますが、argumentsエラーはクライアントから簡単に起こすことができるのと、そもそもargumentsエラーの内容が全て必要になることはほぼないと思うので、validate_max_errorsはぜひ設定しておきましょう！！
conic-gradientとrepeating-linear-gradientを使ってみる

[ひとりCSS Advent Calendar 2022](https://qiita.com/advent-calendar/2022/css-becolomochi) 5日目です。

conic-gradientとrepeating-linear-gradientを使ってみます。
どちらも background プロパティ background-image プロパティに指定する値。

## conic-gradient とは

原点を中心に周りを周りながら色が変化する。conic = 円錐

- angle - 角度
    - from - 開始角度をずらせる
    - at
- position
- 色と角度
- 使い方しだいで円グラフや市松模様の表現もできる（おもしろい）

## repeating-linear-gradient

線形グラデーションを繰り返し並べられる。

- angle 角度
- 色と位置

## 遊んでみた

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="JjZeQrV" data-user="becolomochi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/becolomochi/pen/JjZeQrV">
  gradient</a> by Beco (<a href="https://codepen.io/becolomochi">@becolomochi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41088/bbf0682d-8b52-e312-3980-1603ad9f909c.png)

## 参考

- https://developer.mozilla.org/ja/docs/Web/CSS/gradient/conic-gradient
- https://developer.mozilla.org/ja/docs/Web/CSS/gradient/repeating-linear-gradient
【書き方ちょろすぎて草】Alpine.jsの書き方の基本

# 書き方
### <b><font color="red">x-dataを書くところから始まります。</font></b>
x-dataはプロパティと関数を定義するために使います。

x-dataは基本的にHTMLのタグに付けます。
```html
    <div x-data="{
        プロパティ名: 値,
        関数名() {
            実行したい処理
            例）プロパティに値を代入する
                this.プロパティ名 = 値
        },
    }">
        HTML要素を書く
    </div>
```
ここで定義したプロパティ、関数の適用範囲は上記の例で言えば<b><font color="red">div要素で囲んだ範囲内のみ</font></b>となります。
# 実例
こんだけのコードで表示の切り替えが実装できます。
一瞬で書けてしもた！！
```html
<div x-data="{
    open: false,
    toggle() {
        this.open = ! this.open
    },
}">
    <button @click="toggle">￥表示</button>
 
    <div x-show="open">
        やっほー
    </div>
</div>
```

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="oNyQreK" data-user="gorimatyan" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/gorimatyan/pen/oNyQreK">
  Untitled</a> by gorimatyan (<a href="https://codepen.io/gorimatyan">@gorimatyan</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# まとめ
プロパティと関数名を定義していくだけで簡単に表示非表示のトグルボタンが作れる。お手軽すぎる。
開発組織を全て業務委託メンバーで構築した話

CTOやVPoEの皆さんはエンジニアの採用には困っていると思います。もちろん、社長も含めて頭の痛い問題です。
スカウトメールを送ったり、イベントを開催したり、勉強会をやったり、エンジニアブログを書いたり、採用活動は色々とありますが、レッドオーシャン化してます。

# 業務委託メンバーで構築
社員を取っていくのはとてもハードルが高いので、業務委託メンバーで構築してみました。
業務委託メンバーというのは、
- SESエンジニアに入ってもらう
- フリーランスエージェント経由で契約する
- フリーランスを直接で契約する
SESエンジニアとフリーランスエンジニアは、特に変わりはありませんが、SESエンジニアの中には、企業の所属しながらSESエンジニアとなっている人と個人契約でSESエンジニアとなってる人がいます。

# 業務委託メンバーの良さ
## 1.採用が早い
社員採用となると速くても半年くらいかかると思いますし、半年掛かっても思っていたレベルのエンジニアを見つける事は難しいでしょう。少し妥協しながらの採用になることがほとんどです。
しかし、業務委託メンバーの採用になると、採用レベルと一切変えることなく採用する事ができます。しかも当月に見つかる事も少なくありません。紹介の量も社員の紹介量と比べて１０倍以上の量の紹介を受ける事が可能です。スピード感半端ないです。
## 2.採用費がかからない
通常、社員の場合は、エージェントに年収の紹介費を払う必要があります、エージェントでない場合も、媒体費、スカウト費、イベント参加費等結構なコストが必要です。
## 3.手間がかからない
採用の場合は、結構なコストが掛かるので退職された場合のダメージが大きい為、人材の選別に時間と労力をかける必要があります。これは家事と一緒で見えないコストがめちゃくちゃ大きいです。採用人件費を考えても凄いコストが掛かってる事を気付いてない場合も多いです。
## 4.評価制度がいらない
業務委託メンバーなので半年に一度の目標設定とか評価とか、評価のフィードバックは不要です。これもエンジニアマネジメント職にとってめちゃくちゃコストの掛かる部分です。人材の育成・教育・評価等は、組織にとってメインタスクと言っても良いくらい大事です。ここの力抜く訳には行きませんが、業務委託メンバーなら不要となります。
## 5.教育がいらない
業務委託メンバーは、エンジニアとしてプロの人達です。自分のスキルでお金を稼いでる人達なので、基本的には自分達で勉強します。もちろん案件的にやってみたい言語とかテクノロジー等はあると思いますが、プロなので環境を与えれば自分で解決、自走してくれます。この自走できるエンジニアを採用しようとすると超難しいです。
## 6.モチベーション管理がいらない
プロの人達なので、基本的にはモチベーション管理等はいりません。仕事で直接お金をもらってるのでモチベーションを下げてられません。もちろん人としてエンジニアとしての人格を否定したりするのは論外です。
## 7.人数の増減が容易
VUCA時代の経営としては、サービスが上手く行かなくなる事や瞬間的に人を減らす事等あるでしょう。更にサービスやテクノロジーをピボットする事もあります。社員と違って、フレキシブルに変更する事ができます。
## 8.技術も変更できる
Javaで開発していたものを、AI絡みでPython言語に変更する事があるかもしれません。社員の場合は、Pythonの勉強をしてもらう必要がありますが、業務委託メンバーの場合は、Java言語のプロからPython言語のプロへ入れ替わってもらう事が可能です。

# 業務委託メンバーがコストが高いと思われているけど
この話をしても社員に拘る会社さんが多いです。一番がコストです。社長が特に言いますね。
でも計算してみてください。
## 社員の場合のコスト
- 500万のエンジニアを6名
- 700万のエンジニアを３名
- 1000万のエンジニア(VPoE)を１名
の組織で考えた場合は、
これに人事の人件費 １名　500万を加えます
社員の場合は、
(500万*1.2)*7+(700万*1.2)+(1000万*1.2)=7,920万円です
1.2は、社会保険等
## 業務委託の場合は、
- 500万のエンジニアを6名
- 700万のエンジニアを３名
- 1000万のエンジニア(VPoE)を１名
採用がないので人事はいりません。他と兼務で良いでしょう。
(500万*1.3)*6+(700万*1.3)+(1000万*1.3)=7,930万円です
1.3は、エージェントの中間マージンですが、もっと安いです
## コスト比較
社員：7,920万円と業務委託：7,930万円でほとんど変わりません。
ここから社員の場合は、採用に関してエンジニアも書類選考・面談に入ります。マネジメント職は、評価・目標設定・教育・モチベーション管理等の人件費を考えたら、きっと1000万は必要でしょう。
圧倒的にコストでも業務委託メンバーの勝ちです。
# 会社への帰属意識等
これについては、絶対的に社員の方が良いです。ただ社員だと言っても来月辞める可能性もあります。今の時代長く勤務してくれる保証は全くありません。これは会社側からの勝手な重い思いだと思います。
ここを大事にするなら、新卒エンジニアの採用に力を入れる事がオススメします。新卒エンジニアの場合は、文化形成含めて最初の会社なので会社と個人の人格も同一化しやすいでしょう。
# 最後に
開発組織の構築の仕方を社員限定で考える時代は終わってます。フレキシブルな頭でフレキシブルに動ける体制について考えてみて欲しいです。
「Effective DevOps」を流し読みした要点

[Effective DevOps ―4本柱による持続可能な組織文化の育て方 | Jennifer Davis, Ryn Daniels, 吉羽 龍太郎, 長尾 高弘 |本 | 通販 | Amazon](https://www.amazon.co.jp/Effective-DevOps-%E2%80%954%E6%9C%AC%E6%9F%B1%E3%81%AB%E3%82%88%E3%82%8B%E6%8C%81%E7%B6%9A%E5%8F%AF%E8%83%BD%E3%81%AA%E7%B5%84%E7%B9%94%E6%96%87%E5%8C%96%E3%81%AE%E8%82%B2%E3%81%A6%E6%96%B9-Jennifer-Davis/dp/4873118352)

![](https://m.media-amazon.com/images/I/51hSE7AENQL._SX388_BO1,204,203,200_.jpg)

流し読みも甚だしいが、以下要点。

## 要点

https://effectivedevops.net/

- 人間の問題
    - https://itrevolution.com/articles/devops-culture-part-1/
- DevOps は文化運動
- 「DevOpsの4つの柱」
    - コラボレーション
    - アフィニティ(親近感、一体感)
    - ツール
    - スケーリング
- 「人が語るストーリーは、彼らの世界を収め、彼らの世界に意味を与えるコンテナである。」
- Netflix の TechBlog
    - https://netflixtechblog.com/
- 「全部入りのdevops」、devops-as-a-serviceといったものはない

## 参考
[【資料公開】Effective DevOps | Ryuzee.com](https://www.ryuzee.com/contents/blog/7126)
[『Effective DevOps』読んだ: DevOpsという文化の作り方 - Hack Your Design!](https://blog.toshimaru.net/effective-devops/)
[「Effective DevOps」から学んだこと。 - はてなの金次郎](https://jumpyoshim.hatenablog.com/entry/book-report-of-effective-devops)
[文化である DevOps の誤解を紐解こう /「Effective DevOps」を読んだ - kakakakakku blog](https://kakakakakku.hatenablog.com/entry/2019/05/31/100634)
[Effective DevOps devopsに対する誤解とアンチパターン - Qiita](https://qiita.com/yutachaos/items/a608dfe0a84c914d273d)

### PodCast
- Arrested DevOps（https://www.arresteddevops.com）
- DevOps Cafe Podcast with John Willis and Damon Edwards（http://devopscafe.org）
- Food Fight Show（http://foodfightshow.org）


以上です～
Delphi / FireDAC　PostgreSQLで、画像の保存と取り出しのテストをしてみました。　　　　　

# はじめに
## PostgreSQLでの、画像の保存と取り出しのサンプルコードが、自分は、うまく検索できなかったので、PostgreSQL15とUbuntu22.04LTS環境で、実行してみました。

### 1.　Ubuntu22.04LTS はローカルの機器にインストール

### 2.　PostgreSQLは最新の15をインストール

### 3.　PostgreSQLでは、データ型は　BLOBではなく　BYTEA　
```Delphi:FD_PostgreSQL15_b_Unit.pas　の Create SQL文
  sqlstmt:='CREATE TABLE test_tbl '+
  '('+
  'ID         serial,'+
  'TS_NO      INTEGER  not null,'+
  'TS_NAME    TEXT ,'+
  'TS_QTY     DECIMAL(14,2) Default 0 ,'+
  'TSBLOB     BYTEA ,'+    //BLOBに該当
  'TSBLOB2    oid,'+	   //こちらも使えるようです
  'primary key(TS_NO)'+
  ')';
```

### 4.　Delphiで、uses JPEG, GIFImg, PNGImage ;  //使用する画像を宣言
##### Delphi 10.2でテストしています。

![11_IDE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/88517/8f6cb57c-16b6-7dea-fe2d-1b21654d6ad9.png)

***
#### 以下サンプルコード

### 画像データの追加のサンプルコード
```Delphi:FD_PostgreSQL15_b_Unit.pas
procedure TForm1.SpeedButton6Click(Sender: TObject);
var
  SQLstmt:String;
begin
  with FDConnection1 do
  try
    SQLstmt :=' INSERT INTO '
             +' test_tbl ( ts_no  , tsblob ) '
             +'	VALUES ('
             +' :ts_no , :tsblob '
             + ')';
    FDQuery1.SQL.Clear;
    FDQuery1.SQL.Text:= sqlstmt;
    FDQuery1.ParamByName('ts_no').AsInteger:=StrToInt( Edit_TS_NO.Text );  //オープンした画像ファイル名
    FDQuery1.ParamByName('tsblob').LoadFromFile( Edit_Files.Text ,ftBlob);
    FDQuery1.ExecSQL();
    ShowMessage('登録しました');
  finally
    FDQuery1.Close;
  end;
end;
```

### 画像データの表示のサンプルコード
```Delphi:FD_PostgreSQL15_b_Unit.pas
procedure TForm1.SpeedButton7Click(Sender: TObject);
var
  SQLstmt:String;
begin
  with FDConnection1 do
  try
    SQLstmt := 'SELECT * FROM test_tbl '
            +  'WHERE ts_no = :ts_no';
    FDQuery1.SQL.Clear;
    FDQuery1.SQL.Text:= sqlstmt;
    FDQuery1.ParamByName('ts_no').AsInteger:=StrToInt(Edit_ts_no.Text);
    FDQuery1.Open();
    if not FDQuery1.Eof then
    begin
      Edit_ts_no.Text  :=IntToStr(FDQuery1.FieldByName('ts_no').AsInteger);
      Image1.Picture.Assign( TBLOBField(FDQuery1.FieldByName('tsblob') ) );    //保存した画像ファイルを表示
    end;
  finally
    FDQuery1.Close;
  end;
end;
```


##### 画像データの追加のポイント
　FDQuery1.ParamByName(フィールド名).LoadFromFile( 画像ファイル名 ,ftBlob);
　FDQuery1.ParamByName('tsblob').LoadFromFile( Edit_Files.Text ,ftBlob);

##### 画像データの表示のポイント
　Image1.Picture.Assign( TBLOBField(FDQuery1.FieldByName('フィールド名') ) );
　Image1.Picture.Assign( TBLOBField(FDQuery1.FieldByName('tsblob') ) );


***
##### 簡単な、サンプルですが、画像をいままで、あまり扱ってこなっかったので、実行するのに時間がかかりました。
##### 開発言語の人気の順位は、疑問対する解答(実現したいことに対すのサンプル)の多さでも、決まるような気もしますので、簡単なコードですが、多少なりともDelphi界隈の貢献となれば幸いです。

#### もう少し細かい手順とソースのダウロードは、ここからできます
http://a23.sblo.jp/article/189966773.html
【解決】Flask RuntimeError: Working outside of application context.  This typically means that you attempted to use functionality that needed the current application. To solve this, set up an application context with app.app_context(). 

# エラー
SQLalchemyを使ってデータベースを作成しようとしたところ以下のようなエラーを吐かれて次に進まない状態に、、、

```
RuntimeError: Working outside of application context.

This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.
```

# 解決方法
ターミナルで以下のコマンドを順に実行してみましょう！
```:ターミナル
% python
>>> from app import app
>>> from app import db
>>> with app.app_context():
...    db.create_all()
>>> exit()
```
これで解決しました！

### 注意！！
```
>>> with app.app_context():
...    db.create_all()

```
の2行目はtabキーでインデントを揃えるようにしてください！

# 最後に
いかがでしたでしょうか？
少しでも誰かの助けになっていれば幸いです！
【超簡単】Rails 公開・非公開投稿 実装方法

# はじめに
Twitterライクのようなアプリを作成してみたが、投稿を公開・非公開できるようにしたい・・・！という人に向けて執筆します！

# 完成形
下記の写真のように、公開非公開ボタンを作成し、公開を押して投稿すると全員にその投稿が表示され、非公開を押して投稿すると全体には表示されないが、マイページに自分だけが見れる投稿が作成される仕組みを作ります！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/5130136f-2606-005c-a98a-9632b959b850.png)

# 公開か非公開かを判定するためのカラムを追加しよう！
```ターミナル
rails g migration AddreleaseToテーブル名 release:integer
```

```ターミナル
rails db:migrate
```
該当するコントローラーの最後の方の行にparams〜とあると思います！
そこに,:releaseをつけたそう！
```rb:コントローラー
    params.require(:tweet).permit(:body,:title, :image,:release)
```
# 新規投稿ページ
以下のコードを<%= form_for 〜 do |f| %> 〜 <% end %>の間に挿入します！
```html:new.html.erb
 <div class="form-check form-check-inline">
   <%= f.radio_button :release, '1' ,class:"form-check-input mb-3" %>
   <%= f.label :release, '公開', value: 1 %>
 </div>
 <div class="form-check form-check-inline">
   <%= f.radio_button :release, '0',class:"form-check-input mb-4" %>
   <%= f.label :release, '非公開', value: 0 %>
 </div>
```
# 一覧ページのコントローラー
```rb:tweets_controller.rb
def index
 @tweets = Tweet.where(release:1).order(id: "DESC")
end
```
このwhere分が今回の鍵です！
where(カラム名：値)とすることで、特定のレコードを取得することができます！
今回はreleaseカラムの値が1、つまり公開する投稿のレコードを取得しています！

# 一覧ページのview
```rb:index.html.erb
<% @tweets.each do |t| %>
    <%= t.title %>
    <%= t.body %>
<% end %>
```
# マイページのコントローラー
```rb:users_controller.rb
def show
    @user = User.find(params[:id])
end
```

# マイページのビュー
```rb:show.html.erb
<%if current_user.id == @user.id %>
    <% @user.tweets.each do |t| %>
        <%= t.title %>
        <%= t.body %>
    <% end %>
<% else %>
    <% @user.tweets.where(release:1).each do |t| %>
        <%= t.title %>
        <%= t.body %>
     <% end %>
<% end %>
```
if文にて条件分岐しています！
もしログインしているユーザーがマイページのユーザーと一致していれば、自分の投稿を全部表示
そのほか(ログインしているユーザーとマイページのユーザーが違っているとき)の場合、そのページのユーザーの公開の投稿のみ表示
というわけです！

# 最後に
いかがでしたでしょうか？
ほかにももっといい書き方があると思うので、コメントなどで教えていただけるとありがたいです！
ここまで読んでいただきありがとうございました！
少しでも力添えできていたなら幸いです！
【裏技】生産性爆あがり Googleドキュメント,スプレッドシート 簡単に新しいページを開く方法

# はじめに
Googleドキュメントやスプレッドシートの新規ページを作成したいとき、わざわざドキュメントページに行ったりスプレッドシートのページに行ったりしていませんか？？

今回はそういった人に向けて必殺の裏技を伝授します！

# これだけ！
お使いのブラウザの検索バーに
```
doc.new
```
と打ってエンターを押してみてください！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/b80661d5-1d20-2fce-ab02-bd3fa388ff98.png)

これだけで新しいドキュメントを開くことができます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/d55165e6-e493-34b7-f135-6ee19f0fbc85.png)


スプレッドシートの場合
```
sheet.new
```
Googleスライドの場合
```
slide.new
```
Googleフォームの場合
```
form.new
```

いかがでしたでしょうか？？

# 最後に
一回あたりたかが10秒ほどの差ですが、塵も積もれば山となるです！
是非是非積極的に今回の必殺技を使って依位多くの時間を生み出しましょう！
【超簡単】Excel・スプレッドシートでアンケートの回答状況を確認する方法

# はじめに
アンケートを集めるものの、誰が提出していて、誰が提出していないかを確認するのが手間！って方多いのではないでしょうか？

今回はそういった人に向けて、簡単に誰が提出していて誰が提出していないかを確認するための方法を伝授します！

# 完成形
以下の写真のように、名簿から未提出者に色をつけることが今回目指すものです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/e3aee55f-74c8-03dc-8cba-7e182bfa5c9e.png)
※ こちらの名簿は以下のサイトからお借りしました。

http://mw211.com/tekito/tekito01.htm

また実際の完成形スプレッドシートも以下に載せておくのでぜひご確認ください！

https://docs.google.com/spreadsheets/d/1mwXMG8534N31__e-K-ygA28RKHl2Ly3-1li6d75bsx0/edit#gid=1103384671

# 実装方法
① 以下のスプレッドシートをコピーしてください

https://docs.google.com/spreadsheets/d/1mwXMG8534N31__e-K-ygA28RKHl2Ly3-1li6d75bsx0/edit#gid=1103384671

ファイル→コピーを作成 で作成できます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/9214ef90-c443-a90d-18c8-c8dd7b0e0af9.png)

コピーを作成できたら、シートの一番下に三つのシートがあることを確認してください！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/5ac7ce95-06ff-64f1-aba2-4fccbea2af48.png)

<シート説明>
名簿→今回出欠アンケートを提出するべき人が載っているシートです
アンケート回答→こちらが今回の出欠アンケートの結果です
提出状況→こちらが今回完成を目指すシートの見本となります！

② 新たなシートを作成してください
左下のプラスボタンを押すとシート4が作成されます！何かしらのシートが作成されたことが確認できればOKです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/22bd97d5-86ba-8c54-0877-7ced6b6f8717.png)

③ 項目を記入
A1セル,B1セルに項目を記入しましょう！
今回はA1セルを名前,B1セルを提出状況としています！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/668aab13-e030-2194-daf8-f98392892b90.png)

④ 名簿から名前を取得しましょう！
A2セルに以下の関数を埋め込みます！
```
=ARRAYFORMULA('名簿'!B2:B)
```
下のようになっているはずです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/fcbdd9a9-dee7-8822-d11d-8a68e49312da.png)

⑤ 提出しているかどうかcountifで判定！
以下の関数をB2に埋め込みましょう！
```
=COUNTIF('名簿'!B:B,A2)
```
解説
```
countif(カウントしたい範囲,カウントしたい値)
```
今回は、名簿からアンケート回答されているかどうかを確認したいため、カウントしたい範囲は、名簿シートのB列となり、カウントしたい値は、作成中のシートの名前となります！

以下のようになっていれば成功です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/3ed864b5-f5df-4308-b74b-9330cfa7cac6.png)

アンケート回答シートに名前があれば(アンケートを提出していたら)1,アンケート回答シートに名前がなければ(アンケートを提出していなかったら)0が表示されます！

⑥ 提出していれば提出済み、未提出なら未提出と表記されるようにしよう！
先ほど関数を埋め込んだB2セルを以下の関数に書き換えましょう！
```
=if(COUNTIF('名簿'!B:B,A2)>=1,"提出済み","未回答")
```
解説
```
=if(条件,条件一致した時に返す値,それ以外の時に返す値)
今回は、第一引数が COUNTIF('名簿'!B:B,A2)が1以上の時、つまりA2(アンケート回答者)が'名簿'!B:B(名簿の中の人)と一致したら、第二引数が "提出済み"、不一致ならば 第三引数が"未回答"と表記
```
以下のようになっていたら成功です！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/d62e519e-6211-4c79-18ad-d6987e2cc259.png)

⑦ 全員の提出状況を確認しよう！
B2セルに埋め込む関数を以下に変更しましょう！
```
=ARRAYFORMULA(if(COUNTIF('アンケート回答'!B:B,A2:A30)>=1,"提出済み","未提出"))
```
ARRAYFORMULAに関しては説明が長くなるので、気になる方は調べてみてください。

⑧ 未提出者にわかりやすく色付けしよう！
表示形式→条件式書式から
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/880f206b-53fc-89c8-ca8c-fe7b0521ec1f.png)

条件式書式を以下の写真のように設定しよう！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/04ef3488-3d51-4dec-8406-dc4ca1305bb3.png)

これで完成です！

# 最後に
スプレッドシートでできることはほかにもたくさんあります！
関数を勉強してみてたくさん組み合わせて、自分が作りたいものを実装できるようになるまで練習しましょう！
【学習ノート】BIツールについて

# 基本情報

### BIツールとは
1. 企業が持つさまざまなデータを分析・見える化して、経営や業務に役立てるソフトウェアのこと。 

2. BIはビジネスインテリジェンス、つまり、ビジネスの意思決定に関わる情報という意味

3. BIツールの価値はさまざまなデータから、行動に移すことが可能な知見を得られることにある。ITを活用してデータを収集・分析してその結果をレポートの形でグラフや図表でわかりやすく表現できることにある

4. 企業活動の中で日々蓄積されるデータは、しばしばビッグデータと呼ばれるほど膨大になり、ばらばらの場所や別々のシステムに保存されていることも多いため、一般的な表計算ツールで分析しようとすると不正確になってしまったり、データ分析の知識を持った専門職が必要になったり、時間がかかりすぎてBIを作成できた頃にはビジネス環境が変わったりしている。

### 目的・役割

膨大なデータから必要な情報を引き出し、経営や売り上げ拡大に活用するために、分析してレポーティングすることであり、誰にでも利用できることに意味がある。いちいちExcelで手集計する必要がなくなり、非常に便利なツールです。知りたいことが浮かんだときに、パッとデータを集計し、分析結果が表示されれば、それほどありがたいことはない。意思決定にはスピードが求められるため、例えば「ところで、あのデータ集計の結果はどうなった？」と業務に追われる集計担当者をせかす必要もなくなる。

##### 活用シーン

・経営分析・財務分析
・営業分析・売上分析
・人事データ分析
・残業分析
・予算管理システム
・データ集計

### メリット

1. 社内のデータが集約され管理しやすくなる
2. レポートを作成する手間が省ける
3. 迅速な軽々判断ができる
4. 一般社員が資料を作成する手間と時間を軽減することが可能
5. 各部署の現状を一目で確認できる
6. 社内で事業の進捗を共有できる
7. 専門家に頼らず必要なデータを抽出・分析・加工することが可能
8. 専門部署のシステムを横断してデータを分析できる

### デメリット
1. 慣れ親しんだこれまでの方法からBIツールという新しい方法に変えることで、設定に手間がかかったり、操作や画面に慣れる必要があるという。結果、BIツールを導入したものの、活用しきれず失敗に終わってしまう企業もある
→ こういった事態を避けるには、BIツールの中でもセルフサービスBIと呼ばれる専門知識のないユーザーだけで使うことを前提に作られたものを利用する方法が有効である。

2. 一定の費用がかかる
企業が利用するに値する、無料のBIツールはどこも提供していないが、一般的に無料ツールを利用するということには、リスクがある。
そのリスクとは、利用企業がアップロードした情報を、ツール提供企業が加工して販売したり、それのデータをもとに広告配信するなど、導入企業が本来、自社の競争優位性を生み出すために活用するべき貴重なデータが、外部で活用されてしまう

3. 導入するとやめにくい

### 種類
BIツールは、レポーティングツール・OLAP分析ツール・データマイニングツール・プランニングツールの四つに分けられる。

##### 1. レポーティングツール
・ いかに素早くタイムリーに問題の兆候を発見できるかを目標とするツール
・ 企業のあらゆる活動のリレ区データからパフォーマンスを計測し、監視する

##### 2. OLAP分析ツール
・問題の要因を深く掘り下げ、検証を行うことを目的とする
・Online Analytical Processingの略であり、蓄積したデータベースを様々な角度から解析して問題点や解決策を発見する
・使用結果 ある店舗で突出した売上の要因が、同日の近くのイベント開催であったことが判明した

##### 3. データマイニングツール
・問題への対処のヒントを得るために使用されるもの
・対処のヒントを得るために、様々なデータから、使えそうな道の関係や傾向などを探して分析する。クロス分析・相関分析・回帰分析という手法が取られ経営においてはこれらの分析データを用いて対処策を実行する

・使用結果 休日のネットショップ利用者数が大幅に減少していた。この問題に対して、データマイニングツールの分析結果により、その要因nの一つとして、天気や時期に密接に関係していることがわかった

##### 4. プランニングツール
・経営層による予算編成に役立つツール。計画の根拠を得るために使用される。過去実績の分析や趣味レーションを通して、予算計画などに活用する

・使用結果 : トップダウン予算を作成する際に、為替や需要の予測を行い、全体の利益や売上がどうなるかをシミュレーションできるようになったため、予算計画がより具体的で確実生を帯びるようになった

### 参考サイト
https://bi.lakeel.com/course/detail01/ 
https://it-trend.jp/bi/article/explain
https://www.justsystems.com/jp/lab/bi/business-intelligence.html
【学習ノート】無料で使えるBIツール 4選

# BIツールとは
1. 企業が持つさまざまなデータを分析・見える化して、経営や業務に役立てるソフトウェアのこと。 

2. BIはビジネスインテリジェンス、つまり、ビジネスの意思決定に関わる情報という意味

3. BIツールの価値はさまざまなデータから、行動に移すことが可能な知見を得られることにある。ITを活用してデータを収集・分析してその結果をレポートの形でグラフや図表でわかりやすく表現できることにある

4. 企業活動の中で日々蓄積されるデータは、しばしばビッグデータと呼ばれるほど膨大になり、ばらばらの場所や別々のシステムに保存されていることも多いため、一般的な表計算ツールで分析しようとすると不正確になってしまったり、データ分析の知識を持った専門職が必要になったり、時間がかかりすぎてBIを作成できた頃にはビジネス環境が変わったりしている。


# 無料BIツールまとめ

## 1. Googleデータポータル

特徴
Googleが提供するBIツール
Google内のデータを一箇所に集約できる
Google内のデータをさまざまな角度で分析できる

##### メリット
ノンプログラミングでデータ取得可能
ドラッグ&ドロップでレポート、ダッシュボード作成可能
Googleドライブで共有可能

##### デメリット
レポートの上限が1ユーザー5個 (2017年2月上限が撤廃されました)
印刷機能がなくweb閲覧のみ
異なるソースからのデータの合算描画と計算機能はなし
アドホックな分析には不向き
##### 利用可能DB・ファイル
Google AdWords、アトリビューション 360、BigQuery、Cloud SQL、Google アナリティクス、Google スプレッドシート、MySQL、YouTube アナリティクスなど
##### サイト
https://marketingplatform.google.com/intl/ja/about/data-studio/
## 2. ペンタホ
##### 特徴
プロフェッショナル向けに作られたオープンソースBI
先端技術が迅速に取り入れられ、データ統合、データマイニング、レポーティングなど、基本的な機能は充実しているが、英語のみになっている
##### メリット
インタラクティブでビジュアル化された対話型の分析手法
多様なれポーティングが可能
先進的な分析手法のライブラリ
専門的なビジュアライズプラグインでビジュアルかしたレポート作成が可能
##### デメリット
無料版はインストーラーがなく、ツールをここにサーバーとクライアントにインストールする必要がある(一定の技術・知識が必要)
無料版はダッシュボードのカスタマイズが不自由
無料版は、一般的なMySQLではなく、HSQLDBを使用
基本的なプログラミングの知識がないと利用が難しい
## 3. Metabase
現在開発されているオープンソースソフトウェアのデータ可視化ツール。分析機能自体は強くないが、データをわかりやすく可視化することで、データ分析の補助的なツールとして活用することができる
##### メリット
グループごとにデータソースのアクセス権が設定できる
ActiveDirectoryと連携できる
全13種類のデータベースをグラフか・可視化
##### デメリット
開発されて間も無く、バグが多い
データベースの参照のみで保存ができない
専門用語が多く、操作の理解に時間がかかる
##### 利用可能DB・ファイル
BigQuery (GCP)、Druid、Google Analytics、H2、MongoDB、MySQL、PostgreSQL、Presto、Redshift (AWS)、Snowflake、Spark SQL、SQL Serverなど

## 4. Microsoft Power BI
マイクロソフトが開発したBIツール「パワーBI」。マイクロソフトの車内ではメールソフトよりも頻繁に使われていると言われている。使い慣れたエクセルのような操作感で簡単にデータ分析をし、PowerPointのようにレポート作成ができ、ブラウザやスマートフォンでの閲覧もできる
##### メリット
プログラミングをせずにダッシュボードやレポートを作成可能
モバイルやwebで閲覧可能。アプリも用意されている
ビジュアル性の高いれポーティング、ダッシュボード作成
GoogleアナリティクスやFacebook、SalesforceなどのSaaSにも対応
データソースからの定期更新が可能(ただし無料版は1日ごと)
##### デメリット
無料では容量が1GB/ユーザーと少ない
無料版では他のアカウントのレポートの共有や共同編集ができない
無料版では、オンプレミス上にあるデータベースのデータを取り扱うことができない
無料版はアクセス制御できない
##### 利用可能DB・ファイル
Web ページ内の Table タグや URLアクセスが可能なファイル（Excel や CSV、XML、JSON、Text など）、Hadoopファイル（HDFS）、SQL Server、Oracle、DB2、MySQL、PostgreSQL、ODBC、Teradata、Sybase、Access、MicrosoftAzure 上の各種サービス（AzureSQL Database、AzureSQL Data Warehouse、Azure HDInsight、BLOB／テーブル ストレージ、Marketplace）、Active Directory、Salesforce、GitHub、SweetIQ、Google Analytics、Twillio、QuickBooks、Facebook、Zendesk、OData、Exchange、SharePoint リスト、Dynamic CRM など

# 最後に
無料版で使うとしたら現時点では、Googleデータポータルが一番良さそうではないでしょうか？
不備等ございましたらコメントにて教えてくださるとありがたいです！
GUI改造4 up変更

「instantNeRFで遊ぶ Advent Calendar 2022」の8日目です。

今日はup directionについて調べてみました。

:::note
業務外の個人的な検討活動です。
:::

:::note alert
警告
環境や入力内容によっては現在使用できている状況が壊れることがあります。
あなたの責任と判断で試してください。私は責任を取りません。
:::

#### transform.json
upの名前で指定できます。
![8-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/7066759f-519e-a5e1-cfc7-bd800de23122.png)

#### testbed.exe 従来
マウスの右ボタンを押しながらマウスを動かすとモデルの向きを変更できますが、upの設定内容によっては動かしにくい場合があります。

挙動を調べた結果です。
黄色の矢印がドラッグした方向、赤・緑・青色の矢印がそのときのモデルの動きです。
![8-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/dca7d3b3-4090-4565-0b25-d776fcdd10d2.png)
upを[0,1,0]にしたとき、左右と上下にドラッグしたときのモデルの回転軸が重なっていました。

#### nerf_loader.cu
transform.jsonのupが読み込まれる部分のコードを見ました。
![8-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/adb0b383-f630-d822-8509-4b501bc5c1cc.png)
yがx, zがy, そしてxがzに代入されていました。
したがって、[0,1,0]は[1,0,0]になりますので、マウスの上下のドラッグが左右のドラッグと重なってしまうようです。

#### testbed.cu
upはcolmap2nerf.pyの中で変更されます。
結果的に変換後の姿勢は出たとこ勝負になってしまうので、今回のようにモデルが横倒しになってしまうことがあります。

下記の部分を追加し、testbedの実行中にモデルの姿勢を変更できるようにしました(正確にはカメラの向きを変える座標かもしれません)。

![8-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/4782e3a0-ab1e-23da-110e-bfef4db8a1ea.png)

```
			int up_dir;
			if (m_up_dir.x() == 1) up_dir = 0;
			if (m_up_dir.y() == 1) up_dir = 1;
			if (m_up_dir.z() == 1) up_dir = 2;

			ImGui::Text("mouse left-right: "); ImGui::SameLine();
			accum_reset |= ImGui::RadioButton("u1", &up_dir, 0);	ImGui::SameLine();  ImGui::TextColored({ 0.95f, 0.05f, 0.05f, 1.0 }, "x");		ImGui::SameLine();
			accum_reset |= ImGui::RadioButton("u2", &up_dir, 1);	ImGui::SameLine();  ImGui::TextColored({ 0.05f, 0.95f, 0.05f, 1.0 }, "y");		ImGui::SameLine();
			accum_reset |= ImGui::RadioButton("u3", &up_dir, 2);	ImGui::SameLine();  ImGui::TextColored({ 0.05f, 0.05f, 0.95f, 1.0 }, "z");
			ImGui::Text("mouse up-down: "); 						ImGui::SameLine();  ImGui::TextColored({ 0.95f, 0.05f, 0.05f, 1.0 }, "x");

			if (up_dir == 0) m_up_dir << 1, 0, 0;
			if (up_dir == 1) m_up_dir << 0, 1, 0;
			if (up_dir == 2) m_up_dir << 0, 0, 1;
```

#### testbed.exe 変更
赤枠で示した部分のラジオボタンが追加されました。
crop aabbを開いてGuizmoを表示していると、回す方向が見えやすくなってさらに便利です。
![8-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/cb70ab01-a4c5-a59c-1ea5-fb225184ba4f.png)


参考

https://qiita.com/Ushio/items/446d78c881334919e156#imgui%E3%81%A8%E3%81%AF

https://github.com/NVlabs/instant-ngp/issues/72