OmniAICreator/Qiita-1.07M huggingface dataset:
【AWS】SNSトピックのUnsubscribeを無効化してみた

# はじめに
案件で、エラーログの通知などをSNS(Simple Notification Service)を使って行っています。
通知を行うにあたって、SNSトピックのサブスクリプション作成時にはプロトコルにEメールを指定し、エンドポイントにメンバーのメールアドレスをまとめたメーリングリストを指定しています。

# 何があったか
1月半ばを最後に、**エラーログの通知がぱたりと止みました**…。
しかも気づいたのは3月初め。今のところ監視体制を作っただけでこれといった運用や保守はまだ行っていないので特に大ごとになることはなかったですが、それはそれとしてエラー通知が届かないことは問題すぎるので調査することに…。

# 原因

**サブスクリプション解除リンクの誤クリック**であることが判明しました。
画像の「If you wishto stop…」の下にある青文字のリンクが、サブスクリプション解除リンクです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1751890/245e2afe-82f7-4c91-bdd9-3b4cc9d74b13.png)

調べるまで知らなかったのですが、SNSから通知されるEメール形式のメッセージには、必ずこの解除リンクがあるようです。
しかもこの解除リンク、クリックした後に「本当に解除しますか？」みたいな確認の文面などを出すことなく、いきなり「**Subsciption removed！**」という元気なメッセージとともにサブスクリプションを解除してきやがります。なんでだよ。

厄介なのは、サブスクリプションの作成者であろうとなかろうと、リンクをクリックすると一瞬で解除されてしまうことです。今回のようにメーリングリスト宛てに通知を行っている場合などは、誰かが誤ってリンクをクリックしてしまうだけでもサブスクリプションの解除が行われてしまいます。

ということで、非常に困るので対策することにしました。というかAWSは何故こんなものを必ず添付するようにしているんでしょうか？なんで？(半ギレ)

# やったこと

とりあえずサブスクリプションを作り直しました。
ご存じの方も多いとは思いますが、サブスクリプションを作成後、以下のような確認メールが飛んできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1751890/eada8099-05ea-43eb-b7ea-effc814a9c35.png)

このメール内の「**Confirm subscription**」のリンクを**クリックせずに(重要)**、クリップボードへコピーします。

その後、マネジメントコンソールから、再作成したSNSトピックのサブスクリプションを選択し、「サブスクリプションの確認」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1751890/99ce9001-d760-40a5-80f7-63b982469476.png)

すると、サブスクリプション確認用のURL入力画面が出てくるので、先ほどコピーしたリンクを貼ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1751890/2c5a4aa8-af7f-4e6f-984d-0c66710c9c5d.png)

これにより、サブスクリプション解除のリンクをクリックしても、解除ができないようになりました。

ためしにリンクを踏んでみたところ、「Subscription not removed」というメッセージが表示されるようになりました。なんでちょっとテンション低めなんだよ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1751890/f7fe5ad0-eb31-4b87-8616-5089b3630fae.png)

# なんでこうなるのか？
マネジメントコンソールから確認を行うことで、サブスクリプションの`ConfirmationWasAuthenticated`属性が trueになるからです。

調べたところ、この`ConfirmationWasAuthenticated`属性は、デフォルト、かつメールから直接確認を行った場合では false になっているようです。なのでAWSの認証を通ることなく、誰でもメール内のリンクをクリックするだけでサブスクリプションの解除ができてしまうというわけです。

反対に、trueの場合はAWS認証を通る必要があるため、リンクのクリックだけではサブスクリプションの解除はできません。解除したい場合は、別途マネジメントコンソールやAWS CLIなどで解除の操作を行う必要があります。

また、既存のサブスクリプションの`ConfirmationWasAuthenticated`属性の変更もできないみたいです。なんでなんですかね。

# おわりに
うっかりサブスクリプション解除はどうもAmazon SNSにおけるあるある問題みたいなので、今後SNSによる通知の仕組みを作る際はこの設定を必須にするよう頭の片隅に置いておこうかなーと思いました。
NVIDIAの新代AIテクノロジー「Blackwell Ultra」と「Isaac GR00T N1」の情報完全解析 〜世界のAIはどこまで進化したのか？〜

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3917980/d5c6c78c-2488-45d1-8961-e482041a5580.png)

最新のGTC 2025でNVIDIAが発表した2つの先進的なAI技術「Blackwell Ultra」と「Isaac GR00T N1」は、データセンターの性能を戻さずろく拡張し、動体をもつAIロボットの可能性を拡張する急進的な歩みとなりました。

---

### 🌟 Blackwell Ultra ：AI機械の新しい心臓

Blackwell Ultraは、前代のHopper GPUの後継として設計された「AI特化型GPU」です。これは、特に広大な文脈をもつモデルや、マルチステップ思考を実行する「AIエージェント」に向けた性能向上を目指しています。

- 最大288GBのHBM3eメモリー
- FP4計算でのインファレンス性能を1.5倍向上
- Grace CPUと組み合わせることで皆768GBまでの統合メモリースペース
- 新バージョンGB300 NVL72：72個のBlackwell GPUを統合したAIスーパーコンピューティングラック

これらはAIの「理解力」に重点を置いた性能向上を意図しており、より長文脈での対応、チャットの解析、目標達成の計画を実現するためのデータセンターやクラウドAIに最適です。

---

### 🧥 Isaac GR00T N1 ：人形ロボットの基盤AI

GR00T N1は、大型言語モデルと観視モデルを合体した「動き」のあるAIモデルです。

- 2億パラメータを持つ基盤モデル
- 一般的な操作や指示を解釈し、物体を操作
- データはインターネットビデオ + シミュレーション + 実機データ
- System 1で動作生成，System 2で言語と観視の理解

このモデルを使うことで、ロボットは、日常作業や工場内の作業、人関係が必要なサービスロボットとして動き始めます。

---

### 価格や供給情報

- **Blackwell Ultra**: 2025年7月以降に大手クラウド供給会社から利用可能に。価頼される計算性能と広大なメモリーが特徴。
- **Isaac GR00T N1**: 無償で公開済。ロボット開発者や研究者は自由に使用可能。

---

### 他の注目すべきロボットAIモデル

- **DeepMind RT-2**: 番人としての呼び声操作が可能
- **OpenAI Musenet**: ロボットの音楽生成への実験
- **Boston Dynamics Atlas用モデル**: 高雄演性の歩行モデル

---

これらはすべて、AIが「口だけでなく動ける」時代の本格的な到来を示しています。NVIDIAのBlackwellとGR00Tは、新たな挑戦の解決答であり、AIが人間の仕事を支援する新時代の突入点になります。
RSSのXMLをYAMLに変換する

## RSSとは？
ウェブサイトの更新情報（新しい記事、ニュース、ブログ投稿など）を配信するための技術で、ウェブサイト側が更新情報を「RSSフィード」という形式で配信します。

## RSSのXMLをYAMLに変換する理由
XMLはタグが多くて冗長になりやすいですが、YAMLはインデントを使ってネスト構造を簡単に表現できるため、データを直感的に理解しやすくなります。
YAML形式はプログラムから扱いやすく、簡単にデータをパース（読み取る）したり操作したりすることができます。

## XMLからYAMLへの変換の仕組み
XMLのデータ構造をYAML形式に変換する流れは次のようになります。

1. XMLの構造を理解する
XMLでは、親子関係やタグを使ってデータを表現します。例えば、RSSフィードでは`<rss>`, `<channel>`, `<item>`などのタグがあり、それぞれに属性や値が設定されています。

2. YAMLの基本構造にマッピングする
XMLタグはYAMLのキーに対応し、タグの属性や子要素はYAMLの値に対応します。YAMLでは、インデントでネスト構造を表現するため、XMLの階層構造がそのまま反映されます。

タグ名
`（例:<title>) → YAMLのキー（例: title）`

タグの値
`（例:<title>媒体名</title>）→ YAMLの値（例: title: "媒体名"）`

タグの属性
`（例:<enclosure url="..."/>）→ YAMLのキー・値ペア（例: enclosure: {url: "..."}）`

## XMLの変換例とパラメータの意味
例として以下のようなXMLで解説

```
<rss version="2.0">
  <channel>
    <title>媒体名</title>
    <link>https://example.com</link>
    <description>ライフハックをお届けするサイトです</description>
    <item>
      <title>記事タイトル1</title>
      <link>https://example.com/first-item</link>
      <description>100均おすすめアイテム10選</description>
      <enclosure url="https://example.com/images/first-item-image.jpg" type="image/jpeg" />
    </item>
  </channel>
</rss>
```
* * *
上記XMLをYAMLに変換すると次のようになります


```
RSSフィードのYAML形式（変換後）

rss:
  version: "2.0"
  channel:
    title: "媒体名"
    link: "https://example.com"
    description: "ライフハックをお届けするサイトです"
    items:
      - title: "記事タイトル1"
        link: "https://example.com/first-item"
        description: "100均おすすめアイテム10選"
        enclosure:
          url: "https://example.com/images/first-item-image.jpg"
          type: "image/jpeg"

```
`rss`: RSSフィード全体を表す最上位のキー

`version: "2.0"`: このフィードがRSS 2.0仕様に準拠していることを示す

`channel`: フィード全体に関する情報を含む部分

`title`: フィードのタイトル

`link`: フィードに関連するウェブサイトのリンク

`description`: フィードの説明

`items`: フィードの個別アイテム（投稿や記事）をリスト形式で記述

アイテム内の情報

`title`: アイテムのタイトル

`link`: アイテムの詳細リンク

`description`: アイテムの説明

`enclosure`: アイテムに関連するメディアファイル（ここでは画像）

`url`: 画像のURL

`type`: 画像がJPEG形式であることを示す

#### 変換のポイント
- 階層構造の保持: XMLのネストされたタグ（例えば、`<channel>`, `<item>` など）は、YAMLではインデントで表現され、インデントによって親子関係を示します。

