OmniAICreator/Qiita-1.07M huggingface dataset:
「Visual Studio Codeはこの大きなワークスペースでファイルの変更を監視できません」のエラーが出ない様にする

# 目的

- 題名のエラーを出力されない様に設定する。

# 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| Visual Studio Codeバージョン | 1.47.3 | こちらの方法で導入→[Mac Visual Studio Code 導入方法 VSCode ダウンロードから日本語化対応まで～画像付き導入解説～](https://qiita.com/miriwo/items/4ed96b54b4421fe9d275) |

# 問題までの経緯

1. 下記コマンドを実行してカレントディレクトリをVisual Studio Codeで開こうとした。

    ```terminal
    $ code .
    ```

# 問題

1. 下記のエラーがウインドウ右下に出力された。

    ```terminal
    Visual Studio Codeはこの大きなワークスペースでファイルの変更を監視できません
    ```
1. 日本語化プラグインを入れていない時は下記が出力された。

    ```terminal
    Visual Studio Code is unable to watch for file changes in this large workspace
    ```

# 問題解決までの経緯

1. 下記コマンドを実行して設定ファイルを開く

    ```terminal
    $ sudo vi /etc/sysctl.conf 
    ```
1. 下記情報を追記する

    ```/etc/sysctl.conf
    fs.inotify.max_user_watches=524288
    ```
1. 保存して閉じたあと下記コマンドを実行して設定を反映する

    ```terminal
    $ sudo sysctl -p
    ```

# 参考文献

