OmniAICreator/Qiita-1.07M huggingface dataset:
pythonでsshトンネルを作成する

# はじめに
開発では、変なところからアクセスされたくないためにDBにアクセスできるサーバを制限しています。
アクセスできるサーバのことを踏み台といいますが、基本的には中継地点になるだけなので開発に便利なソフトウェアがほとんど入っていません。
そこで、トンネルのようにローカルのPCと目的のDBまでの通信を踏み台は通すだけにして、実際の処理はローカルのPCで行うsshトンネルというものが良く使用されます。
sshクライアントで有名なteratermでも可能ですが、業務の自動化の一環で使用したpythonでのsshトンネルの方法をまとめます。

# 環境
 - python3:3.6.5
 - sshtunnel:0.4.0

# sshtunnelのインストール
sshトンネルを作成するためにsshtunnelを使用します。
sshtunnelのインストールは普通にpipでインストールすれば良いだけです。

```
pip install sshtunnel
```

# sshtunnelの使い方
sshtunnelは以下の手順で使用します。

 1. sshの設定
 2. sshトンネルのスタート
 3. DBなどバインド先に対してしたい処理
 4. sshトンネルのクローズ

## sshtunnelの設定
### 設定内容
sshトンネルは図のように踏み台サーバを通してDBに接続するため、必要な設定は7つあります。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481713/ef2bc6af-96f9-df23-8ea8-f3c4c0043d18.png)

 - 踏み台へログインするための情報
   - 踏み台のIPアドレス（上絵の例:192.168.1.0)
   - 踏み台へログインするためのユーザID
   - 踏み台へログインするためのパスワードまたはキーファイルのパス
 - ローカルPCと踏み台間の設定
   - ローカルPCのIPアドレス（上絵の例:0.0.0.0)
   - ローカルPCにバインドするポート番号（上絵の例:400)
 - 踏み台とDB間の設定
   - DBのIPアドレス（上絵の例:192.168.2.0)
   - 踏み台にバインドするポート番号（上絵の例:5432)


### 設定方法
設定方法は簡単です。sshtunnelをimportしてSSHTunnelForwarderに与えてあげるだけです。
local_bind_addressでポートを指定しないときは自動的に空いているポートが使用されます。使用されたポートを知るためにはserver.local_bind_portで知ることができます。

``` python
from sshtunnel import SSHTunnelForwarder
server = SSHTunnelForwarder((
        192.168.1.0,
        22
    ),
    ssh_username='login_user,
    ssh_pkey='C:\\key.pem,
    remote_bind_address=(
        '192.168.2.0',
        5432
    ),
    local_bind_address=(
        '0.0.0.0',
        400
))
```

### sshトンネル開始
設定後はsshトンネルを有効化します。有効化後は設定で与えたロカールポートにアクセスすると踏み台にバインドしたDBにアクセスすることができます。
例でいうとローカルの5432ポートに対してSQLを実行すると192.168.2.0のDBに対してSQLが実行されます。

``` python
server.start()
```

### sshトンネル終了
全ての処理が終わったら、sshトンネルを閉じてあげる必要があります。

``` python
server.stop()
```

