OmniAICreator/Qiita-1.07M huggingface dataset:
Zoom Webhook でvalidateを通す方法（Python）

# はじめに
以下のzoom公式でアナウンスされたように、2022年10月23日以降に作成されたWebhookには検証が必要になりました。

https://devsupport.zoom.us/hc/en-us/articles/13352207117581-Updated-Webhook-Validation-and-Verification-Processes

本記事ではその検証をpythonで行う例を示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/ecdb0bcb-f6ea-9042-288d-c64327d95e9c.png)

Webhookの登録までは以下の記事が参考になります。

https://qiita.com/yosuke-sawamura/items/a45453f1492a43211b96

# 事前準備

以下のページにあるngrokの実行ファイルをダウンロードする（アカウントがなければSignup for freeから登録）

https://ngrok.com/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/be332429-222a-eddf-9d81-8a74053b27b0.png)



その後、サイトの手順通りに
zipファイルを解凍し、実行ファイル(ngrok.exe)を取り出す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/23c4d978-24a1-f6a0-96a4-b45d8e90bd9c.png)


環境変数にPATHを通してから任意の場所で実行する、もしくは実行ファイル直下で以下のコマンドを実行。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/a8bf9140-9791-c30f-5cad-fa67bb08a3c8.png)

最後にローカルに作成したサーバに対応したポートを指定して実行。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/71a0a2b9-13aa-9b59-b668-fe2c5f939c55.png)


# 実装例

```python:main.py
from flask import Flask, request, jsonify
import os, hmac, hashlib

# Secret Token を使用する
zoom_webhook_secret_token=os.environ["ZOOM_WEBHOOK_SECRET_TOKEN"]

flask_app = Flask(__name__)

@flask_app.route("/webhook", methods=["POST"])
def get_request():
    json = request.get_json()
    if json["event"]=="endpoint.url_validation":
        res={
            "plainToken": json["payload"]["plainToken"],
            "encryptedToken": hmac.new(bytes(zoom_webhook_secret_token, "latin-1"),json["payload"]["plainToken"].encode("utf-8"),hashlib.sha256).hexdigest()
        }
        return jsonify(res), 200

if __name__ == "__main__":
    flask_app.run(host="0.0.0.0", port=5000)
```

まず必要なライブラリをインストール。
```bash
python -m pip install flask
```

以下を実行
```bash
python main.py
```
次に、別ターミナルで
```bash
ngrok http 5000
```
最後にvalidateボタンをzoomのアプリケーションページから実行してください。

# 結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181686/25908680-97c3-8fe2-0239-8dba778aace5.png)

# 参考

Challenge-response check 

https://developers.zoom.us/docs/api-reference/webhook-reference/#validate-your-webhook-endpoint
Package.jsonの記述とpackage-lock.jsonについて

## 概要
Node.jsにおいてインストールするパッケージが記述されたJSONファイルです。パッケージ管理の設計書であり、異なる環境でもpackage.jsonを読み込むことで同じパッケージをインストールすることができます。

## 構成要素
以下、package.jsonの基本的な記述です。
```package.json
{
  "name": "my-package",
  "description": "my first package ever",
  "license": "MIT",
  "version": "1.0.0",
  "bin": "./cli.js",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "axios": "^1.3.4"
  },
  "devDependencies": {
    "eslint": "^8.36.0"
  }
}
```
※`name` `version` `description` `license` などのデータはパッケージのメターデータなので、公開しないのであれば気にする必要は無いです。

機能的に重要なのは、`bin` `main` `dependencies` `devDependencies` `scripts` です。

### bin
パケージを外から使うときに重要な項目。実行可能ファイルが指定されているとパッケージをインストールすれば、CLIとして実行できるようになります。

### main
パッケージを外からインストールする時に、どのJSファイルが入り口であるかを指定するものです。外のパッケージを使う時に、どのファイルをインポートするということなのか確認できます。

### scripts
任意のコマンドに名前を付けることができます。記載したscriptは`npm run <name>`で実行できます。

### dependencies
実行に必要なパッケージを記載します。一度`npm i`した状態でアップデートしたい場合は、直接`package.json`を編集せずに`npm`を通じて行います。

また、`npm`でdependencyを変更すると自動的に`package.json`にも反映されます。
※もし`package.json`を直接編集した場合`npm i`を実行して`node_modules`内のファイルを更新する必要があります。

```
追加
$ npm install <package>

削除
$ npm uninstall <package>
```
### devDpendencies
開発やテストにのみ必要なパッケージを記載します。例えば、ESLintは開発のときにのみ必要で実行するときには不要なため、devDepに記載します。

```
$ npm install -D <package>
```

## semver規格
npmはパッケージのバージョン管理をsemver(semantic versioning)と呼ばれる規格に従って行っています。semverによれば、全てのバージョンは3桁の数字で表記され、その形式は (x.y.z) です。パッケージの新バージョンがリリースされる場合、変更点・意味合いを踏まえて、それに合わせてバージョンを更新する必要があります。

**x : メジャーバージョン**
**y : マイナーバージョン**
**z : パッチバージョン**

大きな変更があった場合、新しい機能が実装された場合、**メジャーバージョン**を上げる。
後方互換性のある新機能が追加された場合、**マイナーバージョン**を上げる。
バグが修正された場合は、**パッチバージョン**を上げる。

### バージョンアップのシンボル
セマンティックバージョンと一緒に、npmは`package.json`ファイルでこれらのバージョンの前に特別なシンボルを追加します。これらのシンボルは`npm update`や`npm i`を行うときにどのバージョンをインストールするかを`npm`に伝えるために使用されます。

それぞれのシンボルには独自のルールがあり、パッケージをインストールする際にバージョンを解決する方法を定義しています。よく使われるシンボルには、カレット( ^ )とチルダ( ~ )があります。

### カレット(^)
マイナーバージョンとパッチバージョンは変更可能ですが、メジャーバージョンは変更できません。例えば、`package.json`に`^13.1.0`と記載されている場合に`npm update`を行うと...

・13.2.0、13.3.0、13.3.1、13.3.2などのバージョンにはアップデートできますが、14.0.0やそれ以上のバージョンの変更を受付けないです。

### チルダ
更新できるのはパッチバージョンだけです。例えば、`package.json`ファイルに`~13.1.0`というバージョンがあった場合、`npm update`を行うということになります、

13.1.1、13.1.3などのバージョンにアップデートすることができますが、13.2.0や13.3.0などのバージョンには適用されません。npmはデフォルトですべてのパッケージに`^`のルールを追加します。

なお、package.jsonで設定できる項目の全てはnpmドキュメントで確認でき、内容を訳してくれた記事もあります。

https://garafu.blogspot.com/2016/11/packagejson-specification-ja.html

## package-lock.jsonについて
dependencyのバージョンをlockするためのファイルです。`npm`を使用してパッケージをインストール/変更するときに自動的に生成されます。このファイルの主な目的は、インストールされたパッケージの正確なバージョンを追跡することです。また、副依存関係（インストールしたパッケージの依存関係として自動的にインストールされたパッケージ）についての情報も含まれます。

機能としては`npm i`を行う際、npmは`package.json`ファイルをスキャンしてパッケージ名を見つけ、`package-lock.json`ファイルをスキャンしてそのパッケージのバージョンを見つけます。`lock`ファイルに記載されているバージョンと`package.json`ファイルに記載されているバージョンが（semver記法に基づいて）互換性があると判断した場合、ロックファイルに記載されているバージョンのパッケージをインストールします。


なお、`package-lock.json`は直接編集せず、削除しないこと。
c++版PyTorchでカスタムデータセットを作る

