OmniAICreator/Qiita-1.07M huggingface dataset:
【Python】派生クラスを動的に取得して処理をぶん回したい

## はじめに
ゴールデンウィークをだらだら過ごしていたらふと気になりました[^1]。
実際どういうことかを「各チェックを行うクラス」を例に見ていきましょう。

## 概要
各チェックを行う元になる抽象基底クラス`CheckBase`を下記のように定義します。
```python:check.py
from abc import ABC, abstractmethod

class CheckBase(ABC):
    """各チェックIDのベースとなる抽象基底クラス"""

    def __init__(self, data):
        self.data = data

    @abstractmethod
    def is_target(self) -> bool:
        """チェック対象であればTrueを返す"""
        ...

    @abstractmethod
    def check(self) -> None:
        """チェックを行う"""
        ...
```
この`CheckBase`を継承した各チェックを定義します。
```python:check.py
class CheckID1(CheckBase):
    def is_target(self) -> bool:
        return True

    def check(self) -> None:
        print("チェックID1が実行された")

class CheckID2(CheckBase):
    def is_target(self) -> bool:
        return True

    def check(self) -> None:
        print("チェックID2が実行された")
```

この`CheckBase`を継承した`CheckID1`と`CheckID2`のインスタンスを作成して処理をぶん回したいとします。
この実行を行う`main.py`は下記のように書くことにします。
```python:main.py
import check

# 呼び出し部分だけ書く
for cls_ in [check.CheckID1, check.CheckID2]:
    check_cls = cls_(check_data)
    if check_cls.is_target():
        check_cls.check()
```

このように書いてしまうと下記のような問題点に遭遇します。
- `CheckID`が増えていくと、`[check.CheckID1, check.CheckID2]`も拡大していく
- `CheckID`を実装したら、呼び出し側の`main.py`の改修が必要になる


この2つを解決するためには、`CheckBase`を継承した派生クラスが動的に取得出来れば良さそうです。

## 派生クラスを動的に取得する
組み込みモジュールである inspect モジュールを使います。

https://docs.python.org/ja/3/library/inspect.html

下記に `CheckBase` を継承した派生クラスだけを取得するメソッドを示します。
ざっくりやっていることは下記の2点です(難しいことはやっていないので詳しい説明は省略)。

  1. `get_all_check_cls` が定義されているモジュール内の全てのクラスを取得する
　→ 今回の場合は`check.py`に定義することにする
  2. `CheckBase` の派生クラスであり `CheckBase` 自身ではないクラスを収集する

```python
import sys
import inspect

def get_all_check_cls() -> list[type[CheckBase]]:
    """CheckBaseを継承した全てのクラスを取得する"""
    ret = []
    module = sys.modules[__name__]
    # クラス名(CheckBase, CheckID1など)とそのオブジェクトがイテレートされる(今回クラス名は使わないので`_`にしている)
    for _, obj in inspect.getmembers(module, inspect.isclass):
        if issubclass(obj, CheckBase) and obj is not CheckBase:
            ret.append(obj)
    return ret
```

呼び出し側の`main.py`は、この`get_all_check_cls`を呼び出すだけで済むので、新しいチェックが増えても`main.py`に変更が生じないので嬉しくなれます。

[^1]: だらだらしてたらゴールデンウィークが終わってしまって、こんな中途半端な時期に投稿することになってしまった…
NCMBの管理画面をGoogle Chrome機能拡張で便利にする（画像プレビュー）

NCMBでは管理画面を提供していますが、時々物足りないことがあります。この機能があったらもっと便利なのに…と思いつつ、使っている方もいることでしょう。

そこで、その足りない機能を補足するGoogle Chrome機能拡張を開発しはじめました。今回は1.2で追加した画像プレビュー機能です。

## 動作について

動作は以下のようになります。機能拡張をインストールしていると、ファイルストアで画像を選択した場合に、プレビューが追加表示されます。

![image-preview.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/a89af8d4-66ea-95bf-571c-bd8fcb40be4a.gif)


## インストール

[Chrome機能拡張のページからインストール](https://chrome.google.com/webstore/detail/ncmb-extension/dglkhlplcpmnbgodhbngcmdfpojkbdnc?hl=ja&authuser=0)してください。

## 利用法

ファイルストアの画面で、任意の画像を選択します。そうすると、プレビューの項目が追加されて、画像が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/34eaaaec-658b-3bb1-cbce-682557ffe271.png)


## 制限

