OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerのリソースを一括削除するエイリアス

Dockerを学習中で、[`コンテナ`, `イメージ`, `ボリューム`, `ネットワーク`]
といったリソースを一括削除したいときがあったので、エイリアスを作りました。

## 準備

.bashrc に 以下を追記します。

``` .bashrc
#===============================================================================
# Add docker alias
#===============================================================================
alias dps='docker ps -a'
alias dv='docker volume ls'
alias di='docker images'
alias dn='docker network ls'

alias dpr=_dockerRemoveResources
function _dockerRemoveResources() {
    if [ "$1" = "prn" ]; then
        _dockerRemovePrune
    elif [ "$1" = "con" ]; then
        _dockerRemoveContainers
    elif [ "$1" = "img" ]; then
        _dockerRemoveImages
    elif [ "$1" = "vol" ]; then
        _dockerRemoveVolumes
    elif [ "$1" = "net" ]; then
        _dockerRemoveNetworks
    elif [ "$1" = "all" ]; then
        _dockerRemoveAllForce
    else
        echo 'need target: [prn, con, vol, img, all]'
    fi
}

function _dockerRemovePrune() {
    docker container prune -f
    docker container ps -a
    docker volume prune -f
    docker volume ls
    docker image prune -f
    docker image ls
    docker network prune -f
    docker network ls
}

function _dockerRemoveContainers() {
    echo -e "\n[Containers]"
    remove_targets=`docker container ps -aq`
    test -n "$remove_targets" && docker rm -f $remove_targets
    docker container ls
}
function _dockerRemoveImages() {
    echo -e "\n[Images]"
    remove_targets=`docker image ls -q`
    test -n "$remove_targets" && docker image rm -f $remove_targets
    docker image ls
}
function _dockerRemoveVolumes() {
    echo -e "\n[Volumes]"
    remove_targets=`docker volume ls -q`
    test -n "$remove_targets" && docker volume rm -f $remove_targets
    docker volume ls
}
function _dockerRemoveNetworks() {
    echo -e "\n[Networks]"
    docker_network_list=`docker network ls | awk 'NR>1 {print $2}'`
    remove_targets=`echo -e "${docker_network_list}" | grep -v -e '^bridge$' -e '^host$' -e '^none$'`
    test -n "$remove_targets" && docker network rm $remove_targets
    docker network ls
}
function _dockerRemoveAllForce() {
    _dockerRemoveContainers
    _dockerRemoveImages
    _dockerRemoveVolumes
    _dockerRemoveNetworks
}


```

## 使い方

dpr [削除するリソース]

```
# すべて削除(危険)
dpr all

# 使ってないものだけ削除
dpr prn

# コンテナだけ削除
dpr con

# イメージだけ削除
dpr img
```

## 内容について

[コンテナ, イメージ, ボリューム, ネットワーク] で
4つすべてか、1つだけ選んで削除できるようにしています。

#### リソースとメソッドの対応

| リソース | メソッド |
| --- | --- |
| コンテナ | _dockerRemoveContainers |
| イメージ | _dockerRemoveImages |
| ボリューム | _dockerRemoveVolumes |
| ネットワーク | _dockerRemoveNetworks |

#### 7行目まで

dps, di, dv, dn は
各リソースを表示するエイリアスです。お好みの名前で登録してください。


#### 8行目以降

`dpr` こいつが一括削除するエイリアスです。
エイリアスに対して、_dockerRemoveResources() という関数を登録してます。

_dockerRemoveResources()の中で、
リソースに対応したメソッドを呼び出しています。

#### _dockerRemoveNetworks について

デフォルトネットワーク(bridge, host, none) は
削除できなかったり、エラー出たりするので、grep -v してます。


## 備考

Dockerコマンドが長くてめんどい場合は、
Makefileを書いて楽しようみたいな情報が出てきましたが、
使いどころがあんまりよくわからなかったです。

