OmniAICreator/Qiita-1.07M huggingface dataset:
RaspberryPiのピンアサインをAAで

Raspberry Piのピンアサインをコードのコメントに入れておこうと思ったら見つからなかったので、作った。
(みんな適当にコピペして使うといいと思う。)

```
+-----------------------------------------------------------------+
|                 Raspberry Pi 40pin - pin assign                 |
+-----------------+------+------+------+------+-------------------+
|3V3 power        |*-----| (01) | (02) |-----*| 5V power          |
|GPIO 2 (SDA)     |*-----| (03) | (04) |-----*| 5V power          |
|GPIO 3 (SCL)     |*-----| (05) | (06) |-----*| Ground            |
|GPIO 4 (GPCLK0)  |*-----| (07) | (08) |-----*| GPIO 14 (TXD)     |
|Ground           |*-----| (09) | (10) |-----*| GPIO 15 (RXD)     |
|GPIO 17          |*-----| (11) | (12) |-----*| GPIO 18 (PCM_CLK) |
|GPIO 27          |*-----| (13) | (14) |-----*| Ground            |
|GPIO 22          |*-----| (15) | (16) |-----*| GPIO 23           |
|3V3 power        |*-----| (17) | (18) |-----*| GPIO 24           |
|GPIO 10 (MOSI)   |*-----| (19) | (20) |-----*| Ground            |
|GPIO 9 (MISO)    |*-----| (21) | (22) |-----*| GPIO 25           |
|GPIO 11 (SCLK)   |*-----| (23) | (24) |-----*| GPIO 8 (CE0)      |
|Ground           |*-----| (25) | (26) |-----*| GPIO 7 (CE1)      |
|GPIO 0 (ID_SD)   |*-----| (27) | (28) |-----*| GPIO 1 (ID_SC)    |
|GPIO 5           |*-----| (29) | (30) |-----*| Ground            |
|GPIO 6           |*-----| (31) | (32) |-----*| GPIO 12 (PWM0)    |
|GPIO 13 (PWM1)   |*-----| (33) | (34) |-----*| Ground            |
|GPIO 19 (PCM_FS) |*-----| (35) | (36) |-----*| GPIO 16           |
|GPIO 26          |*-----| (37) | (38) |-----*| GPIO 20 (PCM_DIN) |
|Ground           |*-----| (39) | (40) |-----*| GPIO 21 (PCM_DOUT)|
+-----------------+------+------+------+------+-------------------+
```

オリジナルは公式で
[Raspberry Pi hardware - GPIO and the 40-pin Header](https://www.raspberrypi.com/documentation/computers/raspberry-pi.html)
「あなたの愛はパラダイス」SSD1306でランダム表示(STM32C011J4M7)



「あなたの愛はパラダイス」SSD1306でランダム表示(STM32C011J4M7)


Arduino STM32 oled ssd1306 STM32C011


x 過去ログを見よ


目的
OLEDのテスト
一応、仮想VRAM方式(白黒)



いろいろ

40年記念、ビューティフル・ドリーマー
2月11日に見たよ!!


結果


![o_cop946.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/42b06e3b-dce9-8ad6-7c7f-4c0275955080.jpeg)



プログラム




```c++


//有機ELのSSD1306でランダムに点を描画
//秋月のOLEDとアイテンドウの売り切れ?OLEDのアドレスは3C
//SSD1306_RAND_C011_1


//ヘッダー
#include <Arduino.h>
#include <Wire.h>


//定義
#define MAX_PAGE                   (7)
#define MAX_COL                    (127)

#define COMMAND_MODE               0x80 // continuation bit is set!
#define DATA_MODE                  0x40

#define SET_COLUMN_ADDRESS         0x21 // takes two bytes, start address and end address of display data RAM
#define SET_PAGE_ADDRESS           0x22 // takes two bytes, start address and end address of display data RAM

#define SET_MEMORY_ADDRESSING_MODE 0x20 // takes one byte as given above
#define HORIZONTAL_ADDRESSING_MODE 0x00


//I2Cに配列を転送する
void write_s(uint8_t *str1, uint8_t len1) {

  Wire.beginTransmission(  0x3c  );

  for (int ii = 0; ii < len1; ii++) {

    //一文字出力
    Wire.write(*str1 ++);

  }//for

  Wire.endTransmission();

}//write_s


//セットページアドレス
void setPageAddress(uint8_t start, uint8_t end)
{
  uint8_t databytes[6] = {COMMAND_MODE, SET_PAGE_ADDRESS, COMMAND_MODE, start, COMMAND_MODE, end};
  write_s(databytes, 6);
}//setPageAddress


//セットカラムアクセス
void setColumnAddress(uint8_t start, uint8_t end)
{
  uint8_t databytes[6] = {COMMAND_MODE, SET_COLUMN_ADDRESS, COMMAND_MODE, start, COMMAND_MODE, end};
  write_s(databytes, 6);
}//setColumnAddress


//セットメモリーアドレシングモード
void setMemoryAddressingMode()
{
  uint8_t databytes[4] = {COMMAND_MODE, SET_MEMORY_ADDRESSING_MODE, COMMAND_MODE, HORIZONTAL_ADDRESSING_MODE};
  write_s(databytes, 4);
}//setMemoryAddressingMode


//初期化
void setup() {

  delay(3000); //not Delete (絶対消すな)(消しちゃィゃーん)

  //I2Cのポートの変更
  Wire.setSDA(19); //PA10
  Wire.setSCL(18); //PA9

  //I2Cの初期化
  Wire.begin(); //C011
  delay(200);

  //SSD1306の初期化スペル(魔法)
  //0x80,0x8d,0x80,0x14,0x80,0xAF
  write_s( (uint8_t*) "\200\215\200\024\200\257", 6);
  delay(100);

  //セットメモリーアドレシングモード
  setMemoryAddressingMode();

}//setup


//メインループ
void loop() {

  uint8_t buff_a[((128 / 8) * 64)]; //バッファー
  memset(buff_a, 0, ((128 / 8) * 64) ); //バッファーのクリア

  //ランダムにドットを200点打つ
  int x, y;
  for (int loop_count1 = 0; loop_count1 < 200; loop_count1++) {

    x = random(128);
    y = random(64);
    buff_a[x + (y / 8) * (128)] |= (1 << (y & 7));//ドットに点を打つ

  }//for loop_count1

  //範囲の設定
  setPageAddress(0, MAX_PAGE);  // all pages
  setColumnAddress(0, MAX_COL); // all columns

  //データの配列の定義
  uint8_t databytes[2] = {DATA_MODE, 0x00};

  //128x64の再描画
  for (int icount = 0; icount < ((128 / 8) * 64); icount++) {
    databytes[1] = buff_a[icount];
    write_s(databytes, 2);
  }//for icount

  delay(1000);//1秒待つ

}//loop



```
パラメーター、引数についての簡単な単語メモ

当初は引数、パラメータの意味をごちゃごちゃにして使っていので、用語について簡単にメモします。
値渡しや参照渡しについても書いています。

## パラメータ、仮引数
関数に定義されている、関数の中で使う変数名のこと。
関数定義側で表記されている、()の中に指定されている、変数名。
```C#:パラメータ.cs
private int Sum(int intX) //←これがパラメータ
{
    int intY = 0;
    return intX + intY;
}
```
 
## 引数、実引数
関数呼び出し側で指定する値のこと。関数に渡す実際の値のこと。
パラメータで指定されているデータ型の値を渡す必要がある。
ちなみに英語ではargumentという。
```C#:引数.cs
private void DoSomeyhing()
{
    Sum(1);//←これが引数
}
```
 
## オプションパラメータ、省略可能引数(オプション引数)
関数、コンストラクタ、インデクサで、初期値が既に設定されているパラメータ。
呼び出すときに省略できて、その場合は初期値が適用される。
呼び出し元で、その引数の場に初期値とは違う値を入れたら、そちらが適用される。
関数を定義している側の目線で言うとオプションパラメータで、
呼び出し元の目線で言うと省略可能引数という言い方になる。
(※名前付きパラメータと書いてあるものもありますが、おそらく名前付き引数のことです。）
 
```C#:オプションパラメータ.cs
private int Sum(int intX, int intY = 0) //←intYがオプションパラメータ
{
    return intX + intY;
}
```
```C#:省略可能引数（オプション引数）.cs
private void DoSomeyhing()
{
    Sum(1); //←オプションパラメータは省略できるので、省略可能引数とも呼ばれる
    Sum(1, 1);//←省略せず、指定してあげることもできる
}
```
 
## 名前付き引数
オプションパラメータが複数ある関数、コンストラクタ、インデクサを呼び出す際に使用する。
呼び出し元の引数に名前を付けて、どのオプションパラメータかを指定できる。
```C#:オプションパラメータ.cs
//例えばオプションパラメータが同じint型で２つ以上あるとき（intYとintP)
private int Sum(int intX, int intY = 0, int intP = 0) 
{
    return intX + intY+ intP ;
}
```
```C#:名前付き引数.cs
private void DoSomeyhing()
{
    //このように書くと、引数５は、先に指定してあるintYに代入され、intPは初期値0が使用される
    Sum(1,5);
    //intPに代入したい場合はこのように「パラメータ名:引数」と書いてあげる
    Sum(1, intP:1);
    
    //※可読性が上がるので、オプションパラメータが複数ある場合は、必要ない場合でも、名前付きで書いてあげると親切かもです
    Sum(1, intY:5);
}
```

## 引数の値渡し
引数の渡し方の一種で、引数に指定した変数のコピーがメモリへ新たに作られる。
そのコピーされた変数を関数内でいじる。
よって、引数に指定した変数の中身には影響が出ない。
```C#:関数呼び出し元.cs
    string strHello = "こんにちは";

    //１．変数を値渡し。C#の場合、このまま変数を書くだけでOK
    this.EchoHello(strHello);

    //４．"こんにちは"が出力される。呼び出し元には影響がでないのが特徴。
    Console.WriteLine(strHello);
```
```C#:関数定義.cs
    private void EchoHello(string strValue)
    {
        //２．パラメータ、【strValue】のコピーが作られて、コピー側の変数を使って、"Hello"を表示する処理を行う。
        //(以下に追加を記載しています）
        strValue = "Hello";

        //３."Hello"が出力される
        Console.WriteLine(strValue);
    }
```
### 追記
以下の記事を参考に、かみ砕いた言葉で書いています。
メモリの使われ方などを表にされていて、大変分かりやすい記事です。
感謝いたします。

https://qiita.com/YuMo_tea/items/63e76cefa5acf38d30cf

## 引数の参照渡し
引数の渡し方の一種で、引数に指定した変数の参照(変数の実態が存在している住所)をその関数に渡す。
つまり、関数内では、渡された参照値を元に変数の実態をいじることになるため、関数内で変数の値を書き換えると、呼び出し元の変数の中身も書き変わる。

```C#:関数呼び出し元.cs
    string strHello = "こんにちは";

    //１．関数を参照渡し（C#の場合、変数の前にをref書いてあげる）
    this.EchoHello(ref strHello);

    //４．"Hello"が出力される。呼び出し元の変数にも反映されるので注意
    Console.WriteLine(strHello);
```
```C#:関数定義.cs
    private void EchoHello(ref string strValue)//パラメーターにもrefを書く必要がある
    {
        //２．パラメータ、【strValue】には【string strHello】の参照値が入っている
        //(こちらもかみ砕いて書いています。）
        strValue = "Hello";

        //３．Helloが出力される
        Console.WriteLine(strValue);
    }
```

## 省略可能引数(オプション引数)とオーバロードの違い
コンパイル時の挙動が異なります。
省略可能引数を使用している関数は、コンパイルすると、呼び出し元の関数に省略可能引数の値が埋め込まれます。
よって、アセンブリの違うプロジェクト間で省略可能引数のある関数は基本的に使用せず、オーバーロードを使用します。（ライブラリなど）

例えば、省略可能引数の値を変更→コンパイルしても、
呼び出し元側には、古い方の省略可能引数の値が埋め込まれている状態になるので、
こちらもコンパイルし直さなければなりません。
Oracle SQL*Loader にてバイト区切り（position 利用時）における末尾の全角スペースの取り扱いに関する仕様

## 概要

Oracle SQL*Loader にてバイト区切り（position 利用時）において、末尾の全角スペースが含まれている場合には全角スペースもTRIM されるようです。

以下がソースファイルと SQL*Loader の実験後のテーブルの出力結果ですが、全角スペース（`□`）が消えていることが確認できます。

< ソースファイル >

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/4aa964c2-4b3c-8c25-8683-c993c9d1189b.png)

< Oracle Databaseのテーブルのデータ >

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/3e1895b5-e6d7-c5ff-0260-b8c00b9dc5cb.png)

