OmniAICreator/Qiita-1.07M huggingface dataset:
AnsibleでActiveDiretoryのユーザー、セキュリティグループを作成

# 概要
検証の都合で、Active Directoryに複数のユーザー、セキュリティグループを登録する必要がありました。
Ansibleを勉強中だったこともあり、Ansibleで実装してみました。

ユーザー、セキュリティグループの情報はCSVで定義しておき、playbookからはCSVを読み込んでloop処理で回す動きです。

## CSVサンプル（抜粋）
※値をマスクした関係で、正しくない設定になっている部分があります。
※ユーザー登録用のCSVです。

```
uid,name,sAMAccountName,UserPrincipalName,Path,Company,Surname,GivenName,DisplayName,mail,password,group1,group2
XX0000,名前,XX0000,XX0000@local.com,"OU=Dev_XX,DC=local,DC=com",XX,サンプル,サンプル,サンプル,XX0000@local.com,initialpassword,"CN=GitLab,OU=Dev_XX,DC=local,DC=com",
XX0001,名前,XX0001,XX0001@local.com,"OU=Dev_XX,DC=local,DC=com",XX,サンプル,サンプル,サンプル,XX0001@local.com,initialpassword,"CN=GitLab_Dev_XX,OU=Dev_XX,DC=local,DC=com",
XX0002,名前,XX0002,XX0002@local.com,"OU=Dev_XX,DC=local,DC=com",XX,サンプル,サンプル,サンプル,XX0002@local.com,initialpassword,"CN=GitLab_Lib_XX,OU=Dev_XX,DC=local,DC=com",
XX0003,名前,XX0003,XX0003@local.com,"OU=Dev_XX,DC=local,DC=com",XX,サンプル,サンプル,サンプル,XX0003@local.com,initialpassword,"CN=GitLab_Dev_XX,OU=Dev_XX,DC=local,DC=com",
XX0004,名前,XX0004,XX0004@local.com,"OU=Dev_XX,DC=local,DC=com",XX,サンプル,サンプル,サンプル,XX0004@local.com,initialpassword,"CN=GitLab_Dev_XX,OU=Dev_XX,DC=local,DC=com","CN=GitLab_Dev_XX,OU=Dev_XX,DC=local,DC=com"
XX0005,名前,XX0005,XX0005@local.com,"OU=Dev_XX,DC=local,DC=com",XX,サンプル,サンプル,サンプル,XX0005@local.com,initialpassword,"CN=GitLab_Dev_XX,OU=Dev_XX,DC=local,DC=com","CN=GitLab_Lib_XX,OU=Dev_XX,DC=local,DC=com"
```

## ユーザー登録用playbookサンプル
```
- name: create user from csv
  hosts: AD
  tasks:
  - name: read csv
    community.general.read_csv: 
      path: files/userList.csv
    register: users_list
    delegate_to: localhost  

  - name: create users
    microsoft.ad.user:
      identity: "{{ item.uid }}"
      name: "{{ item.name }}"
      firstname: "{{ item.GivenName }}"
      surname: "{{ item.Surname }}"
      password: "{{ item.password }}"
      password_never_expires: true
      display_name: "{{ item.DisplayName }}"
      email: "{{ item.mail }}"
      company: "{{ item.Company }}"
      upn: "{{ item.UserPrincipalName }}"
      sam_account_name: "{{ item.sAMAccountName }}"
      path: "{{ item.Path }}"
      groups:
        set:
          - Domain Users
          - "{{ item.group1 }}"
          - "{{ item.group2 }}"
      state: present
    loop: "{{ users_list.list }}"
```

## グループ作成用のplaybookサンプル

```
- name: create group from csv
  hosts: AD
  tasks:
  - name: read csv
    community.general.read_csv: 
      path: files/groupList.csv
    register: group_list
    delegate_to: localhost  

  - name: createt groups
    microsoft.ad.group:
      name: "{{ item.name }}"
      path: "{{ item.Path }}"
      scope: global
      state: present
    loop: "{{ group_list.list }}"
```
テーブル作る初期設定

```php:
動かすファイル名指定(プロジェクトフォルダがあるルートディレクトリで)
export FLASK_APP=run_sample.py

flask db init

flask db migrate -m "initial migration"

flask db upgrade
```

```php:インストされてる？
pip list flask-Migrate
```

### init.pyにこの設定ある？

```php:
migrate = Migrate()

def create_app(test_config=None):

    if test_config:
        app.config.from_mapping(test_config)

    # 初期化
    migrate.init_app(app, db)
    bcrypt.init_app(app)
    login_manager.init_app(app)
```

## route.pyにこの設定ある？

```php:
main = Blueprint('main', __name__)
```

隠しDBを見つけ、消す方法

```php:
find . -name "test.db"

rm -rf ファイル名
```
Raspberry Piでアプリをフルスクリーン実行 (Labwc)

この手の話題、色々なところでいろんな方法でできるとかできないとか書かれているけど、ボクはこの方法でできた。

## 前提条件
- 現時点 (2025/5/28) で最新のRaspberry Pi OS
- Labwcを使う (raspi-configのAdvanced Optionsから)
- アプリ側が全画面で実行できるようになっている

## アプリをJUCE + Projucerで作ってる場合
```JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP=1```をPreprocessor Definitionsに書いてStandAloneAppを自分で作る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107818/5bd7387c-1867-4e60-96b7-a06eea00b0bb.png)

その自前のStandAloneAppクラスの中で```Desktop::getInstance().setKioskModeComponent()```でフルスクリーン化する。

```MyStandAloneApp.cpp
void MyStandAloneApp::initialise (const String&)
{
    //  In this method, an instance of AudioProcessor is created, initialized, and setStateInformation() is called.
    mainWindow.reset (createWindow());

    // これは関係ないかも。やったとしても左上にいるっぽい。Windowsサイズに合わせてComponentのサイズもリサイズすべき
    mainWindow->centreWithSize(mainWindow->getWidth(), mainWindow->getHeight());

    mainWindow->setVisible (true);
#if JUCE_LINUX
    Desktop::getInstance().setKioskModeComponent(mainWindow.get(), false);
#endif
}
```
これで手動起動でフルスクリーンになることを確認。


## Labwc の autostart と rc.xml
設定用のディレクトリを作成。
```shell
mkdir -p ~/.config/labwc
```
autostart という名前で下記のファイルを作成。
```shell
#!/bin/sh
# Labwc 起動後に実行するアプリ
# 必要に応じて１秒ほど待ってから起動すると安定する
sleep 1
/path/to/MyApp &
```

さらにrc.xmlというファイルを作成。
```rc.xml
<?xml version="1.0"?>
<labwc_config>
  <windowRules>
    <!--
      identifier は Wayland ネイティブなら app_id、
      XWayland なら WM_CLASS のトリミング後の文字列
      （自分のアプリ名に合わせて書き換える）
    -->
    <windowRule identifier="MyApp" event="onMap">
      <!-- フルスクリーン化 -->
      <action name="ToggleFullscreen"/>
      <!-- タイトルバーなど装飾を完全にオフ -->
      <action name="ToggleDecorations" decorations="none"/>
    </windowRule>
  </windowRules>
</labwc_config>
```
このrc.xmlの中に```<action name="HideCursor"/>```を追加するとカーソルが消える…と思っても消えなかった。


## マウスカーソルを隠す
```shell
sudo apt-get install unclutter-xfixes

# ~/.config/labwc/autostart に下記を記述
unclutter-xfixes --hide-on-touch &
```
アプリの起動と合わせると
```shell
#!/bin/sh
# Labwc 起動後に実行するアプリ
# 必要に応じて数秒ほど待ってから起動すると安定する。早すぎるとフルスクリーンんにならない様子。
sleep 5
unclutter-xfixes --hide-on-touch &
/path/to/MyApp &
```
【AArch64アセンブリ】ファイルを開き内容を出力し閉じるプログラム【Linuxシステムコール】

筆者は、こういうのをやろうと思った。

```c:foo.c
#include <fcntl.h>
#include <unistd.h>

int main(int argc, char **argv) {
   if (argc < 2) {
      static char  msg[] = "Usage: $0 FILE\n";
      write(2, msg, sizeof(msg)-1);
      return 1;
   }

   int myfd = openat(AT_FDCWD, argv[1], O_RDONLY);
   if (myfd < 0) {
      static char msg[] = "Could not open\n";
      write(2, msg, sizeof(msg)-1);
      return 1;
   }

   char buf[4096];
   ssize_t n = read(myfd, buf, sizeof(buf));
   if (n<0) {
      static char msg[] = "Read error\n";
      write(2, msg, sizeof(msg)-1);
   } else {
      write(1, buf, n);
      if (n > 0 && buf[n-1] != '\n') write(1, "\n", 1);
   }

   if (close(myfd) < 0) {
      char msg[] = "Close error\n";
      write(2, msg, sizeof(msg)-1);
   }
}
```

なんでかって？暇だからである。

筆者は適当にいろいろと調べた。その結果、次に示すことが分かった。

