OmniAICreator/Qiita-1.07M huggingface dataset:
【初学者向け】PostgreSQLの環境構築

## 開発環境

macOS      10.15.7
postgresql 13.1
Homebrew 2.7.0



インターンとして参画した初現場の環境構築でPostgreSQL周りについていろいろ調べたのでアウトプットします。
（まだまだ知識不足ですので間違えている部分などは積極的に教えていただけると幸いです。）



## PostgreSQLをinstallする手順について

前提としてHomebrewがインストールされている上で下記の手順に沿って環境構築して行ってください

①HomebrewでPostgreSQLをインストールします。

```ターミナル
$  brew install postgresql
```

②PostgreSQLがインストールされているかどうかを確認する（Vが大文字になっている点に注意）

```ターミナル
$ postgres -V
```

③次にPostgresqlを起動します(下記のコマンドのどちらでもサービスの起動が可能です！！)
（その際に、Homebrewのservicesサブコマンドを利用することで簡単にPostgresqlを立ち上げることが
できます。）

```ターミナル
$ brew services start postgresql 
```

```ターミナル
$ postgres -D /usr/local/var/postgres
```

下記のような文言が返ってきたらおそらく、Postgresqlは起動しています。

>==> Successfully strated `postgresql` (label....)


※ ここで場合によっては、「postmaster.pidはすでに存在しています」といったようなエラーが発生したら、/usr/local/varにあるPostgresqlに関するフォルダ（postgresなど）の中にあるpostmaster.pidを下記のコマンドで削除して下さい

```ターミナル
$ rm /usr/local/var/postgres/postmaster.pid
```

④PostgreSQLサーバが立ち上がったら、実際にコンソールに入って動作確認を行います。
ここで問題なくコンソールに入れたら、環境構築は完了です。

```ターミナル
$ psql postgresql
```

※ ここの「postgresql」の部分は、実際のデータベース名によって変わるので注意しましょう。
また、psqlコマンドや、postgresコマンドが使えない場合には、（zshrcファイルまたは、bashrcファイルなどに）パスを通す必要があるかもしれません。

```~/.zshまたは、~/bashに追記する
 export PGDATA='/usr/local/var/postgres'
```

なお、Postgresqlを停止する場合には下記のコマンドを実行すれば良いです。

```ターミナル
$ brew services stop postgresql
```


## 参考


Postgresqlの諸コマンドは下記の記事を参考にさせていただきました。

>PostgreSQLコマンドチートシート
https://qiita.com/Shitimi_613/items/bcd6a7f4134e6a8f0621



>PostgreSql コマンドの覚え書き
https://qiita.com/mm36/items/1801573a478cb2865242



>PostgreSQLの基本的なコマンド
https://qiita.com/H-A-L/items/fe8cb0e0ee0041ff3ceb



## 最後に

一つ次回の意味も込めて、エラーメッセージはちゃんと読みましょう！！！
③から一切前に進めなくなる現象（postmaster.pidが消しても消えない）については、別途記事にまとめたいと思います。
【C】bitwise operator メモ

いつもいつもC言語で必要になるたびに調べているのでメモを書いておきます。今回も調べました。（涙）

# Bitwise Operator

### 書き方

どこを本家として参照すればよいのか分かりませんが、Wikipediaがあったので、リンクをメモリます。

https://en.wikipedia.org/wiki/Bitwise_operations_in_C