全角スペースが含まれているかを確認するクエリを実行しましたが、含まれていないことが確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/62f8d9e3-361c-f1e6-4206-473f903d25c1.png)


has_fullwidth_space 列では次のような処理をしています。

> このSQLクエリは、space_testテーブルからIDとNAMEを選択し、さらにNAMEカラムに全角スペースが含まれているかどうかを判定しています。
>
> CASE WHEN instr(NAME, '　') > 0 THEN 'Yes' ELSE 'No' END AS has_fullwidth_spaceの部分がその判定を行っています。
>
> instr(NAME, '　')は、NAMEカラムの値に全角スペースが含まれている位置を返します。全角スペースが含まれていない場合、この関数は0を返します。
>
> したがって、instr(NAME, '　') > 0は、NAMEカラムの値に全角スペースが含まれている場合に真（true）を返します。
>
> CASE WHEN句は、その条件が真である場合（つまり、NAMEカラムに全角スペースが含まれている場合）に'Yes'を返し、偽である場合（つまり、NAMEカラムに全角スペースが含まれていない場合）に'No'を返します。
>
> この結果は、has_fullwidth_spaceという名前の新しいカラムとして出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/b27b7ffa-eebe-9158-3bdb-fa5127c30ce6.png)

Oracle Database の文字コードは、`JA16SJISTILDE`で検証しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0202dd2e-b660-3aac-1049-f8924e5d31ee.png)

以上の結果から、Oracle SQL*Loader にてバイト区切り（position 利用時）において、末尾の全角スペースが TRIM されると解釈しました。

## 検証手順

### 1. データファイルの準備

次のデータをもつファイルを、`/home/oracle/char_test/text.txt`に作成

```text
1 ABC       
2 あいう 　 
3 abc　　   
```

### 2. 制御ファイルの準備

SQL*Loader の制御ファイルを、`/home/oracle/char_test/test.ctl`に作成

```text
-- char_test/test.ctl
LOAD DATA
CHARACTERSET JA16SJIS
INFILE '/home/oracle/char_test/text.txt'
TRUNCATE
INTO TABLE space_test
FIELDS TERMINATED BY ','
(
    ID position(1:2) CHAR,
    NAME position(3:12) CHAR
)
```

### 3. テーブルの作成

```sql
/*
DROP TABLE space_test;
*/
CREATE TABLE space_test (
    id   CHAR(2),
    name CHAR(10)
)
;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/bccc5d30-6fd2-8207-8f59-8ac3f4d8c3f1.png)


### 4. SQL*Loader の実行

```bash
sqlldr username/password@database control=char_test/test.ctl log=char_test/test.log
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/afd8f100-fe48-a681-5715-1af6beb0fa4c.png)

### 5. 実行結果を確認

```sql
SELECT
    ID,
    NAME,
    CASE WHEN instr(NAME, '　') > 0
        THEN 'Yes'
        ELSE 'No'
    END AS has_fullwidth_space
    FROM space_test
;
```

| ID   | NAME   | has_fullwidth_space |
| ---- | ------ | ------------------- |
| 1    | ABC    | No                  |
| 2    | あいう | No                  |
| 3    | abc    | No                  |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1164dfb2-1740-86d1-c568-0e110d0e37c5.png)
Javaの配列

# 配列とは
配列は1種類のデータ型を複数個管理する際に使用されます。

Javaでは配列の要素を0から表記するので、配列の一番目の要素は
配列名[0]となります。

宣言の際には、要素の型と配列の変数名の他に、newが必要です。

~~~:配列宣言の例
要素の型[]　配列変数名　= new 要素の型[要素数];
~~~
databricksのAIコード生成

# databricksのAIコード生成

## promptを指定してコード生成

|train_test_splitのパラメータを指定して目的変数の分布が均一になるようにtrainデータを分割|
|-|

↓こんな感じ
![ai_dbc_split.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3687201/f199d509-a820-b5fd-b795-567627954330.png)

↓(参考)Google Colab
![ai_colab_split.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3687201/b44c045b-a952-9fdf-ae35-0c48dc07e00c.png)

random_state=42は偶然の一致なのだろうか？
Laravelで`Carbon::setTestNow`がCarbonImmutableに適用されない

# 概要

Laravelでテスト書いていた時に、 `Carbon::setTextNow(now())`しても`CarbonImmutable::now()`の結果が固定されなかった。


発生バージョン(他のバージョンでも出るはず)

```
Laravel Framework 10.17.1
```

# 原因

`Carbon::setTestNow` と同じインターフェース実装が２箇所あり

`\Illuminate\Support\Carbon::setTestNow`
`\Carbon\Carbon::setTestNow`

useしているネームスペースが間違っていただけというミスでした。
IDEのサジェストから一番上のを適当に選んでいたので気づけませんでした...

# 詳細

\Illuminate\Support\Carbon::setTestNow のコード見て「あ・・・」ってなりました

```
namespace Illuminate\Support;

use Carbon\Carbon as BaseCarbon;
use Carbon\CarbonImmutable as BaseCarbonImmutable;

...

class Carbon extends BaseCarbon

...

    public static function setTestNow($testNow = null)
    {
        BaseCarbon::setTestNow($testNow);
        BaseCarbonImmutable::setTestNow($testNow);
    }
```
JSP・サーブレット　備忘録