最近PyTorchのC++版をいじることが多いのですが、過去には[M1 MacでPytorchのc++版、libtorchをインストールして実行する](https://qiita.com/cometscome_phys/items/96b94074fdaf1c2bfa04)などの記事を書きました。

この記事では、英語でもなかなか出てこない情報である、PyTorch C++版でのデータセットとデータローダの作り方について忘備録的な意味でまとめておきます。

# バージョン
- PyTorch 2.0 C++ API

# やりたいこと
インプットデータとアウトプットデータを自分で指定した形で取り出したいです。例えば、
- インプット：```std::vector<torch::Tensor>```
- アウトプット：```std::vector<torch::Tensor>```

のようなデータを取り出すことを考えます。インプットが複数、アウトプットが複数、という状況に対応できれば、多くのことに対応できるでしょう。

# カスタムデータセット
例えば、
```c++
namespace Dataloader{

    using inputtensors = std::vector<torch::Tensor>;
    using outputtensors = std::vector<torch::Tensor>;
    using Example = torch::data::Example<inputtensors,outputtensors>;

     class SDataset : public torch::data::Dataset<SDataset,Example>
    {
        public:
            explicit SDataset(const size_t & numofdata){
                this -> numofdata = numofdata;
            }
            Example get(size_t index);
            torch::optional<size_t> size() const {
                return numofdata;
            }
        private:
            size_t numofdata;
    };

    Example SDataset::get(size_t index){
        std::vector<torch::Tensor> inputdata(2);
        std::vector<torch::Tensor> outputdata(2);

        inputdata.at(0) = at::linspace((double) index, (double)index+0.3, 4);
        inputdata.at(1) = at::linspace((double) index, (double)index+3.0, 2);
        outputdata.at(0) =  torch::randn({4,2});
        outputdata.at(1) =  torch::randn({3,2});
        return {inputdata,outputdata};
    }
}
```
のようにします。クラス```SDataset```は```torch::data::Dataset<SDataset,Example>```を継承していますが、これによってPyTorchのデータセットとして扱うことができるようになります。なお、この```Example```の部分がデータの入力出力形式を指定するもので、この場合は
```c++
    using inputtensors = std::vector<torch::Tensor>;
    using outputtensors = std::vector<torch::Tensor>;
    using Example = torch::data::Example<inputtensors,outputtensors>;
```
としています。```torch::data::Example```がデータセットの形式になります。そして、その入力と出力は```<inputtensors,outputtensors>```で指定されています。

このデータセットのクラスは、
```c++
Example get(size_t index);
torch::optional<size_t> size() const {
    return numofdata;
}
```
のように、```get```と```size```を最低限実装している必要があります。このサンプルでは適当な実装をしています。

このように定義したクラスを用いると、
```c++
auto sd = Dataloader::SDataset(100);
int batch_size = 10;
auto data_loader = torch::data::make_data_loader<torch::data::samplers::RandomSampler>(
                            sd, batch_size); 
for (auto& batch : *data_loader ){
    auto c = batch.size();
    auto inputdata = batch.at(0).data;
    auto outputdata = batch.at(0).target;
}
```
のようにすると、データローダーも利用することができます。ここでは、バッチサイズが10となるランダムバッチを作って取り出す、ということをやっています。バッチとなっている場合には```std::vector```でデータが束ねられており、```Example```というクラスは```data```がインプット、```target```がアウトプットとなっています。今回は、これらがそれぞれ```std::vector<torch::Tensor>```になっているわけです。
仮想マシン_空き容量拡張手順

## 前提
OS：Ubuntu20.04.3LTS
仮想化ソフト：Oracle VM VirtualBox

仮想マシンのUbuntuマシンの容量を拡張する方法の手順メモです。

## 手順
```bush:bush(Ubuntu.20.04.3LTS)
##サーバーをシャットダウン

##バーチャルボックスの「ファイル」から「仮想マネージャー」を開いて、
GUIで仮想HDDを拡張する。

##サーバーを起動する

sudo sh -c "echo 1 > /sys/class/block/sda/device/rescan”を実行する

parted -l
##を打って、Fixする

gdisk
##で、最大容量でデバイスに新規パーティションを作成する
##pで確認
##nでパーティションを新規作成
##開始も終了も、全てデフォルト値でエンターキー押下
##8E00?のLVMを指定する
##wで書き込む

pvcreate
##で、物理ボリュームとして初期化する
##>この時、エラーになったら、-A n で、バックアップを無効化する

vgextend
##を行う

lvextend
##で、拡張するバイト数を指定して、拡張する

resize2fs
##を打つ->拡張完了
```

※上記の手順を実施する前に、自身のデバイスをLVMに変更をする必要があります。
まずはLVMに変更をしてから、上記の手順を実施していただけると幸いです。
コードで画面遷移のやり方

# はじめに
コードで画面遷移するとき混乱したのでメモ、備忘録
ストーリーボードでsegue、ストーリーボードリファレンスでも画面遷移できますが条件をつけて遷移するときコードの方が便利！
今回はボタンで遷移させています。
テーブルビューのセルでも試して画面遷移できました。
サンプルです
https://github.com/kabikira/TestScreenTransition

# 同じstoryboard上で遷移したい場合
![スクリーンショット 2023-03-25 20.04.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/298e2ee7-a6ac-0370-fcdc-ca0a3a8c88f1.png)

storyboardIDを指定して行う。
```swift
// 同じストーリーボードに遷移したい画面があるとき
    @IBAction func goFristDetail(_ sender: Any) {
        if let vc = storyboard?.instantiateViewController(withIdentifier: "FirstDetail") as? FristDetailViewController {
            navigationController?.pushViewController(vc, animated: true)
        }
    }
```
            
            
# ViewControllerのみの場合
![スクリーンショット 2023-03-25 20.06.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/16568b63-8e50-b4de-9bc2-c3deceefcef2.png)

storyboardがなくViewControllerだけのときはこれだけ
```swift
    @IBAction func goSecondDetail(_ sender: Any) {
        // ViewControllerのみの場合
        let vc = SecondDetailViewController()
        navigationController?.pushViewController(vc, animated: true)
    }
```

# 違うストーリーボードとViewControllerに遷移するとき
![スクリーンショット 2023-03-25 20.06.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/37265948-d303-901d-adf9-8d4f023905f0.png)

storyboardの名前を指定して画面遷移します。
```swift
    @IBAction func goThirdDetail(_ sender: Any) {
        // 違うストーリーボードに遷移するとき
        if let vc = UIStoryboard(name: "ThirdDetail", bundle: nil).instantiateInitialViewController() as? ThirdDetailViewController {
            navigationController?.pushViewController(vc, animated: true)
        }
    }
```

# おわりに
モダールで表示するときはpresentを使います
```swift
    @IBAction func goFristDetail(_ sender: Any) {
        // 同じストーリーボードに遷移したい画面があるとき
        if let vc = storyboard?.instantiateViewController(withIdentifier: "FirstDetail") as? FristDetailViewController {
            // モダールで遷移
            self.present(vc, animated: true)
        }
    }
```
間違ってたら教えてください！
サンプルです
https://github.com/kabikira/TestScreenTransition
Ubuntu_マシン使用容量削減方法

## 前提
OS：Ubuntu20.04.3LTS

以前、自宅サーバーとして稼働をさせているLinuxサーバーの空き容量が0になり、
その結果サーバーがダウンし起動できなくなるという事態が発生しました。

上記のような事態が発生した際には、通常ならサーバーの空き容量を拡張しますが、
まず事前作業として、一時的にサーバーを復活させるために実施した、不要ファイルの削除方法を紹介させていただきます。

## あまり効果がないコマンド
```bush:bush(Ubuntu.20.04.3LTS)
apt autoremove
apt autoclean
```
上記を実施しても、空き容量はほとんど変わりません。


## Ubuntu不要ファイル削除コマンド
```bush:bush(Ubuntu.20.04.3LTS)
Du -sh /*
```
まず、上記のコマンドで、Linux内の各デバイスの逼迫容量を確認します。
すると、「swap」という名称のついたデバイスが出てくると思います。このswapは、imageファイル等のバックアップのようなもので、特別使用しない場合は削除して大丈夫です。

```bush:bush(Ubuntu.20.04.3LTS)
sudo swapoff -a
##これでswapの生成を無効化する

sudo rm /swap.img
##これで削除をすると、かなり減る
```
上記のコマンドを実行することで、サーバーの空き容量をある程度削減をすることができます。
3/25 Ruby入門remained 基礎文法編

# 個人的リマインド用

## ifで条件分岐
ユーザーから値を受け取る gets
```ruby
gets.to_i

if score > 80
    puts "great!"
elsif score > 60
    puts "good"
else
    puts "so so"
end

/*簡単な条件分岐は puts "great!" if score > 80で代替可能
```

## caseで条件分岐
getsは最後に改行コードがついているので.chompで取り除く
```ruby
case signal
when "red"
    puts "stop"
when "green", "blue"
    puts "go"
when "yellow"
    puts "caution"
else
    puts "wrong signal"
end
```

### timesで繰り返し
```ruby
10.times do | i | /*1行しかない時はdo,endを{}で代替可能*/
    puts "#{i}: Hello"
End
```
## forとeachで繰り返し
```ruby
for i in 15 .. 20 do /*省略可*/
    p i /*15 ~ 20が1つずつ入っていくる*/
end

for color in ["red", "blue"] do /*省略可*/
    p color
end

for name, score in {taguchi: 20, sato: 40} do /*省略可*/
    p "#{name}: #{score}"
end

/*eachで書き換え可能*/
{Taguchi:20, sato:40}.each do |name, score|
    p "#{name}: #{score}"
end
```

## loapでずっと繰り返し
ctrl+Cで止められる
```ruby
i = 0
loap do
    p i
    i += 1
end
```
**break(途中で止める), next(1つスキップ)**
```ruby
10.times do | i |
    if i == 7
        break or next
    end
    p i
end
```
## method
```ruby
def sayHi(name = "tom(default)") 
    puts "hi! #{name}"
    /*値を返す時はreturn(returnなくても最後に読み込んだ値は返す)*/
end

sayHi("tanaka") /*()は省略可*/
```
ITエンジニア的なChatGPTの使い方メモ

ITエンジニアとしてChatGPT(GPT-4前提)を用いる際の使い方のメモです。
革新的な使い方等は一切記述がないのでご注意ください。

# 問い合わせ方法について

## 1. 条件を箇条書きする

ほしい結果の条件を箇条書きします。

ChatGPTは話し言葉や文章で問い合わせても結果を得ることができますが、複雑な条件を文章で伝えることはそれなりに難しいことから、指示を出す人間側が楽をするために箇条書きにします。
複雑な問い合わせの場合には必要に応じて親子関係等の構造化を取り入れます。

## 2. 指示を追加する

問い合わせ結果が意図したものでない場合には指示を追加します。

最初の問い合わせで必ずしも望む結果が得られるとは限らないことから、要件に合わせて指示を追加し微調整します。
例えばサンプルコードの生成であれば、ライブラリや処理系のバージョン、設定の記述方法等できる限り詳細に指示を出した方が望む結果が得られやすいです。

## 3. アスキーアートを出力させる

シーケンス図やクラス図等をアスキーアートで生成させます。

現状のChatGPTは画像を出力する機能が備わってないものの、テキストは出力可能であることから、シーケンス図やクラス図等の情報をアスキーアートで出力させます。
あるいはPUML等のツールで利用可能な形式で出力する方法もあります。

## 4. URLを列挙させる

ChatGPTに特定の情報の内容を求めるのではなく、求める情報が記載されたURLを列挙させます。

ChatGPTは必ずしも100%正確な情報を答えてくれるわけではなく、厳密な仕様の確認が必要なITシステム、コンポーネントの情報の検索にはそのままでは不向きです。
そこでベストプラクティス集や、公式ドキュメントなどのURLをChatGPTに探させることで、情報の正確性を担保しつつ必要な情報を入手できます。(検索が柔軟なgoogle検索のイメージです)

## 5. サンプルコードを生成させる

LinuxのシステムコールやOSSのライブラリのサンプルコードを生成させます。

LinuxのシステムコールやOSSをmanページや公式ドキュメントをみても、サンプル実装がなかったり、理解が難しいことがあります。
単にGoogle検索するだけでは大量のノイズが紛れ込み、なかなかよい感じのものがみつからないこともざらにあることから、個人的にはかなり有効な使い方であると考えています。

## 6. 完璧を求めない

ChatGPTの出力する結果に完璧を求めず、おおよそ望ましい結果が得られた場合には手動での操作に切り替えます。

自然言語の指示で100%完全に望む結果を得ることは難しいことから、おおよそ望む結果を得られた場合には、googleサイト内検索や成果物の手修正に切り替えます。

# 個人的に役に立った使い方について

個人的には以下のような使い方が役にたちました。

1. 全く知らない技術情報のサマリーにプラスして、公式ドキュメントやベストプラクティス集のURLを出力させることで素早く概要を把握しつつ、ダブルチェックを実施する
1. OSSのライブラリやLinuxのシステムコールのサンプルコード生成する
1. 特定処理の概要をシーケンス図化する
【知識0】文系大学生がChatGPTを駆使してChrome拡張を作ってみた

# はじめに
突然、Chrome拡張を作ってみたくなったので知識0の状態からChatGPTを活用して簡単なものを作ってみました。
現在審査待ちです！！(2023/03/25 19:37)
審査が終わったら更新します！！

是非使ってみてください！！

# 何を作ったの？
ChatGPTを使っていると回答が途中で途切れることがよくあります。
毎回、「続きを出力して」と送信するのは大変なので、ボタン1つで送信できる機能の拡張を作成しました。

# ChatGPTとの会話
![FireShot Capture 002 - ChatGPTのChrome拡張 - chat.openai.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/efa77097-8b54-e8c8-82cb-408a997a7ae8.png)

# 動作
Continueボタンを押すと続きを出力してくれます。
既に全文出力されている場合は補足などを出力してくれます。
![スクリーンショット 2023-03-25 13.37.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/1c98d7d5-c1f2-2178-8179-f6131bf735e9.png)

# Chromeウェブストアのデベロッパー登録
[こちら](https://chrome.google.com/webstore/devconsole/register)からChromeWebStoreDeveloperDashboardにはいります。
登録料は1回限りの5ドルでした！親切！！！
![スクリーンショット 2023-03-25 13.34.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/1628052e-2ca8-9c95-0be5-3c8c501de6ea.png)

# リリース手順(必須項目だけ埋めます)
① 「新しいアイテム」を選択します
![スクリーンショット 2023-03-25 14.59.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4e86fb2b-2651-4fdf-f2a0-e7a39633bfa5.png)

② 作成したChrome拡張が入っているフォルダをzipにしてドラッグ&ドロップします
![スクリーンショット 2023-03-25 15.01.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/2e42c96c-6e59-7cdd-8876-cfa2b2e0f7ae.png)

③ 「説明」を入力します
![スクリーンショット 2023-03-25 15.44.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/065107e8-2bcc-c712-5db1-0cd3ea0db181.png)

④ 「カテゴリ」を選択します
⑤ 「言語」を選択します
⑥ 「ショップアイコン」を選択します(128×128の画像を作るのが面倒！！)
![スクリーンショット 2023-03-25 15.45.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/08196c7a-dffc-042e-f135-41df50e31984.png)

⑦ 「スクリーンショット」を選択します(1280×800の画像を作るのが面倒！！)
![スクリーンショット 2023-03-25 15.52.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/ad91c509-111f-1f0b-2065-690eb3e37ac4.png)

⑧ 「プライバシーの取り組み」を選択します
⑨ 「単一用途」を入力します
![スクリーンショット 2023-03-25 15.57.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/92e22ef2-38de-02b0-7aa1-012f84e766fe.png)

⑩ 「ホスト権限が必要な理由」を記入します
⑪ 「リモートコードが必要な理由」を記入します
![スクリーンショット 2023-03-25 19.28.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/aed64582-5dc7-c039-e06a-ec8146e46f4d.png)

⑫ 全てにチェックを入れます
![スクリーンショット 2023-03-25 19.31.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b0a19202-f8b4-f88a-c20b-e6ee925c358a.png)

# おわり

審査に提出することができました！
![スクリーンショット 2023-03-25 19.35.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/58b51959-2a3f-7452-483f-dfb53dd0f1e3.png)

リポジトリはこちらです。

https://github.com/SNQ-2001/ChatGPTContinueButton

# 追記(2023/03/28)
審査通りました！！！
ぜひ使って見てください！！

https://chrome.google.com/webstore/detail/chatgpt-continue-button/fnjdboejkfbaeijiogeaickgfmjopdno?hl=ja&authuser=0
3/25 Ruby入門remained 基礎知識編

# 個人的リマインド用

##  初歩
irb → 簡易的にRubyを実行できる
ri → ドキュメントを見ることができる

## コメントと出力
```
=begin
~この中をコメントに~
=end

print ~ (オブジェクトをstringに)
puts ~ (改行がつく)
p ~ (デバッグ用)
```

## 変数と定数
```
変数は英小文字か_で始めなければならない
例: msg = "こんにちは"

定数は全部大文字
例: VERSION = 1.1
※Rubyは定数を書き換える際、警告は出すがそのまま実行されるので注意
```

## オブジェクト
Rubyは全部object
例: string(stringクラス), floot(flootクラス)

(インスタンス→)"Hello world".length(←メソッド)

## method
### 様々なメソッド
54.8.class(所属しているクラスが見れる)
54.8.methods(使えるメソッドが見れる)

四則演算 + - * / % ** などなど

分数の計算→ Rational(2, 5) == 5分の2
※ちなみに2/5rてな感じに短くかける

## ""と''
### ””と’’の違い
""は特殊文字と式展開ができる
**特殊文字**→文字列途中に\nで改行、\tでタブなどなど
※\はoption + ¥キー

**式展開**→"#{300 * 300}だったり#{変数名}"文字列の中で式を展開したり変数を表示できる

"hello" + "world" → "helloworld"
"hello" * 10 → "Hello"を10回表示

## !と?
**!や?がついたmethod**
```
!がついたmethodは破壊的なメソッド
例: .upcase(大文字にするメソッド)の場合
.upcase!(大文字を返した上で書き換える)→これを破壊的なメソッドという

他にも.downcase(全小文字)や.reverse(文字を逆に)などがある
```
```
?がついたmethodは真偽値を返す
例: .empty(空)や.include(含む)
name.empty?(空ですか？), name.include?("g")(gを含んでいますか？)
```

## 配列
```
colors = ["red", "blue", "yellow"]

アクセス
colors[0(添字)] → "red"
colors[-1] → "yellow"
colors[0 .. 2] → 全部
colors[0 ... 2] → "red", "blue"(2の直前まで)
colors[5] →　nil(何もないと言うオブジェクト)
```
```
書き換え 
colors[0] = "pink"
colors[1 .. 2] = ["green", "black"]
*後ろに追加* colors.push("gold") == colors << "silver"

※他にも.size(配列の数)や.sort(並び替え)などのmethodもあるよ
```

## ハッシュ
ハッシュ(jsでいうobject)
```
scores = {tanaka: 200, sato: 100}

アクセス方法
scores[:tanaka]
書き換え方法
scores[:sato] = 600

様々なmethod
.size(ハッシュ内の数) .keys(キーだけ取る) .values(バリューだけ取る)
.has_key?(:tanaka)(このキーありますか？)
```

## 変換
変換
.to_s(文字列)
.to_i(整数)
.to_f(浮動小数点)
.to_a(配列)
.to_h(ハッシュ)

## ""と''の書き換え
**""から%()に,''から%q()に**
```
"Hello" == %(Hello)
'Hello' == %q(Hello)
メリットは\nとかを使う時に分かりやすい

他にも
["red", "blue"] == %W(red, blue)
['red', 'blue'] == %w(red, blue)
```

## 埋込
**埋込 "文字列" % 値**
```
"name: %s" % "tanaka"　→ "name: taguchi"
"name: %10s" % "tanaka"　→ "name: (10桁空) tanaka"
"name: %-10s" → "name: tanaka (10桁空)"

%d(整数) %f(浮動小数点)
"id: %05d(5桁にして0で埋める), rate: %10.2f(左に10桁空きで小数点以下2桁) % [355, 3.284]
→"id: 00355, rate: (10桁空き) 3.28"
```
Next.js x TypeScript x react-chartjs-2でグラフ実装

`Next.js`, `TypeScript` x `react-chartjs-2`を使ってグラフを実装します。
画像のような完成イメージです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551042/e4d20514-234d-bdbd-f42d-8174d05895b8.png" width="500" />

## 環境
`next 13.2.4`
`react 18.2.0`
`react-chartjs-2 5.2.0`
`chart.js 4.2.1`
`typescript 5.0.2`

### 準備
必要なライブラリをインストールします。

```console
npm install chart.js
```

```console
npm install react-chartjs-2
```

`faker`はダミーデータ生成のために使います。

```console
npm install --save-dev @faker-js/faker
```

### `chart.js`初期設定
今回の作業は`pages/index.tsx`で完結させようと思います。
必要なパーツを`chart.js`から読み込み、登録します。

```pages/index.tsx
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend,
} from 'chart.js';
import { Bar } from 'react-chartjs-2';
import { faker } from '@faker-js/faker'

ChartJS.register(
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
);

...
```

### グラフ表示
オプション、ラベル、グラフに表示するデータを準備して`Bar`コンポーネントに渡してあげます。
全体のソースコードはこちらです。

```pages/index.tsx
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend,
} from 'chart.js';
import { Bar } from 'react-chartjs-2';
import { faker } from '@faker-js/faker'

ChartJS.register(
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
);

export default function Home() {
  const options = {
    responsive: true,
    plugins: {
      legend: {
        position: 'top' as const,
      },
      title: {
        display: true,
        text: 'Chart.js Bar Chart',
      },
    },
  }
  const labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];

  const data = {
    labels,
    datasets: [
      {
        label: 'Dataset 1',
        data: labels.map(() => faker.datatype.number({ min: 0, max: 1000 })),
        backgroundColor: 'rgba(255, 99, 132, 0.5)',
      },
      {
        label: 'Dataset 2',
        data: labels.map(() => faker.datatype.number({ min: 0, max: 1000 })),
        backgroundColor: 'rgba(53, 162, 235, 0.5)',
      },
    ],
  };
  return (
    <Bar options={options} data={data} />
  )
}

```

## 参考
https://react-chartjs-2.js.org/
https://fakerjs.dev/
【JavaScript】Promiseの基礎

## はじめに
こんにちは。
非同期処理を楽に書けるPromiseを分かっていない人が多い(10年選手や20年選手が分かっていない)ので、記事を書きます。
大事なところだけやります。解説するというか簡単なプログラムを書きます。(プログラムに斜めの矢印とか使って解説したかったので、画像にしています。)
例外処理やasync/awaitについてはやりません。
では、いってみましょー。

## 共通仕様
本記事で扱う処理は以下とします。
m1秒後に処理1を行う。
処理1完了後のm2秒後に処理2を行い、処理1完了後のm3秒後に処理3を行う。
処理2,処理3の両方完了後のm4秒後に処理4を行う。

勘違いが無いように、噛み砕くと
処理1の後に処理2,処理3両方が終わるのを待って処理4を行うってことです。

## Promiseを使わず書いてみる - 非同期処理って面倒
まずは、Promiseなしで、プログラムを書いてみます。
処理が進むごとにネスト化しているのが分かります。
処理が複雑になると読むのが大変そうですよね。
処理を関数化したところで読みにくさは変わりません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163605/95fd427f-b3b7-7e84-51bd-fdc366f44572.png)


## PromiseオブジェクトってPromiseクラスのインスタンスのことだよ
これ分かってない人が多い気がします。
Promiseって何かっていうと、<b>単なるクラス</b>です。
クラスなんで、Promiseオブジェクトを作るために、もちろんnewする必要があります。
そのコンストラクタの引数が、resolveとrejectを引数とする関数であることが要求されます。
で、そのPromiseオブジェクトは、thenやallメソッドを持ちます。

通信用のAPIであるgetJSONやfetchなどは戻り値がPromiseオブジェクトだから、getJSON(...).then(...)とか書くことができるわけです。

## Promiseを使って書いてみる - 見やすいでしょ

右が処理を関数化したやつです。こうすると見やすくなったのが分かりやすいですよね。
簡単なプログラムなのであえてrejectを呼んでいません。
<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">then</a>,<a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/then">all</a>についてはmozillaのリファレンスを参考にしてください。
最後の処理4はPromise化しなくてもOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163605/bdfb9203-2f88-709c-d4a3-7741702b4c12.png)

