OmniAICreator/Qiita-1.07M huggingface dataset:
SQL Serverで新しいDBを作成する

# 1. はじめに
* SQL Serverでデータベースを作成する機会があったため、手順として残しておきたい

# 2. 開発環境 
* SQLServer 2017
* Microsoft SQL Server Management Studio v18

# 3. データベース作成手順
## 3.1. 新しいデータベースを追加する
* Microsoft SQL Server Management Studioを開く
    * Databaseを右クリックして、New DatabaseからDBを追加する

## 3.2. ログインユーザーを追加する
* Secruity > Logins を右クリックして、New Loginを選択する
    * SQL Server authenticatioを選択して、パスワードを入力する
    * Enforce password policyのチェックを外す
    * Enforce password expirationのチェックを外す
    * User must Change password at next loginのチェックを外す
    * Default Databaseを New Databaseに変更する

## 3.3. 新しいデータベースにログインユーザーを設定する
* Database > New Database > Security > Usersを右クリックして、New Userを選択する
    * Generalページで、Login nameより作成したアカウントを選択、Login nameを入力する
    * Membershipページで、db_datareader, db_datawriter, db_ddladminの権限にチェックをする

# 4. 参考文献

https://www.ipentec.com/document/sql-server-create-database
C#のWindowsフォームのコントロールを文字列で操作してみる

# 1. はじめに
* C#のWindowsフォームアプリのコントロールを文字列としてコードから制御したい
* Windowsフォームのコントロールをすべて取得して一括でプロパティをセットしたい

# 2. 開発環境
* C#
* .NET 6
* Visual Studio 2022
* Windows 11

# 3. Windowsフォーム（デザイナー）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/799cd3a5-3f34-ffb2-b6a9-29270de8e576.png)

* Label 1～3
* Textbox 1～3

# 4. コードビハインド
```csharp:Form1.cs
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {
        foreach (Control ctrl in this.Controls)
        {
            this.Controls[ctrl.Name].Text = "Test";
        }
    }
```

# 5. 動作確認
* 全コントロールのTextプロパティを"Test"に変更してみた
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/cac06c3a-4908-73ee-d34c-81d300e4b388.png)

# 6. 参考文献

https://blog.hiros-dot.net/?p=4590
ラムダ式

## ラムダ式とは
・関数を直接表現するためのもので、引数を受け取って値を返す。
・メソッドに似ているが、名前をつける必要がなくメソッドに実装することができる。
　→従来のJavaでは、関数を表現するためにインターフェースを定義し、そのメソッドをオーバーライドするクラスを作成する必要がある。しかしラムダ式を使用することで、関数を匿名で定義し直接渡すことができる。
ラムダ式を使うことで、コードが短く、より直感的になる。


## 書き方
```java
(型 引数1, 型 引数2,・・・) -> {
    処理;
    return 戻り値
}

//例
int func = (int x) -> {return x * 2;}
```

### 省略記法
・代入文の右辺で使う場合、引数の右辺を省略可能
・引数が１つの場合は()を省略可能
・単一のreturnの場合、{}とreturnを省略可能
```java
int func = x -> x * 2;
```

## 使用例
比較しながら使用例を確認

**ラムダ式を使わない場合**
```java
interface Greeting {
    String greeting(String name);
}

public class Hello {
    public static void main(String[] args) {

        Greeting human = new Human();
        System.out.println(human.greeting("高畑")); // こんにちは高畑さん
    }
}

class Human implements Greeting {
    @Override
    public String greeting(String name) {
        return "こんにちは" + name + "さん";
    }
}
```

**匿名クラスで書いた場合**
```java
interface Greeting {
    String greeting(String name);
}

public class Hello {
    public static void main(String[] args) {

        Greeting human = new Greeting() {
            @Override
            public String greeting(String name) {
                return "こんにちは" + name + "さん";
            }
        };
        System.out.println(human.greeting("高畑")); // こんにちは高畑さん
    }
}
```

**ラムダ式を使った場合**
```java
interface Greeting {
    String greeting(String name);
}

public class Hello {
    public static void main(String[] args) {

        Greeting human = name -> "こんにちは" + name + "さん";
        System.out.println(human.greeting("高畑")); // こんにちは高畑さん
    }
}
```
ラムダ式は匿名クラスと同じく、実装クラスを作成せずにインタフェースのメソッドを使うことができます。
ラムダ式は短い記述で関数を表現することができるので、匿名クラスに比べて簡潔に書けました。
🐛🔨GitHub絵文字を雑に検索できるようにしてみた

# イメージ
![GitHubPictograph_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521440/ca0ac301-eebe-d9d6-6e81-8ef01ea7f78f.gif)

# URL
https://setools.tokyo/GitHubPictograph
for で散々盛り上がったようですが...

for も，言語によって文法，実行結果は色々です。
同じ **for** という単語が使われていても，言語によって実際の挙動は違う可能性があります。

---

## 制御変数を途中でいじるとどうなる?

C においては，途中で制御変数を変更すると，意図した通り（?）次のループは変更した値を更新した値で実行されます。i を 5 にして，しかる後次のループでは i++ して 6 として実行。

```C
#include <stdio.h>
int main(void){
    int i;
    for (i = 0; i < 10; i++) {
        printf("%d\n", i);
        if (i == 3) {
            i = 5;
        }
    }
}
```
実行結果
```
0
1
2
3
6
7
8
9
```
Python では，制御変数をどういじろうが，粛々と実行が進みます。
つまり，前もって制御変数のリスト（正確な用語ではないかもしれないが）が作られそのリストに従って，順に制御変数に割り当ててループが実行される。
```Python
for i in range(10):
    print(i)
    if i == 3:
        i = 5
```
```
0
1
2
3
4
5
6
7
8
9
```
---

## ループを break で脱出したあとの制御変数の値はどうなる

Python では，break したときの値が保存されています。
```Python
for i in range(10):
    if i == 3:
        break
print(i)
```
```
3
```

C でも，同じです。

```C
#include <stdio.h>
int main(void){
    int i;
    for (i = 0; i < 10; i++) {
        if (i == 3) {
            break;
        }
    }
    printf("%d\n", i);
}
```
```
3
```
でも，Julia だと，スコープの関係で，ループを抜け出すと制御変数は「蒸発」しています。

```Julia
julia> for i = 0:9
           if i == 3
               break
           end
       end

julia> print(i)
ERROR: UndefVarError: `i` not defined
Stacktrace:
 [1] top-level scope
   @ REPL[2]:1
```
---

なんだかんだと言っても，for にしろ何にしろ，それぞれの言語仕様によるので，一概に 「for はなんとかかんとかなんだよ。」と決めつけるのは良くないでしょうね。

C や BASIC (ALGOL なども)，for は 「 i を 1 から n まで k 刻みで変化させて以下を実行してね」ということだったけど
Python や Julia その他の for は「i を 1 から n まで k 刻みまで変化してできる集合を順番に取って，以下を実行してね」になっている。だから，途中で制御変数をいじっても，何の遅滞もなく物事が進む。

今更ではあるが，「ドイツ語のfürの意味」についてあえてこじつけるなら，昔の言語 C, BASIC, ALGOL は「❼ ⸨時間的⸩ ⸨期間を表して⸩ …の間〔の予定で〕; ⸨予定の日時を表して⸩ …に.」なのかもしれないが，最近の新しい言語では「❿ ⸨反復・連続；無冠詞の同一語を反復して⸩ …ずつ, …ごとに.」に近いのかもしれない。

後者に関しては，for each に近いのだろう。繰り返しについてはあと2つ，for next, do loop がある。

要するに，「郷に入れば郷に従え」。個人的な感想・感慨はおいておいて，各言語の文法規約に従いましょう。従わないとプログラムが動かないんだからしようがない。
(自分用覚書)HP純正のドッキングステーションを使ったらネットワーク切れが頻発する

※自分用の覚書なのでいろいろ適当です
※自力ではほとんど判明しておらず、ご協力いただいた方に感謝申し上げます。

#### 使用機器
1.ネットワーク機器：SA-W2
https://www.seil.jp/saw-mpc/doc/sa/hardware/saw2.html

2.PC：HP EliteBook 830 G8
https://jp.ext.hp.com/blog/bnb/product/HP_EliteBook_830_G8/

3.ドッキングステーション：HP USB-C Mini Dock
https://support.hp.com/jp-ja/product/setup-user-guides/hp-usb-c-mini-dock/17859030

#### 発生している事象
①ネットワーク機器⇔ドッキングステーション⇔PCの構成で業務している。
②ネットワーク機器とドッキングステーションはLAN線で接続している。
③新しいPCにしてからネットワーク接続切れが多いといわれていたため調査した。

#### 結論
①ドッキングステーションのドライバがWindows10 22H2に適合していない。
②ドッキングステーションのドライバをアップデートしようとしたがアップデート方法がHPのHP上に掲載されていない。
③HPサポートに直接問い合わせた結果、ドッキングステーションのファームウェアの更新は方法は教えてくれたがWindows10 22H2のドライバ更新時期は未定と回答があった。

④ファームウェアのアップデートしたうえで、ネットワーク機器とPCを接続する→HP社用ツールを使ってもアップデート済のため対応なし

⑤他社製のドッキングステーションを使って回線接続
　→月末の可能性もあるため様子見
　　→ユーザーの体感速度が変わらなかったので、別機種を再配布することとした

#### 気づくまで試したこと
①PCのWindows updateを最新まで適応する
②PCのドライバを最新にする
③HPのアシストアプリを使ってドライバ判定を実施する
④LAN線を新しいものに変える
⑤ネットワーク機器の再起動する
⑥ネットワーク機器の置く場所を移動する