## おわりに
pythonでsshトンネル操作する方法をまとめました。
上のことを活用して[踏み台の先のDBから情報を取得してエクセルに記載するプログラム](https://github.com/mink0212/ssh_tunnel_get_db_to_excel)を作りました。
このように[前回のエクセル操作](https://qiita.com/mink0212/items/964c1936cb00584c8a91)とさらに[前のDB操作](https://qiita.com/mink0212/items/d7f31f6e2903c5f0b837)を使えば出来ることが広がります。。
踏み台にログインして色々するのではなく、自身が快適になるように作成したローカルの環境を最大限利用してテストや本番環境などの作業を最高効率で作業して極力楽しましょう。
JDLA_E資格の深層学習「CNN」

#1. CNN(畳み込みニューラルネットワーク）の活用範囲
Convolutional Neural Network

CNNは、画像判別によく使われるが、画像のみに使う手法ではない。
次元間で繋がりがあるデータなら何でも扱える。音声、や動画など。
次元間の繋がりとは、画像の場合、横のピクセルは似たような色という意味合い。音声なら次の時刻の強度は似たような強度であるなど。

#2. CNNの構造

CNNの基本構造は以下。

![CNN構造.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1436941/8f347bd2-8a10-4cb7-16da-8cdb3ceb1f60.png)

##2.1  LeNetの構造

1998年にヤンルカンが発表した有名なLeNetは、入力画像は、32×32ピクセルとかなり小さいサイズの画像をとる。（LeNetは現在のCNNの原型といわれる。）
そして、出力として、10種類の何かに画像分類を行う。
構造は以下。

![LeNet.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1436941/3441e49e-747c-a045-7ef8-1dee647857ce.png)

####2.1.1  LeNet内での処理

1. 6人で入力画像を見て、特徴を抽出(Convolution : C1)
1. 6人で出した特徴をわかりやすく要約(Pooling :S2 sub sampling)
1. 要約した特徴を16人に見てもらって、さらに特徴を抽出(Convolution : C3)
1. 16人で出した特徴をさらに分かりやすく要約(Pooling :S4)
1. すべての情報を120文字で言い表す(dense)
1. さらに84文字に要約(dense)
1. さらに10文字に要約(dense)

####2.1.2  畳み込み層の処理（Convolution)

畳み込み層では、入力画像に対してフィルタ処理（赤枠）を行い、結果を特徴画像として出力する。フィルタは、入力画像よりも小さいサイズで、ピクセルを横へずらしながら計算を行っていく。
なお、この際に、バイアスや活性化関数を通す。
このフィルタ処理の際に、周りの次元のデータを合わせて処理を行うことで、次元間の繋がりを特徴量として抽出することができることがCNNの特徴である。

![CNNフィルタ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1436941/4c989413-a91d-f359-5b65-4662cd3cebcb.png)

####2.1.3  全結合層の処理(dense)

全結合層の処理は、NNの基礎となる入力に重みをかけてバイアスを足してを行うだけの処理である。
ここでは次元の繋がりなどは考慮されない。

#3. 畳み込み演算

##3.1 convolution処理
畳み込み層は、画像の場合、縦、横、RGBの入力データに対して学習が出来る。つまり多次元、多チャンネルのデータに対応した演算ができる。
普通の全結合層の処理だと、RGBの関連を含めて学習を行うことが出来ないという問題の解決策となる。
ここで、畳み込みの処理を少し詳細にみる。
基本的に、フィルタという重みをかけてバイアスをかけてやるだけである。

![畳み込み.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1436941/b32497df-c779-671f-6d70-6f40c0eebad7.png)

##3.2 パディング
ただし、これをすると、どんどんサイズが小さくなってくるので、**パティング**という処理を行う。

パディングとは、入力画像の周囲を固定データ（ふつうは０）ですこし広げる処理をいう。事前にサイズを広げておくことで、どんどん小さくなることを防ぐ。これを行うと、入力画像に対して、同じサイズの出力画像を出すことが出来る。

![パディング.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1436941/d6580361-cf94-af2d-41cb-dd147d8a7b0d.png)

##3.3  ストライド

フィルタ処理は、通常は、1ピクセルずつずらして処理を行う。このずらす量をストライドという。ストライドが2ピクセル、3ピクセルずつの場合もある。

#4.　プーリング演算

プーリングには、**MaxPooling**や、**AveragePooling**という種類がある。畳み込みのように重みはなく、領域内の最大値か、平均値を出力結果として採用する。

#5. プーリング層から全結合層への演算

畳み込みが終わり、プーリング層から全結合層へいくさいに、複数レイヤー（多次元　16層×5×5）のデータを1次元(120)のデータへ落とす処理が必要である。

![全結合.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1436941/a27ee370-16d2-f0bc-5fc0-14455d5dd9dc.png)

この際によく使われる3種類の処理がある。

1. Flatten
1. GlobalMaxPooling
1. GlobalAveragePooling

##5.1 Flatten

Flattenは単純に複数レイヤーにわたる全データを単純に一次元配列に並べる処理だる。データ数は変わらない。

##5.2 GlobalMaxPooling

GlobalMaxPoolingは、各層の最大値を1次元配列として出力する。データ数が一気に削減され、かつ特徴量をよく抽出する優秀なやつ。


##5.3 GlobalAveragePooling

GlobalAveragePoolingは、各層の平均値を1次元配列として出力する。データ数が一気に削減され、かつ特徴量をよく抽出する優秀なやつ。
AWSリソースの消し忘れで課金されたので調査

昼休み、昼飯を終え一息ついているとスマホに通知が。

「Visaデビットご利用通知　Amazon web services 2.57USD」

AWSリソースの消し忘れで$2.57が徴収されたようです...
勉強も兼ね、どこで発生したのか調査しよう。

#利用料金の確認

ググったところ、
- 請求情報とコスト管理コンソール
- Cost Explorer
この辺りが使えそう、クラウドプラクティショナーの勉強でも出てきたやつだ。

###請求情報とコスト管理コンソール
月毎の利用料がグラフになっている。
**$2.57は昨月の利用料だったことが判明**
なるほど翌月頭に徴収のシステムなんですね、知らなかった。

更に、
**今月の予想利用料$2.84**
まじで？こっちも調べないと
ちなみに既に**$0.43発生している模様**、WAFとConfigらしい。
まだ今月３日だぞ...

###Cost Explorer
過去６ヶ月の請求金額とその内訳が確認できる。
**４月にも$0.69発生していることが判明**
なんで気づかなかったんだ。

肝心の５月分の内訳は、
**WAFが\$2.26、EC2その他が\$0.07、税金\$0.24**
**WAFの課金は5/20から毎日$0.2**
EC2は何度も立ち上げたり消したりしてるからいいとして、WAFってなんだっけ...
そして5/20に何をしたんだろう。

更に今月分はWAF（5/20から継続）とConfigで発生している模様、Configも調べないと。

#WAFの課金
WAFはWeb Application Firewallの略。
>AWS WAF は、可用性、セキュリティ侵害、リソースの過剰消費に影響を与えるような、ウェブの脆弱性を利用した一般的な攻撃やボットから、ウェブアプリケーションまたは API を保護するウェブアプリケーションファイアウォールです。
https://aws.amazon.com/jp/waf/


よく覚えてないけど確かに触った気がする、どこで課金されたのだろう。

>作成する各 Web ACL および Web ACL ごとに作成する各ルールに対して請求されます。さらに、Web ACL によって処理された Web リクエストの数に対して請求されます。
https://aws.amazon.com/jp/waf/pricing/

- Web ACL
- ルール
- リクエスト

の3つで課金が発生するらしい。
AWS WAFのダッシュボードからWeb ACLを確認するとリソースは無さそう。

あれ？でも、WAFの課金止まってないよな。

#CloudTrailを遡る
CloudTrailで5/20を確認してみる。
**CreateWebACL	May 20, 2021, 16:53:57 (UTC+09:...**
これか。
削除のログも確認しないと。

**DeleteWebACLで検索したがヒットしない、おかしい**

CreateWebACLを確認するとus-east-1での記録になっている。
AWS WAFのページに戻りus-east-1を確認、**WebACLは残っていない**。
もちろんap-northeast-1にもWebACLなし。

ここまでをまとめると
**Cost Explorer : 5/20からWAFに課金、今も継続中**
**CloudTrail : 5/20にus-east-1にてCreateWebACL、以降のDeleteの記録なし**
**AWS WAF : us-east-1にWebACLは無し**


**????**

ここでギブアップ、上司のWさんに相談。

**「CloudFrontとWAFで使ったんじゃない？」**

#騙されたポイント

CloudFrontとWAF連携させる場合、WebACLはグローバルで作成しなければならないらしい。
そのため、WebACLダッシュボードでの表示は**Global**。
しかし実際にはus-east-1のサーバに作成されるため、CloudTrailでの記録はus-east-1に残る。
ここで騙されたようです。

確認してみると、WebACLのダッシュボードでリージョン名に並んでGlobalの選択肢がある。
**無事Web ACLを発見、削除しました。**

Web ACL名が*handson-waf*なので、AWSハンズオンをやったときの残りだ、消し忘れてた...

#AWS Configの課金
>AWS Config では、アカウントの記録された設定項目の数、アクティブな AWS Config ルールの評価数、コンフォーマンスパックの評価数に基づいて課金されます。
https://aws.amazon.com/jp/config/faq/

- ルールの評価数
- コンフォーマンスパックの評価数

で課金されるらしい。

configの課金は6/1だけだった、適当に触っていたのでどこかで$0.08課金されたらしい。
ともかく課金は止まっているようなのでよかった。

#振り返り
CloudTrailはほぼ初めて触ったし、WAFについても少し知れた。
何より無駄な課金を止めれてよかった。
UbuntuとWindowsでデュアルブートする方法

#はじめに
大学院の研究でCUDAなどを使う必要性が出てきたので、GPUの認識を考えるとデュアルブートが一番良いと判断。もともと持っていたWindowsPCでUbuntu20.04とのデュアルブートを試みます。

#PCスペック
(変更前)
OS : windows10 home
m.2 nvme SSD : 1TB
HDD : 2TB
メモリ : 8G×2
GPU : Nvidia RTX2070super

(変更後)
OS : windows10 home or Ubuntu20.04LTS
m.2 nvme SSD : 1TB (windows 10 home)
m.2 nvme SSD : 500TB (Ubuntu20.04LTS)
HDD : 2TB
メモリ : 8G×2 + 16G×2 = 48G
GPU : Nvidia RTX2070super

#デュアルブートの必要性 
まず本当にデュアルブートが必要か判断してください。
Linux系のOSをWindowsで使いたい場合は方法は大まかに分けて３つあります。

1. 仮想環境の構築
一番オーソドックスなのはDocker、VirtualBoxなどの仮想環境作成ツールを使っての作成だと思います。Windows内のリソースは取られ、少し動作も遅いですがGPUなどの認識がいらないのであればこれでもいいです。DockerなどでもGPUが使えるようになったと噂を聞きましたが、めんどくさかったのでやめました。

1. WSL
お手軽にCUIを体験してみたい、atcoderなどの競技プログラミングでのファイル作成しかしないということであればwslがいいです。WindowsStoreにあるのをダウンロードすればターミナルは使えるようになるので一番簡単でしょう。新しいwsl２ではGPUが使用可能らしいですが、バグがあったり動作が不安定だったりするので記事投稿時点では採用しません。2023年頃にはまともに使えるようになってそうな気はします。

1. デュアルブート
結局これが一番楽。起動時にOSを選択するのが面倒ですが。同じSSD内でパーティションを区切って他OSをインストールすることも出来ますが、よっぽどわかっている人以外は辞めたほうがいいです。

**結論: GPUを使いたいならSSD増設してデュアルブート化する**

#参考記事
検索したところこちら[[1]]がわかりやすくまとまっていたので、この記事を参考にデュアルブートに挑戦していきます

#LiveUSBの作成
いまあるPCでLiveUSBを作成します。ブートメディアならばなんでもいいのでDVDでも問題ないです。
最初はbalena Etcherを使用して作成しようとしたのですが、フリーズしてできなかったので仕方なくUNetBootinでLiveUSBを作成しました。


#SSDの増設
僕はM.2SSDを買いましたがSATA接続のものを買っても問題ないと思います。
SATA接続の場合は電源ケーブル、SATAケーブル、
SSDを購入する前に自分のPCを開けてみて中身がどうなっているのかをきちんと確認しましょう。
僕はもともとPCゲームをするためにBTOで買っていたので、購入履歴からマザボの名称を発見。
その名称を検索してマザボ上にSSDをどうつけるかを考えました。
m.2スロットが２つあっても同時に使えなかったり、そもそも2つなかったりするかもしれないのでしっかり調べましょう。
SSDをマザボに接続できたらwindowsで起動して認識しているか確認しましょう。
認識していることが確認できたらOSを入れたい記録媒体以外は全部マザボから外しましょう。
間違えてwindowsの方にインストールしたら当然データふっとぶのでやばいです。
よっぽど自信のある方以外は全部外すことをおすすめします。
あとケーブル類を外す際はマザボ側の端子、電源側の端子を外しましょう。
逆側を外しただけのときに何故かうまく行きませんでした。
メモリ不足を感じていたので、ついでにメモリも増設しました。

#OSのインストール
Live USBを挿した状態で起動してBIOSを開きます。
僕はF2で開いて、F11でOSの選択でしたがそれはPCによるので自分で調べてください。
あとは[[1]]の通りに進めていきます。
パーティションのところだけわからなかったので調べました。
どのサイトか忘れたのでわからない人は調べてください。
再起動すると画面がバグっていたので[[1]]に書いてある参考文献をみて解決。
要するにNVIDIAドライバーがうまく動かないので無効にしてあとでダウンロードする感じらしい。
書いてある通りやって再起動するとうまく行きました。
とりあえず流れでいろいろダウンロード。
ひとまずダウンロードが必要とのことで再起動すると無限にログインを求められる。
調べて見ると[[2]]に対応作が書いてあってのでそれを実行。
再起動するとやっとログイン出来た。
linux系はやっぱりある程度調べたり解決する力がないときついですね。

#確認とダウンロード
ターミナルを開いて

```
nvidia-smi
```
と入力してGPU情報が出てくればGPU認識されています。

```
sudo apt update
sudo apt upgrade 
```
でパッケージの更新ができるので好きなコマンドやアプリケーションを入れましょう。
storeからダウンロードしてもOKです。
#おわりに
今回はデュアルブート化をしてみました。ノートPCもUbuntuにしたことがあるのでまだ楽でしたが、デスクトップPC内部をいじったりするのは初めてだったので壊さないか緊張しましたね。リスクを減らして作業を行うことの大切さが改めてわかりました。次はディープラーニング用の環境を構築していきたいと思います。

それではまた！

#参考文献
[1]:https://qiita.com/shimopino/items/464ca8d5294a3a2cb9ee
[[1]] WindowsでSSDを増設してデュアルブートしたUbuntuでPyTorch(GPU)を使うまで
[2]:https://musaprg.hatenablog.com/entry/2020/06/30/201759
[[2]]:Ubuntu20.04がログインループで立ち上がらなくなった場合の対処法
Cygwin+EmacsでのPython実行

# Run python in Emacs with Cygwin in Windows
Windows10 の中で、Cygwin と Emacs で Python する
## Windows x64 の Python を使う
インストールは説明不要
## .emacs　その１

パスの表現は各自の環境次第

```
(require 'python) #　これを使うかはお好みだろう
(setq python-shell-interpreter "/cygdrive/c/Users/.../Python39/python.exe")
```
## Your `python-shell-interpreter' doesn't seem to support readline
の警告を防ぐ

https://qiita.com/ignorant/items/50f8eb2852d0f0214659
の　use-package python
で始まる設定を .emacs　に追加する

## C-cC-c で FileNotFoundError になる
No such file or directory: '/cygdrive/c/Users/...'
というエラーが出る
これはパスの形式が Windows Python とこの Cygwin で違うためみたい
### python-shell--save-temp-file に手を加える
advice-add を filter-return で使い、return するパスを加工する。
一例として先頭の　/cygdrive/c を除去する

```
(defun my-xxx (fpath)
(replace-regexp-in-string "/cygdrive/c" "" fpath))
(advice-add 'python-shell--save-temp-file :filter-return "'my-xxx)
```

### Emacs/Cygwin からもアクセス可能にする
トリッキーだがシンボリックリンクで解決する
管理者権限で Cygwin (64) を起動し、

```
ln -s /cygdrive/c/Users /Users
```

これで、 /Users/... で始まるパス記述でアクセスできる

## おまけ tkinter
なぜか `from Tkinter import *` ではだめで、
`ModuleNotFoundError: No module named 'Tkinter'`
となってしまう。
理由はわからないが tkinter　と小文字にしたら問題が消えた。
使ったテストでは tkinter による Window を閉じてもプロンプトに戻らず、　
py の最後に quit()　を加えて、プロセスを終えるようにした。
読書OUTPUT  # THE MODEL

趣味で読んでいる読書のアウトプット記事です。
せっかく読書してもなかなか思い出せない！印象の残ったワードが３語くらいしかない！ということがしばしばあるので、こうやってアウトプットすることにしました。

今回は一度読んだ**「THE MODEL」**を再度読み返してメモしたいところをアウトプットしていきます。

# THE MODEL 冒頭〜第１部まとめ

## ビジネスにおいて重要なのは再現性ということが分かった
完成したモデルを記憶して同じことをしようとしても同じ結果が得られるわけではない。

```
本当に大切なのは完成に至る過程で行われたたくさんの意思決定プロセスを習得すること。
```
そうすることで*どんな環境にも適応することができる*。
これこそが本書で伝えたい***再現性***。

#### 個人メモ１（感想）
THE MODELを読むにあたって、方法論的な結果に焦点をあてるのではなく、プロセスに焦点をあてる。

> 愚者は経験に学び、賢者は歴史に学ぶ　/　オットー・ビスマルク

１人でできる経験には限界があるが、他者の経験を研究すると補える。
他者の経験を知ることができるチャンスの一つとして<font color=red>読書</font>がある。

## 第１部 アメリカで見た新しい営業のスタイル
結論：レベニューモデルという完全分業の営業スタイルが確立されていることが分かった

> 従来の営業スタイルよりも細分化された完全分業体制が構築されており、そうすることのメリットが書かれていた。
また、新規リード（見込み客）はいつか頭打ちになるため、どうすればリードを獲得することができるのかが書かれていた。


■新出ワードメモ

+ SFA:営業支援システム、営業が商談管理をおおなうツール（Sales Force Automation）
+ ナーチャリング:リードを育成すること
+ CRM:顧客関係管理といって、顧客を中心に考えて利益を最大化する手法。顧客情報を分析し、可視化する。(Customer Relationship Management）


`今回はここまで`

`qiitaを執筆してのメモ`
今回はアウトプットのため、自分用のメモ感がすごかった。
もう少し見ている人へわかりやすい内容にまとめた方が良いと感じたのでこれからは思考錯誤していきます。
Ruat Actix-webでCSVのZipファイルダウンロードコードです

# Actix-webでファイルダウンロードコードです

# Cargo インストール
```
csv = "1.1.6"
zip = "0.5.12"
```

# コード書く
```
#[get("report")]
async fn execute(
// 何かする
) -> Result<HttpResponse, ApiError> {

    // CSV作成
    let mut wtr = Writer::from_writer(Vec::new());
    wtr.write_record(&["a", "b", "c"])?;
    wtr.write_record(&["x", "y", "z"])?;


    // ZIP作成
    let mut zip = zip::ZipWriter::new(std::io::Cursor::new(Vec::new()));
    let options = zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Stored);
    zip.start_file("hello_world.csv", options)?;
    zip.write(&wtr.into_inner()?[..])?;
    zip.flush()?;
    let result = zip.finish()?;
    Ok(
        HttpResponse::Ok()
        .header("content-encoding", "application/zip")
        .header("Content-Disposition", "attachment;filename=sampleZip.zip")
        .body(result.into_inner())
    )

```
GitHubにpushした時のエラー

## GitHubのpush時にエラー発生

git push origin masterと入力し、GitHubに変更内容を反映させようとしたところ
下記のようなエラーが発生して怒られてしまいました。


```

 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://github.com/MASAKi-cell/php01.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

```

## 解決方法
調べてみると、stackoverflowで同じようにエラーに直面している方がいました。


<a href="https://stackoverflow.com/questions/20939648/issue-pushing-new-code-in-github">
Issue pushing new code in GitHub</a>


リモートリポジトリを作成した際、Readme.mdを作成しており、ローカルリポジトリでは
その内容がcommitしてないので、反映させる必要がある様です。


## git fetchコマンドでリモートから最新情報をローカルに持ってくる

リモートリポジトリの内容がローカルに反映されていないので「fetch」コマンドを使用して、リモートリポジトリの最新情報を取得していきます。
さらに「merge」してmasterへの最新情報を持ってくるようにします。

git fetchの詳細は下記Qiita記事を参照してください。

<a href="https://qiita.com/wann/items/688bc17460a457104d7d#:~:text=git%20pull%E3%81%AF%E3%80%81%20%E4%B8%8A%E3%81%AEgit,fetch%E3%80%81git%20merge%E3%82%92%E5%90%8C%E6%99%82%E3%81%AB%E8%A1%8C%E3%81%86%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%20%E3%81%A7%E3%81%99%E3%80%82">【初心者向け】git fetch、git merge、git pullの違いについて</a>

``` 

$ git fetch origin master
$ git merge origin/master

```

これで、ローカルにReadme.mdが反映されるので、再度「git push origin master」と打ち込むと正常に反映されます。


以上です。
CSVデータをSQLServerにインポートする(DataTable経由)

ここではカラムをidとnameの２つとする。

```sample.vb
        'ダイアログを開く
        Using ofd As OpenFileDialog = New OpenFileDialog
            'デフォルトのファイル名を指定する
            ofd.FileName = "新規社員リスト.csv"

            Dim filename As String = ofd.FileName

            '選択できるファイルの種類（拡張子）を限定する
            ofd.Filter = "CSV Files |*.csv"

            If ofd.ShowDialog() = DialogResult.OK Then

                Using sr As New StreamReader(ofd.FileName, Encoding.UTF8)

                    Dim dt As DataTable
                    Dim dr As DataRow
                    Dim i As Integer

                    dt = New DataTable("DataTableHoge")
                    dt.Columns.Add(New DataColumn("id", GetType(String)))
                    dt.Columns.Add(New DataColumn("name", GetType(String)))

                    Using textParser As New TextFieldParser($"C:\Users\Desktop\{filename}", System.Text.Encoding.GetEncoding("Shift-JIS"))

                        'CSVファイル
                        textParser.TextFieldType = FieldType.Delimited

                        '区切り文字
                        textParser.SetDelimiters(",")

                        'ファイルの終端までループ
                        While Not textParser.EndOfData
                            
                            '1行読み込み
                            Dim row As String() = textParser.ReadFields()

                            'DataRow作成
                            i = 0
                            dr = dt.NewRow()
                            For Each col As String In row
                                dr(i) = col
                                i += 1
                            Next

                            'DataTableに追加
                            dt.Rows.Add(dr)
                        End While
                    End Using

                    ' SQLServerに接続する
                    Dim con As New SqlConnection(
                    "Data Source=HOGE\SQLEXPRESS;" +
                    "Initial Catalog=hogehoge;" +
                    "Integrated Security=True")
                    Dim cmd As New SqlCommand
                    Dim sql As New StringBuilder
                    con.Open()
                    cmd.Connection = con

                    sql.AppendLine("INSERT INTO dbo.HOGE ")
                    sql.AppendLine("( ")
                    sql.AppendLine("  id, name ")
                    sql.AppendLine(") VALUES ( ")
                    sql.AppendLine("  @id, @name ")
                    sql.AppendLine("); ")

                    For n As Integer = 0 To dt.Rows.Count - 1
                        cmd.Parameters.Clear()

                        'パラメータの作成
                        cmd.Parameters.Add("@id", SqlDbType.Int).Value = dt.Rows(n).Item(0)
                        cmd.Parameters.Add("@name", SqlDbType.VarChar).Value = dt.Rows(n).Item(1)

                        'プロシージャの実行
                        cmd.CommandType = CommandType.Text
                        cmd.CommandText = sql.ToString()
                        cmd.ExecuteNonQuery()

                    Next n
                End Using
            End If
        End Using
```
wp-cli の使いかた

インストール

```bash
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
```

```bash
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
```

バージョンの確認

```text
$ wp --version
WP-CLI 2.5.0
```

WordPress のインストールしてあるフォルダーで

テーマの状態を確認

```text
$ wp theme status
3 installed themes:
  I twentynineteen  2.0
  I twentytwenty    1.7
  A twentytwentyone 1.3

Legend: I = Inactive, A = Active
```

テーマのインストール

```text
$ wp theme install habakiri --activate
Installing habakiri (2.5.2)
https://downloads.wordpress.org/theme/habakiri.2.5.2.zip からインストールパッケージをダウンロード中...
Using cached file '/home/uchida/.wp-cli/cache/theme/habakiri-2.5.2.zip'...
パッケージを展開しています…
テーマをインストールしています…
テーマのインストールが完了しました。
Activating 'habakiri'...
Success: Switched to 'habakiri' theme.
Success: Installed 1 of 1 themes.
```

プラグインの状態を確認

```text
$ wp plugin status
2 installed plugins:
  I akismet 4.1.9
  I hello   1.7.2

Legend: I = Inactive
```

参考ページ
[WP-CLI Commands](https://developer.wordpress.org/cli/commands/)
viewModelScope.launch { } の Job を公開したくない件

## 発端

`viewModelScope.launch { }` を使うときにネストが大きくなるのを避けたいなどの理由で、以下のように `=` を使って書くことがあります。

```kotlin
fun buy(item: Item): Job = viewModelScope.launch { // ← return type は Job
    // do something
}
```

しかしながら、不用意に `Job` を公開することになるのが若干気になります(気にならない人は気にならないかもしれない)。

かといって `=` を使わないと若干不格好な感じがします。

```kotlin
fun buy(item: Item) {
    viewModelScope.launch {  // ネストが大きくなり、本質的なコードがかすんでしまう
        // do something
    }
}
```

## どうすればいいか考える

F# という関数型言語には `ignore` というものがあって、名前の通り関数の返り値を無視することができます。これを Kotlin の世界でも使うことができれば上記の問題を解決できそうです。

```fsharp
let add x y = x + y
add 2 3 |> ignore      // 返り値 を無視する
```

## Kotlin で F# の ignore 相当の関数を作る

アイデアはとても簡単です。何もせず `Unit` を返すだけの拡張関数を作ります。

```kotlin
fun <T> T.ignore() = Unit
```

## 解決

先程の`ignore()`を `viewModelScope.launch { }` の後ろに書いてあげると... できました 🎉
こうすればネストを最小限にしつつ Job を公開せずに済みます。

```kotlin
fun buy(item: String): Unit = viewModelScope.launch { // ← return type が Unit になった!
    // do something
}.ignore()
```

しかも最後に `ignore()` をつけるかどうかで `Job` を公開するかどうかを選択することもできていい感じですね！
RubyのStringクラスに翻訳機能をつけてしまった話

# 翻訳知りたいけど、irbの外の世界って面倒くさいよね

上記のような思いをもって、解決作を探りました。
結局は`String`クラス自体に翻訳機能をつけることにしました。
このGemの目的はあくまで遊びです。

コード的には以下で行けました：

```ruby
class String
  include Translation
end
```
Stringというクラスを開いて、今回の怪しい翻訳機能を中にいれています。

これで以下のような動作ができるようになりました：


<script id="asciicast-417971" src="https://asciinema.org/a/417971.js" async></script>

これで翻訳も簡単だ！
DeepLのAPIキーを取得して、

```sh
$ gem install translate_self
$ export DEEPL_AUTH_KEY="your-api-token"
```
上記操作だけで翻訳がString自身でできるようになります。

今回は`define_method`を初めてちゃんと使って、それで対応言語全部にたいして`translate_to_#{言語}`のような使い方ができるようになりました。ソースでいうと以下のようになっています：

```ruby
%w[bg cs da de el en es et fi fr hu it ja lt lv nl pl pt ro ru sk sl sv zh].each do |lan|
 define_method("translate_to_#{lan}") do |language = lan|
   call_deepl(self, self.language, language)
 end
end
```

25個のメソッドを上記だけで定義できたと考えると気持ちいいですね。

## Benchmark

実はパフォーマンスはそんなに悪くないかもしれない？

```shell
C:\home\sampo\translate_self> ruby benchmark.rb
Rehearsal -------------------------------------------------------
normal string         0.252435   0.000000   0.252435 (  0.252490)
translatable string   0.299736   0.000000   0.299736 (  0.299789)
---------------------------------------------- total: 0.552171sec

                          user     system      total        real
normal string         0.237091   0.000000   0.237091 (  0.237091)
translatable string   0.237607   0.000000   0.237607 (  0.237611)
```

ソースは以下リンクから確認できます:
https://github.com/sampokuokkanen/translate_self
VCP-DCV2021取得にあたり

#VMWAREコース受講
VMware vSphere: Install, Configure, Manage [V7]

5月中頃、ネットワールド主催の上記ライブオンラインコースを受講しました。
集合研修やオンデマンドコースもあるらしいよ。

Troubleshootingの方がよかったかな。値段が違うみたいだけど

#試験に向け
VCP-DCV2021取得にあたり、下記いずれかのパターンでの試験合格が必要

①vSphere Foundations試験 (2V0-01.19) ＆ Professional VMware vSphere 6.7 (2V0-21.19)　※2021/6月末まで
②Professional VMware vSphere 7.x (2V0-21.20)

悩んだあげく①のパターンで行くことに。vSphere Foundations受験分の費用は余計にかかったが。

理由としては下記
vSphere 6.7の経験が多い
クラムメディアは2V0-21.19までしか無かった。
　→トレーニングモード、練習モード等色々機能がありクラムメディアが良かった。
　→日本語対応の2V0-21.20の問題集を他に探したけど、信頼できそうなサイトが見つけられなかった。
6月末までという期限が切られている。※期限が決まってないとやる気がでない:)

#受験
vSphere Foundations試験 (2V0-01.19) を自宅からオンラインで受験。合格基準が300/500。1万5000円くらい。
カンニングし放題。
事前に日本語問題集をヤフオクで2000円で入手したので回答を見ながら受験。すべて表記は微妙に違うけどすべて問題集に乗ってたかな。
結果378/500で合格ｗｗｗなんでだよｗｗｗ


まぁ無事合格したのでProfessional VMware vSphere 6.7 (2V0-21.19)に向けて勉強する。
クラムメディアで30日間のプランを6000円くらいで購入。
とりあえず適当に数十問といてみるもまったくわからないので、問題を理解する事は諦め丸暗記する事にする。

1～2日程度の勉強でほぼ100％正解するまでいけたので、そのままの勢いで受験。
これも全部クラムメディアに乗ってたかな。10分程度で終わる。
結果395/500ｗ

これで無事VCP-DCV2021の要件を満たしましたとさ。

あ、Professional VMware vSphere受験バウチャーはコース受講中に頂きました。

ビビッて有料の日本語問題集を探したけど、別に英語の問題集でよかったかも。
単語自体は難しくないので、英語が苦手でも理解できるはず。
無料のもあるみたいだし。
https://www.examtopics.com/exams/vmware/2v0-2120/
ターミナルでERRORとかに色をつける

# やりたいこと
ErrorとかWarningとかに色がつけたいよね。

# .bashrcに追加

```bash:.bashrc
function highlight(){
    grep -i --color=auto -e '$' -e error -e warning -e failure $@
}
```

# 使い方
```
$ echo "This is error test" | highlight
```
> This is <font color=red>error</font> test

```
$ echo "This is error test" | highlight -e is
```
> Th<font color=red>is is</font> <font color=red>error</font> test


# 参考リンク
- [Linuxでファイル・標準出力の特定のキーワードだけハイライト表示させる | 俺的備忘録 〜なんかいろいろ〜](https://orebibou.com/ja/home/201602/20160205_001/)
eval "$(pyenv init -)" がうまく動かない時の対処法

#参考

https://github.com/pyenv/pyenv/issues/1906


#問題

RaspiOSでpyenv使おうとしたら

```
WARNING: `pyenv init -` no longer sets PATH.
Run `pyenv init` to see the necessary changes to make to your configuration.
```

っていうのが出て、`which python` してもpyenvのpythonじゃなく `/usr/bin/python` を見てしまっていた。

#解決策
```
eval "$(pyenv init -)"
```
を

```
eval "$(pyenv init --path)"
```
に書き換えたらうまくいった
【JAVA】 superとは

#【JAVA】superとは

##superとは
継承元を呼び出す

##ルール
superは、コンストラクタの最初に書かないといけない

##superの使い方
##super()
```java:main
public class Main {
    public static void main(String[] args) {
        SubRabbit sub = new SubRabbit();
    }
}

// サブクラス
class SubRabbit extends Rabbit {
    public SubRabbit() {
        super();
    }
}

// スーパークラス
class Rabbit {
     public Rabbit(){
        System.out.println("うさぎ");
    }
}
```
```java:実行結果
うさぎ
```

##super(引数)
```java:main
public class Main {
    public static void main(String[] args) {
        SubRabbit sub = new SubRabbit();
    }
}

class SubRabbit extends Rabbit {
    public SubRabbit() {
        super("むぎ");
    }
}

class Rabbit {
     public Rabbit(){
        System.out.println("うさぎ");
    }
     public Rabbit(String rabbitName) {
    	 System.out.println("うさぎの名前：" + rabbitName);
     }
}
```
```java:実行結果
うさぎの名前：むぎ
```

##super.変数
```java:main
public class Main {
    public static void main(String[] args) {
        SubRabbit sub = new SubRabbit();
    }
}

class SubRabbit extends Rabbit {
    public SubRabbit() {
        System.out.println(super.usagi);
    }
}

class Rabbit {
	String usagi = "うさぎ";
}
```
```java:実行結果
うさぎ
```

##super.関数
```java:main
public class Main {
    public static void main(String[] args) {
        SubRabbit sub = new SubRabbit();
    }
}

class SubRabbit extends Rabbit {
    public SubRabbit() {
        super.RabbitInfo();
    }
}

class Rabbit {
	public Rabbit() {
	}
	
	public void RabbitInfo() {
		System.out.println("うさぎはかわいい");
	}
}
```
```java:実行結果
うさぎはかわいい
```
Play framework2.8にDockerを導入してみた

この度Play frameworkの環境をDockerで構築してみたのでメモ。

##使用するdocker image
今回使用したDocker imageはこちら

- [hseeberger/scala-sbt](https://hub.docker.com/r/hseeberger/scala-sbt/)
- [mysql](https://hub.docker.com/_/mysql)

sbtのimageに関してはhseebergerさんが作成したものがあったので使わせてもらいます。
また、データベースにmysqlを使用するのでmysqlのimageも使います。他のデータベースを使う場合は使いたいデータベースのimageを用意してください。


##作成したdocker-compose.yml
複数のコンテナを使う場合はdocker-composeを使うと便利です。
playframeworkのプロジェクトに以下のymlファイルを作成しました。

```yml:docker-compose.yml
version: '3'
services:

  sbt:
    build: .
    image: hseeberger/scala-sbt:8u222_1.3.5_2.13.1
    container_name: sbt
    volumes:
        # このプロジェクト自体をコンテナ内の/rootディレクトリにマウント
        - .:/root
    ports:
        - 9000:9000
    expose:
        - "9000"
    tty: true

  db:
    image: mysql:5.7
    container_name: mysql
    environment:
        MYSQL_DATABASE: playdb
        MYSQL_USER: hoge
        MYSQL_PASSWORD: hogepassword
        MYSQL_ROOT_PASSWORD: hogepassword
    volumes:
        - ./db/data:/var/lib/mysql # データを永続化するためローカルにデータをマウント
        - ./db/sql:/docker-entrypoint-initdb.d # 初期データの投入関係
        - ./db/my.cnf:/etc/mysql/conf.d/my.cnf # 文字コード設定用
    ports:
        - "3306:3306"
    expose:
        - "3306"
```

## play framework側の設定
play frameworkにmysqlを導入するための設定をします。
build.sbtとapplication.confに以下のコードを追加します。

```sbt:build.sbt
libraryDependencies +=  "mysql" % "mysql-connector-java" % "5.1.41"
```

```conf:application.conf
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://db:3306/playdb" #コンテナ名:ポート番号/データベース名
db.default.username=hoge
db.default.password=hogepassword
```

詳しいことはplayframeworkの公式ドキュメントを参照してください。

https://www.playframework.com/documentation/2.8.x/AccessingAnSQLDatabase


##dockerでmysqlを導入するときの注意点
dockerのmysqlはデフォルトのままだと latin1という日本語を扱えない文字コードが設定されているのでutf8やutf8mb4に変更しないといけません。
方法はいくつかありますが、私はmy.cnfファイルを使いました。
プロジェクトにdbディレクトリをつくり、そこに以下のmy.cnfファイルを作成して文字コードを指定します。

```cnf:my.cnf
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci
explicit-defaults-for-timestamp=1
general-log=1
general-log-file=/var/log/mysql/mysqld.log

[client]
default-character-set=utf8mb4
```

先程のdocker-compose.ymlにもありましたが、これをdockerコンテナ内のetc/mysql/conf.d/my.cnfにマウントします。

```yml:docker-compose.yml
volumes:
        - ./db/my.cnf:/etc/mysql/conf.d/my.cnf # 文字コード設定用

```

こちらが参考にした記事。

https://qiita.com/Suzuki09/items/c05664c7c0c08a19cebe

http://ucwd.jp/blog/814

これでmysqlで日本語を扱えるようになります。
ただし変更前に一度作成したテーブルの文字コードはそのままになっているので自分で変更する必要があります。

###mysqlの永続化
また、Dockerでmysqlを導入した場合、気をつけないといけないのがデータの永続化についてです。
当然ですがmysqlに保存したデータはmysqlのコンテナが持っているので、もしmysqlのコンテナを削除したら保存したデータも一緒に消えてしまいます。
それでは困るのでデータはコンテナだけでなくローカル側にも持たせてデータを永続化しましょう。

今回docker-compose.ymlにて以下のコードを記述してコンテナ内のデータをローカルにも持たせています。

```yml:docker-compose.yml
volumes:
        - ./db/data:/var/lib/mysql # データを永続化するためローカルにデータをマウント

```

参考にした記事

https://qiita.com/juhn/items/274e44ee80354a39d872
モバイルアプリ向けDynamoDB設計ハンズオンをやってみた

# 概要

[モバイルアプリ向け DynamoDB 設計ハンズオン][link-1]をやってみました。
このハンズオンでは、モバイルアプリ向けの DynamoDB の設計方針を学ぶことができます。
せっかくなので、学んだことをアウトプットします。

以下[公式説明][link-1]です。

> このラボでは、DynamoDB により提供するモバイルアプリケーションを構築しながら、Amazon DynamoDB での高度なデータモデリングパターンを学びます。DynamoDB を使用する場合、データをモデリングする前にデータへのアクセス方法 (アクセスパターン) を検討することが重要になります。ここではそういったパターンを学ぶために、ソーシャルネットワークを内臓したサンプルのモバイルアプリケーション用に、データモデルを構築していきます。DynamoDB で素早く一貫性のあるパフォーマンスを実現するための、データモデルの設計法を習得できます。

## データモデリングについて

DynamoDB などの NoSQLDB は RDB 等と異なり、速度とスケールの為に設計されています。
そのため、以下の点に注意してモデリングする必要があります。

1. アクセスパターンを検討する
    - まず、DynamoDBをどのような使い方をするのかを検討する。(どういうアプリなのか、どういうリクエストが多いのか等)
        - とっかかりとしては、まずエンティティを抽出し、多重度をつける。
        - 次に、アクセスパターンを検討する。エンティティがどういったデータにどういう操作を行うかを検討する。
            - SNSを例に挙げると、ユーザが他のユーザのプロフィールを参照する等。

2. DynamoDB へのリクエスト数を最適化する
    - 1で検討したアクセスパターンごとにリクエスト数を最小限に抑えるようにテーブルを設計する。
    - 理想は各アクセスパターンに必要なリクエストを1つのみにすること。
    - 最適化を行う為に、DynamoDBのコアコンセプトを理解する。
        - [プライマリキー][link-3]
        - [セカンダリインデックス][link-2]
        - [DynamoDB トランザクション][link-5]

3. リレーショナルモデルの考え方をしない
    - DynamoDB にリレーショナルモデルの考え方を持ち込むと DynamoDB の利点がほとんど失われる。一般的なアンチパターンは以下である。
 
       1.  正規化：
           DynamoDB はテーブルが多くなるにつれて速度が遅くなるため、正規化を行わないほうが良い。
        2. テーブルごとに 1 つのデータ型にまとめる：
        DynamoDB テーブルには単一のテーブルに様々なタイプのデータが含まれる。
        3. [セカンダリインデックス][link-2]を大量に作る：属性の柔軟性を使用してテーブル内の複数のデータ型にかけて単一のセカンダリインデックスを再利用する。

## プライマリキーの設計

- プライマリキーは各エンティティを明確に識別できる必要がある。そのため,個々のアイテムのコアアクションを実行できること確認する。
- プライマリキーはプレフィックスを使用することにより、コンフリクトを防ぐことができる。
    - 同一のテーブルに顧客と従業員がある場合、以下のようにプレフィックスをつけ、エンティティを区別することにより、IDの衝突がなくなる。
        - 顧客：CUSTOMER#\<CUSTOMERID>
        - 従業員：EMPLOYEE#\<EMPLOYEEID> 
- 多対多のマッピングが存在する場合、2つのクエリパターンが必要となる。この場合、パーティションキーとソートキーという二つの値を使う[複合プライマリキー][link-6]を使用する。
    - SNSを例に挙げると、フォロー、フォロワーを管理しているエンティティは、フォローしているユーザを取得するアクセスパターンとフォローされているユーザを取得するアクセスパターンが存在する。

## インデックスの置きかえ

置換インデックスは一般的なセカンダリインデックスのデザインパターンである。置換インデックスを使用して、テーブルのプライマリキーの逆であるセカンダリインデックスを作成する。

置換インデックスは 2 つのシナリオで役に立つ。

- 多対多関係の「反対側」をクエリする場合。
- それ自体が一対多関係の対象であるエンティティの多対一関係をクエリする場合

## 非正規化

DynamoDB ではデータを非正規化することがよくある。非正規化は、結合を回避し、クエリのパフォーマンスを向上させるのに役立つ。非正規化を行うには、クエリ中に両方のアイテムをフェッチしないようにするために、アイテムの属性をそのアイテムを参照する別のアイテムにコピーする。

ただ、非正規化によってデータを持ちすぎるとデータモデルが複雑になる場合があるので注意が必要。

# まとめ

それぞれについてより詳しく知りたい場合には実際にハンズオンを行ってみてください。
手を動かしながら理解することができます。

また、以下にベストプラクティスが載っています。一度参照されると設計がより楽になると思います。

https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/best-practices.html#GuidelinesForItems.MultipleTables

[link-1]: https://aws.amazon.com/jp/getting-started/hands-on/design-a-database-for-a-mobile-app-with-dynamodb/
[link-2]: https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/SecondaryIndexes.html
[link-3]:https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.PrimaryKey
[link-5]:https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/transactions.html
[link-6]:https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.CoreComponents.html#HowItWorks.CoreComponents.PrimaryKey
Rust - Actix-web - Zipファイルダウンロードコード

# Actix-webでファイルダウンロードコードです

# Cargo インストール
```
zip = "0.5.12"

```

# コード書く
```
#[get("report")]
async fn execute(
// 何かする
) -> Result<HttpResponse, ApiError> {

    let mut zip = zip::ZipWriter::new(std::io::Cursor::new(Vec::new()));

    let options = zip::write::FileOptions::default().compression_method(zip::CompressionMethod::Stored);
    zip.start_file("hello_world.csv", options)?;
    zip.write(b"Hello, World!")?;
    zip.flush()?;
    let result = zip.finish()?;
    Ok(
        HttpResponse::Ok()
        .header("content-encoding", "application/zip")
        .header("Content-Disposition", "attachment;filename=sampleZip.zip")
        .body(result.into_inner())
    )

```
Sequel ProでMySQL8.0以降を使用して、DockerからアプリケーションからMySQLをつなげるときにはまったこと

### 問題発生
Dockerを使ってアプリケーション(Laravelなど)からMySQLに接続する(php artisan migrateなどで)時に、
接続できません！！
とターミナルで怒られてしまったのですが、
Sequel Proを見ても動いているし、
MySQLのコンテナに入っても動いているので原因がわからず、
envファイルが違うのかなんなと原因究明していて迷走していたので記事にしました。。。


## 結論
MySQLの認証方式が「mysql_native_password」ではなく、なぜか「caching_sha2_password」を使う必要があったため。

ただ、Sequel Proでは「caching_sha2_password」使えないから「mysql_native_password」を使えよと怒られたので、
使ってみたんですが、この場合はアプリケーションとMySQLは接続できたのでSequel Proを動かしてみたら以下のように怒られてしまいました。

→Sequel Proで使うために「mysql_native_password」を使用したからこんなことになってしまったのです。

多分MySQL8.0以降を使うならMySQL Workbenchとか別のもの使った方がいいのか？


![スクリーンショット 2021-06-03 14.09.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322356/f5376b3e-8d78-fb15-b53b-17341109497b.png)
Sequel Pro Nightly build より

```
MySQL said: Authentication plugin 'caching_sha2_password' cannot be loaded: dlopen(/usr/local/mysql/lib/plugin/caching_sha2_password.so, 2): image not found
```

## まとめ
- MySQL8.0.4以降 のログイン認証方式は caching_sha2_password がデフォルト
- PHP 7.1.16, 7.2.4 以降のバージョンから caching_sha2_password に対応しているので「caching_sha2_password」をそのまま利用する
- しかし、Sequel Pro Nightly buildでは「caching_sha2_password」を使用できない


以上、Sequel ProとMySQL8.0以降を使用する機会があったらご注意ください。(Sequel Pro不具合多いし、MySQL Workbench使った方がいいのかな...)
ほんと環境設定とかで止まるのが辛いです。


参考文献
https://www.suzu6.net/posts/256-mysql8-pdomysql-caching_sha2_password/
https://qiita.com/ucan-lab/items/3ae911b7e13287a5b917
https://qiita.com/ucan-lab/items/b68db1db931c954da921
Jestでcontextを使えるようにする

## これは何

記事投稿イベント「3000文字Tips」の参加記事です。

https://qiita.com/official-events/d523df99d6479293ffa7

## はじめに

RSpec などのテストを書かれる方は、`desctibe` と `context` を使い分けることがあるかと思います。
Jest には `describe` のみが存在していて、 `context` を利用することができませんでした。

Jest を使い始めて慣れて筆者は、久しぶりの RSpec で全部 `describe` で書いてレビュアーから指摘をいただきました()

あまり RSpec と Jest での書き方を分けたくない、同じように書けることを目指して、Jest でも `context` を使えるようにします。

既に context の設定の仕方は Jest のリポジトリでやり方が話されていますが、少し古いので、やり方を少し変える必要があります。

https://github.com/facebook/jest/issues/2468

## 開発環境

検証した環境です。

- Next.js: 10.2.2
- Jest: 26.6.3

## やり方

### context を定義する

issue 内に書いてあるように、describe のエイリアスを context に設定します。

```js:setupTestFramework.js
global.context = describe
```

### Jest 実行時に作成したファイルを読み込むようにする

```js:jest.config.js
module.exports = {
  setupFilesAfterEnv: ['./setupTestFrameWork.js'],
}
```

元々はpackage.jsonや、jest.config.js に `setupTestFrameworkScriptFile` を定義していたようですが、今は `setupFilesAfterEnv` に置き換わったとのことです。
これで、testファイル内で `context` を利用できるようになりました。

### VSCode でエラーが出るのを解消する。

これで終わり！と思いきや、testファイルを開いてみると、何やら context に赤線が...

![VSCodeでエラーが出ている画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166596/693a08c0-54b6-4073-034f-a582c50df2e5.png)

Jest は context を解釈してくれていますが、VSCodeがそれを認識できず、エラーになっているようです。

手っ取り早く解消するのは、`d.ts`に定義してあげるのが良さそうです。

```
declare let context: jest.Describe
```

こちらで赤線が解消されます。
node.jsで、A処理が終わったらB処理を実行するアレを今更書いてみる

[node.jsで、A処理が終わったらB処理を実行するアレを今更書いてみる | ハイテク好きが楽しめるウェブメディア off.tokyo](https://off.tokyo/blog/node-a-b/)

---


node.jsに限らず、非同期処理を書いてると、上から順番に処理が走らずに変数が未定義のまま次の処理が走ってしまうことがあります。

 

これを解決するためには、コールバックみたいなものを書いて、処理Aがリターンされたら、処理Bを実行するみたいなことを書かないといけません。

 

まあ、この手の詳しいことはいくらでも詳しく書いてる情報があるので、今回の記事は備忘録みたいな感じで書くだけです。

 

書いたコードはこんな感じです。

 

```js
    async function A() {
      try {
        // この中でawaitなりで非同期処理でapiとか叩く
         return "返り値";
      } catch (err) { 
        console.log("エラー発生");
        console.log(err);
      }
    }
 ```

こんな感じですね。tryの中でapiなりを叩いて、それを受け取ったらリターンする。

```js
    A().then(result => {
      console.log("Aの処理がリターンされたらBを発動させる"); 
      B(result)
    });
 ```

resultはA()を実行して返ってきた値です。

 

非同期処理で普通に書いてると未定義で進んでしまうのを防ぎます。


---

[node.jsで、A処理が終わったらB処理を実行するアレを今更書いてみる | ハイテク好きが楽しめるウェブメディア off.tokyo](https://off.tokyo/blog/node-a-b/)
Windows 10にAerospikeの Community Editionをインストール

Windows 10にAerospikeの Community Edition (Docker) をインストールしたときのメモ。

Install on Windows
https://download.aerospike.com/docs/operations/install/docker/win/index.html
公式サイトのこのページには、Enterprise Editionの話しか書いてなく、Community Editionはどうやって入れるのか分からなかった。

Using Vagrant On Windows
https://download.aerospike.com/docs/operations/install/vagrant/win/using-vagrant.html
ちなみにCommunity Edition は Vagrantを使う以前からの方法もあったけれど、deprecatedになりDocker版を使えと書いてあった。。。
（Install on Windowsページの左側のメニューのInstall on Windowsの左の＋をクリックするとこのページが出てくる。ちなみにこのページのリンクをクリックしても、上のInstall on Windowsページにリダイレクトされて表示されない！ので見つけるのに苦労した。この方法ではやってほしくないのか隠されてるっぽい（笑））
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/b2e41c83-4f9b-9d90-d7fd-32387e457666.png)

探していたら、DockerのCommunity Edition あるらしい事がわかった。
https://qiita.com/suganury/items/b3cdcf4fd2cb2eba66ac
今回はこれを使う。

# 1 Docker インストール
Dockerが必要なので、
ここから、まずDocker Desktopをインストールした。
https://hub.docker.com/editions/community/docker-ce-desktop-windows/

# 2 インストール
コマンドプロンプトで、
```docker pull aerospike:ce-[version]```
https://hub.docker.com/_/aerospike の __Supported tags and respective Dockerfile links__ を見て、
例えばce-5.6.0.4なら、
```docker pull aerospike:ce-5.6.0.4
```とする。
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/587e8806-7ac5-0894-5d4f-02a3bce159e4.png)

# 3 起動
```docker run -d -v DIR:/opt/aerospike/etc/ --name aerospike -p 3000:3000 -p 3001:3001 -p 3002:3002 aerospike:ce-[version]```

docker runコマンドでコンテナを作成した後は、Docker DesktopのUIでも起動や停止（startやstop）できる。
![Docker Desktop aerospike.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/56deae27-fd73-d5d1-4685-c9b90189a83b.png)


# 4 ログイン
```docker exec -it aerospike /bin/bash```

# 5 AQL で操作
SQLのようなクエリ言語AQL(Aerospike Query Language)でAerospike を操作する。

https://docs.aerospike.com/docs/tools/aql/

```aql``` でAQLを起動。
```quit``` でAQLを終了。

# 6 Docker ログアウト
"control"を押した状態で"P、Q"を順番に押す。

# 参考にしたページ
https://qiita.com/suganury/items/b3cdcf4fd2cb2eba66ac

https://qiita.com/suzukihi724/items/961112f6578a60dd6266#0-docker%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%97%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3
【2021年6月最新版】ExpressをserverlessでAPI GatewayからLambdaを使ってWeb APIを使用する方法

最近色々と忙しく、約1か月ぶりの投稿になります。

今回の内容は、Node.js（Express）で作成したAPIを、AWSのLambdaで環境構築を行うという内容です。

そこまで難しくは無いのですが、権限の部分で少し躓いたので、次回からは躓かないように記事を書いていきます。

# はじめに

まず初めに必要なパッケージをインストーしておきましょう！

```powershell
npm i @vendia/serverless-express express
```

# ローカル環境構築

次に、以下のようにプロジェクト直下にファイルを作成していきましょう。

```powershell
touch app.js server.js lambda.js
```

```app.js
const express = require("express");
const app  = express();

// ルーティングの設定
app.get("/", (req, res) => {
  return res.send("Hello");
});

// 他にルーティングなどの設定を行っていたらここに書いてください

module.exports = app;
```

```server.js
const app = require("./app");
const port = 3000;

// HTTPサーバを起動する
app.listen(port, () => {
  console.log(`listening at http://localhost:${port}`);
});
```

```lambda.js
const serverlessExpress = require('@vendia/serverless-express')
const app = require('./app')

const server = serverlessExpress.createServer(app)

exports.handler = (event, context) => serverlessExpress.proxy(server, event, context)
```

このように設定したら、まずはローカルで動くかの検証をしてください。

```powershell
node server
```

ここで動かなかったらLambdaにアップロードしてもエラーが起きるので、今一度ご確認ください。

# Lambdaへアップロード

## 権限

ここまできたらあとはデプロイすだけなのですが、人によっては権限のエラーの種類が違うと思うので、必要な権限を書いておきます。

・AmazonS3FullAccess
・CloudWatchLogsFullAccess
・AmazonAPIGatewayAdministrator
・AWSCloudFormationFullAccess
・AWSLambda_FullAccess

## serverless.yml

サーバーレスでデプロイするには``serverless.yml``を作成し、以下のように設定してください。

```
touch serverless.yml
```

```serverless.yml
service: example

provider:
  name: aws
  runtime: nodejs12.x
  region: ap-northeast-1

package:
  exclude:
    - .git/**
    - test/**
    - README.md

functions:
  exampleFunction:
    handler: lambda.handler
    events:
      - http: ANY /
      - http: 'ANY {proxy+}'
```

## デプロイ

```powershell
npx serverless deploy
```

EndpointのURIが表示されればOK

# 権限を追加してもエラーが出る場合

上の権限を追加してもエラーが出る場合以下の2つを試してください。

まず、エラー名に``CreatRole``や``PutRolePolicy``の権限がありません的なエラーが発生した場合は「IAM」から今デプロイしようとしているユーザーを選択。

「アクセス権限」の「インラインポリシーの追加」をクリック。

「JSON」タブを選択し、以下のコードをコピペ。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "OperationRole",
            "Effect": "Allow",
            "Action": [
                "iam:AttachRolePolicy",
                "iam:CreateRole",
                "iam:PutRolePolicy"
            ],
            "Resource": "*"
        }
    ]
}
```

「ポリシーの確認」をクリックし、名前は適当に入力。

デプロイする前に以下のコマンドを入力

```powershell
npx serverless remove
```

この時にエラーが起きたら、AWSコンソールから手動で消去してください。

```powershell
npx serverless deploy
```

AWSは権限周りが色々と面倒くさいですね。

でも権限にうるさいのは逆にありがたいことなのかも？？

こんな感じで実装することができました！

以上、「【2021年6月最新版】ExpressをserverlessでAPI GatewaykaraLambdaを使ってWeb APIを使用する方法」でした！

Thank you for reading

# 参考記事

[serverless-expressでAPI GatewayからLambdaを実行する](https://zenn.dev/yuta_saito/articles/8b543a1957c375593ee5)
【STUDIO】Googleカレンダーを埋め込む方法

今回は、STUDIOを用いて、googleカレンダーを埋め込む方法を紹介します！

ポイントは2点です！

①googleカレンダーの iframe コードを取得
▼参考記事
https://support.google.com/calendar/answer/41207?hl=ja

この記事に従って、iframeコードを取得します。
この際、カレンダーのアクセス権限に注意しましょう！公開していい範囲を指定します。

取得できたら
②iframeコードをstudio内にペースト

studioを開き、左メニューの「追加」＞「Box」＞「iframe」を選択します。
![スクリーンショット 2021-06-03 13.02.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1550168/e1d6a6d8-22f8-9db3-e5ab-3d55ee9d96fe.png)


選択すると右側にこのような画面が出てきます。
![スクリーンショット 2021-06-03 13.05.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1550168/a3b9d260-5b31-7957-509d-d259da6f8beb.png)

こちらに先ほど取得したiframe コードをペーストすると、googleカレンダーが表示されると思います！

以上、STUDIOを用いて、googleカレンダーを埋め込む方法でした！
Strpeを使ってみる


# はじめに
[Stripe](https://stripe.com/docs)はオンライン決済サービスです。TwitterなどのSNSにURLを貼ることで物販やサービスの決済ができます。マイクロECショップの構築などに使えるサービスです。

[アカウント作成はこのあたり参考](https://qiita.com/Annoske/items/25dc74a4fc406c80e4fc)

# テストのリンク作成
[商品1](https://buy.stripe.com/test_4gweYf6mZgPmauQbII)

[商品2 100円](https://buy.stripe.com/test_9AQdUb5iVaqY1YkdQR)

# 【違いはココ】決済代行の”PayPal”と”Sprite”を徹底比較
https://n10shop.com/post-49191/
Eclipseの初期設定

#はじめに
Eclipseを使用するのに便利な初期設定。

#コンテンツアシストのショートカットキー変更

###windows

1. ウインドウ　＞　設定
1. 一般（＋）　＞　キー
1. 「コンテンツ・アシスト」を選び、バインディングに「Shift + Space」を設定
1. 「適用」　＞　「OK」


#構文色指定

###windows

1. Javaソースコード上で右クリック　＞　設定
1. エディター（＋）　＞　構文の色の指定
1. Java（＋）

* パラメータ変数：赤
* フィールド　　：青
* ローカル変数参照：ピンク
* ローカル変数宣言：ピンク＋太字

#おわりに
必要に応じ更新します。
Let's Encryptでレート制限に引っかかった。

皆さん注意しましょう、というだけの話です。


## 結論から言うと

ちゃんと外部から80番でアクセスできるよう、ネットワーク、ファイアーウォールの設定を確かめてから、certbotを動かしましょう。
検証の失敗は1時間に5回までは許されているようです。
それを超えると1週間は申請できない模様です。

## 経緯

久しぶりにあるテストでLet's Encryptで証明書をもらおうとしていました。
久しぶりすぎて、作業開始の時点ではLet's Encrypyでは外部から80番へのアクセスが必要なのを忘れていた。
そもそも80番でサーバを立ち上げる予定はなかった。
公式サイトを読みながら、`certbot certonly --standalone`で立ち上げてFQDNを入れた。

公式サイト

https://certbot.eff.org/lets-encrypt/centosrhel7-other

そうすると、以下エラーが出た。

```
Certbot failed to authenticate some domains (authenticator: standalone). The Certificate Authority reported these problems:
  Domain: hoge.example.com
  Type:   connection
  Detail: Fetching http://hoge.example.com/.well-known/acme-challenge/ごにょごにょ: Timeout during connect (likely firewall problem)

Hint: The Certificate Authority couldn't exterally verify that the standalone plugin completed the required http-01 challenges. Ensure the plugin is configured correctly and that the changes it makes are accessible from the internet.

Some challenges have failed.
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
```

`(likely firewall problem)`とある。
自宅の中で試験的に立ち上げたサーバだったので、そうだ、そもそも外部から80番にアクセスできないとだめだったんだ。ルータでポート開放しないとならないですよね、と思い出す。

これもまた久しぶりだったので、静的NATとフィルターと…、などと設定し、再度`certbot certonly --standalone`をやってもエラーが改善せず。
そういやルータのアウト側のフィルターもあるか、あとどこだ？などと何度か`certbot certonly --standalone`をやっていた。
何度かやってから、そもそも一度Webサーバ立ち上げて、そこで外部からページが見えるようにしておいたほうがいいなと、とりあえずApacheを入れて、ルータの設定をいじり、外部から80で見えるようにした。

これで問題ないだろうと再度`certbot certonly --standalone`をやったところ、

```
An unexpected error occurred:
There were too many requests of a given type :: Error creating new order :: too many failed authorizations recently: see https://letsencrypt.org/docs/rate-limits/
Ask for help or search for solutions at https://community.letsencrypt.org. See the logfile /var/log/letsencrypt/letsencrypt.log or re-run Certbot with -v for more details.
```
というエラーが。
嫌な予感がしながら、URLを開いてみる。

https://letsencrypt.org/docs/rate-limits/

古いとは書いているけど日本語訳もありました。

https://letsencrypt.org/ja/docs/rate-limits/

日本語訳の方を見ると、

> 検証の失敗は、1アカウントごと、1ホスト名ごと、1時間毎に、5回までに制限されています。

あ。はい。確かに1時間に5回はやったかも…。
制限解除できるんだろうか…。
ドキュメントの下に、

> レート制限に引っかかった場合、制限を一時的にリセットする方法はありません。レート制限が解消されるまで1週間後まで待つ必要があります。

との記載。ああああぁ…。1週間…。

みなさん、横着はしないでちゃんと順序どおりに作業してくださいね…。
80番を開放したルータのフィルターをそっと削除しました…。
Eclipseの便利なショートカットキー

#はじめに
自分が良く使うショートカットキーをまとめました。

#まとめ
|名前|キー|備考|
|:-:|:-:|:-:|
|戻る|ctrl + z ||
|やり直す|ctrl + Y ||
|変数名一括変更|shift + alt + R||
|行削除|ctrl + d||
|コメントアウト|ctrl + \/||
|選択行を移動|alt + ↑ or ↓|複数行可|
|選択文字列を大文字化|ctrl + shift + X||
|選択文字列を小文字化|ctrl + shift + Y||

#おわりに
随時更新します。
【学生向け】学生のためのAWS学習リソース

先にいっておきますが，AWSを使ったからといって，サーバ構築の知識がなくてもwebサービスを簡単に公開できるわけではないです．
また，費用に関してもサーバにするためにラズベリーパイや中古PCを買ったりするよりも安くできる!なんてことは無いです．
同じくらいの費用はかかります．


## アカウント作成
### AWS Educate
- 登録にクレジットカード不要
- オンライン動画などがある
- 以下理由のため個人アカウントと併用して使うのがオススメ．
- 共有アカウントの1ユーザー?的振る舞いで，制限されるサービスがあります

https://aws.amazon.com/jp/education/awseducate/



## 情報収集先
### AWSに関する情報収集(日本語)は，[日本の APN プレミアティアパートナー](https://aws.amazon.com/jp/premiumsupport/knowledge-center/)が発する情報がだいぶ正確です

 中でもオススメは，DevelopersIOで知られるクラスメソットとサーバーワークスのブログです．

#### -[クラスメソッド発「やってみた」系技術メディア | DevelopersIO]
https://dev.classmethod.jp/

#### - [サーバーワークスエンジニアブログ]
https://blog.serverworks.co.jp


 あまり知られていませんが，AWS公式ブログのbuilders.flashというのもあります.
####【builders.flash】
https://aws.amazon.com/jp/builders-flash/?awsf.filter-name=*all


## 無料動画
(以下は学生向けというより，AWSの導入中や検討中の場合に見ることが多いのですが一応)

### 得体の知れないサービスの概観を掴みたいときはBlackBeltSeminarの動画がオススメ
資料が公開されている場合もあります．
#### 【AWS Black Belt Online Seminar】
https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/

### 【Amazon Web Services Japan 公式 YouTubeチャンネル】
https://www.youtube.com/channel/UCnjKWUK2t5QJYfeqqilhJhQ

## よくある質問の解決方法
### 【AWS ナレッジセンター】
https://aws.amazon.com/jp/premiumsupport/knowledge-center/
findのまとめ　find_byのまとめ　whereのまとめ

findのまとめ
・主キーに対応するレコードを取り出す
・主キーを複数指定することも可能
・主キーが１つでも見つからない場合ActiveRecord::RecordNotFound例外が発生する
・findで取得したオブジェクトのクラスはBook　

find_byのまとめ
・与えられた条件にマッチするレコードのうち最初のレコードだけを返す
・条件を複数指定することができる
・与えられた条件がない場合nilを返す
・find_byで取得したオブジェクトのクラスはBook

whereのまとめ
・与えられた条件にマッチするレコードをすべて返す。
・NOT条件
・AND条件
・OR条件
・条件にマッチしない場合は空の配列を返す
・取得したオブジェクトのクラスはBook::ActiveRecord_Relation
Microsoft Excelでシート名を抽出し一覧にする方法

定義書や基本設計仕様書などを作成する際の目次に使うため
シート名の一覧を抽出する方法のメモ

1. 「数式」タブをクリック
2. 「名前の定義」をクリック

![スクリーンショット 2021-06-02 午前11.38.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100163/448cf726-8937-08d7-e97e-35ca98904e48.png)


3.データ範囲の名前を入力してくださいの項目に
　適当な名前を入力(例 SheetName)

4.セルの範囲を選択してください
　`` =GET.WORKBOOK(1) ``と入力


5.「OK」ボタンを押下

![スクリーンショット 2021-06-03 午後0.22.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100163/32330e17-2102-6e98-5ede-99b9381feff5.png)


6.シート名を出したいセルに次の数式を入力し、オートフィルする
　``=REPLACE(INDEX(SheetName,ROW(A1)),1,FIND("]",INDEX(SheetName,ROW(A1))),"")``
太陽観測にarduino

さて太陽観測にarduinoを導入する
![UNADJUSTEDNONRAW_thumb_fdb9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654098/dfd0c4a8-f578-fd59-53cd-d2d7802edfff.jpeg)
Nuxt.jsのnuxt.config.jsをtsファイルに変更して型定義を追加する方法【nuxt.config.ts】

TypeScript導入時などに、nuxt.config.jsをtsファイルに変更する方法になります。

## nuxt.config.jsの拡張子をtsに変換
まずは、拡張子をjsからtsに変換します。

## @nuxt/typesを読み込み、型定義を追加する
### 変更前
```js:nuxt.config.js
export default {
  mode: 'universal',
  /*
   ** Headers of the page
   */
  head: {
    title: process.env.npm_package_name || '',
    meta: [
      { charset: 'utf-8' },
      { name: 'viewport', content: 'width=device-width, initial-scale=1' },
      {
        hid: 'description',
        name: 'description',
        content: process.env.npm_package_description || ''
      }
    ],
    link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
  },
  /*
   ** Customize the progress-bar color
   */
  loading: { color: '#fff' },
  /*
   ** Global CSS
   */
  css: [],
  /*
   ** Plugins to load before mounting the App
   */
  plugins: [],
  /*
   ** Nuxt.js dev-modules
   */
  buildModules: [
    '@nuxt/typescript-build',
    // Doc: https://github.com/nuxt-community/nuxt-tailwindcss
    '@nuxtjs/tailwindcss'
  ],
  /*
   ** Nuxt.js modules
   */
  modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios'
  ],
  /*
   ** Axios module configuration
   ** See https://axios.nuxtjs.org/options
   */
  axios: {},
  /*
   ** Build configuration
   */
  build: {
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {}
  }
}
```

### 変更後

```ts:nuxt.config.ts
import { NuxtConfig } from '@nuxt/types'

const nuxtConfig: NuxtConfig = {
  /*
   ** 上記と同様なので省略
   */
}

export default nuxtConfig
```
これで、nuxt.config.jsをtsファイルに変換することができます。

### 補足
`@nuxt/types`のバージョンによっては、`Configuration`を使用する必要があります。

```ts:nuxt.config.ts
import { Configuration } from '@nuxt/types'

const nuxtConfig: Configuration = {}
```

しかし、`Configuration`は現在非推奨なので、可能であれば`NuxtConfig`を使用するのが良さそうです。

## 参考
https://typescript.nuxtjs.org/ja