OmniAICreator/Qiita-1.07M huggingface dataset:
正規表現メモ：先読み・後読み

先読み(Lookahead)
```
foo(?=bar)
```
fooがあって、その後にbarがある場合にのみfooがマッチする
先のほうを読むだけ読んで判断するが、条件自体は結果にはかけないイメージ（なので先読み）

後読み(Lookbehind)
```
(?<=foo)bar
```
barがあって、その前にfooがある場合にのみbarがマッチする
前の方を後から読んで結果にかけるかかけないかを決めるイメージ（なので後読み）

蛇足: 記号だけ見ると初見じゃ分かりづらいが、先読みの記号パターンを見てそれの順番が逆のバージョンと考えると「まぁこういうふうにするしかないんだろうなぁ」となる（なった）

## イコールを`!`（感嘆符）と入れ変えると否定的先読み/後読みになる
先ほどの「ある場合」を「ない場合」に置き換えたものと考えればよいと思われる

否定的先読み
```
foo(?!bar)
```
否定的後読み
```
(?<!foo)bar
```

## 参考
[正規表現 > 言明 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions/Assertions#%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%AE%E8%A8%80%E6%98%8E)
[Firefox 78 for developers - Mozilla | MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/78#javascript) - 本題とはあまり関係ないが、火狐だと2020年6月末のアップデートで完全に対応されたらしい（それまでは火狐では後読み(Lookbehind)が使えなかったんだとか。[ここ](https://bugzilla.mozilla.org/show_bug.cgi?id=1225665)を見るに、Chromeはそれ以前から対応してたと思われる）
[regextester.com](regextester.com) - 数ある正規表現テスターの一つ。これが気に入ってて使ってたんだけど、なぜか「後読みはjsじゃ使えませんよー」的なこと言われるので調べるきっかけになった。同じようなこと言われるサイトがほかにもあったけど、それら含めテスト自体はできる模様（規格で標準化されてないだけとか？）

追記：Look ahead/behindをLookahead/behindと続けるかどうかについては[英語版MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet#other_assertions)に倣ってとりあえずそうしてみていたのですが、検索にかけてみてもregex関連だと続けざまの用例のが多いっぽいのでこのままにさせていただきます（なんでなんだろう）。編集リクエスト感謝
（釈明の意味でこう言おうと思ってたのだけど、なぜか普通にLookahedと誤字っていたのでそれのついで程度のつもりだったのしれない。というか多分そうだけど。ともかく感謝）
文字コードの本質(JIS、SJISの変遷編）

文字コードのうち1文字分として2バイト（0x88 0xB7）を得たところまでOK！という方を前提にしています。

以下のことが全てだったりするのですが、
　（私たち）Shift-jis としては、
　0x88 0xB7 を 姐 とする
ということです。

これが　画面　に文字を、という仕様であれば画面のドットに 姐 と見えるような点を表示させる、
これがプリンタに文字を、という仕様であればプリンタは紙に 姐 と見えるような黒を付ける、
という動作をします。

ポイントとしては、画面は点を表示させる処理、プリンタは黒を付ける処理、のところまでは 0x88 0xB7 のまま、ということです。

具体的には、ファイルやネットワーク上では常に 0x88 0xB7 としてデータが記録・読出・通信をしています。

これを頭の中でイメージしておくと、次のことがよくわかると思います。


データを見ようとすると、点を表示させる、黒を付けることになるので、 安 もしくは 0x88 0xB7 でしか見れない！

当たり前でもあるし、次の理由から悩ましい問題でもあります。
これは、jis78 のコードを見たくても、2020年代のWindows、MacOS等で行おうとすると、その時代の処理となることです。

では、一覧のようにして比較してみると、
（私たち）Shift-jis としては 0x88 0xB7 を 姐 とする
（私たち）      jis としては 0x88 0xB7 を 袷 とする
参考：https://pentan.info/doc/sjis_list.html
という定義を、それぞれの人たちがしているにすぎません。

なので、0x88 0xB7 が 姐 と画面に表示されたらWidnows、MacOSがShift-jisとして文字を出したんだな、
　　　　　　　　　　　袷 と 紙 に印字されたらWidnows、MacOSが   jis   として文字を出したんだな、
ということなのです。


これらが特に問題になるのは、コード変換のとき、でしょう。
一番よい方法は、全部の時代コードそれぞれに、他では何番、としてデータがあることです。
ただ、誰も作っていないようです・・・
概要としては、Shift-jis > jis のとき、 0x88 0xB7 だったら 0x88 0xBF に置換する。（jisで袷は 0x88 0xBF）
というようにあればOK。
現在では計算での変換が多いのと、一見問題がなさそうですが、jisには78、83、90、2004 で文字の形が違うこと、同じ文字「厩」は 0x 0x の場所が異なること、文字コードとしてShift-jis、Code932(Microsoft Shift-jisと表現されるもの）、UTF-8、NEC系、IBM系、があります。
それぞれの特徴だけが掲載されたページが多いのですが、ライブラリでも全体を賄うものは無いようなので、単純なコード表と変換表（エクセルで作れる？）があればなと思います。
compile: version "go *.**" does not match go tool version "go *.**"エラーの解決

# compile: version "go *.**" does not match go tool version "go *.**"エラー

goの環境構築していてhello worldさせるために、
はりきって` go run hello.go `をしたら上記のエラーがでた。

## エラー内容
```
# unicode/utf8
compile: version "go1.16.2" does not match go tool version "go1.17.8"
# runtime/internal/sys
compile: version "go1.16.2" does not match go tool version "go1.17.8"
# internal/unsafeheader
compile: version "go1.16.2" does not match go tool version "go1.17.8"
# internal/race
compile: version "go1.16.2" does not mat
```

goenvを使っていて`goenv global 1.17.8`の指定なのにgo toolでは1.17.8が使用されている？

そういえば環境構築時にbrewインストールしたバージョンとは違うバージョンをgoenv globalで指定していた記憶があったような。

### 一旦goenvの確認
```
$ go env | grep GOVERSION
GOVERSION="go1.17.8"
```


### brewでgoをアンインストールする

```
$ brew uninstall go
Uninstalling /usr/local/Cellar/go/1.17.8... (10,831 files, 566MB)
```
これで1.17.8とはさよなら。もう一回確認。

```
$ go env | grep GOVERSION
GOVERSION="go1.16.3"
```
go1.16.2になってほしいのに今度はなぜかgo1.16.3が設定された。
いっそのことGo関係すべてを削除する。
```
$ sudo rm -rf /usr/local/go
$ sudo rm -rf /etc/paths.d/go
$ rm -rf ~/go
$ rm -rf ~/.goenv
```
※他のところを削除しないように注意して実行してね。

### Go再インストール
```
$ brew install go
$ which go
/usr/local/bin/go
```
PATHは以下のように設定

```~/.zshrc
export PATH=$PATH:/usr/local/go/bin
```

.zshrc再読み込み
```
$ source ~/.zshrc
```


仕切り直して` go run hello.go `する。

一発でうまくいかなかったのでPC再起動したらできました。
NamedTemporaryFileにおけるアップロード時のclosed file関連のバグ

:::note info
本記事で扱っている内容はNamedTemporaryFileのバグです。
:::
### 概要
NamedTemporaryFileでDLしたファイルをS3へアップロードした後、再度参照しようとした際にclosed file関連でエラーが出たので、その時の対処法を記載する。

### 困った事
以下の手順で開発を進めていたが、手順4の箇所で以下のエラーに遭遇し解決策を模索していた。
```python:
ValueError: I/O operation on closed file
```
```python:
ValueError: seek of closed file
```
```python:
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpoirwooqn.xlsm'
```
1. S3からxlsmをDL
2. 情報を転記
3. S3へxlsmをUP
4. xlsmを参照して情報を修正
5. S3へxlsmをUP（3とは独立）

### 元のソース
```python:
with tempfile.NamedTemporaryFile(mode='wb+', suffix='.xlsm') as tf:
    # S3からテンプレートファイルをダウンロード
    s3 = S3()
    s3.download_report_file('template_hoge/hoge/', 'template', tf)

    # テンプレートファイルにデータを入力してファイルを作成
    for file_type in ['xlsm', 'xlsx']:
        if file_type == 'xlsm':
            wb = openpyxl.load_workbook(tf.name, keep_vba=True)
            # ファイルに情報転記（省略）
            wb.save(tf.name)
            # ファイルをS3へアップロード
            tf.seek(0)
            s3.upload_report_file('hoge/hoge/', 'hoge', tf)
        elif file_type == 'xlsx':
            wb = openpyxl.load_workbook(tf.name)
            # ファイルに情報転記（省略）
            wb.save(tf.name)
            # ファイルをS3へアップロード
            tf.seek(0)
            s3.upload_report_file('hoge/hoge/', 'hoge', tf)

```

### 解決策
https://github.com/boto/s3transfer/issues/80

```python:
class NonCloseableBufferedReader(BufferedReader):
    def close(self):
        self.flush()

with tempfile.NamedTemporaryFile(mode='wb+', suffix='.xlsm') as tf:
    # S3からテンプレートファイルをダウンロード
    s3 = S3()
    s3.download_report_file('template_hoge/hoge/', 'template', tf)

    # テンプレートファイルにデータを入力してファイルを作成
    for file_type in ['xlsm', 'xlsx']:
        if file_type == 'xlsm':
            wb = openpyxl.load_workbook(tf.name, keep_vba=True)
            # ファイルに情報転記（省略）
            wb.save(tf.name)
            # ファイルをS3へアップロード
            tf.seek(0)
　　　　　　　　　　　　　　　　　　　　　　　　buffer = NonCloseableBufferedReader(tf)
            s3.upload_report_file('hoge/hoge/', 'hoge', buffer)
            buffer.detach()
            assert not tf.closed
        elif file_type == 'xlsx':
            wb = openpyxl.load_workbook(tf.name)
            # ファイルに情報転記（省略）
            wb.save(tf.name)
            # ファイルをS3へアップロード
            tf.seek(0)
            s3.upload_report_file('hoge/hoge/', 'hoge', tf)

```

### 回避策の説明
:::note warn
近日公開
:::
JavaScriptでDOMをDFSする4つの書き方

## はじめに

DOM(Document Object Model)のDFS（深さ優先探索）をする場合、再帰関数を使う普通の書き方をしています。

再帰関数を使わないでDOMのDFSを書けることは有名ですが、DOMが子要素や兄弟要素へのリンクを持つ特性を利用することによって、配列も再帰関数も使わないで書けます。

コメントで知った方法と合わせて4つの書き方があることを紹介します。

それぞれの時間を計測したら意外な結果になりました。

## 4通りの書き方

4つのJavaScriptプログラムは[一文字命名規則](https://qiita.com/querykuma/items/02e28f8357666d1b3ed1)を使っています。

### dfs_1

普通は再帰関数で書きます。

```javascript
var dfs_1 = (e_base) => {
	var e_children = e_base.children;
	for (let index = 0; index < e_children.length; index++) {
		const e_child = e_children[index];
		dfs_1(e_child);
	}
};
```

### dfs_2

配列に状態を保存することによって再帰関数を使わないで書けます。

```javascript
var dfs_2 = (e_root) => {
	var e_focus;
	var d_dfs = [e_root];

	while (d_dfs.length) {
		e_focus = d_dfs.shift();

		if (e_focus.children.length) {
			d_dfs.unshift(...e_focus.children);
		}
	}
};
```

### dfs_3

DOMが子要素(`firstElementChild`)や兄弟要素(`nextElementSibling`)へのリンクを持つ特性を利用することによって実は**配列も再帰も使わないで**書けます。

どのように書けば良いでしょうか？

頭の体操です。正解を折りたたみで隠しますので少し考えてみてください。

<details><summary>再帰も配列も使わない書き方</summary>

```javascript
var dfs_3 = (e_root) => {
	var e_focus = e_root;

	outer: while (true) {

        if (e_focus.firstElementChild) {
			e_focus = e_focus.firstElementChild;
			continue;
		}

		while (true) {
			if (e_focus == e_root) {
				break outer;
			} else if (e_focus.nextElementSibling) {
				e_focus = e_focus.nextElementSibling;
				continue outer;
			} else {
				e_focus = e_focus.parentElement;
			}
		}
	}
};
```

</details>

### dfs_4

Web API の[createTreeWalker](https://developer.mozilla.org/en-US/docs/Web/API/Document/createTreeWalker)でも書けます。

MDN Web Docs には DFS という説明がありませんが DFS のようです。

```javascript
var dfs_4 = (e_root) => {
	var t_root = document.createTreeWalker(e_root, NodeFilter.SHOW_ELEMENT);
	var e_focus = t_root.currentNode;

	while (e_focus) {
		e_focus = t_root.nextNode();
	}
};
```

## 時間計測

時間を計測してみました。

| dfs    | 時間(msec) |
| ------ | ---------: |
| dfs_1  |       23.7 |
| dfs_2  |       91.0 |
| dfs_2b |       79.7 |
| dfs_3  |       12.8 |
| dfs_4  |        5.7 |

> メソッド push/pop は処理が速く、shift/unshift は遅いです。
>
> [現代の JavaScript チュートリアルの配列](https://ja.javascript.info/array)

というのを見つけて shift/unshif を push/pop に変えたプログラムがdfs_2bです。

## さいごに

dfs_1 > dfs_2 > dfs_3 と予想していたので意外な結果になりました。

JavaScriptで配列を使うくらいなら再帰関数のままで良い、と言えそうです。

shift/unshift を push/pop に変えても少しだけ速くなりましたが、そもそも配列を使うことが遅くする、と言えそうです。

dfs_4 はシンプルで可読性が高く最速です。Web API が存在するなら Web API を使いましょう。
SUID とは

## 勉強前イメージ

特殊なパーミッションだけどなんだっけ？
最近そういうの調べてる

## 調査

### SUID とは

Set User ID の略で、実行ファイルに設定されます。
通常の実行ファイルは実行者の権限で実行されますが
SUIDが設定されていたら所有者の権限で動作します。

### 代表的なファイル

centosで確認しています。
`/usr/bin/passwd ` を見ると所有者の実行権限に `s` が書かれています。
これがSUIDを表しています。

```
[root@localhost ~]# ll /usr/bin/passwd 
-rwsr-xr-x. 1 root root 27856  4月  1  2020 /usr/bin/passwd
```

このSUIDが意味するのは、
/usr/bin/passwdについて誰がこのコマンドを実行してもroot権限で実行されることになります。

### SUIDを設定してみる

- ファイルを作ってみる

file_suid を作ってみました。

```
[root@localhost ~]# touch file_suid
[root@localhost ~]# ll
-rw-r--r-- 1 root root    0  3月 19 09:27 file_suid
```

- SUIDの権限を指定

元々は644なのですが、所有者に実行権限がないので
755にしてSUIDを設定します。
SUIDは4000を足して付与します。
下記のように所有者に `s` が付きました。

```
[root@localhost ~]# chmod 4755 file_suid 
[root@localhost ~]# ll
-rwsr-xr-x 1 root root    0  3月 19 09:27 file_suid
```

## 勉強後イメージ

そういえばそんなんあったなぁって。
これで特殊権限は終わりかな？

## 参考

- [【初心者でもすぐわかる】SUIDとは？と設定方法](https://eng-entrance.com/linux-permission-suid)
- [SUIDとは](https://www.itmedia.co.jp/enterprise/articles/0804/08/news014.html)
Mysql2::Error: Unknown database 'app_development'が急に出た

## 環境
macOS Monterey 12.3
docker-compose 2.2.3
mysql 8.0
rails 6.1.4
rails初心者が突然のエラーに出会い、もうrails諦めようと思ったので、経緯を含めて書きました。
半日くらいでエラー解消。

## 困ったこと

アプリ作成中に突然エラーが出ました。
```
Mysql2::Error: Unknown database 'app_development'
```

> app_developmentなんてデータベースありません。

かな？いや、さっきまでずっと使えてたのに、、

[画像イメージ](https://rails-ambassador.herokuapp.com/debugs/NoDatabaseError)


## 試したこと

### 1. とりあえずコマンド打った
docker-compose exec web rails db:reset
docker-compose exec web rails db:migrate:reest
docker-compose exec web rails db:create

どれも共通のエラー
```ターミナル: ターミナル
Mysql2::Error: Schema directory './app_development' already exists. This must be resolved manually (e.g. by moving the schema directory to another location).
```
> このディレクトリは既に存在します。手動で解決しましょう。

かな？んー、、

---
docker-compose exec web rails db:create:all
```ターミナル: ターミナル
This task only modifies local databases. app_development is on a remote host.
This task only modifies local databases. app_test is on a remote host.
```
> このタスクはローカルのデータベースのみを変更します。app_developmentはリモートホストにあります。

んー、、

### 1. とりあえずmysqlに入ってみた
シェルに入る
```ターミナル: ターミナル
docker-compose run --rm web bash
```
---
とりあえずmysqlに入るコマンド 何だったか忘れたけど打っていった。
***
mysql -u root -p app_development
pass入力すると、
```ターミナル: ターミナル
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/run/mysqld/mysqld.sock' (2)
```
[mysqlが起動できない](https://qiita.com/___fff_/items/3a4398b3e6a8f5e27b09)
エラー、、

***
[Docker MySQL ではlocalhostでのアクセスは禁止されている](https://timesaving.hatenablog.com/entry/2021/11/23/150000#%E7%B5%90%E8%AB%96)
mysql -u root -h 127.0.0.1 -p
pass入力
同じエラー、、

***
[Dockerコンテナ上のMySQLにホストOSから接続できない](https://kamatimaru.hatenablog.com/entry/2020/05/30/023739)
mysql -u root -p -h 127.0.0.1 -P 3306
pass入力
同じエラー、、、

***
[mysqlを立ち上げる](https://qiita.com/SwuBHj8aKGqBKHet/items/2033b0b327b9b8d96ce3)
```SQL:sql
mysql -u root -p -h db
```
pass入力
入れた!
dbって(database.yml)_default_hostに書いたやつ？、、
***

### やっとmysqlに入った
データベース一覧を見る
```SQL:sql
SHOW databases;
```
![スクリーンショット 2022-03-19 6.09.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699159/2319117e-d311-edea-d496-2aafa27b4bbf.png)

何個もあるけど何これ、、。
あと今更だけど、db/mysql_data 見ると大量にデータある。。
作った覚えはない。自動バックアップのせい、、？


とりあえずデータベースを削除していく。
```SQL:sql
DROP DATABASE IF EXISTS `app_development-3`;
```
他も削除していって、こうなった。
![スクリーンショット 2022-03-19 6.10.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/699159/70edc166-c606-4380-9517-bdd2b7afb6c6.png)


データベースを新しく作る。

```SQL:sql
CREATE DATABASE app_development;
```

またエラーかよ、、

```ターミナル: ターミナル
ERROR 3678 (HY000): Schema directory './app_development' already exists. This must be resolved manually (e.g. by moving the schema directory to another location).
```

もうわからないので、app_developmentを手動で削除した。 (db/mysql_data/app_development)

データベースを新しく作る。

できた!

そしてマイグレーション！

エラー消えた!

ひとまず終わり。。。
今回みたいに何もしていないのにエラー出る可能性が今後もあるかもしれない。
それで挫折してしまうことを考えるとすごく怖い。一人じゃわからない。
Android keystore コマンドラインから作成

Javaがインストールされているか確認
（インストールされてない場合は <a href="http://jdk.java.net/">こちら</a> からインストール）
```
$ java --version
java 17.0.2 2022-01-18 LTS
Java(TM) SE Runtime Environment (build 17.0.2+8-LTS-86)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.2+8-LTS-86, mixed mode, sharing)
```

キーストアを生成する
（ ※ `-storetype JKS` を指定しないと<b>Unityで上手く読み込めなかった</b> ）
```
$ keytool -genkey -v \
-keystore keystore_name.keystore \
-storetype JKS \
-storepass XXXXXX \
-alias alias_name \
-keypass XXXXXX \
-keyalg RSA \
-validity 65700
```

質問事項に答えていく
```
姓名は何ですか。
 [Unknown]: Name
組織単位名は何ですか。
 [Unknown]: GroupName
組織名は何ですか。
 [Unknown]: CompanyName
都市名または地域名は何ですか。
 [Unknown]: Shibuya-ku
都道府県名または州名は何ですか。
 [Unknown]: Tokyo
この単位に該当する2文字の国コードは何ですか。
 [Unknown]: JP
CN=Name, OU=GroupName, O=CompanyName, L=Shibuya-ku, ST=Tokyo, C=JPでよろしいですか。
 [いいえ]: Y
```
生成されたキーストアを確認する
```
$ keytool -v -list -keystore keystore_name.keystore
キーストアのパスワードを入力してください: XXXXX
キーストアのタイプ: JKS
キーストア・プロバイダ: SUN

キーストアには1エントリが含まれます

別名: alias_name
作成日: 2022/03/11
エントリ・タイプ: PrivateKeyEntry
証明書チェーンの長さ: 1
証明書[1]:
所有者: CN=Name, OU=GroupName, O=CompanyName, L=Shibuya-ku, ST=Tokyo, C=JP
発行者: CN=Name, OU=GroupName, O=CompanyName, L=Shibuya-ku, ST=Tokyo, C=JP
シリアル番号: xxxxxxxxxxxxxxxx
有効期間の開始日: Fri Mar 11 00:00:00 JST 2022終了日: Wed Jan 27 00:00:00 JST 2202
証明書のフィンガプリント:
	 SHA1: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
	 SHA256: XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
署名アルゴリズム名: SHA256withRSA
サブジェクト公開キー・アルゴリズム: 2048ビットRSAキー
バージョン: 3

拡張: 

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: XX XX XX XX XX XX XX XX   XX XX XX XX XX XX XX XX  ...$...Z!h..(..9
0010: XX XX XX XX                                        D...
]
]



*******************************************
*******************************************



```
効率のいいコードの書き方

コードを書いていると、下部のようなデザインによく出くわします。
　
![Group 6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531102/687bdd0a-9777-f1e6-8497-f68f37ede195.png)

スキーマのblockforで動的に追加するのであれば、アイテムになる部分の記述は１度でいいのですが、
静的に固定されているような時は、同じものを４回書くのもあれだし…だからといってSHOP内で、このカード使うところここしかないのでスニペットファイルにするのも…うーん…みたいな時に、for文で書く方法がないかとやり始めた方法です。

管理しやすく？記述量も大幅に減らせると思っているので、個人的におすすめです。

## コード紹介
```
{%- comment -%} ラベル {%- endcomment -%}
{% assign title_array = "a,b,c,d" | split: "," %}

{%- comment -%} リンク {%- endcomment -%}
{% assign link_array = '/pages/a,/pages/b,/pages/c,/pages/d' | split: "," %}

<ul class="list">
  {% for i in (0..3) %}
    <li class="item">
      <a href="{{ link_array[i] }}"
        class="{% if i == 2 %} active {% endif %}"
      >
        {{ title_array[i] }}
      </a>
    </li>
  {% endfor %}
</ul>
```
変更になる箇所、タイトルやリンクなどの部分を先に配列で作成してあげて、for文をアイテム数だけ(0..3)で回してあげる方法です。
この方法で記述すると
・記述量を減らせ、見渡しやすい
・要素を新しく追加する時は、配列に追加して、カウント数を増やすだけでいい
・HTMLの構造の変更やクラス名の追加時に変更箇所が一箇所でいいこと
・ちょっと仕事できそうな雰囲気w

## 特定のスタイルの追加
aだけフォントを赤にしたい。
全てのカードの背景画像が違う
そんなこともあるかと思います。
aタグのクラス名にサンプルを追加していますが、for文の値が今何なのか？に合わせてクラス名を付与してもOKですし、スタイルシート内で:nth-child()で記述してもいいと思います。
そこは臨機応変に
　
### まとめ
始まりは、ただ、書くのが面倒臭い！から始まったんですが…。
本当に楽です！
どこか使い道があれば活用されてみてください！
【図解】SASEの概念を婚活に例えてみた

ネットワークエンジニアとして、 **SASE（Secure Access Service Edge、サシー）** の概念を少し学びました。

> ネットワーク機能とセキュリティ機能とを組み合わせてクラウドサービスとして提供する「SASE（サシー）」。テレワーク時代の新たなサービスとして注目されています。（下記サイトより引用）

https://www.nttpc.co.jp/column/network/sase.html

これをわかりやすく説明するためのアナロジーとして、 **医師限定オンライン婚活と対比できる** と考えました。

![sase.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464218/8c22db95-eeb9-f8ec-b5c2-86aa4d4f2329.png)

SASEの特徴は前述のとおり、 **ネットワーク** と **セキュリティ** の機能を **クラウドベース** で提供するところです。それぞれの意味合いは下記のようになります。

・実現したいこと ＝ ネットワーク (厳密には、実現したいことの手段としての通信)
・認証の仕組み ＝ セキュリティ
・プラットフォーム ＝ クラウドベース


これと似た仕組みとして、 **医師などの職業を限定した、オンライン上での婚活サービス** が挙げられます。

・実現したいこと ＝ 婚活
・認証の仕組み ＝ 医師免許の提出 (必要ですよね…？)
・プラットフォーム ＝ オンライン

顧客の複雑なニーズを、複数サービスの寄せ集めではなくワンストップなサービスとして実現できる、というメリットを説明できるかと思います。それをService Edgeに置くメリットをまだ自分が理解しきれていないので、引き続き学ばないといけないです。

医師限定オンライン婚活を利用したことがある方(つまり医師)にSASEの説明をする機会はそうそうないのが残念ですけどね…

https://note.com/anpanda_44075/n/n37e8ae66ad40
IP毎にログ保管し指定期間を超えたらログ削除するsyslogサーバを作る

# はじめに
CentOS７上に、rsyslogを使ってsyslogサーバを構築した際の設定メモです。

# 実現したいこと
1. サーバや無線アクセスポイントなど機器ごとにIP名でディレクトリを自動的に作ってログを保管。
1. ログは各ディレクトリに1日1ファイルで残す。
1. 一定期間が経過したログファイルを自動削除。

# 設定
rsyslogが入ってなければ、事前にyumでインストールする。

## ログ受信に必要なポートを開ける
firewall-cmdでログ受信に必要なポートを開ける。
```shell-session
$ sudo firewall-cmd --add-port=514/udp --permanent
$ sudo firewall-cmd --add-port=514/tcp --permanent
$ sudo firewall-cmd --reload
```

## rsyslog設定ファイルの変更
rsyslogの設定ファイルを変えて、実現したいことの1と2ができるようにする。

```shell-session
$ vi /etc/rsyslog.conf
```

次を変更する。

14-20行目あたりを次のようにコメントアウトして、syslogを受信できるようにする。

```vim:/etc/rsyslog.conf
# Provides UDP syslog reception
$ModLoad imudp
$UDPServerRun 514

# Provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514
```

51行目以降に次を記載して、IP単位でディレクトリを作り、日付単位でログファイルを作成する。（/var/log/rsyslogのディレクトリにログを保管するとする場合）
さらに、指定のグループ（仮にhogeとする）にもログやディレクトリに権限を与える（何もしないと作成ファイルはrootのみしか権限付与されない）。

```vim:/etc/rsyslog.conf
$umask 0000
$DirCreateMode 0770
$DirGroup hoge
$FileCreateMode 0660
$FileGroup hoge
$template hostFile,"/var/log/rsyslog/%fromhost-ip%/%$year%-%$month%-%$day%.log"
```
## 一定期間後の自動ログ削除対応
実現したいことの3については、簡単なスクリプトを作りcronに登録することで対応する。

ログ保管フォルダに存在するファイルで、最終更新が100日以上のものをfindで見つけ、それを削除するスクリプトを次のように書く。

```shell:rm-rsyslogfile.sh
#!/bin/bash
find /var/log/rsyslog/ -mtime +100 | xargs --no-run-if-empty rm
```

なお、xargsの--no-run-if-emptyをつけないと、対象ファイルが無い時に"rm: missing operand"のエラーが出るので、つけた方が良い。

chmodで実行可能にし、cronに登録する。（hogeユーザのホームに上記のスクリプトがあるとする。）

```shell-session
$ crontab -e

00 00 * * * /home/hoge/rm-rsyslogfile.sh
```
# 確認方法
別PCからログの送信（logger）をしたり、あえて古い更新時間のファイルを作ったり(touch --date)などして、動作確認する。参考文献の後ろ2つ参照。

# 環境

- CentOS Linux release 7.9.2009
- rsyslog 8.24.057.le7_9.1

# 参考文献
- [rsyslog.readthedocs.io](https://rsyslog.readthedocs.io/en/latest/index.html)
- [ネットワーク・ログ監視の技術情報 – ナレッジステア：rsyslogをホスト名、IPアドレスごとにフォルダー分けする方法](https://www.secuavail.com/kb/tech-blog/tb-210521-01-2/)
- [Linuxねた帳：rsyslog DirCreateMode・FileCreateModeが意図したとりに動作しない](https://knowledge4linux.blogspot.com/2014/01/rsyslog-dircreatemodefilecreatemode.html)
- [技術メモメモ：自宅PCにESXiを入れて検証を行うインフラエンジニアの技術メモ。](https://tech-mmmm.blogspot.com/2017/12/rsyslog-logrotate.html)
- [[Linux] 最終更新日や最終アクセス日を指定して、ファイルを検索/削除する](https://www.yoheim.net/blog.php?q=20170202)
- [@m_doi xargsで標準入力が空だったら何もしない](https://qiita.com/m_doi/items/432b9145b69a0ba3132d)
- [rsyslogでリモートからのログ出力を受け付ける設定とloggerコマンドでの確認](https://zaki-hmkc.hatenablog.com/entry/2020/03/22/184044)
- [【 touch 】コマンド――タイムスタンプを変更する／新規ファイルを作成する](https://atmarkit.itmedia.co.jp/ait/articles/1606/14/news013.html)
VSCodeを使ってシーケンス図をMarkdownで書いてみた

# Markdownでシーケンス図を描くメリット
- astahやdraw.ioが使えなくても描ける
- テキスト形式のファイルならGITやSVNのマージを楽にできる
- テキスト形式のため差分比較がしやすい
- htmlにmermaid.jsを読み込ませるとhtmlでも表示ができるらしい

# VSCodeのインストール

[VSCodeのダウンロードはこちら](https://code.visualstudio.com/ "https://code.visualstudio.com/")

VSCodeのインストール手順は下記サイトを参考にさせていただいた。

https://breezegroup.co.jp/201904/visualstudiocode/

# VSCodeの拡張機能(プラグイン)をインストール
VSCodeに下記の拡張機能(プラグイン)をインストールする。

1. Markdown Preview Enhanced
1. Markdown PDF
1. Markdown All in One
1. Marp for VS Code
1. markdownlint
----------------
1. Markdown Preview Enhanced
[公式ドキュメント](https://shd101wyy.github.io/markdown-preview-enhanced/#/ "https://shd101wyy.github.io/markdown-preview-enhanced/#/")
markdownでシーケンス図を書くときにmermaidとういライブラリを使えるようにする

1. Markdown PDF
https://marketplace.visualstudio.com/items?itemName=yzane.markdown-pdf
Markdownファイルをpdf、html、png、またはjpegファイルに変換する

1. Markdown All in One
https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one
Markdownを書くのが便利になる
(参考：https://zenn.dev/ctrlkeykoyubi/articles/vscode-markdown-all-in-one)

1. Marp for VS Code
https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode
VSCodeのMarpMarkdownで記述されたスライドデッキを作成できる
https://github.com/marp-team/marp-vscode
https://marpit.marp.app/markdown

1. markdownlint
https://marketplace.visualstudio.com/items?itemName=DavidAnson.vscode-markdownlint
Markdownの構文やスタイルをチェックしてくれる(フォーマッタ的な？)
(参考：https://tonari-it.com/vscode-markdownlint/)
--------------
左の拡張機能(プラグイン)ボタンを押下し、出てきた検索BOXで追加したい拡張機能を検索する。
検索で出てきたら「インストール」ボタン押下。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2330584/7ec88db1-3c8e-fd7d-7094-d4101fa3ec1d.png)

以上で準備完了！！(^^)/

# シーケンス図を書いてみた
markdownでのシーケンス図の書き方は下記サイトを参考にさせていただいた。

https://qiita.com/konitech913/items/90f91687cfe7ece50020

https://qiita.com/nozaki-sankosc/items/602ccaae25f81d0c06bf

★シーケンス図を作成する際のファイルの拡張子は **.md**(Markdown)。

**書いてみたmarkdown**
~~~ruby:sample.md
```mermaid
sequenceDiagram
participant goodsController as 商品表示画面Controller
participant goodsService as 商品表示画面Service
participant goodsRepository as 商品表示画面Repository

goodsController ->>+ goodsService: 文房具検索メソッド(種類, 色, メーカー)
    goodsService ->>+ goodsRepository : 文房具DBデータ検索メソッド(種類, 色, メーカー)
    goodsRepository　-->>- goodsService : 文房具データ
    goodsService　->> goodsService : 在庫数チェックメソッド
goodsService　-->>- goodsController : 画面表示用文房具データ
```
~~~
**結果**
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2330584/1b754a74-7f4e-733d-d5e4-e893957ac7d9.png)|
|:-:|

以上！！　(￣∀￣)ﾃﾞｷﾀｾﾞ!!　ｳﾚｼｲﾃﾞｽ!!


## 上記に記載されている以外で参考にさせていただいたサイト

https://qiita.com/tomo_makes/items/aafae4021986553ae1d8

https://qiita.com/take_me/items/5ff5304b58d9feec21df

https://e-words.jp/w/Markdown.html#:~:text=Markdown%20%E3%80%90MD%E3%80%91%20%E3%83%9E%E3%83%BC%E3%82%AF%E3%83%80%E3%82%A6%E3%83%B3%E8%A8%98%E6%B3%95,%E5%AD%90%E3%81%AF%E3%80%8C.md%E3%80%8D%E3%80%82

https://qiita.com/caesar_cat/items/e8a116a585863633d15a
Blazorでダイアログを出したい

## Step1_ダイアログのテンプレート

```c#:TemplateDialog.razor
@if (isShow)
{
<div class="dialog-outer" @onclick="@(() => this.Close())">
    <div class="dialog-content" @onclick:stopPropagation="true">
        @ChildContent
    </div>
</div>
}


@code {
    [Parameter]
    public RenderFragment ChildContent { get; set; } = null!;

    private bool isShow;

    public void Show()
    {
        this.isShow = true;
        this.StateHasChanged();
    }

    public void Close()
    {
        this.isShow = false;
        this.StateHasChanged();
    }
}
```

```css:TemplateDialog.razor.css
.dialog-outer {
    display: flex;
    justify-content: center;
    align-items: center;
    position: fixed;
    top: 0px;
    left: 0px;
    width: 100vw;
    height: 100vh;
    background-color: rgba(75, 85, 99, 0.8);
}

.dialog-content{
    max-height: 90vh;
    max-width: 90vh;
    overflow: auto;
    background-color: white;
}
```

## Step2_ダイアログの基底クラス
```c#:AbstractDialog.cs
    public abstract class AbstractDialog : ComponentBase
    {
        /// <summary>
        /// Dialog参照
        /// </summary>
        protected TemplateDialog TemplateDialog { get; set; } = new TemplateDialog();

        /// <summary>
        /// ダイアログを開く
        /// </summary>
        public virtual void Show()
        {
            TemplateDialog.Show();
        }

        /// <summary>
        /// ダイアログを閉じる
        /// </summary>
        public virtual void Close()
        {
            TemplateDialog.Close();
        }
    }
```

## Step3_好きなダイアログ作る
```C#:TemplateDialog.razor
@inherits AbstractDialog

<TemplateDialog @ref="TemplateDialog">
    <h2>ダイアログサンプル</h2>
    <hr />
    <hr />
    <p>本日は晴天なり本日は晴天なり</p>
    <p>あいうえおカキクケコ</p>


    @*Close()を呼び出して閉じる*@
    <Button @onclick="()=> this.Close()">閉じる</Button>
</TemplateDialog>
```

## Step4_ダイアログを呼び出したい画面に貼り付ける

```c#:Index.razor
@page "/"

// step2 - ダイアログの参照紐付けて
<TemplateDialog @ref="_dialog" />

// step3 - 好きなタイミングで.Show()を呼ぶ
<button @onclick="()=> _dialog.Show()">開く</button>
@code{
    // step1 - ダイアログインスタンス作って
    private TemplateDialog _dialog = new TemplateDialog();
}
```

## 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456434/5ccc8ade-5930-720e-384c-82926be5919e.png)

閉じるボタンか背景のグレーをタッチするとダイアログが消えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456434/2c49b572-4abf-be6f-78d1-55871181bd63.png)
【iOS】【Objective-C】【Swift】のコードまとめ

# 【iOS】【Objective-C】【Swift】のコードまとめ

# はじめに
仕事柄、バージョンアップの時にかなり調べたりすることが多かったので
【iOS】【Objective-C】【Swift】のコードをまとめておこうと思います

## 一覧
https://qiita.com/sunstripe2011/items/717c7f17395e6249f54a

# 最後に

iOS 開発の現場でもかなり重宝すると思いますので、こちらにまとめていきたいと思います。


---

【About】(http://qiita.com/sunstripe) - サンストライプ

---

## 制作チーム：サンストライプ

[![sunstripe_logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/322f2d60-f19d-af9e-2b6f-7290ca546848.png)](http://sunstripe.main.jp/)
http://sunstripe.main.jp/

(月１ WEBコンテンツをリリースして便利な世の中を作っていくぞ！！ボランティアプログラマー/デザイナー/イラストレーター/その他クリエイター声優募集中!!)

緩募


### 地域情報 THEメディア
THE メディア 地域活性化をテーマに様々なリリース情報も含め、記事をお届けしてます！！
https://the.themedia.jp/

### ゼロからはじめる演劇ワークショップ
多様化の時代に向けて他者理解を鍛える

https://workshop.themedia.jp/

### プログラミングワークショップ・ウェブ塾の開講！！！
様々なテーマでプログラミングに囚われずに取り組んでいきます。
詳しくはこちら　↓　↓　↓　↓　↓　↓　↓　↓
[プログラミングサロン 月１だけのプログラミング学習塾](https://workshop.themedia.jp/posts/7057553?fbclid=IwAR32CfRQ7RvDOhvuogoSwqxDLMOU7Jvuzljlnx-TMc27qBPX1BnWsfLcBR8
)

### 協力応援 / 支援者の集い
## チーム：サンストライプ
https://twitter.com/sunstripe2011

#### プログラミングラボ
https://twitter.com/PLab2020

一緒にポートフォリオを作りませんか？現場の体験やそれぞれの立場から年齢関係なく作品を作りたい方々と一緒にチームを作って、作品を作っています。現場に行きたい人には、職場紹介や職場の体験や悩み相談なども受けております。
様々な職種からプログラミングの知識を得たい、デザインの知識を得たい、データーベースの知識を得たいという人が集まっております。
週１のミーティングにそれぞれの近況と作業報告して、たまにリモート飲み会などをしております！！

興味がある方は、DMに話しかけてみてください。

#### トラストヒューマン
http://trusthuman.co.jp/
私たちは何よりも信頼､人と考えてます｡

｢コンサルティング｣と｢クリエイティブ｣の両角度から｢人材戦略パートナー｣としてトータル的にサポートします！！

### キャリア教育事業

#### 青空プログラミング
[![青空プログラミング100px.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/603d53ab-828b-645e-a415-1b6f158d7356.png)](https://actcoin.jp/project/detail.php?id=600)

[![ダウンロード (9).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/9bde9318-28c2-ce74-d4c5-326168061bcc.jpeg)](https://www.youtube.com/hashtag/%E9%9D%92%E7%A9%BA%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)

#### 広域学習支援プラットフォーム『のびのび日和』
https://slc-lab.amebaownd.com/

#スポンサー募集

## ネリム
https://nerim.co.jp/
配信事業などを映像コンテンツなどの制作しております

## ビヨンドXプロジェクト

[ビヨンドXプロジェクト全体会議](https://www.youtube.com/playlist?list=PLaR6-YWiGWkYhEHWnt8f1z-JC0g3nwwC9)
【Docker】複数のdocker-compose.ymlのネットワークを繋げる方法


## はじめに
　本記事は、プログラミング初学者、学習を進めていて疑問に思った点について調べた結果を備忘録も兼ねてまとめたものです。
　そのため、記事の内容に誤りが含まれている可能性があります。ご容赦ください。
　間違いを見つけた方は、お手数ですが、ご指摘いただけますと幸いです。

## 複数のdocker-compose.ymlのネットワークを繋げる方法
### Docker-compose.yml

```docker-compose.yml
version: '3'
 
services:
  drakov:
    build: .
    ports:
      - "3001:3001"
    volumes:
      - "./docs:/projects"
    tty: true
    command: drakov -f "**/*.md" --public --watch --p 3001
```




```docker-compose.yml
version: '3'
 
services:
  app:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - ".:/projects"
    tty: true
    networks:
      - [APIのネットワーク名]
networks:
    [APIのネットワーク名]:
      external: true
```
【iOS】【Objective-C】【Swift】for文について

# Swiftのfor文について

# はじめに

今更だけども聞いておきたい
昔のコード比較してみるとこんなに違うんだって思う時がありますね。
Objectice-C、Swift2、Swift3を比較にしてまとめていきましょう

#### Objective-C

~~~Objective-C:
//Objective-C
for (int i = 0; i < 10; i++) {
    NSLog(i);
}
~~~~

#### Swift2以前

~~~Swift:
//Swift2以前
for var i = 0; i < 10; i++ {
    print(i)
}
~~~~

#### Swift3以前

~~~Swift:
//Swift3以降
for i in 0..<10 {
    print(i)
}
~~~~

# 終わりに

脳のトレーニングで、直してみたりして勉強中です。
忘れた頃に検索して調べる時にまとめて行きたいと思います。

---
# 関連情報

- Objective-C バージョンアップ
- Swift バージョンアップ


---

【About】(http://qiita.com/sunstripe) - サンストライプ

---

## 制作チーム：サンストライプ

[![sunstripe_logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/322f2d60-f19d-af9e-2b6f-7290ca546848.png)](http://sunstripe.main.jp/)
http://sunstripe.main.jp/

(月１ WEBコンテンツをリリースして便利な世の中を作っていくぞ！！ボランティアプログラマー/デザイナー/イラストレーター/その他クリエイター声優募集中!!)

緩募


### 地域情報 THEメディア
THE メディア 地域活性化をテーマに様々なリリース情報も含め、記事をお届けしてます！！
https://the.themedia.jp/

### ゼロからはじめる演劇ワークショップ
多様化の時代に向けて他者理解を鍛える

https://workshop.themedia.jp/

### プログラミングワークショップ・ウェブ塾の開講！！！
様々なテーマでプログラミングに囚われずに取り組んでいきます。
詳しくはこちら　↓　↓　↓　↓　↓　↓　↓　↓
[プログラミングサロン 月１だけのプログラミング学習塾](https://workshop.themedia.jp/posts/7057553?fbclid=IwAR32CfRQ7RvDOhvuogoSwqxDLMOU7Jvuzljlnx-TMc27qBPX1BnWsfLcBR8
)

### 協力応援 / 支援者の集い
## チーム：サンストライプ
https://twitter.com/sunstripe2011

#### プログラミングラボ
https://twitter.com/PLab2020

一緒にポートフォリオを作りませんか？現場の体験やそれぞれの立場から年齢関係なく作品を作りたい方々と一緒にチームを作って、作品を作っています。現場に行きたい人には、職場紹介や職場の体験や悩み相談なども受けております。
様々な職種からプログラミングの知識を得たい、デザインの知識を得たい、データーベースの知識を得たいという人が集まっております。
週１のミーティングにそれぞれの近況と作業報告して、たまにリモート飲み会などをしております！！

興味がある方は、DMに話しかけてみてください。

#### トラストヒューマン
http://trusthuman.co.jp/
私たちは何よりも信頼､人と考えてます｡

｢コンサルティング｣と｢クリエイティブ｣の両角度から｢人材戦略パートナー｣としてトータル的にサポートします！！

### キャリア教育事業

#### 青空プログラミング
[![青空プログラミング100px.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/603d53ab-828b-645e-a415-1b6f158d7356.png)](https://actcoin.jp/project/detail.php?id=600)

[![ダウンロード (9).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/9bde9318-28c2-ce74-d4c5-326168061bcc.jpeg)](https://www.youtube.com/hashtag/%E9%9D%92%E7%A9%BA%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)

#### 広域学習支援プラットフォーム『のびのび日和』
https://slc-lab.amebaownd.com/

#スポンサー募集

## ネリム
https://nerim.co.jp/
配信事業などを映像コンテンツなどの制作しております

## ビヨンドXプロジェクト

[ビヨンドXプロジェクト全体会議](https://www.youtube.com/playlist?list=PLaR6-YWiGWkYhEHWnt8f1z-JC0g3nwwC9)
MySQLの基本CREATE DATABASEでデータベース作成

![hosting-g92cf767da_1280.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530779/4477770f-b3ff-091b-c169-7da38144cb4b.png)
ハッカソンでバックエンドも一部担当し若干FastAPIを触ってみました。
DB周りは他の方がやってくれていたのでほぼ触っていないのですが、バックエンドやるからには必須スキルなのでなんとか身につけたいと思います。

## まずはSQLのお約束
* 慣習としてコマンドは`CREATE DATABASE`のように大文字で記述します。（コマンド打つ時は小文字で打ったりしますが）
* データベース名、テーブル名、カラム名などコマンド以外の部分は`this_is_database`のようにスネークケースで記述します。
* SQL文の末尾は`CREATE DATABASE this_is_database;`のように基本的に`;`となります。

## コマンドCREATE DATABASEとは
読んで字のごとくデータベースを作成するコマンドです。
[Envader](https://envader.plus/)の仮想環境でコマンドを打ちながら学んでいきます。

```sql
CREATE DATABASE this_is_database;
```
これでデータベースが作成されます。


:::note warn
すでに存在するデータベース名で作成しようとするとエラーが出るので、`IF NOT EXISTS`と記述すればエラーを回避できます。
:::

```sql
CREATE DATABASE IF NOT EXISTS this_is_database;
```


実際にDBが作成されたかを見るには`SHOW DATABASES;`です。

```sql
SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| food_app           |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| this_is_database   |
+--------------------+
6 rows in set (0.01 sec)
```
`this_is_database`が作成されていることを確認できました。

### 文字コードを指定する
デフォルトでは`utf8`となっていますので必要に応じて変更します。
```sql
CREATE DATABASE DB名 CHARACTER SET 文字コード;
```

### 照合順序を指定する
デフォルトで`utf8_general_ci`となっています。ソート順を指定する場合に指定します。
```sql
CREATE DATABASE DB名 COLLATE 照合順序;
```

### 文字コードと照合順序をまとめて指定することもできます
照合順序と文字コードはセットで扱います。異なる文字セットを指定するとエラーが出ます。

```sql
CREATE DATABASE DB名 CHARACTER SET 文字セット COLLATE 照合順序;
```

### DB作成時にwarningが出てしまったら

`SHOW WARNINGS;`コマンドを入力することで詳細を表示できます。
コードなどを元にググって対処方法を見つけましょう。

```sql
# 例
mysql> CREATE DATABASE IF NOT EXISTS my_sample_list;
Query OK, 1 row affected, 1 warning (0.01 sec)

mysql> SHOW WARNINGS;
+-------+------+---------------------------------------------------------+
| Level | Code | Message                                                 |
+-------+------+---------------------------------------------------------+
| Note  | 1007 | Can't create database 'my_sample_list'; database exists |
+-------+------+---------------------------------------------------------+
1 row in set (0.00 sec)

```

:::note warn
Can't create database 'my_sample_list'; database exists
（my_sample_listというデータベースが既に存在するのでデータベースを作成することができませんでした。）

同名でデータベース作成しようとしたときに出力するエラー文と同じものですが、`IF NOT EXISTS`と指定してDB作成コマンドを打ったため警告（warning）として出力されています。
DB名を別にして対処しましょう。
:::

コード引用：[データベースの作成](https://envader.plus/course/2/scenario/1043/ex)

## 学習のまとめ
だいたい[Envader](https://envader.plus/course)で触ってみてわからないところは検索して幾つか参考になるページを見つけて理解を深めるというやり方をやっています。
inputとOutputを並行してできるので自分の中ではかなり学習効果が高いと思っています。

## 参考にした記事
皆さんの知見のおかげでなんとか理解ができています。ありがとうございます。

https://qiita.com/knife0125/items/bb095a85d1a5d3c8f706

https://qiita.com/kazu56/items/6af85ffcf8d3954455ad

https://gihyo.jp/dev/serial/01/mysql-road-construction-news/0065

### これまでの学習
https://qiita.com/Terralien/items/a24d3b8aed0757388a7c

https://qiita.com/Terralien/items/a784e77edbb59217a2eb
[RxSwift]UITableViewCellで再利用時の購読が重なるのを防ぐ

## 前提
RxSwiftでは購読を解除するためにdisposeBagというものがあります。
片や、UITableViewやUICollectionViewのCellには再利用をする機能が実装してあります。
これらを無意識に実装しているとこんなコードになりがちです。

```swift
class hogeTableViewCell: UITableViewCell {    
    private var disposeBag = DisposeBag()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
    }
}
```

## ここで発生する問題点
上記のコードではcellの再利用で購読が重なる可能性が出てきてしまいます。
そのためには、再利用時に適切に購読を解除（破棄）してあげる必要があります。

そこで使用するメソッドが``func prepareForReuse()``です。
これはdequeueReusableCell(withIdentifier:)からオブジェクトを返す直前にこのメソッドを呼び出されるメソッドです。

https://developer.apple.com/documentation/uikit/uitableviewcell/1623223-prepareforreuse

> If a UITableViewCell object has a reuse identifier, the table view invokes this method just before returning the object from the UITableView method dequeueReusableCell(withIdentifier:). 

>To avoid potential performance issues, you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state.

func prepareForReuse()はパフォーマンスの観点から**コンテンツの内容に関係ない属性、例えばアルファ値、エディティングやセレクション状態などのみをリセットすべき**と書いてあります。
ですのでここでdisposeBagをセットしてあげることは今回の最適解と言えるでしょう。


## after
```swift
class hogeTableViewCell: UITableViewCell {    
    private var disposeBag = DisposeBag()

    override func prepareForReuse() {
        super.prepareForReuse()
        self.disposeBag = DisposeBag()
    }
}
```
vimのカーソル位置保持できない解決メモ

```:.vimrc
au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
```
これで前回ファイルを開いた位置にカーソルが移動するはずなのに、いつの間にか保持してくれない。
```
❯ ll ~/.viminfo
-rw------- 1 root root 12K  3月 13 21:57 /home/nakayama/.viminfo
```
`.viminfo`の所有がrootになってた。chownで変更して解決。
報告、質問をする際のポイント

※随時更新(たぶん・・・)
報告、連絡、相談、質問をする際に、自分が学んだこと、参考になるサイト等を記載していきます。

### 送信したメール等の報告に誤記を見つけ、メールを送り直す際のワンポイント
★報告に関する修正は、修正部分のみ送り直すのではなく、報告文を正しく書き直したもを送り直す
★報告文の修正箇所には「★」を付けたりして変更箇所を明示する
★送り直す時のメールの件名には【再】などをつける
　→・間違えた箇所の修正部分だけを送り直すと、見る人は2つのメールを見て文章全体を把握し直すという手間が、メールを見る人の人数文発生する
　　・件名に【再】と記載があり、報告全体がまるっと送られてくれば、見る人は件名を見るだけで前のメール(報告)は見なくて良いと分かる

**例**
間違えて送っちゃった！！(´;ω;｀)
```perl:件名：作業報告
本日の作業内容
　・ほげほげ画面の詳細設計書[40%]
　・ふがふがクラスの改修[100%]

残作業
　・ぴよぴよ画面改修
```


修正して送り直すぞ！！(｀・ω・´)
```perl:件名：【再】作業報告
申し訳ありません、先程報告内容を間違えて送信してしまいました。
下記が正しい報告になります。
修正箇所には「★」を付けてあります。

本日の作業内容
　・ぴよぴよ画面の詳細設計書[40%]　// ★
　・ふがふがクラスの改修[100%]

残作業
　・ぴよぴよ画面改修
```

### 参考になりそうなサイト等
https://qiita.com/seki_uk/items/4001423b3cd3db0dada7
【DAX】当期と前期のカテゴリ毎の売上金額とその差をDAXで

### FacebookでのDAX式に関する質問への回答を考えてみる
---
#### FacebookでのDAX式に関する質問
Facebook  ( Japan Power BI User Group ) 2022/03/18
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2233310/a12de80b-1633-ecbc-63f6-7947d82e11c5.png)

---
#### 自分なりの回答
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2233310/a8254a20-1f7a-f5c7-1bce-b6c8240e6ca4.png)
##### 元データ　:　Adventure Works
---
### DAX式
```
Current Sales = 
   CALCULATE(SUM('Sales'[Sales Amount] ))
Previous Sales = 
   CALCULATE(SUM('Sales'[Sales Amount]),SAMEPERIODLASTYEAR(’Date'[Date]))
Sales Diff = 
   CALCULATE('Sales'[Current Sales] - 'Sales'[Previous Sales])
```
---
### 大事なこと
タイム インテリジェンス関数を使う時は、必ず日付テーブルが必要！！！
目的は何かをよく考えてみること
試験を行う際の注意点

※随時更新(たぶん・・・)

試験を行った際に、自分が学んだことを記載していきます。


### テストを行う時
★  **「そもそも、何のためにこの試験をするのか？」 = 「テストの目的」** を明確にしてから作業を行う
　→・作業の大枠を理解するため
　　・なぜその作業を行うかを理解していないと、試験項目書が間違えているのか、実装や仕様、試験結果が間違えているのかの判断がつかない
WPFのDataGridの行を取得する方法

# はじめに
初めまして、現在大学3年生でWindowsのアプリケーション開発を行なっております。

今回は WPF と呼ばれるWindowsアプリケーション用に使用するフレームワークで使用するC#の記事になります。
WPFを使用する際には、UIの作成にXAML、クリックイベントやバックエンドにC#と言語を分けて作成します。

**今回は、選択してる行を取得する方法を書いていきたいと思います。**

# 今回やりたいこと
DataGridから列を複数選択し、それぞれのデータを取得したいと考えています。

今回は以下のようなデータを使用したいと思います。
|ID  |店名    |前回の連絡日付|次回の連絡日付|担当者  |
|---|---|---|---|---  |
|1  |俺のリップクリーム    |2022-3-18|2022-3-22|山田太郎  |
|2  |俺のスマホ    |2022-3-18|2022-3-22|高橋花子|
|3 |俺の天津飯    |2022-3-18|2022-3-23|ああ二郎 |
|4  |俺のチャオズ  |2022-3-18|2022-3-23|ああ二郎  |

取得した上でtextboxに取得したものを代入するプログラムを作る設定でプログラムを書いていきます。

複数行取得した際には、「,(カンマ)」で続けて書きたいと思います。
# DataGeidの行を取得する方法

### 今回使用する上で必要なデータの型
DataGridのColumn名が入ったリストを使用します。

今回は以下の情報が入ったリストです。
|ID  |店名    |前回の連絡日付|次回の連絡日付|担当者 |
|---|---|---|---|---  |

```C#: MainWindow.xaml.cs
private List<string> Column_list = new List<string>();
```

### Xamlの情報
今回のXamlには、DataGridとID, 店名、前回の連絡日付、次回の連絡日付、担当者のTextBoxがあるとします。

```XAML: MainWindow.xaml
<DataGrid/>
<TextBox x:Name="ID_textbox"/>
<TextBox x:Name="Shop_textbox"/>
<TextBox x:Name="pre_day_textbox"/>
<TextBox x:Name="post_day_textbox"/>
<TextBox x:Name="manager"/>
```

### 取得する方法
foreachを利用して、一行一行選択した項目の中身を確認します。
```C#: MainWindow.xaml.cs
foreach (var row in this.datagrid.SelectedItems)
```

現在選択している行のうち、header_strと同じ列を取得します。
この時、行を取得する方法として**DataRowView**を使用します。
```C#: MainWindow.xaml.cs
var row_data = (row as DataRowView)[header_str];
```

```C#: MainWindow.xaml.cs
private void row_get()
{
   string[] row_list = [Column_list.Count()]
   foreach (var row in this.datagrid.SelectedItems)
   {
      int i = 0;
      int j = 0;
      foreach (string column in Column_list)
      {
         if(j!= 0)
            row_list[i] += ", ";        
         var row_data = (row as DataRowView)[header_str];
         row_list[i] += row_data.ToString();
         i++;
      }
      j++;
   }
   this.ID_textbox.Text = row_data[0];
   this.Shop_textbox.Text = row_data[1];
   this.pre_day_textbox.Text = row_data[2];
   this.post_day_textbox.Text = row_data[3];
   this.manager_textbox.Text = row_data[4];
}
```


### プログラム結果
例えば、DataGridの一行目、二行目を選択すると、textboxの中身は以下のようになります。
```
ID	　　　　　 1, 2
店名	　　　　　 俺のリップクリーム, 俺のスマホ
前回の連絡日付　2022-3-18, 2022-3-18
次回の連絡日付　2022-3-22, 2022-3-22
担当者　　　　　山田太郎, 高橋花子
```
SuperJSONでNext.js 12以降のgetServerSidePropsやgetStaticPropsをスマートに書く

## Next.jsの`getServerSideProps`や`getStaticProps`とJSON

Next.jsでSSRやSSRをする際に使う`getServerSideProps`や`getStaticProps`では、戻り値をJSONでシリアライズ可能な型に制限しなくてはならない制約があります。例えばデータベースから取得したデータがDate型を含む場合はエラーになってしまいます。

- `getStaticProps`でMongoDBデータベースから取得したデータが`Date`型の値を含む場合:

```ts
export const getStaticProps:GetStaticProps = async (ctx) => {
  const client = await new MongoClient("mongodb://127.0.0.1:27017");
  await client.connect();
  const db = client.db("DATABASE");
  const col = db.collection("COLLECTION");
  const posts = await col.find({}).toArray(); #created_atなどDate型を含んでいるとする 
  return {
    props:{
      posts
    }
  }
}
```

エラー

```js
Server Error
Error: Error serializing `.data[0].date` returned from `getStaticProps` in "/".
Reason: `object` ("[object Date]") cannot be serialized as JSON. Please only return JSON serializable data types.
This error happened while generating the page. Any console logs will be displayed in the terminal window.
```

- `undefined`を含む場合:

コード

```ts
export const getStaticProps:GetStaticProps = async (ctx) => {
  return {
    props:{
      data: undefined
    }
  }
}
```

エラー

```sh
Server Error
Error: Error serializing `.data` returned from `getStaticProps` in "/".
Reason: `undefined` cannot be serialized as JSON. Please use `null` or omit this value.
This error happened while generating the page. Any console logs will be displayed in the terminal window.
```

これを回避するためには、Date型をString型に変換するなど、JSONとしてシリアライズ可能な形式に変換する必要がありますが、毎回変換処理を書くのは面倒です。

こんなときに便利なライブラリが[SuperJSON](https://github.com/blitz-js/superjson)です。SuperJSONとNext.js用のBabelプラグインを使えば明示的な変換なしに`getServerSideProps`や`getStaticProps`でJSON範囲外のDate型などが扱えます。

- [blitz-js/superjson](https://github.com/blitz-js/superjson) 
- [blitz-js/babel-plugin-superjson-next](https://github.com/blitz-js/babel-plugin-superjson-next): Next.jsで特別な記述なしにSuperJSONを使うためのbabel plugin

## Next.js 12以降でのSuperJSON

しかしながらNext.js 12では標準のトランスパイラがBabelからSWCに変更され、[blitz-js/babel-plugin-superjson-next](https://github.com/blitz-js/babel-plugin-superjson-next)が標準では使えなくなりました。

SWC以降のNext.jsでもこれまでと同じようにSuperJSONを使えるようにしたのが、2021年12月に登場した[remorses/next-superjson](https://github.com/remorses/next-superjson)です。

### インストール

```sh
npm install superjson (未インストールの人)
npm install next-superjson
```

### 設定

`next.config.js`に`next-superjson`用の設定を追加します。

```js
const { withSuperjson } = require('next-superjson')

module.exports = withSuperjson()({
  reactStrictMode: true,
})
```

### アプリ側の処理

特に何も記述する必要はありません。SuperJSONを使わない場合はシリアライズが必要ですが自動でシリアライズしてくれます。

## 注意

- SuperJSONがSWC対応してくれるのが望ましいですが、未対応のためワークアラウンドとして使っています。将来SuperJSONがSWCに対応したらそちらに移行しましょう。
- 楽だからといってデータベースから取得したデータをNext.jsにそのまま投げるのはやめましょう。
VSCodeのMarkdownPreviewEnhancedでOctave-cliを使った図を埋め込もうとした

# 動機

markdownにoctaveで作った簡単な図を突っ込みたくて、どうせならコードも1つのmdファイルで管理したかったのでやってみた。結局直接埋め込めてはいないけど、個人的には今の状態のほうが使い勝手がよく満足。
もっといい方法があるかもしれないけど、とりあえずメモ。

# 動作環境

windows10 home
VSCode 1.65.2
Markdown Preview Enhanced v0.6.2
GNU octave-6.4.0-w64
# 準備

## octave-cliの準備

octaveを公式サイトからダウンロードしてインストール。
octave-cli.exeのある場所をユーザー環境変数のPathに追加。多分下記のあたりにある。
`C:\Program Files\GNU Octave\Octave-6.4.0\mingw64\bin`
コマンドプロンプト等で`octave-cli`と叩いてoctave-cliが起動することをチェック。

## vscodeの準備

vscodeを公式サイトからダウンロードしてインストール。拡張機能でMarkdownPreviewEnhancedをインストール。

# グラフを埋め込む

## やり方
MarkdownPreviewEnhancedでは、pythonとかgnuplotとかならダイレクトに図を埋め込めるけど、octaveではそれができなかった。
なので、画像をいったん保存し、改めてその画像を読むことにした。
こんな感じに書く。

    ``` matlab {cmd=octave-cli output="html" hide=true}
    figure;
    plot3(1, 3, -2, 'o')
    axis([-3 3, -3, 3, -3, 3], 'equal')
    grid on;
    xlabel('x')
    ylabel('y')
    zlabel('z')
    saveas(gcf, 'fig01.png')
    ```
    <img src=fig01.png width=400> 

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1327569/8239b17e-20fd-ba9d-dc93-0203040a2595.png width=400>

(言語の名前はmatlabを指定すると、matlabのシンタックスで色がつくのでうれしい。`hide=true`にすると見えなくなるけど、とりあえずそれを切っておくと書いているときにミスに気付きやすくなる)

コードを実行したあとは、`ctrl` + `k` -> `v`などでプレビューを更新することで、画像を読み込みなおせる。

## 注意点

octave-cliのファイルの文字コードの問題があって、pathなどに日本語があるとうまくいかないことがある。
日本語は使わないようにするのが無難。

# 感想

便利。matlabに慣れているため、octaveで図をかけるのがうれしい。
MySQLのDockerコンテナbuildで発生するGPGエラーの解消

## はじめに
AWSのCodeBuildで突然エラーが発生するようになった。
エラー文は下記
```
 GPG error: http://repo.mysql.com/apt/debian buster InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 467B942D3A79BD29
```
調べてみるとこの鍵は有効期限が2022年2月16日までだったそうで、新しい鍵に切り替えられたらしい。
古い鍵ではアップデートが出来なくなったようだ。だったら、新しい鍵をインポートしちゃえばいいってことでした。

### 修正内容
調べてみると新しい鍵をインポートするコマンドはこちら
```
sudo rpm –import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022
```
これで解決！と思ったがこちらをDockerコンテナに対して実行する方法がわからなかった。

rpmコマンドはDockerfileでは使えなさそう。。。
※使える方法をご存知の方は教えていただけると幸いです

さらに調べて行くと下記コマンドがヒット
```
RUN apt-key adv --keyserver pgp.mit.edu --recv-keys 467B942D3A79BD29
```

こちらを該当Dockerfileに追記したら、CodeBuildが通るようになりました。

### 最後に
GPGのエラーを修正するだけなら、MySQLのバージョンを最新版にすれば解決できましたが、CodeBuildで別のエラーが発生したので現在はそちらを調査中。

知見ある方いましたらコメントいただけると幸いです。
【SwiftUI】PickerのBindingに設定した値が変更されない

# 何があったのか？
SwiftUIでPicker実装時にBindingに設定した値がPickerの値を変更しても変わらない事象が発生

# 解決策
#### tagをつける
以下のコードのようにPickerに表示する内容に対して、**.tag()** をつけ、引数にはどのIndexのものかを入れることで、Picker変更時にBindingに設定した値が変更されるようになるみたいです。

```swift
struct ContentView: View {
   @State var selectedIndex: Int
   var testArray = ["test1","test2","test3"]

   var body: some View {
      Picker(selection: $selectedIndex) {
         ForEach(0..<testArray.count) { index in
            Text(testArray[index]).tag(index)
         }
      } label: {
         EmptyView()
      }
   }
}
```

# 参考
https://stackoverflow.com/questions/57305372/why-does-binding-to-the-picker-not-work-anymore-in-swiftui
VBEの初期設定をいじる

### はじめに
ExcelのVBE（VBAを書くとこ）を以下のようにするやり方についてメモしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2536951/60010f93-1b89-f11e-68de-ef80c64357c4.png)

いいところ
- ダークモードっぽくできる
- 予約語を見やすく色付できる
- VBEとExcelの行き来がしやすい
- コメントアウトしやすい

### ダークモードっぽくするには
まず、VBEを開きます。そして、ツールタブのオプションより、エディターの設定から、色を変更できます。当然、色は何でもいいです。ただ、重複を避けたり見やすい色を選ぶことが重要です。背景を黒にすることで、ダークモードっぽくすることが可能です。

### VBEとExcelの行き来
これは Alt + F11 で可能です。最終的にはこれを覚えるのが一番と思います。ただ、僕はクイックアクセスツールバーに余裕があったので、Alt + 1 にVBEを置いています。そして、VBE上でも、Excelへの移動をAlt + 1 に設定しています。以下のように変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2536951/96c8c0ec-eb06-19ab-717e-b3a48c21f4a3.png)

また、同様にしてコメントアウトにもキーを割り振ります。コメントアウトは最初の状態ではツールバーにありません。出しておくといいかもです。

### その他設定
- 自動構文チェック を外す
- 変数の宣言を強制する
- フォントを変更する
- AutoHotKeyを利用することで、( と打つと右括弧も自動で記述し、さらに括弧の間にカーソルを移動させる。" も同様にする。

私は、以下の記事を参考にMyricaなるフリーフォントを利用しています。

https://hatena19.com/recommended-option-setting-of-vbe/

また、AutoHotKeyの処理はこちら
```
#IfWinActive ahk_class wndclass_desked_gsk 
; VBE には以下の処理を適用する
+8::
Send, ()
Send, {Left}
Return

+2::
Send, ""
Send, {Left}
Return

#IfWinActive
```

### ショートカットキー
よく使うやつ。

- F5：実行
- Alt → I → M：モジュール追加
- コメントアウト / コメントアウト解除（キーは任意）
- F8：一行ずつ実行
- ctrl + F8：カーソル業の前まで実行
- ctrl + Tab：予測候補を表示

### VBAを勉強する
youtuber

https://www.youtube.com/user/officetanaka

https://www.youtube.com/channel/UCc1sntWEyGXMhH0fXI5mMiQ

website

https://excel-ubara.com/

http://officetanaka.net/excel/vba/
zshのエイリアスにオプション(可変)を引き渡したい

## やりたかったこと

該当ディレクトリに遷移し、以下3つのコマンドをエイリアスに登録したかった。

```
cargo run -- -t [token]
cargo run -- -t [token] -b
cargo run -- -t [token] -d mm/dd
```

## 解決方法

以下を`.zshrc`に登録。(エイリアス名は`vacation`です)

```zsh
alias vacation='(){pushd ~/path/to/script;cargo run -- -t [token] $1 $2;popd}'
```

予め渡されるかもしれない引数の個数を宣言しておけばそのまま使えました。
変数をひとつしか用意していないと`vacation "-d mm/dd"`のように文字列であることを明記しないといけず、面倒ですが一応動きます。

これで以下3つどれでも動くようになりました。

```
vacation
vacation -b
vacation -d mm/dd
```

## ちなみに

以下自作したslackアプリで上記を使いたかったのがモチベーションでした。
トークンを発行して、上記エイリアス登録すると、以下ができます。

- `vacation` でslackの表示名の末尾に`(mm/dd休)`を付与する(翌日)
- `vacation -b`でslackの表示名の末尾の`(mm/dd休)`を消す
- `vacation -d mm/dd` でslackの表示名の末尾に`(mm/dd休)`を付与する(指定日)

https://github.com/okaponta/slack-vacation
plotly dashでサイドバーを作る

# 目的
plotly dashでw3cssを使ってサイドバーを作ります。

# Gif
![edf6df9b-5513-4aee-99b1-ac7895d2cebb.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130763/79da9bd1-4ab0-6f70-1c28-a68903df2599.gif)

# コード
## 1. import
```python
from dash import dcc, html, Input, Output, callback
```
## 2. Dashアプリの作成
以下のコードで**w3css**をDashで使えるようにします。
```python
w3_css = "https://www.w3schools.com/w3css/4/w3.css"
app = Dash(__name__, external_stylesheets=[w3_css])
```

## 3. サイドバーの作成
- `className="w3-sidebar w3-bar-block"`でサイドバーを作成
- `style={"width": "25%", "background-color": "#EEEEEE"}`で幅と背景色の指定
```python
sidebar = html.Div([html.H3("sidebar")],
                   hidden=True, id="sidebar", className="w3-sidebar w3-bar-block",
                   style={"width": "25%", "background-color": "#EEEEEE"})
```

## 4. メインコンテンツの作成
- `html.Button("sidebar", id="sidebar button")`でボタンの作成
- `style={"margin-left": "0%"}`で右にどれだけずれるのかを指定
```python
main = html.Div([
    html.H3("main"),
    html.Button("sidebar", id="sidebar button")
], id="main", style={"margin-left": "0%"})
```

## 4. レイアウトの作成
サイドバーを上にしてください。
```python
app.layout = html.Div([
    sidebar,
    main
])
```

## 5. コールバックの作成
```python
@callback(Output("sidebar", "hidden"),
          Output("main", "style"),
          Input("sidebar button", "n_clicks"),
          State("sidebar", "hidden"))
def sidebar(n_clicks, hidden):
    # サイドバーボタンがクリックされた場合
    # サイドバーが表示されていたら閉じる
    # 閉じていたらサイドバーを開く
    if n_clicks
        hidden = not hidden
    # サイドバーを表示させるときに`margin-left`を25%に
    # 閉じるときに0%にする
    style = {"margin-left": "0%" if hidden else "25%"}
    return hidden, style
```

## 6.アプリに実行
```
app.run_server(debug=True)
```