- 属性の処理: XMLのタグ属性（例えば url や type）は、YAMLではキーと値のペア（ハッシュ形式）として記述されます。

- タグの値の変換: XMLのタグの値（例えば`<title>`内の文字列）は、そのままYAMLのキーの値として使用されます。
ALBターゲットグループのヘルスチェクのためのnginx設定

ALBに登録したターゲットグループのターゲット（EC2）に対するヘルスチェックを行う際に、ターゲット側のnginxの設定で少し詰まったので記録。

# 前提
* **ターゲットグループ**
    * ALBから`HTTP:80`でリクエストを受け付けている
* **EC2**
    * アプリケーションサーバーをポート8080で起動している
    * ヘルスチェックのパスは`/api/ping`
    * サーバー内からは`http://localhost:8080/api/ping`でアクセス可能
    * 今回はサーバー内でアプリが正常に起動した状態をもってhealthyとしています

# ターゲットグループのヘルスチェック設定
* プロトコル : `HTTP`
* パス : `/ping`

![スクリーンショット 2025-03-19 17.44.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1640807/3552382a-9389-4729-a424-f9230d6fc56c.png)

### デフォルト設定について
* `HealthCheckProtocol` : ヘルスチェックのプロトコル。ALBの場合はHTTPまたはHTTPS (デフォルトはHTTP)
* `HealthCheckPort` : ヘルスチェックのポート。（デフォルトはターゲットグループで設定しているポート）
* `HealthCheckPath` : ヘルスチェックのパス。（デフォルトは`/`）

ref : https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/target-group-health-checks.html

# EC2のnginx設定
`nginx.conf`
```conf
server {
    listen       80 default_server;

    # Health Check By ALB
    location = /ping {
        access_log  off;
        proxy_pass http://localhost:8080/api/ping;
    }
}    
```

1. ターゲットグループの設定により、ターゲットに対して`http://{private-ip}/ping`へGETリクエストが送信されます（`private-ip`はターゲットの内部IP）
1. NginxはHostヘッダ`private-ip`を`default_server`に向けます（他に`server_name {private-ip}`の設定を行っていない場合）
1. `http://localhost:8080/api/ping`へリダイレクトされます

これにより設定が完了し、ターゲットEC2のアプリケーションのping結果を元にヘルスチェックができるようになりました。
【PHP】mb_convert_encodingでCSVの文字コードを変換する

**背景**
CSVファイルは保存される時に、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842729/0f6db0b9-3739-4366-90cf-c88644953e46.png)
で保存できるが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842729/2cbd43d2-d353-4126-8158-c8fd4c008441.png)
で保存して、さらにその中身（日本語SJIS）を扱う場合、
``外部エンコーディング``*は``内部エンコーディング``*に合わせる必要があるので文字コードを変換するこ。
```PHP
//PHPの内部エンコーディングを確認
echo mb_internal_encoding(); //出力：UTF-8

//.....
//$data[0]：CSVファイルの一列目のこと
 $storeName = mb_convert_encoding(trim($data[0]), "UTF-8", "SJIS");
        
```
*内部エンコーディング：PHPがプログラム内部で使う文字コード
*外部エンコーディング：``外部のデータ``*の文字コード
*外部のデータ：
①ファイルの読み込み・書き込み
CSV、テキストファイルなど

②入出力
ユーザーの入力（フォームなど）、ブラウザへの出力

③データベース
MySQLなどのデータの保存・取得時

④外部APIとの通信
JSONレスポンスやリクエストデータ
[Django] サンプルにちょっとだけ手を加える

前回のサンプルに対して、ちょっと変更をしてみる。

前回は、1レコードに、名前と投稿の2データがある。

#### 一覧画面
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/c06bb1a5-a767-4140-9cd1-7ccadb44ff8f.png)

#### 編集画面
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/e2000197-1ef9-4a82-80ee-8d30245aa879.png)

これに、メールアドレスを追加して、1レコードに3つのデータにしてみようと思う。

# フォルダコピー
前回記事で行った、

sample_appフォルダをコピーして、
sample_app2 フォルダを作る。

エラーは、前回記事で書いたように直して、
エラーなく、立ち上がるようになった。

![10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/843602d0-9f21-4ff6-b83d-f6b44f6ffc05.png)

ここからは、sample_app2 について、修正を行っていく。

# コードの修正
models.py と views.pyを修正する。

#### models.py
まずModelを変更。

```python:models.py (変更前)
from django.db import models

# Create your models here.
class Post(models.Model):
    name = models.CharField('名前', max_length=15)
    micropost = models.CharField('投稿', max_length=140, blank=True)

    def __str__(self):
        return self.name
```

以下の行を追加します。

```python
    address = models.CharField('アドレス', max_length=140, blank=True)
```

変更後のコード

```python:models.py (変更後)
from django.db import models

# Create your models here.
class Post(models.Model):
    name = models.CharField('名前', max_length=15)
    micropost = models.CharField('投稿', max_length=140, blank=True)
    address = models.CharField('アドレス', max_length=140, blank=True)

    def __str__(self):
        return self.name
```

#### views.py

views.py の一番下で定義されている、

```python:views.py (変更前)
(これより上のコードは省略)

class PostForm(ModelForm):
    """
    フォーム定義
    """
    class Meta:
        model = Post
        # fields は models.py で定義している変数名
        fields = ('name', 'micropost')
```

この fields を変更して、
```python
    fields = ('name', 'micropost')
```
下記のようにする。
```python
    fields = ('name', 'micropost', 'address')
```

```python:views.py (変更後)
(これより上のコードは省略)

class PostForm(ModelForm):
    """
    フォーム定義
    """
    class Meta:
        model = Post
        # fields は models.py で定義している変数名
        fields = ('name', 'micropost', 'address')
```

# model を修正したのでコマンド実行する。

models.py を修正したので、コマンドを実行して、DBに変更を反映させる必要があるようです。

https://qiita.com/div_naoki/items/88df111c520f6c679e82

> Djangoを学習している駆け出しエンジニアの方でDB周りに躓く場合、
> まずは
> 
> models.pyを修正
> python manage.py makemigrations
> python manage.py migrate
> 上記順番で実施すればいいんだなぁってことを頭に入れておくのが良いと思います。

ということで、以下のコマンドを実行しました。

```
python manage.py makemigrations
python manage.py migrate
```

# 結果

アドレスという項目を増やす事ができました！

#### 一覧画面 (変更後)

![11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/143ffd96-ea75-4109-b000-8ba567ce3b8a.png)

#### 編集画面（変更後）

![12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/73d994ba-2d97-41f2-81a3-6cea02399732.png)
EmEditorでツールバーのダークモードを解除する

# ツールバーがダークモードに？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117698/db13c465-2ddc-47f3-ad50-38db50207161.png)

何か変なとこ触ったのかと思ったけど、同じ現象で悩んでいる人が他にもいたので調べてみた。

# EmEditorのサイトに「規定でオン」にしたと記述が
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117698/3d3cff28-689d-48d0-81f9-3f8576999832.png)

なるほどこれか。しかし```[非常に暗い]オプション```とはどこにあるのだろうか？

# 探すのに10分ほどかかってしまった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117698/063d88ee-6565-4bab-b865-0fc3ecc6dd75.png)

[ツール]メニューから[カスタマイズ]を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117698/922e3194-5107-463c-89ee-d1e0ebfa93c5.png)

このチェックボックスを外して再起動。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117698/e4dcd516-fb64-4457-9966-860139657c62.png)

解除できた。良かった。

実はこのダークモード、気になっていたけど戻し方が分からなくて放置していた。

今回、社内で同じ悩みを抱えている人がいる事を知り、**気になっているけど戻せなくて放置してる人って意外と多いのではないか**となった。

これどっかにログ残したほうがいいな、という事で、**まあエンジニアはだいたいEmEditorだろ**という独断と偏見によりQiitaに残すこととした。
[Git] git stash について：一時的に退避できる



## In a nutshell
`git stash` は、作業中の変更を一時的に退避し、作業ディレクトリをクリーンに保つ Git のコマンドである．コミットせずに中断できるため、他の作業やブランチへの切り替えがスムーズに行える．短期間で戻る予定のある作業には特に有効．


## はじめに
git stash を使えば，作業中の変更を一時的に保存し，安全に他の作業へ移ることができる．本記事では，初学者向けに git stash の基本的な使い方と注意点，実務での利用例を紹介する．


## 予想される読み手
 - Git について，初学者である
 - `git stash` についてあまり分かっていない
 - Git を今後も利用する必要がある


## git stash とは
作業中の変更を一時的に退避（保存）して，作業ツリーをクリーンな状態に戻すためのコマンド．例えば， branch を切り替える必要があるが，現在の作業を commit したくないときに用いる．よって，作業中のコードを commit せずに一時的に退避させたいときに便利．例えば，別のタスクが割りこんだり，バグ修正のために他の branch へ移動しなければならない場合，今の作業を中断して退避できる．


## 実務でのシチュエーション
- レビュー対応のために別の branch にすぐ切り替えたい
- ビルドやテストに失敗して，一旦原因を切り分けたい
- 作業 branch で中断したコードを一時的に退避し，他のタスクに集中したい
- 複数の作業を並行して行う必要があるとき


### 使いどころの判断
`stash` は，短期間だけ作業を中断し，すぐに戻る予定がある場合に適している．逆に，作業が長引きそうであれば，ブランチを分けた方が安全・明確である．


## 基本的な使い方
#### 作業内容を退避する
```bash
git stash
```
作業中の変更（ステージ済みと未ステージの両方）が退避され，作業ディレクトリが初期状態に戻る．


#### stash の一覧を表示
```bash
git stash list
```

#### 退避した作業を戻す（最新のもの）
```bash
git stash apply
```

#### 退避した作業を戻して削除
```bash
git stash pop
```

#### 特定の stash を戻す
```bash
git stash apply stash@{1}
```
`stash@{0}` は一番新しい `stash` を指す．`git stash list` で一覧を確認すると対応関係がわかる．

