OmniAICreator/Qiita-1.07M huggingface dataset:
VagrantとDockerで依存しない開発環境構築

ローカルに開発環境を整えてしまうとトラブルが絶えません。今回はVagrantを使って快適な、依存しない開発環境を構築します。

# 依存しない開発環境構築

問題：ローカルで環境構築をすると環境汚染でトラブル続出
解決：OS、カーネル、コンテナ　→ 仮想化してしまおう！
方法：Vagrant(VirtualBox)で仮想OS　→ さらに、仮想OSの中でDockerで仮想コンテナを立てる

# 準備
1. Virtualboxをインストール (仮想OS)
    * https://www.virtualbox.org/

2. Vagrantをインストール　(Virtualbox管理)
    * https://www.vagrantup.com/
    
3. Vagrant Box(OS)をダウンロード

   ~~~
$ vagrant box add ubuntu/focal64
   ~~~

3. Mutagenをインストール　(仮想環境とファイル同期)

    ~~~
$ brew install mutagen-io/mutagen/mutagen 
    ~~~
4. Vagrantのプラグインを取得　　(Docker, Mutagen等々)

    ~~~
$ vagrant plugin install vagrant-disksize vagrant-hostsupdater vagrant-mutagen vagrant-docker-compose
    ~~~

# 設定
任意のディレクトリに移動

~~~
$ mkdir ~/dev
$ cd ~/dev
~~~
以下の設定ファイルを作成します。

* Vagrantfile
* mutagen.yml

### Vagrantfile

