OmniAICreator/Qiita-1.07M huggingface dataset:
【人工生命】オープンエンド性の良記事あったのでまとめてみる

# はじめに
趣味で、「人工生命(コンピュータ上に生命をシミュレートしようという分野)」の勉強を進めているのだが、
「オープンエンド性」というのが研究のキーになっていることを知った。
そしてそのオープンエンド性についてまとめられている良記事をA先生から教えてもらったので読んでみた。
今回はそのまとめである。

### 元記事
**Open-endedness: The last grand challenge you’ve never heard of**
https://www.oreilly.com/radar/open-endedness-the-last-grand-challenge-youve-never-heard-of/

# 超要約
※自分の琴線に触れた部分を中心に端折る+意訳です。

### イントロ

Open-endedness (オープンエンド性)の理解は、人類未踏の大いなる謎である。
(David Hilbert’sの23の未解決問題にもリストアップされている。)

オープンエンド性とは、「終わりなき進化」を起こしている状態のことをいう、
「生命の進化」がその例だ。
生命は多様に進化しており、その進化には終わりはなくいまだに進化を続けている。

進化的アルゴリズムは進化を模倣した探索プログラムだが、大抵が短い期間で
解へと収束してしまい、多様性をもった進化は続かない。
逆に、多様性を生じることにフォーカスしたプログラムは、個体種が四散してしまい
新たな種などが生まれない状況になる。

もしオープンエンド性の鍵を、見つけることができれば、それは様々な想像的な分野で応用できる。
例えば、新しい校舎のデザインや、車のデザイン、コンピュータアルゴリズムの探索などだ。
今までにない、創造的なデザインを産む可能性があり、これは生命の多様性複雑性を考えると夢物語ではない。


### オープンエンド性の歴史
Alife(人工生命)という、コンピュータ上に、生命的な世界をシミュレートしようという試みがある。
例えば、

- Tierra  (by Thomas Ray)
- Avida ( by Charles Ofria, Chris Adami, and Titus Brown)
- Polyworld (by Larry Yaeger)
- Geb (by Alastair Channon)
- Division Blocks (by Lee Spector, Jon Klein, and Mark Feinstein)
- Ecosphere (by Thomas Miconi and Alastair Shannon)

ただ、どれも無限の多様な進化を内包できていない。
また、実世界のごく一部を切り取ってシミュレートしようとしているものになっている。(これが興味を皆が分けてない理由と作者は指摘)

オープンエンド性に焦点を当てた、
"activity statistic”という指標もMark Bedau(1992)によって示された。
(Gebはactivity statisticをpassしてるらしい。)
ただまだまだ現実世界のオープンエンド性には程遠い。

その後、Novelty Search Algorithm (by Stanley and Lehman)が考案された。
これは従来の進化的アルゴリズムと違って「良いもの」を選択していくのではなく
「Novelty(新しいもの)」を選択していくアルゴリズム

また、Noveltyと目的関数のバランスをとるアルゴリズムも考案された
 quality diversity (QD) algorithmsと呼ばれるものだ。
(novelty search with local competition(NSLC)やthe multi-dimensional archive of phenotypic elites(MAP-Elites)など)

さらに、共進化(個体と環境が相互に干渉し合い進化していくこと)を盛り込むことも研究されている。
また、ニューラルネット周りだとGANsも共進化的な振る舞いを見せている。

### オープンエンド生の必要条件
オープンエンド性の条件がわかれば、アルゴリズムに組み込むことができる。
Soros and Stanleyは2014にオープンエンド性の条件を下記と提案した。

1 何らかの小さな基準(Minimal Criterion = MC)を満たすと個体が繁殖できる系であること
2 個体の進化が、新しいMC(=繁殖)の機会をもたらすこと
3 世界へどのように干渉するかは個個体ごとで決められること
4 個体の表現型の複雑性は無限であること

ただこの定義はまだ曖昧である。

### オープンエンドの実用性
想像的なデザイン、音楽やアートの分野で活躍しそう。AIとも関わりが深い。

**さあみんなで、「オープンエンド」の冒険(研究)をはじめよう！！**


# 感想
オープンエンド性の「終わりなき進化」にワクワクした。
今回の資料は歴史などがざっくりまとまっていてよかった。
特に、Gebなどは興味がわいたので中身をみてみたい。
また、自身は単純にオープンエンド性に興味がでている勢だが、
「新しいデザイン」へのアルゴリズム展開などオープンエンド性の実用性を説いているのが新鮮な視点だった。

**さあみんなで、「オープンエンド」の冒険(研究)をはじめよう！！**
【Django】mysqlclientでMySQLのDBへ接続する

# 目的
DjangoからMySQLのDBに接続できるようにします。

# 環境
Python：3.8
Django：3.1.5
MySQL： Ver 8.0.21 for Win64 on x86_64

今回はPipenvで構築した仮想環境で行います。

#環境構築
・pythonのインストールとDjangoアプリケーションの作成をします。

```console
$ pipenv --python 3.8                          # pythonインストール
$ pipenv shell                                 # 仮想環境へ入る
$ pipenv install django                        # Djangoインストール
$ pipenv install mysqlclient                   # ドライバをインストール
$ django-admin startproject <プロジェクト名>     # Djangoのプロジェクトを作成
$ cd <プロジェクト名>                            # Djangoプロジェクトのmanage.pyがある階層に移動
$ python manage.py startapp <アプリケーション名>  # Djangoのプロジェクトを作成
```

・MySQLに接続し、データベースを作成します。

```
mysql> create database <テーブル名>;
```


# DjangoへDB情報を登録
Djangoプロジェクトの`settings.py`にある`DATABASES`の設定を変更します。

```python
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': '<作成したMySQLのDB名>',
        'USER': 'root',                        # MySQLのユーザ名
        'PASSWORD': '<MySQLのパスワード>',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}
```

# 接続確認
Djangoアプリケーションの`manage.py`がある階層で下記コマンドを実行します。

```console
$ python manage.py dbshell
```

これでDjangoに設定したmysqlのDBに接続できます。
最後に念のため接続しているDBが正しいか確認して終わります。

```console
mysql> SELECT database();  # 接続されているDBが表示されます。
```

以上で環境の構築から設定、確認までを行えました。
resolv.confをもう一度調べてみた

## 勉強前イメージ

基本的には名前解決をするためにDNSサーバ指定するくらいしか使ってない...

## 調査

### resolv.conf とは

リゾルバの設定ファイルです。
DNSにおいて、名前解決を必要とする場合に通常リゾルバを介して名前解決を行う。
レゾルバは1つ以上のDNSサーバを知っている。

### よくある設定

下記はlocalのサーバの設定になります。
`nameserver` としてネームサーバが記載されています。

```text:/etc/resolv.conf
# Generated by NetworkManager
nameserver 192.168.1.1
```

### resolv.conf に書く内容

自サーバが使用するDNSサーバの情報を書く箇所になります。

- nameserver : DNSサーバのIPアドレス
- domain : ドメイン名
- search : 検索リスト

#### nameserver : DNSサーバのIPアドレス

下記のように記載します。
`nameserver` は最低でも書いておかないと名前解決ができないので、yum update等も実行できません。
名前解決が必要になった場合、上から順に問い合わせを行います。
こちらはいくつでも設定できるわけではなく、3台まで指定可能です。

```
nameserver 192.168.1.1
nameserver 192.168.1.2
nameserver 192.168.1.3
```

#### domain : ドメイン名

こちらは、自分が所属しているドメイン名を指定します。
記載しておくと名前解決の際にドメイン名を加えて解決を行います。
例えば、 `www` の名前解決の際に、 example.com を加えて `www.example.com.` で名前解決をしようとします。

下記のように記載します。

```
domain example.com.
```

#### search : 検索リスト

search は domeinを複数指定する際に使用します。
こちらも名前解決の際にドメイン名を加えて解決を行い、
一番左であれば、`www` の名前解決の際に、 aaa.example.com を加えて `aaa.www.example.com.` で名前解決をしようとします。
解決できないのであれば、 その左の test.example.com で名前解決を行います。
こちらは6つまで指定することができます。

```
domain aaa.example.com. test.example.com. example.com.
```

## 勉強後イメージ

ほぼlocalだったら基本的なことしか書いてなかった。
オプションとかもあるみたい。
なんとなくnameserverは3つまでしか書けないのかなって思ってたけど、やっぱりそうだったのか。


## 参考

