OmniAICreator/Qiita-1.07M huggingface dataset:
ローカルLinux⇔リモートLinuxでのファイルコピー

パーミッション問題が発生するので回避方法
OPCセグメント→AWSセグメントにトンネルを経由して送受信
ファイルをAWS→OPCにコピー

1.ログイン経路を確保。（１行で到達する方法）
myproject-web.pemを用意した上で
ホームディレクトリ/.ssh下にconfigを作成で1行でsshログインできます。
（ex./root/.ssh/）

「パーミッション：600」にする
↓中身

~~~python:config
#OCI-0_205
Host oci_ope_web
  Hostname 10.0.0.205
  User opc
  IdentityFile ~opc/.ssh/id_rsa

#AWS-0_205
Host ope_web
  Hostname 106.133.79.64
  User ec2-user
  IdentityFile ~opc/myproject-web.pem
  ProxyCommand ssh oci_ope_web -W %h:%p

#AWS-0_206
Host ope_web_stg
  Hostname 10.0.0.206
  User ec2-user
  IdentityFile ~opc/myproject-web.pem
  ProxyCommand ssh ope_web -W %h:%p

#AWS-1_035
Host ope_db1
  Hostname 10.0.1.35
  User ec2-user
  IdentityFile ~opc/myproject-web.pem
  ProxyCommand ssh ope_web -W %h:%p

#AWS-1_036
Host ope_db2
  Hostname 10.0.1.36
  User ec2-user
  IdentityFile ~opc/myproject-web.pem
  ProxyCommand ssh ope_web -W %h:%p
~~~
「ssh db1」でope_webへのログインを手作業で経ることなくAWS内の10.0.1.35にダイレクトログイン。

参考にしたURL
SSHコマンドで多段接続する方法(config設定、秘密鍵利用)
https://rurukblog.com/post/ssh-multi-stage/

他の方法でもトンネルを掘る方法はあります。
👇
踏み台で sudo -u しているsshでの ssh_config
https://qiita.com/shase428q/items/c796188b9840eaec9ead
踏み台サーバを飛び越えて一発で目的のサーバへsshする方法
https://qiita.com/hkak03key/items/3b0c4752bfbcc52e676d

2.到達先でのroot権限を確保。（通常のやり方では「1.」でログインした平ユーザーでの権限になってしまう）
ローカルLinuxでは「sudo su」でroot化。
リモートLinuxでは「rsync」のオプションを使いroot権限で読み・書きする。
#プロンプトはrootにて実行している状態

AWS内での205（まず２つファイル作成）

```
[root@ip-10-0-0-205 ec2-user]# ll who-am-i*
-rw------- 1 ec2-user ec2-user 13 Jun 16 10:36 who-am-i0616a.txt
-rw------- 1 root     root     15 Jun 16 10:36 who-am-i0616b.txt
[root@ip-10-0-0-205 ec2-user]# pwd
/home/ec2-user
[root@ip-10-0-0-205 ec2-user]#
```
OPC内での205（↑で作った２ファイルのパーミッションを変えずに持ってくる）

```
[root@0205oci_opeweb opc]# ll who-am-i0616*
ls: cannot access 'who-am-i0616*': No such file or directory
[root@0205oci_opeweb opc]# rsync -arp --rsync-path="sudo rsync" ope_web:/home/ec2-user/who-am-i0616a.txt /home/opc
[root@0205oci_opeweb opc]# rsync -arp --rsync-path="sudo rsync" ope_web:/home/ec2-user/who-am-i0616b.txt /home/opc
[root@0205oci_opeweb opc]# ll who-am-i0616*
-rw------- 1 ec2-user ec2-user 13 Jun 16 10:36 who-am-i0616a.txt
-rw------- 1 root     root     15 Jun 16 10:36 who-am-i0616b.txt
[root@0205oci_opeweb opc]# pwd
/home/opc
[root@0205oci_opeweb opc]#
```
↑所有者とグループがec2-userになっているファイルはそれぞれopcに変更する必要がありますが、リスキーな手間は無くなるかと思います。

参考URL
root権限でrsyncを実行する
https://ex1.m-yabe.com/archives/6104
（👇コチラも参考になります。）
「SSHホスト鍵が変わってるよ！」と怒られたときの対処
https://qiita.com/hnw/items/0eeee62ce403b8d6a23c

練習として作ったコマンド
```
rsync -arp --rsync-path="sudo rsync" ope_web:/home/ec2-user/who-am-i0616a.txt /home/opc
rsync -arp --rsync-path="sudo rsync" ope_web:/home/ec2-user/who-am-i0616b.txt /home/opc
```
Concrete CMS タスク設定方法 (Plesk 編)

Concrete CMS version 9 から搭載されているバッチ処理を行う「タスク機能」。

サーバー側の Cron でも設定する必要がありますが、Plesk では、PHP のバージョン切り替えが特殊で、 Cron の設定がややこしかったので、手順に書き残しておきます。

確認済み Plesk: 18.0.57

設定の詳細方法は「[Concrete CMS タスク設定方法: Cron版 (V9 以降)](https://qiita.com/katzueno/items/ad7598565f4909c697ae)」をご覧ください。

# タスク設定例

Plesk で設定する方法だけ共有します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44367/5711a530-f321-3fe4-a22b-e185549e90a3.png)

Concrete CMS がインストールされているフルパスをあらかじめ取得して、以下のコマンドの `concrete/bin/concrete` の位置を差し替えてください。

## スケジューラー

項目 | 設定値
-----|--------
タスクタイプ | コマンドを実行
コマンド | `/opt/plesk/php/8.2/bin/php -f /var/www/vhosts/ドメイン/concrete/bin/concrete concrete:scheduler:run`
説明 | `concrete:scheduler:run`
通知 | `通知しない`

## コンシューマー

項目 | 設定値
-----|--------
タスクタイプ | コマンドを実行
コマンド | `/opt/plesk/php/8.2/bin/php -f /var/www/vhosts/ドメイン/concrete/bin/concrete messenger:consume async --time-limit=55`
説明 | `messenger:consume`
通知 | `通知しない`


# こぼれ話: Plesk の SSH で PHP バージョンを切り替える方法

Plesk サーバーに SSH で入り、PHP を実行しようと思っても、サーバーにデフォルトで入っている PHP バージョンしか実行できません。RHEL 7 ベースだと、PHP 5.3 と超古い PHP になってしまいます。

その時実行するのが、以下の CLI コマンドです

```
# 変更したい PHP のバージョンを入れる
phpenv shell 8.2
```
[EA億り人計画 序章]自動売買プログラム（EA）を自作して、億り人になるために色々調べてみた

## 経緯
＼おかねがほしい／

嫁「なんでお金無いの？もう私がやる！私があなたより稼いだら、離婚する！」

このまま稼がなければ、オヨメチャンとの関係が危ういが、
オレタマがめっちゃ稼げるようになって、オヨメチャンもハッピーになれば、
もっとたくさんの人を幸せにできるジャマイカ！！！！

### 動機

* 安心して開発に取り組むには、お金の心配をしなくていいほうが集中できる。
* 資産形成をし、「インフレがー、年金がー、税金がー」とか何も心配しなくていい幸せな世界へ行きたい
* 自分たちだけでなく、周りのすべての人をなるべく幸せにしたいが、それにはお金があるととても楽ですよNE!

## 調べたこと

### 自動売買プログラムについて
* 自動売買プログラムは350ドルとかで誰かが作ったものを買うこともできるが、自分でも作れる
* MQL言語というので書けばいいらしい
* そもそもテクニカル指標について知って、どのようなテクニカルを用いるかは自分で考えて決める必要がある
* MT5というトレーダー向けのアプリケーションで自動売買プログラムが動くらしい
* MT4とMT5があるが、MT5の方ができることが多いらしい
* 自動売買中はMT5（メタトレーダー５）というソフトを常駐させる必要がある
* MT5はwindows版がメイン、mac版はおまけ。しかも自動売買中は、安定して起動させておく必要がある
    * 本番口座はクラウドサーバーとかで運用すると良さそう。我が家やわが町は停電がそこそこあるので。。。

### 口座や対象について
* 自動売買に向いた、テクニカルに素直な銘柄を選ぶ（急騰や急落、為替介入、突発的なニュースが大きなリスクとなることがあるため）
    * 稚拙なアイデアではUSD/JPYや金/USDが良さそう、日経先物とかの指数系でも良いかもしれない。
* MT５の自動売買に対応した口座を選ぶ必要がある
* たいていデモ口座があるので、安心してテストできる

### 海外業者か国内業者か
* 海外業者＝ハイリスクハイリターン
    * レバレッジが無制限
    * 相場が予想と逆行した場合、ロスカットが預け金の率0%でのカット
    * 申告分離課税が無く、総合課税のため、１億円稼ぐと半分税金になる

* 国内の業者＝ローリスクローリターン
    * レバレッジ２５倍が制限
    * 預け金の100%を下回ったらロスカットされる←少し運ゲー
    * 申告分離課税があるため、一律20.315%で済む。

### どのぐらい稼げば1億円になるか

レバレッジ２５倍でどのぐらいの期間で稼ぐのを目標にすればよいかを考えてみる。

#### 妄想(理論的なお遊び）

* １００万円あったとして、25倍のレバレッジで資金を２倍にするには、同じ１００万円稼ぐ必要がある。
* １００万円の２５倍＝2500万円を２６００万円にすれば資金が２倍になるので、1.04倍にすれば良いので、１ドル１５０円が１５６円になる＝6000pipsを稼ぎ出せばよいはず
* 6000pipsを一度に稼ぐのではなく、デイトレードでも比較的取りやすい100pipsを６０回と考える。
* １回に100pips〜200pips稼ぐことにして、一日最低１２回を５日間繰り返せば、１週間で２倍となる。

