OmniAICreator/Qiita-1.07M huggingface dataset:
動画の文字起こしと翻訳

# 目的
動画 （Webinar）の英文の文字起こしと、その自動翻訳を作成するまでの手順を試してみました。

# 手順
2種類あります。APIを使用したかったのですが要領を得ないので、後ほど更新予定です。
・Google Documentの音声認識機能を使う方法
・API経由で実行する方法（未完）
## Google Documentの音声認識を使う
とっても簡単、誰にでもできます。
### [1]サウンドの設定
無効のデバイスを表示します
![sound.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584443/172f2bda-a106-922a-2fbd-0be744cf85b4.png)
ステレオミキサーを有効にします
![sound2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584443/d27b29e7-a4ce-5ba2-d6da-28c25e6d006d.png)

### [2] Google Document を準備

1. 新規ファイル作成し音声の設定を行います
https://docs.google.com/document/u/0/
![googledocument.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584443/ca4dda95-cec4-6b20-770b-d5b2e389cf3a.png)

2. 言語を設定後、動画を再生しボタンをクリックします。
![g2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584443/068d22b6-3c43-3ff0-a605-2c9d14f04ec0.png)

3. ドキュメントの翻訳機能を選択します。
![trans.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584443/d7b68e89-1ee5-4405-c6ee-c26e35f7260c.png)

4. 保存します。
![trans2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584443/0ad50cb0-2b7b-e8ce-b7db-288bd5f7caf6.png)

##Speech-to-text APIを使おう(未完)
###  [1] 素材の用意
1時間のmp4動画の音声を抜き出し、FLC (モノラル/16000Hz/16bit)にするものを探す。
（ffmpeg でやればよかったと今更気づく）

