OmniAICreator/Qiita-1.07M huggingface dataset:
【デイトラ】初級ノートDAY6~DAY7

## ◆悩んだとこ、後から気づいたとこをシェアしていきます。

デイトラをはじめました。
現在中級に入ったところですが、つまずくようになってきたので
初めて復習をしています。

復習にあたって、VSCodeでmarkdownを使ってノートをとるようにしました。
せっかくなので、同じ悩みの方に向けて投稿していきます。

単元を学習した後に読むのが良いと思います。

**わたしも同様に初学者です。内容の正確性を保証することはできません。**
**訂正やより良い情報があればご教授お願いします。**

### ✔この記事で解決できること

- 講義内容と課題の中でわからないことが解決できるかもしれない。
- 調べる時間を短縮できるかもしれない。
- 学習の仕方を効率化できるかもしれない。

---

## DAY6 ゼロから作る ②

### ✔ button タグはインラインブロック

| 違い     | ブロック    | インライン   | インラインブロック |
| -------- | ----------- | ------------ | ------------------ |
| 改行     | 要素の前後  | 入らない     | 入らない           |
| 幅、高さ | 指定できる  | 指定できない | 指定できる         |
| margin   | 上下左右    | 左右のみ     | 上下左右           |
| タグ     | div,h1,p,ul | a,span,input | button             |

私は、インラインブロックが何かはわかりましたが、
どう使い分けるのか未だにわかっていません。
しかし、コードを読むために今のうちに特徴はを覚えた方が良いと思います。

参考サイト
https://www.itra.co.jp/webmedia/what-is-inline-block.html

### ✔ Flexbox

今後必ず使いますので、
可能な限り慣れたほうが良いです。

私は、いざ使う時にどの要素に
display: flex
を記述するのかわからなくなりました。

下記にとても良い練習サイトがあります。

練習サイト
https://flexboxfroggy.com/#ja

参考サイト
https://www.ameamelog.com/css-flex-header/

## DAY7 ゼロから作る③

### ✔ レスポンシブ

max-width = 以下
min-width = 以上
iPadの表示幅は768px

モバイルファーストという記述方法が一般的だそうです。
教材では、PCの表示を作ってからモバイル向けに作っていますが、
まず、モバイル向けに作ってからPC向けに作ることを言うそうです。

メリットは、スマートフォンで見られる可能性がとても高いということ。
そして、スマートフォンで見る場合にPC用の不要なデータまで通信することで、
表示が重くなってしまう可能性があるということです。

個人的なメリットですが、
レスポンシブの記述をする時にどうしても尻込みしていたのが、
軽減されたと思います。

私は、復習する際にモバイル向けに作ってから、
教材のようにPC向けに作るようにしました。
Railsチュートリアル Herokuへのデプロイのエラーを解決したので解決方法をメモ


初めてのqiita投稿です。
Rails-Tutorialの第一章 1.5.2 Herokuへのデプロイでいきなり躓きました。ググってもなかなか解決策が出て来なくて序盤で手こずったので、解決策を覚書。

##◆症状

Rails-Tutorialのテキストの通り進めていったところ、
"git push Heroku main"を行い、無事デプロイまで進んだように見えたが、以下の画面となった。
（本当なら「Hello, World!」と表示されるはずであった。）
![スクリーンショット 2020-10-09 224816.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310158/a9e1ae29-1c09-3aad-7479-e94c4a9069e8.png)

##◆原因
原因は、Heroku上の別のリポジトリへデプロイを行っていたこと。
詳細は分からないけれど、元をたどれば、デプロイ前に一度食事で手を止めたせいで、デプロイ前のherokuコマンド"heroku create"を２回行ってしまっていたことが原因と思われる。

　　デプロイ先　　　　：　１回目に作成したリポジトリ
　　閲覧していたＵＲＬ：　２回目に作成したリポジトリ

上記の通りとなっていた。

##◆解決策
######①閲覧していた2回目に作成したリポジトリに、push先を変更した。（下記コマンドの実行）

```ruby:Terminal
git remote set-url heroku ["heroku create"の実行時にターミナルに表示されるgitのリポジトリ ]
```

######②再度pushの実行

```ruby:Terminal
git push heroku main
```





※Railsチュートリアルには"main"が"master"と記載されているけれど、githubの仕様変更？で、この記事の作成時点（2020年10月9日現在）ではmainで正となっている。

![スクリーンショット 2020-10-09 230523.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310158/e09a1236-f0eb-cf19-0b21-ed94f0e3f7e8.png)


#####_無事画面が表示された。（"hello, world!"じゃなかった。）_
Buildrootでラズパイ上のOBDなLinuxを開発するために必要そうなこと一覧

## ホスト

```
$ sudo apt-get install build-essential 
$ sudo apt-get install ncurses-dev
$ sudo apt-get install flex
$ sudo apt-get install bison
$ sudo apt-get install python
$ sudo apt-get install unzip
```

## menuconfig

```
make raspberrypi3_defconfig
```

でラズパイ３用のデフォルト設定に変更。ちなみに、

```
make list-defconfigs
```

ですべてのリストを見れる。 `raspberrypi3_qt5we` ってなんだ。

後はここを参考に

* ビルド時のキャッシュの有効化
* DHCPサーバからIPを取得できるようにする
* SSHの有効化
* ホスト名でSSHログインできるようにする

## ELM327を使えるようにする

```
make linux-menuconfig
```

をしたら、

```
Device Drivers ->
    USB support -> 
        USB Serial Converter support
            USB_SERIAL_PL2303 (USB Prolific 2303 Single Port Serial Driver)
```

を有効化し、ドライバをイメージに含める。

後はお好きに

設定後はpythonでpython-obdしてみたり、menuconfigからQt5いれてみたり、煮るなり焼くなりご自由に！
千葉県 Go To EATの加盟店一覧をCSVに変換