Symbol	|Operator
--- | ---
& | bitwise AND
&#124; | bitwise inclusive OR
^ | bitwise XOR (exclusive OR)
<< | left shift
>> | right shift
~ | bitwise NOT (one's complement) (unary)

### 出力してみる

以下、NOT operator のテストです。

```C:test.c
#include <stdio.h>

void printBi(char num) {
  int len = 8;
  int bit[8];

  for(int i = 0; i < len; i++) {
    int x = 1 << i;
    x = num & x;
    bit[len - i - 1] = x >> i;
  }

  printf("0b");
  for(int i = 0; i < len; i++) {
    printf("%d", bit[i]);
  }
}

int main(void) {
  int num = 0b00000101;
  int result = ~num;

  printf("Input  %4d(Decimal) ", num);
  printBi(num);
  printf("(Binary)\n");
  printf("Output %4d(Decimal) ", result);
  printBi(result);
  printf("(Binary)\n");
  return 0;
}
```

gcc でコンパイルして実行すると、以下を得ます。

```
Input     5(Decimal) 0b00000101(Binary)
Output   -6(Decimal) 0b11111010(Binary)
```

### flag を読む

実際に必要となったのは、4byte のデータの2byte 目の3bit 目のbinary を読みたい、のような場面です。

2byte, 3bit の（開始から8+3=11 bitの位置）の値を読みたいとします。次の^ の位置です。

```
0b00100000 00001100 00000000 00000000
                ^
```

いろいろデータのの取り出し方はあります。以下は、bit mask とシフトで必要なflag を読むためのテストコードです。4byte の各データの3bit 目を出力しています。

```c:test2.c
#include <stdio.h>
#include <stdint.h>

void print_binary_byte(unsigned char num) {
    int len = 8;
    int bit[8];
    for(int i = 0; i < len; i++) {
        int x = 1 << i;
        x = num & x;
        bit[len - i - 1] = x >> i;
    }
    for(int i = 0; i < len; i++) {
        printf("%d", bit[i]);
    }
}

void print_binary_bytes(unsigned char* buf, unsigned int buflen) {
  printf("0b");
  for(unsigned int i=0; i<buflen; i++){
    print_binary_byte(buf[i]);
    printf(" ");
  }
  printf("\n");
  for(unsigned int i=0; i<buflen; i++){
    unsigned char v0 = buf[i];
    unsigned char v2 = (v0 & 0b00000100) >> 2;
    printf("[%d/%d] 0b", i, buflen);
    print_binary_byte(v0);
    printf("(input) ");
    printf(" 0b00000100(mask) --> shift --> 0b");
    print_binary_byte(v2);
    printf("(output)\n");
  }
}

int main(void) {
    uint32_t val1 = 32 + 1024 + 2048;
    union bytes4{
      unsigned char buf[4];
      uint32_t val_uint32;
    };
    union bytes4 val1_union;
    val1_union.val_uint32 = val1;
    print_binary_bytes(val1_union.buf, sizeof(val1_union.buf));
    return 0;
}
```

実行すると、以下を得ます。

```
0b00100000 00001100 00000000 00000000
[0/4] 0b00100000(input) 0b00000100(mask) --> shift --> 0b00000000(output)
[1/4] 0b00001100(input) 0b00000100(mask) --> shift --> 0b00000001(output)
[2/4] 0b00000000(input) 0b00000100(mask) --> shift --> 0b00000000(output)
[3/4] 0b00000000(input) 0b00000100(mask) --> shift --> 0b00000000(output)
```

1だったことが分かります。mask　をかけてシフトしていますが、もっと頭の良い方法もあったと思います。

## まとめ

今回はとりあえずメモでした。いつも確認コードを書かないと分からなくなってしまうのですが、今回も、目的の実装はできてのりきれました。ふー。

今後、なにか思い出したりしたら追記したいと思います。
ヘッドレスChrome(Chromium)がzombie processを生み出してしまう場合の対処法

# TL;DR

chrome(chromium)を起動するときに`--no-zygote`オプションを指定すると、
余計なプロセスが立ち上がらなくなりゾンビプロセスも発生しない。

# 概要
ヘッドレス(`--headless`)でChromeを立ち上げた場合に、以下のようにゾンビプロセスが溜まってしまうことがあります。
(以下はAWS Lambda内でchromiumを立ち上げた場合)

```
sbx_use+    24  0.0  0.0      0     0 ?        Z    13:50   0:00 [chromium] <defunct>
sbx_use+    25  0.0  0.0      0     0 ?        Z    13:50   0:00 [chromium] <defunct>
sbx_use+    53  0.0  0.0      0     0 ?        Z    13:50   0:00 [chromium] <defunct>
sbx_use+    54  0.0  0.0      0     0 ?        Z    13:50   0:00 [chromium] <defunct>
sbx_use+    82  0.0  0.0      0     0 ?        Z    13:51   0:00 [chromium] <defunct>
sbx_use+    83  0.0  0.0      0     0 ?        Z    13:51   0:00 [chromium] <defunct>
sbx_use+   111  0.0  0.0      0     0 ?        Z    13:52   0:00 [chromium] <defunct>
sbx_use+   112  0.0  0.0      0     0 ?        Z    13:52   0:00 [chromium] <defunct>
```

ゾンビプロセスは貴重なPIDを浪費するだけでなく、元のプロセスが開いていたファイルを開きっぱなしにしてしまうなど、
様々な弊害を生み出す元凶となります。

# ゾンビプロセスはなぜ発生するのか

そもそも、正常な過程で実行・終了されたプロセスはゾンビ化することはありません。
正常な過程というのは具体的に以下のようなものを言います。

1. 親プロセスが`fork`する
2. 子プロセスが`exit`する
3. **親プロセスが子プロセスを`waitpid`する(重要)**

`waitpid`というのはいわば不要になったプロセスの回収作業であり、
これを忘れると子プロセスに関するリソースを開放することができずゾンビ化します。
逆にちゃんと`waitpid`してやればプロセスがゾンビ化することはありません。

子プロセスが`waitpid`されることなくfork元のプロセス(親プロセス)が終了してしまった場合、
ゾンビ化した子プロセスは行き場を失ってしまいます。

しかし、UNIXシステムには特別なプロセスである`init`プロセス(PIDが1のプロセス)が存在し、
initプロセスは行き場を失ったゾンビプロセスを子プロセスとして取り込むようになっています。

一般的な`init`プロセスは取り込んだゾンビプロセスに対処するため、
`waitpid`をゾンビプロセスに対して実行するようなロジックが組み込まれています。

しかしながら、**`init`プロセスがおバカな場合**、
即ち`init`として利用されることを想定されていないプロセスがPID1で立ち上がってしまっている場合、
取り込んだゾンビプロセスをそのまま放置してしまうためゾンビが溜まり放題になってしまうのです。

これはコンテナ環境では割と起こりうる話だったりします。
というのも、**コンテナ内では一番最初に立ち上がったプロセスのPIDが1になる**ためです。
コンテナで実行されるプロセスのほとんどは`init`として動かされることを想定されていないでしょうから、
必然的にゾンビプロセスも世話されること無く放置されてしまうということです。

>なお、あくまで本質的な解決方法ではないのですが、
一番最初に起動するプロセスをコントロールできる場合には、
ちゃんとゾンビプロセスを回収してくれるプロセスを最初に起動することで解決できます。
>
例えば、コンテナ用の擬似`init`のひとつである`tini`などです。
https://github.com/krallin/tini
詳しい使い方はここでは割愛します。
>
AWS Lambdaなどのいわゆるサーバーレスなプラットフォームを利用する場合は
最初に起動するプロセスを変更できない場合が有り、
この場合はtiniを使った解決方法を適用することはできません。

## ゾンビプロセスって後から叩き潰せば良いんじゃ？

ゾンビプロセスが発生したなら後から手動でkillしてやれば良いような気がしてしまいますが、
**ゾンビプロセスはそもそも既に死んだ(exitした)後のプロセスであるためいくらkillしようとしても全く意味がありません**。

実際に`kill -9 [ゾンビのPID]`を実行してみると全く効かないことが分かると思います。

ゾンビプロセスというのは溜まってしまうともはやシステムを再起動することでしか消すことができないため、
非常に厄介な存在でありできる限り生み出さないようにする必要があるのです。
(特にPID1のプロセスがinitとしての役割を果たせない場合)

# ゾンビプロセスを発生させないために

元はと言えば自分で生んだ子プロセスをちゃんと回収しないchromeが悪いわけなので、
chromeがちゃんと子プロセスを回収する(ないし余計なプロセスを生まないようにする)ように仕向けることを第一に考えます。

そもそも、chromeはわざわざ好き好んでゾンビプロセスを作っているわけではありません。
本来常駐させようと思っていたプロセスが何故か終了してしまったがためにゾンビ化してしまったのです。

この常駐プロセスはZygoteと呼ばれ、プロセスのセットアップ時間の短縮やライブラリ依存関係の維持などに用いられているようです。
https://chromium.googlesource.com/chromium/src/+/master/docs/linux/zygote.md

普段は当然役に立っているのでしょうが、勝手に死なれてゾンビ化されると迷惑なだけなので、
そもそもZygoteプロセス自体を起動しないようにするのが一番良さそうです。

Zygoteを起動しないようにするには`--no-zygote`オプションをchromeに渡します。
これによりZygoteプロセスは作成されなくなり、余計なゾンビプロセスも発生しなくなります。
TypeScriptで中身がオブジェクトであるuseStateの初期値にnullが使えない

# TypeScriptで中身がオブジェクトであるuseStateの初期値にnullが使えない
長いタイトルになってしまいましたが、TypeScriptでuseStateを使う時に
自分がハマってしまった注意点を記しておきます。

## useStateでオブジェクトを扱う（JavaScript）
ECサイトの商品詳細ページを作成しています。
このページはURLが「product/(:id)」の形で呼び出され、
初回レンダー時(useEffect)にURLのidをもとに、その商品の詳細情報を
データベースから取得してローカルステート(useState)に格納して管理します。

その部分はこの様なコードになります。
(JavaScriptの場合)

```ts
const [product, setProduct] = useState(null);

  // URLで指定されたidをもとにDBから１件データを取得しローカルステートを更新
  useEffect(() => {
    db.collection('products').doc(id).get()
      .then((doc) => {
        const data = doc.data()
        setProduct(data) 
      })
  }, [])

```

## useStateでオブジェクトを扱う（TypeScript）
しかし、上記のコードをTypeScriptで記述すると、上手くいかないのです...
nullの箇所でコンパイルエラーが起きます。
他にも「undefined」,「{}」,「{} as any」など試しましたが
TypeScriptはこれらを上手に型推論してくれません。

(具体的には、以降のコードでproduct.nameやproduct.priceのように
データを呼び出そうとして、その箇所でエラーになったり、undefinedになったり...)

**どうするか** ※より自然な書き方に修正 2020/12/30

```ts
type Product = {
    name: string;
    description: string;
    price: number;
  }

  const [product, setProduct] = useState<Product | null>(null);

  // URLで指定されたidをもとにDBから１件データを取得しローカルステートを更新
  useEffect(() => {
    db.collection('products').doc(id).get()
      .then((doc: any) => {
        const data = doc.data()
        setProduct(data) 
      })
  }, [])
```
productオブジェクトの取りうるプロパティの型を明示した
Product型を用意しました。
これをuseStateに対してジェネリクスで指定します。

## プリミティブでのuseState
以下の様なプリミティブな型はTypeScriptが正しく推論してくれるので
ジェネリクスの指定は要らないということなのかも

```ts
const [name, setName] = useState('')
const [age, setAge] = useState(0)
```
※こう書いても問題は無い

```ts
const [name, setName] = useState<string>('')
const [age, setAge] = useState<number>(0)
```


## 覚えておきたいこと
- useStateにはジェネリクスで型を指定できる
- そのジェネリクスに適切な型を与えることで、初期値を「null」や「[]」にしても
  TypeScriptは上手く型推論をしてくれる

## 参考
以下を読んで勉強し直します...
[Typescript で React useState の引数を明示的にアノテートする](https://qiita.com/murata0705/items/35c893dd7d6aec3bed4b)
[TypeScriptの型演習]
(https://qiita.com/uhyo/items/e4f54ef3b87afdd65546)
Amazon DynamoDB とは

## 勉強前イメージ

データベース....しかわからない....
RDSとかと何が違うんだろうね。

## 調査

### DynamoDBとは

フルマネージド型のNoSQLデータベースクラウドサービスです。
`NoSQLデータベース` とは非リレーショナルデータベースとも呼ばれ、
RDSで使用されている、スキーマ定義が必要なリレーショナルデータベースとは違い、
非定型な構造を持つデータを柔軟に管理することができます。

### NoSQLデータベースとは

Not Only SQL の略です。
リレーショナルデータベースとは違い、ビッグデータに対応すべく生み出された技術でSQLを使用しないということが特徴です。
DynamoDBだけでなく、GoogleのBigTableもNoSQLデータベースに当たります。

### DynamoDBの特徴

- ストレージは必要に応じて自動的にパーティショニングされる

分散型アーキテクチャーが採用されており、テーブルのデータをパーティションに小分けして割り当てられています。
パーティションは、設定した値以上になったり容量がいっぱいになったりしたら自動で追加され、ほぼ無限で容量を増やすことができ、また一貫したパフォーマンスを維持することができます。

- データの格納と取得に特化し、結合などは不得意
	- 値とキーだけを格納するというシンプルな機能
	
NoSQLの特徴でもあり、その中のキーバリューストア型の機能になります。
単純なデータ構造だからこそ応答速度が速い。

- 1桁ミリ秒単位のレイテンシーを要求するアプリケーションにも対応

またNoSQLの特徴でもありますが、RDSよりデータ構造が単純なため
数ミリ秒単位での応答速度も可能になり、モバイル・ウェブ・ゲームなどで使われています。

- データは3箇所のAZに保存される

SPOFが存在しないので、可用性・堅牢性ともに高くなります


## 勉強後イメージ

そもそものデータの管理の仕方から違った。
RDSは結構色々組み合わせてSQLで出すのが得意。
DynamoDBはキーとバリューだけを早く出すのが得意。
速さが必要だったり、容量がほぼ無限なのがメリット。


## 参考

- [【超入門】RDBとNoSQLの違いに着目！NoSQLに求めるものとは？](https://tech-blog.rakus.co.jp/entry/20180919/nosql/bigdata)
- [【AWS】DynamoDBの基礎知識をカンタンに解説する](https://kirohi.com/dynamodb_basic)
- [RDSとDynamoDBの違いとは？AWSのサーバーレスにおけるデータベースの上手な使い分け(後編)](https://serverless.co.jp/blog/243/)
- [Amazon DynamoDB](https://qiita.com/leomaro7/items/383c1aa287c7daf49518)
- [【AWS】Amazon DynamoDBについて解説します。](https://www.acrovision.jp/service/aws/?p=2536)
- [AWSのNoSQLデータベースAmazon DynamoDBの特徴とベストプラクティス](https://business.ntt-east.co.jp/content/cloudsolution/column-115.html)
- [DynamoDB全くわからない、から、ちょっとわかるようになるまでの道しるべ](https://dev.classmethod.jp/articles/dynamodb-chottowakaru/)
- [【AWS】今更ながらDynamoDB入門](https://qiita.com/maaaato/items/4a0f5c1dcc78677973c9)
[Laravel] 入力フォームにJQuery-UIを使ってサジェスト機能を実装する

## 概要

Laravelプロジェクトを作成後にマイグレーションすると生成されるusersテーブルのデータに対して、JQuery-UIを使ってサジェスト機能を実装するサンプルです。
こんな感じの、名前を途中まで打ち込むとDBから取得したデータを元にサジェストが出るフォームを作ります。
![users_table.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/780135/1c2afbc0-cf2c-64a6-7feb-5f1413fbf34a.png)

## 実装

コントローラー側は名前(`name`カラム)のコレクションを取得してViewに渡します。

```php
    public function showIndex()
    {
        $user = new User();
        $suggests = $user->select(['name'])->get();

        return view('index_view', compact('suggests'));
    }
```

View側はinputフォームの設置とautocompleteの設定を行います。
また、jQuery-UIを読み込むため`<header>`タグ内に[Google Hosted Libraries](https://developers.google.com/speed/libraries#jquery-ui)からコピペしたリンクを貼ります。

```php
<head>
    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
    <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
</head>
<body>
    <script>
        $(function() {
            $('#user_name').autocomplete({
                source: @JSON($suggests).map(item => ({
                    label: item.name,
                    value: item.name,
                })),
                autoFocus: true,
                delay: 300,
                minLength: 2
            });
        });
    </script>

    <input id="user_name" type="text" />
</body>
```

以上です、ありがとうございました。
qiita_orgのインストール

\![macOS-11.1](<https://img.shields.io/badge/macOS-11.1-brightgreen>) \![ruby-2.7.2p137](<https://img.shields.io/badge/ruby-2.7.2p137-brightgreen>) 


# Preface (はじめに)

Qiitaの記事を作成から投稿までターミナルで行おうとするツールそれが`qiita_org`です. 
本記事では, [作成者さんのQiita記事](https://qiita.com/yamatoken/items/858692178d288c40714d)をもとにインストールから各種設定まで行い, 最後に簡単な例を作ります. 


# qiita\_org


## インストール

```
> gem install qiita_org
```

ちゃんと入ったか確認

```
> qiita
```

```
Commands:
  qiita all [teams/public/private] [options]    # post all org files in the directory
  qiita config [global/local] [option] [input]  # set config
  qiita get [qiita/teams] [ITEM_ID]             # get qiita report
  qiita help [COMMAND]                          # Describe available commands or one specific c...
  qiita list [qiita/teams]                      # view qiita report list
  qiita post [FILE] [private/public/teams]      # post to qiita from org
  qiita say_hello                               # say_hello
  qiita template                                # make template.org
  qiita upload [FILE] [teams/public/private]    # upload about image to qiita
  qiita version                                 # show version

```

無事完了. 


## 設定


### 前提

`qiita_org`は`get`コマンドで`pandoc`を使うためインストールします.

-   mac

```
> brew install pandoc
```

-   ubuntu

```
> sudo apt update
> sudo apt install pandoc
```


### 設定ファイル作成

設定ファイルを作成するために以下のコマンドを実行

```
> qiita config global
```

するとホームディレクトリに`.qiita.conf`という設定ファイルが作られます.

現時点では, 

```
/Users/[User Name]/.qiita.conf

  "name": ""
  "email": ""
  "access_token": ""
  "teams_url": ""
  "ox_qmd_load_path": ""
```

となっています. 


### 設定ファイルの変更とQiitaのアクセストークン発行

上から一つずつ設定していきます.

-   名前

```
> qiita config global name "Your Name"
```

-   メールアドレス

```
> qiita config global email "Your Email address"
```

-   アクセストークン

Qiitaの[設定のアプリケーション](https://qiita.com/settings/applications)で個人用アクセストークンを新しく発行する. アクセストークンの説明を書き込み, スコープではすべてにチェックを入れる. 

ページが推移した後に表示されるアクセストークンをコピーし,以下を実行
**※アクセストークンはページを移動すると再表示されなくなるため注意!!**


```
> qiita config global access_token "Your Access token"
```

-   TeamsのURL

`teams`オプションのために必要. 所属しているQiitaTeamのURLを書き込むただし, なければ何もしなくてもいいです. 

```
> qiita config global teams_url "Your Qiita Teams URL"
```

**※URLは最後に/をつけ忘れないように注意**


-   ox-qmd

[ox-qmd.el](https://github.com/0x60df/ox-qmd)を ~/.emacs.d/site\_lisp 下に作成する. 

次に ~/.emacs.d/init.elに以下を加える. 

```
;; elファイルの置き場所を設定 
(setq load-path (cons "~/.emacs.d/site_lisp" load-path))

(require 'ox-qmd)
(add-to-list 'ox-qmd-language-keyword-alist '("ruby" . "ruby"))
```

これで初期設定は完了です.


# 簡単な例

例えば, `template`コマンドで適当なorgファイルを作り, 以下のような内容に編集して`post`コマンドで投稿すると 

```
　* equation <2020-10-28 水>
  　$$
    　\int_{x=1}^{x=3}\ln \left(\frac{1}{4x}\right) {\rm d}x
  　$$
```

下のような記事が作成できる. 


# equation <span class="timestamp-wrapper"><span class="timestamp">&lt;2020-10-28 水&gt;</span></span>

$$  \int_{x=1}^{x=3}\ln \left(\frac{1}{4x}\right) {\rm d}x$$
electron 最小構成


## electron install

```bash
yarn init -y 
yarn add -D electron 
```

## index.js

```index.js
const { app, BrowserWindow } = require('electron')

let window

app.on('ready', () => {
    window = new BrowserWindow({
        width: 500,
        height: 500,
        useContentSize: true
    })

    window.loadFile('index.html')

    window.on('closed', () => {
        window = null
    })
})

app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit()
    }
})
```

## index.html

```index.html
<!DOCTYPE html>
<body>
    <div>
        hello, world
    </div>
</body>
```

## 起動

```
yarn electron .
```

## 結果
![スクリーンショット 2020-12-29 0.07.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278474/f6126875-0353-2559-907b-84b9402de36d.png)
【Android Studio】Failed to open zip file.と表示されてビルドできなくなった

#Failed to open zip file.と表示されてビルドできなくなった
Failed to open zip file.
Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
と表示され、ビルドできなくなった。
####~目次~
[0.結論](#0.結論)
[1.状況](#1.状況)
[2.解決方法](#2.解決方法)

##0.結論
「C:\\Users\\ユーザー名\\.gradle」をフォルダごと削除する。

##1.状況
プロジェクトのgradleファイルを開いたら、
「You can configure Gradle wrapper to use distribution with sources. It will provide IDE with Gradle API/DSL documentation.」
(ソースで配布を使用するようにGradleラッパーを構成できます。 IDEにGradleAPI / DSLドキュメントを提供します。:Google翻訳)
と言われたので、よくわからなかったが、「Ok,apply suggestion!」(おっけー、適用する！)を選んだ結果、ダウンロードが始まった。
![gradle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/930269/260156c9-a83c-f73a-eca4-8b1b12159b8b.png)

しかし途中でネットワーク環境がとぎれてしまい、ダウンロードが中断された。
結果以下のエラーが表示された。

```
Failed to open zip file.
Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
```

「this sometimes occurs after a network connection timeout.」
(このエラーはしばしばネットワーク接続タイムアウトの時におこります。)
と書いてあったのでネットワークに再接続して再度ダウンロードを試みたが、毎回同じエラーになった。

##2.解決方法

- 「C:\\Users\\ユーザー名\\.gradle」をフォルダごと削除する。

全バージョンのgradleファイルを消してしまうため抵抗はあったが、gradle内の必要なファイルはプロジェクトを開くと自動で再ダウンロードしてくれるため問題なかった。
(ダウンロードに時間はかかる。)
Clip Studio PAINT にテンキーを導入してみた(Win10+AutoHotKey)

###イントロダクション
家にいる時間が増えたので挫折したイラスト練習に邁進することにしました。
折角なので流行りの左手デバイスとやらに手を出してみようかなと思い密林に潜ると……oh
30000円は流石にふざけが過ぎます:no_mouth:
[wacomのたかいやつ](https://www.amazon.co.jp/dp/B07XC6KNQR/ref=cm_sw_r_tw_dp_x_yRD6Fb2K81D08)
[TourBoxのたかいやつ](https://www.amazon.co.jp/dp/B07WRQY7ZW/ref=cm_sw_r_tw_dp_x_BRD6Fb0Y9ZR8C )
3万円あったら新しい液タブの軍資金に回したいので今回はお安いテンキー使いになることにしました。

ちなみに、買った製品はこれです。イラスト界隈で一躍有名になったあのテンキーです。キーの数が多い＋充電式という点でおすすめ。充電コネクタがTypeBなのがネック。
[iClever テンキー IC-KP08](www.amazon.co.jp/gp/product/B081NJGDZB/ref=ppx_yo_dt_b_asin_title_o01_s00)


#何するの
ClipStudioに便利な左手デバイスを導入します。
ココに書いてあることをすれば、左手デバイス使いになれる。はず。
テンキーの接続は済ませている前提で進めます。

#なぜAutoHotKeyなのか

スクリプトいじるのが好きだから

1. ソフトウェア毎、デバイス毎に設定ファイルを作成できる
2. キー入力の自由度が高い
3. 64bitに対応している（Hidkeysequenceは二次配布なのが気になってしまいました）

近々Windows公式から[キーボード配置を変更できるソフト](https://github.com/microsoft/PowerToys/wiki/Keyboard-Manager)が公式に出そうなので、それが来たらAutohotkeyとはサヨナラするかもしれません:upside_down:

##作者の環境
Windows 10 2020H2
ClipStudio PAINT EX(PROでもキー配置は流用できます）
AutoHotKey 1.1.33.02
テンキー　IC-KP08

エディタにはAtomを用いました。後ほど文字コード変更が必要になる場面があるので、その時に活躍します。

#必要なソフトのダウンロード
[AutoHotKey](https://www.autohotkey.com)　好きなバージョン/bitを選択してください。
[Atom(任意)](https://atom.io)
ClipStudio
[テンキー用のシール（女性向けデザイン？）](https://twitter.com/sayonaki_sayo/status/1303201626040094720) シール台紙に印刷するとキーボード用ラベルが作れます。作者に最大限の感謝。

#AutoHotKeyのインストール
ダウンロードしたインストーラを実行します。
筆者は「Express Install」を選択しました。
1秒ほどでインストールが終わります。拍子抜けしました。

#スクリプト作成
`.ahk`拡張子のファイルを作成します。内容は以下のサイトが参考になります。
ファイルを保存する際には、エンコード（文字コード）を「Shift JIS(ANSI)」にするのを忘れずに。


筆者は[こちらのサイト様](https://oekakitoka.blogspot.com/2020/07/autohotkey-002.html)からコードを参考にしました。一部自分用にキーを変更した部分があります。

配置はこのような感じにしてみました。テンキーを左に90度回転させています。
1.  上段が1回、下段が2回押下時のキー入力です。
2.  黒は元から変更しなかった場所、青はファンクションキーとして用いますので単体では意味を成しません。
3.  オレンジは単体で用いるキーボード、緑は単体でも青と組み合わせても活用できます。
![haichi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315665/8fab6f58-75fa-8d23-ad55-e4c192637fa8.png)

"P","B","E"キーはブラシの切り替えに活躍するので、Ctrlを外した状態で設定しています。

自分好みのCilpショートカットが複数含まれているので、ここに記載します。反転がうまく動かなかったので、ショートカットを独自にあてて対応しています。
グラデ調整レイヤー：`Ctrl+G`
用紙：`Ctrl+Alt+W`
レイヤーマスク：`Ctrl+Alt+M`
画像読み込み：`Ctrl+Alt+A`
ナビゲーター左右反転（レイヤーに影響しない方）：`Ctrl+Shift+R`


神絵師のショートカットキーではないのであまり参考にしないように


他人様のプログラムを改変したものを載せるのもどうかと思うので、ソースは掲載しません。必要であれば掲載します。

#ahkファイルを起動します。
作成したahkファイルをダブルクリックします。
タスクバー（通常なら右下部分）にアイコンが出現すれば成功です。

#参考ブログ様
https://oekakitoka.blogspot.com/2020/07/autohotkey-002.html
http://ahkwiki.net/SampleCodes
OSSに貢献したくてOSSを自作した

# はじめに
2020年も終わりに近づいてますが皆さんはアドベントカレンダー書きましたか？僕はまだ枠を２つ埋めてないのでこのポエムを書いています。12月の最初にアドベントカレンダーのネタを作ろうと思い、これを期にOSSに貢献しようと思い立ちましたが、なんだかんだあってOSS（といっても簡単なCLIですが）を作ることになりました。

<img src=https://1.bp.blogspot.com/-3eLwtzF2kK0/Vl2zAMEhblI/AAAAAAAA1Oo/9mZo3ujkLNU/s800/christmas_zangyou_man.png width=50%>

# TL;DR
OSS貢献しようとするアクションは勉強になります。特に普段使っているライブラリやツールに対して機能を追加しようと考えた時に既存の機能でできないかちゃんと調べてみたり、実装を理解しようとするからです。しかし、使っているライブラリやツールは比較的スター数が多いものを使うと思うので、その点で言えば簡単に貢献できるかと言うとタイミングによる部分が多いなと感じました。

なので、ネットで見かけるOSS貢献簡単だよ系の記事はスター数が少ないものに貢献するという内容が多い気がします。自分が使わないスター数の少ないものに貢献してもあまり意味がないと思った結果、自作OSSを作ることにしました。

宣伝ですが、作ったのはKustomizeのsourcesの依存関係を可視化する[Graphmize](https://github.com/hourglasshoro/graphmize)というコマンドラインツールを作りました。良かったら使ってみてください。コントリビュートもお待ちしてます。

# OSSに貢献したくて…
## 最初は何もわからない
最初は何もわからないのでネットの記事を頼りにやり方を勉強しました。やり方はこの辺りが参考になりそうです。
[意外ととっつきやすいOSS開発参加方法まとめ](https://qiita.com/shunsuke227ono/items/94dd6e707d34a1da2617)

しかし、TL;DRでも書いた通り普段使っているライブラリは有名どころが多く、最初に手を出すにはキツそうな雰囲気を感じました。思った通りで、この資料にある通り、初心者はプロジェクトと取り組む課題を選ぶところが難しいです。
https://speakerdeck.com/ohbarye/how-to-find-good-first-issues-final?slide=17

## ドキュメントで貢献してみる
とりあえずドキュメントなら貢献できるだろうと思い、業務で使っていた[Kubernetes Cloudflare Sync](https://github.com/calebdoxsey/kubernetes-cloudflare-sync)のREADMEにちょっと追加して、コントリビュートした気分になってみました。しかし、次につなげようとした時にドキュメントを整備するだけでは実装の理解には繋がらないなと感じてしまいました。

## 自分が使ってないツールを開拓する
GtiHubのタグにはgood first issueという親切なものがあり、それがついているissueを眺めることにしました。調べ方ですが、[Github Help Wanted](http://github-help-wanted.com/) というサイトが言語とタグで絞り込むことができ、探しやすかったのでオススメです。ですが、知らないプロジェクトが多いので興味が引かれるものがあればいいですが、使ってみようかなとなるところにハードルを感じました。

## 無理やりOSSに貢献する（？）
Github Help Wantedで探すのも疲れてきてモチベが下がってきてしまったので、自分が普段課題に感じていることを解決するようなアプローチにした方がいいなと思いました。課題を解決できそうなOSSがないか調べているとそれっぽいのがあったのですが、更新が２年前で止まっていたので以下のリポジトリをベースに新しいものを作ろうと考えました。
[jpreese/kustomize-graph](https://github.com/jpreese/kustomize-graph)


実際は欲しい機能と少し違っていたので、このリポジトリを参考にして自分のツールを作ったのですが、やっていることはある意味、機能追加なので得られる経験としては実質貢献（？）だと思います。
<img src=https://3.bp.blogspot.com/-idbE4ndIdhA/VJ6XIw5h0aI/AAAAAAAAqF8/VJm4FpyECb0/s800/shinpai_sosei_kaigo.png width=50%>

# まとめ
アドベントカレンダー用のネタとしてOSSに貢献しました！と高らかに言うことはできませんでしたが、OSSの楽しさを少し感じることができました。モチベを持って地道に続けることができる人ならOSS貢献は楽しめそうな気がします。
すごいコントリビュータになるまでの道は厳しそうですが、スター数の多いライブラリのバグ修正だったりも挑戦してみようと思っています。
RDBに慣れていた自分がDynamoDBを使ってハマった事


## はじめに
ずっとRDB（ほぼmysql）で開発をしてきた自分がDynamoDBを使用した時にハマった事をざっくり記載します。
自分のメ同じような状況の方の参考になればと思います。

## データを検索(where区)する時は、キーに指定したカラムしか検索できない
ハッシュキーとレンジキーに指定したカラムしか検索出来ないので、その他で検索したい場合は
ローカルセカンダリインデックス(LSI)かグローバルセカンダリインデックス(GSI)を使う必要があリます。
グローバルセカンダリインデックスを使えばある程度の検索条件の追加などはクリア出来そうです。

[グローバルセカンダリインデックスの公式doc](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/GSI.html)

## 複数テーブルを更新する時にtransactionを使う事は可能
親子テーブル等の構成の時に一貫性を保って更新したい時はDynamoDBでもtransactionをかける事が可能です。
但し25アイテムまでと制限があるので同時にたくさんのレコードを更新する処理には向いてないと思います。

[transactionについての公式doc](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/transaction-apis.html)

## 取得したデータ量が１mbを越えた場合、１mbまでのデータが取得される（残りは取得できない）
テスト時に少ないデータでテストをしているといつの間にか１mbを超えていて全てのデータが取得できて
いなかったと言った事になりそうなので、複数データを取得する場合などは最初から１mbを超えた場合を想定しておく事が必要そうです。

[1mbを超えた場合の対処法の公式doc](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Query.Pagination.html)

## auto incrementのような機能はない
各テーブル毎のsequence numberを保存する専用のテーブルを作成し、アトミックカウンタを使うことにより実現する事は可能です。

[アトミックカウンタ公式doc](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.AtomicCounters)

## scanは出来るだけ避けてqueryを使う
scanは常にテーブル全体がscanされるため、どうしてもという時以外使わないように設計しないとデータ量が増えた時等に問題になりそうです。

## おわりに
仕様の更新等でだいぶ使いやすくなってきているような気はしますが、RDB経験者にはあまりドキュメントを読まずに実装しようとすると苦戦するポイントもあるように思います。
ドキュメントを読んでいくとまだ他にも制約などがありそうなので、経験者に聞くもしくはドキュメントを読み込んだ上で採用した方が良さそうです。
VSccodeでの初歩的なミス

フロントエンド開発へのスキルチェンジを目指してUdemyを使って学習していて
その過程でやってしまった本当に初歩中の初歩のミスを書いていきます。
学習している技術はVuejsです。
動画の教材通りにコードを書いて
いざ、ブラウザで表示させようとするのですが
「Failed to compile.　./src/components/HelloWorld.vue Module build failed (from ./node_modules/eslint-loader/index.js): Error: ENOENT: no such file or directory, open 'C:\Users\user\udemy-test\src\components\HelloWorld.vue'」
のエラーメッセージが。。
「あれ、教材通りのコードを書いたのどうして？」と混乱しました。
Udemyの動画にはQ&Aの項目があり、そちらに講師に直接、質問できる
機能があるのでさっそく質問してみました。
しかし、質問したのが夜だったこともありすぐには返信が来ず、
エラーの原因もわからず焦るばかりでその日は、Udemyの学習をストップしました。
翌日、講師の方から返信がありました。
しかし、それでもエラーの原因は解決しませんでした。
どうしてだろうとVScodeの画面をじっとみていると
あることに気づきました。
それは、「未保存」という項目。
![資料１.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987352/6cfdcded-22b7-edff-2b59-3630c1828b1d.png)

そう、コードをちゃんと書いてもコードの内容がエラーに表示されなかったのは
コードを書いた後に保存していなかったからでした！
保存をクリックすると、コード通りにブラウザが表示されました。
エラーになったときは、焦っていて全く気が付かなかったのですが
一日開けて冷静になったのか未保存であることに気が付きました。

プロのエンジニアやプログラマーの方からすれば
こんな初歩的なミスをするなんてと呆れられるかもしれないですが、
本当にやってしまいました。。

今後は、このような初歩的なミスをしないためにと、
いるかどうかはわかりませんが他の学習者が私と同じような
ミスをしないためにという思いから残しました。
レスポンシブWebデザインについて

＃目的
・レスポンシブWebデザインについて理解を深める
#内容
画面の大きさによって表示されるWebのスタイルは変更できる。
例えば、パソコンとスマホでは同じウェブサイトでもレイアウトが異なります。
画面の大きさによって見やすく表示内容を変更する機能をメディアクエリといいます。

メデイアクエリは表示内容が切り替わる地点をブレイクポイントと呼び、
ブレイクポイントの領域を定めてCSSの内容を記述します。

```style.html
@media (max-width: 500px){
p{
font-size: 10px;
}
}
```
→画面幅が最大５００pxの時、フォントサイズが１０px
つまり、５００px以下はフォントサイズは１０pxとなる

ブレイクポイントごとにCSSを記述し、デバイスに応じた見やすいウェブデザインをすることができます。
clangでコールグラフを出力

https://stackoverflow.com/questions/5373714/how-to-generate-a-calling-graph-for-c-code/5373814#5373814
ここの記載を参考にやってみた、というお話です。
やってみた、調べた、をメモがてら残そうと思った記事なので、話の裏どりはあまりしていません。

# 検証環境
* MacOS11.1
* clang++(homebrew) 11.0.0

# homebrewで必要なツールをインストール
* macにプリインストールされているllvmではoptコマンドが入っていないので、homebrewを使ってインストールしました。
* dotファイルのプレビュー用にgraphvizというソフトをインストールしました。

# 記事を参考に実行
## dotファイルの作成
下記のコマンドを実行することで、main_cpp.callgraph.dotというファイルが出力されます。

```shell
/usr/local/opt/llvm/bin/clang++ -S -emit-llvm main.cpp -isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk -L /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -o - | /usr/local/opt/llvm/bin/opt -analyze -dot-callgraph --callgraph-dot-filename-prefix=main_cpp
```

オプション。

### clang++
<dl>

<dt>-isysroot</dt>
<dd>sysrootを起点にusr/includeなどのヘッダファイルのディレクトリを探しに行きます。macでは/Library/Developer/CommandLineTools/SDKs/MacOSX.sdkになると思います。(これを指定しないとinclude_nextディレクティブで指定されているヘッダファイルを見つからなくてコンパイルが通りませんでした。参考 : https://qiita.com/coil_msp123/items/00bfa7a1e42602883882)</dd>

<dt>-S</dt>
<dd>プリプロセスとコンパイルだけ。リンクはしない、ってことだと理解。</dd>

<dt>-emit-llvm</dt>
<dd>アセンブラやオブジェクトファイルの表現として、LLVMの表現形式を利用。</dd>

<dt>-o -</dt>
<dd>-oが出力ファイル名を指定。
多分標準出力に結果を出力、だと思ったのですが、パッと文献を見つけられなかったので深追いはしていません。</dd>

</dl>

### opt

opt自体はllvmの各パスを調査するためのツール、みたいな説明でしたがllvmにおけるパスの意味がしっかりわかっていないので深追いはしません。

<dl>

<dt>-analyze</dt>
<dd>分析を行う。最適化なし。</dd>

<dt>-dot-callgraph</dt>
<dd>dot形式でグラフを出力</dd>

<dt>--callgraph-dot-filename-prefix</dt>
<dd>dotファイルの接頭辞です。指定しないと&lt;stdin&gt;が用いられて扱いにくいファイルができます。(このオプションは—help-hiddenで確認できます。参考 : https://nothingcosmos.wiki.fc2.com/wiki/optの概要)</dd>

</dl>

## dotファイルをpngに

dotコマンド(Graphviz)は/usr/local/binにインストールされる。

```shell
dot -Tpng -ocallgraph.png main_cpp.callgraph.dot 
```

オプションは-Tで形式指定、-oで出力ファイル名、という感じだと思う。
床の上をバウンドする球の作り方

#平らな床を配置する

##Planeの配置
**GameObject->3D Objectから、Planeを配置する。
PlaneにRiditbodyを付与し、Is Kinematicにチェックを入れる。
（これで、床の上のものが、貫通して下に行かなくなる。）**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/850380/958ca69a-66d1-f5a1-7e6c-aaaf2dc6bdda.png)

#バウンドする球を作る

##sphereの配置

**GameObject->3D Object からsphereを選択して作成する。
ProjectのAssets直下に、ファイルを作成する
（今回のファイル名は、Physics Materialsとしている。）**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/850380/379ba796-db39-7f95-406e-2ab8d14741c0.png)

##Phisic Materialの作成

**さっき作ったファイルの中で、Create->Phisic Materialを選択する。
（今回の名前は、Boundとしている。）
このPhisic Materialは、よく使うものらしい。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/850380/0653ce2e-a231-55d8-4c5e-bd0ce3912596.png)

##Phisic Materialの設定

**Boundを選択し、右に出てきた
「Bounciness」->0.7に
「Bounce Combine」->Maximumにする。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/850380/4dc3e2ab-7e40-0c90-6c65-0b2ce634a46f.png)


##Phisic Materialの詳細解説

**Phisic Materialの項目についてまとめておく。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/850380/d77f3b6a-5b7a-273d-912a-72f88e24eaeb.png)


|名前|詳細|
|-----|-------------------------------------------|
|Dynamic Friction|摩擦抵抗の値で、０～１が推奨値。動いている物体に対して、「どのくらい滑り続けるか」を決める。|
|Static Friction|動いてない物体に対して、「どのくらいの力で押せば動くか」を決めることができる。大きいほど、滑りにくくなる。|
|Bounciness|弾性の値。０であれば全く跳ねず、<br>1であれば力の減衰なしに跳ね返ってくる。|
|Friction Conbine|実際に適用される摩擦抵抗の計算方法。Avarageでは<お互いの摩擦抵抗の平均値。<br>MaximumとMinimumでは、摩擦抵抗の大きい方・小さい方を採用する。Multipleでは、掛け算する。|
|Bounce Conbine|実際に適用される弾性の計算方法。上と同じ計算方法。|

##球の作成&Materialのアタッチ

**sphereを選択し、Inspectorの下の方に行くと、
「Sphere Collider」という欄があるので、
その「Material」の場所に、さっき作ったBoundを付与する。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/850380/2266b916-ea65-a5e6-3a1e-749b9f92afc7.png)

##SphereにRiditbodyを付与

**最後にSphereにRiditbodyを付与し、
Use Glavityにチェックを入れて、画面左上のFile->Saveを押す
再生ボタンを押すと、ボールがバウンドして止まる運動が再現される。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/850380/94a10f41-c755-0645-ae8f-7d0eea23512b.png)


今回の内容は以上です。
読んでいただき、ありがとうございました！
Faker使ってFactoryBot作ったけど、たまに意図しないパスワードが生成されるから、コンソールで色々条件を変えて検証してみた話

#はじめに
　Fakerを使ってFactoryBotを作成して、テストコード書いていました。しかし、時々すでにテストコードが通っていた場所なのに、「パスワードが不正な値です」というエラーが出てしまいました。ふと、疑問に思い、Fakerについて調べてみました。
　主な内容は、Fakerが提供している、パスワードをランダムに生成する機能の英語を訳したようなものです。

##Fakerとは

[FakerのGitHub](https://github.com/faker-ruby/faker)

　gemとしてインストールすることで、ランダムに色々な値を生成してくれます。名前や住所はもちろん、ポケモンの名前まで…（笑
　しかし、全て英語です…。私は、雰囲気だけで使ってます。

##[Faker::Internet](https://github.com/faker-ruby/faker/blob/master/doc/default/internet.md)

###基本形

```ruby
Faker::Internet.password
#=>"W9vSoO7oRzE5aNkB"
```
基本形と言いつつ、以下の文字からランダムにが選ばれています。字数はバラバラです。
- <font color=red>大文字</font>
- 小文字
- 数字

逆に、%や$や#などの記号は選ばれません。

---
ここからは、基本形に条件を加えていったものです。
まずは、
###<font color=orange>字数</font>に条件を設ける

【最低文字数】

```ruby
Faker::Internet.password(min_length: 8) #最低でも8文字生成します
#=>"IgQnSpLk113E"
```
【最大文字数】

```ruby
Faker::Internet.password(max_length: 20) #最大でも20文字生成します
#=>"RbL74hTbLxJl1UrI5327"
```
---
次に紹介する2つは、ランダムに選ばれる文字の種類についてです。
2つとも`true`と`false`を切り替えることが出来ます。

###<font color=green>文字の種類</font>に条件を設ける

【大文字小文字】

```ruby
Faker::Internet.password(mix_case: true) #大文字も小文字も数字も選ばれる可能性があります
#=>"FbSeLc2PyJ"
```

```ruby
Faker::Internet.password(mix_case: false) #大文字が選ばれることはありません
#=>"1w24yba8g1wa"
```

<font color=red>【大文字小文字】はデフォルトで`true`です。</font>

【記号】

```ruby
Faker::Internet.password(special_characters: true) #色々な記号が選ばれる可能性があります
#=>"!@*2zBxB7yD4yCl"
```

```ruby
Faker::Internet.password(special_characters: false) #記号が選ばれることはありません
#=>"50MtIaT8kLaHv"
```
これは、もはや、基本形と全く同じ状態です。
<font color=red>【記号】については、デフォルトで`false`です。</font>

##備考
　それぞれの条件は単体で使うことも、組み合わせて使うことも可能です。生成したいパスワードに合わせて指定してください。組み合わせる際は、`,`で区切ります。
例）
【<font color=orange>最大文字数</font>・<font color=green>記号可</font>】

```ruby
Faker::Internet.password(max_length: 10, special_characters: true)
#=>"#%&!4XxO"
```

【<font color=orange>最低文字数</font>・<font color=green>大文字不可</font>】

```ruby
Faker::Internet.password(min_length: 6, mix_case: false)
#=>"ysndk7ao450u"
```
【<font color=orange>最低最高文字数</font>・<font color=green>大文字不可・記号可</font>】

```ruby
Faker::Internet.password(min_length: 6, max_length: 10, mix_case: false, special_characters: true)
#=>"$l0cam32"
```

##最後に
　あくまで、ランダムに生成されているので、確率の問題で、たまに、数字が入らず、バリデーションで英数字最低1文字以上としていると、エラーになることがあります。現状の解決方法としては、<font color=red>最低文字数を多めに設定</font>しておけば、数字がないために、エラーとなる可能性を減らすことが出来そうです。
　正規表現みたいに、英数字最低1文字以上という指定の仕方があればいいのに…
M1のMACでOpenCV＋Tensorflowができない話 （解決）

# 2020/12/29追記　（解決）
解決策が見つかりました。
方法としてはターミナルをRosettaで起動して、Anaconda経由でtensorflowとopencvをインストールすればいけます。
ただ、Appleが最適化してくれたtensorflowコードを利用することはできないので処理速度は落ちます。
細かい導入手順については、別記事にまとめます。
# はじめに
<!-- 発端や概要を記載 -->
前の記事でOpenCVは入ったので、Tensorflowを入れましたが上手く動きませんでした...

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [導入手順](#Chapter1)
1. [実行！！](#Chapter2)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# 手順
①tensorflowをインストール[ここ参照](https://qiita.com/tomoyaeibu/items/46f2f3384a370df71d5e)
②Opencvをインストール
※注意：Opencvはターミナルを「Rosettaを使用して開く」にしないとインスールできない

```
pip3 install opencv-python
```


<a id="#Chapter2"></a>
# 実行！！
はい。動きません。理由は下の通り
tensorflowは「Rosettaを使用して開く」では動かない！
opencvは「Rosettaを使用して開く」じゃないと動かない！

情弱なので苦労してますが、良い解決策が見つかったら更新します
初めてgit pullしようとしたら、何やらSSH keyを設定しろと言われた。

Macを新調したついでに、ちょっとチーム開発気分を味わってみようかなと思い、古いMacでチョコチョコ上げていたリポジトリを、新しいMacでpullしてきて開発してみようと試みた。

ら、



```

$git pull origin master

The authenticity of host 'github.com (数字.数字.数字.数字)' can't be established.
RSA key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
Warning: Permanently added 'github.com,数字.数字.数字.数字' (RSA) to the list of known hosts.
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

```

と言われてしまった。

エラー文で検索すると、[Qiita記事:GitエラーPermission denied (publickey).の解決方法](https://qiita.com/tetsu-upstr/items/e72147250701cf30ee72)が出てきたので、とりあえずSSH鍵を作る必要があると理解。

以下記事をコピペで、SSH keyを設定したら、無事にpullできるようになった。
・[Qiita記事:お前らのSSH Keysの作り方は間違っている](https://qiita.com/suthio/items/2760e4cff0e185fe2db9)



その後、git pushの度にSSH鍵入力を要求されるようになってしまったので、以下記事を実行したら解消した。
[Git:Git BashにてSSH鍵のパスフレーズ入力を初回のみにする](https://takanosho.wordpress.com/2013/01/11/input-ssh-key-passphrase-only-once-on-git-bash/)
GitHub Actions Self Hosted Runnerで.git/が存在しない場合の対処

GitHub Actions Self Hosted Runnerで .git/ が存在せず `git add` が出来ない場合の対処をメモしておく．

# 結論

Gitのバージョンが2.18以上でないとDownloadになる．GitHub Actionsのログのメッセージに出力されていた．

> To create a local Git repository instead, add Git 2.18 or higher to the PATH

# 対処

Ubuntu 18.04でapt経由でインストールすると古いGitになるので入れ替える．

参考: [How To Install Git from Source on Ubuntu 20.04 [Quickstart] | DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-install-git-from-source-on-ubuntu-20-04-quickstart)

現在のGitバージョンを確かめる．

```
$ git version
git version 2.17.1
```

以下のコマンドでgitを削除する．

```
$ sudo apt purge git
```

記事を執筆している時点での最新バージョンは 2.29.2 である．
ソースからGitをビルドする．

ソースコードの取得と解凍を行う．

```
$ cd /tmp
$ wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.29.2.tar.gz
$ tar xvf git-2.29.2.tar.gz
$ cd git-2.29.2/
```

ビルドに必要なパッケージ群を導入する．

```
$ sudo apt install libz-dev libssl-dev libcurl4-gnutls-dev libexpat1-dev gettext cmake gcc
```

ビルドを行いインストールをする．

```
$ ./configure
$ make prefix=/usr/local all
$ sudo make prefix=/usr/local install
```

Gitが入れ替わったか確かめる．

```
$ exec bash
$ git version
git version 2.29.2
```

# 参考URL

- [[自分用] git clone https:/~ でfatal: Unable to find remote helper for 'https'が出たとき - Qiita](https://qiita.com/a_ishidaaa/items/8bb63a625e8a89b21a12)
mongo-go-driverで「$in」オペレータを使う

## 概要
MongoDBで、複数の値のいずれかに該当するドキュメントを取得する[$in](https://docs.mongodb.com/manual/reference/operator/query/in/)オペレーターがあります。今回はmongo-go-driverで `$in`を使いたい時に、どうすれば良いかを書きます。

## 対応
[How to use the elements of a slice in bson.A using mongo-go-driver 0.2.0](https://stackoverflow.com/questions/54276007/how-to-use-the-elements-of-a-slice-in-bson-a-using-mongo-go-driver-0-2-0)の記事にある通り、`$in`に続く配列の値を`bson.A`型にして設定します。[こちら](https://godoc.org/go.mongodb.org/mongo-driver/bson#A)のドキュメントにある通り、`bson.A`はクエリの中で配列を扱う型になります。

## 実装サンプル
クエリの設定部分のみサンプルとして記載します。コレクション取得までの記載は割愛しますので、詳細は@yotahada-nus3さんの[mongoDB公式のGoのDriverを使ってみた](https://qiita.com/yotahada-nus3/items/9798b4ebb30f0842c137)の記事をご参考ください。内容としては、絞り込みたい「_id」の内容を保持したsliceを、bson.A型に詰め替えてクエリに設定します。

```go:sample.go
func SampleGetByIDs(ids []string) error {
	// コレクションの取得処理は割愛・・・
	idBsonA := bson.A{}
	for _, id := range ids {
		idBsonA = append(idBsonA, id)
	}
	filter := bson.D{{Key: "_id", Value: bson.D{{Key: "$in", Value: idBsonA}}}}
	cur, err := col.Find(context.Background(), filter)
	// curの取得処理は割愛・・・
}

```
【AWS】$docker build .＊エラー＊ Gem::Ext::BuildError: ERROR: Failed to build gem native extension. 

#　結論
Swapファイルの領域が足りなかったみたいです。

###　◆Swapファイルとは
メモリの容量を一時的に増やすために準備されるファイル。
EC2はデフォルトではSwapファイルを用意していないため、大きな処理をすると処理エラーが起こってしまうようですね！


#　エラー文
```ターミナル.
[ec2-user@ip-10-0-0-180 app]$ docker build .
Sending build context to Docker daemon  889.9kB
Step 1/12 : FROM ruby:2.7
 ---> 7e58098089a4
~省略~

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    current directory: /usr/local/bundle/gems/sassc-2.4.0/ext
/usr/local/bin/ruby -I /usr/local/lib/ruby/2.7.0 -r
./siteconf20201228-6-fydanh.rb extconf.rb
creating Makefile

current directory: /usr/local/bundle/gems/sassc-2.4.0/ext
make "DESTDIR=" clean

current directory: /usr/local/bundle/gems/sassc-2.4.0/ext
make "DESTDIR="
compiling ./libsass/src/ast.cpp

~省略~

compiling ./libsass/src/parser.cpp
virtual memory exhausted: Cannot allocate memory
make: *** [Makefile:237: parser.o] Error 1

make failed, exit code 2

Gem files will remain installed in /usr/local/bundle/gems/sassc-2.4.0 for
inspection.
Results logged to
/usr/local/bundle/extensions/x86_64-linux/2.7.0/sassc-2.4.0/gem_make.out

An error occurred while installing sassc (2.4.0), and Bundler cannot continue.
Make sure that `gem install sassc -v '2.4.0' --source 'https://rubygems.org/'`
succeeds before bundling.

In Gemfile:
  sass-rails was resolved to 6.0.0, which depends on
    sassc-rails was resolved to 2.1.2, which depends on
      sassc
The command '/bin/sh -c bundle install' returned a non-zero code: 5
```

__<font color="FireBrick">＊＊下記注目すべきエラー個所</font>__
仮想メモリが足りなくて「gem native extension」がbuildできなかったみたい。

```
// gem native extensionがbuildできなかった
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
```
```
// 仮想メモリが使い果たされました：メモリを割り当てることができませんmake：*** [Makefile：237：parser.o]エラー1
virtual memory exhausted: Cannot allocate memory
make: *** [Makefile:237: parser.o] Error 1
```

#　Swapファイルの領域を広げる
```ターミナル.
# ホームディレクトリで行います
[ec2-user@ip-172-31-25-189 ~]$ cd
[ec2-user@ip-172-31-25-189 ~]$ sudo dd if=/dev/zero of=/swapfile1 bs=1M count=512

# 下記内容が表示されます
512+0 レコード入力
512+0 レコード出力
536870912 バイト (537 MB) コピーされました、 7.35077 秒、 73.0 MB/秒

# 権限の変更
[ec2-user@ip-172-31-25-189 ~]$ sudo chmod 600 /swapfile1

# Linux のスワップ領域をデバイス上またはファイル上に準備する
[ec2-user@ip-172-31-25-189 ~]$ sudo mkswap /swapfile1

# 以下のように表示される
スワップ空間バージョン1を設定します、サイズ = 524284 KiB
ラベルはありません, UUID=74a961ba-7a33-4c18-b1cd-9779bcda8ab1

# おそらくデバイスやファイルへのページング、スワッピングを有効にしてる
[ec2-user@ip-172-31-25-189 ~]$ sudo swapon /swapfile1

# 細かい内容はまだわかっていません。ご存知の方がいらっしゃればコメント欄へ記入いただけますと幸いです。
[ec2-user@ip-172-31-25-189 ~]$ sudo sh -c 'echo "/swapfile1  none        swap    sw              0   0" >> /etc/fstab'
```

__私の場合は、Swapファイルの領域を広げるとエラーでずにbuildできました！　__
__ご参考になれば！__
今日から少しずつDiscord.pyの記事を書きます！

##少しずつ書いていきます！
Discord botの開発を行っています。
（詳細は[URL](http://koucha.html.xdomain.jp/mattya/mattya.html)をご覧ください）
そして現在私が開発しているbotの開発者を募集中です。
よければサポートサーバーまでお願いします。
リーマンサット・プロジェクト　2021新春アドベントカレンダー　インデックス記事

あけましておめでとうございます。
**趣味で宇宙開発を行う団体**「[リーマンサット・プロジェクト](https://www.rymansat.com)」がお送りする新春アドベントカレンダー的な記事リレーのインデックス記事です。

> リーマンサット・プロジェクトは、**2機目の人工衛星**である[RSP-01](https://www.rymansat.com/satellites)を**趣味で開発**しました。
> この人工衛星は、2021年に[宇宙へ打ち上げ予定](https://www.rymansat.com/archives/11607)です。
> すごい！

新春アドベントカレンダーは昨年も実施し、実はリーマンサット**内部でも結構好評**でした。
**記事がきっかけでrsp.に参加**された方が発生した事、さらには**継続は力**なりという事で今年もやります。

リーマンということで平日だけの投稿になります。

| 日付 | 投稿者 | タイトル |
|:--:|:--|:------------------|
| 1/5(火) | @Pinductor  | [趣味で宇宙開発するのに必要な〇〇駆動開発](https://qiita.com/Pinductor/items/d0aa1427daf853c26161) |
| 1/6(水) | @manabu042001 | [基板設計初心者がカメラモジュールプロトタイプを作ってみた](https://qiita.com/manabu042001/items/0beb094a9a84d80b5a29) |
| 1/7(木) | @rsp-dgkz | [今年のショートケーキは役に立つはず](https://qiita.com/rsp-dgkz/items/ea9ec4a3d660da0fc9dc) |
| 1/8(金) | @hokke_mirin | [パソコンの自作って難しいのか？](https://qiita.com/hokke_mirin/items/d002532fc7c9238557f9) |
| 1/12(火) | @ynaoya_swpjt | [愛知県で宇宙開発やってます](https://qiita.com/ynaoya_swpjt/items/961aea8f46034d94a374) |
| 1/13(水) | @Gan0803 | [1 / f で七色にゆらぐLED照明を電子工作する（入門レベル）](https://qiita.com/Gan0803/items/ac8c54ba75428d64f448) |
| 1/14(木) | @Ushinj | [CSSアニメーションを使って、Webブラウザに流れ星を流したい](https://qiita.com/Ushinji/items/b2641f0e458dacd609a6) |
| 1/15(金) | @ukisoft | [firebase storage のサイズが大きくなったのでオラったらやらかしちゃった話](https://qiita.com/ukisoft/items/c5abe2280662515b8592) |
| 1/18(月) | @lemonade787 | [カッコウは人工衛星に卵を産むか〜人工衛星のセキュリティ脅威概況〜](https://qiita.com/lemonade787/items/e5a98b86983a64b83027) |
| 1/19(火) | @kohei0302 | [NATを越えよう！MQTTを使って家の外からLチカ](https://qiita.com/kohei0302/items/fd1681e14a426c4dd072) |
| 1/20(水) | @KaitosLab | [趣味で宇宙開発の技術広報課長の課外授業：Web系メディア開発はじめる](https://qiita.com/KaitosLab/items/bc041068107e87d20a7e) |
| 1/21(木) | @rhiro | [アポロ計画におけるマトリックス組織について](https://qiita.com/rhiro/items/d6a78d27ba311b04ccac) |
| 1/22(金) | @pmbit_jam | [KiCADである程度の規模の基板を効率よく設計したい (モジュール設計を気軽にオープンソース開発環境で)](https://qiita.com/pmbit_jam/items/e306f1e9dc84f63a0ffd) |
| 1/25(月) | @Fuminori_Souma | [【Python】高速道路のIC/JCTは本当にクロソイド曲線状に建設されているのか？検証してみた](https://qiita.com/Fuminori_Souma/items/2f530a61566e20f09a58) |
| 1/26(火) | @yohachi | [GreengrassでIoT入門](https://qiita.com/yohachi/items/78f794ac665099c3a82a) |
| 1/27(水) | @ishikawa-takumi | [スマートめだかライトを作ってみた](https://qiita.com/ishikawa-takumi/items/97af23d190a97346b2bf) |
| 1/28(木) | @prestissimo2020 | [趣味の宇宙開発の広報がprogateから始めてみた](https://qiita.com/prestissimo2020/items/c479399651ebad5f3aab) |
| 1/29(金) | @iriyamanorio | [衛星追尾のアンテナ方位・仰角の制御について](https://qiita.com/iriyamanorio/items/891ac6a18a5e1432d791) |
| 2/1(月) | @ad_motsu | [Python再履修も兼ねて宇宙関係のMicrosoft Learnをやってみた](https://qiita.com/ad_motsu/items/fc35b2fa0e8b5ee1b089) |
| 2/2(火) | @pisamatsu | [RTL-SDR と V-Dipole アンテナで作る地上局 ー RSP-01 の電波を受信するために](https://qiita.com/pisamatsu/items/2cd25d20281d3a3e41c8) |

---

リーマンサット・プロジェクトは「普通の人が集まって宇宙開発しよう」を合言葉に活動をしている民間団体です。
他では経験できない「宇宙開発プロジェクト」に誰もが携わることができます。

興味を持たれた方はこちら [https://www.rymansat.com/join](https://www.rymansat.com/join) からお気軽にどうぞ。
**寄付**も募っています。[https://www.rymansat.com/donate](https://www.rymansat.com/donate)
Visual Studio CodeでRemote-SSHできないときの対処法

Windows標準のSSHクライアントとVisual Studio CodeのRemote-SSHの組合せハマった時のメモ。

結論としては、Windows標準のssh.exeを使わずに、Windows版gitに付属のssh.exeを使ったら解決した。

## 環境
- ホスト
  - OS: Windows 10 
  - SSHクライアント: Windows 10 標準 (OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5)
- Remote
  - OS: Ubuntu 18.04
  - SSHサーバ：OpenSSH Server
  
## 現象
VSCodeからRemote接続すると、RemoteとのSSH接続までは成功する。その後、Remoteのフォルダを開こうとするとフリーズ。
しばらくするとSSHが切断され、再接続を求められる。これの繰り返し。

## 対策
VSCodeが使うSSHクライアントを、Windows版gitに付属のssh.exeに変更する。
具体的にはVSCodeのsettings.jsonを開いて下記のエントリを追加する。

```
"remote.SSH.path": "C:\\Program Files\\Git\\usr\\bin\\ssh.exe"
```
Windows版gitが未インストールの場合には先にインストールしておくこと。

## 補足
Window標準のSSHクライアントのバージョン

```
PS C:\Windows\System32\OpenSSH> ssh -V
OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
```
Windows版gitのSSHクライアントのバージョン

```
PS C:\Program Files\Git\usr\bin> & 'C:\Program Files\Git\usr\bin\ssh.exe' -V
OpenSSH_8.3p1, OpenSSL 1.1.1g  21 Apr 2020
```
本番環境にアニソンのファイルあげて大恥かいた話

## 概要
今年ももうすぐ終わりですね。
「今年の反省は今年のうちに」ということで、今回は**年末に本番でやらかしたお話**を投稿したいと思います。

遡ること2日前、私は現在エンジニアをしているインターンで、**ファイルをアップロードするシステムのバグ修正**を行っていました。
コーディングはすんなりとすすみ、無事デプロイも終了。本番でちゃんとアップロードできるかの軽いテストを行い、その日は退社しました。

翌日、出勤するやいなや、上司に呼び出されました。


上司 *「〇〇くん, ファイルアップロードのシステムさわった？なんか変なファイルが上がってるんだけど...」*
私 *「変なファイル...ですか ?」*

指定されたurlを確認してみると, なんとそこには友人が熱唱している**[私アイドル宣言](https://www.youtube.com/watch?v=m7ddbml_vkY)の音源がアップロードされていました。**
（ちなめっちゃいい曲です　聞いてみてください）

![スクリーンショット 2020-12-28 22.57.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223014/e19fd7ba-c8d6-3047-726e-1a7fcd1c2642.png)

幸いにもファイルは非公開設定になっており、アップロードも自社のテスト用アカウントで行ったものだったので、「俺くんはキモオタ」という噂が会社中に流れるだけですみました。 ~~いや普通に死にたい。~~
が、もしもそのファイルが公開設定で、ユーザーの目に触れてしまっていたら...考えるだけでゾッとします。

## （余談）なんの実装をしようとしていたのか
背景として、**なんの実装をしようとしていたのか**について軽くふれておきます。（なぜ本番環境でテストをするはめになったのかという話に若干繋がりますが、読み飛ばしてもらっても全く問題ありません。）

ことは「**なぜか本番だけサイズの大きいファイルのアップロードができない**」という問題から始まりました。
そもそも弊社では従来以下の図のように「ファイルそのものをAPIに渡し、s3にアップロードする」という仕組みをとっており、本番では前段にAPI Gatewayを設置していました。調査の結果、**API Gatewayの仕様上、10MB以上のファイルのリクエストははじかれていることが発覚しました。**
![スクリーンショット 2020-12-28 22.46.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223014/dfab1010-3e5f-938b-809b-17e403e68b49.png)
そこで回避策として、**APIからはアップロード用のpresigned-urlを発行 => ファイルはフロントから直接アップロードという構成**を取ることにしたわけです。
![スクリーンショット 2020-12-28 23.00.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223014/95a32bd8-a43b-0bee-220c-6d437b9c8c43.png)

より詳細な説明が欲しい方は[この記事](https://qiita.com/akatsukaha/items/2ba0d709835899dae8dd)などが参考になると思います。

ちなみに、**ステージング環境では前段のAPI Gatewayを省略していたため同じ状況は起こっていませんでした。**（それが原因の一端を担うことになったのですが...）

## 一体何が原因だったか
一体なぜこのようなミスが起きてしまったのでしょうか？
私が無能だったからと一括りにしてしまうのは簡単ですが、同じミスを繰り返さないためにきちんと分析してみようと思います。

### 開発時もよくわからないファイルをあげていた
件のファイルですが、Finderで動画を検索した時にトップに出てきていました。
中身は知っていたものの、開発中は**「どうせ開発環境だから」**という意識で、何も考えずに同ファイルでアップロードのテストをしていました。結果本番でのテストアップロードの際も同じファイルを無意識であげてしまう事態につながりました。
適当なファイルをあげる、適当な名前をつける（タイトルにう●ことつける）など、**本番環境でやってはいけないことは開発中もやらないようにしよう**という教訓を得ました。

### 本番という意識があまかった
そもそも開発中のサービスは正式リリース前で、利用客もほとんどおらず、本番に多少変なデータやバグのあるプログラムがあがってしまってもほとんど被害が出ない状況でした。ここから「**本番だけどある程度適当でいいや**」という甘えが生じ、結果今回の自体に繋がりました。（おかげで失敗に対して被害はほとんど出なかったわけですが...）
しかしながら、このような意識のままでは正式リリース後も同じようなミスをし、取り返しのつかない失敗をしていたかもしれません。
**たとえリリース前でも本番環境であるという意識はきちんともとう**という教訓を得ました。

### ステージングがうまく機能していなかった
弊社でもいわゆる「ステージング環境」は存在していたものの、あくまで「本番と同様のデータで齟齬がでないかをチェックする」ための環境であり、**本番の構成とはかなりの差がありました。**（今回で言えばAPIの前段にAPI Gatewayを設置していないなど）
そもそも、本番とステージングで同等の構成をとっていれば、本番でテストをしなければならないような状況になることもなかったでしょう。
**ステージングは本番の写絵として、本番と全く同じ構成で作るべし**という教訓を得ました。


## 来年気をつけること
以上を受けて、今後開発をする際には以下のことに気をつけてやろうと思います。

- **本番でやらないことは開発でもやらない。**
- **本番環境であるという意識をきちんともつ。**
- **ステージングを機能させる（本番環境と同等の構成でつくる）**

来年はこんなしょぼいミスをしないよう、日々精進していきます。
FortiClient VPN(Windows版)でパスワード保存を有効にする

# TL;DR
- FortiClient6.4で毎回パスワードを入力したくない方へ、朗報です。以前のFortiClientのように（少なくともFortiClient5.0以前ではパスワード保存できていました）、パスワード保存を実現します。
- 設定ファイルをバックアップ・リストアする方法もあるようですが、うまくいかなかったので、こちらの方法を紹介します。
- 管理者権限が必要ですので、お持ちでない方は、残念ながら回れ右でお願いします。
- レジストリを編集しますので、自己責任でお願いします。

# 手順概要
- FortiClient VPNインストール→接続設定登録→レジストリ編集 の手順で完了します。

# 手順詳細
## 1. FortiClient VPNインストール
https://www.forticlient.com/downloads
より、FortiClient VPNをダウンロード・インストールします。

## 2. FortiClient VPN設定
- a. インストール後に、FortiClient VPNを起動し、「VPN設定」リンクをクリックします。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85163/47ee3584-4a5d-5aa9-210a-93030a549b69.png)

- b. システム管理者より受領した情報を入力し保存します。「ユーザ名を保存」にチェックを入れないと、パスワード保存の意味がなくなります。。。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85163/158aa7e8-b0a4-3601-9b3c-9029b20834b7.png)

- c. 接続名とユーザ名が入力された状態になります。ここで右上の×ボタン等で、いったんFortiClient VPN を終了します。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85163/72579bf7-70be-9630-fee6-21005a2fcfac.png)

- d. ファイル名を指定して実行等で、レジストリエディタを起動します。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85163/eb80719d-1d82-0953-c4e2-23844d8c00df.png)

- e. レジストリエディタより、HKEY_CURRENT_USER\SOFTWARE\Fortinet\FortiClient\Sslvpn\Tunnels を選択します。その下に、b. で設定した「接続名」があるので、それを選択します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85163/7d3a3954-7cad-5b75-8de2-ba2a11fe593b.png)

- f. 新規にDWORD値を作成します。キー名は、show_remember_password で、値は16進数で1を入力します。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85163/badd070b-8447-06b6-4010-7fe65dd3104f.png)

- g. 無事に「パスワードを保存」チェックボックスが表示されました。あとは、パスワードを入力し、「パスワードを保存」チェックボックスにチェックを入れて、「接続」するだけです。FortiClient VPN を再起動しても、パスワードは保存されたままとなっています。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85163/05744613-e5ff-3229-921a-7e9cb9a456c5.png)

- h. 参考までですが、レジストリのDATA2のところに、保存されたパスワードが暗号化されていることが確認できます。 （DATA1はユーザ名が暗号化されたものと思われる）
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85163/ad431825-c5ca-60bd-c7f1-e8ff4459a278.png)

# 余談

- レジストリの位置を探すことが、今回のメインでしたね。以前のバージョンではHKLMの下に配置されていたようなので、少し手こずりました。
- 自動接続(show_autoconnect)や、常にアップ(show_alwaysup)の機能もあるようですが、未検証です。
非推奨のAPIを使用またはオーバーライドしています

#何が問題か
android環境下でflutter runしたら
「非推奨のAPIを使用またはオーバーライドしています」となった。

#解決策
minSdkVersion を21から23に変更
※各々の開発環境に合わせて、ここの数字を上げていけばエラーは消えます