OmniAICreator/Qiita-1.07M huggingface dataset:
PHPのjson_encode←変数→json_decodeで改行コード(LF)が含まれている場合の挙動

PHPの `json_encode` と `json_decode` でこれまで把握していなかった挙動を最近知ったのでメモとして残しておきます。

動作環境は `PHP 7.4.28` を利用しました。

```
$ docker container run --rm -it php:7.4.28-cli-alpine /bin/sh
```

まず、改行コード(LF)を含む変数をヒアドキュメントで作成（変数 `$heredoc` にセット）します。

```
# vi json_test.php
<?php

$heredoc =<<<EOD
12345
ABCDE
67890
FGHIJ
EOD;

var_dump($heredoc);
```

実行してみると、このように改行を含んだ形で変数の内容が表示されました。

```
# php json_test.php
string(23) "12345
ABCDE
67890
FGHIJ"
```

次に、先ほどの変数 `$heredoc` を連想配列にセットして、 `json_encode` を実行するための元ネタを作成します。

```
$array = [
    'heredoc' => $heredoc,
];

var_dump($array);
```

実行してみると、このように連想配列に改行を含んだ形でセットされていることがわかります。

```
# php json_test.php
・
・
array(1) {
  ["heredoc"]=>
  string(23) "12345
ABCDE
67890
FGHIJ"
}
```

次に、先ほど作成した連想配列を `json_encode` してみましょう。

```
$encode = json_encode($array);

var_dump($encode);
```

実行してみると、改行コード(LF)が文字列の「\n」に変換されて格納されていることがわかります。これまでこの挙動を知らなかったので、なるほどなと思いました。

```
# php json_test.php
・
・
string(40) "{"heredoc":"12345\nABCDE\n67890\nFGHIJ"}"
```

それでは、 `json_encode` された変数を `json_decode` で元の形にもどしてみます。（連想配列の形式にするため、第2引数の `associative` に true を渡します）

```
$decode = json_decode($encode, true);

var_dump($decode);
```

実行してみると、文字列の「\n」が改行コード(LF)の状態に戻っていることがわかります。

```
# php json_test.php
・
・
array(1) {
  ["heredoc"]=>
  string(23) "12345
ABCDE
67890
FGHIJ"
}
```

では、元の変数 `$heredoc` をこのように「\n」を含む形でセットしたらどうなるのでしょう？

```
$heredoc =<<<EOD
12345
A\nBCDE
67890
FGH\n\nIJ
EOD;
```

`json_encode` を実行するとこうなりました。そりゃそうか。

```
# php json_test.php
・
・
string(46) "{"heredoc":"12345\nA\nBCDE\n67890\nFGH\n\nIJ"}"
```

もちろんこれを `json_decode` すると、文字列の「\n」が改行コード(LF)に変換されてこうなります。 `json_encode` 、 `json_decode` を行う際、「\n」には注意が必要ですね。

```
# php json_test.php
・
・
array(1) {
  ["heredoc"]=>
  string(26) "12345
A
BCDE
67890
FGH

IJ"
}
```

