OmniAICreator/Qiita-1.07M huggingface dataset:
メソッド・関数の作成時に意識したい事

# 凝集度
凝集度とは関数内の処理の関連性の強さや高さを表している。
凝集度が高いほど理解しやすくシンプルで，開発後のテストや保守のフェーズで非常に助かるもの。

凝集度が高い順にメモを残していく。
※後で追加や修正していく可能性がある記事。

### 1.機能的凝集度（理想）
1つのタスクを実行する関数。
・例：getUserId(),getBookName(),caluculateTotalPrice()


### 2.情報的凝集度/逐次的凝集度

1つの関数の中で2つ以上の処理が含まれている。関連性の高い機能。順に処理していく関数。
・例：商品購入日→配送日→商品到着予定日

下記の2つの関数に分ける事で機能的　凝集度の関数が作れる。
商品購入日→配送日
商品購入日→商品到着予定日



### 3.連絡的凝集度/通信的凝集度

凝集度の強さは情的凝集度とほぼ同じ。
1つのメソッド，関数内の実行処理が同じ情報を使用する。関連性がない。

・例：
商品購入→購入した商品を保存，購入した商品をカートから削除

※商品が同じ情報に該当する。

下記関数に分ける事で凝集度を高くする事ができる。
購入商品を保存する関数
購入した商品をカートから削除する関数





### 4.手順的凝集度
ある実行順序で処理をまとめた関数。
共通する情報を扱っているわけではない。


・例：患者の名前を取得→既往歴を取得/性別を取得→内服歴を取得

患者情報を入力するフォームがあったとする。
一つ目の関数で患者の名前を取得し，患者の既往歴を取得するAという処理。
別の関数で患者の性別を取得，患者のの内服歴を取得するというBという処理。
AとBの処理をひとまとめにしたパターン
※ここから関数の再利用性は非常に悪くなってしまい、保守作業に支障を来すようになる。


### 5.時間的凝集度・一時的凝集度
複数の機能の操作が同じタイミングで実行される関数。

・例：初期化


### 6.論理的凝集度
複数の同じ似た処理が一つにまとめられた関数。
・YouTuberの名前とか構成メンバーといった，「YouTuberの詳細」を表示する処理
・再生回数が〇〇回以上でそのYouTuberが「人気」と表示する処理
これらの処理がまとめられていた関数があったとする。

この関数は
「YouTuberの詳細」と「人気なのか」という2つの処理を担っている事になる。
片方の処理だけを行いたい場合には対応できない。



### 7.偶発的凝集度/暗号的凝集度
関連のない複数の処理がまとめられた関数。





