OmniAICreator/Qiita-1.07M huggingface dataset:
Japanglish Tech Talk #5 プレゼンテーション紹介

こんにちは！[Tamtam](https://x.com/TamtamFitness) です。  
[Naru](https://x.com/1026NT) と一緒に **“Japanglish Tech”** イベントを主催しています。  

---

## Japanglish Tech Talk とは？

東京で開催する **エンジニア向け “英語オンリー” LT イベント** です。  
日本では英語で登壇する機会が少ないため、LT形式で気軽にアウトプットできる場として企画しています。  

---

## Japanglish Tech Talk #5 プレゼンテーション概要

> 📅 **開催日:** 2025-04-24  
> 🔗 **Connpass:** <https://japanglish.connpass.com/event/348703/>

---

### 🙏 スポンサーの皆さま、ありがとうございます！

| Sponsor | Blog / Site |
| --- | --- |
| **Ichizoku** | <https://ichizoku.io/category/sentry/> |
| **Loglass** | <https://zenn.dev/loglass> |
| **AI model** | <https://www.ai-model.jp/> |
| **Job Draft（転職ドラフト）** | <https://job-draft.jp/articles> |

---

### My AI Therapist: A Love Story 〜Dear AI, Am I a Good Engineer?  
**Speaker:** Ayaka  

![Ayaka Talk](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qr4tcnddeoctgcm0itzi.jpeg)

---

### Let’s Speed Up Personal Development with AI Code Reviews!  
**Speaker:** goofmint  
  
![goofmint Talk](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tn4qfnyjeh4ranf5hyo8.jpeg)

---

### Goodbye Stack Overflow, Hello AI-san: Coding in Plain English  
**Speaker:** Omer Ishag  
  
![Omer Talk](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/psns2xnfgzn9u0m9a4gh.jpeg)

---

### How to Double Your Development Speed with Cursor  
**Speaker:** Ryoya Fukudo  
 
![Ryoya Talk](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r5sg76weiu7imfdgm08r.jpeg)

---

## 次回イベントも開催予定！

🎉 **2025 年 8 月に次回ミートアップ開催予定！**  
登壇者・スポンサーも募集中です。ぜひご参加ください！

![Next Event Banner](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wjgkeve3imfh1wz4pjc8.png)

英語でアウトプットしたいエンジニアの皆さん、  
そして国籍を問わずテックコミュニティを盛り上げたい皆さんの参加をお待ちしています！
株価情報を取得する。

## 目的
株式コードから株価情報を調べるためのコードを作成してみました。コードは、copilotを使用して作成しました。

出力は、下記のようにしています。
```bash
                        社名 株式コード   PER      ROE  自己資本比率 配当利回り      PBR
0  NS SOLUTIONS CORPORATION  2327  21.834608  0.12227      11.431      2.10  2.505156
1       SOFTBANK GROUP CORP  9984  12.453234  0.10550     137.406      0.61  0.865052
2         TOYOTA MOTOR CORP  7203   7.042254  0.14547     107.389      3.72  0.981000
```

### Code
numeric_codes内に取得したいコード名を追加すると、情報が取得できます。取得したい情報を増やしたい場合は、リンクを参考に取得した項目名を追加することで取得項目を増やすことができます。
```Get_stock_information.py
import yfinance as yf
import pandas as pd

#stock codes
numeric_codes = ['2327', '9984', '7203'] 

# Prepare an empty list to hold data
data = []

# Loop through each stock code to collect data
for stock_code in numeric_codes:
    stock_data = yf.Ticker(stock_code + '.T')  # '.T'を追加してデータを取得
    try:
        # Extract relevant data
        short_name = stock_data.info.get('shortName', 'N/A')  # 社名
        yfpe_ratio = stock_data.info.get('trailingPE', 'N/A')  # PER
        roe = stock_data.info.get('returnOnEquity', 'N/A')  # ROE
        debt_to_equity = stock_data.info.get('debtToEquity', 'N/A')  # 自己資本比率
        dividend_yield = stock_data.info.get('dividendYield', 'N/A')  # 配当利回り
        pb_ratio = stock_data.info.get('priceToBook', 'N/A')  # PBR

        # Append the data as a row
        data.append([short_name,stock_code,yfpe_ratio, roe, debt_to_equity, dividend_yield, pb_ratio])
    except Exception as e:
        print(f"Error retrieving data for {stock_code}: {e}")

# Create DataFrame with the collected data
columns = ["社名","株式コード", "PER", "ROE", "自己資本比率", "配当利回り", "PBR"]
df = pd.DataFrame(data, columns=columns)

# Display the DataFrame
print(df)

# Save to CSV
csv_file_name = "stock_data.csv"
df.to_csv(csv_file_name, index=False)
```

### Link
[Yahoo Financeから会社情報を取得する](https://financialmarkets.hatenablog.com/entry/2024/06/26/165744)
はじめて「技術を学ぶ人、伝える人」に伝えたい。自然言語とプログラミング言語の違い

## はじめに

技術の進化を肌で感じながらも、**「その技術って実際どういう意味があるの？」** とずっとモヤモヤしていませんか？そんな疑問を解決するために、今回はプログラミング言語と自然言語の違いを整理してみました！

**「え、まさか自分が自然言語の感覚でプログラミング言語を理解してた！？」** という発見が私にはありました。これからプログラミングを学ぶ人や、技術広報、エンジニア採用に携わる人には絶対に知ってほしい、そんな内容です！

## 自然言語とプログラミング言語の違い

| 項目 | 自然言語 |プログラミング言語 |
|---------|-------------------------------|-------------------------|
| 言語の例 | 日本語・英語・ドイツ語など | JavaScript・PHP・Swiftなど |
| 伝える相手 | 人間 | コンピュータ |
| 言語の目的 | 情報や感情、考えを伝える | 正確な命令を与える |
| ニュアンス | 曖昧でも文脈で理解される | 厳密な文法ルールに従う |
| 表現方法 | 話す・書く・聞く・読む | コード（プログラムとして書く） |

学校で習った「英語」や「ドイツ語」など、 **人間へ話しかける時に使われる言葉は「自然言語」** と呼ばれています。それに対して「JavaScript」や「PHP」など、 **コンピュータに話しかける言語は「プログラミング言語」** と呼ばれています。

「画面に ‘Hello, world!’ と表示してね」と伝えたい時、相手が日本人なら「画面に ‘Hello, world!’ と表示してくれませんか？」と日本語（自然言語）で伝えます。

一方でコンピュータに「画面に ‘Hello, world!’ と表示してね」と伝えたい時は、例えばJavaScript（プログラミング言語）で以下のようなコードを書きます。

```javascript
console.log("Hello, world!");
```

## 正しく動いてもらうための命令を出す

日本語や英語など **自然言語の目的は情報や感情、考えを伝えること** です。例えばアメリカ留学中に現地の人に、I go school. というと「ああ、学校に行くのね」と何となく相手に意味は伝わりますよ。

でもプログラミング言語では、ほんの少しの間違いでもエラーになります。それは **プログラミング言語の目的は「命令」** だからです。そのためプログラミング言語を扱う際にはルールを厳守する必要があります。

自然言語とプログラミング言語の違いを整理するとこんな感じです。
- 自然言語＝ **「伝えたい気持ちに合わせていろんな方法を使う」**
- プログラミング言語＝ **「コンピュータに間違いなく伝えるためにコードを書く」**

TOEICのようなマークシート形式のテストに似ていますね。 I go school. だと不正解（0点）、I go to school. だと正解（5点）みたいな感じのイメージです。正しいか、正しくないかで判断されます。

## 正しさを判断するために、表現方法は限定的

目的の違いから表現方法の豊富さにも差異があります。自然言語（英語や日本語）は表現方法が豊富です。使う場面や媒体が自由で、表現も感情やニュアンスを乗せられます。

- 話す（会話、スピーチ）
- 書く（手紙、小説、メール）
- 聞く（ラジオ、会話を聞く）
- 読む（本、記事）

一方でプログラミング言語は基本的には「コードを書く」ことがメイン。コンピュータに正確に命令すること」が目的なので、表現が正しいかどうか判断できないときにエラーが発生します。

- 決められた場所で（テキストエディタなどで）
- 決められた方法で（基本はテキストを用いて）
- 決められたルールで（厳密な文法のルールに則って）

というように、プログラミング言語には厳密なルールがあります。

これもTOEICのようなテストと似ていますね。不正解（0点）、正解（5点）で、マークシートの記入欄がズレていても情状酌量の余地は一切ありません。

## まとめ

| 項目 | 自然言語 |プログラミング言語 |
|---------|-------------------------------|-------------------------|
| 言語の例 | 日本語・英語・ドイツ語など | JavaScript・PHP・Swiftなど |
| 伝える相手 | 人間 | コンピュータ |
| 言語の目的 | 情報や感情、考えを伝える | 正確な命令を与える |
| ニュアンス | 曖昧でもOK（文脈で理解される） | 命令が全て（ルール厳守） |
| 表現方法 | 話す・書く・聞く・読む | コード（プログラムとして書く） |

改めて自然言語の特徴を踏まえて、プログラミング言語の原則はこんな感じです。
- プログラミング言語は**コンピュータに対して期待される動作を指示する**ための手段。
- コンピュータに指示を出しているので、**英語（自然言語）を理解できないのは当然**。
- 正確な指示を伝えるのが目的のため、**基本的にはルール厳守で表現方法も限定的**。

例えばこの前提を理解していると、**コンピュータが人間の言語を理解し、解釈し、生成するための技術である自然言語処理（NLP、Natural Language Processing）** の優れた点を技術の歴史から理解できたりします。

ということで技術広報を始めて1年目の人にまず最初に知ってほしい、自然言語とプログラミング言語の違いでした！
type-challenges解いてみた 初級 268 easy-if


# 問題

````md

条件値`C`、 `C`が truthy である場合の戻り値の型`T`、`C`が falsy である場合の戻り値の型`F`を受け取る`If`を実装します。
条件値`C` は`true`か`false`のどちらかであることが期待されますが、`T` と `F` は任意の型をとることができます。

例えば：

```ts
type A = If<true, 'a', 'b'>; // expected to be 'a'
type B = If<false, 'a', 'b'>; // expected to be 'b'
```
````



## 回答

```ts
type If<C extends boolean, T, F> = C extends true ? T : F;
```

### ちょっと解説

- `C extends boolean,`
C(ジェネリクスの第一引数)がbooleanでない場合エラーを出したいためこう書きます。

- `C extends true ? T : F`
条件付き型 (conditional type)です。
C(ジェネリクスの第一引数)がtrueである場合`T`を、そうでない場合`F`を返します。
今回の場合`C`は`C extends boolean`と書かれており、booleanであることは確実なのでtrueなら`T`、falseなら`F`を返す形になります。
共通エラーメッセージ変更【Laravel】

# やりたいこと
新規登録ページで、
バリデーションエラーメッセージのデフォルトを変更させたい。



## ビフォーアフター例
### 新規登録画面
#### ↓ 編集前
![スクリーンショット 2025-04-27 23.52.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726068/16333adb-9cc3-40ac-a1cb-a1364359c724.png)

#### ↓ 編集後
![スクリーンショット 2025-04-27 23.54.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726068/b892f4dc-809d-4b69-b4e6-b74ab81e082b.png)



# ⚠️ 最初に注意点
以下4点を元に実装していく。
✅ ラベル（パスワード）そのまま使う（＝ラベル名は変更しない）
✅ 新規登録画面で
✅ エラー文を共通管理（langファイルだけでやる）
✅ つまり、コントローラー側では何もしない



# ✅ 手順
## ① /lang/ja/validation.php を開く
ファイルパス例👇
```
/lang/ja/validation.php
```
このファイルが、 Laravel でバリデーションエラーメッセージを共通管理する場所！


## ② custom セクションにフィールド名別にエラーを書く
具体的には、customキーの中にこう追加👇
```/lang/ja/validation.php
'custom' => [
    'password' => [
        'required' => 'パスワードを入力してください。',
        'confirmed' => 'パスワードとパスワード(再確認)が一致していません。',
        'min' => 'パスワードは8文字以上で指定してください。',
    ],
    'password_confirmation' => [
        'required' => 'パスワード(再確認)を入力してください。',
    ],
],
```

### ここでポイント
| 項目 | 内容 |
|:-----------|:------------|
| name属性 | そのまま（password, password_confirmation） |
| ラベル表示 | 「パスワード」「パスワード（再確認）」そのまま |
| コントローラー側 | 特にエラーメッセージを指定しないでOK！ |


## ③ コントローラーのバリデーションは普通でいい
例えば、新規登録処理（たぶんRegisteredUserController）のバリデーションは
普通にこれでOK👇
```/Http/Controllers/Auth/RegisteredUserController.php
$request->validate([
    'name' => ['required', 'string', 'max:255'],
    'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
    'password' => ['required', 'confirmed', 'min:8'],
]);
```
メッセージ指定は一切不要！
→ 自動的にlang/ja/validation.phpのカスタムメッセージが使われる！



## ④ ゴール
![スクリーンショット 2025-04-27 23.54.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726068/b892f4dc-809d-4b69-b4e6-b74ab81e082b.png)



# 関連
https://qiita.com/honaki/items/0696fe34fc8883a279f7
【Mac】コマンドでスリープさせる方法

## スリープ

以下のコマンドを実行するとMacをスリープさせられます。

```terminal
pmset sleepnow
```

## ディスプレイのみ

以下のコマンドを実行するとディスプレイのみスリープさせられます。

```terminal
pmset displaysleepnow
```
ハムチレクチャー配信まとめ

REALITYで2025/4/27 21:00~ の配信で
使用したスライドとサンプルをおいておきます！


# スライド

<script async class="speakerdeck-embed" data-id="d525dd27239b4233a1c6233e87b2fc40" data-ratio="1.77777777777778" src="//speakerdeck.com/assets/embed.js"></script>


# サンプルプログラム

https://codesandbox.io/embed/cc8hdj?view=preview
長いテキストを自動分割して複数QRコード（SVG）にするツールを作った話

# はじめに

最近、「大きなテキストデータをQRコードにしたい」というニーズに直面しました。  
しかし、通常のQRコードには文字数制限があり（おおよそ最大1000字程度）、そのままでは入りきりません。  

そこで今回は、**長いテキストを自動で分割し、複数のSVG形式のQRコードとして出力する簡単なツール**を作ったので紹介します。

使用した主な技術は以下です。

- Node.js
- `fs`モジュール（ファイル読み書き）
- `qrcode`パッケージ（QRコード生成）

https://www.npmjs.com/package/qrcode

# 処理の流れを解説

1. **入力ファイルの読み込み**
   - 指定された`path`のテキストファイルを読み込みます。
2. **文字数制限ごとに分割**
   - 1チャンク最大1000文字ずつに分割します。
3. **HTMLファイルの初期化**
   - 出力先`result.html`を空にして、HTMLのヘッダー部分を書き込みます。
4. **各チャンクをQRコードに変換して出力**
   - 各チャンクをSVG形式のQRコードに変換し、順番にHTMLファイルに追記していきます。
5. **HTMLの締め**
   - 最後に`</body>`と`</html>`を追加してHTMLを完成させます。
6. **生成されたファイルを自動で開く**
   - `this.openFile(outputDir)`で、生成されたQRコード一覧HTMLをすぐにブラウザなどで確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760374/dea1cd4a-55c6-49da-bb64-7efdedb29775.png)

# 実装コード

作成したメインメソッドは以下の通りです。

```typescript:FileUtil.ts
public genQrcode(path: string): void {
  const MAX_QR_CHARS = 1000;
  const chunks: string[] = [];
  const outputDir = "output/qr_parts/result.html";
  const input = fs.readFileSync(path, "utf8");

  for (let i = 0; i < input.length; i += MAX_QR_CHARS) {
    chunks.push(input.slice(i, i + MAX_QR_CHARS));
  }

  fs.writeFileSync(outputDir, "");
  fs.appendFileSync(
    outputDir,
    [
      `<!DOCTYPE html>`,
      `<html>`,
      `<head>`,
      `<title>SVG parts</title>`,
      `</head>`,
      `<body>\n`,
    ].join("\n")
  );

  chunks.forEach((chunk, i) => {
    QRCode.toString(chunk, { type: "svg" }, function (_err, url) {
      fs.appendFileSync(outputDir, `<h1>part ${i + 1}</h1>\n`);
      fs.appendFileSync(outputDir, url);
    });
  });

  fs.appendFileSync(outputDir, [`</body>`, `</html>`].join("\n"));
  this.openFile(outputDir);
}
```

# 使い方

1. 長いテキストファイルを用意する（例: `input.txt`）
2. コードの`path`にファイルパスを指定して`genQrcode`を呼び出す
3. `output/qr_parts/result.html`が生成され、ブラウザで開くとチャンクごとのQRコード一覧が見れる！

# 工夫したポイント

- **ファイルを一気に作るのではなく、チャンクごとに少しずつ追記する**ことで、大量データにも対応できるようにしています。
- **SVG形式で出力**しているので、解像度を気にせずきれいなQRコードが表示できます。
- それぞれのチャンクに「part n」という見出しをつけて、どの部分かわかりやすくしています。

# 注意点

- 1000文字という制限は、データの内容（日本語/英語や記号の比率）によってはもっと厳しくなる場合があります。
- ファイルサイズが大きすぎる場合、ブラウザで開くのに少し時間がかかるかもしれません。
- インデントや空白が全部なくなり、1行でベタっと出力されてしまいます。

# まとめ

長文を複数QRコードに分割するニーズは意外と多くあります。  
今回のツールは、 **「とりあえず分割して一覧化したい！」** という用途にぴったりです。

今後、さらに改善するなら、
- ダウンロードボタンを付ける
- ZIP圧縮でまとめて保存
- PDFとしてまとめる
などにもチャレンジしていきたいです！
LPIC300のための勉強備忘録②

・samba-tool サブコマンド
Samba サーバーを管理するためのCLI（コマンドラインインターフェース）ツールです。特に **Active Directory ドメインコントローラー（AD DC）**として Samba を使っている場合に非常に重要なツール
サブコマンドの部分に入るのは、以下の４つ
dns　DNSを管理
domain　ドメインを管理
drs レプリケーションを管理(DRSとはディレクトリ複製サービスの意味)
testparm　設定ファイルの構文チェック
user　ユーザを管理
group グループを管理
・wbinfo
winbindデーモンに情報を問い合わせるコマンド、winbindはSambaにおいてLinuxとWindowsのアカウント管理を統合するサービス

・smbpasswd
Sambaユーザーのパスワードを設定・変更するためのコマンド（-a：追加、-x：削除）

・Sambaの設定ファイル(smb.conf)において、idmapオプションで使用できるバックエンド
tdb,ldap,nss

・Samba 4サーバにおいて、Active Directoryのドメインコントローラ(AD DC)としての機能を有効化する
samba-tool domain provision

・samba-toolコマンドのuser createサブコマンド
--surname : ユーザーの姓
--must-change-at-next-login : 次回ログイン時にパスワード変更を強制するかどうか
--userou : ユーザーのOU

・Windowsにおいて、セキュリティ識別子（SID）が割り当てられる対象となるエンティティ
ユーザー
グループ
サーバー（コンピューター）

・Sambaの設定ファイル(smb.conf)において、Sambaサーバ自身で処理できないDNSリクエストの転送先となるDNSサーバを指定するオプション
dns forwarder

・Active DirectoryのUsersコンテナ（CN=Users）の特徴
このコンテナにグループポリシー（GPO）を割り当てることはできない (﻿※GPOを割り当てられるのはコンテナでなくOUである)
新しく作成したユーザーはこのコンテナに追加される

・FSMOロール
ADは基本的に複数のドメインコントローラー（DC）で情報を共有・同期するが、いくつかの操作は1台のDCだけがマスターとして行う必要がある。これを担うのが「FSMOロール」
スキーママスター(スキーマ（ADの構造）を変更できる唯一のDC)
インフラストラクチャマスター(ドメイン間のオブジェクト参照を更新する)
ドメイン名前付けマスター(ドメインの追加・削除などを管理)
RIDマスター(オブジェクトの一意ID（RID）の割り当てを管理)
PDCエミュレーター(パスワード変更の即時反映、時刻同期、古いクライアントの互換性など)

なぜ必要なのか⇒ADは分散システムだけど、一貫性を保たなきゃいけない処理があるから。全部が同時にマスターをやったらデータがぶつかるので、「この処理はこのサーバーだけが担当ね」と役割分担している。

・samba-tool domain passwordsettings show　で確認できるもの
パスワード履歴の保存数
最長のパスワード有効期間

・SYSVOL 
Active Directory (AD) ドメイン環境で、グループポリシー設定やログオンスクリプトなどの設定ファイルを ドメインコントローラー間で共有し、同期させるために使用される。"SYSVOL"ファイル共有はすべてのドメインコントローラ上に存在している必要がある

・複数のSambaサーバ間でSYSVOL共有をrsyncによる同期をする際にすべきこと
PDCエミュレータであるドメインコントローラから他のドメインコントローラに同期する
同期元とならないサーバのSYSVOL共有を読み取り専用にする
GPOを変更する際は、同期元となるドメインコントローラで行う（レプリケーションソースとなるドメインコントローラですべてのGPOを変更を行う）

・Sambaにおいて、特定のユーザーの詳細情報とステータスフラグを表示するコマンド
pdbedit

・Sambaサーバで解決不能なDNS問い合わせを別のDNSサーバに転送する
パラメータ"dns forwarder"に転送先のDNSサーバを指定する

・Active Directoryドメインのグローバルカタログにアクセスする方法
TCP/3268ポートに対するLDAP 接続

・samba-tool group addコマンド実行時に使用できるオプション
--groupou : ユーザオブジェクトを所属させるOUを指定する
--group-type : "Security"もしくは、"Distribution"でグループの種別を指定する
・realm
Sambaの設定ファイル(smb.conf)において、Active Directoryドメイン名を指定するパラメータ
このパラメータはKerberosレルムを指定するためにも使用される。

・Sambaの設定ファイル(smb.conf)において、SambaをActive Directoryのドメインコントローラとして設定するために設定する必要があるもの
server role = active directory domain controller

・LDAPルートオブジェクト
DC＝***,DC=**,DC=*(「DC」は「Domain Component」の略で、ドメイン名の一部を表す。)

・Sambaの設定ファイル(smb.conf)において、Winbindが生成するpasswdデータベースにエントリを定義するtemplate設定
template homedir
template shell
自宅でPower Platformを学習するには？私が選んだ最適なMicrosoft 365プラン

## はじめに


業務でPower PlatformやSharePointを使える環境にありますが、 
就業時間中にじっくり学習するのは難しく、
「自宅でも自由に触れる環境を持ちたい」と考えるようになりました。

最初は、Power BI学習のためにMicrosoft 365 Personalプランを契約し、 
64bit版Office環境を自宅PCに整えていました。

Power Platformの学習は、許可を得て会社PCで業務時間外に行っていましたが、  
気軽に自由に学習することが難しいこともありました。

そこで、自宅に自由に使えるビジネス環境を整えるため、  
Microsoft 365 Businessプランへの切り替えを決断しました。


この記事では、
- なぜPersonalプランではダメだったのか
- Businessプランをどう選んだか
- Microsoft 365プラン比較（個人向けとビジネス向け）2025年現在
- 気づいたこと

をまとめます。

---

## 1. なぜMicrosoft 365 Personalではだめだったか

Microsoft 365 Personalは
個人利用では十分なプランですが、  
ビジネス用途では次の制約がありました。

- SharePointサイトを作れない
- ビジネス用Teamsが使えない
- Power Platformの本格運用が難しい（特にSharePoint連携）←これができないのは困りました！

**Power Platform全体を使いこなすには限界**を感じました。

---

## 2. Microsoft 365 Business Basic契約 → Standardにアップグレード

最初に個人用のPersonalライセンスにプラスして、一番安いBusiness Basic（月額1038円）を契約しSharePointを利用することを検討しました。

- SharePoint、Teams、Power Platformの利用はすぐできた
- しかし、私（と家族）にPersonalが必要なのか疑問
- PersonalとBusiness Basic2つのライセンスではなく1つのライセンスに統一したほうが安いじゃん

そこで、Personalは解約し、  
Business Standardにアップグレードしました。

これで、
- ローカル版Word、Excel、PowerPoint
- SharePoint、Teams、Power Platform

すべてを自由に使える最もコスパのよい環境が完成しました！

---

## 3. Microsoft 365プラン比較（個人向けとビジネス向け）

| プラン | 月額（税込） | Share Point | Power Platform | コメント |
|:-|:-|:-|:-|:-|
| Personal |2,130円 | ❌ | 一部 | 家庭利用向け、Power Platform本格利用には不向き（SharePoint連携できない） |
| Business Basic | 1,038円 | ✅ | ✅ | コスパ重視。デスクトップOfficeなし |
| Business Standard | 1,774円 | ✅ | ✅ | SharePoint＋デスクトップOfficeも全部入り！ |

**👉 最終的に会社と同じ環境がひとつのライセンスで完成するBusiness Standardを選びました。**

---

## 4. 【参考】Microsoft公式ライセンス情報リンク

- [Microsoft 365 Business プラン比較（公式サイト）](https://www.microsoft.com/ja-jp/microsoft-365/business/compare-all-microsoft-365-business-products)
- [Microsoft 365 個人向けプラン（公式サイト）](https://www.microsoft.com/ja-jp/microsoft-365/buy/compare-all-microsoft-365-products)
- [Microsoft サブスクリプションのキャンセル方法（公式サポート）](https://support.microsoft.com/en-us/account-billing/cancel-your-microsoft-subscription-c2c6b0e3-cab3-cb98-d83e-c9ad54620530?OCID=AID_ema_TRX_SubscriptionRenew)

公式の最新情報を必ずチェックするのが大切です！

---

## 5. まとめと感想

- 初めからMicrosoft 365 Businessプランにしておけばよかった。
- **自宅に自由に使えるビジネス環境を自分で整える**ことはプライスレスで、もっともストレスのない最適解でした。

---

> 環境が整うと気持ちいい♪
![https___girlydrop.com_wp-content_uploads_post_p3753.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4022390/66b87494-25bd-4695-909c-65e26bd6c588.jpeg)
Rubyのバージョン管理：rbenvの使い方と他言語との比較

# はじめに
プログラミング言語の多くは、バージョン管理ツールを提供しています。​これらのツールは、複数のバージョンをインストールし、プロジェクトごとに適切なバージョンを切り替えることを可能にします。​例えば、Node.jsにはnvm、Pythonにはpyenvがあります。​Rubyでは、rbenvがその役割を果たします。​本記事では、Rubyのバージョン管理ツールであるrbenvの基本的な使い方と、他言語のバージョン管理ツールとの比較について解説します。​

# バージョン管理ツールとは？
バージョン管理ツールは、特定のプログラミング言語の複数のバージョンを管理し、プロジェクトごとに適切なバージョンを選択・切り替えるためのツールです。​これにより、異なるプロジェクトで異なる言語バージョンを使用する必要がある場合でも、柔軟に対応できます。​

**主なバージョン管理ツールの一覧**

| 言語     | バージョン管理ツール      | 備考                               |
|----------|---------------------------|------------------------------------|
| Ruby     | rbenv, rvm                | 軽量なrbenvが人気                  |
| Node.js  | nvm, fnm                  | nvmがデファクトスタンダード       |
| Python   | pyenv, conda              | pyenvがシンプルで使いやすい       |
| Java     | sdkman                   | 複数のJDKを簡単に切り替え可能     |
| Rust     | rustup                   | 公式が提供するツール              |

# rbenvの基本的な使い方
rbenvは、Rubyの複数バージョンを管理し、プロジェクトごとに適切なバージョンを切り替えるためのツールです。​以下に、rbenvの基本的なコマンドとその用途を示します。​

**Rubyのインストール**
まず、目的のRubyバージョンをインストールします。​

```Bash
rbenv install 3.2.2
```
このコマンドは、Rubyのバージョン3.2.2をインストールします。​インストール後、どのプロジェクトでこのバージョンを使用するかを指定する必要があります。​

**グローバル設定**
システム全体でデフォルトとして使用するRubyバージョンを設定します。​

```
rbenv global 3.2.2
```
この設定により、特定のプロジェクトで別のバージョンが指定されていない限り、Ruby 3.2.2が使用されます。​

**ローカル設定**
特定のプロジェクトディレクトリ内で使用するRubyバージョンを設定します。​
```
rbenv local 2.7.6
```
このコマンドを実行すると、現在のディレクトリに.ruby-versionファイルが作成され、その中に2.7.6と記述されます。​これにより、そのディレクトリ内ではRuby 2.7.6が使用されます。​

# バージョンの優先順位
rbenvは、以下の優先順位でRubyのバージョンを決定します。​

1.ローカル設定（.ruby-versionファイル）

2.シェル設定（rbenv shellコマンドで一時的に設定）

3.グローバル設定（~/.rbenv/versionファイル）​

# 他言語のバージョン管理ツールとの比較
rbenvと同様に、他のプログラミング言語でもバージョン管理ツールが提供されています。​以下に、Node.jsのnvmとPythonのpyenvの基本的な使い方を示します。​

**Node.jsのnvm**
nvmは、Node.jsのバージョンを管理するツールです。​

```
nvm install 18.16.0
nvm use 18.16.0
```
これらのコマンドで、Node.jsのバージョン18.16.0をインストールし、使用することができます。​

**Pythonのpyenv**
pyenvは、Pythonのバージョンを管理するツールです。​

```
pyenv install 3.10.4
pyenv global 3.10.4
```
これらのコマンドで、Pythonのバージョン3.10.4をインストールし、システム全体で使用することができます。​

# まとめ
バージョン管理ツールは、複数のプロジェクトで異なる言語バージョンを使用する際に非常に便利です。​rbenvを使用することで、Rubyのバージョンを柔軟に管理でき、他の言語でも同様のツールが提供されています。​これらのツールを活用することで、開発環境を整え、プロジェクトごとの要件に対応することが可能になります。​
仮想マシン上のユーザにログインできないとき (Hyper-V, Windows Server)

## 前提となる環境
* 仮想環境
    * Hyper-V
* ホストOS
    * Windows 10 Enterprise LTSC 1809
    * ワークグループ環境（非ドメイン環境）
* ゲスト
    * Windows Server 2016 Standard
    * ワークグループ環境（非ドメイン環境）

## 状況
仮想環境 Hyper-V 上の仮想マシン (Windows Server) にローカルユーザアカウントを作成した。
作成したアカウントにサインインしようと、ユーザ名・パスワードを入力したところ、次のようなメッセージが表示されて正常にサインインできなかった。

> リモートでサインインするには、リモートデスクトップサービス経由でサインインする権限が必要です。既定では、Remote Desktop Usersグループのメンバーがこの権限を持っています。所属しているグループに権限がない場合や、Remote Desktop Usersグループから権限が削除されている場合は、権限を追加する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125577/eb136a20-0ea5-41ac-b77b-d36dab46b65d.png)


## 解決方法

* Hyper-V 仮想マシン接続の `拡張セッション` と `基本セッション` を切り替える
* Remote Desktop Users グループに所属させる
* 仮想マシンを再起動する
AtCoderをPythonで取り組んだ振り返り(ABC403 A,B)

どうもこんにちは！

今週もAtCoderのコンテストに参加しましたので記録します。
今回はBまで完答。Cは計算量を最後まで落としきれず。残念。

# 問題

問題は以下のリンクから。完答できたA,Bと途中までやったCを振り返ります。

https://atcoder.jp/contests/abc403/tasks

## A - Odd Position Sum -
与えられた長さNの正整数列から、奇数個目の要素の総和を出力する問題。
素直に、数列を配列に入れて奇数個目の値だけを変数に足しあわせていくとしました。なお与えられた数列は最初を1個目と指定されています。
~~~Python
n = int(input())
s = [int(x) for x in input().split()]

ans = 0
for i in range(len(s)):
    if (i+1) % 2 == 1:
        ans += s[i]

print(ans)    
~~~

## B - Four Hidden -
英小文字と?で構成する文字列Tと英小文字からなる文字列Uが与えられ、Tの中にUが含まれるケースがあるかを判定するという問題。なお、?は任意の1文字に置き換えることができます。(いわゆるワイルドカードですね)
解くにあたって、Tの文字列の起点を１文字ずつずらしながら１文字ずつ一致するかをチェックするとしました。例えばTの5文字目とUの1文字目が一致すれば、次はTの6文字目とUの2文字目が一致するかを判定していくという感じです。Tの文字が?のときも一致する扱いです。
このときに、Tの文字列より長い位置を判定しないようにする必要があります(これを忘れて2ミス)
~~~Python
s = input()
u = input()
ans = "No"

i,j,k = 0,0,0
for i in range(len(s)):
    for j in range(i,i+len(u)):
        if j < len(s) and (s[j] == u[k] or s[j] == '?'):
            k += 1
            if k == len(u):
                ans = "Yes"
                break
        else:
            k = 0
            break
    if ans == "Yes":
        break
    
print(ans)
~~~

## C - 403 Forbidden -
N人のユーザーとM個のページがあるとして、Q個のクエリを処理した結果を出力する問題。クエリは以下の3種類。
1\. ユーザXにページYの閲覧権限を与える
2\. ユーザXにすべてのページの閲覧権限を与える
3\. ユーザXがページYの閲覧権限があるかを出力する

ユーザもページもクエリも最大数は$2 × 10^5$個です。計算量を考えないといけないC問題の定番ですね。
解くにあたって、まずユーザーごとの閲覧権限を保存する2次元配列に保存したところ、以下の2点で計算量をオーバーするケースがありました。
* すべてのページの閲覧権限を与えるときに、ユーザXの配列に1からMの数字を格納する(for文)
* ユーザXの配列にYの数字が入っているかを判定する(y in xの配列)
クエリを１つずつ処理するだけでもQ回ですが、for文にしてもy in 配列にしても、O(n)なので制限オーバーとなりました。
このうち、すべてのページの閲覧権限については、すべてのページの権限があるか無いかの2値で保存するとして独立させたのでよいのですが、一部のページしか権限がない場合の判定の計算量の落とし方がわかりませんでした。集合を使えばよさそうとは思っていたのですが、実装のしかたがわからず。
で、これを踏まえて書いたコードが以下です。
解説を見ると、配列の中にset()を入れて集合にしていました。配列の要素に集合を使えるという知識や発想がなかったです。残念。
~~~Python:計算量が多くてTLE
n,m,q = map(int,input().split())
allow_part = [[] for _ in range(n)] # 解説では [set() for _ in range(n)]とされていた。
allow = {}

for _ in range(q):
    query = list(map(int,input().split()))
    x = query[1]-1
    if query[0] == 1: # XにYの閲覧権限を付与
        y = query[2]-1
        allow_part[x].append(y)
    elif query[0] == 2: # Xにすべてのページの閲覧権限を付与
        allow[x] = 1
    elif query[0] == 3: # XにYの閲覧権限の有無を出力
        y = query[2]-1
        if x in allow and allow[x] == 1:
            print("Yes")
        elif y in allow_part[x]: # ここの計算量を減らす必要がある
            print("Yes")
        else:
            print("No")
~~~


# おわりに
C問題の完答には計算量の落とし方を色々知りたいところです。
ところで、いつもは1万人くらい参加していますが今日は7900人程度だったみたいですね。珍しく日曜日に開催だったからでしょうか。GWで不在の方も多いのかもしれませんね。
来週はGWまっただなかなので、不参加になるかもしれませんが、参加したら振り返りしたいと思います。

ではでは。
pushしたコミットメッセージを修正する方法

## はじめに
Gitで作業中に誤ったコミットメッセージをpushしてしまうことがあります。
その場合、リモートリポジトリの履歴を修正することができます。
本記事では、誤ったコミットメッセージを修正する方法をステップごとに説明します。

## コミットメッセージの修正方法
今回は、以下のような誤ったコミットメッセージを修正していきます。
**"[add]実装した内容"**を記載したはずが、"**[実装した内容]**"のままリモートブランチに
pushしてしまいました:rolling_eyes:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958955/2a3025bc-14b0-433f-b38e-032ea18698cc.png)

### 1. インタラクティブリベースを開始する
まず、修正したいコミットがリモートリポジトリに反映されている場合、そのコミットを編集するためにインタラクティブリベースを使用します。対象のコミットから遡ってリベースを行います。

コミット履歴を確認するために、**git log --oneline コマンド**を実行します。

```bash
git log --oneline
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958955/9cbc8a1b-d87a-4b5d-83fe-69216d6f0208.png)

今回は、c59f733 のメッセージを修正したいので、次のコマンドを実行します：
```bash
git rebase -i c59f733^
```

下記内容が実行結果です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958955/82a92dc0-1e26-439a-b2c3-656fb6499331.png)

今回は Git のコミットハッシュを指定しましたが、下記のコマンドでも実行可能です：

```bash
git rebase -i HEAD~N
```
:::note info
**N** は修正したいコミットの数を指定します。
例えば、最後の4つのコミットを対象に修正する場合は HEAD~**4** と指定します。
:::

### 2.リベース対象のコミットを選択する
エディタが開いたら、vimで修正したいコミットの行を「**pick**」→「**reword**」に変更します。`reword` はそのコミットメッセージのみを修正するオプションです。

**pick**を

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958955/d4cfe247-ecf3-4555-b148-cb8fac8db37d.png)

**reword**へ変更します。その後、**Esc キー**を押した後に **:wq** と入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958955/1bde2edc-7643-47d1-86a9-7c55a0730b02.png)

### 3. コミットメッセージを修正する
エディタが進行すると、修正したいコミットメッセージが表示されます。
ここで、誤って記載したメッセージを修正します。
最初に表示されるのは次のような状態です:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958955/1bde2edc-7643-47d1-86a9-7c55a0730b02.png)

ここで、メッセージを"**[add]実装した内容**"に変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958955/6d9db816-d645-4904-8fcc-835c3c83e6b0.png)


以下の通りに修正が完了したら、**Esc キー**を押した後に **:wq** と入力し、エディタを保存して終了します。この操作によって、コミットメッセージが修正されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958955/df5f6d67-8d1c-404a-9823-445ed1d9ab83.png)

### 4.リベースの結果を確認
[ユーザー情報の取得、更新、削除機能のエンドポイントを実装] → [add]ユーザー情報の取得、更新、削除機能のエンドポイントを実装へ変更できていることを確認できました:ok_woman:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958955/76986f14-e01c-4c69-b1d3-0e0847741be4.png)

### 5.強制的にリベース結果を pushする
意図した通りにコミットメッセージが修正されましたので、リモートに変更を反映させるために、以下のコマンドを実行します。リベース後、リモートに強制的にプッシュする場合は、**--force オプション**を使います。

```bash
git push --force
```

修正後、リモートリポジトリにもきちんとコミットメッセージが反映されていることが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3958955/a743ed74-7a56-4890-bc28-6fe2effaf9e0.png)

## おわりに
コミットメッセージを修正する際は慎重に行い、pushする前に確認しましょう:sweat_smile:
ABC403をPythonで（A～D）

AtCoder Beginner Contest 403（Promotion of AtCoder Career Design DAY）の解答等の速報的まとめ

https://atcoder.jp/contests/abc403



# A問題
https://atcoder.jp/contests/abc403/tasks/abc403_a

最初から1つおきに選択した総和を出力
```python:A
n = int(input())
a = list(map(int, input().split()))
print(sum(a_i for a_i in a[::2]))
```

# B問題
https://atcoder.jp/contests/abc403/tasks/abc403_b

全パターンをシミュレーションする
```python:B
t = input()
u = input()

for i in range(len(t) - len(u) + 1):
    flag = True
    for t_i, u_i in zip(t[i:], u):
        if t_i != "?" and t_i != u_i:
            flag = False
    if flag:
        exit(print("Yes"))

print("No")
```

# C問題
https://atcoder.jp/contests/abc403/tasks/abc403_c

前ページ見れる人と各人が見れるページ一覧をsetで管理する
```python:C
n, m, q = map(int, input().split())

all_view = set()
can_view = [set() for _ in range(n + 1)]

for _ in range(q):
    com = list(map(int, input().split()))
    if com[0] == 1:
        x, y = com[1:]
        can_view[x].add(y)
    elif com[0] == 2:
        x = com[1]
        all_view.add(x)
    elif com[0] == 3:
        x, y = com[1:]
        if x in all_view or y in can_view[x]:
            print("Yes")
        else:
            print("No")
```

# D問題
https://atcoder.jp/contests/abc403/tasks/abc403_d

$d=0$のとき、同じ数は１つを残して消す

$d > 0$のときは、$d$の余りで各数をグループ分けができ、各グループの中で連続して数が出現する区間でのみどこを消すか考慮する必要が出てくる
消す個数はDPで最小パターンを考える

```python:D
from collections import Counter

def solve(lst):
    # dp[i][j] = i番目でj(0消した、１消さない)のときの消した最小個数
    dp = [[0] * 2 for _ in range(len(lst))]
    for i, l_i in enumerate(lst):
        # 消す
        if i == 0:
            dp[i][0] = l_i
        else:
            dp[i][0] = min(dp[i - 1]) + l_i
        # 消さない
        if i > 0:
            dp[i][1] = dp[i - 1][0]
    return min(dp[-1])


n, d = map(int, input().split())
a = list(map(int, input().split()))

count = Counter(a)

ans = 0
if d == 0:
    for c_i in count.values():
        ans += max(c_i - 1, 0)
else:
    groups = [list() for _ in range(d)]

    for i in range(max(a) + 1):
        g_i = i % d
        if i in count:
            groups[g_i].append(count[i])
        else:
            if groups[g_i]:
                ans += solve(groups[g_i])
                groups[g_i] = list()

    for g_i in groups:
        if g_i:
            ans += solve(g_i)

print(ans)
```

# E問題
https://atcoder.jp/contests/abc403/tasks/abc403_e

- **感想**
文字列を木に落とし込む方法があったのは覚えていたが、それの名前ややり方を思い出せなかった
試行錯誤したけどWAを積み重ねて終了

(追記) トライ木だった。もう忘れない
エンジニア必見！技術トレンドを追うためのおすすめ情報サイトまとめ

## はじめに
技術の進化スピードはすさまじく、エンジニアは日々新しい情報をアップデートしていくことが大切です。

本記事では、技術トレンドを追うために最適な日本国内の情報サイトや企業テックブログを厳選してまとめました！


# 1. ニュース系メディア

- [TechCrunch Japan](https://jp.techcrunch.com/)：スタートアップ・IT技術ニュース
- [ITmedia](https://www.itmedia.co.jp/)：日本全般のITニュース
- [CNET Japan](https://japan.cnet.com/)：テック系全般

# 2. 技術ブログ・個人発信

- [Qiita](https://qiita.com/)：日本語中心。短文技術記事が多数
- [Zenn](https://zenn.dev/)：深い技術解説記事

# 3. 企業公式テックブログ

## 日本のIT企業
- [LINEヤフー Tech Blog](https://techblog.lycorp.co.jp/ja)
- [サイボウズ エンジニアリングブログ](https://blog.cybozu.io/)
- [メルカリエンジニアリングブログ](https://engineering.mercari.com/blog/)
- [楽天技術研究所ブログ](https://tech.rakuten.co.jp/)
- [ラクス開発者ブログ](https://tech-blog.rakus.co.jp/)

## スタートアップ・注目企業
- [SmartHR エンジニアブログ](https://tech.smarthr.jp/)
- [クックパッド開発者ブログ](https://techlife.cookpad.com/)

## インフラ・SRE特化
- [はてなエンジニアブログ](https://developer.hatenastaff.com/)
- [サイバーエージェント アドテク本部 技術ブログ](https://developers.cyberagent.co.jp/blog/)
- [Yahoo! JAPAN Tech Blog（古）](https://techblog.yahoo.co.jp/)
- [LINE Engineering Blog（古）](https://engineering.linecorp.com/ja/blog/)


# おわりに

技術情報は、一つのサイトやブログにこだわらず、複数ソースを組み合わせて読むことが大切です。
自分に合った情報源を一つでも見つけ、日々のアップデート習慣を作っていきましょう！
UnityとVSCodeで開発していたら突如.code-workspaceが生えてデバッグできなくなる

# 結論
Visual Studio Editorというパッケージのバージョンを2.0.22以下に戻してください。

![スクリーンショット 2025-04-27 22.32.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44992/f5aa35e6-c66b-4704-8bc2-32de4a015c5d.png)

## 戻し方

`packages/manifest.json` を開き、以下のパッケージのバージョンを `2.0.22` に編集してください。

```json
"com.unity.ide.visualstudio": "2.0.22"
```

# 何が起きたか
ある日開発をしているとVSCode側でうまく開発作業ができなくなってしまいました。
具体的には、

- すでにエディタが開かれているのに新規ウィンドウで開こうとしてくる
- C#のコード補完が効かなくなる
- Unityデバッガーにアタッチできなくなる

といった現象が発生しました。

# 原因と調査

この原因を探っていくと辿りついたのがタイトルにもある`{プロジェクト名.code-workspace}`
というファイルが悪さをしていることがわかりました。

これはVSCodeのワークスペースを管理するファイルで、ざっくりいうと、このフォルダを起点に作業するよというのをVSCodeに教えるためのファイルです。
ここにVSCodeの設定を追加していけば、そのワークスペース内でのみ◯◯機能を有効にするみたいなことも可能になります。

ただこれが現状のUnity開発とあまり噛み合っていません。
1つ目の問題はワークスペースとして新規ウィンドウで開くため、以後ワークスペースとしてVSCodeを開いていれば問題ないのですが、
2つ目の補完が効かなくなるのは、そもそもこのフォルダをC#のプロジェクトだと認識していないことが原因となっています。なぜかというとソリューションファイル(.sln)がどこにあるかわからず、C#プロジェクトではなく単にフォルダを開いているだけという状態になってしまっているためです。
そして3つ目ですが、当然C#のプロジェクトとして認識していないためUnityのデバッガにもアタッチできないということが起きてしまいます。

これを回避するにはデフォルトで生成された.code-workspaceにUnity向けの設定を書くか、このファイルを消してしまえばOKです。
ただ私の環境では消せども消せどもworkspaceファイルが生え続けたため、Unity側で何か悪いことしているんじゃないかと調べた結果、結論のところに書いたパッケージの新バージョンでそのような実装をしたと記載がありました。

https://docs.unity3d.com/Packages/com.unity.ide.visualstudio@2.0/changelog/CHANGELOG.html#2023---2025-02-03

**Code Editor Package for Visual Studio**

> Try opening a Visual Studio Code workspace if there's one (.code-workspace file in the Unity project).

とあるのでどうやらこいつが原因のようです。



こいつが原因とわかったのであれば元のバージョンに戻すだけで良さそうです。戻し方は一番上の結論ページに記載しましたので、もし同じような症状が出た人は試してみてください。
【Linux基本設定】サーバーのコンソールの背景色を変更する

# 目的
検証環境と本番環境でコンソールの背景色を変えることで事故を防ぎたい

# Linux設定変更
## 全ユーザーに適用する(AmazonLinux)

AmazonLinuxはbashrcを.bash_profileに読み込ませるので
実はbashrcを書き換えないと共通設定にならない

```bash
vim /etc/bashrc
```

```bashrc
setterm -background red -foreground white -clear
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/28279506-91e9-431c-ad57-dbd64a1b415d.png)
↑成功

また、ログインした先の別のユーザーでも赤色で表示されることも確認できた
LINE Notifyの代替に！DiscordでMATLABのプログラム終了通知を受信する方法【Webhook活用】

# LINE Notifyの代替に！Discordで簡単プログラム終了通知【Webhook活用】

## はじめに

2024年末，LINE Notifyのサービス終了が発表されました． 
長い時間計算処理させる場合に終了通知やエラー発生の通知があると便利で，重宝していたのでサービス終了には困っていました...
どうにかできないかなと，色々調べたところDiscordのWebhookをLINE Notifyの代わりに使うことができそうだったので，それらを試した結果を記事としてまとめました．
この記事ではMATLABを使用していますが，Pythonなど他の言語にも応用できると思います．（余力があればPython版も追加します）

---

## 準備：DiscordのWebhook URLを取得する


1. Discordをダウンロードして使える状態にする
1. Discordで通知を送りたい「**チャンネル**」に移動
2. チャンネル名，横の `⚙️ 歯車マーク`「**チャンネル設定**」をクリック
3. 「**連携サービス**」→「**Webhookを作成**」
4. Webhookの名前を設定し「**Webhook URLをコピー**」

WebhookのURLを使ってMATLABなどから通知を送信できます.

---

## MATLABからDiscordにテスト通知を送るコード

以下がMATLABのコード例です．

```matlab
webhook_url = '準備5でコピーしたURL';

% ==== 通知メッセージ ====
msg = struct('content', 'MATLABからの通知テストです！');

% ==== HTTP Body（JSON形式） ====
body = matlab.net.http.MessageBody;
body.Data = msg;  % ここでは構造体のままでOK（自動でJSON化される）

% ==== ヘッダー ====
headers = matlab.net.http.HeaderField('Content-Type', 'application/json');

% ==== POSTリクエスト作成 ====
request = matlab.net.http.RequestMessage('POST', headers, body);

% ==== リクエスト送信 ====
response = request.send(webhook_url);

% ==== 結果表示 ====
disp("ステータスコード:");
disp(response.StatusCode);

disp("レスポンス:");
disp(response.Body.Data);

```
## MATLABからDiscordにループ処理の完了通知とエラーつうちを送るコード

ループ処理に組み込みたい場合は以下を参考に，適宜変更して使用してください．
```MATLAB

clc; 
clear; 
close all;

webhook_url = '';  % ここにあなたのWebhook URLを記入

% ==== 通知送信用関数（メッセージだけ渡す） ====
function sendDiscordNotify(message, webhook_url)
    msg = struct('content', message);
    body = matlab.net.http.MessageBody;
    body.Data = msg;
    headers = matlab.net.http.HeaderField('Content-Type', 'application/json');
    request = matlab.net.http.RequestMessage('POST', headers, body);
    response = request.send(webhook_url);
    disp("通知ステータス: " + string(response.StatusCode));
end

% ==== メイン処理 ====
try
    % 処理ループ（例: 1～5まで繰り返す）
    for i = 1:5
        disp("処理中: " + i);

        % i == 3でエラーを意図的に発生させる
        if i == 3
            error("処理中にエラーが発生しました: i = %d", i);
        end

        pause(1); 
    end

    % ==== 正常に完了したときの通知 ====
    sendDiscordNotify("MATLABの処理が正常に完了しました！", webhook_url);

catch ME
    % ==== エラーが発生したときの通知 ====
    errMsg = sprintf("エラー発生: %s", ME.message);
    sendDiscordNotify(errMsg, webhook_url);
end
```

何かのお役に立てばうれしいです．
間違いやわからないことありましたら，ご連絡ください！
コマンド実行

指定したコマンドを実行する。
~~~
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' コマンド実行
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Public Function F_Cmd_RunCommand( _
        ByVal aCmd As String, _
        Optional ByVal aWindowStyle As Long = 0, _
        Optional ByVal aWaitOnReturn As Boolean = False) As Boolean
    If aCmd = "" Then
        Exit Function
    End If
    
    F_Cmd_RunCommand = M_Shell.F_Shell_Run("%ComSpec% /c " & aCmd, aWindowStyle:=aWindowStyle, aWaitOnReturn:=aWaitOnReturn)
End Function
~~~
gsacaで接尾辞配列(suffix array)構築

接尾辞配列を線形時間で構築する[gsaca](https://github.com/waYne1337/gsaca)の紹介。特徴は再帰を利用しない事。しかし入力に対して約17倍もの記憶空間を消費します。
## 実装編
ただ実装するだけでは面白くないので、本家の不便な点を改良。何が不便かと言うと入力配列の末尾が0かつ、途中に0を含めてはいけない点です。ちなみにJavaScriptで記述
```js
/*
gsaca(S[,A,n,k])
@S: input(Array/Uint8Array/Uint16Array)
@A: output of suffixes(Array/Int32Array/Uint32Array). A size must be n+1 if A.constructor is TypedArray. if !A==true then process time is fast.
@n: S.length
@k: max symbol of S[0..n-1]. k:0-65535
@return: @A
*/
function gsaca(S,A,n,k){
	n=n||S.length;k=k&65535||255;
	var p=n++,P=new Uint32Array(n*3),ISA=P.subarray(n),GS=P.subarray(n*2),SA=A||new Uint32Array(n),a,b,c,i=0,j=-1,r,s=0,t,z=p;
	if(p<2)return p?SA[0]=0:0,SA;
	if(p<3)return SA[n=0|S[0]<S[1]]=1,SA[1-n]=0,SA;
	for(c=new Uint32Array(k+2<<1);i<p;)++c[S[i++]+1<<1|1];
	for(c[1]=1;s<n;)
		if(b=c[++j<<1|1])
			s+=GS[c[j<<1]=s]=b;
	for(SA[--c[1]]=i;i;SA[ISA[i]=--c[s+1]+a]=i)a=P[--i]=c[s=S[i]+1<<1];
	for(;z>0;z=b-1){
		for(GS[a=b=P[SA[i=c=z]]]=0;i>=a;P[s]=p)
			for(s=SA[i--],p=s-1>>>0;p<n;p=P[p])
				if((r=ISA[p])<=z){
					if(r>=a)GS[r]=1;
					break
				}
		for(i=j=a;i<=z;GS[i++]||(SA[j++]=s))ISA[s=SA[i]]=z;
		z=j;j=0;
		do{
			for(i=z-1,r=z;i>=a;)
				if(p=P[s=SA[i]],p<n)
					if(ISA[p]<b)SA[i--]=SA[--z],SA[z]=p;
					else--i,P[s]=P[p],P[p]=n;
				else SA[i]=SA[a++];
			if(z<r)GS[z]=r-z,++j
		}while(a<z);
		for(;j--;){
			for(i=z=a+GS[a];i>a;ISA[SA[r]=p]=r)
				r=P[p=SA[--i]],
				ISA[SA[t=ISA[p]]=SA[r+=--GS[r]]]=t;
			for(;i<z;P[p]=r+GS[r])r=P[p=SA[i++]];
			for(;a<z;)++GS[P[SA[a++]]]
		}SA[c]=b
	}
	for(SA[i=0]=n-1;i<n;)
		for(s=SA[i++]-1>>>0;s<n&&(r=ISA[s])^n;s=P[s])ISA[SA[SA[r]++]=s]=n;
	if(A){for(i=0;i<n;)A[i++]=A[i];return--A.length,A}
	return SA.subarray?SA.subarray(1):SA.slice(1)
}
```
```js:例
var S=[98,97,110,97,110,97];//構築元の配列
//Array版
var SA=[];gsaca(S,SA);
//TypedArray版
var SA=new Uint32Array(S.length+1);
gsaca(S,SA);SA=SA.subarray(0,S.length)
//TypedArray 簡易版
var SA=gsaca(S)
```
## 性能
かなり高速ですが[SAIS](http://wpage.cocolog-nifty.com/wp/2010/08/sais-241.html)程ではないかな…。
コマンド実行結果取得

# コマンド実行結果取得
指定したコマンドを実行し、実行結果を取得する。
DoEventsによる待ちは作成ツールにおいて基本デメリットにしかならないため実施しない。
## コマンド実行結果取得
~~~
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' コマンド実行結果取得
'++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
' コマンド実行結果取得
'------------------------------------------------------------------------------
Public Function F_Cmd_GetCommandResult( _
        ByRef aRtn As String, _
        ByVal aCmd As String) As Boolean
    Dim wkRtn As String
    
    '引数チェック
    If aCmd = "" Then
        Exit Function
    End If
    
    F_Cmd_GetCommandResult = M_Shell.F_Shell_GetResult(aRtn, "%ComSpec% /c " & aCmd)
End Function
~~~
## コマンド実行結果配列取得
~~~
'------------------------------------------------------------------------------
' コマンド実行結果配列取得
'------------------------------------------------------------------------------
Public Function F_Cmd_GetCommandResultArray( _
        ByRef aRtnAry As Variant, _
        ByVal aCmd As String) As Boolean
    Dim wkRtnAry As Variant
    Dim wkRtnStr As String
    
    Dim wkTmpAry As Variant, wkTmp As Variant
    Dim wkTmpAry2 As Variant, wkTmp2 As Variant
    
    'コマンドの結果がNGであれば終了
    If F_Cmd_GetCommandResult(wkRtnStr, aCmd) <> True Then
        Exit Function
    End If
    
    'CRLF区切りで分割
    If M_String.F_String_GetSplit(wkTmpAry, wkRtnStr, vbCrLf) = True Then
        For Each wkTmp In wkTmpAry
            '空行でなければ追加
            If wkTmp <> "" Then
                wkRtnAry = M_Common.F_ReturnArrayAdd(wkRtnAry, wkTmp)
            End If
        Next wkTmp
    End If
    
    If IsArray(wkRtnAry) = True Then
        aRtnAry = wkRtnAry
        F_Cmd_GetCommandResultArray = True
    End If
End Function
~~~
M_Cmd：各種定義

~~~
'##############################################################################
' コマンド処理
'##############################################################################
' 参照設定          |   Windows Script Host Object Model
'------------------------------------------------------------------------------
' 参照モジュール    |   M_String
'                   |   M_Shell
'------------------------------------------------------------------------------
' 共通バージョン    |   250504
'------------------------------------------------------------------------------

'==============================================================================
' 公開定義
'==============================================================================
' 定数定義
'------------------------------------------------------------------------------
Public Enum E_CMD_IDX_GREP_INF
    E_CMD_IDX_GREP_INF_NONE = D_IDX_START - 1
    E_CMD_IDX_GREP_INF_RESULT
    E_CMD_IDX_GREP_INF_FULLPATH
    E_CMD_IDX_GREP_INF_RLTPATH
    E_CMD_IDX_GREP_INF_FILE
    E_CMD_IDX_GREP_INF_LINE
    E_CMD_IDX_GREP_INF_OFFSET
    E_CMD_IDX_GREP_INF_SOURCE
    E_CMD_IDX_GREP_INF_MAX
    E_CMD_IDX_GREP_INF_EEND = E_CMD_IDX_GREP_INF_MAX - 1
End Enum

'------------------------------------------------------------------------------
' 構造体定義
'------------------------------------------------------------------------------
Public Type T_CMD_ARG_GREP_INF
    '検索文字列
    SrchPtn As String
    
    '単語チェック指定
    ChkWordFlg As Boolean
    ChkWordPtn As String
    ChkWordSpec As E_STRING_SPEC
    
    FullPath As String
    ExtSpec As String
End Type

'==============================================================================
' 内部定義
'==============================================================================
' 定数定義
'------------------------------------------------------------------------------
Private Enum PE_CMD_POS_GREPRET
    PE_CMD_POS_GREPRET_RLTPATH = 0
    PE_CMD_POS_GREPRET_LINE
    PE_CMD_POS_GREPRET_OFFSET
    PE_CMD_POS_GREPRET_SOURCE
    PE_CMD_POS_GREPRET_MAX
    PE_CMD_POS_GREPRET_EEND = PE_CMD_POS_GREPRET_MAX - 1
End Enum
~~~
Prisma応用ガイド - リレーションと最適化


## Prisma応用ガイド 

### 1. 複数テーブルのリレーション設計
例：UserとPost（ユーザーは複数の記事を持つ）
```prisma
model User {
  id    Int    @id @default(autoincrement())
  name  String
  posts Post[]
}

model Post {
  id      Int    @id @default(autoincrement())
  title   String
  content String
  userId  Int
  user    User   @relation(fields: [userId], references: [id])
}
```

### 2. リレーションのクエリ操作

- データ登録
```typescript
await prisma.user.create({
  data: {
    name: '田中一郎',
    posts: {
      create: [
        { title: '記事1', content: '内容1' },
        { title: '記事2', content: '内容2' },
      ],
    },
  },
});
```
- データ取得（リレーション込み）
```typescript
const users = await prisma.user.findMany({
  include: { posts: true },
});
```

### 3. パフォーマンス最適化：selectとincludeの違い
- `select` → 必要なフィールドだけ取りたい
- `include` → リレーションも含めたい
例：
```typescript
const user = await prisma.user.findUnique({
  where: { id: 1 },
  select: { name: true },
});
```

### 4. バルク操作（createMany, updateMany）
大量データ登録・更新も簡単
```typescript
await prisma.post.createMany({
  data: [
    { title: 'まとめ記事1', content: '概要1', userId: 1 },
    { title: 'まとめ記事2', content: '概要2', userId: 1 },
  ],
});
```

### 5. 複雑なフィルタリング
例：特定ユーザーの記事だけ取得
```typescript
const posts = await prisma.post.findMany({
  where: {
    user: {
      name: {
        contains: '田中',
      },
    },
  },
});
```

### 6. Prismaのベストプラクティス
- `prisma.$disconnect()` を忘れず使う（DB接続解放）
- モデル名は単数形推奨（User, Post）
- エラーハンドリングを入れる
- 必要ならPrisma Middleware（ロギングなど）



## Prismaマイグレーションの仕組み
1. Prismaのモデルを変更する
2. `npx prisma migrate dev --name xxx`でマイグレーション
3. **マイグレーション履歴がコードとして残る**

### 実際にできるもの
- `prisma/migrations/{タイムスタンプ名}/migration.sql`
  - 中身は**純粋なSQL**！
  - 手動編集も可能（ただし上級者向け）

### マイグレーションの流れまとめ
```
schema.prismaを編集
↓
migrate devでSQLファイル作成＋適用
↓
DBに反映
↓
履歴もGit管理できる
```

### 本番環境への適用
開発と本番では違うコマンドを使う
```bash
npx prisma migrate deploy
```
→ これは**すでに作ったマイグレーションSQLだけを本番DBに適用**するコマンド！

---

## パフォーマンス最適化Tips
- 必要なフィールドだけ取得する（`select`を使う）
- 可能なら`createMany`や`updateMany`で一括処理する
- Prisma Clientをアプリ内で使いまわして**コネクション数を抑える**
初心者によるJavascript１（変数と宣言）

これは初心者によるjs講座です。（ChatGPTと会話して作りました）
## 目的
・JavaScriptにおける変数と宣言の基本を理解すること
・変数はプログラムでデータを扱うために欠かせないことを紹介する
## まとめ（忙しい人向け）
・`変数`とは、データを保存するための`名前付きの箱`。

・変数を宣言するには、`var / let / const`を使う。

・`基本`は `const`、値を変えたいときだけ `let` を使う。

・`var`は再宣言できてしまうため、`バグのもと`になりやすいので基本使わない。

・変数には`スコープ`（使える範囲）があり、`let`と`const`はブロック単位、varは関数単位で管理される。
## そもそも変数とはなにか？
「変数」とはデータに名前をつけて保存する箱のようなもの。例を示すとすれば次の２つのたとえがわかりやすい。
#### １、箱のたとえ
プログラムはたくさんのデータ（数字や文字など）を扱う。しかし、ただデータを置いておくだけでは、どれがどれだかわからなくなってしまう。そこで「変数」という名前付きの箱を用意して、分類し、しまうことで簡単に管理したり取り出したりできるようになる。
#### 2、メモ帳のたとえ
プログラムは、何かを記憶しておく必要がある。例えば、計算結果を覚えて置いたり、ユーザーの名前を保存したりする場面だ。そんなとき、メモ帳に名前をつけてメモしておくようにプログラムでは「変数」をつかって情報を一時的に保存する。
## なぜ変数が必要か
前述の例でもしめしたように、データを再利用、または管理しやすくするためだ。
## 変数を宣言する方法
結論から言うと、`var`、`let`、`const`の三つがあり、
・`var`→歴史的に古く、注意点がある
・`let`→現在主流の変数宣言方法
・`const`→値を変更しない（定数）のための宣言方法
それぞれについて以下で解説する。
#### `var`を使った宣言
例
```js
var message = "こんにちは";
console.log(message); // 結果: こんにちは
```
`var`は古くから使われてきた宣言方法ではある。しかし、後述する`スコープ`の問題で現在はあまり使われていない。また同じ名前の変数を再定義できてしまうことからも忌避される
#### `let`を使った宣言
例
```js
let count = 5;
console.log(count); // 結果: 5
```
現在もっとも主流な宣言方法。あとから値を変更できるのが特徴。また`var`の`スコープの問題`や同じ名前の変数を再定義できてしまう問題も解消さている。

#### `const`を使った宣言
例
```js
const pi = 3.14;
console.log(pi); // 結果: 3.14
```
`const`は値を変更することができない変数を作るときに使う。一度値を代入すると基本的には変更できない。数値や文字列などのオブジェクト以外のデータを代入したときは定数になるが、オブジェクトそのものを宣言したときは違う。
例
```js
// `const`でオブジェクトを定義している
const object = {
    key: "値"
};
// オブジェクトそのものは変更できてしまう
object.key = "新しい値";
```
#### どの変数を使うべきか？
基本はまずは`const`で宣言して、「値を後から変えたい」ときだけ`let`を使うのが無難。`var`はなるべく使わないほうが安全。
#### なぜ`let`や`const`は追加されたのか
`const`や`let`を追加し、`var`の動作を変更しなかったのは後方互換性のためである。すなわち、`var`の動作を変更してしまうとすでに`var`で書かれたコードが動かなくなってしまうのを避けるためである。
## 変数名のルール
英数字、$、_ が使える。しかし、数字からはじめることや、予約語は使えない。意味のある名前をつけることも大切である。
#### 意味のある名前を付けよう→「変数名だけで何を表しているか伝わるようにしよう」

悪い例
```js
let a = 10;
let b = 20;
let c = a + b;
console.log(c);
```
なにを意味しているかわかりにくい。
良い例
```js
let price = 10;
let tax = 20;
let totalPrice = price + tax;
console.log(totalPrice);
```
価格と税金を足して「合計金額」を出しているとすぐにわかる！
## 変数のスコープとは
結論からいうと、スコープとは変数がつかえる範囲のことである。`var`と`let/const`のスコープは、それぞれ関数スコープ、ブロックスコープという違いがある。以下で詳しく解説する。
#### `var`のスコープ（関数のスコープ）
`var`で宣言した変数は関数の中だけで有効。関数外には影響しない。（関数外からはアクセスできない）
例
```js
function greet() {
  var message = "こんにちは";
  console.log(message); // 結果: こんにちは
}

greet();
console.log(message); // エラー！messageは関数の外では使えない
```
#### `let・const`のスコープ（ブロックスコープ）
letとconstで宣言した変数は、ブロック（{}で囲まれた範囲）内だけで有効。
これはif文やfor文の中も同じである。
例１
```js
{
  let color = "blue";
  console.log(color); // 結果: blue
}

console.log(color); // エラー！colorはブロックの外では使えない
```
例２
```js
if (true) {
  const number = 100;
  console.log(number); // 結果: 100
}

console.log(number); // エラー！numberはifの中だけで使える
```
#### ポイント
基本は`const/let`を使う。変数の「生きている範囲」を意識し、無駄に広いスコープを持たせないようにする。`var`は思わぬバグを生むのでできるだけ使わない。
## まとめ（再掲）
・`変数`とは、データを保存するための`名前付きの箱`。

・変数を宣言するには、`var / let / const`を使う。

・`基本`は `const`、値を変えたいときだけ `let` を使う。

・`var`は再宣言できてしまうため、`バグのもと`になりやすいので基本使わない。
## 参考

https://jsprimer.net/basic/variables/
【初心者向け】fastq-dlでFASTQをダウンロード

[備忘録]fastq-dlを使ってNCBIからメガデータをダウンロードする


# はじめに&今回の概要
こんにちは。
オミクス解析を使って軟体動物の研究をしている某大学院生です。
今回はNCBIのSRAからメタデータ (e.g. トランスクリプトーム) をダウンロードする方法を書き残します。＊主に自分用のメモです


# 手順
1. fastq-dlの入手
2. データダウンロード
2. 複数データを一括ダウンロード

# 用語
fastq-dlとは??
https://github.com/rpetit3/fastq-dl

# 1. fastq-dlの入手
condaを使ってインストールする。
minicondaもしくはanacondaをインストール後、下記のコマンドを実行
＊各サイト参照 

```sh:
conda create -n fastq-dl -c conda-forge -c bioconda fastq-dl
conda activate fastq-dl 
```


# 2. データダウンロード
```sh:
cd "xxx/yyy/path" #ダウンロード場所をpathしておく
fastq-dl --accession SRRxxxxx
```

# 2. 複数データを一括ダウンロード
以下の　"Download_List.txt"　と　"SRA_download.sh"　を作成し、ターミナルで　"まとめてダウンロード"　を実行する。

```text:Download_List.txt_ダウンロードするSRR番号をまとめてtextに保存
SRR00000
SRR00001
SRR00002
SRR00003
SRR00004
```
```sh:SRA_download.sh
cat Download_List.txt | 
while read SRR_ID
do
	cmd='fastq-dl --accession  ${SRR_ID}';
	eval ${cmd}
done

```

```sh:まとめてダウンロード
cd "xxx/yyy/path" #ダウンロード場所をpathしておく
sh SRA_download.sh

```
Prisma入門　ORM


## Prisma入門

### 1. Prismaとは？
- データベースとプログラムをつなぐORM（Object Relational Mapper）
- SQLを書く代わりにTypeScriptで直感的にデータ操作できる
- Prisma Client（使うもの）、Prisma Migrate（マイグレーション）、Prisma Studio（GUIツール）がある

### 2. セットアップ手順
- プロジェクト作成
- 必要パッケージインストール
  ```bash
  pnpm add @prisma/client
  pnpm add -D prisma
  ```
- Prisma初期化
  ```bash
  npx prisma init
  ```

### 3. モデルを作ろう（例：Userテーブル）
```prisma
model User {
  id    Int    @id @default(autoincrement())
  name  String
  email String @unique
}
```

### 4. マイグレーションでDBを作成
```bash
npx prisma migrate dev --name init
```

### 5. Prisma Clientでデータ操作
```typescript
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
  const user = await prisma.user.create({
    data: {
      name: '山田太郎',
      email: 'taro@example.com',
    },
  });
  console.log(user);
}

main();
```

### 6. Prisma StudioでGUI操作
```bash
npx prisma studio
```

### 7. まとめ
- Prismaを使うと型安全・直感的にDB操作できる
- マイグレーション管理も簡単
「突然のサブリーダー離任」を “バーチャル・サブリーダー” で乗り切った話

# 「突然のサブリーダー離任」を **“バーチャル・サブリーダー”** で乗り切った  
### ――SES現場・リアルケース
## 事件は突然に――“頼れるサブリーダー”の退場

SES 常駐プロジェクトでは **サブリーダー（SL）** がリーダー（PL）とメンバーの潤滑油。  
ところがある日、家庭事情で SL が急遽離任。

- **影響範囲**
  - タスク進捗確認・品質レビュー・顧客定例の議事録作成など SL 業務が真空
  - PL は複数現場を掛け持ち、フォローに割ける時間が限界
  - 若手は「誰に相談すれば？」と不安増大

属人化の怖さを痛感した瞬間でした。

---
##  解決アイデア：**「マネジメントチーム」＝バーチャル・サブリーダー**
### コンセプト比較
| 旧：1名 SL | 新：**マネジメントチーム** (3〜4名) |
| :-- | :-- |
| SL が多岐業務を担当 | ロール分担で共同遂行 |
| 属人化しやすい | 可視化・継承容易 |
| “抜けたら終わり” | 冗長構成で交代容易 |

> **狙い**：①属人化の解消　②育成機会の創出　③業務の標準化
### ロール設計
| ロール | 主な責務 | 週次稼働目安 |
| :-- | :-- | :-- |
| **タスクコーディネータ** | 進捗ボード更新・負荷調整 | 2 h |
| **品質アンバサダ** | PR レビュー・テスト観点洗い出し | 3 h |
| **コミュニケーションリーダー** | 顧客定例・議事録・FAQ 一次対応 | 1.5 h |
| **教育サポータ** | OJT 計画・ドキュメント整備 | 1.5 h |

> 兼任可。**ローテーション**運用で全員が全ロールを体験 → スキル拡張＆バックアップ性アップ。

---

## 実装ステップ

1. **緊急棚卸し (Day 1)**  
   サブリーダー業務を 90 分でブレスト 
2. **ロール割当 (Day 1)**  
   興味 × 得意 × 稼働を基準に 4 ロールをドラフト決定  
3. **運用ルール作成 (Day 2–3)**  
   チェックリスト＋依頼フロー自動化  
4. **試験運用 (Week 1)**  
   毎日 15 分夕会で引き継ぎ漏れを即時エスカレーション  
5. **レトロスペクティブ (Week 2)**  
   KPT 法で課題抽出 → ルールを 2 週間サイクルで磨き込み  
---

## 学びと再現のヒント

- **タスク単位で切り出せば「人」ではなく「仕組み」で回る**  
  → テンプレ＋自動化ツールが鍵
- **“やりたい人”を公募**すると自発的モチベーションが高い
- **ローテーション**で育成とリスクヘッジを同時実現
- **2 週間ごとに KPT** を回すと現場に馴染みやすい

---

## まとめ

サブリーダー不在はピンチ。  
しかし視点を変えれば――  

> **「1 人分の役割をチームで担い、属人化も育成も同時に解決するチャンス」**

“バーチャル・サブリーダー”＝マネジメントチームは、SES 特有の **現場分散・人材流動リスク** に効く新しいアプローチ。  
同じ悩みを抱える方は **ロール設計と運用ルールの型** をコピーし、自社プロジェクトにチューニングしてみてください！

---

> **「次の離任が怖くない組織」** を目指して、今日から一歩踏み出しましょう！