* AArch64などLinuxカーネルにおいて新しく実装されたアーキテクチャのものは新しいシステムコールに統一されたこと
* openシステムコールはなくopenatを使うように求められてること
* read、openat、closeのシステムコール番号はそれぞれ63、56、57であること

## 書いた
```assembly:foo.s
.data
.L.errorUsage.msg:.ascii "Usage: $0 FILE\n"
.L.errorUsage.msg.len = . - .L.errorUsage.msg
.L.errorOpenFile.msg: .ascii "Open error\n"
.L.errorOpenFile.msg.len = . - .L.errorOpenFile.msg
.L.warnReadError.msg: .ascii "Read error\n"
.L.warnReadError.msg.len = . - .L.warnReadError.msg
.L.warnWriteError.msg: .ascii "Write error\n"
.L.warnWriteError.msg.len = . - .L.warnWriteError.msg
.L.warnCloseError.msg: .ascii "Close error\n"
.L.warnCloseError.msg.len = . - .L.warnCloseError.msg

.L.buf: .ds.b 4096
.L.buf.len = . - .L.buf

.text
.globl _start
_start:
ldr x0,[sp]
cmp x0,2
b.lt .L.errorUsage

mov x0,-100
//
// argc: i32, argv: [*:0][*:0]const u8
ldr x1,[sp,16]
mov x2,xzr
//
// openat
mov x8,56
svc 0
tbnz w0,31,.L.errorOpenFile
mov x19,x0
// x19 = myfd

// x0 = myfd
ldr x1,=.L.buf
ldr x2,=.L.buf.len
mov x8,63
svc 0
mov x20,x0
// x20 = retval of read()
tbz w0,31,.L.myfdOk
bl .L.warnReadError
b .L.writeOk

.L.myfdOk:
mov x0,1
ldr x1,=.L.buf
mov x2,x20
mov x8,64
svc 0
tbz w0,31,.L.writeOk
bl .L.warnWriteError

.L.writeOk:
mov x0,x19
// close
mov x8,57
svc 0
tbz w0,31,.L.finally
bl .L.warnCloseError

.L.finally:
mov x0,0
.L.exit:
mov x8,93
svc 0

.L.errorUsage:
mov x0,2
ldr x1,=.L.errorUsage.msg
ldr x2,=.L.errorUsage.msg.len
.L.error:
mov x8,64
svc 0
mov x0,1
b .L.exit

.L.errorOpenFile:
mov x0,2
ldr x1,=.L.errorOpenFile.msg
ldr x2,=.L.errorOpenFile.msg.len
b .L.error

.L.warnReadError:
ldr x1,=.L.warnReadError.msg
ldr x2,=.L.warnReadError.msg.len
.L.warn:
mov x0,2
mov x8,64
svc 0
ret

.L.warnWriteError:
ldr x1,=.L.warnWriteError.msg
ldr x2,=.L.warnWriteError.msg.len
b .L.warn

.L.warnCloseError:
ldr x1,=.L.warnCloseError.msg
ldr x2,=.L.warnCloseError.msg.len
b .L.warn
```

## 書いた感想
デバッグは少し大変だった。
識別子の名付け方は便利になるようにした。

コードゴルフをやってるつもりはないが、次のコード

```
ldr x1,=.L.buf
```

するだけでなんかファイルサイズ増えたもんだと思った。何故ならtext領域に該当のアドレスを後置して埋め込むからだ。正直言って直接埋め込められるんだったら埋め込めることができたら良いのにとは思う。まあ無理ではないか。
写真バリエーションの定量的評価

## 背景
記事執筆現在スクールフォトの業界にいて、販売する写真の売上を評価するにあたり、1イベントあたりの写真のバリエーションが購買決定要因になりうるのか検討するのになにか定量的な評価はできないものかと思い、以下の方法を思いつきました。本題的には、結論から言うと写真のバリエーションと売上には相関関係はなかったことを先にお伝えしておきます。

## 実行環境
- macOS Ventura Ver.13.6.1
- Python 3.12.2
- Pandas 2.2.2

## 評価方法の流れ
1. inputフォルダ直下の写真（ファイル）一覧を取得する。
1. 計算結果を格納する用の入れ物（Pandas DataFrame）を用意する。
1. 事前学習済みの画像キャプション生成機械学習モデルを利用して、写真のキャプションを生成する。
1. 2画像の組み合わせについて、キャプションの類似度を計測する。
1. キャプションの類似度を総合評価する。
以上の流れで進めていきます。

## コード
### inputフォルダ直下の写真（ファイル）一覧を取得する。
```.py
import os

dir_path = "input"
files = os.listdir(dir_path)
files = sorted(files)
#画像ファイルの拡張子リスト
img_exts = ['.jpg', '.jpeg', '.png', '.bmp', '.gif']
#読み込むファイルを上の拡張子リストにあるものに厳選する
files = [f for f in os.listdir(dir_path) if os.path.isfile(os.path.join(dir_path, f)) and os.path.splitext(f)[1].lower() in img_exts]
```
実行環境がmacなので、macOSが自動的に生成する隠しファイルで、ディレクトリの表示設定（アイコンの位置、表示形式など）を保存するために使用される「.DS_Store」ファイルが紛れ込まないように弾いておきます。
Jupyter Notebookで実行している場合には、さらに「.ipynb_checkpoints」ファイルが紛れ込む可能性がありますのでご注意ください。

### 計算結果を格納する用の入れ物（Pandas DataFrame）を用意する。
```.py
import pandas as pd

columns = files
b = "caption"
columns = columns + [b]
index_list = files
df = pd.DataFrame(columns = columns,index = index_list)
```
九九の表を思い浮かべてください。交差する升にキャプションの類似度を、一番右にキャプション（str）を格納しておく列を作成するイメージです。

### 事前学習済の画像キャプション生成機械学習モデルを利用して、写真のキャプションを生成する。
```.py
from transformers import BlipProcessor, BlipForConditionalGeneration
from PIL import Image
import requests
import torch
import os


#プロセッサとモデルの読み込み
processor = BlipProcessor.from_pretrained("Salesforce/blip-image-captioning-base", use_fast=True)
model = BlipForConditionalGeneration.from_pretrained("Salesforce/blip-image-captioning-base")

for f in files:
    image_path = os.path.join(dir_path, f)
    image = Image.open(image_path).convert('RGB')
    #キャプション生成
    inputs = processor(images=image, return_tensors="pt")
    out = model.generate(**inputs)
    caption = processor.decode(out[0], skip_special_tokens=True)
    df.at[f, 'caption'] = caption
    #以下のprintはお好みで。
    print("Generated Caption:",str(f),caption)
```
キャプションの生成には結構時間が掛かるので、tqdmをforループに組み込んでプログレスバーを表示させると待ち時間のストレスを緩和できます。

### 2画像の組み合わせについて、キャプションの類似度を計測する。
```.py
import Levenshtein

captions = []
[captions.append(df.loc[i,'caption']) for i in files]
for i in tqdm(range(len(files))):
    for j in range(i+1,len(files)):
        distance = Levenshtein.distance(captions[i],captions[j])
        similarity = 1 - distance / max(len(captions[i]),len(captions[j]))
        df.iat[i, j] = similarity
```
![スクリーンショット 2025-05-28 11.49.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263048/cebb1e10-6973-4750-a269-1c49075db28a.png)
DataFrameの見た目は以上の画像のようになります。

### キャプションの類似度を総合評価する。
```.py
n = len(files)
full = n * (n + 1) / 2 - n
col_sum = df.sum(axis=0)
sum = 0
for i in range(len(col_sum)-1):
    sum += col_sum.iloc[i]
sum = sum - n
#スコアを正規化
p = (full - sum) / full * 100
print(round(p,2))
```
similarityは1.0に近いほどcaptionの文字列が類似していることを示すので、バリエーションはその逆であるところがミソです。写真が類似していなければsimilarityは0に近づくので、そうすると最終的なスコアであるpが大きな値を取ります。pは1~100までの値で正規化されるので、ことなる写真セット同士の比較をするのに有用です。
Microsoftを使って ログイン認証 route.py

```php:route.py
@main.route("/ms_login")
def ms_login():
    session["state"] = str(uuid.uuid4())
    auth_url = _build_msal_app().get_authorization_request_url(
        SCOPE,
        state=session["state"],
        redirect_uri=url_for("main.ms_authorized", _external=True)
    )
    return redirect(auth_url)

@main.route(REDIRECT_PATH)
def ms_authorized():
    if request.args.get("state") != session.get("state"):
        return redirect(url_for("main.index"))

    if "error" in request.args:
        return f"エラー: {request.args['error_description']}"

    if "code" in request.args:
        result = _build_msal_app().acquire_token_by_authorization_code(
            request.args["code"],
            scopes=SCOPE,
            redirect_uri=url_for("main.ms_authorized", _external=True)
        )
        if "id_token_claims" in result:
            session["user"] = {
                "name": result["id_token_claims"].get("name"),
                "email": result["id_token_claims"].get("preferred_username")
            }
            return redirect(url_for("main.index"))

    return "Microsoftログイン失敗"

@main.route("/ms_logout")
def ms_logout():
    session.clear()
    return redirect(url_for("main.index"))

def _build_msal_app():
    return msal.ConfidentialClientApplication(
        CLIENT_ID, authority=AUTHORITY, client_credential=CLIENT_SECRET
    )
```

