OmniAICreator/Qiita-1.07M huggingface dataset:
CoreBluetoothForUnity のディレクトリ構造

## 本記事について

この記事は [CoreBluetoothForUnity Advent Calendar 2023](https://qiita.com/advent-calendar/2023/core-bluetooth-for-unity) の9日目の記事です。

CoreBluetoothForUnity の開発リポジトリのディレクトリ構造がなぜ現状のようになっているかについて紹介します。

## 前提

本ディレクトリ構成は hecomi さんの記事、構造を非常に参考にして作成しています。

https://tips.hecomi.com/entry/2021/10/29/001304

https://tips.hecomi.com/entry/2021/12/19/003344

公式カスタムパッケージの作成方法

https://docs.unity3d.com/ja/2022.3/Manual/CustomPackages.html

## パッケージ作成方針

私のパッケージ作成方針は以下のようにしました。

- ローカルパッケージとして作成 (Packages以下に配置)
- Native Plugin は同じリポジトリで開発する
- ドキュメントも同じリポジトリに含める
- Samples は開発しやすくするために Assets 以下に配置する
- インストール方法は複数対応しなくても構わない。

この方針にした理由を以下に記載します。

#### ローカルパッケージとして作成する理由

[公式ドキュメント](https://docs.unity3d.com/ja/2022.3/Manual/CustomPackages.html)より、パッケージの作成方法は 埋め込みパッケージ と ローカルパッケージ の2種類があります。

ローカルパッケージを選択した深い理由はありません。
ただ、パッケージは Packages 以下に入ってた方が自然だと思ったためローカルパッケージにしています。

#### Native Plugin は同じリポジトリで開発する理由

メリット・デメリット以下のように考えています。

- メリット
  - リポジトリ切り替える手間がなく楽
  - 変更履歴が一元管理できる。
- デメリット
  - リポジトリの肥大化
  - コミットログが混ざって汚くなる。

メリットの方が大きいと考え、同じリポジトリで開発することにしました。
この判断は正しかったと思っています。

プラグインの配置場所は hecomi さんの以下のリポジトリを真似しました。

https://github.com/hecomi/uTouchInjection/tree/master

#### ドキュメントも同じリポジトリに含める理由

ドキュメントというか docs フォルダです。
ドキュメントのフォルダ名はなんでもよかったのですが、UniTask や Unity 公式のリポジトリで docs という名前が使われていたためそれに合わせました。

GitHub Pages でリポジトリ内のフォルダを公開する設定にする場合には、
静的サイトでコミットログ汚くなるため別リポジトリにしてもいいかなと思っていました。

幸いCI で静的サイトをビルドし、GitHub Pages で公開する仕組みにできたため、変更差分はほとんど発生しなくなりました。
そのため docs には生成に必要なファイルのみを配置しています。

これについては別の記事に詳しく書こうと思っています。

#### インストール方法は複数対応していない。

単純に手間削減のためと、依存関係がどうなるかよくわかっていないためです。

CoreBluetoothForUnity は部分的に別パッケージに分離することを考えています。
従って、それらをまとめてインストールできる方法が望ましいです。

で、Git だとわからないけど、[Scoped Registry](https://docs.unity3d.com/ja/2022.3/Manual/upm-scoped.html)ならできそうということで npmjs で公開しています。

## 結論

以上を踏まえて、以下のようなディレクトリ構成にしました。

```
<Repository>
  ├── Assets
  │   └── CoreBluetooth
  │         └── Samples
  │               ├── 01_LightControl
  │               └── ...
  ├── Packages
  │   └── com.github.teach310.corebluetoothforunity
  │         ├── Runtime
  │         ├── package.json
  │         └── ...
  ├── docs
  ├── Plugins
  │   └── CoreBluetoothForUnity
  ├── ...
```

## おわりに

本記事では CoreBluetoothForUnity のディレクトリ構造について紹介しました。
私はこのディレクトリ構造に辿りつくまでに調査に何時間か使ってしまったためこの記事が誰かのライブラリ作成の時間につながればいいなと思います！
ImportError: No module named apex.fp16_utilsの解決方法（備忘録）

上記のエラーについて、今回は備忘録的に残しておきます！

1. [背景](#背景)
1. [過程（ソースコードを見てみる）](#過程ソースコードを見てみる)
1. [結論](#結論)


## 背景
Google Colabで学習済みのSSDを推論させるべく、必要なコードをColabに移植したところ、上記のエラー`ImportError: No module named apex.fp16_utils`が出てきました🫠
「これ、どうしたら良いんや、、、ライブラリのエラーとかどうしようもないやん、、、」
色々とIssueは立っていてインストール方法を変えるだのなんだのあったので全部試しましたがダメでした、、、

といったところで、apex（Github）のソースコードを見ることにした次第です。


## 過程（ソースコードを見てみる）
今回、importできないのはapexの中の*fp16_utils*です。つまり、ライブラリであるかどうかは置いといて、Pythonの構造的には**apex配下のfp16_utils**というディレクトリあるいは.pyファイルを確認すれば良いわけです。

実際にNVIDIA/apexを見てみると、以下のようになってました。
案の定`apex/fp16_utils`の構造ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/a36e0f34-2b2a-b6c7-dc18-c7f523b89a4a.png)

更に`fp16_utils`の中を見て、使用されているコードを引っ張って実質ライブラリを導入せずに使えるかどうか見てみます。（PyTorchはColabにデフォルトで入っているので考慮しなくてOK）

大体モジュールをExportしているのは`__init__.py`なので
そこから今回欲しいコードを入手します。

SSDで使いたかったのは`network_to_half`関数なので、そちらをメインで探します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/2c7471ab-a7f5-c879-5ffd-76287c94c519.png)

`__init__.py`を見ると、Githubの便利機能で`apex/fp16_utils/fp16_util.py`にあるとのこと。見てみましょう！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/facd0d25-6ca6-9b93-3f62-10cfb82c5802.png)

ここにありますね。よく見ると、依存している部分（Import）は全てPyTorchのみで
他のライブラリやApex内の他ファイルからImportしていないので、PyTorchが使える環境で、この関数に関するコードをそのままコピペすれば動作しますね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2017749/7c8e97f9-e86b-d9f4-e8f6-b594b85ed115.png)

## 結論
必要だった以下のコードをapexから取得し、そのままコピペ。
```python
import torch
import torch.nn as nn

class tofp16(nn.Module):
    """
    Utility module that implements::

        def forward(self, input):
            return input.half()
    """

    def __init__(self):
        super(tofp16, self).__init__()

    def forward(self, input):
        return input.half()

def BN_convert_float(module):
    """
    Utility function for network_to_half().

    Retained for legacy purposes.
    """
    if isinstance(module, torch.nn.modules.batchnorm._BatchNorm) and module.affine is True:
        module.float()
    for child in module.children():
        BN_convert_float(child)
    return module

def network_to_half(network):
    """
    Convert model to half precision in a batchnorm-safe way.

    Retained for legacy purposes. It is recommended to use FP16Model.
    """
    return nn.Sequential(tofp16(), BN_convert_float(network.half()))
```
【JavaScript】reduceメソッドの使いかた

## はじめに

[JavaScript Primerのサンプルコード](https://jsprimer.net/use-case/ajaxapp/display/#escape-html)に取り組んだ際、reduceメソッド部分の処理の流れが理解できず苦戦したので、簡単なサンプルを用いて整理しました。

## reduceメソッドとは

配列に対して使えるメソッドです。

配列の各要素に対してコールバック関数を実行した結果を足し合わせていき、すべてを足した結果を返り値とします。

```javascript
const totalValue = array.reduce(callback, [initialValue])
```
引数には以下を設定します。

- `callback`：配列の各要素に対して呼び出されるコールバック関数
    - `accumulator`：合計値
    - `currentValue`：現在処理している要素の値
    - `currentIndex`：`currentValue`の位置
    -  `array`：reduceメソッドが呼び出された配列
- `initialValue`： `accumulator`の初期値。省略可能

では、具体例として、**配列の合計値を求める処理**を見ていきます。[^1]

## 例1

`[1, 2, 3, 4]`という配列の要素を1つずつ足し合わせ、最終的な合計値を返し`totalValue`に格納する処理です。

初期値として、`initialValue`（reduceメソッドの第二引数）に0を設定しています。

```javascript
const array = [1, 2, 3, 4];

// 0 + 1 + 2 + 3 + 4
const initialValue = 0;
const totalValue = array.reduce((accumulator, currentValue) => {
    return accumulator + currentValue;
}, initialValue); // 初期値として0を設定

console.log(totalValue); // 10
```

コールバック関数の実行ごとの結果は以下のようになります。

|                 | accumulator        | currentValue | return する値 | 
| --------------- | ------------------ | ------------ | ------------- | 
| 1回目の呼び出し | 0  (initialValue） | 1            | 0 + 1 = 1     | 
| 2回目の呼び出し | 1                  | 2            | 1 + 2 = 3     | 
| 3回目の呼び出し | 3                  | 3            | 3 + 3 = 6     | 
| 4回目の呼び出し | 6                  | 4            | 6 + 4 = 10    | 

## 例2. `initialValue`を省略した場合

`initialValue`（reduceメソッドの第二引数）を省略すると、**コールバック関数を最初に実行したとき、`accumulator`には配列の最初の値が、`currentValue`には配列の2つ目の要素が格納されます。**

```javascript
const array = [1, 2, 3, 4];

// 1 + 2 + 3 + 4
const totalValue = array.reduce((accumulator, currentValue) => {
  return accumulator + currentValue;
}); // 初期値を省略

console.log(totalValue); // 10
```

コールバック関数の実行ごとの結果は以下のようになります。

|                 | accumulator      | currentValue     | return する値 | 
| --------------- | ---------------- | ---------------- | ------------- | 
| 1回目の呼び出し | **1 (array[0]の値)** | **2 (array[1]の値)** | 1 + 2 = 3     | 
| 2回目の呼び出し | 3                | 3                | 3 + 3 = 6     | 
| 3回目の呼び出し | 6                | 4                | 6 + 4 = 10    | 

初期値を設定した場合より、呼び出し回数が1回減ることになります。

[^1]: なお、今回の例ではコールバック関数の第三引数と第四引数は使用しないため指定しません。

## 参考

- [MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
- [JavaScript Primer](https://jsprimer.net/basic/array/#array-reduce)
闘魂Elixir ── Raspberry Pi OSでElixir 1.16.0-rc.0が動きました

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>



# はじめに

[Elixir](https://elixir-lang.org/) 1.16.0-rc.0を[Raspberry Pi OS](https://www.raspberrypi.com/software/)で動かします。
動くはずなんです。だけど百聞は一見にしかずです。自分で動かしてみないと気が済まないのです。

[Elixir](https://elixir-lang.org/)をRaspberry Piで動かすには、[Nerves](https://nerves-project.org/)という**ナウでヤングなすごいヤツ**を使うのがオススメです。
知っているんですよ、私は。
なんとなく（いや実はちょっとした事情があって)[Raspberry Pi OS](https://www.raspberrypi.com/software/)をインストールしたんです。
**当然**、[Elixir](https://elixir-lang.org/)を動かしたいじゃないですか。できるだけ新しいものを動かしたいのがアルケミストの心意気ってものじゃないですか！

# What is [Elixir](https://elixir-lang.org/) ?

[Elixir](https://elixir-lang.org/)という素敵なプログラミング言語があってがですね。
その素敵具合は「[Elixir Saves Pinterest $2 Million a Year In Server Costs](https://paraxial.io/blog/elixir-savings)」によく現れています。開発者も経営者もこの事実に瞠目することでしょう。 **$2 Million/年の節約ですってよ！、奥さん。**

https://paraxial.io/blog/elixir-savings

# 動きました :tada::tada::tada::tada::tada::tada:

Raspberry Pi 4を使いました。

![2023-11-01-ラズパイ4-elixir.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/079e3c43-d7e9-07fc-fe4c-eac8ad2eeb4c.png)

[Elixir](https://elixir-lang.org/) 1.16.0-rc.0のインストールは、[Nervesのドキュメント](https://hexdocs.pm/nerves/installation.html)をおおいに参考にしました。

https://hexdocs.pm/nerves/installation.html

ついでにAHT20で温度・湿度を測りました。

![2023-11-01-ラズパイ4-elixir2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131808/98076dc1-9ff9-753e-3642-e0da4e93ea30.png)



# さいごに

[Raspberry Pi OS](https://www.raspberrypi.com/software/)でElixir 1.16.0-rc.0が動きました。
**当然の結果です。**

さあ、そこのあなたも[Elixir](https://elixir-lang.org/)の世界へようこそ。
_手始めに[エリクサーチ](https://elixir-lang.info/)なんていかがでしょうか。私のオススメです。_

---

**闘魂**とは、  **「己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことである」** との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
**アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。**

---

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>
<b><font color="red">$\huge{１、２、３ ぁっダァー！}$</font></b>
自宅サーバの夢と課題

# 自宅サーバしたくない!?
自宅サーバの課題について書きたいと思います。

## 自宅サーバしたいのなぁぜなぁぜ
その周りの技術をしっかり学べる。実際に使えることで何かができる範囲が広がる。webサーバ、メールサーバ、DBサーバ、いろいろつくれる。VPSとかを契約しなくてもいいのも魅力的。

## 自宅サーバの課題①
#### セキュリティが心配!!
万が一、家のネットワークに侵入されたらやばい。セキュリティの徹底は確実に必要。

## 自宅サーバの課題②
#### ネットワークの制限
マンションなどのネット回線だとグローバルIPが一つしか割当たっておらず、自分が操作できるルータよりも外にルータ？的ななにかがあったりします。これのせいで外部からアクセスできない。これでめちゃくちゃ苦しんだ。そうすると外部サーバを立てて通信するしかなくなります。<それならそのサーバでよくない...

## 自宅サーバの課題③
#### 発火の危険性!!
PCは24時間起動されることを想定されていないため、発火して最悪火事になることがあるらしい。じつは結構危険みたい。

## まとめ
自宅サーバは魅力的だしやりたいけど、意外とリスク、問題がある。電気代とかを考えると費用的にもVPSとかを借りたほうが安上がりかも。
rex0220 計算式プラグインの使い方をGPTsに学習させてみる（その４）項目のタイプ別学習

[rex0220 計算式プラグインの使い方をGPTsに学習させてみる（その３）](https://qiita.com/rex0220/items/3d019e04b89cd208081d)の続きです。
項目のタイプ別に計算式の学習を行います。

# 概要
項目のタイプ別に計算式の指定方法を学習させます。

# 学習前の文字列項目の応答
結構まともな応答を返してくれるが、配列等を設定した場合の説明などが不十分。

![2023-11-15_16h40_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/0f606d91-a503-4a50-8e71-b26589451ab9.png)

# 文字列項目の学習
配列・チェックボックス・ユーザー選択等の扱いについて、説明を学習させる。

```fields1.txt
kintone の項目のタイプ別に、計算式の設定方法を解説

・文字列項目
文字列を返す計算式を指定する

文字列： "" で囲んだ文字列
 例：　"", "ABC", "あいうえお", "123"

文字列を返す計算式
 例：　文字列1, 文字列1 & "ABC", 文字列1 & 文字列2, LEFT( "ABC", 2), JOIN( ARRAY( "ABC", "XYZ" )), LOGIN_NAME()

数値を返すと数値を文字列として設定します。
　例： 123 -> "123", 1 + 2 -> "3"

配列を設定すると、「,」区切りで値を文字列に設定します。
　例：　ARRAY( "ABC", "XYZ" ) -> "ABC,XYZ"

チェックボックス項目、複数選択項目などの配列値をもつタイプの項目を指定した場合、「,」区切りで値を文字列に設定します。
　例：　チェックボックス1 -> "A,B" ※ チェックボックス1 の選択肢に "A", "B" が選択された場合

ユーザー選択項目、組織選択項目、グループ選択の配列でオブジェクトをもつタイプは、名称を「,」区切りで値を文字列に設定します。
　例：　ユーザー選択1 -> "ユーザー1, ユーザー2" ※ ユーザー選択1 に、ユーザー1, ユーザー2 が選択されていた場合
```

# 学習後の文字列項目の応答
応答内容に配列・チェックボックス・ユーザー選択等の説明が追加された。

![2023-11-15_16h43_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5dd82c6d-198f-1c10-9789-99dff3e6ad76.png)

# 学習前のチェックボックス項目の応答
応答がチェックボックス項目への設定の説明ではなく、チェックボックス項目の参照方法になっている。

![2023-11-15_17h28_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/f0b24c04-b4a7-770f-70ff-051851699002.png)

# チェックボックス項目の学習
チェックボックス項目への設定は配列を指定することをアップロード。

```.fields1.txt
・チェックボックス項目
配列で、選択肢の値を指定する

配列を返す計算式
　例：　ARRAY() -> 選択肢なし, ARRAY( "ABC", "XYZ" ) -> 選択肢 "ABC", "XYZ" を設定

他のチェックボックス項目の値をそのまま設定
　例： ARRAY(チェックボックス2)
```

# 学習後のチェックボックス項目の応答
チェックボックス項目への設定は配列を指定することを応答してくれる。

![2023-11-15_17h42_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/089b768f-1783-7646-1bd7-86ef1187a1a0.png)

# まとめ

kintone 項目のタイプによって扱い方が異なりますが、計算式もタイプに合わせて学習させる必要があります。
S3を用いて画像を保存する方法

# S3を用いて画像を保存する方法

Amazon Web Services（AWS）の中でも特に人気のあるサービスの一つが、Amazon Simple Storage Service（S3）です。このサービスは、インターネット上で大量のデータを保存・取得するための堅牢なストレージソリューションを提供します。ここでは、S3の基本概念、S3でバケットを作成する手順、RailsアプリケーションでS3をローカル環境および本番環境で使用する方法について詳しく解説します。

## S3とは

### スケーラブルなオブジェクトストレージサービス

Amazon S3は、インターネット上でのデータストレージとリトリーバルを提供するサービスです。ファイルや画像などのオブジェクトを保存し、必要に応じていつでもアクセスできるようにすることが可能です。

#### 特徴

- **高い耐久性**: データは複数の物理的な施設に跨って保存され、耐障害性が高いです。
- **容易なスケーラビリティ**: ストレージの容量を気にすることなく、必要に応じてデータ量を増やすことができます。
- **柔軟なアクセス制御**: AWS IAM（Identity and Access Management）を通じて、データへのアクセスを細かく制御できます。

## S3でバケットを作成する手順

### S3バケットの設定

S3でデータを保存するには、まずバケット（データを格納するためのコンテナ）を作成する必要があります。

1. **AWS Management Consoleにログイン**
2. **S3サービスページに移動**
3. **「バケットを作成する」をクリック**
4. **バケット名を入力し、リージョンを選択**
5. **必要に応じて他のオプション（バージョニング、ログ記録など）を設定**
6. **「バケットを作成」をクリックして完成**
7. **IAMユーザー等からのアクセスを許可する際はパケットポリシーの設定**

## RailsでのS3の使用

### ローカル環境での設定

RailsプロジェクトでS3を使用するには、まず必要なgemをインストールし、設定ファイルを編集する必要があります。

1. **Gemfileにaws-sdkを追加**
   ```ruby
   gem 'aws-sdk-s3', require: false
   ```
2. **Bundle Installを実行**
3. **`config/storage.yml`にS3の設定を追加**
   ```yaml
   amazon:
     service: S3
     access_key_id: <your_access_key_id>
     secret_access_key: <your_secret_access_key>
     region: <your_region>
     bucket: <your_bucket_name>
   ```
4. **開発環境の設定ファイル（`config/environments/development.rb`）を編集**
   ```ruby
   config.active_storage.service = :amazon
   ```

 **（`config/storage.yml`）を編集**
   ```yml
   service: S3
  region: ap-northeast-1
  bucket: パケット名
  access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
  secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
   ```

### 本番環境での設定

本番環境でS3を使用する場合は、セキュリティを強化するために、環境変数を介して認証情報を提供することが推奨されます。

1. **本番環境の設定ファイル（`config/environments/production.rb`）を編集**
   ```ruby
   config.active_storage.service = :amazon
   ```
2. **環境変数を設定**
   -

 AWSの認証情報は環境変数経由で安全に設定されるべきです。
   - Herokuなどのプラットフォームを使用する場合は、プラットフォームのドキュメントに従って設定してください。

## まとめ

AWSのS3は、安全かつ効率的な画像ストレージの選択肢として、多くの開発者に利用されています。バケットの作成から、Railsアプリケーションでの簡単な設定を通じて、ローカルおよび本番環境での画像保存が可能になります。セキュリティとアクセス管理に優れたS3を活用することで、アプリケーションの画像管理を効率化し、より安全なウェブサービスを提供できるようになります。
小ネタ：Microsoft Edgeが勝手に起動しないようにする

皆様こんにちは。
今回はちょっとした小ネタになります。
つい数日前にPCを起動した所、Edgeが勝手に開いてしまいました。
何も設定を変えていないのに何故……？自動でアップデートでも入ったのかな……？
Chromeを普段使いしているため少々煩わしく感じ(マイクロソフトさんごめんなさい)、設定を変えることにしました。
やってみたらとても簡単だったので、皆様に共有させていただきます。

# 設定方法
以下のように設定を行います。
ちなみにOSはWindows 10を使用しています。

**①Microsoft Edgeを起動し、画面右上の「･･･」を押す**
**②表示されたメニューの中から「設定」を選択する**
![Edgge設定完了①.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2150221/410e0d88-cb61-6d5e-b1e4-6d78f8bdf44c.png)
**③左メニューの中から「[スタート]、[ホーム]、および [新規] タブ」を選択**
**④「Windowsデバイスの起動時」の「Windowsにサインインすると、Microsoft Edgeが自動的に開きます」をオフにする**
![Edge設定完了②.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2150221/87f61bbd-76e2-3cc9-e296-9a5aae610fc9.png)
**スイッチアイコンが白背景に黒の丸ポチになっていればOKです！**

以上になります。
今回はメモ書き程度の記事になりますが、少しでも参考になれば幸いです。
Kubernetes上のNode.jsアプリケーションのHeapdump

Kubernetes上のnode.jsアプリケーションでメモリーリークをしている可能性があったので、Heapdumpを取って解析をすることにしました。

どのようにKubernetes上のnode.jsアプリケーションのHeapdumpを取得したか紹介したいと思います。

# Deploymentの変更
実際にある程度のロードがある状態でHeapdumpを取りたかったので、すでにデプロイされているDeploymentを少し変更して、そこからHeapdumpを取ることにしました。

本来はPodでNode.jsがスタートするように設定しますが、スタートのパラメータを変更したいので、一時的に

```bash
kubectl -n mynodejs edit deployment mynodejs
```
で以下のように`tail -f /dev/null`とかしてPodはスタートしてもNode.jsはスタートしないようにします。

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mynodejs
  namespace: mynodejs
  labels:
    app: mynodejs
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mynodejs
  template:
    metadata:
      labels:
        app: mynodejs
    spec:
      containers:
      - name: mynodejs
        image: mynodejs:1.2.3
        command: ["/bin/bash", "-c"]
        args: 
          - tail -f /dev/null 
```

これでNode.jsのPodをデプロイして、自動的に開始されないようにできました。何かの都合でデバッグ中にNode.jsが止まってもPod自体は動き続けるので、再度Node.jsをスタートしてデバッグでき便利です。

# Node.jsのスタートパラメータの変更
次にPod内のNode.jsにパラメータをつけてスタートします。

```bash
kubectl -n mynodejs exec mynodejs-1bw5d-1234 -it -- /bin/sh
node --inspect main.js
```

これによりデバッガーをアッタッチできるようになります。デフォルトで9229のポートを使っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/0ddc36a0-7cb2-fc32-d1bd-9d4a4afd006f.png)
Podのポート9299でデバッガーをアッタッチできる状態になりました。

# ポート転送
次にポート転送を行ってデバッガーでHeapdumpを採取します。

```bash
kubectl -n mynodejs port-forward mynodejs-1bw5d-1234 9999:9229
Forwarding from 127.0.0.1:9999 -> 9229
Forwarding from [::1]:9999 -> 9229
```
この例ですとLocal hostの9999からNode.jsの9229に転送されます

# Chrome DevTools
次にChrome DevToolsをつかってポート転送されたデータを採取します。
Chromeで`chrome://inspect`を開き
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/7d1d6bb6-c174-561d-c1cc-53d1a42789cc.png)

Configureボタンから転送ポートを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/75ebed44-822f-da59-9c75-7baf192f017a.png)

ポート転送の設定がうまく行くと画面がこのように変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/2b57088f-8daa-b164-fa34-542832f8abc2.png)

ここで`inspect`をクリックすると、デバッガーをアッタッチできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/1aef5224-aa3b-d264-c8db-54adda9bce1e.png)

これでHeapdumpをとったり、実際のアクセスの状況をトレースできたりします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/79638f30-94e8-6fb3-8813-b56317fe950e.png)

Heapdumpをとるとこのように、何にどれだけメモリーが使用されているかわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/1601d46a-58a3-44c5-fb21-8594be17dc9f.png)
git-secretsでパスワードのプッシュを防ぐ方法

# git-secretsでパスワードのプッシュを防ぐ方法

ソフトウェア開発において、セキュリティは非常に重要です。特に、誤って機密情報をGitリポジトリにプッシュすることは避けなければなりません。ここでは、git-secretsを使用してパスワードや秘密情報の不用意なプッシュを防ぐ方法を初心者向けに解説します。また、環境変数の設定方法とgit-secretsの導入手順、AWS関連情報の設定、GitHub Desktopでの使用方法についても触れます。

## 環境変数とその設定方法

環境変数は、オペレーティングシステムで設定される値で、プログラムの実行時に様々な情報を提供します。例えば、APIキーやデータベースの接続情報などの機密データを安全に管理するために用いられます。

### 設定方法

- **Windows**:
  ```bash
  set VARIABLE_NAME=value
  ```
- **Linux/Mac**:
  ```bash
  vim ~/.zshrc         
  
  export VARIABLE_NAME=value
  
  source ~/.zshrc    
  ```

## git-secretsについて

git-secretsは、誤って機密情報がGitリポジトリにコミットされるのを防ぐためのツールです。このツールは特定のパターン（例えば、パスワードやトークン）をスキャンし、それらがコミットされるのをブロックします。

## git-secretsの導入手順

git-secretsの導入は以下のステップに従います。

1. **git-secretsのインストール**:
   - **Linux** (Amazon Linux, Red Hat系):
     ```bash
     sudo yum install -y git-secrets
     ```
   - **Mac** (Homebrewを使用):
     ```bash
     brew install git-secrets
     ```

2. **リポジトリでgit-secretsを初期化**:
   ```bash
   git secrets --install
   ```

3. **機密情報が含まれないことを確認するルールを設定**:
   ```bash
   git secrets --add '秘密情報の正規表現'
   ```

## AWS関連情報の設定

AWSの資格情報やアクセスキーを誤ってコミットしないようにするため、git-secretsにはAWS関連の情報を検出するための設定が用意されています。

```bash
git secrets --register-aws --global
```

このコマンドを実行すると、AWSの資格情報に関連する一般的なパターンが自動的に登録されます。

## GitHub Desktopでの使用

GitHub Desktopでは、git-secretsを直接使用する機能はありませんが、コマンドラインを通じてgit-secretsを設定し、その後にGitHub Desktopでリポジトリを操作することができます。つまり、git-secretsの設定はGitリポジトリに紐付けられるため、GitHub Desktopでもその影響を受けます。


```bash
sudo cp /usr/local/bin/git-secrets /Applications/GitHub\ Desktop.app/Contents/Resources/app/git/bin/git-secrets

git secrets --install ~/.git-templates/git-secrets

git config --global init.templatedir '~/.git-templates/git-secrets'
```

## まとめ

git-secretsは、誤って機密情報をGitリポジトリにプッシュするリスクを軽減する強力なツールです。このツールを使用することで、セキュリティ違反を防ぎ、安全なソフトウェア開発プロセスを確立することができます。環境変数の適切な設定と組み合わせることで、機密情報の取

り扱いをさらに安全に管理できるようになります。また、AWS関連情報の自動設定機能やGitHub Desktopとの互換性もgit-secretsの便利な特徴です。
ChatGPTを用いたゲーム作成 - プログラミング言語：Python -

# 検証目的

私たちのチームでは近年、世間に浸透しつつある「ChatGPT」と技術的に多様な活用が出来る「Python」のそれぞれの有用性の組み合わせに注目しました。
また「ゲーム製作」に興味のあるメンバーも多かったため、「ChatGPTを活用したPythonゲーム製作の実行可否」を検証しました。


# 成果物
- ChatGPTに質問を繰り返し、Pythonを用いてゲームを製作
⇒「テトリス」を作成

![MiConv.com__メディア1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629109/322ae33a-5dae-1899-6ec5-9e46d735b5c0.gif)


# ChatGPTを利用したゲーム作成の詳細

## ①-1 広範囲の条件を指定して、ChatGPTに質問
### (例)Pyhotnではどんなゲームをつくることができるか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629109/261a0108-e8a6-c355-0113-959eab666848.png)

## ①-2 作成したいゲームを考え、条件を指定してChatGPTに作成を依頼
### (例)Pythonでテトリスの作成を依頼  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629109/d7fd8288-8def-bd6f-278b-c7094c849c6c.png)

## ②-1 追加したい機能について条件を指定して質問
### (例)ゲームの背景にグリッド線を追加したい場合のコードを質問⇒"pygame.draw.line()"関数を利用した方法を解答
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629109/05fd5fb6-8eca-e336-9bae-53e306518ac0.png)

## ②-2 バグに対する解決策を条件指定して質問
### (例)ブロック通過後にブロックの色が背景についてしまう現象について質問および解決策の提示を依頼  ⇒毎フレームごとに、背景にブロックの色が描画されないよう、フィールドの状態を一度クリアする方法を解答
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629109/275da9b0-551c-3464-f923-73b82d145824.png)

## ③ 稀にエラーや想定外の挙動が起きるコードを提示されることがある
### (例)ブロック消去の際、ポイント付与機能を追加しようと考え、コードを質問⇒実際にはエラーになり機能しなかった(今回は機能未搭載)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629109/fc3bdcd9-58ab-5cba-0232-e1f0c863f6da.png)


# 今後の展望

### 検証後の感想（メリット・デメリットについて）
- メリット（便利だと感じた点）
  - ChatGPTに質問した際、明確な条件を付けた場合は詳細に提案及び回答してくれること。
  - ゲーム作成の際、質問に対してChatGPTから具体的な回答やPythonのコード情報が得られた為、基本的な機能に関しては（一からのコード作成等）修正が不要であったこと。
- デメリット（不便だと感じた点）
  - 詳細な質問や条件指定をしない場合、意図した解答が返ってこないことがあること。
  - 稀に、機能しない情報（コード）を回答してくること。

### 今後の展望（作業活用の可能性について）
- 関連情報や製作に必要なコードを提示してもらえる為、一からの設計・情報収集の省略が可能。  
ただし、情報を得る為に複数回の質問が必要になる場合がある。
→機能がアップグレードすれば、情報を得る為のやり取りが減る可能性がある為、機能向上に期待。
- 質問する際、内容や条件を明確にする必要がある。（具体的な質問をしないと必要な情報が帰ってこない。）
→ChatGPTに100%の答えを求めるのではなく、あくまで参考情報として柔軟に活用する必要がある。  
また、質問内容によって回答内容も変わる為、質問者の理解度向上も重要。


# 終わりに

ChatGPTを利用してのゲーム作成を通じて、チーム全体的に以下のような取り組みを行うことができました。

- Pythonの学習の機会
  - ChatGPTを使用してゲームを作成するプロセスにおけるゲーム構成やデバックを行うことで、Pythonの学習に役立てることができた。
  - 新しいスキルを習得する過程で、文法、アルゴリズムの理解など、Pythonプログラミングの基本的な概念の理解を深めることができた。
- 実践的な経験
  - ゲームを設計することで、プログラミングの実践的な経験を積むことができ、  
  理論的な知識だけでなく、実際の問題へ対処するスキルもChatGPTを通じて向上することができた。
CSS 中央, 右, 左寄せの方法メモ

# 概要
マークアップに慣れるまで縦横 中央,右,左寄せを毎回調べていたのでメモ
本記事の方法以外にも手法はあるがよく使うものだけ抜粋


## 前提: ボックスモデルとは
1. インラインボックス
    1. `<span>, <a>`など、同一行で横並びに配置されるもの
    1. 幅・高さの指定はできない
    1. 上下マージンの指定はできない
1. ブロックボックス
    1. `<div>, <p>, <ul>, <ol>, <table>`など上から下に配置されるもの
    1. 幅・高さ・パディング・マージンを設定できる

## text-align
条件
1. 親がブロック要素である
1. インライン要素の左右に余白があること
1. 子のインライン要素が移動する

利用方法は
1. 親のブロック要素に対して text-alignを設定する
```
●HTML -------------------------------
<div class="outer"> // ブロック要素
    テキストテキストテキスト // インライン要素
</div>

●CSS ---------------------------------
.outer {
  width: 100%;
  // 以下を追加
  text-align: center; //left, rightなど
}
```

mdn: https://developer.mozilla.org/ja/docs/Web/CSS/text-align

## margin
条件
1. ブロック要素の左右に余白があること
1. ブロック要素ごと移動する

利用方法は
1. ブロック要素に対して`margin: 0 auto`を設定する
1. 縦移動についても同じ
```
●HTML -------------------------------
<div class="outer"> // ブロック要素
    <div class="inner">  // ブロック要素
        テキストテキストテキスト // インライン要素
    </div>
</div>

●CSS ---------------------------------
.outer {
  width: 100％;
  height: 1000px;
}
.inner {
  width: 50%  // 親要素の半分の横幅を指定して余白を作る
  height: 200px;
  // 以下を追加
  margin: 0 auto;
}
```

## display: flex
条件
1. 子のブロック要素の左右に余白があること

利用方法は
1. 親に対して
    1. display: flex
    1. justify-content: center  // 横移動
    1. align-items: center  // 縦移動
```
●HTML -------------------------------
<div class="outer"> // ブロック要素
    <div class="inner">  // ブロック要素
        テキストテキストテキスト // インライン要素
    </div>
</div>

●CSS ---------------------------------
.outer {
  width: 100％;
  height: 1000px;
  // 以下を追加
  display: flex;
  justify-content: center;
  align-items: center;
}
.inner {
  width: 50%  // 親要素の半分の横幅を指定して余白を作る
  height: 200px;
  margin: 0 auto;
}

mdn: https://developer.mozilla.org/ja/docs/Web/CSS/justify-content
```
VSCodeのインデント関連をまとめてみた


VSCodeのインデント関連が、初見では結構ややこしいのでまとめてみました。

# 環境

- Windows 11
- VSCode 1.84.2

# 設定系

## Editor: Insert Spaces

`Tab`キーを押したときに、スペースを入れるかタブ文字を入れるかの設定

:::note  warn
注意
この設定は、厳密に言うと**ファイル作成時の既定のインデント**ですので、
既に作成したファイルの場合は、上書きできません。
後述の**変換**を使用してください。
:::

## Editor: Tab Size

インデントがスペースの場合はスペースの数、タブの場合は表示が何文字分かの設定

:::note warn
注意
`Editor: Insert Spaces`と同様に、既に作成したファイルには上書きできません。

また、タブの表示はVSCodeのみ有効で、メモ帳などには反映されません。
:::

## Editor: Detect Indentation

上二つの項目をファイルごとに自動で設定するかの項目。

基本的に有効がおすすめ。

# ステータスバー系

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621500/c738cb72-dae5-6447-e8c2-b905eabaf759.png" alt="スタータスバーの「スペース: 4」を矢印でさしている画像"></img>

ここからはここを押したら出てくるメニューについてまとめます。

## スペースによるインデント

入力するインデントをスペースにする。
また、スペースの数も1~8の間で選ぶことができる(おすすめは4 or 2)

:::note warn
注意
既存のインデントは変更されない。
:::

## タブによるインデント

入力するインデントをタブ文字にする。
また、タブ文字の表示も1~8文字分の間で選ぶことができる。(おすすめは4 or 2)

:::note warn
注意
既存のインデントは変更されない。
:::

## タブの表示サイズを変更

タブ文字の表示を1~8文字分の間で選ぶことができる
**変更するのは表示のみであり、スペースの数やインデントに変更はない。**

## 内容からインデントを抽出

ファイルのインデントを抽出して設定する。
なお、スペースとタブ文字が混ざっている場合は数が多い方が優先される。

## インデントをスペースに変換

既存のインデントを全てスペースに変換する

## インデントをタブに変換

既存のインデントを全てタブに変換する

## 末尾の空白をトリミング

行の末尾にある空白を削除
Regexp.last_match(1)の地雷のような挙動を踏み抜いてしまった話

# 事象発生
「画面に表示される金額がおかしい」とクレームがあったのが先月。
該当の画面はDBからレコードを取ってきて表示するだけのシンプルなもので、バグりようがない。コードはこんな感じ。

```ruby
class SomeRecord < ApplicationRecord
  scope :by_code, ->(code) {
    if /abc(\d+)/ =~ code
      where(code: $1)
    else
      none
    end
  }
end
```
どうせ客の見間違えだろうと放置していたところ、他にも似たような問い合わせがちらほら来るように。
さすがに金額がおかしいのはやばいだろ、来週までに直しといてと言われたので仕方なく調査。
# 原因
* 公式ドキュメントに嘘が書いてあった。

https://docs.ruby-lang.org/ja/latest/method/Kernel/v/1.html

どうやらRegexp.last_matchや$1等の変数は、procの中で使った場合
「ローカルスコープかつスレッドローカル」ではないらしい。


```ruby
P = ->(str) {
  /abc(\d+)/ =~ str
  sleep 0.5
  puts "str=#{str}, Regexp.last_match(1)=#{Regexp.last_match(1)}"
}

def f1
  Thread.new { P.call('abc100') }
  Thread.new { P.call('abc200') }
end

f1
sleep 5
```

結果
```
str=abc100, Regexp.last_match(1)=200
str=abc200, Regexp.last_match(1)=200
```

1回目は`str=abc100, Regexp.last_match(1)=100`と出力されるはず。
しかしもう片方のスレッドによって結果が上書きされて`str=abc100, Regexp.last_match(1)=200`と出力されてしまっている。

# 対処方法
正規表現のマッチ結果を一旦変数に入れる

```ruby
P2 = ->(str) {
  m = str.match(/abc(\d+)/)
  sleep 0.5
  puts "str=#{str}, m[1]=#{m[1]}"
}

def f2
  Thread.new { P2.call('abc100') }
  Thread.new { P2.call('abc200') }
end

f2
sleep 5
```
結果は期待通り
```
str=abc100, m[1]=100
str=abc200, m[1]=200
```

# まとめ
rubyの正規表現でlast_matchや$1等は使わず、マッチ結果は一度変数に入れた方が安全。

公式で報告されてないのかなと思ったら以下のチケットが該当する模様。
https://bugs.ruby-lang.org/issues/8444

10年前に報告されて今までほったらかし、ドキュメントだけしれっと修正という対応を見ると、今まで踏む人がいなかったんだろうな。
2023RCJ WRL polaris チーム運営

## 概要
ここでは RCJワールド･レスキューライン出場チームのチーム運営について記述する。
機体開発の上でどこに要点を置き何に注意するか、3年の間で考えたことを綴る。

## 前置き
### チーム
polaris 普通高一年4人編成
学校なので金銭面は多少なんとかなる
多少無駄買いしても10万はいかなかった

### 機体
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3515767/26d7eabb-ac5f-eadf-175c-211fe77b51ce.png)
(回収機構のついていない姿)


### 結果
ブロック大会出場

## 開発日誌
~7月 基本仕様の決定 のための試作など
8~10月 基底ハード制作
11月前半 ハード完成とする これ以降基本変えない
11月後半 ソフト試作
12月前半 マーカー動作までプログラム制作
12月後半 障害物など制作
12/25 ノード大会当日
直前調整 ハード問題はもう無視
1/8 ブロック大会当日

## ハード班のすすめ
・とにかくハード班は最速で機体を制作し、ソフト班からダメ出しをもらうこと。完成させる必要は無いが、ソフト班が困るような変更がもう必要のない状態であるべき。

・駆動周りは1度決めたら設計側の都合で変えない。駆動そのものの問題を早急に解決して、もう変更しないようにしよう。ソフト班が困る。

・回収機構は後回しにする。ライントレースに必要なハードを完成させてから、ゆっくり考えてください。(駆動周り弄れないのでほぼスペースないと思うが 頑張れ)

・本番が近づいたら、ハード側の改修は避けよう。できる限りソフト側で修正する。プログラ厶はいくらでも修正できるからね。

## ソフト班のすすめ
・ハード班と分担して、回路の問題(センサー見れないなど)はハード班に解決してもらう。ハード側の問題に気づかず時間を浪費してしまう。

・基本から1つづつやっていくしかない。ハードができたらひたすら持久戦。

・本走行向けにエラー落ち回避は重要。おすすめは別ファイルからコード実行するやつ。デバック性も上がる。

・暇になったら(ならないかもだけど)デバック性向上に努める。

## メンバーみんなのすすめ
・自機の得意不得意を把握する。不得意を減らすように頑張るだろうが、得意な部分でミスをしないことも重要である。この競技はノーミス点が高い:1回のミスで大幅に得点が下がる。

・作業記録をとる。動画ひとつでもいいし、ツイートでもいい。メモにまとめてあるとなお良い。次年度に非常に役立つ上、競技関係なく自分の糧になる。

## 本番の立ち回り
・本番は最後の頑張りだと思って開発環境全部持っていこう。自室全部くらいの気持ちでいい。絶対あのあそこに置いてた六角レンチ忘れる。

・予備部品は必須。電子部品は当然、機体に使った兌換性のあるアクリル板などもあった方が良い。輸送中の破損などの心労を減らせる。

・会場をある程度把握しておく。現地作業がある場合特に。インターネット環境の有無など。(会場によってはモバイル通信も怪しい)

・いつでもルールを参照できる状況にする。稀にルール違反コートがある。

・調整中、暇なメンバーで本走の作戦を建てる。「どこが苦手でどこが得意か」、「どこを得点源としどこを捨てるか」、「その判断はいつどんな条件で行うか」まで全て考えよう。具体的な点数も出して見るのも良い。本番は1ミスで頭真っ白になるので………｡

・コートをくまなく見る。言い方悪く言うと粗探しする。あとから不備を見つけても遅い。よくあるのは 坂バンプシーソーの間のライン欠け 、 緑マーカー剥がれ 、 黒ずみ汚れ 。障害物設置違反、瓦礫サイズ違反なども留意。

## 総合記事リンク

https://qiita.com/rakurobo68th/items/bb5cfbd359a3ea8e4670
RCJ WRL polaris 開発目録 はじめに

## まえがき
このアカウントはロボカップジュニア(通称RCJ)にワールド･レスキューライン競技で出場しているチーム｢polaris｣の開発目録である。
同競技に出場するチームや、ロボット開発に取り組むエンジニアの参考になれば幸いである。

## チーム紹介
洛星高校ロボット研究部 68th polaris
<details> <summary></summary>

</details>


## 2023RCJ
### ソフト
https://qiita.com/rakurobo68th/private/a21e7cd36906e91b9c57
### ハード
https://qiita.com/rakurobo68th/private/56a73a24d187e7785938
### チーム運営
https://qiita.com/rakurobo68th/private/1cff21da498547fcbdaf

## 2024RCJ
［随時更新中］

### 京都ノード大会
https://qiita.com/rakurobo68th/items/e99acef34bf4a8933ecd
コードレビューの完了時間を30%削減した時の取り組み

## この記事では
「プルリクエストをマージするまでの時間を削減したい」
そのような方向けに、チームで行った取り組みをいくつかご紹介します。

## 背景
私の所属するチームでは「プルリクエストを作成してからマージされるまでの期間が長い」という課題を抱えていました。
変更行数が数十行のものでも０～３日、変更行数が多かったり新人のものだと１週間以上・・・

その課題は、さらに以下のような課題の原因となっていたよう思われます。
- 競合の発生が増える
- 後続のプルリクエストを出せない
- 開発者の脳内スイッチングコストが増える
- リリースタイミングが読めなくなる

## レビュー期間が延びる原因

大きな原因としてはまず、各プルリクエストをメンバー全員（開発者５名ほど）でレビューしていることが考えられます。ただ、全員レビューの目的もありますので（[おまけ参照](#おまけ全員コードレビューの目的と問題点)）、まずは全員レビューを維持した上での取り組みを検討することにしました。

開発メンバー全員で原因をディスカッションしたところ、以下があがりました。
- プルリクエスト内のコミュニケーションに時間がかかる
    - 指摘 → 返答 → 議論...のタイムスパンが長い
    - コメントに気づきにくい、返信を忘れる
- レビュー時間を確保できない
- プルリクエストの優先度が自分の中で低い
- 変更量が多いとレビュー負荷（工数的にも精神的にも）が高い
- 簡単にレビューできるものだったとしても、リンクを開かないと簡単だと気づけない

## 取り組み内容
ディスカッションした内容を元に、以下を行うこととしました。

1. [優先度の意識の改善](#優先度の意識の改善) 
1. [デイリースクラムでのレビュー残の確認](#デイリースクラムでのレビュー残の確認)
1. [もくもくレビュー会の実施](#もくもくレビュー会の実施)
1. [プルリクエストのテンプレートの利用](#プルリクエストのテンプレート利用)
1. [プルリクエストを見てもらうための工夫](#プルリクエストを見てもらうための工夫)

残念ながら、１回のプルリクエスト内の変更量を削減するための取り組みはまだできていません。

### 優先度の意識の改善
原因にありましたが、元々レビューの優先度は開発者の中では高くないようでした（そりゃコード書く方が楽しい）。
とはいえ全体の生産性に関わるため、開発者のマインドを変えるべく、以下を提案しています。

- レビューの優先度を普段の開発タスクより高くしよう
- レビュー指摘に対する修正の優先度を普段の開発タスクより高くしよう

※いきなりこんなことを言うと反発を生むので、自分事として捉えてもらうための活動は必要と思います。雑談に含めたり、メンバー間で問題点を話し合ったり。

### デイリースクラムでのレビュー残の確認
プルリクエストの承認状況をデイリースクラムで共有するようにしました。
Googleスプレッドシートで画像の内容を見えるようにしています。（変更行数多いな・・・）
![承認状況.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620254/5fa6ba49-477c-97ef-ce4d-0e00ed6265ef.png)

### もくもくレビュー会の実施
15~30分のデイリースクラム後、30分のレビュー時間を確保するようにしました。
全員オンラインの状態を保ち、確認点あれば口頭または画面共有で確認します。そして、口頭での結論のみをプルリクエスト内に残します。

### プルリクエストのテンプレート利用

記載内容の統一化のため、プルリクエストのテンプレート機能を利用することとしました。
「あれどうなった？」という余計なコミュニケーションを生まないという効果を見込めます。

### プルリクエストを見てもらうための工夫

見るべきものがわかりやすいよう、タイトルにキーワードを埋め込むようにしました。キーワードは【簡単】【至急】などです。
ささいな工夫ですが、精神的負担を減らす、優先順を迷わないようにする、といった効果があります。

## 結果
運用を変えてから１ヶ月後、改善効果を測るために運用改善前後を同条件で比較してみたところ、画像のようになりました。

![改善結果2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620254/bcded530-d472-9454-d282-a42a2f7636a8.png)


中央値こそ変わりませんが、平均およびバラつき（分散・標準偏差）の改善を確認できています。１日で確認を終えているものの割合が減った理由は、新機能追加のチケットの割合が多いためと思われます。
全員コードレビューの体制を維持しつつ、日数を削減できたことはとても良いことと思われます。

メンバーからも「感覚的にもプルリクがマージされやすくなった」「ちょっとした口頭のコミュニケーションが取りやすくなった」「開発リズムが安定した」といったポジティブな声が出ています。

## 今後
１回のプルリクエストの変更量を下げる取り組みなど、継続して改善活動を続けていく予定です。

## おまけ：全員コードレビューの目的と問題点
### 目的
- ソースコードの共同所有を促進する
- 実装方法を学ぶ
- レビュー観点を広げる（人によって注視する観点が異なるため）

### デメリット
- レビュー時間がかかる
- レビューコストがかかる
- （目的を共有できていない場合）「やらされている」と考えてしまう
開発中に画像が消失？Expoのファイルシステムと相対パスの重要性

# はじめに

### 対象読者
ReactNative、Expoでアプリ開発を行っている人
expo-file-systemを使って画像データをローカルにキャッシュしたい人
npm run iosなどでアプリを立ち上げ直すと画像が表示されず困っている人

### 読者への思い
Expoでアプリ開発中に画像の保存や表示でかなり詰まったので同じ罠にハマっている人がいたらこれ見て解決してください！

# その時の現状と問題点

私は**ReactNative**と**Expo**、**Firebase**を使ってアプリを開発しており、アプリとFirebase間での通信をなるべく減らすべく、ReactNativeの**AsyncStorage**とExpoの**expo-file-system**を使って画像をキャッシュをローカルに作れるようにしようとしていました。

システムの概要はこちらになります。
![無題のプレゼンテーション (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2509924/c09581c5-5cf9-f744-c0cd-bd266317460b.png)
1. FirebaseのStorageに画像を保存しており、そのファイルパスをFireStoreに保存しています。
2. アプリはFireStoreからStorageのファイルパスを取得し、Storageからその画像ファイルをダウンロードします。
3. 一度取得した画像はキャッシュとして使い回したいので、expo-file-systemを使用して保存し、expo-file-systemのファイルパスをAsyncStorageで保存していました。

実際に最初にダウンロードし、表示させた結果がこちら

<img width="300" alt="Simulator Screenshot - iPhone 15 Pro Max - 2023-11-15 at 16.09.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2509924/09c985bf-3e6d-adf9-55ec-54ef28bcce06.png">

これはリロード(rコマンド)をしても変わらず表示されて期待通りです。

しかし、ctrl+cでアプリを止め、再度`npm run ios`でアプリを立ち上げた際に、以下のように画像が表示されなくなってしまいます。

<img width="300" alt="Simulator Screenshot - iPhone 15 Pro Max - 2023-11-15 at 16.08.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2509924/2b13c961-43ff-67a5-b445-e743b86f8040.png">

この原因について調べることにしました。

# 解決法

問題を調べていく中で、画像のファイルパスは正しく保存されており、特にエラーも出ていないことから、expo-file-systemから画像をうまく取得できていないことがわかりました。
そこで調べていくと、、、

https://github.com/expo/expo/issues/4261

こちらの記事に辿り着きました。

結論として、iOSシステムはビルド間でパスが継続することを保証していないため、相対パスを使用することで、異なるアプリビルドやバージョン間でファイルへのアクセスを維持することができるとのことでした。

私はexpo-file-systemの絶対パスをAsyncStorageに保存してそれをImageのsourceに入れていたため、`npm run ios`で立ち上げ直すと画像の保存されているパスとは別のパスにアクセスしてしまい、取得できていなかったのです。

### 使える関数等

ここでは上記の問題を解決するためのコードなどを紹介します。

```javascript:getDownloadImage.js
import * as FileSystem from 'expo-file-system';

export default function getDownloadedImageUri(relativePath) {
  return `${FileSystem.documentDirectory}${relativePath}`;
}
```
こちらは相対パスから画像を取得する関数です。相対パスを引数にFileSystemのパスへ変換します。

```javascript:ccreateImagesDirectory.js
import * as FileSystem from 'expo-file-system';

export default async function createImagesDirectory() {
  const imagesDir = `${FileSystem.documentDirectory}images`;

  const dirInfo = await FileSystem.getInfoAsync(imagesDir);
  if (!dirInfo.exists) {
    await FileSystem.makeDirectoryAsync(imagesDir, { intermediates: true });
  }
}
```
こちらはFileSystem内にimagesというディレクトリを作成する関数です。こちらを使いimagesの直下に保存するようにすると良いでしょう。

```javascript
await createImagesDirectory();
const relativePath = `images/${filename}`;
const downloadDest = `${FileSystem.documentDirectory}${relativePath}`;
```

このようにすることで、画像の保存も取得も可能になります。

# まとめ

画像の保存には相対パスが大事！！！
指定したパスで経路を探索する

# はじめに
ツリー構造になっているオブジェクトに対して、
指定したパスが存在するかどうか判定する処理を施す際になかなかいい処理が思い浮かばず…
何とか絞り出して、処理を実装することが出来ました…
## ツリー構造とは
枝分かれになっているデータ構造のことを言います。

上の部分が「親」または「根」といい、
そこから枝分かれで生えているのが「子要素」になります。

それぞれの領域を「ノード」、それらを繋いでいるのを「エッジ」といいます。

そして、子要素の無いノード、要は末端のノードは「葉」「リーフノード」と呼ばれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2641311/739e775c-a87b-6afa-6c1f-4a9bddf91a09.png)


https://wa3.i-3-i.info/word1257.html

## ソース

```python
def search_path(_module, path):
    path_parts = path.split("/") # 検索するパスを'/'で分割して配列化

    current_module = _module     # 現在いる階層を定義
    for part in path_parts:      # 分割したパスを1階層ずつ見ていく
        found = False            # 発見フラグを初期化

        for ch in current_module.children: # 各ノードの子要素は配列を想定
            if ch.name == part:            # 階層名と一致したら、
                current_module = ch        # current_moduleに発見した階層を代入
                found = True               # 発見フラグを更新
                break
            else:
                if found:                  # 階層名が一致していなかったら、Falseに更新
                    found = False
        if not found:
            return False
    return True
```

# 終わりに
本当は再帰関数を利用する手もあったかもしれませんが、
私自身理解が浅いため危ういと判断しやめました。

ですが、次回こういった処理に出くわした際には実装できるように
再帰関数についても理解を深めていきたいです。
Dockerイメージ作成の方法

こんにちは　

IBMのDB2を使って、デプロイをする機会があり、そこで学んだこといつでも見返せる様に投稿しました。

本投稿では、Dockerイメージの作成について記述してあります。

Dockerとはコンテナ仮想化を用いてアプリケーションを開発・配置・実行するためのオープンプラットフォームです(wikipedia引用)。

Dockerイメージ作成の手順
①Podmanのインストール
➁Dockerfileの作成
③Docker Image Build

Dockerイメージの作成はデプロイする上で必ず必要になります。



本題
①Podmanのインストール

Podmanのインストールはこちらから行ってください。　https://podman.io/　　　

インストール完了したら、VScode等で以下を入力し、成功したらバージョン情報が表示されます。

 　podman --version


➁Dockerfileの作成

ビルド情報を定義するDockerfileを作成します。　以下のコードを参考に
 こちらはVScode等で新たにファイルを作成し、入力してください。
　FROM node:16-alpine AS build
　WORKDIR /usr/src/app
　COPY package*.json ./
　RUN npm install
　COPY . .
　EXPOSE (ポート番号)
　CMD ["node", "app.js"]


③Docker Image Build

上記のDockerfileを作成後以下のコードを入力

　 Podman build --tag○○：○○.   (○○にはファイル名と番号を記載)
  
問題なくビルドされれば、FINISHEDになります。

最後にBuildしたDockerfileを確認するために以下のコードを入力

　podman images　(入力すると以下の5点の情報が表示される)
  　REPOSITORY　　TAG　　IMAGE ID　　CREATED　　 SIZE


    
以上がDockerfileの作成方法です。
【Exchange】リモートドメインで制御可能な自動応答機能について

## Exchangeにおけるリモートドメインとは
Exchange管理センターより設定可能な項目に”リモートドメイン”という設定があります。

[リモートドメイン](https://learn.microsoft.com/ja-jp/exchange/mail-flow-best-practices/remote-domains/remote-domains)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618331/7133de37-2065-1b61-28e4-6bc7860afd03.png)
*[Exchange管理センター]-[メールフロー]-[リモートドメイン]-[Default]*

こちらの設定を操作することでユーザーが外部ドメイン宛に送信するメッセージの種類や形式を制限することが可能です。
それらの設定の1つ、”メールの返信の種類-自動応答”機能が何を制限する機能か判りづらいため、当記事で動作を確認します。


## 設定対象
以下画像箇所の設定が対象です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618331/d8275a9d-2b3d-fabe-7f50-890aa8962751.png)
*[Exchange管理センター]-[メールフロー]-[リモートドメイン]-[Default]-[メール返信の種類]*

既定では画像の通りに、”不在時の自動応答の種類”は”外部の不在時返信のみを許可する”となっており、”自動応答”の項目はどちらも☑（有効）状態です。

一見、”不在時の自動応答の種類”という項目と”自動応答”の項目の内容が重複しているように見えます。
ただし、実際は異なる制限を施す設定値となるためその影響範囲を理解することが必要です。


## 設定影響
### 1.不在時の自動応答の種類
”不在時の自動応答の種類”で制御される項目は、ユーザー個々が作成する”自動応答”の機能です。
（対象：Outlookクライアント、Outlook on the web）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618331/4183eec9-e03b-87a6-b84a-b5e486446cda.png)
*[Outlook on the web]-[設定]-[メール]-[自動応答]*

こちらの機能は予め組織内・組織外ごとに文章を作成し、ユーザーそれぞれが不在（＝長期休暇など）のタイミングで有効にすることで自動応答を利用することが可能です。

”不在時の自動応答の種類”の設定影響は以下の通りです。
| 設定 | 概要 |
|:-|:-|
| なし | 内部の送信者にのみ自動応答を送信し、外部宛には自動応答を送信しません。 |
| 外部の不在時返信のみを許可する | 組織内には組織内向けに作成した自動応答のテンプレートを送信し、組織外には組織外向けに作成した自動応答のテンプレートを送信します。 |
| 外部とレガシの不在時返信を許可する | 組織内には組織内向けに作成した自動応答のテンプレートを送信し、組織外には組織外向けに作成した自動応答のテンプレートを送信します。※ [従来の不在応答] につきましては、Outlook 2003 以前の自動応答機能を指しております。 |
| 内部の不在時返信を許可する | 自動応答は組織外 / 組織内ともに動作しますが、組織内向けに作成した自動応答のテンプレートが組織内 / 組織外に送信されます。 |


”不在時の自動応答の種類”が既定値であれば、ユーザーの自動応答設定の通りに動作が行われます。

:::note warn
要注意点は以下2点です
・[なし]とした場合でも、内部の送信者には自動応答は送信されます。
・[内部の不在時返信を許可する]とした場合でも、組織外の送信者に自動応答は送信されます。
:::

設定値の文言通りに受け取ると勘違いする可能性があります。

### 2.自動応答を許可する
”自動応答を許可する”で制御される項目は、ユーザー個々が作成する”仕分けルールの処理の一部”です。
（対象：Outlookクライアント）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618331/f3aa0e3a-e38b-cd3b-71cf-41a5d79867e9.png)
*[Outlookクライアント]-[ファイル]-[仕分けルールと通知]*

仕分けルールの作成時、実行する処理の中に”通知メッセージを使ってサーバーで返信する”という項目があります。
こちら処理は予めメッセージを設定し、仕分けルールの条件に沿った際にその設定したメッセージを自動で送信する動作です。

”自動応答を許可する”が既定値であれば、該当する仕分けルールは設定どおりに動作が行われます。
設定値を□（無効）にすることで、該当する仕分けルールの動作を無効にできます。

仕分けルールの処理が疑似的な自動応答のような処理となっており、それを制御するための設定値となっています。

### 3.自動転送を許可する
”自動転送を許可する”で制限される項目は、ユーザー個々が作成する”転送”処理です。
（対象：Outlookクライアント、Outlook on the web）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618331/21a26000-93bb-b8bd-6a82-5859e29cba96.png)
*[Outlookクライアント]-[ファイル]-[仕分けルールと通知]*
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618331/19ba1903-60c4-edd9-b594-76bae5a17865.png)
*[Outlook on the web]-[設定]-[メール]-[転送]*

メールの転送先としてアドレスを入力することで、組織内・組織外問わずメールを転送することが可能な機能です。


”自動転送を許可する”が既定値であれば、ユーザーの設定通りに転送処理が実行されます。
設定値を□（無効）にすることで、組織外へのメール転送処理は無効化されます。

※管理者がユーザーに対して自動転送を設定していた場合、リモートドメインの設定を受けません。
（メールボックスに対しての転送設定、トランスポートルールによる転送設定）


## まとめ
"自動転送”の設定値に関してはイメージする通りの動作かとは思いますが、”不在時の自動応答の種類”、”自動応答を許可する”の2つの設定値は文言が似通っており判りづらくなっております。

特に”自動応答を許可する”設定を無効にすることで、ユーザーが個々に設定する[自動応答]設定に影響が及ぶものだという勘違いが発生しやすいです。

設定の影響範囲を正しく理解して、設定変更を行いましょう。
プロビット回帰分析 

## 1.プロビット分析とは

プロビット分析とは、重回帰分析において被説明変数をダミー変数（0と1など）に置き換えることにより、被説明変数$Y$が1になる確率が他の説明変数$X$に影響されているかどうかを調べる手法である。


以下、$\Phi$を標準正規分布関数とする。
$$\Phi \left( x\right) =\int ^{x}_{-\infty }\dfrac{1}{\sqrt{2\pi }}e^{-\frac{1}{2}t^{2}}dt$$

プロビット回帰は **連結関数(リンク関数, link function)** として$\Phi^{-1}$を用いた場合の一般化線形モデルの例である。

## 2.連結関数とは

通常、回帰モデルでは、予測変数と応答変数の間の関係を線形にすることが期待される。しかし、応答変数が線形ではなく、例えば0から1の範囲に制約されている場合や、指数的に増加する場合などがある。そのようなときに、リンク関数を使って、応答変数を予測変数の線形結合と関連付ける。

## 3.説明変数が一つの場合
$$P(Y = 1|X) = \Phi(β_0 + β_1X)$$

観測値$y_1, \cdots, y_n$が与えられた時の尤度関数は

$$L(β_0,β_1) = \prod^n_{i=1} \Phi(β_0 + β_1x_i)^{y_i}(1-\Phi(β_0 + β_1x_i))^{1-y_i}$$となる。ロジスティックスモデルの尤度関数も同様である。

## 4.説明変数が二つの場合
$$P(Y = 1|X_1,X_2) = \Phi(β_0 + β_1X_1 + β_2X_2)$$


## 5.コードの例
```python:
import numpy as np
import statsmodels.api as sm
import seaborn as sns
import matplotlib.pyplot as plt

# ダミーデータの生成
np.random.seed(42)
X = np.random.randn(100, 2)
# 係数
beta = np.array([0.5, -0.5])
# ノイズ項
epsilon = np.random.randn(100)
# 線形予測子
linear_predictor = X.dot(beta) + epsilon
# 応答変数の生成（0または1に変換）
y = (linear_predictor > 0).astype(int)

# プロビット回帰モデルの推定
X_with_intercept = sm.add_constant(X)  # 定数項を追加
probit_model = sm.Probit(y, X_with_intercept)
result = probit_model.fit()

# 結果の表示
print(result.summary())

# ダミーデータの可視化
plt.figure(figsize=(8, 6))
sns.scatterplot(x=X[:, 0], y=X[:, 1], hue=y, palette='viridis', marker='o', s=100, alpha=0.8)
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('Dummy Data and True Decision Boundary')
plt.legend()
plt.show()

# モデルの予測
y_prob = result.predict(X_with_intercept)

# 予測された確率とデータの散布図
plt.figure(figsize=(8, 6))
sns.scatterplot(x=X[:, 0], y=X[:, 1], hue=y_prob, palette='viridis', marker='o', s=100, alpha=0.8)
plt.xlabel('Feature 1')
plt.ylabel('Feature 2')
plt.title('Predicted Probabilities and True Decision Boundary')
plt.legend()
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359600/352eadc5-9ae4-ed19-de83-4f3a9bc3b182.png)
Pleasanter Tips: コメントにメンション（みたいな機能）を付けてみた

# はじめに
Pleasanterのサポートをしているとお客様からいろいろな希望を聞くことが有ります。その中で今回あったのが「Pleasanterにメンションが有りませんよね～」この一言で何かいい方法が無いかと考えてみました。  
今回はコメントにメンションのような機能を付けてみました。  
メンションは「送信する相手を明確にしてメッセージができる機能」という点を実装しています。
コメントはPleasanterの通知機能（メール）を使用して送信しています。  


# テーブルの準備
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63349/8c219423-5e1f-579d-08d1-af905dac4c32.png)
コメントを入力した際に、新しいコメントのみ送信するように数値Aを追加し、コメントIDを保存するようにしました。

# サーバスクリプト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63349/7992a170-aff0-fafe-82a9-af7b7ddafa10.png)
```
model.NumA = 0;
let Comments = model.Comments;
Comments = JSON.parse(Comments.toString());
if( Comments.length != 0 ){
  if( Comments[0].CommentId > model.NumA ){
    let result = String(Comments[0].Body).match(/(^\/\/.*)/gm);
    let result1 = String(String(result).substr(2)).split(/\s/gm);
    for(let c=0; c<result1.length; c++){
      let notification = notifications.New();
      notification.Address = result1[c];
      notification.Title = '【通知】' + model.Title;
      notification.Body = Comments[0].Body + '\n' + Comments[0].CreatedTime;
      notification.Send();
    }
  }
  model.NumA = Comments[0].CommentId;
}
```
# メンションの付け方
メンションは行の先頭に//を付けた行になります。  
送信先の指定方法はPleasanterの通知のアドレスと同じです。
https://pleasanter.org/manual/table-management-notification
コメント部に下記の通り入力するとmail@hogehoge.comに送信されます。
```
コメントです。
//mail@hogehoge.com
```

他の方法として  
[User1]...ユーザーID1に送信します。  
[Group1]...グループID1に送信します。  
[Dept1]...組織ID1に送信します。  
グループIDの1と10に送信する場合は下記の通りです。
```
//[Group1] [Group10]
```
送信先の間にスペースを入れてください。

# 問題点
現在の方法はIDやアドレス指定なので相手が明確に判りません。また、アクセス権の無いユーザーや使用できない人にも送信できます。

# 最後に
とりあえずメンションらしき機能はできましたが、使い勝手はいまいちです。改善方法があればご指導お願いします。
今更ながらのJaSST23 kyushu参加備忘録パート１

お疲れ様です！
ALICEです！


今回はスポンサー協賛でJaSSTに登壇した時の話を備忘録として残しておきたいと思います！
ちょっとすぐにかけてなくて、少し記憶が薄れているところもありますが。

結構久しぶりに出張したので、しっかり記憶に残っているはずです！！


今回は一般応募がなく、登壇できないと思っていたので、
室長とCTOにおねだりしてDevrelの方のおかげでスポンサーとして登壇（宣伝）してきました！

そもそも時間が10分しかなかったので、色々端折りましたが、
端折りすぎましたw w w
でもこういうフランクな、変なやつの宣伝がインパクトあってよかったぽいです！！
結構、普通に、地味に、めっちゃ嬉しいw w w

もし、聞いてた方いたら励ましの言葉ください！w

パート１では登壇関連のお話と、全体的な個人的な感想をはなして
パート２でりなさんと末村さんのセッションの感想を書こうと思います！

-----

もともとは普通に登壇したかったので、30〜60分の内容のもので応募予定でした
でも上でも言った通り、今回一般応募はないとのことで:sob:

急ぎで10分で喋れる開発本部QAのアピールを精一杯書きました
こちらとしては本当に精一杯作成したスライドだったのですがw w w
他のスポンサー様のスライドが本当にレベチでして・・

わくわくどきどきしながら順番待って、焦っていたら最後でした！
最後にこんなもので良いのか！
と思いつつも

面白いの好きだし、面白いと印象に残ればいいなーと途中から思ってきて
普通に話せることができました（宣伝）

開発本部の自慢話を10分喋るみたいな形になったのですが、
それが本望なので！！
会社紹介とか忘れたわけじゃないので！（これは嘘）
自己紹介もわざと省いたくらいなので！（これは本当）


今回学生さんがメインで、採用宣伝できたので本当に良かったです！
少しでもQAに興味を持ってくれたらなーと思います


スポンサー協賛することになって
登壇は10分って知ってそこから下書き書いて、スライド作って
３部署の方にレビューしてもらってー
それを持って登壇したので、めちゃくちゃ自慢したいのですが、
スポンサーセッションはアーカイブが公開されないらしいです・・・・・

悲しいいいい


今期の登壇と同じくらいのタイミングで来年の東京のJaSSTの一般応募したのおですが、
落ちてしまいました:sob:


悲しいいいい

ちなみに私は来年のJaSSTkyushuも狙ってます！！！！！
福岡には5年ほど住んでいたので、地元に帰ったみたいでめちゃくちゃよかったです
やっぱ食べ物が美味しいい〜〜
それと普通にJaSSTの現場にも知り合いがたくさんいて
結構心強かったです！

いろんな企業のQAの方達との交流会も、
QAに興味持ってきてくれた学生さんたちとも
交流ができてとてもよかったです！
やはり、オフラインで、直接交流する機会があるのはいいですね！

オンラインだと、セッション聞いて、メモったりして終わりですが、
オフラインだと、その後みんなでわいわい交流できるので、
振り返りもできてとても嬉しかったです！


これからは積極的にJaSSTの登壇狙って、落ちたら一般参加でも、
またおねだりして協賛でもできるだけ参加したいと思ってます！


これからもよろしくお願いします！
OpsRampにおけるアラート発生したデバイスに対するAnisble Playbookを実行する方法

本記事では、OpsRampにおけるアラート発生したデバイスに対するAnisble Playbookを実行する方法について説明します。

# 概要
OpsRampでは、アラートをトリガにしたワークフローからAnsible Playbookを実行することができます。アラートが発生したリソース情報をAnsibleに渡すことで、対象のリソースに対してAnsible Playbookを実行することができます。
例えば、CPU使用率に関するアラートが発生した場合に、Ansible Playbookを用いてtopコマンド等でどのプロセスがCPUを使用しているか取得することが可能です。

# 設定方法

::: note 
Ansibleの設定方法は、[こちら](https://qiita.com/vistanet-kh/items/511879fa030ae88c245b#ansible-integration)をご参照ください。
:::

「Automatin」->「Process Automation」からワークフローを作成します。

![worflow.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/4f422017-eca7-f586-237f-e2c8e6d578de.png)

「Signal Start Event」、「Script Task」、「End Event」で構成します。

- Signal Start Event
特定メトリクスのアラートの場合にワークフローをトリガするStartイベントを設定します。
![workflow-start.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/65c4ab98-165d-ffc2-55ac-16f301c2171b.png)

「Configuration」に、「Alert」・「Created」を選択します。
「Filter Criteria」に、アラートの一致条件を設定します。「\$metric」を指定することで特定のモニタメトリクスを指定することができます。
例: \$metric \= \"cpu\"

- Script Task
AnsibleホストおよびPlaybookを設定します。
![workflow-script.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/ee410687-8b67-03af-827e-a66b62e0293a.png)

「Configuration」に、「Agentless」を指定します。
「Integration」に、インテグレーションで設定したAnsibleホストを指定します。
「Playbook」に、インテグレーションで登録したPlabookを指定します。
「Inputs」に、Ansible Playbook実行時のオプションを指定することが可能です。「-e」でAnsible Playbookに変数を渡すことができます。「\$\<start event id\>\.alert\.resource\.ipAddress」でアラートに紐づくリソースのIPアドレスを指定することができます。

::: note info
IPアドレスのほかにも色々な変数を使用することができます。下記をご参照ください。
[Alert variables](https://docs.opsramp.com/solutions/remediation-automation/process-automation/process-definitions/variables/#alert-variables)
:::


---------------------------------------
[<img width = 250 height = 200 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/111de30a-4d33-aa33-5c7d-83d9015093e6.png">](https://www.vistanet.jp/knowledge-base/)
GitHubでのコードレビューのミスとその回避方法

GitHubのコードレビューに関するトラブルと対策

近年、ソフトウェア開発の現場では、Gitを利用したバージョン管理と共同開発が一般的になってきました。その中でも、GitHubは多くの開発者に利用されており、便利な機能やツールを提供しています。しかし、時にはコードレビューのプロセスで問題が発生することもあります。今回は、そんなトラブル事例と対策について考えてみたいと思います。

## 問題の発生

あるプロジェクトにおいて、Aさんが新たな機能の追加を行いました。その後、レビュワーのBさんとXさんから「Approveしました！」との返信があり、Aさんは安心してマージボタンを押しました。しかし、そのタイミングでDさんが外出しており、戻ってきた時にはもう遅かったのです。

Dさんは意図していない箇所に修正が加わったことに気づき、パニックに陥ります。「なんでそれマージしちゃったの！！！？」と叫びながら、修正が必要な箇所の詳細を話し始めます。しかし、既に自動デプロイが走っており、バグが生じてしまったのです。

## コードオーナーの有効活用

このような問題を回避するためには、コードオーナー機能を有効活用することが重要です。GitHubでは、[Code Owners](https://docs.github.com/ja/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners)という機能が提供されています。この機能を利用することで、特定のファイルやディレクトリに関する修正に対して、レビュアーを自動的に指定することができます。

例えば、今回のケースでは、Dさんが該当のファイルに対してコードオーナーとなるよう設定することが可能です。その場合、Aさんがマージボタンを押しても、Dさんにレビューの通知が行きます。そして、Dさんが確認して問題がなければマージを行う、といった流れを作ることができます。

## まとめ

GitHubを利用したコードレビューでは、誤ったマージやバグの発生といった問題が発生することもあります。しかし、Code Ownersといった機能を利用することで、このようなリスクを減らすことができます。開発チーム全体でこの機能を有効活用し、スムーズなコードレビューと品質保証を行うことが望ましいです。

あと、ちなみにCode Owners機能は有料プランでしか利用できないようです。なので、課金する必要があります。また、この機能は単一の問題の解決策ではないので、慎重に活用することが重要です。

以上、GitHubのコードレビューにおけるトラブル事例と、それに対する対策について紹介しました。一層の円滑な開発作業を進めるために、是非参考にしてみてください！