#### 気づかなかった理由（というなの言い訳）
「PCを変えたらネットワーク切れがよく起きる」との意見を素直に信じすぎてしまった。
ネットワーク機器の問題だと思い込んでいた。
ドッキングステーションなんてどれも同じでファームウェアの更新は不要だと思っていた。
herokuを短時間だけ試したい時に適したプラン

# 結論

Ecoではなく、Basicが良いです。

# 解説

|  | Eco | Basic |
|:-:|:-:|:-:|
| 課金単位 | 月単位 | 秒単位 |
| 価格 | $5 / 月 | 約$0.01(約1.5円) / 時間  |
| 最大 | 1,000時間まで | 1アプリあたり $7 / 月  |
| スリープ | あり | なし |

Ecoが一番安そうに見えますが、１日だけ使っても $5 です。
それに比べて、Basicは約$0.01（約1.5円） / 時間です。

例えば4時間なら6円、チロルより安いです。
丸１日なら36円、セコイヤチョコレートより安いです。

# Basicプランのアプリを作る

appを作る時にプランの選択はありません。
デフォルトで自動的に「Basic」のアプリが作られます。

# アプリを停止する

「Resources」タブで鉛筆ボタンを押して、オフにして「Confirm」ボタンを押して停止します。

:::note alert 
使い終わったら必ず停止させます。停止しないと課金され続けます。
:::

:::note warn
GitHubの連携を切ったり、アプリを削除したりする必要はありません。
停止するだけで課金されなくなります。
:::

:::note
利用金額が $0.09 だった月は丸められて課金されていませんでした。
最低課金額があるのかも知れません。
:::
automatorでJupyterLab Desktopの親ディレクトリを固定する

適当なノートブックをJupyterLab Desktopで開くと親ディレクトリがそのファイルのあるところになってしまう。   
それが嫌だったので、automatorでapplescriptを使って全部親ディレクトリを統一します   

まず、automatorを開き、アプリケーションを選択   
applescriptを実行をドラッグしてきて、以下のコードをコピペ、   
その際に`/Users/working_dir_path`の部分を自分のものに変更してください。   
```
on run {input, parameters}
	set len_input to length of input
	if len_input = 0 then
		do shell script "/usr/local/bin/jlab /Users/working_dir_path"
	else
		set anAlias to item 1 of input
		set path_ to POSIX path of anAlias
		do shell script "/usr/local/bin/jlab --working-dir /Users//Users/working_dir_path " & path_
	end if
end run
```
最後に「ファイル」→「書き出す」からどっかに保存してください

あとは.py, .ipynbなどのファイルを右クリックして「情報を見る」から、「このアプリケーションで開く」で選んだ後に「すべてを変更」でok

一応アプリダブルクリックでも開くようにしています。

---


やっていることとしては、
```
on run {input, parameters}
~~
end run
```
の部分でアプリへの入力を取得していて、これは`input`にlistではいる。  

アプリダブルクリックでも開くようにしているので、inputが空な可能性があるので、if文で弾いています。   
- http://www.script-factory.net/history/2010/12/18_1356.xhtml


`set anAlias to item 1 of input`
listの1個目を取り出し,
このままだとpathではなくAliasというよくわからない形式らしい

`set path_ to POSIX path of anAlias`
いつも使うstringのpathに変換
- http://tonbi.jp/AppleScript/Introduction/11/
- http://piyocast.com/as/archives/1886

`do shell script "/usr/local/bin/jlab  ~~`
実行するだけ
エクセルからpandasを使ってデータフレームに読み込む

### 解決したいこと
※プログラム初心者ですので分からないところが多く，抜けている部分があると思いますのでご了承ください．

データフレームでの検索が一部うまくいきません．
すでに解決済みです．

### 環境
macOS version13.5
VSCode
python 3.10.9

## やりたいこと
「塾で生徒が登校した際，読み取るIDから生徒情報を抽出し，座席を指定する」プログラムを作ろうとしています．

#### 大枠
1. 143席を偶数奇数に分別.
2. エクセルに保存されている{ID, 氏名, 学年, 状態, 座席}をデータフレームとして読み込む．

--入力待ちの状態で待機--
3. キーボード(本番はバーコード)から生徒番号を取得．
4. 偶数席から指定して行き，偶数席がなくなれば奇数席を指定．
5. 生徒名と番号を画面に表示させて登校者に伝える&渡した座席は一時的に使用できないようにする．
6. データフレームにおける該当生徒の'座席'列に座席番号を追加

#### 以降付け加えようと思う機能
・すでに座席を持っている生徒番号の入力があった場合，その座席を使用可能状態に戻し，データフレーム>'座席'列の値を削除する
・生徒番号と座席の手入力機能
・座席の変更機能
等

### まずは全体のプログラム(途中まで)
```python
#'*'の削除のため
import re
#座席をランダムに出力するため
import random
#エクセル読み取り
import pandas as pd

#座席
seat = set(range(1, 144))

#偶数，奇数に分別
seat_even = []
seat_odd = []

for i in seat:
    if i % 2 == 0:
        seat_even.append(i) #偶数
    else:
        seat_odd.append(i) #奇数

#エクセルから生徒情報を読み込み
df = pd.read_excel('st_info.xlsx',sheet_name='st_g',header=0, index_col=None)

df['num'].astype('int')

#生徒番号入力
st_num = str(input('生徒番号：'))
#アスタリスクを削除
st_num = st_num.strip('*')

#偶数席が残っていればその座席を渡す
    #そうでなければ奇数席を渡す
seat_even_taken = []
seat_odd_taken = []
seat_num = 0

if seat_even:
    seat_act=random.choice(seat_even)
    print(st_num)
    print(seat_act)
    seat_even_taken.append(seat_act) #渡した座席
    seat_even = set(seat_even) - set(seat_even_taken) #渡した座席を要素から削除
    seat_num = seat_act
else:
    seat_act=random.choice(seat_odd)
    print(st_num)
    print(seat_act)    
    seat_odd_taken.append(seat_act) #渡した座席
    seat_odd = set(seat_odd) - set(seat_odd_taken) #渡した座席を要素から削除
    seat_num = seat_act    
    
print(df)
print(st_num)

#ここの検索機能がうまく働かない
print(df[df['num'] == st_num])
```

### 発生している問題・エラー
#### うまくいく例
```
          num    name grade state seat
0    43546534    東京 広大    高2   通期生
1    47387344    福岡 美味    高3   通期生
2    4768203      北 海道    高3   通期生
```
上記はエクセルから読み込んだデータフレームです．'num'列に生徒番号を格納しており，基本8文字であるのに対して一人，7文字のIDである生徒がいます．

8文字の生徒に対して上記のプログラムを実行すると

```
生徒番号：43546534
43546534
98

[199 rows x 5 columns]
43546534
        num   name grade state  seat
0  43546534  東京 広大    高2   通期生   NaN
```
このようにIDが一致する生徒の情報を抽出し98番の座席を渡すことができます．

#### うまくいかない例

```
          num    name grade state seat
0    43546534    東京 広大    高2   通期生
1    47387344    福岡 美味    高3   通期生
2    4768203      北 海道    高3   通期生
```
2行目のIDが7文字の生徒番号を与えてみます．
```
[199 rows x 5 columns]
4768203 
Empty DataFrame
Columns: [num, name, grade, state, seat]
Index: []
```
この様に見つからないという出力になります．


### 自分で試したこと
・numをstr形式で試す
    →うまくいっていた部分も見つからない判定となる
・正規表現を使う
    →生徒番号が変数であるため煩雑
・query関数を使う

### 解決方法
読み込んだExcelファイルの数値を確認すると文字列が7桁のものは最後の8桁目に空白が入っていました．
空白を消すと,
```
[199 rows x 5 columns]
8326673
         num   name grade state  seat
2   4768203  北 海道    高3   通期生   NaN
```
[SwiftUI] NavigationBarにViewを設置する方法

## はじめに
こんにちは!
アプリ開発が好きで、Swiftの勉強をしている大学生です。
温かい目で見ていただけると幸いです。

## やりたいこと
タイトルにあるようにNavigationBarにViewを設置したいです。

## 実装

`.toolbar`を利用すると簡単にできました！

```swift
public struct HogeView: View {
    public var body: some View {
        NavigationStack {
            VStack {
                Text("hoge~~")
            }
            .toolbar {
                Button("right") {

                }
            }
            .navigationTitle("hoge~~")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}
```

ただ、デフォルトだと右に表示されるため、左に表示したい場合は以下のようにします

```swift

public struct HogeView: View {
    public var body: some View {
        NavigationStack {
            VStack(alignment: .leading) {
                Text("hoge~~")
            }
            .toolbar {
                 ToolbarItem(placement: .navigationBarLeading) {
                    Button("right") {
                        //
                    }
                }
            }
            .navigationTitle("hoge~~")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}
```

両方に設置したい場合は以下のようにします

```swift

public struct HogeView: View {
    public var body: some View {
        NavigationStack {
            VStack(alignment: .leading) {
                Text("hoge~~")
            }
            .toolbar {
                  ToolbarItem(placement: .navigationBarTrailing) {
                    Button("right") {
                        //
                    }
                }
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("left") {
                        //
                    }
                }
            }
            .navigationTitle("hoge~~")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}
```

## 終わりに
誰かの役に立つことができていれば幸いです。
間違い等がありましたらご指摘していただけると幸いです🙏
VCD ファイルフォーマット リバエベース 解説

