OmniAICreator/Qiita-1.07M huggingface dataset:
未経験のおっさんがプログラミングを学ぶまで

はいどうも！
某プログラミングスクールに通い始めたおっさんです。
プログラミングは完全に未経験。
そんなおっさんが転職するまでの軌跡（奇跡？）をぼちぼち綴っていこうと思います。

投稿は今日が初めてですがスクールは今日で9日目。
HTML＆CSSをやってRubyに入り、Railsをやって試験を受けて、というところです。<br><br>




簡単に私の経歴を
↪️
地方出身、東京の文系私立大学卒、東京で就職し営業職(toC & toB)でマネジメント経験あり。

今はちょっと難しくなってしまいましたが海外旅行もそこそこ行きました。
<br><br><br>
なぜプログラミングを始めたのか、どうして転職を決意したのかなどは後々ゆっくりとupしていこうと思います。
とりあえずまだ始めたばかりですが感想としては
「めちゃくちゃやることがいっぱいある」
「勉強すること、覚えることが今までやってきたことの比じゃないレベルで多い」
この二つですね。
日々思ったこと、できなかったこと、疑問点などなど
自分が見返した時に
「あ〜こんなことあったな」とか、
「こんなことで悩んでたんだな」とかとか、
あとはこれを読んだ他の方に少しでも役に立てればなと思います。

そんな具合ですが本日は頭がパンクしているのでこれにて:wave_tone1:
Anaconda で　conda install したはずの　パッケージが import できない

##問題
Anaconda で　install したはずの　パッケージが使用できず　下記のようなエラーが発生しました．

```
ModuleNotFoundError: No module named 'selenium'
```
今回はselenium をinstall したはずなのに　上記のようなエラーが出ました．
##原因
 anacondaプロンプトで python プログラム(****.py) を動作するときにpy.exeを使用していた．

##対策
起動するときに　以下のように記述した．

###前: py *********.py (エラーが出た)
###後: python *********.py  (動いた)

##感想
 pyrhon.exe と　py.exe 2種は違うものだと知った(今までは同じだと思っていた)
 py.exe とはいったい何なのか，新たな疑問が生まれた
 解決してみれば非常に単純な問題だが，時間がかかった
 単純なミス過ぎて，ネットで検索しても出てこなかった．この記事が誰かの役に立とうれしいです．


##解決までの道
自分に対するメモです
1.問題に気づく
2.py と　python パッケージをどこからimportしているか調べる

```
import sys,pprint
pprint.pprint(sys.path)
```
###結果が違うことに気づく!!(計　2時間程度)
3.解決 (力尽きて作業進まず)
goでサーバーを立ちあげたらVSCodeがフリーズ＆PCが落ちる

## 起こった事
`go run ***.go`でサーバーを立ちあげた後にエディターでgoファイルを編集すると`gocode-gomod`がかなりCPUを食いエディターがフリーズ＆PCが落ちてしまう、、、、

## 環境
- go 1.15.3
- docker
- VSCode


## 解決策??
設定ファイル(`setting.json`)を開き以下のコードを追記すると治るそう

```json:setting.json
{
  "go.useLanguageServer": true,
}
```
と言ってもまだ動きモッサリしていてマシになった程度でした、、、

## 原因
>https://github.com/golang/vscode-go/issues/249#issuecomment-647902730

`go`の候補表示してくれる`gocode-gomod`は現在メモリをかなり食ってしまうようになっているらしくメンテナンス中かつ開発がストップしているそう、、
なので、変わりに`gopls`を使ってくれとの事でした！

~~これでgoでの開発に集中できる^^~~
C++入門 私的まとめ