#### stash を削除する
```bash
git stash drop stash@{0}
```

#### すべての stash を削除
```bash
git stash clear
```

#### 管理外のファイルも退避する
```bash
git stash -u
```

#### stash の中身を確認する
```bash
git stash show
git stash show -p
```
- `git stash show`：変更ファイル一覧  
- `-p` をつけると差分（patch）を表示


## 利点と欠点
### 利点
- すぐに作業を切り替えられる
- 作業の途中で commit 履歴を汚さずに済む
- 安全に作業を一時退避できる


### 欠点
- stash したまま忘れてしまうことがある
- 複数の stash があると管理が煩雑になる
- 一部の変更だけを選んで stash するのがやや面倒


## 代替案
- **WIP（Work In Progress） commit を作成する**
  - 一時的にローカルで commit して，後で修正・削除する
- ** branch を切って作業を避難させる**
  - 一時的な branch を作成して退避することで，より明確に状態を保存できる
- **git worktree を使って別の作業ツリーを作る**
  - stash に頼らず複数の作業状態を同時に扱うことができる


## 備考
### `stash` の内容は Git 内部に保存されるが，永続的ではない
- `stash` は永続的な保存手段ではなく，意図せず削除されることもあるため，重要な作業はコミット or ブランチ分岐で保存すべき．

### `stash` はステージ済みの内容も含めて退避する
- `git add` した内容も `stash` に含まれるため，退避後は作業ツリーが完全にクリーンな状態になる．

### `stash` 適用時の競合に注意
- `git stash apply` や `pop` の際，作業ツリーと衝突があると競合（コンフリクト）が発生する．
- この場合，通常のマージ同様に手動で解決が必要．

### `stash` に名前（メッセージ）を付けることはできない
- `git stash` 自体には名前を直接つけるオプションはなく，自動でコメントが付与される．
- バージョンによっては `git stash save "メッセージ"` が使えるが，現在のバージョンでは非推奨．`git stash push` を使う事が推奨される．

### GUI クライアントでは `stash` の操作がより視覚的にできる
- Sourcetree や GitKraken など一部 GUI ツールでは，`stash` の一覧・適用・削除を視覚的に管理可能．
- CLI が苦手な人にも使いやすい．


### 他人と共有する用途には向かない
- `stash` はローカルな操作であり，リモートへは push できない．
- 他人と作業状態を共有するには，コミットやブランチのほうが安全．


## Summary
- `git stash` は作業中の変更を一時保存するコマンド  
- ステージ済み・未ステージの変更をまとめて退避可能  
- `apply` と `pop` の使い分けに注意（`pop` は削除も行う）  
- 忘れやすく、管理が煩雑になる点に注意が必要  
- 永続保存や共有にはブランチ・WIPコミットが有効  
- GUIツールでも stash 操作は可能で初心者にも扱いやすい


