OmniAICreator/Qiita-1.07M huggingface dataset:
Mac + Atom + PlantUMLの環境構築

MacでPlantUMLを使いたくなったので、環境構築をします！

# PlantUMLとは？
テキストベースでUMLを描けるツールです。
例えば、ユースケース図を描きたい場合は、こんな感じになります。
テキストファイルの拡張子は「pu」です。

~~~java:ユースケース図.pu
@startuml
left to right direction
skinparam packageStyle rectangle
actor 一般ユーザー
actor 管理者
rectangle 勤怠システム {
  一般ユーザー -- (勤怠入力・参照)
  (勤怠入力・参照) -- 管理者
  (ユーザー情報更新・参照) -- 管理者
  (勤怠一括エクセル出力) -- 管理者
}
@enduml
~~~

**ユースケース図**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/2d98920f-e8a9-3ad2-3567-3dbf9a0fe5c7.png)

# 環境
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/5718c3bf-12a1-1067-0f6e-d448fb614793.png)

# インストール項目
・Java
・Atom
・graphviz
・plantuml
・Atomパッケージ(plantuml-preview,language-plantuml)

# JavaとAtomのインストール
ご自由にお願いします。

# graphvizとplantumlのインストール

~~~
brew install graphviz
brew install plantuml
~~~

# Atomパッケージのインストールと設定
Atom→Preferencesを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/4850d65d-52a7-6058-1174-bf9fa73b28f7.png)
Settings→Installを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/87bce1da-d4b1-795d-5163-974b40d18dda.png)
plantuml-preview、language-plantumlでそれぞれ検索し、インストールする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/3d315360-0343-a5cd-2c56-2fcd8d79bf82.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/b68b190d-f093-b30e-b83b-cc5eae4c2729.png)
puファイルを開き、Packages→PlantUML Preview→Toggleでプレビューを表示する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/a00ae1ca-c3e6-e94b-e630-3e6a986be2bc.png)
「plantuml.jar is not a file.」のエラーが出ので、「Open Package Settings」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/ee4f7753-12ce-a1be-a87f-6479aac55a02.png)
ターミナルで以下のplantuml.jarの場所「/usr/local/Cellar/plantuml/1.2021.0/libexec/plantuml.jar」をコピーする

~~~bash:ターミナル
$ which plantuml
/usr/local/bin/plantuml
$ cat /usr/local/bin/plantuml
#!/bin/bash
if [[ "$*" != *"-gui"* ]]; then
  VMARGS="-Djava.awt.headless=true"
fi
GRAPHVIZ_DOT="/usr/local/opt/graphviz/bin/dot" exec "/usr/local/opt/openjdk/bin/java" $VMARGS -jar /usr/local/Cellar/plantuml/1.2021.0/libexec/plantuml.jar "$@"
~~~

plantuml-previewのSettingsの「PlantUML Jar」の項目に貼り付ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/c5c91fe2-e3ea-f723-bdfa-c806229e0a34.png)

もう一度実行すると、プレビューが表示されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/558865/967d42d6-c7dd-75dd-b5bd-fca5c0668d9c.png)