## formタグ
action属性
送信先のプログラムのURLパターンを指定します。（『 / 』は不要）

method属性
起動するリクエストメソッドを指定します。「get」と書けばdoGetメソッド、「post」と書けばdoPostメソッドが起動されます。
method属性を書かない場合は自動でdoGetメソッドが起動されます。

```jsp:jsp
       <form action=¥"Servlet02¥" method=¥"get¥">
```

### リンクタグ
href属性
送信先のプログラムのURLパターンを指定します。（『 / 』は不要）
aタグで囲われた文字列にリンクとしての機能が付与されます。
```jsp:jsp
       <a href=¥“Servlet02¥”>画面02へ</a>
```

### Web.xml
XML形式で記述された、Webアプリケーションを動作させるための設定ファイルです。

### doGetとdoPostの違い
・doGet ：主に画面を表示させるリクエストを出す際に使用する
・doPost：主にサーバーに顧客の入力データを送る際に使用する


### リクエストパラメータの取得
```java:java
       		protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

			//レスポンス（出力データ）の文字コードを設定
			response.setContentType("text/html;charset=UTF-8");     //文字コードをUTF-8で設定
			//リクエスト（受信データ）の文字コードを設定
			request.setCharacterEncoding("UTF-8");                  //文字コードをUTF-8で設定

			//リクエストパラメータを取得
			String receiveParameterName     = request.getParameter("NAME");      //リクエストパラメータ（NAME）
			String receiveParameterDogType  = request.getParameter("DOG_TYPE");  //リクエストパラメータ（DOG_TYPE）
			String receiveParameterGender   = request.getParameter("GENDER");    //リクエストパラメータ（GENDER）
			String receiveParameterBirthday = request.getParameter("BIRTHDAY");  //リクエストパラメータ（BIRTHDAY）
			String receiveParameterColor    = request.getParameter("COLOR");     //リクエストパラメータ（COLOR）
			String receiveParameterComment  = request.getParameter("COMMENT");   //リクエストパラメータ（COMMENT）
}
```

受け取ったデータを元に表示画面を作成
```java:java
		//出力用のストリームの取得
		PrintWriter out = response.getWriter();

		//HTML文書（受信画面）の出力
		out.println("<html>                                                                    ");
		out.println("<head>                                                                    ");
		out.println("  <title>受信画面</title>                                                 ");
		out.println("</head>                                                                   ");
		out.println("<body>                                                                    ");
		out.println("  <p>以下の内容が送られてきました。</p>                                   ");
		out.println("  <p>                                                                     ");
		out.println("  ▼name属性『NAME』として受け取った値<br>" + receiveParameterName         );
		out.println("  </p>                                                                    ");
		out.println("  <p>                                                                     ");
		out.println("  ▼name属性『DOG_TYPE』として受け取った値<br>" + receiveParameterDogType  );
```
Mac環境にHomebrewをインストールする方法🔰

# はじめに

Macで開発環境を整えようとしている初学者の方は、
`brew`というおまじないをよく見かけるだろう。
gitはじめ何をするにもまずは`brew`...とにかく環境を作りたいだけなのに！
`brew`とターミナルに打ち込んでも`zsh: command not found: brew`...
それは`Homebrew`がインストールされていないからなのです。
そんな環境作成に対する意欲に溢れたあなたに贈ります。

## 検証環境
* macOS Sonoma 14.3.1
* 使用ターミナル:mac標準インストールアプリ使用


# Homebrewとは？
**パッケージ管理システム**の一種。
ちなみにHomebrewを翻訳すると**自家醸造**。

# インストール手順

下記公式ページにアクセスする。
[ダウンロード用サイトリンク](https://brew.sh/ja/)

![Monosnap macOS（またはLinux）用パッケージマネージャー — Homebrew 2024-02-13 14-24-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518298/1cc2632d-c3f9-237b-95dd-f01df25dcbad.png)

`$ /bin/bash ...`から始まるコマンドをコピーし、任意のターミナルに貼り付け、`Enter`を押下。

すぐに下記の記述が出るので、今ログインしているユーザのパスワードを入力する。
```
==> Checking for `sudo` access (which may request your password)...
Password:
```

その後、下記の記述が表示されるので、`Enter`を押下。
```
==> The Xcode Command Line Tools will be installed.

Press RETURN/ENTER to continue or any other key to abort:
```
出力されない場合は、すでに`Xcode`というツールがインストールされているということだ。心配せず次に進もう。

しばらく待ち、以下のような出力があれば、インストールに成功している。

```
==> Downloading https://ghcr.io/v2/homebrew/portable-ruby/portable-ruby/blobs/sha256:d783cbeb6e6ef0d71c0b442317b54554370decd6fac66bf2d4938c07a63f67be
######################################################################### 100.0%
==> Pouring portable-ruby-3.1.4.arm64_big_sur.bottle.tar.gz
Warning: /opt/homebrew/bin is not in your PATH.
  Instructions on how to configure your shell for Homebrew
  can be found in the 'Next steps' section below.
==> Installation successful!
```

まだ気を抜いてはいけない。
出力の最後の方に、次のステップが案内されている。
xxxxには現在実行しているユーザー名が記載されている。

```
==> Next steps:
- Run these two commands in your terminal to add Homebrew to your PATH:
    (echo; echo 'eval "$(/opt/homebrew/bin/brew shellenv)"') >> /Users/xxxx/.zprofile
    eval "$(/opt/homebrew/bin/brew shellenv)"
- Run brew help to get started
- Further documentation:
    https://docs.brew.sh
```

案内の通り、コマンドを実行する.

```
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/xxxx/.zprofile 
    eval "$(/opt/homebrew/bin/brew shellenv)"
```

**このコマンドのよくあるエラー**

1. 不要な`(`がある
    ```
    zsh: parse error near `)'
    ```
    `(`が閉じられていないという出力だ。`>>`の直前の`)`が余分についていることが原因なので、該当の`)`を削除しよう。出力をそのままコピペするとこうなる。
2. コマンドの改行がない
下記出力の場合、コマンド内の改行が不足している。
コマンドを手打ちしたことや、コピペを編集してしまったことが原因として考えられる。
    ```
    echo 'eval "$(/user/local/bin/brew shellenv)"' >> /Users/xxxx/.zprofile eval "$(/user/local/bin/brew shellenv)" 
    zsh: no such file or directory: /user/local/bin/brew
    ```
    2回目の`eval`の直前に、`\(バックスラッシュ)`を挿入しよう。
    ```
    echo 'eval "$(/user/local/bin/brew shellenv)"' >> /Users/xxxx/.zprofile \eval "$(/user/local/bin/brew shellenv)" 
    ```


# 最終確認

` brew -v`を実行しバージョンが確認できれば、正常にインストールができている。
```
brew -v
Homebrew 4.2.8
```
reg-suit の VRT (ビジュアルリグレッションテスト) を local だけで実行・レポート閲覧ができる reg-cli ライブラリ ( node js )

# reg-cliとは

https://github.com/reg-viz/reg-cli


かなりマイナーなライブラリのようだが、localだけでVRTを実行してHTMLレポートで比較できるようだ

```
npm i -g reg-cli
```

```
 reg-cli /path/to/actual-dir /path/to/expected-dir /path/to/diff-dir -R ./report.html
```

以下のように使う

```
reg-cli <画像のあるディレクトリ(1)> <画像のあるディレクトリ(2)> <差分を生成するディレクトリ> -R <レポート用のHTMLを生成するファイルパス>
```

# 画像群はどうやって用意する？

何らかの方法で用意する。
方法は問わない。

「比較したいgitブランチを切り替えて、それぞれスクリーンショットを生成するスクリプト走らせる」とか。

# reg-suit とは

[reg-suit](https://github.com/reg-viz/reg-suit)

画像を比較してHTMLのレポートにしてくれるプラグイン

>Compare Images - reg-suit is inspired by snapshot testing. It compares the current images with the previous images, creates an HTML report for their differences. All you need is to give images to assert.

画像はCloudに自動保存される

>Store Snapshots - reg-suit automatically stores snapshot images to external cloud storage(e.g. AWS S3, Google Cloud Storage). You can review result of comparison and differences at any time you want.

localでも各種CIでも動かすことが出来る
(だが画像保存先がクラウドなので、完全にlocalだけで実行できるわけではなさそうだ)

>Work Everywhere - reg-suit is just a CLI. So it's easy to integrate with your project. It works at any CI services and even your local machine.

クラウド保存先

AWS S3 と GCP の GCS が選べるようだ (2024/02/13現在)

<img width="884" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/99062a10-dbd6-40f8-98c3-1638d2f60b51">




# 参考

https://note.com/cyberz_cto/n/n79e344f59651 



# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
createOrReplaceTempViewの代わりにパラメータ化クエリを使う備忘録

## はじめに

自分用メモ。

複雑な変換をするとき、
SELECT結果をデータフレームに→データフレームをTempViewに→TempViewから新しいSELECT を作成→・・・　というようなことをしていたが、今はパラメータ化クエリが推奨されているらしい。
テキスト→日付などの型変換もpython内ででき、SQLインジェクションにも対応できてよいとか

参考：
https://www.databricks.com/jp/blog/parameterized-queries-pyspark


## 今までのやり方

CTEのようにViewを使って多段での変換をしていた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/3d9b2612-6266-ab2e-33e2-fde0a87fbfc8.png)

```python: pyspark