# 概要
 VCD（Value change dump）ファイルのフォーマットについて
リバエベースで確認できた内容についてまとめる。
本記事の内容だけで、GTKWaveで波形を確認することができるvcdを作成できる。

vcd ファイルは宣言部とデータ部に大きく分けることができる。
vcd ファイルは ASCII なので手書きできる。

## 宣言部
wire, module, reg を記すことが出来る。
wire, reg は宣言が同じ形式

### wire, reg の宣言
```
$var reg 1 hoge piyo $end
```
`$var`：変数宣言表記
`reg`：値がレジスタであることを意味する。ワイヤの場合は`wire`
`1`：ビット数。4bitなら`4`
`hoge`：識別子。本当になんでもいい。 `1`でも変数名と同名でも
`piyo`：変数名 reg の名前
`$end`：終了表記

上記の宣言で verilog の
 ```
 reg giyo;
 ```
と同じ意味となる。

### module の宣言
```
$scope module hoge $end
wire, reg の宣言
$upscope $end
```
`hoge`：モジュールインスタンス名
構造の問題なので以降のデータ部には影響しない

## データ部
表記は３種類
1. タイムスタンプ
2. 1bit 信号
3. 多bit 信号
各行間に空行を入れても問題ない（GTKWaveでは）

### 1. タイムスタンプ
```
#3
```
絶対時間のタイムスタンプ
verilog シミュレーションの`#`表記とは意味が若干異なる

### 2. 1bit 信号
```
1hoge
or
0hoge
```
`1`：1に変化することを意味する
`hoge`：変数識別子。宣言部で宣言した識別子
空白の挿入は **許されない**

### 3. 多bit 信号
```
b1010 hoge
```
`b`：2進表記識別子。省略不可。`h`不可
`1010`： `A`に変化することを意味する。上位bitの0は省略可
`hoge`：変数識別子。宣言部で宣言した識別子
空白の挿入は **絶対**

# 簡単な自作 vcd と波形
```mymade.vcd
$var wire 1 hoge a $end
$var reg  4 123 c $end

#0
b1 123
0hoge
$end
#3
1hoge
#5
0hoge
#6
b1010 123
#10
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253609/da70e025-9b57-e6c5-67f8-b894af5cb82a.png)
AWS SAP-C02 合格体験記

# はじめに
2023/08/17にAWS認定試験のSAP-C02に合格することができたため、記録を残します。
スコアは843点で余裕を持って合格することができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534814/5f56ab3d-ff48-e5df-ae24-241238c7fab7.png)

# 事前知識
・AWSの業務経験1年半ほど
・AWS SAA-C02取得済み(2022年1月)

# 勉強期間
7月の頭から始めたので約1ヶ月半です。
平均して1日3hくらいはやっていたと思います。

# 勉強内容
### TechStock
実際の試験を想定した問題が多数用意されているサイトです。
SAPの#31～#83を3週解きました。
1周目は1問も分からなくて絶望しましたが、根気よく解いていくと各サービスに対しての理解が深まっていきます。
最初に教科書的な書籍を読んでから問題を解いていこうと思いましたが、SAPの試験では業務で触っていないサービスも多いせいか、なかなかやる気が出なかったので、いきなり問題を解いていく勉強法が自分にはあっていたと思います。
効果としては、AWSの各サービスの知識がついたのはもちろんですが、問題数をこなすことで問題を解くことに慣れたのが大きかったです。試験本番では、問題で問われている知識がなくても問題文と選択肢の雰囲気からなんとなく正解が予想できるという状態になっていたような気がします。

### AWS認定資格試験テキスト＆問題集　AWS認定ソリューションアーキテクト - プロフェッショナル
Kindleの書籍を過去に購入していたので、試験対策として全体を1周読んだのと、模擬試験を3周実施しました。
模擬試験ではTechStockの問題を解いていてもわからない問題がいくつかあったので、やる意味はあったと思います。
過去に購入した書籍のためSAP-C01対応版でした。いまは改訂版でSAP-C02に対応した版が出ているためそちらを購入したほうがいいと思います。

### Professional (SAP-C02) 試験ガイド
https://d1.awsstatic.com/ja_JP/training-and-certification/docs-sa-pro/AWS-Certified-Solutions-Architect-Professional_Exam-Guide.pdf
AWS公式の試験ガイドです。
「範囲内の AWS のサービスと機能」に試験範囲のAWSサービスが一覧で載っているため、わからないサービスについては最低限概要を覚えておくようにしました。


# 試験当日
テストセンターで受験しました。
見覚えのある問題は体感で3割程度で、あとは初見の問題だったため結構焦りましたが、3割の問題は即答することができたため、見直しの時間を確保することができました。
不安な問題は見直しフラグをクリックすればあとで見直すことができますが、1週目はすべての問題に見直しフラグを立てました。
1周解き終わったあとに80分ほど残っていたので、全問見直しして試験時間3時間をフルに使いました。
途中でトイレはいけました。

# 試験結果
試験終了後約24時間後に結果が通知されました。
他の方の合格体験記で、試験当日の夜に結果が来たという話もあったため、かなりソワソワして待ってました。

# おわりに
SAPの試験は内容も難しく、試験時間も3時間と過酷な試験でした。
これから試験に挑戦する方に本記事が参考になれば幸いです。

# これから
資格取得しようと思ったのは転職のためです。
AWSを利用したアジャイル開発ができる会社を探して転職活動を始めようと思います。
ゼロから始めるSTM32マイコン開発-環境設定-

 # ゼロから始める開発
全く知識がない状態からSTM32マイコンを用いた開発ができるようになることを目指していきます。
本当に何も知識がないところ(かつての自分)を想定しているので、「こんなことわざわざ説明する必要ある？」と言われるところを目指します。



 # STM32の開発は環境が整っている
STM32マイコンでの開発は環境が整っているので以下のものをダウンロード・インストールしてしまえば簡単に環境設定できます。

後述のツールをダウンロードするためにはSTの会員登録が必要になりますが、登録さえしてしまえばダウンロード・インストールできるようになるので登録してみてください。


 ## STM32CubeMx
[STM32CubeMxのダウンロードはこちらから](https://www.stmcu.jp/design/sw_dev/pc_soft/52798/?utm_source=google&utm_medium=text&utm_campaign=2022aug_JP104&gclid=Cj0KCQjwrfymBhCTARIsADXTablpVAMtlDqMm269p49sBzWDGpxgvgLusgFO3Srp4RySb-jn6GAssUMaAkf5EALw_wcB)

CubeMXとはGUIで様々なマイコンの設定ができ、自動コード生成を行なってくれる便利なツールです。
知識ゼロから開発を始めるには必須のツールです。

 ## STM32CubeIDE
[STM32CubeIDEのダウンロードはこちらから](https://www.st.com/ja/development-tools/stm32cubeide.html#st-get-software)

CubeIDEとはその名の通り、IDE(統合開発環境)です。
CubeMXで出力した自動生成コードに対し、簡単に追記・編集できます。

 # インストールはデフォルトで
知識ゼロでソフトウェアをインストールする時はなんだか不安になるものですが、全てデフォルトの状態でインストールしてしまって問題ありません。
安心してください。

 # 次回予告
次回は初めての組み込み開発でお馴染みのLEDチカチカの説明をしていきたいと思います。
もし基本情報技術者試験の前に戻れるならこう勉強する

# 他人の失敗から学びなさい。あなたは全ての失敗ができるほど長くは生きられないのだから。By エレノア・ルーズベルト

筆者は81時間5分（78日）を費やし、基本情報技術者試験に多分*落ちた者である。
こう言うと「試験に落ちたやつの記事に価値はない」と思い、本記事を閉じようとしたのではないか。
少し待ってほしい。あなたは社会人で日々忙しく生きているのは重々承知している。
これから紹介する内容は、そんな忙しいあなたにこそ価値があると考えている。
なぜなら、本記事には81時間5分を費やして判明したイケてない勉強法が書かれており、この勉強法を避ければ、あなたは私と同じような道を辿ることにならないからだ。

*8/18時点 結果待ち

# 著者のスペック
試験の計画を立てる際、本記事のような資格対策系の記事は参考にされると考えた。
しかし、試験に合格するまでの時間は試験受講前の人間のスペックに大きく左右される。
したがって、本記事でも著者のスペックを紹介したいと思う。
- 偏差値50前後の現代社会学専攻
- 勉強開始するまでプログラミングは未経験
- IT業界（SES）で営業として1年の勤務経験

「IT業界に1年勤務経験しとんかい！」というツッコミが大いに来そうだが、それでも不合格を叩き出していることから筆者の凡人さが垣間見える。

# 間違いだらけの勉強法
さて、ここからは私の「イケてない勉強法」と、「もし試験前に戻れたらこう勉強をする」という提案も含めてお伝えしていきたい。
不合格した奴の提案なんて聞きたくないと思うが、話半分に聞いてほしい。

## 過去問をいち早く始めるべし
結論から言うと、今すぐ過去問を参照してほしい。
大事なところだからもう一度言う。今すぐ過去問を参照してほしい。
なぜなら、出題形式を知らずに教科書を読み進めても、教科書に書かれた内容をどの粒度で暗記をするべきかの判断ができないからである。
TCP/IP階層モデルを例にとろう。
私はインプットの段階では「TCP/IP階層モデルは4層ある」という粒度で暗記をしていた。
しかし、過去問を解き進めると以下のような問題に出会った。
![IMG_5777.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3362344/777308ec-b87c-f278-abde-ebaa16710e3c.jpeg)
この問題に出会って初めて、各層の名称まで暗記をする必要があるという事を知った。
これは単なる一例でこういった事は頻繁に起こる。
したがって、どの粒度で暗記をすべきかを最初に知るために過去問をいち早く参照することを強くオススメする。
ここまであえて「参照」という言葉を使ってきたのだが、それには訳があり、いきなり問題を解き始める必要はないと考えている。いきなり問題を解き始めたら、あまりの難しさに挫折する可能性があるからだ。
## 教科書のインプットに1ヶ月を費やした結果がこちら
私は資格の受験まで約2ヶ月を確保し、内1ヶ月間を教科書の理解に努めた。
その成果が以下である。
![IMG_4769.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3362344/f0e34bee-6b09-5d55-8228-ffa1f3be84e5.jpeg)
こうならないためにも、過去問の参照を今すぐ初めてほしい。
## 科目Bの勉強時間を確保せよ
科目Bは科目Aより難易度が高い。ということは、科目Bの勉強は科目Aより時間を割く必要がある。
非エンジニアの皆さんであればなおさらだ。
なんとなくそんな事は聞いていたが、私が本気で取り組み始めたのは試験の約2週間前である。
これだけのんびりしていたのは、恐らく科目Bがどれほど難しいか分かっていなかったからだと思う。
ここまで読んでくれたあなたには、是非以下のサイトから科目Bのサンプル問題に取り組んで難易度を理解してほしい。

https://www.ipa.go.jp/shiken/mondai-kaiotu/sg_fe/koukai/2023r05.html

サンプル問題を解いた後「やばい！科目Bも勉強せねば！」と思えたならば、それは良い兆候である。
もし私が試験前に戻れるなら、私は科目Aよりも科目Bの勉強時間を確保して勉強を行うだろう。
#  まとめ
ここまで読んで、何も目新しい情報がなかったという方は、今の勉強方法を進めていって是非合格してほしい。
逆に、私と同じ勉強方法をしていた人は、すぐに過去問に取り組むのと同時に、科目Bの勉強時間を十分に確保してほしい。
基本情報技術者試験は難易度が非常に高い。だからこそ価値があると考えている。本記事を読んだ少しでも多くの方が合格できるよう祈っている。

> 100点、100点、100点だったら、くだらないテストしか受けていない証拠でしょうよ。 By ジェームス・スキナー
ABC314復習

# ABC314復習
[AtCoder Beginner Contest 314 - AtCoder](https://atcoder.jp/contests/abc314)
## ■結果  
* AC2完。（BのケアレスミスでWAしたままDが時間切れ。）
* レートは-15と余り落ちなかったが、落ち着いてれば取れた内容で悔しい。

## ■Ａ問題（3.14）
設問の「切り捨て・末尾の0を取り除かない」の条件だと演算は不要で文字列処理が最適そうなので文字列でスライス。（所要時間約3分）
```python
n = int(input())
pi="3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679"
print(pi[:n+2])
```
## ■Ｂ問題（Roulette）  
１）xに賭けた人のリストを作成、賭けた目数も同時に保存し目数の最小を算出
２）上記から目数が最小の人のリストを作成
の２段階に分けて人番号を抽出。最後にソートして出力。20分で提出。
ここでケアレスミスがあり、賭けた目数の最小値を初期値30からカウントダウンする実装にしてしまった。（各人37か所まで賭けられるので、全員30か所以上賭けた場合にWAになる。）これに気づかずWA。コンテスト後に以下でAC。
```python
n = int(input())
bets=[]

