OmniAICreator/Qiita-1.07M huggingface dataset:
wikiのFacadePatternをpython3.xで実装(python3.9)

```python:facade_wiki.py

"""UML
    -------------->   ModuleB
   |                /    |
Facade --> ModuleA       |
   |                \    |
    -------------->   ModuleC
"""

# Module B
class Car:

    def __init__(self):
        self.__speed = 0
        self.__distance = 0

    @property
    def speed(self) -> int:
        return self.__speed

    @speed.setter
    def speed(self, speed: int):
        self.__speed = speed

    @property
    def distance(self) -> int:
        return self.__distance

    def run(self, minutes: int):
        self.__distance += self.__speed * minutes


# Module A
class Driver:

    def __init__(self, car: Car):
        self.__car = car

    def push_pedal(self, speed: int):
        self.__car.speed = speed

    def drive(self, minutes: int):
        self.__car.run(minutes)


# Facade
class DrivingSimulator:
    """Point
    Facadeクラスはあくまでサブシステム内部に仕事を投げるだけで複雑な実装は持たない
    """
    def simulate(self):
        car = Car()
        driver = Driver(car)
        driver.push_pedal(700)
        driver.drive(30)
        driver.push_pedal(750)
        driver.drive(20)
        print(f'The travel distance is {car.distance}m')

# Client
if __name__ == '__main__':
    driving_simulator = DrivingSimulator()
    driving_simulator.simulate()
```
【Project Euler】Problem 83: 経路の最小値（４方向）

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 83.経路の最小値（４方向）

原文 [Problem 83: Path sum: four ways](https://projecteuler.net/problem=83)

**問題の要約：ファイルから読み込んだマトリクスの左上から右下まで上下左右4方向の動きで到達したときの経路の数の和の最小値を求めよ**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1922159/d22793ef-e16e-6225-3533-a95ba182aae6.png)