df = spark.sql("SELECT * FROM <テーブル名>")
display(df)
```

```python: pyspark
df.createOrReplaceTempView("tempV1")
df2 = spark.sql("""
SELECT 
    *,quantity * 1.1 as `110% QTY`
FROM 
   tempV1
""")

display(df2) 

```

## パラメータ化クエリを使ってデータフレームをソースにする

spark.sql はpythonオブジェクトをそのまま埋め込みできるのでちょっと楽ちん


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a07701d4-5e6c-5805-0b7e-1aac1be12a0e.png)


```python: pyspark

df = spark.sql("SELECT * FROM <テーブル名>")
display(df)

```

```python: pyspark

df2 = spark.sql("""
    SELECT 
        *,quantity * 1.1 as `110% QTY`
    FROM 
        {df}
    """
    ,df=df)

display(df2) 
```
モデルの軽量化について【E資格対策】

# <font color="#1e90ff">**プルーニング**</font>
プルーニングは、モデルの精度に寄与が少ないニューロンや重みを削除することで、モデルのサイズや計算量を減らす。枝刈りとも呼ばれる。



# <font color="#1e90ff">**蒸留**</font>
蒸留は、高精度な大規模モデル（教師モデル）から情報を伝えて、小さくて速いモデル（生徒モデル）を学習する方法です。教師モデルの出力を目的関数に利用して、生徒モデルに知識を移植します。


# <font color="#1e90ff">**量子化**</font>
量子化は、モデルのパラメータを小さいビットで表現して、モデルのサイズや計算量を減らします。例えば、64ビットの浮動小数点を16ビットや8ビットに変換します。
rex0220 計算式プラグイン 日付と時刻から日時に変換

[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で、日付と時刻から日時に変換します。

# 概要

[計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で、日付と時刻から日時に変換して日時項目にセットします。

![2024-02-13_15h16_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ce90dd6b-9e0b-e8a7-ed88-83fe69a792df.png)

# 計算式プラグイン設定

日時項目の設定は、いろいろな形式でセットできますが、"YYYY-MM-DD HH:mm" の形式がわかりやすいと思います。
日付と時刻を組み合わせて、"YYYY-MM-DD HH:mm" の形式になるように、変換します。

- 日付が未入力の場合、""
- DATE_FORMAT(日付)： 書式を省略すると"YYYY-MM-DD"
- NVL(時刻, "00:00")
    - 時刻が未入力の場合、"00:00" をセット

![2024-02-13_15h18_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/81a58bbb-1888-dedb-a7bd-c05a7e6e5a89.png)

```.js
// 日時 DATETIME
IF(日付,
  DATE_FORMAT(日付) & " " & NVL(時刻, "00:00")
)
```
商品購入機能　単体テストコードの実装

# はじめに
プログラミング初心者です。現在フリマアプリの終盤、商品購入機能実装中。
間違っていたら、コメントをお願いします。
# 単体テストコード
これまで、商品購入機能の実装を進めてきました。
まだ、クレジットカード機能の実装はしていませんが、ひとまずテストコードを書きます。


### 今回のポイント
１、MySQL client is not connectedのエラーが出たときはこちらを記載！

config/environments/test.rb
```
Rails.application.configure do
 #省略
 config.active_job.queue_adapter = :inline #追記
 #省略
 ```
 ２、カラム名は揃えるべし
 テストコードのファイルやFacrtoryBotのファイルごとで、ActiveHashカラムの~~~_idのidを付けたり付けなかったりしていました。
 それによって、テストコードがいつまでもActiveStorageエラーになり成功しませんでした、、、。

３、誤字をなくす！
```
  2) OrderAddress 商品購入機能 購入情報が保存できない時 municipalitiesが空では保存できない
     Failure/Error: expect(@order_address.errors.full_messages).to include("Muncipalities can't be blank")
       expected ["Municipalities can't be blank"] to include "Muncipalities can't be blank"
     # ./spec/models/order_address_spec.rb:45:in `block (4 levels) in <top (required)>'
```
このようなエラーが出たときは大抵誤字です。

今回は以上！
T-Dash + AnyTest  Real SmartPhone Web Test

# outline

T-DashのPC WEBをtryしてみた。
次は、スマホの実機を使ってのテストを試してみた。


# Step1. 画面定義

PC同様にSPの画面定義を作成する必要がある。
しかし、現時点 ver 4.0.004 では、PCのような画面キャプチャ機能がないようだ。
そのため、エミュレータを駆使して画面定義を作成する必要がある。

### 1-1. chrome + UserAgent Switcher

まず、SPのエミュレータを設定する。
自分に合った、UserAgent Switcherを使うとよい。
自分はUser-Agent Switcher for Chrome が一番使いやすいと思って、これを使用している。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/b31e44e3-0840-3ded-ea7d-12f002bea345.png)

https://chromewebstore.google.com/detail/user-agent-switcher-for-c/djflhoibgkdhkhhcedjiklpkjnoahfmg


### 1-2. chrome developer tool 

画面定義の値をchrome developer toolを用いて取得する。

1. inspect modeにして、取りたい画面の要素を選択する
2. 選んだ要素のElementsが右側に表示される。その要素を選択し、"Copy Xpath"で xpathを取得する
3. 取得したxpathをそのまま値に使用してもよい。ただ、修正する場合、修正後に Ctl+F で要素検索を行い、修正後のxpathが正しいxpathであるか、再確認したほうが良い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/2c4b9b9a-5d25-6bfc-af47-eda6eae8a56c.png)

### 1-3. define 画面定義

上記で得られた画面定義の値を、T-Dash上で定義していく。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/d8b7063e-30c2-8d2f-a99c-67f1dd6975a2.png)

# Step2. test case

PCと同様にtest caseを作成する。
今回、シンプルにログインの機能を作成する

1. ブラウザをopenする
2. マイページログインをクリックする
3. ID & Passwordを入力する
4. My pageの表示をvalidateする
5. スクリーンショットを取る

尚、一部機能は使えないようだ。
例えば、「スクリーンショットを保存する」はSPでは使えない。
そのため、以下のように、カスタム動作でAppiumLibrary + RobotFraemworkを使用して代用品を作成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/068eb870-83a4-80da-5b8b-e9afb3c81c51.png)


完成したテストケースは以下のようになった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/1814c150-170a-aaad-be83-ec547af92f7d.png)

その実行結果は以下の通り

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/bae40ef9-e8ab-611b-baba-e9dbc88e236e.png)


# 最後に

T-Dashのモバイルテストは、まだまだ改善が求められそうだ。

- NativeAPPはT-Dashは基本機能は動かない（カスタム動作でrobot frameworkで組んでしまえば動くが。。。。）
- web driverのerrorが端末によって発生する（たぶん、localにinstallされているdrvierとスマホのchrome versionを一致させないといけない）
- 一部基本操作が対応せず、かつ見分けがつかない（例えば、スクリーンショットを取る）
- 画面キャプチャが使えない
- デバッグがつかえない（PC版のみになる）
- テスト時、スマホの動作がわからない（バックグラウンドテストのみ）

これらが改善されると、もっと使いやすくなるんではないかと思う。　┃電柱┃_･)ｼﾞｰ
AzureストレージアカウントでWebコンテンツを公開する

AzureストレージアカウントでWebコンテンツを公開する手順を解説します。  

## ストレージアカウントの作成

👇サブスクリプションの設定

```text
az account set --subscription "***-***-***-***"
```

👇ストレージアカウントの作成

```text
az storage account create^
 --name webstorageaccount11^
 --location japaneast^
 --resource-group sample_resource_group^
 --sku Standard_LRS
```

## ストレージアカウントへの権限付与

```text
az role assignment create^
 --role "Storage Blob Data Contributor"^
 --assignee "0000-0000-0000-0000-0000"^
 --scope "/subscriptions/***-***-***-***/resourceGroups/sample_resource_group/providers/Microsoft.Storage/storageAccounts/webstorageaccount11"
```

## Web サイトのホスティングを有効にする

```text
az storage blob service-properties update^
 --account-name webstorageaccount11^
 --static-website
```

## サンプルHTMLの登録

👇サンプルHTML(test.html)を準備します。  

```html
<html>
  <h1>
    サンプルページ
  </h1>
</html>
```

👇ファイルアップロード

```text
az storage blob upload^
 --account-name webstorageaccount11^
 --container-name $web^
 --name test.html^
 --file test.html^
 --auth-mode login