## init.py

```php:
import msal
import uuid

client_id="あなたのクライアントID",
    client_secret="あなたのクライアントシークレット",
    AUTHORITY = "https://login.microsoftonline.com/common"
    scope=["User.Read"],
    redirect_url="/ms_authorized"
```

```php:html
<a href="{{ url_for('main.ms_login') }}">Microsoftでログイン</a>
```
ChatGPT で Microsoft Edge の拡張機能を作った

## Qiita で特定のユーザーのコメントを非表示にする機能
こちらの記事で公開されている拡張機能を、Chromeで使用してみましたが、自分の使用手順の問題なのか、開発されてからページの構成が変わったためなのかわかりませんが、動きませんでした。開発者の方、記事がきっかけになりました。ありがとうございます。

https://qiita.com/standard-software/items/7ee380f86c2816d4f263

## 作り方を ChatGPT に聞いた
何度もエラーが出て修正しましたが、結論のみを記録します。ここからは、Microsoft Edge を使用しています。
### 手順
1. Tampermonkey をインストールする
1. Tampermonkey で、コメントを非表示にするスクリプトを記述して、上書き保存（ctrl + S）する
### 1. Tampermonkey のインストール
Edgeブラウザを開き、アドレスバーに以下を入力してEnter
```
edge://extensions/
```
ページ右下にある「Microsoft Edge アドオンを検索」というリンクをクリック

または、直接 Microsoft アドオンストア https://microsoftedge.microsoft.com/addons/Microsoft-Edge-Extensions-Home へアクセスする

アドオンストアの検索ボックスに、Tampermonkey と入力して検索する

Tampermonkey をインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/35c4a442-9437-49cf-bc18-b8c7389e414f.png)

### 2-1. コメントを非表示にするスクリプトを記述
ブラウザのメニューから、「拡張機能」をクリックして、Tampermonkey をクリック、「ダッシュボード」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/2dcdba24-d838-43a7-8953-2b57c9d88230.png)
「+」マークをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/236ce311-6dcd-4d2c-9173-ce44011c83fa.png)
エディターに最初から記述されているテンプレートを削除
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/2b444977-a16e-480b-b898-a82ed082196e.png)

次のコードをペーストして、上書き保存する
```
// ==UserScript==
// @name         Qiita コメントブロック（動的監視強化版）
// @namespace    http://tampermonkey.net/
// @version      1.9
// @description  指定ユーザーのQiitaコメントを非表示にする（動的監視）
// @match        https://qiita.com/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    const blockedUsers = ['ユーザー名'];
    const HIDE_CLASS = 'blocked-comment';

    const hideBlockedComments = () => {
        const commentSections = document.querySelectorAll('section[id^="comment-"]');
        console.log('検出されたコメント数:', commentSections.length);

        commentSections.forEach(section => {
            if (section.classList.contains(HIDE_CLASS)) return; // 既に処理済みならスキップ

            const userLink = section.querySelector('a[href^="/"]');
            if (!userLink) return;

            const href = userLink.getAttribute('href');
            const username = href.replace('/', '').split('?')[0];

            console.log('検出ユーザー:', username);

            if (blockedUsers.includes(username)) {
                section.style.display = 'none';
                section.classList.add(HIDE_CLASS);
                console.log('コメントを非表示にしました:', username);
            }
        });
    };

    // 500ミリ秒ごとに監視
    setInterval(hideBlockedComments, 500);
})();
```
const blockedUsers = ['ユーザー名']; の、ユーザー名に@は不要

拡張機能を有効にして、ページをリロードする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/ca574e9b-0c9f-4cc6-b4bd-e0d1ddb03fc7.png)

### 2-2. 非表示にしたいアカウントが複数ある場合
ユーザー名をカンマで区切って追加する
```
const blockedUsers = ['username1', 'username2', 'username3'];
```
ほぼ確実に不正が起きるリリース作業の共通点。

その日は、リモート作業でクラウド環境の構築作業がありました。作業者とチェッカーで行なわれるその作業は、手順書にかかれたとおりにするだけです。

<br>

「このプロジェクト、ちょっと炎上ぎみなんだよな…」

私はプロジェクトのメンバーではなかったのですが、構築担当者が体調を崩してしまったため、急きょチェッカーとして作業に参加することになりました。

<br>

作業内容は、そんなに難しいものではありません。製品のインストーラをポチポチするだけなので、とくに問題なくすすみます。

しかし、それは作業後半に起こりました。

<br>

作業者が「あ…」と声をあげます。

モニターには手順書にかかれていない設定画面。

作業者の手は止まっていました。

<br>


「この画面、手順書にないね。なんの設定か心あたりある？」

「……。いえ、この画面、はじめてみました。」

「カスタム設定の画面かな。デフォルトはオフか。今回の構築には影響のない設定にみえるけど。」

「…そうですね。」

「検証時には出なかった画面？」

「あ……えと、検証はやったのですが、その……検証環境が完全にお客様環境を再現したものではなくって、大丈夫だと思ってたのですが……」

<br>

作業者の声がどんどん小さくなっていきます。

画面は「次へ」をクリックしないと先にすすめないタイプの画面。つまり、チェックをはずしたままにするか、チェックをいれるのか、どちらか決めないといけません。

<br>

「あまり重要な設定値じゃなさそうですし…このまま…」

（まぁ、このプロジェクトの状況は聞いている。スケジュール的には、もうやりなおす余裕なんてないよなぁ。）

「……。いや、とりあえず上に相談しよう。あと、お客さんにも状況を伝えよう。」

「…そうですね、わかりました。」

<br>

相談の結果は非常にシンプルなものでした。デフォルトがオフのカスタム設定ということで、「オフのまま先にすすんでもよい」と、お客様から言っていただけたのです。

その後は、手順書どおりにすすみ、構築作業は完了しました。

<br>

「これで終わりかな」

「はい！終わりです！よかったです！」

<br>

作業者の安心した顔をみて、そのときは <b>"あの知らない設定画面"</b> のことはすっかり忘れてしまっていました。

しかし、ふとした瞬間に、思いだすワケです。

「もし、あの場面。私もプロジェクトのメンバーで、私が作業者だったら、相談せずにオフのまま先に進んでたかもな。」

<br>

# 強烈な不安で人をドライブさせると、ほぼ確実に不正が起きる
このセクション名は、パクリです。

以下の記事からそのまま引用させていただきました。

https://blog.tinect.jp/?p=71732

<br>

この記事には、「リーダーが不安をあたえることでマネジメントするタイプの場合、組織の心理的安全性が著しく損なわれる。」といった内容のことがかかれています。

<br>

記事内の事例も、そのようなものです。

例えば、フォルクスワーゲンの不祥事。排ガスが基準に適合するように数値を捏造した。原因は、排ガス規制をパスさせろとの、上からの強い圧力によるものだったとされている。

例えば、「かんぽ生命」の不正販売。ここでも「ノルマに追い詰められて」という話が出てくる。不正販売の背景には、過大なノルマや数字第一主義の組織文化があった。

<br>

───で、このセクション名をみたときに、私は「不安の原因はこんなようなあきらかな圧力だけじゃないよな」と思ったわけです。

<br>

- 作業者の経験が少ない
- プロジェクトの納期が近い
- いつも助けてくれる先輩が不在


こんなネガティブな要素もそうですが、

<br>

- 責任感が人一倍つよい
- 上司から期待されている
- 人にいいところを見せたい。


ポジティブな要素でさえ、不安のタネになるよなと思ったわけです。

<br>

冒頭の構築作業では、プロジェクトの納期が近かったことと、作業者の責任感がつよかったこと、そして「不完全な作業手順書」が不安要素だったでしょうか。

<br>

私は、「検証環境が完全にお客様環境を再現したものじゃなくて…」と言った作業者の、<b>不安が的中してしまったような</b>、絶望した顔をわすれられません。

あと付けになってしまいますが、「”作業内容は製品の設定画面をポチポチするだけ”なのに、どこか不安そうに見えたのはそういうことだったのか。」と思ったりしたわけです。

きっと、さまざまな不安を抱えながら作業をしていたのでしょう。

<br>

そういう体験をした私は、若手には構築手順書の作成に時間をかけるようにいっています。私が指示をだせるときは、かならずふたりで手順書のランスルーをし、そのふたりで本番作業にあたるようにいいます。

せめて、「この手順書で絶対に大丈夫。」と、作業者とチェッカーのふたりが自信をもって作業ができるようにしてあげたいのです。

<br>
<br>

以上です。
AWSを使ってRAG構築してみた！　【概要】

## 背景
会社でRAGシステムの導入を検討中。
Azureを使って構築予定だが、RAGに詳しくない上にAzureにも詳しくない…
→一旦AWSで作ってみよう！
という背景になります。

## ユーザのフロー概要
①参照したいドキュメントをアップロード
②画面から質問
③裏処理でドキュメントを参照、回答を返す

 
## ①ベクトル化処理

