OmniAICreator/Qiita-1.07M huggingface dataset:
[Rails]seedファイルごとにデータを管理する

某フリマアプリのクローンサイトをチームで作成中です。
その時に、seedファイルの扱いに少し困ったので備忘録として残しておきます。

# したいこと
商品を出品する時に、「商品の状態」「配送料」..etcなんかは、
データベースに先に値を入れておいて、プルダウンから選択できるようにする
 
こんな感じ
![スクリーンショット 2020-06-29 17.41.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656249/c26de7ab-f8f8-d07d-fd8e-e3127a0b2e50.png)


# 実装
##1. rake taskの作成 
lib/tasks/直下にseed.rakeを作成し、以下を記載


```ruby:lib/tasks/seed.rake
 Dir.glob(File.join(Rails.root, 'db', 'seeds', '*.rb')).each do |file|
   desc "Load the seed data from db/seeds/#{File.basename(file)}.
   task "db:seed:#{File.basename(file).gsub(/\..+$/, '')}" => :environment do
     load(file)
   end
 end
```


##2. それぞれのseedファイルを作成
db/seedsディレクトリを作成し、そこに「データを入れたいモデル名.rb」のファイルを作成
今回はとりあえず、商品の状態を表すCondition.rbを作成


```ruby:db/seeds/Condition.rb
conditions = Condition.create([
  {condition: "新品・未使用"},
  {condition: "未使用に近い"},
  {condition: "目立った傷や汚れなし"},
  {condition: "やや傷や汚れあり"},
  {condition: "傷や汚れあり"},
  {condition: "全体的に状態が悪い"}])
```
##3. 実行
あとは実行するだけなので、以下のコマンドをターミナルに

```
bundle exec rake  db:seed:condition
```

conditionsテーブルにデータを入れられました！
![スクリーンショット 2020-06-29 18.18.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656249/81ab5667-e0ea-76e8-5769-4591e9473cce.png)


# が、問題発生・・・
ローカルの環境ならこのままで良かったのですが、本番環境にデプロイする際に
作成したそれぞれのseedファイルの読み込ませ方が分からず、データを反映できませんでした

## 解決法
seeds.rbに以下の記述を追加

```ruby:seeds.rb
require "./db/seeds/condition.rb
```
あとは、本番環境側で反映させたらOK