bash-completion入れてたら、
コマンドライン補完が使えるので、入れると幸せになれるかもしれません。
[docs.docker.jp | コマンドライン補完](https://docs.docker.jp/compose/completion.html)
vivadoのsimが重いので、サードパーティのsimを使ってみた

# vivadoのguiが重すぎる
今の開発環境は、手元のPCからVPN経由RDPで会社のWindows PCに接続、会社のWindows PCからsshでLinuxサーバに入ってそこでVivadoを起動している。ほかのguiアプリケーションではストレスに感じることはほとんどないのだが、vivadoに関していうと非常に遅い。

コーディングや合成であれば大した操作はないので我慢できるのだが、問題なのはシミュレーション。VivadoのIPを使用したデザインのためvivadoのsimulatorを使うのが楽なのだが、この遅さはいかんともしがたい。

そこでvivadoで作成したデザインを(リモートでの動作速度にストレスの少ない)サードパーティ製のシミュレータで実行する方法を調べた。

https://japan.xilinx.com/support/documentation/sw_manuals_j/xilinx2018_2/ug900-vivado-logic-simulation.pdf

# PATHの設定

いきなりだがここで躓いた。この後の操作で、Vivadoから使用するシミュレータパスを設定するのだが、そもそも\$PATHに登録されていないとだめらしい。ということで、Vivado起動前に\$PATHにツールパスを通しておくことが必要。

今回はcadenceのxceliumを使用する。vcsでもmodelsimでも大枠は同じはず。もともと使い慣れているvcsでやろうとしたが、vcsのバージョンとvivadoのバージョンがあわなかったので、今回はxceliumで進める。

# vivadoの設定

xceliumのバイナリにパスを通した状態でvivadoを起動。Tools→Compile Simulation Librariesで以下の項目を設定して、ターゲットのシミュレータ向けにXilinx IPのsimmodelをコンパイルする。

- Simulator: xcelium
- Language: verilog
- Compiled library location: \<project_path\>/\<project_name\>.cache/compile_simlib/xcelium
- Simulator executable path: \<path to xmsim\>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996063/cc17b57e-a07e-d9ca-12df-56fedc9ed749.jpeg" width="400">

続いて、シミュレータをデフォルトのxTools→Settingsで以下2項目を設定。
Project Settings→Simulationで、
- Target simulatior: xcelium
- Compiled library location: \<project_path\>/\<pronect_name\>.cache/compile_simlib/xcelium

Tool Settings→3rd Party Simlatorsで
- Install Paths→Xcelium: \<path to xmsim\>
- Default Compiled Library Paths→Xcelium: \<project_path\>/\<pronect_name\>.cache/compile_simlib/xcelium

＃結構重複しているので、どちらかだけでよいのかも
![図2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/996063/d9e5f3d6-5975-0007-482a-a09d35d0decc.jpeg)

この状態でシミュレーションを実行すると、simvisionが立ち上がる。Vivadoでシミュレーション実行までは重たいが、simvisionは単独で立ち上げたときと同様で、サクサク動いてくれる。

ただ、RTLを修正してsimを再実行する際にsimvisionを落とさないといけなさそうなのと、デフォルトで1階層しか波形をとってくれないので、いまいち取り回しが良くない。次はこのあたりの仕組みを確認する。
ド忘れしていたRubyの基礎5選②

どうも、三町哲平です。

https://qiita.com/TeppeiMimachi/items/bfa9c178826b5b5eec8e

ド忘れしていたRubyの基礎5選の第2弾です。

今回も引き続き、コチラの問題を解く際を想定
[(4) Two Sum - LeetCode](https://leetcode.com/problems/two-sum/)

解き方は、コチラを参照
[RubyでLeetCodeやってみる-TwoSum - Qiita](https://qiita.com/Wa_takumi/items/5c8283ca9d455b955742)
[LeetCodeでRubyの勉強をしてみた - Qiita](https://qiita.com/SotaMakino/items/db8c26b314fe0d48ad54)

# 1. has_key?メソッド
```ruby
planet = { Mercury: 'emerald',　Venus: 'diamond', Jupiter: 'Yellow sapphire' }
p planet.has_key?(:Mercury)
p planet.key?(:Mercury)
p planet.include?(:Mercury)
p planet.member?(:Mercury)
#=>
true
true
true
true
```
メソッド機能としては、__has_key?, key?, include?, member?__は、全て同じ。

引用及び参考記事:[Rubyでハッシュのキーを存在確認する方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン)](https://techacademy.jp/magazine/20159)

# 2. fetchメソッド

fetchでは、ハッシュのキーを指定して紐づくバリューを取得しています。

```ruby
fruits = { "apple" => 100, "orange" => 80, "melon" => 450 }
 
puts fruits.fetch("apple")
puts fruits.fetch("orange")
puts fruits.fetch("melon")
# => 100
# => 80
# => 450
```
引用及び参考記事:[はじめてのRuby！fetchメソッドの使いかたをマスターしよう！ | 侍エンジニアブログ](https://www.sejuku.net/blog/58930)

fetch => 読み込む # Google翻訳より

# 3. each_with_indexメソッド

eachループで回しつつ、それぞれのデータに番号を振ることが出来ます。

```ruby
fruit = ["りんご", "みかん", "いちご"]
fruit.each_with_index do |item, i|
 "#{i}番目のフルーツは、#{item}"です。
end
# => 0番目のフルーツは、りんごです。
# => 1番目のフルーツは、みかんです。
# => 2番目のフルーツは、いちごです。
```
引用及び参考記事:[each_with_indexの使い方 - Qiita](https://qiita.com/tsuchinoko_run/items/5cef7dd9d8baf48ffde7)

# 4. empty?メソッド

Hashが空かを調べる事ができます。

```ruby
menu = {"うどん" => "300円", "ラーメン" => "500円", "パスタ" => "800円"}
p menu.empty?
#=> false
```
引用及び参考記事:[RubyのHashとは？Hashの概要と基本操作を解説｜TECH PLAY Magazine ［テックプレイマガジン］](https://techplay.jp/column/569)

# 5. eachメソッド

```ruby
オブジェクト.each{|変数|
  実行する処理1
  実行する処理2
}

# 又は次のように記述することも出来ます。

オブジェクト.each do |変数|
  実行する処理1
  実行する処理2
end
```

「each」メソッドは配列や範囲オブジェクトなどで用意されているメソッドであり、オブジェクトに含まれている要素を順に取り出します。

```ruby
(18..20).each{|num|
  print("num = ", num, "\n")
}

print("\n")

# => num = 18
# => num = 1９
# => num = 20
```
引用及び参考記事:[eachメソッド - 繰り返し - Ruby入門](https://www.javadrive.jp/ruby/for/index5.html)

https://qiita.com/TeppeiMimachi/items/a0a449a1d2f0897fa6e2
C++で、実行中に作成した文字列をassertで出力する方法

**※本記事では、「ファイルを読み込み、成否をbool型で返すLoadFile関数」があると仮定して解説する。**
# assertの概要
(Visual)C++のassertマクロは、エラー箇所で自動的に実行を停止することができる、便利なデバッグ用機能だ。

```cpp:assert関数のもっともシンプルな利用例
// ※LoadFile関数は、ファイルを読み込み、成否をbool型で返す関数とする
bool loadResult = LoadFile("config.txt");
// assertマクロ関数は、引数がtrueだったときのみ動作する
assert(loadResult);

//---------------------------------------
// assert出力結果抜粋：LoadFile(loadResult)
```

上記のソースではエラーメッセージとして分かりづらい。
そこで、assertの動作条件がtrueかfalseかであることを利用して、このような使い方もできる。

```cpp:assertで任意の文字列を表示する
// ※LoadFile関数は、ファイルを読み込み、成否をbool型で返す関数とする
if (!LoadFile("config.txt"))
{
	// assertマクロ関数は、引数がtrueだったときのみ動作する
	assert(0 && "設定ファイル読み込み失敗");
}

//---------------------------------------
// assert出力結果抜粋：0 && "設定ファイル読み込み失敗"
```

# 実行中に作成した文字列をassertできない
さて、ここで本題である。
今回の例の場合、「読み込みに失敗したファイル名」をassert画面で表示したいときがあるだろう。
とりあえず文字列を渡しておけば良さそうに見えるので、思った通りに書いてみる。

```cpp:うまくいかない例
// ※LoadFile関数は、ファイルを読み込み、成否をbool型で返す関数とする
std::string filename = "config.txt";
if (!LoadFile(filename))
{
	std::string errorMsg = "読み込み失敗：" + filename;
	assert(0 && errorMsg.c_str());
}

//---------------------------------------
// assert出力結果抜粋：0 && errorMsg.c_str()
```

errorMsg.c_str()の戻り値が展開されず、そのままソースコードの内容が展開されてしまった。

# とりあえず解決方法

先にちゃんと動いてくれる例を提示しておく。
assertではなく、_wassertを使うことになる。
結論としては、使いやすい自作assert作るしかないんですね……

```cpp:実行中に作成した文字列をassertで出力する
// ※LoadFile関数は、ファイルを読み込み、成否をbool型で返す関数とする
std::string filename = "config.txt";
if (!LoadFile(filename))
{
	// エラーメッセージ
	std::string errorMsg = "読み込み失敗：" + filename;
	
	//ワイド文字列に変換
	WCHAR* _wtext = new WCHAR[strlen(errorMsg.c_str()) + 1];
	mbstowcs_s(nullptr, _wtext, strlen(errorMsg.c_str()) + 1, errorMsg.c_str(), _TRUNCATE);
	
	// _wassertを使って、文字列出力
	// (現在のファイルや行数は__FILE__マクロと__LINE__マクロで取得可能)
	_wassert(_wtext, _CRT_WIDE(__FILE__), (unsigned)(__LINE__));

	// ワイド文字列を解放
	delete[] _wtext;
}

//---------------------------------------
// assert出力結果抜粋：読み込み失敗：config.txt
```

# 超絶簡易な解説

以下、上記のソースの簡易な解説。

## assertマクロの中身

まずは、assertマクロが何故このような挙動をするのか、中身を見て確認してみよう。

```cpp:assertマクロのソース
#define assert(expression) (void)(                                                       \
        (!!(expression)) ||                                                              \
        (_wassert(_CRT_WIDE(#expression), _CRT_WIDE(__FILE__), (unsigned)(__LINE__)), 0) \
    )
```

ここで着目したい点は、以下の４点。

* 本質的には**「_wassert」関数を使ってassertを出力している**こと。
* _wassert関数の各引数の文字列は、**「_CRT_WIDE」マクロ関数でワイド文字列に変換**してから渡していること。
* assertマクロの引数expressionが、**「#」でソースコード上の記述そのままで出すようになっている**こと。
* 該当する箇所の**ファイル名と行数を、マクロ「\_\_FILE\_\_」「\_\_LINE\_\_」で取得している**こと。

これを踏まえると、「自力で_wassert関数を呼び出す。ただし、文字列はワイド文字列に変換する必要がある。」ということだ。

ただし、ワイド文字列に変換する**「_CRT_WIDE」マクロ関数は、本質的には「文字列リテラルをの先頭に「Ｌ」を追加しているだけ」**である。
つまり、「\_CRT\_WIDE(errorMsg.c_str())」 のようにシンボル名を入れてしまうと「LerrorMsg.c_str()」としてコンパイルされることになり、コンパイルエラーが発生する。
すなわち、**自分でワイド文字列に変換する処理を書いてあげる必要がある**。
今回はmbstowcs_s関数を使用した。

# 結論

つまり、自作assert作れってことですね、ハイ。
【jQuery】セレクトボックス

```javascript
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Shopping list example</title>
  </head>
  <body>
    <select id="selectCountry">
      <option value="0">選択してください</option>
      <option value="1">日本</option>
      <option value="2">アメリカ</option>
      <option value="3">中国</option>
      <option value="4">ロシア</option>
    </select>


    <script src="https://code.jquery.com/jquery-3.3.1.js"></script>
    <script>
      $('#selectCountry').change(function(e) {
        // 値を取得
        // let selectedVal = $(this).val();
        let selectedVal = e.target.value;

        // テキストを取得
        let selectedText = $('option:selected', this).text();
        // let selectedText = $(this).children(':selected').text();
        
        console.log(selectedVal);
      })
    </script>
  </body>
</html>
```
Azure IoTHubから受け取ったデータをAzure Functionsで受け取る

# はじめに
> 前回は、「[Azure IoTHubを触ってみた](https://qiita.com/arakirai1128/items/05f05eb40063c3037516)」をやりました。
今回は、IoTHubに送信したデータをAzure Functionsで受け取ってみようと思います。

# アジェンダ
1. Functionsアプリの作成
1. 関数を作成
1. 動作テスト

# Functionsアプリの作成

1. リソースの作成からFunctionsアプリをクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/528f30eb-0a5c-de6c-f7f3-9241a41dc3bb.png)

2. 作成に必要が表示されるので、埋めていきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/f7b730f5-ce89-1f29-62d3-4f1fde307e96.png)

3. 確認できたら作成ボタンを押します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/43ce0b20-fc90-74f9-046e-846b23643d88.png)


4.リソースに移動をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/e744d34a-8a29-3b4a-ebe3-1b01ccbebbef.png)


# 関数を作成

5. 関数をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/cbcf1dca-7e1e-6300-2e60-31367af34220.png)


6. 追加ボタンをクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/082eef42-e736-fca0-630d-d6f4bb02a932.png)

7. 関数を作成するにあたり必要な項目を埋めていきます
  - 開発環境欄は、vscodeで開発することも可能ですが、この記事では「ポータルでの開発」で進めていきます
  - テンプレートの選択では、今回はIoT Hubを使用しているのでIoT Hub(event Hub)を選択します 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/74e8e52e-6531-68a3-655e-604d73c11ca1.png)

  - テンプレート選択でIoT Hubを選択するとテンプレートの詳細が表示されるので埋めてきます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/c5e8f46c-62c2-6e6f-4f68-0ddc65f455c1.png)

  - 「Event Hub connection」は、「New」をクリックし作成済みのIoTHubを選択し「ok」ボタンをクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/29eb2d80-c43e-4960-04fc-8d4faa5d1aef.png)