- [https://code.visualstudio.com/docs/setup/linux#_visual-studio-code-is-unable-to-watch-for-file-changes-in-this-large-workspace-error-enospc](https://code.visualstudio.com/docs/setup/linux#_visual-studio-code-is-unable-to-watch-for-file-changes-in-this-large-workspace-error-enospc)
Vimのカラースキームの配色がおかしくなる...

[iceberg][i]といういい感じのカラースキームがあったので、vimに導入しようとしたら配色がおかしくなってしまいました...
これを直すために数時間かかったので備忘録としてここに残します。

# 環境
一応書いておきます。
OSはwindows10で、docker上のUbuntuのVimです。Vimのバージョンは以下の通りです。

```
VIM - Vi IMproved 8.1 (2018 May 18, compiled Apr 15 2020 06:40:31)
```

# 具体的な症状
- 理想

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678998/e1b8e6a4-e847-cf3d-1253-5ff42670e027.png" width=70%>

- 現実

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678998/c43cc1d9-2f51-ff31-807e-0bd527510862.png" width=70%>

こんな感じになります。配色がおかしくなっています。

# 解決法
```
set t_Co=256             
colorscheme iceberg      " 適用したいcolorscheme
set bg=dark
```
~~適用したいcolorscheme(この場合は[iceberg][i])の前にset t_Co=256とcolorscheme [jellybeans][j](適当なカラースキーム)とすると配色が直りました。同じようなところで躓いた方はためしてみてください。~~

[8/11に修正しました。]
[iceberg][i]がライトテーマになっているのが原因だったようです。set bg=darkでダークテーマになります。コメントしてくださった方ありがとうございます！！

# おまけ
この記事の中で使っているカラースキームの[iceberg][i]と[jellybeans][j]はどちらも落ち着いた配色でとてもいい感じです。デフォルトのカラスキームに飽きた方はぜび使ってみてください。おまけとして[iceberg][i]と[jellybeans][j]のスクリーンショットを載せておきます。

- [iceberg][i]
<img src="https://camo.githubusercontent.com/5f26868fd936695c97a02883a5a13fdc055eafd2/68747470733a2f2f636f636f706f6e2e6769746875622e696f2f696365626572672e76696d2f6173736574732f6769746875622f73637265656e73686f742e706e67">

- [jellybeans][j]

<img src="https://camo.githubusercontent.com/707cd3e91122014ee4b6273e6873838e5b5df558/68747470733a2f2f6e616e6f746563682e6e616e6f74656368636f72702e6e65742f646f776e6c6f6164732f6a656c6c796265616e732d707265766965772e706e67">

[i]:https://github.com/cocopon/iceberg.vim
[j]:https://github.com/nanotech/jellybeans.vim
コメント投稿機能

アウトプット備忘録です。

簡単な掲示板のコメント機能を実装していたのですが、エラーはでないのですが投稿出来ず。
下記コード

```top_page>show.html.haml
.main
  = form_for @comment , url:{controller: 'responses', action: 'create'}do |f|
    .main__consultation
      .main__consultation__title
        お悩み一覧
      .main__consultation__text
        = @toppage.contents
    .main__comment
      = f.text_area :comment, class: "main__comment__form"
      .main__comment__sent
        = f.submit "投稿する"
      .main__comment__text
        <コメント一覧>
      -if @comments
        -@comments.each do |response|
          .main__comment__main
            .main__comment__main__name
              = response.user.name
            .main__comment__main__form
              = response.comment
```

```response_controller.rb
class ResponsesController < ApplicationController
  def create
    response = Response.create(response_params)
    redirect_to root_path
  end

  private
  def response_params
    params.require(:response).permit(:comment).merge(user_id: current_user.id, top_page_id: params[:top_page_id])
  end
end
```

```top_page_controller.rb
class TopPageController < ApplicationController
  def index
    @toppages = TopPage.all
  end

  def new
    @toppage = TopPage.new
  end

  def create
    TopPage.create(top_page_params)
    redirect_to top_page_index_path
  end

  def show
    @toppage = TopPage.find(params[:id])
    @comment = Response.new
    @comments = @toppage.responses.includes(:user)
  end

  private
  def top_page_params
    params.require(:top_page).permit(:contents,:name).merge(user_id: current_user.id)
  end
end
```

これでエラーはでないのですが投稿はされず。
binding.pryをかけた結果
<img width="1255" alt="20200807101155.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653208/ad2e8081-a6e2-711b-9bc8-1282e0636978.png">

top_page_id（投稿ページのid）に何も入っていないことが原因？と考えられたので

下記修正

```top_page>show.html.haml
.main
  = form_for @comment , url:{controller: 'responses', action: 'create'}do |f|
    .main__consultation
      .main__consultation__title
        お悩み一覧
      .main__consultation__text
        = @toppage.contents
    .main__comment
      = f.text_area :comment, class: "main__comment__form"
      = hidden_field_tag :top_page_id, value: @toppage.id
      .main__comment__sent
        = f.submit "投稿する"
      .main__comment__text
        <コメント一覧>
      -if @comments
        -@comments.each do |response|
          .main__comment__main
            .main__comment__main__name
              = response.user.name
            .main__comment__main__form
              = response.comment
```

= hidden_field_tag :top_page_id, value: @toppage.id
を追加しました。

今回はfield_tagは１つの単体のパラメーターを渡すときだけ使用可能の様。
はじめて初めて使いました。
こちらも参考にしたいところ
https://qiita.com/yukiweaver/items/8e1e01fd6dcadf36d420
rails5中級チュートリアルのテストがうまく通らなかった時

### 前提・実現したいこと
[rails5中級チュートリアル](https://techracho.bpsinc.jp/hachi8833/2018_02_21/51678)を行なっています。
チュートリアルの3-3でのテストの部分で
昨日から以下のエラーが発生し、テストをパスすることができず、困っていた。

### 発生している問題・エラーメッセージ

 ターミナルでのrspec spec/features/user/login_spec.rb実行時

```ruby
  1) Login ユーザーがloginページにリダイレクトされ、ログインに成功する
     Failure/Error: expect(page).to have_selector('#user-settings')
       expected to find css "#user-settings" but there were no matches
     # ./spec/features/user/login_spec.rb:13:in `block (2 levels) in <top (required)>'

Finished in 4.17 seconds (files took 2.75 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/features/user/login_spec.rb:6 # Login ユーザーがloginページにリダイレクトされ、ログインに成功する
```

### 該当のソースコード

```ruby:login_spec.rb

require "rails_helper"

RSpec.feature "Login", :type => :feature do
  let(:user) { create(:user) }

  scenario 'ユーザーがloginページにリダイレクトされ、ログインに成功する', js: true do
    user
    visit root_path
    find('nav a', text: 'ログイン').click
    fill_in 'user[email]', with: user.email
    fill_in 'user[password]', with: user.password
    find('.login-button').click
    expect(page).to have_selector('#user-settings')
  end

end

```

### 試したこと
①エラー文で検索をかけるも、手がかりを見つけることができなかった。

②エラー文にcssの"#user-setting"とhave_selectorの"#user-setting"が一致しないとあるため、cssの"#user-setting"に問題があると仮説するが、そもそもcssに"#user-setting"というものがなくどうすれば良いのかすらわからない状態であった。

③vscodeの文字列検索で[user-setting]と検索した際に、[_signed_in_links.html.erb]ファイル内でuser-settingをidとして定義してある箇所があったためそちらの記述を"#user-setting"に変更してみたが、解決することができなかった。

```ruby:_signed_in_links_html.erb
<li class="dropdown pc-menu">
# この下の行の"user-settingを変更を試した"
  <a id="user-setting"  class="dropdown-toggle" data-toggle="dropdown" href="#">
   <span id="user-name"><%= current_user.name %></span>
   <span class="caret"></span>
  </a>

  <ul class="dropdown-menu" role="menu">
   <li><%= link_to 'プロフィールを編集', edit_user_registration_path %></li>
   <li><%= link_to 'ログアウト', destroy_user_session_path, method: :delete%></li>
  </ul>
</li>

<li class="mobile-menu">
  <%= link_to 'プロフィールを編集', edit_user_registration_path %>
</li>
<li class="mobile-menu">
  <%= link_to 'ログアウト', destroy_user_session_path, method: :delete %>
</li>
```

###解決方法
一日以上時間を費やしては埒が明かないと考え,teratailで質問を投げかけたところ解決。
上記にある試したこと③にもある_signed_in_links_html.erbでのid指定を#user-settingsではなく
user-settingsに修正したところテストを通過することができた。


###学び
cssセレクタでは、＃はid属性、.の場合はclss属性ということを完全に忘れてしまっていた。
### 補足情報（FW/ツールのバージョンなど）

vscode最新バージョン使用
railsバージョン　5.1.7
bootstrap

テストツール
factory_bot_rails
capybara 2.15
rspec-rails
selenium-webdriver
rails-controller-testing
headless
poktergeist
Java: ストリームとループってどっちが速いの問題

やる前から予想は付いてるけど、形にしておくことも重要だと思います。

# ストリームの処理速度ってどうなんでしょうか

Java言語におけるストリームは、流れにそった記述ができるということで、うまく使えば可読性に優れたコード、すなわち挙動の予測が付きやすいものへと移行できる可能性を持つ機能です。分岐の発生しにくい流れで記述できると気持ちよくなりますよね。

とはいえ、実行時のことを考えたとき、本当にストリームで良かったのかということになります。
良くありそうなのが、ループ処理で書いていたことをストリームにするような行為です。

# 試してみよう

ということで、**100万回乱数を発生してすべて足し込む**という処理にかかる時間を計測してみます。実行環境はWin10Pro(i5, 8GB RAM)です。

```java:InfinitTest2_loop.java

public class InfinitTest2_loop {

	public static void main(String[] args) {
		Double result = 0.0;
		var start = System.currentTimeMillis();
		for (int i = 0; i < 100 * 10000; i++) {
			result += Math.random();
		}
		var end = System.currentTimeMillis();
		System.out.println(result);
		System.out.println("所要時間(ミリ秒): " + (end - start));
	}
}

```

このコードをさっとストリームに変換してみます。`reduce()`に渡して足し込み処理までを記述してみます。

```java:InfinitTest2.java
import java.util.stream.Stream;

public class InfinitTest2 {

	public static void main(String[] args) {
		var start = System.currentTimeMillis();
		Double result = Stream.generate(Math::random)
					.limit(100 * 10000)
					.reduce((p, q) -> p + q).get();
		var end = System.currentTimeMillis();
		System.out.println(result);
		System.out.println("所要時間(ミリ秒): " + (end - start));
	}
}
```

ということで両者を実行してみた。それぞれ3回実行したときのミリ秒です

- ループ版: 45,41,39
- ストリーム版: 63,71,70

ループ版はストリーム版の70%程度ほ処理時間で動いてます。うん、やっぱり下手にクラスの処理が入らないループ版の方が速いんですね。

# バカにできない「最適化」

ここで終わりにしてはいけない気がします、Javaは実行環境も含めたJavaです。たとえば、Java VMをサーバーモードにすると、通常のVM(ClientVM)においては実行中の最適化を意識するところを、実行前に可能な範囲で最適化を試みることになります。

```powershell
PS> java -server -cp . InfinitTest
499714.1320036936
所要時間(ミリ秒): 63
```

あれ? たいして変わらない、ただし繰り返したときに65ミリ秒までにおさまってますので、「可能な範囲での最適化」は試みてるみたいですね。

あともうひとつ最適化という話になると、さらっと出ていた「実行中の最適化」という問題で、「よく実行している部分を順次最適化していく」という動きです。つまりループするならその部分が最適化によって高速化しないのか?ということです。

先ほどの処理を大量にループするようにします。この部分は差違が発生しないよう、どちらも`for`を使って書くことにしておきます。

```java

public class InfinitTest2_loop {

	public static void main(String[] args) {
		for (int n = 0; n < 100; n++) {
			Double result = 0.0;
			var start = System.currentTimeMillis();
			for (int i = 0; i < 100 * 10000; i++) {
				result += Math.random();
			}
			var end = System.currentTimeMillis();
			System.out.println(result);
			System.out.println("所要時間(ミリ秒): " + (end - start));
		}
	}

}
```

```java
import java.util.stream.Stream;

public class InfinitTest {

	public static void main(String[] args) {
		for (int i = 0; i < 100; i++) {
			var start = System.currentTimeMillis();
			Double result = Stream.generate(Math::random).limit(100 * 10000).reduce((p, q) -> p + q).get();
			var end = System.currentTimeMillis();
			System.out.println(result);
			System.out.println("所要時間(ミリ秒): " + (end - start));
		}
	}
}
```

と、100回繰り返すようにしてみました。
途中で最適化が入り始めるのか、ミリ秒出力が徐々に減っていきました。

最後の3回をそれぞれ出してみるとこうなりました。

- ループ版: 33,34,22
- ストリーム版: 32,30,39

あら、けっこう差が縮まってる(それでもループ版が速いけど)。

ということで、ループ処理をストリームに置換すべきにおいて、速度を意識しないといけない場合は、

- ストリーム部分の高速化は、繰り返し処理されることによる最適化は期待できることを意識する
- 1回しか処理しないループであれば、最適化を期待せずループのままの方が速い

というところでしょうかね。

# ぼやき

なにも渡さずに無限回数(何らかの条件で抜け出すまで)のデータを生成するストリームのジェネレータってないのかな。
`while(true){...}` をストリーム的に表現できないかという話です。
Excelファイルを右クリックして、各シート毎のファイルに分割するツールをPythonで作ってみた

#背景・目的
Excelファイルにある各シート別ファイルとして分割したいという依頼を受けました。本来はVBA案件かと思うのですが、Excelファイルをわざわざ開いてマクロを起動するのも面倒。というか、そもそもVBAが書きたくない。
というわけで、Excelファイルを右クリックして、各シート毎のファイルに分割するツールをPythonで作ってみたいと思います。

#外部ライブラリのインストール
Excelを操作するためのライブラリと、ファイルのパス作成のためのライブラリが必要になります。標準では無いので、事前にインストールしておきます。

```PowerShell
$ pip install win32com.client
$ pip install pathlib
$ pip install openpyxl
```

#コード
```excel_split.py
import os
import glob
import win32com.client
import pathlib
import openpyxl
import sys

excel_dir = pathlib.Path(sys.argv[1]).parent #対象のExcelファイルが保存されているフォルダのパス
input_file = str(sys.argv[1]) #Excelファイルのパスを文字列に変換

#シートの一覧取得 (openpyxlを利用)
book = openpyxl.load_workbook(input_file)
sheets_list = book.sheetnames

for i in range(len(sheets_list)):

    # Excelを起動する
    app = win32com.client.Dispatch("Excel.Application")
    app.Visible = False
    app.DisplayAlerts = False

    # Excelでワークブックを読み込む
    sheet_no = i + 1 #excelのシートは1スタートのため1を足す
    book = app.Workbooks.Open(input_file)
    book.WorkSheets(sheet_no).Activate()
    new_book = app.Workbooks.Add()

    # 各シート毎に保存
    new_file = sheets_list[i] + '.xlsx'
    path_obj = pathlib.Path(excel_dir, new_file) #パスオブジェクトに変換
    output_file = path_obj.resolve() #絶対パスに変換
    book.Worksheets(sheet_no).Copy(Before=new_book.Worksheets(1)) #新しいExcelファイルに指定シートをコピー
    new_book.SaveAs(str(output_file)) #ファイル保存

    # Excelを終了
    app.Quit()

```

#batファイルの作成
pyファイルはsendtoフォルダに置いてもキックされません。
作成したexcel_split.pyをキックするためにbatファイルを作ります。※PowerShellでも良いです。

```excel_split.bat
python \\Pythonファイルの保存先\excel_split.py
```
#Sendtoフォルダに保存
作成したbatファイルをsendtoフォルダに保存します。
sendtoフォルダは[Win]キーと[R]キー同時押しして、検索ボックスに「shell:sendto」と入れれば表示されます。

#利用方法
Excelファイルを右クリック→送る→excel_split.batをクリックするとそのExcelファイルにある各シート毎のファイルが作成されます。
<img width="422" alt="無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242659/88dc7e6b-f58b-114c-3c92-c7abf7d8218e.png">


# 補足：EXE化してユーザーへ配布したい場合
ユーザーに配布する場合は、EXE化したものを同じくsendtoフォルダに置いてあげればbatファイル不要で起動出来ます。以下の記事でEXE化の方法を紹介しています。

https://qiita.com/sw1394/items/2123fa9aaecb766657e5
PythonファイルをEXE化してみた(Recursion error対応済)

# 外部ライブラリのインストール
PyファイルをEXE化するためにはライブラリが必要です。
以下のコマンドでインストールします。

```PowerShell
$ pip install pyinstaller
```

exe化するには以下のように入力します。
-–onefile とつけると１つのファイルになり、
-–noconsole はコンソールが表示されなくなります。
オプションを付ける場合は以下のようにコマンド入力します。

```PowerShell
$ pyinstaller pythonファイル名 --onefile --noconsole
```

成功するとdistというフォルダが新規に作成され、
EXEファイルが保存されます。

これですんなりEXE化出来ればいいのですが、
以下のようなエラーが表示され、失敗することがあります。

```PowerShell
Recursion error : maximum recursion depth exceeded
```

上記エラーが表示された場合は、以下の手段でリトライします。

まず、「ファイル名.spec」というファイルがpyinstaller実行完了時に保存されています。これをメモ帳などで開いてから、以下のように２行追記してください。

```Python
# -*- mode: python ; coding: utf-8 -*-
import sys #追記
sys.setrecursionlimit(10000) #追記
block_cipher = None
```

追記出来たら、PowerShellを開きpyinstallerを実行するのですが、
１点注意が必要です。pyファイルではなく、先ほど編集したspecファイルに対してpyinstallerを実施します。

```PowerShell
$ pyinstaller 編集したspecファイル.spec --onefile --noconsole
```
これで無事EXE化出来るかと思います。
EXEファイルはdistというフォルダに新規に作成されます。
Nuxt.jsでグーグルアナリティクスを設定する方法【analytics-moduleを使用】

Nuxt.jsでグーグルアナリティクスを設定する方法です。
Nuxt.js用の公式モジュール[【analytics-module】](https://github.com/nuxt-community/analytics-module)を使用します。

## analytics-moduleをインストールする

```
# yarn
yarn add @nuxtjs/google-analytics
 
# npm 
npm install --save @nuxtjs/google-analytics
```

## nuxt.config.jsで設定をする

```nuxt.config.js
export default {
  buildModules: [
  '@nuxtjs/google-analytics'
  ],
  googleAnalytics: {
    id: 'UA-12345-0' //自身のアナリティクスコード
  }
}
```

上記の設定を追加することで、Nuxt.jsでグーグルアナリティクスを設定することができます。

### 環境変数でアナリティクスコードを設定する場合
アナリティクスコードを環境変数で設定する場合は、`'@nuxtjs/dotenv'`をインストール後に下記のように記述します。

```:env
GOOGLE_ANALYTICS_ID=UA-12345-0
```

```nuxt.config.js
export default {
  buildModules: [
  '@nuxtjs/google-analytics'
  ],
  publicRuntimeConfig: {
    googleAnalytics: {
      id: process.env.GOOGLE_ANALYTICS_ID
    }
  },
}
```

以上が【analytics-module】を使用して、Nuxt.jsにグーグルアナリティクスを設定する方法です。
MockKでモックが呼ばれないことをテストする

MockKでテストを書いていく上で、モックが呼ばれないことをテストしたかったのでメモ。
（Mockitoで言うところの `verifyZeroInteractions` です。）

# `wasNot called` を使えばOK
テストしたいモックが `mockObject` だとすると、下記のように書けばOKです。

```kotlin
verify {
    mockObject wasNot called
}
```

英文ぽくなって、かなりいいですね:relaxed:

---
以下、サンプルコードを記載します。

# サンプルコード

`Hoge` というクラスがあり、 `fuga()` では `Logger` が呼ばれ、`piyo()` では `Logger` 呼ばれないようになっています。

```kotlin
interface Logger {
    fun log()
}

class Hoge(private val logger: Logger) {

    fun fuga() {
        logger.log()
    }

    fun piyo() {
        // NO LOG
    }
}
```

これをテストする場合は…、


```kotlin
class HogeTest {

    @Test
    fun fuga_Loggerが呼ばれる() {
        val logger = mockk<Logger>(relaxed = true)
        val hoge = Hoge(logger)

        hoge.fuga()

        verify {
            logger.log() // log()が呼ばれることを検証
        }
    }

    @Test
    fun piyo_Loggerが呼ばれない() {
        val logger = mockk<Logger>(relaxed = true)
        val hoge = Hoge(logger)

        hoge.piyo()

        verify {
            logger wasNot called // loggerが呼ばれないことを検証
        }
    }
}
```

という感じになります。
非同期通信についてを学習した

Webアプリを作る上では今後、しっかり勉強しなければならないと思う。
今は、ざっくり概略を掴む程度にする。

僕は、この記事がわかりやすかった。
[Qiita「Ajax(非同期通信)についてわかりやすさ重視でまとめてみた(Rails使用のデモ付)」](https://qiita.com/__tambo__/items/409ccf256e84017ea307)

### 非同期通信の概略
- サーバーとブラウザの間で、通信しないで別個に動いている。
- 例えば、リクエストを送信しないで、画面遷移せず、ブラウザのみでDBから取得したデータを表示させる。
- リクエスト送信をいっぱい使う（画面遷移いっぱい）より、非同期通信を駆使したほうが待ち時間が少なくアプリを楽しめる。
- 非同期通信の代表がAjax（Asynchronous JavaScript + XML）だろう。

javascriptがよくわかっていないので、細かい話はまだ理解できないが、いまはこの理解でとどめておく。

以上。
Qiitaのアンケートに答えたら限定絵文字が使えるようになったので見せびらかす

`:qiita:`
:qiita: 

`:qiita-team:`
:qiita-team:

`:qiita-fabicon:`
:qiita-fabicon:

`:qiita-team-fabicon:`
:qiita-team-fabicon:

`:qiitan:`
:qiitan:

`:qiitan-cry:`
:qiitan-cry:

`:lgtm:`
:lgtm:

`:edit-request:`
:edit-request:

`:stock:`
:stock: 

`:file:`
:file:

エイリアス分からんしどう打てばそのスタンプ打てんねん
と思ったらGUIちゃんと用意されてました

![スクリーンショット 2020-08-07 9.22.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67471/9d23781f-7acc-edcb-132c-c738a5b0a3e4.png)
YouTubeでAWSの解説動画(Solution Architect Associate)を作成しました

こんにちは。
YouTubeでAWSの解説動画を作成しました。
レベル的にいうとソリューションアーキテクトのアソシエイト程度を意識しています。


## 1.AWSとは？ サービスの概要と認定試験
[![1.AWSとは？ サービスの概要と認定試験](http://img.youtube.com/vi/BbSUrh-vfH4/0.jpg)](http://www.youtube.com/watch?v=BbSUrh-vfH4)

[1.AWSとは？ サービスの概要と認定試験](https://youtu.be/BbSUrh-vfH4)

## 2.AWSをはじめよう! アカウントの作成方法
[![2.AWSをはじめよう! アカウントの作成方法](http://img.youtube.com/vi/QMqvGl_ELfE/0.jpg)](http://www.youtube.com/watch?v=QMqvGl_ELfE)

[2.AWSをはじめよう! アカウントの作成方法](https://youtu.be/QMqvGl_ELfE)

## 3.認証とユーザ管理 (IAM)
[![3.認証とユーザ管理](http://img.youtube.com/vi/I1U1gQjJ_T0/0.jpg)](http://www.youtube.com/watch?v=I1U1gQjJ_T0)

[3.認証とユーザ管理](https://youtu.be/I1U1gQjJ_T0)

## 4.ストレージサービス (S3, Glacier, EBS, EFS)
[![4.ストレージサービス](http://img.youtube.com/vi/s3PeZ9XK5lk/0.jpg)](http://www.youtube.com/watch?v=s3PeZ9XK5lk)

[4.ストレージサービス](https://youtu.be/s3PeZ9XK5lk)

## 5.EC2仮想サーバーとコンテナサービス(ECS)
[![5.EC2仮想サーバーとコンテナサービス](http://img.youtube.com/vi/GT3ujjxMaxY/0.jpg)](http://www.youtube.com/watch?v=GT3ujjxMaxY)

[5.EC2仮想サーバーとコンテナサービス](https://youtu.be/GT3ujjxMaxY)

## 6.ネットワークサービス (VPC, Route53)
[![6.ネットワークサービス](http://img.youtube.com/vi/uMt5WUjTXsg/0.jpg)](http://www.youtube.com/watch?v=uMt5WUjTXsg)

[6.ネットワークサービス](https://youtu.be/uMt5WUjTXsg)

## 7.データベースサービス (RDS, Redshift, Aurora, DynamoDB, ElasticCache)
[![7.データベースサービス](http://img.youtube.com/vi/ze9NXF1kZxs/0.jpg)](http://www.youtube.com/watch?v=ze9NXF1kZxs)

[7.データベースサービス](https://youtu.be/ze9NXF1kZxs)

## 8.運用監視サービスおよびIaC (CloudWatch, CloudTrail, ElasticBeanstal, CloudFormation)
[![8.運用監視サービスおよびIaC](http://img.youtube.com/vi/ZSib4i1FX-E/0.jpg)](http://www.youtube.com/watch?v=ZSib4i1FX-E)

[8.運用監視サービスおよびIaC](https://youtu.be/ZSib4i1FX-E)

## 9.アプリ間連携サービス (SQS, SNS, SES)
[![9.アプリ間連携サービス](http://img.youtube.com/vi/pdDaToq6pTc/0.jpg)](http://www.youtube.com/watch?v=pdDaToq6pTc)

[9.アプリ間連携サービス](https://youtu.be/pdDaToq6pTc)

## 10.開発者ツール (Commit, Build, Deploy, Pipeline)
[![10.開発者ツール](http://img.youtube.com/vi/28bWeozkZTA/0.jpg)](http://www.youtube.com/watch?v=28bWeozkZTA)

[10.開発者ツール](https://youtu.be/28bWeozkZTA)

## 補足:
[日本語版再生リスト](https://www.youtube.com/playlist?list=PLoVNA6SXr3DYLSa6baSTEIYYQ8qcBhMJn)
[英語版再生リスト](https://www.youtube.com/playlist?list=PLoVNA6SXr3Da3509baNhZnx475wT50spy)
[YouTubeチャンネル:MaruchinBroadcast](https://www.youtube.com/channel/UCm5dbZs0-iXwaajSIGMdA5Q?view_as=subscriber)
VSCodeでUnityのIntelisenseが効かなくなった時の対応

Unity x VSCodeで開発をしていてIntelisenseが効かなくて困った時の対応です

# 環境
Unity 2020.1.1f1
VSCode 1.47.3

# 対応
1. UnityのEigt -> Preferences -> External Tools  
2. "Generate.csproj files for:"のチェックを全て外して"Regenerate Project Files"を選択
3. リロードする  
VSCode上で"Ctrl+Shift+P"を押下し"Developer:Reload Window"でOK

おわり
初めて書いたサーバーサイド側の処理で、Node.jsを使いログイン処理を実装してみました。

#### 生JS(EC6)を3ヶ月ほど叩き込んだ後、HTMLとCSSを一通り学び、Node.jsでログイン処理を実装してみました。

【実装環境】
* Node.jsのStable版をインストール
* 実装が便利になるということで、Expressを導入。
* Vagrant上で8001のポートを空けて作業

Nodeでログイン処理を行うにあたり、
機能を追加した結果が以下の通り。


```js
  "dependencies": {
    "body-parser": "^1.19.0",
    "ejs": "^3.1.3",
    "express": "^4.17.1",
    "express-session": "^1.17.1",
    "request": "^2.88.2"
    }
```


#Step1

#### ID、パスワードが入力され、POSTされるまで

処理のスクリプトを書いているファイル内の処理。
ブラウザで/loginが叩かれた際、login.htmlをレンダリング。

```js
// /loginが開かれた場合の処理
app.get('/login', function (req, res) {
  res.render('login.html', {err:""});
  req.session.name = "";
})
```




この画面で「ログイン」ボタンを押すと、`/loginSend`にPOSTする。
<img width="364" alt="スクリーンショット 2020-08-07 8.43.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647101/22000928-9ba6-c3d7-baf0-f9653abd36f9.png">

```html
<form action="/loginSend" method="POST">
    メールアドレス：<input type="text" name="mail" >
    <br>
    パスワード    ：<input type="text" name="password">
    <br>
    <br>
    <input type="submit" value="ログイン" >
    </form>
```




#Step2

#### POSTされたデータを処理する


・ここで入力されたID/パスワードを、データベースに取得する
(その際にパスワードはハッシュ化してID/ハッシュ化されたパスワードの組み合わせを取得する)
・正常なログインができた際、セッション情報を付与する。

```js
    //アイパス一致すれば、Main画面をレンダリングする。
    if (result["結果"] === "OK"){
      res.render('main.html');

      req.session.mail = result["user_id"];
      req.session.name = result["user_name"];
    }
```

執筆中..
君らってペアだよね？という時のはなし(公開・暗号鍵)

同じ名前みたいだけど、君らってペアの鍵なんだよねというのを再確認したいときがあります。多分。
そんな時のチェック方法。

**公開鍵**

```
# ssh-keygen -l -f id_rsa.pub
4096 SHA256:AAAAB3NzaC1yc2EAAAADAQABAAABAQDC72ZZ9fhXyNn rsa key (RSA)
```

**秘密鍵**

```
# ssh-keygen -y -f id_rsa | ssh-keygen -l -f -
4096 SHA256:AAAAB3NzaC1yc2EAAAADAQABAAABAQDC72ZZ9fhXyNn no comment (RSA)
```

2020/8/17追記
@angel_p_57 さんにご教示頂きました。上記の方法の方が表示がコンパクトで読みやすいですね。
下記でも確認可能です。

**公開鍵**

```
# cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDC72ZZ9fhXyNnC1Rz1Zl6p
```

**秘密鍵**

```
# ssh-keygen -y -f id_rsa
Enter passphrase:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDC72ZZ9fhXyNnC1Rz1Zl6p
```
ServiceNowからTeamsに通知を飛ばす

# 概要
ServiceNowではIntegrationHub にSlack Spoke, Microsoft Teams Spoke その他メッセージ送信するアクションがありますが、
別のサブスクリプションが必要なので、RESTメッセージを使用して実装できないか調べてみました。

## プラットフォーム
Paris

## サンプルケース
変更要求のステータスが実装になるとTeamsに通知するというケースを想定
変更要求の更新をトリガーでビジネスルールでTeamsのWebhookにメッセージを送信します。

# 手順

## Webhookの設定
Webhookの設定は他の記事を参考にして
[Microsoft Teams API (Incoming Webhook) で投稿](https://qiita.com/wataash/items/72b49509c3964294dd67)

エンドポイントをコピーしておく
## RESTメッセージの設定
System Web Services > Outbound > REST Message から[New] ボタンを押してREST Messageを登録
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676866/8288539d-b3d3-dc51-ba09-9ebc8f7e6626.png">
コピーしたエンドポイントをここにペースト
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676866/f60ee875-058d-fa20-adfa-3b82854c50d7.jpeg">
登録後RESTメッセージ関数（HTTP Methods）を作成
今回はDefault GETを編集しました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676866/95a6b39d-241b-aae7-8f0f-832b19e1479b.jpeg">
HTTPメソッドを**POST**にして更新
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676866/d0900461-182a-6211-a8b9-0dae4ca92ce3.jpeg">

## テスト送信
Script - Backgroundで実行してみます。

```bg_script.js
var restMessage = new sn_ws.RESTMessageV2("Teams通知", "メッセージ送信");
var message = "メッセージテスト"; 
var body = createBody(message);
restMessage.setRequestBody(body);
var response = restMessage.executeAsync();
 	
 function createBody(message) {
 	var body = {
  		type : "message",
  		text : message
  	};
  return new JSON().encode(body);
 }
```
飛びました
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676866/c872464b-a292-d49d-dedb-f5fc046134d9.png">

## ビジネスルールを設定
変更要求の更新をトリガーにしてメッセージを送信するビジネスルールを作成
実行タイミングは非同期にしています。
ChangesやChangesToは変更前が無いから非同期では使えないと思っていたのですが、コンディションビルダーで使用する場合には使えるらしいです。知らなかった。
https://docs.servicenow.com/bundle/paris-application-development/page/script/business-rules/reference/r_HowBusinessRulesWork.html
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676866/a290cbcd-3dad-e47b-2c30-650fba9ec5f3.png">

コードはこんな感じで書いてみる

```send_change_implementation.js
(function executeRule(current, previous /*null when async*/) {
	var restMessage = new sn_ws.RESTMessageV2("Teams通知", "メッセージ送信");
	var message = createMessage(current);
	var body = createBody(current, message);
	restMessage.setRequestBody(body);
	var response = restMessage.executeAsync();
})(current, previous);

function createMessage(current) {
	var url = gs.getProperty('glide.servlet.uri')+'/change_request.do?sys_id=' + current.sys_id;
	var message = '【お知らせ】以下の変更を実装します！<br/>' +
			'番号：<a href="' + url + '">' + current.number + '</a><br/>';
	message += '作業名： ' + current.short_description + '<br/>';
	message += '終了予定時刻： ' + current.end_date.getDisplayValue();
	
	return message;
}

function createBody(current, message) {
	var body = {
		type : "message",
		text : message
	};
	return new JSON().encode(body);
}
```

結果がこちら
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676866/0ad0ac08-57fb-9607-95ec-7080e03962e0.png">
シェルの変更方法

Linuxで新しくユーザ作成した時なんかに「あ！シェル変わってるじゃん」ということがあります。
下記手順はそんな場面を想定。

まずは現在のシェルを確認。

```
$ echo $SHELL
/bin/sh
```

あ、やっぱりshに変わってる！

現環境で使用可能なシェルを確認。

```
$ cat /etc/shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
/bin/zsh
/usr/bin/zsh
```

使用したいシェルに変更。bashにしたい。

```
$ chsh
Password:
Changing the login shell for okamoto
Enter the new value, or press ENTER for the default
	Login Shell [/bin/sh]: /bin/bash
```

もしくはオプション(-s)を付けて、対話せずに変更。

```
$ chsh -s /bin/bash
Password:
```

変更完了。
console.logでJSONから特定の要素を取り出す方法

JavascriptでJSONから特定の要素を取り出す際の考え方が配列のときと少し異なるのでまとめました。

#JSONとは
- JavaScript Object Notationの略。直訳すると「Javascriptオブジェクト記法」ということになる。JSONにおけるJavascriptオブジェクトとは基本的には、{}（オブジェクト）と[]（配列）を組み合わせてデータ構造を表現したものをJSONとして扱うことができる。

→つまり、JSONとは、{}（オブジェクト）と[]（配列）を組み合わせてデータ構造のこと。

#JSONの特定の要素の取り出し方

```example.tsx
const messageArrayContainer: any[] = [{
    "text": ["Suzuki", "Yamada", "Miyazaki" ]
    "user": {"_id": 1, "avatar": "", "name": ""}
  }];

console.log('データ' + JSON.stringify(messageArrayContainer, replacer));
console.log('userデータ' + JSON.stringify(messageArrayContainer[0].user, replacer) );
```

```
//データ
[{
    "text": ["Suzuki", "Yamada", "Miyazaki" ]
    "user": {"_id": 1, "avatar": "", "name": ""}
  }]

//userデータ
{"_id": 1, "avatar": "", "name": ""}

```

ここで、注意なのが、配列と同じように考えると、userデータのみを取り出したいときに、下記のように書きたくなるがこれだとundefinedが表示される。

```example1.tsx
console.log('userデータ' + JSON.stringify(messageArrayContainer[0].user, replacer) );

//結果は,undefinedになる
```

JSONは大きな一つの要素と考え、

```example2.tsx
console.log('userデータ' + JSON.stringify(messageArrayContainer[0].user, replacer) );

//出力：　userデータ{"_id": 1, "avatar": "", "name": ""}
```

と書く。
【Linux】実際の職場でyumやrpmのパッケージ依存関係エラーを解決する場合の方法とは？

# はじめに

職場にてyumやrpmにてパッケージをインストールする際に、依存関係エラーと格闘するシーンがよくありました。
(例えば、LinuxサーバにGNOMEデスクトップをインストールする場合等です。)
今回は、実際の職場でやっている依存関係エラーの対処方法についてアウトプットしていきたいと思います。

# パッケージ依存関係エラーとは？

下記のようなエラーになります。

```bash
[root]# rpm -ivh compat-libstdc++-33-3.2.3-69.el6.i686.rpm
警告: compat-libstdc++-33-3.2.3-69.el6.i686.rpm: ヘッダ V3 RSA/SHA256 Signature, key ID fd431d51: NOKEY
エラー: 依存性の欠如:
        libc.so.6 は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
        libc.so.6(GLIBC_2.0) は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
        libc.so.6(GLIBC_2.1) は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
        libc.so.6(GLIBC_2.1.3) は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
        libc.so.6(GLIBC_2.2) は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
        libc.so.6(GLIBC_2.3) は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
        libgcc_s.so.1 は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
        libgcc_s.so.1(GCC_3.0) は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
        libgcc_s.so.1(GCC_3.3) は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
        libgcc_s.so.1(GLIBC_2.0) は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
        libm.so.6 は compat-libstdc++-33-3.2.3-69.el6.i686 に必要とされています
```

# 実際の職場での環境

|  項目  |  内容  |
| ---- | ---- |
|  OS  |  RHEL/CentOS  |
|  リポジトリ先 |  社内のローカルリポジトリ/ISOファイル |


# 実際にやっていた対処方法

## 1.マイナーバージョンが上のローカルリポジトリ/ISOファイルをマウント

現場で一番最初に考えたトラブルシューティング方法になります。
<br>

例えば、パッケージインストールの際に依存関係エラーが表示されるとします。

```
①RHEL7.3(お客様の既存マシン)にRHEL7.3のISOを用いて、yumにてGNOMEデスクトップをインストールする
②依存関係エラーが表示され、インストール不可
```

<br>

このような依存関係エラーの対応の際に、実際にやっていたことはこちらになります。

```
①マイナーバージョンが上のISOをセッティング(例:RHEL7.6等)
②リポジトリ設定/キャッシュクリア/リポジトリ読み込み
③再度、yumにてGNOMEデスクトップをインストール
```

<br>
**このように、マイナーバージョンが上のISOファイル(ローカルリポジトリ)をセッティングした場合、インストールができる場合があります。**

※依存関係で必要とされているパッケージが1つだけ存在しない場合、別のマイナーバージョンのISOファイルに存在する可能性があります。


## 2.複数のリポジトリを利用してパッケージインストール

「1.マイナーバージョンが1つ上のローカルリポジトリ/ISOファイルをマウント」を実施しても、依存関係エラーが表示されてしまった場合の解決方法になります。

対応方法としては、このような形になります。

```
①複数のリポジトリ先にアクセスできるように設定(リポジトリの設定等)
②再度、yumにてインストール作業実施
```
<br>
例えば、社内でローカルリポジトリを持っている企業さんの場合は、
ローカルリポジトリを1つだけではなく、複数にアクセスできるように設定してやってみる形になります。

<br>
**このように、複数のリポジトリを設定する形でやってみても、インストールができる場合があります。**


## 3.どうしても依存関係エラーでインストールができない場合(最終手段)

依存関係エラーで検知されているパッケージをアンインストールします。

```bash
yum remove <原因のパッケージ>
```

**こちらは、お客様の既存サーバ等では非推奨になります。**

なぜなら、サービスに影響が出てしまう可能性があるからです。

パッケージ削除以外の方法を探る方が無難です。

**※もしこちらの方法を実施する場合、削除しても問題ないパッケージかどうか必ず調査しましょう！**

# まとめ

**依存関係エラーが出た場合の対処方法**

1.マイナーバージョンが上のローカルリポジトリ/ISOファイルをマウント
2.複数のリポジトリを利用してパッケージインストール
3.どうしても依存関係エラーでインストールができない場合(最終手段)
Vue学習

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">created<br>　初期に外部のページからデータ取得<br> APIからデータ取得→dataに格納<br>mounted<br>　DOMが作られているため画面操作を行える。<br>beforeUpdate<br> 再描画前に実行<br>updated<br>　再描画後に実行<br><br>特定のタイミングで処理を挟み込める。<a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; だーいし★/PHP/JS/💪🌏👨‍💻 (@issiyrun) <a href="https://twitter.com/issiyrun/status/1291512160997187584?ref_src=twsrc%5Etfw">August 6, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Vue.js<br><br>グローバル登録と<br>ローカル登録<br>グローバル登録<br>→どこからでも呼び出せるがメモリ食ったりする。<br>ローカル登録<br>→登録先コンポーネント内のテンプレートからしか呼び出せない。削除しても他のコンポーネントに影響がないのは便利。<a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; だーいし★/PHP/JS/💪🌏👨‍💻 (@issiyrun) <a href="https://twitter.com/issiyrun/status/1291515667246530561?ref_src=twsrc%5Etfw">August 6, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">FireBase<br><br>Baas Backend as a Service<br>と呼ばれる部類のサービス<br>認証 DBの機能利用できる。<br>サーバレス増えて、バックエンドも値だけ投げたら加工してくれるAPIを提供する機能もどんどん出てきそう。。。<br><br>フロントにより力入れたくなる。。。<a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; だーいし★/PHP/JS/💪🌏👨‍💻 (@issiyrun) <a href="https://twitter.com/issiyrun/status/1291521887231647745?ref_src=twsrc%5Etfw">August 6, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

FireBase便利そうやね。。
色んな展開の仕方があると思うけどAWSと同じで従量課金やから注意やね。
社内ラジオを5ヶ月やってみて

## きっかけ

私は、今年の3月中旬から社内でラジオ(ポッドキャスト)を作成し、配信しています。
始めようと思った理由は単純で面白そうだったからです。
何かの拍子でfreeeさんが社内PodCastを行っている記事を見て、自分も社内でやりたいと思いました。
[freeeさんの記事はこちら](https://developers.freee.co.jp/entry/internal-podcast-anaguma-fm)
facebookでそんな話をしていると偶然見た、社内の2名(1名出演、1名編集等)の有志が参加したいということでトントン拍子でスタートすることが決まりました。

## 始めてみて

私たちは、3月後半くらいからポッドキャストの配信を初めています。

ペースとしては、一回30分くらいの番組を週に一回程度のペースで行っています。
内容としては、2名のパーソナリティとゲストを1人お呼びしてゲストの方の会社の仕事どんなのしてるかだったり
プライベートで好きな事だったりをお話しています。

スタート時期~今日まで、Covid-19が流行していた(現在、8/7時点でも流行ってますが、、)のでリモートでの収録を行っています。

## 良かった事

ゲストの決め方は、いいとも方式で決めているのでパーソナリティ自身も話したことがない人をお呼びすることが多いので
自身としても社内の詳しく知らない人とお話しできることはとてもありがたいです。
また、社内からラジオを聞いたという事で話しかけてもらえることが増えました。
何より、自分はラジオを通じて、毎週40~50人以上の人達に話をする機会があります。
やはり、話を上手にするためには機会が無いとダメですが、ラジオで獲得できました。

弊社では、毎月3~6名くらいがご入社されるのでラジオをやっていることが社員の事が知れるのではないかなと思います。


## 気を付けている事

基本的には、深く考えず収録を行っているのですが、一点だけ。

###マイクは大事です。

ポッドキャストでは、音声情報しかインプットが無いので、
唯一のインプットである音は雑さが無いものが良いですね。
自身は、スタート時点ではヘッドフォンのマイクを利用していましたが、
外付けでマイクを付けた方がやはり音質は安定しています。
（僕はマランツを利用しています。)

## 最後に

社内ラジオを初めてみて5ヶ月程たちましたが、
聴く側だけでなく、話す側にもとてもメリットがあると思います。
なので、皆さんも社内ラジオを始めましょう。
MySQLでBOOLEAN型のカラムに'true'をINSERTするとfalseになる

MySQLでBOOLEAN型のカラムに`'true'`をINSERTすると、その値はfalseになります。

## 問題

次のような構造のテーブルがあり、レコードは空の状態だとします。

```sql
CREATE TABLE `users` (
  `id` INT NOT NULL,
  `name` TEXT NOT NULL,
  `status` TEXT NOT NULL,
  `active` BOOLEAN NOT NULL,
  PRIMARY KEY (`id`)
);
```

このテーブルに対して、レコードを追加してみましょう。

```sql
INSERT INTO `users` (`id`, `name`, `status`, `active`)
  VALUES (1, 'Alice', 'true', 'true');
```

その後、次のようなSQL文を実行するとどうなるでしょうか。

```sql
SELECT count(*) FROM users WHERE active = true;
```

結果は、次のようになります。

|count(*)|
|---|
|0|

それでは、次のようなSQL文を実行するとどうなるでしょうか。

```sql
SELECT count(*) FROM users WHERE active = false;
```

結果は、次のようになります。

|count(*)|
|---|
|1|

これはいったい、なぜでしょうか。

## 原因

レコードを追加したあとのテーブルは、次のような状態になっています。

|id|name|status|active|
|---|---|---|---|
|1|Alice|true|0|

MySQLのBOOLEAN型は実際にはTINYINT(1)型のシノニムで、`0`がfalse、`0`以外がtrueを表しています。[^1]
`true`という文字列はTINYINT(1)型としては無効な値なので、デフォルト値である`0`になってしまったというわけです。

## 解決策

BOOLEAN型のカラムでは、文字列ではなくbooleanリテラルで値を書きましょう。[^2]

```sql
INSERT INTO `users` (`id`, `name`, `status`, `active`)
  VALUES (1, 'Alice', 'true', true);
INSERT INTO `users` (`id`, `name`, `status`, `active`)
  VALUES (2, 'Bob', 'true', false);
```

あるいは、対応する数値を使ってもいいでしょう。

```sql
INSERT INTO `users` (`id`, `name`, `status`, `active`)
  VALUES (1, 'Alice', 'true', 1);
INSERT INTO `users` (`id`, `name`, `status`, `active`)
  VALUES (2, 'Bob', 'true', 0);
```

## CSVファイルをインポートする場合

`LOAD DATA INFILE`構文を用いて次のようなCSVファイルをインポートする場合も、同様の問題が発生します。

```csv
"id","name","status","active"
"1","Alice","true","true"
"2","Bob","true","false"
```

この問題を解決するには、インポート時にBOOLEAN型のカラムの値をbooleanリテラルに変換します。

```sql
LOAD DATA LOCAL INFILE 'users.csv'
  REPLACE
  INTO TABLE users
  FIELDS
    TERMINATED BY ','
    OPTIONALLY ENCLOSED BY '"'
  IGNORE 1 LINES
  (id, name, status, @active)
  SET active = IF(@active='true', true, false);
```

## 参考リンク

- [MySQL :: MySQL 8.0 Reference Manual :: 11.1.1 Numeric Data Type Syntax](https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html)
- [MySQL :: MySQL 8.0 Reference Manual :: 9.1.6 Boolean Literals](https://dev.mysql.com/doc/refman/8.0/en/boolean-literals.html)
- [MySQL :: MySQL 8.0 Reference Manual :: 13.2.7 LOAD DATA Statement](https://dev.mysql.com/doc/refman/8.0/en/load-data.html)
- [MySQL :: MySQL 8.0 Reference Manual :: 12.5 Control Flow Functions](https://dev.mysql.com/doc/refman/8.0/en/control-flow-functions.html)

[^1]: [MySQL :: MySQL 8.0 Reference Manual :: 11.1.1 Numeric Data Type Syntax](https://dev.mysql.com/doc/refman/8.0/en/numeric-type-syntax.html)
[^2]: [MySQL :: MySQL 8.0 Reference Manual :: 9.1.6 Boolean Literals](https://dev.mysql.com/doc/refman/8.0/en/boolean-literals.html)
初心者のためのseaborn基礎④ペアプロット（pairplot）

#seabornとは
Pythonのグラフ描画のためのライブラリです。。最も有名なライブラであるmatplotlibのラッパー関数(内包プログラム)という位置づけ。簡単に見た目綺麗なグラフの描画が出来る他、一括での処理などの機能もある程度充実しています。細かく指定して描画するならmatplotlib、簡単に綺麗にならseabornのです。

#ペアプロット（jointplot）
今回のテーマはペアプロットです。seabornで一番有名な機能ではないでしょうか。作成には`.pairplot`を使用します。データの相関をつかむ際に活用します。

#準備
まずは、pipで`seaborn`のライブラリをインストールして下さい。pip?って方は[こちら]('https://qiita.com/Yanagawa_Yoshihisa/items/35e6f70a8411277282ce')。

ライブラリをインポートします。`seaborn`に`sns`という名前をつけて`import`します。

```python:
import seaborn as sns
```
サンプルはタイタニックのデータで試してみます。タイタニックがわからない人は｢kaggle タイタニック｣で調べて下さい。
pandasでデータフレームを作ります。

```python:
dataframe = pd.read_csv('train.csv')
```

#基本作成
散布図作成には`.jointplot`を使用します。基本的に設定するものは、元データとプロットしたい軸になります。
ここではプロット対象の軸としてAge（年齢）、Fare（運賃）、Pclass（等級）を選定し、`vars`に設定します。

```python:
sns.pairplot(dataframe, vars = ['Age','Fare','Pclass'])
```

それっぽいグラフが書けました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600679/1a5c022d-7686-1b19-b7fd-100b8d03086c.png)


グラフの見方ですが、軸にした項目のn×nのマトリクスが作成されます。
同じ軸の交点（青枠の領域）は、その項目単独のマトリクスとなります。
そのほかの領域は、対象となる軸と軸との散布図になります。対角の位置にある散文図は軸を入れ替えた散布図の関係になります。（赤枠は同じ散布図でX軸とY軸が入れ替わっている）
この機能を使うと、項目感の全体像をざっくりと確認することができます。（赤枠の運賃と年齢をみると年齢と運賃の関係にはわかりやすい相関はなさそうだなど。）

`hue`のオプションを使うと、Z軸を設定することができます。例としてSex（性別）を追加します。

```python:
sns.pairplot(dataframe, vars = ['Age','Fare','Pclass'], hue = 'Sex')
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600679/45cf9e8a-0cbf-47ba-7b3a-c0a367eddcd1.png)

`diag_kind="hist"`でヒストグラムに変更することも可能です。


```python:
sns.pairplot(dataframe, vars = ['Age','Fare','Pclass'], hue = 'Sex' ,diag_kind="hist")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600679/1e19335c-c96b-ec22-072d-3180dbc16063.png)

非常に簡単な構文ですが、詳しくない人にはそれっぽくみえて、やった感がでるのでお勧めです。

他にも色々とオプションは指定できるので、さらに掘り下げたい方は[公式ドキュメント](https://seaborn.pydata.org/generated/seaborn.pairplot.html)をごらん下さい。

#最後に
初心者にもわかるように、Pythonで機械学習を実施する際の必要な知識を簡便に記事としてまとめております。
目次は[こちら](https://qiita.com/Yanagawa_Yoshihisa/items/a3fa521d89c471b3e71f)になりますので、他の記事も参考にして頂けると幸いです。
自分向けメモ AWS_Route53レコード、ホストゾーン削除


cloud9→Route53→ホストゾーン→

タイプAのレコードを選択して削除
削除と入力して削除

※SOAとNSレコードは削除できない。

ホストゾーンでドメインを選択、削除と入力して削除
Ruby on Railsのシード機能についてのメモ

# はじめに

初心者です。
RubyとRuby on Railsを使ってアプリケーションを作っています。
備忘録も兼ねておりますので、間違いなどあればご指摘ください。

# シード機能とは

データベース作成後に、初期データを簡単に流し込むことができる機能。

# どのファイルを使うのか

`db/seeds.rb`に初期データとして流し込みたいコードを記述して、
ターミナルで`rails db:seed`すればOK。
実行してもターミナルに何か表示されるわけではないが、データに問題なければ流し込まれているはず。

#ファイルにはどう記述するのか

例）productsテーブルのnameカラムとdescriptionカラムにデータを５つ流し込む

```ruby
5.times do |i|
  Product.create(name: "Product ##{i}", description: "A product.")
end
```

timesメソッドを使っているが、１行ずつ書いていっても問題なし。

# まとめ

- シード機能はデータベース作成後に初期データを流し込むことができる機能
- `db/seeds.rb`に流し込みたいデータを記述
- ターミナルで`rails db:seed`すれば流し込める

# 参考

Railsガイドv6.0
https://railsguides.jp/active_record_migrations.html
pygameで簡単なFlappyBird(フラッピーバード)というゲームを作る方法

#0.最初に

今回作るものがどういう感じで動くのか見てみたい方は、[こちら](https://youtu.be/NrM8jigWwZk)(youtubeの動画)でどうぞ。

#1.実装
```flappy_bird.py
import pygame
import random

win = pygame.display.set_mode((400,600))
clock = pygame.time.Clock()

class Bird:
    def __init__(self,win):
        self.win = win
        self.y = 300
        self.x = 25
        self.gravity = 1
        self.velocity = 0
        self.lift = -2
        self.air = 0

    def show(self):
        pygame.draw.circle(self.win,(255,255,255),(self.x,self.y),16)

    def update(self):
        if self.air == 0:
            self.velocity += self.gravity
            self.y += self.velocity
            self.air = 1
        elif self.air > 2:
            self.air = 0
        elif self.air > 0:
            self.air += 1


        if self.y > 600:
            self.y = 600
            self.velocity = 0

        if self.y < 0:
            self.y = 0
            self.velocity = 0

    def up(self):
        self.velocity += self.lift

class Pipe:
    def __init__(self,win):
        self.win = win
        self.top = random.randint(0,300)
        self.bottom = random.randint(0,300)
        self.w = 20
        self.x = 400
        self.speed = 2
        self.passed = False
        self.color = (255,255,255)

    def show(self):
        pygame.draw.rect(self.win,self.color,(self.x,0,self.w,self.top))
        pygame.draw.rect(self.win,self.color,(self.x,600-self.bottom,self.w,self.bottom))

    def update(self):
        self.x -= self.speed

    def hits(self,bird):
        if bird.y < self.top or bird.y > 600 - self.bottom:
            if bird.x >= self.x and bird.x <= self.x + self.w:
                return True
        return False

def drawWindow(bird,pipes):
    bird.show()
    bird.update()
    for pipe in pipes:
        pipe.show()

    pygame.display.update()

bird = Bird(win)
pipes = [Pipe(win)]
run = True
while run:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()

    if keys[pygame.K_SPACE]:
        bird.up()

    add_pipe = False
    rem = []
    for pipe in pipes:
        if pipe.x + pipe.w < 0:
                rem.append(pipe)
        if not pipe.passed and pipe.x < bird.x:
            pipe.passed = True
            add_pipe = True

        if pipe.hits(bird):
            pipe.color = (255,0,0)

        pipe.update()

    if add_pipe:
        pipes.append(Pipe(win))

    for r in rem:
        pipes.remove(r)

    win.fill((0,0,0))
    drawWindow(bird,pipes)
```
ここでは、ドカン(Pipe)と鳥(Bird)のクラスをそれぞれ作り、鳥のクラスでは鳥の代わりに円をつくり、重力により鳥が落ちてくるようにしています。ドカンのクラスでは、上のドカンの位置と下のドカンの位置をランダムに決め、それをもとに長方形を描きドカンとしています。また、ドカンは右から流れてくるので動かすためにx座標からある一定の値が引かれるようにしています。また、鳥がドカンにあたったときにTrueを返す関数も用意しています。そして、最後のループでは、ゲームの速度を少し遅らせ、鳥がドカンをすぎたらそのドカンを削除し新しいのを追加し、鳥があたったら赤色にかえています。

#最後に
このFlappyBirdゲームの作り方は[Youtube](https://youtu.be/NrM8jigWwZk)でも解説しているのでそちらも良かったらご覧ください。質問、アドバイスなどがございましたらぜひコメントしてください。
wsl2のインストールを諦めて、nuxtをインストール

2020年9月12日。できる様になっていました！
顛末はこちらにまとめた！
https://qiita.com/fumi-m/items/e950bc6f0d048b6e7bb5


## windows 10 version 2004をインストールする

以下、2020年8月7日時点の状況・・

1. windows updateを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/73cfe2d6-35df-230e-a574-84fc1398e8cc.png)

2. 詳細情報をクリックする
3. 遷移先の https://docs.microsoft.com/ja-jp/windows/release-information/status-windows-10-2004 から、Windows 10, version 2004 is new availbel のリンクをクリックする
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/31d90ac0-dd2b-3021-6e03-c59c9545be10.png)
5. そこによると、windows update の「更新プログラムのチェック」をクリックすることで始まるとのこと・・
6. しばらく待つと「ダウンロードとインストール」が選択できる様になる。。と書いてあったけど、「今すぐ再起動する」が強制的に必要になった。。。

さて、問題無く再起動できるかな、どきどき、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/072143e8-a6fe-ecc3-f66a-6bca796053d7.png)

## 何も起きなくてほっとした。。？

再起動も問題無く行われたーって、ふたたび
win+R → コマンド winver でバージョンを調べても、verion1903 のままだった。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/b04523ad-a162-76b8-04b2-b864885e0704.png)

記事をよく読むと、互換性の問題があったり更新に問題がある場合は更新が止まるらしいですね。。

surface 6でも無理なのかな。。？


で、 一旦wsl2の導入は諦めて、https://docs.microsoft.com/ja-jp/windows/nodejs/setup-on-wsl2　にしたがって先に行きます
1. ubuntu 16.04 では過去のバージョンのnodejsを削除することが必要らしい。といっても、`node --version `で何も出てこない
2. 念のため `https://docs.microsoft.com/ja-jp/windows/nodejs/setup-on-wsl2` としても、インストールされていないとでました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/daaa66a6-9ddd-b35f-1024-620ca291bfb9.png)

3. `sudo apt-get install curl` → これは導入済みだったのでupdate無しで終了
4. nvm をインストール `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash `
5. `nvm ls` でインストール済みモジュールを確認
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42407/8bfd369a-b726-85f8-1d4c-c1e766911afb.png)

6. `nvm install node` を実行
7. Node.jsの安定したLTSリリース（)をインストール `nvm install --lts`
8. `node --version` で確認→インストール完了！
9. yarn install 使用とすると、'sudo apt install cmdtest'を実行しろと言われたけど、そのまま続けたらyarn install で失敗したので、そこは無視して下のコマンドを実行した方が良さそう
10. （もし、cmdtestインストール済みならば、 `sudo apt remove cmdtest` でアンインストール
11. 'curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -'
12. 'echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list`
13. `sudo apt-get update`
14. `sudo apt-get install yarn`
15. で、`yarn install`が上手くいきました！
【TypeScript vs Kotlin 】?. 演算子の違い