## 最後に
then,allの説明はしませんでした。プログラム読めばわかると思ったので。
Promiseは<b>超超超重要</b>です。
理解があやふやな人はこれを機にぜひ習得してみてください。
【GAS】Google Apps Scriptのはじめかた

# はじめに

当記事はGoogle Apps Scriptのプロジェクトの作成方法だけの記事です。
~~(別記事の前フリとして作成していたものを単体で切り出したため、シート名に名残があります)~~

# A.スプレッドシートから作成する(インストール型)

Google スプレッドシートの「拡張機能」メニューから「Apps Script」をクリックすると、当スプレッドシートをコンテナとするApps Scriptプロジェクトが作成されます。

 「株価GASサンプル」スプレッドシートから「拡張機能」→「Apps Script」を選択
![WS000106aa.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633534/9ec6ff2d-d04e-4a61-4cf5-98668afdc204.jpeg)
「無題のプロジェクト」Apps Scriptスクリプトエディタが立ち上がる
![WS000107a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633534/77fa5a9b-eb8d-3621-d527-911b9f03adff.jpeg)
「プロジェクト詳細」ではアイコンがスプレッドシート依存表示となり、コンテナが「株価更新GASサンプル」になっている
![WS000108a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633534/016d76fb-8ec7-fd3a-1ecc-6b9ce630ee1f.jpeg)