この機能拡張は [https://console.mbaas.nifcloud.com](https://console.mbaas.nifcloud.com/) 以下でのみ動作します。また、この機能は管理画面のAPIを使っていますので、APIコール数を消費しません。また、ACLは無視して処理されます。

画像はMimeタイプが `image/*` になっているものを対象としています。それ以外の場合は、データは画像であってもプレビュー対象外になるので注意してください。

## コードについて

機能拡張のコードは[NCMBMania/chrome-extension](https://github.com/NCMBMania/chrome-extension)にアップロードしてあります。ライセンスはMIT Licenseです。依存ライブラリとして[URL.js](https://github.com/duzun/URL.js)を使っています（こちらもMIT Licenseです）。

## まとめ

機能的にはまだ多くありませんが、徐々に機能を追加していきます。Google ChromeでmBaaSの管理画面を利用されている方はぜひお使いください。
Hexabase TypeScript SDKを使ってデータレポートを取得する

[Hexabase（ヘキサベース）](https://www.hexabase.com/)は企業においても安心して利用できるBaaS（Backend as a Service）を提供しています。多くのBaaSがそうであるように、主にフロントエンド開発者に利用してもらいたいと考えています。そこで現在、TypeScript SDKの開発が進められています。

この記事ではHexabase TypeScript SDKのインストールと、データレポートを取得する方法を解説します。

## データレポートとは？

データレポートは、データベースの特定のアイテムやフィールドだけを表示したり、連結・集計したりできる機能です。いわばRDBMSで言うビューに相当する機能です。

データレポートは管理画面で作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/ec934fa3-9955-6c20-a893-41b48c9ae75e.png)


## インストール

インストールはnpmやyarnを使って行います。

```
# npmの場合
npm install @hexabase/hexabase-js

# yarnの場合
yarn add @hexabase/hexabase-js
```

## インポート

インポートすると、 `HexabaseClient` というオブジェクトが取得できます。

```tsx
import { HexabaseClient } from "@hexabase/hexabase-js";
```

## 初期化

HexabaseClientを初期化します。

```tsx
const client = new HexabaseClient();
```

### 認証

Hexabaseでは業務利用を想定しているため、利用する際に認証情報が必須になります。最初はメールアドレスとパスワードで認証し、その後はトークンを使ってGraphQLにアクセスします。 `client` を使って処理します。

初回の認証は次のようになります。emailとパスワード、またはトークンが必須です。

```tsx
await client.login({email, password, token});
```

後はこの `client` に対して処理を行います。

## プロジェクトを取得する

データレポートはプロジェクトに紐付きます。そこで、まず利用するプロジェクトを取得します。

### 現在のワークスペースを取得する

ログインした時点でHexabaseClientのcurrentWorkspaceが現在のワークスペースオブジェクトになっています。

```tsx
client.currentWorkspace
```

ワークスペースを切り替える場合には、 `setWorkspace` メソッドを使います。

```tsx
client.setWorkspace(newWorkspaceId);
```

そのワークスペースに紐付いているプロジェクトを取得します。

```tsx
const project = await client.currentWorkspace.projects(projectId);
```

## データレポートを取得する

まず作成されているデータレポートを取得します。

```tsx
const reports = await project!.reports();
```

## レポートの内容を取得する

そして各レポートオブジェクトに対して `data` メソッドで実レポートのデータが取得できます。

```tsx
const data = await report.data();
```

`data` はレポートの内容がJSONになっています。たとえば以下のようになります。

```jsx
[
  {
    createdAt: 2024-04-07T11:24:27.000Z,
    updatedAt: 2024-06-22T05:43:10.000Z,
    items: [ [Item] ],
    test_text: 'test',
    test_number: 100,
    test_select: 'SELECT_2'
  },
  {
    createdAt: 2024-04-07T11:24:27.000Z,
    updatedAt: 2024-06-22T05:42:09.000Z,
    items: [ [Item] ],
    test_text: 'テストテキスト',
    test_number: 400,
    test_select: 'SELECT_1'
  },
  {
    createdAt: 2024-04-07T11:24:27.000Z,
    updatedAt: 2024-06-22T05:44:11.000Z,
    items: [ [Item] ],
    test_text: 'test',
    test_number: 250,
    test_select: 'SELECT_1'
  }
]
```

結果の型は以下のようになっています。

```ts
interface GetReportDataResponse {
  createdAt: Date;
  updatedAt: Date;
  items: Item[];
  [key: string]: any;
}[]
```

## まとめ

業務システムにおいてレポーティングはよく使われる機能です。各テーブルからデータをダウンロードして自分でレポートを作成するのは手間です。Hexabaseであれば、管理画面上でレポートに必要な情報や条件を設定しておけます。

JSONでダウンロードできれば、後はCSVなどへも変換できるでしょう。ぜひ業務システム開発に役立ててください。

[株式会社 Hexabaseー法人向けクラウドシステム『Hexabase』ー](https://www.hexabase.com/)
HTMLでQuine

## 前書き

HTMLでQuineを作る。
Chromeでソースと同じ文字列が表示されればよしとする。

## というわけで作った。

### ソース

```html:quine.html
<script>
s = `
cc = String.fromCharCode;
bq = cc(96);
nl = cc(10);
ltc = cc(60);
gtc = cc(62);
lt = "&l" + "t;";
gt = "&g" + "t;";
br = ltc + "br" + gtc;
s1 = lt + "script" + gt + br + "s = ";
s2 = ";" + br + "eval(s)" + br + lt + "/script" + gt;
s = s1 + bq + s.replaceAll(nl, br) + bq + s2;
document.documentElement.innerHTML = s`;
eval(s)
</script>
```

### 結果

https://mogamoga1024.github.io/html-quine/quine.html

## 別解

### ソース

```html:quine2.html
<script>
document.documentElement.innerText = document.getElementsByTagName("script")[0].outerHTML;
</script>
```

### 結果

https://mogamoga1024.github.io/html-quine/quine2.html

## 発展記事

https://qiita.com/mogamoga1337/items/660842a1b8849a54051b
WordPress + VS Code: PHP IntelephenseでACFの関数が未定義になるのを回避する

# 状況
PHP Intelephenseの設定でIntelephense: StubsからWordPressを追加したのにACF（プラグインのAdvanced Custom Fields）のコードで未定義エラーが出る

```text:エラー文
Undefined function 'get_field' . intelephense(1010) 
```

# 結論

PHP Intelephenseの設定の
Intelephense > Environment:Include Paths に
```
/wp-contentまでのパス/plugins/advanced-custom-fields/includes
```
を追加する。

# 詳しいやり方
#### 1. VS Codeの左側のメニューから拡張機能をクリック
#### 2. PHP Intelephenseの歯車のアイコンをクリックし、拡張機能の設定をクリック
![スクリーンショット 2023-05-16 17.05.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288781/2865a903-3189-ee4b-83be-b0408c3eaf69.png)
#### 3. Environment:Include Pathsという項目を探してフォームにパスを入力しOKをクリック
![スクリーンショット 2023-05-15 17.03.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288781/b3a3e2a4-8a3e-11dc-72df-ab06d2dfa0ab.png)
パス→`/wp-contentまでのパス/plugins/advanced-custom-fields/includes`
※私の場合すぐに反映されてエラーが消えましたが、効かない場合はVS Codeの再起動などお試しください

# 解決までの道のり

ググって調べたのですが関数未定義のエラーのチェックを外せみたいな記事しか見つからず（そんな怖いことできないよ＞＜；）ChatGPT先生に泣きつきました

#### ChatGPT先生の回答
![スクリーンショット 2023-05-16 18.50.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288781/d7721af9-9830-7ece-8386-d8442975daa8.png)
書いてある通りにしても解決しなかったのですが、関数を定義しているファイルへのパスを入力すれば良いっぽいことを把握。
諦めきれずにサブディレクトリを片っ端から入力してみたところ解決に至りました :tada: 
ちなみにパンくずリストのプラグイン「Breadcrumb NavXT」のコードでも未定義エラーが出ていましたがこちらはプラグインのディレクトリのパスで大丈夫でした。

#### ChatGPT先生に報告した
![スクリーンショット 2023-05-16 18.50.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3288781/ee0982af-6404-8d79-dcd1-bc34d3894dcb.png)
褒められて嬉しい :kissing_smiling_eyes: 

開発環境は人それぞれなのでダメなパターンもあるかもしれないですが未定義エラーのチェック外す前に一度試してみても損はないかと思います！

# 参考サイト
そもそもWordPressのStubが登録されてなくてエラーになっている場合はこちらのサイトもあわせてチェックしてみてください :bulb: 

https://web-creates.com/code/vscode-error-wordpress/

ありがとうございます :pray: :sparkles:
AmazonS3のライフサイクル設定を実施してみる

# 結論(実施結果)
今回は保管期間は10年とし、30日経つと Glacier Deep Archive に移動させるルールとしました。
![2023-05-17_161617.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/e6df371b-c071-b12c-54d8-6aaab7857c36.jpeg)

# ライフサイクル設定
S3バケットを選択し、「管理」の「ライフサイクルルールを作成する」にて実施していきます。
![2023-05-17_161945.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/f86fc3bd-fc49-eccd-1a83-cab34d52aa1c.jpeg)

ライフサイクルルール名を入力し、今回のスコープはすべてのオブジェクトに適用とします。
![2023-05-17_162314.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/2d4929bb-3f8a-a718-b70c-50a9194d8a4e.jpeg)

まずは「オブジェクトの現行バージョンを有効期限切れにする」にチェックを入れます。
オブジェクトの有効期限は今回は3650日(10年)としました。
![2023-05-17_162444.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/da65f889-075d-a804-f69d-90289e5eb678.jpeg)

続いて「オブジェクトの最新バージョンをストレージクラス間で移動」にチェックを入れます。
移行先は「Glacier Deep Archive」とし、30日としました。
![2023-05-17_162616.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/908d4be6-2d1e-3e28-7480-a7ab45d4f193.jpeg)

末尾に設定した内容が表示されるので、問題なければ「ルールの作成」を選択して完了です。
![2023-05-17_162827.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292878/8367a9df-02b8-f1cc-54d2-54f4f665f528.jpeg)

# 料金
3年分くらいのログを移動する結果になったからか、毎月2ドルくらいのAWS環境が1日で23ドルほどになりました。涙
安易に設定すると高額になる可能性があるので、皆様お気をつけください。。
Hexabaseプロジェクトのバックアップとリストア

[Hexabase（ヘキサベース）](https://www.hexabase.com/)は企業においても安心して利用できるBaaS（Backend as a Service）を提供しています。データ操作は管理画面を使って行ったり、API（REST APIまたはGraphQL）を使って行います。

そうした中で、処理の自動化などを手軽にできるようにHexabase CLIが提供されています。こちらは名前の通り、ターミナルを使ってCLIでHexabaseを操作できるコマンドです。

今回はこのHexabase CLIを使って、プロジェクトのバックアップとリストアを行う方法を解説します。

## Hexabase CLIのインストール

まずHexabase CLIをインストールします。これはNode.jsで作られており、npmにて公開されています。

[hexabase\-cli \- npm](https://www.npmjs.com/package/hexabase-cli)

```
$ npm install -g hexabase-cli
```

インストールすると `hx` コマンドが使えるようになります。

## 環境設定

まず環境をセットします。環境ごとにアクセスするURL（プロダクション、ステージングなど）を切り替えられます。

代表的な環境は以下のコマンドで作成できます。

```bash
# 本番環境
$ hx contexts:set prod \
  --server=https://api.hexabase.com\
  --sse=https://sse.hexabase.com

# ステージング環境
$ hx contexts:set dev \
  --server=https://az-api.hexabase.com\
  --sse=https://az-sse.hexabase.com
```

作成した環境は以下のように確認できます。

```bash
$ hx contexts:get
 NAME       SERVER                      SSE                         
 ────────── ─────────────────────────── ─────────────────────────── 
 dev        https://az-api.hexabase.com https://az-sse.hexabase.com 
 prod       https://api.hexabase.com    https://sse.hexabase.com    
Current-context set to: dev
```

利用する環境を切り替える場合には `use` を使います。

```bash
$ hx contexts:use prod
Current-context successfully set to: prod
```

## ワークスペースを指定する

次に利用するワークスペースを指定します。まず現在あるワークスペースを取得します。

```bash
$ hx workspaces      
 ID                       NAME                      
 ──────────────────────── ───────────────────────── 
 62bab4885be1affdb6021ad9 A社
 64620242babcf83ddbb0f267 B社
Current-workspace set to: B社
```

ワークスペースを切り替える場合には、 `use` を使います。

```bash
$ hx workspaces:use 62bab4885be1affdb6021ad9
Current-workspace set to: A社
```

## プロジェクトの一覧を取得する

次にワークスペース配下にあるプロジェクト一覧を取得します。

```bash
$ hx projects                               
 ID                       DISPLAY_ID   NAME                   
 ──────────────────────── ──────────── ────────────────────── 
 62de47659f3360614126382b APP-xKVON9Kk 販売管理
```

## プロジェクトをダウンロード

ではここからが本番です。プロジェクトのデータをダウンロード（バックアップ）します。この時には `save` を使います。

```bash
$ hx projects:save 64631ff60a06c5ab92a8dc5a -d back.zip
✔ Please provide details for your project template  
Name: Development
Category: Development
✔ Include histories · No / Yes
Task successfully queued... done
Template with tp_id 6464816f24dfa14e5a4c9a1b successfully created
Downloading template with tp_id 6464816f24dfa14e5a4c9a1b... done
```

## プロジェクトのリストア

バックアップしたプロジェクトをHexabaseに戻す場合には `restore` を使います。先ほどバックアップしたZipファイルを指定してください。

```bash
hx projects:restore back.zip
You are about to restore the template to:
  workspace: 開発用
  context: dev
✔ Do you want to proceed? (y/N) · true
Task successfully queued... done
Template file successfully uploaded, project successfully restored
```

プロジェクトのリストアは非同期で行われます。復元には数分〜数十分かかります。

## 注意点

作成されるZipファイルにはパスワードがかかっています。パスワードは非公開になります。

## まとめ

データのバックアップは大事です。定期的なバックアップをお勧めします。

Hexabase CLIでは他にも様々な処理を提供しています。Hexabaseとともに利用してください。

[hexabase\-cli \- npm](https://www.npmjs.com/package/hexabase-cli)
【PHP】条件式「==」と「===」の違い

## 意味

- 「==」
値のみ比較する。型定義までは比較しない

 - 「===」
値と型定義まで含めた完全一致か不完全一致かを判定する。

## 速度
 -  **「===」の方が早い**
     - 「==」は型変換してから比較という順番になるため、大規模なデータを扱うと、速度に差が出てくる。

## まとめ
 - 条件式を使う際は、「===」を使用した方が安全な作りになる。速度も早い
AccessのVBAでActiveDirectoryからユーザーが属しているグループ一覧を取得

# 概要

管理者グループに属しているユーザーなら、管理者用フォームを表示…
といったような条件分岐をしたい場合。

# やり方

参照設定に『Active DS Type Library』を追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/22fb1afc-0188-07a4-26ed-6d9ebcfe8ccb.png)

```vb:Accessファイルを開いているユーザーが属してるグループ一覧表示サンプル
Dim ad_system_info_ As New ADSystemInfo

Dim ldap_ As IADs
Set ldap_ = GetObject("LDAP://" & ad_system_info_.UserName)

Dim group_ As IADs
For Each group_ In ldap_.Groups
    Debug.Print group_.Name
Next
```

# 参考サイトさん

https://tsubotaco.blog.fc2.com/blog-entry-13.html

# バージョン

Windows 10 Pro 22H2 19045.2965
Microsoft Access for Microsoft 365 MSO (バージョン 2304 ビルド 16.0.16327.20200) 32 ビット
OpenCALM-7Bをローカルでいい感じに使うpythonスクリプト

# 概要
サイバーエージェントが公開した日本語LLMの[OpenCALM-7B](https://huggingface.co/cyberagent/open-calm-7b)をWSLでいい感じに使うスクリプトをChatGPTに書いてもらったので残しておきます。
自分はPythonのことほんとに何もわからないでやっていますのでご了承ください。
参考にしたページ
https://note.com/npaka/n/n2185b422a2f2

# 使い方

1. transformerのインストール
    1. `pip install transformers accelerate`
1. モデルのあるリポジトリのclone?（すべてのファイルは必要ないかも）
1. 下記スクリプトをCloneしたフォルダにおいて実行
1. checkpointのロードが終わったら質問を入力してエンター
1. やめる場合はquit

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2341187/06306990-2f5a-8a33-ab1c-58fd0dfb6221.png)

素のtransformerの挙動なので？文章を補完させる形で聞くのがいいらしい。
# コード
```run.py
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

# モデルとトークナイザーの準備
model = AutoModelForCausalLM.from_pretrained(
    "cyberagent/open-calm-7b", 
    device_map="auto", 
    torch_dtype=torch.float16
)
tokenizer = AutoTokenizer.from_pretrained("cyberagent/open-calm-7b")

while True:
    # ユーザーからの質問を受け取る
    question = input("Enter your question (or 'quit' to stop): ")
    
    # ループを抜けるための条件
    if question.lower() == 'quit':
        break
    
    # プロンプトの作成
    prompt = f"{question}\nA:"
    
    # 推論の実行
    inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
    with torch.no_grad():
        tokens = model.generate(
            **inputs,
            max_new_tokens=64,
            do_sample=True,
            temperature=0.7,
            pad_token_id=tokenizer.pad_token_id,
        )
        
    output = tokenizer.decode(tokens[0], skip_special_tokens=True)
    print(output)
```
初心者でも分かるRubyのインスタンスメソッド・クラスメソッドについて



# はじめに

Ruby初心者や。「クラスメソッドとかインスタンスとかなんぞや」って方が理解できるようにしました
クラスの基本文法は理解している前提で說明します。
私も現在Ruby学習中で、あまり理解ができていませんでした。誰かのお助けになれば幸いです。

# 本題

例としてこのようなクラスがあるとします。

```ruby

class Sample
	def self.hello
		puts "Hello!これはクラスメソッドです"
	end

	def hello
		puts "Hello!これはインスタンスメソッドです"
	end
end
```

# インスタンスメソッド

### インスタンス/インスタンスオブジェクト

例のコードをもとに説明するとSampleクラスから.newをして生成したものをインスタンスオブジェクトと呼びます。

```ruby
instance = Sample.new
#insanceはSampleクラスのインスタンスオブジェクトです
```

インスタンメソッドとはインスタンスを生成して初めて実行できるメソッドです。

```ruby
class Sample
	#def self.hello
	#	puts "Hello!これはクラスメソッドです"
	#end

	def hello
		puts "Hello!これはインスタンスメソッドです"
	end
end

Sample.hello # => undefined method `hello' for Sample:Class (NoMethodError)

sample = Sample.new
sample.hello # =>  Hello!これはインスタンスメソッドです
```

インスタンスオブジェクトを生成前にSampleクラスのインスタンスメソッド`hello`を実行するとエラーが発生しました

# クラスメソッド

クラスメソッドとはクラスに紐付いているメソッドであり、インスタンスオブジェクトを生成する前から実行できる（クラスに直接実行できる）メソッドです。
クラスメソッドは通常、クラスの状態や振る舞いを管理するために使用されます。例えば、特定の条件に基づいてインスタンスを生成するメソッドや、クラスの変数や定数を操作するメソッドなどがクラスメソッドとして定義されることがあります。クラスメソッドは通常、メソッド名の前に「self.」を付けて定義されます。

```ruby
class Sample
	def self.hello
		puts "Hello!これはクラスメソッドです"
	end

	#def hello
	#	puts "Hello!これはインスタンスメソッドです"
	#end
end

Sample.hello # =>  Hello!これはクラスメソッドです
```

またselfのプレフィックスはクラスの名前に置き換えることもできます。

```ruby
class Sample
	def self.hello
		puts "Hello!これはクラスメソッドです"
	end

	def Sample.hello
		puts "Hello!これはクラスメソッドです"
	end
end
#上記２つのメソッドはクラスメソッドです
```

# おわりに

今回の記事の他にもDockerやLinux、webの知識について、できるだけ初心者でもある程度理解ができるよう説明した記事がありますのでよければご覧下さい。
[Power Automate/Logic Apps] SharePointコネクタでファイル検索する

# やりたいこと

特定のSharePointライブラリ内で、ファイルを検索したい。
Power AutomateかLogic Appsで実装します。

# 使用するアクション

SharePointコネクタの「ファイルの取得（プロパティのみ）」アクションを使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022607/a3b6f485-3c2e-d0c0-4655-a5579e4e1c83.png)

# フィルターをかける

## フィルター画面の追加

「Add new parameters」ボタンからフィルタークエリ入力画面を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022607/a218e06c-46bd-1d68-adde-447686d36b85.png)

## フィルターの書き方

フィルターの書き方はOData フィルター クエリで記載します。
等しい値を探すには `Eq` 、等しくない値を探すには `Ne` を使います。
フィルターオプションは [ODataのドキュメント（4.5. Filter System Query Option）](https://www.odata.org/documentation/odata-version-3-0/url-conventions/) に記載されています。
ODataバージョンは3が利用されています。

## フィルターで使用するファイル名等

ファイル名等は下記のものをクエリで使用可能です。

|  フィルターで使用するときの名称  |  説明  |  例  |
| ---- | ---- | ---- |
|  FileLeafRef  |  拡張子を含めたファイル名  |  ExampleFile.docx  |
|  FileRef  |  サーバー相対パスを含めたファイル名  |  sites/Playground/Shared Documents/20201231/ExampleFile.docx  |
|  File_x0020_Type  |  	ファイルタイプ  |  docx  |

> [Power Automate to filter files in SharePoint by file name](https://tomriha.com/power-automate-to-filter-file-in-sharepoint-by-file-name/)

## やってみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022607/424765c0-8d08-1efc-bd05-8c4c2990e541.png)

とある案件コードから始まるファイルを探そうと思います。
`startswith` を使ったところ期待通りの結果を得ることができました。

# 注意

* ファイルを探しに行っているドキュメントライブラリにアイテムが5000件以上存在する場合は、ファイルが見つからない場合があるそうです。

# 参考

## ODataバージョン

SharePointのフィルターで使用しているODataバージョンは2023/5時点でversion3になります。
Version4では「○○を含む」のような `contains` を使えますが、今のところSharePointでは利用できません。

## 参考リンク

> [SharePoint \- Connectors \| Microsoft Learn](https://learn.microsoft.com/ja-jp/connectors/sharepointonline/#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E3%82%92%E5%8F%96%E5%BE%97-(%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%AE%E3%81%BF))
> [Power Automate to filter files in SharePoint by file name](https://tomriha.com/power-automate-to-filter-file-in-sharepoint-by-file-name/)
> [URI Conventions \(OData Version 2\.0\) · OData \- the Best Way to REST](https://www.odata.org/documentation/odata-version-3-0/url-conventions/)
#Nginxを使ってPHPでSSH接続するときにパーミッションエラーが出た。

docker上でnginx,php(php-fpm),ubuntuコンテナを作成して、php上からubuntuコンテナにSSHする際にハマったので、備忘録を記載。  
今回は私がハマったところのみを記載するので、基本的なSSH接続方法等はスルーします。  
基本的なSSH接続の方法については以前記載しておりますので、良ければ見てください。

## 今回ハマったエラー
```php
file_get_contents(/home/{ユーザ名}/.ssh/id_rsa): failed to open stream: Permission denied
```
今回はこのパーミッションエラーにハマりました。

## 結論
### /usr/local/etc/php-fpm.d/www.conf PHPのデフォルトユーザを変更しよう！

まず初めに /usr/local/etc/php-fpm.conf をいじって、www.confを参照するように変更  

下の方に下記コードが書かれている(変更前はちょっと間違っているかも。変更済みで見当たらなかったから記憶を頼りに書いています。)
```
# コメントアウトされている
:include=etc/fpm.d/*.conf
```
これをコメントアウトを外して、下記の通りにする。  
最悪見つからなければ一番下とかに下記一文を追記しても良いかもしれない。

```
include=etc/php-fpm.d/*.conf
```
そのあとに /usr/local/etc/php-fpm.d/www.confを編集する。  
※もしもphp-fpm.dディレクトリが無ければ、php-fpm.dディレクトリ，www.confファイルを自作する。

```
user = www-data
group = www-data
```
この *www-data* を秘密鍵の所有者ユーザに変更する。今回の場合は*testphp*ユーザ。  
```php
user = testphp
group = testphp
```

※所有者の確認方法
**ls id_rsa -la** で所有者とグループが表示される  
```
# ls id_rsa -la の結果
#           |所有者  |グループ|
-rw------- 1 testphp testphp 2610 May 17 03:00 id_rsa
```

## エラーの原因
**www-data**ユーザで**testphp**ユーザの秘密鍵を見に行こうとしていて、パーミッションエラーが出ていた(当たり前)。  

phpのexecコマンド等php上からだと上記の**www.conf**で設定されているデフォルトユーザ(www-data)で実行される。  
私はそれがわからず必死にパーミッションを777とかにしていた。  

ちなみに秘密鍵のパーミッションを777にするとセキュリティがガバガバすぎと怒られ、鍵を使ったSSH接続ができなくなる。  
怒られているエラーメッセージ  
```
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0777 for '/home/testphp/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/home/testphp/.ssh/id_rsa": bad permissions
```

## おまけ(ここからは推測なので間違っているかも)
### www.confを直接いじるのはNGかもしれない。
今回私は開発段階で設定ファイルをいじっていたのと、めんどくさかったので直接www.confをいじったが、本来はダメな気がする。  
基本的にwww.confを新たな名前でコピーして、それを編集するというの方法が正しいかもしれない。  
ファイルの頭に**00**とかを付けたら優先的に読み込んでくれそうな気がする。  

### www.confをいじらずに鍵の権限をいじることで行けるかもしれない。
最初は私も鍵の権限をいじる方法を試していたが、なんかうまくいかなかった。  
なんか、www-dataユーザのグループをtestphpと同じにして、色々したらいけそうな気もする。  
そもそも違うユーザの鍵を使ってSSH接続するというのが無理かもしれないが。
Docker上で日本語のvimtutorを起動する

ふと思い立ってDockerでUbuntuを起動してその中で`vimtutor`をやろうと思ったら、日本語が文字化けしたりと思いの外ハマったので、やり方をメモしておきます。

:::note info
ちなみにmacOSなら標準で`vimtutor`コマンドが入っていますし、WindowsでもGit Bashに`vimtutor`が付属しているそうなので、わざわざDockerでやる人は少ないかもしれません。

私は新人にVimを教えるときに「vimtutorで練習するといいよ」と言っているので、実行方法の一環としてDockerでもできるかな？　と試してみたのでした。
:::

## vimtutorとは

`vimtutor`はVimの基本を学べるチュートリアルおよびそれを起動するコマンドです。

`vimtutor`を実行すると、チュートリアルの内容が表示されたVimが起動して、その中で実際に操作しながら学べるようになっています。
チュートリアルの画面自体を操作しながら学べるというコンセプトがなかなか面白いです。今どきのアプリやゲームみたいですね！

普段使うエディタはVS Codeなど好きなものを使うものの、サーバー上での作業などで少なからずVimを触ることもあり、簡単でいいのでちょっと使い方を覚えたいな、という人はぜひとも`vimtutor`をやってみてください（冒頭のコラムで書きましたが、わざわざDockerでやる必要はないです）。

## Dockerで実行する方法

まずDockerで普通にUbuntuを起動します。

```sh
# -i, -t: 標準入力とTTYの割当て（シェルやvimに必要）
# --rm: コンテナを終了したらコンテナを削除する
docker run -it --rm ubuntu:focal /bin/bash
```

bashが起動したら、以下の手順でVimと日本語パックを入れることで、日本語で`vimtutor`が起動できます。

```sh
# vimとlanguage-pack-jaをインストール
apt update
apt install -y vim language-pack-ja

# LANGを日本語に設定
export LANG=ja_JP.UTF-8

# vimtutorを起動
vimtutor
```

日本語で存分にチュートリアルを楽しんでください！

### おまけ

上記を一発でやるワンライナー

```sh
docker run -it --rm -e LANG=ja_JP.UTF-8 ubuntu:focal /bin/bash -c "apt update && apt install -y vim language-pack-ja && exec vimtutor"
```
vim dyld[33099]: Library not loaded: エラー

## はじめに

vimを起動しようとしたらpython関係のエラーが出たのでメモ

```
% vim
dyld[33099]: Library not loaded: /usr/local/opt/python@3.9/Frameworks/Python.framework/Versions/3.9/Python
  Referenced from: /usr/local/Cellar/vim/8.2.3350/bin/vim
  Reason: tried: '/usr/local/opt/python@3.9/Frameworks/Python.framework/Versions/3.9/Python' (no such file), '/Library/Frameworks/Python.framework/Versions/3.9/Python' (no such file), '/System/Library/Frameworks/Python.framework/Versions/3.9/Python' (no such file)
zsh: abort      vim
```

## 原因

根本原因はわからない。pythonを最近アップデートしたからかもしれない。

## 解決

brewでvimをupgradeしたらvimが起動するようになった

```
$ brew upgrade vim
```
[AWS Q&A 365][Batch]AWSのよくある問題の毎日5選 #59

# 1. AWS Batchにおけるジョブスケジューリングとは何ですか？
回答: AWS Batchにおけるジョブスケジューリングとは、ジョブキューに提出されたジョブの実行を管理し優先順位付けするプロセスです。スケジューリングポリシーは、ジョブの優先度、ジョブ間の依存関係、利用可能な計算リソースなどの要素に基づいて、どのジョブが実行されるかを選択する方法を決定します。

# 2. AWS Batchでジョブキューを作成する方法は？
回答: AWS Batchでジョブキューを作成するには、AWS管理コンソール、AWS CLI、またはAWS SDKを使用できます。ジョブキューの名前、キューの優先度、および関連付ける計算環境を指定する必要があります。

# 3. AWS Batchで複数のジョブキューを作成することはできますか？
回答: はい、AWS Batchでは複数のジョブキューを作成することができます。各ジョブキューには独自のスケジューリングポリシーと優先度があり、1つ以上の計算環境と関連付けることができます。

# 4. AWS Batchでジョブキューのスケジューリングポリシーを指定する方法は？
回答: AWS Batchでジョブキューのスケジューリングポリシーを指定するには、キューを作成する際に指定します。スケジューリングポリシーは、ジョブの優先度、ジョブ間の依存関係、利用可能な計算リソースなどの要素に基づいて、どのジョブが実行されるかを選択する方法を決定します。いくつかの事前定義されたスケジューリングポリシーから選択するか、カスタムポリシーを作成することができます。

# 5. AWS Batchにおけるフェアシェアスケジューリングとは何ですか？
回答: フェアシェアスケジューリングは、AWS Batchにおけるスケジューリングポリシーの一つで、フェアシェアアルゴリズムに基づいて各ジョブキューに計算リソースを割り当てます。このアルゴリズムは、各キュー内のジョブの数、各ジョブの優先度、利用可能な計算リソースの量を考慮します。フェアシェアスケジューリングは、時間の経過に伴い、各ジョブキューが公平な割り当ての計算リソースを受け取ることを保証します。
[AWS Q&A 365][Batch]Daily Five Common Questions #59

# 1. What is job scheduling in AWS Batch? 
Answer: Job scheduling in AWS Batch is the process of managing and prioritizing the execution of jobs submitted to a job queue. The scheduling policy determines how jobs are selected for execution based on factors such as job priority, job dependencies, and available compute resources. 

# 2. How do I create a job queue in AWS Batch? 
Answer: To create a job queue in AWS Batch, you can use the AWS Management Console, AWS CLI, or AWS SDKs. You need to specify the name of the job queue, the priority of the queue, and the compute environment(s) that the queue is associated with. 

# 3. Can I create multiple job queues in AWS Batch? 
Answer: Yes, you can create multiple job queues in AWS Batch. Each job queue can have its own scheduling policy and priority, and can be associated with one or more compute environments. 

# 4. How do I specify the scheduling policy for a job queue in AWS Batch? 
Answer: You can specify the scheduling policy for a job queue in AWS Batch when you create the queue. The scheduling policy determines how jobs are selected for execution based on factors such as job priority, job dependencies, and available compute resources. You can choose from several pre-defined scheduling policies or create a custom policy. 

# 5. What is fair share scheduling in AWS Batch? 
Answer: Fair share scheduling is a scheduling policy in AWS Batch that allocates compute resources to each job queue based on a fair share algorithm. This algorithm takes into account the number of jobs in each queue, the priority of each job, and the amount of compute resources available. Fair share scheduling ensures that each job queue receives a fair allocation of compute resources over time.
Reactを学ぶためNext jsを導入する

目的：Reactを学ぶため、Next jsをセットアップする

理由：プロジェクト「study-react」をGitHubにpushするため

準備：Node.js推奨版のダウンロード（同時にnpmもダウンロードされる）
    gitのダウンロード
    typescriptのダウンロード
    

流れ:
ターミナルを開き「yarn create next-app --typescript」と入力
プロジェクト名を聞かれるので好きな名前を入力(study-reactと入力)
その後「cdコマンド」で「C/user/名前/study-react」にディクトリを移動する
「yarn dev」をする

VsCodeで「study-react」を開く
「yarn build」して「yarn start」する

ターミナルで
「git init」
(初期化して「study-react」内のフォルダなどがgit管理下になる）
「git add .」
（変更履歴を記録する対象を追加する、"."は今いるディクトリのファイルすべてを追加すること）
「git commit -m 'コミットのメッセージ'」
（ここで変更履歴のコメントやメモを残す）
「git log」
（今の状況を見れる）

GitHubでリポジトリを立ち上げる
下から2番目をコピーしてターミナルに張り付ける

Vercelでインポートする（これで誰でもサイトが見れる）

↓完成品

https://study-react-two-woad-83.vercel.app/

参考サイト

https://www.youtube.com/watch?v=15WLMqnkPsE&t=897s

https://www.youtube.com/watch?v=qerW4vBftNA&t=1339s

https://qiita.com/hatorijobs/items/1cae1946656ece954c63

https://codelikes.com/git-add/
Gitの力をすべての人に: 効率的なバージョン管理の手引き

## はじめに

世界中のすべての人がGitを使えるようになると、より幸せになれるのではないかと、わりと真剣に思う今日このごろです。

[低レイヤを知りたい人のためのCコンパイラ作成入門](https://www.sigbus.info/compilerbook)で、Rui先生が

> Gitの高度な機能を使う必要はありません。たとえばブランチを使う必要はないはずです。

と述べられていて、「まさにそうだ」と思い、大いに勇気づけられました。

小さなプロジェクトでも積極的にGitを使用しようと思いました。しかし、フルタイムのエンジニアではないため、しばらくするとすぐに忘れてしまいます。毎回思い出す手間が省ければ、もっと効果的に使用できると思います。そのため、ここにメモを残します。このメモが皆さんのGitの活用を気軽に行うための助けになれば幸いです。


## 手順

### 初期化からコミットまで

最初の設定は一度だけ行うため、特に忘れやすいです。しかし、この設定がGitの基礎を築く大切なステップです。

- git init

Gitで管理したいディレクトリ（フォルダ）に移動し、このコマンドを実行して初期化します。これにより、そのディレクトリがGitの管理下に入ります。

- git add a.sh b.txt

次に、Gitが管理するべきファイルを明示的に指定します。全ての変更をまとめて指定するために`git add .`を使うこともできますが、個々のファイルを明示的に指定する方が、何がしているのか一目瞭然です。

- git commit -m "コメントを書く"

なるべく小まめにコミットします。シェルスクリプトなら、「少し変更を加えて動作確認が取れたらすぐにコミット」することを心がけています。

- git commit -A

`-A`ですべての変更をまとめてコミットします。viエディタが起動し、そこでメッセージを入力することができます。`i`キーで入力モードに入り、メッセージを入力した後、`esc`キーでモードを抜け、`:wq`(write & quit)と打ち込むことで保存してコミットできます。

これらの手順を踏むことで、ファイルはしっかりバージョン管理され、変更点を追跡することが容易になります。これはあなたのファイルを安全に保つために大切なステップです。


### 状況確認

Gitは主にコマンドラインで操作するため、「現在の状態」をすぐに把握できません。しかし、以下のコマンドを使うことで、簡単に確認できます。自信を持ってファイルをを管理し、変更を追跡する強力な道具になります。

Gitはコマンドラインで使うので、「いまどうなっているか」が直感的にわかりません。これらのコマンドを用いると、現状把握ができます。

- git ls-files

これはGit版の`ls`コマンドです。Gitが管理対象としているファイルを一覧表示します。これにより、何が管理対象となっているかが一目でわかります。

- git status

このコマンドを使うと、コミット後にどのファイルが変更されたかなどの重要な情報を一覧表示できます。これにより、次に何をするべきかが明確になります。

- git log
- git log -p

これらのコマンドは過去のコミット履歴を表示します。`-p`オプションを使用すると、各コミットで何が変更されたかを詳細に確認できます。

- git diff

このコマンドは、最後のコミットと現在のワーキングディレクトリの間で何が変更されたかを表示します。これは、まだコミットされていない変更を確認するのに特に便利です。

これらのコマンドを活用することで、Gitの現状を正確に把握し、ファイルをより効果的に管理できるようになります。


### 変更

プロジェクトの進行中、管理対象のファイルの名前を変更したり、不要なファイルを削除したりすることがよくあります。そうした変更も適切にバージョン管理するためのコマンドです。

- git mv a.sh c.sh

Git版の`mv`コマンドです。ファイル名を変更しても、以前のコミット履歴は保持されます。ファイルの進化を追跡し続けるための重要な機能です。

- git rm a.sh

ファイルを削除し、管理対象から外すときは、Git版の`rm`コマンドを使用します。これにより、ファイルの削除が適切に記録されます。

- git checkout -- <filename>

何か間違えてファイルを変更してしまった場合、このコマンドで最後にコミットされた状態にファイルを戻すことができます。

- git reset --hard

前回のコミット以降に行った変更を全て取り消します。

これらのコマンドを用いることで、プロジェクトの変更管理はよりスムーズに、より効率的に行えます。

## おわりに

Gitの基本的な使い方について簡単にまとめました。コミットから状況確認、さらにはファイルの変更管理まで、Gitの基本操作をカバーしました。これらの基本コマンドは、たとえ小さなプロジェクトであっても非常に役立ちます。

この記事では意図的に、以下の機能の解説を省きました。

-   ブランチ
-   リモートリポジトリ
-   プルリクエスト／マージリクエスト

個人的な小規模なプロジェクトでは、これらの機能を使わなくてもGitの力を十分に発揮できます。むしろ、小規模なプロジェクトでもGitを使うことは、労力に対する効果が高い使いかただと言えるかもしれません。

Gitを初めて（または久しぶりに）使うときは難しく感じるかもしれませんが、一歩ずつ進めばそれほど難しいものではありません。そして、プロジェクトをより効率的に、より安全に運営するための強力な手段となります。

この記事が、あなたがGitを気軽に使うきっかけになれば幸いです。一人でも多くの人がGitの力を活用することで、より創造的で効率的なコンピュータ利用の世界が広がることを願っています。

### 環境

- macOS Ventura 13.3.1
- MacBook Pro (14-inch, 2021)
CyberAgentの日本語LLMを動かしてみる

# モデルについて
Hugging Face 🤗 上で公開された CyberAgent さんの日本語版 LLM を動かしてみます。CyberAgent さんの Hugging Face 🤗 ページへのリンクを以下に載せておきます。

https://huggingface.co/cyberagent

リンク先へ飛ぶと、以下の画像のように様々なレポジトリが出てきますが、 `open-calm-hoge` となっているレポジトリが日本語版 LLM のレポジトリになっています。 `hoge` の部分はモデルの大きさを表しています。（[レポジトリとモデルのサイズの対応表](https://huggingface.co/cyberagent/open-calm-7b#model-details)）

![https://huggingface.co/cyberagent](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2962238/b818c9e5-ec80-c5be-a6ad-ac0fde12ccb2.png)

# 使用方法
Python の環境を構築しておきます。[PyTorch](https://pytorch.org) と [Transformers](https://huggingface.co/docs/transformers/installation) が最低限入っていれば動くと思います。

```python:公式に紹介されている実行コード + α (主に変更しそうな部分にコメント)
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("cyberagent/open-calm-7b", device_map="auto", torch_dtype=torch.float16)
tokenizer = AutoTokenizer.from_pretrained("cyberagent/open-calm-7b")

inputs = tokenizer("AIによって私達の暮らしは、", return_tensors="pt").to(model.device)  # 入力するプロンプト.
with torch.no_grad():
    tokens = model.generate(
        **inputs,
        max_new_tokens=64,  # 生成する長さ. 128 とかでも良い.
        do_sample=True,
        temperature=0.7,  # 生成のランダム性. 高いほど様々な単語が出てくるが関連性は下がる.
        pad_token_id=tokenizer.pad_token_id,
    )
    
output = tokenizer.decode(tokens[0], skip_special_tokens=True)
print(output)
```

以下のモデルを読み込む際の部分のオプションについて少し紹介します。

```python:モデルを読み込む部分
model = AutoModelForCausalLM.from_pretrained("cyberagent/open-calm-7b", device_map="auto", torch_dtype=torch.float16)
```

`"cyberagent/open-calm-7b"` となっている部分を、[レポジトリとモデルのサイズの対応表](https://huggingface.co/cyberagent/open-calm-7b#model-details)を参照して自分の使いたいモデル名を指定し、変更することができます。（tokenizer の部分も同じものに変更する必要があります。）
また、複数の GPU デバイスを持っている人向けのオプションですが、 `device_map="auto"` となっている場合は、それぞれの GPU デバイスに均等にモデルがロードされますが、 `device_map="sequential"` とすることで、1つの GPU デバイスにロードさせることができます。（使用したい GPU デバイスが決まっていれば、`os.environ["CUDA_VISIBLE_DEVICES"] = "0"`　のように、プログラムの一番最初で指定してあげると良いかもしれません。）
`torch_dtype=torch.float16` となっている部分は、モデルを半精度型の浮動小数点数で読み込んでいます。

一番大きい 7B のモデルを `torch.float16` 型で使用すると、 14~15 GB の GPU メモリを使用しました。
ですが、さらにビット数を落としてモデルを使用することもできます。
[Accelerate](https://github.com/huggingface/accelerate) というライブラリと [bitsandbytes](https://github.com/TimDettmers/bitsandbytes) というライブラリを追加でインストールすることで、 `torch.int8` 型で推論させることができます。
これらのライブラリをインストールすれば、モデルを読み込む部分を以下のように変更するだけで、さらに半分の 8bit へと量子化してくれます。

```python:少し変えたモデルを読み込む部分
model = AutoModelForCausalLM.from_pretrained("cyberagent/open-calm-7b", device_map="auto", torch_dtype=torch.int8, load_in_8bit=True)  # torch_dtype=torch.int8 のところが他の型であっても override されます.
```

こうすることで、同じ 7B のモデルでも、使用する GPU メモリは 8 GB 前後に抑えることができます。（生成の質は若干ですが下がるかもしれません。）

日本語の LLM を手軽に手元で動かせるようになるのはとても嬉しいですね！
CyberAgent さん公開ありがとうございます👏👏👏
テーブルの作成とデータの挿入(SQL)

SQLでのテーブルの作り方を簡単にまとめておく。
PostgreSQL使用。pgAdmin4で実行。
PostgreSQLのすべて：[PostgreSQL 14.5文書](https://www.postgresql.jp/document/14/html/index.html)

### テーブルの作成
テーブル作成の際は、列名、データ型、列の制約を指定する。
テーブル名、列名の最初は必ずアルファベットで始める（数字はNG）。

例

|列名|データ型|制約|
|:-:|:-:|:-:|
|product_id|VARCHAR(10)|PRIMARY KEY|
|product_name|VARCHAR(15)|NOT NULL|
|price|INTEGER||
|product_category|VARCHAR(10)|NOT NULL|

~~~sql:SQL
CREATE TABLE product
(product_id VARCHAR(6),
product_name VARCHAR(10) NOT NULL,
price INTEGER,
product_category VARCHAR(10) NOT NULL,
PRIMARY KEY (product_id)
);
~~~
- データ型

|データ型|内容|
|:-:|:-:|
|INTERGER|整数を入れる数値型|
|CHAR|文字列型、固定長文字列、カッコ内の数字で最大文字数指定|
|VARCHAR|文字列型、可変長文字列、カッコ内の数字で最大文字数指定|
|DATE|日付型|

固定長文字列では文字数が少ない場合、最大文字数になるまで半角スペースで文字埋めされるが、可変長文字列ではそれがない。

- 制約
"NOT NULL"はNULL(データ無し)ではいけないという意味。
"PRIMARY KEY"は列または列のグループがテーブル内の行を一意に識別するものとして利用できることを意味する。
[主キーについて](https://www.postgresql.jp/document/14/html/ddl-constraints.html#DDL-CONSTRAINTS-PRIMARY-KEYS)

### テーブルの削除

~~~sql:SQL
DROP TABLE product;
~~~

### テーブル定義の変更（列追加）

productテーブルに列taxを追加

~~~sql:SQL
ALTER TABLE product ADD COLUMN tax INTEGER;
~~~

### 列名変更
taxをinclude_taxに変更
~~~sql:SQL
ALTER TABLE tax RENAME TO include_tax;
~~~

### 列削除
~~~sql:SQL
ALTER TABLE practice DROP COLUMN include_tax;
~~~

### データ（行）の挿入

productテーブルにデータを追加する。

~~~sql:SQL
BEGIN TRANSACTION;
INSERT INTO product VALUES('p0001', 'カップ麺', '100', 'food');
INSERT INTO product VALUES('p0002', '醤油', '50', 'seasoning');
INSERT INTO product VALUES('p0003', 'バナナ', '200', 'food');
COMMIT;
~~~

__以上！__
【Git】Git cloneが上手くいかない 【Permission denied】

## TortoiseGit を使ったHTTPSでのクローンに失敗

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3337593/4e8a1452-b5e5-25ab-74af-7d9f9df9550b.png)

fatal: could not create work tree dir 'XXXXXXXXX': **Permission denied**





## 環境
Windows11

## 原因
クローン先のディレクトリの権限に問題があった（読み取り専用になっていた）。

## 解決方法
クローンしたいディレクトリを右クリック → プロパティ → セキュリティ → アクセス許可を変更、適用

もしくはコマンドから権限付与

```shell:shell
sudo chmod 777 ディレクトリ
```
dockerコンテナ内でUSBカメラを使う方法 (ホスト：Ubuntu 18.04、コンテナ：Ubuntu 20.04)

# まずはホストOS側で確認

## ホストOSへカメラユーティリティをインストール
```bash
$ sudo apt install v4l-utils qv4l2
```

## ホストOSで "USBカメラ認識" を確認
```bash
$ ll /dev/video*
/dev/video0
/dev/video1
```
または、
```bash
$ v4l2-ctl --list-devices
USB  Live camera: USB  Live cam (usb-0000:00:14.0-5.3):
    /dev/video0
    /dev/video1
```

## ホストOSで "USBカメラ画像" を確認
```bash
$ qv4l2
```
ツールで再生ボタン▶を押して、画像が表示されればOK

----

# つぎにコンテナで確認

## コンテナ内へカメラユーティリティをインストール
```bash
$ sudo apt install v4l-utils qv4l2
```

## コンテナでUSBカメラ認識を確認
- Tips:認識されない場合：
  - udevで認識させる方法
```
udevをインストール
$ sudo apt install udev
udevルールを下記のように作成
SUBSYSTEM=="usb", ATTR{idVendor}=="<vendor_id>", ATTR{idProduct}=="<product_id>", MODE="0666", GROUP="plugdev"
下記でリロード
$ udevadm control --reload-rules && udevadm trigger
```

## コンテナにUSBカメラを認識させる
いちど```docker stop```して、
再度docker runするときに、
下記オプションを追加してrunする。
"--privileged --device=/dev/video0"

## コンテナ内でカメラ画像を確認する方法は前述のホストの場合と同じ
【React】useLocateの使い方

# useNavigateでページ遷移するときに遷移先に値を渡す

## 背景
useNavigateを使って遷移先のページに値を渡すときにpropsが使えないので困った

## 結論
useLocationを使用すればいい

## 値を渡す方法
### 渡し方
```js:App.jsx
import { useNavigate } from 'react-router-dom';
function App(){
    const navigate = useNavigate();
    navigate('/',{state: {message: '成功', type: 'success'}});
}
```
### 受取り方
```js:Rciept.jsx
import { useLocation } from 'react-router-dom'
function Reciept() {
    const location = useLocation();
    const message = location.state;
  return (
    <div>{message.message}</div>
  )
}
```

## オブジェクトを渡す方法
### 渡し方
```js:App.jsx
import { useNavigate } from 'react-router-dom';
function App(){
    const navigate = useNavigate();
    navigate('/',{state: user});
}
```
### 受取り方
```js:Rciept.jsx
import { useLocation } from 'react-router-dom'
function Reciept() {
    const location = useLocation();
    const user = location.state;
  return (
    <div>{user.uid}</div>
  )
}
```
学認 × OpenAM

# 0. はじめに

　学認連携の新規接続やシステム更改をされる際、多様な認証方式と認証連携方式を兼ね備えた
「OpenAM」の導入もご検討いただけると、様々な利点を感じていただけると思います。
　もし本記事をお読みくださったら、ベンダ候補として弊社も加えていただけますと嬉しいです。

# 1. 概要

　学認を含めた大学様のシングルサインオン系として、これまでもShibbolethとOpenAMとを併用（連携）、
という形で導入いただくことが数多くありました。学認との認証連携接続はShibbolethが担い、
Shibbolethでは実現できないような「レガシーアプリとの認証連携接続」や「複雑な認証フローの実現」をOpenAMが担う、という形です。

　もちろん今後も併用の形を採ることも可能ですが、OpenAMは直近のエンハンスにて
「学認との接続・運用に必要となる機能」を搭載しましたので、今後はOpenAMのみを導入いただく形も可能となります。
下図のようにOpenAM単独での導入でも、学認・各種クラウドサービス・レガシーアプリに対し、
強力な認証機能によるセキュアなシングルサインオン（SSO）系を実現できます。
<img width="800" alt="図１＿概要.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316192/0ed78d5d-236b-d888-ca39-0d16bfa5af96.png">

# 2. 学認との接続・運用に必要となる機能の搭載

　学認と認証連携するにあたっては、SAMLプロトコルにより認証連携するというだけでなく、学認特有の機能への対応が必要となります。OpenAMは、この学認との接続・運用に必要となる機能を製品標準機能として搭載しました。
　具体な機能群は、以下の表の通りです。

| 機能 | 説明 | Shibbolethでの相当機能 |
|---|---|---|
| 送信属性同意機能 | SAMLアサーション送信前に、SPに送信する属性についてユーザーに同意してもらう機能 | Attribute Release Consent に相当 |
| メタデータ自動更新機能 | 学認が提供するメタデータから 、SP 証明書などの変更を自動的に読み込んで反映する機能 | metadata-providers.xml および  reload-metadata.sh に相当 |
| SPへの送信値の生成機能 | ユーザーデータに無い値を動的に生成して SP へ送信できる機能 | attribute-resolver.xml に相当 |
| SPデフォルト設定定義機能 | SP作成時に適用する共通設定を定義できる機能 | relying-party.xml の DefaultRelyingParty に相当 |

# 3. 学認連携をOpenAMで実現する利点

　学認連携のためにOpenAMを導入していただく場合、以下のような利点が考えられます。

| 利点 | 説明 | 備考 |
|---|---|---|
| 強力な認証機能 | FIDO2による最新の認証、各種ワンタイムパスワードなどの多要素認証、リスクベースの認証分岐など、OpenAMに標準で備わる強力な認証機能をワンパッケージで利用できます。<br>　例えば、「学内からの接続時はID/PW認証、学外からの接続時は多要素認証」というような構成も容易に実現できます。 | [多様な認証方式＆組み合わせ](https://qiita.com/hoshino_osstech/items/b49c6154f4c38737a9dc) |
| アクセス制御機能 | ユーザーの種類（学生／教職員）、接続元（学内／学外）、連携アプリケーションの種類などに応じて、各アプリへのユーザアクセスの許可／拒否を中央制御できます。 |  |
| サポート範囲と期間 | Webコンテナミドル部分を含め、商用製品としてサポートが受けられます。長期の製品ライフサイクルで安定した運用ができます。 |  |
| GUIによる管理機能 | 連携アプリケーション追加、認証方式の追加設定といった管理業務を、Linuxやvimなどの知識無しにブラウザのGUIベースで行えます。 |  |
| ダッシュボード機能 | ユーザーダッシュボード（アプリケーションランチャー）に、ユーザ毎に利用可能なアプリケーションリンクの一覧をタイル表示できます。 |  |
| OSS製品を日本で開発 | ベースはオープンソースソフトウェアであり、日本のOpenAMコンソーシアムで開発しています。 | [OpenAMコンソーシアム](https://www.openam.jp/)　 |
| コスト抑止 | ライセンスがサーバー台数課金であるため、ユーザー数による費用増加を抑えられます。 |  |

# 4. おわりに

　OpenAMは学認に必要な機能となる機能を標準搭載し、単独で導入いただく場合でも、
学認・クラウドサービス・レガシーアプリに対して強力な認証機能によるセキュアなシングルサインオン系を
実現できるようになりました。もちろん、従来の様にShibbolethとOpenAMの併用（連携）という形を
採ることも可能です。
　学認連携の新規接続やシステム更改をされる際は、様々な利点があるOpenAMをご検討いただけますと幸いです。
WordPressに特化した ChatGPT 「ChatWP」に関連記事を表示するコードを教えてもらう

### ChatWP について
ChatGPT を使って WordPress関連の情報を学んだものが ChatWP です。
以下 [ChatWPのサイト](https://wpdocs.chat/) より
> The WordPress docs chatbot
I'm an AI chatbot that gives direct answers to your WordPress questions. I've been trained on all the official WordPress documentation and will do my best to answer your questions accurately and truthfully.
---DeepL翻訳：WordPressのドキュメントチャットボット
私は、あなたのWordPressに関する質問に直接答えるAIチャットボットです。WordPressの公式ドキュメントをすべて学習済みで、あなたの質問に正確かつ誠実に答えるために全力を尽くします。

サイトのF&Qで
> We use OpenAI's GPT-3.5 embedding and completion APIs

という記述があったので最新のGPT-4ではなく、3.5のようです。

### ChatWP を試してみる
今回はタイトルにあるように、関連記事を表示するコードを教えてもらおうと思います。
ChatWP の使い方はすごく簡単。本家ChatGPT のようにアカウント登録などは不要です。

![スクリーンショット 2023-05-17 12.47.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/f9c52a83-0d91-1236-c6eb-e58cbf1595ca.png)
サイトのファーストビュー下に進むと上の入力画面が出てきます（[入力画面へ飛べるリンク](https://wpdocs.chat/#ask)も貼っておきます）
説明など全て英語ですが、日本語入力にも対応してくれます。

![スクリーンショット 2023-05-17 12.47.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/bcdcd937-e760-fd18-1b7e-94dbf2115ca8.png)
実際、上記のように ChatWP に尋ねてみました。（ちなみに、入力欄右の`random`をクリックすると適当な質問を英語で用意してくれます）

ChatGPT と同じような速さで下記のコードを教えてくれました。リアルタイムで回答を入力していってくれるところは本家の ChatGPT と同じです。
![スクリーンショット 2023-05-17 13.17.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/91f993c6-2a15-8090-f034-1135ad0b0e91.png)

実装コードの概要だけでなく、具体的な説明までしてくれました。
ここまで大枠を作ってもらえると制作時にはすごく助かりますよね！

過信は禁物
---
先程の質問内容に少し変更を加えて、あえて誤字を入れてみました。
`single.phpで、`という文言を省き、末尾に`ください`の入力ミス`くだｓり`を追加しました。

![スクリーンショット 2023-05-17 13.21.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3368730/57dcf40a-3f28-d1a1-e343-d816ddeaa2f7.png)

こんな質問でもコードを生成してくれることに驚きました（しかもコメントアウト付き！）が少し冗長気味な印象です。

あと、コード最終行から2行目（あと真ん中あたりにも）に`wp_reset_query()`でクエリリセットの記述があります。
……そうですね。`query_posts()`は現在非推奨です。

それに、`new WP_Query()`でサブループしているので`wp_reset_query()`ではなく`wp_reset_postdata()`が正しいでしょう。

実際、こちらの[サイト様（取得した情報をリセットする wp_reset_query と wp_reset_postdata - KoMariCote）](https://komaricote.com/wordpress/howto-wp_reset/)にも、
> query_posts() を使って投稿表示をした場合、この wp_reset_query() を使います

と書いてあります。

::: note info 
WordPressのサブループについての説明は割愛しますが、一般的には下記を使用することが多いと思います。
- get_posts
- new WP_Query
- pre_get_posts（アクションフック）

上記の知識が古かったり、誤っていたりしましたらお手数ですがコメントなどで教えていただけますと嬉しいです。
:::

### まとめ
本家の ChatGPT 然りですが、質問内容・指示文（プロンプト）により回答が変わってきます。
実際に使って改めて、生成AIから返ってきた回答を鵜呑みにせずしっかり自分で調査・精査した上で活用するのが大切だと実感できました。

とはいえ、アカウント登録も不要で、プロンプト次第で実装したい機能の大枠（内容によっては全て）を **迅速に構築** してくれるのは素晴らしいですよね。
敵対するのではなく、ちょっと毛色の違う同僚やパートナーとしてうまく接していきたいと感じました。

::: note warn
ChatGPT の特性上、プロンプトはChatGPT の学習ソースとなります。
実際、Samsung でChatGPT を使用して機密漏洩した報道を目にしました。
コードの修正をお願いしようと思って漏洩。なんて悲劇にならないよう、極力社内・社外問わずコードの修正を見てもらおうと思う場合は工夫が必要だと思います。
:::

ここまで読んでいただき、ありがとうございます！


参考にさせていただいた情報
---
[チャットで質問！「ChatWP」ならWordPressのコードをAIが教えてくれる | Web Design Trends](https://webdesign-trends.net/entry/16004)
[取得した情報をリセットする wp_reset_query と wp_reset_postdata - KoMariCote](https://komaricote.com/wordpress/howto-wp_reset/)
[【やじうまPC Watch】Samsung、ChatGPTの社内利用で3件の機密漏洩  - PC Watch](https://pc.watch.impress.co.jp/docs/news/yajiuma/1490904.html)
例え話が好きな人向けのスクラム用語

認定スクラムマスター研修でいくつか面白いたとえ話があったのでメモ。


## ハリボー：ストーリーポイント
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670908/6fa25f39-b3da-ad9e-73f4-889ddbfd7096.jpeg">

ストーリーポイントは時間ではなく、くまのグミの個数で考える。

>くまのグミ・・・グミベア。いわゆるハリボー。 デンマーク語で *vingummibamser*

時間単位で見積もってしまうと、余計な期待値がついてしまう。
たとえばあるタスクを「８時間」と見積もったとする。それは１日あれば終わるだろうか？？
⇒答えはNO。実際はメールチェックや井戸端会議で30%~60%の時間がかかると言われているため

ストーリーポイントはチームのベロシティを測るのが目的。
バーンダウンチャートも「グミが何個残っているか？」で考える。

https://wiki.cantara.no/display/dev/Gummy+Bears

https://agilesutra.wordpress.com/2012/03/16/story-sizing-use-points-gummy-bears-or-earth-days/

グミで例えているのは単に好きだからか。。
グミベアについては面白い記事がありました↓

https://medium.com/@raid.naim_66772/in-pursuit-of-the-gummy-bear-what-a-neuroscientist-taught-me-about-digital-transformation-109d098c7574

## ステーキ：完了の定義
レストランでステーキを注文するとき、焼き加減を聞かれますよね。
バックログアイテムも同じで、必ず焼き加減（＝完了の定義）をチームですり合わせておく事。
基本的にはリリース可能な状態ですが、細かい完了の定義のレベル感を予め決めておくのも面白そうですね。

https://www.braintrustgroup.com/blog/done-how-scrum-is-like-cooking-a-steak/


## 台風予報：プロダクトバックログ
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670908/c15ab60d-0aaf-e99c-33b6-d092586d2c41.png">

画像:https://www.nhc.noaa.gov/aboutcone.shtml


台風の予報円は、直近は限りなく小さく、遠い未来になるにつれ円の範囲は大きくなっていきます。
これをプロダクトバックログに置き換えて考えると、
上にあるアイテムは詳細な見積や分割が十分にされた状態にしておき、
下にいくほどざっくりとした内容でOKということです。

すぐに着手しないアイテムは大まかに見積りしておけば将来の変化に対応しやすくなる、ということですね。

## 豚と鶏：POと開発者
![3478003_s.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670908/a1d281bb-6f5d-fd79-f412-75e4f0ab1023.jpeg)
鶏と豚が一緒に歩いていました。
🐔「今度レストランをオープンしようよ」
🐷「おお、その店の名前は何にするの？」
🐔「『ハム＆エッグス』はどうかな？」
🐷「あかん、あんたは卵を産めばいいけど俺は切り刻まれる」

アメリカの寓話を用いたたとえ話です。
🐔がPOやステークホルダー、🐷が開発メンバーとして考えると、
POが開発メンバーの事情を考慮せずにプロダクトの決定をしている状況を表しています。

https://yamitzky.hatenablog.com/entry/2017/07/13/001440

"The Chicken is involved, but the Pig is committed"

https://www.visual-paradigm.com/scrum/scrum-pig-and-chicken/

ちなみに鶏と豚の話はスクラムガイド初版に記載されていましたが、例えが的確でないという理由で
2011年版では削除されました。

豚と鶏以外の例え話もあるようです。↓

https://www.ryuzee.com/contents/blog/4215



## ボーイスカウトルール：リファクタリング
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670908/bc062d4a-9a5c-7dda-2345-9f6032b01fe6.jpeg">


ボーイスカウトの精神のひとつに「キャンプ場は来た時よりキレイにして帰ろう」というものがあります。

スプリント開発を進める中、整理されていないコメントや見づらい分岐などは見つけたら即直す。
リファクタリングはこまめに行い、技術負債を次のスプリントに持ち越さないようにしましょう。
モブプロやペアプロで実施することで、技術の伝達や理解が深まります。
コーディングに限らず、ドキュメントやレビューのフローなど、整理されていない手順は少しづつカイゼン!

まさに「立つ鳥跡を濁さず」ですね。

https://zenn.dev/naoki_oshiumi/articles/546d9d7b58bc8b
ケーブルのはんだ付けにはフラックスを使え！

# 素人考え休むに似たり
フラックス？アレでしょ？ヤニ入りはんだとかってやつの、「ヤニ」のことでしょ？入ってるんだからいいんじゃないの？別に買うこたーないでしょ。

……と思っていた時期が自分にもありました。

**極めて遺憾であり、大変認識が間違っておりました。**
謹んでお詫び申し上げます。

専門の方から見れば、なにを今更なことを、と思われると存じますが、典型的な反面教師として生暖かい目で見守っていただけると幸いです。

# まずは結果をごろうじろ
## フラックス使用前

**絶対に納品してはいけないレベル。**
ヒドい。
何回やってもうまくいかない。
やり直ししすぎて、既に電子部品を痛めていそうで怖い。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082015/dc9df2c8-37cf-11c9-d114-e839aab68642.png)

## フラックス使用後(+こて先酸化対応)
はい……？誰がやったの？前のと違う人だよね？
**いいえ、私です。**
すこぅしだけ、はんだ盛りすぎかな？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1082015/bbac30dc-75f0-60cd-2989-de62f03ae512.png)

# 所感
プリント基板に部品をはんだ付けするのはそれほど問題ない。それなりに富士山型になって、プロにはかなわないけど、まあ許容レベル。と思っていましたが、ケーブルのはんだ付けがすごい苦手で、どうにもうまくいかねえなあ、と長年思っていました。

イチケンさんに感謝です。
**フラックスは表面張力を弱める** が、カギでした。
[【永久保存版】はんだ付けのやり方を解説します【はんだづけの原理, DIP部品, 表面実装】【イチケン電子基礎シリーズ】RX-802AS](https://www.youtube.com/watch?v=dQ7AUjb1tkA)


きちんと学び、適切な資材・工具を適切に使用することも含めての **"技量"** であると痛感させられた出来事でした。
つうか数百円ケチるなという話だね。

# 使用資材
1. フラックス
白光 FS-200: https://www.hakko.com/japan/products/hakko_fs200.html
2. こて先復活剤
白光 FS-100: https://www.hakko.com/japan/products/hakko_fs100.html
Javaでよくやる文字列操作

思いついたものがあったら追記します。

# 環境
JDK 17

# 参考資料
[StringクラスのJavadoc](https://docs.oracle.com/javase/jp/17/docs/api/java.base/java/lang/String.html)

# 部分文字列を取得する
終了インデックスの文字は含まれ**ない**ことに注意。
```java
String source = "abcdefghijk";
// 開始インデックス（＝0始まり）のみ指定。開始インデックスの文字は含まれる
String sub1 = source.substring(3);
System.out.println(sub1);
// 開始インデックス（＝0始まり）と終了インデックスを指定。
// 開始インデックスの文字は含まれる。終了インデックスの文字は含まれない。
String sub2 = source.substring(3, 6);
System.out.println(sub2);
```

```shell:実行結果
defghijk
def
```

# CSV文字列を分割する（囲み文字無し）
```java:コード
String source  = "aaa,bbb,ccc";
String[] result = source.split(",");
for (String s : result) {
    System.out.println(s);
}
```

```shell:実行結果
aaa
bbb
ccc
```

# CSV文字列を分割する（囲み文字あり）
`'aaa','bbb','ccc'`から`aaa`・`bbb`・`ccc`が欲しい場合。

一番最初と最後の`'`を削除してから、`','`で分割するのがポイントです。

```java:コード
String source  = "'aaa','bbb','ccc'";
// 最初と最後の'を取り除く
String substring = source.substring(1, source.length() - 1);
// ','で分割する
String[] result = substring.split("','");
for (String s : result) {
    System.out.println(s);
}
```

```shell:実行結果
aaa
bbb
ccc
```

# 結合してCSV文字列を作成する（囲み文字無し）
```java:配列で指定
String[] source = {"aaa", "bbb", "ccc"};
String result = String.join(",", source);
System.out.println(result);
```

```java:可変長引数で指定
String result = String.join(",", "aaa", "bbb", "ccc");
System.out.println(result);
```

```java:Listで指定
List<String> source = List.of("aaa", "bbb", "ccc");
String result = String.join(",", source);
System.out.println(result);
```

```java:Stream_APIを利用
List<String> source = List.of("aaa", "bbb", "ccc");
String result = source.stream()
    .collect(Collectors.joining(","));
System.out.println(result);
```

```shell:実行結果（全て同じ）
aaa,bbb,ccc
```

# 結合してCSV文字列を作成する（囲み文字あり）
```java
List<String> source = List.of("aaa", "bbb", "ccc");
String result = source.stream()
    // 「区切り文字,最初の文字,最後の文字」の順に指定
    .collect(Collectors.joining("','", "'", "'"));
System.out.println(result);
```

```shell:実行結果
'aaa','bbb','ccc'
```

# 文字列の置換
```java
String source = "おいしいいちごをたべたい";
String result = source.replace("い", "あ");
// 元の文字列は変更されないことに注意
System.out.println(source);
System.out.println(result);
```

```shell:実行結果
おいしいいちごをたべたい
おあしああちごをたべたあ
```

> 似たメソッドで`replaceAll()`と`replaceFirst()`というものがあります。これらは置換対象を正規表現で指定します。対して👆の`replace()`は単純な文字列一致で置換対象を指定します。

# 変数の埋め込み
`%d`は整数、`%s`は文字列です。

```java
String source = """
    本日の気温は%d度です。
    これは%sです。
    """;
int temperature = 30;
String expression = "夏日";
String result = source.formatted(temperature, expression);
System.out.println(result);
```

```shell:実行結果
本日の気温は30度です。
これは真夏日です。
```

> - `String.format(source, temperature, expression)`でも全く同じことができます。しかし、Java 15で導入された`.formatted()`メソッドの方が読みやすいので、最近のJavaではこちらをよく使います。
> - Java 21では変数を直接埋め込むことができるようになるみたいです（[JEP 430](https://openjdk.org/jeps/430)）。


# 文字コード変換（UTF-8 -> Shift-JIS）
TBD

# 文字コード変換（Shift-JIS -> UTF-8）
TBD