OmniAICreator/Qiita-1.07M huggingface dataset:
gcloudからのcloud functions操作メモ


#### 認証
```
gcloud auth login
```

#### プロジェクト作成
```
gcloud config configurations create <任意の設定名>
gcloud config set project <gcp上のプロジェクト名>
gcloud config set account <gcpのアカウント>
```

#### プロジェクトの切り替え
```
gcloud config configurations list  ##設定名の確認
gcloud config configurations activate <切り替え先の設定名>
##変更後、listで対象の設定のIS_ACTIVEがTrueになっていることを確認
```

このあたりの参照元：<a href="https://qiita.com/sonots/items/906798c408132e26b41c">gcloud でプロジェクトの切り替え設定</a> 

#### functionの確認
```
##対象のプロジェクトに入ってる状態で
gcloud functions list
```

#### functionのダウンロード
既に作成されてるfunctionをダウンロードしてくるコマンドはないっぽい。(2019年1月現在)
なのでGUIからZIPをダウンロードしてくる。

#### functionのデプロイ
```:初回/ランタイムとトリガーの指定が必須
gcloud functions deploy <function name> --region=<デプロイ先region> \
--runtime <ランタイム> \
[FLAGS...]

例)
gcloud functions deploy test_function_1 --region=asia-northeast1 \
--runtime nodejs8 \
--trigger-http \
--memory=512MB \
--entry-point=exported_function \
--allow-unauthenticated
```


指定しなかったオプションについてはデフォルト値で作成される。
`--entry-point`についてはプロジェクト名と同じFunctionで検索されるので、違う関数名にしてる場合はちゃんと指定してあげないとエラーになる。
外部公開するFunctionの場合は、`--allow-unauthenticated`を指定する。
※CloudFunctions起動元に`allUsers`を追加するオプション。昔はデフォでついてたけど最近デフォでは認証が必要になった。
各オプションのデフォルト値や、記載以外のオプションについては<a href="https://cloud.google.com/sdk/gcloud/reference/functions/deploy?hl=ja">公式参照</a>のこと。

```:アップロードファイル構成例(nodejsの場合)
.
├ index.js       //コード
├ package.json   //必要なパッケージ
├ .env.yaml      //環境変数を記載
└ .gcloudignore  //uploadしないファイルを指定(yamlファイルとか。自身も無視でOK)
```


2回め以降のアップデートでは必要なオプションのみ記載すればOK。
ただし、もしデフォルトregion以外で作成してた場合は、`--region`オプション必須。
CloudFunctionはFunction名/regionで一意に判別してるっぽい。

```:2回目以降のアップデート例
gcloud functions deploy <function name> --region=<region> [FLAGS...]
```

なお、Current Directory以外のファイルをアップしたい場合は`--source=PATH`で指定必須。


#### 環境変数の指定
1個1個指定もできるが、yamlで書いて`--env-vars-file=FILE_PATH`でアップするのが良さそう。
既存の環境変数はすべてクリアされるので注意。
Win「このデバイスは現在使用中です」俺「いや誰が？」

## 概要

下記のメッセージが出てきたときに、どのプロセスがデバイスを使用しているのか調べる方法。

> 
> USB 大容量記憶装置 の取り外し中にエラーが発生しました
> 
> このデバイスは現在使用中です。デバイスを使用しているプログラムまたはウィンドウを閉じてから、再試行してください。

## 方法

### 準備

* [Sysinternals Process Explorer](http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx) をインストールしておく

### 使用中メッセージが表示されたら

* **Process Explorer を起動**
* **メニュー：Find Handle or DLL**
* **ロックされてるデバイスのドライブレター（ `E:` とか `F:` とか）を入力して検索**
* そのデバイス内のファイルを使用しているプロセス一覧が出てくる :sunglasses:

## 参考元

https://superuser.com/questions/87364/can-windows-tell-me-what-is-using-my-usb-drive

＊完全に上記リンク内容のコピペですが、日本語メッセージで検索してもヒットしなかったのでここにまとめました。
React HooksのuseEffectの中でコンポーネント内の変数を呼び出す

### Before

```react
export const HogeComponent: React.FC = (() => {
  const fuga = useSelector((state: State) => state.fuga);
  const dispatch = useDispatch();

  useEffect(() => {
    const piyo = fuga.someMethod();
    dispatch(MogeAction.someAction(piyo));
  }, [dispatch]);

  return (......
});
```

このようなコンポーネントで、Appコンポーネントに付随する非同期処理で `fuga` がstoreに入る前に、 `useEffect` が呼ばれてしまった。

### After

```react
export const HogeComponent: React.FC = (
  const fuga = useSelector((state: State) => state.fuga);
  const dispatch = useDispatch();

  useEffect(() => {
    const piyo = fuga.someMethod();
    dispatch(MogeAction.someAction(piyo));
  }, [dispatch, fuga]); // 第2引数にfuga追加

  ......
});
```

`useEffect` の第2引数に使う変数を書いたところ、変数の更新と同時に `useEffect` が呼ばれるようになった。
Lightning Web Componentでdeployは成功するのにcomponentがsalesforce上で表示されない

# 概要

lightning web component開発にてsalesforcedx cli上ではエラーが出ないのにいざsalesforce上のアプリケーションビルダーなどで閲覧するとcomponentが表示されない現象に悩まされたが解決したのでメモ

## 解決法

```bash
SFDX:Create Lightning Web Component
```

コマンド又は、

```bash
sfdx force:lightning:component:create --type lwc --componentname example --outputdir force-app/main/default/lwc
```

などとすると、exampleディレクトリが作成されるとともに、

-example.html
-example.js
-example.js-meta.xml
が作成される。

この時のexample.js-meta.xmlにデプロイした後salesforce上のどのアプリケーションで表示させるかを指定する。

```xml
<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>47.0</apiVersion>
    <isExposed>false</isExposed>
</LightningComponentBundle>
```

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata">
    <apiVersion>47.0</apiVersion>
    <isExposed>true</isExposed>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__HomePage</target>
    </targets>
</LightningComponentBundle>
```

などとコンポーネントを表示するターゲットをxml上で明記する必要がある。

## 参考になるページ

### js-meta.xmlについて

- <https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.create_components_meta_file>
- <https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.reference_configuration_tags>

### salesforce Lightningアプリケーションビルダーでデプロイする場合

- <https://developer.salesforce.com/docs/component-library/documentation/lwc/lwc.use_config_for_app_builder>
【Embulk】CSVの全カラムをString型で取り込みたい場合

バルクETLツールである[Embulk](https://www.embulk.org/docs/)は CSVデータを扱う際にデフォルトでデータ型の推測してくれる。

しかし、必ずしも推測されたデータ型に合致しないデータが出力されることもある。
その場合 推測されたデータ型と一致しないレコードはスキップされてしまう。

```
13:06:58.841 +0900 [WARN] (0015:task-0000): Skipped line s3://~~~ (org.embulk.spi.time.TimestampParseException: Cannot parse '### not datatime column' by '%Y-%m-%d %H:%M:%S'): ...
```

なんとかできないかと思っていたら、ドンピシャで解決してくれる神プラグインが提供されていた。

[Add csv_all_strings guess plugin](https://github.com/embulk/embulk/pull/489)

```digdag
exec:
  exclude_guess_plugins: ['csv']
  guess_plugins: ['csv_all_strings']
in:
  type: csv
  ...
```

上記のように`exec`セクションを`in`、`out`などと同様トップレベルセクションとして記載するだけでOK。
しかもデフォルトで使える（`embulk gem install` は不要）。
3分でイメージできるPrometheus

## Prometheusとは
- クラウドネイティブなPull型の監視・モニタリングツール
- OSSなので無料で使える
- https://github.com/prometheus/prometheus

## マインドマップにしてみた
書いてみたところ俯瞰できるのでイメージしやすかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97541/97e20fe4-851f-353d-0d8b-39566ed66d4f.png)
再帰関数

はじめに、 木情報源であったり、決定木アルゴリズムだったり、木構造の再帰を使う機会が多いので、再帰関数についてまとめたいと思います。
自分自身を実行する関数を再帰関数といい、再帰関数内の自分自身の実行箇所を再帰呼び出しと言います。

```python:recursive.ipynb
def recursive_f(depth):
  print("depth: "+ str(depth))
  if depth == 10:
    return 
  recursive_f(depth + 1)

if __name__=="__main__":
  recursive_f(0)