# B.Googleドライブからスタンドアロンで作成する

Googleドライブ画面左上の「+ 新規」から「その他」「Google Apps Script」と選択することでも、Apps Scriptプロジェクトを作成可能です。
その場合は特定のファイルに依存しない独立型となります。
![WS000109a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633534/b910b07e-c73f-d742-dd9c-f312548711b2.jpeg)
アイコンがApps Scriptになり、コンテナ表示がない
![WS000110a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633534/2c84ae54-67b9-0a84-bf11-5b02188241ad.jpeg)

# C. Google Apps Scriptプロジェクト管理画面からスタンドアロンで作成する

**https://script.google.com** をたどるとGoogle Apps Scriptのプロジェクト管理画面が開くので、左上の「+ 新しいプロジェクト」をクリックすることでプロジェクトが作成され、スクリプトエディタが開きます。

![WS000114a.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633534/d791a2c3-f1a7-de94-c123-08444a5565ce.jpeg)

# おわりに

Google Apps Script は一般向けのサービスではないのか、スプレッドシートからもGoogleドライブからも階層が深い上、プロジェクト管理画面も検索しないと出てこないため、サービスの入り口が分かりづらいなと個人的に感じております。
JavaScriptベースで、環境もChromeとGoogleアカウントさえあれば良いため、気軽に触れて面白いと個人的には感じております。

以上、よろしくお願いいたします。
Vim入門：基本操作から始める1