for ii in range(n):
    c = int(input())
    bet = set(map(int, input().split()))
    bets.append([c,bet])
x = int(input())

result=[]
min_bet=100 # 最初30にした箇所
for ii in range(n):
    if x in bets[ii][1]:
        c = bets[ii][0]
        result.append([ii+1,c])
        min_bet = min(c, min_bet)

if min_bet == 100:
    print(0)
    exit()

ans_list=[]
for r in result:
    if r[1] == min_bet:
        ans_list.append(r[0])

ans_list.sort()
print(len(ans_list))
print(*ans_list)
```
## ■C問題（Rotate Colored Subsequence）
色ごとに右ローテートしたいので、下記の２回のループにした。
ループ１）色ごとに最後の文字が何かを取得してv[c]の初期値にする。
ループ２）色ごとに一つ前の文字としてv[c]を書き出してからv[c]更新。
（所要時間約9分でACし巻き返し）
```python
n,m = map(int, input().split())
s = input()
c_list = list(map(int, input().split()))

# 1st scan loop
v=[0]*m
for ii in range(n):
    c=c_list[ii]-1
    v[c] = s[ii]

# 2ns output loop
for ii in range(n):
    c=c_list[ii]-1
    print(v[c],end="")
    v[c]= s[ii]
```
強い方に、pythonのdeque.rotate()だと直接ローテート出来るという見識を習う。色毎にローテートするには下記の様に辞書で色別のdequeを作るとか。今回は元解がシンプルだが、これはこれで使い勝手良さそう。
```python
from collections import deque,defaultdict
d = defaultdict(deque)
for ii in range(n):
    c = c_list[ii]
    d[c].append(s[ii])
for c in set(c_list):
    d[c].rotate(1)
```

## ■Ⅾ問題（LOWER）
クエリのバッチ処理の問題。残念ながら時間切れ。
素性は判る問題だったので素早く整理すれば解けたかも。反省は２点。
反省１）Q=2,3のUpper/Lowerでは過去分の操作影響が消えるのが判っていながら、まず逐次処理で解いてからコード改修しようと考えて時間を消費。
反省２）Pythonの文字列はimmutableなのでList化し処理する必要あるが、毎回、文字列→リスト化→文字置換→joinで再文字列化するコードを書いてTLEした。
コンテスト後、最初のループでQ=2,3の最後の回を決め、２回目にQ＝1の操作全部とQ=2,3の最後の回をリストに対して適用するコードにしてAC。
```python
n = int(input())
s = list(input())
q = int(input())

commands = []
lastCaseChange = 0
for ii in range(q):
    cmd, x, c = input().split()
    x = int(x)
    cmd = int(cmd)
    commands.append([cmd, x, c])
    if cmd != 1:
        lastCaseChange = ii

for ii in range(q):
    cmd = commands[ii][0] 
    x = commands[ii][1]
    c = commands[ii][2] 
    if cmd == 1:
        s[x-1]=c
    if cmd == 2 and lastCaseChange==ii:
        s=list("".join(s).lower())
    if cmd == 3 and lastCaseChange==ii:
        s=list("".join(s).upper())
        
print("".join(s))
```
【Swift】import文を省略する

# はじめに
何度も同じ`import`文を書かなければいけない時に省略できる機能を知ったので記録しておきます。

# 実装
```swift
@_exported import SwiftUI
```

# 使い方
1ファイルに`@_exported`でインポートすると同列以下でのファイルでは書かなくてよくなります
![スクリーンショット 2023-08-18 19.52.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/3bc03622-9874-d4a6-de2c-1c5917f50453.png)

ここでは`import SwiftUI`を書かなくても使用できる
![スクリーンショット 2023-08-18 19.53.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/e76bc9cf-74e7-73ba-0204-bf9ded2d2e94.png)

ここでも書かなくて良い
![スクリーンショット 2023-08-18 19.54.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/8eba9259-28e9-bb80-1395-003626d17d2c.png)

# おわり
これは便利ですね
AdGuardでTwichの広告をブロックすると固まってしまう。

AdGuardでTwichの広告をブロックすると固まってしまう。
どうにかしたいので色々調べてある程度できたので情報共有   

環境はM1 macbookair os13.5
AdGuard for Mac 2.11.0.1292 release

AdGuardには拡張機能があり、ここからuserscriptが使用できる。   
いわゆるブラウザ拡張のtampermonkeyみたいなので使えるやつ。 
別にtampermonkeyとかで使用してもいいと思う。  

以下のページの画像部分をクリックするとAdGuardで開くみたいなのが出るのでそこで追加する。
https://github.com/pixeltris/TwitchAdSolutions

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1278266/d3cadd1e-536e-79ca-28c7-4a615b147b7e.jpeg">


もしくは以下urlを手動でAdGuardに追加
https://github.com/pixeltris/TwitchAdSolutions/raw/master/video-swap-new/video-swap-new.user.js
[flutter]badgesでは小さいサイズの通知バッジを作成できないので自作してみた。

## はじめに

こんにちは、今回は自作通知バッジについてです。

基本的に通知バッジを実装する際には[badges](https://pub.dev/packages/badges)を使うのが一番丸いかと思いますが、、

このライブラリだとバッジの**サイズが一定より小さくならない**みたいで今回のプロジェクトの要件には満たなかったので自作しました。（めちゃ簡単）



     
####  小さくなる限度


```dart
Badge(
  badgeContent: const Text("3"),
  child: const Icon(Icons.notifications, size: 50,),
),
```

上記のsizeパラメータに任意の値を設定したいのですがこの値を１以下にしようとするとそれ以上サイズが変わりません。

おんなじような方に参考になれば幸いです。

## 概要

![スクリーンショット 2023-08-18 18.37.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3158219/156a1250-36b5-c64b-46a1-0ae788de745b.png)

今回実装するのは上記のようなからり小さいタイプの通知になります。
（画像小さくてすみません。）






## 全コード

```dart
Stack(
   children: [
    const Icon(Icons.notifications_none_sharp,color: 
    blackColor,size: 35,),
             Positioned(
                 top: 0.5,
                 right: -0.5,
                 child: Container(
                   width: 5.0,
                   height: 5.0,
                   decoration: const BoxDecoration(
                     shape: BoxShape.circle,
                     color: Colors.red, // バッジの色を調整してください
                   ),
                 ),
               ),
             ],
           ),