```
実行結果は次のようになります。
depth: 0
depth: 1
depth: 2
depth: 3
depth: 4
depth: 5
depth: 6
depth: 7
depth: 8
depth: 9
depth: 10

自分自身を呼び出すので、どこかで条件分岐をしてあげなければ無限に実行が続きます。

決定木で実装する時は、ノードクラスを作ってやり、自分の子ノードを格納するメンバ変数を持たせ、自分を分割して子ノードを生成するメンバ関数を再帰関数化してやればいいです。自分の子ノードとなるメンバ変数が、更に孫ノードとなるメンバ変数を持ち、更に曽孫ノードとなるメンバ変数を持ち、、の様に永遠に子ノードを生成します。
簡単のため、深さが3のときの図を表すと、
<img width="701" alt="スクリーンショット 2020-01-21 15.26.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554960/bb85f0af-a1aa-325f-99e5-f9b6822c28a8.png">

これをコード化してあげると

```python:recursive_tree.ipynb
class Node:
  def __init__(self, max_depth):
    self.left = None
    self.right = None
    self.max_depth = max_depth
    self.depth = None
        
  def split_node(self, depth):
      self.depth = depth
      print("depth: " + str(self.depth))
        
      if self.depth == self.max_depth:
          return

      self.left  = Node(self.max_depth)
      self.right = Node(self.max_depth)

      self.left.split_node(depth + 1)   # recursive call
      self.right.split_node(depth + 1)  # recursive call

if __name__ == "__main__":
    max_depth = 3
    initial_depth = 0

    tree = Node(max_depth)
    tree.split_node(initial_depth)
```
実行結果
depth: 0
depth: 1
depth: 2
depth: 3
depth: 3
depth: 2
depth: 3
depth: 3
depth: 1
depth: 2
depth: 3
depth: 3
depth: 2
depth: 3
depth: 3
以上が、再帰関数の利用例です。この考え方を身につけると決定木アルゴリズムが実装しやすいのでぜひ試してみましょう。
メソッド名を日本語(JP)で作ったら分かりやすいんでは

*日本語でコーディングしてもコンパイルが通るみたいな話じゃないよ


## 言いたいこと
コーディング始めにメソッドを作るとき

パッと見何をやるかわかりにくい ↓

```csharp:実装.cs
#region event
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
    IsPaintBox();
}
#endregion
#region method
private void IsPaintBox()
{
    if (csrPos[0] <= BOX_POS_LEFT) return;
    if (csrPos[0] >= BOX_POS_RIGHT) return;
    if (csrPos[1] <= BOX_POS_TOP) return;
    if (csrPos[1] >= BOX_POS_BOTTOM) return;

    PaintBox();
}
private int[] GetMousePosition()
{

}
private void DrawBoxFrame()
{

}
private void PaintBox()
{

}
#endregion

```

ので 日本語でみたら

```csharp:日本語.cs
#region イベント
マウスが動いたときのイベント()
{
	四角に色を塗るか判断するメソッド();
}
#endregion
#region メソッド
マウスの位置を補足するメソッド()
{

}
// 画面初期描写時にのみ使用する
四角を描写するメソッド()
{

}
四角に色を塗るか判断するメソッド()
{
	マウスの位置を補足するメソッド();
	if(マウスの位置が四角の中なら)
	{
		四角を塗るさせるメソッド();
	}
}
四角を塗るメソッド()
{

}
#endregion
```
わかりやすくない？　って話
## 問題提起
最初から英字・ローマ字でコーディングすると、めっちゃ頭がこんがらがる...

→なら日本人に合った言語＝日本語でコード組み立ててみたらいいんでは
→分かりやすくなった（手間は増える）
## メリット（日本語で組むとどうなる）
・わかりやすい≒見やすい　→ 不足点・変更点が見つけやすい
　これが大きい

・そのままコメント化できる
　英字で作った後にコード読み直しながら概要コメントを作らなくていい

・メソッド名を考えやすくなる
　マウスが四角の上に来たら四角を塗りつぶすメソッド
　→マウスが四角の上に来たら/四角を塗りつぶすメソッド
　→Mouse_On_Square / Paint_Square
　→Paint_Square_On_Mouse
　みたいな

・メソッド作る目的の軸がブレない
　GetMousePosition より マウス位置取得、の方が
　目的が明確に見える　ワイは見える
## デメリット
・多人数プロジェクトだと 命名の仕方が人によってバラつきが出そう
　日本語→英字に変える時、コーディングルールに気をつけよう
　既存メソッドがあるならそれに合わせよう（既存プロジェクトなら）

・後で結局メソッド名作んなきゃなのでめんどくさい

## 具体例
作成するプログラムは
「カーソルを四角の中に移動させると、四角の中に色がつく」
とする

流れとして
①イベントとメソッドを１つずつ作る
②メソッドを細分化する
③メソッドへ遷移する条件分岐を考える
④足りなそうなメソッドを足す
⑤完成
の順で考える


```csharp:①イベントとメソッドを１つずつ作る.cs
マウスが動いたときのイベント()
{
	四角に色を塗るか判断するメソッド();
}
四角に色を塗るか判断するメソッド()
{

}
```
すごく大まかにつくる ↑

```csharp:②メソッドを細分化する.cs
四角に色を塗るか判断するメソッド()
{

}
//↓
マウスの位置を補足するメソッド()
{

}
四角を塗るメソッド()
{

}
```
大まかなメソッドに、何が必要なのかを解体して考える ↑

```csharp:③メソッドへ遷移する条件分岐を考える.cs
四角に色を塗るか判断するメソッド()
{
    マウスの位置を補足するメソッド();
    if(マウスの位置が四角の中なら)
    {
    	四角を塗るメソッド();
    }
}
マウスの位置を補足するメソッド()
{

}
四角を塗るメソッド()
{

}
```
どう遷移するかぼんやり書く↑

```csharp:④足りなそうなメソッドを足す.cs
四角の枠を描写するメソッド()
{

}
```
上の方で遷移書いてみて、足りないなーと思う機能（動作）が出たら追加する
出なければいい

```csharp:⑤完成.cs
マウスが動いたときのイベント()
{
	四角に色を塗るか判断するメソッド();
}
四角に色を塗るか判断するメソッド()
{
    マウスの位置を補足するメソッド();
    if(マウスの位置が四角の中なら)
    {
    	四角を塗るメソッド();
    }
}
マウスの位置を補足するメソッド()
{

}
四角を塗るメソッド()
{

}
四角の枠を描写するメソッド()
{

}
```

みたいな

## 最後に
英語がわかりにくいんだ
印刷物について for mac

# 基本
カラーモード = CMYK
単位 = mm（用紙、画像サイズ）, pt（フォント）
解像度 = 350推奨 （適宜変更可）
※ポスターなど遠目に見るものは150〜200などだいぶ下げても良い
**画像のファイルサイズ、解像度は容量が大きくなりやすく負担になりやすいので十分配慮する**

# 作業
* 紙を確認する（発色が異なるため）
* illustratorで新規作成
* レイヤー名を「トリム&ガイド」などに変更
 * トリムつける
 * 適宜ガイドをひく
 * 他オブジェクトは置かない！
* 新規レイヤー名称を「背景」などに設定
 * 背景全面にpsdを敷く場合はトリムサイズでpsdを作成する（NG:大きすぎ=容量大きくなる）
     * トリムに沿ってオブジェクト作成しphotoshopにコピペでサイズ計らず簡単作成
 * 背景用のオブジェクトのみ置く！
* 新規レイヤー名称を「デザイン」などに設定
 * デザイン用の素材を置く
* 適宜レイヤーを増やし、ロックかけたり外したり事故らない作業を心がける
* 入稿の際は入稿先のルールに従って1つのレイヤーにオブジェクトをまとめたり適宜作業あり

## 注意事項
### illustrator
* テキストエリアに表示される赤い「+」のマークはエリア外にテキストが溢れた状態なので必ず確認して消えた状態に修正する！
* ぼかし機能などを使用する場合、[効果]→[ドキュメントのラスタタイズ効果設定]の内容を紙用に設定する

## ちょいコツ
### illustrator
* [テキストばらし](https://www.tactsystem.co.jp/applescript/illustrator07.html)入れとくと便利（入れ方は「illustratoer イラレのver スクリプト mac」などで検索）
* 上記で大雑把にテキストを整形してpsdに書き出しなど便利
* 必要なければ背景に写真素材を使用しないデザインにする
* illustratorで作れる素材は写真素材を使用しない
 * 但し、複雑なパスのイラストはpsdにした方が軽量な場合もある
* アピアランスを活用して修正しやすいデータにする
* タブルーラーを使用して目次のようなデザインを簡単作成
* ブレンドツールを使用するとノート素材を簡単作成できる
* オブジェクトのグループ化→ダブルクリック=グループ内編集モードを活用する

### photoshop
* 写真素材の色調整はrgbで出来るだけ調整し、cmyk変換後はちょこっと仕上げ
* 無彩色の写真素材はcmykではなくグレースケールに変換すると容量削減できる
* 長方形の素材は斜めで作らず横にしてaiに配置してから斜めにする（画像容量の節約）
* アクションを作ってバッチ機能を活用すると便利
* QRコード→tiffで大丈夫。解像度1200でも軽量

#ショートカット
```
以下オススメのショートカットです。
強粘着の付箋に覚えたい物を書いて貼って、覚えたら捨てるといいですよ。
```
### illustratorのショートカット

| 説明 | キー |
|---|---|
| [ command ]+[ R ] | ルーラーの表示/非表示 |
| [ command ]+[ 5 ]  | オブジェクトをガイドに変換 |
| [ command ]+[ ; ] | ガイドの表示/非表示 |
| [ command ]+[ shift ]+[ T ] | タブルーラーの表示/非表示 |
| [ command ]+[ g ] | オブジェクトのグループ化 |
| [ command ]+[ shift ]+[ g ] | グループ解除 |
| オブジェクトを選択して<br>[ command ]+[ 2 ] | オブジェクトのロック |
| [ command ]+[ option ]+[ 2 ] | オブジェクトのロック一括解除 |
| [ command ]+[ D ] | 前回の変形の繰り返し |
| [ O ]→[ enter ] | リフレクトツール |
| [ S ]→[ enter ] | 拡大縮小ツール |
| [ R ]→[ enter ] | 回転ツール |
| [ V ] | 選択ツール |


### photoshopのショートカット
| 説明 | キー |
|---|---|
| [ command ]+[ R ] | ルーラーの表示/非表示 |
| ルーラーからガイドを引く時に[ shift ] | 1px単位で揃う（小数点の位置にならない） |
| [ command ]+[ J ] | レイヤーの複製 |
| [ command ]+[ I ] | 階調の反転 |
| [ command ]+[ g ] | レイヤーのグループ化 |
| [ command ]+[ shift ]+[ g ] | グループ解除 |
| [ command ]+[ [ ] | レイヤーを背面に移動 |
| [ command ]+[ shift ]+[ [ ] | レイヤーを最背面に移動 |
| [ command ]+[ ] ] | レイヤーを前面に移動 |
| [ command ]+[ shift ]+[ ] ] | レイヤーを最前面に移動 |
| [ shift ]+[ + ] または<br>[ shift ]+[ - ] | 描画モードを順に切り替え |
| [ V ] | 選択ツール |
Pythonの正規表現が覚えられない

使い方のかんたんなメモ

```py
import re
ptn = re.compile(r"hoge+")  # 使い回すならcompileしたほうが速い
ptn_with_capture = re.compile(r"(hoge)e*")  # キャプチャはカッコを使う
string = r"hogee_qwerty_hogeeeeee"