# はじめに
最近[dotfiles](https://github.com/hellomyzn/dots)を改めて作り直し、ついでにvimのコマンドなども勉強し直しました。
なので、その備忘録です。


## モードの切り替え

| コマンド | 説明 |
|---------|------|
| `i`     | インサートモードに移行する |
| `I`     | 行頭に移動し、インサートモードに移行する |
| `a`     | カーソルの次の位置に移動し、インサートモードに移行する |
| `A`     | 行末に移動し、インサートモードに移行する |
| `s`     | カーソルがある位置の1文字を削除し、インサートモードに移行する。 |
| `S`     | カーソルがある行をすべて削除し、インサートモードに移行する。|
| `c`     | 行末に移動し、インサートモードに移行する |
| `C`     | カーソルがある位置から行末までを削除し、インサートモードに移行する。 |
| `o`     | 下に一行追加してインサートモードに移行する |
| `o`     | 上に一行追加してインサートモードに移行する |
| `v`     | ビジュアルモードに切り替える |
| `Esc`   | ノーマルモードに戻る |



## カーソル移動

| コマンド | 説明 |
|---------|------|
| `h`     | 左に1文字移動する |
| `j`     | 下に1行移動する |
| `k`     | 上に1行移動する |
| `l`     | 右に1文字移動する |
| `w`     | 次の単語の先頭に移動する |
| `W`     | 次の単語の先頭に移動する(記号を含めた単語) |
| `e`     | 次の単語の終端に移動する |
| `E`     | 次の単語の終端に移動する(記号を含めた単語) |
| `b`     | 前の単語の先頭に移動する |
| `B`     | 前の単語の先頭に移動する(記号を含めた単語) |
| `0`     | 行頭に移動する |
| `$`     | 行末に移動する |



## テキストの編集

Vimには、
- 範囲を選択してからコマンドを実行する方法
- コマンドを実行してから範囲を指定する方法
の両方あります。

例えば
`<select>x`: 選択範囲を消す
```vim
# 単語の先頭で下記のコマンドをノーマルモードで試して下さい。
vwd
```
`d<motion>`: `<motion>`でカーソルが一回動いた部分を消す
```
# 単語の先頭で下記のコマンドをノーマルモードで試して下さい。
dw
```
と結果は同じですが２通りあります。
それを踏まえて下記のコマンドを参照ください。

| コマンド | 説明 |
|---------|------|
| `<select>x`,`d<motion>` | テキストを削除 |
| `<select>y`,`y<motion>` | テキストをコピー |
| `<select>c`,`c<motion>` | テキストを削除してインサートモードに移る |
| `<select>U`,`gU<motion>` | テキストを大文字にする |
| `dd`    | カーソルのある行を削除する |
| `yy`    | カーソルのある行をコピーする |
| `p`     | カーソルの下/右に削除またはコピーしたテキストを貼
| `P`     | カーソルの上/左に削除またはコピーしたテキストを貼り付ける |
| `.`     | 直前のコマンドを繰り返す |
| `u`     | Undo |
| `<C-r>`     | Redo |


## テキストの選択(ビジュアルモード)
| コマンド | 説明 |
| --- | --- |
| `v` | 通常のビジュアルモード。カーソルの移動で選択範囲を変更できる。 |
| `V` | 行単位のビジュアルモード。カーソルの移動で選択範囲を行単位で変更できる。 |
| `CTRL-V` | 矩形ビジュアルモード。選択範囲を矩形(縦型)にすることができる。 |
| `o` | 選択範囲の始点と終点を切り替える。 |


## ファイルの保存と終了

| コマンド | 説明 |
|---------|------|
| `:w`    | ファイルを保存する |
| `:q`    | Vimを終了する |
| `:q!`   | 変更を破棄して強制的にVimを終了する |
| `:wq`   | ファイルを保存してVimを終了する |



## おわりに

[Vim入門：基本操作から始める2](https://qiita.com/hellomyzn/private/c40c20f0e8c1c39d6ed2)に続きます。
Intune Win32アプリで対話型インストールを行う その２


[前回](https://qiita.com/keitanak/items/d026406fcbfce20e2f77)に引き続き、今度は海外ネットで一般的なServiceUIを利用した方法を試してみたいと思います。

Intuneを利用してアプリ配布を行う時に、Win32アプリを利用することが多いと思います。
残念ながらIntuneではサイレントインストールにしないとインストールができません。
すべてのアプリがサイレントインストールならばいいのですが、実際にはそういかない場合も多いと思います。
色々と調べてみると、海外のコミュニティでも同様のことで困っている人がいて、以下のような対応策が公開されています。

[Use ServiceUI with Intune to Bring SYSTEM Process to Interactive Mode](https://www.anoopcnair.com/use-serviceui-with-intune-to-bring-system-process-to-interactive-mode/ "Use ServiceUI with Intune to Bring SYSTEM Process to Interactive Mode")

この方法をいろいろなスクリプトなどで試してみたいと思います。


## ServiceUIの入手方法

[Microsoft MDT](https://www.microsoft.com/en-us/download/details.aspx?id=54259)を入手して、インストールします。
インストール後、以下のフォルダにServiceUI.exeが保管されています。(x64の場合)
C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Tools\x64

# ファイル構成
以下のように保管し、Intune形式のファイルを作成しておきます。
D:\Documents\Intune\Apptest04\Src

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/001a1618-4b8e-ffe2-ff00-b857d9a4cc05.png)


IntuneWin作成のコマンド
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/5f47ebfc-c247-1150-8f33-727369fc3d18.png)





# EXEの場合

前回の7zipを利用します。
Intune Win32 アプリ インストールコマンドの指定
explorerを実行しているセッションに画面を表示する　ということのようです。
```
ServiceUI.exe -process:explorer.exe 7z1900-x64.exe
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/f555ea11-32ee-05e3-8853-6d9f5d488870.png)


# バッチファイル

```ruby:inst.bat
@echo off
echo Test Batfile
pause
exit 0
```
Intune Win32 アプリ インストールコマンドの指定
```
ServiceUI.exe -process:explorer.exe inst.bat
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/29718bc0-3bd4-8bf4-15cf-2543bbac909f.png)


# VBSスクリプト
```ruby:inst.vbs
Msgbox("Test!")
```
Intune Win32 アプリ インストールコマンドの指定
ServiceUIですが、パスを勘案しないようですので、コマンドによってはこのようにフルパス指定が必要のようです。
```
ServiceUI.exe -process:explorer.exe %SYSTEMROOT%\System32\wscript.exe inst.vbs
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/a89b1204-faa8-9a93-d20d-ec3b6b3c6e1f.png)


# Powershellスクリプト
```ruby:inst.ps1
Write-Host "Hello World!!"
[Console]::ReadKey() | Out-Null
```

Intune Win32 アプリ インストールコマンドの指定
```
ServiceUI.exe -process:explorer.exe  %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned .\inst.ps1
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015969/960d4bd3-817a-580b-3734-12bb885fcb0d.png)


# 最後に

やはりネットで情報が見つかるだけあって、こちらの方法が簡単ですね。
前回同様、そもそもこれをIntuneの機能でできないことが問題ですね、MSのFeedbackサイトにも投稿してみましたので、ご賛同いただける方は、投票をお願いいたします。

[Ability to allow Win32 Application(System context) Interactive installation](https://feedbackportal.microsoft.com/feedback/idea/bc1837a6-29c6-ed11-a81b-002248519701 "Ability to allow Win32 Application(System context) Interactive installation")

Enjoy your Intune life!
JavaScriptを初めて学ぶ3

関数（function）はタスクや値の計算を実行する処理の集まり。つまり、さまざまな処理を１つにまとめて名前をつけてまとめれる。まとめられるもの的な。
値を受け取ったり、その結果を返すことができる。何回も同じコード書かなくてよくなる。コスパの良いやつだ。

関数の定義の仕方は４つ↓

１.function命令

function 関数名（引数１、引数２,...){
    任意の処理
    return 戻り値
}

例えば
```javascript
function getRectangle(tate, yoko){  //()で引数を渡す。引数は関数に渡す特別な変数
    return tate * yoko; //これを計算した後、関数の呼び出し元に値を返す。
}

console.log(getRectangle(4, 6));　//4がtate, 6がyokoの引数に。tate(4)xyoko(6)で24。これを呼び出し元のgetRectangleにreturn。
console.logで24が出力される。

```

ちなみに引数（いんすうじゃなくて、ひきすう）は関数の呼び出し元から、関数へ値を渡すときに使う特別な変数
戻り値は関数から関数呼び出し元へ返す値

2.関数リテラル（関数名がないので、匿名関数なんて呼ばれることも）

function(引数１,引数2,...){
    実行する処理
    return 戻り値
}

例えば
```javascript
const getRectangle=function(tate, yoko){  //関数リテラルを定数に入れる
    return tate*yoko;
}

console.log(getRectangle(4,6))

```
したら24が出力される

3.Fuctionコンストラクタ

const 変数名 ＝ new Function(引数1, 引数2,..., 関数本体の処理);

例えば
```javascript
const getRectangle= new Function('tate', 'yoko', 'return tate * yoko')};

console.log(getRectangle(4,6));
```
したら24が出力される

4.アロー関数（関数リテラルの省略バージョン）

（引数1,引数2,...）=>{
    実行する処理
    return 戻り値
}

例えば
```javascript
const getRectangle =function(tate, yoko) {
    return tate * yoko;
}
console.log(getRectangle(4,6));

// ↓省略バージョン！アロー関数

const getRectangle2 =(tate2, yoko2) >= {
    return tate2 * yoko2;
}
console.log(getRectangle(4,6));
```

こうしてみると、関数はなんかテンプレート作りみたいな感じで覚えた方が良さそう
Firebase Crashlytics

以下は、FlutterでFirebase Crashlyticsを使用するための基本的なコースです。

1.Firebaseプロジェクトの作成：Firebase Crashlyticsを使用するには、Firebaseプロジェクトを作成する必要があります。Firebaseコンソールにログインして、新しいプロジェクトを作成してください。

2.Flutterアプリの設定：FlutterアプリでFirebase Crashlyticsを使用するには、firebase_coreとfirebase_crashlyticsパッケージをプロジェクトに追加する必要があります。pubspec.yamlファイルを開き、以下の依存関係を追加してください。


```dart
dependencies:
  firebase_core: ^1.4.0
  firebase_crashlytics: ^2.5.2
```


3.Firebaseプロジェクトの設定：FirebaseプロジェクトにFlutterアプリを追加するには、Firebaseコンソールからアプリを追加する必要があります。Flutterアプリのパッケージ名を入力し、Googleサービスの構成ファイル（google-services.json）をダウンロードして、アプリのルートディレクトリに保存してください。

4.Firebase Crashlyticsの設定：Firebase Crashlyticsを使用するには、FirebaseCrashlyticsインスタンスを初期化する必要があります。main.dartファイルを開き、以下のコードを追加してください。

```dart
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  FirebaseCrashlytics.instance.setCrashlyticsCollectionEnabled(true);
  FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterError;
  runApp(MyApp());
}
```

5.アプリのクラッシュをトリガー：Firebase Crashlyticsをテストするには、アプリでクラッシュをトリガーする必要があります。例えば、以下のようなコードを使用して、意図的なクラッシュを発生させることができます。


```dart
FirebaseCrashlytics.instance.crash();
```

これで、FlutterアプリでFirebase Crashlyticsを使用するための基本的な手順が完了しました。Firebaseコンソールからアプリのクラッシュレポートを確認することができます。
【備忘録】Kotlin基本

## インストール

```sh
curl -s https://get.sdkman.io | bash
sdk install kotlin
kotlin -version
```

## 使い方
### コンパイルと実行
```sh
kotlinc index.kt -include-runtime -d index.jar
kotlin index.jar
```

## コメント
```kotlin
  // 一行コメント
  /*
    複数行コメント
    複数行コメント
  */
```

## 基本構文
```kotlin
fun main() {
  // 出力
  println("テスト")
  println(5 + 10);

  // 変数
  val num:Int = 1
  println(num)

  // 配列
  val name = arrayListOf("tanaka", "yamada", "yamasita");
  println(name[0])
  println(name[1])
  println(name[2])


  // 条件分岐
  if (num > 10) {
    println("10より大きい");
  } else if (num == 10) {
    println("10と同じ")
  } else {
    println("10未満");
  }

  // 繰り返し
  for (i in 0..10) {
    println(i)
  }
}
```

## 参考サイト
https://kotlinlang.org/
[Rails][test] プロンプトのプログレスバーがうまく動かない場合の対処

Railsチュートリアルで行うテストでは、Gemのminitestとminitest-reportersを使います。
私の環境はWindows11で、ローカルで作業をしています。プロンプトはコマンドプロンプトを使っています。

- OS: windows11
- prompt: cmd
- Rails
- Gem: minitest
- Gem: minitest-reporters

minitest-reportersを使えば、Green/Redがわかりやすくなっていいのですが、私の環境ではプログレスバーの表示がおかしくなっていました。
本来１つであるプログレスバーがGreen/Redにかかわらず、テストの個数に応じて複数表示されてしまいます。

```プロンプト
たぶんこんな表示になるはず。
5/10[=====.....]
          ^ ここだけが進んでいくはず。


私の環境でのプログレスバー
1/10[=.........]
2/10[==........]
3/10[===.......]
4/10[====......]
5/10[=====.....]
プログレスバーがいっぱい出てくる。
```

あまりこのような現象になることはないかもしれませんが、私が行った対策を記します。

## minitest-reportersの設定
test/test_helper.rbにminitest-reportersの設定を書いていると思います。
そこにMinitest::Reporters::DefaultReporter.newを追記しました。

```test/test_helper.rb
# 修正前
require "minitest/reporters"
Minitest::Reporters.use!

# 修正後
require "minitest/reporters"
Minitest::Reporters.use! Minitest::Reporters::DefaultReporter.new
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                         ↑  ここを追記
```
結論としてはこれでプログレスバーが複数出ることはなく、見やすい表示になりました。

## 他にもいろいろ
test_helper.rbのMinitest::Reporters.use!の後に、
Minitest::Reporters::DefaultReporter.newを付ければ表示方法を変えてくれるようですが、
Minitest::Reporters::`DefaultReporter`.newのDefaultReporterの箇所は他にもあるようです。

- DefaultReporter
- SpecReporter
- ProgressReporter
- RubyMateReporter
- RubyMineReporter
- MeanTimeReporter
- JUnitReporter

自分にあったものを探してみると面白そうです。

## おわり
これで一画面にテスト結果が表示されるようになりました。テストがより楽しくなりますね。
私の目的は複数表示されてしまうプログレスバーを何とかすることなのでこれ以上深入りはしていませんが、下記のリンクではさらに詳しく書かれていますので参考になさってください。

https://github.com/minitest-reporters/minitest-reporters

下記のように複数指定することも可能とのことです。
```test/test_helper.rb
Minitest::Reporters.use! [Minitest::Reporters::SpecReporter.new, Minitest::Reporters::JUnitReporter.new]
```

ブロックでの設定も可能なようです。
```test/test_helper.rb
Minitest::Reporters.use!(
  Minitest::Reporters::DefaultReporter.new,
  ENV,
  Minitest.backtrace_filter
)
```

細かい設定はしておりませんし、英語のサイトをなんとなしに読んだ結果なので、間違いがあるかもしれません。
お気づきの点がありましたらコメント等でご指摘いただければ幸いです。
【備忘録】Python 基本

## pythonを実行
```sh
$ python ファイル名
$ python hello.py
```

## 基本構文
```python
# 出力
print("hello")

# 変数
hello = "hello world"
print(hello)

# データ型確認
print(type(hello))

# 配列
name =["tanaka","yamada"]
print(name[0])

#　条件分岐
age = 5
if age >= 20:
  print("adult")
elif age ==0:
  print("body")
else:
  print("child")

# 繰り返し
for i in range(10):
  print(i)
```
WordPressサイトの検索機能をURLから利用する方法

求めている記事やページが見つからない場合、通常は検索フォームを利用したり、Googleで検索することが一般的です。しかし、検索フォームが存在しない場合や、Googleにインデックスされていないコンテンツの場合でも、WordPressで構築されたサイトならURLを利用した検索方法で目的の記事やページを見つけることができることがあります。
※検索結果ページが用意されていない場合は、利用できないです。


パラメータの"s"に検索したいキーワードを与えることで、URLから検索することができます。
```
https://example.com/?s=キーワード
```
モノリシックから徐々にマイクロサービスへシフトしてみた

# 基本的欲求診断システム

システムエンジニアとして仕事をしながら、心理学を10年以上学んでおり、現在は講師業などもしています。その関係で、2年前から心理テストを作成してリリースしています。

https://peace-tea.jp/ct/basic-needs-survey/

無料で3分ほどで結果が出るのでぜひ気軽に使ってみてください。

# その裏側
さて、このシステムなんですが裏側は長年使い慣れたPHP & Laravelをベースにして構築しました。詳細な構成は以下の通りです。

![スクリーンショット 2023-03-25 17.20.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1926542/809e0d5d-645f-9756-0936-62a1770e0982.png)

シンプルといえばシンプルです😅

AWSのLightsail上に最小構成でLAMP環境を構築してLaravelをインストールしています。フロントはLaravel-vueプラグインをComposerでインストールし、画面からLaravelのControllerへはREST API経由で通信をする構成にしていました。

この構成だと以下の課題があります。

::: note warn
同一サーバにDBもフロントエンドも一緒になっているため、完全にモノリシックな構成になっている
:::

特にDBのメンテナンスなど運用負荷が高くなります（サーバコストは$3.5と安いんですけどね・・・）。

# 疎結合な構成へ変えてみた
今回、以下のような構成に変更してみました。

![スクリーンショット 2023-03-25 17.20.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1926542/f86083ea-063e-11f9-fe7d-d9cae7158837.png)

ポイントは以下の通りです
* Laravelからフロントエンドを完全に分離してVue.js3で再構成
* データベースをマネージドサービスであるLightsailDBに移動
* フロントエンドはAmplifyによりS3及びCloudFront上にホスティング

フロントエンドとバックエンドの通信をREST APIにしていたのでそこは何も変えずに済んでいます。

# よかった点
S3へのホスティングとCloudFrontを使ったCDNの構成があっという間にできるのでAmplifyはやはり便利ですね。データベースもマネージドサーバ上に置いたことで安心感が増しました。

フロントエンド、バックエンド、データベースを疎結合にしたので、それぞれ別にマイグレーションすることができるようになりました。例えば、LightsailDBからAmazonAuroraやDynamoDBへ切り替えるなどもできるでしょうし、フロントエンドもVueからReactに変更するなどもできるでしょう。

:::note
今回、LightsailサーバとCloudFrontのドメインは別ドメインにしたので、Laravel・S3・CloudFrontのそれぞれでCORSの設定をする必要は出てきました
:::

# 反省点
反省点は一気にフロントエンドに色々と改善を加えたので非常に手こずったことです。
* フロントエンドのデザイン刷新
* Laravel-vueから純粋なVueへのシフト
* Vue.js3へのバージョンアップ
* TypescriptとCompotisionAPIを利用

この辺を一度に盛り込んだので非常に時間がかかってしまったので、やはりマイグレーションはステップを踏んで行っていくべきですね。

# 今後の予定
次はバックエンドをLambaベースでサーバレス化する、またロジックもDDDベースで整理していくと面白そうです。
とはいえ、今のところあまりバックエンドを修正する必要性は低いので、しばらくはこのまま様子を見てみたいと思います。
ローカルのterrariaをCloudflare Tunnelと適当なvmで公開する

## 経緯
ローカルのサーバーPCに[Terraria](https://terraria.wiki.gg/wiki/Server#How_to_(Linux))をインストールした。
しかしポート開放はめんどくさいのでOracleCloudでvmを借りて、そこにCloudflare Tunnelで接続しnginxでリバースプロキシを建てることで解決した。

## ローカルTerrariaサーバーでのCloudflare Tunnelの設定
Cloudflare Tunnelのサーバー側の設定は[公式ドキュメント](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-guide/remote/)に従ってDashbordのAccess→Tunnelsから行った。
ここで設定するホスト名はOCIから繋ぐ用なので適当な名前にしといたほうがいい。

## OCIのvm上でのCloudflare Tunnelの設定
OCIのvm上でcloudflaredをインストールし、以下のコマンドでローカルのterrariaサーバーと接続する
```sh
cloudflared access tcp --hostname ここにホスト名 --url localhost:6666
```

## nginxの設定
aptでnginxをインストールし、`/etc/nginx/nginx.conf`の`include`の下に以下を追加する
```
stream {
    server {
        listen 7777;
        proxy_pass 127.0.0.1:6666;
    }
}
```
設定ファイルの検証
```
sudo nginx -t
```
nginxを再起動する
```
sudo nginx -s reload
```
## iptablesの設定
OCIのubuntuではiptablesでポートがブロックされているため開ける
```
sudo iptables -I INPUT 5 -p tcp --dport 7777 -j ACCEPT
```
設定を適用する
```
sudo /etc/init.d/netfilter-persistent save
sudo /etc/init.d/netfilter-persistent reload
```
## OCIのセキュリティ・リストの編集
対象vmのサブネットからセキュリティリストの編集→イングレスルールを追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593714/67c0fa5e-d755-037b-7437-03a84e90a42f.png)

## (任意)OCIのPublic IPにドメインを紐づける
OCIのIPを適当なドメインのAレコードとして登録するといろいろ嬉しいのでやっておく

## おわり
多分これで繋がるはず。詰まったら[@honahuku](https://twitter.com/honahuku)にでも声をかけてみてください
アラサーOLが学ぶExcel初心者講座

初めてのIT業界に携わる前にExcel習得に励もうということで、
備忘録をかねて勉強した事をメモしていこうと思います。
間違えている所やオススメの方法があれば教えていただけると嬉しいです🌸

**はじめに**
・Excelをピン留めしてショートカットを作成
・Excelの事を本来は「ブック」というが、通称は「Excelファイル」。
・Excelファイルを開き、空白のブックを選択

**Excel機能の名称**
・クイックアクセスツールバー：Excel最上部にあるアイコンのこと。「上書き保存、戻る↩、進む↪」がデフォルトで表示されている
・タイトルバー：Excelファイルの名前が表示される。新規作成時のデフォルトでは「Book1 - Excel」と表示
・タブ：「ファイル、ホーム、挿入･･･ヘルプ、検索」まで
・リボン：別のタブを選択するごとに表示される細々とした項目のこと。
・グループ名：別のタブを選択するごとに表示される大まかな項目名のこと。
→デフォルト表示の「ホーム」タブに対し、グループ名「クリップボード」には「貼り付け」というリボンがあったり、グループ名「フォント」には「ゴシック」「太字」など、グループ名「配置」には「上下中央揃え」というリボンがあったりする。
※コマンド（タブやリボンなど）が見つからないという場合には、Excelを最大化表示しているか？を確認する。最大化しても見つからない場合は、ディスプレイの大きさや解像度の違いが関係している。

**ワークシートとセル**
・シート：デフォルトで「Sheet１」が用意されている。シート名は変更できる。
　→シートを沢山追加できるので、それをまとめてブック（本）と呼ばれている。
・シート見出し：シート名のこと。

・アクティブセル：選択されているセルのこと。
・スクロールバー：ドラッグしたり右端や下の方を見る事ができるようになる。

・ズームスライダー：画面の表示サイズを変更できる。ー（マイナス）選択で縮小、＋（プラス）を選択で拡大できる。
・ズームのダイアログボックス：右下の「100％」を選択する事で表示できるボックス。ズームサイズを倍率を変更する事ができる。

・列：A、B、C・・・と縦軸を「列」とよぶ。
・行：左端にある1，2，3に沿って横軸を「行」とよぶ。

・名前ボックス：現在アクティブなセルがどこかが分かる。
・数式バー：入力された内容が分かる。
（例）A１セルに「＝3+7」と入力しEnterを押すと、A1セルに「10」と表示される
　　　しかし、もう１度A1セルを選択すると数式バーに「=3+7」と入力されている事がわかる。


**1⃣データ入力**
・Deleteキー：入力された情報を削除できる
・半角/全角：
　右下に「A」と表示されていたら、「半角」
　右下に「あ」と表示されていたら、「全角」
・文字と数字：
　文字が入力された場合は、「左寄り」
　数字が入力された場合は、「右寄り」に表示される。
・**F2キー**：
　マウスでダブルクリックと同じように、選択したセルを入力モードにすることができる。
　Enterで入力情報を確定したセルに対し、再度セルを選択してF2を押すとセルを再編集できる。
・BackSpaceとDeleteキー：
　カーソルより前の文字を消したい時は、「BackSpace」を
　カーソルより後ろの文字を消したい時は、「Deleteキー」を使用する

　また、入力後にEnterで確定されたセルを再度選択し（カーソルキーがない状態で）
　Deleteキーを押すと入力された情報を全消去する事ができる。

・リターン矢印（ ↰ ）：
「消去する前に戻したい」、「入力前に戻したい」といった時は、
　Excel最上部にあるクイックアクセスツールバーのリターンキー「 ↰ 」を使用するか
　ショートカットキー「Ctrl」+「z」を同時に押す事で対応する。

**シート名の変更、シートの追加・移動・削除**
・シート名の変更：
シート名「Sheet1」をマウスでダブルクリックする or 
シート上で右クリックから「名前の変更」を選択する。

・シートの追加：
デフォルトで生成される「Sheet1」横の「+」を選択する。

・シートの移動：
マウスでのクリックとドラッグで移動できる。
どこに移動するかは黒い線で確認する。

・シートの削除
A1セルに「123」と入力後、シート上で右クリックからシートの削除を選択。
すると、ポップアップで”シートを削除しても良いですか？”と聞かれるので「はい」を選択。
→何か入力している場合、このポップアップが出るので、「はい」を選択し削除できる。
※シートの削除は元に戻す事が出来ないので注意すること

**ファイルの保存、Excelの終了・ファイルの確認**

・ファイルの保存：
　初めてファイルを保存する場合に使用する。「名前をつけて保存」を選択する。
　次から保存時は、「上書き保存」を選択する。
・ファイルを閉じる：
　右上の赤い×ボタンを押してファイルを閉じる事ができる。
・ファイルの開き方：
　開きたいファイルをダブルクリックまたは、ファイル上で右クリック→このファイルを開くを選択。

**オートフィル**
・オートフィル：自動で規則的な値を連続入力してくれる機能。
（例）
　A1セルに「1月」と入力しEnter。
　→A1セルを選択して、セルの右下の所にカーソルを合わせると「+」と表示される
　→「+」の状態でマウスをクリックして、そのまま下へドラッグすると
　→縦に「1月」「2月」「3月」･･･と表示される。

（Other）
・「10」「20」と入力し、この2つを「+」でドラッグする方法
　→「10」「20」「30」・・・（10ずつ増えるデータ）
・「東京」「大阪」「名古屋」を入力し、この3つを「+」でドラッグする方法　
　→「東京」「大阪」「名古屋」・・・(3単語が順に連続で記載されるデータ)

※連続で入力されない場合、「オートフィルオプション」を活用する。


**疑問**
(あとで調べる予定のメモ)
・？ショートカットキーによるアクティブセルの移動とは？
・？オートフィルオプションを使わないで連続データを表示する方法とは？

**感想**
・普段なにげなく使っている項目の名称を知ることができた
・既に入力済のセルを編集時、F2キーの活用はすごく便利だと思う。ショートカットキーと合わせて活活用していきたい。
・ここまで、分かりやすかったのでどんどん習得していきたい。
Railsチュートリアル第11章：Missing host to link to! Please provide the :host parameter

このようなエラーが

~~~
Failure/Error: <%= link_to "Activate", edit_account_activation_url(@user.activation_token,
     
     ActionView::Template::Error:
       Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true
~~~

どうやらホストが見つからないことが原因らしい。
チュートリアルの中では次の1文を追加したのだが、、、
~~~
config.action_mailer.default_url_options = { host: 'example.com' }
~~~

30分くらいかけてようやく気付いた。
追加する場所を間違っていた。

僕はここ
config/environments/development.rb

正解はここ
config/environments/test.rb

テストでエラーが出ているので環境もテストのところをいじるのは当たり前だろう
JavaScriptを初めて学ぶ２

・配列
１つの変数に対して、複数の値を入れれる。また要素にインデックス(検索機能的なやつ)でアクセスできる。インデックスは０から始まる

例えば

```javascript
const favariteArea = ['Hokkaido', 'Osaka', 'Fukuoka', 'Kyoto']; //配列を定義
console.log(colors[0]); //0はHokkaidoを取り出してる
console.log(colors[1]);
console.log(colors[20]); //範囲外はundefinedって出る
```

と言う風に一つのボックスに色んなの入れて取り出すみたいなイメージ

```javascript
const favariteArea = ['Hokkaido', 'Osaka', 'Fukuoka', 'Kyoto']; //配列を定義

for (let i=0; i<favoriteArea.length; i++){
    console.log(favoriteArea[i]);
}

```
したら、Hokkaido, Osaka, Fukuoka, Kyotoって出る
favoriteArea.lengthで配列の長さを取得。cosole.log(favoriteArea.length)って打ったら,４って出る
i<favoriteArea.length;は、iが４未満てこと。
また、i=0始まりなのに注意
これを使うと配列の長さが変わってもコードを変更しなくていいのが利点

・連想配列
各要素を文字列キーでアクセス可能な配列。Hashって呼ばれてたりもする

```javascript
const ichigo={name:'黒崎一護', age:'15歳',hairColor:'オレンジ', eyesColor:'ブラウン'};
console.log(ichigo.name);
console.log(ichigo.age);
console.log(ichigo.hairColor);
```
そしたら
黒崎一護、15歳、オレンジって出る。病院の待合室みたいなコードだなあ
DeploymentとStatefulSetのPodのスケールと更新のストラテジーの違い

KubernetesにはPodを管理するリソースとして、DeploymentとStatefulSetの2つが挙げられます。これらのPodのスケールと更新のストラテジーにおける違いについてまとめると次の表のようになります。

||Deployment|StatefulSet|
|:--|:--|:--|
|スケール|なし|OrderedReady or Parallel
|更新|RollingUpdate or Recreate|RollingUpdate or OnDelete|

## Podのスケール

DeploymentはPodをスケールする時、選択できるストラテジーはありません。Podの数を増減する場合には常に並列的に行われます。実際、DeploymentがPodを増減しているのではなく、Deploymentが管理しているReplicaSetが行っているのであり、この動作はReplicaSetによるものです。

一方で、StatefulSetはOrderedReadyとParallelの2つのストラテジーがあります。Deploymentと異なり、StatefulSetはPodを直接管理しています。

- OrderedReadyはReadinessProbeを監視しつつ、一つずつPodを増減します。
- ParallelはDeploymentのスケールと同様、Podを並列的に増減させます。

## Podの更新

DeploymentはRollingUpdateとParallelの2つのストラテジーがあります。

- RollingUpdateは段階的に古いPodから新しいPodへ以降する方法です。ダウンタイムは発生しないので本番環境では積極的に使われるストラテジーだと思います。
- Recreateは全てのPodを一度に削除し、一度に作成する方法です。Podの数が0になる時間が発生するのでダウンタイムが発生します。

StatefulSetもRollingUpdateとOnDeleteの2つのストラテジーがあります。

- RollingUpdateは一つずつPodを更新する方法です。Deploymentと同じ名前を持つストラテジーですが、Deploymentは任意の数で更新できるのに対し、StatefulSetは一つずつであるという違いがあります。
- OnDeleteは手動で削除されたPodが更新される方法です。更新をよりコントロールしたい場合、こちらのほうが適切でしょう。
ETLツール pentaho（spoon）の環境設定紹介

* spoon は Excel、csv、各種DB などのデータソースの読み込み、http リクエスト、httpレスポンス（json）に対して処理が出来る ETL ツールです。
* GUI でパーツを組み合わせてETL処理を組み立てます。
（SQL、java、javascript などのコードを書くことも出来ます。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/890a7667-222e-90c7-5878-c00fed6a194d.png)
* そのまま使っても良いですが、業務などで使う場合環境設定をする事で更に便利に扱えるので環境設定方法についてまとめています。

|記事内で使用する環境|ダウンロード先
|-|-
|pdi-ce-9.3.0.0-428|https://sourceforge.net/projects/pentaho/files/Pentaho-9.3/client-tools/<br>・pdi-ce-9.3.0.0-428.zip	
|openjdk version "11.0.2" 2019-01-15|https://jdk.java.net/archive/<br>・11.0.2

* [環境準備](#環境準備)
* [起動](#起動)
* [プロパティの設定](#プロパティの設定)
* [その他設定](#その他設定)

# 環境準備
* java の配備
今回は下記場所へ配備しました。
`C:\java\jdk-11.0.2`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/c215d0c9-27c2-f95a-2ef5-91edcd0d3ede.png)
* pdi の配備
今回は下記場所へ配備しました。
`C:\PDI\data-integration`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/fae27936-fe95-743e-9633-27ffd9c10d32.png)

# 起動
* 環境変数の JAVA_HOME に java ディレクトリが設定されていれば、
data-integration\Spoon.bat を実行するだけで spoon が起動します。
* 今回は KETTLE_HOME を設定して、本番環境・検証環境ごとにプロパティを分離して起動します。

1. `C:\PDI` に下記の .bat を作成して起動します。
    ```preSpoon.bat
    cd /D %~dp0
    SET KETTLE_HOME=C:\PDI\config\PRE
    SET JAVA_HOME=C:\java\jdk-11.0.2
    data-integration\Spoon.bat
    ```
    ```proSpoon.bat
    cd /D %~dp0
    SET KETTLE_HOME=C:\PDI\config\PRO
    SET JAVA_HOME=C:\java\jdk-11.0.2
    data-integration\Spoon.bat
    ```

# プロパティの設定
1. spoon が開いたら `Ctrl + Alt + P` で `kettle.properties` を開きます。（または「編集」→「kettle.propertiesファイル編集」）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/ba303f4c-b924-dd9c-c0c5-956e6dd98afe.png)

1. kettle プロパティに接続環境の情報を入力します。（PW は後ほど設定します。）
下記は例として postgreSQL のプロパティを設定。
事前に postgreSQL で spoonPre DB を作成済み。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/d03c136d-d94d-e5f6-584f-0be2df72a5ad.png)
    * `C:\PDI\config\[PRE or PRO]` 配下に
`.kettle\kettle.properties` が作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/b7bf39ea-b72e-55fa-d138-98afcb12891c.png)

1. 「ジョブ」→「データベース接続」の順に選択する。
    1. 「接続名」に適当な名前を入力する。
    1. 「ホスト名」「データベース名」「ポート番号」「ユーザー名」に `kettle.properties` で設定した環境変数を設定します。
    1. 「パスワード」を入力します。
    1. 「テスト」を選択すると、接続テストが実施出来ます。
    1. 最後に「OK」を選択して、ジョブ（.kjb）を保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/b7219f3d-a813-7de6-5377-e5b789a106c0.png)

