OmniAICreator/Qiita-1.07M huggingface dataset:
【備忘録】sedコマンドを理解する

## 概要

`sed`コマンドは「Stream EDitor」のことです。
Streamとは、Wikipediaでは以下のように記載されています。

> ストリーム（英: stream）とは、データを、比較的小さい単位が連続したものと捉え、上流から下流へ「流れるもの」とみなし、そのデータの入出力・送受信（途中段階を含む）を最小限の滞留とさせ低遅延処理となるように扱う形態を指す。またその操作のための抽象データ型を指す[1]。
https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%88%E3%83%AA%E3%83%BC%E3%83%A0_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)

すなわち、標準入力（stdin）や標準出力（stdout）のエディタが`sed`コマンドです。

## 基本的な使い方

sedコマンドの基本的な使い方は以下の通りです。

```bash
$ sed "{対象となる初めの行（最初からの場合はs）}/{置換前の文字列}/置換後の文字列}/{出現番号（最後までの場合はg）} 入力ファイル名"
```

例えば、以下のような内容が記載されている`example.txt`があります。

```
hello hello
hello world
```

これの`hello`を任意の単語（例えば`hoge`）に置き換えるときは以下のように記述します。

```bash
$ sed "s/hello/hoge/g" example.txt
```

出力

```
hoge hoge
hoge world
```

また、この出力は`example.txt`を書き換えるわけではなく、標準出力されます。


## 用途別使用例

### 変更した箇所だけ表示する

以下のようなファイル`example.txt`があります。
```
helo world!!
```

この`hello`という文字列を`fuga`に置き換えて標準出力するには以下のコマンドを実行します。

```bash
$ sed -n "s/hello/fuga/p" example.txt
fuga world!
```


### パターンマッチに合致する箇所を削除

以下のようにすることで、`hello`を削除できます。
```bash
$ sed "s/hello//g" example.txt
 world!
```


### パターンマッチに合致する行を削除

以下のようにすることで、`hello`を含む行すべてを削除できます。
```bash
$ sed -e "/hello/,//d" example.txt

```

### 電話番号形式の数値だけ表示する

正規表現を用いて、以下のようにします。
```bsah
$ echo 'TEL: 0120-000-000' | sed "s/[A-Z :]//g"
0120-000-000
```

### HTMLから特定のタグの要素を削除する
以下の例では`<td>`タグを消して、表の中身だけ出力しています
```bash
$ curl -X "GET" https://nlftp.mlit.go.jp/ksj/gml/codelist/PrefCd.html | sed -e "s/^ *\(<td>\)* *\(.*\)<\/td><td>\(.*\)<\/td>\(<td>\)*/\2,\"\3\"/g"
```

少し複雑なので、分けて解説していきます。

まず、`sed`の`-e`オプションは複数条件を指定するときに使用するオプションです。
sed文での対象範囲は`s/{hogehoge}/g`という形なので、ここではダウンロードしたHTML全体となります。

ここで正規表現の意味は以下の通りです。
- `^`: 行の先頭
- `*`: 直前のパターンの0回以上の繰り返し
- `\(<td>\)*`: `<td>`と`</td>`で囲まれた部分を0回以上繰り返すグループ
- `*`: 直前のパターンの0回以上の繰り返し
- `\(.*\)<\/td><td>\(.*\)<\/td>`: `<td>`と`</td>`で囲まれた部分の2つのグループにマッチ。それぞれのグループは0文字以上の任意の文字列（任意のデータ）にマッチ
- `(<td>\)*`: <td>と</td>で囲まれた部分を0回以上繰り返すグループ

よって`^ *\(<td>\)* *\(.*\)<\/td><td>\(.*\)<\/td>\(<td>\)*`では`<td></td>`で囲まれた部分を抽出します。

## 参考資料
- https://zenn.dev/peg/articles/72bde0980dde20
- https://qiita.com/shunbaba/items/faf0cf2dbfd4e205e945
windows powershellでgrep コマンドを使う。

翻訳作業をする時、マーク・ダウンでやっていますが、macOSとかLinuxでとても有用は機能は`grep`です。フォルダ内のテキストファイルの中、特定の単語を含めてるファイルと位置するラインNoを探してくれるからです。

たまに翻訳作業をwindowsでやってますが、windowsでは`grep`機能が見つからなったのでとても不便でした。totalcommanderの`find`を用いましたが、これも不便でした。

windows powershellで`grep`見たいのが`select-string`コマンドです。でも、これが手に馴染まないし、`Select-String`というコマンドを使おうとするとよく覚えていませんでした。だから見つけた方法は、powershellの`New-Alias`機能です。

これからはpowershellの`New-Alias`を通じて`Select-String`コマンドに`grep`というのを被る方法です。powershell ターミナルで下のように入力します。

```
New-Alias -Name grep -Value Select-String
```

でもこうすると現在のセッションだけで適用されるしセッションが終わったら効果が消えてしまいます。

powershellのターミナルでセッション・プロフィールを作成します。

```
New-Item -path $PROFILE -type file -force
notepad $PROFILE
```

するとメモ帳が`$profile`の名で開かれてます。ここに

```
New-Alias -Name grep -Value Select-String
```

を入力してセーブして終了します。それで終わりです。

これからはセッションが終わってもAliasが消えなくて、`grep`コマンドを使えます。

参考：https://learn.microsoft.com/ko-kr/powershell/module/microsoft.powershell.utility/set-alias?view=powershell-7.3
PythonでWordをPDFに変換

Word文書をPDFに変換することで、文書がデバイス間で一貫してレンダリングされ、他のユーザーがコンテンツに不正な変更を加えるのを防ぐことができます。さらに、PDFに変換することで、文書を印刷する必要があるときに、印刷の正確さも保証されます。
この記事では、Pythonライブラリを使用してWord Doc/DocxをPDF形式に変換する方法について説明します。

## WordからPDFへの変換のためのPythonライブラリ
使用するPythonライブラリは [**Spire.Doc for Python**](https://www.e-iceblue.com/Introduce/doc-for-python.html) で、Word文書の作成、読み込み、編集、変換を簡単に行うことができます。使用するには、以下のpipコマンドを使ってVS Codeにインストールします。
```
pip install Spire.Doc
```

## PythonでWord Doc/DocxをPDFに変換する
変換を実現するには、単に.docまたは.docx文書をロードし、WordをPDF形式に変換するために**Document.SaveToFile(string fileName, FileFormat.PDF)** メソッドを使用します。
Pythonコード：
```python
from spire.doc import *
from spire.doc.common import *

# Documentオブジェクトを作成する
document = Document()

# Word文書を読み込む
document.LoadFromFile("Input.docx")

# WordをPDF形式で保存
document.SaveToFile("WordtoPDF.pdf", FileFormat.PDF)
document.Close()
```
![WordtoPDF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/6618b443-fe10-b7d8-4943-4814c731db6f.png)


## PythonでWordをパスワード保護されたPDFに変換する
単純にWordをPDFに変換するだけでなく、Spire.Doc for Pythonは変換プロセスを制御するために**ToPdfParameterList** クラスも提供しています。まず生成されるPDFにパスワードを設定し、**Document.SaveToFile (string fileName, ToPdfParameterList paramList)** メソッドを使用してWordを暗号化されたPDFファイルとして保存することができます。
Pythonコード：
```python
from spire.doc import *
from spire.doc.common import *

# Documentオブジェクトを作成する
document = Document()

# Word文書を読み込む
document.LoadFromFile("Input.docx")

# ToPdfParameterListオブジェクトの作成
parameter = ToPdfParameterList()

# 生成されたPDFファイルにオープンパスワードと許可パスワードを設定する
openPsd = "abcd"
permissionPsd = "1234"
parameter.PdfSecurity.Encrypt(openPsd, permissionPsd, PdfPermissionsFlags.Default, PdfEncryptionKeySize.Key128Bit)

# Word文書を暗号化されたPDFとして保存する
document.SaveToFile("EncryptedPDF.pdf", parameter)
document.Close()
```

## Pythonでフォントを埋め込んだWordをPDFに変換する
PDFにフォントを埋め込むことで、文書がさまざまなデバイスで正しく表示され、フォントの欠落による問題が回避されます。これは、カスタムフォントや特殊なグリフを含むドキュメントでは特に重要です。 Spire.Doc for Pythonは、WordをPDFに変換してフォントを埋め込むのに役立つ**ToPdfParameterList.IsEmbeddedAllFonts** プロパティを提供します。
Pythonコード：
```python
from spire.doc import *
from spire.doc.common import *

# Documentオブジェクトを作成する
document = Document()

# Word文書を読み込む
document.LoadFromFile("Input.docx")

# ToPdfParameterListオブジェクトの作成
parameter = ToPdfParameterList()

# 生成されたPDFにフォントを埋め込む
parameter.IsEmbeddedAllFonts = True

# Word文書をPDFとして保存する
document.SaveToFile("ToPdf.pdf", parameter)
document.Close()
```

:pushpin: WordをPDFに変換する際に画像を圧縮して生成されるPDFのファイルサイズを小さくしたい場合は、**Document.JPEGQuality** プロパティで画質を設定することができます。
さらに、**ToPdfParameterList**クラスは、変換中に元のしおりを保持したり、タイトルによって新しいしおりを作成することもサポートしています。
```python
# Wordの見出しからPDFのしおりを作成
parames.CreateWordBookmarksUsingHeadings = True

# Wordの既存のしおりからPDFのしおりを作成する
parames.CreateWordBookmarks = True
```
* * *
赤い透かしを消すには、こちらからトレイルライセンスをお申し込みください。
https://www.e-iceblue.com/TemLicense.html

Python Wordライブラリについてもっと知る：
https://www.e-iceblue.com/Tutorials/Python/Spire.Doc-for-Python/Program-Guide/Spire.Doc-for-Python-Program-Guide-Content.html
Excelファイルをリストにインポートする



本来はライブラリにExcelファイルが保存されたらというトリガーを使いますが、テストするのを簡単にするためにまずはファイルが選択されたらというトリガーで作成してみます。

困ったことが１つ。
自働化って選択肢が出てこない。　Sandbox用のサイトのドキュメントからファイルを選択しています。何で？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/78c88b7f-aa20-1fd9-a3af-f4cedf05cca5.png)

