OmniAICreator/Qiita-1.07M huggingface dataset:
「Terraform」作成した GCE インスタンス中で、GitHub プライベートリポジトリからソースを落とす

## 背景
Terraform を利用して GCP などのリソースを簡単に apply・destroy できるから、必要となる時に、GCE インスタンスを作って、GitHub 上のプライベートリポジトリのソースをインスタンスで動かすという要望はありました。

Terraform バージョン: 

* Terraform v0.12.28
* provider.google v3.5.0

## GitHub アカウントの SSH 秘密鍵
[GitHub Docs](https://docs.github.com/ja/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent)を参照して、パスフレーズなしの SSH 秘密鍵を作ります。そして、作成した公開鍵（id_rsa.pub）は GitHub アカウントへ追加します。
秘密鍵（id_rsa）は Terraform で GCS バケットの作成とともに、バケットにアップロードします。

## Cloud Storage バケット
```terraform:gcs.tf

# GitHub 秘密鍵を格納するバケット
resource "google_storage_bucket" "github" {
  name          = var.gcp_bucket_github
  location      = var.gcp_region
  force_destroy = true
  storage_class = "STANDARD"
}

# GitHub 秘密鍵
resource "google_storage_bucket_object" "github-id-rsa" {
  name   = "github-id-rsa"
  source = "./id-rsa"
  bucket = google_storage_bucket.github.name
}
```


## Compute Engine インスタンス
```terraform:gce.tf
resource "google_compute_instance" "demo" {
  name         = "demo"
  machine_type = var.gcp_instance_type
  zone         = var.gcp_zone

  tags = ["demo"]

  boot_disk {
    initialize_params {
      image = "projects/debian-cloud/global/images/family/debian-10"
    }
  }

  network_interface {
    network    = google_compute_network.gcp-network.name
    subnetwork = google_compute_subnetwork.gcp-subnet.name

    // 省略不可
    access_config {
    }
  }

  metadata = {
    startup-script = templatefile("./gce_init.sh",
      {
        bucket_github   = google_storage_bucket.github.name
        id_rsa          = google_storage_bucket_object.github-id-rsa.name
    })
  }

  service_account {
    scopes = ["storage-ro"]
  }

  depends_on = [google_storage_bucket_object.github-id-rsa]
}
```

### templatefile 関数
templatefile 関数を使って、「gce_init.sh」にバケット名とファイル名をパラメータで渡します。

```shell:gce_init.sh
#! /bin/bash

apt update
apt install -y git-all

# GitHub の秘密鍵(id_rsa) を GCS からダウンロードする
#echo gsutil cp gs://${bucket_github}/${id_rsa} id_rsa
gsutil cp gs://${bucket_github}/${id_rsa} id_rsa

chmod 400 /id_rsa
GIT_SSH_COMMAND='ssh -i /id_rsa -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no' git clone git@github.com:username/hoge.git

```

[templatefile - Functions](https://www.terraform.io/docs/configuration/functions/templatefile.html) により、Terraform 0.12 からは追加されました。Terraform 0.11 までは [template_file data source](https://www.terraform.io/docs/providers/template/d/file.html)を使うことになります。

### スコープ

インスタンスから GCS バケットアクセス（read）できるように、「storage-ro」と設定します。ほかのスコープは [gcloud compute instances create  |  Google Cloud](https://cloud.google.com/sdk/gcloud/reference/compute/instances/create?hl=ja#--scopes)を参照してください。
python3エンジニア認定基礎試験を受験した感想と試験対策について



## はじめに
先月python3エンジニア認定基礎試験を受験し、認定証が届いたので感想と試験対策に関して記載しようと思います。
これから受験しようと思っている方の参考になれば幸いです。

## どんな試験か
名前の通りpython3の基本知識を問う試験です。
下記に出題範囲等記載があります。
https://www.pythonic-exam.com/exam/basic

問題はオライリー・ジャパン「Pythonチュートリアル 第3版」から出題されますが、下記リンク先の内容とほぼ一緒なので買わなくても大丈夫です。
紙での資料が欲しい人だけ買えばいいと思います。
https://docs.python.org/ja/3/tutorial/

## 試験対策
試験対策ですが、正直Pythonチュートリアルがお世辞にもわかりやすいとはいえなかったため、まずはpaizaラーニングのpython入門編で勉強しました。
https://paiza.jp/

python入門編は全編無料で視聴できるため(2020年5月時点)、プログラミング経験のない人にもおすすめです。
1レッスンあたり5分前後で区切られているため、まとまった時間を取らなくても隙間の時間で見れるので忙しい時でもコツコツと進めることができます。

paizaラーニングで学習した後は、paizaのスキルチェック問題で実際にコードを書いて、文法の知識の定着を図りました。
Dランク、Cランクあたりの問題を何問か解けば基本的な文法は頭に入ると思います。

ある程度pythonでコードが書けるようになってから、Pythonチュートリアルを出題範囲の比率が高い個所を中心に読み込みました。
テキストに出てくるコードの実行結果が理解できるようになることと、ちょこちょこ出てくる用語の意味を抑えるようにしました。

テキストを何回か周回した後は下記サイトで模擬試験を受験しました。
https://exam.diveintocode.jp/exam

ランダムで40問出題されますが、5回もやれば見たことない問題はない、という感じなので問題の数はそこまで多くありません。
本番の試験は模擬試験よりも難しいです。
この模擬試験では900点以上を安定して取れるようにしておいた方がいいです。

## 感想
結果は740/1000で結構ギリギリの合格でした。(700点以上で合格)
試験時間は1時間ですが、ゆっくりやってじっくり見直しをしても40分ほどで終わります。

テキストは結構読み込んだつもりでしたが、こんなこと書いてあったっけ？ というようなことがあったので索引のキーワードの意味をちゃんと理解できてるかとか確認すればよかったかなぁと思いました。

正直取得したところで大きなメリットがあるような資格ではありませんが、それでも届いた認定証を見てうれしくなりました。(認定証しょぼいなぁ、とも思いましたが)
勉強したことがはっきりと目に見える形になるというのはやっぱいいですね。

今後業務で使う機会があるかはわかりませんが、プライベートではpythonをメインに使っていきたいのでいい勉強になったかなーと思います。

年内にはデータ分析試験の方も取りたいですね。
では、ここまで読んでくださってありがとうございました。
駆け出しエンジニアのスタートライン

<h2>ごあいさつ</h2>
はじめまして。
エンジニアへの転向を目指している、いちかわと申します。

今回が初めての投稿になりますので、下の三つのことについて、
お話させていただきます。
<ol>
<li>簡単な自己紹介
<li>エンジニアになりたいと思ったきっかけ
<li>Qiitaをはじめるに至った経緯
</ol>



（今回の記事は、問題解決といったテクニカルな内容を含みません。あらかじめご了承ください。）

<h2>自己紹介</h2>


名前：いちかわ（本名ではございません）
出身：私立大学・大学院の化学専攻
前職：電気・化学メーカー研究職
プログラミング経験：ほとんどございません

学生の頃は、プログラミングとはまったく関係のない、化学を専攻していました。
当時はケイ素という元素に魅せられて、夜遅くまでフラスコを振り続ける毎日をすごし、
ケイ素科学界の最右翼だったフランスの研究所へ留学するなど、
しあわせなケイ素ライフを送っておりました。

卒業後も、ケイ素と関わりをもつことができる企業さんに入社することができ、
「ケイ素とともにお墓に入るんだ」というこころづもりでお仕事を学んでおりました。
<br>
しかし、入社してわずか３ヶ月で私は退職を決意しました。
環境が悪かったわけではなく、やりたい仕事がやれなかったわけでもなく、
ただ、エンジニアになりたいという理由でした。
これまで会社が私に対して行った時間とお金の投資は、決して安いものではありません。
それを還元する前にやめてしまったので、申し訳ないと思う気持ちがまだ残っています。
一方で、絶対にエンジニアになってやるという気持ちが固まりました。



<h2>エンジニアになりたいと思ったきっかけ</h2>

一番大きなきっかけは、<b>IT分野特有の時間の流れ方</b> を意識したことです。

入社してすぐ、「化学研究者としての今後の人生を歩むとしたら、
一体どれだけの時代の変化を体感することになるんだろう」と考えました。

化学分野では、製造プロセスや生産コスト、安全性を考える必要があるため、
ものを世に出すまでには、どうしても多くの時間がかかってしまいます。
特に基礎研究となれば、10年や20年と言った長い時間が必要になりますので、
業界を大きく揺さぶるほどの変化は、頻繁には起こりません。

一方IT業界では、今はまだ誕生していないサービスが、
10年後には、なくてはならない必需品になっている可能性もあります。
そんな凄まじいスピードで移り変わるIT業界は、
私にはとてもキラキラして見えました。
この頃、「ケイ素から一旦離れてみるのも良いのかな？」と考えはじめました。

（こういったこと考えるようになったのは、
前職の研修中で行ったPythonのシュミレーションに触れたことがきっかけです。
思い返してみると、私にとっての大きな出会いだったように思います。）

<br>

漠然としたイメージを抱えたまま、私はまず情報収集をはじめました。
インターネットや本・YouTubeなどから情報を集めて、
同時にオンラインのプログラミング学習サイトでの勉強をスタートしました。
そして、色んなことを学んでいくうちに、自分の興味のあるキーワードが見えてきました。


<ul>
<li>チームでの開発
<li>WEBアプリケーション
<li>ゲームプログラミング
<li>グロースハック
<li>機械学習
<li>ケモインフォマティクス
</ul>

この６つのキーワードに私は魅力を感じていることがわかりました。
学生時代、ゲーム制作を行った経験がありますが、
用意されたスクリプトの変数の値を書きかえるだけで、
自分でしっかりとしたスクリプトを書いたことは、ほとんどありませんでした。
また、機械学習については高度な数学の専門知識が必要なので、
プログラミング初学者にはハードルが高すぎるという印象を受けました。
<br>
ここであげた６つのキーワードは、今の私にはハードルの高いものばかりですが、
どれも自分が関わってみたいと感じた夢のキーワードです。
そして、私が最初に魅力に感じていたIT分野特有の時間の流れを、
直接、体感できるような環境がそこにはあると思いました。


<h2>Qiitaをはじめるに至った経緯</h2>

私がQiitaをはじめた理由は、次の２つです。

一つめは、<b>「プロのエンジニアの意見に触れるため」</b>です。
自分勝手なプログラムを書かないようにするために、
自分の考え方を、なるべく多くの人の目に触れさせて、
貴重なフィードバックをいただける機会を持とうと思いました。


二つめは、<b>「学習の効率を上げるため」</b>です。
プログラミングを学ぶ中で解決できたことと、反省したことを記録して、
いつでも次に活かせる状態にしたいと思いました。
最初は質の低い投稿しかできませんが、将来見返したときに、
「この頃に比べたら成長できてる！」と実感できると思います。
そして将来の自分が、高いモチベーションを維持して、
楽しくプログラミングをできていたらいいなと思っています。
<br>
自分の考えをきちんとまとめながら、
積極的に情報発信をしていきたいと思います！


<h2>おわりに</h2>
今後、Qiitaを通して、1週間に1度の頻度でアウトプットを重ねていきたいと思います。

まだまだ分からないことだらけで、右も左も分からない駆け出しですが、
これから先もご覧いただけましたら幸いです。

ここまで読んでいただき、どうもありがとうございました！
Azure botで質問をするGoのサンプルコード


## 公式

- https://docs.microsoft.com/ja-jp/azure/cognitive-services/qnamaker/quickstarts/publish-kb-go

## ソース

```golang
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"net/http"
	"strconv"
)

func main() {
	// Represents the various elements used to create HTTP request URIs
	// for QnA Maker operations.
	// From Publish Page: HOST
	// Example: https://YOUR-RESOURCE-NAME.azurewebsites.net/qnamaker
	var host string = "https://qa-bot-service.azurewebsites.net/qnamaker"

	// Authorization endpoint key
	// From Publish Page
	var endpoint_key string = "ffdbcf11-cxxxxxxxxxxxxxxxxxxxxxxxa"

	// Management APIs postpend the version to the route
	// From Publish Page, value after POST
	// Example: /knowledgebases/xxxxxxxxxxxxxxx/generateAnswer
	var route string = "/knowledgebases/xxxxxxxxxxxxxxxxxxxx/generateAnswer"

	// JSON format for passing question to service
	var question string = "{'question': 'パスワード','top': 3}"

	req, _ := http.NewRequest("POST", host+route, bytes.NewBuffer([]byte(question)))
	req.Header.Add("Authorization", "EndpointKey "+endpoint_key)
	req.Header.Add("Content-Type", "application/json")
	req.Header.Add("Content-Length", strconv.Itoa(len(question)))
	client := &http.Client{}
	response, err := client.Do(req)
	if err != nil {
		panic(err)
	}

	defer response.Body.Close()
	body, _ := ioutil.ReadAll(response.Body)

	fmt.Printf(string(body) + "\n")
}
```

## 実行

```bash

go run main.go
```
僕が考えた最強の React アーキテクチャ

![Untitled Diagram-Copy of Page-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244226/3095c796-8384-e122-b945-892ef371cbcc.png)

# Component

## Page

Container と Component を組み合わせてページを構成する

## Container, Component

Container → Container Components
Component → Presentational Components

![redux.js.org_basics_usage-with-react.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244226/19693bf0-8540-473f-637b-005ad4476764.png)

https://redux.js.org/basics/usage-with-react#presentational-and-container-components

# Store

## Action, Reducer, State, Selector

![vuex.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244226/621c7cb7-5dca-1c65-df3f-f48581b917cd.png)

https://vuex.vuejs.org/ja/

## Facade

https://ja.wikipedia.org/wiki/Facade_パターン

## Service

[CRUD](https://ja.wikipedia.org/wiki/CRUD#:~:text=CRUD%EF%BC%88%E3%82%AF%E3%83%A9%E3%83%83%E3%83%89%EF%BC%89%E3%81%A8%E3%81%AF%E3%80%81,%E7%94%A8%E8%AA%9E%E3%81%A8%E3%81%97%E3%81%A6%E3%82%82%E4%BD%BF%E3%82%8F%E3%82%8C%E3%82%8B%E3%80%82)
標準出力がコンソールか別のコマンドかによって、バッファリングやフラッシュの規則が異なる

# 環境

- ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-linux]
- Ubuntu 20.04 LTS (Focal Fossa) [Windows Subsystem for Linux 2; WSL2]

# 事象

Rubyで標準出力を利用する場合、標準出力の先がコンソールか別のコマンドかによって、バッファリング・フラッシュの規則が異なっているようです。

- 標準出力が別コマンドにつながっている場合、バッファリングする
- 標準出力がコンソールにつながっている場合、1行ごとにフラッシュする。

これを簡単に検証してみましょう。標準出力がコンソールにつながっている場合は`true`、コマンドにつながっている場合は`false`を標準出力に出力したあと、0から4までの数字を1秒おきに標準出力に出力するRubyコードです。

```rb:main.rb
puts "STDOUT.isatty = #{STDOUT.isatty}"
5.times do |x|
  sleep 1
  puts x
end
```

以下の`cmd.rb`と`console.rb`は`ruby main.rb`の標準出力をパイプまたはコンソールにつなげて実行し、出力した結果にタイムスタンプを付与します。

```rb:cmd.rb
require 'open3'

# 読み込み専用IOから1行づつ読み込み、タイムスタンプを付与して出力する。
puts '*** main.rbの標準出力が別コマンドにつながっている場合 ***'
Open3.popen3('ruby main.rb') do |stdin, stdout, stderr, wait_thr|
  stdout.each do |line|
    timestamp = Time.now.strftime('%F %T')
    puts "#{timestamp} #{line}"
  end
end
```

```rb:console.rb
require 'pty'

# 読み込み専用IOから1行づつ読み込み、タイムスタンプを付与して出力する。
puts '*** main.rbの標準出力がコンソールにつながっている場合 ***'
PTY.spawn('ruby main.rb') do |read, write, pid|
  read.each do |line|
    timestamp = Time.now.strftime('%F %T')
    puts "#{timestamp} #{line}"
  end
end
```

`cmd.rb`と`console.rb`の実行結果は以下の通りになります。

```
$ ruby cmd.rb 2>/dev/null
*** main.rbの標準出力が別コマンドにつながっている場合 ***
2020-07-05 16:45:09 STDOUT.isatty = false
2020-07-05 16:45:09 0
2020-07-05 16:45:09 1
2020-07-05 16:45:09 2
2020-07-05 16:45:09 3
2020-07-05 16:45:09 4
$ ruby console.rb 2>/dev/null
*** main.rbの標準出力がコンソールにつながっている場合 ***
2020-07-05 16:45:11 STDOUT.isatty = true
2020-07-05 16:45:12 0
2020-07-05 16:45:13 1
2020-07-05 16:45:14 2
2020-07-05 16:45:15 3
2020-07-05 16:45:16 4
```

タイムスタンプを見ると、標準出力がパイプにつながっている`main.rb`はバッファリングしていますが、コンソールにつながっている場合は、行ごとにフラッシュしていることがわかります。

# 標準出力がコマンドにつながっている場合でも、バッファリングしたくない

いろいろやり方はあるとは思いますが、とりあえず思いつくのはこのあたりでしょうか。

- `STDOUT.sync = true`を設定して、標準出力を同期モードにする
- `STDOUT.flush`を任意のタイミングで呼び出す。

前者について実験してみます。上記の`main.rb`を以下のように改造します。

```rb:main.rb
$stdout.sync = true
puts "STDOUT.isatty = #{STDOUT.isatty}"
5.times do |x|
  sleep 1
  puts x
end
```

`main.rb`の標準出力を別コマンドにつなげる`cmd.rb`を実行すると、さきほどとは違って、バッファリングしていないことがわかります。

```
$ ruby cmd.rb 2>/dev/null
*** main.rbの標準出力が別コマンドにつながっている場合 ***
2020-07-05 16:51:33 STDOUT.isatty = false
2020-07-05 16:51:34 0
2020-07-05 16:51:35 1
2020-07-05 16:51:36 2
2020-07-05 16:51:37 3
2020-07-05 16:51:38 4
```

# 標準出力がコンソールにつながっている場合でも、フラッシュしてほしくない

これについてもやりようはいろいろありそうですが、自分の思いつく範囲だと「`$stdout`を`StringIO`にリダイレクトし、任意のタイミングで`StringIO`にため込んだ内容を`STDOUT`に出力する」というものがあります。この場合、`main.rb`は以下のようになるはずです。

```rb:main.rb
require 'stringio'

StringIO.open do |io|
  # 標準出力をStringIOにリダイレクト
  $stdout = io

  # ここはもともとのmain.rbと同じ
  puts "STDOUT.isatty = #{STDOUT.isatty}"
  5.times do |x|
    sleep 1
    puts x
  end

  # StringIOにためた内容をSTDOUTに吐き出す
  $stdout = STDOUT
  io.rewind
  puts io.read
end
```

`console.rb`を実行して、`main.rb`がコンソールにつながっている場合の動きを確認すると、想定通りバッファリングしていることがわかります。

```
$ ruby console.rb 2>/dev/null
*** main.rbの標準出力がコンソールにつながっている場合 ***
2020-07-05 16:56:38 STDOUT.isatty = true
2020-07-05 16:56:38 0
2020-07-05 16:56:38 1
2020-07-05 16:56:38 2
2020-07-05 16:56:38 3
2020-07-05 16:56:38 4
```
Firebase Crashlyticsを効果的に使うお話

## 最初に

今回はユーザーさんからのクラッシュの問い合わせをCrashlyticsを使い
どうしたら素早くやバグを解決できるか考えてみました。
デバッグって大変ですよね。

導入自体については、公式のドキュメントをご確認ください。
https://firebase.google.com/docs/crashlytics?hl=ja

今回は、Android javaでのコードを記載しました。

## ユーザーID検索

ユーザーがログインした時などにユーザーの情報をセットしていくと、文字列をいれて送ることができます。

```java
Crashlytics.setUserIdentifier("userid-12345678910");
Crashlytics.setUserEmail("userid-email");
Crashlytics.setUserName("userid-name");
```

そうするとこれはクラッシュ詳細の「データ」のタブに表示されます。
この画像の右下あたりのユーザーの部分です。
<img width="1203" alt="スクリーンショット 2020-07-05 16.04.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30138/6ac98964-b87a-eb07-e5cd-3b29925e3909.png">


実はこの値TOPの右下の「ユーザー検索」から検索ができて検索してみると
Email,Name,Identiferどれも横断で部分一致で検索してくれます。
<img width="1208" alt="スクリーンショット 2020-07-05 16.06.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30138/54f5328a-6a12-d590-9f5c-cbfff0a5d466.png">

どのユーザーがどのクラッシュをしたかが特定できます。

## ログとキー
これを使うことにより、クラッシュする前にどの画面を経由したか？が分かります。

#### ログ
```java
// 各ActivityやFragmentでそれぞれ文字列を決めて、logにセットしていきます。
Crashlytics.log("******");
```

セットした値は、最終的にクラッシュしたクラッシュ詳細の「ログ」のタブに上から時系列順に並びます。
例えば以下は、1-aはAのActivity、2-bはBのActivityでCrashlytics.logを呼んでBでクラッシュさせたものです。
<img width="1172" alt="スクリーンショット 2020-07-05 16.15.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30138/b552eb6e-26ac-8541-9236-6a1a5e98e0cc.png">

そのため、どこの画面から遷移してクラッシュしたか？
クラッシュする前にどの画面を通ったか？などを確認することができます。

#### キー
```java
Crashlytics.setInt("1-a", 1);
Crashlytics.setBool("1-a", true);
Crashlytics.setDouble("1-a", 1);
Crashlytics.setFloat("1-a", 1);
Crashlytics.setLong("1-a", 1);
Crashlytics.setString("1-a", "1-a");
```

key/valueでデータをセットして送る事もできます。
クラッシュ詳細の「鍵」のタブに集計されます。（翻訳ミスってる説）
<img width="1170" alt="スクリーンショット 2020-07-05 16.24.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30138/28ce112b-f992-9ae7-9afe-8989485cd904.png">

こちらの上から順に並んでいきます。
そして便利なのが「キー」をフィルタしますの部分に文字入力すると、そのキーのみの一覧表示ができます。
このログとキーについては、よく考えて設計すると、デバッグにかなり効果を発揮しそうです。

## 非重大
想定されるExceptionが起こった時、それをそのまま渡して集計ができます。
「クラッシュ」ではなく「非重大」の方にまとまります。

```java
Crashlytics.logException(Exception);
// 自分でExceptionのインスタンスを作って渡す事もできます。
Crashlytics.logException(
  new IllegalArgumentException("IllegalArgumentExceptionのテストです")
);
```

こっちは、左上の「フィルタ」をクリックして非重大に切り替えて確認しましょう。
こちら上に記載したユーザー情報を入れる、ログやキーを入れる
をしておくと非重大の方の詳細にも同じように反映されます。
本棚で考えるJavascriptの配列操作

javascriptのオブジェクトを本棚に見立てて
色々操作してみる。

```javascript

const books = {
    novel: {
      name: ['火花', '赤毛のアン', '星の王子様']
    },

    comic: {
      name: ['鬼滅の刃', 'ONE PIECE', 'キングダム']
    },

    business: {
      name: ['7つの週間', 'サピエンス全史', '自助論']
    },

    philosophy: {
      name: ['方法序説', '死に至る病', 'ニコマコス倫理学']
    },

    biography: {
      name: ['フランクリン自伝', '果てなき野望', 'マイ・ストーリー']
    },

    favorite: {
      name: ['FACTFULLNESS', '蹴りたい背中', '恋は雨上がりのように']
    },
}

console.log(books);

```

## Q1
新しく**進撃の巨人**を買ったので本棚に追加する

- comicに進撃の巨人を追加(先頭に)

## A

```javascript
books.comic.name.unshift('進撃の巨人');
```
ちなみに末尾に追加するにはpush

## Q2
**7つの習慣**を読みたくなってきた

- 7つの習慣を取り出す
- **「7つの習慣を読み終わりました」**と出力する
- businessの棚の一番最後に戻す。


## A

```js
const choose = books.business.name.shift();
console.log(choose + 'を読み終わりました');
books.business.name.push(choose);
console.log(books);
```

7つの習慣を読み終わりましたと出力された後に
business.nameの配列の最後に7つの週間が追加されていればOK



## Q3
**「赤毛のアン」**がとても面白かったのでお気に入りの棚に追加しようと思ったが、お気に入りの棚がもういっぱいで本が入らない！

仕方ないので、**「恋は雨上がりのように」**は漫画の棚に移動する

- 赤毛のアンを取り出す
- 恋は雨上がりのようにを取り出す
- 赤毛のアンをfavoriteに追加
- 恋は雨上がりのようにcomicに追加

## A

```js
const read = books.novel.name.splice(1, 1);

console.log(read + 'を読みました')

//読んだ後にパンパンだと気づく

const move = books.favorite.name.pop();

books.comic.name.push(move);
books.favorite.name.push(read);

console.log(books);
```

- novelが2つになって
- comicに恋は雨上がりのようにが追加されて
- favoriteに赤毛のアンが追加
 
されてればOK
windowsから、WSL上のサービスへアクセスする

# tl;dr
WSL（またはWSL2）内で動作するサービスへのアクセス方法です。
`localhost`を使用することで簡単にアクセスできます。
ただし、`127.0.0.1`ではアクセスできません。

# WSL内のサービスを立ち上げる
ここでは、node+expressのテンプレートを使い、httpサーバーを起動させます。
※WSLに`nodejs`と`git`がインストールされている必要があります。

WSLを開き、以下のコマンドを実行し、httpサービスを起動させます。

```
$ git clone https://github.com/quzq/play_express.git --depth 1
$ cd play_express
$ npm i
$ npm start
```
成功すると、以下のように出力されます。

```
Listening on port 3000
```

# Power Shell からアクセス
Windows Power Shell を起動し、上記のサービスへアクセスします。

```
PS > curl http://localhost:3000
```
httpサービスのページを取得できました。

```
StatusCode        : 200
StatusDescription : OK
Content           : <!DOCTYPE html><html><head><title>Express</title><link rel="stylesheet" href="/stylesheets/style.cs
                    s"></head><body><h1>Express</h1><p>Welcome to Express</p></body></html>
RawContent        : HTTP/1.1 200 OK
                    Connection: keep-alive
                    Content-Length: 170
                    Content-Type: text/html; charset=utf-8
                    Date: Fri, 03 Jul 2020 07:18:31 GMT
                    ETag: W/"aa-z+ebXSEdArbZ+EXlN/WQjf6HV8c"
                    X-Powered-By: Expre...
Forms             : {}
Headers           : {[Connection, keep-alive], [Content-Length, 170], [Content-Type, text/html; charset=utf-8], [Date,
                    Fri, 03 Jul 2020 07:18:31 GMT]...}
Images            : {}
InputFields       : {}
Links             : {}
ParsedHtml        : mshtml.HTMLDocumentClass
RawContentLength  : 170
```

# webブラウザからアクセス
適当なwebブラウザに、`http://localhost:3000`を指定してアクセスします。

以下のようなページが表示されました。
![express.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395902/f8c90fd4-f80f-8870-6aad-c558bf5d0466.png)

# その他
インスタンスの違う複数のWSL上で同一ポートのサービスを起動した場合、その内の１つのサービスにのみアクセスできました。どういう優先順になっているのかはわかりませんでした。

以上。
UserDefaultsに配列を追加・リセットする

~~端末にデータを保存するにはUserDefaultsを使います。~~その中でもよく使う配列についてまとめます。
追記：端末にデータを保存することはUserDefaultsの本来の意図ではないようです。ご指摘感謝いたします。


##データを追加する
データを保存するためにはUserDefaultsからKeyを指定して呼び出す必要があります。
呼び出した後は配列の操作と同じなので、`append`や`insert`を用いて追加しましょう。(`insert`を使うことで新しいデータが先頭に保存されます。)
呼び出した配列に値を追加した後は、Key(呼び出したものと同じ)を指定して`set`します。

```Swift
var userDefaults = UserDefaults.standard
var passwordArray = self.userDefaults.array(forKey: "password") as? [String] ?? []
passwordArray.insert(self.roomNameTextField.text!, at: 0)
self.userDefaults.set(passwordArra, forKey: "password")
```
##データをリセットする

```Swift
var userDefaults = UserDefaults.standard
userDefaults.removeObject(forKey: "password")
```
GCPでgitするやり方

#1.目的
最近Gitを学習しているが、Git BashとGit Hubのみ使っている。

GCP（Google Cloud Platform）もBigQueryがメインではあるものの最近使い始め、GSR（Google Source Repositry）も使えるようになりたいと思い、基本的なコマンドを調べて実践してみた。

その際に備忘録用のメモ。
バージョンアップしていきたい。

#2.GSRを使ってみる

##(1)リポジトリの作成
GSRからリポジトリを作成しておく。
新しいリポジトリの作成→続行をクリック

<img width="815" alt="キャプチャ1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465870/092f1bb8-d216-b8ed-cdce-6199423ee1ce.png">

リポジトリ名を設定する。今回はremote-repo2。

プロジェクトは、クリックすると自分のプロジェクトがプルダウンで選択できるので適当なプロジェクトをクリックする。

<img width="533" alt="キャプチャ2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465870/ce241958-ad1c-45be-ea1a-2b3a8ca27ba3.png">


すると下記の様な画面になるので、赤枠のようにGoogle Cloud SDKをクリックする。

<img width="588" alt="キャプチャ3.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465870/73e20239-c6a9-e1c0-e2f1-b4448bfbf08d.png">

打てばいいコマンドが出てくるので、テキストエディタ等にコピペしておくとうっかり画面を閉じても安心。

<img width="513" alt="キャプチャ4.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465870/5ec0c5b7-0773-b20d-04d9-58273b112760.png">

##(2)初期設定

Home画面の下記赤枠から、cloud shellを立ち上げる。
<img width="639" alt="キャプチャ5.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465870/5b6da4e8-afd2-6d2a-9f73-2a1f206b3077.png">

立ち上げたcloud shellから、自分のIDとメールアドレスを設定する
※●●●●や××××は自分の情報を入力する。

```
$ git config --global user.name ●●●●
$ git config --global user.email ××××
```

下記コマンドで、各種設定をする。（質問が何点か聞かれるので答えていく）

```
$ gcloud init
```

##(3)コミット用ファイルの作成
コミットする用のファイルを作っておく。

```
$ echo "hello git" > hello.txt
```

##(4)リポジトリをクローンする

(1)で作成したリポジトリをクローンしてくる。
コマンドは、(1)の最後のキャプチャの「3.ローカルGitリポジトリにこのリポジトリのクローンを作成します」をそのままコピペでOK

```
$ gcloud source repos clone remote-repo2 --project = ●●●● 
```

##(5)add,commit,push

```
$ git add hello.txt
$ git commit -m 'first-repo'
$ git push -u origin master
```

ここまでいって、GCPのGSRを更新するとremote-repo2にhello.txtが追加されている。

今回はここまで。
徐々にバージョンアップさせていきます！
gem installでパーミッションがないと警告された時の対処


Jekyllとbundler gemsをインストールしたくて以下のコマンドをターミナルで打つと

```
$ gem install jekyll bundler
```

パーミンションが書かれていないと怒られました。

```
You don't have write permissions for the /Library/Ruby/Gems/2.6.0 directory
```

## 解決策

sudoをつける

```
$ sudo gem install jekyll bundler
```

deal
![akusyu_hand_naked.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315096/1f4f395b-e952-f3b2-c525-8eace9706897.png)
GitでSSHのパスフレーズ入力を省略する方法

## やりたいこと

ED25519鍵で Git push などを行うと以下のようにSSHのパスフレーズを要求されてしまう。

```
$ git push origin name_of_branch
Enter passphrase for key '/Users/[user_name]/.ssh/id_ed25519':
```

毎回聞要求されるのはしんどいので、要求されないようにする。

## 解決策

`ssh-add` でSSH鍵を`ssh-agent`に登録する

```
$ ssh-add /Users/[user_name]/.ssh/id_ed25519

Enter passphrase for /Users/[user_name]/.ssh/id_ed25519: <- SSHのパスフレーズを入力
Identity added: /Users/[user_name]/.ssh/id_ed25519 (<作成時に入力したコメント>)
```

登録されていることを確認する

```
$ ssh-add -l
```

`~/.ssh/config` にSSH Keyのパスフレーズを記憶するように設定する。
Macのみ、以下の設定が可能。

```
# common
Host *
 UseKeychain yes
 AddKeysToAgent yes
```

これで、毎回聞かれることはなくなりました。

## 参考
- [ssh-agentとssh configの設定方法 git push時に Permission denied (publickey). エラー](https://kiraba.jp/ssh-agent-and-ssh-config-setting/)
- [GitのSSH鍵認証で毎回パスワードを要求される](https://qiita.com/shinki_uei/items/70f8f9ae50f1b9e24dce)
- [macOS Sierra の SSH で、秘密鍵のパスフレーズが Keychain 保存されない問題の解決方法](https://h2ham.net/macos-sierra-use-keychain/)
macOSのターミナルからVisual Studio Codeを扱えるようにする方法

## 前提条件
OSバージョン: macOS Mojave Version 10.14.6
Visual Studio Codeバージョン: 1.46.1
Visual Studio Codeがインストール済みであること

## 方法

1. Visual Studio Codeを開き、コマンドパレットをショートカットキー 「⇧ + ⌘ + P 」で開く
2. shell command と入力して、シェルコマンドを検索、「code」コマンドをインストール(=codeコマンドのパスを通す)
<img width="825" alt="Screen Shot 2020-07-05 at 15.50.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668194/1283d1fe-c4b3-1683-561a-c0cd9e791c82.png">
3. macOSのターミナルを再立ち上げすることでPATHを有効化します。PATHが通ってcodeコマンドが使えるようになったかどうかの確認は、以下のようにしてヘルプが表示されるか確認することで可能です。<img width="809" alt="Screen Shot 2020-07-05 at 15.57.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668194/c26dc946-9042-ce25-c9ba-5e15beb5a909.png">
4. 例えばバージョンの確認はこのようにやるとできます。<img width="809" alt="Screen Shot 2020-07-05 at 16.00.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668194/8afbb08b-a7ec-2baf-5344-f89f8b1ba6df.png">




## 

## 参考リンク

Command Line Interface (CLI)
https://code.visualstudio.com/docs/editor/command-line
記事を移行しました

はてぶ、note、qiitaなどなど、色んな所に自分の記事を書き散らかしてるので一箇所にまとめることにしました。

qiitaの記事も徐々に移行しているので、記事がなくなってたらそういうことだと思ってください。

移行先のサイトはプロフィールの自分のwebサイトみたいな項目に入れておきます。
Django-TodoList②~詳細ページを表示してみよう~

#はじめに
今回の記事では「TodoList」の詳細ページを表示していこうと思います。
対象者としては、Djangoの学習を始めたばかりの人を考えています。
前回までの記事にも目を通していただけるとスムーズに進められると思います。

前回までの記事
↓
↓
↓
[PycharmでDjangoでアプリケーションを作成する手順~準備編~](https://qiita.com/heku_777/items/0951bb1da7b664affbfb)

[Django~settings.py編~](https://qiita.com/heku_777/items/0962d426d967c4c0b016)

[Django~ブラウザに表示させてみよう~](https://qiita.com/heku_777/items/302ba92db3e3a1d3cfef)

[Django-TodoList①~一覧を表示してみよう~](https://qiita.com/heku_777/items/ea9d8e3a478af7226a46)

#urls.pyの編集

まずは'urls.py'にURLの繋ぎ込みを行っていきます。
アプリケーションの'urls.py'を開いてください。
（デフォルトでは用意されていないので作成していない方は、ターミナルに次のように打ち込んでください。）

```terminal
#アプリケーションディレクトリに移動
$ cd アプリケーション名        #今回は「todo」

#urls.pyの作成
$ touch urls.py
```

'urls.py'を開いたら(作成できたら)、次のように追記してください。

```python
from django.urls import path
from .views import TodoList, TodoDetail

urlpatterns = [
    path('list/', TodoList.as_view()),
    path('detail/<int:pk>/', TodoDetail.as_view()),   #詳細画面の繋ぎ込み
]
```
'int:pk'とは、どのデータを表示するのか指定するものです。
あとで実際に入力しますが、URLの末尾に'detail/1/'と付け足すことで、１つ目のデータが表示されます。
ちなみに管理画面で一つ一つのデータの詳細を見ると、URL部分nの末尾に数字が表示されているのを確認できます。

'TodoDetail.as_view'は’view.py’にある'TodoDetailクラスを持ってくると思ってもらえたら良いです。

#view.pyの編集
次に'view.py'を編集していきます。

```python
from django.shortcuts import render
from django.views.generic import ListView, DetailView   #DetailViewをインポート
from .models import TodoModel


class TodoList(ListView):
    template_name = 'list.html'
    model = TodoModel


class TodoDetail(DetailView):        #TodoDetailクラスを定義
    template_name = 'detail.html'    #'template'は'detail.html'を指定
    model = TodoModel                #モデルは'TodoModel'を指定
```
前回の記事でも説明した通り、'views.py'は材料を集めるために動くものなので、'tempalte'とモデルの指定を行っています。

#models.pyの編集
前回作成した'models.py'から少し変更を加えるので、次のように追記してください。

```python
from django.db import models
from django.utils import timezone


class TodoModel(models.Model):
    title = models.CharField(max_length=50)
    content = models.TextField()
    deadline = models.DateTimeField(default=timezone.now)
```
これで編集は完了です。

#表示
それでは早速表示できているか確認していきましょう。

ターミナルに次のように打ち込んでください。

```terminal
$ python manage.py runserver
```
URLが表示されるのでそれをクリックするとブラウザに飛びます。
ブラウザに飛んだら、URLの末尾に'detal/1/'と付け足してください。

そうすると一番最初に登録したデータの中身が表示されているのが確認できるはずです。

#終わりに

今回は一つ一つのデータの詳細画面を表示することをしました。
今後も記事を追加していくので、参考にしていただければ幸いです。
「SSHのパスフレーズ忘れた！！」からのGitLabに公開鍵を再登録するまでの話

暫くぶりにプライベートで使用しているGit リポジトリを触る時間を作れたので、  
Git pushしてみたら

```
Enter passphrase for key '/Users/reinayamaguchi/.ssh/id_rsa':
```
って問われて、「はて？？？　パスフレーズどこ行った？？」となり、  
仕方ないので、今までのSSH鍵さんにサヨナラして新しい鍵を作成することになった。

という、情けない経験からの覚書です。

## Step 1 - SSH KEY の削除
1. ターミナルで「.ssh」のディレクトリに移動

```
$ cd ~/.ssh
```

2. ファイルを確認

```
$ ls -l

-rw-r--r--@ 1 [user_name]  staff   192 Sep  9  2018 config
-rw-------@ 1 [user_name]  staff  1766 Sep  4  2018 id_rsa
-rw-r--r--@ 1 [user_name]  staff   401 Sep  4  2018 id_rsa.pub
-rw-r--r--@ 1 [user_name]  staff   383 Jun 28 17:35 known_hosts
```

3.「id_rsa」「id_rsa.pub」を削除し`ls -l`で確認

```
$ rm id_rsa id_rsa.pub

$ ls -l

-rw-r--r--@ 1 [user_name]  staff  192 Sep  9  2018 config
-rw-r--r--@ 1 [user_name]  staff  383 Jun 28 17:35 known_hosts

```

## Step 2 - SSH公開鍵を作成

GitLabでは「ED25519」「RSA」を推奨している。
作成方法は[Generating a new SSH key pair](https://gitlab.com/help/ssh/README#generating-a-new-ssh-key-pair)で解説している。

どっちを採用しようかと思ったところ、
[SSH は (RSA 鍵より) ED25519 鍵の方が強固で速い](https://sig9.hatenablog.com/entry/2020/01/11/000000)ということ記事で
「ED25519 の方が RSA よりも強度が高く、しかも速いです。」と記されていたので「ED25519」で作成することにした。

1. key作成コマンドでkeyの作成。`-C`フラグでメールアドレスなどのコメントを入れられる。`-C`フラグなしでも作成できる。

```
$ ssh-keygen -t ed25519 -C "<comment>"
```

2.以下のコメントが表示される

```
Generating public/private ed25519 key pair.　
Enter file in which to save the key (/home/user/.ssh/id_ed25519):
```

なにも入力せずに［Enter］キー押下すると、
パスフレーズの入力を求められるので確認含め２回入力する

```
Enter passphrase (empty for no passphrase): <- 好きなパスワードを入力
Enter same passphrase again: <- 確認のためにもう一度入力
```


3. 以下が表示されてSSH Keyが作成される


```
Your identification has been saved in /Users/[user_name]/.ssh/id_ed25519.　
Your public key has been saved in /Users/[user_name]/.ssh/id_ed25519.pub.  
The key fingerprint is:
SHA256:t4XcnCqRp6cGxy81cR3zyJiurATJ1UBOfv5LEUCn7wY <comment>
```

- 公開鍵：id_ed25519.pub　<- 公開鍵、GitLab（Bitbucket/GitHub）に渡す
- 秘密鍵：id_ed25519　<- 秘密鍵、他人には見られないようにする

4.他の人が秘密鍵・公開鍵を観覧できないようにパーミッションを変更する。

```
$ chmod 600 id_ed25519

$ chmod 600 id_ed25519.pub
```

## Step3 GitLabに公開鍵を登録する

1.公開鍵をコピーする

```
$ pbcopy < ~/.ssh/id_ed25519.pub
```

2.GitLabの「ユーザー設定」→　「SSH Keys」に移動し公開鍵を登録する。

## Step4　「クライアント側」 ~/.ssh/config にSSH Keyを設定する

`~/.ssh/config`を開く。

```
$ vim ~/.ssh/config
```

前回、SSH鍵を作成してGitLab登録したときに以下を追記してあるので、秘密鍵のファイル名を変更した。

```
# GitLab.com
Host gitlab.com
  User <User Name> <- GitLabで使用しているユーザー名
  HostName gitlab.com
  TCPKeepAlive yes <- IdentityFileを利用する場合。yesを指定
  identitiesonly yes <- 持続的接続のこと。yesを指定
  identityFile ~/.ssh/id_ed25519 <- [id_rsa]を[id_ed25519]に差し替え
```

以上で、git pull , git push　ができるようになった！

## 参考サイト
- [GitLab - GitLab and SSH keys](https://docs.gitlab.com/ee/ssh/)
- [GitLab - Options for SSH keys](https://gitlab.com/help/ssh/README#generating-a-new-ssh-key-pair)
- [GitLab - Adding an SSH key to your GitLab account](https://gitlab.com/help/ssh/README#adding-an-ssh-key-to-your-gitlab-account)
- [【GitLab】SSH Key忘れた。。リセットしょ。。の方法](https://t-hsn.com/tech/201907/gitlab-sshkey/)
- [SSH は (RSA 鍵より) ED25519 鍵の方が強固で速い](https://sig9.hatenablog.com/entry/2020/01/11/000000)
- [SSH認証キーをGitLabに登録・設定手順 覚書(Qiita)](https://qiita.com/redamoon/items/07e445d1fce360cb5fa3)
bash / .bash_profile / .bashrcについて「とりあえず」部分を理解する


#この記事の目的
**bash、.bashrc、.bash_profileについて「とりあえず」理解すること。**

環境構築時に、「.bashrc」と「.bash_profile」というファイルを訳も分からず編集しました。

訳もわからないまま突き進むといつかきっとドツボにハマるので、個人的に「ひとまずこれだけ分かれば良いかしら？」という部分をまとめました。

#まずは、bashとは？

**shellの種類の一つで、shのパワーアップ版のこと。**


##shellって？
**ユーザーがOSカーネルへ指示を出すために使う、CLI（Command Line Interface)のソフトウェア。**

「shell」は上記に挙げた機能をもつソフトウェア全般のことを指し、実際に私たちが使用する「shell」には、いくつか種類があるようです。

##shellには、2流派+1がある

「+1」というのは、2つの流派の両方の特徴を備えたshellのこと。具体的には、**zsh**がそれに当たります。

流派が同じだと、コマンドや機能も似ていることが多いようです。

###shellの種類
- sh系
    - sh
        - もっとも基本的なshell
        - 他のsh系shellの元
    - bash
        - shの後継
        - GNUプロジェクトの一部で、オープンソースソフトウェア
        - **Linuxディストリビューションの多くで標準shellとして同包されている**
        - Macでは、**Catalinaより前にログインshellとして使われていた**
    - ksh
        - 多くの**UNIX系OSで標準的に用いられているshellの一つ**
        - cshの機能を多く取り入れている
- csh系
    - csh
        - BSD系UNIXの一つである2BSDを利用するためのshell
        - 対話的に利用する際に便利な機能が多数ある
    - tcsh
        - cshのパワーアップ版
        - 特にユーザーインターフェイスの部分を中心に拡張された
- zsh
    - sh系とcsh系の良いとことを採用して作られたshell
    - Macでは**Catalinaから、ログインshellにzshを採用**

よく耳にするのは**bash**と**zsh**かな。


###...私が使っているshellは何だろう？
自分のshellの種類がわからないときは、このコマンドで確認できる。

- `echo "$SHELL"`：現在のshell
- `cat /etc/shells`：システムにインストールされているshell一覧

その他shell情報を確認するコマンドは、こちらの[マイナビニュースの記事](https://news.mynavi.jp/article/20181121-727279/)が参考になりそうです。


#`.bash_profile`と`.bashrc`は実行タイミングが違う
`.bash_profile`と`.bashrc`は、どちらもbashの設定です。
では、具体的にどう違うのか？
[man bash](http://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbAH) と [Bash入門](https://bash.open-code.club/%E3%82%B7%E3%82%A7%E3%83%AB%E3%81%AF%E3%81%84%E3%81%8F%E3%81%A4%E3%82%82%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B.html)を参考にして、2つ説明を要約すると、こんな感じです。

- `.bash_profile`
    - 対話的（コマンド入力によって起動）なログインシェルまたは、`--login`オプション付きの非対話的シェルとしてbashが起動された時に呼ばれる
    - 実行順番は、`/etc/profile`→`~/.bash_profile`→ `~/.bash_login`→`~/.profile`
    - ログアウト時に`~/.bash_logout`があればこれも実行
- `.bashrc`
    - ログインシェルではない非対話型（shell script実行時など）起動の時に実行される

特に重要そうなポイントとして、「**`.bash_profile`はログイン時の1回だけ呼び出される**」、「**`.bashrc`はshell起動のたびに呼び出される**」と覚えてればいいのかなと思いました。


##結局、どう使うのか
[Linux: .bashrcと.bash_profileの違いを今度こそ理解する](https://techracho.bpsinc.jp/hachi8833/2019_06_06/66396)から引用させていただくと、結論はこうです。

>そこまで厳密に書かなくても動くのが設定ファイルですし、書き方は人それぞれになると思います。

>しかし、少なくとも~/.bashrcで何も出力してはならない、という部分は外さないようにする必要があります。

とりあえずはシンプルに、こう覚えておきましょう。

- `.bash_profile`
    - ログイン時に必ず呼ばれるので、出来るだけ余計なものは書かない
    - `.bashrc`はここで読み込む

- `.bashrc`
    - 出力されるようなものは書かない
    - 書くなら、例えばエイリアスやコマンドライン補完の設定
    - `.bash_profile`に、`.bashrc`を呼び出す処理を書く必要がある
    
```
sample -r ~/.bashrc && . ~/.bashrc
```

#まとめ: bashはshell。`.bashrc`に出力のある設定を書かなければ一旦はOK

記事によって結論が様々で何が正解なのかわからなかったのですが、「設定ファイルなので、書き方は人の好みによる」という答えで納得しました。

（もし記事中に間違いがあったらコメントいただけると大変ありがたいです...！）

#参考サイト

- [「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word11274.html)
- [Linux: .bashrcと.bash_profileの違いを今度こそ理解する](https://techracho.bpsinc.jp/hachi8833/2019_06_06/66396)
- [man bash](http://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html#lbAH)
- [bash入門](https://bash.open-code.club/%E3%82%B7%E3%82%A7%E3%83%AB%E3%81%AF%E3%81%84%E3%81%8F%E3%81%A4%E3%82%82%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B.html)
初回起動時のみ画面遷移する方法

備忘録。ログインしていない状態の時には登録画面に遷移するなどにも応用できます。

##application(_:didFinishLaunchingWithOptions:)にUserDefaultsを設定する

```Swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        let userDefaults = UserDefaults.standard
        let firstLunchKey = "firstLunchKey"
        let firstLunch = [firstLunchKey: true]
        userDefaults.register(defaults: firstLunch)
        return true
    }
```

##起動画面のViewDidAppeearにUserDefaultsを設定する

```Swift
override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        let userDefaults = UserDefaults.standard
        let firstLunchKey = "firstLunchKey"
        if userDefaults.bool(forKey: firstLunchKey) {
        performSegue(withIdentifier: "遷移させたい画面へのsegue.identifier", sender: self)
    }
}
```
誰に投票するかをくじ引きで決める

今日は都知事選ですね！

今年はすでに出来レースとなっていて、「誰に投票してもかわらないや」と思う人も多くいそうですし、投票率が下がるかもしれません。

https://www.amazon.co.jp/dp/4887597126
若者は、選挙に行かないせいで、四〇〇〇万円も損してる!? (ディスカヴァー携書) (日本語) 新書

なんて本もありますが、

* 投票しない
* 白票を投じる

となりますと、
支持基盤を持った人たちがただ有利になるだけ、
つまり **つまらない政治がずっと続く** ことになるので是非投票したいですね。

上記の書籍にもありますが、選びたい人がいない場合はエンピツ転がして選んでもいいんですよね。

目的は

* 投票率を上げる
* 候補者に支持基盤だよりにさせない

ことなので。

ただ、選びたい人がいなくても選びたくない人はいる、ということはあります。

候補者のリストを渡したらその中で一人を選んでくれる
といったプログラムを用意しました。

```python:given_lottery.py
import secrets
import sys

def draw_lots(data=None):
    if data is None:
        return -1
    
    lot_member = data.split(',')
    r = secrets.randbelow(len(lot_member))

    return lot_member[r]

if __name__ == '__main__':
    args = sys.argv
    print(draw_lots(args[1]))
```

というくらいですね。


1. 引数をカンマ区切りで分ける
2. 0～要素数のなかでランダム値を出力する
3. ランダム値でリストを引けば、名前が出力される

といった動きになります。


 **追記**

コメントで「choice関数あるよ」と指摘を受けました。

というわけでリファクタリング。

```python:given_lottery.py
import secrets
import sys

def draw_lots(data=None):
    if data is None:
        return -1
    
    return secrets.choice(data.split(','))

if __name__ == '__main__':
    args = sys.argv
    print(draw_lots(args[1]))
```
1. 引数をカンマ区切りで分ける
2. ランダムに名前を出力

と、スッキリしましたね。


ソースファイルは
https://github.com/atworks/given-lottery
に置きました。

あとは

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184265/3abee968-aea1-bdc1-b658-1c687239aa0e.png)

```
> python .\given_lottery.py a,b,c,d,e,g
e
```
のように、カンマ区切りで文字列を渡したらランダムで1つを選んで出力します。
（fさんへは投票したくないので除いたリストを投入して選ぶ、といった動きを想定してます）


よい投票ライフを送りたいものです。
pip install が通らない場合のmodule install

# 要約
通常、pythonのmoduleは、「pip install module名」でインストールするが、セキュリティ等に阻まれて、「pip install module名」が効かない場合がある。例えば、会社PCなどで。その場合はwhlファイルをPypiからdownloadして「pip install whlファイル名」でインストールするか、圧縮ファイル (zip形式及びtar.gz形式のファイル) をdownloadして「python setup.py install」でインストールする。

# 材料及び方法
1. Pypi (https://pypi.org/) の検索欄に対象モジュール名を入力する。
2. 検索リストから対象モジュール名を選択する。
3. 左側の「Release history」をクリックすると、version履歴が確認できる。
<img width="876" alt="pypi_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616208/46d37389-57f0-5d6e-9cc4-d468207dbcd5.png">

4. 左側の「Download files」をクリックすると、対象モジュールのファイルリストが見られる。
<img width="877" alt="pypi_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616208/c582194c-5973-fdf9-5ce3-4a5433b73585.png">

5. whlファイルまたはtar.gzファイルをダウンロードする。
6. 対象モジュールファイルがダウンロードされたディレクトリに移動する。
7. tar.gzファイルは解凍する。
8. whlファイルの場合は、「pip install whlファイル名」を実行する。
9. tar.gz解凍の場合は、解凍されたフォルダに入って、「python setup.py install」を実行する。
10. 依存するモジュールが無い場合はerrorが出るので、依存モジュールについても同様の手順でインストールする。

# 結果及び考察
当方法でpycaret実行環境を構築したときは、依存moduleのインストールが約100個必要だったので、ちゃんと効くpip installは偉大だなーと思いました。
[ターミナル] 知っておきたい UNIX コマンド

#前提
業務効率化のため、フォルダーの新規作成や削除、移動など基本的な操作をターミナルで実行する方法を練習したため、まとめ記事として記載

# ターミナルの起動
1. `commnand + space` Spotlight 検索の起動
2. 「ターミナル」と入力

#### 便利なコマンド
- [Tab]キー：入力値の予測変換
- [↑]キー：履歴の表示

# UNIXコマンド
ターミナルで実行するコマンドを UNIX コマンドという。 UNIXコマンド -X でオプションの実行

#### pwd
`pwd`　print work directory
参照しているフォルダー名の表示

#### ls
`ls` list segment
参照しているフォルダーの中に入っているアイテム名の取得
`ls -a` list segment all
隠しファイルを含め、全てのファイルの表示

#### cd
`cd` change directory
ディレクトリの移動
`cd ../` または `..`
前のディレクトリに戻る

#### mkdir
`mkdir` make directory
ディレクトリの作成

#### rmdir
`rmdir` remove directory
ディレクトの削除
※ ファイルを削除する時は `rm`

#### touch
`touch` ファイルの作成
※ `touch sample.text` のように拡張子を一緒に記載する

#### cat
ファイルの中身の情報の取得

#### echo 
print と同じ
`echo helloworld`
「helloworld」 という文字列の表示
`echo helloworld >a.text`
「helloworld」と入力した a.text を作成

#### cp
`cp` copy コピー
`cp -f` コピー先に同じ名前のファイルがあった場合に上書き保存
`cp -i` 上書きするかどうかファイルごとに確認
`cp -r` ディレクトリごとにコピー

#### mv
`mv` move 移動、リネーム
`mv file directory`
`mv fileA fileB`

#### curl 
API (Application protocol interface) を利用するときによく使う
`curl -h` または `curl -help`コマンドの使い方、オプションの表示

# 参考
https://kitsune.blog/linux-command-summary
MySQLのインデックス構造


通常MySQLのインデックスはB+木と呼ばれる構造に格納される。

インデックスには、クラスタインデックスと呼ばれる特別なものと、それ以外のセカンダリインデックスがある。

クラスタインデックスはMySQLのデータ構造そのもので、リーフノードにはテーブルの実データが格納される。
セカンダリインデックスはリーフノードにクラスタインデックスを参照するためのキーが格納される。

https://dev.mysql.com/doc/refman/5.6/ja/innodb-index-types.html

# B+木

2分探索木の1種で、ルートノードから、データが格納されるリーフノードまでの距離が等しくなる。
リーフノード内のデータはキーで整列しており、リーフノード同士もリンクで連結されている。

![b+tree.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267628/e059b21e-7365-69fe-65be-24df8fbd3586.png)

# クラスタインデックス

テーブルに必ず一つ作成される。リーフノードにはテーブルの実データが格納される。

通常 Primary key がクラスタインデックスになる。Primary key がテーブルに作成されない場合、Unique key (全てのカラムがNOT NULLである必要がある), それも無い場合は非表示の行IDを格納するカラムの値を使ってクラスタインデックスが作成される。

![mysql-cruster-index (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267628/9f844a50-bb0b-a469-f9de-f99944063084.png)

末端のノード (リーフノード) はページと呼ばれ、既定で16KBの固定長サイズの領域で、テーブルの実データが格納される。

https://dev.mysql.com/doc/refman/5.6/ja/innodb-file-space.html

# セカンダリインデックス

クラスタインデックス以外の通常のインデックス。

セカンダリインデックスは任意のカラムを使って構築出来る。クラスタインデックスと同様にB+木の構造に格納されるが、指定された任意のカラムの値を使ってツリー構造が作成される。
また、セカンダリインデックスのリーフノードには、クラスタインデックスを検索するためのキー (通常はPK) が格納される。

![mysql-secondary-index (1) (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267628/1d1dda61-db5f-58d7-4aea-ce32f0f8ebf3.png)
vimへVundleを導入してPluginSearchで出たエラーを解決

# 経緯
Windowsでvimを使っているのですがvimのパッケージソフトを導入することにすることにしました。

- [Vim におけるプラグイン管理についてまとめてみた](https://qiita.com/tanabee/items/e2064c5ce59c85915940)
- [Vimのプラグインマネージャの種類と選び方](https://qiita.com/nil2/items/ddcf23f1163d0abd805b)

こちらの記事などを参考にVundleというものを導入することにしました.

## 導入

[githubのQuick Start](https://github.com/VundleVim/Vundle.vim#quick-start)を参考に導入しました. windowsなので追加で[Vundle on Windows](https://github.com/VundleVim/Vundle.vim/wiki/Vundle-for-Windows)こちらの設定も必要のようです.

## 問題

これで使えると意気揚々と`:PluginSearch hoge`と叩いてみたところ以下のようなエラーがでました.

```
function vundle#scripts#all[3]..<SNR>46_load_scripts の処理中にエラーが検出されました:
行    7:
E15: 無効な式です: <html>^M
E15: 無効な式です: <html>^M
function vundle#scripts#all の処理中にエラーが検出されました:
行    5:
E712: filter() の引数はリスト型または辞書型でなければなりません
行   10:
E686: reverse() の引数はリスト型でなければなりません
function vundle#scripts#all[10]..vundle#scripts#bundle_names の処理中にエラーが検出されました:
行    1:
E712: map() の引数はリスト型または辞書型でなければなりません
function vundle#scripts#all[10]..vundle#scripts#view の処理中にエラーが検出されました:
行   15:
E745: リスト型を数値として扱っています
E116: 関数の無効な引数です: append
1 plugins found
```

# 解決

- [これ](https://github.com/VundleVim/Vundle.vim/issues/599)を参考にして解決しました.

## 原因

`:PluginSearch hoge`はvimのプラグインの一覧をjsonファイルからダウンロードしてきて使っています. ところが、デフォルトの[ダウンロード先](http://vim-scripts.org/api/scripts.json)は既に役目を終えたようです.

>This used to be a mirror of Vim's scripts site on Github.
>
>It was created to allow early package managers (such as Vim Update Bundles and Vundle) to install scripts straight from GitHub *.
>
>Now that most Vim scripts are developed on GitHub and installable straight from the source, >I'm happy to say that there's no need for vim-scripts anymore.
>
>The code has been emptied out to compel users to switch to better sources. The repos remain so none of the work in pull requests is lost.
>
>The scraper code is preserved on GitHub: vim-scraper.
>
>Happy vimming!

このため、jsonファイルをダウンロードできずhtmlファイルがダウンロードされているため出ているエラーのようです.

## 解決法

現在も使えるjsonファイルのダウンロード先を指定してあげればうまくいきます. 

1. `\bundle\.vundle\script-names.vim-scripts.org.json`を削除
2. `\bundle\Vundle.vim\autoload\vundle\scripts.vim`の237行目

```vimscript
  let l:vim_scripts_json = 'http://vim-scripts.org/api/scripts.json'
```

を

```vimscript
  let l:vim_scripts_json = 'https://raw.githubusercontent.com/i-cooltea/resource/master/vim-api_scripts.json'
```

に変更.

これで使えるようになりました.[ここ](https://github.com/VundleVim/Vundle.vim/issues/599)で見つけたリンクなのでもっと良いものがあるのかもしれません.
Hyper-V の ゲスト OS (Ubuntu 18.04 LTS) を固定 IP にする

# はじめに
Hyper-V の仮想スイッチに標準で存在する `Default Switch(規定のネットワーク)` は、

* ゲスト OS が外部ネットワークにかんたんに接続出来る環境を作れる
* <font color="Red">**IP アドレスが自動で割り振られる**</font>

の特性があります。

本記事は、<font color="Red">**IP アドレスが自動で割り振られる**</font> と困る！<font color="Red">**固定 IP アドレス**</font>にする必要がある！
という方を対象とした記事です。

# おそらく
一番かんたんに設定できる方法と思います。
Ubuntu 設定ファイルの編集・PowerShell の操作はしません。

# 1. 設定 : Hyper-V 編 (内部ネットワークを作成)
Hyper-V マネージャーの仮想スイッチ マネージャーから
新しい仮想ネットワーク スイッチ > 内部 > 仮想スイッチの作成
![2020-07-05_14h19_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296531/f5e0a29f-963b-628b-1d68-71cd5cd5935f.png)

名前は好きなもので問題ありません。ここでは、`Internal Switch`とします。
VLAN ID > "管理オペレーティング システムの仮想 LAN ID を有効にする" にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296531/45853a28-a2ff-d973-67f0-7fd1c3cc8d81.png)

次は、固定 IP アドレス化する仮想マシンの設定です。
ハードウェアの追加から"ネットワーク アダプター"を追加し、ネットワーク アダプターを追加します。
先程作成した`Internal Switch`を指定し、ここでも"仮想 LAN ID を有効にする"にチェックを入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296531/1d4e1eb3-1be5-7c19-ce42-b51950df0e44.png)

Hyper-V 側の設定は、以上になります。Windows のネットワーク アダプターの設定を行います。

# 2. 設定 : Windows 編 (ネットワーク アダプターの設定)

Windows 側の設定です。
ネットワーク アダプターの設定画面で、
先程作成した`vEthernet (Internal Switch)`が新しく追加されていることを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296531/4c0f1eff-03f3-6913-a759-2d3379eb5683.png)

`vEthernet (Internal Switch)`を右クリックし、プロパティ画面に移動します。
インターネット プロトコル バージョン 6(TCP/IPv6) のチェックを外し、
インターネット プロトコル バージョン 4(TCP/IPv4) のプロパティ画面に移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296531/95575811-affa-64dd-a3fe-6658113545d4.png)

次の IP アドレスを使うを選択し、好きな IP アドレスとサブネット マスクを設定します。
※よくわからない方は、画像の通りの IP アドレスを設定してください。(いつでも変更できます。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296531/fff877d0-eeab-f108-0754-d7a21cf77f5a.png)

Windows 側の設定は、以上になります。最後に Ubuntu のネットワーク設定を行います。

# 3. 設定 : Ubuntus 編 (ネットワーク アダプターの設定)
画面右上をクリック > 設定マークをクリック > Network
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296531/08b772b4-4c7c-bbd2-7fee-9f701cd7c8a0.png)

### Ethernet (eth0)
"歯車" マークをクリックして、設定画面に移動します。
`IPv6`
Ethernet (eth0) の IPv6 を Disable にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296531/130e3d6b-5494-6b8e-749c-7e46b68227e3.png)

### Ethernet (eth1)
Ethernet (eth1) に `Internal Switch` を割り当て、固定 IP アドレス化します。
"+" マークをクリックして、設定画面に移動します。
`Identity`
MAC Address に (eth1) を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296531/04980ad6-a37f-073b-232e-c65cc48e8f4a.png)

`IPv4`
IPv4 Method の Manual を選択します。
IP アドレスを設定します。Windows 側で設定したものとは、IP アドレスが異なっていることに注意。
※よくわからない方は、画像の通りの IP アドレスを設定してください。(いつでも変更できます。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296531/97bd85e1-2dd6-8f63-84a2-a4f284cdf354.png)

`IPv6`
Ethernet (eth0) と同様に Ethernet (eth1) の IPv6 も Disable にします。

# さいごに
コマンドプロンプトでゲスト OS に ping を飛ばし、応答があれば設定完了です。

いつも通信が通ったものの、どの設定ファイルを変更したんだっけ？？となっていたため、
極力シンプルな方法で固定 IP アドレス化できる手順をまとめました。

筆者自体、ネットワークに精通した人間ではないため不備等ありましたら
コメントで指摘いただけると幸いです。
Pythonで大学の未開始の課題をLineに通知させてみた・・・！

# 概要/理由
・ Pythonで自分の大学の課題サイトをスクレイピングをして、未開始の課題を収集しLineに通知させることをしました。
・理由：最近、スクレイピングにハマり、これを自分の日常に役立つものに生かしたいなと考えた。大学の課題が多すぎて、提出し忘れることがあるのでやっていない課題を知らせてくれると便利だなと考え作ってみた。
・ソースコードは[こちら](https://github.com/yuta97/untask_notify_by_lambda)

# 全体の流れ
1. Dockerで環境構築
2. スクレイピングコードをかく
3. Line NotifyでLineに通知
4. AWS Lambdaにデプロイし定期実行させる

# 使ったもの・ライブラリー等
- Python のライブラリー
 - selenium
 - Beautifulsoup4
 - requests
- その他
 - Docker
 - python3.6
 - Line notify
 - AWS Lambda
  
# 詳細な流れ
## ①環境構築
Dockerで環境構築するのだが、Lamdaにデプロイすることを考え、serverless-chromeを使った。
環境構築は[こちら](https://torahack.com/python-scraping-docker-for-lambda/)が参考になった。
Dockerに
・severless-chrome 
・chromedriver 
requirements.txtに
・selenium
・Beautifulsoup4
・requests　
を書いていく。
そしてDockerイメージを作成
## ②スクレイピングコードをかく
大まかな流れは、
seleniumでログイン→課題ページのURLを取得
その後、課題ページの一覧から「期限が来てない＆未開始になっている」課題を収集
## ③Line Notify
Line Notifyの使い方は[こちら](https://qiita.com/yoshi_san/items/7879b3117d298a143101)の記事を参考にしました。
登録して、数行コードを書くだけなので簡単です。
## ④AWS　Lambdaにデプロイ＆定期実行
大まかな流れは[こちら](https://torahack.com/python-scraping-docker-for-lambda/)をそのまま使わせていただきました。
・コードのフォルダーをS3にアップロード
・Lambda関数の作成
・環境変数を設定する。
・テストを作成し、Lineに通知されることを確認。
・LambdaからトリガーにAmazon CloudWatch Eventsを追加させ、定期実行させる。完成！課題多ない・・・
<img width="350" alt="79530.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432257/68eb4788-b730-ebba-92e7-2e7148d00bbe.jpeg">
# 感想・今後に・・・
・思っていたよりLineやAWSとの連携が簡単だったので今後も使っていきたいですね。
・PDFのダウンロードの自動化にも挑戦したい！
VsCode + C# + .NETCore 3.1 + MySqlConnector から mariadb10.5 にアクセスしてみる

# 目的
・VsCode + C# + .NETCore 3.1 + MySqlConnector から [mariadb10.5](https://qiita.com/tabizou/items/381b2b43bbc634b4c088) にアクセスしてみる
・Windows 10 と Ubuntu 18.04 でコードをコピペして確認

##サンプルを試してみる
・VSCode を立ちあげて適当なフォルダを選択する
・コンソールから作成したフォルダ以下で dotnet new console 
~/code/my0001$ ls
Program.cs  bin  my0001.csproj  obj

## MySqlConnectorを追加する
※事前にvscode-nuget-package-managerが追加されてることを確認
表示メニュー
　-> コマンドパレット
　　-> nuget
　　　-> Nuget package Manager:Add Pckage
　　　　-> MySqlConnector を入力後 enter
　　　　　-> MySqlConnector を選択
　　　　　　-> 1.0.0-beta.5 を選択
## サンプルコード

```cs
using System;
using MySqlConnector;
using System.Data;

namespace my0001
{
    class Program
    {
        // 接続情報
        private static readonly string Server = "192.168.5.xxx";    // ホスト名
        private static readonly int Port = 3306;                    // ポート番号
        private static readonly string Database = "nation";         // データベース名
        private static readonly string Uid = "demo";                // ユーザ名
        private static readonly string Pwd = "passwd";              // パスワード

        // 接続文字列
        private static readonly string ConnectionString = $"Server={Server}; Port={Port}; Database={Database}; Uid={Uid}; Pwd={Pwd}";

        static void Main(string[] args)
        {
            using (MySqlConnection conn = new MySqlConnection(ConnectionString))
            {
                conn.Open();

                MySqlDataAdapter da = new MySqlDataAdapter("SELECT * FROM guests", conn);
                DataSet ds = new DataSet();
                da.Fill(ds, "guests");
                DataTable tbl = ds.Tables["guests"];

                foreach(DataRow row in tbl.Rows)
                {
                    Console.WriteLine("Column 0: {0} Column 1: {1}", row[0].ToString(), row[1].ToString());
                }
            }
        }
    }
}
```
# 参考にしたサイトはこちら
[Ubuntu 18.04 + VsCode + Pytho3 + mysql-connector-python から mariadb10.5 にアクセスしてみる](https://qiita.com/tabizou/items/381b2b43bbc634b4c088)
[Ubuntu 20.04 に Posgtgres12 をインストール後 C# + Npgsql でアクセスしてみる](https://qiita.com/tabizou/items/47f395d7ab3030dd1915)
gitをHomebrewでインストールし直す際のエラー

一度gitをインストールしていたが、Homebrewでインストールしておいた方がgit-prompt.shが自動生成される為gitをHomebrew経由で再インストールした話です。
エラーでハマってしまったので自分用メモとして残ります。

インストール済みのgitのディレクトリを削除後、以下のコマンドでgitが存在しないことを確認
(実行後何も表示されなければ存在しません)

```
 $ which git
```

以下のコマンドでHomebrewを更新

```
brew install git
```

実行後、以下のコマンドを実行し、実行結果が同じであることを確認

```
$ which git
/usr/local/bin/git
```

実行結果が異なる場合はパスの設定が以前のままになっている可能性がありますので、以下のコマンドでリンク先を上書きする。
(このリンク設定を忘れエラーにハマりました)


```
$ brew link --overwrite git
```

実行後、以下のコマンドを実行し、実行結果が同じであることを確認

```
$ which git
/usr/local/bin/git
```