OmniAICreator/Qiita-1.07M huggingface dataset:
RSpecでのmodelのテスト

#modelテストの準備#
今回はPostモデルにタイトルカラムがあるかどうかと文字数のテストをする。

```ruby:app/models/post.rb
class Post < AplicationRecord
  belongs_to :user
  validates :title, presence: true, length: {maximum: 20}
end
```

#ファイルの作成#
①spec配下にmodelsフォルダとfactoriesフォルダを作成し、テストしたいモデルのファイルを作成する。今回は spec/models/post_spec.rbを作成

②FactroyBotを使用可能にする。
使用すると user = create(:user)のようにDB登録やモデルのビルドができるようになる。
spec配下にsupportフォルダとfactory_bot.rbファイルを作成し、下記を記述。
ユーザーがログインしている状態でないと投稿出来ないことをテストするためpost_spec.rb user_spec.rbの２ファイルを作成する。

```ruby:spec/support/factroy_bot.rb
RSpec.configure do |config|
  config.include FactroyBot::Syntax::Methods
end
```

③spec/rails_helper.rbの編集

```ruby:spec/rails_helper.rb
require 'spec_helper'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../config/environment', __dir__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'rspec/rails'
require 'support/factory_bot'

begin
  ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
  puts e.to_s.strip
  exit 1
end
RSpec.configure do |config|
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.use_transactional_fixtures = true
  config.infer_spec_type_from_file_location!
  config.filter_rails_from_backtrace!
  
  
  #今回の記事では関係ないがsystem_specにおいてヘッドレスモードでchromeを起動するための記述
  config.before(:each) do |example|
    if example.metadata[:type] == :system
      if example.metadata[:js]
        driven_by :selenium_chrome_headless, screen_size: [1400, 1400]
      else
        driven_by :rack_test
      end
    end
  end
  
  #capybaraに関する記述
  config.include Capybara::DSL
end
```

#ダミーデータの作成#
```ruby:spec/factories/user.rb
FactoryBot.define do
  factory :user do
    name {Faker::Name.name}
    email {Faker::Internet.email}
    password {'password'}
    password_confirmation {'password'}
  end
end
```

```ruby:spec/factories/post.rb
FactoryBot.define do 
  factory :post do
    body {Faker::Lorem.characters(number: 20)}
    user
  end
end
```

#テストコードの作成#

```ruby:spec/models/post_spec.rb
require 'rails_helper'

RSpec.describe 'post model test', type: :model do
  describe 'validation test' do
    #factoriesで作成したダミーデータを使用する
    let(:user) {FactoryBot.create(:user)}
    let!(:post) {build(:post, user_id: user.id)}
    #test_postを作成し、空欄での登録ができるか確認
    subject {test_post.valid?}
    let(:test_post) {post}
    
    it 'titleカラムが空欄でないこと' do
      test_post.title = ''
      is_expected.to eq false;
    end

    it '21文字以上であればfalse' do
      post.title = Faker::Lorem.characters(number: 21)
      expect(post).to eq false;
    end
  end
end
```

#RSpecの実行#

```terminal
$ bin/rspec spec/models/post_spec.rb
```
『OpenCVによる画像処理入門』練習問題4.2

