OmniAICreator/Qiita-1.07M huggingface dataset:
Docker + Django + Wagtail を使ってCMS構築する - 導入編

## はじめに

CMSに少し触れてみたいなあとふと思いついて、この記事を書いてみました。
CMSといえば、私は真っ先にWordPressを思い浮かべます。

しかしながら、開発でDjangoを使っていることもあり、
面白そうだと思いまして、今回はDjango製のCMSを使っていきます。

WagtailとはDjango(Python)上で動くCMSです。
オープンソースで、インストール手順も下記ページを見る限り簡単に導入できそうと
思い、一連の流れを記事にしてみました。
http://docs.wagtail.io/en/v2.6.1/getting_started/index.html

他のQiita記事でも導入方法は載っていたので、
私の記事ではDockerComposeを使用した構築方法を載せております。



## 環境の構築 - ファイルの作成

Wagtailを導入するコンテナのDockerfileを記載していきます。

```dockerfile:Dockerfile
FROM python:3.6
ENV PYTHONUNBUFFERED 1

WORKDIR /server
ADD . /server/
RUN pip install --upgrade pip
RUN pip install wagtail
```

DBやNginxを今後入れられるよう、
Docker Composeファイルも作っておきます。

```yml:docker-compose.yml
version: '3'

services:

  cms:
    build:
      context: ./cms
      dockerfile: Dockerfile
    command: 'python manage.py runserver 0.0.0.0:8000'
    ports:
      - 8000:8000
    volumes:
      - ./cms:/server/
```


## 環境の構築 - サーバーの立ち上げ

コマンドにて、Wagtailプロジェクトを立ち上げます。
管理画面にログインする際のユーザーも作成します。

```terminal
$ docker-compose run cms wagtail start mysite
$ docker-compose run cms python ./mysite/manage.py createsuperuser
```

導入する際に使用したコンテナを
Wagtailプロジェクトに向き先を変えて起動します。

```dockerfile:Dockerfile
FROM python:3.6
ENV PYTHONUNBUFFERED 1

WORKDIR /server
ADD . /server/
RUN pip install --upgrade pip
RUN pip install wagtail
RUN pip install -r ./mysite/requirements.txt
RUN python ./mysite/manage.py migrate
```

## サーバーの立ち上げ

サーバーの立ち上げを行います。
もしうまくいかない方は `docker-compose run ./mysite/manage.py migrate` を行なってください。

```terminal
$ docker-compose build
$ docker-compose up -d
```

localhost:8000 にアクセスすると、
初期ページが見ることができると思います。
<img width="1440" alt="wag2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258186/2fa8e80d-0043-211f-132d-646696722467.jpeg">

また、管理画面の方も localhost:8000/admin から確認できます
<img width="1440" alt="wag.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258186/bfb07ecc-b08b-61ef-bfae-8879fae3b233.jpeg">

## まとめ

今回は、環境を構築〜サーバー立ち上げまでを行いました。
次回は実際にブログを作成することを意図とした実装をしていきたいと思います。

現在弊社では、HRモンスターと呼ばれる
採用の新しいスタイルを提供するサービスをローンチいたしました。

ローンチ後のさらなる機能追加、改善などのPDCAサイクルを回すべく、
エンジニアを募集しております。
https://www.wantedly.com/projects/341182

Kubernetes、Vue.js（Javascript）、Django（Python）といったモダンな技術を使って、
開発しておりますので、もしご興味がある方はぜひ、ご応募お待ちしております。
Wagtailチュートリアル 3 バナーを追加しよう(1) 