そういえば、左側にもドキュメントがあるので、それをクリックしてファイルを選択します。
ああああ、何故かここでは出てきますね。何でだろう？　MSさんのシステムの構成は理解できません。UIの考え方が私とはとても大きく違うと感じます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/144e8e8a-9134-294e-c7b4-831776a55000.png)

ということで、めでたく実行できそう。

あちゃぁ、いきなりエラーですね。


```Json
{
  "status": 404,
  "message": "The resource could not be found.\r\nclientRequestId: d357a0e3-b9e2-468b-addb-8563f773a27c\r\nserviceRequestId: 6fec5d0b-8ac0-4a49-8276-430235c09029",
  "error": {
    "message": "The resource could not be found."
  },
  "source": "excelonline-jw.azconn-jw-001.p.azurewebsites.net"
}
```

404エラー？？？

う~ん、もしかして「テーブル１」の１が全角だとダメかな？半角にしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/cdc6d2f7-87ed-0924-251a-362888c1b72a.png)

数値を半角にしも同じエラーです。


Excelをもう一度みてみましょう

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c0731cad-e92a-a742-5dd7-0bd1c0b0deab.png)

おおお、ー が違うように見えるけどテキストエディターでは同じみたいに見えます。

ファイル名のころをidで指定していたのが問題だったようです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/9d8a357d-bc6f-50ef-e962-3d8bf40feb9e.png)


さて、修正すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c0547d22-03a9-301c-2e44-6e387e65eb27.png)

:::note alert
Unable to process template language expressions in action '項目の作成' inputs at line '0' and column '0': 'The template function 'formatDate' is not defined or not valid.'.
:::

formatDateはない？　あっ、もしかしてformatDateTimeかな？

```
@{formatDateTime(items('Apply_to_each')?['納期'],'yyyy/MM/dd')}
```

今度はうまくいきましたね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/630e6e9d-ea7b-2d95-6295-59b876f9b2d8.png)

# 全体

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/fe24fbf0-9d82-98af-86c3-80b3fda37cb0.png)

# このトリガーにより、選択したファイルのフローを開始できます。入力: サイトのアドレス、ライブラリの名前。出力: 名前、項目へのリンク、ID。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b0335b8d-f3d3-80ed-9cb9-e58eb9566c23.png)

# 表内に存在する行を一覧表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c0a00557-8132-4ea1-1d0c-bf113a597fb9.png)

# 項目の作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c7eec96d-f53d-ae37-86ea-51cf235b6dac.png)

```
@{items('Apply_to_each')?['営業所']}
@{items('Apply_to_each')?['棚番']}
@{items('Apply_to_each')?['枝番']}
@{formatDateTime(items('Apply_to_each')?['納期'],'yyyy/MM/dd')}
```
meta（facebook）のピクセルコードの確認方法を調べたからメモ

広告効果のトラッキングなどで使う、meta（旧facebook）のピクセルコードですが、新しいビジネスマネージャになったとたん、全然どこにあるかわからなくなったのでメモがてら記事にします。
ちなみに、既存の記事では画面が違うなどで私は全然わからなかった。
いい解説サイトをご存じの方はぜひ教えてください。

取得場所は割とシンプルです。
1. イベントマネージャを開く
2. 取得したいピクセルのページを開く（「◯◯のピクセル」というタイトルで概要ページにリンクがあります）
3. 開いたら、画面中央下の方にある「イベントを追加」をクリック
4. 「新しい統合を追加」をクリック
5. 「Metaピクセル」を選び、「設定」をクリック
6. 「ウェブサイトにコードを手動で追加」を選び「スタート」をクリック
7. 「コードをコピー」という黄緑のボタンをクリック
8. コードの取得はここで完了
9. このあと設定を進めたい人は「次へ」をクリック
10. 「自動詳細マッチング」を設定して、「ピクセルの概要へ戻る」をクリックして完了
11. コードをトラッキングしたいサイトの</head>直前に設置したらイベントの取得が始まります

一応画面のスクショも順次置いておきます。

![スクリーンショット 2024-04-10 15.56.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586941/5fffa963-914f-d4d8-6ab5-981415b6275f.png)
![スクリーンショット 2024-04-10 15.56.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586941/b5a9699b-c1c1-75a9-3623-a486ffad5ce0.png)
![スクリーンショット 2024-04-10 15.56.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586941/e4cac48a-381a-f443-f065-24e3ce93c10c.png)
![スクリーンショット 2024-04-10 15.56.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586941/2695faa7-1653-b847-3ed9-528c2664fcc4.png)
![スクリーンショット 2024-04-10 15.57.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586941/07ee010c-9abd-a0ad-0bd5-3e8276f69cf7.png)
![スクリーンショット 2024-04-10 15.57.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586941/e603a8d2-0686-155a-f234-cf92d4fc7816.png)
![スクリーンショット 2024-04-10 15.57.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586941/b0d95812-8a87-dd24-6ec4-2f5859ce3586.png)

このために1時間は費やしたから賢いみんなはこの記事を読んで10秒で終わらせていただければ幸いです。
秘密の合言葉のためにランダムなひらがな文字列を作る

コマンド
```bash
python -c "import random; print(''.join([chr(random.randint(ord('あ'), ord('ん'))) for _ in range(64)]))"
```
出力例
```
さてえぞゃくなぶんらなぇおぱょたどざへさぶみさぼむたとぴすろくをぎやっとぐおぴをいづぬぬづいぺぞぽがけつふばよわづしおっゐざやる
```
階層構造 JSONの書き方

## JSONとは？
- **JSON**（**JavaScript Object Notation**）は「JavaScript Object Notation」の略で、{} や [] などJavaScriptオブジェクトの表現形式で記述する。
- JavaScriptで使われることを想定したデータ構造なので、JavaScriptと相性が良い。
- Python、Java、PHPなどの幅広い言語でも使われている。JavaScriptなどのクライアント言語とPythonなどのサーバサイド言語間のデータのやり取りで使われることが多い。

## JSONの基本の書き方
- JSONはキーと値がペアになっており、キーは文字列で、必ずダブルクォーテーション（"）で囲む必要がある。
<font color="Red">※文字列をシングルクォーテーションで囲むとエラーになる。</font>
- JSONは {} の中に、"キー"と"値"をコロン（:）で区切って記述する。

```json:
{"key1" : "value1"}
```

カンマで区切ると、キーと値の組み合わせを複数記述できます。
```json:
{"key1":"value1", "key2":"value2", "key3":"value3"}
```

行数が多くなってくると読みにくくなるので、適宜、改行とインデントを加える。
```json:
{
    "key1":"value1",
    "key2":"value2",
    "key3":"value3"
}
```

## JSONの値のデータ型
JSONの値は、文字列、数値、真偽値、null、オブジェクト、配列のいずれかを指定できる。
- 文字列（ダブルクォーテーションで囲む)
- 数値（ダブルクォーテーションで囲まない）
- bool値（true または false）
- 配列
- オブジェクト
- null（ヌル値）

```json:サンプル（文字列、数値、bool値、配列、オブジェクト、null）
{
    "key1":"value1",
    "key2":100,
    "key3":true,
    "key4":["apple","orange","banana"],
    "key5":{
        "area": "tokyo",
        "country": "Japan",
        "date": "2024/04/10"
    },
    "key6":null
}
```

## JSONの階層構造（オブジェクト／配列のネスト）
JSONはネスト（入れ子構造）をサポートしており、オブジェクト内に別のオブジェクトや配列を含めることができる。

#### 例１：値がオブジェクトになっている場合
```json:
{
    "key1":{
        "key1-1":"value1-1",
        "key1-2":"value1-2",
        "key1-3":"value1-3"
    },
    "key2":"value2",
    "key3":"value3"
}
```