```

## アクセスURLの取得

```text
az storage account show^
 --name webstorageaccount11^
 --resource-group sample_resource_group^
 --query "primaryEndpoints.web"^
 --output tsv
```

👇以下のような出力が得られます。  

```text
https://webstorageaccount11.zxx.web.core.windows.net/
```

👇以下のURLで先ほどアップロードした`test.html`へアクセスします。  

```text
https://webstorageaccount11.zxx.web.core.windows.net/test.html
```

## 👇関連記事

- [ユーザー割り当てマネージドIDによるAzureリソースへのアクセス権限付与](https://docs.saurus12.com/azure/user_manage_id)
- [Azure Blob Storage CLI及びPython経由ファイルアップロード／ダウンロード操作手順](https://docs.saurus12.com/azure/blob_upload_download)

## 👇参考URL

- [Azure Storage で静的 Web サイトをホストする](https://learn.microsoft.com/ja-jp/azure/storage/blobs/storage-blob-static-website-how-to?tabs=azure-cli)

[keywords]  
Azure CLI ストレージアカウント Web

[AzureストレージアカウントでWebコンテンツを公開する](https://docs.saurus12.com/azure/storage_account_web)

更新日:2024年02月13日
PythonでgRPCクライアントを作成する際の_InactiveRpcError解決法

### はじめに:
PythonでgRPCクライアントを作成し、外部のgRPCサーバーに接続する際に、`_InactiveRpcError`というエラーに直面することがあります。この記事では、この問題に遭遇した際の一般的な原因と解決策を紹介し、特にセキュアな通信を行うためのTLS設定に焦点を当てます。

### 問題の発生
PythonのgRPCクライアントからサーバーへのリクエストを送信した際に、以下のようなエラーが発生することがあります。

```
raise _InactiveRpcError(state)  # pytype: disable=not-instantiable
```

このエラーは、gRPCコールが何らかの理由で正常に完了しなかったことを示しています。

### 原因の分析
この問題の主な原因は以下の通りです。

1. **接続問題**: サーバーへの接続が確立できない、または接続が途中で中断された。
2. **タイムアウト**: 指定された時間内にサーバーからのレスポンスが得られない。
3. **誤ったサービス定義**: クライアントが使用しているサービス定義またはメソッド名がサーバーで定義されているものと一致しない。
4. **セキュリティ設定の不一致**: 特にTLS/SSLを使用する場合、クライアントとサーバー間でセキュリティ設定が一致していない。

### 解決策の概要
1. **エラー詳細のログ出力**: エラーをキャッチして、詳細な情報をログに出力する。
2. **接続設定の確認**: 使用しているアドレスとポートが正しいか、セキュリティ設定（TLS/SSLなど）に誤りがないかを確認する。
3. **サーバーログの確認**: 可能であれば、サーバー側のログを確認して、リクエストの処理状況を確認する。
4. **gRPCバージョンの確認**: クライアントとサーバーのgRPCバージョンが互換性を持っていることを確認する。

### TLSを使用したセキュアな通信の設定
PythonのgRPCクライアントでTLSを使用するには、以下のように`grpc.ssl_channel_credentials()`を使用してセキュアなチャネルを作成します。

```python
import grpc
import health_check_pb2
import health_check_pb2_grpc

with grpc.secure_channel('server-address:port', grpc.ssl_channel_credentials()) as channel:
    stub = health_check_pb2_grpc.HealthcheckServiceStub(channel)
    request = health_check_pb2.PingRequest(name='ping')
    response = stub.Ping(request)
    print(response.message)
```

このコードは、TLSを介してサーバーとセキュアな通信を行うための基本的な構成を示しています。`grpc.ssl_channel_credentials()`は、デフォルトの証明書を使用してチャネルをセキュアにしますが、必要に応じてカスタム証明書を提供することも可能です。

はい、その点を記事に含めるのは良い考えです。多くの開発者がローカルホストや内部ネットワークでの実装に慣れ親しんでいるため、インターネットを介した実際のデプロイメントやセキュアな通信の設定には注意が必要です。その部分を強調することで、読者がより実践的な知識を得られるようになります。以下は、記事に追加することを提案する内容の一部です。


### 実践的なデプロイメントにおけるgRPCの使用

多くのgRPCのチュートリアルやサンプルコードは、簡単化のためにローカルホスト（`localhost`や`127.0.0.1`）上での実装を想定しています。これらのサンプルは、gRPCの基本的な概念やAPIの使用法を理解するのに非常に役立ちますが、実際のアプリケーションでは、クライアントとサーバーが異なるマシン上にデプロイされることが一般的です。

例えば、以下のコードはローカルホストでの使用を想定したものですが、実際のデプロイメントでは適切ではないかもしれません。

```python
with grpc.insecure_channel('localhost:50051') as channel:
    stub = health_check_pb2_grpc.HealthcheckServiceStub(channel)
    request = health_check_pb2.PingRequest(name='ping')
    response = stub.Ping(request)