#Wagtailチュートリアル 3
<=[2 ホームページを始めよう](https://qiita.com/tagawahirotaka/items/c0aeca21c01872097d81)
=>[4 バナーを追加しよう (2)](https://qiita.com/tagawahirotaka/items/477f66c6f5ed0206270b)
##バナーを追加しよう(1) 


8,9,10,11

```python:home/models.py

from django.db import models #⓪ モデルをインポート

from wagtail.core.models import Page #⓪ページをインポート
from wagtail.core.fields import RichTextField #⑧ RichTextFieldをインポート
from wagtail.admin.edit_handlers import FieldPanel,PageChooserPanel #④ FieldPanelをインポート 11 必要なものをインポート
from wagtail.images.edit_handlers import ImageChooserPanel #11 必要なものをインポート


class HomePage(Page):#⓪ページを引数に

    templates = "home/home_page.html" #① wagtailtutorial/templates/home/homepage.html

    max_count = 1 #⑥ ADD CHILD PAGEを制限

    banner_title = models.CharField(max_length=100, blank=False, null=True) #③ banner_titleを定義

    banner_subtitle = RichTextField(features=["bold", "italic"]) #⑧banner_subtitleを定義

    banner_image = models.ForeignKey( #⑨banner_imageを定義
        "wagtailimages.Image",
        null=True,
        blank=False,
        on_delete=models.SET_NULL,
        related_name="+"
    )

    banner_cta = models.ForeignKey( #⑩banner_ctaを定義
        "wagtailcore.Page",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+"
   )

    content_panels = Page.content_panels + [ #④ 11 admin画面に追加
        FieldPanel("banner_title"),
        FieldPanel("banner_subtitle"),
        ImageChooserPanel("banner_image"),
        PageChooserPanel("banner_cta")
    ]

    class Meta:

        #verbose_name = "OH HELLO WORLD" ⑦ ADD CHILD PAGEでの表記
        verbose_name = "Home Page"
        verbose_name_plural = "Home Pages"
```

11
<img width="1440" alt="スクリーンショット 2019-08-26 08.57.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/27cc752c-bd8e-ef98-177c-842717244e62.png">
Talendコンポーネント活用（３）階層化JsonファイルをtExtraJsonFieldsで入力する

#**階層化Jsonファイルの入力処理**
前回までは１階層のJsonファイルを入出力してみましたが、今回は２階層のJsonファイルの入力をtFileInputJsonコンポーネントとtExtraJsonFieldsコンポーネントで行う処理を紹介します。

#**入力するJsonファイル**
今回入力するJsonファイルは２階層の販売データです。
![Input_Sample_Extra_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463924/6f8ce221-60c5-4074-e818-aad1ec26a866.jpeg)

#**tFileInputJsonの設定**
１階層目のSalesDataをtFileInpuJsonで入力するように設定します。
スキーマの編集からSalesDataを設定します。
![Input_Sample_Extra_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463924/7b8adbc8-6206-82ae-7045-bbbd942b8c5c.jpeg)

ループJSONクエリーには"$"を設定し、MappingのSalesDataのJSONクエリーには"SalesData[*]"を設定します。
![Input_Sample_Extra_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463924/262b3ffe-7fba-6a06-220b-772b7aff14ac.jpeg)

#**tExtraJsonFieldsの配置**
ジョブにtExtraJsonFieldを追加して下図のようにtFileInputJsonと接続します。
![Input_Sample_Extra_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463924/aaa7a60e-0bea-30ab-146d-e2610b371e85.jpeg)

#**tExtraJsonFiledsの設定**
スキーマの編集から展開する各スキーマを設定します。
![Input_Sample_Extra_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463924/d5888429-617f-d327-57fb-68a5ebf6b927.jpeg)

Read ByはXpathに変更し、ループXpathクエリーには２階層目の"/details/"を設定します。
![Input_Sample_Extra_6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463924/45393e63-f842-6a98-ef33-3bd4d3afab91.jpeg)

各スキーマのXpathクエリーは以下のように設定します。
Store→"Store"
Date→"Date"
Num→"Num"

【要チェックポイント】
detailsの１階層上にあるtypeとnameを読み込む場合には、先頭に"../"を付加することにより読み取ることができます。
type→"../type"
name→"../name"
![Input_Sample_Extra_7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463924/edea6a63-28cb-4d25-dfed-abc26374b46a.jpeg)

これで２階層のJsonファイル読み込みの設定が完了です。
ジョブの最後にtFileOutputDelimitedを追加してCSVに出力して実行します。
実行するとrow1では１行ですが、row2では展開されて１２行で出力されています。
![Input_Sample_Extra_8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463924/13a61541-f009-9bfd-81d5-c09d59260b0b.jpeg)

#**実行後の出力結果**
CSVには１２行の販売データとして出力することができました。
![Input_Sample_Extra_9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463924/4373c23d-3eed-076d-a5f1-afc816505945.jpeg)

#**まとめ**
tExtraJsonFieldsを使用することにより２階層のJsonファイルを読み込むことができました。
次回は複数回層のJsonファイル出力を紹介します。
heroku上でseleniumを使用した際のエラー解決 ”Webdrivers::BrowserNotFound”

#エラー内容
seleniumをheroku上で使用していたがエラーが発生するようになった。**$ heroku logs**で確認すると、**"Webdrivers::BrowserNotFound (Failed to find Chrome binary.):"**が発生していた。
#原因
webdriversがChromeのバージョンを取得するために使用していたChromeのShimが、サーバーを立ち上げる挙動に変わってしまったことが原因のようです。
#解決方法
Selenium::WebDriver::Chrome.pathをshimではなくbinaryへ直接向ける。
#サンプルコード
```ruby:gemfile
gem 'selenium-webdriver'
gem 'webdrivers'
```
```ruby
require 'selenium-webdriver'
require 'webdrivers'
Selenium::WebDriver::Chrome.path = ENV.fetch('GOOGLE_CHROME_BIN', nil)

options = Selenium::WebDriver::Chrome::Options.new(
  prefs: { 'profile.default_content_setting_values.notifications': 2 },
  binary: ENV.fetch('GOOGLE_CHROME_SHIM', nil)
)

driver = Selenium::WebDriver.for :chrome, options: options
```
>[HerokuでSeleniumとHeadless Chromeを動かしたい](https://medium.com/shuheiktgws-blog/herokuでseleniumとheadless-chromeを動かしたい-cb164538942e)

##herokuのbuildpack
```
$ heroku buildpacks:add https://github.com/heroku/heroku-buildpack-google-chrome
$ heroku buildpacks:add https://github.com/heroku/heroku-buildpack-chromedriver
```

#参考
[HerokuでSeleniumとHeadless Chromeを動かしたい](https://medium.com/shuheiktgws-blog/herokuでseleniumとheadless-chromeを動かしたい-cb164538942e)
Shuhei Kitagawaさんのブログ記事に助けられました。たいへん感謝しています。
エンジニアのスキルアップに大切なマインドセットの話 〜 パラシュート勉強法とメタ学習

# はじめに
最近Qiitaなどで、最先端のエンジニアになるためのスキルセットといった内容の記事をよく見かけますが、どれも素晴らしい内容で、とても刺激になりますよね。

こんなスキルセットを身に付けられたら良いなぁと思いつつ、実際の仕事ではプログラムに触れる機会がないなど、思うようにスキルアップできず悩んでいる方もいらっしゃるのではないかと思います。

そんな方のために、スキルアップのために役立つマインドセットを紹介したいと思います。

# パラシュート勉強法
たとえば仕事や学校で新しいプログラミング言語を使うことになったとき、基礎からコツコツ勉強できると良いですよね。

計画を立てて自律的に勉強できる人は本当に素晴らしいです。

一方で、三日坊主で続かないという人も多いんじゃないでしょうか。私も間違いなく後者のタイプです。

そういう人にオススメなのが__パラシュート勉強法__です。

パラシュート勉強法とは、__必要なことを必要なときに都度学ぶ__という学習スタイルです。

たとえば、手元に参考書があったとしたら、最初から1ページずつ読むのではなくて、__必要なことが書かれているページとその周辺だけを拾い読みする__ようなやり方です。

体系立った知識の習得よりも、まずは__目の前の課題にフォーカスする__やり方とも言えます。

これを繰り返していくと、点と点だった知識が線に、線と線が面になっていき、徐々に体系立った知識の習得につながっていきます。

パラシュート勉強法は、プログラマの界隈では__遅延評価勉強法__とも言われています。

遅延評価勉強法については、けんすうさんの記事がとても分かりやすいです。

[勉強が苦手な人向けの「遅延評価勉強法」](http://blog.livedoor.jp/kensuu/archives/50555054.html)

# やらざるを得ない状況に自分を置く
パラシュート勉強法/遅延評価勉強法にとって重要なのは、__やらざるを得ない状況に自分を置くこと__です。

自分の会社の中で、自分が伸ばしたいスキルに関連するプロジェクトを見つけたら、あなたはラッキーです。マネージャーにジョインできないか聞いてみましょう。

もし会社の中で見つからない場合、周囲の人にいつまでに何をやると宣言してやらざるを得ない状況を作るのも一つのアイディアです。ブログやSNSで宣言するのも良いですね。

# メタ学習
ITの世界は進化が早く、毎年新しいプログラミング言語やフレームワークが登場しますし、一所懸命学んだスキルが数年で陳腐化してしまうこともあります。

日進月歩のIT業界で現役のエンジニアとして活躍し続けるためには、絶えず勉強し続ける必要があります。

そのようなITエンジニアにとって最も重要なスキルは、スキルを身に付けるためのスキル、すなわち__メタ学習のスキル__を磨くことだと思います。

メタ学習というのは、__勉強の仕方を学んでいく__ということです。

もし職場で興味のない仕事を任されたとしても、その中に新しい学びの要素があるのであれば、それはメタ学習のスキルを鍛えるチャンスです。

学習リソースの調べ方や、どういう順番で学べば効率的かを考えたりするのはもちろん、その知識をすでに持っている人にどのように質問すれば効果的な回答が得られるのかを知っていることも、立派なメタ学習のスキルです。

自分に合った勉強法を身に付けて、どんどんスキルを伸ばしていきましょう！
iOSのSwift Packageプロジェクトのテストをコマンドで実行する

# Swift Package

WWDC19 で Swift Package Manager の機能が Xcode に統合されたことが発表され、ついに iOS のライブラリも Swift Package Manager で導入することができるようになりました。

https://developer.apple.com/videos/play/wwdc2019/410
https://developer.apple.com/videos/play/wwdc2019/408

※ beta 版の内容を含むため、以降の内容は今後結果が変わる可能性があります。この投稿は Xcode 11 beta 6 の動作に基づきます。

# Swift Package として作った iOS ライブラリをコマンドでテストしたい
CIサービスなどでテストを動かすために、テストをコマンドで実行したい時があると思います。
今までの SPM プロジェクトであれば、下記のコマンドで実行できました。

```bash
$ swift test
```

しかし、iOS ライブラリを SPM で作った場合は、うまくいかないケースがあります。

上記のコマンドは macOS で動かした場合、 macOS プラットフォームのプロジェクトとして認識されるため、`UIKit` のような macOS では使えないフレームワークを利用している場合、ビルドエラーになってしまいます。

## xcodebuild を使う
Swift Package として作成した iOS のプロジェクトには .xcodeproj ファイルがありませんが、 `xcodebuild` コマンドでテストを動かすことができました。

```bash
$ xcodebuild -scheme <パッケージ名> test -destination "name=iPhone XS" | xcpretty
```

scheme にはパッケージ名を指定します。 `$ xcodebuild -list` で名前を確認できます。

## Bitrise で動かす
現時点では Bitrise はまだ Swift Package を認識してくれませんが、 Bash スクリプトを動かせるので Workflow に Script のステップを追加して、以下のスクリプトを書くとテストを動かせます。 (マニュアルセットアップする必要があります)

```bash
#!/usr/bin/env bash
# fail if any commands fails
set -e
set -o pipefail
# debug log
set -x

rm -rf *.xcodeproj
xcodebuild -scheme <パッケージ名> test -destination "name=iPhone XS" | xcpretty
```

現状ではライブラリを Carthage にも対応させるために .xcodeproj ファイルを `swift package generate-xcodeproj` で作成して、commit しておく必要があります。
しかし .xcodeproj ファイルがあると、 `xcodebuild` コマンドが Swift Package のパッケージ名を認識してくれなくなる問題があるようです。
そのため、 .xcodeproj を一旦削除してから、 `xcodebuild` を動かす必要があります。

# まとめ

iOS の Swift Package プロジェクトでは、 `swift test` ではなく、 `xcodebuild` でテストを動かしましょう。
(今後、 `swift test` でもうまくいくようになりそうな気はしてます)
Wagtailチュートリアル 2 ホームページを始めよう 

#Wagtail チュートリアル 2 
<=[1 Wagtailをインストールしよう](https://qiita.com/tagawahirotaka/items/ae8f0660bc36ab2b3699)
=>[3 バナーを追加しよう(1)](https://qiita.com/tagawahirotaka/items/c28d7277a5f832700bc9)
##ホームページを始めよう

0,1,3,4,6,7

```python:home/models.py

from django.db import models #⓪ モデルをインポート

from wagtail.core.models import Page #⓪ページをインポート
from wagtail.admin.edit_handlers import FieldPanel #④ FieldPanelをインポート


class HomePage(Page):#⓪ページを引数に
    
    templates = "home/home_page.html" #① wagtailtutorial/templates/home/home_page.html
    
    max_count = 1 #⑥ ADD CHILD PAGEを制限

    banner_title = models.CharField(max_length=100, blank=False, null=True) #③ banner_titleを定義

    content_panels = Page.content_panels + [ #④ admin画面にbanner_titleを追加
        FieldPanel("banner_title")
    ]

    class Meta:
    
        #verbose_name = "OH HELLO WORLD" ⑦ ADD CHILD PAGEでの表記
        verbose_name = "Home Page"
        verbose_name_plural = "Home Pages"
```

2,5

```html:wagtailtutorial/templates/home/home_page.html

{% block content %} <!--② base.htmlから引っ張り出す-->
    <!--② Helloworld -->
    {{self.banner_title}} <!--⑤banner_titleを表示-->
{% endblock %}
```

②
<img width="1440" alt="スクリーンショット 2019-08-26 08.12.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/41688388-bcf3-e702-67e4-7d41e53be04e.png">
④
<img width="1440" alt="スクリーンショット 2019-08-26 08.19.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/8300ec4d-b755-3955-06fe-b620c12ce1a7.png">
⑤
<img width="1440" alt="スクリーンショット 2019-08-26 08.21.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/8ff75140-b570-81db-aa63-4db23b75420e.png">
⑦
<img width="1440" alt="スクリーンショット 2019-08-26 08.28.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/e431481e-7345-3f63-e0d5-05a134fd746f.png">
Wagtailチュートリアル 1  Wagtailをインストールしよう

#Wagtailチュートリアル 1
=>[2 ホームページを始めよう](https://qiita.com/tagawahirotaka/items/c0aeca21c01872097d81)
##Wagtailをインストールしよう

```pip install wagtail```
wagtailをインストール

```wagtail start wagtailtutorial```
**wagtailtutorialフォルダ**ができる

```cd wagtailtutorial```
```pipenv shell```
仮想環境を構築する

```pip3 install -r requirements.txt```
おまじない

```python3 manage.py migrate```
マイグレーション

```python3 manage.py createsuperuser```
admin画面

```python3 manage.py runserver```
 http://127.0.0.1:8000/
<img width="1440" alt="スクリーンショット 2019-08-26 07.52.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/26494c89-c35c-6d1c-c82d-39d2cc72d194.png">

 http://127.0.0.1:8000/admin
<img width="1440" alt="スクリーンショット 2019-08-26 07.52.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402245/4b25ef54-5a06-6e76-e560-2d70d8c37d29.png">
【SQL】NULLを別の値に置き換える関数COALESCE関数

文字列や数値を扱う際、NULLが混入しているカラム場合、NULLと文字列を結合するとNULLになり、NULLと任意の数値で四則演算を実行するとNULLとなる。

## 問題設定

| purchase_id<br />character varying(255) | amount<br />integer | discount<br />integer |
| --------------------------------------- | ------------------- | --------------------- |
| 101                                     | 2960                | [null]                |
| 102                                     | 7980                | 1000                  |
| 103                                     | 1680                | [null]                |

上のように、購入額とNULLを含む値引き額が格納されているデータ列から、値引き後の売り上げ金額を求める。

## COALESCE関数

NULL値でない最初の引数を返す

`COALESCE(a, b)`: aがNULLのときbを返す。aがNULLでないときaを返す。

例

```sql
SELECT
	a
	, COALESCE(a, 0)
FROM
	fic_table
;
```

実行結果

| a      | COALESCE(a, 0) |
| ------ | -------------- |
| 1      | 1              |
| [null] | 0              |
| [null] | 0              |
| 2      | 2              |

aがNULLの箇所には0が、NULLでない個所では同じ値がそのまま入っている。



## クエリ

```sql
SELECT
	purchase_id
	, amount
	, coupon
	, amount - discount AS dis_amount1
	, amount - COALESCE(coupon, 0) AS dis_amount1
FROM
	purchase_log_with_coupon
;
```

実行結果

| purchase_id | amount | discount | dis_amount1 | dis_smount2 |
| ----------- | ------ | -------- | ----------- | ----------- |
| 101         | 2960   | [null]   | [null]      | 2960        |
| 102         | 7980   | 1000     | 6980        | 6980        |
| 103         | 1680   | [null]   | [null]      | 1680        |
初心者によるJavaScriptによる要素生成・削除などの学習

JavaScript側からHTMLに要素を追加します。

html側はbodyが空だったとします。

```JavaScript:main.js
const h1 = document.createElement('h1');
h1.textContent = 'title';
document.body.appendChild(h1);
```
まずはh1を宣言。
そこに文字列titleを入れて、
`appendChild`で追加する。

この`body.appendChild`はbodyの最後に追加するというもの。
bodyの子要素としてappend（追加する）ということですね。

続いてpも入れましょう。

```JavaScript:main.js
const h1 = document.createElement('h1');
h1.textContent = 'title';
document.body.appendChild(h1);

const p = document.createElement('p');
p.textContent = 'text text text text text ';
document.body.appendChild(p);

```
こうすると、pはh1よりもあとに配置される。
(ここにhtmlだとどう出てくるか表示したいのですが、Qiitaのチートシートを見てもよくわかりませんでした）

さらにh1とpの間にh2を追加してみる。
単純にjsファイルのh1とpの間に書くのではなく
指定して差し込む。


```JavaScript:main.js
const h1 = document.createElement('h1');
h1.textContent = 'title';
document.body.appendChild(h1);

const p = document.createElement('p');
p.textContent = 'text text text text text ';
document.body.appendChild(p);

const h2 = document.createElement('h2');
h2.textContent = 'subtitle';
document.body.insertBefore(h2, p);

```
差し込む場合は`insertBefore`を使う。第一引数に追加する要素、第ニ引数に**どこの前に入れるか**を指定する。上記の場合はpの前にh2を入れろということですね。こうすることで、要素をh1,h2,pと並べることができた。
※ちなみにinsertAfterは存在しないらしい


では続いて、h1の後にpのコピーを挿入する。書き方は

```JavaScript:main.js
const h1 = document.createElement('h1');
h1.textContent = 'title';
document.body.appendChild(h1);

const p = document.createElement('p');
p.textContent = 'text text text text text ';
document.body.appendChild(p);

const h2 = document.createElement('h2');
h2.textContent = 'subtitle';
document.body.insertBefore(h2, p);

const copy = p.cloneNode(true);
document.body.insertBefore(copy, h2);

```
`p.cloneNode(true)`とすることでp要素をまるごとコピーできる。
挿入場所はh1の後なので、h2の前、つまり`insertBefore(copy, h2);`とする。

ちなみにこれを`p.cloneNode(false)`にすると、pの中身（子要素）はコピーせずにp要素だけコピーする。（ここだと`<p></p>`となる）中身は別のものを用意して側だけ流用したい時に使ったりします。


では続いて要素の削除です。要素の削除は親要素から指定する。

```JavaScript:main.js
document.body.removeChild(h2);
```
こうすることで、bodyの中の子要素（h2）を削除する、ということになる。
【Git】あなたが知らない新コマンドswitch/restoreの世界にご招待

## はじめに
先日Gitのバージョン2.23がリリースされました。
そして、そのリリースの中で試験的に新コマンド `switch` と `restore` が導入されることが発表されました。

導入の背景として、`checkout` コマンドを分離することで、よりわかりやすくする狙いがあるようです。

御存じのとおり、これまで`checkout`には「ブランチの切り替え作業」と「作業ツリーのファイルの復元」の2つの役割がありましたが、
今回のリリースで、それぞれの役割を`switch` と `restore`に持たせる形になります。

というわけで、実際に新しく導入されたこれらのコマンドをいじってみました。

## Gitのアップデート
一応Windows向けにGitのアップデート方法を載せておきますので、不要な方は飛ばしてください。

アップデートといっても単純で、下記のように`git update-git-for-windows`と入力し、`y`を押すだけです。

```console
$ git update-git-for-windows
Git for Windows 2.18.0.windows.1 (64bit)
Update 2.23.0.windows.1 is available
Download and install Git for Windows 2.23.0 [N/y]? y
```

少し待つと、初回にインストールしたときと同様にウィンドウが開くので、インストール作業を進めていけば完了です。

![20190824_102458.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239294/fc13dd6e-ab14-c69c-972d-bc2afd2c2d65.jpeg)

`git version` と叩き、下記のように2.23となっていれば、準備完了です。

```console
$ git version
git version 2.23.0.windows.1
```

## switchコマンド
さて、本題の新コマンドです。

まず、新しくローカルにブランチを作成する際には今までですと`git checkout -b hogehoge`としていました。

これを新コマンドを用いるとこのようになります。

```console
$ git switch -c hogehoge
```

checkoutがswitchに変わり、-bが-cに変わります。
ちなみに-cは--createの略です。

また、作業するブランチを切り替える時ですが、
今まで`git checkout master` としていましたが

```console
$ git switch master
```

とすれば切り替えることができます。

## restoreコマンド

今まで自分はローカルで行ったコミット前の修正を取り消す際に、` git checkout .` や `git checkout hogehoge`といった形でcheckoutコマンドを使用してきました。

予想がついているとは思いますが、これらをrestoreコマンドで行うと、下記のようになります。

```console
$ git restore .
$ git restore hogehoge
```

こちらも単純にcheckoutをrestoreに置き換えるだけです。

## おわりに
自分が最初にcheckoutコマンドに出会った際は、上述したように複数の使い方があるコマンドであり、わかりにくいと感じましたし、checkoutという単語のイメージも今でもあまりピンときていません。(もしかして私だけ...?)

それに対して今回の新コマンドは直観的でわかりやすくなったように感じています。

なんども書いていますがこれらのコマンドは試験的に導入とのことなので、今後どうなるかに注目していきたいと思います。

なお、バージョン2.23では今までどおりcheckoutコマンドを用いることも可能ですので、気軽にGitをアップデートし、本番では今までどおりcheckoutを用い、遊びで新コマンドに触れてみるということも可能です。

今回記事においては基礎的な動作しか試していませんが、その他細かい仕様が記載されているドキュメントを参考文献として載せておきますので、他の操作が気になる方はぜひ試しに触れてみてください。

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

## 参考文献
リリース内容の概要(日本語)
https://mag.osdn.jp/19/08/19/183000

リリース内容のもう少し詳しい概要(英語)
https://github.blog/2019-08-16-highlights-from-git-2-23/

switchコマンドのドキュメント
https://git-scm.com/docs/git-switch/2.23.0

restoreコマンドのドキュメント
https://git-scm.com/docs/git-restore/2.23.0
初心者によるJavascriptによるDOMクラス属性操作の学習

JavaScriptにおけるクラス属性の操作について

```html:index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>Javascript Basic</title>
    <style>
      .box {
        width: 100px;
        height: 100px;
        background:gray
      }
      .border-pink {
        border-bottom:5px solid pink;
      }
    </style>
  </head>
  <body>
    <div class="box"></div>
    <script src="js/main.js"></script>
  </body>
</html>

```

上記において、'box'クラスにboreder-pink追加したい。
JavaScript側から操作する方法は


```JavaScript:main.js
const div = document.querySelector('div');

div.className = 'boreder-pink';
```
としてしまいがちだが、これは間違い。
classNameだと最終的に形成されるクラス属性になるので、
これだと`<div class="border-pink">`だけになっていまう。
したがって

```JavaScript:main.js
div.className = 'box boreder-pink';
```
とする。
ただこれだといちいち元のクラスを調べてこないといけないので、`classList`を使う。

```JavaScript:main.js
div.classList.add('border-pink'); //追加
div.classList.remove('box'); //削除
div.classList.contains('box'); //あるか検索 true,falseで返す
```
とする。
ちなみにcontainsとifで、よく見かけるあったら削除、なかったら追加ができる。

```JavaScript:main.js
if (div.classList.contains('border-pink')) {
  div.classList.remove('border-pink');
} else {
  div.classList.add('border-pink');
}
```
ただしこれは

```JavaScript:main.js
div.classList.toggle('border-pink');
```
にまとめることができる。
ROS講座100 Moveitでサンプルを動かす

# 環境
この記事は以下の環境で動いています。

| 項目 | 値 |
|:-:|:-:|
| CPU | Core i5-8250U |
| Ubuntu | 16.04 |
| ROS | Kinetic |

インストールについては[ROS講座02 インストール](https://qiita.com/srs/items/e0e0a9dc3f94c2d3348e)を参照してください。
またこの記事のプログラムはgithubにアップロードされています。[ROS講座11 gitリポジトリ](https://qiita.com/srs/items/25a56a6abda41dcf396e)を参照してください。

# 概要
アームロボット（多関節ロボット）の主なタスクとしてアームの先端を特定の姿勢にするというタスクがあります。これをやるためにはIK（逆運動学）と軌道計画の2つのタスクを行う必要があります。しかしこれらは、高度な数学的な知識が必要なために実装は大変面倒です。ROSではこれらの処理はMoveitというライブラリが担っています。
今回はcrane_plusというアーム用のrosパッケージをcloneしてsim上で動かしてみます。

## アームの制御とは
ここでのアームの制御の目的はゴール地点のposeを指定することでアームの先端をその場所に移動させることです。分解するとこれは2つのタスクに分かれます。

* 目的のposeになるための各関節の角度を求める作業（IK:逆運動学）
* 現在の関節角度から上記で求めた角度に変化するための角度の変化のさせ方を計算する作業（起動生成）

## 今回の目的
crane+というturtlebot2用のアーム（現在ではもう売っていない？）のコントロール用のパッケージであるcrane_plus_armを使ってmoveitによるアームの制御を体験してみます。

# install
moveit関連のパッケージをインストールします。

```shell:インストール
sudo apt install ros-kinetic-moveit
sudo apt install ros-kinetic-moveit-ros-visualization 
```

# サンプルの実行

## ダウンロードとコンパイル

```shell
cd ~/catkin_ws/src/
git clone https://github.com/gbiggs/crane_plus_arm.git
cd ~/catkin_ws/
catkin_make
```

## 実行1
moveitそのものだけを動かすデモlaunchを起動します。

```shell
roslaunch crane_plus_moveit_config demo.launch 
```

インタラクティブマーカーをドラッグすると先端をその位置に持ってくるための姿勢が計算されます。
![cp1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/37125e73-0ef9-bb1d-f381-425498c728b3.gif)

Plan and Executeを押すと開始点から目標点まで移動する軌跡が計算されます。
（表示がうるさいのでrviz左上のdisplayパネルのMotionPlanning->Planning Path->Loop Animationをoffにするのをお勧めします。）
![cp2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/a61d943e-9785-f696-09d1-c167b59fcc60.gif)

## 実行2
より実機に近い状態で動かします。実機の代わりのgazebo上のアームをmoveitで操作します。ターミナルを3つ開きます。

```shell:gazeboシミュレーターの起動
roslaunch crane_plus_simulation simulation.launch
```

```shell:moveit本体の起動
roslaunch crane_plus_moveit_config move_group.launch
```

```shell:moveitのGUI(rvizプラグイン)の起動
roslaunch crane_plus_moveit_config moveit_rviz.launch config:=true
```

上記の実行1と同様に操作を行えます。
![cp3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/694952ea-2fca-f84f-c744-e90d4859c197.gif)

# 参考
[crane+リポジトリ](https://github.com/gbiggs/crane_plus_arm)
[moveitの使い方](https://gbiggs.github.io/ros_moveit_rsj_tutorial/manipulators_and_moveit.html)

# 目次ページへのリンク
[ROS講座の目次へのリンク](https://qiita.com/srs/items/5f44440afea0eb616b4a)
【Unity】オブジェクトが自分より前か後か判定する (追記あり)

# 加速リングを作りたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307985/38683d1d-c172-aa1e-68c8-63c653beead6.png)
プレイヤーが中を通ると加速する「加速リング」を作ろうと思いました。
後ろから入ると前に飛び、前から入ると後ろに飛ぶ仕様です。
その仕様から、プレイヤーが加速リングより前にいるか否かを判定する必要があります。

# 後ろ前をどうやって判定するか
プレイヤーを加速リングの子にして、プレイヤーの localPosition.z を見ることで、プレイヤーが加速リングより前にいるか否かを判定できます。

```C#:Ring.cs
    private void OnTriggerEnter(Collider other)
    {
        Player player = other.GetComponent<Player>();
        if (!player) return;

        Transform playerParent = player.transform.parent;
        player.gameObject.transform.SetParent(transform);
        if (player.transform.localPosition.z <= 0) player.RingAction(transform.forward);
        elss player.RingAction(-transform.forward);
        player.gameObject.transform.SetParent(playerParent);
    }
```

### 加速リングの処理の流れ
1. プレイヤー以外を無視する処理
2. プレイヤーの親を記録する
3. プレイヤーの親を自分(加速リング)に変更させる
4. プレイヤーのローカルZ座標の値から飛ばす方向を分岐
5. プレイヤーの親を元に戻す

#追記 ( InverseTransformPoint を使う方法)
フツララさん ([Twitter](https://twitter.com/yasukiwatanabe)) に教えていただいた [InverseTransformPoint](https://docs.unity3d.com/jp/460/ScriptReference/Transform.InverseTransformPoint.html) 関数を利用して、より簡潔に書けました。

```C#:Ring.cs
        if (player.transform.InverseTransformPoint(transform.position).z <= 0) player.RingAction(transform.forward);
        else player.RingAction(-transform.forward);
```

#追記 ( Vector3.Dot を使う方法)
リームさん ([Twitter](https://twitter.com/LittleMtMachine)) に教えていただいた [Vector3.Dot](https://docs.unity3d.com/jp/460/ScriptReference/Vector3.Dot.html) 関数を利用しても実装できました。

```C#:Ring.cs
        if (Vector3.Dot((player.transform.position - transform.position).normalized, transform.forward) <= 0) player.RingAction(transform.forward, time, speedRate);
        else player.RingAction(-transform.forward, time, speedRate);
```
Cloud Functions for Firebaseのcronみたいな定期実行を試したら簡単だった

FirebaseのFunctionsがスケジューリングできるようになったらしい( ﾟдﾟ)!
cronみたいに定期実行したりできる様になったので試してみた。

- [The Firebase Blog: Scheduling Cloud Functions for Firebase (cron)](https://firebase.googleblog.com/2019/04/schedule-cloud-functions-firebase-cron.html)


### 注意: 有料Blazeプランの機能。3つまで無料

[公式ドキュメント](https://firebase.google.com/docs/functions/schedule-functions)に記載が。

- Blazeの料金プランが適用されている必要があります。
- の各ジョブのコストは月額 $0.10（USD）であり、
- **Googleアカウントごと**に3つのジョブを無料で使用できる

**無料枠はプロジェクトごとではないので注意...**


### コードサンプル

こんな感じでできるらしい。日本時間で毎日0:00に定期実行する例。

```javascript
exports.scheduledFunctionCrontab = functions.pubsub.schedule('0 0 * * *')
  .timeZone('Asia/Tokyo') // Users can choose timezone - default is America/Los_Angeles
  .onRun((context) => {
  console.log('This will be run every day at 11:05 AM Eastern!');
});
```

1. `functions.pubsub.schedule()`を使う
2. `schedule('5 11 * * *')`の部分は、実行スケジュールを書く。
   - 公式ドキュメントの[ここ](https://cloud.google.com/appengine/docs/standard/python/config/cronref#schedule_format)を参照。
   - cronの記法も使える。(「分(0-59)」「時(0-23)」「日(1-31)」「月(1-12)」「曜日(0-7 (0または7は日曜日）)」)
3. `.timeZone('America/New_York')`の部分は、タイムゾーンを書く。
   - 値は[ここ](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)を参照


以上!!
Firebaseだけで定期実行も簡単になってる...(´ω｀)

# こんなのつくってます

最近、積読用の読書管理アプリ「積読ハウマッチ」をリリースしました!

[積読ハウマッチ](https://tsundoku.site)は、Nuxt.js+Firebaseで開発してます!

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/478782/572d4947-f40b-e4dc-1c9c-bc584cd2a66c.png" width="25%"/>

もしよかったら、遊んでみてくださいヽ(=´▽`=)ﾉ

要望・感想・アドバイスなどあれば、
公式アカウント([@MemoryLoverz](https://twitter.com/MemoryLoverz))や開発者([@kira_puka](https://twitter.com/kira_puka))まで。


# 参考にしたサイト
- [関数のスケジュール設定  |  Firebase](https://firebase.google.com/docs/functions/schedule-functions)
- [cron.yaml リファレンス  |  Python の App Engine スタンダード環境  |  Google Cloud](https://cloud.google.com/appengine/docs/standard/python/config/cronref)
- [List of tz database time zones - Wikipedia](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)
BEMについて

## はじめに
HTML, CSSでの設計方法の一つとして`BEM`という設計思想があります。昔勉強で作ったページも添えて記事にまとめます。


## BEMとは
- BEMとは、`Block`、`Element`、`Modifier`という3つの概念に沿って設計する手段です。
- BEMでは、クラス名とするBlock、Element、Modifierの単語を`-`や`_`、`__`で区切ることが特徴です。これを`セパレート`と呼びます。


### Block: 塊
- 単体で独立して動作します。
- BlockとElementの区切りは、「Block__Element」のように、アンダースコア2つで接続します。

### Element: 要素
- Blockの中の要素として使います。
- Modifierとの区切りは、「Element--Modifier」のように、ハイフン2つで接続します。



### Modifier: 修飾語（状態、変化）
- 名前（key）や値（value）の役割を持ち、BlockやElementから派生させたい場合に使います。
- Block（またはElement）とModifierとの区切りと、Modifierの区切りは、「Block_Modifier(key)
_Modifier(value)」または「Element_Modifier(key)_Modifier(value)」のように、区切り文字にアンダースコアを1つ使用します。



## メリット
- コーディングルールが明確なので、命名に悩む時間が短縮されます。
- コーディングルールに沿っているので可読性が上がります。
- クラス名の重複を防ぎやすくなります。
- 長期的や大規模なプロジェクト、複数人での開発に向いています。
- コードの再利用性が上がります。


## デメリット
- 必然的にクラス名が長くなってしまう。
- 慣れるまでの学習コストがかかります。


## 練習用として作ったページはこちら
[takumiwada129/Practice-HTML-CSS](https://github.com/takumiwada129/Practice-HTML-CSS)


## 感想
ご指摘等あればぜひよろしくお願いします。

## 参考にした記事
- [BEMという命名規則とSass 3.3の新しい記法](http://blog.ruedap.com/2013/10/29/block-element-modifier)
- [「BEM」+「Sass」でスッキリ見やすいスタイリッシュなスタイルを書いてみたい BEM[基礎編]](https://www.genius-web.co.jp/blog/cat-117/bem1.html)
- [BEM という命名規則](http://snagimo.com/bem)
- [BEMによるフロントエンドの設計 第1回 基本概念とルール](https://app.codegrid.net/entry/bem-basic-1)
- [一番詳しいCSS設計規則BEMのマニュアル](https://qiita.com/Takuan_Oishii/items/0f0d2c5dc33a9b2d9cb1)
- [BEMを参考にしたCSS設計](https://qiita.com/mrd-takahashi/items/07dc3b4bad027daa2884)
- [CSS設計 BEMを使うとき](https://qiita.com/ko8@github/items/d237318b76f6ffa7f61d)
OAuth2.0の認可サーバーを理解する〜フロー編①〜

# はじめに

この記事はOAuth2.0の認可サーバーを理解することを目的にしています。
前回の[動作理解編](https://qiita.com/rocinante-ein/items/54f345f798ae4a8070cb)に引き続き、OAuth2.0のフローについてまとめていきたいと思います。

- [x] [動作理解編](https://qiita.com/rocinante-ein/items/54f345f798ae4a8070cb)
- [ ] フロー編 ← 今回ここ
- [ ] セキュリティ編
- [ ] 設計編
- [ ] 実装編

# OAuth2.0の認可フロー

OAuth2.0の認可サーバーの主な仕事はリソースオーナーの認証・認可の後に**アクセストークン**を**クライアントアプリケーション**に渡すことです。
今回説明する**「フロー」**は、アクセストークンをクライアントに渡すために用意された複数の手順（フロー）です。
RFC6749では**「4.Obtaining Authorization（認可の取得）」**として記述されている箇所になります。説明するフローは以下の４つです。

* 認可コード処理フロー → ①で説明
* インプリシットグラントフロー → ②で説明
* リソースオーナーパスワードクレデンシャルフロー → ②で説明
* クライアントクレデンシャルフロー → ②で説明

それではこの記事では認可コード処理フローについて見ていきたいと思います。

# 認可コード処理フロー

認可コード処理フローはOAuth2.0の最も基本的なフローです。
認可コード処理フローを用いたアクセストークン取得までのシーケンス図は以下のとおりです。

<img width="1057" alt="OAuth_Authorization_Code_Flow_Sequence.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377704/b4e8adbf-bd87-c066-c170-ae7c8de68084.png">

## 認可コード処理フローの概要
認可コード処理フローでは、認可サーバーから直接ユーザーエージェントにアクセストークンを発行するのではなく、**認可コード（authorization_code）**というアクセストークンとの引き換えチケットを発行します。
この認可コード（authorization_code）と、クライアントの認証情報（client_id、client_secret）を提示できた場合にアクセストークンおよびリフレッシュトークンを発行します。

認可コードフローではクライアントの認証情報（client_secret）を秘匿にする必要があり、これを秘匿にできないJavaScriptのみで完結したアプリケーションではclient_secretを用いた認可コードフローは使用できません。

**ただし**、本来**パブリッククライアント（ブラウザベースのJavaScriptアプリケーション等）**向けに用意されたインプリシットグラントフローが、アクセストークン傍受にかかる攻撃を受けやすいことから、それに対応するべく認証情報を秘匿に保てない場合でも認可コードフローが行える仕組みもあります。（RFC7636）
それについてはセキュリティ編で触れていきたいと思います。

## 認可コード処理フローのメリット・デメリット
### メリット
1. 利用者はユーザーエージェント（ブラウザ）上の操作のみで連携処理が行える
2. ユーザーエージェントにアクセストークンを保持する必要が無いため、セキュリティが高い
3. 安全に情報が保持できるため、有効期間が長いリフレッシュトークンを使っていても安心

### デメリット
1. クライアントの認証情報を秘匿に扱えるクライアントでなければ使用できない（一部除く）
2. 基本的にはリソースオーナーがリアルタイムで認証情報を入力する必要がある

## 認可コード処理フローにおける認可サーバーの仕事
ここまではOAuth自体の説明でしたが、この記事の目的である認可サーバーの動作について触れていきたいと思います。

<img width="1057" alt="OAuth_Authorization_Code_Flow_Sequence.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377704/b4e8adbf-bd87-c066-c170-ae7c8de68084.png">

認可サーバーが用意するエンドポイントとしてRFC6479で定義されている「認可エンドポイント」「トークンエンドポイント」に加えて、RFC6749では仕様の範囲外としている「リソースオーナーの認証エンドポイント」を含めた以下3つのエンドポイントを実装する必要があります。

1. 認可エンドポイント
2. リソースオーナー認証エンドポイント
3. トークンエンドポイント

それでは各エンドポイントについて、簡単に処理内容をまとめていきたいと思います。

### 認可エンドポイント
1. リクエスト内容がRFC6749の「4.1.1.  認可リクエスト」に沿っているか精査を行う
2. 精査結果が正しい場合はログイン画面をユーザーエージェントに返却する
3. 精査結果が正しいくない場合はエラーを返却する

### リソースオーナー認証エンドポイント
1. 認証情報が正しいか精査を行う
2. 認証情報が正しい場合はユーザーエージェントに「redirect_uri」で指定されたURIへのリダイレクト命令を返却する
3. 認証情報が正しくない場合は再度認証画面を表示する

### トークンエンドポイント
1. リクエスト内容がRFC6749の「4.1.3.  アクセストークンリクエスト」に沿っているか精査を行う
2. 精査結果が正しい場合はアクセストークン・リフレッシュトークンを返却する
3. 精査結果が正しくない場合はエラーレンスポンスを返却する


# まとめ
- アクセストークンを取得するフローは基本的に４つ
- 認可コード処理フローはOAuth2.0の中でも基本的なフロー
- 認可サーバーでは３つのエンドポイントを実装する必要がある

次の記事では残り３つのフローについて触れていきたいと思います。
Retrofit+CoroutineのJake神ライブラリが非推奨になっていた

今までRetrofit+Coroutineで通信処理を書く際には、jake神が作ってくださったライブラリを使っていた方が多いと思います。
> https://github.com/JakeWharton/retrofit2-kotlin-coroutines-adapter

# 非推奨
すでに非推奨になって3ヶ月ほど経っていました。
なので、自分が知らなかっただけで既にQitiaの記事にあるかもしれません。。。。

非推奨の旨がReadmeに書いてあって

> Kotlin Coroutine Adapter (DEPRECATED)
> A Retrofit 2 CallAdapter.Factory for Kotlin coroutine's Deferred.

> This library is deprecated. Please migrate to Retrofit 2.6.0 or newer and its > > built-in suspend support

バージョン2.6.0以降のRetrofit側で対応したので、
そちらの機能を使うように案内があります。

それを使うことによって、今までの

```kotlin
@GET("users/{id}")
fun user(@Path("id") id: Long): Deferred<User>
```

から


```kotlin
@GET("users/{id}")
suspend fun user(@Path("id") id: Long): User
```

とsuspend関数を使う形になります。

# 理由?

> #### RetrofitのKotlin Coroutine Adapterにひそむ罠
> https://qiita.com/kafumi/items/e8b9a74b59e00d5e2f3a

上の記事で知ったのですが、jake神のライブラリはsuspend関数でないものに、無理してcoroutine対応を入れていたため、通信を行なっているCoroutineScopeが、呼び出し元と親子関係のないものになっていたそうです。
そのため、通信処理でエラーが発生した場合に、正しくエラーを伝播できない問題がありました。(本人がissueで匙を投げていた模様)

なので特に理由がない場合、早めに置き換えた方が良いと思います。
続かない理由

## 何かにつけて言い訳をしている

言い訳すればやらなくていいので楽

## 現状を見ていない

過去や他人にとらわれている

## 理想を決めてない

行き先の無いお化けのようにさまよい続けている

## アウトラインがない

細部の完璧だけを求めている

## 段階がない

一気にスターになれると思っている

## ハードルが高い

再現性の無いことに手を伸ばして勝手に絶望する

## ハードルが低い

再現性の高いことをいつまでもやっている
FuelというAndroidのHTTPクライアントを使う時の最低限の依存関係の設定

# はじめに
最近 Fuel というライブラリを使った際に依存関係の設定でつまるところがあったので、備忘録のためにこちらの記事に残したいと思います。

#そもそもFuelとは何なのか
[kittinunf/fuel](https://github.com/kittinunf/fuel)
>The easiest HTTP networking library for Kotlin/Android.

Kotlin/Androidのためのもっとも簡単なHTTPクライアントです。
下記のようによく使用しているJSONパーサーのライブラリもサポートしているようです。
サポートされているものは各パッケージに分割されているので、必要なものを入れるみたいです。

| Package | Description |
|:--|:--|
| [fuel-android](https://github.com/kittinunf/fuel/tree/master/fuel-android) | Android: Automatically invoke handler on Main Thread when using Android Module |
| [fuel-coroutines](https://github.com/kittinunf/fuel/tree/master/fuel-coroutines) | KotlinX: Execution with coroutines |
| [fuel-forge](https://github.com/kittinunf/fuel/tree/master/fuel-forge) | Deserialization: Forge |
| [fuel-gson](https://github.com/kittinunf/fuel/tree/master/fuel-gson) | (De)serialization: Gson |
| [fuel-jackson](https://github.com/kittinunf/fuel/tree/master/fuel-jackson) | Deserialization: Jackson |
| [fuel-json](https://github.com/kittinunf/fuel/tree/master/fuel-json) | Deserialization: Json |
| [fuel-kotlinx-serialization](https://github.com/kittinunf/fuel/tree/master/fuel-kotlinx-serialization) | (De)serialization: KotlinX Serialization |
| [fuel-livedata](https://github.com/kittinunf/fuel/tree/master/fuel-livedata) | Android Architectures: Responses as LiveData |
| [fuel-moshi](https://github.com/kittinunf/fuel/tree/master/fuel-moshi) | Deserialization: Moshi |
| [fuel-reactor](https://github.com/kittinunf/fuel/tree/master/fuel-reactor) | Reactive Programming: Responses as Mono (Project Reactor 3.x) |
| [fuel-rxjava](https://github.com/kittinunf/fuel/tree/master/fuel-rxjava) | Reactive Programming: Responses as Single (RxJava 2.x) |
| [fuel-stetho](https://github.com/kittinunf/fuel/tree/master/fuel-stetho) | Utility: Debug utility for Android on Chrome Developer Tools, Stetho |

# Gradleの依存関係 (2019/11/02編集)
```gradle
implementation 'com.github.kittinunf.fuel:fuel:2.2.0'
implementation 'com.github.kittinunf.fuel:fuel-moshi:2.2.0'
implementation 'com.github.kittinunf.fuel:fuel-android:2.2.0'
```

上記が必要最低限 Fuel を使用する際に設定する項目かと思います！
ちなみに自分は Kotlin を使う際は相性の良い Moshi を使用しています。
下記に Maven リポジトリを載せておきます。
[fuel-android](https://mvnrepository.com/artifact/com.github.kittinunf.fuel/fuel-android?repo=springio-libs-release)
[fuel-moshi](https://mvnrepository.com/artifact/com.github.kittinunf.fuel/fuel-moshi)

# 最後に
とても簡単に通信処理を書くことができる Fuel は案件でも使用してみたいと思います。
見ていただきありがとうございます！
全く今更だが、忘れていたので忘備録するLetsEncrypt（Certbot）on CnetOS6

## 以前に設定して、書いておかなきゃって思ってたら忘れてた。

また忘れるだろうから書いておこう。

## Let's Encrypt 総合ポータル

* https://free-ssl.jp/

お世話になります。
よろしお願いいたします。

CentOS6 についてはここ見てね。とのこと。了解です。
→ https://free-ssl.jp/usage/install-certbot.html#CentOS6

## epel-release を有効にする...とな？

この後のインストールで自動であれこれするのにリポジトリの設定でenabledにしなければいけないようですね。
無効にしている場合は一時的に有効にします。（後で戻す）

``` vim:/etc/yum.repos.d/epel.repo
[epel]
name=Extra Packages for Enterprise Linux 6 - $basearch
#baseurl=http://download.fedoraproject.org/pub/epel/6/$basearch
mirrorlist=https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=$basearch
failovermethod=priority
enabled=0 #ここを1にする
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-6
```
## EpelRelease を有効にしたら CentOS6 はその他のUNIXのインストール方法に従う

* https://free-ssl.jp/usage/install-certbot.html#OtherUNIX
  1. certbotを実行するためのスクリプトをwgetで取得
  1. 実行権限を与える
  3. 実行する

という流れ。
以下コマンドはコピペ。

```txt
# wget https://dl.eff.org/certbot-auto
# chmod a+x certbot-auto
# ./certbot-auto
```

## ポート80番でLISTENしてないと怒られる。よ。

 ~~プロキシしてんだよなぁ。どうすっかな~~

そんなことなかった。
オプションちゃんとあった。

* https://free-ssl.jp/command/

## 更新しようとしたらエラーが出る件 (2020.01.10更新)

```
./certbot-auto renew
```

でコケる。

調べたらアップデートがあったみたいなのでもういっかいDLしてインストールすればよい。
C++ Library: Armadillo(線形代数ライブラリ)のinstall

C++のライブラリインストールは初心者なのですが，Armadillo (C++ library for linear algebra & scientific computing)のインストールにチャレンジしてみました．
（環境：Ubuntu 16.04.6 LTS）

この[サイト](https://solarianprogrammer.com/2017/03/24/getting-started-armadillo-cpp-linear-algebra-windows-mac-linux/)を参考に進めます．

ターミナルにて，まず
sudo apt update
sudo apt upgrade

依存ライブラリ（cmake, LAPACK, BLAS）の設定，
sudo apt install cmake libopenblas-dev liblapack-dev

[Armadillo](http://arma.sourceforge.net/download.html)のサイトからstable versionをダウンロードして，解凍して，解凍したフォルダに移動(cd arma*)して，
cmake .
make
sudo make install
で完了[^1]．

examplesのフォルダに移動して，example1.cppをコンパイル＆実行(./test)．
g++ -std=c++14 example1.cpp -o test -DARMA_DONT_USE_WRAPPER -lopenblas -llapack
とか
g++ -std=c++14 example1.cpp -o test -DARMA_DONT_USE_WRAPPER -lblas -llapack
とか
g++ -std=c++14 example1.cpp -o test -larmadillo
で，コンパイルが無事できました（3つ目は[こちら](https://stackoverflow.com/questions/8978742/armadillo-blas-lapack-linking-error)も参照）．

以上です．お粗末さまでした．

[^1]: Virtual box[^2]を使っているのですが，shared folder内に解凍・上記を実行してもダメでした．なんらかの設定が必要そう．．そういう環境の違いによって，libraryのinstallにいつも連戦連敗してます．．

[^2]: Windowsで開いたNetbeansでの開発を行っています．ですが，どうもNetbeans上からはコンパイルできない．．arma::lapack::getrf ~~ undefined reference to `dgetrf_'なので，一部の関数にリンクできていないようです．[これ](https://stackoverflow.com/questions/10889629/compiling-c-with-armadillo-library-at-neatbeans)も試してみたのですが，
[GCP] GCPサービスを勝手にまとめてみた

# GCPって
Google Cloud Platform。
Googleアカウントがあれば使用でき、世界中に多くのデータセンターを持つGoogleの大規模なインフラをCloudサービスとして提供している。

# 何のメモ
GCPには数多くのサービスがあり、ちょっとまとめてみようと思った。

# どんな時に役立つ？
GCPのこのサービスって何だっけ？どんなんだっけ？と思った時に。
あくまで自分がどんなサービスだったかを思い出すためのメモ。

# サービスの分類
おおまかにはこんな感じ。（一部省略してます）
※2019年8月末時点のもの。
※α版、β版を含む。
https://cloud.google.com/products/?hl=ja よりいろいろ引用してます。

| 分類       |  サービス例    |
|:-----------------|:------------------|
| AIと機械学習   | AutoML,Vision AI,Cloud TPU... |
| API管理 | Apigee Sense,Cloud Healthcare API... |
| コンピューティング | Compute Engine,App Engine,Cloud Functions... |
| データ分析 | BigQuery,Cloud Composer,Cloud Dataflow... |
| データベース | Cloud SQL,Cloud Bigtable,Cloud Spanner... |
| デベロッパーツール | Container Registry,Cloud Build... |
| ハイブリットとマルチクラウド | Anthos,GKE On-Prem... |
| IoT | Cloud IoT Core,Edge TPU |
| 管理ツール | Stackdriver,Monitoring,Private Catalog... |
| メデイアとゲーム | Zync Render,Anvato... |
| 移行 | Cloud Data Transfer,Transfer Application... |
| ネットワーキング | Virtual Private Cloud,Cloud DNS,Cloud NAT... |
| セキュリティ | Cloud Security Scanner,Cloud IAM,Cloud HSM... |
| ストレージ | Cloud Storage,Cloud Firestore... |

# サービスをもう少し深く見てみる
## AIと機械学習
https://qiita.com/risa0320/items/1e0956b497b31bbf3932
## API管理
https://qiita.com/risa0320/items/8a01182a1756278f5f5a
## コンピューティング
https://qiita.com/risa0320/items/ffb532c96b5c823b0a23
## データ分析
https://qiita.com/risa0320/items/ff6aa5ec87c84e14560e
## データベース
https://qiita.com/risa0320/items/6fcec06afd352baaf7fc
## ハイブリットとマルチクラウド
https://qiita.com/risa0320/items/aee08a2cb8efb46fa4ae
## IoT
https://qiita.com/risa0320/items/23683e5a02f115489d3b
## 管理ツール
https://qiita.com/risa0320/items/f1b24a0d7821720e4aeb
## メディアとツール
https://qiita.com/risa0320/items/8ddc5774247df85dd2dd
## 移行
https://qiita.com/risa0320/items/d769af5f2549385738c9
## ネットワーキング
https://qiita.com/risa0320/items/f9e5709f1829a30fa0a8
##セキュリティ
https://qiita.com/risa0320/items/3b14941622b12d205ff3
## ストレージ
https://qiita.com/risa0320/items/ee9e88c54af7b19f361b

# 触ってみる(WIP)
## API管理
### Apigee
https://qiita.com/risa0320/items/ae5361eb753edd7f7cd4

## データ分析
### Cloud Datafolw
https://qiita.com/risa0320/items/b030e79b04b75ae94ae0
[GCP] GCPサービスを勝手にまとめてみた(移行編)

# GCPって
https://qiita.com/risa0320/items/5f34bc9102e575705274

# サービスの分類
おおまかにはこんな感じ。（一部省略してます）
※2019年8月末時点のもの。
※α版、β版を含む。
https://cloud.google.com/products/?hl=ja よりいろいろ引用してます。

| 分類       |  サービス例    |
|:-----------------|:------------------|
| AIと機械学習   | AutoML,Vision AI,Cloud TPU... |
| API管理 | Apigee Sense,Cloud Healthcare API... |
| コンピューティング | Compute Engine,App Engine,Cloud Functions... |
| データ分析 | BigQuery,Cloud Composer,Cloud Dataflow... |
| データベース | Cloud SQL,Cloud Bigtable,Cloud Spanner... |
| デベロッパーツール | Container Registry,Cloud Build... |
| ハイブリットとマルチクラウド | Anthos,GKE On-Prem... |
| IoT | Cloud IoT Core,Edge TPU |
| 管理ツール | Stackdriver,Monitoring,Private Catalog... |
| メデイアとゲーム | Zync Render,Anvato... |
| 移行 | Cloud Data Transfer,Transfer Application... |
| ネットワーキング | Virtual Private Cloud,Cloud DNS,Cloud NAT... |
| セキュリティ | Cloud Security Scanner,Cloud IAM,Cloud HSM... |
| ストレージ | Cloud Storage,Cloud Firestore... |

# サービスをもう少し深く見てみる
## 移行
### Cloud Foundation Toolkit
Google Cloud をすぐに使い始めるのに最適なテンプレート。
> Cloud Foundation Toolkit には、Google Cloud のベスト プラクティスを反映した、Deployment Manager 用と Terraform 用の参照テンプレートが用意されています。これらの既製のテンプレートを使って、Google Cloud で繰り返し使用できるエンタープライズ向けの基盤を迅速に構築できます。そのため、お客様はこの安全な基礎環境でアプリケーションをデプロイすることに集中できます。また、﻿Infrastructure as Code（IaC）を使用すると、ニーズの変化に合わせて基盤を簡単に更新できます。

* Deployment Manager
* Terraform

### Transfer Appliance
データをラックに保存し、キャプチャしてからGoogle Cloudに送信します
> Transfer Applianceは、データセンターにセットアップする安全でラックマウント可能な大容量ストレージサーバーです。データを入力し、データがGoogle Cloud Storageにアップロードされる取り込み場所に発送します。データは自動的に暗号化され、復号化するまで安全です。アプライアンスあたり100TBまたは480TBのraw容量から選択して、データをGoogle Cloudにすばやく移動します。

### Cloud Storage Transfer Service
AWS S3 と Google Cloud Storage など、クラウド ストレージ サービス間でデータを転送します。
> Storage Transfer Service では、オンライン データソースからデータシンクにデータが転送されます。データソースは、Amazon Simple Storage Service（Amazon S3）バケット、HTTP/HTTPS のロケーション、Cloud Storage バケットのいずれかです。データシンク（転送先）は、必ず Cloud Storage バケットです。

gsutil と Storage Transfer Service のどちらを使用するか
→gsutil コマンドライン ツールで、Cloud Storage と他のロケーションの間でデータを転送することもできます。gsutil を使用して Amazon S3 バケットを操作し、データを Amazon S3 から Cloud Storage にデータを転送できますが、このユースケースでは Storage Transfer Service がおすすめです。

* オンプレミスのロケーションからデータを転送する場合は、gsutil を使用します。
* 別のクラウド ストレージ プロバイダからデータを転送する場合は、Storage Transfer Service を使用します。

### BigQuery Data Transfer Service
BigQuery 用のフルマネージド データ インポート サービス。
> BigQuery Data Transfer Service は、あらかじめ設定されたスケジュールに基づき、SaaS アプリケーションから Google BigQuery へのデータの移動を自動化するマネージド サービスです。そのため、1 行もコードを書くことなく分析用のデータ ウェアハウス基盤を構築できます。BigQuery Data Transfer Service は、Google 広告、キャンペーン マネージャー、Google アド マネージャー、YouTube といった Google アプリケーションのソースを最初からサポートしています。BigQuery Data Transfer Service を使用すると、データコネクタにもアクセスでき、Teradata や Amazon S3 から BigQuery にデータを簡単に転送できます。

<特徴>

* 設定が簡単
* 自動アップグレード
* 代表的なアプリケーションへの接続
単体のvueファイルに、後付でvuetifyjsを導入する方法

自作のvueコンポーネントを作って、単体で公開しています。
nuxtとかは使わず、既存のhtmlの中に後付で追加出来るvueコンポーネントです。


そのvueコンポーネントの中に、vuetifyjsを追加する時のメモ。

### 追加でnpm installするモジュール

`npm install --save vuetify @mdi/font sass`

node-sassがあっても、別途sassのインストールが必要。これが無いとスタイルシート関連でエラーが出る

### vueファイルの中でvuetifyjsを有効にする方法

vueファイルの中身はこんな感じ

```
import Vue from "vue";
import Vuetify from 'vuetify';
import { VApp,VBtn } from "vuetify/lib"

Vue.use(Vuetify);// 1
export default Vue.extend({
  vuetify: new Vuetify({}), // 2
  mounted: function () {}
});
```

Vuetifyの指定、1と2の2種類あるけど、**どっちかだけ指定する**のが正しい。
自分の場合、エントリーポイントとなるvueファイルでは2の方法で指定して、実際にVuetifyを使う子vueファイルの中では1の方法で定義した。
どっちも同じ書き方にしたり、エントリーポイントのvueファイルでは不要じゃないかと思って色々試したけど、これ以外の組み合わせではダメだった

### v-appで全体を囲う必要

ボタンみたいな単純なVuetifyエレメントであれば何も考えずに使う事が出来るが、v-menuの様にhtml全体から位置を計算するようなVuetifyエレメントを使う場合は、body直下をv-app要素で囲う必要がある。
既存のhtmlで作られたページにvueコンポーネントを追加する場合はこれが最大のネックになる。というか、この仕様があるから実質不可能と言える。

v-app要素はcssで`min-height: 100vh;`と定義されているので、htmlの中の一部にvueコンポーネントを埋め込む場合、高さが狂ってしまう。

またVuetifyは以下のようなスタイルシートも定義するから既存のhtmlにどうしても影響が出てしまう。

```
html {
    font-size: 16px;
    overflow-x: hidden;
    text-rendering: optimizeLegibility;
}
* {
    background-repeat: no-repeat;
    padding: 0;
    margin: 0;
}
```
考える時間を増やそう！Windowsショートカットキー集

<h2>概要</h2>
今回は業務効率化のために現場で使える以下のショートカットを紹介します。
・Windowsショートカット
・エクスプローラショートカット
・Googleショートカット

<h2>なぜショートカットを使うか</h2>
ショートカットを覚えることによって単調作業の作業スピードが格段に上がります。
エビデンスをまとめたり、設計書を使ったりする作業時間を短縮し、
仕様を考えたり、ロジックを考えたりといった頭をつかって考える仕事に時間が割いていくことができます。

ショートカットになれない人はマウス捨ててみてください。
慣れるまで少し時間がかかるかもですが、慣れたらその後の人生はずっと時間短縮につながりますのでオススメです！

<h2>ショートカット集</h2>
特に使うものだけを厳選してまとめてみました。お役に立てればと思います。

<h3>Windowsショートカット</h3>
|機能|コマンド|
|---|---|
|タスクバーの特定のアプリを開く|Windows + 1　～ Windows + 0|
|アプリを切り替える|Alt + Tab|
|アプリを切り替える(逆)|Alt + Tab + Shift|
|アプリを閉じる|Alt + F4|
|指定したパスに移動|Windows + r|
|ウィンドウの最大化(縮小)|Windows + ↑ (↓)|
|ウィンドウの右寄せ(左寄せ)|Windows + → (←)|
|ウィンドウをモニター側に移動(手元側に移動)|Windows + Shift + →|
|ウィンドウを全て最小化|Windows + d|

<h3>エクスプローラショートカット</h3>
|機能|コマンド|
|---|---|
|エクスプローラを開く|Windows + e|
|前のフォルダーへ戻る|Alt + ←|
|戻る前のフォルダーへ移動|Alt + →|
|親フォルダーへ移動|Alt + ↑|
|ファイル・フォルダ名を変更|F2|
|新しいフォルダを作成|Ctrl + Shift + n|

<h3>Googleショートカット</h3>
|機能|コマンド|
|---|:---:|
|新しいタブを開く|Ctrl + t|
|タブを閉じる|Ctrl + w|
|タブを1つ移動|Ctrl + Fn(ファンクションキー) + ↓|
|タブを1つ移動(逆)|Ctrl + Fn(ファンクションキー) + ↑|
|特定のタブに移動|Ctrl + 1 ～ Ctrl + 8|
|検索バーに移動|Ctrl + l (エル)|
|戻る|Alt + ←|
|進む|Alt + →|
|ブックマークバーに移動|Shift + Alt + b|

Googleでは「google検索キーボードショートカット」の拡張機能がお勧めです。
Googleでの検索画面をキーボードを選択することができます。(マウスいらずでリンクを踏める)
https://chrome.google.com/webstore/detail/google-search-results-sho/dchaandmcifgjemlhiekookpgjmkcelg?hl=ja

<h2>まとめ</h2>
というわけで特に使うショートカットをまとめました。
次回はExcelショートカットをまとめていこうと思います。
それでは！

Excelアクセスキー集はこちら
https://qiita.com/harumaki_dayo/items/9524ea2de0a7934b9a87

![ショートカット.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402218/7a27b6d8-ff66-3f4e-5801-dc7bc31265c3.jpeg)
【RubyonRails入門】生成したコードを元に戻す方法

忘備録です。

##1.コントローラの自動生成と、それに対応する取り消し処理の例

```
 $ rails generate controller StaticPages home help
=> StaticPagesの home,helpアクションを作成

 $ rails destroy  controller StaticPages home help
=> StaticPagesの home,helpアクションを削除
```

##2.モデルの自動生成と、それに対応する取り消し処理の例

```
$ rails generate model User name:string email:string
=> Userモデルに、name,emailカラムを追加

$ rails destroy model User
=> Userモデルを削除
```

##3.マイグレーションの変更を元に戻す

```
$ rails db:migrate
=> migrationする

$ rails db:rollback
=> migrationしたものを、1つ前の状態に戻す

$ rails db:migrate VERSION=0
=> 最初の状態に戻す
```
【Unity】シーンの読み込みイベントをIObservableにする【UniRx】

# はじめに
`SceneManager.sceneLoaded`を`IObservable`にしようと思ったら型パズルで苦戦したのでメモ[^1]。

# コード
```ObservableSceneEvent.cs
using System;
using UnityEngine.Events;
using UnityEngine.SceneManagement;

namespace UniRx
{
    public static class ObservableSceneEvent
    {
        public static IObservable<Tuple<Scene, Scene>> ActiveSceneChangedAsObservable()
        {
            return Observable.FromEvent<UnityAction<Scene, Scene>, Tuple<Scene, Scene>>(
                h => (x, y) => h(Tuple.Create(x, y)),
                h => SceneManager.activeSceneChanged += h,
                h => SceneManager.activeSceneChanged -= h
            );
        }

        public static IObservable<Tuple<Scene, LoadSceneMode>> SceneLoadedAsObservable()
        {
            return Observable.FromEvent<UnityAction<Scene, LoadSceneMode>, Tuple<Scene, LoadSceneMode>>(
                h => (x, y) => h(Tuple.Create(x, y)),
                h => SceneManager.sceneLoaded += h,
                h => SceneManager.sceneLoaded -= h
            );
        }

        public static IObservable<Scene> SceneUnloadedAsObservable()
        {
            return Observable.FromEvent<UnityAction<Scene>, Scene>(
                h => h.Invoke,
                h => SceneManager.sceneUnloaded += h,
                h => SceneManager.sceneUnloaded -= h
            );
        }
    }
}
```

各イベントがstaticなせいで拡張メソッドとして実装できないので、苦肉の策でstaticな`ObservableSceneEvent`クラスを実装。

`SceneManager`を完全にラップする`ObservableSceneManager`クラスの実装も考えたけどUnityのAPIが変わるごとにメンテナンスするのが面倒だったのでこの形に落ち着いた。

C#7以上を使ってる場合は`Tuple`を適当に書き換えてください（参考：[タプル](https://ufcpp.net/study/csharp/datatype/tuples/)）。

# 参考
* [UniRxのObservable.FromEventを使う](https://qiita.com/ShirakawaMaru/items/4071aad0937ecbdc7fe9)
* [Observable.FromEventで引数を受け取りたい場合](https://befool.co.jp/blog/8823-scholar/unirx-from-event-args/)

[^1]: `FromEvent()`はたまにしか書かないので全然覚えられない😂
manコマンドの各セクションまとめ

manコマンドの各セクションの分け方を忘れてしまうのでまとめた.

# manコマンド
manコマンドはマニュアルを表示するためのコマンド.
コマンドのオプションや関数の引数等を確認できて便利.

# セクション
manコマンドで出力されるページはいくつかのセクションに分類されている

|セクション|説明|
|:--|:--|
|1|ユーザコマンド|
|2|システムコール|
|3|ライブラリ関数|
|4|デバイスファイル等|
|5|ファイルフォーマット|
|6|ゲーム|
|7|規格等|
|8|システム管理用コマンド|

# 使い方
例として `printf` を用いる.

##### セクションを指定しない場合
セクション1から順に調べてはじめに見つかったセクションのページを表示する.

```
$ man printf
```

##### セクションを指定する場合
指定したセクションのページを表示する.
下の例の場合, セクション3(ライブラリ関数)における `printf` のページを表示する.

```
$ man 3 printf
```

このようにセクションを指定できるようになっているのは, 複数のセクションのページに同じ名前が存在することがあるため.
例えば `printf` はセクション1(ユーザコマンド)にもセクション3(ライブラリ関数)にも存在する.

# $MANPATH
manコマンドで出力されるページは, 環境変数 `$MANPATH` が指す先にあるファイルを元に作成されている.
`$MANPATH` は `manpath` コマンドで確認できる.

# GNU Info
glibcの一次情報はmanではなくGNU Infoと呼ばれるドキュメントのため, manの結果がおかしいと感じた場合はそちらを参照する.

GNU Infoの確認は `info` コマンドを使って確認するか, Webに公開されている情報で確認する.