# マッチする最初の部分を取得
first_matched_string = re.search(ptn, string).group()
print(first_matched_string)
# => hogee
# キャプチャをつけるとgroup(番号)でその部分だけ取得
first_matched_string = re.search(ptn_with_capture, string).group(1)
print(first_matched_string)
# => hoge

# マッチするすべての部分をリストで取得
matched_string_list = re.findall(ptn, string)
print(matched_string_list)
# => ['hogee', 'hogeeeeee']
# キャプチャをつけるとキャプチャ部分だけ取得
matched_string_list = re.findall(ptn_with_capture, string)
print(matched_string_list)
# => ['hoge', 'hoge']

# マッチするすべての部分をイテレータで取得
matched_string_iter = re.finditer(ptn, string)
print([ s.group() for s in matched_string_iter])
# => ['hogee', 'hogeeeeee']

# マッチする部分で文字列を分割
split_strings = re.split(ptn, string)
print(split_strings)
# => ['', '_qwerty_', '']

# マッチする部分を別の文字列で置換
replace_with = r"→\1←"  # バックスラッシュと番号でキャプチャしたものを使う。 
substituted_string = re.sub(ptn_with_capture, replace_with, string)
print(substituted_string)
# => →hoge←_qwerty_→hoge←

# 最小マッチ
minimal_ptn = re.compile(r"h.*?e")  # *や?、+など繰り返しを表す記号の後ろに?をつけて最小マッチ。
minimal_matched_string = re.search(minimal_ptn, string)
print(minimal_matched_string.group())
# => hoge
```
dotenv のサンプルメモ

bkeepers/dotenv: A Ruby gem to load environment variables from `.env`. https://github.com/bkeepers/dotenv

# サンプル

- 存在しないキーを指定すると `nil` となる
- 実際の環境変数があったらそちらが優先される

```sh:.env
TEST="hogehoge"
```

```ruby
require "dotenv"
require "pp"

Dotenv.load

pp ENV["TEST"] # => "hogehoge"
pp ENV["TEST2"] # => nil
```
Edge(Chromium版)で IEモードするまで (Stable版)

# 目的

仕事上 Internet Explorer での確認が必要で、でも開発や調査には Chromium系のブラウザがいい、切り替えるのも面倒ってことで新らしい edge で IEモードをできるようにする

# 環境
* Windows 10 Pro (1909)
* Workgroup 環境 ( Active Directory 環境ではない )
* Microsoft Edge: `バージョン 79.0.309.68 (公式ビルド) (64 ビット)`

> 公式サイトでは **Microsoft Edge ポリシー テンプレート** をダウンロード&インストール と書いているのでその通りに行ったが、グループポリシーに表示されなかった。

# 作業

1. edgeのアドレスバーに `edge://flags/` を入力した画面上で、 **Enable IE Integration** を **IE mode** に変更
  ![p2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169835/b518dcec-1914-317e-021c-e4ef94c926e9.png)
2. IE mode 表示するサイトのリストを **Enterprise Mode Site List Manager** で作成(またはxmlを直接書いてしまう)
3. **ドキュメント** フォルダとか適当な自分用のフォルダにファイル配置
4. **ローカル グループ ポリシー エディター** を開く
5. [ユーザーの構成] > [管理用テンプレート] > [Internet Explorer] > [エンタープライズ モード IE の Web サイト一覧を使用する] を開く
  ![p3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169835/c2871575-e65b-caca-851d-6d33668b9285.png)
6. 有効を選択し、オプションのURLの箇所にファイルまでのパス (例: `C:\Users\~~~\Documents\sites.xml`) を入力してOK
7. ここで edge 再起動必要かは分からないがとりあえず、いったん edge を閉じた

> ※下のように UTF-8, CRLF で作成すればツール不要だと思う

```xml:sites.xml
<site-list version="1">
  <created-by>
    <tool>EMIESiteListManager</tool>
    <version>10.0.14357.1004</version>
    <date-created>01/21/2020 00:00:00</date-created>
  </created-by>
  <site url="192.168.11.29">
    <compat-mode>Default</compat-mode>
    <open-in>IE11</open-in>
  </site>
</site-list>
```

# 結果
xmlで指定したurlの場合だけそのタブ上の内容が IEモードに自動で切り替わり表示された。(他のurlで始まっているのは通常の表示)

![p1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169835/0640ea57-f5ef-ba86-171a-ae28a0a0016e.png)

# 参考
* https://docs.microsoft.com/ja-jp/deployedge/edge-ie-mode
* https://qiita.com/yuppejp/items/acec7c8d248e888a9a8d
logwatchの送信元アドレスを変更する

logwatchの送信元アドレスを変更する方法です。
標準の設定項目では実現できなかったため、メール送信は標準機能に頼らず、sendmailコマンドに頼りました。
環境：RHEL7.5、logwatch-7.4.0-35.20130522svn140.el7_5.noarch

以下、私がトライした順に記載します。

# logwatchの送信元アドレス設定

/etc/logwatch/conf/logwatch.conf に、MailFrom = メールアドレス といった形式で記載するようです。
なお、@は特別な意味に解釈されてしまうようですので、\@のようにエスケープが必要です。
※どのファイルに設定するべきかは多くの方が記事を書かれているので割愛。

私の環境では自サーバ内のPostfixを経由してメール送信しているのですが、MailFromの設定をおこなっても、Postfixのログ上はずっとFromがrootのままで、意図した変更にはなりませんでした。

# logwatchのメール送信部分を読み解く

どうもlogwatchは、メール本文中にあるFromにセットしているようで（1154行目）、EnveropeFromは何も指定していない。このため、Postfixで見るとFromは実行ユーザであるrootになってしまうのだと思いました。

```
# cat -n /usr/share/logwatch/scripts/logwatch.pl
  （中略）
  1143     #fixme mailto
  1144        if (($Config{'hostformat'} eq "splitmail") || ($emailopen eq "")) {
  1145           #Use mailer = in logwatch.conf to set options. Default should be "sendmail -t"
  1146           #In theory this should be able to handle many different mailers. I might need to add
  1147           #some filter code on $Config{'mailer'} to make it more robust. -mgt
  1148           open(OUTFILE,"|$Config{'mailer'}") or die "Can't execute $Config{'mailer'}: $!\n";
  1149           my $mailto = $Config{"mailto_$Config{'hostname'}"};
  1150           $mailto = $Config{'mailto'} unless $mailto;
  1151           for my $to (split(/ /, $mailto)) {
  1152              print OUTFILE "To: $to\n";
  1153           }
  1154           print OUTFILE "From: $Config{'mailfrom'}\n";
  1155           #If $Config{'subject'} exists lets use it.
  1156           #This does not allow for variable expansion as the default below does -mgt
  1157           if ($Config{'subject'}) {
  1158              print OUTFILE "Subject: $Config{'subject'}\n";
  1159           } else {
  1160              print OUTFILE "Subject: Logwatch for $Config{'hostname'} (${OStitle})\n";
  1161           }
```

# 対処方法

方法は下記３つが思いつきましたが、簡単な案２にしました。

1. logwatch改造する
2. メール送信をlogwatchに任せず自作する
3. Postfixでメール送信時にEnvelopeFromを書き換える

以下、案2の具体的な実現方法について。