TypeScript と Kotlin での `?.` 演算子の違いについて。

## TypeScript（optional chaining 演算子）

`?.` 演算子の左項が nullish（`null` もしくは `undefined`）であれば
そのチェインにおいてそれ以降の評価を行わずに
チェイン全体の結果として `undefined` を返す。

`a?.b.c` において `a` が nullish だった場合
`b` も `c` も評価されず `undefined` が返る。

```TypeScript
const list = ["Qiita", null]; // : (string | null)[]

list[0].substring(1).substring(1); // コンパイルエラー！
list[0]?.substring(1).substring(1); // ★OK
list[0]?.substring(1)?.substring(1); // OK だが冗長

console.log(
    list[0]?.substring(1).substring(1)
); // > ita
console.log(
    list[1]?.substring(1).substring(1)
); // > undefined
```

## Kotlin（safe call 演算子）

`?.` 演算子の左項が `null` であれば
右項の評価を行わずに
その演算の結果として `null` を返し、
チェインを継続する。

`a?.b.c` において `a` が `null` だった場合
`b` は評価されず `null.c` を評価した結果が返る。

```Kotlin
val list = listOf("Qiita", null) // : List<String?>

list[0].substring(1).substring(1) // コンパイルエラー！
list[0]?.substring(1).substring(1) // ★コンパイルエラー！
list[0]?.substring(1)?.substring(1) // OK

println(
    list[0]?.substring(1)?.substring(1)
) // > ita
println(
    list[1]?.substring(1)?.substring(1)
) // > null
```

