OmniAICreator/Qiita-1.07M huggingface dataset:
Vim設定

### 記載内容と想定読者
 - Vimを使いだしてそれほど時間が経っていない、
 - 基本操作（移動やCut&Pasteなど）は、習得済みで
 - Vimさらに使いやすくするために設定をカスタマイズしたいと思いだした方
 - Vimでもコード補完やシンタックスハイライト（構文強調）を使いたいと思いだした方


# 1.設定ファイル（.vimrc）について
- Vimは、`.vimrc`という設定ファイルに設定内容を記載することで設定をカスタマイズすることが可能です。

## .vimrcの作成方法

```bash
## homeディレクトリに移動
$ cd

## .vimrcを作成
$ vim .vimrc

## 保存後にvimを起動すれば、設定が反映された状態で起動します
$ vim sample.txt
```

## .vimrcのサンプル
```vim:.vimrc
"viエディタとの互換性を持たせるためのオプションを無効にする
"（後述のPluginの機能を有効化させるために必要）
set nocompatible

"行番号を表示させる
set number

"編集しているファイル名などをTeratermやMacのターミナルなどのタイトル部分に表示させる
set title

"文字列検索にマッチする部分をハイライト表示させる
set hlsearch

"上記のハイライト表示がうざいときに[Esc]二度押しでハイライトを消す
nnoremap <silent><Esc><Esc> :<C-u>set nohlsearch!<CR>

"カーソルラインをハイライトさせる
set cursorline

"コマンドモードでのコマンド補完を有効化する
set wildmenu

"構文のハイライト表示を有効化する
syntax enable

"ファイルタイプの検出を有効にし、
"ファイルタイプ用のPluginを自動読み込みし、
"ファイルタイプに応じた自動インデントを有効化する
filetype plugin indent on

"Plugin Managerの有効化
call plug#begin('~/.vim/plugged')

Plug 'ctrlpvim/ctrlp.vim'
Plug 'scrooloose/nerdtree'
Plug 'jistr/vim-nerdtree-tabs'

call plug#end()
```

## Linux環境で使用している場合のroot userへの設定の反映方法
 - 一般ユーザとrootユーザの両方でvimを使用する場合、一般ユーザの設定（.vimrcの内容）は、rootユーザに反映されない。
 - root userを使うのが自分だけのような場合であれば、一般ユーザのvim関連ファイルのシンボリックリンクを設定することでroot userにも同じ設定を反映可能。

```bash:command
$ sudo ln -s ~/.vimrc /root/.vimrc
$ sudo ln -s ~/.vim /root/.vim
```

# 2.Pluginについて
### Pluginとは
 - Vimに機能を追加するための手段として、オープンソースの追加ソフト（Plugin）が提供されています。
 - Vimでは、Pluginを追加・更新するためにPlugin Managerというものを使用するのが一般的です。
 - Plugin Managerは、いくつか種類があり機能面や使いやすさで選択します。
 - どのPlugin Managerを使っても同じPluginを追加可能です。（おそらく）

### vim-plug
 - Plugin Managerの1つ。
 - ホームディレクトリで以下のコマンドを実行することで導入可能。

```bash:curl
## curlでgithubからplug.vimファイルをダウンロードして、.vim/autoload配下に配置
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
```

 - 以降のPluginは、vim-plugを利用している前提で導入方法を記載します。

### ctrlp.vim
 - コマンドラインモードから、作業ディレクトリやその配下のファイルを検索し一覧化、選択、編集できる。
 - 以下を.vimrcに追加し、最終行モードで`:PlugInstall`を実行することでインストールできる。

```vim:.vimrc
call plug#begin('~/.vim/plugged')

Plug 'ctrlpvim/ctrlp.vim'

call plug#end()
```

### coc.nvim
 - 詳しいことは、まだ把握できてないがコード補完のためのPlugin
 - https://github.com/neoclide/coc.nvim/wiki/Install-coc.nvim
 - https://qiita.com/atsushieno/items/ce31df9bd88e98eec5c4

```
## 使うにはnodeが必要であるためインストール（Macの場合）
brew install node

## .vimrc内のPluginの記載場所に以下を記載し、PlugInstall
Plug 'neoclide/coc.nvim', {'branch': 'release'}
```


### 参考記事
 - https://qiita.com/nil2/items/ddcf23f1163d0abd805b
本物のプログラミング初心者な自分が自作キーボードのセットアップで四苦八苦した時のメモ

プログラミング初心者過ぎてMDの記法もよく分からないです。後で調べよう...。

アリエクスプレスで購入したxd60 ver.3が届いたので、とりあえず動作確認するためにファームウェアのセットアップ(?)をすることに。(ちなみに動作確認にこの作業は必要ないです...。)

ここで詰まったことをメモしていきます。


1.　コマンドプロンプトで指定する時のキーボードのボード名が分からない！

https://roudokuvip.hateblo.jp/entry/2018/05/14/022016
こちらの記事を参考にセットアップを進めていたのですが、
”defaultのキーマップ設定ファイルが正しくコンパイルできることを確かめておく”
という項目で詰まってしまいました。

qmk_firmwareというディレクトリ(今自分がいるファイル)で

make xd60:default

を実行しろと書いてあるのですが、コピペして実行したところ

[ユーザー名@パソコン名 qmk_firmware]$ make xd60:default
QMK Firmware 0.13.19
make: *** No rule to make target 'xd60:default'. Stop.
|
|  QMK's make format recently changed to use folder locations and colons:
|     make project_folder:keymap[:target]
|  Examples:
|     make dz60:default
|     make planck/rev6:default:flash

というエラーが出てしまいました。

おそらくproject_folder名として入力したxd60が適切じゃないんだろうな...とは思ったのですが、適切な名前はどこで知れば良いのかわからず詰まってしまいました。

結果として
qmk_firmware\keyboards\xd60
にある
readme.mdに載っていた

Make example for this keyboard (after setting up your build environment):

    make xd60/rev2:default  # rev2
    make xd60/rev3:default  # rev3

という文章から分かりました。まさしく今実行しようとしていたことを例として上げてくれていたみたいです。

自分が購入したのは

Xd60 xd64 3.0 pcbカスタムメカニカルキーボードキットunderglow rgb GH60 60% プログラマブルmx alps幹分割スペースバータイプc
https://ja.aliexpress.com/item/32919981329.html?channel=twinner 

だったのでxd60/rev3が正しいと分かりました。

このpcbでなくとも、qmkに対応していればqmk_firmware\keyboardsから目的のキーボードのreadme.mdを見つけて名前がわかるはずです。

こんなところで詰まる人はなかなかいないとは思いますが、いい機会だと思い投稿することにしました。この先も長いので詰まった点があれば追記していこうと思います。
ArduinoUNOとにおいセンサーAE-TGS8100で液晶表示 (Arduino)(AQM0802A)


目的
コロナ等を含め室内の空気のよごれをにおいを通して値数表示する。

構成
AE-TGS8100 K-15562
AQM0802A-RN-GBW P-06669

説明
まず後で3.3V系で使いたいのでマニュアルの式から
プログラムを作った。秋月の式と値が正しい事を確認した
0で割るとエラーになることを確認したので何でも良かったので
0を-1に変換した。現実的には、マイナスの大きい数になるので
区別が付くからマーいいか
そのままだとつまらないので液晶を付けた。
CO2センサーの為の前段階

main - 初期化
loop - 繰り返し処理
i2c_led_w - 2バイトI2Cに送る


![serial_nioi_uno_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/7a203dd9-e48b-ee3a-6a90-d3f72c71ef0b.jpeg)



![serial_nioi_uno_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/ed2b0cfb-e86f-a746-974a-e33833b3a1ac.jpeg)


![serial_nioi_uno_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a38154dc-5873-2ce1-8d65-1e184812f864.jpeg)




