OmniAICreator/Qiita-1.07M huggingface dataset:
RHELを無料で使う ( Red Hat Developer プログラム サブスクリプション適用 )

## 概要

既報の通り、RHELの無償利用が拡大されました、
[Red Hat Developer](https://developers.redhat.com/) にアカウントを作るだけでサブスクリプションがもらえるので、この機会にさくっともらっておきましょう。3分で終わります。

既報 : [個人開発者はRed Hat Enterprise Linuxを無料で最大16システムまで利用可能に　本番環境もOK - ITmedia NEWS](https://www.itmedia.co.jp/news/articles/2101/22/news099.html)

## サブスクリプションをGETする

[Red Hat Developer](https://developers.redhat.com/) にアカウントを作成します。
ほどなく [Red Hat Customer Portal](https://access.redhat.com/management/subscriptions) に以下のように `Red Hat Developer Subscription for Individuals` というサブスクが降ってくることが確認できます。
サブスクをもらう手順はこれだけです。

なおサブスク名をクリックすると確認できる詳細の`Entitlement Quantity`の値が適用可能な数です。
記事執筆次点では`16`でしたので16台のRHELに適用できそうです、十分な数ですね。

![subscriptions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21106/7cd5accc-6588-b046-6958-10945ebed3ee.png)

また、`エラータ`タブには、自身のシステムに紐づくパッケージの更新情報や脆弱性情報などのエラータ情報が閲覧でき、関連するRed Hatの技術情報が参照できます。
サブスクのメリットですね。

## RHELにサブスクを適用する

RHELを新規インストールしてサブスクを適用する場合は [Red Hat Enterprise Linux Hello World | Red Hat Developer](https://developers.redhat.com/products/rhel/hello-world) をご参照ください。

すでに REHLマシンがある場合は以下のように`subscription-manager attach`で適用できます。

```sh
[loft@rhel8 ~]$ sudo subscription-manager register
[loft@rhel8 ~]$ sudo subscription-manager list
+-------------------------------------------+
    Installed Product Status
+-------------------------------------------+
Product Name:   Red Hat Enterprise Linux for x86_64
Product ID:     479
Version:        8.3
Arch:           x86_64
Status:         Not Subscribed
Status Details: Not supported by a valid subscription.
Starts:
Ends:

[loft@rhel8 ~]$ sudo subscription-manager attach
Installed Product Current Status:
Product Name: Red Hat Enterprise Linux for x86_64
Status:       Subscribed

[loft@rhel8 ~]$ sudo subscription-manager list
+-------------------------------------------+
    Installed Product Status
+-------------------------------------------+
Product Name:   Red Hat Enterprise Linux for x86_64
Product ID:     479
Version:        8.3
Arch:           x86_64
Status:         Subscribed
Status Details:
Starts:         03/13/2021
Ends:           03/13/2022

[loft@rhel8 ~]$ 
```

これで`yum`や`dnf`が使えるようになります。
個人開発の環境として気軽にRHELという選択肢も選べるようになりましたね。
あとは煮るなり焼くなりして楽しんでいきましょう。

## 参考文献

- [FAQs for no-cost Red Hat Enterprise Linux offered via the Red Hat Developer Subscription for Individuals | Red Hat Developer](https://developers.redhat.com/articles/faqs-no-cost-red-hat-enterprise-linux#)
  - `1. How do I get a no-cost Red Hat Developer Subscription for Individuals that offers Red Hat Enterprise Linux?` をご参照ください。
windows10でCUDA：GPUを使ってPyTorchを動かすためのポイント

##PytorchをCUDAで動かす
###日経ソフトウェア21/01の記事の後半部
日経ソフトウェアの２１年１月号に`pytorch`でのCNNを動かす特集記事があります。わかりやすい記事で良かったです。この記事の後半部にGPUで`Pytroch`を動かす方法がのっています。そこで、CUDAを入れてみたのですが、動かすまでに時間がかかりましたので、自分がはまったポイントを覚えのために書いておきます。
（※10/04　５のパスについて追記しました）

###４つの条件が合わないといけない
まず４つのドライバーやライブラリーは以下の４つです。
このバージョンが合わないと動かない。

・NvideaのGPUドライバー
・CUDA　toolkit
・cuDNN
・Pytorch

まず`Pytorch`の[公式サイト](https://pytorch.org/)を見ます。
INSTALL PYTORCHのところを見ると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/26bfaa76-9cb6-f6ef-761a-5bc3ffe1fb37.png)

今は、CUDAのv10かv11のようです。
ここの指定は、V11.1ですが、私は最新（21/03/14）のv11.2を入れてしまいました。

CUDAの入れ方は基本的には、この方のHPで良いと思いました。でも、この方のHPは`tensorflow`ですので、最後で`Pytorch`を入れないといけません。
[TensorFlow (v2.2.0)でGPUを使う方法 (Windows)](https://qiita.com/marin-oz/items/317d6763045ee5bad2ed)

０．GPUドライバーを最新にする。

1.Visual Studio のインストール
たぶん、これは、途中でCUDAが動いているかどうかの確認をするために必要なのだけだと思う。この確認を省くならば、いらないと思う。私は、以前入れていたVisual studia2017を使用することにした。

２．CUDA Toolkitのインストール
私は、最新のV11.2をインストールした。結論としては、V11.1でなくてもV11.2で動いた。

３．CUDA Toolkit が正常に入ったか確認
これを省くかどうかはやる人任せですね。私はVisual studia2017が入っていたので、bandwidthTest_vs2017.slnをビルドして実行して、確認した。ここでCUDA自体が動いているのが確認できた。

４．cuDNN のダウンロードおよび解凍
まず、CUDAでGPUを動かすためには、cuDNNがいる。これをダウンロードして解凍すると、CUDAというフォルダーができます。他のHPには、これを３でできたCUDAのフォルダーの中に入れてしまうというのもあるが、このHPのように、別で置いておいた方が、何かあった時によさそうだと思ったので、`C:\tools\cuda`においた。

５．Pathを通す（10/04追記）
CUDAtoolkitのPATHで自動で入るものもありますが、このHP[TensorFlow (v2.2.0)でGPUを使う方法 (Windows)](https://qiita.com/marin-oz/items/317d6763045ee5bad2ed)で書いてあるすべてのPATHは自動で入らない。私の場合は、２つ目と３つ目は自動では入っていなかった。後、cuDnnは自分でPATHを通さないといけない。
そういうわけなので、とりあえず、この~~４つ~~５つのPATHが通るように、windowsのシステムのプロパティから環境変数の設定に入って、自分で設定します。

５つのパスはこれです。
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.2\bin
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.2\libnvvp
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.2\extras\CUPTI\lib64
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.2\include
C:\tools\cuda\bin

このHP[TensorFlow (v2.2.0)でGPUを使う方法 (Windows)](https://qiita.com/marin-oz/items/317d6763045ee5bad2ed)から一つ増えていますが、どれが必要でどれがいらないのか、よくわかっていません。

ここまでで、CUDAの設定は終了。
基本は[TensorFlow (v2.2.0)でGPUを使う方法 (Windows)](https://qiita.com/marin-oz/items/317d6763045ee5bad2ed)で良いのですが、ここからが`Pytorch`用で異なります。

６．CUDAのバージョンに合う`Pytorch`を入れる。
`Pytorch`の[公式サイト](https://pytorch.org/)で、自分のCUDAに合うPytorchのpipコマンドを作る。条件を選択すると、`Run this Command:`のところにインストールコマンドが出てきます。
私の場合は、stable版＋windows+pip+CUDA11です。

`pip install torch==1.8.0+cu111 torchvision==0.9.0+cu111 torchaudio===0.8.0 -f https://download.pytorch.org/whl/torch_stable.html`

このコマンドをコピペして、`pip`インストールする。

これでCUDAと`Pytorch`のインストールは完了です。

CUDAが有効かどうか？は

```Python

import torch
print(torch.cuda.is_available())

#True
```
こで、`True`がでれば、成功です。


### はまったポイント
・そもそもcuDNNがいるとは思っていなかった。CUDAToolkitのみで動くと思っていた（笑）
・PATHを通すのが自動で入るもの以外にもいるみたい（検証していませんが）
・CUDAに合う`Pytorch`がいることも知らなかった。

知らないということは恐ろしい。（苦笑）
スマホとPCで求められるUIの違い

# 概要
皆さん、Webアプリを作成する時レスポンシブ対応をすると思います。その時、スマホとPCに求めらるデザインは異なります。それは、画面の大きさやユーザと画面の距離、タッチ操作とマウス、トラックパッド操作の違いなどハード面で異なるためUIのベストプラクティスも異なるためです。今回は、異なるポイントとその改善案をまとめてみました。

# 異なるポイントと改善案
## スマホ
- タッチ操作のため細かい操作がしづらい  
**-> 要素を大きめにデザインする必要がある</font>**  
- ホバーをつけることができない（マウスポインタを表示できないため）  
**-> タッチ操作ができることを直感的にわかる見た目にする**
- 片手操作  
**-> 右利きが多いことから左上や上部を片手操作で押すことが難しい。ボトムタブなどの採用も考える**
- スクロール操作が可能  
**-> カルーセルデザインを採用させやすい（PCでも可能だかスクロールのできるスマホの方が適している）**
- 画面サイズが小さく省スペースする必要がある  
**-> 空白はできるだけ小さくする。カルーセルデザイン、アコーディオンメニュー、ハンバーガーメニューなどの採用も検討**

## PC
- スマホに比べて画面サイズが大きい  
**-> マルチカラムレイアウトを可能にする**  
- マウス操作のため細かい操作が可能  
**-> 要素は小さくていいが、見づらくない大きさにはする（ターゲット層が高齢な場合は文字を大きくするなどの配慮も必要）**  

# おわりに
今回は、スマホとPCのUIの異なるポイントを簡潔にまとめてみました。デザインを作る際の参考に少しでもなれば幸いです。
miniconda+conda-forgeでの開発環境をDockerでそろえる

#はじめに
Anacondaの有償化に伴い、[こちら](https://qiita.com/kimisyo/items/986802ea52974b92df27)でminiconda+conda-forgeに関する運用の記事を書いたところ、そこそこに反響があったので、今回はDockerで開発環境を揃えるところをご紹介したい。

#環境
私がWindows派であり、condaはケモインフォマティクスをやるために利用しているため、今回は以下の構成で説明する。またWebアプリの開発を想定してDjangoも用意することする。

- Windows 10
- python 3.7
- django 3系 (WEBアプリフレームワーク)
- Pytorch 1.7 cpu版 (ディープラーニングフレームワーク)
- RDKit (ケモインフォマティクスライブラリ)
- gunicorn (WEBサーバ)

#手順
## Dockerのインストール
まずは以下に従ってDockerをインストールしよう。

- https://qiita.com/zaki-lknr/items/db99909ba1eb27803456

## Dockerfileの作成

続いて以下のようにDockerfileを作成しよう。

```Docker

FROM continuumio/miniconda3

# conda create
RUN conda create -n chemodel python==3.7 

# install conda package
SHELL ["conda", "run", "-n", "chemodel", "/bin/bash", "-c"]
RUN conda install django=3.* -c conda-forge --override-channels
RUN conda install pytorch==1.7.1 torchvision==0.8.2 torchaudio==0.7.2 cpuonly -c pytorch -c conda-forge -c tboyer --override-channels 
RUN conda install -c rdkit -c conda-forge rdkit --override-channels

# install pip package
RUN pip3 install --upgrade pip
RUN pip3 install gunicorn
```

Dockerfileについて解説する

- まず、```FROM～```のところで、minocondaのベースイメージを指定する。
- 続いて、```RUN conda create -n chemodel python==3.7 ```で、作成したいPythonのバージョンでConda仮想環境を作成する。
- ```SHELL～```の行でその仮想環境をActivateする。ここが**今回の最大の肝**で、この方法を間違えると、それ以降のconda installによるインストールが、作成した仮想環境ではなく、**base環境に反映されてしまう**のだ。
- ここまでくれば、その後は、conda, pipで各自インストールしたいものを列挙すればOKだ。Anaconda有償化の影響をうけ、チャネルやオプションの指定は、[前回の記事](https://qiita.com/kimisyo/items/986802ea52974b92df27)を参考にしてほしい。
- pytorch1.7は、pytorch, conda-forgeだけからではインストールできなかったっぽかったので、tboyerというマイナーなチャネルを指定したが、危険だと思われる方は別のPyTorchのバージョンを指定してみてほしい。

## Dockerイメージのビルド
作成したDockerfileのあるフォルダで以下を実行するとビルドできるはずだ。

```sh
docker build -t kimisyo/dev:1.0 -f Dockerfile ./
```

## Dockerイメージの確認
```docker images```でイメージができたか確認してみよう。

```sh
$ docker images 
REPOSITORY                         TAG       IMAGE ID       CREATED        SIZE
kimisyo/dev                        1.0       90cbde3916c9   17 hours ago   3.33GB
```

## Dockerコンテナの起動
Djangoアプリを作成し、以下のようにDockerコンテナを起動すると、```http://locahost:8080/``` で、作成したDjangoアプリを参照できるはずだ。

```sh
$docker run -itd -p 8080:8000 --name chemodel --mount type=bind,src=<Djangoのプロジェクトがあるフォルダを絶対パスで指定>, target=/chemodel,readonly kimisyo/dev:1.0 /bin/bash -c "conda run -n chemodel;
 cd /chemodel/; /opt/conda/envs/chemodel/bin/gunicorn --bind 0.0.0.0:8000 chemodel.wsgi"
```

ちょっと分かりにくいので簡単に説明する。

- ```-p 8080:8000```は、Dockerコンテナ側の8000ポートをローカルの8080ポートで参照できるようにするための指定である。
- ```-mountオプション```では、ローカルにあるDjangoプロジェクトのフォルダを、コンテナ側で認識させるために /chemodelというフォルダにマウントしている。
- 最後の```/bin/bash -c "conda run -n chemodel;
 cd /chemodel/; /opt/conda/envs/chemodel/bin/gunicorn --bind 0.0.0.0:8000 chemodel.wsgi" ```ではコンテナ起動時に、conda仮想環境をActivateし、コンテナ内のDjangoアプリフォルダに移動し、gunicornによりDjangoアプリを起動している。

#おわりに
一度開発環境を作ってしまえば、毎回パッケージをインストールする必要もなく、本番環境もDockerで簡単にデプロイしてしまうこともできそうだ。Hava a good miniconda+conda-forge & Docker Life! 

# 参考
- [Activating a Conda environment in your Dockerfile](https://pythonspeed.com/articles/activate-conda-dockerfile/) 今回の肝となるCondaのActivte方法が記載されている。
Next.jsにTSLintを導入する手順

Next.jsにTSLintを導入する手順になります。


## TSLintをインストール

### npm

```npm
npm install --save-dev tslint tslint-config-airbnb
npm install --save-dev tslint-react-hooks　//react hookを使用する場合
```

### yarn 

```
yarn add --dev tslint tslint-config-airbnb
yarn add --dev tslint-react-hooks　//react hookを使用する場合
```
まずは、Next.jsのプロジェクトにTSLintをインストールします。

## package.jsonに追記

```package.json
 "scripts": {
    "tslint": "tslint -p . -c tslint.json"
  }
```

## tslint.jsonを追加

```tslint.json
{
  "extends": ["tslint-config-airbnb", "tslint-react-hooks"],
  "rules": {
    "import-name": false,
    "align": false,
    "react-hooks-nesting": true,
    "semicolon": false,
    "trailing-comma": false,
    "function-name": [
      true,
      {
        "function-regex": "^[a-zA-Z$][\\w\\d]+$",
        "method-regex": "^[a-z$][\\w\\d]+$",
        "private-method-regex": "^[a-z$][\\w\\d]+$",
        "protected-method-regex": "^[a-z$][\\w\\d]+$",
        "static-method-regex": "^[a-z$][\\w\\d]+$"
      }
    ],
    "variable-name": {
      "options": [
        "ban-keywords",
        "check-format",
        "allow-leading-underscore",
        "allow-pascal-case"
      ]
    }
  }
}

```
tslint.jsonを追加し、TSLintの設定を行います。

## コードを確認する

```
npm run tslint
yarn tslint
```
TSLintの設定が完了したら、上記のコマンドでコードを確認できます。

## 参考資料
https://dev.to/oahehc/how-to-config-react-project-with-next-js-typescript-tslint-and-jest-11l0
[メモ] C#のusingステートメントの使い方

# はじめに
C#初心者の私が[ドメイン駆動設計入門書](https://amzn.to/30JYUy0)を読んでいて躓いたので調べた。

# リソースの開放
C#では外部リソースとつながったあとは、usingステートメントを用いることでソースが占領しているメモリを開放しメモリリークを防いでいる。

```C#
public class UserRepository : IUserRepository
{
.
.
.
  public void Save(User user)
  {
    using (var connection = new SqlConnection(connectionString))
    using (var command = connection.CreateCommand())
    {
    .
    .
    .
    }
  }
}
```
HerokuでMySQLサーバーを使う方法(Rails)

## Heroku CLIをインストールしてから、ClearDBの導入、Heroku apps:infoまでの手順を紹介します！（学習記録）

#### Heorkuのインストールからアプリ作成:shinto_shrine:
``` 
#　heroku cliのインストール
% brew tap heroku/brew && brew install heroku 

# herokuのversionを確認
 % heroku --version 

# herokuにログインする
% heroku login --interactive

#パスワードとメールアドレスを入力してログイン

# heroku createで本番環境用のアプリを作成
cd ~/(アプリまでの相対パス)
heroku create (アプリの名前)

# アプリが正常に作られていることを確認
% git config --list | grep heroku
```

### HerokuにMySQLを導入
```
# ClearDBを導入
% heroku addons:add cleardb

# Railsに対応させる
heroku_cleardb=`heroku config:get CLEARDB_DATABASE_URL`

# データベースのURLの再設定
 heroku config:set DATABASE_URL=mysql2${heroku_cleardb:5}
```
###Heroku上で非公開の値を管理
```
# masterkeyを確認
% cd ~/(アプリまでの相対パス)
% EDITOR="code --wait" bin/rails credentials:edit

# heroku上に環境変数を設定
% heroku config:set RAILS_MASTER_KEY=`cat config/master.key`

# 正しく反映されているか確認
% heroku config
```
### Herokuにpush
```
# herokuに自分のアプリを追加
% git push heroku master

# Rubyのバージョンによっては必要なコマンド
heroku stack:set heroku-18 -a (アプリの名前)

# migrateを実行
heroku run rails db:migrate

# heroku apps:infoで確認
heroku apps:info

#最後にHerokuのMySQLサーバーをリセットするコマンド
% heroku run DISABLE_DATABASE_ENVIRONMENT_CHECK=1 rails db:drop db:create db:migrate
```
以上がHerokuでMySQLサーバーを使う流れになります。参考までにどうぞ！！
GitHub CLI のインストール (ubuntu)

# GitHub CLI のインストール (ubuntu)


## 手順


```
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key C99B11DEB97541F0
sudo apt-add-repository https://cli.github.com/packages
sudo apt update
sudo apt install -y gh
```

※ リンクに記載の手順に `sudo apt install gh` に `-y` を追加

## リンク

https://github.com/cli/cli/blob/trunk/docs/install_linux.md#debian-ubuntu-linux-apt
git init の "unknown error occurred while reading the configuration files"への対処方法

## git init でまさかのエラー

`git init`でこんなエラーが出た。


```command
(xxx) xxx$ git init
warning: unable to access '/Users/xxx/.gitconfig': Is a directory
warning: unable to access '/Users/xxx/.gitconfig': Is a directory
fatal: unknown error occurred while reading the configuration files
```

ちなみに環境は
macOS Big Sur 11.2.2
macbookPro16 M1じゃないやつ。

Anacondaでpython3.8の環境を作ってPythonアプリを作っていました。


## 対処方法

さて、エラーメッセージに従ってルートディレクトリを見ると、`.gitconfig`がある。

これを削除してみる。

```
(xxx) xxx$ rm .gitconfig
rm: .gitconfig: is a directory
```

どうやらディレクトリとして認識されている。

```
(xxx) xxx$ rm -r .gitconfig
rm: .gitconfig: is a directory
```

これで削除出来た。

対象のディレクトリに移動して、

```
(st0) xxx$ git init
Initialized empty Git repository in /Users/xxx/.git/
```

出来た！

個人的備忘録です。
感熱紙プリンター QL700 を Ubuntu で使う

感熱紙プリンター QL700 を Ubuntu で使います。

####インストールと起動（単体）

````bash
cd
git clone https://github.com/pklaus/brother_ql_web.git
cd brother_ql_web/
pip3 install -r requirements.txt

# フォントのインストール
sudo apt install -y fonts-ipa*
sudo apt install -y ttf-mikachan ttf-aoyagi* ttf-takao* ttf-kochi-gothic ttf-kochi-mincho ttf-sazanami* ttf-vlgothic
sudo apt install -y otf-yozvox-yozfont

ls -al /dev/usb/lp0 # ラベルプリンタのメンテナンスランプが点灯してないこと。していたら長押しで解除
chmod 777 /dev/usb/lp0
cp config.example.json config.json 
gedit config.json # ラベルプリンタの型番とプリンタの場所を指定
python3 brother_ql_web.py 
````

上記で起動できたらブラウザで http://localhost:8013 にアクセス

#### USBを常に権限 777 モードにする

プリンタのベンダーIDやシリアル番号は下記で調べておきます。

````bash
ls -al /dev/usb/lp0 
lsusb
dmesg 
sudo gedit /etc/udev/rules.d/49-printer.brother.rules ;
````

QL700 であれば idVendor と idProduct は一緒かと思います。serial だけ dmesg から得られる情報で適宜修正を行います。

````text:49-printer.brother.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="04f9", ATTRS{idProduct}=="2042", ATTRS{serial}=="XXXXXXXXXXXX", MODE="0777", GROUP="www-data",  SYMLINK+="/dev/usb/lp0"
````

USB ルールの再読込と起動

````bash
sudo /etc/init.d/udev stop
sudo /etc/init.d/udev start
#sudo udevadm control --reload-rules && udevadm trigger

# ラベルプリンタの USB を抜き差ししてみる
ls -al /dev/usb/lp0 
python3 brother_ql_web.py 
````

#### Webサービス化

毎回 python とコマンドを打つのが面倒なのでサービス化します。

````bash
gedit ql_web.service
#which python3
#gedit brother_ql_web.py 
````

下記 ql_web.service ファイルの USERNAME の部分を適宜修正します。

````text:ql_web.service
[Unit]
Description = ql_web

[Service]
ExecStart = /bin/bash -c '/usr/bin/python3 /home/USERNAME/brother_ql_web/brother_ql_web.py'
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target
````

保存をしたら、必要なライブラリを sudo でインストールして（ここ重要）サービスの登録と起動を行います。

````
sudo pip3 install -r requirements.txt
sudo cp ql_web.service /etc/systemd/system
sudo systemctl daemon-reload
sudo systemctl start ql_web.service
sudo systemctl status ql_web.service
sudo systemctl enable ql_web.service
````

これ何気に画像にも対応したものがあったりとおもしろいプリンターになります。

#### 参考リンク

- [GitHub - pklaus/brother_ql_web: A Python-based web service to print labels on Brother QL label printers. Based on brother_ql: ](https://github.com/pklaus/brother_ql https://github.com/pklaus/brother_ql_web)
- [GitHub - Mikhail5555/brother_ql_web_image: A Python-based web service to print labels on Brother QL label printers. Based on brother_ql_web: https://github.com/pklaus/brother_ql_web]( https://github.com/Mikhail5555/brother_ql_web_image)
Windows10でCドライブ容量が突然不足したときの対処方法

# 症状
200GB以上も容量のあるCドライブの空き領域が，10GB程度になっていた。
アプリケーションはDドライブにをインストールするようにしていたので，何かがおかしい。

# Cドライブ容量不足の対処法
* 「マイコンピュータ」で右クリック－［プロパティ］をクリック。
* 表示された「システム」ウインドウで，［システムの詳細設定］をクリック。
* 「保護設定」ボックス内で，Cドライブを選択－［構成］。
* 「ディスクの使用領域」を任意の量まで下げる。
    * 自分の場合，この量が100GBになっており，Cドライブ容量不足の原因となっていた。
    * ここは人によって変わるところだが，今回は「最大使用量」を「10%」まで下げた。
* （「このドライブのすべての復元ポイントを削除します」で［削除］をクリック。）
* ［適用］－［OK］。
* 完了。

## 結果
対処の結果，Cドライブの空き領域が 10GB → 119GB に増加した。

# まとめ
今回のドライブ容量不足の**原因は，復元ポイントの領域が大きかったこと**だ。
自分は復元ポイントを利用してシステムを復元することはほとんど全くないため，復元ポイントのディスク使用領域を最小限に抑えることで解決した。
TEENでUDP

PC-9801用のTCP/IPスタックTEENにはTLIBというライブラリがありC言語で使えるようになっています。このライブラリはTurbo Cで作られていて他の処理系ではそのままは使えません。

まずはUDPのAPIをOpen Watcom(OW)に移植してみました。

https://github.com/yamori813/ow-pc98

TLIBにはudpechoというサンプルコードが含まれています。このプログラムはECHO UDPパケットを送信して返ってきたものを受信するようになっています。ECHOプロトコルはIPが作られて初期の段階で通信回線のテストのために設計されたようです。

サーバ側はもちろんFreeBSDで用意します。ポート7番に飛んできたUDPパケットをそのまま返すだけなので、自分でプログラムを書いても40行ぐらいでできると思います。

![echo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/3555ce87-cc24-dfc8-f3f4-d0380a9fb934.png)

FreeBSDではinetdにこのサーバー機能が実装されています。/etc/inetd.confの下記の行をコメントを外してinetdを立ち上げるとサーバ機能が使えます。

```:/etc/inetd.conf
#echo    dgram   udp     wait    root    internal
```

とりあえずFreeBSDで確認するクライアントも40行くらいでできると思いますが、わざわざ書く必要もなくncコマンドでできます。

```
% nc -u 192.168.0.2 7
xyz
xyz
```

環境は用意できたのでTLIBのアセンブラを書き換えてこつこつテストしました。FreeBSD上でビルドしたバイナリをtftpでPC-9801にコピーして試しました。TEENと一緒に[TFTP.EXE](http://www.abk.nu/~kattyo/freesoft.htm#prog_tftp)をPC-9801にコピーしておきます。FreeBSDでtftpサーバを上げるのはinetd.confのtftpコメントをはずしてinetdを起動します。ビルドしたファイルを/tftpbootディレクトリにコピーしてPC-9801から拾います。ある程度動くようになったらテストにtcpdumpで確認すると便利です。

```
% sudo tcpdump -xX -i ng0 port 7
07:18:09.040629 IP 192.168.0.201.blackjack > 192.168.0.200.echo: UDP, length 3
        0x0000:  4500 001f 0069 0000 4011 f783 c0a8 00c9  E....i..@.......
        0x0010:  c0a8 00c8 0401 0007 000b b48b 6162 63    ............abc
07:18:09.040934 IP 192.168.0.200.echo > 192.168.0.201.blackjack: UDP, length 3
        0x0000:  4500 001f 2df6 0000 4011 c9f6 c0a8 00c8  E...-...@.......
        0x0010:  c0a8 00c9 0007 0401 000b b48b 6162 63    ............abc

```

一番苦労したのはsendto,recvfromのパラメータブロックを作って引き渡すところで、元々はスタックに積むようなコードになっていましたが、データにしてそこに入れて引き渡すようにしました。今のコードで動いてはいるのですが、あまり良く分かってないところがあります。

udpechoは引数でホストをしているするとudp_send,udp_recvのテストになり、引数無しだと、毎回ホストを指定してudp_sendto,udp_recvfromのテストになります。

なぜかargc,argvが壊れるのでワークアラウンドを入れてあります。原因不明です。


オリジナルのソースにはメッセージやコメントでSJISの漢字コードが使われていました。編集などが面倒なので一括UTF-8に変換してMakefileでnkfコマンドを使ってコンパイル前にSJISに変換するようにしました。SJISの漢字のメッセージはデフォルトでも通りましたが一部化けるようなのでオプションの-zk0を指定すると良いようです。

tftpやsntpのコードもあったのでビルドできるようにしました。

TCPはesenetというコードがあったので、動くようにしてみました。このコードはtelnet相当のコードで、FreeBSDでnc -l 23で動作確認をしました。

esenetでhttpbin.orgに手打ちでhttpリクエストして正常にレスポンスが返ってきました。

現代のインターネットではTLS(SSL)が必須になっていますが、16BitでコンパイルできるTLSのライブラリはwolfくらいしかなさそうで、OWでコンパイルできるか分かりません。やはり16BitだとTLSはちょっと厳しい気がします。

wccで-ecc -zp1オプションを使うとTurbo Cと同じ呼び出し規約になるので、ライブラリもそのまま使えるようです。移植する必要がなかったのですが、久しぶりにx86のアセンブラを復習できてよかったです。
JavaScriptでrange関数を書く！ ～連番と逆順～

# はじめに

前回[こんな記事](https://qiita.com/yukikaze/items/5dd76d9e04f9d75027db)を書きました。

>- 最短コードでrange(start,stop,step)を実装する。
- 出力はリスト・イテレータを問わない
- 負の値は考慮しない（start, stop, step, 出力する連番すべて0より大きいとする）

実装でかなりいろんなアイデアを出せたんですが、どれもPythonの負のステップを実現できていません。

Pythonのrange関数はかなり便利で、特にstepに-1を入れると連番リストを逆順にして返してくれるという機能があります（正確にはリストではないですが）。

前回の記事でもこの点が実装できてないことを指摘され、自分でもそれが痛いなぁと感じていました。それからというもの、ことあるごとにJavaScriptでのPython range関数の実装を考えるようになっていました。しかし今回、ついに？ワンライナーでのそれっぽい実装を思いついたので、記しておきます。

# 本題

まずコードから。

```javascript

var f=(a,b,c)=>(b-=a+1)&&(([d,e])=>[...Array((b-b%c)/e+1)].map((_,i)=>d+i*c))(c>0?[a,c]:[b+a-b%c,-c])
```

ワンライナーを意識して書きたかったのですが、かなり長くなりました。101文字で、減算代入を使っているので関数の形でしか使えません。前回の最短、ジェネレータ記法が45字だったことを考えると、随分長いですね。

ロジックを読みやすいように、書き下してみます。

```javascript
function range(start, stop, step) {
  stop -= start + 1;

  const inner = ([startValue, positiveStep]) => {
    const length = (stop - (stop % step)) / positiveStep + 1;
    return [...Array(length)].map((_, i) => startValue + i * step);
  };

  if (step > 0) {
    return inner([start, step]);
  } else {
    return inner([stop + start - (stop % step), -step]);
  }
}
```

# 結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258414/24985f6e-054e-8a8a-9e81-0e761b814aea.png)

あまり本腰を入れてテストしたわけではないですが、どうやら動いてそうですね。

# 解説

inner関数が機能の中心です。等差数列の式`初項 + 公差 * index`をここで計算しています。

しかし難しいのはそれ以外の場所で、

- 末項がstopよりも手前のときの、末項の値
- stepが負の時の、配列の長さ
- stepが負の時の、初項の値

などに場合分けや剰余算を使って対処しています。

ショートハンド版ですが、減算代入の組み込みに苦労し、文字数をかなり使っています。その上実は、`stop == start + 1`のときだけ`false`が返るというバグもそこで組み込んでしまっています。ｗ　全体的にテクニックを盛り込めず、長くて率直な書き方になってしまったのでそこが要改善ですね。

しかし今回は、range関数の複雑な処理をそれっぽく実装するというのが趣旨だったので、短縮アイデアには前回ほど凝っていません。

短縮アイデア、別の実装、バグなどなど、思いついたらぜひ教えてください。
以上です。
Redux学び_2

今回は前回の続きからです。
前回はReducerのところまでいきました。

https://qiita.com/ttttkkkkccccc/items/b3e6330f91cc27dbe3d4




##Store
⇨stateを保存するところ

今日のやること
・StoreとReducerを関連づける
・Redux（Store）とReactを接続

**Storeのimport**

１、reduxのモジュール
２、Reducerのimport

```jsx
import {
  createStore as reduxCreateStore,
  combineReducers
} from "redux";

import {UsersReducer} from "../users/reducers";
```


**createStore関数の定義**

１、reduxのcreateStoreメソッドをreturn
２、combineReducersでstateを生成


```jsx
export default function createStore() {
  return reduxCreateStore(　//reduxのcreateStoreメソッドを別名
    combineReducers({
      users: UsersReducer
    })
  )
}
```


**combineReducers()とは？**


１、分割したReducersをまとめる。
２、stateのカテゴリ毎
３、オブジェクトをreturnする。

initialStateの初期状態が入ってくるのかな？

▪️例

```jsx
combineReducers({
			product: ProductsReducer
      users: UsersReducer
    })

⬇︎ 

{
	product: {
			.
			.
			.
	}
}

{
  users: {
    isSignedIn: false,
    uid: "",
    username: ""
  }
}

```

**StoreとReactアプリの接続**

src/index.js

```jsx
import {Provider} from 'react-redux';
import createStore from './reducks/store/store';

export const store = createStore(); //ここでstoreが初めて作られる。

<Provider store={store}>
   <App />
</Provider>,

```

react-reduxのProviderとは？

１、propsにstoreを渡す。
 　⇨上記のようにラップしたコンポーネントにstoreの情報を渡す。
2、Reactコンポート内でreact-reduxのconnect関数を使えるようにする。
　⇨ReactとReduxを接続してstoreを変更できるように

簡単に接続確認

```jsx

export const SIGN_IN = 'SIGN_IN';
export const signInActions = (useState) => {
  return {
    type: "SIGN_IN",
    payload: {
      inSignedIn: true,
      uid: useState.uid,
      username: useState.username
    }
  }
}
```

初期状態は、console.logで確認したところ、以下のように。

```jsx
Object
isSignedIn: false
uid: ""
username: ""
__proto__: Object
```

```jsx
const dispatch = useDispatch();　//storeのstateの変更する
const selector = useSelector((state)=> state);　//storeのstateがselectorに入っている状態

console.log(selector.users);

例
<button onClick={ () => dispatch(signInActions({uid:'00000',username: 'kodama'})) }>
    SIGN_IN
</button>

```

SIGN_INがクリックされた時に以下のようにstateが変更。

```jsx
{isSignedIn: false, uid: "00000", username: "kodama", inSignedIn: true}
inSignedIn: true
isSignedIn: false
uid: "00000"
username: "kodama"
__proto__: Object
```


今回は簡単な接続までやりました。
大体Reduxの流れがわかってきたのでいい感じです。

以上、ありがとうございました。
OpenCV SVM predict score取得

##はじめに
OpenCV SVMで入力顔写真からトランプかプーチンかを判別するプログラムを以前作りました（[詳細はこちら](https://qiita.com/herr-shigeo/items/d459ada6dbf85112a11f)）。その際、誤認識するケースがありましたので、predict scoreによる判定処理、及びトレーニング画像を追加して改良を試みましたので、その時の備忘です。

##開発環境
Ubuntu 18.04.4 LTS
Python 3.6.9
opencv 4.5.1

##改良点
既存のコードに以下２点の改良を加えました。

* トレーニング画像追加
横顔のトランプの顔写真をプーチンと認識していたので、横顔の写真を集めてトレーニングデータに追加しました。
また、若い頃のプーチン顔写真をトランプと認識していたので、若き日のプーチン画像もトレーニングデータに追加しました。

* predict scoreを利用
predict scoreが低い場合は、判定不能とするようにプログラムを修正しました。

##ソースコードの変更点

```python
--- a/sift_svm.py
+++ b/sift_svm.py
@@ -13,8 +13,9 @@ from matplotlib import pyplot as plt
 logger = logging.getLogger()
 
 BOW_NUM_TRAINING_SAMPLES_PER_CLASS = 30
-SVM_NUM_TRAINING_SAMPLES_PER_CLASS = 100
+SVM_NUM_TRAINING_SAMPLES_PER_CLASS = 220
 BOW_NUM_CLUSTERS = 40
+SVM_SCORE_THRESHOLD = 0.15
 
 class MyBoW:
        def __init__(self, dextractor, dmatcher, cluster_count):
@@ -68,7 +69,11 @@ class MySVM:
                self._svm = new_svm
 
        def predict(self, descriptros):
-               return self._svm.predict(descriptros)
+               raw_prediction = self._svm.predict(descriptros, flags=cv2.ml.STAT_MODEL_RAW_OUTPUT)
+               logger.debug(raw_prediction)
+               score = raw_prediction[1][0][0]
+               label = -1 if score >= SVM_SCORE_THRESHOLD else 1 if score <= (SVM_SCORE_THRESHOLD * -1) else 0
+               return label            
 
 class MyMatcher:
        def createFlann():
```

下記の１行は可読性が悪いですが

```python
label = -1 if score >= SVM_SCORE_THRESHOLD else 1 if score <= (SVM_SCORE_THRESHOLD * -1) else 0
```

スコアの絶対値がSVM_SCORE_THRESHOLD（この場合は0.15）未満であれば、判定不能としてlabelに0を設定する。
SVM_SCORE_THRESHOLD以上であれば、labelに判定結果(この場合は、1 or -1)を設定しています。

##結果
誤認識していた若きプーチンの写真はトレーニングデータ追加の結果、正しく認識するようになりました。スコア値は0.24258254でした。
もう一方の誤認識画像であるトランプの横顔は依然として、プーチンに分類はされたのですが、スコア値が0.14894724となり、ぎりぎりSVM_SCORE_THRESHOLD未満となったため、誤認識では無く判定不能となりました。

##まとめ
トレーニング画像を少し追加しただけで予想以上の効果が得られ、トレーニングデータは重要であると再認識しました。
attr_readerメソッド

---
attr_readerメソッド
---
インスタンス変数を呼び出すメソッドを定義するメソッド

```ruby
class #クラス名
  attr_reader :name

  def initialize(name)
    @name = name
  end
end
```

attr_readerを使用しない場合

```ruby
class #クラス名
  def initialize(name)
    @name = name
  end
#この部分の記述をattr_reader :nameに省略できる
  def name
    @name
  end
```

記述を省略できる
pythonを使った機械学習でよく出てくる画像読み込み/描画処理

# 画像の読み込み
以下のようにディレクトリ内の画像ファイルパスを配列で読み込んでおいて使うことが多い。

```python
# globで対象ファイルパスを読み込み、sortedで並び替えている
train_images_path_list = sorted(glob('./input/train_images/*.jpg'))
```

画像の読み込みにはだいたいPillowかOpenCVが使われる。
読み込み後はPillowは独自形式、OpenCVはnumpy.ndarray型になる。
numpyによってPillowの独自形式の型もnumpy.ndarray型に変換可能。

```python
import cv2

image = cv2.imread(train_images_path_list[0])
print(type(image))
# => numpy.ndarray

from PIL import Image
import numpy as np

image = Image.open(train_images_path_list[0])
print(type(image))
# => （jpeg形式のファイルの場合）PIL.JpegImagePlugin.JpegImageFile
print(type(np.array(image)))
# => numpy.ndarray
```

# 画像の表示
画像の描画はだいたいmatplotlib.pyplotが使われる。
Pillow独自形式もnumpy.ndarray型もどちらもimshowで描画できる。ただし、色の取り扱いが異なるので注意が必要。

## Pillowを使う場合
```python
import matplotlib.pyplot as plt
from PIL import Image

image = Image.open(train_images_path_list[0])

plt.imshow(image)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77606/c03c07b4-9018-321c-e448-800498f145d0.png)

## OpenCVを使う場合
OpenCVは色の取り扱いに注意が必要。
numpy.ndarray型は1階層目：幅、2階層目：高さ、3階層目：色として値が格納されている。
注意すべきは3階層目の色でOpenCVはBGR、PillowはRGBの順で値を格納しており、
matplotlib.pyplotはRGBとして色を認識するので、OpenCVで読み込んだ場合は色の変換が必要になる。

```python
import matplotlib.pyplot as plt
import cv2

image = cv2.imread(train_images_path_list[0])
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

plt.imshow(image)
```

## 複数枚表示
複数枚表示したい場合は以下のようにsubplotsメソッドでaxesを生成し、各axesのimshowにnumpy.ndarray（もしくはpillow独自型）を渡す。

```python
from PIL import Image
import matplotlib.pyplot as plt

# 3*3 =9枚の画像を描画したい場合
ROWS = 3
COLS = 3
fig, axes = plt.subplots(nrows=ROWS, ncols=COLS, figsize=(15, 10))
for row in range(ROWS):
  for col in range(COLS):
    file = train_images_path_list[(row * COLS) + col]
    image = Image.open(file)
    axes[row][col].imshow(image)
    axes[row][col].set_title(file)

plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77606/330a488e-64b1-9cb1-9830-d8bd96c50643.png)
いくつ知ってる？_（アンダースコア）と__（ダンダー）の使い方【Python】

最近Pythonトリックを読み学びがあったのでメモまで。

# 概要
1. ```_```と```__```の読み方知ってます？
2. Pythonで出てくる```_```と```__```の組み合わせ
3. 各組み合わせの意味合い
4. 感想


# 1. ```_```と```__```の読み方知ってます？
Pythonトリックおすすめです。

- ```_```：アンダースコア
- ```__```：ダンダー

と読むらしいです。自分は知らずにアンダーアンダースコアと読んでました（恥ずかしい


# 2. Pythonで出てくる```_```と```__```の組み合わせ

Pythonで```_```と```__```の組み合わせで主に使われているのは以下の５つ。

- 変数の先頭の```_```
- 変数の末尾の```_```
- 変数の先頭の```__```
- 変数の先頭と末尾の```__```
- 単一の```_```

# 3. 各組み合わせの意味合い
組み合わせの意味合いは下記の通り。
## 変数の先頭の```_```
これはよく見ます。変数がプライベートであることを示しています。これはPythonのお約束の１つであり、外部からは普通にアクセスできます。

```python:アンダースコアの挙動
class TestUnder():
    def __init__(self,a):
        self._a = a
test = TestUnder(1)
test._a = 2
# _aは書き換わる
```

## 変数の末尾の```_```
定義する変数の末尾にアンダースコアを追加することで名前の衝突をさけることがあります。これもPythonのお約束の１つです。

## 変数の先頭の```__```
これも変数がプライベートであることを示しています。
ただし```_```の場合と違い、プログラム上にも変化を及ぼします。

実はこれは完全なプライベート変数ではなく、
Python側が変数名を変更することで擬似的に作ったプライベート変数です。

```python:アンダースコアとダンダーの違い
class TestUnder():
    def __init__(self,a):
        self._a = a
test = TestUnder(1)
test._a = 2
# _aは書き換わる

class TestDunder():
    def __init__(self,a):
        self.__a = a
test = TestDunder(1)

# Attribute Errorが発生
# print(test.__a)

# 例外は発生せず一見、__aが書き換わるように見えるが、 __init__で設定した変数とは異なる
# test.__a = 2

# 実はこれでアクセスできてしまう
print(test._TestDunder__a)
```

## 変数の先頭と末尾の```__```
よく見る```__init__```とかの特殊メソッドで使用されます。特別な理由なければ使わないほうがいいでしょう。

## 単一の```_```
変数が一時的なものや使用しないものを示すために使用されます。

```python:単一のアンダースコア
test = ('Necessary','Unnecessary')
a,_ = test
```
# 感想
それぞれ知ってはいましたが、まとめたことはなかったので勉強になりました。
余談ですが、Pythonトリックいいよ。effective Pythonで挫折した自分でも読めました。
Python トリック（https://www.amazon.co.jp/dp/B085455WKV/）
vagrant up 時にdefault: SSH auth method: private keyでログが停止する

windows 10 にて vagrant up 実行時に default: SSH auth method: private key でログが停止してしまう。
どうやら、docker for windows インストール時に設定される Hyper-V が原因のよう。
これをoffにするとVirtualBoxは使えるようになるがdockerは使えなくなる。
windows 10 ではdockerとVirtualBoxは競合するらしいのでHyper-VをいちいちON/OFFする必要がありそう。

###有効化の方法
```bcdedit /set hypervisorlaunchtype auto```
これを実行し再起動

###無効化の方法
```bcdedit /set hypervisorlaunchtype off```
これを実行し再起動
JavaFXのDialogで入力値チェック制御

# この記事について

将来的に書く予定の「JavaFX で DynamoDB Viewer作ってみた」記事の１ステップ。
結構大きな話になると思うので、少しずつ技術ポイント毎に記事を書いて、ある一定程度の要件を満たせた段階で前述まとめ記事書く予定。

第一回記事：[DynamoDBの情報を読み込んでJavaFXで表示してみる](https://qiita.com/silverbox/items/eba824a9f003df67181e)
第二回記事：[JavaFXで動的にテーブル列を設定する](https://qiita.com/silverbox/items/904a01d561014d800696)
第三回記事：[AWS java SDKでDynamoDBテーブル情報を取得してみる](https://qiita.com/silverbox/items/3caefb782f1bb269490f)
第四回記事：[JavaFX の TableView の選択範囲をクリップボードにコピーする。](https://qiita.com/silverbox/items/19e131bd3da02940a8c1)
第五回記事：[JavaFX でコンポーネント作って動的生成してみる](https://qiita.com/silverbox/items/3128fd2128374e11c1f7)
第六回記事：[DynamoDBのデータ型をjava SDKから把握してみる。](https://qiita.com/silverbox/items/3a434ec4a85262f973c9)
第七回記事：[JavaFXでジェネリック使って入力ダイアログ作成してみる](https://qiita.com/silverbox/items/bb3cee5a328ccc63246c)
第八回記事：[JavaFXで各種サイズ制御](https://qiita.com/silverbox/items/17b7982683be06c32240)

※これまでの記事が基本になってます。メソッドなど細かい部分で再説明していない部分があります。不明点などありましたらコメントなど頂けたら対応しようと思います。


# 今回の追加機能

各種属性追加、値の編集が出来る様に
要素数が多い時、ウィドウサイズが大きすぎない様に
Map型ダイアログの要素順を要素の型でソートする様に
要素に下線を引き、要素の情報を見やすい様に
ダイアログのタイトルに、どの情報かを表示する様に

# 現在の進捗

基本ダイアログ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530376/33acb127-2629-b260-848f-322f0b4a1f31.png)

子ダイアログ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530376/e88b0788-95c8-9533-4112-ec01f4a65d42.png)

[この時点でのソース(github)](https://github.com/silverbox/dynamodbtool/tree/10th-addattribute2)

# 技術ポイント

## 入力ダイアログのValidation

ダイアログでOKボタンが押された時、値の最終チェックをし、駄目だったら警告アラート出してダイアログを閉じずに入力継続したい。
Dialog#setOnCloseRequest で、チェック関数を指定。そのチェック関数の中で、チェックが駄目だったら dialogEvent.consume()を実行する事で実現可能。
ただ、取り消しボタンでもチェックが走ってしまう。今の時点では対応方法が見つからず、一旦そのまま。

```java:Dialog継承クラス

	// コンストラクタ辺りでセットする
	this.setOnCloseRequest(this::doFinalValidation);

	// チェック関数
	private void doFinalValidation(DialogEvent dialogEvent) {
		if (!isFinalValidationOk()) {
			dialogEvent.consume();
		}
	}
```

## ダイアログの最大＆最小サイズ指定

画面のサイズを最大値に。最小値は幅300、高さ200

```java
		Rectangle2D screenSize2d = Screen.getPrimary().getVisualBounds();
		double screenHeight = screenSize2d.getHeight();
		double screenWidth = screenSize2d.getWidth();

		final Window window = this.getDialogPane().getScene().getWindow();
		Stage stage = (Stage) window;
		stage.setMinHeight(200);
		stage.setMinWidth(300);
		stage.setMaxHeight(screenHeight);
		stage.setMaxWidth(screenWidth);
```


# その他のポイント

- コンストラクタ時点では、インスタンス宣言部でNodeを生成しても参照できない。
- 当たり前だが、継承元と継承先で関数記述の順番をそろえておくと後々確認する時に楽。

# 次回予定

検索部分の強化（PartiQLとか）

# 残課題

- 取り消しボタンでもチェックが走ってしまう
- 新要素を追加した時、テーブルに列が追加されない

# 参考にさせて頂いたページ

[JavaFX Dialogs: How to set min-size and prevent closing?](https://lestard.eu/2018/dialogs_minsize_closing/)

[[Dialog] add method to suppress closing of dialogs](https://bugs.openjdk.java.net/browse/JDK-8130377)
Elixir側で実装したHTMLを描画する例

```shared_view.ex

  def url(:twitter) do
    "<a href=\"https://twitter.com/ruby_zuki\">Twitter</a>"
  end
```

`helper`に記載された`url(:twitter)`を`html.eex`で下記のように呼び出す。

```eex
<%= raw url(:twitter) %>
```
Caching.ClearCacheでキャッシュの削除に失敗してfalseが返ってくる


事象
・Caching.ClearCacheでキャッシュの削除に失敗してfalseが返ってくる
・アセットバンドルのダウンロード後すべて失敗

再現方法

1. アセットバンドルダウンロード
2. Caching.ClearCache()実行
3. アセットバンドルダウンロード
4. Caching.ClearCache()実行(失敗!!!!)


ClearCacheする直前に AssetBundle.UnloadAllAssetBundles(false); を呼んであげると解決
[AmongUs]記憶力が悪くても勝つ方法

##前置き

※初めての記事です。


2020年9月から一気に人気になったAmongUs

日本でもかなりの人がプレイしていますね

始めたばかりの初心者から上級者の方まで
プレイ中に多くの人が悩むことと言えば
タスクをこなしているている時に、自分が通った経路や、一緒に行動した色や、すれ違った色を覚えられないことですよね

zabuは暗記が不得意なので、覚えることを諦めました。

暗記が不得意な方に良い方法を提案します。


この記事の最後におすすめの日本人AmongUsのDiscordサーバーの招待URLがあるのでぜひ最後までお読みください！！

##方法

自分の行動や身の回りで起きたことを声に出して実況し、
[Googleドキュメント](https://docs.google.com/document)の音声入力を文字起こしをすると正確な情報を話すことができます。


##詳しいやり方

[Googleドキュメント](https://docs.google.com/document)を開き↓
![スクリーンショット 2021-03-14 020109.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203052/dc943479-2943-f7e6-d0b3-81ae946a80ec.png)
新しいドキュメントを作成の空白を押します。
メニューバーにある「ツール」を押し「音声入力」を押します↓![スクリーンショット 2021-03-14 020308.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203052/47caa48a-d0dd-608d-595a-37d26eee72dd.png)

押すと画面上にこのようなものが出てきます↓
![スクリーンショット 2021-03-14 015907.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203052/604b1365-161d-9ec3-7271-90d9aa8328dd.png)
クリックをするとマイクマークが赤くなるのでそしたら実況を始めましょう!!

#使用例
これはあくまでも、私の使い方なので皆さんの使いやすいように使うと良いです！

私の場合は、ゲーム開始と同時にDiscordのVCのマイクがOFFになってることを必ず確認してからGoogleドキュメントのマイクをONにして実況開始です。
初手どっちへ向かったか、何色も同じ方向に行っているか、何色がどこではぐれたか、何の緊急タスクが起こったか、自分がどこの部屋に入ったか
これらを言ってメモっておけば大丈夫です。

私が使用するとこうなりました↓
![スクリーンショット 2021-03-14 025213.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203052/3d0b1d76-a33c-f3d2-26ec-dd143500d96d.png)


##注意事項
VCを繋げっぱなしでの実況には注意してください。

あとは、クルーの時にこの方法を使うと正確な情報をポンポン言えるのでとても良いのですが、インポスターになったときに急にちゃんとした情報が言えなくなり怪しさ抜群になってしまうので、この方法を使用してメモっていることは周りに言わないほうが良いです。自分だけの技ということでこっそり使いましょう！

##最後にAmongUsを楽しめるDiscordサーバーの紹介！

AmongUsを楽しむならやっぱりVC(ボイスチャット)があったほうが確実に楽しいですよね！
おすすめの日本人AmongUsサーバーはこちら！
現時点(2021/03/14)で21,814人が参加しているかなり大規模サーバーです！
24HボイスチャットでAmongUsを楽しめます！
参加はこちらから↓
https://note.com/hokutora_/n/nd4ca4ff248d8



最後まで読んでいただきありがとうございました。
初めての記事なので誤字脱字があったり日本語が間違えていたりするかもしれません。
見つけ次第コメント欄で教えていただけると幸いです。
Kotlinで標準入力

Kotlinで競技プログラミングをやりたいと思ったので覚書に
文法等は別の記事に丁寧にまとめられているのでそちらを参照下さい
[はじめよう、Kotlin（基本編）](https://qiita.com/SYABU555/items/7cc5909c119ec9ab0288)

指摘等コメントで頂けると幸いです



# 入力
### 一行に一つ
`readLine()`を利用します

```kotlin
val s = readLine() //String
val n = readLine()!!.toInt() // Int
```

`readLine()`は入力を文字列として返す関数なので、数値として扱う場合は別途キャストを入れてください(double等も同様)

ちなみに`Integer.parseInt()`でキャストする方法もあります。若干こちらが早いです
大量の数値の入力を受け取る場合はこちらを使うのもよいかもしれません

↓"0"を数値にキャストしたときの処理速度の違い(`measureNanoTime`関数で測定)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661075/0a158575-d59c-d3db-99e2-20c278c344c8.png)

### 一行に複数
`a b c`のように空白区切りになっている入力です
`split()`を利用します

```kotlin
val s = readLine()!!.split(" ") // List<String>
val n = readLine()!!.split(" ").map(String::parseInt) // List<Int>
```

`split()`はPython等と違い空白文字でも引数が必要な点に留意してください
各値のキャストは`map()`に`parseInt`を渡すことで簡潔に行えます

このままでは不便なので各値を変数にばらしますが、ここでKotlinの便利な機能が利用できます

```kotlin
val (s1, s2, s3) = readLine()!!.split(" ") // String
val (n1, n2, n3) = readLine()!!.split(" ").map(String::parseInt) // Int
```

変数名を括弧で囲んで複数指定することで、配列の各値が順番に代入されます

### 複数行に一つ
```
a
b
c
```
のように改行区切りで入力されるパターンです
List生成時にブロックをくっつけることで値の代入が同時に行えます

```kotlin
val s = List(n) { readLine() } // List<String>

val num = List(n) { readLine()!!.toInt() } // List<Int>
```

もちろん上記で紹介した複数変数への代入も可能です

```kotlin
val (s1, s2, s3) = List(n) { readLine() } // String
val (n1, n2, n3) = List(n) { readLine()!!.toInt() } // Int
```

### 複数行に複数
```
a b c
d e f
g h i
```
みたいなのです
多次元配列に格納する形とします

```kotlin
val s = List(n) { // List<List<String>>
  readLine()!!.split(" ")
}

val num = List(n) { // List<List<Int>>
  readLine()!!.split(" ").map(String::parseInt)
}
折れ線グラフ

# matplotlib
```python
import numpy as np
import matplotlib.pyplot as plt

# 折れ線グラフ
x = np.array([0,1,2,3,4,5,6,7,8,9])
y = np.array([2,3,4,3,5,4,6,7,4,8])

plt.plot(x,y, color ="black")
plt.title("lineplot")
plt.xlabel("x")
plt.ylabel("y")
plt.savefig("折れ線グラフ") # 保存
plt.show()
```
![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/8235947d-f729-9107-b02d-723ca45ab66a.png)

# seaborn+matplotlib
```python
import seaborn as sns
sns.set() # グラフのデザインが変わる
plt.plot(x,y, color ="black")
plt.title("lineplot seaborn")
plt.xlabel("x")
plt.ylabel("y")
plt.show()
```
![download-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/a6f6eb0a-bea2-4e12-37da-8925771dcae4.png)

# seaborn
```python
sns.lineplot(x, y)
plt.show()
```
![download-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/162b66ce-433a-792e-86a5-5832d3107c64.png)

# おまけ：plotを使って放物線を書く
plotを使って折れ線だけでなく、曲線も書ける。

$ y = 2x^2+1 $ の放物線を描画  
$x$には指定した区間で連続する数列(np.linspaceで作る）
$y$には二次関数数の式

```python
import matplotlib.pyplot as plt

plt.figure(figsize=(6,4))
x = np.linspace(-2,2)
y = 2*x**2+1 # この二次関数に乗せる
plt.plot(x, y)
```
![download-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698282/e759c20a-8314-3317-deb3-99bea78ae37d.png)
Fire Storageを監視してサイレントプッシュ通知を送信

# 概要
Fire Storageに画像ファイルのアップロードがなされるとCloud Functionsを通してサイレントプッシュ通知を送信します。

今更感はありますが、ググってもpayloadの記述に統一性がなかったりして割と苦戦しました:sweat:

Stack OverFlowの方でも同じ悩みを抱えていた人がいたので参考になれば幸いです。

なお、本記事ではFirebase CLIや証明書周りについては触れません。
下準備ができている前提で進めます。

# 環境
- Xcode 12.4
- Swift 5
- nodejs 12

# Fire Storage
デフォルトバケットを使用

# クライアント
## Capability
TARGETS > CapabilitiesよりBackground ModesとPush Notificationsを有効にします。
Background ModesはRemote notificationsにチェックを入れます。
(バックグラウンドで通知を受け取りたい場合はBackground fetchもチェック)

## Swift
今回はTopic購読で実装します。

```AppDelegate.swift

import Firebase

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        FirebaseApp.configure()

        // 1. 通知許可
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: { (granted, error) in
                // todo
            })
        application.registerForRemoteNotifications()
        return true
    }

    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // 2. Topic購読
        Messaging.messaging().subscribe(toTopic: "hoge") { _ in
            // todo
        }
    }
    
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // 3. 画像ファイルの名称を取り出す
        guard let imageName = userInfo["imageName"] as? String else {
            return
        }
        print("image name: \(imageName)")
    }
}

```
# Cloud Functions

onFinalize関数でバケットに画像がアップロードされたことを検知します。

```index.js
'use strict';

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

exports.sendSilentNotificationWithTopic = functions.storage.object().onFinalize((object) => {
  const topic = 'hoge';
  const payload = {
    data: {
      imageName: object.name, // 画像名をセット
    },
  };
  const options = {
    contentAvailable: true // サイレントプッシュはtrueにする
  };
  return admin.messaging().sendToTopic(topic, payload, options)
    .then(function(response) {
      return console.log("Successfully sent message:", response);
    })
    .catch(function(error) {
      return console.log("Error sending message:", error);
    });  
});
```

firebase deployを実行してデプロイします。

# 実行
1. Xcodeに実機をつないでRun
2. Fire Storageに画像ファイルを追加

Xcodeのコンソールログに画像名が表示されれば成功です。
自分はこれで成功したのですが、失敗したらすいません。。。
【AWS】Lambdaの初回起動を早くする方法 

# はじめに
個人請負でとあるサイトをサーバーレスで構築しています。
よくあるAmazon API Gatewayでリクエストを受けてAWS Lambdaで処理を行って結果を返却する簡単な構造なのですが・・・Lambdaからのリクエストが初回だけとにかく遅い！
原因は関数実行前の準備に時間がかかるからです。
Lambdaというサービスの内部では、初回実行時に実行する関数のパッケージのロードや展開、ランタイムの起動など色々な**「実行前準備」**をやってくれています。
しかし、一定時間関数が呼び出されないと**「実行前準備」**がアンロードされてしまうのです。そのため実行頻度の低いLambdaの場合は毎回遅い初回実行になってしまいます。

今回は色々と試してみてなんとか解決した方法を載せておきます。

#前提
この方法が有効なケースは以下の場合です。

+ Lambdaの実行頻度が低い。※30分に1度程度しか実行されないなど

デプロイパッケージのサイズをランタイムに必要な最小限のサイズにしていることやJavaよりPythonを選択している等も速度に影響してきますが今回は実行頻度が低い場合のみを対象としています。

# 解決した方法
なんと**「Lambdaを定期的に実行する」**だけです。
邪道のような気もしますがこれが一番効果がありました。
一定時間関数が呼び出されないと**「実行前準備」**がアンロードされてしまうのでアンロードされる前に再度実行だけしておく。そりゃ効果ありますよね。

今回は**5分毎**に実行するようにLambdaのトリガーを追加しました。
始めは1分毎で設定してみたのですが5分でも大丈夫そうなので5分毎に変更しています。
AWS Lambdaは関数に対するリクエストの数とコードの実行時間に基づいて課金されるので「コストあがっちゃうよ！」ってお考えの方もいらっしゃるかもしれませんが安心してください。1日288回プラスになるだけです。誤差です。

では早速設定してみます。

関数を選択した状態で**「トリガーを追加」**をクリックします。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/0f8891ef-96b8-b9e1-ea6b-157a7254a01e.png)

トリガーの種類を選択できるので、**「EventBridge(CloudWatch Events)」**を選択します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/0ea41ea0-ad06-cfb9-cd27-9924fe367621.png)

**「新規ルールの作成」**を選択し、ルール名を入力します。
今回は「scheduled-execution」としました。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/ac101853-2cf8-54cd-7c0c-3b063857fa19.png)

次にルールタイプを選択します。**「スケジュール式」**を選択します。
スケジュール式に**「rate(5 minutes)」**と入力します。
※5分毎に実行しますよの設定です。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1203022/1f514beb-cf0e-a8e3-1134-afb200c3a28c.png)

あとは追加ボタンを押下すれば完了です。
定期実行されてもエラーにならないよう関数側を必要に応じて修正してください。パラメータなしで実行されるのでそれを判定に使っても良いかと思います。

これできっと何かが数秒早くなって世界のどこかで誰かが喜びます。
Ublox ZED-F9PをRaspberry Piで使う【シリアル接続編】

#はじめに

ZED-F9PにDocomoのRTK補正信号を送信し
UDPで補正されたNMEA情報を送信するユニットを作成したので
作り方をメモ

ZED-F9Pの設定とかは出来る前提で話を書いています。
リクエストああればその辺の話も書くかも・・・

#ハード構成
下図のとおりです。
今回はZED-F9PとRaspberryPi4との接続の部分を記載します。
![raspi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286585/47f96cf6-1359-3beb-8196-e3229da97235.png)



#必要な設定
プログラムの構成をNMEAパケット側とRTCM3パケット側で分けたかったので
この事例ではUARTを2本使用します。
そのために下記の操作が必要となります。


***1.40pinのGPIOのUART端子を有効化***
***2.シリアルコンソールの無効化***
***3.GPIOのUARTをPL011に変更***
***4.UARTの追加***

#1.40pinのGPIOのUART端子を有効化
GUIで「RaspberryPiの設定」->「インターフェース」で下記のように設定
![2021-03-14-004538_1920x1080_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286585/48ac3c60-3e39-8be7-ffa5-d9e38d3cdfcb.png)


#2.シリアルコンソールの無効化
上図参照

#3.GPIOのUARTをPL011に変更
標準のままですとGPIOに接続されているUARTがminiUARTなのでPL011に変更します。
miniUARTでも動きましたが機能制限があるようなので変更しておきます
詳しくは下記をお読みください。
https://www.raspberrypi.org/documentation/hardware/raspberrypi/bcm2835/BCM2835-ARM-Peripherals.pdf

使用したいUART0をBluetoothのモデムが使用しているので　
「/boot/config.txt」に下記を追加してBluetoothを無効化します。

```
dtoverlay=disable-bt
```

　miniUARTにBluetoothを割り当てることも出来るようですが
　ボーレートが低下したり不具合もありそうなので無効化しておきます。


　次にモデムを初期化するシステムサービスを下記コマンドで無効化して
　モデムを接続しないようにします。

```
$　sudo systemctl disable hciuart
```

一度再起動します・・・

「/dev」の中を確認して

```
serial0 -> ttyAMA0
serial1 -> ttyS0
```

になっていれば完了です。

#4.UARTの追加
普通に考えればUART2を追加すると思うのですがUART2のTX端子が遠いので
UART0のRX「GPIO15」に近いUART3を有効化させます

「/boot/config.txt」に下記を追加します。

```
dtoverlay=uart3
```

「/dev」の中を確認して「ttyAMA1」が追加されていれば成功です。

#次回
シリアルでNMEAのパケットを受信してUDPで送信したいと思います。

# おまけ
追加可能なシリアルは4個のUART2，UART3，UART4，UART5で下記で設定可能です。
「*」は有効にしたいUARTの数字です

設定

```
・フロー制御無し
dtoverlay=uart*

・フロー制御有り
dtoverlay=uart*,ctsrts
```

ピン割り当ては下記のようです

```
UART2 Tx(GPIO0) Rx(GPIO1) CTS(GPIO2) RTS(GPIO3)
UART3 Tx(GPIO4) Rx(GPIO5) CTS(GPIO6) RTS(GPIO7)
UART4 Tx(GPIO8) Rx(GPIO9) CTS(GPIO10) RTS(GPIO11)
UART5 Tx(GPIO12) Rx(GPIO13) CTS(GPIO14) RTS(GPIO15)
```
メモ化について

#この記事を書く動機
フィボナッチ数列の高速化で何がありますかと言われて答えられなかったから
調べたものを共有してほしいと思い書きました。

#メモ化とは
>メモ化（英: Memoization）とは、プログラムの高速化のための最適化技法の一種であり、サブルーチン呼び出しの結果を後で再利用するために保持し、そのサブルーチン（関数）の呼び出し毎の再計算を防ぐ手法である。メモ化は構文解析などでも使われる（必ずしも高速化のためだけとは限らない）。キャッシュはより広範な用語であり、メモ化はキャッシュの限定的な形態を指す用語である。(Wikipedia)


###フィボナッチ数列の原文
```python
def fib(n):
    if n==0:
        return 0
    elif n==1:
        return 1
    else:
        return fib(n-1)+fib(n-2)

```
nが大きくなるほど再起関数呼び出しが深くなり計算時間増加
でもよく考えると

___f(4)___=___f(3)___+___f(2)___
___f(3)___=___f(2)___+___f(1)___
___f(2)___=___f(1)___+___f(0)___

何回___f(2)___計算するん。。。

キャッシュしちゃおう！！

一回計算して出た結果は配列に保存しておいて、関数から値を計算するのではなく配列から呼び出そう！！！

すると以下のコード

例えばN=50

```python
N=50

memo=[-1 for i in range(N+1)]

def fib(n,memo):

    if n==0:
        memo[n]=0
        return memo[n]
    elif n==1:
        memo[n]=1
        return memo[n]
    else:
        if memo[n]!=-1:
            return memo[n]
        else:
            memo[n]=fib(n-1,memo)+fib(n-2,memo)
            return memo[n]

```

配列memo[n]は再起関数を呼ぶごとにインデックスが変わっていくためnに応じて値がキャッシュされる

#計算速度比較
###N=40の場合
メモ化無し
t=37.91sec

メモ化有り
一瞬

###N=400の場合
メモ化無し
オーバーフロー

メモ化有り
t=0.001sec

#結論
アルゴリズムおそるべし
エラー:AWS VPC構築

目的：ネットワークの知識を活かし深めつつ、サーバの構築やLinuxの活用などできるようにしたい。そして、ベースができたらプログラム書いてみたい。

１■AWS　VPC構築
-
特段難しい点はなし。
AWSで始めるインフラ構築入門がとても良い本で、サクサク進んでいる。
2■VPCへのログイン
-
詰まった。下記エラー発生
ssh: connect to host 〇.〇.〇.〇 port 22: Connection timed out

以前、書き残しておいたAmazon linuxへのssh接続の方法が全く通用しない。
VPCとEC2インスタンスだと何かが違うのかもしれない。
試したこと
・セキュリティグループのssh許可、マイipでの許可、デフォルトのセキュリティグループの削除
・ACLにsshの許可を追加
・ルートテーブル周りの設定の確認←これな気がしているが、調査するにはaws特有の理解がいりそう
・鍵のディレクトリ
まだ確認していないこと
・鍵の書き込み読み取権限→エラーの種類が違う気がするが...一応試してみる![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189399/fe1faa4d-3ff6-b5d9-065b-1b2a56384d25.png)

解決)
一度EC2インスタンスを破壊し、先週利用したEC2の鍵を使って新たなEC2を作るとssh接続できた。
鍵の書き込み権限周りかインスタンスの破損が原因か要確認
今回のエラーを通して、AWSのネットワーク周りを勉強する必要があると感じた。
Nginx Basic認証を複数ページに別ユーザでかける

#まず始めに
　今回やりたかったことは、表題通り。
　**NginxのBasic認証を複数ページで別々のユーザ・パスでかける**

　ページA(page_a)にユーザ(alpha)・パス
　ページB(page_b)にユーザ(beta)・パスでBasic認証をかけ、
　ページAでユーザ(beta)・ページBにユーザ(alpha)では認証をできないようにしたい。

　まずはBasic認証についてまとめてみました。

　
#Basic認証
　Basic認証とはWebサイトの特定のページやファイルにアクセス制限をかけることができる認証方法の1つです。
　Basic認証をかけると、認証をかけたWebサイトにアクセスしようとしたとき、
　認証ダイアログが立ち上がって、ユーザー名（ID）とパスワードの入力が求められます。
　簡易的な認証のため、公開前のWEBサイトの関係者のみの閲覧などの目的でも使用できます。
　
　
#導入方法
　今回はOSは**linux**で**Nginxは導入済み**を想定。
　導入方法は[こちら](https://qiita.com/noblin_1031/items/459997b2f811d3f1f8ab)。

 
 
###htpasswd コマンドインストール
```
$ sudo yum install httpd-tools
```
　
###.htpasswd ファイルの作成
ユーザ名とパスワードを記載


```
$ sudo htpasswd -c /etc/nginx/.htpasswd alpha
 New password: alpha1
 Re-type new password: alpha1
 Adding password for user username

$ cat /etc/nginx/.htpasswd
alpha:$alpha1$1HL4gU0L$Sm5cgGBydSUV5uo9Z8aNe0
```
 

###nginxの設定ファイルの追記
　Basic認証と.htpasswd ファイルを読み込みの記載。

```
$vim /etc/nginx/nginx.conf
…
server {
    listen 80;
    root /usr/share/nginx/html;
    index index.html index.htm;

    location /page_a{

        #認証時に表示されるメッセージ
        auth_basic "Restricted";

        #.htpasswdファイルのパス
        auth_basic_user_file /etc/nginx/.htpasswd; 

        proxy_pass: http://127.0.0.1:8000;
    }
}
…
```
　※proxy_passは忘れがちですが、gunicornとかWSGI使ってると404エラーが出ます。
　
###再起動
```
$sudo service nginx restart
```

　以上でページA(page_a)にはBasic認証がかかりました！
　サイトにアクセスするとBASIC認証がかかっていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1195805/a56c3165-e331-3e03-7f49-cf0034ae0ffb.png)
　
#異なるページにBasic認証をかける
　先ほど作成した.htpasswdとは異なるファイルにユーザB(beta)・パスを記載。

```
$ sudo htpasswd -c /etc/nginx/.htpasswd_beta beta
 New password: beta2
 Re-type new password: beta2
 Adding password for user username

$ cat /etc/nginx/.htpasswd_beta
beta:$beta2$1HL48ana$3OxkzGBydDeyzsc1nURil1
```
####nginx.confへの追記。

```
$vim /etc/nginx/nginx.conf
…
server {
    listen 80;
    root /usr/share/nginx/html;
    index index.html index.htm;

    location /page_a{ 
        #認証時に表示されるメッセージ
        auth_basic "Restricted";
        #.htpasswdファイルのパス
        auth_basic_user_file /etc/nginx/.htpasswd; 
        proxy_pass: http://127.0.0.1:8000;
    }
   
    location /page_b{
        auth_basic "Restricted";

        #ページBの.htpasswdファイルのパス
        auth_basic_user_file /etc/nginx/.htpasswd_beta; 
        proxy_pass: http://127.0.0.1:8000;
    }
}
…
```
####再起動

```
$sudo service nginx restart
```

　以上でページBにもBasic認証がかけることができました。



#最後に
　今回は別々のページで同一のユーザ・パスが使えないようにするため、.htpasswdを分けました。
　単純に複数ページに認証をかけるだけなら、分ける必要がないです。
　用途に合わせた設定をお勧めします。

　最後まで読んでいただきありがとうございました。