参考記事
・[本番環境でrake db:seedを使ったデータ投入]
(https://qiita.com/Sotq_17/items/a091fe92dd64d3cf429b)

# 終わりに
active hashを使えばもうちょっと楽にできたりしたのかな〜なんて思いますが、
納期もあるので一旦この方法で実装しました
他にいい方法があれば教えていただきたいです


# 参考記事
・[Railsでseedデータを分割して実行できるようにする](http://yu0105teshi.hateblo.jp/entry/2016/08/03/180603)
・[Rails・seedファイルを分割して管理する](https://qiita.com/masaki7555/items/d65f56958020cbca5ee0)
To install the missing version, run `gem install bundler:2.1.4`と出たときの対処法

日々学んだことやつまずいたことについてまとめていきます。
記載に誤りがありましたら、ご指摘していただけると助かります！
いつも他のかたの記事に助けられているので、少しでもお役に立てればと思います。
##どういうエラーなのか
Gemfile.lockにbundler 2.1.4が指定しているが、そのバージョンのbundlerが見当たらないというエラー。

```
Traceback (most recent call last):
	2: from 
	1: from 
#省略
Could not find 'bundler' (2.1.4) required by your /Users/<ユーザー名>/<ルートディレクトリ名>/Gemfile.lock. (Gem::GemNotFoundException)
To update to the latest version installed on your system, run `bundle update --bundler`.
To install the missing version, run `gem install bundler:2.1.4`
```
##どんなときに起こるのか
Rubyのバージョンの変更をしたときなどに起こる。rbenvではRubyのバージョンごとにgemをインストールする必要があるとのこと。

##対処法
```
gem install bundler -v 2.1.4
```
と入力して、bundler 2.1.4を入れたら解決！

##参考
https://qiita.com/kodai_0122/items/c4c13e89dd5c4cba1f32
https://qiita.com/YumaInaura/items/64e5721549e4927ce85f
https://k-koh.hatenablog.com/entry/2020/01/27/200511
pythonのpandasでcsv読み込む

#pythonでcsvファイルを読み込む
・python
・sqlite3
・pandas

```python:
import sqlite3
import pandas as pd

df = pd.read_csv('{csvファイルのpath}', encoding='shift-jis') 
db_name = 'sample.db'  #dbの作成
conn = sqlite3.connect(db_name)  #dbへ接続
df.to_sql('class_table', conn, if_exists='replace')  #csvを取り込んだ情報をsqlへ変換
c = conn.cursor()
query = 'SELECT * FROM class_table'
result = c.execute(query)
c.fetchall()  #全件取得

for row in result:  #1件ずつ取得
  print(row)

for vert in range(2, 10):  #カラムを順に取得
  vert += 1
  for side in range(0, 4):
    print(df.loc[vert, side])
    side += 1

conn.close()  #db切断
```
タスクの導出理由の可視化

##タスクの導出根拠の可視化
私が10年前に関わったアジャイル開発プロジェクトでは開発チームはタスクの発生した導出理由を明確にしていました。この導出項目は

- 当初：最初のプロダクトバックログで定義された仕様通りの開発作業
- 追加：プロジェクト期間中に追加されたプロダクトバックログに関する開発作業
- 変更：開発済みのプロダクトバックログに対する変更の作業
- バグ対応：バグと指摘されたものに対する改修作業
- 環境：システムの環境周りに対する作業。準備作業だけでなく、環境変更も全て含む。
- その他：この分類に入らない、例外的な作業

この様に、タスクの種類を分けて、その様子を観察していると、チームの自律の様子が把握できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621379/18942a35-eafb-8a3e-d797-79d9df683b2e.png)
特にバグ対応に関してはこのプロジェクトでは後半のスプリントでは一切バグ対応のタスクは発生していませんでした。この事はチームが品質に拘って色々な工夫をして実践してきた証です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621379/973e6895-ea69-c79d-d62e-82453e5b48f0.png)

これは、タスクの導出根拠別にイテレーション作業を可視化したものです。
このプロジェクトのシステム稼働後もバグは一切なく安全可動しています。
CircleCI Bitrise CodeMagicの料金を1ページでみる

開発してて、CIの料金についての話が定期的にあるので。
これから僕が使いそうなCIの料金を1ページで見るための記事です。

全て2020/06/24時点の料金です。

## CircleCI
### Freeプラン
* 料金
    * もちろん無料 
    * 利用マシンの種類やスペックによって別途料金がかかる
* 機能
    * 無料クレジット: 2,500/週<br>
    * 同時実行ジョブ: 1
    * Linux および Windows プロジェクトのビルド
    * macOSは**含まれない**(近日リリースと書かれてる)

### Performanceプラン
* 料金
    * 月額 $30~
    * 利用マシンの種類やスペックによって追加料金がかかる
* 機能
    * Freeプランの機能
    * 同時実行ジョブ: 自動スケーリング
    * macOS プロジェクトのビルド
    * Docker レイヤーキャッシュ 
    * グローバル サポート

### Customプラン
* 料金
    * [お問い合わせで決める](https://circleci.com/ja/talk-to-us/?source-button=Talk%20to%20us%20-%20Custom)
* 機能
    * 必要な機能だけに抑える。または、Performanceプラン以上のスペック
    * サポートの充実
    * GPU–NVIDIAを使うようになる
    * 支払い方法を柔軟に行える

## Bitrise
### Hobbyプラン
* 料金
    * 無料
* 機能
    * 同時実行ジョブ: 1
    * 月に200回のbuildまで
    * 30分でbuildのタイムアウト
    * 仮装マシン
        * Ubuntu
            * 2 vCPU 
            * 2.6 GHz Intel Xeon E5 
            * 7.5 GBのRAM
        * MacOS
            * 2 vCPU 
            * Intel® Xeon® CPU E5-2697 v2 @ 2.70GHz
            * 4 GBのRAM
    * 2名のチームメンバー
    * メールとコミュニティサポート
   
### Developerプラン
* 料金
    * 40ドル/月
* 機能
    * 同時実行ジョブ: 1
    * 無制限のbuild
    * 45分でbuildのタイムアウト
    * 仮想マシン
        * Hobbyプランと同じ
    * 無制限のメンバー
    * 標準サポート
    
### Org Standardプラン
* 料金
    * 100ドル/月
* 機能
    * 2つの同時実行から追加するごとに50ドルの追加料金
    * 無制限のbuild
    * 90分でbuildのタイムアウト
    * 仮想マシン
        * Hobbyプランと同じ
    * 無制限のチームメンバー
    * グループ管理
    * プレミアムサポート

### Org Eliteプラン
* 料金
    * 300ドル/月から~
* 機能
    * 3つの同時実行から追加するごとに100ドルの追加料金
    * 無制限のbuild
    * 90分でbuildのタイムアウト
    * 仮想マシン
        * Ubuntu
            * 4 vCPU 
            * 2.6 GHz Intel Xeon E5 
            * 15 GBのRAM
        * MacOS
            * 4 vCPU 
            * Intel®Xeon®CPU E5-1650 v2 @ 3.5GHz
            * 8 GBのRAM
    * 無制限のチームメンバー
    * グループ管理
    * シングルサインオン（SAML SSO）
    * プレミアムサポート

### Enterprise Build Platformプラン
* 料金
    * [お問い合わせで決める](https://www.bitrise.io/contact)
* 機能
    * 必要な機能だけに抑える。または、Performanceプラン以上のスペック

## CodeMagic
### Freeプラン
* 料金 
    * もちろん無料
* 機能
    * 500分のbuildまで
    * 同時実行ジョブ: 1
    * 2名分のチーム
 
### enterpriseプラン
* 料金 
    * 使用量によって加算されていく
* 機能
    * Mac miniビルドの分　1分あたり0.038ドル
    * Mac Proビルドの分　1分あたり0.095ドル
    * 追加チームするたびに 10ドル/月


## 細かく機能を確認したい方はこちら

CircleCI https://circleci.com/ja/pricing/
Bitrise  https://www.bitrise.io/pricing
CodeMagic  https://codemagic.io/pricing/
【自作】自動デプロイ、AWSの各種サービス起動について

###  <font color='lightblue'>１）背景</font>
自動デプロイはcapstranoなどありますが、簡単に自動化するため、以下のshellを作成しました。このshellを使えば、手数はかなり減ります。

###  <font color='lightblue'>２）環境</font>

| 項目              |               内容 | 
|:-----------------|:------------------:|
| OS.Amazon Linux AMI      |            release 2018.03 |            
| Ruby             |            v2.5.1 |  
| Ruby On Rails    |           v5.2.4.3 |  
| MySQL    |           v5.6 |  
| Unicorn    |           v5.4.1 |  


###  <font color='lightblue'>３）内容</font>

####  （1） AWSの対象インスタンスの再起動
インスタンスを再起動することで、現在稼働しているアプリが停止します。

####  （２） shellを実行する（ホームディレクトリの配下に配置する）
以下のshellを実行することで、必要なサービスの起動と、アプリの起動を行います。
サービスを起動する前には、必要なgitプル、scssやJavascriptのコンパイルを行います。

```shell:auto-service.sh
#/bin/sh

#任意ディレクトリへ移動
cd /var/www/☆アプリ名; sleep 5; echo `pwd`;

#git-pullする。
echo "get!! new-master.. wait 5sec"; sleep 5;
git pull origin master;

#Assetsのプレコンパイル
echo "precompile!!";sleep 5;
rails assets:precompile RAILS_ENV=production

#NGINXの開始
sudo service nginx start; sudo service nginx status; sleep 5;

#MySQLの開始
sudo service mysqld start; sudo service mysqld status; sleep 5;

#アプリ開始
echo "Rails Start!!!!!!!!!!!!!!"
RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
```

以上、よければご活用ください。
（レポート）Scrum Fest Osaka 2020 Day2 "「ふりかえり」と言えばKPTAでしょ！ KPTで食べてきたおじさんが、これからはKPTAで食べていこうと思います。 " #scrumosaka.oblove

# はじめに

こんにちは、森です。

[Scrum Fest Osaka 2020](https://www.scrumosaka.org/)は、6/26-27に開催された、オンラインでの大規模カンファレンスです。
今回、チームメンバーの島田さんが参加したワークショップについてレポートを記載してくれたので、そちらを乗せておきます。
（森は今回、自身の登壇が被ってしまったためこのワークに参加していません…。残念。）

今回、NRI asleadのチームメンバー2人で参加しています。

---

こんにちは、島田です。

この記事では、Scrum Fest Osaka 2020 2日目 #oblove（オブラブ） 14:00-14:45で行われた、KPTAフレームワークによるふりかえりのワークショップに関するふりかえりです。
ワークショップを通して得られた個人的な学びや感じたことを記載しています。

ふりかえりの手法として広く知られているものとして、以下のふりかえり手法がありますが、今回のワークショップでは、新しいふりかえり手法のKPTAとはどういうものか、アクティビティを通して体験しました。

- YWT
- KPT
- PDCA

## KPTAワークショップ
実際に参加した45分間のワークショップでは、以下のアクティビティを実施しました。

1. KPTAの説明
    1. KPTでよくあること
    2. KPTAとは
    3. KPTA体験ワークショップの進め方
3. KPTA体験ワークショップ
    1. 自己紹介
    2. アクティビティ（１回目）
    3. KPTAでふりかえり
    4. アクティビティ（２回目） 
4. まとめ

### KPTでよくあること

「１．KPTAの説明」の中では以下のようなTryが出される場面が多いとのことでした。

- 実行可能でないもの
- 効果が少ないもの
- 落とし込めてないもの

このようなTryを出しても、ただこなすだけの形骸化したふりかえりとなってしまい、結局実施されないままになってしまう可能性が高いです。

また、きっちりとふりかえりの目的や進め方の認識を持てていないと、意味のないふりかえりになってしまうどころか、KPTはつらいものとなってしまう危険性があるとのことした。

- 責任追及になりがち
- 成果を実感できなくなっていく

本来前を向いてカイゼンをしていくための場が責任追及の場になってしまうのはつらいですよね。

### KPTAとは

KPTAはふりかえりフレームワークのKPTを拡張した手法です。
Keep、Problem、Tryに加え、ふりかえりの内容を次の活動のカイゼンにしっかり活かすための具体的なアクションに落とし込む、Actionのフェーズを設けています。

###  KPTA体験ワークショップ
ワークショップでは２，３名のグループに分かれ自己紹介をしたのち、協力してジグソーパズルを完成させるというワークをしました。

#### アクティビティ（１回目）

初対面の方と共同作業するため、まずは自己紹介をしました。時間が限られているため、自己紹介をしたあとはすぐにワークに取り掛かりました。
動き方もぎこちなく、会話を少ないままとりあえず動いたという感覚でした。
結果、圧倒的に時間が足りず、ほとんど完成できません。

#### KPTAでふりかえり

１分間のアクティビティ（１回目）実施後に、５分でKPTAを用いたふりかえりを実施しました。
ふりかえりでは[Continuous KPTA](https://kpta.agile.esm.co.jp/)というツールを使い、Keep・Problem・Try・Actionを付箋に書き出して共有しました。
 
 ふりかえりでは付箋に書き出した内容を見ながら感じたことを共有しました。

- Keep:全体像が見えないのでまずは把握しようと動き出しが早かった
- Problem:お互いの作業がかぶってしまうことがあり、動きづらかった。
- Try：枠の右側と左側で担当を分けて、それぞれパズルを埋めていく

といった話をしました。
 
ここでふりかえりの時間切れとなりました。
Actionのフェーズではありますが、エリアで分けて作業を進めるという方針で合意できたため、アクティビティ（２回目）を開始しました。
 
#### アクティビティ（２回目）

アクティビティ（２回目）は、１回目の続きから作業を再開しました。
ふりかえりでのTry通り作業領域を分けたため、パズルを当てはめていく作業がスムーズに進み、時間内に完了まで持っていくことができました。


## ワークショップのふりかえり

ふりかえり時にTryとして「左右で領域を分割してピースをはめていく」を挙げましたが、これは本来Actionに書く内容で、Tryとしては「作業領域を分割して作業する」といった内容が入ってくるのかなと思います。
具体的な案には落とし込めているものの、いきなりHowに入ってしまっているため、思考が展開しづらくなってしまったように思います。
Whatを一度書き出したうえでHowに入っていくというプロセスを踏むことで、より視野の広いHowが出てくるのではないかと考えています。
この点は、スクラムでの「価値」（What）に視点を置き、受入条件を満たせる方法であれば手段（How）は問わないという考え方に通ずるところもあるのではないかと感じました。

アクティビティ（２回目）ではパズルを完成させることができたものの、ほぼ作業が完了したと思ったタイミングで、実は２つのピースの場所が逆であり、バタバタするという一幕がありました。
これは、ピースをバラけさせた際に右側にはめるべきピースを左寄りに、左側にはめるべきピースを右寄りに置いてしまっていたため、それぞれの作業者が自分の領域にはめるべきでないピースを手に取りやすかったというが１つの原因としてあったのではないかと考えています。
この点について再びふりかえりを実施できそうだなと感じました。

## まとめ

ふりかえりを通して最終的に「"実行可能"なアクションを出せているか／なっているのか」という観点を参加者が意識することが必要なのだと理解しました。
その仕組みとして、Tryで終わらずActionというフェーズを明に設けるというのポイントだと個人的に考えています。
また、業務の中で「手段が目的化する」ことがよくあると個人的に感じています。
What（Try）とHow（Action）を明確に分けることで、両者を混同してしまうことや発想の幅が狭まってしまうことを防ぎやすい点も１つのポイントなのではないかと感じました。
k8sでkustomizeを使ってみる

##tl; dr

- kustomize使うとまとめてapplyできるよ
- kustomizeで環境を分ける場合はpatchを使おう

## kustomizeとは

k8sのクライアントを使う上で、環境を再構築する場合や、
環境ごとにわけてapplyしたい場合などにまとめてやることができるクライアントツールです。
version14以上の `kube-ctl`が使える状態だと標準で使うことがきます。
今回は、使うための最低限の動作を試してみたいと思います。

## まとめてdeployしてみる

シンプルな例として、下記のようなファイルを用意します。
(deployとserviceの作成は割愛します)

```kustomization.yaml
commonLabels:
 app: test01
resources:
- deploymant.yaml
- service.yaml
```

`kustomization.yaml`の配置しているディレクトリで、
buildをしてみます

```
kustomize build .
```

すると、それぞれの定義が、`---`で区切られて作成されていることがわかります。さらにこれをapplyするには以下を実行します。

```
kustomize build . | kubectl apply -f -
```

## patchを使って、環境想定の構成でdeployしてみる

例えば環境によって、デプロイ内容を変えてみましょう。
今回はディレクトリ構成を以下のようにし、
`deploymant_patch.json`を新しく作成します。

```
.
├── base
│   ├── deploymant.yaml
│   ├── servece.yaml
│   └── kustomization.yaml
└── overlays
    └── develop
        └── deploymant_patch.yaml
        └── kustomization.yaml
```

特殊な構文ですが、以下を参照に、今回はreplica数を変えてみます
(元々`replicas: 3`)のdevelopだったとします


```overlays/develop/kustomization.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test01-develop
spec:
  replicas: 4
```

この状態でapplyをしてあげると、replica数が増えていることがわかります

```
kustomize build overlays/develop/ | kubectl apply -f -
```

## patchを動的に追加する

ラベルの追加

```
kustomize edit add label labelKey1:"labelValue1"
```
imageのセット
kustomize edit set image hoge.docker/hoge-image:develop



## 参考） 
公式:
- https://github.com/kubernetes-sigs/kustomize
patchの参照:
- https://caddi.tech/archives/427
- https://qiita.com/yakisuzu/items/6b6a65d9cbc0422f4b3d
Java8のリストソート方法

# Java8のリストソート方法

java8のリストソートは簡単です。

> ソート対象DTO

```java
@Data
public class Dto {
    private String id;
    private String name;
    private int age;
}
```

> リストソート

```java
public class TestListSort {
    public static void main(String args[]) {
        // リスト定義
        List<Dto> list = new ArrayList<>();
        list.add(new Data("001", "DTO1", 10));
        list.add(new Data("001", "DTO1", 5));
        list.add(new Data("003", "DTO3", 4));
        list.add(new Data("002", "DTO2", 4));
        
        // ソート処理(id、ageの昇順)
        list.sort(Comparator.comparing(Dto::getId).thenComparing(Dto::getAge));
        // ソート結果検証
        list.forEach(dto -> {
            System.oup.println("id=" + dto.getId() + " name=" + dto.getName()) + " age=" + dto.getAge());
        });
    }    
       
}
 
```



> リストソート後、新しいリスト生成する場合

```java
List<Dto> sortedList = list.stream().sorted(Comparator.comparing(Dto::getId).thenComparing(Dto::getAge)).collect(Collectors.toList());
```

> id昇順、age降順の場合

```java
list.sort(Comparator.comparing(Dto::getId).thenComparing(Comparator.comparing(Dto::getId).reversed()));
```
Linux コマンド

# check free space
`df -h`

# search file
`grep -r UIWebView .`

# search && replace sting
`grep -rl 'windows' ./ | xargs sed -i 's/windows/linux/g'`

#delete all files with a given extension
`find . -type f -name '*.meta' -delete`

# list file permission
`ls -l`

# unzip
`unzip file.zip -d destination_folder`

# rename allfile extension
`for x in *; do mv "$x" "${x%}.png"; done `

# zip file
`zip zipfoldername -r dir`
`zip -r file.zip file`

# find file
`find . -name "xxx.png"`

# move types of files into one folder
`find . -name "*.png" -exec mv "{}" ../../../png/ \;`

# reboot
`sudo reboot`

# copy files less than 100mb
`cd src_folder && find ./folder -size -100M -exec cp -r {} ../new_folder/ \;`
EC2に立てたJenkinsのソースコード管理でGitHubを使う方法

# 概要
AWS EC2に立てたJenkinsのソースコード管理でGitHubのprivateリポジトリを使う。
なかなかうまくいかなくてハマったので備忘録を兼ねてメモ。

# 環境
- AWS EC2(OS: Amazon Linux 2)
- Jenkins 2.235.1

# 1. Jenkinsにgitを認識させる
これに気付かずめっちゃハマった。

- Jenkinsの管理 > Global Tool Configuration からGitを設定する
 - install済のgitのパスを指定する
 - 自動インストールを選択する
- どうせgitは使うと思うので、サーバーにgitをinstallして設定した

```
$ sudo yum install -y git
$ git --version
git version 2.23.3
$ which git
/usr/bin/git
```
![jenkins_git.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265229/edbcafde-5a5f-3ace-08a8-7d3fbce187ac.png)

# 2. 公開鍵と秘密鍵を作成する
- `/var/lib/jenkins/.ssh/`に鍵を作成する
 - 公開鍵: id_rsa_github.pub
 - 秘密鍵: id_rsa_github
- パスフレーズはなしでOK
- デフォルトだとjenkinsユーザーにスイッチできないのでrootで作成して所有者を変更する
 - `/etc/passwd/`を見るとjenkinsユーザーは`/bin/false`

```
// .sshディレクトリを作成する
$ cd /var/lib/jenkins/
$ sudo mkdir .ssh
$ sudo chmod 700 .ssh/
$ ls -la | grep ssh
drwx------  2 root    root       6 Jun 29 15:08 .ssh

// 鍵を作成する
$ sudo su -
# cd /var/lib/jenkins/.ssh/
# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): id_rsa_github
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in id_rsa_github.
Your public key has been saved in id_rsa_github.pub.

// 所有者を変更
# chown jenkins:jenkins id_rsa_github.pub
# chown jenkins:jenkins id_rsa_github
# cd ../
# pwd
/var/lib/jenkins
# chown jenkins:jenkins .ssh/
# ls -la | grep ssh
drwx------  2 jenkins jenkins   52 Jun 29 15:14 .ssh
# exit
```

# 3. `.ssh/config`を作成する
- `id_rsa`以外の名前で作成した場合はconfigで設定する必要あり
 - `id_rsa`の場合はデフォルトで見に行くので不要(のはず)

```
$ sudo touch .ssh/config
$ sudo vi .ssh/config
Host github.com
  HostName github.com
  IdentityFile ~/.ssh/id_rsa_github
  User git

// 所有者を変更
$ sudo chown jenkins:jenkins .ssh/config
```

# 4. GitHubに公開鍵を登録する
- pullできれば良いので、リポジトリのDeploy Keysに登録する
- Settings > Deploy keys > Add deploy key
![github_keys.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265229/327b5f18-f492-e2fd-07f9-0635d5087dc1.png)

# 5. ssh接続の確認
- サーバーからsshが通るか確認しておく

```
$ sudo -u jenkins ssh -T github.com
Hi tamorieeeen/repositpry_name! You've successfully authenticated, but GitHub does not provide shell access.
```

# 6. JenkinsのJobで設定する
- ソースコード管理でGitを選択
- リポジトリ
 - リポジトリURL: GitHubのClone with SSHのURL
 - 認証情報: なし
- 今回はサーバー上でid_rsaを管理しているので認証情報はなしでOK

![jenkins_job_git.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265229/7eef0b0c-ff0a-a723-7a26-2e71f225535b.png)

# 参考
- [GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~](https://qiita.com/shizuma/items/2b2f873a0034839e47ce)
ROS2における変更点: from Eloquent Elusor to Foxy Fitzroy

【[ROS2関係トップページへ](https://qiita.com/NeK/items/7ac0f4ec10d51dbca084)】

# modern CMakeの使用について

* modern CMakeが使用可になった？前から使えてたけど推奨になった？
    * classic CMakeとmodern CMakeの混在は不可っぽい．
        * たぶん「Foxy Fitzroyからmodern CMakeも使えるようになった」ということだと思う．ここで重要なのが<font color="Red">modern CMake使うなら全部の部分で使え</font>ということ．混ぜると強制的にclassicになるっぽい．特に，ament_export_{interface,include_directories,libraries}あたりは不使用が推奨．
        * 参考:[Foxy Fitzroyでの変更点](https://index.ros.org/doc/ros2/Releases/Release-Foxy-Fitzroy/)のうち[Classc CMake vs. modern CMake](https://index.ros.org/doc/ros2/Releases/Release-Foxy-Fitzroy/#classic-cmake-vs-modern-cmake)


# 基本タグの効率化？
## package.xml
以下の三つのタグについて，全部同じなら一つにまとめられるようになった．

* 旧記載
    * \<build_depend\>
    * \<exec_depend\>
    * \<test_depend\>
* 新記載
    * \<depend\>

## CMakeLists.txt

* ament_export_interfacesはament_export_targetsに変更
* ament_export_{include_directories,libraries}は廃止
* ament_export_directoriesは使ってもいいが不使用を推奨？

# 独自メッセージ関連のタグ
## package.xml

rosidl_default_generatorsは\<buildtool_depend\>タグだった(と思う)が\<build_depend\>になった．

* 旧記載
    * \<buildtool_depend\>rosidl_default_generators\</buildtool_depend\>

* 新記載
    * \<build_depend\>rosidl_default_generators\</build_depend\>

# 新機能
## パラメータ再設定の関数

set_on_parameters_set_callback関数に加え，add_on_set_parameters_callback関数およびremove_on_set_parameters_callback関数が使えるようになった．

参考:[ROS2におけるパラメータ変更に対するcallback関数の設定](https://qiita.com/NeK/items/37cbae948f8a4178044b)
Railsプロジェクト開発方針

- Railsの思想を理解する
  - [Railsの基本理念 : Railsの生みの親が掲げる8つの原則 | POSTD](https://postd.cc/rails-doctrine/)
  - [Getting Real: The smarter, faster, easier way to build a successful web application](https://basecamp.com/books/getting-real)
      - 日本語版アーカイブ: [Getting Real by 37signals](https://web.archive.org/web/20110721234749/http://gettingreal.37signals.com/GR_jpn.php)
  - Railsは思想を強く持ったフレームワーク。Railsを使うのであれば、ある程度、Railsの思想を理解しておいた方が良い。
- 読みやすさ、分かりやすさ、直しやすさを意識する
  - システムやコードは常に変化していくもの。変化に対応しやすいコードを意識する。
  - 新しく入った人や数年後の自分が理解しやすく、修正や実装を行いやすいコードを意識する。
- なるべくRailsのデフォルトに沿う(ただし、例外もある)
  - 例外：`erb`、`CoffeeScript`、`jQuery`は使わない
- 使わない方が良いもの
  - Gem
      - `Devise`
      - `grape`
  - `default_scope`
  - 論理削除
- 使った方が良いもの
  - `Ridgepole`
  - `action_args`
- テストコードは何の為に書くのか、目的を明確にする
  - 書こうとすると際限無く書けてしまう
  - テストコードは実装コスト、メンテナンスコストもそれなりにある
      - コストに見合う効果があるのか、費用対効果も考える。
  - バグの発生を防ぐため、デグレを防ぐため、など、何の為のテストコードかを明確にする。
- `before_action`は使い過ぎない
  - 処理が暗黙化されてしまうため、処理やデータの流れを分かりにくくしてしまう場合がある。
- ローカル環境での開発効率を保つ
- ローカル環境の構築手順を`README`に書く
SQL Laravel 論理削除されたカラムを検索に含めない

## 目的

- Laravelにて論理削除するための設定を行ったDBのテーブルに対するSQLのselect文にてすでに論理削除されたレコードを出力しないwhere条件をまとめる

## 実施環境

- ハードウェア環境

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

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravel バージョン | 7.0.8 | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

## 前提条件

- 下記の作業を行い、現存するテーブルのレコード削除機能を物理削除から論理削除に変更する。
    - [Laravel テーブル内のデータ削除を論理削除にする](https://qiita.com/miriwo/items/5e5a47ece1b805266246)

## 読後感

- SQL文でselect句を使用した際に論理削除されたレコードの情報を表示しないようにwhere句の条件が記載できる。

## 概要

1. Laravel側からのデータ削除
1. where句の条件の追加と実行

## 詳細

1. Laravel側からのデータ削除
    1. アプリ名ディレクトリで下記コマンドを実行してtinkerを起動する。

        ```terminal
        $ php artisan tinker
        ```
    1. 下記の公式ドキュメントに従い任意のレコードを論理削除する。
        - [Eloquent：利用の開始](https://readouble.com/laravel/7.x/ja/eloquent.html)
        
            ![Eloquent：利用の開始_7_x_Laravel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/a1cb0b83-85c6-8713-ebc5-20f743d011d0.png)

        ```php
        >>> 変数A = App\論理削除を行うレコードが存在するテーブルのデータ操作を行うモデル名::find(削除するレコードのid);
        >>> 変数A->delete();
        ```
1. where句の条件の追加と実行
    1. 下記コマンドを実行してMySQLにターミナルからログインする。(MySQLのrootユーザのパスワードを忘れてしまった方はこちら→[Mac ローカル環境の MySQL 8.0 のrootパスワードを忘れた時のリセット方法](https://qiita.com/miriwo/items/1880e9d2ebcfd3c0e60d))

        ```terminal
        $ mysql -u root -p
        ```
    1. 下記を実行してこれから実行するSQL文がどのテーブルに対するものなのかを設定する。
   
        ```sql
        use Laravelアプリに紐づいたDB名;
        ```
    1. 下記を一旦実行してselect句を使用してusersテーブルの内容を出力する。(論理削除のレコードも出力される。)

        ```sql
        select * from users;
        ```
    1. 下記を実行して論理削除のレコードを除いたusersテーブルの内容を出力する。(deleted_atカラムがnullとして条件付けしたのはdeleted_atは論理削除された日時を格納するカラムなのでnullなら論理削除していないことになるためである。)

        ```sql
        select * from users
        where deleted_at is null;
        ```

## null判定の落とし穴

1. nullは`=`を使って判定できない。
    - `where deleted_at = null;`などの条件だとnullは判定することができない。間違えやすいので注意する。
1. nullの判定は`is null`もしくは`is not null`を使用する。
    - `=`での判定ができないためnullの判定に関しては条件の記載方法が変わることに注意する。
競技プログラミング練習記 No.28【ABC132練習】

初回 -> [はじめに](https://qiita.com/easychoco/items/a9ae28aca97cfe47091f)

[ABC132](https://atcoder.jp/contests/abc132)を解きました。
4完です！

|問題|時間|アルゴリズム|実行時間
|:-:|:-:|:-:|:-:|
| A |  1min |-| 8ms|
| B |  4min |-| 6ms|
| C |  3min |-|24ms|
| D | 45min |組み合わせ|8ms|



## A - Fifty-Fifty
```c++
	string s;
	cin >> s;
	sort(s.begin(), s.end());
	if (s[0] == s[1] && s[1] != s[2] && s[2] == s[3])
	{
		cout << "Yes";
	}
	else
	{
		cout << "No";
	}
```
「2種類の文字が2回ずつ出てくる文字列」はソートすると●●××の形になりますね。
ソートした後、●●××の形を判定する式を書いて正解です。
●●●●や●●●×を間違えて判定しないように注意です。


## B - 	Ordinary Number
``` c++
	int n;
	cin >> n;
	vector<int> p(n);
	for(int i = 0; i < n; ++i)
	{
		cin >> p[i];
	}

	int ans = 0;
	for(int i = 1; i < n - 1; ++i)
	{
		if (p[i - 1] < p[i] && p[i] < p[i + 1])ans++;
		if (p[i + 1] < p[i] && p[i] < p[i - 1])ans++;
	}
	cout << ans;
```
`p[i-1], p[i], [i+1]`の中で`p[i]`が二番目に小さいときは、
`p[i-1] < p[i] < [i+1]` または `p[i+1] < p[i] < [i-1]`の状態ですね。
ループの範囲に注意しながら数え上げました。

## C - Divide the Problems
``` c++
	int n;
	cin >> n;
	vector<int> d(n);
	for(int i = 0; i < n; ++i)
	{
		cin >> d[i];
	}
	sort(d.begin(), d.end());
	cout << d[n / 2] - d[n / 2 - 1];
```
「要素数が同じになるように難易度で2つに分けたい」という問題ですね。
「要素数が同じ」なので、難易度の中央で分けます。
つまり、ソートして、「中央の要素」と「そのひとつ前の要素」の差が答えになります。


## D - Blue and Red Balls
こちらのライブラリを使いました。
https://github.com/atcoder-live/library/blob/master/mint.cpp
https://github.com/atcoder-live/library/blob/master/comb.cpp

``` c++
	int n, k;
	cin >> n >> k;
	cout << n - k + 1 << endl;
	for(int i = 2; i <= k; ++i)
	{
		cout << c(k-1, i-1) * c(n-k+1, i) << endl;
	}
```
ライブラリの関数より、`c(n, k)`で`nCk`のコンビネーションを`O(1)`で計算しています。

青いボールが`k`個
赤いボールが`n-k`個
ですね。

`c(k-1, i-1)`で青、
`c(n-k+1, i)`で赤の組み合わせを計算しています。

この計算について解説します。
B1 を青のボールが1個以上とします。
同様に、
R0 を赤のボールが0個以上
R1 を赤のボールが1個以上とします。

例えば`K=4`のとき、
i=1 : R0 B1 R0
i=2 : R0 B1 R1 B1 R0
i=3 : R0 B1 R1 B1 R1 B1 R0
i=4 : R0 B1 R1 B1 R1 B1 R1 B1 R0
となりますね。
青いボールが`i`箇所に分割されています。
ちなみに`N`の値に関係なくこうなります。

この時、青いボールについては
`k`個あるボールを並べて、その「間」に仕切りを`i-1`個置くのと同じ組み合わせになります。
これは`(k-1) C (i-1)`通りですね。
赤いボールについては、
`n-k`個あるボールを並べて、「外側も含めた」場所に仕切りを`i`個置くのと同じ組み合わせになります。
これは`(n-k+1) C i`通りですね。
この二つを掛け合わせて答えがでます。

以上です。ありがとうございました。
rspec書く時のメモを全部ここに残す

自分の記憶力がアレすぎるので、ここにいろいろ記す。




# 基本的な書き方
```rb
require 'rails_helper'

RSpec.describe XXXX do
  let(:xxx) {xxx}
  describe "#method" do
    subject { xxx.method }

    it 'returns hogehoge' do
      is_expected.to eq(hoge)
      expect(subject.keys).to eq([hoge1, hoge2])
    end
  end
end
```
- `is_expected` = `expect(subject)` である



# 配列の比較

- eq => 並び順と要素
- match => 同上
- match_exactly, match_array => 並び順関係なく要素

# Datatimeの使い方

```rb
Time.now()
Time.new(2019, 5, 26, 23, 0, 0)
Time.zone.local(2019, 12, 13).beginning_of_day
Time.zone.local(2019, 12, 25).end_of_day
```
ノートPCかスマホかタブレットを活用してマルチディスプレイにする

# はじめに

本稿は、リモートワークにて、自宅に複数のディスプレイがなくても、マルチディスプレイでプログラミングする方法の紹介です。

マルチディスプレイの場合、リモートでペアプログラミング/モブプログラミングを実施する際に便利です。
例えば、ナビゲーター役が、画面共有しているディスプレイを見ながら、今プログラミングしている部分に関連する情報のリンクをもう一方のディスプレイからSlackで送るなどできます。

# Windows 10 のノートPCを Miracast で繋ぐ

家に利用していないノートPCがあれば、それを利用してマルチディスプレイにできます。
Windows 10 には、Miracast という Wi-Fi で複数のPCの画面を共有する機能が備わっているため、以下の条件を満たす場合は、これが一番簡単だと思います。

- Wi-Fi環境がある
- Windows 10 のノートPCがある

余っているノートPCが複数あれば、ディプレイを3つにすることも可能です。
詳細な設定手順は、以下の記事を参照ください。
[余ったWindows 10ノートがサブディスプレイに早変わり!](https://pc.watch.impress.co.jp/docs/column/yajiuma-mini-review/1251697.html)

# スマホやタブレットを specedesk で繋ぐ

Android か iOS のスマホかタブレットを Specedesk というアプリを使って、マルチディスプレイにできます。
また、Windows 10 のPCでも、Miracast が利用できないPCもあるので、その場合は、このアプリでマルチディスプレイにできます。
こちらのアプリは、すべてのデバイスが、同じWi-Fiネットワークに接続されていれば利用できます。

アプリのインストールは以下のサイトからできます。
[spacedeskのホームページ](https://spacedesk.net/)

大まかな利用手順を以下に記します。

1. メインで利用するPCに、PRIMAY PC(Server) 向けのアプリをインストールする。
2. サブディスプレイとして利用するデバイスに、プラットフォームごとのアプリをインストールする。
3. サブディスプレイのデバイスで、アプリを起動する。

詳細な手順は以下の記事を参照ください。
[「spacedesk」でマルチディスプレイが無料で高性能、超簡単。タブレット、スマホ、ノートPCが外部画面に](https://cloud-work.jp/productivity/spacedesk/)

私も実際に利用してみましたが、画面の遅延はまったく気になりませんでした。

現実的な運用として、8インチ以上のタブレットなら、かなり使いやすいと思います。
（個人的には、ノートPCを2台並べるよりも、ノートPC＋タブレットの方が、視野を広げなくて済む分、使いやすく感じました）
ノートPC＋8インチタブレットの場合は、下図のような感じになると思います。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403606/072cbe43-7948-a67f-37a0-e5fa8dad59ad.png" width="75%">


# まとめ
自分にあったマルチディスプレイ環境を構築しましょう。

ちなみに、私はLT初心者が集まるコミュニティとして「Serverless LT 初心者向け」というコミュニティを運営しています。
このコミュニティで開催しているLT大会なら、失敗しても大丈夫なので、初めてのLTをやってみようという人は、コミュニティのメンバーにご参加ください。
[Serverless LT 初心者向け - connpass](https://serverlesslt.connpass.com/)

Twitterでも開発に役立つ情報を発信しています → [@kojimadev](https://twitter.com/kojimadev)
bcrypt導入時のエラーたち

#bcrypt導入時のエラー
パスワードを暗号化するためのgem, bcryptを導入する際に起こった、小さなエラーの解決法まとめです

#その1 An error occurred while installing bcrypt, and Bundler cannot continue.
```ruby:Gemfile
gem 'bcrypt'
```
と書き足し、bundle install を実行したところ、
![5A9EC28E-C920-4220-8E26-235FCFFCA819_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429131/03721c09-3698-fc3c-83d3-c18365f5af89.jpeg)
An error occurred while installing bcrypt (3.1.13), and Bundler
cannot continue.
というエラーが発生。
続けて、エラーメッセージ内に書いてある、
gem install bcrypt -v'3.1.13'
を実行したところ、今度はPermission denied が発生

Permissionということはsudoの出番ではないかと下記のコードを実行

```
$ sudo gem install bcrypt
```
これで無事bundle install 時のエラーが消え、bcryptを追加できました！

##その２　cannot load such file -- bcrypt
無事、エラー1を克服し、localhostのブラウザを再起動したにも関わらず、このエラー

そういえば、このような時昔あったなと思い出し、 rails s　を再実行。

すると通りました！！


今回はbcrypt導入時の小さいエラーもろもろでした〜
【vue】トランジションのあらゆるタイミングでjsを走らせる【トランジションフック】

# 概要
トランジションが発生したタイミングでjsを処理させたいときに便利な機能

#例


トランジションの中でも、以下のタイミングでjsの処理をさせてみる。

1. DOMに要素が追加された後(`enter`)
2. トランジションが終わるとき (`after-enter`)

規定に沿ったフック名を`transition`要素に与えることで、各タイミングで処理が走る。

```html:.html
<div id="app">
  <button v-on:click="hook = !hook">hook</button>
  <transition v-on:enter="enter" v-on:after-enter="afterEnter">
    <div v-if="hook">example</div>
  </transition>
</div>
```

```js:.js
new Vue({
  el: '#app',
  data: {
    hook: true
  },
  methods: {
    /*1.DOMに要素が追加された後の処理*/
    enter: function(el, done) {
      console.log('enter')
      setTimeout(done, 1000)
    },
    /*2. トランジションが終わるときの処理*/
    afterEnter: function(el) {
      console.log('after-enter')
    }
  },
})
```

#トランジションのタイミング

トランジションが発生するタイミングとして下記のように分類できる。
- 要素が追加されるとき
- 要素が削除されるとき

さらに細かく分類したときのフック名は以下の通り

###要素が追加されるとき(Enterフェーズ)
1. DOMに要素を追加: `before-enter`
2. `v-enter`を追加: `enter`
3. トランジション終了: `after-enter`
4. Enterフェーズが途中でキャンセル: `enter-cancelled`

###要素が削除されるとき(leaveフェーズ)
1. クラス付与前: `before-leave`
2. `.v-leave`が追加後: `leave`
3. 要素削除後: `after-leave`
4. leaveフェーズが途中でキャンセル: `leave-cancelled`
numpy で画像処理のメモ


## 画像の読み込み, 保存

imageio がよいでしょうか(中身的にはいろんなライブラリを wrap している)

32bit TIFF や, Camera RAW 画像なども読めます.

## 浮動小数点数の精度

デフォルトでは `float64`.
`float32` にしたいときは,`astype('float32')`, `astype(numpy.float32)` などとする.
(`float32` で文字列でも, `numpy.float32` で定数でもどちらでも OK)

## 特定の値で fill する

`full` を使う


## それぞれのチャネルデータから RGB 画像を作る

RGBRGBRGB... とならんだ配列を作りたい.

dstack を使う

https://stackoverflow.com/questions/10443295/combine-3-separate-numpy-arrays-to-an-rgb-image-in-python

```
rgb = numpy.dstack((r, g, b))
```

## RGB 各レイヤの和を取りたい

```
RGB.shape = (3, 512, 512)
```

とする.

`numpy.sum(RGB, 0)` でいける.

## gather, scatter

標準ではないっぽいので自作する

https://stackoverflow.com/questions/46065873/how-to-do-scatter-and-gather-operations-in-numpy

## パターンを作る

`np.tile`

## 配列データをずらす

[1, 2, 3, 4, 5] -> [2, 3, 4, 5, 1] みたいにしたい.

roll を使う.

https://numpy.org/doc/stable/reference/generated/numpy.roll.html

(TODO): zero fill や, クランプしたいときは vstack, hstack がいいのかしら?

## 配列にマスク演算したい

numpy.ma がいけるかしら.

https://numpy.org/doc/stable/reference/maskedarray.baseclass.html#numpy.ma.MaskedArray.mask

マスクした配列同士の or などは無いっぽい.
(=> マスクされた配列(e.g. R だけマスク, G だけマスク)の合成(compisite), とりあえずは `numpy.where` あたりで代用でしょうか)
Heroku上のプログラムが勝手に実行される問題

#問題
[こちらの記事](https://qiita.com/takaya901/items/c75d394c4ad37b1cbd59)でPythonスクリプトをHerokuにデプロイし，schedulerで毎朝9時に実行されるよう設定しました．ところが，schedulerとは別で6時間おきくらいに勝手に実行されてしまいました．
<img width="1292" alt="Screen Shot 2020-06-29 at 16.21.51.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239014/7ce39721-1e2a-6f13-c09d-f34dddc5db2b.jpeg">
schedulerを無効にしてもだめだったので，schedulerの問題ではないようです．
Herokuのdynoは1日1回再起動されるらしいのですが[（Automatic dyno restarts）](https://devcenter.heroku.com/articles/dynos#restarting)，それのせいでしょうか．

#解決方法
ダッシュボードのResourcesで，画像の赤枠の部分がオンになっていたのをオフにしました（画像はオフの状態）．以降は，schedulerからのみ実行されるようになりました．
<img width="1232" alt="Screen Shot 2020-06-29 at 16.24.05.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239014/fa78ea36-edf4-186c-6080-8197008df378.jpeg">

ここをオンにしていると，dynoの起動時に実行されるという感じでしょうか．Procfileの内容がここに出るっぽいので，schedulerのみで実行したい場合は，Procfileはなくていいのかもしれません．
Heroku初心者なので，もし詳しい事情をご存知であればコメントいただけると幸いです．
数値計算用プログラムのための開発環境・備忘録

## 本記事の概要

cを用いた数値計算用プログラムのための環境構築を行う人々の参考になることを目的とし、私の開発環境を紹介します。  
ちなみに私は数値計算を用いた研究を行っている大学院生です。新しいノートPC購入を機に、計算用プログラム開発を一新しました。
個人のメモ的な要素も強く，大変読みにくいですが，ご了承ください．

## 計算環境の概観
### 用意するもの
 - Githubアカウントおよびリポジトリ
 - 計算用サーバー(Linux, gitインストール済)
 - ノートPC(Mac, git, VSCodeインストール済)

### 作業フロー
    ノートPCのVSCodeでコード作成  
    -> Githubへpush  
    -> 計算用サーバからpull (sshを使用)  
    -> 実行スクリプトを回す  (sshを使用)  

#### VSCode: 
前はSublimeを使っていました．()の追跡性能が高く，
Githubとの連携もより便利なので乗り換えました．
VScodeではマークダウンのプレビューもデフォルトで入っているので，
こちらも気に入って使っています．
VSCodeには統合ターミナルも付属しています．
しかし私はターミナルソフトを物色するのが好きなので，
現状では別のターミナルソフトを使用しています．


#### Github:  
Privateリポジトリを使用．
計算サーバーにはネットワークの関係上，
VPN接続ができません．
そこでインターネット経由でクラウドとの同期を行う必要があります．
そこで以上要件を満たすなGithubを選択しました．超初心者なので早く慣れるべく奮闘中です．
パッケージ管理もこちらで行っています．
(↑注）不正コピーソフトを使ったりしてるわけではありません


#### 実行スクリプト:  
汎用市販ソフトウェアのスクリプトを真似して作成しました．
今はすべて自前でコードを作成していますが，
今後はOSSの利用を視野に入れています．


<img width="536" alt="スクリーンショット 2020-06-29 16.44.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197157/0616ad6c-eca4-628d-564e-26fdf5a3af7e.png">
jQueryでさくっとアコーディオンメニューを作る

本当にさくっと作りたい時のメモ用
本当に最低限の動きだけ。

```html:HTML
<div class="js-accordion-toggle">開く</div>
<div class="js-accordion-item" style="display:none;">
　ここにコンテンツが入る
</div>
```
ボタンとなる要素に`.js-accordion-toggle`、開閉したい要素に`.js-accordion-item`を設定。
`display:none;`を直書きしているのはHTMLが一番早く読み込まれるため、CSSやJSに設定を追加するよりも遅延が少なく、コンテンツが一瞬表示されてしまうのを防ぐため。

ページが開いた状態を初期状態にしたい場合は`style="display:none;"`を書かずに`.js-accordion-toggle`に`is-open`クラスを追加しときましょう。


``` js:jQuery
  var $toggle       = $( '.js-accordion-toggle' );
  var $item         = $( '.js-accordion-item' );
  var openClass     = 'is-open';
  var operationText = [ '開く', '閉じる' ];


  $toggle.on( 'click', function() {
    if ( $( this ).hasClass( openClass ) ) {
      $( this ).removeClass( openClass );
      $( this ).next( $item ).slideUp();
      $( this ).text( operationText[0]);
    } else {
      $( this ).addClass( openClass );
      $( this ).next( $item ).slideDown();
      $( this ).text( operationText[1]);
    }
  });

```

クリックした`$toggle`が`is-open`クラスを持っているかどうかを判別し、

* ついていなければ`is-open`を付与し、直下にある`$item`を表示させる。
* ついていれば`is-open`を削除し、直下にある`$item`を非表示にする。


`operationText`はボタンの文言を変更するための文字列のまとまり。

* `is-open`がついていれば`operationText[open]`に格納されている文字列を表示
* ついていなければ`operationText[close]`に格納されている文字列を表示させる。

###完成形

こちらが完成形です。

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="nagomi-753" data-slug-hash="NWxXZea" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="NWxXZea">
  <span>See the Pen <a href="https://codepen.io/nagomi-753/pen/NWxXZea">
  NWxXZea</a> by nagomi-753 (<a href="https://codepen.io/nagomi-753">@nagomi-753</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

以上です。
さっくりアコーディオンさせたい場合のメモでした。
VSCodeにおけるタブの非表示

# VSCodeにおけるタブの非表示

VSCodeでは編集中のファイル名が左部におけるサイドバーおよび上部のタブの両方に表示されています．特にコードの表示範囲を広げるという点において，横長ディスプレイが普及している現代では上部のタブが邪魔です．タブを非表示にする方法を検索しましたが日本語の結果が見当たらなかったので，自分用のメモも兼ねて記録として残すことにしました．


## 設定方法
Presserance > Setting を開くとウィンドウ右上に Open settings (JSON) というアイコンが出てきます．

表示される.jsonファイルに

```java,json
"workbench.editor.showTabs": false  
```
を追記するとタブが非表示になります．

<img width="500" alt="スクリーンショット 2020-06-29 16.13.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197157/5af01b07-6382-76ec-b3a3-779d3646747f.png">
<img width="500" alt="スクリーンショット 2020-06-29 16.16.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197157/334bba2d-abf8-2436-f10e-ebd1e0489864.png">



## 注意点
この方法でタブを非表示している場合，他の設定（Show status barなど）を適用できなくなります．
（設定変更時に右下にエラーメッセージが出てくるようになります．）

この場合，jsonファイルにおいて上記手順で追記した行をコメントアウトします．
この状態で他の設定（Show status barなど）を適用し，この後，サイドタブを消すようにしています．

この問題を解決できる方はコメント頂けると幸いです．

## 参考
[How do I disable tabs in Visual Studio Code?](https://stackoverflow.com/questions/38147154/how-do-i-disable-tabs-in-visual-studio-code)
PowerShellでヘッダーにGitの情報から自動的に作成日時と変更日時を挿入してみた

# 動機
大量の .h ファイルと .cpp ファイルに以下のようなヘッダーを挿入しなければいけない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539095/3c6c8afe-f875-a233-b1a2-9aff184b0364.png)
140ファイル近くあるソースコードのヘッダーに手作業で日付を入れるのは無理だと考えた。

## ヘッダーを入れるためには？
今回ヘッダーを全ソースファイルに挿入するために Visual Studio の拡張機能の [License Header Manager](https://marketplace.visualstudio.com/items?itemName=StefanWenig.LicenseHeaderManager) を使用した。

以下のテンプレートファイルを作成した。あとで置き換えるためにプレイスホルダー `${created_date}` と `${modified_date}` を作成した。
(なお、`${ydeagames}` は後で名前に置き換える予定だ。)

```3DShootingGame.licenseheader
extensions: designer.cs generated.cs
extensions: .cs .cpp .h
// Copyright (c) 2019-2020 ydeagames
// Released under the MIT license
// https://github.com/ydeagames/3DShootingGame/blob/master/LICENSE
//
// Author: ${ydeagames}
// Created: ${created_date}
// Modified: ${modified_date}
```
プロジェクトを右クリックして `License Headers > Add License Headers to All Files` を選ぶことですべてのファイルにヘッダーを挿入できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539095/cbdf2d50-fe82-6d61-4c52-96a2434d88e4.png)

## プレイスホルダーを日付に置き換えよう
今回置き換えるために比較的簡単な、PowerShell を採用した。

Gitでのファイルの作成日は

```powershell
git log --diff-filter=A --follow --pretty="format:%ci" -1 -- $file.Path
```
最終変更日は

```powershell
git log -1 --pretty="format:%ci" $file.Path
```
で取得できる。

ソリューションがあるフォルダに PowerShellのバッチファイルである `.ps1` ファイルを作成した。

### 作成日時置き換え
```powershell:ReplaceCreationDate.ps1
$sel = '\${' + 'created_date' + '}' # 置き換える対象

# 対象を含むファイルをループ
foreach ($file in Get-ChildItem . * -Recurse -Force | Select-String $sel -casesensitive)
{
    Write-Host "Processing " -ForegroundColor Red -NoNewline
    Write-Host $file.Path
    # Gitの作成日時を取得
    $gitCreated = git log --diff-filter=A --follow --pretty="format:%ci" -1 -- $file.Path
    Write-Host 'Created: ' + $gitCreated
    ((Get-Content -path $file.Path -Raw) -replace $sel,$gitCreated) | Set-Content -Path $file.Path
}
```
### 変更日時置き換え
```powershell:ReplaceModifiedDate.ps1
$sel = '\${' + 'modified_date' + '}' # 置き換える対象

# 対象を含むファイルをループ
foreach ($file in Get-ChildItem . * -Recurse -Force | Select-String $sel -casesensitive)
{
    Write-Host "Processing " -ForegroundColor Red -NoNewline
    Write-Host $file.Path
    # Gitの変更日時を取得
    $gitModified = git log -1 --pretty="format:%ci" $file.Path
    Write-Host 'Modified: ' + $gitModified
    ((Get-Content -path $file.Path -Raw) -replace $sel,$gitModified) | Set-Content -Path $file.Path
}
```

プレイスホルダーを日付に置き換えることができた。めでたしめでたし。
[漏洞通告]CVE-2765-2020/jackson-databind JNDI注入导致远程代码执行

### 漏洞描述
近日,亚信安全网络攻防实验室跟踪到`jackson-databind`更新了1个jndi注入的黑名单类.如果在项目包中存在该类的jar包且JDK版本满足注入版本,则可以使用JNDI注入的方式导致远程代码执行.类名为`org.jsecurity.realm.jndi.JndiRealmFactory`.

### 漏洞编号
CVE-2765-2020

### 漏洞威胁等级
中危

### 不受影响范围
jackson-databind >= 2.11.1

### 漏洞验证
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/dbd6ece3-3236-4e0d-af13-9da5f40623f9.png)


### 修复建议
参照官方更新至最新版

### 时间轴
[0] 2020/06/29 亚信安全网络攻防实验室分析&复现该漏洞并发布漏洞通告

### Reference
https://github.com/FasterXML/jackson-databind/issues/2764
Rustを5行でセグフォらせる

Pythonで流行ってる[^1]らしいのでRustでやってみました。

```rust:main.rs
fn main() {
    unsafe {
        *(0x012345 as *mut i32) = 0x0000;
    }
}
```

## コードゴルフ風

```rust:main.rs
fn main(){unsafe{*(1 as*mut _)=0}}
```

## 結論

- システムズプログラミング言語なので簡単に出来て当たり前。
- Rustは明示的に非安全なコードを書けるのでデバッグフレンドリー

これより簡単または最短コードがあれば教えてください。

[^1]:
  - [pythonを三行でセグフォらせる](https://qiita.com/autotaker1984/items/a8ba955acdc81c907b3d)
  - [pythonを2行でセグフォらせる](https://qiita.com/sh1ma/items/a6dd1bcca0d9725e7e67)
  - [pythonを1行でセグフォらせる](https://qiita.com/MysteriousMonkey/items/0e389ccdc12988dd4263)
  - [Pythonを33文字でセグフォらせる](https://qiita.com/kanimum/items/95a45d8be31ef75d4332)
[漏洞通告]CVE-2020-1948/Apache Dubbo Provider存在远程代码执行

### 漏洞描述
2020年2月22日,亚信安全网络攻防实验室跟踪到`Apache Dubbo Provider`某些协议存在远程代码执行漏洞.攻击者可以通过RPC请求发送无法识别的序列化数据,当恶意参数被反序列化时,可以造成远程代码执行.

### 漏洞编号
CVE-2020-1948

### 漏洞威胁等级
高危

### 影响范围
2.7.0 <= Apache Dubbo <= 2.7.6
2.6.0 <= Apache Dubbo <= 2.6.7
Apache Dubbo <= 2.5.x(官方不再维护)

### 漏洞验证
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/e56a1a89-ec67-b947-2939-186448e50840.png)


### 修复建议
1.建议升级到官方最新版本
2.该端口勿对互联网开放

###时间轴
[0] 2020/02/11 threedr3am在先知社区公开该漏洞详情
[1] 2020/02/12 亚信安全安全研究员——清水川崎发布概念验证视频
[2] 2020/06/29 亚信安全网络攻防实验室分析&复现该漏洞并发布漏洞通告

### Reference
https://xz.aliyun.com/t/7235#toc-4
SSH接続について

# ssh 接続する際の注意点，手順

1. .ssh の隠しフォルダに移動
   ```
   ~
   ❯❯❯ cd .ssh
   ```
2. 鍵を作成

   ```
   ~/.ssh
   ❯❯❯ ssh-keygen
   ```

   この際，passphrase を作成せずに return を 3 回押す．

3. 鍵をコピー

   ```
   ~/.ssh
   ❯❯❯ cat id_rsa.pub
   ```

   出力されたものをコピー．

4. ssh 接続先に移動

   ```
   ssh hoge@bar
   ```

   ここで求められるパスワードは ssh 接続先のユーザ登録したときのもの．

5. .ssh の隠しフォルダに移動
   ```
   cd .ssh
   ```
6. key を登録
   ```
   emacs authorized_keys
   ```
   コピーした key を貼り付け．

## これで，パスワードなしで，ssh 接続できるようになった．

## 注意

### ssh-keygen する度に key は変わってしまうので，すでに github 等に登録してた場合は，再度登録し直す．
UbuntuでAppImageをインストール

```
chmod a+x UnityHub.AppImage
./UnityHub.AppImage
```

## UnityカスタムVersionをインストールの方法
https://unity3d.com/get-unity/download/archive
Unity Hubのリンクをコピーして

```
./UnityHub.AppImage　unityhub://xxxx.x.xxf1/xxxxxxxxxxxxx
```

## 古いプロジェクトをAddできない?
Create New Project で一回を実行する
普通にAddできる!
【Javascript】ワンライナーで現在時刻をフォーマットした日付で表示する

getDay()、getHours()とかやってから繋げるのめんどくさい:confounded:

## コード:writing_hand:
```javascript:ワンライナー
new Date().toLocaleString(undefined, { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" });
```

```javascript:↑改行するとこう
new Date().toLocaleString(undefined, {
  month: "short",
  day: "numeric",
  hour: "2-digit",
  minute: "2-digit"
});
```

```:結果
8月10日 19:19
```

### 別のやり方
```
new Intl.DateTimeFormat(undefined, { [ここにオプション] }).format(new Date());
```

## 使い方
```
dateObj.toLocaleString([locales[, options]])
```
詳細：[Date.prototype.toLocaleString()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString)

- locales "ja"とかが入ります。undefinedなら、OSのデフォルトです
- options フォーマットを指定できます(自由度は低い)。[詳しくはMDNで](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat)

※ localesが日本だと"2-digit"で表示されないことがあります:innocent:

## まとめ
moment.jsのが楽です:hugging:
Rails のscaffoldってなに？

Railsの記事を見ると、`scaffold`というジェネレーターを使用して
モデルからビューまで一括で作成してます。
スクールでは個別に作成するよう学んだので、違いを調べてアウトプットしました。

# 今までの方法

例えば`Book`のモデル・コントローラ・ビューを作成する場合は以下のように実行していました。

```:ターミナル
$ rails g model Book title:string introduction:text 
$ rails db:migrate
$ rails g controller Books index show new edit
```

そして最後にルーティングを設定するまでが一連の流れです。

```rails:config/routes.rb
Rails.application.routes.draw do
  resources :books 　#ここを追加
end
```


# scaffoldを使用してみると

同様の内容で作成する場合、`scaffold`を使用すればこれだけで済んでしまいます。
(おまけに各ビューには簡単なフォーム、部分テンプレートまで用意されています。)

```:ターミナル
$ rails g scaffold Book title:string introduction:text
$ rails db:migrate
```

# 最後に

`scaffold`とは『土台』との意味で、それを全部組み立てるのが、この手法とのことです。
確かに基礎を十分に理解していれば便利ですが、最初からこれで覚えてしまうとMVCの理解も
出来ないままになりますね。

今までは見たこと無い方法だと思ってビビって使えませんでしたが、
ある意味良かったかもです。(笑)
今後は理解を深めて積極的に使用してみます。
[漏洞通告]Fastjson <= 1.2.68存在远程代码执行漏洞

### 漏洞描述
近日,亚信安全网络攻防实验室跟踪到`Fastjson <= 1.2.68`存在远程代码执行漏洞.可在未开启`autotype`开关的情况下被利用,以至于可直接获取服务器权限.

### 漏洞编号
无

### 漏洞威胁等级
高危

### 影响范围
Fastjson <= 1.2.68

### 漏洞验证
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491410/5c654325-d5c9-6c13-5acd-9bc48b3c7f5f.png)


### 修复建议
1.建议升级到官方最新版本
2.建议配置以下参数开启`SafeMode`来防护攻击： 
`ParserConfig.getGlobalInstance().setSafeMode(true);`
#### 注意:一旦开启`safeMode`会完全禁用`autotype`,无视白名单,可能会影响业务连续性.


### 时间轴
[0] 2020/05/18 腾讯云发布漏洞通告
[1] 2020/06/29 亚信安全网络攻防实验室分析&复现该漏洞并发布漏洞通告

### Reference
https://cloud.tencent.com/announce/detail/1112?from=timeline&isappinstalled=0
ログインエラー

ログインボタンを設定し、ホームからログインに飛ばなくて困っています。
エラーは
NameError in Staff::SessionsController#new
undefined method `rescue500' for class `#<Class:#<Staff::SessionsController:0x00007faea4837e30>>' Did you mean? rescue rescuer
Extracted source (around line #106):
              
        case rescuer = find_rescue_handler(exception)
        when Symbol
          method = object.method(rescuer)
          if method.arity == 0
            -> e { method.call }
          else

で、
自身の書いたRoutes.rbは次の通りです。
以前、同じエラーが出た時は、
全く違う箇所の小さなスペルミスだったのですが、
何度見直しても誤記は見つけられません。
ルートが間違っているのでしょうか？？


Rails.application.routes.draw do
  config = Rails.application.config.baukis2

  constraints host: config[ :staff ][ :host ] do
    namespace :staff, path: config[ :staff ][ :path ] do
      root "top#index"
      get "login" => "sessions#new", as: :login
      resources :session, only: [ :create, :destroy ]
      resources :account, except: [ :new, :create, :destroy ]
    end
  end

  constraints host: config[ :admin ][ :host ] do  
    namespace :admin, path: config[ :admin ][ :path ] do
      root "top#index"
      get "login" => "sessions#new", as: :login
      resources :session, only: [ :create, :destroy ]
      resources :staff_members
    end
  end

  constraints host: config[ :customer ][ :host ] do
    namespace :customer, path: config[ :customer ][ :path ] do
      root "top#index"
    end
  end
end
M5StickVでAprilTagを認識する

#ソースコード
```boot.py
import sensor
import image
import lcd
import time


clock = time.clock()

lcd.init()
lcd.rotation(2)

sensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)

sensor.set_framesize(sensor.QVGA)
sensor.set_windowing((0, 40, 320, 200))
sensor.set_brightness(-3)
sensor.set_vflip(0)
sensor.set_hmirror(0)
sensor.skip_frames(30)
sensor.run(1)

while True:
    clock.tick()
    img = sensor.snapshot()
    try:
        iterater = img.find_apriltags()
        if len(iterater) > 0:
            for tag in iterater:
                print(tag)
        lcd.display(img)
    except Exception as e:
        print(e)

```

こういうのってなんとなくグレースケールでとるのが一般的な気がするので、

```python
sensor.set_pixformat(sensor.GRAYSCALE)
```

としている。
カラーとどっちが認識率が高いのかは比較していないです。
また、micropython環境でのfind_apriltags()が、64000pixelまでしか対応してないらしいので、

```python
sensor.set_framesize(sensor.QVGA)
sensor.set_windowing((0, 40, 320, 200))
```

として、QVGA画像から真ん中を切り出している。
ただ、set_windowing()の与えるtupleの最初の二つの値は効いていないようで、どんな値を渡しても、(0, 0)からの切り取りになる。。

また、画面を反転したり回転させたりしているところ

```python
sensor.set_vflip(0)
sensor.set_hmirror(0)
```
ここに関しては、M5StickVとUnutVで挙動が違う可能性があるので注意。
現状だとすべてのタグに対して検索がかかるが、

```python
find_apriltags(families=image.TAG16H5)
```

などとして指定すれば、検出するtagfamilyを指定できる。
順列 C#

順列 C#

```c#
using System;
using System.Collections.Generic;

namespace Permutation
{
	class Program
	{
		static void Main(string[] args)
		{
			new Program();
		}

		public Program()
		{
			List<int> data = new List<int> { 1, 2, 3, 4 };
			List<List<int>> perm = GetPermutation(data);
			foreach (List<int> p in perm) {
				Console.WriteLine(string.Join(",", p));
			}
		}

		private List<List<int>> GetPermutation(List<int> data)
		{
			List<List<int>> perm = new List<List<int>>();
			if (data.Count == 0) {
				perm.Add(data);
				return perm;
			}

			for (int i = 0; i < data.Count; i++) {
				int head = data[i];

				List<int> dataCopy = new List<int>(data);
				dataCopy.RemoveAt(i);
				List<List<int>> childPerm = GetPermutation(dataCopy);
				foreach (List<int> child in childPerm) {
					child.Insert(0, head);
					perm.Add(child);
				}
			}
			return perm;
		}
	}
}
CKA受験メモ

2020/6/25 にCKA (Certified Kubernetes Administrator) を受験し無事合格しました!
スコアは 98/100 でほぼ満点でした(全部合ってる自信あったのですが、なにか微妙に違っていた模様。。。)

受験にあたってのメモを公開しておきます。といっても受験体験記はたくさんネット上にあるので重複する内容はできるだけ避け、重複しないような内容だけメモしておこうと思います。

なお、学習する際の教材としては Udemy の[Certified Kubernetes Administrator (CKA) with Practice Tests](https://www.udemy.com/course/certified-kubernetes-administrator-with-practice-tests/) がイチオシです。とりあえずこれだけ(特に Mock Exam)やっとけばほぼ大丈夫。

# JSONPath
[JSONPath](https://kubernetes.io/docs/reference/kubectl/jsonpath/)は意外と見落としがちですが、結構使うのでちゃんと覚えておきましょう。
Udemy のコースには Section 14 Other Topics にちゃんと入っています。

# Kubernetes バージョン
2020/6時点の CKA で使用される Kubernetesのバージョンは 1.18 になっています。

上記の Udemy のコースで使用されている Kubernetes のバージョンは 1.16 あたりなのでちょっと古いです。

特に注意が必要なのは、`kubectl run` の挙動の違いです。1.17以前は `kubectl run` はデフォルトで Deployment を作るようになっていて Pod を作る場合は `--generator=run-pod/v1` または `--restart=Never` をつける必要がありました。1.18以降は `kubectl run` はPod しか作れないようになっていて、Deployment を作るときは `kubectl create deployment` としなければならないので、注意が必要です。

# root権限
上の Udemy で使っているコンソールはすべて root 権限で動作するようになっていましたが、CKAの環境は一般ユーザになっており、適宜 sudo しなければなりません (これは Handbook に書いてある)。

特に root でないと書き込めない領域にリダイレクトが必要な場合はちょっと注意が必要です。`sudo kubectl ... > /file` としてもだめです。`kubectl ... | sudo tee /file` みたいにしないといけません。Linuxに慣れていればこの程度は常識ですが、時間が限られているので焦るかもしれません。

# alias
とりあえず `alias k=kubectl` だけは補完含めやっておいたほうが良いです。alias と補完の設定は [kubectl Cheat Sheet](https://kubernetes.io/docs/reference/kubectl/cheatsheet/)にあるので、試験開始直後に設定しておくのがおすすめです (本ページも当然ブックマークしておく)

逆に上記以外の alias は無くて良いと思います。普段使いの alias があるなら設定してもいいと思いますが、試験のためだけに新たに alias 覚えるのは無駄です。

# vim設定
私は Emacser なのですが、試験環境で Emacs の環境設定をしていたら日が暮れてしまうので、vim を使いました。ネットから dotfile を引っ張ってくるのは当然駄目です。

vim は管理業務ではたまに使うくらいであまり使いこなしてなかったので、ある程度は使えるように習熟しておきました。

vimの設定ファイルについてはもちろん試験環境には何も設定されていないので、最低限の設定を暗記しておいて、試験開始したら ~/.vimrc に書いておく必要があります。私が設定した内容は以下の通りです。

```
set smartindent expandtab ts=2 sw=2
set number relativenumber
```
# tmux設定

コンソールは１枚しか使えないので、複数端末使いたければ tmux(またはscreen)を使う必要があります。ただ正直言うと、試験中に tmux を使う機会はあんまりないです。1問だけ複数マシンにログインして作業したので使いましたが。

tmux の設定も当然ないので、必要なら覚えておく必要があります。私は ~/.tmux.conf に以下のように設定しました。プレフィクスの設定だけですね。

```
set -g prefix C-j
unbind C-b
```

# Mac を使う
受験時には Windows ではなく Mac (Mac mini 2018) を使いました。

Windows でもいいんですが、コンソール内で使用するキーバインドがブラウザのショートカットとぶつかったりしがちです。特に Ctrl-W がタブを閉じるショートカットになっていて、bash の前ワード削除と被っているので、うっかりタブを閉じてしまう危険性があります。
Mac だとブラウザで使うショートカットは Cmd との組み合わせになっているので Ctrlキーバインドとぶつからず気が楽です。コピー&ペーストも Cmd + C / Cmd + V が使えます。

# kubeadm
kubeadm を使ったシングルクラスターの構築はきちんとできるようになっておきましょう。

# Score Report
Score Report は試験終了後 36 時間以内に来ます。

。。。ということになっているのですが、遅れることもあるようです。気長に待ちましょう。私の場合はまる４日(96時間)かかりました。。。