8. 全て埋めることができたら「追加ボタン」をクリックします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/20775126-776e-6936-d8e3-973feb4e7f5c.png)


# 動作テスト

9. 「コードとテスト」を選択します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/f6cb4e7e-241a-c7ed-90a5-368d53374427.png)


10. デフォルトでソースのテンプレートが用意されているのでそのまま使っていくので「ログ」ボタンをクリックし、ログを表示させます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/2e7d756d-38f3-b420-59b3-e48895e3452f.png)

11. データをIoT Hubに送信し、IoT Hubで受信されるたびに作成したfunctionsが起動しfunctionsでデータが受け取れているのがわかるかと思います

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533263/7399a95e-2a47-4e8a-46fb-8bad1788588b.png)

# まとめ
今回、初めてfunctionsを使ってみましたがこんなに簡単にできることに感動しました笑
次回は、functionsで受け取ったデータをAzure Cosmos DBに保存する所までやってみようと思います。
DatabricksにてPyCaretにおけるsetupの実行が終了しない事象への対応方法

## 概要
DatabricksにてPyCaretのsetupが完了しない場合には、"silent"と"html"の引数を設定することで解決します。

下記のPyCaretのissueに解決策が提示されていました。
[PyCaret in Azure Databricks issue · Issue #781 · pycaret/pycaret (github.com)](https://github.com/pycaret/pycaret/issues/781)



## エラー事象
下記のコードの実行が完了せず、実行したまま（Running command）となってしまう。

```python
from pycaret.regression import *
s = setup(data, target = 'charges', session_id = 123)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/63591107-233c-ac56-bad5-8e82b5400f65.png)

## 対応方法
"setup"の引数に", silent = True, html = False"を追記。

```修正後
from pycaret.regression import *
s = setup(data, target = 'charges', session_id = 123, silent = True, html = False)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c2c537fe-c5e2-d3c4-fb1e-54cb09f4dfd3.png)
【SwiftUI】CoreData エンティティの削除方法

たまにど忘れしてしまうので備忘録として残します。

◯◯.xcdatamodel ファイルを選択し、"ENTITIES"の中の削除したいエンティティを選択し

$\huge{Deleteキーを押す}$

だけです。これだけの事なのに何で忘れちゃうんでしょうね...
HTML セレクトボックスのデフォルト値を設定する

# 目的

- HTMLのセレクトボックスのデフォルト値を設定する方法をまとめる

# 方法

- そのままだとoption要素の最も上の内容をデフォルトで表示する。

    ```html
    <select name="stg">
        <option value="1">hogehoge</option>
        <option value="2">fugafuga</option>
        <option value="3">piyopiyo</option>
    </select>
    ```

- 下記のように表示される。

    ![Document.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/34a06c98-dcb4-fc3b-eae4-b187d3ce3d42.png)

- デフォルト表示したいoption要素に`selected`と記載する。例えば「piyopiyo」をセレクトボックスにデフォルト表示したい場合は下記のように記載する。

    ```html
    <select name="stg">
        <option value="1">hogehoge</option>
        <option value="2">fugafuga</option>
        <option value="3" seleced>piyopiyo</option>
    </select>
    ```

- 下記のように表示される。

    ![Document.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/c4d83faa-9743-fc82-e40a-d6784480ee58.png)

# 参考ソースコード

- 「piyopiyo」をデフォルト表示するソースを下記に記載する。

    ```html
    <!DOCTYPE html>
    <html lang="js">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <header></header>
        <main>
            <select name="stg">
                <option value="1">hogehoge</option>
                <option value="2">fugafuga</option>
                <option value="3" selected>piyopiyo</option>
            </select>
        </main>
        <footer></footer>
    </body>
    </html>
    ```
プロジェクトの錬金術師

## 受託開発の構造的問題

受託開発とは、お客様より製品の開発を請け負い対価を頂く開発形態です。
多くの場合、サービスの開発に対する予算が決まっていて、その予算内に収まる様に開発を行う事がPMの仕事となります。

IT業界では古くから人月という単位で開発コストを扱う風習があります。
一人の人間を一月動かすのにいくらかかる。このぐらいの開発規模だと何人必要という考え方です。

多くの異論はあるもののこれに変わる考え方は未だ見つかっていない状況です。

さらに困ったことに、わたし達はは１年に１度年を取ります。
年を取ると、給与はベースアップして欲しいものですが、開発力は案件力によってオーバースペックになったり、加齢とともに下がったりします。

人月ベースの考え方では、同一プロジェクトメンバーで同様のサービス開発を続けていた場合、どこかでコストが予算を上回ってしまい開発を継続できないという問題が発生します。


## プロジェクトの錬金術？

わたし達はその様な問題が起きても事業を継続するために開発コストを下げなければなりません。
開発のコストを下げる戦略は以下かと思います。

1. 類似する開発を受託する
    - コードの流用などで開発コストを下げる
    - ただし、類似製品は商品力が弱いため、予算も大幅に下るリスクがある

2. 新しい技術を取り入れる
    - （学習コスト < 従来の開発コスト）となるような技術を採用する
    - 枯れてない技術を採用するリスクは高い
    - 大規模案件では人員を集める難易度が上がる

3. 単価の安い若いスタッフを正しく教育する
    - あるべき姿
    - 昔は大規模案件が多かったのでやりやすかった
    - 短期・低予算案件では教育が難しい

さて、どの戦略が錬金術でしょうか。

`1`は焼き畑なので違いますね。
`2`は悪くないですが、丁度よい技術が存在するか、丁度よい技術を選択できるか、といった外的要因に大きく依存するし、そのプロジェクト限りでサスティナブルな戦略ではないですね。

では、`3`はどうでしょうか。

人月単位で線表を引く業界で新人を入れたプロジェクトのマネジメントは難易度が高いです。
しかし、実質0人月の新人をきちんと育て、0.2人月のアウトプットを出せるまでに成長させたとしたら、自分が何もしなくても毎月0.2人月稼いでくれる人が一人できます。また、0.2人月のアウトプットを出せるまでに成長した新人は、独学で成長した人間と違い、更なる若手を育ててくれます。
この活動は、コストを下げる活動と言うよりむしろ**錬金術**と言えるでしょう。


## まとめ

PMが実践すべきは`3`。単価の安い若いスタッフを正しく教育することかと思います。
※当然`1`、`2`も実施可能であれば実施した方がよいです。

毎年斬新なWebサービスがリリースされわたし達の「普通」は更新されます。
今あるものは新しく作る必要がなく、全く新しいものか、既存のものに機能追加したものを作る必要があり、顧客の要求仕様は肥大化し続けます。

一方で、個人差はありつつもある年齢から加齢とともに開発力は落ちます。
若手を育てることを放棄するのは緩やかな衰退を意味します。

目先の納期や予算にとらわれ育成に対する時間やコストが捻出できないことが多いかと思いますが、サスティナブルな組織を目指して活動していきましょう。
ローカルで通るRSpecがCircleCI上でフリーズしタイムアウトする（Docker環境）

#はじめに
右も左もわからない未経験エンジニアが書く初めての投稿です。
今後も膨大な勉強量の中で、気になったことや発見などを書いていこうと思います。

今回の記事は根本的な解決には至ってはおりませんが、
同じ問題に阻まれた方の助けになればと思い、メモを残しておきます。
間違いやこうした方が良いなどのご指摘も頂けると嬉しいです！

#開発環境
ruby 2.5.1
Rails 5.2.4.5
Docker version 20.10.6
RSpec 3.10

アプリの目的はsolidusを使用したECサイト作成の勉強です。
開発環境はDockerで整え、CircleCIでテスト後、HEROKUデプロイする流れです。
AWS S3とも連携してあります。

#問題点
ローカルでは問題なく通るrspecがgit push後に通るCircleCIでフリーズ（？）し、タイムアウトしてしまう事態が発生。

問題が発生するのは rspecのSetup database

```.circleci/config.yml
 - run:
     name: Setup database
     command: |
       docker-compose exec [ディレクトリ名] bash -c 'yes n | bundle exec rails g spree:install --migrate --seed --sample --auto_accept'
```

![スクリーンショット 2021-06-17 12.39.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1624943/d62cb836-8be1-1db8-55aa-9222e0805dcf.png)
フリーズする[WARNING]の所までは1分もかからず到達します、
なお、[WARNING]の内容は本件と関係ないと考えております（次のメジャーリリースへ向けてMoney.rounding_modeを変更してくれとの指示であり、様々なサイトでこれが表示されていてもテストが通っているため）
また、Too long with no output (exceeded 20m0s)になっていますが「もしかしたらただ単に処理の時間がかかりすぎているだけかも。。。」という淡い期待の産物ですのでスルーしてください。
___
####〜補足〜

