OmniAICreator/Qiita-1.07M huggingface dataset:
CheckStyleの対応

[Javaの開発環境メモ](https://qiita.com/kero3/items/2a22c786b89aa7e8dcf8)
で開発環境を構築しているが、CheckStyleでアラートが大量に出ているので、その対応方法を調べて記載していく。

JenkinsをIEで表示して、ソースコードが表示されない問題はIEのため。
Chromeだと表示された。

# 1.CheckStyle

## 1-1.pomの設定

```xml:pom.xml
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-checkstyle-plugin</artifactId>
				<version>3.1.1</version>
				<dependencies>
					<dependency>
						<groupId>com.puppycrawl.tools</groupId>
						<artifactId>checkstyle</artifactId>
						<version>8.37</version>
					</dependency>
				</dependencies>
				<configuration>
					<configLocation>google_checks.xml</configLocation>
					<failsOnError>true</failsOnError>
					<failOnViolation>true</failOnViolation>
					<violationSeverity>error</violationSeverity>
					<consoleOutput>true</consoleOutput>
				</configuration>
				<executions>
					<execution>
						<id>checkstyle</id>
						<phase>verify</phase>
						<goals>
							<goal>check</goal>
						</goals>
					</execution>
				</executions>
			</plugin>
```

## 1-2.設定ファイルのダウンロード

以下からダウンロードする？

https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml

pom.xmlファイルは以下のサイトを選考に設定した。
https://maven.apache.org/plugins/maven-checkstyle-plugin/examples/custom-checker-config.html

### エラーになる場合は？
https://github.com/checkstyle/checkstyle/blob/master/src/main/resources/google_checks.xml

ルールのファイルとライブラリのバージョンに差があるのかもしれない。

## 2-1.インポート文が辞書式順序になっていません。
### 2-1-1.原因
自作のクラスのパッケージがorgよりもアルファベットの先頭にある場合（jpなど)に、警告になる。

### 1-2.Eclipseによる解決方法

1. [ウィンドウ]-[設定]
2. [Java]-[コード・スタイル]-[インポートの編成]
3. 「新規」ボタンで自作のパッケージ(jp)を作成し、orgの上に移動する。

## 2.Package name 'パッケージ名' must match pattern '^[a-z]+(\.[a-z][a-z0-9]*)*$'.
### 原因 パッケージ名に「_」などの記号が含まれている。


### 2-1.CheckStyleによる解決方法

```xml:修正前
    <module name="PackageName">
      <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
      <message key="name.invalidPattern"
             value="Package name ''{0}'' must match pattern ''{1}''."/>
    </module>
```
上記のルールを警告ではなくINFOに変更する。
<property name="severity" value="info" />
指定できるのは ignore, info, warning, error のいずれか。

```xml:修正後
    <module name="PackageName">
      <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]*)*$"/>
      <message key="name.invalidPattern"
             value="Package name ''{0}'' must match pattern ''{1}''."/>
             <property name="severity" value="info" />
    </module>
```

# 参考URL
マルチモジュールでCheckStyleとかのルールを共有する
https://ssogabe.hatenadiary.org/entry/20091219/1261196056


## 2-2.static importでアスタリスク使用
### 原因


### 2-2-2.Eclipseによる解決方法
1. [ウインドウ]-[設定]
2. [Java]-[コード・スタイル]-[インポートの編成]
3. 「*に必要な静的インポート数’の値を【999】に変更。

