OmniAICreator/Qiita-1.07M huggingface dataset:
UnityでBlockchainのWalletを操作ライブラリ紹介


最近NFTゲームの発展が早い、毎日は数本ゲームがリリースされる。
NFTゲームをやるのはWalletが必要、ゲーム財産がWalletに保存しますから。
Unityから作るゲームでも個人Walletと連結して、基本操作をできるようために、色々ライブラリが使えます。

## Wallet Connect
+ HomePage: https://walletconnect.com/
+ GitHub: https://github.com/WalletConnect
+ UnitySample: https://github.com/WalletConnect/WalletConnectUnity

Walletと連結ライブラリです、Unityバーションはまだ開発中です、安定はしていないです。
Customize可能性が高い。
無料で使えます、ソースコードがGithubに公開されている。
最近はV2.0を開発されています、ベタ版も出ました。
クロスチェイン使えます、正しいコードを書くなどが大変。（テストしたのはBSCとETHチェインです）

対応Wallet, DApp：

+ Dapp: https://walletconnect.com/registry/apps
+ Wallet: https://walletconnect.com/registry/wallets
+ Unityライブラリ対応するWallet:　Metamask,Trust　ただしTrustの方まだバグがあります。

## Enjin Wallet
+ HomePage: https://enjin.io/
+ AssetStore SDK: https://assetstore.unity.com/packages/tools/utilities/blockchain-sdk-by-enjin-124133

使いしやすい、UIやAPIなども用意されています。
ソースコードが公開されない。
Enjiメインネットだけ推進、他のチェインも使えますが使う感じがあまり良くない（エラーや不明バグが多い）。
基本無料、ビジネス目的アプリは有料、このSDKを使うとEnjiのインフラプロジェクトを登録が必要ですから。
対応Wallet:　EnjiWallet

### 個人感想：

+ エンジニアとして、WalletConnectの方が良い、カストマイズ可能性が高いし、色々チェインが対応されていて（クロスチェインではないです）、対応Walletも多い、無料など。
+ Enjiの方はゲーム使うのがベストフィットですが、Enjiネットワークはまだ発展中段階で、BSCやEthernetと比べるとユーザーが少ないんで、使うのはこれからかと思います。
Kintone JavaScriptカスタマイズVol.2

#フィールドへの入力可、不可をラジオボタンを使用して制御する