#### 例２：値がオブジェクトで、オブジェクトの中にがオブジェクトになっている場合
```json:
{
    "key1":{
        "key1-1":{
            "key1-1-1":"value1-1-1",
            "key1-1-2":"value1-1-2"
        },
        "key1-2":"value1-2",
        "key1-3":"value1-3"
    },
    "key2":"value2",
    "key3":"value3"
}
```
 
#### 例３：オブジェクトが配列になっている場合
```json:
[
    {
        "key1":"value1"
    },
    {
        "key2":"value2"
    },
    {
        "key3":"value3"
    }
]
```

#### 例４：値が配列で、配列の中がオブジェクトになっている場合
```json:
{
    "key1":[
        {"key1-1":"value1-1"},
        {"key1-2":"value1-2"},
        {"key1-3":"value1-3"}
    ],
    "key2":"value2",
    "key3":"value3"
}
```

#### 例５：値が配列で、配列の中が配列になっている場合
```json:
{
    "key1":[
        ["value1-1","value1-2"],
        ["value2-1","value2-2"],
        ["value3-1","value3-2"]
    ],
    "key2":"value2",
    "key3":"value3"
}
```

以上
Stripe PHP SDK Connectの子アカウントの残高を取得する方法

## 概要

StripeにてConnectの子アカウントの残高をPHP SDKを使って取得する方法を簡単にまとめる。

## 方法

下記のようにコードを書くことで残高を取得する事ができる。

```php
$stripe = new \Stripe\StripeClient("stripeのシークレットキー");

// 子アカウント（接続されたアカウント）のIDを指定
$connectedAccountId = 'acct_から始まる子アカウントのID';

// 子アカウントの残高を取得
$balance = $stripe->balance->retrieve([], ['stripe_account' => $connectedAccountId]);

echo $balance->pending[0]->amount; // まだ利用可能になっていない残高
echo $balance->available[0]->amount; // 利用可能になっている残高
```

## 参考文献

https://docs.stripe.com/api/balance/balance_retrieve
Kubernetes超入門 part2 Rancherの導入

前回、kubernetes超入門でクラスタを構築しました。

https://qiita.com/Yuumillar/items/ee7a3ad4d6fd40c080c3

それではkubernetesを使いやすくするために、rancherというGUIを入れてみましょう。

## helmのインストール
helmというのはKubernetesのパッケージマネージャーです。いい感じにデプロイしてくれます。
公式HPの通りで良いですが、下記になります。

別にkubernetes外のPCから操作してもいいのですが、ひとまず前回サーバーにした1台で下記実行していきます。

```sh
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
helm version
```

これでOK。

次にrancherのhelmチャートを追加します。

```sh
helm repo add rancher-latest https://releases.rancher.com/server-charts/latest
kubectl create namespace cattle-system
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/<VERSION>/cert-manager.crds.yaml
helm repo add jetstack https://charts.jetstack.io
helm repo update
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace
```
もしここでunreachable localhost:8080とかになったときは、helmがkuberenetesのURLをうまく叩けていません。~/.kube/configがあるか、ちゃんと正しいサーバーURLか、全サーバーにその設定が入っているか、など確認してみてください。

あとはhelmでインストールするだけです。
```sh
helm install rancher rancher-latest/rancher --namespace cattle-system --set hostname=rancher.your.host --set replicas=1 --set bootstrapPassword=super_strong_password
```

で、ここのhostnameなんですがhostsで設定しておくと良いと思います。
同じネットワーク内にWindowsとかMacとかあれば、そいつのhostsをいじってあげます。
rancher.your.hostを192.168.0.70とか、いま設定している（helmをインストールした）端末のIPにしてあげると、ブラウザでrancher.your.hostを開くとrancherが開けるようになります。

起動確認は以下

```sh
kubectl get pod -n cattle-system -w
kubectl get pod,svc,ingress -A
```

まだrancherを入れただけだと何もできませんが、ポチポチいろいろ押してみると楽しいでしょう。
今回ハマりがあるとすればkubeconfigの設定がちゃんと入っていなかったときだと思います。helmがちゃんと参照できるようにしておかないとうまくいきません。

次回は簡単なアプリケーションのデプロイです。
Java　引数　戻り値

## 戻り値
メソッドの実行結果として返される値のこと

##### 戻り値をもつメソッドの定義
```
public static 戻り値の型　メソッド名（引数リスト) {
 メソッドの処理
 return 戻り値;
}
```

##### 戻り値を利用したメソッドの呼び出し
```
 型　変数名　= メソッド名(引数リスト);
```
```
例）
public class Main {
 public static void main(String[] args) {
   // 戻り値を利用したメソッドの呼び出し
  int result = add(5, 3);
  System.out.println("合計: " + result);
    }
    
  // メソッドの定義
 public static int add(int num1, int num2) {
  // メソッドの処理
 int sum = num1 + num2;
 
  // 戻り値の返却
 return sum;
 }
}

```

#### 戻り値をそのまま使う
```
☆変数に格納したコード

public class Main {
 public static void main(String[] args) {
 　\\addメソッドを呼び出し、その結果を変数`result`に格納
  int result = add(5, 3);　
  System.out.println("Result: " + result);  
 }
 public static int add(int a, int b) {
  return a + b;
 }
}


☆戻り値をそのまま使ったコード

public class Main {
 public static void main(String[] args) {
  System.out.println("Result: " + add(5, 3));
 }
 public static int add(int a, int b) {
  return a + b;
 }
}
```

##### return文
return文は値を戻す役割だけではなく、メソッドの終了も行う

```
public class Main {
　public static void main(String[] args) {
　　System.out.println("Result: " + a());
　}

　public static int a() {
　　return 42;
　　System.out.println("この行は実行されない"); ←この文は実行されず、コンパイルエラーになる
　}
}
```

少しずつ難しくなってきたな:tired_face:
この辺をしっかり理解しないと:joy:
なんかRBENV_VERSIONが勝手に入ってるな。。と思ったらjetbrainsを疑う

SSIA(最近覚えたので使ってみる)

rbenvでは`.ruby-version`より`RBENV_VERSION`の値が優先される。

プロジェクトで`rbenv local 2.6.10`みたいな事をして2.6.10を使おうとしていたら、`ruby -v`で違うバージョンが出てびっくり、ということがあったので備忘録として残す。

# 結論

RubyMineを使っていたのだが、こいつが勝手に`RBENV_VERSION`に値を入れてくる模様。

`Ruby SDK and Gems`で変えられるので、ここを変えたら`RBENV_VERSION`も変えられる。

![スクリーンショット 2024-04-10 15.45.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441085/f3fbcd03-f069-dc3f-1562-718236998eb9.png)
AWSで予算を算出するときに出てくるコスト評価サービスの違い

### なぜこの記事を書いたのか？
AWS-SAA の問題の中で、予算を算出するときに出てくるコスト評価サービスの違いがよくわかりませんでした。
Cost Explorer 、AWS Billing and Cost Management、AWS Budgets 、AWS Cost and Usage Reports の違いを把握して、適切なサービスが選択できるようになるために表にまとめました。


|サービス名|機能|データ粒度|レポート形式|主な用途|コスト|
|:-:|:-:|:-:|:-:|:-:|:-:|
|Cost Explorer|コストと使用状況の可視化、分析|1時間単位|標準レポート、カスタムレポート|コストと使用状況の分析、コストドライバーの特定|無料|
|AWS Billing and Cost Management|請求情報の表示、ダウンロード、支払い|月単位|請求書、明細書|請求情報の管理、支払い|無料|
|AWS Budgets|コスト予算の設定、アラートの通知|1時間単位|なし|コスト超過の防止|無料|
|AWS Cost and Usage Reports|コストと使用状況の詳細なレポート|1時間単位|CSV、JSON|詳細な分析、コストの割り当て|無料|

#### サービスの違いを認識
- Cost Explorer は、コストと使用状況の詳細な分析に強いツールです
- AWS Billing and Cost Management は、請求情報がわかります。リソース作成時にコスト配分タグをつけておくと、プロジェクトごとの費用を正確に把握できます
- AWS Budgets はアラートを出せます。単体ではレポートが出せません
- Cost and Usage Report (CUR) は、AWS コストと使用状況データを詳細に分析するためのツールです。Cost Explorer と似ていますが、CUR はレポートをCSV 、JSON で入手するため、他のAWS サービスなどと連携して使う必要があります
JLCPCBの3Dプリントサービスを使ってみた

