OmniAICreator/Qiita-1.07M huggingface dataset:
Eclipse ZenohでNAT越えROS2通信

ROS2でNAT越えするのって何かいい手段無いかなぁと探していた際に見つけたものです。

https://zenoh.io/

https://github.com/eclipse-zenoh/zenoh

よくある＊MQ系の何かと思いきや、もうちょっと融通が利いていろいろとできそうな雰囲気が伝わってきます。ROS2のPluginもあり、Rust, C, Python, Javaと言語Bindingも揃っているようです。

今回は、クラウド上にZenohのRouter（サーバ）を立てて、2PC間でROS2通信させてみます。

# サーバ
zenohのインストールを行います。aptでも入るのですが、zenoh-bridge-ddsのバージョンと整合しないため、ソースからビルドしていきます。

Rustのビルド環境が必要となります。以下コマンドで入ります（Rustのインストールってこんな簡単でしたっけ・・めっちゃ楽です。参照：https://www.rust-lang.org/ja/tools/install ）
```:Rust環境構築
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
```
また、ビルドにはClangが必要となるため、apt等でインストールしておいてください。
```:clang インストール
sudo apt install -y clang
```

[zenohのgithubリポジトリ](https://github.com/eclipse-zenoh/zenoh)から最新の[Release](https://github.com/eclipse-zenoh/zenoh/releases)のタグを指定してをソースを取得します。この際、後述のzenoh-bridge-ddsとバージョンを揃えるようにしてください。
```:githubからソースを取得
git clone https://github.com/eclipse-zenoh/zenoh.git -b 0.6.0-dev
```
ビルドには結構時間が掛かります。ゆっくりお待ちください。
```:ビルド
cargo build --release --all-targets
```
./target/release/　以下に一通り成果物が生成されます。
```:Routerの起動
./target/release/zenohd
```
サーバの設定は以上です。なおポートは7447を通す必要があるので、適宜開けてください。

# クライアント
こちらもRust環境、clangが必要です。上記と同様にインストールしてください。

```:githubからソースを取得
git clone https://github.com/eclipse-zenoh/zenoh-plugin-dds.git -b 0.6.0-dev
```
```:ビルド
cargo build --release -p zenoh-bridge-dds
```
```:起動
./target/release/zenoh-bridge-dds -e tcp/サーバのIPアドレス:7447
```
この状態でもう一枚ターミナルを開き、ROSアプリを動かします。
```:Talker
ros2 run domo_nodes_cpp talker
```

上記の設定を別PCでも行い、同様にListenerを動かします。
```:Listener
ros2 run domo_nodes_cpp listener
```
以上で本当に何の苦労もなくNAT越えROS2通信が行えてしまいます。

今回はROS2のbridgeに絞ってしまいましたが、Zenohは様々な機能を持っているようです。また、組込み向けの軽量実装もあるようです。
今後もいろいろ試してみたいと思います。
SORACOM CLIを多要素認証で利用する（--mfa-otpcodeオプション）

タイトルの件をSORACOM Air SIMのリストを一覧するコマンドを使って例示します。

```shell
#!/bin/bash

# 認証に必要なパラメータを取得
read -p "Enter OP ID : " op
read -p "Enter SAM User : " sam_user
read -p "Enter SAM Password : " sam_pass
read -p "Enter OTP : " otp

# API KeyとAPI Tokenを取得
auth=`soracom auth --operator-id ${op} --user-name ${sam_user} --password ${sam_pass} --mfa-otpcode ${otp}`
api_key=`echo ${auth} | jq -r .apiKey`
token=`echo ${auth} | jq -r .token`

# --api-keyと--api-token オプションを付けコマンドを実行する
soracom sims list --api-key ${api_key} --api-token ${token}
```

# 参考

https://users.soracom.io/ja-jp/docs/mfa/usage/
(105期) 2021/7〜2022/1 テックキャンプ受講感想

### 目次
テックキャンプを無事卒業したので、以下について感想を書きます！
- 結論
- よかった点
- 改善されるといいな!と感じた点
- 受講前に感じた不安や疑問→どうなったか


### 対象期
105期生
学習期間：2021年7月〜2022年1月
就活期間：2022年1月〜2022年3月

### 個人的な結論
「プログラミングを習得する」、「転職成功させる」ではなく、
「人生を好転させたい」なら、テックキャンプがいいと感じた。

無料カウンセリングと、14日間保証を使って、
「まず試しにやってみる」という選択もアリじゃないかと思った。

どのスクールがいいか、そもそもスクールを使うか、の選択より
選んだ選択を正解にするか、が大事で
おそらくそれには自責思考で進めることがポイント。(自分次第)


### 良かった点
- 今まで受けた中で、一番最高のサービス
担当LCも、CAも、全メンターも、関わったすべての人の対応が真摯だった。
divの理念やビジョンに、皆さん共感して仕事をされているんだろうなと、強く感じた。
メンターの方は、絶対わかるようになるまで付き合ってくれるし、
LCは、学習以外の個人的な不安・相談にも快く乗ってくださるし、
CAは、エージェントとは比べ物にならないレベルでサポートしてくれた。

サービスを通して感じたのは、
プログラミングのカリキュラムを終わらせるとか、IT企業に転職させるとか、ではなくて
その人の人生を幸せにする機会を提供することに、皆さんが全力投球してくださっているという事だった。

- 挫折させない
独学時は、なぜなぜなぜ・・・と突き詰めた疑問は解消できず諦めていたが、
テックキャンプではわかるまでメンターが付き合ってくれた。
だから、一人ではたどり着けなかった答えにたどり着けた。

学習中に、モチベーションや自己肯定感が低下してしまう事があっても、
週1のLC面談で悩みを相談し、解決することで、学習の挫折をせずストレートで終了できた。
なんでも相談できる、真摯に悩み相談に乗ってくれる人が1人いる存在の大きさを実感した。

転職活動に関しては、面接でお祈りを量産して、PGになってもよいのか悩んでいた時期に
「PG転職をした方がいいとも、しない方がいいとも思わない。
ただ、今後の◯◯さんの人生がより幸せになれる選択を一緒に考えよう。」
と、担当CAの方に言葉をかけてもらえて、挫折せず転職成功できた。


- 独学では挫折してできなかった「0からアプリをつくる」ができるようになった
「こういうものがつくりたい」というイメージを、実際にオリアプで具現化できて、嬉しかったし、つくれる技術を学べたと感じた。

- 卒業生の受け入れ実績のあるIT企業に、PGとして転職できた
はじめはPG以外の職種から〜ではなく、ちゃんとエンジニア転職ができた。
- 自分をメタ認知できた
ダメだダメだ、と思っていた自分の性質も、使いようがあるなと思えるようになった。
LCやCAと話す中で、ふと気づく事が多かった。
これは個人的には大きな副産物だった。


### イマイチな点
ここも改善されたら、もっと最高になるなーと感じた点です。

- 表記方法
    - 期日系は、書き方がちょっと分かりづらいな・・・と感じた
    - 時間割学習日変更期日/提出物期日/slack使用可能期日等・・・
 
→これで合ってるのか？と、思ったので、逐次LC/CAに確認していました。
汎用的にするには仕方ない面もあると思う反面、「ん？」となることが多かったです。笑


- 質問画面のUIの改善
    - 質問が多いと、動作が不安定になる
    - 投稿した質問の編集がし辛かった
    - 通話中は、投稿内容の表示面積が狭く説明し辛い
    
→私は、notionを併用して質問することで解決していました。
→動作不安定のときは、ZOOMなどで対応してくれました。

- 質問中のタイムロス
    - メンターさんが、回答の答え調査中の間、PCが操作不可になるのが辛かった

→これは細かい内容や、テキスト外の質問をしたときにことなので、こちらの質問内容によっては仕方ないものだと思っています。
ただ、仕組みとして、学習が止まらないサービス設計だと、もっと質問のハードルが下がったかなーと思いました。

- 紹介求人の情報
    - 補足情報で、少し古いものがあった
    - 求人によって、ある情報、ない情報がある

→ご時世的に、リモートか実地面接か、フル明記されてると、もっとよいなーと感じました。
→あとは、求人の内容を面接担当者に聞くと、今はちょっと変わってて〜ということがあったので、
　　ちょくちょく更新されるような仕組みもあれば、いいのかなーと思いました。


### 受講前に感じた不安→どうなったか
- そもそも独学でできずにスクールに頼る方法でPGになっていいんだろうか
    - 独学で時間を浪費するより、さっさとスクール活用して、最短で転職した方がよかった
    - 新しいスポーツしよう！と思ったら、どっかに習いに行くのと一緒で選択の１つではないか
    - 独学で挫折して諦めるくらいなら、どんな手を使っても、まずスタートラインに立つ方がいい！
- 自分にできるかな・・・
    - 結論、できた
    - 環境(整備されてるカリキュラム/ルール/締め切り/助けてくれる人)があるので大丈夫
- 地方住みだが、就活大変なのでは
    - ご時世的にリモート面接が多かったので、私は実地面接1回だけだった


### まとめ
受講前に目標にしていた、「こういうものがつくりたい」の具現化、
IT企業にPGとして転職ができたので、結果としては良かった！と感じている。

職業訓練給付金対象前に受講したので、受講費はやっぱり高いと感じるが、
そこは転職先で頑張って投資の回収をしていきたいと思っている。

サービスの質に関しては、本当に感動した。
全従業員の方が理念に共感して働らいていると感じ、
divという会社に対しても、素敵な会社だなと感じた。

何にせよ、これから実務も、学習も積み重ねていく事が大事だし、
それは自分次第なので頑張っていきたい。
C言語 close()でRST送信する


## 0.概要
C言語実装において、ネットワークソケットに対してclose()をコールすると通常FINが発行されるが、TCPコネクションがTIME_WAITになって処理が遅いなどRSTで強制切断したい場合がある。

## 1.方法
ソケットに対して、ソケットオプションSOL_SOCKET, SO_LINGERを設定する。
linger on, タイムアウト値0にするとRSTが送信される。

```c
int force_close(int sock)
{
	int ret = 0;
	struct linger ling;

	memset(&ling, 0, sizeof(ling));
	ling.l_onoff = 1;  /* 0以外でon, 0でoff */
	ling.l_linger = 0; /* 0で即時切断。0以外は指定時間(秒)でタイムアウト */

	ret = setsockopt(sock, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling));
	if(ret != 0) {
		printf("setsockopt:%s\n", strerror(errno));
	}
	ret = close(sock);

	return ret;
}
```
[App Service]Web AppsとAPI Appsの違いとは

# はじめに

```txt
App Service
  |-web apps
  |-API apps
```

上記の関係前提で喋ってます。間違ってたら指摘ください。

## やりたいこと

SpringBootとか、Expressを使用して、Azure上にAPIサーバを作りたい

## 記事を書いた経緯

やりたいことの実現方法を調べていると、AzureにはWeb AppsとAPI Appsなるサービスがあることを知りました。ただ、ぱっと見は名前とアイコン以外に違いはあるのかよく分からなかったので、ちょっと書き残しておきます。

# 公式ドキュメント

[Azureのドキュメント](https://docs.microsoft.com/ja-jp/azure/?product=web)では、API AppsもApp Serviceも、下記[App Service のドキュメント](https://docs.microsoft.com/ja-jp/azure/app-service/)にリンクします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647946/2c4ce245-9cae-e2dd-f45d-cb9431c18a46.png)

https://docs.microsoft.com/ja-jp/azure/app-service/

# 結論

できることは一緒
※2022/5/17時点の意見

私はAPI appsを使ったことがないので、ネットで調べた情報だけで判断してますが、それぞれに「強み」はあれど、できることは「一緒」なのかなあ、というのが結論です。

## 個人的にわかったこと

### 本当に違いがなさそうだなあ

[API AppsのOverviewページ](https://azure.microsoft.com/ja-jp/services/app-service/api/#documentation)のドキュメントリンクは、すべてApp Serviceのものに繋がってる

### 認証の種類

AzureADは知ってたけど、下記プロバイダのサポートもあったのは初めて知った。

* [Facebook](https://developers.facebook.com/docs/facebook-login)
* [Google](https://developers.google.com/identity/choose-auth)
* [Twitter](https://developer.twitter.com/en/docs/basics/authentication)
* [OpenID Connect](https://openid.net/connect/)

## 想定される使い分け

[参考](#参考)2より
>When your business application has got multiple UI components to be compatible with Mobile and desktop interfaces, the UI applications can be hosted in the Mobile App and Web App respectively. However, the underlying business logic needs to be severed from a common source to maintain consistency. In this scenario hosting the business tier in an Azure API App will be the best solution.

モバイル・デスクトップのインターフェースに適応した、複数のUIコンポーネントを持つフロントエンドアプリケーションは、それぞれMobile AppとWeb Appにホストすることができる。しかし、ビジネスロジックは一貫性を保つために切り離す必要があり、このようなシナリオではビジネス層をAzure API Appにホストするのがベストプラクティスとなる。

うーーん……それこそWeb Appsでもいいのでは😂

# 参考

1. [Azure API App vs Web App](https://www.serverless360.com/blog/azure-api-app-vs-web-app)
2. [What is the difference between an API App and a Web App?](https://intellipaat.com/community/1183/what-is-the-difference-between-an-api-app-and-a-web-app#:~:text=An%20API%20(Application%20programming%20interface,easily%20with%20the%20other%20programs. )
2. [Azure App Service および Azure Functions での認証と承認](https://azure.microsoft.com/ja-jp/services/app-service/api/#documentation)
Heroku利用方法[Windows]

# 目次
1. 事前準備
1. Herokuの利用
1. Herokuの運用
1. データベースの利用

# 1. 事前準備

### Gitインストール
>[こちら](https://www.curict.com/item/60/60bfe0e.html "Gitインストール詳細")を参考にしながら、Gitをインストールします。
私はすべてデフォルトでインストールしました。

### Herokuアカウントを作成
>[こちら](https://jp.heroku.com )から、「無料で新規登録」より作成できます。

### HerokuCLIインストール
>[こちら](https://devcenter.heroku.com/ja/articles/heroku-cli)からインストールできます。
CLI -> Command Line Interface

# 2. Herokuを利用
### Heroku環境構築
>```bash
>heroku login  # ログインページが起動するので、アカウントを入力する
>heroku create <アプリ名>  # アプリを作るフォルダーを作成する
># 環境変数の設定
>heroku config:set <ValiableName>=<"設定する値"> --app <アプリ名>
>```

### 作成したアプリをHerokuに上げる
特定のフォルダーに移動し、以下を実行。
>```bash
>git init  # 共有レポジトリ新規作成
>git add .  # フォルダ内のすべてをコミットするデータとして予約する
>git commit -m "My first commit"  # 変更データ保存
>heroku git:remote -a <APP NAME>    # Herokuとgitを結びつける
>git push heroku master # Herokuへ送信
>```

### ログの確認
エラーでも色が変わらないので注意する。
>```bash
>heroku logs --app <アプリ名>  # アプリのログを表示する

# 3. Herokuの運用
### 作成したアプリのソースコードを取得
>```bash
># ローカルに複製
>heroku git:clone --app <アプリ名>
># 最新データを取得
>git pull
>```

### 変更を反映させる
>```bash
>git add .    # フォルダ内すべてをcommit予約
>git commit -m "Second_commit"    # 変更をレポジトリへ保存
>git push heroku master    # Herokuへ送信
>```

# 4. データベースの利用
Herokuでは※1sqliteが使えないので、Postgresを利用する。
※1.Herokuは定期的にに最後にcommitした状態に戻るため、作成された.dbは消える。

### データベースの作成

https://qiita.com/shosho/items/5ebabf11efb1f3b604f7
【SwiftUI】SwiftUIでUIKitを使う

## はじめに
基本的にSwiftUIを中心にいじっているのですが、
たまにUIKitの部品を使うことがあるので、使い方を備忘録として残します。

## 環境
- Swift: version 5.6
- Xcode: Version 13.3.1 (13E500a)
- macOS: 12.3.1 (21E258)

## 使い方

### 1. UIViewRepresentableプロトコルを適合させる
SwiftUIのUI部品は構造体で定義されていますが、UIKitのUI部品はクラスで定義されています。
そのため、型が異なるのでそのままでは使用できません。
SwiftUIでUIKitのUI部品を使うためには、`UIViewRepresentable`プロトコルを利用します。

```swift: UIKitLabel.swift
import SwiftUI

struct UIKitLabel: UIViewRepresentable { //UIViewRepresentableに適合
}
```

#### UIViewReporesentableプロトコルとは？

UIKitやMapKitなどのViewをSwiftUIのViewとして使うためのラッパーです。
`makeUIView(context:)`と`updateUIView`を実装する必要があります。

### 2. makeUIView(context:)メソッドを実装する

続いて、必須メソッドの1つである`makeUIView(context:)`メソッドを実装します。

```swift: UIKitLabel.swift
import SwiftUI

struct UIKitLabel: UIViewRepresentable {
    //表示するViewを作成するときに実行
    func makeUIView(context: Context) -> UILabel {
        print("makeUIView") //後で動作確認する用
        let uiLabel = UILabel()
        return uiLabel
    }
}
```

#### makeUIView(context)メソッドとは？

`UIViewRepresentable`プロトコルの必須メソッドの1つ。
UIKitのUI部品を生成するメソッドで、画面が描写される前に一度だけ実行されます。
今回は`UILabel`を使用しました。

### 3. updateUIView(_:)メソッドを実装する。

同様に、必須メソッドの`updateUIView(_:)`を実装していきます。

```swift: UIKitLabel.swift
import SwiftUI

struct UIKitLabel: UIViewRepresentable {
    var text: String

    /*省略*/

    //表示したViewが更新するたびに実行
    func updateUIView(_ uiView: UILabel, context: Context) {
        print("updateUIView")
        uiView.text = text //引数で受け取ったtextをセット
    }
}
```

### updateUIView(_:)メソッドとは？

`UIViewRepresentable`プロトコルの必須メソッドの1つ。
makeUIView(context)で生成したViewを更新するメソッドです。

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

## 動作確認

さきほど作った`UIKitLabelView`を使ってみます。

```swift: ContentView.swift
import SwiftUI

struct ContentView: View {
    @State var text = ""
    var body: some View {
        VStack {
            Text("▼ UILabel ▼")
            UIKitLabel(text: text) //通常のSwiftUIのUI部品と同様に使える。
                .frame(height: 50)
                .border(Color.gray)
            Text("▼ TextField ▼")
            TextField("テキストを入力", text: $text)
                .padding(5)
                .border(Color.gray)
        }
        .padding()
    }
}
```

シミュレータで実行してみます。
![スクリーンショット 2022-05-17 14.10.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/fbe82ebd-3e0b-9f4c-844d-3697d930f59c.png)
起動直後のコンソールを確認してみると、
`makeUIView(context)`と`updateUIView(_:)`が実行されているのが分かります。
![スクリーンショット 2022-05-17 14.19.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/6a233b3b-bf7a-66fe-cfe1-c9d33d227a1d.png)
テキストフィールドに文字を入力します。
![スクリーンショット 2022-05-17 14.21.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/ae383497-23e2-c7fe-26bc-7c86ccd529c9.png)
文字入力の度にViewが更新され、`updateUIView(_:)`が実行されているのが分かります。

![スクリーンショット 2022-05-17 14.26.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/0528e6c2-9c98-9461-f3dc-5bec10f368b3.png)

## さいごに
SwiftUIでUIKitを使う方法をまとめました。
さいごまで見ていただきありがとうございました。

## 参考書籍

https://ticklecode.com/swiftbook2020/
UE4 exe、dumpファイル関連


https://qiita.com/donbutsu17/items/76ea5c5531aa4da77f9d


https://historia.co.jp/archives/4496/

# pbdファイルの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/6638f835-ae49-dc1f-b0cc-6d54981f5185.png)
* ProjectSetting>Packaging>Include Debug Filesにチェックを入れる
* Packagingを行う
* 作成されたフォルダの「WindowsNoEditor\XXX\Binaries\Win64」内にpdbファイルがexeと一緒に作成されている

# visual studioでexeを使ってデバック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/fa22b7a2-a30c-01c6-52f6-251f81adbd1a.png)

* コマンドの「$(TargetPath)」箇所をWindowsNoEditor\XXX\Binaries\Win64\XXX.exeに変える
* VisualStudioからDebug

# dumpファイルを使う
【備忘録】Golangで文字列型(YYYY-MM)から月を取得する

```go:main.go
package main

import (
	"fmt"
	"strconv"
)
func main() {
	// YYYY-MM形式から月を保存する。
	str := "2021-04"
	str2 := str[5:]
	month, _ := strconv.Atoi(str2)
	fmt.Println("month: ",month)

	str = "2021-12"
	str2 = str[5:]
	month, _ = strconv.Atoi(str2)
	fmt.Println("month: ",month)
}
```

```shell:実行結果
~/go/src/array_slice $ go run main.go
month:  4
month:  12
```
商談商品のレコードをメールテンプレートに表示する


元の質問 : [Email with Multiple OrderItems](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000HDJQlSAP)

初めにこれを見つけて回答していたのですが、実際に設定してみると保存できん。

[Adding Opportunity Products Related List to Visualforce Email Template](https://salesforce.stackexchange.com/questions/79615/adding-opportunity-products-related-list-to-visualforce-email-template)

relatedTo.OpportunityLineItems がない。そうだよねぇ。

```
<apex:repeat value="{!relatedTo.OpportunityLineItems}" var="oli">
   <apex:outputText value="{!oli.PriceboonEntry.Product2.Name}">
   <apex:outputText value="{!oli.UnitPrice}">
   <apex:outputText value="{!oli.Quantity}">
</apex:repeat>
```
過去に作ったものを参考に作ってみました。

[PDFを作成し、Salesforceメールテンプレートに添付する方法](https://qiita.com/Keiji_otsubo/items/63581eade221ec5e1a51)



VF page email template

```
<messaging:emailTemplate subject="{!relatedTo.Name}" recipientType="User" relatedToType="Opportunity">
<messaging:plainTextEmailBody >

<c:ReceiptOppItems opportunityId="{!relatedTo.Id}"/>


</messaging:plainTextEmailBody>
</messaging:emailTemplate>
```


ReceiptOppItems.vfc
 
```
<apex:component controller="ReceiptOppItemsController" access="global">
    
    <apex:attribute name="opportunityId" description="Opportunity Id" assignTo="{!OpportunityObjectId}" type="Id" />   
    
    <apex:repeat value="{!OpportunityLineItems}" var="oli">
        <apex:outputText value="{!oli.PricebookEntry.Product2.Name}"/>
        <apex:outputText value="{!oli.UnitPrice}"/>
        <apex:outputText value="{!oli.Quantity}"/>
    </apex:repeat>
</apex:component>
```

ReceiptOppItemsController.apex

```
global class ReceiptOppItemsController {
    
    global String OpportunityObjectId{ 
        get;
        set {
            UpdateContents2(value);
        } 
    }
    
  
    
    global List<OpportunityLineItem> OpportunityLineItems{ get; set; }    
   
    public void UpdateContents2(String OpportunityObjectId) {
        
        if (OpportunityObjectId != null) {
            OpportunityLineItems = [SELECT Id,UnitPrice,Quantity,PricebookEntry.Product2.Name FROM OpportunityLineItem WHERE OpportunityId =:OpportunityObjectId];
           
            
        }
    }

}
```
セキュリティ上の理由により、Google Play に公開するにはデバッグを無効にする必要があります

## 現象
Google Play Consoleでaabファイルをアップロードすると上記タイトルのエラーになった

## 対応
Unity上で以下を検索してファイルを開く
__AndroidManifest.xml__

以下がTrueになっているのでfalseに編集する
 __android:debuggable="false">__
![スクリーンショット 2022-05-16 23.42.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/376429/949a53e3-03c9-f01d-d8e1-5ae74677b28d.png)

再ビルドしてアップロードするとできた！

どうやら一度Development Buildにチェックをつけてしまうと、AndroidManifest.xmlのdebuggableがtrueになってしまうらしい

参考
https://unity-yuji.xyz/release-build-debuggable-apk-android-app-bundle-uploaded/
FastAPIでクエリパラメータの指定にPydanticのModelを使う

以下のように `Depends()`  を使えば指定できる

```python
class ArticleFilter(BaseModel):
    tag: str | None = None
    author: str | None = None
    favorited: str | None = None
    limit: int = 20
    offset: int = 0

@router.get("/", response_model=MultipleArticleResponse)
async def read_articles(
    filter: ArticleFilter = Depends()
):
	# TODO implement 
	pass
```

Swagger見てみるときちんとクエリパラメータとして指定できるようになっている

![スクリーンショット 2022-05-17 13.06.16.png](https://res.craft.do/user/full/d3c976f4-50c5-ba12-9e71-29edf789f3c0/doc/55D08C95-1DF2-47FB-ABCA-25A49A10BA7A/A3213D40-E90B-4AF7-A48D-0B52BCD897FB_2/%202022-05-17%2013.06.16.png)

----
参考
[FastAPI query parameter using Pydantic model](https://stackoverflow.com/questions/67580885/fastapi-query-parameter-using-pydantic-model)
AWS SSOでno accessエラーが出る。

AWS SSOでno accessエラーが出る。

Provide your administrator with the following info: No access
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102438/db429157-8d0f-9505-9c07-380482c00f0c.png)


この記事をもとに作っていて、動いていたはずなのに動かなくなった。
https://qiita.com/daisukeArk/items/abedd59194c9401a7423

サーバー環境では動くのに、ローカルでエラーが出る。

原因は、ローカルPCの時計が2分ほど遅れていたこと。
【Microsoft Lists】フォームのレイアウトをセクションに分けて複数列で表示する

## 1つ以上のセクションでカスタムの本文を構成する

1. 本文に書式を適用するには、**[書式]** ウィンドウの **[書式を適用する]** ドロップダウンから **[本文]** を選択します。
1. カスタムの本文フォーマッターを JSON テキスト入力領域に貼り付けます。
1. ヘッダーやフッターとは異なり、本文の構成では、1 つ以上のセクションを定義し、それらの各セクションに 1 つ以上の列を追加することしかできません。
   - 1 つまたは複数のセクションを本文に定義できます。
   - 各セクションは、リストまたはライブラリの 1 つ以上の列を参照できます。
   - 列は 1 つのセクションでのみ参照できます。
   - 列が複数のセクションで参照されている場合、列が参照されている最初のセクションが優先されます。
   - どのセクションでも参照されていない列は、最後のセクションで自動的に参照されます。
   - 追加された新しい列は、最後のセクションで自動的に参照されます。
1. 以下は、セクションの定義とセクション内の列の参照を開始するための JSON 構造です。  
   ```JSON
   {
    "sections": [
    {
      "displayname": "",
      "fields": [
      ]
    },
    {
      "displayname": "Details",
      "fields": [
      ]
    },
    {
      "displayname": "Additional Info",
      "fields": [
      ]
    }
    ]
   }
   ```
1. 本文が 1 つ以上のセクションでカスタマイズされると、リストまたはライブラリフォームは複数列のレイアウトに切り替わります。  
   > 注意
   > フォーム 本文を構成すると、リストまたはライブラリのフォームレイアウトが単一列から複数列のレイアウトに切り替わります。 将来の更新で、単一列レイアウトで本文を構成するためのサポートを追加する予定です。
   > ![セクション付きのカスタム リスト フォーム本文](https://docs.microsoft.com/ja-jp/sharepoint/dev/declarative-customization/images/list-form-configuration-body.png)
1. 変更をプレビューするには、[**プレビュー**] ボタンをクリックします。
1. 変更を保存するには、**[保存]** ボタンをクリックします。
1. フォームを閉じてからもう一度開き、カスタム本文を表示します。

# 参考サイト

- [リスト フォームを構成する | 1つ以上のセクションでカスタムの本文を構成する](https://docs.microsoft.com/ja-jp/sharepoint/dev/declarative-customization/list-form-configuration#configure-custom-body-with-one-or-more-sections)
【Firebase】onChildChangedの使い方と注意点

# 子ノードの更新を検知するonChildChangedとは
全ての更新を検知する度に発火するイベントで、更新データを取得することができます。
※onChildAddedはデータが追加されたとき。Firebase含め、@kyok01_japanさんの記事をご参考にしてください。

https://qiita.com/kyok01_japan/items/7733232e050cb64eb4fd

## ドキュメントの翻訳（とりあえず）
onChildChanged()
指定した場所でデータが変化したらListenします。

データベースからデータを読む1番の方法です。初期データやデータが更新されるcallbackがトリガーとなります。Invoke the returned unsubscribe callback to stop receiving updates. 

onChildChangedイベントは子ノード（もしくはさらに下層）で保存されたデータが変更されたときに発火します。注意：child_changedイベントが1つでも子ノードは複数変化しているかもしれません。callbacに渡されたDataSnapshotは新しい子要素を含むことがあります。並べ替えたいとき、callbackは第二引数がわたされます。第二引数はソート順でひとつ前の子のキーを含む文字列が渡され、最初の子の場合は、nullが渡されます。

API Referenceより

https://firebase.google.com/docs/reference/js/database.md#onchildchanged

## 使い方と注意
まずは、FirebaseのRealtimeDatabaseの初期設定。
```javascript
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-app.js";
import {getDatabase, ref, push, set, onChildAdded, remove, onChildRemoved, child, get, onChildChanged} from "https://www.gstatic.com/firebasejs/9.8.1/firebase-database.js";
// Firebaseから引っ張ってきてください。
const firebaseConfig = {
      apiKey: "xxx",
      authDomain: "xxx",
      projectId: "xxx",
      storageBucket: "xxx",
      messagingSenderId: "xxx",
      appId: "xxx",
    };
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const db = getDatabase(app);
```
次に、onChildChangedを呼び出します。callbackはfunction(data){}を当てます。 **`onChildChanged`で変化した要素が`data`に入ってきます。** 
```javascript
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-app.js";
import {getDatabase, ref, push, set, onChildAdded, remove, onChildRemoved, child, get, onChildChanged} from "https://www.gstatic.com/firebasejs/9.8.1/firebase-database.js";
// Firebaseから引っ張ってきてください。
const firebaseConfig = {
      apiKey: "xxx",
      authDomain: "xxx",
      projectId: "xxx",
      storageBucket: "xxx",
      messagingSenderId: "xxx",
      appId: "xxx",
    };
// Initialize Firebase
const app = initializeApp(firebaseConfig);
const db = getDatabase(app);

// ここからonChildChangedに関わるところ
// dbRefを作成します。第二引数でお好きな構造を設定します。
const dbRef = ref(db, "parent/child");
// データ構造のイメージは以下のとおり
// parent
//  └child
//   └grandchild
// 
onChildChanged(dbRef, function (data) {
 console.log(data);
 console.log(data.val());
}
```
最後に私がひっかかった点を。
データは以下のような構造になっています。 **`grandchild`の階層で変更があったとします。** 
```
// parent
//  └child
//   └grandchild
```
`const dbRef = ref(db, "parent/child");`では、childの階層を指定しているため、`grandchild`の階層での変更が検知され、`grandchild`のデータが`data`に返ってきます。
もし、あなたが`child`階層からデータが欲しいとき（=更新されたデータと同じ階層の他のデータも欲しいとき）は、`parent`階層を指定する必要があります。
`const dbRef = ref(db, "parent");`
このようにすると`parent`階層から二階層下の`grandchild`階層の変化を検知し、`parent`階層の一つ下の変化した`child`を取得します。

日本語下手すぎで説明ができていないかもしれないので、追って修正するかもです...
Git 分散バージョン管理システム

# Gitとは
```分散バージョン管理システム```呼ばれる。
## バージョン管理システム
・同じプロジェクトのリポジトリをネットワーク上に複数置いて管理できる
・複数人で同じプロジェクトで開発する際に便利だ。
・サーバには裸のレポジトリというステージや作業ツリーを持たないリポジトリを置く（そこで開発しないから）
・プロジェクトに応じてリポジトリの配置が可能になる。
### プロジェクト
プロジェクト：目的を達成するための計画
出典　https://backlog.com/ja/project-management-guide/intro/intro1/intro1_2/
### リポジトリ
バージョン（ファイルの変化分）を入れる場所

# Gitのコマンドとヘルプ
```
git help
```
gitの後に```help```などをつけるがこのコマンドを```gitコマンド```（サブコマンド）という。
またこのサブコマンドを含めた意味は
```サブコマンドの説明```を見ることができる。
例えば
```
git config 引数..
```
を使いたいが、どのようなコマンドかを詳しく知りたいときは
```
git help config
```
とすると```config```のgitコマンドの説明を見ることができる。
Railsチュートリアル 第1章のデプロイでつまずいた話。

意気揚々とRailsチュートリアルを初めてみた。

どんどん勧めていくうちにGithubにpushできたー。

よしいよいよデプロイするでー。

git push heroku master

なんとエラー出てしまった

ログをたどると

!
 !     Precompiling assets failed.
 !
 !     Push rejected, failed to compile Ruby app.
 !     Push failed

さらに上にたどると

Compilation failed:
       error Command "webpack" not found.
       
       yarn run v1.22.17
       info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

あれーwebpackインストールしたはずなのになーとか思いつつ

再度rails webpacker:install

Webpacker successfully installed 🎉 🍰

さあいざもう一度

git push heroku

ｷﾀ━(ﾟ∀ﾟ)━!デプロイ成功👏

やっぱりログを見て英語だから分かんないではなく、案外見てみるとわかりやすいものですなー。
PHPのタイプヒンティングがやばい

## はじめに
タイトルが非常に釣り(？)っぽくなってしまいました。お詫びします。
引数の型を指定しているにも関わらず`TypeError`にならないなと思って確かめてみました。
僕が知らなかっただけであると信じているのですが隠された衝撃の事実が最後にあるので見てください。

## 参考 ?

https://www.php.net/manual/ja/language.types.declarations.php

```php
<?php

function yabai(int $yabai): void
{
    var_dump($yabai);
}

yabai(1);     //int(1)
yabai(1.1);   //int(1)
yabai('1');   //int(1)
yabai(true);  //int(1)
yabai(false); //int(0)

yabai(null); //Fatal error: Uncaught TypeError
yabai([]);   //Fatal error: Uncaught TypeError
yabai('a');  //Fatal error: Uncaught TypeError
```

なんだこれ。キャストできないもの？はエラー出すとかそんなのかなと思って`TypeError`が投げられたものをキャストしてみました。

```php
yabai(((int) null));   //int(0)
yabai(((int) []));     //int(0)
yabai(((int) 'a'));    //int(0)
```

全部キャストできました。`TypeError`でるものとでないものの違いがわからないです。

## おわり
なんと `declare(strict_types=1)` が指定されていないとこういう挙動をするというオチです。存在は知っていたのですがタイプヒンティングしたら関係なくない？と思っていました。いまさらリポジトリ全体に`declare(strict_types=1)`を適用しちゃうと帰れなくなると思うのでそっと胸にしまっておきます。新規ファイルでは都度指定しようと思います。
~~型を指定する意味が全くの無意味ではないかもしれませんが、厳密比較の条件文等を書く時`false`になってしまうのでまずいのでは？と思いました(小並感)。リファレンス等を見つけられなかったのでご存じの方はコメント等で教えていただければ幸いです。~~

## おまけ
ちなみに戻り値の型も同様な挙動をします。おそろC#

```php
<?php

function yabai($yabai): int
{
    return $yabai;
}

var_dump(yabai(1));      //int(1)
var_dump(yabai(1.1));    //int(1)
var_dump(yabai('1'));    //int(1)
var_dump(yabai(true));   //int(1)
var_dump(yabai(false));  //int(0)

var_dump(yabai(null));  //Fatal error: Uncaught TypeError
var_dump(yabai([]));    //Fatal error: Uncaught TypeError
var_dump(yabai('a'));   //Fatal error: Uncaught TypeError

var_dump(yabai(((int) null)));  //int(0)
var_dump(yabai(((int) [])));    //int(0)
var_dump(yabai(((int) 'a')));   //int(0)
```
PostgreSQLよりOLTPが4倍／OLAPが100倍高速のPostgreSQL互換のAI／機械学習搭載DB新サービス！AlloyDB

![1433418.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633992/012ba770-e459-5a6d-f451-8272cba68d4f.jpeg)


Google Cloud の新サービスとして、AlloyDB for PostgreSQLのリリースが発表され、Previewとして利用できるようになりました。

AlloyDB for PostgreSQLは、オープンソースDBであるPostgreSQLとの互換性を維持しつつ、DBに最適化されたストレージアーキテクチャを採用されています。
さらにAI・機械学習による最適化などによって高速化し、SLA 99.99％（予定）の高可用性、リニアなスケーラビリティ、AI・機械学習による運用管理の自動化なども実現できるとのことです。

このようなAlloyDB for PostgreSQLの特徴を紹介していきます。

## PostgreSQL完全互換
現時点ではPostgreSQL14と互換性があります。
PostgreSQL 14との互換性をもつだけでなく、175以上の設定パラメータや50以上の拡張をサポートしている。
そして、既存のPostgreSQLアプリケーションをそのままコードの変更なしに移行可能である。

## トランザクション処理はPostgresの最大約4倍、AmazonのAuroraより2倍速い
Gutmans氏いわく、オープンソースのPostgresの最大約4倍、Amazonの同等サービス（「Aurora」）の約2倍速いらしい。

## 通常のPostgreSQLよりOLTPが4倍、OLAPが100倍高速に
標準的なPostgreSQLに比べて最大4倍のスループット、100倍高速なレイテンシを実現しているとのこと。
パフォーマンスにおいては、2022年3月のGoogle Cloudでのテスト結果から、標準的なPostgreSQLと比べてOLTPワークロードにおいて4倍高速という数字を示した。
vCPUが64個のときだけでなく16個のときにも高いパフォーマンスを出し、64個でもきちんとスケールしているとし、スモールスタートして事業が大きくなったら大きくすることが可能だとしている。
カラム型キャッシュがうまく機能したときに分析のクエリでも最大で100倍高速とした結果が出た。

## 分析クエリを高速化しているのがAI・機械学習による「カラム型キャッシュ」機能
本来行指向データベースであるPostgreSQLに列指向データベースとしての特性を透過的に加えることで、メモリ上でカラムデータを保持する様になり、クエリ側は特殊な記法などは無く列指向のスキャンが行えるようになっています。

カラム型キャッシュ機能によって、AI・機械学習がワークロードの内容に基づいてキャッシュすべき行を自動選択し、さらに行形式／列形式の動的変換も行うことで、カラム型（列形式）データを多用する分析クエリもindexが不要であるため削除することで負荷削減などによって大幅に高速化し、また行指向、列指向と複数レイヤーのキャッシュを活用することで、費用対効果の高いパフォーマンスが実現する。
他に、Vertex AI[^1]で開発したモデルをSQLの関数で呼び出し、AlloyDB内で簡単に推論処理を実行できる。

## AI・機械学習による運用管理の自動化
AI／機械学習によるDBの運用管理面でも活用されており、ワークロードの状況に応じて自動的にVacuumを行ったり、Vacuum時にワークロードが使っていないメモリを転用して実行します。
また、ストレージの階層化やメモリ管理、パッチの適用やバックアップ、レプリケーションの判断なども自動化されています。
これらはAlloyDB用の機械学習モデルにより運用されます。

## 高可用性・高速メンテナンス
AlloyDBは高可用性・高速メンテナンスも実現しており、メンテナンスを含めて99.99%の高可用性 SLAを実現（予定）します。
DB障害を60秒以内に自動検出／回復させる機能が盛り込まれているため、ほとんどのデータベース障害を数秒以内に自動的に検出して回復し、メンテナンスも同様に数秒で完了します。

## 料金について
AWSのAuroraとは異なりStorage I/O課金は発生しません。
vCPUコア数・メモリ料金は時間とメモリ容量によって決まり、ストレージ料金はプロビジョニングした容量でなく格納したデータ容量（使用した分だけが課金対象）によって決まる。
そしてストレージは自動的にスケールするため、注意が必要です。
ネットワーク料金は、リージョン内およびデータが入ってくる側についてはかからない。


[^1]: Vertex AIはGoogle Cloudの機械学習関連のサービスを統合したプラットフォームです。

https://www.esprit-fort.co.jp/


https://www.esprit-fort.co.jp/recruit/
python で マルチスレッド(サンプルプログラム)

# はじめに
pythonにおける、マルチスレッドの基本的なサンプルプログラム。
※`threading`は標準ライブラリなので、pipは必要ない

# 確認環境
Windows 10
python 3.9.4


# コード

```python
import threading
import logging

# デバッグログ出力設定（どのスレッドの実行かがわかるので便利）
logging.basicConfig(level=logging.DEBUG, format="%(threadName)s: %(message)s")

# 指定最大値までの指定倍数の値を出力する
def counter(multiple=1, max=1):
    for i in range(1, max + 1):
        if i % multiple == 0:
            logging.debug(i)


if __name__ == "__main__":
    # スレッドの定義(targetは仕様する関数を指定、argsは引数を順番に指定)
    trd1 = threading.Thread(target=counter, args=(1, 10))
    trd2 = threading.Thread(target=counter, args=(2, 8))
    trd3 = threading.Thread(target=counter, args=(3, 9))
    # 処理開始
    trd1.start()
    trd2.start()
    trd3.start()

    # スレッド全体が終了するまでブロック
    for trd in threading.enumerate():
        if trd is threading.currentThread():
            continue
        trd.join()

    # 単体のブロックも可能
    # trd1.join()

    # 終了時の処理
    print("complete")
```

# おわりに
マルチスレッドは並列処理ではなく、並行処理になる。
これが大事。
rails5 progate 整理メモ　投稿者権限

# 投稿者だけが編集できるようにしよう（1）
他のユーザーが編集できないようにする
## 投稿者だけが```編集```,```削除```をできるようにする
```@post.userのid```と、```@current_userのid```を比較し、等しい場合にのみ編集・削除リンクを表示するようにする。
```html
      <% if @post.user_id == @current_user.id %>
        <div class="post-menus">
          <%= link_to("編集", "/posts/#{@post.id}/edit") %>
          <%= link_to("削除", "/posts/#{@post.id}/destroy", {method: "post"}) %>
        </div>
      <!-- 以下の<% %>を使ってif文のendを追加してください -->
      <% end %>
```
```@current_user```は```application_controller.rb```で設定されているため書くコントローラがアクションを作動させる前にこのコントローラを通るのでこのインスタンス変数は全てのコントローラで使うことができる。
（自信ないです。）

# 投稿者だけが編集できるようにしよう（2）
リンクを表示不可にしてもURLで簡単にアクセスすることができる。
なので今回も
```before_action```を使いそれを防ぐ。
## なんでこれで防げるかというと、(多分）
```routes.rb```をみてもらうとわかるが、特定のパスを入力した後、コントローラーのアクションが動くから
このアクションが作動する前にコントローラで```設定したメソッド```と```before_action```で止めることができるからだ。
これは作動を防ぎたいコントローラのアクションのために使うのでそのコントローラーでメソッドを書く。（機能別）
また全コントローラーで使うのは```application_controller.rb```で書く。（ログイン機能など）

## メソッドを書いた
```posts_controller.rb
class PostsController < ApplicationController
  before_action :authenticate_user
  # before_actionでensure_correct_userメソッドを指定してください
  before_action :ensure_correct_user, {only:[:edit, :update, :destroy]}
  
.
.
.
  def ensure_correct_user
    @post = Post.find_by(id: params[:id])
    if @post.user_id != @current_user.id
      flash[:notice] = "権限がありません"
      redirect_to("/posts/index")
    end
  end
```
これでurlからのアクセスを防げるのか？
成功！
4Kホームページ制作メモ part5 、どの解像度が必要？ 

## よくアクセスされる固定画像についての考察です。

より高鮮明になるレンティナディスプレイ等は考慮していません。

まぁ、max-width: 100% ってやればどの解像度にも確かに適切に配信できますが、表示速度や利用者に過剰にギガの請求をさせない（実質利用制限のないMNOの楽天モバイルや安めな20Gプランが増えたため、そこまで気にする人最近あまりいないようですが）ためにも、きめ細やかに設定する

## 横幅一覧

- 375
- 414
- 428

→iPhoneのあるバージョンとCSSピクセルの横幅が一致

- 512
- 750

→このあたりまで高解像度のスマホが出力してもおかしくない横幅

- 810
- 992
- 1100

→ここまでタブレッドがほとんどと思われる
→今は使う人あまりいないかもしれませんが、1024x768のPCディスプレイも横解像度1100にフィットします。

- 1284
- 1680
- 1920

→このあたりより（たぶんWindows 7ぐらい以降の）PCが出てくる

なお、Windowsが画面拡大することから、1920は4Kノートパソコン、4Kモバイルモニタ（並びにCSSピクセルを利用するフルHD超えタブレッド）にも該当すると推測される

4Kノートパソコンは十分に持ち運びできるサイズですので、ギガの使いすぎ防止（それでも画像は大きい）で、適切な解像度を用意する

https://kakaku.com/pc/note-pc/itemlist.aspx?pdf_Spec107=16

https://kakaku.com/pc/note-pc/itemlist.aspx?pdf_Spec107=18

- 2160
- 2600
- 3840

フルHDを超えると完全にPCの領域となります。

タブレッドの物理解像度は2160とかそういうのがありますが、CSSピクセル等で認識されるので、このような解像度は出ないと推測されます。

:::note info
デスクトップ4Kディスプレイで実質従量制の回線で閲覧される可能性も少なからずあるので、最低限でもブレークポイントを指定しておきます
:::


## （実際動かしていないが）仮にbootstrapを4K対応するとしたら？

最新の5バージョン系で改造するとしたら

```_variables.scss
/* 430行ぐらい */
// Grid breakpoints
//
// Define the minimum dimensions at which your layout will change,
// adapting to different screen sizes, for use in media queries.

// scss-docs-start grid-breakpoints
$grid-breakpoints: (
  xs: 0,
  sm: 576px,
  md: 768px,
  lg: 992px,
  xl: 1200px,
  xxl: 1400px,
  hd2k: 1920px,
  wqhd: 2560px,
  hd4k: 3840px,
  hd8k: 9999px
) !default;
// scss-docs-end grid-breakpoints
```

に変更して

```
npm install
npm run dist
```

でビルドしておけばよさそうな感じは一応はします
【Rails】新規アプリケーション作成までの流れ（確認方法もご紹介）



新規アプリケーション作成時の流れと、その作業がしっかり完了しているのか確認する手順も踏まえてご紹介いたします。



### はじめに

指定したフォルダ内にアプリケーションを格納したい場合は予めフォルダを作成しておく。
（例　projects、Macの場合は「Finder」）

→ 新規アプリケーション作成前にターミナルでそのディレクトリ（フォルダ）に移動しておきましょう。

projectsディレクトリの場合
```
cd projects
```


## 1　新規アプリケーション作成


##### ①新規アプリケーション作成コマンドを実行（ターミナル）
```
rails _6.0.0_ new アプリ名 -d mysql
```

##### ②作成した以下のファイル内を変更（コードエディタ）
  １４行目くらいにある　encoding: utf8mb4 を encoding: utf8　に変更

config/database.yml
```
default: &default
  adapter: mysql2
  encoding: utf8  #こちらの記述に変更
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock

```

##### ③データベースの作成
先ほど作成したアプリのディレクトリに移動してから実行
```
cd 先ほど作成したアプリのディレクトリ
rails db:create
```

##### ④データベースができている確認
例　シークエルプロの場合以下が確認できればOK
（中身は今後テーブルを追加するので空欄でOK）

☑️アプリ名_development
☑️アプリ名_test


ここまででアプリケーションの新規作成ができました！


## 2 GitHubにリポジトリを作成する

### 前提
GitHubへのアカウント登録、GitHubDesktopのアプリのインストールが完了している

### 手順

#### ①GitHub Desktop（アプリ）を用いてローカルリポジトリを作成する

・左上　current Repositoryをクリック
→Add▼（追加する）をクリック
→Add Exising Repositoryをクリック
→choose.... をクリックし、先ほど作成したアプリを追加
→Add Repositoryのボタンをクリックすると追加できる

＊左上の黒いバーに作成したアプリ名があるか確認しましょう

##### ②アプリ名直下「Changes」のバーに「changed　files」があることを確認した後、「first commit」というコミットメッセージでcommitする



##### ③アプリケーションと同名のリモートリポジトリを作成し、pushする

・右上の黒いバーにある「Publish Repository」をクリック
・公に見られたくない場合は「keeo this code private」にチェックを入れる。日々の作業量の確認（草を生やすと表現される）ができなくなる可能性があるので、特に理由がない場合は外してOK。
・Publish Repositoryをクリックすると「History」にコミットが追加される

##### ④ブラウザのGitHubで作成したアプリ名・先ほどのコミットが反映されているか確認する。
https://github.com/



これでGitHubにリポジトリを作成することができました。
おつかれさまでした！
Dynamics 365 アプリをコピーする方法（セールスアプリ、顧客サービスアプリetc）

Dynamics 365のアプリをコピーする。

例えば、開発したアプリの検証環境を複製したい。
プリセールスエンジニアとして、デモをするときに
既存のものをコピーしてデモをしたい。

やり方は複数あり
* 新規にソリューション作成し、設定したテーブルや追加項目をソリューションへ追加する。
* 同じ環境にアプリをコピーする。URLは別となる。（同じテナントであるが、環境は異なる）


## 完成イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/d8359207-7ccd-d077-f5e0-45f42a8ee2af.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/8bafcf7e-712a-3f92-291a-156d4403d458.png)


## 手順
### 1.Power Platform 管理センター　で環境を新規に作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/2f51fb0b-cd8c-599d-55e0-74cbd93680e4.png)


### 2．コピーしたい環境を選択し、コピーボタンを押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/de5ba538-7347-7310-dfa6-c28821471944.png)

### 3．コピー先に対して上書きを行う。最大8時間待つ。


https://docs.microsoft.com/ja-jp/power-platform/admin/copy-environment?WT.mc_id=ppac_inproduct_env

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/367026/ed874ec2-23e3-44e4-8d56-6553798027de.png)

以上
【MT7】公開記事と未公開記事の総数を表示させる

## はじめに
**MovableType7**
公開記事と未公開記事の総数の出力方法についてのメモ。
プラグイン「[MTEntriesStatusFilter](https://github.com/alfasado/mt-plugin-mtentries-status-filter)」を使用します。

## やりたいこと
・今回は記事に登録された「合計会員数」を表示させるとする。
・会員の記事は非公開でも、記事の数をカウントし、合計人数を表示させたい。

## コード

```
<mt:setvar name="count">
  <mt:Entries status_filter="1,2" lastn="0">
     <MTSetVar name="count" value="1" op="+">
  </mt:Entries>
</mt:setvar>

<mt:setvar name="total_count" value="$count">

<p>会員数：<$mt:var name="total_count"$>人</p>
```

## 説明
・entriesでループ処理を行い、記事の数をカウントしています。
・ポイントはstatus_filterで公開、非公開を指定しているところです。
・公開記事と非公開記事を指定しています。

## タグ

・**status_filter**：「1」の場合は未公開、「2」の場合は公開記事、「4」は日時指定された記事となります。
複数指定する場合は「1,2」とカンマで区切ります。

【参考】
・Unpublished (1)
・Published (2)
・Review (not commonly used, 3)
・Scheduled (4)
・Junk (used with community-submitted content, 5)
※「[MTEntriesStatusFilter](https://github.com/alfasado/mt-plugin-mtentries-status-filter)」より

・**lastn**：属性値に「0」を指定すると全件表示されます。



## 参考サイト
・[MTEntriesStatusFilter](https://github.com/alfasado/mt-plugin-mtentries-status-filter)

・[MTEntries  | MovableType テンプレートタグリファレンス](https://www.movabletype.jp/documentation/appendices/tags/entries.html)

・[プレビュー画面でMTEntriesに未公開の記事も表示したい](https://communities.movabletype.jp/2013/03/mtentries-2.html)

・[Movable Type で全エントリーを表示する方法](https://www.koikikukan.com/archives/2006/12/13-015025.php)
PL-900 Power Platform Fundamentals 受験記

# Power Platform Fundamentalsとは
試験の概要について公式サイトに以下の記載があります。

> この試験の受験者は、Power Platform の機能を理解し、Power Automate で基本的なビジネス プロセスを自動化し、Power BI で基本的なデータ分析を実行し、シンプルな Power App を作成することでより効果的に行動し、Power Virtual Agents を使用して強力なチャット ボットを作成することで、生産性の向上を目指します。

[引用元](https://docs.microsoft.com/ja-jp/learn/certifications/exams/pl-900 "PL-900")
つまり、Power Platform FundamentalsはMicrosoft Power Platformの初級者向け資格です。

# PL-900の試験範囲
> Power Platform のビジネス価値について説明する (15-20%)
Power Platform のコア コンポーネントを特定する (15-20%)
Power BI の機能を実証する (15-20%)
Power App の機能について説明する (15-20％)
Power Automate の機能を実証する (15-20％)
Power Virtual Agents のビジネス価値を実証する (10-15%)

[引用元](https://docs.microsoft.com/ja-jp/learn/certifications/exams/pl-900 "PL-900")

受験してみた印象としてはPowerApps関連の問題が多かったように感じました。
これから受験する方は特にPowerAppsに注力すると合格しやすいかもしれません。

# PL-900の受験料
普通に受験すると12500円掛かるのですが、無料で受験する方法もあります。
それは「[Microsoft Power Platform Virtual Training Day: Fundamentals](https://www.microsoft.com/ja-jp/events/top/training-days/powerplatform?activetab=a1%3aprimaryr4 "イベント")」という定期的に開催されているイベントに参加するだけ。
このイベントに参加することでPowerPlatformの勉強も出来るし、無料受験も出来ちゃいます！
まさに一石二鳥のイベントなのでPL-900の受験を考えている方は是非参加してみてください。

# 試験対策
書籍や有償のオンライン教材等もありますが、Microsoftが提供している無償の教材やウェビナーでも十分対策することが出来ますのでご紹介します。

- [Microsoft Learn](https://docs.microsoft.com/ja-jp/learn/paths/power-plat-fundamentals/ "Microsoft Power Platform の基本")
    - Microsoft が提供する無料のオンライントレーニングプラットフォームです。こちらの「Microsoft Power Platform の基本」を一通り実施しました。
- [ウェビナー | Microsoft Power Platform Fundamentals 試験対策](https://info.microsoft.com/JA-PowerApps-WBNR-FY21-05May-03-MKTOFY21PL900PrepSessionOndemandWebinar-SRDEM73329_LP02OnDemandRegistration-ForminBody.html "PL-900 : Microsoft Power Platform Fundamentals 試験対策")
    - こちらは約4時間のオンデマンドセミナーです。要所要所で実際に出題される問題に近しい傾向の模擬問題を出してくれるため非常に役立ちました。

# ここは押さえておきたい
各製品ごとにどんな学習が試験に役立ったのかを記載していきます。
- PowerApps
    - おおまかなコンポーネントの種類や使い方とアプリ発行までの手順
    - コネクタを利用したアプリケーションの作成の方法
    - モデル駆動型アプリの作成方法
    - ビジネスプロセスフローやポータルサイトについて
    - 管理センターで行えるアプリケーションの設定内容
    - 最新版のアプリで不具合が発生した場合に前のバージョンへ戻す方法

- Power Automate
    - 自動フローの作成と、発行やフローの共有までの手順とフロー作成方法
    - カスタムコネクタについても作成方法
    - 標準コネクタ、カスタムコネクタ、認証コネクタの違い
- Power Virtual Agents
    - チャットボットの作成方法から公開までの手順
    - チャットボットからPower Automateと連携を行う方法
- Power BI
    - デスクトップ版とサービス版の差異
    - ダッシュボードとレポートでそれぞれの制約と出来ること
    - 受信登録の機能
    - どういったデータソースを指定できるか
- その他(管理画面やセキュリティ等)
    - 自身が作成したフロー、アプリ、チャットボットの共有や公開の方法
    - Microsoft Dataverseがどの製品で使用されており、どの製品と連携が可能か(D365含む)
    - D365とPower Platformがどういう連携が行えるか
    - 想定のシナリオに対して、どの製品が有効か判断が行えること

## 注意点
試験対策のオンデマンドウェビナーでは**Microsoft Dataverse**ではなく旧サービス名の**CDS**で説明されています。また、PL-900の問題もCDSではなくMicrosoft Dataverseで出題されるようになっているので混乱しないように気を付けましょう。

# 最後に
上記の対策を行い、無事に合格することが出来ました！
イベントに参加することで無料で受験出来ますし、仮に落ちてしまったとしても再度イベントに参加すれば無料で受験することができます。
そこまで気負わずにチャレンジ出来ますので少しでも興味がある方は是非チャレンジしてみてください！
[Flutter]Plugin開発中の unable to load asset エラー

# はじめに

Flutterの独自Pluginを開発中に、

通常のアプリ開発同様画像を表示しようとしたところ

表題のエラーでちょっと困ったので書いておきます。

# 問題のコード

下記 `SampleWidget` はPlugin内に実装した画像を表示するためのシンプルなWidgetてす。

をexample app(※1)て実行すると `Unable to load asset: assets/images/sample.png` エラーにより、画像表示に失敗します。

```dart
class SampleWidget extends StatelessWidget {
  const ExampleWidget({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Image(
      image: AssetImage(
        'assets/images/sample',
      ),
    );
  }
}
```

(※1) 

example appはPlugin作成時にデフォルトで用意される確認,検証用のAppです。

exampleフォルダ以下に生成されます。

# 確認したこと

画像の表示に失敗するケースとして、

- そもそもassetのバスを間違えている
- pubspec.ymlの内容が間違っている

などありますが、どれも該当しませんでした。

# 解消した方法

下記のように、AssetImage classのコンストラクタ引数 `package` に 

```dart
class ExampleWidget extends StatelessWidget {
  const ExampleWidget({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const Image(
      image: AssetImage(
        'assets/images/example.png',
        package: 'package_name'
      ),
    );
  }
}
```

自身のPlugin名を指定することで、無事表示に成功しました。

# なぜ画像が表示できなかったのか

[ドキュメント](https://api.flutter.dev/flutter/painting/AssetImage-class.html)によると、外部Package(広義のPackage)からAssetを参照する場合はpackage名を指定することが必須になっています

> To fetch an asset from a package, the [package](https://api.flutter.dev/flutter/painting/AssetImage/package.html) argument must be provided.
> 

自身のパッケージ内にAssetがある場合は指定の必要がありません。

しかし今回の用にPlugin側が画像を保持している場合は、

呼び出し側は該当Pluginの画像を保持していないため、

画像の取得先を指定する必要がありました。

# 都度パッケージ名を書く手間を省く

下記のように、 常にPackage名を指定するクラスを用意するのも良いかもしれません

```dart
class SampleAssetImage extends AssetImage {
  const SampleAssetImage(String assetName) : super(assetName, package: 'sample');
}
```
KubernetesのFeature Gatesを使おうとして使い方がわからなかったのでメモ

Kubernetes には [Feature Gates](https://kubernetes.io/ja/docs/reference/command-line-tools-reference/feature-gates/) という「**アルファ機能または実験的機能を記述するkey=valueのペアのセット**」があります。

古参の Kubernetes ユーザーの方々からすれば「何を今更」という感じでしょうが、新参の私からしたら Feature Gates で使えるようになる機能を有効にする方法が全然わからなかったので、同じように悩んでいる方のために使い方をまとめておきたいと思います。

## まずは公式ドキュメント

https://kubernetes.io/ja/docs/reference/command-line-tools-reference/feature-gates/

> 各コンポーネントはそれぞれのコンポーネント固有のフィーチャーゲートの設定をサポートします。すべてのコンポーネントのフィーチャーゲートの全リストを表示するには `-h` フラグを使用します。kubeletなどのコンポーネントにフィーチャーゲートを設定するには以下のようにリストの機能ペアを `--feature-gates` フラグを使用して割り当てます。

公式ドキュメントには上のように書かれており、その下には使える Feature Gates の一覧があります。

上の説明を見るとわかる通り、Feature Gates で機能を有効化するには、その機能に関連するコンポーネントのコマンドに `--feature-gates` フラグを付けてあげれば良さそうです。

では、「**どのコンポーネントのコマンドにつければいいの？**」という点で、私はつまずきました。

## 答えは

このように書くと明らかに当然のことですが、**各コンポーネントのヘルプを見ればわかります**。

[Component tools](https://kubernetes.io/docs/reference/command-line-tools-reference/) のページにある下記コンポーネントの `--feature-gates` オプションで使える値の説明を見れば、どのコンポーネントにフラグを追加すればよいかがわかります。

* [kubelet](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/)
* [kube-apiserver](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/)
* [kube-controller-manager](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-controller-manager/)
* [kube-proxy](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-proxy/)
* [kube-scheduler](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-scheduler/)

例えば、Kubernetes 1.24 で alpha として追加された機能 [CronJobTimeZone](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#time-zones) を使うには、kube-apiserver, kube-controller-manager, kube-proxy, kube-scheduler に CronJobTimeZone の記載があるので、上記コンポーネントのコマンドにフラグを付ければよいとわかります。

ちなみに kubeadm で構築した場合の各コンポーネントのオプション付与方法は

* kubelet: `/var/lib/kubelet/kubeadm-flags.env` に追記して `systemctl restart kubelet`
* kube-proxy: `kubectl -n kube-system edit ds kube-proxy`
* kube-apiserver, kube-controller-manager, kube-scheduler: `/etc/kubernetes/manifests/kube-*.yaml` を編集

という感じです。

それではよい k8s ライフを～。
【備忘録】Golangでスライスを利用する。

## Golangで１次元スライスを利用する

```golang:main.go
package main

import "fmt"

func main(){
	// １次元スライス
	s1 := []int{1, 2, 3}
    s2 := []int{5, 6, 7}

	// 1次元スライスに要素を追加する。
	s1 = append(s1, 4)

	fmt.Println("s1: ",s1)

	// １次元スライスに１次元スライスを追加する。
    s1 = append(s1, s2...)

    fmt.Println("s1: ", s1)
}
```

```shell:実行結果
~/go/src/array_slice $ go run main.go
s1:  [1 2 3 4]
s1:  [1 2 3 4 5 6 7]
```

## Golangで２次元スライスを利用する
```golang:main.go
package main

import (
	"fmt"
)

func main() {
    s1 := [][]int{{1, 1}, {1, 2}, {1, 3}}
	fmt.Println("s1:", append(s1, []int{1,4})) // 追加時に[]int{}とする所に注意！！

	s2 := [][]int{{2, 1}, {2, 2}, {2, 3}}
    s1 = append(s1, s2...)
	fmt.Println("s1: ", s1)
}
```

```shell:実行結果
~/go/src/array_slice $ go run main.go
s1: [[1 1] [1 2] [1 3] [1 4]]
s1:  [[1 1] [1 2] [1 3] [2 1] [2 2] [2 3]]
```

### おまけ：配列とスライスの違い。
配列は固定長、スライスは可変長で定義されている。Javaで言うスライスはList、配列は配列となる。
可変長で利用できる方が便利だから、なぜ配列が利用されるのかと言うのは誰しも思う疑問。
その答えは公式のドキュメントで答えが書いてありました。興味のある人は読んでみてね！！！

https://go.dev/blog/slices-intro
Oracle Analytics Cloud：クリックしたデータをダッシュボードに引き渡す

# はじめに
Oracle Analytics Cloud（**OAC**）は、

- エンタープライズBI
- セルフサービスBI
- 拡張分析

の3つを機能の柱としています。
従来のオンプレミスBIツールであるOracle Business Intelligence Enterprise Edition（**BIEE**）の流れを汲むのが、「エンタープライズ分析」機能であり、BIEEで作成したダッシュボードをOACに移行することもできます。

# やりたいこと

- OACのセルフサービスBI機能で作成したビジュアライゼーションから、従来のエンタープライズBIによるダッシュボードにドリルスルーしたい。
- その際、クリックした場所のデータを検索条件として引き継ぎたい。

# 準備
エンタープライズBIのダッシュボードを用意します。
今回は、BIEEから移行したダッシュボードを使います。
ダッシュボードの上部には「ダッシュボード・プロンプト」を配置しており、利用者が対話的に検索条件を変更することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/97bc308e-5dc3-cedc-0fc2-5646c3332dda.png)

# ビジュアライゼーションの作成
データセットとして、ダッシュボード・プロンプトで使用されているのと同じサブジェクト領域を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/dd941398-bf58-277a-5b58-e75658a34c92.png)
今回は、ビジュアライゼーションのタイプとして「ドーナツ」を選択してみました。
「チャネルカテゴリ」を右クリックして、ダッシュボードにドリルスルーするように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/2a12a05c-708a-1d0b-2f1f-60fe5dd7d4dc.png)

# データ・アクションの設定
画面右上の「メニュー」アイコンをクリックし、「データ・アクション」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/8805f60d-6328-f989-a234-68731c714399.png)
「名前」に任意の名称を入力します。ここで入力した名称がメニューに表示されます。
「タイプ」は「分析リンク」とします。
アンカー先は、「チャネルカテゴリ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/2317de01-2d64-61d7-1f50-bee5a48689d4.png)
「ターゲット」の「このワークブック」をクリックし、「カタログから選択」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/db053b8a-d0db-29ac-e83c-00fcc15f2cf0.png)
カタログの中から、ドリルスルー先のダッシュボードを探して「OK」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/edde347d-b5d9-badd-f439-eb766d1629ae.png)
遷移先のダッシュボード・ページを指定し、「値を渡す」を「アンカー・データ」とします。
「OK」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/82856938-81bb-7b3f-c21a-2e096b6b59ac.png)

# ドリルスルーしてみる
ドーナツの「直販」部分を右クリックするとメニューが表示されます。
データ・アクションの定義で付けた名前がメニューとして表示されるので、クリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/fa918e21-b994-5e7b-c6f3-23bdad4b2272.png)
指定したダッシュボードの指定したページが表示され、ダッシュボード・プロンプトに検索条件が自動的に適用されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342206/026c68f7-f9a5-cb27-e4e8-008bd44867f0.png)
Qiitaのコメント欄を改善するユーザースクリプト

## はじめに

Qiita のコメント欄を見て「連番が振ってあれば見やすいのに」と思ったことはありませんか？:thinking:

Qiita のコメント欄を改善するユーザースクリプトを作りました。

## Qiitaのコメント欄の何が不満か

このユーザースクリプトがどの不満をどのように解決するかを表にしました。解決策がユーザースクリプトの機能に対応します。:blush:

| 何が不満？ | 解決策 |
| ------ | ------ |
| どこまで読んだか分からない。 | 各コメントに連番と総コメント数を振る。 |
| コメント投稿者の何件めまで読んだか分からない。 | コメント投稿者ごとに各コメントに連番と総コメント数を振る。 |
| どれが作者のコメントか分からない。 | 作者のコメントに（作者）の印をつけ、枠の左に縦線を付ける。 |
| 本文を読む前にコメントの存在が分からない。 | 冒頭にコメント数を表示する。 |
| 作者が投稿したコメント数が分からない。 | 冒頭に作者が投稿したコメント数を表示する。 |
| コメントの性質がわからない。 | 冒頭に前向きなコメント数[^1]を表示する。 |
| 冒頭でコメント投稿者ごとのコメント数がわからない。 | 冒頭のホバーでコメント投稿者ごとのコメント数を表示する。 |
| 本文にホバー型のリンクアイコンがあるのに、コメントにない。 | コメントにもホバー型のリンクアイコンを付ける。 |
| 返信先のコメントがわからない。 | `@ユーザー名`のホバー時に返信先コメントをポップアップする。 |
| コメント投稿者のコメントだけを読みたい。 | `@ユーザー名`のホバー時に抽出コメントをポップアップする。 |
| 目次(TOC)にコメントがない。 | 目次(TOC)にコメントを追加する。 |

## ユーザースクリプトのインストール方法

Chromeの拡張機能Tampermonkeyを追加した後、次のリンクをクリックするとユーザースクリプトを導入できます。

https://raw.githubusercontent.com/querykuma/QiitaCommentsKaizen/main/QiitaCommentsKaizen.user.js
https://github.com/querykuma/QiitaCommentsKaizen

## Qiitaにコメント番号がないことの意味

Qiitaにはコメント番号がないので、>>1の形でコメントの返信先を示せません。ヤフーニュースのように、返信の機能もありません。:sob:

コメントの返信先を示す方法がない中で、一部の利用者が`@ユーザー名`の形でコメントの返信先を示す方法を見つけ、使っています[^2]。

`@ユーザー名`をホバーしたときに返信先のコメントをポップアップする機能を作りました。

## さいごに

Qiita のコメント欄に不満があったので、不満を解決するユーザースクリプトを作りました。

コメントの読みやすさが改善されれば幸いです。:coffee:

[^1]: 簡単な AI が判定します。
[^2]: この方法を使う人数はまだ多くないようです。
【Python】Seleniumを使わずにInstagramのフォロワーを全件取得する

# 初めに
　Instagramのフォロワーを全件取得する際、いくつか候補があります。例えば別のサイトではSeleniumを使用しています。

https://tachitechi.com/%E3%80%902020%E5%B9%B4%E3%80%91instagram%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%AE%E3%83%95%E3%82%A9%E3%83%AD%E3%83%AF%E3%83%BC%E6%83%85%E5%A0%B1%E3%82%92%E8%87%AA%E5%8B%95%E3%81%A7/

　Instagramのフォロワーの表示はフレキシブルになっているため、画面上では一度で取得できず、スクロールする必要があるため、時間がかかってしまいます。
# Instaloaderとは
　こちらを解決するのが、InstaloaderというPythonライブラリです。[以前の記事](https://qiita.com/fishyamamoto/items/3bc909051d13207f885d)でも記載しましたが、Instagramで行いたいと思うことはこのライブラリを用いればGUIを使うことなく、すべて行うことができます。
# ソースコード
　全件取得のソースコードは以下になります。順に解説していきます。
```python
import instaloader

    #インスタグラムにログイン
    loader = instaloader.Instaloader()
    loader.login(INSTAGRAM_ID, INSTAGRAM_PASSWORD)

    #指定したIDのprofileオブジェクトを作成
    profile = instaloader.Profile.from_username(loader.context, id)#id:フォロワーを取得したいアカウントのユーザーID

    #指定したIDのフォロワーを全件取得
    followers = profile.get_followers()

    #ユーザーIDを出力する
    for follower in followers:
        print(follower.username)
```

　まずはinstaloaderをインポートします。
```python
import instaloader
```
 instaloaderのインストール方法はpip3を使用するだけです。
```sh
pip3 install instaloader
```
　以下の公式サイトも参照してください。

https://instaloader.github.io/installation.html

　次にinstaloaderでInstagramにログインします。
```python
    #インスタグラムにログイン
    loader = instaloader.Instaloader()
    loader.login(INSTAGRAM_ID, INSTAGRAM_PASSWORD)
```
　Instagramでフォロワー一覧を見たり、投稿を保存したりするためにはログインが必要になります。それと同じで、instaloaderでも任意のアカウントのフォロワーを取得するためにはログインが必要になります。
　instaloaderのMainClassであるInstaloaderのlogin関数を使います。
　引数はユーザーIDとパスワードです。
　一行にまとめることもできます。
```python
    #インスタグラムにログイン
    instaloader.Instaloader.login(INSTAGRAM_ID, INSTAGRAM_PASSWORD)
```

　次にフォロワーを取得したいアカウントのProfileオブジェクトを作成します。
```python
    #指定したIDのprofileオブジェクトを作成
    profile = instaloader.Profile.from_username(loader.context, id)#id:フォロワーを取得したいアカウントのユーザーID
```
　Profileオブジェクトは任意のアカウントに対して作成することができ、関数を使用することで、そのアカウントの投稿や、画像、フォロワーなどすべての情報を取得することができます。Postオブジェクトと並んで、非常に使い勝手の良いclassです。

　最後にPorileオブジェクトで指定したユーザーのフォロワーを取得します。
```python
    #指定したIDのフォロワーを全件取得
    followers = profile.get_followers()
```
　取得するアカウントに鍵がかかっている場合には注意が必要です。
# 終わりに
　使用方法が分かれば、公式サイトで関数を見ることで、本当にすべての情報を簡単に取得することができます。
　参考にしたサイトと公式サイトのリンクを張っておきます。
　ご指摘、ご質問がございましたら、ぜひコメントよろしくお願いします。

https://www.geeksforgeeks.org/introduction-to-instaloader-module-in-python/

https://instaloader.github.io/index.html