```

インターネットを介してサービスを公開する場合、セキュリティとパフォーマンスの観点から、いくつかの追加的な考慮が必要になります。

1. **セキュリティ**: インターネット経由でデータを送受信する際には、TLS/SSLを使用してデータを暗号化し、機密情報を保護する必要があります。`grpc.secure_channel`を使用してセキュアなチャネルを確立し、適切な証明書を配置することが重要です。

2. **接続設定**: 実際のデプロイメントでは、サービスのURLやポートが異なる可能性があります。デプロイメント環境に応じて、これらの設定を適切に調整する必要があります。

3. **デプロイメント環境**: クラウド環境やマネージドサービス（例：Google Cloud Run、AWS ECSなど）を使用する場合、環境固有の設定やセキュリティポリシーが適用されることがあります。これらの環境でgRPCサービスを運用する際には、プラットフォームのドキュメントを参照し、適切な設定を行うことが重要です。

### まとめ

ローカルホストでの開発と実際のデプロイメントでは、セキュリティ、接続設定、環境に応じた調整など、考慮すべき点が異なります。この記事が、ローカル開発から実際のデプロイメントへの移行をスムーズに行うためのガイドとなり、同じ問題に直面している他の開発者の助けになることを願っています。
macOSのメニューバーのアイコンを非表示にするアプリ

いくつか調べて候補があったのでメモしておく．Hidden Barがメジャーだった為，インストールした．

Dozer

- [Mortennn/Dozer: Hide menu bar icons on macOS](https://github.com/Mortennn/Dozer)

Hidden Bar

- [dwarvesf/hidden: An ultra-light MacOS utility that helps hide menu bar icons](https://github.com/dwarvesf/hidden)
- [「Hidden Bar」をMac App Storeで](https://apps.apple.com/jp/app/hidden-bar/id1452453066?mt=12)

Vanilla

- [Vanilla - hide Mac menu bar icons for free](https://matthewpalmer.net/vanilla/)
WSL2 SFTP

1. **WSL 2内のApacheデプロイ先ディレクトリの確認:**
   Laravelプロジェクトがデプロイされたディレクトリを確認します。通常、Apacheのドキュメントルートは `/var/www/html` などに設定されています。Laravelの`public`ディレクトリが公開されていることを確認してください。

2. **SFTPサーバーのインストール:**
   WSL 2上のUbuntuにSFTPサーバーをインストールします。OpenSSHサーバーが一般的に使用されます。次のコマンドでインストールできます。

   ```bash
   sudo apt-get update
   sudo apt-get install openssh-server
   ```

3. **SFTPサーバーの設定:**
   SSHの設定ファイル (`/etc/ssh/sshd_config`) を編集し、SFTPを有効にします。

   ```bash
   sudo nano /etc/ssh/sshd_config
   ```
   ```plaintext
   # /etc/ssh/sshd_config

   # Port 22  # デフォルトのポート番号（変更することができます）
   PermitRootLogin no  # ルートユーザーでの直接ログインを禁止

   # SFTPの設定
   Subsystem sftp /usr/lib/openssh/sftp-server

   # ユーザーホームディレクトリ内の.sshディレクトリにある認証鍵を使用
   AuthorizedKeysFile      %h/.ssh/authorized_keys

   # パスワード認証を有効にする場合
   PasswordAuthentication yes

   # パスワード認証を無効にする場合（公開鍵認証を使用する場合）
   # PasswordAuthentication no

   # ユーザーのセッションがアクティブな場合のタイムアウト設定（秒）
   ClientAliveInterval 60
   ClientAliveCountMax 3

   # ログの設定
   LogLevel VERBOSE
   SyslogFacility AUTH
   ```

   この設定ファイルでは、以下のポイントに注意しています：

   - `PermitRootLogin no`: ルートユーザーでの直接ログインを禁止しています。セキュリティ上の理由から、通常はルートユーザーでの直接ログインを無効にしておくことが推奨されます。
   - `Subsystem sftp /usr/lib/openssh/sftp-server`: SFTPの有効化およびSFTPサーバーのパスを設定しています。
   - `AuthorizedKeysFile %h/.ssh/authorized_keys`: SSH公開鍵認証を使用する場合の設定です。ユーザーのホームディレクトリ内の `.ssh/authorized_keys` ファイルに公開鍵を配置することで、公開鍵認証が有効になります。
   - `PasswordAuthentication`: パスワード認証を有効または無効にします。公開鍵認証を使用する場合は、通常は無効にしておくことが推奨されます。
   
   ファイルを保存したら、SSHサービスを再起動します。

   ```bash
   sudo service ssh restart
   ```

4. **WSL 2のIPアドレスの取得:**
   WSL 2のIPアドレスを取得します。

   ```bash
   ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'
   ```

5. **WindowsホストからSFTPアクセス:**
   Windowsホストから、取得したWSL 2のIPアドレスを使用してSFTPアクセスします。Windows上でSFTPクライアントを使用するか、PuTTYなどのツールを利用できます。

   ```
   SFTP Host: WSL2_IP_ADDRESS
   Username: your_username
   Password: your_password (または秘密鍵を使用)
   ```

   Laravelプロジェクトがデプロイされたディレクトリにアクセスして、必要な操作を行います。

注意: パスワード認証の代わりに公開鍵認証を使用することをお勧めします。Windowsホスト側でSSH鍵を生成し、公開鍵をWSL 2の`~/.ssh/authorized_keys`に追加します。その後、SFTPクライアントで秘密鍵を指定してアクセスします。これにより、よりセキュアな通信が可能になります。
.gitignoreがうまく動作しなくて30分とかした話

# 課題
.gitignoreファイルに無視したいディレクトリを.gitignoreファイルをカレントディレクトリとした相対パスで書いているのに無視されない

# 解決策
すでに追跡（トラッキング）されているファイル、ディレクトリは後から.gitignoreファイルに追記しても無視してくれない仕様であるそう。
よって、
```
git rm --cached [file or directory name]
```
でトラッキングを取り消す必要がある。
Cognos Analytics(11.2.4) on Linux & AIX で監視すべきプロセス

# 背景

cognosバージョンアップに伴う下記の更新記事です。

https://qiita.com/shinyama/items/f4d20c1d0678bc04923b

Cognos Analytics で起動してくるプロセスと、その中で監視すべきプロセスを考えてみました。
Cognosとして正式なガイドがあるわけではないので、あくまで個人の検証・調査結果です。

# 以前と同じプロセス

①　/opt/ibm/cognos/analytics/./bin64/./cogbootstrapservice ...　runAsDaemon
 ②　/opt/ibm/cognos/analytics/jre/bin/java　...　cognosserver
 ③　/opt/ibm/cognos/analytics/bin64/cgsServer.sh
 ④　/opt/ibm/cognos/analytics/jre/bin/java　...　CGSServer
 ⑤　/opt/ibm/cognos/analytics/jre/bin/java　...　dataset-service
 ⑥　/opt/ibm/cognos/analytics/bin/BIBusTKServerMain
 ⑦　/opt/ibm/cognos/analytics/bin/BmtMDProviderMain

# 認証プロセス
従来のバージョンにも存在していましたが、
LDAPやApacheDSを稼働させた際に起動するプロセスを検証します。
対応するプロセスは下記になります。

⑧　/opt/IBM/cognos/analytics/bin64/CAM_LPSvr

親プロセスは、
②　/opt/ibm/cognos/analytics/jre/bin/java　...　cognosserver　です。

# 認証プロセス障害検証

⑧はkillしても自動で立ち上がってきません。
レポートの実行をスケジュールで設定し（キャプチャは１分毎の実行で設定）、ログを確認します。

実行時間が1秒だけ、スケジュールより遅れているログが２件あります。
この実行の前に、⑧をkillしているので、実行自体は正常に終了したことがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1985245/0d5e744f-9519-3333-d6ee-a3f8abf9937a.png)



 # 新たに追加されたプロセス
 ⑨　/opt/ibm/cognos/analytics/jre/bin/java...　-Dspark.master=local[*]
　　Dspark.sql.warehouse...　flint.server.FlintServerApp




親プロセスは⑤dataset-serviceです。
前回記事を踏まえると、プロセスの親子関係はこのようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1985245/6ed5cf01-28a3-3db7-46f6-5a80a5cff61a.png)





 # プロセス障害時の動作

 新たに追加された⑨の動作を検証します。
 プロセスを削除した後、自動起動されるか、で監視すべきか判断します。


該当するPIDを確認したのち、topコマンドで実行中のプロセスを見ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1985245/300e69b4-dbaa-411f-1f18-4f9425d56bc3.png)

PID416（⑧Dspark)をkillします。

数秒後、topコマンドで見ている起動中のPIDから416が消えます。

代わりにCOMMANND:javaのプロセスが立ち上がってきている気がしますが、一応　ps -efで確認します。
すると、Dsparkを含むPIDが新しく立ち上がったものに変わっています。

親である、PID14999 dataset-service がkill されても、自動起動されます。
※⑤がkillされると、②により自動起動されるのは前回記事参照のこと。


# 結論
⑧　必要なタイミングで②により自動起動されるため、監視不要。

⑨　親である⑤により自動起動されるが、何らかの理由で自動起動できない場合に、レポート実行に支障が出るため監視する事が望ましい。

# おわりに


最後まで読んでいただきありがとうございました。
ご指摘等ありましたら、コメントいただけますと幸いです..！

以上、新しく増えたプロセスの検証でした。


**検証環境**:　OS:　Red Hat Enterprise Linux Server release 7.5 (Maipo)
　　　　 　Cognos-version: 　11.2.4　FP2
LaTeXでfigureの位置指定オプションHを使うと、図のあとの勝手な改行への対処法

# 修正した課題
修士論文など編集者の図位置の修正が入らない文章を書いていると図をlatexコマンドの位置に入れたいことが多々あるかと思います。その時にパッケージhereを読み込んで
```latex
\begin{figure}[H]
    ~~~
\end{figure}
```
とすることでlatexコードの図を入れた位置へ強制的に図を出力できます。
問題はこのコマンドを使うと図を入れた後に勝手に改行されてしまうことです。

# 解決策
https://tex.stackexchange.com/questions/310777/how-to-start-a-new-line-after-inserting-a-figure-without-indentation-at-the-begi
で解決策が提示されていました。
プリアンブルに
```latex
\makeatletter
\renewcommand\float@endH{\@endfloatbox\vskip\intextsep
  \if@flstyle\setbox\@currbox\float@makebox\columnwidth\fi
  \box\@currbox\vskip\intextsep\relax\@doendpe}
\makeatother
```
を書くことで解決します。
torch.nn.functional.one_hot で "RuntimeError: one_hot is only applicable to index tensor" したときの対処法

## はじめに
`torch.nn.functional.one_hot` で `RuntimeError: one_hot is only applicable to index tensor` したときの対処法です．
原因がわからなすぎて頭おかしくなりそうでした...

## 環境
* Python 3.11
* torch==2.1.2

## 具体例
```Python
import numpy as np
import torch
import torch.nn.functional as F

arr = np.array([0,1,2,3,0,1,2,3,0,1,2,3])
arr_T = torch.tensor(arr, dtype=torch.int32)
T = F.one_hot(arr_T)

# RuntimeError: one_hot is only applicable to index tensor.
```
一見問題なさそうですが，エラーを吐きます．

## 原因と対処法
`torch.nn.functional.one_hot` が対応している型が `torch.int64` 型のみなのが原因．したがって，以下のようにコードを書き換えればよい．
(そういう大事なことはドキュメントに書いてくれ...)
```Python
import numpy as np
import torch
import torch.nn.functional as F

arr = np.array([0,1,2,3,0,1,2,3,0,1,2,3])
arr_T = torch.tensor(arr, dtype=torch.int64)
T = F.one_hot(arr_T)
```

## 追記
`one_hot` が対応している型を明示してくれと言いましたが，実は下記のように明示してくれてました．
`LongTensor` というのが `torch.int64` とほとんど同じ意味みたいです．

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642842/5d39acd6-1025-744b-52ef-da841af81815.png" width="50%">


実際，以下のようなプログラムで確認すると，いずれも同じ型であることが分かります．
```Python
arr1 = torch.tensor([[1,2],[3,4]])
arr2 = torch.LongTensor([[1,2],[3,4]])
print("arr1 :",arr1.dtype)
print("arr2 :",arr2.dtype)