豊橋技術科学大学ロボコン同好会，回路班のGavadyです．JLCPCBの3Dプリントサービスを利用したので，そのレビューをしていきます．
# 背景
ロボットの組み立てや基板の取り付けで[電動の精密ドライバー](https://www.amazon.co.jp/gp/product/B099DT6MLH/ref=ppx_yo_dt_b_asin_title_o05_s00?ie=UTF8&th=1)を使用しているのですが，私の持っているものには，ナットを回すビットがないんです．ロボットでは，場所的にボルトを回すスペースがないことがあるので前々から不便だと感じていました．
以前のブログで，JLCの3Dプリントサービスについて調べたときに，ナット回し用のビットを作れるのではないかと思いやってみました．

# JLC3DPとは？
JLCPCBのサブブランドである[JLC3DP](https://jlc3dp.jp/?source=JLCPCB-top-productbar)では，様々な方法・材料の3Dプリントが0.3ドルから行うことができます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586033/2a074bac-1316-90b5-dc3b-8bf7c226d2e4.png)


# 設計
ドライバー側の内径と，他のビットの外径をノギスで計測し，M3用のナットドライバのデータシートを参照しながら設計しました．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586033/fc44daf2-97af-8a34-9ecd-82fa49a1e9af.png)

# 発注方法
3Dプリントサービスの発注方法はとても簡単です．
まず，3Dデータをアップロードします．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586033/a835e71f-86ba-c0af-a71c-94eae229d443.png)
次に製造方法と材料の選択です．今回は，比較のために3種類発注します．
まず一つ目は，SLAのCBY Resinです．![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586033/aa6f44c6-8508-3552-cd30-4004acd4c6e1.png)
こちらは最安値の0.3USDで製造可能です．

二つ目は，MJFのPA12-HP Nylon Blackです．![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586033/edf27f8a-755d-cd18-30b7-34e8ef775b96.png)

三つ目は，SLM（金属）です．金属に関しては，ほか二つとデザインルールが異なっており，細い部分が印刷しにくいということだったので，一部設計を変更しています．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586033/16969d87-d2f9-0b04-7ee7-795b75527ab8.png)

クーポン等をうまく使って11.31USDで購入しました．また，3Dデータをシェアすると，7USDのクーポンをもらうことができます．

# 実際に届いた物
実際に届いた物がこちらです．上から順に前章の一つ目，二つ目，三つ目です．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586033/f8d83236-f7b3-8dfb-6373-f10933cbe051.png)

細かく見ていきます．
写真を見て何か気が付くかもしれませんが，銅色のテープが巻かれています．これは，材料の収縮によって設計したときの寸法よりも小さくなっているため，ドライバーにはまらなかったからつけています．大体0.2mmほど小さくなっています．それ以外は，設計通り．ちゃんとナットを回すことができます．

SLAのCBY ResinとMJFのPA12-HP Nylon Blackは，使用すると少しずつ樹脂が削らて行く感覚があります．これは仕方のないことですが，値段を考えると摩耗してなくなるくらい使ってからまた購入しても痛くなさそうです．
金属のほうは，当たり前ですが頑丈です．まったく摩耗する気配がありません．

# 感想
今回の発注を通して感じたことですが，材料の収縮を予測するのが難しいです．3Dプリンタが近くにあれば，何度も挑戦して収縮の感覚をつかむことができますが，こういった発注はそううまくいきません．収縮を予想して大きく作ってしまうと，そこまで収縮しなくてやすりで削る必要が出てきたり，そのままの寸法で発注して小さくなることもあります．これらは仕方のないことなのですが，やっぱりぴったりできてくれると嬉しいですね．
それでも，値段のことを考えればとても便利なサービスで間違いないです．
Java基本用語の備忘録【随時更新】

# 初めに

「プロになるJava」という書籍でJavaの勉強を始めたが、初心者なもので用語をよく忘れてしまう。そこで忘れそうな知識を整理しようと思った。

# 整理

<b>クラス</b>
基本単位の1つ。データのルールを決める仕組み。

<b>メソッド</b>
処理をひとまとめにしたもの。Javaはメソッドを呼び出すことで処理が進む。
```java:メソッドの呼び出し
値.メソッド名()
値.メソッド名(引数)
```

<b>オーバーロード</b>
メソッド名が同じでも異なる引数を受け取るメソッドを用意すること。そのため引数の区別も重要。

<b>シグネチャ</b>
「メソッド名・受け取る引数・戻り値」の種類をあわせたもの。

<b>基本型・プリミティブ型</b>
メソッドを呼び出せない。
| 型 | 値の種類 |
|:-:|:-:|
|`int`|整数|
|double|実数|
|boolean|論理値|
|char|文字|


<b>参照型</b>
クラスを含める基本型以外の型。メソッドを呼び出せる。

<b>API</b>
クラス単位で機能をまとめて、他のプログラムから呼び出せるようにした"部品"のこと。

<b>ライブラリ</b>
APIをまとめたもの。

```java:API例
java.time.LocalDateTime.now()
```
ここで、

|`java`|パッケージ|
|:-:|:-:|
|`time.LocalDateTime`|クラス|
|now()|メソッド|

である。`java.time.LocalDateTime.`などのパッケージ名まで含めたクラス名を完全修飾名と呼ぶ。

<b>staticメソッド</b>
クラス名を指定して呼び出すメソッドのこと。

```java:staticメソッド
クラス名.メソッド(引数)
```

<b>インスタンスメソッド</b>
値に対して呼び出すメソッドのこと。

```java:インスタンスメソッド
値.メソッド(引数)
```

<b>オブジェクト</b>
基本型以外の値。具体的には、クラスに基づいて生成されたデータのこと。オブジェクトはメソッドを呼び出せる。オブジェクトはクラスの実態である（→インスタンス）。

<b>インスタンス</b>
クラスから見たときのオブジェクトのこと。インスタンスは「実態」を意味する。

<b>インスタンス化</b>
オブジェクトを生成すること。


<b>命名規則</b>
クラスやメソッドの命名ルール

|要素|規則|例|
|:-:|:-:|:-:|
|クラス|単語の頭文字のみ大文字|`String`, `SampleForm`|
|メソッド|先頭の文字は小文字、単語の頭文字は大文字|`main`,`setSize`|
|変数|メソッドと同様の命名規則|`button`, `sampleText`|
|定数|すべて大文字、単語と単語はアンダースコアで区切る|`BLUE`、`TYPE_INT_RGB`|
|パッケージ|全て小文字|`projava`、`javax.swing`|

<b>ジェネリクス</b>
扱う型を`<型>`のように囲んで指定する記法。また以下の例のように`names`から型を予想できる場合、`<String>`とすべきところを`<>`と省略できる。これをダイヤモンドオペレータと呼ぶ。

```java:ジェネリクス
var names = List.of("yamamoto", "kishida", "sugiyama")
var authors = new ArrayList<>(names)
```

<b>イミュータブル</b>
オブジェクトの内容を変更できないこと。例えば`List.of`はイミュータブルである。
Java　メソッド 引数

```
public class Main {
 // メソッドA
 public static void methodA() {
  System.out.println("メソッドA");
   // メソッドAからメソッドBを呼び出す
   methodB();
  }
  // メソッドB
 public static void methodB() {
  System.out.println("メソッドB");
  }
  
 public static void main(String[] args) {
  // mainメソッドからメソッドAを呼び出す
    methodA();
 }
}
```
`main() →　methodA() →　methodB()`
の順番で実行される
mainメソッドより上に他のメソッドが定義されていても、プログラミングは必ずmainメソッドから動き始める。

## 引数
メソッドを呼び出す際に渡す値
#### なぜ必要か
①データの受け渡し
メソッド引数を使用することで、メソッド内で処理するために必要なデータを渡すことができる。メソッド内で外部のデータを使う場合や、結果を返す場合に有用。

②再利用性と柔軟性
メソッド引数により、同じメソッドを異なるデータで呼び出すことができる。これにより、コードの再利用性が向上し、柔軟性が増しま。たとえば、同じメソッドを異なる数字で呼び出すことで、様々な計算が可能です。

③機能の独立性
メソッドが引数を受け取ることで、そのメソッドは他のコードと独立して動作できる。このため、特定の機能を持つメソッドが汎用的に使いやすくなる。

④可読性と保守性
メソッド引数は、メソッドの目的や機能を明確にするのに役立つ。メソッド呼び出し時に渡される引数を見ることで、そのメソッドが何を行っているか理解しやすくなる。また、引数の型や名前が明確になっているため、コードの保守性が向上する。
シリアルポート通信の傍受

今ではレガシーポートとなってしまったシリアルポートだが現場ではまだまだ使われており、ときに受信してデータを取り出さなければならないことがある。機器が古すぎて通信仕様書が手に入らないこともあるし、受信だけの一方通行の垂れ流しならまだいいが双方向だとこちらから正しく問い合わせないとまともに返ってこないのでお手上げだ。リプレースであれば既存機器間の通信を傍受すれば手がかりを得られるだろう。今回はそんな場面に遭遇したので覚書として残しておく。

### com0comのインストールと設定

https://qiita.com/yaju/items/e5818c99857883a59033
Setupでは例えば物理ポートがCOM5だった場合、Virtual Port Pair 0をCOM10, 11、Pair 1をCOM20, 21のように設定してuse Ports classは全てチェックを入れてApplyする

### comleak.pyの準備
https://www.rouge.gr.jp/~fuku/tips/python-comleak/