ドキュメントをS3にアップロード（/uploadフォルダ）

→アップロード検知でLambdaキック、parse処理、jsonに変換してS3にアップロード（/parsed）

→アップロード検知でLambdaキック、ベクトル化、OpenSearchへ取り込み（モデルはBedrodckのものを利用）

 

## ②API呼び出し

httpsでPOST処理呼び出し

→API Gatewayで検知、Lambda呼び出し

→Lambda内部でベクトル検索、Bedrockで回答生成、返却

→回答返却

 

## ③画面呼び出し

ユーザがWeb画面から入力

→バックエンド処理でAPI Gatewayへアクセス（POST）

※画面についてはDjangoで実装予定
【rails】minitestをデフォルトで作成する設定


## はじめに

こんにちは。アメリカ在住で独学エンジニアを目指している Taira です。

現在 Rails アプリを作成しているのですが、私が今まで学習してきたテストは minitest なのに Rails8 を使用しているとデフォルトで RSpec のテストが生成されてしまいます。

今回は、**Rails で Minitest をデフォルトのテストフレームワークとして設定する方法**についてまとめます。

---

## 設定方法

`config/application.rb`に下記のコードを追加することで、Minitest をデフォルトのテストフレームワークとして generator に設定できます。

```ruby
module YourAppName
  class Application < Rails::Application
    # ... 省略 ...

    config.generators do |g|
      g.test_framework :minitest, spec: false
    end
  end
end
```

- `g.test_framework :minitest` : テストフレームワークとして Minitest を指定
- `spec: false` : スペック形式ではなく、標準のテスト形式（`test/`配下の`*_test.rb`ファイル）が生成される

---

## テスト生成方法

サインアップのインテグレーションテストを生成したい場合

```bash
bin/rails generate integration_test users_signup
```

上記コマンドを実行すると、test/integration/users_signup_test.rb が生成されます。

```ruby
require "test_helper"

class UsersSignupTest < ActionDispatch::IntegrationTest

end
```

---

## まとめ

- Rails でデフォルトのテストフレームワークを Minitest にするには`config/application.rb`で generator の設定を明示する
- `spec: false`で標準形式、`spec: true`で spec 形式が選べる
- チームやプロジェクトの方針に合わせて柔軟にカスタマイズ可能
Database ManagementによるOracle Databaseのパフォーマンス監視 実践編③

[前回](https://qiita.com/Western24/items/d2159a7fb9ddf4072726)はADDMを使用したパフォーマンス分析の手順を紹介しました。Database Managementには、それ以外にもGUIでパフォーマンス監視するための便利な機能があります。その代表的なものを最後にいくつかご紹介します。

## ブロックしているセッションの検出
意図的にブロックしているセッションを作成する

```
##SOEスキーマで接続
sqlplus soe/パスワード@ホスト名:ポート/サービス名

CREATE TABLE test_tbl (
  id NUMBER PRIMARY KEY,
  value VARCHAR2(100)
);
INSERT INTO test_tbl VALUES (1, 'dummy');
COMMIT;

UPDATE test_tbl SET value = 'session A' WHERE id = 1;

新しいターミナルを開き、下記を実行
UPDATE test_tbl SET value = 'session B' WHERE id = 1;
```
- パフォーマンス・ハブのブロックしているセッションを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/f358f7fb-1ccc-47fb-9bd1-5e7836938583.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/c7b3a286-4729-452b-9c93-18ca6bdb3bb1.png)

- セッションの遮断を実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/ae67b009-6741-4848-8778-7049ce4335f1.png)

- セッションの検索からでも検索可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/6e3f9abe-efb0-491c-bd03-d49ad2983c5a.png)

## AWRエクスプローラ
AWRエクスプローラは、取得されているAWRスナップショットの時間範囲内で自由に指定して、時系列に情報をサマリーしてくれる
- ロードプロファイル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/204368b0-d9f7-44fb-ab1d-8713cf33e022.png)
- メトリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/8e2f54ef-ee73-48d5-9dbe-4df3a50894e9.png)
- 待機イベント
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/e157cbae-2acb-44fa-a305-d4a063c8f3a5.png)
- アクティビティ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/f91e3365-d0d6-418b-a4fa-78cad766d390.png)
- SQL IDをクリックするとSQLヘルスチェック・レポートを出力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/8ff193b4-92d0-4ca2-8ae5-ae008aa5e62c.png)
- AWRエクスプローラからAWRレポートの作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/9a76a05b-c9f2-47b4-84f6-95ab8c917e9d.png)

- 出力されたAWRレポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/562423/d0061ec8-49fc-4b04-8858-99d4ba8b5fc8.png)

上記以外にも様々な監視機能があります。最近では、データベースの脆弱性検出やパッチ管理の機能が新しく追加されました。詳しくは、[こちら](https://speakerdeck.com/oracle4engineer/oci-database-management)のサービス詳細資料をご確認下さい。

Database Managementは、他のO&Mのサービスと比較しても新機能のリリースが早く、今後Enterprise Managerの様々な監視機能を取り込んでいく予定です。EMよりも手軽に使えるクラウド版として、益々利用ケースが増えていくのではないかと思っています。
Tableau Agent(AI)のご紹介

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/9597a215-89ea-411d-a322-c4d9e98cfacc.png)
### Tableau 2.0 へようこそ
2025年5月27日(火) @ 虎ノ門ヒルズフォーラム

参加してまいりました。下記のWSは人気過ぎ、抽選制になっていましたが、キャンセル待ちで無事入室することが出来ました！

[WS3-1]基礎：データ分析は難しくない！Tableauで始めるシンプルなデータ活用
[WS3-2]Pulse/Agent：Tableau×AIで日々の業務をスマートに！
[WS3-3]基礎：データ分析は難しくない！Tableauで始めるシンプルなデータ活用
[WS3-4]Pulse/Agent：Tableau×AIで日々の業務をスマートに！

### Tableau Agentについて
本記事はTableau Agentに関する簡単な紹介です。
![1Agent.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/bb4beffb-2ee2-4346-8f67-61c76937ae57.jpeg)

* 製品ラインナップ（Tableau AIの位置付け）
![2位置付け.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/216c6a4d-c460-4c47-8430-ae60ddfebd8c.jpeg)

* Tableau AIの技術アーキテクチャ
![3アーキテクチャー.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/e412fc90-55cc-42f0-8a03-4828d0c77b7a.jpeg)

* Tableau Cloudのライセンス
![4ライセンス.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/410a09c8-13ef-4e2a-bff2-f8c42e609b8a.jpeg)

* Tableau ユーザーライセンス別のAI機能比較
![5機能.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/a2c6f0d9-3698-4757-8447-08712a76c0cd.jpeg)

### デモ

* データソースのご紹介：
Tableau デモでよく使用されるデータ。注文データで、カテゴリ、サブカテゴリ、都道府県、売上、利益などの項目がリストアップされています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/b740c6ba-875f-4a48-8d3d-66855ac9ce03.png)


Tableau Agentに使用されているデータソースは以下のファイルと似ていると思われ、ご紹介次第です。Tableau Desktopインストール後に、"C:\Users\...\Documents\マイ Tableau リポジトリ\データ ソース\2025.1\ja_JP-Japan\サンプル - スーパーストア.xls"のファイルをご確認できます。


* Tableau Agentへの指示
使用した文言：カテゴリとサブカテゴリごとの売上を売上の大きい順に、利益に色を付けて表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/189223a6-13b1-4f71-b69a-bfe129ffedda.png)

* Tableau Agentは処理中
本ケースの場合は約16秒
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/17d78a5f-1529-4a4c-b1b9-2d757734fd7a.png)

* 作成されたChart
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/afc40b33-f8f0-435e-a10e-823b35670db1.png)

約16秒で3DのChartがTableau Agentによって作られました！いかがでしょうか？Salesforce関連製品も今後Agentを積極的に投入すると推測でき、作業効率はますます向上できるでしょう！

補足：本文中の3Dについて：
* 1D（行）：カテゴリとサブカテゴリ
* 2D（列）：売上
* 3D（色）：利益
売上の大きい商品は、一律利益大きい訳ではないことを確認できます。
例：カテゴリ：家具、サブカテゴリ：テーブル


### おわりに
右側のビルは本イベント会場、虎ノ門ヒルズフォーラムの所在ビル、虎ノ門ヒルズ森タワーです。
![7会場.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1129251/bf974688-e966-4254-9bd7-498c624ac501.jpeg)
🛴ループ処理まとめ🔁❷ ー .eachメソッド

# Ruby の `.each` メソッド入門

Rubyで最も多く使われる繰り返し処理メソッドが `.each` です。`Array`や`Hash`、`Range`、`Enumerator`といったコレクションから要素を順次取り出し、ブロック内で任意の処理を実行します。  
`for`文よりも可読性が高く、Rubyコミュニティでも圧倒的に使用頻度が高い点が特徴です。

---

## `.each` メソッドとは