1. 「データベース接続」→「共有」をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/5039ca22-7498-80f0-23f1-8a551a1cbf50.png)
    * 「共有」する事で .kettle\shared.xml に DB 接続情報が保存されて spoon 起動時に接続情報が読み込まれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/a02c12d8-b421-c7c3-37a6-c1bb53116acd.png)

# その他設定
便利だと感じた設定をまとめています。
* カラー変更
`.kettle\.spoonrc` を変更すると spoon のカラー変更が出来ます。
本番環境：🟥系、検証環境：🟩系などにしておくと起動後に一目で判別しやすいのではないかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424166/1b988765-ab60-f17c-d3f8-c731892866c8.png)
sqlite3で、sqliteファイルをまたいでテーブルをJOINすることはできますか?

はい、SQLite3では複数のSQLiteファイル間でテーブルをJOINすることができます。そのためには、次の手順を実行します。

1.  まず、各ファイルを別々に接続します。これは、それぞれのSQLiteファイルを開き、.openコマンドを使用して接続することによって行います。例えば、以下のコマンドで2つのファイルを接続します。

```
sqlite3 file1.db
sqlite3 file2.db
```

2.  次に、各ファイル内のテーブルをJOINするクエリを作成します。これは、通常のJOINクエリと同じように実行します。例えば、次のクエリで2つのファイル内のテーブルをJOINしています。