pyserialのインストール
```
> python -m pip install pyserial
```
:::note info
※以下は上記リンク先のコードを転載させていただいてます。port = serial.Serial(port=s, baudrate=115200, write_timeout=0.05) のbaudrateは実際の機器にあわせて9600などに変更してください。
:::
```comleak.py
#!/usr/bin/python3
# -*- coding: utf8 -*-
# comleak.py v1.0 written by fuku
#
# Usage: comleak.py SerialDevice1 SerialDevice2 [..]
#   ex(Windows): python3 comleak.py COM4 COM10 COM12
#   ex(Linux): comleak.py /dev/ttyS3 /dev/ttyS9 /dev/ttyS11
#   ひとつのシリアルポートに出力されたデータを他のシリアルポートにも流す。
#

import sys, time
import serial

argv = sys.argv     # コマンドライン引数を取得する。

# シリアルデバイス名のリストを作成する。
deviceList = []
for s in argv[1:]:
  if not s in deviceList:
    deviceList.append(s)
deviceCnt = len(deviceList)

# 下記の場合は中断する。
# ・デバイスの数が不足している
# ・デバイス名に重複がある
if deviceCnt < 2 or deviceCnt != len(argv) - 1:
  print('Usage: comleak.py <Ser0> <Ser1> [..]')
  exit()

# 指定されたシリアルポートをすべて開く。
ser = {}
for s in deviceList:
  try:
    port = serial.Serial(port=s, baudrate=115200, write_timeout=0.05)
    ser[port] = b''
  except:
    print("Error: %s can't open." % s)
    exit()

ports = ser.keys()  # 開いたシリアルデバイスをリスト化する。

try:    # ^C をキャッチするため try にする。
  while True:
    # 全シリアルデバイスを読み込む。(データが到来していれば)
    for p in ports:
      ser[p] = p.read_all()

    # 到来したデータを全デバイスに出力する。(自デバイスを除く)
    for p in ports:
      data = ser[p]
      if data != b'':
        for q in ports:
          if q != p:
            try:
              q.write(data)
            except serial.serialutil.SerialTimeoutException:
              pass  # 読み込む準備が出来ていないデバイスはスキップ*する。

    time.sleep(0.1)   # 100ms 待つ。
except KeyboardInterrupt:
  pass

for p in ports:
  p.close()
```
### comleak.py の実行（以下の4）
https://www.rouge.gr.jp/~fuku/tips/serial-sniffing/
```
> python .\comleak.py COM5 COM10 COM20
```
止めるときは Ctrl + C で

### Ratatoskrのインストール（以下の2）と設定、傍受（以下の6）
https://www.rouge.gr.jp/~fuku/tips/serial-sniffing/
上記で設定した場合、機器をCOM11、RatatoskrをCOM21に接続して傍受する（COM10, 20は物理ポートのCOM5を介して通信する）

### Ratatoskrの使い方
最初はよくわからないと思うが、上部のGATE_00Xを右クリックしてポートや通信速度を設定した後、これ自身がトグルボタンになっておりクリックして接続、もう一度クリックして切断になる。また、接続した状態で下部のSend file Pathの右の[...]ボタンで送信したいデータの入ったファイルを選択して[Send]ボタンでデータを送信できる。

![Ratatoskr_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56191/bf5e70e3-d7f1-f5e1-9ee7-1017a1c9e4af.png)

実は今までなるべく実環境に近い方がよいだろうという考えもあり、PC2台をシリアルケーブルとUSB変換ケーブルでつなぎ、各々でテストプログラムを動かして開発していた。しかし、これを使えば1台で済むしクラウドの仮想環境で構築すればどこでもシリアル通信プログラムのテストが可能になる（つまり寝っ転がったままできる）のだ。

以上
ちょっとAlmaLinuxでのコマンドを確認したいなをDockerで実現する

## 概要、趣旨
ちょっとAlmaLinuxのコマンドを試したい、確認したい
けどMacだと仮想環境の用意も手間だし、AWSに環境を作ったこともない

そんなことありませんか
Dockerを使えば簡単に環境が作れます

すぐに作れて、コンテナを削除すればすぐいちからやり直せます

## 用意するファイル

``` Dockerfile
# 基本イメージとしてAlmaLinuxの最新版を使用
FROM almalinux:latest

# ユーザー名とパスワードのための環境変数
ARG USER_NAME
ARG USER_PASSWORD

# AlmaLinuxのパッケージ管理システムを更新し、必要なパッケージをインストール
RUN dnf -y update && \
    dnf -y install sudo passwd vim wget net-tools iputils iproute bash-completion && \
    dnf clean all

# 一般ユーザーの作成
RUN useradd -m ${USER_NAME} && \
    echo "${USER_NAME}:${USER_PASSWORD}" | chpasswd && \
    echo "${USER_NAME} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/${USER_NAME}

# 作業ディレクトリの設定
WORKDIR /home/${USER_NAME}

# コンテナ起動時に実行するコマンド
CMD ["/bin/bash"]
```

``` docker-compose.yml
version: '3.9'
services:
  almalinux_app:
    build:
      context: . # Dockerfileが置かれているディレクトリのパス
      args: # build時の引数
        USER_NAME: user # ここに一般ユーザー名を設定
        USER_PASSWORD: password # ここにユーザーのパスワードを設定
    container_name: almalinux_custom_container
    tty: true
    volumes:
      - ./home:/home/user # ホストとコンテナ間でディレクトリを共有（任意）
```

## 使い方
お好みの環境で下記コマンドを実行してください
``` shell
docker-compose up -d --build
```

私はIntellijを使用してDockerを管理しています
コンテナが立ち上がったらお使いの環境や、`docker exec` コマンドでコンテナの中に入ってAlmaLinuxを使用することができます


## 解説

肝となっているのは
`AlmaLinuxのパッケージ管理システムを更新し、必要なパッケージをインストール`
というところです

DockerでインストールするLinux環境には通常ログインして使用するようなパッケージがインストールされていません
これをインストールすることによってあたかも仮想環境かのように使用することができます
この部分を `自分好みにカスタマイズ` してご利用ください

## 免責
私はこれをローカルでのコマンドの確認などに使用しているのであまり複雑なことは検証していません
通常インストールするAlmaLinuxとのパッケージの差の検証も行っていません
ModuleNotFoundError: No module named '_tkinter' の時の対処法

macOSを使っている著者が、tkinterを使って遊ぼうと思った時に、タイトルのエラーにでくわしました。
めっちゃ簡潔に、このエラーを解決した手順を記しておきます。

```bash
$ brew install tcl-tk
(中略)
```
でインストールしたtinkerについて、以下のエラーが出ました。

```bash
$ python3
Python 3.12.2 (main, Feb  6 2024, 20:19:44) [Clang 15.0.0 (clang-1500.3.9.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>import tkinter
(中略)
ModuleNotFoundError: No module named '_tkinter'
```

調べたところ、よくあるバージョンの食い違いエラーだったみたいです。
具体的にはPythonとtkinterとのバージョンの食い違いです。
```bash
$ python3 --version
Python 3.12.2
```
このPythonに合わせたtkinterをインストールします。
```bash
$ brew install python-tk@3.12.2
```
これで解決しました。

あんまり意義のない記事かと思いますが、質より量かと思って残しておきます。
【Unity】Debug.Log で StackTrace を活用してみる。(そのメソッドの実行元を知る)

この記事は特定のメソッドが
様々な場所から実行されている場合に
実行元を辿る事が出来るログを出す方法を
提案する記事です。

サンプルコードを載せて
その解説をします。

***


```Csharp:サンプルコード

public class LogTest
{
    int count = 23;
    string text = "Hellow World!!";

    public void ShowLog()
    {
        try
        {
            throw new System.Exception();
        }
        catch (System.Exception e)
        {
            Debug.Log("count: " + count + ", text: " + text + ", Hierarchy is \n" + e.StackTrace);
        }
    }
}

```

では解説していきます。

実行元を特定するのは
e.StackTrace の場所です。

例えば次のようなログが出力されます。

```Csharp:出力されるログ
count: 23, text: Hellow World!!, Hierarchy is 
  at LogTest.ShowLog () [0x00000] in C:\Users\User\Test4\Assets\LogTest.cs:10 
UnityEngine.Debug:Log (object)
LogTest:ShowLog () (at Assets/LogTest.cs:14)
ClassA:Start() (at Assets/ClassA.cs:12)
```

このログを見ると
ClassA の Start メソッドから
実行されていることが分かります。

ClassA の Start メソッドが
他の場所から実行されているならば
その情報も知ることができます。
Raspberry PiとeLabFTWを用いた電子実験ノート構築

# はじめに
紙で実験ノート整備すると事後の管理が非常に面倒です。検索はできない、どこに行ったかわからなくなる、過去の研究データを探すことができなくなるなど問題だらけ。電子版実験ノートを用意すればデータの保管や検索は容易になりますが、市販のソフトウェアを購入するにもコストがかかる。
そこで、無料・オープンソースの電子実験ノートeLabFTWとRaspberry Piを用いて、低コスト（1万円くらい）で実験ノート環境を整備したので、備忘録がてら共有する。
あくまで私がやったことを書いておくので、参照は自己責任で。