＝つまり、４週間で１６倍

１００万円あれば、１ヶ月で1600万円、２ヶ月で2億5600円

今日はここまで。つづく。
PrismaとTypeScriptで実現する、PostgreSQLでのFOR UPDATEと集約関数との同時利用法

今回はTypeScriptとPrismaを用いた例を中心に、PostgreSQLでロックとデータの集約を同時に行う方法について解説します。

PostgreSQLでは、`FOR UPDATE`と集約関数を同時に使用することが許可されていません。

しかし、一時的なテーブルを作成することで、この問題を効果的に回避することが可能です。

その一つの方法として、Common Table Expression（CTE）を使用する手法をここでは紹介します。

## 集約関数とは？
集約関数は、複数のレコードを一つにまとめる関数です。

PostgreSQLでよく使われる集約関数には、例えば`SUM`（合計値を求める）や`COUNT`（レコード数を数える）などがあります。

これらの関数を用いると、特定の条件を満たすレコードの合計値や数を手軽に計算することができます。

## FOR UPDATEとは？
PostgreSQLでは`FOR UPDATE`を使うことで、一連のトランザクションを行う際に、選択したレコードを他のトランザクションから隔離することができます。

この機能により、あるトランザクションがそのレコードを変更または削除するのを防ぎます。

しかし、PostgreSQLでは、`FOR UPDATE`と集約関数を直接組み合わせることは出来ません。

そのため、集約処理とロックを同時に行いたい場合には、別の手法を用いる必要があります。

## Common Table Expression (CTE)とは？
Common Table Expression（CTE）はSQLの一部で、一時的な結果セットを生成します。

CTEは、名前をつけたサブクエリのようなものであり、その結果はその後のクエリの中で再利用することができます。

CTEを使うと、複雑なクエリをより読みやすく、管理しやすい形に分解することが可能になります。

## Common Table Expression（CTE) を使用する例
まず、CTEを使用せずに`FOR UPDATE`と集約関数を用いるケースを考えてみます。

指定した商品IDに対して対象となる全レコードを選択しようとすると以下のようなコードになります。

```typescript
const inventoryEntries = await tx.$queryRaw`
    SELECT * FROM "Inventory" WHERE "itemId" = ${id} FOR UPDATE;`;
```

これでレコード全体がロックされ、選択したレコードを他のトランザクションから隔離することができます。

ただし、この方法では全てのレコードを取得しているため、レコードの数が非常に多い場合には時間がかかることが懸念されます。

一方、CTEを使用すると選択したレコードの集約を効果的に行うことができます。

まず一つ目のクエリで目的の商品を抽出し、その結果を一時的なテーブルに保存します。

そして二つ目のクエリでそのテーブルのレコード数を数えます。

そのコードは以下の通りです。

```typescript
const result = await tx.$queryRaw`
  WITH "temporaryTable" AS (
    SELECT "itemId" FROM "Inventory" WHERE "itemId" = ${id} FOR UPDATE
  ) 
  SELECT COUNT(*) FROM "temporaryTable";
`
```
上記のCTEを使用したアプローチにより、大量のレコードデータを一度に取得することなく、必要な数を効率的に得ることができます。

## まとめ
アプリケーションのパフォーマンスは、必要なデータのみを効率的に操作することにより向上します。

この方法は、データ量が非常に大きい際に、データ抽出と集約処理を効率的に行うための有効な手段となります。
バッチサイズの定義と学習に及ぼす性質について

# はじめに
　Imitationの模倣学習モデルを動かす際、batch_sizeの項目が存在したがその値が何を意味するのか分からなかったためバッチサイズについてまとめました。バッチサイズについて簡潔にまとめると、
<dl>
<dt>バッチサイズの定義</dt>
<dd>データセットをいくつかのグループ（バッチ）に分けた際の、ひとつあたりのサイズ。
バッチサイズ＝データサイズ/イテレーション</dd>
<dt>バッチサイズの性質</dt>
<dd> <table border="1">
    <tr>
      <th>バッチサイズ</th>
      <th>トレーニング時間</th>
      <th>学習精度</th>
    </tr>
    <tr>
      <td><strong>大</strong></td>
      <td><font color="red">短い</font></td>
      <td>低い</td>
    </tr>
    <tr>
      <td><strong>小</strong></td>
      <td>長い</td>
      <td><font color="red">高い</font></td>
    </tr>
  </table></dd>
  となります。それぞれの用語や理由について以下でまとめていきます。
  
## 1.バッチサイズの定義について
　バッチサイズとはデータセットをいくつかのグループに分割した際の一つあたりのサイズのことです。
　機会学習における勾配降下法などでは、学習するデータセットをいくつかのグループ（バッチ）に分けるのが一般的とされています。一つずつバラバラのデータで考えるわけでも、全てを一気に学習するのでもなく、適した一口サイズに区切って学習していきましょうというわけです。その一口がバッチサイズです。
　具体例として、データサイズ4000のデータ（例えば4000枚の画像）を10個のグループに分けて学習させていくことを考えます。このとき、バッチサイズは4000/10=400ということになります。
 　ここで、分割数「10」のことを専門用語でイテレーションと呼びます。よって、上の具体例を用語になおすと、
  **・データサイズ/イテレーション＝バッチサイズ**
　ということになります。
 　バッチサイズの意味がわかったところで、このパラメータをどのように扱っていけばいいのでしょうか。この問題に答えるため、バッチサイズが持つ性質について次節で説明していきます。
  
  *※注意　”サイズ”と聞くと、メモリ的なサイズのことを想像しがちですが、ここでのデータサイズの単位はあくまで「個数」であり、ビットやバイトなどのメモリ単位ではないことにも注意が必要です。*

## 2.バッチサイズが持つ性質
　バッチサイズが持つ性質を知るために、バッチサイズの変化によって学習器の振る舞いがどのように変化するのかについて見ていきましょう。
　まずは学習器が行っている学習手順を以下に示します。
 
 １．データセットからバッチサイズ分のデータを取り出してくる
 ２．それらを一気に使い、現在のパラメータにてスコアを計算する。
 ３．スコア結果をもとにパラメータを変更する。
 
 　これをイテレーションの数だけ繰り返します。つまり、**学習の本質であるパラメータの更新はバッチごとでしか行われない**のです。ここにバッチサイズが持つ性質が隠されています。
　例えば、バッチサイズを100倍に大きくしたとき、パラメータの更新回数はそれまでの1/100で済むようになるため、学習にかかる時間も単純に100分の１とまではいかないにしても大幅に減らすことができます。その代わり、更新が少ない分データセットに対しての学習精度は低くなってしまいます。
 　反対に、バッチサイズを1/100に小さくすればそれまでの100倍のパラメータ更新を行うようになるので時間がかかる分学習精度の高い学習を行えるようになります。
　まとめると、
 <dd> <table border="1">
    <tr>
      <th>バッチサイズ</th>
      <th>トレーニング時間</th>
      <th>学習精度</th>
    </tr>
    <tr>
      <td><strong>大</strong></td>
      <td><font color="red">短い</font></td>
      <td>低い</td>
    </tr>
    <tr>
      <td><strong>小</strong></td>
      <td>長い</td>
      <td><font color="red">高い</font></td>
    </tr>
  </table></dd>
  となります。この性質を頭に入れた上で適切なバッチサイズを学習ごとに調べていく必要があります。
  
  # さいごに
　自分としては、データサイズ4000,学習回数(エポック数)1_000_000なら、単純掛け算で40億回のパラメータ更新をしているとばかり思っていました。バッチサイズも含めて更新の回数を様々なハイパーパラメータから調整していくことで、学習不足も過剰適合も起こさない適切に収束したパラメータを得ることができるようです。みんなで素敵なパラおじになっていきましょうね。
[.NET Framework/.NET].NET Frameworkと.NETの違い

# 環境
- Windows 11 Enterprise
# まとめ
- .NET:Windows向けのみでなく、macOSやLinuxなどさまざまなOSで動作するアプリケーションやWebサービスの開発環境
    オープンソースであるため無料で利用できるほか、必要な機能を選んでインストールが可能なため軽量なアプリケーション開発が可能。
- .NET Framework:Windows向けアプリケーションやWebサービスの開発環境
    プログラムの実行環境とライブラリ、フレームワークで構成されており、複数のプログラミング言語に対応可能。

### ※.NET は以前 .NET Core と呼ばれていたが、.NET5以降は.NETとなった。

# 詳細（.NET Framework/.NET共通機能）
### 1. CLR（共通言語ランタイム）
人間の書いたプログラムを特定のOS・機種に依存しない「マネージドコード」へ変換されたものが利用者に配布され、それをCLR（共通言語ランタイム）が実行可能なプログラムへと変換・実行できる。CLRにより異なるプログラミング言語で書かれたコードの相互運用が可能となり、開発者は対応言語の中から任意の言語を選び開発を進められる。
### 2. BCL（基本クラスライブラリ）
アプリケーション開発で頻繁に使用される機能をまとめたライブラリであり、BCLに保存されている基本クラスを用いれば、基礎的な部分を意識しなくても開発を進めていくことが可能となる。
### 3. FW（フレームワーク） 
Webアプリケーションのフレームワークである「ASP.NET」が備わっており、複雑なWebアプリケーションから簡単なWebサイトまで幅広く対応。簡単な操作でWebページを作成できるWeb Formsや、ユーザーとサーバーでデータをやりとりするアプリケーション構築が可能なWeb APIなども利用できる。