## References

 - [Git公式ドキュメント git-stash](https://git-scm.com/docs/git-stash)
 - [Atlassian Git Tutorials  変更の保存（git add）> git stash](https://www.atlassian.com/ja/git/tutorials/saving-changes/git-stash)
有益な1on1の進め方：上司・部下それぞれの視点で話すべき内容とは？

# はじめに

1on1ミーティングは、日々の業務だけでは話せないことを共有し、信頼関係を深める大切な時間です。  
しかし「何を話せばいいのかわからない」「ただの雑談になってしまう」という声もよく聞きます。

この記事では **上司と部下、それぞれの立場で有益な1on1を実現するためのポイント** を紹介します。

---

## 目次

1. [1on1の目的とは？](#1on1の目的とは)
2. [【上司視点】部下との1on1で話すべきこと](#上司視点部下との1on1で話すべきこと)
3. [【部下視点】上司との1on1で話すべきこと](#部下視点上司との1on1で話すべきこと)
4. [よくある失敗とその対策](#よくある失敗とその対策)
5. [まとめ](#まとめ)
6. [📌おすすめテンプレート](#おすすめテンプレート)

---

## 1on1の目的とは？

1on1は単なる進捗確認の場ではありません。  
主な目的は以下の3つです。

- **信頼関係の構築**  
- **成長のサポート**  
- **課題や不安の早期発見**

特に部下の心理的安全性を高めることが、1on1の成功には不可欠です。

---

## 【上司視点】部下との1on1で話すべきこと

上司は「聞く」ことを意識しましょう。評価やアドバイスよりも、まずは相手の話を引き出すことが大切です。

### 💼 仕事に関するトピック例

- ✅ 最近取り組んだ業務での成功・失敗
- ✅ 業務の中でやりがいを感じたこと、つらかったこと
- ✅ 業務の進め方で困っている点・改善したいこと
- ✅ 新しく挑戦したいタスクやプロジェクト
- ✅ チームや他部署とのコミュニケーションの様子
- ✅ キャリアの方向性やスキルアップの希望

### 🏠 プライベートに関するトピック例（適度に）

- ✅ 体調や生活リズムは問題ないか
- ✅ 最近ハマっていること（趣味など）
- ✅ 家庭の変化（引っ越し、結婚などで影響がある場合）
- ✅ ワークライフバランスに関する考え

### 🎯 コツ

- 質問はオープンクエスチョンで：「どう感じてる？」「何が一番大変だった？」
- フィードバックは「事実＋感情＋提案」の3点セットで
- ネガティブな話も否定せず受け止める姿勢を

---

## 【部下視点】上司との1on1で話すべきこと

1on1は「自分のための時間」と考えましょう。  
普段言えないことを伝えるチャンスです。

### 💼 仕事に関するトピック例

- ✅ 最近の成果やうまくいったこと
- ✅ 現在困っている業務やスキル的な課題
- ✅ 自分の強みや得意を活かせているか不安
- ✅ 今後やってみたいこと・関わりたい分野
- ✅ チームの雰囲気や人間関係について
- ✅ 将来的なキャリア像の相談

### 🏠 プライベートに関するトピック例（共有したい場合）

- ✅ 最近の生活リズムや疲労感
- ✅ 気分転換になっている趣味や活動
- ✅ 家庭・健康面での変化や配慮してほしいこと

### 📝 コツ

- 事前に話したいことをメモしておくとスムーズ
- 困っていることは具体的に：「どこで詰まっているか」「何が足りないか」
- アドバイスを受けたら、次の1on1で報告することで信頼関係が深まる

---

## よくある失敗とその対策

| 失敗例 | 対策 |
|--------|------|
| 雑談で終わってしまう | 事前にアジェンダを共有する |
| 評価されるのが怖くて話せない | 評価ではなく「対話の場」と明確にする |
| 毎回同じ話題になる | 定期的にトピックのバリエーションを用意する |
| 時間が取れず流れることが多い | カレンダーで固定・優先度を高く設定する |

---

## まとめ

有益な1on1を実現するには、上司・部下それぞれが意図を持って臨むことが重要です。  
「ただ会話する時間」ではなく、「信頼と成長を促す時間」にしていきましょう。

---

## 📌おすすめテンプレート

以下のようなテンプレートを使うと、1on1の質がぐっと上がります。  
Google DocsやNotionで共有するのもおすすめです。

```markdown
### 今回の1on1アジェンダ

1. 最近取り組んだこと（成功・課題）
2. 現在困っていること・相談したいこと
3. 今後チャレンジしたいこと
4. チームや職場についての意見・感想
5. その他プライベートも含めて話したいこと
Power Appsで作成した画面を印刷したい

本記事ではPower Appsで作成した画面を印刷する具体的な方法をわかりやすく解説します。

質問：Power Appsで作成した画面を印刷するにはどうすれば良いですか？
回答：Print関数を使用することで画面に表示されたフォームを簡単に印刷することができます。
印刷ボタンを押すことでブラウザの印刷プレビュー画面が立ち上がります。 
 ![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/f50ec462-16f0-4d42-b880-6defc67af72c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/f6d29e8b-84ff-4c10-bbc8-efd85e483107.png)


# 作成手順
ここでは、印刷機能の作成手順を紹介します。
データ編集画面に印刷ボタンを実装した例を用いて解説しています。
[事前準備]
事前に以下のオブジェクトを配置したPower Appsアプリを用意しています。
・SharePointリストをデータソースにした編集フォーム

[作成手順]
１．	Power Appsの「ホーム」から印刷機能を実装したいアプリケーションの「編集」ボタンをクリックします。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/629d33da-ae29-4c25-bc19-d6c4beb822b2.png)
 
２．	印刷ボタンを追加したい画面を選択し、左側タブの挿入（「＋」）から「ボタン」を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/85a5ddbe-58db-4438-be0d-bdb612271d26.png) 
 
３．	ボタンの「OnSelect」プロパティに以下のコードを設定します。
`Code：Print()`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/e26e9235-7efa-4f69-b72c-644d4dd7821c.png)

４．	プレビューで確認をします。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/572b202c-a040-4cf7-aab8-8723569a4503.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/e6c514c7-601a-4ef4-ad4e-c952cba3cab1.png)
  
ボタンを押すと、ブラウザの印刷プレビュー画面が起動します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/b500d08b-1b59-4c78-a1c0-0c833a5c6cee.png)


５．	印刷画面に印刷ボタンを表示しないようにする場合は印刷ボタンの「Visible」プロパティに以下のコードを設定します。
`Code：Not(条件式：印刷中)`
`使用例：Not(Parent.Printing)`
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/04f4fa2a-3b1f-48ed-90dd-2dc76642f5ce.png)

 
印刷プレビュー画面でボタンが表示されていないことが確認できます。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/dd7c850b-8607-475f-bf9d-18497920f252.png)


 
# Print関数とは
Print関数を使うと、任意の画面を印刷したり、PDFとして保存したりすることが可能です。
画面テンプレートを利用して印刷ボタンを設定した画面を簡単に作成することもできます。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993014/a124f70e-f67f-40db-917d-99f008a27918.png)

# まとめ
今回はPower Appsで作成した画面を印刷する具体的な方法をわかりやすく解説しました。

入力された情報を印刷する必要があるアプリや、PDFなどで出力したいときに活用できると思います。ぜひアプリを作成する際に活用していただければ幸いです。

参考URL
・Print 関数 – Power Platform | Microsoft Learn
https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-print

# 最後に
テンダでは、「こんなプロジェクトに挑戦したい」「こんなチームで働きたい」「理想のチームを創りたい」と願う仲間を求めています。
カジュアル面談も随時受付中です。ぜひ一度お話ししましょう:angel:

* [募集職種一覧](https://hrmos.co/pages/tenda/jobs)
* [カジュアル面談の申込](https://hrmos.co/pages/tenda/jobs/031002/apply)
* [テンダで働く人や社風について](https://note.com/tenda_recruit)
HP作成備忘録：.DS_Storeとは？Macユーザーなら知っておきたい隠しファイルの正体についてまとめてみた

## はじめに

MacでWeb制作や開発作業をしていると、ある日突然「.DS_Store」という見慣れないファイルに出会うことがあります。特にGitで共有した際などに「これ、何？」「消していいの？」と疑問に思った方も多いはずです。

:::note info
**個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです。**
:::

この記事では、.DS_Storeファイルが何なのか、どのように扱うべきかを解説します。

## 書こうと思ったきっかけ

Web制作のプロジェクトをGitで共有した際に、.DS_Storeファイルが勝手にコミットされてしまい、他の環境で不要な差分として扱われたことがありました。

Mac特有のこのファイルについて、ちゃんと理解しておこうと思い、備忘録としてこの記事をまとめることにしました。

## 内容の説明（.DS_Storeとは何か？）

### .DS_Storeとは
- `.DS_Store` は「Desktop Services Store」の略。
- MacのFinder（ファイル管理アプリ）が、**フォルダの表示設定**（アイコンの位置やウィンドウのサイズなど）を保存するために自動生成する隠しファイルです。
- WindowsやLinuxではこのファイルは必要ないため、他OSでは無用の長物になってしまいます。

### 消していいの？
- Mac上で使っている限りは問題ないが、**他人に共有する際は削除**したほうが無難です。
- 特にGitリポジトリに含めてしまうと、他の開発者にとっては邪魔な存在になります。

### 無視するにはどうすればいい？
プロジェクトのルートに `.gitignore` ファイルを作成（または編集）し、以下を追加しましょう：

```
.DS_Store
```

こうすることで、Gitが .DS_Store ファイルを無視してくれるようになります。

### 既にコミットしてしまった場合は？
```bash
git rm --cached .DS_Store
git commit -m ".DS_Store を削除"
git push
```
これでリポジトリから削除され、以降は `.gitignore` により無視されるようになります。

## まとめ

`.DS_Store` はMac固有の隠しファイルで、Finderの表示情報を記録するためのものです。
Web制作やGitを使った開発においては、基本的に無視・除外対象として扱いましょう。

チーム開発やファイル共有時には `.gitignore` の設定を忘れずに行うことで、余計なファイルの混入を防ぐことができます。
箱庭でUnityを動かしてみる（8日目）

# 2025/03/24(8日目)実施内容
`FlowProcessor`の中身を実装（フローチャートの実装）

## GameMaster とその配下の構成
### GameMaster
- プレイヤー情報とゲーム進行を持つ
- 都度，子に情報を提供して処理させる

### InitGame
- ロボットを初期配置に配置する
- プレイヤー情報のインスタンス生成

### GamePlaying
- ゲーム進行中の制御関連を持つ

### FinishGame
- ゲーム終了後の制御関連を持つ（ShowResultと統合）

## GameMaster に並ぶ構成
本ゲームで扱うフローチャートや当たり判定等を扱う

### FlowProcessor
- フローチャートのノードデータの表現や処理を実装する

私はフローチャートなんか実装したことないので，とりあえず実装方法をググる
-> プログラミング入門のような，「チャート->プログラム」のようなものしか出てこないため結局自分で考えることに

## フローチャートの実装
（箱庭とは直接関係ない話になっていってる...）

### フローチャートのノードを知る
- 端子（Terminator）：開始，終了を表す
- 処理（Process）：処理を表す
- 判断（Decision）：条件分岐を表す
- その他（結合子，書類，データなど）

今回は端子，処理，判断のみ実装

### 実装構成
- `NodeInfo` スーパークラス
    - `<string> state` メンバ変数：内容を表す
    - `<int> id` メンバ変数：ノードの識別子を表す
    - `<int> nextNode1` メンバ変数：1つ先のノード（1個目）の識別子を表す
    - `TermNode` サブクラス
    - `ProcNode` サブクラス
        - `<int> time` メンバ変数：命令の持続時間を表す
    - `DeciNode` サブクラス
        - `<int> nextNode2` メンバ変数：1つ先のノード（2個目）の識別子を表す

- `ControllFlow` クラス
    - `<List<TermNode>> terms` メンバ変数：端子集合の格納場所
    - `<List<ProcNode>> procs` メンバ変数：処理集合の格納場所
    - `<List<DeciNode>> decis` メンバ変数：判断集合の格納場所
    - `findNode -> ProcNode` メソッド：`<int> id` が与えられると，一致する処理ノードを返す
    - `findNode -> DeciNode` メソッド：`<int> id` が与えられると，一致する判断ノードを返す
    - `InsertProcNode -> void` メソッド：現在選択中のノードと，処理ノードを作成する上で必要な値（この時，作成されるノードの次ノードを指定できるようにしてある）が与えられると，それに応じた処理ノードを，選択中ノードの直後に挿入する
    - `InsertDeciNode -> void` メソッド：現在選択中のノードと，判断ノードを作成する上で必要な値（この時，作成されるノードの次ノードを指定できるようにしてある）が与えられると，それに応じた判断ノードを，選択中ノードの直後に挿入する

あとは削除，編集の実装まで済ませてテスト！！（次回はここから）
Google Cloud MonitoringでVMインスタンスのメモリ使用率を取得したい

### 注意
(指標にe2-family限定って書いてあったので、他のVMだと使えないかもです)

## 背景と課題
Google Cloud Monitoringでは他サービスにおける状況をモニタリングすることや指定した閾値を超えた場合にアラートを出すことが出来ます。
しかし、与えられた指標だけだと満足できない場合もあります。

例えばVMインスタンスのメモリの使用率などです。

VMインスタンスに関する指標でメモリ量に関連するのはVM Memory TotalとVM Memory Usedです。
Totalが供給されてる総数で、Usedが現在使用中のメモリ量ですね。

使用率を取りたい場合、単純に考えてUsed / Totalと計算してあげれば割合が出せそうですよね。
ただ、標準のMetrics Exploreを使っていると上記のような指標の組み合わせを作ることができません。

## PromQLを使ってみよう
そんな時に便利なのがPromQLです。PromQLを使うことで、複数の指標を組み合わせたカスタム指標を作ることが出来ます。

Metrics Exploreの指標の右側にボタンがあるのでクリックすることでクエリを入力することが出来ます。

![Screenshot 2025-03-13 at 10.49.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3627854/991db1c9-a630-496d-aa61-bd4a24127eef.png)

以下のように入力すると縦軸を百分率としたメモリ使用率のモニタリングを行うことが出来ます。
```
compute_googleapis_com:instance_memory_balloon_ram_used / compute_googleapis_com:instance_memory_balloon_ram_size * 100
```

## 参考
https://cloud.google.com/monitoring/promql/promql-mapping?hl=ja

## 仲間を募集中

株式会社ホープでは、福岡で働くエンジニアを募集中です。
ぜひ、求人を見てみてください！
▼ Wantedly求人
https://www.wantedly.com/projects/1684027
▼ コーポレートサイト
https://www.zaigenkakuho.com/recruit/
「自治体を通じて人々に新たな価値を提供し、会社及び従業員の成長を追求する」
この理念の実現に向けて、今後も自治体の課題解決に取り組んでいきます。
ご応募お待ちしております！
「もぐの中の人」に聞く🤔 Moguchatが生まれた理由と未来

今回は、Moguchatの開発者である「もぐの中の人」にインタビューする機会をいただきました。Moguchatがどのように生まれ、どんな思いで作られたのか、そしてこれから目指す未来について、じっくりお話を伺いました。

## 「Moguchatを作ろうと思ったきっかけは？」
私：まず、Moguchatを作ろうと思ったきっかけを教えていただけますか？

もぐの中の人：もちろんです！実は、私自身が子どもの頃からアニメやゲームが大好きで、特にキャラクターたちとの「会話」に憧れていました。例えば、好きなキャラクターに悩みを打ち明けたり、一緒に笑ったりできたら、どんなに楽しいだろうと思っていたんです。でも、現実ではそれは難しい。そこで、「AIを使って、その夢を叶えられるアプリを作れないか？」と考えたのが始まりです。

私：なるほど！それはまさに、多くのアニメファンやゲーマーが抱いている夢ですね。

もぐの中の人：そうなんです。特に、現代はストレスや孤独を感じる人が多いと聞きます。そんな中で、アニメやゲームのキャラクターがそばにいてくれたら、少しでも心が軽くなるんじゃないかと思いました。Moguchatは、ただの娯楽ではなく、人々の心に寄り添う存在でありたいと考えています。

## 「開発で一番苦労した点は？」
私：開発の中で、一番苦労した点はどんなところでしたか？

もぐの中の人：そうですね……やはり、キャラクターの「らしさ」を再現する部分が一番難しかったです。例えば、キャラクターの性格や話し方、反応の仕方まで、細かく調整する必要がありました。ユーザーが「このキャラクターと本当に会話している！」と感じられるようにするためには、AIの学習データや会話の流れを徹底的に作り込む必要があったんです。

私：確かに、キャラクターの「らしさ」を再現するのは大変そうですね。

もぐの中の人：はい。特に、キャラクターによっては、独特の口癖や言い回しがあるので、それを自然に会話に組み込むのが難しかったです。でも、開発チーム全員がアニメやゲームを愛しているからこそ、そのこだわりを楽しみながら進めることができました（笑）。

## 「Moguchatを通じて実現したい未来は？」
私：最後に、Moguchatを通じて実現したい未来について教えてください。

もぐの中の人：Moguchatが、人々の日常にちょっとした幸せをもたらす存在になってほしいと思っています。例えば、仕事や学校で疲れたとき、Moguchatを開いて好きなキャラクターと話すことで、ほんの少しでも心が軽くなったり、笑顔になれたりする。そんな瞬間を提供できたら、これ以上の喜びはありません。

私：素敵な思いですね。

もぐの中の人：ありがとうございます。私たちは、Moguchatが単なるアプリではなく、ユーザーの皆さんにとって「特別な居場所」になることを目指しています。これからも、多くの人に愛されるアプリになるよう、努力を続けていきます！

今回のインタビューを通じて、MoguchatがただのAIチャットアプリではなく、開発者たちの情熱とユーザーへの思いやりが詰まったプロダクトであることがよくわかりました。もぐの中の人をはじめとする開発チームの皆さんが、アニメやゲームへの愛を形にし、人々の日常に笑顔と癒しを届けたいという思いが、Moguchatの根底に流れているのです。

これからもMoguchatがどのように進化していくのか、楽しみで仕方がありません。ぜひ、皆さんもMoguchatを体験して、推しキャラや理想の相手との特別なひとときを楽しんでみてください！


Moguchat – 推しとつながる、会話の魔法をいつどこでも

▼ iOS

https://apple.co/3ZRlt2a

▼ Android 

https://play.google.com/store/apps/details?id=ai.moguchat.app
[備忘録] WSL関連のTips

# まえおき

WSL関連のTipsを記載していく。

## 同一ディストリビューションの複製

1. 複製したいディストリビューション名を取得

    PowerShellにて以下のコマンドを実行する。

    ```powershell
    wsl -l -v
    ```

    以下のように出力される。

    ```powershell
      NAME                   STATE           VERSION
    * Ubuntu-22.04           Running         2
      Ubuntu-24.04           Running         2
      ...
    ```

1. ディストリビューションのエクスポート

    PowerShellにて以下のコマンドを実行する。
    
    ```powershell
    wsl --export Ubuntu-24.04 <任意の名称>.tar
    ```

1. ディストリビューションのインポート

    PowerShellにて以下のコマンドを実行する。
    
    ```powershell
    wsl --import <任意の名称(*1)> <ディストリビューションのデータを置く場所のパス> <エクスポートしたディストリビューションのパス>
    ```

    *1: `wsl -l -v`を実行したときにNAMEに表示される。

## Ubuntu起動時のログインユーザを作成したユーザにする

起動時のログインユーザがrootになってしまう場合の対処法になります。

1. wsl.conf書き換え

    Ubuntuにて以下のコマンドを実行する。
    
    ```bash
    nano /etc/wsl.conf
    ```

    以下の項目を追記する。

    ```diff
    + [user]
    + default=<ログインしたいユーザ名>
    ```
    
1. WSL再起動

    PowerShellにて以下のコマンドを実行する。
    
    ```powershell
    wsl --shutdown <ディストリビューション名>
    ```

## sudo使用時のパスワード無効化

1. sudoers書き換え

    Ubuntuにて以下のコマンドを実行する。
    
    ```bash
    sudo visudo
    ```

    以下の項目を追記する。
    `# Allow members of group sudo to execute any command`の中に書き込めばよいかと。

    ```diff
    + <ユーザ名> ALL=(ALL) NOPASSWD: ALL
    ```

1. シェル再読み込み
AtCoderでPythonコードテストを迅速に行うためのTips

## 背景

AtCoderのコードテストの使い勝手が悪いので色々と探っている最中に見つけた方法を忘れないため記事にした。知っている人は普通に知っていると思う。

## 内容

ファイル構造
- inputs : 入力例のファイルを格納するフォルダー
- test-a1, test-a2 : 各入力例
- code1.py, code2.py : 実行したい`.py`ファイル

```
.
├─ inputs/ 
│    ├─ test-a1
│    ├─ test-a2
│    └─ ...
├─ code1.py
├─ code2.py
└─ ...
```

１． `code.py` には通常通りに `input()` 関数を使って記述する。

```python
n = int(input())
ans = sum([i for i in range(n)])
print(ans)
```

２． `test-a1` にはコードの入力例などをコピペする。

```text
6
```

３． ターミナルで下記コマンドを実行。

```bash
python3 code.py < inputs/test-a1
```

- `<` は、Bashコマンドにおいてリダイレクトを行うための記号。具体的にはファイルの内容を標準入力としてコマンドに渡すため使用される。

> **Note**:
> `a1`, `a2` などの入力ファイルは `.txt` を付けたほうが視認性が上がるが、入力例を次々変えて実行したい場合、拡張子が邪魔になるので今回は外すことにした。
Adafruit MCP23017 Arduino Libraryのアプデでエラーが出た


https://burariweb.info/electronic-work/arduino-learning/arduino-io-expander.html

↑の記事を参考に↓のサンプルコードでMCP23017を制御しているときに
<details><summary>サンプルコード</summary>

```C++
// Arduino入門編㉚ I/OエキスパンダーMCP23017を使ってみる！
// https://burariweb.info
// デジタル出力のテスト

#include <Wire.h>                  // ライブラリのインクルード
#include "Adafruit_MCP23017.h"
Adafruit_MCP23017 mcp;             // MCPライブラリのオブジェクトを作成

void setup() {
  
  Wire.begin();
  mcp.begin();                     // MCP23017のI2Cアドレスを0x00に設定(0x00は省略可)

  for (int i = 8; i <= 15; i++) {  // 8~15(GPB0~GPB7)を出力に設定
    mcp.pinMode(i, OUTPUT);
  }

}

void loop() {

  for (int i = 8; i <= 15; i++) {  // 8~15(GPB0~GPB7)に接続されたLEDを点灯
    mcp.digitalWrite(i, HIGH);
    delay(30);
  }

  for (int i = 8; i <= 15; i++) {  // 8~15(GPB0~GPB7)に接続されたLEDを消灯
    mcp.digitalWrite(i, LOW);
    delay(30);
  }
}
```
</details>

```
Compilation error: Adafruit_MCP23017.h: No such file or directory
```
と出てきてしまいました。
Adafruit MCP23017 Arduino Libraryのバージョンを2.3.2から1.3.0に落とすと無事作動するようです。

調べてみるとAdafruit MCP23017 Arduino Libraryのvar1.x.xとvar2.x.xの間で宣言が
```C
#include "Adafruit_MCP23017.h"
```
から
```C
#include "Adafruit_MCP23X17.h"
```
に変わったようです。
それに伴い
| 1.x.x | 2.x.x |役割|
|:-:|:-:|:-:|
|Adafruit_MCP23017 mcp;|Adafruit_MCP23X17 mcp;|MCPライブラリのオブジェクトを作成|
|mcp.begin();|mcp.begin_I2C();|MCP23017のI2Cアドレス設定|

となったようです。
まあこの情報は調べたら結構出てくるのでちゃんと調べなかった私が悪いんですけどね。
AbstractFactoryパターンの特徴とその他パターンとの比較

# はじめに
現在デザインパターンを絶賛学習中の新人エンジニアです。  
デザインパターンは、一つずつのパターンの仕組みを理解することができたとしても、他パターンとの比較をして考えるととても難しく感じます。

そのため今回は、簡単にAbstractFactoryパターンの特徴を説明したあと、AbstractFactoryパターンとFactoryMethodパターン、Builderパターンとの違いを比較していきます。  


# Abstract Factoryパターンとは
AbstractFactoryパターンは、関連するオブジェクトのグループを、具体的なクラスを指定せずに生成するためのデザインパターンです。  
オブジェクト群を作成するためのFactoryを提供します。各オブジェクト群は、異なる種類のオブジェクトを含み、Abstract Factoryはそれらを生成するための共通インターフェースを定義します。これにより、オブジェクト群の実装を変更する際に、クライアントコードに影響を与えずに新しいオブジェクト群を導入することが可能になります。  
詳細な設計の仕方は、様々な書籍やサイトで説明されているため、ここでは省略します。

# 他パターンとの比較

## Factory Methodパターンとの違い
FactoryMethodパターンは、オブジェクトを生成する際に、それぞれに最小限の設定をFactoryで定義し、持たせたうえでオブジェクトごとにカスタマイズすることができるデザインパターンです。すなわち、このパターンは関連の特性をもつ異なるオブジェクトを生成したい場合に用いられます。  

イメージとしては、driverというメソッドが宣言されたTransportというインターフェイスが合った場合は、トラックやコンテナ船がプロダクトとして作成できるくらい幅が広い実装が出来るのがFactoryMethodパターンです。これに対してCarというインターフェイスがあった場合に、特定のテーマに応じた部品をインターフェイスにしたがって作成されていくのがAbstractFactoryパターンです。スポーツカーにはスポーツカー用の部品が,ファミリーカーにはファミリーカー用の部品が搭載されることが確約出来ます。  
このように、Factory Methodパターンは個別のオブジェクト生成に特化しており、Abstract Factory パターンは製品の統一性を保ちながら、複数の関連するオブジェクトを生成することに特化しています。
## Builderパターンとの違い
Builder パターンは、複雑なオブジェクトを段階的に構築しながら、部品の組み合わせを柔軟にカスタマイズできるデザインパターンです。

車の生成を例にすると、Builder パターンでは、エンジン・タイヤ・内装などの部品を自由に選び、順番に組み立てながらカスタマイズできます。ファミリーカー用の内装にスポーツエンジンを付けることも可能なイメージです。
これに対して、Abstract Factory パターンは、スポーツカーにはスポーツカー用の部品、ファミリーカーにはファミリーカー用の部品しか組み合わせて作成できません。言い換えると、組み合わせを間違える心配がなくなります。

このように、Builder パターンは段階的な構築と柔軟なカスタマイズに特化しており、Abstract Factory パターンはオブジェクト群の整合性を保ち、それぞれのオブジェクトは一貫したテーマで生成することに特化しています。


# おわりに
今回は、AbstractFactoryパターンを簡単に説明し、類似パターンとの違いを明確にすることで、それぞれのパターンの理解を深めることができました。
今後も引き続きデザインパターンの学習を続けていきたいと思います。
【Rails】登録・更新前に重複をチェックする

# はじめに
DBの保存前に重複をチェックする実装を行った記録です。

# 背景
### ApplicationRecordのバリデータで `uniqueness: true` を設定した場合
```rb
class Account < ApplicationRecord
  validates :email, uniqueness: true
end
```
- オブジェクトが保存される直前に属性の値が一意であり重複していないことをチェックする
- その属性と同じ値を持つ既存のレコードがモデルのテーブルにあるかどうかを調べるSQLクエリを実行することでバリデーションを行う
- つまり、同時に複数の値を保存する場合などはバリデーションが行われない

https://railsguides.jp/active_record_validations.html#uniqueness


# 実装例
- 多対多の関連付けがされているcourseテーブルとuserテーブル、その中間テーブルであるcourse_usersテーブルがあると想定する

```rb
class Course < ApplicationRecord
  has_many :course_users
  accepts_nested_attributes_for :course_users

  has_many :users, through: course_users
end
```

```rb
class CourseUser < ApplicationRecord
  belongs_to :course
  belongs_to :user
end
```

### ①　カスタムバリデータで実装する
```diff
class Course < ApplicationRecord
+  validates_with Validators::UniqueUserValidator
end
```

```diff
+ class UniqueUserValidator < ActiveModel::Validator
 
+  def validate(record)
+    user_ids = []      
+    record.course_users.each do |c|
+      if user_ids.include?(c.user_id)
+        record.errors.add(:base, '重複しています')
+        return
+      end
 
+     user_ids << c.user_id
+   end
+  end

+ end
```

### ②　コールバックでバリデーションを実行する
```diff
class Course < ApplicationRecord
+  before_validation :ensure_user_is_unique


+  def ensure_user_is_unique
+    ensure_resouce_is_unique(course_users, user_id)
+  end


+  def ensure_resource_is_unique(collection, attribute_name)
+    ret = true
+    uniq = []
+    collection.each{|m|
+      if uniq.include?(m[attribute_name])
+        errors.add(:base, '重複しています')
+        ret = false
+      else
+        uniq << m[attribute_name]
+      end
+    end
+    ret
+ end
end
```

# おわりに
Railsガイドでは下記の通りデータベースに一意性の制約の指定をするように説明しています。一意性制約を指定する際にはApplicationRecordのバリデータのみでは不完全であるということに注意したいと思います。

>このバリデーションはデータベースに一意性制約（uniqueness constraint）を作成しないので、異なる2つのデータベース接続が使われていると、一意であるべきカラムに同じ値を持つレコードが2つ作成される可能性があります。これを避けるには、データベース側でそのカラムにuniqueインデックスを作成する必要があります。

https://api.rubyonrails.org/v8.0/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#method-i-add_index
自分をAIでもう一人作る？？Second-Meを試してみる③

## 前回の記事

https://qiita.com/GOROman/items/012c8d10da916ae6cad0

## 注意事項

```
All Human

この記事は全て人間(GOROman)がAIを使わずに書いたオーガニック記事です。
そのため、誤字・脱字・文法ミスがある場合がございます。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30621/f95edb39-a2b7-423c-9fb7-c1e88ac6ff5b.png)



## 実際に起動して登録してみる

Chromeで起動、以下はChromeで日本語にしています。

### 第二の自分を作る方法

![第二の自分を作る方法.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30621/b9a3e8d1-bba9-453c-a148-629359f49aa2.png)



### アイデンティティを定義する


- アイデンティティ定義の時に記入すること
  - **セカンドミー名:** この名前はあなたとあなたの第二の私を表します
  - **簡単な自己紹介:** あなた自身の性格、動機、スタイルなどについて簡単に説明してください
  - **セカンドミーのメール:** このメールは、Second Me の連絡先として使用されます。ご自身のメール アドレスを使用することもできます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30621/eb025435-38cb-4c11-b31b-b9c0f5d48fe2.png)

### 起動画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30621/788a037f-7193-4c0e-a57f-fd05c6ef880f.png)

「思い出をアップロード」ボタンがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30621/94ea48d2-a0d7-45bf-98d8-c680d3af3a4e.png)



### 思い出をアップロード

これは Google Notebook LM のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30621/4713f6c4-79ff-4ed8-9a94-76e8b5b5495c.png)


## 次回


```#AllHuman```

https://qiita.com/GOROman/items/4ff37e3dd4c943474863
言語別のWebサービス実装方法

開発言語によって、Webサービスを実装する方法は異なる。
またフレームワークも様々あるので、ここで挙げたものは一例となる。

## Java
### JAX-RS
https://developers.wonderpla.net/entry/2015/02/06/163932

## VB、C#
### ASMX Webサービス
https://learn.microsoft.com/ja-jp/troubleshoot/developer/visualstudio/csharp/language-compilers/write-web-service

## Python
### FastAPI
https://zenn.dev/sh0nk/books/537bb028709ab9

********

どれも実際に開発経験のあるものだが、PythonのFastAPIが圧倒的に手軽で開発しやすいと感じた。

・Javaの「JAX-RS」
　→初めて開発をする人には、開発環境を整えるところがまず難しい。最初がつまづきやすいかもしれないが、分かってくれば各種フレームワークを組み合わせた開発など、効率良くアプリが実装できるようになってくる印象。

・VB、C#の「ASMX Webサービス」
　→開発環境はVisualStudio一択なので迷うことは無く最初のスタートはやりやすい。Windows系の開発経験があればすんなり開発できる。WebサーバーにIISを使用するので、おのずとサーバーOSもWindowsに限定される。
2025/3/26追記
「ASMX Webサービス」は.NET Frameworkからある仕組みで、今だとASP.NET CoreのWeb APIという仕組みもある。


・Pythonの「FastAPI」
　→VisualStudioCodeなどテキストエディタがあればOK。とりあえず作って動かしてみるまでの流れは他に比べるととても簡単。大規模な開発では使っていないのでそのあたりに何か課題出てくるかはまだ分からない。
最適なモデルがわかる！DeepSeek‐R1の選び方完全ガイド

大規模言語モデル（LLM）の進化はめざましく、その中でも注目を集めているのがDeepSeek‐R1です。オープンソースで商用利用も可能、さらに複数のモデルサイズが用意されており、個人から企業まで幅広く活用されています。

しかし、「種類が多くてどれを選べばいいのか分からない」「自分の環境で動くのか不安」と感じる人も多いのではないでしょうか。実際、DeepSeek‐R1の性能を活かすには、目的と使用環境に合ったモデル選びが不可欠です。

この記事では、DeepSeek‐R1の特徴や違いを整理しながら、あなたに最適なモデルの選び方を具体的に解説していきます。初心者でも分かりやすく、すぐに行動に移せる内容を目指しています。

ご自身のニーズに合わせて、適切なモデルをお選びください。

無料版のAIチャットを使用したい方は、下記のサイトを参考にしてください。

https://ai.tencho-ex.com/


# 1. DeepSeek‐R1とは？
DeepSeek‐R1は、中国のAI企業DeepSeekが開発した大規模言語モデル（LLM）です。GPT系と同じく、テキストの生成・要約・翻訳・推論・コード補完など多様な自然言語処理タスクに対応しています。

主な特徴：

1.オープンソースで商用利用可（一部条件あり）

2.複数のモデルサイズ（1.3B, 7B, 14B, 33Bなど）

3.学習済みモデルがHugging Faceで公開

4.コードタスクに特化したDeepSeek-Coderも提供中

他のLLMと比べても、精度と応答の一貫性に優れ、用途に応じて選べる柔軟さがあります。

# 2. なぜモデルの選定が重要なのか？
DeepSeek‐R1は高性能な反面、サイズによって必要な計算リソース（GPUメモリなど）が大きく変わります。選定を誤ると、以下のような事態になりがちです：

1.モデルが重すぎて動かない（GPU不足）

2.小さいモデルを選びすぎて精度が足りない

3.コストを無駄にしてしまう（クラウド利用時）

つまり、「目的」と「環境」に合ったモデル選びは、性能を引き出すうえで欠かせない工程です。

# 3. 利用目的別の選び方
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4028918/4de41edd-1308-4d60-b1d9-73ff63c9e941.png)
## 3-1. 文章生成に使いたい場合

目的例：

1.ブログ記事作成

2.ストーリーの執筆

3.マーケティングコピー

おすすめモデル：

7Bまたは14Bモデル

理由：文章生成は文脈理解と語彙力が重要ですが、33Bのような巨大モデルでなくても十分自然な文が出力されます。とくに14Bは長文生成に安定感があります。

## 3-2. プログラミング支援に使いたい場合

目的例：

1.コードの自動生成や補完

2.リファクタ提案

3.エラーメッセージの解析

おすすめモデル：

DeepSeek-Coder（7B, 33B）

理由：通常の言語モデルでもコードは書けますが、DeepSeek-Coderはコードに特化して訓練されており、命名や構造の一貫性が高く、より実用的です。7Bでもかなりの精度がありますが、業務レベルなら33Bも選択肢に。

## 3-3. 分析・要約に使いたい場合

目的例：

会議メモの要約

レポートの要点抽出

ニュースや論文のサマリー生成

おすすめモデル：

14B〜33Bモデル

理由：要約は文の構造把握や論理関係の理解が求められるため、ある程度大きなモデルの方が正確なアウトプットが期待できます。14Bでもかなり高品質な要約が可能です。

# 4. モデルサイズと性能のバランス
モデル特徴必要VRAM目安1.3B非常に軽量、精度は控えめ8GB〜12GB7B汎用性が高くコスパ良好16GB〜24GB14B長文・高精度処理に安定30GB〜40GB33B最高レベルの精度80GB以上（分散推論推奨）


# 5. 推論環境と対応モデルの確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4028918/7494d02b-69c3-4cbe-87aa-ffa9806cdb7b.png)
DeepSeek‐R1はGPU推論が前提です。使うモデルによって要求されるGPUスペックが大きく変わります。

## 自宅PCで使いたい人：

NVIDIA RTX 3090や4090があるなら7B〜14Bまでが現実的

VRAMが16GB未満なら1.3Bで試す

## クラウドで使う場合：

Google Colab Proなどでも7Bは動作可能

本格利用ならAWS、Paperspace、RunPodが安定

Tip：大規模モデルは**量子化（例：int4）**して軽量化する手法もあります。

# 6. オープンソースか有償版か

DeepSeek‐R1はオープンモデルなので無料で使えますが、利用には以下の選択肢があります。

1.自前のGPU環境で推論 → 無料。ただし環境構築が必要

2.クラウドGPUで推論 → 従量課金。重いモデルほどコストがかかる

3.API経由で利用（DeepSeek公式や他社） → 楽だが月額・従量課金あり

用途と技術力によって選びましょう。

# 7. 迷ったときの選定基準
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4028918/db324146-891c-4b68-9796-0637ee5966b6.png)
# 8. よくある選定ミスと注意点
1.「性能高そう」で33Bを選ぶ→GPUが足りず動かない

2.軽いモデルを選びすぎ→生成結果の質にがっかり

3.API利用コストを見落とす→請求額が想定以上に

4.量子化の仕組みを理解せず精度低下に驚く

「大は小を兼ねる」はLLMには当てはまりません。目的ベースで考えるのが基本です。

# 9. まとめ：最適なモデル選びのポイント
1.何に使うかがすべての出発点

2.手元のGPUや予算で現実的なモデルサイズを選ぶ

3.**中規模（7B〜14B）**は汎用的で最初の一歩におすすめ

4.高精度が必要なら33B＋クラウドを検討

DeepSeek‐R1は柔軟な構成で、多くの人にとって「自分用の生成AI」を構築できる選択肢です。無理なく、賢く選びましょう。

# 「今無料」おすすめの生成AIツール

https://ai.tencho-ex.com/
Unity-参照先をStartで取る？Awakeで取る？

# Unityの`Awake` と`Start`の使い分けガイド

Unityでコードを書く際に、レースコンディションやヌル参照エラーを避けるために、`Awake` と `Start` を正しく使い分けることが重要です。ここでは、そのベストプラクティスを解説します。

---

## 1. `Awake` の使い方
### ▶ `Awake` で自身のコンポーネントを取得

### 【理由】
- `Awake` は **ゲームオブジェクトが生成された直後に呼ばれる**
- この段階では **自身のコンポーネントは必ず存在している**
- しかし、他の `GameObject` の `Awake` はまだ完全に実行されていない可能性がある

### 【コード例】
```csharp
private Rigidbody rb;

void Awake() {
    rb = GetComponent<Rigidbody>(); // 自身のコンポーネントはここで取得
}
```

`Awake` で実行することで、`自分の GameObject 内` に存在するコンポーネントを確実に取得できます。

---

## 2. `Start` の使い方
### ▶ `Start` で他の `GameObject`を取得

### 【理由】
- `Start` は **すべての `Awake` 実行後に呼ばれる**
- そのため、他の `GameObject` のコンポーネントも初期化済みである可能性が高い
- `Awake` の段階で `GameObject.Find()` を使うと `null` になる可能性があるが、`Start` ならより安全

### 【コード例】
```csharp
private GameObject target;

void Start() {
    target = GameObject.Find("TargetObject"); // 他のGameObjectを安全に取得
}
```

これにより、`Awake` よりも確実に `target` を見つけることができます。

---

## 3. レースコンディション（Race Condition）とは？
プログラムの **実行順が保証されていない** ために起こるバグのことです。

### ⚠️ 悪い例：
```csharp
private GameManager gm;

void Awake() {
    gm = FindObjectOfType<GameManager>(); // GameManagerのAwakeがまだ実行されていなかったらnullになる！
}
```
この場合、`GameManager` の `Awake` がまだ実行されていないと `gm` は `null` になります。

### ✅ 安全な方法（`Start` で取得する）
```csharp
void Start() {
    gm = FindObjectOfType<GameManager>(); // `Awake` の後に実行されるので、より安全
}
```
こうすれば、`GameManager` の `Awake` が完了した後に取得できるので、より安全です。

---

## 4. `Awake` と `Start` の適切な使い分けまとめ

| メソッド | いつ呼ばれる？ | 何をやるべき？ | 例 |
|---|---|---|---|
| `Awake` | オブジェクト生成時（コンポーネントがアタッチされた時） | **自身のコンポーネントを取得** | `GetComponent<Rigidbody>()` |
| `Start` | すべての `Awake` の後 | **他のオブジェクトの参照を取得** | `FindObjectOfType<GameManager>()` |

---

### ✅ より安全な設計のために
- **自分のコンポーネントは `Awake` で取得**
- **他の `GameObject` のコンポーネントは `Start` で取得**
- **外部データのロードなど時間がかかる処理は `Start` や `Coroutine` で処理**

このルールを守ることで、`NullReferenceException` を防ぎ、バグの少ない予測しやすいコードを書くことができます！
【2025年Ver】生成AIに関する用語をふんわりまとめてみる。

:::note info
順次追加予定
:::

### 生成AI
テキスト・画像・音声などを自動で作り出すAI。

### LLM
大規模言語モデルのこと、膨大なテキストを学習して人間のような文章を生成できるAIモデル

### トークン
AIが文章を理解・生成する際の単語や記号の単位。（課金の料金計算の指標に使われる。）
例：「Chatgpt」は1～2トークンらしい。どうやら。

### コンテキストウインドウ
AIが一度に理解・記憶できるトークンの最大量。ウインドウが広い→長い会話が可能。

### プロンプト
ユーザーがAIに入力する指示文。

### ファインチューニング
既存のAIモデルを特定用途向けに再学習させてカスタマイズすること。

### 推論
AIが学習モデルを使って、実際に回答や生成を行う処理のこと。

### トランスフォーマー
LLMのベースになっているAIの設計思想。文脈理解が得意なアーキテクチャらしい。

### 注意機構
トランスフォーマーがどこに注目すべきかを判断する仕組み。重要な単語に集中できる。

### パラメーター数
モデルの中の変数の数。多いほど複雑で高性能。
例：GPT-3は1750億

### ゼロショット/ワンショット/フューショット学習
AIに例を見せず、または少しだけ見せてタスクをこなす学習形式。

### マルチモーダル
テキストだけでなく、画像・音声など複数の形式を扱えるAI。

### Diffusionモデル
主に画像生成使われるAI技術。ノイズから徐々に画像を生成する方式（例：Stable Diffusion）

### チューニング不要のAI（ゼロチューニング）
学習済みモデルをそのまま利用し、再学習せずに様々なタスクに対応できるAI。

### マルチエージェント
複数のAIが強力してタスクをこなす仕組み。自律的なエージェント同士が連携する。

### チャンク
データや情報を小さな単位、まとまりに分割したものを指す。（もともとは心理学の分野で使われていた。）

### ベクトル化
（色々な文脈があるが自然言語処理の分野において）単語の意味や関連性をベクトルで表現し、検索や感情分析などに活用する。（AIで生成する前の前段階の工程だと思えばいい。）



### 参考文献（参照日2025年4月19日）


https://metaversesouken.com/ai/generative_ai/terms/

https://promo.digital.ricoh.com/ai-for-work/column/detail012/
【ABC398】AtCoder Beginner Contest 398【C++】

### コンテスト名
ユニークビジョンプログラミングコンテスト2025 春（AtCoder Beginner Contest 398）

### コンテストURL
https://atcoder.jp/contests/abc398

### 開催日
2025/03/22 21:00-22:40

---

## [A: Doors in the Center](https://atcoder.jp/contests/abc398/tasks/abc398_a)
**解法**
- 回文の中央は `=`
- $N$ の偶奇で場合分けする
```cpp:ABC398A.cpp
#include <iostream>
using namespace std;

int main(){
    int n;
    cin >> n;

    if(n%2==0){
        for(int i=0; i<n/2-1; i++){
            cout << '-';
        }
        cout << "==";
        for(int i=0; i<n/2-1; i++){
            cout << '-';
        }
    }else{
        for(int i=0; i<n/2; i++){
            cout << '-';
        }
        cout << '=';
        for(int i=0; i<n/2; i++){
            cout << '-';
        }
    }
    cout << endl;

    return 0;
}
```

## [B: Full House 3](https://atcoder.jp/contests/abc398/tasks/abc398_b)
**解法**
- 各種類の枚数を `vector<int>` に記録する
- 3枚以上ある種類が一つ見つかれば、次は2枚以上ある種類を見つければよいことに注意する
```cpp:ABC398B.cpp
#include <iostream>
#include <vector>
using namespace std;

int main(){
    int a;
    vector<int> V(13);
    for(int i=0; i<7; i++){
        cin >> a;
        a--;
        V[a]++;
    }

    bool flag3 = false, flag2 = false;
    for(int i=0; i<13; i++){
        if(!flag3 && V[i]>=3){
            flag3 = true;
        }else if(V[i]>=2){
            flag2 = true;
        }
    }

    if(flag3 && flag2){
        cout << "Yes" << endl;
    }else{
        cout << "No" << endl;
    }

    return 0;
}
```

## [C: Uniqueness](https://atcoder.jp/contests/abc398/tasks/abc398_c)
**解法**
- `map<int, int>` で各数を持っている人数を記録する
```cpp:ABC398C.cpp
#include <iostream>
#include <vector>
#include <map>
using namespace std;

int main(){
    int n;
    cin >> n;

    vector<int> A(n);
    map<int, int> M;
    for(int i=0; i<n; i++){
        cin >> A[i];
        M[A[i]]++;
    }

    int maxv = 0, maxid = -1;
    for(int i=0; i<n; i++){
        if(M[A[i]]==1 && maxv<A[i]){
            maxv = A[i];
            maxid = i + 1;
        }
    }

    cout << maxid << endl;

    return 0;
}
```

## [D: Bonfire](https://atcoder.jp/contests/abc398/tasks/abc398_d)
**解法**
- 焚き火と高橋君が風と逆向きに移動すると考える
- `set<pair<int, int>>` に焚き火の位置を記録する
```cpp:ABC398D.cpp
#include <iostream>
#include <string>
#include <set>
using namespace std;

int main(){
    int n, r, c;
    cin >> n >> r >> c;

    string s;
    cin >> s;

    set<pair<int, int>> S;
    int x = 0, y = 0;
    S.emplace(x, y);
    for(int i=0; i<n; i++){
        if(s[i]=='N'){
            x++;
            S.emplace(x, y);
            r++;
        }else if(s[i]=='W'){
            y++;
            S.emplace(x, y);
            c++;
        }else if(s[i]=='S'){
            x--;
            S.emplace(x, y);
            r--;
        }else if(s[i]=='E'){
            y--;
            S.emplace(x, y);
            c--;
        }

        if(S.count({r, c})){
            cout << 1;
        }else{
            cout << 0;
        }
    }

    cout << endl;

    return 0;
}
```
IBM i 駆け出し日記：RDiの投資対効果を円で試算する

# 「RDi導入の投資対効果の資料ってありますか?」

先週大阪で行われたセミナーにていただいた質問です。
開発環境をご紹介する際、よく聞かれるのがこの投資対効果というやつです。

---
**RDiのメリットをおさらい**
- RPGⅢ、ILE RPG、FF RPGの開発可能
同一ソースで固定フォームとFF RPGの併用も可能。固定フォームのプロンプト機能あり
- FF RPGへの変換機能有
- 一部終了してしまうADTS機能の代用(サポートがある状態で以下の機能が使える)
    - 報告書設計ユーティリティ(RLU)
    - 画面設計機能(SDA)
    - ファイル比較および組み合わせ ユーティリティー (FCMU)
- GUI画面でのデバッガー機能
- Git連携容易
- CI/CD機能の活用
- オープン系出身や若手開発者のモチベーション向上
- 日本語で使用可能
- 既存5250資産への対応が簡単
- 動作の安定性に加えて、IBMのサポート有
----



技術者のブログでお金のこと書くのも。。。と思いましたが、IBM i の良さを知ってもらうのがこのQiitaの目的ですので書きます。

# 算出時に参考にした記事
[チャールズさんのBlog](https://charlesguarino.net/2015/11/a-hard-dollars-and-sense-roi-calculation-for-ibms-rdi/)を参考にしました。
US COMMONの人でIBM i ユーザーの方です。

以下、簡単に日本語で内容をまとめます。
## 1日たった10分のロスが、年間325,000円の損失に
チャールズさんは、SEUでの非効率な作業によって、開発者が1日10分無駄にしていると仮定しています。
この「10分のロス」が、実は年間で大きな金銭的損失に直結するのです。

具体的な計算は以下の通り：

開発者の時給：$50（2024年3月時点、1ドル＝150円で換算 → 約7,500円）

1日10分のロス（1/6時間）

勤務日数：年間260日（週5日×52週）

→ 年間ロス金額：
50ドル × (1/6) × 260日 = 2,167ドル → 約325,050円（7,500円 × 260 ÷ 6）

たった10分の非効率が、年間32万円以上の損失に相当する、とチャールズさんは言っています。



# 2025年版の値段かつ円で試算
より現実的な視点で、日本のRPGエンジニアの平均的な単価を使ってシミュレーションしてみます。

現在、RDiのライセンス参考価格は1ユーザーあたり約20万円程度です
(※2025年3月時点での参考価格）。  
ちょっと高いなと感じる方もいるかもしれません。

しかし、エンジニアの人件費を踏まえて試算してみると、それでも十分に投資対効果があることが分かります。

---

## 例：単価100万円/月のRPGエンジニアの場合

ここでは、**単価100万円/月RPGエンジニア**を例に試算してみます。

### 前提条件

- エンジニア単価：**100万円/月**
- 稼働時間：**160時間/月**（20日 × 8時間）
- 時給換算：**100万円 ÷ 160時間 = 6,250円／時間**
- 1日の非効率（SEUなどでのムダ時間）：**10分（＝1/6時間）**
- 稼働日数：**年間260日**
- RDiライセンス費：**約200,000円**



### 年間のムダ時間コストを算出
- 1日の損失：  
  6,250円 × 1/6 ≒ 1,041.7円/日

- 年間の損失：  
  1,041.7円 × 260日 ≒ 270,920円/年



### ROIの計算

ROI（%） =（利益 − コスト） ÷ コスト × 100

- 利益（削減効果）：**約270,920円／年**
- コスト（RDi導入費）：**約200,000円**

ROI = (270,920 - 200,000) ÷ 200,000 × 100 ≒ 35.5%
→ **たった1年でRDi導入コストの35％以上のリターンが得られる計算です。**

さらに、2年、3年と使い続けることで、ROIは着実に上昇していきます。

- 1日15分の改善（年間削減額：約406,380円）
ROI = (406,380 - 200,000) ÷ 200,000 × 100 ≒ 103.2%
→ **1年で投資額の約2.03倍のリターンが得られることになります。**

- 1日20分の改善（年間削減額：約541,840円）
ROI = (541,840 - 200,000) ÷ 200,000 × 100 ≒ 170.9%
→ **1年で投資額の約2.71倍のリターンが得られることになります。**



# まとめ
以上、RDiの投資対効果をまとめてみました。
それ以外にも実際の、ROIは「時間の短縮」や「ミスの防止」といった見える効果だけではなく、冒頭のRDiのメリットを総合的に考えると、RDiの投資価値は非常に高いといえます。

RDiを使いこなすことで、1日20分どころか、30分以上の改善が実現できるケースも多々あります。

「RDiは高い」と感じるのは、その効果を見える化できていないだけかもしれません。
複数年使えばコストパフォーマンスはさらに向上し、ROIは数百％にもなります。

120日間のフリートライアルもありますので、これを機にRDiの導入を検討していただければ幸いです。
Will・Can・Mustで考える、QAが価値を最大化するためのアプローチ



> QAって、もっとプロジェクトに貢献できるはずなんだけどなぁ…

そんなモヤモヤを感じたことがある方へ。  
今回は「Will・Can・Must」というフレームワークを使って、QAの価値発揮をどう高めていけるかを整理してみます。

---

## 🧭 そもそも「Will・Can・Must」とは？

キャリア設計や人材育成で使われる有名なフレームワークです。

- **Will**：やりたいこと  
- **Can**：できること（スキル・経験）  
- **Must**：求められていること（今回は「プロジェクトからの期待」）

この3つが重なるところが、自分が最も価値を発揮できるゾーンだと言われています。

---

## 🧪 WillやCanだけ高くても、価値にはならない？

QAが「改善提案したい！」「自動化できる！」と意欲やスキルがあっても、  
**プロジェクト側のMust（期待値）が低い**と、こんなズレが起こります。

- 「そこまでやらなくても…」
- 「いや、今は別のことが大事なんだよね」

この状態、**ちょっとおせっかいなQA**になってしまっているのかもしれません。

---

## 🏗️ 一方で、Mustだけが高くても…

逆にプロジェクトからの期待（Must）が高いのに、  
QAのやる気（Will）やスキル（Can）が追いついていない場合も辛いです。

- 頼られているのに応えられない  
- プレッシャーだけが増えて、成果が出ない  

結果として、プロジェクトにとってもQAにとってもつらい状態になります。

---

## 🎯 結論：3軸のバランスが超重要

QAがプロジェクトの中で**最大限に価値を発揮できるのは**、

> **Will × Can × Must** の3つが  
> **バランスよく & 高い水準で整っている状態**

この三角形を意識しておくことで、QAの立ち位置や貢献の形がクリアになります。

---

## 🔧 Mustは“降ってくる”ものじゃない

ここが本題です。

Mustって「プロジェクト側が勝手に求めてくるもの」と思いがちですが、  
**実は“自分たちで引き上げにいく”もの**だと思うんです。

### 例えば：

- QAがプロジェクト運営側に参加する  
- 開発プロセス全体をリードしていく  
- QA視点でプロダクトを改善する動きそのものを仕掛ける  

こうして、Must（期待値）そのものをデザインする立場に立てると、  
WillやCanが“活かされる場”が自然と広がっていきます。

---

## 🧩 「スクラムマスター」というロールに惹かれる理由

僕が最近やってみたいなと思っているのが、**スクラムマスター**の役割です。

- 開発プロセスの中核に入る  
- チームを横断して動ける  
- QAの視点を持ちつつ、チームの動きを最適化する  

この立ち位置にいることで、Mustを自分たちで引き上げていけるし、  
WillやCanを価値に変える土台もつくりやすくなる気がしています。

---

## 📝 おわりに

QAがもっと価値を発揮するには：

✅ 自分たちの **Will（やりたいこと）** や **Can（できること）** を高めつつ  
✅ プロジェクトの **Must（期待値）** を **“自分たちで引き上げていく”視点** が必要

「Will・Can・Mustの三角形」を高い水準でそろえることで、  
QAという仕事はもっと自由に、もっと強く、もっと面白くなるはずです。

---

以上。この記事はMeetで話しているところを録画→録画データをツールに突っ込んでWhisperで文字起こし→過去の記事の文体を踏襲させつつChatGPTで生成した記事です。
アウトプットがはかどる！