本記事はRaspberry Piを触ったことがない初心者でもトライできることを目指して書いてみます。

## 用意するもの
・Raspberry Pi4 4GB版
・SDカード（32 GB以上推奨。画像等も保存することを考えると、256GBや512GBを使用するのも良い）

## 実装手順
1. Raspberry PiへのOSインストール
2. Docker環境の構築
3. eLabFTWのインストールと実行
4. eLabFTWの初期設定
5. eLabFTWの改造

## Let's Try!
### 1.Raspberry PiへのOSインストール
1.1 [公式サイト](https://www.raspberrypi.com/software/)からOSイメージをダウンロードする
記事執筆時点のImagerのversionは1.8.5であった。WindowsPCに管理者権限でインストールした。
1.2 Operating Systemは"Raspberry Pi OS 64-bit"を選択。SSH接続をEnableにしてSDカードにOSを書き込んだ。
1.3 書き込んだSDカードをRaspberry Piに挿入し起動。このとき、Raspberry Piは有線LAN接続しておいた。Raspberry PiのIPアドレスを確認し、SSHの設定を実施。(証明書が面倒なのでPWにした。)
1.4 手元のWindows PC (VS Code)経由でRaspberry PiにSSH接続できることを確認した。


### 2. 推奨環境の構築
基本的にはeLabFTWの公式HPに従ってインストールすれば良い。Raspberry PiのOSアップデートやapt, apt-getのアップデートは済ませておく。
2.1 依存関係パッケージのインストール
eLabFTW公式ページにStrongly recommended dependenciesとして上がっているパッケージをインストールする。
```
sudo apt update
sudo apt-get update
sudo apt install curl dialog borgbackup #curl dialog borgbackupのインストール
```
2.2 Docker環境の構築
Docker公式ページに従ってDocker環境を構築する
```
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo apt-get install docker-compose-plugin #docker compose pluginのインストール
```

::: note alert
docker-compose-pluginのバージョンに注意。うっかりv1.x.xをインストールすると、eLabが動作しない。
:::


### 3. eLabFTWのインストールと実行
#### パッケージのDLとインストール
[公式HP](https://doc.elabftw.net/install.html)記載の通りに実施する。
```
curl -sL https://get.elabftw.net -o elabctl && chmod +x elabctl
sudo mv elabctl /usr/local/bin/
elabctl install
```
イントラで使う分には、オレオレ証明書で良い。

#### YAMLの書き換え
- タイムゾーンを規定している場所が３ヶ所あるので
PHP_TIMEZONE=Asia/Tokyo
TZ＝Asia/Tokyo (これが２ヶ所ある)
と書き換える

- URLの書き換え
SITE_URL=https://raspberrypi.local
などにする。RaspberryPiの設定にあわせる。

#### elabFTWの起動
```
sudo elabctl start # elabFTW, MySQLコンテナのビルド
sudo elabctl initialize # MySQLの初期化
```

これで起動準備完了。https://raspberrypi.localで起動できるはず。
【コツコツ学習】UtilityクラスとStaticメソッドについて

# Utilityクラスとは？

Utilityクラスは、共通の処理をstatic領域にまとめて、簡単に処理を呼び出すためのクラス 

特徴としては以下の内容です

- staticメソッドとstatic変数
- インスタンス化できない
- 状態を持たない

# Staticのメリットは何か？

### インスタンスを生成せずに呼び出せること
インスタンス生成にかかるオーバーヘッドがなくなるので、インスタンス生成に時間がかかるクラスに有効です
そのため、頻繁に呼び出されるユーティリティメソッドはよくstaticメソッドとして実装されます

### 状態に依存しないことを保証できること
与えられた引数のみでメソッドの挙動が決まります（振る舞いが変わらない）
つまり副作用が発生しません

# Staticを利用するか否かの判断軸

### インスタンス毎に持つ意味があるかどうか
インスタンスごとに持つ意味がなければstaticメソッド、あればインスタンスメソッドにすべき

### オーバーライドされる予定がない
オーバーライドを前提としたメソッドは、インスタンスメソッドとして定義する必要がある（staticはできない）

### 状態に依存しないかどうか
属性の参照・変更がなく、引数と戻り値のみで完結する場合のみ使うべき（振る舞いが変わらない場合）
インスタンスの値を変更しなものかですね

## 参考
https://qiita.com/uhooi/items/f32e20750d2fb0f2da46
Azure Data Engineer Associate (DP-203) を取得しました

# Azure Data Engineer Associate とは
[この辺](https://learn.microsoft.com/ja-jp/credentials/certifications/azure-data-engineer/)を参照ください。

# 教材
1. Microsoft Learn:[コース DP-203T00--A: Microsoft Azure でのデータ エンジニアリング](https://learn.microsoft.com/ja-jp/training/courses/dp-203t00)
    - 公式の学習サイトです。
    - データ分析系の製品を一通り学習できます。Synapse Analyticsに偏っているのが気になります(試験ではそれ以外の製品も問われます)。
    - これだけで試験に受かるのは難しいと思います。
1. Udemy:[Practice Exams | Microsoft Azure DP-203 Data Engineering](https://www.udemy.com/course/practice-exams-microsoft-azure-dp-203-data-engineering/)
    - 問題集です。
    - 他者の受験記で紹介されていましたので購入してみました。
    - 問題数が多く知識の底上げにはなりましたが、少し使いにくいです。例えば、問題が何の製品の事を指しているのか説明がない。回答に対する説明が公式ドキュメントの文章そのままであったり、問題の主旨から外れていたりで、自分で正しい内容を探す必要があります。試験対象外の製品も含まれていたりします。
1. Microsoft Learn:[コース DP-203T00--A: Microsoft Azure でのデータ エンジニアリングプラクティス評価](https://learn.microsoft.com/ja-jp/credentials/certifications/azure-data-engineer/practice/assessment?assessment-type=practice&assessmentId=49&practice-assessment-type=certification)
    - 問題集です。
    - 用意された数十問からランダムで50問出題します。3周程度で全ての問題が出題します。
    - 上記のUdemyとは傾向が異なりますので、この問題集もおさえておいた方が良いです。

# 感想
- 試験は難しいと思います。上記教材通りの問題は数問でした。
- 試験中は[Microsoft Learn](https://learn.microsoft.com/ja-jp/)を見ることができますので、かなり助かります。ただ、試験アプリのブラウザが特別なものを使用しているためページ内の検索(Ctrl+F)ができません。ページ内の文章量が多い場合は探すのに苦労します。
進め方としては、1周目は[Microsoft Learn](https://learn.microsoft.com/ja-jp/)を使わず解き、少しでも不明点があれば、振り返り用のチェックを入れておく。2週目は不明点な問題を中心に[Microsoft Learn](https://learn.microsoft.com/ja-jp/)を使って解きました。あまりにも不明点が多く[Microsoft Learn](https://learn.microsoft.com/ja-jp/)を使って調べるのに時間を要し、時間ギリギリとなってしまいました。
- 試験アプリの品質が良くなく、試験終了後にフリーズしてしまいました。試験監督によりアプリの再起動をしてもらいましたが、再起動後の画面がなぜか試験途中の問題(且つ未回答)が表示し、困惑しました。結果的にはシステムの方では回答済み扱いとなっていたため合否の影響はありませんでした。
chimaki-2b-baseは『雪国』の冒頭をどうトークナイズするのか

[K-walk](https://k-walk.co.jp/)という会社が「[chimaki-2b-base](https://huggingface.co/K-walk/chimaki-2b-base)」という日本語Gemmaモデルを[リリースした](https://www.niikei.jp/931859/)ので、トークナイザを試してみることにした。

```
>>> from transformers import AutoTokenizer
>>> tkz=AutoTokenizer.from_pretrained("K-walk/chimaki-2b-base")
>>> print(tkz.convert_ids_to_tokens(tkz("国境の長いトンネルを抜けると雪国であった。","夜の底が白くなった。")["input_ids"]))
['<bos>', '国', '境', 'の', '長い', 'トンネル', 'を', '抜け', 'ると', '雪', '国', 'であった', '。', '<bos>', '夜の', '底', 'が', '白', 'くなった', '。']
```

残念ながら、日本語トークナイザとしてはボロボロだ。特に「抜け」「ると」のあたりは、単語の切れ目を完全に無視していて、日本語における言語処理としては話にならない。元の[gemma-2b](https://huggingface.co/google/gemma-2b)のトークナイザを、何も考えずにそのまま使ってしまったのだろう。残念だ。
GitHub CLIでテンプレートからPRを作成する

## 概要

GitHub CLI で PR を作成する際に、リポジトリにあるPRテンプレートを利用したいケースがありました。この時の手順メモです。

以下の2つを紹介します。

1. テンプレートをそのまま利用する場合
2. テンプレート内の変数を書き換えたい場合

## 前提

 - gh version 2.46.0 (2024-03-20)
 - 記事内でPRテンプレートのファイル名は `pull-request-template.md` とします。

## 内容

### 1. テンプレートをそのまま利用する場合

```bash
git pr create --template pull-request-template.md 
# --template or -T でPRテンプレートのファイルを指定します
```

注意事項として、指定するファイルはコマンドを実行するディレクトリに存在する必要があるということです。つまり以下のように**パスを含めた指定はできません。**

```bash
git pr create --template .github/pull-request-template.md
# ...略...
# 実行すると以下のようなエラーが出ます
template ".github/pull-request-template.md" not found
```

`.gihub/` 配下にテンプレートを置き、`gh` コマンドの作業はプロジェクトのルートディレクトリで実施する人も多いと思いますが、注意いただければと思います。

### 2. テンプレート内の変数を書き換えたい場合

CIの中で GitHub CLI を使って自動で PR を作成しているケースを想定します。このようなケースでは、チケットのURLなどテンプレート内の変数を自動で書き換えてPRを作成できたら便利です。

色々調べましたが、`sed` 等のコマンドを使いテンプレートの文字列を置換するのが素直で確実なやり方のようです。　　
私が調べた範囲では、GitHub CLI でそのまま実現できる方法はありませんでしたが、もし別の方法ご存じの方いましたらコメントください🙏

GitHub Actions 等の CI で使うことを想定したPR作成の流れは以下となります。

1. テンプレートから置換した文字列を中間ファイルに出力
2. 中間ファイルの文字列からPRを作成

```bash
TICKET_URL="https://xxx"
# PRテンプレート内の ${TICKET_URL} を一行上で設定した TICKET_URL で置換
sed "s|\${TICKET_URL}|$TICKET_URL|g" .github/pull-request-template.md > tmp-pull-request-template.tmp
# --body-file オプションを使う
gh pr create \
  --base main \
  --head your-branch-name \
  --title "Your PR Title" \
  --body-file tmp-pull-request-template.tmp
```

ポイントは以下です。

 - `gh pr create` コマンドでは `--body-file` (or `-F`) オプションを使う
   - `--template` は元のテンプレートファイルを利用するオプションであり、置換した後のPRテンプレートのファイルからPRを作りたいため
 - PRテンプレートから `sed` で置き換えた内容を中間ファイル（例：`.tmp`）として出力する。あらかじめ `.tmp` は `.gitignore` に追加しておく
   - GitHub Actions からこのコマンドを実行した時、`tmp-pull-request-template.tmp` ファイルがプロジェクト配下に新規作成されるため、未コミットのファイルが残っているという趣旨のワーニングが出ます。余計なワーニングは混乱を招くだけなので、`.gitignore` されている拡張子で作成するようにします。
   - またはCIのプロセスで中間ファイルを削除しても良いです

## 参考

 - [GitHub CLI | Take GitHub to the command line](https://cli.github.com/manual/gh_pr_create)
Macでcronにdateコマンドの結果を使いたくてハマった話。

こんにちは、ひらきちです。

時々、cronで実行したいプログラムの引数で、
dateコマンドの実行結果（例えば今日の日付（2024/04/09など））
を与えたいことって、ありますよね？

これがなかなかうまくいかない！！
なんかいつもハマる！

今日も例によって、Macでハマりました。
備忘録的にメモとしてQiitaに記事を残しておきます。

# Macでcronにコマンドの実行結果を使いたい場合
```
35 11 * * * python hoge.py "$(date -v-1d +\%Y/\%m/\%d)"
```

# （参考）Linuxでcronにコマンドの実行結果を使いたい場合
```
35 11 * * * python hoge.py `date -d "1 day ago" +%Y/%m/%d`
```

# 悩んだ軌跡
- Linux系だとバッククオーテーションを使うと、コマンドの実行結果を引数に使える
- でもMacでは許容されなくて、ハマってしまった（MacはFreeBSD系（Unix系）ということでLinuxとはちょっと違うらしい）
- そこで（流行りの）chatGPT 3.5に6回ほど質問して解決できました
- しかし、chatGPTも平気で嘘をつく（ハルシネーション）ので、何度も質問することに
- 解決できてよかった（笑）

# 参考記事
https://qiita.com/setonao/items/85435d5f7c480425ba95

まぁ次は同じことに出会ったら、
サクッと片付けられれば良いなぁと思いながら、
この記事を閉めます。

以上！
My sql サーバー起動　

Mysql2::Error::ConnectionError: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) (Mysql2::Error::ConnectionError)

というエラーがたびたび出てくる。
MySqlをつながげるための解決方法のうちの1つとして。`mysql.server start`をターミナル上に打ち込むと解消することが多い。
Amazon SNS メール通知で日本語が文字化けした話

# はじめに
Amazon SNS メール通知機能を使用した際、日本語が文字化けしました。
同じ事象に遭遇し困っている方の参考になれば幸いです。

# 構成
1. CloudWatch Logs ロググループにサブスクリプションフィルタを設定し、文字列 "ERROR" を検知します。
1. Lambda 関数をトリガーし、SNS を使用してログの内容をメール通知します。Lambda 関数では Boto3 の[ SNS.Client.publish ](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/sns/client/publish.html)を使用して SNS メール通知します。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3516261/42305b74-57a4-98a7-5a19-dd4cd79cbe9a.png)

# 発生した事象
通知されたメール本文が以下のように文字化けしました。
以下の例の場合、「清水」の「清」１文字だけ文字化けしており、メール本文に同様に存在する他の「清」の字は文字化けしていませんでした。

![キャプチャ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3516261/b8c8184f-6fb6-8c1b-61e2-230cb8c199f9.png)

# 原因
Amazon SNS では、本文に UTF-8 エンコーディングを指定しており、かつ Content-Transfer-Encoding が 7bit という仕様となっています。
このため、経由するメール転送エージェントによっては、情報が欠落し文字化けが発生する場合があります。
Amazon SNS ではメールのエンコード方法が指定できないため、本事象が発生しうる挙動となります。

# 解決策
## 解決策1
Amazon SNS で通知する内容には 7bit の ASCII 文字列のみを使用する。
つまり日本語は使用せず英語のみ使用する。

## 解決策2
日本語を使用したい場合、Amazon SNS の代わりに Amazon SES を使用する。
Amazon SES では、以下のようにエンコーディングとして ISO-2022-JP を指定することができます。
ご参考：[Boto3 SES/Client/send_email](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ses/client/send_email.html)

~~~Python
response = client.send_email(
    Source='送信元メールアドレス',
    Destination={
        'ToAddresses': [
            '送信先メールアドレス',
        ]
    },
    Message={
        'Subject': {
            'Data': 'メール件名',
            'Charset': 'ISO-2022-JP'
        },
        'Body': {
            'Text': {
                'Data': 'メール本文',
                'Charset': 'ISO-2022-JP'
            }
        }
    }
)
~~~

以下のように文字化けを解消することができました。

![キャプチャ.2PNG.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3516261/3d2324fb-222f-6691-db51-eef621882466.png)
Slackでの勤怠連絡をワンクリックで済む様にした

# 前置き

弊社では、勤務するエンジニアの大多数がリモートワーカということもあり、日々の業務の開始と終了の連絡をSlackを使って行なっています。
ワークスペース内に「勤怠連絡板」チャンネルがあり、そこで各自が業務開始や業務終了の連絡をするわけです。
![Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090428/bab2812c-4617-9ecb-c139-5fafccee8298.png)

ただ、毎日「開始します」や「終了します」といったメッセージを手入力して投稿することになるので、ちょっと手間に感じます。
「なんか簡単に済ませられるよい方法がないかなー」と思っていたところに、同僚の投稿したQiita記事が目に留まりました。

https://qiita.com/wanawana/items/771d4da3860547262ca8

なるほど、ワークフローを作れば簡単に仕組み化できそうです！

# 作った
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090428/5d7ef72f-382c-a872-708b-16cc0c0687fe.png)
「勤怠連絡板」チャンネルの関連リンクに「開始連絡する」というリンクと「終了連絡する」というリンクを追加しました。
それぞれ、1回クリックするだけでワークフローが実行され、業務を開始 or 終了した旨の連絡が自動で投稿されます。
![slack2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090428/9516bb82-93cf-b62b-90b8-19278c3ebbb0.png)

勤怠連絡がらくちんになりました。

# 社内の反響
- ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090428/da5c1edf-9511-492e-bbe1-e9508fc93243.png)
- ワークフローが連続投稿する形になることで投稿間の行間が狭まり、目視での稼働状況の確認がしやすくなりました
- 突発で休暇を取得するなどの連絡は従来通り手入力で投稿するのでむしろ目立つ様になり、他の投稿に埋もれにくくなりました

# 作り方
[前述した記事](https://qiita.com/wanawana/items/771d4da3860547262ca8)の二番煎じですが、作成手順に差分があるので記載します。
なお、ワークフローの作成には、対象のワークスペースがSlackの有料プランに加入している必要があります。

1.Slackの左側のバーから「その他」→「自動化」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090428/23860c23-1f22-8bfc-2e13-44add8519b06.png)

2.「ワークフロー」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090428/1687f48f-7d9f-59a9-c63b-74da78f80629.png)

3.「ワークフローを作成する」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090428/b5277172-cb90-5f7f-064c-20740140f230.png)

4.「ゼロから始める」→「Slack 内のリンクから」→「続行する」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090428/2d5f735d-fbf9-98ed-1027-74605431bb03.png)

5.ワークフロービルダーが立ち上がる
- 右側の選択肢から、「メッセージ」を選択する
- 「チャンネルへメッセージを送信する」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090428/41393d55-8cad-5063-240f-5aac66134c08.png)

6.送信するメッセージの作成画面が立ち上がる
- 送信先のチャンネルを選択する
- 「変数を挿入する」から、「このワークフローを使用した人」を挿入し、メッセージを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090428/7db57c58-ac83-5e48-553f-8fedc799d2ba.png)

7.ワークフロービルダーの「完了」を選択→アイコン・ワークフロー名・説明を入力して「公開する」を選択する

8.ワークフローがワークスペース内に公開され、所属メンバーの全員が使える状態になる。ワークフローの実行用URLが同時に発行されるので、それを「勤怠連絡板」チャンネルの関連リンクに追加する

9.手順を繰り返して、「開始連絡する」ワークフローと「終了連絡する」ワークフローをそれぞれ作成する

10.完了！
raspberrypie zero2wをROTORHAZARDでミラーとして使う方法

FPV計測システムのROTORHAZARDを扱い始めて分かりにくかった所なんかを覚書程度に書いていこうかと思います。
といってもだいたいは凡ミスですぐ導入できたんですけどね(´･ω･`；)

ラズパイzero2wにプライマリ同様にpython及びrotorhazardインストール
今回 LED用に使うので必要なプラグインも導入しておきます。
この時点でipアドレスを固定しておくといちいち探しにいかなくていいのでオススメ。
あとはプライマリの方でセカンダリーを認識させるおまじないを記述
src/server/にあるconfig.jsonファイルにある"GENERAL"記述に下記を追加

"SECONDARIES": [{"address": "192.168.1.2:5000", "mode": "mirror",}],

(ipアドレスの部分はzero2wのipアドレス)
これで保存後再起動してあげるとzero2wもプライマリと同じ動きをしてくれます。
プライマリの詳細設定にあるステータスにも繋がっているzero2wの情報も表示されるのでそこでも確認できます。

と、まあこんな感じでざっくりの説明ですが、ここの使い方も含めてボチボチと書いていこうかと思います。
[Power Automate] SharePoint list の新規 item をメールでお知らせする

# はじめに

List に追加されたアイテムのお知らせに Power Automate を使ってみましたが、いろんな Q&A サイトやブログを検索しながらかなりの試行錯誤してしまったので、備忘録として調べた内容をまとめておきます。他に良い方法などあれば教えてください。

# SharePoint list の新規 item をメールでお知らせ

まずは全体像から。Get items で list のアイテムを条件付き（24 時間以内に作成）で読み込んで、Apply to each で 1 つずつメール送付します。

![スクリーンショット 2024-04-10 113728.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/5cb02582-7f4e-ac65-3a96-5d683fa7603d.png)

:::note
メールでなくても Teams の Channel にポストしてもいいですね（今回は行いません）
:::


# 24 時間以内に作成という条件

「サイトのアドレス」と「リスト名」は伏せますが、大事なのはフィルタークエリ。

![condition.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/5d825c57-2bc3-d5b0-9f3a-3e74fac60417.png)

今回は「作成日時」を元にフィルターをかけますが、変数名（？）がわからなかったので、フィルターなしで実行した結果の（JSON 形式）から見つけました。

フィルタークエリですが、ge: ~ より大きい を使用します。日付を指定する場合はこんな感じ

```
Created ge 2024-04-10T00:00:00Z
```

フィルタクエリについてはこちらのページを参考にさせてもらいました👇
参考：[（Power Automate）OData フィルタで日時を指定する方法について](https://iyemon018.hatenablog.com/entry/2020/10/12/081000)

## 日付の決め方

日付を動的（実行日時を基準に）決定させるところで、少し悩んで検索しまくりましたが、結果的には以下の式に。

```
formatDateTime(addDays(utcNow(), -1), 'yyyy-MM-dd')
```

1. `utcNow()` で現在（実行されるとき）の日時を取得
1. `addDays()` で -1 日、すなわち 24 時間前の日時に
1. `formatDataTime` でクエリに使える文字列に変換

という感じです。

:::note
キャプチャ画像だと見にくいのですが、式の前後に ' があることにご注意を。ここで30分ほど解かしてしまいました。直書きするとこんな感じです。

Created ge '@{formatDateTime(addDays(utcNow(), -1), 'yyyy-MM-dd')}'

:::

これで 24 時間以内に作成された item が取得できます。

# あとはメールで送るだけ

![email.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/a52d03a1-cce3-3a01-853d-6f5adcdc2d9b.png)

です。

# まとめ

item が作成されたタイミングで送付という方法もあると思いますが、手動で入力する List なので、作成し始めてから項目を全部埋めるまで時間もあるだろうし、少しして変更するかもしれないので、24 時間区切って送付したかった、ということで、今回の Flow となりました。

今回は日付を実行日時を基準に決定するところではまりました。同様の Flow を作成したい方の参考になりましたら幸いです。
【ChatGPT＋DALL-E3】“policy”でもなく、描画を拒否られる。なぜ？


　どうも、カーブミラーです。

　今回は、“policy”でもなく、描画を拒否られる、という話を書きます。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はありません。あしからず。
:::

　まずは、
　　ChatGPTのニュース。

　以前から
　　OpenAIが
　　　アナウンスしていた
　　　　プラグインの廃止ですが、
　　　　　設定から、ベータ機能タブが
　　　　　　なくなりました。

　今後、
　　プラグインは使えません。

　使っていたプラグインの代わりは、
　　GPTsが用意されている可能性が
　　　ありますので、そちらを
　　　　探してみてください。
***
　次のニュース。

　こちらも
　　OpenAIからのものです。

　GPT-4 Turbo with VisionのAPIが、
　　一般に公開されました。

　このAPIによって、
　　ChatGPT有料版の
　　　機能の多くを
　　　　アプリに取り込むことが
　　　　　可能になります。

　まぁ、これは
　　開発者向けの
　　　ニュースですけどね😅

　詳しくは
　　こちらを。
[【朗報】gpt-4-turbo API が使用可能に](https://twitter.com/shota7180/status/1777809655600906520?t=bFhHcHjr0r2qAqKGMDsXbw&s=19)
***
　さて、
　　本題です。

　セッションを続けていくと
　　Prompt上では
　　　問題ありそうにないのに、
　　　　DALL-E3からは
　　　　　拒否されることが
　　　　　　ありますよね。

　再試行を
　　何度繰り返しても
　　　やはりダメで、
　　　　ChatGPTに尋ねても
　　　　　理由はわかりません。

　“policy”とか
　　メッセージがあれば、
　　　“何かに引っ掛かったんだな”と
　　　　わかるんですけどねぇ😅
***
　この原因が
　　どうやら、
　　　セッションでの依頼で
　　　　DALL-E3に、“policy”で
　　　　　引っ掛かった記録が残り、
　　　　　　次の依頼が似たような
　　　　　　　場面の際に弾くのでは
　　　　　　　　ないかと疑われます。

　一度、“policy”に引っ掛かったら
　　確実に違う依頼を出す必要が
　　　あるのではないか、と。

　そうした場合、私は
　　Promptをコピって
　　　新たなセッションを開き、
　　　　Promptをペーストして
　　　　　実行してます。

　イケる可能性があるので。

　セッションを変えると
　　別の依頼として
　　　受け付けてもらえるのです。

　もちろん、
　　そのPromptに
　　　“policy”に引っ掛かる部分が
　　　　ある場合は、ダメですけどねw

　この“policy”に
　　引っ掛かる言葉としては
　　　いろいろとありますので、
　　　　ここには書きません😅

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
cscの作法 その485

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
datatableを、csv出力せよ。

# サンプルコード

```
using System;
using System.Text;
using System.IO;
using System.Data;
using System.Data.Common;
using System.Linq;

namespace App
{
	class Program {
		static void Main(string[] args) {
			DataTable dt = new DataTable();
			dt.Columns.Add("No", typeof(int));
			dt.Columns.Add("Name", typeof(string));
			dt.Columns.Add("Age", typeof(int));
			dt.Rows.Add(1, "太郎", 20);
			dt.Rows.Add(2, "次郎", 15);
			dt.Rows.Add(3, "三郎", 10);
			Encoding enc = Encoding.GetEncoding("Shift_JIS");
			using (StreamWriter sr = new StreamWriter("dt.csv", true, enc))
			{
				foreach (DataRow row in dt.Rows)
				{
					sr.WriteLine(string.Join(",", row.ItemArray));
				}
			}
		}
	}
}
```

# CSVファイル

```
>type dt.csv
1,太郎,20
2,次郎,15
3,三郎,10

```

以上。