# 選び方（.NET目線）
- クロスプラット フォームが必要である。
- マイクロサービスが対象である。
- Docker コンテナーを使用している。
- 高パフォーマンスでスケーラブルなシステムが必要である。
- 1 つのアプリケーションに複数の .NET バージョンが必要である。

# 参考リンク
- [.NET Frameworkとは？基礎知識から「できること」まで徹底解説【2023年最新版】](ライブラリとフレームワークの違いとは何か？目的・制御・自由度の点から違いを解説)
- [まるわかり .NET Frameworkのバージョン比較表](https://kcfran.com/2023/02/15/net-framework-comparison/)
- [.NET Framework](https://wa3.i-3-i.info/word13559.html)
- [サーバー アプリ用 .NET と .NET Framework](https://learn.microsoft.com/ja-jp/dotnet/standard/choosing-core-framework-server)
TextFieldがキーボードで隠れてしまう問題

# はじめに
`TextField`をタップした時にキーボードが表示されますが、その際にテキストフィールドが隠れてしまうことがありますよね？:thermometer_face:
そんな時はTextFieldを上に移動させちゃいましょう！！！
今回は`combine`を使ってやってみました。
結構この実装は使うのでメモのつもりで書いてみました。

## キーボードの通知を受け取って処理を行う

### キーボードが表示される前と閉じる前
・指定された通知をPostされた時にその通知を受け取り、keyboardの高さを取得し、高さ分Viewを上に上げました！
・combineで書くとすごく簡単！

```
    private func setupKeyboardPublisher() {
        NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)
            .merge(with: NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification))
            .sink { [weak self] notification in
                guard let keyboardSize = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
                      let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval,
                      let self else{
                    return
                }
                switch notification.name {
                case UIResponder.keyboardWillShowNotification:
                // ここは上に上げる処理
                    alertContainerViewBottomCostraint.constant = keyboardSize.height
                case UIResponder.keyboardWillHideNotification:
                // ここは下に上げる処理
                    alertContainerViewBottomCostraint.constant = 0
                default:
                    break
                }
                UIView.animate(withDuration: duration,
                               delay: 0,
                               options: .curveEaseInOut) {
                    self.view.layoutIfNeeded()
                }
            }.store(in: &disposeBag)
    }
```
JavaScriptでimport文が使えなかった話

# はじめに
JavaScript学習として、簡単なToDoリストのサイトを作成中です。
その際にcssファイルがimportできずエラーになったので、解決方法をまとめます。
# 問題
VSCodeでファイルを作成後、ブラウザ上に表示させようとしたが、cssをimportしている箇所で **"Cannot use import statement outside a modul"** というエラーが出ました。
# 解決方法
**import文はサーバーを立てないと使えない** ようです。
サーバーを立てない場合は、htmlにcssを読み込ませる必要があります。

記載例
```html:index.html
 <link rel="stylesheet" href="src/styles.css" />
```
こちらの方法が成功した場合、import文は不要になります。
# おわりに
ファイル読み込み＝import　みたいなイメージがあったので、このような決まりごとがあるとは知りませんでした。困っている方のお役に立てたら幸いです。

# 参考
https://qiita.com/hideya670/items/8acaab60644d02eaed0f
[AWS]プライベートAPIを作成(雑メモ)

# 概要
実務でプライベートAPIを作成したので、忘れないように、構築する手順をメモとして書いていきます。
かなり雑に書いているので見にくいです。ごめんなさい

イメージとしては、以下のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613586/b3031782-1b53-c72a-f8f7-1d51919c8630.png)

以下のサイトから画像は頂きました。

https://iret.media/52328

# 手順

## Lambda関数を作成し、API Gatewayと接続
・Lambdaを開き、関数を作成する。
↓
・API Gatewayを開き、「APIを作成」をクリックする。
↓
・「REST API プライベート」の「構築」をクリックする。
↓
・「新しいAPI」を選択し、API名に任意の名前を入力、「APIエンドポイントタイプ」が「プライベート」となっていることを確認し、「APIを作成」をクリックする。
↓
・APIが作成されたら、サイドバーから「リソース」を選択し、「メソッドを作成」をクリックする。
↓
・メソッドタイプを「GET」とし、統合タイプに「Lambda関数」を選択し、Lambda関数のリージョンは「ap-northeast-1」を選択し、右側のメソッドには、先ほど作成した関数を選択し、「メソッドの作成」をクリックする。
↓
・メソッドが作成されたら、APIとLambda関数が接続されたかを確認するため、「テスト」から「テストの実行」をクリックする。

 ## VPCエンドポイント作成
・「VPCエンドポイント」を開き、「エンドポイントの作成」をクリックする。
↓
・名前に任意の名前を入力し、サービスカテゴリは「AWSのサービス」を選択する。
↓
・サービスで「execute-api」を選択。これを選択しないとAPIを実行できない。VPCは実行したいec2が属するVPCを選択する。
↓
・サブネットもec2が所属するものを選択する。セキュリティグループはHTTPSがインバウンドで許可されていればなんでもOK。
↓
・ポリシーで「フルアクセス」を選択し、「エンドポイントの作成」をクリックする。
↓
・エンドポイントが作成される。エンドポイントIDをコピーしておく。

## API Gatewayの追加設定
・API Gatewayで、先ほど作成したAPIを開き、サイドバーから「APIの設定」を選択し、「APIの詳細」の「編集」をクリックする。
↓
・「VPCエンドポイントID」に、先ほどコピーしたVPCエンドポイントIDを追加して、「変更を保存」をクリックする。
↓
・「VPC endpoint IDs」に、追加したVPCエンドポイントが表示される。
↓
・続いて、サイドバーから「リソースポリシー」を選択し、「ポリシーを作成」をクリックする。
↓
・以下のコードをポリシーの詳細に記入し、「変更を保存」をクリックする。

```yaml
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "execute-api:/*"
            ],
             "Condition": {
                  "StringEquals": {
                      "aws:sourceVpce": "VPCエンドポイントID"
                  }
              }
        }
    ]
}
```
↓
・続いて、サイドバーの「リソース」を選択し、「APIをデプロイ」をクリックする。
↓
・「ステージ」で「新しいステージ」を選択する。
↓
・「ステージ名」で任意のステージ名を入力し、「デプロイ」をクリックする。
↓
・APIがデプロイされたら、URLをコピーしておく。

## APIを実行
・コマンドプロンプトを起動し、ssh接続をして、以下のコマンドを入力して、EC2からAPIを呼び出せるかを確認する。

```
curl 先ほどコピーしたURL
```
↓
・EC2にログインしないで、先ほどと同じコマンドを入力して、以下のメッセージが表示されるかを確認する。
```shell
curl: (6) Could not resolve host: コピーしたURL
```
↓
以上の手順が問題なくいけば、成功している。


# 参考サイト

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-private-apis.html

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-resource-policies-create-attach.html

https://taiyakikuroann.hatenablog.com/entry/2021/07/09/214956

https://www.higutthiengineer.com/2022/10/22/awsprivateapi/

https://oji-cloud.net/2020/03/13/post-4469/

https://dev.classmethod.jp/articles/private-api-is-not-private-for-you/
Next.js13でDynamic Sitemapを設定する

# はじめに

以前こちらの記事でNext.js13でのサイトマップの作り方を説明しました

https://qiita.com/Sicut_study/items/2f71e5afe0cd2bb6e786

今回はさらに`/events/1`のような`id`を含めたサイトマップを作る方法をまとめます

# やり方

`app/sitemap.ts`を作って以下の処理を書きます

```ts:app/sitemap.ts
import { getEvents } from "./lib/api/event";
import { getPitches } from "./lib/api/pitch";

const URL = "https://pitchme.jp";

export default async function sitemap() {
  const events = await getEvents();
  const eventsPages = events.map((event) => {
    return {
      url: `${URL}/events/${event.id}`,
      lastModified: event.date,
    };
  });

  const pitches = await getPitches();
  const pitchesPages = pitches.map((pitch) => {
    return {
      url: `${URL}/pitch/${pitch.id}`,
      lastModified: new Date(),
    };
  });

  const routes = [
    { url: `${URL}/` },
    { url: `${URL}/events` },
    { url: `${URL}/events/recruitment` },
    { url: `${URL}/pitch` },
    { url: `${URL}/terms` },
    { url: `${URL}/privacy` },
    { url: `${URL}/contact` },
  ].map((route) => ({
    url: route.url,
    lastModified: new Date(),
  }));

  return [...routes, ...eventsPages, ...pitchesPages];
}
```

サーバーサイドでデータを取得してIdを取得して返しています
ちなみにサイトマップ登録したところ日付が不正となったのですが、時間が経つとなおりました 

# 参考

https://claritydev.net/blog/nextjs-dynamic-sitemap-pages-app-directory
Gitのローカルブランチをまとめて削除する方法

## 結論
```:mainブランチを除くすべてのローカルブランチを削除するコマンド
git branch | grep -v "main" | xargs git branch -d
```
mainブランチ以外のすべてのローカルブランチが一度に削除され、ローカルブランチ一覧をスッキリさせることができます。

## 使用例
例えば、以下のように多くの使用済みローカルブランチが存在する場合に便利です。
```:main以外のローカルブランチはもう用済みだから削除したい…
% git branch
  hoge
  hogehoge
  hogehogehoge
* main
```

## 解説
### git branch
リポジトリ内の全てのブランチを一覧表示します。

### grep -v "main" 
"main"という文字列を含む行を除外することで、mainブランチを削除の対象リストから外しています。

### xargs git branch -d
残りのブランチを一つずつ削除します。
xargsは標準入力から受け取った各行を次のコマンドの引数として渡します。
この場合、各ブランチに`git branch -d`コマンドが渡されて、それぞれのブランチが削除されます。

## 補足
### 強制削除 `git branch -D`
 マージされていないコミットがある場合は`git branch -d`だとエラーになります。
 マージしなくて構わないのであれば`git branch -D`でコミットを無視して強制削除ができます。

```
git branch | grep -v "main" | xargs git branch -D
```

### 個別にローカルブランチを削除
```
git branch -d hoge
git branch -d hogehoge
git branch -d hogehogehoge
```
QRコードを生成するChrome拡張機能を作る

記事「[JIS X 0510 - QRコードの GIF 画像を HTML+JavaScript (ローカル) で生成する](https://qiita.com/ikiuo/items/824b914ccd065b57a887)」を弄って Google Chrome の拡張機能（デベロッパー モード用）としてみました。

https://github.com/ikiuo/google-chrome-extension-genqrcode

# 拡張機能

manifest.json では

- action
    - default_popup (ユーザー インターフェイス)
- permissions
    - storage (設定情報の保存)
    - tabs (popup から現在の URL を取得)

を指定しています。

```json:manifest.json
{
  "manifest_version": 3,
  "version": "0.1.1",
  "name": "QRコードのGIF画像生成",
  "description": "文字列からQRコードのGIF画像を生成します。文字列の初期値は開いているページのURLです。",
  "action": {"default_popup": "popup.html"},
  "permissions": ["storage", "tabs"],
  "icons": {
    "32": "icon32.png",
    "64": "icon64.png"
  }
}
```

## ポップアップ

現在のページの URL を既定の文字列として基本的なデザインの QR コードが生成されます。文字列は編集可能です。

![SS20240119-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/b2b3d227-5421-e7ff-8f5a-eb4c1b5ba131.png)

### 設定

設定は<code>&lt;details&gt;</code>タグ内にあり、開くと以下のようになります。内容は <code>chrome.storage</code> を使用して保持しています。

![SS20240119-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226677/634d6569-a37b-e447-c5d1-71be89e95ee6.png)
childrenで受け取ったコンポーネントの再レンダリング

## はじめに
備忘録です。


## 勘違いしやすい再レンダリングの違い
ケース1はParentが再レンダリングされると、ChildComponentも再レンダリングされる
ケース2はParentが再レンダリングされてもChildComponentは再レンダリングされない

ケース2の時ChildComponentはHomeと親子関係を持っている、Homeが再レンダリングされればChildComponentも再レンダリングされる

ケース1 Parentに直接記述する
*ParentとChildComponentは親子関係*
```tsx
export const Parent = () => {
  return <ChildComponent />
}
```

ケース2: propsのchildrenとしてChildComponentを渡す
*ParentとChildComponentは非親子関係*
```tsx
export default function Home() {
  // childrenによる受け渡しなので、ParentとChildComponentに親子関係はない
  // ChildComponentはHomeと親子関係
  return (
    <Parent>
      <ChildComponent />
    </Parent>
  )
}
```

## どこで使われているか
特に意識していなくてもuseContext使用時のProviderでこの仕組みを使用したことがある方が多いのではないでしょうか？
この時の`<App />`は`<TestProvider>`を定義しているコンポーネントと親子関係であり、`<TestProvider>と<App />`に親子関係はありません。
私はこの挙動についての理解が足りず、TestProviderで定義されたstateを更新したら全てのComponentが再レンダリングされてしまうではないか!!と誤解し、調べるにあたりました。
他の箇所で再レンダリングの最適化も行うことができるので、覚えておくとどこかで使えるかもしれないですね。
```
<TestProvider>
  <App />
</TestProvider>
```
サーバー立てずにMisskeyのBotをお手軽に作る

## はじめに
サーバー管理無しでBotが作れないかやってみました
結果上手く動かすことができたのでなにか参考になれば幸いです。

## 用意するもの
- Googleアカウント
- ちょっとの根気

## Botを作っていく
### 1.BotにしたいアカウントでAPIキーを発行する
![スクリーンショット 2024-01-19 035448.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/e4f3f958-3ec8-50b4-b860-911ef553fdb3.jpeg)
設定の中のAPIボタンから発行します。
![スクリーンショット 2024-01-19 035548.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/aac28b27-fd70-c891-4c89-f8f30b3ef58c.jpeg)
権限がないと操作できない！ということが起こるので、今回は「すべて有効にする」を選択しました。
チャックマークを押すとキーが発行されるので、しっかりメモして保管します。
### 2.GASを用意しよう
https://script.google.com

↑にアクセスして早速空のプロジェクトを作ります。
ここでGoogleアカウントが必要になるのでログインしてくださいね。
![スクリーンショット 2024-01-19 041133.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/b0563b46-be00-1171-9b0a-701977261149.jpeg)

### 3.テストノートしてみよう
https://misskey.dev/api-doc#operation/notes/create

公式のドキュメントに詳しく書かれてますが、難しいのでシンプルなコードを書いてみます。
```javascript
//TLに投稿する関数
function TLPost() {
  let postURL = "https://投稿したいサーバーURL/api/notes/create"
  var headers = {"Content-Type": "application/json",}
  var data = {
    "method": "post",
    "headers": headers,
    'payload': JSON.stringify({
      "i" : "ここにAPIキー",
      "text": "ここに投稿したい文章"
    })
  }
  let responses = UrlFetchApp.fetch(postURL,data)//リクエスト
}
```
![スクリーンショット 2024-01-19 043002.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/3dc71e28-7f60-5eb8-f3d2-6e0e2ec84f9d.jpeg)

書き終わったら実行してみましょう。

https://nefs.jp/blog/gas-certification/

警告が出てびっくりすると思いますが自分の書いたプログラムなので安心してください。
ちなみに警告は初回だけで、以降は認証しなくても動いてくれます。

![スクリーンショット 2024-01-19 044024.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/a7869d64-a57f-5945-0514-e5b7c8281342.jpeg)
おめでとう！記念すべき初投稿ができました！！

### 4.応用する
応用すればランダムな投稿をさせることもできます

```javascript
//ランダムなノートをする
function RandomNote() {
    let massage = []
    let rand = Math.random() //サイコロを用意する
    rand = Math.floor(rand*3) //3面ダイスにする

    //会話のパターン
    massage[0] = "パターン1"
    massage[1] = "パターン2"
    massage[2] = "パターン3"
  
    let postURL = "https://投稿したいサーバーURL/api/notes/create"
    var headers = {"Content-Type": "application/json",}
    var data = {
        "method": "post",
        "headers": headers,
        'payload': JSON.stringify({
            "i" : "ここにAPIキー",
            "text": massage[rand] //用意したどれかの文章になる！！
        })
    }
    let responses = UrlFetchApp.fetch(postURL,data)//リクエスト
}
```

### 5.定期的にノートしてもらう
これは簡単でトリガーというものを用意するだけで完了です。
![スクリーンショット 2024-01-19 045540.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/63ab462a-0ff8-0d13-e404-c3e689f92a29.jpeg)

![スクリーンショット 2024-01-19 045929.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679188/f33c58ec-fbaf-ecf3-459e-38b86de3ed5e.jpeg)

①にランダムノートの関数を選んで、②でどのくらいの間隔でノートするかを選べます。
あまりサーバーに負担をかけないように注意してくださいね。

## おしまい
お疲れ様でした！これでランダムにつぶやくBotが作れました！

https://misskey.dev/api-doc#section/Permissions

公式ドキュメントから確認できるのでお好みでカスタマイズしてみてください。
では良きMisskeyライフを～～！！
IrisでのUI作成方法の紹介記事一覧

# 目次
1. はじめに
1. 記事紹介
1. 最後に


# はじめに
Irisでアプリの画面を作る際、各ウィジェットを使ってどのようにUI実装を行えば良いか迷う場面があるかと思います。
そこで今回は、UIを作成する際に参考になりそうな記事の一覧をまとめてみました！

初めてIrisを使ってアプリデザインを作る方など是非参考にしてみてくださいね！

また、初心者向けの学習コンテンツも用意しています。

https://qiita.com/VoltMX_Team/items/4c922fa016ce95c58406

3章の「[Exercise1 デザインを元にモバイルで画面を作ってみよう](https://qiita.com/Kony_Team/items/8685b53a8878d41cdaf6)」では、UIの作成方法も学ぶことができますので、基礎から学びたい方はこちらもご参考ください:writing_hand_tone1:




# 記事紹介

各項目でUIを実装するための方法を書いた記事のリンクを貼っておきます。
実装したいUIの例を確認して、興味のある記事を参考にしてみてください👀

## 画像付きのボタンを作成する方法
https://qiita.com/VoltMX_Team/items/ba7ac72f7385636a534a

このようなUIを作成することができるようになります。
![ezgif-1-f803112d7a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/ce37ba1d-f09b-50b6-58f5-f0dfca7344bb.gif)

## 画像ファイルを使わずにデフォルトアイコンを使ってUIを作成してみた

https://qiita.com/VoltMX_Team/items/4d7a408dea83551fc85e


画像ファイルを使わずに、以下のようなステータスバーを作成することができるようになります。

![ezgif-4-d2ce24bdc1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/0522146a-e7c8-d89a-2146-a007447d5215.gif)

## フッターメニューを作成する方法

https://qiita.com/VoltMX_Team/items/6b50ffeed0b27059bf92

このようなUIを作成することができるようになります。
<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/LrfpJORNZw">pic.twitter.com/LrfpJORNZw</a></p>&mdash; Kony (@Kony12763790) <a href="https://twitter.com/Kony12763790/status/1373882910256734210?ref_src=twsrc%5Etfw">March 22, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## リッチテキストを使って簡単な商品紹介ページを作成

https://qiita.com/VoltMX_Team/items/7bf89a8d5fcea073aa47

RichText Widgetを使ってこのようなUIを作成することができるようになります。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3539323236342f63373763623330652d666338632d356362612d616661322d6666373836313131616334372e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/aa7d7828-ea11-a975-e86f-6f4baa88dff0.png)


## Visualaizerでアコーディオンメニューを作ってみる

https://qiita.com/VoltMX_Team/items/039c353d224e2fd74fe9

このようなUIを作成することができるようになります。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3539323236342f63653530376437662d363362662d393638372d623961382d3935663461363266313664632e676966.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/8f0009cc-0f89-e718-1327-343669fb0daa.gif)

## VisualizerでTabPane Widgetを利用する方法

https://qiita.com/VoltMX_Team/items/01cdf19623076963a00f

このようなUIを作成することができるようになります。


<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/zlw0jbg4Nv">pic.twitter.com/zlw0jbg4Nv</a></p>&mdash; Kony (@Kony12763790) <a href="https://twitter.com/Kony12763790/status/1377102283494748166?ref_src=twsrc%5Etfw">March 31, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 最後に
新しい記事が更新されたら随時更新していきます！
TypeScriptの非nullアサーション演算子(!)について

## 非nullアサーション演算子とは？
非`null`アサーション演算子（`!`）は、その直前のオブジェクトが`null`または`undefined`でないことをTypeScriptにアサート（主張）します。

```typescript
let result = doSomething();  // doSomething could possibly return null or undefined.
const item = result!;
```

ここで注意すべきは、非`null`アサーション演算子はあくまでコンパイル時のチェックをパスさせるためのものであり、実行時に`null`や`undefined`が入らないことを保証するわけではありません。

## いつ非`null`アサーション演算子を使うべきか？
非`null`アサーション演算子の使用は注意が必要です。実行時に`null`または`undefined`が発生すると、アプリケーションはクラッシュする可能性があります。

非`null`アサーション演算子は「絶対にそれが`null`または`undefined`ではない」という強い確信があるとき、そしてその確信がテストで裏付けられている場合等に使用する必要があります。

確信できない場合は、他の安全な手段である`null`チェックやOptional chaining(`?.`)などを選択することが推奨されているようです。
Route53でCloudFrontへエイリアスを貼ろうとしてプルダウンに見つからない件

# 問題はすごく単純

### 原因

cloudfrontの代替えドメインはcloudfront側でCNAMEレコードに登録してるようです。
なのでcloudfrontに代替えドメインを設定してないと出ないだけです。
LPC810をmbedで触れる

# はじめに
小さな格安マイコンということで興味を持ち、以前に購入したLPC810ですが、当時は開発環境を整える敷居が高いように感じ、諦めて暫く放置していました。しかし、大学の授業で無償のオンライン開発環境が手軽に利用できることを知り、今回はLEDの点滅まで試してみました。LPCXpressoは使いません。書き込みに必要なのは汎用的なUSBシリアル変換モジュールだけという点も助かります。あまりメモリのサイズは大きくないため、プログラムのサイズを小さくするなどの工夫は必要ですが、勉強になりそうです。
![picture.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2951963/e8e4addf-1035-9492-c891-ad14f026ebd1.jpeg)
# 動作確認環境
* Windows 11 Home 22H2 (22621.3007)
* Keil Studio Cloud 1.7.14
# Keil Studio Cloud
mbedコンパイラの後継に当たるオンライン開発環境です。アカウントを作成すると無償で利用できます。今回はLPC810を使いますが、公式ではサポートされていないので少し注意が必要です。まず、ターゲットを`NXP LPC800-MAX`に変更します。次に[**こちら**](https://os.mbed.com/users/va009039/code/lpc810_helloworld/)で提供されているパッチファイルを後述するプログラムファイルと同じディレクトリに置きます。後はビルドして成功すると自動的にバイナリファイルがダウンロードされます。
# プログラム
8番のピンに接続したLEDを点滅させます。1番、3番、4番のピンを使う場合は初期設定が必要になるみたいです[^1]。まず、普通に標準ライブラリ関数を使用したところ、プログラムファイルのサイズは2KBとなりました。
```cpp:main.cpp
#include "mbed.h"

DigitalOut led(P0_0); //8番のピンを出力に設定

int main() {
    while (1) {
        led = !led; //LEDの点灯と消灯を切り替え
        wait(0.1); //0.1秒待つ
    }
}
```
次に直接レジスタを操作することで軽量化しました。また、`wait_ms`を使うことで少しだけ軽量化できるみたいです。プログラムファイルのサイズは972Bとなりました。
```cpp:main.cpp
#include "mbed.h"

int main() {
    LPC_GPIO_PORT->DIR0 = (1 << 0); //8番のピンを出力に設定
    while (1) {
        LPC_GPIO_PORT->NOT0 = (1 << 0); //LEDの点灯と消灯を切り替え
        wait_ms(100); //0.1秒待つ
    }
}
```
# 書き込み方法
まず、ダウンロードしたバイナリファイルを用意します。次にUSBシリアル変換モジュールとLPC810を以下のように接続します。LPC810はVSSとVDDのピン配置が特殊です。0.1uFのパスコンも付けました。3.3Vで駆動します。5番のピンをGNDに落とし、電源を入れると書き込み可能な状態で起動します。
![lpc810_download_circuit_breadboard.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2951963/ca6508f0-a5d4-98fa-7637-310ca6f5df8b.png)
書き込みに必要な実行ファイルは[**こちら**](https://os.mbed.com/users/va009039/code/lpc810_helloworld/wiki/lpc81isp_go)からダウンロードできます。CUIで操作します。FlashMagicを使う方法だとバイナリファイルをHEXファイルに変換する手間があるため、今回は使いません[^2]。コマンドプロンプトを開き、以下のようなコマンドを実行します。ここで、USBシリアル変換モジュールが接続されたCOMポートとバイナリファイルのパスを指定します。
```
lpc81isp.exe port=COM3 blink.bin
```
書き込みが完了するとターミナル上に完了メッセージが表示されます。後はUSBシリアル変換モジュールを外し、5番のピンを開放してから電源を入れ直すと書き込んだプログラムが走ります。今回の場合はLEDが素早く点滅するはずです。
# おわりに
割と放置していたLPC810ですが、無事に動かすことができたので良かったです。しかし、残念ですが、現在では廃番になっているみたいです。
[^1]:http://tetschan.blog.fc2.com/blog-entry-37.html
[^2]:https://microcraft.blog.fc2.com/blog-entry-115.html
ポートフォリオを作ってみた(3)

# サーバー構築
以下の流れで説明をしていきます。前回は(2)ドメイン作成をしたので、今回は(3)サーバー構築を説明いたします。
(1)環境説明
(2)ドメイン作成
(3)サーバー構築
(4)デザイン検討
(5)コーディング
(6)公開

今回使うものは、[Cloud Flare](https://www.cloudflare.com/ja-jp/)になります。

Public Cloud(Azure、AWS、GCP)を選ばなかった理由につきましては、今回は個人運営を想定しているのでコストを極力抑えるためです。Cloud Flareは無料枠があるため、その無料枠の範囲内でサーバー構築を行います。

(1)まずは、[Cloud Flare](https://www.cloudflare.com/ja-jp/)のサイトにアクセスして、サインアップをクリックします。
(2)アプリケーションサービスのFreeから「Webサイトを追加」をクリックします。
![](https://storage.googleapis.com/zenn-user-upload/626ab2530ebd-20240119.png)
(3)アカウント作成後、「Add a site(サイトを追加)」をクリックします。
![](https://storage.googleapis.com/zenn-user-upload/f9c8e7564720-20240119.png)
(4)前回作成したドメインを入力し、「Add a site(サイトを追加)」をクリックします。
→私の場合はすでに一つ登録しているため、「Continue(続行)」と表示されています。
![](https://storage.googleapis.com/zenn-user-upload/7974c4a8d34f-20240119.png)
(5)料金プラン選択画面が表示されるので、Freeを選択して「Continue(続行)」をクリックします。
(6)DNS管理は何もせずに「Continue(続行)」をクリックします。
(7)表示されたCloud Flareのネームサーバーを[ネットオウル](https://www.netowl.jp/)に設定します。
→ネットオウルにログイン後、スタードメイン管理 -> 管理ドメイン一覧 -> ドメイン管理ツールをクリックして、「ネームサーバーの確認・変更」から既存の設定を全て削除後、Cloud Flareのネームサーバーを設定してください。
(8)「Check nameservers now(ネームサーバーを今すぐ確認)」をクリック後、チェックが終わったら「Continue(続行)」をクリックします。
![](https://storage.googleapis.com/zenn-user-upload/056c1b637430-20240119.png)

ここまででサーバー構築はほぼ完了です。

今回は「Workers & Pages」のPagesを使ってポートフォリオを公開します。Pagesはサーバーレスであるため、ネットオウルとCloudFlareのネームサーバー/DNS設定が終わればサーバー構築完了と言ってもいいレベルです。

個人で作成したWebアプリケーションやWebサイトを公開する場合にも使えるため、Cloud Flareはおすすめです。
UbuntuにCrystalをソースコードからインストールする

## はじめに

Crystal言語は素晴らしい言語ですが、Ubuntuユーザーはinterpreterを使いたい場合、Crystalをソースコードからコンパイルする必要があります。

## 方法

### リポジトリの準備

GitHubでCrystalのリポジトリをフォークし、ローカルにクローンします。

```sh
git clone https://github.com/kojix2/crystal
```

次に、リモートリポジトリにCrystalの公式リポジトリを追加します。

```sh
git remote add upstream https://github.com/crystal-lang/crystal
```

以下のコマンドで更新しますが、タグも更新する必要があるため、`--tags` オプションも使用します。

```sh
git fetch upstream --tags
git merge upstream/master
```

### Snapを使ったCrystalのインストール

Crystalはセルフホスティングされているため、初回インストールにはCrystalが必要です。Snapを使用すると簡単ですが、インタープリタ機能は利用できません。

```sh
sudo snap install crystal --classic
```

後述するように自分でビルドしたCrystalが準備できたら、パッケージマネージャーのCrystalは削除します。

```sh
sudo snap remove crystal
```

### 必要なパッケージのインストール

GitHubのWikiにある[All required libraries](https://github.com/crystal-lang/crystal/wiki/All-required-libraries)を参考に、必要なライブラリをインストールします。

```sh
sudo apt-get install -y \
  automake \
  build-essential \
  git \
  libbsd-dev \
  libedit-dev \
  libevent-dev \
  libgmp-dev \
  libgmpxx4ldbl \
  libpcre3-dev \
  libssl-dev \
  libtool \
  libxml2-dev \
  libyaml-dev \
  lld \
  llvm \
  llvm-dev\
  libz-dev
```

（上記は2024-01-19時点でのものです。最新の情報をご確認ください）

### Crystalのコンパイル

リリースされたバージョンでコンパイルします。

```sh
git clean -f # 以前に生成されたファイルの削除
git checkout -b v1.11.2 refs/tag/1.11.2
cd crystal
```

コンパイルのためのオプションが表示されます。

```
make help
```

```
  CRYSTAL         which previous crystal compiler use
  LLVM_CONFIG     llvm-config command path to use
  check           Enable only check when running format
  debug           Add symbolic debug info
  interpreter     Enable interpreter feature
  junit_output    Path to output junit results
  order           Enable order for spec execution (values: "default" | "random" | seed number)
  progress        Enable progress output
  release         Compile in release mode
  static          Enable static linking
  stats           Enable statistics output
  target          Cross-compilation target
  threads         Maximum number of threads to use
  verbose         Run specs in verbose mode

recipes:
  Build the compiler
    $ make
  Build the compiler with progress output
    $ make progress=1
  Clean up built files then build the compiler
    $ make clean crystal
  Build the compiler in release mode
    $ make crystal release=1 interpreter=1
  Run tests
    $ make test
  Run stdlib tests
    $ make std_spec
  Run compiler tests
    $ make compiler_spec
  Run generators (Unicode, SSL config, ...)
    $ make -B generate_data
```

私は通常、以下のコマンドを使用します。

```sh
make release=1 interpreter=1 debug=1
```

Crystalはインクリメンタルコンパイルに対応していないので、`make -j16` などとしても効果はありません。

### 既存のCrystalをアンインストールする

SnapでインストールしたCrystalは、ビルドが完了したら削除します。

```sh
sudo snap remove crystal
```

前回debパッケージを作ってインストールした場合も同様です。

```
sudo dpkg -r crystal
```

### Crystalのインストール

`checkinstall` を使用してdebパッケージを作成し、インストールします。

```sh
sudo checkinstall
```

## おわりに

この方法が最適とは限りませんが、インタープリタがほしい場合は有効な方法の一つだと思います。
macOSではHomebrewを使用する方が簡単です。この記事が何かの参考になれば幸いです。皆さんはどのようにCrystalをインストールしていますか？

この記事は以上です。
@clickのあとに@blurを発火させたい

# 前提
Vue.js 3

検索機能付きのセレクトボックスを作成中

![pulldown_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493001/ce9cf471-cbcf-4665-be72-01addb508853.png)

# やりたいこと
選択肢モーダルの外側をクリックしたときに、モーダルが閉じるようにしたい。
`@blur`でフォーカスが外れた時にモーダルを閉じる。

# 困っていること
モーダルに`@click`を設定して選択肢をセレクトしているが、
clickイベントより先にblurイベントが発火するため、選択肢を押下できない。

# 解決
そもそも`@click`ではなく`@mousedown`をつかう。

参考
https://stackoverflow.com/questions/61137481/blur-event-cancels-click-event-in-vue-component
転職フェアに出展した話

# はじめに
　先日、初めて転職フェアというものに企業出展しました。その時のメモ的なことを書いていこうと思います。オチはないです。
　弊社は最近キャンプ場運営事業も始めたSESの会社です。従業員は19名の小さな会社で、18期目になります。書いてる人はPHPerで営業でデザイナーです。
## 出展した理由
 今まで、エンジニアの中途採用はリファラル採用しか行ってきませんでした。そんな中、懇意にしている営業さんと会食の際にした中途採用の悩み相談から、転職フェアへの出展を勧められました。以前は媒体にも出していたのですが、費用だけかかり面接設定にすら辿り着けなかったので、実際に求職者の方と面と向かって会話ができる機会があるフェアへの出展もありかも？、と出展を決意します。
 余談ですが、新卒採用は、1〜2名程度ですが行っています。しかしこれも従業員の卒業校のみで応募を行っています。事務職の応募にはハロワを利用しています。
## 準備
 事前準備は色々したのですが、打ち合わせ系以外のところだと下記になります
 - 当日会社説明に使用するパンフレットの作成
 - ノベルティの作成
 - ブース内デザインの作成
    - 今回はキャンプ場で使用している横断幕、キャンプ場レンタル品のテーブルとチェアを用意しました
    - ランタンとか飾っちゃって
 - ヒアリングシートの作成
 - 面接設定調整用紙の作成
     - いい人だなって思ったら、その場で面接を組んじゃうんですって
## 当日
 キャンプ用品を社用車に詰め込んでいざ会場へ。ブースには呼び子も含めて1社4名まで、という決まりがあったため、少人数での参加になりました。
 完全にブースの位置ガチャがあると思ったのですが、開会すぐは入り口付近のブースに来場者が取られて、奥の方には人が流れてきませんでした。立ち寄ってくれないとかのレベルじゃないんです。人が通らないんです。なので開始1時間は同僚と手相の話で時間を潰していました。あと思ったのは、開会間際は年配者が多いなという印象を持ちました。
 その後はちらほらと人も流れ始めます。
### 来場者の様子
　来場者は自分がどんな職種の人間なのかのを表すためのシールを体の見える位置に貼っています。IT開発なのか、インフラなのか、コンサルなのか、ものづくりなのか、未経験なのか、的なやつです。なので、呼び子はそのシールを目安に声をかけていきます。しかしまぁ、目安なので、実際にお話を聞いてみたら全然違いました、というのは無きにしも非ず。
 ここで、どんな人がブースにきたのかをまとめたいと思います
 ちなみに着座が50強、後日面接設定ができたのは4人でした。
#### パターン1： 情報収集
転職は考えてない、または、転職先は決まっている、がどんな会社があるのか情報収集目的で来場していました。情報収集が目的なので、会話が弾みます。そして大抵、いい人が多いです。
#### パターン2： 未経験
スクール卒（予定）で転職先探してます系の人。IT業界を選んだ理由に一番多かったのが、テレワークがしたい、でした。そんなにテレワークをしているように見えるのでしょうか？（この件は後述）
また、完全なる未経験だけどどうしたらIT系の職業につけるのか、という方もいらっしゃいました。
ちなみに、未経験の方ほどブース内でデザインに食いついてくださる傾向にありました。
#### パターン3： テレワークがしたい
テレワークができる転職先を探していますって人ですね。これも多かったです。テレワークを希望される理由は様々ですが、年配者になればなるほど介護を理由とされていました。
#### パターン4： ブランクがある
昔IT系の職に就ていて、今は違う職についてるんだけど戻りたい、って人ですね。
#### 例外: キャンプが好き
ごく少数ですが、キャンプが好きという方もいらっしゃいましたね。ブースを見て、おっ、と思ってくださる方もいらっしゃいました。

## 総称して思ったこと 
### 『IT系がテレワークって都市伝説じゃない？』
営業も兼務しているので思うことなのですが、テレワークを希望される割合とテレワーク可能案件のバランスがおかしいなと。明らかに、フルテレ案件は減っています。一部テレとかはまだありますが数は減ってきています。弊社内でもフルテレで仕事をしているのは自分を入れて4人くらいじゃないかな。
やっぱり、会社の上層部がテレをよく思っていない、という企業は少なくないです。顔を突き合わせて仕事がしたいと思っている方もいると思います。なので、必要がないなら出社しろ、という企業は少なくないです。でも、せっかく整えたテレワーク環境だから併用にしようか、というのが一番多いのかな。コロナ禍で事務所自体を解約ないし縮小してしまった企業などはフルテレというところが多いですね。確かに今更また物理スペースを増やすのはナンセンスな気がします。
来場者のテレワーク希望率の多さから、「IT系のテレワークが多いのは都市伝説なのでは？」と思ったのでした。他の企業に比べたら比率的には多いってだけで、案件数から見るとそんなに多くはないんじゃないかなと。

これは絶対言いたいのですが、テレワークは向き不向きがある！ と、思っている。
（自分はコロナ禍前からフルリモ案件だったので、6年近くこの生活なので流石に慣れました）
### 疲れる
ひたすら短時間の面談をこなしているのと同じ状態なので、とにかく疲れます。特に脳が。自分は特に日頃言葉を発しないので翌日は喉がガラガラでした。呼び子も立ちっぱなしなので足に来たそうです。

## 最後に
開会も閉会も誰も拍手してなかったんですよ。どういうことですかね？
Pythonで動画から音声を抽出する

# 前置き
英語の動画を文字起こしし、日本語の字幕を作成します。
今回はその第一段階として、PythonとMoviePyを使って英語の動画を音声ファイルに変換します。

# MoviePyについて
MoviePyは動画の編集を行うためのPythonモジュールです。
インストールは以下の要領で行えます。

```
pip install moviepy
```

pipのアップデートなども必要に応じて行ってください。


# 実行環境
- Python 3.10.13
- moviepy 1.0.3


# ソースコード
- 必要なライブラリのインポート
MoviePyは以下の要領でインポートします。

``` python
from moviepy.editor import VideoFileClip
```

その他のライブラリもインポートしましょう。
 ``` python
from tkinter import filedialog
import os
```

- 動作部の実装
実際に動画→音声の変換を行う部分は、以下のように実装しました。

 ``` python
 if __name__=="__main__":
    # ユーザーにビデオファイルを選択させる
    video_file_path = filedialog.askopenfilename()
    
    # 選択したビデオファイルの相対パスを取得する
    video_file_path = os.path.relpath(video_file_path)

    # ビデオファイルの名前を取得する（拡張子なし）
    video_file_name = os.path.splitext(os.path.basename(video_file_path))[0]

    # ビデオファイルを読み込む
    clip = VideoFileClip(video_file_path)

    # ビデオからオーディオを抽出し、wavファイルとして保存する
    clip.audio.write_audiofile(f'{video_file_name}.wav', 44100, 2, 2000,"pcm_s32le")
```

まず、変換を行うファイルを選択します。
今回はfiledialogを用いて選択していますが、別の方法を使っても構いません。

``` python
video_file_path = filedialog.askopenfilename()
```

今回は、変換前の動画ファイルと変換後の音声ファイルでファイル名を共通にしたいです。
"video_file_path"には拡張子込みでパスが格納されているので、ファイル名から拡張子を取り除いてファイル名に使います。

``` python
video_file_name = os.path.splitext(os.path.basename(video_file_path))[0]
```

ここまで出来たら、満を持して動画ファイルを音声ファイルに変換します。
音声ファイルの拡張子は何でもいいのですが、前置きでも話した通り今後この音声ファイルを文字起こしするので、その都合で今回は.wav形式に変換しています。

ファイル名、サンプリングレート、チャンネル数、ビットレート、コーデックを指定して動画→音声の変換を行います。

``` python
    # ビデオファイルを読み込む
    clip = VideoFileClip(video_file_path)

    # ビデオからオーディオを抽出し、wavファイルとして保存する
    clip.audio.write_audiofile(f'{video_file_name}.wav', 44100, 2, 2000,"pcm_s32le")
```

以上が、今回作成した動画を音声に変換するプログラムです。

次回は、whisperを使い、今回作成した音声ファイルの文字起こし、翻訳作業を行うことを計画しています。


# 最後に
ここまで、特に上の一文を読んで勘のいい方は気づいたかもしれませんが、whisperは動画ファイル(mp4)をそのまま読み込めるそうです。(私はこのプログラムを組んだ後に知りました……)

あれ、このプログラムの存在意義。。。。
EC2インスタンスのEBSボリュームを拡張する手順

# 1.マネジメントコンソールからEC2のディスクサイズを上げる。
対象のEC2インスタンスに接続されているEBSボリュームのサイズを増やす。
EBSのボリュームの変更から変更できる。
上記で増やしても、OSレベルで自動的に反映されない。
# 2.デバイス名を確認
```df -hT```マンドを使用して、拡張するマウントポイントのデバイス名を確認する。
出力が```/dev/nvme0n1p1 xfs         20G  7.4G   13G   37% /```
の場合、拡張すべきデバイスは```/dev/nvme0n1p1```。
末尾のp1はパーテーション1番ということみたい。
# 2.パーティションのサイズを拡張
ストレージデバイスのサイズ変更をOSレベルで認識させ、パーティションテーブルを更新する必要がある。
```sudo growpart /dev/nvme0n1 1```
このコマンドで、デバイス ```/dev/nvme0n1``` のパーティション1（nvme0n1p1）のサイズを拡張する。
# 3.ファイルシステムのサイズを拡張
パーティションのサイズが増えても、ファイルシステムは自動的に新しいサイズに拡張されない。
```sudo xfs_growfs /dev/nvme0n1p1```
このコマンドは、拡張されたパーティション ```/dev/nvme0n1p1``` 上のXFSファイルシステムのサイズを拡張する。
ここではp1と繋げて書く。

---

と、上記だけだとよくわからなかったので、chatGPTにレストランに例えてもらった。

# 1. レストランの座席数を増やす（EBSボリュームのサイズを増やす）
あなたはレストランのオーナーで、もっと多くの客を収容するために店を拡張することにしました。これは、EC2インスタンスに接続されているEBSボリュームのサイズを増やすことに相当します。しかし、単に店を大きくしただけでは、スタッフは自動的に新しいスペースを使い始めることはありません。まず、新しいスペースをどのように使うかを計画する必要があります。
# 2. 新しいスペースのレイアウトを計画する（パーティションのサイズを拡張）
店を拡張した後、新しいスペースにテーブルと椅子を配置する計画を立てます。これは、sudo growpart コマンドを使用してOSが新しいストレージサイズを認識し、パーティションテーブルを更新することに相当します。つまり、新しいスペース内にどこに何を置くかを決める作業です。
# 3. 新しいスペースを利用するようスタッフに指示する（ファイルシステムのサイズを拡張）
レイアウト計画が完成したら、次にスタッフに新しいテーブルと椅子を使うよう指示します。これは、sudo xfs_growfs コマンドを使用してファイルシステムを新しいパーティションサイズに合わせて拡張することに相当します。これにより、スタッフは新しいスペースをフルに活用して、より多くの客を収容できるようになります。
Silicon Labs Arduino CoreでEFR32をArduinoで動かす

__Silicon Labs__ の __EFR32__ が __Arduino__ 対応していました。

https://github.com/SiliconLabs/arduino?tab=readme-ov-file

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

今回は、10ドル弱で買える __BGM220 Explorer Kit__ を __Arduino__ で触ってみましょう。

# BGM220 Explorer Kitとは
__BGM220P__ は __EFR32BG22__ をモジュール化したもので、技適取得済みになります。
BGM220 Explorer Kitは__BGM220P__の開発ボードになります。

https://qiita.com/usashirou/items/1e86c2bb0d2b6a7dede8

# 環境構築

__ファイル→基本設定__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/ab335fe4-25d7-6f89-c880-6270254fccec.png)
__追加のボードマネージャ__ の __URL__ に以下を入力して、OKをクリックします。

    https://siliconlabs.github.io/arduino/package_arduinosilabs_index.json

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/d8bf26ff-edff-b2f0-c73a-bb1fff74df47.png)
# ボード設定を追加する
__ツール⇒ボード⇒ボードマネージャー__ をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/995f3c20-215e-f789-6eb6-5227cf2a2854.png)
ボードマネージャーにおいて __Siliconlabs__ を検索し、__インストール__ をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/82bfff06-5ba3-af4c-2167-41c62a75fdf6.png)
インストール後、__ツール⇒ボード⇒Siliconlabs__ 使用するボードを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/49013148-2de4-038c-081d-6eeb13771f30.png)
# 書き込み装置を設定する
__ツール⇒書き込み装置⇒Simplcity Commander__ を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/b41ed6bc-3fbe-62b3-87d3-123f7e7110c0.png)
# ブートローダーを書き込む
__ツール⇒ブートローダーを書き込む__ をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/a636f70d-228d-14fe-d239-8a6de5e004e7.png)
# 書き込みをする
以上でArduinoの対応が終わりましたので、書込みを行いましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/4e02c63d-3324-a83d-dd42-c740273d8ce3.png)
これで、Arduinoで開発できるようになりました。
なお、まだ、すべてのデバイスでMatter対応はされていないようで、これからに期待です。
Power Automate Desktopでクライアント証明書を選択する

自分用メモ。

## やりたいこと
Power Automate Desktopでクライアント証明書を選択する。だけ

## 動作環境
・Windows 11(22H2)
・Microsoft Edge

## 失敗した方法
下記のアクションは、実行時にエラーとなった。
・ウィンドウのUI要素をクリック
・Webページのリンクをクリック

## 成功した方法
１．「アクション：新しいMicrosoft Edgeを起動」でアクセスしたいWebページを開く
２．「アクション：マウスクリックの送信」を利用してクライアント証明書を選択し、OKを押下する

※注意※
クライアント証明書を選択させる際に、マウスの移動スタイルを「すぐに」ではなく「アニメーション付き」にしないと上手くいかない。
OKボタンを押下するときはマウスの移動スタイルを「すぐに」でも出来る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3537508/c2335bbf-ecc1-5da7-55df-9088aa50ec0a.png)
Java,kotlinの実装で共通で使えるモノ

# Java,kotlinの実装で共通で使えるモノ

↓実装の際に参考にさせて頂いたサイト 

「Java8」LocalDateTimeクラスのtruncatedToメソッドで時間を切り捨てるサンプル
https://arkgame.com/2020/11/05/post-160269/

### その他参考サイト

Java8の日時APIはとりあえずこれだけ覚えとけ
https://qiita.com/tag1216/items/91a471b33f383981bfaa
Docker + GolangでTimeZoneがうまく設定できない

# はじめに
どうも僕です。

業務でDockerを使うことがあるのですが、`golang`のコンテナで`cron`の実行をする際、タイムゾーンが`UTC`だったので`JST`に変えようとしたところ、結構つまづいたのでメモっておきます。

# 概要
`golang`にてcronを使って毎日特定の時刻に関数を走らせたい！
↓
しかしタイムゾーンがUTCだ！！
↓
どうにかせんといかん。

# 結論
先に結論を言うと、 Dockerfileに次のコードを追加する。

```Dockerfile
FROM golang:1.19

WORKDIR /usr/src
# これを追加↓
ADD https://github.com/golang/go/raw/master/lib/time/zoneinfo.zip /usr/local/go/lib/time/zoneinfo.zip
```

そしてコード

```go:sample.go
package main

import (
	"fmt"
	"log"
	"os"
	"time"
)

func main() {
	os.Setenv("TZ", "Asia/Tokyo")
	log.Println("Now time is: ", time.Now())
	local, err := time.LoadLocation("Local")
    if err != nil {
		log.Println(err)
	}
	fmt.Println(local)
}
```

```bash:結果
root@c74f69be4f71:/usr/src# go run main.go
2024/01/19 12:29:18 Now time is:  2024-01-19 12:29:18.482109833 +0900 JST m=+0.000930959
Local is:  Asia/Tokyo
```

# 解説
DockerのTimeZoneに関しては色々な設定があると思います。
設定の際にやってみたこととしては
- ホストOSのTimezoneをJSTにしてVolumeでDockerに渡す
- DockerfileにTZ：Asia/Japanを入れた
- Dockerコンテナ内で`date`コマンドからJSTなるようにした
- Dockerfileで`COPY --from=builder /usr/share/zoneinfo/Asia/Tokyo /usr/share/zoneinfo/Asia/Tokyo`をしてみた

等々、いろいろありますが、問題点がいくつかあるようです。

----
>ホストOSのTimezoneをJSTにしてVolumeでDockerに渡す
>Dockerコンテナ内でdateコマンドからJSTなるようにした


あまり推奨されてなさそう

https://qiita.com/rururu_kenken/items/972314402d588e073d40#2019729%E8%BF%BD%E8%A8%98

```bash
$ docker compose exec golang bash

# コンテナに入る
$ date
Fri Jan 19 12:45:47 JST 2024
```
こうなってもgolangがTimezoneを参照しに行く場所が違うため意味がない

----
> DockerfileにTZ：Asia/Japanを入れた

TZが対応していないDocker Imageもあるから必ずできるわけではない

----

> DockerfileでCOPY --from=builder /usr/share/zoneinfo/Asia/Tokyo /usr/share/zoneinfo/Asia/Tokyoをしてみた

DockerImageが`alpine`のような軽量のものでは`/usr/share/zoneinfo`が存在せず、
`docker compose build`の際にエラーが出る

---

# 結論２
Dockerfileに
`ADD https://github.com/golang/go/raw/master/lib/time/zoneinfo.zip /usr/local/go/lib/time/zoneinfo.zip`
を追加してgolangがTimezoneを参照できるところにTimezoneの情報を置いて、`os.Setenv("TZ", "Asia/Tokyo")`
 すればいい。


# 参考になったリンク

https://yuya-hirooka.hatenablog.com/entry/2020/04/12/204550
AI品質保証、AIテスティングに関する日本語主要ガイドライン

AIの品質保証、AIテスティングに関する記事を個人的に集めているのですが、その中でも体系的に情報がまとめられている資料がいくつか出ています。

品質保証やテストというだけでなく **「AIにおける品質とは何か？」** を言語化している資料として、AIに関して理解を深めるためにも良い資料となっているので、テストエンジニアやQAエンジニアに限らず、広く読まれると良いなと思います。

以下に3つ主要なものをご紹介します。


## AIプロダクト品質保証ガイドライン
https://github.com/qa4ai/Guidelines/tree/main
- AIプロダクト品質保証コンソーシアムが出しているガイドライン
- AIプロダクトの品質保証の分類軸ごとのチェックリストが用意されているなど、かなり実用的
- 生成系システム、自動運転、OCRのようにプロダクトの種類ごとの言及もあり
- 実際に機械学習やAIシステムを作るエンジニアにが品質を改善し作り込むために有用


 
## 機械学習品質マネジメントガイドライン （AIQM）
https://www.digiarc.aist.go.jp/publication/aiqm/guideline-rev4.html

- デジタルアーキテクチャ研究センターが出しているガイドライン
- 「機械学習 AI を含むシステム全体を企画開発する企業などが、システム全体の利用時品質をライフサイクルプロセス全体を通じて確保するための必要事項を網羅的に分析し可能な限り列挙することが意図されている」
    - 外部品質や内部品質などの考え方がかなり体系的・網羅的に整理されている


### QA4AIガイドラインとAIQMガイドラインの関係

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551524/2c010b2f-5bb2-6d2b-a14a-a4a9d60c798a.png)

引用元

https://speakerdeck.com/tokuty/open-qa4ai-conference-2023-2024-01-17-qa4ainokoremadetokorekara?slide=12


## ISTQB FL Specialist AIテスティングシラバス
https://jstqb.jp/dl/JSTQB-Syllabus.Foundation_CT-AI_v1.0.J01.pdf
- JSTQBが出してる、ISTQBのAIテスティングのシラバスの日本語訳
- AIテスティングに関しての情報がかなり網羅されている
- AIをテストする上での前提となる「AIとは何か？」の説明に紙幅が割かれている
- 更にはAIをテストに活用する事例（QA4AIではなくAI4QA）も記載されている
- とはいえ正確にはガイドラインではなくシラバスなので、具体的な内容が書かれているわけではない

おまけ

https://sqripts.com/2023/09/05/67600/
- 上記シラバス作成に携わったStuart Raeid氏の記事の日本語版
- AIに対するリスクベースドテストの適用可能性について書かれている



### その他ガイドライン

#### 人間中心のAI 社会原則
https://www8.cao.go.jp/cstp/aigensoku.pdf
- 内閣府が発表した、AIの社会規範についてのガイドライン


#### AI・データの利用に関する契約ガイドライン

https://www.meti.go.jp/policy/mono_info_service/connected_industries/sharing_and_utilization/20180615001-2.pdf

https://www.meti.go.jp/policy/mono_info_service/connected_industries/sharing_and_utilization/20180615001-3.pdf
- 経済産業省が発表した契約に関するガイドライン
    - データ編とAI編とで分かれている
Git コンフリクトの解消

# 起こったこと
コンフリクトが起こった模様。
`This branch has conflicts that must be resolved`
`Use the web editor or the  to resolve conflicts.`

![スクリーンショット 2024-01-19 11.54.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/f591eda7-e6d3-bb7c-a0eb-1fbee86661f7.png)


# 起こった操作
Udemyの講座で自己学習中に、講座内で新しいの教えるからローカルのファイルを全部削除し、新しく作ろうとなった。
削除ののち新しいファイルをローカルで作って git push してPR作ったら発生した。


# 発生原因
1. 同じファイルの異なる部分を編集している:
複数のブランチで同じファイルの異なる部分が編集された場合、マージ時にコンフリクトが発生する可能性がある。

1. 同じファイルの同じ部分を編集している:
同じファイルの同じ行が異なるブランチで異なる方法で編集された場合、Gitはどちらの変更を優先すべきかを自動的に判断できず、コンフリクトが発生する。

# 解消方法
1. `Resolve conficts` を押してみる
![スクリーンショット 2024-01-19 12.07.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/e5b66c09-7655-79c6-b698-eccb712da7c7.png)

1. 差分内容を確認して、余分箇所を削除していく
    - 両方残したい場合は、このスクショで言うと以下の3つを消す。
        - `<<<<<<< make-hinagata`
        - `=======`
        - `>>>>>>> main`
    ![スクリーンショット 2024-01-19 12.10.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/bbf8c141-917e-c5aa-5804-70514ee13933.png)

    - 緑枠だけ残す操作をしたスクショ
        - この画面UI上で文字を消したりできる
        - `<<<<<<< make-hinagata`
        - `=======`
        - `オレンジ枠の内容全部`
    ![スクリーンショット 2024-01-19 12.17.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/bf9946b2-0f89-390d-7089-cd7d947ee4e9.png)
1. 書き換えて問題なければ右上の `Mark as　resolved` を押してみる。
チェックされてOK的なマークが出てくる。

1. 全部書き換えていくと右上の `conflicts` 数が0カウントで表示される。
![スクリーンショット 2024-01-19 12.19.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/f9324d3f-9364-a07f-4034-6ce6a7053bd3.png)

1. `confilicts` がなくて、各ファイルで `Mark as　resolved` を実施した状態
![スクリーンショット 2024-01-19 12.22.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/b6cc167f-5b99-9f2f-470a-5fbfa6aa097a.png)

1. 右上の `Commit Merge`　を押してみる。
1. コンフリクトが解消されたような画面に遷移する。
自分のスクショはPrivateの個人リポジトリなので、このような画面になる。
![スクリーンショット 2024-01-19 12.25.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/28318c47-c86d-4db1-af5f-d7591942e5ad.png)

# 所感
最初、めっちゃ焦るけど、差分を確認してマージしていくだけで良さそう。(当たり前か・・・)
これはチームでやっていたら、別の人と話しながら対処するのがベターな気がする。