```.circleci/config.yml
 - run:
     name: Setup database
     command: |
       docker-compose exec [ディレクトリ名] bash -c 'yes n | bundle exec rails g spree:install --migrate --seed --sample --auto_accept'
     no_output_timeout: 20m
```

と書き加えるとタイムアウト設定を変更出来ます。
___

#原因

```rb:config/environments/development.rb
config.cache_classes = false
(アプリケーションのクラスやモジュールをリクエストごとに再読み込みするか(=キャッシュしないかどうか)どうかを指定
)
config.reload_classes_only_on_change = false
(監視しているファイルが変更された場合にのみクラスを再読み込みするかどうかを指定)
```

を記述した。
（config.cache_classes = false　はdevelopmentモードではデフォルトなので実際に記述する必要はないと思いますが、今回の原因として考えられる要因のため記述しております）

参考にさせて頂いたサイト

https://railsguides.jp/configuring.html

#なぜ原因のコードを記述したか
アプリ開発していてコントローラーの可読性が悪くなって来たので、models配下にdecoratorファイルを作成
module_evalにてscopeで変数の定義をした所、decoratorファイルと、関連するコントローラの内容の変更が反映されなくなった。
反映させるためにはDockerコンテナの再起動が必要で、かなり手間が掛かるので何とかしたい
その解決方法の一つとして色んなサイトで原因のコードが紹介されていたので試してみました。

#なぜ原因だと判断したか
問題が発生する前と発生時のファイル差違を確認し、上記コードに目星を付けました。
問題が発生するブランチの上記コード二点を削除し　git push　した所、CircleCI上でも問題なくテストが通ったことからこの問題の原因と特定しました。

#原因を排除した結果

![スクリーンショット 2021-06-19 16.01.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1624943/36edc283-9470-e4b2-3f23-1c2731d00c1c.png)

原因排除前は21m11sでタイムアウトしていましたが、排除後は1m9sでクリアしています。

#解決策
原因のコードは使わず

```rb:config/environments/development.rb
#config.file_watcher = ActiveSupport::EventedFileUpdateCheckerを以下に変更
config.file_watcher = ActiveSupport::FileUpdateChecker
```

に変更することでDockerコンテナの再起動が必要なくなりました

Docker環境では
>volumeで共有ファイルとしてホスト側のディレクトリを仮想環境にマウントしており、この方式だと変更イベントが発生しないようです。故にファイルの変更を検知することができず、コンテナを再起動しないとソースコードの変更がされないという事態になります。

と勉強させて頂きました。ありがとうございます！

参考にさせて頂いたサイト

https://qiita.com/Kiyo_Karl2/items/147d604e625b8a55e12e


#残る疑問点
以下内容に関しては順次、解決次第追記していきます。
もしご教授頂けるのであればとても嬉しいです！
解決しない場合は改めて質問へ投稿させて頂こうと考えております。

1. なぜ原因のコードを記述するとフリーズしてしまうのか




#最後に
勉強を始めたばかりで知識もなく、拙い文章ですがアウトプットすることで頭の中を整理しつつ、どなたかのお役に立てれば良いなと思い投稿させて頂きました。
最後まで見て頂きありがとうございました！
僕がCSSフレームワークを嫌うただ一つの理由

最近Tailwindとやらが流行っているようなので、試しに使ってから批判してやろうと思ってドキュメントを読んだところ、結局この一点だけで試す気になれず終わったため、代わりにこれを書きました。

ちなみにBulmaとbootstrapを使ったことがあります。

# TL; DR

結論: **「HTMLは文書構造、CSSは体裁」という役割分担のもと、HTMLには可能な限りデザインに関する情報を記述したくない。**

# 2000年代のコーディング

僕がはじめて"ホームページ"を作ったのは、15年ほど前のことでした。

その当時は、ちょうどCSSが普及しはじめた頃でした。
「これからはCSSでデザインを当てるのがイケてるホームページ制作だぜ」的な、CSS＝最新技術な雰囲気があった気がします。

CSSそのものの歴史はもっと古いみたいですが、主要ブラウザのIEがこの時期にCSSをサポートし始めたようです。

(思い出レベルのため、間違っていたらすみません)

当時僕は、最新技術であるCSSにまだ追いつけず、↓こんなHTMLを書いていました。

```html
<div align="center">中央寄せにしたい要素</div>

<p>
  <font size="7">大きくしたい文字</font>
  <font color="red">赤くしたい文字</font>
</p>
```

CSSが普及する前は、上記のような、デザインをあてるためのタグや属性がありました。
それらは、CSSの普及とともに非推奨、廃止となりました。

# なぜCSSが登場した？

当時の僕のCSSに対する理解は、「同じスタイルを何箇所にも書かないで済む」「スタイルを使い回せて便利」あたりでした。

もし今、CSSの存在意義について説明を求められたら、「HTMLは文書構造、CSSは体裁」という役割分担の実現を真っ先に挙げると思います。
「スタイルを使い回せる」といったメリットはその役割分担による恩恵の1つだと思います。

> 文書の構造と体裁を分離させるという理念を実現するために提唱されたスタイルシートの具体的な仕様の一つ。
> ― wikipedia

# 僕が意識するClass名

その思想に従い、僕はHTML内にデザイン的要素を極力書かないように意識しています。

例えば、メニューボタンを作るとして、クリックされた要素が赤くなる、とします。

そんなとき、↓のようなHTMLを僕は書きたくありません。

```html
<ul class="menu">
  <li class="menu-item">Item1</li>
  <li class="menu-item">Item2</li>
  <li class="menu-item red">Item3</li>
</ul>
```

Item3はなぜ赤いんですか？「赤いから赤い」んですか？

いいえ、「クリックされているから赤い」んです。

だから、↓のように書きたいです。

```html
<ul class="menu">
  <li class="menu-item">Item1</li>
  <li class="menu-item">Item2</li>
  <li class="menu-item clicked">Item3</li><!-- または active とか -->
</ul>
```

前者はHTML(class名)がデザインに踏み込んでいますが、後者は自分の状態を示しているに過ぎません。

clickedなアイテムを赤にするか、太字にするか、あるいは何もしないかはCSS＝デザイン側に任せたいです。

# 時代を逆行するCSSフレームワーク

CSSフレームワークによって、再びHTMLに体裁が書き込まれる時代に逆戻りしてしまいました。

```html
<div class="grid grid-cols-1 sm:grid-cols-2 sm:px-8 sm:py-12 sm:gap-x-8 md:py-16">
  <div class="relative z-10 col-start-1 row-start-1 px-4 pt-40 pb-3 bg-gradient-to-t from-black sm:bg-none">
    <p class="text-sm font-medium text-white sm:mb-1 sm:text-gray-500">Entire house</p>
    <h2 class="text-xl font-semibold text-white sm:text-2xl sm:leading-7 sm:text-black md:text-3xl">Beach House in Collingwood</h2>
  </div>
  <div class="col-start-1 row-start-2 px-4 sm:pb-16">
    <div class="flex items-center text-sm font-medium my-5 sm:mt-2 sm:mb-4">
      <svg width="20" height="20" fill="currentColor" class="text-violet-600">
        <path d="M9.05 3.691c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.372 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.539 1.118l-2.8-2.034a1 1 0 00-1.176 0l-2.8 2.034c-.783.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.363-1.118l-2.8-2.034c-.784-.57-.381-1.81.587-1.81H7.03a1 1 0 00.95-.69L9.05 3.69z" />
      </svg>
      <div class="ml-1">
        <span class="text-black">4.94</span>
        <span class="sm:hidden md:inline">(128)</span>
      </div>
      <div class="text-base font-normal mx-2">·</div>
      <div>Collingwood, Ontario</div>
..
```

> 引用 https://tailwindcss.com/

`class="menu-item red"`すら嫌がる僕にとって、↑のようなHTMLは見たくもありません。

# おわりに

実用面を主軸においた要不要の議論については、僕も一応意見は持っているものの、他のTailwind否定派の記事が僕の言いたいことを十分に言ってくれているので、「HTMLがキモいから使いたくない」ってことだけ主張してみました。

CSSフレームワークファンの皆さん、ごめんなさい。
AI-900に合格した話

AzureのAI系サービスに関するベンダー資格AI-900に合格したので、その体験と自分で書いたまとめ記事の宣伝を書きます。


# AzureのAI系のサービスのカタログを覚えれば合格できた

最初に結論を書くと、機械学習の基礎的なこととAzureの基本的な使い方が分かっていれば、AzurenのAI系のサービスを整理するだけで取得できるお手軽な資格でした。

ちなみに機械学習の基礎的なこととは、「回帰、分類、クラスタリングの違い」とか、「前処理、学習、評価などの機械学習の流れ」で、なんとなくわかっていればOKです。