logwatchをインストールすると、何も設定せずとも、毎日メール通知してくれるようになっています。
これは、/etc/cron.daily/0logwatch スクリプトによって実行されています。
このスクリプトでは、メール通知を行うオプションを指定してlogwatchを実行しています。

logwatchはオプションを指定しないと、標準出力にそのまま出力してきます。ですので、この内容をひろってメールすればよいだけです。
0logwatchスクリプトの中身を下記のように書き換えます。これでEnvelopeFromが書き換わります。

```
#!/bin/sh
echo -e "To: root\nSubject: Logwatch for [${HOSTNAME}] (Linux)\n\n`logwatch`" | sendmail -i -t -f 送信元メールアドレス
exit 0
```

# 背景

なぜEnvelopeFromを変更しないといけなくなったか、ですが、
メール中継サーバが、プライベートドメインのメールアドレスだと拒否するためです。
logwatchの標準だと、Fromアドレスが root@locahost.localdomain のようになってしまいます。
【SQL】GoogleのBigQuery - テーブル結合について(INNERJOIN)

#【SQL】GoogleのBigQuery - テーブル結合について(INNERJOIN)

BigQueryにおけるSQLについて勉強しています。

同じように覚えたての方、勉強中の方向けに
テーブルの結合について、少しつまづいたのでメモを残しておきます。
※Oralceに慣れすぎて同じような書き方をしてしまった。

Aというテーブルと、Bというテーブルの両方に欲しいデータがあり、
これらを結合して必要なデータだけ取り出すことを目指します。

**→　FROM文以降の結論から記載します。**

【まとめ】
・FROMで使用するテーブル（A)を宣言し、
・INNER JOIN で結合するテーブル(B)を宣言し、
・USING(フィールド名)で結合に使うフィールド名を指定します。

```

SELECT CastNo,hobby,class
--　表示する項目を指定

FROM
`dbname.table1`
-- メインで使用するテーブルを指定する

INNER JOIN `dbname.table2`
-- 結合するテーブルを指定する

USING(CastNo);
-- 結合に使うフィールド名を指定する

```

例では、両方のテーブルにある【CastNo】を結合するキーとしています。
特定のユーザーの、クラスと趣味を別々のテーブルから取得しています。


▼table1の内容

| CastNo       |       Name |    class    |
|:-----------------|------------------:|:------------------:|
| A000|              syana |        a        |
| A001           |            kino |       s       |
| A002            |              yamada |        aa        |
| A003               |                toma |         b         |
| A004             |             sagiri |       a       |
| A005          |           mikoto |      s       |


▼table2の内容

| CastNo       |       Hobby
|:-----------------|------------------:
| A000|              Magic |        a        |
| A001           |     Journey        |
| A002            |              Music |
| A003               |                Talk |
| A004             |             Illust |
| A005          |           Elk | 


▼クエリの結果

| CastNo       |       Hobby|    class    |
|:-----------------|------------------:|:------------------:|
| A000|              Magic |        a        |
| A001           |            Journey        |       s       |
| A002            |              Music |        aa        |
| A003               |                Talk |         b         |
| A004             |             Illust |       a       |
| A005          |           Elk |      s       |



何かご指摘があれば、ご連絡ください...
CNContactで電話番号を取得、比較する際の注意

#事象
```objective_c:
NSArray *ary = CNContact型.phoneNumbers
```

で対象連絡先の電話番号配列が取得できるが、

```objective_c:
if ([CNContact.phoneNumbers isEqualToArray:CNContact2.phoneNumbers])
```
などで同一連絡先かどうかを比較する際、同じ連絡先なのに別データとなってしまう。

#解決法

```objective_c:
- (NSArray *)getPhoneNumber:(CNContact *)contact{
    NSArray <CNLabeledValue<CNPhoneNumber *> *> *phoneNumbers = contact.phoneNumbers;
    NSMutableArray *phoneNumberArray = NSMutableArray.array;

    for(CNLabeledValue<CNPhoneNumber *> *phoneNumber in phoneNumbers){
        CNPhoneNumber *number = phoneNumber.value;
        [phoneNumberArray addObject:number.stringValue];
    }

    return phoneNumberArray;
}
```
一度対象のCNContactから電話番号のみを取得して配列に入れたものを対比すると問題なく動作する。

```objective_c
if ([[self getPhoneNumber:CNContact] isEqualToArray:[self getPhoneNumber:CNContact2]])
```

ちなみにメール一覧を取得するのはこう

```objective_c
- (NSArray *)getEmailAddress:(CNContact *)contact{
    NSArray<CNLabeledValue<NSString *> *>  *mailArr = contact.emailAddresses;
    NSMutableArray *addressArray = NSMutableArray.array;
    for(CNLabeledValue<CNLabeledValue *> *mailAddress in mailArr){
        CNLabeledValue *address = mailAddress.value;
        [addressArray addObject:address];
    }
    return addressArray;
}
```
GatsbyのHot reloadがMarkdownファイルをイジると死ぬ

# どうしたの

GatsbyにはHot reload機能があって、普通にReactを書いているだけなら大丈夫なんですが、gatsby-source-filesystemとかでMarkdownをレンダリングしたい時に、Markdownを編集するとhot reloadが死にます。

GraphQLクエリが非同期で発行されるので、データが入っていない状態が存在することが原因ぽいです。開発中にいちいちhot reloadが死ぬと煩わしくてしょうがないのでこれを解決します。

# 解決

