OmniAICreator/Qiita-1.07M huggingface dataset:
【Android 9.0 Pie Java】RecyclerView 長押しで要素毎に内容の変わるコンテキストメニューを表示する

RecyclerViewで要素を長押しして、要素毎に内容の変わるコンテキストメニューを表示する方法の記事が見当たらなかったのでメモしてみます！

↓完成イメージ↓
![7c30d4aa9804094e0e83ddb1b9247cb8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285286/85bfd135-43e4-7a80-315c-c2ee6e4e2fd7.gif)

## 実装方法
### コンテキストメニューの表示
Activity or Fragmentに

```
View.OnCreateContextMenuListener
```
をimplementsします。

```java:SampleFragment.java
public class SampleFragment extends Fragment
        implements View.OnCreateContextMenuListener {
```
他にもViewHolderにimplementsするパターンもありますが、
コンテキストメニューを要素毎に内容を出し分けしたくて、都合のよかったFragmentにimplementsしました。

次に、RecyclerViewを生成をしているonCreatedViewメソッドで

```java:SampleFragment.java
RecyclerView rv = view.findViewById(R.id.recyclerView);

// Adapter等のアタッチは省略します

registerForContextMenu(rv); // 追記
```
を追記します。
`registerForContextMenu`はView.OnCreateContextMenuListenerをimplementsすることで呼び出せるようになります。
この記述でコンテキストメニューを認識させることができます。

続いて、Fragmentに`onCreateContextMenu`を実装します。

```java:SampleFragment.java
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        // 長押しされたメッセージ位置を取得し、
        // RecyclerViewで表示させているListのindexとして扱い、
        // ユーザーIDを取得してメニューの出し分けを実現
        if (list.get(adapter.getPosition()).getUserId() == loginUserId) {
            menu.add(Menu.NONE, 1, Menu.NONE, "コピー");
            menu.add(Menu.NONE, 2, Menu.NONE, "編集");
            menu.add(Menu.NONE, 3, Menu.NONE, "削除");
        } else {
            menu.add(Menu.NONE, 1, Menu.NONE, "コピー");
        }
    }
```
ContextMenuオブジェクトに追加したい内容をaddする形で簡単に項目を追加できます。
addメソッドの第二引数に数値をセットしていますが、これは押された際のリスナーのハンドリングで使用します。
参考程度ですが、Adapterに以下の要領で`getPosition()`メソッドを用意して、長押しされた要素の位置を取得できるようにしています。

```java:Adapter.java
    @Override
    public void onBindViewHolder(final ChatViewHolder holder, int position) {

        // 省略

        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                setPosition(holder.getPosition());
                return false;
            }
        });
    }

    // 長押しされた要素の位置を取得する
    public int getPosition() {
        return position;
    }

    // 長押しされた要素の位置をセットする
    public void setPosition(int position) {
        this.position = position;
    }

```

ここまでの実装でコンテキストメニューは表示できます。

### コンテキストメニューのイベントリスナー
以下のように、`onContextItemSelected`を実装し、中でswitch文を用いてハンドリングします。
MenuItem.getItemId()で先ほど登録した各要素の判別用の数値が取得できますので、
switch文で振り分ける感じですね。

```SampleFragment.java
    @Override
    public boolean onContextItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case 1:
                // TODO メッセージをクリップボードにコピー
                return true;
            case 2:
                // TODO メッセージを編集
                return true;
            case 3:
                // TODO メッセージを削除
                return true;
            default:
                return false;
        }
    }
```

以上です。

どなたかの参考になりましたら幸いです！！
GitHubに自動コミット&プッシュするシェルスクリプト

# 作成目的
エンジニアを目指している方なら分かると思いますが、企業側はGitHubの草の生え方を見て「学習しているのか？」を確認します。
GitHubの草が全てではないですが、「草が生えている＝勉強している」となり、とてもいい印象を与えます。(他にもQiitaの投稿、ブログへのアウトプット記事もいい印象を与えます。)


`毎日ポートフォリオ作りに励んでいるが、毎日プッシュしないので草が生えない。けど、草を生やしたい`
と思っている方に向けて作成しました。

毎日コミット&プッシュをするとこんな感じに生えます。
これを目指しましょー！！
![スクリーンショット 2020-08-30 7.32.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520383/69828927-e774-19f6-cd41-e507514d3abc.png)


# 完成までの流れ
>1.作成しているポートフォリオをGitHubのリポジトリの管理下に置く
>(この作業は本記事では省略します。)
>2.シェルスクリプト作成
>3.cronで定期実行設定

上記の流れですが、1.の説明は省略して2.から説明します。

# 2.シェルスクリプト作成

GitHubのリポジトリの管理下に置いているポートフォリオが『PostBlog』だと仮定して話を進めていきます。

```ruby:shellscript/automatic_commit
#!/bin/bash
##########################################################
#概要 :PostBlogのshow.html.erbファイルの最終行に改行コードを挿入。
#      挿入後、コミット&プッシュを実行
##########################################################
#--------------------------------------------------------------
#変数宣言
#--------------------------------------------------------------
#ルートディレクトリ〜PostBlogまでの絶対パスを記載(自分の環境に合わせて変更してください)
DIR="${HOME}/Ruby/projects/PostBlog"  
#PostBlog〜改行を入れるファイルまでのパスを記載(自分の環境に合わせて変更してください)  
newline_file="/app/views/users/show.html.erb"

#--------------------------------------------------------------
#改行付加
#--------------------------------------------------------------
#${HOME}/Ruby/projects/PostBlog/app/views/users/show.html.erbの最終行に改行を挿入
echo "" >>$DIR$newline_file

#--------------------------------------------------------------
#GitHubにコミット&プッシュ
#--------------------------------------------------------------
cd $DIR
git add .
git commit -m"最終行に改行を挿入"
git push origin master
```

シェルスクリプトは完成！！
試しに実行してみたい方はこちらを実行

```ruby:shellscript
$./automatic_commit
```

# 3.cronで定期実行設定
作成したシェルスクリプトを定期実行する様に設定をしたら完成となります。
毎日12時にシェルスクリプトが実行される様に設定していきます。

```ruby:
#cron設定を開く
$crontab -e
```

![スクリーンショット 2020-08-30 9.21.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520383/8c0fcbbe-1fca-466c-2a9e-2425493a67dd.png)

iでインサートモードに変更してcronを設定していきます。

![スクリーンショット 2020-08-30 9.25.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520383/6bd0dc69-3b47-0b6d-f831-82eddfd85cd6.png)

設定後、`escキー押して:wqで保存終了`

```ruby:詳細
# (分)(時)(日)(月)(曜日) 実行するコマンドのパス
```

設定確認

```ruby:
$crontab -l
00 12 * * * bash ./shellscript/automatic_commit
```

設定されていたら完成！！！！
pythonでデータ分析2

##pythonでデータ分析のつづき：初心者ですが
***
データの読み込み
`train = pd.read_csv("train.csv")`
***
データの中身を見る
`train.head()`
***
データの行数・列数を見る
`train.shape`
***
yの平均値と中央値を見る
`train["y"].mean()`
`train["y"].median()`
***
trainのyの折れ線グラフを描いてみまる
`train["y"].plot()`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282938/44d5a316-dacf-760d-20a3-54b207567eb8.png)
codamaをRaspberry pi 3B+でセットアップする時の注意点