前回の投稿では、新規レコード作成画面を開いた際に一部のフィールドを非表示にする処理をJavaScriptカスタマイズで実装しました。
[前回の記事はこちら](https://qiita.com/chiba1019/items/7ae4650d667085ef48dd)
２回目である今回はフィールド内に設置したラジオボタンを使用して、フィールドへの入力可、不可を制御できるようなカスタマイズを行っていきたいと思います。


#環境と準備
今回も前回同様、kintone内でJavaScriptの編集・保存が簡単に行えるプラグイン「JSEdit for kintone」を使用していきます。
JSEdit for kintone：https://developer.cybozu.io/hc/ja/articles/205452653
また、アプリは任意作成した物を使用していきます。

#カスタマイズ
カスタマイズの内容をもう一度確認します。
今回は、「任意アプリの新規レコード作成画面で、フィールド内に設置したラジオボタンを使用し、フィールドへの入力可、不可を制御する」というカスタマイズを行っていきます。
完成形としては添付画像のように、ラジオボタンの「無効にする」選択時に”入力を制御したい項目”を入力不可となるようにしていきます。
![スクリーンショット 2021-11-08 12.56.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1954118/443a1197-86bc-d981-d8eb-a7ee8de1d148.png)

実現したいことの整理ができたので、先ずはサンプルアプリの準備をします。
新規アプリ作成ではじめから作成を選択し、フォームに「ラジオボタン」と「文字列（複数行）」を設置します。
またラジオボタンの項目は、デフォルトだとsample1.2のようになっているため、今回は設定から項目を編集し「有効にする」「無効にする」のようにしました。
また、文字列も分かりやすく「入力を制御したい項目」とフィールド名だけ変更しました。


![スクリーンショット 2021-11-08 15.45.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1954118/10e72031-958d-a05f-0fbb-735de88ae0af.png)
![スクリーンショット 2021-11-08 15.46.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1954118/401557d7-3f2c-14a1-3e60-c175595ec4be.png)

さて、ここからはJavaScriptを用いてカスタマイズを行っていきます。
基本的な流れとしては前回と同じく、イベントを発火点に処理内容を記述していくのですが、今回は条件分岐が発生します。
ラジオボタンのどちらが選択されたかによって結果を変えたいからです。
先にソースコードですが、以下となります。

```javascript:ソースコード
(function() {
    "use strict";
    
    //① ラジオボタンイベントを取得
    var my_events = ['app.record.create.change.ラジオボタン', 'app.record.edit.change.ラジオボタン'];
    //②　条件分岐の記述 
    kintone.events.on(my_events, function(event) {

        var record = event['record'];
        
        if (record['ラジオボタン']['value'] === "有効にする") {

            //"有効にする"を選択している場合の結果
            record['文字列__複数行_']['disabled'] = false;
        }else {

            //"無効にする"を選択している場合の結果
            record['文字列__複数行_']['disabled'] = true;
        }
        return event;
    });
})();
```


先ずは、ラジオボタンイベントを取得するコードを記入します。[フィールド変更時イベント記述について](https://developer.cybozu.io/hc/ja/articles/201941984#step3)
<font color="Red">*ソースコード内コメントアウト①部分*</font>

その後にイベント（今回の場合はラジオボタンイベントを取得した変数 ”my_events”）を発火点として条件分岐の内容を記述します。
<font color="Red">*ソースコード内コメントアウト②部分*</font>

今回は、ラジオボタンが”有効にする”になっていた場合には `文字列__複数行_` を通常表示　`['disabled'] = false;`
”無効にする”選択時には入力欄を無効化しグレーアウト　`['disabled'] =true;`
となるように条件分岐部分を記述しました。

##実際の画面で確認
![スクリーンショット 2021-11-08 17.01.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1954118/597a0c0c-d571-ee7f-cb12-b6ec9f59be5b.png)

![スクリーンショット 2021-11-08 17.01.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1954118/223c4505-2ef9-d080-38ca-7917f88365b8.png)



ラジオボタンの選択によって、「入力を制御したい項目」というフィールドの表示結果が代わり、無効にする選択時にはフィールドがグレーアウトされ入力不可とすることができました。

#まとめ
条件分岐をうまく活用する事でもっと複雑な処理が可能となりそうです。
メモ〜mockの使い方

今回のお題
-
今回はpythonのmockライブラリの基本的な使い方について取り上げます。

目次
-

- mockとは何か
- 具体例
- 終わりに

mockとは何か
-
mockとはテスト内で用いる代替品、及びそれを簡単に用意するためのpythonの標準ライブラリのことを指します。

例えばあるプログラムに、戻り値を返す`メソッドA`とメソッドAを呼び出すための`メソッドB`を実装する予定だして、先にメソッドBが完成したとしましょう。

この場合、メソッドAの完成を待ってからメソッドBをテストするというのはあまり望ましくありません。

そんな悠長なことをしていてもしメソッドBに不備があった場合、メソッドAの実装後だと修正が大変になる可能性があるからです。

ですがメソッドBのテストにはメソッドAが必要なので、暫定的にメソッドAの代わりをしてくれるものを作り、それを呼び出せるかどうかを以てメソッドBのテストとする、というのが一般的です。

この`メソッドAの代わり`のことをプログラミングの世界ではmockと言います。

また、pythonにはこのmockを簡単に用意できるライブラリが用意されており、そちらもmockと呼ばれています。

具体例
-
具体的に見ていきましょう。

以下が実装予定のプログラムです。

```python:calc.py
class Calculator(object):
  def add(self, a, b):
    return (a + b)

  def sub(self, a, b):
    return (a - b)

  def mul(self, a, b):
    return a * b

  def div(self, a, b):
    return (a // b)
```
```python:calclib.py
from calc import Calculator

class CalculatorLibrary(object):
  def __init__(self):
    self.calc = Calculator()

  def calculate(self, input_a, input_b, operation):
    if operation == "+":
      return self.calc.add(input_a, input_b)
    elif operation == "-":
      return self.calc.sub(input_a, input_b)
    elif operation == "*":
      return self.calc.mul(input_a, input_b)
    elif operation == "/":
      return self.calc.div(input_a, input_b)
    else:
      raise ValueError("wrong operation!")
```
一つ目のモジュールは四則演算の関数を定義しており、二つ目のモジュールは引数に応じて然るべき四則演算関数を呼び出す役割を持っています。

そして、二つ目の`calclib.py`のためのテストも用意しました。

```python.tests.py
from calc import Calculator
from calclib import CalculatorLibrary
import unittest

class MyTestCase(unittest.TestCase):
  @classmethod
  def setUpClass(cls) -> None:
    cls.calc = CalculatorLibrary()
    print("calclib is ready")
    return super().setUpClass()

  def test_add(self, mock_add):
    self.assertEqual(self.calc.calculate(10, 5, "+"), 15)

  def test_sub(self):
    self.assertEqual(MyTestCase.calc.calculate(10, 5, "-"), 5)

  def test_mul(self):
    self.assertEqual(self.calc.calculate(2, 4, "*"), 8)

  def test_div(self):
    self.assertEqual(self.calc.calculate(8, 3, "/"), 2)

if __name__ == "__main__":
  unittest.main()
```
ですがこの時に`calc.py`が以下の状態だったらどうでしょう。

```python:calc.py
class Calculator(object):
  def add(self, a, b):
    pass

  def sub(self, a, b):
    pass

  def mul(self, a, b):
    pass

  def div(self, a, b):
    pass
```

テストができないですよね。

なのでこの関数の代わり、すなわちモックを用意しなければなりません。

では、代わりとして用意するモックがどのような性質を持っていれば良いでしょうか。

例えば以下のテストの場合、

```python
  def test_add(self, mock_add):
    self.assertEqual(self.calc.calculate(10, 5, "+"), 15)
```

- Calculatorクラスのaddメソッドが呼ばれる。
- 呼び出されたaddメソッドが15を返す

という二つをクリアできればテストは成功します。

なのでCalclatorLibraryクラスのテストを行うための最低限の要件として、
- addメソッドが呼び出されるときに代わりに呼び出される
- 毎回必ず`15`を戻り値として返す

という機能を持ったモックを用意します。

```python:モックの用意
# from unittest.mock import patch

# ...省略...
@ patch(Calculator, "add")
def test_add(self, mock_add):
  mock_add.return_value = 15
  self.assertEqual(self.calc.calculate(10, 5, "+"), 15)
# ...省略...
```
`patchデコレータ`でどのクラスのどのメソッドを模倣するのかを指定し、`mock_xxx.return_value`でその模倣した関数の戻り値を指定します。

今回確かめたいのはあくまでも関数の呼び出しがうまくいくかどうかなので、これでも十分にテストの要件を満たします。

終わりに
-

以上がmockの使い方でした。

使い方そのものよりも、その場でテストしなければならないのはどの部分で、逆にどの部分はテストしなくても大丈夫かという切り分けが大事かなと感じました。
Kibana を WSL2（Ubuntu）にインストールする

# はじめに
業務で Kibana の導入検討を行ったので、自分のPCにも環境構築をしてみた。その手順を備忘録を兼ねて記事にしておく。なお、基本的に公式のwebページの手順通りにインストールを行った。
https://www.elastic.co/guide/en/kibana/current/deb.html

また基本的には「[Elasticsearch を WSL2（Ubuntu）にインストールする](https://qiita.com/ryamamoto0406/items/3067e69286cecafb6e5a)」と同じ手順を行っている。

# インストール手順
前半のコマンドについての詳細は「[Elasticsearch を WSL2（Ubuntu）にインストールする](https://qiita.com/ryamamoto0406/items/3067e69286cecafb6e5a)」を参照との事。

```bash
$ wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
$ sudo apt-get install apt-transport-https
$ echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list
```

これで apt-get でインストールする準備が整う。

```bash
$ sudo apt-get update && sudo apt-get install kibana
```

# Kibana の起動&停止 (systemd)
まずは以下のコマンドを実行する。

```bash
$ sudo /bin/systemctl daemon-reload
$ sudo /bin/systemctl enable kibana.service
```


起動、停止するには以下のコマンドを実行する。

```bash
sudo systemctl start kibana.service
sudo systemctl stop kibana.service
```

# おわりに
Elasticsearch でインストールしていたのと同じ方法で Kibana も導入することができた。その使用方法についても記事にしていければと思う。
strptime()とstrftime()の使い方

Pythonにおいて、入力された日付のチェックなどに***datetime***モジュールを使用した。
その中で、```strptime()```と```strftime()```の使い方についてまとめておく。
この2つのメソッドは振る舞いだけでなく、```strptime()```はクラスメソッドである一方で、```strftime()```はインスタンスメソッドという違いがある。

##strptime()
文字列を日付形式に変更することができる。
指定された日付を示す文字列と指定されたフォーマットが正しければ、***datetime***オブジェクトが作成される。

```python
from datetime import datetime

datetime.strptime(<日付を表す文字列>,<フォーマット>)
# 例
datetime.strptime('2021-11-8','%Y-%m-%d')
```

また、これを使用して指定された日付が妥当でフォーマットに一致するかチェックすることができる。もし指定された日付が正しくなければ、```ValueError```が発生するため、エラーが発生するかどうかで判別できる。

##strftime()
日付オブジェクトがもつ日付を書式を指定して文字列に変換することができる。

```python
from datetime import datetime

<日付オブジェクト>.strftime(<フォーマット>)
```

###参考
フォーマットを指定する書式化コードは以下の公式ドキュメントを参照。
[公式ドキュメント](https://docs.python.org/ja/3/library/datetime.html#strftime-and-strptime-format-codes)
JLCPCB-3Dブリントサービスの始まり

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1873014/81d8a1bc-1350-aa5c-5714-7961d643da00.png)

https://jlcpcb.com/3d-printing

いよいよ<a href="https://jlcpcb.com/JPA" rel="nofollow"><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">JLCPCB</font></font></a> プリント サービスが始まりました。

ご注文の際、https://jlcpcb.com/JPA を通してクーポンを受け取ることができます。

また、「JLCPCB$7」のコードを入力すると7ドルの割引があります。


何がありましたら、ここにフォローして　<a href="https://twitter.com/JLCPCB_Japan" rel="nofollow"><font style="vertical-align: inherit;"><font style="vertical-align: inherit;">JLCPCB Twitter</font></font></a>、いつでもお気軽にご連絡くださいね！！
vSphere HAとFTの障害テスト

## 目的
障害テストを行い、挙動を確認する

## 手順

![スクリーンショット 2021-11-08 15.45.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/8029241d-b102-676a-68ae-0e369a8ad756.png)

esx-t12にホストと仮想マシンを置く
FTのプライマリも置く

![スクリーンショット 2021-11-08 15.51.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/3704b9bc-1f74-7dd9-61bc-88cc16b9a99b.png)

![スクリーンショット 2021-11-08 15.52.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/8993237b-f75d-cac8-cff1-48283f06354d.png)

11にはセカンダリがいる

この状態で、12-HAへの疎通確認とesx-t12への疎通確認を行い続けて、挙動を確認する

## 結果

FTについては1度だけタイムアウトしたが、すぐに復旧
![スクリーンショット 2021-11-08 15.56.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/b13e13e1-729a-f0d3-367d-a6004157d611.png)

HAはずっとダウン
![スクリーンショット 2021-11-08 15.56.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/3611618a-a4ae-962d-4e83-c6fee95f217d.png)

FTのプライマリは赤い警告が出る
![スクリーンショット 2021-11-08 15.57.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/b132e104-c38b-be35-9fb9-dacb755f0973.png)

11のFTがプライマリに変更された
![スクリーンショット 2021-11-08 15.57.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/2e85de7a-47dd-342e-8d1f-1ae85c6c5ae0.png)

HAも11にマイグレーションされた
![スクリーンショット 2021-11-08 15.58.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/833d4670-f4d4-cb90-71ad-7cb8a1be62af.png)

4分ほど経過したらパワーオンされた
![スクリーンショット 2021-11-08 16.00.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/1699a8f3-e5e2-edb3-471d-ea538502dd65.png)

5分ほどで疎通確認が取れた
![スクリーンショット 2021-11-08 16.01.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/0d8196ba-eee8-c013-a0a2-c9d2defd78c1.png)

12にセカンダリが生成される
![スクリーンショット 2021-11-08 16.15.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1603537/ef46df27-2481-56c8-ad5c-ceec86e179fd.png)

### 補足事項
本来であれば、2台以上でクラスタ構成となる
なので、仮に11、12、13でクラスタ構成となると、11で障害が発生した場合、12にプライマリ、13にセカンダリが自動で生成される
今回は2台でクラスタ構成しているため、11にプライマリもセカンダリも存在する形となった

## まとめ
HAで保護した仮想マシンは約5分ほどで復旧
FTで保護した仮想マシンは1パケットロスで復旧
ざっくり理解するFirebase Authentication

# Firebaseを使った認証

## 全体図はこんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573723/9a95bf7c-4868-71b5-56db-5601c869ebf0.png)


## 流れ

① ログイン情報の送信。

② ユーザ情報（emailとかnameとか）とJWT（idTokenが帰ってくる）

③ JWTをバックエンドにPOSTする。（サインアップならnameとかemailも一緒に送ってあげるとそれをDBの初期値に出来る。）

④ JWTをfirebaseに投げる。（捏造じゃないかチェック）

⑤uidがfirebaseから帰ってくる。このuidが一意のIDとなるのでこれをユーザーモデルのIDとして扱うことが出来る。

⑥ケースに応じてレスポンスを返す。

①〜②はライブラリで、④〜⑤もライブラリで出来る。

## その他

- 無料プランでも実質無制限

[Firebase Authentication の上限 | Firebase Documentation](https://firebase.google.com/docs/auth/limits?hl=ja)

## 参考記事

[Firebase Authentication | Firebase Documentation](https://firebase.google.com/docs/auth?hl=ja)

[Firebase Auth のユーザ認証機能を自前のデータベースと連携する - Qiita](https://qiita.com/geerpm/items/165c31302edce1e52146)
DjangoでLoginRequiredMixinとUserPassesTestMixinの併用

LoginRequiredMixinとUserPassesTestMixinの併用するときに、未ログイン時にログインページへ飛ばなくなって困ったのでメモです

django　3.0.8

## やり方

```
def handle_no_permission(self):
        if self.request.user.is_authenticated:
            raise PermissionDenied
        else:
            return redirect('account:login')
```
LoginRequiredMixin、UserPassesTestMixinを継承しているclassにこれを追加するだけです
svelte-kitでwasm-packを使う

wasm-packを使って作成したwasmのパッケージを利用していた時にsvelte-kitのビルドにはまったのでメモします．

## svelte-kitでwasmのパッケージを読み込む
svelte-kitは内部でviteを利用しているのですが，viteでwasm-packで作成したパッケージを利用するためには

```
wasm-pack build --target web
```

のようにターゲットを指定します．`--target`はwasm-packのオプション なので，featuresの指定をするときは`wasm-pack build --target web -- --features console_error_panic_hook`のように前に`--`を入れます．他のビルドターゲットにしたい場合もあると思いますが，viteで読み込む方法は分かりませんでした．
javascript側では普通に以下のようにimportできます．以下はwasm-bindgenでinterface(`IAppOption`)とクラス(`CanvasApp`)を定義した例です．

```javascript
import init, {CanvasApp} from '$lib/wasm/pkg/wasm';
import type {IAppOption} from '$lib/wasm/pkg/wasm';
```

上ではビルドで生成したjsファイルを読み込んでいますが，`$lib/wasm/pkg`のように`pkg`ディレクトリを指定することもできます．デフォルトで読み込まれる`init`は非同期関数であり，`init`が完了した後に`CanvasApp`が利用可能になります．具体的には

```javascript
import init, {CanvasApp} from '$lib/wasm/pkg/wasm';
import type {IAppOption} from '$lib/wasm/pkg/wasm';
import {onMount} from "svelte";

onMount(async () => {
	await init();
	const app_opt: IAppOption = {...何かオプション};
	const canvas_app = new CanvasApp(app_opt);
	...何か処理
});
```

のように利用します．こちらは`svelte-kit dev`(`npm run dev`)では問題なく動きますが，`svelte-kit build`(`npm run build`)では

> `Error: 'new URL(url, import.meta.url)' is not supported in SSR.`

というエラーがでます．これはインポートしたjsファイル内のURLコンストラクタがnodeで動かないためです．

## svelte-kit build が通るようにする
[こちら](https://github.com/sveltejs/kit/issues/1896)にissueが上がっているので，紹介されている[テンプレート](https://github.com/doomnoodles/sveltekit-rust-ssr-template)を参考にします．以下はrustプロジェクトのディレクトリがルートから`./src/lib/wasm`である場合の例です．

```json:.rsw.json
{
 "crates_path": "./src/lib/",
 "crates": [
 "wasm"
 ]
}
```

と

```javascript:fix-new-urls.js
// Temporary fix for https://github.com/vitejs/vite/issues/5169
import { readFileSync, writeFileSync } from 'fs';

const re = /[^\n]*new URL[^\n]*/g;
for(let crateName of JSON.parse(readFileSync("./.rsw.json", "utf8")).crates) {
 try {
 const crates_path = JSON.parse(readFileSync("./.rsw.json", "utf8")).crates_path
 const fileName = crates_path + crateName + "/pkg/" + crateName + ".js";
 writeFileSync(fileName, readFileSync(fileName, "utf8").replace(re, ""));
 } catch {}
}
```

 をプロジェクトのルートに用意し`node fix-new-urls`を`svelte-kit build`の前に実行します(jsファイルを変更してしまうのでtsconfigがvscode上でエラーを出します)．ビルド時のエラーの該当部分を削除しています．
すると`svelte-kit build`が通るようになります．以上でビルドは成功しますが
 ブラウザで
 
 > `WebAssembly.instantiate(): Argument 0 must be a buffer source or a WebAssembly.Module object`
 
 というエラーが出てwasmを読み込めなくなってしまいます．そこで javascript側を以下のように変更します．
 
 ```javascript
import init, {CanvasApp} from '$lib/wasm/pkg/wasm';
import type {IAppOption} from '$lib/wasm/pkg/wasm';
import wasm_path from "$lib/wasm/pkg/wasm_bg.wasm?url";
import {onMount} from "svelte";

onMount(async () => {
	await init(wasm_path);
	const app_opt: IAppOption = {...何かオプション};
	const canvas_app = new CanvasApp(app_opt);
	...何か処理
});
 ```
 
 `init`関数にwasmファイルのパスを与えるだけです．これで`npm run dev`でも`npm run build`でも動くようになります．
AppStore リジェクト「Safety - Physical Harm: COVID-19 の対策について触れてるけど情報ソースがないよ」の対処

初めて見るリジェクト内容で少し戸惑ったため共有。

# 状況
2021年10月ごろ。
とあるイベントで使用するアプリの申請を行った際に「Guideline 1.4.1 - Safety - Physical Harm」を理由にリジェクトされた。

# 詳細

リジェクト内容は以下。

>  Your app provides health or medical recommendations or references without including the sources of the medical information. 
> Specifically, we found your app includes safety precautions related to COVID-19 upon launch.
> All apps with medical and health information should include links to sources for the information. This helps ensure that App Store users are being provided accurate information. 
> **Next Steps**
> Please include citations in the app of the sources of the recommendations or information and links to those sources. The links to the sources should be easy for the user to find. Resources Please review the App Store Review Guideline 1.4 - Physical Harm for more information on the importance of providing accurate medical information.

COVID-19 関連の情報が含まれているのに情報ソースが示されていないことでリジェクトされていた。
アプリ内では、イベントに参加する際の注意事項としてマスク着用等を呼びかけていた。そのソースが示されていないことで引っかかっていると考えられる。

# 対応
[厚生労働省のコロナウイルス感染予防のサイト](https://www.mhlw.go.jp/stf/covid-19/kenkou-iryousoudan.html)に飛ぶボタンを、注意喚起の View に配置することで審査が通った。
AppleSilicon搭載Macの仮想WindowsでUnityからビルドしたアプリを動かしてみる

Windows向けの社内ツールを作成することになり、動作確認のためWindowsPCを借りて帰ることに。
PC2台担ぐのは肩が痛くて辛いのでMac1台で動作検証くらいならできないかな〜と思いたちました。
会社から借りている仕事用のMacはintel製チップ搭載機なのですが、今後はAppleSilicon搭載機に置き換わっていきそうなので、私物のMacで動かせるか試してみました


ParallelsDesktop 17を使ってWindows11を使えるようにします

#準備
導入方法は公式のこちらの通り
https://kb.parallels.com/en/125375

動かしたいものはUnityでビルドしたWindows用のアプリなので
以下のようなボタンを押したらテキストを表示するだけの簡単なプロジェクトをビルドします

![スクリーンショット 2021-11-08 14.54.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261379/a7e23a32-c4d6-efc0-40fa-2c8d6935d483.png)

![スクリーンショット 2021-11-08 14.56.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261379/edf848b1-7309-d97a-939b-00f4c39c6755.png)


#結果

仮想マシンのWindows上で問題なく動作しました！
![スクリーンショット 2021-11-08 14.53.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261379/23d47df6-cc1f-6244-e9ad-eaebdf0b1fa3.png)


#感想
arm版のWindowsの導入に少し手間どりましたが、導入後は通常のWindowsとかわりなく使用できるように感じました
Windowsのスクリーンショットの撮り方やキーボードのキー配置に慣れないので、Macの機能をそのまま使えるのは非常に使いやすく感じました（普段からデスクトップのWindowsPCを使っているはずなんですが）
Prallels通常版ではRAMが8Gまでなのであまり負荷のかかる作業はできませんが、ちょっとした検証程度なら便利に使えそうです
Sync Gateway機能解説：管理〜停止と再開

## 概要
Sync Gatewayを使用すると、データベースをオフラインにしてオンラインに戻すことができます。これは、Sync Gatewayインスタンスを停止することなく実行されます。

データベースのステータス（オンラインまたはオフライン）の変更は、アドレス指定された特定のSync　Gatewayインスタンスでのみ発生します。同じデータベースを使用する(Sync Gatewayクラスターの)他のSync　Gatewayインスタンスには反映されません。

## ユースケース
データベースのオフライン/オンライン機能の具体的な用途は次のとおりです。

- 他のデータベースに影響を与えることなく、データベースをオフラインにします。
- Sync Gatewayを再起動せずに、データベースの構成プロパティを（オフライン中に）変更します。
- オフライン中にデータベースを再同期します。
- 失われたDCPまたはTAPフィードを検出し、データベースを自動的にオフラインにします。
- オフライン状態でデータベースを作成し、データベースのサービス提供の開始を延期したり、Sync　Gatewayインスタンス間で調整したりできるようにします。
- Couchbase　Serverのアップグレードを実行します。

## アクション

- データベースをオフラインにする：POST `/{db}/_offset`
- データベースをオンラインにする：POST `/{db}/_online`

デフォルトでは、Sync Gatewayが起動すると、構成ファイルで定義されているすべてのデータベースがオンラインになります。Sync Gatewayの起動時にデータベースをオフラインに保つには、`offline`構成プロパティをデータベース構成プロパティに追加します。

後で、データベースをオンラインにするために、POST `/{tkn-db}/_online` Admin RESTAPIリクエストを使用できます。

## 自動オフライン
Sync Gatewayは、データベースのDCPまたはTAPフィードを失うと、データベースを自動的にオフラインにします。これにより、原因を調査して修正することができます。

原因が解決され、フィードが復元されたら、Admin REST APIリクエストを使用してデータベースをオンラインに戻します。

## 状態図
以下の状態図は、Sync Gatewayの状態と、Sync　GatewayとCouchbase　Serverデータベース間の接続を表しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176567/dea673fc-ffbf-2be4-8683-5915c53084c9.png)



- Sync Gatewayインスタンスを開始または停止すると、そのインスタンスがサービスを提供するすべてのデータベースへの接続に影響します。
- 特定のデータベースに対して操作を実行します。たとえば、2つのデータベースをオンラインにし、3つ目のデータベースをオフラインにして再同期し、オンラインに戻すことができます。

## 関連情報

https://docs.couchbase.com/sync-gateway/3.0/database-offline.html
[Python] [openpyxl] １つのExcelファイルから全てのシートを単独のExcelファイルに分割（コマンドライン）

[前回の記事](https://qiita.com/VoshVolk/items/4ed52cedb2214d437ae2)で作成したものを、コマンドライン引数が取れるよう、一般化した。

```python:splitsheet.py
import os
import sys
import argparse
import openpyxl
import copy

def create_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "excel_file",
        type=str,
        help="This is a Excel file. (Supported formats are: .xlsx,.xlsm,.xltx,.xltm. And wildcards cannot be used. )"
    )
    parser.add_argument(
        "dest_dir",
        type=str,
        nargs="?",
        default=None,
        help="This is a destination dir."
    )
    return parser

def split(excel_file, dest_dir):
    try:
        book = openpyxl.load_workbook(excel_file)
        print("EXCEL FILE: " + excel_file)
        for sheet in book:
            file_name = dest_dir + "/" + sheet.title + ".xlsx"
            print(file_name)
            new_book = copy.deepcopy(book)
            for new_sheet in new_book:
                if new_sheet.title == sheet.title:
                    continue
                else:
                    new_book.remove(new_sheet)
            new_book.save(file_name)
        book.close()
        print("COMPLETE!")
    except:
        print("ERROR:")
        print(sys.exc_info()[1])
        sys.exit(1)


def main():
    parser = create_parser()
    args = parser.parse_args()

    if not os.path.isfile(args.excel_file):
        print("ERROR: Excel file does not exist.")
        sys.exit(1)
    
    if args.dest_dir is None:
        dest_dir = "."
    else:
        dest_dir = args.dest_dir
    
    try:
        os.makedirs(dest_dir, exist_ok=True)
    except FileExistsError as e:
        print("ERROR: dest_dir is " + e.filename)
        sys.exit(1)
    
    split(args.excel_file, dest_dir)


if __name__ == '__main__':
    main()
```

github は[こちら](https://github.com/VoshVolk/public_python/blob/main/excel/splitsheet.py)。
Oracle VM VirtualboxでOBAファイルを読み込む方法

#はじめに
いつもは拡張子がvmdkやxdiのLinux OSを用いたVMを利用していました。
今回初めて拡張子がovaのものを扱うので記事を書きました。

# 環境
Windows10
Oracle VM Virtualbox 6.1.26
読み込ませるVMの拡張子 ova

# OVAファイルの読み込み
ツール ＞ インポート(もしくはCtrl + i)で仮想アプライアンスのインポートを開きます。

OVAファイルを選択して読み込みます。
### ガイド付きモードの場合
![20211108_135101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42625/5cb9c007-ba66-bf88-3b75-b98df508a9a0.png)

### エキスパートモードの場合
![20211108_135404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42625/4a431192-aba9-7e40-5ed5-6f1f0fd9a405.png)


インポートを押下するとOVAファイルの読み込みが開始します。
以上です。
ショートカットで「モバイルデータ通信」設定を呼び出す方法

## はじめに

iPhone13に変えてDSDV（物理SIM+eSIM）にしたところ、モバイルデータ通信を切り替える手順が面倒なのでショートカットを導入。
毎回ググるのもアレなので、自分メモとして残す。

通常、「設定」→「モバイル通信」→「モバイルデータ通信」と辿る必要がある。

ショートカットを作成すると、ウィジェットやホーム画面にリンクをおけるので多少の簡略化ができる。
欲を言えばコントロールセンターから呼び出したい。

## 手順

1. 「ショートカット」アプリでマイショートカットを新規作成
1. カテゴリから「Web」を選択
1. 「（Safariで）URLを開く」を選択
1. URLを編集
`
prefs:root=MOBILE_DATA_SETTINGS_ID&path=MOBILE_DATA_SETTINGS
`

![IMG_3225.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384316/3ef7345b-1bc2-5aba-041b-790e6b5bf382.png)
[nginx] 問い合わせフォームへのPOSTリクエストにリファラが設定されていない場合ブロックする設定

Bot とかで大量に問い合わせフォームにリクエストしてくる人がいて困りますよね。
POSTリクエストにリファラとして自ドメインが設定されていない場合は、ブラウザ経由ではなく、直接叩いてるんだろうと仮定してブロックしちゃうのも良いかもしれません。
Nginx で設定するなら、こんな感じ

```
    location ~* ^/contact {
        valid_referers server_names;
        set $allowed 1;
        if ( $invalid_referer ) {
            set $allowed 0;
        }
        if ( $request_method != 'POST' ) {
            set $allowed 1;
        }
        if ( $allowed = 0 ) {
            return 404;
        }

```

Nginx の if 文では複数の条件を書くことができない、else を使用することができないという縛りがあるので、上記のような記述方法になります。

`valid_referers server_names;` は、リファラチェックして自ドメインからのリクエストじゃない場合は `$invalid_referer` に `0` をセットします。
`$allowed` という変数を `1` で初期化しておいて。
`$invalid_referer` だったら `0` をセットする。
`$request_method` が `POST` 以外だったら `1` をセットする。

これで `$allowed` が `0` なら、「許可されていないリファラがセットされている、かつ、POSTメソッドでのリクエスト」ということになるので、404 を返します。
IDaaS としての Azure AD 活用のメリット

#はじめに
本記事では Microsoft 社の Identity as a Service （以降 IDaaS ）である Azure Active Directory (以降 Azure AD )活用によるメリットにつき解説します。
現在多くの企業で SaaS を始めとしたクラウドソリューションの活用が推進されています。一方で ID / パスワードに代表される認証情報を利用する攻撃は増加し続けており、多要素認証などのより堅牢な認証機能の組み込みが必要となっています。
IDaaS である Azure AD を活用することで、SaaS 、オンプレミスのアプリケーションに対する堅牢な認証基盤を容易に構築/運用することが可能です。
当記事では以下３つの観点で IDaaS としての Azure AD 活用のメリットを解説します。
>	・高い可用性と運用負荷の低減
>	・豊富なアプリケーション連携テンプレート
>	・End to End でのセキュリティ対策

#認証情報を利用した攻撃の増加
では攻撃の実態についてみてみましょう。以下の数字が報告されています。
![図1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261868/37ad6dd6-08f5-27eb-7cf8-6e6bb57fd55f.jpeg)

一方で金融サービスや特定の企業を狙った標的型攻撃においては、多要素認証すら破られてしまった事例も出ています。
このような状況を受けて多要素認証/パスワードレスといった技術を使った認証強化やリスクベースアクセス制御の組み込みを検討する企業が増えてきています。


#IDaaS としての Azure AD - 高い可用性と運用負荷の低減 -
認証基盤は全てのサービスの入り口となるため高い可用性が求められる機能コンポーネントです。オンプレミスの認証基盤を使っている場合、攻撃対象となりやすいと判っていてもなかなか脆弱性対応やバージョンアップはできないのが実状ではないでしょうか？
Azure AD では、脆弱性対応やパッチ適用だけでなくバージョンアップもサービスの一部として提供されておりメンテナンス停止はありません。可用性のサービスレベルは 99.99% となっており、オンプレミスの認証基盤と比較すると構築/運用にかかる負荷を大幅に低減することができます。
また Azure AD Premium Plan2 に含まれる Identity Protection を組み合わせることで、リスクの検出だけでなく自動修復まで管理コンソールからの設定のみで実装することが可能です。
参考リンク：Azure Active Directory の価格 | Microsoft Security
https://www.microsoft.com/ja-jp/security/business/identity-access-management/azure-ad-pricing

#IDaaS としての Azure AD - 豊富なアプリケーション連携テンプレート -
Office 365 のユーザリポジトリとして Azure AD を利用していても、Microsoft 以外の SaaS やオンプレミス Web アプリケーションとのシングルサインオンはまだ実装していないという企業も多いのではないでしょうか？ Azure AD はアプリケーションギャラリーとして国内外の多くの SaaS と連携するテンプレートを提供しており、これを活用することでベンダーによる検証済みの構成をもとに容易にSaaSをシングルサインオンの対象とすることができます。例えば Salesforce や SAP のような海外のサービスだけでなく、Sansan や LINE Works など国内のサービスもアプリケーションギャラリーの対象です。
![図2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261868/25197de3-a966-6fff-b38a-213e8a1c125f.jpeg)
参考リンク：Azure Active Directory (Azure AD) アプリ ギャラリー | Microsoft Security
https://www.microsoft.com/ja-jp/security/business/identity-access-management/integrated-apps-azure-ad

#IDaaS としての Azure AD - End to End でのセキュリティ対策 -
認証を Azure AD に集約することで、マイクロソフトだけでなく他社の SaaS 、オンプレミスWebアプリを一元的に保護/監視することが可能となります。またセキュリティ対策においては全体を俯瞰し整合性の取れた対策を施すことが非常に重要です。エンドポイント管理、アプリケーション保護、データ保護を組み合わせ、さらに Sentinel / Splunk / QRadar などの SIEM による統合的な脅威分析/対応につなげていくことも可能です。
![図3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261868/7b223878-98ca-1e96-4cfe-824e597d8803.jpeg)

#まとめ
Azure AD は Office365 のユーザリポジトリだけでなく、最先端テクノロジーを実装した統合認証基盤として活用できる機能を有しています。FIDO2、SAML / OpenID Connect など業界標準技術を使い他社ソリューションとの連携も可能ですので、ベンダーロックインの懸念なく安心してお使いいただけます。

次回の記事では「Azure ADを利用した適応型アクセス制御の現在」を掲載する予定です。

投稿内容は私個人の意見であり、所属企業・部門とは関係ありません。また、いかなる保証を与えるものでもありません。
CloudFormationで出会ったエラー集【随時更新】



###Circular dependency between resources:　[xx,yy,zz]

循環依存でループになってしまい発生するエラー。
回避するには下記を追記

```yml
Transform: AWS::Serverless-2016-10-31
```

https://aws.amazon.com/jp/premiumsupport/knowledge-center/cloudformation-circular-dependency-sam/

ただ、IAMが関わると少し注意が必要らしい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469267/d71a332f-c29c-1cef-ced8-8379fc7ffcc9.png)


####Template format error: Every Default member must be a string.

パラメータの値として関数は使えないみたいなので、文字列リテラルにし解決。
また、下記の投稿を見ると関数の引数も文字列リテラルのみ受け付ける様子。

https://living-sun.com/ja/amazon-web-services/6892-cloudformation-template-format-error-every-deletionpolicy-member-must-be-a-string-amazon-web-services-amazon-cloudformation.html
CentOS5で「M2Crypto.SSL.SSLError」にてyum できなくなったとき

#CentOS5で「M2Crypto.SSL.SSLError」にてyum できなくなったとき

ふっるいCentOS5をvagrant bentoで使っていて、yum が使えなくなった。

```
M2Crypto.SSL.SSLError: tlsv1 alert protocol version
```

そんなときは、`/etc/yum.repos.d/Bento-Vault.repo` の `base_url` を以下に変えてしまうと自分の場合は、うまく `yum`が動いてくれました。

```ssh
#BENTO-BEGIN
[C5.11-base]
name=CentOS-5.11 - Base
#baseurl=http://vault.centos.org/5.11/os/$basearch/
baseurl=http://archive.kernel.org/centos-vault/5.11/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
enabled=1

[C5.11-updates]
name=CentOS-5.11 - Updates
#baseurl=http://vault.centos.org/5.11/updates/$basearch/
baseurl=http://archive.kernel.org/centos-vault/5.11/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
enabled=1

[C5.11-extras]
name=CentOS-5.11 - Extras
#baseurl=http://vault.centos.org/5.11/extras/$basearch/
baseurl=http://archive.kernel.org/centos-vault/5.11/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
enabled=1

[C5.11-centosplus]
name=CentOS-5.11 - Plus
#baseurl=http://vault.centos.org/5.11/centosplus/$basearch/
baseurl=http://archive.kernel.org/centos-vault/5.11/centosplus/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-5
enabled=1
#BENTO-END

```
VBScriptで、すぐに消えるダイアログを表示する

例えば **BizRobo!** は、Automation Anywhere や UiPath のようにダイアログを表示しません。
多分設計思想的にダイアログを出さないのだと思いますが、処理の途中に出した方が便利な時もあります。
以下のようなVBSで、n秒で消えるダイアログを表示できます。

呼び出す時の引数は、以下の3つです。

+ args(0) = prompt（本文）
+ args(1) = title（タイトル）
+ args(2) = waittime（待機秒、消さない時は0）


```vb:ShowPopup.vbs
Option Explicit

On Error Resume Next

'prompt　本文
'title　タイトル
'waittime　待機秒（消さない時は0）

Dim arg

'引数の数は3
If WScript.Arguments.Count <> 3 Then
	WScript.Quit(-1)
End If

Set arg = WScript.Arguments

Dim prompt
Dim title
Dim waittime

prompt = arg(0)
title = arg(1)
waittime = arg(2)

'メッセージは1文字以上
If Len(prompt) =0 Then
	WScript.Quit(-2)
End If

'タイトルは1文字以上
If Len(title) =0 Then
	WScript.Quit(-2)
End If

'第3引数は数字
If IsNumeric(waittime) =0 Then
	WScript.Quit(-3)
End If

Dim WSH
Set WSH = CreateObject("WScript.Shell")
WSH.Popup prompt, waittime, title, vbExclamation
Set WSH = Nothing

'0以外はエラー
WScript.Quit(Err.Number)
```

他のvbsから呼び出すならこんな感じ。

```vb:呼び出し方法
Set obj = WScript.CreateObject("WScript.Shell")
ret = obj.Run("ShowPopup.vbs 本文 タイトル 3",0,True)
```
VBoxManage modifyhd --compact

# VBoxManage modifyhd --compact

同じ記事がたくさんあるので詳細は割愛です。
自分用の雑メモです。

# 概要
VirtualBoxではGuestでファイル等を消しても、一度増えたディスクサイズはホスト側では減りません。
減らし方のメモです。

# やり方

## 1. UUIDをメモ

ホスト側

```
$ VBoxManage list hdds
```

で該当ディスクを探してUUIDをメモ

## 2. ゼロで埋め尽くす

Guest側

```
$ dd if=/dev/zero of=zero bs=4k
$ rm zero
```

## 3. compact

ホスト側

```
% VBoxManage modifyhd "1でメモったUUID"　--compact
```

# まとめ

VBoxManage modifyhd --compactでホスト側のサイズを減らせました。
InDesign JavaScript ライブキャプションの作成

ライブキャプションの作成をするスクリプトは、これで良いのかな・・・？

~~~JavaScript
/*
このスクリプトを利用して起こった不具合の責任は取れません。
ご了承下さい。

更新 2021/11/08
*/

// アプリ指定
#target "indesign";

// スクリプト名
var scriptName = "ライブキャプションの作成";

//スクリプトの動作指定（一つのアンドゥ履歴にする、及び、アンドゥ名）
app.doScript(function(){
    
    // 検索の初期化
    app.findTextPreferences = NothingEnum.NOTHING;
    
        // ダイアログ
    var dialogueFlg = confirm("全ての画像に「オブジェクト」メニューの「キャプション」の「ライブキャプションの作成」を行います。" + "\r"
    + "ライブキャプションの作成が行えない画像には作成は行われません。" + "\r\r"
    + "処理で画像（Rectangle）を選択します。" + "\r"
    + "処理に時間がかかる場合は「ページ」や「索引」、スタイルのウィンドウ等は閉じておいた方が良いかもしれません。" + "\r"
    + "「検索と置換」ウィンドウの　『テキスト』の検索文字列に進行状況を表示します。" + "\r"
    + "止まっているのか動いているのかの判断が出来ると思います（スクリプトウィンドウのメニューの「再描画を有効にする」が選択されている場合）。"
    ,"", scriptName);

    // Noの場合
    if (dialogueFlg == false) {

        // 終了
        exit();
    }

    var textVariablesAssociatedInstancesCount = 0;
    var originTextVariablesAssociatedInstancesCount = countTextVariablesAssociatedInstances(app.activeDocument.textVariables);
    
    var repeatCount = 0;
    
    for(var i = 0; i < app.activeDocument.allGraphics.length; i++){
        
        if(app.activeDocument.allGraphics[i].parent.constructor.name == "Rectangle"){

            app.activeDocument.allGraphics[i].parent.select();
            
            // 処理中表示用
            app.findTextPreferences.findWhat = "processing selectObjectID:" + app.activeDocument.selection[0].id;

            if(app.menuActions.itemByID(132644).enabled){

                app.menuActions.itemByID(132644).invoke();
            }
        }
    }

    // 検索の初期化
    app.findTextPreferences = NothingEnum.NOTHING;

    textVariablesAssociatedInstancesCount = countTextVariablesAssociatedInstances(app.activeDocument.textVariables) - originTextVariablesAssociatedInstancesCount;
    
    // 結果
    alert("ライブキャプション追加数 " + textVariablesAssociatedInstancesCount);

//スクリプトの動作指定の続き
}, ScriptLanguage.JAVASCRIPT, [scriptName], UndoModes.ENTIRE_SCRIPT, scriptName);

function countTextVariablesAssociatedInstances(textVariableCollection){
    
    // 初期化
    textVariablesAssociatedInstancesCount = 0;
                    
    for(var i = 0; i < textVariableCollection.count(); i++){
        
        textVariablesAssociatedInstancesCount += textVariableCollection.item(i).associatedInstances.length;
    }

    return textVariablesAssociatedInstancesCount;
}
~~~
Sync Gateway機能解説：設定〜概要

## 概要
Sync Gateway 3.0ベータでは、「一元化永続的モジュラー構成（Centralized Persistent Modular Configuration）」が導入され、マルチノード、マルチクラスターでの使用により適したものになっています。

一元化永続的モジュラー構成は、これまでのファイルベースの構成方法に置き換わり、モノリシックな構成ファイルへの依存からの脱却をサポートします。これにより、よりシンプルかつ俊敏な構成の更新が可能になります。

一元化永続的モジュラー構成の特徴を、以下の様に整理することができます。

#### ブートストラップの起動
最小限の構成ファイルを使用して、Sync Gatewayノードをブートストラップし、Couchbase Serverクラスターに接続します。このファイル、および設定はノード固有です。

#### 動的構成
データベース設定、アクセス制御ポリシー、およびSync Gatewayレプリケーションに対して、実行中のリモート構成を変更する機能により、よりシンプルで俊敏なメンテナンスが可能になります。

#### 永続的な更新
APIエンドポイントを使用して行われたデータベースの変更はすべて永続化され、Sync Gatewayノードの再起動後も存続します（これは、ファイルベースの構成モードで実行している場合は適用されません）。

#### クラスター対応
APIエンドポイントを介してノードに加えられた構成の変更は、同じクラスターに属する他のSync Gatewayノード（またはノードのユーザー定義サブセット）に伝播されます。

#### セキュアREST API
デフォルトで、REST APIにアクセスする際には、Couchbase ServerのRBACユーザーの資格情報を使用して認証と承認を必要とします。これは、開発、テスト目的で無効にすることができます。


## 構成ワークフロー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176567/a6ab614f-3212-55d3-eb80-326f3d90f0ad.png)




1. Couchbase Serverで管理REST APIのユーザーを設定する。

1. Sync Gatewayノードの実行時の動作を定義するブートストラップ構成ファイルをJSON形式で定義する。この構成はノード固有です。変更を加える場合は、Sync Gatewayを再起動する必要があります。

1. Admin Rest APIを使用して、実行中の構成アイテムを追加または修正します。
すべての変更は、Sync Gatewayの再起動後も保持されます。自動再起動は、変更が必要な場合に開始されます。

## 構成対象

以下を構成および保守します。

- データベース: 必要なデータベースを追加します。

- データベースセキュリティ: ユーザーとロールを構成します。

- アクセスコントロール: ユーザーとロールに対するアクセスコントロールを設定します。

- Sync Gateway間レプリケーション：Sync Gateway間レプリケーションを設定します。

## 関連用語

#### Sync Gatewayクラスター

共通のCouchbase　Serverクラスターに接続されたSync Gatewayノードのコレクション

#### 同種（Homogeneous）Sync Gatewayクラスター

クラスター内のすべてのノードが共通の構成（Config)を共有する同期ゲートウェイクラスター

#### Sync Gateway構成（Config)グループ

共通の構成を共有するSync Gatewayクラスター内のSync Gatewayノードのグループ。グループ内の各ノードは、ノード固有の構成を持つことがあります。

## 構成レベル
ブートストラップ構成ファイルで定義されているか、Admin REST APIエンドポイントで定義されているかに関係なく、すべての構成プロパティは、「ノード」または「データベース」というふたつのコアレベルのいずれかに属します。表1を参照してください。

### ノードレベルプロパティ

||使用|範囲|変更可否？|
|---|---|---|---|
|Couchbase　Server接続|Couchbase Serverバケットへの接続に必要な構成プロパティの最小限のセット（サーバーの資格情報やグループIDなど）|ノード固有。非共有|イエス。再起動が必要|
|システムプロパティ|たとえば、`api.tls.cert_path`およびを含むノードレベルのシステムプロパティ|`max_file_descriptors`|ノード固有。非共有|イエス。再起動が必要|
|ロギングプロパティ|ロギング関連のプロパティ|ノード固有。非共有|管理REST APIによるはい|再起動は不要だが、永続化されない|

### データベースレベルプロパティ

||使用|範囲|変更可否？|
|---|---|---|---|
|DBプロパティ|例えば、データベースなどの構成プロパティbucketのような、またはアクセス制御ポリシーusersとsync|ノード固有の場合がありますが、通常は同じグループ内のノード間で共有される|イエス。Admin REST APIコールにより再起動が必要に応じて開始される|
|レプリケーションプロパティ|Sync Gatewayのレプリケーションプロパティ|参加しているすべてのレプリケーションノードで共有|イエス。Admin REST APIコールにより再起動が必要に応じて開始される|

## 安全な管理
安全な管理はデフォルトでオンになっています。

AdminまたはメトリクスREST APIリクエストを送信するには、その目的のために特定のCouchbase Serverユーザーを作成する必要があります。次に、各APIリクエストで、これらのRBACユーザーに有効なCouchbase Serverクレデンシャルのセットを提供します。

認証されたユーザーは、Adminおよび/またはメトリクスAPI機能、アプリケーションデータ、および構成設定にアクセスできます。


## 構成グループ
Config-Group-IDプロパティ（`bootstrap.group_id`）を使用して、Sync Gatewayノードを同種のクラスターにグループ化できます。これは、ノードが属するデータベース構成グループを定義します。

グループ内のすべてのノードは、同じデータベース構成を共有します。1つのノードから行われた変更は、グループ内の他のノードに自動的に伝播されます。

クラスタ内のすべてのノードは、デフォルトで、共通の`default`グループに属しています。

Sync Gatewayノードを新しいグループに移動すると、そのグループに関連付けられている構成が継承されます。これは、グループを`default`グループに戻す場合も同様です。

## 参考情報

https://docs.couchbase.com/sync-gateway/current/configuration-overview.html
CSSのみで作るアコーディオンメニュー

アコーディオンメニュー

```sample.html
<html>
<head>
<style>
.accordion {
	margin: 0px;
}
.acd-check {
	display: none;
}
.option {
	position: relative;
}
/* アコーディオンCLOSE */
.acd-label,
.acd-content {
	-webkit-backface-visibility: hidden;
	backface-visibility: hidden;
	transform: translateZ(0);
	transition: all 0.1s;
}
.acd-label {
	font-size: 0.9em;
	border: solid 1px #ffffff;
	padding-top: 0.5em;
	padding-left: 1em;
	padding-bottom: 0.5em;
	padding-right: 0em;
	display: block;
	color: #ffffff;
	background-color: #4682B4;
	font-weight: bold;
}
/* プラマイ切り替え */
.acd-label::after,
.acd-label::before {
	content: "";
	position: absolute;
	right: 1em;
	top: 0.8em;
	width: 2px;
	height: 0.75em;
	background-color: #FFFFFF;
	transition: all 0.1s;
}
.acd-label::after {
	transform: rotate(90deg);
}
.acd-content {
	max-height: 0;
	overflow: hidden;
	background-color: #CCCCCC;
}
.acd-content p {
	margin: 0;
	padding-left: 1em;
	padding-top: 0.5em;
	padding-bottom: 0.5em;
	padding-right: 0em;
	font-size: 0.7em;
	line-height: 1.5;
}
/* アコーディオンOPEN */
.acd-check:checked + .acd-label + .acd-content {
	max-height: 500px;
	transition: all 1.5s;
}
.acd-check:checked + .acd-label::before {
	transform: rotate(90deg) !important;
}
</style>
</head>
<body>
<div>
<div style="width:250px;">
	<form>
		<div class="accordion">
			<div class="option">
				<input type="checkbox" id="acd-label1" class="acd-check" />
				<label class="acd-label" for="acd-label1">メニュー1</label>
				<div class="acd-content">
					<p><a href="#">コンテンツ1</a></p>
					<p><a href="#">コンテンツ2</a></p>
					<p><a href="#">コンテンツ3</a></p>
					<p><a href="#">コンテンツ4</a></p>
					<p><a href="#">コンテンツ5</a></p>
				</div>
			</div>

			<div class="option">
				<input type="checkbox" id="acd-label2" class="acd-check" />
				<label class="acd-label" for="acd-label2">メニュー2</label>
				<div class="acd-content">
					<p><a href="#">コンテンツ6</a></p>
				</div>
			</div>

			<div class="option">
				<input type="checkbox" id="acd-label3" class="acd-check" />
				<label class="acd-label" for="acd-label3">メニュー3</label>
				<div class="acd-content">
					<p><a href="#">コンテンツ7</a></p>
				</div>
			</div>
		</div>
	</form>
</div>
</div
</body>
</html>
```
【実装編】remを用いたレスポンシブ実装

[こちら](https://qiita.com/ryowakitazawa82/items/0513cb9f66b3de6e74ba)の記事の続きです。

## レスポンシブを実装するためのscssファイルを用意しよう
1つのファイルに記述しすぎるのは良くないため、新しくファイルを作り、メインのscssファイルにimportしましょう。
### 新しくファイルを作る
※アンダーバーを頭につけることで、Watch Scssの対象から外すことができるため、忘れずにつけましょう。

```
$ touch _responsive.scss // アンダーバ-を忘れずに！
```
もしくはターミナルを使わないで追加。
![スクリーンショット 2021-11-08 11.28.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1994221/d8974c69-4d3c-d33d-79fe-f3957f8f8c1b.png)
### メインのscssファイルにimportする
importは以下のように記述します。

```scss:style.scss
@import "responsive";
```
## _responsive.scssに記述をしよう
ここでは5つのメディアクエリを設定していますが、各自お好みでそうぞ！
可視性を考慮して、max-widthを変数で指定しています。

```scss:_responsive.scss
$pc2: 1279px;
$ipad: 1024px;
$sp: 767px;
$sp2: 360px;
$sp3: 280px;


@mixin pc2 {
  @media only screen and (max-width: $pc2) {
    @content;
  }
}

@mixin ipad {
  @media only screen and (max-width: $ipad) {
    @content;
  }
}

@mixin sp {
  @media only screen and (max-width: $sp) {
    @content;
  }
}

@mixin sp2 {
  @media only screen and (max-width: $sp2) {
    @content;
  }
}

@mixin sp3 {
  @media only screen and (max-width: $sp3) {
    @content;
  }
}

```

### @contentってなんすか
[こちら](https://qiita.com/annaaida/items/a0794a6d38fc1327085a)が参考になると思います。
>@mixinの中で@content;と記述するとコンテントブロックを渡すことができる
>これにより1つのmixinで呼び出し側に合わせた処理が可能

## PC・タブレットをレスポンシブ対応させてみよう
[前回](https://qiita.com/ryowakitazawa82/items/0513cb9f66b3de6e74ba)の記事で、基準値を10pxに指定しましたね。これの基準値を変えるだけです！
※タブレットにもブレイクポイントを置いている場合は、次の項目『SP版のデザインを実装しよう』をご参考に。

```scss:style.scss
html {
  font-size: 10px;
  @include pc2 {
    font-size: 8px;
  }
  @include ipad {
    font-size: 6px;
  }
}
```


## SP版のデザインを実装しよう
SP用のデザインを実装する場合の記述を解説します。
### 記述方法

```scss:style.scss
   @include sp {
        //ここに記述をする
      }
```
まあこれだけですね。

### 具体例
例えばflexの横並びを解除したいとかだと、 『flex-direction: column;』を以下のように指定してあげれば大丈夫です。
逆にモバイルファーストの場合は、flexを当てるって記述になりますね。

```scss
.dummy__list_content-wrapper {
      padding-top: 2rem;
      padding-bottom: 2rem;
      display: flex;
      flex-wrap: wrap;
      border-bottom: 0.5px solid $gray;
      @include sp {
        flex-direction: column;
      }
    }
```
### 各端末の調整
モバイルって色々なサイズがありますからね、、必要に応じて以下のように記述しましょう。
たったこれだけの記述で全てのデバイスに対応できるのはとても楽です。

```scss:style.scss
html {
  font-size: 10px;
  @include pc2 {
    font-size: 8px;
  }
  @include ipad {
    font-size: 6px;
  }
  @include sp {
    font-size: 10px; //追加
  }
  @include sp2 {
    font-size: 8px; //追加
  }
  @include sp3 {
    font-size: 6px; //追加
  }
}
```

### おまけ
モバイルに独自のスタイルを当てる時、結構同じ記述があるんですよね。
その場合は、以下のように@mixinを利用すると良いですよ。

```scss
@mixin sp-wrap {
    padding-left: 3rem;
    padding-right: 3rem;
    width: 31.6rem;
}
```
【CodePen】Qiita記事に埋め込む

CodePenを投稿に埋め込む方法とBootstrapのリファレンスを記載する。

#CodePen埋め込み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2122199/960cb0aa-e3db-5dfb-1173-7c775b8992fc.png)

Embed→HTML (Recommended)をコピーして、Qiitaのエディット画面で貼り付け

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="ExvLjoo" data-user="yui-ko" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yui-ko/pen/ExvLjoo">
  ToDoApp</a> by yui-ko (<a href="https://codepen.io/yui-ko">@yui-ko</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


貼り付けると以下のようになる

```markdown
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="ExvLjoo" data-user="yui-ko" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/yui-ko/pen/ExvLjoo">
  ToDoApp</a> by yui-ko (<a href="https://codepen.io/yui-ko">@yui-ko</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
```
【IoT】お風呂の換気扇を自動停止する環境を作ってみた

##はじめに

どうも、未経験からエンジニア転職をめざしているもきおです。
[AWSだけで飯が食えるのか](https://dev.classmethod.jp/articles/agritech-iot/)や[ラズパイで冷蔵庫のプリンを監視する](https://qiita.com/horoyoi3/items/188b1500bd756966fb5c)の記事を読んで電子工作してみたい！といつしか思うようになりました。

そこで今回はお風呂の換気扇を自動停止する環境をIoT機器を使用し構築してみました。

##作成背景
お風呂に入った後換気扇を付けるのは良いもののある程度換気したら換気扇を止めたいのにいつもつけっぱなしにしてしまい、朝起きてまた付けっぱなしにしてしまったと多々後悔していました。

そこで今回自動で換気扇を切ってくれる装置を作ってみたいと思ったのがきっかけです。
それも湿度が一定値下がってから切りたいと思いました。

ラズパイとAWS Lambdaとかで作るのかなとなんとなく思っていたのですが、調べてみるとSwitchbotという革新的なIoT機器があるではないか！

今回はSwitchbot機器を使用しセッティングしていきます。

##早速構築していく！！

今回使用したのは温湿度計、スイッチ、SwitchBot Hub miniの３点
![スクリーンショット 2021-10-30 17.59.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/26bc0807-201b-47a1-31d0-74a4ad32d061.png)
本来はこの３点セット、エアコンを自動でオンオフするのに使用するのがデフォルトの使用方法って感じらしいのですが、ここからヒントを得て自分がやりたい事をこの機器で実現しました。

###スイッチ動作確認
まずはスイッチの動作確認を行いました。

ん？ちゃんとスイッチ押せないぞ？
スイッチを押そうとすると周りの枠部分が浮いてしまい、上手く換気扇スイッチに力が伝わらず押せていないようでした。

そこで急遽以下を購入

![スクリーンショット 2021-11-08 12.05.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/9412fb66-1192-aff6-eb35-aa884cd7fba6.png)
これを換気扇ボタン部分に貼って高さを出すことによって、正常にボタンを押すことができました

<iframe width="560" height="315" src="https://www.youtube.com/embed/KeyRRQN7JFs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

###お風呂の湿度経緯確認
続いてお風呂の湿度がどのような経緯で下がっていくのかを温湿度計を使用し測っていきました。
お風呂上がった直後のMax湿度は83%でした。そこから換気扇を回し、55%程度で落ち着きました。
![IMG_0145.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/033878f2-3d69-374f-b1b4-d17bf6f1e919.png)


![IMG_0148.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/094419e0-9ddb-8778-6b1d-39cdf7f2c7c1.png)
よって60%を切れば換気扇を止めても良さそうだと思いました。


###各種Switch Bot接続、セッティング
あとは各SwitchBotをSwitchBot Hub miniを使用し連携。
SwitchBotアプリ内で湿度60％以下になったらスイッチを押すシーンを設定すれば完了となります。

![IMG_0146.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/d601caa6-b295-1930-0c72-f98a143df784.png)
こんな感じで60%以下になったらスイッチのボタンを押す設定をしました。他にも温度をトリガーにしたりもでき、さまざまなシーンを設定できそうです。非常に便利！！

最後にこのシーンで動作するかテストを行いました。
<iframe width="560" height="315" src="https://www.youtube.com/embed/NZVWXN4Nluw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

無事動作できているみたいです。

これでお風呂上がったら換気扇を手動で回す→湿度が60%以下になったらSwitch Botのシーンが発動→スイッチが起動し換気扇を自動停止してくれるという一連の流れを構築できました！！

##あとがき

今回はIoT機器を使用しお風呂の換気扇を自動停止する環境を構築してみました。
ちょっとスイッチがうまく押せない、SwitchBot Hub miniが全然Wi-Fiと接続してくれないなど手こずる面はありましたが、非常に楽しかったです。

今後はちゃんとコードも書いてLINEbot通知とかも導入していきたいです。

大人の自由研究みたいで最高！
最後までご覧いただきありがとうございました！
【Mac版】AndroidStudioでRealmのパスを確認してRealmのデータを確認するまでの流れ

先にパスの表示

        var realm = Realm.getDefaultInstance()
        val realmPath = realm.path
        Log.d("realmpath",realmpath.toString())


するとこんな感じでパスを返されます。

/data/user/0/com.example.buttonapp2/files/default.realm

ただ実際のパスは
![スクリーンショット 2021-11-08 12.03.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/29705da3-f97e-bbb1-5049-e6d9da0cdaa3.png)

userねえじゃん！0もねえじゃん！！！と若干イラつきつつ

デフォルトの実際のパスは

data/data/com.example.buttonapp2/files/default.realm

上記のような感じでした。

それどうやってみんの？ってとこなんですけど、

![スクリーンショット 2021-11-08 12.07.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/b419696d-43b6-301a-470a-26e5787f846a.png)

僕はAndroid studioを日本語化しちゃってるんであれなんですが、デバイス・ファイル・エクスプローラーみたいな欄がクッソわかりづらく存在してます。

そこをタップします。

するとこんな感じでバーって出てきます。

![スクリーンショット 2021-11-08 12.13.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/d1c1efb7-d8e2-43b0-fa3b-2f4731345f16.png)

それでdata→dataと進んでもらって自分のアプリ名と同じフォルダがあります。

僕の場合だとcom.example.buttonapp2



その後にfilesという場所があるのでそこをタップするとdefault.realmがあるのが確認できます。

ただそれをタップしてもデータベースの中身は見れません。

クソが！！！！！！！と思いつつ悪戦苦闘してたんですけど、default.realmを二本指でタップしてみると

![スクリーンショット 2021-11-08 12.18.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494487/dd215daf-0050-b10c-73b3-697d8f9854aa.png)

こんな感じで出てきて別名保存やったらデスクトップにコピーできました。

iOS畑からandroidを触ってみてrealmのパスごときでクソめんどくせえと思いつつ今後もこの工程で詰まるなと思ったので怒りのエネルギー使ってバーーーーーーっと書きました

記事を探したんですけど、ターミナル使ってどうのこうのとかそれでコピーとかやってたんですけど、もっと簡単な方法ないんかと思ってやってたらこれが一番楽だろって思ったので共有です。

参考にしていただけたら幸いです。
【Swift】文字列から特定の文字を削除

Swiftで文字列から特定の文字を削除。

例えば郵便番号や電話番号、検索ワードで入力されてほしくない、半角スペースや全角スペース、伸ばし棒などを取り除きたい時などに使用。

```swift
//半角と全角の空白
var str1 = "文房具 消しゴム　　　　おすすめ"
//半角と全角の伸ばし棒
var str2 = "0120-0000ー0000"

let delete_str: Set<Character> = ["-","ー"," ","　"]
str1.removeAll(where: { delete_str.contains($0) })
str2.removeAll(where: { delete_str.contains($0) })
```
`delete_str`で設定した文字（単数でも複数でも可）がすべて削除されます。

## 参考
https://developer.apple.com/documentation/swift/array/3017530-removeall

https://developer.apple.com/documentation/foundation/characterset
## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
【準備編】remを用いたレスポンシブ実装

web制作において苦戦しがちなのが、レスポンシブの実装ですよね。
そこで今回は、remを使って楽にレスポンシブを実装する方法を記事にしてみようと思います。
※この記事ではPCファーストでレスポンシブを実施していますが、モバイルファーストの場合でも参考になると思います。
## remって？
[こちら](https://owl-view.com/css/1099/)とか参考になると思います。
要は相対的にfont-sizeを決められる単位がremです。
そのため、レスポンシブ対応する際に便利な代物なのです。

## remで記述する準備をしよう
### 基準値を設けよう
キリよく、10pxとしておきましょう。

```scss:style.scss
html {
  font-size: 10px;
}
```
### そうすると、、
px* 0.1でremを使用できます！

| px | rem | 
| :--- | :--- | 
|10px | 1rem |
|14px | 1.4rem |
|16px | 1.6rem |

### 使ってみる
あとはpxみたいに使えるので、難しいことはないですね。

```
margin-top: 14rem;
```

## さあ記述しよう
あとは普通にいつものように記述してください！
remを用いたコーディングが終わったら、いよいよレスポンシブを実装していきましょう。
続きはまた別の記事で。
[実装編の記事はこちら](https://qiita.com/ryowakitazawa82/items/fd9e787bdd4008e4e117)
【SQL】CASE文の使い方

# 入力データ ※データの作成は一番下を参照

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/bb7fdfff-7702-8e84-8fb0-7e5734f0ba88.png)

#実行文
```SQL
SELECT id,name,price,

CASE 
    WHEN 40 <= price  THEN  "合格(ラクラク)"
	ELSE "不合格"
END

判定

FROM food_data;

```

１・priceが40以上だった合格
２・priceが40以下だったら不合格


#結果   ※条件分岐によるカラムを追加できた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/938fe14e-6c90-054d-db7f-d583a32d9dc3.png)




#データ作成

```SQL
CREATE TABLE `food_data` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `category` varchar(255) DEFAULT NULL,
  `price` int(10) DEFAULT '0',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=2423 DEFAULT CHARSET=utf8mb4;

```
terraform でVPCなどを作る


参考
--

https://qiita.com/gogo-muscle/items/58fee5760400ff1bc602

https://hacknote.jp/archives/58595/

前提
--

Windows10 WSL Ubuntu 
terraform
aws cli
導入済み


手順
--
①作業ディレクトリを作成する。参考サイトのようにファイルやフォルダを作成する
②treeコマンドを入っていなかったらインストールする
③terraform.tfvars　を作成する
④main.tf を編集する
⑤terraform init
⑥terraform plan
⑦terraform apply

AWSコンソール上で作成されていること確認する