```c++

#include <Wire.h> //I2C library

//STM32G031J6M6
#define sdaPin PA12    // ArduinoA4
#define sclPin PA11    // ArduinoA5

// I2C  address. 
#define I2Cadr  0x3e  // 固定

char    data_read[2]={'@','t'}; //i2cバッファー
int     ii;                     //ループカウンター

char INIT_com[]={0x0,0x38,
0x0,0x39,
0x0,0x4,
0x0,0x14,
0x0,0x70,
0x0,0x56,
0x0,0x6C,
0x0,0x38,
0x0,0xC,
0x0,0x1,
0x40,0x41};

char INIT_cls[]={0x0,0x1};

void i2c_led_w(char *buff1){
  Wire.beginTransmission(I2Cadr);
  Wire.write(buff1[0]);
  Wire.write(buff1[1]);
  Wire.endTransmission();
  delay(2);
}//i2c_led_w

int adval = 0;
float sensor_r;

void setup() {

  delay(3000); //not delete

  //i2cの初期化
  Wire.begin(); // initialise the connection //767 UNO
  //Wire.begin(sdaPin,sclPin); //STM32G031J6M6

  //液晶の初期化
  for(ii=0;ii<11;ii++){
    i2c_led_w(&INIT_com[ii*2]);
  } //for

  Serial.begin(9600);
  pinMode(A0, OUTPUT);
}//setup

float v1;
float rs;

void loop() {
  digitalWrite(A0, HIGH);
  delay(1);  
  adval = analogRead(A1);
  delay(1);
  digitalWrite(A0, LOW);

//Serial.println(adval);
//adval = 1024;
//adval = 0;

if(adval == 0) {adval = -1;}

v1 = (    ((float)adval) * 5.0) / 1024.0;

//Serial.println(v1,3);

rs =( (3.0-v1)/v1 ) * 10.0;

Serial.println(rs,3);

/*
  if(adval != 0) {
    sensor_r = 6144.0 / adval - 10;
    Serial.println(sensor_r,3);
  } else {
    Serial.println("0");
  }//end if
*/
  delay(998);

  int s = rs;
  int n0,n10,n100;

  n10  = s / 10;           // 123 -> 12
  n0   = s - (n10 *10);    // 123 - 120 -> 3
  n100 = n10 / 10;         // 12  -> 1
  n10  = n10 - (n100 *10); // 12 - 10 -> 2
  
  //画面のクリア
  i2c_led_w(INIT_cls);

  //液晶に表示
  data_read[1] = '0' + n100;
  i2c_led_w(data_read);
  data_read[1] = '0' + n10;
  i2c_led_w(data_read);
  data_read[1] = '0' + n0;
  i2c_led_w(data_read);

}//loop



```
Django初心者がつまずいたmodelsを変更した際にmigrateができない！？

環境 
macOS Big Sur
python 3.8.5
django version 3.0.5


Djangoでデータベースを作成する際に便利なmodelsですが、変更や修正を加えた時にちょっと難しいなと思った場面があったので記事にまとめてみました。

まず現在のテーブルに入ってるカラムに新しいカラムを追加をする更新は簡単にできるみたいなのですが、
現在のテーブルにあるカラム自体に変更を加えると何やらめんどくさいことになるようです。
（例えばカラム名を変更したり、カラムのfieldを変更したり）

※詳細はこちらのサイトをご参考ください
https://kunimiya.hatenablog.com/entry/20080726/p1

なので大胆に仕様変更する場合には一度migrationフォルダにあるinitial.pyを削除してmakemigrationsした方が早いことが分かったのですが、ここで問題が発生！

makemigrationsはできるけど...migrateができません...
![スクリーンショット 2021-07-10 19.37.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748791/d1697427-af85-aa3d-9d4c-8312a14bda7c.png)

よく考えれば当たり前のことなのですがテーブルが前のままなので結局変更できないんですね。
ということはデータベースをまた作り直すのか...と思っていたのですがそんなことはありませんでした。

![スクリーンショット 2021-07-10 20.01.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748791/866b32ed-5cee-217f-6851-a3ca1d18b575.png)

python manage.py migrate [削除したアプリ名] zero

でテーブルをリセットすることができました。
これで無事migrateをやり直し、modelsを新たに反映させることができました。
![スクリーンショット 2021-07-10 20.02.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748791/d177387b-5799-7691-3bed-0bddb98be005.png)
Linux で動くBASIC

Linuxで動くBASICインタプリタ、bwbasicを試してみました。
Linuxで動くBASICインタプリタは、色々あって、１０進BASIC何ていうのもありますが、
数値計算用ではなく、ちょっと動かして見ただけなので、bwbasicを選択しました。
インストール：
sudo apt-get install bwbasic

実行例

```
$ bwbasic
Bywater BASIC Interpreter/Shell, version 2.20 patch level 2
Copyright (c) 1993, Ted A. Campbell
Copyright (c) 1995-1997, Jon B. Volkoff
 
bwBASIC: 
bwBASIC: 10 for i=1 to 10
bwBASIC: 20 print "Good Morning. God Bless Us All."
bwBASIC  30 next
bwBASIC:
bwBASIC: list
     10: for i=1 to 10
     20: print "Good Morning. God Us All."
     30: next
bwBASIC: run
Good Morning. God Bless Us All.
Good Morning. God Bless Us All.
Good Morning. God Bless Us All.
Good Morning. God Bless Us All.
Good Morning. God Bless Us All.
Good Morning. God Bless Us All.
Good Morning. God Bless Us All.
Good Morning. God Bless Us All.
Good Morning. God Bless Us All.
Good Morning. God Bless Us All.
bwBASIC: 
```
Ruby on railsで最低限知っておくべきコマンド

1.最低限これらのコマンドは使えるようにしましょう。
cloud9で開発を前提で記載します。

```console

　新規アプリ作成
$ rails new アプリ名　　　　　　　　　　　新規アプリ作成

　サーバーの起動
$ rails s -b $IP -p $port  　サーバーの起動

コントローラー作成
＄　rails g controller コントローラー名　　　　　　　コントローラー作成

バージョンの確認
$ rails -v 

モデル作成コマンド
　$ rails g model モデル名　カラム名:型  モデル名は大文字から始まる
　$ rails g model  User name:string age:integer

カラム追加コマンド
$ rails  g migration   add_カラム名_to_テーブル名　カラム名：型
$ rails  g migration   add_mail_to_users mail:string

マイイグレーション実行
$ rails  db:migrate　　　　　　　データベースへの反映

データベース作成
$ rails db:create
```
Pythonのos.listdirを使ってフォルダ内のファイルリストを取得する

今回はglobではなくos.listdirでファイルリストを取得する方法を紹介します。
最後にも紹介しますが、この関数とwxPythonを組み合わせてファイルマネージャーをつくることができます。
→ <a href="https://programming-self-study.blogspot.com/2021/06/wxpython-filem.html">https://programming-self-study.blogspot.com/2021/06/wxpython-filem.html</a>
#コード

```Python:sample.py
import os
filelist = os.listdir("C:\\Users\\")
for file in filelist:
    print(file)
#.NET v2.0
#.NET v2.0 Classic
#.NET v4.5
#.NET v4.5 Classic
#All Users
#Classic .NET AppPool
#Default
#Default User
#DefaultAppPool
#desktop.ini
#...
```
こんな感じで取得します。
#globとの違い
まず、globは`C:\\Users\\*.txt`のように拡張子などをを指定してできます。
が、別のことも調べていきましょう、
##出力内容の違い
###os.listdir

```
.NET v2.0
.NET v2.0 Classic
.NET v4.5
.NET v4.5 Classic
All Users
Classic .NET AppPool
Default
Default User
DefaultAppPool
desktop.ini
...
```
ファイル名のみを出力しています。
###glob
```
C:\Users\All Users
C:\Users\Classic .NET AppPool
C:\Users\Default
C:\Users\Default User
C:\Users\DefaultAppPool
C:\Users\desktop.ini
...
```
パス全体を出力しています。あとなんか.NETなどのフォルダが表示されていません。
##速度の違い
比較に利用したコードはこんな感じです。

```Python:hikaku.py
import glob
import os
import time

#glob

s = time.time()
filelist = glob.glob("C:\\Windows\\System32\\*")
print(time.time()-s)

#listdir

s = time.time()
filelist = os.listdir("C:\\Windows\\System32\\")
print(time.time()-s)
```

###glob
```
0.04687190055847168
```
###listdir
```
0.0
```
あくまでも自分の環境で実行した場合です。
実行すると、その都度速度が変わりますが、listdirのほうがほんの少しはやいのがわかります。


#おわりに

あえてblogではなくlistdirを使わなければいけないというわけではありませんでした。

これらの関数とwxPythonを組み合わせてファイルマネージャーをつくってみました。
→ <a href="https://programming-self-study.blogspot.com/2021/06/wxpython-filem.html">https://programming-self-study.blogspot.com/2021/06/wxpython-filem.html</a>

↑の記事はファイルリスト取得してListCtrlに反映、あとはリストクリック時の設定をするだけのシンプルなものです。
pythonを便利に使おう第四回！行列編！

#初めに
　数学の歴史には表現の秀逸さを整える歴史とも言える部分が多くあります。その中で私が好きな要素を上げるとすれば、自然対数e、虚数i、そしてlogです。…行列はこの中には特に入ってなかったのですが、ビッグデータを解析したいというときには、行列の内積を使いたいなとなりましたので、今回は行列についてpythonで勉強して行こうと思います。

#第８章「行列」の問題
　というわけで今回例題として使わせていただくのはこちら！
>http://web.sfc.keio.ac.jp/~kawazoe/math/book/d-chap8.pdf

  Google先生で数学　行列　問題で調べれば一番上に出てきました。この中から適当に問題をセレクトして解いていこうと思います。
##第一問　行列の計算

```math
3 
\left(
\begin{matrix}
1 & -3 \\ 
2 & -4 
\end{matrix}
\right)
-2
\left(
\begin{matrix} 
5 & 6 \\ 
7 & 3 
\end{matrix}
\right)
```

  pythonのnumpyを使用した場合、使用できるメソッドはarrayとmatrixがあります。matrixは2次元の行列に適応しており、３次元以上を渡すとエラーする模様です。３次元以上も使いたいので、今回はarrayを使っていきます。