# arr1 : torch.int64
# arr2 : torch.int64
```


## 参考文献
* 公式ドキュメント: https://pytorch.org/docs/stable/generated/torch.nn.functional.one_hot.html
* github のissue: https://github.com/pytorch/pytorch/issues/86162
* `LongTensor` はここを参照 https://pytorch.org/docs/stable/tensors.html
BizRobo!のエラーハンドリングとは~エラー処理を上手く取り入れるには~

就業先では、RPAツールのBizRobo!を使用しています。BizRobo!開発で悩み、BizRobo!ナレッジベースで日々検索しています。

RPAは元々の仕組み上、エラーがでやすいです。そのため、エラーが出た時にどうやって検知するのか、つまりエラーハンドリングが重要だと考えています。

どういう時にエラー処理が起こりやすいのか、そして発生したエラーに対し、どうハンドリングするのかを就業先で学ぶ機会があったため、整理いたしました。

今回は、BizRobo!のエラーハンドリングについて共有いたします。

※時間が経過して変わってしまった箇所や間違っている箇所、不適切な表現があるかもしれませんが、その時は都度修正いたしますので、ご指摘いただけると幸いです。

## エラーハンドリング1
以下は、私が作成したサンプルロボットです。
<img width="75%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955689/79403e7a-bdcd-3a60-8948-d323f2854f95.png">
※BizRobo!バージョンは、10.3.0.7です。

同名ファイルが存在する場合は、一旦削除してからファイルコピーし、存在しない場合はそのままファイルコピーを行います。
ファイルコピーステップは、同名ファイルが存在する場合、エラーになります。そのエラーを予測し、条件分岐で処理を分けようと試みました。これも一種のエラーハンドリングとみなせると考えています。

エラーハンドリング1は、判定・エラー時の代替手段を個々に準備するような場合に利用し易いです。

## エラーハンドリング2
以下は、私が作成したサンプルロボットです。
<img width="75%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955689/14691738-7550-2b9b-30bf-3c48c5110d92.png">
※BizRobo!バージョンは、10.3.0.7です。

上記は各ステップでエラーが発生した場合、「エラー処理」のトライステップで、下の分岐に流れるようにしております。各ステップのエラー処理タブ内で、「エラー処理」のトライステップを選択することで実現できます。

エラーハンドリング2では、ロボット全体のエラー処理を集約するような場合に適しています。

## エラーハンドリング3
以下は、私が作成したサンプルロボットです。
<img width="75%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955689/e7268f2f-01ff-5517-c8d5-e465f3058d97.png">
※BizRobo!バージョンは、10.3.0.7です。

エラーハンドリング2で示したサンプルロボットは、実際の現場ではあまりないでしょう。
実際は、エラーハンドリング3のように複数のブランチが複雑に組み込まれているロボットがほとんどだと考えています。
エラーハンドリング2を各ブランチや各グループに配置することもありだと思いますが、エラー検知メールをその都度設定しなければならないことがネックになります。
上記サンプルの場合、各ブランチでエラーメッセージを変数に格納し、一番最後のブランチで格納した変数をエラーログ出力ステップとエラーメール送信ステップに格納するようにしています。
こういうエラーハンドリングを行うことで、メンテナンスしやすいロボットにしています。

## エラーハンドリング4
<img width="60%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955689/90110b0d-f400-7e65-04f2-3e39117dcef7.png">

※BizRobo!バージョンは、10.3.0.7です。

エラーハンドリングのトライステップを組み込まないという選択肢もあります。API例外のチェックを外し、エラーとしてログ記録だけにチェックをつけることで、ロボット処理を止めず、エラー内容をMC上に表示させることができます。
上記設定を上手く行うこと、MCが使えること、MC空のメール通知が届くなどの前提条件があれば、これでもエラーハンドリングを行うことが可能です。

## エラーハンドリングを組み込むうえで参考になるURL
BizRobo!のナレッジベースで参考になるURLを記載します。
[別のエラー処理方法](https://knowledge.bizrobo.com/hc/ja/articles/360028158511)
[エラーが発生した場合の処理や動作を変更できますか。](https://knowledge.bizrobo.com/hc/ja/articles/360027214212)
[MCでのロボット実行時に、エラーの検知をコントロールする方法](https://knowledge.bizrobo.com/hc/ja/articles/360035939732)
[ロボットの実行方法によるAPI例外発生時の挙動の違い](https://knowledge.bizrobo.com/hc/ja/articles/360036376152)

## 最後に
BizRobo!のエラーハンドリング処理について解説いたしました。

プログラミングもRPA開発もエラーハンドリングは重要なフローです。エラーハンドリングが正しく設定されていない場合、後々大規模な障害を引き起こす可能性があるからです。
就業先でBizRobo!のエラーハンドリングに関する経験を蓄積したため、吸収したエラーハンドリングの知見を整理することが大事だと思い、記事にいたしました。

今回の記事が、RPA開発で悩んでいる人の為になれば幸いです。
cscの作法 その453

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

# 練習問題
モグラ叩きを作れ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a8b2229d-9021-edf3-b553-e7dcb5b01f28.png)


# サンプルコード

```
using System;
using DxLibDLL;

class Test {
	[STAThread]
	static void Main() {
		int X;
		int Y;
		int[] cx = new int[9];
		int[] cy = new int[9];
		int[] cz = new int[9];
		int j;
		int k;
		int t1;
		int t2;
		int t3;
		int s;
		int g = 0;
		Random r = new Random();
		System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
		double ts;
		for (k = 0; k < 3; k++)
		{
			for (j = 0; j < 3; j++)
			{
				cx[k * 3 + j] = 30 + 160 * j;
				cy[k * 3 + j] = 30 + 160 * k;
				cz[k * 3 + j] = 1;
			}
		}
		uint red = DX.GetColor(255, 0, 0);
		DX.ChangeWindowMode(DX.TRUE);
		DX.SetGraphMode(640, 480, 32);
		if (DX.DxLib_Init() == -1)
			return;
		t1 = DX.LoadGraph("mogu_tan1.png");
		t2 = DX.LoadGraph("mogu_tan2.png");
		t3 = DX.LoadGraph("mogu_tan3.png");
		s = DX.LoadSoundMem("coin07.mp3");
		sw.Start();
		while (DX.ProcessMessage() == 0 && DX.CheckHitKey(DX.KEY_INPUT_ESCAPE) == 0)
		{
			DX.ClearDrawScreen();
			DX.DrawBox(0, 0, 640, 480, DX.GetColor(255, 255, 255), DX.TRUE);
			for (k = 0; k < 3; k++)
			{
				for (j = 0; j < 3; j++)
				{
					if (cz[k * 3 + j] < 3)
					{
						cz[k * 3 + j] = r.Next(2) + 1;
					}
				}
			}
			if ((DX.GetMouseInput() & DX.MOUSE_INPUT_LEFT) != 0)
			{
				DX.PlaySoundMem(s, DX.DX_PLAYTYPE_BACK);
				DX.GetMousePoint(out X, out Y);
				//Console.WriteLine(X);
				for (k = 0; k < 3; k++)
				{
					for (j = 0; j < 3; j++)
					{
						if (X > cx[k * 3 + j] && X < cx[k * 3 + j] + 120 && Y > cy[k * 3 + j] && Y < cy[k * 3 + j] + 120)
						{
							cz[k * 3 + j] = 3;
							g++;
						}
					}
				}
			}
			for (k = 0; k < 3; k++)
			{
				for (j = 0; j < 3; j++)
				{
					if (cz[k * 3 + j] == 1)
					{
						DX.DrawGraph(cx[k * 3 + j], cy[k * 3 + j], t1, DX.TRUE);
					}
					if (cz[k * 3 + j] == 2)
					{
						DX.DrawGraph(cx[k * 3 + j], cy[k * 3 + j], t2, DX.TRUE);
					}
					if (cz[k * 3 + j] == 3)
					{
						DX.DrawGraph(cx[k * 3 + j], cy[k * 3 + j], t3, DX.TRUE);
					}
				}
			}
			DX.ScreenFlip();
			DX.WaitTimer(800);
			ts = sw.ElapsedMilliseconds;
			if (ts > 30000)
			{
				break;
			}
			//Console.WriteLine(ts);
		}
		DX.SetFontSize(64);
		if (g == 9)
		{
			DX.DrawString(250, 240, "GAME CLEAR", DX.GetColor(0, 0, 255));
		}
		else
		{
			DX.DrawString(250, 240, "GAME OVER", DX.GetColor(255, 0, 0));
		}
		DX.ScreenFlip();
		DX.WaitTimer(5000);
		DX.DxLib_End();
	}
}





```

以上。
electron-forge --template=vite-typescriptで Error: crtypto.getRandomValues() not supportedと出るとき

uuidを生成する際、ブラウザ版のuuidが呼ばれてしまいエラーになっている。
vite.main.config.tsを以下のように変更すればrollupに巻き込まれない。

```ts
import { defineConfig } from "vite";

// https://vitejs.dev/config
export default defineConfig({
	resolve: {
		// Some libs that can run in both Web and Node.js, such as `axios`, we need to tell Vite to build them in Node.js.
		browserField: false,
		mainFields: ["module", "jsnext:main", "jsnext"],
	},
	build: {
		rollupOptions: {
			external: [
				"uuid"
			],
		},
	},
});
```

たしかmongodbとかknexとかもelectronだとうまく動かなかった気がする。そういうやつらはexternalに入れておいてやるとなんとかなる。
Oracle Database にて CDB の文字コードを JA16SJISTILDE に変更する方法

## 概要
Oracle Database にて CDB の文字コードを変更した際の実行結果を共有します。

## 手順

### 1. 既存の文字コードを確認

```bash
sqlplus /  as sysdba
```

```sql
SELECT VALUE FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER='NLS_CHARACTERSET';
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/34c2ddfb-8922-2c39-dfe0-32d08fc188cc.png)