JSONの文字列に改行コード(LF)を含んでいると、ダブルクォートで括ったときにJSONの形式が壊れるので、改行コード(LF)を「\n」に変換するような挙動になっているんだと思いますが、知っておかないとバグの原因になりそうだなと感じました。
もしかすると、 `json_encode` 、 `json_decode` の引数「[flags](https://www.php.net/manual/ja/json.constants.php)」で何かしら制御ができるかもしれませんが、今回そこまでは調べてません。

#### 追記(2021/03/20)

@tadsan から「[ヒアドキュメント構文](https://www.php.net/manual/ja/language.types.string.php#language.types.string.syntax.heredoc)」と「[Nowdoc構文](https://www.php.net/manual/ja/language.types.string.php#language.types.string.syntax.nowdoc)」で動作が違いますよ、と教えてもらいました。
php.net の説明によると、「ヒアドキュメントがダブルクォートで囲んだ文字列として扱われるのに対して、 Nowdoc はシングルクォートで囲んだ文字列として扱われます。」とのこと。

つまり、このように文字列の「\n」を含む形でNowdoc構文（終端を示す識別子をシングルクォートで囲む）で定義して、

```
<?php

$nowdoc =<<<'EOD'
12345
A\nBCDE
67890
FGH\n\nIJ
EOD;

var_dump($nowdoc);
```

実行してみると、Nowdoc構文はシングルクォートで囲んだ文字列として扱われるので「\n」は「\n」のまま出力されます。（改行コード(LF)には変換されません）

```
php json_test.php 
string(29) "12345
A\nBCDE
67890
FGH\n\nIJ"
```

変数 `$nowdoc` に対して `json_encode` を実行してみると、

```
$array = [
    'nowdoc' => $nowdoc,
];
$encode = json_encode($array);

var_dump($encode);
```

文字列の「\n」は「\\\n」とエスケープされ、改行コード(LF)は「\n」となります。

```
string(48) "{"nowdoc":"12345\nA\\nBCDE\n67890\nFGH\\n\\nIJ"}"
```
RubyのThreadについてメモる

個人的メモ。知らなかったところだけ箇条書きでメモる。

https://docs.ruby-lang.org/ja/latest/class/Thread.html

- スレッド終了時には ensure 節が実行されます。これはスレッドが正常に終了する時はもちろんですが、他のスレッドから Thread#kill などによって終了させられた時も同様に実行されます。
- スレッドの状態は、run, sleep, aborting, dead
- Thread.abort_on_exception = true によって、いずれかのスレッドが例外によって終了した時に、インタプリタ全体を中断させます。false の場合、あるスレッドで起こった例外は、Thread#join などで検出されない限りそのスレッドだけをなにも警告を出さずに終了させます。
- Thread.exit は、カレントスレッドに対して Thread#exit を呼びます。
- Thread.forkとTread.startは、スレッドを生成して、ブロックの評価を開始します。生成したスレッドを返します。基本的に Thread.new と同じですが、 new メソッドと違い initialize メソッドを呼びません。
- 非同期割り込みの利用は難しいため、スレッド間での通信を実現する場合はまずはキューのような他の方法を検討してください。それでも非同期割り込みを利用する場合は本メソッドをよく理解してから利用してください。
   - スレッド間で共有される変数はどうやって定義されるんだっけ？
- スレッドローカル変数は、`thread_variable_get(key)`, `thread_variable_set(key)`でセット/ゲットできる。
   - Fiberローカル変数は、Thread#[] でセット/ゲットできる。
- Thread#valueは、スレッド self が終了するまで待ち(Thread#join と同じ)、そのスレッドのブロックが返した値を返します。スレッド実行中に例外が発生した場合には、その例外を再発生させます。
10ヶ月くらい担当していた案件の振り返りをしてみた

# 概要

Flutter開発案件のPMを担当したのでナレッジを残します。
案件規模は2つのFlutterアプリ開発をほぼ同時期に開発する案件、合計５０人月くらいでした。

# やったこと

要件定義工程で見積を行い、
基本設計工程以降は請負開発で開発しました。

技術構成

・Flutter（Riverpod, SharedPreferences, など）
・Firebase（Firestore, API(CloudFunctions), など)

PjMの役割、やったこと

・スケジュール調整、作業指示、成果物レビュー（コードも）、顧客調整

メンバー全員Flutter開発経験は未経験だったので、
モバイルアプリ開発歴の長い自分の方で成果物レビューも担当しました。

# 振り返り

## わかったこと

- Flutter の開発についての所感を得た

Flutterは初めてでしたが、XamarinやIonicなどのクロスプラットフォームに比べて
UI描画の点が優れていると思いました。

UI描画が優秀でパフォーマンス、端末差分の問題が思ったほど出ませんでした。
端末差分については通常のandroidアプリ開発よりもよかった印象です...

また、ライブラリが豊富でいろいろ機能をつなぎこみやすいのと、
ライブラリの中身も最終的にandroid/iosのコードになるので、FLutter自体のFWでなければ
それなりに読めて、ライブラリができること・できないことの把握もしやすかったです。

一方でコードの書き方はdartがkotlinに比べると弱いなぁと思うのと、
Widgetの作り方がコンポーネントの設計に慣れないと必然的に長いView・深いネストが生まれやすいなぁと思いました。

- 大きく計画を作って、小さく立て直していく手法

上司には「プロジェクトのクリティカルパスの見極めとリスクの洗い出し、ABプランの用意を進めてください」的なことをよく言われました。
自分なりに今回実践できたのは、各工程の区切りをクリティカルパスと定め、
クリティカルパスに到達するためのリスクの整理と細かいスケジュールの調整をしました。

スケジュールの調整という点では大枠の工程の区切り、見積計算に対しての計画を作りました。
これは大体1ヶ月、その後詳細な作業内容を1週間単位で作っていました。
実際、遅延や前倒し、差し込みが入れば1日レベルで計画が狂うので、
細かく作りすぎず、日々の細かい調整と1週間での調整を繰り返すことでPJとして問題に対応しやすくできたと思います。

リスクの整理という点では妥当なプラン以外に取れるプランみたいなものを常に考えるようにしていました。
これは、調達の時に特に必要な考えで、追加でFlutter開発要員を探したいというときがあったのですが、
流石に全然市場に出てこない。なので、テストをメインにする予定だったメンバーを開発に維持して、
テスターを追加することでPJとして必要なリソースを揃えるということができました。

- 品質の作り込み方

試験計画を結合試験、総合試験の段階で立てましたが、
計画時点で不足した試験を強化試験という形で追加・実施しました。
受入試験や単体試験で実施しきれなかったところ、品質のリスク（重要機能、不具合が多い）を感じるところに
強化試験を積み重ねていきました。
試験を増やすだけではなく、技術的な問題に対して設計を行い、不具合が起きにくい作り、
起きた不具合に対しての横展開を行なっていきました。

## うまくいかなかったこと

- PJの負荷増

Flutter開発経験は全員なく、モバイルアプリ開発経験もいくらかばらつきがありました。
一番経験が長かったのが自分だったので、技術面のリードも自分ともう一名でおこなっていましたが、
自分が行ったのは完全に悪手でした。
プロジェクト管理で手が埋まり、経験値の大きい技術ならともかく新しい技術をメンバーより先に吸収して、
リードするのは完全に無理でした。
その結果、メンバーがサンプルにするコードの準備がうまくいかず、メンバーそれぞれに頑張ってもらいながら
進めていくようになりました。
結果として、メンバーが成長しコードは間に合いましたが、けっこうそれぞれのコードが広がっちゃったなぁと

## 次にやること

エンジニアとしてはFlutterの開発をもっと行い、リードできるだけの実装経験を積みたい。
PjMとしては負荷を上げすぎなくても良いプロダクトを作っていけるようにしたい。
Rustのファイル分割方法

## 1. はじめに

ファイル分割ができると、ファイル管理がしやすくなります。今までは Rust で何回も cargo new をして分けていましたが、容量が圧迫してきたので分割方法を探りました。

記事を見ながらコードを書くことを想定して執筆したため、講義形式の記事になります。

完成後のサンプルコードは下記 URL にあります。
file_split URL:
https://github.com/DiaSird/files_split

## 2. プロジェクトの作成

今回は Hello World!を例にファイル分割を行います。
まず、cargo new で新規プロジェクトを作ります。

```ps
$ cargo new files_split
```

ここで、main プログラムにある出力形式(println!())を関数 say_hello();に書き換えておきましょう。

```rust
// main.rs
fn main() {
    // Hello, world!
    say_hello();
}
```

## 3. モジュールで整理する

次に、src フォルダに lib.rs と module フォルダを作成します。下のように、lib.rs で module の宣言を行います。

```rust
// lib.rs
// pub mod <directory name>
pub mod module;
```

続いて module フォルダ内の操作に移ります。

module フォルダでは、最初に mod.rs を作成します。
mod.rs 内では下記のように、モジュールとクレート(モジュールツリー)の宣言を行います。

```rust
// mod.rs
// pub mod <module file name>
pub mod hello;
// pub use crate::<module name>::<module file name>
pub use crate::module::hello::say_hello;
```

module フォルダの中での module は、次に作成する hello.rs に該当します。

hello.rs を作成し、下のように say_hello 関数を作成しましょう。pub は public の略称で、rust はデフォルトの状態が外部から呼び出せない private な関数となっています。

```rust
// hello.rs
pub fn say_hello() {
    println!("Hello, world!");
}
```

## 4. 実行

最後に src/main.rs に戻り、ワイルドカード \* 形式でファイル(or ファイル群)にある関数を呼び出します。中継役は lib.rs が担当しています。

main.rs の変更:

```rust
// main.rs
// use <project name>::<module name>
use files_split::module::*;

fn main() {
    // Hello, world!
    say_hello();
}
```

以上でファイル分割は完成です。サンプルコードでは module フォルダ内で hello2.rs を追加していますが、main 関数で say_hello2();をコメントアウトすれば自由に出力形式が切り替えられます。

この記事の応用例として、構造体ではimplを複数ファイルに分離して書けることから、各ファイルでパスを通せば大規模なプログラムも作成可能です。

実行: 

```ps
$ cargo run
```

実行結果:
```ps
Hello, world!
```

## 参考資料

Rust をやってみる(ファイル分割)

- 前編
  https://www.wow-creators.com/programming/rust%E3%82%92%E3%82%84%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%88%86%E5%89%B2/
- 後編
  https://www.wow-creators.com/programming/rust%e3%82%92%e3%82%84%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%8b%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e5%88%86%e5%89%b2-%e5%be%8c%e7%b7%a8/
初心者ブロックチェーンに挑戦する　17

# 次の課題はNFT

## 昨日は本物をいただきました。今日は偽物をつくります。

　こう書いておいて、NFTの本物とか、偽物ってなんだ、って、ちょっと考え込んでしまう。いただいたパスポートは画像でしかなくて、同じデザインのパスポートは、ほかの修了者だって持っている。そしてだれも、それを手で持つわけにはいかない。空港のコントロールで見せるパスポートみたいな物質ではないからね。
　ただ、昨日いただいたNFTは、私が所有しているという事実が本物のブロックチェーンに刻まれているし、売ることもできる(売らないけど)。そのに対して、これからつくるのは、テストネット上の、ダミーのブロックチェーンに刻まれる。だから、前回のおもちゃのお金に引き続き、おもちゃの所有権、というところでしょうかね。

　まずはスマートコントラクト、バックエンドからつくっていきます。terminalでdirectoryやfileつくるのも、VSCodeで編集するのも、慣れてきましたねえ。そうそうterminalの

- code　なんてコマンドはないよ

という、つれない返事に対応することも学びましたよ。

https://maku.blog/p/f5iv9kx/

　語学は音で勉強したいタイプで、実はプログラム言語も音読しながら打ってますす。とくに英語としてなり立ってるものは英語として読むし、英語を略してるとわかれば、元に戻して発音してます。たとえば

- mkdir は　make directory 

　ほんとはそういう略じゃないよ、というのがあっても、自分で覚えてタイプしやすければいい。でも、hreとか、npxとか、頭文字系のヤツは読みにくくてキライ。ちなみに

- height をヘイトと発音するの、やめてほしい。

## NFT作成手順

-　画像を選んで[Imgur](https://imgur.com)にアップロードします。
-　そのURLをつかって、NFTのメタデータをつくります。
-　メタデータを[JSONkeeper](https://jsonkeeper.com)に保存します。
-　[Alchemy](https://www.alchemy.com)にprojectをつくります。･･･テストネットね。
-　お財布が空にならないようにおもちゃのイーサを補充します。
-　それらの情報をsolidity fileやhardhat.config.jsに貼ります。

　はい、実行しま〜す
　はい、できました〜

## 本物とおもちゃでは、OpenSeaも違う。

　自家製NFTが登録されたのはおもちゃの[OpenSea](https://testnets.opensea.io)。今日つくったNFTだけじゃなく、すでに終了した人のサイトで遊んで獲得したNFTもある。
　昨日いただいたのは、本物の[OpenSea](https://opensea.io)にあります。

　今日はここまで〜。
JSONの型確認（JavaScript）

JSON の型が一致するかの確認をしたかったので、サンプルを書きました。
型の確認といっても、JSON は Key と value のペアの配列という扱いなので、Key の有無チェックをすることになります。
また、key に対しての value が null だと、確か、key が存在しない扱いになり、判定できないということになるため、実装の際は、注意が必要になりそうです。

```jsonCheck.js
// JSON の判定用 key リスト
const type_1 = {
    type: 1,
    key_list: ["param1", "param2"],
};

const type_2 = {
    type: 2,
    key_list: ["param_a", "param_b"],
};

const JSON_CHECK_LIST = [
    type_1, type_2
];

function checkType1() {
    // JSONの形状の判定対象
    /*
    // こっちで実行すると type = 1 の判定
    let target = {
        "param1": "a",
        "param2": "b"
    };
    */

    // こっちで実行すると type = 2 の判定
    let target = {
        "param_a": "a",
        "param_b": "b"
    };

    console.log("type->");
    console.log(jsonTypeChesk(target));
}

/**
 * 各パラメータの存在チェック
 * @param {JSON} json 
 * @returns type値
 */
function jsonTypeChesk(json) {
    for (let i = 0; i < JSON_CHECK_LIST.length; i++) {
        let isNotContain = false;
        for (let key_i = 0; key_i < JSON_CHECK_LIST[i].key_list.length; key_i++) {
            let key = JSON_CHECK_LIST[i].key_list[key_i];

            // null が取得される場合は、パラメータが存在しないため、型が不一致の判定
            if (json[key] == null) {
                isNotContain = true;
                break;
            }
        }
        if (isNotContain) {
            continue;
        } else {
            // isNotContain == false なら、型一致の判定
            return JSON_CHECK_LIST[i].type;
        }
    }
    console.error("該当するType が存在しません。");
    return null;
}

```
Laravel8 Blade上の記述で"〇日前"と表示する

Blade上の記述で、DBから取得した"Y-m-d H:i:s"フォーマットの日時が何日前かを表示する

# コード

```php
           <p>
              @php
                 $var = \Carbon\Carbon::parse(年月日)->diffInDays(\Carbon\Carbon::now())
              @endphp
              @switch( $var )
                 @case(0)
                     今日
                     @break
                 @case(1)
                     昨日
                     @break
                 @default
                     {{ $var }}日前
              @endswitch
           </p>
```

# 説明
PHPのDateTimeを拡張したパッケージの日付ライブラリ「Carbon」を使います。
```php
$var = \Carbon\Carbon::parse(年月日)->diffInDays(\Carbon\Carbon::now())
```
Carbonライブラリのparse()を使って、年月日の文字列からインスタンスを作成します。
そこからdiffInDays()を使って現在の日付との差を出します。

```php
    @switch( $var )
        @case(0)
            今日
            @break
        @case(1)
            昨日
            @break
        @default
            {{ $var }}日前
    @endswitch
```

あとは、1日前なら「今日」、2日前なら「昨日」、それ以降なら「〇日前」と表記するようにします。

# 最後に
こうした方が良いや、間違っている箇所があれば教えてください。
【初心者向け】SRA toolkitを使ってSRAからFASTQをダウンロード

[備忘録]sratoolを使ってNCBIからメガデータをダウンロードする

# はじめに&今回の概要
こんにちは。
普段、オミクス解析を使って軟体動物の研究をしている大学院生です。
今回はNCBIのSRAからメタデータ (e.g. トランスクリプトーム) をダウンロードする方法を紹介します。
ここは主に自分用のメモで、詳しい扱いはNCBIさんへ。


# 手順
1. sra-toolkitの入手
2. データダウンロード
2. 複数データを一括ダウンロード

# 用語
SRA toolkitとは??
NCBIのSRAデータにアクセスして、必要なデータを扱うことができるツール群のこと。
↓詳しいことはNCBIのサイト参照
https://www.ncbi.nlm.nih.gov/books/NBK569238/

# 1. sra-toolkitの入手
condaやbrewを使ってインストールできる。
minicondaもしくはanacondaをインストール後、下記のコマンドを実行
＊各サイト参照 

```sh:
conda install -c bioconda sra-tools
```

# 2. データダウンロード
```sh:
cd "xxx/yyy/path" #ダウンロード場所をpathしておく
fastq-dump --split-files SRRxxxxx --gzip

```
 --split-files　＃ペアエンドシーケンスの時に必要
--gzip ＃圧縮

# 2. 複数データを一括ダウンロード
以下の　"Download_List.txt"　と　"SRA_download.sh"　を作成し、ターミナルで　"まとめてダウンロード"　を実行する。

```text:Download_List.txt_ダウンロードするSRR番号をまとめてtextに保存
SRR00000
SRR00001
SRR00002
SRR00003
SRR00004
```
```sh:SRA_download.sh
cat Download_List.txt | 
while read SRR_ID
do
	cmd='fastq-dump --split-files ${SRR_ID};
	gzip ${SRR_ID}*fastq';
	eval ${cmd}
done

```

```sh:まとめてダウンロード
cd "xxx/yyy/path" #ダウンロード場所をpathしておく
sh SRA_download.sh

```


# コメント
パソコンのスペックにもよるが、複数データを一括ダウンロードすると、1サンプルあたり30min~(MacBookproを使用)と結構時間かかる。もっといい方法あるかもしれません(汗。

# 引用
https://www.ncbi.nlm.nih.gov/books/NBK569238/
Splunk: CSVファイルをルックアップとして登録し検索条件として使用する

たびたび必要となるのでメモ。

###### 実施環境： Splunk Free 8.2.2

ルックアップは一般的には既存のデータに情報を追加するために使用しますが、本体がリストデータであることから、検索条件としても使用できます。
例えば、以下のような2つの条件を OR でつないで検索を行いたいとします。

* STR が AAA かつ NUM が 1 であるもの
* STR が BBB かつ NUM が 2 であるもの

まずは、以下のような CSV ファイルを準備します。

|STR|NUM|
|:-----|-----:|
|AAA|1|
|BBB|2|

![スクリーンショット 2022-02-06 21.47.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/3c09a33a-3ac8-5e61-3493-43b17cd3e816.png "csv")

用意した CSV ファイルをルックアップテーブルファイルとして登録します。
登録したルックアップテーブルファイルは、以下のように inputlookup コマンドと format コマンドを組み合わせて使用します。
条件によっては、 format コマンドの代わりに return コマンドを使用することも可能です。

```Splunk:Splunk
| makeresults count=10
| streamstats count AS CNT
| eval NUM = CNT % 3
| eval STR = if(CNT % 2 = 1, "AAA", "BBB")
| where
    [
      | inputlookup "testsearch.csv" 
      | format
    ]
```

![スクリーンショット 2022-02-06 21.51.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/ccc17ae0-f0f5-d76d-eef0-7c7fd4575e27.png "search")

ここでは where コマンドの引数として指定しましたが、先頭の search コマンドの引数として利用することも可能ですし、サブサーチ内で加工すれば複雑な条件を処理することもできます。

また、 Splunk のアドオンである Lookup Editor と合わせると、検索条件を簡単に変更できるようになるため便利です。
お出かけ先から簡単家電操作【HomeAssistant導入】

# 家の環境
ホームコントローラーの環境としては、常時起動が望ましいため。
その辺にあるRaspberry Piを活用します。
今回は下記の感じで、Raspberry PiにHomeAssitantという家電操作用OSを入れる手順に触れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510530/9331250b-4eef-52ad-98f7-cb8ea4b2e86e.png)



# Home Assistantって
「Home Assistant」は、オープンソースで提供されるホームコントローラーのツールになります。家電製品の管理や電気などのインフラ系の使用量を記録して、使用料金の算出などもできる様です。公式ホームページにデモムービーがあるのでそれを見た方がイメージはつかみやすいです。

# Home Assistantのインストール
此方のリンクが公式になります。
インストール方法に関しては幾つかあるので、次の章で触れています。

https://www.home-assistant.io/

# Home Assistant のインストール方法
2022/3/20 現在、[公式にサポートされている](https://www.home-assistant.io/installation/) Home Assistant のインストール方法は 4 つあります。

①Home Assistant Operating System
②Home Assistant Container
③Home Assistant Supervised
④Home Assistant Core
ここでは③の方法を選択します。理由としては、、、Raspberry Piとしてはそのまま使いたいので、Raspberry Pi OSとHome Assistantの機能が全部使える方法として選択しました。
因みに、ラズパイの仮想PC上で動かすことになるので、オススメ方法ではないです…公式でも…

①～④の違いはざっくり下記のようです。

① Home AssistantのOSをRaspberry Piにインストールする方法。
② DockerというLinuxのコンテナ技術を使った方法です。
③ Linuxの仮想環境にHome Assistant OSを入れる方法。⇦今回これ！
④ Python パッケージになっているHome Assistantを使う方法



# 公式を参考にインストール
③に関しては下記がインストール方法の手順になります。
https://github.com/home-assistant/supervised-installer


**Step 1:Install the following dependacy's with this command:** 

```
apt-get install \
jq \
wget \
curl \
udisks2 \
libglib2.0-bin \
network-manager \
dbus -y
```

**Step 2: Install Docker-CE with the following command:**
Duckerの公式インストール
```
curl -fsSL get.docker.com | sh
```

**Step 3:Install the OS-Agent:** 
OS-Agentをインストールします。これが無いとSuperviserがタスクをちゃんと処理できないようです。[インストール方法はこちらを参照。](https://github.com/home-assistant/os-agent/tree/main#using-home-assistant-supervised-on-debian)

因みにOS-AgentはProcessaに応じたものをダウンロードする必要があります。
Processaの調べ方は
```
cat /proc/cpuinfo
```
で確認できます。
私はARMv7 Processor rev 4でしたので、os-agent_1.2.2_linux_armv7.debを使いました。


**Step 4:Install the Home Assisistant Supervised Debian Package:** 
```
wget https://github.com/home-assistant/supervised-installer/releases/latest/download/homeassistant-supervised.deb
dpkg -i homeassistant-supervised.deb
```
-----------------------------------------------
無事インストール出来たら、起動状態を確認します。
```
$ docker ps -a
```
NAMESのところにhomeassistantのsupervisorがあればＯＫ！


# Home Assistant へのアクセス
同じネットワーク内のpcからポート 8123 でアクセスできます。
私の環境では、WindowsPCからhttp://192.168.○.○:8123 でHomeAssistantへアクセスできました。

# まとめ
という事で、HomeAssitantのインストールまでを扱いました。
ラズパイ on 仮想環境 on HomeAssistantという少し微妙な構成ですが、、、参考になれば幸いです。
MGSDRVでループすると音がズレる...？

MGSDRV用のMMLを作っていると、ループすると音がズレるのでバグではないか？と思うことがあります。
原因は多くの場合、入力ミスなのですが、入力したMMLが一見完璧に思えるのに、演奏すると期待通り発音されないことがあります。

## 実例

次のMMLを演奏してみましょう。同じフレーズを2回演奏するつもりのMMLです。

```
#opll_mode 1
#tempo 90

9 v15@10 l4 [ g4>d4<b-4.l8 agb-agf+ad4 r1 ]2
```

- MMLは[こちら](https://f.msxplay.com?id=19705adf)で実際に演奏できます。

同じフレーズが2回演奏されるように見えますが、2回目は、最初の`g4>d4<` が4分音符ではなく8分音符で演奏されてしまいます。バグっぽいですよね。

## 原因
MGSDRV 用の MML コンパイラ MGSC には MML の最適化機能がついていているのですが、ループを一切考慮しないで最適化してしまうという問題があります。

最適化とはどういうことが行われるかというと、直前の音長`l`コマンドで指定したのと同じ音長のノートは、音長を省略したMMLとして扱われます。例えば

```
l4 c4d4 l8 e8f8
```

と書いた場合、直前の音長指定コマンドを考慮して

```
l4 cd l8 ef
```

と書いたかのようにコンパイルされます。これがなぜ最適化なのかというと、音長付きの `c4` や `d4` はコンパイル後に2バイトになるのですが、音長なしの `c`や`d` は1バイトになるのです。

この最適化は大変ありがたいことなのですが、ループを使うと、問題が起こります。
例えば次のように書いたMMLが

```
l4 [c4d4 l8 e8f8]2
```

次のように最適化されます。

```
l4 [cd l8 ef]2
```

このMMLのループを展開して考えてみると、

```
l4 cd l8 ef cd l8 ef
```

となります。MMLを書いた側からすると、2回目の `cd` も4分音符で演奏されることが期待なのですが、
8分音符として演奏されてしまうことが分かります。

## 対策
`l`コマンドはループの開始点で必ず指定しましょう。

```
l4 [cd l8 ef]2
```

ではなく

```
[l4 cd l8 ef]2
```

とすれば意図通りに演奏が行われるようになります。
NatureRemo  APIをInsomniaクライアントを介して叩いてみた

# はじめに

スマートハウスにして日々の生活を便利にしたくて、[Nature Remo 3](https://nature.global/nature-remo/) を買った。
赤外線リモコンで操作できる家電については、スマホアプリor WebAPIからコマンドを送れるという。

今回は、[Insomnia](https://insomnia.rest/)というWebAPIを設計/デバッグ/テストするデスクトップツールを介して、
WebAPIを叩いて、テレビをON/OFFさせてみる。

# この記事の前提条件

- Nature Remo 3の初期設定が完了して、テレビ(本記事で触る家電)との連携がすでにできていること
- Insomniaをインストールしていること

# 参照情報

- [公式：Nature Developer Page](https://developer.nature.global/)
- [公式：Nature API仕様(クラウド)](https://swagger.nature.global/)


# 大まかな流れ

1. アクセストークンを発行
2. OAuth2の設定でアクセストークンを指定
3. [Nature API仕様(クラウド)](https://swagger.nature.global/)を元にGET/POSTする

# アクセストークンの発行

- [公式：Nature Developer Page](https://developer.nature.global/)
ここを参考にアクセストークンを発行する。（ログインするだけで簡単)

# OAuth2の設定

[Nature API仕様(クラウド)](https://swagger.nature.global/)の"Authorize"という鍵マークボタンを押すと、
Token URLが記載されていた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15085/c8218ca6-8abd-a6ec-36de-e9c1a6be0d32.png)

このToken URLに、さきほど発行したアクセストークンを送信すれば良いので、
InsomniaのOAuth2タブにて、GRANT TYPEをClient Credentialsにして下記の通り設定すると良かった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15085/7f004ff7-097d-fe4f-ba3a-4660f343d3bd.png)

"https://api.nature.global/1/users/me" にGETリクエストを投げて、200が帰ってくれば認証成功となる。

# 室内の温度を取得してみる

"https://api.nature.global/1/devices" にGETリクエストを投げると、下記が帰ってきた。

```
...
			"hu": {
				"val": 36,
				"created_at": "2022-03-20T01:59:17Z"
			},
			"il": {
				"val": 173,
				"created_at": "2022-03-20T01:59:11Z"
			},
			"mo": {
				"val": 1,
				"created_at": "2022-03-20T01:54:24Z"
			},
			"te": {
				"val": 24,
				"created_at": "2022-03-20T01:43:16Z"
			}
...
```

API仕様の末尾にModels仕様が記載されていて、
Devicesレスポンスから、temperature,humiditym illumination, movementが取得できることがわかった。
API仕様書内のDeviceはNatureRemoのことを指しているようだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15085/470acb89-0408-59ea-beea-39d70c5ba547.png)

# 接続機器のIDを取得する

"https://api.nature.global/1/appliances"  にGETリクエストを投げることで、Nature Remoに登録済みの家電一覧が取得できる。

その中からテレビに対応するApplianceのidを取得する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15085/49788646-543e-3bd7-a1c6-04b92f4bcba0.png)


# 取得したテレビのApplianceのidを介して制御

"https://api.nature.global/1/appliances/<テレビのApplianceのid>/tv" にPOSTリクエストを送信することで、テレビのON/OFFができる。
Quearyとして、buttonに制御したいキーを設定(今回はpower)する必要がある。

この制御できるキーは、"/1/appliances" のレスポンス一覧に含まれている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15085/d6c76266-a321-8012-366b-8242f4148381.png)
ブランチ毎にコミットメッセージのテンプレートを切り替えたい【Git】【prepare-commit-msg】

## はじめに

マスターブランチと、開発用の作業ブランチではコミットの粒度が異なるため、異なるテンプレートを用いたい。フックスクリプトを用いてテンプレートファイルを切り替えてみます。

## 前提

テンプレートファイル、およびその切り替えを行うフックスクリプトが、作業ディレクトリ内に以下のように配置されているものとします。

```
./work_directory
├── .git
│   ├── hooks
│   │   └── prepare-commit-msg
...省略
│
├── .templates
│   ├── develop_template.txt
│   └── master_template.txt
│
...省略
```

# prepare-commit-msg

フックスクリプトの内容は、以下のようになります（実行権が必要です）。

```bash:prepare-commit-msg
#! /bin/bash

# 現在のブランチ名を取得する
branchName=$(git rev-parse --abbrev-ref HEAD)

template_content=""
if [[ "$branchName" == "master" ]]; then
    template_content=$(cat .templates/master_template.txt)
elif [[ "$branchName" == "develop" ]]; then
    template_content=$(cat .templates/develop_template.txt)
fi

mv $1 $1.tmp
echo "$template_content" > $1
```

## おわりに

作業ディレクトリに対して設定をしました。`global` に設定したい場合は、パスを適切に変更してください。
【Ruby】freezeを使用してオブジェクトを凍結させる。

## freezeについて
Rubyにはfreezeというインスタンスメソッドがあるらしい。

``` ruby
array = ["a", "b", "c"].freeze
array = array.map!{|content| content.succ}

p array
```

```
 can't modify frozen Array: ["a", "b", "c"] (FrozenError)
```
このようになる。

このfreezeメソッドを使用すると、オブジェクトを凍結させることができるらしい。
凍結　＝　変更が効かなくなるらしい。

だから、``array = ["a", "b", "c"].freeze``こうすることで配列を凍結することができる。
そのため、次の行の処理``array = array.map!{|content| content.succ}``はエラーとなる。

### 参考
https://docs.ruby-lang.org/ja/latest/method/Object/i/freeze.html
Flutterでパッケージネームをcom.exampleからオリジナルに変更したら起動しなくなった(Android)。

# 解決策
android/app/src/main/kotlin/MainActivityもしくは、
android/app/src/main/Java/MainActivity
を開いて、パッケージネームをオリジナルのものに変更する。
そして、
android/app/src/main/AndroidManifest.xml
のapplicationタグの下のactivityタグのandroid:nameが".MainActivity"じゃなかったら、".MainActivity"に変更する
ffmpegのインストールと使い方

# FFmpegとは

FFmpegは無料の動画変換ツールです。非常に高機能で画質も良いです。
yt-dlpと並んでビデオジョッキーの素材集めには欠かせないツールです。

https://ja.wikipedia.org/wiki/FFmpeg


# Homebrewをインストール
Homebrewとはパッケージマネージャーです。Homebrewを使うことでいろんなアプリケーションを簡単にインストール、アップデートすることができます。

ホームページにアクセスして真ん中あたりのコマンドをコピー
![スクリーンショット 2024-07-09 19.38.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588661/4cfa3b01-0fe1-9d0e-f2a9-29d47231d174.png)

https://brew.sh/ja/

Launchpadを開き「その他」の中から「ターミナル」をクリックして起動します
![original.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588661/508cbdd4-12b9-9120-feab-c9fe52673094.png)

ターミナルを起動したらコピーしたコマンドを貼り付けてEnterを押す
![スクリーンショット 2024-07-09 19.48.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588661/4534b487-54be-81ca-690b-3f8e8a19bbc9.png)

https://www.pc-koubou.jp/magazine/79193

## パスを通す

しばらくするとインストールされて、下の画像のとおりメッセージが表示される
その「Next steps」にあるとおりコマンドを実行する
![スクリーンショット 2024-07-09 20.34.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588661/60f1e621-d26a-7fd6-34a4-ca8957fe010e.png)

`brew help`と入力してヘルプ画面が出てきたら、インストール成功です

# ffmpegをインストール

ターミナルで下記の通り実行します
```zsh
brew install ffmpeg
```

# 使い方 基本編

最も簡単な使い方として、ファイル形式の変換を紹介します。
ターミナルでこのように入力します。
```
ffmpeg -i [入力動画ファイル] [出力ファイル]
```

変換したいファイルを用意します
![スクリーンショット 2024-07-09 22.21.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588661/6650e707-b14f-ab76-c1cd-12ac0a8bf4fc.png)

ターミナルで`ffmpeg -i input.mkv output.mp4`を実行します
![スクリーンショット 2024-07-09 22.15.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588661/9c69e3f4-b5f4-5e1c-d346-42dee42c61b9.png)

しばらくすると変換された動画ファイルができます
![スクリーンショット 2024-07-09 22.21.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588661/5046a03d-e194-700b-b7ac-6c0032ca993d.png)


コーデックをHEVC(H.265)に変換する場合は、このとおりオプションを指定します
`-tag:v`というのはFourCCを指定するオプションです

```
ffmpeg -i [入力動画ファイル] -c:v hevc -tag:v hvc1 [出力ファイル]
```

# 使い方 発展編

非常に高機能です。詳しくは、

https://tech.ckme.co.jp/ffmpeg_basic.shtml

# シェルスクリプトで複数ファイルを一括変換

まずデスクトップにInputフォルダとOutputフォルダを作って
Inputフォルダに変換したいファイルをまとめて
Outputフォルダは空のままにする

![スクリーンショット 2024-07-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588661/b8fdccb6-4d74-230b-35d1-bd6901562ffe.png)

テキストエディットで以下を保存

```zsh:convert.sh
#!/bin/sh

INDIR=~/Desktop/Input/
OUTDIR=~/Desktop/Output/

for FILE in ${INDIR}*
do
  FILENAME=`basename "${FILE}"`
  OUTPATH=$OUTDIR$FILENAME
  ffmpeg -i "${FILE}" -c:v hevc -tag:v hvc1 "${OUTPATH%.*}.mp4"
done
```
![スクリーンショット 2024-07-10 22.11.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588661/26258f50-bc57-942d-92c3-1cac0f02f4b5.png)

ターミナルで下記を実行する

```zsh
sh convert.sh
```

すると、このとおり一気にバッチ変換できる
変換されたファイルはOutputフォルダに出力される

![スクリーンショット 2024-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588661/77b27991-b072-631f-df48-b9b034692ea1.png)

参考リンク

https://qiita.com/mriho/items/b30b3a33e8d2e25e94a8

https://qiita.com/HXYoUGZ/items/1a463a814e0e6d1cda58



# [参考]Homebrewを使わずffmpegをインストール
Homebrewを使わずインストールする必要性はとくにないけど、参考までに

https://cyber-tenchou.com/tips/20200904/
MacのAirPodsの音質で困ってる時はとりあえずcoreaudiodを終了させろ

# TL; DR

```shell
sudo launchctl stop com.apple.audio.coreaudiod && sudo launchctl start com.apple.audio.coreaudiod
```

# AirPods、いきなり音質が悪くなる

ときどき、普通にミュージックアプリで音楽を再生していただけなのに、いきなりコーデックがSCOに変わって、出力が8kHzになります。

[Apple サポートのページ](https://support.apple.com/ja-jp/HT208896)を見てみると、どうやらマイク使用モードになっていて、マイクを使うアプリケーションを起動しているために起こる現象のようです。

マイク？AirPodsのマイクなんて使ったことがあるのはせいぜい通話する時くらいでしょう。友達がいないので、そんな機会滅多にありませんが。

# SCOに変わると、とてつもなく迷惑

8kHzの音質でできることってなんでしょう？通話くらいですね。[^1]

いつも再起動をしていたのですが、再起動の手間（ところで、macOS Big Surにアップデートしてから起動時間が2倍くらいに増えたのですが、なんででしょうかね？）やその後のアプリの起動の手間などを考えるととても大変です。

# coreaudiodを終了させてみた

アクティビティモニタをぼーっと眺めて怪しいプロセスを観察していたのですが、[^2]`coreaudiod`というプロセスが少し気になったので普通に終了させてみました。

すると、ミュージックの音声が停止され、再度再生してみるとコーデックがAACに戻ってました！解決！

# コマンドで落とせるよ

いちいちアクティビティモニタを開くのは面倒なので、コマンドで`killall coreaudiod`してやろうかと考えていました。

ですが、記事を書こうと思ってタグ指定するときにcoreaudiodタグがついている記事が1件あったので、見ると[coreaudiodがメモリを大量に占有しているときの対処法](https://qiita.com/shge/items/7d022ed6a8d900ceb966)という記事がありました。

```shell
sudo launchctl stop com.apple.audio.coreaudiod && sudo launchctl start com.apple.audio.coreaudiod
```

killallよりこちらの方が再起動に向いているらしいです。

昔、`killall Finder`をやったことがあるのでkillallは再起動するものだと勝手に思っていたのですが、どうやら違うみたいです。ただの勉強不足です。

# 追記: DAWは落としておけ

Studio Oneを開きっぱなしでこのコマンドを実行したらその後左耳しか聞こえなくなりました。

この症状がこのコマンドを実行すると必ずこうなるのかどうなのかはまだ未検証ですが、プロセスをいきなり停止してるのでDAWに良いかと言われると良くなさそうなので、DAW、音声編集アプリケーションを起動している時は一応落としておきましょう。

[^1]: DTMをしたりするのは特に向いていない、と私は思ってます。特にPiapro Studioはフレームレートが変わると44.1kHz→8.0kHzの場合音声が引き伸ばされてピッチが低くなったり、逆に44.1kHz→48kHzになるとピッチが高くなります。とても迷惑です。
[^2]: アクティビティモニタで見ていてもマイクを使用しているプロセスなんてわかりませんよ
C# とは？

C#について、プログラム初心者の僕が感じたことをつらつらと書いていきます。
良かったら読んでみてください。
コメントやアドバイスなどは受け付けておりますが、過激な発言などはお控えください。（僕がしんどいです)

# そもそもC#とは
C言語→C++の派生系だと考えています。
C言語がオブジェクト指向に対応していないのに対して、C++はC言語の良さを取り入れ改善されたオブジェクト指向型言語、C#はC++よりも拡張性を高くしたオブジェクト指向型言語という位置づけのようです(かなりざっくりした説明ですね)。
C#自体様々なプラットフォームで動作が可能です。
.Net 6.0(C# 10.0)ではそれはもう本当に素晴らしい。
MAUIというiOS、macOS、AndroidOS、Windowsなどに対応したアプリケーションの開発が可能だとか…
.Net 6.0だからこそできることでしょうね。
.Net 5.0の時代はXamarinと呼ばれる.Net Frameworkに属するフレームワークを使用しないと開発不可能だったのが、.Net 6.0が導入されたことによって敷居が低くなった感じです。

# Xamarinって？
AndroidOSではJavaやKotolin、iOSではObjective-CやSwiftを使用して開発を行う必要がありました。
XamarinはC#で統一してソースコードを書けるという画期的な代物です。
UIなどデザインの観点ではOSによって書き方を変えないといけない(複数のXAMLファイルを書く必要がある)のが完全な統一化となっていないのが残念です。
が、将来的には様々な機能が増えて(.Net 6.0でそうなる予定だったのが延期に…)で.Net 7.0ではこれまでと比較して容易にアプリ開発が可能になるとのことです。

# .Net〜〜〜って？
この辺ごちゃごちゃしています。
.Net Standard、.Net Framework、.Net Core…
まずは.Net Standardからでしょうか？
## .Net Standardの位置付け
この.Net StandardはBCL(Base Class Library)と呼ばれるものです。
.Net Standardとは、根幹になる部分と考えるのがいいかもしれません。
土台に.Net Standardがドンッと構えているのを想像してみてください。

## .Net Framework
この.Net Frameworkは、Windows向けのアプリを動作させるためのランタイム実行環境、すなわちWindowsには必要な機能となります。
アプリケーションフレームワークというものでもあり、開発時にはWindowsの機能の実装を簡単にしてくれるみたいです。
.Net Frameworkはバージョン4.8を最後にサポートが切れるとのことです。
下記に記載した.Net Coreに統合されるのかはたまた…

## .Net Core
.Net Frameworkよりも幅広くプラットフォームを対象としているソフトウェアフレームワーク。
Linux系OSやmacOS、そして当然Windowsも対象です。
現在の.Net Coreのバージョンは「.Net Core 3.1」となっております。

## 実は・・・
Xamarinも.Netなんちゃらに含まれる構成員の一人です。←表現w
これが冒頭でお話ししたiOSやAndroidOSのアプリ開発が可能になるという機能なんですね〜
技術的には.Net FrameworkとC#なのですが、Monoというライブラリを使用した開発となります。
.Net6.0で標準で付いてくるMAUIというものはXamarinと似たようなものですが、別物のようです。(？)
Xamarinとは違って、コントロールの配置が直感でできない(デザイナー機能がない)ようで、XAMLコードを書く必要があるため、XAMLの知識なども必要だなと感じました。
この辺は別の記事で細かくご紹介しますね。

## 最終的には…
.Net Standardを土台として、その土台の上に上記の.Net Framework、.Net Core、Xamarinが分かれて乗っかっている感じです。
分かれて乗っかっているということは、土台との互換性はあっても、横の繋がりはないということになります。
そりゃBCLなんだから互換性ないとだめよね。
とにもかくにも最終的には.Netは一つになるようです。
.Net○○というややこしい関係はなくなり、様々なプラットフォームの開発がさらに容易になるということなのかなと考えていますが…
プログラム初心者のためよくわかりませ〜ん笑

# まとめ
初心者だからこその観点でざっくりした説明になってしまいました。
ちなみにUnityという技術もあり、ゲームプログラミングなどでは重宝されているようです。

今後記事の改訂、内容の増強などもしていきますよ〜
ちなみに執筆時点(2022/3/20)でこの程度なので有識者の方々からすればその程度じゃC#は語れねぇよ…とか言われそう笑
インプットばかりでアウトプットができてないので、とりあえず簡潔に、自分なりにまとめてみました。
全然理解していないことの方が多いので、今の段階ではこんな感じに理解しています。間違っていたらご指摘いただけると幸いです。(言葉は選んでちょ)
ここまで読んでくださりありがとうございます。
swiper を vueで使うときの現在のスライド番号の取得

# はじめに
electronとvueを使って、デスクトップアプリを作る際、スライドショーが必要になったので、
swiperを入れて作ってみたところ、現在いるスライド番号を取得したくて調べていたら、
どの方法もうまくいかず、今回のこの方法でうまくいったので備忘録的に書きました。
# 環境
- vue 3.0.0
- swiper 6.8.4
- electron 13.0.0
# 取得方法
```vue:hoge.vue
<template>
<div>
  <swiper
    v-on:swiper="onSwiper"
    v-on:slideChange="onSlideChange">
    <swiper-slide>slide1</swiper-slide>
    <swiper-slide>slide2</swiper-slide>
  </swiper>
</div>
</template>

<script>
import {Swiper,SwiperSlide} from "swiper/vue"
import "swiper/swiper-bundle.min.css"
export default{
  name:'hoge',
  components:{Swiper,SwiperSlide},
  data(){
    return{
      swiper:null
    }
  }
  methods:{
    onSwiper(_swiper){
      this.swiper = _swiper
    }
    onSlideChange(){
      console.log(this.swiper.activeIndex)
    }
  }
}
</script>
```
Swiperの初期設定を知らせる `v-on:swiper` で、`onSwiper` が呼び出され、Swiperの情報が `_swiper` 変数に入るので、それを `this.swiper` に移して、vueの中で参照できるようにする。
スライドの遷移を知らせる `v-on:slideChange` で、`onSlideChange`が呼び出されるので、`this.swiper.activeIndex` と記述すれば、現在のスライド番号を取得できる。
# うまくいかなかった方法
各ライブラリのバージョンによるものや、ライブラリがそもそも違うかもしれませんが、
`<swiper>` タグに `ref='mySwiper'` という感じで `ref` を追加して、`this.$refs.mySwiper.activeIndex` とか、`this.$refs.mySwiper.swiper.activeIndex` とか、`this.$refs.mySwiper.$swiper.activeIndex` など色々と試してみたんですが、どれも `undefined` となってしまいました。
# 参考サイト
- [Swiper Vue.js Components](https://swiperjs.com/vue)
【Ruby】nestingについて

nestingというものがあるらしい。
いつどんなときに使うのかわからない。

``` ruby
module Gorira
  module Saru
    module Tanuki
      p Module.nesting
    end
  end
end
```
```
[Gorira::Saru::Tanuki, Gorira::Saru, Gorira]
```
このnestingを使用すると、クラス・モジュールのネスト情報を配列にして返してくれるらしい。

なにで使うのかはわからない。笑

### 参考
https://docs.ruby-lang.org/ja/latest/method/Module/s/nesting.html
技育祭2022年春で学んだこと

## はじめに
2022年3月17日(木)～2022年3月19日(土）にかけての技育祭2022年春が終了しました。サポーターズさんお疲れ様です。そして、ありがとうございました。3日間の学びが非常に多く楽しかったので、この記事では学んだこと3つと、まとめを書きます。

## 学んだこと
### 1.発信の効果
こちらから製作物や情報をオープンにすることで、フィードバックが得られる。そこから相互的なやり取りが始まるかもわからないし、とにかくTwitteerやQiita、Githubに記録を残しておくと、人とつながりが生まれる。周りにエンジニアがいない僕の学びを一気に加速する。また、この記録はいつか、就職やフリーランスで働くときに履歴となる。そして、今回登壇したエンジニアの方々が「就職のために書いたプログラムと、以前から好きで勝手に書いてきたコードは一発で分かる」と述べていた。

### 2.まず動くものを作る
落合陽一さんが、ブサイクでもいいからとにかく動くものを作れと仰っていた。誇れるモノや自分のオリジナル作品にこだわる必要はない。まず動けばいい。その後、うまく動かなかった理由を考えて改善することで学ぶ。
### 3.気になったら手を付けてみる
最後のクロージングセッションで、ちょまどさんと同じブレイクアウトルームに振り分けられ、これはチャンス！！と思い、凄い個人的な質問をした（笑）。簡単に言うと、「色んな技術を試したいが、どのように優先順位をつけるべきか」という質問をさせて頂いた。その際に、「優先順位を考えて効率を求めすぎると、義務感出る。また、これは一般に広まっていて、これはどの企業が使っていて、というように余計なことを気にし始めるようになる。時間は有限だけど、まず触ってみないと分からないから、色々やってみる。何をするかは日々の気分で選んでもいいし、Hello world!まで書いて色んな言語に触れるのも全然良いと思う。」と答えていただけた。納得。始めるからにはある程度まで、と考えていたけど、ちょっとでも良いから、触りたいものに優先順位をつけずに色々試そう。

## まとめ
松尾研究室のGCI 2022 Summerが気になってどうしようもないので募集した。
発信することに対する障壁みたいなものを取っ払って、twitter,Qiita,Githubを稼動した。
CTFのイベントに参加(興味津々)
まとめじゃないかも、、、
「GCP Professional Data Engineer」 取得に向けた学習まとめ

# はじめに
先日、GCP Professional Data Engineerの認定試験を受験し、無事合格しました。自分が利用した学習コンテンツとその概要について、記載をしています。

# 受験目的
GCPを用いた分析基盤構築案件に携わることになり、GCPのデータ関連サービスについて、業務上でのキャッチアップと並行して、体系的な知識の習得を行いたいと思い、受験することに決めました。

# 前提
- クラウドサービスに関しては、AWS側にて「AWS 認定ソリューションアーキテクト – アソシエイト」の資格は取得、加えて業務での利用もあり、基本は習得済。
- データ関連サービスに関しては、AWS側にて「AWS 認定データアナリティクス 専門知識」の資格は取得、加えて関連書籍も数冊読んでおり、一般的な知識は習得済。
- GCPに関しては、業務上での利用は今回が初めて。

# 利用した学習コンテンツ
- [Google Cloudではじめる実践データエンジニアリング入門\[業務で使えるデータ基盤構築\]](https://www.amazon.co.jp/dp/429711948X)
    - Google Cloudのアーキテクトの方々が書いた本です。
    - 最近出版されたこともあり、内容が現状と乖離しているようなことがないので、安心して読むことができます。
    - 平易な文章と豊富な図解、実画面の画像などで構成されているので、最初にGCPのデータ関連サービスの大枠を把握するのにぴったりかと思います。
- [模擬試験](https://docs.google.com/forms/d/e/1FAIpQLSd4j4bcgbYenBRFIL6Kb0cvXp13qCQ-z6JzowgDxRaPITn56g/viewform)
    - GCPの認定試験は無料の模試があります。
    - 学習前、学習後に2回受講しました。
- coursera
    - [Google Cloud 認定の準備: クラウドデータエンジニア プロフェッショナル認定証](https://ja.coursera.org/professional-certificates/gcp-data-engineering-jp)
        - Google公式のコースです。
        - まさにこの資格の取得に向けた講義なので、本資格試験を受験する際は受講必須かと思います。
        - 最後に模試もあります。
    - [Google Cloud Fundamentals: Core Infrastructure 日本語版](https://ja.coursera.org/learn/gcp-fundamentals-jp)
        - こちらもGoogle公式のコースです。
        - 上記がカバーしていないストレージサービスが一部あるので、本コースのストレージの章を見てカバーする必要があります。


# 受験を終えての感想
BigQuery、Cloud Storage、Composerなど、現PJにおいて利用中の技術スタックの基本知識・プラクティスなどについては、すでに業務で役に立っている部分も多くあり、資格取得に取り組んで良かったなと感じています。
また一方で、Pub/SubやDataflowを用いたストリーミング処理や各種機械学習支援サービスなど、現在の業務では関わらないものの、データ活用という意味では重要な役割を担うサービスについても学べたので、既存案件での活用提案などに繋げていきたいと思います。
【クエリビルダ】保存したクエリをインポートしてみる

**[Sharperlight](https://sharperlight.jp/)クエリビルダ**には、クエリの保存機能があるという記事を以前に投稿しました。
ここではどのようにインポートするのかを紹介します。
**クエリビルダ**の[フィルター]領域の右クリックメニューから、**クエリーのインポート**を選択します。すると**ファイル**、**パブリッシャー**、**クリップボードから**の3つのオプションが表示されます。
![2022-mm-dd Figure 01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/eca383b6-50fa-b7b4-5fde-44011cf02bde.png)
**ファイル**オプションは、クエリがファイルとして保存されている場合、**クリップボードから**オプションは、クエリがクリップボードに保存されている場合です。**パブリッシャー**オプションは、パブリッシャーで既に作成されているレポート一覧から使用されているクエリをインポートするオプションです。

このようにして新しいクエリを作成する場合は、既存のものをテンプレートとして使用することができ、効率よくクエリを作成することができます。

:postbox:[Sharperlight](https://sharperlight.jp/)
[Unity] Unity Editor上からVisual Studioを開いても、「Solution1」と表示されてしまう

ハマったので対処法をメモ

* windows 10
* Unity 2021.1.24f1
* Visual Studio Community 16.11.11
    * Visual Studio Tools for Unity 4.11.4.0

# 症状

Unity Editor の Project から csファイルを開くと、Visual Studioは起動するがソリューション名が「Solution1」となり、そのままだとUnityにアタッチができない。

# 調査

* UnityのEdit > Preference > External Tools > External Script Editor で「Visual Studio」を選択している。
    * バージョンは「16.11.11」表示されていない。
* Window > Package Manager を表示して、一覧に「Visual Studio Editor」がない。
    * 「Visual Studio Code Editor」とは異なる。

# 原因

何らかの原因で「Visual Studio Editor」がパッケージから抜けてしまっている。

# 対処方法

1. 同じバージョンのUnityで、新規のプロジェクトを作成する。
1. 作成した新規のプロジェクトを開いて、Visual Studioを開ける、アタッチできることを確認する。
1. 新規のプロジェクトを閉じる。
1. 新規のプロジェクト内の`Packages/packages-lock.json`を開く。
1. `"com.unity.ide.visualstudio": {`から`},`までをコピーする。
1. 症状が発生しているプロジェクトの`packages-lock.json`にコピーした内容を追加する。
1. 症状が発生しているプロジェクトを開いて、Package Managerを開く。
1. 「Visual Studio Editor」が表示されるようになったので、選択して右下「install」をクリックしてインストールする。
1. Edit > Preference > External Tools > External Script Editor で「Visual Studio」を選択する。

これで解決した。
VSCodeのEmmetが使えない (Webアプリ開発初心者向け)

## Emmetとは
VSCodeでHTMLを書くときに、コーディングをショートカットしてくれる便利な機能だそうです。

VSCodeには標準装備されているようなので、拡張機能からインストールをする必要がありません。

### Emmetの構文
参考: https://docs.emmet.io/cheat-sheet/

これを初めて使用するときは使えませんでした。
その時の簡単な解決方法は以下となりました。
(他の方法もあるそうですが)

## Emmetが使えない時の対処法
1. 左下の設定アイコンから「設定」を選択。
![settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1597214/21a27107-0e4c-7a1c-e989-5d407486d39f.png)

1. 「Trigger Expansion On Tab」を検索して有効にする。
![search.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1597214/53bebad2-d3ee-92ef-adbc-a564491bca60.png)


1. VSCodeを再起動しましょう。

###

以上で使用できるようになりました。

(以下は 「!」 + Tab と打った時の例)
![ex1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1597214/afea5fbc-eaf1-7d28-698b-384cb696e96e.png)
Python ループ処理させたい関数が複数あるときのテクニック

以下のように第一引数にループさせたい関数を、第二引数に前処理したい関数を指定するwrapper関数を作成して、マルチスレッドでtargetを指定する前にwrapして使ったりしています。


# 無限ループさせる例

```python
import time

def wrap_loop_func(main_func: any, preprocessing_func: any = None):
    """関数をループさせる関数を返す"""
    def loop_func():
        if preprocessing_func:
            preprocessing_func()
        while True:
            main_func()
    return loop_func

def task():
    print('task')
    time.sleep(1)

def preprocessing():
    print('pre-processing has done.')
    

# loop_task = wrap_loop_func(task)
loop_task = wrap_loop_func(task, preprocessing)
loop_task()
```

```:実行結果
pre-processing has done.
task
task
task
.
..
...
```

# 終了条件と後処理をさせる例

上の処理だと味気ないので、終了条件と後処理も追加

```python
import time

begin = time.time()

def wrap_loop_thread_task(main_func: any, exit_condition_func: any, preprocessing_func: any = None, postprocessing_func: any = None):
    """関数をループさせる関数を返す"""
    def loop_func():
        if preprocessing_func:
            preprocessing_func()
        while exit_condition_func():
            main_func()
        if postprocessing_func:
            postprocessing_func()
    return loop_func

def preprocessing():
    print('pre-processing has done.')

def postporcessing():
    print('post-processing has done.')

def exit_condition():
    """経過時間が３秒未満ならTrue"""
    return True if time.time() - begin < 3 else False

def task():
    print('task')
    time.sleep(1)

# loop_func = wrap_loop_thread_task(task,exit_condition)
loop_func = wrap_loop_thread_task(task,exit_condition,preprocessing,postporcessing)
loop_func()
```

```:実行結果
pre-processing has done.
task
task
task
post-processing has done.
```

# 終了条件が必要とは限らないので

第２引数がNoneの場合、`lambda : True`とする。（常にTrueを返す関数)

```python
def wrap_loop_thread_task(main_func: any, exit_condition_func: any = None, preprocessing_func: any = None, postprocessing_func: any = None):
    """関数をループさせる関数を返す"""
    def loop_func():
        if preprocessing_func:
            preprocessing_func()
        if exit_condition_func:
            should_continue = exit_condition_func
        else:
            should_continue = lambda : True
        while should_continue():
            main_func()
        if postprocessing_func:
            postprocessing_func()
    return loop_func
```
Docker Desktop for MacでCPU消費が異様に高い時の対処

CPU使用率が常に100％超えでファンがブンブン回っていたのを
解消できたのでメモ

## やったこと
後述2つの記事参考に
1. ボリューム削除してマウントし直し
2. Swap：3G→512Mにリソースを変更
3. File sharingを最低限のものへ修正
4. Quit Dokcer Desktopで一度終了させてから再起動

でCPUほぼ0％になった。

https://www.deep-rain.com/mac/docker/1423

https://www.scriptlife.jp/contents/programming/2020/07/08/docker-desktop-for-mac-cpu/

## ポイント
- 4つ目の「Quit Dokcer Desktop」が重要。
- 「Restart」ではなく「Quit」してから再起動しないと効果がないようなので注意。
- 逆にいうと1-3はどれが効果あったのか、なかったのか、は謎。

## 【20220321追記】
3.のFile sharingが問題だった模様。
やはりMacのDokcer DesktopはDiskマウントに問題があり、
CPU使用率が高い場合はマウントするディレクトリを最低限のものにすることを意識したほういがよさそう。
「Restart」ではなく「Quit」が必要なのも、Diskマウントの反映は再起動が必要なのかも。

## ひとこと
単純に作業軽くなるのと、
PCのファンがブンブン回るのBGMにすると、
脳のCPU効率も悪くなる気がして精神衛生上よろしくないですしね、、
OpenSSLの最近の脆弱性

# 1.1.1n [15 Mar 2022]

細工された証明書を処理すると問題を起こすようです。通常のhttpsなWEBサーバは証明書は送るだけなので、影響ありません。影響があるのはcurlなどでhttpsなサーバにデータを取りにいった時に不正な証明書があると問題が起きます。SMTP over TLSの通信も不正な証明書を送りつけられる可能性があります。ただこれらは、接続先が悪意を持つか、乗っ取られるか、DNSを偽造して、別のサーバに接続させるなどの方法がないと、現実にはならないと思います。VPNサーバー(ikev2)がクライアント証明書で認証している場合も不正な証明書が送られる可能性があるので該当します。こちらは任意に起きえるので重要かもしれません。

# 1.1.1m [14 Dec 2021]

MIPSでの脆弱性のようです。BN_mod_exp()が正しい値を返さない事があったようです。この処理はr=a^p % mのBigNumberの処理になります。BigNumberは32Bitを越える数値で、いくつかの32Bitをつなげて処理します。このため、32Bitを越えたときは次の32Bitに渡す必要があります。これがMIPSでは上手くいかないケースがあったようです。

8BitのCPUの頃からアセンブラで演算した結果がオーバーフローするとキャリーフラグがたちます。たとえば8Bitで0x80 + 0x80すると返り値は0ですが、キャリーフラグが立っています。これは32Bitでも同じですし、ほとんどのCPUで同じように動作すると思います。C言語ではキャリーフラグを直接処理する機能はないですが、コンパイルされたバイナリに含まれるのかと考えられます。

OpenSSLにはキーの発行、証明書の確認、暗号化などいろいろな処理がありますが、この処理がどこで使われるのかはいまいちよく分かりません。

具体的にどのようになっているのか知りたいところではありますが、探せてません。他に影響ないように直した方法も知りたいです。

この問題による攻撃は出来ないので、脆弱性というよりバグな気がします。
【Notion】トグルヘディング（見出しのトグル化）のショートカットキー

# はじめに
[Notion](https://www.notion.so/ "公式")を愛用しているの[@kat_log](https://twitter.com/kat__log "Twitter")と申します。

最近Notionに「Toggle heading」という、トグルリストとヘッダーが組み合わさった機能が追加されたのですが、ショートカットキーを調べたところ日本語記事が見当たらなかったため共有です！

![computer01_boy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/e76cd760-a7ea-8344-525e-3cff1b8dda70.png)

# 結論

`>`+`空白`+`#`でできます！
（`>`+`空白`+`##`でヘッダー2タイプ）
（`>`+`空白`+`###`でヘッダー3タイプ）


# おわりに
お読みいただきありがとうございました！
良いNotionライフを😄

# 参考
https://www.reddit.com/r/Notion/comments/sbmlkl/shortcut_for_toggle_headings/
[rails] graphql-rubyでどこが遅いのかわからない場合

# 問題

graphqlを使ってると、model側で遅いのか？graphqlのタイプ側で遅いのか？更に階層が深いと検討がつきにくい。

# 解決


https://graphql-ruby.org/queries/tracing

公式ドキュメントには丁寧な説明がないけど、

https://thecodest.co/blog/graphql-ruby-what-about-performance

ここのブログでいい感じにログに出せるようなコードがあった。

`platform_trace`で実行時間を計算して`observe`に渡してるんで、そこでログに吐くなりできる。

```rb:app_schema.rb
class MyCustomTracer < GraphQL::Tracing::PlatformTracing
  self.platform_keys = {
    "lex" => "graphql.lex",
    "parse" => "graphql.parse",
    "validate" => "graphql.validate",
    "analyze_multiplex" => "graphql.analyze_multiplex",
    "analyze_query" => "graphql.analyze_query",
    "execute_multiplex" => "graphql.execute_multiplex",
    "execute_query" => "graphql.execute_query",
    "execute_query_lazy" => "ygraphql.execute_query_lazy",
    "execute_field" => "graphql.execute_field",
    "execute_field_lazy" => "ygraphql.execute_field_lazy",
    "authorized" => "graphql.authorized",
    "authorized_lazy" => "graphql.authorized_lazy",
    "resolve_type" => "graphql.resolve_type",
    "resolve_type_lazy" => "graphql.resolve_type_lazy",
  }

  def platform_trace(platform_key, key, _data, &block)
    start = ::Process.clock_gettime ::Process::CLOCK_MONOTONIC
    result = block.call
    duration = ::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - start
    observe(platform_key, key, duration)
    result
  end

  def platform_field_key(type, field)
    "graphql.#{type.graphql_name}.#{field.graphql_name}"
  end

  def platform_authorized_key(type)
    "graphql.authorized.#{type.graphql_name}"
  end

  def platform_resolve_type_key(type)
    "graphql.resolve_type.#{type.graphql_name}"
  end

  def observe(platform_key, key, duration)
    return if key == "authorized"

    Rails
      .logger.debug "platform_key: #{platform_key}, key: #{key}, duration: #{(duration * 1000).round(5)} ms"
  end
end

tracer(MyCustomTracer.new)
```

元々のコードは

```rb
def observe(platform_key, key, duration)
  return if key == 'authorized'

  puts "platform_key: #{platform_key}, key: #{key}, duration: #{(duration * 1000).round(5)} ms".yellow
end
```

となっていて`.yellow`は無いとエラーになったが、たぶんこれは[https://github.com/sickill/rainbow](1)を入れているんだと思う。


```rb
# https://github.com/sickill/rainbow#refinement
require 'rainbow/refinement'
using Rainbow
puts "Hi!".green
```

[1]: https://github.com/sickill/rainbow
Rufusで古いバージョンのWindowsがダウンロードできる件が気になった

# 古いWindowsが必要になるかもしれない・・・？

私が今手元にあるWindowsのプロダクトキーといえば、Windows 7時代から使っているもの、初めて買ったラップトップのWindows Vistaのもの、今使っているWindows 10のもの、そしてなぜか実家から持ってきているWindows 95のもの。

Windows 7以来、マイクロソフトはプロダクトキーを持っていれば、OSへのアップグレードに費用が発生していないわけですが、古いシステムを使う関係で旧Windowsがどうしても必要になる・・・という事態を想定しておこうと思って色々探っているわけです。

職場では、Windows XP、Windows 7、Windows 10のDVDメディアを作っていたので、それが残っているし、プロダクトキーも残っているので、いざというときはいいのですが、自宅で仮想環境で使う場合はどうなるのかなと気になったわけです。


# ダウンロードできるソフトウェアがある

この界隈では[Rufus（ルーファス）](https://rufus.ie/)というフリーウェアが有名、というか過去のWindowsをダウンロードするときの定番ソフトウェアらしいです。
ひとまずポータブル版をダウンロードして、Windows 7のISOをダウンロードしたところ、だしかにできる。
ダウンロードする過程で、「Downloading using a browser」にチェックを入れれば、ブラウザ経由でダウンロードできるので、どこからダウンロードしているのかも明らかになる。

![qiita_rufus01_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131218/e41d3ac3-4eee-27a9-7592-2faaf58f269a.png)

怪しいところからダウンロードしているんじゃない？と思ったんですが、これがマイクロソフト本家からダウンロードされているのです。

![qiita_rufus01_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131218/3d2eacfd-65cc-7aea-0528-7a117251beec.png)

そこに辿り着く前に、どういう経路でダウンロードしているんだというのが気になったので、ソースコードを解析したのですが、普段見慣れないソースコードでよくわからんので、わからんなりに色々調べた結果をまとめておこうと思いました。


# 古いWindowsがダウンロードできるわけ

いくらなんでもWindows 95とかはダウンロードできません。
2022年3月の時点ではWindows 7以降のバージョンがダウンロードできるみたいです。

Rufusはオープンソースなので、Githubでソースコードが公開されています。

[pbatard / rufus](https://github.com/pbatard/rufus)

が、読んでもよくわからん。

「where does rufus download iso from」とGoogleにたずねてみたところ、以下のような記事がヒットしました。

[How To Use Rufus To Download Windows 10 ISO](https://www.intowindows.com/how-to-use-rufus-to-download-windows-10-iso/#:~:text=Starting%20with%20Rufus%203.5%2C%20Rufus,and%20Windows%208.1%20ISO%20images.)

内容によるとFidoというプログラムを使っているそうで、これもGithubで公開されています。

[pbatard / Fido](https://github.com/pbatard/Fido)

っていうか作者一緒ですね。

これの[Fido.ps1](https://github.com/pbatard/Fido/blob/master/Fido.ps1)というPowerShellスクリプトを見てみると、WindowsのISOのダウンロードURLが書いてあったりします。
ダウンロードできるWindowsのバージョンは、マイクロソフトの[Software Download](https://www.microsoft.com/en-us/software-download/)というページをもとに判断されている？みたいです。
このページを見てみるとWindows 8.1は2022年3月20日の時点でダウンロードできるみたいです。
なので、ヘッドレスブラウザみたいな要領で、ISOをダウンロードしているみたいです。
ただWindows 7だけはダウンロードURLが出てこないので、スクリプトの中にハードコードしているみたいです。
Windows 7のダウンロードURLは生きているんですね。


# そもそもWindows 7より前ってISO配布されていたっけ？

Windows Vistaのプロダクトキーを持っているのはいいけど、そもそもISOなんて存在していたかなと言うのがあります。
一応メーカー製PCだったので、リカバリー用のDVDを作っていたのでそれは残っているのですが、これ使えるのかな？

気が向いたら試してみます。（できなさそう）

余談ですが、Linuxは古いバージョンのOSがダウンロードできたりします。
https://vault.centos.org/
https://old-releases.ubuntu.com/releases/
SOLANAを使った開発で、チェックした記事

# 開発系

1. https://github.com/solana-labs/solana/issues/22618
1. https://blog.tanebox.com/archives/1597/#Attempt_to_load_a_program_that_does_not_exist%E3%82%A8%E3%83%A9%E3%83%BC
1. https://github.com/solana-labs/wallet-adapter/blob/master/packages/ui/react-ui/src/WalletConnectButton.tsx

# 基礎知識系

1. https://hedge.guide/cryptocurrency/glossary/onchain#:~:text=%E3%82%AA%E3%83%B3%E3%83%81%E3%82%A7%E3%83%BC%E3%83%B3%E3%81%A8%E3%81%AF%E3%80%81%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF,%E3%83%81%E3%82%A7%E3%83%BC%E3%83%B3%E3%81%AE%E5%8F%96%E5%BC%95%E3%81%A8%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82
1. https://blog.liquid.com/ja/glossary/over-the-counter/
【Docker】複数のMySQLデータベースに一般ユーザーで接続する方法


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

## 複数のMySQLデータベースに一般ユーザーで接続する方法

```:ターミナル
$ mkdir docker-entrypoint-initdb.d && cd $_

$ code 00_grant.sql
```

```00_grant.sql
GRANT ALL ON `myapp_test`.* TO user@'%';
```

```docker-compose.yml
  db:
    image: mysql:5.7
    environment:
      MYSQL_USER: 'webapp'
      MYSQL_PASSWORD: 'webapp_pass'
      MYSQL_DATABASE: 'rails_app_development'
      MYSQL_ROOT_PASSWORD: 'pass'
    volumes:
      - ./docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
```
```:ターミナル
$ docker-compose down

$ docker-compose up
```
Unityでの開発における git worktree のすすめ

Unityでマルチプラットフォーム開発を行なっているとき、
環境を別PFに変更する際はSwitch Platformを実行します。
しかしプロジェクトが大きくなっていけばいくほど、このSwitch　Platformにかかる時間は増えていきます。

これに対する解決のアプローチとして、PFごとにリポジトリを作る方法があります。
``` bash
$ git clone https://hoge.git ios
$ git clone https://hoge.git android
```
こうすることにより、PF切り替えをしなくてすみます。
しかしその一方で、リポジトリそのものを複数用意することで次のような欠点があります。
* git fetch等をそれぞれで行わなければならない
* リモートリポジトリを介さなければローカルリポジトリ間でやりとりできない

git worktreeを使用すると、このような欠点を避けつつ複数のプロジェクトを管理することができます

# worktreeによるプロジェクト構築

github等にリポジトリ作成後、以下のようにしてプロジェクトを作成します。
空の状態から始めるのがポイントです。
``` bash
$ mkdir hoge; cd hoge # リポジトリ用ディレクトリ作成
$ git init # 大元は空の状態にしたいので、cloneではなくinitから作る
$ git remote add origin https://hoge.git # 作成したリモートリポジトリのURLを設定
$ git fetch
$ git worktree add -b ios ./ios origin/master # hoge直下にiosというディレクトリを作成し、iosというブランチ名でmasterをチェックアウト
$ git worktree add -b android ./android origin/master
```

このようにすることで、ios、androidのPFごとにプロジェクトを作成することができました。
worktreeの利点としてリポジトリとしては単一なので、git fetch一回で済みますし、
iosでの変更をcherry-pickでandroidに取り込んだり、git stashで送ることもできます。

また、単一PFだったとしても、開発用・ビルド用と複数プロジェクト使用したい場合もあったりするので、
その際にも活躍すると思います。
MacにNode.jsをインストールする方法(2022/03)

タイトルの部分、(2022/03)とか書くだけで少し悲しくなる。。。
「ああ、年取ったなって」

まあ今回はNode.jsのインストールです！
Mac初期化したのでね。。。
最初からです。
今回は早く終わりそうでよかった。

## Node.jsとは？
Node.jsが何かわからずに、必要だとわかったからインストールする人もいると思うので(AtCoder cliのために必要など)、駆る紹介します。
と思ったのですが、さすがはインターネットさん、めっさわかりやすい説明をしている記事を見つけたので載せておきます。

https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb


## Node.jsのダウンロード
https://nodejs.org/ja/

[こちら](https://nodejs.org/ja/)のサイトからLST版(推奨版)をダウンロードして実行します。
最新版って書いてある奇数番号の方は約7ヶ月でどれもサポート終わるのでLST版の方がいいです。

全肯定していけばインストールできます。迷う部分は特に無いと思います。

![スクリーンショット 2022-03-20 2.12.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512282/7450ea7f-fd08-c41d-9d83-5d0f4e3bf36b.png)

``node -v``や``npm -v``と打ってバージョンが確認できたら正常にインストールできています。
Atcoder cli組の方はnpmを使うと思うので確認しておいてください。

## 終わりに
記事短すぎて物足りないですね。
まあ特に説明するところもないので今回はこれで終わります。
AtCoder環境も記事にしたいので。。。
[DNS] スタブリゾルバーとフルサービスリゾルバー


## リゾルバーは二種類
- (ローカルPC側) プログラムの問い合わせに関していろいろ頑張った上でIPアドレスを返してくれる**スタブリゾルバー**
- (サーバー側) FQHNを受取り、各DNSサーバーにお問い合わせをしてくれる**フルサービスリゾルバー**