```vbnet
SELECT *
FROM file1.table1
JOIN file2.table2
ON file1.table1.column = file2.table2.column;
```

3.  最後に、クエリを実行します。このクエリを実行する前に、.openコマンドでファイルを接続しておく必要があります。

注意：各ファイル内のテーブルに重複する列名がある場合は、テーブル名を列名の前に付けて列を参照する必要があります。例えば、上記のクエリで両方のテーブルに"column"という名前の列がある場合、クエリ内で "table1.column"と "table2.column"という形式で参照する必要があります。
MySQL完全削除方法

## 前提
OS：Ubuntu20.04.3LTS

マシンにインストールしたMySQLを削除したい時に、依存ファイル等も含めて完全に削除して、
同じマシンに再度インストールするための参考記事になります。

MySQLのDBサーバが起動中に、マシンに対する大量リクエスト等でマシンがダウンしてしまった場合に、
MySQLが破損し、起動できなくなってしまう場合があります。

MySQLをアンインストールして、MySQLをマシンに再インストールする場合に、
Sudo apt-get remove —purgeをして削除しただけでは、依存ファイル等を削除することができず、
結果、再インストールしたMySQLを起動できなくなってしまいます。


## MySQL削除手順
```bash:bash(Ubuntu20.04.3LTS)
Sudo apt-get remove —purge mysql-serer* mysql-common
Sudo apt-get auto remove —purge
Sudo rm -r /etc/mysql
Sudo rm -r /var/lib/mysql
```
上記のコマンドを順番に入力することで、依存ファイルも含めて関連ファイルを全て完全に削除することができます。

※この記事は、データバックアップの手順は含まれていません。データバックアップが必要な場合は、
先にデータバックアップを実施してください。