### 2. 文字コードを変更

```sql
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER SYSTEM ENABLE RESTRICTED SESSION;
ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
ALTER SYSTEM SET AQ_TM_PROCESSES=0;
ALTER DATABASE OPEN;
ALTER DATABASE CHARACTER SET INTERNAL_USE JA16SJISTILDE;
SHUTDOWN IMMEDIATE;
STARTUP;
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e274afe9-8af9-9e8c-ff75-b7e803c0539c.png)

### 3. 文字コードが変更されたことを確認

```sql
SELECT VALUE FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER='NLS_CHARACTERSET';
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/90a2c89b-a5c4-e5e1-644a-3f130bcca290.png)
Phenix refinementでマニュアルでリガンドとタンパク質の結合を指定する。

Phenix refinementにおいてcootなどで導入したリガンド、タンパク質間の共有結合は必要に応じて自動で形成されるが、タンパク質の構造次第では難しい場合がある。その場合、自動形成はオフにし、マニュアルで結合する原子を指定する方法を取ることができる。
色々検討した結果、本方法がよさそうなので備忘録として残したものである。

参考資料

https://phenix-online.org/documentation/reference/refinement.html#definition-of-custom-bonds-and-angles

http://www.bmsc.washington.edu/CrystaLinks/man/pdb/guide2.2_frame.html


<h2>automatic linking optionをオフにする。</h2>

1. 通常通り、Refinement用のファイルをinput dataタブで設定した後、Refinement settingsタブに移動する。画面上のAutomatic liking optionをクリックする (図１、図２)。
1.  画面下のLink noneをクリックし、自動リンクをオフにする　（図3）。


![240213-1-memo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1825372/4524c35c-ae7f-0928-61fd-cd43800ab730.jpeg)
図１ real space refinementの場合



![240213-2-memo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1825372/da1836a3-8997-4fcf-0431-7c707f19b0bf.jpeg)
図２　Phenix.refineの場合



![240213-3-memo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1825372/a0d410ab-fe9d-5860-a14b-0b2dda70768a.jpeg)
図3　Automate Linking Optionsの画面

<h2>手動で結合のある原子を指定する。</h2>

- Refinement settingsタブ, Strategy項目のSelect atomsをクリックする (図４)。 


![240213-4-memo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1825372/ef3c33c8-8826-e1ae-1ea3-dae110c64f05.jpeg)
図4　Select　atomsの場所。

- 図5のようなページが開くのでCustom Geometry Restrainsタブを選ぶ。
- ついで、Bondsタブを選ぶ。
- Add Bondsをクリックすることで必要な数だけ行を追加する。
 
 
![240213-5-memo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1825372/3820b4f3-8a9d-c9d0-88f5-82c451b2ea86.jpeg)
図5 Selection Editorの図

- Selection 1とSelection ２に該当の原子の情報を記入する。Distanceはそれぞれの結合に応じた結合距離を入力する。Sigmaは0.02と指定する。Symmetry operatortorとSlackは未入力でもいい。
- Selectionに入力するべき内容は以下を参考にする。

```
#かっこの中に入力、'B'はchain ID, ９３８は残基番号、OGは該当の原子、今回はセリンの側鎖水酸基である。
(chain 'B' and (resid 938 and (name OG )))
```

- 作成した情報はExportにより保存できる。Loadから読み込むこともできる。
- 必要情報を入力が、左上の「Save and Close」で閉じる。
- あとは通常通りrefinementを行うと良い。

<h2>モデルを利用した原子の選択</h2>
Selectionに直接入力する以外にも構造モデルを表示させることで原子を選ぶ方法もある。図５上のモデルから選択可能である。しかし、このツールは使いにくい。選択すると図6のような画面が表示される。以下の方法で入力可能である。

- モデルツールを開く
- View Controls, ColorをElementに指定する。
- Selection Controls, SelectをAtomsに指定する。
- 目的のリガンドがある箇所にzoomする (使用感はpymolなどとほぼ同じである)。
- Edit Selectionをクリックする。
- 目的の原子をクリックする。白いバツ印が表示されます。
- Acceptをクリックします。
- Selection Editorに目的の原子情報が表示されているか確認する。
- 同様の操作をついとなる原子に対して繰り返す。

![240213-6-memo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1825372/f0e9bb96-5000-73fd-62d6-1d09674af074.jpeg)
図6 モデルツールの外観
ITエンジニアとしてのキャリア ※ジョーク投稿

# はじめに


# 自己紹介

{{ me.name }}({{ me.sns1.account_name }})と申します。

{{ me.birthdate }}生まれ、現在{{ me.getAge }}歳です。

{{ me.workExperiences[0].startDate | formatDate }}から{{ me.occupation }}としてのキャリアをスタートしました。

{{ calculateExperienceYears(me, 'web developer') + 1 }}年目になります。

<template v-if='hasOtherExperience'>
    
</template>
Typoだっていい！OSSにコミットするチャンスだ！


# こんな重箱の隅を突くようなコミットに価値があるのか...？

（最近やっていないのですが）私は競技プログラミングを趣味としており、コード作成・テスト・提出に[online-judge-tools](https://github.com/online-judge-tools/oj)を利用しています。
そこで、個人的に新機能を作成したいと思いコードを読んでいた所、思う所があり[Pull Requestを出しApproveを頂きました](https://github.com/online-judge-tools/oj/pull/921)。
まだmergeされてはいませんが、クリティカルな部分ではないですし、問題はありません。

何のPRを上げたでしょうか？そう、**Typo**です。

# これじゃ、俺...コードやコメントを書けなくなっちまうよ

Typo（タイプミス）はプログラムを書く上で一定の確率で起こり、実行時またはコンパイル時にエラーが引き起こされます。
最近は静的解析ツールなどが優秀なので、キーワードや予約語、変数等のハイライトやインデント等で開発者が間違いに気づきやすくなる環境が整備されています。

しかし、”文字列”の場合はどうでしょうか。
プログラム内に差し込まれたドキュメントやコメント、例外処理時に渡す文字列についてはいつ間違いに気づくのでしょうか。
大体書いていて気づくか、レビュー時に気づくことがほとんどだと思います。今回はPRという形でレビューをしたことになります。

# 根本的な解決にはなりませんよね？

エラーメッセージやコメントで書かれているドキュメントにあるTypoは、最も動作に影響を及ぼさないTypoの1つだと考えています。
つまり、根本的な解決にならないので見逃されがちです。
ですが、Typo等に気が付きPRを挙げることでいくつかメリットがあります。

1. メンテナーが実装したい部分に対して集中することができる
2. 皆で作っている感が出る
3. より良いメッセージやドキュメントを作成できる

1点目に、中心となる開発者が実装したい目標がある場合、細やかな間違いを一部後回しにして作業を進めることができます。
クリティカルでない限り、「なんか変だな」と思ったら直せばいいのです。

2点目は、「俺だけしか役に立ってない」という気持ちを減らすことができます。
私はOSSコミットはこれが初めてですが、サークル等で資料を作成するとき、担当箇所でないテキスト内にある表現の修正などもやっていました。
これにより、丸投げというより、皆で作っている一体感を生むことができます。

3点目は、文章そのもののクオリティが上がります。
私は英語を母語としておらず外国語が苦手なため、エラーメッセージの読み書きをする場合はDeepLと英和辞典を両脇に置いています。
今回のTypo修正に限らず、外国語でエラーメッセージを書く場合、どうしてもネイティブでは使わない表現を使う場合があります。
その時に、「この表現だと〜という意味で取られかねないので、...という表現に直しといた方がいいと思うよ」等のコメントで救われる場合があります。
このような添削を積み重ねることで、結果として良いドキュメントが生まれます。

このような話は、先日開催されたPHPカンファレンス関西2024でも同じようなことが言われていました。
てきめんさんがスライドを含めて公開してくださっているので、こちらもご覧ください。

https://x.com/asumikam/status/1756498674589532607?s=20

https://x.com/youkidearitai/status/1756500694763483141?s=20

https://speakerdeck.com/youkidearitai/hazimetenoosskontoribiyuto

# 支えてくれる人が傍にいればOSSだって成長しますよ、猿渡さん!

長々と書いてしまいましたが、OSSにTypoでもいいからコミットすれば、メンテナーから喜ばれます。
興味を持って新機能を作成したい場合は一旦自分で作り、大本にmergeするかどうかはその場で考えればいいと思います。
要らないと言われたら「いや自分が欲しいのでこれは残しときます」でも最悪良いとも思っています。

# おわりに

自分で直せるなと思ったらOSSにコミットしてPRを上げましょう。

（蛇足）見出しは[ミストさん](https://dic.nicovideo.jp/a/%E3%83%9F%E3%82%B9%E3%83%88%E3%81%95%E3%82%93)の語録を参考に作成しています。