```

## 解説

まずはcontinerで丸い点を作成します。

```dart
Container(
    width: 5.0,
    height: 5.0,
    decoration: const BoxDecoration(
    shape: BoxShape.circle,
    color: Colors.red, // バッジの色を調整してください
    ),
```

今度は Positionedでcontainerの位置を調整します。

```dart
  Positioned(
     top: 0.5,
     right: -0.5,
     child: Container(
        width: 5.0,
        height: 5.0,
        decoration: const BoxDecoration(
              shape: BoxShape.circle,
              color: Colors.red, // バッジの色を調整してください
                   ),
                 ),
               ),
```

positionedの座標は実際に表示する文字等によって変わってくるかと思いますので、各自で調整してください。

あとは実際に通知バッジをつけるwidgetに対してstackでネストしてあげるだけです。

後半に置いたwidgetの方が手前側に表示されるので、表示方法によっては、ネストする順番を逆にする方が適当になる場合もあります。
win11右键菜单改回win10的操作方法

1、首先我们在电脑桌面主页按下“Win+R键”，打开运行对话框。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734236/96c0a1b4-b097-237c-5e62-14b7284cc270.png)

2、接着在对话框中输入指令“regedit”然后按下回车确认，打开注册表界面。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734236/1329ad33-e29d-e7b2-f876-3cfb25af526f.png)

3、把“计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell\Update\Packages”复制下来。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734236/56fbcfad-b7fb-01f9-73bb-d2d123db662c.png)


4、接着鼠标右键空白的地方，选择新建-DWORD值，重命名为“UndockingDisabled”。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734236/78a0d1cb-4534-a3e8-6fb6-51370e122c2d.png)


5、鼠标右键新建的项目修改，将数值数据改为“1”，重启后就可以发现我们的菜单已经变为win10样式了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734236/e304700b-1c19-fecc-bcf5-f9adecbfba66.png)
人事からPMOへ① 〜PMOってなに？〜

こんにちは☀️

私は、人事からPMOにキャリアチェンジしました。
これから、未経験で大規模なプロジェクトのPMOとして、体験したことをいろいろ書いていこうと思います。

【そもそも、PMOとは？】
PMOは「Project Management Office（プロジェクト・マネジメント・オフィス）」の頭文字を取った言葉です。
組織内のグループであり、組織全体のプロジェクトマネジメントの標準とプロセスを定義し、設定し、維持することを支援します。

【PMOの役割とは？】
プロジェクトによって多少違いはあるかと思いますが、主な役割として、次のものが挙げられます。

・プロジェクトマネジメント業務の支援
・プロジェクトマネジメントの標準化
・プロジェクトマネジメントに必要な人材育成
・プロジェクト間のコストやリソースの調整
・プロジェクト環境の整備
・プロジェクトに付随する管理業務

各プロジェクトの成功率を高め、経営戦略・事業戦略に掲げられた目標を着実に達成していくことがPMOの本質的な役割といえるでしょう。


こんな感じで書くと、なんか難しそうと思う方もいるかと思いますが、難しい業務ばかりではありません！

次は、実際プロジェクトでやってる業務や感じたことを書いていきます！
【Flutter】リップルエフェクトを無効にする


# リップルエフェクトってなに？

アクションがつくWidgetを長押しした時に出てくる波紋あるじゃないですか？？
あれです。

<img width="300" alt="08182023171430.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524065/a1ebb842-da1c-6f76-a28e-3d13e1bcf914.gif">

でも、リップルエフェクトが不要の場合ってありますよね。
と言うわけで、今回はリップルエフェクトを無効にする方法を3パターンご紹介します！

# なぜ出てくる？？

マテリアルデザインにデフォルトで搭載されている機能みたい。
基本的に、アクションがついているWidgetに有効になっている機能のように思います。


# プロジェクト全体でリップルエフェクトを無効にする方法

ひとつ目は、プロジェクト全体でリップルエフェクトが不要な際、
デフォルトでリップルエフェクトを無効にする方法です。

```dart
MaterialApp(
  title: 'Flutter Demo',
  theme: ThemeData(
    splashColor: Colors.transparent, //ThemeDataのsplashColorを透明にする
  ),
  home: const Test(),
);
```
ThemeDataのsplashColorに対して、`Colors.transparent`を渡してあげることで、
リップルエフェクトを無効にすることが可能です！

:::note alert
注意！！
リップルエフェクトをデフォルトで持つWidgetは数多くありますが、
上記の対応でできるのは、パラメータにsplashColorを持つWidgetのみになります！
:::

# 特定のWidgetのリップルエフェクトを無効にする方法

ふたつ目は、特定のWidgetに対してリップルエフェクトを無効にするパターンです。

これが厄介で、Widgetによって以下の二つの方法を使い分けないといけません。

### 1\. アクションを持たないWidgetで代用できる場合

以下のコードでTextButtonを表示させていますが、
TextButtonは、ThemeDataでリップルエフェクトを無効にさせる方法では対応できないWidgetとなっています。

```dart
 TextButton(
    onPressed: () {},
    child: const Text('Text Button'),
 ),
```

このコードを、InkWellでラップして、splashColorに`Colors.transparent`を渡してあげます！
さらに、TextButtonを使用しているところ、アクションについてはInkWellに持たせ、子要素にTextを代用するようにします。

```dart
InkWell(
    onTap: (){},
    splashColor: Colors.transparent, // splashColorを透明にする。
    child: const Text('Text Button'),
),
```
こうすることで、リップルエフェクトを無効にすることができます！

### 2\. アクションを持たないWidgetで代用できない場合

初めに言っておきますが、自作でボタンを作れば、アクションを持たないWidgetへ代用することは可能です。
ただそんなことするよりも、元のWidgetを崩さない方法があればいいですよね。
その方法がこちらになります。

以下のコードで、ElevatedButtonを表示させています。

```dart
  ElevatedButton(
    onPressed: () {},
    child: const Text(
      'ElevatedButton',
    ),
  ),
```
Widgetのstyleタグに、`{Widget}.styleFrom`を渡し、`onPrimary`(もしくは`primary`)に対して、背景色と同色を渡してあげます！


```dart
  ElevatedButton(
    onPressed: () {},
    style: ElevatedButton.styleFrom(onPrimary: Colors.blue), //背景色と同色にする。
    child: const Text(
      'ElevatedButton',
      style: TextStyle(color: Colors.black), // 文字色を指定する。
    ),
  ),
```

これでリップルエフェクトが無効にできました！！


:::note warn
primaryに対してColorを渡した際、ボタン内の要素が全て指定した色に統一されてしまうので、適宜色の指定する必要があります。
:::

## 参考
デフォルトで無効にする方法

https://www.choge-blog.com/programming/flutterrippleeffect-disabled/

特定の箇所で無効にする方法

https://www.choge-blog.com/programming/flutterinkwell-ripple-effect-disabled/

## 終わりに
もっと簡単な方法があったら教えてください〜
jupyterlab-desktopでjlabコマンドが使えない

普通にjupyterlab-desktopを使っていて、jlabコマンドの存在を知ってしようとしたら使えず困ってしまいました。   
リインストールしてもつかえず、、   
調べてみるとM1mac系でバグがあるようです。


https://github.com/jupyterlab/jupyterlab-desktop/issues/655
以下のコマンドを実行すると使えました。

```
mkdir /usr/local/bin
sudo ln -s /Applications/JupyterLab.app/Contents/Resources/app/jlab /usr/local/bin/jlab
```
Recoil selectorのJestでのUnitTest

# RecoilのselectorのJestでのUnitTestを作成する方法

## Code
こんなselectorがあったとしてそのUnitTestを書く

```ts:state.ts
import { atom, selector } from "recoil";

const dateAtom = atom<Date>({
  key: "dateAtom",
  default: new Date("2000/01/01 00:00:00"),
});

export const dateSelector = selector<string | Date>({
  key: "dateSelector",
  get: ({ get }): string => {
    const date = get(dateAtom);
    const yy = date.getFullYear();
    const MM = (date.getMonth() + 1).toString().padStart(2, "0");
    const dd = date.getDate().toString().padStart(2, "0");
    const HH = date.getHours().toString().padStart(2, "0");
    const mm = date.getMinutes().toString().padStart(2, "0");
    return `${yy}/${MM}/${dd} ${HH}:${mm}`;
  },
  set: ({ set }, props) => {
    const date = props as Date;
    date.setHours(date.getHours() + 1);
    set(dateAtom, date);
  },
});

```

## Test
`snapshot_UNSTABLE`を利用することで、ある状態のsnapshotが取得できるため、その中の目的のselectorの値を取得し評価することができます

また`snapshot_UNSTABLE`のcallbackで`set`を行うことでsetした状態のsnapshotが取得されます。

参考

https://recoiljs.org/docs/guides/testing/#testing-recoil-state-outside-of-react

```ts:state.test.ts
import { dateSelector } from "./state";
import { snapshot_UNSTABLE } from "recoil";

it("dateSelector initial", () => {
  const snapshot = snapshot_UNSTABLE();
  expect(snapshot.getLoadable(dateSelector).valueOrThrow()).toBe(
    "2000/01/01 00:00"
  );
});

it("dateSelector set", () => {
  const snapshot = snapshot_UNSTABLE(({ set }) => {
    set(dateSelector, new Date("2000/01/01 00:00"));
  });
  expect(snapshot.getLoadable(dateSelector).valueOrThrow()).toBe(
    "2000/01/01 01:00"
  );
});

```
#PowerApps の入力で 全角のみかどうかを判定する方法

# 前置き (IsMatch関数について)

Power Apps では IsMatch関数を使うことで、指定した文字列が含まれているかどうかを判定する事ができますが、IsMatch 関数は、正規表現を指定する事もできたりします。

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-ismatch?WT.mc_id=DX-MVP-5003651

# 正規表現

正規表現は非常に奥深く、英数字判定からパターン判別まで様々な事ができます。
https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/regular-expressions?WT.mc_id=DX-MVP-5003651

# 全角判定をするためには？

なのでまずは、入力文字列が全て全角のみかを判定すればいいのですが、全角の文字は数多くあるため、日本だけでも

* 全角ひらがな
* 全角カタカナ
* 全角記号
* 全角数字
* 全角大文字
* 全角小文字
* 全角漢字

と7種類もありますし、それ以外の言語も含めるととても範囲指定できなさそうです。

でも、よく考えてみてください。
全角を判定をすることは難しくても・・・半角のほうがまだ簡単そうではありませんか？

* 半角大文字
* 半角小文字
* 半角記号
* 半角数字
* 半角カナ

項目は複数ありますが、文字の数はそれほど多くなさそうです。
なので、入力文字中に半角文字があるか判定させ、その結果が偽（False)であれば、全角のみであると判断できます。

# 指定文字が全て半角かどうか判断する

とはいっても、それでも難しいので、ChatGPT に聞いてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/35d71da6-4afd-e7c3-bfeb-4729c1e5213e.png)

というわけなので、Power Apps に反映させてみます。

# Power Apps

```
!(IsMatch(TextInputCanvas1.Value,"^[!-~｡-ﾟ]+$"))
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/2cb6260f-cb65-94cd-03b3-e7138a1a4275.png)