[『OpenCVによる画像処理入門』](https://www.kspub.co.jp/book/detail/1538290.html)の練習問題4.2をやった。

# 練習問題4.2
## 1 
2次元配列imageを使用してPGM画像を作成する。

※main関数に毎回サンプルプログラムを書いていくと長大になりすぎるため、
subX()の関数を作り、適宜mainから呼ぶような構成にした。
## プログラム

```sub6_1.cpp
#include "sub.h";

using namespace std;

int sub6()
{
	const int width = 9, height = 9;
	unsigned char image[height][width];
	
	string filename = "output.pgm";
	ofstream fout(filename);
	
	for (int y = 0;y < height;y++)
	{
		for (int x = 0;x < width;x++)
		{
			/* ここから作成開始 */
			int tmp = 32 * x + 32 * y;
			
			if (tmp < 256)
			{
				image[x][y] = tmp;
			}
			else if (tmp == 256)
			{
				image[x][y] = 255;
			}
			else if (tmp > 256)
			{
				image[x][y] = 256 - (tmp - 256);
			}
			/* ここまで */
		}
	}
	
	fout << "P2" << endl;
	fout << width << " " << height << endl;
	fout << "255" << endl;
	for (int y = 0;y < height;y++)
	{
		for (int x = 0;x < width;x++)
		{
			fout << (int)image[x][y] << " ";
		}
		fout << endl;
	}
	fout.flush();
	fout.close();

	return 0;

}
```

## 作成ファイル
```output.pgm
P2
9 9
255
0 32 64 96 128 160 192 224 255 
32 64 96 128 160 192 224 255 224 
64 96 128 160 192 224 255 224 192 
96 128 160 192 224 255 224 192 160 
128 160 192 224 255 224 192 160 128 
160 192 224 255 224 192 160 128 96 
192 224 255 224 192 160 128 96 64 
224 255 224 192 160 128 96 64 32 
255 224 192 160 128 96 64 32 0 
```

## 表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581044/c59b88ce-397e-66bf-1e14-ea221204ea3d.png)

## 2
1と同じ画像を、1次元配列imageを使用して作成する。
## プログラム

```sub6_2.cpp
#include "sub.h";
using namespace std;

int sub6()
{
	const int width = 9, height = 9;
	unsigned char image[height * width];
	
	string filename = "output.pgm";
	ofstream fout(filename);
	
	for (int y = 0; y < height; y++)
	{
		for (int x = 0; x < width; x++)
		{
			/* ここから作成開始 */
		    int tmp = 32 * x + 32 * y;

			if (tmp < 256)
			{
				image[y*width+x] = tmp;
			}
			else if (tmp == 256)
			{
				image[y * width + x] = 255;
			}
			else if (tmp > 256)
			{
				image[y * width + x] = 256 - (tmp - 256);
			}
			/* ここまで */
		}
	}
	
	fout << "P2" << endl;
	fout << width << " " << height << endl;
	fout << "255" << endl;
	for (int y = 0;y < height;y++)
	{
		for (int x = 0;x < width;x++)
		{
			fout << (int)image[y*width + x] << " ";
		}
		fout << endl;
	}
	fout.flush();
	fout.close();

	return 0;

}
```

pgmファイルおよび画像は1と同じなので省略。
Arduino IDEをUbuntu 20.04にインストールする

## ポイント

1. https://www.arduino.cc/en/Guide/Linux よりも簡単になっている。
2. `./install.sh` を実行した場所がインストール先となるため、先にインストール先に移動しておく必要がある。

### 確認環境

- Ubuntu 20.04 amd64 (in VirtualBox 6.1)
- Arduino IDE 1.8.13

## 手順

ここでは Arduino IDE のインストール先を `~/.local/` とします。
一回はrebootする必要があります。

- https://www.arduino.cc/en/software からダウンロード

```console
$ tar xvf ~/Downloads/arduino-1.8.13-linux64.tar.xz
$ mkdir -p ~/.local/
$ mv arduino-1.8.13 ~/.local/
$ cd ~/.local/arduino-1.8.13/
$ bash arduino-linux-setup.sh $USER
$ sudo systemctl reboot
```

再起動後

```console
$ cd ~/.local/arduino-1.8.13/
$ sudo bash install.sh
```

デスクトップ上に `arduino-arduinoide.desktop` がある場合は、右クリックのコンテキストメニューにて「起動を許可する」を選択すると、起動できるようになります。
※ランチャーの中で Arduino IDE を探して起動も可能です。
※日本語環境で英語フォルダ名にしている場合はショートカットが作られない場合があるようです。

## ちょっとだけ解説

`arduino-linux-setup.sh` が `$USER` を dialout グループとかに追加してくれるので `/dev/ttyACM**` とかのパーミッション問題が片付きます。

EoT
【Rails】 PG::DuplicateTable: ERROR:  relation "users" already existsの解消法

## PG::DuplicateTable: ERROR:  relation "users" already existsエラー
Railsでデータベースをmigrateしようとした時に出たエラーです。
エラーの内容は、「usersテーブルが既に存在してるよ！」ということでした。
はじめはよく理解していなかったので、マイグレーションファイルを削除して、
もう一回作成してみたりしてみたのですが、また同じエラーが出ました。

## rails db:migrate:resetを実行
エラー内容を検索してみた結果、リセットするのが一番良いようだったので、
`rails db:migrate:reset`
を実行。

```
Dropped database 'rspec_sample_development'
Dropped database 'rspec_sample_test'
Created database 'rspec_sample_development'
Created database 'rspec_sample_test'
== 20210103133942 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0317s
-- add_index(:users, :email, {:unique=>true})
   -> 0.0051s
== 20210103133942 CreateUsers: migrated (0.0371s) =============================
```

このような表示が出て、みごとにデータベースのリセットが出来ました。
再度、`rails db:migrate`でデータベースを反映させる事ができました。

## 参考資料
[[Rails5] PG::DuplicateTable: ERROR~の解決方法](https://kirohi.com/rails_duplicate_error)
CSVファイル  メモ

##CSVファイルとは
互換性が高く、ほとんどのソフトに取り込んで閲覧、編集することが可能なファイル
**Comma Separated Value(`カンマ(,)`で区切った値)」**の
頭文字をとって名付けられた


Railsで実装するのも簡単にできそう
・require csv と format をコントローラー側で実装できそうだったので
時間を見つけて簡単なアプリで実装してみる
Don't know how to build task 'credentials:edit' 

問題
-
```
$ rails credentials:edit
rails aborted!
Don't know how to build task 'credentials:edit' (see --tasks)
```



解決策
-
credentials.yml.encは、Rails5.2から追加されたので問題なければ5.2にしましょう。

```gemfile
gem 'rails', '~> 5.2'
```

```
bundle update
```



情報源
-
https://fuzzyblog.io/blog/rails/2020/09/14/deploying-to-hatchbox-with-rails-5-x.html
【Unity VR】備忘録 GVRを使った際にAndroid端末で2画面にならなかったときの話。

UnityVersion : 2019.4.16f

GVRの設定を終わらせ、
Cardboardの設定も済ませたが、
Android実機で2画面にならなかった。

![Screenshot_20210103-224833.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794992/1f2af201-99e7-41b9-6a22-e4d34c4d72f4.jpeg)


設定を見直したが、
マニュアル通りの設定になっている。

おかしい。

ジャイロセンサーも効かない状態。

何度か繰り返しても１画面のままなので、
ふとした瞬間にある事がよぎった。

「もう一回CardboardのSDKインストールしてみるか。。。」

VR SDKsのCardboardを削除して、もう一度プラスボタンを押し、
CardboardSDKを再インストール。
![スクリーンショット 2021-01-03 224609.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794992/650c5201-ca94-b7c9-8049-952f7610ea01.png)

これが大当たり。

![Screenshot_20210103-224828.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/794992/4e64ed67-069d-e7af-b916-6e65628f8d6c.jpeg)


ようやく動作して一安心。
GitHubのwikiをローカル編集してPushする際に出たエラー

## 要点

- GitHubレポジトリのwikiクローン→ローカルで編集→Pushする際にエラーが発生しました。
- 原因は、二段階認証を有効にしている状態で、HTTPSでPushしてることにありました。
- なので、.git/configのリモートURLをSSHプロトコルに変更すればPushできました。

## エラー発生→解決までの経緯

### 前提条件

- GitHubで二段階認証を有効にしているため、SSHでPushするのがマストな状態。
- SSH接続に必要な設定は済ませてある。

※GitHubにSSH接続するための手順は、[こちら](https://qiita.com/0ta2/items/25c27d447378b13a1ac3)の記事がわかりやすかったです！

### 発生したエラー

GitHubレポジトリのwikiをローカルにcloneして編集し、Pushしようとしたところ以下のようなエラーが発生しました。

```
$ git push origin master
Username for 'https://github.com': USERNAME
Password for 'https://USERNAME@github.com': 
remote: Invalid username or password.
fatal: Authentication failed for 'https://github.com/USERNAME/REPOSITORY.wiki.git/'
```

### 解決方法

二段階認証を有効にしている状態で、HTTPSプロトコルでPushしようとしているため、上記のようなエラーが起こるようです。

```
# 元の状態
$ git remote -v
origin	https://github.com/USERNAME/REPOSITORY.wiki.git (fetch)
origin	https://github.com/USERNAME/REPOSITORY.wiki.git (push)
```
なので、ローカルレポジトリのリモートURLをSSHプロトコルに変えてからPushする必要があります。

```
$ vim .git/config
------------------
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
        ignorecase = true
        precomposeunicode = true
[remote "origin"]
        # ↓ここをHTTPSからSSHプロトコルに変更
        url = git@github.com:USERNAME/REPOSITORY.wiki.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master
```

リモートURLが変更できていることを確認して、Push。

```
$ git remote -v
origin	git@github.com:USERNAME/REPOSITORY.wiki.git (fetch)
origin	git@github.com:USERNAME/REPOSITORY.wiki.git (push)

$ git push origin master
```
無事にPushできました。

（ちなみに自分は、リモートURLを修正する際に`git@github.com:`の`:`を`/`のままにしていて、一瞬「あれ？Pushできない？」となりました。）

### その他気づいた点

なお、この記事を書いている2021年1月現在では、GitHubレポジトリのwikiはHTTPSでしかクローンできないみたいです。
そのため、wikiをローカルで編集する際は、必要に応じてリモートURLをSSHに変えておく必要がありそうです。

## 参照

#### 解決の際に拝見した記事
- [githubを二段階認証に変更後に起こるエラーの対処方法](https://qiita.com/sayama0402/items/670b6b650ebdd8680a0b)
【Swift】Scroll Viewを設置したあと

# z-index

他の設置しているアイテムと重なり順がおかしくなっていたら修正する。
例えば今回のパターンでは『スキップ』と書かれたButtonの上に、全面に広げたScroll Viewが載ってしまっている。
**Document Outline**上でドラッグドロップして直す。

## Before

![b528a5889a6273e526348f7f82886198.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413699/58a1ca59-203c-9309-e908-16388fd30b3a.png)

## After

![5fe6724ccb7c88c1651bdf7c3e22e9b0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413699/4eb7bd79-ce67-15c2-5e7f-a82c3767356e.png)

これでScroll Viewの上にButtonが載るカタチになった。
Tableau製品と価格体系について

#はじめに#
業務上に初めてTableauを触りますが、製品の特徴と価格体系があまりにも複雑なので調べてみました。

#Tableauとは#
Tableauとは、ノンプログラミングで誰でも簡単にビッグデータなどの膨大なデータを分析できるビジネスインテリジェンス（BI）ツールです。

#Tableauで何ができるのか#
- 大量のデータ分析：Excelのデータ数の限界は100万行で、この限界を超えたらTableauが圧倒的に有利です。
- 扱いデータソースの種類が充実：Excel、RDBやクラウドベースのデータソースにも接続できます。
- 計算式に強い：印象的に計算フィールドがExcelより表現が強い。

#Tableauの製品#
大まかに以下のように分けられます
- 自分で作業するための製品：Tableau Desktop、Tableau Prep Builder、Tableau Public
- 作成した分析結果を共有する製品：Tableau Server、Tableau Online
- 共有された分析結果を閲覧する製品：Tableau Reader、Tableau Mobile
- アドオンパッケージ：「Tableau Data Management Add-on」、「Server Management Add-on」（Tableau Server）、「Resource Blocks」（Tableau Online）

|製品|価格|特徴|
|---|---|---|
|Tableau Public|無料|◎対応しているデータソースが少ない<br>◎分析結果の保存先がTableau PublicのWEBサービスのみ<br>◎誰でも閲覧することができる
|Tableau Desktop<br>Professional Edition|有料|普段には「Tableau」と言われる|
|Tableau Desktop<br>Personal Edition|有料|◎Professionalより、安い<br>◎Professionalより、対応しているデータソースが少ない<br>◎Tableau Server及びOnlineにアップロードできない|
|Tableau Prep Builder|有料|フローを作成するアプリケーション|
|Tableau Prep<br>Conductor|有料|◎作ったフローを管理（定期実行）する<br>◎Tableau Data Management Add-onのライセンスに属する|
|Tableau Server|有料|◎作成した分析結果を共有する製品<br>◎サーバー用意が必要|
|Tableau Online|有料|◎作成した分析結果を共有する製品<br>◎サーバー用意が必要ないが、ホスティング料がライセンス<br>価格に加算される|
|Tableau Data <br>Management Add-on|有料|データの準備とガバナンス強化|
|Server Management<br>Add-on|有料|Tableau Server 導入環境で、管理性、スケーラビリティ<br>およびセキュリティ強化|
|Resource Blocks|有料|サイト内で複数の Prep フローを同時に実行|

#ライセンス価格#
展開オプションの選択によって、ライセンス価格が変わります。ライセンスプログラムが３種類があります。

|プログラム|利用できる商品|用途|
|---|---|---|
|Creator| Tableau Desktop<br>Tableau Prep Builder<br>Tableau Online|◎分析データの準備<br>◎公開データの分析
|Explorer|Tableau Online|公開データの分析
|Viewer|Tableau Online|分析データの閲覧

##Tableau Serverでの展開##

|プログラム|年間価格（税抜）|注意点|
|---|---|---|
|Creator|102,000円|最低購入数:1
|Explorer|51,000円|最低購入数:5
|Viewer|18,000円|最低購入数:100
|Tableau Data Management<br>Add-on|8,000円|すべてのライセンスに価格が適用される|
|Server Management Add-on|5,000円|すべてのライセンスに価格が適用される|

##Tableau Onlineでの展開##

|プログラム|年間価格（税抜）|注意点|
|---|---|---|
|Creator|102,000円|最低購入数:1|
|Explorer|60,000円|最低購入数:5|
|Viewer|22,000円|最低購入数:100|
|Tableau Data Management<br>Add-on|8,000円|すべてのライセンスに価格が適用される|
|Resource Blocks|360,000円|◎最低購入数:1<br>◎1 Resource Block につき、1つのPrep<br>フローを同時実行可能|

#最後に#
第１印象は高額なツールだと感じます。ただし、多様なデータソース対応なので、プログラミングせずに直接にDB上のデータを分析できることが便利です。エンジニアの開発工数にかけるより、Tableauがいろいろな機能が揃えていますので、こちらにかけた方が価値があるかと思います。
学習の目的などで初めてTableauを触ったら、Tableau Publicが良いと思います。10万行のデータと保存先がTableau Publicサーバのみ、ユーザーアカウント毎に保存容量の10GBが無料という制限がりますが、これでも充分だと思います。
Vega解説 〜基準線をひく〜

今回は、垂直、あるいは水平な線を引きます。グラフと一緒に引くことで閾値と表現したりします。


## 離散データに閾値の線を引く

以前作成した[離散データ](https://qiita.com/ihgs/items/87fda0cd39693bae44f3)に閾値(y=35)の線を引きます。ついでに閾値を下回ったものものは、棒グラフの色を変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51316/5afe1854-11a8-3d73-bc95-965920fcdf45.png)

[Online Editor で開く](https://vega.github.io/editor/#/gist/b57295c8d2d65149715e41c154a74471/pattern1.json)
[差分](https://ihgs.github.io/online-diff/?diff=ihgs/54fcc244e57c652c3d4d227881fcdecc/raw/01_barchart_base.json...ihgs/b57295c8d2d65149715e41c154a74471/raw/pattern1.json)


### 詳細

data に閾値のデータを追加します。 

```json
 {"name": "threshold", "values": [{"value": 35}]},
```


marks に以下を追加します。線は `type=rule` で表現します。これは(x,y)から(x2,y2)に線を引くものになります。

ポイントは、xにグラフ描画キャンバスの始点０を指定し、x2 で幅一杯の端を表すため `{"field": {"group": "width"}}` を設定しています。

```json

    {
      "name": "layer_threshold",
      "type": "rule",
      "from": {"data": "threshold"},
      "encode": {
        "enter": {
          "x": {"value": 0},
          "x2": {"field": {"group": "width"}},
          "y": {"scale": "yscale", "field": "value"},
          "y2": {"scale": "yscale", "field": "value"},
          "strokeWidth": {"value": 2},
          "stroke": {"value": "red"}
        }
      }
    }
```

閾値以下の棒グラフの色を変更するために、元々ある棒グラフのmarkの `fill` を変更します。

```json
          "fill": [
            {
              "test": "datum.amount < data('threshold')[0].value",
              "value": "red"
            },
            {"value": "steelblue"}
          ]
```


## 時系列データに今日の日付の直線を引く

[Vega 解説 ~時系列データを処理する~](https://qiita.com/ihgs/items/05e10b9f20faa002be18)の最後の[グラフ](https://vega.github.io/editor/#/gist/54fcc244e57c652c3d4d227881fcdecc/06_time_barchart_02_2.json)をベースに今日を表す線を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51316/cac04ae4-29cb-fb3e-6369-0cd840104bc0.png)

[Online editorで開く](https://vega.github.io/editor/#/gist/b57295c8d2d65149715e41c154a74471/pattern2.json)
※ data の `month` は今日の日付を出すために適当に変更してください。


### 詳細

marksに以下を追加しています。
x,x2に `now()` という関数を利用しています。

```json
    {
      "name": "layer_today",
      "type": "rule",
      "encode": {
        "enter":{
          "x": {"scale": "xscale", "signal": "now()"},
          "x2": {"scale": "xscale", "signal": "now()"},
          "y": {"value": 0},
          "y2": {"field": {"group": "height"}},
          "strokeWidth": {"value": 5},
          "stroke": {"value": "red"}

        }
      }
    }
```
個人アプリ開発日記 #3

#目次
[1.はじめに](#1-はじめに)
[2.内容](#2-内容)
[3.おわりに](#5-おわりに)

#1. はじめに
前回の[個人アプリ開発日記#2](https://qiita.com/shimataro1988/items/6ff4c2ce6b80ad790173)では、このアプリを開発したいと思ったきっかけについて述べました。

そして3記事目の今回は、私が現在作っている「フレンドマッチングアプリ」と
既存のアプリについて比較します！理由は、将来的にリリースすることも視野に入れているので、
せっかく作ったものの「これって○○と似てない？」「○○と何が違うの？」
というような残念なことにしたくないからです。

とは言えまだまだ詰めが甘い点は多いですが、自分なりに差別化を図りながら制作しているつもりなので、
思考整理も兼ねて投稿します。

#2. 内容
まずは、既存のアプリを友人、他人、1:1、1:nの4つの切り口で、簡単なマトリックスにしてみました。

||友人|他人|
|:--:|:---:|:--:|
|1:1|チャット(LINE, WeChat, Snapchat)|マッチング(Tinder, Pairs, with, タップル)|
|1:n|SNS(Facebook, Instagram, Twitter)|メディア(YouTube, TikTok, SHOWROOM|

LINEのオープンチャット、Twitterの趣味垢、InstagramやFacebookのDM/
メッセンジャーなどを含めると、もっと細分化してしまいますが、
ざっくりしたところでは上記のように大別できるのではないでしょうか。

私のフレンドマッチングアプリは、1:1で他人がターゲットなのでマッチング系に属することになります。
しかし、既存のマッチング系は顔写真でスワイプで好みを選択したり、恋愛・婚活寄りが多いと感じています。
「つながりを、もっと身近に」というコンセプトは以前の記事にも書いたのですが、あくまで年齢や出身地、
血液型などの項目別もしくは、ハッシュタグ検索を主としています。

また「友達が欲しいけど作る機会に恵まれていない人」をペルソナに設定しているため、友達や雑談相手
探しに利用することをイメージしています。ただし、フレンドマッチングアプリ自体は当然先行がいて
（"Tantan"というアプリ名で顔写真でスワイプする点はTinderと同一）、マッチングアプリ世界王者の
Tinderも当初の恋愛系からライフスタイル全般のマッチングに裾野を広げていますので、
独自性を追求すべくこれからも動きを注視したいと考えています。

#5. おわりに
アプリ制作は初めてのため初心者ですが、中身の細かい実装をしながらでも、
視野が狭くなりすぎないように適度にアプリ全体を俯瞰することを意識しています！
SQLでSELECT文にユーザーが指定した条件のみ検索条件を足していく方法

＊sqlインジェクション対策はしておりません

転職サイトでの絞り込み検索のようなユーザーが指定した検索条件のみを足していくとき、


```java
"SELECT * FROM HOGE_TABLE WHERE "; //ベースとなるSELECT文

" AGE = 30 " //ユーザーが指定するかもしれない検索条件
" NENSYUU > 300 " //ユーザーが指定するかもしれない検索条件
```

としていると、このあと上記２つともを検索条件に足す場合,
ユーザーがどちらを先に検索条件に指定するかわからないためANDをつける位置を
if文で分岐しないといけない。
しかし、ベースとなるSELECT文を

```JAVA
"SELECT * FROM HOGE_TABLE WHERE 1 = 1 "; //ベースとなるSELECT文

```

とするだけで全表示の意味になり、検索条件のSQL文にすべてANDをつけてよくなる。

```JAVA

"SELECT * FROM HOGE_TABLE WHERE 1 = 1 "; //ベースとなるSELECT文

" AND AGE = 30 " //ユーザーが指定するかもしれない検索条件
" AND NENSYUU > 300 " //ユーザーが指定するかもしれない検索条件
```

ユーザーが上記２つの検索条件を指定した場合、結果的にできるSQL文はこうなる。

```JAVA
" SELECT * FROM HOGE_TABLE WHERE 1 = 1　AND AGE = 30　AND NENSYUU > 300 "


```
【フロントエンド学習②】インライン要素とブロックレベル要素

# HTMLタグの種類について
bodyタグ内で使用するHTMLタグには、
大きく分けて「インライン要素」と「ブロックレベル要素」がある。


## インライン要素の特徴
- 自動で改行されない<font color="red">（ヨコに並ぶ）</font>
- 横幅・縦幅を指定ができない
- 中央揃え（右寄せ）の時は、親要素に「text-align: center(right);」を記述する

## ブロックレベル要素の特徴
- 自動で改行される<font color="red">（タテに並ぶ）</font>
- 横幅・縦幅の指定ができる
- 中央揃えの時は、自身に「margin: 0 auto;」を記述する

デモ

<p class="codepen" data-height="400" data-theme-id="dark" data-default-tab="css,result" data-user="tanakatarou590" data-slug-hash="YzGaWYK" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="YzGaWYK">
  <span>See the Pen <a href="https://codepen.io/tanakatarou590/pen/YzGaWYK">
  YzGaWYK</a> by 転職活動中の なーちゃん@Webエンジニアに転職2020 (<a href="https://codepen.io/tanakatarou590">@tanakatarou590</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>



## おまけ（初めて見るタグの判別方法）

```html:index.html
<span>あいうえお</span>
<span>かきくけこ</span>
<span>たちつてと</span>
```

上記のように記述して、ブラウザで表示してみる(文章はなんでもOK)

- 改行される→ブロックレベル要素
- 改行されない→インライン要素

ちなみにspanタグはインライン要素なので、改行されません。

おわり
laravel + vue.jsのファイルアップロードについて

###この記事を書いたきっかけ
これから始めるvue.js実践入門(山田祥寛)のファイルアップロードの項目を見ていて、laravel+vueの時には同じ書き方だと動かないことに気づいたから。

###vue.jsでは普通はどうするの？

```js:test.vue
new Vue({
  el: '#app',
  data: {
    message: ''
  },
  methods: {
    onchange: function() {
      let that = this;
      let fl = this.$refs.upfile.files[0];
      let data = new FormData();
      data.append('upfile', fl, fl.name);
      fetch('upload.php', { 
        method: 'POST',
        body: data,
      }) 
      .then(function (response) {
        return response.text();
      })
      .then(function (text) {
        that.message = text;
      })
      .catch(function (error) { 
        window.alert('Error: ' + error.message);
      });
    }
  }
});
```
(upload.phpは省略します。下にあるtest.blade.phpと内容は同じです。)

####試したこと1
resources/js/app.jsと、resources/js/components/Mycomponents.vueに上記のファイルの内容を配置しupload.phpをcomponents配下にupload.phpを置いてみる(雑。)
結果：
fileupload後に、「No input file specified. file upload」のメッセージが返ってくる。(失敗)

####寄り道はこれくらいにして・・・・・・
```js:myComponent.vue
    <form>
       <input ref="upfile" type="file" v-on:change="onchange3" />
       <input type="hidden" name="_token" v-bind:value="csrf">
    </form>
    <br />
    <p>{{ message }}</p>
    <br />

<script>
  data: function () {
    return {
      csrf: document.head.querySelector('meta[name="csrf-token"]').content,
    };
  },
  methods: {
 onchange3: function() {
      let that = this;
      let fl = this.$refs.upfile.files[0];
      let data = new FormData();
      data.append('upfile', fl, fl.name);

      fetch('/hello/fileupload',{
        method: 'POST',
        body: data,
        headers: {"X-Requested-With": "XMLHttpRequest",
        'X-CSRF-TOKEN':this.csrf}
      })
      .then(function(response){
        return response.text();
      })
      .then(function(text){
        that.message = text;
      })
      .catch(function(error){
        window.alert('Error：' + error.message3);
      });
    }
}
</script>
```

```php:web.php
Route::post('/hello/fileupload', [HelloController::class, 'file']);
```
```php:HelloController.php
class HelloController extends Controller
{
    public function file()
    {
        return view('hello.test');
    }
}
```
```php:test.blade.php
<?php
$error = false;
if ($_FILES['upfile']['error'] !== UPLOAD_ERR_OK) { 
  $error = true;
} else {
  $src = $_FILES['upfile']['tmp_name']; 
  $dest = mb_convert_encoding($_FILES['upfile']['name'], 'SJIS-WIN', 'UTF-8');
  if (!move_uploaded_file($src, $dest)) { $error = true; }
}
if ($error) {
  header('HTTP/1.1 500 Internal Server Error');
  print 'アップロードできませんでした。';
} else {
  print 'アップロード成功：'.$dest;
}
?>
```
```php:index.blade.php
<!doctype html>
<html lang="ja">
<head>
    <title>Index</title>
    <link href="{{ mix('css/app.css') }}"  rel="stylesheet" type="text/css">
    <meta name="csrf-token" content="{{ csrf_token() }}">
</head>
<body>
<-- 以下省略 -->
```

これでとりあえずは（？）うまくいっているように見えました。
・非同期処理でaxiosをつかっていないところ
・laravelのファイルアップロード機能をつかっていないところ

等、通常のやり方でないところもあると思うのですが、一応一つのやり方のメモとして参考になればと存じます。ここまで読んでいただきありがとうございました。
Zゲートの固有状態

＃はじめに
[量子コンピュータによる量子化学計算入門](https://bookclub.kodansha.co.jp/product?item=0000347332)を見ていたら次のような記述があった。

> パウリ-Zは量子ビットの量子状態が$|0\rangle$であれば$|0\rangle$のままに, $|1\rangle$であれば$-|1\rangle$に変換するが,これはブロッホ球でZ軸上にある$|0\rangle, |1\rangle$がパウリ-Z演算子の固有状態となっていて,その固有値がそれぞれ1, -1であることを意味している。
> (p.41)

は? ...うわ、まじか。全然意識してなかった。

#Zゲート
Z軸上の基底$|0\rangle,|1\rangle$にZゲートを作用させる式は次のようになる。

- $Z|0\rangle = |0\rangle$
- $Z|1\rangle = -|1\rangle$

確かにZゲートを作用させても状態ベクトルは変わっていないから、この状態ベクトルはZゲートの固有状態だ。
Zゲートはユニタリ行列で状態ベクトルの大きさを変えないから、固有値は位相として現れるのか。

ユニタリ行列をその固有状態に作用させる演算は、固有値を位相として取り出す演算になるのだろうか？

#Xゲート
今度はXゲートを見てみる。
Z軸上の基底$|0\rangle,|1\rangle$にXゲートを作用させると次のようになる。

- $X|0\rangle = |1\rangle$
- $X|1\rangle = |0\rangle$

状態ベクトルが変わっているから$|0\rangle,|1\rangle$はXゲートの固有状態ではない。
X軸上の基底でやってみると

- $X|+\rangle = |+\rangle$
- $X|-\rangle = -|-\rangle$

確かに$|+\rangle,|-\rangle$がXゲートの固有状態であることがわかる。

#ZX演算
じゃあ、Zゲート、Xゲートの順で作用させるような演算の固有状態、固有値ってどうなるんだろ？ $XZ = -iY$なので次式でいける？

- $XZ|i\rangle = -i|i\rangle$
- $XZ|-i\rangle = i|-i\rangle$

計算は合ってそう。
演算子の関係がわかっていれば、固有値や固有ベクトルもそこからわかるのかな？

#おわりに
ZゲートとZ基底の関係がわかった。
けどそこから先はいまいち。。。今は一旦ここまで。
Laravelのサービスプロバイダについて

Laravelのサービスプロバイダについて調べたことを簡単にまとめます。

##サービスプロバイダとは？
サービスプロバイダとはサービスをサービスコンテナに登録するためのもの。

サービスコンテナについては[Laravelのサービスコンテナについて調べたことを簡単にまとめてみた](https://qiita.com/howaito01/items/34940d7286b281b1b36d)でざっくりまとめてます。

##サービスプロバイダを使って、サービスコンテナにサービスを登録する手順

###サービスプロバイダーの作成

```
php artisan make:provider SampleServiceProvider
```

実行するとapp\Providersの下にSampleServiceProvider.phpファイルが作成される。

中身は下記の通り。

```
class SampleServiceProvider extends ServiceProvider
{
    public function register()
    {
        //
    }

    public function boot()
    {
        //
    }
}
```

registerメソッドはサービスコンテナにサービスを登録するための記述をする。
bootメソッドはすべてのサービスプロバイダーが読み込まれたあとに実行したいコードを記述する。

###registerメソッドに処理を追加

```
public function register()
{

    app()->bind('testSample', function(){
        return 'test';
    });

    //下記の記述でもOK。
    $this->app->bind('testSample', function(){
        return 'test'; 
    });     
            
}
```

###config/app.phpへ追加

```
    'providers' => [
        App\Providers\SampleServiceProvider::class,
    ]
```

###サービスを使う

```
$test = app()->make('testSample');

dd($test);
```

##参考
[Laravel サービスプロバイダーついに理解](https://reffect.co.jp/laravel/laravel-service-provider-understand)
【Python】AnacondaでJupyter Notebookを使ってpandasをインポートするとModuleNotFoundErrorが出るときの対処法

環境メモ
⭐️Mac Book Pro(macOS Catalina)
⭐️Anaconda 4.9.2
⭐️Python 3.8.5
⭐️Jupyter Note book 6.1.6
⭐️Pandas 1.1.5

AnacondaでJupyter Notebookを使用。
Pandas（パンダス）を実行すると

<b><font color="MediumVioletRed">ModuleNotFoundError: No module named 'pandas'</font></b>
のimportエラーが出て、実行できない場合の対処法を説明します。

# Anacondaでpandasをインストール

Anacondaを使っていれば、最初からpandasがインストールされているようです。

```
conda list | grep pandas
```


インストールされていなければインストールする

```
conda install pandas
```

pandasをアップデートする

```
conda update pandas
```

## Anaconda Navigatorでpandasのライブラリを追加する

Anaconda Navigatorでpandasのライブラリを追加します。
![スクリーンショット 2021-01-01 1.01.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93155/68817300-97e6-95c5-9117-2268eda71b8b.png)


これでOK！！

## AnacondaやPythonのバージョンなど環境の確認する
AnacondaやPythonのバージョンなど環境の確認をする場合は、下記のコマンドで確認することができます。

```
conda info
```

## Anacondaのpandasのバージョンを確認する

```
conda list  | grep pandas
```


## Jupyterのバージョン確認

下記コマンドでJupyterのバージョンを確認することができます。

```
jupyter --version
```

## Pythonのバージョン確認

下記コマンドでPythonのバージョンを確認することができます。

```
python --version
```
Laravelのサービスコンテナについて調べたことを簡単にまとめてみた

Laravelのサービスコンテナについて調べたことを簡単にまとめます。

##そもそもサービスコンテナとは？
LaravelではDIコンテナをサービスコンテナと呼びます。
簡単にいうと、**サービスを格納できる入れ物**です。
そして、**格納しているサービスを使うこと（インスタンス化）**ができる。

サービスとは、色々な機能（メール送信など）のこと。

クラスを入れておくものぐらいのイメージでも良いと思います。（たぶん）

##サービスコンテナの使い方
（）の箇所は省略可能です。

>1.サービス化したいクラスを作る
2.（サービスプロバイダを作って app.php に登録する｜AppServiceProviderを使う）
3.（registerにインスタンス化する方法を定義しておく）
4.（bootでサービス同士の依存関係を解決する）
5.（ファサードを定義して app.phpに登録する）
6.サービスコンテナにインスタンスを提供してもらう

>参照：[第1回 もう怖くない DIだって知らなくていい こんなにカンタンだから今日から Laravelのサービスコンテナ を使ってみて！](https://qiita.com/kd9951/items/951ab700f28d1d49c9c9#%E5%89%8D%E6%8F%90)

要するに最低限の機能で使うなら、1と6だけでOK。
記述すると、次の通り。（引数にクラスを入れてあげるとインスタンス化できる。）
 
```
$sampleobject = app()->make('App\SampleClass');

//new　で書く場合
$sampleobject = new App\SampleClass;
```

##サービスコンテナはクラスの依存を解決するためのもの
今紹介したように、サービスコンテナは最低限の機能だけを利用するなら、超簡単。

でもこれだと「何のためにあるの？」ってことになりますよね。

**結論から言うと『クラスの依存を解決するため』らしいです。**

ちょっと難しい話ですが、要するにクラスに依存しているものを自動的に解決してくれるのがサービスコンテナとのこと。

これらによって、下記のメリットがあります。
>(1)テスト時にはアプリケーションコードで生成されるインスタンスをテスト用にすり替えるといったことができたり、
(2)あるインスタンスはアプリケーション実行プロセスで一つだけ（シングルトン）にしたいので、2回目の生成時には前回生成したインスタンスを返す

##サービスコンテナへの登録方法

サービスコンテナへの登録方法は2つ。

①bindメソッド・singletonメソッドをコントローラーなどに記述する方法
②サービスプロバイダーを使用する方法

ちなみにbindメソッドとかは下記のように使える。

```
app()->bind('myclass', Sample\MyClass::class);

app()->singleton('myclass', Sample\MyClass::class);
```

②の方法でやるなら、
・サービスプロバイダーの作成
・registerメソッド内に処理（インスタンスを返す）を追加
・config/app.phpのproviderに登録
この手順で登録すればOK。
SPAで作成されたWebサイトをスクレイピングする方法

Pythonでスクレイピングする方法としてこれまでrequestsモジュールを使っていたのですが、これはサーバ側で生成したHTMLを返すサイトでは使用できますが、JavaScriptを実行する前のレスポンスしか得られませんので、クライアント側でJavaScriptを実行してHTMLを手元で生成するようなSPAで作成されたサイトでは使えませんでした。

## requests-htmlモジュール

SPAで作成されたサイトをスクレイピングするためにはrequests-htmlを使う必要があります。

## インストール

```
pip install requests-html
```

## 使い方

```main.py
# -*- coding: utf-8 -*-
import requests
from requests_html import HTMLSession

def main_render_javascript_page():
    url = 'https://hogehoge'
    session = HTMLSession()
    r = session.get(url)
    r.html.render()
    title =  r.html.find('body', first=True).text
    print(title)
        
def main_normal_page():
    url = 'https://hogehoge'
    r = requests.get(url)
    print(r.text)

if __name__ == '__main__':
    main_normal_page()
    main_render_javascript_page()

```

## 公式

https://requests.readthedocs.io/projects/requests-html/en/latest/

## 参考サイト

https://dev.classmethod.jp/articles/python-asyncio/
https://blog.ikedaosushi.com/entry/2019/09/15/162445
EC2インスタンスを停止しても従量制課金が適用される

#何が問題か

テスト用のEC2インスタンスをもう使わないと思い、停止したのだが後日料金が発生していることに気がついた。

![スクリーンショット 2021-01-03 21.12.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668547/02440307-87de-9c19-9744-b00f7aa26fcf.png)

12月の初め頃からEC2を停止していたはずなのだが、課金されている。。

#解決方法

EC2インスタンスに紐づいていたElasticIPの関連付けを解除する。


#問題解決までの流れ

EC2インスタンスは全て停止しているので、課金が発生するのはおかしいと思い調べたところAWSによる以下の説明が。

>インスタンスを終了したが、アカウントに EC2 リソースがプロビジョニングされている

>請求書の Elastic Compute Cloud の明細項目には、インスタンス以外のリソースが含まれています。EC2 インスタンスは、次のような他の EC2 リソースと共に使用されることがよくあります。

>Elastic IP アドレス
Amazon Elastic Block Store (Amazon EBS) のボリューム


https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-billing-terminated/

どうやらEC2の請求明細にはElastic IP アドレスやAmazon Elastic Block Store (Amazon EBS) のボリューム（何のことかわからないです、初心者でスンマソ）が含まれているらしい。。

Amazon EBSを使った覚えはないので、Elastic IP アドレスが怪しいと睨んだ。

以下のAWSユーザーガイドを参考にElastic IPの解除を行う。手順は以下のとおり。


1.EC2コンソール( https://console.aws.amazon.com/ec2/ )を開く

2.リソースのElastic IPを選択

3.関連付けを解除するElasticIPアドレスを選択し、アクションから「ElasticIPアドレスの関連付けを解除」を選択

4.関連付けを解除するを選択


https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html#using-instance-addressing-eips-associating-different

#ElasticIPの料金体系

これで関連付けは解除できましたが、そもそもElasticIPって料金かかるんだっけ・・？という疑問が。

公式サイトで調べてみると、

>次の条件がすべて満たされている限り、Elastic IP アドレスに料金は発生しません。

>Elastic IP アドレスが EC2 インスタンスに関連付けられている。
Elastic IP アドレスに関連付けられているインスタンスが実行中である。
インスタンスには、1 つの Elastic IP アドレスしかアタッチされていない。
Elastic IP アドレスは、Network Load Balancer や NAT ゲートウェイなどのアタッチされたネットワークインターフェイスに関連付けられます。


上記の条件を全て満たしている時のみ課金されないみたい。

私の場合、EC2を停止したことによって「Elastic IP アドレスに関連付けられているインスタンスが実行中である。」の条件を満たさなくなってしまったので、Elastic IPによる料金が発生するようになってしまったわけですね。。

料金について理解しておくの大事・・。

#参考になったサイト
https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-billing-terminated/
https://qiita.com/s_tatsuki/items/c808a916acf044d94afc

何か気づいたことよ間違ったことあればご教授ください。
Pythonの導入

PythonをMacにインストールしたので備忘録


### pyenvのインストール

pyenvは、「複数のバージョンのPythonを管理できる」ツールです。
とりあえず、入れたほうがいい。

```:homebrewでインストール
brew install pyenv
```

インストールできたかは、以下にてバージョンが表示さればイントールできていることになる。

```
pyenv -v
```


### pyenvの設定

私は、zshを使用しているので以下を設定。

```:.zshrcの設定
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
export PATH="$HOME/.pyenv/shims:$PATH"
eval "$(pyenv init -)"
```

```:設定を反映させる
source .zshrc
```

### Pythonのインストール

最初にも紹介した通り、pyenvでは複数のバージョンのPythonを使用することができます。
どのようなバージョンのPythonがインストールできるか以下のコマンドをターミナルで実行してみる。

```
pyenv install --list
```

上記リストにて私の場合は、3.9.0が最新のようでしたのでインストールしてみる。

```
pyenv install 3.9.0
```

イントールできたかは以下で確認してみましょう。

```
pyenv versions
```

```
[~/work] % pyenv versions

*  system
   3.9.0 (set by /Users/XXXXX/.pyenv/version)
```

上記では、systemのため、Macに標準でインストールされているバージョンのPythonを使用しています。
変更しましょう。


```
pyevn global 3.9.0
```

最後にちゃんと3.9.0に変更されていることを確認して完了です。

```
python --version
```
Raspberry Pi OS　アップデート

まず
sudo apt update
次に
sudo apt upgrade

注意事項
何があっても
sudo apt full-upgrade
というコマンドは打ってはいけない。大変危険である。互換性を考慮せずに色々インストールされてしまい、二度とGUIに行けなくなる。
OSインストールし直しになるよ。
[Flutter] FlappySearchBarを使った検索機能の実装

UIKitのUISearchBar風のUIをFlutterで実装するために「[FlappySearchBar](https://pub.dev/packages/flappy_search_bar)」を使ってみたので、
そちらをご紹介したいと思います。

##完成形
これを作ります
<img src ="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393442/f6910ac7-f01b-0e3e-1d84-02babb8891ed.png" width=350>

##インストール
podspec.yamlに以下を定義します。推奨versionについては[pub.dev](https://pub.dev/packages/flappy_search_bar)をご確認ください。
定義した後に、_pub get_をお忘れなく。

```yaml
dependencies:
flappy_search_bar: ^1.7.2
```

##実際のコード
RepoListというStatelessWidgetを作成して、その中にScaffoldを入れ、
そのbodyにSearchBarを入れました。
実際のコードは以下になります。


```dart
import 'package:flappy_search_bar/flappy_search_bar.dart';

class RepoList extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),   
      body: SearchBar(
        onSearch: hoge, // テキスト入力された時に実行される
        onItemFound: (item, index) {
          return Fuga(item); // onSearchで実行された結果
        },
      ),    
    );
  }
}
```

余談ですが、
SearchBarの引数の__onSearch__と__onItemFound__は必須となっています。
2つは内部でそれぞれ、以下のように定義されています

```dart
class SearchBar<T> extends  StatefulWidget {

 final Future<List<T>> Function(String text) onSearch;
 final Widget Function(T item, int index) onItemFound;

/// 省略
}
```

なので、
Widget内の、__hoge__と__Fuga__はそれぞれ以下のようになります。

```dart

// hoge
Future<List<String>> hoge(String text) async {
  //　何かしらの非同期処理
}

// Fuga
class Fuga extends StatelessWidget {
  final item String

  Fuga(this.item, {Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Text(item),
    );
  }
}

```

さらに余談ですが、__SearchBar__は他にも引数が定義されており、色々とカスタマイズすることができます。
使用頻度が高そうなものは以下でしょうか、

```dart

// 検索に必要な最低文字数の指定　デフォルトは3
  final int minimumChars;
// 検索のDebounceTimeを指定 デフォルトは500ms
  final Duration debounceDuration; 
// 結果が空の時に表示するWidget デフォルトはSizedBox.shrink()
  final Widget emptyWidget; 
// Placeholder用のWidget  デフォルトはなし
  final Widget placeHolder;
```

##まとめ

普段はiOSをメインで触っていて、Flutterは勉強中ですが、
すごくいい感じに実装することができて、書いていて気持ちいいですね🤤

見ていただきありがとうございました。

##関連記事
FlappySearchBar https://pub.dev/packages/flappy_search_bar

***

普段は東京でiOSエンジニアとして活動しています。
個人開発のアプリもリリースしました。

[Twitter](https://twitter.com/maxmax2525425)
Axios / Get

## 本日のゴール
- axios.get を使えるようになる

## アジェンダ
1. 下準備
2. import axios
3. getData の出力

## 1. 下準備
- html, jsonは下記のように準備

### HTML

```html
<ul class="js-AxiosTest">
<!-- 
  // この中にgetしたデータを出力予定
  <li>Heading 1<br>text 1</li>
  <li>Heading 2<br>text 2</li>
  <li>Heading 3<br>text 3</li>
 -->
</ul>
```

### json

```json
[{
  "title": "Heading 1",
  "text": "text 1"
}, {
  "title": "Heading 2",
  "text": "text 2"
}, {
  "title": "Heading 3",
  "text": "text 3"
}]
```

## 2. import axios

### Github
https://github.com/axios/axios

### CDN
```html
<script src="https://unpkg.com/axios/dist/axios.min.js" defer></script>
```

### 3. getData の出力
```javascript
class AxiosGet {
  constructor(el) {
    this.el = el
    this.srcHtml = ''
  }

  async init() {
    this.items = await this.getData()
    this.srcHtml = this.createHtml(this.items)
    this.el.innerHTML = this.srcHtml
  }

  async getData() {
    const { data } = await axios.get('http://localhost:3000/data/index.json') // 取得したいjsonのパスを記載
    return data
  }

  createHtml(items) {
    let elements = ''
    for (let item of items) {
      elements += `
        <li>${item.title}<br>${item.text}<li>
      `
    }
    return elements
  }
}

const el = document.querySelector('.js-AxiosTest')
new AxiosGet(el).init()
```
ネットワークの基礎（２）【プロトコル(OSI参照モデル)】

CCNAの試験に向けて学習中。
復習に見返せるようにメモしていきます。
ほぼ自分の勉強メモです。
過度な期待はしないでください。


プロトコル
-
プロトコルとは、<b>データ通信を行うための手順や規則を定めたもの</b>です。
コンピュータ同士がデータをやりとりする際、データをどのような形式で、どのような手順で送るか
または、受け取るかを決める規則が必要になります。
なので、データ通信はプロトコルで決められた手順や規則に沿って実行して初めてネットワークが機能します。

また、ネットワークで使用されているプロトコルは一つではありません。
インターネットで検索したり、メールを送信したりする際には、それぞれ別の異なる複数のプロトコルが
使用されています。

そうした複数のプロトコルを階層的に構成したものを、<font color="Red">プロトコルスタック</font>または<font color="Red">プロトコルスイート</font>をいう。

そして、その際の階層化の考え方として、<b><font color="Red">OSI参照モデル</font></b>や、<b><font color="Red">TCP/IPモデル</font></b>があります。

<br>

OSI参照モデル
-
- OSI参照モデルの概要

OSI参照モデルとは、<b>機種が異なるあらゆるPC、ネットワーク機器、ソフトウェアがそれぞれ相互に接続
出来るようにISO（国際標準化機構）で定められたもの</b>をいう。
そして、OSI参照モデルに基づいて設計されたプロトコル群を、<font color="Red">OSIプロトコル</font>をと言います。

以前は、ネットワーク機器はベンダー（ネットワークメーカーの事を総じてこう呼ぶ）独自のプロトコルで通信をしていた為、
機器のベンダーが異なると通信出来ませんでした。
異なるベンダーでも通信が出来るように共通の仕様を考える必要があり、そこで生まれたのが、OSI参照モデルです。
<br>

- OSI参照モデルの7階層とその役割

OSI参照モデルは、通信を行う為の機能が７つの階層に分かれ、それぞれが役割を定められています。
各階層は<b>レイヤ</b>と呼ばれ、上から順に、レイヤ７、レイヤ６となり、一番下がレイヤ１となります。
データを送信する際には、上の層から順番に各階層で、通信に必要な情報が付加されます。
<br>

※OSI参照モデルの各階層

|レイヤ　　　　|階層　　　　　　　　　　　　　　　　　　　　　|
|:---|:---|
|7|アプリケーション層|
|6|プレゼンテーション層|
|5|セッション層|
|4|トランスポート層|
|3|ネットワーク層|
|2|データリンク層|
|1|物理層|
７〜５が上位層、４〜１が下位層
<br>

・アプリケーション層
ユーザーが利用するアプリケーション間での通信に関して規定。
Web用のプロトコル、メール用のプロトコルといったユーザーが利用するアプリケーションで
使用するプロトコルで規定されています。
　

・プレゼンテーション層
通信する際の文字コードといった、データの表現方式に関して規定。
送信側が使用した独自の表現方式から、受信側で使用する表現方式に復元することで、
送信元と宛先の機器で使用するアプリケーションが異なった表現方式を利用していても通信出来る
ようになります。
<br>


・セッション層
通信の、開始、維持、終了を規定。
通信が開始して終了するまでを管理する一塊を<b>セッション</b>といい、
セッションが確率する事でアプリケーション間での通信が可能になる。
<br>

・トランスポート層
ノード間の通信を制御する為の機能を規定。
送信元から送信されたデータが欠けることなく宛先に届けるといった<b>通信の信頼性</b>に
関する機能が規定されています。
<br>

・ネットワーク層
複数のネットワークでエンドツーエンドの通信を可能にする機能を規定。
エンドツーエンドとは、通信を開始する送信元から最終的な宛先までの端末の間のこと。

ネットワーク層の機能により、データの届け先を識別する為に必要となるIPアドレスなどに関する
プロトコルが規定され、また複数の機器を経由する場合どういった経路を通れば良いかを
決定する機能が提供されています。
<br>

・データリンク層
直接接続されたノード間での通信を可能にする機能を規定。
直接接続されている機器間で、相手を識別する為のアドレスに関する規定やエラーの検出と
いった機能が提供されています。
<br>

・物理層
コンピュータ上で使用するデータの電気信号への変換や物理的な接続に関して規定。
<br>

OSI参照モデルのメリット
-
- 各階層に機能を分ける事で、ネットワーク設計者やアプリケーション開発者が各階層の役割を理解しやすい

- 標準化されている為、各ベンダーの製品やプロトコルを組み合わせて設計や構築が可能

- プログラムの開発や改修が容易

-  階層が別れている為、問題の早期切り分けや解決が可能

<br>

カプセル化と非カプセル化
-
- カプセル化

上位層のプロトコルのヘッダ + データをデータとして、その階層のヘッダを付加して下位層に渡すことを
<b><font color="Red">カプセル化</font></b>といいます。

各階層でデータを送信する際に必要な情報は、<font color="Red">ヘッダ</font>という形でデータの先頭に付与されます。
なので、通信データは、<b>ヘッダ + データ</b>の形式で送られます。
ただし、データリンク層ではデータの後ろに<font color="Red">トレーラ</font>もつきます。

階層ごとにヘッダの形式や設定する情報が異なる為、各階層でヘッダを作成し、上の階層から渡された
ヘッダ + データをデータとして、新たにヘッダを付加して通信データを作成します。
<br>

- 非カプセル化

受信側では、送信側とは逆に下の階層から上の階層に向かって通信データが渡されます。
下位層のデータから、その階層のヘッダを取り除き、データを上位層に渡すことを、
<b><font color="Red">非カプセル化</font></b>といいます。

<br>

PDUとペイロード
-
PDUとは、各階層で扱う通信データの単位のこと。

レイヤ4で扱う通信データを<font color="Red">セグメント</font>といい、レイヤ3で扱う通信データを<font color="Red">パケット</font>、
レイヤ2で扱う通信データを<font color="Red">フレーム</font>をいいます。

そして、各階層で取り扱うPDUから、その層のヘッダを取り除いた部分を、
<b><font color="Red">ペイロード</font></b>と言います。

過去投稿記事
-
[ネットワークの基礎（１）【接続形態と通信方法】](https://qiita.com/k-yasuhiro/items/38d643ec262a0309db06)
【Ruby】購入機能実装〜ログイン中・完売商品に対しての分岐〜

### 解決したいこと

①完売商品に対してもう一度購入ができてしまう
②出品者が販売中・完売どちらも商品の編集・削除ができてしまう

if文の分岐すごく苦手なんです。
どこをどう考えたらいいのかわからないので、まずは紙に書き出してみる。

![qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/887559/c821564d-e720-441b-0734-9febe89f0fff.png)


<h4>出品者</h4>
自分の出品物の販売中商品だけ編集＆削除OK
**購入は全てNG**

<h4>購入者</h4>
販売中商品のみ購入OK
**編集＆削除は全てNG**

だいぶ絞れたので実際にコードにしてみます。


```ruby
1<% if user_signed_in? %>
2 <% if current_user.id == @item.user_id %>
3  <% unless @item.purchase.present? %>
4   <%= link_to '商品の編集', edit_item_path(@item.id), method: :get, class: "item-red-btn" %>
5   <p class='or-text'>or</p>
6   <%= link_to '削除', item_path(@item.id), method: :delete, class:'item-destroy' %>
7  <% end %>
8 <% end %>
```
1行目
まずはログイン済ユーザーかどうかをチェック。

2行目
そのユーザーが出品者かどうかをチェック。

3行目
完売商品ではないかをチェック。

4〜6行目
3行目がunlessなので完売商品ではなければ(偽)編集&削除ボタンを表示させる。


時間がかかったのはこの後、どうしても購入ボタンが表示されてしまう。
elsifで分岐・・・いや違う。
もう一度if文で分岐・・・これも違う。
そもそも最初の分岐で売れてるか売れてないかを判断したらいいんじゃないか・・・？
そう思い、生み出した奇跡のコードがこちら。

```ruby
<% if current_user.id == @item.user_id && @item.purchase.present? %> 
```

わけがわからないですね😂

もう一度書いた図を見てみる。
OKなのは販売中商品のみということか。
しかし販売中商品に購入ボタンをつけてしまうと出品者にも購入ボタンが表示されてしまう。
そこでハッと気付く。

2行目
そのユーザーが出品者かどうかをチェック。

ここでelseを使えばユーザーではあるけど出品者ではない＝**購入者**ということではないのかな？


```ruby
1<% if user_signed_in? %>
2 <% if current_user.id == @item.user_id %>
3  <% unless @item.purchase.present? %>
4   <%= link_to '商品の編集', edit_item_path(@item.id), method: :get, class: "item-red-btn" %>
5   <p class='or-text'>or</p>
6   <%= link_to '削除', item_path(@item.id), method: :delete, class:'item-destroy' %>
7  <% end %>
8 <% else %>
9  <% unless @item.purchase.present? %>
10   <%= link_to '購入画面に進む', item_orders_path(@item.id),class:"item-red-btn"%>
11  <% end %>
12 <% end %>
13<% end %>
```

8行目
ログイン中ユーザーだけど出品者じゃない分岐。

9行目
3行目と同じく出品物が完売ではないかをチェック。

10行目
9行目がunlessなので完売商品ではなければ(偽)購入ボタンを表示させる。


<br>
うまいこといきました。
自己解決できるとまた一つ階段を昇れた気がします。
※違っている点、もっと簡単に書けるよというものがあればご指摘頂ければ幸いです。


<br>
2021 1/4
一部修正。

```ruby
1<% if user_signed_in? && @item.purchase == nil %>                                  
2 <% if current_user.id == @item.user_id %>                                        
3  <%= link_to '商品の編集', edit_item_path(@item.id), method: :get, class: "item-red-btn" %>
4  <p class='or-text'>or</p>
5  <%= link_to '削除', item_path(@item.id), method: :delete, class:'item-destroy' %>
6 <% else %>                                                                       
7  <%= link_to '購入画面に進む', item_orders_path(@item.id),class:"item-red-btn"%>
8 <% end %>
9<% end %>
```

1行目
unlessで繰り返されていたものを1行目に追記。
@item.purchase == nilで、**「商品の購入情報がnil(まだ購入されていない)」**と表現。

4行ほど短く、コンパクトにすることができました。
生み出した奇跡のコードにちょっと近いかな？！と自分を褒め称えました。
奥が深い。
量子暗号について簡単に勉強してみた

#はじめに
今回の記事は、研究室のテーマ決めで量子暗号通信についての研究を行うことを視野に入れ、事前にどのようなものなのかある程度知っておきたいことから調査し、まとめました。
ど素人の解釈なので雑な部分や適当、または極端な部分が多々あると思いますがお許しください。

#量子暗号通信
現在はRSA暗号といった公開鍵と秘密鍵から成り立つ暗号が主流となっています。この方式は、現在の古典コンピュータでは、破るのに膨大な時間を要することから、安全性が高く広く利用されています。しかし、このRSA暗号も量子コンピュータによって短時間で破られてしまう日も近いと言われています。
そこで近年話題となっているのが「絶対に破られない」通信方式と言われているBB84プロトコルを用いて量子(光子)を配送する量子暗号通信です。

#量子暗号通信を理解するために必要な知識
ここで量子暗号通信について説明する上で必要となる知識についてザックリとまとめていきます。

###ハイゼンベルグの不確定性原理
ある量子の位置xは精密に測定でき、また同様に運動量pも精密に測定できます。
しかし、それらを共に精密に測定することは不可能であり、一方の精度を上げると、必然期に他方の精度が落ちてしまいます。

###量子の重ね合わせ
量子は２つの状態を同時に保有すことができます。

###観測者効果
量子は微小な粒であることから、1度観測するとその量子が持つ性質が変化してしまいます。

###Vernam暗号
Vernam暗号は、送信側のアリスが伝達したい文字列Aと、同じ長さの乱数列Xの排他的論理和をした文字列Sを受信側のボブに送信します。ボブは受信したSと、先ほどと同じ乱数文字列Xとの排他的論理和を求めることで、文字列Aを得られるといった暗号です。
Vernam暗号の特徴として、

```math
A⊕X⊕X=A
```
と、なることです。そのため、文字列Sは、乱数列Xが知られない限り復元が不可能ということです。
しかし、この暗号には２つの欠点が存在します。
１．ボブとアリスが暗号を共有している必要がある
２．送信毎に別の乱数列を生成する必要がある
そのため、実用的な暗号通信ではなく、一般的には利用されていません。


#量子暗号通信とVernam(バーナム)暗号の併用
量子暗号通信では、Vernam暗号では難点とされている乱数列X(鍵)を、量子の持つ特徴を活かすことで盗聴者イブにばれないようにボブに共有します。
鍵の配送を行うBB84プロトコルでは、光子を光ファイバーを利用してボブに送ります。
アリスが送る光子は偏光方向(0°, 45°, 90°, 135°)を4つの状態の内から1つ決めて送ります。偏光に意味を持たせるため、次の表のように翻訳することとします。

| 0 | 1 |
|:-:|:-:|
| 0° | 90° |
| 45° | 135° |
ボブは送られてきた光子を0°, 90°の偏光状態の光子を観測できるフィルターを用いるか、45°, 135°の偏光状態の光子を観測できるフィルターを用いるか任意に決定します。
ここで重要となるのが光子には(0°, 90°)の0または1と、(45°, 135°)の0または1の性質を両方持たせることができ、観測側は、(0°, 90°)と(45°, 135°)の2つの状態両方を同時に観測する方法がないことです。そのため1度観測してしまうと性質が変化する量子は2度と同じ状態を再現できなくなります。また、アリスが斜めの偏光状態で送った光子を(0°, 90°)を観測できるフィルターを用いても、意味のあるデータ(0または1)として受け取ることができてしまうことです。
ボブは、どちらのフィルターを用いたのか、従来のネット回線を用いてアリスに報告し、正しいフィルターを用いた観測以外の受信したデータは破棄します。
アリスは間違ったデータの部分となる光子を送信し、ボブが任意のフィルターで受信します。これを全てのビットが共有できるまで繰り返し行います。

###利点
この通信方式を用いることの利点は、現在の計算量の観点からの安全性ではなく、現代の物理法則に基づいて安全が保障されている点です。そして、2つのデータを保持する光子の片方のデータしか確認できないため、盗聴しようとしもそれを検出できる点です。

###難点
光子の伝送速度が速くても10Mbpsで決して速い通信速度とは言えないことです。

#まとめ
今回の記事はここまでになります。
自分ではある程度理解しているつもりですしたが、それを書きとめようとすると理解が足りていないことに気づかされました・・・。また、上手くまとめられず書きたいことが上手に書けなかったため、わかりづらい記事になってしまったと思います。m(_ _)m
量子コンピュータや、それに関連する技術は遠い未来の物だと考えていましたが、実現する世界がすぐそこまで来ていることを改めて感じました。近未来の技術を先取りし、これからの時代の技術に後れを取ることがないよう、これからも深く学び続けていきたいと思います。

#参考文献
バーナム暗号について：
https://mathwords.net/vernam

量子暗号の仕組み：
https://www.imes.boj.or.jp/research/papers/japanese/kk28-3-5.pdf

BB84プロトコルの仕組み：
https://www.ipa.go.jp/security/fy12/report/ryoushi.pdf
【Ruby】FizzBuzz問題

## 概要

Rubyの勉強として **FizzBuzz問題** を **while** と **each** を使用して解きました。解き方は他にもありますが、今回は個人的に使用頻度の低い **while** と、よく使用する **each** で問題を解いてみました。

**（2020.1.13 追記） uptoメソッドと引数をつかった方法でも実践しました。**

## 目次

- 実践
    - 問題
    - 解答(while)
    - 解答(each)
    - 解答(upto)
    - おまけ

- 補足

- まとめ

- 参考文献

## 実践

#### 問題

>`1~100` の数字をターミナルに出力してください。

**【条件】**

- 値が3の倍数のとき、`"Fizz"` と出力
- 値が5の倍数のとき、 `"Buzz"` と出力
- 値が3と5の倍数のとき、 `"FizzBuzz"` と出力

#### 解答(while)

```ruby
def fizz_buzz
  num = 0

  while (num <= 100) do    # 100まで繰り返す条件
    num += 1               # 繰り返すたびに1を足していく

    if (num % 15) == 0     # 15の倍数のとき
      p 'FizzBuzz'
    elsif (num % 3) == 0   # 3の倍数のとき
      p 'Fizz'
    elsif (num % 5) == 0   # 5の倍数のとき
      p 'Buzz'
    else                   # それ以外の時
      p num
    end
  end
end

fizz_buzz
```



#### 解答(each)

```ruby
def fizz_buzz

  (1..100).each do |num|     # 1~100まで
    if (num % 15) == 0       # 15の倍数のとき
      p 'FizzBuzz'
    elsif (num % 3) == 0     # 3の倍数のとき
      p 'Fizz'
    elsif (num % 5) == 0     # 5の倍数のとき
      p 'Buzz'
    else                     # それ以外のとき
      p num
    end
  end
end

fizz_buzz
```

#### 解答(upto)

```ruby
def fizz_buzz
  1.upto(100) do |num|  # 1〜100まで
    if num % 15 == 0
      p 'FizzBuzz'
    elsif num % 3 == 0
      p 'Fizz'
    elsif num % 5 == 0
      p 'Buzz'
    else
      p num
    end
  end
end

fizz_buzz
```

#### おまけ

`1〜100まで` ではなく `１〜任意の数まで` というパターンもできたらと思いプログラムを書きました。

方法はあまり変わらなくて **引数で指定した値まで繰り返し処理** をするというだけです。

```ruby
def fizz_buzz(max_num)
  1.upto(max_num) do |num| # 1〜引数で指定した数（任意の数）まで
    if num % 15 == 0
      p 'FizzBuzz'
    elsif num % 3 == 0
      p 'Fizz'
    elsif num % 5 == 0
      p 'Buzz'
    else
      p num
    end
  end
end

p 'いくつまで数えますか？'
num = gets.to_i
fizz_buzz(num)
```

## 補足

>値が3と5の倍数のとき、 `"FizzBuzz"` と出力

```ruby
num % 3 == 0 && num % 5 == 0
```
解答では `(num % 15) == 0` このように書いていますが、上記のように置き換えることができます。

>**3の倍数 or 5の倍数( 15の倍数 )** という条件を先に書く理由



問題文にもあるとおり、 **「3と5の倍数」のとき、FizzBuzz** なので **3の倍数でもあり5の倍数( 15の倍数 )** でなくてはいけません。この条件を最後に書いてしまうと、その前に **「3の倍数」** と **「5の倍数」** の条件が評価されてしまうのではじめに **15の倍数** を追加しています。

## まとめ

- FizzBuzz問題の解き方は他にもあり上記で上げた以外でも解くことができる
- 今回のような条件があるときには **15の倍数** をはじめに追加しないと評価されない

## 参考文献

- [「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典 (フィズバズ問題 (FizzBuzz問題))](https://wa3.i-3-i.info/word18535.html)

- [Ruby 3.0.0 リファレンスマニュアル (Integer#upto)](https://docs.ruby-lang.org/ja/latest/method/Integer/i/upto.html)
opencv4 系のsdkでonCameraViewStartedが呼ばれないエラー回避備忘録

## 概要

```java

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.tutorial2_activity_surface_view);
        mOpenCvCameraView.setVisibility(CameraBridgeViewBase.VISIBLE);
        mOpenCvCameraView.setCvCameraViewListener(this);
        mOpenCvCameraView.setMaxFrameSize(IMG_Width,IMG_Height);
        mOpenCvCameraView.setClickable(true);

```

のようにopencvのCameraViewを使おうとしても、


```
    public void onCameraViewStarted(int width, int height) {
        Log.d(TAG, "onCameraViewStarted w:"+width+"  h:"+height);

    }
```

で定義された`onCameraViewStarted` が呼ばれないというエラーが発生していた。



## 解決策

opencv3系で動いていたcameraview のコールバックは4系だと書き直す必要があるようだ。
ここのチュートリアルを一回コピーし、そこから徐々に自分のやりたかったことに調整すると良い。

https://github.com/opencv/opencv/tree/master/samples/android/tutorial-1-camerapreview
【備忘録】tmuxの設定

#tmux
tmuxは便利だが設定をよく忘れる。設定項目が多い分一つ一つコメントをつけていかないとわからなくなるので備忘録として記録してゆく。

```.tmux.conf
#

# Reset prefix-key
unbind-key C-b

# Set prefix-key C-t
set-option -g prefix C-t

# Use vi key bindings in copy mode.
set-option -g mode-keys vi		
set-option -g mouse on

# Set the base index from which an unused index should be searched when a new window is created.
set-option -g base-index 1

# Update the status line every 1 seconds.
set-option -g status-interval 1	

# Set the maximum length of the right/left component of the status line.
set-option -g status-left-length 20
set-option -g status-left '[#[underscore]#S#[default]] ' 
set-option -g status-right-length 60
set-option -g status-right '{#H} [%Y-%m-%d(%a) %H:%M]'

# Set the foreground/background colour in the status.
set-option -g status-fg "colour255"
set-option -g status-bg "colour70"

# Set monitor activity
set-window-option -g monitor-activity on

set-window-option -g window-status-format " #I:#W{-} " 
set-window-option -g window-status-current-format "#[reverse,bold]|#I:#W{#P}|" 

bind-key X kill-window
bind-key d detach
bind-key i display-panes
bind-key b break-pane
bind-key r source-file ~/.tmux.conf
bind-key e setw synchronize-panes \; display "synchronize-panes #{?pane_synchronized,on,off}"
bind-key ! split-window -h

bind-key h select-pane -L
bind-key j select-pane -D
bind-key k select-pane -U
bind-key l select-pane -R

bind-key -r H resize-pane -L 5
bind-key -r J resize-pane -D 5
bind-key -r K resize-pane -U 5
bind-key -r L resize-pane -R 5

# Start selection per charactor with 'v'.
bind-key -T copy-mode-vi v   send-keys -X begin-selection
# Start selection linewise with 'V'
bind-key -T copy-mode-vi V   send-keys -X select-line
# Start selection blockwise with 'C-v'
bind-key -T copy-mode-vi C-v send-keys -X rectangle-toggle
# Yank with 'y'
#bind-key -T copy-mode-vi y send-keys -X copy-selection
# Yank lines with 'Y'
bind-key -T copy-mode-vi Y   send-keys -X copy-line	
# Put the text after the cursor with 'C-p'
bind-key C-p paste-buffer

## Cooperation with the clipboard
### MacOS
bind-key -T copy-mode-vi y	           send-keys -X copy-pipe-and-cancel "pbcopy"
bind-key -T copy-mode-vi Enter		   send-keys -X copy-pipe-and-cancel "pbcopy"
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "pbcopy"

```

#参考サイト
* [tmuxのおすすめconf設定@2019](https://qiita.com/kalafinalice/items/c02c0345293fe60af6e5)
* [tmux の status line の設定方法
](https://qiita.com/nojima/items/9bc576c922da3604a72b)