[千葉県 Go To EAT事業公式サイト](https://www.chiba-gte.jp/user/)の加盟店一覧のPDFをCSVに変換

※10/28現在はPDFがダウンロードできません

```shell
wget https://www.chiba-gte.jp/downloads/store_list.pdf -O data.pdf

apt install python3-tk ghostscript
pip install camelot-py[cv]

# 10/9 ※文字数オーバーの場合隣のセルと結合されています
camelot -p all -o data.csv -f csv -split stream -C 97,116,146,365,500 data.pdf

# 10/10以降
camelot -p all -o data.csv -f csv -split stream -C 18,34,50,305,573 data.pdf
```

# 地図からスクレイピング

x1,x2,y1,y2は緯度経度

```python
import pandas as pd
import requests

url = "https://gotoeat-chiba.liny.jp/map/api/data.json?x1=35.6053372125437&x2=35.62051386759826&y1=140.09609738558348&y2=140.13085881441648"

r = requests.get(url)
data = r.json()

df = pd.json_normalize(data["data"])

df.to_csv("data.csv", encoding="utf_8_sig)
```
Java HashMapクラス

#【Java HashMapクラス】

HashMapは、Javaで開発しているとよく使うので、復習を兼ねてまとめました。

##Map

ListやSet、Queueと異なる要素で管理される。
Mapは、keyとvalueの組み合わせで要素を管理されている。

##HashMap

HashMapは、Mapの実装クラスの中で最も基本的なクラスである。
keyは重複できない。順番を持たない。

##HashMapクラスの主なメソッド

###・int size( )
Mapの要素数を取得

###・clear( )
すべての要素を削除

###・get( Object key )
keyに対応する値を取得

###・keySet( )
すべてのkeyを取得

###・put( key, value )
指定されたkey, valueの組み合わせを追加

###・isEmpty( )
Mapが空かを判定

###・remove( Object key )
指定のkeyを削除

###・Collection<V> values( )
すべてのvalueを取得

###・containsKey( Object key )
keyがMapに含まれているかを判定

###・containsValue( Object value )
valueがMapに含まれているかを判定
GitLab CE(Community Edition)にBasic認証をかける

前提

・GitLab CE導入済み
・httpd-toolsなどで.htpasswdを作成できる

設定方法

```
cat /var/opt/gitlab/nginx/conf/gitlab-http.conf
```

すると、内容が表示されるので

```
  location / {
   proxy_cache off;
   proxy_pass  http://gitlab-workhorse;
 }
```


となっているところに追記する。
具体的には

```
  location / {
   proxy_cache off;
   proxy_pass  http://gitlab-workhorse;
   auth_basic "Restricted";
   auth_basic_user_file /var/opt/gitlab/nginx/conf/.htpasswd;
 }
```

などとする。

上記で指定したディレクトリ

```
/var/opt/gitlab/nginx/conf/
```

にhttpd-toolsやここを使って.htpasswdを作成する。
パーミッションは604。
AWSのUbuntuのEC2でEFSのマウント(amazon-efs-utils)

他のQiitaの記事の言っていることだけではだめだったので備忘録．

EFS (Elastic File System)はファイルサーバとして便利で，[https://docs.aws.amazon.com/ja_jp/efs/latest/ug/mounting-fs.html](https://docs.aws.amazon.com/ja_jp/efs/latest/ug/mounting-fs.html)でいっているようにマウントヘルパーを使うのが便利です．Amazon Linux2のAMIを用いればデフォルトで

```bash
sudo mount -t efs fs-12345678:/ /mnt/efs
```
のようにして簡単にできるのですが，Ubuntuベースなど他のディストリビューションを使うとこれが入っていないのでメモ．

amazon-efs-utilsを入れればいいと公式も言っている([https://docs.aws.amazon.com/ja_jp/efs/latest/ug/installing-other-distro.html](
https://docs.aws.amazon.com/ja_jp/efs/latest/ug/installing-other-distro.html))わけですが，ちょっとだけトラブったのでメモ．


# 結論
`sudo apt update & sudo apt upgrade`が必要．

```bash
sudo apt update
sudo apt upgrade
sudo apt install -y stunnel4
git clone https://github.com/aws/efs-utils
cd efs-utils
sudo apt install -y binutils
./build-deb.sh
sudo apt install -y ./build/amazon-efs-utils*deb
```

# 他の記事で言っていること
`sudo apt install -y stunnel4`しないと

```bash
The following packages have unmet dependencies: amazon-efs-utils : Depends: stunnel4 (>= 4.56) but it is not installable E: Unable to correct problems, you have held broken packages.
```
と怒られる，というのはよく見る．また，エラーをよく見ると

```bash
sudo apt install -y binutils
```
をしなさいというのもわかる．けどこれでもバージョンの依存関係が合わなかった．

ということで，

```bash
sudo apt update
sudo apt upgrade
```

すればokだった．

あとは

```bash
sudo mount -t efs fs-12345678:/ /mnt/efs
```

できる．
テーブルの扱い_『スッキリわかるSQL入門』6~9章

#はじめに
『スッキリわかるSQL入門』5-9章に取り組みました。
7、9章は今はサラッとでokとのことだったので、サラッと読んだだけです。

第二部 SQLを使いこなそう
-第5章：式と関数
-第6章：集計とグループ化
-第7章：副問い合わせ（→サラッと）
-第8章：複数テーブルの結合
第三部 データベースの知識を深めよう
-第9章：トランザクション（→サラッと）



【つまずいたところ】
・「.」を使うのはどんなとき？
・テーブルの別名



#「.」の使い方
##「.」が登場
p246　8章「8.2_テーブルの結合」で、下記のように「.」が登場しました。

>リスト8-4_　図8-3の結合を実現するためのSELECT文
SELECT 日付 , 名前 AS 費目, メモ
FROM 家計簿
JOIN 費目　　　　　　　　　　　　　 　　--結合する他の表を指定
ON 家計簿 .費目ID　＝　費目 .ID　　　　--結合条件を指定

その後も例となる構文の中に何度も登場しました。

p266「8.5.2_この章でできるようになったこと」でも、
下記の通り登場しました。ここでは*とセットで「家計簿.*」として登場しています。

>「給料」という名前の費目に関する、家計簿テーブルの行を見たい。
SELECT 家計簿 .* FROM　家計簿
JOIN (SELECT * FROM 費目 WHERE 名前 = '給料') AS 費目
ON 家計簿 .費目ID = 費目 .ID

思い返せば7章でも「SUB.」という表現がサラッと出てきていました。


##「.」を使うのはどんなとき？
どのテーブルに属する列であるかを示すときです。

p261「8-4_結合に関するさまざまな構文-8.4.1_テーブル名の指定」に

>列名指定の前に「テーブル名.」という表記を加え、どのテーブルに属する列であるかを明示的に指定することができます

という一文がありました。

#テーブルの別名
提示されていないテーブルが、問題に出てきました。
>(p267)8章 練習問題 8-1
次のようなテーブルAとテーブルBがあります。これらを用いて、下のSQL文を実行したときの結果表を記述してください。
(小問4）SELECT A.A1,**C.A2**,B1,B1 FROM A JOIN B ON A.A1 = B.B1 JOIN A AS **C** ON B.B1= **C.A1** 

テーブルA

|A1|A2|
|:--|:--|
|1|3|
|2|4|

テーブルB

|B1|B2|
|:--|:--|
|1|2|
|3|NULL|

問題文にある「C.」に戸惑いました。提示されているテーブルはA、Bのみです。
問題のコードには「C.A2」「C.A1」とあるので、仮にこんなテーブルを用意してみました。

テーブルC

|A1|A2|
|:--|:--|
|NULL|NULL|
|NULL|NULL|

そして問題のコードにあてはめて・・・
後半の「A AS C」がポイントなのでしょうか。

|A.A1|C.A2|B1|B2|
|:--|:--|:--|:--|
|1|3 or NULL|1|2|
↑こうなりました。
解答はこうでした。↓

|A.A1|C.A2|B1|B2|
|:--|:--|:--|:--|
|1|3|1|2|

仮にテーブルCを作ったのは、意味がありませんでしたね。
「C」とは何でしょうか？
Cがあることで、Aを置き換えたりと、ややこしくなります。

「別名」でしょうか。
最初の方に「SELECT A.A1,C.A2,B1,B1 FROM A 」、
最後の方に「JOIN A AS C ON B.B1= C.A1」があります。
コードは前にあるものから適用されると思っていたのですが、
SELECTの中で「AS」は使わないですし、
文の後ろの方で「A AS C」と指定されたら、それがSELECT直後のCにも適用される
ということだと解釈しました。

ちょっと不完全燃焼な気もしますが...
前に進みます。



#おわりに/5~9章の振り返り
5章では関数が何個も出てきました。それぞれの説明を読んでいる時には「ふむふむ」となんとなく納得した気になるのですが、それをいざ使っているところをイメージしようとすると、
例えば
「「CURRENT_DATE」ってどの時点での日付が表示されるのだろう？更新した日なのだろうけど、それがどんな形でどこに表示されるの？ファイルを開くたびに勝手にその日の日付に更新されてしまいそう…。」
等、まだ実際に使っていないからこそわからない部分があり、現段階では「なんとなく、わかった」という感覚です。

dokoQL上ではなく、実際に使って試したいという気持ちがどんどん大きくなっています。

8章では、
『マンガでわかるデータベース』で「正規化」として説明されていた内容が
解説されていました。『スッキリわかるSQL入門』では「正規化」という表現は使われておらず、リレーションシップの説明と共に、データを扱いやすいように「複数テーブルに分ける」という説明がされていました。(p241)
『マンガで~』でもつまずいた「副問い合わせ」「別名」も出てきました。


SQLについては、本書の前に『マンガでわかるデータベース』で簡単な用語や基礎的な文法について学んでいたおかげで、大きくはつまずかずに進めることができました。

たとえば「SELECT」の使い方について、
『マンガで～』は、SELECTを使う前の状態から使う過程、使ったあとの結果までを漫画＆文章で丁寧に解説されていたので、どんな場面で使うのかというイメージができましたし、考え方の流れをざっと理解することができました。
『スッキリ～』は、まず見本の通りにdokoQLにSQL文を入力することで、SELECTを入力することで何が実行できるのかを体感できました。解説もシンプルにまとめられており、文法については、『マンガ~』よりも『スッキリ~』の方が、理解しやすかったです。

SQLを、実際にデータベースを作りながら使ってみたいという気持ちもありますが、ここは焦らずに。
次回からは、次のお題であるAccessに入っていきます。

#参考
・書籍『スッキリわかるSQL入門第2版ドリル222問付き！』（インプレス）

#進捗記録
2020/9/15：データベースの学習スタート
2020/9/15～9/21：『マンガでわかるデータベース』オーム社 / 1～4章（Qiita記事2本）
2020/9/22～10/9：『スッキリわかるSQL入門第2版ドリル222問付き！』インプレス/ 1～9章（Qiita記事3本）
ROS1とROS2の環境変数管理

## ROS環境の設定

Ubuntu上でROS1とROS2の双方を使って開発をすることが多くなり、環境をターミナルで行き来することが多くなったので、各ターミナルでこの環境が読み込まれてるかをわかりやすくしたときの設定のメモ。

最終的にはこんなことができるようになります。
![ros_chdis.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243073/e9ea34f1-b8a6-b1e2-932d-6feb5c2e4f87.gif)

## 環境
本記事では以下で検証しています。

- Ubuntu 20.04
- ROS noetic
- ROS2 foxy

Ubuntu18.04, melodic, eloquentの環境でも可能なはずです。

## 環境を読み込むためのaliasの設定
- bashの場合
  -  `~/.bashrc`か`~/.bash_aliases`などに以下を記載
  -  それぞれ環境の設定ファイルの読み込みや、workspaceへのpath、ROS通信に関わる変数の設定を行っている
  -  それぞれの最後の行にある`PS1`をすることでターミナル上でどちらの環境が読み込まれてるかわかるようになっている。
  -  workspaceへのpathは適宜自分の環境に合わせてください


```bash
## ROS ##
LOCAL_IP=`hostname -I | cut -d' ' -f1`
alias noetic='
    source /opt/ros/noetic/setup.bash;
    export ROS_WORKSPACE=${HOME}/catkin_ws;
    export ROS_PACKAGE_PATH=${ROS_WORKSPACE}/:$ROS_PACKAGE_PATH;
    export ROS_IP=${LOCAL_IP};
    export ROS_MASTER_URI=http://localhost:11311;
    source ${ROS_WORKSPACE}/devel/setup.bash;
    export PS1="\e[1;32m\]\u@\h\e[1;31m\]<noetic>\e[m\]:\e[1;34m\]\w\e[m\]$ "
    '
alias foxy='
    source /opt/ros/foxy/setup.bash;
    export ROS_WORKSPACE=${HOME}/ros2_ws;
    source ${ROS_WORKSPACE}/install/local_setup.bash;
    export ROS_LOCALHOST_ONLY=1;
    export PS1="\e[1;32m\]\u@\h\e[1;33m\]<foxy>\e[m\]:\e[1;34m\]\w\e[m\]$ "
    '
```

- zshの場合
  - bashの場合とほぼ同じです。`~/.zshrc`などに記載してください。
  - 設定ファイルの読み込みファイルの拡張子が変わるだけです。

```zsh
## ROS ##
LOCAL_IP=`hostname -I | cut -d' ' -f1`
alias noetic='
    source /opt/ros/noetic/setup.zsh;
    export ROS_WORKSPACE=${HOME}/catkin_ws;
    export ROS_PACKAGE_PATH=${ROS_WORKSPACE}/:$ROS_PACKAGE_PATH;
    export ROS_IP=${LOCAL_IP};
    export ROS_MASTER_URI=http://localhost:11311;
    source ${ROS_WORKSPACE}/devel/setup.zsh;
    export PS1="%F{red}<noetic> %f"$_LIBERTY" "
    '

alias foxy='
    source /opt/ros/foxy/setup.zsh;
    export ROS_WORKSPACE=${HOME}/ros2_ws;
    source ${ROS_WORKSPACE}/install/local_setup.zsh;
    export ROS_LOCALHOST_ONLY=1;
    export PS1="%F{blue}<foxy> %f"$_LIBERTY" "
    '
```

- 上記を記載後、`source ~/.bashrc`か`source ~/.zshrc`をし変更を読み込みます。(別ターミナル起動でも良いです。)
- ROS１を使いたい場合は`noetic`をROS2を使いたい場合は`foxy`を実行することで環境が読み込まれます。

## それぞれのworkspaceのmake
- 以下を追加することで`ros_make`とすると現在読み込まれている環境のワークスペースをビルドしてくれます
- buildのoptionは適宜変更してください。

```bash
function ros_make() {
    dir=$PWD;
    cd $ROS_WORKSPACE;
    if [[ $ROS_DISTRO == "noetic" ]]; then
        catkin_make --cmake-args -DCMAKE_BUILD_TYPE=Release;
        . devel/setup.zsh;
    elif [[ $ROS_DISTRO == "foxy" ]]; then
        if [ $# -gt 0 ]; then
            colcon build --packages-select $1 --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release;
        else
            colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release;
        fi;
        . install/local_setup.zsh;
    else
        echo "set ros distribution";
    fi
    cd $dir;
}
```


## 参考・関連サイトなど
- https://speakerdeck.com/youtalk/ros-2kai-fa-sheng-chan-xing-xiang-shang-turu
- https://github.com/youtalk/chdistro
- https://hans-robo.hatenablog.com/entry/2020/03/10/121017
Start to Selenium using python

 知り合いからテストツールの色々聞かれて、
Seleniumへ挑戦することになった。

browserの拡張機能を使ってから
# Selenium IDE
https://github.com/SeleniumHQ/selenium-ide

# Selenium using Python
pip : Virtualenv/VirtualenvWrapper 

```python
from selenium import webdriver

browser = webdriver.Chrome();


```


>
```powershell
 selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home   

上のサイトでダウンロードしようとしたらVERSIONによって再ダウンロードする必要がある。

```
pip install webdriver_manager
```
してダウンロード後
https://github.com/SergeyPirogov/webdriver_manager 参照して

```python:
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

browser = webdriver.Chrome();
```
from webdriver_manager.chrome import ChromeDriverManager追加
GCP: Firestore

# Firestore
について書きます。
Firebaseのお仲間かと思ったら、Datastoreの上位互換的な立ち位置のようです。
https://cloud.google.com/firestore/docs

# Data model

https://cloud.google.com/firestore/docs/data-model

- NoSQLのドキュメントデータベース
- ドキュメントはKey-Valueペアをもっている
- 小さなドキュメントがたくさんあるデータに適している
- ドキュメントの中にサブコレクションを作って階層的なデータを作れる

# Structuring data

https://cloud.google.com/firestore/docs/concepts/structure-data

- ネストされたデータ
    - シンプル、作るのが簡単
    - ほかの構造と比べてスケーラブルではない
- サブコレクション
    - リストが大きくなっても親ドキュメントの構造が変わらない
    - クエリキャパシティがよい
    - 簡単には消せない
- ルートレベルコレクション
    - many-to-manyリレーションに良い
    - データ取得が複雑になる

# Location

https://cloud.google.com/firestore/docs/locations

- Firestoreのロケーションはデフォルトではプロジェクトのロケーションになる
    - マルチリージョンやリージョンを指定できる
- レイテンシを下げるために利用するサービスに近いロケーションを選ぶ

# Index

https://cloud.google.com/firestore/docs/concepts/index-overview

- single-fieldインデックス
    - a sorted mapping
    - デフォルトで自動でメンテしてくれる
- compositeインデックス
    - a sorted mapping
    - インデックスモード
        - ascendhing
        - descending
        - array-contains
    - スコープ
        - コレクションスコープ: 1つのコレクションから結果が返る
        - コレクショングループスコープ: 同じコレクションIDをもつコレクションから結果が返る

# Encryption

https://cloud.google.com/firestore/docs/server-side-encryption

- 自動でサーバーサイド暗号化
- クライアントサイドで暗号化したい場合、TLSを使う

# Best practices

https://cloud.google.com/firestore/docs/best-practices

- ドキュメントIDに単調増加する名前を避ける
- インデックスが増えすぎるのを避ける
- インデックスが単調増加する値になるのを避ける
- 1秒に1回以上の書き込みは避ける
- できるだけ非同期的呼び出しを使う
- オフセットではなくカーソルを使う
- Firestore SDKは自動でリトライを行う、RESTやRPC APIでは自動でリトライしない
- ホットスポットを避けるために、辞書順で近いドキュメントの読み書きを避ける

# Key visualizer

https://cloud.google.com/firestore/docs/key-visualizer

- Firestoreの利用パターンを可視化できる
- パフォーマンス課題の発見
- データアクセスのパターン

![keyvis](https://cloud.google.com/static/firestore/docs/images/key-visualizer-heatmap.png)

# Transaction

https://cloud.google.com/firestore/docs/manage-data/transactions

- トランザクション
- バッチ書き込み
- 最大500ドキュメントの書き込み
openFrameworksで右クリックを判別する方法

```c++:ofApp.cpp
void ofApp::mousePressed(ofMouseEventArgs &mouse) {
	switch (mouse.button) {
		case 0:
			ofLog() << "左クリック";
			break;
		case 1:
			ofLog() << "中クリック";
			break;
		case 2:
			ofLog() << "右クリック";
			break;
		default:
			break;
	}
}
```

`mouse.button` の中に入っている値で判別する。
もしくは `void ofApp::mousePressed(int x, int y, int button)` の `button` の値

マウスの中ボタンのクリックも取得できた。
[PHP]実行中の関数名を取得する

#はじめに
業務で調べる機会があったので備忘録としてまとめました。

#取得方法
実行中の関数は`__FUNCTION__`という定数に格納してある。


```
public function test() {
 echo __FUNCTION__;
}
```
出力結果

```
test
```

#おまけ
`__FUNCTION__`のような使用する場所によって値が変化する定数（マジカル定数）は、[PHP公式][link]によれば9つ存在する。
[link]:(https://www.php.net/manual/ja/language.constants.predefined.php)
GroupedのUITableViewで一番上の余白を消したい(swift)

![Xcode-12.0](https://img.shields.io/badge/Xcode-12.0-brightgreen) ![iOS-14.0](https://img.shields.io/badge/iOS-14.0-brightgreen) ![Swift-5.3](https://img.shields.io/badge/Swift-5.3-brightgreen)

# はじめに
下記の画像のように `style` が `grouped` の `UITableView` で条件によって一番上の余白の表示・非表示を切り替えたいときに試行錯誤したのでやり方をメモ。

| 余白表示 | 余白非表示 |
| --- | --- |
|![success_1](https://user-images.githubusercontent.com/34936885/95586068-197fe780-0a7b-11eb-9df7-a02e8b937132.png)|![success_2](https://user-images.githubusercontent.com/34936885/95586085-200e5f00-0a7b-11eb-8ecd-a4667bd4f6d9.png)|
 
 今回は画像のようにヘッダー表示時は余白をなくして、ヘッダー非表示の場合は余白ありにしたかった。。。
 
# だめだったパターン
とりあえずだめだったパターン。。。下記のように `isHeaderShown` が `true` のときにセクション０にヘッダーを設定して高さを設定してみた。
 
```swift
extension TableViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        guard section == 0 else {
            return UITableView.automaticDimension
        }
        return isHeaderShown ? 50 : UITableView.automaticDimension
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        guard section == 0 else {
            return nil
        }
        return isHeaderShown ? HeaderView() : nil
    }
}
```
 
結果
 
![failure](https://user-images.githubusercontent.com/34936885/95586196-4c29e000-0a7b-11eb-9f2d-4fa8bc2c015a.gif)

初回表示だけいけてるけど２回目以降がおかしい。。。:frowning2:

# いけてそうなパターン１
上の方法 ＋ 下記のようにテーブル更新時に `tableHeaderView` をいじってみました。
 
```swift
tableView.tableHeaderView = isHeaderShown ? UIView() : nil
tableView.reloadData()
```
 
結果

![success](https://user-images.githubusercontent.com/34936885/95586218-55b34800-0a7b-11eb-8153-4495bc817db8.gif)

いけてそう:tada:

# いけてそうなパターン２
上の方法でもいけてそうですがそもそも一番上にしかヘッダー設定しないなら sectionHeader に View を設定する必要はないと思い最終的には下記のようにしました。

```swift
extension TableViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        guard section == 0 else {
            return UITableView.automaticDimension
        }
        return isHeaderShown ? CGFloat.leastNormalMagnitude : UITableView.automaticDimension
    }
}

// 更新時の処理
tableView.tableHeaderView = isHeaderShown ? HeaderView(frame: .init(origin: .zero, size: .init(width: 0, height: 50))) : nil
tableView.reloadData()
```

結果はパターン１と同じだったのでたぶんいけてそう:clap:

# おわりに
こんなレイアウトにしたくなるのはレアだと思いますがどなたかの参考になれば幸いです。他にいい方法ご存知でしたらぜひ教えて下さい:pray:

今後は `UITableView` より `UICollectionView` 使っていった方がいいよって言うのも聞くしもうあんまりテーブルをごちゃごちゃするのはよくないのかもしれない。。。:thinking:
【Java Siler】varによる型推論について

#varとは
Java SE10 以降登場した、**ローカル変数**の**型推論**を行う仕組み。
右辺の型からデータ型を推論する。
varによる型推論は、コンパイル時に行われる。

**※【ローカル変数とは】**
**メソッド内**で宣言する変数のこと(メソッドの中の仮引数または引数として使われる)

**・varによる型推論の例**

```java
var i = 10;  //右辺の値より、iはint型であると推論する
```
**varによる型推論ができるのはローカル変数のみ！！！！**

##varを使えないパターン（コンパイルエラー発生）
・ローカル変数以外の変数（インスタンス変数・static変数・**メソッドの戻り値型**）の場合
・変数宣言時に初期化していない場合（つまり、「var i;」と変数だけ作成する場合）
・nullで初期化している場合
・配列の初期化を代入する変数の場合

#varで配列を作る際の注意
varは右辺の型からデータ型を推論する。そして、配列の作成に使う初期化子（{}）も、代入する値の型から配列の型を推論する。お互いに推論しあってしまうため、型が決まらずにコンパイルエラーとなる。

**・コンパイルエラーとなる配列の初期化例**

```java
var array = {1,2,3};
```

しかし、右辺で配列の値を作成する際に、型を宣言してくれれば、varによる配列の初期化が可能になる

**・varによる配列の初期化例**

```java
var array = new int []{1,2,3};  //int型の配列が作成できる
```

#varでArrayListを作る際の注意
配列と同様に、varによってArrayListを作成することもできる。

**・varによるArrayListの初期化**

```java
var list = new ArrayList<>();
```

ArrayListの**ダイヤモンド演算子**は、参照できる型がない時に、**Object型**を返す。故に上記のコードは下記のコードと同じ。

```java
 var list = new ArrayList<Object>();
```

listとして、Object型のArrayListが作成される。
【webpack】vuetifyのアイコン(mdi)をローカルにインストールして使う方法

#【webpack】vuetifyのアイコン(mdi)をローカルにインストールして使う方法

webpackにおいて、mdiアイコンをvuetifyのv-iconで使う場合に、CDNで使用する方法があるが、本番環境では外部依存をなくすためローカルで使用する必要がある。

ローカルにインストールするときにエラーが発生するなど手間取ったのでインストール方法をまとめておく。


>[vuetify公式 icons](https://vuetifyjs.com/en/features/icons/)


##パッケージのインストール

```
$ npm install @mdi/font -D
```


##vuetify.jsの編集

```js:src/plugins/vuetify.js
import '@mdi/font/css/materialdesignicons.css' // Ensure you are using css-loader
import Vue from 'vue'
import Vuetify from 'vuetify/lib'

Vue.use(Vuetify)

export default new Vuetify({
  icons: {
    iconfont: 'mdi', // default - only for display purposes
  },
})
```

・css-loaderがインストールしてあること。


<br>
エントリーポイントのファイルで上記src/plugins/vuetify.jsを読み込む。

```js:エントリーポイントのファイル記述例
import Vue from "vue"
import App from "./components/App.vue"
import vuetify from "./plugins/vuetify.js"  //ここで読み込んでいる

Vue.config.productionTip = false

new Vue({
  vuetify,
  render: h => h(App)
}).$mount('#app')
```


##webpack.config.jsの編集

これが重要。これを記述することでエラーがなくなった。
file-loaderを使って、指定した拡張子のファイルをjsで読み込めるようにしている。

```js:webpack.config.js
  module: {
    rules: [
      省略
       {
        test: /\.(eot|svg|ttf|woff|woff2)$/,
        loader: 'file-loader?name=[name].[ext]'
    },
    ]
  },
```

file-loaderが未インストールの場合は下記を実行。

```:bash
$ npm install file-loader --save-dev
```

>（参考）[webpack file-loader](https://webpack.js.org/loaders/file-loader/)


以上。



<br>
##(補足) 発生していたエラー
unexpected characterということで、mdiパッケージのデータが正しく読み込めていない。

```
ERROR in ./node_modules/@mdi/font/fonts/materialdesignicons-webfont.eot 1:1
Module parse failed: Unexpected character '�' (1:1)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
```



<br>
##(補足) CDNを利用する方法。
これは超簡単。CDNとして下記リンクを記述すればOK。

```
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css" rel="stylesheet">
```
[Phoenix LiveView] link、live_redirect、live_patchの違い

これらの違いについてもやもやしていましたが、[Jose Valimさんの分かりやすい解説](https://elixirforum.com/t/concrete-examples-of-when-to-use-live-patch-live-redirect-push-redirect-push-patch/30751/9)を見つけたので、要点を整理します。

## コツ

- LiveViewでページ移動する場合、基本的に`live_redirect/2`（ブラウザ側）と`push_redirect/2`（サーバ側）使う。
- 同じLiveView内でページ移動時にサーバから送るデータを最小限にしたい場合のみにpatchヘルパー（`live_patch/2`、`push_patch/2`）の使用を検討する。（例：テーブルのソート）

## どうリロードされるか

### `link/2`
- フルリロード

### `redirect/2`
- フルリロード

### `live_redirect/2`（ブラウザ側） & `push_redirect/2`（サーバ側）
- LiveViewはリロードされるが、 使用中のレイアウトはそのまま。
- `mount`が呼ばれる。

### `live_patch/2` （ブラウザ側）& `push_patch/2`（サーバ側）
- 使用中のLiveViewが最小限の差分のみ更新される。
- `mount`は呼ばれない。
- 別のLiveViewsにpatchすることはできないが、仮にもし別のLiveViewにpatchしようとしたら、フォールバックとしてredirectされる。

以上
スクールに通ってた頃の自分に教えてあげたいLinuxの便利なキーボード操作

##この記事について
ポートフォリオの作成にあたって、**フレームワークの学習ばかりでLinuxの勉強をあまりできていない**方が多いのではないかと思います。

しかし、**開発においてLinuxは密接に関わってきます。**
そんなことも知らずにプログラミング学びたての頃は、Linuxでの効率性やLinuxの「L」も知らずに黙々とポートフォリオを作成していました。
そんな過去のスクールに通ってた頃の自分やこれから開発をしていこうという方のために、**開発効率を上げるための便利なLinuxのキーボード操作を記した記事**となっております。


##環境
・Mac
・CentOS
・bash


##カーソルキーを使わずにカーソルを移動させる

`Linux`と打つはずが`Linx`と打ち間違えた時、← →（カーソルキー）を使ってカーソルを移動させたいよね？
しかし、**カーソルキーというのは右下の方にあって、ホームポジションから大きく外れてしまってるのでスムーズにカーソルを移動させることができない。**

```
$ echo Linx
```

そんな時は`ctrl` + `f` or `b`でカーソルを移動させる。


| コマンド | 説明 |
|:------------:|:------------:|
|  `ctrl` + `f`     |    foward【カーソルを前に（右に）】        |
| `ctrl` + `b`      |   back【カーソルを後ろに（左に）】           |




##カーソルを最初・最後に移動する

こんな馬鹿みたいに長いコマンドの一番最後や最初まで1文字ずつカーソルを戻していくのがめんどくさいそこの奥さん！！！！便利なコマンドがこちらです！！！

```
$ git log --graph --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(bold white)— %an%C(reset)%C(bold green)%d%C(reset)' --abbrev-commit --date=relative --all
```

| コマンド | 説明 |
|:------------:|:------------:|
|  `ctrl` + `a`      |    カーソルを最初に移動させる          |
| `ctrl` + `e`       |   カーソルを最後に移動させる            |




##カーソルを1単語単位で移動させる

時には一単語ずつカーソルを移動させたいわよね！！！

| コマンド | 説明 |
|:------------:|:------------:|
|  `option` + `→`       |    右へ移動          |
| `option` + `←`        |   左へ移動            |



##入力した文字を一文字削除する
入力した文字を`backspace`で削除するのもいいけど、このキーを使うためにはホームポジションから大きくずれてしまう。だからそんな時には、、、


| コマンド | 説明 |
|:------------:|:------------:|
| `ctrl` + `h`        |   カーソル位置の後ろの文字を削除           |
| `ctrl` + `d`        |   カーソル位置の文字を削除           |



##入力した文字を一単語単位で削除する
一文字ずつではなく、一単語単位で削除する


| コマンド | 説明 |
|:------------:|:------------:|
| `ctrl` + `w`        |   一単語単位で削除           |




##カット（全切り取り）とヤンク（ペースト）
| コマンド | 説明 |
|:------------:|:------------:|
| `ctrl` + `k` | カーソル位置から行末までを切り取る（カット） |
| `ctrl` + `u` | カーソル位置から行頭までを切り取る（カット）  |
| `ctrl` + `y` | 最後に切り取った内容を貼り付ける（ヤンク） |

##コマンド履歴
過去に入力したコマンドをもう１度使いたい時に使える

| コマンド | 説明 |
|:------------:|:------------:|
| ↑キー | 一つ前のコマンド履歴へ |
| ↓キー | 次のコマンド履歴へ（コマンド履歴を過去からみている時に） |
| `ctrl` + `r` | 履歴を検索する |

###`ctrl` + `r` の例

過去に使用した同じコマンドを検索する時
①`ctrl` + `r`を押す
②使いたいコマンド名の一部を入力（今回の場合は`echo`）
③見つかれば`Enter`でそのコマンドを実行する

```
(reverse-i-search)`': 

↓

(reverse-i-search)`echo': echo hello world
```

##補完機能

`echo`ってコマンドを打つ時に、最後まで入力するめんどくさくね？
そんな時はTabキーを押してやると残りの文字を補完してくれる

```
$ ec → Tabキーを押すと

$ echo → 残りの「ho」を自動で補完してくれる
```


##最後に
いきなり全ての操作を覚えることは難しいので、何かしたの操作で**「あれ？この操作すんのめっちゃめんどいねんけど。。。」**って思ったら、大体解決することができると思うので、ぜひこちらの記事であったり自力で調べて開発の効率をドンドン上げていってください。
WSL2でDockerを爆速化

ウチのWin10もようやくこの前のWindowsUpdateでWSL2が有効になりました。

早速、公式の手順に従ってDockerをWSL2に対応させて行きましょう
https://docs.docker.com/docker-for-windows/wsl/

# その前に、What's WSL2
WSLはWindowsSubsystemForLinuxの略称
WindowsのコマンドラインでLinuxのコマンドが使えるよー的なものだとおもって貰えば良いでしょう。

WSL2はWSLのバージョン２になります。ただし、WSL1の完全上位互換ではなくメリットとデメリットがあります。
https://docs.microsoft.com/ja-jp/windows/wsl/compare-versions

# まずは前提確認
1. Docker、バージョンは2.3.0.2以上
2. Windows10、バージョン 2004、ビルド 19041 以上

# WSL2をインストールする
## まずは、MicrosoftストアからUbuntuを入手
WSLにつかうLinuxOSは汎用性を考えてUbuntuにしました。
ファイルサイズが大きいですが、WSL用には一番オススメできるかと思います。
https://www.microsoft.com/ja-jp/p/ubuntu/9nblggh4msv6?activetab=pivot:overviewtab

## WSL2にアップデート
そのままだと、WSL1でインストールされるので、WSL2にアップデートしましょう。

```powershell
# インストールされているWSLとバージョンを確認
wsl -l -v
```
```text
  NAME                   STATE           VERSION
* Ubuntu                 Running         1
```
`*`がついているのがデフォルトのWSLです。WSLに複数のLinuxを入れているとたくさん出ます。
通常は、デフォルトのWSLがDockerと統合されます。

```powershell
# WSLをバージョンアップ
wsl --set-version Ubuntu 2

# インストールされているWSLとバージョンを再確認
wsl -l -v
```
```text
  NAME                   STATE           VERSION
* Ubuntu                 Running         2
```
UbuntuのVersionが２になっていれば成功です。

# 早速 Docker For WindowsでWSL2を有効に
1. `Settings > General`と進んで、`Use WSL 2 based engine`にチェックして`Apply & Restart`
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168736/e17ae6b6-de94-c4cf-c9a8-ca1ad85cb3b7.png)

1. `Settings > Resources > WSL Integration`　デフォルトのWSLで統合機能が有効になっています。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168736/6ac9264f-db85-3b31-896e-47982dedb7e1.png)

これで、いままでHyper-V上の仮想マシンで動いていたDockerが、WSL2で動くようになりました。

# が、落とし穴
WSL2は完全なLinuxになったもののWindowsのファイル共有でパフォーマンスが落ちてしまうデメリットがあります。
そのため、volumesでWindowsのローカルフォルダをコンテナに共有していた場合、体感的にかなり遅くなってしまいました。

# Linuxのファイルシステムにソースコードを配置することで解決
wslのWindowsとの共有領域である`/mnt/c/`配下をvolumesで共有すると遅くなってしまうので、
プログラムのコードはそれ以外の場所に置きましょう。
公式のベストプラクティスにもそう書いてあります。
https://docs.docker.com/docker-for-windows/wsl/#best-practices

# WSL2のDockerでVSCodeのDevContainer開発
https://docs.docker.com/docker-for-windows/wsl/#develop-with-docker-and-wsl-2

WSL内で`code`コマンドを実行すれば、WindowsのVSCodeがRemote-WSLモードで開く！！！

```bash
code ~/hoge_workspace/
```

あとは、WSL内のフォルダに`devcontainer.json`を用意していつもの手順で`Reopen in Container`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168736/61595eb2-74e3-e06b-dce0-f5879d4e7c11.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168736/d780fbd8-e186-3d76-9834-31c8275d0737.png)

## DevContainer関連
- [VSCodeでリモートホスト上のDocker上で開発する](https://qiita.com/sgmryk/items/e8178fbf246b2c7aad81)
- [VSCodeのHaskell拡張を使って最速開発環境構築](https://qiita.com/sgmryk/items/bc99efe36ad1c9104e1b)

# WSLのディレクトリにWindows10のエクスプローラーからアクセス
WSL内のLinuxが起動した状態で以下のネットワークパスにアクセスすることで、WSL内のフォルダにエクスプローラーでアクセス可能です。
そのままWindowsからファイルを編集することも可能です。

```
\\wsl$\
```
AzureAppServiceのWebシステムをWindowsからLinuxに乗せ換えた話

# 概要
AzureのAppServiceにて自作Webサイトの運営を行っていたのですが、カスタムドメインやSSLバインディングをするためには**月約7000円程度**のプランを選択する必要があり、収益の見込めないシステムには少し高いな～と思っていたところ、Linuxであればもう少し安く済むことを知り、乗せ換えることを決意。

###以下、自作Webサイトの構成

|||
|:---|:---|
|フロントエンド|Vue.js|
|バックエンド|.Net Core 3.1(C#)|
|データベース|SQLServer|
|CI/CD|AzureDevopsPipelines|
|SSL証明書|Let’s Encrypt|
|その他使用サービス|BlobStorage、SendGrid|

# AppServiceの「Windows」と「Linux」の違い
とりあえず出来るかどうかはわからないけど、一回作ってみよ～ってことで、AppService(Linux)を作成してみた。
ちらちら～っと中身を見たところ、以下の機能がLinuxだと使用できない。

- Application Insight
- Webジョブ
- MySql in App
- アプリの複製
- 拡張機能
- App Service Planの種類が少ない

拡張機能が使えない。。。
ということは、「Let's Encrypt」の導入は手動でやらなければいけないのか。。。
波乱の予感。。。(Windows版であれば拡張機能の「Azure Let's Encrypt」を使用して楽に適用できた)

# 何はともあれやってみる
とりあえずサービスは作成したので、ソースをデプロイして、構成情報設定してなんなく起動はできた。
カスタムドメインの設定方法もWindowsの時と変わらないので、特に困ることもなく完了。

ということで、最後の難関、手動での「Let's Encrypt」によるSSL証明書の取得

# Certbotのインストール
該当のAppServiceにSSH接続(Azureポータルから可能)し、以下のコマンドを実行

```
$ apt-get update
$ apt-get install certbot
```
これでCertbotがインストールされているはず。


# 証明書の発行
Certbotを使用して証明書の発行を行います。
先度と同じように、SSHにて以下のコマンドを実行

```
certbot certonly -d <ドメイン> --manual --preferred-challenges dns
```

「--preferred-challenges dns」の部分は、認証方式の選択。

今回は**DNSチャレンジ**という、証明書を取得したいドメインにTXTレコードを追加することで認証を行うことにした。
(他にも特定の場所にファイルを配置して参照させる**Httpsチャレンジ**などがある)

コマンドを進めていくと、途中で「DNSにこの値を使用してTXTレコード作れ」みたいな指示がでるので、指示に従う。
TXTレコード作成しても５分くらいは反映されないと思うので、以下のコマンドで反映されていることを確認してから次に進むこと。

```
nslookup -q=TXT [ドメイン]
```

以下のような文字列が表示されれば成功です。

```
IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/[ドメイン]/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/[ドメイン]/privkey.pem
   Your cert will expire on <some-date>. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le
```

# プライベート証明書の作成
Let's Encryptから取得した中間証明書等を使用し、プライベート証明書を作成。

```
$ mkdir /tmp/sandbox -p
$ cd /tmp/sandbox

$ SOURCE=/etc/letsencrypt/live/[ドメイン]
$ sudo cp $SOURCE/{cert.pem,privkey.pem,chain.pem} .

$ sudo chown ope *.pem

$ openssl pkcs12 -export -out certificate.pfx -inkey privkey.pem -in cert.pem -certfile chain.pem
```
最後の**openssl**コマンドを実行した際に、パスワードの設定を要求されるので入力。
ここで入力したパスワードは、AppServiceに証明書を登録する際にも要求されるので覚えておくこと。

# AppServiceへの設定
作成されたpfxファイルをダウンロードし、AppServiceのカスタムドメインから対象のドメインにSSLバインディング。
これで作業は完了！

# 終わりに
企業等で運用する場合には、**ApplicationInsight**とか分析ツール使えると便利ですが、個人運営の小規模サイトであればLinuxでいいかなぁ～と個人的には思いました。
Linuxサーバーで.NetCore動作させるのってどうなんやろ。。。って思っていたけど、案外普通に動いてて良かったです。
(ただ、Windowsに比べて多少の動作のもっさり感を感じました。気のせい？)

Windowsサーバーだと**月約7000円**だったのが、Linuxサーバーだと**月約2000円**!!
これならもう幾つかサーバ立ち上げてWEBサービス作ってもいいかなぁ～と考える今日この頃。
逆引きよく使うGitコマンド

よく使うGitコマンドを使いたい状況別にまとめてみました。
Gitの仕組みの話とかはまた別の記事で書こうかなって思っています。

<hr>

### GitHubでリポジトリ作ったからローカルに落としたい


```
git clone https://github.com/XXXX/XXXXXX
```

リモートにあるリポジトリを、ローカル環境に落としてくることをクローンと呼びます。
https://～ はクローンしたいリポジトリのURLを指定してください。

### ローカルのリポジトリの状態を最新に更新したい

```
git fetch origin XXX
git merge origin/XXX
```

または

```
git pull origin XXX
```

※ XXXはブランチ名です。
リモートリポジトリから情報を取得するのはフェッチと呼びます。
このへん奥が深いので別で記事にします。。


### ソースを書き換えたからGitに保存させたい

```
git add path/to/file.txt
git commit -m "コミットメッセージだよ"
```

保存＝コミットと覚えて問題ないと思います。
コミットってスナップショットを取るんだっけ？

### 自分のコミットをリモートに送信したい

```
git push origin XXX
```

リモートリポジトリへ情報を送信するのはプッシュと呼びます。
【push⇔pull】で対の関係みたいなイメージが強い気がするけど、【push⇔fetch】だと思うんだよなぁ。なんでもいいけど。

### ブランチを切り替えたい

```
git checkout XXX
```
チェックアウトは、ブランチの切り替え以外にも様々な用途で活躍します。
オプションも様々なので、これまた別で解説します。

### ローカルリポジトリの状態を確認したい

```
git status
```

筆者が作業を始めるときは、必ずこのコマンドから。
ローカルでどのファイルが変更されたか、新規追加や削除されたファイルを含め一覧表示してくれます。

### コミットの履歴を見たい

```
git log
```

普通にログ表示させると見づらいので、用途に応じてオプションをつけて、表示内容を整形してあげましょう。

### ファイルの差分を見る

```
git diff path/to/file.txt
```


### 新しくブランチを作りたい

```
git checkout -b XXX YYY
```

※ XXXは新しく作るブランチ名。YYYは分岐元のブランチ名。
チェックアウトさん早くも2度目の登場。

<hr/>

Git操作の基本として必要かなというものをいくつか並べてみました。
ほかにもあれば追記していく予定です。あと詳細を解説した記事のリンクとかも。。。

※resetとかのGitをブッ壊せる魔力を持つコマンドは載せていません。責任が取れませんものでm(__)m
コンビニエンスストアにおけるデータウェアハウス構築及び分析（データベース）－午後


応用情報技術者平成28年春期 午後6

ファイル：2016h28h_ap_pm_qs.pdf

参照：
https://www.ap-siken.com/kakomon/28_haru/pm06.html

メモを簡単に記載します。
詳細の分析は、上記リンクをご参照くだいますようよろしくお願いします。

１、
図3中のgに入れる適切な字句又は式を答えよ。
　なお，表の列名には必ずその表の別名を付けて答えよ。

gは
ORDER BY SF.売上年月 DESC，SF.店舗ID ASC，平均在庫数量 DESC　（参考答え）

※平均在庫数量は別名ですが、本当に？？

売上年月が新しいものから　DESC
平均在庫数量が多い順　DESC
ですね。

＜＜図３＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/51e4b67d-a5ab-4e7b-5e00-06f43319673e.png)


２、
〔売行きが悪い商品分類の一覧を作成するSQL文の不具合〕について，(1)，(2)に答えよ。
（１）、本文中の下線①に該当する副問合せは図2中のどの位置にあるか。α又はβで答えよ。
（２）、本文中の下線②とはどのようなデータか。40字以内で述べよ。
　　　　なお，販売及び在庫管理の運用方法は変更しないこと。


データウェアハウスから在庫実績を参照可能ということであり、在庫表に当該日のレコードが記録されていなくても、同じデータベース内に格納されている在庫実績から、日次の在庫数量を導出できるということです。

在庫数量を記録していない日の商品の在庫数量を実績から導出したデータ（参照答え）
書籍販売システムのセキュリティ（情報セキュリティ）－午後

応用情報技術者平成28年春期 午後1

ファイル：2016h28h_ap_pm_qs.pdf

参照：
https://www.ap-siken.com/kakomon/28_haru/pm01.html

メモを簡単に記載します。
詳細の分析は、上記リンクをご参照くだいますようよろしくお願いします。

１、本文中のa及び表2中のb，cに入れる適切な字句をそれぞれ4字以内で答えよ。
aは暗号化通信ですね。

HTTPS（私の答え）
→
TLS（参考答え）

HTTP には情報を安全にやりとりする仕組みがありません、そこで登場するのが「SSL/TLS」です。
HTTP で行われるウェブ通信に、「SSL/TLS」をくわえて「ウェブで情報を安全にやりとりする仕組み」にしたものが、「HTTPS」なのです。HTTPS は HTTP Secure（セキュア）の略称です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/9be5b589-9a67-abd9-de16-34fe4b5b656f.png)

bは、踏み台です。
cは、脆弱性の存在が広く公表される前にそれを悪用するので、ゼロディ攻撃ですね。

・ゼロデイ攻撃は、
あるOSやソフトウェアに脆弱性が存在することが判明し、ソフトウェアの修正プログラムがベンダーから提供されるより前に、その脆弱性を悪用して行われる攻撃のことを指します。問題解決のための修正パッチが提供された日を1日目としたとき、それ以前に始まった攻撃という意味でゼロデイ(0 day)攻撃と呼ばれます。


＜＜Webシステムのテスト環境、Webシステムの認証と通信＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/af68a30a-fa4a-5ad2-c46d-288de4ecb453.png)


＜＜侵入テスト＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/2e1cde08-7d52-5b7e-4767-a8604a85704b.png)


２、

・バッファオーバフロー攻撃は、
攻撃者が故意にプログラムが確保したメモリ領域(バッファ)よりも大きなデータを読み込ませることで、メモリ領域からあふれた部分に不正なデータを書き込ませ、システムへの侵入や管理者権限の取得を試みる攻撃です。

この攻撃は、プログラムが入出力するデータサイズの検査を怠っていることを悪用して仕掛けられます。したがってこの攻撃に対しては、バッファに書込むデータサイズを必ずチェックし、想定外のサイズで合った場合はエラーにする仕組みをWebアプリケーションに備えることが有効な対策となります。

３、
〔改善項目とその対策〕について，(1)～(3)に答えよ。
（１）、本文中の下線①について，Webサーバの構成情報の調査によって得られる，Webサーバを攻撃するために有用な，アプリケーションに関する情報を二つ挙げ，それぞれ7字以内で答えよ。

・ポートスキャンは、
コンピュータやルータのアクセス可能な通信ポートを外部から調査する行為で、不正アクセスを行うための下調べや、脆弱性検査などの目的で実施されます。スキャン対象の応答からOSの種類、稼働しているサービスとそのバージョンなどの情報が得ることが可能です。
WebサーバはDMZに設置され外部からのアクセスを受け付けている状態です。このためポートスキャンは容易に成功し、Webサーバソフトウェアの種類とそのバージョン情報などを得ることができます。

（２）、本文中の下線②について，Webサーバへのポートスキャンの対策として効果的な方策は何か。15字以内で答えよ。
これは簡単ですね、必要なポートだけを開ける


（３）、本文中の下線③で，N氏が導入を推奨するセキュリティ機器とは何か。アルフアベット3字で答えよ。
WAFですね。

・WAF(Web Application Firewall)は、
通過するパケットのIPアドレスやポート番号だけでなくペイロード部(データ部分)をチェックすることで、Webアプリケーションに対する攻撃を検知し、遮断することが可能なファイアウォールです。WAFでチェックされる内容はURLパラメタやクッキーの内容などのHTTPヘッダ情報や、POSTデータの内容などのメッセージボディ部などです。


＜＜改善項目とその対策＞＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591618/76b47a87-9219-6837-4e0c-19dfe5a15f70.png)


参照：
HTTPS と SSL と TLS
https://blog.qbist.co.jp/?p=1441
C言語でも配列とポインタはぜんぜん違うものだよ

# これは何？

C言語の配列とポインタがごっちゃになりがちなので、何がどう違うのかを軽く説明する。

# 前提

配列は、同じ型の値を複数入れる入れ物。

```c:C99
int a[3]; // int 3個。初期値は不定。
int b[] = { 1, 2, 3, 4 }; // 初期化子リストがあると、件数は省略できる。
int c[3] = { 1 }; // 初期化子リストが短いと、残りは 0 で埋められる。
```

ポインタは、ある値がある場所を指す値。

```c:C99
int a=3;
int * pa = &a; // pa は a を指す。
int ** ppa = &pa; // ppa は pa を指す。
int * p = (int*)malloc(10*sizeof(int)); // p は 10個のintを格納する領域の先頭を指すだろう。
```

このとおり、配列はポインタじゃないし、ポインタは配列じゃない。
似たものですらない。

# 操作
## ポインタに対する操作

ポインタに対しては

* 間接演算子( `*` )で、ポインタが指している値(の左辺値)を得る。
* 整数を加減して、近所のオブジェクトを指すようにする。
* 同じ型の値を指す近所のポインタを減じて、そのポインタとの距離のような値を得る。
* アドレス演算子( `&` )で、そのポインタを指すポインタを得る。
* `sizeof` 演算子で、そのポインタのサイズ(ポインタが指しているオブジェクトのサイズではない)を得る。
* 代入演算子で、右辺から左辺に代入する。単なる代入だけではなく、 `+=` なんかもできる。
* 代入演算子がなくても、 `some_func(pa);` みたいな形で、他の関数にポインタを渡すことができる。
* ポインタの指す先が関数の場合、 `pa(1,2)` みたいに、 `(1,2)` のようなものをつけると関数呼び出しになる。

など、様々な操作ができる。

## ポインタ周辺のシンタックスシュガー

ポインタに対してよく使われるのシンタックスシュガーが2つある。

ひとつは `a->b` 。これは `(*a).b` のこと。

もうひとつは `a[b]` 。これは `*(a+(b))` のこと。

有名な話だけど、 `1[p]` は `*(1+p)` なので `p[1]` と同じ意味になる。

## 配列に対する操作

一方。
配列に対してできる操作は限られている。

* アドレス演算子( `&` )で、その配列を指すポインタを得る。
* `sizeof` 演算子で、その配列全体のサイズ(要素のサイズでも、要素を指すポインタのサイズでもない)を得る。

ぐらいしかない。あともう一つあるけど(後述)。

いや普通に

```c:C99
int a[3]={1,2,3}; // これは定義。操作じゃない。
*a = 123; // 間接演算子で先頭要素へのアクセスを得る
int b = a[1]; // シンタックスシュガー [] の適用
int * p = a+1; // 二項演算子 `+` の適用
int * q = a; // 代入演算子の右辺になる
printf( "%p\n", a ); // 関数に渡す
```

のように書けるじゃないか、と思うかもしれないけど、いずれの操作も実は配列に対する演算ではない。

C言語の配列に対するスペシャルなルール「**前述の２つ以外の操作を試みると、先頭の要素へのポインタへと暗黙のうちに変換される**」が発動し、いずれもポインタ、それも、配列そのものを指すポインタではなく、先頭の要素を指すポインタに対する演算になる。

つまり前述のコードは、宣言の行以外はすべて **先頭の要素へのポインタへの暗黙の変換** を利用してポインタへの変換が行われたうえで、ポインタに対する操作をしている。

# 関数の引数にある配列のように見えがちなもの

まれに

```c:C99
void foo( int a[3] );
void bar( double b[]) { /* 略 */ }
```

のような関数宣言・定義を見ることがあるが、これは完全に

```c:C99
void foo( int * a );
void bar( double * b ) { /* 略 */ }
```

と同じものである。仮引数の `a` , `b` は一見配列っぽく見えるが、単なるポインタである。
ちなみにコンパイラは `a[3]` に現れる、配列のサイズのように見える `3` を無視する。

配列ではなくポインタである証拠に

```c:C99
void foo( int a[3] ){
    ++a; // a はポインタなので ++ することもできる。
    int ary[3];
    ++ary; // ary は配列なので ++ できず、この行はエラーになる。
}
```

と、仮引数リストで `int a[3]` という形で導入された `a` は、 `++` して値を変えることができる。

# このように

このように C言語は、配列は暗黙のうちにポインタに変換されるし、配列のように見えるものの正体がポインタだったりと、配列とポインタがごっちゃになるような文法になっている。

でも最初に書いたとおり、配列とポインタはぜんぜん違うものだ。

# まとめ

* 配列とポインタはぜんぜん違うものだよ。
* 配列はなにかと暗黙のうちに「先頭の要素を指すポインタ」に変換されるよ。
* 仮引数リストに配列のように見えるものを書けるけど、それは配列じゃなくてポインタだよ。

# 私見

C言語の配列は不便でわかりにくい言語要素だと思う。

関数の返戻値にもなれないし、一度定義した配列への代入もできない。そのような性質を持つ合理的理由もないと思う。

配列とポインタの混同をうながすような文法になっていて、多くの人が混乱していると思う。
CPU ウィンドウを Delphi 2 および 3 で使う

# はじめに
何を今更な話です。

# CPU ウィンドウについて
[CPU ウィンドウ] の機能 は **Delphi 4** からの実装なのですが、レジストリに値を追加する事により、裏技的に **Delphi 2** から利用可能となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/72e47c41-3fa1-0697-79b1-274c04c4a3d9.png)
**Delphi 2** の場合ですと、`HKEY_CURRENT_USER\Software\Borland\Delphi\2.0\Debugging` に `EnableCPU (REG_SZ)` を新規作成して値を `1` に設定すると [CPU ウィンドウ] が使えるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/c5d6411f-a87c-09ea-700b-1664dcd8e0e7.png)

| バージョン | レジストリ位置 | メニュー |
|:---|:---|:---|
| Delphi 2 | HKEY_CURRENT_USER\Software\Borland\Delphi\2.0\Debugging  | \[表示｜CPU\] |
| Delphi 3 | HKEY_CURRENT_USER\Software\Borland\Delphi\3.0\Debugging  | \[表示｜CPU ウィンドウ\] |
| Delphi 4 以降| (不要)  | [表示｜デバッグ｜CPU] |

## Delphi 2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/440f548a-0c86-5d33-e041-90008bbb0d4f.png)
## Delphi 3
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/4ecdc1f6-52fa-d174-4024-c9bb4dcca453.png)

# おわりに
**Delphi 2** や **Delphi 3** のプロジェクトの殆どが **Delphi 7** でコンパイル可能で、**Delphi 7** でコンパイルできなくても **Delphi 5** ではまずコンパイルできるので、この情報が必要になる方はあまりいらっしゃらないかとは思います。

残念ながら **Delphi 1** にはこの機能はありません。

**See also:**

 - [CPU ウィンドウ (DocWiki)](http://docwiki.embarcadero.com/RADStudio/ja/CPU_%E3%82%A6%E3%82%A3%E3%83%B3%E3%83%89%E3%82%A6%EF%BC%9A%E3%82%A4%E3%83%B3%E3%83%87%E3%83%83%E3%82%AF%E3%82%B9)
TomcatでAJP 1.3 Connectorの接続をローカルに限定する

#やり方
こんな感じでadress属性を指定するとよい。

```server.xml
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" address="127.0.0.1"/>
```

#参考
https://qiita.com/polarbear08/items/f016a0675e6c9637e7b8
CentOS8でしぶといIPv6を無効にする

#はじめに
掲題の件で、手間取って調べた時のメモ

#まずは王道
まずはよくあるパターンとして以下を実行してreboot

```/etc/sysctl.conf
net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv6.conf.enp0s3.disable_ipv6 = 1
```

再起動後に```ip a```でチェックすると、しぶとく残っている。

```
$sudo sysctl --all | grep disable_ipv6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.enp0s3.disable_ipv6 = 0
net.ipv6.conf.lo.disable_ipv6 = 1
```

#解決策
Network mangerで管理しているから、効かないらしい。
そこで以下のおまじないを実行してリブート(enp0s3は環境によって読み替える)

```
$sudo nmcli connection modify enp0s3 ipv6.method ignore
```

これで ```ip a```で見ると、無効になっている。


#ちなみに
この状態でnetstat で見てもapacheなどはIPv6でLISTENと表示される。
これについては以下が詳しい。
https://qiita.com/fetaro/items/d5164ba8271114d8a0c8


#参考
https://linuxhint.com/disable_ipv6_centos8/
Xcode12でAppStoreConnectへアプリをアップロードするとITMS-90562: Invalid Bundleでビルドが無効になる問題

## 手元で解決した方法

Podfileから[Quick](https://github.com/Quick/Quick)を削除してXCTest使うように変更したら直りました。

## 問題

今携わってるプロジェクトではスキームを分けて、AppStoreConnectでalpha, staging, productionの３つの環境のアプリを配布しているのですが、Xcode12にアップデートしてアプリを配布しようとしたらalpha, staging環境のアプリでなぜか表題のエラーが起こるようになりAppleからメールが届くようになりました。

```
ITMS-90562: Invalid Bundle - The app submission can not be successfully recompiled from bitcode due to missing symbols during linking. You can try to reproduce and diagnose such issues locally by following the instructions from: https://developer.apple.com/library/archive/technotes/tn2432/_index.html
```

![スクリーンショット 2020-10-09 19.59.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52019/5497a6eb-024f-878f-5915-9d4c2ee54516.png)


それとテストもよく分からないエラーを出して失敗するように。

```sh
▸ Processing Info.plist
▸ Running script '[CP] Check Pods Manifest.lock'
▸ Processing Info.plist
▸ Running script '[CP] Check Pods Manifest.lock'

❌  error: Illegal instruction: 4 (in target 'XXXXXTests' from project 'XXXXX')


▸ Linking XXXXXUITests
▸ Generating 'XXXXXUITests.xctest.dSYM'
▸ Running script '[CP] Embed Pods Frameworks'
Testing failed:
	Illegal instruction: 4
	Testing cancelled because the build failed.

** TEST FAILED **


The following build commands failed:
	CompileSwift normal x86_64
	CompileSwiftSources normal x86_64 com.apple.xcode.tools.swift.compiler
(2 failures)
[19:14:01]: Exit status: 65

[!] Error building the application. See the log above.
```

色々試していたのですが、結局解決方法が分からずとりあえずテストで失敗していたのでQuickを使用している部分のテストを削除してみたらテストが通るようになり、そのままXCTestに書き直して再度AppStoreConnectへアップロードしたら表題の問題が起こらないようになりました。


## その他

Xcode12でググったりTwitterで検索しても、[ワーニングの件](https://qiita.com/temoki/items/46ad22940e819a132435)や、[シミュレータ向けのビルドからarm64アーキテクチャ外す必要がある](https://stackoverflow.com/questions/63607158/xcode-12-building-for-ios-simulator-but-linking-in-object-file-built-for-ios)などに言及している記事やつぶやきしかひっかからず、困っていました。

一応[フォーラム](https://developer.apple.com/forums/thread/654917)に同じような問題が上がっているのは確認できたのですが、解決はしてなさそう。

あまり起こっていない問題なのかも。
引数で渡した文字列をsendでメソッドとして発動させる

## 概要

sendメソッドの使い方で、勉強になったのでメモ。

画像を2枚まで添付できるフォームがあり、どれくらい閾値を超えるサイズで投稿されているか調べたかったので、ログを仕込もうとしていた。

そこで、もともと次のようなコードを書いていた。

## リファクタリング前

```ruby
validate :checking_image_size_over_limit

def checking_image_size_over_limit
  logging_image_size(image_first, 'first') if image_first.present?
  logging_image_size(image_second, 'second') if image_second.present?
end

def logging_image_size(image, number)
  if image&.size >= 5 * 1024 * 1024
    Rails.logger.info "[#{self.class.name}] Over 5MB of images (image_#{number})"
  end
end
```

1枚目と2枚目どちらなのかを判別したかったので、第2引数に文字列を渡し、ログのメッセージの中で展開させていた。
しかし、先輩から「それだったら、sendを使えば引数1つでいけるよ」とレビューをもらい書き直した。

## リファクタリング後


```ruby
validate :checking_image_size_over_limit

def checking_image_size_over_limit
  logging_image_size('image_first') if image_first.present?
  logging_image_size('image_second') if image_second.present?
end

def logging_image_size(image)
  if send(image)&.size >= 5 * 1024 * 1024
    Rails.logger.info "[#{self.class.name}] Over 5MB of images (#{image})"
  end
end
```

sendといえば、動的にメソッドを切り替えるために使うくらいのイメージしか持っていなかったが、このように引数で渡した文字列をまたメソッドとして発動させるという方法でも使えるのだと勉強になった。
【VSCode】改行されてないソースコードを一発で簡単に見やすくする方法

圧縮などで改行がなくなり、見にくいソースコードを超簡単に成形する方法。

**使うのはvscode**。html, css, js, jsonなどほとんど対応。


<br>
▼圧縮されているソースコードの例
一行になっていたり、**改行されてなくて超見にくいヤツ**。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/154a45f1-7c79-70c1-0104-1bb35f86a2de.png)|
|:--|


##やり方
右クリックでメニューを開いて、`ドキュメントのフォーマット`をクリックするだけ。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/cac05198-de01-aca5-b103-1f83c94ce215.png)|
|:--|

　　↓

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563526/93271f81-14d7-43ae-a658-4a4966141b7b.png)|
|:--|

かんたん。vscode神ツール。


<br>
もちろん、
・html以外のcss、jsやjsonなどの他の言語もOK。
・ソースコードの一部が成形されてない場合も使えます。
What is the Significance in Buying a Men’s Plus Size Plain T-Shirt Online?

The t-shirt for men is one of the most promising attire loved by men for all the occasions. To keep the appearance of the attire appealing and casual, there so limitless design available in the option of the t-shirt of men. Purchasing the gent’s t-shirt from the online store is no more a tedious task as the online store are overloaded with the different style of men’s t-shirt in all the size and in a different color. If you want to look simple and adorable, then plain t-shirt is the best style to opt. Buying the gent’s t-shirt is now very easy and much faster due to the online transaction option provided by the online stores. These are the significance of buying plain men’s t-shirt online:

Designs: The online store offers the unlimited designs in the collar like round neck, v-neck or y-neck t-shirt and the sleeves 

Quality: There are a variety of fabrics in the plain t-shirts for men like cotton, nylon, synthetic or mixed fabric. But the cotton t-shirt is all time favorite of gent’s as it can be put on in any occasions and easy to maintain.
Reasonable price: The price of the t-shirt should be affordable so that everybody can easily buy it from the online store. This is one of the important points which is considered by every customer before option for the online store to purchase a plain men’s t-shirt.

Saves time: The online stores provide the huge options in plain gent’s t-shirt for which you need not rush to the different shops in the market and as a result, you can save a lot of time and even the online store make the delivery of the items you have selected to your doorstep.

Refund, exchange, and cancellation: The most exciting thing of the online store is that they have the refund, exchange, and cancellation option for all the products they are selling. It is very easy, if you want to exchange the trendy t-shirt from the plain t-shirt for men which you have purchased but didn’t like. And for cancelling the order, you only need to give a reason for cancellation and you will get your amount refunded.

All the above-mentioned details for the plain t-shirt for men will help you to buy the t-shirt for yourself or for someone else if you want to gift, as the online store is the best option accessible at a reasonable rate. 

Summary: The articles explains the benefits of buying a plain t-shirt for men from the online stores as they carry so many offers and discounts on every t-shirt for men. 

Conclusion: The plain men’s t-shirt can be best purchased from the online stores as there are immense varieties available in the best quality and at a price which can be afforded by any person.
visit here: https://www.beyoung.in/mens-plus-size-t-shirts
Flexboxで縦並びかつ左右中央揃えがうまくいかない理由と対策

ポートフォリオ作成のため久しぶりにCSSを触って、思うようにいかなかったので解決方法を共有します！

#Flexboxで縦並びかつ左右中央にする
要素を縦並びかつ左右中央揃えにしたいな〜
「よし！Flexboxを使おう！」

ということで、
要素を縦並びにするのは　flex-direction: column
要素を左右中央揃えにするには　justify-content: center

######HTMLはこんな感じ

```html:index.html
<main>
    <div class="main-box">
      <h1>タイトル</h1>
      <p>pタグです</p>
    </div>
  </main>
```

###早速やってみる！

```css:style.css
.main-box {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
```

![スクリーンショット 2020-10-08 23.23.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706118/056008b6-0c87-da05-57ab-102e5c4319a6.png)

あれ？あれれ？
左右中央にならない...

#なぜ左右が中央にならないのか

###ググってみたら発見した！
参照:https://baqamore.hatenablog.com/entry/2018/02/14/220836

この記事を書いた人曰く、縦並びにするということは、
![スクリーンショット 2020-10-08 23.51.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706118/ed1ebe85-bfdb-b143-815f-cf4632c89f32.png)
こういうことだそうだ！

#解決方法
ということは左右を中央に寄せたいならば、
justify-content: centerをalign-items:centerに変えれば......

```css:style.css
.main-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}
```
![スクリーンショット 2020-10-08 23.56.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706118/c217ad2c-4c04-45e9-d1c7-89ccce9c9d89.png)

###できた！！