## 考察：違いの理由

TypeScript では nullish な値に対して `.` 演算を行うと必ずエラーである。
そのためチェインの途中で nullish な値が出てきた場合
チェインを続ける意味がない。

しかし Kotlin では nullable な型をレシーバーとした拡張関数・拡張プロパティ[^nullableな型をレシーバーとした拡張関数・拡張プロパティ]を定義できるため
`null` に対して `.` 演算を行える場合がある。
そのためチェインの途中で `null` になっても
チェインを続ける意味がある。

[^nullableな型をレシーバーとした拡張関数・拡張プロパティ]: 例えば [`Any?.toString()` 関数](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/to-string.html)

／以上
mvn package コマンドが 400 エラーになった時の対応メモ

メモです。

# 事象

`pom.xml` に 必要なライブラリを追記して `mvn package` コマンドを実行したが 400 エラーとなった

# 原因

事前に `mvn package` コマンドで利用するライブラリを push していたが、`jar` ではなく、 `war` が push されていた
その状態で `mvn package` しても `jar` はないので 400 エラーとなっていた

# なぜ `war` が push されていたのか

`mvn archetype:generate` コマンドで maven プロジェクトの雛形を作っていたが、`DarchetypeArtifactId=maven-archetype-webapp` を設定してしまっていた
この場合、Web アプリの雛形となるため、 `pom.xml` には `<packaging>war</packaging>` が設定されていた
これによって `war` が生成され、`war` が push されていた