- **繰り返し処理用のメソッド**  
- コレクション（`Array`、`Hash`、`Range`、`Enumerator` など）から要素を順次取り出し、ブロックを実行  
- `for`文よりも直感的で、Rubyらしい書き方  
- 「要素の数だけブロックを繰り返す」というイメージ

---

## 基本的な記法

```ruby
コレクション.each do |要素|
  # 要素に対する処理
end
```
## 具体例
```ruby
[1, 2, 3].each do |n|
  puts n * 2
end

# 実行結果
2
4
6
```

---
## ⚠️戻り値に関する注意
`.each`は「元のコレクション自身」を返します。要素を変換して別の配列を作りたい場合は`map`を使い分けましょう。
```ruby
arr     = [1, 2, 3, 4]
arrx2   = arr.map  { |n| n * 2 }
arrxx2  = arr.each { |n| n * 2 }

p arrx2   # => [2, 4, 6, 8]
p arrxx2  # => [1, 2, 3, 4]
```
map はブロックの戻り値を集めた新しい配列を返す

each は元の配列を返し、ブロック内の戻り値は破棄される

---
## まとめ
- `.each`メソッドは要素を順番に取り出してブロックを実行する基本メソッド
- 戻り値は常にレシーバーのまま
- 要素変換が必要な場合は map と使い分ける

## まとめてみて
- 自分の勝手な思い込みとして、`.each`メソッドって、`(1..5)`みたいな順列にしか使わないイメージが強くて、上手く利用できていない。
- 例えば、テストの点数`[40, 54, 70, 95]`のような配列に使うケースの方が多いと思うから、この固定観念を打破したい。
PlayCanvas x Photonのサンプルを動かす

※記事執筆時点（2025/05/28）の情報です。

こちらのサンプルを動作させるまでの簡易手順です。

https://playcanvas.com/project/926999/overview/playcanvas-photon-realtime

