OmniAICreator/Qiita-1.07M huggingface dataset:
ネットワーク解析 〜中心性紹介〜

# はじめに

世の中には多くのネットワーク構造が溢れています．

- Twitter，InstagramなどのSNSデータ
- WWW
- 交通道路

ネットワーク構造を理解することは世の中の構造を理解することにつながります．

かのGoogleもWWWのネットワーク構造に着目し，重要なホームページを評価するための指標としてPageRankを利用することでここまでの富を成し，世の中を支配するに至りました．

そこで今回はネットワーク解析の中心性について有名な指標をいくつか紹介したいと思います．

# 中心性

中心性の例として仮想のSNSによる相互フォローを考えます．
ノードはユーザを表し，リンクはそれぞれのユーザがお互いに相互フォローの場合にリンクが貼られます．

![IMG_0002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/59969e56-1f01-78c4-5332-22789b543df8.png)

$n$はノードの数を，$d_{（i, j)}$はノード$i$とノード$j$の最短経路を，$k_i$はノードiの次数(ノードに繋がれているリンクの数)を表します．

## 次数中心性(Degree Centrality)

次数中心性は「ノードに接続されるリンクの数」になります．

```math
DegreeCentrality_i = \frac{k_i}{n-1}
```

上記のグラフでは $B=4$でありになり，単純に相互フォローの人間が多い人が高くなります．
計算時間はリンクを数えるだけなのでそこまで必要なくすぐに計算が可能です．


## 近接中心性(Closeness Centrality)

近接中心性は「全体のノードとの最短経路がどのくらい近いか」の指標になります．

```math
ClosenessCentrality_i = \frac{n-1}{\Sigma_{j=1}^{n-1}d_{(i, j)}}
```

対象のノードから全ノードへの最短経路の和の逆数となります．
SNSの例だと「コミュニティ内の全員と最短で知り合える人」となり，$B=1$となり最大となります．

## 媒介中心性(Betweenness Centrality)

媒介中心性は「ネットワーク全体の最短経路の中心」となります．

```math
BetweennessCentrality_i = \sum_{j\neq k \neq i}\frac{d_{(j,k)(i)}}{d_{(j,k)}}
```

$d_{(j, k)(i)}$は$j$と$k$を通る最短経路のうち$i$を通る最短経路の数を表し，$d_{(j,k)}$は$j$と$k$の最短経路になります．
これにより，媒介中心性とは全ノードの組み合わせのうち対象のノードを通る経路の割合を表します．

SNSの例だと「コミュニティの人と人の繋がりの中心人物」となり，Bが最大となります．

## その他の中心性

その他の中心性として

- 固有ベクトル中心性
- 媒介中心性
- 情報中心性

などが挙げられます．

かなり奥が深く場合により使用する値が変わるため調べてみると面白いです．

# 終わりに

中心性の主要なもの3つをまとめましたが，ネットワーク解析における指標にはさまざまなものがあり，場合によって使用する場面が変わるため，色々な指標を知っているとものを考える角度が変わるかもしれません．

また，近年はネットワークにニューラルネットを適応させてGraph Convolutional Networks(GCN)も注目を集めているため，GCN周りのサーベイをしてみると新たなる分析ができるかもしれません．

https://qiita.com/TsuchiyaYutaro/items/81bee506534eab1956c3

# 参考

http://networksciencebook.com/
初めてのpython ~print()

#はじめに
この記事の著者はPC初心者です。
そんな私がpythonを学んでみようかと思ったので、勉強も兼ねて、記録を残そうかと思います。初投稿となるこの記事の内容は基本中の基本である、print関数について。（今更?）
#開発環境
・VSCode
・Python 3.9.2

#print関数
print関数の公式ドキュメントURL
https://docs.python.org/ja/3/library/functions.html#print
私には書かれていることが全く理解できません…


#基本的な使い方

```python:コード
print("Hello World")
print(1234)
print((1234 + 5678) / (5 - 2))
```
```:出力結果
Hello World
1234
2304.0
```
()の中に文字や数値を入力すると、入力されたモノが出力される。
計算式を入力すれば、電卓としても使用できる。

#連結
```python:コード
a = "Hello"
b = " World"
c = 12345
print(a + b)
print(a, c)
```
```:出力結果
Hello World
Hello 12345
```
文字列同士の連結ならば、「+」or「,」を間に入力する。
文字列と数値の連結ならば、「,」を間に入力する。「+」は使用できない。
ちなみに、文字列と数値の連結で「+」を使用すると…

```:出力結果
TypeError: can only concatenate str (not "int") to str
```

と、表示されます。



#区切り文字の指定: sep
```python:コード
a = "HelloWorld"
b = 1234
print(a, b, sep=' 0あ ')
```
```:出力結果
HelloWorld 0あ 1234
```
表示させたい文字列, 数値の後に「,sep='〇〇'」を書く。
'〇〇'の中に文字や数値を入力すると、その文字で区切られる。
区切りたい場所は,(コンマ)で指定する。

#終わりの文字の指定: end
```python:コード
a = "Qitta"
print(a, end = "です")
```
```:出力結果
Qittaです
```
表示させたい文字列,数値の後に「,end="〇〇"」を書く。
'〇〇'に文字や数値を入力すると、出力される文字列,数値の後ろに〇〇の中身が連結される。

#改行: \n
```python:コード
a = "Qitta"
b = "print"
print(a, b, sep = "\n")
print(a,"\nで記事を書いた")
```
```:出力結果
Qitta
print
Qitta
で記事を書いた
```
・sepの使用
・""の中に「\n」を入れる。
連結された文字列の中に「\n」が存在すると、改行される。
Windows上でpyton インストーラーを作成してはまった事。

Windows 10 pro
python3.9 
anaconda3


cx_Freeze’sでインストーラーを作成してはまった事。

setup.pyを作成して、ビルドしてインストーラーを作りました。
![dsafsafdsa.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/928107/f81f417a-e6db-30b3-df1f-fdbe94477aab.jpeg)
 cx_Freeze はpython３．10でインストールしてもエラーになるので、python3.9でインストールできました。
ビルドも正常にできたのですが、アプリをパソコンにインストールしても問題なくインストールは完了しました。
動作確認の為、アプリを起動すると上の画像のようにエラーが発生。

試行錯誤したのですが、python3.10を削除しました。
勉強中、python3.10に関連するエラーが多い。
python3.9が安定していました。
なので削除してpython3.9において


````
python setup.py build
````

再度ビルドをを実行しました。
今度は違うエラー


````
Python cx_Freeze error "No module named 'cx_Freeze.util'
````
検索したら以下の情報を入手
[Python cx_Freeze error "No module named 'cx_Freeze.util'"]("https://stackoverflow.com/questions/40857091/python-cx-freeze-error-no-module-named-cx-freeze-util")


````
 python -m pip install cx_Freeze --upgrade
````


を実行したら正常にビルド完了。

```
 python setup.py bdist_msi
```


を実行してインストーラーを作成。
インストールして動作確認も問題なく完了しました。
[Android]Installed Build Tools revision 31.0.0 is corruptedエラーの対策


概要
---

以下のエラーが出た時の対応策

```
Installed Build Tools revision 31.0.0 is corrupted. Remove and install again using the SDK Manager.
```

2022年3月31日追記
Android T(Tiramisu)に向けてbuildToolsVersionを挙げた際にも発生することがされ、
同様の対応で回避できることを確認しました。

現象
---

このエラーはGradleの設定が以下の時にBuildすることで出るようです。

```gradle
    compileSdkVersion 31
    buildToolsVersion "31.0.0"

    defaultConfig {
        minSdkVersion 30
        targetSdkVersion 31
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
```

原因
---
build-toolsにdx.bat, dx.jarが存在していないことによりエラーが出ています。

対策
---
以下の2つの対策を行うことでBuildを通すことができます。

1.以下を開く
```
C:\Users\<ユーザ名>\AppData\Local\Android\sdk\build-tools\31.0.0
```

2.d8.batをdx.batにリネーム

3.以下を開く

```
C:\Users\<ユーザ名>\AppData\Local\Android\sdk\build-tools\31.0.0\lib
```
4.d8.jarをdx.jarにリネーム


