OmniAICreator/Qiita-1.07M huggingface dataset:
React/Typescriptの開発環境を作る

#目次
[1.はじめに](#1-はじめに)
[2.インストール](#2-インストール)
[3.プロキシ環境の場合](#3-プロキシ環境の場合)
[4.おわりに](#4-おわりに)

#1. はじめに　参考資料など
JavaやC#で基幹系システムしか作ってこなかったエンジニアがフロント開発に挑戦する。さて、開発環境の構築を記録していきます。
なお、Reactを使う上で必要なJavascriptとしての知識レベルですが、以下ぐらいです。

* 普通のJavascriptについては、他人の書いたコードは読める
* 一からコードを書くのはできない
* コールバック関数は読めることには読めるがあまり自信がない
* ReactやVue.jsなどのライブラリ関連はよくわからない。コードも読んだことはない。

まず参考にした書籍は以下です。

* [React公式ドキュメント](https://ja.reactjs.org/docs/getting-started.html)
「チュートリアル」から読み始めて、動かしてみたりしました。「おー、動いた」レベルでとどまり、チュートリアル最後のサンプルコードを書き換えてみよう、というお題がわからずやめました。

* Kindle書籍
ちょうどKindle Unlimitedの無料体験があったので、何冊かダウンロードしました。
[はじめてさわるReact & JavaScript Kindle版 / mod728著](https://www.amazon.co.jp/gp/product/B09693ZJCV/ref=ku_mi_rw_edp_ku)
[はじめてつくるReactアプリ Kindle版 / mod728著](https://www.amazon.co.jp/gp/product/B08XWMVX76/ref=ku_mi_rw_edp_ku)
[はじめてつくるReactアプリ with TypeScript Kindle版 / mod728著](https://www.amazon.co.jp/gp/product/B094Z1R281/ref=ku_mi_rw_edp_ku)
これも「おー、動いた」と感じ、なんとなくPropsやStateの理解レベルが上がったかなー。で終わりました。

で結局。
「お題がないとがっつり作ろうとしない」からいまいち覚えないよね。という状況になりました。プログラミングあるあるですね。
お題はのちの記事に書いていくので、まず今回はツール類のインストールをまとめていきます。

#2. インストール
以下のツールをインストールしました。

* Node.js

ちゃんと勉強するまで知らなかったが、Node.jsを入れただけでReactが使えるとは。
公式サイトよりダウンロード→ https://nodejs.org/ja/
入れたバージョンは14.17.16だが、なぜこれを入れたのかは忘れました。。。

* Visual Studio Code (VS Code)

もともとPythonを扱っていたので、インストール済みでした。
公式サイトよりダウンロード→https://azure.microsoft.com/ja-jp/products/visual-studio-code/

* VS Code拡張機能： Japanese Language Pack

このサイトを参考に拡張機能をインストールし、VS Codeを日本語で扱えるようにしました。
https://www.javadrive.jp/vscode/install/index4.html

* VS Code拡張機能： Babel Javascript

入れた経緯を思い出せません。Javascript構文のハイライト表示に使っています。
https://marketplace.visualstudio.com/items?itemName=mgmcdermott.vscode-language-babel

#3.プロキシ環境の場合
自分の環境ではプロキシありませんが、プロキシがある場合はnpmコマンドで以下に設定するようです。

```
npm -g config set proxy htt://xxxxxx:9999/
npm -g config set https-proxy htt://xxxxxx:9999/
```

プロキシを解除する場合は以下

```
npm -g config delete proxy
npm -g config delete https-proxy
```

参考：https://qiita.com/ymaru/items/cf513ab05fe0ebac7d3b

#4. おわりに
以上が開発環境構築になります。

**と、おもいきや**
Web開発者はWindowsじゃないほうが良いのではという意見を見てしまったがために…。
次回へ続く。

https://qiita.com/saisuke3309/items/4c7f550d42609144a957
【PHP】チャット機能の自作！Ajaxでスムーズな更新も実現

PHPで作れる定番機能の1つ「チャット機能」を自作してみました。

完成までの流れと苦労したポイント、どんなふうに作っていったかをまとめてみました。

#チャット機能を自作

今回使ってみたのはこのような感じのチャットです。
[自作チャット](https://portfolio.amefure.com/chatsystem/chat.php#chat-area)

チャット機能を作ることができればPHPのあらかたのテクニックが学習できるかなと思い、作成することにしました。

##要件定義

まず最初にチャットを実現するために必要な機能を洗い出します。

チャットで欲しい機能
- チャットを送信時に時間とアイコンを表示
- チャットログを蓄積、表示
- チャットログが増えたら自動更新
- デモなのでユーザー切り替え
- チャットログリセット


必要になる言語
- HTML/CSS（元枠）
- PHP（データ操作）
- JavaScript（自動更新）


##設計

実現方法
- ログはJSONファイルに格納
- ログが増えたかどうかはファイルサイズで判断
- ajaxを使って更新時のチラツキを抑える


##制作

実際のコーディング方法は記事にまとめてみました。

[【自作】PHPでチャット機能の作り方！LINEのような会話形式のプログラムのコードを徹底解説！](https://appdev-room.com/web-chat)

苦戦したポイント
- PHPでJSONファイルを操作する
- Postの二重送信対策
- ログが増えたかどうかをどうやって判断するか
- ajaxの更新

###JSONファイルへの格納
まずは送信されたチャットデータ（Post）にエスケープ処理を施し別の配列に格納し直します。

配列に格納されたデータをJSONファイルとして操作できるように整形、chatlog.jsonファイルに蓄積していきました。

これでログが増えればどんどんJSONファイルに溜まっていきます。

###二重送信対策
入力値をPHPで扱おうとするとページリロード時の二重送信が起きてしまいました。（一度送信されたデータが再度送信される）

これは入力値を受け取り後即座にリダイレクトさせることで解消することができました。


###ログの増減の識別方法
一番四苦八苦したのはログ増減の識別方法です。

いろいろ悩んで調べたあげくajaxという機能を知りました。ajaxとは日本語で非同期通信という意味でページ全体を更新せず、一部分だけを更新できるので余計な通信をしなくて済む優れた機能でした。

JavaScriptのsetIntervalメソッドを使ってajaxの処理を0.1秒ごとに呼び起こす方法を取りました。

input要素を2つ用意し1つはajax前のファイルサイズを格納、もう1つはajaxで常に現在のファイルサイズに更新し続けます。input要素自体は表示されないようにしておきます。

2つのinput要素のファイルサイズが異なる場合にのみログのリフレッシュ処理を起動させることで余計なリフレッシュを起こさせずに実現することができました。

##テスト

MAMPを使ったローカル環境で幾度となくテストを繰り返し、問題なさそうだったので無事公開しました。

##公開

しかし公開後ユーザー切り替えを行うと、2人同時にチャットをしている場合に、ユーザーを後手で切り替えた側に乗っ取られてしまう不具合が発生しました。

これはまだ解決できていませんが、sessionをうまく使えば行けるかな？と甘く考えております。

そしてもう一つの課題点。
sessionの破棄が明示的にできないことです。
sessionを使ったは良いもののチャットページを離脱するタイミングが読めないので破棄する処理を入れ込めませんでした。。

まだまだ至らぬ点も多く、自分のスキルの無さが出てきてしまいましたがこれからも楽しみながら学習していきたいと思います。

ご覧いただき本当にありがとうございました！

あめ
Azureでデータ活用してみる(データ加工編)

#概要
Azure DataLake Gen2に格納したrawデータを分析しやすいようにETL処理します。
ETL処理をするために、Azure Databricksを利用し、ETL処理したデータをAzure DataLake Gen2に格納します。

#Azure Databricks notebooksの実装
Azure Databricks notebooksの実装の前にデータを蓄積する為のAzure DataLake Gen2やAzure Databricksのクラスターを作成する必要がありますが、作成手順は割愛させて頂きます。

####Azure DataLake Storageコンテナーのマウント


```python:cmd_1 
# コンテナーのマウント

# DataLake Storage情報（データ抽出用）
mount_name= "【任意のマウント先ディレクトリ名】"
storage_account_name = "【ストレージアカウント名】"
container_name = "【任意のマウント先ディレクトリ名】"
storage_account_access_key = "【ストレージアカウントアクセスキー】"

# マウント先DBFSディレクトリ
order_items_json = "dbfs:/mnt/【任意のマウント先ディレクトリ名】/【データ抽出対象ファイル】"

# DataLake Storageのマウント
mount_point = "/mnt/" + mount_name
source = "wasbs://" + container_name + "@" + storage_account_name + ".blob.core.windows.net"
conf_key = "fs.azure.account.key." + storage_account_name + ".blob.core.windows.net"


mounted = dbutils.fs.mount(
  source=source,
  mount_point = mount_point,
  extra_configs = {conf_key: storage_account_access_key}
)
```

####DataFrame化
```python:cmd_2
df = spark.read\
  .format("json")\
  .options(header="true", inferSchema="true")\
  .option('charset', 'utf-8')\
  .load(order_items_json)
 
df.display(df)
```

####必要なカラムの選択
```python:cmd_3
"【任意の名前】" = df.select("【必要なカラム】")

display("【任意の名前】")
```

####日付(string型)のdatetime型へ変更
```python:cmd_4
import pandas as pd
import datetime

pdf = df.toPandas()
pdf["【対象のカラム】"] = pd.to_datetime(pdf["【対象のカラム】"].astype(str), format='%Y-%m-%d')

df = spark.createDataFrame(pdf)
display(df)
```

####変換されたデータの格納 : Json
```python:cmd_5
# データの保存
df.write.mode('overwrite').json("/mnt/【任意のマウント先ディレクトリ名】/【任意のファイル名】")
```
#まとめ
Azure DataLake Gen2に格納されたrawデータをETL処理し、変換データを格納するところまでが完了しました。
データ分析の内容も掲載してみようかなと思います。と言っても、データの公開が出来ないのでSQL文の内容だけになるので、どうしようかと・・・
Azureでデータ活用してみる(データ可視化編) 

#概要
Azure Databricks notebooks上でもデータの可視化が可能でしたが、Azureでデータ可視化と言えば、言わずもがなPower BIが候補に挙がってくるのではないでしょうか。
そこで、Power BIを利用してみたいと思います。

#Azure DatabricksとPower BIの連携
####アクセス情報の確認
[Compute]から使用するクラスタを選択
![Databricks_クラスタ選択.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/9aaaf302-ea3d-c369-3b14-e3269f810dfa.png)

[Advanced Option]をクリック
![Databricks_AdvancedOptions.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/d6150857-64ad-6e4c-9f30-a7720300163a.png)

[JDBC/ODBC]を選択し、[Server Hostname]と[HTTP Path]をメモ
![Databricks_JDBC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/e3ca7ffe-a464-f10b-d8c7-3889a8ba70a6.png)

アクセストークン発行
左下の歯車アイコンから、[User Setting]をクリック
![Databricks_User Settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/96c053b7-3615-dd3a-29f6-17e2ed822b10.png)

[Generate New Token]を選択。トークンの名称と有効期限を任意で入力し、[Generate]をクリック
![Databricks_GenerateToken.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/bb776add-0c49-92c2-2d53-6af254a34b11.png)

アクセストークンキーが発行されるので、これもメモしておき[Done]をクリック
※紛失するとトークンの使用が不可能になるので注意が必要
![Databricks_Token.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/94c1bc28-6f9f-4846-662d-8c8f62744ca2.png)

#Power BI DesktopにAzure Databricksを接続

Power BI Desktopをインストールし起動後、左上のデータの取得をクリック。[Azure Databricks]を選択し、[接続]をクリック
![PowerBI_GetData.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/704ccd14-b4a5-e8bf-aeae-87c3650fdddd.png)

メモしておいた[[Server Hostname]と[HTTP Path]を入力して[OK]をクリック
![PowerBI_Path.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/59c79b6b-e09e-dcfb-a32c-91f8a73f8069.png)

[Personal Access Token]を選択。メモしておいたトークンIDを入力し、接続をクリック
![PowerBI_PersonalAccessToken.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/4e2c0999-2997-f150-93ef-19837cc64c37.png)

これで Databricksで作成されたテーブルを取り込むことができます。
![PowerBI_Data.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/0717ce45-15da-517d-3dd3-40323dd1a417.png)

#まとめ
Azure Databricksで作成したテーブルの情報を可視化する事が出来ました。
Power BIの他に、Azure Data Explorerのダッシュボードやworkbookも試しておりましたが、可視化データの共有も考慮したところ、Power BIを利用することで進めます。
Azureでデータ活用してみる(構成編)

#概要
Azureでデータ活用してみようということで、簡単な構成を考えてみました。
試行錯誤しながら作業をしているので、途中で構成変更もあるかもしれません。

#何を知りたいのか
自社SEの単価を受注金額や工数データを用いて調べてみたいと思います。
※自社データで作業している為、実際のデータのやり取りを掲載することが出来ず、申し訳ございません。

#Azure構成
まずは以下の工程で、データ活用を進めてみることにします。
進めていく過程の中で、他のサービスがよければ、変更する予定です。
![構成2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/14737c32-badd-00c3-a137-656a77e01576.png)

・Azure Data Factory
データ接続、収集、蓄積を自動化します。

・Azure DataLake Gen2
rawデータとDatabricksにて加工したデータもDataLakeに蓄積します。

・Azure Databricks
notebooksにてrawデータを分析しやすいように加工します。

・Power BI
言わずと知れたデータ可視化ツールです。

#まとめ
Azureのサービスを利用してのデータ分析基盤の構成を考えてみました。
データ連携、データ加工、可視化についても記事を書きます。
Power BI Desktop:クラスが登録されていません

#Power BI Desktopとは何？
Power BI Desktop は、利用されているデータソースを抽出・変換し、視覚化を行うことが可能なデスクトップアプリケーションです。

#概要
Power BI DesktopにAzure Databricksを接続し、データを視覚化を試みました。
しかし、プレビュー画面ではテーブルの情報が見えていましたが、読み込もうとすると、「サーバーに対する変更の保存に失敗しました。返されたエラー：次のシステムエラーが発生しました：クラスが登録されていません。」というエラーが表示され、データを取得出来ませんでした。
![PowerBI_クラスが登録されていません.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1514023/15b7bc01-2040-d319-5781-cfc1c846f460.png)


#対処
Microsoft Store経由でインストールしたPower BI Desktopをアンインストールし、Microsoft ダウンロードセンター経由でPower BI Desktopをインストールしたところ、解決できました。

####Microsoftダウンロードセンター
https://www.microsoft.com/ja-jp/download/details.aspx?id=58494

####Microsoft Store
https://powerbi.microsoft.com/ja-jp/downloads/
[AfterEffects] オーディオレベルをスクリプト変更する方法 audioLevel 

久々にafterEffectsのスクリプトを書いたら簡単なところでつまずいたので備忘録として残しておきます。

紹介する内容はタイトルの通り、スクリプトでオーディオレベルの変更の仕方です。
早速↓がスクリプトの内容です。


```javascript:ChangeAudioLevels.jsx
for (var i = 1 ;i < app.project.items.length ;i++)
{
    var comp =  app.project.items[i];
    if(comp instanceof CompItem)
    {
        $.writeln(comp.layers[1].name);
        $.writeln(comp.layers[1].audio.audioLevels.value);
        comp.layers[1].audio.audioLevels.setValue([8,8]);
        $.writeln(comp.layers[1].audio.audioLevels.value);
    }
}
```


プロジェクトのコンポを検索して問答無用で1番上のレイヤーのオーディオレベルを8に設定するスクリプトです。
オーディオレベルはproperty objectなので、***.audioLevels.value = [8,8]とかやってしまうとエラーで
読み取り専用オブジェクトですとか言われて結構迷ってしまいました。
ちなみに代入するvalueが配列なのは、恐らく左右のオーディオバランスがあるんだと推察しております。

私と同じように、はまった方はご参考までに。
Docker環境でDBに接続するとcould not find driverが出たときの対処方法

## DBに接続する処理を作成
```php
<?php
define('DB_NAME', 'データベース名');
define('USER_NAME', 'ユーザー名');
define('USER_PASS', 'パスワード');

try {
  $pdo = new PDO(
    DB_NAME,
    USER_NAME,
    USER_PASS,
    [
      PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
      PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_OBJ,
      PDO::ATTR_EMULATE_PREPARES => false
    ]
  );
} catch (PDOException $e) {
  echo $e->getMessage();
  exit;
}
```
## 接続すると下記のエラーが出力された
```bash
could not find driver
```
### ドライバが見つからないようなので現在のドライバを確認してみる

```bash
php -m | grep pdo

# pdo_sqlite
```
### pdo_mysqlがインストールされていないのが原因らしいのでDockerFileに処理を追加する
```docker
FROM php:7.2-fpm
COPY php.ini /usr/local/etc/php/

# 追加
RUN docker-php-ext-install pdo_mysql
```

### 再度ビルドすると無事に接続できた!

参考資料[【Laravel】CentOSのLAMP環境でcould not find driver
](https://www.suzu6.net/posts/198-could-not-find-driver/)
Provision ESXi 7 with MAAS イメージの作り方

# MAAAAAAAAS!
MAAS(Metal as a Service)チョー便利。もう離せません

ESXiもMAASで物理サーバーにプロビジョニングできるということは
あんなことやこんなことも自動化できるわけですね。

https://maas.io/tutorials/maas-esxi-quickstart#1-overview
にあるオフィシャルな情報からESXiを試しにデプロイしてみたわけですが、
挫折したものもあったので記録して残します。
※深夜のテンションなのでお見苦しい点もあるかと思いますが・・・

# 環境

ESXi用のイメージを作りには物理サーバーがよい。

packerがqemuを使っているのですが、MAAS のイメージビルド環境をVMware上で実行すると
```
Qemu stderr: qemu-system-x86_64: CPU model 'host' requires KVM
```
で失敗します。

KVM仮想マシンなら行けるのでしょうが、物理サーバーで行ったところ無事できました。

# 材料
- VMware ESXi ISO
    - VMware社からダウンロード
    - VMware-VMvisor-Installer-7.0U3b-18905247.x86_64.iso
    - /home/ubuntuに置きました
- Packer
    - https://www.packer.io/downloads
    - Linux上にインストールします
- Packer-maas
    - https://github.com/canonical/packer-maas
    - /home/ubuntuでgit cloneします

## 必要パッケージのインストール

### apt package
```
$ sudo apt install -y maas qemu-system-x86 xorriso python3-pip
```

### packer

```
$ curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
$ sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
$ sudo apt-get update && sudo apt-get install packer
```

### packer maas templateのダウンロード

```
$ git clone https://github.com/canonical/packer-maas.git
$ cd packer-maas/vmware-esxi/
```

## imageのビルド
```
$ sudo modprobe nbd
$ sudo packer build -var 'vmware_esxi_iso_path=/home/ubuntu/VMware-VMvisor-Installer-7.0U3b-18905247.x86_64.iso' vmware-esxi.json
```

## MAASへログイン
※事前にAPI Keyを取得しておく
http://{MAAS-IP}:5240/MAAS/r/account/prefs/api-keys

```
$ maas login admin http://{MAAS-IP}:5240/MAAS/
API key (leave empty for anonymous access):

You are now logged in to the MAAS server at
http://{MAAS-IP}:5240/MAAS/api/2.0/ with the profile name
'admin'.

For help with the available commands, try:

  maas admin --help
```

## imageのアップロード

```
$ sudo chown ubuntu:ubuntu vmware-esxi.dd.gz
$ maas admin boot-resources create name='esxi/7.0u3' title='VMware ESXi 7.0U3' architecture='amd64/generic' filetype='ddgz' content@=vmware-esxi.dd.gz
```

## ふえてる！

http://{MAAS-IP}:5240/MAAS/r/images

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126158/ab1cae2a-fe9e-fe29-cc28-f6fb6abf542f.png)

## Deploy & login

デプロイはMAASの通常デプロイで一発でインストールできました。
ESXiのWeb画面はMAASでデプロイされたノードのネットワーク・インターフェースのIPアドレスへ接続するだけで入れます。

| UserID| Password|
|:--|:--|
|root|password123!|
Macで.devドメインに繋げない場合の対処法

Macのブラウザから `http://lightship.dev` に接続しようとすると403が出たので調べました。
.devドメインがlocalhost(127.0.0.1)を指してたので、以下の手順で解決しました。

### 修正手順

ターミナルで、次のコマンドを入力します。

`cd /etc/resolver/ && ls`

Enterキーを押したときにエントリ名が表示された場合、これはワイルドカードリゾルバであり、.devドメインへのアクセスのすべての試行を127.0.0.1にポイントしている可能性があります。

これは以下のコマンドで削除できます。

`sudo mv dev dev.ignore`

これで.devドメインにアクセスできます。
Python初心者がノンプロ研でPython学んでみた vol.1


# はじめに
こんにちは、な～です。
ここのところずっとGASをしていた私ですが、この度、Pythonを学んでみることにしました。
Pythonの本は以前買ってずっと積ん読してあったのですが、全く手がでず、ノンプロ研の講座で学んで見ることにしました。今回はこの講座の1回目で学んだことについてまとめてみます。

# ノンプロ研とは
まずは、ノンプロ研とは、正式名称「[ノンプログラマーのためのスキルアップ研究会](https://tonari-it.com/community-nonpro-semi-2/)」と言います。ノンプログラマーがVBA・GAS・Pythonなどのプログラミングスキルを身につけるためにコミュニティです。
私は2021年の2月末に入会し、GASを中心に学んでいました。講座以外にも数多くのもくもく会や勉強会などが開催されており私は、多くの刺激をもらっているコミュニティです。

# 目次
## はじめてのPython

この講座では、Jupyter Notebookを使って学んでいきます。Jupyter Notebookとはプログラムの実行＆記録ツールです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208544/8a5b3dba-fa7e-378f-326e-f290badae240.png)

こちらがJupyter Notebookの画面です。
NewボタンよりPython3をクリックして、プログラムファイルを作成して操作していきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208544/f59a7a2b-658e-78e1-4b26-16d62b3fca38.png)

こちらは、プログラムファイルの画面です、ファイル名を変更してプログラムを書いていきます。

print('Hello Python!')と入力後、Ctrl＋Enterを入力するとHello Python!と出力されます。

printは関数です。括弧の中のデータを標準出力に表示します。
数値と文字列の入力にはルールがあり、そのルールをリテラルと呼びます。
数値はそのまま、文字列は、「'」または「"」で囲んで表します。

Pythonのコメントはハッシュ記号の後ろに書きます。

## 変数

変数とは、データに付与するラベルです、
データに変数を割り当てることを代入と言います。
変数に初めてデータが代入されることを初期化。
変数に新しいデータが代入されることを上書きと言います。

Pythonの変数名のルールは、アルファベットで小文字のスネーク記法で命名します、

## データ型と演算

オブジェクトとは、操作するデータ型のことで、いろいろな種類があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208544/616b45d2-1585-45d6-0b6a-7183909711b7.png)
まだ全然ピンと来ていないので少しずつデータ型について学びたいです。
「type(値)」で値のデータ型を調べることができます。

算術演算子
加算・減算などはおなじみのところですが、整数除算は、除算の結果を整数で返します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208544/cc0b7031-dd22-bcfa-de90-87a7eceaac43.png)
こちらは累算代入演算子、計算した結果を変数に代入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208544/6d9abc9f-6c15-c949-41b1-3b0cbe98e1a3.png)


## 文字列とシーケンス
文字列は、文字を要素とするシーケンスです。個々の要素にはインデックスが振られていて、インデックスを使用すれば、文字列から文字を取り出すことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208544/27a226c6-b3c5-ab81-03cb-ba3115772735.png)
インデックスは0から付番されています。インデックス0は1番目の文字列を指します。また、インデックスには負の整数も付番されています。負のインデックスは文字列の後ろから-1、-2・・・と振られています。このインデックスは、部分的な文字列を取得したりするのに利用するそうです。

# まとめ
今回は、はじめてのPython・変数・データ型と演算・文字列とシーケンスについて学びました。Pythonの必ず知らなければならないところでした。

また、このノンプロ研、講座中にツイートをすることが推奨されています。
今回、ツイートした内容はこちらにまとめてみました。
https://togetter.com/li/1802581

Pythonのスタート地点にたったばかりですが、これから卒業LTに向けてがんばりたいと思います。
Spresense開発環境のビルド時間を比較してみた

Spresense SDK開発環境のビルド実行時間をプラットフォームごとに比較してみました。

## 実行環境

* Windows PCのスペック
 * OS: Windows 10 Pro 64 ビット
 * プロセッサ: Intel Core i7-10700 @ 2.90GHz
 * メモリ: 16GB

* Linux PCのスペック
 * OS: Ubuntu 16.04
 * プロセッサ: Intel Core i7-4770 @ 3.40GHz
 * メモリ: 8GB

* M1 Macのスペック
 * OS: macOS Big Sur 11.6
 * プロセッサ: Apple M1
 * メモリ: 8GB

* VirtualBox(1)の設定
 * Windows PC に Ubuntu20.04 インストール
 * Main Memory: 4GB
 * プロセッサ数: 1
 * マザーボード チップセット: PIIX3

* VirtualBox(2)の設定
 * Windows PC に Ubuntu20.04 インストール
 * Main Memory: 4GB
 * プロセッサ数: 4
 * マザーボード チップセット: ICH9

## 実行コマンド

①〜④の実行コマンドを以下に示します。実行時間は単純に`time`コマンドで計測しています。

**① コンフィグレーション**
例として、Arduinoパッケージを作成するためのコンフィグレーションを実行したときの時間を計測します。コマンド実行中に、ネットワーク越しにzipのダウンロードも行っていてその時間も含まれます。

```console:config.py
time ./tools/config.py default device/adc device/camera device/charger device/emmc device/hostif device/pwm device/sdcard feature/asmp feature/audio_player feature/audio_recorder feature/audio_recognizer feature/audio_synthesizer feature/dnnrt_mp feature/gnss feature/imageproc feature/libcxx feature/lte_stub_mbedtls feature/step_counter feature/digital_filters -- +CXD56_I2C_DRIVER=n +CXD56_I2C1 +CXD56_I2C1_SCUSEQ=n +CXD56_LTE_LATE_INITIALIZE=y +CXD56_HPADC0_INPUT_GAIN_M6DB +CXD56_HPADC1_INPUT_GAIN_M6DB +CXD56_USE_SYSBUS=n -LTE_SYSCTL=y
```

**② フルビルド**
①のコンフィグレーション実行後のフルビルド時間を計測します。

```console:make
time make -j
```
**③ 再ビルド**
②でフルビルド済みの状態からソースコードを何も変更せずに再度ビルドを実行した時間を計測します。

```console:make
time make -j
```

**④ distclean**
コンフィグレーションファイルの削除を含めてクリーンビルドを実行したときの時間を計測します。

```console:distclean
time make -j distclean
```

## 実行結果

(単位:秒)

| 環境 | MSYS2 | WSL | WSL2 | Linux | M1 Mac (x86_64) | M1 Mac (arm64) | Virtual Box(1) | Virtual Box(2) |
|:-|-:|-:|-:|-:|-:|-:|-:|-:|
| ① コンフィグレーション | 96.723 | 23.816 | 2.245 | 3.789 | 6.657 | 6.461| 3.623 | 3.960 |
| ② フルビルド        | 262.530 | 80.102 | 17.194 | 34.747 | 84.001 | 47.073 | 130.303 | 40.734 |
| ③ 再ビルド         | 158.166 | 37.430 | 3.640 | 5.457 | 11.833 | 12.107 | 18.129 | 9.487 |
| ④ distclean      | 167.876 | 39.336  | 2.889 | 6.103 | 17.699 | 17.641 | 40.205 | 12.193 |

![スクリーンショット 2022-01-06 1.16.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/432852/ac1e9f82-09e4-d445-9942-38c1f5c8f305.png)

## 感想

* WSL2最強説！ (参考:[WSL2でSpresense開発環境を構築する](https://qiita.com/baggio/items/56bea3eb2b231364d7cf))
 * WSLに比べても圧倒的に速いです。
 * VirtualBoxも遅い...設定次第で大きく変わる
* MSYS2環境を使うのは止めた方が良い。 "Time is Money."
* M1 MacはRosetta2経由のx86版と[ネイティブarm64版](https://qiita.com/baggio/items/35f682e9effbca36cd97)の両方のgccで実測
 * ネイティブ版の方がコンパイルは2倍ぐらい速そう

このベンチマーク結果はPCスペックやアンチウィルスソフトの影響などにも依存するのであくまで参考値です。
技術メモ：Apexから指定オブジェクトの表示ラベルとAPI名取得

指定項目取得

```java
String accPhoneLabel = Schema.SObjectType.Account.fields.Phone.label;
```

全部項目マップ取得

```java
public static Map<String,String> getFieldLabelMap(String sObjectName){
    Map<String,String> fieldLabelMap = new Map<String,String>();

    for(Schema.SObjectField field : Schema.getGlobalDescribe().get(sObjectName).getDescribe().fields.getMap().values()){
        fieldLabelMap.put(field.getDescribe().getName(), field.getDescribe().getLabel());
    }

    return fieldLabelMap;
}
```
docker で mysql のコンテナが立ち上がらない

なぜか mysql  のコンテナが立ち上がらない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364773/a32660f3-c297-1081-3e95-7fad8a2b1212.png)


```
docker system prune
```

https://docs.docker.jp/config/pruning.html

使用していないオブジェクトを削除したら動いた

リソースが圧迫されてた（？）ぽい
Arduinoの勉強　第2弾：Arduinoの入出力（デジタル入出力）

# #Arduinoの入出力（デジタル入出力）
##はじめに
ハードウェアの勉強のためにArduinoを復習も兼ねて参考教材に沿って，勉強する．細かな部分の理解までして，自在に扱えるようになることが目的である．その第2弾として，「Arduinoの入出力（デジタル入出力）」を扱う．

## Arduinoの入出力

### サポートしている入出力一覧
![slide1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/429a7116-d82a-e659-1060-e242033a5c95.png)

### デジタル入出力
![slide2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/9ec75aea-e7e3-f6ba-289a-da5a6339c918.png)

### HIGHとLOWの判断
単に5Vと0VだけでHIGH・LOWを決めているのではなく，Threshold（閾値）により判断している．以下にそのイメージ図を示す．なお，Arduino UNOでは2.7V，2.1VがそれぞれHIGH，LOWの境界（閾値）となっているようである．
![slide3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/b492778f-d8f3-19ce-0ca5-4aab58190c4b.png)

## 感想
Arduino UNOでサポートされている入出力を改めて知った．デジタル入出力やアナログ入力などはなんとなくで使っていた．また，PWMも特に深く考えずに使っていた．ましてやデジタル通信など考えたこともない．改めて何があるかを知ることで，何ができて，何を学ぶべきかの見通しが少しは見えてくると思う．今回はそれの導入ということで，デジタル入力と出力についてまとめた．これからの学びで，今までなんとなくにしていたところが埋められていくと考えると，また士気が高まる．楽しみである．次回はPWMについて学ぶ．

## 参考文献
- 電子部品ごとの制御を学べる！Arduino電子工作実践講座 改訂第2版 福田和宏 著 ソーテック社
古いUSBデバイスをWinusbで動かす

お手元に20年ほど前に製造された**化石**のようなUSBデバイス、ありますよね？
今のOSに対応したドライバなんてものは存在しないので、汎用USBドライバであるWinusb.sysを使って無理やり動かしてやりましょうという話。
# 署名なきデバイスドライバに人権なし
ググると.infファイルを作ってうにゃんにゃというやり方が出てくるかと思います。
一つの解法ではあるのですが、**署名のないドライバはインストールが面倒臭い**というデメリットがあります。
再起動してスマートスクリーンをオフにして…となかなかに面倒です。
**実体はMS謹製のWinusbなんだから署名なんかいらねーだろ！**と怒りたくなりますが、こればっかりは仕方ない。
オリジナルの.infファイルを作る限り、以下の２通りの道しかありません。

* 面倒な方法で未署名のドライバを無理やり入れる
* 高い年会費を払ってEVコードサイニング証明書を買う

この件については以下の図がとても分かりやすいです。
> ![usb-driver-renewal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2271250/0be7009f-369f-3b18-ec4a-e25dd774f1cf.png)
> [古いUSBドライバーをWindows 10 で使いたい](http://www.devdrv.co.jp/hidaka/node/70)より引用

実は正攻法ではありませんが、ファームウェア改変不可能の先にもう一つやり方があります。

# 署名付きのWinusbドライバをインストールしてしまえ
以下のような手順でWinusbドライバをインストールします。

1. デバイスマネージャーで当該デバイスを開く
1. ドライバーの更新
1. コンピューターを参照してドライバーを検索
1. コンピューター上の利用可能なドライバーの一覧から選択します
1. 互換性のあるハードウェアを表示のチェックを外しておく
1. ディスク使用
1. "C:\Windows\INF\winusb.inf"を開く
1. Winusbデバイスを選択してインストール
1. 警告が出るが無視して入れる

![警告.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2271250/8b91fce9-ffd4-064d-224b-9a7e1e8aa0a5.png)
こんな警告が出ますが、「互換性があるかな？」じゃなくて「互換性を作るんだよ」というわけで無視してインストールします。
![署名.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2271250/7aeb3acf-48b5-0454-c340-0d06c576dfdc.png)
はい、署名はついているのですんなり入りましたね。

こんな簡単な結論に至るまで１日くらい右往左往してしまったぞ…
この記事が私と同じレベルの人の役に立ちますように…
シンプルな JSON 読み込み Java サンプル (jackson-databind 利用)

JSON をちょっと Java で読み込みたい時のサンプルをメモしておきます。

JSON読み書きには [RFC 4180](https://www.rfc-editor.org/info/rfc8259) を実装する必要がありますが、一般的にはライブラリ利用により実現します。
この例では、 `jackson-databind` を利用した JSON読み込みサンプル記述を残しておきます。

# Maven (pom.xml)

まず最初に、JSON読み込みを実現するためのライブラリである `jackson-databind` をビルドに組み込みます。 pom.xml ファイルの <dependencies> に以下の Maven Repository 記述を追加します。 (ビルドでの自動ダウンロードの実現のためには、インターネットに接続されている必要があります)

```xml
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.0</version>
</dependency>
```

# POJO 作成

`jackson-databind` はデータの読み込みに Java の POJO クラスを利用します。この POJO クラスは一般的にはツールを用いて自動生成します。ここでは、`jsonschema2pojo` を利用して、JSON文字列を入力に Java ソースコードを自動生成します。

* https://www.jsonschema2pojo.org/

`jsonschema2pojo` サイトは以下のような画面のイメージです。

![json2java.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105739/e348d5cd-e5a2-d68d-a0ce-9aabef3d165f.png)

## 生成ソースコードの設定例

* JSON文字列を貼り付け
* `Package` に生成後 Javaソースコードのパッケージ名を入力。この例では `pojo` と入力
* `Class name` に生成後 Javaソースコードのクラス名を入力。この例では `Climate` と入力
* `Source type` を `JSON` に設定
* `Annotation style` を `Jackson 2.x` に設定
* チェックボックスは、`Include getters and setters` のみチェック

`Zip` をクリックして、そして Java ソースファイルを ZIP ファイルとしてダウンロードします。

# Java 記述

生成した POJO (`Climate.java`) を利用して JSON データを読み込むプログラミングをします。

* `ObjectMapper` インスタンスを作成して、JSON文字列を入力に readValue を呼び出して、値が設定済みの Climate インスタンスを出力として取得します。

```java
import java.io.IOException;
import com.fasterxml.jackson.databind.ObjectMapper;
import pojo.Climate;

public class App {
    public static void main(String[] args) throws IOException{
        final String content = "{\"publishingOffice\":\"気象庁\",\"reportDatetime\":\"2021-11-15...高いでしょう。\"}";
        final ObjectMapper mapper = new ObjectMapper();
        final Climate data = mapper.readValue(content, Climate.class);
        System.out.println("data: " + data.getPublishingOffice());
    }
}
```

# 文書情報

* 初出: 2021-11-16

## 関連情報

* [シンプルな JSON 読み込み Java サンプル (jackson-databind 利用)](https://qiita.com/igapyon/items/14c6ff9430c5d8727e91)
* [シンプルな JSON 書き出し Java サンプル (jackson-databind 利用)](https://qiita.com/igapyon/items/384b88d364e0d241f91b)
* [シンプルな HTTP クライアント Javaサンプル (Apache HttpComponents 4.5系を利用)](https://qiita.com/igapyon/items/b0f9918db992c308949b)
アドレッシングモードとは

#アドレッシングモード
CPUの命令セットアーキーテクチャにおいて、命令のオペランド部（演算の対象となるデータのこと）を表すための方法のこと。オペランドが格納されている場所（実効アドレス）を指し示すため、実効アドレッシング・モードということもある。

　例えば加算演算を行う場合、加算命令のほかに、加算される2つのデータ（オペランド）が置かれている場所と、結果を格納する場所の3カ所を指定する必要がある（ただし多くのプロセッサ・アーキテクチャでは、加算されるオペランドの場所に結果を書き戻すことにして、オペランドの指定を2つで済ませている）。<br><strong>この場所の指定方法のことを「アドレッシング・モード」という。</strong>代表的なアドレッシング・モードとしては、イミディエイト（即値）モードやレジスタ直接モード、レジスタ間接モード、スケールド・インデックス・モードなどがある。

引用
https://atmarkit.itmedia.co.jp/icd/root/55/5784555.html

#命令セット 【ISA】 Instruction Set Architecture 
( 命令セットアーキテクチャ)

命令セットとは、あるマイクロプロセッサ（CPU/MPU）を動作させるための命令語の体系。プロセッサが直に解釈して実行できる機械語（マシン語）の仕様を定めたもの。

https://e-words.jp/w/%E5%91%BD%E4%BB%A4%E3%82%BB%E3%83%83%E3%83%88.html

#cのポインタ型のサイズ

アドレッシングモードのサイズが、ポインタ型のサイズとなる。
32bitのOSの場合、32ビットのアドレス番地を持つ。つまり0~0xFFFF FFFFまで。
64bitのOSの場合、64ビットのアドレス番地を持つ。つまり0~0xFFFF FFFF FFFF FFFFまで。

なので、ポインタ型を宣言すると、その最大値を格納できるサイズが確保される。

```c
void* ptr;
printf("%d", sizeof(ptr)); // 8
```
斜めってみた

[FOSS4G Advent Calendar 2021](https://qiita.com/advent-calendar/2021/foss4g) 5日目です。

[FOSS4G 2021 Japan Online](https://www.osgeo.jp/archives/2457) おつかれさまでした。チュートリアルデイのセッションを担当したのと、 LT で喋りました。今回は LT でも喋ったネタです。

## 万能なプロジェクションはない

まぁるい地球を平らな地図にすると、どこかに無理が生じます。断裂する箇所を作ったり、一部を引き延ばしたり。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215290/b36c0f05-7723-d2a4-f3d4-512896ff825b.png" width="222">
(C) いらすとや

よく使われるメルカトル図法も、基準線である赤道から離れるほど縦に横に拡大し、距離比率や面積比率が場所によって異なっています。経線と緯線を直線にし、直交するなどの特徴を優先したためです。

メルカトル図法の拡大率は、赤道直下を100%とすると、沖縄で110%、札幌で137%となり、沖縄を基準にしたときでも札幌は1.2倍以上で描画されます。面積比率はその2乗です。でっかいどーですね。

特に全世界レベルの表示で統計値の比較などを行う場合には不適切となることがあります。

表示の問題だけでなくデータもそうで、たとえば EPSG:3857 で保存されたデータは EPSG:3857 地図上の座標値を持つので、地図単位はメートルでも現実のメートルよりも拡大されています。

また基準線を赤道ではなく子午線とした基準とし横メルカトル図法があります。横メルカトル図法も同様に基準線から離れるほど拡大されますが、別の地域は別の基準の横メルカトルを使うことができます。

ですがこの場合、各地域で別々の座標系を使うことになるので、これはこれで面倒です。

## 斜軸

同じように基準線を斜めにすることもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215290/68003e24-55c3-e5d4-5737-e429cd2115ba.png)

よさそうなパラメータを探したところ、基準点を $\varphi=0, \lambda_0=0$ 、傾斜角 $\alpha=31.3 {}^\circ$ （北から時計回りに）がよさそうでした。また日本をほぼカバーするために、やや誤差を許容する必要があります。今回は $k_0=0.9990$ を設定し、$\pm0.1\%$許容するエリアとしました。

座標系の定義としては

```
+proj=omerc +datum=WGS84 +lonc=110 +lat_0=0 +alpha=31.3 +k_0=0.9990
```

QGIS の場合は、設定から「カスタム投影法」で利用することができます。

## メリット

この座標系でデータを作ると、若干の誤差を持ちつつもある程度正確な距離比率を保った状態なので、バッファなどのパラメータを日本全国でデータ分割・各座標系設定することなく、ほどほど正確に実行できます。

## スライド

LT で使ったスライド資料です。

https://github.com/tohka/pub/blob/main/FOSS4G_Japan_2021_LT.pdf
DIについてまとめてみる

## DIとは？
DIとは、いわゆる「依存性の注入」と呼ばれているものです。
依存性の注入だとわかりづらいので、「オブジェクトの注入」と読み替えるとわかりやすいかもです。
## 前提
例えば、PayPayクラスと、TestPayクラスが存在するとします。
どちらのクラスも、「起動する」、「支払いをする」という動作は共通しています。
共通している動作「起動する」、「支払いをする」振る舞いは、インターフェースに切り出しています。



### ケース1：コンストラクタの引数にオブジェクトを渡した場合
```php
<?php

interface E_Money
{
  // 「起動をする」という振る舞いを定義
  public function start();
  // 「支払いをする」という振る舞いを定義
  public function payment();
}

class PayPay implements E_Money
{
  public function start()
  {
    var_dump('PayPayを起動しました');
  }
  public function payment()
  {
    var_dump('PayPayで支払いました');
  }
}

class PayTestService
{
  public function __construct(PayPay $paypay)
  {
    $this->paypay = $paypay;
  }

  public function buy()
  {
    $this->paypay->start();
    $this->paypay->payment();
  }
}

$test = new PayTestService(new PayPay());
$test->buy();
// string(27) "PayPayを起動しました"
// string(27) "PayPayで支払いました"
```
コンストラクタ内に`PayPay`オブジェクトを渡して、`buy()`で`PayPay`クラスの関数を呼び出しています。
この時、**PayTestServiceクラスはPayPayクラスに依存している**状態になります。

### ケース2：コンストラクタの引数にインターフェースを渡した場合

```php
<?php

interface E_Money
{
  // 「起動をする」という振る舞いを定義
  public function start();
  // 「支払いをする」という振る舞いを定義
  public function payment();
}

class PayPay implements E_Money
{
  public function start()
  {
    var_dump('PayPayを起動しました');
  }
  public function payment()
  {
    var_dump('PayPayで支払いました');
  }
}

class TestPay implements E_Money
{
  public function start()
  {
    var_dump('TestPayを起動しました');
  }
  public function payment()
  {
    var_dump('支払いテスト');
  }
}

class PayTestService
{
  public function __construct(E_money $e_money)
  {
    $this->e_money = $e_money;
  }

  public function buy()
  {
    $this->e_money->start();
    $this->e_money->payment();
  }
}

$test = new PayTestService(new TestPay());
$test->buy();

// string(28) "TestPayを起動しました"
// string(18) "支払いテスト"
```
コンストラクタ内に`E_money`インターフェースを渡すことによって、`new PayTestService()`した時に
引数に `E_moneyインターフェースを採用している` PayPayオブジェクト or TestPayオブジェクト のどちらも入れることができます。
この時、**PayTestServiceクラスはインターフェースに依存している**状態になります。

インターフェースをコンストラクタの引数に渡すことによって、PayTestServiceクラスの単体テストがしやすくなります。

例えば、ケース1の場合だと**PayTestServiceクラスはPayPayクラスに依存している**状態なので、`PayPayクラスが完成しないとPayTestServiceクラスのテストができない`状態になります。

反対に、ケース2の場合であれば**PayTestServiceクラスはインターフェースに依存している**状態なので、`同じインターフェースを採用しているモッククラスに差し替える`ことが可能です。

このような形で、**外から依存先の情報を渡してあげる**ことを、DI(依存性の注入)と呼びます。
（k8s向け）Grafanaで踏み台経由のDB接続

Grafanaで別のネットワークにあるDBをデータソースにしたいけど、DBにはグローバルな接続ができない
というような状況はそれなりにあるかと思います

通常だとこのような状況で思いつくのは踏み台サーバーを使ったSSHトンネル越しの接続
が、Grafanaのデータソース単体でこれを設定することはできません
需要はあると思うのですが、関連するIssueを見る感じだと対応する予定もなさそうです
https://github.com/grafana/grafana/issues/24044

ので、autosshのコンテナを立てて対応してみることにします
今回はこちらを使用させてもらいました
https://github.com/jnovack/autossh
https://hub.docker.com/r/jnovack/autossh

で、このような設定のpodを作成します

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: db-tunnel
spec:
  selector:
    matchLabels:
      app: db-tunnel
  template:
    metadata:
      labels:
        app: db-tunnel
    spec:
      containers:
        - name: autossh
          image: jnovack/autossh:latest
          volumeMounts:
            - name: pem
              mountPath: "/tmp/my.pem"
              subPath: my.pem
          ports:
            - name: publish
              containerPort: 3306
          env:
            - name: SSH_REMOTE_USER
              value: tunnel-user # 踏み台のsshユーザー
            - name: SSH_REMOTE_HOST
              value: "xxx.xxx.xxx.xxx" # 踏み台のhost/IP
            - name: SSH_MODE
              value: -L
            - name: SSH_REMOTE_PORT
              value: "22"
            - name: SSH_KEY_FILE
              value: "/tmp/my.pem"
            - name: SSH_TARGET_HOST
              value: "xxx.xxx.xxx.xxx" # 最終的に繋ぎたいdbのhost/IP
            - name: SSH_TARGET_PORT
              value: "3306"
            - name: SSH_TUNNEL_PORT
              value: "3306"
            - name: SSH_BIND_IP
              value: '\*'
      volumes:
        - name: pem
          secret:
            defaultMode: 0400
            secretName: db-tunnel
---
apiVersion: v1
kind: Service
metadata:
  name: db-tunnel
spec:
  ports:
    - port: 3306
      protocol: TCP
      targetPort: 3306
  selector:
    app: db-tunnel
---
apiVersion: v1
kind: Secret
metadata:
  name: db-tunnel
type: Opaque
data:
  my.pem: xxxxxxxxxxxxxxxxxxxxxxxxx # 踏み台のsshキー
```

で、grafanaからは `db-tunnel.default.svc.cluster.local:3306` でターゲットのDBに接続できます

manifestをわかりやすくするためにpod/serviceで作成しましたが、この設定だとk8sクラスタ内どこからでもDBに接続できてしまうのであまりよろしくないです
grafanaのサイドカーでautosshのコンテナを立てて環境変数SSH_BIND_IPを127.0.0.1に設定し、`127.0.0.1:3306`で接続するのが無難かと思います

難点としては

- autosshとdbがひとつずつで対応なのでつなげたいDBがたくさんある場合は…となる
- 踏み台サーバーがが接続元IPを絞ってる場合、そこはなんとか頑張ってください

このあたりです

kubernetesでしかやったことないのでわかりませんが、ただのSSHトンネルなのでkubenetes以外にも流用は可能でしょう、たぶん
WordPressの自動返信メールのカスタムするプラグインはこれにした

ワードプレスで会員登録、ログイン機能を追加したのはいいけど、
その時の自動返信メールが雑。
なのでカスタムしたかった。

こんな感じのメールが相手に送られるので、ちょっと流石に雑すぎる。
![スクリーンショット 2021-12-05 23.38.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/898667/ad8d6447-60dc-39d5-fa67-f836364f0e1e.png)

会員登録系のプラグインの中でテキストを変更できず、ワードプレスのファイルをいじるのも大変だったのでプラグインを探しました。

そこで、「Theme My Login」を使ったんですが、これだとメール本文の修正ができなくなってた。２０２１年
https://sys-guard.com/post-14680/

なのでさらに探したら
「Customize WordPress Emails and Alerts – Better Notifications for WP」
https://nl.wordpress.org/plugins/bnfw/#reviews
このプラグインにした。

これだと、notification を追加するときに、ユーザー登録などの項目が多いのと、何より
メール文を書けるのでとても助かる
![スクリーンショット 2021-12-05 23.45.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/898667/dae455c7-9775-1564-f301-a561d7a512d5.png)

ただ、自動返信メールを設定するだけなのに、だいぶ上手くいかないことも多く、意外と情報も少なくて１日かかってしまった。

質の良い会員サイトをワードプレスだけで作れるようになってきたので、この辺も記録しておこうと思いました
誰かにチャレンジしてもらいたいときに気を付けていること

こんにちは、GxPの石村です。
この記事は[グロースエクスパートナーズ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/gxp)の8日目です。

ここしばらく、自分自身がちょっとチャレンジしたり、周囲の人にチャレンジしてもらう機会が増えています。
このアドベントカレンダーもそのひとつで、25日埋めるべく社内のいろんな人に声をかけて記事を書いてもらっています。
この記事を書いている時点で25日中24日まで予定が立っており、ありがたい限りです。

今回は誰かに「少し踏み出してもらいたい」と思った時に、私が気を付けているポイントをご紹介したいと思います。
私もまだまだうまくやれているわけではないので、これを見て「私はこうしているよ」「それは逆効果だったことがある」といったアドバイスがあればぜひ教えてください。

# ハードルは人それぞれ

最初に認識しておきたいのは、自分がその行動をとるのに感じるハードルの高さと、相手がその行動をとるのに感じるハードルの高さは違うということです。

何かをするときに、それがチャレンジなのかどうか、また、どのぐらい負担に感じることなのかは人それぞれです。
しかし、一度乗り越えた側の人間から見ると、チャレンジしてくれない人がじれったく感じたりガッカリしたりすることがよくあります。

ブログを書く、LTで発表する、行ったことのない勉強会に行く、といった他人との関わりがあるものは特にハードルを感じやすいと思います。
また、チームに「これを変えてみたい」「こんなモヤモヤを感じている」「こうしてほしいと思っている」といった提言をすることは、慣れ親しんだ相手であってもハードルを感じることだと思います。
私はこういったことに対するハードルは低い方ですが、超えてみようなんて思いつかないぐらい高く感じる人もたくさんいます。

# 期待を伝えずにガッカリするのは勝手

次に避けたいのは、チャレンジしてもらえなかったときに、勝手に期待して勝手にガッカリすることです。
どんな期待をされているか知らない状態で、期待通りの言動をとるというのは、かなり難易度が高いです。
エスパーみたいな人は存在しますが、だいたいの人は普通の人間なので、あなたの考えていることはわかりません。

「この人に是非やってもらいたい！」というチャンスが巡ってきて、「こんなのあるんだけどやってみない？」と声をかけたらあっさり断られた、なんてことはよくある話です。
相手がやりたいことと違った場合は仕方ないのですが、なぜその人にそのタイミングで声をかけたのかの説明が不十分な場合も多いです。
どんな期待を込めて誘われたのかわかっていたら回答が違う場合もあります。

私自身、あっさりした誘いだったので軽い気持ちで断ったら、しばらくたってから「こういう期待をしてたから声をかけたのに」と恨みがましく言われたことがありますが、「そんなこと言ってなかったじゃん。勝手な人だな。」と思いました。

期待を伝えることがプレッシャーになってしまう場合もありますし、勝手な期待をしないという選択肢もあります。
しかし、期待されることを嬉しく思ってくれたり、伝えることで関係性がよくなることも多いので、なるべく丁寧に伝えたいですね。

# 不特定多数ではなくひとりひとりに声がけをする

ここまでは特定の誰かへの期待についてのお話でしたが、「誰でもいいから誰かやってほしい」という場合がありますよね。
このアドベントカレンダーや、LT大会、社内勉強会などの参加者募集がそうです。

既に人気のあるイベントであれば、告知をするだけで人があつまるということもあるでしょう。
そうではない場合、オープンな場所（例えばSlackの多くの人が集まるチャンネル）で声をかけても、リアクションがないことが多いのではないでしょうか。
ここで「みんな興味がないみたいだ」と判断するのはまだ早いです。

興味があるのに反応をもらえない理由には、以下のようなものが多いです。

* 期待されているのは私じゃないだろうと思ってしまう
* ネタが思いつかない
* 宣伝文だけではイメージがわかなかったので、流してしまった
* 今度考えようと思ってそのままになっていた
* チャレンジするのは今じゃなくていいやと思っていた

これらを解消するにはひとりひとりと会話するのが一番いいと思っています。
私がよくやるのは、宣伝はなるべく多くの人がいる場所でしておき、その後で話す機会があった人ひとりひとりに声がけをする作戦です。
アドベントカレンダーでは、1on1で「こないだ参加してたあの勉強会について書かない？」とか、勉強会で「こういうネタでAさんとかBさんとかどう？」といったように声がけをすると何人かにひとりは前向きに検討してくれました。
また、すべてのひとを私が知っているわけではないので、他の子会社や部署については、そこにいる人の「人となり」を知っている人にお願いしました。
社内勉強会であれば、日々の会話の中で相手の関心ごとを知ったときに、「そういうことに関心があるならこの勉強会いいかも」とおすすめしています。

# おわりに

誰かにチャレンジしてほしいと思う気持ちを持っているイベント主催者や先輩は、たくさんいると思います。
「別にチャレンジなんてしたくない」と思う人からすれば、余計なお世話かもしれません。
でもきっと、チャレンジしてほしいと思う背景には、チャレンジした先にある素敵なことを体験してほしい気持ちがあるはずです。
それを丁寧に伝えていくことはめんどくさい部分もありますが、ひとりひとりと向き合うことで、より意味のあるチャレンジができたり、チャレンジしてくれたことへの喜びが倍増することにつながります。
ぜひチャレンジ仲間を増やしていきましょう！来年もよきチャレンジを！
【JavaScript】変数宣言の使い分けについて（var let const）【初学者の疑問点を簡潔に解説】

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

## 今回の疑問点
　今回の疑問点は、

　　_JavaScriptにおける変数宣言の使い分け_
　
　です。　

　最近、JavaScriptを勉強し始め、上記の点については一度まとめておいた方が良いと感じたので、記事にすることにしました。
## 疑問点についての解説

###結論
　varは現在は、ほとんど使用されていない。
　letは再代入が必要なときに使用し、constは定数的に扱う場合に使用する。

###それぞれの変数宣言の違いと特徴
　それぞれの再宣言、再代入、スコープについてまとめます。

####再宣言
**再宣言**：一度宣言した変数名と同名の変数を再度宣言すること

`var` → 可能。
`let` → Uncaught SyntaxErrorが出る。不可。
`const` →　Uncaught SyntaxErrorが出る。不可。

####再代入
**再代入**：変数に値を代入した後に別の値を代入すること（変数の中身だけを変える）

`var` → 可能。
`let` → 可能。
`const` →　Uncaught TypeErrorが出る。不可。

####スコープ
**スコープ**：変数の有効範囲
**グローバルスコープ**：どこからでも参照可能
**関数スコープ（ローカルスコープ）**：関数の中でのみ有効
**ブロックスコープ（ローカルスコープ）**：ブロック`（）`や`{}`の中でのみ有効


`var` → グローバルスコープと関数スコープの変数を宣言可能。
`let` → ブロックスコープの変数を宣言可能。
`const` →　ブロックスコープの変数を宣言可能。


## まとめ
最後にポイントをまとめます。

|  | var | let | const |
|:-:|:-:|:-:|:-:|
| 再宣言  | ○  | ×  | ×  |
| 再代入  | ○  | ○  | ×  |
| スコープ  | グローバル・関数  | ブロック  | ブロック  |

　上記の表から、`var`はスコープも広く一見便利そうに見えますが、スコープが広いことで、意図しない参照等からエラーが発生する可能性を高めてしまうため、現在はあまり使用されていません。

　`let`と`const`では、`let`が再代入可能、`const`では不可であるため、

- `let`を再代入が必要な場合に、
- `const`は定数的な扱いをする場合に使用します。
サポートと協議したPiMAX ８K Plus ベストセッティング

Valve Index から PiMAX 8K Plusに乗り換えて一番の不満点は解像度でした。
それは明らかにValve Indexよりぼやけた甘い画像でした。

そこでPiMAXのサポートと色々やりとりして聞き出したセッティングを列記します。色々これ以外にも試しましたが、概ねこのセッティング以上に画質を改善することはできませんでした。
片目4KなのになぜValve Indexより体感解像度が悪いのかですが、表示している範囲が広いことが最も影響していると考えています。

・視野角
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201026/d33fdd76-40c0-4a20-f17e-e0ed44868e13.png)
画質には直接影響しません。
ただ、描画角度を狭める程GPUへの負荷は減ります。せっかくの広FOVですので「大きい」一択ですかねぇ。

・画質を調整します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201026/bba76cae-71c0-65d9-1242-06889f97a5af.png)

これが画質調整のキモです。「1.25」または「1.5」に設定します。
これに伴いStemaVRのレンダリング解像度を「カスタム」にし。片目あたりの解像度を「46%」にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201026/506ba54e-8c90-b92c-fdcb-60056cad44f9.png)
なぜ低い解像度でも良いのか疑問ですが、確かにこれ以上の値を入れても解像度は改善されません。
ちなみに8K Plusの片目のパネルは、2560 × 1440をPCより送信し、HMD側で3840 × 2160にスケールアップしています。従って、3840 × 2160以上の解像度を設定しても無駄なのでしょう。
「画質を調整します」がなぜ1よりちょっと大きめの値が良い結果を出すのかの理由は謎です。すいません。


・固定注視レンダリング
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201026/19361170-b4a0-3c58-886d-ef3d8209df1c.png)
「閉じる」を選びます。以下にも概ね同じですが、オプション類はOFFにしておく方が、画質は向上すると
いう雰囲気のサポート側のニュアンスでした。

・平行射影対応
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201026/750affdd-48e5-6ca4-6600-b9294e1f286a.png)
チェックを外します。

・スマートフレームをオンにする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201026/ca7ef7a2-6173-d36c-4e4a-08718bfbaf49.png)
チェックを外します。

・Compulsive Smooth
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201026/87195285-9a32-9878-454d-5663651c2e00.png)
「Close」を選びます。

・隠し領域カバーをオンにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201026/def36926-aea7-a0dc-d253-aec4408a7c7c.png)
チェックを外します。

・Vive独占ゲーム対応
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201026/67f177da-82d6-9723-d76e-b75055c0e016.png)
お好みでOKです。

以上で得られる限り高い解像度が得られると思います。
その日にgithubにpushした数が規定の回数に届かなかったら自動でcommit&pushして草を生やしてくれるシェルスクリプト

題名通りのシェルスクリプトを書いてみました。
理由としては二つあります。

1. シェルスクリプトを全然書いた事が無いので勉強したかったから。
2. githubの草を自動で生やしたいから。(ごめんなさい)

**※githubの草を生やす方法は下記をご参照ください(必ずしもcommit&pushすれば草が生えるというわけではありません)**

https://docs.github.com/ja/account-and-profile/setting-up-and-managing-your-github-profile/managing-contribution-graphs-on-your-profile/why-are-my-contributions-not-showing-up-on-my-profile#about-your-contribution-graph

今回書いたコードを下記に載せます。(泥臭いコードになっていますがそれは今後の課題としておきます)

筆者の環境
OS : macOS Big Sur 11.6
bash : 3.2.57(記事を書いてる途中でかなり古い事に気がつきました。すみません...)

```bash
#!/usr/bin/env bash

set -e

function push_commit (){
  for i in `seq $1`;do
    echo 'hoge' >> ./hoge.txt
    git add ./hoge.txt
    git commit -m "$(gdate +"%Y-%m-%d"):$i 回目の自動プッシュ"
    git push
  done
}

function calc_push_date (){
  local commit_datetime=$1; local result
  commit_datetime=`echo ${commit_datetime%Z}`
  commit_datetime=`echo ${commit_datetime//T/ }`
  result=$(gdate -d "9 hours $commit_datetime" +"%Y-%m-%d")
  echo $result
}

declare -i today_push_count=0
readonly PUSH_QUOTA_COUNT=5

json=$(curl -H "Accept: application/vnd.github.v3+json" https://api.github.com/users/$GITHUB_USER_NAME/events | jq)
len=$(echo $json | jq length)

for i in $( seq 0 $(($len - 1)) ); do
  row=`echo ${json} | jq .[${i}]`
  event_type=`echo ${row} | jq -r .type`

  if [ ${event_type} = "PushEvent" ]; then
    created_datetime=`echo ${row} | jq -r .created_at`
    push_date=`calc_push_date $created_datetime`
    today=$(gdate +"%Y-%m-%d")
    if [ "$push_date" = "$today" ]; then
      today_push_count=$((today_push_count+1))
    fi
  fi
done

additional_push_count=$((PUSH_QUOTA_COUNT-today_push_count))
if [ $additional_push_count -gt 0 ]; then
  push_commit $additional_push_count
else
  echo "今日は既に$PUSH_QUOTA_COUNT 回のプッシュをしています"
fi

```

以降自分用のメモとして書いておきたいことをずらずらと書いていきます。

### jsonを扱う時はjqコマンドで色々できて凄く便利
今までjqコマンドはcurlコマンドで取得したjsonを見やすくする為に`curl *url* | jq`くらいでしか使った事ないですが色んな事ができて便利です。

https://stedolan.github.io/jq/

### macOSのdateコマンドに--dateオプションが無い
dateコマンドでググるとよく出てくる`date -d "1 days"`みたいなオプションが最初使えませんでした。
理由としては上記のようなオプションで書くにはGNU版のコマンドではなくてはいけないらしいのですが、MacにはBSD版のコマンドがインストールされているため使えないかららしいです。

なので下記を参考にHomebrewからGNU版のコマンド達をインストールしました

https://blog.freedom-man.com/macos-gnudate

https://www.shigemk2.com/entry/20120416/1334578046

### リポジトリを跨いで全てのコミットを取得するにはActivityからどんどん辿っていけば取得できそう
今回はpushした数・日時を取得しましたがは本当はcommitの数・作成した日時を取得したいので、下記の流れでコミットの情報が取れそうです。

1.[ユーザーのアクティビティ](https://docs.github.com/ja/rest/reference/activity#list-events-for-the-authenticated-user)を取得
2.[取得したレスポンスのtypeパラメータのPushEventに各コミットのurl](https://docs.github.com/ja/developers/webhooks-and-events/events/github-event-types#pushevent)があるのでそれを取得
3.[作成日時を取得](https://docs.github.com/ja/rest/reference/repos#get-a-commit)

もっと上手なやり方があったら是非ご指摘ください。

https://docs.github.com/ja/rest/reference

## 今後の改善点
- コードを綺麗に改善する
- pushではなくてcommitを集計する
- 初期化のコードとかも可能なら書く(現状だとまずはリモートリポジトリを作ってそれからoriginのURLを設定して...みたいにセットアップする必要があるので)

https://github.com/ryo-takaya/auto-push-script/blob/master/auto-push.sh
小ネタ：IntelliJでCSVファイルをテーブル形式で参照する

この記事は　[ZOZO #3 Advent Calendar 2021](https://qiita.com/advent-calendar/2021/zozo) １０日目の記事になります。

小ネタです。

DBUnitなどでテスト用のDBテーブルのレコードをCSVで用意することありますよね。

そのレコードを作るのが面倒だったりするのですが、IntelliJにはCSVをテーブル形式で参照できる機能があります。

![スクリーンショット 2021-12-06 18.22.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150455/0ce146a6-2ee9-850e-a0ff-c2b371288964.png)

たとえばこんなCSV。タイトルと行が位置あっておらず編集しずらいです。

![スクリーンショット 2021-12-06 18.22.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150455/24ff0d6e-873d-4ffe-e6ac-e049b30ea101.png)

右クリックで上記のようにテーブル形式に表示するメニューが出てきます。

![スクリーンショット 2021-12-06 18.22.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150455/2d7c0551-582b-21fb-5203-29347c0ad727.png)

こんな感じで編集、行追加も可能です。

![スクリーンショット 2021-12-06 18.22.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150455/6edfeea2-b511-f660-a409-914b9a612b35.png)

画面左下から切り替えも可能です。

以上小ネタでした。

明日は@satto_sannの記事になります！
ファイルのdropイベントが発火しないときに見るメモ

drag and drop の実装をしたいとき 
dragenter、dragleave は発火するのに drop だけが発火しない事象に遭遇した。


## ブラウザデフォルトの 画像をブラウザ上で表示する機能をキャンセルする必要があった


```javascript
// ファイルドロップしたときに ブラウザデフォルトの 画像をブラウザ上で表示する機能をキャンセル
const htmlReplaceCancel = (e) => {
  e.preventDefault()
  return false
}
document.addEventListener('dragover', htmlReplaceCancel)
document.addEventListener('drop', htmlReplaceCancel)

```
カラーのPDFを白黒2値に変換するやつ

# はじめに
<font size="6" color="DarkGreen">__この記事は[苫小牧高専アドベントカレンダー2021](https://adventar.org/calendars/6387) 6日目の記事です。__</font>
[これ](https://colab.research.google.com/github/SnowFairyTea/pdfBlackAndWhiteBinarization/blob/main/pdfToImgToBW.ipynb#scrollTo=2h5RGAcQybI-)を作った話です
# 導入
とある先生が**ノート提出を白黒2値のpdfで出せ**とのたまいました。
そこでカラーのPDFを白黒2値で印刷する必要があったのですが、調べた感じ[Acrobat Pro](https://www.adobe.com/jp/acrobat/acrobat-pro.html)が必要っぽかったです。
~~奴~~**その先生**はライセンスを持っていますが、我々学生は[そんな高いもの](https://www.adobe.com/jp/acrobat/acrobat-pro.html)は持っていません。
大変キレたので自分用にこれを作成しました。
~~MacOSなら普通に二値化できるらしい~~

# 成果物

https://colab.research.google.com/github/SnowFairyTea/pdfBlackAndWhiteBinarization/blob/main/pdfToImgToBW.ipynb


# 使い方
<font color="Red">**CTRL＋ENTERでセル内のコードを実行しつつ次のセルに進むことができます。 
セルを順番に実行したいときはCTRL＋ENTERを連打すると良いでしょう**</font>

1. 1つ目のセルを実行します。  
(pdfをアップロードするためのフォルダ(pdf_file)が生成されます。)
1. 左のファイルアイコンをクリックしてファイル管理する画面を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1495553/b79e1c56-ace1-8609-82d2-50471121f982.png)



1. pdf_file/以下に変換したいPDFファイルをアップロードします。
複数のpdfをアップロードできます！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1495553/a46f34b8-15d7-292d-73e2-95b311a6f2ea.png)



1. 残ったすべてのセルを上から順に実行します。
1. ファイルを開きなおします（更新するため）。
↓開きなおした後のファイル画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1495553/72611c30-c665-05ef-d7ee-3c058d90cb8e.png)

増えたフォルダについての解説は以下の通りです。

+ result_dir
    + 白黒変換後のpdfが格納されているフォルダ。
* img_dir
    * 白黒変換後のpdfの内容がページ毎に画像化したものが格納されているフォルダ

こんな感じで格納されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1495553/1b070efc-8a50-688c-99e6-eee8585cffbe.png)


1.  ほしいデータをダウンロードします。
    1. 補足：二値化のしきい値は１つ目のセルにある変数threshに代入する値をいじることで変更できます（0~255）


# 実行例
before
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1495553/6bb20b04-7924-9c63-1a35-e6edc8234626.png)

after(thresh==170)
![01.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1495553/b7ecb506-f83c-1982-6307-627d020cd84f.jpeg)

after(thresh==200)
![01 (2).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1495553/339100c1-64e1-17d6-3abd-2e9d7e22d47a.jpeg)




# ソースコード
[ここに載ってます。]
(https://github.com/SnowFairyTea/pdfBlackAndWhiteBinarization)
やってることはpdf2imageでpdfを画像に変換し、その画像をcv2で二値化してimg2pdfでpdfにくっつけなおしているだけです。


# 終わりに
奴先生は多分この課題を出し続けると思われます。
そうなったときにこの記事を思い出して楽をしてもらえたらなと思いこの記事を執筆しました。
ちなみに紙でノートを取っている人はスキャンの段階で二値化できるのでそうしたほうが速いですね。
私はiPadのGoodNotesを使ってノートを取っていたのでバックアップのpdfファイルをこれに投げて提出しました。~~締め切り後に~~

[苫小牧高専アドベントカレンダー2021](https://adventar.org/calendars/6387)、明日は[nullpointerexception]さんです!!

それでは！！
React Hook Form v6 でMaterial UIのSwitchに初期値が入らない

##はじめに
初投稿になります。
業務でReact Hook Form v6を使っていて、かなり詰まったので投稿します。

##現象
タイトルの通り、React Hook Form v6のdefaultValuesに設定した値が
Material UIのSwitchに設定されないという事象が発生しました。
Switchだけでなく、ラジオボタンやチェックボックスでも同じだと思います。

```
import { Button, Switch, FormControlLabel } from "@material-ui/core";
import { Controller, useForm } from "react-hook-form";

const ReactHookFormTest = () => {
  const { handleSubmit, control } = useForm({
    defaultValues: {
      switch1: true,
      switch2: true
    }
  });

  return (
    <>
      <form onSubmit={handleSubmit((data) => console.log(data))}>
        <Controller
          as={Switch}
          type="checkbox"
          name="switch1"
          control={control}
        />
        <br />
        <FormControlLabel
          control={
            <Controller
              name="switch2"
              control={control}
              as={Switch}
            />
          }
          label="aaa"
        />
        <Button type="submit" color="primary">
          送信
        </Button>
      </form>
    </>
  );
};

export default function App() {
  return (
    <div className="App">
      <ReactHookFormTest />
    </div>
  );
}

```
![スクリーンショット 2021-12-05 22.59.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1342270/3e841be1-ef11-24f9-f7eb-f0d768219c99.png)
defaultValuesに両方trueを設定しているのに、スイッチがオフのままです...。

##原因
React Hook Formのバージョンによる原因だったようです。
公式のGithubのリリース情報を調べてみると、チェックボックス系の仕様が
v6.0.3から変わったようで、Controllerの中のasプロパティは使えないようです。
v6.0.3以上を使っている場合は、renderプロパティを使う必要があります。
ちなみに上記コードはv6.0.2以下のバージョンであれば、正常に動作しました。

##対策
公式Githubで拾ってきたコードに変更してみた。

```
import { Button, Switch, FormControlLabel } from "@material-ui/core";
import { Controller, useForm } from "react-hook-form";

const ReactHookFormTest = () => {
  const { handleSubmit, control } = useForm({
    defaultValues: {
      switch1: true,
      switch2: true
    }
  });

  return (
    <>
      <form onSubmit={handleSubmit((data) => console.log(data))}>
        <Controller
          render={(props) => (
            <Switch
              onChange={(e) => props.onChange(e.target.checked)}
              checked={props.value}
            />
          )}
          type="checkbox"
          name="switch1"
          control={control}
        />
        <br />
        <FormControlLabel
          control={
            <Controller
              name="switch2"
              control={control}
              render={(props) => (
                <Switch
                  onChange={(e) => props.onChange(e.target.checked)}
                  checked={props.value}
                />
              )}
            />
          }
          label="aaa"
        />
        <Button type="submit" color="primary">
          送信
        </Button>
      </form>
    </>
  );
};

export default function App() {
  return (
    <div className="App">
      <ReactHookFormTest />
    </div>
  );
}

```

![スクリーンショット 2021-12-05 23.11.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1342270/abdbfd48-f0f2-52cb-e992-c120ebb7134a.png)

見事チェックが入りました！