[このIssue](https://github.com/gatsbyjs/gatsby/issues/11183)が参考になりました。

GraphQLのクエリを通してデータを引っ張ってくる部分がnullableであるという前提を置いてコードを書いていくと良さそうです。自分の場合はもともとこんな感じで書いていました。MDXを使っています。

```jsx:post-template.tsx

export default ({ data } : Props) => {
  const { body, excerpt, headings, frontmatter } = data.mdx;

  return (
    <>
      <SEO />
      <StyledPost
        body={body}
        headings={headings}
      />
    </>
  );
};
```

これだとdata.mdxにデータが入る前にレンダリングされると死ぬので、以下のように一行追加しました。

```jsx:post-template.tsx

export default ({ data } : Props) => {
+  if (!data.mdx) return <></>;
  const { body, excerpt, headings, frontmatter } = data.mdx;

  return (
    <>
      <SEO />
      <StyledPost
        body={body}
        headings={headings}
      />
    </>
  );
};

```

これでMarkdownファイルを編集しても、一瞬ホワイトアウトするくらいで、GraphQLクエリの実行結果が入ってきたら正常にレンダリングされるようになりました。


# まとめ

二回目ですが,
GraphQLで引っ張ってくるデータは非同期処理が基本になっているので、nullableであることを前提においておくとよいですね。👰
そもそも型定義からnullableにしておきましょう。
Nervesのnode_nameとnode_hostとcookieを設定した

そろそろNerves同士を接続したくなってきたので接続に必要な`node_name`と`node_host`と`cookie`を設定しました。

これは「[NervesのSSH環境を整えた　〜upload.shを使ってファームウェア更新も〜](https://qiita.com/nishiuchikazuma/items/6773d8f1d351d9355738)」の続編になります。


#環境

## ハードウェア
- Mac OSX
- NervesをRaspberryPi 3で稼働


## ネットワーク
- Mac OSX
  - 有線LAN→メンテナンス用、固定IPアドレス（192.168.88.1/24）

- ラズパイ
  - 有線LAN（eth0）→メンテナンス用、固定IPアドレス（192.168.88.2/24）
  - 無線LAN（wlan0）→インターネット接続用、DHCP（192.168.0.10-100/24から自動割当）


#ゴール（こうしたい）
Nervesを起動してログインした際、`node_name`と`node_host`と`cookie`が設定されている状態にしたい。

```bash:bash
$ ssh 192.168.88.2
```
↓

```elixir:iex
iex(nishiuchikazuma@192.168.0.11)> Node.self()
:"nishiuchikazuma@192.168.0.11"

iex(nishiuchikazuma@192.168.0.11)> Node.get_cookie()
:comecomeeverybody
```


# 前提
前提としてネットワークの設定ができていることとします。ネットワークの設定は「[Nervesのネットワーク環境を整えた](https://qiita.com/nishiuchikazuma/items/1341b32c4ce997fc362d)」を参考にしてください。


# やったこと
`config/target.exs`の`config :nerves_init_gadget`に`node_name`と`node_host`の設定をします。

```elixir:config/target.exs
（変更前）
config :nerves_init_gadget,
  ifname: "usb0",
  address_method: :dhcpd,
  mdns_domain: "nerves.local"
  node_name: node_name,
  node_host: :mdns_domain

↓

（変更後）
config :nerves_init_gadget,
  ifname: "wlan0",
  address_method: :dhcp,
  node_name: "nishiuchikazuma",
  node_host: :ip
```

`cookie`の設定は`mix.exs`の`def release`に設定します。`cookie`は`node_name`と`node_host`が設定されていないと有効にならないようです。無効の場合は`:nocookie`となります。

デフォルトの設定だと`cookie: "#{@app}_cookie"`となっているので`mix.exs`の上の方に設定されている`@app（プロジェクト名）`が展開されて`プロジェクト名_cookie`となります。

```elixir:mix.exs
  def release do
    [
      overwrite: true,
      cookie: "comecomeeverybody",    ←ここに設定を記載
      include_erts: &Nerves.Release.erts/0,
      steps: [&Nerves.Release.init/1, :assemble],
      strip_beams: Mix.env() == :prod
    ]
  end
```

ファームウェアをアップロードします。

```bash:bash
$ mix deps.get
$ mix firmware
$ ./upload.sh 192.168.88.2
```

確認します。

```bash:bash
$ ssh 192.168.88.2
```
↓

```elixir:iex
iex(nishiuchikazuma@192.168.0.11)> Node.self()
:"nishiuchikazuma@192.168.0.11"

iex(nishiuchikazuma@192.168.0.11)> Node.get_cookie()
:comecomeeverybody
```


#まとめ
`config/target.exs`に`node_name`と`node_host`を、`mix.exs`に`cookie`の設定をすることでNerves起動時に`node_name`と`node_host`と`cookie`を設定することができました。


#おまけ
NervesのIPアドレスとインタフェースを確認するコマンドは以下で`ifconfig`がオススメ。

```elixir:iex
iex> ifconfig
or
iex> Nerves.NetworkInterface.interfaces()
iex> Nerves.NetworkInterface.settings("eth0")
iex> Nerves.NetworkInterface.settings("wlan0")
or
iex> Nerves.NetworkInterface.interfaces() |> Enum.map(& Nerves.NetworkInterface.settings(&1))
```


#参考URL
[nerves-project/nerves_init_gadget - Configuration](https://github.com/nerves-project/nerves_init_gadget#configuration)
文章読み上げアプリをJavaScriptで作成してみました

#はじめに
最近文章読み上げアプリをJavaScriptで作成したので作成するうえで苦労した点などをまとめてみます。
アプリはHerokuにアップしてあるので、リンクへ飛んでいただければ試していただけます。
[読みあげ君へのリンクはこちら](https://enigmatic-mesa-03938.herokuapp.com/)
どうして"読みあげ君”を作ろうと思ったかというと、”初音ミク”に似たソフトで誰の声でも当てられたら面白いな、と感じたことがキッカケです。

読みあげ君の画像↓

![読み上げ君画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427892/9f639e97-880a-ebc6-f5ff-7225b95f082b.png)

#苦労した点について
1.テキストエリアへ打ち込まれた文字と音声を対応させる方法
2.音声を連続で再生する方法

#1.テキストエリアへ打ち込まれた文字と音声を対応させる方法
この解決策はとても単純で、連想配列を使用しました。
```
var voiceDictionary={1:'あ',2:'い',............71:'ぽ'};
```
といった風に1文字ずつキー値と対応させる方法です。
詳しいコードはリンク先で見ていただければ、と思いますが例えば、"あほか"と打ち込まれたとすると
あ→1、ほ→30、か→6といった風に連想配列を用いて数値へと変換します。
あとは、voiceDictionaryの音表通りに声のmp3ファイルを個別に配置していくことで、文字と音声の対応が出来ました。

#2.音声を連続で再生する方法
最初は、for文で(打ち込まれた文字数).lengthの回数を連続で鳴らそうかと思ったのですが、何度やってもfor文ではうまくいかなかったので
```
(オーディオインスタンスの変数名).addEventListener('ended',function(){
//(オーディオインスタンス).play();が終了した後動作させたいコードを入れる
}
```
という構文を追加することで解決できました。
この構文の前に、
```
(オーディオインスタンス).play();
```
というコードがあるのですが、そのplay();が終了したことを検知して、動作する構文となっています。

そして、その構文の中に音声を連続で再生するためのアルゴリズムを入れたら上手く解決できました。

#終わりに
つたない説明で申し訳ありません。
Qiitaへの記事を書きながら、自分の説明力不足を痛感しました・・・。
備忘：クラウドの利用拡大で切迫してきたネットワークを見直したい！（IPv6通信について整理）

# はじめに

社内で利用している基幹システム、ファイルサーバ、メール、グループウェア、SNSなど、
多様なサービスをネットワークを介して利用するケースが非常に多くなってきており、
ネットワークに求められる通信／帯域がどんどん高くなってきている中、
いまだIPv4のネットワークを利用し続けていましたが、いい加減限界を感じてきた今日この頃です。

かといって専用線を引いてまでの費用はかけられない。。
そこで今更かもしれませんが、早くなると評判のIPv6通信を検討したい思い、
改めて整理してみた結果を備忘として投稿します。
# IPv4はなぜ遅く、IPv6はなぜ早い？
一昔前までネットワーク上には「IPv4」しかなく、全ての通信は「IPv4」のネットワーク上で行ってました。
そして近年になって「将来的にIPv4ネットワークが枯渇する」と言われるようになり登場したのが「IPv6」です。
しかし今だWEBサイトや利用者はIPv4を利用し続けているので、IPv4ネットワークが混雑してる状況です。

またIPv6の登場により、IPアドレス空間が大幅に広がったことはもちろんですが、
通信方式も従来の「PPPoE」に加えて「IPoE」にという新たな方式が利用できるようになりました。

この「通信の混雑状況」と「通信方式」が影響して以下図のような状況になっていたそうです。
![canstockphoto56154991.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568492/2f325b33-cba9-76e0-38b4-9e2b5ac1b68e.jpeg)
つまりIPv6は混雑が少なく、通信設備も大容量で、ボトルネックが少ないので、IPv4よりも早い。
# 「IPv6 IPoE」＋「IPv4 over IPv6」
「IPv6」が早いというのは理解したが、世の中のほとんどのWEBサイトは「IPv4」を利用している状況の中、
IPv6でも問題なく通信できるのかというのが心配になります。
IPoE方式はIPv6のみに対応しているため、アクセス先のWebサイトやWebサービスも本来ならIPv6に対応している
必要があります。
これを解決するために登場したのが、「IPv4 over IPv6」です。
「IPv4 over IPv6」では、ブロードバンドルーターでIPv4形式のパケット（情報のかたまり）を
IPv6形式に変換して通信を行い、「IPv6に見せかけたIPv4」のパケットは、IPv6通信網を抜け、
通信先のウェブサービスに到達する直前で、元のIPv4形式に再度変換されます。
IPv6の仮想のトンネルを抜けてIPv4のパケットを通信することが可能となるのです。
![canstockphoto56154990.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568492/e052509c-904a-fc57-f243-6998fbe4f442.jpeg)
参照：https://www.ntt.com/business/services/network/internet-connect/ocn-business/ftth/know.html

# IPv4とIPv6の速度を比較
実際導入したらどのくらい早くなるのでしょうか。
地域で異なりますが、最寄りの地域で計測サイトで確認した結果が以下です。

IPv4上り速度：27.75Mbps
IPv6上り速度：236.96Mbps
IPv4下り速度：32.88Mbps
IPv6下り速度：254.32Mbps
参考：https://www.speed-visualizer.jp

かなり違います。早いとこ検討を進めたほうがよさそうです。

# IPv6サービス紹介
インターネット：OCN光 IPoEサービス
https://www.ntt.com/business/services/network/internet-connect/ocn-business/ftth/ipoe.html

社内NW（閉域網）：フレッツ・VPN プライオ
https://business.ntt-east.co.jp/service/vpnprio/
https://flets-w.com/biz/vpnprio/

##最後に、共に働くWebエンジニアを募集しています!
不動産SHOPナカジツでは自社サービスを作っていく仲間を募集しています。
詳しくは[Wantedly](https://www.wantedly.com/projects/134741)からお問い合わせください。
matplotlibの点の大きさについて


Pythonのmatplotlibは大変便利なのでいつもお世話になっています。とても足を向けて寝られませんが、今日は「点」の大きさについてちょっと試してみたいと思います。

```python
%matplotlib inline
import matplotlib.pyplot as plt
```

# 点を描く


```python
plt.scatter(0, 0, c='k')
```


![output_1_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/80b0c86b-b3d9-c417-1c4c-3385f893a6b8.png)


# 大きい点を描く


```python
plt.scatter(0, 0, c='k', s=1000)
```



![output_2_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/c4c88b7e-9960-f212-4c39-b841b010faae.png)


# 点を増やす

ここで、点の大きさが少し変わったように見えますね。原点にある点の大きさは変えていないはずなんですが、この大きさは、あくまで表示サイズの大きさであって、座標の大きさとは対応していないようです。

```python
plt.scatter(0, 0, c='k', s=1000)
plt.scatter(0.1, 0.1, c='k', s=700)
plt.scatter(-0.1, 0.1, c='k', s=700)
```


![output_3_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/401f6e8e-e022-4ea3-2327-2c3c6156c33c.png)


# 画像の表示域を変える

なので、画像を表示する座標域を変えると、全く違って見えます。水分子みたいになってしまいました。

```python
plt.xlim([-1, 1])
plt.ylim([-1, 1])
plt.scatter(0, 0, c='k', s=1000)
plt.scatter(0.1, 0.1, c='k', s=700)
plt.scatter(-0.1, 0.1, c='k', s=700)
```


![output_4_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/5d5e2792-e040-049e-6763-32700c51fbee.png)


# 画像の縦横比を変える

画像の縦横比を変えても同様に、形が変わって見えます。ミッ...水分子...のように見えます。

```python
plt.figure(figsize=(8,8))
plt.xlim([-1, 1])
plt.ylim([-1, 1])
plt.scatter(0, 0, c='k', s=1000)
plt.scatter(0.1, 0.1, c='k', s=700)
plt.scatter(-0.1, 0.1, c='k', s=700)
```


![output_5_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/6d1592bf-0761-5f59-a01c-3e6a9ad4e225.png)


# 画像のサイズを変える

画像のサイズを変えても同様に、形が変わって見えます。ミッ...水分子...のように見えます。


```python
plt.figure(figsize=(6,6))
plt.xlim([-1, 1])
plt.ylim([-1, 1])
plt.scatter(0, 0, c='k', s=1000)
plt.scatter(0.1, 0.1, c='k', s=700)
plt.scatter(-0.1, 0.1, c='k', s=700)
```


![output_6_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/67fc4d0a-dd87-1240-31e1-e491f63625e4.png)


# 複製をたくさん作る

同じものを水平移動して、複製をたくさん描画してみましょう。あれ？ 耳...じゃなくて...水素原子？みたいなのが見えなくなってしまいました。

```python
plt.figure(figsize=(6,6))
plt.xlim([-10, 10])
plt.ylim([-10, 10])
for x in [-5, 0, 5]:
    for y in [-5, 0, 5]:
        plt.scatter(0 + x, 0 + y, c='k', s=1200)
        plt.scatter(0.1 + x, 0.1 + y, c='k', s=700)
        plt.scatter(-0.1 + x, 0.1 + y, c='k', s=700)
plt.show()
```

![output_7_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/60799c8f-f4db-074a-7615-41715f535158.png)

ミッ...水分子みたいな形に戻すためには、位置関係を見直す必要があります。

```python
plt.figure(figsize=(6,6))
plt.xlim([-10, 10])
plt.ylim([-10, 10])
for x in [-5, 0, 5]:
    for y in [-5, 0, 5]:
        plt.scatter(0 + x, 0 + y, c='k', s=1000)
        plt.scatter(1 + x, 1 + y, c='k', s=700)
        plt.scatter(-1 + x, 1 + y, c='k', s=700)
plt.show()
```

![output_8_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211162/5930532d-d3ba-9540-baef-e0587d51bf84.png)

# まとめ

matplotlib は便利ですが、点の大きさをいい感じにするのは、ちょっと面倒です。
【Nuxt.js】環境変数の設定とswagger mockの設定メモ

## 環境変数の設定
- 環境ごとに環境変数を分ける
- APP配下に以下の3つのファイルを作成する
    - 開発環境：development
    - 検証環境：staging
    - 本番環境：production

- 開発環境

```javascript:env.development.js
module.exports = {
  // mockを使って開発を進めるとき ポートはswagger用リポジトリのdocker-compose.yamlで設定
  apiBaseUrl: "http://mock:8080/"

  // apiの作成が完了したら ポートはapi用リポジトリのdocker-compose.yamlで設定
  apiBaseUrl: "http://app:1323/"
}
```
※ swagger用とapi用のdocker-compose.yamlを一部抜粋

```yml:swagger/docker-compose.yaml
services:
  mock:
    image: swaggermock/swagger-mock
    ports:
      - 0.0.0.0:8081:8080
    volumes:
      - ./swagger.yml:/openapi/swagger.yml
    environment: |
      SWAGGER_MOCK_SPECIFICATION_URL: /openapi/swagger.yml
    networks:
      - internal
      - external
```
```yml:api/docker-compose.yaml
services:
  app:
    build: // 省略
    volumes: // 省略
    command: // 省略
    ports:
      - 1323:1323
    environment:
      - PORT=1323
      - DB_HOST=db
      - DB_USER=root
      - DB_PASSWORD=
      - DB_PORT=xxxx
      - DB_DATABASE=nuxt-app
```
- 検証環境

```javascript:env.staging.js
module.exports = {
  apiBaseUrl: "http://stg-api.nuxt-app.com/"
}
```
- 本番環境

```javascript:env.production.js
module.exports = {
  apiBaseUrl: "http://api.nuxt-app.com/"
}
```

## APIの呼び出し
- `apiBaseUrl`以下のAPIパスを設定する

```vuejs:index.vue
<script>
const url = process.env.apiBaseUrl + "users/index"

export default {
  async asyncData() {
    const result = await axios.get(url)
    return {
      users: result.data
    }
  }
</script>
```

## package.jsonの設定

```json:package.json
{
  "name": "nuxt-app",
  "version": "1.0.0",
  "description": "nuxt-app project",
  "author": "名前",
  "private": true,
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "build:stg": "cross-env NODE_ENV=\"staging\" nuxt build",
    "build:prod": "cross-env NODE_ENV=\"production\" nuxt build",
    "start": "nuxt start",
    "start:stg": "cross-env NODE_ENV=\"staging\" nuxt start",
    "start:prod": "cross-env NODE_ENV=\"production\" nuxt start",
    "generate": "nuxt generate",
    "test": "jest",
    "prettier": "prettier --write ./{components,layouts,middleware,pages,plugins,store,test}/**/*.{js,vue}"
  },

  // 省略

}
```

## nuxt.config.jsの設定

```javascript:nuxt.config.js
const environment = process.env.NODE_ENV
const envSet = require(`./env.${environment}.js`)

export default {
  env: envSet,

  // 省略

}
```
## 参照
- [dotenvとcross-envで環境変数を設定して開発環境の処理を切り替える](https://www.tam-tam.co.jp/tipsnote/program/post17589.html)
- [Nuxtで環境設定ごとにファイル分ける](https://himariweb.com/%E6%9C%AA%E5%88%86%E9%A1%9E/use-cross-env/)
- [【Nuxt.js】nuxt.config.jsで.envで定義した環境変数を取得して使用する](https://public-constructor.com/nuxt-config-js-dotenv/#toc3)
Ubuntu18.04にPython3とOpenCV環境を構築する

# モチベーション
ラズパイとカメラでPythonを使って顔認識による顧客分析をやってみようと思い、VMでテスト環境を構築する。今回のゴールは、MacにUbuntuの仮想環境を作り、Ubuntu上でPython3とOpenCVを動作させるまでとする。

# 環境
- Ubuntu16.04が動作することが前提
- Python 3.6.9を導入
- OpenCV 4.2.0を導入

# OpenCVと依存するライブラリのインストール
gitコマンドを使って、ソースコードを取得しています。

```
$ sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
$ sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libdc1394-22-dev
```

#ソースコードの入手
gitコマンドを使って、ソースコードを取得しています。

```
$ git clone https://github.com/opencv/opencv.git
$ git clone https://github.com/opencv/opencv_contrib.git
```

wgetコマンドでダウンロードする場合はunzipコマンドでzipファイルを解凍してください。

```
$ wget -O opencv.zip https://github.com/opencv/opencv/archive/4.2.0.zip
$ wget -O opencv_contrib.zip https://github.com/opencv/opencv_contrib/archive/master.zip

$ unzip opencv.zip
$ unzip opencv_contrib
```
ソースが保存されたディレクトリを確認します。

# OpenCVのコンパイル・ビルド
OpenCVをビルドします。
cmakeのとき、-D OPENCV_EXTRA_MODULES_PATH=../../opencv_contrib/modules をつけることでcontribの方もまとめてビルドされます。

```
$ cd ~/opencv-4.2.0
$ mkdir build
$ cd build
$ cmake -D CMAKE_BUILD_TYPE=RELEASE \
    -D CMAKE_INSTALL_PREFIX=/usr/local \
    -D INSTALL_PYTHON_EXAMPLES=ON \
    -D INSTALL_C_EXAMPLES=OFF \
    -D OPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules \
    -D BUILD_EXAMPLES=ON ..
```

OpenCVをコンパイルします。

```
$ make -j4

[100%] Build target opencv_python3 　　//この表示が出ればコンパイル成功
```
私のMac Book ProのVM環境では、１時間ほどコンパイル・ビルドに時間がかかりました。
無事、コンパイル・ビルドに成功したら、OpenCVをインストールします。

```
$ sudo make install
$ sudo ldconfig
```

OpenCVのバージョンを確認します。

```
$ opencv_version
4.2.0
```

# Python3と関連モジュールのインストール
まずは、Pythonパッケージを管理するpipをインストールします。次のモジュール（numpy, pandas, matplotlib, sklearn）が使えるようにします。

```
$ sudo install pip3
$ pip3 install numpy pandas matplotlib sklearn
```

# 動作確認
pythonコンソールに入り、各種モジュールがimportできるかを確認する。
エラーが出なければ、無事モジュールがインストールされている。念のためopnecvのバージョンを確認する。

```
$ python3
>>>import numpy
>>>import pandas
>>>import sklearn
>>>import matplotlib
>>>import cv2       //これがopencvのライブラリ
>>>cv2.__version__  //opencvのバージョン確認
'4.2.0'
>>>
```

これで仮想マシンのUbuntuでPython3とOpenCVが利用できるようになりました。ディープラーニングをやりたい方はディープラーニング用のライブラリ（tensorflow, kerasなど）をpip3でインストールしてあげると利用できるはずです。それでは、次回、OpenCVを使った顔認識サンプルコードを実行してみたいと思います。

### 参考サイト
・こちら<a href="https://avinton.com/academy/opencv3-4-3-python3-6-ubuntu18-04-install">Python3.6とOpenCVのインストール (Ubuntu18.04LTS)</a>の記事がとても参考になりました。
・こちら<a href="https://qiita.com/tetsu_koba/items/7487fc5fa258f683122b">opencvをソースからビルドする</a>の記事も参考になりました。
・OpenCV公式サイトは<a href=https://opencv.org/>こちら</a>です。
今日のpython error: invalid keyword argument for this function

組み合わせ爆発の凄さ
https://qiita.com/kaizen_nagoya/items/f309b0c2bb015bbc71c3

で、

graphillionを使ってみた
https://qiita.com/cabernet_rock/items/50f955afc16287244154

をファイルにした。

実行しても何も出ない。

printを加えた。

```python:gra.py
# https://qiita.com/cabernet_rock/items/50f955afc16287244154
# 必要なモジュールのインポート
from graphillion import GraphSet
import graphillion.tutorial as tl
import time              # 計算時間を調べる。
# グリッドのサイズを指定
universe = tl.grid(2, 2)
GraphSet.set_universe(universe)
tl.draw(universe)
start = 1 # スタート位置
goal = 9 # ゴールの位置
paths = GraphSet.paths(start, goal)
print (len(paths))
#
key = 4        # 1箇所目
treasure = 2   # 2箇所目
paths_to_key = GraphSet.paths(start, key).excluding(treasure)
treasure_paths = paths.including(paths_to_key).including(treasure)
print (len(treasure_paths))
#
universe = tl.grid(8, 8) # 9×9のグリッド
GraphSet.set_universe(universe)
start = 1
goal = 81
s = time.time()          # 計算開始時刻
print  (paths = GraphSet.paths(start, goal))
time.time() - s # 計算時間
print (len(paths))
```


```shell-session:docker/ubuntu
# python3 gra.py
12
2
Traceback (most recent call last):
  File "gra.py", line 26, in <module>
    print  (paths = GraphSet.paths(start, goal))
TypeError: 'paths' is an invalid keyword argument for this function
```

print  (paths = GraphSet.paths(start, goal))

を

paths = GraphSet.paths(start, goal)
print  (paths)

に変更。

### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
pyautoguiで日本語入力

#半角/全角キーを使う

```python:jatype.py

import pyautogui as pag

pag.hotkey('hanja')
pag.typewrite('tesuto')
```

#コピペする
pyperclipを使って入力したい日本語をクリップボードに保存して、ctrl+vでコピペ。

```python:jatype.py

import pyautogui as pag
import pyperclip

pyperclip.copy("テスト、てすと")
pag.hotkey('ctrl','v')
```
【PHP】ファイル入出力、dirnameとbasename結合時の注意点｜'/'を忘れずに！

web系エンジニアを目指し、MENTAを利用し、PHPを学習している初学者です。
日々学習していることの忘備録、モチベ維持、ちゃんとやってることの証明！で、投稿していきます。
（今回の内容もなんてことないのですが、一瞬「？？」となったので、メモ）
#対象者
PHPを学びはじめた、初学者
#内容
ファイル入出力設定時便利な、dirnameとbasename結合時の注意点
#動作環境
PHP 7.1.32
##基本のおさらい
###ファイル入出力とは
プログラムに書いた通り、
・ファイルを読み込んだり
・ファイルに書き込んだり
・ディレクトリを作成したり
することが出来ます。
GUIでしかパソコンを触ってこなかった私からすると、ちょっと感動！

```php5:ファイル入出力のイメージ
//対象のファイル
$filepath = './a/b/c/hoge.csv';

//ファイルを読み込む
１、開いて
$hondle_read = fopen($filepath, 'r');

２、読み込んで
while($read[] = fgets($handle_read))

３、閉じる
fclose($handle);

//ファイルへ書き込む
１、開いて
$handle_write = fopen($filepath, 'w');

２、書き込んで
$write = 'ファイルに書き込む内容';
fwrite($handle_write, $write);

３、閉じる
fclose($handle_write);
```
####このコードは問題有り
一定の条件
`$filepath`のディレクトリ+ファイルが実在していれば、読み込み
`$filepath`のディレクトリがあれば、書き込み
が実現しますが、本来は
・ディレクトリがあるか検証
・ファイルがあるか検証
・ファイル内の改行を意識
などが必要です。
公式リファレンスがわかりやすいので、基礎を学びたい方はご参照ください。
[PHPマニュアル fgets](https://www.php.net/manual/ja/function.fgets.php)

#これが本題！
メンターさんからの課題を解く中、
**$filepathからディレクトリ部分・ファイル部分を抜き出す関数**
`dirname,basename`
を教えてもらい、早速使ってみるも思い通りに動かない！

今回書きたいのは、
**dirnameとbasename結合時の注意点**です。

```php5:dirname,basenameとは
//対象のファイル
$filepath = './a/b/c/hoge.csv';

//dirname
$directory = dirname($filepath);
echo $directory; // ./a/b/c

//basename
$filename = basename($filepath);
echo $filename;  // hoge.csv
```
このように、きれいに**$filepathからディレクトリ部分・ファイル部分を抜き出してくれる**んです！素晴らしい。

でもよくみて下さい。
**ディレクトリ「c」と、ファイル「hoge.csv」の間にあった「/」がなくなってる！**
なので、これらを結合する時は十分に気を付けて下さいね。

「・・・だから？」
「どう気を付ければ？」
「どんな場面で、その必要が出てくるの？」
そんな初学者の方向けに、実例を出して終了します。
#実例
「連番のファイル名にして出力せよ！」というような課題で、意気揚々と`dirname,basename`を使用するも、変なファイル名になってしまう・・

```php5:失敗例と解決策
上記の続き
//作成したいファイル
'./a/b/c/hoge_1.csv'
'./a/b/c/hoge_2.csv'
'./a/b/c/hoge_3.csv'

失敗例
//ファイル名にfor文で番号を付加して、ディレクトリと結合すれば、新しいファイルパスの完成だ！
for($i = 1; $i <=3; $i++) {
    $filepath[$i] = $directory . $filename . '_' . $i;
}

//$filepath[1]〜[3]を使ってファイル書き出し。出来上がったのは・・
'./a/b/choge_1.csv'
'./a/b/choge_2.csv'
'./a/b/choge_3.csv'

解決策
for($i = 1; $i <=3; $i++) {
    $filepath[$i] = $directory . '/' .$filename . '_' .$i;
}

//$filepath[1]〜[3]を使ってファイル書き出し
'./a/b/c/hoge_1.csv'
'./a/b/c/hoge_2.csv'
'./a/b/c/hoge_3.csv'
```
なんてことないですね！
[TIPS] Power AutomateでHTTPを使わずにHTMLを取得する

# Power AutomateのHTTPアクションは有償です

残念ながら、Power Automateで私がよくやる、スクレイピングに利用しているHTTPのアクションは有償プラン/コミュニティプランでのみ利用可能です。
例えば前回の投稿でもHTTPアクションでPrime Videoの作品ページをGETしています。[Prime Videoの更新通知を Power Automateでつくる](https://qiita.com/h-nagao/items/fdbfcf4a7dae6373a224)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/67c40edc-1278-2c21-19e9-c2e3f42c4558.png)

残念ですが、これは仕方ない。何か回避方法はないものか。

## OneDriveのUpload file from URLが使える？

そう、OneDrive/OneDrive for Businessコネクターには、URLを指定してファイルをアップロードするというアクションがあります。
これはたとえば画像ファイルをWebから取得して保存するような場合に利用しますが、中でやっていることはHTTPのGETなので、プレミアムであるHTTPアクションの代用として、単純なGETに限れば使えるかもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/3ef14784-deaf-eb99-e9a9-88163e3c86c0.png)

# OneDrive - Upload file from URLでHTMLを取得する

実際に試してみます。
適当なURLでHTMLをGETしてみます。あとでこの内容を分割したり文字列置換するので、後続処理でGet file content using pathをしてみます。

**どちらも成功！** これで後続処理でHTMLの解析ができます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/3eb08031-c6c7-41c7-6a9c-1f184ce1535e.png)

使うときは
```split(body('Get_file_content_using_path'),'xxx')```
のように 文字列を分割したり、置換したりできます。

# まとめ
本当ならAPIがあればそれをたたいたり、表示する際にやり取りしているjsonをデータとして利用するのがよいのですが、そうもいかない場合、HTTPでGETして、得られたHTMLを解析というのはよくあるパターンかなと思います。
そんな時、Power Automateでは、リクエストの内容によっては、OneDrive (for Business) のURLから取得のアクションで代用できるかもしれません。ぜひ試してみてください！
ESXi 6.x へ Windows Server 2016 をインストールする際に unsuccessful EFI Network と表示され進まない

# 事象
ESXi 6.x へ Windows Server 2016 をインストールしようとして CD-ROM ドライブに ISO ファイルをセットして起動したら、
コンソール上へ **unsuccessful EFI Network** と表示されてブートしない。

# 対処
1. ESCキーを押して Boot Manager を起動する
2. *EFI VMware Virtual SATA CDROM Drive* を選択し、`Enter`キー押下
3. *Press any Key to boot From CD or DVD...* が表示されたら何か適当なキーを押下

# 原因
UFEI でのブートができていない？
`.vmx`の`firmware`を`efi`へ変更すると通常通り起動するようだが、面倒なため直接 Boot Manager を起動することにした。
(特に今のところ問題は起きていない)
[Rails]DB操作を行うコマンドまとめ

### はじめに
DB操作を行うコマンドというのは`rails db:migrate`などのことです。
コマンドは数が多く、名前から想像しにくい(自分だけ？)ものもあったりするため、備忘録としてまとめておこうかと思います。

■参考サイト(公式GitHub)
https://github.com/rails/rails/blob/v5.2.0/activerecord/lib/active_record/railties/databases.rake

### 環境
- Rails 5.2.0

### コマンド一覧
|コマンド            |説明               |備考               |
|:------------------|:------------------|:------------------|
|rails db:create    |データベースを作成   |                   |
|rails db:drop      |データベースを削除   |                   |
|rails db:migrate   |マイグレートを実行   |                   |
|rails db:migrate:reset|データベースを作成し直した後にマイグレートを実行||
|rails db:reset     |DB再作成後、マイグレートを実行し、seedファイルからデータ作成|db:drop後にdb:setupを行っている。|
|rails db:setup     |DB作成後、マイグレートを実行し、seedファイルからデータ作成|マイグレーションファイルは使用せず、schema.rbからマイグレートを行う|

今はスカスカですが、少しずつ充実させていく予定です。
※表の見栄えもあまり良くないので、今後少しずつ整えていきます。。。
今日のpython error:ModuleNotFoundError: No module named 

graphillionを使ってみた
https://qiita.com/cabernet_rock/items/50f955afc16287244154

組み合わせ爆発の凄さ
https://qiita.com/kaizen_nagoya/items/f309b0c2bb015bbc71c3


dockerで実行しようとした。

```
# python3 gra.py
Traceback (most recent call last):
  File "gra.py", line 7, in <module>
    universe = tl.grid(2, 2)
  File "/usr/local/lib/python3.6/dist-packages/graphillion/tutorial.py", line 28, in grid
    import networkx as nx
ModuleNotFoundError: No module named 'networkx'
```

docker 作る時に、

```
# pip3 install networkx
```

とすべきところを

```
# pip3 install network
```

としていた。１文字違いはまぎらわしい。
# 文書履歴(document history)
ver. 0.01 初稿 20200121
ver. 0.04 URL追記　20230302

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
git branchして、特定のbranch名のファイルをクローンしてくる

git初心者の私がudemyのビデオ講座で学習しながら、gitのコマンドでつまずいた話です。

udemy でreactを学びながら、作った物をgitで管理していました。講義を一周してreactのreduxの部分だけを復習したいときにredux学習前のファイルをgit cloneしてくるときにつまずいたのでメモ。

#方法
まずgit cloneしてきたい人もしくは自分ののgithubからコピーしたいリポジトリ（ファイル）を選択する。
clone or download からURLをコピーする。

![スクリーンショット 2020-01-21 13.06.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498892/608029da-a458-296e-e9c3-34a51911ac5f.png)


ターミナルに行き

```
git clone　コピーしたURL
```


```
cd　URLから作られたファイル名
```

```
git checkout -a 
```


でファイルのある全てのブランチが確認できる

```
git checkout 使いたいbranch名
```


でそのブランチ名がある段階でのファイル状態から作業できるようになる。
iOSアプリ、Adhoc配信でもプッシュ通知は飛ばせます！飛ばないときのトラブルシューティング

## はじめに

今回、社内用にAdhocでプッシュ通知を伴うアプリをリリースしました。
結構証明書周りや署名、ビルド方法などが難しく、「Adhocではできない」と書かれたブログ記事も多くあったため、
ここに確認すると幸せになれる項目を書きます。
結論としては、Adhocでもプッシュ通知飛ばせます。
順不同に並べるので、不安なところを参考にしていただけたら幸いです。

## 前提

- サーバサイドからFCMへプッシュを投げて、iOSで通知を受け取る流れ
- すでにWebのプッシュ通知は実装済みで、サーバサイド→FCMへの連携はできている状態
- xcode Version 11.2.1
- enterprise apple developer program ではなく、apple developer program に登録しています

## ビルドする　target の内容をチェック

- TARGETS の Signing & Capabilities タブで、Background Modes の Remote notifications にチェックがついていること
- Push Notifications が選択されていること
- TARGETS の Build Settings タブで、各種設定ファイルが本番用になっていること

## プロビジョニングファイルのチェック

### ipaファイルを生成

1. Window > Organizer > Atchices で対象のアプリを選択し、「Distribute App」
2. 「Ad Hoc」を選択、rebuild from bitcode
2. 「Code Signing Identity」で、公開用の「Production」プロビジョニングファイルを選択
3. 
※Adhoc配信でもここで公開用のプロダクションを選択していること

### ipaのzipを展開し、署名状況を確認

```
$ unzip xxxxx.ipa
$ codesign -d --entitlements :~ Payload/xxxxx.app
```

ここで表示される環境がdevelopmentではなく、productionになっていればOK

## ビルドの種類を確認

Product > Scheme > Edit Scheme で、Runメニューの build Configuration が Release になっていればOK 

## SSL証明書を確認

Macのキーチェーンアクセス > 自分の証明書
本番では「Apple Push Services」という証明書をサーバ側で設定する必要があります。
private keyではなく、public keyから書き出す必要があるので注意。
xcode上の署名には、「iphone Distribution」の証明書を設定します。（Developerになっていないことを確認）

## デバイストークンが正しいかどうか

```swift

// APNsへプッシュ通知の利用の登録が完了すると呼び出される関数です
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        let tokenBytes = deviceToken.map { (byte: UInt8) in String(format: "%02.2hhx", byte) }
        NSLog("Device token: \(tokenBytes.joined())")
}
```
上記のようにトークンを取得。
これで生のデバイストークンが取れるので、このトークンを元にProductでプッシュが飛ばせるかをチェック。

私はこれを使わせていただきました。
https://github.com/noodlewerk/NWPusher
「Push Certificate」→[bundleid]（sandbox|Production） を選択
Adhocなので 「Should use sandbox environment」のチェックを外し、「Push」を押下
→これで通知が飛んだらサーバー（今回はFCM）への設定に問題がありそう

## GoogleService-Info.plist が正しいかチェック

- 本番でプロジェクトを分けている場合、読み込んである内容が本番環境のプロジェクトであることをチェック

## FCMに設定しているAPNs証明書をチェック

- FCMの管理画面 > 設定 > クラウドメッセージング > APNs 証明書 ※APNsに認証キーを使っている場合は本番のキーになっているかを確認
- 開発環境と本番環境でCSRが同じでないこと


## 参考
https://developer.apple.com/documentation/usernotifications/registering_your_app_with_apns
https://firebase.google.com/docs/cloud-messaging/ios/client?hl=ja
https://www.amazon.co.jp/iPhone-Android-%E3%80%8C%E9%80%9A%E7%9F%A5%E6%A9%9F%E8%83%BD%E3%80%8D%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%BE%B9%E5%BA%95%E3%82%AC%E3%82%A4%E3%83%89-%E7%A5%9E%E5%8E%9F-%E5%81%A5%E4%B8%80-ebook/dp/B00H539T4S
https://qiita.com/tyshgc/items/1e4ba87def4dbe94cd9d
SteamVR導入後に設定ポップアップがしつこく出るときの対処法メモ

（いつも調べなおすのが大変なのでメモ書き）

#何度許してもでてくるこいつがうざい！
![Steam VR popup.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500311/ecafa3e9-4c8e-3c9e-0c6d-37f84a9a77de.png)
いろんな記事で「“Accept All”を押して進んでください。」ってあって、
その通りにするんだけど、事あるごとにこいつがでてきて正直うざい。

ということで、このポップアップを消す方法のメモ書き。

①Asset⇒SteamVR⇒Editorの順に進み
　SteamVR_UnitySettingsWindow.csを開く。

②41行目の
```const bool recommended_UnitySprashScreen = false;
```　
falseをtrueに書き換える。
![VRメモ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500311/1376255d-4d86-eca6-2fc7-7bba63e9e1a0.png)
（参考スクリーンショット）

これでもうしつこく許可を乞われることはなくなるはず。
[参考ページ（英語）：https://stackoverflow.com/questions/41418481/in-unity-how-to-stop-popup-for-show-unity-splashscreen](https://stackoverflow.com/questions/41418481/in-unity-how-to-stop-popup-for-show-unity-splashscreen)