# 解消方法

`pom.xml` から `<packaging>war</packaging>`  を削除して再度 `mvn deploy` を実施することで `jar` が push される
その後、再度 `mvn package` コマンド実行により成功

また、今後はライブラリを作る時には `mvn archetype:generate` で `DarchetypeArtifactId=maven-archetype-webapp` を指定しなければ良い
FirestoreのCollection Group Queries(コレクショングループクエリ)について

# これは何
[ここ](https://firebase.google.com/docs/firestore/query-data/queries?hl=ja#collection-group-query)に説明が書いてありますが、例が個人的には分かりずらかったので、なんなのかを一言で説明すると、

**同じ名前のサブコレクションに対してデータベース全体を跨ってクエリが書ける機能** です。

終わり

# 簡単な例
以下のようなpiyoサブコレクションがあったとします。
/hoge/{hogeId}/piyo
/hogehoge/{hogehogeId}/piyo
/foo/{fooId}/bar/{barId}/piyo

以下のように書くことで全てのpiyoサブコレクションからtypeフィールドが'fuga'のドキュメントを検索できます。
親のコレクション名や階層が違ってもOK。

```javascript
db.collectionGroup('piyo').where('type', '==', 'fuga');
```

ただし、以下のようなセキュリティルールを書いておく必要があります。

```
match /{path==**}/piyo/{piyoId} {
  allow read: if true
}
```

いやいや、そんなルール書いたら見られちゃいけないものまで全部見れちゃうやんけ！！
それがまずい場合、フィールドの内容で制限がかけられます。

```:publicフィールドがtrueのもののみアクセス可能
match /{path==**}/piyo/{piyoId} {
  allow read: if resource.data.public;
}
```

ただし、上記のようにフィルタリングする場合は、条件以外のドキュメントにアクセスしないようにクエリでもその条件で絞ってあげる必要があります。

```javascript
db.collectionGroup('piyo').where('public', '==', true);
```

ユーザーIDで絞る場合も、ユーザーIDをドキュメント内に格納しておくことで可能です。

```
match /{path==**}/piyo/{piyoId} {
  allow read: if resource.data.user == request.auth.uid;
}
```

もちろんクエリでも指定する必要があります。

```javascript
db.collectionGroup('piyoSubCollection').where('user', '==', uid);
```

ドキュメントパスで絞りたいんだけど…
多分、無理っぽいです。

公式のドキュメントにそれっぽい説明がありますが、書いてあることが私には意味不明です。
この文章の意味がわかる方がいたら是非教えてください。

https://firebase.google.com/docs/firestore/security/rules-query?hl=ja#secure_and_query_documents_based_on_collection_group_and_document_path