こちらの記事は以下の書籍を参考にアウトプットとして執筆しました。
[新・明解C++入門](https://www.amazon.co.jp/gp/product/B0787YH4L2/ref=ppx_yo_dt_b_d_asin_title_o00?ie=UTF8&psc=1)

とりあえず1章ずつ記事にしていく方向で行こうと思います。


###処理系
C++プログラム開発に必要なソフトウェア

- Microsoft zVisual c++
- GNU C++

など

###std名前空間の利用
std名前空間の利用しないで`cout`を使用する場合、`std::cout`とする必要がある。
いまは呪文として落とし込んでおく。

###整数接尾語
||説明|
|---|---|
|u,U|その整数定数が符号なしである|
|l,L|その整数定数がlongである|

####例

```
1000→int型で表現できる→int型
60000→int型で表現できないがlong型で表現可能→long型
60000U→unsigned型で表現可能→unsigned型
```


###文字列の読込

||説明|
|---|---|
|cin|スペースを含まない|
|getline(cin,変数名)|スペースを含む|
###bool
boolalpha操作子を使うと真偽値をアルファベットで表示
noboolalphaで数値で表示

```c++
cout << boolalpha;
cout << noboolalpha;
```
###浮動小数点型
小数点以下を持つ実数のことで型は

- float
- double
- long double

の3つがある

####浮動小数点リテラル
3.14などの実数を表す定数
####浮動小数点接尾語
|接尾語|説明|
|---|---|
|f,F|float型|
|l,L|long double型|
|接尾語がない|double型|

###演算と型
```
int型+int型=int型
double型+double型=double型
int型+double型=double型
```
int型とdouble型混同では**暗黙の型変換**が起きている
整数と浮動小数点の型変換には静的キャストが適している。

###列挙体
整数値の集まり

##配列
###定値オブジェクト
配列の宣言時に大きさをconstが使えるということ
universal-ctagsを使おう

皆さんSytemVerilogでエディタのタグジャンプ用のTAGSを作るのはどのようにしているでしょうか? ctagsに正規表現でTAGのルールを定義したファイルを食わせて生成している方がほとんどではないでしょうか。Qiitaですと[ここ](https://qiita.com/tethys_seesaa/items/6c2622d6e63607633493)に方法が書いてあります。WEB検索すると、SytemVerilogのTAGS生成方法でヒットするのはほとんどがこの方法です。

ただ、この方法はワンラインの正規表現での定義なので構文解析に限界があります。目立つところでは`bit a, b;`のように一行に複数の変数が宣言された場合に対応できない、/\*と\*/ではさまれたコメントが複数行にわたる場合、そこもctagsに解釈されてしまうなどの問題があります。

githubにはuniversal-ctagsというツールが登録されています。これはツールネイティブでSystemVerilogに対応しており、前記のctagsよりもはるかに多くの書式に対応しています。とても高機能なのに、SytemVerilogのTAGS生成ツールとしてはなぜかほとんど紹介されていないようです。現在でも活発にSystemVerilogへのサポートが拡充されていますので、是非皆さん使ってみてください。

レポジトリは以下になります。
https://github.com/universal-ctags/ctags

# コンパイルとインストールの方法

特にstable releaseとかなさそうなので、HEADをコンパイルしてしまいましょう。

```
> git clone  https://github.com/universal-ctags/ctags
> cd ctags
> ./autogen.sh
> ./configure --program-prefix=ex --prefix=$HOME/local #インストール先を$HOME/localに設定
> make
> make install
```

# unversal-ctagsの使い方
上記の方法でインストールすると、~/local/binにexctagsというファイルができています。使用方法はctagsと全く同じです。TAGSを作りたいソースツリーの根本まで行き、vimの場合`exctags -R` emacsの場合`exctags -Re`となります。

# 追記
コメントで以下のctagsラッパの紹介をいただきました。並列実行での高速化以外に、ctagsで無視したいファイルを.gitignoreなどを元に自動判別してくるとのことです。便利そうなので是非見て下さい。
[gitリポジトリ向けの高速ctagsラッパー：ptags](https://qiita.com/dalance/items/c76141a097e25fabefe8)
【Java】parseIntとvalueOfの違い

#プログラミング勉強日記
2020年11月17日
コードを書いていて、`parseInt`と`valueOf`の違いがわからなかったので備忘録として残しておく。

#違い
　コードを実行したときに結果が同じになる。調べてみると<b>戻り値が違う</b>と出てきた。具体的には、`parseInt`がint型やchar型などのプリミティブ型で`valueOf`はIntegerクラスを返す。

```java
public class Main {
    public static void main(String[] args) throws Exception {
        int hoge = Integer.valueOf("12345");
        System.out.println(hoge);
        
        int fuga = Integer.parseInt("12345");
        System.out.println(fuga);
    }
}
```

```:実行結果
12345
12345
```




#参考文献
[parseIntとvalueOfの違い](http://welovy.hatenablog.com/entry/2013/04/28/121057)
[parseIntとvalueOfの違いって何！？](https://tomoprog.hatenablog.com/entry/2016/02/03/182803)
MySQLで取得結果にランクをつける

金額の高い順にランクをつける。

対象のテーブル

````sql
select
*
from
products

+-----------+-------+
| name      | price |
+-----------+-------+
| スイカ    |    80 |
| バナナ    |    50 |
| ぶどう    |    50 |
| みかん    |   100 |
| りんご    |    50 |
| レモン    |    30 |
+-----------+-------+
````

相関サブクエリを用いる方法

````sql
SELECT P1.name,
P1.price,
(
    SELECT COUNT(P2.price)
    FROM Products P2
    WHERE P2.price > P1.price
) + 1 AS rank_1
FROM Products P1
ORDER BY
rank_1;

+-----------+-------+--------+
| name      | price | rank_1 |
+-----------+-------+--------+
| みかん    |   100 |      1 |
| スイカ    |    80 |      2 |
| バナナ    |    50 |      3 |
| ぶどう    |    50 |      3 |
| りんご    |    50 |      3 |
| レモン    |    30 |      6 |
+-----------+-------+--------+

````

ランクを0から始めたい場合、+1を消せば良い。
また、count(distinct p2.price)とすれば、
同じ順位にならず、飛び石でランクがつけられる。

みかんのrank_1の値に1がつく理由としては、
みかんのprice(100)以上のレコードがないため、
where P2.price > P1.priceをcountした結果が0になるため。

また、自己結合を用いる方法もある。

````sql
SELECT P1.name,
MAX(P1.price) AS price,
COUNT(P2.name) +1 AS rank_1
FROM Products P1 LEFT OUTER JOIN Products P2
ON P1.price < P2.price
GROUP BY P1.name
ORDER BY
rank_1;
````

こちらを参考にさせていただきました。
<a href="https://www.amazon.co.jp/%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6SQL%E5%BE%B9%E5%BA%95%E6%8C%87%E5%8D%97%E6%9B%B8-%E7%AC%AC2%E7%89%88-%E5%88%9D%E7%B4%9A%E8%80%85%E3%81%A7%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%9F%E3%81%8F%E3%81%AA%E3%81%84%E3%81%82%E3%81%AA%E3%81%9F%E3%81%B8-%E3%83%9F%E3%83%83%E3%82%AF-ebook/dp/B07GB4CNKP/ref=sr_1_1?adgrpid=48836428930&dchild=1&gclid=Cj0KCQiA48j9BRC-ARIsAMQu3WSrZJJd4-psCT9_qj0w4f0_fuN9b3Rh3DD8mwgP9UkTOLLapCJzwJwaAsG_EALw_wcB&hvadid=338547693256&hvdev=c&hvlocphy=1009306&hvnetw=g&hvqmt=e&hvrand=10462958271481352436&hvtargid=kwd-335112034228&hydadcr=4076_10899478&jp-ad-ap=0&keywords=%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6sql%E5%BE%B9%E5%BA%95%E6%8C%87%E5%8D%97%E6%9B%B8&qid=1605532234&sr=8-1&tag=googhydr-22">達人に学ぶSQL徹底指南書 第2版 初級者で終わりたくないあなたへ
</a>
Warning: You are using macOS 11.0.となった時の対応方法

# 事象 : brew doctorしたらなんか言われた
- 環境
    - macOS Big Sur バージョン11.0.1
    - Homebrew 2.5.11

```bash
% brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: You are using macOS 11.0.
We do not provide support for this released but not yet supported version.
You will encounter build failures with some formulae.
Please create pull requests instead of asking for help on Homebrew's GitHub,
Twitter or any other official channels. You are responsible for resolving
any issues you experience while you are running this
released but not yet supported version.

```

## 原因 : macOS 11.0はサポートされていないから
参考 : [まったく新しいmac OS Big Sur betaにした結果 - YusukeIwakiのブログ](https://yusukeiwaki.hatenablog.com/entry/2020/09/18/macos-beta-6-for-engineers)

昨日何となくバージョンアップした・・・・セキュリティツールのESETもまだmacOS 11.0をサポートしていなかったし・・・何となくバージョンアップしてはいけない

### 対応 : 諦める
全く使えないわけじゃないみたいだし。

> You will encounter build failures with some formulae.
> (雑な訳)いくつかのformulaeでビルドが失敗します。
Self-Sizing（Auto Layoutによる高さの自動調整）機能について

##はじめに
この機能を知るきっかけとなったのは、セルのimageViewを誤って大きくしてしまったことでした。
オレンジが変更箇所になってます。この結果、チェックマークが表示された時にCellが縦に大きくなると言う現象が起きました。
この件を相談すると、Self-Sizingという機能が元々備わっていて、セルの表示に影響が出たと分かりました。
![スクリーンショット 2020-11-17 20.27.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/755375/aa1b3555-0eaf-a2dc-3de3-d2621e082281.png)


##Self-Sizingとは
タイトルにもある通り、セルなどの高さを自動で調整してくれる機能です。
Xcode 9（iOS 11 SDK）でデフォルトになったみたいです。それ以前はコードで表示しなければいけなかったみたいです。
私はデフォルトになってからswiftの勉強を始めたので気にしたこともなかったです。

##最後に
今回の件は、
そりゃ、セルのimageViewの大きさ変えたら、表示するために高さ変わるやろ〜って感じですが、
チェックマークの表示を切り替えるたびにサイズが切り替わるのでめっちゃ焦りました（笑）
チェックマークのサイズを誤って変更したばっかりに、Self-Sizingの機能が働いてくれて、表示できる様に高さを変更してくれていたんですね〜

##参考サイト
https://dev.classmethod.jp/articles/xcode-9-uitableview-self-sizing-by-default/
Warning: A newer Command Line Tools release is available.となった時の対応方法

# 事象 : brew doctorしたらなんか言われた
- 環境
    - macOS Big Sur バージョン11.0.1
    - Homebrew 2.5.11

```bash
% brew doctor
Please note that these warnings are just used to help the Homebrew maintainers
with debugging if you file an issue. If everything you use Homebrew for is
working fine: please don't worry or file an issue; just ignore this. Thanks!

Warning: A newer Command Line Tools release is available.
Update them from Software Update in System Preferences or run:
  softwareupdate --all --install --force

If that doesn't show you an update run:
  sudo rm -rf /Library/Developer/CommandLineTools
  sudo xcode-select --install

Alternatively, manually download them from:
  https://developer.apple.com/download/more/.

```

## 原因 : 新しいコマンドラインツールがあるよって教えてくれている
気にしない人は見なかったことにしても大丈夫そう、だけど気になるからアップデートしてみる

```bash
# あ・・・なんもないって・・・
% softwareupdate --all --install --force
Software Update Tool

Finding available software
No updates are available.
```

表示されているメッセージを読むとやり方が書いてあった

```bash:雑な訳
更新が表示されなかったら、次の手順を実行してね。
  sudo rm -rf /Library/Developer/CommandLineTools
  sudo xcode-select --install

​または、次の場所から手動でダウンロードもできるよ。
  https://developer.apple.com/download/more/.
```

### 対応 : 古いコマンドラインツールを削除して新しいのをインストールする
```bash
# 古いコマンドラインツールを削除して
% sudo rm -rf /Library/Developer/CommandLineTools
Password:

# 新しいのをインストールしようとしたら・・・なんかインストールせいと言われた
% sudo xcode-select --install
xcode-select: note: install requested for command line developer tools
```

言われるがままにインストールする
![スクリーンショット 2020-11-17 21.18.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/1438b59a-9f47-5666-0636-308dba2cd07f.png)
![スクリーンショット 2020-11-17 21.18.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/bc57dbfd-50f4-3d26-aed3-e7e5b5d6d189.png)
![スクリーンショット 2020-11-17 21.18.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/4efdebc4-e4fa-6be1-2013-43b39a037664.png)
![スクリーンショット 2020-11-17 21.21.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/f9883694-31df-02ea-46f1-3ee9f4d43199.png)

```bash
# インストールできた？インストールできたくさい
% sudo xcode-select --install
xcode-select: error: command line tools are already installed, use "Software Update" to install updates
```

`brew doctor`してもメッセージは表示されなくなったので解決ということで。
tcpdumpしてみました

## tcpdumpとは

ネットワークの通信をキャプチャするもの
今回はlinux(CentOS7)で実行します。

## 使い方

- すべてのインタフェースの通信をキャプチャ

コマンドは `tcpdump` のみ


```sh
$ tcpdump
```

## よく使うオプション

- インターフェースを指定(-i)

`-i インタフェース名` を使用

```sh
$ tcpdump -i インタフェース名

使用例
$ tcpdump -i enp0s8
```

- キャプチャ結果を出力(-w)

`-w ファイル名` を使用

```sh
$ tcpdump -w ファイル名

使用例
$ tcpdump -w tcpdump.log
```

- キャプチャデータをASCIIで表示(-A)

`-A` を使用

```sh
$ tcpdump -A
```

- 時間を表示しない(-t)

```sh
$ tcpdump -t
```

## フィルタ

- IPアドレスを指定(送信元・送信先関わらず)

```sh
$ tcpdump host 送信元IPアドレス

使用例
$ tcpdump host 192.168.1.1
```

- ポート指定

```sh
$ tcpdump port ポート番号

使用例
$ tcpdump port 80
```

- 送信元IPアドレスを指定

```sh
$ tcpdump src host 送信元IPアドレス

使用例
$ tcpdump src host 192.168.1.1
```

- 送信元ポート指定

```sh
$ tcpdump src port ポート番号

使用例
$ tcpdump src port 80
```

- 送信先IPアドレスを指定

```sh
$ tcpdump dst host 送信元IPアドレス

使用例
$ tcpdump dst host 192.168.1.1
```

- 送信先ポート指定

```sh
$ tcpdump dst port ポート番号

使用例
$ tcpdump dst port 80
```

- 複数組み合わせる

```sh
IP:192.168.1.1, port:80 をキャプチャ
$ tcpdump host IPアドレス port ポート番号

使用例
$ tcpdump host 192.168.1.1 port 80
```

## 見方

- tcpdumpコマンドで見る

```sh
$ tcpdump -r ファイル名

使用例
tcpdump -r tcpdump.log
```

## 参考

- [超絶初心者むけtcpdumpの使い方](https://qiita.com/tossh/items/4cd33693965ef231bd2a)
- [tcpdumpの使い方](https://qiita.com/aosho235/items/d87e0d69e89513d02a3f)
- [tcpdump コマンドの使いかたをまとめてみた](http://blog.livedoor.jp/sonots/archives/18239717.html)
FlutterのRaisedButtonの幅を指定したい！

# FlutterのRaisedButtonの幅を指定したい！
ButtonThemeでRaisedButtonをラップすると良い。


```dart
ButtonTheme(
  minWidth: 200.0,
  height: 100.0,
  child: RaisedButton(
    onPressed: () {},
    child: Text("test"),
  ),
);
```

> refs: https://www.it-swarm-ja.tech/ja/flutter/flutter%E3%81%A7raisedbutton%E3%81%AE%E5%B9%85%E3%82%92%E8%A8%AD%E5%AE%9A%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%E3%81%AF%EF%BC%9F/838604783/
libcxx iostream cin 初期化メモ


## 背景

libcxx で iostream cin(や cout)の初期化どうなっているのかしらん?

`cin` はグローバルな変数だけど, main の前に初期化(コンストラクタが走る必要がある)する必要があるけどどうなっているのかしら?
(iostream クラスそのものはコピー, コピーコンストラクタを呼ぶのは不可)

## ソースコードを調べる

header では

`extern istream cin`

https://github.com/llvm/llvm-project/blob/master/libcxx/include/iostream#L49

と定義していました.

https://github.com/llvm/llvm-project/blob/6795984a47dfd2da4f451ad86a99021d6c9f85b5/libcxx/src/iostream.cpp#L21

まず, ストレージ(メモリ領域)として char の配列で確保していました.

iostream のヘッダとは型が違うので, コンパイラで厳格なエラーを出すようにしている場合 suppress する必要があります.



https://github.com/llvm/llvm-project/blob/6795984a47dfd2da4f451ad86a99021d6c9f85b5/libcxx/src/iostream.cpp#L111

その後, placement new で, ストレージ領域を iostream として初期化(コンストラクタ)していました!

https://cpprefjp.github.io/reference/new/op_new.html

あとはこの関数が

```
_LIBCPP_HIDDEN ios_base::Init __start_std_streams __attribute__((init_priority(101)));
```

により起動時に呼ばれます.

https://github.com/llvm/llvm-project/blob/6795984a47dfd2da4f451ad86a99021d6c9f85b5/libcxx/src/iostream.cpp#L80

`__attribute__((init_priority(101)))` で初期化の優先度を指定していますね. gcc/clang 拡張かな?
【アウトプット】find_by メソッド

今回はfind＿byについてアウトプットをしていく。

find_byはある特定のIDを取得すときに使われる。
３番目のIDのデータを取得するとか５番目とか

モデル名.find_by(カラム名: 値)と書くことでその値を持ったデータのデータベースから取得ができるようになる。

例）post = Post.find_by (id:3)
ちなみにpostはeachのときに使った変数

このようにして使われる。

変数paramsとよく使われる？らしいのでこれも併用して覚えるとGOOD
メモ帳の劣化版

# 何作ったん？
初のクソアプリ参戦ということで、今回は「使えないかもしれないメモ帳」を
作りました。ご覧ください。
# 概要
python3.8.5でつくた
tkinter使用

# どんなん？
こんなん↓
![Qiita](https://user-images.githubusercontent.com/74484618/99239467-71f69180-283e-11eb-89ae-26b808582f28.png)
![スクリーンショット (3)](https://user-images.githubusercontent.com/74484618/99388787-72178f80-2919-11eb-954a-44f1e218e849.png)
## アドべ2020に出すにあたり

- バッチファイルを介しての「実行」を廃止いたしました。(写真に実行とありますが機能しません。)
- フォントを変えました。 

# ダウンロード
Github:https://github.com/pythonmaster1027/-2020-
[備忘録]MySQLのコマンド



#データベース

### ローカル環境でMySQLに接続する

```
$ mysql -u ユーザー名 -p [データベース名]
```

###データベースの新規作成

```
MySql> CREATE DATABASE [任意のデータベース名];
```

###データベースの表示

```
MySql> SHOW DATABASES;
```

###データベースの選択

```
MySql> USE データベース名;
```

###データベースの削除

```
MySql> DROP DATABASE [任意のデータベース名];
```

###ログアウト

```
MySql> EXIT;
```


#テーブル
###テーブルの作成

```
MySql>　CREATE TABLE テーブル名 (カラム名1 データ型1, カラム名2 データ型2, ...);
```
(例）idカラムとnameカラムを持ったcategoriesテーブルを作成

```
MySql>　CREATE TABLE categories (id INT, name VARCHAR(100));
```

__データ型の種類__

| データ型 | 意味 |
|:-----------|:------------|
| INT | 数値 | 
| DECIMAL |　少数。例えば DECIMAL(5, 2) とした場合、小数点以下が2桁、全体で5桁の数値を格納することができる。この場合、格納できる値は、-999.99 から 999.99 の範囲になります。      |
| VARCHAR(文字数) | 文字列。後ろにカッコで文字数を指定して使う。VARCHAR(100) のように指定すると、ひとつのフィールドに100文字まで保存できる。| 
| DATETIME | 日時。 | 
| DATE | 日付。 |

###テーブルの一覧表示

```
MySql>　SHOW TABLES;
```

###テーブルの削除

```
MySql>　DROP TABLE テーブル名;
```
【Python】table[key][0] += 1 でやっていることがわからない

# table[key][0] += 1 でやっていることがわからない。

Kaggleで他の人のノートブックをみている際に以下のような記述を見つけた。

```
import random
import string
import collections

action_seq = [2,1]
action_seq, table = [], collections.defaultdict(lambda: [0, 0, 0]) 
key = ''.join([str(a) for a in action_seq[:-1]])
table[key][0] += 1 
print(table[key][0])
```
上記の実行結果は以下のようになる。

```
1
```
正直何がどうなって「１」という結果になるのかさっぱりわからなかった。
collections.defaultdict()の処理内容や、lambdaについても確認したがそれでもよくわからない。
そもそも配列に対して「+= 1」を行う行為がどのような結果になるのか想像がつかなかった。

# どのようにして理解をしたか
以下のようなデバックを行うことで動き方を理解することができた。

```
import random
import string
import collections

action_seq, table = [], collections.defaultdict(lambda: [0, 0, 0]) 
action_seq = [2,1]
key = ''.join([str(a) for a in action_seq[:-1]])
print(table)
table[key][0] += 1 
print(table)
table[key][1] += 1 
print(table)
table[key][2] += 1 
print(table) 
```

結果は以下のようになる。

```
defaultdict(<function <lambda> at 0x7fd38dfa43b0>, {})
defaultdict(<function <lambda> at 0x7fd38dfa43b0>, {'2': [1, 0, 0]})
defaultdict(<function <lambda> at 0x7fd38dfa43b0>, {'2': [1, 1, 0]})
defaultdict(<function <lambda> at 0x7fd38dfa43b0>, {'2': [1, 1, 1]})
```

この結果からわかることは、「table[key][0] += 1」では以下のような構成で処理される。

```
table[key]...テーブルのキーを「2」に設定
[0]...デフォルトで設定した[0,0,0]の１番目の列を指定
+= 1...テーブルキー2の配列の１番目の列の値に1を加算
```

あくまで[key]の後に指定している[0]は列指定であることがわかりました。
※二次元配列なのか？とか余計なことを考えていたので混乱しました。。

結構この処理内容を理解するのに時間が掛かったので参考になれば嬉しいです。
UNIX ファイルディスクリプタ

#【UNIX ファイルディスクリプタ】

##3つの標準ディスクリプタ

0　　標準入力　（普通はキーボードからの入力）

1　　標準出力　（普通は端末画面への出力）

2　　標準エラー出力　（普通は端末画面への出力）

##リダイレクト、パイプ

<strong>リダイレクト</strong>とは、入出力はコマンド実行時に切り替えられ、コマンドの入出力をファイルに切り替える機能のこと。

<strong>パイプ</strong>とは、コマンドの出力結果を別のコマンドの標準入力に渡すことが出来る機能のこと。
macOSでのnumbaインストール時のエラー解決

* 2020年2月時点
* OS: macOS Big Sur 11.2.1
* CPU: Intelの方
* Python: 3.9

## 以下のエラーが再現する条件

Pythonのバージョンが3.9であり、numbaのバージョン0.50.xをインストールしようとしてた場合に以下エラーが発生するようです。

0.50.x以前はPython3.9をサポートしてなかったためです。

0.51.x以降をインストールする場合は`pip3 install numba`のみで大丈夫です。

Pythonのバージョンが3.9よりも前の場合でも`pip3 install numba`で大丈夫だと思います。

## エラー解決方法

まず先に解決方法です。上記の条件を満たしていた場合、多分これでいけます。

```
brew install llvm@9
```

```
export LLVM_CONFIG=/usr/local/Cellar/llvm@9/9.0.1_2/bin/llvm-config
```

```
pip3 install numba==0.50.1
```

## numbaインストール時エラー例

### llvm-configのパスが不明

```
RuntimeError: llvm-config failed executing, please point LLVM_CONFIG to the path for llvm-config
```

エラー概要: llvm-configの実行に失敗。LLVM_CONFIGにパスを設定してください。

LLVMインストール時に「llvm-config」という実行ファイルがインストールされているのでそのパスを環境変数LLVM_CONFIGに設定すればOK。

下記コマンドで環境変数を設定してください。(各々のllvm-configのパスをLLVM_CONFIGに設定してください)

```
export LLVM_CONFIG=/usr/local/Cellar/llvm@9/9.0.1_2/bin/llvm-config
```

私のllvm-configは下記パスだった。

`/usr/local/Cellar/llvm@9/9.0.1_2/bin/llvm-config`

#### パスが不明の場合

brewでLLVMをインストールした場合、`usr/local/opt/`にエイリアスが作成されているので、そこからたどる(Finder > 移動 > コンピュータでルートディレクトリを見れる。隠しフォルダの表示の仕方は各自調べてください)。

目的のものが見つかれば、右クリックしてoptionキーを押せば「"llvm-config"のパス名をコピー」という項目が出るのでそれをクリックしてコピーできる。

### LLVMのバージョン違い

```
RuntimeError: Building llvmlite requires LLVM 10.0.x or 9.0.x, got '11.0.0'. Be sure to set LLVM_CONFIG to the right executable path.
  Read the documentation at http://llvmlite.pydata.org/ for more information about building llvmlite.
```

エラー概要: llvmliteのビルドは LLVM 10.0.x か LLVM 9.0.x を要求しているが11.0.0が見つかった。LLVM_CONFIGに正しい実行できるパスを設定してください。

brewでLLVMをインストールする際`brew install llvm`とすると、最新バージョンがインストールされる。2020年11月時点ではLLVM 11.0.0がインストールされていた。brewでパッケージをインストールする際は`@(アットマーク)`でバージョンを指定できるので`brew install llvm@9`でバージョン9のLLVMをインストールする。(2020年2月時点では`llvm@10`は無い)
ARcore ver1.21を使おうとしてエラー吐かれまくった話

2020/12/03 追記
## 事の発端
ARcoreがバージョンアップし、ついにAnchorが最長1年保つことになりましたーわーい。
てなわけで、今までこき使ってた**Unity2018.4.20**プロジェクトのARcore(バージョンは忘れた)に上書きしたところ、エラー吐かれまくってビルドが出来なくなった。
# どう対処したか
解決策から書くと**Unity 2020.1.13に切り替えることで解決**しました。
~~Unity 2020.1.13では特に設定は弄らなくていいが、~~
Window→Package Managerから「Multiplayer HLAPI」と「XR Legacy Input Helpers」の２つをインポートする必要がある。見当たらない場合の対処法も追記。(2020/12/03 追記)
また、ビルドの前にGraphicsAPIsのvulkanを削除しないとエラーが出る。↓画像参照
![GraphicsAPIs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580375/1a8144ad-485b-c6fb-4d43-2e5fcae916d5.png)
ちなみにUnity 2019.4.14でもエラー吐かれまくって一向に解決の目途が立ちませんでした。(全ギレ)

### Unity2018.4.20でのエラー内容
エラーの内容はこんな感じ。

```
BuildFailedException: Main Gradle template is not used in this build.
ARCore SDK for Unity requires gradle plugin version >= 3.6.0. Nevigate to 'Project Settings > Player > Android Tab > Publish Settings > Build', check 'Custom Gradle Template'.
Then edit the generated file 'Assets/Plugins/Android/mainTemplate.gradle' by adding dependency 'com.android.tools.build:gradle:3.6.0.'.
```

![エラー内容.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580375/8af96090-ad4f-87f6-74b5-ca52a38ef7db.png)
Custom Gradle Templateにチェックを入れろとのこと。
チェック入れてもっかいビルドかけるとまた別のエラーが。

```
CommandInvokationFailure: Gradle build failed. 
```

とのこと。
その後は
Project Settings > Player > Configuration > Scripting Backend を Mono→IL2CPPにしたり、
mainTemplate.gradleにclasspathを追記したり、書き換えたりしたり、
exportかけてAndroidStudioで開くも読み込み時にエラーやUpdate失敗やらexport自体が失敗するなどで解決せず。

## 該当Packageがない場合
2020/12/03 追記。
Unity2019では最初から表示されているのだが、Unity2020.1以降では「Multiplayer HLAPI」と「XR Legacy Input Helpers」がPackage Managerにない場合がある。
その際は、
１.左上の「＋」を押し「Add Packeage from git URL...」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580375/eea25552-371a-ae90-db37-0f9a1e6af31e.png)
２.無いPackageを入力しAddする。Addが完了すると同時にインポートも完了。
・「Multiplayer HLAPI」が無い場合→「com.unity.multiplayer-hlapi」
・「XR Legacy Input Helpers」が無い場合→「com.unity.xr.legacyinputhelpers」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580375/1ee17b49-ad4f-3a68-b577-aab4c121757e.png)
この件についてはUnity公式が謝ってらっしゃる。許して差し上げろ。(参考URLを参照)

# オチ
**ARcore ver1.21を使いたい場合は2020.1以降のUnityを使おうね！**

# 参考
・https://developers.google.com/ar/develop/unity/android-11-build
・https://forum.unity.com/threads/you-have-enabled-the-vulkan-graphics-api-which-is-not-supported-by-arcore.896741/
・http://blog.lab7.biz/archives/21920252.html (2020/12/03 追記)
・https://helpdesk.unity3d.co.jp/hc/ja/articles/900002171066-Unity-2020-1-%E3%81%8B%E3%82%89%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3%E3%81%A7%E7%99%BA%E8%A6%8B%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%96%B9%E6%B3%95 (2020/12/03 追記)
【Firebase】TimeStampクラスの変数をsessionStorageに入れて出すとただのObjectになる

# はじめに

**タイトルが全てです．**
JavaScriptを使った開発中，FirebaseのFireStoreから受け取った値をsessionStorageに保存し，再利用するコードを書きました．
その際，エラーが出てかなり苦戦したので，備忘録を兼ねて記事を書きました．

# 出たエラー
コンソールには以下のようなエラー文が表示されました．

```
.toDate is not a function.
```

# 原因
sessionStorageに入れるためにTimeStampクラスのものをJSON形式にすると，出てきたものはただのObjectになるみたい．

toDate()メソッドはTimeStamp型にしか使えないので，エラーが出ていたみたいです．


# 対処法
原因が分かれば，対処法は色々あると思います．
自分の場合はsessionStorageに入れる前にtoDate()メソッドを用いて，JSのdate型に直してからsessionStorageに入れました．

# 終わりに
JavaScriptは変数の型を指定しないのでこういったエラーがよく起こりそう．気を付けねば……
とりあえず，

```
not a function
```

って出てきたときは，変数の型をチェックするのがよさそう．
読書会「プログラマが知るべき97のこと」 #7

# 1．今回の読んだ記事
No.86　[DRY原則](https://xn--97-273ae6a4irb6e2hsoiozc2g4b8082p.com/%E3%82%A8%E3%83%83%E3%82%BB%E3%82%A4/DRY%E5%8E%9F%E5%89%87/)　
著者: Steve Smith

# 2．記事の概要
**著者の主張**

- DRY（Don’t Repeat Your Self：繰り返しを避けること）原則はプログラミングに関して守るべきとされている原則の中でも特に重要なもの
- 開発者がシンプルなアプリケーションを作るうえでの基本的な指針

**要約**

- 重複は無駄
- 作業（テスト・ビルドなど）の重複は自動化で防ぐ
- ロジックの重複は抽象化で防ぐ 


# 3．この記事を選んだ理由・感想
**理由**
開発を行う上で、繰り返しを防ぐというテーマは重要なことだと思ったので議題として取り上げたかった。

**感想**
システム開発において、自動化が重要であることを再認識した。
担当システム内でも改善できると思うので対応したい。
一方で歴史が古いシステムであるほど、後からからプロジェクトに新しいやり方を浸透させるのは難しいだろうなとも感じた。


# 4．議論
**繰り返しを避けることに関して、普段意識していることはあるか？**

- 毎回同じ作業だなと思ったら、効率化できないか考えたりする
- ラクできるように考える

**過去に無駄な繰り返し作業をが発生していて、改善した事例があるか？**

- 試験
    - 性能試験などで毎回同じことをすることがあるので自動化のためにツールを作成した
        - 毎回全く同じ作業なので、ログを自動で取得できるようにするなど
            - 結果、作業時間が半分くらいになった
            - 自動化のアイディアと方法は上司が考えたもの<br><br>

    - モジュール結合試験を一括で自動実行できるようにした
        - リグレッション試験をしたいので、変更していないところや基本機能を集約して毎回試験できるように自動化した
        - REST APIの試験だが、環境の問題などでマッチしたツールがなかったので自作した
            - 現状ではデータ作成などエクセルなどを使ってるので、もう少し進化てよい方法にしたい<br><br>

    - 画面の試験を自動化したい
        - デザインの試験が自動化できていない
        - 文言の表示などは自動化できるが、デザインは提供を受けていいる
        - 動的な表示が影響してデザインがズレたり隠れてしまったりするので、おかしな表示を見つける試験を簡単にしたい<br><br>


- デプロイ
    - PHPの画面系のアプリはデプロイを自動化している
        - 試験のたびに表示値を変えたりなどもできるようにした<br><br>
    - Jenkinsなどに移行したい
        - これまでのやり方もあるのでお客様を説得しつつ計画する（設定を作るのは手間）
        - うちのチームはビルドなどは活用しているが、まだデプロイするところまでは完全にできていない
<br><br>

**現状、無駄な作業だと感じていて改善したいと考えていることはあるか？**

- 申請の類はまだ改善ができるかもしれない
    - 若手にに改善をお願いしたいなぁ
- 日常生活では何かありますか
    - 趣味のために定期的にWebを検索するツールを作りました
    - 無駄というわけではないが、ラクしたいので食器洗い機が欲しいです！


# まとめ
同じようなことは何度もやるので無駄だと思う。ラクしたい。
環境によって自動化できたりできなかったり、、、個々の環境なども知ることができました。
次回に続く。
Linux 主なパッケージ管理システム

#【Linux 主なパッケージ管理システム】

##RPM形式

RedHat LinuxやFedora Linux、CentOS等のRedHat系ディストリビューションで採用されている。
rpmコマンド、yumコマンドを利用してrpmパッケージの管理を行う。

##Debian方式

Debian GNU/LinuxやUbuntu LinuxのDebian系ディストリビューションで採用されている。
dpkgコマンド、apt-getコマンド、apt-cacheコマンドを利用して debパッケージの管理を行う。

##主なパッケージの形式と管理コマンド

<strong>RedHat系</strong>
パッケージ形式は、rpm形式　
パッケージ管理コマンドは、rpmコマンド　
リポジトリを利用したパッケージ管理コマンドは、yumコマンド

<strong>Ubuntu/Debian系</strong>
パッケージ形式は、deb形式
パッケージ管理コマンドは、dpkgコマンド　
リポジトリを利用したパッケージ管理コマンドは、apt-cacheコマンド、apt-getコマンド
転生できないからVimで2つのファイルの差分を確認してみた

### 状況
案件の対応で先方の都合？で
Bitbucketでコードの管理を行い
完成したコードをFTPを使って直接サーバーにコードをアップする
その際にコードの改修をする場合に仮にclone(pull)したコードが
先方のサーバーにあるコードと相違があった場合に意図しない処理が
先方のサーバーに上がってしまいトラブルの原因となってしまうので
その確認のために差分を見ることを実施したのでその忘備録

参考サイト
→ https://nanasi.jp/articles/howto/diff/diff_text.html

改修を予定しているAファイルを開いて下記コマンドを実行

```
:vertical diffsplit 差分を取りたいファイル
```
今回はBファイルと照らし合わせるとした場合には

```
:vertical diffsplit Bファイル
```

こうすることで画面が縦に２分割されて差分がみれる
なお自分がやったときには差分が無かった為
一行ほどに文言が書かれているだけだった。

もしこれで差分があった場合には
Bitbucketにあるファイルが古いのか
または先方のサーバーにあるファイルが古いのか
と気づけてその対応をすることによって
事前にトラブルを防ぐことができる
【Rails】混乱しがちなアソシエーションのclass_nameやforeign_keyを理解する

Railsでお知らせ機能やフォロー機能を実装しているとclass_nameやforeign_keyが出てくると思います。これらを理解するのに時間がかかったので、備忘録もかねて投稿します。

今回はお知らせ機能を例に挙げる。
イメージしやすいようER図を載せる。（最低限のカラムしか書いてません。）

![お知らせ機能ER図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/583698/31cc3e39-db27-39db-653d-e485bb4b87e5.png)

お知らせ機能を実装していると@user.passive_notificationsのようにして自分に来ている通知のレコードをまとめて取得したいことがある。そういう場合、下のように書く。

```ruby:user.rb
has_many :passive_notifications, class_name: "Notification", foreign_key: "visited_id"
```

少し複雑なので、簡単な例を挙げる。

### Userモデルで下記のように定義した場合
よく使うhas_many :tweetsは実は色々省略されている。

```ruby:user.rb
has_many :tweets

# 同じ意味
has_many :tweets, class_name: "Tweets", foreign_key: "user_id"
```
Railsで開発をするとhas_manyやbelongs_toを使ってモデルでリレーションを組むが、これを書くことによって、Userクラスへのticketsメソッドの定義が裏で行われている。例でいうと、ticketsメソッドの対象となるClassはTweetクラスで、ticketsテーブルのuser_idの値を参照してレコードを取得する。

Railsの規則によりモデルの複数形でメソッドを定義する場合、クラス名、外部キーを省略することができる。なぜならメソッド名により暗黙的にクラス名、外部キーが決定されるからである。

上記のようにメソッドを定義する(リレーションを組む)ことで、コントローラーなどで下のメソッドが使えるようになる。

```ruby:user.rb
@user = User.find(params[:id])
@user.tweets
```

少し脱線したが、このことを頭に入れてお知らせ機能のリレーションをもう一度見てみる。

```ruby:user.rb
has_many :passive_notifications, class_name: "Notification", foreign_key: "visited_id"
```

ここの記述では、Userモデルにpassive_notificationsメソッドを定義している。
メソッド名からはクラス名が不明なため、class_name: "Notification"として対象のクラスを明示している。また、外部キーを設定しない場合、notificationsテーブルからuser_idのカラムを探しにいってしまうため、foreign_key: "visited_id"として定義する。

これにより、@userのidとnotificationsテーブルのvisited_idとが一致したレコード、つまり@user宛の通知のレコードがまとめて取得できるようになる。

```ruby:user.rb
@user = User.find(params[:id])
@user.passive_notifications #ユーザ宛の通知のレコードを全件取得
```

以上です。
まちがっていたらご指摘お願いします。
HTML/CSSについて

今回は今まで習ったことの内容の中の、HTMLとCSSについてアウトプットしていきます！！

# HTMLについて
HTMLとはマークアップ言語の一つで簡単に言えば文字を表示するための言語です。入れ子構造になっている。
例）< h1 >文字を入力< /h1 >
上記のように左右をタグと呼ばれるもので囲み表示します。
タグには沢山種類があり、主要な物を下記に記します。
<h5>h1,h2,h3,h4...タグ</h5>見出しタグ。数字が大きくなっていくほど、小さい文字となる。
<h5>pタグ</h5>段落を指定するためのタグ。
<h5>headタグ、bodyタグ</h5>headタグには簡単に言えばHTMLの設定を記載する。bodyタグには実際にweb上に表示したい文字を記載
<h5>headerタグ、mainタグ、footerタグ</h5>この三つはbodyタグの中に記載するものになる。<br>※ <b>header</b>タグと<b>head</b>タグは間違えないようにしよう！！
<h5>divタグ</h5>ブロックレベル要素としてグループ化できる要素。基本的に何もない限りこのタグを使用する。
<h5>ulタグ、liタグ</h5>ulを親要素としてliタグを使用。基本的にlistとして使用するため、同じ意味合いを持つものをいれる。

# CSSについて
簡単に言えば、CSSとはHTMLで記述した文章に色やサイズ等を適用するための言語である。
例)
index.html

```html
<html>
  <head>
    <link rel = "stylesheet" href = "style.css">
  </head>
  <body>
    <div class = "class">背景が赤くなる</div>
    <div class = "class-j">
      <p>文字が赤くなる</p>
    </div>
  </body>
</html>
```

style.css

```css

.class{
  background-color: red;
}
p{
  color: red;
}
```

上記のように、HTMLの方でlinkタグを指定してあげることで、CSSが適用されるようになる。CSSはHTMLでclassを指定して使用することも可能であると同時に、要素を指定して使用することも可能。
また、CSSは上記で記載したように、プロパティ(background-color等)と呼ばれるものを記載することで色や大きさなどを変更することが可能。
プロパティの主要なものは下記に記載。

<h5>colorプロパティ</h5>
文字の色を変更
<h5>background-colorプロパティ</h5>
背景色を変更
<h5>font-sizeプロパティ</h5>
文字のサイズを変更
<h5>heightプロパティ</h5>
高さを指定できるプロパティ
<h5>widthプロパティ</h5>
幅を指定できるプロパティ

<h4>HTMLの表示について</h4>
HTMLは箱のような形になっており、外から順にmargin,border,paddingとなっている。それらの幅の指定を行う方法が下記のプロパティである。
<h5>marginプロパティ</h5>
外のサイズを指定できるプロパティ
<h5>paddingプロパティ</h5>
内側のサイズを指定できるプロパティ
<h5>borderプロパティ</h5>
marginとpaddingの間の線の部分を指定できる。

# FlexBoxとは

HTMLが箱のようなものと前述に記したと思うが、この箱を自由に動かす便利な概念みたいな物。
基本的に下記を使用する。
<h5>display: flex</h5>
親要素に指定すると、小要素のブロックが全て横並びになる。
<h5>justify-content: A;</h5>
親要素に指定すると子要素の互いの横幅を一括で指定することが可能。Aにはspace-aroundやspace-betweenなどを指定する。
<h5>align-items: A;</h5>
親要素に指定すると小要素の縦の位置を一括で調整できる。Aにはcenterなどを用いる。
<h5>float: A;</h5>
子要素に指定すると横並びになる。Aにはrightとleftが入る。
※ floatとdisplay: flex;は、一見似たようなものに見えるが、display: flex;の方が圧倒的に移動できる範囲が広いため、floatはあまり使用されない。

# まとめ
まだまだ、色々なタグやプロパティが存在するが、この範囲はいずれ何度も行う内容だと思うので、開発の際にその都度公式リファレンスを確認すると良いのではないかと思います。
AtCoder Beginner Contest 125 C - GCD on Blackboard 反省log 緑色

## 概要

[hirokihello](https://twitter.com/maxyasuda)の解けずに解説を見た問題を、なぜ解けなかったかの分析log

## 問題について

長さnの数列について、i=1~nを満たすaのi番目の要素全ての最大公約数を、最大にするように数列から一つ要素を選び書き換える。

https://atcoder.jp/contests/abc125/tasks/abc125_c

## 思考

まず書き換えるものi番目として、それをそれ以外の最大公約数とすることでi番目を書き換えた時の最大値となることが思いついた。

しかし、それ以外の全ての数列の最大公約数の求め方が思いつかず、愚直に全てのiでi以外を求める方針以外思いつかなかった。

これだと計算量がO(n^2)になり、制約が1e5なので1e10でTLEすることから断念した。

## 足りなかった思考

- iを選びi番目以外の最大公約数を求める時に、左右にさらに分割して部分問題にする点
- 左右に分割したものを求める時にそれぞれをDPで分割して計算量を減らす発想。
- そもそもDPを使うという発想

これらを抽象化すると、さらに小さい問題に分割することがまだまだできていない。

## 具体的な解法

i番目を取り除いた、左側の数列の最大公約数は、i-1番目の左側の数列と、数列のi-1番目との最大公約数で求めることができる。
i番目を取り除いた、右側の数列の最大公約数は、i+1番目の右側の数列と、数列のi+1番目との最大公約数で求めることができる。

イメージとしては、左からのDPと、右からのDPの二つを作っていくイメージである。

それぞれを合計n個づつ求めて、最後に1~nまでのそれぞれを取り除いたのを求めたものを使ってとけばいい。

全てDPで計算量を減らせばいいので、O(n log 1e9)となる(log 1e9は最大公約数を求める時の最大値)

#### 結論

細かい問題に分割していくことが大事....

その力が足りてなかった.....
【OpenAPI】定義ファイルを分割して管理する

# はじめに
そこそこの規模のアプリでOpenAPIを導入すると、1つのYAMLファイルで管理し続けるには限界があります。定義ファイルの分割と、分割した定義ファイルの参照について情報をまとめました。

# 対象バージョン
OpenAPI Specification Version 3.0.3

# 定義ファイルの分割
肥大化していたり、使い回すことの多いスキーマやコンポーネントを中心に、別ファイルに切り出します。
切り出したファイルは、参照元が参照できる任意の構成で設置することができます。
個人的には、OpenAPIのコンポーネント構造と同じディレクトリ構成にすると直感的で分かりやすいと感じています。

```txt:ディレクトリ構成例
openapi.yaml
paths/
    items.yaml
components/
    schemas/
        item.yaml
```

# 参照
別ファイルに記載したスキーマ等を呼び出すには `$ref` を用います。ファイルパスは相対パスで指定します。

[Using $ref - swagger.io](https://swagger.io/docs/specification/using-ref/)

```yaml:openapi.yaml
# 省略

paths:
  /items:
    $ref: "paths/items.yaml"  # paths ディレクトリ内の items.yaml ファイルを参照する

components:
  schemas:
    Item:  # 別の箇所からスキーマ名で参照できるようになる
      $ref: "components/schemas/item.yaml"
```

```yaml:paths/items.yaml
# 省略

responses:
  200:
    content:
      application/json:
        schema:
          type: array
          items:
            # openapi.yaml で定義したスキーマを参照する場合
            $ref: "../openapi.yaml#/components/schemas/Item"  

            # 直接ファイルを参照する場合
            $ref: "../components/schemas/item.yaml"
```

定義ファイルの記述にVSCodeを使用していれば、拡張機能をインストールすることで参照先にコードジャンプできるようになります。

[OpenAPI (Swagger) Editor](https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi)

# 定義ファイルのバンドル

ツールを使って定義ファイルをバンドルします。

[swagger-cli](https://apitools.dev/swagger-cli/)


# 参考
- [OpenAPI Specification - Version 3.0.3 | Swagger](https://swagger.io/specification/)
- [OpenAPI (Swagger) Editor](https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi)
- [swagger-cli](https://apitools.dev/swagger-cli/)
YouTubeのチャット欄取得をチャレンジ

## はじめに
YouTubeのチャット欄のデータを取ろうとして解決していない話です。

## 前提
YouTubeはスクレイピング(クローリング)禁止です。

[YouTube利用規約](https://www.youtube.com/static?template=terms&hl=ja&gl=JP)の「本サービスの利用 > 許可と制限事項」を引用
> 本サービスの利用には制限があり、以下の行為が禁止されています。
> ...
> 3. 自動化された手段（ロボット、ボットネット、スクレーパなど）を使用して本サービスにアクセスすること。ただし、（a）公開されている検索エンジンをYouTube の robots.txt ファイルに従って使用する場合、または（b）YouTube が事前に書面で許可している場合を除きます。
> ...

ですので、スクレイピングでチャット情報やスパチャの金額を取得するのは利用規約違反です。

## やってみたこと
とりあえず、配信中のvideosに含まれているactiveLiveChatId(liveStreamingDetails.activeLiveChatId)を元にYouTube LiveStreaming APIを叩いてみる。

## リクエスト
- https://www.googleapis.com/youtube/v3/liveChat/messages
- key={APIキー}
- part=snippet,authorDetails
- liveChatId={liveStreamingDetails.activeLiveChatId}
- maxResults=2000

## 結果
- [APIリファレンス](https://developers.google.com/youtube/v3/live/docs/liveChatMessages/list
)にmaxResultsは200～2000と記載があるのに70件程度しか返却されてこない。
- 10,000件チャットがあったら約143回程度実行する必要がある。クォータに関しては後述。

## クォータ(APIの利用回数)
- クォータが許すなら、配信が終了したタイミング(を何とか見つけて)で、activeLiveChatIdが消える前にAPIを叩こうかとも思ったけれどもYouTube Live Streaming APIのQuotaは[YouTube Data APIのQuota
Calculator](https://developers.google.com/youtube/v3/determine_quota_cost)にそれとなくLive Streaming APIのクォータに言及はあるが対応するクォータが見つけられない。
- stackoverflowを探すにリソースに対応するらしいのだが、LiveChatMessagesに対応するようなリソースが見つけられない。
- video内のリソースと思われlist取得なので「1」だとしても、仮に最大1万チャットあるとして1クォータで70件の取得と見積もると143回。
- 大体、1日の配信数は40～60程度なので、多くて60だとして8,580回。
- あれ、意外といけるのでは…。
- チャット数ってどのくらいなのだろう。1万は少なすぎな気がしてきた。

## その他気になった事
- YouTube利用規約内、以下の内容からするに、チャット情報を取得しても、チャットのユーザー名を保持するのはダメっぽい。
- メッセージ本文とかスパチャの金額だけならセーフだと思われる。

> 4. 個人を特定できる可能性のある情報（ユーザー名など）を収集または取得するこ
と。ただし、その人物が許可している場合および本項第３号で認められている場合を
除きます。

## 現状の結論(状況)
- チャット数と消費クォータ数が未知数なので、今度適当な配信で試してみようと思う。

## 後日談
- liveChatの取得は諦めた。詳細は[別記事](https://qiita.com/DevIwatan/items/0c3b61db9b40d8e5d6d7)参照。
Ionic SplashScreenとStatusBarはCapacitorのプラグインを使うと警告が消えた

#はじめに
XcodeでIonic + Capacitorアプリをビルドすると、よく見かけるこのエラー。。。

```console
[warn] - Native: tried calling SplashScreen.hide, but the SplashScreen plugin is not installed.
⚡️  [warn] - Install the SplashScreen plugin: 'ionic cordova plugin add cordova-plugin-splashscreen'

[warn] - Native: tried calling StatusBar.styleDefault, but the StatusBar plugin is not installed.
⚡️  [warn] - Install the StatusBar plugin: 'ionic cordova plugin add cordova-plugin-statusbar'
```

**特にビルドが失敗するわけでもなく、警告が出るだけで何事もなく動作するアプリ:thinking:**

いったいこのエラー（ではなく警告）は何なのか？
**ついに解決しました！**

#原因はcordovaのプラグインをcapacitorで使ってる事??
https://github.com/ionic-team/capacitor/issues/3511
>Ionic angular templates are still cordova templates and include some cordova plugins. For now you have to manually replace those plugin usages with capacitor plugin equivalents until the templates are updated.

ふむふむ、要するに。。
**Ionic + Angularのテンプレートではデフォルトでcordovaのプラグインが含まれてるが、テンプレートがまた更新されていないうちは手動でCapacitorのプラグインに置き換えてね！**

ということだろう。。

「テンプレート」というのは、シンプルに`ionic start`のコマンドで作られるやつのことかな？



##Splash Screen
https://capacitorjs.com/docs/apis/splash-screen

`@ionic-native/splash-screen/ngx`の代わりに、capacitorのプラグインを使う

```typescript:app.component.ts
// import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { Platform } from '@ionic/angular';
import { Plugins } from '@capacitor/core';
const { SplashScreen } = Plugins;

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent  {
constructor(
    private platform: Platform,
  ) {
    this.initializeApp();
}

initializeApp() {
  this.platform.ready().then(() => {
      SplashScreen.show({
          autoHide: false
        });
     // do something
    SplashScreen.hide();
      });
 }
}
```

##Status Bar
https://capacitorjs.com/docs/apis/status-bar

`@ionic-native/status-bar/ngx`の代わりに、capacitorのプラグインを使う


```typescript:app.component.ts
// import { StatusBar } from '@ionic-native/status-bar/ngx';
import { Platform } from '@ionic/angular';
import { Plugins, StatusBarStyle } from '@capacitor/core';
const { StatusBar } = Plugins;

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss']
})
export class AppComponent  {
constructor(
    private platform: Platform,
  ) {
    this.initializeApp();
}

initializeApp() {
  this.platform.ready().then(() => {
      SplashScreen.show({
          autoHide: false
        });
     // do something
    StatusBar.setStyle({ style: StatusBarStyle.Light });
    SplashScreen.hide();
      });
 }
}
```

ちなみに、Status Barというのは電波とか電池かが表示されてる部分
`style: StatusBarStyle.Dark`だと、画像のように背景が黒の時のカラーになる
![スクリーンショット 2020-11-16 23.00.13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/eacc7078-a72b-7749-0146-ed6cfbefeaed.jpeg)


#参考
https://forum.ionicframework.com/t/statusbar-text-color-not-changing-for-iphone-11/189392/2
【Rails】ユーザ入力情報の保護機能

<h1>本投稿の目的</h1>
・Rails学習の議事録です。

---
<h1>学習に使った教材</h1>
Udemyの ["はじめてのRuby on Rails入門-RubyとRailsを基礎から学びWebアプリケーションをネットに公開しよう"](https://www.udemy.com/course/the-ultimate-ruby-on-rails-bootcamp/) を教材として使用しました。

---

<h1>①Validates(バリデート)</h1>
・modelファイルに対して実施
・ユーザーが入力した値をdb保存する際の条件を指定できる
・Ex)空入力禁止,最大文字数10文字まで...

```ruby:qiita.rb
def model名
  validates :column名, 条件: 値の指定
end
```

【解説】
○validates :column名
⇒条件を課したいcolumn名を記載

○条件: 値の指定
⇒実施したい制約に応じた記述法を記述
⇒以下に2つ例を記述する

・空入力禁止

```ruby:qiita.rb
presence: true
```
・最大文字数10文字まで

```ruby:qiita.rb
length: { maximum: 10 } 
```

<h1>②params</h1>
・配列を入れるための箱(ハッシュ)
・ユーザーが送信したデータを一時的にparamsに格納
・その中から,必要なハッシュにヒットする値を取り出す

【例: ユーザーが名前と年齢をフォームから送信した場合】
・フォームからparams へ次のように格納される

```ruby:qiita.rb
params = [:name,'naoto', :age,24]
```
・名前を取得したい場合

```ruby:qiita.rb
 params[:name]
```
・年齢を取得したい場合 

```ruby:qiita.rb
params[:age]
```
<h1>③strong_parameters</h1>
・指定したcolumn情報以外のフォーム受信値を無視するフィルター

【いつ役に立つ?】
・ECサイトを作成したと想定
・ユーザーがフォームでソースを操作
・ポイントcolumnを修正し残高を高めに変更
・こういった改ざん処理を止めるための設定

【使いかた】
・controller中に記述(フォーム送信後のインスタンス生成時)
・引数にこのメソッドを()で指定する
・フィルタされた値がdbへ格納

**【例:question_paramsメソッド】**

```ruby:qiita.rb
params.require(:question).permit(:name, :title, :content)
```
【paramsには以下が格納された場合を想定】

```ruby:qiita.rb
params = [
question={name: 'naoto',age: 24, content: '質問内容'},
answer={name: 'kanopyo',age: 27, content: '回答内容'}
]
```


【解説】
〇.requireについて
⇒モデル名をキーに指定

〇.permitについて
⇒.requierで指定したモデルのプロパティをキーに指定
AWS BeanstalkでLaravelをデプロイするときにCloudwatch Logsにログを転送する

# 前提のBeanstalk環境

PHP 7.4 running on 64bit Amazon Linux 2/3.1.3

# やること
- lavavel.logのパーミッション設定
- EC2にCloudwatch Logsのロググループ作成のためのサービスロールを追加
- 設定ファイル（.ebextensions）の作成


# 1. lavavel.logのパーミッション設定

```sh
$ chmod 0664 /var/www/html/storage/logs/laravel.log
```

# 2. lavavel.logのパーミッション設定
- Beanstalk環境のIAM インスタンスプロフィールに設定されているIAMロールに、CloudWatchLogsFullAccessのポリシーを追加
（Codepipelineでデプロイしている場合は、そのロールにも同様にCloudWatchLogsFullAccessのポリシーを追加）


# 3. 設定ファイル（.ebextensions）の作成

- PHP Platformでデフォルトで追加されるログの設定

参考: https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/AWSHowTo.cloudwatchlogs.html

```yml:.ebextensions/4-eblog.config
option_settings:
  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: StreamLogs
    value: true

  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: DeleteOnTerminate
    value: false

  - namespace: aws:elasticbeanstalk:cloudwatch:logs
    option_name: RetentionInDays
    value: 7
```

- カスタムログでlaravel.logを設定する

参考: https://github.com/awsdocs/elastic-beanstalk-samples/blob/master/configuration-files/aws-provided/instance-configuration/logs-streamtocloudwatch-linux.config

```yml:.ebextensions/5-laravellog.config
packages:
  yum:
    awslogs: []

files:
  "/etc/awslogs/awscli.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [plugins]
      cwlogs = cwlogs
      [default]
      region = `{"Ref":"AWS::Region"}`

  "/etc/awslogs/awslogs.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [general]
      state_file = /var/lib/awslogs/agent-state

  "/etc/awslogs/config/logs.conf" :
    mode: "000600"
    owner: root
    group: root
    content: |
      [/var/www/html/storage/logs/laravel_log]
      log_group_name = `{"Fn::Join":["/", ["/aws/elasticbeanstalk", { "Ref":"AWSEBEnvironmentName" }, "var/www/html/storage/logs/laravel_log"]]}`
      log_stream_name = {instance_id}
      file = /var/www/html/storage/logs/laravel*

commands:
  "01":
    command: systemctl enable awslogsd.service
  "02":
    command: systemctl restart awslogsd

```
[Swift] 数値を漢数字に変換する

`NumberFormatter`を使えばいいです。が、いくつか注意点があります。

```swift
//漢数字
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut
formatter.locale = .init(identifier: "ja-JP")
let number = 123456789012345678
if let string = formatter.string(from: NSNumber(value: number)){
    print(string)   //十二京三千四百五十六兆七千八百九十億千二百三十四万五千六百七十八
}
```
まずロケールを指定しないと`.spellOut`に設定しても英語になります。

数値が負だった場合はしっかり「マイナス」と付けてくれるので安心です。
ただ、数値が「百京」を超えると変換してくれず、代わりに三桁区切りの数字が返ってくるようになります。

```swift
let numberA = Int(1E18)
let numberB = Int(1E18) - 1

if let string = formatter.string(from: NSNumber(value: numberA)){
    print(string)   //1,000,000,000,000,000,000
}
if let string = formatter.string(from: NSNumber(value: numberB)){
    print(string)   //九十九京九千九百九十九兆九千九百九十九億九千九百九十九万九千九百九十九
}
```

`Int`のみを対象とするなら、実用的にはこのような関数を作っておく必要があると思います。

```swift
func toKansuji(from number: Int) -> String? {
    if number >= Int(1E18){
        return nil
    }
    if number <= -Int(1E18){
        return nil
    }
    return formatter.string(from: NSNumber(value: number))
}
```
湯婆婆言語作ってみた

# 湯婆婆言語作ってみた
Qiitaで湯婆婆のセリフをいかに短く実装するかブームらしいので自作言語を作って
実装した話です
ソースコードはここにのってます
https://github.com/riya-amemiya/yuba

うぷ主の環境

- macOS Big Sur 11.0.1
- Node 12.16.3

手順
1. 自作言語の構文を考える
2. トランスパイル先の言語を決める
3. ファイルを読みこむ
4. トランスパイラを作る
5. トランスパイラをビルドする

手順は僕の他の記事に詳しく書かれているので省きます
この記事のソースコードを少し変えただけです
https://qiita.com/riya81/items/b1d5261205d13e4740cb

## コマンド

```shell
y "名前";
```

これだけで湯婆婆を実装できます
この機能しかないです

## まとめ

まとめることなんかほぼ無いうっすい記事ですが以上
湯婆婆言語を作った話でした
でかいデータのAjaxリクエストを圧縮して軽くしてPHPで受け取る

数MBくらいあるデータをリクエストボディに載せたいけど、少しは軽くしたいのでゴニョゴニョ。

## JS側

```js
import pako from 'pako'
import axios from 'axios'

const bigObject = { /* 超でかいObject */ }
const json = JSON.stringify(bigObject)
const gzipped = pako.gzip(json, { to: 'string' })
const base64Encoded = btoa(gzipped)
axios.post('/api/foo', { compressed: base64Encoded })
```

- JSONにする
- [pako](https://www.npmjs.com/package/pako) を使ってgzip圧縮する
- [btoa()](https://developer.mozilla.org/ja/docs/Web/API/WindowOrWorkerGlobalScope/btoa) を使ってBase64エンコードする
- 文字列としてリクエストする

## PHP側

```php
$gzipBinary = base64_decode($_POST['compressed']);
$json = gzdecode($gzipBinary);
$data = json_decode($json, true);
```

- [base64_decode()](https://www.php.net/manual/ja/function.base64-decode.php) でbinaryにデコードする
- [gzdecode()](https://www.php.net/manual/ja/function.gzdecode.php) でgzipを解凍してJSON文字列にする
    - [ext-zlib](https://www.php.net/manual/ja/zlib.installation.php) が必要
- [json_decode()](https://www.php.net/manual/ja/function.json-decode.php) で配列にする

余計な処理は入るけど、リクエストボディが `1.5MB` から `250KB` くらいまでは小さくなったので満足。
複数のprotoファイルから出力するswaggerファイルを1つにまとめるお話

# はじめに
[前回記事](https://qiita.com/kito_engineer/items/81acd1d143d12a380c74)に引き続き、今回もprotoファイルを分けた時の困りごとについてです。

例えば増えすぎたserviceを複数ファイルに分けて記述するようにしたときに、そのままそこからswaggerファイルを出力しようとするとprotoファイルの数だけswaggerファイルが出来上がってしまいます。
それは絶対にやだやだということで複数protoファイルからswaggerファイル1つにまとめて出力する方法を調べたところ日本語情報がなかったようだったので残しておきます。

# 実践
このようなディレクトリ構造だった場合について考えます。

```
.
└── pb
    ├── swagger
    └── type
        ├── item.proto
        ├── shop.proto
        └── user.proto
```

普通に下記のようなコマンドでprotoファイルからswaggerファイルを出力するとそれぞれのファイルが出力されてしまうと思います。

```
protoc -I<pb/typeのパス> -I${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis --swagger_out=logtostderr=true:./pb/swagger ./pb/type/*.proto
```

出力ファイル

```
.
└── pb
    ├── swagger
    │   ├── item.swagger.json
    │   ├── shop.swagger.json
    │   └── user.swagger.json
    └── type
        ├── item.proto
        ├── shop.proto
        └── user.proto
```

そこでprotoファイルを1ファイルにまとめるには先ほどのコマンドに ``allow-merge=true`` オプションと ``merge_file_name=<出力ファイル名>``オプションを追加することで1つのswaggerファイルにまとめられます。


```
protoc -I<pb/typeのパス> -I${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis --swagger_out=logtostderr=true,allow-merge=true,merge_file_name=api:./pb/swagger ./pb/type/*.proto
```

出力ファイル

```
.
└── pb
    ├── swagger
    │   └── api.swagger.json
    └── type
        ├── item.proto
        ├── shop.proto
        └── user.proto
```

# 参考
https://medium.com/golang-diary/7-tips-when-working-with-grpc-gateways-swagger-support-afa0c2d671d8
【Unity】マルチディスプレイにおける座標の扱い

# はじめに
Unityでは、スタンドアロンモードのみマルチディスプレイに対応しています。（対応OS：Windows、Mac、Linux）

Windowsでマルチディスプレイ対応のアプリを作成していたところ、
座標の扱いで何度か混乱してしまったため、書き留めておきたいと思います。

# 環境
- Windows 10
- Unity 2019.2.19f1
- Visual Studio 2019

# スクリーン座標とワールド座標
Unityをさわったことがある方ならご存知だと思いますが、Unityの座標にはスクリーン座標系とワールド座標系が存在します。
スクリーン座標系は画面上の座標で、左下隅が (0, 0)となります。
ワールド座標系はUnityのゲーム空間上の座標で、Scene直下にあるオブジェクトであればInspectorのTransform > Position の値となります。
![ワールド座標・スクリーン座標.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367596/8e0d40f5-edea-1089-9bc8-81c6a0c0be18.png)
マウス位置（Input.mousePosition）は画面上のどこかを表すものなので、当然スクリーン座標系となります。

# マルチディスプレイの場合のマウス位置は？
マルチディスプレイの場合、Input.mousePositionで取得できる座標は、メインディスプレイ基準の座標となります。
例えば、1920 x 1080のディスプレイ2台を以下のように配置していた場合
![ディスプレイ配置.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367596/88675de3-543a-0020-0e4d-8f8006fff381.png)
座標は以下のようになります。
![ディスプレイ配置2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367596/0519982d-10b4-4828-b0b0-3f4231a509f9.png)

# ワールド座標に変換したい
取得したマウス位置の座標をワールド座標に変換するには、
① 画面ごとのスクリーン座標に変換
② 該当する画面のカメラでワールド座標に変換
の2段階の変換を行う必要があります。

```C#
    // cameras という変数に、ディスプレイ番号順のカメラが保持されている想定です

    private Vector2? ConvertScreenPointToWorld(Vector2 position)
    {
        // 1. 画面ごとのスクリーン座標に変換
        // ※ 各画面の左下隅を(0, 0)とする座標に変換されます
        var relativePosition = Display.RelativeMouseAt(position);
        // ※ 気持ち悪いですが、z座標にディスプレイ番号がセットされます...
        var displayIndex = (int)relativePosition.z;
        if (displayIndex >= cameras.Count) return null;

        // 2. 該当する画面のカメラでワールド座標に変換
        var camera = cameras[displayIndex];
        return camera.ScreenToWorldPoint(relativePosition);
    }
```

ちなみに、Unityエディター上では `Display.RelativeMouseAt()` は動作しないのでご注意ください。
CSSグリッド活用によるレスポンシブ対応

#はじめに
現在オリジナルアプリを作成中です。投稿した画像を一覧で表示するページを作成しました。一覧を見栄え良くするため、タイル型レイアウトを採用しました。具体的手段はグリッドの活用です。忘れないように書き記します。

**開発環境**
ruby 2.6.5
Rails 6.0.3.4
HTML
CSS

#目次
1.HTMLの準備
2.CSSの設定

#HTMLの準備
タイル状にしたい部分全体(親要素)をdivタグで囲い、クラス名をわかりやすく「grid」とつける。
補足：Ruby on Railsでアプリを制作しています。

```html:index.html.erb
<div class = "wrapper grid"> #全体をdivで囲み、クラス名gridを追加する
  <% @desks.each do |desk| %>
    <%= link_to desk_path(desk.id) do %>
        <%= image_tag desk.image, class: "desk-img" %>
        <p>
          <%= desk.title %>
          <%= "by#{desk.user.nickname}さん" %>
        </p>
    <% end %>
  <% end %>
</div>
```

#2.CSSの設定
※最終コードは一番下にあります。

CSSではdisplayプロパティにgridを設定する。これにより、子要素はタイル状にレイアウトされる。タイル間の余白はgapプロパティで設定する。

```css:index.css
.grid {
  display: grid;
  gap: 26px;
}
```

次に各タイルの横幅設定をする。grid-template-columsプロパティにより、横に並べたいタイルの枚数だけfrを設定する必要がある。ここで1frは親要素に対する横幅を自動で調整する。下記の場合、1frが3つあるので、1:1:1の3等分されたグリッドが配置される。もし1fr 2fr 1frのように設定した場合、タイル枚数は3枚であるものの、各タイル幅は左から1:2:1となる。

```css:index.css
.grid {
  display: grid;
  gap: 26px;
  grid-template-columns: 1fr 1fr 1fr;
  margin-top: 6%;
  margin-bottom: 50px;
}
```

最後にレスポンシブ化を記す。repeat関数を使うことにより、タイル数を指示し、コードを簡略化できる。

```css:index.css
.grid {
  display: grid;
  gap: 26px;
  grid-template-columns: repeat(3, 1fr); /*　1fr 1fr 1frと同じ　*/
  margin-top: 6%;
  margin-bottom: 50px;
}
```
またminmaxを使うことにより、1タイルの最小と最大幅を設定できる。下記の場合、最小値を240px、最大値を1fr(親要素の3等分相当)となる。最大値は親要素の幅(画面サイズ)に依存する。一方で最小値は24opxに固定され、これ以上は小さくならない。

```css:index.css
.grid {
  display: grid;
  gap: 26px;
  grid-template-columns: repeat(3, minmax(240px, 1fr)); /*　1fr 1fr 1frと同じ　*/
  margin-top: 6%;
  margin-bottom: 50px;
}
```

最終コードを下記に記す。上記おrepeat関数のタイル数を表す「3」をautofitに書き換えた。これにより、画面の幅に応じて最適なタイル数を自動で表示する。

```css:index.css
.grid {
  display: grid;
  gap: 26px;
  grid-template-columns: repeat(autofit, minmax(240px, 1fr)); /*　1fr 1fr 1frと同じ　*/
  margin-top: 6%;
  margin-bottom: 50px;
}
```

参考：
[1冊ですべて身につくHTML-CSSとWebデザイン入門講座](https://www.amazon.co.jp/1%E5%86%8A%E3%81%A7%E3%81%99%E3%81%B9%E3%81%A6%E8%BA%AB%E3%81%AB%E3%81%A4%E3%81%8FHTML-CSS%E3%81%A8Web%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E5%85%A5%E9%96%80%E8%AC%9B%E5%BA%A7-Mana/dp/4797398892/ref=asc_df_4797398892/?tag=jpgo-22&linkCode=df0&hvadid=295723231663&hvpos=&hvnetw=g&hvrand=14579486333190010068&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009202&hvtargid=pla-637663128882&psc=1&th=1&psc=1)

以上