参考
---
[Android Studio error "Installed Build Tools revision 31.0.0 is corrupted"](https://stackoverflow.com/questions/68387270/android-studio-error-installed-build-tools-revision-31-0-0-is-corrupted)
Crystalで文字列のmd5sumを求める

Crystal1.2.2の公式ドキュメントを見ると、

https://crystal-lang.org/api/1.2.2/Digest/MD5.html

こんな感じで書いてあってどうすればよいかよくわからない。

`OpenSSL::MD5` とかもあるし、さらに古いドキュメントだと `Crypto::MD5` みたいのもあったりする。しかし、実際には、普通に `hexdigest` メソッドが使えるので、下記のようにするだけでいい。

```crystal
require "digest/md5"

p Digest::MD5.hexdigest("hoge")
# => "a4b1b42ffe743732a437b6c1e2a16106"
```

この記事は以上です。
クラス、インスタンス、オブジェクト、メソッドについてのまとめ

今更ながら、Rubyの基本知識についてまとめてみる。  

#### クラスとインスタンス
Rubyの参考書でよく出てくる、「〇〇クラスのインスタンス」という表現について。
##### クラス
単に「種類」という程度に考えておけば問題ない。
Intergerクラスなら「整数という種類」。
「このオブジェクトはどのクラスのオブジェクトか」という問いは、
「このオブジェクトは整数？小数？文字列？それとも…」という意味。

##### インスタンス
〇〇の一種、というニュアンスに近い。

なので、例えば「Intergerクラスのインスタンス」は「整数の一種」という意味になる。


#### クラスとメソッド
クラスによって使えるメソッドが決まっているが、
一部、どのクラスに対しても使えるメソッドもある。

```Ruby:
to_s    #文字列以外のクラスを文字列に変換する
class   #そのオブジェクトのクラスが何であるかを表示する
```

これは上記のメソッドが、全てのクラスの親クラス（スーパークラス）である、
Objectクラスのインスタンスメソッドであるため。

インスタンスメソッドというのは、
クラスあるいはモジュールをレシーバとするメソッドを「クラスメソッド」と呼ぶのに対し、
定数・変数といったインスタンスをレシーバとするメソッドのこと。
詳しくは[こちら](https://docs.ruby-lang.org/ja/latest/doc/glossary.html)を参照。


#### オブジェクト及びクラスの親子関係
superclassメソッドを使うと、対象オブジェクトのクラスのスーパークラスを確認できる。

```Ruby:
p 2.class.superclass    #=> Numeric
p 2.class.superclass.superclass    #=> Object
p 2.class.superclass.superclass.superclass    #=> BasicObject
```
一番上のクラスがBasicObjectで、それ以上のクラスはないので、
superclassメソッドで見ようとしてもnilが返ってくる。

また、スーパークラスで使えるメソッドは、
サブクラスのオブジェクトに対しても使えるという特徴がある。
上記の例で言えば、2はIntergerクラスのインスタンスなので、
Interger, Numeric, Object, BasicObjectのクラスのメソッドが使える、ということ。


#### リテラル
Rubyのプログラム中に直接記述できる値のこと。
通常、インスタンスの生成には

```Ruby:
クラス名.new(引数)
```

と記述する必要があるが、リテラルが設定されている値の場合は単に

```Ruby:
"値"
```

と記述するだけでインスタンスが生成される。
例えば、文字列オブジェクトを定義する際は

```Ruby:
str = String.new("Hello world!")
```
という風に記述する所を、

```Ruby:
str = "Hello world!"
```

とだけ書けばよい。

尚、数値（Integer、Floatなど）、真偽値（True、False）、シンボル（Symbol）、Nilクラスは
そもそもnewでインスタンスを作れないようにしてある。


#### レシーバとメソッド
メソッドは基本的に以下の形式で使用する。

```Ruby:
[オブジェクト].[メソッド名]
```
このオブジェクト側を「レシーバ」と呼ぶ。
レシーバとなったオブジェクトは呼び出されたメソッドが自身に使えるか否かを確認し、
可能なら実行、不可能ならエラーを返す。

putsやprintのように、レシーバを必要としないメソッドも存在するが、
実はプログラム実行時に「main」というObjectクラスのインスタンスが密かに作られており、
これをレシーバとすることで実行している。
Laravelのnullチェック使い分け（随時更新）

## Request
以下がある。

- isset()
- is_null()
- empty()

※PHPのネイティブメソッド
各メソッドの違いは[こちら](https://qiita.com/xQIEBo4zFWKZ0ig/items/a69ec15aa1697b13d666)

### ちなみに ： Requestのnull挙動
- そもそも対象のnameが存在しない時
nullになる

- nameは存在するが、valueが空の時
これもnullになる

## Collection
以下がある。

- isEmpty()
- isNotEmpty()

※Laravelのコレクションメソッド

## 参考文献
https://readouble.com/laravel/6.x/ja/collections.html
Ibexa DXP と旧 eZ Publish / eZ Platform との違い

eZ Platform が Ibexa DXP に製品名が大きく変更されましたが、旧来の eZ Publish および eZ Publish Platform を含め、どのような違いがあるのかを整理します。

### Ibexa DXP
**Ibexa DXP** は **eZ Publish** および **eZ Platform** の後継で、基本的には eZ Platform のブランド名の変更以外に機能的に大きな違いはありません。

### eZ Platform
eZ Platform は eZ Publish 5.x まであったレガシーカーネルを除去し、純粋な Symfony フルスタックアプリケーションになりました。

eZ Platform 1.13.x から 2.x の場合、 eZ Publish 5.x の LegacyBundle が外部化された [Legacy Bridge](https://github.com/ezsystems/LegacyBridge) を利用することで eZ Publish 5.x と同じような形で旧来の eZ Publish の資産を一時的に流用することが可能です。 [^LegacyBridge]

[^LegacyBridge]: <q cite="https://github.com/ezsystems/LegacyBridge/blob/master/README.md">It is meant to be installed as an addition to eZ Platform 1.13.x - 2.x installs when you need legacy for migration.</q> - <cite>[LegacyBridge/README.md at master · ezsystems/LegacyBridge · GitHub](https://github.com/ezsystems/LegacyBridge/blob/master/README.md)</cite>



### eZ Publish Platform
**eZ Publish Platform** は前回の eZ Publish から eZ Platform への製品名変更時の過渡期の呼称で、実質的には **eZ Publish 5.x** のことを指します。

eZ Publish 5.x はデュアルカーネルを採用し、 eZ Publish 4.x 以前のレガシーカーネルと、新しく Symfony ベースで開発された新カーネルのどちらも同梱しています。

### eZ Publish
eZ Publish は eZ Systems 社によって開発された当初の CMS の名称で、 eZ Platform に製品名を変更されて以降は Legacy (レガシー) と呼ばれています。

現在の Ibexa DXP でも、用語自体は一部変更になっているものの、当初の eZ Publish から基本的な CMS としての仕様や概念は大きくは変わっていません。
PHPのnullチェック使い分け

## nullのみチェック
### isset
- nullの時だけfalse
- 空文字、空配列はtrueになる


### is_null
- nullの時だけtrue
- 空文字、空配列の時はfalse


## 全チェック
### empty
- null、空文字、空配列すべてtrueになる


## 参考文献
https://qiita.com/shinichi-takii/items/00aed26f96cf6bb3fe62
MacのPHPを8.1にバージョンアップする

Macのローカル環境をPHP8.1にバージョンアップしたい。
phpenvなどでバージョンの切り替えは必要なく、ただただプリインストールされているPHPをバージョンアップする。

## 現環境

```shell-session
$ php -v                 
PHP 7.4.27 (cli) (built: Dec 16 2021 18:14:21) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Zend OPcache v7.4.27, Copyright (c), by Zend Technologies

$ which php  
/usr/local/opt/php@7.4/bin/php
```

## PHPをアップグレードする

```shell-session
$ brew upgrade php
```

```shell-session
$ ls -al /usr/local/opt/php@8.1
$ /usr/local/opt/php@8.1/bin/php -v
PHP 8.1.1 (cli) (built: Dec 17 2021 23:49:52) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.1, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.1, Copyright (c), by Zend Technologies
```

`/usr/local/opt/php@8.1/bin/php` phpのバージョンが8.1がインストールされていることを確認しました。

## パスをシェル設定ファイルに追記する。

毎回絶対パスを入力するのは手間なのでパスに追加します。
`~/.zshrc` 等のシェル設定ファイルにパスを追記する(古いPHPのパスがあれば削除する)

```~/.zshrc
export PATH="/usr/local/opt/php@8.1/bin:$PATH"
export PATH="/usr/local/opt/php@8.1/sbin:$PATH"
```

下記のコマンドで設定ファイルを読み直すか、ターミナルを再起動すれば反映されます。

```shell-session
$ . ~/.zshrc
```

phpのバージョンが8.1に切り替わったことが確認できればok

```shell-session
$ php -v
PHP 8.1.1 (cli) (built: Dec 17 2021 23:49:52) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.1, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.1, Copyright (c), by Zend Technologies
```

## VSCode: PHP Intelephense拡張機能を使ってる場合

Intelephense > Environment: PHP Version の設定を合わせる。

![ScreenShot 2021-12-31 17.39.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52879/600a3bba-9f41-8b42-9a43-fc4ff1723fb0.png)
VLANコマンド


参考　https://www.infraexpert.com/study/vlanz10.html

#VLANの作成とVLAN名の変更
(config)#

```
vlan [vlan番号]
```

(config-vlan)#

```
name [vlan名]
```

#accessポート設定
(config-if)#

```
switchport mode access
```
```
switchport access vlan [vlan番号]
```


#trunkポート設定
(config-if)#

```
switchport mode trunk
```
```
switchport trunk encapsulation [ dot1q | isl ]
```
↑このコマンドが通らないときは、dot1qにしか対応していない可能性がある。


#allowed VLAN設定
(config-if)#

```
switchport trunk allowed vlan [vlan番号]
```



#ネイティブVLAN設定
(config-if)#

```
switchport trunk native vlan [vlan番号]
```




#管理VLAN設定
(config)#

```
interface vlan [vlan番号]
```

```
ip address [IPアドレス] [サブネットマスク]
no shutdown
```



#VLANの削除

`#

```
delete flash:vlan.dat
```

```
reload
```

#コピペ用

```
#VLANの作成とVLAN名の変更
(config)#
vlan [vlan番号]
(config-vlan)#
name [vlan名]


#accessポート設定
(config-if)#
switchport mode access
switchport access vlan [vlan番号]


#trunkポート設定
(config-if)#
switchport mode trunk
switchport trunk encapsulation [ dot1q | isl ]
↑このコマンドが通らないときは、dot1qにしか対応していない可能性がある。


#allowed VLAN設定
(config-if)#
switchport trunk allowed vlan [vlan番号]


#ネイティブVLAN設定
(config-if)#
switchport trunk native vlan [vlan番号]


#管理VLAN設定
(config)#
interface vlan [vlan番号]
ip address [IPアドレス] [サブネットマスク]
no shutdown


#VLANの削除
#
delete flash:vlan.dat
reload
```
メモ：R上のデータをローカルに保存する

#やりたいこと
複数のターミナルでRを実行しマルチスレッド化しており，それぞれの結果を一つのプロセスで扱いたい状況になった．
そのため，R言語でデータのみを保存して別環境で読み込みたい．
snowパッケージなどの並列化パッケージを使えればそんなことしなくてもいいかもしれないが...

```R
###別環境で読み込むデータ
tmp <- "Hello"

###データを保存する
save(tmp,file = "tmp.rda")

###データを読み込む
load("tmp.rda")

tmp #"Hello"
```
注意：`save()`関数でデータを読み込む際に変数名とファイル名は合わせるようにする．

```R
tmp <- "Hello"
save(tmp,file = "data.rda")

load("data.rda")
data #"Hello"と出力されない
```
Ibexa DXP のシステム要件

**Ibexa DXP** のサーバーセットアップにおける**システム要件**について、以下の公式ドキュメントを参考に確認します。

[Requirements - Developer Documentation](https://doc.ibexa.co/en/latest/getting_started/requirements/)

#### 最小セットアップ
最小セットアップには、LAMP 環境 (Linux、Apache/Nginx、MySQL/MariaDB/PostgreSQL、PHP) に加えて Node.js と yarn が必要となります。

#### 本番環境構築
本番環境のセットアップでは、Varnish/Fastly、Redis/Memcached、NFS/EFS/S3、Solr/Elasticsearch を[クラスタリングして使用](https://doc.ibexa.co/en/latest/guide/clustering/)することが推奨されます。

#### オペレーティングシステム
* Debian 10.x "Buster"
* Ubuntu 20.04 "Focal Fossa"
* RHEL / CentOS 8.1 以上

#### Web サーバー
* Nginx 1.18
* Apache 2.4
    * 必須モジュール
        * mod_rewrite
        * mod_env
    * 推奨モジュール
        * mod_setenvif
        * mod_expires
        * mod_mpm_event

#### データベース
* MariaDB 10.3, 10.4
* MySQL 8.0
* PostgreSQL 10 以上

#### PHP
* 8.1
* 8.0
* 7.4

#### PHP パッケージ
* php-cli
* php-fpm
* php-mysql (php-mysqlnd) または php-pgsql
* php-xml
* php-mbstring
* php-json
* php-process (on RHEL/CentOS)
* php-intl
* php-curl
* php-pear (optional, provides pecl)
* php-gd または php-imagick (via pecl on RHEL/CentOS)

#### クラスター PHP パッケージ
* php-redis または php-memcached

#### 検索
* Solr 7.7 LTS または Solr 8
* Elasticsearch 7.7 (Oracle Java/Open JDK 8 以上を使用)

#### グラフィックハンドラー
* GraphicsMagick
* ImageMagick
* GD

PNG、SVG、GIF、WEBPファイルをイメージエディターで編集する場合、オプションで使用できます。
* JpegOptim
* Optipng
* Pngquant 2
* SVGO 1
* Gifsicle
* cwebp

#### クラスタリング
* Linux NFS または S3/EFS (for IO, aka binary files stored in content repository, not supported with legacy)
* Redis 4.0 以上, 5.0 以上 (separate instances for session and cache, both using a volatile-* eviction policy, session instance configured for persistence) または Memcached 1.5 以上
* Varnish 6.0 LTS with varnish-modules または Fastly using the bundle provided with Ibexa Experience (for HttpCache)

#### ファイルシステム
* Linux ext4 / XFS

#### パッケージマネージャー
* Composer: recent 2.1 version

#### アセットマネージャー
* Node.js 14
* yarn 1.15.2 以上

#### ブラウザー
Ibexa DXP は、最新の標準規格に対応したウェブブラウザで、ウェブに適した画面解像度で、あらゆるデバイスで動作するように開発されています。ただし、編集および管理用ユーザーインターフェイスでは、最低でも1366×768の画面解像度、デスクトップまたはタブレット端末、および以下に示す推奨/サポートされるブラウザが必要です。

* Mozilla® Firefox® 最新安定版 (推奨)
* Google Chrome™ 最新安定版 (推奨)
* Microsoft® Edge® や Opera® などの Chromium™ ベースのブラウザ, 最新安定版 (デスクトップおよびタブレット)
* Apple® Safari® 最新安定版 (デスクトップおよびタブレット)
地理空間情報の運搬活性示数

政府の業務見直しの文脈でも、運搬活性示数の概念が使われます。

地理空間情報に当てはめてみると、このような感じではないかと思いました。

- 活性示数0: 個別のレイヤまたはレコード（バラ）
- 活性示数1: データパッケージ（利用の便のためにまとめられている）
- 活性示数2: カタログサイト（サイトの上に置いてある）
- 活性示数3: ウェブ地図（実際に利用されている）

[里親ジオデータ](https://github.com/optgeo)は、活性示数を1から3、または2から3に上げる作業と言えるかもしれません。
本格的にプログラミングの勉強を始めた2021年を振り返る

# はじめに
2021年の振り返りをまとめます。
今年からプログラミングを本格的に始めた初学者が取り組んできたことや良かった点、反省点などをまとめました。誰かの参考になれば幸いです。

※記憶違いがあるかもしれませんが、ご了承ください

# 2021年の振り返り
1. 各月の振り返り   
※ただし、プログラミング関連のもののみとする
1. 全体を通しての振り返り

## 1．各月の振り返り

### 3月
- この時期まではプログラミングは軽く触れた程度
    - 個人的にpaizaでDランクの問題を解いてはいた（C#）
        - プログラミングに興味はずっとあった
        - 基礎的な問題しか解けなかった
    - 何か制作物を作った経験は一切無し
    - （正直プログラミングに苦手意識を持っていました…）
- 将来を考えるにあたり、しっかりと1から自分で勉強しようと決意し、3月をもってアルバイトを辞めた
    - そんな中、大学からのメールでトレーニングプログラムの存在を知り、応募
        - この時初めてコーディングテストを受験
        - （完答出来なくて落ちたと思ってました）

### 4月

- トレーニングプログラムに合格
    - ここから本格的にプログラミングの勉強を開始
    - 期間は3週間程度
- 基本情報技術者試験に申し込み：4月20日(火)
    - 午前試験：5月9日(日)
    - 午後試験：6月17日(木)
    - （トレーニングプログラムと並行して試験勉強しており、結構大変でした）


### 5月

- トレーニングプログラム終了
    - KotlinとPythonの基礎を学習
        - Android Studioがインストール出来ず、PC買い替え
    - AtCoderの演習に力を入れる（Python）
    - 周りのレベル感に圧倒される
        - 現実を知り、焦る
        - （なぜ自分がここにいるのか、なぜ合格出来たのかとても不思議でした）
    - 「ハッカソン」の存在を初めて知る
        - 調べたところ、6月に開催される初心者歓迎のハッカソンがあったので参加申し込み
        - （ここはかなり勢いで行動。ちゃんと作れるのか不安しかなかったですが、何事もチャレンジあるのみです！！）


### 6月

- 初めてハッカソンに参加
    - 6月に入りハッカソンに向けてHTML・CSSの学習を開始
    - Djangoを上手く扱えず、悔しさが残る結果に
- 人は頑張りすぎると体調を崩すことを実感


### 7月

- 個人開発に力を入れる
    - 本で学んだじゃんけんアプリを改良（Kotlin）
    - クソゲーだったが、楽しんでもらえた
- 基本情報技術者試験に合格
    - 学習期間は約2ヶ月程度
- AtCoder入茶


### 8月

- 個人開発に力を入れる
    - Webアプリの開発を進める（Django）
- 2名での開発をスタート
    - Flutterを学び始める


### 9月

- 個人開発に力を入れる
    - Webアプリを作成・公開（Django）
    - Androidアプリを作成・公開（Kotlin）
- 2回目のハッカソン参加
    - 最優秀賞受賞


### 10月

- 3回目のハッカソン参加
    - ブロックで2位
    - 本線に進めることに
- 初めて逆求人イベントに参加
    - 企業側からのフィードバックで自信を無くす
    - 1つのことを極める方が良かったのだとここで気付く


### 11月

- 4回目のハッカソン参加
    - 全80組中の16組まで残り、本線出場
    - 結果は残せず
    - このハッカソン後、チームが解散
        - チーム開発の難しさを実感
        - （ある意味貴重な体験が出来たので良かったと思います）
- 5回目のハッカソン参加
    - 企業の2日間のハッカソン
    - 初めて友人以外の人とチームを組んで開発（4名）
    - 最優秀賞受賞
- 機械学習のトレーニングプログラムに参加（1ヶ月間）
    - Flaskで画像認識を使ったシンプルなWebアプリ作成


### 12月

- 逆求人イベントに参加（2つ）
    - どちらも事前審査を通過して参加
    - 自分はまだまだ未熟であることを改めて痛感
- 個人開発に力を入れる
    - Qiitaで積極的に投稿
    - Flutterをメインに学習


## 2．全体を通しての振り返り

### やったこと（5月頃～）

- 資格取得
    - 基本情報技術者試験（約2ヶ月）
- 個人開発
    - webアプリ作成・公開
    - Androidアプリ作成・公開
- ハッカソン
    - 計5回参加
    - チーム開発を経験
- 逆求人イベント
    - 計3回参加


### 良かった点

- 少しでも興味を持ったら即行動した点
    - 自分の性格が発揮されたなと思います(笑)「迷ったらやる！！やれることは全部やってみる！！！」がモットーです
    - 密度の濃い期間でした
- プログラミングの楽しさを実感出来た点
    - プログラミングへの苦手意識が消えました
    - ものづくりってたのしー！！！


### 反省点

- 様々なことに手を出すのではなく、1つの技術・分野に特化すべきだった点
    - 自分の認識が誤っていたことに気付くのが遅すぎた。
        - 「広く浅く」よりも「深さ」が重要でした
    - 「学生の技術力」や「新卒に求める技術レベル」が想像以上に高い。即戦力として活躍できるだけの技術力が必要。
        - 自分の周りにはIT志望が全くいないので、全然知りませんでした…
        - 今大学1・2年で時間があるのならば、長期インターンを強く勧めます
- スケジュールを詰めすぎた点
    - 人は無理をすると体調を崩すので、ほどほどにしましょう


# おわりに
来年も積極的に頑張っていこうと思います！！

ここまで読んでいただき、ありがとうございました。
何かありましたらコメントをお願いします。
VmwareのゲストOSがホストに接続できなくなった現象

定期的に、VmwareのゲストOSがホストに接続できなくなる現象は発生し、解消方法の調査。

以下の記事を参考にさせていただきました。
https://tech.pjin.jp/blog/2017/02/04/cannot-connect-network-in-the-virtual-machine/

ネットワークカードのプロパティを開いて、経由して欲しいNICのみ「VMware Bridge Protcol」のチェックを付けると良いとのこと。

そのため、経由してほしくないネットワークの「VMware Bridge Protcol」を以下の画像のように

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365942/c051a082-dce1-2708-2e4a-4297d8833679.png)

全て外したところ解消。
【PHP】if文で「isset()」を使うより「??」を使うべき理由がコレ

以前ちょっとだけPHPのチームに所属していた時に、タイトルの通り、__ある変数に値が入っていた場合にのみ、その後の処理を行う__ようにコードを書こうとしていました。

なんてことない処理なのですが、自分が思いつくままに書いたコードはこんな感じでした。

```php
if (isset($someVar)) {
    echo("Uno");
}
```

そして、そのままプルリクエストを出したのですが、
レビュアーの先輩から「こんな書き方で動かないかな？」というコメントと共にこんなコードを送られました。

```php
if ($someVar ?? "") {
    echo("Uno");
}
```

それまでPythonしか触ってこなかったので、「ダブルはてな？なにこれ？」となりました笑

この「??」の働きとしては、ざっくり言うと__「??」の前にある変数に値が無い場合には、「??」の後ろにある変数の値に置換する__というものになります。

基本的な使いかたについては[こちらの記事](https://tektektech.com/php-double-question/)を参考にしていいただくと良いかと思います。

ただ、自分はなぜ`if ($someVar ?? "")`という条件分岐が機能しているのかが当時よく分からなかった上に、
`isset()`がダメな理由もピンと来ていなかったので、
自分なりにググったり、コードをいろいろ書いてみて理解を試みました。

結果的にそれなりに理屈が分かるようになったので、
今回の記事にはその中で調べたことをまとめておこうと思います！

# `isset()`を使わない理由

この理由自体はシンプルなものでした。

PHPにおいて値が入っているかどうかを調べためには、
`isset()`の他に、`empty()`、`is_null()`が使われることが多いようなのですが、
コード全体で、これらが混ざり合ってしまい、可読性が下がるのを避けるためとのことでした。

加えて、値が入っているかの判定を`??`に揃えることで、
チェックしたい変数に値が入っていなかったときに代入したい値があれば、そのまま代入することも可能なので、
この`??`を使うようにチーム全体で統一するようにしていたみたいです。



# `if ($someVar ?? "")`がどう機能しているのか

そして本題なのですが、
自分は`if ($someVar ?? "")`がどう機能しているかが全く分かりませんでした。

もう少し具体的に書くと、
__`if ("")`（←からの文字列）__という形でコードを見たことがなく、どんな挙動になるのかが見当が付きませんでした。

そこで自分でいろいろと実験をしてみました。

まずは下記のコード。

```php
$someVar = null;
echo($someVar ?? "Uno");

if ($someVar ?? "Uno") {
    echo("Dos");
}
```

1行目で`$someVar`という変数にnullを設定
2行目で`$someVar ?? "Uno"`を出力することで、後の4行目のif文に渡るデータを確認
4行目の`$someVar ?? "Uno"`の結果、5行目の処理が走るかを確認

結果としては、`UnoDos`という文字列が出力されました。

つまり、4行目では`if("Uno")`がチェックされ、
Trueが返ってきていたようです。

なぜifの中に文字列が入ることでifの中の処理が走るのか全く理解できず小一時間ほどググり続けていたのですが、
実はifに文字列というのは自分が別の形でずっとやってたことと同じだったんです笑

というのも、自分が普段使っているPythonで下記の様なコードを書くことはあったのですが、
ちゃんと考えれば、何かしらの値（厳密に言ったら違いますが、）が変数に入っていればifの中の処理が走るというのはどの言語でも同じことでした。

```python
var = request.GET.get('param')
if var: 
    print('var has some value in it') 
# request.GET.get('param')で値が取れた場合
#    >>> var : paramに設定された文字列
# とれなかった場合
#    >>> var : None　（ifの中身が実行されない）
```

こんな感じで「リストが空の時は～」みたいなことは今まで何百回も書いていたのですが、
こうやって整理してみることで、改めて基礎の勉強になりました。

#まとめ

* 変数に値が入っているかどうかで条件分岐をする時には、`isset()`よりも`??`を使ってコード全体でそろえる方がベター（好みにはよりますが、）
* if文で空文字はfalse判定になる。なにかしらの文字を含んでいればtrue判定になる。
【matplotlib】3次元ヒートマップを作る方法

# 概要
matplotlibで**3次元ヒートマップを作る方法**を紹介します。3次元空間に別の次元、例えば温度の次元を加えたりする場合に役立つと思います。
Google Colabで作成したコードは、[こちら](https://colab.research.google.com/drive/1nPY2NIkX0MkQZGd8nybuaafGkhjhlFY-?usp=sharing)にあります。

# 手順
1. 各種インポートします。（各モジュールの実行時のversionは、Google Colab内で作成したコードにあります。）
1. 3次元ヒートマップを作ります。

## 1.　各種インポート
```Python:各種インポート
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from matplotlib import colors
```
各モジュールの実行時のversionは、Google Colab内で作成したコード[こちら](https://colab.research.google.com/drive/1nPY2NIkX0MkQZGd8nybuaafGkhjhlFY-?usp=sharing)にあります。

## 2.　3次元ヒートマップを作成
```Python:3次元ヒートマップ
# 3次元ヒートマップ
fig = plt.figure(figsize=(13, 10))
ax = fig.add_subplot(111, projection='3d')

#　プロット内容
x = np.arange(0, 100, 1)
y = np.arange(0, 100, 1)
X, Y = np.meshgrid(x, y)
Z = 0.01*(X*np.sin(0.1*X) + Y*np.cos(0.1*Y))
# heatmapの内容
myheatdata = np.sin(0.15*X) + np.cos(0.15*Y)
# heatmapの内容をfacecolors用に[0-1]に正規化
norm = colors.Normalize(vmin=np.min(myheatdata), vmax=np.max(myheatdata))
norm_myheatdata = norm(myheatdata)
# プロット
surf = ax.plot_surface(X, Y, Z,
                       facecolors=cm.CMRmap(norm_myheatdata),
                       cmap=plt.get_cmap('CMRmap')
                       )
# 軸ラベル
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
# カラーバーを表示（カラーバーに使う目盛は正規化前のheatdataの尺度で表示する）
m = cm.ScalarMappable(cmap=surf.cmap, norm=norm)
m.set_array(myheatdata)
fig.colorbar(m, shrink=0.6, label='myheatdata')
plt.show()
```
出力結果
![3dheatmap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/b8e9f424-4f58-1b6e-4717-7ea2cb3db5d9.png)

# まとめ
matplotlibで**3次元ヒートマップを作る方法**を紹介しました。
3次元ヒートマップを作る場面は少ないと思いますが、誰かの役に立てれば幸いです。

# 参考資料
* [Stack Overflow, Colorbar for matplotlib plot_surface using facecolors](https://stackoverflow.com/questions/42924993/colorbar-for-matplotlib-plot-surface-using-facecolors)
* [Stack Overflow, unexpected constant color using matplotlib surface_plot and facecolors](https://stackoverflow.com/questions/49325704/unexpected-constant-color-using-matplotlib-surface-plot-and-facecolors)
組み込み開発の始め方（あるいは生協でマイコンを入手することについて）

この記事は[広島大学 HiCoder Advent Calendar 2021](https://adventar.org/calendars/6509)の14日めの記事です。
大遅刻です。ごめんなさい。

これまで組み込み系に興味はあったけど、なかなか手を出せてこなかった！という人の
背中を押せたらと思います。

# 生協でマイコンボードを買える

広島大学生協は、[スイッチサイエンス](https://www.switch-science.com/info/coop/) と [マルツオンライン](https://www.marutsu.co.jp/pc/static/large_order/1501_131_purchase) との取引があります。
学生個人であっても、これらのサイトで売られている商品を生協で購入できます。

私はスイッチサイエンスの製品は生協経由で購入したことがないのでわからないのですが、
マルツの製品はなんと **MyPleで支払いができます**。

私はクレジットカードを持っていない頃は、毎回秋月電子通商に振り込みしていました。
それに比べるとダンゼン楽ですね！送料もかかりません。

昨年のミールカードが余っている皆さん、[ラズベリーパイ](https://www.raspberrypi.org/) でもいかがですか？

# 組み込み開発の始め方

## マイコンボードを選ぶ

組み込み開発と一口に言っても幅が広いのですが、最初のマイコンボードは得意な処理系に応じて
選ぶのがいいんじゃないかと思います。だいたいどれを選んでも、そこそこのことができます。

### C/C++ に触ったことがある

最初の一歩としておすすめしたいのが [Arduino](https://arduino.cc/)（アルドゥイーノと読みます）です。
電子工作の入門者向けマイコンとして一番ポピュラーで、情報も多いです。

ボードのシリーズがたくさんありますが、とりあえず買っておくなら Uno がおすすめです。
純正品は3,000円くらい。はんだ付け等をしなくても、買ってそのまま動きます。
シールドという拡張ユニットが多数売られており、必要になった時に機能を追加しやすいのもメリットです。

プログラムはスケッチという C++ の亜種のような文法になります。

### Python ができる

組み込み向けに [MicroPython](https://micropython.org/) という環境があります。
公式が出している [PyBoard](https://store.micropython.org/product/KIT-START1R) というマイコンがありますが、これは7,000円くらいしてそこそこに高価なので気軽に壊せません。

慣れないうちは部品を逆接続したり、大きすぎる電圧をかけたりして壊してしまうことが多々あります。
そうして、どんな扱い方をしたら部品を壊すのかを覚えていくのです。
なので、気軽に壊せる値段のボードをお勧めします。

環境を自力でインストールすれば、ESP8266 や ESP32 というマイコンで動かせます。
ESP32 であれば [DevKitC](https://akizukidenshi.com/catalog/g/gM-11819/) という開発用ボードがほぼ定価（1,500円くらい）で生協に売っています。マルツを頼むまでもなく、店頭で購入できます。

### JavaScript ができる

[obniz board](https://obniz.com/ja/products/obnizboard) という IoT 向けの開発ボードがあります。ボード自体は6,000円以上しますが、簡単にネットワークに繋げて、
JSでプログラミングできる上、各種保護回路が入っているのでそう簡単には壊れません。

Web系の人が IoT に入門するのには最適な選択肢だと思います。

ちなみに、この obniz board も ESP32 マイコンをコアにしています。
慣れてきてもっと自由度の高い開発がしたくなったら、ESP を搭載している他のボードに乗り換えると良いでしょう。
Arduino 言語も動きますし、ESP-IDF という標準開発環境を使って C を書けば、全機能が使えるようになります。
【SAP-C01試験対策】AWS Diretory Serviceのまとめ

# はじめに

AWSの管理ツールについて学習したので内容をまとめます。

https://www.amazon.co.jp/dp/B08F9CQ6LT/

https://www.slideshare.net/AmazonWebServicesJapan/aws-black-belt-tech-2015-aws-directory-service

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



# 背景
本記事はAWSソリューションアーキテクトプロフェッショナルに合格するために、[Udemyの模擬試験](https://www.udemy.com/course/aws-53225)を解いて分からなかった部分を勉強してまとめるものです。

試験対策用のため、分からない知識を補足したり試験で問われなさそうなところを省略したりしながらまとめています。
なるべくわかりやすい記載を心がけますが、最終目的は自己学習用であるということをご容赦ください。

# 基本用語
- Active Directory：Windowsネットワークの基本的な認証とセキュリティ基盤
- AWS Directory Service：Microsoft Active DirectoryをAWSで利用するためのサービス。以下の三つがある。
 - Simple AD：一般的なディレクトリ機能を提供
 - AWS Managed Microsoft AD：Simple ADより多彩な機能を提供
 - AD Connector：既存のオンプレミスActive DirectoryをAWSに接続

## Simple AD
- 一般的なディレクトリ機能を提供
- 信頼関係はサポートしない
- 小規模

## AWS Managed Microsoft AD
- Simple ADに加え多くの機能の利用可能。
- AWSアプリケーションと統合可能。
- 既存(オンプレミス)のActive Directoryドメインとの信頼関係を設定可能。
- IAMのアクセス許可があればマネジメントコンソールからAWSリソースの管理も可能。

## AD Connector
- VPNやDirect Connectを通じてVPCをオンプレミスのActive Directoryに接続する。
- 設定後、既存の認証情報を使用してAWSアプリケーションにサインイン可能。
- IAMのアクセス許可があればマネジメントコンソールからAWSリソースの管理も可能。
- MFAと統合することで多要素認証も可能。


# 試験対策

## 設問①SAML対応のアプリケーションを構築したい。MFAも必要。
- SAML連携やSSOはAD Connectorと連携可能。

## 設問②Direct Connectで接続されているMicrosoft Active Directoryからマネジメントコンソールにアクセスしたい。
- SAML2.0形式でIdP側とAWS側でメタデータの交換をし、信頼関係の構築が必要。
- オンプレミス環境にADFSをセットアップ、SAMLメタデータを取得しAWSのID プロバイダーに登録、IAMとIdPの間の信頼関係を確立するIAMロールを作成、ADFSでもAWSのフェデレーションメタデータを登録。

## 設問③オンプレミスのMicrosoft Active Directoryを使用してマネジメントコンソールにログインしたい。
- オンプレミスのActive DirectoryにSAML2.0に対応したIdPとしてADFSをインストールする。ADFSからSAMLアサーションを受け取りAWS SSOでマネジメントコンソールにシングルサインオンする。

## 設問④ハイブリッドアーキテクチャでオンプレミスのWindowsアカウントからAWSリソースにアクセスしたい。ADワークロードはAWS側に移行したい。
- AWS Managed Microsoft ADを利用してシングルサインオンを実現する。
- ADConnectorではワークロードがオンプレミス側になる。




# 用語集
- ADFS：クラウドにアクセスするために必要なトークンを発行する
- SAMLアサーション：ユーザー認証ステータスを含むXMLドキュメント
- SAML2.0：シングルサインオンで利用するプロトコル。認証を管理する。
TDF2021のShader Showdownで使用したSonicPi 小技集

先日12/11~12/12で開催されましたTokyo Demo Fest（以下TDF)のShader Showdownセミファイナル第1戦にてBGMをSonicPiによる演奏を使用して担当させていただきました。
以下は実際に行われたTDFの様子になります。

https://www.youtube.com/watch?v=bp37xTVNRrM&t=6125s

SonicPiの画面のみを確認したい方はこちらをご覧ください。

https://www.youtube.com/watch?v=0bOXEpCUPtQ

今回はこちらで使用していたSonicPiのコードの小技的な部分をさっくりと解説したいと思います。
なお、実際に動画内に乗っているコードと今回の記事内で記述されているコードに差異がある場合でも機能的には大差ありません。

##16小節の把握
自分はオードソックスな四つ打ちをメインにしたテクノっぽい方向に寄せて書くのが基本です。
となると、変化はおおよそ16小節などで区切ってかけていきたいところですが、いちいちログに吐かせるための無駄な行の追加などは省いてしまいたいし、折角なのでなにがしかの要素に使いたいところ。
なので、自分は以下のような形でクラッシュシンバルを鳴らすことで、16小節の間隔を耳と体で認識できるように実装しています。

```ruby:
live_loop :hi do
  16.times do
    tick
    #trは自分が使用しているサンプルフォルダまでのパスを定義してある変数です
    #以下の記述ではtrのパスにあるフォルダ内でcrashと名前に入っているサンプルファイルが鳴ります
    sample tr,'crash',amp:2 if(spread,1,256).look
    sleep 0.25
    end
end
```

##ブレイクもどきの手軽な作り方
一瞬だけ高音/低音だけを残して他の音を切ることで多少展開に近い何かを作れるようにしています。
例として挙げると、以下のコードのうちhpfの数値を一瞬だけ120~130程度まで上げて実行し、音が変わり始めたのを認識した瞬間に0に戻して再実行することで一瞬だけ低音を切る、などになります。

```ruby:
set_mixer_control! hpf:0,hpf_slide:0.75
set_mixer_control! lpf:130,lpf_slide:16
```

##負荷をかけないエフェクトの使い方
公式フォーラムに記述があったはず（現在目下捜索中）なのですが、SonicPiの仕様として以下のような書き方をした場合1ループごとにエフェクトを生成している状態になります。
この状態だと毎ループ毎にエフェクト生成処理が挟まるため、どんどん処理が重くなっていきます（特にreverbなどの処理が重めのエフェクトだと顕著です。）

```ruby:
live_loop :synth do
    with_fx :reverb do
          tick
          #ここにシンセやサンプルを記述
          sleep 0.25
    end
end
```
そのため、以下のようにlive_loop内に繰り返し処理を入れて記述をすることでエフェクト生成処理の回数を抑え、かかる負荷を少なくするようにしています。
ただし、この繰り返し処理を入れて実行するとループ内を書き換えて実行した後反映されるまでワンテンポ掛かる（実行中のループでは反映されず、次のループから反映される）ため、その点には注意が必要です。
自分は上記で書いた16小節把握用のクラッシュシンバルの間隔を体で覚えて、おおよそ同タイミングで反映されるように実行しているときが多いです。

```ruby:
live_loop :synth do
    with_fx :reverb do
        16.times do　##以下16回繰り返し
          tick
          #ここにシンセやサンプルを記述
          sleep 0.25
        end        
    end
end
```

---
おおよそ以上が自分が使っているちょっとしたtipsになります。
他の記述は基本的に公式チュートリアルに記載のあるものばかりですので、ぜひ実際にSonicPiをインストールしてチュートリアルに触れてみてください。

[SonicPi 公式サイト](https://sonic-pi.net/)
[SonicPi 公式フォーラム](https://in-thread.sonic-pi.net/)


##Shader Showdown出演感想
注：以下ポエムに似た何かですので読み飛ばしたい方は読み飛ばしてください。

今回幸運にもオーガナイザーの一人からお声がけをいただきShader Showdownのイベントに音源だけとはいえ参加させていただくことができました。
自分の腕で足りるのか不安なところはありましたが、実際に自分の音が鳴る中[がむさん](https://twitter.com/gam0022)や[かもしかさん](https://twitter.com/kamoshika_vrc)がゴリゴリにかっこいい絵を作り出していくのを見ていくのは本当に興奮しました。
実際に終わった後も音を褒めていただき、特にがむさんから直接自分の音を聞いて書くものを決めたという話を聞いたときは飛び上がるほど嬉しかったです。
また、配信をご覧になられていた方々もコメントなどで積極的に音源褒めていただきまして本当にありがたかったです。

まだまだつたないところもありますが、今後ともSonicPiなどを使用してlive codingを頑張っていこうと思います。
本当に今回はありがとうございました！
VSCodeのPHP IntelephenseでPHP8.1の記法記載時にエラーがでる

# はじめに

ローカル環境にて、PHP8.1 にバージョンアップしたところ、PHP Intelephense 拡張機能でエラーが出るようになってしまいました。
どうやら readonly アクセス修飾子を型と認識しているようです。

![php_intelephense_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586387/09e59da7-40a6-1d12-adf9-f7b4d498220d.png)

# 結論

:::note info
settings.json に PHP Intelephense の設定で PHP バージョンを指定すれば OK
:::

```json-doc
{
    // ターゲットのPHPバージョンを表すsemver互換の文字列。
    // バージョンに適した提案と診断を提供するために使用されます。 
    // PHP5.3.0以降がサポートされています。
    "intelephense.environment.phpVersion": "8.1.0"
}
```

# バージョン

- PHP
    - 8.1.0

# 確認

バッチリ消えました！

![php_intelephense_error_resolution.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586387/3fbc9b13-c5b8-d7ec-c16e-0eb80b71c88e.png)

# おわりに

WSL2 の Ubuntu ディストリビューションに PHP8.1 を公式で `apt install` できるようにしてほしい・・・
【Python覚書】selenium on raspberry pi(002)_環境構築～画面キャプチャまで

# はじめに

以前、IoTの勉強をしようと思って、raspberry pi 3 modelBを数個購入したのですが、長い間眠っている状態でした。

これを機に、稼働させてみようと思い、「【Python覚書】selenium on centos stream 8(001)」とほぼ同じ内容ですが、raspberry piのOSである「Buster版」上での環境構築手順を記載しようと思います。

# OSの最新化

```bash
# パッケージリストの更新
sudo apt-get -y update
# パッケージの更新
sudo apt-get -y upgrade
# OSのアップグレード
sudo apt-get -y dist-upgrade
```

# python環境構築(設定変更)

raspberry piのOSは初期状態でpython2とpython3がインストール済みなので、まずはpython3をデフォルトに設定します。

```bash
# 設定前のバージョン確認
python --version

cd /usr/bin
# Python 2のシンボリックリンクを解除
sudo unlink python
# Python 3.7へのシンボリックリンクに変更
sudo ln -s python3 python

# 設定後のバージョン確認
python --version
```

# seleniumのインストール
```
pip3 install --upgrade pip
pip3 install --upgrade setuptools
pip3 install selenium
```

# Chromiumドライバのインストール

```bash
sudo apt install -y chromium-chromedriver

which chromedriver
```

#pythonプログラムの動作確認

```python:Action_configurate.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome import service as fs

from time import sleep

options = Options()
options.add_argument('--headless')
options.add_argument("--no-sandbox")

# ドライバー指定でChromeブラウザを開く
chrome_service = fs.Service(executable_path="/usr/bin/chromedriver")  # 修正箇所
driver = webdriver.Chrome(service=chrome_service, options=options)  # 修正箇所

# ウィンドウサイズを設定
driver.set_window_size(1280, 720)

# 対象のページを指定
driver.get('https://qiita.com/o_chan_t')
sleep(5)

# キャプチャするページの幅
my_width = driver.execute_script('return document.body.scrollWidth')
# キャプチャするページの高さ
my_height = driver.execute_script('return document.body.scrollHeight')
# 保存するウィンドウサイズ(画像サイズ)
driver.set_window_size(my_width, my_height)

driver.save_screenshot('Qiita_MyPage_Capture.png')
```

raspberry piの方は、日本語の文字化け問題が起きませんでした。
Oracle SQL Developer フリーズ回避 -「ようこそページ」の非表示

# 事象
Mac に入れた SQL Developer が、起動後の初回クリックですぐに固まる。

#記事の背景
久々に SQL Developer を触ることにした。Mac に SQL Developer を入れてみる。
起動したところ、ちょっとしたクリックですぐに固まる。困った。(その後の紆余曲折は省略)
メニューバーから SQLワークシート などを開き、それから操作すると固まらない模様。
「ようこそページ」が邪魔をしているという結論に至る。
その観点で調べると、設定ファイルで「ようこそページ」を表示する情報に行き当たる。救われた。
日本語での検索では到達しなかったため、ここに残したい。
なお、「ようこそページ」を表示しないチェックボックスが、「ようこそページ」自体にあるため、この様な対応が必要になる。
詳しくは末尾の元情報のリンクを参照されたし。

# 環境
- macOS 11.6
- SQLDeveloper 21.2.1.204 (ビルド204.1703)
- Oracle Instanct Client 19.8
- JDK 11.0.6

# 大雑把な手順
~/.sqldeveloper フォルダーで dtcache.xml を探す。
「ようこそページ」の表示を制御するキーがあるので、下記の状態に変更する。
なければ追加する。

```xml:dtcache.xml
   <Item>
      <Key>oracle.help.StartPageEditor:TabCheckboxState:Default</Key>
      <Value class="java.lang.Boolean">false</Value>
   </Item>
```
# 参考文献
[Oracle SQL Developer Problem initializing Welcome Page](https://stackoverflow.com/questions/52484814/oracle-sql-developer-problem-initializing-welcome-page)
いまさらSwinTransfomer

# はじめに

恥ずかしながらいまさらSwinTransfomerをしり論文を読み面白かったため論文中の主なアイデアをまとめました．

# 概要

- SwinTransfomer は　ViTでは考慮できない階層的な特徴量を学習するモデル
- 主なアイデア
    - PatchMerging : 階層が深くなるにつれて特徴量マップが小さくなるように設計し階層的な特徴量を取得
    - W-MSA と SW-MSA の二つの Attention : windowサイズを不均一にすることでwindow間のインタラクションを考慮
- Object Detection, Semantic Segmentation分野で当時のSoTA

# 背景

現在，CV分野で人気のViTですが，以下の問題があります．

- パッチサイズが固定になってしまうため，階層的な特徴量が取得できずに物体検出などのタスクに向いていない
- 高解像度の画像では画像サイズの二乗で計算量が増えるため計算時間の削減が必要である

SwinTrasnfomer では上記の問題を解決するために提案されたモデルであり， Object Detection, Semantic Segmentation でSoTAを達成したモデルとなります．

# 主なアイデア

![swin_transformer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/127a9925-6eb2-3f6c-8327-8f41e51a1f9b.png)


## PatchMerging

![unHHISomtzDKWczC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/dae90f98-12c9-c994-c405-06674bca4011.png)


まず，層が深くなるにつれて特徴量マップが小さくなる機構「PatchMergin」について説明します．

これは近傍の 2*2*C のデータを一列に並べ線形変換して W/2 * H/2 * 2C へとデータを縮小します．
これにより，Pooling層のように層が深くなるにつれて階層的に特徴量を抽出できます．

## W-MSA と SW-MSA

![block.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/7aac0f57-fa4f-ffe2-c82a-4250ca390c52.png)

### W-MSA(Window based Multihead Self Attention)

SwinTransfomerには二つのAttentionが含まれています．その一つが W-MSA になります．

これはパッチをWindowという単位にまとめてwindow内のパッチ間にAttentionをにかけることで高解像の画像でも効率的に学習を行うことができます．従来の MSA では `4hwC^2+2(hw)^2C` の計算量が必要なのに対して， W-MSA では `4hwC^2+2M^2(hw)C` で計算が可能となります．従来の手法では画像サイズの二乗に比例するのに対して，提案手法ではWindowサイズの二乗で計算ができるため，高解像度画像でも効率的に学習ができます．

### SW-MSA(Shifted Window based Multihead Self Attention)

![swin_transformer_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/a57f6931-80be-af6b-ee5e-a9e19b85a9c1.png)

次に SW-MSA について説明します．
これは偶数番目のWindowサイズを半分にすることでパッチ間のインタラクションを考慮した学習が可能になります．

上記二つのAttentionを利用して効率的に学習が可能となるのがSwinTransfomerが優れている点になります．

# 結果

Swin-T : C=96, 層数 = {2, 2, 6, 2}
Swin-S : C=96, 層数 = {2, 2, 18, 2}
Swin-B : C=128, 層数 = {2, 2, 18, 2}
Swin-L : C=192, 層数 = {2, 2, 18, 2}

![スクリーンショット 2021-12-31 15.49.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/e2997590-0501-4cd4-b213-b7916330700e.png)

ImageNetの分類においても高い精度を記録していることがわかります．

![スクリーンショット 2021-12-31 15.51.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/252a12a0-0b80-d3d0-08fe-aff9ba0455d5.png)

COCOデータセットの物体検出でも他のどのモデルよりも高い性能を示していることがわかります．

詳しい条件や詳細などは本論文をご覧ください．

# まとめ

まとめると…

- SwinTransfomerは階層的なアーキテクチャとウィンドウ間のインタラクションを考慮して学習が可能
- 従来の学習よりも高解像度の画像でも効率的な学習が可能
- Object Detection と Semantic Segmentation の分野で高い性能を誇る

非常に勉強になりました．面白かったです．

# 引用

本論文
https://arxiv.org/abs/2103.14030
Blockly Menu作成(1)

# Blockly Menu作成(1)
Google Blockly環境構築はできましたので、エディタ画面を作成していきたいと思います。

## 環境構築
環境構築に関しては別記事「[Google Blockly環境構築](https://qiita.com/tkhr68000/items/b8430c0c6021d0a18ed1)」を参照してください。

# 最小構成画面作成
googleのガイドを参照して少しずつ作成していこうと思います。

[Google for Education > Blockly > Guides > Get Started](https://developers.google.com/blockly/guides/get-started/web)

## 固定サイズの画面を配置
最初なので、「動けばいい」コードで作ります。（コード整理は後でやる予定です。）
Blocky Guides を参照し、最初は固定画面で作成します。
[Google for Education > Blockly > Guides > Fixed-sized Workspace ](https://developers.google.com/blockly/guides/configure/web/fixed-size)

具体的には以下のようなソースとなります。

```html:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
	<meta charset="utf-8">
	<title>Blockly Sample</title>
	<script src="../blockly/blockly_compressed.js"></script>
	<script src="../blockly/blocks_compressed.js"></script>
	<script src="../blockly/msg/js/en.js"></script>
</head>

<body>
	<p>Fixed blockly</p>
	<div id="blocklyDiv" style="height: 480px; width: 600px;"></div>
	<script>
		var toolbox = {
			"kind": "flyoutToolbox",
			"contents": [
				{
					"kind": "block",
					"type": "controls_if"
				},
				{
					"kind": "block",
					"type": "controls_repeat_ext"
				},
				{
					"kind": "block",
					"type": "logic_compare"
				},
				{
					"kind": "block",
					"type": "math_number"
				},
				{
					"kind": "block",
					"type": "math_arithmetic"
				},
				{
					"kind": "block",
					"type": "text"
				},
				{
					"kind": "block",
					"type": "text_print"
				},
			]
		}
		var workspace = Blockly.inject('blocklyDiv', { toolbox: toolbox });

	</script>
</body>

</html>
```

保存もコード生成もできないBlocklyですが、とりあえず、画面表示はできました。

少し解説します。
Blocklyの基本処理はblockly_xxxx.js、blocks_xxxx.jsにあります。
xxxxがcompressedなのは、縮小バージョンとなります。
通信量、通信速度の関係から、基本的には縮小バージョンを使用します。
デバック等の場合は、非縮小バージョン「*_uncompressed.js」を使用して下さい。

各言語のメッセージは、「msg/js/xx.js」の読み込みによって切り替えます。
上記では英語バージョンですが、もちろん、「msg/js/ja.js」も準備されています。

次回（[Blockly Menu作成(2)](https://qiita.com/tkhr68000/items/0fe0777e34c6bd629f68)）はToolboxカスタマイズを行っていきます。
AWS EC2でssh登録してgit clone [Please use a personal access token instead.]

AWS EC2で勉強のため作業していたらgithubからgit cloneするときに普通にhttps使うとエラーが出るようになっていました。

```
remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.
remote: Please see https://github.blog/2020-12-30-token-authentication-requirements-for-git-operations/ for more information.
fatal: unable to access 'https://github.com/名前/リポジトリ.git/': The requested URL returned error: 403
```
簡単にいうとアクセストークンというのを使うか、ssh使ってくれ。ってこと
![GitHub.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260345/31eb4e95-3499-b68e-5099-7e615574524b.png)

今回私はEC2のUbuntuで起こりましたが、それ以外でも起こりますし、初心者でAWSもわからない状態でこんなエラー出たらデプロイはやっぱり無理！！となりそうなので記事書きます。

慣れればなんの問題もないし、新しいPCで環境構築するときにもsshの設定は必ずするのでできるようにしておきましょう。

# 鍵作る
今回EC2で作った環境はUbuntu。まあ他のLinuxでもMacでも同じです。

```
ubuntu@ip-172-31-11-111:~$ cd ~/.ssh
```

`.ssh`というディレクトリあったらOKなかったらディレクトリ作る。

```
$ mkdir ~/.ssh
```

鍵を作ります。そして中身を表示させる。

```
$ ssh-keygen -t rsa
```

なんか表示されますが、こだわりがないならEnter 3回ほど押せば問題ありません。
設定を変更したい場合は適時変更してください。

秘密鍵と公開鍵のファイルが作成されたはずです。

- id_rsa （秘密鍵）
- id_rsa.pub （公開鍵）

```
$ cat id_rsa.pub
```
表示された
`ssh-rsa ~~~~~~~~`みたいな長い文字列全部コピー。これが公開鍵なのでgithubに登録します。

# githubでSSHキー登録
githubにログインして、↓のURLでいけると思う

https://github.com/settings/keys

行けなかったら
`左上のアイコン > settings > SSH and GPG keys`
で行けるはず。

![スクリーンショット 2021-12-30 23.20.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260345/f64143d5-a31e-cbf9-e944-46d04e26b809.png)

「New SSH key」を押す
Titleは自分でわかるような名前つければOK
Keyにさっきコピーした`ssh-rsa ~~~~~~~~`みたいなのを貼り付ける

![スクリーンショット 2021-12-30 23.22.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260345/589b7da0-0ca6-1571-c747-0b7586010ce2.png)

# githubとの接続確認
接続確認します。

```
$ ssh -T git@github.com
Are you sure you want to continue connecting (yes/no/[fingerprint])?
```

yesって打てばOKです。`You've successfully authenticated`みたいなのでたらOK

git cloneしてください。URLはgithubのssh選んで表示されたものをコピペ

![スクリーンショット 2021-12-30 23.28.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260345/08507686-b27d-a08b-c7ec-c768d6cba6d3.png)


任意のディレクトリで以下をcloneを実行。そのディレクトリにcloneされます。
(`git@github.com:ユーザー名/リポジトリ名.git`の部分をコピペしたものを貼る)


```
$ git clone git@github.com:ユーザー名/リポジトリ名.git
```
【AWS/SOA】VPCフローログ 記録のされ方の問題（図解あり）

AWS、SOA取得にむけて勉強していて、VPCフローログの問題でこれどういう意味？ってなったので備忘として残しておきます。（あくまで私の解釈なので間違ってたら教えてください。）

##問題
サーバからEC2にpingを投げましたが、サーバ側でICMPが応答しませんでした。VPCフローログ見せてやるから理由教えろや的な問題。

VPCフローログは簡易的に記載します。Aはサーバー、BはEC2。

```
①A→B ACCEPT OK
②B→A ACCEPT OK
③B→A REJECT OK
```

答えはネットワークACL（以下NACL）のアウトバウンド拒否です。

##考察
私の最初の解釈。
①サーバからEC2にpingはいってますね
②最初の返却だからSGからアウトバウンドOKだね
③次の返却はNACLだからVPCはアウトバウンドNGだね

と思ったのだけどたまたまこの問題は②と③の順なだけで、ここは実際のVPCフローログだ順不同っぽいです。そうなるとこの答えの導き方は成立しなくなります。

ここで必要な情報になるのが、ステートフル/ステートレスの考え方。SGではステートフル、NACLではステートレスです。なのでこの問題の場合、REJECTを返却するのはNACLだけという考え方になるそうです。

ステートフル（SG）：戻りのトラフィックは全許可
ステートレス（NACL)：戻りのトラフィックは明示的に許可が必要

##図解
![スクリーンショット 2021-12-31 15.29.24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/7ac45d42-041e-fbf2-1727-e4a5290f3ac3.jpeg)


パワポ作るの楽しい。
【form_with】名前空間でadminを使用した際の書き方

編集画面の実装がうまくいかず困っていたところ、ドンピシャの記事を見つけたためメモ。
[Rails: form_withで名前空間が異なるコントローラを簡潔に指定する方法](https://techracho.bpsinc.jp/ohno/2019_12_10/84349)

form_withの引数に[:admin, @user]を渡す。

```
<%= form_with model: [:admin, @user], local: true do |f| %>
```
Julia: Genie の使いかた （その2）

こちらと同じことを Genie でやってみました。
[python3: bottle の使い方](https://qiita.com/ekzemplaro/items/ed9fef17b2572c3e8a8a)
プロジェクトの作成方法はこちら
[Julia: Genie の使いかた](https://qiita.com/ekzemplaro/items/4119bbe5dbc341c37ae1)

```julia:routes.jl
using Genie.Router

route("/") do
  serve_static_file("welcome.html")
end

route("/hello") do
    str_out = "Hello World!<br />"
    str_out *= "<blockquote>"
    str_out *= "こんにちは。<br />"
    str_out *= "</blockquote>"
    str_out *= "Dec/31/2021<br />"
end

route("/morning") do
    str_out = "Good Morning!<br />"
    str_out *= "<blockquote>"
    str_out *= "おはようございます。<br />"
    str_out *= "</blockquote>"
    str_out *= "Dec/31/2021<br />"
end

route("/evening") do
    str_out = "Good Evening!<br />"
    str_out *= "<blockquote>"
    str_out *= "今晩は。<br />"
    str_out *= "</blockquote>"
    str_out *= "Dec/31/2021<br />"
end
```

ブラウザーで　http://localhost:8000/hello にアクセス
![genie_hello.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/e17efb72-37a4-1cd6-9ca6-26778e1eb182.png)


ブラウザーで　http://localhost:8000/morning にアクセス
![genie_morning.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/aac836b3-3b35-e4af-245a-7feff6387613.png)



ブラウザーで　http://localhost:8000/evening にアクセス
![genie_evening.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/16824513-27c2-0e36-b5fa-1a067ebe500b.png)
【Project Euler】Problem 25: 1000桁のフィボナッチ数

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 25：1000桁のフィボナッチ数

原文 [Problem 25: 1000-digit Fibonacci number](https://projecteuler.net/problem=25)

**問題の要約：フィボナッチ数が1000桁を超えるのは何番目か求めよ**

素直にインプリですると「[Problem 2: 偶数のフィボナッチ数](https://qiita.com/masa0599/items/666d42f84bf817f81d6b)」で作成したフィボナッチ数Generator関数**fibgen**を使って$10^{1000-1}$を超えるまでループします。

```python
import itertools
fib = fibgen()
for i in itertools.count(1):
  f = next(fib)
  if f > 10**(1000-1): break
print(f"Answer: {i}")
# Answer: 4782
```

これでも十分早いのですが、余りにも大きい数を扱っているのと、ただループするだけでちょっと脳がないのでちょっと工夫します。

このような大きな数を扱うときには対数のlogを使うのが常套手段ですね。

[フィボナッチ数(Wikipedia)](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%9C%E3%83%8A%E3%83%83%E3%83%81%E6%95%B0)によると一般項は、

```math 
\begin{align}
&F_n = \frac{1}{\sqrt{5}}\{(\frac{1+\sqrt{5}}{2})^n-(\frac{1-\sqrt{5}}{2})^n\} \\
&ですが右辺の第2項はnが大きくなると無視できるので、\\
&F_n \simeq \frac{1}{\sqrt{5}}(\frac{1+\sqrt{5}}{2})^n>10^{1000-1} \\
&この両辺のlog10を取って移項すると、\\
&n > \frac{1000-1+log_{10}(\sqrt{5})}{log_{10}(\frac{(1+\sqrt(5))}{2})}　
\\
&となります。
\end{align}
```

これをプログラムにすると一発で答えが求まります。

```python
from math import sqrt, log10, ceil

print(ceil((1000-1+log10(sqrt(5)))/log10(((1+sqrt(5))/2))))
```

### フィボナッチ数の指数表記

**【例題】1000番目のフィボナッチ数を仮数部の小数部3桁の指数表記であらわせ**

このlogを使う考え方を使うと指数表記にすることができます。

```math 
\begin{align}
&LF = log_{10}F_n = log_{10}(\frac{1+\sqrt 5}{2})-log_{10}(\sqrt{5})\\
&仮数部　= 10^{LF-int(LF)} \\
&指数部　= int(LF)
\end{align}
```
これをコードにすると以下になり、答えは **4.347e208**となります。

```python
import math

def fibfloat(n, d):
  logfn = n*math.log10((1+5**(0.5))/2.0) - math.log10(5**(0.5))
  logm = logfn-int(logfn)
  return f"{10**(logm):.0{d}f}e{int(logfn)}"

for n in [10**2, 10**3, 10**4, 10**8]:
  print(n, fibfloat(n, 3))
# 100 3.542e20
# 1000 4.347e208
# 10000 3.364e2089
# 100000000 4.737e20898763

```

（開発環境：Google Colab）
【Django】get_user_model()

# get_user_model()

CustomUserモデル、DjangoデフォルトのUserモデルを問わず、使用しているUserモデル自体を返してくれる関数。


## 使い方

`from django.contrib.auth import get_user_model`をインポートすると使用できる。

* 公式で推奨されている通り、デフォルトのUserモデルを使用することは推奨されていない。
* 何らかのCustomUserモデルを作成し、多くのユースケースに適切なUserモデルの参照先を簡単に提供することができる。
* すなわち、viewsファイルなどで簡単にuserオブジェクトを作ることができる。
    * `user = get_user_model() ` 

## 補足

CustomUserモデルを作成するとsettings.pyに変更の旨を記述（`AUTH_USER_MODEL = 'some.User'`）し、
`UserModel = settings.AUTH_USER_MODEL`のようにuserモデルを参照することができるが、
これはviewsでは使うことができない。
t-wadaさんの研修を受けたので、改めてTDDについてまとめる(C#編)

# はじめに
社内でt-wadaさんを招いてTDDオンライン研修を開催していただく機会がありました。そこで学ぶことがたくさんあったので復習をかねてまとめてみました。
(4年前に[Angularで試した記事](https://qiita.com/usomaru/items/66fd195ce1e2ce5b17c9)をかいていましたが、TDDに関するポイントのまとめがあまりにも少なかったので、今回はコードではなく、研修で得たポイントをメインにまとめたいと思います。)

# 環境

- Visual Studio 2019
- C#(xUnit)

# TODOリストをかいてみる
今回の研修では整数閉区間を示すクラスを作成するというお題に対してTDDで作成していく、というワークショップがありました。
(おそらく題材はTDD Boot Camp 2020 Online #1と同じ)

さっそくお題を分解していったのですが、…？？？
t-wadaさんの講義でもおっしゃってましたが、このリストを作成するのが難しい…！

とりあえず、文章を読んでここはテストができそうと見分けのつく簡単なところだけ書き出し、テストコードを書き始めようとしたところで1度目のレビューを受けました。

実はこの進め方は正解みたいです。
**TODOリストとはあくまでメモ**。そのため何時間も考え込むというのはNGらしいです。テストを書き始めていくと気づいてくることもあります。
**気づいたら都度TODOリストに追加**していけばいいそうです。


# テストコードをかく

上で私が分解したTODOリストのうち、「(整数閉区間は)指定した整数を含むかどうか判定できる」のテストについて今回はピックアップして紹介します。

最初に書いたテストコードがこちら

```C#:ClosedRangeTest
[Fact]
[Trait("(整数閉区間は)指定した整数を含むかどうか判定できる", "")]
public void 閉区間3_7に整数3を渡すと閉区間に含まれていると判定される()
{
    Assert.True(closedRange.IsContain(3));
}
```

C#だと、「,」とか「[」とかが使えなくて、テストのメソッド名どうしようか困りました。

当然この状態ではまだ何も実装していないので、テストは失敗します。

# 茶番コード

1秒でも早くこのテストを成功させるように茶番のような実装をします

```C#:ClosedRange
public bool IsContain(int num)
{
    return true;
}
```

これでテストコードは正しいというテストもできました。

# ちゃんと実装

茶番コードでのテスト成功を維持したままちゃんと実装します。

```C#:ClosedRange
public bool IsContain(int num)
{
    if (num <= _upperNumber && num >= _lowNumber)
    {
        return true;
    }
    else
    {
        return false;
    }
}
```

# リファクタリング

一行にまとめました。

```C#:ClosedRange
public bool IsContain(int num)
{
    return num <= _upperNumber && num >= _lowNumber;
}
```

今回のこのテストなのですが、境界値によって少なくとも4通りほどのテストが必要と考えられるかと思います。
この時私はすべての境界値のテストをしてからリファクタリングに入りたいと思ったのですが、実際どのタイミングでリファクタリングをするのがいいのか気になりました。

結論としては**リファクタリングのタイミングに正解はない**とのことでした。

リファクタリングのタイミングとしては大きく２つあります。

1. **できたなと思ったタイミングでリファクタリングをする方法**
1. **ごちゃついてきたなと思ったタイミングで、先にリファクタリングしてから増やしていく方法**

t-wadaさん的にはまずごり押ししてからリファクタリングしていくのがおススメとのことです。何ができていくべきかとか見通しが立ってからリファクタリングした方が無駄がないからです。
ただ👆は、短時間で実装しきれるという自信がある場合に取る方法とのことです。

今何やったらいいかわからない…となったら、リファクタリングしてから先に進む方が良い場面もあるそうです。

つまり…
⇒ **両方のタイミングでリファクタリングができるようになろう！**

# ツリー構造にさせることで見やすくする大切さ

上でテストした内容は下の画像のような形でテストエクスプローラーに表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201826/33cd0f88-954a-3b4a-cb01-eefe31bdd75a.png)

レビューすることや品質保証を考えると、このテスト内容をツリー構造にすることは大切になってきます。
私が以前所属していた部署ではソースコードをかけない方がテストをしていたため、このツリー構造によって、**ツリーを見ただけで何のテストがされているか、実装されているか分かりそう**だなという感想を抱きました。

# TDDの不安が解消された、特に印象に残ったコメント

ずっと感じていた不安が解消された、私が個人的に印象に残った言葉を紹介します。

- **事前状態・入力・事後状態・出力**　この4つを押さえればだいたいのテストはかける

- **実務では無理にテストからかく必要はない**
ただ、**テストコードとプロダクトコードをかく時間が近ければ近いほどいい**。その日の内ならなお良し

- 設計を固くしてテストを容易にする。**テスト容易性が高いということは、よいアーキテクチャーといえる**。

# さいごに
直接講義をしていただけたことによって、モヤモヤが解消されたのが何よりも素晴らしかったなと思いました。
最後にt-wadaさんが**質とスピード**に関しての講義もあるというお話をされていたので、来年はそちらも触れたいところです。
(忘れないうちに年内にギリギリまとめられて良かった。良いお年を！)

# 参考
- [見てわかるテスト駆動開発(TDD Boot Camp 2020 Online #1 基調講演/ライブコーディング)](https://www.youtube.com/watch?v=Q-FJ3XmFlT8&t=1145s)
- テスト駆動開発　Kent Beck (著), 和田 卓人 (翻訳)