##### 参考元
[独学エンジニア](https://dokugaku-engineer.com/course/serverside/lecture/3gIyo)
YahooAPIを用いた銘柄情報取得

# はじめに
<!-- 発端や概要を記載 -->
どうも、emonです。
今回は、YahooFinanceに保存されている情報をAPIを用いて取得します。
今回、APIをより扱いやすくする為、OSSの[node-yahoo-finance2](https://github.com/gadicc/node-yahoo-finance2)を用いて取得してみようと思います。
■環境
- macOS
- Node.js
- npm(パッケージ管理)
- Express(WEBサーバ)
- javascript
# 目次
<!-- タイトルとアンカー名を編集 -->
1. [環境構築](#環境構築)
1. [APIを叩いてデータを取得](#apiを叩いてデータを取得)
1. [動作確認](#動作確認)
1. [エンドポイントの作成](#エンドポイントの作成)
1. [参考文献](#参考文献)

<!-- 各チャプター -->
<a id="#環境構築"></a>
# 環境構築
1. package.json及び必要ライブラリのインストール

    ```
    npm init
    npm install express
    npm install yahoo-finance2
    ```

1. アプリルートディレクトリ配下にmodulesフォルダを作成し、quate.jsを作成する。
1. app.jsを作成する。
1. 以下のようなフォルダ構成になっていればOKです。
    ```cmd:1.フォルダ構成
    |- modules
    |-- quate.js
    |- node_modules
    |- app.js
    |- package-lock.json
    |- package.json
    ```

<a id="#apiを叩いてデータを取得"></a>
# APIを叩いてデータを取得
1. quate.jsに以下を追加する。今回は、例としてアップルの情報を取得する。

    ```javascript:1./modules/quate.js
    import yahooFinance from 'yahoo-finance2';

    // quote
    export const get = async () => {
        try {
            const data = await yahooFinance.quote('AAPL');
            return data;
        } catch (e) {
            return e;
        }
    };
    ```

<a id="#エンドポイントの作成"></a>
# エンドポイントの作成
1. expressを用いてWEBサーバを構築する。

   ```javascript:1.app.js
   /* 1. appにインスタンスにexpressを格納*/
   const app = express();

   /* 2. 3000番ポートで起動する。*/
   const port = 3000;
   const server = app.listen(port, () => {
       console.log("listening to PORT:" + server.address().port);
   });

   ```

1. app.jsに'/quate/get'のルーティングを追加する。

    ```javascript:1.app.js
    import * as quate from './modules/quate.js';

    // quate
    router.get("/quate/get", (req, res, next) => {
      const quateGet = quate.get();
      quateGet.then((result) => {
        res.json(result);
      });
    });
    ```

<a id="#動作確認"></a>
# 動作確認
1. WEBサーバを起動させる

    ```cmd:
    node app.js
    ```

1. 任意のブラウザを起動させ、'localhost:3000/quate/get'を叩く。以下の画像のようにデータが取得できていればOKです。
![スクリーンショット 2022-09-11 15.18.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819209/fc14270c-9796-80fe-76c9-64e9bfb5b6eb.png)

以上、YahooAPIを用いた株データの取得方法でした。


<a id="#参考文献"></a>
# 参考文献
- [node-yahoo-finance2](https://github.com/gadicc/node-yahoo-finance2)
cscの作法 その272

# 概要
cscの作法、調べてみた。
.NETFramework2.0 に書き直してみた。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/32466d1a-93de-dd41-1152-cc7ee2ee85b6.png)


# 参考にしたページ

https://qiita.com/Hnming/items/fe38e3b3d2d4b677226c

# サンプルコード

```
using System;
using System.Drawing;
using System.Windows.Forms;

namespace App
{
	public partial class form1 : Form {
		Bitmap Bm;
		bool mouseDrug;
		int prevX;
		int prevY;
		PictureBox DrawingPicBox;
		public form1() {
			DrawingPicBox = new PictureBox();
			DrawingPicBox.Size = new Size(300, 300);
			DrawingPicBox.MouseDown += new MouseEventHandler(DrawingPicBox_MouseDown);
			DrawingPicBox.MouseUp += new MouseEventHandler(DrawingPicBox_MouseUp);
			DrawingPicBox.MouseMove += new MouseEventHandler(DrawingPicBox_MouseMove);
			this.Controls.Add(DrawingPicBox);
			Bm = new Bitmap(DrawingPicBox.Width, DrawingPicBox.Height);
		}
		private void DrawingPicBox_MouseDown(object sender, MouseEventArgs e) {
			mouseDrug = true;
			prevX = e.Location.X;
			prevY = e.Location.Y;
		}
		private void DrawingPicBox_MouseUp(object sender, MouseEventArgs e) {
			mouseDrug = false;
		}
		private void DrawingPicBox_MouseMove(object sender, MouseEventArgs e) {
			if (mouseDrug == true)
			{
				Graphics objGrp = Graphics.FromImage(Bm);
				Pen objPen = new Pen(Color.Blue, 3);
				objGrp.DrawLine(objPen, prevX, prevY, e.Location.X, e.Location.Y);
				prevX = e.Location.X;
				prevY = e.Location.Y;
				objPen.Dispose();
				objGrp.Dispose();
				DrawingPicBox.Image = Bm;
			}
		}
		[STAThread]
		static void Main() {
			Application.EnableVisualStyles();
			Application.Run(new form1());
		}
	}
}





```



以上。
Java 推奨されるnullチェックについて

本日も実務の実装の中で、学んだことがあったので備忘録として書き残しておこうと思います。

人知れず変数の中に入ってしまうnullの対処についてです。
Java歴の浅い方や古いバージョン(8以前)を中心に実装していた方もためになるかと思います。


## 僕の知っていたnullチェック
僕が研修などで学んだチェックは一般的な以下でした。

```java
String a = null;
String b = "あいう";

if (a != null) {
  System.out.print(a);
} else {
  System.out.print(b); //こっちが実行される
}

```

!= または == これで比較してif文の分岐でヌルポで落ちないようにすることしか知りませんでした。
今でもシステム内では結構使われていましたが、、、


## 推奨されるnullチェック

nullの考慮ができるメソッドやOptionalを利用することで、nullチェックの数は減るとは思いますが、
どうしてもnullチェックをしたい時があります。
そんな時にjava8以降で推奨されるnullチェックは以下です。


```java
String a = null;
String b = "あいう";

if (Objects.nonNull(a)) {
  System.out.print(a);
} else {
  System.out.print(b); //こっちが実行される
}

```

ObjectsクラスのnonNullメソッドは、!=nullと同じ役割を果たします。
<br>

== nullの判定と同じメソッドも用意されています。
それが下記で、ObjectsクラスのisNull()メソッドです。

```java
String a = null;
String b = "あいう";

if (Objects.isNull(a)) {
  System.out.print(b);//こっちが実行される
} else {
  System.out.print(a); 
}

```
<br>

### Objectsクラスのメソッドを利用するメリット

メリット①：!=や==と記述するより可読性が上がる。 

メリット②:関数型プログラミングで利用しやすい、見やすい

<br>
メリット②についてですが、streamAPIにて中間操作でnullのデータを破棄したい時に利用できます。

クラス名::メソッド名　もしくは、インスタンス名::メソッド名で利用できます。

```java
List list = Arrays.asList(1,null,2,null);
List<Integer> result = list.stream().filter(Objects::nonNull).collect(Collectors.toList());
//resultの中身は[1,2]のみになる

```


可読性が上がるかつ簡潔に記載ができるのが良いですよね。

nullチェックをする時はObjectクラスを利用してくように心がけます。
ウザイ性格診断サイトを作った

こんな感じ
https://ahya-test.ahyaemon.com

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244354/eeca1f14-ac86-5545-23de-b9d7f07c1e9f.png)

## なにこれ

9 つの質問に回答すると性格が分かる、みたいな良くあるアレ。

## なぜ作ったか

- css grid を使って何か作りたかった
- SolidJS を使って何か作りたかった

## 技術スタック

- [TypeScript](https://www.typescriptlang.org/)
- [SolidJS](https://www.solidjs.com/)

詳しくは　GitHub　リポジトリを参照
https://github.com/ahyaemon/ahya-test

## SolidJS 周り

ページの構成は大きく分けると「質問ページ」と「結果ページ」の二つに分かれているため、その間を遷移させるために [solid-router](https://github.com/solidjs/solid-router) を使用した。
あとトーストも出したいなーと思っていたら [solid-toast](https://www.solid-toast.com/) というものがあったので使わせていただいた。

React を使うと再レンダリングを防ぐためにテクニックが必要だけど、SolidJS の場合は再レンダリングさせるためにテクニックが必要になることがあり、この差は結構好き。

 ## サイト周り

回答中に誰かに後ろから覗かれるのって嫌だよなー、と思って、まさにそれを実現させるためにおじさんのトーストを用意した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244354/9dd06317-f3d6-46cd-8cf7-7b4c21c4c899.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244354/073ea2ff-83ab-0398-26e6-7623ec83c157.png)

こういう相槌打たれたらウザイな、というセリフを盛り込んだ。
また、結果ページではまず第一印象を大事にした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244354/ed0e35de-9b6e-2801-1e56-dd47b8d21c4e.png)

さらに名言を入れることで、診断アプリ感を出した。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244354/586289bb-868e-06e8-a6fb-a2f1536e88dc.png)

## 終わりに

主に css の学習のために作ったけど、思ってたよりそれっぽいサイトができた。
診断結果は結構あってると思う。
なぜなら質問の回答を適当に言い換えただけだから。
Ruby on Rails　form-forの記述をform-withへ変更した時、model: @○○を記述するがこのインスタンス変数はどこからやってきたの？


# はじめに
Ruby on Railsでdeviseのgemを導入した際にはコントローラは生成されない。となった時にどこで何を見たらいいの？と思い、分からなかったので、メンターさんに質問して理解した内容をここに記録する。

(自分にしかわからない書き方となっていること、ご了承ください:bow:)

# form-forの記述をform-withへ変更した時、model: @○○を記述するがこのインスタンス変数はどこからやってきたの？

#### form-forの記述
```
<%= <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %> %>
```
#### form_withの記述
```
<%= <%= form_with model: @user, url: user_registration_path do |f| %> %>
```

#### 疑問点。。。
`model: @user`と記述したので、インスタンス変数`＠user`はどこかで定義されてるはずだが、どこをみたらいいのだろう？deviseのgemを導入した場合はコントローラは生成されてないし。。



#### やってみよう！
とりあえず`model: @user`を`model: user`にしてみた！



#### 結果。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2823804/bcd8fbce-a65c-8a2b-eb27-29a758848c84.png)

もちろんエラー発生。。。
おそらくdeviseのgemを導入したらdeviseで作成したモデルをインスタンス変数で持ってこれるのだと思われるが、モヤモヤするので念のためメンターさんに質問した。

#### メンターさんの回答
上記の認識で基本的には合っています。
<font color=red>Gemファイルで導入した場合、裏で必要な機能をすでに実装してくれている</font>ので、そのまま持ってこれるようになります。

とのことです！

# 終わりに
どこでインスタンス変数を定義しているのか分かったら追記させていただきます！
まだまだ理解できていないことが多いので少しずつでも解消していきたいと思います！
KotlinでListのバリデーション

#### Listの中身をバリデーションしたいけど、Listの場合Spring側でバリデート用アノテーションが用意されてない...

Listの場合、せいぜい用意されているアノテーションでバリデートできるのが、桁数や要素のサイズしかなくて、Listの中身をバリデーションさせたい場合は
①バリデート用のアノテーションを自作
②data classのinit内でバリデーションさせる
ぐらいしかないのかな、と思います。

Listもネットで見つかった要素がほぼStringだったので、今回Intで特定の要素以外だったら弾くバリデーションを作ってみました。(逆に`List<Object>`だった場合は、@Validアノテーションが使えるのかなと思いますが。)

### バリデーションを自作する

```UserSearchForm.kt
data class UserSearchForm(
    @filed:Positive
    @field:Schema(
        required = false,
        type = "Int",
        description = "ユーザId",
        example = "1"
    )    
    val usesrId: Int = null,    

    @field:UserTypeCheck
    @field:Size(max=3)
    @field:Schema(
        required = false,
        type = "List<Int>",
        description = "ユーザタイプ",
        example = "[1,2,3]"
    )
    val usesrType: List<Int> = null,
)
```

**バリデーション**
```UserTypeCheck.kt
@Target(AnnotationTarget.FIELD)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Constraint(ValidateBy = [UserTypeCheckValidation::class])
@ReportAsSingleViolation
@Supress("unused")
annotation class UserTypeCheck(
    val message: String = "UserTypeCheck Fail",
    val groups: Array<KClass<out Any>> = [],
    val payload: Array<KClass<out Payload>> = [],
)
```

```UserTypeCheckValidation.kt
internal class UserTypeCheckValidation : ConstraintValidator<UserTypeCheck, List<Int>> {
    @Supress("EmptyFunctionBlock")
    override fun initialize(ConstraintAnnotation: UserTypeCheck){}

    override fun isValid(value: List<Int>?, context : ConstraintValidatorContext?): Boolean{
        if(value != nulll) {
            for(i in value) {
                if(i < 0 || 4 < i) {
                    return false
                }
            }
            return true
        }
    }
}
```

これだけで、`List<Int>`の要素で1-3以外の数値が来たらValidation Errorを返すことができました。

#### data class内のinitでバリデーションする

次はinitのrequire内でバリデーション用メソッドを実行する方法です。

バリデーション用のアノテーションクラスはどうしても書きたくないならこういうやり方もあります、というレベルだとは思いますが。。

・参考: [Validation and DDD](https://stackoverflow.com/questions/52093474/validation-and-ddd-kotlin-data-classes)

```UserSearchForm.kt
data class UserTypeSearchForm(
    @filed:Positive
    @field:Schema(
        required = false,
        type = "Int",
        description = "ユーザId",
        example = "1"
    )    
    val usesrId: Int = null,    

    @field:UserTypeCheck
    @field:Size(max=3)
    @field:Schema(
        required = false,
        type = "List<Int>",
        description = "ユーザタイプ",
        example = "[1,2,3]"
    )
    val usesrType: List<Int> = null,
){
    init {
        require(CheckUserType(userType)) { "userTypes is incorrect." }
    }
}

private fun CheckUserType(userType?: List<Int>): Boolean {
    if(userType != nulll) {
            for(i in userType) {
                if(i < 0 || 4 < i) {
                    return false
                }
            }
            return true
     }
}
```
Salesforce認定アドミニストレーター試験の公式練習問題を解説してみた-その026

こんにちは。本橋孝昭です。

Salesforce認定アドミニストレーター試験の公式練習問題があるのはご存じでしょうか。
Trailheadにフラッシュカードとして何度も解ける練習問題がございます。

今回はTrailhead
アドミニストレーター認定の準備: アプリケーションと活動
サービスアプリケーションとサポートアプリケーションの準備

にある練習問題2問目をご紹介します。

https://trailhead.salesforce.com/ja/content/learn/modules/administrator-certification-prep-applications-activities-and-mobile/prep-for-service-and-support-applications?trail_id=administrator-certification-prep

今回のナレッジについての設定や解説はこちらの動画で解説されています

https://www.youtube.com/watch?v=gq6XKyCMIhY

<iframe width="560" height="315" src="https://www.youtube.com/embed/gq6XKyCMIhY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


問題はこちらです
![ナレッジ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531631/6ff320b6-d85b-aba5-6192-7f4b2bb67fb7.png)


データカテゴリの詳細はこちらのTrailheadがおすすめです

https://trailhead.salesforce.com/ja/content/learn/projects/set-up-salesforce-knowledge/create-and-customize-data-categories
Docker Compose V1 が deprecated となり、Docker Compose V2 が推奨となる様子

Docker Compose V1 が deprecated となり、Docker Compose V2 が推奨となる様子
（最近気付いた）

> [[Docker Compose] V1 End of Life Policy #257](https://github.com/docker/roadmap/issues/257)
> April 2023 - 1 Year Post GA
Users can alias docker-compose to docker compose
Users can no longer opt-out of V2 via the Docker Desktop UI or through the docker-compose disable-v2 command in new versions

以下の記事がわかりやすかった

> [Docker Compose V2(Version 2) GA のまとめ](https://qiita.com/zembutsu/items/d82b2ae1a511ebd6a350)

Docker Compose V2 は公式手順からインストールできる

> https://docs.docker.com/engine/install/ubuntu/
> 
> ```sh
> sudo apt-get update
> sudo apt-get install ca-certificates curl gnupg lsb-release
> sudo mkdir -p /etc/apt/keyrings
> curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
> echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) 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-compose-plugin
> ```



もし上記でインストール失敗した場合は以下の先人の記事を参照すればよさそう

> [Where to get Docker Compose](https://github.com/docker/compose#where-to-get-docker-compose)
> [Ubuntu20.04へのDocker Compose v2 インストール](https://qiita.com/kujiraza/items/e1bf4069514ce8c4fd4d)
>  
> ```
> /usr/local/libexec/docker/cli-pluginsにインストールする場合
> # インストール先ディレクトリがなければつくる。説明を楽にするためにカレントディレクトリも変更
> sudo mkdir -p /usr/local/libexec/docker/cli-plugins
> cd /usr/local/libexec/docker/cli-plugins
> 
> # リリースモジュールをダウンロードし、docker-composeという名前でインストール先に保存
> sudo curl -L https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-linux-x86_64 -o docker-compose
> # docker-composeを実行可能にする
> sudo chmod +x docker-compose
> ```
> 
> ```
> 動作確認
> $ docker compose version
> Docker Compose version v2.6.1
> ```

docker compose switch (Compose V1をCompose V2に変換してくれるコマンド)

> https://github.com/docker/compose-switch/
> Compose Switch
> Compose Switch is a replacement to the Compose V1 docker-compose (python) executable. It translates the command line into Compose V2 docker compose then run the latter.
Linux inetd,xinetdについて

●スーパーサーバ
「inetd」や「xinetd」はスーパーサーバと呼ばれ、登録された利用頻度の低いサービスを監視し、リクエストが来た場合にだけ、該当のサービスを実行。 これにより利用頻度の低いサービス（例えばTELNETやFTPなど）をシステムにデーモンとして常駐させる必要が無くなり、メモリやCPU等のリソースの消費を抑えられる。

●inetd
設定ファイルは「etc/inetd.conf」
アクセス制御はTCPラッパー「/etc/hosts.allow」、「/etc/hosts.deny」

・設定ファイル「etc/inetd.conf」の各項目内容

1、サービス 2、ソケットタイプ 3、プロトコル 4、ウエイト 5、ユーザー名 6、プログラム（デーモン）のパス 7、プログラム（デーモン）名と引数

行の先頭に#を入れる事で、その行をコメントアウトし、「inetd」で該当のサービスを起動しないように出来る。

■「/etc/inetd.conf」ファイルの変更後はinetdを再起動する必要がある。

inetdの再起動には、killまたはkillallコマンドでinetdにHUP（SIGHUP）シグナルを送る、inetdの起動スクリプト（/etc/init.d/inetd）に引数restartを付けて実行するなどの方法がある。

・kill -HUP inetdのPID
・killall -HUP inetd
・/etc/init.d/inetd restart



●xinetd
「xinetd」は「inetd」より新しいスーパーサーバで、サービス毎に詳細な設定が可能。
xinetdの全体的な設定は「/etc/xinetd.conf」ファイルで行い、各サービスの個別設定は「/etc/xinetd.d/」ディレクトリ内の設定ファイルで行う。
各サービスの個別設定ファイルを配置するディレクトリは、「/etc/xinetd.conf」の「includedir」で指定。

xinetdの主な設定項目
・bindまたはinterface サービスを提供するインターフェイスのIPアドレス
・disable サービスを無効化するかの設定(yes:無効化,no:有効化)
・instances サーバプログラムの最大起動プロセス数
・log_type ログの記録先指定。syslogや記録するログファイルの絶対パスを指定
・no_access サービスへのアクセスを拒否する接続元
・only_from サービスへのアクセスを許可する接続元
・server サーバプログラムの絶対パス
・server_args サーバプログラム起動時に指定する引数
・socket_type ストリーム型、データグラム型といったサービスの接続タイプ
・user サーバプログラムを起動するユーザ
・wait サーバプログラムへの接続処理を待ち合わせるかの設定。サーバプログラムがマルチステッドであり１プロセスで同時に複数処置できる場合はno、シングルスレッドで接続処理を待ち合わせる必要がある場合はyes


●xinetdによるアクセス制御のルール判定
・only_fromもno_accessも設定されていない場合、サービスへのアクセスは全て許可
・only_fromだけが設定されている場合、指定されたアクセス元しかサービスへアクセス出来ない
・no_accessだけが設定されている場合、指定されたアクセス元はサービスへアクセス出来ない
・only_fromとno_accessが同時に指定された場合、より厳密にマッチするほうに従う
Vue.js の Storybook で args に型を指定

# Vue.js の Storybook で args に型を指定

Vue.js の `.stories.ts` ファイル内で `args` が `any` になっていたので対応してみました。

https://github.com/ysKuga/vue3-storybook-args

- [対応した内容](https://github.com/ysKuga/vue3-storybook-args/pull/1)

## 追記

https://storybook.js.org/blog/improved-type-safety-in-storybook-7/#vue

> You can type check SFC files with vue-tsc and get editor support in VSCode by installing the Vue Language Features (Volar) and TypeScript Vue Plugin extensions.

2 つの拡張と `@storybook/vue3` を使用することにより
`.stories.ts` ファイル内でも Vue コンポーネントの型が確認できるようになっていたようです。

## 初期設定

以下の手順により Vue.js のプロジェクト設定と Storybook 設定を実施

```bash
yarn create vite . --template vue-ts
yarn
npx sb init --builder @storybook/builder-vite
```

設定後、 `src/stories/Button.stories.js` ファイルの拡張子を `.ts` に変更

ここで `Button.stories.ts` ファイルを開くと `args` など `any` になってしまっています。

![image](https://user-images.githubusercontent.com/17670283/190837442-696bdebd-c786-44c6-bcd9-ea49f0cf9871.png)

## 対応内容

以下が対応内容となります。
    
[Storybook の args の型について #1](https://github.com/ysKuga/vue3-storybook-args/pull/1)

- `.stories.ts` ファイル内で Storybook 用の型指定
- コンポーネントのスクリプトを `.ts` ファイルに分離

### `.stories.ts` ファイル内で Storybook 用の型指定

https://github.com/storybookjs/storybook/issues/17932

上記 Issue での回答を参考に型指定を実施

- [`.stories.ts` での型指定](https://github.com/ysKuga/vue3-storybook-args/pull/1/commits/45f1986e4138569143ff8b6c64a2509c33c9e5b4)

ただし、この状態だとコンポーネントの型が取得できていませんでした。

### コンポーネントのスクリプトを `.ts` ファイルに分離

以下はコンポーネントの型取得について参考にした Issue です。

https://github.com/vuejs/vue/issues/5298#issuecomment-402499566

今回対応した PR では前述の `.stories.ts` 内での型指定の手順と前後しているのですが、
`.stories.ts` 内でコンポーネントの型を取得するためにスクリプト部分を分離しました。

- [コンポーネントからスクリプトを `.ts` ファイルに分離](https://github.com/ysKuga/vue3-storybook-args/pull/1/commits/953b06838ee97b74f938e5fd8e07984ea8afed8c)

SFC とは・・・

Nuxt を使用する場合か、そのバージョンによってはコンポーネント側で拡張子を指定する必要があるかもしれません。

```vue
<script lang="ts" src="./Button.ts"></script>
```

## 対応の結果

対応により型が指定され `argsType` や `args` でのサジェストが出るようになりました。

![image](https://user-images.githubusercontent.com/17670283/190837817-89ad25d3-1640-43c3-8ee1-056c956f04b3.png)

![image](https://user-images.githubusercontent.com/17670283/190837797-88dd92fb-3898-4ce4-a7c0-094ae0f4f0de.png)

![image](https://user-images.githubusercontent.com/17670283/190837834-7d36820e-b0f0-4245-a20b-74c375072f6f.png)

もしかしたら別に正しい方法があるのかもしれません。
[DVA試験対策]AWS ECS



# AWSのコンテナサービス

コンテナのオートストレーションサービス（EKSも同様のサービス）。
実行環境はFargate,EC2があり、イメージレジストリはECR。

コンテナが実行されるまでの流れ
①ユーザーがオーケストレーターに指示
②仮想マシンにインストールされているエージェントからコンテナのランタイムを呼び出す
③イメージレジストリからコンテナイメージを取り出してコンテナを実行する
↓
手作業によるミスオペや効率ダウンをなくす


# ECSの要素
### タスク定義
・コンテナの仕様書。
・コンテナの定義（イメージの場所）、割り当てるIAMロールなどの情報が入っている。
・JSON形式。
・タスク定義は変更できない（イミュータブル）なので、更新したコンテナイメージ（古いイメージはバージョニングされているので別物）をタスク定義する（Familyパラメータ）。その後サービスを、古いものから新しいものに変え、見るサービスを変更する。
・コンテナ定義内でログの設定ができる。

### クラスター
実行環境の境界。タスク定義に基づいて実際に実行されるもの。複数のコンテナを1つのタスク上、ホスト上で実行される。

### サービス
タスクを決められた数コピーして、維持する。
ELB、オートスケーリングと連携できる。

# ECSの実行環境
### EC2
・ECSコンテナエージェントを実行（コンテナ内で実行されている）
・ECSコンテナインスタンスIAMロールを設定
・ECS-optimize AMIはスターターキットのようなものなので手軽に実行できる
・運用の手間がある
・スケーリングは自分でやる

### Fargate
・マネージドサービス
・コンテナネイティブなので起動時間や使用リソースに応じた料金設定（従量課金）
・AWSリソースとの連携（オートスケーリング、VPC)が自動でされる


## 機密情報の取り扱い
### Secret Manager シークレット
EC2起動タイプではJSONキーやバージョンを指定する

### Systems Manager パラメーターストア
同じリージョンの場合は名前で指定可能だが、別リージョンはARNを指定

## コンテナの実行方法
### タスク
タスク定義で指定されたコンテナを起動し、メインのコンテナが終了するとタスクも停止する、バッチ処理などのワークロード向け。
### サービス
指定した数のタスクを維持する。失敗した場合は、新しいタスク起動してを置き換える。
ELBやオートスケーリングなど。長時間使用するときに向いている。

## その他

### クラスターキャパシティープロバイダー
タスク配置を柔軟にコントロール
オンデマンド、スポットを割合で組み合わせられる。

### ターゲット追跡スケーリングポリシー
指定したメトリクスがターゲットの値に近づくように自動的に調整

### ステップスケーリングポリシー
アラームをトリガーに調整値に基づいて増減。ターゲット追跡スケーリングポリシーと組み合わせできる。
久しぶりにGithubActionsでDockerImageをビルドしたら署名に失敗した


# GithubActionsでビルドをしたらエラーが発生
イメージのビルドには成功しているが、最後の署名でエラーとなっている。

```bash
client.go:194: root pinning is not supported in Spec 1.0.19
Error: signing [ghcr.io/xxxxx/docker-images/yyyyy@sha256:a9e5759627ab935912cc005d38fe77e09e886235e91f1b5dbe1a65a03d54598d]: getting signer: getting key from Fulcio: verifying SCT: unmarshal: unexpected end of JSON input
main.go:46: error during command execution: signing [ghcr.io/xxxxx/docker-images/yyyyy@sha256:a9e5759627ab935912cc005d38fe77e09e886235e91f1b5dbe1a65a03d54598d]: getting signer: getting key from Fulcio: verifying SCT: unmarshal: unexpected end of JSON input
Error: Process completed with exit code 1.
```

# 原因：cosignのバージョンが低かったため

```diff_yaml:workflow.yml
      - name: Install cosign
        if: github.event_name != 'pull_request'
        uses: sigstore/cosign-installer@7e0881f8fe90b25e305bbf0309761e9314607e25
        with:
-          cosign-release: 'v1.4.0'
+          cosign-release: 'v1.9.0'
```

# 解決
イメージのビルドおよび署名に成功

```bash
Generating ephemeral keys...
Retrieving signed certificate...

        Note that there may be personally identifiable information associated with this signed artifact.
        This may include the email address associated with the account with which you authenticate.
        This information will be used for signing this artifact and will be stored in public transparency logs and cannot be removed later.
Successfully verified SCT...
tlog entry created with index: 3524110
Pushing signature to: ghcr.io/xxxxx/docker-images/yyyyy
```
EC2のネットワークアダプタ（NIC）を誤って無効化した時の対応方法

# はじめに

作成した仮想マシン（Windows Server 2019）でネットワーク設定を触っていた時、誤ってネットワークアダプタを無効化してしまいました。

これにより「仮想マシンの電源ON/OFFはできるものの、仮想マシンとの間で一切の通信が出来ない」という状態に陥り、仮想マシンにログインして操作できなくなりました。

そこで、今後同様の事態に陥った時に素早く対応できるように、この時の対応手順を記事としてまとめてみました。

# 対応方法

## 1. ネットワークインターフェースの作成

* EC2の画面から［ネットワークインターフェイス］に入り、Elastic Network Interface（ENI）を作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/6db0c84b-c161-e9ae-670b-d1d240cf2f52.png)

* リソースIDだけだと区別がつかなくなるので、ENI作成時に識別できる情報を入れておきます。
  * 「ネットワークインターフェースの説明」に使用する仮想マシンの名称などを入れておく。
  * 「Tagsオプション」に`Name`というキーのタグを作り、ENIの名称を入れておく。
* サブネットとセキュリティグループは、「復旧する仮想マシンと同じ設定」にします。
* プライベートIPv4アドレスは、デフォルトの「自動割り当て」のままで進めます。

![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/fc7347bb-1c02-c265-88c0-5e818ccfb780.png)

## 2. Elastic IPとネットワークインターフェースの紐付け（※オプション）

この章はElastic IPを使う場合の作業となります。

* Elastic IP画面の「割り当て ID」をコピーしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/2752a490-e6a2-3d24-b9e0-7d401d7eb630.png)

* ネットワークインターフェイスの画面で所望のネットワークインターフェースを選択した状態で、［アクション］>［アドレスの関連付け］と進みます。

![image (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/50370f3c-8503-14f0-311b-17aa80e87a75.png)

* ［アドレスの関連付け］画面で、ネットワークインターフェイスに紐づけるElastic IPの「割り当て ID」を指定します。
  * ここまでの操作で、ElasticIPとネットワークインターフェースの紐付けが完了します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/c46ecb2d-3a32-733b-5903-f2ee02c154ff.png)

## 3. ネットワークインターフェースの割り当て

* ネットワークインターフェイスの画面でネットワークインターフェイス IDをコピーします。
* EC2のインスタンス画面を開き、所望のインスタンスを選択した状態で［アクション］>［ネットワーキング］>［ネットワークインターフェイスをアタッチ］を選ぶ。
* ［ネットワークインターフェイスをアタッチ］画面で、ネットワークインターフェイス IDを指定してアタッチします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/88cf340f-d639-c707-3137-1c4f040e31fd.png)

# 参考URL

* [Amazon EC2 Windows インスタンスへのネットワーク接続を誤って無効にしました。この問題を解決する方法を教えてください。](https://aws.amazon.com/jp/premiumsupport/knowledge-center/restore-network-connectivity-windows/)
  * 「方法 2: 一時的な Elastic Network Interface を作成する」を参考にしました。
【Rails】f.text_areaのサイズ指定の仕方【Bootstrap】

# 結論

```html
<div class="form-label"> 
  <%= f.text_area :content, class: "form-control", style: "width:40%", rows: "3" %>
</div>
```

## 解説
+ 親要素に`form-label`のクラスを付与する。
→`form-floating`クラスだと`rows`の指定が出来ない。

+ `text_area`に`form-control`のクラスを付与する。

+ `text_area`内で`style: "width:XX%"`と`rows: "X"`を指定する。

## 注意
属性の付与は`○○:`といったシンボルの形式を指定すること。
`,class="{任意の値}"`のような形式を追加すると下記のようなエラーメッセージとともにバグが発生する。

```terminal
[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: https://www.ruby-lang.org/bugreport.html

[IMPORTANT]
Don't forget to include the Crash Report log file under
DiagnosticReports directory in bug reports.
```

# 参考

[Bootstrap5 公式リファレンス #Form Control](https://getbootstrap.jp/docs/5.0/forms/form-control/)

[Bootstrap3 formテキストフィールド横幅の指定の仕方](https://blog.shuffleee.com/248/)
見積もりの話 🤔

# 始めに
見積もりの精度を上げるためにどんなことに気を付ければいいのか、会社の人と話していて腑に落ちることがあったのでメモしておく
ちなみに、ここで見積もり対象としているのは、JIRAチケットのような粒度の小さい（数人日で終わる）タスクを指す

後、見積もりについての著名な本を読んでいる人からすれば、当たり前では？という内容かもしれない
自分はこの手の本は読んだことなかったので、その分新鮮に感じたのだと思う

# 結論
今まで経験したことのある内容であれば、経験値から精度の高い見積もりを算出できる（問題なし）
今まで経験したことのない内容であれば、`見積もりを算出するのではなく設定する`（論点はここ）

# 補足
重要なのは、`人は未来を予測することができないこと`を理解すること
精度の高い見積もりを出すためには、経験値という知識が必要であり、
経験値のない（知らない）ことに対して、見積もりを出すことはできないという当たり前を認識する
※ とは言っても「いつまでかかるか分からない」でタスクを始めるのは、共同して仕事を進めている上で好ましくない

上記を踏まえることで、その前提において戦略を考えることが出来るようになる
「経験値のない」ということは、そのタスクのゴールまでの道筋が明確でないことを意味する
その`明確でないものを拠り所にして考えること`が間違っていて、逆に見積もりを設定することでそれらをより明確にするという流れ

具体的には、他タスクの優先度や周りから期待されている工数等を考慮して、決めの見積もりを設定することで、その設定値から逆算して、そのタスクでやるべきことを明らかにする
イメージ的には、何か市場調査するみたいなタスクがあったとして、リソースが無限にあれば終わりがないけれど、現実は様々な制約があり、その中で最適解を出すことが求められるみたいな

そうやってタスクを消化していくことで、経験値の領域が広がって、精度の高い見積もりを算出できる機会も増えていく

# 終わりに
なんか無意識のうちにやっていたことを言語化できた気がする
Invoke-WebRequestはiwrで実行できるしcdの実態はSet-Location

PowerShellはコマンドプロンプトに比べてちょっとだけLinuxっぽいシェルになってる。

その実態はエイリアスをLinuxっぽくしてるだけで、実態はゴリゴリのPowerShellのメソッド。

```powershell
PS C:\Users\yugoy> alias

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Alias           ? -> Where-Object
Alias           % -> ForEach-Object
Alias           ac -> Add-Content
Alias           cat -> Get-Content
Alias           cd -> Set-Location
Alias           chdir -> Set-Location
Alias           clc -> Clear-Content
Alias           clear -> Clear-Host
Alias           clhy -> Clear-History
..
```

PowerShellのコマンドなげーよ！と思った人は、エイリアスをみれば短いコマンドがあるかも知れない。

例えば、Invoke-WebRequestが長いけどiwrというエイリアスがある。こんな感じでレスポンスを取り出すことができる。

```powershell
PS C:\Users\yugoy> (iwr http://yahoo.co.jp).content
```

PowerShellのメソッドは標準出力に値を返すのではなくオブジェクトを返すので、テキストだけ取り出したいときにはさらにメソッドを呼び出す必要がある。一見面倒くさいけど、レスポンスのヘッダとボディを分けて扱いたいときにはちょうど便利。
Nuxt3（RC版）にElementPlusをインストールする

※執筆当時のNuxt3バージョンはRC10のため、正式リリース後は変わる可能性があります


# Nuxt3プロジェクトを作成

- 公式リファレンスに従ってNuxt3プロジェクトを作成します
https://v3.nuxtjs.org/getting-started/installation

```bash
npx nuxi init nuxt-app
cd nuxt-app
npm install
```

# ElementPlusを導入

## ElementPlusのインストール

```bash
npm install element-plus sass
```

## プラグインのインストール

ElementPlusによると、Vue3では以下のように導入するようです。
https://element-plus.org/en-US/guide/quickstart.html

```typescript
// main.ts
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'

const app = createApp(App)

app.use(ElementPlus)
app.mount('#app')
```

Nuxt3ではcreateAppをしないので、プラグインとしてロードします
参考：https://v3.nuxtjs.org/guide/directory-structure/plugins/#vue-plugins

```element-plus.client.ts
import { defineNuxtPlugin } from 'nuxt/app';
import ElementPlus from 'element-plus';

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(ElementPlus);
});
```

`import ElementPlus from 'element-plus';`でプラグインモジュールをインポートし、`nuxtApp.vueApp.use`でインストールします。

## 型の適用

```tsconfig.json
{
  "compilerOptions": {
    // ...
    "types": ["element-plus/global"]
  }
}
```

## CSSの読み込み

```assets/css/indexscss
@use "element-plus/dist/index.css";
```

```nuxt.config.ts
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
  css: ['~/assets/css/index.scss'],
});
```


# 動作確認

## App.vueを修正

```App.vue
<template>
  <div style="padding: 20px">
    <el-button @click="onClick">test</el-button>
  </div>
</template>
<script lang="ts" setup>
import { ElMessage } from 'element-plus';

const onClick = () => {
  ElMessage({ message: 'test' })
}
</script>
```

## 起動

```bash
npm run dev -- -o
```

## アクセス

以下のようにElementPlusのボタンが表示され、押下時にメッセージが表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/211c8eda-e8a3-0aed-234c-21fa14c8d0bc.png)
ポートフォワードしながらブラウザでlocalhost管理画面を開くワンライナー

## サンプル

Windowsの場合（WSL2上で動かしています）

```bash
ssh [ssh接続先] -fNL 4567:localhost:4567; explorer.exe http://localhost:4567/
```
macの場合はこちら

```bash
ssh [ssh接続先] -fNL 4567:localhost:4567; open http://localhost:4567/
```

## 解説

- sshで接続しながらポートフォワード
    - `-L` がポートフォワード
    - `-fN` がバックグランドで接続
    - この例では、localhostの4567にアクセスすると、リモートホストの4567につながるポートフォワードを実施してる
- 成功したらフォワードされているポートに対してブラウザで開く
    - デフォルトのブラウザで開きたい
    - windowsの場合はexplorer.exe のあとに引数を与えることでデフォルトアプリで起動してくれる
        - WSL2という仮想環境とはいえWindowsのexeを呼び出すことはできる
    - macの場合はopenコマンドでデフォルトのアプリが起動する
    - 「デフォルトブラウザ」のさらに手前のデフォルトアプリを起動させてるのがポイント

## 背景

いわゆる管理画面は限られた人しか使わないので、インターネット上に公開する必要などない。なので以下のような管理画面がセキュア。

- localhostからしかアクセスできない管理画面を4567のポート（よくある開発モード）で起動
- 外部からマシンの接続はsshのみ（つまり最小限）
- 画面に接続する際にはsshのポートフォワードで接続し、localhostに対してブラウザで開く

## 使い方

以下のようにエイリアスに入れておくと便利。

```bash:.bash_aliases
alias kanrigamen='ssh  [ssh接続先] -fNL 4567:localhost:4567; explorer.exe http://localhost:4567/'
```

## 未検証の発展系

ssh使えるという時点で開発者向けツールだけど、非開発者が1人もしくは2人で運用する画面もありえる。
その場合は素のWindowsで実行したい。

イマドキのWindowsはOpenSSHが入ってるので、puttyなどのsshクライアントを使わずともほぼ同じ機能のsshが使えるはず。

- PowerShell上で
- OpenSSHのssh.exeを使ってポートフォワードして
- explorer.exe を使って管理画面を開く

ということはできていいはず。sshのキーペアの設定は最初はエンジニアのサポートが必要だけど、逆にそれくらいのひと手間があった方がいい。
Stable Diffusionをローカル環境で動かした

## 環境
- windows11(64bit)
- vs code:1.71.1
- RAM16G
- GPU NVIDIA GeForce RTX 3060
- python3
- pip
## hugfaceに登録する
Stable Diffusionをローカル環境で動かすためには[Hugging Face](https://huggingface.co/)のアカウントを作る必要がある。
>[【簡単】ローカル環境でStable Diffusionを実行する方法](https://self-development.info/%e3%80%90%e7%b0%a1%e5%8d%98%e3%80%91%e3%83%ad%e3%83%bc%e3%82%ab%e3%83%ab%e7%92%b0%e5%a2%83%e3%81%a7stable-diffusion%e3%81%a7%e5%ae%9f%e8%a1%8c%e3%81%99%e3%82%8b%e6%96%b9%e6%b3%95/
)


### hugfaceに登録


https://huggingface.co/blog/stable_diffusion

### 次にAccess Tokensを入手

https://huggingface.co/settings/tokens

入手したAccess Tokensはメモしておこう

VScodeのターミナルで
```
pip install diffusers
```

longpath が許容されない場合は↓を参考に
[How to Make Windows 10 Accept File Paths Over 260 Characters](https://www.howtogeek.com/266621/how-to-make-windows-10-accept-file-paths-over-260-characters/)

## pytorchの導入
pytorchはpythonのオープンソース機械学習ライブラリ

pytorch導入前にwindowsを開発者モードにしましょう 

[pytorchの公式ページ](https://pytorch.org/get-started/locally/)から
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2847174/7c1f3385-f5d7-591b-87f9-5efb984abc1b.png)

PCの環境に合わせてputorchのオプションを選べるので、適切な項目をえらんで
```
pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu113
```
https://self-development.info/pytorchの簡単過ぎるインストール【pythonで機械学習】/

http://tecsingularity.com/cuda/version_conf/

## デモコードの実行
ここまでできれば下準備が整ったはずです。ローカル環境に適当にフォルダ作って以下のコードを実行

```demo.py

import torch
from diffusers import StableDiffusionPipeline
from torch import autocast
 
MODEL_ID = "CompVis/stable-diffusion-v1-4"
DEVICE = "cuda"
YOUR_TOKEN = "コピーしたアクセストークン"
 
pipe = StableDiffusionPipeline.from_pretrained(MODEL_ID, revision="fp16", torch_dtype=torch.float16, use_auth_token=YOUR_TOKEN)
pipe.to(DEVICE)
 
prompt = "a dog painted by Katsuhika Hokusai"
 
with autocast(DEVICE):
  image = pipe(prompt, guidance_scale=7.5)["sample"][0]
  image.save("test.png")
```
>https://self-development.info/【簡単】ローカル環境でstable-diffusionで実行する方法/

フォルダ内にtest.pngの画像が生成されれば成功です

絵の内容を変える場合、```prompt = '' ```を変更します。
今回は```prompt = 'consept idea of The street of Medieval Europe daytime'```
で試してみました。
## 出力結果
![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2847174/f870f0fc-394e-133b-d521-645cc8eeb6e7.png)
いいですね
phpでhello world出力方法、2パターンの連想配列

基本知識

```javascript
<?php

$hello = "hello world"

echo $hello
?>

```


PHPで連想配列、その１
```javascript

<?php
//その①
$person3 = [ 
    "name" => "ST",
    "age" => 20,
    "home" => "kagawa"
];

echo "<pre>";
print_r($person3);
echo "</pre>";

//その②
$person4 = [];
$person4["name"] = "TY";
$person4["age"] = 30;
$person4["home"] = "tokyo";

echo "<pre>";
print_r($person4);
echo "</pre>";

?>

```


PHPで連想配列、その2 

```javascript
//その①
let person5 = {
            name: "太郎",
            age: 26,
            home: "tokyo"
        };

        echo "<pre>";
        print_r($person5);
        echo "</pre>";


//その②
        person6 = {};

         person6["name"] = "次郎";
         person6["age"] = 40;
         person6["home"] = "kanagawa";

         echo "<pre>";
        print_r($person6);
        echo "</pre>";

    </script>


```
Dockerにおいてソースコードが即時反映されない問題について

# 背景
現在就職のためのポートフォリオを作成しているのですがその際、Docker環境のrailsでソースコードを書 いているときにソースコードが即時反映されなかったので、即時反映される方法を記しておきます。

# 即時反映させる方法について
自分が調べた限りでは即時反映させる方法は2つありました。

**一つ目ですが**
```ruby:config/environments/developments.rb
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
```
これを・・・
```ruby:config/environments/developments.rb
config.file_watcher = ActiveSupport::FileUpdateChecker
```
とすれば大丈夫です！
# 何をしているのか？
これは
・ファイルの保存イベントを監視するのか
・ファイルを追跡して変更を監視するのか
の違いがあるらしいです！
```ruby:config/environments/developments.rb
config.file_watcher = ActiveSupport::EventedFileUpdateChecker
```
の状態だとファイルを追跡して変更を監視する状態になっています。
ですのでこれを
```ruby:config/environments/developments.rb
config.file_watcher = ActiveSupport::FileUpdateChecker
```
に変更して、ファイルの保存イベントを監視する状態に変更してあげるとソースコードが即時反映されるようになります。
詳しく知りたい方は以下参考にしてみてください。
・[Class: ActiveSupport::EventedFileUpdateChecker | RubyDoc.info](https://www.rubydoc.info/github/rails/rails/ActiveSupport/EventedFileUpdateChecker)
・[Class: ActiveSupport::FileUpdateChecker](https://www.rubydoc.info/github/rails/rails/ActiveSupport/FileUpdateChecker)

**２つ目の方法ですが**
開発ディレクトリをDockerコンテナにマウントすることで編集時に即時反映することが可能です。

どういうことかというと・・・
```ruby:docker-compose.yml
version: '3'
services:
  db:
    platform: linux/x86_64
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root
    ports:
      - "3306:3306"
    volumes:
      - ./tmp/db:/var/lib/mysql

  mangabestgram:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/mangabestgram
    ports:
      - "3000:3000"
    depends_on:
      - db
```
開発環境一式をdocker-composeで管理しているので、docker-compose.ymlで上記のようにvolumesの設定をすることで、実行ディレクトリをそのままdockerのアプリ実行ディレクトリにマウントすることができます。
```ruby:docker-compose.yml
volumes:
      - .:/mangabestgram #この部分でマウントしている(実行環境のディレクトリに随時書き替えてください)
```
# 最後まで閲覧ありがとうございました
自分の勉強のアウトプット用なので、読みにくい点や分かりにくいところも多々あるとは思いますが、ご了承ください。
他に追記することや間違っていることなどあればコメントなどしていただけると幸いです。
pycaret→LightGBMのツリー構造可視化

# 初めに
私が日常の解析でPycaretで手法選定をしていると
LightGBM、ランダムフォレストが好成績であることがしばしばある
そして、ツリー構造を調べたくなる経験が多い

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/827921ef-eac1-200f-829f-5443cbcd439a.png)

# PyCaretの実行
~~~python
import numpy as np
import matplotlib.pyplot as plt
import plotly
import pandas as pd
import os
import seaborn as sns

from pycaret.regression import *
from sklearn import preprocessing,linear_model,svm,ensemble
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split,cross_val_score
import warnings
warnings.filterwarnings('ignore')
%matplotlib inline

#データインポート
data_train = pd.read_csv('train.csv')
data_test = pd.read_csv('test.csv')

#pycaret起動
expl=setup(data_train,
           target='MedHouseVal',
           test_data=data_test,
           session_id=1,
           normalize=False,
           transformation=False,
           transform_target=False,
           numeric_features=[],
           ignore_features=['Unnamed: 0']
          )

#モデルの比較
compare_models(sort='rmse',fold=4,n_select=3)
#モデルのパラメータ最適化
lgbm=create_model('lightgbm',fold=4)
tuned_lgbm=tune_model(lgbm,n_iter=100,optimize='rmse',fold=4)
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/62ed8210-f701-1568-8d23-cb3cba97b62f.png)

なお、訓練データ、テストデータについては下記の私の記事から作成したので割愛する。

https://qiita.com/shimokame777/items/d370a7ac94432e222dc5

# 最適化したLightGBMの詳細を知る
上記コードの`tuned_lgbm`が最適化した変数となっているので
そのまま変数名を入力するだけで詳細がわかる。

~~~python
tuned_lgbm
~~~

実行してみると、scikit-learnのLGBMRegressorが使用されていることがわかる。つまりPycaretが統括して各種クラスを使用して最適化を図っているようだ
今回のLGBMRegressorは`plot_tree`で可視化できるので実行してみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/1f444e62-f145-1178-f0bb-43702d2c21bc.png)


# Plot_treeの実行
可視化の前に
`graphviz`のインストールを忘れずに
Windows＋Anaconda環境であればAnaconda Promptで
~~~
conda install python-graphviz
~~~
を実行し、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/e03131f4-4cb5-ab6a-0ce8-cfb98fa0a192.png)
の環境変数のPathに
~~~
C:\Users\ユーザー名*\anaconda3\pkgs\graphviz*\Library\bin
~~~
を追加し、リブートすればよい。
（ユーザー名やgraphvizのバージョンは環境で異なるため、ワイルドカード*部は変更すること）

~~~python
import lightgbm
import graphviz
lightgbm.plot_tree(tuned_lgbm, tree_index=0,figsize=(150, 100));
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2696103/a6f57aa8-fbe2-f1e6-e6c1-41e7442199a8.png)

なお、下記のようにfor文でループさせることで
Leaf-wiseの様子が可視化できると思います。
~~~python
for i in range(tuned_lgbm.n_estimators):
    lightgbm.plot_tree(tuned_lgbm, tree_index=i,figsize=(150, 100));
~~~

# 最後に
決定木、ランダムフォレストも同様に可視化できますので
解析時にどの因子をどのくらいのThresholdで分類しているのか
理解するときに役立つと思います。
以上　最後までお読みいただきありがとうございました。
パソコンのパワードスピーカーの再利用

NecのValue Starに付いてたパワードスピーカーを鳴らしてみたところ音を大きくするとノイズが混じります。

よくよくスピーカーを見てみると、ウレタンのエッジに亀裂が入っています。

スピーカーを直すことも考えたのですが、小さいので結構面倒です。

ACアダプタは純正のDC9V 500mAのものがちゃんと残っています。

しばらく放置していたのですが、今日の朝見直してアンプだけを再利用する事にしました。

アンプが入ってる方(L)は直にスピーカーに結線されていて、反対側(R)は後ろのジャックから送るようになっています。

このジャックはモノなのですが、よくよく見ると三つ端子があるので、ステレオで出せます。

パターンをカットして、直付けされているLの+側をつないで、ステレオで出せるようにします。

![AMP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/a41d274b-f929-26c3-9a54-9284bc1c3000.png)


![IMG_20220917_085228.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/dc173e1e-66ff-06a2-ca54-2e8fa9a0faa7.jpeg)

40年前に作ったスピーカーにつないでテストしてみました。70年代のスピーカーはエッジが布だったりするので、まだ使えるものも多いですが、80年代にはいってウレタンが使われるようになり、そのころのものはもうぼろぼろになって使い物になりません。

右左ともちゃんと出力されます。結構大きな音鳴ります。

ステレオミニプラグから左右のスピーカーに接続するケーブルを作りました。

ミュート回路がないので、電源投入じにボツっと音がでます。

このアンプはDIP 16ピンのICでヒートシンクがのってるので型番は確認できませんが、中央の4ピンがGNDのピン配列からTEA2025なような気がします。

TEA2025はセカンドソースもありますが、時期的にSTのオリジナルと思われます。

1/2Wくらいの大きな金属皮膜抵抗が使われていて、結構こった作りに見えます。

TEA2025を使ったキットは1000円もしませんが、あったので使えるようにして見ました。

TEA2025は2000年初頭の製品でこの頃にはD級のチップも出始めていましたが、TEA2025はD級ではありません。

80年代はワンチップのアンプというと東芝(TA7222APなど)が良く使われていましたが、やめちゃってたみたいですね。

SOTECのスピーカにはTDA2822Lが使われていました。これのスピーカーのエッジは紙か布で大丈夫そうです。
【Swift】TableViewのnumberOfRowsInSectionとcellForRowAt indexPath


# はじめに
table viewを実装する際におまじないのように書いていた下記のコードについて、少し意味を考えてみた。
```swift:
let itemArray = ["A", "B", "C"]

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 
    }
```

# 環境
| No |    項目     |   内容    |
|---:|-------------|------------|
| 1  |      OS       |   Mac     |
| 2  |      Swift    |   5.6.1 |
| 3  |      Xcode     |   13.4.1 |

# 実装
まず、実際にはこんな感じで実装する。
```swift:
let itemArray = ["A", "B", "C"]

// ①テーブルに何行のリスト、何個のセルを入れるか
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return itemArray.count
    }

// ②セルの数だけこの関数が呼び出される。indexPathプロパティはUITableViewで用意されている。(delegateメソッド)
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: K.cellIdentifier, for: indexPath)
        
        cell.textLabel?.text = itemArray[indexPath.row]
        print(indexPath) //[0, 0][0, 1][0, 2]
        
        return cell
    }
```
**①numberOfRowsInSection**
[tableView(_:numberOfRowsInSection:)](https://developer.apple.com/documentation/uikit/uitableviewdatasource/1614931-tableview)
何行あるかを伝える。
returnした数（INT）のセルだけ、テーブルにレンダリングされる。

**②cellForRowAt indexPath**
[tableView(_:cellForRowAt:)](https://developer.apple.com/documentation/uikit/uitableviewdatasource/1614861-tableview/)
再利用可能なセルをreturnする。
・tableviewには再利用するセルのクラスを記載する。（基本変えない）
・indexPathにはテーブルの行を示す座標を記載する。（配列を順番通りに表示する場合は基本変えない。）

dequeueReusableCellにセルのIDとindexPathを入れる。
indexPathはdelegateのため、UITableViewのプロパティを利用して、テーブルの座標情報を取得する。

indexPathプロパティを用いてrowの番号を取得することで、セルに入れる文字を行に合わせてレンダリングすることができる。

# おわりに
さまざまなクラスやプロトコルが用意されているので、とても便利だが、なんとなくこうかなくらいの理解しかできないのが難しいです。ご指摘があれば気軽にコメントしてください。
なぜか、STM32G071が当たった、よって、Lちか(準備中)(Arduino)



目的
GPIOのテスト


いろいろ
ST様からキャンペーンかなにかでNUCLEOを貰った
STM32G031J6M6の開発用に応募した。
STM32G031がなぜか世界中からない(2022/09/17)
基本STM32G031のプログラムは、そのまま動くはず
いまは、そんなところ
みんな、STM32G031J6M6のすごさにきずくの遅すぎ
STM32G031J6M6のArduinoの半二重シリアルに約2日
かけたのは、無駄では、なかった。



![o_con756.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/7c024717-91f7-df93-7cbf-81861572f535.jpeg)



GPIO_Blink_PA5_071_1




```c++



/*
  Blink

  Turns an LED on for one second, then off for one second, repeatedly.

  Most Arduinos have an on-board LED you can control. On the UNO, MEGA and ZERO
  it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN is set to
  the correct LED pin independent of which board is used.
  If you want to know what pin the on-board LED is connected to on your Arduino
  model, check the Technical Specs of your board at:
  https://www.arduino.cc/en/Main/Products

  modified 8 May 2014
  by Scott Fitzgerald
  modified 2 Sep 2016
  by Arturo Guadalupi
  modified 8 Sep 2016
  by Colby Newman

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Blink
*/

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(PA5, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(PA5, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(PA5, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);                       // wait for a second
}



```
Qiita Daily Survey memo 2022.09.17

# Qiita Daily Survey memo 2022.09.17

Qiita の記事を可能な限り毎日読むために、読んだmemoを公開することでモチベーションを維持しようという試み。（2日目）

## [Herokuの無料枠が廃止になるのでDeta.shへ移行する](https://qiita.com/namachan/items/b8c1ee89dc091d656d4f)

namachan 様の記事

昨日に引き続き、Heroku の無料枠終了の話題があったので、気になって拝見させていただきました。
2022/11/28 までに有償版にアップグレードしてね、との情報も連携いただきました。

昨日は「Render.com」への以降の記事でしたが、本日は「Deta.sh」というサービスがあるそうで、そちらをご紹介いただいています。

アプリの構造までは追いかけ切れていませんが、デプロイまでのフローも書かれており、わかりやすそうです！

やはり、無料でのPaaSというとHerokuの印象が強かったので、皆様移動先を探していらっしゃるご様子…。
しばらく、動向を追いかけたいと思いました。

## [IEサポート完全終了記念（？） 今後使いたい、便利なCSSプロパティ・HTMLタグ、＆etc](https://qiita.com/transel/items/c401fcd0d6da8220128c)

transel(transel) 様の記事。

今まではIEで閲覧していたために使えなかったCSSのうち、便利なものをまとめて紹介してくださっている記事になります。

「うひょー！」とか声を上げながら、サンプルを拝見させていただきました。
ﾎﾝﾄﾆｽｺﾞｲ…
CSSど素人なのでどれもすごく感じましたが、特に「背景をテキストの形でクリッピング | Background-clip: text」の項目は「これがjavascriptなしか…」という感じです。

デザインする際に、是非参考にさせてもらおうと思いました！

## [SQLの練習ができる学習サービス「SQLab」を作ってみた](https://qiita.com/paolo_takechi/items/6b69767d8efbd013bf64)

paolo_takechi 様の記事。

タイトルの通り、SQL を学習できるサービスの作成を記事にまとめてくださったものです。
ちょうど苦手なSQLをお仕事で使っており、苦戦していたのでタイムリーな記事でした。

早速利用させていただきましたが、まずUIがめちゃめちゃ好みで、とても使いやすかったです。
また、問題やデータも見やすく直感的で、利用しやすかったです。

お勉強のため、もう少し利用させて頂きたいと思います…！

サービスを作るのは本当に大変で、ここまでクオリティの高いものを作成し、それを記事にして公開してくださっていることに感謝です！

## [高校の文化祭でソフトウェア開発をしたお話](https://qiita.com/YumNumm/items/32ffcced7193e11930d9)

Yum Numm(Yum Numm) 様の記事。

文化祭に向けて開発をされ、その内容を記事にまとめてくださっている内容です。

ルーズリーフに書き殴られた設計が、とてもとても印象的でした…。なつかしい！
学生の間に、全力の開発を経験されて、その上で内容を振り返り記事にまとめていて、凄いなーと思いました…

学園祭の動画の雰囲気もとても良く、楽しく（もちろん過渡期はバックエンドをSaaSに任せるなど、大変だったとは思いますが）開発ができているようで、充実感が画面のこちらがわまで伝わってきました。
また、サービスの作成が始めてではなさそうで、いろいろなことに挑戦していて羨ましい…！

自分のサービス作成に向けてエネルギーを貰いました。
FlutterのRiverpodで配列を扱っているとref.watchで内容が更新されない時の対処法

## 追記
StateProviderは現在非推奨になってます。StateNotifierProviderを使いましょう。

## どのような場合に起こるか

RiverpodでListを使用しているときに内容を変更したのにそれがref.watchで監視している場所に通知されないことがあります。
そのような場合おそらくこのような書き方をしていませんか?

```Dart:Dart 
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';


final textListProvider = StateProvider<List<String>>((ref) => []);

final numberProvider = StateProvider<int>((ref) => 0);


class ChatView extends ConsumerStatefulWidget {
  const ChatView({Key? key}) : super(key: key);

  @override
  ChatViewState createState() => ChatViewState();
}

class ChatViewState extends ConsumerState<ChatView> {

  void addText() {
    ref.read(textListProvider.notifier).state.add(ref.read(numberProvider).toString());
    ref.read(numberProvider.notifier).state++;
  }


  @override
  Widget build(BuildContext context) {
    final texts = ref.watch(textListProvider);
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: List<Widget>.generate(texts.length, (i) {
          return Center(
            child: Text(
              texts[i],
            ),
          );
        }),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: addText,
      ),
    );
  }
}


```
ここで注目してほしいのがaddTextメソッドで，ref.readで取得してきたtextListProviderの値をaddを用いて変更しています。このような場合は変更が通知されず，ref.watchで監視していたとしてもWidgetは更新されません。

## なぜか
これはStateがイミュータブル(変化しないもの)でなければならないことに起因します。
addやinsertなどの関数を利用して値を変更してもそのProviderで使用されている変数のインスタンスは変化していないので変更が通知されず，結果的にWidgetも更新されないという仕組みです。
これに関して特にコンパイルエラーやLinterのエラーも発生せず，一度HotReloadを挟むと変更された値が表示されてしまいます。そのため非常にエラーの原因に気づきにくいものになっています。
ドキュメントにはStateはイミュータブルにしないといけないと書いてあるのでちゃんと読みましょう。

## どうすれば良いのか

新しく配列を作り直し，それを代入すれば通知されます。
新しく配列を作る際はスプリット演算子などを用いて以下のようにする必要があります。

```dart: Dart
    final t = ref.read(textListProvider);
    t.add(ref.read(numberProvider).toString());
    ref.read(textListProvider.notifier).state = [...t];
```
ここで注意しなければいけないのは直接tを代入してはいけないということです。直接tを代入してしまうとデータのメモリアドレスが変更されないため通知されないのだと考えられます。スプリット演算子を用いた`[...t]`の書き方であれば完全に新しい配列になるので通知されます。

## 参考文献

[【Riverpod】Listの値を更新したのにref.watchで再描画されない](https://zenn.dev/shu_illy/articles/d43e842ea9ad4e)
[StateNotifierProvider(Riverpod公式ドキュメント)](https://riverpod.dev/ja/docs/providers/state_notifier_provider/)

## 最後に
何かご指摘等ありましたらコメントにお願いします。