- [resolv.confの設定について](https://www.bigbang.mydns.jp/resolv-x.htm)
- [Linuxのリゾルバとは何か？（/etc/resolv.conf ）](https://hombre-nuevo.com/linux/network0003/)
- [RESOLV.CONF](https://linuxjm.osdn.jp/html/LDP_man-pages/man5/resolv.conf.5.html)
- [resolv.conf - ファイルのフォーマットと規約の説明 - Linux コマンド集 一覧表](https://kazmax.zpp.jp/cmd/r/resolv.conf.5.html)
[2021Jan] Zabbix Frontend の消費メモリ量をミニマイズしたい

# はじめに

とあるホストに間借りして Zabbix を設置しようとしたとき、そんなにリッチなリソースが利用可能だったわけでなく、なるべく消費メモリ量を削減する必要がありました。
それと、そういえば nginx で php 動かしたこと無いなーということで、それも試してみたくなりました。

というわけで、各 HTTP Server で Zabbix Frontend を動作させたときの消費メモリ量を調べました。

そして今更 nginx には CGI 機能が無いということに驚愕してみたり。


# 諸元

## 利用したモジュール

|項目|内容|
|---|---|
|OS|CentOS 7.9.2009 x86_64|
|Zabbix|MIRACLE ZBX 5.0.8-3|
|PHP7|remi 7.3.26-1|
|apache|2.4.6-97|
|nginx|epel 1.16.1-3|
|lighttpd|epel 1.4.54-1|

SCL の rh-php には apache 用のモジュールが入っていません。libphp7.so という名前のファイルは入ってますが、これは configure スイッチの --enable-embed で生成されるファイルであって apache で使えません。

SCL の rpm ってモジュール構成とかビルド設定に互換性が無くて使いづらかったりしますよねぇ。あと approve されないままだったり。複数バージョンが共存できるようになっている点は助かりますが。


## php 実行環境

|項目|内容|
|---|---|
|apache|php7_module (libphp7.so)|
|nginx|php-fpm (UNIX Socket)|
|lighttpd|php-cgi|


## 計測方法など

- 起動して、しばらく操作して、ちょっと落ち着いたところで平均を算出
- １人で操作、ブラウザからの接続も１つ
- 30sec 間隔で監視、もちろん Zabbix で
- PSS の値


# 結果

単位は MiB です。

|項目|合計|http server|php|
|---|--:|--:|--:|
|apache|118.87|n/a|n/a|
|nginx|64.37|3.36|61.01|
|lighttpd|24.57|1.93|22.64|

参考まで、php-fpm と組み合わせた場合の apache は 5MiB くらいでした。

ということで lighttpd が最小です。

むかし、Intel NUC で Zabbix Server + Agent + Frontend を１１セット動かして１日稼動させる、というお仕事をしていましたが、そこで利用していたのも lighttpd でした。もっとも、その時点では nginx を好きじゃなかったので non apache と言えば lighttpd の一択だったわけですけど。Docker じゃなくて lxc しかもシステムコンテナでしたし。


# そもそも

Frontend を止めてしまっても Zabbix の監視は止まらないので、不要な時は止めておくのが良いですね。

もっと言えば、リモートで DB に繋げられるならローカル（ブラウザを開いている手元のホスト）で動かすのが正解って気もします。


# おわりに

lighttpd は奇跡的にメンテが続いてます。ありがたい。ありがとうございます。もうしばらく lighttpd 使っていこうと思います。

nginx は HTTP Reverse Proxy には便利ですが、FastCGI 環境とか、使いづらいユースケースもありますねぇ。Docker だと monit とか併用するんでしょうか。それはそれで面白いけど。
プログラミング初学者メモ(1)　n進法について

#この記事について
プログラミング学習の基礎づくりのため、基本情報技術者の参考書で学習したことを記録しています。
今回は、n進法についてまとめました。コンピュータでの利用を前提としているため、2進法を例としています。

##1.目次

1.目次
2.基本用語
3.加法と減法
4.シフト演算
5.乗法と除法
6.小数点を含む表現
7.誤差

##2.基本用語
###ビット(bit)
　2進法における1桁分の情報。8進法なら3bit、16進法なら4bitを1桁で表すことができる。
###基数
「基本となる数」の略で、n進法におけるnを指す。
###桁の重み
n進法におけるそれぞれの位を指す。桁が1つ変わるごとに、nを累乗していった数値となる。
2進法であれば、2,4,8,16,32,64,128,256,...というように桁の重みが変わっていく。
###基数変換
すでにある進法で表記されている数値を別の進法に置き換えることをいう。
「桁の重み」で求める方法と、「整数部は乗法」「小数部は除法」で求める方法がある。


##3.加法と減法
###加法
繰り上がりのタイミングが異なるだけで、基本は10進法の時と同じ。
2進法であれば、1＋1の時点で繰り上がる。

###減法
コンピュータには加法の概念しかないため、負の数を加えることによって減法を表す。
最も単純に負の数を表す方法としては、

先頭の1bitを正負の符号とする。
残りのbitを全て反転(0と1)を入れ替える
1を加える

といった手順を踏む(2の補数表現)ものがある。


##4.シフト演算
bit列を左右にずらす操作をシフト演算という。
###論理シフト
符号を考慮せずにシフトする。
シフト後の空白には0を補うことで、元の数を2^nあるいは1/2^n倍した数を表せる。
1がはみ出した時、はみ出した方向が
左ならオーバーフロー(表せる範囲外)、右なら剰余となる。

###算術シフト
符号を考慮し、先頭1bitを固定してシフトする。
シフト後の空白を補う際に
左にシフトする場合は0を補い、
右にシフトする場合は符号bitで補う。

##5.乗法と除法
基本的に上述のシフト演算を利用して計算される。

###乗法
乗数を2^n同士の加法に置き換えてから計算する。
例えば、
2*7　 
= 2*(2^2+2^1+2^0)
= 2*2^2 + 2*2^1 + 2
あとは、シフト演算を用いれば計算できる。

###除法
除法は、「いくつに分けられるか」という計算だが、
見方を変えて、「何回引くことができるか」と考えることで減法として計算する。

例えば、
15 / 3 なら、
1111 - 11　　　 まず2進法にする
1111 - 1100 　 ＊計算結果が負にならない範囲で、除数を左シフトしてから引く
11   - 11　　　 ＊繰り返し
元の数値から引けた回数は、
2^2 + 2^0 = 4 + 1
          = 5
よって、商は5だとわかる。

##6.小数点を含む表現

###固定小数点数
「bit列のどの位置に小数点があるか」をあらかじめ決めておく方式。
小数点より上の位を「整数部」、下の位を「小数部」という。

###浮動小数点数
± m × n^e
このように、指数表記を用いて表す。
bit列では
±(符号) | e(指数部) | m(仮数部) |
という形式で表される。
また、仮数部で有効な桁を多く表せるように小数点を移動することを「正規化」という。

##7.誤差
実際の数値と、コンピュータで表すことのできる数値のズレを指す。

###けたあふれ誤差
コンピュータで表せる最小値や最大値を超えてしまった時に生じる誤差。
最小値を下回ることをアンダーフロー
最大値を上回ることをオーバーフローという。

###情報落ち
絶対値が大きく異なる数の加減法を行ったあと、
正規化により小さな数の部分が有効桁数からはみ出し、無かったことにされる。

###けた落ち
絶対値がほぼ等しい数の加減法を行った際に、
有効桁数が減り、信用できない桁数が増えてしまうこと。

###打ち切り誤差
完了まで待たずに計算処理を打ち切ることによって生じる誤差。

###丸め誤差
コンピュータが表現できる桁数を超えた際に、
超えた部分を四捨五入などして処理することにより生じる誤差。


#所感
拾う情報を増やしすぎてアウトプットの効率があまり良く無かったと感じる。
今後は、より覚えておきたいものに厳選して記述していくことにする。
devise_token_authを使おうとしたら依存関係でエラーが出た話

#はじめに
Rails6のAPIモードでdevise_token_authを使用してログイン機能をもつアプリを作ってみようと思ったところ、`bundle install`でエラーを吐いた。

#エラー内容
```
Bundler could not find compatible versions for gem "rails":
  In snapshot (Gemfile.lock):
    rails (= 6.1.1)

  In Gemfile:
    rails (~> 6.1.1) x86_64-darwin-20

devise_token_auth x86_64-darwin-20 was resolved to 0.1.21.alpha2, which
depends on
      rails (~> 4.1.4)

Running `bundle update` will rebuild your snapshot from scratch, using only
the gems in your Gemfile, which may resolve the conflict.
```

エラー文を読む感じrailsとdevise_token_authの依存関係が上手くいってないらしい。

調べたところ、devise_token_authはrails6.1より大きいとダメらしい。
参考：https://stackoverflow.com/questions/65865321/cant-install-devise-token-auth

>That seemed to do it. Seems like devise_token_auth v1.1.4 needs rails >= 4.2.0, < 6.1, so I just specified gem 'rails', '6.0'. 

#対処法
今回はRails6を使用できれば何でも良かったので、Railsのバージョンを6.0にすることで対応。

```Gemfile.
gem 'rails', '~> 6.0'
```

Gemfileのrailsを上記のように6.0に修正して`bundle update rails`をすると依存関係の問題がなくなりインストールできる。

#追記
依存関係の問題がなくなったので、`rails g devise:install`しようとしたらまたエラーがでた。

cinfig/application.rb内に6.1を指定している箇所があるらしいのでそこを修正。

```config/application.rb
class Application < Rails::Application
    config.load_defaults 6.0
    config.api_only = true
end
```

修正後に`rails g devise:install`したら無事にインストールが完了した。

#追記2
`rails s`でサーバーを立ち上げようとしたところまたエラーを吐いた。

```
config.ru:6:in `block in <main>': undefined method `load_server' for #<アプリ名::Application:0x00007f953935ef00> (NoMethodError)
Did you mean?  load_seed
```

エラーを読むとload_serverというメソッドが存在しないと言われてるらしい。load_serverで調べたら6.1から6.0にダウングレードする場合はconfig.ruのload_serverは削除しないといけないらしい。

```config.ru
# This file is used by Rack-based servers to start the application.

require_relative "config/environment"

run Rails.application
+ Rails.application

# 削除
- Rails.application.load_server
```

config.ruを修正したところ無事にサーバーを起動できた。
CORSの要点をサクッとつかむ

Web API を開発する際避けて通れないCORSについてサクッと要点をつかめるように記載していきます。細かい設定方法などは記載しないので、CORS理解の足掛かりにしていただければなと思います。
## CORSとは？の前に同一生成元ポリシーについて
同一生成元ポリシー（Same-Origin Policy）ってご存知でしょうか。まずはこちらの絵をご覧ください。
![image-qiita-cors.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051954/77ee7ee8-0f72-3008-6814-5e5126dcc87d.jpeg)
悪質サイトにアクセスしてしまいそのレスポンスに含まれたJSから、善良なサイトにアクセスされている様子です。悪質サイトっていうのは例えば、有名なサイトの偽サイトや悪質ブログなどですね。悪質なJSが埋め込まれていると、勝手に善良なサイトにアクセスされて良からぬことをされてしまう可能性があります。プライベートな情報を保持しているサイトに接続されると、情報を抜き出されたり勝手に操作されるかもしれません。
これを防ぐためにブラウザは同一生成元ポリシーというものを導入しています。簡単に言うと、とあるオリジンからレスポンスされたスクリプト経由で別のオリジンへアクセスできないような仕組みにしています。
オリジンというのは「プロトコル+ドメイン+ポート番号」のことです。例えば`http://example.com:80`は一つのオリジンを表していて、プロトコル、ドメイン、ポート番号のどれか一つでも違えば別オリジンということになります。
## CORSとは？
別オリジンにアクセスできないと書きましたがそれはそれで困っちゃいますよね。それができなかったらWeb API はほぼ機能しないわけですし。セキュリティを考慮にいれつつ、なんとかして別オリジンへアクセス可能にする方法を考えていたわけですが、そこで編み出された手法の一つがCORSなんですよ。Cross-Origin Resource Sharingと書き、オリジンを跨いでリソースをシェアできるようにしましょうといったことを表しています。
#### CORSの仕組み
ブラウザが別オリジンにアクセスさせないのは、悪質サイト経由でアクセスさせたくなかったからです。だったらアクセスされるオリジン側で、特定のオリジンだけアクセスできるようにしておけばいいじゃないかという風に考えます。絵を書いていきます。
![image-qiita-cors.002.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051954/6ca1cd65-6d53-3ce2-39ec-30f2f1fb06c8.jpeg)
ブラウザはオリジンAから受け取ったJSでオリジンXにアクセスしようとしています。その際、オリジンXにどのオリジンからのアクセスを許可しているかのリストを送ってもらい、そこにオリジンAが含まれているかを見てアクセス可否を判別します。この確認作業を本来のリクエスト（GET、POSTなど）の前にOPTIONSというHTTPメソッドを使って行います。これをプリフライトリクエストと言います。プリフライトリクエストでのOK例、NG例の絵です。
![image-qiita-cors.003.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051954/57c4b52c-7f17-ed66-84c3-46aa5298874c.jpeg)
![image-qiita-cors.004.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051954/9b39c7a7-08a9-8fc7-9b20-17ae068136ec.jpeg)
こんな感じでブラウザはCORSという手法を導入して別オリジンへのアクセス可否を判断しているわけです。プリフライトリクエストは必ず行われるわけではなく、シンプルなリクエストの場合は行われませんが詳細は割愛します。
#### CORSの設定方法
設定としてはサーバ側でアクセス可能なオリジンを定義しておき、それをHTTPヘッダに含めてレスポンスしてあげるだけです。具体的に言うと、`Access-Control-Allow-Origin`というヘッダに、アクセスを許可するオリジンを記載してレスポンスします。セキュリティ上どこからアクセスされても構わない場合は`Access-Control-Allow-Origin: *`とすれば、どのオリジンからもアクセス可能となります。`Access-Control-Allow〜`というヘッダは他にもあってもう少し細かく制御できるので詳しくは調べてみてください。
以上CORSについてざっくり記載しましたが、要点を掴んでいただけてたら幸いです。
terraformでcloudfront用のACMを取得する

aliasを使い、providerで選択する。


```tf

provider "aws" {
  alias  = "virginia"
  region = "us-east-1"
}

resource "aws_acm_certificate" "main" {
  provider = aws.virginia
}
```

[domain_validation_options](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/acm_certificate#domain_validation_options)のSetは[for_each](https://www.terraform.io/docs/language/meta-arguments/for_each.htmlhttps://www.terraform.io/docs/language/meta-arguments/for_each.html)で実装する.


```tf
provider "aws" {}
provider "aws" {
  alias  = "virginia"
  region = "us-east-1"
}

data "aws_route53_zone" "main" {
  name = "example.com."
}

resource "aws_acm_certificate" "main" {
  domain_name       = data.aws_route53_zone.main.name
  validation_method = "DNS"
  provider          = aws.virginia

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "main" {
  for_each = {
    for dvo in aws_acm_certificate.main.domain_validation_options : dvo.domain_name => {
      name   = dvo.resource_record_name
      record = dvo.resource_record_value
      type   = dvo.resource_record_type
    }
  }

  allow_overwrite = true
  name            = each.value.name
  records         = [each.value.record]
  ttl             = 60
  type            = each.value.type
  zone_id         = data.aws_route53_zone.main.zone_id
}

resource "aws_acm_certificate_validation" "main" {
  certificate_arn         = aws_acm_certificate.minecraft.arn
  validation_record_fqdns = [for record in aws_route53_record.main : record.fqdn]
  provider                = aws.virginia
}

```

## 参考
https://qiita.com/Toshinori_Hayashi/items/08bd5a12bc7d87d9ba18
https://qiita.com/tos-miyake/items/f0e5f28f2a69e4d39422
Aws::S3::Errors::SignatureDoesNotMatch in PostsController#createについて

こちら、S3を初めて導入していた際に沼ってしまったので、忘れないように記事に残します。
大した対応とはっきりとした原因は見つけられておらず参考にはならないかもしれません。

# こちらの記事に助けられました。
https://qiita.com/tettsu__/items/165afe4570f27468b90f

# 概要
・S3導入時にSignatureDoesNotMatchエラー発生
・「仮説」　S3利用に使う秘密キーが一致しないためにエラーが出ている。

#エラー解除のためにしたこと
・まず、記述ミスがないか確認。（この前に別のエラーがありそちらは環境変数に入れた秘密キーの記述に間違いがあった。）
・gemの確認
・ターミナルの更新
・サーバーの再起動
・環境変数の更新
#結論
キーに特殊文字が入っているとNGになる？（可能性）

IAMの秘密キーとパスワードはAWS側のランダム生成で作成しています。
上記の記事を見つけて再度IMAユーザーを別で作成。
そちらのユーザーで新しいキーを作りそちらと入れ替えたところ、状態が改善されました。
# 終わり
GitHubなんかでイシューとしてでているとか…
英語頑張って勉強します。しなきゃいけないとおもいました。
Next.jsにstyled-componentsを適応させる

# styled-components is 何？
 CSS in JSのライブラリの一つ。最近では採用しているプロダクトが増えてきています。cssとjsを同一ファイル内に記述できるため、Reactの設計思想にあるようにコンポーネント単位での管理がスタイルにも可能になります。

### 導入するメリット
①保守性が高まる（コンポーネント単位でcssを管理）
②cssにjsの値を渡すことができる(動的スタイル)
③コンポーネント単位でスコープが生成される
④重複やスペルミスなどを気にする必要がない
(単一のクラス名をstyled-componentsが作成するため)


# styled-componentsの導入手順

①ライブラリの追加

```shell


$ npm install --save styled-components
もしくは
$ yarn add styled-components
```

②以下のようにスタイルを割り当てていきます。

```react
import styled from "styled-components";

export default function FirstPost() {
  const Container = styled.div`
    max-width: 36rem;
    padding: 0 1rem;
    margin: 3rem auto 6rem;
  `;

  const Text = styled.div`
    //引数に色が渡すことができる
    color: ${props => props.color ? props.color : "dark"};
  `;  

  return (
    <Container>
      <Text color="red">Hello!</Text>
    </Container>
  );
}
```

③babelのプラグインの設定
Next.jsとstyled-componentsが実行される前提とする環境が異なります。（styled-componentは元々クライアント側で動くことを前提としています）そのため、サーバーサイドでもstyled-componentsが働くようにしていきます。

```
$ npm install --save-dev babel-plugin-styled-components
もしくは
$ yarn add -D babel-plugin-styled-components
```
④プロジェクトのルートに.babelrcを作成

```json
:.babelrc
{
    "presets": [
      "next/babel"
    ],
    "plugins": [
      [
        "babel-plugin-styled-components",
        {
          "ssr": true,
          "displayName": true,
        }
      ]
    ]
  }
```


# 参考にさせていただいた記事
[Next.jsにstyled-componentsを取り込む方法【Babelの設定が必要】](https://zenn.dev/syu/articles/0f92abf7f0b5c5)

[styled-components（CSS in JS）をやめた理由と、不完全なCSS Modulesを愛する方法](https://qiita.com/jagaapple/items/7f74fc32c69f5b731159)

[Reactのプロジェクトならstyled-components使うのがいいかも](https://top-men.hatenablog.com/entry/2018/07/25/141542)
SQLの副問い合わせを使ってみる

##概要
SQLの副問い合わせについてあまり知見がなかったので、理解できた範囲で少しまとめてみたいと思います。

#####副問い合わせとは
「副問い合わせとは、あるselect文の結果を別のSQL文で利用することです。
サブクエリとも呼ばれます。クエリ(query)は、問い合わせという意味です。」
参考：[SQL 副問合せのサンプル(サブクエリ)](https://itsakura.com/sql_subquery)

select使用時の副問い合わせのある場所はwhere、from、select、having。
また、selectだけではなくinsertやdelete、update文でも使用可能のようです。

例：各都道府県名とidが格納されたprefectureテーブルとユーザー情報が格納されたテーブルが存在するとする。ユーザー情報の出身地にはprefectureテーブルのidが紐づいている。

特定の都道府県出身のユーザーを取得したい場合は下記のように取得することができる。


####検索条件
※userテーブルのlocalとprefecturesテーブルのidは外部キーとして連携しているとする。

特定の商品を購入した購入者情報を特定したいとき。

1. 特定の商品が複数の時はIN句を使用

```sql
   SELECT * FROM user
   WHERE user.id
   IN (
    SELECT user_id
    FROM purchase_history
    WHERE product_id
    IN (1, 2, 3)
    );
```
他にもさまざまな方法があるようです。
jooqなどでも副問い合わせを書くことは可能なので、押さえておきたいです。
[jooq使用方法のまとめ](https://qiita.com/rubytomato@github/items/93ed18b30605f4491086)
powershellで指定フォルダ以下に存在する特定の名前のフォルダだけを削除したい

```powershell
foreach($DIRNAME in ("消したいフォルダ名A", "消したいフォルダ名B", "消したいフォルダ名C...")){
    Get-ChildItem -Recurse -Directory "ルートフォルダ" |
    Where-Object {$_.name -eq $DIRNAME} | Remove-Item -Recurse
}
```
1. forearchなんかしないでWhere-Objectのところで-in $DIRNAMES的なことやれたほうがいいんだろうけどどういう書き方するのか知らない
2. forearchするにしても最外なんかでやらないでWhereのところでやったほうが絶対に処理早いけどどう書くのがスマートなのかパッと出てくるほどpowershellに慣れてないしどうせ2回目以降のGet-ChildItemはオンメモリで一瞬で処理されるだろうから妥協した
パンくずリストを作る

##パンくず機能とは

パンくずを実装する利点は、Webサイトを利用しているユーザーが、どのページにアクセスしているのか一目でわかることです。アクセス場所がわかることによって、サイトの巡回が行いやすくなります。

例として、旅行会社のホームページで、旅行先を調べている場面を考えます。トップページに最初の選択肢で、「国内」と「海外」があり、「国内」を選択したとします。次に「国内」の中には、北海道などの観光地が選択肢として表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/730703/87eea285-1c1f-0787-907e-102e8a5136ed.png)

「トップページ」の中に「国内」があり、「国内」の中に「北海道」があるように、要素同士が紐付いており、親要素・子要素の関係であることを指します。

##Gemをインストール

```:Gemfile
gem 'gretel'
```

```:ターミナル
bundle install
```

##パンくずの設定
```:ターミナル
rails g gretel:install
```

* config/breadcrumbs.rbのファイルが生成されます。

ファイルの記述方法は以下のようになります。

```:config/breadcrumbs.rb
crumb "現在のページ名（表示させるビューにもページ名記述）" do
  link "パンくずリストでの表示名", "アクセスしたいページのパス"
  parent :親要素のページ名（前のページ）
end
```

```:config/breadcrumbs.rb
crumb :root do
  link "Home", root_path
end

crumb :tweets do
  link "国内旅行", hoge_index_path
  parent :root
end

crumb :contacts do
  link "北海道", huga_index_path
  parent :hoge
end
```

##ビューを編集
views/layouts/application.html.erb

```application.html.erb
<!DOCTYPE html>
<html>
 <head>
   <title>Breadcrumb</title>
   <%= csrf_meta_tags %>
   <%= csp_meta_tag %>
   <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
   <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
 </head>
 <body>
   <%= breadcrumbs separator: " &rsaquo; " %>   
   <%= yield %>
 </body>
</html>
```
separator: " &rsaquo;”は、パンくず間の区切りである「>」を示します。

各indexファイルの編集

```app/views/top/index.html.erb
<p><%= link_to "国内旅行へ", hoge_index_path %></p>
<% breadcrumb :root %>
```

```app/views/hoge/index.html.erb
<p><%= link_to "北海道へ", huga_index_path %></p>
<% breadcrumb :hoge %>
```

ブラウザ上で以下のようになっていたら成功です。
![スクリーンショット 2021-01-31 1.38.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/730703/492cf33d-605d-a601-fa10-07984595b37f.png)
【GitHub 】リポジトリを削除する方法

不要なリポジトリを削除する機会があったので、その方法を書き留めます。

#削除手順

####1.対象リポジトリのメインページにアクセス

####2.`Settings`をクリック
リポジトリ名の下部に表示されているナビゲーションバーから`Settings`を選択します。
(一番右のやつです)
![github-settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701834/8d22f789-9673-8d48-9a34-19be80b05e17.png)

####3. `Danger Zone`の`Delete this repository`をクリック

画面をスクロールしていくと、一番下にあります。![github-dangerzone.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701834/6f17b3b9-b72c-f754-8120-ead9b869d5c1.png)

####4.警告を読んで、リポジトリの名前を入力
削除対象のリポジトリ名を入力するのは、削除しようとしているリポジトリに間違いがないかを確認する為です。
![gtihub-absolutely.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701834/d23840ce-cce4-2beb-ad2a-c423b20e90df.png)

####5.`I understand the consequences, delete this repository`をクリック
これで削除完了です。

#参考
* [リポジトリの削除 - GitHub Docs](https://docs.github.com/ja/github/administering-a-repository/deleting-a-repository)
[AtCoder]AtCoder Beginner Contest 190 A~D問題

# A問題
以下の4つに場合分けします。
1. A > Bの時 : 高橋くんの勝ち
2. A = BかつC = 1の時 : 高橋くんの勝ち
3. A = BかつC = 0の時 : 青木くんの勝ち
4. A < Bの時 : 青木くんの勝ち

すると高橋くんの勝つ条件は A + C > B と言い換えられます。

```c++
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int a,b,c;
    cin >> a >> b >> c;

    if(a + c > b){
        cout << "Takahashi" << endl;
    }
    else{
        cout << "Aoki" << endl;
    }

    return 0;
}
```
# B問題
問題文からダメージを与えられる条件はX < S かつ Y > Dとわかります。
一つでも条件に一致するものがあればYes、一つもなければNoです。

```c++
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,s,d;
    cin >> n >> s >> d;

    for(int i = 0; i < n; i++){
        int x,y;
        cin >> x >> y;
        if(x < s && y > d){
            cout << "Yes" << endl;
            return 0;
        }
    }

    cout << "No" << endl;

    return 0;
}
```
# C問題
各人がそれぞれCを選択した場合とDを選択した場合の組み合わせをすべて検証する。
このとき、各bitを人に見立て1ならC、0ならDというふうに決めて列挙する(bit全探索)。
また配列のindexを0オリジンに統一するため入力値A,B,C,Dはすべて-1する。

```c++
#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,m,k;
    cin >> n >> m;
    vector<int> a(m);
    vector<int> b(m);
    for(int i = 0; i < m; i++){
        cin >> a[i] >> b[i];
        a[i]--;
        b[i]--;
    } 
    cin >> k;
    vector<int> c(k);
    vector<int> d(k);
    for(int i = 0; i < k; i++){
        cin >> c[i] >> d[i];
        c[i]--;
        d[i]--;
    }
    
    int ans = 0;
    for(int i = 0; i < (1 << k); i++){
        bitset<32> bs(i);
        vector<bool> s(n);
        int sum = 0;
        for(int j = 0; j < k; j++){
            if(bs[j])
                s[c[j]] = true;    
            else
                s[d[j]] = true;
        }
        for(int j = 0; j < m; j++){
            if(s[a[j]] && s[b[j]]){
                sum++;
            }
        }
        ans = max(ans, sum);
    }

    cout << ans << endl;

    return 0;
}
```
# D問題
N = 2n x 2m + 1(n,mは0以上の整数)が成り立つとき、以下２つの等差数列が成立する。
[m+1-2n,...,m,m+1,...,m+2n]
[n-m/2,...,n,...,n+m/2]

よってNの因数のうち奇数のものの数を計算し x 2した数が答えとなる。

```c++
#include <bits/stdc++.h>
using namespace std;
#define ll long long

vector<pair<ll, ll> > prime_factorize(ll N) {
    vector<pair<ll, ll> > ret;
    for (ll a = 2; a * a <= N; ++a) {
        if (N % a != 0) continue;
        ll ex = 0;
        while (N % a == 0) {
            ++ex;
            N /= a;
        }

        ret.push_back({a, ex});
    }

    if (N != 1) ret.push_back({N, 1});
    return ret;
}

int main()
{
    ll n;
    cin >> n;
    auto tmp = prime_factorize(n);

    int ans = 2;
    for(auto& t : tmp){
        if(t.first%2 == 1){
            ans *= t.second + 1;
        }
    }

    cout << ans << endl;

    return 0;
}
```
[Unity]音声の再生についてまとめ

# 概要
音声周りがよくわからんのでとりあえず調べてわかったことを簡単にまとめた。
イメージ図で全体像をすぐ把握できるようにすることを目指した。

# 全体イメージ
**音声の再生に必要なものとやらなきゃいけないこと**

![SEの概念-音声の再生.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59542/cb8e2e81-a6e3-9962-97dd-e02db14239f9.png)

## 解説
**AudioClip**
Unityでの音声データ形式。
Unity上では、wavやmp3ファイルといった音声データファイルをこの形式で扱う。

**AudioMixer**
以下ができる。

- 音声データのグループ化(AudioMixerGroup)
- グループに所属する音声データの音量・エフェクト設定(の保存・使用)
- 音声データを流した際の音量可視化

**AudioSource**
音声データ(AudioClip)をAudioMixerGroupを通して再生・停止する機能をもつコンポーネント。
再生・停止メソッドとしては以下がある。


- Play():AudioSourceに設定しているAudioClipを再生する(LoopがTrueになっているならば連続再生)
- PlayOneShot(audioClip):引数で指定したaudioClipを1回再生する。音を重ねることができる
- Stop(): 当該AudioSourceで再生中の全音声を停止
- Pause() : 当該AudioSourceで再生中の全音声を一時停止
- UnPause() : 当該AudioSourceで一時停止中の全音声を再生

# 音声再生に便利なアセット(AudioManager)
上記の内容を理解した上で、実際に諸々の設定とスクリプトのコーディングをして音声を再生しようとすると結構めんどくさい。以下のアセットを使うと比較的簡単に音声が再生できた。便利。

[kankikuchi / AudioManager](https://github.com/kankikuchi/AudioManager)

使ってみて感じた注意点としては以下。
どうしてもイヤということでなければ十分実用的かと思う。

- AudioMixerが使えない
- BGMPath, SEPathから音源のファイルパスの参照は、メソッド内でしかできないっぽい

**使い方**
[誰でも簡単に使える最強のAudio(BGM, SE)Manager【Unity】](https://kan-kikuchi.hatenablog.com/entry/AudioManager_2019)


# 参考
- [サウンドの基本を理解して再生や停止をしてみよう](https://yttm-work.jp/unity_beginner/unity_beginner_0011.html)
- [[Unity] Unity×音についてざっくりまとめ
](https://qiita.com/lycoris102/items/5d5359b2015a8fdebaaa)
- [【Unity】AudioMixerで遊んでみよう！(1/3)](https://zenigane138.hateblo.jp/entry/2018/02/20/222436)
#1 NW試験は午前問題で基礎固めできるか？

この記事はシリーズものです。トップはこちらから。

 - [ネットワークスペシャリスト試験を受けることにしました【令和3年春季】](https://qiita.com/foxtail1979/items/5e333d28f2e93acb552b)

# NW試験は過去問が大事だそうで
午後に論文試験がない高度情報試験では、(DBとかNWとかSCとか)過去問を繰り返し解くことが合格の鍵となるようです。その辺を意識したわけではありませんが、今のところ午前Ⅱの過去問を分野別で指定して解いています。

 - [ネットワークスペシャリストドットコム](https://www.nw-siken.com/)  

また、下記の本の最後の方に基礎知識300問があるので、これを2週しました。苦手意識があるのはセキュリティと無線LANですね。なかなか覚えられない。

 - [ネスペR1 - 本物のネットワークスペシャリストになるための最も詳しい過去問解説](https://www.amazon.co.jp/dp/4297113279/)  

そういえば当初の予定にはなかった下記を買おうと思っています。

 - [情報処理教科書 ネットワークスペシャリスト 2020年版](https://www.amazon.co.jp/dp/B0841WNWC1)

知らない用語や技術が出てきたとき、[ネスペイージス](https://www.infraexpert.com/info/netspecial1.html)などで都度調べるより、書籍でじっくり読むほうが性に合ってる感じがするのです。
電子書籍版にしようかなと思いましたが、試験合格後に手元に残しておいてパラパラ振り返るのに使えそうなだなということで物理本にしました。

こういう教科書は他にもあるので、前書きのノリが合うかとか、段組がみやすいかとか値段とかで直感的に決めていいと思います。

今週の総勉強時間は、、、うーんだいたい一日３０分くらいでしょうか。やはり平日は仕事終わりで時間が取りにくいので、ちょこちょこ知識を増やして週末にまとめて問題を解く、というスタイルになりそうです。
[Laravel]バリデーションを日本語化する


## はじめに
バリデーションメッセージが英語だったから日本語にしたい。

##環境
* macOS Catalina
* PHP 7.4.14
* Laravel 8.21.0

## 手順
### 1.コマンドを入力
以下のコマンドをプロジェクトのディレクトリの下で実行する。（何も表示されません）

```
php -r "copy('https://readouble.com/laravel/5.6/ja/install-ja-lang-files.php', 'install-ja-lang.php');"
php -f install-ja-lang.php
php -r "unlink('install-ja-lang.php');"
```

``resources/lan`` に ``ja`` というファイルが生成されています。
``ja``の中には

- auth.php
- pagination.php
- passwords.php
- validation.php

の４つのファイルが生成されていて、これらは日本語版のバリデーションファイルです。

### 2. localeを変更
``config/app.php``を開きます。
``'locale' => 'en'``になっているので``'locale' => 'ja' ``に変えます。

- 変更前

```php:app.php
'locale' => 'en';
```

- 変更後

```php:app.php
'locale' => 'ja';
```
これでバリデーションメッセージが日本語化されます。

##参考
[Laravel 5.6 validation.php言語ファイル](https://readouble.com/laravel/5.6/ja/validation-php.html
)
Matlabのfind()をpythonで

遅いとか言われつつ、matlabではよく使うfind()
似たようなことはnumpy.argwhere()でできるっぽい。

#できること
Matlabの

```matlab
[n, m] = find(condition)
```
をpythonで書くと

```python
import numpy as np

nm = np.argwhere(condition)
n = nm[:, 0]
m = nm[:, 1]
```
こんな感じになる。

##例:Matlab find()
```matlab
>> x=reshape(0:11, [], 4)';
>> [n, m] = find(mod(x, 3)==0)

n =

     1
     2
     3
     4


m =

     1
     1
     1
     1
```
##例:python numpy.argwhere()
```python
>>> import numpy as np
>>> x = np.arange(12).reshape(4, -1)
>>> np.argwhere(x % 3 == 0)

array([[0, 0],
       [1, 0],
       [2, 0],
       [3, 0]])
```

インデックスが0始まりか1始まりか、という差以外は同じ。

#できない（？）こと

##'first' 'last'
matlabの

```matlab
find(condition, 1, 'first')
find(condition, 3, 'last')
```
最初から１つだけ、とか最後から３つだけ、みたいなのは、numpy.argwhere()だけではできないっぽい。
全部取ってきてから必要なところだけ拾うか、forで書き下すか？
なんか他に良いモジュール/メソッドがあるのかも。見つけたら更新します（たぶん）。


##ベクトル展開した上でのインデックス
matlabの

```matlab
n = find(condition)
```
のようなベクトルに展開した上でのインデックスをとってくるのはコマンド一発では無さそう（？）
個人的にはベクトル展開してインデックスをとってくるのはあまり直感的じゃないので、割とどうでもいい。
どうしても必要なら、行と列と行列サイズから簡単に求められるし。
【Heroku】アプリの削除から再デプロイ

herokuへのデプロイでエラーが解決できなかったので、
一旦削除してから再デプロイまでの流れを備忘録として記載します。

## 前提

- Herokuアカウントの作成が完了している
- gitが使用できる状態
- herokuにpushするアプリがある

## herokuアプリの削除（コマンド）

```
$ heroku apps:destroy --app アプリ名
```
- アプリ名はheroku画面から確認ができる
- `heroku apps:info` or `heroku apps`でも確認できる

画面上から削除した場合はgitのherokuのリモート先を変更ないとダメなので、
上記のコマンドでやった方が簡単です。

## 新しいherokuアプリをcreate〜push

```
$ git push heroku アプリ名
```
最後にアプリ名を入れれば指定できる
アプリ名を付けなかったら、herokuが自動的に名前を決める

上記の`heroku create`でリモートリポジトリにherokuのリポジトリが登録されます。

```
$ git push heroku main
```
最近、gitのデフォルトブランチは`main`になりました。

```
$ heroku open
```
これで自動的にブラウザが立ち上がり、
デプロイしたアプリ画面が表示されます。

以上で、デプロイできないアプリの削除から再デプロイまでの流れでした。

#### 参考
[herokuのリモートリポジトリを削除](https://off.tokyo/blog/heroku%E3%81%AE%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E3%82%92%E5%89%8A%E9%99%A4/)
【MapStruct】コンストラクタ呼び出しでマップする/Kotlinのdata classへマップする

`MapStruct`は、`1.4.0.Final`よりコンストラクタの呼び出しによるマッピングを正式にサポートしています。
この機能により、`Kotlin`の`data class`へのマッピングもできるようになったため、実際にやってみます。

この記事では、`MapStruct 1.4.1.Final`を利用します。

- [mapstruct/mapstruct: An annotation processor for generating type\-safe bean mappers](https://github.com/mapstruct/mapstruct)
- [MapStruct 1\.4\.1\.Final bug fix released – MapStruct](https://mapstruct.org/news/2020-10-11-mapstruct-1_4_1_Final-bug-fix-released/)

# コード例
## src/dst
例として、以下の`src`と`dst`を行います。

```kotlin:ソース
data class Src(
    var arg0: Int,
    var arg1: Int,
    var arg2: Int,
    var arg3: Int,
    var arg4: Int
)
```

```kotlin:マップ対象
data class Dst(
    var arg0: Int,
    var arg1: Int,
    var arg2: Int,
    var arg3: Int,
    var arg4: Int
)
```

## マッパー
マッパーの定義は以下の通りです。
`injectionStrategy = InjectionStrategy.CONSTRUCTOR`を指定することで、コンストラクタ呼び出しができます。

```java
import org.mapstruct.InjectionStrategy;
import org.mapstruct.Mapper;

@Mapper(injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public interface MapStructConstructorMapper {
    Dst map(Src src);
}
```

### 生成されたコード
生成されたコードは以下の通りです。
確かにコンストラクタが呼び出されています。

```java
import javax.annotation.Generated;

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2021-01-31T00:44:38+0900",
    comments = "version: 1.4.1.Final, compiler: IncrementalProcessingEnvironment from gradle-language-java-6.1.1.jar, environment: Java 1.8.0_241 (Oracle Corporation)"
)
public class MapStructConstructorMapperImpl implements MapStructConstructorMapper {

    @Override
    public Dst map(Src src) {
        if ( src == null ) {
            return null;
        }

        int arg0 = 0;
        int arg1 = 0;
        int arg2 = 0;
        int arg3 = 0;
        int arg4 = 0;

        arg0 = src.getArg0();
        arg1 = src.getArg1();
        arg2 = src.getArg2();
        arg3 = src.getArg3();
        arg4 = src.getArg4();

        Dst dst = new Dst( arg0, arg1, arg2, arg3, arg4 );

        return dst;
    }
}
```

## 呼び出し
以下のようにすることで、`Kotlin`の`data class`へマッピングできます。

```kotlin
val src = Src(1, 2, 3, 4, 5)
val mapStructConstructor: MapStructConstructorMapper = Mappers.getMapper(MapStructConstructorMapper::class.java)
val dst = mapStructConstructor.map(src)

println(dst) // -> Dst(arg0=1, arg1=2, arg2=3, arg3=4, arg4=5)
```

# 補足
試した所、`Kotlin no-arg plugin`などで無引数コンストラクタを生成している場合、`injectionStrategy = InjectionStrategy.CONSTRUCTOR`を指定してもコンストラクタを呼び出すコードが生成されませんでした。

また、`interface`を`Kotlin`で書いた場合コード生成が機能しないようでした。
これに関しては、調べた所`gradle`の設定で回避できるかもしれませんでしたが、簡単のため一旦`Java`で書いています。
Amazon EC2(Windows OS)にログインしたら自動的にメール通知を行う

踏み台用や試験用でAWSにサーバを作ったときに「不正アクセスされたらどうしよう...」ってなんとなく不安になることってないですか？セキュリティグループで制限をかけているとはいえ不安...かといって一時利用なのでセキュリティに手間をかけていられないという人が安心して眠れるように、サーバにログインがあったときに自動的にメール通知してくれる設定をしてみようと思います。

# 今回のゴール
Windows サーバにログインが成功したら、指定のアドレスへ自動的にメールを送信する

# 前提条件
- 使用するサーバはAmazon EC2(windows OS)
- サーバのログオンスクリプトにメール送信操作を行うコマンドを記述したPowershellファイルを設置して、ログインをトリガーに動作させる
- メールサーバへEC2のPoweshellコマンドからアクセスできるようにアクセス認証を調整しておく
- Amazon VPC のセキュリティグループのアウト方向は全許可にしておく
- メールサービスは送信はgmailで受信はYahoo mailを使う　※申請が面倒なのでAWS SESは使いません
- メールサーバへの通信ポートは587を利用する


# 設定内容
①EC2を準備する
②Poweshellファイルを作成する
③サーバのログオンスクリプトを設定する
④Gmail側でアクセス認証の設定を行う

# 実際にやってみる
①については他に詳しい記事が多くありますので割愛します。とりあえず、RDP接続できて、インターネットへ接続できればOKです。
続いて②ですが、Powershellの中身は以下のような感じです。xxxの部分は実環境ごとに変更してください。

    # Send Gmail Script
    # HeaderをScript内に指定（メール送信元/送信先/件名/本文）
 
    # gmail Account
    $AccountName = "xxxxxxxx@gmail.com"
    $Password = "xxxxxx"
 
    # connect gmail
    $SMTPClient = New-Object Net.Mail.SmtpClient("smtp.gmail.com", 587)
    $SMTPClient.EnableSsl = $True
    $SMTPClient.Credentials = New-Object 
    System.Net.NetworkCredential("$AccountName","$Password");
 
    # Header
    $MailFrom = "$AccountName"
    $MailTo   = "xxxxxx@yahoo.co.jp"
    $Subject  = "EC2よりメール送信テスト"
    $Body     = "これはEC2のログオンスクリプトからのメール送信テストです。"
 
    # message object
    $Message = New-Object Net.Mail.MailMessage($MailFrom, $MailTo, $Subject, $Body)
 
    # send mail
    $SMTPClient.Send($Message)


③で上記②で設定したPowershellがログオン時が実行されるように設定します。
タスクスケジューラーで設定する方法もありますが、今回はログオンスクリプトに設定する方法で構築します。

[Windowsボタン]+[R]を押し、gpedit.mscを検索し、アクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655033/9bf35416-9e76-0f46-2970-aac62f65dd42.png)
ローカルコンピュータポリシーエディターが開くので、[ユーザの構成]の中の[Windowsの設定]-[スクリプト「」ログオン/ログオフ]のログオンを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655033/675da3d5-bb80-f6b7-bee7-8ed18a12fa0e.png)

以下のように[Powershellスクリプト]タブへ先ほど作成したPowershellを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655033/d8671732-38aa-114a-3ff9-e0734f4a66a1.png)



次に④でGmailの管理ページで、Powershellコマンドでメール送信できるように「安全性の低いアプリのアクセス」を有効にしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655033/483adb44-753e-cda2-f620-ae8961cb3174.png)
これをしておかないとpowershellからgmailサーバへの認証が通らないです。

では準備は整いましたので、EC2へRDPしてみましょう。
ログインすると以下のようにメール通知されていると思います。
![画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655033/891616e8-24a9-63c0-606c-607f087224ad.png)


これで安心して眠れますd(`・ω・’)

EC2から通信ポート25を使って、メール送受信しようとするとAWSへ申請などが必要で面倒ですがポート587を使って送信するだけであればややこしい申請も不要です。

# 参考にしたページ
[【PowerShell】Windows PowerShell を使用して GMail や Office 365 からメールを送信する]
(https://docs.microsoft.com/ja-jp/archive/blogs/junichia/powershellwindows-powershell-gmail-office-365)
画像のポップアップ機能

## はじめに
オリジナルアプリ制作で画像のポップアップ機能を実装したので、備忘録として載せておこうと思います。
今回の実装では**Lightbox2（画像などをクリックすると、ポップアップウィンドウで画像が拡大されるスクリプト）**を用いて実装しました。

## 1.ファイルの読み込み
Lightbox2を読み込むためのコードをapplication.html.erbのヘッダーに記述する。

```html:app/views/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <!--中略-->
    <!--　以下3行を追記する　-->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/css/lightbox.css" rel="stylesheet">
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.7.1/js/lightbox.min.js" type="text/javascript"></script>

  </head>
  <body>
    <%= yield %>
  </body>
</html>
```

## 2.viewの編集
ポップアップさせる画像を表示したい箇所にコードを記述していく。

```html:表示させたいviewファイル
<%= link_to hoge-image, "data-lightbox": hoge-image do %>
  <%= image_tag hoge-image, class:"img"%>
<% end %>
<!--　hoge-imageとしている箇所に、表示させたい画像ファイル名を記述する　-->
```

##実装完了
ポップアップ機能を実装することが出来ました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941480/564e0420-5cc3-9221-d486-9e112c712a31.png" width=70%>

##さいごに
ポップアップ機能は実装するまでは難易度が高いのかなと思っていたのですが、lightbox2を用いたことで簡単に行うことが出来ました。
Qiskitで　DeprecationWarning に遭遇した話

# DeprecationWarning

小ネタです。
qiskitで以下のような回路をコーディング中に、警告文が出てきました。
(少しぼかしてますが）

```python
    angle_y = np.arcsin(x_in)
    for i in range(nqubit):
      angle_y_index = angle_y[i]
      circuit_in.ry(angle_y_index,i)
```

`/usr/local/lib/python3.6/dist-packages/qiskit/circuit/instruction.py:84: DeprecationWarning: Gate param type <class 'numpy.ndarray'> is being deprecated as of 0.16.0, and will be removed no earlier than 3 months after that release date. Considering creating your own Gate subclass with the method validate_parameter  to allow this param type.`

# 何が問題だったか

どうやら、qiskitのryゲートでは回転角度にnp.array型を禁止することを予定しているようです。
回転角度はスカラーですから、確かにnp.arrayのような配列を使う必要はありませんね。
解決方法としては、 np.float でスカラーにキャストしてやればいいみたいです。

```python
    angle_y = np.arcsin(x_in)
    for i in range(nqubit):
      angle_y_index = np.float(angle_y[i]) #cast
      circuit_in.ry(angle_y_index,i)
```

# 結論

Warningはちゃんと気にしておこう。。
Matlabのdiff()をPythonで

Matlabでちょいちょい使うdiff()
これもpythonではnumpy使ってできる。

#numpy.diff()
matlabでXのDim軸方向のN階の差分はdiff(X,N,Dim)で求める。
同じことは、numpy.diff(X,n=N,axis=Dim)でできる
ただし、matlabのDimは1から始まるのに対し、numpy.diffは0から始まる点に注意。
もっとも、これは配列のインデックスとかと同じ。

#例：diff() in Matlab
```matlab
x = reshape(0:99,[],5)';
dx = diff(x,1,1);
ddx = diff(x,2,1);
```
```
>> x
x =

     0     1     2     3     4     5     6     7     8     9    10    11    12    13    14    15    16    17    18    19
    20    21    22    23    24    25    26    27    28    29    30    31    32    33    34    35    36    37    38    39
    40    41    42    43    44    45    46    47    48    49    50    51    52    53    54    55    56    57    58    59
    60    61    62    63    64    65    66    67    68    69    70    71    72    73    74    75    76    77    78    79
    80    81    82    83    84    85    86    87    88    89    90    91    92    93    94    95    96    97    98    99
```
```
>> dx

dx =

    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20
    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20
    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20
    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20    20
```
```
>> ddx

ddx =

     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0     0
```


#例：numpy.diff() in Python
```python
import numpy as np

x = np.arange(100).reshape(5, -1)
dx = np.diff(x, n=1, axis=0)
ddx = np.diff(x, n=2, axis=0)
```

```
>>> print(x)
[[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19]
 [20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39]
 [40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59]
 [60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79]
 [80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99]]
```
```
>>>  print(dx)
[[20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20]
 [20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20]
 [20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20]
 [20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20]]
```
```
>>> print(ddx)
[[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]]
```
同じですね。
#余談：列vs行
diff()の話はこれでいいのだが、
何も考えずにベクトルつくると縦だったり横だったりの挙動がMatlabとPython（numpy)で違うっぽい？
（上の例だとMatlabの方でしれっと転置している）
気が向いたら調べるかも。
Power BI学習コンテンツとして最適なDashboard in a Dayによる学習方法

## 概要
Power BI を学習するための最適なコンテンツとして、マイクロソフトが提供しているDashboard in a Day（DIAD）というものがあり、学習方法を共有します。コンテンツは日本語を含む複数言語で提供されており、すべてダウンロード可能です。

学習方法としては下記の2パターンあり、それぞれの申し込み方法を共有します。
2の実施日については、Dashboard in a Day Event Listというページにて確認可能です。

1. 自己学習する方法
2. マイクロソフト主催のワークショップに参加する方法

## 1. Dashboard in a Dayを自己学習する方法
### 1-1. [Dashboard in a Day](https://powerbi.microsoft.com/ja-jp/diad/)に接続後、"その他の言語"を選択するとファイルのダウンロードが始まります。ファイルサイズが大きいため、とても時間がかかる場合があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/79aa3fa6-6103-6fff-c493-abecb4e7281a.png)
引用元：[Dashboard in a Day (microsoft.com)](https://powerbi.microsoft.com/ja-jp/diad/)

### 1-2. ダウンロードしたファイルを解凍後、"ja-JP"というフォルダを開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/af62a133-8b09-f229-f068-de3e76ffde8b.png)

### 1-3. "LAB..."と名称のファイルを開き、学習を実施します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/10dac40a-5326-239d-cad7-7c1f5cfc74e8.png)

### 1-4. 解凍したフォルダにて、"data"というフォルダに学習で利用するデータ等があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f0a0282f-5998-a4b1-175e-71764f87e10d.png)


## 2. マイクロソフト主催のワークショップに参加する方法
### 2-1. [Dashboard in a Day Event List](https://www.microsoftevents.com/profile/web/index.cfm?PKwebID=0x1728241abcd)に接続し、ページの下にスクロールします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/3c08ab56-6518-2474-9e79-2b22fb18cda3.png)
引用元：[Dashboard in a Day Event Web page (microsoftevents.com)](https://www.microsoftevents.com/profile/web/index.cfm?PKwebID=0x1728241abcd)

### 2-2. "--Select A Country--"にあるドロップダウンにて、"Japan"を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/af0b0774-a9c8-489a-fd0f-784aca58652e.png)
引用元：[Dashboard in a Day Event Web page (microsoftevents.com)](https://www.microsoftevents.com/profile/web/index.cfm?PKwebID=0x1728241abcd)

### 2-3. 参加したい日付のイベントの"Register now"を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/be9bf488-850f-ec36-3b02-655d4051cc90.png)
引用元：[Dashboard in a Day Event Web page (microsoftevents.com)](https://www.microsoftevents.com/profile/web/index.cfm?PKwebID=0x1728241abcd)

### 2-4. 申し込みサイトにて、申し込みを実施します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/09d4d97c-a349-335f-6445-c96775ca88b8.png)
引用元：[ワンデー ダッシュボード - 株式会社ジール (ZEAL Corporation) - Japan (microsoftevents.com)](https://www.microsoftevents.com/profile/form/index.cfm?PKformID=0x118636580001)
Unity Input System その２

# environment
Unity2020.2.0f1
OS : windows10 pro
IDE : VS2019 free

# InputSystem
[【Unity】新しいInput System入門](https://light11.hatenadiary.com/entry/2020/08/18/202627)

# Questコントローラー名称
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/62c4d610-bfe3-6909-4b7b-d37958ac4790.png)
[【Unity】Input System（新・入力システム）の使い方
](https://moon-bear.com/2020/08/20/unity-input-system/)

人差し指:PrimaryIndexTrigger
中指：PrimaryHandTrigger

# Questの入力 InputActionManager・InteractionManager
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/49cf6f7c-0489-2443-2b02-5ceca5084747.png)

InputActionManagerに入力用スキーマが登録されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/ab9ba3fc-86ce-6668-243b-2c7a4fdd051e.png)
サンプルで中指トリガーひくとブレークポイント停止するので、ここから見ていく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555658/f1fdf51a-4a9f-ea9a-9b3a-e140c12af9a5.png)
GCPとCloud9を使って開発環境を作ってみる

#はじめに
今回、GCPを使う機会があったので、GoogleCloudShellより使いやすいものはできないかということで今回はAWSでも使われている「Cloud9」を使ってみたいと思います。
#準備
1.Googleアカウントを作る
2.GCPのコンソールへ移動する
#Cloud9とは
そもそも説明していなかったのですがCloud9とはwebベースの開発環境です。
現在、AWSに買収されてしまっていますが、もともとはオープンソースの
開発環境なので、ソースは公開されています。今回は、それを使って構築していきたいと思います。
SKProductのダミーを作るメモ

普通に`SKProduct()`で作れるけど
価格,Localeの表示を確認したい場合の備忘


## extensionで簡易イニシャライザを定義

```.swift:extension
import Foundation
import StoreKit

extension SKProduct {

    convenience init(identifier: String, price: String, priceLocale: Locale) {
        self.init()
        self.setValue(identifier, forKey: "productIdentifier")
        self.setValue(NSDecimalNumber(string: price), forKey: "price")
        self.setValue(priceLocale, forKey: "priceLocale")
    }
}
```

## Dummyで利用時

```.swift:Dummy
struct DummyBillingItemImpl: BillingItem {

    // other dummy properties

    var product: SKProduct = SKProduct(identifier: "XXXX", price: "120", priceLocale: Locale(identifier: "ja_JP"))
```

表示の確認ならこれでさらっとできた
SPAでログイン済か否かをチェックする方法

##概要

SPAで作成されたアプリで、ログイン済であるか否かをチェックする方法について自分なりに備忘録としてまとめていきたいと思います。
###全体の流れ

APIで認証トークンが発行され、その認証トークンを保持しているのか否かをチェックする方法を用います。

1. APIに接続し、認証トークンを受け取る
2. フロント側で認証トークンを保持しているのか否かをチェックする

######APIから認証トークンを受け取る(※axiosを使用)
```typescript:AccessTokenAPIConnector.ts
private var accessToken = "";

axios.get('https://example.com', params) // この辺は適当です。
.then(function(response) {
    // APIから受け取った認証トークン
    this.accessToken = response.data.token;
}).catch(function(error) {
    // APIでエラーが発生した場合の処理
});
```

######認証トークンをlocal Storageに保存する
```typescript:AccessTokenAPIConnector.ts
// ローカルストレージ
private val store: Storage = localStorage

// ローカルストレージに受け取った認証トークンを設定
this.store.setItem("token", accessToken);
```

######local Storageに認証トークンが保存されているのかをチェック
```typescript:Authentication.ts
// ローカルストレージ
private val store: Storage = localStorage

if(!this.store.getItem("token")){
    // ローカルストレージに認証トークンがない場合
    this.$route.go("/login")
}else{
    // 認証済！
}
```

####最後に...
他により良い方法などもあるかもしれないですが、今回紹介した方法はあまり時間をかけずに期待通りに動いてくれたので、ひとつの方法として覚えておきたいなと思いました。

####参考にした記事
[SPAでのログイン処理のやりかた](https://qiita.com/uryyyyyyy/items/56f9a80a829161ae1f8e)
pip に関して

:::note warn
2020年に書いた個人的なまとめです
:::

- Python のほぼほぼデファクトスタンダードと言っていいパッケージ管理ツール
- Pythonのパッケージ手段は数あれど、 ensurepip が標準になっているので公式に近い存在
    - 参考: 数あるパッケージ手段の例 https://packaging.python.org/key_projects/#non-pypa-projects
- pip は PYPAのプロジェクト
    - [Python Packaging Authority とは](https://www.pypa.io/en/latest/)
- PYPA とは
    - Python Packaging Authority
    - pip や setuptools を開発
    - Python core development team と協力している
        - https://www.pypa.io/en/latest/future/
    - docs.python.org のパッケージング関連の改善も行う
- Python Package Index
    - pip 形式に対応した パッケージディストリビュション 
- パッケージ仕様の理解は基本的にここが参考になる
   - [Python パッケージングの標準を知ろう - Tech Blog - Recruit Lifestyle Engineer](https://engineer.recruit-lifestyle.co.jp/techblog/2019-12-25-python-packaging-specs/)
   - > setuptools 以外の依存についてはうまく扱えないということです。 このままでは、パッケージングに関する改善に PyPA 以外のコミュニティが貢献できないことにもなります。
   - ![pip_system.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/783f2427-b262-4b30-7fbd-9e0ce15db42c.png)

- ensurepip は標準だが pip は標準ではない
   - > ensurepip パッケージは pip インストーラを既にインストールされている Python 環境や仮想環境にブートストラップする助けになります
   - [ensurepip --- pip インストーラのブートストラップ — Python 3.9.1 ドキュメント](https://docs.python.org/ja/3/library/ensurepip.html)
   - [標準パッケージ](https://docs.python.org/ja/3/library/index.html)の中に確かに存在していない
   - ubuntu には最初から python3 が入っているものの、pip が最初から入ってない
- (個人的な意見) pyproject.toml を使った pip エコシステムに則ったパッケージングがスタンダードになっていく
深層学習における、畳み込み、相互相関。np.convolve,  np.correlate。

#深層学習における、畳み込み
深層学習における「畳み込み」の意味は、比較的わかりにくい、かもしれない。
「畳み込み」の説明として、wikipadiaの説明が引用されている例もよくみる。

この記事では、「畳み込み」と「相互相関」の違いを強調されている例があったので、備忘のため、記事にする。
ここにこだわる人の意図は、CNNが、相関のかたまりのようにとらえる立場のような気がする。

ワタシの理解では、あまり、その差を強調しすぎるより、「相互相関」も「畳み込み」の一種ぐらいの理解でもいいような気がする。


#CNNは、畳み込みではく、相互相関である

Wikipediaの英語のほうのconvolutionの記事によると、以下のように説明されている。

https://en.wikipedia.org/wiki/Convolution

引用
>Convolutional neural networks apply multiple cascaded convolution kernels with applications in machine vision and artificial intelligence. Though these are actually cross correlations rather than convolutions.

↓DeepL翻訳
>畳み込みニューラルネットワークは、マシンビジョンや人工知能に応用されている複数のカスケード畳み込みカーネルを適用しています。しかし、これらは実際には畳み込みではなく相互相関である。

#np.convolve,  np.correlate。
np.convolve,  np.correlateの例を示す。向き、符号の差であることが理解できるのでは。

##f
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/168efc57-abdb-979c-2e82-9d942d0236b1.png)

##g
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/ae61e6fc-5d55-c807-1d98-144ea4c7b221.png)

##np.convolve
2つ目の山のみが非常に大きくなることを期待しましたが、、、、それほど、差はないですが、一応、2つ目のが一番高い！！(2つ目は、逆向きです。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/9710a3d2-030f-e313-742e-0211dc233a8d.png)

##np.correlate
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/667c157e-7c86-2003-2be5-68fe2aa021eb.png)

#まとめ
特にありません。

以前、以下の記事を書きました。この記事は、単なる言葉に対する違和感でした。

[深層学習のCNNのConvolution（畳み込み）の意味がどうしても納得できなかったが。。。](https://qiita.com/enoughspacefor/items/910d1357f34b78ddac47)

今後、ちょっと、留意したいのが、
「畳み込み」は、ある分野の技術者には、とっても馴染みがあるはずで、それに馴染んでいないワタシと馴染んでいる人では、ちょっと、頭に浮かぶものが違う可能性あり、ということなど。
ちょっとニッチなNotionのショートカット③

#はじめに

昨日に引き続き…
[ちょっとニッチなNotionのショートカット②](https://qiita.com/TerToEer_sho/items/69fc3680fdf43431189e)

##最近利用したページに飛びたい！
声を大にして言いたい。「とにかく、便利です!!」

`command + p`

直近で使ったページ(RECENT PAGES)を5つ表示してくれます。
いちいち、左のバーから探し出さなくてすみます！

##ショートカットとはちょっと違うけど…
iPhoneにもNotionのアプリをインストールしていて、IOS14.0以降であれば、
ウィジェットにNotionを置くときに、FAVORITESにしておくと、いつも同じページにすぐにアクセスすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741816/9b1cc12a-c1d8-d388-5aaa-12142a5fd548.png)

##最後に

Notionの投稿って、Qiitaでは人気無いんですね…