参考：[VagrantコマンドとVagrantfileの設定メモ](https://qiita.com/pugiemonn/items/bcd95a35c3ec7624cd61#vagrantfile%E3%81%AE%E8%A8%AD%E5%AE%9A)
Vagrant box(OS)一覧：https://app.vagrantup.com/boxes/search

~~~bash:~/dev/Vagrantfile
Vagrant.configure('2') do |config|
  #使うVagrant box(OS)を選択
  config.vm.box = 'ubuntu/focal64'

  #任意の名前を設定
  config.vm.hostname = 'MyUbuntu'

  #ipとportを設定
  config.vm.network :private_network, ip: '192.168.60.10'
  config.vm.network 'forwarded_port', guest: 8000, host: 8000

  #VirtualBox設定
  config.vm.provider :virtualbox do |vb|
    vb.gui = false
    vb.cpus = 2
    vb.memory = 4096
    vb.customize ['modifyvm', :id, '--natdnsproxy1', 'off']
    vb.customize ['modifyvm', :id, '--natdnshostresolver1', 'off']
  end

  #ファイル共有設定
  config.disksize.size = '30GB'
  config.mutagen.orchestrate = true

  config.vm.synced_folder './', '/home/vagrant/app', type: "rsync",
    rsync_auto: true,
    rsync__exclude: ['.git/', 'log/', 'tmp/']

  config.vm.provision :docker, run: 'always'
  config.vm.provision :docker_compose
end
~~~

### mutagen.yml

~~~yml:~/dev/mutagen.yml
sync:
  app:
    mode: "two-way-resolved"
    alpha: "./"
    beta: "MyUbuntu:/home/vagrant/app"
    ignore:
      vcs: true
      paths:
        - "/log"
        - "/tmp"
~~~

# 結果
### Vagrantを起動

Vagrantを起動します。

```bash:~/dev/
$ vagrant up
```

コマンド実行後に、エラーが発生しました。

```
$ /Users/hoge/.vagrant.d/gems/2.7.4/gems/vagrant-mutagen-0.1.3/lib/vagrant-mutagen/Mutagen.rb:22:in `initialize': No such file or directory @ rb_sysopen - /Users/hoge/.ssh/config (Errno::ENOENT)
```
configが無いと言われているので、作成します。

```
$ touch /Users/hoge/.ssh/config
```

### 仮想環境にSSH接続

`vagrant up`が完了したらSSH接続します。

```bash:~/dev
$ vagrant ssh
```

接続できたら、`app`ディレクトリに移動してdocker-compose確認

```bash:~/
$ cd app
$ docker-compose up
```

立ち上がったアプリケーションにはVagrantfileで指定したIPアドレスでアクセスできます。

`http://192.168.60.10:8000/`

### Vagrantの終了方法

`vagrant halt`にてVMを終了します。

```bash:~/my_app
$ vagrant halt
```

`vagrant status`にて終了できたか確認できます。

`poweroff`になっていれば終了しています。
`running`になっていれば`vagrant halt`にて終了してください。
Python初心者はWordCloudで遊んでみたい1

#始めたきっかけ
pythonの勉強をしたくて、基礎的な勉強をしていたけどつまらない！基礎は必要だけどやっぱり何かを作らないと成長してるという実感が湧かず、pythonで出来る事を探していたらこんな記事を見つけた。
[米津玄師の歌詞をWordCloudで可視化してみた。](https://qiita.com/Senple/items/1ad08b1a7ac9560bef62)
なんだこれ、めちゃくちゃ面白そう！と思い、これをやってみる。

いきなり全部をやろうとすると、どこかで躓いて辞めそうだから初学者は黙って一歩ずつやってく。
初めは形態素解析についてを勉強し、その後にWordCloudをやっていくつもり。

最終目標は、入力で好きなアーティストの歌詞でできるようにしたい。
技術云々の前に、そもそもそんなことできないよ〜って言われたら言われたでしょうがないけど、とりあえずやるだけやってみる。

参考にさせていただいているサイトはこちら↓
https://note.nkmk.me/python-janome-tutorial/

#環境
Google Colaboratory

※初めてGoogle Colaboratoryを使う方は、こちらを参考にマウントしてみてください。
[Google Colaboratoryでファイルを読み込む方法](https://rbn-lab.net/google-colaboratory-file-import/#toc_id_2)

#形態素解析とは
pythonで形態素解析をする方法は、MeCabとjanomeの２つがあるらしい（他にもあるかも）今回はjanomeでやっていく。
janomeとMeCabの詳しい違い↓
[JanomeとMecabを使って形態素解析してみる](https://qiita.com/mizutokage/items/d6ab52a885b0eb61f45b)

#インストール
```
!pip install janome
```

#とりあえず動作確認
```python
from janome.tokenizer import Tokenizer

s = "すもももももももものうち"

# 形態素解析オブジェクトの生成
t = Tokenizer()

for token in t.tokenize(s):
    print(token)
```
##実行結果
```
すもも	名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
も	助詞,係助詞,*,*,*,*,も,モ,モ
もも	名詞,一般,*,*,*,*,もも,モモ,モモ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
うち	名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
```

#.txtを読み込んで出力できるかやってみる
※sapmle.txtには桃太郎を書き込んであります。

```python
from janome.tokenizer import Tokenizer

f = open("sample.txt", "r", encoding="UTF-8")
text = f.read()

t = Tokenizer()

for token in t.tokenize(text):
    print(token)
```

##実行結果
```
むかし	名詞,副詞可能,*,*,*,*,むかし,ムカシ,ムカシ
むかし	名詞,副詞可能,*,*,*,*,むかし,ムカシ,ムカシ
、	記号,読点,*,*,*,*,、,、,、
ある	連体詞,*,*,*,*,*,ある,アル,アル
ところ	名詞,非自立,副詞可能,*,*,*,ところ,トコロ,トコロ
.
.
.
```
#まとめ
今回は初めてのjanomeだったから、どんなものかを把握するために軽くしかやらなかったが、次回は不要な単語の消去、使われた単語の回数を見るあたりをやっていきたい。
Next.jsにTailwindcssを導入する

#Next.jsにTaillwindowの導入方法。
基本的に公式サイトを見ればいけるが初歩的なところでミスったのでメモで残しておこうと思う。
https://tailwindcss.com/docs/guides/nextjs

1.下記のコマンドを実行

```
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
```

2.下記のコマンドを実行して、tailwind.config.js と postcss.config.jsファイルを作成する。
tailwind.config.jsにオリジナルのカスタマイズを記載する。

```
npx tailwindcss init -p
```

3.tailwind.config.jsのpurgeを下記に変更する。

```
  module.exports = {
   purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
    darkMode: false, // or 'media' or 'class'
    theme: {
      extend: {},
    },
    variants: {
      extend: {},
    },
    plugins: [],
  }
```

4../styles/globals.cssを下記に変更

```
@tailwind base;
@tailwind components;
@tailwind utilities;
```

5.pages/_app.jsにimportを追記

```
//追加
import '../styles/globals.css'

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

export default MyApp
```

導入した際に起こったエラー

```
./styles/globals.css
Global CSS cannot be imported from files other than your Custom <App>. Due to the Global nature of stylesheets, and to avoid conflicts, Please move all first-party global CSS imports to pages/_app.js. Or convert the import to Component-Level CSS (CSS Modules).
Read more: https://nextjs.org/docs/messages/css-global
Location: pages/index.js
```
エラーの内容は`カスタム<App>以外のファイルからグローバルCSSをインポートすることはできません`ということだった。
要は_app.js以外のファイルで`import '../styles/globals.css'`しちゃダメだよと言っている。
index.jsxにも`import '../styles/globals.css'`を記載していたので、上記のエラーが出てしまっていた。

ちゃんとドキュメントを読むことを意識しないとな〜。
【M1 Mac】Dockerのコンテナを立ち上げるとruntime: failed to create new OS threadが出る

# はじめに
M1 Macに乗り換えて開発を進めようとしたら、Intel版 Macなら動いたDockerイメージのコンテナを立ち上げると、以下のエラーが出た

```bash
 runtime: failed to create new OS thread (have 2 already; errno=22)
 fatal error: newosproc
```

# 解決策
ENTRYKITを使わずにENTRYPOINTを用いて外部コマンドを使うようにする

### 修正前
Dockerfile

```dockerfile
 ENTRYPOINT [ \
  "prehook", "yarn install", "--" \
 ]
```

### 修正後
Dockerfile

```dockerfile
 ENTRYPOINT ["sh", "./entrypoint.sh" ]
```

./entrypoint.shを作成して

```shell
 #!/bin/bash
 
 yarn install
 
 exec "$@"
```

# 解説

### Entrykitとは

>Entrykit は一言でいうと、コンテナ内のプロセス起動時に便利な軽量 init システムだ。Docker の起動コマンドに Entrykit を使うと、起動時にテンプレートファイルを元に設定ファイルをレンダリングしてくれたり、メインプロセスの前にコマンドを実行できたりする。

だそうです。なるほど。

また、どうやらENTRYPOINTがentrykitの実行部分であること、entrykitにはコマンドが４つあるということがわかった。

| コマンド | 　　　　　　　　　　　　　　実行内容 |
|:-----------:|------------|
| prehook |コンテナ起動時にコマンドを実行する|
| render |テンプレート化したファイルに記載されている変数部分を動的に変更する |
| switch |コンテナ起動時に実行できるコマンドを複数用意し<br>切り替えられるようにする|
| codep |複数のプロセスを並列実行する| 


### なぜEntrykitはダメなのか
downloadしてくるものはx86_64(amd64)向けのものらしく、M1(arm64)では動かなかった。っぽい
Flaskでバックグラウンド実行


[PythonでThreadを使うflaskサンプルを作ってみた \- Qiita](https://qiita.com/juri-t/items/5cec3822e168215aff49)
の練習とブラウザで操作できるようにstart,stopボタンをつけてみた。


uwsgiなどで並列プロセス化するとjobs変数共有できないので、別途ジョブキューのceleryなどを使ったプロセス作る必要がある。

```py:app.py
from datetime import datetime
from flask import Flask, make_response
from time import sleep
import threading

app = Flask(__name__)


class MyThread(threading.Thread):
    def __init__(self):
        super(MyThread, self).__init__()
        self.stop_event = threading.Event()

    def stop(self):
        self.stop_event.set()

    def run(self):
        try:
            for _ in range(1000):
                print(f'{datetime.now():%H:%M:%S}')
                sleep(1)

                # 定期的にフラグを確認して停止させる
                if self.stop_event.is_set():
                    break
        finally:
            print('時間のかかる処理が終わりました\n')


@app.route('/')
def index():
    html = """

<!DOCTYPE html>
<html>

<button type="button" id="start">start</button>
<button type="button" id="stop">stop</button>

<script type="text/javascript">
document.getElementById('start').addEventListener('click',function(){
  fetch("/start/1");
},false);
document.getElementById('stop').addEventListener('click',function(){
  fetch("/stop/1");
},false);
</script>

</html>
"""
    return html


jobs = {}


@app.route('/start/<id>/')
def start(id):
    if id in jobs:
        return make_response(f'{id}は実行中です\n'), 200
    t = MyThread()
    t.start()
    jobs[id] = t
    return make_response(f'{id}の処理を受け付けました\n'), 202


@app.route('/stop/<id>/')
def stop(id):
    jobs[id].stop()
    del jobs[id]
    return make_response(f'{id}の中止処理を受け付けました\n'), 202


@app.route('/status/<id>/')
def status(id):
    if id in jobs:
        return make_response(f'{id}は実行中です\n'), 200
    else:
        return make_response(f'{id}は実行していません\n'), 200

```


[【脱jQuery】JavaScriptをネイティブで書くときのあれこれTips \| Will Style Inc\.｜神戸にあるウェブ制作会社](https://www.willstyle.co.jp/blog/1025/)
[jQueryを使わない書き方 ajax, each, trigger, on/off, extend, deferred, animate, css編 \| maesblog](https://mae.chab.in/archives/2821)
[flask run と uWSGI prefork](https://masayuki038.github.io/blog/2019/09/23/flask-uwsgi-prefork/)
[python \- Flaskが応答を返した後に関数を実行する](https://try2explore.com/questions/jp/10327151)

[Celery Background Tasks — Flask Documentation \(2\.0\.x\)](https://flask.palletsprojects.com/en/2.0.x/patterns/celery/)

[miguelgrinberg/flask\-celery\-example: This repository contains the example code for my blog article Using Celery with Flask\.](https://github.com/miguelgrinberg/flask-celery-example)
[celery/examples at master · celery/celery](https://github.com/celery/celery/tree/master/examples)
CCNA　トランスポート層

今回はレイヤ4のトランスポート層についてアウトプットしたいと思います。

復習ですが、トランスポート層は通信における信頼性に関するプロトコル群です。
この代表的なプロトコルはTCPとUDPです。

まず、IPアドレスを使って荷物を運ぶにもどこに運んで良いか分かりません。
これを示すのがポート番号です。IPアドレスが郵便番号だとしたら
ポート番号は住所の詳細のことになります。

つまり、トランスポート層はポートとポート間のプロトコルになります。
ポート番号はアプリケーションを特定するための番号で、
1つのIPアドレスで複数のポート番号を持てることから
セッションの多重化と言います。

ポート番号には3種類あります。
1~1023をウェルノウンポートと言って、予め用途が決まっている番号です。
1024~49151を登録済みポートと言って、サーバーに登録されている番号です。
残りはダイナミックポートで、誰でも利用できるポートです。

大きく分けるとTCPは正確性重視、UDPは速さ重視になります。
TCPはTransmission Control Protocolで
状況を通信し合いながらデータを送信するプロトコルです。
なので、コネクション型と呼ばれ、セグメントを送ります。

**セグメントの中身**

宛先ポートと送信元ポートで2バイトずつ使います。
セグメントで一番重要なのは制御ビットです。
これはArgument Acknowledge Push Reset Synchronize Finishの6つを
使って通信します。
そしてセッションは通信そのものを指しますが、コネクションはセッションのルートです。
コネクションを接続するための方法が3ウェイハンドシェイクです。

**３ウェイハンドシェイク**

①まずは送信元から宛先にSYN：１を送ります。
②次に宛先から送信元にACK:1 SYN:1を送ります。
③最後に送信元から宛先にACK:1を送ります。
これによりコネクションの接続が完了します。

**TCPセグメンテーション**

一度に送ることができるサイズをMSS(Maximum Segment Size)と
言います。MTUとは違い、レイヤ4で使うものになります。
このサイズに合うように分割することをTCPセグメンテーションと言います。
MSSは３ウェイハンドシェイクで決定しますが、基本的にはMTU-40です。

この分割、送信、再構築を順序制御と言います。

**シーケンス番号とACK番号**

送信元から宛先に送られる再構築の手がかりになる番号を
シーケンス番号と言います。また、宛先から送信元へ送られる確認番号を
ACK番号と言います。
これの初期値は3ウェイハンドシェイクで決められます。

**再送制御**

ACKが返ってこないと送信元は送信に失敗したとみなしてデータを再送します。
そのことを再送制御と言います。再送に使われる時間は再送タイマーと言って、
3ウェイハンドシェイクで決めれらます。

**ウィンドウ制御**

ACKが返ってきたらまた送っての繰り返しだと送るのに
時間がかかってしまいます。それを防ぐために宛先にはバッファと呼ばれる
保管場所があります。そのサイズをウィンドウサイズと言います。
その分だけ一度に送ることができます。
確認応答が返ってくるとウィンドウをずらすことができます。
これをスライディングウィンドウと言います。
また、ウィンドウサイズも3ウェイハンドシェイクで決定されます。

**フロー制御**

受信側のバッファがいっぱいになりそうで、やはり
ウィンドウサイズを減らしたい時は確認応答で知らせます。
これにより送信量を調節することができます。
これをフロー制御と言います。

**輻輳制御**

1:1の関係だと分かりやすいが、宛先が他のPCと
繋がっている可能性もあります。ですので、バッファがどのくらいいっぱいか
確認することができません。だからスロースタートと言って、1から順に
倍々で送っていきます。それでいっぱいになっていて、確認応答が
返ってこなかった時にまた0からスタートして送ります。
送信側には輻輳ウィンドウをおきます。

コネクションを終了するときは3ウェイハンドシェイクでFINを送り合います。

**UDP**

UDPはUser Datagram Protocolの略で特徴はコネクションレス型、
ベストエフォート型である。オーバーヘッド(データ以外での処理負荷)が小さいため
処理スピードが高速になります。

#最後に

自分のアウトプットとして知識を出していますので、分かりにくい点等があると
思いますが、良ければ見て頂けると幸いです。
勉強中の身ですので、もし不明点や間違った点がありましたら是非コメント下さい。
crtdbg.h を使ってメモリリークを探しやすくする

メモリリークはがあるのよねー…というのを見かけたので。

スマートポインタの利用も検討するといいと思うよ！というところもありますが今あるコードの問題が解決するわけじゃないですからね。

ってことで、お手軽手段を軽く紹介。

まずはVC++では同じみプリコンパイルヘッダーに以下のコードを入れておきます。
インクルードするヘッダーによっては順番の問題があることもあるので注意しましょう…＜
＜どうやって！

```cpp
//プリコンパイルヘッダー
#include <crtdbg.h>
#include <memory.h>

#ifdef _DEBUG
# define DEBUG_NEW new(_CLIENT_BLOCK,__FILE__,__LINE__)
#endif
```

次はメイン関数と実際のメモリ確保部分。

```cpp
// ソース
#include "pch.h"
#include "app.h"

#ifdef _DEBUG
# define new DEBUG_NEW
#endif

void MainRoutine();
int main()
{
  _CrtSetDbgFlag( _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)| _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );

  MainRoutine();

  return 0;
}
void MainRoutine()
{
  lstrcpy( new wchar_t[32], L"First Leak" );
}
```
デバッグ実行するとプログラム終了時にアウトプット画面に以下のような感じでリークメモリをダンプしてくれます。

とあるサンプルプログラムでの実行例です。
lstrcpy の行をそのままWinMainの最初に配置して試した例です。

```
Dumping objects ->
sample.cpp(41) : {221} client block at 0x0000027092637A90, subtype 0, 64 bytes long.
 Data: <F i r s t   L e > 46 00 69 00 72 00 73 00 74 00 20 00 4C 00 65 00 
Object dump complete.
```

もっと詳しく！という場合はリファレンスを見てくださいね。
[CRT デバッグ ヒープ](https://docs.microsoft.com/ja-jp/visualstudio/debugger/crt-debug-heap-details?WT.mc_id=DT-MVP-32182&view=vs-2019)
【備忘録】GCE上の環境でgcloud docker -- pushを実行するとAccess deniedが出る

GCEに開発環境を作り、GCE環境内で作成したアプリケーションのコンテナイメージをCloud Runで実行させるために、Container Registryにイメージをpushした際に「denied: Access denied.」とエラーが表示されてpush出来なかった話。

```
$ sudo gcloud docker -- push gcr.io/[projectID]/[Name]

...
7cf0f434f498: Waiting 
8555e663f65b: Waiting 
d00da3cd7763: Waiting 
4e61e63529c2: Waiting 
799760671c38: Waiting 
denied: Access denied.
```

## 原因
作成したGCEのVM環境からContainer Registryにコンテナイメージをpushするためには、以下画像のようにVM環境がストレージに対して書き込みなどのアクセス権限を持っていないとダメみたいでした。

![スクリーンショット 2021-09-18 1.25.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154154/d08faf56-de86-6f3a-8758-0e0e3ebd530d.png)

上記のようにVM環境がストレージに対して書き込み権限を与えたあとは無事にpushすることが出来ました。

## その他エラーに対して確認した内容
○Container RegistryのAPI設定が有効になっているかどうか
○Container Registryの権限のロールが正しく設定されているかどうか
かの有名なFrog問題に奮闘する

#Topic
- 前の記事に引き続き，お世話になっている「問題解決能力を鍛える！アルゴリズムとデータ構造」関連の話．
- Frog問題（AtCoder Educational DP Contest A - Frog 1)の別解を考えたい

## 別解？？
Frog問題は，[AtCoder Educational DP Contest A - Frog 1](https://atcoder.jp/contests/dp/tasks/dp_a)を参考されたい．
ここでは，自分の考え方を記述しておく．（実装はまだできていない）

```Python
#xはコスト，iは段数
func(x,i):
    if i == n-1: return
    func(x + abs(h[i+1] - h[i]), i+1)
    func(x + abs(h[i+2] - h[i]), i+2)

#初期値は0で，段数は0段目から始まるからx,iに0を代入
func(0,0)
```

実現したいこととしては，再帰で0段目からN段目までのコストを全て計算させること．
ただ，分かってもらえるとおりこの命令では，出力もしていないし何ができるの？って感じ．
けど，やりたいことがわかってもらえる人がいれば教えていただきたい．

わかれば，また実装する．

では，この辺で．
こんな記事ですが読んでいただいてありがとうございます．
理系な家継簿の楽しみ方！

みなさん、「理系な家継簿」を手に取っていただき、ありがとうございます！これからも、ぼちぼち、アプリの更新を続けていくので、ご意見などは、専用のメールアドレスに、送っていただけると、幸いです！

あ、まだ、『理系な家継簿』をインストールできてない方のために、URL載せときます！

『[apple store：理系な家継簿](https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=1586902057)』

ぜひ、これで、日々の出費を見つめ返してあげてください！

##理系な家継簿って？

まず、名前を理系な家継簿とした理由について、お話しします。
開発者である、僕自身極度のめんどくさがり屋で、ずっと、これは、理系の特徴である、と考えてきました。めんどくさがり屋だから、楽するアイデアが生まれたり、めんどくさがり屋と言っても、悪いところばかりでは、ないんです。

ですが、家計簿、日記などとなると、3日坊主で終わってしまう。そんな悩みを持った、理系の方、多いんじゃないでしょうか。

アプリ名は、理系な家継簿ですが、目指すは、『めんどくさがり屋さん』でも、継続できる家計簿アプリですね。今回は、この家計簿を存分に楽しむためのポイントを、ここで紹介していこうと思います！

##①初回がスムーズ！

ほんとに基本的な設定に関しては、開始時に、説明が見られるような設定にしています！ここで、ベースとなる、機能を全部習得しちゃってください！

##②背景写真を自由に選べる！

毎日見るアプリにとって、背景を設定できるのは、日々のモチベーションに繋がりますね！方法は、簡単、

"設定"->"背景画像とテーマ色"->"背景画像を選択"

だけですね！文字の見やすさを調整するために、背景の明るさまで、変更できます。ぜひ、お試しください！

##③暗号モード！

みなさんは、家計簿を、あとでつけようって思って、ちゃんと、後まで、覚えてられますか？僕は、100％忘れてしまいます。笑

そこで、環境に作用されず、どんなとこでも、家計簿をつけたいという方のために作った、"暗号モード"。地下鉄の中でも、隣に誰がいようとも、全く気にせず、家計の管理できます！

 *どういうことかって?* 

それは、画面上の数字が、みんなが読めない、僕たちだけの暗号に切り替わるのです！

 *...みなさんも、読めないって?*

ご安心ください！このアプリをお使いいただいてるみなさんに、特別に、暗号の読み方を紹介しちゃいたいと思います！

2021/09月中には、暗号解説の記事を、ここにアップするので、ご期待ください！

##④この記事をここまで読んだみんなだけに

実は、あぷりが立ち上がったときのアニメーション。
数学好きには、たまらないですね。名前は、リサージュ曲線って言います。

一応、数式は、こんな感じになってます。

x = sin(6.0 × t)
y = cos(4.0 × t + θ)　( 0 ≦ θ ≦ 2π )

って感じで、θの値が毎回、ランダムで決まるので、毎回、モーションがちょっとずつ、変わります。以後のアップデートでは、リサージュ曲線以外にも、sin,cosで表される美しい曲線がたくさんあるので、あたらしい、モーションもたくさんつけていきたいと思います！

って。。。特別感なかったかな？だよね。

最後に、毎回モーション表示されて、飽きちゃったよ。。。という方のために。新しい機能を用意しました。それは、モーション中に、左スワイプで、メイン画面に飛べるようになってます！

また、上向きスワイプで、レシート撮影用のカメラを直接立ち上げられます！急ぎで、写真だけ保存しときたい方もどうぞ！

##最後に

最後まで、見ていただきほんとに、ありがとうございます！これから、この家計簿アプリで、ともに建設的な毎日を送って参りましょう！！
ABC186 C - Unlucky 7 から学んだ

https://atcoder.jp/contests/abc186/tasks/abc186_c

![abc186_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/1aa4645a-7d77-3cd8-74c9-d1d032c8aa8f.png)

![abc186_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/562e5007-caa6-ea2e-c73b-dee93a12f9fb.png)

とりあえず、8 進数への変換は基本文字列。
10 進数も文字列へ統一した方が楽そうだ。

こんな記述でも通った。

```Unlucky.py
N = int(input())
lis = []
for n in range(1,N+1):#O(10^5)
    if "7" in str(n) or "7" in oct(n):#worst O(12)
        lis.append(str(n))
print(N-len(set(lis)))
#total O(12*10^5)
```
UIテスト自動化してみた～発展編～

### 前回

[UIテスト自動化してみた～導入編～](https://qiita.com/KAWAII/items/f7af1611fc497b2df47b)

引き続き、テスト自動化について記載したいと思います。

まずは、エビデンス残しですね。

### エビデンス取得

Junitのように`asertEquals`を使用してもいいね、
web画面を経由しつつPTってのは面白発想かもしれない。

例えば、

```java
import static org.junit.jupiter.api.Assertions.assertEquals;

// 画面から要素を取得
String name = Selenide.$("input[name=username]").val();

// 期待する値かを比較
assertEquals("jobs", name);

// もっと簡単にSelenideの機能を使ってもできる！
Selenide.$("input[name=username]").shouldHave(Condition.text("jobs"));

```

とはいえ、やっぱり画面だから画面キャプチャが多いのでは？？

`Selenide`なら簡単に取れちゃいます！

```java
import com.codeborne.selenide.Selenide;

// 画面全体スクリーンショットを作成
Selenide.screenshot(file名);
```

でも、実際のテストって、
ボタンをクリックするとき→クリック後の両方でキャプチャ取得したりしませんか？

実際の動きに合わせるとこうなる。

```java
import com.codeborne.selenide.Selenide;

// 画面全体スクリーンショットを作成
Selenide.screenshot(file名_001);

// selecterにはCSSセレクタが入る
Selenide.$(selecter).click();

// 画面全体スクリーンショットを作成
Selenide.screenshot(file名_002);

```

ここで、`Selenide`の欠点が出る…

**マウスカーソルが存在しない！！**

そりゃよく考えたらそうですよね。マウスはブラウザの中にあるものではないからね…

これにより、キャプチャからどこクリックしたのか判断がつかない！

私の思いついた解決策は、
クリックをホールドしてその状態でキャプチャ取得すれば、クリックされるのがわかるんじゃないか？？？

### 試作品

```java
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.interactions.Actions;

import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.Selenide;
import com.codeborne.selenide.WebDriverRunner;

// アクションを宣言
WebDriver driver = WebDriverRunner.getWebDriver();
Actions action = new Actions(driver);

// クリックホールド状態でキャプチャを取得
action.clickAndHold(Selenide.$(selecter)).perform();
takeScreenshot(file名001);
Selenide.$(selecter).click();

// クリック実行後キャプチャ取得
action.release().perform();

// クリック後の処理によってwaitなどが必要かも。。。

Selenide.screenshot(filena名002);

```

上記の方法によってどこをクリックしたかわかりやすいキャプチャが取得できた。

### Selenideマイナスポイント

**マウスカーソルが存在しない**と**アドレスバーがキャプチャ対象外**なところだろうか。
どちらもエビデンスとしての信ぴょう性や妥当性に少し影響するかなって程度。

### おわりに

基本的には使いやすく、便利なテスティングフレームワークだと思う。
Java、Junitを使用したことがある方なら導入コストが低いと思うので、
みなさんぜひ試してみては。
Swift で Kruskal（クラスカル法）使って MST：Minimum Spanning Tree（最小全域木）

備忘用のメモ

## NOTE

- アルゴリズム：クラスカル法（Kruskal Algorithm）（貪欲法（Greedy Algorithm））
- 実装：Union Find

## コード

アルゴリズムの部分。

- 辺の重みで小さい順にソートするし、
- 小さい順に辺を１つずつ取り出す
- 取り出された辺が使えるなら採用する。使うとサイクルになって使えない辺はスキップする。これを繰り替えす。

```swift
// n: number of node
func kruskal(_ n: Int, _ graph: [Edge]) -> Int {
    // init
    let sorted = graph.sorted(by: { $0.weight < $1.weight })
    var result = [Edge]()
    var uf = UF(n)
    
    // algo
    for edge in sorted {
        if uf.isConnected(edge.from, edge.to) { continue }
        let _ = uf.union(edge.from, edge.to)
        result.append(edge)
    }
    
    // return
    let sum = result.reduce(0) { $0 + $1.weight }
    return sum
}
```

---

Edge の部分

```swift
struct Edge {
    let from: Int
    let to: Int
    let weight: Int
}
```

---

Union Find の部分

- path compression（経路圧縮）してる
- Union by size してる

```swift
struct UF {
    var size: [Int];
    var parentsOf: [Int];
    
    init(_ n: Int) {
        self.size = [Int](repeating: 1, count: n)
        self.parentsOf = [Int](repeating: -1, count: n)
        for i in 0..<n {
            self.parentsOf[i] = i
        }
    }
    
    mutating func root(_ elem: Int) -> Int {
        var current = elem
        while current != parentsOf[current] {
            parentsOf[current] = parentsOf[parentsOf[current]] // path compression
            current = parentsOf[current]
        }
        return current
    }

    mutating func isConnected(_ a: Int, _ b: Int) -> Bool {
        return root(a) == root(b)
    }
    
    mutating func union(_ a: Int, _ b: Int) -> Bool {
        if isConnected(a, b) { return false }
        
        let rootA = root(a)
        let rootB = root(b)
        
        // union by size
        let (smaller, larger) = size[rootA] < size[rootB]
            ? (rootA, rootB)
            : (rootB, rootA)
        
        self.size[larger] += self.size[smaller]
        self.parentsOf[smaller] = larger
        return true
    }
}
```


## LeetCode

- https://leetcode.com/problems/min-cost-to-connect-all-points/

愚直にグラフへ変換してからKruskal。

```swift
func minCostConnectPoints(_ points: [[Int]]) -> Int {
    var graph = [Edge]()
    for i in 0..<points.count {
        for j in i..<points.count {
            let x1 = points[i][0], y1 = points[i][1]
            let x2 = points[j][0], y2 = points[j][1]
            let dist = abs(x1-x2) + abs(y1-y2)
            graph.append(Edge(from: i, to: j, weight: dist))
        }
        
    }
    
    return kruskal(points.count, graph)
}
```
バブルソートとは

# はじめに
本記事では、バブルソートについて記述します。
ふと知らない単語が私の元に来たので、調べてアウトプットします。

# バブルソートとは
`データ列を大小などの順序通りになるよう並べ替えるソート（整列）アルゴリズム`の最も基本的な手法の一つで、
端から順番に隣接する要素同士を比較・交換していくもの。

ソートを実行すると値の大きいまたは小さい要素が泡みたいに浮かびあがってくるように見えることから、
バブルソートと呼ばれるらしいです。

# アルゴリズムについて
リスト（今回なら数列）を昇順に整列させる手順。

```
① ⑨ ④ ② ⑤ ⑦
```
1.先頭の①と隣の⑨を比較する
2.今回は、昇順ですので、①は⑨より小さいため、交換はしません。
3.次に2番目の⑨に焦点を当てます。⑨は④よりも大きいため、ポジションを交換します。

```
① ④ ⑨ ② ⑤ ⑦
```
4.このように次は、３番目になった⑨を焦点にし、⑨と②を比較する。次は⑨と⑤を比較する。次は...

```
① ④ ② ⑤ ⑦ ⑨
```
5.このようにして終末まで繰り返します。
6.次は④と②を比較します。
.
.
.

```
① ② ④ ⑤ ⑦ ⑨
```
このような流れで数列の大小が整うということですね。

#　特徴
以下の記事にて詳しく説明されていたため、参照します。
[バブルソート　一番参考になった記事](https://www.codereading.com/algo_and_ds/algo/bubble_sort.html)
> リストの個数を n とすると、バブルソートは必ず` n(n - 1)/2 回`のスキャンが行われます。

> n 個のリストがある場合、1回目で1番目に重い(大きい)値がリストの終端に移動してゆき、2回目のスキャンで2番目に重い値を浮かびあがらせ、3回目のスキャンで・・・、という具合に n 回のスキャンで n 番目に重い値を浮かびあがらせるのがバブルソートの特徴です。 (条件を入れ換えると「軽い(小さい)値を浮かびあがらせる」と述べることができます)

> リストの個数が多くなればなるほど処理速度も遅くなりますが、シンプルなアルゴリズムなのでデータ量が少ないときには手軽に実装できます。


# 終わりに
バブルソートという仕組み自体は、簡単に思えますが、
バブルソートという言葉を知らなかったです。
まだまだ知らない単語が出てくるので、１つ１つ潰して理解していきます。

今回の参考サイト
[バブルソート　qiita記事](https://qiita.com/mczkzk/items/c909c510ca413ac5b574)
[バブルソート　一番参考になった記事](https://www.codereading.com/algo_and_ds/algo/bubble_sort.html)
[バブルソート 【bubble sort】 単純交換法 / 隣接交換法 / 基本交換法](https://e-words.jp/w/%E3%83%90%E3%83%96%E3%83%AB%E3%82%BD%E3%83%BC%E3%83%88.html)
[バブルソート ruby](https://qiita.com/kajitack/items/13a36add30f4922eff4b)

明日も頑張ります！
CCNA　インターネット層　TCP/IP

今回はレイヤ3のインターネット層について記述します。

OSIは理論重視であって、考え方をわかりやすくしたものです。
それに対して、実践的に作られたのがTCP/IPになります。
なので、これをデファクトスタンダードと言います。
TCP/IPはRFCによって標準化されています。

特に代表的なプロトコルはIP ARP ICMPの3つになります。

**IP**

IP(Internet Protocol)はIPアドレスを使用してエンドツーエンドの通信を
可能にするプロトコルになります。IPアドレスはネットワークにおける住所のようなもので、
MACアドレスと違い、付与されるIPアドレスは状況によって異なります。
これを論理アドレスと言います。

特徴は3つあります。
1つ目はコネクションレス型です。これは送りっぱなしという意味です。
2つ目はベストエフォート型です。これはやるだけのことはやるという意味です。
3つ目はデータ回復機能はない点です。これは破棄したら破棄しっぱなしです。
必要であれば他のプロトコルで補います。

IPアドレスは元々、IPv4でした。しかし、付与できるIPアドレスの数に限りが
あるので、IPアドレス枯渇問題が発生しました。これにより、IPv6ができました。
ネットワークの場所を表す、ネットワーク部とその中のノードのアドレスを表す
ホスト部に分かれます。

**デフォルトゲートウェイ**

これは他のネットワークの出入り口となるところです。
ノードは自身のネットワークに宛先がないと、自身のネットワークの
デフォルトゲートウェイに送ります。その後、宛先ネットワークの
デフォルトゲートウェイから宛先のノードに送ります。

**IPヘッダ**

では、IPヘッダの中身を見ていきましょう。
まずは、送信元IPアドレスが4バイト、宛先IPアドレスが4バイトです。
合計20バイトあります。下記のフラグメンテーションの他に
ToSとTTLがあります。
ToSはType of Serviceの略で、パケットの優先順位と輻輳の際の
処理の方法など(QoS:Quality of Service)を管理しています。
TTLはTime To Liveで、ルータの生存時間を表します。
これはルータを経由する回数を表しています。
残りはプロトコルで、これは上位のプロトコルを表しています。

**フラグメンテーション**

レイヤ3でMTUを超えるパケットを送る場合、一度分割して送信してから
再構築する必要があります。これをフラグメンテーションと言います。
それに関するフィールドがあります。
まずは識別子ですが、これは再構築の際に必要となるフィールドです。
同じデータなのかを表します。
次にフラグですが、これは分割はまだされているかと続きはあるかを表しています。
最後にフラグメントオフセットです。これは送信のスタート地点を表しています。
しかし、それぞれのノードで分割、送信、再構築が行われるので、今はあまり
使われていません。

**ARP**

ARPはAddress Resolution Protocolの略で、宛先IPアドレスに紐づく
MACアドレスを見つけるプロトコルです。
これにはARPテーブルが必要になります。
まず、ARP要求でノード全体にブロードキャストで送ります。
該当するMACアドレスをARPリプライをユニキャストで返します。
送る際はMACアドレスは随時変わりますが、宛先のIPアドレスは変わりません。
何度もARP要求を行うとPCに負荷がかかってしまうので、ARPリプライ後の
MACアドレスとIPアドレスは保存しておきます。
ただし、一定時間が経つと消えます。これをARPキャッシュと言います。
Ciscoのコマンドはshow ip arpでARPテーブルを表示させます。
消すときはclear ip-cacheです。

**ICMP**

ICMP(Internet Control Message Protocol)はIPを補うプロトコルです。
IPの上位のプロトコルになります。
ICMPのフォーマットで重要なのはタイプとコードです。
0と8はセットで覚えて下さい。これはpingでも使われます。
pingとは通信ができるかどうかの確認です。
8がエコー要求で、0がエコー応答です。これはセットで4回行われます。
3は宛先経路到達不可です。コードが0だとネットワーク、1だとホストになります。
5は宛先経路変更です。コードが0だとネットワーク、1だとホストになります。
11は時間超過です。0はTTL超過、1は再構築の際のタイムアウトです。
ちなみにtracerouteを使うと経路情報が見れます。

#最後に

自分のアウトプットとして知識を出していますので、分かりにくい点等があると
思いますが、良ければ見て頂けると幸いです。
勉強中の身ですので、もし不明点や間違った点がありましたら是非コメント下さい。
BIツール導入案件で個人情報閲覧防止のためマスキング処理を実装

#本稿の目的

BIツール導入の実務案件を担当しました。

今回のBIツール導入案件では、「本サービス運用に影響が出ないよう、本サービス用データベースからデータを分析用に取ってくること」「分析ように取ってきたデータにマスキング処理を施し、BIツールのユーザーが閲覧できないようにすること」の2点を担保する方法を考えて実装するのが一番の山場でした。

そこで本稿では、「要件」「課題」「解決策」に分けて上記2点についての詳細かつ正確な説明を試みます。また、最後に実装したコードも掲載しております。ぜひご覧ください。

#要件
BIツールを導入するに当たって、下記の要件（クライアントの要望）を満たす必要がありました

要件1. 本サービス運用に影響が出ないよう、本サービスのデータベース以外のところにBIツールが参照するようにしてほしい

要件2. BIツールの利用者（従業員）に個人情報が見えないようにusernameとemailにはマスキング処理を施してほしい

要件3. 以上をできるだけコストをかけないで実現してほしい 


#課題

課題1. 要件1を満たすために、本番データベースを何らかの形でエクスポートする必要がありました。

課題2. 要件2を実現するためにマスキング処理用のプログラムを作成する必要がありました

課題3. BIツールがアクセスするDBサーバーのデータベースにマスキング処理を実施する方針だと、本サービスのデータベースからデータを移したばかりの時に、まだマスキング処理ができていない状態が発生し、BIツールのユーザーが個人情報を閲覧できてしまう可能性があります。なので、本番DBサーバーでもBIツール用DBサーバーでもない第3の場所でマスキング処理を実行する必要がありました

課題4. 第3の場所でマスキング処理実施後のデータをBIツール用データベースに何らかの形でエクスポートする必要がありました

課題5. 要件3を満たすために、マスキング処理用の場所は必要な作業が終われば削除するようにすべきでした

課題6. 以上全てを定期的に自動実行できなければなりません。

#解決策

・課題1に対しては、本サービスのRDSのスナップショットを作成して、それから別のRDSを復元することで対処しました。

・課題2のマスキング処理用のプログラムは、Rubyを使って作成しました。

・スナップショットの復元により作成したRDSのデータベースにマスキング処理を施すことで、課題3の解決を図りました。

・課題4を解決するため、マスキング処理を施したテーブルを含む全データベースのdumpファイルを作成し、それをBIツール用のRDSで復元するようにしました。

・マスキング処理したデータのエクスポートが完了してすぐに、スナップショットから復元したRDSを自動的に削除するようにしました。これにより、課題5をクリアしました。

・シェルスクリプトにAWS CLIなどのコマンドを記述し、これをcronで定期実行することで課題6を解決しました。同じスナップショット名で何回も自動実行できるよう、作成したスナップショットは毎回削除しています。

#コード
```
#!/bin/bash

#スナップショットの作成
/usr/bin/aws rds create-db-snapshot \
  --region ap-northeast-1 \
  --db-instance-identifier database-0 \
  --db-snapshot-identifier hogehoge

#スナップショットの作成を待つ
/usr/bin/aws rds wait db-snapshot-available \
  --region ap-northeast-1

#スナップショットからRDSを復元する
/usr/bin/aws rds restore-db-instance-from-db-snapshot \
  --region ap-northeast-1 \
  --db-snapshot-identifier hogehoge \
  --db-instance-identifier database-3 \
  --availability-zone ap-northeast-1c \
  --db-subnet-group-name redash-db-sub-groupe \
  --vpc-security-group-ids sg-0cdd1b46c92f20dd7 \
  --db-parameter-group-name redash-db-param \
  --no-multi-az

#RDSの立ち上がりを待つ
/usr/bin/aws rds wait db-instance-available \
--region ap-northeast-1

#dokugaku_engineerデータベースにマスキング処理
/bin/bash -lc "~/.rbenv/shims/ruby ~/app/masking.rb"

#マスキングしたデータベースからダンプファイルを作成
mysqldump --defaults-file=~/etc/.my.cnf --set-gtid-purged=OFF \
--single-transaction dokugaku_engineer > dokugaku_engineer.dump.spl

#BI専用RDSのデータベースにダンプデータを投入
mysql --defaults-file=~/etc/your.cnf dokugaku_engineer < dokugaku_engineer.dump.spl

#作成したスナップショットを削除
/usr/bin/aws rds delete-db-snapshot \
  --region ap-northeast-1 \
  --db-snapshot-identifier hogehoge

#作成したRDSを削除
/usr/bin/aws rds delete-db-instance \
  --region ap-northeast-1 \
  --db-instance-identifier database-3 \
  --skip-final-snapshot
```
UIテスト自動化してみた～導入編～

### はじめに

web開発してて、UIテスト面倒な～

これ全部、自動化されたら、楽なのにな～って思ってる開発者は少なくないと思う！

テスト自動化に`Selenide`を使ってみたので簡潔に内容を記載しようと思う。

### Selenide導入

[Selenide公式ページ](https://selenide.org/)

以下、mavenで使用する場合。

```xml
<dependency>
    <groupId>com.codeborne</groupId>
    <artifactId>selenide</artifactId>
    <version>5.24.3</version>
    <scope>test</scope>
</dependency>

```

### まずはwebサイトを開く

これだけで画面は開けちゃう。

```java
import com.codeborne.selenide.Selenide;

// yahooを開く
Selenide.open("https://www.yahoo.co.jp/");

```

### 要素にアクションを起こす

以下、クリックの例

```java
import com.codeborne.selenide.Selenide;

// selecterにはCSSセレクタが入る
Selenide.$(selecter).click();

```

個人的にはCSSセレクタを使って、
`.click()`ってメソッドがあるとかjqueryの感覚で使えそうだな～って印象
Javaは得意じゃないけど、jqueryはよく使ってたからJavaよりもとっつきやすい！(^^)/

### ココがスゴイ
- 勝手に要素wait

```java
import com.codeborne.selenide.Configuration;
import com.codeborne.selenide.Selenide;

// 要素の出現待機する秒数を設定(ミリ秒)
Configration.timeout = 10000;

Selenide.$(selecter).click();

```
このような記述をした場合、`selecter`の値が表示されるまでフレームワークでwaitしてくれる！！

昔、`Selenide`を使ったときはブラウザでアクセスしてどれくらいのwaitかければいいか計算してやった記憶があるな…
あの時はがむしゃらだったなー…(ホジホジ)

- 実施者の裁量に依存しない！

```java
// ブラウザサイズを指定
Configuration.browserSize = width + "x" + height;
```

UIテスト実施等で大変なのは、複数人で実施した時の前提条件合わせ
ルールは決めてたけど、設定し忘れて実施しちゃった…なんてことも…

設定値に完全統一が難しいブラウザサイズの固定もできる！

- 複数ブラウザも楽ちん！

```java
import org.openqa.selenium.chrome.ChromeDriver;
import com.codeborne.selenide.WebDriverRunner;

// chromeを設定
ChromeDriver chromeDriver = new ChromeDriver();
WebDriverRunner.setWebDriver(chromeDriver);
```

`WebDriverRunner`の`setWebDriver`メソッドを使用すれば、ブラウザの切り替えも余裕！

いや～これ導入したら、「IEとchromeとfirefoxでテストしてほしいんだよね」って言う人がいても余裕ですね～笑(IEはもうやらんくて良くない…??)

### 次回予告

次回は、

- テスト自動化でエビデンスをとる
- 使ってみてのマイナスポイント

の2本立てでお送りします！

それでは～(*´ω｀)ﾉｼ
Rubyで時間の差（HH:MM:SS）を計算する

時間の差をHH:MM:SSとして欲しい時に、変換する際にJSTとして+9:00されてしまって困ったので備忘録

こんな感じ↓
6時間10分ー4時間＝11時間10分（JST）+9:00

足し算引き算はunixtimeで数字として行う（これは他に記事いっぱいあるのでそっち見て）

```ruby
    # 時間の差を見たいので引き算
    diff = Time.zone.at(unix_base_time) - Time.zone.at(something_unix_time)
    p diff.class # FloatとかActiveSupport::TimeWithZoneならいけることを確認した
    p Time.zone.at(diff).strftime('%H:%M:%S') # "09:10:00"
    p Time.zone.at(diff).utc.strftime('%H:%M:%S') # "02:10:00"
```
terraformで管理したくない時のちょっとしたtips

terraform以外からのリソース変更を適用しない方法。

普段は便利に使っているterraformですが、何でもかんでもterraformで〜っていう事が偶に煩わしく感じるのもまた事実ということで
一部のリソース変更を無視する対処をしたい。

今回はリソースにつけられているタグが変更されても無視する書き方です。

対象リソースの該当部分を指定して  **ignore_changes = [tags]** を記述する。
下記のような場合、subnetのtagがterraform外で更新があっても、planやapply時に上書きされないようにしてくれる。

```
  lifecycle {
    ignore_changes = [tags]
  }
```


```
# public subnet

resource "aws_subnet" "public" {
  count                   = 6
  vpc_id                  = aws_vpc.main.id
  availability_zone       = element(lookup(var.az, "${terraform.workspace}.az"), count.index)
  cidr_block              = element(lookup(var.public_subnet_cidr, "${terraform.workspace}.public_cidr"), count.index)
  map_public_ip_on_launch = element(var.launch_ip, count.index)
  tags = {
    Name = element(var.public_tags, count.index)
  }
  lifecycle {
    ignore_changes = [tags]
  }
}
```
デバイスの傾きを検知して向きによって決めた処理をさせる。（UIDevice）

#今回の内容

* デバイス(iPhone自体)を傾けた時に、傾けた事を検知して傾けた向きによって処理をさせる。

#コードと簡単解説

* まずは、`UIDevice.current.beginGeneratingDeviceOrientationNotifications()`でデバイスを回転させた時の検知を始める。
* デバイスの向きが変わった時、変わった向きによって`mapView`の`frame`を対応させる。（縦長にしたり横長にしたりって感じです）

```Swift:
           ~~~一部省略~~~

     @IBOutlet weak var mapView: MKMapView! 

     let device = UIDevice.current

     override func viewDidLoad() {
        super.viewDidLoad()
        
        device.beginGeneratingDeviceOrientationNotifications()        
        NotificationCenter.default.addObserver(self, selector: #selector(devicOrientationDetection), name: UIDevice.orientationDidChangeNotification, object: nil)

           ~~~一部省略~~~
     } 

    @objc func devicOrientationDetection(){
        
        switch UIDevice.current.orientation{
        
        case .portrait:
            mapView.frame = CGRect(x: self.view.frame.minX, y: self.view.frame.minY + self.view.safeAreaInsets.top, width: self.view.frame.size.width, height: self.view.frame.size.height - self.view.safeAreaInsets.bottom - self.view.safeAreaInsets.top)
            
        case .portraitUpsideDown:
            mapView.frame = CGRect(x: self.view.frame.minX, y: self.view.frame.minY + self.view.safeAreaInsets.top, width: self.view.frame.size.width, height: self.view.frame.size.height - self.view.safeAreaInsets.bottom - self.view.safeAreaInsets.top)
           
        case .landscapeLeft:
            mapView.frame = CGRect(x: self.view.frame.minX, y: self.view.frame.minY + self.view.safeAreaInsets.top, width: self.view.frame.size.width, height: self.view.frame.size.height - self.view.safeAreaInsets.bottom - self.view.safeAreaInsets.top)
             
        case .landscapeRight:
            mapView.frame = CGRect(x: self.view.frame.minX, y: self.view.frame.minY + self.view.safeAreaInsets.top, width: self.view.frame.size.width, height: self.view.frame.size.height - self.view.safeAreaInsets.bottom - self.view.safeAreaInsets.top)

        default:
            print("取得出来ませんでした")
            
        }
    }
```

#終わり
検知自体はそこまで難しくは無いですね。
あとは、何を処理させるかですね。
まだ、UIDeviceで面白そうなプロパティがあったので試してみたいです。
ご指摘、ご質問などありましたら、コメントまでお願い致します。
OS や開発言語の〇〇PATHって何よ？　①シンジツはいつも一つ！！

# PATH PATH PATH!!
プログラム環境を整えていると、**PATH** って言葉がたくさん出てきます。多くの場合、**「おまじない」** とか **「最初の準備だけ」** とか割と適当に流されます。今はやりのプログラミング学習サイトでは、そもそも環境構築の手順すら教えません。そうすると、自分の開発環境を整えようとした瞬間、**PATH？なにそれ食べられるの？** となるわけです。

**おまじないも、最初の準備も1つだけなら確かにそうです。** でも、普通に開発やっていれば導入する開発環境も1つではなく、対象となる環境も自分のＰＣだけとは限りません。

そんな時、概念とか基本的な考え方を知っているのと知らないのとでは雲泥の差です。また、自分で書くプログラムでも応用が利くかもしれません。この記事は**PATH? 食べられる？何それ？** な初めての人に、概念を伝えるものです。 **また、説明のしやすさを優先するので、必ずしも厳密ではありません。**


コンピュータって、普通に思うより。 **頭良くありません**

* 自分で「何をすればいいか」を考えることはできない。
* 自分で「何かを探すこと」はできない。

ほんと。頑固で融通の利かない、子供みたいな存在です。なにがどこにあって、 **「ほらここにおいてやったよ。これを使ってね」** と教える必要があります。

### コンピュータは融通が利かない

ほんと、コンピュータって融通効かないですよね。自分のやるべきことを教えてもらっても。**「やらせること、ものは一つに絞ってね。2つとか嫌だからね！！」** ということが要求されます。まるで **「プレゼント。ほかの友達とかぶったら、殺すからね」** と強要する彼女の様です。いやこういう人とはお別れしたいですが。。コンピュータとお別れしてはいけません。我慢強くわがままを聞いてあげる必要があります。なにせ相手は子供です。

##### 部屋を分けないとね
同じものを一つの部屋に入れられないときどうするか？　部屋を分けて別々に保管します。コンピュータの世界でこういう「部屋を分けて名前がかぶらないようにするよ！！」という場合、「部屋」にあたる考え方を **「名前空間」** と呼んでいます。 

ある学校に「木村」さんは3名います。この時それぞれの木村さんを区別して呼ぶにはどうすればいいでしょうか？

- 荒川　： この前、木村さんがさぁ
- 伊藤　：あぁ、知ってる知ってる。書道で賞もらったんだよね？
- 宇佐美：え？？違うよ、音楽コンクールで予選通ったんだよね？
- 荒川　：え？何言ってるの？　給食の時に転んじゃったんだよ

想定される「木村」さんが3人いるので、誰の事だかわからないのです。名前異空間の活躍の場所はこんな時です。 ~~本名つければいいんですが。 そこはおいておいて~~ おそらくこんな感じになります。

- 荒川　：この前、**3組の**木村さんがさぁ
- 伊藤　：知ってる知ってる。ころんじゃったんだよね
- 宇佐美：え？いつ？
- 荒川　：給食の時だよ

お、なんとなくスムーズです。この場合、同じ「木村」さんを **「3組」という「名前空間」** を用いて区別しているわけです。こういうの、コンピュータの世界ではよくあります。

##### 名前空間の例

|No.|使いどころ、言語|名前空間|目的|
|--|-----|-----|---|
|1.|WEB派生技術|URI|リソースをユニークに特定するという意味で、名前空間として利用される|
|3.|Java|パッケージ|同一のクラス名、インターフェース名の存在を許容する。|
|4.|Java|クラスローダ|javaのクラス定義は、厳密にはFQDNレベルで同一のオブジェクトを同一の処理系に保持できます。これは、クラスローダが「名前空間」としてユーザの見えないところで働いているからです。|
|5.|XML|namespace(xmlns)|少しずつ機能の違うタグを定義する。|
|6.|K8s|namespace|クラスタ内部のオブジェクトそのものの名前重複を避ける。|

昔のものからイマドキのものまで、実に広い範囲で利用されています。そのほか、アイデアはいろいろなところで利用されているので気付いたら、考察してみてください。
(肝心要のPATHはここでは触れません。)

### みんながよく知ってる「名前空間」

ここまでの話をまとめると。

* 名前空間は「同じ名前」を区別して管理するために導入する
* 同一名前空間の中では、「同じ名前のもの」は存在することができない。（ユニークに区別できないので）

あれ？これ、Windowsの「フォルダ」とかUNIX/Linux/Macの「ディレクトリ」にあてはまりませんか？
**その通り。そもそもファイルの名前空間を分割するための仕掛けがフォルダだったり、ディレクトリです。**　コンピュータリソース的な背景とかいろいろあるんですが。そこはまぁ目をこぼしておきましょう。

長くなったので、この記事はここまで、次回は本格的にPATHの話に移ります。

# まとめ

この記事の話をまとめます。

* コンピュータは融通が利かない
* コンピュータの操作の対象、やることは常に一つ！！「真〇は常に一つ!!」
* 名前空間は超便利
* ディレクトリ、フォルダも名前空間の側面をもつ
Java　ど初心者メモ①

ど初心者メモ：

２の２乗を8回行う。
public class Main{
	　　public static void main(String[] args) {
		　　　int x = 1;
		　　　for(int i = 1; i <= 8; i++) {
			　　　　x *= 2;
			　　　　System.out.println("2の" + i + "乗は" + x );
		　　　}
		
		
　　}
}

Javaを使えるようになるのだろうか....はぁ....
ABC194 C - Squared Error から学んだ

https://atcoder.jp/contests/abc194/tasks/abc194_c

![abc194_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/55166834-cb3a-f1c8-ba7f-7aae40174cf6.png)

ふむふむ。サンプルを見てみよう

![abc194_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/93858539-9905-7a53-b3c0-105cbbaf97cc.png)

うーん。シグマ使ってるけど、結局、
A の要素の組み合わせで差 => 二乗 で良くね？

だがしかし、WA

```SquaredError_r0.py
N = int(input())
A = list(map(int,input().split()))

#辞書で要素をリスト 
dic = {} 
for i in range(N):
    if A[i] not in dic:
        dic[A[i]] = 0
    dic[A[i]] += 1

#配列長の N でカウントすると 3*10^5 もあるので
#条件の|A|<200 を使って combination すれば良いかと。
score = 0
from itertools import combinations
for a,b in combinations(range(-200,201),2):
    if a in dic and b in dic:
        score += (a-b)**2
print(score)
```

結局、条件には A の要素は全て異なる値とは書いていない。
もしかして重複する可能性もあるのか？
解説を聞いたが、自分の力不足なのか、ピンとこない。

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

有識者の解答を見るとしっくり来るものを見つけた。
結局、重複したことを前提に書き換えると良いみたいだ。

```SquaredError_r1.py
N = int(input())
A = list(map(int,input().split()))

dic = {}

for i in range(N):
    if A[i] not in dic:
        dic[A[i]] = 0
    dic[A[i]] += 1
score = 0
from itertools import combinations
for a,b in combinations(range(-200,201),2):
    if a in dic and b in dic:
        score += dic[a]*dic[b]*(a-b)**2# <= dic[a], dic[b] の値を掛けた。
print(score)
```

試しに 1,2,2,1 or 1,2,3,1 で試してほしい。
手書きで全部列挙して計算すると驚きが待っている。
【Flutter】アプリアイコンを変更する方法

## 【Flutter】アプリのアイコンを変更する方法

こんにちは。
今回はFlutterのデフォルトのアイコンを変更する方法がめちゃくちゃ簡単だったので、
Qiitaに残します。

### 内容
デフォルトのお洒落なアイコンをこんな簡単にダサくできます。
![スクリーンショット 2021-09-17 23.14.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1976926/360c82cc-c011-5b73-78ae-834c463c516f.png)

一ヶ月前くらいに試したときは専用のジェネレーター（[App Icon Generator](https://appicon.co/)）使ってディレクトリに格納して〜
みたいな感じで意外にめんどくさいなと感じてたんですが、flutter_launcher_iconsパッケージを使えばすぐに実装できました。

https://pub.dev/packages/flutter_launcher_icons

まず、`pubspec.yaml`に記述。

```yaml:pubspec.yaml
dev_dependencies:
  flutter_launcher_icons: ^0.9.2
```
次にアイコンにしたい画像をディレクトリに格納。
デフォルトで作成される`assets`の下に`images`を作っているのでそこに画像をペースト。
そして格納した画像を読み込みます。

```yaml:pubspec.yaml
dev_dependencies:
  flutter_launcher_icons: ^0.9.2
# ↓記述
flutter_icons:
  android: true
  ios: true
  image_path: "assets/images/icon.png"
```

最後に

```
flutter pub get
flutter pub run flutter_launcher_icons:main
```

ビルドして終了です。

某プロスポーツ選手もFlutterを始めるみたいなので、
これから自分も負けないようにFlutterを楽しんでいきたいなと思います。

## 参考文献

https://pub.dev/packages/flutter_launcher_icons
👵インターネット老人👴のためのホームページ（死語）リフォーム術

# この記事の対象
～00年代初頭にホームページ作っていて、現在放置中……という人、あるいはそういう人から依頼されて昔のフォルダを受け取った人が対象になります。
スキル的にはjQuery(Bootstrap)なら何とか勢～（バックにも関心がある）SPA初心者勢を想定しています。

# 手順
## 1.本当に自前でやる必要があるか考える
Webサービスが氾濫する現在、現在サイトにある機能を本当に自前で提供する必要があるか考えましょう。

### 日記
まぁ**最有力はブログへの移行**ですね。黒歴史を消す人も多いですが、逆に過去の日記みたいなもんで、残しておきたいと思う人もいるかと思います。ていうかホームページは放置してて日記にあたる部分だけ流石にブログに移行してる人も多いかと思いますね。
何らかの理由でブログに移行できない、不適切だと思う場合はスクレイピングして文章データをmdやらjsonに纏めて、今流行りのGatsbyあたりに手を出すのも良いのではないでしょうか。

### イラスト
これは現行のシェアとしてもシステム的にも**[pixiv](https://www.pixiv.net/)へ丸投げするのが一番妥当**かと思います。
画像ギャラリー系のライブラリを入れて自前のサイトで見せることもできますが、pixivと二重管理になって放置する可能性が高いかと。

### 小説
**これは難しい。**投稿サイトは昔から山ほどありますが、[なろう](http://syosetu.com/)を始め色がついてたりするので……。（2～3年で閉鎖しないという意味で）安定してて、ジャンル問わずで一強みたいなのがあればいいんですが。
あと00年代初頭って「Web小説ならではリッチ表現を目指そう」的な流れもあって、小説本文中に挿絵画像ぶちこんだり、JSやフォントタグ弄りやってたりする小説もそこそこあるので、そこらへん守る必要がある（ギミックが前提）があったり、その系譜を現代の技術で更に進化させたいという気骨の方は自前も全然アリだと思います。

### 掲示板
**これも難しい。** SNSの直接交流やハッシュタグ交流で代替できちゃってそうで完全には出来てないので、「アカウントを持たなくても書ける、個人管理のフォーラム」のニーズは確かにあるんですよ。
ただ当時でいうところのCGI（死語）がPerl/PHP＋ただのログファイルで出来てたのに対し、現在はバックエンド系言語(Ruby/PHP等) + フレームワーク + DBが普通かつ、今時の設計だとバックエンドはAPIのみとなって、表示面はフロントエンドでやる必要があると敷居上がりまくってるんですよね。真っ向からやるにはバックエンドの勉強をガッツリしないときついかと。
OSSのフォーラムアプリも調べましたが、需要がニッチ化したのと、今だとバックエンドAPI+フロントエンドのセット提供になり、なおかつ密結合にならざるを得ないので、今一つ開発が盛り上がってない印象を受けました。現行問題なく動いてるのならそのまま＋SNS交流で逃げてもいいのではという感触はありますね。
ゲーム系チャットアプリのイメージが強いですが、[discord](https://discord.com/)とかで丸投げできないかなーというのは考えたりしますが、使ったことがないので（ry

### チャット
掲示板と同じく[discord](https://discord.com/)に丸投げできないかな～（ry


# 2. WebスクレイピングしてHTMLから実データを取り出して整形する
昔はHTMLファイルの中に装飾データ（fontタグ）や実データを含めて全てが詰まっていたので、解析してオブジェクトの形に纏める（＝スクレイピング）のは必須ですね。**DOMを、tableタグを、ひたすら掘り続けるのだ……**⛏
ゲーム攻略サイトとかデータ系サイトはここの工数を覚悟しといた方がいいです。抽出もさることながら、使い勝手が悪いとか色々データ整形したくなると思うので、延々とデータ整形することになります（体験談）
ところでスクレイピングといえばPython （というかBeautifulSoup）がオススメとされていますが、「Webフロントエンド系の技術は仕方ないにせよ、Pythonまで手出すのはキツイ……」と思う方も多いかと思います。
そういう方は、そもそも自分のサイトであることを活かし、

1. ローカルの開発サーバー（手っ取り早いのはVSCodeの拡張機能のLiveServerとか）を用意
2. 自サイトにJSのスクレイピングプログラムを仕込んでデータオブジェクトを作る
3. 以下のJSでJSONファイルを生成してダウンロードさせる

```ts
export const downloadJsonFile = (data: unknown, baseName: string): void => {
	const blob = new Blob([JSON.stringify(data)], { "type": "application/json" })
	const fileName = `${baseName}.json`
	const url = URL.createObjectURL(blob)
	//aタグを生成し、クリックしたことにしてDLさせるというアプローチを取る
	//かなり無理くり感あるが現状これがベストプラクティスな模様。
	const aTag = window.document.createElement("a")
	document.body.appendChild(aTag)
	aTag.download = fileName
	aTag.href = url
	aTag.click()
	aTag.remove()
	URL.revokeObjectURL(url) //生成したURLが保持されてしまうので解放する
}
```

こういう感じで対処しましょう。ちなみに自分はJSでファイルを生成→DLさせられるのを知らなくて、途中までconsole.logに吐き出し→エディタにコピペでせっせとJSONファイルを作ってました😨 

参考:[JavaScriptでファイルダウンロード処理を実現する - Qiita](https://qiita.com/wadahiro/items/eb50ac6bbe2e18cf8813)


# 3.旧サイトとの連携を気にしつつ好きな技術で作り直す
わざわざ作り直したいと思うぐらいですし、サイトの規模としてはそこそこ大きいですよね？となると、旧サイトと繋がりを意識しつつ徐々に入れ替えていく形を取る方が良いかと思います。
技術面に関しては関心のあるお好きな技術で……としか言いようがありませんが、最近のトレンドから言うと大規模→React/小規模→Vueという形になるのかなと思います。
また元が静的なウェブサイトという特性からリフォーム後も静的な特性が強いかと思われるので、SSGとの親和性が高いのかな～とも感じます。

# アイデア募集
この記事はどっちかというと「（おっさん）初心者プログラマーが現代フロントエンドを学習しながらDIY精神でリフォームする🛠」方向なんですけど、既存のサービスを駆使して、パッと作るというのも全然アリだと思います。
そっち方面は詳しくないので、もし何か使えそうなサービスがあれば教えて下さい。
MariaDB(MySQL) でストアドファンクションで3値論理を返す

「MariaDB(MySQL) でストアドファンクションでローカル変数を使う」
https://qiita.com/nanbuwks/items/dbcf8790d73c0afa63bc

において、1 と 0 ( True/False )の2値論理で結果を返す関数を作りました。

今回は、格納されているレコードが条件にマッチすれば1,マッチしていなければ0,レコードが存在しなければ-1を返す3値論理を返すようにしてみます。


先のストアドファンクションでは

```

DELIMITER //
 CREATE FUNCTION IS今年のアクセス(_会員番号 TEXT) RETURNS INT NOT DETERMINISTIC
 BEGIN
 DECLARE _アクセス年 INT ;
 SELECT アクセス年 INTO _アクセス年 FROM アクセス記録 WHERE 会員番号=_会員番号;
 IF _アクセス年 = 2021 THEN    RETURN 1;
   ELSE    RETURN 0;
 END IF;
 END//
DELIMITER ;
```

としていて、ストアドファンクションで IF 文を使って場合分けしていた。
結果が空行でも ELSE RETURN 0 となって 0 
が返る。

そうではなくて、結果が空行の場合は -1 などを返すようにするにはどうしたらいいかな？


SELECT 文中で場合分けするには CASE 文を使うことができる。しかしながら CASE 文は空行結果には適用できない。したがって検索結果が該当なしの場合は NULL を返すようなサブクエリと組み合わせた上で CASE 文を使うテクニックをつかったりすることになり、可読性が悪くなる。


しかしながらストアドファンクションの場合は 結果がNULL かどうかを IF文で判定できるので簡単。


上記のストアドファンクションを以下のようにすれば良い。

```

DELIMITER //
 CREATE FUNCTION IS今年のアクセス(_会員番号 TEXT) RETURNS INT NOT DETERMINISTIC
 BEGIN
 DECLARE _アクセス年 INT ;
 SELECT アクセス年 INTO _アクセス年 FROM アクセス記録 WHERE 会員番号=_会員番号;
 IF _アクセス年 IS NULL THEN RETURN -1;
   ELSEIF _アクセス年 = 2021 THEN    RETURN 1;
   ELSE    RETURN 0;
 END IF;
 END//
DELIMITER ;
```

実行結果

```
MariaDB [test]> SELECT IS今年のアクセス("123-4567");
+---------------------------------+
| IS今年のアクセス("123-4567")    |
+---------------------------------+
|                              1 |
+---------------------------------+
1 row in set (0.009 sec)

MariaDB [test]> SELECT IS今年のアクセス("123-4568");
+---------------------------------+
| IS今年のアクセス("123-4568")    |
+---------------------------------+
|                              0 |
+---------------------------------+
1 row in set (0.009 sec)

MariaDB [test]> SELECT IS今年のアクセス("999-9999");
+---------------------------------+
| IS今年のアクセス("999-9999")    |
+---------------------------------+
|                             -1 |
+---------------------------------+
1 row in set (0.009 sec)



```
Seabornってすごいのよ！

# はじめに
僕は理系大学生として日々Pythonで遊んだり苦戦してたりしてます．
そのなかでmatplotlibを使うことがよくあるのですが少しめんどくさい(できることが多すぎて手間が多い)と感じます．
なので今回はもっと手軽に使えておしゃれにプロットできる個人的最強ライブラリ"Seaborn"についてです．

# Seabornとは
Seabornとは簡単に言うと`Pythonで使えて簡単にそれっぽく見せられるグラフ描画ライブラリ`です
僕も詳しくその概要を説明できるわけではないですが，Seabornはmatplotlibの機能を利用しています．そのためグラフの調整や大まかなルールはmatplotlibと一緒です．

# インストール方法

```
!pip install seaborn
```
※seabornをインストールする際"numpy","matplotlib","pandas"他も同時にインストールします．すでにインストールしている場合，バージョンの違いなどによって実行時エラーが発生する可能性があります(僕はそのエラーが何かわからず1時間ネットの海をさまよった)のでよくわからないエラーが出たら一度上記のライブラリをアップグレードしてみてください．

# 何ができるの？
Seabornは上記の通りmatplotlibをもとに作られています．なのでmatplotlibでできることはすべてできます．
さらにタイタニック号のデータなど有名なものはもともと入っているのでデータビジュアライゼーションの学習にはとても適しています．
「Seaborn hogehoge」と調べると大体この中に入っているデータを使っている記事が出てくるのでマネしやすいです

#試しに
ということで早速Seabornのすごさを体験してみましょう．

``` python
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

df = sns.load_dataset("titanic")
df.head()
```

`df`にはタイタニック号のデータが入っています．冒頭五行を見てみることうなっているはずです．(後半は省略してます．)

|survived |pclass |sex |age |sibsp |---|
|---|---|---|---|---|---|
|0 |3 |male |22.0 |1 |---|
|1 |1 |famale |38.0 |1 |---|
|1 |3 |female |26.0 |0 |---|
|1 |1 |female |35.0 |1 |---|
|0 |3 |male |35.0 |0|---|

まずはmatplotlibのほうで描画してみます．

```python
plt.bar(x="sex",height="age",data=df)
plt.show()
```

![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112260/3b718984-1fed-039f-8186-9f4c9db2d5c7.png)

`これ間違えてます明日更新するのでちょっと待っててください`
よくあるありきたりなグラフです．
これがSeabornだと…

```python
sns.set()
sns.barplot(x="sex",y="age",data=df,ci=None)
plt.show()
```

![output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112260/787dd9a5-603c-906d-3376-fa1c94fc8eb1.png)
なんかいい感じにしてくれましたね

#疲れたのでこれ以降はまた今度
Flutter Null Safety を無効化したい

flutterのバージョンが2.0になったことにより、Null Safetyが導入されました。

flutter2.0ではあるがNull Safetyを無効化し、現段階ではNullableで開発したいという一時的な状況もあるかと思います。

そのための方法を紹介します。

```pubspec.yaml
environment:
  sdk: ">=2.12.0 <3.0.0"
      #2.12.0以上の可能性もあります
```
から

```pubspec.yaml
environment:
   sdk: ">=2.7.0 <3.0.0"
```

にプロジェクトが許容するSDKの最低バージョンを下げてください。そうすればNull Safetyを無効化できます。
[初学者]javascriptのクロージャー

#はじめに
while文とかfor文とか~文あるけど、あれは関数なのか？の疑問から生まれたものです。
文の正体は分かりませんでした。


#目次
　1.ループ文の謎
　2.ガベージコレクション？　ガレージコレクションなら知ってます。
　3.静的スコープとはなんですか？ 
　4.クロージャー

#ループ文の謎
ループ文とはご存知でしょうか？基礎で出てくるあれです。

```
for(let i = 0; i < 5; i += 1) {
  console.log(i);
}
// 0,1,2,3,4と出ます。
```

基礎の基礎のループ文。
ではあえて関数で書くとどうやって書くのかを疑問に持ちました。

```
let a = 0;
function A() {
  a += 1;
  console.log(a);
};

A(); //1
A(); //2
A(); //3
A(); //4
A(); //5
```

普通に出ますね。ではlet a = 0;を関数内に入れてみましょう。

```
function A() {
  let a = 0;
  a += 1;
  console.log(a);
};

A(); //1
A(); //1
A(); //1
A(); //1
A(); //1
```

関数内に入れたら数字が全て1になってしまいました。
私みたいな初学者には、関数の中と外なんて似たりよったりやんと思いますが結果から見ても違います。

#ガベージコレクション？　ガレージコレクションなら知ってます。
簡単に言うと必要なタイミングで不要なデータをメモリから解放するものです。
人間が不要な記憶を消すようなもので、ここで重要なのは不要と判断されるタイミングです

```
let A = 1;
A = 2;  //変数Aに２が代入されたことにより1が解放される。
console.log(A);　//2
```

これは関数でも起きます。解放されるのが先程の変数を中に入れたループ関数です。
ここで思うのは関数が終わったタイミング変数のデータは解放されると思いますが違っていて
次に解放されないパターンです

```
function A() {
  let a = 0;
  return a;
};

const B = A();
console.log(B); //0
```

やってることはリターンで返して変数に入れてるだけです。( )は関数の実行をします。
const B = A( );としているので関数自体は実行されてますが結果としてはコンソールに0と表示されます。
実際にデータが解放されるのはどこからも参照されなくなったときに解放されます。
この場合関数が終了してもconst Bに参照されてるため消えません。

#静的スコープとはなんですか？ 
一言でいえば変数の参照は変わらないってだけです。
javascriptは静的スコープですが他言語では動的スコープもあるらしいです

```
const a = 1;

function A() {
    console.log(a);
}

function B() {
    const a = 2;
    A(); 
}

B(); //1
```

loa(a)は最初に上の１を参照します。その後別の関数に値の変わった変数があるのに結果は1が出る

#クロージャー
片やデータの解放、片や参照元が変わらない。それで何が出来るんじゃいという話。クロージャーになります。
これも簡単にいうと関数にデータ保持させたろってことです。

```
function A() {
  let count = 0;

  function B() {
    count += 1;
    return count;
  }
  return B;
}

const C = A();
console.log(C()); //1
console.log(C()); //2
console.log(C()); //3
console.log(C()); //4
console.log(C()); //5

```

まぁこれだけ見るとショボって思うでしょう。私も思います。
グローバル変数が減るのと関数に状態を持たれるのがメリットとのことです。
試しに作ったけど、うん。何がすごいかわからない。入力値が5に対しての関数です。

```
function A(a) {
  return function B(b) {
    if(a > b){
      console.log(a + "の方が大きい!");
    } else if (a < b) {
      console.log(a + "より小さい!");
    } else {
      console.log("値が同じ!");
    }
  }
}

const A5 = A(5);
A5(2); //5の方が大きい!
A5(4); //5の方が大きい!
A5(6); //5より小さい!
A5(8); //5より小さい!
A5(5); //値が同じ!
```

#おわり
軽い気持ちで調べたらえらくかかりました。クロージャーの凄さは分からなかったですがいつか使うでしょう。
何か個人的に画期的にものが思いついたらまた書きます。