```python
>>>import numpy as np
>>> 3*np.array([[1,-3],[2,-4]])-2*np.array([[5,6],[7,3]])
array([[ -7, -21],
       [ -8, -18]])
```

##第二問　行列の積

```math
\left(
\begin{matrix}
1 & 2 \\ 
3 & 1 
\end{matrix}
\right)
\left(
\begin{matrix} 
1 \\
2 
\end{matrix}
\right)
\qquad\
\left(
\begin{matrix}
1 & 3 \\ 
2 & 4 
\end{matrix}
\right)
\left(
\begin{matrix} 
4 & 1 \\
3 & 2
\end{matrix}
\right)
```

```python
>>> np.array([[1,2],[3,1]])@np.array([[1,2]]).T
array([[5],
       [5]])
>>> np.array([[1,3],[2,4]])@np.array([[4,1],[3,2]])
array([[13,  7],
       [20, 10]])
```

　もしかしたら分からないかもしれないところもあるので、解説しましょう。まずアットマーク(@)についてですが、これは内積を表しています。np.array().Tというのは行列の転地を表しています。これらを駆使して計算しています。

##第三問　次のrankを求めなさい。

```math
A=\left(
\begin{matrix}
-1 & 1 & -1 \\ 
2 & 0 & 1  \\
1 & -3 & 2 \\
\end{matrix}
\right)
```

  ここでいうrankというのは行列の階数ということらしいです。

>行列の階数というのはある行列 に含まれる行（列）ベクトルがいくつのベクトルの１次結合でそれぞれ表されるかという意味です。他にも捉え方も色々とありますが、行列そのものが持つある種の次元に近いイメージです。
https://deepage.net/features/numpy-rank.html

　ということらしいです。こういう数学の細かい要素っておそらく勉強して　いるんでしょうが、覚えていないものですね。
　兎にも角にも問題を解きましょう。

```python
>>> np.linalg.matrix_rank(np.array([[-1,1,-1],[2,0,1],[1,-3,2]]))
2
```

　もはやここまで長い式になるのなら可視性のためにも、A=などして定義を分けるべきなんでしょう。次からします(めんどくさがり)

##第四問　次の逆行列を求めなさい。

```math
\left(
\begin{matrix}
1 & -1 & -2 \\ 
2 & -1 & 5  \\
1 & -1 & -1 \\
\end{matrix}
\right)
```

```python
>>> A=np.array([[1,-1,-2],[2,-1,5],[1,-1,-1]])
>>> np.linalg.inv(A)
array([[ 6.,  1., -7.],
       [ 7.,  1., -9.],
       [-1.,  0.,  1.]])
```

##第五問　次の行列式を求めなさい。

```math
\left|
\begin{matrix}
-1 & 1 & 3 & -2 \\ 
-3 & 3 & 5 & -3  \\
3 & -2 & -5 & 3 \\
2 &-1 & -3 & 2 \\
\end{matrix}
\right|
```

```python
>>> A=np.array([[-1,1,3,-2],[-3,3,5,-3],[3,-2,-5,3],[2,-1,-3,2]])
>>> np.linalg.det(A)
-0.9999999999999991
```

-1とはならずに-1の近似になってしまったのはコンピューターの仕方のないことでしょうか。正解…でいいのかな？

#最後に
　今日はこの程度で終わりです。
　pythonの便利さというのがとてもわかりますね。そりゃコンピュータで計算するんですから、エラーはあっても間違えに到着することはそこそこないでしょうけれど、しかし、人間が計算するよりは計算制度が高いというところに意義があるので、学校でのテストでパソコンを持ち込ませてほしいですね!(´；ω；｀)
　numpyでの行列の操作が理解できたので、今後は上手く使っていけそうです。
商品詳細表示機能のおさらい

必要な機能

１.トップページから商品をクリックすると商品詳細ページに移動できるようになること
２.ログイン中のユーザー、投稿主ではないログイン中のユーザー、ログインしていないユーザーで詳細ページの表示が変わること



１.トップページから商品をクリックすると商品詳細ページに移動できるようになること

①showアクションのルーティング設定

画像は省略。

②showアクションのコントローラー設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1650636/b48e0a96-d8c0-e0e2-6c37-2805f777cd27.png)

③showアクションに商品の情報を入手するset_productメソッド作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1650636/0e314ceb-7ddd-c78f-022c-bded1560a213.png)

④beforeアクションに適用
https://gyazo.com/582372a527a8e275f22744452882c11e

⑤トップページから表示機能のパス指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1650636/58d05ade-8f78-4d55-a910-0ffaac7d8516.png)

＊product_path(product.id)のproductをインスタンスとして使わない理由は、親要素のeacｈ文にインスタンスを取り入れっており、ブロック変数productを使用する必要があるため

⑥商品情報を表示させるためのビュー修正

省略

２.ログイン中のユーザー、投稿主ではないログイン中のユーザー、ログインしていないユーザーで詳細ページの表示が変わること

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1650636/3d985168-f333-7901-35a2-a8d4c6465cd5.png)

if文のネスト構造によって、elseで表示する値は、<% if user_signed_in?>は真だが、
<% if current_user.id == @product.user.id %>
は負である、という条件にできる
そして、両方違う場合は何も返さない、という結果にできる

イメージとしては、ザルの上に更に穴の小さいザルを載せるかんじ。
R (>= 4.1)用のvimコマンド (3行)

R 4.1のパイプ演算子 `|>` が打ちにくすぎるので、neovimのキーマッピングに以下を追加した。

`inoremap <silent> <C-p> \|>`

Ctrl + p で `|>` が入る。`<silent>` は、あってもなくても良いと思われる。
Material UI のTextFieldのInputPropsの使い方

# `InputProps`の用途
`TextField`のプロパティ。
3rdパーティ製ライブラリなどを用いて、入力フォーマットをカスタマイズすることなどができる。
細かい制御も可能になる。

`InputProps`は、`inputProps`と`inputComponent`を持つ。
**I**nputPropsは、**i**nputPropsを内包している。

## `inputComponent`
`TextField`の処理コンポーネントを指定する。

## `inputProps`
`inputComponent`で指定したコンポーネントに渡す`props`オブジェクト。
自作コンポーネントのPropsと`HtmlInputElement`や`HTMLTextAreaElement`のPropsが許容される。

# 実装例
```sample.jsx
const sample = ()=>{
    const [value, setValue] = useState("")

    return <TextField
            className={classes.text}
            InputProps={{
                inputProps: {
                    value: val,
                    onChange: (e:React.ChangeEvent<HTMLInputElement>) => setVal(e.target.value),
                    type: "text",
                    test: () => {}
                } as OriginalBaseInputProps, // 自作コンポーネントPropsとHtmlInputElementやHTMLTextAreaElementのProps
                inputComponent: OriginalBaseInput // 自作コンポーネント
            }}
        />
}
```

```OriginalBaseInput.jsx
export interface OriginalBaseInputProps {
    test: () => void
}

export const OriginalBaseInput = (props: PropsWithChildren<InputBaseComponentProps>) => {
    function onKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
        // 1桁目を常に選択
        ref.current?.setSelectionRange(0, 1)
    }

    const ref = createRef<HTMLInputElement>()
    return <input {...props} onKeyDown={onKeyDown} ref={ref}/>
}
```

`inputComponent`に渡ってくる`props`には、`inputRef`が入っている。
`OriginalBaseInput`の`{...props}`で自作コンポーネントのPropsと`HtmlInputElement`や`HTMLTextAreaElement`のPropsが展開している。
言語処理100本ノックで苦戦した話

#### 言語処理100本ノックで苦戦した話

この記事は100本ノックの回答を書いたものでもなければ、
問題に対する意見を述べるものではありません。