動画から音声の抽出
- 動画が長すぎてオンラインでは使えない
- アプリを7つ程試したけれどうまく動画と音声を分離できなかった。
- [EaseUS Video Editor](https://jp.easeus.com/multimedia/video-editor.html "EaseUS Video Editor") の使用版でmp3に書き出し


mp3 からflacへの変換 （色々試したがなかなかうまくいかず...）
- AV Audio Converter
- https://www.freac.org/

###[2] GCP環境で実行
参考：https://qiita.com/knyrc/items/7aab521edfc9bfb06625
1.GCPでSpeech-to-textのAPIを有効にする。
　https://console.cloud.google.com/
　https://console.cloud.google.com/apis/api/speech.googleapis.com
2. サービスアカウントを設定し、秘密キー（JSON）を作成
3. JSONキーをダウンロード
4. コンソールから JSONをアップロードし、環境変数に設定
5. Bucketを作成し、音声ファイルをアップロード 
6. Python を実行。-> Python3でやりなさいエラー -> Python3で実行 ->import speechでエラー
->投げ出す

調べていたらもっと楽な方法を見つけてしまい解決せずに投げ出しましました。
LLVMで unsupported GC: shadow-stack が出た場合の解決方法

LLVMを用いてGCを実装しようとした際、以下のエラーが発生した。

```
LLVM ERROR: unsupported GC: shadow-stack (did you remember to link and initialize the CodeGen library?)
```

`llvm/CodeGen/LinkAllCodegenComponents.h`をIncludeして、`    llvm::linkAllBuiltinGCs()`を事前に呼び出すことで解決した。

# 参考

https://llvm.org/doxygen/LinkAllCodegenComponents_8h_source.html
http://llvm.1065342.n5.nabble.com/unsupported-GC-shadow-stack-when-using-MCJIT-td79766.html
WGAN-GPで導関数が非連続な活性関数を使ってよいのか

# 疑問

ある日ふと思いました。
WGAN-GPのGradient Penaltyは非連続関数の最適化をしてるのではないかと


WGAN-GP損失関数に以下のような Gradient Penalty を追加しています。

```math

\mathbb{E}_{\hat{x}~\mathbb{P}_\hat{x}}[(\|\nabla_x D(\hat{x})\|_2 - 1)^2]

```

この式には Discriminator を微分した結果が含まれます。そこで気になるのは、Discriminator の中では一般的に LeakyReLUが使われている点です。

LeakyReLUの導関数は連続ではありません。したがって Gradient Penalty の最適化では不連続な関数の最適化を勾配法で行っていることになります。

勾配法で非連続な関数を最適化するのは無理があるように思えたので導関数が連続している活性関数を利用することで性能が向上しないかなと試してみました。

# 結論

性能は向上しませんでした。

今回実験した範囲では生成画像の質自体は滑らかな活性関数である Swish を使った場合劣化しています。

また、よく考えると当たり前ですが、LeakyReLUで普通に学習すると普通に画像を生成できるようになります。
最初に非連続なことが原因でうまくいかない事例を探すところから始めないと、検証になりませんでした・・・


# 実験

WGAN-GPのDiscriminatorで活性関数を切り替えて性能を確認してみました。
利用した活性関数は以下の通りです。

- LeakyReLU
- ReLU
- Swish

このうち導関数が連続なのは Swish のみです。

データはMNISTを利用しました。

実験につかったコードは以下の通りです。

- https://gist.github.com/hatonosuke/2ec965fcbd9a82f05a34b690be7affa1

実行は Google Colab で行いました。

損失は次の通りです。

Discriminatorの損失

![D_cost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494948/024526bb-4663-6e50-c91d-8d46d86fb9c8.png)

Gradient Penalty

![gp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494948/c3d577ba-79f8-f0e6-62ca-0476dac4ba2e.png)

Generatorの損失

![G_cost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494948/54554983-37b0-1009-f704-ab831c5a9962.png)

FIDを次の通りです。

| 活性関数  |  FID    |
|:--------|---------:|
| LeakyReLU | 24.74 |
| ReLU | 26.46 |
| Swish | 36.07 |

- LeakyReLUとReLUでは損失がほぼ重なっています。Swishのみ損失値の動きが異なります。
- Swishを使った場合の方が Gradient Penalty が大きくなっています。
- FIDを比較すると Swish のみ大きく性能が悪くなっています。

事前の予想と異なり、 滑らかな活性関数を利用しても性能は向上しませんでした。

以上です。
Google Cloud Funtions で puppeteer v3.0.0 以降が使えない

# 追記 : 2021/07/13

> Node.js 14 / puppeteer ver 10.1.0 で試したら使えるようになってました。  
> 詳細は追ってません  

Google Cloud Funtions の環境に [libgbm1が入ってないかららしい](https://github.com/puppeteer/puppeteer/issues/5704#issuecomment-626873725)。

- [issues #5704](https://github.com/puppeteer/puppeteer/issues/5704) : v3.0.0がGoogle Cloud Functionsノード10ランタイムで機能しない

2020/06/09 に あと2週間くらいで反映されるような[コメントがあった](https://github.com/puppeteer/puppeteer/issues/5704#issuecomment-640752512)けど 2020/07/08 時点でまだ使えてるようになってない

> We are still pending the roll out of the change. It's expected in 2 weeks.
> 
> in the meantime, you should be able to run v3.0.0 on Cloud Run, which allows you to bring a  container that would have the missing OS package libgbm1.


nodejs12にアップグレード動いたっていう[コメントもある](https://github.com/puppeteer/puppeteer/issues/5704#issuecomment-643663365)

> Ran into the same issue, and got it working by upgrading to `nodejs12`

firebaseはできない。GCPのみ
複合PK（制約）を変更したい場合（メモ用）

制約を一度削除しないと、変更できなかったのでメモ

制約削除
ALTER TABLE テーブル名 DROP CONSTRAINT 制約名;

制約作成
ALTER TABLE テーブル名 ADD CONSTRAINT 制約名 PRIMARY KEY (カラム名1, カラム名2, カラム名3);

制約名はpgAdminでテーブル開いて確認
【JavaScript】イベント

#はじめに

自分の勉強用メモとして残しています。

#イベントとは

JavaScriptにおける「イベント」とは、Webページ上で発生するあらゆるアクションの総称です。

例えば、ボタンのクリック、フォームへの入力、ページの読み込み、マウスポインタを要素の上に合わせるなど、様々な出来事がページ上で発生します。

イベントハンドラとは
ハンドラとは英語のhandlerであり動詞handle（扱う）から由来しています。

JavaScript様々なイベントの発生下タイミングで処理を行うことが出来ます。
例えば、ボタンがクリックされた際に画像を切り替える、ページが読み込まれた際に何かを表示させる、など。
このようなイベントの処理を行うのが「イベントハンドラ」の役目です。

「on」キーワードの隣にイベント名をくっつけたものがイベントハンドラのネーミングパターンとなっています。


#イベントハンドラの一覧

| イベントハンドラ | 説明 |
|:--|:--|
| onBlur | ページやフォーム要素からフォーカスが外 れた時に発生 |
| onFocus | ページやフォーム要素にフォーカスが当 たった時に発生 |
| onChange | フォーム要素の選択、入力内容が変更され た時に発生 |
| onSelect | テキストが選択された時に発生 |
| onSubmit | フォームを送信しようとした時に発生 |
| onReset | フォームがリセットされた時に発生 |
| onLoad | ページや画像の読み込みが完了した時に発 生 |
| onClick | 要素やリンクをクリックした時に発生 |
| onDblClick | 要素をダブルクリックした時に発生 |
| onKeyUp | 押していたキーをあげた時に発生 |
| onKeyDown | キーを押した時に発生 |
| onMouseOut | マウスが離れた時に発生 |
| onMouseOver | マウス乗った時に発生 |
| onMouseUp | クリックしたマウスを上げた時に発生 |
| onMouseDown | マウスでクリックした時に発生 |
| onMouseMove | マウスを動かしている時に発生 |


##参考例

onclick (要素がクリックされた時)を例に挙げてみます。


###HTML属性から発火

HTML要素にはイベント属性というものがあり、そこに対応するイベントハンドラとJavaScript内の実行したい関数名を設定することで、要素に設定したイベントによって関数を実行できます。

```html:html

<p id="testid" onclick="test()"> 要素がクリックされた時にイベント発火</p>
```

```javascript:js
function test() {
  console.log("クリックされました！");
}
```


###イベントリスナーから発火

同じ要素の同じタイプのイベントに複数の処理の登録が出来ないので、
イベントを複数指定したい場合はこちらの方法を使いましょう。

JS側で取得した要素.addEventListener(イベント名, 関数);

```html:html
<p id="testid"> 要素がクリックされた時にイベント発火</p>
```

```javascript:js
var elem1 = document.getElementById("testid");
elem1.addEventListener("click", function(){
  console.log('クリックされました！（イベントリスナー）');
});
```


該当要素をクリックして、クリックしたタイミングでコンソールログが表示されれば、成功です。
CentOS8で簡易ルーターを作成する手順

# はじめに
## この手順は何？
独立したセグメントを作りたかったので簡易ルーターが必要になった。
その時に作った簡易ルーターの作成手順＋補足

## 作成環境
ルーターになるサーバーにCentOS8.2を最小構成でインストール
NICは必要なセグメント数分用意してそれぞれ必要に応じたIPアドレスを設定
※VyOSとかでも良かったけどセグメント分けられれば良かっただけなので、とりあえずCentOS8で作った。
※多分CentOS7でも同じ手順で動くと思う。

# 1.カーネルパラメタ設定

~~~
# cat << EOF > /etc/sysctl.d/router.conf
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 1
EOF

# sysctl --system
~~~

※「net.ipv4.ip_forward = 1」はパケットのフォワードを許可
※「net.ipv4.conf.all.rp_filter = 1」スプーフィング(プライベートアドレスの詐称)対策

# 2.firewalldをiptablesに切り替え
※切り替えは必須ではないので手順省略は可

~~~
# systemctl stop firewalld
# systemctl disable firewalld
# yum install -y iptables-services
# systemctl enable iptables
# systemctl enable ip6tables
# systemctl restart iptables
# systemctl restart ip6tables
~~~

# 3.iptablesのルールの修正
※firewalldの場合はfirewalld-cmd等で同等の内容を実施

## 3.1.ルールのバックアップ
~~~
# cp -p /etc/sysconfig/{iptables,iptables_bak}
~~~

## 3.2.ルールの修正
※ルーターとなるサーバ自体へのアクセスルール(INPUT)は変えない。(変える必要があれば必要に応じて実施)
　パケットの転送(FORWARD)を破棄から許可に変更する。

~~~
# vi /etc/sysconfig/iptables

以下を修正
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
  ↓
-A FORWARD -j ACCEPT
~~~

## 3.3.ルールの反映

~~~
# systemctl restart iptables
~~~

# 4.必要に応じてルーティングを設定
nmtui、nmcli 等を使用して必要に応じてルーティングを設定
jupyter notebookをリモート(非LAN環境)で利用

## やりたいこと
自宅のPCから高性能GPU搭載サーバ上(非LAN環境)でJupyter Notebookを起動し、プログラムの実装、実行したい。

## 本文における想定環境
下図のような環境を想定する。GPUサーバは踏み台サーバからしかアクセスできない。
![jupyter-server.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287300/7cbaa917-dbd6-0e9b-9af3-0803b07e8cd6.png)

## 環境
### 手元のPCの環境
- Mac OS Catalina 10.15.4
- Google Chrome 83.0.4103.116
- Proxy Switchy Omega 2.5.21
- Safari 13.1

### GPUサーバの環境
- Ubuntu 18.04 LTS
- Python 3.6.8
- pip 20.0.2

## GPUサーバでの設定
まず、GPUサーバにjupyter notebookをインストールする。

```zsh
$ pip3 install jupyter
```

その後、`ipython`を起動すると対話型モードが開く

```
$ ipython
Python 3.6.8 (default, Mar 11 2020, 10:09:18)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.
```

`ipython`の対話型モードで以下のようにコマンドを実行する。

```python
In [1]: from notebook.auth import passwd
In [2]: passwd()
Enter password: [パスワードの入力]
Verify password: [パスワードの再入力]
Out[2]: [ハッシュ化済パスワード]
```

続いて設定ファイルを作成する。

```zsh
$ jupyter notebook --generate-config
```

デフォルトでは `~/.jupyter/jupyter_notebook_config.py` というファイルが生成される。このファイルを以下のように編集する。

```python:~/.jupyter/jupyter_notebook_config.py
c = get_config()
# Notebook上でplotを表示できるようにする
c.IPKernelApp.pylab = 'inline'
# 受け付けるIPアドレス
c.NotebookApp.ip = '0.0.0.0'
# IPython notebookのログインパスワード
c.NotebookApp.password = [作成済みのハッシュ化済パスワード]
# 起動時にブラウザを起動させるかの設定
c.NotebookApp.open_browser = False
# ポート指定
c.NotebookApp.port = 8888
```

受け付けるIPアドレスはデフォルトでは'localhost'となっているが、これを0.0.0.0にしてあげればよい。これはすべてのIPアドレスからのアクセスを受け付けるという意味であり攻撃を受ける可能性があると考えるかも知れないが、もともと踏み台サーバからしかアクセス出来ないため問題ない。
これで設定が完了したので、以下のコマンドを叩くことでjupyter notebookサーバが立ち上がる。

```zsh
$ jupyter notebook
```

## 手元のPCの設定
踏み台サーバをプロキシサーバとしてインターネットアクセスするように手元PCの設定を変更する必要がある。
まず、手元のPCから踏み台サーバにダイナミックポートフォワードでアクセスする。

```
$ ssh -D 10080 1.2.3.4
```

このあとWebブラウザをプロキシ経由でアクセスできるようにするには以下の2つの方法が挙げられる。
1. システム環境設定を利用 (Safari)
2. Proxy SwitchyOmegaを利用 (Google Chrome)

### 1. システム環境設定を利用 (Safari)
Mac上の`システム環境設定`->`ネットワーク`->`詳細`->`Socksプロキシ`を設定する。Socksプロキシにチェックを入れ、以下のように設定する。
<img width="666" alt="スクリーンショット 2020-07-08 11.24.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287300/fa5b038a-e36f-41e0-aa5d-40e22fc22dc4.png">

設定後、Safariのアドレスバー(URLを入力するところ)に`http://10.1.2.3:8888`と入力するとjupyter notebookを開くことが出来る。

### 2. Proxy SwitchyOmegaを利用 (Google Chrome)
Chrome拡張機能からProxy SwitchyOmegaをインストールする。
<img width="307" alt="スクリーンショット 2020-07-08 11.45.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287300/a88645d7-14ff-fd15-fc55-3f4d26cc3e48.png">

上の画像からOptionsをクリックすると以下の設定画面が取得できるので、以下のように設定する。
<img width="800" alt="スクリーンショット 2020-07-08 11.43.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287300/840b490f-1175-4d9b-7e8f-99161e0cd6ce.png">

設定後、1枚目の画像からProxyを選択することでプロキシの設定が完了する。
その後、Google Chromeのアドレスバーに`http://10.1.2.3:8888`と入力するとjupyter notebookを開くことが出来る。
Danger用にxcpretty-json-formatterを実行して ld: symbol(s) not found for architecture x86_64  になった時には-fprofile-arcsを追加する

## 環境
- Xcode11.3.1, CocoaPods1.5.3, FirebaseCore6.6.6 

## 現象
BitriseのWorkflow内でDangerを回している際に
xcpretty-json-formatterの出力を指定した以下のスクリプトでテストビルドを実行
すると「 ld: symbol(s) not found for architecture x86_64 」のエラーが発生した。

```shell
set -o pipefail && env "NSUnbufferedIO=YES" xcodebuild -workspace $WORKSPACE -scheme $SCHEME \ 
clean build test -destination "platform=iOS Simulator,name=iPhone Xs,OS=12.4" \
GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES | \ 
XCPRETTY_JSON_FILE_OUTPUT=xcodebuild.json xcpretty -f `xcpretty-json-formatter`
```
<img width="778" alt="スクリーンショット 2020-07-08 11.00.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6691/5f7cd3a7-fe0e-7f5f-6e4d-df9ee2397e2d.png">

## 対応内容 

`Build Settings > Other Linker Flags` に `-fprofile-arcs`を追加

スクリプトは以下に変更

```shell
set -o pipefail && env "NSUnbufferedIO=YES" xcodebuild -workspace $WORKSPACE -scheme $SCHEME \ 
clean build test -destination "platform=iOS Simulator,name=iPhone Xs,OS=12.4" \ 
"GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES" "GCC_GENERATE_TEST_COVERAGE_FILES=YES" \
"OTHER_LDFLAGS=\$(OTHER_LDFLAGS) -fprofile-arcs" | \ 
XCPRETTY_JSON_FILE_OUTPUT=xcodebuild.json xcpretty -f `xcpretty-json-formatter`
```

## 参考リンク
助けて頂きました。ありがとうございます🙏

- [Problems using GCC_INSTRUMENT_PROGRAM_FLOW_ARCS and Firebase/Core #2235](https://github.com/firebase/firebase-ios-sdk/issues/2235)
- [Firebase/Coreをcocoapodで入れたらUITestが通らなくなった](http://harumi.sakura.ne.jp/wordpress/2019/04/20/firebase-core%E3%82%92cocoapod%E3%81%A7%E5%85%A5%E3%82%8C%E3%81%9F%E3%82%89uitest%E3%81%8C%E9%80%9A%E3%82%89%E3%81%AA%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F/)
- [Clang Code Coverage - Mac OS X - Linker Error](https://stackoverflow.com/questions/19290946/clang-code-coverage-mac-os-x-linker-error/39579344#39579344)
Wordpress サイトの検索結果を「カスタム投稿のみ」「カスタムフィールドで並び替え」にする

# Wordpress サイトの検索結果を「カスタム投稿のみ」「カスタムフィールドで並び替え」にする

Wordpress サイトのカスタマイズでサイト内検索の結果を「カスタム投稿のみ」「カスタムフィールドで並び替え」られたものにしたいと要望を受けた際の対応のメモ。

## 結果
　　　　　　　　　　　　　　　　　　　　　　　　　
functions.php で `pre_get_posts` と `posts_search` をフックに処理かませた。

```php
function post_type_filter_and_sort( $query ) {
	if ( !is_admin() && $query->is_main_query() && $query->is_search() ) {
		$query->set( 'post_type', 'カスタム投稿タイプ名' );
		$query->set( 'orderby', 'meta_value' );
		$query->set( 'meta_key', 'ソートしたいフィールド名' );
		$query->set( 'order', 'ASC' );
		$query->set( 'posts_per_page', $posts_per_page );
	}
	return $query;
}
add_filter( 'pre_get_posts', 'post_type_filter_and_sort' );

function title_filter( $search, $query ) {
	global $wpdb;
	if (
		!is_admin() &&
		$query->is_main_query() &&
		$query->is_search() &&
		isset( $query->query_vars[ 'search_terms' ] )
	) {
		$terms = $query->query_vars[ 'search_terms' ];
		$search = "AND post_type = 'カスタム投稿タイプ名'";
		$sql_operator = "AND";
		foreach ( $terms as $term ) {
			if ( !empty($term) ) {
				$search_term = '%' . esc_sql( $term ) . '%';
				$search .= " {$sql_operator} ({$wpdb->posts}.post_title LIKE '{$search_term}')";
				$sql_operator = "OR";
			}
		}
	}
	return $search;
}
add_filter( 'posts_search', 'title_filter', $posts_per_page, 2 );
```

`pre_get_posts` にフックしてタイトルのみを検索対象に含める処理ができず、
`ORDER BY～` 追記するなど試したがなど試したが、
`posts_search` にフックして並び替えをすることもできなかった。

結果合わせ技にして実装。

## 参考

[pre_get_posts | Hook | WordPress Developer Resources](https://developer.wordpress.org/reference/hooks/pre_get_posts/)
[posts_search | Hook | WordPress Developer Resources](https://developer.wordpress.org/reference/hooks/posts_search/)

## 環境

PHP: 7.1.32
mysql: 5.6.23
WordPress: 5.4.2

### プラグイン

* [Custom Post Type Permalinks 3.3.5](https://github.com/torounit/custom-post-type-permalinks)
* [Advanced Custom Fields 5.8.11](https://www.advancedcustomfields.com/)
* [Custom Post Type UI 1.7.4](https://github.com/WebDevStudios/custom-post-type-ui/)
「Not a binary MAT-file.」のデバッグ方法【MATLAB】

はじめまして、ますみです！

[![自己紹介.png](https://www.umi-mori.jp/wp-content/uploads/2023/02/introduction_banner_2-2048x533.png)](https://bit.ly/banner_intro_masumi_creator_qiita)


# バグ内容
`.mat`ファイルをMATLABで読み込む際に、以下のようなエラーが出る時があります。

原因としては、以下のようなことが考えられます。
・ファイルの破損
・バイナリじゃないファイルのmatファイルへの変換
・octaveで生成された事による互換性の問題

```matlab:error.m
>> load('design.mat')
Error using load
Unable to read MAT-file /Users/masumi_morishige/design.mat. Not a binary MAT-file. Try load -ASCII to read as text.
```

# デバッグ方法
1. ファイルの拡張子をcsvへ変更
2. 区切り文字を指定して、読み込み

```matlab:debug.m
movefile('design.mat', 'design.csv');
x = readmatrix('design.csv', 'Delimiter', ' ');
```

少し邪道に思えるかもしれませんが、この方法でおそらく大抵の場合は解決すると思います。

# 最後に
最後まで読んでくださり、ありがとうございました！
いかがだったでしょうか？

この記事を通して、少しでもあなたの学びに役立てば幸いです！

:::note info
【仕事の相談はこちら】
お仕事の相談のある方は、下記のフォームよりお気軽にご相談ください。

[問い合わせフォームはこちら](https://forms.gle/G5g1SJ7BBZw7oXYA7)

もしもメールでの問い合わせの方がよろしければ、下記のメールアドレスへご連絡ください。

info*galirage.com（*を@に変えてご送付ください）

🎁 「生成AI活用の無料相談券」もしくは「生成AIの社内ガイドライン（無料PDF）」を『公式LINE』で配布中 🎁
『生成AIを業務に活用したいけど、どうしたらいいかわからない』といった声を多くいただきます。

Galirageでは公式LINEにて、チャットやオンライン会議で「完全個別の生成AI活用無料相談会」を実施しております！
（期間限定で実施しているため、ご興味ある方はお早めに以下のLINE公式アカウントをご登録ください^^）
https://lin.ee/rvz6lMN

※ 予告なく、キャンペーンを終了する可能性がございますが、ご了承ください。

【業務内容】
具体的には、以下のお仕事を中心に受け付けております！（[詳しくはこちら](https://galirage.notion.site/Galirage-AI-c2f3945fafb0433d8d2fd03e56927fd8)）
1. 受託開発（例：生成AIを使った社内システムの開発）
2. コンサルティング（例：技術戦略のアドバイス）
3. 講演（例：社内研修、イベント登壇）

※ 特に「生成AIを使ったシステム開発のご依頼」が多く、ご好評いただいております。

【これまでの相談事例】
以下のようなご相談が多くあります。

🔑 機密情報を漏洩させないための、生成AIのシステム構築をお願いしたい。
🤖 自社データを用いたFAQチャットボットの作り方を知りたい。
💡 ChatGPTを、自分たちの事業にどのように活かせるか、アドバイスやアイデアが欲しい。
:::
# おまけ
エンジニアの仲間（データサイエンティストも含む）を増やしたいため、公式LINEを始めました🎉

「**一緒に仕事をしてくれる方**」「**友だちとして仲良くしてくれる方**」は、友だち追加をしていただけますと嬉しいです！（仲良くなった人たちを集めて、「ボードゲーム会」や「ハッカソン」や「もくもく会」もやりたいなと考えています😆）

とはいえ、みなさんにもメリットがないと申し訳ないので、特典を用意しました！

友だち追加後に、アンケートに回答してくれた方へ「**エンジニア図鑑（職種20選）**」のPDFをお送りします◎

https://lin.ee/hFUN4TL

[![](https://www.umi-mori.jp/wp-content/uploads/2023/10/line_banner_v2.png)](https://lin.ee/hFUN4TL)
【初心者向けチュートリアル】Boltを使用してUnityで簡単なゲームを作成する-7

こちらの記事では**アイテムのPrefab化～アイテムの種類を増やす**を行います。

#アイテムのプレハブ化

今回の記事は少し簡単な内容です。

前回少し触れましたが、今回はアイテムの種類を3種類に増やしてみたいと思います。
そのために便利なのが**Prefab**です。
Prefabとは、オブジェクトとそれに関する設定をひとつにまとめたものです。同じオブジェクトを複製したいときにはPrefab化しておくと便利です。

実際に作ってみましょう。
Assetsフォルダ内に「Prefabs」という名前のフォルダーを新規作成しましょう。
作成したフォルダの中にStrawberryオブジェクトをドラッグ&ドロップしてみます。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654796/219b5564-70ac-9cb3-1692-1fc4ce384248.png)
このようにフォルダ内でStrawberryがサムネイル表示されるようになったと思います。
これでStrawberryのPrefabができました。このStrawberryをSceneウィンドウに適当にドロップすると簡単に量産できます。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654796/b1bfef86-02fc-3dfd-56f6-af3d3c551083.png)
わーい！
これでPrefab化は完了です。

#アイテムの種類を増やす
次に、Prefabを活用してイチゴ以外にもオレンジ、メロンのアイテムを作っていきます。

Hierarchy内Strawberryを選択>名前を「Orange」に変更>Inspector内SpriteRendererからSpriteをOrangeに変更
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654796/d4e53a7f-f463-f432-b194-5f168da467cd.png)
Rigidbody2DからGravityScale(重力により影響を受ける度合い)を「0.5」に変更
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654796/b2c65a50-02bc-9a28-169e-36d0843d785f.png)
VariablesからpointのValueを「30」に変更
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654796/5cd675b0-7068-e217-6a88-e13155b7e346.png)
ここまで終わったらこのOrangeもProjectにドロップしてPrefab化します。
ドロップすると新しいPrefabを作成しますか?といった内容のメッセージが出ますので、OriginalPrefabをクリックしましょう。

これでOrangeという新しいアイテムが出来ました！
同じ手法でMelonも作成してみましょう。GravityScaleは「0.7」に、pointのValueは「50」にしてください。

Sceneにそれぞれ配置して再生してみましょう。
![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654796/58d24a2b-33c0-2780-36b4-66e9b504bd29.gif)
アイテムごとに挙動が変わるようになっていますね。

これでアイテムの種類を増やすことができました。

今回のチュートリアルはここまでです。お疲れさまでした！
次回は**制限時間の設定**をやっていきます。
[【初心者向けチュートリアル】Boltを使用してUnityで簡単なゲームを作成する-8](https://qiita.com/mma/private/64d9349991f49f6c96ec)
ArrayListを使ったバブルソート（JAVA)


```java
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        //ArrayListのlistを宣言
        ArrayList<Integer> list = new ArrayList<Integer>();
        //countは繰り返し回数
        int count = 0;
        count = scanner.nextInt();
        
        //listに入力値を格納
        for (int i = 0; i < count; i++) {
            list.add(scanner.nextInt());
        }
         //ArrayListのバブルソート
         for (int i = 0; i < list.size() - 1; i++) {
            for (int j = list.size() - 1; j > i; j--) {
                if (array.get(j - 1) > list.get(j)) {
                    // 入れ替え
                    int tmp = list.get(j - 1);
                    list.set(j -1, list.get(j));
                    list.set(j, tmp);
                }
             }
        }
        //拡張for文
        for(int a: list) {
            System.out.println(a);
        }      
    }
}
```
Vue.jsでページ離脱前に確認ダイアログを出す

編集中のものがあったりして、保存されませんが、続けますか？という確認をするあれです。
Nuxt.jsで書きます。

## ブラウザを閉じたり、リロードしたりしたとき

```js

export default {
  created () {
    window.addEventListener("beforeunload", this.confirmSave);
  },
  destroyed () {
    window.removeEventListener("beforeunload", this.confirmSave);
  },
  methods: {
    confirmSave (event) {
      event.returnValue = "編集中のものは保存されませんが、よろしいですか？";
    },
  }
}
```

もし、編集されている時だけ出す、のような分岐をする場合は、

```js
    confirmSave (event) {
      if (this.formChanged){
        event.returnValue = "編集中のものは保存されませんが、よろしいですか？";
      }
    },
```

`returnValue`で設定したメッセージを表示できるのはIEだけのようです。

## 違うページに遷移しようとしたとき

```js
export default {
  beforeRouteLeave (to, from, next) {
    const answer = window.confirm("編集中のものは保存されませんが、よろしいですか？")
    if (answer) {
      next()
    } else {
      next(false)
    }
  },
}
```

編集されている時だけ出す場合は、

```js
export default {
  beforeRouteLeave (to, from, next) {
    if (this.formChanged){
      const answer = window.confirm("編集中のものは保存されませんが、よろしいですか？")
      if (answer) {
        next()
      } else {
        next(false)
      }
    } else {
      next();
    }
  },
}
```

`beforeRouteLeave`を使うときは、`next()`が必須です。どこにも遷移できなくなります。
また、`beforeRouteLeave`はルートコンポーネントにしか書けないようで、サブコンポーネントに書いても呼ばれません。
mixinに書くのは問題ないです。

サブコンポーネントに記述をまとめている場合はちょっと面倒ですが、コンポーネントの参照を使って書くことができます。

ルートコンポーネント

```vuejs
<template>
  <sub-component ref="subComponent" />
</template>

<script>
export default {
  beforeRouteLeave (to, from, next) {
    if (this.$refs.subComponent.formChanged){
      const answer = window.confirm("編集中のものは保存されませんが、よろしいですか？")
      if (answer) {
        next()
      } else {
        next(false)
      }
    } else {
      next();
    }
  },
};
</script>
```

コンポーネントの参照は、メソッドも可能なので、基本的に出来ないことはなさそうです。
ルートコンポーネントだけでしか使えないことがちょっと使いづらいかもしれません。

## 参考
https://blog.hirokiky.org/entry/2019/08/22/111031
https://ja.coder.work/so/vuejs2/724205
https://router.vuejs.org/ja/guide/advanced/navigation-guards.html
SQLSTATE[HY000] [1044] Access deniedでハマった時に見てください

PDOを使ってMySQLデータベースに接続しようとした際にハマったので少し調べてみました。

# ハマった時の状況
## 出たエラー
【接続失敗】SQLSTATE[HY000] [1044] Access denied for user 'takeshi'@'%' to database 'testdb'

## PHP
「takeshi」というユーザーでMySQLの「testdb」というデータベースに接続しようとしています。

```php
<?php
$host = "db";
$dbname = "testdb";
$user = 'takeshi';
$password = 'brock';
$dsn = 'mysql:host='.$host.';dbname='.$dbname.';charset=utf8';

try {
    $dbh = new PDO($dsn, $user, $password);
    echo "【接続成功】";
} catch (PDOException $e) {
    echo "【接続失敗】" . $e->getMessage();
    exit();
}
```

## MySQL
### takeshiの権限
「leader」というロールを与えています。

```
mysql> show grants for takeshi;
+-------------------------------------+
| Grants for takeshi@%                |
+-------------------------------------+
| GRANT USAGE ON *.* TO `takeshi`@`%` |
| GRANT `leader`@`%` TO `takeshi`@`%` |
+-------------------------------------+
```

### leaderロールの権限
testdb内のすべてのテーブルに対してSELECT, INSERTが可能な権限を与えています。

```
mysql> show grants for leader;
+----------------------------------------------------+
| Grants for leader@%                                |
+----------------------------------------------------+
| GRANT USAGE ON *.* TO `leader`@`%`                 |
| GRANT SELECT, INSERT ON `testdb`.* TO `leader`@`%` |
+----------------------------------------------------+
```

# 解決方法
## SET DEFAULT ROLEする
ロールは付与しただけでは意味がないようで明示的に有効化する必要がありました。

```
mysql> set default role leader to takeshi;
```

## ロールを使わない
ロールを使わずにleaderと同等の権限をtakeshiに与えるだけです。

```
mysql> grant select, insert on testdb.* to takeshi;
```

# おわりに
今回はSELECTとINSERTの権限を与えていますが、データベースレベルの権限([参考URL](https://dev.mysql.com/doc/refman/5.6/ja/grant.html#grant-database-privileges))なら何でも良さそうな雰囲気なので用途に合わせて変えてください。
いくら練習といえどALL権限与えるのは乱暴すぎると思うのでやめたほうがいいと思います。
pythonのclassを使って、自給農家の生産・消費行動を超ざっくり簡単にシミュレーションしてみる①　条件設定

今回は自給的農家のシミュレーションを作ってみました。
①では設定の説明をし、次回の[②](https://qiita.com/kuru_kirino/items/79537e674ad309a9ca96)でコードを説明します。
農家行動の理論的な説明は今回省きました（本当は書きましたが、読むのがかったるいから消しました泣）。

##今回やりたいこと
前回は、1農家と1消費者が存在して、市場を介して2者が農産物の生産と消費を行うシミュレーションを行いました。価格の変動を表すために、前期消費量の多い作物の価格が約1.01倍上昇し、前期消費量の少ない作物の価格が約0.99倍低下することにしました。
しかし、①次期価格を算出する際に均衡価格を計算しなかった点、②生産消費行動の影響を受けて価格が変動→生産消費行動の変化→価格が変動…というループが起こり、価格や生産・消費量が安定しなかった点
で問題が生じたので、今回は価格変動を単純化しました。
また、新しい要素として、今回は「自給農家行動」をシミュレートしてみます。


以上の状況を反映させるために、以下のステップを踏みました。
①class「Autarky（自給的）」を作る。
②初期価格で価格を固定して生産・消費行動をさせてみる。
③換金作物の価格増加後の反応をみる。
④消費財の価格低下後の反応をみる。
⑤換金作物の価格増加、尚且つ消費財の価格低下後の反応を見る。


##自給的農家に関する理論
日本には自給農家があまりいないので、自給農家の存在理由が意味不明だと思います。しかし、一定の条件下では自給的農家が生じる可能性があります。その理論を説明しようと思いましたが、長いのでやめました。詳しくはJanvry(1991)を見てください。
まあ、ざっくりいうと、市場参加が困難な自給的農家は自分が食べる主要穀物を自分で作るということです。


##クラス（登場人物の説明）
###クラスAutarky(自給農家)
特徴1: 
自給的穀物Aと換金作物Bを生産する。
特徴2: 
労働力と固定資本という生産要素を自家保有しており、AとBの生産に振り分ける。また、労働力の一部は農外労働に振り分けて賃金を得る。
特徴3: 
①ランダムに生産要素を振り分けてAとBを生産し農業収入を得て、同時に農外労働によって農外賃金も得る。②農業収入と農外賃金に基づいて嗜好品oを購入し、その時の効用を計算する。③指定回数①と②を繰り返し、効用が最も大きかった時の生産要素配分を記録する。

##クラスMarket（価格変動を起こす神のような存在）
特徴1:
換金作物Bの値段を50円上げる。
特徴2:
嗜好品oの値段を50円下げる。


##生産関数と利潤関数と効用関数
###生産関数
```math
Q_A = 3*L_A^{0.3} +K_A^{0.7} \\Q_B=1*L_B^{0.7} +K_B^{0.3}
```
L: 労働力(L=LA+LB+Ln+l)
K: 固定資本(K=KA+KB)
※Aは穀物、Bは換金作物です。一般的に、穀物は資本集約的であり、園芸品目などの換金作物は労働集約的だと思うので、以上のようなパラメータ設定にしました。

###利潤関数
```math
\Pi = p_B*Q_B+w*L_n
```
Ln: 農外労働に費やした労働力
w: 農外賃金
pB: Bの価格
QB: Bの生産量

###効用関数
```math
U = Q_A^{0.2}+C_o^{0.45}+l^{0.35}
```
QA: Aの生産量（自給量）
Co: Netflix等の嗜好品の消費量
l: 余暇時間（l = L-LA-LB-Ln）
※パラメータは適当にそれっぽく割り振りました。また、予算制約（po*Cp < π）が満たされています。

##価格の変化
1~10期：初期価格で効用最大化を行う
11~20期:Bの価格が50上昇して、効用最大化を行う
21~30期:oの価格が50低下して、効用最大化を行う
31~40期:Bの価格が50上昇し、尚且つoの価格が50低下して、効用最大化を行う

##締めの言葉
以上の条件設定の下、シミュレーションしてみました。
色々と細かく改良したい点は多いですが、少しずつ進めていきましょう。
なお、先取りして今回のシミュレーションの問題を言っておくと、ズバリ最適化問題のやり方です。
じゃあ、また次回あいましょう。

##参考文献
～論文～
[1]Alain de Janvry, Marcel Fafchamps and Elisabeth Sadoulet(1991) “Peasant household behavior with missing markets: some paradoxes explained” Economic Journal. Vol.101, pp.1400-1417.
ベイヤー FITS ファイルをデモザイクしてカラー TIFF に変換する

macOS や Linux には FITS ファイルを変換する手軽なツールがありません。
Python を利用してベイヤー FITS ファイルをデモザイクし、Photoshop などで編集できる TIFF 形式に変換する方法を紹介します。

## 撮影環境

- カメラ
    - ZWO ASI 294MC
- 制御ソフト
    - KStars + Ekos

ZWO ASI 294MC のベイヤーパターンは RGGB です。

## 環境構築

FITS ファイルの読み込みに [Astropy](https://www.astropy.org/)、画像処理に OpenCV を利用します。
執筆時のパッケージバージョンは下記の通りです。

- anaconda3-2020.02
- opencv (4.1.0)
- astropy (4.0.1.post1)

## 処理

望遠鏡で撮影した月面の画像 (`moon.fits`) を処理してみます。

### 1. FITS ファイルオープン

```py
from astropy.io import fits

hdul = fits.open('moon.fits')
src = hdul[0].data
```

この段階ではベイヤー配列のままなので、モノクロのモザイク画像です。

<img width="452" alt="test3-bayer_tif.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15173/1931741f-70c8-107f-ca5b-e464bdee533f.png">

### 2. デモザイク・保存

`cvtColor` 関数でベイヤー変換を指定することで、カラー画像を復元します。

```py
import cv2
dst = cv2.cvtColor(src, cv2.COLOR_BayerBG2BGR)
cv2.imwrite('moon.tif', dst)
```

下記の TIFF 画像が出力されました。
任意の画像編集ソフトで明るさやカラーバランスを調整することができます。

![moon.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15173/78794281-0be3-38cf-e61d-362d61b8d959.jpeg)

### 3. Photoshop での編集例

レベル補正・カラーバランス調整を行い、シャープフィルタを適用したものです。

![moon-edited.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15173/0a47e607-d833-db13-d20f-3bd1fced448c.jpeg)
form_withのform.〇〇について

##form_withのform.〇〇について

form.withのform.〇〇について、わからないところがあったので、備忘録としてまとめていく。

###form.text_field

```ruby:
<%= form.text_field :title %>
```
幅２０文字の入力欄が設定される


###form.text_area

```ruby:
<%= form.text_area :content %>
```
40×20の入力欄が設定される

###form.email_filed

```
<%= form.email.field :email %>
```
投稿内容に@が含まれていないとメールアドレスとみなされず、エラーになる。
テスト時に注意！

他にもいろいろあるが今回はメールの入力欄にてテスト時にエラーが出たので、備忘録としてまとめた。
俺のVR 2020/07/07: Godotのはじめの挨拶、RTFM

#Godotは一体なんだ？

Godotとは、無料のオープンソースのゲームエンジンです。　
UnityとUnrealと比べると、手に入るはしやすいです。

https://godotengine.org/download/windows

👍ポイント

- 無料！すぐにダウンロードができる
- ライセンスなし！　ゲームを作ったら、ゲームは君のものだ。誰にもお金を渡さなくてもいいです。
- 小さい！　UnityとUnrealはまず10ギガバイト以上のパッケージをダウンロードしなきゃですが、このGodotは30メガしかないぜ。
- 問題があれば、直接エンジンに確認ができます！
- 自分でもエンジンに改善ができます！
- パソコンのリソースはそんなに使わない！
- VRでもできるらしいです。 https://docs.godotengine.org/ja/stable/tutorials/vr/vr_starter_tutorial/vr_starter_tutorial_part_one.html

👎ポイント

- もちろんFOSSだから、このエンジンの開発はボランティアに任せています。
- 開発中ので、アップデートしたらエンジンが壊れたり、謎バグに入ったりことがあるはずです。
- UnityとUnrealと比べると、そんなに大きいなユーザーベースがいません。もちろん、ユーザーは熱心ですが、本当のプロの人は・・・？

## RTFM: スクリプティングから行きましょう

まあ、すぐに「VRをやろうぜ」と言いたいですけど、最初2Dゲームもできなかった、いったいどうするの？
その上に、俺のプログラミングの経験は一年間しかないし、ゲーム開発もこどもごろのゲームメーカーソフトしかやったことないんだ！　

でもゲームを作りたいだから、早速始まったら大丈夫だもーん。って格好つけたいね。

![wtf.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393501/7514d222-40bf-815d-8e70-3c1d323870e1.png)

あれれ、Sceneっていったい何？　Root Node?? あの真ん中のものは俺のゲーム？？何もないけど？？？
ああ、もうわかんないー

その時、本当に「RTFM」にしたほうがいいです。

```
RTFMとは、　Read The Fucking Manualという意味だ。
```

なるほど。じゃあ、しょうがねーな。　読みます。

### ⭐ポイント! Godotのマニュアルは日本語でも読めます！

https://docs.godotengine.org/ja/stable/getting_started/step_by_step/scenes_and_nodes.html

```
ちょっとの間、ゲーム開発者でない自分を想像してみてください。代わりにあなたは今、シェフです！
```

Godotの世界観がわかりますか？日本の厳しい世界より、もうちょっとゆったりしているものだから。
まあ、このマニュアルを読むと、シーンやスクリプトの種別ができます。

```
このキッチンでは ノード が、冷蔵庫にいっぱいの新鮮な料理材料です。
ノードにはたくさんの種類があります。画像を表示するためのものや、
音を再生したり、3Dモデルを表示するためのもの等、数十種類があります。
...
シーンは、ツリーの形で階層構造をしたノードのグループから構成されます
```

じゃあ、ノードはただにゲームのオブジェクト、シーンはノードのまとめじゃないっか・・・

とりあえず、今日はこのマニュアルを読んで、ノードとシーンの使い方が把握したら超役に立つはずです！！

今日はここまで！
【ReactNative】既存のアプリにPrettierを導入する

## 1　npmでインストール

```
$ npm install --save-dev prettier
```

今回は開発にのみ必要なので``--save-dev`` オプションをつけます。
[npm install の --save-dev って何？](https://qiita.com/heyheyww/items/092fcbc490a249a2d05c)
[【いまさらですが】package.jsonのdependenciesとdevDependencies](https://qiita.com/chihiro/items/ca1529f9b3d016af53ec)

```json:package.json
...
"devDependencies": {
    "@babel/core": "^7.8.6",
    "@types/react": "~16.9.23",
    "@types/react-native": "~0.61.17",
    "babel-preset-expo": "~8.1.0",
  + "prettier": "^2.0.5",
    "typescript": "~3.8.3"
},
...
```

## 2　.prettierrcファイルの設定

一番上の階層に``.prettierrc``ファイルを作成する。

```json:.prettierrc
{
    "printWidth": 100,
    "singleQuote": true,
    "trailingComma": "none",
    "tabWidth": 4,
    "semi": true
}
```

オプションについては https://prettier.io/docs/en/options.html を参照。

## 3　package.jsonにコマンドを設定して実行

```json:package.json
...
"scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "eject": "expo eject",
  + "prettier": "npx prettier --write '**/*.tsx'"
},
...
```

対象を1つ以下の全てのtsxファイルにして``--write``で上書きしています。
[ESLintのglobパターンがマッチしない問題の対処](https://qiita.com/Tsuyoshi84/items/7c80851371b4bee48de4)

```
$ npm run prettier

$ @ prettier /Users/tagawahirotaka/Desktop/flash-mental-arithmetic
$ npx prettier --write '**/*.tsx'

App.tsx 182ms
components/Modal/DigitModal.tsx 34ms
components/Modal/IntervalModal.tsx 46ms
components/Modal/SheetModal.tsx 25ms
components/Modal/SurfaceModal.tsx 30ms
components/RecordList.tsx 30ms
components/Screen/AnswerScreen.tsx 44ms
...
```

ReactNativeに限らなかったり、VSCodeで自動整形できたりすると思いますが。。。
コマンド叩いてズラッと整形してる！！って感じが個人的には好きなので。
Java リテラルについて

##リテラルとは
値の表記のことをリテラルといいます。変更されないことを前提とした値で、数値や文字列を直接記述した定数のことです。
リテラル(literal)とは英語で、「もじどおりの、言葉本来の意味通りの」といった意味を持ちます。

リテラルは全部で６種類あります。


###文字リテラル
値をシングルクォート（'）で囲んだもの。値が１文字の時に使用します。一般的には文字列リテラルを使用することが多く、文字リテラルはあまり使用しません。
ただし、特殊記号を使う時にはこの文字リテラルを使います。

###文字列リテラル
値をダブルクォート(")で囲んだもの。値が１文字でも使用できます。


###整数リテラル
小数点のない値を指します。
2,8,10,16進数の表現ができます。

###浮動小数点リテラル
小数点を持つ値を指します。１０進数と指数を表現できます。

###論理値リテラル
論理値の値を指します。

真=true
偽=false

###nullリテラル
参照型のデータを参照する時に、何も参照してないということを指します。

##例
以下の例では、int型の変数nに数値の6を、String型の変数nameに文字列のmojiを代入しています。
代入した「6」と「moji」が、それぞれ「数値リテラル」「文字列リテラル」
になります。

int n = 6;
String name = moji;

##まとめ
リテラルは特別な意味を持つわけではなく、ただ「そこに書かれてあるままの文字」のことをいうと理解しています。
Laravelで新規プロジェクトを作成する時にGitでやっておくべきこと

プロジェクトを新規作成する際に最初にやるべきことは、Gitコマンドによる開発環境の構築になります。
本記事では、新規プロジェクト作成からgit-flowモデルでの開発環境の構築手順をまとめました。
なお、Composerは既にインストール済みのものとしています。

#環境
MacBook Pro (13-inch, 2020, Two Thunderbolt 3 ports)
PHP 7.4.1
Laravel Framework 7.18.0

# Laravelプロジェクト作成
```
composer create-project --prefer-dist laravel/laravel SampleProject
```
# localhost起動確認
```
  cd SampleProject
  php artisan serve
  Laravel development server started: <http://127.0.0.1:8000>
```
#ステージング領域作成からプッシュまで
```
git init
Initialized empty Git repository in 作業ディレクトリのパス
git add .
git commit -m "コミットメッセージ"
git remote add origin リモートリポジトリURL
git push -u origin HEAD
```
#作業ブランチを新規作成
```
git checkout -b develop
git checkout -b feature/作業ブランチ名
```
【小ネタ】git-cryptのインストール手順まとめ(Windows/AmazonLinux2/Ubuntu)

# はじめに
本稿は下記記事からの派生となります。

[【GitBash】git-cryptをWindows/Linux環境で活用する【git-crypt】
](https://qiita.com/tmiki/items/5d403025b1f5536423b4)

Gitリポジトリ上のファイルを透過的に暗号化／復号する手段として、git-secretやgit-cryptなどがありますが、プロジェクト内では共通のものを用いる必要があります。
Windows+GitBash環境においては実質的にgit-cryptが選択肢となるため、これにあわせて他の環境用のインストール手順もまとめました。（macOSはありません、すみません。）

git-cryptのGitHubリポジトリは下記になります。
[AGWA/git-crypt: Transparent file encryption in git](https://github.com/AGWA/git-crypt)

# TL;DR
- git-cryptの最新版は0.6.0
- Windowsはバイナリ版の配布があるのでこれを利用する
- Amazon Linux2は、標準的なリポジトリ（amzn2-core/amzn2extra-epel）にはgit-cryptが無いため、ビルドする
- Ubuntuはaptリポジトリにgit-cryptがあるためそのまま利用する


# インストール手順
## Windows+GitBash
git-cryptのWindows版バイナリを作ってくれている方がいるので、これをそのまま利用します。

https://github.com/oholovko/git-crypt-windows

インストール先は、GitBashのPATHが通っていればどこでも構いません。
上記のREAMDE.md上は、「C:\Program Files\Git\cmd\git-crypt.exe」にインストールしていますが、このフォルダへの書き込みはAdministrator権限が必要なこと、GitBash標準インストールディレクトリであるため、避けます。

今回はユーザプロファイルフォルダの「bin」フォルダにインストールしました。
GitBash上からは「~/bin/」として参照できるディレクトリになります。

```
$ mkdir ~/bin/

$ ls -1 ~/bin/git-crypt.exe
/c/Users/your-user/bin/git-crypt.exe*
```

格納後、.bashrcファイル等PATH環境変数を設定しておきます。

## Amazon Linux 2
yumリポジトリに存在しないため、ビルドします。
下記、INSTALL.md手順通りに実行することでインストール可能です。

https://github.com/AGWA/git-crypt/blob/master/INSTALL.md

まず、C++コンパイラ、OpenSSLライブラリをインストールします。

```
$ sudo yum install gcc-c++ openssl-devel -y
```


次に、git-cryptリポジトリをCloneします。

```
$ git clone https://github.com/AGWA/git-crypt.git
```

ビルドします。

```
$ cd git-crypt/
$ make
```

インストールします。
/usr/local/binにインストールしたいため、PREFIXは/usr/localとします。

```
$ sudo make install PREFIX=/usr/local
install -d /usr/local/bin
install -m 755 git-crypt /usr/local/bin/
```

## Ubuntu
aptリポジトリ上に存在するため、そのままインストールします。

```
$ apt search git-crypt
Sorting... Done
Full Text Search... Done
git-crypt/focal 0.6.0-1build2 amd64
  Transparent file encryption in git
```

```
$ sudo apt install git-crypt
```

## macOS
下記記事を見る限り、Macの場合はHomebrewリポジトリにgit-cryptが存在しているようです。

[git cryptを導入する - Qiita](https://qiita.com/batch9703/items/f6959ba51bb9bb32ef93)
練習のためにSwiftをUdemyで勉強してみた(1日目)

#まず、誰？
どこにでもいる社会人です。
普段、職場ではGASを使って仕事の効率化を図りながら日々を過ごしております。
もともとVBA、GASと業務効率化のためにプログラミングを行っておりましたが、職場内だけで使えるものではなくて、世界中の人が触れるものを作りたいとと思い、iPhoneアプリを作ろうと思い至りました。
なんでWebアプリじゃないのかって？
覚えることが多岐にわたって面倒くさそうだったので。
iPhoneアプリだったらとりあえずSwiftができればいいだろうと。
将来的にはWebアプリにも手を伸ばしていきたいです。

#何で勉強するの？
Udemyの以下の講座を受講しました。
ちょうどセールで安かったので。

色々Swiftの言語の基本を学ぶよりかは、早速実物を作りたいと思い、実践重視のこれにしました。

【6日で速習】iOS 13アプリ開発入門決定版 20個のアプリを作って学ぼう（Xcode 11, Swift 5対応中）
https://www.udemy.com/course/ios11basics/

#1日目
2つ作りました。

#FirstMap
https://github.com/blumemond10/FirstMap

Swiftの使い方確認も兼ねて、単純にMap Kit Viewを配置しただけです。
プログラミングのプもしていませんｗ
後々、現在地を表示したり、指定の住所の地図を出せるようにしたいです。

#FirstCamera
https://github.com/blumemond10/FirstCamera

一気にコーディングしていったので、何が起きたのかよくわからないまま完成に至りましたｗ
あとでしっかりコードを読んで、何をしたのか把握したいです。
以下を記述したけど。。。

```ViewController.swift
import UIKit

class ViewController: UIViewController,UINavigationControllerDelegate,UIImagePickerControllerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBOutlet weak var photoImage: UIImageView!
    
    @IBAction func cameraLaunchAction(_ sender: Any) {
        if UIImagePickerController.isSourceTypeAvailable(.camera){
            print("Camera can be usd.")
            let ipc = UIImagePickerController()
            ipc.sourceType = .camera
            ipc.delegate = self
            present(ipc,animated:true,completion:nil)
        }else{
            print("Camera is not avaiable.")
        }
    }
    
    @IBAction func shareAction(_ sender: Any) {
        if let sharedimage = photoImage.image{
            let sharedItems = [sharedimage]
            let controller = UIActivityViewController(activityItems: sharedItems, applicationActivities: nil)
            controller.popoverPresentationController?.sourceView = view
            present(controller,animated:true,completion: nil)
        }
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        
        photoImage.image = info[UIImagePickerController.InfoKey.originalImage]as? UIImage
        dismiss(animated:true,completion: nil)
    }   
}
```

#次にやること
- 上記コードの内容を理解する
- 次のアプリを作ってみる

がんばります。
【Vue.js】Jest+scss でユニットテスト時のスタイルのコンパイルを止めた件

Vue CLI 環境で Jest によるユニットテスト環境を構築しようとしたところ、 scss や CSS Modules との兼ね合いでうまくテストを走らせられませんでした。
スタイルに関するユニットテストをしないなら、テスト時はスタイルのコンパイルを止められるのではないかと考え調べてみたところ、実現できることがわかったのでその設定を紹介します。

# 動作確認した環境
- macOS Catalina
- Chrome 83
- Node.js 12.18.1
- npm 6.14.5
- Vue CLI v4.4.4
    - `vue` 2.6.11
    - `sass` (dart-sass) 1.26.5
    - `sass-loader` 8.0.2
    - `@vue/test-utils` 1.0.3
    - `@vue/cli-plugin-unit-jest` 4.4.0

# テスト時のスタイルのコンパイルを止める方法
`vue-jest` の設定で `experimentalCSSCompile` [^1]を `false` にします:

```js:jest.config.js
module.exports = {
  preset: '@vue/cli-plugin-unit-jest/presets/typescript',
  globals: {
    'vue-jest': {
      experimentalCSSCompile: false
    }
  }
}
```

# ユニットテスト時のスタイルのコンパイルを止めた理由
## 理由1: スタイルに関するユニットテストは難しい
デザインの変更が頻繁に発生する場合、「この状態のときは○○の色が赤である」といったテストは壊れやすいのではないかと思います。
(デザイナーがわずかに色を調整するとユニットテストが通らなくなる、といったケースなど)

スタイルに関するユニットテストはしないという選択をする場合、テスト時は vue ファイルのスタイルブロックを無視できるのではないかと考えました。

## 理由2: scss 変数を vue ファイルのスタイルブロックに自動挿入しているケースに対応できる
`sass-loader` の `prependData` という設定[^2]で、 vue ファイルの各 `<style lang="scss">` ブロック(`scoped`, `module` 付きを含む)の先頭部分に scss 変数等を自動挿入することができます。

Vue Loader のドキュメントでも紹介されている手法で、使われている方も多いかと思います。

```js:vue.config.js
module.exports = {
  css: {
    loaderOptions: {
      scss: {
        prependData: `$main-color: #333333;`
      }
    }
  }
}
```

テスト時のスタイルのコンパイルを止めない場合 `jest.config.js` の `jest.globals['vue-jest'].resources.scss` で `vue.config.js` の `prependData` と近い設定ができるようですが、設定の重複管理は避けたいと思いました。

スタイルのコンパイルを止めることで、この問題を解決できました。

## 理由3: `<style lang="scss" module>` があると `node-sass` のインストールを求められる
テスト時のスタイルのコンパイルを止めない場合、 CSS Modules と scss を併用している vue ファイルのテストをしようとすると `node-sass` のインストールが必須となります:

```text:sass(dart-sass)をインストールしている場合
 FAIL  tests/unit/example.spec.ts
  ● Test suite failed to run

    [vue-jest] Error: You are trying to use "scss". node-sass is missing.

    To install run:
    npm install --save-dev node-sass
```

上記のメッセージに従って `node-sass` をインストールすることでもこのエラーを回避できます。
しかし `node-sass` は OS 依存のバイナリを含んでいたり `sass`(dart-sass) と同じく scss をコンパイルする役割を持つパッケージのため、インストールは避けたいと思いました。

スタイルのコンパイルを止めることで、この問題を解決できました。

## 理由4: CSS Modules を使っていてもテンプレート上の `$style.class_name` で例外が発生しない
vue ファイルに `<style module>` ブロックがあると `$style` というオブジェクトが注入されテンプレート上で利用することになります。

単純に vue ファイルから `<style module>` ブロックを消すことを考えると、 `$style` のオブジェクトが注入されなくなってテンプレート上にある `$style.class_name` のようなプロパティへのアクセスで例外が発生しそうです。

ですが、紹介した設定ではテスト対象の vue ファイルに `<style module>` がある場合はブロック内の記述は無視しつつ `$style = {}` を注入してくれるため、上記のような例外は発生しないようになっています。

[^1]: `vue-jest` の `README.md` のコミットログを追ったところ [2018/04/09 のコミット](https://github.com/vuejs/vue-jest/commit/3f656466492316917ef09c05facf32fb1a7eca31) で `experimentalCSSCompile` に関する記述が追加されていました。2年以上経過していますが "experimental" は外れていないようです
[^2]: `sass-loader` 7.x.x までは `data` で、 9.x.x からは `additionalData` となるようです。 `additionalData` は prepend だけでなく append もできるそうですが、 8.x.x の `prependData` と同じように使うことができました
サーバーレス戦役から戦線離脱しないようにするために削りたいこと

俺です。
サーバーレス戦役一兵卒なファンクションにロングネームつけてしまうとき、AWSのリソース文字数制限はdeployする前から意識しておきましょうという話でした。

- sls deploy時にIAM Role文字数制限で引っかかって戦線離脱した例

```
  An error occurred: IamRoleLambdaExecution - 1 validation error detected: Value 'aaaaaa-aaaaaaaaaaa-aaaaaaaa-production-ap-northeast-1-lambdaRole' at 'roleName' failed to satisfy constraint: Member must have length less than or equal to 64 (Service: AmazonIdentityManagement; Status Code: 400; Error Code: ValidationError; Request ID: XXXXXXXXXXXXXXXXXXXXXX).
```
Si1132の制御

Si1132は、可視光線と赤外線、UVの指数の値を取れるセンサーです。センサーは縦横２mm非常に小さくQFN
動作電圧も広く、1.7Vから3.6Vなので電池の電圧がそのまま使える。インターフェースはI2C(3.4MhzまでOK）

用途
フィットネス、スマートウォッチ、スマーフォトフォン、タブレット、ディスプレイの制御など

内部構造
フォトダイオード（可視光線、赤外線）　温度計（値は取れないようです）それぞれ搭載、アナログコンバータとデジタルシーケンサに計測回路搭載。

計測時は４mA〜５mAぐらい消費。スリープモードは0.5nA　消費電力はとても低い。計測時間を285uS

i2C周波数は95~3400kHz

5Vのマイコン等は直接繋ぐことはできません。レベル変換を使いましょう。
絶対定格　供給電圧-0.3V~4V,動作温度（−４０〜８５度）
I2C電圧　-0.5~3.6V

###アンビエントライト（周囲光）###





ハロゲンや日光など、光源により補正が必要な場合があります。

このセンサーには、INTピン（割り込み出力）が付いています。なお、この割り込み出力が電源投入時、電圧レベルHigh出ないと省電力にはなりません。

データを取るのには、データを取得するたびに、データを送るように指示するとこもできますが、他にも通知を行うこともできます。これを使えば、ホストは割り込みを受信したら、ホストマイコンはウェイクして、データを受け取ることができます。これにより非常に優れた省電力となります。

設定

コマンドレジスタ以外はいつでもウェイクアップせずにレジスタにアクセスできます。強制モードと自立モードがあり,強制モードは、ホスト側が要求しなければ、測定は行わず、自立モードでは自動的に測定を行います。

チャンネルリストCHLISTパラメータの設定

MEAS_RATE が０出ない場合は、自動測定モードになります。これはセンサーがウェイクアップし、測定する時間の間隔になります。測定は最大三回行われる。測定は、ALS_VIS（可視光線)、ALS_IR(赤外線)、AUX(紫外線)の順で測定が行われる。

電源投入後、初期化され、スタンバイモードに入るためには、ホストマイコンはHW_KEYレジスタに0x17に書き込む

スタンバイモードに入り、

測定間隔を設定します。

IR補正

UVインデックスの読み取りを有効化

CHILIST EN_UVビット　UCOEF[0:3]を07B
VIS_RANGE
IR_RANGE

紫外線データは、AUXデータに１６ビット値が含まれます。そのデータは１００で割る必要があります。

##コマンド##

レジスタ0x18（コマンド）であらかじめPRAM_WRで設定したパラメータ（PRAM）を書き込みます。

まず、0x17でパラメータをセット、0x18でコマンドでパラメータセット。


先頭ビットに次のビットを与えます。

パラメータを照会
PARAM_QUERY

100* ****(2)

パラメータをセット
PARAM_SET

101* ****(2)

NOP
0x00
レスポンスレジスタにゼロを返す。

RESET
0x01
ソフトウェアリセット

BUSADDR
0x02
i2cアドレスの修正命令

GETCALL
0x12
キャリブレーションデータ

ALS_FORCE
0x06
強制ALS測定

ALS_PAUSE
0x0A
自律型ALSを一時停止する

ALS_AUTO
0x0E
自律型ALSループの開始/再開

コマンドの例

0xA0 | 0x01
CHLIST

0xA0 | 0x0E
ALS_IR_ADCMUX

自立型でデータを開始

###レスポンスレジスタ###

0000 ****

1000 0000

1000 1100

1000 1101

1000 1110
TypeScriptでクラスのフィールド名だけを抜き出す

```typescript
class Person {
  name: string;
  age: number;
  walk() {}
}
```

みたいなのがあったときに

```typescript
// "name" | "age" になってほしい
type PersonFields = Fields<Person>;
```

としたい。

以下のコードで実装できます。

```typescript
type Fields<T> = { [P in keyof T]: T[P] extends Function ? never : P } extends Record<string, infer U> ? U : never;
```

TypeScript楽しい。
秘密鍵を設定したcircleCIでEC2にSSH接続できない原因は、EC2のセキュリティグループでローカルIP以外のSSH接続を拒否していたからだった

ローカルからSSH接続もcapistranoデプロイも正常に可能だから、
EC2側は問題ないという灯台下暗し


# # 問題
circleCIのDeployフェーズで毎回SSH接続がTimeoutする

```
bundle exec cap production deploy 

cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as <user名>@xx.xxx.xx.249: Net::SSH::ConnectionTimeout
 
Caused by:
Net::SSH::ConnectionTimeout: Net::SSH::ConnectionTimeout
 
Caused by:
Errno::ETIMEDOUT: Connection timed out - connect(2) for xx.xxx.xx.249:22
 
Tasks: TOP => rbenv:validate 
(See full trace by running task with --trace)
```

# 解決
VPCにアタッチしているセキュリティグループの
インバウンドルールを後述のように変更した

```
SSH		TCP		22		<ローカルIP>
```

```
SSH		TCP		22		0.0.0.0/0
```


# 検証
<user名>@xx.xxx.xx.249(EC2のElastic IP)は適切
Terminalから同じ秘密鍵を使用してEC2ログイン可能
ローカル環境では`bundle exec cap production deploy `は成功する


# 原因
AWSのVPCに割り当てられたセキュリティグループが、
SSH接続(port: 22)でローカル環境のIPアドレスのみを許可する設定になっていた

Qiitaの記事などを参考に手順どおりEC2へのデプロイ環境を構築してきた場合、同様に遭遇する可能性が高いと考えます
i18nのロケールをJavaScriptにわたす

## 多言語対応のアプリを作成中に詰まった
jQueryとAjaxを使って、親カテゴリを選択すると子カテゴリの候補がプルダウンで表示されるようにしました。
ところが、子カテゴリだけ、デフォルト表記のベトナム語でしか翻訳されてませんでした。

例：親カテゴリ => 質問
　　子カテゴリ => １，Ngôn ngữ và văn hóa
　　　　　　　　　２，Tập huấn kỹ thuật
　　　　　　　　　３，Ứng dụng và thủ tục

## 原因
Ajaxで子カテゴリを取得する際、コントローラにロケールを渡してないことが原因でした。

```category_pulldown.js
$("#parent").on("change", function () {
  // 選択した親カテゴリからIDを取得
  var id = document.getElementById("parent").value;
// 中略
$.ajax({
  type: 'GET',
  data: { parent_id: id }, // IDをparams[:parent_id]に入れて送信
  url: '/categories/pulldown', // categoriesコントローラにて、受け取ったIDで子カテゴリを取得
  dataType: 'json',
}).done(function (children) { // 取得した子カテゴリを表示させる処理...
```

一部抜粋ですがロケールの取得は以下の方法でやってました。

```application_controller.rb
before_action :set_locale

  private

  def set_locale
    I18n.locale = locale
  end

  def locale
    @locale ||= params[:locale] ||= I18n.default_locale
  end

  def default_url_options(options = {})
    options.merge(locale: locale)
  end
```

## 現在のロケールをJava Scriptへわたす

まずは、inputタグを使って現在のロケールを保持させます。
以下のように`type="hidden"`と書くと、ユーザーから見ても画面には表示されません。

```hoge.html.erb
<input type="hidden" class="current_locale" value="<%= I18n.locale %>">
```

次に`locale: $('.current_locale').val()`を追加すると
親子カテゴリの翻訳言語が統一されました。

```category_pulldown.js
$("#parent").on("change", function () {
  // 選択した親カテゴリからIDを取得
  var id = document.getElementById("parent").value;
// 中略
$.ajax({
  type: 'GET',
  data: { parent_id: id, locale: $('.current_locale').val() }, // IDをparams[:parent_id]に入れて送信
  url: '/categories/pulldown', // categoriesコントローラにて、受け取ったIDで子カテゴリを取得
  dataType: 'json',
}).done(function (children) { // 取得した子カテゴリを表示させる処理...
```

HTMLはRubyからもJavaScriptからも情報の受け渡しができるので便利ですね:smiley:
ディレクトリ内のファイルを一括リネーム

こんな感じ。

```sh:sedname.sh
#!/bin/bash

file_all=(`ls`)
for ((i=0; i<${#file_all[*]} ; i++))
{
  file_subd[i]=`echo ${file_all[i]}| sed $1`
  if [ ${file_subd[i]} ]; then
    echo mv ${file_all[i]} ${file_subd[i]}
    mv ${file_all[i]} ${file_subd[i]}    
  fi
}
```

スクリプトをコマンド的に使いたいなら、aliasを忘れずに。下は一例。

```sh:~/.bashrc
alias sedname="sh ~/docs/tools/sedname.sh"
```

実行結果。
<img width="456" alt="Screen Shot 2020-07-08 at 9.01.11 copy.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351420/f58b1dbe-2060-9001-7c00-6383c91fee4a.png">

その他、リネームするファイルのリストを別のテキストファイルから取得したいなら

```sh:
file_all=(`cat list.txt`)
```

というように書き換えればいいと思います。
【Python】dict in listやinstance in listをsortする方法

listのソートはよくありますが、ここではdict in listやinstance in listをsortする方法を書き留めます。
sortは全て昇順とします。
sortで使用するのは組み込み関数の`sorted`です。

## 動作確認済みのPythonバージョン

- 3.7
- 3.8

標準ライブラリdataclassesを使用しなければ3.6とかでも動くはずです

# dict in list

dict in listの場合はsorted関数のkey引数を指定してあげる必要があります。
keyを指定する時にlambda使って無名関数で`lambda x: x['a']`でもいいですが、公式によると標準ライブラリoperatorのitemgetterを使用した方が高速らしいです(検証していないのでなんとも言えませんが)。

https://docs.python.org/ja/3/howto/sorting.html#operator-module-functions
> Python は高速で扱いやすいアクセサ関数を提供しています。 operator モジュールには itemgetter(), attrgetter() そして methodcaller() 関数があります。

```python
from operator import itemgetter
person_list = [{'name': 'a', 'age': 4}, {'name': 'b', 'age': 3}, {'name': 'c', 'age': 10}, {'name': 'd', 'age': 2}, {'name': 'e', 'age': 1}]
sorted(person_list, key=itemgetter('age'))
```

```python
[{'name': 'e', 'age': 1},
 {'name': 'd', 'age': 2},
 {'name': 'b', 'age': 3},
 {'name': 'a', 'age': 4},
 {'name': 'c', 'age': 10}]
```

# instance in list

dict in listと同様にsorted関数のkey引数にソートしたいパラメータを指定してあげましょう。instanceの場合はattrgetterを使うといいですよ。

一旦sourcesでdict in list作成して、list(map(...))でインスタンス作成しているのに深い意味はありません。dict in listで使用したperson_listを流用して楽をしたかっただけです。

```python
from dataclasses import dataclass
from operator import attrgetter

@dataclass
class Person:
    name: str
    age: int

sources = [{'name': 'a', 'age': 4}, {'name': 'b', 'age': 3}, {'name': 'c', 'age': 10}, {'name': 'd', 'age': 2}, {'name': 'e', 'age': 1}]
person_list = list(map(lambda x: Person(**x), sources))
sorted(person_list, key=attrgetter('age'))
```

```python
[Person(name='e', age=1),
 Person(name='d', age=2),
 Person(name='b', age=3),
 Person(name='a', age=4),
 Person(name='c', age=10)]
```

降順でソートしたければ、sorted関数のreverse引数をTrueにすればOK

# Reference

- https://docs.python.org/ja/3/howto/sorting.html
Chrome画面のスクリーンショットを取る方法(途中で切れるのを防ぐ)

# 背景
Seleniumを使って自動でスクリーンショットを取ろうとしたのですが、いくら大きいサイズを指定しても、画面サイズで切れてしまってスクロールの下の方が取れずに苦労したので、その備忘録です。

# 使用したもの
chromedriver(使用しているchromeのバージョンにあったもの)
selenium
python

# 対応法
optionsでheadless付ければOKでした。

```screenshot.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

if __name__ == "__main__":

    # 切れないスクリーンショットのために必要な設定
    options = Options()
    options.add_argument('--headless')
    driver = webdriver.Chrome(options=options)

    # サイズを広めに指定しておく
    driver.set_window_size(1400, 2000)

    # キャプチャ先の指定
    driver.get(r'https://ja.wikipedia.org/wiki/Qiita')

    # キャプチャ実施。保存ファイルを指定。
    driver.save_screenshot('screenshot.png')

    driver.close()
```

# 考察
optionsでheadlessを付けると、Chromeが立ち上がることがなくなります。
つけない場合にスクショが切れてしまうのは、おそらくChromeが立ち上がった際にwindow幅に合わせて縦・横が微修正されるからなのかなぁ。。。と。多分そう。