# はじめに
codamaは[ユカイ工学が販売している音声コミュニケーション開発キット](https://codama.ux-xu.com/)です。
自由にウェイクアップ・ワードを設定でき、ノイズに強い録音ができます。
久しぶりRaspberry pi 3B+でつかってみようと、セットアップを進めてみたのですが、つまずいたポイントがあったので、その解決方法について書きたいと思います。

[公式のセットアップ方法](https://github.com/YUKAI/codama-doc-r0/wiki/Raspberry-Pi-Setup)はこちらに記載されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212276/233c454e-2baf-854e-734f-f63ffbe5d8f8.png)

# セットアップ
# Raspberry pi 3B+の準備
Raspberry pi 3B+にOSを書き込む時に最新のものを使わないようにしましょう。
今回は、[2020-02-13-raspbian-buster.img]
(http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian/images/raspbian-2020-02-14/)をダウンロードし、[Rasberry Pi Imager](https://www.raspberrypi.org/downloads/)でmicroSDカードに書き込みを行いました。
手順としては、
1.[2020-02-13-raspbian-buster.img]
(http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian/images/raspbian-2020-02-14/)をリンクからzipでダウンロードして展開。
2.Rasberry Pi Imagerを起動して下記のように書き込むOSと書き込み先を選択して「Write」をおすと、OSの書き込みが始まります。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212276/93470973-518b-2a62-29cb-8b7061a65645.png)


# 最新のOSを避ける理由
rasberry-kernel-headersのバージョンが新しすぎると、[セットアップ手順最後](https://github.com/YUKAI/codama-doc-r0/wiki/Codama-Setup)の

```
./setup.sh
```

でエラーがでます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212276/99320a34-c8ce-7e56-a33b-4e6fc6916e6d.png)

![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212276/71dc1555-e057-c868-44ac-07fce39f6052.png)

なので最新のOSを使わず、さらには、[Raspberry Piの設定ガイド](https://github.com/YUKAI/codama-doc-r0/wiki/Raspberry-Pi-Setup)にある

```
sudo apt-get install --reinstall raspberrypi-bootloader raspberrypi-kernel
```


こちらのコマンド実行しないようにしましょう。
rasberry-kernel-headersが新しくなりすぎて上記のようにセットアップに失敗します。。
少なくとも、上記の写真中のlinux-headers-5.4.51-v7+ではセットアップが失敗し、linux-headers-4.19.97-v7+ではセットアップに成功します。

セットアップに成功すると下記のようになります。
説明にもあったように、

```
arecord -l
```

で

```
card 0: sndrpisimplecar [snd_rpi_simple_card], device 0: simple-card_codec_link snd-soc-dummy-dai-0 [simple-card_codec_link snd-soc-dummy-dai-0]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
```

と表示されcodamaがRaspberry pi 3B+で認識されていることがわかりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212276/1906b02d-317a-5165-3bf5-5aff8109e73b.png)


# まとめ
まとめですが、codamaのセットアップで上手くいかない時は最新のOSとrasberry-kernel-headersを避けましょう。

引き続き、codamaでgoogle assitanceを使えるようにセットアップを進めます。

# 参考
Raspberry piをつかうときに、ディスプレーやマウス、キーボードを用意できないときはこちらのやりかたが参考になります。
[ラズパイをディスプレイや有線LANなしで初期設定する](https://qiita.com/atsuto/items/9c65a560b7c5e4cb45d6)
Angularにおけるnullとundefinedの使い分け

# 課題
Javascriptにおいて、nullとundefinedはど扱っていけばいいのか。ということは考えていきたい。

nullとundefinedの詳細な違いは[こちら](https://qiita.com/shuhei/items/199281e07925d24059d5#:~:text=null%20%E3%81%AF%E4%BD%95%E3%81%8B%E3%82%92,%E3%81%AA%E3%81%A9%E3%81%AF%E5%85%A8%E3%81%A6%20undefined%20%E3%81%A7%E3%81%99%E3%80%82)を見ればわかるだろう。

# 注目ポイント
Angularは、webアプリケーションで、結局はviewとして表現していくために存在するもの。nullとundefinedもその観点において違いを書いてみる。

# undefinedの使い方
undefinedは**何もない**状態である。この何もないというのは、実行時に値がないということだけではなく、**永続機関から取得するものがない**ということである。Angularでおなじみの、AngularFirestoreを使って例を出す。

## コード例と説明

```typescript
getByID$(account_id: string) {
    return this.firestore.collection<Account>('accounts').doc<Account>(account_id).valueChanges();
  }
```

上記のvalueChanges()で返される型は、`Observable<Account | undefined>`である。undefinedは、angular firestoreのdataを検索したときに、データベースに存在しなかったときに返される。このように、永続期間にデータとして存在しない時にundefinedを使うという事をしたほうがよい。

# nullの使い方
undefinedは**何もない**状態である。この何もないというのは、実行時に値がないということだけではなく、**永続機関からまだ値が返ってこない**ということである。わかりやすくいうと、Loading状態である。Angularでおなじみの、AngularFirestoreを使って例を出す。

## コード例と説明

```typescript
const account$ = 
    return this.firestore.collection<Account>('accounts').doc<Account>(this.account_id).valueChanges();
  }
```

```html
<component [account]="account$ | async"></component>
```

typescript上で定義されたObservableをasync pipe(詳しくは[こちら](https://qiita.com/ryuseikurata/items/43d16cdbe697880ee55b))を通してcomponentに値を流すことで、初期値はnull状態になる(詳しくは[こちら](https://blog.lacolaco.net/2020/02/async-pipe-initial-null-problem/))。つまり、componentのaccountは、`Observable<Account> | undefined | null>`となる。初期値がnullになることで、Loading状態を作り出す事ができるのである。

# 使い分けのメリット
Componentの状態を細かく出し分けする事ができる。現代のアプリケーションでは、UXが重要項目の一つにあり、一つのUIでも、UIStack(詳しくは[こちら](https://note.com/nowim/n/n185d63cfda5c))を定義していかねばならない（はず）。非同期データを扱うUIになると、**データがない状態**、**Loading中**であるStackを表現することは必須となる。上記の使い分けをすることで、それぞれのStackのUIを**一つのComponent**に閉じ込める事ができ、非常に保守性の高いアプリケーション開発を行う事ができるのである。

## 例

### 値を取得
```typescript
const account$ = 
    return this.firestore.collection<Account>('accounts').doc<Account>(this.account_id).valueChanges();
  }
```

### 親Component
```html
<component [account]="account$ | async"></component>
```

### 子Component

```html
<ng-container *ngIf="account; else noValue">
  <account></account>
</ng-container>
<ng-template #noValue>
  <!---永続期間にデータが存在しなかった時に表示-->
  <ng-container *ngIf="account === undefined; else loading">
    <not-found></not-found>
  </ng-container>
  <!---Loading中の時に表示--->
  <ng-template #loading>
    <loading></loading>
  <ng-template>
</ng-template>
```


# まとめ
以上は私が実際にアプリケーションを開発をしてきた上で整理された事項である。また、必ずしも正しくはなく、nullとundefinedの使い分けも千差万別かと思われる。何かしらの参考になれば幸いである。


# 参考リンク
- [nullとundefinedの違い](https://qiita.com/shuhei/items/199281e07925d24059d5#:~:text=null%20%E3%81%AF%E4%BD%95%E3%81%8B%E3%82%92,%E3%81%AA%E3%81%A9%E3%81%AF%E5%85%A8%E3%81%A6%20undefined%20%E3%81%A7%E3%81%99%E3%80%82/)
- [初期値null問題](https://blog.lacolaco.net/2020/02/async-pipe-initial-null-problem/)
- [UIStackとは](https://note.com/nowim/n/n185d63cfda5c)
Makefile で作成されたプログラムに対して Sourcetrail で解析する

# Makefile で作成されたプログラムに対して Sourcetrail で解析する

[Sourcetrail](https://www.sourcetrail.com/) を使って Makefile でビルドするプロジェクトの解析方法を説明します。

## 入手方法

最新版は
https://github.com/CoatiSoftware/Sourcetrail/releases/latest
からダウンロードできます。


## プロジェクト作成方法

[プロジェクト作成方法](https://www.sourcetrail.com/documentation/#CreatingaNewProject) にはいくつかありますが、よく使うのは compile_commands.json を使う方法、Windows なら Visual Studio のプロジェクトから作る方法があります。このページでは `Makefile` から `compile_commands.json` を生成して、[Sourcetrail](https://www.sourcetrail.com/) のプロジェクトを生成する方法を説明します。

## compile_commands.json を生成する方法

### cmake を使うプロジェクトの場合

[cmake](https://cmake.org/) で作成されたプロジェクトの場合 https://www.sourcetrail.com/documentation/#CreatingaNewProject にも記載されているように 

```
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=1 <ソースコードのパス>
```

というように実行するとカレントディレクトリに `compile_commands.json` を生成してくれるのでそれを利用できます。
※ https://www.sourcetrail.com/documentation/#CreatingaNewProject によるとVisual Studio 用の Generator を使用した場合は `CMAKE_EXPORT_COMPILE_COMMANDS` は使えないらしいです。(未確認)

### `Makefile` を使うプロジェクトの場合

`Makefile` のプロジェクトの場合はこの方法は使えないので [compiledb](https://github.com/nickdiego/compiledb) を使います。

## compiledb のインストール方法

```
pip3 install compiledb
```

pip でインストールします。ここでは python 3 を対象にしているので pip3 を使います。

## compiledb での compile_commands.json の生成方法

compiledb  を指定して make を実行するとカレントディレクトリに `compile_commands.json` が生成されます。

```
compiledb make
```

大きなプロジェクトでは、ビルドが終わって最後に `compile_commands.json` に書き出すときに時間がかかります。

```
compiledb -n make
```

とすることで、実際のビルドはせずに `compile_commands.json` を生成することだけということができるらしいですが、make の生成物に依存する処理がある場合、エラーになるので、実際にビルドしてから `compile_commands.json` を生成したほうが、確実かもしれません。
[Xcode] [Swift] Unwind Segueで2つ以上前の画面に一気に戻って画面を再更新する

今日からでもすぐに取り入れられて、

- コードをよりクリーンにできる、とか
- 工数を削減できる、とか

そんなTipsの紹介記事です。
「知らなかった」「気づかなかった」「忘れていた」そんな誰かの役に立てば幸いです。

# 前提環境

- Xcode 11.3.1
- Swift 5.1.3

# Unwind segue

## 概要・使い所

- **2つ以上前の画面に一気に戻りたい時。**
- **特に、戻り先の画面にて、画面更新などの処理を行いたい時に便利。**

## 手順

例えば、こんな感じのStroyboardがあるとします。
![スクリーンショット 2020-08-29 9.58.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122917/7969ac15-d86a-d4c5-beb5-1567ff7e96dd.png)

- FirstViewController > SecondViewController はpush遷移です。
- SecondViewController > ThirdViewController はmodal遷移です。

やりたいことは**「ThirdViewControllerからFirstViewControllerに一気に戻りたい」**です。

### 手順１．戻り先に関数を定義する

戻り先であるFirstViewControllerに以下のようなコードを書きます。
関数名はなんでも良いです。

```swift:FirstViewController.swift
    @IBAction func backToFirst(_ segue: UIStoryboardSegue) {
        print("\(segue.identifier!)")
    }
```

### 手順２．遷移元にUnwind Segueを定義する

Storyboardの遷移元のViewControllerの"Exit"に対して、Ctrlを押しながらオブジェクトをドラッグするとUnwind Segueを定義できます。
![スクリーンショット 2020-08-29 10.11.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122917/4398d05d-22f6-65cf-2847-130fc45e08b1.png)

例えば、UIButtonから"Exit"にCtrl+ドラッグするとこんなふうに上で定義した`backToFirst`が表示されますので、それを選択するとUnwind Segueを追加できます。
![スクリーンショット 2020-08-29 10.32.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122917/83c95ef2-7db4-079e-1e0a-a4b92ff16bb4.png)

Unwind Segueを追加したら任意のSegue Identifierを付けます。
![スクリーンショット 2020-08-29 10.33.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122917/1a515687-b237-5ac6-12a4-a95eee01779a.png)

### 実行結果

ThirdViewControllerのUIButtonをtapすると、
(1) ThirdViewControllerが閉じられ、
(2) SecondViewControllerからFirstViewControllerにpopされる、
という動きになります。

すなわち、**「ThirdViewControllerからFirstViewControllerに一気に戻りたい」を簡単に実現できます。**

また、FirstViewControllerの`backToFirst(:_)`が実行され、`segue.identifier`に上で付けた`fromThirdToFirst`が渡ってきます。
すなわち、**`backToFirst(:_)`に、画面更新など、戻り先で行うべきコードを記述することができます。**

## 蛇足

私はコードでこれらを（Unwind Segueと同程度に簡単に）実現できる方法を知りません。
もしご存知の方がいたらコメントで教えていただきたいです。:bow:
[Swift] Initialization Closureを使ってオブジェクトの初期化コードをリーダブルにする

今日からでもすぐに取り入れられて、

- コードをよりクリーンにできる、とか
- 工数を削減できる、とか

そんなTipsを紹介していく記事シリーズです。
「知らなかった」「気づかなかった」「忘れていた」そんな誰かの役に立てば幸いです。

# 前提環境

- Xcode 11.3.1
- Swift 5.1.3

# Initialization Closure

## 概要・使い所

プロパティが属する型が初期化されるたびに、クロージャーが呼び出され、その戻り値がプロパティのデフォルト値として割り当てられます。

特に、UIをコードで構築する場合に効果を発揮します。
プロパティの宣言部分に初期化のためのコードを集約できるため、見通しが良くなります。

```swift
class ViewController: UIViewController {
    private let label: UILabel = {
        let l = UILabel()
        l.translatesAutoresizingMaskIntoConstraints = false
        l.text = "label"
        return l
    }()

    private let button: UIButton = {
        let b = UIButton()
        b.translatesAutoresizingMaskIntoConstraints = false
        b.setTitle("button", for: .normal)
        b.setTitleColor(.blue, for: .normal)
        b.sizeToFit()
        return b
    }()

// 以下省略
}
```

## 公式ドキュメント

[The Swift Programming Language - Initialization](https://docs.swift.org/swift-book/LanguageGuide/Initialization.html)
adb connectでmissing port in specificationとなる場合

### はじめに
adbのバージョンによるのか、adb connectで接続できない場合があったため備忘録

### コマンド

```bat
C:\Users\hoge>adb tcpip 5555
restarting in TCP mode port: 5555

rem 接続に失敗する
C:\Users\hoge>adb connect 192.168.XXX.XXX
missing port in specification: tcp:192.168.XXX.XXX

rem ポート番号を末尾に追加すると接続できる
C:\Users\hoge>adb connect 192.168.XXX.XXX:5555
connected to 192.168.XXX.XXX:5555

C:\Users\hoge>adb devices
List of devices attached
192.168.XXX.XXX:5555       device

```

### 確認したバージョン
```bat
C:\Users\hoge>adb version
Android Debug Bridge version 1.0.41
Version 29.0.1-5644136
```
### 参考サイト
* [Android Developers] (https://developer.android.com/studio/command-line/adb?hl=ja#wireless)
* https://stackoverflow.com/questions/55158265/adb-missing-port-in-specification
CentOS8 USB LANアダプターのネットワークの設定

# おうちサーバのNUCの有線LANが認識しない？
ちょいと色々と設定入れていたら NetworkManager が起動しなくなっちゃり内蔵の有線LANが認識しないとかあったので、USB LANアダプターを刺してみた。そして少しはまったので自分めも。

# USB LANアダプター認識するも
LANアダプター認識しているがアドレス設定できない・・・。

```cmd
# nmcli d
DEVICE           TYPE      STATE     CONNECTION 
enp0s20f0u3      ethernet  切断済み  --         

# nmcli c modify enp0s20f0u3 ipv4.addresses 192.168.33.34/24 
エラー: 不明な接続 'enp0s20f0u3'.
```

# 新規デバイスを追加をする
すっかり忘れてた、そしてぐぐった。新規デバイスを追加しないとだめやんね。

```cmd
# nmcli c add type ethernet ifname enp0s20f0u3 con-name enp0s20f0u3
接続 'enp0s20f0u3' (c6488439-e233-4874-8b2b-13f8d5022501) が正常に追加されました。

# nmcli c modify enp0s20f0u3 ipv4.addresses 192.168.33.34/24 

# nmcli d
DEVICE           TYPE      STATE     CONNECTION  
enp0s20f0u3      ethernet  接続済み  enp0s20f0u3 
```

# すっきり
なぜか内蔵の有線LANも認識した。折角USB LANかってきたのにうむむ…。
【GitHub Actions】LaravelのCI環境構築

# 実現したいこと
GitHub Actionsを用いて、LaravelのCI環境構築をします。

# 前提
開発環境でPHPUnitの`vendor/bin/phpunit`コマンドを実行したら問題なくテストが正常に動作するのが前提です。

# ワークフローの作成

```.github/workflows/ci.yml
name: CI

on:
  push:
    branches: [master]
  pull_request:
    branches: [master]

jobs:
  php-nuit:
    runs-on: ubuntu-latest

    services:
      mysql:
        image: mysql:8.0.19
        ports:
          - 3306:3306
        options: --health-cmd "mysqladmin ping -h localhost" --health-interval 20s --health-timeout 10s --health-retries 10
        env:
          MYSQL_ROOT_PASSWORD: password
          MYSQL_DATABASE: testdatabase

    env:
      DB_CONNECTION: mysql
      DB_HOST: 127.0.0.1
      DB_PORT: 3306
      DB_DATABASE: testdatabase
      DB_USERNAME: root
      DB_PASSWORD: password

    steps:
      - uses: actions/checkout@v2
      - name: Copy .env
        run: cp .env.ci .env
        working-directory: ./server
      - name: composer install
        run: |
          composer install --no-scripts
        working-directory: ./server
      - name: Generate key
        run: php artisan key:generate
        working-directory: ./server
      - name: Directory Permissions
        run: chmod -R 777 storage bootstrap/cache
        working-directory: ./server
      - name: migrate
        run: php artisan migrate
        working-directory: ./server
      - name: php-unit test
        run: ./vendor/bin/phpunit
        working-directory: ./server
```

今回のテストでは、データベースも絡んでいるため、MySQLを使用しました。また、私のLaravelのディレクトリ構造は下記の添付画像のようになっていたため、コマンドによってはディレクトリを指定する`working-directory: ./server`を記述しています。

![スクリーンショット 2020-08-30 6.29.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264073/cd720f8d-9b74-e78a-5439-541c0f2d3ffa.png)

■参考
https://github.com/yuuta1988/shussekikun/blob/master/.github/workflows/ci.yml


# .env.ciの作成

ワークフローで.env.ciを元に.envファイルを複製するので、.env.ciを作成します。

```server/.env.ci
APP_NAME=Laravel
APP_ENV=testing
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=testdatabase
DB_USERNAME=root
DB_PASSWORD=password
```

■参考
https://github.com/yuuta1988/shussekikun/blob/master/server/.env.ci

## 参考

- [GitHub Actionsのドキュメント
](https://docs.github.com/ja/actions)
- [GitHub Actions で LaravelのCI/CD環境を構築する（MySQL, Deployer）](https://qiita.com/wim/items/7eb8386672fd114c2576)
supertest で "Type 'typeof supertest' has no call signatures." の エラー

# 発生したエラー

突如、 **supertest** がエラーを吐き出した。

```ts
 FAIL  test/app.e2e-spec.ts
  ● Test suite failed to run

    TypeScript diagnostics (customize using `[jest-config].globals.ts-jest.diagnostics` option):
    test/app.e2e-spec.ts:20:16 - error TS2349: This expression is not callable.
      Type 'typeof supertest' has no call signatures.

    20         return request(app.getHttpServer())
                      ~~~~~~~

      test/app.e2e-spec.ts:2:1
        2 import * as request from 'supertest';
          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        Type originates at this import. A namespace-style import cannot be called or constructed, and will cause a failure at runtime. Consider using a default import or import require here instead.
```

![Screen Shot 2020-08-30 at 7.51.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252342/d00daf47-dea9-bde8-0f99-47ee4a058aac.png)

## 環境

```
"typescript": "^3.7.4"
- "@types/supertest": "^2.0.8"
+ "@types/supertest": "^2.0.10"
"supertest": "^4.0.2"
```

# 解決方法

**request.default** のような形で呼び出すように変更する。

```ts
it('/ (GET)', () => {
    return request.default(app.getHttpServer())
    .get('/')
    .expect(200)
    .expect('Hello World!');
});
```

# ひとこと

本体のほうで変更があったのかな…
1時間以上溶かした…
Linux Mint Mate 20で有線接続、固定IPアドレスを設定する

#初めに
私はこの度、Linux Mint Mate 20 にアップデートしました。久しぶりのことでインターネット接続に必要な設定方法を忘れていました。今後の覚書の意味もあり忘れないうちに書き記します。


#メニュ-
メニュのコントロールセンターを選びます。そうするとあれこれと設定する画面になります。その中のインターネットとネットワーク、高度なネットワーク設定をクリックします。

![Screenshot at 2020-08-30 07-37-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/3187b122-5ec3-e606-1285-0092986ace06.png)

#ネットターク接続の作成
すると下記のような画面になります。ここで左下のプラスボタンをクリックします。新規作成になります。

![Screenshot at 2020-08-30 07-38-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/89f96c6d-a019-8e0e-2536-c8122c3b6bac.png)

#接続の種類
有線接続の場合にはEthernetを選択します。

![Screenshot at 2020-08-30 07-38-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/be326fa3-f787-98ca-1a1e-0fd39d6d168a.png)

#タブ
さらに次の画面になりましたらIpv4設定を選びます。

![Screenshot at 2020-08-30 07-39-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/4a7c892a-84e2-1e9b-8a40-be99d9057046.png)

#設定
固定IPの場合にはメソッドを手動とします。さらにアドレス、ネットマスク、ゲートウェイ、DNSサーバーのアドレスを入力します。最後に右したにある保存のボタンを押します。これで完了です。接続中のメッセージが表示されているはずです。

![Screenshot at 2020-08-30 07-39-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/0c06f8d0-02c5-b763-ed01-027184a3dcda.png)
【備忘録】【iOS】SwiftエンジニアがObject-Cを学ぶ際に最低限学んだこと


##最初にさらっと読んだ記事
[今さらまとめるObjective-C文法基礎](https://qiita.com/gorilla9015/items/7efdab32d25851089072)
→変数やif分などの基礎文法を学ぶ。
[SwiftとObjective-Cとの違い](https://thinkit.co.jp/article/12089)
→クラスや関数などを学ぶ。
[意図せずObjective-C を読まなければいけなくなった Swift エンジニアへ贈る Objective-C読み方まとめ](https://qiita.com/yamatatsu10969/items/5e73ea753953eb4086d5)
→SwiftとObjective-Cの違いで大事な点だけ学ぶ。

上記でさらっとObjective-Cを理解。
後は不明点が出たらググるスタンスで良いのかなと思います。

以下はメモ。
##.hと.mのファイルが存在する
###.hファイルとは
>ヘッダファイル（.h）はクラスの「目次」
→このファイルのみでクラスの全体を俯瞰できる。
→@interface〜@end
　→クラスの目次（宣言）（〜終わり）

###.mファイルとは
>実装ファイル（.m）はクラスの「本体」
→@implementation〜@end
→クラス実装（〜終わり）

###分割メリット
>※分割のメリット・・クラスを外部に公開する際、ヘッダファイルだけでもユーザはそのクラスを利用できる。
一方実装の内部は隠蔽することができる。

引用先：[Objective-Cの基本](https://qiita.com/kidach1/items/866c7ea6ce7eaf02c35c)
##importの種類
### #import <hoge.h>
>クラスライブラリ(CocoaやCocoa Touchに予め用意されているクラス)をインポートするときに使う

### #import "hoge.h"
>自作ファイルからインポートする場合

引用先：[Objective-Cのimport](http://watarotten.hatenablog.com/entry/2015/10/13/181613)
###@import hoge;
>Xcode5あたりで新規作成したprojectからデフォルトでYESになっている機能だったようです。
この機能を利用するためには、BuildSettingsからEnable Modules (C and Objective-C)をYESにする必要があります。
（※古いプロジェクトでは、デフォルトがNOになっている）

>  #import \<Cocoa/Cocoa.h>などのように書いていた箇所は
@import Cocoa;で置き換えられます。

引用先：[frameworkのimportを簡略化する（@importについて）](https://qiita.com/Takumi_Mori/items/b40745c8bf899ca67476)
##おわりに
後はググりながらObjective-Cを学んでいこうと思います。
躓いた点があれば随時追記してこうと思います！
Watson Assistantで会話ができなくなった時のTips(2020年8月版）

# はじめに
Watson AssistantのSkills Detailに 以前はWorkspace IDがあったのですが、 2020年8月時点で確認すると無くなってて困ったのでTipsとして掲載しておきますね。

@Shibu-Shin さんの「 [TJBot zeroと会話しよう！](https://qiita.com/Shibu-Shin/items/954f4693d3009f854395)　」 を参考にして作った方は、今回の事象にぶつかるので参考にしてくださいね。

>注) Node-RedのassintantノードをアップグレードするとGUIが変わるかもしれませんが、そこは未検証です。

# 変更箇所と対応方法 

## 以前は、 Skill Detailsの箇所に Workspace IDがあった。
![ibm-assicetant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209170/81fd586f-2249-d3a0-d0d7-be8f0a8949fd.png)

## 2020年8月時点に確認したときは、Workspace IDが無くなってて困った。
![node-tjbot-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209170/73a40374-bde7-7798-89d3-58dad6226a93.png)

## 回避策 
- IBM Cloudのサポートに問い合わせた結果、 Workspace IDを入力する必要がある場合は、Skill IDを入力する。


## 「 [TJBot zeroと会話しよう！](https://qiita.com/Shibu-Shin/items/954f4693d3009f854395)　」 で変更する箇所
- [TJBot zeroと会話しよう！](https://qiita.com/Shibu-Shin/items/954f4693d3009f854395)　を使ってTJBotと会話を楽しんでた方は、 assistantノードでエラーになります。
![node-tjbot-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209170/3a7d9c8b-9eea-c31c-2c4e-eb73bd994bee.png)

- assistantノードを編集を開いて workspaceIDの箇所に Skill IDを入力する。
![ibm-assistance.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209170/58f413e1-4b21-fb20-1198-2ea95f74518e.png)


# 最後に
クラウドサービスのバージョンアップは結構早くて、機能も追加・改善するので、とても便利なのですが、今回のように、たまに、仕様変更でぶつかって困っちゃうこともありますね。そこは、自分が今後も何かぶつかったら、Tipsで紹介して埋めれればいいかなと個人的に思うところです。
皆さんもTipsがあったら紹介してくださいね♪
Linux (ディレクトリ・パスについて)

ディレクトリについて、もう少し深く取り下げていきましょう。

下記の画像をご覧下さい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697209/474b49f7-2fd3-be14-7d3e-fa83493fce73.png)

簡易的ですが、ディレクトリツリーです。一番上は/(ルートディレクトリ)といいます。
ディレクトリの場所をコマンドで表記する場合に、パスという概念を覚えてください。
例えば、nekoディレクトリから見てimagesのパスは、/neko/date/imagesで表記される事なります。
homeディレクトリから見る場合は、/home/neko/date/imagesで表記されます。

パスは経路と考えてください。nekoからimagesに行く経路・homeからimagesの行く経路。
イメージ先行で行きましょう。

このファイルやディレクトリの経路を表すパスには2種類あります。
<font color=red>
<ol>
<li>絶対パス</li>
<li>相対パス</li>
</ol>
</font>
上記の2種類です。<b>絶対パス</b>から紹介しましょう。

<font color=red>
<h1>絶対パス</h1>
</font>
/(ルートディレクトリ)を基準にパスを表す方法です。
例えば、nekoの中のdateを表す場合は<font color=red>/</font>home/neko/dateと表記します。

説明だけしてもよく分からないですよね。
<font color=red>mkdir</font>コマンドと<font color=red>cd</font>コマンドを使って、実演しましょう。

まずは<font color=red>mkdir</font>コマンドで、ディレクトリを作成しましょう。
nekoのホームディレクトリ内で、neko-beyaを作成しましょう。

```
[neko@localhost ~]$ mkdir neko-beya
[neko@localhost ~]$ ls
neko-beya
```

neko-beyaに移動しましょう。
<font color=red>cd</font>コマンドを使用します。このコマンドはディレクトリの移動に使用します。絶対パスを指定して下さい。

```
[neko@localhost ~]$ cd /home/neko/neko-beya
[neko@localhost neko-beya]$
```

~(チルダ)の部分が、neko-beyaに変わっていますか？
ちなみに、~はホームディレクトリを表しています。ログインして最初は、~になっています。

<font color=red>
<h1>相対パス</h1>
</font>

ユーザが作業を行っているディレクトリを基準にパスを表記する方法です。
ユーザが作業を行っているディレクトリ=<font color=red>カレントディレクトリ</font>と言います。
覚えておいてください。知っている前提で書籍等でも解説される事があります。
例えば、カレントディレクトリがhome/nekoであるとしましょう。
neko-beyaを絶対パスで指定する時は、/home/neko/neko-beyaと表記します。
相対パスで指定する時は、neko-beyaで表記します。
カレントディレクトリがhomeである場合は、neko/neko-byaとなります。

実演しましょう。
<font color=red>pwd</font>コマンドを使うと、カレントディレクトリが分かります。

```
[neko@localhost ~]$ pwd
/home/neko
```

/home/nekoがカレントディレクトリですね。neko-beyaに移動しましょう。

```
[neko@localhost ~]$ cd neko-beya
[neko@localhost neko-beya]$
```

いけましたか？

以上、
<font color=red>
<ul>
<li>mkdir</li>
<li>cd</li>
<li>pwd</li>
</ul>

ディレクトリ・パスについてでした。
VSCode メモランダム

***
ドットインストールの学習メモです
***

クイズ　ショートカットまとめ

command + B
command + s
command + c
command + x
command + option + s
command + ,
shift + command + p
ommand + enter
command + shift
command + d
command + shift + L
command + option +↓
command + f
command + g
command + shift + g
command + option + f

答えは下を読め＾＾

***







##アクティビティバー
上から

* explore ファイル管理
* 検索
* git
* debug
* extensions  拡張機能
...
* 設定

右クリックで表示非表示を選べる
表示　appearance メニューから戻せる
もしくは command + B
削除・フォルダ・ファイル作成もできる。

##一番下はステータスバー
行
列の位置
タブサイズ
文字コード
改行コード
ファイル種別-自然にコードを補完したりしてくれる

###広いエリアはエディタエリア


##ファイル編集
フォルダを追加
ファイルの作成
ファイルの保存-ファイルから保存か、command + s


##Emmet記法
標準のテンプレートを呼び出してくれる機能。
カーソルを置いて
command + c
command + x
で行ごとコピー・カット。
ul>li*3
でul下にliを３つ作ってくれる。
emmet記法を勉強しておくのもいいでしょう。

##css,javascriptを読み込んでみよう
<link rel="stylesheet" href="css/styles.css">
<script src="js/main.js"></script>
***書いてからホバー・クリックでフォルダとファイル作成してくれる。***
タブを閉じるのはcommand + B
タブをエディタエリアに持ってくと分割できる。
タブエリアに戻せば分割を解除。


###cssを編集してみよう
***色指定後の、色見本(文字のところ）にホバーするとカラーピッカーが出てきて、そこから色を選べる！！***
***セレクターにホバーするとセレクタが示す要素を例示してくれたり、詳細度を表示してくれたりする。
h1 .title, h1.titleの違いなど***

###javascriptを編集してみよう
document = docで候補を選ぶ
***queryselector = queselでも候補を選んでくれる！！
ddEventListener = adevliで出てきた！すごい。。。。***

###CSS JavaScript全てのファイルを保存するには
command + option + s

##設定の変更
preference setting or command + ,
auto save  afterDelay
fontsize 14
fontfamily Ricty diminished
tab 2
render white space  all 空白の表示
word wrap  on 行の折り返し

##コマンドパレット
view command palette or shift + command + p
カラーテーマの変更など
ミニマップの削除　minimapを検索
ショートカットを調べる
side barの削除　→　sidebarを検索


##実践的なショートカットキー
option + 上下　行を移動できる
option + shift + 上下　複製を任意の方向で
行選択 + option +上下　選択行を移動
command + enter 行の途中でも下に行を挿入
command + shift + enter 行の途中でも上に行を挿入

##マルチカーソル
option + マウスで編集箇所を選択　２カ所以上の同時編集が可能
	他のところをクリックかescでマルチカーソルを解除
command + d カーソル前の単語が選択され、も一度押すと同じ単語が選択される。
command + shift + L で一気に同じ単語を選択できる。
command + option +↓　真下にカーソルを追加できる


##検索と置換
###検索
command + f 検索
command + g 次の検索結果へ
command + shift + g 前の検索結果へ
###置換
command + option + f
検索窓右隣一つ目のアイコンで一つずつ置換
検索窓右隣二つ目のアイコンで全部置換

###作業フォルダ内全てのファイルを対象とする
activity barの検索アイコン
3つの検索アイコン
大文字小文字の区別・単語ごとの検索・正規表現を使うかどうかのオプション
アラートをreplace

##拡張機能の導入
パス。
[JavaScript] クロージャー(closure) をわかりやすくまとめてみた　No.1

#なんと、このコードもクロージャーなんです。

```
const myName = 'rika'

function printName(){
  console.log(myName)
}

PrintName() // rika
```
他の言語では、functionの内側の変数から外側の変数にアクセスすることは出来ないのですが、JavaScriptだとそれが可能になります。それを「クロージャー」と呼びます。

上の例でも、グローバル変数myNameをfunctionの中での使用することが出来るんです。

#一番使われるクロージャーの形はfunction内のfunction! 

```
function outerFunction(outerVariable) {
 return function innerFunction(innerVariable) {
      console.log(`Outer Variable: ${outerVariable}`)　//結果 outside
      console.log(`Inner Variable: ${innerVariable}`) //結果　inside
 }
}

const newFunction = outerFunction('outside')
newFunction('inside')
```

ここでもouterVariableが、innerFunction内でもアクセス出来ちゃってます。つまり「クロージャー」が使われているということですね。

たとえば、functionの外側に新しく変数を置いてみましょう。

```
function outerFunction(outerVariable) {
　　　const name = 'rika'　定数nameを追加してみました。↓
 return function innerFunction(innerVariable) {
      console.log(`Outer Variable: ${outerVariable}`)　//結果 outside
      console.log(`Inner Variable: ${innerVariable}`) //結果　inside
      console.log(name) //結果　rika と出力されます
 }
}

const newFunction = outerFunction('outside')
newFunction('inside')
```

つまり、functionの内側から、外側の変数・定数にアクセス出来ますよー！というのがクロージャーの特徴になりますね！　


#なぜクロージャーを使うのか？
たとえばグローバル変数を使えば、どこからでもアクセスが出来ます。
ですが、あえてクロージャーを使う利点をあげるとすれば、その名の通り外部から変数にアクセスできない仕組みになっているからです！（カプセル化と呼びます）これはコードの安全性を高める上で重要なテクニックです。クロージャーのテクニックを利用することでより安全で保守性の高いプログラムにすることが可能です。


参考動画: https://www.youtube.com/watch?v=3a0I8ICR1Vg
ポート番号443以外でWEBアプリを運用していたら、繋がらないと言われたのでプロキシで解決した

# 更新履歴
　ProxyRequests ON  にすると、どんどん踏み台にされるので、OFFにすることをオススメします

# ポートフィルタリングしているケースって多いんですね
フリーランスになってすぐに運用し始めたお客さんのWEBアプリがあるんです。
最初はExcelVBAではじめ、続いてブラウザで動作させるため、GASで運用。
今やユーザ数も多くなり、GASで耐えられなくなったので、ちゃんとクラウドサーバで運用を始めました。
**node** で作成したのですが、せっかくサーバ立てるので、**wordpress** なんかも動作させていたんです。

**node** では 443 以外のポート（例：12345ポート）で **express** が **https** を受け付けていたのですが、新しくサービスに追加したお客さんから

**つながらないよ～**

と連絡をいただきました。

スクショを見て、Wifi使っていることと、お客さんの状況から、おそらくポートだと気付き、4Gにしてもらったら案の定つながりました。
さすがに

**さっせん。4Gで頑張ってください。**

と言えるほどメンタル強くないので、２～３日で改善する約束をしたので試行錯誤した結果、Apacheによる プロキシ運用にしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366986/6e0d1608-0651-196f-61c3-f609eb05f2dc.png)



# プロキシの設定

conf ファイルで一発解決。
やっぱ **Apache** ってよく考え抜かれていますね。

```conf:proxy_appli.conf
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
ProxyRequests off            #ここをONにすると、踏み台にされちゃうので、自ホスト内変換だけが目的ならばOFF
ProxyVia On
SSLProxyEngine on
SSLProxyVerify none          #ここから3行は、接続先の SSLハンドシェイクに失敗したときに追加した
SSLProxyCheckPeerCN off      #/var/log/httpd/ssl_error_log を見ると、次のようなエラーコードが出ています
SSLProxyCheckPeerName off    #AH01797 AH01961 AH00961 AH00898 AH01097 AH01276 AH00957
                             #こんなのが出たら追加してみると幸せになれそう
                             #外部サイトへのプロキシを今後貼らないと信じて、これでよいと判断

<Proxy hoge.com:443/*>       #httpsの書き方
        Require all granted
</Proxy>
<Proxy hoge.com/*>           #httpの書き方
        Require all granted
</Proxy>

<Location /appli/>
        ProxyPass https://localhost:12345/
</Location>

```

# ほかに考えたこと
 Apache の 巨大な conf を見るのがあまり好きじゃないので、少し考えたけどやめたことを書いておく。

 - node express 側で、振り分けるというのも考えたが、node がプロキシのような動作をすると、wordpress とかの接続を node が一度受け取ることになり、負荷的になしかなと。
IX2106の設定2

# はじめに
auひかりはPPPoEで認証しておらず、貸し出されるHGWのMacアドレス+特殊なパケットで認証してるらしい。
自前のルータで直接つなぐことはできない。

ということでauのHGWにDMZ設定してそこにIX2106を設置してみた。

# 1．au HGWの設定（管理WEB）
管理WEBにブラウザアクセスして設定変更を行う。

## 1-1．LAN側設定確認
IPアドレス/サブネットマスクを確認
　e.g. 192.168.0.1/24

## 1-2．DMZ設定
DMZホスト機能をONにする。
IX2106のWAN側に設定する予定のIPアドレスを割当てる。
　e.g. 192.168.0.100

## 1-3．DHCP固定割当設定
IX2106のWAN側MACアドレスに対して1-2で設定したDMZホストのIPアドレスを固定割当する。


# 2．IX2106の設定
コンソール接続して設定変更を行う。

## 2-1．WAN側設定
DHCPでauのHGWからIPアドレスを自動取得するよう設定する。
これで1-2で設定したIPアドレスがDHCPで降ってくる。
ついでにNAPT設定もする。

```
Router# enable
Router(config)# interface GigaEthernet0.0
Router(config-GigaEthernet0.0)# ip dhcp receive-default
Router(config-GigaEthernet0.0)# ip napt enable
Router(config-GigaEthernet0.0)# no shutdown
```

## 2-2．LAN側設定
WAN側とは別ネットワークを設定する。
今回はLAN側インターフェースのIPアドレスを192.168.10.100にしている。
また、各ポートに接続した端末にはDHCP設定で192.168.10.0/24の.1～.20までを自動割当している。
DNSサーバはauのHGWのLAN側IPアドレスを設定する。
コマンドは、DHCP設定のプロファイルを作成してインターフェースにバインドしている。

```
Router# enable
Router(config)# ip dhcp enable
Router(config)# ip dhcp profile dhcp_profile
Router(config-dhcp-dhcp_profile)# assignable-range 192.168.10.1 192.168.10.20
Router(config-dhcp-dhcp_profile)# subnet-mask 255.255.255.0
Router(config-dhcp-dhcp_profile)# dns-server 192.168.0.1
Router(config-dhcp-dhcp_profile)# exit
Router(config)# interface GigaEthernet1.0
Router(config-GigaEthernet1.0)# ip address 192.168.10.100/24
Router(config-GigaEthernet1.0)# ip dhcp binding dhcp_profile
Router(config-GigaEthernet1.0)# no shutdown
```

## 2-3．スタティックルートの設定
IX2106からauHGWに対してルーティングを設定する。
※いらないかも？

```
Router# enable
Router(config)# ip route 192.168.0.0/24 192.168.0.1
Router(config)# ip
```

# まとめ
上記設定でIX2106LAN側にPCやSynologyのNASをつないでインターネット接続やインターネット経由のNAS接続が確認できた。
筆者は初心者のため、設定の過不足やベストプラクティスなどコメント頂けると嬉しいです。

# 参考
https://www.tp-link.com/jp/support/faq/2000/
Mac USキーボードで英数かな切り替え 〜Beter Touch Tool編〜

# BTTを使えば親指シフトで英数かな切り替えができる
もう結論を書いてしまいましたが、MacにおいてBTTで親指シフトによる英数かな切り替えができることに気づいたので書き残しておきます。
ちなみに、ここで言う「かな入力」はローマ字入力の意味で使っています。

### BTTとは
[Beter Touch Tool](https://folivora.ai)の略。言わずと知れたMacでは定番のトラックパッドのカスタマイズツール（有償）。
最近は、タッチバーのカスタマイズにも対応しているが、そもそもタッチバー視線を落とすことはないため、ムダ機能となってしまっている。実はキーボードショートカットやキーシーケンスのカスタマイズもできる。今回使っているのは、このキーシーケンスのカスタマイズ機能。

### 親指シフトとは
MacのJISキーボードはスペースキーの右サイドに「かな」キー、左サイドに「英数」キーがあり、それぞれ

- かなキー：絶対かな入力に変換
- 英数キー：絶対英数入力に変換

という機能を持つキーが配置されている。
これを使って、かな・英数の入力モードを切り替えることを「親指シフト」と呼ぶ。

**メリット：**
Windowsの「かな/英数」キーのように１つのキーで`今の入力モードと別の方に切り替える`のではなく、２つに分けていることで`今の入力モードに関係なく`変換できるので、パスワード(英数)や住所(全角文字)の入力の場合に、いちいち今の状態を気にすることがない。
そのため、画面端に表示されている今の入力モードを見たりする必要はないし、スペースキーの横にあり押しやすいため、押し間違わないようにキーボードに視線を落とす必要もないという優れたキー配置。ありがとう。

## 経緯
完全に余談なので「やり方はよ」という方は飛ばしてほしい。
仕事でWindows端末を使うことがほとんどだったため、プライベートだけUSキーボードというのは混乱するので揃えていたが、今は仕事でもMacを使っている。そして99%以上自宅で仕事しているので、もうUSキーボードでいいのではないかなと思った。
MacbookProを今すぐUSキーボード仕様のものに買い換えることは難しいので、まずマジックキーボード（US配列）を購入することにした。

USキーボードへの切り替えの最大の障壁である`親指シフトによる変換ができないことによる作業効率低下`を危惧し、いろいろ調べてみた。
予想通り、以下の様な方法が多く目についた。

| キーマップ方法 | 割り当てキー | メリット・デメリット |
| --- | ---| ---|
| Macの基本設定 | CapsLock | 余計なソフトを入れなくて済む。CapsLock(Aキーの左隣)も押しにくくないが、変数定義など大文字入力固定したい場合が結構ある |
| Karabiner-Elements | 左Cmd=英数、右Cmd＝かな | 親指シフトができる。一時期Karabinerが最新OSに対応していなかったことがやや懸念 |

ちょっと違う感を感じて悩んでいたところ、
BTTにもキーシーケンスという項目があったので試してみたら、左Cmd=英数、右Cmd＝かな（親指シフトできるキー配置）ができた。
BTTは、だいぶ以前に買い切りのライセンスを購入しているし、タッチバーにも割と早く対応し、アップデートもうざいくらいちゃんとくるのでOS追随も安心と思う。

こうして、スッキリ気分でマジックキーボードの購入ボタンをポチった。


# やり方
1. BTTの構成をクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411291/ed17c369-1260-806f-5b2f-50c7d8af5052.png" width=320>

2. ヘッダーのプルダウンメニューから、`キーシーケンス/タイプした単語`を選択
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411291/f7a80655-df9b-4b14-6063-5b4c33281118.png" width=320>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411291/b803cc72-610d-773f-47ab-1b999b40f44c.png" width=320>

3. キーシーケンスを記録する
その際、左Commandボタンだけを押して記録終了
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411291/7b5e6833-5d7e-766d-684c-47afa33a1876.png" width=680>

4. 記録したキーシーケンス(左Command)に英字切り替えのキーボードショートカットを割り当てる
右Commandキーも同様に、キーシーケンス記録→ショートカット割当てをすれば完了
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411291/b0622bde-88eb-648a-eab0-79ac73358dcf.png" width=540>


Macの日本語入力ソースを設定/切り替えショートカットは以下。（以下はmacOS Catalina 10.15の場合）
キーボードによって割り当てるショートカットが異なる。

| 切り替え | キーボード | ショートカットキー |
| --- | ---| ---|
| ひらがなに切り替え | US配列 | Control＋Shift＋Jキー、Option＋Shift＋Zキー |
| ひらがなに切り替え | JIS配列 | Control＋Shift＋Jキー、Option＋Shift＋Zキー、かなキー（かな） |
| 英字に切り替え | US配列 | Option＋Shift＋Sキー |
| 英字に切り替え | JIS配列 | Control＋Shift＋セミコロン（;）、英数キー（英数） |

ショートカットキーについては、[Apple公式ページ](https://support.apple.com/ja-jp/guide/japanese-input-method/jpim10267/mac)があるので、最新はそちらを確認してほしい。


#### 補足
キーボードというエンジニアの生産性に直結する話題なので投稿。
ただ、Qiita的に適切でない場合は別のプラットフォームに移すので、ご指摘ください。
ABC177参戦記

古戦場帰りで頭がグルグルになってたのか何もわからなくなった。
もうだめだ……おしまいだ……。

#[A - Don't be late](https://atcoder.jp/contests/abc177/tasks/abc177_a)

普通。
$T×S≧D$ならYes、そうでないならNoを出せば良いですね。

```python
d,t,s=map(int,input().split())
print("Yes" if d<=t*s else "No")
```

#[B - Substring](https://atcoder.jp/contests/abc177/tasks/abc177_b)
メダパニゾーン
なんかとち狂った解法にたどり着いてしまった気がする。
というかどういう考えでこのコードに至ったのか思い出せない。

```python
s=input()
t=input()
res=float("INF")
if t in s:
    res=0
else:
    for i in range(len(s)):
        for j in range(len(t)):
            if s[i]==t[j] and i>=j and len(s)-i>=len(t)-j :
                tmp=j
                for k in range(j,len(t)):
                    if i-j+k<(len(s)) and s[i-j+k] != t[k]:
                        tmp+=1
                res=min(res,tmp)
 ```

解説見たらあーなるほどねという感じと、なんでこれにたどり着かなかったのかという感じが半々。
やはりメダパニかかってたのでは？


```python
s=input()
t=input()
res=len(t)
for i in range(len(s)-len(t)+1):
    tmp=0
    for j in range(len(t)):
        if s[i+j] != t[j]:
            tmp+=1
    res=min(tmp,res)
print(res)
```

#[C - Sum of product of pairs](https://atcoder.jp/contests/abc177/tasks/abc177_c)
愚直にやったらTLEだよなあと思いつつも短縮させる方法が思いつかなかったのでぶん投げ~~て残りの時間はすべてゲームに費やし~~た。

```python
n=int(input())
a=[int(i)for i in input().split()]
res=0
mod=10**9+7
for i in range(n-1):
    res+=sum(map(lambda x:x*a[i]%mod,a[i+1:]))
 
print(res%mod)
```

あらかじめsumAを求めておいてそこから$A_i$を引いたものに$A_i$をかければ良かったとは……。分配法則の概念を完全に忘れてました。

```python
n=int(input())
a=[int(i) for i in input().split()]
s=sum(a)
mod=10**9+7
res=0
for i in a:
    s-=i
    res+=i*s%mod
print(res%mod)
```

#おわりに
なんか今回難しくなかったですか？　twitter見ても悲鳴が多いような気が[^1]。
先週は10分でCまで終わったので急に意味わからないのが来て結構やる気が消えました。
バランス調整が雑なゲームは嫌ですね。
とりあえず[これ](https://qiita.com/hortensia/items/364f33a7909c169cdd45)の残りをやります。

[^1]: 過去の開催時のtwitter見てないのでわかりませんが
Virtual Box & Vagrant & Centos7 & GitLab 構築

# **Hello GitLab みたいなやつ**
## **0. 前提条件**
```
- Windows 10 Home
- Oracle VM Virtualbox 6.0.22
- vagrant 2.2.6
- Centos 7.8
- Box centos/7
- GitLab CE 10.2.5
```

## **1. 依存パッケージのインストールなど**
```bash
sudo yum install -y curl policycoreutils-python openssh-server
sudo systemctl enable sshd
sudo systemctl start sshd
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo systemctl reload firewalld
```
- メール送信設定
  - 外部のSMTPを利用する場合は以下参照
    外部利用は以下参照  
    [外部SMTP利用](https://docs.gitlab.com/omnibus/settings/smtp.html)
  - インストールする場合は以下  

```bash
sudo yum install postfix
sudo systemctl enable postfix
sudo systemctl start postfix
```  

## **2. Version を指定して GitLab インストール (今回は 10.2.5 を指定)**
```bash
curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
sudo yum install gitlab-ce-10.2.5-ce.0.el7.x86_64
```
- 別の Version をインストールしたい場合は以下より検索  
[gitlab repositories](https://packages.gitlab.com/gitlab/gitlab-ce)

## **3. 起動前に初期構築作業**
```bash
#Gitlab設定ファイル編集(必要に応じて修正DB情報など)
sudo vi /etc/gitlab/gitlab.rb

#再構築(初期構築)
sudo gitlab-ctl reconfigure
```

## **4. GitLab の起動方法**
  - 起動方法  

```bash
sudo systemctl start gitlab-runsvdir
```


  - 自動起動設定有効・無効は以下  

```bash
#自動起動の有効化 
sudo systemctl enable gitlab-runsvdir.service
#自動起動の無効化 
sudo systemctl disable gitlab-runsvdir.service
```

- **以下のサイトを参考に実施**  
[猫のプロトコル : 古いGitLabのインストール](https://protocol.nekono.tokyo/2017/09/01/%E5%8F%A4%E3%81%84gitlab%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/)  
[GitLab : 公式Document](https://docs.gitlab.com/omnibus/update/README.html)
[Swift] 条件を指定して配列を分割できる`partition(by:)`の使い方

## [`partition(by:)`](https://developer.apple.com/documentation/swift/array/3017524-partition)とは
>与えた条件に一致するすべての要素が、一致しないすべての要素の後に来るように、コレクションの要素を並べ替えます。

## 使い方
```swift
var numbers = Array(0...10)
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

let p = numbers.partition(by: { $0 % 2 == 0 })
// 5

print(numbers) // [9, 1, 7, 3, 5, 4, 6, 2, 8, 0, 10]

let odds = numbers[..<p] // [9, 1, 7, 3, 5]
let evens = numbers[p...] // [4, 6, 2, 8, 0, 10]
```

## 注意点
- `partition(by:)`は条件に一致する要素が始まるindexを返すのであって、新しい配列を返すわけではない。
  - つまり`partition(by:)`は自身を変化させる`mutating func` (元の配列を宣言する時は`let`ではなく`var`)
- 要素を並び替えた後、条件を満たさない前半(or満たす後半)の要素の連続の中で元の順番は保証されていない

## 問題点 & 対応策
前述したように、`partition(by:)`は条件によって配列を２つに分割することができますが、元の配列の順番が重要で、分割後もそれを維持したいケースにこのメソッドは向いていないです(そして多分そのケースの方が多い🤫)

対応策として

**`Array`を拡張する**

```swift
extension Array {
    /// 条件を満たさない要素の配列と、満たす配列をtupleにして返す
    func partitioned(predicate: (Element) -> Bool) -> (unsatisfied: [Element], satisfied: [Element]) {
        return reduce(into: ([Element](), [Element]())) {
            if predicate($1) {
                $0.1.append($1)
            } else {
                $0.0.append($1)
            }
        }
    }
}
```
**使い方**

```swift
let partitioned = numbers.partitioned(predicate: { $0 % 2 == 0})

print(partitioned.unsatisfied) // [1, 3, 5, 7, 9]
print(partitioned.satisfied) // [0, 2, 4, 6, 8, 10]

// 順番はそのまま！
```
ちなみに、今回extensionに利用した`reduce(into:_:)`については、こちらに[素晴らしい記事](https://qiita.com/koher/items/17636e95e18e529e5b9b)があります。

また、パフォーマンスについては`reduce(into:)`ではなく素直に`for in`を使って回す方法もありますが、[リリースビルドにおいては問題無い](https://medium.com/@r.izumita/swift%E3%81%AEfor-in%E3%81%A8map%E3%82%84reduce%E3%81%AE%E9%80%9F%E5%BA%A6%E3%82%92%E6%AF%94%E3%81%B9%E3%81%A6%E3%81%BF%E3%82%8B-21d059c02a85)ようです。
(あっても自分はreduceで書きたいが🤐)

## 最後に
当然ですが、分割した配列内の要素の順番を気にしないのであれば、パフォーマンスの観点からSwift標準の`partition(by:)`を使うべきですね😌
RDSはデフォルトパラメータグループはやめよう

RDSのMySQLをデフォルトパラメータグループで運用していたのですが、カスタムパラメータグループにしておけばよかったと後悔した話です。

## RDSのInnoDBモニターを有効化したかった。
DeadLockなどのログが見たくてInnoDBモニターを有効化しようと思いました。
有効化にはMySQLのDBパラメータinnodb_status_output/innodb_status_output_locksをONにする必要があります。
ですが、<font color="Red">デフォルトパラメータグループのパラメータは変えることが出来ません。</font>
そのためカスタムパラメータグループを作成し付け替えたのですが、<font color="Red">パラメータグループの付け替えには必ずインスタンスを再起動する必要</font>がありました。

ということでRDSは作成時からカスタムパラメータグループで運用するよう心掛けましょう。
GitHubリポジトリのファイルをクロスオリジンで配信する超簡単な方法

小ネタです。

ちょっとしたスクリプトを配信したいな〜というとき。

GitHubリポジトリのファイル実体が保管されている`https://raw.githubusercontent.com`から直接`src`属性などで引っ張ろうとしても、レスポンスヘッダに`Access-Control-Allow-Origin: *`がないためCORSエラーで弾かれてしまいます。

```html:CORS-Error
<script src="https://raw.githubusercontent.com/dojyorin/myrepo/master/dist/index.min.js"></script>
```

# jsDelivrを使おう
- https://www.jsdelivr.com

実は、みんな大好きいつもお世話になっているjsDelivrさんからGitHubレポジトリのファイルへ **クロスオリジン** でアクセスできます!!

# 準備
jsDelivrでの配信準備はとても簡単。

1. タグを発行する
2. タグをpushする
3. おわり

タグがリモートリポジトリと同期されると、jsDelivr側も即座に反映されます。

# アクセス方法
タグが同期されたら、あとは以下のようにタグ名ごとのURLでアクセスできます。
タグ名を`latest`にすれば常に最新版をロードできるのはいつもと変わりません。

```html:CORS-OK
<script src="https://cdn.jsdelivr.net/gh/dojyorin/myrepo@tagname/dist/index.min.js"></script>
```
放置してたGCPを復活させる（３）- gcloud CLIインストール - ※エラーも出ちゃったよ。

GCP復活の作業履歴
[放置してたGCPを復活させる（１）- プロジェクト作成 -](https://qiita.com/3S_Laboo/items/62322280d1844d461bab)
[放置してたGCPを復活させる（２）- VMインスタンス作成 -](https://qiita.com/3S_Laboo/items/03b54621479e193101f7)
[今回：放置してたGCPを復活させる（３）- gcloud CLIインストール -](https://qiita.com/3S_Laboo/items/75682b3d008d0fdce355)
[放置してたGCPを復活させる（４）- PC(Windows10)からVMにssh接続 -](https://qiita.com/3S_Laboo/items/63a17738071a171decb1)
[放置してたGCPを復活させる（５）- VMのIPを固定する -](https://qiita.com/3S_Laboo/items/c897628aec6d04f4fe5f)
[放置してたGCPを復活させる（６）- nginxインストールとhttp設定 -](https://qiita.com/3S_Laboo/items/9a8446f84baa80252cb9)
[放置してたGCPを復活させる（終わり）- 独自ドメインの設定 -](https://qiita.com/3S_Laboo/items/cce944d49cbd1d4aa745)

今回はVMへのssh接続の前段として、gcloud CLIをインストールしていきます。
# ダウンロード
以下からダウンロード
[Windows 用のクイックスタート](https://cloud.google.com/sdk/docs/quickstart-windows?hl=ja)
# 迷わずgcloud CLIインストール⇒そしてエラー
![2020-08-30_01h18_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/324cc9a1-dda2-1ac0-635f-148385b67e07.jpeg)
ガイダンスに従い、次へ次へ
![2020-08-30_01h23_08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/06c219a3-4081-8f10-d366-7098b21fa759.jpeg)
なんかエラー
To use the Google Cloud SDK, you must have Python installed and on your PATH.
As an alternative, you may also set the CLOUDSDK_PYTHON environment variable
to the location of your Python executable.
# Pythonインストール・環境変数設定
うーん。PythonなしでCLOUDSDK_PYTHONの環境変数が無いのか。。。
よし。
https://www.python.org/downloads/
![2020-08-30_01h27_55.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/40276ae0-3679-de68-271c-8cdc8e0e2211.jpeg)
最新版をインストールだ！
![2020-08-30_01h29_28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/e5f9d2cc-78d1-7aff-2943-4186c9d3bfbf.jpeg)
環境変数設定
![2020-08-30_01h39_10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/7fd19ec1-634d-595b-3c15-31ed78160176.jpeg)
# gcloud CLIインストール再実行！！
![2020-08-30_01h46_49.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/1b82e938-7150-5b4f-25ab-bc5b84418907.jpeg)
イエイ！！
![2020-08-30_01h47_38.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/c7a964d3-e57e-0cab-c3da-b7ec6a6374a1.jpeg)
# コマンドライン出現
なんか出てきた
![2020-08-30_01h48_33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/f29b7871-67a0-9d64-9326-8d88223af444.jpeg)
Y押すとgoogleの認証がブラウザで表示された。
認証処理を実施。
![2020-08-30_01h51_32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/705020fc-4f58-8b70-cb29-d3979167f59f.jpeg)
。。。めんどくせ～からもういいや。×ボタン
git bashで確認
![2020-08-30_01h57_27.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/04373c13-a97e-3895-69a8-a9c1d3f6ef9f.jpeg)

なんか出たからこれでOKとしーとこ。

疲れた。おやすみなさい。

ありがとうございました。

次回
[放置してたGCPを復活させる（４）- PC(Windows10)からVMにssh接続 -](https://qiita.com/3S_Laboo/items/63a17738071a171decb1)