今回は4方向ということで今までのアルゴリズムが使えないので、最初から[問題 81](https://qiita.com/masa0599/items/1721639ff2189ee38ea8)で使った**networkX**の**single_source_dijkstra**を使います。すると違いはあまりなく4方向のedgeデータを作るだけで解くことが出来ました。

今回は元のデータの周りに十分大きな値**infv**を加えていないので、はじのノードのedgeの処理を考える必要があります。ファイルの読み込みは[問題 82](https://qiita.com/masa0599/items/b30fd7137a6fc91dd0c9)と同じなので省略します。

```python 
# networkXのsingle_source_dijkstraを使って解く（target nodeの値をedgeの重みとして使った）
from itertools import product
import networkx as nx
def nodeName(node):
  return str(node[0])+'-'+str(node[1])

def edgeData(n1,n2):  # node1, node2,
  return [nodeName(n1), nodeName(n2), mtx[n2[0]][n2[1]]]  # use node2 value as edge weight

wedge_list = []
for (y,x) in product(range(msize),repeat=2):
    if x > 0      : wedge_list.append(edgeData((y,x),(y,x-1)))  # left
    if x < msize-1: wedge_list.append(edgeData((y,x),(y,x+1)))  # right
    if y < msize-1: wedge_list.append(edgeData((y,x),(y+1,x)))  # down
    if y > 0:       wedge_list.append(edgeData((y,x),(y-1,x)))  # up

#--- Create the graph from nodes/edges
G = nx.DiGraph()
G.add_weighted_edges_from(wedge_list)

length, path = nx.single_source_dijkstra(G,nodeName((0,0)),nodeName((msize-1,msize-1)))
print(f"answer is : {length+mtx[0][0]}")
print(path)
```

（開発環境：Google Colab）
【Project Euler】Problem 82: 経路の最小値（３方向）

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 82. Path sum: three ways（３方向）

原文 [Problem 82: Path sum: three ways](https://projecteuler.net/problem=82)

**問題の要約：問題81と同じマトリクスの左端のどれかの数から左端のどれかの数まで上、下、右の３方向の動きを使ってで到達したときの経路の数の最小値を求めよ**

この5 x 5の例題では赤の経路で994が最小値となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1922159/3962e10d-7cbc-6d37-31aa-f6fe87e15a2e.png)

[問題 81](https://qiita.com/masa0599/items/1721639ff2189ee38ea8)との違いは始点と終点が決まっていないことと、動きが3方向のことです。特に上と下は進行方向の右に進まない動きなので以下のように965から右の列に動くときに複数の動きを考慮する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1922159/cb301176-a97b-1863-83c7-196ad1fa46e7.png)
これを考慮すればあとは[問題 81](https://qiita.com/masa0599/items/1721639ff2189ee38ea8)と同様に右から、右に一つ動く経路のなかの最小値を一つ左に足して行くことで最小値が求まり、最後の答えは左端の列の最小値となります。今回はマトリクスの部分を切り出すのが容易にできるように**numpy.array**を使いました。

```python 
import numpy as np
mtx = np.array(mtx)
for x in range(msize-2,-1,-1):
  mtx1 = np.array([0]*msize)
  for y in range(msize):
    mtx1[y] = min([ sum(mtx[y1:y:1 if y>=y1 else -1,x])+mtx[y1][x+1] for y1 in range(msize)]) 
  mtx[:,x] +=  mtx1   # add to orinal matrix (column x)
print(f"Answer: {min(mtx[:,0])}")
```
今回は始点と終点が決まっていないということで**networkx**は使いませんでした。

### ファイルの読み込み

```python 
# show upload dialog

from google.colab import files
uploaded = files.upload()
#---- read numbers from file
f = open("p081_matrix.txt")
fmatrix = f.readlines()
f.close()
mtx = []
for l in fmatrix:
  l=l.strip()        #remove cr code
  mtx.append(list(map(int,l.split(",")  )))
msize = 80
```

（開発環境：Google Colab）
画像ファイルをまとめてPDFにするツールを作ってみた

# スマホで撮った書類をまとめてPDFにしたい

こういうときにいちいち変換ツールにかけるのも馬鹿らしいので、プログラム化してみた。

https://github.com/MasatoHanayama/pdf_gen

使い方はgithubのreadme参照。
【Project Euler】Problem 81: 経路の最小値（２方向）

* 本記事は[ProjectEuler](https://projecteuler.net/about)の「100番以下の問題の説明は記載可能」という規定に基づいて回答のヒントが書かれていますので、自分である程度考えてみてから読まれることをお勧めします。

### 問題 81.経路の最小値（２方向）

原文 [Problem 81: Path sum: two ways](https://projecteuler.net/problem=81)

**問題の要約：ファイルから読み込んだマトリクスの左上から右下まで右か下の動きで到達したときの経路の数の最小値を求めよ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1922159/abf49cf5-c8d0-38e4-d34a-e0b5ee15f3dc.png)

ここから3問連続で同じマトリクスに対して違う条件で経路の最小値を求めます。まずは動きが右か下の2方向です。

基本的には「[経路の合計の最大値 （その１）](https://qiita.com/masa0599/items/83727c4b158b7ca07a7c)と同じアルゴリズムで三角形を斜めにして四角形に対応します。はじの処理を簡単にするために、十分大きな値を右辺と下
辺に加えています。ファイル読み込みは後半に添付しています。

```python 
for xy in range((msize-1)*2-1,-1,-1):
  for x in range(msize-1,-1,-1):
    y = xy - x
    if y < 0 or y > msize-1: continue
    mtx[y][x] += min(mtx[y+1][x],mtx[y][x+1])
print(f"Answer: {mtx[0][0]}")
```
### 【別解】networkXを使って解く

この問題はグラフ理論の最短経路問題とみなすことができますので、別解として、**networkX**の**single_source_dijkstra**を使って解いてみます。target nodeの値をedgeの重みとして使いました。

```python 
from itertools import product
def nodeName(node):
  return str(node[0])+'-'+str(node[1])

def edgeData(n1,n2):  # node1, node2,
  return [nodeName(n1), nodeName(n2), mtx[n2[0]][n2[1]]]  # use node2 value as edge weight

wedge_list = []
for (y,x) in product(range(msize),repeat=2):
  wedge_list += [edgeData((y,x),(y,x+1)), edgeData((y,x),(y+1,x))] # right & down edges

G = nx.DiGraph()
G.add_weighted_edges_from(wedge_list)

length, path = nx.single_source_dijkstra(G,nodeName((0,0)),nodeName((msize-1,msize-1)))
print(f"Answer: {length+mtx[0][0]}")
print(path)
```


###　ファイルの読み込み

はじの処理を簡単にするために、十分大きな値**infv**を右辺と下辺に付加しています。

```python 
# show upload dialog
from google.colab import files
uploaded = files.upload()
#---- read numbers from file 
f = open("p081_matrix.txt")
fmatrix = f.readlines()
f.close()
msize = 80    # matrix sizef
infv = 9999*msize   # add infinite value on right and bottom edge
mtx = []
for l in fmatrix:
  l=l.strip()        #remove cr code
  mtx.append(list(map(int,l.split(",")))+[infv])
mtx.append([infv]*(msize+1))
```

（開発環境： Google Colab）
イニシャライザの定義（サンプル）





- 構造体のイニシャライズの定義について


```swift:sample.swift

struct SimplePlus {
    var plus: Int
    var Message: String
    
    // 一つ目のイニシャライザ。
    init(number1: Int, number2: Int){
        plus = number1 + number2
        Message = ""
    }
    // 二つ目のイニシャライザ。
    init(number1: String, number2: String){
        plus = Int(number1)! + Int(number2)!
        Message = "\(number1) + \(number2) = \(plus)"
    }
}

var ans1 = SimplePlus(number1: 4, number2: 5)
print(ans1.plus)
var ans2 = SimplePlus(number1: "1", number2: "2")
print(ans2.Message)



```
GitHub Issueのタスクを絵文字で見やすくする

# 背景

以下の記事をみつけて、GitHubのIssueやPull Request内のタスク（チェックリスト）も見やすく出来そうだったので絵文字を導入してみました。

https://qiita.com/sho_v00/items/a1b04522e113d35ee776

# 導入イメージ

![issue.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345760/9bd9a9b1-bbb2-f90e-8abc-35edb5c60300.png)

# 個人的なタスクの分類

以下のように分類しています

```bash
🔎 :mag_right: - 調査
📝 :memo: - ドキュメント作成・設計
⚙️ :gear: - 環境設定
🔤 :abc: - 実装
🧪 :test_tube: テスト
✅ :white_check_mark: - 確認事項
🙆‍♂️ :ok_man: - レビュー
```

# 導入した効果

- issue確認時にタスクのイメージがしやすくなった
- タスクを作成するのが楽しくなった
- タスクの分類ごとにソートしやすくなった

# おわりに

- 現在の現場ではチケット管理に[Pivotal Tracker](https://www.pivotaltracker.com/)を使用しています。チケットのタスク機能が使いにくいので、絵文字を導入することでタスクの分類が分かりやすくなりました。
- チームごとに絵文字の分類を話し合うのも楽しそうです。
tensorboardを実行するとエラー`ERROR rustboard_core::disk_logdir] Log directory outputs/xxx is not a prefix of run directory`と出る場合の解決策

例えば以下の通り実行すると、、
`tensorboard --logdir outputs/2022-02-11-14-15/tensorboard/events.out.tfevents.1644556551.seigonoMacBook-puro-3868.local `

以下のようなエラーが出る場合、`--logdir`の差し先がおかしい。

```bash
$ tensorboard --logdir outputs/2022-02-11-14-15/tensorboard/events.out.tfevents.1644556551.seigonoMacBook-puro-3868.local 
[2022-02-11T05:20:14Z ERROR rustboard_core::disk_logdir] Log directory outputs/2022-02-11-14-15/tensorboard/events.out.tfevents.1644556551.seigonoMacBook-puro-3868.local is not a prefix of run directory outputs/2022-02-11-14-15/tensorboard

NOTE: Using experimental fast data loading logic. To disable, pass
    "--load_fast=false" and report issues on GitHub. More details:
    https://github.com/tensorflow/tensorboard/issues/4784

Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all
```

具体的には、`$ tensorboard --logdir outputs/2022-02-11-14-15/tensorboard`とログ用のディレクトリをさせばOK

```
$ tensorboard --logdir outputs/2022-02-11-14-15/tensorboard

NOTE: Using experimental fast data loading logic. To disable, pass
    "--load_fast=false" and report issues on GitHub. More details:
    https://github.com/tensorflow/tensorboard/issues/4784

Serving TensorBoard on localhost; to expose to the network, use a proxy or pass --bind_all
TensorBoard 2.5.0 at http://localhost:6006/ (Press CTRL+C to quit)
```

これで、ブラウザから`http://localhost:6006`にアクセスすればtensorboardを見ることができる！
Google TestでC++の単体テストをやってみた②

# はじめに
前回、googletestのインストールまでを実施した。今回は実際の動作確認を行う。

# サンプルプログラム
googletest/googletest/samples以下にサンプルコードがあるので、この中のsample1を使ってみる。
まだパスを通していないので、オプションが多いが以下のコマンドでビルドする。

```sh
$ g++ sample1.cc sample1_unittest.cc -pthread -lgtest -lgtest_main -I../include/ -L../../build/lib/ -std=c++11
$ ./a.out
./a.out: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by ./a.out)
./a.out: /lib64/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./a.out)
```

とりあえずgccのバージョンをあげてみる。たまたま7.3.0を入れていたので、そちらに入れ替えてビルドしなおして実行。
以下のように6個すべてのテストがパスしているので、動作確認としてはこんなところでよいかな。

```sh
$ ./a.out
Running main() from /home/server/tmp/googletest/googletest/src/gtest_main.cc
[==========] Running 6 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 3 tests from FactorialTest
[ RUN      ] FactorialTest.Negative
[       OK ] FactorialTest.Negative (0 ms)
[ RUN      ] FactorialTest.Zero
[       OK ] FactorialTest.Zero (0 ms)
[ RUN      ] FactorialTest.Positive
[       OK ] FactorialTest.Positive (0 ms)
[----------] 3 tests from FactorialTest (0 ms total)

[----------] 3 tests from IsPrimeTest
[ RUN      ] IsPrimeTest.Negative
[       OK ] IsPrimeTest.Negative (0 ms)
[ RUN      ] IsPrimeTest.Trivial
[       OK ] IsPrimeTest.Trivial (0 ms)
[ RUN      ] IsPrimeTest.Positive
[       OK ] IsPrimeTest.Positive (0 ms)
[----------] 3 tests from IsPrimeTest (0 ms total)

[----------] Global test environment tear-down
[==========] 6 tests from 2 test suites ran. (0 ms total)
[  PASSED  ] 6 tests.
```

# /usr/local以下に移動
ヘッダとmakeしたライブラリを/usr/local以下に移動しておく。

```sh
$ sudo cp -r tmp/googletest/googletest/include/* /usr/local/include/
$ sudo cp -r tmp/googletest/googlemock/include/* /usr/local/include/
$ sudo cp -r tmp/googletest/build/lib/* /usr/local/lib64/
```

# sample環境
以下自前でテストを書いてみる。gccのバージョンは5.2.0に戻している。以下のような環境を作って、

```sh
.
`-- test
    |-- run.sh
    `-- test.cpp
```

自明なテストを置いて、

```c++:test.cpp
#!/bin/sh
g++ test_rect_coord.cpp ../src/rect_coord.cpp -I. -I../src -I../ac_types_2.6 -lgtest -lgtest_main -std=c++11 -pthread
```

実行スクリプト書いて、

```sh:run.sh
#!/bin/sh
g++ test.cpp -I. -lgtest -lgtest_main -std=c++11 -pthread
```

```sh
$ ./run.sh
$ ./test_rect_coord
Running main() from /home/server/tmp/googletest/googletest/src/gtest_main.cc
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from sample
[ RUN      ] sample.sampletest
[       OK ] sample.sampletest (0 ms)
[----------] 1 test from sample (0 ms total)

[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (0 ms total)
[  PASSED  ] 1 test.
```

という感じで、無事移行完了。が、毎回googletestをビルドした場所が表示されるの嫌だな…本番環境ではビルドする場所にも気を付けよう。
M1 MacでPython + OpenCVを試してみる

#はじめに

前回の記事

https://qiita.com/tnar-f/items/719cc3b018a7f1c761b0

でOpenCVによる画像のフィルター処理を試してみた折に、その高速な処理に驚き、手持ちのもう一台のPC(Macbook Air)でやってみることにしました。

Macbookのスペックは以下のようなものです。
MacbookAir (M1 2020)
チップApple M1
メモリ 8GB
OS macOS Monterey 12.1

#環境構築
@ShinnnosukeNakamuraさんの記事を参考に、環境を作りました。

https://qiita.com/ShinnnosukeNakamura/items/4b334c52e13993c10634

Pythonは3.9にUpgradeし、途中の
conda create -n py37_opencv python=3.7 anaconda
の部分は
conda create -n py39_opencv python=3.9 anaconda
のようにしました。

#平滑化処理をやってみる

Windowsのときと同じように、1920 x 1200の約230万画素、グレースケール画像の3x3近傍の平滑化処理をやってみます。以下のコードを使用します。20回連続して処理を行い、処理時間の平均を表示します。

```python
import cv2
import time

src = cv2.imread('test1.bmp',-1)
loopnum = 20
skip = 4

total = 0
for i in range(loopnum+skip):
    start = time.perf_counter()
    dst = cv2.blur(src,(3,3))
    end = time.perf_counter()
    if ( i > skip-1):
        print(str(end - start))
        total += end - start

print('Ave:',total/loopnum)

cv2.imwrite('test1_result.bmp',dst)

```

実行結果は以下の通りです。

```
0.00057787499999995
0.000581542000000046
0.000579166999999936
0.0005787919999999946
0.0005787080000000389
0.0005786249999999438
0.0005788749999999787
0.0005826669999999812
0.0005792499999999201
0.000578540999999988
0.0005786660000000055
0.0005764590000000291
0.0005809999999999427
0.0005792909999999818
0.0005787080000000389
0.0005784589999999756
0.0005784170000000532
0.0005783750000000198
0.0005671660000000633
0.0005787080000000389
Ave: 0.0005784645499999963
```

#0.6ミリ秒！
速っ！
( д) ﾟ ﾟ

結果画像はしっかりBlurしています。

ちなみに、Windowsでやった時はCore-i5@2.6GHzのマシンで3.3ミリ秒かかっていました。

M1 MacでのOpenCVはいま、過渡期のようで、この結果をどう捉えるのが正解か、いまいちわからないところがあります。そのあたりのことがわかってきたら、このページでお知らせしようと思います。

*iPhoneでPython + OpenCVの環境がある、という記事を読んだのでやってみました。

https://qiita.com/tnar-f/items/3a1e3044cb8211235658
pythonを実行しようとしたらエラー`"ModuleNotFoundError: No module named 'omegaconf'"`

pythonを実行しようとしたらエラー`"ModuleNotFoundError: No module named 'omegaconf'"`

```
ModuleNotFoundError: No module named 'omegaconf'
error: subprocess failed.
```

（hydraを使おうとする文脈だと)`hydra-core`をインストールして解決

```
pip install hydra-core --upgrade
```

# 参考
[https://hydra.cc/docs/intro Getting started](https://hydra.cc/docs/intro/)
【備忘録】vscodeで選択範囲内を検索する

**きっかけ**
ディレクトリパス内の、\を/に置換したいのだが...
[こちら](http://hogeo.blog.jp/archives/1075961045.html "こちら")を参考にしても、ハンバーガーメニュー（と呼ぶらしい）が出てこない

↓コレ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513603/173f6db9-cfad-1de0-62ad-98e8529e9e73.png)

ショートカット押しても反応せず...


**解決策**
ショートカットを割り当ててみた
以下手順


1.
赤枠の設定を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513603/e471b96c-0845-ce28-d481-7461125882b9.png)


2.
キーボードショートカットを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513603/68b8b418-4690-02fe-7645-13a0008294b2.png)

3.
キーボードショートカットというタブが開くので、検索窓に「検索」と打ってEnter
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513603/e2a5108b-12f1-306c-edbf-235ccaaf2090.png)

4.
設定後なので、鉛筆マークになっているが未設定の場合は+マークになっているはず…
+マークを押してお好みのキー設定をする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513603/a36db979-3bb0-f852-0bc0-65b7e8238c27.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513603/6090c530-84e3-1638-0912-6b9c608fb90e.png)


**使い方**
ついでに使い方も書く

1.
設定したショートカットキーを押す

2.
検査したい範囲を選択し、検査窓に\と入れ、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513603/7f3632be-49d3-e215-17ad-e353abde8b62.png)

ハンバーガーメニューを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513603/59ca3df1-15f8-b18e-2740-0dfe653f396b.png)

これで検査完了、あとは置換窓にお好みの文字を入れて置換



vscodeのアップデートでショートカットキーが変わっちゃったのかな
Node.js + Expressの環境にロギング機能を追加してみる。

![log4jsのブログ用ヘッダー.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299653/ac09f539-e4ed-6faa-38af-4c1e376bdcda.jpeg)


# Node.jsとExpressで構築したWebサーバーにロギング出力の設定を追加する。

今回は、Node.jsとExpressで構築したWebサーバーにロギング出力設定を追加してみたので
その設定の流れを共有してみたいと思います。

## 準備
1. log4jsをインストールする。
2. ログ出力用の設定ファイルを作成する。
3. Webサーバーを起動させるファイルに設定を追加する。
4. ログを出力したい箇所にlogger.debug()メソッドを突っ込む。

## ソースコード
   今回のソースコードは下記リポジトリを利用しました。

https://github.com/mashharuki/iroha

### 1.log4jsのインストール
  まずは、下記コマンドでlog4jsをインストールします。
  ```npm install log4js```

### 2. ログ出力用の設定ファイルの作成
  次にログ出力用の設定ファイルを用意します。参考サイトなどを参考に次のように設定しました。
  
  ```json
  {
      "appenders": { 
            "server": { 
                  "type": "file", 
                  "filename": "./server/log/server.log" 
            } 
      },
      "categories": { 
            "default": { 
                  "appenders": ["server"], 
                  "level": "debug" 
            } 
      }
}
  ```

### 3. Webサーバーを起動させるファイルに設定を追加
  ここまでできたらいよいよWebサーバー用のファイルにログを使用するための設定を追加していきます。
  筆者の環境の場合は、<a href="https://github.com/mashharuki/iroha/blob/main/iroha_front_app/server.js">server.js<a/>に次のように追加しました。

```js
// Webサーバーの起動
const express = require('express');
var log4js = require('log4js');

// log4jsの設定
log4js.configure('./server/log/log4js_setting.json');
const logger = log4js.getLogger("server");
```

### 4. ログを出力したい箇所にlogger.debug()メソッドを突っ込む
  3.まで完了したらあとは、ログを出力したい箇所にlogger.debug()メソッドを突っ込みます。

```js
logger.debug('起動しました', `https://localhost:${portNo}`)
```
うまくできていれば、server.logというファイル名が作成され、次のように出力されているはずです。

```log
[2022-02-11T13:49:44.393] [DEBUG] server - 起動しました https://localhost:3001
```

### 最後に
  今回は、Node.jsとExpressで構築したWebサーバーにロギング機能を追加してみました。
  思ったよりも簡単に設定ができたのでこの記事が参考になれば幸いです。
  よろしくお願いいたします。

#### 参考にさせていただいたサイト
 https://www.yoheim.net/blog.php?q=20130903

 https://www.npmjs.com/package/log4js

今回使用したiroha_front_appについては、こちらの記事で紹介させていただいているのであわせて
確認していただければ幸いです。

https://qiita.com/mashharuki/items/21bb3c49459e5bd8338d
Docker環境構築

##概要
CentOS7上でのDocker構築手順です。
自分メモ用になります。

##構築手順
1.レポジトリをyum-config-managerで管理するために、yum-utilsをインストール

```bash
sudo yum -y insgtall yum-utils
```
2.dockerのレポジトリをインストール

```bash
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
```

3.dockerをインストール

```bash
sudo yum install -y docker-ce docker-ce-cli containerd.io
```
4.dockerデーモンの設定ファイルを作成

```bash
sudo mkdir /etc/docker
sudo cat > /etc/docker/daemon.json <<EOF
{
      "exec-opts": ["native.cgroupdriver=systemd"],
      "log-driver": "json-file",
      "log-opts": {
            "max-size": "100m"
       },
      "storage-driver": "overlay2",
      "storage-opts": [
      "overlay2.override_kernel_check=true"
       ]
}
EOF
```

5.dockerサービスを起動し、サーバ起動時に自動的にサービスが起動できるようにする。

```bash
sudo systemctl start docker
sudo systemctl enable docker
```
Pythonでwordle補助ツールを作ってみた

# 
正規表現に対応している辞書などを使って今まで解いていたんですが、もっと効率よくやりたかったのでPythonで補助ツールを作りました。ソースコードは以下から見れます。

https://github.com/tennmusu/wordle-helper

# 下準備
1. まずは以下のリンクから辞書をダウンロードします。最新版の「Japanese Wordnet and English WordNet in an sqlite3 database」を選んでください。

    http://compling.hss.ntu.edu.sg/wnja/

2. そして、wordle-helper.pyからダウンロードしたデータベースにアクセスできるようにすれば下準備は完了です。

# 使い方
このツールは３つの入力を使って候補を絞り込んでいきます。具体的には以下の３つです。

## ・ 正規表現は？

位置が確定しているもので正規表現を作り一気に絞り込みます。先頭と末尾の正規表現は補完されるので入力しないでください。[.]は任意の一文字に該当します。ですので、緑の情報がない場合は[.....]としてください。　

[ex) a...e]→appleなどが候補になります。

## ・ 黄色は？
黄色の情報でさらに候補を絞り込みます。以下の例を見てください。

[ex) l4 a1]

この例はlが4文字目で黄色であり、aが１文字目で黄色であるという意味です。１～５の数字を入力してください。また、異なるアルファベット間は半角スペースで隙間を開けて入力してください。尚、アルファベットと数字のペアは一対一を想定しているので複数は入力できません。

## ・ 使わないのは？
ハズレ文字でさらに候補を絞り込みます。 以下の例のようにハズレ文字を並べて書いてください。

[ex) pweral]

## ・ 補足
「黄色は？」と「使わないのは？」の入力の際、該当する情報がない場合はそのままエンターキーを押してください。また、このツールは３つの入力を無限ループで繰り返し行います。ですので、「黄色は？」と「使わないのは？」の入力に関しては、2回目以降は追加したいものだけを入力すれば良いです。

## ・ 留意点
そもそもこのツールで使用している辞書にない単語が答えになる可能性もあるので、その際は以下の正規表現に対応している辞書サイトを使って考えるのが良いと思います。

https://www.visca.com/regexdict/

# 実際に補助ツールを使って解いてみた
Wordle Archive 9を解いて補助ツールの効果を確かめたいと思います。

https://www.devangthakkar.com/wordle_archive/?9

## ３手目までの結果
とりあえず自力で３手目までを適当に入力してみました。これだけ情報があれば大分候補は絞れそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517983/4801dba5-7cf1-63aa-0c09-b64d6a8c4fa3.png)

## 補助ツールにこれまでの情報を与えてみる
結果は以下のようになりました。一部同じ候補が２回出ていますが、これは使用している辞書のデータの関係かもしれません。

```
正規表現は？s....
黄色は？e4 r5
使わないのは？powblackhift
serum
surge
serve
serge
serve
surge
```
## 候補の中から答えっぽいのを選ぶ
とりあえずserveを選んでみます。すると、今回は運よく一発で正解することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517983/aabf5913-930b-b653-5c60-45754f75d7ac.png)

## 終わりに
今まで頭の中で行っていた操作を自動でやってくれるのが、この補助ツールの良いところかなと思います。実際にこの記事に載せた問題以外も補助ツールを利用して数問解いてみましたが、自力でやるよりも楽に解くことができました。使ってくださったら嬉しいです。

## 参考にした記事
以下の記事を参考にさせていただきました。ありがとうございました。
https://qiita.com/insei_99/items/738a6dd08ee5e600972e
AutomatorとTesseractを使ってテキスト検索可能な画像ファイルを作る

この記事はmacOS Monterey 12.2時点で書かれています。

Spotlightは便利だけど書類をスキャンした画像のテキストまで検索してくれないかなあ…でもGoogle documentとかEvernoteのクラウドなOCRは使いたくないなあ…という動機がありました。
じゃあTesseractを使ってローカルでOCRして、結果を画像ファイルのコメントに書き込めばいいのでは？やってみました。
#Homebrewをインストールする
していなかったらします。
https://brew.sh
指示通りにターミナルに打ち込むだけ。パスを通せと言われるので通します。
#Tesseractをインストールする
していなかったらします。（追記：言語もインストールします）

```
brew install tesseract
brew install tesseract-lang
```

#Automatorを使う
なんでAutomatorを使うの？ええと…ファイルにSpotlightコメントを設定するコマンドやAPIが無いっぽいんですよね…Automatorなら出来るはず。

#Automatorからシェルスクリプトを実行する
出来上がりを貼りますね。
![スクリーンショット 2022-02-11 13.38.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37794/5b763ea6-706f-244a-e843-05cd909bdfb1.png)
フォルダアクションにしていますが、アプリケーションでもサービスでもいいはずです。
まずファイルを受け取って、画像かどうかチェックして、変数に入れつつ次のアクションに渡します。
「シェルスクリプトを実行」アクションでTesseractを実行します。

```
export PATH=$PATH:/opt/homebrew/bin:/opt/homebrew/sbin
for f in "$@"
do
	tesseract "$f" stdout -l jpn+eng
done
```
Automatorで実行するシェルスクリプトは、ターミナルとは違うその場限りの環境らしいので、最初にパスを通しています。
標準出力に渡すとそれがAutomatorの次のアクションの入力になります。日本語と英語を認識させています。
次のアクションでは読み取り結果を一旦変数に入れて、もう一度さっきのファイルを思い出し、Spotlightコメントを設定するアクションで読み取り結果を設定します。
#実行と注意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37794/7b14cc54-f2a0-5516-0131-c1e779188567.png)
できた。
できたんですが、非常に残念なことにAutomatorは複数ファイルを1つずつ処理する機能がないので…せっかくフォルダアクションにしたのに1つずつファイルを入れないとうまく動きません。このワークフローで複数ファイルを指定すると、全ての読み取り結果テキストを連結して全てのファイルのコメントに設定してしまいます。なんとかならんか
RDSからAuroraに移行する方法2つ

# はじめに
Amazon RDS for MySQLからAuroraに移行する方法についてまとめました。
移行方法は、2つあります。

RDS MySQL
![スクリーンショット 2022-02-11 13.45.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/ddb026c4-fdfd-8fc4-79d1-5b226623c1e1.png)


# RDSからAuroraに移行方法①
1. RDS から インスタンスアクションで `[Aurora リードレプリカの作成]` を選択し、Auroraリードレプリカを作成します。
以下の3つが作成されます。
    - レプリカクラスター
    - リーダーインスタンス
    ![スクリーンショット 2022-02-11 13.41.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/f256d278-ff74-e800-ad60-74c52ed5ff0c.png)
2. 途中で、リーダー１台がライターインスタンスに変わります。
    - レプリカクラスター
    - リーダーインスタンス
    ![スクリーンショット 2022-02-11 13.42.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/bae55608-283f-453c-587a-3ac054ac81ba.png)
3. RDSからAuroraにデータ移行されるのを待ちます。
3. Amazon RDS for MySQL の停止させます。
RDS を停止することで RDSへの書き込みが停止され、Aurora クラスターへの書き込みを開始します。
3. Aurora レプリカクラスター（リードレプリカ）を昇格させると、以下のように変更されます。
    - レプリカクラスター → リージョン別クラスター
    - リーダーインスタンス → ライターインスタンス


# RDSからAuroraに移行方法②

1. RDS の最新のスナップショットを取ります。
1. 最新のスナップショットを選択して、`[スナップショットのアクション]`から`[スナップショットの移行]`を選択します。
2. DBエンジンをAurora にして作成すると、以下の2つが作成されます。
    - リージョン別クラスター
    - リーダーインスタンス
    ![スクリーンショット 2022-02-11 13.22.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/20fee2c5-81c3-6462-ee86-2c6ee580379b.png)
3. データ移行されるのを待ちます。移行完了後、以下の構成になります
    - リージョン別クラスター
    - ライターインスタンス
    ![スクリーンショット 2022-02-11 13.21.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988747/204a46d3-0816-848d-96d3-b30cec0e7b98.png)




②の移行方法は、昇格させる必要がないため、①よりも早く移行できます。


# 参考

https://aws.amazon.com/jp/blogs/news/best-practices-for-migrating-rds-for-mysql-databases-to-amazon-aurora/

https://www.yuulinux.tokyo/8070/

https://www.sunnycloud.jp/column/20211021-01/
AWS Amplifyハンズオン

#Amplify
・フロントエンド、モバイルアプリの開発を加速させるプラットフォーム
・AWSを用いたサーバーレスなバックエンドを構築するためのCLIや、バックエンドと接続するためのクライアントライブラリ、Webサイトホスティングの仕組みをもつ
・Amplifyを利用することでアプリケーションのコアとなるビジネスロジックの実装に集中できる
（認証機能やAPI、ホスティングなどを手軽に実装できる）

#Amplifyを利用したWebアプリケーション構築ハンズオン

※YouTubeにリンクします

1.  　[AWS Amplifyの紹介](https://youtu.be/XvA5lxKy2pA)
2.  　[環境構築、Cloud9編](https://youtu.be/iWLAgWtmdq4)
3.  　[環境構築、CLI編](https://youtu.be/7fE-x5xlFSM)
4.  　[API/DB編](https://youtu.be/qfHYatvktGE)
5.  　[Auth、Cognito編](https://youtu.be/yFDB0BW0S-w)
6.  　[Hosting編](https://youtu.be/2E8bXEJNlQo)
7.  　[リソースの削除](https://youtu.be/WW_EdN9ET7Q)


[Amplify公式ドキュメント](https://docs.amplify.aws/)


#Amazon Cognito
・ウェブ及びモバイルアプリの認証、承認、ユーザー管理機能を提供
・ユーザープール　アプリへのアクセスに利用できるトークンを提供
・IDプール　AWSにアクセスできるcredentialを提供

#Next Step
[SNSの構築](https://amplify-sns.workshop.aws/ja/)
[学習リソース集]
(https://github.com/aws-amplify-jp/awesome-aws-amplify-ja/blob/main/readme.md)
Financial-grade API Security Profile 1.0 - Part 1: Baseline 5.2.3. Public client メモ

- Financial-grade API Security Profile 1.0 - Part 1:Baseline 5.2.3. Public clientの章についての個人的メモ。
- ほぼ訳しただけ。

## 5.2.3. Public client

**1.RFC 7636  `Proof Key for Code Exchange(PKCE)`をサポートしなければならない**

* `Proof Key for Code Exchange` 
  * 認可コード横取り攻撃（authorization code interception attack）対策に関する仕様
  * 認可コード横取り攻撃
     * ネイティブアプリでブラウザで認可レスポンスを受け、アプリに遷移させる際に、悪意あるアプリがカスタムスキームを悪用して認可コードを横取りし、以降に正規アプリになりすましてユーザーのリソースを不正に入手する攻撃。
      * 条件：攻撃者が、正規のネイティブアプリと同じカスタムスキーム で起動する悪意あるアプリを作成してユーザーの端末に何らかの形でインストールさせることに成功していた場合 

**2.`code_challege_method`(コードチャレンジメソッド)に `S256` を用いなければならない**

* `code_challenge_method`
  * ``code_verifier`(`code_challenge`の生成元となる43~128文字の値)をハッシュ化する方法
* `S256`
  * SHA-256

**3.認可サーバーに応じて異なるリダイレクトURI を用いなければならない**

**4.リダイレクトURI の値をU/Aセッションに保存し、認可レスポンスを受けたリダイレクトURIと比較すること**

* URI不一致の場合、クライアントはエラーとして処理を終了しなければならない

**5.撤回**

**6.CSRF防御策を実装すること**

* `state`パラメータの利用

IDトークンを要求する場合、

**7.`scope` パラメータに `openid` を含まなければならない**

**8.`nonce` パラメーターを含まなければならない**

* `nonce`
  * リプレイアタック(不正に取得したIDトークンを送りつけて、不正アクセスする攻撃)を防ぐためのパラメータ

`openid`をscopeパラメータに含めない場合、

**9.`state` パラメーターを含まなければならない。**

**10.トークンレスポンスの`scope`が、次の値であることを検証しなければならない**

* 認可リクエストの`scope`と一致する
* 認可リクエストの`scope`のサブセットとなっている

**11.認可サーバーメタデータについては、ディスカバリーエンドポイントから取得したもののみを使用すること**

* ディスカバリーエンドポイント
  * OpenID Providerの発行者識別子 (`https`始まりのURI) に `/.well-known/openid-configuration` を付与したURLへHTTP GET リクエストすることで、OpenIDプロバイダーの情報を取得できるエンドポイント
  * `issuer`,`authorization_endpoint`,`token_endpoint`などがプロバイダー情報として取得できる

## 参考情報

* [Financial-grade API Security Profile 1.0 - Part 1: Baseline](https://openid.net/specs/openid-financial-api-part-1-1_0-final.html#public-client)
Tweepyで使うTwitter API v2は、最低限しか取得しない

# 概要

TweepyのAPI v2は最低限しか情報を取得しないので、`*_fields`で取得したいプロパティを指定しましょうというお話です。

# ツイートを取得

ツイートの作成時間を知りたくて、いつものようにget_tweetしました。

```python
>>> print(api.get_tweet(20).data.created_at)

None
```

# データの取得方法

## `None`って何

`None`とは🤔
ツイートの作成時間なんていう重要そうな項目、普通に考えたらないわけないので、ソースコードを見に行くことにしました。

[TweepyのTweetクラスのソースコード](https://github.com/tweepy/tweepy/blob/master/tweepy/tweet.py)を見ていたところ、どうやら`tweet.data`で内部データを取得できるようです。
やってみましょう。

## 内部データを見る
```python
>>> print(api.get_tweet(20).data.data)

{'id': '20', 'text': 'just setting up my twttr'}
```

なんと、idとtextしかそもそもないことがわかりました。では、created_atのようなプロパティはどこへ消えてしまったのでしょう？

## ドキュメントは読んどけ

答えは[公式ドキュメント](https://docs.tweepy.org/en/stable/client.html#tweepy.Client.get_tweet)に書いてありました。

![get_tweet.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2309889/7958c178-578a-c225-cc79-e94f0ed7c18e.png)

`tweet_fields`ですが、`str`か`list[str]`で取得したいプロパティを指定することでプロパティが帰ってくるようです。

# 実践

```python
>>> print(api.get_tweet(20, tweet_fields=["created_at"]).data.data)

{'created_at': '2006-03-21T20:50:14.000Z', 'id': '20', 'text': 'just setting up my twttr'}
```

しっかり`created_at`が帰ってきました。

# 応用

```python
>>> for status in api.get_users_tweets(783214, tweet_fields=["created_at"]).data:
...     print(str(status.id) + " : " + str(status.created_at))

1491089523291394052 : 2022-02-08 16:40:20+00:00
1491089514818846723 : 2022-02-08 16:40:18+00:00
1491085462013759491 : 2022-02-08 16:24:11+00:00
1491084952846352388 : 2022-02-08 16:22:10+00:00
1491084940624248836 : 2022-02-08 16:22:07+00:00
1491084675225427969 : 2022-02-08 16:21:04+00:00
1491084352800894978 : 2022-02-08 16:19:47+00:00
1491084344579997699 : 2022-02-08 16:19:45+00:00
1491084033874345986 : 2022-02-08 16:18:31+00:00
1491082777021792262 : 2022-02-08 16:13:31+00:00
```

`*_fields`は結構どこでも取得できるようです。

# 結論

最低限しか取得しないから、取得したいプロパティを`*_fields`で指定しよう！
windows10 PCセットアップ時のBitLockerの注意点

随分前（去年の中旬くらい）の経験になりますが、何か投稿しようと思い、記事を作成しました。

社内SEとして、PCの管理やセットアップなどをしているとき、

ある日突然、Windows10の起動時にBitlockerの回復キーを入力するよう要求されました。

調べたところこういった現象が多いらしいですが、PCのセットアップ時デフォルトでBitlockerが有効化されてしまっていることがあるようですね。（Bitlockerを手動で有効化したときに回復キーを発行できるので、印刷するなりどこかへ保存するなりして保管しておかないと回復キーが分からない）

※Microsoft Accountでも保管されているらしいですが、私は設定しておらず、そもそも回復キーを知らないという現象に陥りました。

PCセットアップ時にはまずBitlockerが勝手に有効化されていないことを確認した方がよいですね。

やり方は調べたらすぐ出てきましたので、そのうち私の記事でも載せようかとは思っております。
[Django] DEBUG=False時にMIME typeがtext/htmlとなってしまいcssが読み込めなくなった。jsも404。

## 現象

cssのMIME typeが`text/html`だから読み込めない問題が急に発生。
![スクリーンショット 2022-02-11 10.59.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335866/76b96ef7-f8e3-87ab-365a-097333922f3a.png)


## 解決策

`settings.py`などの修正は必要なく、サーバの起動コマンドに`--insecure`を追加するだけで解決した。

```
python manage.py runserver 0.0.0.0:8000 --insecure
```

どうやらsettings.pyのDEBUG=Fasleだと本番モードで起動されるみたいで、insecureモードじゃないとstaticファイルが公開されないみたい。
https://github.com/MoriTomo7315/django_gpxtoimage/blob/main/gpxtoimage/settings.py#L50
【Flutter】AppBarを使わずにTabBarを使う

## やりたいこと
TabBarの使い方を調べるとAppBarのbottomにTabBarを指定するやり方が多く、AppBarを使わない例があまりなかったので、DefaultTabControllerを使ったシンプルな例を作ってみる。

## できたもの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263661/c0072d7d-50c9-ec91-fa44-9820c7eddc35.png)



### 全コード
```dart
class TestView extends StatelessWidget {
  const TestView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        title: 'TestView',
        home: Scaffold(
            body: SafeArea(
                child: DefaultTabController(
                    length: 2,
                    child: Column(
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: const [
                          Center(
                            child: Text(
                              "Tabbar without Appbar",
                            ),
                          ),
                          TabBar(
                              labelColor: Colors.blue,
                              unselectedLabelColor: Colors.black12,
                              tabs: [Tab(text: "LEFT"), Tab(text: "RIGHT")]),
                          Expanded(
                              child: TabBarView(
                                  physics: NeverScrollableScrollPhysics(),
                                  children: [
                                Center(child: Text("LEFT")),
                                Center(child: Text("RIGHT"))
                              ]))
                        ])))));
  }
}
```


## 参考記事
https://stackoverflow.com/questions/50609252/flutter-tabbar-without-appbar
さくらサーバー内のサイト移転

今回さくらのレンタルサーバーの中でプランが違うサーバーに、運用中のWordPressのサイトを移転する際に、色々苦労したので備忘録を兼ねて記録します。

##出来るだけサーバーダウンの時間を無くしたい
実際に運用されているサーバーなので、出来るだけサイトにアクセス出来ない状態を短くしたいと思い、色々と方法を模索していました。

自分のパソコンのホストのファイルを書き換えて、ネームサーバーを書き換える前に強制的にサーバーにアクセスして、テストする方法を試しました。

https://site-hikkoshi.com/1803/

この方法は、ネームサーバーが変更されていなくても、サーバーの中でドメインが紐ついている必要があると分かりました。

さくらのレンタルサーバーは、プランが違うサーバー移転の場合、ネームサーバーに入力するIPアドレスが、同じなのです。
そのため、ドメイン管理している会社のネームサーバーを書き換えなくても良いので楽です。

でも、サーバーにドメインを設定するときに、以降元のサーバーからひっこすドメインを削除していないと、新しいサーバーに設定できないのです。

そのため自分のパソコンだけ強制的にドメインに接続する方法を試そうとしても、サーバーにドメインが設定されていないので使えないです。

実際、何度試しても、４０４エラーとなりアクセス出来ませんでした。

それで方法がないか色々検索していたら、さくらのレンタルサーバーの無料の機能で、バックアップ＆ステージング機能があることを知りました。

https://knowledge.sakura.ad.jp/14143/

https://help.sakura.ad.jp/115000200501/

このバックアップ＆ステージング機能は、サイトのバックアップだけでなく、テスト環境を作ったり、他社サーバーからWordPressをさくらのレンタルサーバーに移転する際にも活用できる便利なものです。

##注意点
バックアップ＆ステージング機能は、稼働しているWordPressは、設定できます。
でも、移転したばかりで稼働するかテストしたい場合は、スナップショットを撮ることが
できないのです。
そのためディレクトリで、指定しました。

###ディレクトリでは、ステージングサーバーを使えない
HTMLまたは、WordPressを選んだときに、ステージングサーバーを利用できます。

###SSH接続のアカウントを確認
SSH接続するためのユーザー名とパスワードは、サーバーのユーザー名とパスワードで使えます。
こちらの記事を参考にしました。

https://help.sakura.ad.jp/206054152/#ac01

##引っ越し元のさくらサーバーを指定
最初に選択されている移転先のサーバーではなく、移転元のサーバーを追加します。

##動いているWordPressを指定
引っ越すWordPressのスナップショットを撮ります。

##気をつけるプラグイン
私が引っ越しをしたWordPressは、プラグインを全部停止してもステージングサーバーで起動できませんでした。
ページ転送のエラーが、出てしまいました。

そのため今回は、ステージングサーバーを通さずに、引っ越し先に暫定的にWordPressをインストールして、バックアップ＆ステージング機能で引っ越し先のサーバーにサイトを追加するときに、WordPressとして選択できるようにしました。

同じサイトの種類同士（HTMLまたはWordPress）は、バックアップ＆ステージング機能上で、別のサーバーにスナップショットをコピーできるのです。
この方法で、引っ越し元のスナップショットを引っ越し先のサーバーにコピーできます。
そして、このスナップショットを本番環境に入れることで引っ越しが完了します。


##大幅な時間短縮
私は、モバイル回線でFTP転送しています。
そのため今回のように、大量のファイルの転送は、負担が大きいですし時間もかかります。
でも、バックアップ&ステージングを使うと、とても早く引っ越しができます。
さくらのレンタルサーバーのバックアップ&ステージングが、これほど便利だとは、思いませんでした。


![スクリーンショット 2022-02-11 8.00.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/20977/b1c35869-7d4c-9a37-61de-f61124793075.png)



##無料で使える
ブラウザで無料で、ステージングサーバー使えるのですね。
早く知りたかったです。
https://snapup.jp/

##さくら内でのサーバー移転の苦労
さくらのレンタルサーバーは、スタンダードとビジネス共に、同じネームサーバーの設定です。
そのため、とりあえずサーバーにドメインを設定してWordPressをテストした後に、ネームサーバーを切り替えるという手法ができません。

サーバーのルート直下に配置したフォルダにドメインが紐ついていないためか、自分のパソコンのhostファイルを修正して強制的にテストする方法も、使えないです。

そのため、ステージングサーバーを使ってサーバー移行、サーバーの引っ越しをするのが良いと思います。
今回FTP転送してデータベースをインポートして設定する方法で行いましたが、ドメインを切り替えてもアクセスできず苦戦しています。

ステージングサーバーのことを、もっと早く知りたかったです。
この技術を使えば、サーバーダウンの時間を極力短くできると思いました。

##最終的にプラグインを使い復旧
紆余曲折の末に、WordPressのプラグインのDuplicatorを使い復旧しました。
でも、データベースが文字化けしてしまいました。
事前にバックアップを取っていたので、手動でMyAdminを使ってインポートしました。

##ステージングサーバーに接続する際にエラー
ステージングサーバーで試してスナップショットを取り出して、本番環境に入れるという流れを体験したかったのですが、ステージングサーバーに接続する際に、何度試しても接続エラーが出てしまいました。

スナップアップが0.3GBなら無料で使えることが分かったので、使い方を勉強して活かしていきたいと思っています。

##ステージングサーバー接続エラー
先ほど一般的なWordPressのスナップショットをセットしたステージングサーバーは、正常にウェブサイトにアクセス出来ました。
そのため今回は、私が携わったサイト固有の問題があり、ステージングサーバーで接続エラーが出たと思われます。
ポケットWi-Fiはssh接続が容易ではない話

ラズパイで作ったモーターカーを外で走らせたかった。macbookからssh接続をしたいと思いポケットWi-fiを使おうと思ったけどconnect refusedのエラーが。

どうやらポケットWi-Fiはプライベートセパレートなる機能があるようで、要は同じワイファイ同士の直接のやりとりを禁止しているらしい。確かに電車とかでワイファイのパスを盗まれて、直接入ってこられたら情報抜き取られるもんね...

なので外でラズパイをssh接続して操作したい場合はポケットWi-Fiの設定をする。

ー忘備録ーそのうちまとめます。
小道具：Unicode のサロゲート コードを得る

サロゲート コードを直接記述したくなったときの小道具です。

Unicode 文字列の一文字のビット幅が 16 （例： JavaScript, MSVC の wchar_t など）では、コード ポイントが 65536 を超える文字を直接格納できないので、サロゲート コードとして格納することになります。

```python:surrogatefy.py
#!/usr/bin/env python3

import argparse


def surrogatefy(code):
    return [code] if code < 0x10000 else [(0xd800 | ((code >> 10) - 64)), (0xdc00 | (code & 0x03ff))]


def print_code(msg, prefix, code, separator):
    print('\'%s\':0x%x -> %s' % (msg, code, separator.join(['%s%04x' % (prefix, c) for c in surrogatefy(code)])))


parser = argparse.ArgumentParser()
parser.add_argument('-c', '--code')
parser.add_argument('-m', '--message')
parser.add_argument('-p', '--prefix', default='0x')
parser.add_argument('-s', '--separator', default=',')
args = parser.parse_args()

if args.code or args.message:
    if args.code:
        print_code(args.code, args.prefix, int(args.code, 0), args.separator)
    if args.message:
        for c in args.message:
            print_code(c, args.prefix, ord(c), args.separator)
else:
    parser.print_help()
```

実行結果

```console:
$ python3 surrogatefy.py -m '🃏🇯🇵'
python3 surrogatefy.py -m 🃏🇯🇵
'🃏':0x1f0cf -> 0xd83c,0xdccf
'🇯':0x1f1ef -> 0xd83c,0xddef
'🇵':0x1f1f5 -> 0xd83c,0xddf5
$ python3 surrogatefy.py -c 0x1f0cf
'0x1f0cf':0x1f0cf -> 0xd83c,0xdccf
```

node.js でのテスト

```console:
$ node
Welcome to Node.js v16.13.1.
Type ".help" for more information.
> s = String.fromCodePoint(0x1f0cf, 0x1f1ef, 0x1f1f5)
'🃏🇯🇵'
> s.length
6
> [s.charCodeAt(0).toString(16), s.charCodeAt(1).toString(16)]
[ 'd83c', 'dccf' ]
> [s.charCodeAt(2).toString(16), s.charCodeAt(3).toString(16)]
[ 'd83c', 'ddef' ]
> [s.charCodeAt(4).toString(16), s.charCodeAt(5).toString(16)]
[ 'd83c', 'ddf5' ]
> s.codePointAt(0).toString(16)
'1f0cf'
> s.codePointAt(2).toString(16)
'1f1ef'
> s.codePointAt(4).toString(16)
'1f1f5'
> for (const c of s) console.log(c, c.codePointAt(0).toString(16));
🃏 1f0cf
🇯 1f1ef
🇵 1f1f5
undefined
> '\u{1f0cf},\ud83c\udccf,\u{1f1ef}\u{1f1f5},\ud83c\uddef\ud83c\uddf5'
'🃏,🃏,🇯🇵,🇯🇵'
> '🇯🇵'.length
4
```

日章旗 🇯🇵 はコード <code>0x1f1ef</code> と <code>0x1f1f5</code> の組み合わせなので、('🇯🇵'.length)は 4 になります。
buildしようとしたら出た MiniCssExtractPlugin is not a constructor というエラーの解決策

Firebaseでデプロイ作業をしようとして buildをしたら次のようなエラーがでました。

`
TypeError: MiniCssExtractPlugin is not a constructor
`



## 結論
mini-css-extract-plugin＠2.4.5にダウングレードする必要があるみたいですね。

NPMを使用しているなら、下記のコマンドでダウングレードできます。
`
npm i -D –save-exact mini-css-extract-plugin@2.4.5
`



これで無事にビルドできるようになります！


## 参考
https://exerror.com/typeerror-minicssextractplugin-is-not-a-constructor/
【Kaggle解法まとめ】～House Pricing～ ＃特徴量選択

## 記事の概要
Qiita初投稿です:v:

本記事は、Kaggleのコンペティション「[House Prices](https://www.kaggle.com/c/house-prices-advanced-regression-techniques)」で公開されているいろいろなNotebookを参考にさせてもらいつつ、**特徴量選択**や**EDA**について自分の勉強も兼ねてまとめたもの。

## 特徴量選択とEDAのポイント
まずはEDAや特徴量選択におけるポイントをまとめていく。今回紹介するポイントは次の4つ。

- SalePriceとの相関
- 特徴量重要度
- 特徴量どうしの相関
- 共通の単語がついた特徴量


それぞれもう少し具体的に説明していく。

### SalePriceとの相関
まず大多数の参加者が行っていたのが、**予測対象である「SalePrice」との相関関係をみる**ということだった。

下図のように、SalePriceと各特徴量との相関係数を調べる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/e2d475ce-8341-c34b-df3a-eacb45b5dd12.png)

そして、相関が一定以上の（0.5以上くらい？）特徴量については散布図で可視化していく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/4b5b250a-32b2-35ef-67bb-711d575ad9fe.png)

例えば上の散布図では、右下あたりにある2つの外れ値が気になる。面積が広いのに販売価格はだいぶ安くなっている。このように、可視化の過程で外れ値に目をつけておいたりしておくと後々役に立つかもしれない。（外れ値を削除すると相関係数はどうなる？モデル精度はどうなる？など）

ちなみに「OverallQual」といったカテゴリ変数（ただし順序尺度に限る）の場合は、下図のように箱ひげ図にした方が見やすくなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/bb42504e-52c0-c494-9268-c593fc4f743a.png)

しかし、順序のないカテゴリ変数は散布図の描きようがない。順序のないカテゴリ変数とSalePriceとの関係を調べたいなら、単純に各カテゴリのSalePriceの平均値や中央値をとって棒グラフにしてみるとよい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/c10385fd-1033-5f59-8225-6d5365f07e01.png)


### 特徴量重要度
いったん何かしらのモデルで学習させて、特徴量重要度を見てみるのも一つの手。

下は簡易的なランダムフォレストを使ったときに、各特徴量がMSEに与える影響を表したもの。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/c50262a6-940b-6319-6fcf-79739a0e28cb.png)
(Source:["House prices: Lasso, XGBoost, and a detailed EDA"](https://www.kaggle.com/erikbruin/house-prices-lasso-xgboost-and-a-detailed-eda), Erik Bruin, LastAccess:2022-02-11)

あるいは、重回帰モデルでそれぞれの係数を見るという方法でもよい。

### 特徴量どうしの相関
ある２つの特徴量に強い相関がある場合は、一方の特徴量だけを使えば十分。不要な特徴量はできるだけなくしておきたい。また、重回帰モデルなどの場合は多重共線性の問題が生じる。

そのため、必ず特徴量どうしの相関関係についても調べておかなくてはならない。

seabornにheatmapという便利なツールがあるので、それを使って相関係数が非常に高い組を探していく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1900599/4c6cc1ad-37eb-1e93-012c-1cd0a0e0ffc4.png)


### 共通の単語がついた特徴量
特徴量どうしの相関係数を調べてみると、共通の単語が入っている特徴量どうしの相関が高くなりがちだということがわかる。

例えば、
- Year……
- Bsmt……
- Garage……
など。

このように同じ単語が含まれている特徴量があるときは、以下のことに注意してみる。

- それらの特徴量どうしの相関係数は？

特徴量どうしの相関係数をみて、相関係数が高いものは削除候補とする。相関係数が非常に高い場合は、この段階で一方を削除してしまってもよい。

- 必然的な関連性はないか？

例えば、Garageの面積が広けりゃ当然車もたくさん入る。なので「GrageArea」「GarageCars」のどちらかは不要。実際、相関係数は0.88でかなり高いです。この場合は迷わず、どちらかの列を削除しても大丈夫だと思われる。

- SalePriceとの相関が最も高い変数はどれか？

当たり前ですが、SalePriceとできるだけ関係のある変数で予測をしたいので、SalePriceとの相関関係もしっかり見ておく。

- 分布に違いはあるか？

分布が偏りすぎていると区別がしづらいため、予測には若干不利になる可能性がある。そのことを考慮して残す特徴量を選んでいく。データの粒度も参考になるかも。

## 次回の記事
[次回](https://qiita.com/matsuda-blog/items/f0b09fe2e46767f82253)は欠損値の扱いについてまとめようと思う。

## 参考リンク
https://www.kaggle.com/erikbruin/house-prices-lasso-xgboost-and-a-detailed-eda
https://www.kaggle.com/pmarcelino/comprehensive-data-exploration-with-python
Betafpv nano ELRS 送信機のFlashエラー対処法 

### Betafpv nano ELRS 送信モジュールのファームウェアをアップデートする時に失敗してしまう時
こちらを参考にしました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/Pt5rMp7Zs8s" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

### 原因
その①　そもそもCP210xドライバーが入っていない。
その②　設計ミスのボードに当たってしまった。
### 対処法
#### ①の場合
　[こちらからドライバーをダウンロードしてインストールします。](https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers)
<img width="300" alt="Silicon_labs2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520758/eddc539c-0f6b-3513-400f-04abb8ca1f72.jpeg">
ダウンロードしたzipファイルを適当なところに解凍します。
その中の ＜CP210xVCPInstaller_x64.exe＞ を実行してくだい。
以上でインストールは完了です。

#### ②の場合
　どうやら上のビデオによると、本来あるべきコンデンサーがボード上にないのが原因のようです。
<img width="200" alt="ESP32.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520758/df3b1789-7011-a048-03a4-63fe17002cf0.jpeg">
##### 対処法その１
 送信機のカバーを開けて、中のボタンを押しながらUSBを接続し書き込みモードにしてから、FLASHすると旨くいくそうです。
ビデオではずっと押してましたが、どちらか旨く行く方でやって見てください。
（私はコンデンサーを追加してしまいましたので確認できません。）
<img width="200" alt="ELRS_TX1.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520758/76922755-618c-224f-cf3f-923371d5dc9a.jpeg">
##### 対処法その２
　いちいちバージョンアップの度にボタンを押すのが面倒な人は、足りないコンデンサーを基盤に半田付けします。
　ビデオでは100nF(0.1uF)のコンデンサーを使うように言っていましたが、実際やってみると旨くいかず、代わりに手元にあった1uFのコンデンサーを図のように半田付けしたら旨くいきました。
<img width="400" alt="ELRS_TX2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520758/6b046a60-cdcd-c75b-24da-dca979a64b58.jpeg">
中には基盤を削ってグランドを出し、そこにコンデンサーを半田付けしている人もいました。
<img width="400" alt="ELRS_TX3.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520758/3f45f1c6-ff3e-fdb6-1a6b-a60054ab2f47.jpeg">
#### ※注意※
改造は、あくまで自己責任でお願いします。私は一切責任を負いませんので。
改造が嫌な方はBETAFPVさんにクレームのメールを送りましょう。なんとかしてくれるかも？？？
（技適を取ってくれたBETAFPVさんには、とても感謝ですが・・・）
#### 外部リンク
ExplessLRSの使い方は052さんのブログがとても分かりやすく解説されていて参考にさせていただきました。
[<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520758/5665d195-3c8e-b24b-7c10-e070f0b12086.jpeg">](https://052.jp/howto-expresslrs-install-guide/)
あとこちらもよろしく
　[ELRSのUSBドングルの作り方](https://qiita.com/kobatan/items/40728fbb625057d9f42b)
登山動画クリエイター向けにGPXファイルを軌跡画像に変換するサービスをつくってみた

はてなブログに掲載しています。

https://moritomo7315.hatenablog.com/entry/gpx2route


## 本サービス「GPX2ROUTE」

https://gpx2route-image.com/

## やったこと

* YamapなどのGPX山行記録データ(GPXファイル)を用いて、登山の軌跡画像を作成するwebアプリを作った。
* 軌跡画像を作るためには`matplotlib`を使用
* pythonを使用するためwebフレームワークはDjangoを使用
PHP独学ノート　その3

<font color="red">変数の続き</font>
<font color="blue">名前の記法ルール</font>
①camelCase記法
先頭文字は小文字、その後、単語の区切りを大文字で表記。

```
$userName
```

②Pascal記法
先頭文字も含めて、全ての単語の頭文字を大文字で表記。

```
$UserName
```

③アンダースコア記法
全ての文字は小文字/大文字で表し、単語の区切りはアンダースコア（_）で表記（スネークケース記法ともいう）

```
$user_name
```

どれを使っても間違いではないが、変数、関数はcamelCase記法、定数は全て大文字のアンダースコア記法、クラスはPascal記法が一般的。

<font color="blue">予約語</font>

予約語はPHPで予め意味が決められた単語。

予約語の利用は定数、関数/クラスの名前では使用禁止。
変数は頭に「$」が付くので例外的に使えるが、混乱するので使わない方が良い。

識別子の命名は、変数や関数の名前を見るだけでおおよその内容を把握できるようにする。

<font color="blue">可変変数</font>
可変変数とは、「変数名を変数の値によって決める」事ができる変数の事。

「$」マークを２つ重ねることによって変数名を別の変数の値で動的に決定する。

```
<?php
$x = ‘title’;
$title = ‘今日は祝日で忙しいと思ったら雪で意外と暇’;

print $$x;  
//結果: 今日は祝日で忙しいと思ったら雪で意外と暇
```
変数\$xに「title」という値がセットされているので、可変変数「\$\$x」は「\$x」の内容が評価された結果、「\$title」と同じになる。

可変変数を利用することで、ある変数の値に応じて動的に変数名を付け替えられる。

どこまでが変数を表す変数であるかを明確にしたい場合、可変部分を{~}で括ることもできる。

```
$$x
//と
${$x}
//は同じ意味
```

この例だけでは可変変数の使い所が分かりにくいが、後々出てくるクラスや関数の呼び出しにも利用できる。
可変変数を利用することで呼び出すべきクラスや関数を動的に変更できる。
VMware Cloud on AWS環境でContent Libraryを利用してみた (#1 前編 - 初期作成)

# 1. はじめに
「[VMware Cloud on AWS](https://www.vmware.com/jp/products/vmc-on-aws.html)」でコンテンツライラブリを利用した際の備忘録をまとめます。記事は前編後編に分けていて、前編は初期作成について、後編は異なるVMware Cloud on AWS環境(別SDDC)でのコンテンツライラブリのサブスクライブについてご紹介します。

コンテンツライラブリの利用方法はオンプレミスVMware vSpehre環境でもVMware Cloud on AWS環境でも変わらないので、例えばオンプレミスVMware vSphere環境で作成したコンテンツライラブリをVMware Cloud on AWS環境でサブスクライブするといったことも可能です。

https://qiita.com/sanjushi003/items/d702c39cd4d5fdc469db

# 2. そもそもコンテンツライラブリって？
VMware仮想環境同士でファイルの、特に仮想マシンのイメージファイルの共有を可能にする、「[VMware vSphere 6.0](https://docs.vmware.com/jp/VMware-vSphere/6.0/rn/vsphere-esxi-vcenter-server-60-release-notes.html)」から実装された素敵な機能です。より正確な定義は、下記のVMware公式サイトからの引用をご参照ください。

> コンテンツ ライブラリは、仮想マシン テンプレートおよび vApp テンプレートに加えて、ISO イメージ、テキスト ファイルなどの他のファイル タイプのコンテナ オブジェクトです。vSphere インベントリに仮想マシンおよび vApp をデプロイするには、ライブラリ内のテンプレートを使用します。コンテンツ ライブラリを使用して、同じ場所または異なる場所の vCenter Server インスタンス間でコンテンツを共有することもできます。テンプレートとファイルを共有すると、ワークロードの大規模なデプロイで整合性やコンプライアンスを確保し、デプロイを効率化および自動化できます。 - [「VMware Docs: VMware vSphere製品のドキュメント - コンテンツ ライラブリの使用」](https://docs.vmware.com/jp/VMware-vSphere/7.0/com.vmware.vsphere.vm_admin.doc/GUID-254B2CE8-20A8-43F0-90E8-3F6776C2C896.html)より。

前編では、事前に作成した仮想マシンのOVFテンプレートをVMware Cloud on AWS環境のコンテンツライラブリに登録するところまでご紹介します。
後編では、作成したコンテンツライラブリを別のVMware Cloud on AWS環境からサブスクライブするところをご紹介します。


# 3. コンテンツライラブリの作成
##VMware Cloud on AWS環境のvCenter Serverにログイン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/ab399b41-3e39-22ee-3dcf-91c471677d7f.png)

## メニューからコンテンツライラブリに遷移
「作成」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/21b501f6-d745-b8ec-fa5c-4da105f14e50.png)

## 新しいコンテンツライラブリの初期作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/98f29129-5864-d37f-2452-995b1a29ef39.png)

まずはデフォルト設定のままで作成しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/1fc76c4e-3cef-a61f-a09f-24fc7c419dbc.png)

## 作成したコンテンツライラブリの確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/ab8d0218-c80e-c0c9-0c3e-c3c7860981f9.png)

## OVFテンプレートの登録
手元にあるOVFテンプレート(今回はホームラボ環境で作成したTiny Linux仮想マシンのイメージ)をインポートします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/40d69e86-8be6-5b55-fa69-1cb3118b619e.png)

> 今回は作業端末内からOVFテンプレートをインポートしていますが、各種LinuxなどのISOファイルのダウンロードURLを上記「URL」欄に入力することで、作業端末にISOイメージをダウンロード/アップロードすることなく、コンテンツライラブリにそのままISOファイルを登録することもできます。

## 登録したOVFテンプレートの確認
作成したコンテンツライラブリにOVFテンプレートが登録されたことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/238b676c-78ef-37a9-dd69-13921a2c4f69.png)

## 登録したOVFテンプレートから仮想マシンをデプロイ
コンテンツライラブリに登録されたOVFテンプレートから、仮想マシンのデプロイも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864151/5125eb3e-e143-5c5f-a499-b40900685bec.png)

# 4. 関連記事

https://qiita.com/sanjushi003/items/d702c39cd4d5fdc469db

https://qiita.com/sanjushi003/items/3fed25f688c6e0b20a80

https://qiita.com/sanjushi003/items/2dd1ccdafdb93795561b
【Flask】なんで急にimport flask could not be resolvedと出たのかわからなかった

わからなかったがわかるようになったので覚書です。

## なにがあった？
さっきまでVScodeからターミナルで実行できていたのに、
新規ファイルを作成して実行したら「import flask could not be resolved」とエラーが出てきた。

## 試したこと
1.Flaskを入れ直した
2.ファイルがあるディレクトリに移動した
3.アクティベートしてあるか確認した

→全部だめだった。

## ググったらでてきた動画で解決した

[SOLVED : Import “flask” could not be resolved from sourcePylance in Python](https://www.youtube.com/watch?v=LjXxTvhilOM)

インタープリターを「3.8.12」に変えたら実行できた。
なぜこのファイルだけ変わってしまったのかは不明……

　　
　　
　　
　　

##### 余談
速攻で解決したように書いていますが実際は2日くらい躓いてました。
ブラウザのレンダリングについて【学ぶ動機】

## 動機
働いている同期と話す中で、`ReactやNext.jsで用いられている技術のCSR,SSG,SSR,ISRはどのようなレンダリングをおこなっていてどんなアプリ開発に向いているのか。`というような疑問が出てきました。
[CSR,SSG,SSR,ISRの参考記事](https://qiita.com/hiroki-yama-1118/items/b3388c5dcb155e2e367d)
### そもそもレンダリングについて詳しくないではないかと...

そこで、ブラウザで行われているレンダリングから学んで、この記事にまとめておこうと決めました。

[ブラウザのレンダリングのサイクル](https://qiita.com/kosuke-17/items/aaf8ecb090fb664198f4)


***
**参考記事**
 [【JavaScript】ブラウザのレンダリングの仕組みについて](https://qiita.com/wqwq/items/9e87e018e5725b8c2c0d)


**書籍**
[Webフロントエンド ハイパフォーマンス チューニング](https://www.amazon.co.jp/Web%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%83%89-%E3%83%8F%E3%82%A4%E3%83%91%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%B3%E3%82%B9-%E3%83%81%E3%83%A5%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0-%E4%B9%85%E4%BF%9D%E7%94%B0-%E5%85%89%E5%89%87/dp/4774189677/ref=pd_sim_14_2/355-8347036-3165354?_encoding=UTF8&pd_rd_i=4774189677&pd_rd_r=242f1b07-5d75-484b-831f-8e3186723bd4&pd_rd_w=SLj3f&pd_rd_wg=efHnd&pf_rd_p=51d7f721-ab31-4c99-8db8-c3f45803167a&pf_rd_r=639J7G22C2SMCZT0SF5B&psc=1&refRID=639J7G22C2SMCZT0SF5B)