OmniAICreator/Qiita-1.07M huggingface dataset:
PythonでUnit Testを記述する。

# PythonのUnit Test について

PythonでもUnit Testを記述することは、品質を保つために重要です。しかしながら、テストコードを書くのは、結構手間がかかります。テストはしたいけど、めんどくさい感がプロジェクト内部でもないでしょうか？今回はテストコードを書くのはめんどくさいという課題を解決するツールを紹介します。


# PythonのUnit Testで使用するツール

[Python テストコード生成ツール](https://github.com/shigeshige/py-ut-generator)


このツールは、テストメソッドや呼び出し、パラメータの記述、関数のモック化を自動で記述してくれます。なので、あとはパラメータを調整し、内部で呼んでいる関数のモックを設定すれば、テストが実行できます。


## インストール

下記のコマンドでインストールできます。
[Python Unit Test Generator install](https://pypi.org/project/pyutgenerator/)

```
pip install pyutgenerator
```


## 実行

実行は引数にPythonファイルを指定し実行します。出力は"test"の下にテストコードが出力されます。

```
pyutgen aaa\bbbb.py
```

## 出力サンプル

テストされるコード

```
"""
test pattern 02
"""


def p01():
    x = f01(f01(f01))
    return x


def f01(prm1):
    return prm1
```


生成されたテストコード

```

import pytest
from unittest.mock import patch
from unittest.mock import MagicMock

from tests.pyutgenerator.data import pattern02

def test_p01():
    # plan

    # do
    with\
            patch('tests.pyutgenerator.data.pattern02.f01') as m1:
        m1.side_effect = [None, None]
        ret = pattern02.p01()

        # check
        assert ret

def test_f01():
    # plan
    prm1 = None
    # do


    ret = pattern02.f01(prm1)

    # check
    assert ret
```

## まとめ

ツールを使用することによって、自身で記述するコードをなくし、手早くテストコードを記述することができます。特に、モック記述しなければと言うときに、自動的に記述してくれます。あとはモックの戻り値を記述するだけでとりあえず動きます。かんたんにテストできます。是非活用し、コードの品質を上げてください。
日記；回すだけIII ①CANopenの準備

　CANopenの2回目のテストベンチです。最初の部分は、TRINAMIC社とほぼ同じ構成です。
###PC側のCANインターフェース

　入手性、日本法人があるなどの理由からIXXATのUSB-to_CAN V2 Compactをマルツで入手しました。付属のビューワcanAnalyser3 Miniでは、CANopenのプロトコルを見ることはできません。接続したPCのOSはWindows10 12H1です。

<img width="400" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/d4d49e9f-da3f-78bc-9047-23b9a0c19587.png">


　購入したモデルのCAN接続口は、一般的なDサブ9ピンです。130Ω（120Ωがなかったので）の終端を取り付けたケーブルを自作しました。終端は、モータ側にもつけています。まったく終端を入れないと、同期をとるためのスタッフィング信号のエラーが多発しました。CANopenの物理層はCANバスです。ツイストペア線で、複数の機器がぶら下がります。両端には終端抵抗を入れます。
　近距離だとモータ側には終端なくても通信できるようです。

<img width="700" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/bac86440-1327-808b-4924-3274c759ef9d.png">

###使用したモータ
　オリエンタルモーター のブラシレスモーターBLVシリーズ Rタイプを使います。
　　[BLMR5100K-A-B+BLVD-KRD](https://www.orientalmotor.co.jp/products/detail.action?hinmei=BLMR5100K-A-B%2BBLVD-KRD&seriesCd=FJ01&additionalHinmei=CCM010B1AAF)

＜モータBLMR5100K-A-B＞

- 定格出力（連続）　100 W
- 電源入力　定格電圧　DC24～48 V
- 電源入力　定格入力電流　2.6（48 V）～5.1 A（24 V）
- 定格トルク（モータ軸）　0.319 N・m
- 速度制御範囲　1-4000 r/min
- 許容慣性モーメントJ　23×10-4kg・m2
- モーター部 質量　1.1 kg

＜コントローラBLVD-KRD＞

- PCとの接続　USBマイクロコネクタ
- 上位接続　Modbus（RS-485）、CANopen

＜サポート・ソフト（無償） BLST01＞
- https://www.orientalmotor.co.jp/download/software/blst01/



###使用した電源
　DINレール用の、モータBLMR5100K-A-B用には24V 1.5A、コントローラBLVD-KRD用には24V 0.63Aを使いました。モータの電源は、専用のLC03D06Aケーブルを使いました。

###接続
　モータとコントローラは専用のケーブルでつなぎます。UVWの電源と、エンコーダ/電磁ブレーキのコネクタが用意されています。延長用が「接続ケーブル」で、交換用が「可動接続ケーブル」と呼ばれているようです。近距離ならば、別途購入は不要です。
　マニュアルHP-5139J.pdfの6項に従ってコネクタを差し込みます。
　28ピンのCN4コネクタは、5ピンがCAN_L、6ピンがCAN_H、7ピンがCAN_GND、20ピンNET-VIN（コントローラ24V）、21ピンNET-GND（コントローラGND）をつなぎます。
　　マニュアルは、https://www.orientalmotor.co.jp/products/detail.action?hinmei=BLMR5100K-A-B%2BBLVD-KRD&seriesCd=FJ01&additionalHinmei=CCM010B1AAF#option01　からダウンロードできます。

![IMGP0820.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/543db683-744f-3687-c8d7-af37c1fa0d9c.png)
自他に「対抗する」テクニカルサポートの目次

あらゆるものと、「対抗する」テクニカルサポートシリーズの目次です。

## 開発チームの苦悩

https://qiita.com/e99h2121/items/f4c5856734d136f672b7

## あらゆるものと対抗する開発チーム

https://qiita.com/e99h2121/items/bb9e22af744dec95caa0

https://qiita.com/e99h2121/items/43873ffd84b102d95929

https://qiita.com/e99h2121/items/be9247563fb936b77511

https://qiita.com/e99h2121/items/668affd9bf19f6d4c34f


## でも「テクニカルサポートを絶対にやったほうがいい」

敢えて「やったほうがいい」という、テクニカルサポートは意味があるという理由。

https://qiita.com/e99h2121/items/b5c2497000c32d6fd3c3

https://qiita.com/e99h2121/items/eca7b4b48579b101d237

https://qiita.com/e99h2121/items/9dd41104671286904830

## サポート良いぞという話

https://qiita.com/e99h2121/items/e25a4a6990c3997e472b

これからも増えるかも...

参考になればさいわいです。
ハロウィンを楽しめるアプリを作った

こんにちは、Yuiです。

先日はハロウィンでしたが、この自粛モードではなかなか外で仮装をして楽しむこともできないので、**オンラインでハロウィンを楽しめるアプリ**を[とみー](https://twitter.com/tommy19970714)さんと作りました！

今回はそのアプリについて書きます。

<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">なかなかオフラインでハロウィンを楽しめない中、オンラインでハロウィンを楽しめるサービスを作りました！自由自在に顔を変換させて遊んでみてください！面白いと思ったら拡散して皆に知らせてくれると嬉しいです！<a href="https://t.co/LwxQx2EwmX">https://t.co/LwxQx2EwmX</a> <a href="https://t.co/WL8ZFG8ogf">pic.twitter.com/WL8ZFG8ogf</a></p>&mdash; Yui 🌘 Yuiko Ito (@yui_active) <a href="https://twitter.com/yui_active/status/1454025906742185987?ref_src=twsrc%5Etfw">October 29, 2021</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

URL→https://ohmyface.ai/


## 使い方

使い方は以下のスライドの通りです。

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670446/bca756c8-831a-22b8-3d31-bf9a521b15cc.png)

まず、https://ohmyface.ai/ にアクセスすると**今週の人気ランキング**と**全体のランキング**を選ぶことができるようになっています。

このランキングはスタイルの変換数によって変動するようになっており、毎日21時に更新されます。

スタイルを選択したら、あとは変換したい画像をアップロードするだけです。
自動でローディングが走り、画像が変換されます。

※アップロードされた画像はサーバー側で保持することはありません。

## 構成

構成は以下です。

- バックエンド...python
- インフラ...AWS（API gateway, Lambda, dynamo DB, s3）
- フロントエンド...Next.js + TypeScript + Chakra UI

ランキング機能実装のために、画像を変換する際にどのスタイルで変換されたかをタイムスタンプとともにpostするAPIを作り、データをdynamoに保存しています。

データを集計するために、上記の情報を元に変換数ごとに並び替えた状態でスタイルの情報を返却するLambda関数を作り、集計結果をdynamoの別テーブルに保存しています。
そのLambda関数はEventBridgeで一日に1回動かすようにしています。

そして、集計結果が保存されてるdynamoのテーブルにアクセスしてデータを取得するAPIを作って、クライアント側から呼び出してランキング順に表示しています。

フロントエンドに関してはいつものNext.js + TypeScriptで組みましたが、今回初めて[Chakra UI](https://chakra-ui.com/)を使ってみました。
非常に使いやすかったので今後もリピートしようと思います。

## あとがき

ハロウィンは終わっちゃいましたが、ハロウィン後も楽しめるアプリだと思うので、ぜひ遊んでいただけると嬉しいです！
joisc2010 日本情報オリンピック春合宿OJ 本選会場(Finals)  解答

##問題
これ:
>JOI 国には N 個の都市があり，1 から N の番号がついている．また，M 本の道路がある．全ての道路は異なる 2 つの都市を結び，双方向に通行可能である．JOI 国の任意の 2 つの都市は，道路をたどって片方からもう片方へ到達可能である．JOI 国の道路は全て有料道路であり，道路ごとに通行料金が決まっている．
JOI 国でも情報オリンピックは開催される．JOI 国の情報オリンピックの本選には，各都市の代表選手が出場する．本選をどの都市で開催するかを決定し，選手をそれらの都市に集めるためにかかる金額を見積もっておく必要がある．本選は K 個の都市で開催し，本選の際には全ての選手をそれらのいずれかの都市に移動させなければならない．1 つの都市に集まる選手の人数に制限はない．
本選を開催する都市に選手を集める際には，道路を利用する．通行料金が c の道路は，一度に何人で通行しても料金は c である．そこで，選手を移動させる順番を工夫することによって，複数の選手を一度に通行させるようにすれば，料金を節約することができる．
本選を開催する都市を決定し，選手を本選会場に集める際にかかる通行料金の和を最小化したい．

https://atcoder.jp/contests/joisc2010/tasks/joisc2010_finals

##方針
各選手の移動距離に注目することで、"選手を移動させる順番"を無視してよいと分かるから、最も経済的な会場とルートの組を見つけられれば十分。さらに、出力は通行料金の最小値なのでルートだけ特定できれば十分。

そのようなルートは、各都市を安い道路から繋いでいって木を作るとき（初期時点で木は n 個）、木が k 個になった時点で張られている辺として得られる。その重みの和が解であるが、それは、Kruscal 法において、停止条件として「木の数がk個」なる条件を足すことで得られる。

時間計算量は sort 部分のオーダーに等しいから、10^5 の N と M ならば十分に間に合う。

##実装
典型的な Kruscal 法の実装に木の数を格納する変数 count_trees を加えて、それを基にした exit 条件を増やしただけ。

```cpp
#include <atcoder/all>
using namespace std;
#define rp(i, n) for (int i = 0; i < n; ++i)
typedef long long ll;

struct edge_k {
    ll u;
    ll v;
    ll weight = 1;
    // ordering; weight < from < to
    bool operator<(const edge_k& rhs) const {
        if (weight == rhs.weight) {
            if (u == rhs.u) {
                return v < rhs.v;
            } else {
                return u < rhs.u;
            }
        } else {
            return weight < rhs.weight;
        }
    }
    edge_k(const ll& u, const ll& v, const ll& w) : u(u), v(v), weight(w) {}
    edge_k(const ll& u, const ll& v) : u(u), v(v) {}
    edge_k() {}
};

using kruskal_graph = vector<edge_k>;

int main() {
    // store input
    ll n, m, k;
    cin >> n >> m >> k;
    kruskal_graph g(m);
    rp(i, m) {
        ll a, b, c;
        cin >> a >> b >> c;
        --a;
        --b;
        g[i] = edge_k(a, b, c);
    }

    auto kruskal = [&](kruskal_graph& g) -> ll {
        ll res = 0;

        // sort by weight
        sort(g.begin(), g.end());

        ll count_trees = n;
        atcoder::dsu uf(n);
        for (auto e : g) {
            ll u = e.u;
            ll v = e.v;

            // skip if merging (u,v) cause a cycle
            if (uf.same(u, v)) continue;

            // end loop if exactly k trees are there
            if (count_trees == k) break;

            res += e.weight;
            // merge until exit by break
            --count_trees;
            uf.merge(u, v);
        }
        return res;
    };

    // show
    cout << kruskal(g) << endl;
}
```
AWSで Wordpressを設置する際にRDSに接続できなくてはまった時のメモ

##RDSって何？
Amazon Relational Database Servicesの略。

##RDSって作らないといけないの？
EC2のなかに直接作ることもできるけど、その場合スケーラブルな調整ができなくなるのでRDSあった方がいいらしい。

##RDSの設定値がたくさんありすぎて選べないのだが？
少なくとも、ストレージに関しては最小単位で選択しておけば後で上げることができる。
ストレージに関しても料金が変わってくるのでどれを選択すればいいか迷ったときに
参考にしたサイト：
https://qiita.com/jyotti/items/d47b52fa13d12476406f

DBのインスタンスサイズは、後で大きくしたり小さくしたり変更できる。

##プライベートサブネット、パブリックサブネット
公開するWebサーバはパブリックサブネットに配置し、公開対象としないプライベートサブネットにDBサーバを置く。

##Webサーバ（EC2)からRDSに接続する時にうまくいかなかった
セキュリティグループの設定を見直したらうまくいった。
RDSに接続可能なのは事前に作っておいたセキュリティグループのみに設定しておいたのだが、
途中で別の担当者がセキュリティグループの設定にプロキシ設定を挟んでくれたせいなのか、うまく動かなくなっていた。

##参考になったサイト
https://creative-studio.jp/%E3%80%90aws%E3%80%91rds%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%92%E7%AB%8B%E3%81%A6%E3%81%A6wordrpess%E3%82%92%E6%A7%8B%E7%AF%89%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B/
PHP入門

# PHP超基礎文法
PHPを勉強し始めたので自分用にまとめていきます。Progateで勉強しています。
***

## Hello World
```php
<?php echo 'Hello World';?>
```
- <?php ~ ;?>
~ の部分にphpのコードを書く
セミコロンを文末に入れる

- echo
出力命令

- 文字列
文字列にはシングルクォーテーションかダブルクォーテーションをつける
数値には不要

## 変数
```php
$num = 1;
$num++; //$num += 1;　と同義
echo $num++; //echoの後にプラス　結果2
echo ++$num; //echoの前にプラス　結果3
```
- 変数
$英単語の形
数字スタート・ローマ字不可

- 変数更新
後に書かれたコードが優先される
+=や++など利用可能

```php
$hello = 'こんにちわ'；
$name = 'イチロー'；
echo $hello.$name; //　こんにちわイチロー
$name.= 'さん'; //イチローさん
echo "こんにちわ{$name}" //こんにちわイチローさん
```
- 文字列の結合
ドットを用いることで文字列を連結可能

- 変数展開
文字列内に変数を挿入する場合はダブルクォーテーションで囲む

## 条件分岐
```php
$num = 50;

if($num > 40){
 echo '40より大きい';
}elseif($num >= 30){
 echo '30以上';
}else{
　　echo '30より小さい';
}　//４０より大きい

$remainder = $num % 3;

switch ($remainder) {
　case 0:
　　echo '大吉';
　　break;
        
　case 1:
　　echo '中吉';
　　break;
      
　case 2:
　　echo '小吉'
　　break;
        
　default:
　　echo '凶';
　　break;
}
```
- 条件分岐 if
if（条件式） ~ elseif（条件式） ~ else　の形

- 条件分岐 switch
switch(式) ~ case ~ default　の形。
式がcaseの値に一致した時、該当のcaseが実行される。（該当なしの時はdefaultが実行）
break命令がないと後ろのcaseブロックが続けて実行される。

## 配列
```php
$titles = array('aaa','bbb','ccc');
$titles[] = 'ddd'; //配列の値を追加
$titles[1] = 'eee'; //bbbがeeeに値更新

$titles = array(
           'a' => 'aaa', 
           'b' => 'bbb',
           'c' => 'ccc'
          ); //キー => 値
echo $titles['a']; //結果:aaa
$titles['d'] = 'ddd'; //値の追加
```
- 配列
$〇〇 = array('aaa','bbb','ccc');　の形

- 連想配列
'キー' => '値'
キーによって値を呼び出せる

## 繰り返し処理
```php
for($i = 1; $i <= 100; $i++){
 echo $i;
}
```
- 繰り返し処理 for

1.変数の初期化 $i = 1

2.ループの条件 $i <= 100

3.繰り返す処理 {echo $i;}

4.変数の更新 $i++

```php
$i = 1;
while($i <= 100){
 echo $i;
 $i++;
}
```

- 繰り返し処理 while

1.変数の初期化 $i = 1

2.ループの条件 $i <= 100

3.繰り返す処理 {echo $i;}

4.変数の更新 $i++

```php
$names = array('Taro','Ichiro','Jiro');
foreach($names as $name){
 echo $name;
} //配列


$names = array(
 'Tanaka' => 'Taro',
 'Suzuki' => 'Ichiro'
 'Yamada' => 'Jiro'
);
foreach($names as $key => $value){
 echo $key.$value;
} //連想配列
```
- 配列の繰り返し処理　foreach

配列`$names`の要素を順番に`$name`に代入していく。

連想配列の場合はキー変数も利用できる。
***
### 繰り返し+α
```php
for($i=1; $i<=100;$i++){
 if($i>50){
  break;
 }
}
```
- break

ループを強制的に終了させる

```php
for($i=1; $i<=100;$i++){
 if($i%2==0){
  continue; //2で割り切れる時その周のループを終了し、次の周へ
 }
}
```
- continue

現在のループをスキップし、次のループへ

***
## 関数
```php
function hello($world){
 echo "hello,{$world}";
}

hello("Tokyo"); //結果：hello,Tokyo
```
- 関数の定義
function 関数（仮引数）{処理}　　の形で定義する

- 組み込み関数
元から使える関数
    - strlen : 文字数を数える
    - count :配列の要素を数える
    - rand :ランダムな整数を出す
FastApiで静的ファイルをマウントする

## 概要
- FastApiで静的ファイルを表示するときの備忘録
- index.htmlを自動で読み込みたければ設定が必要

## 構成
```
.
├── main.py
└── static
    ├── favicon.ico
    ├── index.html
    └── static
        ├── css
        └── js
```

## 静的ファイルのマウント
`StaticFiles`をimportしてdirectory指定することでマウントできます。
ただし、このままだと`/static`にアクセスしても`index.html`は表示されません。

```python:main.py
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()

app.mount("/static", StaticFiles(directory="static"), name="static")
```

### 対応方法
HTMLモードを有効にします。

FastApiのサイトには書いてないですが、[starlette](https://www.starlette.io/staticfiles/)のサイトに書いてあります。

```python:main.py
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles

app = FastAPI()

app.mount("/static", StaticFiles(directory="static", html=True), name="static")
```

## 参考
- https://fastapi.tiangolo.com/ja/tutorial/static-files/
- https://www.starlette.io/staticfiles/
Github don't ask certification but cannot push to remote repo

1. **`check you are using personal access token.`**

https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token

2. **`If Github don't ask but cannot access to remote, try to delete cache.`**

https://docs.github.com/ja/get-started/getting-started-with-git/updating-credentials-from-the-macos-keychain
Reactでnpm run buildした際に何も表示されない時の対処法

## 事象
- `npm run build`して、生成された`build`ディレクトリのindex.htmlを開いても真っ白で何も表示されない。
- 開発者ツールを確認しても特にエラーは表示されていない。

## 対策
- デフォルトで表示するコンポーネントを指定する
- ビルド後のファイルからjsを参照できるようにする

### デフォルトコンポーネントの指定
Routerの中にpathを指定しないコンポーネントを追加する。

これでデフォルトで表示するコンポーネントを設定できます。

```js:App.tsx
<Router>
  <div>
    <Route component={Home}/>
  </div>
</Router>
```

### ビルド後のファイルからjsを参照できるようにする
やることは`package.json`に`"homepage": "./",`を追加するだけです。

```json:package.json
{
   "name": "react-material-ui-sample",
   "version": "0.1.0",
   "private": true,
   "homepage": "./",
```


## 参考リンク
- https://qiita.com/stakezaki/items/2beceb3cc8b5dd696a8f
- https://github.com/facebook/create-react-app/issues/165#issuecomment-235801531
【備忘録】チェックボックス作成と変数の宣言

#チェックボックス作成と変数の宣言

@state
　値の更新を可能にする。
　宣言した変数を参照できるスコープの範囲を広げるための宣言？



```
struct CheckBox: View {
    @State var checked: Bool = false; //boolean型の変数定義
    var body: some View {
　　　　　//引数isOnに状態を表すBool型のプロパティを指定（※ここでは上記で定義したcheckedを指定）
        Toggle(isOn: $checked){
            //booleanの状態に合わせて表示を切り替え
            Text(checked ? "ON" : "OFF")
        }
    }
}
```

参考：https://capibara1969.com/2654/
sedで拡張正規表現 (ERE) を使う時は -r ではなく -E オプション（POSIX Issue 8 準拠）を使いましょう

## TL;DR

- POSIX Issue 8 で 拡張正規表現 (ERE) を使うための `-E` オプションが標準化されます。
  - もう `sed` で 基本正規表現 (BRE) を使う必要はありません。
  - POSIX Issue 8 は 2022 年後期予定ですが今使えるのであれば待つ必要はありません。
  - `-r` オプションは `-E` と同じ意味の古いオプションです。
- `s/foo/bar/i` ← この `i` (ignore case) も POSIX Issue 8 で標準化されます。
- `grep` でも `-E` オプションで ERE が使えます。
  - 昔は POSIX で標準化されていた（？）`egrep` も POSIX.1-2001 で廃止されています。
- `grep -E` で ERE、`sed -E` で ERE、`awk` は最初から ERE です。

## 標準化に至った経緯

- `-E` オプション
  - [0000528: Support extended regular expressions (EREs) in sed](http://austingroupbugs.net/view.php?id=528)
- `i` フラグ
  - [0000779: Add "ignore case" flag to sed's "s": s/old/new/I](https://www.austingroupbugs.net/view.php?id=779)

## 移植性について

GNU sed は かなり古い時代から ERE を有効にするオプションとして `-r` を持っていました。[ここ](https://unix.stackexchange.com/questions/377654/gnu-sed-version-history-changelog-how-can-you-determine-which-feature-was-in) によると GNU sed 4.0.6 (2003-03-18) から実装されているらしいです。（ただ試したら 3.02 ではドキュメント化されていませんでしたが使えました）。一般的には Debian 3.1 (2005) 頃から使えるようになったと考えて良いでしょう。

そして GNU sed 4.2.0 (2009-04-30) で `-r` オプションの移植性があるエイリアスとして `-E` オプションが追加されました。Debian 6.0 (2011) 頃より使えるようになったようです。ただしこの頃はまだ互換性のために追加されたアンドキュメントなオプションという扱いで `sed --help` に記載されるようになったのは Debian 9 からです。そのため `-E` は比較的最近追加されたオプションだと勘違いしている人も多そうです。

一方 FreeBSD ではかなり早く [4.1.1](https://www.freebsd.org/cgi/man.cgi?query=sed&apropos=0&sektion=0&manpath=FreeBSD+4.1.1-RELEASE&arch=default&format=html) (1993) の時点で `-E` オプションに対応していたようです。NetBSD も [1.6](https://www.freebsd.org/cgi/man.cgi?query=sed&apropos=0&sektion=0&manpath=NetBSD+1.6&arch=default&format=html) (1993) の時点で対応していました。OpenBSD は少し遅く [4.7](https://www.freebsd.org/cgi/man.cgi?query=sed&apropos=0&sektion=0&manpath=OpenBSD+4.7&arch=default&format=html) (2010) のようです。オープンソースの世界では 10 年ぐらい前から使えていたと考えて良いでしょう。

商用 Unix は、いつもの通り対応していませんね（[Solaris 11](https://docs.oracle.com/cd/E26924_01/html/E29112/sed-1.html)、[AIX 7.2](https://www.ibm.com/docs/ja/aix/7.2?topic=s-sed-command)）。まあこちらは POSIX で標準化された後に遅れて対応することになるのでしょう。

## まとめ

ということで、`sed -E` と `i` フラグは POSIX Issue 8 標準化されるので（商用 Unix を考慮しなくていいなら）もう安心して使えるようになったということです。POSIX も少しずつ変わっていますね！
ユーザーにDBアクセスの権限を設定する方法

#エラー
```
ERROR 1044 (42000): Access denied for user 'user'@'localhost' to database 'db'
```

どうやらuserに権限が付与できていない様子。

#解決策
root権限でmysqlにログインして、特定のユーザーに権限を付与すれば良い。

```
$sudo mysql -u root
$GRANT ALL PRIVILEGES ON db.* TO user@'localhost'
```

`GRANT ALL`のところは必要に応じて与える権限を変えてください。[参考](https://qiita.com/ritukiii/items/afdc91e68d0cf3e0f383)
Laravel Rules カスタムバリデーションルールを作成

# はじめに
複雑な条件や独特なバリデーションを作成したい時に便利なルールオブジェクトです。
あまり余計なものを書かずにシンプルに説明しています。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [Rulesファイルの作成](#rulesファイルの作成)
2. [Requestファイルにツールオブジェクトを設置](#requestファイルにツールオブジェクトを設置)
3. [ルールの作成](#ルールの作成)

<!-- 各チャプター -->
# Rulesファイルの作成
下記コマンドでRulesファイルを作成する。
app/Rulesフォルダ下にファイルが作成される。
※命名規則は多分アッパーキャメル

```
$ php artisan make:rule ファイル名
```
例

```
$ php artisan make:rule CheckWords
```


# Requestファイルにツールオブジェクトを設置
先程作成したCheckWordsをRequest.phpファイルのルールにセットする。

```
// Requestファイルでuse宣言
use App\Rules\CheckWords;


public function rules(Request $request)
    {
        return [
                  // new CheckWordsをバリデーションルールに追加
                  'content' => ['required', 'string', new CheckWords],
               ]
    }
```

# ルールの作成
ここでpasses( ) にオリジナルのバリデーションを記述。
passesの中に記述した処理が<font color="blue">trueの場合は、バリデーションを問題なく通過。</font>
<font color="blue">falseの場合は下記のmessage( )メソッドの内容でバリデーションエラーメッセージが表示される。</font>
message( ) にバリデーションのエラーメッセージを記述する。


```
<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class CheckWords implements Rule
{
    /**
     * Create a new rule instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Determine if the validation rule passes.
     *
     * @param  string  $attribute
     * @param  mixed  $value
     * @return bool
     */
    public function passes($attribute, $value)
    {
        // $attributeにはフィールド名(content)、$valueにはリクエストで送信した
　　　　　　　　　　　　　　　　　　　　　　　contentフィールドのデータが入っている。
        // $valueに'#'が含まれていればtrue。含まれていなければfalseとなり、
　　　　　　　　　　　　　　　　　　　　　　　下記message()内の処理を行う。

        return strpos($value, '#');
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        // 通常のバリデーションエラーメッセージと同じように下記のエラーが表示される。 
        return '投稿にハッシュタグがありません。必ず一つ付けてください。';
    }
}
```
BigQueryのスケジュールされたクエリでのカスタムスケジュールの書式

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/356023/6d0188e4-b31a-56ee-bade-a8dc7052218e.png)


↑これ

ただ、これ書き方がわからない。
厄介なことに、ツールチップのやつそのまま書くと動かないし、リンク先にも書き方は載っていない

# 結論
ここに記法が書いてある(`Custom Interval`を選択)
https://cloud.google.com/appengine/docs/flexible/python/scheduling-jobs-with-cron-yaml#formatting_the_schedule
※時刻書く場合はUTCなので注意

こんなのや

```
schedule: every day 00:00
schedule: every monday 09:00
```

こんなのもかけるらしい

```
schedule: 1st,3rd tuesday
schedule: 2nd,third wednesday of month 09:00

schedule: 2nd monday,thu
schedule: 1,8,15,22 of month 09:00
schedule: 1st mon,wednesday,thu of sep,oct,nov 17:00
```
ElixirをMacbookに入れて、IExを動かした

###homebrewを最新化

- 最初に、homebrewを最新化する。

```bash:Terminal
electron@diynoMacBook-Pro ~ % brew update
electron@diynoMacBook-Pro ~ % brew upgrade
```

（ 参考 ）

https://qiita.com/Sunochi/items/a3839129af3e76405855

```bash:Terminal
electron@diynoMacBook-Pro ~ % brew install elixir
```

###Erlangのバージョン確認

- Elixirは、ErlangのVMを使う。
- そのため、Elixirをインストールすると、Erlangも入る。

```bash:Terminal
electron@diynoMacBook-Pro ~ % erl +V
Erlang (SMP,ASYNC_THREADS) (BEAM) emulator version 12.1.3
electron@diynoMacBook-Pro ~ % 
```

###対話型インタプリタIExのバージョン確認

```bash:Terminal
electron@diynoMacBook-Pro ~ % iex --version
Erlang/OTP 24 [erts-12.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]

IEx 1.12.3 (compiled with Erlang/OTP 24)
electron@diynoMacBook-Pro ~ % 
```

###IExの動作確認

__（ 参考 ）__

- Dave Thomas（著）&笹田・鳥居（共訳）『プログラミング Elixir 第2版』（Ohmsha）

```bash:Terminal
electron@diynoMacBook-Pro ~ % iex +V       
Erlang/OTP 24 [erts-12.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]

No file named +V
electron@diynoMacBook-Pro ~ % 

electron@diynoMacBook-Pro ~ % iex
Erlang/OTP 24 [erts-12.1.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]

Interactive Elixir (1.12.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 
nil
iex(2)> 
nil
iex(3)> 
nil
iex(4)> IO.puts "Hello, Elixir!"
Hello, Elixir!
:ok
iex(5)> x = 1 + 1
2
iex(6)> IO.puts x
2
:ok
iex(7)> a = 1  
1
iex(8)> a
1
iex(9)> a = 2
2
iex(10)> a
2
iex(11)> a
2
iex(12)> a = 3
3
iex(13)> a
3
iex(14)> a
3
iex(15)> ^a = 1
** (MatchError) no match of right hand side value: 1

iex(15)> ^a = 5
** (MatchError) no match of right hand side value: 5

iex(15)> ^a = 3
3
iex(16)> a
3
iex(17)> list = [1, [2, 1], 7]
[1, [2, 1], 7]
iex(18)> list 
[1, [2, 1], 7]
iex(19)> list = [1, [2, 1], 7
...(19)> ]
[1, [2, 1], 7]
iex(20)> list = [1, [2, 1], 7]
[1, [2, 1], 7]
iex(21)> lsit = list
[1, [2, 1], 7]
iex(22)> [a, b, c] = list
[1, [2, 1], 7]
iex(23)> a
1
iex(24)> b
[2, 1]
iex(25)> c
7
iex(26)> name = "elixir"
"elixir"
iex(27)> name
"elixir"
iex(28)> name = name
"elixir"
iex(29)> name = String.capitalize name
"Elixir"
iex(30)> name
"Elixir"
iex(31)> name = "elixir"
"elixir"
iex(32)> ^name = String.capitalize name
** (MatchError) no match of right hand side value: "Elixir"

iex(32)> name
"elixir"
iex(33)> ^name
** (CompileError) iex:33: cannot use ^name outside of match clauses

iex(33)> cap_name = String.capitalize name
"Elixir"
iex(34)> cap_name
"Elixir"
iex(35)> name
"elixir"
iex(36)> name
"elixir"
iex(37)> ^name = ^cap_name    
** (CompileError) iex:37: cannot use ^cap_name outside of match clauses

iex(37)> name = ^cap_name
** (CompileError) iex:37: cannot use ^cap_name outside of match clauses

iex(37)> name = cap_name 
"Elixir"
iex(38)> name
"Elixir"
iex(39)> cap_name
"Elixir"
iex(40)> 
BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution
^C%                                
```

最後はCTRL-Cを2回打って、IExから抜ける。
PythonからWindows APIを使ってウィンドウ表示

#はじめに
ctypesパッケージを使ってWindows APIを呼び出すサンプルとしてウィンドウを表示してみた。

![winapp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257554/5f334710-989c-8921-bfcc-3e212acd06b7.png)

#ソース

```winapp.py
from ctypes import *
from ctypes.wintypes import *

gdi32 = windll.gdi32
kernel32 = windll.kernel32
user32 = windll.user32

CS_HREDRAW = 0x0002
CS_VREDRAW = 0x0001
IDC_ARROW = 32512
COLOR_WINDOW = 5
WS_OVERLAPPEDWINDOW = 0x00CF0000
CW_USEDEFAULT = 0x80000000
SW_SHOWDEFAULT = 10
WM_DESTROY = 0x0002
WM_PAINT = 0x000F
WNDPROC = WINFUNCTYPE(LONG, HWND, UINT, WPARAM, LPARAM)

class WNDCLASSEXW(Structure):
    _fields_ = [
        ("cbSize", UINT),
        ("style", UINT),
        ("lpfnWndProc", WNDPROC),
        ("cbClsExtra", c_int),
        ("cbWndExtra", c_int),
        ("hInstance", HINSTANCE),
        ("hIcon", HICON),
        ("hCursor", HANDLE),
        ("hbrBackground", HBRUSH),
        ("lpszMenuName", LPCWSTR),
        ("lpszClassName", LPCWSTR),
        ("hIconSm", HICON),
    ]

class PAINTSTRUCT(Structure):
    _fields_ = [
        ("hdc", HDC),
        ("fErase", BOOL),
        ("rcPaint", RECT),
        ("fRestore", BOOL),
        ("fIncUpdate", BOOL),
        ("rgbReserved", BYTE * 32),
    ]

def WinMain(hInstance, nShowCmd):

    wc = WNDCLASSEXW()
    wc.cbSize = sizeof(WNDCLASSEXW)
    wc.style = CS_HREDRAW | CS_VREDRAW
    wc.lpfnWndProc = WNDPROC(WndProc)
    wc.hInstance = hInstance
    wc.hCursor = user32.LoadCursorW(None, IDC_ARROW)
    wc.hbrBackground = HBRUSH(COLOR_WINDOW + 1)
    wc.lpszClassName = "winapp"

    ret = user32.RegisterClassExW(wc)

    hWnd = user32.CreateWindowExW(
        0, "winapp", "winapp",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, 0,
        CW_USEDEFAULT, 0,
        None, None, hInstance, None)
    user32.ShowWindow(hWnd, nShowCmd)
    user32.UpdateWindow(hWnd)

    msg = MSG()
    while user32.GetMessageW(byref(msg), None, 0, 0):
        user32.TranslateMessage(msg)
        user32.DispatchMessageW(msg)
    return msg.wParam

def WndProc(hWnd, uMsg, wParam, lParam):
    if uMsg == WM_DESTROY:
        user32.PostQuitMessage(0)
        return 0
    if uMsg == WM_PAINT:
        OnPaint(hWnd)
        return 0
    return user32.DefWindowProcW(hWnd, uMsg, WPARAM(wParam), LPARAM(lParam))

def OnPaint(hWnd):
    ps = PAINTSTRUCT()
    hdc = user32.BeginPaint(hWnd, byref(ps))
    txt = "hello, world"
    gdi32.TextOutW(hdc, 10, 10, txt, len(txt))
    user32.EndPaint(hWnd, ps)

hInstance = kernel32.GetModuleHandleW(None)
WinMain(hInstance, SW_SHOWDEFAULT)
```

#実行

```
py winapp.py
```
WSL×VSCode×JupyterNotebook

タイトルのまま
ほぼ自分用メモ

## 前提
- Windows
- WSL
- VSCode
- JupyterNotebook

## 1.WSLでLinux環境構築
Microsoft StoreでUbuntuインストール

## 2.WSL上にpyenvでPython環境構築
こちらの記事のとおりによしなにやる（GitHubに上がっているスクリプトを実行する）

https://qiita.com/HoriThe3rd/items/ea4c98f8518d107bd161

ただしWindowsでGit Cloneすると改行コードがCRLFになり、WSL上で実行するときにエラーが発生するので
VSCodeで開いてLFにしてから保存などするとよろし

## 3. VSCodeでRemoteWSLインストール
拡張機能インストールするだけ（多分RemoteDevelopとかと同じ）
左下の><をクリックして
`New WSL Window Using distro...`
をクリックして、インストールしたUbuntu環境を選択する

## 4. WSL環境のVSCodeで拡張機能インストール
JupyterとかPythonの拡張機能をインストールする
（なんかすぐに切り替わらないので謎だけど、最初はインストールできなかったりするのでVSCode閉じたり開いたりする）

あと
`pip install -U ipykernel`
する

そしたら使えるようになる。やったね
オンライン開催のMicrosoft Igniteに初参加するための手順

知人がオンライン開催の「Microsoft Ignite」へ初参加できるようにと書いた手順メモなのですが、せっかくなのでQiita化しました。毎回使える内容かどうかわかりませんが、今回は日本時間2021年11月3,4日にオンラインで開催される「Microsoft Ignite November 2021」をベースに書いています。

## はじめに

「Microsoft Ignite」は、米国Microsoft社が毎年主催している全世界規模の技術者向けのフラッグシップイベントです。

Webブラウザーにて「Microsoft Ignite」サイトのトップ画面にアクセスします。

- [Your home for Microsoft Ignite](https://myignite.microsoft.com/home)

## サイトにログインする手順

1. トップ画面の「[Attendee sign in](https://myignite.microsoft.com/auth-redirect?dest=home)」リンクをクリックします。
2. Microsoft、LinkedIn、GitHubの何れかのアカウントをお持ちの方は、各アカウントのボタンをクリックした後、各アカウントでログインします。
3. 上記の各アカウントをお持ちでない方は、下記の「アカウントを新規作成する場合の手順」でIgniteアカウントを新規登録した後、登録したメールアドレスとパスワードを入力して「サインイン」ボタンをクリックしてログインします。

## アカウントを新規作成する場合の手順

1. トップ画面にて、「[Register now](https://register.ignite.microsoft.com/auth/login)」ボタンをクリックします。
2. Welcome画面にて「Sign in」ボタンをクリックします。
3. Welcome画面にて、画面を下にスクロールして「アカウントがない場合」欄の「Sign up now」リンクをクリックします。
4. 登録画面にて、電子メールアドレスとパスワード（確認用も）を入力して「作成」ボタンをクリックします。

## セッションを検索する手順

1. トップ画面にて、画面上部の「Sessions」リンクをクリックします。
2. 表示された一覧から該当のリンクをクリックします。遷移先では文字列検索欄があります。

Session catalog：今回の「Ignite November 2021」をセッション単位で検索できます。
Speaker directory：今回の「Ignite November 2021」で登壇者単位で検索できます。
Session archives：過去のIgniteのセッション動画（前回の「Ignite March 2021」と、前々回の「Ignite 2020」）を検索できます。

## サイトからログアウトする手順

1. 画面右上の「Hi ○○」リンクをクリックします。
2. 表示された一覧から「Sign out」リンクをクリックします。

## さいごに

私ですが、今回唯一の日本語セッション「[Japan Local Connection: 技術を学ぶその先にあるもの Learning Together, Growing Together](https://myignite.microsoft.com/sessions/3f0fc384-32d3-4856-8e14-6110deb1ce1d) 」に、6名の方々と共に登壇させて頂きます。
【Python】スクリプトから簡易編集モードを無効にする

#はじめに
コマンドプロンプトなどコンソールウィンドウをpythonの標準出力として使う場合､ 簡易編集モード(QuickEdit)は便利ですが､ 処理の実行中に標準出力を使う場合などには意図しない中断を招いてしまいます｡


もちろんコンソール画面を右クリックすればプロパティからの変更はできるのですが､自分以外の人間の利用を想定する場合にはコードで設定できた方がうれしいです｡


#簡易編集モードを無効化するスクリプト




```python
import ctypes

kernel32 = ctypes.windll.kernel32
mode=0xFDB7 #簡易編集モードとENABLE_WINDOW_INPUT と ENABLE_VIRTUAL_TERMINAL_INPUT をOFFに
kernel32.SetConsoleMode(kernel32.GetStdHandle(-10), mode)

```
これだけです｡
(注) コンソールウィンドウが出てからこの処理が実行されるまでのわずかな時間は簡易編集モードが有効になっています｡

以下を参考にしました
[How to enable Windows console QuickEdit Mode from python?](https://stackoverflow.com/questions/37500076/how-to-enable-windows-console-quickedit-mode-from-python)
[GetStdHandle 関数](https://docs.microsoft.com/ja-jp/windows/console/getstdhandle)
[SetConsoleMode 関数](https://docs.microsoft.com/ja-jp/windows/console/setconsolemode)



自分の理解できた範囲で簡単に説明すると､

- ctypesはC/C++のライブラリを呼んできてくれるらしい

- GetStdHandle(-10)の引数は-10だと標準入力, -11だと標準出力のハンドル?をとってきてくれるらしい

- SetConsoleModeでコンソールウィンドウの設定を変更できる｡設定は16ビットで簡易編集モード(QuickEdit)の設定は0x0040の部分

- 上に貼った記事によるとコンソールウィンドウの設定のうちデフォルトでOFFなのがENABLE_WINDOW_INPUT(0x0008)とENABLE_VIRTUAL_TERMINAL_INPUT(0x0200)なのでそこもOFFにすると0xFDB7(2進数なら0b1111110110110111)になる

本当はGetStdHandleで現在の状態を取得して簡易編集モードだけを無効にしたかったのですが､ byrefの扱いがよく分からず断念しました｡
【Rails】マイグレーションファイル関連のコマンドまとめ

##はじめに
マイグレーションファイル関連のコマンドのまとめです。

##migrationを実行

```
$ rails db:migrate
```
##データベースを作成

```
$ rails db:create
```
##データベースを削除

```
rails db:drop
```

##migrationの実行、データベース作成、削除をまとめて行う

```
$ rails db:reset
```


##migrationを削除
削除する際にはまず、ステータスを確認。

```
＄ rails db:migrate:status
```
ステータスの部分がdownになっていれば削除。
upになっている場合、downにする。

```
$ rails db:rollback　 ・・・　一つ前をdownにする
$ rails db:rollback STEP=○ ・・・　○個前までdownする
$ rails db:migrate:down VERSION=20211101101010　　・・・　ファイルを指定してdownする
```
最後の「20211101101010」の部分はrails db:migrate:statusをした時に表示されるMigration IDです。

ステータスをdownにしてから削除。

```
$ rm db/migrate/ファイル名
```

downする前に削除してしまった場合、
rails db:migrate:statusで確認をするとNOFILEの表示。
同名のファイルを作成してから、down→削除

```
$ touch db/migrate/ファイル名 ・・・作成
$ rails db:migrate:down VERSION=Migration ID　・・・down
$ rm db/migrate/ファイル名　・・・削除
```
もしエラーで削除できないという場合は
作成したファイルの中身を全部コメントアウトしてみればできるかもしれません。

また学習していけば追記していきます。
React GoogleMapAPIで住所or地名から座標（緯度経度）を取得する。

#はじめに
Reactで住所や地名から座標（緯度経度）を取得する方法をまとめました。
以下の方に、参考になれば幸いです。
・Reactにて住所検索してMap上に表示させたい方。
・住所をDB登録して、マーカー等を一覧で表示させたい方

#導入方法
以下のページを参考に、GoogleMapのAPIキーの取得と有効化とGeocoding APIの有効化を行います。
https://qiita.com/Haruka-Ogawa/items/997401a2edcd20e61037

次に、ライブラリを利用する準備を行います。

```react:ターミナル
$ npm install --save @react-google-maps/api
```

# 住所から緯度経度を取得
下記のコードで取得できる。

```react:get.js
import React from 'react';
import { useState } from 'react';
import { LoadScript } from '@react-google-maps/api';

function Get() {
  const [place,setPlace] = useState();
  const [lat,setLat] = useState("");
  const [lng,setLng] = useState("");

  const changeLocationName = (event) => {
    if (event.key === 'Enter') {
      geocode();
      return;
    }
    setPlace(event.target.value)
  }

  function geocode() {
    const geocoder = new window.google.maps.Geocoder();
    geocoder.geocode({ address: place }, (results, status) => {
      if (status === 'OK') {
        setLat(results[0].geometry.location.lat()),
        setLng(results[0].geometry.location.lng());
      }
    });
  }

  return (
     <React.Fragment>
        <div>
           <input type="text" 
             onChange={(event) => changeLocationName(event)} 
             onKeyPress={(event) => changeLocationName(event)}
           />
           <LoadScript googleMapsApiKey{"取得したAPIキー"}>
           </LoadScript>
　　　　　　　　　　　　　　　　　　　　　<p>緯度：{lat}</p>
　　　　　　　　　　　　　　　　　　　　　<p>緯度：{lng}</p>

　　　　　　　　　　　　　　　　　　　{/* 実行結果
              input:福岡県
              output:緯度：33.566255900000010000
                     経度：130.715857
         */}
       </div>
     </React.Fragment>
  );
}

export default Get;
```
#解説
まずは、ライブラリをインポートする。

```react:get.js
import { LoadScript } from '@react-google-maps/api';
```

<br>

住所か地名を入力するときに以下の場面で発火する。
onChangeはinputの値が変更されたら発火する。
onKeyPressはキーボードが押下されたら発火する。その際、どのキーが押されたかを見ている。

```react:get.js
<input type="text" 
             onChange={(event) => changeLocationName(event)} 
             onKeyPress={(event) => changeLocationName(event)}
           />
```

<br>

前段のinputで入力されたものをuseStateに保管する。
入力後にENTERキーを押すと次項のgeocode()が動く。

```react:get.js
 const changeLocationName = (event) => {
    if (event.key === 'Enter') {
      geocode();
      return;
    }
    setPlace(event.target.value)
  }
```

<br>

最後に、useStateに保管されている、地名や住所から緯度経度を取得。
その後、それぞれのuseStateに入れる。

```react:get.js
  function geocode() {
    const geocoder = new window.google.maps.Geocoder();
    geocoder.geocode({ address: place }, (results, status) => {
      if (status === 'OK') {
        setLat(results[0].geometry.location.lat()),
        setLng(results[0].geometry.location.lng());
      }
    });
  }
```

<br>

ここで、googlemapapiで認証を受けている。
取得したAPIキーは導入方法で取得したAPIキーを入力する。

```react:get.js
<LoadScript googleMapsApiKey{"取得したAPIキー"}>
</LoadScript>

```

#まとめ
今回は、住所や地名から緯度経度を取得する方法をまとめました。
最後まで、読んでいただきありがとうございます。
DHCPでもIPsecVPN経由でインターネット接続したい！（RTX810編）

この度、RTX810 2台で2拠点間のインターネットVPNを結んだ後、インターネット接続をIPsec経由にするにあたり、少々躓いたのでメモ。

# 前提
- RTX810 2台での2拠点間のIPsecVPNが確立済
- Rev.11.01.34
- 双方ともWAN側がDHCPだが、グローバルアドレスは半固定
- 拠点1のプライベートアドレスは192.168.1.0/24
- 拠点2のプライベートアドレスは192.168.2.0/24
- sshでRTX810を操作可能

# やりたいこと
現状、拠点1ルータ配下の端末と拠点2ルータ配下の端末は、それぞれのLANへの通信のみVPNを経由する設定になっており、インターネット接続についてはそれぞれのゲートウェイから出るようになっている。
拠点2ルータ配下の端末については、インターネット接続を拠点1経由としたい。

整理すると、次のような要件になります。

- 拠点2ルータからのIPsec通信は今のままつながるようにしつつ
- 拠点2ルータ配下の端末からの通信はすべてIPsecのトンネルに流したい

RTXの仕様を調べると、取れる方法は2つありそうです。

- フィルタ型ルーティング
- パケット転送フィルタ

この内、フィルタ型ルーティングは固定IPを前提としているため、DHCPは利用できません。（※ここでハマりました）
なので、パケット転送フィルタを利用することとしました。

(以下余談)
PPPoEなどで固定IPで接続している方はどちらでも可能です。

フィルタ型ルーティングはいわゆるポリシーベースルーティングで、フィルタに設定した条件によって、同じ経路から来ても複数の経路に流せる機能です。
パケット転送フィルタはルーティングとは異なる機能で、フィルタに設定した条件によって、ルーティングテーブルを迂回してインターフェイスに直接飛ばすもので、ルータというかファイヤウォール的な機能、だと思います。


# 実装
```
administorator
# パスワードを入力

console character ascii

show config
# 事前のコンフィグを取っておく

ip filter 100 pass 192.168.2.16/28 * * * *
# 192.168.2.16〜31からの通信をまでをフィルタ100に登録

ip forward filter 200 1 gateway tunnel 1 filter 100
# フィルタ100にヒットするパケットをtunnel 1に転送するパケット転送フィルタをフィルタ200に登録

ip lan1 forward filter 200
# lan1からくるパケットをフィルタ200に従って転送

dhcp scope 1 192.168.2.16-192.168.2.31/24
# dhcpで振るアドレスをフィルタ1に合わせる

show config
#設定が正しく反映されていることを確認

save
quit
quit
```

# 終わりに
最初、DHCPではフィルタ型ルーティングが使えないことに気づかないまま、うまく行かず、半日ほど無駄にしたあとで、パケット転送フィルタに気づきました。
はまらなかった人にとっては全く不要な記事ですが、意外とネットで調べても引っかからなかったので一応メモに残しておきます。

以上
WSUS とは

## 勉強前イメージ

全然わからん、、、なんの略？

## 調査

### WSUS とは

ダブルサスと読み、Windows Server Update Services の略になります。
普通であればwindowsのアップデートはPC1台ずつアップデートのサーバにアクセスして、
更新プログラムをもらってダウンロード、インストール という形だが、
企業内のPCが一斉に行った場合、大きなトラフィックが発生し、業務に支障を来す可能性がある。
それを解決するのがWSUSで、
WSUSサーバを社内に設置し、WSUSサーバが更新プログラムを受け取って各PCに配布するというものである。
これであれば外部との通信が圧迫されることもなく、配信のスケジュールも組むことができます。

### WSUSのメリット

- 外部との回線を圧迫しない

更新プログラムはWSUSサーバが受け取るので、外部との回線を圧迫しません

- 検証機で先行して適応できる

検証機に適応し、確認してから本番機に適応できる

- 適用する更新プログラムの管理

たまにwindows updateで更新を行った際に特定アプリケーションなどで不具合が出るようなことがあります。
検証機で確認してから他のPCにも適応する、ということができるので
更新する・しないも管理出来るようになります。

- グループ・スケジュール管理

各PCをグループ化して管理することが出来るので、
特定部署にだけ更新プログラムを適応なども出来る。

## 勉強後イメージ

確かにwindows updateって結構時間かかるし遅くなっちゃう・・・・
いっぱいクライアントのPCがあると圧迫するから中継するサーバのことなのね。

## 参考

- [第13回 「WSUS」](https://www.fielding.co.jp/column/it_words/202002_1/)
- [WSUSとは？役割や必要性、導入方法などを紹介！](https://www.sei-info.co.jp/mcore/basics/wsus.html/)
[Docker]コマンド基本

# 前提
Dockerのコマンドは近年、以下の書式に統一しようという動きがある。

`docker コマンド 操作 オプション`

そのため、一つのコマンドに二通りの書き方があったりする。
`docker run ~~~~~`
`docker container run ~~~~~`

# container
`docker container xxx` でも同じコマンドとなる。

## docker ps / docker container ls
`docker ps -a`では停止中のコンテナを含めて表示が可能。

## docker run
### オプション
#### -v
フォルダのマウントを指定する
`-v ホストのマウント元フォルダ:コンテナのマウント先フォルダ`

#### -w
コマンドを実行する際のワークディレクトリを指定
`-w /usr/src/myapp`

#### -p
ポートフォワーディングを設定
`-p ホストのポート:コンテナのポート`

#### --rm
コマンドの実行後に削除する
`--rm`

## docker exec
実行中のコンテナ内でコマンドを起動する。
`docker exec -it my-container-name /bin/bash`

シェルコマンドは配布されているイメージでは基本的に入っているため、/bin/bashでシェルを起動できる。

## docker start {コンテナ名/コンテナID}
*コンテナIDは全て入力するのが面倒なため、頭文字いくつかを入力すればコンテナIDを認識してくれるようになっている。

## docker stop {コンテナ名/コンテナID}

## docker rm {コンテナ名/コンテナID}

## docker logs {コンテナ名/コンテナID}
*「何をコンテナのログとするか」は設定ファイルによって変更可能。

# image
## docker image ls

## docker image rm {repository名:TAG}
*TAGを指定しないとlatestが削除

# その他
## docker cp
ホスト→コンテナにコピー
`docker cp オプション コピー元のパス名 コンテナ名またはコンテナID:コピー先パス名`


コンテナ→ホストにコピー
`docker cp オプション コンテナ名またはコンテナID:コピー元パス名 コピー先のパス名 `
SESから社内SEに転職して変わったこと

はじめまして。ドモナといいます。初投稿します。

僕はSESから社内SEに転職してもうすぐ半年が経ちます。同じエンジニアでもSESと社内SEとではかなり違いがあるので、今日はその違いをまとめてみます。
※社内SEのスタイルは会社によって違ったりすると思うので、あくまで僕のいる会社はこう、ということを書きます。

## 納期という概念がない
SESの頃は要件定義、設計、開発のどの工程にも納期があって、もっと細かい単位のタスクにも必ず期限がありました。
社内SEになってからはそもそも納期という概念がなく「できるだけ早く欲しいけどいつ頃できる？」っていう感じで聞かれることが多いです。

## 残業がない
会社によって大きく違うところかもしれないですが、僕の今いる会社では基本的に残業は禁止です。
SESの頃はと言えば、残業どころか休日出勤さえ当たり前のこともありました。

## 社内作業が定時内にできる
SESでは客先での勤怠管理と自社の勤怠管理があったり自社への作業報告があったり、その他諸々の作業は定時後とか土日にやってました。
社内SEではそもそもそういう面倒な作業はほとんどなくて、あっても定時内にちゃちゃっとできます。

## スキルの幅が求められる
技術的な部分で言うとSESより社内SEの方が幅広くなんでもできる必要があります。
インフラ部門とかアプリ部門とかで分かれてたりしないので、自分が担当するシステムはインフラから設計、開発、保守まで全部自分でやります。
あと、たまにパソコンに慣れてない人たちのサポートをしたりもします。


## 一緒に仕事をするのはエンジニアじゃない
SESでは一緒に仕事をする人のほとんどがエンジニアです。
社内SEの場合は業務の担当者とか責任者で、エンジニアではない人と接することが多くなります。

## レビューの工程がない　※2021/11/2追記※
SESに限らず、普通のシステム開発の各工程には必ずレビューがあると思います。
（うちの会社だけかもしれませんが）社内SEでは基本的にレビューがないことがほとんどです。とはいえ必須の工程でないというだけで、上長などにお願いすればレビューしてもらうこともできます。

## 技術選定も自分でやる　※2021/11/6追記※
SESの場合、既に技術選定が行われた後に参画することが多かったり、そもそも客先で言語やフレームワークが標準化されたりしていました。
社内SEになってからは全てがエンジニア次第になるので、技術選定も当然自分でやることになります。
業務部門の要件やエンジニア自身の興味関心によって技術選定を行うことになります。

## まとめ
ざっと挙げてみましたが、まだ他にもあるかもしれないので、思いついたら追記します。
たまたまかもしれませんがSESの頃と比べると、今の会社での環境があまりにも良すぎて逆に戸惑ってます。

転職して手に入れた自由な時間を使って、転職の体験談や実際に転職した方法などを書いたブログもやってるので、よかったら見てみてもらえると嬉しいです。
→[ドモナのブログ][1]
[1]:https://domona.info/can-change-jobs/
Dataflow Workbench で CloudSQL のデータを BigQuery フェデレーションでみる

# Dataflow Workbench の起動
Google Cloud Console > Dataflow > Workbench

![Screen Shot 2021-11-01 at 23.14.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54176/7371b954-341b-f4a0-ca43-3bf1818b3661.png)

新しいノートブック > Apache Beam > Without GPUs をクリックして、設定はそのままに「作成」。
立ち上がったら、「JUPYTERLABを開く」をクリック。

# コード
```py
import apache_beam as beam
from apache_beam.runners.interactive.interactive_runner import InteractiveRunner
import apache_beam.runners.interactive.interactive_beam as ib
```

```py
from apache_beam.options import pipeline_options
#from apache_beam.options.pipeline_options import GoogleCloudOptions
#import google.auth
```

```py
from apache_beam.io import ReadFromBigQuery
```

```py
ib.options.recording_duration = '1m'
```

```py
options = pipeline_options.PipelineOptions(project='<project id>', temp_location='gs://<bucket name>/temp')

p = beam.Pipeline(InteractiveRunner(), options=options)
```

```py
# need to grand BigQuery connection user paermission to Compute Engine default Service Account
query='SELECT * FROM EXTERNAL_QUERY("projects/<project id>/locations/us/connections/cloudesql-fed", "SELECT * FROM federation_test.item;");'
```

```
query_results = p | beam.io.ReadFromBigQuery(
    query=query, use_standard_sql=True)
```

```
ib.show(query_results, include_window_info=True)
```

# 結果
こんな風にみれる。CloudSQLのフェデレーションでもDataflowでデータ取れた。
![Screen Shot 2021-11-01 at 23.22.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54176/7e08d8b7-8e44-3a54-e17a-9221dfaa4394.png)
VBOファイルがLAP+で読めないとき

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241416/735f78b0-122f-dd05-d578-b70746ee0a9d.png)


こんなエラーメッセージでVBOファイルがLAP+で読めないことが有りますが、
Time列の小数点第2位の桁を0にすると読めました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241416/d258254c-1711-e4c0-97c6-04157dd81f17.png)
[Flask]ModuleNotFoundError: No module named 'app'

#エラー
初めてFlaskにデプロイする際、タイトルのようなエラーが出て困ったので解決方法をメモしておく。

```:エラー
ModuleNotFoundError: No module named 'app'
```

#解決方法
[このサイト](https://stackoverflow.com/questions/22711087/flask-importerror-no-module-named-app)より
→pythonファイルの名前を`app.py`にしたら解決した。
npmとyarnをインストール（mac）

# Homebrewをインストール
```
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

# nodebrewをインストール
```
brew install nodebrew
```
「nodebrew」はNode.jsのインストールから複数のバージョンを管理・切り替えできるツール

# nodebrewをインストール
```
nodebrew install-binary latest
```

# nodebrewをインストール 
``` 
nodebrew use v7.1.0
```

# nodeバージョン確認
```
npm -v
```
【Windows10】マウス・キーボードでスリープ状態を解除するためのBIOS設定

#### 環境
OS: Windows 10 Pro (10.0.19043)
BIOS: msi click bios 5

#### 方法
マウス・キーボードでスリープ状態を解除するには、

1.「デバイスマネージャー」から各デバイスを選択し、「電源の管理」で「このデバイスで、コンピューターのスタンバイ状態を解除できるようにする」をオンにする。

![HID 準拠マウスのプロパティ 2021-11-01 22.44.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/8dd5b0d5-ec89-fbfa-64d3-17708cf11653.png)

2.「コントロールパネル」から「詳細な電源設定の変更」で「USBのセレクティブサスペンド設定」を無効にする

![電源オプション 2021-11-01 22.43.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/225268e9-2e74-b014-dde4-9db00fe6098c.png)

の2点を設定すれば良いが、さらにBIOS設定の変更が必要な場合もある。


#### msi click bios 5の場合
MSIのマザーボードに搭載されている「msi click bios 5」の場合は、PCの起動と同時に「deleteキー」を押してBIOS設定画面に入り、「Setting」→「拡張項目」→「Wake Up Event」で「USBデバイスによるS3S4ステートからのレジューム」を有効にしてやれば良い。

![MSI_SnapShot_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363491/a87de6cf-6dc0-522a-78a7-2c2d61a9c743.png)
Visual Studio 2019で 最新の React(Next.js) + TypeScript + ASP.NET Core を簡単に構築

Frontend は React(or Next.js) で、Backend を ASP.NET Core で開発したい。しかも React(or Next.js) の開発は Visual Studio Code がいい。TypeScript を使いたいし、npm じゃ yarn がいい。でも Visual Studio 2019 の React テンプレートだと React のバージョンが古いし、 jqueryなど余計なものも入っていてすごく嫌。

なんて思ったことないでしょうか。大丈夫、簡単にきれいなプロジェクトを作ることができます。実は何回やっても細かいところを忘れるのでいい加減メモとして残すことにしただけです。VS2022がもうすぐ出そうなこのタイミングで出す内容じゃないですけど、個人的なメモとして残しておきます。
以下の手順です。

## 1. VS のテンプレートを使ってプロジェクトを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/a0c7f7c7-8367-d805-5d2b-b904d269ca60.png)


## 2. ビルドする前に ClientApp の中身を全部削除

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222127/ab1f72d5-4a7a-db95-ec01-b4289a63e396.png)

## 3. ClientApp 内部で yarn を使って React or Next.jsア プリケーションを作成

React の場合

```powershell
yarn create react-app myapp --template typescript
```

Next.jsの場合

```powershell
yarn create next-app myapp --typescript
```

## 4. ClientAppフォルダ内部にできた myapp フォルダの中身をすべて ClientApp へ移動

移動したら myapp フォルダは削除。

## 5. .env ファイルを ClientApp サブディレクトリに追加し、下記の内容を追記

```ini
BROWSER=none
```

## 6. Startup クラスで、spa.UseReactDevelopmentServer の呼び出しを以下に置き換え

```c#
spa.UseProxyToSpaDevelopmentServer("http://localhost:3000");
```

## 7. .cspojファイルを開いて、npm の箇所を下記のように修正

```xml
    <Exec WorkingDirectory="$(SpaRoot)" Command="yarn install" />
```

```xml
    <Exec WorkingDirectory="$(SpaRoot)" Command="yarn install" />
    <Exec WorkingDirectory="$(SpaRoot)" Command="yarn build" />
```

## 8. 起動する

ClietApp フォルダでフロント側の開発サーバーを起動します。Powershellなどから以下コマンドを叩いてもいいのですが、React or Next.js を Visual Studio Code で開発していくなら ClientApp フォルダを Visual Studo Code で「フォルダを開く」で開いてから Terminal でコマンドを叩くことになるでしょう。

```powershell
yarn start
```

もし Next.js を作成していたならば

```powershell
yarn dev
```

Visual Studio でデバッグ実行。すると、https://localhost:44342 など、Visual Studio で設定されているWebサーバーのアドレスでブラウザが立ち上がります。http://localhost:3000 へProxy設定がされているので、それだけ問題なく動作します。
[middleware] Nuxt.jsでページにアクセス制限をかける

## はじめに
Nuxt.jsで`middleware`を使用したページ制限(管理者)を担当したのでその備忘録

## 環境
MacOs
docker環境

## 前提条件
* authModuleを使用したログイン機能が実装されている
* ログイン後vuexにユーザー情報が保存されている

まだの方は[こちら](https://qiita.com/Bezzi05791520/items/d09730e7b8d67053e137)を参考にどうぞ

## この記事を読んでできること
vuexに保存されているユーザー情報で各ページに制限をかける
(今回はユーザーの`admin`カラムが`true` or `false` でページ制限をかけます)

## middlewareってなに？
* ページが表示される前に実行される関数
* 外部JSに記述するもの
* ファイル共通化ができるため、ページ制限で利用される

## middlewareディレクトリの作成

```
front $ mkdir middleware
front $ touch redirect.js
```

## redirect.jsファイル作成
```middleware/redirect.js
export default function ({ store, redirect }) {
  const user = store.getters['user_information/getUser'] // ユーザー情報を保存しているvuexのファイルを指定してください
  if (user && !user.admin) {
    redirect('/')
    store.dispatch(
      'flashMessage/showMessage',
      {
        message: '権限がありません',
        type: 'error',
        status: true
      }
    )
  } else if (!user) {
    redirect('/')
    store.dispatch(
      'flashMessage/showMessage',
      {
        message: 'ログインしてください',
        type: 'error',
        status: true
      }
    )
  }
}
```

## sample.vueファイル作成
```pages/sample.vue
<template>
  <div>
    <p>Hello World</p>
  </div>
</template>

<script>
export default {
  name: 'Sample',
  middleware: 'redirect', // middlewareのredirect.jsを読み込み
  auth: false // falseと表記しないと未ログインでアクセスした時にauthModuleで設定したルートへリダイレクトされる
}
</script>
```
## ページ遷移確認
dockerコンテナを起動して確認

```
root $ docker-compose up
```
①未ログイン状態で`localhost:8080/sample`へアクセス
(ログインしていないため、アクセス制限がかかります)
<img width="400" alt="スクリーンショット 2021-11-01 22.05.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1986536/4fc94f31-f184-50b4-8d91-1581d5a7688f.png">

②一般ユーザーでログインして、再度`localhost:8080/sampleへアクセス`
(adminではないため、アクセス制限がかかります)
　<img width="400" alt="スクリーンショット 2021-11-01 22.15.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1986536/c565f80c-342a-72fb-dc37-c44e55571128.png">

③管理者でログインして、再度localhost:8080/sampleへアクセス
sample.vueの遷移が成功し`Hello World`が表示されます

<img width="400" alt="スクリーンショット 2021-11-01 22.22.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1986536/d470e8a6-72cf-409e-408a-a23e40fc7180.png">

## 最後に
各々のcompomentから共通のmiddlewareのファイルが読み込みできるのでシンプルでよいですね
これを使えば特殊なページ遷移も楽にできるのでぜひ使ってみてください

最後まで見ていただきありがとうございました。
swift safeAreaの取得

#今回の内容

* 最近、`safeAreaの取得`をする事が度々あるので、メモ感覚で書き残しておきます。

#コードと簡単解説

* `safeAreaInsets`種類
 * `top` 
 * `bottom`
 * `left`
 * `right`

* `safeAreaInsets`の値が取得できたのは、
 * `updateViewConstraints()`
 * `viewWillLayoutSubviews()`
 * `viewDidLayoutSubviews()`
 * `viewDidAppear()`
 

```Swift:   
       print("view.safeAreaInsets.top = \(view.safeAreaInsets.top)")
       print("view.safeAreaInsets.bottom = \(view.safeAreaInsets.bottom)")   
       print("view.safeAreaInsets.left = \(view.safeAreaInsets.left)")
       print("view.safeAreaInsets.right = \(view.safeAreaInsets.right)")
       print("view.safeAreaInsets = \(view.safeAreaInsets)")
```

```：print結果
       view.safeAreaInsets.top = 92.0
       view.safeAreaInsets.bottom = 83.0
       view.safeAreaInsets.left = 0.0
       view.safeAreaInsets.right = 0.0
       view.safeAreaInsets = UIEdgeInsets(top: 92.0, left: 0.0, bottom: 83.0, right: 0.0)
```

# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
【Winget】Windows Trminalから使えるWingetで簡単に環境を構築してみた

## wingetとは
Windows11で標準搭載となった、Windows Trminalにて使用できる、コマンドラインパッケージマネージャー。
Linuxで言うところの、aptやyamが該当するコマンドラインからアプリケーションをインストールする手段。

## 使用方法
Windows Terminalで"winget"を実行。下記実行した様子。

```
❯ winget
Windows パッケージ マネージャー v1.3.2691
Copyright (c) Microsoft Corporation. All rights reserved.

WinGet コマンド ライン ユーティリティを使用すると、コマンド ラインからアプリケーションやその他のパッケージをインストールできます。

使用状況: winget [<コマンド>] [<オプション>]

使用できるコマンドは次のとおりです:
  install    指定されたパッケージをインストール
  show       パッケージに関する情報を表示します
  source     パッケージのソースの管理
  search     アプリの基本情報を見つけて表示
  list       インストール済みパッケージを表示する
  upgrade    利用可能なアップグレードの表示と実行
  uninstall  指定されたパッケージをアンインストール
  hash       インストーラー ファイルをハッシュするヘルパー
  validate   マニフェスト ファイルを検証
  settings   設定を開くか、管理者設定を設定する
  features   試験的な機能の状態を表示
  export     インストールされているパッケージのリストをエクスポート
  import     ファイル中のすべてのパッケージをインストール

特定のコマンドの詳細については、そのコマンドにヘルプ引数を渡します。 [-?]

次のオプションを使用できます。
  -v,--version  ツールのバージョンを表示
  --info        ツールの一般情報を表示

詳細については、次を参照してください。 https://aka.ms/winget-command-help
```

## よく使うソフトのインストールコマンド（忘備録）
```
# 原則
>winget insatall {ソフトウェア名称｝
ただし、似たようなソフトウェアがある場合、
>winget install {ソフトウェアID}

# 必須ソフトウェア
> winget install vscode
> winget install Microsoft.PowerToys
> winget install 7zip.7zip
> winget install Google.Chrome
> winget install winscp
> winget install　Git.Git
> winget install python

# 専門ツール
> winget install stellarium
> winget install QGIS
> winget insatall Inkscape.Inkscape
```

## インストールしたソフトのアップデート
```
# アップデートが可能なソフト一覧を出力
> winget upgrade

# すべてのソフトウェアをアップデート
> winget upgrade --all
```

## 終わりに
Linuxでは当たり前となっている、コマンドラインパッケージマネージャーを使用できるのはうれしいですよね。
また、Windows11からは標準搭載となるみたいなので、これから使用頻度が増えると思い、メモを残しました。

## 参考
https://docs.microsoft.com/ja-jp/windows/package-manager/winget/

https://qiita.com/rubytomato@github/items/f9cc8e261c765c86f9cd

https://qiita.com/tfukumori/items/1c6c6c691fdb5abe8856
[java入門]クラスの応用

## クラスの応用

・クラスの継承
・内部クラス
・final修飾子
・ラッパークラス
・抽象クラス

#### クラス継承：
  ・クラスが保持しているメンバやメソッドの内容を他のクラスで継承する
  ・継承元クラスを「スーパークラス」「親クラス」、継承したクラスを「サブクラス」「子クラス」と呼ぶ。
  ・親クラスを継承するためには、「expands」を使用する。
    class 親クラス名 { 実行処理}
    class 子クラス名 expands 親クラス名 { 実行処理 }

#### 内部クラス：
  ・クラスの中にクラスを作成する記述方法
  ・通常javaは『１ファイル１クラス』だが簡単な処理でファイルをわざわざ分けたくない場合に使用する
    class クラス名１ { class クラス名２ { 実行処理 } }

#### final class
  ・final修飾子で子クラスで継承することができなくなる
  ・そのクラスのメンバ・メソッドの内容を不用意に変更されたくない場合に使用
  ・親クラスの安全性を保つために使用
    final class クラス名 { 実行処理 }

#### ラッパークラス：
  ・基本データ型に用意されているクラス
  ・基本データ型をクラスのように扱えてインスタンス化することも可能になる。
    Integer i = new Integer(10)

#### 抽象クラス
  ・実装を持たないシグネチャ（メソッド名、引数の型、引数の数）と戻り値の型飲みを実装したメソッドを一つ以上保持するクラス
  ・「インスタンス化できない」「抽象メソッドを全てオーバーライドする必要がある」などのルールがある。