OmniAICreator/Qiita-1.07M huggingface dataset:
BigQueryのデータを定期的にGooleスプレッドシートに出力する方法

今日は、BigQueryのデータを定期的にGooleスプレッドシートに出力する方法について書きたいと思います。

今回使用するツールはOWOX BI BIgQuery Reportsという無料のアドオンツールです。

というのも、GoogleのConnectedSheetを使用すれば、同様のことは可能なのですが、使用できる条件が、合わなかったので他の方法を探しました。

<!-- more -->

## 概要

OWOX BI BIgQuery Reportsというツールを使って、BigQueryからGoogleスプレッドシートに出力する方法をご紹介します。


## 使用するツール

OWOXの[OWOX BI BIgQuery Reports](https://gsuite.google.com/marketplace/app/owox_bi_bigquery_reports/263000453832)というサービスです。

BigQueryを直接スプレッドシートに出力できるものです。

[OWOX](https://www.owox.com/)はOWOX BIというデータ可視化ツールを提供されています。

OWOXが別途無料で公開しているツールがOWOX BI BIgQuery Reportsのようです。

BigQueryのクエリの課金以外は、無料で利用することができます。


## 使用できる条件

- GoogleWorkPlaceを利用できること

## 設定の流れ

1. OWOX BI BIgQuery Reportsをインストールする

2. OWOX BI BIgQuery Reportsを使ってスプレッドシートからBigQueryのクエリを実行できるようにする

3. 定期的に2を実行するように設定する

## 1. OWOX BI BIgQuery Reportsをインストールする

[Googleのマーケットプレイス](https://gsuite.google.com/marketplace/app/owox_bi_bigquery_reports/263000453832)からインストールできます。

## 2. OWOX BI BIgQuery Reportsを使ってスプレッドシートからBigQueryのクエリを実行できるようにする

2-1. 出力先のスプレッドシートを開く。

2-2. 「アドオン」タブ →  「OWOX BI BIgQuery Reports」 →  「Add a new Report」を押す。

![スクリーンショット 2021-09-17 10.07.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627146/e478981f-efae-19bd-2261-60bff9883b7a.png)


これで右側に「Add & Run a new report」というウィンドウが立ち上がります。

2-3. BigQueryの設定をする。

「Select Google BigQuery project」は、GoogleCloudPlatformのプロジェクト名を、

「Select a query」で、「+ Add new query」を選択します。

2-4. クエリを書いて保存する。

「Add a new query」というウィンドウが開くので、ここに実行したいクエリを書き、「Save＆Run」もしくは「Save」するだけです。

![スクリーンショット 2021-09-17 11.44.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/627146/e5a3499c-9fed-220e-6dc0-7e9a84828a12.png)

これらの、クエリの設定は、スプレッドシートの1シートごとに設定できます。

## 3. 定期的に2を実行するように設定する

定期実行の設定は、同じく「アドオン」タブから行えます。

3-1. 「アドオン」タブ →  「OWOX BI BIgQuery Reports」 →  「Schedule Reports」を押す。

成功時や失敗時にメールで通知を受け取ることもできます。

## おまけ. 他のスプレッドシートにコピーする

このスプレッドシートを他の人と共有したかったのですが、
クエリが叩けてしまうスプレッドシートを共有するのは抵抗がありました。

そこでスプレッドシートにGASを書いて、別スプレッドシートに丸々コピー、それを共有することにしました。

```js
const TO_SPREAD_SHEET_KEY = '<TO SPREAD SHEET KEY>';
const TO_SPREAD_SHEET_NAME = '<TO SPREAD SHEET NAME>';
const FROM_PREAD_SHEET_NAME = '<FROM SPREAD SHEET NAME>';

function copyToSpreadSheet() {
  const toSpreadSheet = SpreadsheetApp.openById(TO_SPREAD_SHEET_KEY).getSheetByName(TO_SPREAD_SHEET_NAME);
  const currentSpreadSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(FROM_PREAD_SHEET_NAME);

  let column = currentSpreadSheet.getLastColumn();
  let raw = currentSpreadSheet.getLastRow();

  let values = currentSpreadSheet.getRange(1, 1, raw, column).getValues();

  toSpreadSheet.getRange(1, 1, raw, column).setValues(values);
}
```

ここまで読んでくださってありがとうございました！
Exam Readiness：SAProのメモ

##はじめに
　こんにちは。今回はAWS資格の最難関SAPについてExam Readinessを視聴し大切だなと感じた部分をメモとして残そうと思います。

　それでははじめます(｡･ω･)ﾉﾞ

##クロスアカウント認証とアクセス戦略
AWSにはMicrosoft Active DirectoryをAWSのほかのサービスと一緒に使用するための方法があり下記の3つの異なるものがある

   * **AWS Managed Microsoft AD**
       * Microsoft Active Directoryが**AWSクラウド内**に必要である 
        * AWSでマネージド型Active Directoryを使用可能に
   * **AD Connector**
      * オンプレミスのユーザーがADを介してAWSのサービスにアクセスする必要がある
        * オンプレミスユーザーがActive Directory経由でAWSのサービスにアクセスできるようにする
   * **Simple AD**
  * 低スケール、低コストの基本的なADの機能を提供する
        * Simple ADはMFAをサポートしてない


◆**フェデレーティッドユーザー** 
　フェデレーティッドユーザーとはAWSアカウントを持たないユーザー（またはアプリケーション）を指す

◆**フェデレーティッドユーザーのロール**
　ロールを使用することでフェデレーティッドユーザーに一定の期間にわたりAWSリソースへのアクセス権を付与できます。
　これはMicrosoft Active Directory、LDAP、Kerberosなどの外部サービスで認証できるAWS以外のユーザーが存在する場合に役立つ
　
　　　※**LDAP（Lightweight Directory Access Protocol）とは**：ディレクトリサービスへとアクセスするためのプロトコル
　　　※**Kerberosとは**：ケルベロス認証では1度ログインすると次回のログイン時にID/パスワードを再度入力する必要がなくSSOを実現する方式の一種

◆**一時的なAWS認証情報**
　一時的なAWS認証情報とロールを組み合わせて使用するとAWSユーザーとAWS以外のユーザー（企業のアイデンティティおよび認可システム内）との間でIDフェデレーションを提供できる。

##ネットワーク
　ハイブリッドに関する理解が必要で以下のサービスおよび知識が必要

##ハイブリッド型-VPN接続

* **AWS マネージドVPN**
    * リモートネットワーク上のオンプレミスネットワーク機器からVPCにアタッチされたAWSマネージド型ネットワーク機器へのハードウェアVPN接続

* **AWS VPN CloudHub**
    * 複数のリモートブランチオフィスをVPCに接続するハブアンドスポークモデル

* **ソフトウェアVPN**
    * リモートネットワーク上の危機から、VPC内で実行されているユーザー管理型ソフトウェアVPNアプライアンスへのVPN接続

##ハイブリッド型-AWS Storage Gateway
　Storage Gatewayを設定して、ファイルゲートウェイ・仮想テープライブラリ（VTL）・保管型ボリュームゲートウェイ・キャッシュ型ボリュームゲートウェイを作成する。これらはオンプレミスアプリケーションによってiSCSIデバイスとしてマントできる。

* **ファイルゲートウェイ**
    * ファイルゲートウェイでは**NFSなどのファイルプロトコル**を使用してS3やGlacierでのオブジェクトの保存や取得を実行できる。
    * IAMロールを使用して、選択したS3バケットにマッピングされるファイル共有を設定します。
 
* **テープゲートウェイ**
    * **仮想テープ**のデータはS3内にも保存されGlacierにアーカイブすることも可能
    * マネコンでデータ転送とストレージインターフェースのステータスをモニタリングする
    * APIまたはSDKを使用して、アプリケーションとゲートウェイ間のやり取りを管理する。

* **保管型ボリュームゲートウェイ**
    * このゲートウェイに書き込まれたデータは、オンプレミスのストレージに保存され**EBSスナップショット形式でS3に非同期でバックアップ**される。
    * ストレージボリュームは最大16TBまで作成可能でオンプレミスのアプリケーションからiSCSIデバイスとしてマウントされる。

* **キャッシュ型ボリュームゲートウェイ**
    * 最大32TBのストレージボリュームを作成できオンプレミスからiSCSIデバイスとしてマウントできる。
    * 書き込まれたデータはS3に保存されるが、**最近書き込みや読み込みをしたデータのキャッシュのみがオンプレミスのストレージにローカルに保存される。**
    * S3にあるボリュームデータのポイントインタイムスナップショットをEBSスナップショットの形式で作成できる。
    * これによりデータ保護と様々なデータ再利用のニーズに合わせて容量効率に優れバージョニングされたボリュームのコピーを提供する。
 
##VPCエンドポイント
　VPCエンドポイントはインターネットゲートウェイや仮想ゲートウェイを通さずにインスタンスがプライベートIPを使用して、サービスと接続することを可能にする仮想デバイスになる。

* **インターフェースエンドポイント**
    * プライベートIPを持ったENIでAWS PrivateLinkを使用するサービス宛のトラフィックのエントリーポイントになる。
    * 試験ではS3DynamoDB以外のエンドポイントはほぼこれ

* **ゲートウェイエンドポイント**
    * ルートテーブルで指定されたルートのターゲットであるゲートウェイでし。サポートされているAWSのサービスはS3やDynamoDBなどがあります。

##マルチアカウントのAWS環境
　AWS のお客様の多くが、ビジネスユニットごとの個別アカウントや、開発、テスト、本番リソースの別個のアカウントなど、組織のために複数の AWS アカウントを作成しています。

開発リソースと本番リソースで別個の AWS アカウント (通常は一括請求 (コンソリデーティッドビリング) と併用) を使用することで、お客様は種類の異なるリソースを明確に分離できます。これにはセキュリティ面での利点もあります。

* **AWS Organizations**
    * **複数のAWSアカウントをポリシーベースで一元管理する**
    * すべてのアカウントに対するポリシーを管理し、不要なアクセスをブロックする
    * APIを使用して新しいアカウントの作成を自動化
    * アカウントを組織単位（OU）で編成
    * 一括請求を提供

##おわりに
　ひとまずExam Readinessの組織の複雑さに対応する設計部分のメモは終了としてその２として新しく書いていきます。
　
　(｡･ω･)ﾉﾞバイバイ
abscract classを使ったプログラム

abctract classを使った糸魚川市のプログラムです。


```Java
package itoigawa;
import java.util.Scanner;



abstract class ItoigawaCity{
	void ItoigawaCity() {}
}

class ItoigawaRikyu extends ItoigawaCity {
	private String city = "糸魚川市";
	void ItoigawaCity() {
		System.out.println(city);
	}
	void ItoigawaRikyu() {
		String shop_name="糸魚川利休";
		System.out.println(shop_name);
	}
	void SetItoigawa(String s) {
		if (s.equals(city)== true) {
			this.city = s;
		} else {
			this.city = city;
		}

	}
	String GetItoigawa() {
		return this.city;
	}
}

public class Itoigawa2 {
	public static void main(String[] args) {
		ItoigawaRikyu ir = new ItoigawaRikyu();
		Scanner sc = new Scanner(System.in);
		System.out.println("糸魚川利休のある市はどこでしょう？");
		String shop_name2 = sc.nextLine();
		ir.ItoigawaCity();
		ir.ItoigawaRikyu();
		ir.SetItoigawa(shop_name2);
		String ans = ir.GetItoigawa();
		System.out.println(ans);
		sc.close();

	}
}
```
Raspberry Pi OS イメージの作成方法

**はじめに**
Raspberry Pi4 を使用するにあたり OS のイメージ作成が必要になる。 
最近(2020年頃？) 新規の [OS作成ツールがリリース](https://www.raspberrypi.org/software/ "Raspberry Pi OS") されているにも関わらず
ネット検索するも 書籍を見ても従来方法での記述であり 非常に悩んでしまった。

特にmicroSDカードの初期化(FAT32 による Format) については、疑問が多かった。
ここでは、私の行った Raspberry Pi4 の OSイメージ作成方法を紹介する。

---
**OSイメージ作成の具体例**
Step1：[https://www.raspberrypi.org/software/](https://www.raspberrypi.org/software/ "Raspberry Pi OS")よりOSのイメージを作成する。
&emsp;&emsp;&emsp;&emsp;環境(Windows/macOS)に合わせたツールをダウンロードした後実行する。
&emsp;&emsp;&emsp;&emsp;★Windows の場合 [imager_1.7.5.exe]（2023年9月6日現在) である。
![Menue.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/14b470b1-3649-ad9f-3504-54ebccacd097.png)
Step2: [ストレージを選ぶ] より ターゲットとなる microSDカード を選択する
&emsp;&emsp;&emsp;私の場合は、下記を選択
&emsp;&emsp;&emsp;※USB起動も可能詳細は、[ここから](https://qiita.com/ytetsuo/items/6f94da8f85843a74ee9b)
![Pi2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/0b11a18b-2ce1-4571-d254-c641f66a499d.jpeg)
Step3: [OSを選ぶ]より下記を選択をした後[書き込む]を押下　(microSDカードがFAT32でFormtされる)
&emsp;&emsp;&emsp;★多くの解説記事で FAT32のFormat に関する記述が抜け落ちている。(重要なのに！！)
![Pi2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/f84b3489-f4d2-73e1-8a55-452ad198b1b9.jpeg)
Step4: Format後に[ストレージを選ぶ]を再設定して[OSを選ぶ] より下記を選択後[書き込む]を押下
&emsp;&emsp;&emsp;OSイメージの作成が開始される。
![Pi1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2056854/09aaafc8-1371-07a0-d529-e377838975d3.jpeg)
★数分で OSのイメージが作成される。
≪注意：私が最初にはまったこと≫
◎Windowsは、32GB以上のSDカードに対してFAT32をサポートしていない。
&emsp; 故に、ここで示したツールを用いてFAT32にする必要がある。
&emsp;また、Windowsは うるさい程に ＜新たにFormatする必要がある＞
&emsp;＜このFormatには、対応していない＞など メッセージを表示するが 無視する。
&emsp;★Windowsは、32G以上のSDでは、exFAT のファイルシステムを推奨している。
◎ネット検索などでは、他のFormatツールを用いてFAT32にする様に記載されているが
&emsp;他のツールでFAT32にしても　ここで示したツールは、イメージの作成はしてくれない。
◎最初他のツールでFAT32にしたためか、このツールで FAT32にFormatしたにも関わらず
&emsp;OSイメージの作成が数時間も必要であった。
&emsp;２回目以後は、サクサクと 数分でイメージ作成をしてくれる。(原因不明)

以上です。

---
☆2021年9月22日(水) 午前6時10分 初版(Ver. 1.00)作成
☆2022年1月11日(火) 午前3時00分 Ver. 1.01 - USB起動について追加
☆2023年9月06日(水) 午前9時55分 Ver. 1.02 - イメージ作成ツールのバージョン変更

---
Ubuntu で windows 共有サーバにアクセス samba

参考にしたサイト

http://www.yamamo10.jp/yamamoto/comp/home_server/WEB_server3/samba/index.php

https://renoji.com/IT.php?Contents=OS_CentOS/Server_File/Samba_UserRegistration.html

https://www.teradas.net/archives/4915/

https://www.geekfeed.co.jp/geekblog/linux-mount/
[android]DataBindingでcouldn't make a guess forが出て困った話

こんにちは。
[DataBinding](https://developer.android.com/topic/libraries/data-binding?hl=ja)についての話です。

__Cause: couldn't make a guess for 〜〜.entity.item__

xmlファイルにdataclassやviewmodelの変数を用意してそこに丸ごとつっこむやり方で起きたエラーです。
何やら記述されているクラスに対して推測ができないといったことが書いてあります。
パッケージを辿ってこれがどんなクラスなのかstudio は理解している(item.○○ といったプロパティアクセスができる)のに、このようなエラーが吐かれてしまいます。

調べてみたところ、これは[kotlinの命名規則](https://kotlinlang.org/docs/coding-conventions.html)から外れているため起こったエラーでした。

kotlinが採用している命名規則は以下の通りです。

|クラス|変数、関数|パッケージ|
|:--|:--|:--|
|アッパーキャメルケース|キャメルケース|スネークケース|
|HelloMyNameIs|helloMyNameIs|hello_my_name_is|

これに従っていないと、読み込み時に推測ができなくてエラーになってしまいます。僕の場合は末尾のitemがクラスなのに小文字で始まっているため発生したエラーでした。うっかりです。
同様に、パッケージ名に大文字が混じっていたりしていてもエラーになります。


以上、
「DataBindingでcouldn't make a guess forが出て困った話」でした。
末筆ながら、誰かの役に立つことがあれば幸いに思います。
RPI4にDockerとDocker-compose をインストールするまで


個人の備忘録です。
よりよい方法のご提案コメントで是非ください。

Docker をインストールします。
すこし前はこんな簡単にインストール出来なかったと思いますが、いつの間にかコピペで出来るようになっていました。
参考: [Raspberry Pi Blog-Docker comes to Raspberry Pi](https://www.raspberrypi.org/blog/docker-comes-to-raspberry-pi/)

```bash:
curl -sSL https://get.docker.com | sh
```

権限の付与

```bash:
sudo usermod -a -G docker ${USER}
```


参考: [Raspberry Pi3/4にDockerとdocker-composeをインストールする方法](https://debimate.jp/2020/09/27/raspberry-pi3-4%E3%81%ABdocker%E3%81%A8docker-compose%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)
Python3パッケージマネージャであるpip3でインストールできるVersionを使用します
そのため、まずはpip3の依存パッケージをインストールします。
ここの前提知識がなかなか見つからず,ずっとインストールできませんでした。心から感謝します。

```bash:
sudo apt install libffi-dev libssl-dev python3 python3-pip python3-dev
```
Docker Composeをインストールします。

```bash:
sudo pip3 install docker-compose
```

確認

```bash:
docker -v
docker-compose -v
```





# 最後にまとめ

Docker
Docker-compose
これらをインストールする.
初めてのセットアップからワンストップでDockerインストールまで行うとコケるので、再起動後に実行することをおすすめします。

```zsh:
# docker
curl -sSL https://get.docker.com | sh 
# sudo 無しで実行したいので権限付与
sudo usermod -a -G docker $USER 

# docker-compose
sudo apt install -y libffi-dev libssl-dev python3 python3-pip python3-dev && \
sudo pip3 install docker-compose 

# 確認
echo '+++++++++++++++' 
docker -v 
docker-compose -v 
```
cloud schedulerをfunctionから操作する

# 概要

GCPコンソールからではなく、Webクライアントから cloud schedulerを操作する方法の一つとしてfunctionから呼び出してみるメモ。

## やり方

cloud schedulerの操作は `google-cloud/scheduler` ライブラリを使えば利用できます。

- cloud schdeuler api
    - https://cloud.google.com/scheduler/docs/reference/rest

webアプリから呼び出すには以下の方法

- 直接APIを叩く
- functionとして実装して呼び出す

直接叩く場合は、サーバにデフォルトの認証情報(環境変数 `GOOGLE_APPLICATION_CREDENTIALS`)を仕込んでおく、もしくはプログラム内で認証情報としてサービスアカウント、キー情報などを渡してあげる必要があります。

https://cloud.google.com/docs/authentication/production#automatically

今回はfunctionとして実装し、もともと紐づけられているサービスアカウント情報を使ってAPIを実行するようにします。

## functionの実装

ライブラリにjobを作るサンプルがあるので、今回は既存のjobを一時停止するAPIを叩くfunctionを作ります。

先に `npm install @google-cloud/scheduler`を実行しておきます。

functionのコードは以下の通り

```javascript
import * as functions from "firebase-functions";
import { app } from "firebase-admin";
import { CloudSchedulerClient } from "@google-cloud/scheduler";
import { RuntimeOptions } from "./options/runtimeOptions";

module.exports = functions
  .region("asia-northeast1")
  .https
  .onCall(async (data, context) => {

    const client = new CloudSchedulerClient();
    const projectId = app().options.projectId;

    try {
      const jobPath = client.jobPath(projectId, "asia-northeast1", "firebase-schedule-someapi-asia-northeast1");
      const request = { name: jobPath };
      const ret = await client.pauseJob(request);

      console.log(ret);
      return true;

    } catch (e) {
      console.log(e.message);
      return false;
    }

  });

```

一時停止は `pauseJob` という関数を実行します。引数に `PauseJobRequest` として `name` を渡します。
name にジョブ名を指定すれば良いと思っていたのですが、ずっとエラーになっておりなんだろ。。と思っていたら、`jobPath` 関数を使ってパスを生成して引き渡す必要があったようです。
ドキュメントではPauseJobRequestのnameプロパティの説明として、「PauseJobRequest name」としか書いてないのでわかりづらすぎ。。

pauseJobの戻り値には以下のようなjob情報が渡されます。

```console
[
  {
    name: 'projects/<projectId>/locations/<region>/jobs/firebase-schedule-someapi-asia-northeast1',
    description: '',
    userUpdateTime: { seconds: '1631762543', nanos: 0 },
    state: 'ENABLED',
    status: { details: [], code: 0, message: '' },
    scheduleTime: { seconds: '1632330000', nanos: 582680000 },
    lastAttemptTime: { seconds: '1632243600', nanos: 372395000 },
    retryConfig: null,
    schedule: '0 2 * * *',
    timeZone: 'Asia/Tokyo',
    attemptDeadline: null,
    pubsubTarget: {
 　    attributes: [Object],
      topicName: 'projects/<projectId>/topics/firebase-schedule-someapi-asia-northeast1',
      data: <Buffer >
    },
    target: 'pubsubTarget'
  },
  null,
  null
]
```
EC-CUBE4でデータベースにUnixソケット接続する場合の設定

いつも忘れるので備忘録

## PostgreSQL

```sh
DATABASE_URL=pgsql://socket:/var/run/postgresql[DB名]?user=[User名]&password=[パスワード]
```
`socket:/var/run/postgresql/.s.PGSQL.5432/`を指定すると`socket:/var/run/postgresql/.s.PGSQL.5432/.s.PGSQL.5432`とかに接続しようとして接続できない。


## MySQL

```sh
DATABASE_URL=mysql://socket:/var/run/mysqld/mysql.sock[DB名]?user=[User名]&password=[パスワード]
```

試してないけどたぶんコレで繋がる
urlパラメータで内容を変える

##Urlからパラメータを取ってきてコンテンツを変える


```jquery:urlからパラメータをとる
/**
 * Get the URL parameter value
 *
 * @param  name {string} パラメータのキー文字列
 * @return  url {url} 対象のURL文字列（任意）
 */
function getParam(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
}

var para = getParam('para');
```


##パラメータでコンテンツを表示非表示

```jquery:jquery

var con = [con1,con2,con3]

if($.inArray(para, con) !== -1){
	$('.contents').hide();
	$('#contents-' + i).show();
}

```




----------------------------
参考にしました

https://www-creators.com/archives/4463

https://js.studio-kingdom.com/javascript/regexp/exec

http://semooh.jp/jquery/api/utilities/jQuery.inArray/value%2C+array/
symfony monologでログをGCPなどのログに出力する設定

EC-CUBE4の標準の設定だと鬼の様にログを吐いて、ちょくちょくディスクフルで死ぬ。
なので、monologのログの出力先を標準出力にしてクラウドのログで見る設定

```yaml
        main_rotating_file:
            type: stream
            max_files: 60
            path: 'php://stderr'
            formatter: eccube.log.formatter.line
            level: debug
```
そもそも吐くログレベルを変えるのはまた
Workato：秘匿情報（パスワードやAPIトークン）をWorkato上でセキュアに管理し、利用するには

# はじめに
WorkatoでパスワードやAPIトークンのような秘匿情報を扱う際、以下のようにべた書きでそのような情報をセットすることは推奨されません。（Workato社も推奨していません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/327616c2-eaf1-9f89-77d8-2d6447213055.png)

また、HTTPコネクターなどの一部のコネクターでは、秘匿情報がべた書きでフィールドにセットされると、以下のように警告メッセージが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/40515d18-1a24-2892-a16e-77541cd6091e.png)

レシピ上に秘匿情報をべた書きでセットすることは、権限の無いユーザーにその情報が見えてしまう（見せるべきではないユーザーにその情報が見られてしまう）、レシピを共有する際に秘匿情報を含めて共有されてしまう等、セキュリティリスクとなる場合がありますので、行うべきではありません。

それでは、Workatoで秘匿情報を管理し、使用するにはどうしたら良いのか・・・ということで、今回はその手順についてご説明します。

# 対応方法
## Account Propertiesでの値管理
秘匿性の高い情報は、「Account Properties」を利用して管理します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/eb60ebbd-52e1-3883-237b-40cf26a3af02.png)

Account Propertiesは、ワークスペース内の全てのレシピより参照可能な定数を管理する機能で、Key-Value形式で値を管理することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/d2d29933-25b5-44d6-eb76-908e0504571d.png)

## レシピ上でAccount Propertiesの値を利用する
Account Propertiesで定義された値は、以下のようにデータピルより選択し、各フィールドへセットして利用することが出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/3a0b2126-83ca-abde-c4f2-06c6dee00d42.png)

## データマスキング（Mask data）の有効化
上記設定までの状態でレシピを実行すると、ジョブの実行履歴上では、次のように秘匿情報が丸見えの状態となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/0d565b45-1e9d-978e-9204-ce864fd2a744.png)

Account Propertiesは、あくまでも定数を管理する機能であり、レシピ実行時にその値を不可視（マスキング）する機能は持ちません。Workatoでこのような値をマスキングするには、該当するステップ（アクション）に対して、「Mask data」を有効化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/7780512a-41be-f712-9843-538e078b7a50.png)

「Mask data」を有効化することで、ジョブの実行履歴上においては、当該ステップの結果が以下のように非表示の状態となり、秘匿情報が履歴上に残ることを回避することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/9fbbbd34-5575-dfbe-09f6-1a55b70f8312.png)


# 参考
https://docs.workato.com/recipes/recipe-security.html
10年後、何が起こってるかわからない。けど、基礎は勉強しよう。

## 未来は確実には予測できない。
まぁ、当たり前ですよね。
未来は確実には予測できません。
もしかしたらReactやVue.jsの採用数が減り、新しいフレームワークが主流になることだってあり得ます。
ただ、HTML、CSSなどの言語は消えていません。
JavaもCもあんなに歴史が長いのに、消えていません。

言語は消えないから、いつでも新しいフレームワークを勉強できるために、
「基礎」を勉強する必要があるかなと思いました。

## 10年後に備えて勉強しておいた方がいいもの
いろいろあると思いますが、
自分のやりたいこととマッチした言語の基礎を勉強するのが一番必要だと思います。

例えば、Webデベロッパーの場合は、HTML & CSS、JSはもちろん、
React、Vue.jsなどのフレームワーク、時間があればGoogle APIなどの応用的な部分まで勉強することで、
10年後に備えられるかと思います。

大事なのは「基礎」。
これをすっぽかして、何度も痛い目を見ました。

## 10年後、何が流行るか（個人的予想）

個人的には、言語は消えないと思います。
ただ、JavaScriptで書かれているのはTypeScriptなどに置き換わると思います。

また、Reactは古い技術と言われながらも生き続けると思います。
あのjQueryでさえ、いまだに生き続けているからです。

正確な予想はできませんが、自分でしっかりと未来に備えて勉強したいです。

## 最後に
私はまだ中学生で、まだまだ新米と言っていいと思います。そして、技術も言うほどありません。
ですが、私にはまだたくさんの時間があり、その時間をJavaScriptなどの学習に使いたいと考えています。
10年後、何が起こるかわかりません。ですが、それに対応する知識と柔軟性があったら乗り越えられると思います。
API GatewayでLambdaに関数:${stageVariables.alias}を指定してエラーが出た場合

# 動作環境
- MacBook Air (M1, 2020)
- AWS 
- AWS CLIがインストールされていること

# :${stageVariables.alias}とは
- `:${stageVariables.alias}`とは、API Gatewayのステージ変数です。
- これをLambda関数のあとに指定すると、ステージごとに異なる値を設定できます。
- 保存時に出てくるコマンドをAWS CLIを使って手動で指定します。
- [参考サイト](https://dev.classmethod.jp/articles/version-management-with-api-gateway-and-lambda/)
- [参考サイト2](https://qiita.com/szk3/items/298dfc8bb86ba802617f)
  - 手順はリンク先のページを参考にして下さい。このページではあくまで、エラーに関しての解決策を書いています。

# ターミナルから実行する際にハマったエラー

- 以下のコマンドを実行する際にいろんなエラーが出ます。
- 正確には、AWSの画面で表示されるコードをそのままターミナルにペーストすると、複数の原因によりエラーになってしまいます。

```
aws lambda add-permission --function-name arn:aws:lambda:ap-northeast-1:000000000000:function:test-hello:dev --source-arn 'arn:aws:execute-api:ap-northeast-1:000000000000:xxxxxxxxxx/*/GET/' --principal apigateway.amazonaws.com --statement-id 00000000-000000000-000000000000000 --action lambda:InvokeFunction
```

## bad substitutionが表示される場合
- モーダルで表示されたコマンドの`:${stageVariables.alias}`をエイリアスで決めた変数名に置き換えてから、コマンドを実行しましょう。

## >が表示される場合

- --function-nameのダブルクォーテーションを削除しましょう。
- `control + c`で抜けれます。

## aws: error: argument operation: Invalid choice, valid choices are:が表示される場合

- オプションの前の半角スペースの数を1つに変えましょう。(デフォルトでは半角スペースが3つ入っていますが、このまま実行すると、上記のエラーになります。)
- `--action lambda:InvokeFunction`の後のスペースを一度消してから、もう一度半角スペースを入れて見てください。もしかすると、エラーが解消されるかもしれません。(--profile などのオプションを追加した場合など)

## You must specify a region. You can also configure your region by running "aws configure".が表示される場合

- 複数のAWSのアカウントをcredentialsで管理している場合は、コマンドの最後に `--profile [文字列]`を追加して実行しましょう。
- また、`~/.aws/credentials`のファイルか、`~/.aws/config`のファイルが間違っているために、このエラーが表示されている可能性もあります。正しく修正しましょう。
- [参考サイト](https://qiita.com/shin1988/items/948501a3bf742e7959ab)

## zsh: no matches found:が表示される場合
- 原因が2つ考えられます。1つは、ダブルクォーテーションを利用していることが原因の場合、2つ目はzshを利用していることが原因である場合です。

### ダブルクォーテーションを利用している場合
- ダブルクォーテーションを削除して実行します。
- [参考サイト](https://stackoverflow.com/questions/63647830/sending-message-to-aws-lambda-from-aws-pinpoint-custom-channel)

### zshを利用している場合
- ~/.zshrcに以下を記述して、source ~/.zshrc

```
setopt +o nomatch 
```
- [参考サイト](https://qiita.com/nisaji/items/f9eede2164a74bc08db7)

- 別の解決策として、zshからbashにSHELLを切り替える方法もあります。

## aws: error: the following arguments are required: --actionのエラーが表示された場合

- `--action`の直前の半角スペースをもう一度入れ直したら、解決しました。

## An error occurred (ResourceNotFoundException) when calling the AddPermission operation: Cannot find alias arn: arn:aws:lambda:ap-northeast-1:yyyyyyyyyyy:function:xxxxxxxxx:dev のエラーが表示された場合

- Lambda関数にエイリアスが設定されていません。

# あとがき
- とりあえず、忘れないうちに急いでまとめたので、間違っているかもしれません。
Rustの型宣言まとめ

## 数値型
アルファベット1文字とビット数であらわす。
アルファベットは以下の意味を持つ。

- i：符号あり整数
- u：符号なし整数
- f：浮動小数点型

u64 ⇒ 符号なし64ビットの整数

## 文字列型
strとStringがある。
コアライブラリの中で定義されているのはstrのみで、Stringは標準ライブラリで定義されている。

### str
スライスと呼ばれるもの。
文字列のスタートのメモリ番地と文字列長を保持している。
変更不可なので、定数を定義しておき、その定数を``&str``の形で参照を保持するのに使うことが多い。

### String
変更が可能な文字列型。
文字列操作を行う場合にはこちらの型を利用する。

## タプル
複数の型の値を格納できる。
後述する配列は、特定の型の値しか保持できない。
タプルは内部の値の型を含めて一つの型として扱われるため、後から内部の値の型を変えることは出来ない。

## 配列
特定の型の値を複数格納できる。
配列サイズはコンパイル時に決まっている必要がある。
xaringan on RMarkdown on VSCodeプレゼン環境構築

# 環境
- Windows 10
- VSCode上でRMarkdownファイルを編集
- xaringanでブラウザ上でのプレゼンを行う

# インストール手段
## R
- https://cran.r-project.org/bin/windows/base から最新版をダウンロード、インストール
- 途中のコンポーネントの選択でMessage translationsはチェックを外す。文字化けするため

## Rのパッケージ
- 以下のパッケージをインストールする
    - language server
    - knitr
    - rmarkdown
    - xaringan

```R
install.packages("languageserver")
install.packages('knitr', dependencies = TRUE)
install.packages('rmarkdown')
install.packages("xaringan")
```

## Pandoc
- https://pandoc.org/installing.html でPandocのインストールを行う
- PandocはR MarkdownのKnitに必要

## VSCode上の設定
- 以下の拡張機能をインストールする
    - R 
    - R Debugger
    - Preview on Web Server
        - HTML PreviewはDark modeを使うと色がおかしくなったり、knitrした後の更新がされないものが多く、利用できなかった。

# 結果
- 以下に示すようなVSCode内で完結するxaringanの編集、プレビュー環境を構成した。
    - R Markdown(.Rmd)ファイルをVSCodeの左側で編集し、プレビューを見たいときは実行ボタンを押し、knitrする。
    - knitrで出力されたHTMLファイルをPreview on Web Serverで開き、VSCodeの右側に表示する。
raspberry pi zeroの初期設定の注意(アップデート時、画面が固まってしまうあなたに)

raspberry pi zeroの初期設定でつまづいたことを書いていく。

とにかく初期設定のアップデートで何回も処理落ちしてしまった。
途中で画面もカーソルも固まってしまいどうにもできない。
電力も５V２Gを使用しているため問題ない。
Wi-Fiも繋いだ。
SDカードがおかしくなったのか？と思ったが問題はなかった。

結局、問題があったのはWi-Fiだった。
筆者は実家(４人)に住んでいるのだが日中に何度もアップデートを試みるも
画面が固まってしまったが
夜遅くにアップデートを行ったらなんとできたのだ。
おそらく日中は家族が携帯やパソコンを使用していたためできなかったが
夜遅くで誰もWi-Fiに接続した機器を使用していなかったためだと思われる。
(ただ、どちらもWi-Fiのマーク的には電波に問題はなかった)

何度もアップデートで画面が固まってしまう人は
時間帯を変えてやるのもいいかもしれない。

#ちなみに
初期設定ウインドウの最後にソフトウェアをアップデートするか聞かれるが
個人的にここでしなくていいと思う。

理由としては動いているのかフリーズしているのか非常に分かりづらいからである。
ターミナルで全く同じことができるためターミナルの方が動きを確認できて
安心感がある。
(進捗が％で表示される。)

ちなみにターミナルで

```
$ sudo apt update
$ sudo apt full-upgrade -y
$ sudo apt autoremove -y
$ sudo apt clean
$ sudo reboot
```

と行うことで初期設定ウインドウのアップデートと同じ状態にすることができる。
[参考にしたサイト](https://raspida.com/rpios-update-upgrade?amp=1)

全部終わるのに１時間３０分はかかったので
時間があるときにアップデートをしよう！
こんな大人になりたい

※技術系とは言えないような内容かもしれませんが、キャンペーンの応募も兼ねて自分の理想の未来の姿を書いてみました。 
21.10/14[追記]:プレゼントも当たり、みなさんからのLGTMも沢山貰えました！！本当に嬉しいです！！！
⬇キャンペーン
https://qiita.com/official-events/12fc7bacec894d33a981

自分は今15歳で、もうすぐ受験なのであまり開発などは出来ません。
が、10年後、つまり25歳の頃には立派なエンジニアとして世に出ているといいなぁ、と思っています。

# 学んでおきたいもの
自分は今

|分野|詳細|
|-|-|
|Linux|KDE plasmaのテーマ作成|
||基本的なコマンド、シェルスクリプト|
||ディストリの開発|
|Qt|KirigamiというQtQuickのフレームワークを用いて、アプリの開発。日本人初かも、、、？
|HTML/SASS|基本的にどのようなサイトでも表現出来るし、学校HP担当になった|
|C#|TweetCatというツイート専門のTwitterクライアントを作るなど少しできる|
|FE|残念ながら不合格でしたが、あと午後2.5点で合格でした。|
|マネジメント|Ablazeというチームの代表。将来どうなるのか|
のような感じで、まだまだ非力です。
が、将来は･･･

# こうなっていたい
- 大好きなMicrosoftで働き、KDEに貢献したい
- Kirigamiをマスターしていたい。Linux向けのとても便利なソフトを作ったりしたい
- KDE plasmaの翻訳を今は少しか出来ないが、将来的には100%翻訳するなど貢献したい
- JSやTS, vue.jsなどを完全にマスターしたい。
- FEやAP, その他のIPAさんの資格も沢山とりたい

# 未来の自分へ
未来の自分、10年前の僕はこう思っています。
あなたは今どうしていますか？
しっかりと出来るようになりましたか？
もしも出来ていて、その頃までQiitaがあるならこの記事に今の生活を書き足して欲しいです。
【9/21（火）】仕事で学んだこと 

<h1>はじめに</h1>
<p>　9/21（火）に学んだことを次にまとめる。</p>

<h1>学んだこと</h1>
<p><b>・エクリプスでのクラス検索</b></p>
<p>　「Ctrl + Shift + R」で検索窓を表示し、任意の検索ワードを入力して検索する。</p>

<p><b>・テストクラス</b></p>
<p>　記述したプログラムの動作について<b>証明（試験、実験）</b>を行うクラスのこと</p>

<p><b>・DDL （Data Definition Language）ファイル</b></p>
<p>　データベースを定義するために用いられる言語（SQL）が記述されたファイルのこと</p>

<p><b>・Eclipseのエラーコード 4499</p>
　アプリケーション・サーバーが接続の確立を拒否したことを意味する。
　今回の場合、DBがローカルで起動していないことが考えられたので、下記手順を実施した。
　１、「コントロールパネル→管理ツール→サービス→【使用しているDBのサービス・プログラム】」を選択。
　２、「スタートアップの種類」を「自動」、「サービスの状態」を「開始」に設定。
　３、「OK」ボタンを押す。
　４、再度、エラーが発生したクラスを実行して、エラーが解消したかを確認。

<h1>まとめ</h1>
テストクラスでの証明とエラーコード：4499の解消に時間がかかってしまった。
だが、テストクラスの証明を行う際に、ソースコードを読むことや不具合の探し方などを少し教えてもらい、
テストの工程で行う業務の流れを触りだけ教えてもらうことができたことがよかった。
railsチュートリアル第五章 名前付きルート

####名前付きルート
ルートを定義したことにより、レイアウトの中で名前付きルートが使えるようになりました
速、link_toメソッドの2番目の引数で、適切な名前付きルートを使ってみましょう。

```html
<%= link_to "About", '#' %>
```
置き換え

```html
<%= link_to "About", about_path %>
```
HomeページとHelpページへのリンクを持つheaderパーシャル _header.html.erbから取り掛かります。
headerパーシャルでは、Web共通の慣習に従って、ロゴにもHomeページへのリンクを追加
#####headerパーシャルにリンクを追加する

```html
<header class="navbar navbar-fixed-top navbar-inverse">
  <div class="container">
    <%= link_to "sample app", root_path, id: "logo" %>
    <nav>
      <ul class="nav navbar-nav navbar-right">
        <li><%= link_to "Home",    root_path %></li>
        <li><%= link_to "Help",    help_path %></li>
        <li><%= link_to "Log in", '#' %></li>
      </ul>
    </nav>
  </div>
</header>
```
#####footerパーシャルにリンクを追加する

```html
<footer class="footer">
  <small>
    The <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    by <a href="https://www.michaelhartl.com/">Michael Hartl</a>
  </small>
  <nav>
    <ul>
      <li><%= link_to "About",   about_path %></li>
      <li><%= link_to "Contact", contact_path %></li>
      <li><a href="https://news.railstutorial.org/">News</a></li>
    </ul>
  </nav>
</footer>
```
変更後プレビューで確認　成功

名前付きルートを書いてない部分はクリックしてもアクセスできない。
```about_path```を書いていないと```about```ページにいけない。
しかし```/about```と書くと```about```ページに行ける。
```link_to```でクリックすると```about```ページに行けることを改めて感じた。
名前付きルートの名前はなんでもいいのかな？

####演習
1. helfルーティングを作成し、レイアウトのリンクを更新してみてください。

```rb
Rails.application.routes.draw do
  root 'static_pages#home'
  .
  .
  .
  get '/helf',     to: 'static_pages#helf'
end
```

```html
<footer class="footer">
  <small>
    The <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
    by <a href="https://www.michaelhartl.com/">Michael Hartl</a>
  </small>
  <nav>
    <ul>
      <li><%= link_to "About",   about_path  %></li>
      <li><%= link_to "Contact", contact_path %></li>
      <li><%= link_to "Helf",    helf_path %></li>
      <li><a href="https://news.railstutorial.org/">News</a></li>
    </ul>
  </nav>
</footer>
```
2.Undo機能を使ってこの演習で行った変更を元に戻してみてください。
元に戻した。
railsチュートリアル第五章 contactページ

##レイアウトのリンク
今度は'#'で代用していたリンクを書き換えてみましょう
RailsのERbテンプレートには素のHTMLを直接書くことも許されているので、次のようにリンクを直接記述することもできます。

```html
<a href="/static_pages/about">About</a>
```
上の記法はRails流ではありません
boutページへのURLは /static_pages/about よりも /about の方がよいでしょう。
Railsでは次のようなコードでは名前付きルートを使うのが慣例となる。

```html
<%= link_to "About", about_path %>
```
about_pathの定義を変えればabout_pathが使われているすべてのURLを変更できるため、柔軟性が高まります。

ページ名	　　URL	　　名前付きルート
Home　　　```　/```	　　　　　```root_path```
About	　　```　/about```	　　```about_path```
Help	　　　　```/help```	　　　　```help_path```
Contact	　　```/contact```	　　　```contact_path```
Sign up	　　```/signup```	　　　```signup_path```
Log in	　　　```/login```	　　　　　```login_path```

###Contactページ

#####コンタクトページのテスト

```rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Ruby on Rails Tutorial Sample App"
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
    assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
  end

  test "should get about" do
    get static_pages_about_url
    assert_response :success
    assert_select "title", "About | Ruby on Rails Tutorial Sample App"
  end

  test "should get contact" do
    get static_pages_contact_url
    assert_response :success
    assert_select "title", "Contact | Ruby on Rails Tutorial Sample App"
  end
end
```

#####Contactページのルートを追加する

```rb
Rails.application.routes.draw do
  root 'static_pages#home'
  get  'static_pages/home'
  get  'static_pages/help'
  get  'static_pages/about'
  get  'static_pages/contact'
end
```
#####Contactページ用のアクションを追加する

```rb
class StaticPagesController < ApplicationController
  .
  .
  .
  def contact
  end
end
```
#####Contactページのビューを追加する

```rb
<% provide(:title, 'Contact') %>
<h1>Contact</h1>
<p>
  Contact the Ruby on Rails Tutorial about the sample app at the
  <a href="https://railstutorial.jp/contact">contact page</a>.
</p>
```
これらの作業は前の章で演習としてcontactページを作っていた。
retrofit2とmoshiとenum

若干詰まったので、備忘録

# やりたかったこと
retrofit+moshiで、APIのレスポンス（json）をenumとしてデシリアライズして返してほしい


# 例：月の和名を返すAPI
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472695/47105826-7204-616e-7013-0e6268685e6f.png)

アプリ側から月（1～12）をサーバにリクエストすると、レスポンスとして月の和名が返却されるような連携があり、
アプリ側とサーバ側の双方で、返却値としてのEnumが定義されている前提。

|定数|値|
|---|---|
|MUTSUKI|0|
|KISARAGI|1|
|YAYOI|2|
|UDUKI|3|
|SATSUKI|4|
|MINADUKI|5|
|FUMIDUKI|6|
|HADUKI|7|
|NAGATUKI|8|
|KANNADUKI|9|
|SHIMOTUKI|10|
|SHIWASU|11|
|UNKNOWN|12|

#### フォーマット
```json
// リクエスト
{
　"month": 1
}

// レスポンス（名前で返す）
{
　"month_jpn": "MUTSUKI"
}

// レスポンス（序数で返す）
{
　"month_jpn": 0
}
```

#### アプリ側
```kotlin
// Enumの定義
enum class Wareki {
    // 縦に長いので折り返してます
    MUTSUKI, KISARAGI, YAYOI, UDUKI,
    SATSUKI, MINADUKI, FUMIDUKI, HADUKI,
    NAGATUKI, KANNADUKI, SHIMOTUKI, SHIWASU,
    UNKNOWN
}

// レスポンスを受け取るオブジェクトのクラス
data class ResData(
    @Json(name = "month_jpn") 
    val monthJpn: Wareki
)

// APIをコールする箇所
suspend fun fetchMonthJpn(month: Int) {
    try {
        // ここ
        val res = Api.service.fetchMonthJpn(ReqData(month))
        Log.d("TEST", res.raw().toString())

        val monthJpn = res.body()!!.monthJpn
        monthJpn.let {
            Log.d("TEST", it.name + ":" + it.javaClass)
        }
    } catch (e: JsonDataException) {
        Log.e("TEST", e.message!!)
    }
}

// moshiとretrofit
private val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

private val retrofit = Retrofit.Builder()
    .addConverterFactory(MoshiConverterFactory.create(moshi))
    .baseUrl(BASE_URL)
    .build()
```

# 1. enumを文字列として受け取る場合（名前で返却の場合）
enumを文字列として受け取る場合は、特に工夫なくそのままEnumとしてデシリアライズしてくれる。

```bash
D/TEST: Response{protocol=http/1.1, code=200, message=OK, url=http://10.0.2.2:8000/api/fetch_month_jpn/}
D/TEST: KISARAGI:class jp.co.sample.Wareki
```

# 2. enumを数値として受け取る場合（序数で返却の場合）
序数として受け取る場合は、デシリアライズできず例外が発生する。

```bash
E/TEST: Expected one of [MUTSUKI, KISARAGI, YAYOI, UDUKI, SATSUKI, MINADUKI, FUMIDUKI, HADUKI, NAGATUKI, KANNADUKI, SHIMOTUKI, SHIWASU, UNKNOWN] but was 1 at path $.month_jpn
```

### アダプターを導入する
こういった場合はアダプターを導入するとうまくいった。

まずはこんなアダプターを作成する。

```kotlin
class WarekiAdapter {
    @FromJson
    fun fromJson(monthJpn: Int): Wareki {
        return Wareki.values().find { it.ordinal == monthJpn } ?: throw IllegalArgumentException()
    }
}
```
moshiにaddするアダプターには、FromJsonかToJsonかのどちらかが必要。
今回はデシリアライズのみなので、FromJsonのみ定義し、jsonから受け取った値<monthJpn>と対応するenum値を
findで探して返却する。見つからない場合は例外を発出するような感じで作成した。

これをmoshiにaddする。

```kotlin
private val moshi = Moshi.Builder()
    .add(WarekiAdapter()) // ここ
    .add(KotlinJsonAdapterFactory())
    .build()
```

以上。

再度APIをコールすると、うまいことデシリアライズしてくれる。

```bash
D/TEST: Response{protocol=http/1.1, code=200, message=OK, url=http://10.0.2.2:8000/api/fetch_month_jpn/}
D/TEST: KISARAGI:class jp.co.sample.Wareki
```


# appendix
ちなみに、上記のアダプターを追加した状態で「1. enumを文字列として受け取る場合」を実施するとエラーになりました:sleepy:

```bash
E/TEST: Expected an int but was KISARAGI at path $.month_jpn
```


どちらでもデシリアライズしてくれるやり方を募集しています。
【PHP初心者】クラス変数とメンバ変数について

## はじめに
PHPを勉強しているときに「メンバ変数」という表記を目にしました。
過去に少しJavaを勉強していた時があり、「プロパティ」「フィールド」というワードはよく目にしていたのですが、「メンバ変数」はあまり馴染みがなかったのでちょっと調べてみました。

メンバ変数とよく対比される「クラス変数」についても併せて見ていきたいと思います。
（ 補足：Javaでも「メンバ変数」ってワードはあるようです。私がたまたま出会わなかっただけみたいです。笑）

## メンバ変数
調べて見たところ、__「インスタンス変数 = メンバ変数 = プロパティ」__と説明されているページが多く見つかりました。
>__参考：__
[【PHP】インスタンス変数（メンバ変数）](https://algorithm.joho.info/programming/php/instance-variable-php/)
[クラスから理解するPHPのオブジェクト指向](https://rightcode.co.jp/blog/become-engineer/php-object-orientation)
[【PHP入門】クラスとインスタンスの使い方
](https://sakuchan.org/php-usage-class-instance/)

ただ、中には
__「メンバ変数 = 静的メンバ（クラスメンバ）&動的メンバ（インスタンスメンバ)」__
のように、両方とも包含して「メンバ変数」といったニュアンスのページもありました。
その場合、「静的メンバ」「動的メンバ」のようにセットで明記されています。
>__参考：__
[【PHP入門】クラス変数・クラスメソッドを使用する方法(static)](https://www.sejuku.net/blog/23753)

以上を踏まえると、単に「メンバ変数」とだけ記載されている場合は、__「インスタンス変数 = メンバ変数 = プロパティ」__と受け取って良さそうな気がします。



## 定義方法

##### クラス変数
・static修飾子をつける
・「同じオブジェクトから生成されたインスタンス全て」が共通で持つ変数
・newでインスタンスを作成しなくても利用可能

```
class クラス名 {
    static $クラス変数名;
}
```

##### インスタンス変数
・static修飾子はつかない(クラス変数と対比）
・インスタンスから呼び出されるため、インスタンスが異なれば別の変数が入る

```
class クラス名 {
    $インスタンス変数名;
}
```



## 変数へのアクセス方法

##### クラス変数

```
クラス名::$クラス変数名;
```

##### インスタンス変数

```
$インスタンス = new クラス名();
$インスタンス->インスタンス変数名;
```
（始めこの`::`と`->`がJavaで見ない表現だったのでなかなか慣れませんでした。）

>参考：
[【PHP入門】PHPのクラス変数とインスタンス変数](https://uxmilk.jp/26442)

## 余談1:「static」と「const」
__static__
全インスタンス共通で使われる値で、__値が変わりうる__。（=変数）

__const__
全インスタンス共通で使われる値で、__値が変わらない__。（＝定数）

```
const 定数名 = 値;     # 定義
self::定数名           # クラス内からアクセス
クラス名::定数名         # クラス外から定数へのアクセス
```


>参考：
[PHPのstaticプロパティとstaticメソッド、定数](https://atmarkit.itmedia.co.jp/ait/articles/1803/20/news005.html)



## 余談2：「プロパティ」と「フィールド」

今まで似たイメージを持っていたのですが、言語によっては明確な違いがあるようですね。
>__C言語：__
[【C#】プロパティとフィールド（メンバ変数）の決定的な違い！](https://hiropon-progra.com/?p=792)
[プロパティ？フィールド？メンバー？C#のクラス構造のおさらい](https://qiita.com/toshi0607/items/801a0d37fb48313cbdbd)
__Java：__
[プロパティとフィールド](https://sites.google.com/site/ushiwiki/java/property)

ちなみに、[PHPの公式ドキュメント](https://www.php.net/manual/ja/language.oop5.properties.php)には
>__プロパティ__
メンバ変数のことを プロパティ といいます。 それ以外に フィールド などという呼びかたを見たことがあるかもしれません。 しかし、このマニュアルでは プロパティ と呼ぶことにします。

とあるので、PHPは__「プロパティ=フィールド」__というイメージで良さそうです。
シリアルLEDでPCをゲーミング使用に光らせるプログラム

#初めに
先日ゲーミングPCを入手しました。
ゲーミングPCといえば、、、
####光っててカッコいい！！！
けどなんか物足りないなあ、もっと光らせたいなあ
と思ったので、今回はシリアルLEDを使ってゲーミングPCをさらに光らせます。

ゲーミング使用でない(光らない)デスクトップPCをお持ちの方必見です。

#今回使用したもの
- Arduino　　(偽物がamazonで￥1,300くらい)
- シリアルLED　　(￥1,000以内で手に入ります)
- 配線材　　(はんだ付けが面倒なのでジャンパーワイヤーがオススメ)

シリアルLEDは8×8のパネル状のものを使用しましたが、テープ状の方が省スペースで隠しやすくオススメです。

#プログラム
```c
//シリアルLEDをゲーミングPCみたいに発光させるプログラム

//設定パラメータ====================================
int Speed = 150; //色が変わる早さ [ms]
int Power = 100; //LEDの明るさ [1~255]
//================================================

//ライブラリimport・LED数・出力ピン定義
#include <FastLED.h> // https://github.com/FastLED/FastLED からインクルード
#define NUM_LEDS 64  // シリアルLEDに搭載されている合計LED数
#define DATA_PIN 3   // 出力ピン番号

CRGB leds[NUM_LEDS];  //配列はシリアルLED上の各LEDに対応
int R = Power;
int G = 0;
int B = 0;

void setup() {
  Serial.begin(9600);
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}

void loop() {
  //FHASE 1
  while(G < Power){
    for(int k = 0; k < NUM_LEDS; k++){
      leds[k] = CRGB(R,G,B);
    }
    FastLED.show(); //点灯
    delay(Speed); //点灯持続時間
    R -= 1;
    G += 1;
  }

  //FHASE 2
  while(B < Power){
    for(int k = 0; k < NUM_LEDS; k++){
      leds[k] = CRGB(R,G,B);
    }
    FastLED.show(); //点灯
    delay(Speed); //点灯持続時間
    G -= 1;
    B += 1;
  }
  
  //FHASE 3
  while(R < Power){
    for(int k = 0; k < NUM_LEDS; k++){
      leds[k] = CRGB(R,G,B);
    }
    FastLED.show(); //点灯
    delay(Speed); //点灯持続時間
    B -= 1;
    R += 1;
  }
}
```

#終わりに
こういうプログラムをサクッと作れるようになってきて嬉しいです。
高校生くらいの夏のプログラミング教室とかで使えそうなネタだなあと思いました。
しょうもない記事でもいいのでもっとアップしていきたいですね^^;
ABC120 C - Unification で閃いてみた

https://atcoder.jp/contests/abc120/tasks/abc120_c

![abc120_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/7e838e93-2752-ceca-ed7e-3f30d9442ac3.png)
![abc120_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/affb2334-7509-3b1d-6dae-a46c09e973ea.png)
![abc120_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/2f1d9cee-08af-8f74-ca79-7db318171341.png)

分からん。
とりあえず風呂はいろ。

入ったら閃いた。

引っこ抜いて勝手にくっ付くなら、
0 , 1 をそれぞれカウントして最小値 x 2 で求められない？

```Unification.py
S=input()

one = S.count("1")
zero = S.count("0")

print(min(one,zero)*2)
```

通った。
Tips

# 1. Visual Studio Codeで保存時自動整形の設定方法

[こちらです。](https://qiita.com/mitashun/items/e2f118a9ca7b96b97840)

# 2. VSCodeでHTMLのひな型をサクッと
![2021-09-21_23-51-59.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/06bcb49a-60da-1603-ce57-2a5e78c524d5.gif)

XXX.htmlファイルで!(半角ビックリマーク)入力しTabキーを押すと、ひな型がザっと！でます！
ちなみに、languageはjapaniseなので`ja`に変更しておきます。

# 3. VSCodeでstyle.cssのlinkタグをサクッと
![2021-09-21_23-58-49.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/c7f82ca6-0452-9bfa-9bd2-4d94649f2781.gif)

`link:css`と入力し`Tab`キーでサクッとできます。

# 4. htmlタグをVSCodeでサクッと入力

例えば、divタグを入力します。

![2021-09-22_00-03-15.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1888749/696f0835-d5b3-7320-569c-ac1968bf85c2.gif)

`div`と入力し`Tab`キーを押すと入力できます。
BitwiseDPをrustで解いてみた

#概要
表題の通り
勉強がてらBitwiseDPで問題に出ているatcoderのhttps://atcoder.jp/contests/abc041/tasks/abc041_d
を解いてみたという話
読んでみたらわかるが知らない人向けの説明になっていない
知ってる人が解読する向け

#解き方
数字列に対して拘束がついている場合の組み合わせ数を求めるときに
DPを使うようだ。Bitwiseはしなくてもよいがすると楽程度の話
自分はこの問題はトポロジカルソートの話をよく読まないとわからなかったと感じた。

#トポロジカルソートとDP
イメージはhttps://algo-logic.info/topological-sort/
ざっくりいうと数字列の一番右側一つから徐々に数字を増やしていきつつ
拘束に引っかかるものは捨てる→トポロジカルソート
残ったものの組み合わせ数を保存しておく→DP
保存の仕方→bitwise
みたいな感じ


#アルゴリズム的な
なんとなく例を書いてみる
1,2,3という数字列があったとして 2←1、2←3　という拘束があったとする（2は1，3よりも左におく拘束）
この拘束を満たす数字列の並び方を考える。いうまでもなく(2,1,3)(2,3,1)の二通りしかない

部分集合を用意する
S={(φ),(1),(2),(3),(1,2),(1,3),(2,3),(1,2,3)}
空集合は重要。アルゴリズムに落とし込むときはこれの組み合わせ数を1通りとしておかないとダメ

DPはググったらわかるが　DP[i+1]=DP[i]
みたいな漸化式であらわされる。使い方はナップサック問題みればわかるが解をどんどん保存していって
新しい解を引っ張ってくる
DP[0]のときはS1の組み合わせの数、DP[1]はS2の組み合わせの数...とやっていくと
最後にはDP[7]はS8の組み合わせの数となりもとめるものが得られる
今回のイメージ的には1,2,3という数字列があるが
まず一番右側から並べていって徐々に組み合わせをチェックしていく感じ

なんでこんなややこしいことをやるかというと数字列長さが1から初めてそのときの組み合わせの数を
DPにいれて次は2で...とやっていことで総当たりでやるより数を減らせるから

あとは組み合わせの数をどうやって計算するかだが、取り合えず最後の組み合わせを考える。最初のほうの処理は
コード見て。
S8:{1,2,3}→これの組み合わせの数をDP[7]に入れることを考える

DP的に考えると

1-{2,3}:1 - S7→DP[6]
2-{1,3}:2 - S6→DP[5]
3-{1,2}:3 - S5→DP[4]

なのでDP[7]=DP[6]+DP[5]+DP[4]
となるように見えるがDP[6]、DP[4]は拘束（2←1、2←3）に引っかかるため
結局DP[5]をそのまま代入するだけになる
ちなみにS6={1,3}→DP[5]を計算すると
1-{3}:1 - S4→DP[3]
3-{1}:3 - S2→DP[1]
これは拘束に引っかからないので
DP[5]=DP[1]+DP[3]


（　＾ω＾）・・・これであとでみてわかるかなあ

```
use proconio::input;
 
 
fn main() {
 
input! {
 
n:usize,
m:usize,
v: [usize; 2*m]
}
 
 
 
 
 
let mut xi = Vec::new();
let mut yi = Vec::new();
for i in 0..m{
xi.push(v[2*i].clone());
yi.push(v[2*i +1].clone());
}
 
 
let mut edge = vec![0 ;n+1];
let  xy = xi.iter().zip(yi.iter());
for (i,j) in xy{
  edge[*i] =  edge[*i] ^ (1<<(j-1));
}
 
let mut DP:Vec<i64> = vec![0 ;2_usize.pow(n as u32)];
let mut s = vec![0 ;2_usize.pow(n as u32)+1];
 
DP[0] =1;
for i in 1..(2_usize.pow(n as u32) ){
  s[i] =i;
  for j in 1..(n+1){
 
    if s[i] & (1<<(j-1)) != 0 && (edge[j]  & s[i] ==0){
      
      DP[i] += DP[s[i] ^ (1<<(j-1))];
    }
  }
 
}
 
 
  println!("{}",DP[DP.len()-1]);
 
}
```
【iOS】同サイズのWidgetをWidget Galley に並べる方法

#WidgetBundle
WidgetBundleを利用することで、同サイズのWidgetや異なる種類のWidgetをWidgetGallery上に並べることができます。

##通常のWidget表示
通常は下記のようにWidgetクラスを継承した構造体に対してmain属性を指定し、以下で言うTestWidgetをエントリーポイントに指定します。この方法ではIntentConfigurationのコンテントに指定したViewのみをWidgetGalleryに表示することしかできません。また**systemSmall、systemMedium、systemLarge**のサイズごとにしかWidgetGalleryに表示できず、同サイズのWidgetを並べることはできません。

```swift
@main
struct TestWidget: Widget {
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: "Test", intent: ConfigurationIntent.self, provider: Provider()) { entry in
            TestWidgetEntryView(entry: TestEntry(date: Date(), testHeader: entry.testHeader , testTitle: "", configuration: ConfigurationIntent()))
        }.configurationDisplayName("DisplayName")
        .description("Description")
        .supportedFamilies([.systemSmall,.systemMedium,systemLarge])
    }
}
```
##WidgetBundleの利用
異なるWidgetや同サイズのWidgetをGalleryに表示するには、下記のようにWidgetBundleクラスを継承した構造体をmain属性でエントリーポイントに指定します。その構造体のbody内で別で定義したWidgetクラスを継承した構造体をインスタンス化することでWidgetGalleryに表示することができます。
異なるWidgetを表示したい場合は、表示したい順でインスタンス化します。
同サイズのWidgetを表示したい場合は、対象のWidgetのsupportedFamiliesを一つだけ選び、複数回そのWidgetをインスタンス化したらその分同サイズのWidgetが表示されます。

```swift
@main
struct TestWidgetBundle: WidgetBundle {
    var body: some Widget {
        // 異なるWidget
        test1Widget()
        test2Widget()

        // 同サイズのWidget(systemSmallが二つ表示される）
        test2Widget()
        test2Widget()
    }
}

struct test1Widget: Widget {
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: "Test1", intent: ConfigurationIntent.self, provider: Provider()) { entry in
            TestWidgetEntryView(entry: TestEntry(date: Date(), testHeader: entry.testHeader , testTitle: "", configuration: ConfigurationIntent()))
        }.configurationDisplayName("DisplayName")
        .description("Description")
        .supportedFamilies([.systemSmall,.systemMedium,systemLarge])
    }
}

struct test2Widget: Widget {
    var body: some WidgetConfiguration {
        IntentConfiguration(kind: "Test2", intent: ConfigurationIntent.self, provider: Provider()) { entry in
            TestWidgetEntryView(entry: TestEntry(date: Date(), testHeader: entry.testHeader , testTitle: "", configuration: ConfigurationIntent()))
        }.configurationDisplayName("DisplayName")
        .description("Description")
        .supportedFamilies([.systemSmall])
    }
}
```
ラズパイで「～が一時的に解決できません」と表示された時の解決方法

#アップデートができない、、、
理由は分からないがラズパイでアップデート等をしようとすると突然
「～(ミラーサイトの名前)が一時的に解決しません」と出てきて
アップデート等ができないことがある。

そのような場合に様々なサイトで言われているのがターミナルで

```
$ sudo dhclient wlan0　#無線LANを使用していたためwlan0 
```

を書けばいいと言われている。実際やってみると


```
$ sudo dhclient wlan0
Too few arguments.
Too few arguments.
```
だったり

```
$ sudo dhclient wlan0
RTNETLINK answers: File exists　 
```
と結果はバラバラになることが多い。

ちなみに前者の結果が返ってきてもアップデート等はできない。
後者の結果が返ってくるとアップデート等ができるようになる。

結果がバラバラなのにどうすればいいのか。

結論から言うと後者の「RTNETLINK answers: File exists」と返ってくるまで
「$ sudo dhclient wlan0」を繰り返す必要がある。

筆者は「$ sudo dhclient wlan0」を２回繰り返すと確実に
「RTNETLINK answers: File exists」が返ってくる。

#毎回やるのは面倒くさい、、、そうだ！
筆者の場合、上記の現象が電源を付けるたびに起こっており
非常に面倒であった。

そこで新しいスクリプトを作り

```reboot.py
import subprocess

subprocess.call("sudo dhclient wlan0", shell=True)
subprocess.call("sudo dhclient wlan0", shell=True)
```
cronで電源起動時に自動でこのスクリプトが実行されるようにした。

```
@reboot python /home/pi/reboot.py
```

これでわざわざ起動時にターミナルで「$ sudo dhclient wlan0」を
やる必要がなくなった！

みなさんもよかったら是非。
【Javascript】オブジェクトの配列をuniqueにする（重複を削除する）ときはfilterではなくMapオブジェクトを使う

# はじめに

単純な配列は以下のように`Set`を使うと重複を削除できるというのがよく知られてます。

```js
const numbers = new Set([1, 2, 1, 1])

const uniqueNumbers= Array.from(numbers)
//uniqueNumbers は [1, 2]
```

以下のようなオブジェクトの配列の重複を削除する方法はあまり紹介されていなかったのでメモとして書きます。


```js
const users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}, {"id": 1, "name": "Alice"}, {"id": 1, "name": "Alice"}]
// [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}] にしたい
```

# Mapを使って重複を削除する

データ量が多いときは[Array.prototype.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)ではなく`Map`を使いましょう。（理由は後述）

`Map`は[Array.prototype.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)ではなく[Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)のことです。

結論から言うとコードは以下のようになります。

```js
const users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}, {"id": 1, "name": "Alice"}, {"id": 1, "name": "Alice"}]

const uniqueUsers = Array.from(
  new Map(users.map((user) => [user.id, user])).values()
);
// uniqueUsers は [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]
```

`Map`について詳しくは他の記事で紹介されているので、ここでは簡単に説明します。
`Map`は`key-value`型のオブジェクトで、任意の値をkeyとして使用することができます。

先程のコードだと、`user`の`id`がkeyで`user`がvalueとなるように`Map`を作成します。
`Map`では同じkeyに違う値を設定できないので、`Map`を作成する際に重複が削除されます。

```js
const userMap = new Map(users.map((user) => [user.id, user]))

// 以下のようなイメージになります（厳密にはこのようなオブジェクトではないです。）
// {
//   1: {"id": 1, "name": "Alice"},
//   2: {"id": 2, "name": "Bob"}
// }
```

`Map`を作成したら[Map.prototype.values()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values)でvalueのみを抽出して、[Array.from()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)で配列に変換したら終了です。

`Map.prototype.values()`は`Iterator`オブジェクトを返すので`Array.from()`で変換が必要です。

# filterを使わない理由

以下のような方法でも重複を削除することが可能です。
`findIndex`で最初のインデックスを取得して`filter`する（1個目だけ採用して重複を削除する）シンプルな書き方です。
標準的な関数を使っているので読みやすいかもしれません。

```js
const uniqueUsers = users.filter(
  (element, index, self) => self.findIndex((e) => e.id === element.id) === index
);
```

「`filter`を使わずに`Map`を使いましょう。」と言いましたが、実は、「要素数が小さい配列を」「頻繁に（多数）処理する」という前提がある場合には、`filter`を使ったほうが早いです。（詳細は以下の記事を参考にしてください。）

https://qiita.com/piroor/items/02885998c9f76f45bfa0

個人的にはデータ量が増えたときにも対応できるので`Map`で書いておいたほうがいいかなと思ってます。

# まとめ

`Map`を使ってオブジェクトの配列の重複を削除する方法を紹介しました。

タイトル詐欺みたいですが、処理するデータ量が少ないときは`filter`のほうがいいです。
でも、個人的にはデータ量が増えたときのために`Map`で書いておいたほうがいいかなと思ってます。

なにかのお役に立てれば幸いです。
Firebase CloudFunctions で"Error: The request was aborted because there was no available instance"というエラーが出る時の強引な解決法

# 現象
私の環境では、2021年9月中旬あたりからFirebase CloudFunctionsで以下のエラーが頻発するようになりました。
`Error: The request was aborted because there was no available instance`

`onRequest`、`onCall`、リージョン変更など試しましたが規則性や条件はなくほぼ全てのfunctionsで発生しました。

頻度が極めて高く、レスポンスすらクライアント側に返ってこない（そもそもFunctionが発火してすらいない）という状況で、かなり困りました。

![スクリーンショット 2021-09-21 21.01.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364049/95c6252d-ef1c-fa6d-3ff8-edabc1492f48.png)

# 原因

どうやら米国時間の2021年8月31日に施されたップデートが原因のようです。

https://cloud.google.com/blog/ja/products/serverless/cloud-functions-supports-min-instances

> この新機能では、需要が低い期間にオンライン状態にしておくアプリケーションのインスタンスの最小数を指定することで、サーバーレスのアプリケーションとワークフローのパフォーマンスを劇的に改善し、コールドスタートを最小限に抑えることができます。

要約すると、 

- FaaSの課題として、長時間リクエストがないとインスタンスが閉じられてしまって、再度リクエストが発生した時にインスタンスの生成などの予備動作から始まるために余計に時間がかかってしまう（コールドスタート）というものがある
- 解決するためにGoogleは、最小インスタンス機能をアップデートした
- 最小インスタンスに設定した数のインスタンスは維持されるようになった
 
というものです。

以前はコールドスタートに数秒かかっても大丈夫だったが、アプデ以降は1秒ほど待ってインスタンスが立ち上がらなかった場合にエラーをスローしてFunctionの発火すらしなくなったという報告がGitHubのIssueに上がっています。

アプデの影響であると断定はできませんが、GitHubにIssueが立ちはじめたタイミングと重なっているので確率は高いでしょう。

https://github.com/firebase/firebase-functions/issues/962#issuecomment-915114148


# 対応策
至ってシンプルです。タイトルにも書きましたが、「強引な方法」であって根本解決ではないです。

### 最小インスタンスを設定し、金を払う（〜数十万円/月）

以上です。

#### 設定方法

```ts
// index.ts
export const api = functions
  .region('asia-northeast1', 'us-central1')
  .runWith({minInstances: 1}) // この行を追加
  .https.onRequest(server)
```
3行目のように、fuictionsの定義に`.runWith({minInstances: 1})`を追加するだけです。
値は1以上の任意の値にしてください。（私はケチなので1にしました）
こうするとインスタンスが閉じなくなり、エラーが出ることもなくなりました。

#### 課金形態

**1ファンクションごと**に、**$6/月**です。

"1プロジェクトごと"ではありません。上記の場合、`onRequest`が2リージョン分ありますから、$12/月になります。
一般的なプロジェクトでは数10個のファンクションがあるでしょうから、だいたい月数万〜数十万になるのではないかと思います。

色々調べましたが、どうやら現状これしか解決がなさそうです。（2021年9月21日）
いやぁ、やってくれましたねぇ。

予算に余裕がありエラーを早急に解決したい担当者は、怒りを覚えながらGoogleに金を払いましょう。
予算に余裕がない担当者は、怒りを覚えながら寝ましょう。

# 今後

ビジネス的に儲けるために設計されたエラーなのか、Googleも予期せぬ不具合なのかは分かりません。
一応、公式に対応していると発表はされていて、IsuueTrackerにも上がってますが...どこまで対応してくれるのか...

どうしても金を払って解決したくない人は以下のページをウォッチして状況を監視しておくのが良いでしょう。

[GCF - Frequent disruption of error - "The request was aborted because there was no available instance."](https://issuetracker.google.com/u/1/issues/194948300)

---
【蛇足】

このオッチャンがお気持ちを全て代弁してくれてた!
![スクリーンショット 2021-09-21 16.55.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364049/b15c029c-1411-d801-a58f-c1d0e5c5f086.png)
![スクリーンショット 2021-09-21 16.55.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364049/1d4a3982-edb0-6380-c422-8e5739ff1499.png)
![スクリーンショット 2021-09-21 23.42.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364049/7145c0e8-14bd-c154-daae-063601824a2f.png)
![スクリーンショット 2021-09-21 23.43.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364049/5399f304-31f7-f9d0-aa44-020b0f94ba5a.png)