# 参考
https://qiita.com/aminevsky/items/c77b13e4ec6db230ea60
https://springwell.hatenablog.com/entry/2018/05/21/075829
[PlantUMLの使い方](https://plantuml.com/ja/)
Javascriptで入れ子の配列やオブジェクトをコピーする際の注意点

仕事でnode書いている時にオブジェクトの参照渡しで思わぬ挙動が起きることがよくありました。
参照渡しと値渡しの違いについては下の記事を参考にしてください。
今回は、オブジェクトを配列で持つ変数の注意点です。

[もう一度理解する、JavaScriptの配列とコピー](https://qiita.com/Tatamo/items/444969a7ff2fbba30479)

## 配列を代入ではなくコピーする
配列を複製してオリジナルとコピーした変数を使いたくなる場面が少なからずあると思います。
そんな時によくやってしまいがちなのが参照渡しです。
この場合、変数bの要素だけを変更したとしても、変数aまで変わってしまいます。

```js
const a = [1, 2, 3];
const b = a; 

console.log(a); // 1, 2, 3
console.log(b); // 1, 2, 3

b[0] = 4;

console.log(a); // 4, 2, 3
console.log(b); // 4, 2, 3
```

aまで変わったらオリジナルじゃないじゃん！って嘆くことってありますよね。（自分はよくやらかしてました）
よく解決策として上げられるのが[concat](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/concat)という関数です。
他にも方法があると思いますが、筆者はこれをよく使うので今回はconcatにだけ着目します。

concat関数は元の配列に対して引数の要素を付け加える関数ですが、新しく配列を生成するのでオリジナルの変数とは参照先が異なる値を持つことになります。
そのため、コピー先の要素を変更してもオリジナルの変数が変更されることはありません。

```js
const a = [1, 2, 3];
const b = a.concat(); 

console.log(a); // 1, 2, 3
console.log(b); // 1, 2, 3

b[0] = 4;

console.log(a); // 1, 2, 3
console.log(b); // 4, 2, 3
```

これが配列の代入ではなくコピーです。

## オブジェクトの配列をconcatしたらどうなるか
表形式でデータを表示する場合など、オブジェクトを配列の形式で持つことがあると思います。

```js
const a = [{"key1" : "value1"}, {"key2" : "value2"}]
```

それではいつものようにこいつをconcatでコピーして中のオブジェクトを更新してみましょう。

```js
const a = [{"key1" : "value1"}, {"key2" : "value2"}];
const b = a.concat();

console.log(a); // [ { key1: 'value1' }, { key2: 'value2' } ] 
console.log(b); // [ { key1: 'value1' }, { key2: 'value2' } ]

b[0]["key1"] = "value3";

console.log(a); // [ { key1: 'value3' }, { key2: 'value2' } ] 
console.log(b); // [ { key1: 'value3' }, { key2: 'value2' } ]
```

あれ？変数aも変わってるやん・・・コピーしたはずなのに・・・
なんてことがあったので解決策調べてまとめて、今回の記事を作成しました(前置きが長い)

## 中のオブジェクトもコピーしよう
concatで配列をコピーしたところで、中のオブジェクトのキーの参照先はオリジナルとコピーで同じものになる、つまり更新すれば片方も変わることになります。
それなら中のオブジェクトもコピーしてしまおう！という発想で解決しました。

```js
const a = [{"key1" : "value1"}, {"key2" : "value2"}];
const b = a.map((obj) => Object.assign({}, obj));

console.log(a); // [ { key1: 'value1' }, { key2: 'value2' } ] 
console.log(b); // [ { key1: 'value1' }, { key2: 'value2' } ]

b[0]["key1"] = "value3";

console.log(a); // [ { key1: 'value1' }, { key2: 'value2' } ] 
console.log(b); // [ { key1: 'value3' }, { key2: 'value2' } ]
```

[assign](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)関数はオブジェクトをマージして新しくオブジェクトを作ってくれる関数です。
こんな面倒なことしなくてもいい感じに配列コピーしてくれよ、って思いますがプログラムは思い通りにいかないもんですね。
しかもこれ、オブジェクトの中が配列やオブジェクトになるとさらにconcatやらassignやらやらないといけなくなることに後々気づきました。


## おわりに
配列やオブジェクトをコピーして使う時には、参照渡しや値渡しを意識しながら使う必要があります。
Javascriptに限らず様々な言語でも同じ事象は発生するので、今回のような事象を機にプログラミング言語を詳しく知っていくことも大事かなと思います。

---

ちなみに記事を書く過程で色々調べていたら、今回のように入れ子になった配列やオブジェクトをコピーすることをディープコピーということが分かりました。
しかもディープコピー用のライブラリとかもあるらしいので、先人たちって偉大だなと痛感しました。（というか早く知りたかった！）
[[JavaScript]色々なディープコピー](https://qiita.com/knhr__/items/d7de463bf9013d5d3dc0)

初投稿につき稚拙なところはご容赦ください。
最後まで閲覧いただきありがとうございました。
nemo


```shell

$ source ~/my_libs_3/nemo/nemo_start.sh
$ cd ~/my_libs_3/nemo/bin
$ ls mk*

mkbaredisk    mkgalaxy  mkplum
mkbodiesfunc  mkhalo    mkplummer
mkbodyfunc    mkhom     mkpolytrope
mkconfig      mkhomsph  mksingle
mkcube        mkking    mksphere
mkdehnen      mknemo    mkspiral
mkdisk        mkommod   mktestdisk
mkexpdisk     mkop73    mkWD99disc
mkexphot      mkorbit
mkflowdisk    mkpdoc


$ mkhomsph help=
mkhomsph out=??? nbody=2048 rmin=0 rmax=1.2 2t/w=0.0 vmax=0 
power=0 seed=0 zerocm=t headline= VERSION=1.4c
```


http://jun-makino.sakura.ne.jp/kougi/simulation2009/makino/jisshuu-2009.pdf

https://www.cfca.nao.ac.jp/~cfca/hpc/muv/text/note.pdf

```shell
$ cd ~/my_libs_3/nemo
$ find . -name mktestdisk*
./bin/mktestdisk
./man/man1/mktestdisk.1
./man/doc/mktestdisk.doc
./src/nbody/init/mktestdisk.c
./docs/man_html/mktestdisk.1.html

```
Outlook 最小化のときタスクトレイだけに表示・常駐させる方法。

###Outlook最小化のときタスクトレイだけに表示・常駐させる方法。

タスクトレイのOutlookを右クリック→最小化時にアイコン化するを選択

###参考URL
https://t-blo.com/entry/outlook2016_tasktray
M1マシンでflowが起動しない問題の対応



## 事象
M1(apple silicon)マシンでrosettaを使って入れたnode.jsで `npx flow` などでflowを起動すると以下のようなエラーが出て起動に失敗する

```
Launching Flow server for /Users/sogasawara/progate
Spawned flow server (pid=6001)
Logs will go to /private/tmp/flow/zSUserszSsogasawarazSprogate.log
Monitor logs will go to /private/tmp/flow/zSUserszSsogasawarazSprogate.monitor_log
Launching Flow server for /Users/sogasawara/progate
Spawned flow server (pid=6008)
Logs will go to /private/tmp/flow/zSUserszSsogasawarazSprogate.log
Monitor logs will go to /private/tmp/flow/zSUserszSsogasawarazSprogate.monitor_log
Launching Flow server for /Users/sogasawara/progate
Spawned flow server (pid=6012)
Logs will go to /private/tmp/flow/zSUserszSsogasawarazSprogate.log
Monitor logs will go to /private/tmp/flow/zSUserszSsogasawarazSprogate.monitor_log
Lost connection to the flow server (0 retries remaining): -Out of retries, exiting!
```

ログ

```
[2021-01-27 17:22:16.301] argv=/Users/sogasawara/progate/node_modules/flow-bi
Unhandled exception: Unix.Unix_error(Unix.EINVAL, "ftruncate", "")
Raised by primitive operation at file "hack/heap/sharedMem.ml", line 82, char
Called from file "hack/heap/sharedMem.ml", line 146, characters 5-26
```

## 環境
Mac Mini(M1), node v10.16.3 (rosetta), flow 0.90.0 

## 解決策(workaround)
.flowconfigに以下のオプションを追加する

```conf
[options]
sharedmemory.heap_size=2147483648
```

なお、公式のissueに問題の対応方法が書いてあります
https://github.com/facebook/flow/issues/8538

heap_sizeはマシンのメモリによって変わるとか。

私のマシンはMac miniのメモリ16GBですが上記の値で動きましたがマシンによって調整が必要そうです
【MMDetection】 環境構築&インストール編

## 概要
まだまだ日本語情報が少ない物体検出フレームワーク"MMDetection"について、学んだことを記録していこうと思います。間違い等ありましたらぜひコメントで教えてください。よろしくお願いします。

## MMDetection とは
香港中文大学（CUHK）が開発している物体検出のためのライブラリであり、PyTorchで書かれている。
物体検出やセグメンテーションの最新研究で頻繁に利用されている。
モジュールを組み合わせてモデルを設計する仕組みになっており、部品の組み替えが簡単に行える。

## 必要な環境
- Linux or macOS
- Python 3.6+
- PyTorch 1.3+
- CUDA 9.2+
- GCC 5+
- MMCV (バージョンについては下表を参照)

|MMDetection ver.  |MMCV ver.  |
|------------------|-----------|
|master	 |mmcv-full>=1.2.4, <1.3|
|2.8.0 	 |mmcv-full>=1.2.4, <1.3|
|2.7.0	 |mmcv-full>=1.1.5, <1.3|
|2.6.0	 |mmcv-full>=1.1.5, <1.3|
|2.5.0	 |mmcv-full>=1.1.5, <1.3|
|2.4.0	 |mmcv-full>=1.1.1, <1.3|
|2.3.0	 |mmcv-full==1.0.5      |
|2.3.0rc0|mmcv-full>=1.0.2      |
|2.2.1	 |mmcv==0.6.2           |
|2.2.0	 |mmcv==0.6.2           |
|2.1.0	 |mmcv>=0.5.9, <=0.6.1  |
|2.0.0	 |mmcv>=0.5.1, <=0.5.8  |

## インストール
Dockerが使える環境であれば[Dockerfile](https://github.com/open-mmlab/mmdetection/blob/master/docker/Dockerfile)が公式から提供されています。
Google Colabを利用する場合、[こちら](https://qiita.com/iwatake2222/items/6a2bd0b599102502720a)の記事が役に立つと思います。

今回はcondaで環境構築するので、Anaconda等を事前にインストールします。


### 1. condaによる仮想環境の作成  
```bash
conda create -n open-mmlab python=3.7 -y  
conda activate open-mmlab
```
### 2. PyTorchとtorchvisionのインストール  
環境に応じて、[公式サイト](https://pytorch.org/)の手順に従ってインストールする。

```bash
conda install pytorch torchvision torchaudio cudatoolkit=10.2 -c pytorch
```
### 3. mmcv-fullのインストール

```bash
pip install mmcv-full==1.2.6
```
### 4. MMDetectionをgithubからクローン
```bash
git clone https://github.com/open-mmlab/mmdetection.git
cd mmdetection
```
### 5. インストール
```bash
pip install -r requirements/build.txt
pip install -v -e .
```

## おまけ
環境構築からインストールまで行うためのシェルスクリプト

```mmdetection_env.sh
conda create -n open-mmlab python=3.7 -y

# >>> conda init >>>
__conda_setup="$(CONDA_REPORT_ERRORS=false '$HOME/anaconda3/bin/conda' shell.bash hook 2> /dev/null)"
if [ $? -eq 0 ]; then
    \eval "$__conda_setup"
else
    if [ -f "$HOME/anaconda3/etc/profile.d/conda.sh" ]; then
        . "$HOME/anaconda3/etc/profile.d/conda.sh"
        CONDA_CHANGEPS1=false conda activate base
    else
        \export PATH="$PATH:$HOME/anaconda3/bin"
    fi
fi
unset __conda_setup
# <<< conda init <<<

conda activate open-mmlab

conda install pytorch torchvision torchaudio cudatoolkit=10.2 -c pytorch -y
pip install mmcv-full==1.2.6

git clone https://github.com/open-mmlab/mmdetection.git
cd mmdetection

pip install -r requirements/build.txt
pip install -v -e .
```

## 参考文献
- [公式ドキュメント](https://mmdetection.readthedocs.io/en/latest/)
【Python】デバッグ時に便利なIcecreamを真似てprintをオーバーライドしてみた。

#はじめに
こちらの記事
[デバッグ時はprintではなく、Icecreamを使うと便利](https://qiita.com/purun/items/c7aca300b970344214cf)
を見て自分で似たような機能を作ってみたくなったので書いてみました。

`print`をオーバーライドすることで既存のプログラムを書き換えることなく、一番上の行にインポート文ないしは定義文を書くだけで`Icecream`を使った際のような表示が可能になります（つまり逆にコメントアウトをすればすぐに元に戻せるということです）。

#つくったもの

```python:printer.py
def print(*args, sep=' ', end='\n', file='', flush=False):
    import builtins, inspect, re, sys
    if not file: file = sys.stdout
    fr = inspect.currentframe().f_back
    arg_names = re.split(
        '\s*,\s*',
        re.findall(
            'print\(((?:.|\s)+?)\)', ''.join(
                inspect.getframeinfo(fr, min(1000,
                                             fr.f_lineno)).code_context))[-1])
    builtins.print(*[
        f'{k}: {v}' if
        not re.match('[\"\'\(\[\{0-9]', k.lstrip()) else str(v)
        for k, v in zip(arg_names, args)
    ],
                   sep=sep,
                   end=end,
                   file=file,
                   flush=flush)
```

#使用例
なるべく`print`と同じような感覚で使えるように、`sep`や`end`、`file`などといった引数を取ることができます。

例えば以下のようなプログラムがあったとします。

```python
a = 1
b = "abcABC"
c = [1, 2, 3]
d = {"A": "a", "B": "b", "C": "c"}
e = {1, 1, 2, 3, 4, 4, 4, 5}

print(a, b, c, d, e)
```
もちろん出力は

```:out
1 abcABC [1, 2, 3] {'A': 'a', 'B': 'b', 'C': 'c'} {1, 2, 3, 4, 5}
```

となりますね。
ここに先程の関数をインポートしてみます。すると、

```python
from printer import print

a = 1
b = "abcABC"
c = [1, 2, 3]
d = {"A": "a", "B": "b", "C": "c"}
e = {1, 1, 2, 3, 4, 4, 4, 5}

print(a, b, c, d, e)
```

```:out
a: 1 b: abcABC c: [1, 2, 3] d: {'A': 'a', 'B': 'b', 'C': 'c'} e: {1, 2, 3, 4, 5}
```

プログラムを書き換えることなく変数名を表示することができます。
先程説明したとおり、`sep`などを指定することで

```python
print(a, b, c, d, e, sep='\n')
```

```:out
a: 1
b: abcABC
c: [1, 2, 3]
d: {'A': 'a', 'B': 'b', 'C': 'c'}
e: {1, 2, 3, 4, 5}
```
より見やすく出力したり、

```python
with open('log.txt', 'w') as f:
    print(a, b, c, d, e, file=f)
```

外部ファイルに出力するなどといったことも、通常の`print`同様可能です。

#仕組み
標準ライブラリ`inspect`を使うことで呼び出し元のコードを取得し、そこから正規表現で変数名を抽出、整形して出力しています。
その性質上、

```python
print(a, b, c);print(d, e)
```
のような書き方をすると上手く変数名を抽出できないのでその点は注意してください（これは`Icecream`も同じ）。
DataTables から Excel エクスポート



#HTML

```html
<!-- data tables -->
<table id="tbl_data" class="display"></table>
```

#Excel エクスポート用ライブラリ

```html
<!-- Excel Export -- -->
<link href="https://cdn.datatables.net/buttons/1.6.2/css/buttons.dataTables.min.css" rel="stylesheet">
<script type="text/javascript" src="https://cdn.datatables.net/buttons/1.6.2/js/dataTables.buttons.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js"></script>
<script type="text/javascript" src="https://cdn.datatables.net/buttons/1.6.2/js/buttons.html5.min.js"></script>
<!-- -- Excel Export -->
```

#データの用意

```javascript
var data = {value:[
	{id:"1",text:"This is test"},
	{id:"2",text:"This is test"},
	{id:"3",text:"This is test"},
]};
```

#データのセット

```javascript
// data for datatables
var dt_data = new Array();

dt_data = data["value"];

if($.fn.dataTable.isDataTable("#tbl_data")){
	$("#tbl_data").dataTable().fnDestroy();
}

$('#tbl_data')
.css("font-size","10pt")
// .addClass("nowrap")
.dataTable({
	"data": dt_data,
	"dom" : '<flipt><B>', // https://datatables.net/examples/basic_init/dom.html
	"oLanguage": {
		"sSearch": "Table Filter:"
	},
	// Export options
	// https://datatables.net/extensions/buttons/examples/html5/simple.html
	"buttons": [
		{
			extend: 'excel',
			text: 'Export as Excel File',
			exportOptions:{
				columns: [ 0, 1 ],
			}
		}
	],
	"columns": [
		{ "title":"ID", "data": "id" }, 
		{ "title":"Text", "data": "text" }, 
	]
	});

table = $('#tbl_data').DataTable();
return;
```
#結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110265/a7c5c179-136d-3920-6cd5-dd775eb70b4f.png)
AppGalleryとGoogle Play ストアのディープリンク（Deep Link）

# 前書き
Android端末において、ファーウェイの[AppGallery](https://consumer.huawei.com/jp/mobileservices/appgallery/)とGoogleのPlayストアは海外でよく使われるアプリストアです。日本ではPlayストアのほうがシェアが高いですが、[AppGallery](https://consumer.huawei.com/jp/mobileservices/appgallery/)のユーザー数も着実に伸びています。

アプリのダウンロード数を増やすために、ウェブページにアプリのダウンロードリンクを入れ、ユーザーをストアに誘導し、ダウンロードを促す方法がよく使われています。このプロセスにおいて大事なのはダウンロードリンクを正しく設定することです。

# AppGalleryとGoogle Play ストアに遷移するリンクの書き方

## AppGalleryのディープリンク
パッケージ名を使うバターンもありますが、<b>アプリID</b>を使うパターンのほうが汎用性が高いです。

### パターン１

```
https://appgallery.huawei.com/#/app/{アプリID}
```
例：https://appgallery.huawei.com/#/app/C100867917

### パターン２

```
https://appgallery.cloud.huawei.com/marketshare/app/{アプリID}
```
例：https://appgallery.cloud.huawei.com/marketshare/app/C100867917

### パターン３

```
market://com.huawei.appmarket.applink?appId={アプリID}
```
例３：market://com.huawei.appmarket.applink?appId=C100867917

### パターン４

```
appmarket://details?id={パッケージ名}
```
例：appmarket://details?id=jp.naver.line.android




## Playストアのディープリンク
パッケージ名を使うパターンのみです。

### パターン

```
https://play.google.com/store/apps/details?id={パッケージ名}
```
例：https://play.google.com/store/apps/details?id=jp.naver.line.android

# 参考サイト
AppGallery：[https://appgallery.huawei.com/#/Featured](https://appgallery.huawei.com/#/Featured)
AppGalleryの紹介：[https://consumer.huawei.com/jp/mobileservices/appgallery/](https://consumer.huawei.com/jp/mobileservices/appgallery/)
EC-CUBE4 テンプレートイベントでテンプレートに変数をセットする

## はじめに

カスタマイズ領域で進める場合、デザインテンプレートは簡単に切り替えられますが、テンプレートにセットする情報は、コントローラーイベントの `EccubeEvents::FRONT_PRODUCT_DETAIL_INITIALIZE` などをフックしても、テンプレートにデータを渡すことはできません。

そんな時は、対象のTwigテンプレートのパスでイベントを監視して、任意のデータをテンプレートに設定できます。

このようにすることで、デフォルトのコントローラーはそのままにしてカスタマイズが可能です。

## イベントリスナーを用意する

```php
<?php

declare(strict_types=1);

namespace Customize\EventListener;

use Eccube\Event\TemplateEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class ProductDetailTwigEventListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            'Product/detail.twig' => 'handle'
        ];
    }

    public function handle(TemplateEvent $event): void
    {
        $product = $event->getParameter('Product');
        if ($product === null) {
            return;
        }

        // do somithing
        $event->setParameter('test', 'TEST');
    }

}
```

## テンプレートで出力する

```twig:app/template/your_template_code/Product/detail.twig
{{ test }}
```
【初心者でもわかる】アラートや確認ダイアログを画面中央に表示する方法

# どうも7noteです。アラートなどの警告ボックスを画面中央に表示させます。

javascriptのalert等は表示位置を変えることができないので1からオリジナルで作ります。
ボタンを押した後の処理は書いてませんので利用目的に合わせて改良してお使いください。

## 確認してくるボックスを画面中央に出すソースのサンプル

※jQueryをちょっとだけ使ってます。jQueryって何？という方は[こちら](https://qiita.com/7note/items/45bd8efbedd557667218)。

```index.html
<div id="overflow">
  <div class="conf">
    <p>本当に決定してもいいですか？</p>
    <div class="btns"><input type="button" value="キャンセル" onClick="cansel();"> <input type="button" value="オッケー" class="ok" onClick="next();"></div>
  </div>
</div>

<p>これでいいですか？</p>
<input type="button" value="決定" onClick="check();">
```

```style.css
#overflow {
  width: 100vw;  /* 横幅を画面いっぱいにする */
  height: 100vh; /* 高さを画面いっぱいにする */
  background-color: rgba(0,0,0,0.2); /* 背景を半透明の黒い背景にする */
  position: absolute; /* 相対位置に指定 */
  z-index: 10;        /* ウィンドウの全面に表示 */
  display: none;      /* 初期は非表示 */
}

#overflow .conf {
  background: #FFF;   /* 背景を白色に指定 */
  padding: 20px;      /* 余白を20pxに指定 */
  position: absolute; /* 装置位置に指定 */
  top: 50%;           /* 上から50%の位置に配置 */
  left: 50%;          /* 左から50%の位置に配置 */
  transform: translate(-50%,-50%); /* コンテンツの半分だけ位置を戻して上下左右中央に配置 */
}

.btns {
  text-align: right; /* 要素を右寄せにする */
}
.btns .ok {
  /* okボタンの装飾を変えるなら書く */
}
```

```script.js
function check(){
  $("#overflow").show();
}
function cansel(){
  $("#overflow").hide(); // 確認ボックスを消す
}
function next(){
  $("#overflow").hide();
  // ok後の処理を書く
}

```

**結果**

![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/93906af7-5852-7381-b8e3-ae9073f9d2a1.gif)

## 解説

標準で出すことのできる`alert()`や`confirm()`は表示位置を変えることができません。
なので、新しくボックスを作り、ボタンを並べてそれぞれ個別に処理を書こうという発想です。

## まとめ

今回装飾は最低限にしていますので、自由に装飾してください。
もちろんアラートのボックスを上下中央にしなくても好きな位置に持ってきたり、出し方を工夫したりしてもいいかなと思います。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
bulletml.jsの研究 その6

#概要

bulletml.jsの研究です。
技を調査。

#n-way


```
<bulletml>
	<action label="top">
		<repeat>
			<times>22</times>
			<action>
 				<fire>
  				<direction type="aim">-30</direction>
	  			<bullet>
						<action>
 							<changeDirection>
  							<direction type="sequence">0</direction>
  							<term>20</term>
 							</changeDirection>
						</action>
					</bullet>
 				</fire>
				<repeat>
					<times>4</times>
					<action>
 						<fire>
  						<direction type="sequence">15</direction>
	  					<bullet>
								<action>
 									<changeDirection>
  									<direction type="sequence">0</direction>
  									<term>20</term>
 									</changeDirection>
								</action>
							</bullet>
 						</fire>
 						<wait>3</wait>
					</action>
				</repeat> 
 				<wait>30</wait>
			</action>
		</repeat>
	</action>
</bulletml>
```

一度に複数の方向へ等間隔に発射する攻撃です。
発射弾数によって5way、7wayなどと呼びます。
間隔、発射弾数、発射方向の自機依存／非依存や偶数／奇数などでバリエーションを広げていきます。

#成果物

https://embed.plnkr.co/plunk/lx80g18Lp4lAUMAb

以上。
System specを用いた結合テスト（画像を送付する）

#初めまして
私は現在ポートフォリオのアプリを製作し、全ての単体テストを終えたのでユーザーの画面遷移が正常に行えるかどうか結合テストで確認しました。
今回、ActiveStorageを用いているのでどのように送付するのかでハマってしまい、それを解決したので備忘録として残したいと思います。

#開発環境
Rails6 

#結合テストで画像を送付する

attach_fileメソッドが鍵になります。
第一引数に画像をアップロードするinput要素のname属性、第二引数にアップロードする画像のパス、第３引数以降はオプションで様々な値をとることができるみたいです。

```
 image_path = Rails.root.join('public/images/people.jpg')←パスをimage_pathに代入しておく
      attach_file('post[image]', image_path)
　　　　　　　　　　　　↑name属性      ↑画像のパス
```

#最後

上記のメソッドによって画像が送付でき、無事結合テストを終えることができました。
アプリ制作は最後のテストを終えるまで気が抜けないな〜と実感しました！

読んでいただきありがとうございました！
友達の誕生日を通知するLinebot

# はじめに
友達が多ければ多いほど，みんなの誕生日を記憶するのは難しいですよね．
僕は友達が多いので(嘘)， 友達の誕生日を通知してくれるLinebotを作成しました．

# 手順
1. [LINE Notify](https://notify-bot.line.me/ja/)にログイン
2. マイページからアクセストークンを発行
3. 発行したトークンをpython scriptにコピー & ペーストして，友達の誕生日を登録
4. crontabを使って毎日00:00にプログラムを実行

# 手順1． LINE Notifyにログイン
LINEアカウントでログインしましょう．
アカウント情報はLINEアプリの「設定＞アカウント」から確認できます．

# 手順2． マイページからアクセストークンを発行
![スクリーンショット 2021-01-23 15.54.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395267/7ed6c957-2f8e-a84a-d181-3412dfbc4062.png)
自分とLINE Notifyの1:1のやりとりなら，トークンを発行するだけでOK!!
グループとLINE Notifyのやりとりなら，グループにLINE Notifyを招待しよう

# 手順3. 
以下のコマンドを打って，[誕生日通知レポジトリ](https://github.com/rikukawamura/LINEBirthdayNotify)をクローンしましょう． 
尚，このレポジトリの99%は[PythonでLINEにメッセージを送る](https://qiita.com/moriita/items/5b199ac6b14ceaa4f7c9)に準じます．

```
git clone https://github.com/rikukawamura/LINEBirthdayNotify.git
```
main.pyにアクセストークンと友達の誕生日を設定．

```main.py
from line_notify_bot import LINENotifyBot
import datetime

# coding: UTF-8
date = str(datetime.date.today()).split('-')
month, day = date[1], date[2]

bot = LINENotifyBot(access_token='アクセストークンをペースト')

if month=='月(e.g.01)' and day=='日(e.g.01)':
    bot.send(
        message='\n{}月{}日は{}の誕生日'.format(month, day, '名前')
    )
elif month=='01' and day=='01':
    bot.send(
        message='\n{}月{}日は{}の誕生日'.format(month, day, '山田太郎')
    )
```

# 手順4．
crontabを使って毎日00:00にmain.pyを実行．

```crontab
PATH=/Users/kawamurariku/.pyenv/versions/anaconda3-2019.10/condabin:/usr/local/Cellar/pyenv-virtualenv/1.1.3/shims:/Users/kawamurariku/.pyenv/shims:/Users/kawamurariku/.pyenv/bi$
00 00 * * * python /Users/kawamurariku/LINEBirthdayNotify/main.py
LANG=ja_JP.UTF-8
```
crontabについては，以下を参考にした．
[【保存版】cronでPython3を定時実行する方法&注意すべき４つのポイント](https://tanuhack.com/cron/)

# 出力確認
こんな感じで通知が来ると思います．
![スクリーンショット 2021-01-27 16.50.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395267/8ec20f6d-721e-c621-787e-188a132f39e1.png)
[test]の部分は，手順2．で設定した以下のトークン名が表示されます．
![スクリーンショット 2021-01-27 16.53.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/395267/c1f52c5a-63f2-cf64-c6b5-80bcd77da6ff.png)

# 終わりに
今回は，LINE APIを使用して，友達の誕生日を通知するBotを作成しました．
LINEは毎日使うし，これなら友達の誕生日を忘れることもなさそうです．
他にも，あったらいいのになと思ったBotを暇があれば作りたいと思います．
最後までご閲覧ありがとうございました．
備忘録 Golang paiza見本問題 Dランク 一番小さな値

備忘録 go言語 paiza見本問題解説

見本問題は解説、公開しても問題ないようですので、備忘録を兼ねて公開します。
Dランク "一番小さい値"


```
package main
import ("fmt") 

type El struct{//構造体の定義。elemは要素, nextには次のデータのアドレスを格納する
    elem int
    next *El
}
type Data struct{
    x, y, z, v, w El//データの名前を定義
}

func f1(a *Data) int{
    var dum int = a.x.elem//一番初めの値のコピー
    var b *El = &a.x//ポインタでないa.xにアドレスを代入することはできないため、ダミーの作成
    for i := 0 ; i < 5; i++{//データは5つであるため5回のループ
        if (*b).elem < dum{//データが最小の場合のケース
            dum = b.elem
        }
       b = (*b).next//bのアドレスに次のアドレスを代入する。
    } 
    return dum//最小値を返却
}

func main(){
    var a = Data{}//aの仮宣言
    a.x.next = &a.y//順次ネクストに次のデータのアドレスを代入する
    a.y.next = &a.z
    a.z.next = &a.v
    a.v.next = &a.w
    a.w.next = nil//終端ノード
    fmt.Scanf("%d\n%d\n%d\n%d\n%d", &a.x.elem, &a.y.elem, &a.z.elem, &a.v.elem, &a.w.elem)
    fmt.Print(f1(&a)


```
定形文字列を一発で出力したい時のバッチサンプル

#用意するファイル：

```address.txt
xxxx@yahoo.co.jp
yyyy@gmail.com
```

```startFormatterAddresslist.bat
@echo off

for /f %%t in (address.txt) do (
  echo メールアドレス : %%t>>output.txt
)

```

#バッチ実行結果

```output.txt
メールアドレス : xxxx@yahoo.co.jp
メールアドレス : yyyy@gmail.com
```
謎の力を棒に与えたかった

抽象的な表現で申し訳ないのですが、棒に謎の力を与える必要がありました。
メモ代わりに使わせていただきます。

[![Image from Gyazo](https://i.gyazo.com/4ea7d7ed71d798ef5599366901c01663.gif)](https://gyazo.com/4ea7d7ed71d798ef5599366901c01663)


* アンカーポイントの変更
* 角度を求めて代入

###アンカーポイントの変更

Unityでは基本的にGameObjectの真ん中にセンターが来るようにデザインされています。
今回は物体の端にアンカーポイントを置きたかったので、空のGameObjectを配置して、以下のスクリプトをアタッチ。

```csharp

public class Gizmo : MonoBehaviour
{
   public float gizmoSize = 0.1f;
	public Color gizmoColor = Color.yellow;

	void OnDrawGizmos()
	{
		Gizmos.color = gizmoColor;
		Gizmos.DrawWireSphere (transform.position, gizmoSize);
	}
}

```

ヒエラルキーの方は、空のゲームオブジェクトの下に置きたいオブジェクトを配置します。
[![Image from Gyazo](https://i.gyazo.com/8f5562924e3e49fcd62c430d1d870c41.png)](https://gyazo.com/8f5562924e3e49fcd62c430d1d870c41)

[こちらの記事を参考（というかほぼそのまま）利用させていただきました。](http://portaltan.hatenablog.com/entry/2016/04/15/134129)

###角度を求めて代入

原点はわかっていたので、だいたいこのへんから取ろうと決めた座標を使って角度を求めました。

```csharp

float rad = Mathf.Atan2(modelpos.y,modelpos.x);
float moveY = 90 - rad * Mathf.Rad2Deg;
```

[上記の参考はこちらの記事をを利用させていただきました。](https://qiita.com/Hoshi_7/items/d04936883ff3eb1eed2d)

このときに、GameObjectが何でも良いように、

```csharp

[SerializeField]GameObject targetmodel;
```

上記のように宣言して、参照元が何でも良いようにUnityでフィールドを見れるようにしました。

Quautanionのりお会が全く追いつかなかったため、今回は Quaternion.Euler を使って値を代入しています。

```csharp

gizmo.transform.rotation = Quaternion.Euler(2.61f,-7.06f,moveY/2);
```

rotationは、Quaternionを代入せねばいけませんが、上記のように雑にVector3みたいなのが代入ができるので便利です。
教えていただいたのはLookAt()関数でしたが、今回は使用しませんでした。

以上メモでした。

もっとこうすれば簡単だよ！ということがありましたら教えていただけると幸いです。
初めて作るアプリのタイトルを決める

##なぜ記事にするのか

本当に無知（アプリ開発初心者）の段階でどのようにタイトルを決めたのか、記録を残しておくため。

##どんなアプリを作っているか

台湾中国語の学習アプリをつくっています。
<img width="250" alt="ForGif.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1010233/d20f6dcc-e701-705f-61d9-1c213b236eea.gif">

日本語文章とその翻訳を一対にしており、？を押すことで台湾中国語が表示できるようになっています。
「Next」と「Back」で文章を変更します。
右上の「lang」を押すことで、日本語と台湾中国語を切り替えることができます。
また、文章の表示と同時に録音音声を鳴らしています。
ちなみにですが、日本語音声は僕、台湾語音声は僕の彼女が台湾人なのでお願いしています。

録音音声の処理はpythonで書いています。

pythonを使って録音した音声を採番、無音部分をカットする【プログラミング超初心者】
https://qiita.com/atamakonkurii/items/af8cddaccf4565361086


##制約
日本人と台湾人に使ってもらいたいので、英語のタイトルがいいかなと考えました。

##考える過程

以下の記事によるとアプリのタイトルは３つ考える必要がありそうです。
[アプリ製作者必見！アプリタイトルを決めるのに必要な情報まとめ](https://www.i3design.jp/in-pocket/4669)

>1.アプリ名（呼称）
>2.ホーム画面の下にあるタイトル
>3.ストア掲載されるタイトル

>メルカリを例にして説明すると
>1は「メルカリ」
>2は「メルカリ」
>3は「フリマアプリ-メルカリ フリマでかんたんショッピング」
>となります。

>yahoo!乗り換え案内の場合は
>1は「Yahoo!乗り換え案内」
>2は「Y!乗換案内」
>3は「Yahoo!乗換案内 無料で路線図や乗り換えの情報を検索できるアプリ」
>といった感じです。

言語学習アプリということを伝えたいので、あまり捻らずに行こうかと思います。

思いましたが、以下のタイトルに決定しました。

1.「AtaCon」
2.「AtaCon」
3.「AtamaConcrete　台湾中国語、日本語勉強アプリ」

読み方は「アタコン」です。
日本ではすでに使われていない日本語ですが、台湾には日本統治時代の名残りで「頭コンクリート」という言葉が残っているそうです。
意味は頭が固いとかそんな感じらしいです。
日本と台湾の言語的な文化のつながりが垣間見えるタイトルなのではないかと思いこれに決めました。
すぐ変えるかもしれません、、、

ちなみに僕がやってるYouTubeのチャンネル名は「頭コンクリ」です。
狙ってやったわけじゃなく、けっこうこの言葉が好きで気に入ってるから結局アプリの名前もこれ関連になってしまいました。
プログラミングと全然関係ないですが、お時間あれば覗いてみてください。
https://www.youtube.com/channel/UC2JHTgLF0wHhkKIPS9sTl0w


##まとめ

結局かなりテキトーに決めてしまいましたが、記録しておきます。
Overleafで日本語: platex使う

# Overleafで日本語文章を作る。
以前，こういう記事を書きました。
[LaTeXで修論を書く（Overleaf使う）](https://qiita.com/ishigaki/items/8da80e4da3e2249a85f8)

毎年修論の時期が近づくとLGTMとかストックしてくれる人がいて，それなりに見られてるようです。
ここではXeLaTeX使って日本語を書くための設定を説明してました。

最近，[Overleafの日本語の文章を書くための設定](https://ja.overleaf.com/learn/latex/Japanese)みたら，もっと楽な設定があったので紹介します。

# 設定
そんなに難しいことはないです。

まず，CompilerをLaTeXにします。

次にlatexmkrcというファイルを作ります。拡張子はなしです。以下の内容を書きます。

``` 
$latex = 'platex';
$bibtex = 'pbibtex';
$dvipdf = 'dvipdfmx %O -o %D %S';
$makeindex = 'mendex %O -o %D %S';
```

documentclassはjsarticleにして，普通に文章書きます。これで大丈夫です。

``` tex
\documentclass{jsarticle}
\usepackage[utf8]{inputenc}

\title{platex-test}
\date{January 2021}

\begin{document}

\maketitle

\section{はじめに}

日本語の設定。

\end{document}
```

他にもLuaLaTeX使う方法も紹介されてますが，jsarticle使うのが楽かなと思います。
JavaScript復習⑥

<a href="https://qiita.com/SOH_engineer/items/400b092b7ad0af144850">JavaScript復習⑤</a>からの続きです。

<h1>関数の呼び出し方と渡し方</h1>

```JavaScript:JavaScriptファイル
printWanko() //関数が呼び出される
printWanko //関数の定義そのもの
```

<h1>'use strict'</h1>
JavaScriptコードを記述する際には、先頭に'use strict'; と記述する

<h1>バックスラッシュ</h1>

```JavaScript:JavaScriptファイル
console.log('it's me!');
// これだとit'sの'が終端記号として認識され、エラーが出てしまう

console.log("it's me!") //ダブルクォーテーションで表記する
//もしくは
console.log('it\'s me!') //バックスラッシュを用いて表記する
```

バックスラッシュを用いた他の記法として、
\n ・・・ 改行  　　　\t ・・・ タブ
などが挙げられる。


<h1>べき乗</h1>

```JavaScript:JavaScriptファイル
console.log(10 ** 3);
// **はべき乗を表す
```

```:コンソール
1,000
```

<h1>JavaScriptのデータ型</h1>

・文字列・・・ String
・数値・・・ Number
・Undefined
・Null
・真偽値・・・ Boolean(true or false)
・オブジェクト ・・・Object (例) {a: 3, b: 5}

<h1>typeof</h1>
JavaScriptで値の方がどの種類の方なのか調べられる演算子

<h1>parseInt</h1>
parseIntで、数値に関して、文字列の連結ではなく、足し算にしたい場合に、
数値を文字列から整数値に変換する方法

```JavaScript:JavaScriptファイル
console.log('5' + 3);
// このままだと53と出力される

console.log(parseInt('5', 10)+ 3);
// このように表記すると8と出力される。10は10進数を意味する
```

<h1>単一の値の真偽値での評価</h1>

false ・・・　0, null, undefined, ' '(空文字列), false
true ・・・ 上記以外
→値をtrue, falseで評価するには、Boolean()という命令を用いる

<h1>条件演算子</h1>

```JavaScript:JavaScriptファイル
// 条件演算子
条件式 ? trueの処理 : falseの処理
```





<h5>JavaScript復習以上</h5>
JavaScript復習⑤

<a href="https://qiita.com/SOH_engineer/items/b109f16e31aff13bab51">JavaScript復習④</a>からの続きです。

<h1>入力値を使う</h1>

```JavaScript:JavaScriptファイル
import readlineSync from "readline-sync";
const name= readlineSync.question("名前を入力してください:");
console.log(`${name}が入力されました);
```

```:コンソール
名前を入力してください: タロウ
タロウと入力されました
```

<h1>整数の入力</h1>

```JavaScript:JavaScriptファイル
const name = readlineSync.question("名前を入力してください:");
const age = readlineSync.questionInt("年齢を入力してください:");
// 整数を入力させる場合はquestionではなく、questionIntを使う
```

<h1>pushメソッド</h1>

```JavaScript:JavaScriptファイル
const numbers = [1,2,3];
console.log(numbers);
numbers.push(4);
console.log(numbers);
```

```:コンソール
[1,2,3]
[1,2,3,4]
```

<h1>forEachメソッド</h1>

```JavaScript:JavaScriptファイル
const numbers = [1,2,3];
numbers.forEach ((number)=> {console.log(number); } );
// コールバック関数の形になっている
```

```:コンソール
1
2
3
```

<h1>findメソッド</h1>

```JavaScript:JavaScriptファイル
const numbers = [1,3,5,7];
const foundNumber = numbers.find ((number)
  =>{ return number > 3;
});
console.log(foundNumber);
```

```:コンソール
5

//条件に合う最初の要素だけが取り出される
```

配列の要素がオブジェクトの場合もfindメソッドが使える

```JavaScript:JavaScriptファイル
const characters = [
  {id: 1, name: "たろう"},
  {id: 2, name: "はなこ"}
];
const foundCharacter = characters.find ((character)=>{
  return character.id === 1;
});
console.log(foundCharacter);
```

```:コンソール
{id: 1, name: "たろう"}
```

<h1>filterメソッド</h1>

```JavaScript:JavaScriptファイル
const numbers = [1,3,5,7];
const filteredNumbers = numbers.filter ((number)=>{
  return > 3;
});
console.log(filteredNumbers);
```

```:コンソール
[5,7]

//条件に合う要素が全て取り出される
```

配列の要素がオブジェクトの場合もfilterメソッドが使える

```JavaScript:JavaScriptファイル
const characters = [
  {name: "たろう", age: 20},
  {name: "はなこ", age: 8},
  {name: "けんた", age: 5}
];
const filteredCharacters = characters.filter ((character)=>{
  return character.age > 7;
});
console.log(filteredCharacters)
```

```:コンソール
[ {name: "たろう", age: 20}, {name: "はなこ", age: 8} ]
```

<h1>mapメソッド</h1>
mapメソッド・・・ 配列内の全ての要素に処理を行い、その戻り値から新しい配列を作成するメソッド

```JavaScript:JavaScriptファイル
const numbers = [1,2,3];
const doubledNumbers = numbers.map ((number)=> {
 return number * 2;
});
console.log(doubledNumbers);
```

```:コンソール
[2,4,6]

//配列numbersの全ての数値が2倍され、新しい配列が作成された
```

配列の要素がオブジェクトの場合もmapメソッドが使える

```JavaScript:JavaScriptファイル
const names = [
  {familyName: "Tanaka", lastName: "Taro"},
  {familyName: "Suzuki", lastName: "Hanako"}
];
const fullNames = names.map ((name)=>{
  return name.familyName + name.lastName;
});
console.log(fullNames);
```

```:コンソール
["TanakaTaro", "SuzukiHanako"]
```

<h5>続きは<a href="https://qiita.com/SOH_engineer/items/e2bfd5ba0863b5d34609">JavaScript復習⑥</a>へ</h5>
【PHP】while文とfor文をざっくりまとめてみた。

PHPで繰り返し処理を行おうとした時に
while文とfor文がごちゃごちゃになってしまっていたので、
備忘録としてざっくりまとめておきます。

#while文
条件式が `真` の間は、ずっと処理を繰り返します。
`繰り返す回数が分からなかったり、特定のタイミングで処理を変えたい場合に便利です。`
形式は以下の通りです。

```
初期化処理;
while (条件式) { 
　繰り返したい処理;
　更新処理;
}
```
実際に書いてみると以下のようになります。

```
$i = 1;
while ($i <= 5) {
　echo $i . "\n";
　$i = $i + 1;
}
```
これで、
「変数*`$i`*が`5以下の時`、処理を繰り返してください。ちなみに*`$i`*`の初期値は1`ですよ。」
という繰り返し処理文の完成です。
実行結果は以下の通りです。

```
1
2
3
4
5
```
余談ですが、この場合に更新処理を以下のように書き換えることが可能です。

```
$i += 1;
$i++;
```

#for文
while文と同様、条件式が `真` の間は処理を繰り返します。
`あらかじめ繰り返す回数が分かっている場合は、for文を使うと良いです。`
形式は以下の通りです。

```
for (初期化処理; 繰り返す条件; 更新処理) {
　繰り返したい処理;
}
```
実際に書いてみましょう。

```
for ($i = 1; $i <= 5; $i++) {
　echo $i . "\n";
}
```
この場合も出力結果は以下のようになります

```
1
2
3
4
5
```

どちらの構文を使っても同じ処理を行えますね。
使う場面ごとに上手く使い分けていきたいものです。

#参考
* [PHP forとwhileの違いと使い分け](https://zeropuro.com/blog/?p=245)
* [PHPでwhile文（ループ処理）を使う方法【初心者向け】](https://techacademy.jp/magazine/4973)
* [PHPのfor文(繰り返し構文)を使いこなす](https://techplay.jp/column/491)
地理分散コンテンツ管理システムとしてのNoSQLの可能性：MongoDB, Couchbase

# はじめに

(NoSQL)データベースをコンテンツ管理システム（CMS）あるいはファイルストレージとして利用するというアイディアはとりわけ珍しいものではなく、その機能を提供しているNoSQLサーバーもあります(例えば、MongoDB)。

ここでは、その意義と現状について整理します。

## データベースによるファイル管理
データベースでファイル管理を行うメリットとして、まず機能面において、以下が考えられます。

- ファイルシステムの持つ制約からの解放（ディレクトリ内のファイル数上限など）
- メタデータ管理

上記の要件については、コンテンツ管理システムを用いることがまず考えられます。

あえて、データベースを用いる理由としては、以下が考えられます。

- シングル・プラットフォームで（準）構造化データと非構造化データの両方を管理したい
 - 両方のデータに相互的に関連するロジックの実現
 - 複数プラットフォームを管理する運用負担・コストの軽減
- 利用するデータベースに固有のメリットを活用したい
 - 分散アーキテクチャの持つ利点（高信頼性、等）の活用、等


# 実現例の検討

## MongoDB

一般にNoSQL（ドキュメント指向）データベースでは、扱えるドキュメントの最大サイズが決まっており、そのサイズを超えるデータを扱うことができないという制約があります。
MongoDBでは、その制約に対する対応として、複数のドキュメントで一つのファイルを管理する、GridFSという機能を提供しています。

[MongoDB GridFS](https://docs.mongodb.com/manual/core/gridfs/)


## Couchbase

Couchbaseもまたドキュメント最大サイズの制約を持ちます。

Couchbaseには、ビルトインの機能はありませんが、以下の様な試みが発表されています。
この試みでも、MongoDBのGridFSと同様、ファイルをチャンクに分割して保存する方式が取られています。

[Flexible and Scalable Content Management using Apache Chemistry OpenCmis and Couchbase](http://cecilelepape.blogspot.com/2015/09/flexible-and-scalable-content.html)

[Storing blobs in Couchbase for Content Management](http://cecilelepape.blogspot.com/2016/01/storing-blobs-in-couchbase-for-content.html)


#### クロスデータセンターレプリケーション (XDCR)
Couchbase Serverが採用される理由の一つとして、XDCR(Cross Data Center Replication)の機能があります（例えば、「[安定稼動を実現したKDDI Business ID、その理由とは？](http://cloudblog.kddi.com/devops/2226/)」を参照）。

XDCRの存在は、地理分散コンテンツ管理システムをCouchbaseを用いて実現したいと考える動機になるかもしれません。

## 地理分散システム

「地理分散」という言葉から思い受かべられるイメージは、必ずしも一様ではないと思われ、ここで具体的な内容を整理したいと思います。以下の二つのパターンについて、混同しないことが必要です。

- 地理分散したノード間でデータをレプリケーションしながら、一つのクラスターを構成する
- 地理分散した複数のクラスター間で、データを双方向にコピーする
 
NoSQLの文脈で「地理分散」と言ったときに、はじめのケースを思い浮かべられる向きもあるかと思い、冗長だったかもしれませんが、あえて整理しました。
XDCRが実現するのは後者のケースです。この場合、クライアント/ユーザは、近いロケーションにあるクラスターを利用することで、データアクセス（リード/ライト）時に最適な応答速度を得ることができます。特にサイズの大きいファイルへのアクセスを考えると、近いロケーションのクラスターを利用する利点は、より大きいと考えられます。

# 最後に

幾分ニッチな話題を扱いましたが、本記事を目にされた方の関心と何らかの接点があれば、嬉しく思います。

## 参考情報

### コンテンツ管理標準
[Apache Chemistry](https://chemistry.apache.org/)

[CMIS (Content Manaement Interoperability Services](https://en.wikipedia.org/wiki/Content_Management_Interoperability_Services)

[OpenCMIS](https://en.wikipedia.org/wiki/OpenCMIS)

### MongoDB
[https://github.com/mdirolf/nginx-gridfs](https://github.com/mdirolf/nginx-gridfs)

[MongoDBでゆるふわDB体験 第7回 GridFS─大容量のファイルをMongoDBに保存する仕組み](https://gihyo.jp/dev/serial/01/mongodb/0007?page=1)

### Couchbase

[https://github.com/cecilelepape/cmis-couchbaseonly](https://github.com/cecilelepape/cmis-couchbaseonly)
[https://github.com/cecilelepape/cmis-couchbase](https://github.com/cecilelepape/cmis-couchbase)

### Rest APIとファイルアップロード

[WebAPI でファイルをアップロードする方法アレコレ](https://qiita.com/mserizawa/items/7f1b9e5077fd3a9d336b)

[GitHub Contents API](https://docs.github.com/en/rest/reference/repos#contents)
bulletml.jsの研究 その5

#概要

bulletml.jsの研究です。
技を調査。

#固定方向弾

```
<bulletml>
	<action label="top">
		<repeat>
			<times>222</times>
			<action>
 				<fire>
  				<direction type="sequence">23</direction>
	  			<bullet>
						<action>
 							<wait>20 + $rand * 50</wait>
 							<changeDirection>
  					  		   <direction type="absolute">180</direction>
  							   <term>20</term>
 							</changeDirection>
						</action>
					</bullet>
 				</fire>
 				<wait>3</wait>
			</action>
		</repeat>
	</action>
</bulletml>
</textarea>
```

自機狙いに対し、自機の位置に依存しない攻撃です。
単発ではあまり意味をなしませんが、規則的にたくさんの固定方向弾を配置することで、障害物として機能させることも出来ます。




#成果物

https://embed.plnkr.co/plunk/mAM1UmYbTZBVempo

以上。
LaravelでWebアプリを作ってみた

#はじめに

ドットインストールからプログラミングをはじめ、PHP,Laravelを半年ほど勉強したので何か有益なものを作ってみたいという気持ちが生まれてきました。

**以前作った有益でないもの。**

 * 「Ohanatter」
 
http://ohanatter.herokuapp.com/login

遊び方はGithubのREADMEを見てください。
https://github.com/kk0055/Ohanatter

 * ペット掲示板
 
https://dry-journey-16818.herokuapp.com/

これらはこれらでかわいくて好きだったのですが、もう１段階有益なものを目指しました。


有益かどうかはわかりませんが、引っ越しを考えていたので「**そうだ、いらないものを人にあげるアプリを作ってみよう**」という考えです。

トータル3週間くらいで完成。

「Kasih」です。
https://kasihkasih.net/

#アプリの概要
不要なモノを投稿して、それを欲しい人がいたらチャットが送れる。そんなサービス。
メルカリ、ジモティー、Carousellなどを参考にしてつくりました。
AWS,Herokuは以前使ったことがあるので今回、サーバーはさくらのレンタルサーバーを使いました。初めてのレンタルサーバーはかなり詰まりましたね。。。

#機能

 * 新規登録、ログイン
 * TwitterOAuthログイン（今は止めてます）
 *  投稿
 *  チャット
 *  チャットを受けとったときのメール通知
 *  ユーザーごとの商品画面
 *  カテゴリーごとの商品画面
 *  登録なしでも閲覧は可能。投稿、チャットはログイン必須


#ER図
初めて書いたので難しかった。

![ER_trim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635968/030f3da3-2b07-b11d-56f2-3439f19473b9.png)


#苦労した点

* チャット機能

アイテムごとにチャット送れるした方がいいとは思ったのですが、同じ二人のユーザー同士なら一つのメッセージボックスの中で完結できるようにしました。
どちらがいいのかわからず迷って何度かやり直しをしました。
今後、必要だと思ったら修正していきます。※必要だと思う。

* モデルバインディング

今となってはなぜうまくいかないのかわかるのですが、しっかりと理解できておらず苦労しました。ググるうちに少しずつ少しずつ理解しました。
この時どうしてもわからずteratailで質問したところ、あっさりとヒントをもらえて、これからは何日か考えてもわからないときは聞こうと決めましたね。
すぐに聞いたら、ググったりドキュメントを見ないのである程度は自分で調べる癖は持っておきたいと思います。

* DBまわり

リレーションがなんとなくしかわかっていなかったことを痛感させられました。
モデルのインスタンスを取っているのか、コレクションをとっているのかという考えすらなくなんとなくで書いていたら上手くいかず。

これまでは書いて試してみるというスタイルだったのですが、やはり勘ではうまくいかない。理解してないと修正もできない。
ドキュメント、Stack Overflowを何回も何回も見て焦らず理解した上で心がけるようになりました。コードだけ流し見しがちですがしっかり説明を読むことが大事。

https://readouble.com/laravel/8.x/ja/eloquent.html

また、SQLをもう一度しっかり勉強しないといけないなとも感じました。
おそらくSQLを理解していればリレーションそんなに難しくないはず。

* フロントエンド

あまりCSSは勉強してこなかったので、主にTailwindをつかってデザインしました。Tailwindは使いやすくてすきなのですが細かい修正が難しいなと思います。
基本的にはググってよさげなデザインをコピペして、細かい部分を修正。

* レンタルサーバ

わりとすべてが謎。なぜサーバ会社は細かいドキュメントを持っていないのか？なぜ人のブログ記事ばかりなのか？書いてることもばらばらだし。
もう理解できたので次は上手くできると思います。
ざっくりと。

Laravelドキュメントのインストーレーションより
>Laravelをインストールできたら、Webサーバのドキュメント／Webルートがpublicディレクトリになるように設定してください。

Laravelのプロジェクトpublicのシンボリックリンクを公開フォルダ内に貼ればOK.
そして

コントロールパネル
→ドメイン/SSL
→ドメイン/SSL
→「WEB公開フォルダ」
をLaravelプロジェクト/publicに変更

![Screenshot (507).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635968/b7d94351-9ac3-b832-c60f-bc3fe8bf3a3e.png)




#結論

なにか特定の教材を参考にするのではなくググりながら書くということを意識して今回作ってみましたが、めちゃくちゃ楽しいしかなり学べる事、吸収できることが多いなと思いました。**100倍くらい。**

チュートリアルをやるだけだと、学べることも多いのですが基本的にはエラーも出ずすんなり進んでいくのであまり記憶に定着しないなと思います。

苦しんで苦しんで考えてる時が一番成長につながるのかな。



「Kasih」です。
https://kasihkasih.net/
Java Wordをイメージに変換

<p><strong>今回はSpire.Doc for　Javaを使ってWordをイメージに変換する、そして、イメージの解像度を設定する方法を紹介します。簡単なので、もしお役に立てば幸いです。</strong></p>
<h4><strong>下準備</strong></h4>
<p><strong>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/doc-for-java-free.html">Free Spire.doc for Java</a>無料版をダウンロードしてください。</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210127/20210127155151.png" alt="f:id:lendoris:20210127155151p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong>2.IDEを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire.doc.jarを参照に追加してください。</strong></p>
<h5><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210120/20210120151914.png" alt="f:id:lendoris:20210120151914p:plain" title="" class="hatena-fotolife" itemprop="image" /></h5>
<h4><strong>コード</strong></h4>
```JAVA
import com.spire.doc.Document;
import com.spire.doc.documents.ImageType;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

public class SetImageResolution {
    public static void main(String[] args) throws Exception {
        //Document objectを作成します。
        Document doc = new Document();
        //Wordをロードします。
        doc.loadFromFile("Example.docx");

        //イメージに変換して解像度を設定します。
        BufferedImage[] images = doc.saveToImages(0, doc.getPageCount(), ImageType.Bitmap, 500, 500);

        int i = 0;
        for (BufferedImage image : images
             ) {
            //pngで保存します。
            File file = new File( "output/" + String.format(("Img-%d.png"), i));
            ImageIO.write(image, "PNG", file);
            i++;
        }
    }
}
```
<h4><strong>実行結果</strong></h4>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210127/20210127161038.png" alt="f:id:lendoris:20210127161038p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong> </strong></p>
Pythonで学ぶアルゴリズム　第23弾：並べ替え（ビンソート / バケットソート）

# #Pythonで学ぶアルゴリズム< ビンソート / バケットソート >

##はじめに
基本的なアルゴリズムをPythonで実装し，アルゴリズムの理解を深める．
その第23弾としてビンソート（バケットソート）を扱う．

##ビンソート（バケットソート）
ビンソートはバケットソートとも呼ばれる．以降ビンソートと呼ぶこととする．

**ビンソート**: 並べ替える要素が限定されているときに用いられるソート方法．

データ内に各要素がいくつあるのかをカウントし，そのカウント数を使って，並べ替える．そのイメージ図を次に示す．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/481b20f9-6083-7901-7886-ae0be5141aeb.png)

##実装
先ほどの説明をもとにPythonでの実装を行った．なお，参考文献では，決まった要素の参照リストが利用されているが，その参照リストも変えられるような実装を試みた．そのソースコードとそのときの出力を以下に示す．

#####ソースコード
```python
"""
2021/01/27
@Yuya Shimizu

ビンソート
"""

def bin_sort(data, data_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]):
    """ 参照リストの要素がデータにいくつあるのかをカウントし，順に並べていく """
    sorted_data = []    #結果を格納する配列

    for i in data_list: #要素を基準にカウントを行う
        count = 0       #カウントするための変数

        for j in data:  #各データについて調べる
            if j == i:
                count += 1  #要素が含まれていればカウント
                
        [sorted_data.append(i) for k in range(count)]   #順にカウント分だけその要素を結果として配列に格納
        
    return sorted_data

if __name__ == '__main__':
    DATA = [9, 4, 5, 2, 8, 3, 7, 8, 3, 2, 6, 5, 7, 9, 2, 9]
    data_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    sorted_data = bin_sort(DATA, data_list)
    print(f"参照リスト: {data_list}\n\n{DATA} → {sorted_data}")
```

#####出力
```
参照リスト: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

[9, 4, 5, 2, 8, 3, 7, 8, 3, 2, 6, 5, 7, 9, 2, 9] → [2, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 8, 9, 9, 9]
```

ソースコード内で定義している関数では，第2引数に参照リストを渡せるが，デフォルトでは``[0,1,2,3,4,5,6,7,8,9]``となるようにしている．そのため，参照リストを変更するときは，関数を扱うときに第2引数にリストの型で指定すればよい．

##感想
ついに，並べ替えアルゴリズムを終えた．少し長かったが，今後役立つと願おう．今回のビンソートは参考文献における"理解度check"の問題であり，様々な書き方があるとは思うが，今の私が思いつく良い方法を示した．次回からも参考文献に沿って学習を進める．残るは後1章分．また楽しみである．

##参考文献
Pythonで始めるアルゴリズム入門　伝統的なアルゴリズムで学ぶ定石と計算量
　　　　　　　　　　　　　　　　　　　　　　　　 増井 敏克　著　　翔泳社
Java  Wordでブックマークを追加・削除

<p><strong>Microsoft Word 文書のなかに「しおり」のようにブックマークを挿入することができます。今日はSpire.Doc for Javaを使ってWordでブックマークを追加・削除する方法を紹介します。</strong></p>
<h4><strong>下準備</strong></h4>
<p><strong>1.E-iceblueの公式サイトから<a href="https://www.e-iceblue.com/Download/doc-for-java-free.html">Free Spire.doc for Java</a>無料版をダウンロードしてください。</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210127/20210127155151.png" alt="f:id:lendoris:20210127155151p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<p><strong>2.IDEを起動して新規プロジェクトを作成してから、インストールされたファイルにあった相応しいSpire.doc.jarを参照に追加してください。</strong></p>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210127/20210127155210.png" alt="f:id:lendoris:20210127155210p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<h4><strong>ブックマークを追加</strong></h4>
```JAVA
import com.spire.doc.*;
import com.spire.doc.documents.Paragraph;

public class InsertBookmark {

    public static void main(String[] args) {

        //Document objectを作成します。
        Document doc = new Document();

        //Wordをロードします。
        doc.loadFromFile("C:\\Users\\Administrator\\Desktop\\sample.docx");

        //しおりをつけたい段落を取得します。
        Paragraph paragraph = doc.getSections().get(0).getParagraphs().get(1);

        //BookmarkStartを追加し、段落の最初へ移動させます。
        BookmarkStart start = paragraph.appendBookmarkStart("しおりです");
        paragraph.getItems().insert(0,start);

        //段落の最後にBookmarkEndを追加します。
        paragraph.appendBookmarkEnd("myBookmark");

        //保存します。
        doc.saveToFile("output/AddBookmark.docx", FileFormat.Docx_2013);
    }
}


```


<h4><strong>完成例</strong></h4>
<p><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/l/lendoris/20210127/20210127155309.png" alt="f:id:lendoris:20210127155309p:plain" title="" class="hatena-fotolife" itemprop="image" /></p>
<h4><strong>しおりを削除</strong></h4>
```JAVA
import com.spire.doc.Document;
import com.spire.doc.FileFormat;

public class RemoveBookmark {

    public static void main(String[] args) {

        //Documentを作成します。
        Document doc = new Document();

        //Wordをロードします。
        doc.loadFromFile("C:\\Users\\Administrator\\Desktop\\InsertBookmark.docx");
        
        //初めのしおりを削除します。
        doc.getBookmarks().remove(doc.getBookmarks().get(0));

        //保存します。
        doc.saveToFile("output/RemoveBookmark.docx", FileFormat.Docx);
    }
}
```

<p> </p>
yarr で Python で numpy データをさくっと RPC 通信するメモ

## 背景

numpy データ(画像データ,　ボリュームデータなどサイズ大きめ)を RPC でやりとりしたい.

IPython, Jupyter-lab で C native module を autoreload するメモ
https://qiita.com/syoyo/items/0c633eda1a0bfdc31e3a

にあるように, 計算モジュールが native module になっており, リロードさせたいために Python プロセスを分けたいとか, 

ぱぱっと numpy データを複数 PC に送って分散処理させたいときとか.

yarr がありました.


## yarr

https://pypi.org/project/yarr/

ありがとうございます. 普通に pip で入ります.

`python -m pip install yarr`

pure Python なので Windows でも動きます.

Linux, Windows で動作確認しました.
(ただ, Win server, Linux client の場合だと通信できませんでした. Win 側でポートを開けておかないとだめ?(client 側で connection error 出してくれない))

### server

```py
import yarr
import numpy

def proc_numpy(a):
    print(a)

# server
yarr.yarr(('localhost', 8000), [proc_numpy])
```

### client

```py
import yarr
import numpy

a = numpy.random.rand(256, 512, 512)

yarr.call(('localhost', 8000), 'proc_numpy', a)
```

Voila! :tada:

さくっと numpy データ送れました.

localhost Threadripper 1950X で試したところ, `256x512x512x8(sizeof(float64)) = 512 MB` で 2 秒くらいでした. ネットワークだと帯域ネックになる(~2.5 G イーサくらいまで)ので, パフォーマンスには問題ないでしょう.

## しくみ

中身としては `struct` module でエンコード/デコードして, socket 通信で送っているだけです.

コードも 100 行ちょっとなので, 必要に応じて自前で改変できます.

## 問題点

ライセンスの名前がよくない...(ライセンス自体は Public domain に近いのでよいので残念)
BEM命名をルール化 & HTML5要素を正しく使う

## はじめに

タイトルについて記事にしました。
この記事で得る内容は以下の通りです。

・ BEMで命名する名前の法則を予め考えておくことで、コーディングの質の向上と効率化を図る
・ HTML5要素を正しく理解し、適切に扱えるようになる

## 前提

#### CSSでidを使用しない

CSSでidを使用しない考え方が今の主流で、**idで指定しなければならない理由がなく、**
**idかクラスにするかの迷いを一切なくしてコーディングスピードを上げる**ことが目的です。

## BEMの命名

表以外にもたくさんあると思いますが、実際に使い勝手を確認して都度編集する可能性があります。

#### Block

汎用的にコンテンツを包むものにはdiv要素を使い、他は目的に合った要素を使います。
以下の表は、`<div class="クラス名">`のように名前を入れる際に使います。

| 名前 | 用途 | 説明 |
|:---:|:---:|:----:|
| wrapper | コンテンツを包む大きな要素 | コンテンツを包んで整列や調整を行う |
| container | 要素のグループ化 | 要素を視覚とスタイリング両方の意味でグループ化する |
| introduction | 導入 | introと略してもOK |
| description | 概要 | descと略してもOK |
| detail | 詳細 | - |
| feature | 特徴 | - |
| block | 汎用的 | 囲うもの |
| box | 汎用的 | 箱・入れ物 |
| inner | 汎用的 | 内側 |
| module | 汎用的 | 部品 |

wrapperとcontainerには、製作者の意図により使用する意味が異なるので正解がありません。
チームで決められているのであればそのルールに従い、個人であれば正しいと思う使い方を選択します。

#### Element

| 名前 | 用途 | 説明 |
|:---:|:---:|:----:|
| item | 項目 | - |
| list | 一覧 | - |
| heading | 見出し | - |
| main / sub | メイン / サブコンテンツ | 主 / 副 |
| next / prev | 方向性を示すもの | 次 / 前（previousの略） |


#### Modifier

| 名前 | 用途 | 説明 |
|:---:|:---:|:----:|
| active / disabled | 汎用的 | 有効 / 無効 |
| open / close | 汎用的 | 開く / 閉じる |
| show / hide | 汎用的 | 表示 / 非表示 |
| size | 大きさ | small,middle,largeを使ってもOK |
| direction | 方向 | top,left,bottom,rightを使ってもOK |
| shape | 形状 | circle,squareを使ってもOK |
| reverse | Flexboxで並び替える | 逆・反転 |

## 考えても思い浮かばない場合

ネーミングツール[codic](https://codic.jp/)を利用しましょう。
例えば、要素を取得するクラスを何にしようか思い浮かばない時は、要素を取得すると入力すると
get_elementと提案してくれます。

## HTML5要素

数多くあるHTML要素の中でも、特に使用頻度が高いものをまとめました。
ルート要素や文書のメタデータは省略します。

#### セクション

文章やアプリケーションの一部分で、意味や機能のひとまとまりのことです。

| 要素 | 用途 | 説明 |
|:---:|:---:|:----:|
| header | ヘッダ | 文書・またはセクションのヘッダを表す |
| footer | フッタ | 文書・またはセクションのフッダを表す |
| section | 章や節 | 文章の論理構造を示すもので、要素内に見出し要素が必要<br>コンテナ要素ではないので、レイアウト目的で使用することは不可 |
| aside | 補足セクション | 補足情報・余談・用語説明・サイドバー・広告に使う |
| nav | ナビゲーション | サイト、またはページ内の移動で必要になるリンクメニューで使う<br>ヘッダやサイドバーのリンクメニューなど |
| h1〜h6 | 見出し | セクションの見出しを表す<br>h1に近いほど見出しのランクが高くなり、h6に近いほど低くなる |

#### コンテンツのグループ化

| 要素 | 用途 | 説明 |
|:---:|:---:|:----:|
| p | 段落 | 文章中の1つのブロックを表し、文章に区切りを入れる時に使う |
| ul | 順不同のリスト | リスト内の項目はli要素で示す |
| li | リスト内の項目 | ul要素の子要素として使う |
| main | 文書のメインコンテンツ | **文書**のメインコンテンツであることを示す |
| div | 特定の範囲をグループ化 | 特定の意味はないが、グルーピングしたい時に使う<br>他に適切な要素があればそちらを優先する |



## 関連記事
[CSSの命名規則BEMについて](https://qiita.com/s79ns/items/83a28387001fc6b318ef)