AI資格で有名なG検定と比較するとかなり初歩的なことしか聞かれません。また、AzureのこともAzureの一番基礎的な資格であるAZ-900と比較するとだいぶライトなことしか問われませんでした。

他の入門的なベンダー資格もそうなのかもしれませんが、要はAzureのAI系のサービス（Azure Machine LearningとCognitive Service）のカタログを覚えて、どのユースケースにはどのサービスが利用できるというこを理解すれば合格できます。

この試験ではまずは全体像をつかむのが重要で、実際にそれらを利用するのはまた別の機会に勉強してねという感じです。


# 合格するためにやったこと


-[Azure Learn](https://docs.microsoft.com/ja-jp/learn/certifications/exams/ai-900) 
-[Udemy講座：AI-900 Azure AI Fundamentals 5 practice tests](https://www.udemy.com/course/microsoft-certified-azure-ai-fundamentals-5-practice-tests/)

Azureも機械学習も、ちょっとぐらいは知識があるつもりなので改めて勉強する必要はないだろうと思いましたが、AI-900に合格するだけだったらちょっとも必要ないなと感じました。

合格するには70%正解する必要がありますが、「～するには次のうちどのサービスを利用しますか」的なAzureのサービスに関する知識問題が7割以上出題されるので、Azureの管理（リソースの仕様や権限など）や機械学習の問題は答えられなくても合格はできます。

ということで、そこら辺の知識はAzure LearnのAI-900のページをやっておけばいいと思います。ハンズオンで実際にAzureのリソースをいじるところもありますが、正直ここはやんなくてもいいです。

Udemyの講座は本番に近い内容の演習問題を1800円前後（セールで買えば）で買えるのでAzureの資格を勉強している人で利用している人は多いと思いますが、残念ながら日本語のものはなかったので英語のもので一番評価が高かったもので勉強しました。

と言ってもここまでやる必要はなかったかなという印象です。広く浅く体系的に抑えられればいいので、もうちょっとまとまっている資料が欲しかったです。

ということで自分で情報をまとめました。2万字近い長々とした文章ですが、試験に出る内容は網羅できたかなと思っています。

https://pickerlab.net/2021/06/12/test-preparation-for-ai-900/

AI-900の試験対策に役立てていただければ幸いです。



# AI-900受かったらもっとAzureを活かしたくなった

完全に、ベンダーの策略にハマってますが、AI-900のためにサービスのことを体系的に理解する、一つのサービスのドキュメントを読んでも見えてこない個々のサービスのメリット見えてきます。

この資格を取得したことで、今すぐ知識を開発に活かせるようには思えませんが自分のように経験の浅いエンジニアがクラウドを活かしていくためのきっかけづくりにはなるのではないでしょうか。
VS CodeのSFTP拡張機能でNo such fileエラーを回避

※より良い解決策を「 [2021/09/24追記](#20210924追記) 」に記載した。

Linux上のファイルをVisual Studio Codeで楽に編集するため、VS CodeからSFTPでアップロード／ダウンロードしたいと考えた。

- Windows 10 Pro 20H2
- Visual Studio Code 1.57.1
- SFTP 1.12.9 (SFTP/FTP sync, liximomo) 拡張機能

以下を参考にsftp.jsonを記述して、RemoteからLocalに同期を取った。

https://qiita.com/ishimasar/items/1324af16e19a59b220d3

これでVS Codeで編集する環境が整ったので、あるファイルを修正してUploadを実行したところ、No such fileと言うエラーが表示された。
sftpのエラーメッセージを確認すると、編集したファイルが実際には存在するのに、存在しないと言っている様子であることが確認された。

検索したところ、sftpの不具合（Nodeとの不整合）であるとの記事が見つかった。

https://blog.supersonico.info/?p=4578

この記事に記載の通り、sftp.jsの2918行で定義されているWriteStream関数に `options.autoDestroy = false;` と追記し、VS Codeを再起動することでエラーを回避することができた。

C:\Users\ユーザー名\\.vscode\extensions\liximomo.sftp-1.12.9\node_modules\ssh2-streams\lib\sftp.js

```js
function WriteStream(sftp, path, options) {
  :
  :

  // For backwards compat do not emit close on destroy.
  options.emitClose = false;
  options.autoDestroy = false;

  :
  :
}
```

なお、本記事は、現時点でQiitaには同様の記事が見つからなかったので、共有を広めるために記載したものである。

# 2021/09/24追記

アップデートが2019年から止まっているliximomo氏のSFTPに変わり、Natizyskunk氏によりforkされたSFTPが登場している。
現時点では、No such fileエラーが出ず、現在も維持管理が行われているため、こちらをインストールすることを推奨する。

https://marketplace.visualstudio.com/items?itemName=Natizyskunk.sftp

https://github.com/Natizyskunk/vscode-sftp

## 移行手順

1. liximomo氏のSFTPを削除
1. Natizyskunk氏のSFTPをインストール
1. VS Codeを再起動

（@taikisさん、ありがとうございました！）

# 2021/10/03追記

.vscode/sftp.json の "remotePath" で指定したサーバー側のパスをタイプミスしても、エラーにならず、新規ディレクトリと解釈される点に要注意である。
SFTP: Sync Remote -> Local を実行すると、サーバー側にはファイルがないので直ぐ正常終了となるため、指定したパスが間違っていることに気が付かない（SFTPプラグインの不正動作を疑ったらそこでハマる）。
SFTP: Upload Active File を実行すると、サーバー側に新しいディレクトリが作成されて、そこにファイルがアップロードされるので、ここでも指定したパスが間違っていることに気が付かない。（サーバー側の正しいディレクトリにあるファイルが更新されないが、ここでもSFTPプラグインの不正動作を疑ったらそこでハマる）。

エラーが起きないのに、意図した通りにアップロード／ダウンロードされない場合、 "remotePath" に指定したパスのタイプミスを最初に疑うべきである（自分への戒め）。
Rubyのクワインを読む

## はじめに

Rubyのクワインとして紹介されていた2つを解読してみました。
割と頭がこんがらがるので、順を追って書いていきます。

コードは下記から拝借しました。
https://stackoverflow.com/questions/2474861/shortest-ruby-quine/2475931#2475931

## 1つ目

### コード
```ruby
_="_=%p;puts _%%_";puts _%_
```

### 解説

まず、演算子の前後にスペースを入れます。
セミコロンは改行します。

```ruby
_ = "_=%p;puts _%%_"
puts _ % _
```

1行目は変数`_`への代入式でした。
2行目で参照しているので、展開します。

```ruby
puts "_=%p;puts _%%_" % "_=%p;puts _%%_"
```

`%`演算子の挙動はsprintfと同様です。フォーマット、変数の順です。
`%p`はObject#inspectの結果で置き換えられます。
`%%`は%自身を出力します。

`%p`の前後で分割して、敢えて文字列連結で書くとこうなります。

```ruby
puts "_=" + "_=%p;puts _%%_".inspect + ";puts _%_"
```

`inspect`の結果を展開して

```ruby
puts "_=" + "\"_=%p;puts _%%_\"" + ";puts _%_"
```

文字列連結します。

```ruby
puts "_=\"_=%p;puts _%%_\";puts _%_"
```

あとは`puts`の出力結果を見るだけです。

```ruby
_="_=%p;puts _%%_";puts _%_
```

## 2つ目

### コード
```ruby
puts <<2*2,2
puts <<2*2,2
2
```

### 解説

このコードはヒアドキュメントを使っています。
1行目の`<<2`が開始ラベル、2行目が本体、3行目が終端行です。
また、Rubyでは開始ラベルが値を返すので、続けて`*2,2`と処理を書いています。

まず、演算子の前後等に空白をいれます。

```ruby
puts <<2 * 2, 2
puts <<2*2,2
2
```

ヒアドキュメントを展開してみます。
改行があるので注意をしつつ

```ruby
puts "puts <<2*2,2\n" * 2, 2
```

`*`演算子は文字列を指定した回数分繰り返します。

```ruby
puts "puts <<2*2,2\nputs <<2*2,2\n", 2
```

あとは`puts`の実行結果を見るだけです。
与えられた引数を続けて出力します。

```ruby
puts <<2*2,2
puts <<2*2,2
2
```

## 参考
- Shortest ruby quine. (n.d.). Stack Overflow. Retrieved June 19, 2021, from https://stackoverflow.com/questions/2474861/shortest-ruby-quine/2475931#2475931
- class String (Ruby 3.0.0 リファレンスマニュアル). (n.d.). docs.ruby-lang.org. Retrieved March 24, 2021, from https://docs.ruby-lang.org/ja/latest/class/String.html
由来で覚えるlinux用語集

随時更新予定。。。

ls = list | list segments(コメント欄参照)
ln = link
mv = move
cd = change directory
cp = copy
rm = remove
mkdir = make directory
rmdir = remove directory
chown = change owner
chmod = change mode
cat = catenate || concatenate
tac = catの逆コマンド(ファイルを逆から出力)
grep = "g/RE/p" || globally search a regular expression and print
ping = 潜水艦などで使われるアクティブソナーの発する音波
sh = shell
bash = Bourne again shell
su = substitute user || switch user || super user
sudo = substitute user do || switch user do || super user do
vi = visual
sed = stream editor　入力(ストリーム)に対して編集を行う
uniq = unique
awk = Aho, Weinberger, Kernighan 開発者3人の名前
man = manual
pwd = print working directory
bg = background
fg = foreground
ps = process status
du = disk usage
df = disk free
dd = IBMの汎用機のJCLのDD文
passwd = password
tar = tape archive
wall = write to all users
xargs = execute arguments
eval = evaluate
uname = UNIX name
tr = translate(変換する)

/bin = binary
/sbin = system binary || static linked binary
/usr = user
/var = variable
/lib = library
/tmp = temporary
/opt = optional 追加インストールしたアプリケーションなどを配置(ユーザー各自のオプション)
/dev = device
/etc = etcetera(その他) 設定ファイルが置かれる
/proc = process
/sys = system
.so = shared object
.a = archive

tty = teletypewriter (参考：https://e-words.jp/w/TTY.html)
stdin = standard input　標準入力
rc = run command 例 .bashrc
dmesg = display message
nl = number line
od = octal dump
cpio = copy input output
tee = 標準出力からファイル出力をT字のように分岐させるから。
ldd = list dynamic dependencies
ld = link editor || LoaD
curl = client for URL
wget = Web get
spool = データを一時的に貯めておく場所
chage = change password age
wc = word count(オプション：-c=char型, -w=words, -l=lines)

netstat = network statistics(ネットワークの統計情報)
ss = socket statistics(ソケットの統計情報)
tc = trafic control
lsof = list open files
dig = domain information groper(※grope=手探りする)
nslookup = name server lookup
getent = get entries

head = 頭
tail = 尾
rev = reverse

fdisk = format disk
cfdisk = curses format disk 
gdisk = GPT fdisk
parted = partition editor?
fsck = file system check
tune2fs = tune file ext2 file system parameters?
etc/mtab = mounted file system table
etc/fstab = file system table
pandas-profilingの日本語文字化け対応

#0.Intro
ProbSpaceやNishikaのデータは大抵日本語なのでグラフに日本語が表示されないのは割と致命的です、全部アルファベットに置き換えるなんて面倒ですし。
pandas-profilingの日本語文字化けへの対応方法は色々書かれていますが、情報が古かったり、matplotlibの日本語対応、seabornの日本語対応とほぼ同義なので逆に情報が混乱していたので纏まった記事も有用だろうと思って書きました。

#1.当方の環境

Windows上のVScodeからDocker経由でUbuntu Serverに接続する形で作業してます。

__Ubuntu Server 20.04__

- Docker:kaggle/python-gpu-build
 
- python:3.7.10

- matplotlib:3.4.2

- seaborn:0.11.1

- pandas-profiling:3.0.0

__Windows10__

- VSCode + Jupyter

#2.手順
以下手順です。基本的にVSCode側ですることはありません。

##2.1.そもそも日本語フォントが入っているか確認。

[Python matplotlib 使えるフォント一覧の作成](https://qiita.com/damyarou/items/0e744da0b45849c28b19)

##2.2入ってなければフォントをインストール

```
apt install -y fonts-ipafont
```
##2.3pandas_profilingで当該フォントを扱えるようにする

/opt/conda/lib/python3.7/site-packages/pandas_profiling/visualisation/context.py (L40-L46)

```
        "font.sans-serif": [
            "Arial",
            "Liberation Sans",
            "Bitstream Vera Sans",
            "sans-serif",
            "IPAMincho",
        ],
```
##2.4.pandas_profilingから呼ばれている(らしい)seabornでも扱えるようにする。

/opt/conda/lib/python3.7/site-packages/seaborn/rcmod.py (L205-L207)

```
        "font.family": ["IPAMincho"],
             "font.sans-serif": ["Arial", "DejaVu Sans", "Liberation Sans",
                                 "Bitstream Vera Sans", "sans-serif","IPAMincho"],
```

##2.5.matplotlibのフォントキャッシュ削除

```
rm -f /root/.cache/matplotlib/fontlist-v330.json
```
##2.6.Jupyter再起動
僕の場合はVSCode上ですのでノート開き直しでOKでした。

#3.備考
フォントの設定なので

```
import seaborn as sns
sns.set(font='IPAMincho')
```
が要りそうなものですが、そもそもコードを弄っているのでデフォルトが入れ替わるのでしょうね、上記の設定無くても日本語表示されました。
Javascriptによるキーイベント受け取りのテストコード

## 備忘録
参考元: [JavaScriptでキーイベントを受け取る方法を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/19613)

参考元のコードを実行すると、ShiftキーやCtrlキーのみを押したとき「keydown: Shift + Shift」「keydown: Ctrl + Control」と出て、少しモヤモヤする。
![table3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577794/7334baf2-a342-edc5-35b5-d59582646547.png)

そこで、ShiftキーやCtrlキーのみを押したときのコンソール出力を変更する。

```
<!DOCTYPE html>
<html>
  <head>
    <script>
      document.addEventListener('keydown', (event) => {
         var keyName = event.key;
 
         if (event.ctrlKey) {
            //  処理を変更
             if(keyName === "Control"){
                console.log(`keydown:Ctrl`);
             }else{
                console.log(`keydown:Ctrl + ${keyName}`);
             }
         } else if (event.shiftKey) {
            //  処理を変更
            if(keyName === "Shift"){
                console.log(`keydown:Shift`);
             }else{
                console.log(`keydown:Shift + ${keyName}`);
             }
         } else {
           console.log(`keydown:${keyName}`);
         }
       });
 
       document.addEventListener('keypress', (event) => {
         var keyName = event.key;
 
         if (event.ctrlKey) {
           console.log(`keypress:Ctrl + ${keyName}`);
         } else if (event.shiftKey) {
           console.log(`keypress:Shift + ${keyName}`);
         } else {
           console.log(`keypress:${keyName}`);
         }
       });
    </script>
  </head>
  <body>
  </body>
</html>
```

## 実行結果

![table4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577794/73773d99-21be-3040-e354-42c078463aec.png)


これで少しすっきり。ShiftもしくはCtrlキーのみを押された時の挙動が分かりやすくなった。
綺麗なコミットログを作りたいときのgitテクニック

## これは何

僕は開発作業をしているとき、PRをあげるまでの開発途中は`wip`コミットに変更を記録していき、最後にコミットを仕上げていくような作業をよくします。

初めからコミットを綺麗に書きながら開発ができれば良いのですが、

https://qiita.com/suzuki-hoge/items/cc91877ce69527ced692

にあるようなコミットログを仕上げていこうと思うとどうしても最後にコミットログを整理したくなります。

この記事はこのようにgitを使うと綺麗なコミットログを作れるよ、というTipsです。
具体的にこういうコミットを作ると良いよ、みたいな話はこの記事ではしません。

僕はこのような工程でPRを出す前にコミットログを作っています。

- `git rebase -i`で作業中のコミットを全て一つのコミットにsquashする
- `git reset HEAD~`で一度コミットを取り消す
- `git add -p`で作りたいコミットごとに変更をstageにあげていく
- コミットを作成する

## `git rebase -i`で作業中のコミットを全て一つのコミットにsquashする
まずは作業をしたときに作ってしまったコミットを一旦整理していきます。
作業中にwipコミットをだらだら作っていると、こんな感じのコミットログができていたりすると思います。

```
commit 166f51a3fead14e70b3e73a98646edb9088d2351 (HEAD -> hoge)
Author: getty104 <>
Date:   Sat Jun 19 17:18:50 2021 +0900

    wip

commit 78be54733b9e9deaeb7a553c8297b2088dc59ea0
Author: getty104 <>
Date:   Sat Jun 19 17:18:40 2021 +0900

    wip
```

このようなコミットを、`git rebase -i`で一つのコミットにsquashしていきます。
`rebase -i`についてはこちらをご覧ください。

https://qiita.com/tsuuuuu_san/items/f708a9f7ea8ab8eb6945

以下のようにはじめのコミット以外を`fixup`で一つにまとめていきます。

```
pick 78be547 wip
fixup 166f51a wip

# Rebase 1ee1d37..166f51a onto 1ee1d37 (2 commands)
```

## `git reset HEAD~`で一度コミットを取り消す
前の項目でまとめ上げたコミットを、一度取り消します。

`git reset HEAD~`を実行すれば取り消しができます。

## `git add -p`で作りたいコミットごとに変更をstageにあげていく
おそらく変更をstageにあげていく際、`git add ファイル名`でファイルごとあげていくことが多いと思います。
しかし、綺麗なコミットを作り上げたいとなると、ファイル単位ではなく、行単位でコミットログを作っていきたい場合が多いです。
そこで`git add -p`を用います。この記事の山場です。

`git add -p`とは、unstageの変更に対して対話形式でstageに上げるかどうかを選んでいけるオプションです。

`git add -p` を実行すると、このような表示がされます。

```diff
diff --git a/foo b/foo
index e69de29..a5e2a02 100644
--- a/foo
+++ b/foo
@@ -0,0 +1,3 @@
+foo
+hoge
+bar
(1/1) Stage this hunk [y,n,q,a,d,e,?]?
```

このような感じでstageに上げるかどうかをいくつかのコマンドで決定していくことができます。
細かいオプションについてはこちらをご覧ください。

https://qiita.com/crifff/items/1abf08bca4ce51db4775

ここでは一旦 `s`、`y`、`e`コマンドについて説明していきます。

`s`コマンドは、差分を行単位で切り分けてより細かいレベルでステージに上げるかどうかを決められるコマンドです。
これを用いることで、ファイル内の行ごとに差分をstageにあげていくことができます。

そして`y`コマンドは表示された差分をそのままstageに上げるコマンドです。変更をそのままstageにあげてしまって問題ない場合は`y`を選択しましょう。

そして一番便利なのが`e`コマンドです。`e`コマンドはstageに上げる変更を自分で指定できる方法です。
上の差分の中で、`foo`と`bar`だけをstageにあげたい場合、どのようにすると良いでしょうか？`s`差分を行の境界で切離分けるので、今回のように間の`hoge`だけは入れたくない、みたいな場合は利用できません。こんなときにまさに`e`コマンドは真価を発揮します。

上の変更で`e`を選択すると、エディタが開きます。そこで差分として取り込みたい行のみ残し、取り込みたくない行は消し、保存をすることでstageにあげたい差分だけを取り込めます。この際エディタで差分を変更しても実際のファイルが書き変わるわけではないのでご安心ください。

```
# Manual hunk edit mode -- see bottom for a quick guide.
@@ -0,0 +1,3 @@
+fuga
+hoge <-ここを消す
+baz
# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
# 
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging.
# If it does not apply cleanly, you will be given an opportunity to
# edit again.  If all lines of the hunk are removed, then the edit is
# aborted and the hunk is left unchanged.
```

## コミットを作成する
stageにあげ終わったら最後はコミットを作成するだけです。適切なコミットメッセージを書きましょう。
DSPBufferSizeの具体的なサイズ

#DSP Buffer Sizeを「Best Latency」にしたらノイズが乗った
　正確に言えばノイズが乗るときと乗らない時がありました。
　これ自体はよくある話ですが、どこを見ても「Good Latencyにしろ」位しかないので少し詳しく調べてみました。
　結論から言えば「SystemSampleRateを下げる」と言う対策をとりました。

# DSP Buffer Sizeを測定するコード
　こちらの関数を使います
　[GetDSPBufferSize](https://docs.unity3d.com/ScriptReference/AudioSettings.GetDSPBufferSize.html)

# 環境
 OS: Windows 10 Pro
 CPU: i5 9600K
 メモリ: 32GB
 オーディオインターフェース: FOSTEX HP-A3(USB接続)

# 測定結果
||bufferLength|numBuffers|
|:--|--:|--:|--:|
|Best Latency|256|4|
|Good Latency|512|4|
|Best Performance|1024|4|

# スクリプトで設定する
　前述の[GetDSPBufferSize](https://docs.unity3d.com/ScriptReference/AudioSettings.GetDSPBufferSize.html)にも書かれていますが、現在はスクリプトからの変更には対応していません。[こちらを参照して](http://mizusoba.blog.fc2.com/blog-entry-709.html)スクリプトからBufferSizeを設定することは出来ましたが、適切な値でないとクラッシュします。サポート範囲外でもあるので使用しない方が良いでしょう。
```SetBufferSize.cs
private void SetBufferSize(int bufferSize)
{
    AudioConfiguration ac = AudioSettings.GetConfiguration();
    ac.dspBufferSize = bufferSize;
    AudioSettings.Reset(ac);
}
```

# 具体的な対策
　どうしてもノイズなくレイテンシーが欲しい場合には、「SystemSampleRateを下げる」が私の環境では有効でした。0に設定していましたが、デフォルトでは48000になるようです。CD音源ですら44100ですから、よっぽど音質にこだわるゲームじゃない限りはこの値まで低くしても十分だと考えています。

　他に対策があれば教えてください。
Hasura と Supabase を接続する

Hasura はデフォルトで Heroku に DB が作成されますが、ここでは Supabase の DB と接続する方法を説明します。

### 前提条件
- Hasura でプロジェクトを作成済み
- Supabase でプロジェクトを作成済み

# 手順
## ① Supabase のデータベース URL をコピーする
プロジェクトを開き、`Settings` (歯車のマーク) をクリックします。
![スクリーンショット 2021-06-19 16.40.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/0b1eee56-875d-b14b-4fd9-a91d23fb615a.png)

`Database` をクリックします。
![スクリーンショット 2021-06-19 16.41.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/11d9478e-e387-bb85-4f53-d1d43f9f0013.png)

`Connection string` の `Copy` をクリックします。
![スクリーンショット 2021-06-19 16.43.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/9b59224e-5133-5d90-9d1f-ff3e6fb232af.png)


## ② Hasura 側にペーストする
作成したプロジェクトのコンソールを開き、`DATA` をクリックします。
![スクリーンショット 2021-06-19 16.51.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/9e2f496c-8b1a-9a42-13a4-25a9ce8e5255.png)


`Connect Existing Database` タブを選択します。
![スクリーンショット 2021-06-19 16.53.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/ff8d9b31-f880-ebbf-474b-320e4335df3f.png)


`Database Display Name` に任意の名前を入力し、
`Database URL` には先ほど Supabase からコピーした URL をペーストします。
![スクリーンショット 2021-06-19 16.56.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/6c282b19-b838-c640-0be7-b15183ad26a5.png)

`[YOUR-PASSWORD]` となっている箇所を、Supabase でプロジェクトを作成したときに設定したパスワードに直します。
![スクリーンショット 2021-06-19 16.58.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/189fd42f-cb9c-deae-1169-1d37b05126bb.png)
↓
![スクリーンショット 2021-06-19 16.59.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/70513d8d-46a2-0b94-59d6-e1c105f2f161.png)


`Connect Database` をクリックします。
![スクリーンショット 2021-06-19 16.59.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/645694d0-2141-296e-9f98-7710ffd04dbb.png)



`Data sourse added successfully` と表示されれば接続完了です。
![スクリーンショット 2021-06-19 17.00.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/7d53e771-4c88-525c-edda-e20091f12fa0.png)

# ちゃんと接続されているか確認する

試しに Hasura 側でテーブルを作って、適当にデータを入れてみます。
![スクリーンショット 2021-06-19 17.11.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/6e221e0e-a36b-dad7-6e4c-075a7b60b0a1.png)
![スクリーンショット 2021-06-19 17.16.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/7b54dbe9-0e9f-e652-6536-353ff4d172eb.png)
![スクリーンショット 2021-06-19 17.17.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/b8ec8ff6-6f2c-4239-ec4f-409840255388.png)

Supabase 側で反映されていることを確認できました。
![スクリーンショット 2021-06-19 17.18.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631600/4d79608a-ff7e-a910-2890-605be95ef889.png)
【LeetCode】就活に向けたコーディングテスト対策 #10

#はじめに
こんばんは．
M1就活生が[LeetCode](https://leetcode.com/)から，easy問題を中心に**Python**を用いて解いていきます．

https://leetcode.com/

↓では，解いた問題のまとめを随時更新しています．
[まとめ記事](https://qiita.com/halpi/items/43761b89a1873dcc9a5c)

https://qiita.com/halpi/items/43761b89a1873dcc9a5c

#問題
今回解いたのは，難易度easyから [問題28のImplement strStr()](https://leetcode.com/problems/implement-strstr/) です．
問題としては，入力文字列`haystack`の中に，もう一方の入力文字列`needle`が最初に出現したインデックスを返すというもの．`needle`が`haystack`に含まれていない場合は-1を返し，`needle`がからの場合は0を返します．

入力例と出力例は以下の通りです．

Example 1:

```python
Input: haystack = "hello", needle = "ll"
Output: 2
```

Example 2:

```python
Input: haystack = "aaaaa", needle = "bba"
Output: -1
```

Example 3:

```python
Input: haystack = "", needle = ""
Output: 0
```

#書いたコード
まず，`needle`が空かどうか判定し，空であれば0を返します．その後，繰り返し処理で，`haystack`を`len(needle)`の長さでずらしていきながら，`needle`と一致すればそのインデックスを返します．最後まで一致するものが見つからない場合に-1を返します．

```python
class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        if needle == "":
            return 0
        for i in range(len(haystack) - len(needle) + 1):
            if haystack[i:i+len(needle)] == needle:
                return i
        return -1
```

この記事を書いている途中で，`haystack[i:i+len(needle)]`は，`len(needle)`に依存してメモリを使用するためあまり良くない解だという議論を見かけました．そのため，`needle`が長い場合には他の解法で解いたほうが良さそうです．

#おわりに
とりあえず，最後まで解いてみることが大事だという考えですが，余裕があればさらに良くなる改善策についても考えてみたいです．今後も他の方の解法や，コメントなども参考に，何が良くて何がダメなのか，何故そうなるのかなど，深く考えていきます．

今回書いたコードはGitHubにもあげておきます．

https://github.com/halpi17/LeetCodeStudy/blob/master/028/implement_strStr.py

[前回](https://qiita.com/halpi/items/387dce16bca5ce7a99ad)　[次回](https://qiita.com/halpi/items/1f1a3c81989606c0e376)
is nullでもインデックスは使われる[PostgreSQL]


今までis null での検索ではindexは見てないと勘違いしていた。
ふと実行計画を確認したら、どうやらindexを参照している。。。
(* users.nameにはインデックスを作成してる。)

```sql
 explain select * from users where name is null;
```


```
Bitmap Heap Scan on users
(cost=4.20..13.65 rows=6 width=37)
  Recheck Cond: (name IS NULL)
  ->  Bitmap Index Scan on index_users_on_name
(cost=0.00..4.20 rows=6 width=0)
        Index Cond: (name IS NULL)
```



# 考察
 
nullは値じゃないので、並び替えが必要なb-treeインデックスを貼るのは無理かと思っていた。
nullは末尾か先頭に配置することでnullを含めてインデックスを作ってるのかな?


#参考

https://www.postgresql.jp/document/10/html/indexes-types.html
gitコマンドの分岐、変更ファイルを見やすくするエイリアス(git lol)


git bashにコピーして実行してください

```bash
git config --global alias.lol "log --graph  --pretty=format:'%Cred%h%Creset -%C(bold yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit --all"
git config --global alias.lof "log  --name-status  --oneline --graph --decorate --abbrev-commit --all"
```

## git lol

* ブランチの分岐、マージを視覚化します
![git-lol.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/423ae7b8-1f93-8947-ea38-e4a25f89dc61.png)


## git lof

* コミット毎の変更ファイルを一覧で表示します
![git-lof.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276579/14d86ad9-2837-8231-c748-d1120ff5e11f.png)



* [独習 git](https://www.amazon.co.jp/%E7%8B%AC%E7%BF%92Git-%E3%83%AA%E3%83%83%E3%82%AF%E3%83%BB%E3%82%A6%E3%83%9E%E3%83%AA/dp/4798144614)に紹介されていたコマンドを改造したものです。
TypeScript 備忘録

#概要
TypeScriptについて学んだことを自分の備忘録とかねて投稿しています。

#目次
-Node.jsを使用してTSからJSにコンパイル
-型注釈と型推論
-オブジェクトの型注釈の仕方
-Tuple型の型注釈
-Any型について
-関数へ型注釈を適応させ方

##Node.jsを使用してTSからJSにコンパイル
Node.jsを使用してコンパイルするには、Node.jsを使用して下記のようにコンパイルする。

```terminal
# これでNode.jsをグローバルで使用することができるようになる。
npm install -g

# Node.jsを使用してTypeScriptをダウンロードする。
npm install -g typscript

# tscを使用して、TypeScriptをJavaScriptにコンパイルする。
tsc index.ts

# watchモードを適応すると、変更がある度に自動でコンパイルしてくれる
tsc index.ts --watch (-w)

# 一括でコンパイルしたい場合
## tsconfig.jsonを作成
tsc --init
## フォルダ内のファイルを一括でコンパイル
tsc
```

##型注釈と型推論
```ts
// 形注釈
let counter: number = 32;
let hello: string = "hello"; 

// 型推論
let checkFlg = true;
let cartLeft = 5;
```
→型注釈とは、初期化する際にその変数の型を指定して初期化する方法のことをさす。
→型推測とは、初期化する際に変数の型を指定せずに初期化する方法。
→型注釈はコードが冗長的になってしまうデメリットがある。

##オブジェクトの型注釈の仕方
```ts
// 形注釈をする際は、セミコロンを使用することを注意する
const person: {
  name: string;
  age: number;
} = {
  name: "Jhon",
  age: 32,
};

// 型推論型で初期化を行っている
const neighbor = {
  name: "Taro",
  age: 34,
};
```

##Tuple型の型注釈
```ts
// Tupleの型注釈
// 何が入っているのかがわかりやすくなる
const book: [string, number, boolean] = ["bussiness", 1500, false];
```

##Any型について
```ts
// any型について
let anything: any = true;
console.log(anything);
anything = "hello";
console.log(anything);
anything = 32;
console.log(anything);
```

```terminal
# console.logで出力される値
true
hello
32
```
→上のように、なんでも入れることができてします。
→バグに繋がる可能性があるので、Any型はなるべく使わないこと。

##関数へ型注釈を適応させ方
```ts
// 関数に型注釈を適応させ方
// 型推論は返り値には適応されるが、引数には適応されないので引数には型注釈をすること。
// 型注釈をしないと、Any型となってしまうため。
function add(num1: number, num2: number): number {
  return num1 + num2;
}
```
APIとは

APIとは、Application Programming Interfaceの略称。直訳すると、アプリケーションをプログラミングするインターフェース。インターフェースは何かと何かをつなげている接点のこと。

要するに、パソコンと周辺機器と繋げるUSBなどを言う。

あるソフトウェアをAPIを通してユーザーや企業に提供することを言う。

例えば、近くにあるコンビニを探すアプリを開発したいとする。その時にGPS機能は必要な機能であるが、1から作ることは難しいため、Googleマップなどを用いてアプリ開発をする。そうした時に、APIを通すことで、Googleマップを使用してアプリ開発ができる。
VBA(Excel)で再帰的にファイルを開くには

#VBA(Excel)で再帰的にファイルを開くには

VBA(Excel)にて、再帰的にファイルを開くスニペット

```vb
Option Explicit

' メイン処理
Sub main()
    Dim targetFolder As String
    Dim fso As Object
    
    ' 画面更新の停止
    Application.ScreenUpdating = False
    'イベント抑止
    Application.EnableEvents = False
    
    
    ' 対象フォルダの指定
    targetFolder = ThisWorkbook.Worksheets(1).Range("B1").Value
    
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    ' 対象フォルダ配下（サブフォルダ）の全ファイルに対する処理（再帰処理）
    Call loopAllFiles(targetFolder, fso)
    
    Set fso = Nothing
    
    'イベント抑止を解除
    Application.EnableEvents = True
    ' 画面更新の停止
    Application.ScreenUpdating = True
    MsgBox prompt:="処理が終了しました。"

End Sub

' 対象フォルダ配下（サブフォルダ）の全ファイルに対する処理（再帰処理）
Private Function loopAllFiles(targetFolder As String, fso As Object)

    Const FILE_TYPE_XLSX As String = "xlsx"
    Const FILE_TYPE_XLS As String = "xls"
    
    Dim folder As Object
    Dim file As Object
    
    'サブフォルダの数だけ再帰
    For Each folder In fso.getFolder(targetFolder).SubFolders
        Call loopAllFiles(folder.Path, fso)
    Next folder
    
    'ファイルの数分繰り返し
    For Each file In fso.getFolder(targetFolder).Files
    
        Dim extentionName As String
        extentionName = fso.GetExtensionName(file.Name)
        
        If LCase(extentionName) = FILE_TYPE_XLS Or LCase(extentionName) = FILE_TYPE_XLSX Then
            ' Excelファイルに対する処理
            Call execExcelFile(file)
        End If
    
    Next file

End Function

' Excelファイルに対する処理
Private Function execExcelFile(file As Object)

    Dim wkbook As Workbook
    
    Set wkbook = Workbooks.Open(Filename:=file.Path, UpdateLinks:=0, IgnoreReadOnlyRecommended:=True, ReadOnly:=True)

    Debug.Print wkbook.Name
    
    wkbook.Close SaveChanges:=False

End Function

```

## 参考資料

[【VBA】【再帰】指定フォルダ配下（サブフォルダ含む）の全てのExcelファイルに対して、処理を行う](https://excel-vba.work/2020/10/30/%e3%80%90vba%e3%80%91%e3%80%90%e5%86%8d%e5%b8%b0%e3%80%91%e6%8c%87%e5%ae%9a%e3%83%95%e3%82%a9%e3%83%ab%e3%83%80%e9%85%8d%e4%b8%8b%ef%bc%88%e3%82%b5%e3%83%96%e3%83%95%e3%82%a9%e3%83%ab%e3%83%80/)