ただただ、初学者である私が環境構築で苦戦した話です。笑
同じ苦労をしている人の助けになればと思い記事を書きました。
参考にする際は自己責任でお願いしますm(_ _)m
[言語処理100本ノック](https://nlp100.github.io/ja/)

捕捉で私が使っている環境を簡単に記載します。
m1 mac
python3.8(anacondaのJupyterNotebook)

#### import　MeCab でのエラー
始めに立ちはだかった壁は**MeCabのimport**。

anacondaにMeCabが入っていなかったので、
anacondaの公式にあった以下のコードでインストールしました。

```
conda install -c conda-forge mecab
```

もちろん何の問題もなくインストールでき、importするためにコードを実行！

```python
import MeCab
```
すると

```python
ModuleNotFoundError: No module named 'Mecab'
```

conda list でインストールされているか確認をすると問題なく入っている。。。
いろいろ調べた結果、pip installで行う必要がありそう。
私の環境がanacondaだけにpip installを使いたくありませんでしたが、背に腹はかえられぬということで
conda uninstall　MeCabを行なってから、pip install MeCabを実行

それでようやく、import MeCabで問題なく動きました！


#### CaboChaの環境構築での苦戦
まず行なったことは、
以下のコードでCRF＋＋をダウンロード、解凍、インストール

```python
FILE_ID = "0B4y35FiV1wh7QVR6VXJ5dWExSTQ"
FILE_NAME = "crfpp.tar.gz"
!wget 'https://docs.google.com/uc?export=download&id=$FILE_ID' -O $FILE_NAME
!tar xvf crfpp.tar.gz
%cd CRF++-0.58
!./configure && make && make install && ldconfig
%cd ..
```
ここまでは問題なくいけました。
その後、以下のコードでCaboChaのダウンロード、解凍、インストール

```python
FILE_ID = "0B4y35FiV1wh7SDd1Q1dUQkZQaUU"
FILE_NAME = "cabocha-0.69.tar.bz2"
!wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=$FILE_ID' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=$FILE_ID" -O $FILE_NAME && rm -rf /tmp/cookies.txt
!tar -xvf cabocha-0.69.tar.bz2
%cd cabocha-0.69
! ./configure -with-charset=utf-8 && make && make check && make install && ldconfig
%cd .. 
```

ここでエラー文が出ました。泣

```
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [cabocha] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
```

初学者の私にはよくわからず苦戦。

結局homebrewでインストールすることにして
ターミナル上で以下のコードを実行。
※今回、homebrewのインストール方法は割愛します。

```
$ brew install cabocha
```

さっきまでの苦労はなんだったのか!!というくらいあっさりいきました。笑

これでjupyter NotebookでもCaboChaが使えるようになり、
言語処理100本ノックの続きに取り組むことができました！
40 代おっさん 基本的なブログを構築してみた　③

## 本記事について

本記事は AWS 初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 最終構成図

![RDSEC2ブログ構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/ff6040e2-3945-fb8b-4bf0-a03cb402cbc3.png)

40 代おっさん 基本的なブログサービスを構築してみた
<https://qiita.com/kou1121/items/9254eb27912311b54c19>

40 代おっさん 基本的なブログサービスを構築してみた　②
<https://qiita.com/kou1121/items/e10c88f458840e81d226>

## WordPressをインストール

前回の見ていただくか、Tera Termでssh接続をしてください。

接続したら
ユーザー権限だと権限が足りないこともあるので管理者権限にスイッチしましょう

```shell
sudo su -
```

![sudo.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/a407b189-a349-c8a0-1a17-72331fa5a5ca.png)

rootになっていれば管理者権限にスイッチしています。
それではパッケージの状態を最新のものにします。

```shell
yum -y update
```

これでパッケージが最新の状態になりました！
次にWordPressに必要なソフトケアがあります、Apache、php、MySQLがありますのでそちらをインストールします。
まずはphp

```shell
amazon-linux-extras install php7.2 -y
```

次にMySQL、Apacheあとphpの必要なものをインストール

```shell
yum -y install mysql httpd php-mbstring php-xml gd php-gd
```

あとApacheのサービスが再起動後も自動で起動するようにします。

```shell
systemctl enable httpd.service
```

アパッチをスタート状態に

```shell
systemctl start httpd.service
```

念のためステータスを確認

```shell
systemctl status httpd.service
```

active(running)　になっていれば大丈夫です。

![active.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/e6ea430f-640d-ef65-c07e-20eb88ae107f.png)

ここまでくればWordPressが動く状態になったのでWordPressをインストールします。

```shell
wget http://ja.wordpress.org/latest-ja.tar.gz ~/
```

カレントディレクトリ内容をllで確認

```shell
ll
```

![ll.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/5479b327-401b-6206-be08-5956f61290b7.png)

tar.gzで圧縮されているので展開します。

```shell
tar zxvf ~/latest-ja.tar.gz
```

再度llで確認

![ll再度.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/49dc54db-01a6-77fa-a179-bb12157bb537.png)

これでwordpressと言うカレントディレクトリがあることがわかり、展開されました。
次に

```shell
cp -r ~/wordpress/* /var/www/html/
```

/var/www/html/にwordpress以下配下のファイルをコピーします。
次に

```shell
chown apache:apache -R /var/www/html/
```

/var/www/html/配下の権限をapacheに変えます。
これでwordpressが閲覧可能になっています。
ではパブリックIPアドレスをコピーしてアドレスバーに貼り付けてください

![wordpress.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/2f815825-97d9-03db-4ef7-cdb647c4035c.png)

wordpressの初期設定画面が出てきます。
ではwordpressの初期設定します。

![wordpress.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/3eb94c72-1845-48d0-d088-bda3ab50bd4d.png)


データベース名はそのままで
ユーザー名はRDSの設定時に作ったユーザー名で（赤枠）
パスワードもRDSの設定時に作ったもので　　　（青枠）
データベースのホスト名はRDSのエンドポイントを入れてください（緑枠）

送信をクリック
インストール実行をクリック
ここから先は任意で大丈夫です

![AWSブログ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/7c9c9c4b-54a8-794d-253e-40eaf7eba9a2.png)

おお～～できた～～

## 最後に

できました～～
うれしいですね＞＜
こんな調子でがんばりたいです！！

またこの記事は AWS 初学者を導く体系的な動画学習サービス「AWS CloudTech」の課題カリキュラムで作成しました。
<https://aws-cloud-tech.com/>
MacにARM EABI HFなツールチェインをインストール

CGOを使ったgoプログラムを、ARM向けにクロスビルドしたくなった。
そのためには、ターゲット用のクロスコンパイラーをインストールする必要があるようだ。

# 環境

- MacBook Air (M1, 2020)
- macOS Big Sur 11.3.1
- Go 1.16.5

# ターゲットの環境

- Armadillo-IoT A6
- アーキテクチャ: ARMv7
- ABI: armeabihf

# 既存の方法

- [【macOS】ARMのGCCコンパイル環境を構築する
](https://www.yokoweb.net/2016/09/03/macos-arm-gcc/)
- [【macOS】ARMのGCCコンパイル環境を構築する（brewから公式「GNU Arm Embedded Toolchain」をインストール）](https://www.yokoweb.net/2018/05/16/macos-gcc-arm-brew-install/)

これらの方法は、ARM公式のビルド済ツールチェインをインストールする方法。
しかし、ARM公式で用意してくれているのは、gcc-arm-none-eabiなツールチェインのみ。

[別のページ](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads)では、EABI HFなツールチェインも配布してくれているが、Mac用は無い orz

[RaspberryPi：Macでクロスコンパイル＆デバッグ](https://qiita.com/infinite1oop/items/c25a592f360e3c72a8ee)
こちらの記事のように、ソースからツールチェインをビルドする方法もあるが、めんどくさい。

# 基本的対処方針

[Pre-built ARM/Linux C cross-compilers for MacOS](https://thinkski.github.io/osx-arm-linux-toolchains/)
Mac OS用のビルト済ツールチェインを公開してくれている人がいたので、これを使う。
しかし、ビルドスクリプトを公開してくれていないので、中身がどうなっているのか大変怪しい。

[crosstool-ng](https://crosstool-ng.github.io/)を使ってビルドしたらしいので、本来は、自前でビルドするのが正しい姿勢だろう。

# インストール手順

arm-unknown-linux-gnueabihfのtarボールをダウンロードし、展開する。

```
% cd ~/Download
% wget https://github.com/thinkski/osx-arm-linux-toolchains/releases/download/8.3.0/arm-unknown-linux-gnueabihf.tar.xz
% sudo mkdir -p /opt/toolchain
% cd /opt/toolchain
% sudo tar xJvf ~/Download/arm-unknown-linux-gnueabihf.tar.xz
```

パスを通す

```sh:.zshrcに追記
export PATH="$PATH:/opt/toolchain/arm-unknown-linux-gnueabihf/bin"
```

シェルを再起動して、動作確認

```
% exec $SHELL
% arm-unknown-linux-gnueabihf-gcc --version
arm-unknown-linux-gnueabihf-gcc (crosstool-NG 1.24.0) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```
Django勉強記録

#はじめに
色々あって今日からDjangoの勉強を始めます。少しずつですが、Djangoの勉強したことをこの記事に残していこうと思います。初心者なので優しい目で見て頂けると助かります。

#Djangoとは何か
Djangoは、Pythonで実装されたWebアプリケーションフレームワークです。簡単に言うと、アプリケーションを開発する際に便利な機能が入った箱のようなものです。

＜主な特徴＞
・「ユーザ認証」,「管理画面」,「サイト案内ページ」,「RSSフィード」
※RSSフィードとは、<b>HPやブログの更新案内</b>のようなものです。
・セキュリティ面で安全
・メンテナンスや拡張が簡単にできる
・用途が広く会社や組織でも使用される
・シンプルなフレームワーク

#Djangoのインストール
早速ですが、Djangoをインストールしてみようと思います。
今回はすでにPythonはインストールされたていで話を進めていきます。
もし、まだPythonをインストールされていない方は以下のリンクからインストールしてから以下の手順を進めてください。
[Python :  https://www.python.org/](https://www.python.org/)

###（１）pipコマンドでインストールしてみよう

```
pip install django
```

###（２）正しくインストール出来ているか確認
Pythonを起動

```
$ python
```

以下のコマンドを入力してバージョンを確認してみよう

```
>>> import django
>>> django.get_version()
'3.2.5'
```

「>>>」の部分のコマンドを入力するとバージョンが表示されます。
今回の場合だとバージョンは'3.2.5'です。
このようにバージョンが表示されたら正しくインストールされています。

#最後に
今回はDjangoの説明とインストールまで書いてみました。
次回は実際にDjangoを使用してみようと思います。
Google Data portalで累計データから日毎推移グラフを作成するためのメモ

##厚労省のオープンデータを利用
Power BI Desktopで、時系列の累計集計データから、日毎の新規数の推移をするグラフを作成するのに手間取ったことがあります。
Google Data Portalでは比較的容易のできることがわかりましたので、その操作手順のメモです。
使ったデータは厚労省が提供している、新型コロナウイルス発生状況の[オープンデータ](https://www.mhlw.go.jp/stf/covid-19/open-data.html)です。

https://www.mhlw.go.jp/stf/covid-19/open-data.html

上記のデータで、「死亡者数」だけがなぜか累計なので、日毎の新規死亡者数の推移の集計に切り替えます。

##「実行中の差分」を利用

そのまま取り込み折れ線グラフを作成するとこうなります。
累計推移です

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/f0e16a7b-15ae-9bde-ebb3-6da7493489ec.png)

同じ死亡者数フィールドを指標に配置し、左端にマウスオーバーし、ペンが斜めになったアイコンをクリックし、データタイプを変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/c51aab56-90e1-6822-5ff2-e041acb5f50d.png)

設定画面を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/8c4714b0-c131-12d3-b16c-33db7c5fa2c9.png)

設定画面下の「関数」で「実行中の差分」を選びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/54212819-67f3-755e-ca78-2f3a6d07231f.png)

右側のY軸を割り当て、累計と日毎推移を重ねて配置しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/01a2f4f9-2a1b-3d81-c0a9-da22abdc5147.png)

表にしてみると、先ほどの「実行中の差分」は、「前日-当日」と計算され、「前日」に差分値が割り当てられています。
グラブにする場合、その差分のみを使うのでなく「プロット当日の値として、-1×（前日-当日）」をプロットしているようです。
こうした構造、仕組みは後ほどもう少し調べてみようと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1143963/53de1fb2-8f6d-7955-1cf9-0db6dc34efc0.png)


**了**
Google認証システムアプリを他の端末でも利用できるようにする

Google認証システムに登録した２段階認証を
他のスマホに移行させる方法。
というか、「移行」という言葉は移し替える意味があるとおもうので
もう１台別のスマホでも利用できるようにするという意味で捉えてください。
なので、以下の操作をすると２台とも同じアカウント認証キーを発行している状態になります。
要するに２台共、アクティブな状態です。


１．１台目の「認証システム」アプリを起動
２．右上・・・メニューボタンから「アカウントの移行」をタップ
３．「アカウントのエクポート」を選択
４．端末認証が現れるので対応してください
すると、QRコードが表示されます

５．２台目のスマホで「認証システム」アプリを起動
６．アプリ右下の（＋）をタップ
７．カメラで１台目に表示されているQRコードを撮影

これで２台共同じアカウントの認証コードが表示されることになります。

アカウントを追加した際、この手順を再度行うことで、２台共同じアカウントが表示されます。
AtCoderログ：0012 - ABC 085 A

# 問題：[ABC 085 A - Already 2018](https://atcoder.jp/contests/abc085/tasks/abc085_a) ([AtCoder に登録したら次にやること 第02問類題](https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-2-%E5%95%8F--abc-081-a---placing-marbles-100-%E7%82%B9))

## 問題文
> $2018$ 年 $1$ 月某日、高木さんは書類を書いています。書類には、その日の日付を yyyy/mm/dd という形式で書き込む欄があります。例えば、$2018$ 年 $1$ 月 $23$ 日は 2018/01/23 となります。
> 書類を書き終えたあと、高木さんは日付欄の先頭に誤って 2017 と書いてしまっていたことに気がつきました。高木さんが日付欄に書いた文字列 $S$ を入力すると、$S$ の先頭の $4$ 文字を 2018 に修正して出力するプログラムを書いてください。

## 制約
> ・$S$ は長さ $10$ の文字列である。
> ・$S$ の先頭の $8$ 文字は 2017/01/ である。
> ・$S$ の末尾の $2$ 文字は数字であり、$1$ 以上 $31$ 以下の整数を表す。

# 回答 (AC)

日付を表す文字列 $S$ を変数 s で受け取り、はじめから 4 文字目の '7' を '8' に書き換えて出力すれば良いでしょう。コードは以下のようになりました。

```C++:abc085a.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  string s;
  cin >> s;

  s.at(3)='8';

  cout << s << endl;
}
```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/abc085/tasks/abc085_a/editorial) → [ユーザ解説](https://blog.hamayanhamayan.com/entry/2018/01/07/224820)
回答と同じ方針でした。

## [AtCoder の解説](https://atcoder.jp/contests/abc085/tasks/abc085_a/editorial) → [コンテスト全体の解説](https://img.atcoder.jp/abc085/editorial.pdf)
回答と同じ方針でした。C++では文字列を書き換えられるので、簡単な問題なのでした。

# 学んだこと
- 文字列の参照・書き換え (a.at(*))

# リンク
- 前の記事 → [AtCoderログ：0011 - ABC 095 A](https://qiita.com/RoadLynton/items/d2821a27e55fad832b79)
- 次の記事 → [AtCoderログ：0013 - ABC 209 に参加しました](https://qiita.com/RoadLynton/items/2a732766771f067b4edf)
Firebase Cloud MessagingをAndroid端末間で送受信する方法

趣味でAndroidアプリの開発をしていますが、端末間で通知の送受信を行う方法が調べても出てこなかったので記録として残しておきます。
HTTP通信で通知内容をJSON形式で送る手法を用いています。

初学者なので所々間違っているかもしれません。ご了承ください。

```

private val URL = "https://fcm.googleapis.com/fcm/send"
private val MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8") 
private val CLIENT = OkHttpClient()
private val id = "送信者ID"

Thread{//非同期処理じゃないと動かないので注意
  try {
      val jsonData = "{\"to\":\"見守る側の端末トークン}\",\"notification\":{\"title\":\"通知のタイトル\",\"body\":\"通知の詳細\"}}"
      val serverKey = "サーバキー"
      send(serverKey,jsonData)
  }catch (e:Exception){
      エラーメッセージ
  }
}.start()

private fun send(serverKey: String, jsonString: String): Response = newCall(serverKey, jsonString).execute()

private fun newCall(serverKey: String, jsonString: String): Call =
    CLIENT.newCall(
        Request.Builder()
        .url(URL)
        .header("Authorization", "key=$serverKey")
        .header("project_id","key=$id")
        .post(RequestBody.create(MEDIA_TYPE_JSON, jsonString))
        .build()
    )
```

これで一応動きました。
サーバキーと送信者IDはFirebaseコンソール上で、トークンはRealtime Databaseに事前に登録しているものを使用しています。
ファイルごとに異なるPWでzip暗号化する作業の省人化。３人日掛かっていた作業を１秒で処理した話。【完成版】

日常業務を省力化を図っております。
一か月前に、「月初エクセル集計処理を完全自動化し、100人日掛かっていた作業を一秒で処理した話。【完成版】を書きました。→https://qiita.com/naiveprince0507/items/3e4d322f7f1c3068487a
それの第２弾となります。

＝＝＝＝＝＝＝＝＝＝＝
１．状況説明
下記の様な、顧客別に送付するPDFファイルがあったとします。
![0710.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/acb30216-863e-1f33-de5b-63948a0313b6.jpeg)
客先にメールで送信する際に、それぞれのpdfファイルに、別個のパスワードでZIP暗号化を掛けて、客先送信すると言う事はよくあると思います。

２．普通のやり方
PW自動生成ソフトやサイトを使って、PWを作成して、それを一つずつコピペして、LhaplusみたいなZIP暗号化ファイル作成ツールを使って、一つずつ暗号化ファイルを作成していく必要があります。

パスワード作成サイト→　https://www.luft.co.jp/cgi/randam.php
![0710x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/546baaa8-c9af-88fe-be05-2024ef7dc41b.jpeg)

![0710y.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1665829/2362e1d0-213c-83f8-9266-d963cde86c42.jpeg)

３．「普通のやり方」の課題
言うまでもなく、面倒くさい。
「ABC CoにはこのPWで、OPQ Coには、あっちのPW」と整理するのも面倒。
この例では、たった３つのPDFだが、実務では、数十のPDFを処理するので、3人日位は普通に掛かった。

４．省力化
Pythonで一秒で処理する。

PWを作成するPythonモジュールのpyminizipを使います。
このサイトが一番分かり易かった。
pyminizipによりzipファイルにパスワードを設定する【Python】→　https://self-development.info/pyminizip%E3%81%AB%E3%82%88%E3%82%8Azip%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B%E3%80%90python%E3%80%91/

私はWindows10環境でやりましたが、pyminizipの環境設定（Microsoft C++ Build Toolsのインストール）で少し詰まりました。
「pyminiziはMinizipのPython用Wrapper」なので、Microsoft C++ Build Toolsのインストールが必要との事。（ここは、詳しく上記記事に書いてあります。）

５．最終コード
下記になります。
まず、pyminizipでPWをpdfの数だけ作成し、その後、作成したPWを順番にPDFにアサインしてZIPファイルを作成する。
最後に、ファイル名（顧客名）とPWを紐づけたPWリストを吐き出す。

＜2021年8月6日、プログラム修正＞
インデントが一部（2か所）変だったので、修正。
また、実行後、Warningがでるので、"warnings.simplefilter("ignore")"で消した。

```Python:invoice_setup.py
import os
import string
import secrets
import pyminizip
import warnings
warnings.simplefilter("ignore")


def pass_gen(size=12):
	chars = string.ascii_uppercase + string.ascii_lowercase + string.digits
	return ''.join(secrets.choice(chars) for x in range(size))

fileExt=r".pdf"
print([_ for _ in os.listdir() if _.endswith(fileExt)])

x=[_ for _ in os.listdir() if _.endswith(fileExt)]

y=[]
for i in range(len(x)):
	z=pass_gen(10)
	print(z)
	y.append(z)
i=i+1
print(y)

for j in range(len(x)):
	pyminizip.compress(x[j], "",  "zipped_"+x[j]+".zip", y[j], 0)
	continue
j=j+1


f=open('pw_list.txt','w',encoding='UTF-8')
for j in range(len(x)):
	f.write("Name: "+x[j]+" / "+"pw: "+y[j]+"\n")
j=j+1
f.close
```

６．
実行すると、フォルダは下記の様になります。

```
C:\Users\xyz\Desktop\xxx_june\test\testx>Tree/F
フォルダー パスの一覧
ボリューム シリアル番号は 2E48-BBB4 です
C:.
    ABC_co.pdf
    invoice_setup.py
    OPQ_co.pdf
    pw_list.txt
    XYZ_co.pdf
    zipped_ABC_co.pdf.zip
    zipped_OPQ_co.pdf.zip
    zipped_XYZ_co.pdf.zip

サブフォルダーは存在しません
```
```＜pw_list.txt＞　自動作成されたPWリストの内容は下記。
Name: ABC_co.pdf / pw: w8RBAfkNHj
Name: OPQ_co.pdf / pw: 2QglGxwGPR
Name: XYZ_co.pdf / pw: emny0xWKFc
```
テキスト入力すると画面が戻る(Flutter)

<エラー内容>
TextFormFieldにテキスト入力をするとWidgetがリビルドされてしまうエラーです。

次の条件下で発生します。
①Material Page Routeで遷移
Navigator.push(context, MaterialPageRoute(builder: (context) => ExamplePage()))

②遷移先でTextFormFieldを使用(類似のWidgetは未検証)

<解決策>

まずエラーが起こっている状態(通常の状態)

```dart
class _ExamplePageState extends State<ExamplePage> {
  @override
  Widget build(BuildContext context) {
       //ここにViewとLogicを書いていく。
     return Container(child: TextFormField());
}
```

上記を下記のように記述するとエラーがなくなります。


```dart
class _ExamplePageState extends State<ExamplePage> {
  Widget _form;

  @override
  Widget build(BuildContext context) {
    if (_form == null) {
      _form = _createForm(context);
    }
    return _form;
  }
  Widget _createForm(BuildContext context) {
        //ここにViewとLogicを書いていく。
     return Container(child: TextFormField());
}
```

<原因>
わかりません。

<参考記事>
https://github.com/flutter/flutter/issues/20607
Goによる競プロライブラリ~Union-Find木~

# 内容

自身の記事である[競プロのライブラリ整理~Union-Find木~](https://qiita.com/DaikiSuyama/items/444e409423bd1b4b83d7)のPythonコードを元に、GoによってUnion-Find木を実装しました。参考になれば幸いです。

# コード

下記が実装になります。


```go
/*
n: 要素数
parent[i]: iの親となる要素
siz[i]: iを含む素集合のサイズ
group[i]j: 代表元をiとする素集合に含まれる要素の配列j
*/
type UnionFind struct {
	n      int
	parent []int
	siz    []int
	group  map[int][]int
}

/*
コンストラクタ
任意のiについて、parent[i]=i、siz[i]=1、として初期化
group[i]jは空のmapとして初期化
*/
func NewUnionFind(n int) *UnionFind {
	uf := new(UnionFind)
	uf.n = n
	uf.parent = make([]int, n)
	uf.siz = make([]int, n)
	uf.group = make(map[int][]int)
	for i := 0; i < n; i++ {
		uf.parent[i] = i
		uf.siz[i] = 1
	}
	return uf
}

/*
要素xの属する木（素集合）の根の値を取得し、インデックスを返す
同時に経路圧縮も行う
*/
func (uf *UnionFind) root(x int) int {
	if uf.parent[x] == x {
		return x
	} else {
		uf.parent[x] = uf.root(uf.parent[x])
		return uf.parent[x]
	}
}

/*
要素xと要素yを含む素集合を併合する
*/
func (uf *UnionFind) unite(x, y int) {
	rx, ry := uf.root(x), uf.root(y)
	if rx == ry {
		return
	}
	if uf.siz[rx] < uf.siz[ry] {
		rx, ry = ry, rx
	}
	uf.siz[rx] += uf.siz[ry]
	uf.parent[ry] = rx
	return
}

/*
要素xと要素yが同じ素集合に属するかを判定し、真偽値を返す
*/
func (uf *UnionFind) same(x, y int) bool {
	rx, ry := uf.root(x), uf.root(y)
	return rx == ry
}

func (uf *UnionFind) size(x int) int {
	return uf.siz[uf.root(x)]
}

/*
現在の素集合の状態に基づいてgroupを更新する
O(uf.n)なので注意
*/
func (uf *UnionFind) grouping() {
	for i := 0; i < uf.n; i++ {
		uf.root(i)
	}
	for i := 0; i < uf.n; i++ {
		uf.group[uf.parent[i]] = append(uf.group[uf.parent[i]], i)
	}
}

/*
素集合を初期化する
*/
func (uf *UnionFind) clear() {
	for i := 0; i < uf.n; i++ {
		uf.parent[i] = i
		uf.siz = make([]int, uf.n)
	}
	uf.group = make(map[int][]int)
}
```
ExcelやGoogleスプレッドシートの数式を読みやすくする試み

ある程度のベテランSEさんでも、Excelやスプレッドシートの数式を書くときは
まったく可読性を意識しないのが不思議でならないです＼(^o^)／

最近スプレッドシートの数式をいじくる時間が多く、その中で
可読性・保守性を上げようと色々試す中で思いついた手法をシェアします。

・コメントを付与する
・適切なインデント（改行・適切な空白）を入れる
・関数名にロウワーキャメルケースを適用する
・ネストしたIF関数より、IFS関数を採用する


理屈より、実例を見てもらった方が早いです。

## 例：複数選択リスト（セミコロン区切り）の形式かをチェックする数式


~~~~Apex:修正前（理解する必要はないです。）
=IF($A3<>"",
  IF($B3<>"",
      IF($C3="","ISBLANK",IF(OR(NOT(REGEXMATCH($C3,"^(りんご|ごりら|らっぱ|;)+$")),RIGHT($C,1)=";"),1,0)),
    0),
"")
~~~~

読みにくいですね。
この数式を、こんな風に書き換えてみました。

~~~~Apex:修正後1
=ifs( $A3 = "", ""            & t(n("作業日が入力されていなかったらチェック対象外"))
    , $B3 = "", 0             + n("〇〇項目がブランクの場合も、チェック対象外")
    , $C3 = "", "ISBLANK"     & t(n("チェック対象項目が未入力"))

    , or( n("複数選択リストの形式と異なる場合は1を返す（＝エラー）")
        , not(regExMatch($C3, "^(りんご|ごりら|らっぱ|;)+$"))
        , right($C3,1) = ";") + n("文末のセミコロンはNG") ,1
    , true, 0 + n("正常ケース")
)
~~~~

だいぶマシになりました。
でも、まだorから始まるメインロジックがごちゃついています。
では、こんな書き方はどうでしょう。

~~~~Apex:修正後2
=ifs( $A3 = "", ""            & t(n("作業日が入力されていなかったらチェック対象外"))
    , $B3 = "", 0             + n("〇〇項目がブランクの場合も、チェック対象外")
    , $C3 = "", "ISBLANK"     & t(n("チェック対象項目が未入力"))

    , not(regExMatch($C3, "^(りんご|ごりら|らっぱ|;)+$")), 1 + n("複数選択リストの形式と異なる")
    , right($C3, 1) = ";")                              , 1 + n("文末のセミコロンはNG") 
    , true                                              , 0 + n("正常ケース")
)
~~~~
①チェック対象外のときや正常ケースのときは、0（またはブランク）を返す
②なにかエラーがあるときは、1を返す
という作成者の意図が伝わりやすいプログラムになったかと思います。




##例2：これはどんな数式でしょう？

そうしたテクニックを踏まえた上で、ちょっとした数式を書いたのでシェアします。
何をしているか、わかりますか？？

~~~Apex
=if( countIf(A3,"*会社")                         & t(n("「法人格」項目に、'会社'が含まれる"))
    ,ifs( regExMatch(B3,"^..会社") , "前"        & t(n("◯◯会社から始まる"))
        , regExMatch(B3, "会社$")  , "後"        & t(n("～会社で終わる"))
        , true                     , "判定不能")

    , ""                                         & t(n("個人事業主の場合は処理対象外"))
)
~~~

答えは「取引先（法人・個人混在）の名前項目から、前株・後株を判定する」でした。
いかがでしょう。以下に示した、ありがち横長記述より読めるかなって気になりませんか？

~~~Apex
=IF(COUNTIF(A3,"*会社"),IF(REGEXMATCH(B3,"^..会社") , "前", IF(REGEXMATCH(B3, "会社$")  , "後", "判定不能")),"")
~~~

###さいご

「インデント」は、通常のプログラムのコーディングだけでなく、Excelなどの数式，SQL，
果ては普段のビジネスメールでも伝わりやすさ向上に効果を発揮すると思っています。
この記事を読んだ方の少しでもお役に立てれば幸いです。

_以上です。Happy Coding！_


##参考URL

[【エクセル】数式内にコメント(覚書き)を残してミス(度忘れ)を防止する方法！](https://nujonoa.com/how-to-comment-in-a-formula/) 

[ExcelのIFS関数の使い方｜複数条件を満たすかどうか判定する](https://office-hack.com/excel/ifs/)
Postman で Slack APIのメッセージ送信を試す

# はじめに
・curlコマンドの内容を`Postman`で代替する方法に詰まったので主にその備忘録です。
・この記事は[こちら(Slack APIを使用してメッセージを送信する)](https://qiita.com/kou_pg_0131/items/56dd81f2f4716ca292ef)のとてもわかりやすい記事を参考にさせていただいています。
・上記の記事の[メッセージを投稿する](https://qiita.com/kou_pg_0131/items/56dd81f2f4716ca292ef#%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%82%92%E6%8A%95%E7%A8%BF%E3%81%99%E3%82%8B)所までは同じですので割愛いたします。

# 簡略的な全体の流れ
1. Slackで新規ワークスペース（テスト環境）を作る
1. [上記の記事](https://qiita.com/kou_pg_0131/items/56dd81f2f4716ca292ef)を参考にアプリ作成・チャンネルに追加
1. 必要なパラメーターを添えてリクエストを送信(**ここがこの記事のメインです**)
1. 成功すればslackにメッセージが表示される

# Postmanでのcurlコマンドの使い方
まず`curlコマンド`のサンプルがこちら

```
$ curl -X POST 'https://slack.com/api/chat.postMessage' \
-d 'token=xoxb-xxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx' \
-d 'channel=#送信先のチャンネル名' \
-d 'text=*送りたいテキスト*'
```
これをどうやって`Postman`で使うのか分からず色々調べる。

# 結論
**Importを使うと解決できた**
以下図解
![スクリーンショット 2021-07-10 15.56.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748419/07a43f29-0a0f-c8bd-d105-bff3d4e0ffb7.png)

下記画像では`$`マークを巻き込んでしまってます。
![スクリーンショット 2021-07-10 15.58.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748419/65447cf0-45cf-6294-9721-f7507fdb25fd.png)

 
![スクリーンショット 2021-07-10 16.05.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748419/b614787f-5ac1-dfca-48b2-ccee251dfab8.png)

importができると自動でデータなどを変換してくれているので`Send`を押す。

![スクリーンショット 2021-07-10 16.19.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748419/a91dbe45-1ba6-d15e-3a58-b853476d4613.png)

![スクリーンショット 2021-07-10 16.06.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748419/b57ce578-f4cb-99cc-2ad7-3fc39801bbfd.png)

成功するとslackにメッセージが届く
![スクリーンショット 2021-07-10 16.08.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748419/c62dfad2-0b4d-060c-3bbc-a8c982d03bbd.png)

Send後のPostman
![スクリーンショット 2021-07-10 16.10.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1748419/f3ef7169-ff2c-8b2d-1a0c-28acb033946b.png)


# まとめ
既存の記事に自分なりに1つ見方を変えたり方法を変えたりするだけでも色々考えるのでいい勉強になりました。
折角なのでもう少しこのAPIを活かして何か機能をplusしてみたいと思います。
vimiumを使ってみた

#概要
　chromeでvimのような操作ができ、マウスを使わないでネットサーフィンができる・・というのを使ってみた感想とtips

#インストール等
　拡張機能でインストールするだけ

#ページ移動
　？を押すと、helpがでるので詳しくはここを見ればいいのだが、ページの推移に関しては次のような対応がある。

| 操作内容 | vimium | chrome default |
|:-:|:-:|:-:|
| ページtop| gg  | [home]  |
| 最終行  | G  | [end]  |
| スクロール下 | j  | [↓]  |
| スクロール上 | k  | [↑]  |
| スクロール頁下 | d  | [space]  |
| スクロール頁上 | u  | [shift]+[space]  |
| 履歴前  | L  | [alt]+[←]  |
| 履歴先  | H  | [alt]+[→]  |
| タブ右 | gt | [cnt]+[tab] |
| タブ左 | gT| [cnt]+[shift]+[tab] |

 つまり、vimiumに頼らなくてもだいたいデフォルトのショートカットが準備されている。

#リンクをクリック

この機能は流石に、vimiumの秀逸な機能だ。
fを押すと、下のようにクリック可能な部分に文字が修飾されこの文字を入力することでリンクをクリックすることになる。Fを最初に押すと、別タブで表示してくれる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60225/78a838b6-ef6a-862c-ef65-97ef6bf5d66a.png)

#ちょっとtips
 [esc]というのがヘルプにはないのだが、vim同様[esc]で様々な効果がリセットされる。
　例えば、googleの検索窓で入力している場合は流石に文字入力中なのでvimiumの文字を入れても効果がない。こんな場合は[esc]を入力すると検索窓からキャレットが消えてvimiumの文字を受け付けるようになる。

#使った感想
　確かに、「マウスを使わない」ことで、効率化は図れるとは思うのだが、問題は手が自然に動くようになるのか？ということである。
　タブの切り替えを自然にキーボードで入力するようになるのか？というとちょっとまだまだである。
　なんとなく、「えーっと[cntl]+[tab]だっけ」と頭のなかで考えていたりする。まあ、vimmerとしてgtをいつも使っている人は「涙がちょちょぎれる感じ」なんでしょうけど、そこまでvimmmerではないのでちょっとなあ・・という感じ

#その他の機能
　pやPで、クリップボードに入っている文字を検索を掛ける・・というのもあるんだけど、そのクリップボードにコピーするのがvやcを使ってy(ヤンク）する・・というこれまた、vimmerの常套手段なんですけど、けっこうこれはまだまだ使いこなせてない。まあ、これから徐々に・・ってとこですかねえ？
ScriptableObjectが「The associated script can not be loaded」と表示される場合

UnityのScriptable Objectで「The associated script can not be loaded」が表示された場合で、スクリプトを見ても要因がわからずはまった場合の対応

# 状況
Scriptable Objectが「The associated script can not be loaded」
以下のような対応をしても治らない
①スクリプトのエラー確認
②スクリプトファイルとクラス名は一致しているか
③使用しているアセットの中に競合するものはないか
④使用しているアセットの中でissueが報告されているものはないか

# 対応
スクリプトをReimportすると治る場合あり（原因不明）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34650/82b7cd15-d97c-fa2d-393f-cf3fed627489.png)


# 参考
https://doogms.com/%E3%80%90unity%E3%80%91scriptableobject%E3%81%8C%E3%80%8Cthe-associated-script-can-not-be-loaded%E3%80%8D%E3%81%A8%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AB%E7%A2%BA/
Unity、配置したPrefabがmesh Colliderをつけても落下してしまう場合

Unity asset storeで入手したオブジェクトを空間に配置すると、Mesh colliderをつけているのに無限落下してしまう状況にちょっとハマったのでメモ。

# 状況
以下の対応をしてもオブジェクトが落下してしまう
* mesh colliderを設定
* mesh colliderのConvexをオン

# 要因
mesh colliderの「Mesh」が未設定（複数のゲームオブジェクトでなりたっている場合、親ゲームオブジェクトのmeshが自動では入らない）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34650/96fc6ba8-7a7a-2748-031f-97975b9d5327.png)

# 対策
meshに適当なmeshを設定（完璧なmeshがない場合、子要素のどれかを設定）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/34650/021f65f9-5c48-9625-b8bb-ce75f6c330e7.png)
シリアル通信パケット用のCOBSエンコーダーを作ってみる

![SS 192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a41cd967-f549-8677-1efa-2e99bf69518d.png) COBSがふにおちたい


#やること
シリアル通信でそれなりの量のデータを短時間に送ろうとしたとき、テキストではなくバイナリで流した方が軽量快速です。
しかしArduinoの Serial.write() はバイナリデータをダーっと流すだけなので、受信側でデータの区切りを判断させるところに一工夫が必要です。
（パケットサイズが大きくてもよい場合には、改行記号で簡単に区切り判別をさせることもできます。1/1000秒単位で少し長めのデータをやりとりしたいときなどにはやはりバイナリ送信が助かります。）

COBS（Consistent Overhead Byte Stuffing）は１パケットのデータの中に0x00が1度しか出現しないようにするデータ変換方法です。
これを手元で（自分でもわかるように）実装してみます。
今回はエンコーダーを作ります。

#参考
https://qiita.com/hideakitai/items/347985528656be03b620

こちらの記事を参考にさせていただきました。とても勉強になりました。ありがとうございました。

# 使うもの
- Arduino
- Arduino IDE など


# COBSの原理
まずデータを1バイトずつ配列に格納していきます。
その際、配列の冒頭に１バイトを追加し、次に0x00が現れるまでのデータの個数をカウントして代入します。次に0x00が現れた配列番号のデータには、その次の0x00が現れるまでのカウントを代入します。これを繰り返していくことで、データに現れる0x00を全て1以上の数値に置き換えることができます。データの最後だけを0x00とし、スタートビット/ストップビットとして利用していくという仕組みです。
たとえばデータ中に一度も0x00が現れないパケットの場合、冒頭のカウンタはデータの最後尾の配列番号を示すことになります。
元のデータの前後に１バイトずつ、合計２バイトしか増えないすぐれた方式です。


# 実装
流し込みたいシリアルデータを準備します。
ここでは、[wikipediaのデータ事例](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing)が成立するかどうかを見ていきます。

なるべく規模が小さくなるように作っています。１パケットあたりのシリアルデータの長さは254バイトが上限となります。




```c++:Arduino
//1バイト型で作っているため、データ配列の最大長は254（カウントできる最大値）
uint8_t source_data[] = {11, 22, 00, 33}; //送信したいデータの配列。書き換えて動作テスト。
uint8_t cobs[sizeof(source_data) + 2]; // COBSに変換した送信データの配列（上記に２バイト追加）

void setup() {
  Serial.begin(115200);//シリアルモニター表示
  delay(500);
}

void loop() {
  //配列をCOBSの方式で処理する

  uint8_t count = 0; //次にsource_data[i]に0x00が出るまでの配列番号をカウント
  int mark = 0; //最後に0x00が出たsource_data[i]の配列番号をキープ

  for (int i = 0 ; i < sizeof(source_data) + 1; i++) {

    //現在チェックしているsource_data[i]の中身が0x00ではない場合
    if (source_data[i] != 0x00) {
      cobs[i + 1] = source_data[i]; //チェックした値をそのままcobs配列に書き込む
      count ++;//前回0x00が出たsource_data[i]の配列内のカウント値を+1
    }

    //現在チェックしているsource_data[i]の中身が0x00だった場合
    else {
      count ++;//前回0x00が出た配列のカウントを+1
      cobs[mark] = count;//前回0x00が出たcobs配列にカウント値を書き込み確定
      mark = i + 1; // 現在のcobs配列を0x00が出た配列としてキープ
      count = 0 ;//0x00が出た配列のカウントをリセット
      cobs[mark] = count; //今回0x00が出たcobs配列にカウント値を書き込む
    }
  }
  
  //末端処理
  cobs[mark] = count; //前回00が出た配列にカウント値を改めて書き込む
  cobs[sizeof(source_data) + 1] = 0; //終端に00を代入する

  //変換した結果を表示
  for (int i = 0 ; i < sizeof(source_data) + 2; i++)
  {
    Serial.print(cobs[i]); Serial.print(",");
  }
  Serial.println();
  delay(1000);
}
```

#動作確認

source_data[]の中の配列データを、Wikipediaの事例のように変更してみてください。
意図通りの結果が出力されると思います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/d3e0d9d3-3b8b-aa05-3277-42904be9e1b6.png" width = 500>


# まちがっていたら
すみません！


# つぎやること
COBSのデコーダーをつくります。

次回記事：

https://qiita.com/Ninagawa_Izumi/items/7b35d16d8f4ae7fc2fb8
Linux デバイス - lspci の出力は何が表示されているのか

`lspci` コマンド の出力について概要をまとめました。

## lspci

lspci は PCIバスとそこに接続されたデバイスの情報を表示してくれるコマンドです。

## オプションを付けない場合

`lspci` を、オプションを付けずに実行した場合は何が表示されるのでしょうか。

下は、 AWS EC2 での実行した場合の出力例です。

```
[ec2-user@sample systemd]$ lspci
00:00.0 Host bridge: Intel Corporation 440FX - 82441FX PMC [Natoma]
00:01.0 ISA bridge: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II]
00:01.3 Non-VGA unclassified device: Intel Corporation 82371AB/EB/MB PIIX4 ACPI (rev 08)
00:03.0 VGA compatible controller: Amazon.com, Inc. Device 1111
00:04.0 Non-Volatile memory controller: Amazon.com, Inc. Device 8061
00:05.0 Ethernet controller: Amazon.com, Inc. Elastic Network Adapter (ENA)
```

このうちの Non-VGA unclassified device の行を例にして、何が表示されているのか見ていきましょう。


### バス・デバイス・ファンクション

一番左の数値は、バス番号、デバイス番号、ファンクション番号を表します。

#### バス番号

`:`の左にある数値です。
16真数で、 範囲は 0-ff です。

3行目では 00 となっています。

#### デバイス番号

`:` と `.` の間にある数値です。
16真数で、 範囲は 0-1f です。

3行目では 01 となっています。

#### ファンクション番号

`.` の右にある数値です。
範囲は 0-7 です。

3行目では 3 です。

##### ファンクションって何？

ファンクションというのは、PCIデバイスに搭載される機能です。
ひとつのPCIデバイスには2つ以上のファンクションが搭載されることがあります。

たとえばネットワークカードには、2つの NIC がある場合があります。
そういうときにひとつめを ファンクション 0、 ふたつめを ファンクション 1　とします (Viscarola, 2009)。

### デバイスクラス

デバイスクラスというのは、どんなデバイスなのか(オーディオデバイスなのか、ネットワークデバイスなのか)、デバイスの種類を表すものです。


1行目から6行目まで:

* Host bridge
* ISA bridge
* Non-VGA unclassified device
* VGA compatible controller
* Non-Volatile memory controller
* Ethernet controller
* Elastic Network Adapter (ENA)

### ベンダ

1行目から6行目までに2社含まれています。

* Intel Corporation
* Amazon.com, Inc.

### 名前

* 440FX - 82441FX PMC [Natoma]
* 82371SB PIIX3 ISA [Natoma/Triton II]
* 82371AB/EB/MB PIIX4 ACPI
* Device 1111
* Device 8061
 
### リビジョン

3行目ではリビジョンも書かれています。
その値は 08 です。 16進数なので、もし 11 となっていたら10進数で 17 です。

## もうちょっと詳しく表示してみる

PCIデバイスは、device's configuration space と呼ばれるレジスタを持っており、デバイスID、ベンダID、デバイスクラスといった情報を格納しています。
全て数値ですが、それをOSが読みやすい形に変換して表示します。

ベンダID は PCI-SIG (PCI Special Interest Group) と呼ばれる企業団体が各企業に割り当てます。
デバイスID は PCI-SIG 内 のベンダが割り当てます。

それらのIDは `lspci` コマンド に `-nn` オプションを付けると表示されます。

```
[ec2-user@sample systemd]$ lspci -nn
00:00.0 Host bridge [0600]: Intel Corporation 440FX - 82441FX PMC [Natoma] [8086:1237]
00:01.0 ISA bridge [0601]: Intel Corporation 82371SB PIIX3 ISA [Natoma/Triton II] [8086:7000]
00:01.3 Non-VGA unclassified device [0000]: Intel Corporation 82371AB/EB/MB PIIX4 ACPI [8086:7113] (rev 08)
00:03.0 VGA compatible controller [0300]: Amazon.com, Inc. Device [1d0f:1111]
00:04.0 Non-Volatile memory controller [0108]: Amazon.com, Inc. Device [1d0f:8061]
00:05.0 Ethernet controller [0200]: Amazon.com, Inc. Elastic Network Adapter (ENA) [1d0f:ec20]
```

### デバイスクラスコード

デバイスクラスの右にある、 [ ] で囲まれた数値です。 16進数で表示されます。

### ベンダID・デバイスID

右の方に [ ] の中に `:` で区切って2つの数字が表示されています。
左がベンダID、右がデバイスIDです。
いずれも16進数です。

インテルは 8086, Amazon.com, Inc. は 1d0f になっていますね。

## References

* Viscarola, P. (2009). _PCI Function Number_. OSR. https://community.osr.com/discussion/155585