0. ↑のプロジェクトをForkする
0. ForkしたプロジェクトをEDITORで開く
0. [Photonの公式サイト](https://www.photonengine.com/ja/photon)から`Photon Realtime（JavaScript）`をダウンロードする
0. ダウンロードしたzipファイルを解凍する
0. `photon.min.js`をPlayCanvasのプロジェクトにインポートする
   - ファイルの場所：photon-javascript-sdk_vx-x-x-x/lib/photon.min.js
0. Photonのダッシュボードから新規アプリを作成（種別は`Realtime`）
0. appIdをコピーする
0. PlayCanvasのプロジェクトで`MainMenu`のシーンを開く
0. HIERARCHYビューから`Root`を選択する
0. `Root`にアタッチされている`photonLoadbalancingPlaycanvas`の`appId`に先ほどコピーした内容をペーストする
0. 実行

試した時点でのPhotonRealtimeのバージョン：v4-3-2-0
猿でもわかるAIプログラミングシリーズ 🐵💻 あなたの声をAIに真似させる（基礎編）

 

## 1. はじめに：AIに声を真似させたい？

最近、YouTubeやSNSなどで「自分の声をAIに真似させてみた！」というコンテンツが注目を集めています。音声クローン（Voice Cloning）と呼ばれるこの技術は、AIが人間の声の特徴を学習し、まるで本人が話しているかのような音声を生成することを可能にします。

本記事では、音声クローンの基本的な仕組みと、オープンソースツールを使って\*\*「自分の声をAIに真似させる」**方法を、コード付きでわかりやすく解説します。
すぐに試してみたくなるような実装例と、実際に開発・運用する中で得た**リアルな知見\*\*も共有します。

---

## 2. 音声クローン技術の概要

音声クローンには大きく分けて以下の3つの技術要素があります：

| 技術要素                               | 説明                       |
| ---------------------------------- | ------------------------ |
| **音声特徴抽出 (Speaker Encoder)**       | 声の特徴（話し方、音域など）を数値ベクトルに変換 |
| **テキスト読み上げ (TTS: Text-to-Speech)** | テキストを音声波形に変換             |
| **ボコーダー (Vocoder)**                | スペクトログラムをリアルな音声に変換       |

代表的なフレームワークには以下があります：

* 🧠 [Real-Time-Voice-Cloning](https://github.com/CorentinJ/Real-Time-Voice-Cloning)
* 🗣️ [ESPnet-TTS](https://github.com/espnet/espnet)
* 🧬 [Tortoise TTS](https://github.com/neonbjb/tortoise-tts)

今回は最も手軽に試せる **Real-Time-Voice-Cloning** を使って、ローカル環境で音声クローンを実装します。

---

## 3. 実装例：Real-Time-Voice-Cloning を使ってみよう

### 🔧 環境構築

#### 必要条件

* Python 3.8+
* CUDA対応のGPU（NVIDIA）
* Anaconda（推奨）

```bash
git clone https://github.com/CorentinJ/Real-Time-Voice-Cloning.git
cd Real-Time-Voice-Cloning
conda create -n voiceclone python=3.8
conda activate voiceclone
pip install -r requirements.txt
```

### 📥 モデルのダウンロード

以下のスクリプトで必要な事前学習済みモデルを取得：

```bash
# ダウンロードスクリプトを実行
python demo_toolbox.py
```

もしくは、手動で以下の3つを `saved_models/` フォルダに配置：

* encoder.pt
* synthesizer.pt
* vocoder.pt

### 🧪 音声クローンを実行してみる

1. 自分の声を録音（例：`myvoice.wav`）
2. GUIツールボックスから読み込む、またはPythonスクリプトで直接試す：

```python
from demo_cli import *
run_cli()
```

コマンドラインから質問に応じて、音声クローンが生成されます。

---

## 4. 実践Tipsとハマりがちな罠

### ✅ 実践的なTips

* **音質が命：** 入力音声は静かな場所で録音するのがベスト。ノイズが多いと精度が落ちる。
* **声の長さ：** 1分程度の音声があるとより正確にクローンされる。
* **TTSの精度向上：** 単語単位で区切って話すとより自然な読み上げが可能に。

### ⚠️ よくあるエラーと対処法

| 問題         | 解決法                              |
| ---------- | -------------------------------- |
| GPUメモリ不足   | バッチサイズや音声長を調整する、あるいはColabを使う     |
| 文字化け       | 日本語TTSには別途学習が必要。今回は英語を前提に。       |
| モデルが読み込めない | `saved_models/` の構成を再確認し、パスを明示指定 |

---

## 5. 応用例と次のステップ

音声クローンは以下のような応用が考えられます：

* 🎮 **ゲームやメタバースでのキャラクターボイス**
* 🧑‍🏫 **教育・eラーニングでのナレーション自動化**
* 🎙️ **ポッドキャスト・動画の声合成**
* 🛠️ **カスタムボイスBot開発（例：Slack / Discord Bot）**

### 🔮 日本語対応やモデル微調整

日本語に対応させたい場合は、日本語のTTSデータセット（JSUTやJVSなど）を用いて、Synthesizer部分のファインチューニングが必要になります。

---

## 6. まとめ：AIの声はここまできた！

### ✅ メリット

* 音声の自動生成による**時間削減**
* 自分の声でパーソナライズされたアプリ開発が可能
* クラウド連携すれば即サービス化も可能

### ❌ デメリット・課題

* 日本語対応には追加学習が必要
* 悪用（ディープフェイク）のリスクが存在

### 🚀 今後の展望

* よりリアルな感情表現の対応
* モバイル向け軽量化
* 法的・倫理的フレームワーク整備

---

## 📚 補足・参考資料

* GitHub: [Real-Time-Voice-Cloning](https://github.com/CorentinJ/Real-Time-Voice-Cloning)
* データセット: [JVS (Japanese Voice Corpus)](https://sites.google.com/site/shinnosuketakamichi/research-topics/jvs_corpus)
* 論文: [Transfer Learning from Speaker Verification to Multispeaker Text-To-Speech Synthesis](https://arxiv.org/abs/1806.04558)

---

## 🙋‍♂️ 最後に

音声クローンは単なる技術的好奇心だけでなく、**実務的にも十分活用可能な武器**です。今回のコードをもとに、自分だけの音声AIをぜひ試してみてください。

---

**📝 著者:**
クラウドインフラ × 機械学習エンジニア / AI技術ライター
実務ではMLパイプライン設計、MLOps、GPUインフラ整備を担当。趣味はボイスボット作りと音声合成。
【2025年05月版】RHEL9.5 の Failed to start dnf makecache への対応

# はじめに

journallog に以下のエラーが定期的に出て監視にひっかかるので静観する＋頻度を修正することに。
犯人は、`dnf makecache` だと予想。
残メモリ量・CPU・ディスクの空き容量などは問題ないはず。
`dnf makecache` の実行は、デフォルトだと 6h 毎です。

```
May 27 15:55:49 rhel01 systemd[1]: Failed to start dnf makecache.
May 13 13:24:17 rhel01 systemd[1]: Failed to start dnf makecache. 
```

# 環境

```terminal
$ uname -a
Linux rhel01 5.14.0-503.35.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Mar 24 11:15:27 EDT 2025 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/os-release 
NAME="Red Hat Enterprise Linux"
VERSION="9.5 (Plow)"
ID="rhel"
ID_LIKE="fedora"
VERSION_ID="9.5"
PLATFORM_ID="platform:el9"
PRETTY_NAME="Red Hat Enterprise Linux 9.5 (Plow)"
ANSI_COLOR="0;31"
LOGO="fedora-logo-icon"
CPE_NAME="cpe:/o:redhat:enterprise_linux:9::baseos"
HOME_URL="https://www.redhat.com/"
DOCUMENTATION_URL="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9"
BUG_REPORT_URL="https://issues.redhat.com/"

REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 9"
REDHAT_BUGZILLA_PRODUCT_VERSION=9.5
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="9.5"
```

# 作業概要

- `/etc/dnf/dnf.conf` を修正
- サービスの再起動

# 作業

## `/etc/dnf/dnf.conf` を修正

`[main]` セクションに以下の行を追加。デフォルトは 6h 。
```/etc/dnf/dnf.conf
metadata_expire=24h
```

## サービスの再起動

```terminal
sudo systemctl daemon-reload
sudo systemctl restart dnf-makecache.timer
```

# 手動で実行する場合

```
sudo dnf clean all
sudo dnf makecache
```

# さいごに

かんたんでしたね

# 追記

このあと、rhel 9.5 から rhel 9.6 にアップデートして様子を見ることにしました。

```
$ uname -a
Linux rhel01 5.14.0-503.35.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Mar 24 11:15:27 EDT 2025 x86_64 x86_64 x86_64 GNU/Linux
$ cat /etc/os-release 
NAME="Red Hat Enterprise Linux"
VERSION="9.6 (Plow)"
ID="rhel"
ID_LIKE="fedora"
VERSION_ID="9.6"
PLATFORM_ID="platform:el9"
PRETTY_NAME="Red Hat Enterprise Linux 9.6 (Plow)"
ANSI_COLOR="0;31"
LOGO="fedora-logo-icon"
CPE_NAME="cpe:/o:redhat:enterprise_linux:9::baseos"
HOME_URL="https://www.redhat.com/"
DOCUMENTATION_URL="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9"
BUG_REPORT_URL="https://issues.redhat.com/"

REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 9"
REDHAT_BUGZILLA_PRODUCT_VERSION=9.6
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="9.6"
```
技術ブログの管理を効率化：GitHubリポジトリでQiita・Zenn・noteの記事を一元管理する方法


# はじめに

はじめまして、ぐみと申します。PM／ディレクターとして働きながら、業務効率化のためのツールやスクリプトを作っています。GAS・CLI・自動化が好きです。現場で役立つTipsを発信します。

この記事では、GitHubリポジトリを使用して複数の技術ブログプラットフォーム（Qiita・Zenn・note）の記事を効率的に管理する具体的な実装手順を紹介します。

# 実装手順

## 1. プロジェクトの初期設定

```bash
# プロジェクトの作成
mkdir tech-blog-management
cd tech-blog-management

# npmプロジェクトの初期化
npm init --yes

# 必要なCLIツールのインストール
npm install @qiita/qiita-cli zenn-cli --save-dev
```

## 2. Qiita CLIの設定

```bash
# Qiita CLIの初期化
npx qiita init

# ログイン
npx qiita login

# 設定ファイルの確認
cat .qiita.config.json
```

## 3. Zenn CLIの設定

```bash
# Zennの初期化
npx zenn init

# 記事用ディレクトリが作成されます
```

## 4. ZennとGitHubリポジトリの連携

- [Zennのダッシュボード](https://zenn.dev/dashboard/deploys)にアクセス
- 「レポジトリ設定」から連携するリポジトリを選択

## 5. note用のフォルダ作成

```bash
# ディレクトリ構造の作成
mkdir -p public note
```

## 6. .gitignoreの設定

```
cat << EOF > .gitignore
node_modules/
.DS_Store
.env
EOF
```

# 記事作成のポイント

## 1. ファイル命名規則

日付\_タイトル.md の形式で統一
例：20240320_tech-blog-management.md

## 2. 画像管理

### Qiita

- ~~ローカルでの画像管理は不可~~
- ~~記事作成時にプレビューから画像をアップロード~~
- ~~アップロードした画像はQiitaのサーバーで管理~~
- 画像はGithubのレポジトリにプッシュしてURLを埋め込むことにしました（2025/06/02更新）
  - GitHubリポジトリの画像直リンク: `https://raw.githubusercontent.com/ユーザー名/リポジトリ名/main/パス/画像.png`

### Zenn

- ローカルで画像を管理可能
- 記事ごとに専用の画像ディレクトリを作成
  ```
  images/
  └── 20240320_tech-blog-management/
      ├── 01_overview.png
      ├── 02_implementation.png
      └── 03_result.png
  ```
- 画像はGitHubリポジトリで管理

### note

- ローカルで画像を管理可能
- 記事ごとに専用の画像ディレクトリを作成
- 画像はGitHubリポジトリで管理
- 投稿時に画像をアップロード

## 3. 記事の構成

各プラットフォームに合わせた記事の構成を意識しましょう：

### Qiita

- 具体的な実装手順を重視
- コード例を多く含める
- トラブルシューティングの手順を記載

### Zenn

- 背景や考え方を重視
- 実装に至った経緯を説明
- 学びや気づきを共有

### note

- 非エンジニア向けの説明を心がける
- 実務での活用例を紹介
- 体験談や気づきを共有

# 記事の投稿手順

## 1. Qiitaへの投稿

```bash
# 記事の作成
npx qiita new 20240101_article-name

# プレビューで内容を確認
npx qiita preview

# 記事の公開
npx qiita publish 20240101_article-name
```

## 2. Zennへの投稿

```bash
# 記事の作成
npx zenn new:article --slug 20240101_article-name

# プレビューで内容を確認
npx zenn preview

# 記事の公開（GitHubリポジトリにプッシュ）
git add .
git commit -m "Add new article"
git push origin main
```

## 3. noteへの投稿

1. ローカルでMarkdownファイルを作成
2. プレビューで内容を確認
3. noteの投稿画面に内容をコピー
4. 最終確認後、投稿

# まとめ

この記事では、GitHubリポジトリを使用した技術ブログ管理の具体的な実装手順を紹介しました。CLIツールとシェルスクリプトを組み合わせることで、記事の管理と投稿を効率化できます。

# おまけ：関連記事のご紹介

この記事の執筆にあたり、投稿プラットフォームの使い分けについて考えた記事をnoteに投稿しました。技術記事の管理方法を考える上で、参考にしていただければ幸いです。

- [投稿媒体の使い分けを考えることで、発信しやすくしようと思った話](https://note.com/gumigumih/n/n27aec58d87ce)

# 参考リンク

- [Qiita CLI Documentation](https://qiita.com/Qiita/items/666e190490d0af90a92b)
- [Zenn CLI Documentation](https://zenn.dev/zenn/articles/install-zenn-cli)

# 更新履歴

- 2025/06/02: Qiitaの画像管理方法を更新（GitHubリポジトリでの管理に変更）
- 2025/06/02: Zenn CLIの記事作成コマンドを更新（--slugオプションを使用する方法に変更）
- 2025/05/28: 初版公開
【Next.js/Docker Rails】コンテナ内で環境変数が読み込まれないエラーの解決方法について

# はじめに
フロント側Nextjsからバックエンド側RailsへAPIリクエストするも、.envが読み込まれておらず認証が失敗しているエラーでつまずいたため記事にします。
　ローカルで.envを作成すればコンテナ内でも環境変数を使うことができると思っておりました。
 

#### APIからの返り値

:::note warn
{message: 'Unauthorized', type: 'unauthorized'}
:::


# 解決方法
下記を追加

```docker-compose.yml
env_file:
  - .env
```




# 参考
https://qiita.com/Sicut_study/items/84a079f495a3b5419758

https://qiita.com/shizen-shin/items/1d41b2311ce7202ea9f1

https://docs.docker.jp/compose/environment-variables.html

# おわりに
bashでも環境変数が使えることを確認して、値も取得できるようになりました。

<br>


# JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
興味のある方は、ぜひホームページをのぞいてみてください！
▼▼▼

https://projisou.jp
カンマ区切りの文字列を含む1列のDataFrameの正規化

# はじめに

私はこういう持ち方のデータが大嫌いだ。無精してExcel上で「データの区切り位置」等でちまちまやろうとすると100億％事故るからである。1つのセルに複数の内容が入っているのが耐え難い。
しかし、現実においてはそうもいっていられないため、自分用のチートシート的に書いておく。

# pandas.melt()を使う方法

```python
import pandas as pd

# データの定義
data = {'hunter_list': [
    'gonn,kilua,leolio,klapika',
    'hisoka,menti,hanzo',
    'kaito'
]}

# データフレーム作成
df = pd.DataFrame(data)

# カンマで分割して複数列に展開
df_split = df['hunter_list'].str.split(',', expand=True)

# meltで縦一列に変換 → 重複・欠損を削除 → インデックスをリセット
df_melted = (
    df_split
    .melt(value_name='hunter')
    .dropna()
    .drop_duplicates(subset='hunter')
    .reset_index(drop=True)
)

# 結果表示
print(df_melted['hunter'])

```
### 出力
```
0       gonn
1     hisoka
2      kaito
3      kilua
4      menti
5     leolio
6      hanzo
7    klapika
Name: hunter, dtype: object
```
★ポイント
str.split(',', expand=True)：カンマで分割して列に展開
melt()：複数列を縦一列に変換
dropna()：空のセルを削除
drop_duplicates()：重複を削除
reset_index(drop=True)：インデックスを振り直し

# pandas.melt()を使わない方法

```python
import pandas as pd

# データの定義
data = {'hunter_list': [
    'gonn,kilua,leolio,klapika',
    'hisoka,menti,hanzo',
    'kaito'
]}

# カンマで分割し、縦一列に並べる
flattened_list = [item.strip() for line in data['hunter_list'] for item in line.split(',')]

# pandasのSeriesに変換して処理
series = pd.Series(flattened_list)

# 空要素削除・重複削除・インデックス振り直し
cleaned_series = series.replace('', pd.NA).dropna().drop_duplicates().reset_index(drop=True)

# 結果を出力
print(cleaned_series)

```
### 出力
```
0       gonn
1      kilua
2     leolio
3    klapika
4     hisoka
5      menti
6      hanzo
7      kaito
dtype: object
```

# 感想
これまでpandas.melt()でずっとやっていたのだが、他の方法でも同じ処理ができることが分かって良かった。
AWS Cloud Practitioner(CLF-C02) 合格体験記

# 0.はじめに

お久しぶりの記事になります。
今回はAWSの認定資格のうち、クラウドプラクティショナーを取得した際の事について記事にしたいと思います。

受験したのは2月末でしたが、当時の気持ちや情報などを忘れないように、記事にしておきます。

前提として、自身のキャリアとしてはエンジニアとしては約7年ほどで、オンプレ(いわゆる仮想系)は5年以上、クラウドについては約3年現場で経験があるといった感じです。

# 1.試験概要

試験にあたっての概要は以下のページにまとまっています。

https://aws.amazon.com/jp/certification/certified-cloud-practitioner/

- 試験時間：90分
- 試験の形態：65個の問題(複数選択または複数応答のいずれか)
- 料金：100USD(税込み16500円)


# 2.なぜ試験を受けようと思ったのか

そもそもの前提として、度々議論を巻き起こす資格不要論について、私はどちらかというと不要派でした。
実務が実績として一番だし、どうせ自宅で勉強するなら現場で使っている物を勉強すればより一層技術力高まるじゃんという気持ちから、率先して資格を取得しようという気持ちはありませんでした。

ただ、資格を持っていれば外部の人からも一定以上のスキルはあると判断してもらえるし、実務の経験+資格がある方が、より価値が高まるというのも理解はしていました。

そのうえで今回資格取得を始めようと思った理由として、以下の2つになります。

- 今後のキャリアも考えたときに、AWSの資格があった方が絶対に市場価値を高められより高度な案件に参画できると思ったから
- 資格不要論を言い訳にして、実は自身は勉強ができない人間なのでは？と心の中で感じたから

1つ目については、冒頭で記載した内容です。
ただ、これの動機となったのは省庁系の案件で参画などにプロフェッショナル系の資格が必要みたいな、SESの求人などを見たことがあり、そういう線引きをするところもあるんだと思いました。

2つ目については、自身は興味ある事に対してはパフォーマンスを発揮できますが、興味ないことにはとことんやる気がでない性格だとわかっているつもりです。
ただ、やる気がない=資格が取れないではないと思うので、自身にがっかりしないためにも資格を取得することで、自分はやればできるだと知りたかったからです。

そのうえで今回クラウドプラクティショナーから順番に取ることに決めました。
正直自身の経験であれば、SAAから一気にとれそうとも思ったのですが、万が一落ちた時のショックに備え、地盤固めとして下位からとっていくことにしました。

# 3.学習期間

資格を取ろうと決意し、申し込んだのは2/8でした。
試験日は最寄りの会場の日程が空いてなく2/24にしました。

# 4.学習方法と試験当日の流れ
学習にあたっては以下のUdemyのみを利用しました。

https://www.udemy.com/course/aws-4260/

演習問題が1～6まであるのですが、時間の関係で1～3を2週、4～5を前日に1回解きました。
2/12から勉強を始めたので、勉強期間は約10日ほどでした。

試験当日は受付で写真などを取られ、そのまま流れるように試験会場内に案内されました。
後述で試験結果は記載していますが、試験自体は見直し含め30分くらいで終わり、受付の人に「え！もう終わりですか！？」と言われました。

# 6. 試験結果と受けた感想

結果は合格でしたが、手ごたえのわりに思ったよりもギリギリだったなという印象です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566232/8aa71e66-a3f9-47da-87cb-10bbf78210f1.png)

よくクラウドプラクティショナーは初心者向け、簡単と言われていますが、クラウドプラクティショナーでしか問われない問題、言い回しなどを考えると難易度は決して低くなかったです。
本記事を執筆時点で、SAA-C03、SOA-C02、SCS-C02に合格していますが、今でもこの気持ちは変わらないです。
(ただ問題文や回答は短いのでそういう意味ではクラウドプラクティショナーの方が簡単ですが)

ただ、この点数の低さには見直しの適当さはあると思います。
上位資格を取っている現在でも、基本見直しはあまりしていません。
テスト中、全くわからない or 考えればある程度分かるの2択しか生まれず、全くわからない問題については見直してもわからないですし、考えてわかる問題は時間をかけてその場で考え抜くので、結局見直しをしても回答があまり変わらなかったからですが、クラウドプラクティショナーについてはあまりにも早すぎるので、もう少し見直しすべきでしたね…。

# 7. まとめ
正直クラウドプラクティショナーが現時点でも一番点数引きかったですが、結果合格できてよかったです。
他にも複数資格取得していますので、どんどん記事にしていきたいと思います。

**サマリ**

| 受験日 | 資格名称 | スコア |
|:-----------|------------:|:------------:|
| 2025/02/25     | CLF-C02        | 749         |

**個人的難易度**
| 順位 | 資格名称 | 一言メモ |
|:-----------|------------:|:------------:|
| 1位     | CLF-C02        | CLF特有の範囲と知識が難しい         |
三日坊主の目標達成を生成AIが手助けしてくれるTodoリストを作成した

「だらしない自分でもタスクをこなせるようになるTodoリストが欲しいなー」
そんな欲望から作った生成AIを組み込んだTodoリスト　【おまかせTodoリスト】
https://omakasetodo.xyz/
# 概要
プログラミング学習では、何かとTodoリストの作成が題材に上がりがちで、自身もReactの習得時に大学の講義の一環で作成した。
大学3年生になって就活もひと段落したため、なにか役に立つものを作りたいなーと思い、Todoリストを改めて作ることにした。ただのTodoリストを作るだけじゃ面白くないと思い、生成AIが目標達成に必要なTodoを作成してくれるシステムってあまり聞いたことないし面白そうと思ってPCで作業を始めた

# 誰向けのプロダクト？
「タスク管理アプリが三日坊主で終わる人」

「やりたいことはあるけど進め方が分からない人」

「学習計画を自動化したい学生」

など...
やる気がない時の自分ですね


# 構成要素の説明
- 目標
    -
    ...ユーザーが最終的に達成したい目標、理想
    
- タスク
    -
    ... 生成AIが目標に基づき、達成に必要な要素をTodo化したもの

- アシスト情報
    -
    ...生成AIが探したタスクの達成のための役にたつ情報

| カテゴリ    | 使用技術・サービス                                  |
| ------- | ------------------------------------------ |
| フロントエンド | Djangoテンプレート, HTML/CSS/JavaScript           |   
| バックエンド  | Django, OpenAI API, Google Custom Search API |   
| データベース  | SQLite                                     |   
| インフラ    | Docker, Debian, ConohaVPS    |   
| セキュリティ  | OpenAI Moderation API                      |   

#  機能概要と流れ

## 目標登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692998/72fc1b5b-0ab8-4459-aba3-5d3524688b24.png)
ユーザーに最終的に達成したい目標、理想をタイトルにて宣言してもらう
ChatGPTに対する捕捉情報として、その目標がどういったものなのかも追加で記述してもらう
#### フィルタリング機能
OpenAI API のModeration APIを用いて、タスクや補足文が不適切な表現を含んでいないかチェックさせる

例えば以下のような典型的な悪用をしようとする人がいたら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692998/80f895ff-ea3b-4395-998b-4fa8ec17be3b.png)

こうなる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692998/e1f387d1-3772-4ba0-ab81-7f2f7d3b47d0.png)

なお、利用規約は作れていない模様

## タスク生成

こんな感じでタスクを生成してくれる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692998/1fec47a0-651b-4b35-910a-2dbdada97b5f.png)
タスクが生成されたら、そのタスクに取り組む日をシステムに登録でき、状況を管理することができるようになっている

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692998/7f075b57-1481-4803-a039-7f946fb18e42.png)


## アシスト情報作成
例えば、AFP認定研修っていうのがなんのことか私はさっぱり知りません
そんなタスクを進める際の障壁にぶち当たったら、追加の情報を取ってきてもらいます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692998/f8efe0d4-ab6b-4d54-98ba-f888a0d7c97e.png)
こんな感じで、必要な情報をとってきてくれます


## 主に役に立っているもの
- OpenAI APIの関数呼び出し https://platform.openai.com/docs/guides/function-calling
このプロダクトを公開する際は、関数呼び出しで一からロジックを書いていたが、この部分はMCPの登場で効率的になりそうだなって感じた。ありゃすごい
- Google Custom Search API
参考にしたサイト: https://www.system-exe.co.jp/kotohajime15/

この二つを組み合わせて、専門的な内容も情報を入手できるようにしている
... けど、今になってはChatGPTでは検索は一般的すぎて新しくないかも

## 将来組み込みたい内容
- Googleカレンダーとの連携
- タスクに基づいた生成AIとの会話フォームを作りたい
- もっとカッコイイデザインにしたい

ここまで読んでいただきありがとうございました
Git運用の基本を整理！Issueとブランチ管理の実践ガイド

## 🔍 **はじめに**  
私は個人開発でGitを使い始めたものの、運用方法が分からず試行錯誤の日々でした。そこで、本日Copilotと徹底的に議論しながら「Gitの基本を曖昧にしない」ための整理を行いました。本記事では、Issue単位のブランチ管理、Pull Requestの流れ、自動化のメリットについて学んだ内容を共有します！

## **🛠 Issueごとのブランチ運用**  
**Issueごとにブランチを作成し、そこに関連する変更をコミットしていく**のが一般的な開発フローです。これにより、変更の目的を明確にし、履歴管理がスムーズになります。  

### **ブランチの命名規則**  
```bash
feature/issue-123-add-login  # 新機能追加に関するIssue 123のブランチ
```
- `feature/` → 新機能追加  
- `issue-123` → 関連するIssue番号  
- `add-login` → 変更内容（ログイン機能追加）  

Issue番号を含めることで、「どの課題を解決するブランチなのか」が明確になります。特にチーム開発では、後から振り返る際に非常に便利です。

## **🚀 Pull Request運用のポイント**  
1つのIssueに対して**1つのPull Request**を作成し、レビューを受けてマージするのが基本的な流れです。  
```mermaid
graph LR;
  A["📝 Issue作成"] --> B["🌿 ブランチ作成"]
  B --> C["⚙️ 開発 + コミット"]
  C --> D["📩 Pull Request"]
  D --> E["👀 レビュー"]
  E -- ✅ 承認 --> F["🔗 マージ"]
  E -- ❌ 修正依頼 --> C
```
1. Issueごとにブランチ作成
2. 開発を進めながら複数回コミット（修正を細かく管理）  
3. Pull Requestを作成し、レビューを受ける
4. 修正が必要なら、Pull Request内で追加コミット 
5. 問題なければメインブランチへマージ

### **Pull Requestの標準フロー**
```bash
git checkout -b feature/issue-123-add-login # 新しいブランチを作成し、そのブランチへ切り替える
git commit -m "ログイン画面のデザイン調整" # 変更をコミットする
git push origin feature/issue-123-add-login # 作成したブランチをリモートに送信し、Pull Requestを作成可能にする
```

## **🔁 Pull Request後の追加変更**
Pull Requestを出した後に**同じIssueに関する追加の変更が必要になった場合**：
- **未マージの場合** → 既存のブランチに追加コミットして更新  
- **すでにマージ済みの場合** → 新しいブランチを作成し、新しいPull Requestを作成  

```bash
git checkout main # ブランチを切り替える
git pull origin main # リモートリポジトリの最新の main を取得して、ローカルの main に統合する
git checkout -b feature/issue-123-fix-login # 新しいブランチを作成し、そのブランチへ切り替える
```
Pull Requestの更新か、新しいPull Requestを作るかは状況次第！

## **⚡️ 自動化の導入**
Gitの操作をスクリプト化することで**手動のコミット＆プッシュ作業を削減**できます。  

### **自動コミットスクリプト**
```bash
git add .
git commit -m "定期コミット"
git push origin main
```
これをシェルスクリプトにまとめることで、**ポチポチ手動でやる手間を削減**できます。  

さらに、GitHub Actionsを設定すれば、**特定のイベントが発生したら自動でコミット＆プッシュ**などの設定も可能です。  

## **📌 まとめ**
今回の学びを整理すると：
- **Issueごとにブランチを作成し、コミットを管理する**
- **Pull Requestは原則1Issueにつき1回。ただし追加修正が必要なら更新可能**
- **CUIを活用することでGitの操作がより効率的になる**
- **スクリプトやGitHub Actionsを使うことでコミット＆プッシュを自動化できる**
- **命名規則を統一することでチーム開発でも管理がスムーズになる**

Git運用を整理することで、開発の流れをスムーズに進めることができます。
私自身も、このプロセスを整理することで理解がより深まりました。
ぜひ皆さんも試してみて、実際のプロジェクトに活かしてみてください！
Flask Deployment

docker build -t asia-east1-docker.pkg.dev/cryptotrade-460823/flask-chart-api-repo/flask-chart-api .
docker push asia-east1-docker.pkg.dev/cryptotrade-460823/flask-chart-api-repo/flask-chart-api

gcloud run deploy flask-chart-api \
  --image asia-east1-docker.pkg.dev/cryptotrade-460823/flask-chart-api-repo/flask-chart-api \
  --platform=managed \
  --region=asia-east1 \
  --allow-unauthenticated
UnityでStaticメソッド内でインスタンスフィールドを変更できない理由

# 導入
Unityでゲームを作っている時、シングルトンパターンを使った事はあるだろうか
このパターンを使うにあたって、Staticという修飾子を使用した変数を使用したのではないだろうか
このStaticについて今回は噛み砕いて説明していく
# 動作環境
Unity 6000.1.0f1
JetBrain Rider 2024.3.3
# サンプルコード
ではこのコンポ―ネントを見てほしい
このコンポーネントの中にはHumanというクラスが定義されている
Staticの変数とインスタンスの変数がある
またStaticのメソッドやインスタンスのメソッドが存在している
```cs
using UnityEngine;

public class StaticAndInstance : MonoBehaviour
{
    public class Human
    {
        public static string Species = "human";
        public string Name = "name";
        
        public Human (string name) => Name = name;

        /// <summary>
        ///     StaticメソッドからStaticフィールドを変更
        /// </summary>
        public static void Method1()
        {
            Species = "monkey";
            Debug.Log(Species);
        }

        /// <summary>
        ///     インスタンスメソッドからStaticフィールドを変更
        /// </summary>
        public void Method2()
        {
            Species = "gorilla";
            Debug.Log(Species);
        }

        /// <summary>
        ///     Staticメソッドからインスタンスフィールドを変更
        /// </summary>
        public static void Method3()
        {
            // Name = "山田";
        }

        /// <summary>
        ///     指定したインスタンスのインスタンスフィールドを変更
        /// </summary>
        /// <param name="human"></param>
        public static void Method4(Human human)
        {
            human.Name = "☆山田☆";
        }
    }

    private void Start()
    {
        SpeciesPropertyChange();
        HumanNameChage();
    }

    /// <summary>
    ///     二つのメソッドからStaticフィールドのHuman.Speciesを変更してログを出している
    /// </summary>
    private void SpeciesPropertyChange()
    {
        Human.Method1(); //Staticメソッドを実行する

        Human h = new Human("nobody"); //人間を作る
        h.Method2(); //インスタンスメソッドを実行する
    }

    private void HumanNameChage()
    {
        Human.Method3(); //Staticメソッドを実行する

        //三人の人を用意する
        var human1 = new Human("田中");
        var human2 = new Human("中村");
        var human3 = new Human("村田");
        
        Human.Method4(human1);
        
        Debug.Log($"{human1.Name}, {human2.Name}, {human3.Name}");
    }
}
```
## SpeciesPropertyChangeの解説
Method1はStaticのメソッドで、内容はStaticのフィールドを変更している
これは馴染み深い人も多いと思う

Method2はnobodyというインスタンスがStaticフィールドを変更している
Staticフィールドはどこからでも同じメモリにアクセスするので、これも実行できる

## HumanNameChageの解説
次のMethod3は
```cs
Name = "山田";
```
のコメントアウトを消してみると、コンパイルエラーが起きる事が分かる
エラー内容は以下のように表示される
```
非 static フィールド 'Name' は静的コンテキストではアクセスできません
```
つまりStaticメソッドからインスタンスフィールドにアクセスはできないのである
この理由は単純で、インスタンスは沢山存在している可能性があるので、どのインスタンスのNameを変えればいいかが分からないから
なのでMethod4では、変えるインスタンスを指定する事で、名前を変更する事ができている
# 終わりに
初心者のうちはStaticとインスタンスの違いが曖昧になりがちだが、Unityでプレハブを使用しているならきっと理解できるようになるはずなので、がんばって！！