これでアスタリスクは無くなるが、static importと通常のimportの間に空行を入れる必要がある。
そのため、static importは無くして、テストコードは「    Assertions.assertThat(」という書き方にする。
### CheckStyleによる解決方法


## 
### 原因


### Eclipseによる解決方法

### CheckStyleによる解決方法
デベロッパーツールのレスポンシブ表示をかっこよくしよう

#今回やりたいこと

百聞は一見に如かず！
ということで今回の記事でできることはコレ！！

![スクリーンショット 2020-11-08 14.15.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706118/211d0e9d-e356-7e2d-705d-cd9ac75d14a8.png)

デベロッパーツールでのレスポンシブ確認時の表示に、フレームをつける技です！

#設定方法
###1
まずは上にあるこの部分の一番左を
*Responsive*ではなく*iPhone*とか*ipad*(*Responsive*じゃなければOK)にします。
![スクリーンショット 2020-11-08 14.24.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706118/dcfb3bb9-1205-2bc1-1bf6-018e4f1b4d73.png)

###2
変更したら、一番右にあるメニューっぽいアイコン(点三つ)をクリックします。
![スクリーンショット 2020-11-08 14.24.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706118/46dca0b0-9929-6393-290c-45fcd06aac59.png)

###3
一番上の*show device frame*をクリックします。
![スクリーンショット 2020-11-08 14.27.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706118/26e8dbd4-a1d7-ec92-0157-f10cef2ad609.png)

おわり
laravel-enum:v2の日本語化

laravel-enumのv2の日本語化の書き方が他の記事と違ったので備忘録的に書き残す

## 環境

```shell-session

% sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.7
BuildVersion:	19H2

% docker version
Client: Docker Engine - Community
 Cloud integration: 1.0.1
 Version:           19.03.13
 API version:       1.40

# php -v
PHP 7.4.7 (cli) (built: Jun 11 2020 18:41:17) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
    with Xdebug v2.9.6, Copyright (c) 2002-2020, by Derick Rethans

# php artisan -v     
Laravel Framework 7.26.1

# mysql --version
mysql  Ver 14.14 Distrib 5.7.30, for Linux (x86_64) using  EditLine wrapper
```

# composer require bensampo/laravel-enum:2.2
最初何も考えずに`composer require bensampo/laravel-enum`叩いたら「最新のlaravel-enumはlaravel7.*に対応してない」と怒られた
[公式doc](https://github.com/BenSampo/laravel-enum)によるとlaravel7.*に対応してるのは`bensampo/laravel-enum:2.2`らしいのでバージョン指定でcomposer requireする
公式doc読むの大事ほんと

```shell-session
composer require bensampo/laravel-enum:2.2
```

ここからは[v2のdoc](https://github.com/BenSampo/laravel-enum/blob/v2.2.0/README.md)を参照する

## enum定義
enumファイル作成

```shell-session
php artisan make:enum UserType
```

enum定義

```php:UserType.php
use BenSampo\Enum\Enum;
use BenSampo\Enum\Contracts\LocalizedEnum;

final class UserType extends Enum implements LocalizedEnum
{
    const Administrator = 1;
    const SuperAdministrator = 2;
}
```
ちなみにmysqlのenum型は0を''として予約されているので1から定義する

# 日本語化
多言語化のインターフェースを有効にする 

```shell-session
# php artisan vendor:publish --provider="BenSampo\Enum\EnumServiceProvider"
Copied Directory [/vendor/bensampo/laravel-enum/resources/lang] To [/resources/lang/vendor/laravelEnum]
Publishing complete.
```


`resouces/ja`配下にenums.phpを作成して定義

```php:resources/lang/ja/enums.php
<?php

use App\Enums\UserType;

return [

    UserType::class => [
        UserType::Administrator => '管理者',
        UserType::SuperAdministrator => 'スーパー管理者',
    ],

];
```
これで日本語化されます
ubuntu https 通信 やりかた (GoogleChrome)

【環境】
ubuntu18.04 
apache2


Ubuntuのデフォルトのssl証明書を有効にする

```
sudo a2enmod ssl
sudo systemctl reload apache2
sudo a2ensite default-ssl
```

GoogleChromeでhttpsアクセスすると警告⚠️画面的なのでてくる。
詳細を開いて、"thisisunsafe"と空打ちして"Enter"キーを押すとhttps通信になる！
Command Line Toolsがうまくインストールできない時の対処法

# 通常のインストールのやり方
①以下のコマンドをターミナルで打ち込む

```
$ xcode-select --install
```
そうすると、画面の指示にしたがって、インストールするだけなのだが、
**「このソフトウェアは、現在ソフトウェア・アップデート・サーバから入手できないため、インストールできません。」**
という文言が出てきて、このやり方ではインストールできない！というのが発覚。
（もちろんこれだけでインストールできる人もいます）

# 何が原因？
細かいことはまだ判明していないのですが、
おそらくパソコンのバージョンによってこういうエラーが出るものではと推測
なのでエラーが出た人はバージョンを確認してメモをしてください。

## バージョンの確認方法は？
![Menubar.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/5444f482-c47f-3d0f-47cf-b2f6a05d6a23.png)
そうすると、**「このMacについて」**という項目があるのでそこをクリックした後に、
以下の画像のようなものが表示されます。
![このMacについて.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/fa5002c7-e29a-5938-826a-1c44efeafbf2.png)
このピンクの枠の中がバージョンです。

# Apple Developersを使おう！
以下、リンクです。
[Apple Developers](https://developer.apple.com/download/more/)
①Apple IDでのサインインを求められるので、サインインをする
②1番下にチェックボックスとsubmitボタンがあるので両方クリック。
これらの作業が終わると以下の画面になります。
![More_Software_Downloads_-_Apple_Developer-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/8cf19d27-07e5-b274-2ea2-bb30d95097bc.png)
③左上の虫メガネマークをクリックし、Command Line Toolsで検索（右上ではないです）
そうすると以下のような画面になります。
![More_Software_Downloads_-_Apple_Developer-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/625088/07e96b5d-e70a-bd87-ed5e-9fc27240666c.png)
④先程メモをしたバージョンに合わせてインストールするだけです。

# 結論
ターミナル上でインストールできるなら、インストールした方が早いですが、
別の解決方法を知っておくとエラーに対処できます！
Ubuntu18.04LTSでCDをリッピングしてMP3にする

子供の習い事の教材でCDを聴きながら進めるものがあるのだが、これを毎回コンポやらCDプレーヤーで聴くのが面倒＆手間だったので、MP3にしてDLNAサーバ(バッファローのNAS)に格納しておき、タブレットのDLNAクライアント(VLC)から聴けるようにしてみた。

## リッピング＆MP3エンコード
### Asunder + lame
先人の教えによると、Ubuntuでは「asunder」と「lame」の組み合わせが最強のようなので、素直にこれに従う。

```
$ sudo apt install asunder lame
```

バージョンはこんな感じでした。

```
$ sudo apt list | grep asunder
asunder/bionic,now 2.9.2-1 amd64 [インストール済み]

$ lame --version
LAME 64bits version 3.100 (http://lame.sf.net)
:
$
```
ランチャーから[Asunder CD]を起動する。デフォルトではogg形式にエンコードなので、[設定]→[エンコード]を開き、MP3にチェックをつける。ビットレートはお好みで。
![qiita_20201108_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552413/b8913c52-b292-0d2f-d5c5-3780b49b0f05.png)

CDDBからの情報取得もできるので、[詳細]のタブを開き、

- サーバ：freedbtest.dyndns.org
- ポート：80

をそれぞれ設定。
![qiita_20201108_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552413/2411fb2a-1bd5-f5d1-1c91-cc43305d7c34.png)

あとはお好きなCDを入れて、曲名などが正しく表示されたら、[吸い出す]でリッピング＆MP3エンコードしてくれる。

### Goobox
ネットを見ていたら「Goobox」というアプリもちらほら見かけた。

こちらは単体でリッピング＆MP3エンコードが出来る他、楽曲情報としてはMusicBrainzに対応してアルバム画像などメタデータの取得も可能というもの。

なのでUbuntuソフトウェアからインストールしたのだが、起動してもMP3エンコードが見つからない。「なんでやー」と調べたところ、MP3やMusicBrainz対応が入った最新版は「3.6.0」であるのに対し、Ubuntu18.04ではこれらの機能が未実装の「3.4.2」が提供されていたのであった。

Ubuntu20.04LTSでは3.6.0が提供されているので、20.04LTSにするというのも一つの手だけど、それはそれで違うだろーってことで見送り。

もう１つの手として、公式サイトからソース一式を持ってきて自分で作れそうなことはわかったけれど、そっちに走るのは(今は)違うと思ったのでやっぱり見送り。

## MP3タグ付け
普通だったらこれで事足りるだろうが、この「習い事のCDの情報」がCDDBではほとんど見つからない、もしくはたまに見つかっても情報が古かったり、微妙に違っていたりする。

ウチの用途においては曲名などは大事な要素ではないのでトラック番号だけわかっていれば事足りるとは思うのだが、使って勉強するのは子供たちであり、子供たちが迷わないようにしなければならないので、MP3タグ付けアプリも合わせて導入した。

### EasyTag
こちらも老舗と評されていて、Ubuntuソフトウェアに登録されていたのでインストールした。

ところが、なぜだかわからないのだが、ウインドウのサイズを目一杯小さくしてもウインドウの下端が画面からはみ出してしまうし、全画面表示ボタンもないので、どうしてもすべての情報を表示しきれないのだ。
![qiita_20201108_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552413/09bb0ba8-bfb5-f4c3-5f09-c30ecddbe9ed.png)

下端に大した情報は無いとは思うもの、この状態で使うというのはなんとなーく気持ち悪いので、EasyTagは早々に諦めた。

### Wine+Mp3Tag
Windowsでは「Mp3Tag」を使っていたので、これと同じ使用感のがあればいいな・・・と探していたのだが、そういえばWine入れてるんだからコレでいいじゃん、ということで導入。

Mp3TagはMusicBrainzにも対応しており、CDDBより情報にヒットする確率が高いので、タグ付けだけでなくこの点でも重宝している。

今の所、文字化けなどは見られず、ちゃんと動いている感じ。

## 雑感
- これでまた一歩、自分のWindowsPCでの使い方に近づきました。
- 子供たちにVLCの使い方を1回説明したら、それ以降、迷うことなく使いこなしてます。これがデジタル世代の力か・・・
 
## 参考
Asunder
http://littlesvr.ca/asunder/index.php

lame
https://lame.sourceforge.io/

Goobox
https://people.gnome.org/~paobac/goobox/home.html

EasyTag
https://wiki.gnome.org/Apps/EasyTAG

Mp3Tag
https://www.mp3tag.de/en/
【Android/Java】Fragmentに戻るボタンを設置する

## はじめに
フラグメントでの戻るボタンの設置において、
親Activity内で定義して呼び出す書き方にしていたのですが、
Activityに置かずに各Fragmentから直接中身を呼び出すほうがいい
と、ベテランエンジニアから指摘をいただいたので備忘録として両パターン残しておきます。

## ①MainActivityから呼び出す方法
```java:MainActivity.java
public class MainActivity extends AppCompatActivity {

//  戻るボタンを定義
    public void setupBackButton(boolean enableBackButton) {
        ActionBar actionBar = getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(enableBackButton);
    }
}
```

```java:Fragment1.java
 // onCreateView内で呼び出す
 MainActivity activity = (MainActivity) getActivity();
 activity.setupBackButton(true);
 setHasOptionsMenu(true);  // FragmentでActionBarを使うために必要な設定
```

```java:Fragment2.java
 // onCreateView内で呼び出す
 MainActivity activity = (MainActivity) getActivity();
 activity.setupBackButton(false);
```


## ②Fragmentから直接呼び出す方法
```java:Fragment1.java
 // onCreateView内で呼び出す
 .setupBackButton()
 setHasOptionsMenu(true);  // FragmentでActionBarを使うために必要な設定
 
 // Fragmentクラス内で定義
 public void setupBackButton() {
        AppCompatActivity activity = (AppCompatActivity) getActivity();
        ActionBar actionBar = activity.getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(true);
  }
```
※下記はFragment1から遷移したときに戻るボタンが表示されてしまうのを防ぐために記載してます。
必要可否は各自判断してください。

```java:Fragment2.java
 
 // onCreateView内で呼び出す
 .hideBackButton()

 // Fragmentクラス内で定義
 public void hideBackButton() {
        AppCompatActivity activity = (AppCompatActivity) getActivity();
        ActionBar actionBar = activity.getSupportActionBar();
        actionBar.setDisplayHomeAsUpEnabled(false);
  }
```

## 違い
ぱっと見た感じ同じですが、Activityの取得先が違います！
①MainActivity activity = (MainActivity) getActivity();
②AppCompatActivity activity = (AppCompatActivity) getActivity();

特定のActivity(今回だとMainActivity)が前提の書き方はやめたほうがいいとのことです。
前提となるクラス(自分で定義したクラス）が増えるほどコードは安全な変更がしづらくなるからです。

取得先がAppCompatActivityであれば継承元なので変更されることはほぼないし安全性が高いということでしょうかね。
先を見据えた実装ができる強強エンジニアになりたいです。
【PHPの名前空間について】

version5.4以降に使える名前空間についてメモっとく


```
namespace A;
class A{
	public  static function xxx(){}
}
namespace B;
class A{
	public  static function yyy(){}
}
```
この場合namespaceAのAクラスと、namespaceBのAクラスということになる。
呼び出すときはuseキーワードを使う。

```
use A\A
```
この場合、これ以下でAクラスを呼び出したときはnamespaceAのAクラスのことを参照していることになる。

```
use A\B
```
こうすることで、namespaceAのBクラスを呼び出していることになる。

別名で呼び出す場合
use A\A as C
こうするとこれ以下で、C::xxx();としたとき、実施にはnamaspaceAのAクラスを参照していることになる。

```
use A\A as C
C::xxx(); 
//A::xxx();と同義
```

【namespaceを使う際はグローバルクラスなのかそのnamespace内のクラスなのかを意識する】
例えば、以下だとエラーになる。

```
namespace A
try{
    //エラー構文
}catch(Exception $e){
    echo $e->getMessage();
}
```

なぜなら、ここでいうExceptionクラスはnamespaceA内のものを指しているから。

```
\Exception 
```
こうしないとエラーメッセージの入ったグローバルなExceptionクラスにアクセスしていないことになる。
Ubuntu20.04 + Visual Studio Codeで日本語が打てなかった

# はじめに
Ubuntu20.04でプログラミングの学習をしていたとき、
ふと、Visual Studio Code（以下 VSCode）で日本語が打てないことに気づきました。

その解決方法を記します。

# この記事でわかること

Ubuntu20.04上のVSCodeで、日本語が打てないときの解決方法


# 環境
Ubuntu20.04

# 原因とその解決方法

Ubuntu SoftWareを経由してインストールしたVSCodeに問題があったようです。
これをいったんアンインストールし、
[公式サイト](https://code.visualstudio.com/download)から .debファイルをダウンロード、
ターミナルを通してインストールすることで解決しました。

```
$ sudo apt install /tmp/mozilla_hogeUser/code_1.51.0-1604600753_amd64.deb 
```


![Screenshot from 2020-11-08 13-57-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549712/5b35fc7b-c7fa-37ee-fd08-ef1ad93bdf77.png)

# 参考
- [Download Visual Studio Code](https://code.visualstudio.com/download)
- [SnapでインストールしたVS Codeで日本語入力ができない ](https://redj.hatenablog.com/entry/2020/04/30/001946#%E8%A7%A3%E6%B1%BA%E7%AD%96)
【Rails5】 japanMapリンク　js.erbファイル内のパラメータ書き方

初投稿になります。プログラミング始めて4ヶ月の初心者です。よろしくお願いします。

ポートフォリオ作成の際にjapanMapを使用して8地方ごとにイベントを検索できるようにしました。  
その際、地方ごとのリンクに任意のパラメータを渡すのに少し苦労したので、自分で確認用として投稿しています。

今回は　application.jsファイルにjapanMapのプログラムを記述しました。

以下が自分の書いたコードになります。

```php:application.js
//検索ページ日本地図
$(function(){
  //8地方でリンク作成
  var areaLinks = {
    1:"/user/index?sort=hokkaido",
    2:"/user/index?sort=tohoku",
    3:"/user/index?sort=kanto",
    4:"/user/index?sort=chubu",
    5:"/user/index?sort=kinki",
    6:"/user/index?sort=chugoku_shikoku",
    7:"/user/index?sort=kyusyu_okinawa",
  };

  //8地方エリア指定
  var areas = [
    {code : 1, name: "北海道", color: "#ab86c4", hoverColor: "#dfcceb", prefectures: [1]},
    {code : 2, name: "東北",   color: "#6d93d1", hoverColor: "#91b0e3", prefectures: [2,3,4,5,6,7]},
    {code : 3, name: "関東",   color: "#f5a164", hoverColor: "#f5c09a", prefectures: [8,9,10,11,12,13,14]},
    {code : 4, name: "中部",   color: "#77e077", hoverColor: "#adedad", prefectures: [15,16,17,18,19,20,21,22,23]},
    {code : 5, name: "近畿",   color: "#ffe966", hoverColor: "#fff2a3", prefectures: [24,25,26,27,28,29,30]},
    {code : 6, name: "中国・四国",   color: "#e68ccc", hoverColor: "#f0b9e0", prefectures: [31,32,33,34,35,36,37,38,39]},
    {code : 7, name: "九州・沖縄",   color: "#de6474", hoverColor: "#f29da9", prefectures: [40,41,42,43,44,45,46,47]},
  ];

  //地図表示設定
  $("#map-container").japanMap({
    width: 600,
    areas  : areas,
    selection : "area",
    borderLineWidth: 0.25,
    drawsBoxLine : false,
    movesIslands : true,
    showsAreaName : true,
    font : "MS Mincho",
    fontSize : 13,
    fontColor :"#777",
    fontShadowColor : "white",
    onSelect : function(data){
    location.href = areaLinks[data.area.code];
  };
});
```

上記のこの部分がリンクになります。

```
var areaLinks = {
    1:"/user/index?sort=hokkaido",
    2:"/user/index?sort=tohoku",
    3:"/user/index?sort=kanto",
    4:"/user/index?sort=chubu",
    5:"/user/index?sort=kinki",
    6:"/user/index?sort=chugoku_shikoku",
    7:"/user/index?sort=kyusyu_okinawa",
};
```

html.erbファイルでは下記のように記述するところを

```:○○.html.erb
<%= link_to '◯◯', ○◯_path(:sort => 'hokkaido') %>
```

js.erbファイルでのlink_to の書き方がわからなかった為、

```php:○○.js.erb
1:"/user/index?sort=hokkaido"
```

のように記述しました。こうすることで任意のparams[:sort]のパラメータを渡すことができました。
[?sort=hokkaido] の部分がパラメーターになります。

```php:○○_controller.rb
def index
    if params[:sort] == 'hokkaido'
        @events = Event.where(prefecture_code: "北海道")
	    @events = @events.page(params[:page]).per(6).order("id DESC")
```

上記がコントローラーの一部になります。
[if params[:sort] == 'hokkaido']の記述でパラメーターを区別し表示するイベントを変更しています。

初めての投稿で見にくいところ間違いなどあるかもしれませんが最後まで見ていただきありがとうございました。
【Ruby】メソッドのselfを戻り値にするとどうなるか？

再度、繋げて同じメソッドを使えるようになります。

## 実践例
```ruby
class Hoge
  def foo
     self
  end
end

Hoge.new.foo
#<Hoge:0x00007f92612b2e38>

Hoge.new.foo.foo.foo.foo
#<Hoge:0x00007f92618c82a0>
```
このように、戻り値が同じ型なので、再度同じメソッドを使うことが可能になります。

## 解説

```ruby
a.method b
```
と言う状況で戻り値がレシーバのaになります。だから、

```ruby
c = a.method b
```
では、cにはaと同じ型のものが出力されます。

## 応用例
インスタンス変数を保持させ、メソッドを呼び出した回数をカウントさせます。

```ruby
class Hoge
  def foo
     @a.nil? ? @a = 1 : @a = @a + 1 
     self
  end
end

Hoge.new.foo
=> #<Hoge:0x00007f92618c2080 @a=1>

Hoge.new.foo.foo.foo.foo
=> #<Hoge:0x00007f92618a0a98 @a=4>
```
こうすると、fooメソッドを呼び出した回数だけ@aの値が増えていっているのがわかります。
Javaのインターフェースについて

## Javaのインターフェースの特徴
インターフェースの特徴として以下の2つが挙げられる

- インターフェースはインスタンスフィールド（インスタンス変数）を持つことが出来ない
- 具象メソッド（抽象メソッドではないメソッド）を実装することができない


### interface はインスタンスフィールドを持たない
インターフェースでは、フィールドを宣言しようとすると`public static final`のように定数を宣言したものとして扱われる。

### 具象メソッドを実装することが出来ない
抽象メソッドしか定義することが出来ず、interfaceは実装された場合インスタンスが生成された場合には抽象メソッドは必ずオーバーライドされる必要がある。

### おまけ
 各クラスの共通化のために、インターフェースの代わりにクラスを作成するときに注意が必要。各クラスが何かしらのサブクラスである場合、共通化してクラスにしたものを継承することは出来ない。なぜなら、Javaでは、スーパークラスは1つしか持てない。
　インタフェースであれば、複数実装することは可能。
[.NET] Fluent Assertionsを使って、きれいで読みやすいテストコードを書く

# はじめに

[Fluent Assertions](https://fluentassertions.com/) は、.NETのテストコードを流麗で読みやすくしてくれるライブラリです。
日本語解説記事があまり見当たらないので、ここでまとめてみようと思う次第です。

JavaScriptの[Jasmine](https://jasmine.github.io/)を知っているかたでしたら、jasminのmatchersの.NET版みたいなものと思ってください。

## Fluent Assertions使うとどうなるの？

だいたいのテストランナーでは、このようなテストコードを書きます。

```c#
Assert.Equal(期待値, 実際の値);
```

Fluent Assertionsを使うと、このように書きます。

```c#
実際の値.Should().Be(期待値);
```

「プログラミングは文学である」と言われます。
どうでしょ？文学ぽいですか？

# 導入

[NuGet](https://www.nuget.org/packages/FluentAssertions/) から導入できます。

Visual Studioの場合は、[プロジェクトを右クリックすると現れるメニューからインストールできます](https://docs.microsoft.com/ja-jp/nuget/quickstart/install-and-use-a-package-in-visual-studio)。


# いろいろなアサーションの書き方

[アサーション用のメソッドがたくさん用意されています](https://fluentassertions.com/basicassertions/)。

よく使うものをあげてみます。

```c#
// 値が等しい
実際の値.Should().Be(期待値);

// 値がNULL
実際の値.Should().BeNull();

// 値がNULLではない
実際の値.Should().NotBeNull();

// 値がTrue
実際の値.Should().BeTrue();

// 値がFalse
実際の値.Should().BeFalse();

// 値が同じオブジェクト
実際の値.Should().BeSameAs(期待値);
```

## コレクション関係

コレクション関係でよく使うものです。

```c#
// 同じ要素を含む
実際の値.Should().BeEquivalentTo(期待値);

// 空のコレクション
実際の値.Should().BeEmpty();
```

## 日時関係

日時関係でよく使うものです。

```c#
// 期待値より後
実際の値.Should().BeAfter(期待値);

// 期待値より前
実際の値.Should().BeBefore(期待値);

// 期待値とズレ(単位:ms)の範囲内
実際の値.Should().BeCloseTo(期待値,　ズレ);
```
文言 / wenyan‑langで湯婆婆を実装してみる

##はじめに
2019末「文言/wenyan‑lang」のカレンダーが作りたくてqiita初投稿し、はや1年。
プログラミングも記事(markdown)もあまり上達してませんが2020年も作りました。
「湯婆婆」は[オンラインide](https://ide.wy-lang.org/)で挑戦してみました。
使い方は[こちら](https://qiita.com/libru1/items/9a93493410e7f4c78df8)の記事で紹介しています。この記事中のコード⬇️をコピペしてすぐ試していただけます。
画像のサイズが調整出来なくてすいません。では、漢文風言語の世界お楽しみください!

# 元ネタ

こちらになります。
@Nemesisさんの[Javaで湯婆婆を実装してみる](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2)

##コード

```sh
吾嘗觀「「質問」」之書。方悟「質問」之義。
夫「「契約書だよ。そこに名前を書きな。」」。
名之曰「湯婆婆」。夫「湯婆婆」書之。
施「質問」於「湯婆婆」於「「荻野千尋」」。名之曰「回答」。
夫「回答」之三。
名之曰「名」。
吾有一言。曰「「フン。」」夫「回答」夫「「というのかい。贅沢な名だねぇ。」」。
夫「「今からお前の名前は」」夫「名」夫「「だ。いいかい、」」夫「名」夫「「だよ。分かったら返事をするんだ、」」夫「名」夫「「!!」」。
名之曰「湯婆婆」。夫「湯婆婆」書之。
```

契約書で受け取った名前からランダムに一文字を選ぶ部分、名前を受け取れなかった場合の処理が実力不足でまだ出来てません。

##実行結果
![Screen Shot 2020-11-07 at 18.39.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334227/f15c99ac-8a8b-7eb1-8f11-a91efac55fe1.png)

![Screen Shot 2020-11-07 at 18.41.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334227/2a0ddb91-0860-1124-ddf0-105dd902a51d.png)

##ソースのレンダリング
![Screen Shot 2020-11-07 at 18.51.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334227/dd2b0434-798b-56c1-aa92-e4dc22f14a28.png)
【PHP】timestamp形式の日付時刻をフォーマットして表示したい

# やりたいこと

現在作成中のアプリで記事投稿日の表示フォーマットを変更したい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588983/2e30b196-ce62-0e84-2da6-47653d9d03d3.png)


# 投稿一覧画面のソース抜粋

```php

    <!-- 投稿一覧画面 -->
    <div class="container">
        <div class="contents">
        <?php foreach($posts_arr as $key => $value) :?>
            
            <div class="card" style="margin-top: 16px;">
                <div class="card-header" style="padding: 0; font-family: serif;">
                    <div class="text-center" style="margin-top: 0.6rem;  line-height: 0rem;">
                        <a><i class="fas fa-fish"></i> <?php echo $posts_arr[$key]['fish_kind']; ?></a>
                    </div>
                    <div class="text-right" style="margin-right: 0.6rem;">
                        <a style="font-size: 0.6rem;">投稿者 <span style="font-size: 0.8rem; font-weight: bold;"><?php echo $posts_arr[$key]['nickname']; ?></span>さん</span></a>
                    </div>
                </div>
                <div class="card-main" style="object-fit: contain; margin-bottom: 16px;">
                    <img src="./img/<?php echo $posts_arr[$key]['file_name']; ?>" class="card-img">
                </div>
                <div class="card-body">
                    <p class="card-text" style="margin-bottom: 0.4rem;"><?php echo mb_strimwidth($posts_arr[$key]['angler_comment'], 0, 200, '…', 'UTF-8'); ?></p>
                    <div class="text-right">
                        <a style="font-size: small;">投稿日: <?php echo $posts_arr[$key]['created_at']; ?></a>
                    </div>
                    <div class="text-right">
                        <a href="./posts/show.php?p_id=<?php echo $posts_arr[$key]['id']; ?>" class="card-link" style="font-size: small;">詳細を見る</a>
                    </div>
                </div>
            </div>

        <?php endforeach; ?>
        </div>
    </div>
```

# 改修内容

投稿日: 2020-11-05 21:42:08
表示の秒数部分を無くして
投稿日: 2020-11-05 21:42
にしたい

# 改修方法

```php
 // 日付表示部分
 <div class="text-right">
     <?php $date = new DateTime($posts_arr[$key]['created_at']);?>
     <a style="font-size: small;">投稿日: <?php echo $date->format('Y-m-d H:i'); ?></a>
 </div>
```

関数一つ通せばできるものかなと考えながら調べている内にdate_format()を発見

しかし、date_format()はそもそもオブジェクトありきの関数だったため
フォーマットする前にオブジェクトを生成してから実行する必要があると知った。
結論、echoの前にtimestamp形式のデータをオブジェクト生成してからフォーマットする流れでできた。
<br>
<br>

```php
<?php echo date_format($date, 'Y-m-d H:i'); ?>
```
もちろんechoの部分はこれでもいけますがなるべくオブジェクト指向の記述で書きたいので
前者の方を採用しました。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588983/ce45ab51-2f86-2077-b1f3-5a4b97033b83.png)

<strong>や↑ったぜ</strong>


# 参考

[PHP公式リファレンス](https://www.php.net/manual/ja/datetime.format.php)
JavaScript製汎用テーブル（第2回：表データ定義）

JavaScript勉強の目的で、小規模のアプリをコーディングしています。
今回はその１つ「汎用テーブル」を制作したので紹介します。
第１回 https://qiita.com/suwanishi77/items/02e2ddeb26f55928ee54

資材は
https://github.com/nnnmu24/generaltable
よりDLしてください。

## 表データの定義
定義するデータは表データと表オプションが存在します。

サンプルの表データは以下の通りです。
```
const tableDataSource = [
["SAMPLE01","映像作品リスト"],
["タイトル","ジャンル","鑑賞方法","鑑賞日","評価"],
["text","text","text","date.YYYY年MM月DD日","num"],
["","option01","","","option02"],
["アメリカのヒーローが大集合","アクション","","",""],
["余命少ない恋人と過ごす","恋愛","テレビ","2017年03月05日","3"],
["銀河を支配する帝国を打倒する","SF","DVD購入","2018年01月15日","5"],
["剣と魔法で闘う勇者","ファンタジー","動画配信サイト","2018年09月16日","1"],
["伝説の龍を育てる","ファンタジー","レンタルDVD","2019年02月05日","3"],
["王子様系の転校生に恋をする","恋愛","テレビ","2019年08月21日","2"],
["ドタバタ家族の海外ドラマ","コメディ","動画配信サイト","2019年05月05日","5"],
["とある王朝の栄枯","歴史","DVD購入","2018年11月03日","5"],
["続・とある王朝の栄枯","歴史","DVD購入","2019年08月21日","4"],
["学校一の不良を決める喧嘩祭","アクション","レンタルDVD","2017年07月11日","3"],
["豪華客船での恋物語","恋愛","映画館","2017年08月01日","5"],
["天下無双の剣豪","アクション","映画館","2020年01月04日","1"],
["伝説の傭兵が立ち上がる","アクション","映画館","2019年12月09日","4"],
["銀河を支配する帝国を打倒する・前日譚","SF","","",""],
["美大生全員が片想い","恋愛","映画館","2017年10月20日","5"],
];
```

サンプルの表オプションは以下の通りです。
```
const tableColumnOption = {
    option01: ["<div style='color:red'>", "</div>"],
    option02: ["★"],
};
```

表データの定義内容を説明します。  
1行目から4行目は表の定義で、5行目以降が表の実データになります。

- 1行目、1要素目：表コード  
　表を識別するコード値を記述します。任意の文字を指定可能です。  
　設定を保存する際のキーに使用します。  
- 1行目、2要素目：表名  
　表の名前を記述します。任意の文字を指定可能です。  
　表のタイトルとして表示します。  
- 2行目：列名  
　各列の名称を記述します。任意の文字を指定可能です。  
　表のヘッダとして表示します。  
- 3行目：列の型  
　各列がどの値であるかを示す型を記述します。文字列、数値、日付のいずれかとします。  
　型名はそれぞれ「text」「num」「date」です。  
　dateは"."を付与し日時書式を追記します（例「date.YYYY/MM/DD」）日時書式は後述のいずれかとしてください。  
　列の型は検索、ソート処理に影響します。  
　配列要素は列名と同数としてください。要素超過分は無視されます。  
　数値型、日付型を1つ以上定義した場合、表示変更エリアに数値絞込、日付絞込が表示されます。  
- 4行目：列オプション  
　特定列の表データを装飾したい場合に、表オプションで定義したオプション名を記述します。装飾しない場合は空文字。  
　オプション名を記述した場合、該当列の表データの前後に表オプションの文字列を付与します。この文字列はHTMLとして解釈されます。  
　配列要素は列名と同数としてください。要素超過分は無視されます。  
　サンプルの場合、2列目にoption1が、5列目にoption2が適用されます。  
　これにより2列目は文字色が赤色に、5列目は先頭に"★"が追加されます。  
- 5行目以降：表データ  
　表データの実値を記述します。  
　行の要素数に上限はありません。  
　値は任意ですが、数値型、日付型を指定した列はその定義に従った値にしてください。空文字は可能です。  
　列の要素数は列名と同数としてください。要素超過分は無視されます。  

## 表の解析、異常ケース
初回表示時に表データの定義値が正当かをチェックし、不備があった場合その内容をダイアログで表示します。
チェック内容と、不正時のデフォルト値は以下の通りです。
- 表コード：未定義または空文字→デフォルト値「T0001」
- 表名：未定義または空文字→デフォルト値「デフォルト表」
- カラム名：空文字→デフォルト値「カラム1」「カラム2」・・・
- カラム型
　カラム型不正→デフォルト値「text」
　日付書式不正→デフォルト値「text」
- カラムオプション：不正なキー→デフォルト値 オプションなし
- 表レコード
　カラム数に足りない→デフォルト値 空文字
　数値型、日付型で不正→デフォルト値 空文字

## 列の型「日付型」の日時書式について
列の型に日付型を指定した場合、型名「date」の後に"."を付与し日時書式を追記します。  
日時書式は以下に示す「日付要素」「時刻要素」または「日付要素 時刻要素」のいずれかとしてください。  

例．
- date.YYYY/MM/DD
- date.HH:mm :ss
- date.YYYY年MM月DD日 HH時mm分ss秒
"."以降を省略した場合はデフォルトで「YYYY/MM/DD HH:mm :ss」が適用されます。

- 日付要素
  - YYYYMMDD
  - YYYY/MM/DD
  - YYYY-MM-DD
  - YYYY年MM月DD日
  - MMDD
  - MM/DD
  - MM-DD
  - MM月DD日
- 時刻要素
  - HHmmss
  - HH:mm :ss（記載時はmm後の空白なしで）
  - HH時mm分ss秒
  - HHmm
  - HH:mm
  - HH時mm分
Quillでテーブル名に定数を使う方法

# 2021/05/25
コンパイルできない問題を回避する方法が見つかりました
doc コマンドを使用しないように設定すればdistが通ります(dist内部でdocを呼んでいるのが問題でした)

~~# 注意(2020/12/13)
この方法を使用すると、play frameworkのdistやsbt-native-packagerでjarが生成できなくなります。(compileコマンドは普通に通りますが、distを行うとコンパイルエラーが出ます)
Quillまたはsbtの制限もしくはバグかもしれません。
 回避するためにはベタ書きするしかありません。~~

# はじめに
[Quill](https://github.com/getquill/quill) でテーブル名に定数を使用しようとしたときにハマったのでメモとして残しておく。

# 動かないコード
一度しか使わないものや書き散らす場合を除き、テーブル名はいろいろな箇所で使用するため定数として定義しておくことが望ましい。

そこで以下のように定数を使用してみた。

```scala
import java.util.UUID

import io.getquill._

object Scalab {

  def main(args: Array[String]): Unit = {
    val ctx = new PostgresJdbcContext(LowerCase, "dataSource")
    import ctx._

    val sample = quote { querySchema[Sample](Schema.SampleTable) }

    println(run(quote { sample }))
  }

}

object Schema {
  val SampleTable = "Sample"
}

case class Sample(id: UUID, name: String, age: Int)
```

一見正しそうに見えるが、コンパイルすると以下のようなエラーが出る。

```console
[error] {PATH TO FILE}: Tree 'ctx.querySchema[Sample](Schema.SampleTable)' can't be parsed to 'Ast'
[error]     val sample = quote { querySchema[Sample](Schema.SampleTable) }
```

# 動くコード
ごく普通の要求なので絶対に解決策があると思い調べてみたらヒントらしきissueが挙がっていた。
[Unable to use constant directly defined in object](https://github.com/getquill/quill/issues/138#issuecomment-179579140)

つまり以下のようにすればコンパイルでき想定通りにコードが動く。

```scala
object Schema {
  final val SampleTable = "Sample"
}
```
Arch Linux インストール時のpacstrapでkeyが見つからないエラーの対処

古ーいISOイメージを使ってArchを導入しようとすると、keyringが古すぎてpacstrapがうまくいかない。ここでは、自分のやった作業をメモとして残す。

対処法をググると以下が見つかる。
1. pacman-key --refresh を使ってkeyringを更新する方法
2. pacman-keyringそのものをインストールしなおす方法。

私の場合、keyserverを指定して1の方法で更新しても見つからないkeyがあった。
そこで2を試すわけだが、pacstrapをするまではbashが入らないのでarch-chrootも使えない。chrootせずにpacmanを使ってkeyringをインストールし直すにはひと手間必要。(本当にひと手間だけ。メモに残す必要もなさそうだけどどうせ次やるときまた忘れてるので。。念のため)

```bash:pacstrap前のkeyringの再インストール方法
pacman -Sy ##pacmanを使うために必要.これが必要なだけ
pacman -S pacman-keyring ##keyringの更新
pacstrap /mnt ##あとはインストールガイドに従ってpacstrapする
```
Adobe XDでの名刺の作成方法

#名刺の作成方法
![スクリーンショット 2020-11-08 13.35.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633943/b2f5a132-055b-4a8e-58da-62e96695fe04.png)
gitのアカウントを切り替えるshellコマンドを作成してみた

## はじめに
エンジニアとして転職して、7ヶ月が経過しました。
少し余裕が出てきたので、プライベートのgitにも草を生やそうとしたけど、
毎回gitのアカウントの切り替えを行うのは非常に面倒だと思いました。

そこで、shellコマンドを作成して、簡単にgitのアカウントを切り替えられるようにしてみました。

## 開発環境
- MacOS
- zsh

## 手動でアカウントを切り替える場合(参考までに)
user.nameとuser.emailをそれぞれ入力して切り替えます。

```:ターミナル 
$ git config --global user.name "<YOUR_NAME>"
$ git config --global user.email <YUOR_EMAIL>
```

上記を実行すると`.git/.gitconfig`のuserの部分が変わります。
(finderでの隠しファイルは `cmd + sht + .`で表示/非表示を切り替えられます。)

```:.git/.gitconfig
[user]
  name = <name>
  email = <email>
```

## shellコマンド作成(本題)
zshのコマンドを作成します。
`.zshrc`を開いて下記を記載します。
`git config --list`は変更できたかを確認するためなので、なくても大丈夫です。

```.zshrc
function gitMain() {
  git config --global user.name "<業務用のgitのアカウント名>"
  git config --global user.email <業務用のメールアドレス>
  git config --list
}

function gitPri() {
  git config --global user.name "<プライベートのgitのアカウント名>"
  git config --global user.email <プライベートのメールアドレス>
  git config --list
}
```

## コマンド実行
zshrcの記載が終わったら、zshrcを閉じます。
ターミナルも再度開き直さないと、反映されないので注意してください。

仕事用のアカウントに切り替えるときは

```:ターミナル
$ gitMain
```

プラベートのアカウントに切り替えるときは


```:ターミナル
$ gitPri
```

を実行することで可能になります。
`git config --list`を記載している場合は、コマンド実行すると`.gitconfig`の中身もターミナルに表示され、name, emailが変更されていることを確認できます。
【ドメイン駆動設計入門】備忘録（第2章まで）

ドメイン駆動設計入門という本を読んだので、
備忘録として知識をアウトプットして自分の考えを整理したい。
読者としてはドメイン駆動設計に興味のある人、ドメイン駆動設計入門を読んでみたい人です。

### ドメイン駆動設計入門について
個人的にはとにかくわかりやすいと思った。
本書に載っているソースはC#で書かれていたが
わたしはJavaをやっているので問題なく読めた。
オブジェクト指向言語をやっている人ならなんなく読めるはずなのでぜひ読んでほしい。

### ドメイン駆動設計とは
なんやかんや言っているが乱暴に要約すると
リファクタリングがしやすい設計手法だと言える気がする。
特徴としては、ドメイン（独立したルールを持つオブジェクト）をソースコード化して、
ルールを一つのドメインオブジェクトにまとめることによって、
ソースコードからルールを読み取ることができるようになるし、
修正箇所を一か所にまとめやすくできるため保守や改善がしやすい設計になるということだと私は解釈した。

### キーワード
* ドメイン
* 値オブジェクト

### ドメインとは
プログラムを適用する対象となる領域。
例えば会計システムなら金銭や帳票。
物流なら貨物や倉庫、輸送手段の概念。
なにに目を当てなければいけないかを明確化するための概念としてのドメイン。

### 値オブジェクト
値オブジェクトの性質
* 不変である
* 交換が可能である
* 等価性によって比較される

#### 「不変である」について
例えばシステムでの処理の中でUserオブジェクトが作成されたとします。
そうするとUserオブジェクトの中にはuserId、firstName、lastNameのフィールドが作られます。
このときuserIdやfirstName、lastNameのどれか一つでも処理中に変更されるとすると
プログラマはデータのライフサイクルとデータの変更タイミング、変更内容について意識しながら
プログラムを書く必要があります。
しかし、不変である値オブジェクトとして生成すれば、
データの変更タイミング、変更内容については意識せずプログラムを書くことができます。
そして不変であることはオブジェクトの正しさを強制します。
不変なオブジェクトとして生成するためにはオブジェクトがルールを持ち、
不正な値ではオブジェクトが生成できないことを表現する必要があります。



#### 「交換が可能である」について
上記のような不変なオブジェクトを生成すれば、
オブジェクト内の値は変更できないため代入操作による交換以外の方法をできないように強制されます。

#### 「等価性によって比較される」について
値オブジェクトは値を表現するため、オブジェクト同士の比較が行われます。
つまり、値オブジェクトを比較するためのequal()関数が必要になります。
このequal()関数を書くことが強制されるため、
システムに新たなルールが追加され、値オブジェクトに新たなフィールドが追加されても、
equal()関数の中身を変えるだけで改修を終えることができます。

### 最後に
上記までがドメイン駆動設計入門の第2章までの内容になります。
値オブジェクトの表現だけでもかなり実践できそうな内容ではないでしょうか？
わたしが今まで作ったものは少ないですが私でさえもこれをやっていたら
無駄な調査を回避できたのになという内容でした。
次にドメイン駆動設計を実践できる場所があったらぜひやってみたいと思います。

第三章は別の記事で。。。
ご拝読ありがとうございました。
多次元配列を1重のループで扱う【JavaScript】

このあいだ4次元美術館プレーヤーというのを書きました。美術館というのはパズルの名前で、もとは2次元上の盤面にやたら指向性の高い明かりを置いて、すべてのマスを照らすパズルです。こんな感じ。

![akari.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696043/c445c90e-5c5c-1adb-eb46-74aef2b5cbf2.png)


で、何を思ったかこれを4次元に拡張したパズルを制作する人がいて、2次元でもデジタルの助けが欲しいパズルなのに4次元ともなるとさすがに紙とペンで解くには限界があり、それならということでプレーヤーを作りました。こんな感じです。なんかヤバそうですね。

![2020-11-08 12.35.33 4次元美術館プレーヤー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696043/9aee13db-bd1c-4c1d-1c7d-0bee0b15a272.png)


って、そんな話はどうでもいいのでした。とにかく、4次元の盤面を生成したり操作したりするのには4次元配列が必要で、すなわち4重ループを回す必要に迫られたのです。

# 問題：深すぎるネスト

愚直に書くとまーこんな感じです。

```javascript
for(let x = 0; x < boardX; x++){
    for(let y = 0;y < boardY; y++){
        for(let z = 0; z < boardZ; z++){
            for(let w = 0; w < boardW; w++){
                board[x][y][z][w] = hogehoge()
            }
        }
    }
}
```

いやこれはさすがにダサい。筆者は別にfor文廃止論者ではありませんが、こんなん誰だって間違うしネストは深過ぎで見づらいし、いいことはなにもない。というわけで、解決策を考えましょう。

# 解決策①： 余りを用いる
なるべくネストは1重にしたいので、まずはそういうふうに書いてみます。

```javascript
for(let index=0; index < boardX * boardY * boardZ * boardW; index++){
    let x,y,z,w // どうやって求める？
}
```

`index`から`x,y,z,w`を求めるには、割り算の余りを使えそうです。

```javascript
function calcQandR(n,m){
    return [Math.floor(n/m), n%m]
}

function index2pos(i){
    var [i,w] = calcQandR(i,boardW)
    var [i,z] = calcQandR(i,boardZ)
    var [x,y] = calcQandR(i,boardY)
    return [x,y,z,w]
}

for(let index=0; index < boardX * boardY * boardZ * boardW; index++){
    let [x,y,z,w] = index2pos(index)
    //処理
}

```

行数は増えましたが、大分すっきりしました。ただ、`index2pos`の中に定数が残っていたりして、まだ使い勝手が向上できそうです。

# 解決策②：ジェネレータを使う

ジェネレータについて詳しいことは他の記事を参照してもらうとして、ここではfor-ofで取り出し可能な座標リスト（正確には「イテラブルなオブジェクト」）を生成するものと思ってもらえれば十分です。

```javascript
function* product(...sizes){
    sizes = sizes.reverse()
    let all = sizes.reduce((a,c) => a*c, 1)
    for(let index=0; index<all; index++){
        let result = [], i = index
        sizes.forEach((size) => {
            result.push(i%size)
            i = Math.floor(i/size) 
        })
        yield result.reverse()
    }
}

for(let [x,y,z,w] of product(boardX,boardY,boardZ,boardW)){
    //処理
}
```

すっきりしました。何次元でも対応できるように書いたので、5次元や6次元になっても最小限の書き換えで対応できます。やったぜ。

# pythonでは
`itertools`というパッケージがあり、その中の`product`を使えば同じことが簡単に実現できます。jsでもこれが使えたらハッピーだねというだけの記事でした。

# 参考
[JavaScript の ジェネレータ を極める！](https://qiita.com/kura07/items/d1a57ea64ef5c3de8528)
OpenID Connect セッション管理 概要


Open ID Connectで定義されるセッション管理の仕組みについてまとめる。殴り書きメモ記事。

## 用語

* **OpenID Connect**
  * OAuth 2.0の認可フローをベースに、追加で、「認証結果」と「属性情報（アイデンティティ情報を提供するエンドポイントへのアクセス認可情報）」をやり取りするためのプロトコル。
* **Relying Party(RP)**
  * OpenID ProviderにID Tokenとユーザー情報を要求するサーバー、SSO対象のアプリケーション。
* **OpenID Provider（OP）**
  * ユーザー認証機能を有し、ユーザー認証時にRelying Partyから要求されたアイデンティティ情報を提供できるエンドポイントを有するサーバー。
* **ID トークン**
  * OPから提供される 認証・認可情報を含むJWT形式のトークン。

## セッションの作成・更新(Creating and Updating Sessions)

### RP

* RPがエンドユーザーのIDトークンを検証した時点でセッションを開始する。 

### OP

* OPはセッション管理をサポートするために、以下を実施する。
  * `Authentication Response/Error Response`で`session_state`を返却する。
        * `session_state`
            * OPでのエンドユーザーのログイン状態(セッション状態)を表現するJSON 文字列。
            * セッション状態値の生成方法
                * クライアントID、オリジンURL、およびOPユーザーエージェント状態をソルトされた暗号化ハッシュに基づいて計算。

## セッション状態変更検知(Session Status Change Notification)

* `Authentication Request/Response`でセッションが確立された場合、RP iframeから`postMessage`を使用して、OP iframeをポーリングすることでログイン状態を確認する。

#### RP iframe

* RP側でセッション状態管理を行うための機構。
* RPアプリに適した間隔で`postMessage`を使用してOP iframeをポーリングする。
  * RP iframeからOP iframeの`postMessage`データ
    * クライアントID + " " +セッション状態
* OP iframeからの`postMessage`を受信する。
  * `changed`(セッション状態変更あり)/`unchanged`(セッション状態変更なし)を受け取る。
  * `changed`を受信した場合は、`prompt = none`を使用して再認証を実行する。
    * 新しいIDトークンとセッション状態を取得し、古いIDトークンを`id_token_hint`として送信する。 
  * 同じエンドユーザーのIDトークンを受け取った場合
        * セッション状態を更新する。
  *  IDトークンを受信しない場合、または別のエンドユーザーのIDトークンを受信する場合
        * 元のエンドユーザーのログアウトとして処理する。

#### OP iframe

* OP側でセッション状態管理を行うための機構。
* OP側に、呼び出し元(RP)情報を事前に登録する。
  * 登録外オリジンからの`postMessage`リクエストを拒否し、XSS攻撃を防ぐため。
* OP iframeは、RPによって渡されたOPセッション状態を計算して比較するためにユーザーエージェント状態(CookieまたはHTML5ストレージ内)にアクセスできる。
* OP iframeは、以前に取得したクライアントID、ソースオリジンURL、および現在のOPユーザーエージェントの状態からセッション状態を再計算する。
* OP iframeは、RPから受信した`postMessage`に対して、
  * 構文的に不正、もしくは投稿されたクライアントIDと発信元URLを特定できない場合
        * OP iframeはエラーをRPに返す。
  * 受信した値と計算した値が一致しない場合
        * OP iframeは`changed`をRPに`postMessage`する(一致した場合は、`unchanged`を`postMessage`する)。
* OP iframeは、ログイン、ログアウト、認証ステータス変更のようなイベントに応答して、ユーザーエージェント状態を更新する。その後にセッション状態を確認すると、変更された値が返される。
* `Authentication Response`が成功の場合、OPは、次のいずれかのイベントでクライアントに返されるセッション状態の値を更新する。
  * ユーザーエージェントに対して、認証済みユーザーの組み合わせが変更される場合（ログイン、ログアウト、セッションの追加など）。
  * エンドユーザーが使用しているクライアントの認証ステータスが変更される場合。

* セッション状態を検証するために使用されるユーザーエージェントの状態は、上述のイベントに合わせて変化させる必要がある。 
* セッション状態確認を行うと、上述のイベント後、以前のバージョンのセッション状態に対して`changed`が返却される。



#### OpenID Provider Discovery Metadata

* RPはセッション管理関連の次のOPメタデータを取得する。
  * `check_session_iframe`
    * RPクライアントとのセッション状態情報のクロスオリジン通信をサポートするOPiframeのURL。
    * 関連するRPiframeからのpostMessageリクエストを受け入れ、postMessageを使用してOPでのエンドユーザーのログインステータスをポストバックする。



## 参考情報

* [OpenID Connect Session Management 1.0 - draft 30](https://openid.net/specs/openid-connect-session-1_0.html)
Oracle PDBについて

##はじめに
Oracle Database12cをインストールし、スキーマ作成にはまったのでメモ。

インストールが完了した後、スキーマを作成しようとするとエラーが発生。
「ORA-65096: 共通ユーザーまたはロール名が無効です」

今までこんなことなかったのになぜだろうと調べると、
デフォルトの接続先がCDB（コンテナデータベース）になっているため
PDB（プラガブルデータベース）に接続が必要とのことでした。

##接続手順
**1.ログイン**
　as sysdba でログインします。

```
sqlplus SYSユーザ名/パスワード@ネットワークサービス名 as sysdba
.....に接続されました
```

**2.接続先確認**
　現在の接続先を確認します。

```
SQL>show con_name;
CON_NAME
------------------------------
CDB$ROOT
```

CDB$ROOTと表示されているのでCDBに接続しているということがわかります。

**3.PDB確認**
　PDB名を確認します。（わかる場合は飛ばします。）

```
SQL>select name, open_mode from v$pdbs;
NAME
------------------------------
OPEN_MODE
--------------------
PDB$SEED
READ ONLY

ORCLPDB
READ WRITE
```

$SEEDではない方ががPDB名となります。
そのため（この場合）ORCLPDBがPDB名だとわかります。

**4.PDB起動**
　PDBを起動します。

```
SQL> alter pluggable database ORCLPDB open;
```

すでに起動している場合は下記が表示されます。（表示されても問題ないです。）

```
alter pluggable database ORCLPDB open
*
行1でエラーが発生しました。:
ORA-65019: プラガブル・データベースORCLPDBはすでにオープンしています
```


**5.接続先変更**
　CDBからPDBに接続先を変更します。

```
SQL> alter session set comtainer = ORCLPDB;
セッションが変更されました。
```

**6.接続先確認**
　PDBに接続できているか確認します。

```
SQL> show con_name;

CON_NAME
------------------------------
ORCLPDB
```

PDB名が表示されていれば接続成功です。

##スキーマ作成
PDBに接続ができたらスキーマを作成します。

```
SQL>create user スキーマ名 identified by パスワード
ユーザが作成されました

```

＊必要に応じて権限付与を行ってください。

##tnsnames.ora追記
作成したスキーマをPDBで接続するために下記をtnsnames.oraに追記します。
>ネットワークサービス名 =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = ホスト名)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = PDB名)
    )
  >)

##ログイン
作成したスキーマでログインをします。

```
sqlplus スキーマ名/パスワード@ネットワークサービス名
.....接続されました
```


<script type="text/javascript">var a8='a20112511629_3BQT58_6IKTWA_2HOM_BUB81';var rankParam='mC7dP.SHVRol5F9PVAonLzo_IRo_0TSUPC0TPLojlhtm_hMZc';var bannerType='0';var bannerKind='item.fix.kind1';var frame='1';var ranking='1';var category='本・雑誌・コミック';</script><script type="text/javascript" src="//rws.a8.net/rakuten/ranking.js"></script>
GitHubの使い方やマナーなど。

# 勉強の記録
- 初心者のプログラミング５　2020/11/08

## 勉強した内容
- GitHubのアカウント作成と運用の仕方。

## 何をベースに勉強してるか
- [N予備校 プログラミング入門](https://www.nnn.ed.nico/courses/668/chapters/9514)

## 内容の詳細
- GitHubの使い方から、マナーや禁止事項等。
- 作ったページ。
- https://caibaseto.github.io/assessment/assessment.html

### わかったことについて
- コードをオープンにすることで皆で技術向上してるんだなって感じました。
- SNSに投稿する用に、OGPの設定の仕方。

### むずかしかったよ
- 今回は特になし。

## 次回やる予定のこと
- 次回から第2章に入ります、不安です。
データカタログを使う（カテゴリー 基本編）

##カテゴリーとは
データカタログとは、欲しいデータを管理する台帳です。
その台帳に登録されているデータ資産は、後でデータを探しているユーザーから適切に探してもらわなくてはいけません。

ユーザーに欲しいデータを適切に探してもらう１つの手段として、ビジネス用語を使う方法があります。
そして、そのビジネス用語を適切に管理するために、カテゴリーを使います。

カテゴリーとは、ビジネス用語を整理するフォルダまたはディレクトリのようなものです。
（※ カテゴリーは、ビジネス用語だけを整理するものではありませんが、ここではわかりやすくそうしています。）

ビジネス用語をカテゴリーでグループ化することで、見つけやすくして、管理しやすくします。
パソコンで、ファイルをフォルダーごとに整理する方法と同じです。
そして、フォルダーと同様に、1つのカテゴリーは複数のサブカテゴリーを持つことができますが、サブカテゴリーは直接の親カテゴリーを1つだけ持つことができます。

##カテゴリーの例
カテゴリーの作成例は、特に決まったものはありませんが、使いやすく整理するように利用することを心掛けます。
例えば、以下のように分けるのが良いかも知れません。

+ 部門単位
+ 地域単位

##カテゴリー作成方法
ここでは、IBM Cloud Pak for Data(CP4D)のWatson Knowledge Catalogを例に、カテゴリーの作成方法をご紹介します。
CP4Dにログインした直後の画面です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/07089994-5af0-aea6-3eef-b43af5b8f16e.png)
左上にあるメニューボタンを押して、ガバナンス -> カテゴリーを選択します。
![スクリーンショット 2020-11-06 22.43.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/b0d481b0-8890-6871-59a8-813290e1c45c.png)
カテゴリー名と説明を記入し、保存を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/98a9d834-8372-1b4c-ff1c-6b814a6a3fd9.png)
カテゴリーが作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/f0d35f05-e1de-39e3-ca88-cd3b02d5881c.png)
同様にカテゴリーを作成していきます。先ほど、例で示したように、**部門単位**と**地域単位**と**その他**で作った例を図示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/284aa1ca-faca-21ba-1abf-bda72d2228ca.png)
以上で、ビジネス用語を作成するための事前準備が終わりました。
なぜか「clasp failed」と言われた時に最初に試すべきこと

GAS (Google Apps Script）のWebアプリケーションを開発している。
Google謹製のclaspというツールを使って、ローカルのPCでコーディングしている。
クライアントサイドの環境はWindows 10 + WSL 1 + Ubuntu + bashで、エディタはEmacsだ。

ローカルでコードをいじって、Google側にあげようとして ```$ clasp push``` というコマンドを叩くと、以下のメッセージで止まることがある。

```
Push failed. Errors:
```

さまざまな原因があるが、ここでは、もっとも対策に労力がいらない簡単なエラーを自分用備忘録として書く。

#(1) 編集中のファイルがある

Emacsで、たとえばCode.tsというファイルを編集しているとき、保存していないとバッファバーにダーティサイン**が出ている。
この状態でpushしようとすると失敗する。
メインのTSコードやHTMLだけでなく、実験用のテキストファイル、作業進行表なども同じフォルダに置いてpush対象になっているとこれで引っかかる。
.claspignoreに細かく指定するか、余計なものは置かない。

#(2) logoutしてloginすると「なぜか」治る
#(3) しばらくほうっておいて再実行すると「なぜか」できる

両方体験した。
コストゼロなので試す価値はあるだろう。

#(4) シンボリックリンクが「なぜか」使えない

作業中に前のコードを見ることがあるので、現在のフォルダから前のコードのフォルダへシンボリックリンクを張っていた。
当然その下のファイルは見に行かないように.claspignoreに指定していた。
しかし、なぜかこの状態ではpushできず、シンボリックリンクを消すとなぜかできた。

原因は究明していないひどい記事だが、誰かの役に立てば。

（この項終わり）
【lightsail】Error establishing a database connection 対応


## aws lightsail bitnamiで構築しているwordpress環境にアクセスすると、
```Error establishing a database connection``` が発生していた。

### ec2インスタンスにsshで接続して、ステータスチェック

```sh
$ sudo /opt/bitnami/ctlscript.sh status
php-fpm already running
apache not running
mysql not running
```

### mysql が起動していないので、start してみるも、disk full が発生している模様。

```sh
df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            488M     0  488M   0% /dev
tmpfs           100M  3.2M   96M   4% /run
/dev/xvda1      9.7G  9.7G  2.3M 100% /
tmpfs           496M     0  496M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           496M     0  496M   0% /sys/fs/cgroup
/dev/loop0       98M   98M     0 100% /snap/core/9993
/dev/loop1       18M   18M     0 100% /snap/amazon-ssm-agent/1566
/dev/loop2       29M   29M     0 100% /snap/amazon-ssm-agent/2012
/dev/loop3       97M   97M     0 100% /snap/core/9804
tmpfs           100M     0  100M   0% /run/user/1000
```

### EBSボリュームを拡張後、ボリュームサイズ変更後の Linux ファイルシステムの拡張 をする

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/recognize-expanded-volume-linux.html


```sh
df -h
Filesystem      Size  Used Avail Use% Mounted on
udev            488M     0  488M   0% /dev
tmpfs           100M  3.2M   96M   4% /run
/dev/xvda1       20G  9.7G  9.7G  51% /
tmpfs           496M     0  496M   0% /dev/shm
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs           496M     0  496M   0% /sys/fs/cgroup
/dev/loop0       98M   98M     0 100% /snap/core/9993
/dev/loop1       18M   18M     0 100% /snap/amazon-ssm-agent/1566
/dev/loop2       29M   29M     0 100% /snap/amazon-ssm-agent/2012
/dev/loop3       97M   97M     0 100% /snap/core/9804
tmpfs           100M     0  100M   0% /run/user/1000
```

### startして、mysqlが起動したことを確認した

```sh
$ sudo /opt/bitnami/ctlscript.sh start
php-fpm already running
apache not running
mysql already running
```

## FYI
https://docs.bitnami.com/aws/faq/administration/control-services/
face-api(ml5.js)は感情ではなく、顔の位置検出のためのAPIであるというメモ

#やろうとしてたこと
画像から感情分析を行って感情に応じたアクションを取ろうとしていた
（ml5.jsを使ってやろうとした）

#face-apiは顔の部位の位置検出のためのものでした
表情の読み取りとどこかに記載があったから、感情に近いものが取れるのかと考えたが違った。
Happyなどの感情をとれるものではない。

faceapiは画像から顔の口や目などの部位の位置を、点の配列で返してくれるものでした。
口は、たぶん6点の情報をくれて、描画で点と点を線でつなぐと口が検出できる。
他もいくつかの点の情報を順番に線でつなぐといったもの。

何の用途で使うの？とおもったが、たぶん、
　１．位置検出→位置を直すようメッセージを出す（証明写真のときに真ん中に寄ってもらうみたいなの）
　２．位置検出→デジカメか何かに組み込んで、その位置にピントを合わせる
といったところか。

ちなみに、目をつぶっても目の輪郭の大きさは変わらなかったから寝ているかは判断できなさそう。
（Next.js） TypescriptファイルでCSS/SCSSファイルを読み込む方法

##1. 問題
Next.jsプロジェクト内のtypescriptファイルでCSSファイルをimportで読み込もうとすると、エラーになります。

```sample.ts
import style from "./styles.css"

//下記のようなエラーが出て読み込めない
TS2307: Cannot find module './styles.css
```

##2.解決策
「next-env.d.ts」というファイルがあるはずなので、そこに下記のように追加で記述。
無事Next.jsプロジェクト内のtypescriptファイルでcss/scssが読み込めるようになります。

```next-env.d.ts
declare module '*.css';
// or scss
declare module '*.scss';
```

参考
[How to fix TypeScript cannot find module CSS/SCSS in Next.js](https://linguinecode.com/post/how-to-fix-cannot-find-module-css-scss-nextjs)
ServiceNow - Parisのバグ

#概要
ServiceNow Parisには次のバグがある。
フローデザイナーのアクションでスクリプトステップの入力変数がアクションが「{{undefined}}」に変更される。

#再現手順
1. Flow Designerを開く
2. 新規にActionを作成
3. ActionにScriptステップを追加
4. ScriptにInput Variableを定義
5. Input Variableに値を設定![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/5d8dbccc-bf41-794b-c49e-eef840ae781b.png)
7. ページの他の項目をクリックする
8. Input Variableが「{{undefined}}」へ変わる![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/e42d88c5-8634-98b9-d4b9-4e2688b4bdb8.png)


#対策
~~既にServiceNowに連絡をして9月16日のParisリリースと共にリリースされたホットフィックス１で対応すみ。Chromeでは正しく入力変数を保存することができるようになりましたが、Firefox及びEdgeでは正しく保存しないことを確認。ServiceNowからの対策を待ち中。
Hotfix1を適用して、ServiceNowから対策版がリリースされるまではChromeを利用する。~~

Paris Patch 2で修正されました。

以上
機能要件と非機能要件【メモ】

先日に引き続き、手書きのノートからの転記です。
# 機能要件
Webサービスやアプリケーションといったサービスがユーザーに提供しなければならない**「機能そのものの要件」**のこと。
例えばQiitaだったら、ログイン機能や記事投稿機能、ストック機能など、ユーザーが利用する機能がたくさんある。
そういうものに関わる要件のことを言う。

# 非機能要件
サービスを取り巻くシステムが実現しなくてはならない**「機能以外の要件」**のこと。
具体的には、以下のようなものが含まれる。

- 「可用性」  
サーバー側で何らかの障害が発生した場合でも、サービスを提供し続けることができる。
- 「性能」 
多数のユーザーが同時にアクセスするなどの負荷がかかっても、サービスの機能を維持できる。
- 「拡張性」  
新機能の追加やテストを行いやすい。
- 「保守性」  
機能の不具合を改修しやすい。
- 「セキュリティ」  
アカウントを乗っ取られたり、悪意あるユーザーからの攻撃といったリスクに対処できる。

今までのプログラミング学習に当てはめると、RubyとRailsを使ってアプリの機能を開発したりするのが機能要件で、AWSを使ってインフラを整えたり、Dockerを使って開発環境を構築したりするのが非機能要件ということかしら。
世の中の仕事の多くは、業務内容の高度化や複雑化にしたがって分業化が進み、機能要件と非機能要件は分断されて双方がブラックボックス化していくものだと思う。
しかしながら、Web系は少人数開発の場合も多いこと、新しい言語や技術の興亡が激しく一つの技術に習熟することの意味が薄いこともあって、両方に関して幅広く知識や経験を備えていくことが重要となるようだ。
Rubyでの正規表現における行頭・行末の扱い

Railsでモデルのバリデーションを正規表現で、チェックしようとしたところエラーが起こったので備忘録としてメモしておきます。

## 環境
`Ruby 2.5.1`
`Rails 5.2`

### エラーになった実装

``` Ruby:user.rb
class User < ApplicationRecord
  validates :age, format: { with: /^[0-9]+$/, message: "は数値のみ入力可能です。"}
end
```

#### エラーの内容

```Ruby
The provided regular expression is using multiline anchors (^ or $), which may present a security risk. Did you mean to use \A and \z, or forgot to add the :multiline => true option?
```
エラーの内容としては、`^`,`$`はセキュリティのリスクがあるため、`\A`,`\z`を使えと言われているようです。
`^` → `A`
`$` → `z`
上記の方法ではない場合、`:multiline => true`オプションをつけることで脆弱性を含むコードでも、あえてエラーを発生させないとい方法もあります。

調べたところによると、Rails4以降ではセキュリティ対策として、正規表現が厳しくなったようです。

Rubyでは特定の頭と末尾を指定したマッチを行いたい場合は以下のように実装するのが良さそうです。
`:multiline => true`オプションをつける方法もありますが、バリデーション処理の場合などは、特別な理由がない限りは、指定しないほうがいいのかなと感じました。

``` Ruby:user.rb
class User < ApplicationRecord
  validates :age, format: { with: /\A[0-9]+\z/, message: "は数値のみ入力可能です。"}
end
```

一応Rubyの公式リファレンスでも以下のように定義されています。
> ^ 行頭にマッチします。行頭とは、文字列の先頭もしくは改行の次を 意味します。
> $ 行末にマッチします。 行末とは文字列の末尾もしくは改行の手前を意味します。
> \A 文字列の先頭にマッチします。
> \z 文字列の末尾にマッチします。

##### 参考文献
[正規表現によるバリデーションでは ^ と $ ではなく \A と \z を使おう](https://blog.tokumaru.org/2014/03/z.html)
[Rails4では正規表現が厳しくなった。](https://jumperson.hatenablog.com/entry/2013/06/27/062237)
[Ruby 2.7.0 リファレンスマニュアル  正規表現](https://docs.ruby-lang.org/ja/latest/doc/spec=2fregexp.html)
Raspberry PiにDockerをインストール

## 概要

### 動作確認機種

- Raspberry Pi 3 Model B+
- Raspberry Pi Zero W

## インストール

※参考：https://docs.docker.com/engine/install/debian/

1. パッケージを最新化します。

    ```shell
    sudo apt update
    ```

1. Dockerインストールスクリプトをダウンロードし、実行します。

    ```shell
    curl -fsSL https://get.docker.com -o get-docker.sh
    sudo sh get-docker.sh
    ```

1. `pi`ユーザを`docker`グループに参加させます。

    ```shell
    sudo usermod -aG docker pi
    ```

1. `pi`ユーザでシェルにログインしている場合は、ログアウトしてから、ログインし直します。

    ```shell
    logout
    ```

## 動作確認

※参考：https://docs.docker.com/engine/install/linux-postinstall/

1. 次のコマンドを実行し、動作確認します。

    ```shell
    docker -v
    ```

    ```text
    Docker version 19.03.13, build 4484c46
    ```

1. 次のコマンドを実行し、`hello-world`してみます。

    ```shell
    docker run hello-world
    ```

    ```text
    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    4ee5c797bcd7: Pull complete 
    Digest: sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    Status: Downloaded newer image for hello-world:latest

    Hello from Docker!
    This message shows that your installation appears to be working correctly.

    To generate this message, Docker took the following steps:
    1. The Docker client contacted the Docker daemon.
    2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
        (arm32v7)
    3. The Docker daemon created a new container from that image which runs the
        executable that produces the output you are currently reading.
    4. The Docker daemon streamed that output to the Docker client, which sent it
        to your terminal.

    To try something more ambitious, you can run an Ubuntu container with:
    $ docker run -it ubuntu bash

    Share images, automate workflows, and more with a free Docker ID:
    https://hub.docker.com/

    For more examples and ideas, visit:
    https://docs.docker.com/get-started/
    ```

## 自動起動

1. 問題なければ、Raspbian OS起動時にdockerを自動起動するように設定します。

    ```shell
    sudo systemctl enable docker
    ```