正しく反映されてますね！
これで、全角のみであれば有効にできるというようなJapanライクなアプリもできるようになります！
ぜひお試しください！
【Rails】マイグレーションでミスった話～エラーに対処する～

前回の記事では、マイグレーションを使ったテーブルやカラムの追加について紹介しました。
##### 前回の記事

https://qiita.com/nakaizumi_slj/items/2e0895cc9d03b5085ee1

この記事ではマイグレーションの記述ミスによって戻すことができなくなった場合の対処について紹介したいと思います。
インデックスのカラム名をミスった私は、3つの方法を試したところ最後の方法によって問題が解決しました。
# 目次
- [どんなミスをしたか](#どんなミスをしたか)
- [問題の原因](#問題の原因)
- [エラーに対してしたこと～その1～](#エラーに対してしたこと～その1～)
- [エラーに対してしたこと～その2～](#エラーに対してしたこと～その2～)
- [エラーに対してしたこと～その3～](#エラーに対してしたこと～その3～)

# どんなミスをしたか
railsチュートリアルの追加機能の実装に取り組んでいました。

https://railstutorial.jp/

中でも返信機能の実装中に問題は発生しました。
「デ、デプロイができない…」
<img width=300 src="https://3.bp.blogspot.com/-882AGVdFZnc/WQA-NmApkJI/AAAAAAABD6A/AkX4BnA78gY5xEIDPeyp4fqXmk93LoMtgCLcB/s800/pose_atama_kakaeru_woman.png">

エラーにはそんなカラム存在しないよという表記がありました。


# 問題の原因
問題のコードは以下の通り。
```ruby
class AddInReplyToColumnToMicroposts < ActiveRecord::Migration[7.0]
  def change
    add_column :microposts, :in_reply_to, :integer, default:0, foreign_key:{ to_table: :users }
    add_index :microposts, [:in_reply_to_id, :created_at]
  end
end
```
上記のコードの何が問題かというと追加したカラム名`:in_reply_to`とインデックスで指定したカラム名`:in_reply_to_id`が違うという初歩的ミスをしていた。


# エラーに対してしたこと～その1～
#### マイグレーションを1つ戻す。

試したコマンドは以下の3つ
```
rails db:rollback
rails db:migrate:redo STEP = 1
rails db:migrate:down VERSION=戻したいファイルの番号
```
参考にしたページ

https://mozy-ok.hatenablog.com/entry/2018/11/13/085938

この方法は失敗。
<img width=300 src="https://4.bp.blogspot.com/-pi2OEw0-Eew/XJB5M76Zf9I/AAAAAAABR9I/5FrJ3BqUJtUKKUVvvIJnxQ54v6O97HL0ACLcBGAs/s800/science_hakase_shippai.png">



# エラーに対してしたこと～その2～
#### カラム修正のファイルを作って実行する。
今度はこんな記事を見つけました。

https://teratail.com/questions/323147

よし、やってみよう。
そして以下のコードを書いてみた。
```ruby
class FixMissingIndex < ActiveRecord::Migration[7.0]
  def change
    # まずindexとカラムの不整合を解消する
    add_column :microposts, :in_reply_to_id, :integer, default:0, foreign_key:{ to_table: :users }
    # 不正なindex削除(事前に不整合を解消しないとインデックスが存在しないと言われる)
    remove_index :microposts, [:in_reply_to_id, :created_at]
    # 不整合解消用に作った一時カラムを削除
    remove_column :microposts, :in_reply_to_id, :integer, default:0, foreign_key:{ to_table: :users }
    # 正しいindexを貼る
    add_index :microposts, [:in_reply_to, :created_at]
  end
end

```
これも失敗。
<img width=300 src="https://4.bp.blogspot.com/-pi2OEw0-Eew/XJB5M76Zf9I/AAAAAAABR9I/5FrJ3BqUJtUKKUVvvIJnxQ54v6O97HL0ACLcBGAs/s800/science_hakase_shippai.png">

# エラーに対してしたこと～その3～
絶対やりたくなかった奥の手を使った。
#### 問題ファイルを消去する。
手順
1.rails db:environment:set RAILS_ENV=development
※この時環境名は自分の環境に合ったものを入れるようにします。
（私は本番環境なのに開発環境の名前入れていてエラーを出しました。）
2.rails db:drop
3.ファイルを消して作り直す
4.rails db:create
5.rails db:migrate
6.rails db:migrate:reset
7.rails db:seed

上記でしたことを説明すると、元あったデータベースをまっさらになくして、
ファイルを作り直して、再度データベースを作り直した。
この方法でやっとできた。
<img width=300 src="https://3.bp.blogspot.com/-aYeabkzZuXw/Whu2k5RDoII/AAAAAAABIjA/p7i7BW2A-eI0LWzMn2p4o2HLO31u8bJEgCLcBGAs/s800/seikou_banzai_woman.png">


絶対個人開発以外の場面では使ってはいけない奥の手です。
使ってはいけない理由については[こちらの過去記事](https://qiita.com/nakaizumi_slj/items/2f0c05d0465d95c5440b)に書いてあります。



マイグレートファイルは非常にデリケートなので反映させる前にミスがないか確認することが大事です。
というわけで、初歩的ミスで苦しんだ話でした。
【プラクティス紹介】1分でさらっと分かる「ただ話す」

## プラクティス名
ただ話す

## プラクティスの目的・狙い
* フロー効率の低下を予防する

## どんな時に使うか
* 他チームと調整すべき課題が発生した時
* この件についてどの場で相談しようかあれこれ迷ってしまう時

## 実施手順
1. 立ち上がる
1. 相手先のチームがいる場所へ歩いて行く
1. 「やぁ、ちょっといいかな？」と声をかける

これだけだとプラクティスの意図が伝わらないと思いますので、趣旨を明確にするためにいくつか質問したいと思います。これまで複数チームが関わる開発で以下のようなことはありませんでしたか？

* 他チームとどう調整するか悩む（チャット？メール？どの会議？課題表？・・・）
* 次回の定例会議で相談するから、と一旦その作業の手を止める
* 自チーム側の仕様がきちんと確定してから声をかけようと後回しにする
* 向こうは向こうできっと対応してくれているだろう、と期待して声をかけるのを止める

このような状況に心当たりがある場合はこのプラクティスを試してみるべきかもしれません。

## アレンジ例
* 他チームとの調整だけでなく、自チーム内の調整（例えばPOへの確認）にも適用する

## アンチパターン
* 「チーム間の課題は管理表に起票するルールになっています！」と「ただ話す」ことを禁止する
（→必要なら後で起票すればよいだけの話）

## 参考情報

書籍

https://www.maruzen-publishing.co.jp/item/?book_no=295180


LeSS公式サイト（「Just Talk」参照）

https://less.works/less/framework/coordination-and-integration

## こぼれ話（私的コメント）
チーム間のコミュニケーションを観察した結果、「より正式な調整方法の環境が整っていると、調整が少なくなる」というパターンが見つかったそうです。円滑なコミュニケーションを図るためのルールが、逆に会話を減らしてしまうというなんとも皮肉な結果ですね。
このプラクティスはアジャイル宣言にある「プロセスやツールよりも個人と対話を」という原則を別の形で表現したものとも言えそうです。またこのプラクティスの最大の発明は、当たり前の概念を「ただ話す」という秀逸なネーミングでプラクティスとして再定義したところにあるのではないかと思います。プラクティス化することで単に「大切だから意識しよう」というスローガンに留まらず、具体的に取り得るアクションとして目の前に現れてくるからです。

余談ですが「ただ話す」の応用技として「ただ叫ぶ」というものがあるらしいのですが、プラクティスの詳細はまだ調べがついておりません。

　[アジャイルプラクティス一覧へ戻る](https://qiita.com/kakashi_h5/items/20584998c5ca4594b9ea)
データベースの基礎

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/da21b332-924f-9bea-973c-787f042766fe.png)
１：主キー（primary key）
　主キーは、行を１行に特定できる属性です。例えば、学生番号、口座番号、商品番号などが主キーになります。属性の組み合わせで主キーとなる場合もあります。例えば、成績表は、各行が、「誰の」、「どの科目の」成績かを表していますから、主キーは{学生番号,科目番号}のきみ合わせになります。複数の属性の組み合わせで主キーとなっているものを複合キーと言います。

　主キーには２つの制約条件が科されます。これらをまとめて主キー制約と言います。
①一意性制約（UNIQUE）：同じ値を取ってはならない。

②非ナル値制約（NOT NULL）：空値を取ってはならない

２：外部キー（foreign key）
複数の表があるときに、他の表で主キーとなっている属性を外部キーと言います。外部キーによって、複数の表が関連づきます。

３：キーバリューストア（Key-Value-Store）
　データ構造（データを保存する仕組み）の１つです。保存したいデータ（Value）と、そのデータを一意に識別できる値（key）を組としてデータを保管する方法です。
例えば、
[10220, トム]
[10243, タロウ]
のように
　[キー（key）, バリュー（value）]を組みとして、データを保管します。ビッグデータの保管に多く利用されています。
DOMの仕組みについて簡単にまとめた

# はじめに

JavaScriptでHTMLの要素を書き換える際に使用される「DOM」について簡単にまとめました。
触ったことはあるけど、実際にどんな構造になっているかがわからない...といった方の参考になれば幸いです。

# 概要

- DOMとは
- DOMの構造

## DOMとは

DOMとは「**D**ocument **O**bject **M**odel」の略で、Webページ全体の要素をオブジェクトで表現するものです。
そして、JavaScriptからオブジェクトを操作するための専用のAPIが用意されています。

見たことがある人もいると思いますが、

```js
Document.getElementById('');
```

上記はDOM APIの一種です。

本来であればHTML要素をJavaScriptから変更することはできませんが、DOM APIを使用することで要素を動的に変更することが可能となります。

DOMは、JavaScriptからHTMLに対する「参照」と「更新」を実現するための仕組みです。

## DOMの構造

DOMがどのように構成されているかを紹介するため、下記に焦点を当てていきます。

- DOMツリー
    - 階層構造
- ノード
    - HTMLの各要素を表現しているもの
- ノードの関係性
- 空白ノード

### DOMツリー

DOMは枝分かれした木のような階層構造となっており、それをDOMツリーと呼びます。

下記のHTMLはその下にあるようなツリー構造で表されます。

```html
<!DOCTYPE html>
<html>
    <head>
      <title>タイトル</title>
    </head>
    <body>
      <h1>見出し</h1>
      <p>段落</p>
    </body>
</html>
```
```
document 
  └── html 
       ├── head 
       │    └── title 
       │          └── #text タイトル
       └── body 
            ├── h1 
            │    └── #text 見出し
            └─── p
                 └── #text 段落
```

<html>などのタグは全てオブジェクトとなり、その下に続く親子関係がツリー構造で表現されます。

元々のHTMLとは特に変わったことはなく、似たものだと思って大丈夫です。

### ノード

HTMLの各要素のことを、DOMツリーではノードと呼びます。

以下、ノードの種類です。

- ドキュメントノード
    - 全体を表現するdocumentオブジェクト
- 要素ノード
    - 要素を表現するオブジェクト（html、div、button等、<>で囲われたもの）
- テキストノード
    - 要素内のテキストを表現するオブジェクト（\<div>テキストだよ</div>の「テキストだよ」の部分）
- 属性ノード
    - 要素の属性を表現するオブジェクト（id=""、class=""といった部分）
- コメントノード
    - コメントを表現するオブジェクト（\<!-- コメントアウト -->で記された部分）

下記のHTMLはその下にあるようなDOMツリーで表されます。

```html
<!DOCTYPE html>
<html>
    <head>
      <title>タイトル</title>
    </head>
    <body>
      <h1>見出し</h1>
      <!-- ここから本文 -->
      <p id="text">段落</p>
    </body>
</html>

```

```
document 
  └── html
       ├── head
       │    └── title
       │         └── #text タイトル
       └── body
            ├── h1
            │    └── #text 見出し
            ├── #comment ここから本文
            │
            └─── p ─── id
                 └── #text 段落
```

このように、HTML上の要素は全てノードとして表現されます。

### ノードの関係性

HTMLの要素に子孫関係があるように、ノードにも下記のような子孫関係があります。

- ルートノード
- 親ノード
- 子ノード
- 子孫ノード
- 兄弟ノード

```
document                 // ルートノード
  └── html               // documentの子ノード　headとbodyの親ノード
       ├── head
       │    └── title 
       │         
       └── body 
            ├── h1       // h1とpは兄弟ノードであり、htmlの子孫ノード
            │    
            └── p 
```

### 空白ノード

なんとなく想像がついていると思いますが、HTMLドキュメント内のスペースや改行はDOMの中では空白ノードと呼ばれます。（空白ノードはテキストノードとして表現される）

下記の２つのHTMLは、ブラウザでは同じように表示されます。

```html
<div><h2>見出し</h2><p>段落</p></div>
```

```html
<div>
  <h2>見出し</h2>
  <p>段落</p>
</div>
```

しかし、当然ですがDOMツリーは別々のものとなります。

```
div 
  ├── h2 
  │   └── #text 見出し
  └── p
      └── #text 段落                            
```

```
div 
  ├── 空白
  ├── h2 
  │   └── #text 見出し
  ├── 空白
  ├── p
  │   └── #text 段落   
  └── 空白  
```

頭に入れておくと、実際にDOMを操作した時に役立つかもしれません。

# 最後に

jQuery等でDOM操作した時に開発者ツールでよくわからないDOM関連のエラーやワーニングが表示されたときも、このあたりを知っておくと原因の究明が楽になる気がします。

最後まで読んでいただきありがとうございました。

参考記事：[【JavaScriptの基本】DOMの仕組みと構造](https://tcd-theme.com/2021/05/javascript-dom.html?gad=1&gclid=Cj0KCQjwkqSlBhDaARIsAFJANkirxuaFOyiPHNMC34L3Oc_7TR_gxm5nSrwSXKo2pR6xYZUfGDiPAX4aAiZ8EALw_wcB)
[統計基礎]~二項分布から正規分布~

# なぜ証明をする必要があるのか
全ての確率分布は中心極限定理によって正規分布になると説明があるが、直感的に理解するのでなく、数式を辿ることで確実に理解できると思ったため。あと、logをとって極大値をとる手法は最尤法でも使われるので計算の練習がてら解説しようと思う。
二項分布は以下のように表せる
```math
P_b(x) = {}_nC_x p^x q^{n-x}
```
logは単調増加関数なので、元の関数p_b(x)の極大値を調べるのと同義である。よく機械学習の最大化問題で使われるね
```math
g(x) = \log P_b(x) = \log \Big(\frac{n!}{x!(n-x)!}p^x(1-p)^{n-x}\Big)
```
```math
g(x) = \log n! - \log x! - \log(n-x)! + x\log p +(n-x) \log (1-p)
```
この関数の極大値となる xを求める 
微分の定理より ＊後進差分
```math
h'(x) \fallingdotseq \frac{h(x)-h(x - \Delta x)}{\Delta x}
= \frac{h(x)-h(x-1)}{1}\qquad(\Delta x = 1)
```
```math
(\log x!)' = \log x! - \log(x - 1)! = \log \frac{x!}{(x-1)!} = \log x
```
xが十分に大きい時に成り立つ 二項分布の試行回数n→∞にするためxも十分に大きくなるとわかる
```math
(\log x!)' \fallingdotseq \log x
```
```math
g'(x) = -(\log x!)' - {\log (n - x)!}' + \log p - \log (1 - p)
```
```math
g'(x) = -\log x + \log (n - x) + \log p - \log (1 - p)
```
```math
g'(x) = \log \frac{p(n - x)}{x(1 - p)}
```
g'(x) = 0のとき
```math
\frac{p(n - x)}{x(1 - p)} = 1
```
```math
np - px = x - px \qquad x = np
```
x = npで極大値をとることがわかる g'(x)を更に微分して
```math
g''(x) = - \frac{1}{x} + \frac{-1}{n-x} = -\frac{n}{x(n-x)}
```
```math
g''(u) = - \frac{n}{np(n-np)} = - \frac{1}{np(1-p)} = - \frac{1}{npq}
```
よって
```math
g'(u) = 0 \qquad g''(u) = - \frac{1}{\sigma^2}
```
ここでマクローリン展開とテイラー展開の復習
```math
f(x) = f(0) + \frac{f(0)'}{1!}x + \frac{f(0)''}{2!}x^2 + ・・・ + \frac{f(0)^{(n)}}{n!}x^n
```
個人的な覚え方だけど、マクローリン展開の上式をパターンとして覚えて、テイラー展開は上式をx方向にaだけ並行移動したものと考えればx=a周りのテイラーが完成する
```math
f(x) = f(a) + \frac{f(a)'}{1!}(x-a) + \frac{f(a)''}{2!}(x-a)^2 + ・・・ + \frac{f(a)^{(n)}}{n!}(x-a)^n
```
本題に戻りg(x)をx=u周りにテイラー展開すると
```math
g(x) = g(u) + \frac{g(u)'}{1!}(x-u) + \frac{g(u)''}{2!}(x-u)^2 + \frac{g(u)^{(3)}}{n!}(x-u)^3 + ・・・
```
第3項以降は0に近似できるため(x≒uより)また、下の式を代入すると
```math
g'(u) = 0 \qquad g''(u) = - \frac{1}{\sigma^2}
```
```math
g(x) \fallingdotseq g(u) - \frac{1}{2\sigma^2} (x-u)^2
```
ここで
```math
g(x) = \log P_b(x)
```
テイラー展開で求めたg(x)を元の P_b(x)に変換する
```math
\log P_b(x) \fallingdotseq \log P_b(u) + \log exp\Big(-\frac{(x-u)^2}{2\sigma^2}\Big) = \log c ・ exp\Big(-\frac{(x-u)^2}{2\sigma^2}\Big)
```
よってP_b(x)は以下の形に近づく
```math
P_b(x) = c ・ exp\Big(-\frac{(x-u)^2}{2\sigma^2}\Big)
```
cの値は確率密度であるための必要条件を適用すると
```math
\int_{-∞}^∞ P_b(x) dx = 1
```
```math
c = \frac{1}{\sqrt{2π}\sigma}
```
となる
```math
P_b(x) = \frac{1}{\sqrt{2π}\sigma} exp\Big(-\frac{(x-u)^2}{2\sigma^2}\Big)
```
windows10環境でStable DiffusionでBRAV6を使いAI美女を作ろう！

# 環境設定

環境設定はこちらの記事を参考にしてください。

[windows10環境でStable Diffusionの環境を構築してみた](https://qiita.com/aramasa_ash/items/4910bc0c18ca083c7ab8)

# モデルのダウンロード

以下から取得出来ます。

https://huggingface.co/BanKaiPls/AsianModel/tree/main

「Brav6」で検索するとHItします。ダウンロードボタンから落としてください。

![333キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/00d655da-c488-3019-2aa7-391041b1dd9b.png)

ダウンロードしたモデルファイルを、git cloneした

`stable-diffusion-webui/models/Stable-diffusion`

直下においてください、

置いた後 `webui-user.bat` をダブルクリックか、コマンドプロンプト上で実行して下さい。
**※すでに開いている方は一度閉じて、再度起動してください。そうしないと反映されません。**

# プロンプトのサンプル

prompt
`(Best quality, 8k, 32k, Masterpiece, UHD:1.1),Photo of Pretty Japanese woman, face focus,`

Neagtive prompt
`(worst quality:2.0)bad hands,2faces,`

こちらで、他の項目はデフォルトでやってみました。

実行結果は以下です。

![FireShot Capture 003 - Stable Diffusion - 127.0.0.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/f0e39333-1cbf-0917-c3cd-3cdff86e00ab.png)

どうでしょう。

ほぼデフォルト設定でも、美人ですね！

![00091-2584496634 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/3453e297-c02c-37e3-549a-9005d56a54db.png)

# プロンプトの参考

制限数は75ですが、ある程度指定をすると細かく描画出来ます。

## カメラのアングル

| prompt | 説明 |
|:-----------|:------------|
| from above | 上から, 上から撮影したような |
|from below|  下から,下から撮影したような|
|from side| 横から, 横から撮影したような|
|from behind |後から, 後ろから撮影したような|
|dynamic angle| 動的なアングル	 |
|dutch angle| カメラを傾けたような|
|wide shot |広角・遠景|
|very wide shot| 超広角・遠景|

## キャラクターの目線・視線について
視線は基本的にこちらを向きます。

| prompt | 説明 |
|:-----------|:------------|
|looking at viewer 	|こちらを向く	よく使われている|
|looking at another |他を見る	効きにくい|
|looking away |よそ見をする|
|looking up |こちらを見上げる	 |
|looking down |こちらを見下ろす	 |
|head tilt |頭を傾ける	変化が少ない|

## 特定の身体部位を強調する
全身を描写したい時は、解像度を縦長に設定して「full body」を入れると良いです。

| prompt | 説明 |
|:-----------|:------------|
|full body |全身|
|face |顔	 |
|face focus |顔に焦点	 |
|close up |顔を強調	 |
|portrait |ポートレイト,顔,似顔絵・肖像画|
|profile |横顔	 |
|cowboy shot |頭部から膝あたり|
|upper body |上半身|
|lower body |下半身|
|foot focus |片脚～脚先|
|feet focus |両脚から脚先|

## 手(hand/hands)・指(finger/fingers)に関する動作
手に関するプロンプトは「指や手を動かす」動作と「何かを持つ」動作に分けられます。

| prompt | 説明 |
|:-----------|:------------|
|peace sign 	|ピース	両手でピースすることも|
|thumbs up |親指を立てる	 |
|waving |手を振る	 |
|salute |敬礼	ビシッと決めるのが困難|
|highfive |ハイタッチ|
|put one’s finger on ～|～に指をおく	 |
|put her finger on one’s lips |唇に指を当てる	, 「しぃ～っ」のポーズや|
|join hands |手を合せる	 |
|paw pose| 猫の手, 片手の時も両手の時も|
|claw pose| 「がお～」みたいな爪を強調したポーズ 長い爪が生える
|hold ～| ～を手に持っている ～を手に持つ	何かを持たせたいときに|
|holding cards |カードを手に持つ|
|holding a phone |電話を手に持つ, スマホを持つ|
|holding an apple |リンゴを手に持つ, リンゴを手に持つ|
|holding an umbrella |傘を持つ, 日傘を持っている|
|holding an umbrella, rain, |傘を持つ+雨, 雨と組み合わせると雨傘を持っているようになる|
|grabbing ～ |～を手で掴む, 手で何かを掴むときに|
|reaching out |手を伸ばす,手を差し伸べる,手を前に突き出す|
|outstretched arms| 大きく手を伸ばす,手が崩れる|
|hand in my pocket |ポケットに手を入れる	 |
podmanでのプロセスカウント方法の注意点

# はじめに

podmanを使っていて最大プロセス数制限に引っかかったのでメモしておく

# podmanにおけるプロセス数制限

podmanでは、デフォルトで一つのコンテナの中での最大プロセス数が2048に制限されている。
これはcgroupsを使って実現しているので、確認は
* コンテナ単独: `/sys/fs/machine.slice/libpod-{GUID].scope/`
* pod配下に入れている場合: `/sys/fs/machine.slice/machine-libpod_pod_{PODのGUID].slice/libpod-{コンテナID}.scope/`

以下にある、"pids.current"で現状のプロセス数が、"pids.max"で最大値が確認できる。
デフォルトではpids.maxは2048となる

# 一致しない?

さて、現在値であるpids.currentだが、実際見てみると、当初想定していた値と一致しない場合がある。
例えば、`docker.io/library/traefik` コンテナを書きコマンドで起動してみる。

```
podman run -d --name tr1 docker.io/library/traefik:latest
```

これで"tr1"というtraefikコンテナが起動するはず。
ここで、 `podman top tr1` でプロセス一覧を見ると、下記のような出力が得られる。

```
USER        PID         PPID        %CPU        ELAPSED       TTY         TIME        COMMAND
root        1           0           0.000       7.484374363s  ?           0s          traefik traefik
```

traefikプロセスが一つだけ。シンプルである。
しかし、この状態でtraefikのpids.currentを見ると、"1"ではないことを確認できるだろう。
筆者の環境では"10"だった。
これはなぜだろうか。

# 原因

一致しない原因は、 [**LWP(Light Weight Process)**](https://en.wikipedia.org/wiki/Light-weight_process) にある。
これ自体はUNIX系OSでは古くから使われているもので、ライブラリのスレッド実装はこの上に作られていることが多い。

topあるいは普通のpsだとこのLWP情報は表示されないが、pids.currentはこのLWPの数をカウントしているのである。
このため、psの結果と一見して一致しない状態になるのである。

# 把握方法

では、これをpodmanのtopやps等で把握したい場合はどうすればいいか。
psの実装にもよるが、procpsのpsならば、 `-L` オプションを付ければ、LWPの情報も見ることができる。
また、`-f`オプションも追加すれば、LWPのIDだけではなく、同じプロセスの中に何個のLWPが存在しているかという"NLWP"という情報も同時に取得できる。
コンテナの実装によってはpsがbusybox由来だったりするが、その時は`-T`オプションを付加すれば、数だけは把握できる。
`podman top`は引数付きで実行された場合はコンテナ内部のpsコマンドを実行するので、この辺りはコンテナによってやり方が異なるので注意

# 超えた場合に何が起きるか

実装によってエラーメッセージは変わってくるが、dotnetの場合、スレッドを作成した瞬間にメモリ不足エラーが起こる時が多い。この場合、スタックトレースも表示されることなく、OutOfMemoryExceptionのメッセージだけ出力されて終わる場合もあったりするので、現象として非常にわかりにくい。

# 増やす方法

podmanの場合、[containers.conf](https://docs.podman.io/en/latest/markdown/podman.1.html#configuration-files)ファイルで、 **pids_limit** を設定すれば変更可能。
例えば以下のようになる。

```ini
[containers]
pids_limit=4096
```

この後、podmanの場合はコンテナを再作成すれば反映される。

# 終わりに

通常一つのコンテナの中で数千のスレッドを同時起動というのは中々無いかもしれないが、重い処理と分かっている場合や、リソース消費の観点からわざとpids.maxを絞っている等は気を付ける必要がある。