OmniAICreator/Qiita-1.07M huggingface dataset:
マルチエージェントとAIについて

#はじめに(まえがき)

こんにちは、お久しぶりです。
また以前と同じようなテーマの記事になってしまい大変恐縮です。
やはり思い付きで「コレは」と思い立ったので(懲りずに)記事を書きました。
よかったら最後まで読んでみてください。どうぞ、よろしくお願いします。
今回は以前書いた記事(エージェント指向等)に関連する記事ということで、
マルチエージェントとAIの関連性について勉強のまとめに書いてみました。


#本題(本文)

マルチエージェントシステムとは、簡単に言えば、あるコンピューターシステムの中で、多数のエージェントが競争あるいは協力をすることで、そのシステムの目的を達成するものです。たとえば、この記事では、イラストを作成するアプリケーションを例にとって簡単に説明してみます。

ここで、アプリケーションのユーザーは、人物・動物であったり、あるいは機械・建物などの絵を描きたいと思います。ここで、人物・動物であったり、あるいは機械・建物を自動的あるいは自律的に描くプログラムが用意されているとします。これがエージェントです。エージェントは複数あって、個々のエージェントが様々に対象物を描きます。つまりイラストを作成するアプリケーションに、複数のエージェントがバインドされている(いうなれば、一つのアプリケーションにエージェント達がぶらさがっている)のです。※実際は、同じ対象物を描くにしても、複数の同じ目的を持った(同じ対象物を描くことのできる)エージェントがシステム(この場合イラストを作成するためのアプリケーション)の内部で競争あるいは協力をすることにより、ユーザーの目的を達成するべく作業を補助してくれます。

つまり、ユーザーが描きたいものに合ったエージェントがアプリケーションから呼び出される格好で実行され、ユーザーの目的を達成するべく作業を補助してくれるということです。ここで、イラストを作成するアプリケーションは、ユーザーから明確になにを描きたいかという指示や要求を受けて目的に合ったエージェントを呼び出すこともできれば、ユーザーが思い立って描きはじめたものを自動的に分析することで、ユーザーがなにを描こうとしているのかを推量や推定をしてエージェントを呼び出すこともできることとします。これにより、ユーザーは煩雑な作業の効率を改善できたり、人間が本来持っている創造性をかきたてることなど新たなエクスペリエンスを提供できます。

最後に、マルチエージェントシステムの内部で動作する個々のエージェントは、仕組みとしてはAIで実現されています。AIといっても各種様々なものが世の中にはありますが、私個人が想定しているものは「強化学習」もしくは「深層強化学習」です。これは、エージェントが外部の環境あるいは自身の置かれている状況を認識する仕組みと、エージェント自身の取る行動を評価する仕組みを併せたもののことですが、おおまかにいってこの二つがAIというものを実現してくれます(AIを実現する技術には、他にも様々な多くのものがありますので、誤解のないよう)。

つまり、エージェントは、私の言っている「サブジェクト」から状況の通知を受けて、その上で自身の得る報酬が最大になる行動を常に選択し続けるということによって、ユーザーの目的達成に寄与するということです。


#おわりに(あとがき)

今回もうまく記事としてまとまっていればよいのですが、なにぶん私個人は大変に勉強が不足しており、なおかつ記事の編集能力が乏しいものですから、記事としての高いクオリティは実現できていないとは思いますが「こんな記事もあるんだ」程度に、この記事を読んで、その存在を知っていただけたら幸いです。それではまた。
M5StickCでGPS座標をInfluxDBに記録する

##GPS座標を記録する
RTKとかでネット必須な環境で、トラクターとかの作業機を使ってると作業記録を付けたくなるので作ってみました。
まだ表示周りは手を付けてないので、メモ代わり。

NMEAの入力は、ソースの中のSerial2.begin(115200,SERIAL_8N1,33,32);
で指定しています。

##Influxdbの設定でUDPを有効にする

```/etc/influxdb/influxdb.conf 
[[udp]]
  # enabled = false
   enabled = true
   bind-address = ":8089"
   database = "test1"
```

influxdbを再起動

```bash
sudo service influxdb restart
```

###データベースを作る

```influx
$ influx
CREATE DATABASE test1
quit
```

##ソース
必要なライブラリ
TinyGPS++
http://arduiniana.org/libraries/tinygpsplus/


<details>
<summary>M5StickC_NMEA_InfluxDB</summary>
<div>

```gps_influx_ds18b20.ino

#include <TinyGPS++.h>
#include <WiFi.h>
#include <WiFiUDP.h>
char ssid[] = "SSID";
const char* password = "password";
// the IP address of your InfluxDB host
byte host[] = {10, 0, 1, 7};
int port = 8089;
WiFiUDP udp;

TinyGPSPlus gps;

void setup()
{
    Serial2.begin(115200,SERIAL_8N1,33,32);
    Serial.begin(115200);
    WiFi.begin(ssid, password); 
    while (WiFi.status() != WL_CONNECTED) { 
    delay(100);
    Serial.print(".");
    }
}

void loop()
{
  uint8_t chipid[6];
  esp_efuse_read_mac(chipid);

  while (Serial2.available() > 0) {
    char c = Serial2.read();
    gps.encode(c);
    if (gps.location.isUpdated()) {
      Serial.print("LAT:  "); Serial.println(gps.location.lat(), 9);
      Serial.print("LONG: "); Serial.println(gps.location.lng(), 9);

  String latnum=String(gps.location.lat(),9);
  String lngnum=String(gps.location.lng(),9);
  String high=String(gps.altitude.meters());
  String id=String(chipid[0],HEX)+String(chipid[1],HEX)+String(chipid[2],HEX)+String(chipid[3],HEX)+String(chipid[4],HEX)+String(chipid[5],HEX);

chipid[1], chipid[2], chipid[3], chipid[4], chipid[5]);
  String line;
  line="gps,device="+id+" lat="+latnum+",lng="+lngnum+",high="+high;
  Serial.println(line);
  Serial.println("Sending UDP packet...");
  udp.beginPacket(host, port);
  udp.print(line);
  udp.endPacket();
  delay(10000);
    }
  }
}

```

</div>
</details>
最速Svelteを速攻デプロイするなら、Zeit NOW一択というメモ。

# Svelteで何かデプロイしたい時には。

普段、バックエンドに引きこもっているデータエンジニアだが、たまにはフロントエンドに出ていってみようかと思い、最速JSに近しい存在という爆速（=>死語？）なSvelteいじって三日目。そろそろ（無料で）デプロイなるものをしてみたい今日このごろ。

...ということで、nodejs系を始めいろいろと無料でお気楽にデプロイできそうなZeit NOWを試してみた。
参考　[Now でクラウドの複雑さから解放されよう、今すぐに](https://qiita.com/aggre/items/f0cb9f8b8e8c54768e50)

github(かgitlabなど)の個人アカウントを持っているならば、たしかに、すぐさまデプロイできたのでメモを残しておく。Zeit now初体験だったが、１０分ほどでデプロイをできた。

デプロイしたもの（カス）:
![sve.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16455/e4bfaeca-fc2b-bda1-2e7d-fec70c366af0.png)
アクセス先:
https://svelte1.now.sh

・・・デプロイしたものは、Svelteの公式チュートリアルの一部を改悪しただけのカス。

# SvelteをNOWにデプロイする手法(2020年版)
## ①　NOW用Svelteをfolk
『zeit svelte』でググると出てくる以下から、
https://zeit.co/guides/deploying-svelte-with-zeit-now
自分が使っているgitリポジトリのアカウントを選ぶだけ。githubの場合
https://zeit.co/import/git?tab=github
あとは、SSOの認証を行うとディフォルトでprivateリポジトリにfolkしてくれる。
公開すると恥ずかしいサービスを作りたいとか、一山当てたいサービスを作りたい際には、privateリポジトリがディフォルトなのはありがたい限り。


## ②　NOW用Svelteをcloneして編集
folkたら当然、git cloneの類を持ってきて編集することになる。
フォルダ構成は以下の通り。ほぼSvelteのフォルダ構成通りだが.nowフォルダ配下がZeit　NOWとの周りの調整を担ってくれているらしい。

![sv.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16455/70a6ca55-afa5-d427-1d41-8e0e71e1aa17.png)

とりあえず、お試ししたい場合は、↑のApp.svelteを編集する。今回の場合。



```js
<script>
    let count = 1
    $: doubled = count * 2
    $: tripled = count * 3

    let handleClick = () =>{
        count = tripled+3
    }

</script>
<style>
    p {
        color: purple;
        font-family: 'Comic Sans MS', cursive;
        font-size: 2em;
    }
</style>

<main>
  <h1>滑る手おぢさん（仮）。</h1>
  <h2>
    <a href="https://zeit.co/docs" target="_blank" rel="noreferrer noopener">
      ZEIT Now
    </a>
    でSvelteしてみる。突然だが、おい、オマイラ、掛け算という奴をしてみないか。すごく大きくなるぞ。
  </h2>
  <br />
<p>元の数{count} しかして、け奴の×２は、 {doubled} 然らば、×３ {tripled}。けだし大きな数なり。</p>
<button on:click={handleClick}>
    クリックしてみて 。 只今の元の数:{count} 
</button>
</main>
```

## ③　デプロイ
node/npm入っている人ならば、ひとまず、`npm i -g now`した後に、メール認証などを済ませた後は、
編集しているフォルダにて、
`now --prod`
するだけで、git add/git commit / git push、そしてNOWを介して本番デプロイという手順を一気に済ませられる。
セキュリティ云々を考えないなら、ほんとにお気軽。

# 終わりに
少なくとも個人開発でのnodejsでの開発工程ならば、Zeit NOWは現時点では文句なしの存在ということを確認した。Svelteのバックエンドは[数十分で始めた、Svelte+Firebaseのアプリ生活。](https://qiita.com/e-a-st/items/5037dda54b010e09d8ce)で、firebaseが良さげと分かっている。
フロントエンド素人として悩ましいのが、node上でSvelteを動かす方法。絶賛開発中のSapperを試してはみたが、（英語でも）文書がなさすぎて素人にはつらすぎる（セキュリティ云々を気にするとfirebaseをバックエンドにしたアプリを公開できるは先になりそう、、）。

どなたかSvelte/Sapperのベストプラクティスを紹介してくださらぬものかのぅ．（コーダー老人的堕ち）。とりあえず、Svelteお試しする分には楽しいので良しとするが。
flutterで子ファイルの関数を呼び出したいだけだったんだ…。

# 注意

flutter入門者の体験談的ななにかの話。
好ましくない部分が多くあると思いますので真似、絶対駄目。

# 前提

関数を使いたい。
たまたま子ファイルに既に存在している。
別ファイルから関数を呼び出した事無い。
動きを見たいだけなので、あまりソースを書き換えずにひとまず動かしたい。

# 自分が詰まったところとか流れ
+ classをグローバル(GlobalKey)にして、childKey.currentStateに続けて関数を呼び出せばいけるかな? < NG、currentStateがnull
+ body:Child(key: childKey)って書いてあるけれど関数呼びたいだけだしな < 間違えの始まり
+ Globalkeyを記述するのをmain.dartじゃないと駄目なのか? < NG、関係ない
+ currentState?関数呼びたいのにState?? < 困惑
+ N時間経過…。
+ あ、widget経由的な?child.dartのChild Widgetにkeyを渡してを適当に呼び出す。 < 呼べた。

# おわりに
InheritedWidgetとかproviderを使った方法の方がなんだか(たぶん断然)いいらしい。
サンプルソースを少し触っただけで、不明点が積み重なるのが怖かったので今回は触らなかったけれど、今度はそれぞれの書き方で書き直してみたい。

main.dartがBLoCでchild.dartがproviderみたいな書き方もできるのかな。

# 参考
https://qiita.com/takenobi/items/17089c3dff247c84aead

# ソース

```dart:main.dart
import 'child.dart'; //呼びたい子

/*
いろいろ削除されてます。
*/

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    childKey.currentState.callChild("message"); //呼びたい関数
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
            Child(key: childKey), //なんでもいいからWidgetとして呼んでkey渡したる
          ],
        ),
      ),
    );
  }
}


```


```dart:child.dart
//特に省略していない
import 'package:flutter/material.dart';

GlobalKey<_ChildState> childKey = new GlobalKey<_ChildState>();

class Child extends StatefulWidget {
  Child({Key key}) : super(key: key);

  @override
  _ChildState createState() => _ChildState();
}

class _ChildState extends State<Child> {
  void callChild(String message) {
    print(message);
  }

  @override
  Widget build(BuildContext context) {
    return new Container();
  }
}
```
vueの書き方でつまづいた所。v-select : itemにajaxで取得したdataの一部を表示させたい！

最近は全くQiitaを書く余裕がありません！
それくらい毎日全力で必死に生きております笑

ただ今慣れないvue.jsでとあるプロダクトを作っています。
毎日いちいちつまづきまくっていますが、その１つを今日は記載します。

#実施していること

ベタですが、vue.js(vuetify導入）とLaravelで簡単なtodo管理アプリ的なのを作っていました。
ajax(axios)とAPIでデータの受け渡しをしています。

#困ったこと
ajaxで受け取れたデータをv-selectの :itemsに上手く表示できない！

##該当コード

```vuejs
   <v-select
     v-model="todo"
     :items="todos"
     prepend-icon="mdi-clipboard-check-multiple-outline"
     label="to doを選択"
      >
   </v-select>

<script>
  export default {
    data: () => ({
      todo: [],
      todos: [],
      }),
    
     methods: {
    

    fetchTodos: function(){
      axios.get('/api/get')
      .then(res=>{
        console.log(res)
        this.todos=res.data　
      })
    },
    },
    
    created() {
    this.fetchTodos()
  },
  }
</script>

```
非常にシンプルでよくあるコードです。
resの中身はデベロッパーツールで確認済み。

```
console.log(res)
[{…}, {…}]
  0: {…}
    id: (1)
    user_id: (1)
    name: (hoge)
    created_at: (...)
    updated_at: (...)
  1: {…}
     id: (2)
    user_id: (2)
    name: (hogehoge)
    created_at: (...)
    updated_at: (...)
```

このnameを :items="todos" に追加したい！
ここまでデータとれてるから絶対出来るじゃん！
と確信しつつもなかなか答えに辿りつかず。

上記のように　```this.todos=res.data```と記載するとitemsの中身は[object Object]、
配列のままそらぁそうだ、
だって配列の中のnameだけ下さいって指示書いてないもーん。
でもその指示の書き方がわかりません・・・

出来たコードがこちら

```vuejs
 <v-select
   v-model="todo"
   item-value="id"
   item-text="name"
   :items="todos"
   prepend-icon="mdi-clipboard-check-multiple-outline"
   label="to doを選択"
   >
  </v-select>
```

```item-value``` と　```item-text```を利用すると表示できました。
久しぶりのvagrant upでつまづいた話

## はじめに
Laravelを少し触ったことがある程度の初心者なので，ガッツリ開発をしている方々は”それって当たり前だよね？”と思うかもしれませんが，ご了承ください．


## 問題発生
久しぶりにLaravelを触ってみようと思い,Homesteadの設定をしていたところ，
```vagrant up```
させたところで…

```ruby:エラー
/opt/vagrant/embedded/lib/ruby/2.4.0/psych.rb:377:in `parse': (<unknown>): mapping values are not allowed in this context at line 14 column 9 (Psych::SyntaxError)
```

というエラーが発生しました．

このエラー，よく見るとrubyがどうのこうのって書いてあります．
あれ？rubyなんて使ったことないし，これLaravelの環境構築なんだけどな…

## 原因
エラー文をググってみると，同じように困っている方がいました．
[この記事](https://stackoverflow.com/questions/26583222/homestead-laravel-vagrant-not-allowed-windows)によると，```map:```の後に半角スペースが足りないことが原因でした．

```ruby:間違い
folders:
    - map:/Users/code 
      to: /home/vagrant/code
```
```ruby:正しい
folders:
    - map: /Users/code 
      to: /home/vagrant/code
```

え？そこのスペース大事だったんだ…
と気づかされました．

```map:```の後ろに半角スペースを追加したところ，無事```vagrant up```が実行出来ました！

## 参考文献
[homestead laravel vagrant not allowed windows
](https://stackoverflow.com/questions/26583222/homestead-laravel-vagrant-not-allowed-windows)
LAPACK/BLAS など行列計算系ライブラリのメモ(C/C++ から使う用)

## 背景

* C/C++ アプリで行列計算をする必要がある(e.g. SVD など).
  * 主に点群レジストレーション 
* Eigen でもいいが, 計算が速くなるなら専用のライブラリを使うのも検討したい.
  * しかしなるべくクロスプラットフォームで, OSS(non-copyleft)がよくて, アーキテクチャや OS 依存は避けたい.
* 数値計算界隈はよくわからない

## 基礎知識

なんとなくの理解です. 基本は BLAS と LAPACK を押さえておけばよさそう.

* BLAS : 基本となる行列計算ルーチン
* LAPACK : SVD とか行列計算アルゴリズムが実装されている. BLAS を使っている. 通常 C/C++ アプリではだたい LAPACK の API を呼び出すのが多い... はず

基本 API は変わらない(fortran 時代)まま, みなさん BLAS/LAPACK を使っているようです(みんな昔から使っているので, あとから変えるのが難しいというのもありそう).

コードベース(source repo)はいろいろ派生があってわかりずらいです.

## ライブラリのまとめ

* 素(?) の BLAS : fortran で書かれている. 古い. 
* **CBLAS** : 基本的には f2c で C に変換したもの. OpenBLAS など, 最適化された BLAS が使えないときに, こちらをビルドして使うのが想定される. アセンブラは使っていないのでポータブルに動く(はず).
* **OpenBLAS** : アーキテクチャごとに最適化された BLAS. アセンブラを使っている. arm もある. https://qiita.com/syoyo/items/6f15ddc8eeb260bda433
* ATLAS : http://math-atlas.sourceforge.net/ BLAS API で BLAS を最適化したもの. LAPACK API もいくらかあるらしい. 最近は OpenBLAS が主流?
* LAPACK : fortran で書かれている.
* clapack : f2c で C に変換したもの. コンパイルは比較的楽. https://qiita.com/syoyo/items/09009ca77393cc0bd986
* lapacke : https://www.netlib.org/lapack/lapacke.html f2c ではなく手で書いた LAPACK C interface っぽい. より C から呼び出しやすい API になっている? https://stackoverflow.com/questions/26875415/difference-between-lapacke-and-lapack
  * 現在は lapack の repo https://github.com/Reference-LAPACK/lapack (本家?) に取り込まれている 
* ARPACK : https://www.caam.rice.edu/software/ARPACK/ 疎行列計算. f77 だったり f90 だったりいろいろ派生があるっぽい? LAPACK/BLAS を使っている模様
* superlu : https://directory.fsf.org/wiki/SuperLU 疎行列計算. LAPACK/BLAS を使っている.

## C++ 行列ライブラリ

* Eigen : LAPACK/BLAS を使うオプションがある. https://eigen.tuxfamily.org/dox/TopicUsingBlasLapack.html
  * MPL or GPL なのでちょっとライセンスが微妙(Eigen のコードをいじらなければ MPL で実質 MIT/BSD 系として使えはする)
* arnmadillo : http://arma.sourceforge.net/ ビルドに LAPACK/BLAS は必須. 疎行列の superlu, ARPACK は optional
  * Apache 2.0 ライセンスなのがよい. 
* blaze: https://bitbucket.org/blaze-lib/blaze/src/master/ BSD ライセンスでよい.
  * Eigen のように基本テンプレートでヘッダオンリー.
  * 自前(?)で疎行列も実装しているっぽい
  * C++14 or later にはなるが, 機能一通りあり, 開発結構アクティブである, 今後の本命かも
  
## 疎行列専用ライブラリ

疎行列ライブラリはさらにいろいろあってよくわからない.

http://faculty.cse.tamu.edu/davis/suitesparse.html

とりあえずは suitesparse と, superlu を押さえておけばよいか?

suitesparse はライセンスが混在していてつらい :cry:
Unityでシーンを読み込むたびに静的フィールドを初期化するたったひとつの冴えたやりかた

## この記事で述べていること
- Unityでシーンを読み込むたびに、静的フィールドの初期化メソッドを一度だけ呼び出したい。
- そんなときは**静的コンストラクタ**で `SceneManager.sceneLoaded` に初期化メソッドを追加すればよい。
- この方法に辿り着く前に検討した方法と、採用しなかった理由はこういうものです。
- もっといいやり方あったら情報ください。

## 使用バージョン
Unity 2018.4.5f1 Personal
  
## 説明
Unityでは静的フィールドの中身はシーンが変わっても保持されます。
しかし、時には「シーンを読み込むたびに初期化したい！」「でも静的フィールドにはしておきたい！」と思うときもあると思います。少なくとも私はありました。
そんなときは、以下の方法を使えば**シーンを読み込むたびに静的フィールドの初期化メソッドを一度だけ呼び出す**ことができます。  

1.まず、以下のようにクラスの静的コンストラクタを用意します。
これは、静的フィールドを初めて参照した際、参照する直前に呼び出されるコンストラクタです。これを使えば静的フィールドが参照される前に**一度だけ**、処理を行うことができます。

  ```c#:静的コンストラクタ
public class Example{
    private static int staticField_;

    static Example(){
     
    }
}
  ```
  
2.次に初期化用のメソッドを用意し、そのメソッドを静的コンストラクタ内で`SceneManager.sceneLoaded`に追加します。
これはUnityAPI側で用意されているイベントで、**シーンが読み込まれた際にここに追加されたメソッドが呼び出されます。**
第一引数には読み込まれたシーン、第二引数にはシーンの読み込みモードが入ります。この引数は追加するイベントに合わせて付ける必要があるため、省くことはできないことに注意してください。
また、SceneManagerクラスは`UnityEngine.SceneManagement`名前空間にあるため、インポートする必要があることにも注意してください。  

```c#:シーンロード時のイベント
using UnityEngine.SceneManagement;

public class Example{
    private static int staticField_;

    static Example(){
      SceneManager.sceneLoaded += init;
    }

    private static void init(Scene loadingScene, LoadSceneMode loadSceneMode){
        staticField_ = 0;
    }
}
```

## 実行タイミング
「シーンを読み込んだ際に呼び出される」と書きましたが、その実行タイミングは
1.Awake
2.sceneLoadedに追加したメソッド(ここで実行される)
3.Start
となっているらしいです。つまりこの方法でも、**自他のスクリプトのAwakeで静的フィールドを参照するようなコードを書くと、未初期化の値を参照してしまう恐れがある**ので、その点は注意してください。

## こうしなかった理由
これを考えつく前に検討した方法と、そうしなかった理由です。
### 1.わざわざ初期化メソッドを追加しなくても、静的コンストラクタで初期化すればいいんじゃないの？  
静的コンストラクタは、初めて静的フィールドを参照した際に一度だけ実行されます。
「ならそれで初期化すればよくない？」と思われるかもしれませんが、Unityでは静的フィールドの値が保持される関係で、最初の一回のみ「初めて参照した」と判断されるらしいです。つまるところこれで初期化してしまうと、最初の一回以外はいくらシーンを切り替えようがゲームを終了しない限りはもう二度と初期化されません。
  
### 2. Awakeで初期化すればいいんじゃない？  
このスクリプトが１つしか張り付いてない・確実にシーンにそのスクリプトが張り付いているオブジェクトがアクティブで存在している保証があるならまあそれでもいいんですが…いくつか以下のようなデメリットが出る場合があるので採用しませんでした。  
デメリット１：Awakeは各インスタンス毎に実行されるため、必然的に複数張り付いていればそれだけ初期化メソッドが実行されます。  初期化が重ければ、それだけシーンのロードが重くなってしまいます。  
  
デメリット２：「なら静的フィールドのフラグを作って一度だけ実行されるように管理すれば…」と思われるかもしれませんが、それだけの理由でフィールドが１つ増えてしまうことになりますし、そのフラグをStartなりでfalseにしてやる手間が増える(シーンの最初で再度初期化を走らせるため)ので、好ましくありません。  
  
デメリット３：Awakeは「オブジェクトがアクティブのとき、インスタンスがロードされたタイミング」に実行されます。つまり、何か理由があって「オブジェクトを最初は非アクティブにしておき、後でアクティブにする」ということをしていた場合、**初期化メソッドが走るタイミングはシーンの最初ではなく、そのタイミングになってしまいます。**(オブジェクトがアクティブならスクリプトが非アクティブでもAwakeは実行されます)  
  
デメリット４：そのスクリプトが張り付いているオブジェクトがなければ、必然Awakeも実行されません。つまりそのスクリプトが張り付いているオブジェクトが存在しないシーンでその静的フィールドを参照した場合、未初期化の値が取得されてしまいます。

## 最後に
これ本当に一番いい方法なんでしょうか？もし「違うよ」って人がいましたら連絡ください。

## 参考サイト
- 【Unity】シーンの切り替えを検出するイベント  
https://tech.pjin.jp/blog/2018/10/24/unity_scene-manager_event/#10
- OnLevelWasLoadedが非推奨になったからSceneManager.sceneLoadedで置き換えてみる【Unity】  
https://kan-kikuchi.hatenablog.com/entry/sceneLoaded
- UnityのメソッドAwakeとStartの違い  
https://gametukurikata.com/program/awakestart
goenvのコマンドチートシート

pyenvと似たような感じですね。

### コマンドチートシート
|  command  |  内容  |
| ---- | ---- |
|  goenv commands  |  使用可能なgoenvコマンドを全て表示  |
|  goenv completions  |  --completeを指定して呼び出すことにより、自身および他のコマンドの自動補完を提供します。  |
|  goenv exec  |  指定した仮想環境のGoバージョンでファイルを実行する。<br>例）goenv exec go run main.go  |
| goenv global |すべてのシェルで使用されるGoのグローバルバージョンを設定する。 |
| goenv help | コマンドのヘルプを表示<br>例）goenv help execとか、goenc help installなど、helpのあとにコマンドを入力すると、当該コマンドのヘルプを表示してくれる。 |
| goenv hooks | 特定のgoenvコマンドのフックスクリプトを一覧表示する。 |
| goenv init | goenvのシェル環境を構成する。 goenvをシェ​​ルと統合する場合に使う。<br>.bashrcや.zshrc、.bash_profileに「eval "$(goenv init -)"」を追記しておく必要がある。 |
| goenv install | Goバージョンのインストール（インストール可能なバージョンは「goenv install -l」で表示できる。） |
| goenv local | ローカルのアプリケーション固有のGoバージョンを設定する。<br>グローバルのGoはv1.10.0だが、特定のフォルダだけv1.11.0にしたりとかできる。 |
| goenv prefix | Goバージョンがインストールされているディレクトリを一覧表示。 |
| goenv rehash | goenvが認識するすべてのGoバイナリ（つまり、〜/.goenv/versions/*/bin/*）にshimをインストールする。<br>Goの新しいバージョンをインストールした後、またはバイナリを提供するパッケージをインストールした後に、このコマンドを実行するらしい。 |
| goenv root | Goバージョンとshimが保持されているルートディレクトリを表示する。 |
| goenv shell | シェルでGOENV_VERSION環境変数を設定して、シェル固有のGoバージョンを設定する。<br>アプリケーション固有のバージョンとグローバルバージョンをオーバーライドするので、一番強い（小並感）。<br>解除は「goenv shell --unset」 |
| goenv shims | goenvのshimを一覧表示する。 |
| goenv uninstall | Goバージョンの削除。<br>例）goenv uninstall 1.11.0 |
| goenv version | アクティブなGoバージョンを一覧表示する。 |
| goenv --version | goenv自体のバージョンを表示する。 |
| goenv version-file | Goバージョンを設定しているファイルを一覧表示する。 |
| goenv version-file-read | 指定されたgo-versionファイルが存在する場合、そのファイルを読み取る。<br>例）goenv version-file-read ./go-version |
| goenv version-file-write | go-versionファイルのバージョンを書き換える。 |
| goenv version-name | 現在のGoバージョンを表示 |
| goenv version-origin | Goバージョンの設定方法を表示する。 |
| goenv versions | 全てのGoバージョンを一覧表示し、現在のアクティブバージョンの横には「*」を表示する。 |
| goenv whence | 指定されたコマンドがインストールされたすべてのGoバージョンを一覧表示。 |
| goenv which | 指定したコマンドを実行したときにgoenvが呼び出す実行可能ファイルのフルパスを表示する。 |

# goenv導入（Homebrew）
```
$ brew update
$ brew install goenv
```

`.bash_profile`に追記（環境によっては`.bashrc`や`.zshrc`）

```
echo 'export PATH="$HOME/.goenv/bin:$PATH"' >> ~/.bash_profile
echo 'export GOENV_DISABLE_GOPATH=1' >> ~/.bash_profile
echo 'eval "$(goenv init -)"' >> ~/.bash_profile
echo 'eval "$(goenv init -)"' >> ~/.bash_profile
```

忘れずに反映

```
source ~/.bash_profile
```

### goenvの最新バージョン取得
brew installしたgoenvは新しいGoバージョンが出ても反映してくれません。
新しいものは全てgoenv 2.0.0bataXXに反映されていくので、それをインストールします。

```
brew install --HEAD goenv
```

<font color="red">以下のようなエラーが出た場合は、エラーメッセージに従って「brew unlink goenv」をしてから再度実行しましょう。</font>

```
Error: goenv 1.23.3 is already installed
To install HEAD, first run `brew unlink goenv`.
Warning: Skipping (old) /usr/local/Cellar/goenv/1.23.3 due to it being linked
```

### 注意
<font color="red">--HEADでインストールしたものはbrew upgradeで更新してくれない</font>
ので、`--fetch-HEAD`で更新する。

```
brew upgrade --fetch-HEAD goenv
```

めんどくさい（;ω;）
jqueryプラグインlightbox2をIEで使うと、ページのTOPにウィンドウが移動してしまう問題。

##問題
IEでjqueryプラグイン「lightbox2」を使うと、クリックしモーダルが開いた後ウィンドウがページTOPに移動してしまう問題。

事象が起きた環境：
jqueryバージョン：jquery 3.4.1
Lightboxバージョン：Lightbox v2.11.1

##解決方法
「lightbox.js」内の
self.$overlay.focus();
の記述を消す。
※これによりキーボード← →で次のスライドに移動する操作はできなくなります。
SwiftUIビューのUIViewControllerにアクセスする

適当な`UIViewControllerRepresentable`ビューコントローラーを作り追加して他のビューコントローラーへアクセスするコードです。多少強引で黒魔術っぽい方法だろうけど、どうしてもそうしたい時に。

```swift
import SwiftUI

public struct ControllerRepresenterView: UIViewControllerRepresentable {
    public typealias UIViewControllerType = UIViewController
    
    private final class ViewController: UIViewController {
        var willAppear: (UIViewController) -> Void = { _ in }
        var didAppear: (UIViewController) -> Void = { _ in }
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            willAppear(self)
        }
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
            didAppear(self)
        }
    }
    
    private let viewController = ViewController()
    
    public init(
        willAppear: @escaping (UIViewController) -> Void,
        didAppear: @escaping (UIViewController) -> Void
    ) {
        viewController.willAppear = willAppear
        viewController.didAppear = didAppear
    }
    
    public func makeUIViewController(context: Context) -> UIViewControllerType {
        viewController
    }
    
    public func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        //
    }
}
```

### 使用例

```swift
import SafariServices

struct ContentView: View {
    func doNothing(uiViewController: UIViewController) {}
    
    func example(uiViewController: UIViewController) {
        // contentへアクセスする為に
        guard let viewController = uiViewController.parent else { return }
        // ex1: 黄色から青色へ
        viewController.view.subviews.last?.backgroundColor = UIColor.systemBlue
        // ex2: 1秒後にフルスクリーンモーダル表示
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            let a = "https://www.apple.com/"
            guard let u = URL(string: a) else { return }
            let c = SFSafariViewController(url: u)
            c.modalPresentationStyle = .overFullScreen
            viewController.present(c, animated: true, completion: nil)
        }
    }
    
    var content: some View {
        Color.yellow
    }
    
    var body: some View {
        Group {
            content
        }
        .background(
            ControllerRepresenterView(willAppear: doNothing, didAppear: example)
        )
    }
}
```
Docker を AWS にインストール

200321

注意点
なぜか動かない、という状況は AWS のセキュリティグループの設定が原因かもしれない。

# AWS の準備
EC2 をたてるまでの手順は、ここでは説明しない。注意が必要なのはセキュリティグループの設定で、デフォルトでは SSH 以外はすべてブロックされる。


# AWS に docker をインストール

`sudo yum update`
`sudo yum install -y docker`

正常にインストールできたか確認できる。バージョンは 1.21.5 のようだ。
`docker info`

## sudo がなくてもいいようにする
`sudo service docker start`
`sudo usermod -a -G docker ec2-user`

# docker-compose インストール

docker-compose 
`sudo curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose`

パーミッション変更が必要
'sudo chmod +x /usr/local/bin/docker-compose'
'docker-compose --version'


# Django のデプロイ

## Docker を使った本番デプロイ
AWS 上でディレクトリ構造などを作ったりする必要はない。そんなことをやっていると手間ばかりかかってミスも連発する。ローカルの開発環境にも Docker を入れて、ここで完成したものをそのまま丸ごとコピーするのが正しい。

## セキュリティグループの追加
EC2 のインスタンスを普通に立てただけでは SSH しかできない設定となってる。セキュリティグループに、HTTP プロトコル（ポート 80 または 8000）を通す設定をしておかないと絶対につながらず、時間を溶かすので注意が必要。


## ローカルで開発したプロジェクトのデプロイ
ローカル環境で動作確認した django プロジェクトは、ディレクトリごと zip にしてホストに転送する。配置したい場所で unzip すると、そのままファイルができるので、あとは docker-comopose up すれば立ち上がる。





おわり
Seleniumでid属性の指定されていない要素を取得する

## やりたいこと
Selenium WebDriverを使って画面の要素を指定する際に、id属性が指定されていない場合はどうやってその要素を取得するか？という話です。ChromeでYahooの検索キーワードに任意のワードを指定し検索ボタンを押下する、というのを例に見てみます。
![コメント 2020-03-21 133909.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/5a895ad9-6a70-0cca-2099-2780fffb4108.png)

まず、検索キーワードを入力するテキストボックスにはname属性（name="p"）が指定されているので、以下のようにそれを利用します。
![コメント 2020-03-21 214940.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/41fdd67a-54ac-899c-58d8-5f2a1203c7f2.png)

検索キーワードがゆりあんレトリバーなのは、YouTubeでゆりあんレトリバーの動画を見ながら本記事を書いているので何となくそうしてます。

```SampleScript.java
webDriver.findElement(By.name("p")).sendKeys("ゆりあんレトリバー");
```

検索ボタンにはid属性もname属性も指定されていません。
![コメント 2020-03-21 133942.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/08675928-bb45-73c3-bc79-07e19c30c3b9.png)

このような場合は、[XPath](http://xml.prognavi.com/?p=95)が利用できます。XPathはChromeのデベロッパーツールから確認、コピーできます。
![コメント 2020-03-21 134008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/93fb6326-14f8-0bc5-0af8-95eda01ff919.png)
コードは以下の通りです。

```SampleScript.java
webDriver.findElement(By.xpath("//*[@id=\"ContentWrapper\"]/header/section[1]/div/form/fieldset/span/button/span/span")).click();
```

###まとめ
ソースはこんな感じです。

```SampleScript.java
public class SampleScript {

    public static void main(String[] args) {
        System.setProperty("webdriver.chrome.driver", "C:\\Development\\selenium\\chromedriver.exe");
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("https://www.yahoo.co.jp/");
        webDriver.findElement(By.name("p")).sendKeys("ゆりあんレトリバー");
        webDriver.findElement(By.xpath("//*[@id=\"ContentWrapper\"]/header/section[1]/div/form/fieldset/span/button/span/span")).click();
    }
}
```

実際に動かしてみると以下のようになります。
![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23101/8e47086c-d53a-28e6-b97e-a2f3303b2293.gif)

ちなみに、上記ではあえて最後にブラウザを閉じていませんが、webDriver.quit();とすること、ブラウザを閉じることができます。
quitメソッドを呼び出すことで、WebDriverインスタンスから生成された全てのブラウザが閉じ、そのブラウザのDriverプロセスも終了します。逆に言うと、quitメソッドを呼び出さないとそれらのプロセスも残ったままとなってしまうので注意が必要です。
Vueのイベントハンドリングを理解する

## どんな記事？

Vue.jsのイベントハンドリングを理解しよう！

## イベントハンドラとは？

イベントハンドラとは、**イベントの通知**を受け取るように登録されている関数またはオブジェクトのことを指します。

その要素がどのようにイベントに反応するか、を管理します。

イベントには、クリック・押されたキーの検出・フォーカスの取得等々があります。

## Vueにおけるイベントの購読

`v-on`ディレクティブを使うことで、**DOMイベントの購読**、**イベント発火時のJavaScriptの実行**が可能になります。

```vuejs:例
<div id="example">
  <!-- クリックされると変数counterに1ずつ足すボタン -->
  <button v-on:click="counter += 1">1足す</button>
</div>
```

```javascript
var example = new Vue({
  el: 'example',
  data: {
    counter: 0
  }
});
```

## メソッドを呼び出す

`v-on`は呼び出したいメソッドの名前も受け付けます。

```vuejs:例
<div id="example">
  <!-- クリックされたら挨拶するメソッドを実行 -->
  <button v-on:click="greet">挨拶する</button>
</div>
```

```javascript
var example = new Vue ({
  el: 'example',
  data: {
    name: 'Vue.js'
  },
  //メソッド定義
  methods: {
    greet: function (event) {
      //`this`はVueインスタンスを参照
      alert('Hello ' + this.name + '!')
      //`event`はDOMイベントを指す
      if (event) {
        alert(event.target.tagName)
      }
    }
  }
})
```

```:実行結果（ボタンを押すとアラートに表示）
Hello Vue.js!
```

## v-onの利点

なぜVueでは`v-on`を使ってHTMLにリスナーを記述するのか。

1. HTMLテンプレートからJSコード内のハンドラ関数を簡単に探せるようにする
2. JS内のイベントリスナーを手作業で付け加える必要がないのでViewModelをDOM依存のない純粋なロジックにできる。これはテストを実施しやすくする。
3. ViewModelが消去される時に全てのイベントリスナーは自動で削除される。

上記の利点により、Vueでは`v-on`を使ってリスナーを記述する。

## 省略記法

`v-on`も`v-bind`同様に省略記法がある。

```vuejs:完全な構文
<a v-on:click="doSomething"></a>
```

```vuejs:省略記法
<a @click="doSomething"></a>
```

## 参考

[DOM on-イベントハンドラ](https://developer.mozilla.org/ja/docs/Web/Guide/Events/Event_handlers)
[イベントハンドリング](https://jp.vuejs.org/v2/guide/events.html)
【UE4】ブループリントで別のレベルを開いて遷移する方法【UnrealEngine】


ゲームのメインのレベル以外にもタイトルやリザルトなど複数レベルを作り、任意のタイミングでレベルを切り替えたいことってありますよね。

ブループリントでシンプルに実装することができます。

結論
---------------------------
![levelの開き方.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497331/ca117472-13ee-0d76-9917-c7b4e55d9b9d.png)


内容
-----------
OpenLevelだけでも別のレベルに切り替える事が出来るのですが
LoadStreamLevelのノードを先に挟む事で、裏でレベルを読み込み終えてからレベルを切り替えれて
画面が固まるのを防ぐことが出来ます。

おわり
--------

Unityではシーン、UE4ではレベル。いとややこしや
Automation Anywhere A2019 常駐プロセス/サービス一覧 メモ

バックグラウンドで走っているプロセスやサービスがいろいろありそうなのでメモすることにしました。

[Automation Anywhere v11.3.x版はこちら](https://qiita.com/RPAbot/items/10529aa7407f0c7aefff)

# Bot Agent

**プロセス**

|名前|標準パス|メモ|
|:--|:--|:--|
|java.exe|C:\Program Files\Automation Anywhere\Bot Agent\jre\bin|Java本体|
|nssm.exe|C:\Program Files\Automation Anywhere\Bot Agent\nssm|The non-sucking service manager。任意のアプリケーションをサービスとして実行できる。Bot Agentをサービスとして実行。|
|Automation.BrowserAgent.exe|C:\ProgramData\AutomationAnywhere\GlobalCache\embedded-resources\2.0.1-20200111-070529-1825fd43-19bc-4dd2-ac56-53a2aed4b0e4|ブラウザー拡張アドイン|

**サービス**

|名前|標準パス|メモ|
|:--|:--|:--|
|Automation Anywhere Bot Agent|C:\Program Files\Automation Anywhere\Bot Agent\nssm\nssm.exe|Bot Agentサービス|
JavaScript イベントリスナー一覧

## よく使用する 12個

- <font color="Red">load</font>	 Webページの読み込みが完了した時に発動（画像などのリソースすべて含む）
- <font color="Red">DOMContentLoaded</font>  Webページが読み込みが完了した時に発動（画像などのリソースは含まない）
- <font color="Red">click</font>  マウスボタンをクリックした時に発動
- <font color="Red">mousedown</font>  マウスボタンを押している時に発動
- <font color="Red">mouseup</font>  マウスボタンを離したときに発動
- <font color="Red">mousemove</font>  マウスカーソルが移動した時に発動
- <font color="Red">keydown</font>  キーボードのキーを押したときに発動
- <font color="Red">keyup</font>	キーボードのキーを離したときに発動
- <font color="Red">keypress</font>	キーボードのキーを押している時に発動
- <font color="Red">change</font>	フォーム部品の状態が変更された時に発動
- <font color="Red">submmit</font>	フォームのsubmitボタンを押したときに発動
- <font color="Red">scroll</font>	画面がスクロールした時に発動

ドキュメント
>https://developer.mozilla.org/ja/docs/Web/Events
GoogleMapsAPI備忘録（2020年3月時点）

# はじめに
今までの案件で使ったGoogleMapsAPIについての備忘録です。
APIの仕様や制限が変わるので、忘れる前に備忘録を残します。

# GoogleMapsAPI
[公式URL](https://developers.google.com/maps/documentation?hl=ja)

## マップ
- **Maps SDK for Android**
  地図を Android アプリに追加します。

- **Maps SDK for iOS**
  地図を iOS アプリに追加します。

- **Maps Static API**
  シンプルで埋め込み可能な地図画像を最小限のコードで追加します。

- **Maps JavaScript API** 
  ウェブサイトにインタラクティブな地図を追加します。独自のコンテンツと画像でマップをカスタマイズできます。

- **Street View API**
  360 度のパノラマ画像を使用して実世界の画像を埋め込みます。

- **マップ URL**
  Google マップを起動し、クロスプラットフォームの URL スキームを使用して、
  検索やルート検索などの操作を開始します。

ネイティブアプリ開発の案件だったため、Android/iOSそれぞれのSDKを使用しました。
検索すれば、やりたいことを実現するための方法を教えてくれるサイト・記事が多く、
特に詰まった部分はありませんでした。

## ルート
- **Directions API**
複数の場所間の公共交通機関、自転車、車、徒歩でのルートを提供します。

- **Distance Matrix API**
複数の目的地について移動時間と距離を計算します。

- **Roads API**
車両が走行する正確なルートを決定します。

Directions APIを使用しました。
ネイティブアプリでもAPIを直接使用する形式になるので、公式ドキュメントでほとんどこと足りました。
一点、そもそもで詰まった部分がGoogle mapのAPI KeyをAndroid/iOSで使用しても、
APIが正常に動きませんでした。
公式ドキュメントに以下の一文があるので、WebのKeyでないとダメなのかもしれません。
（バックエンドチームにラップしたAPIを作ってもらいました..）

> This service is also available as part of the client-side Maps JavaScript API, or for server-side use with the Java Client, Python Client, Go Client and Node.js Client for Google Maps Services.

## プレイス

- **Places SDK for Android**
多くの場所の豊富な詳細を Android アプリに追加します。ユーザーのクエリにオートコンプリートの結果を提供します。住所と地理座標を変換します。

- **Places SDK for iOS**
多くの場所の豊富な詳細を iOS アプリに追加します。ユーザーのクエリにオートコンプリートの結果を提供します。住所と地理座標を変換します。

- **プレイス ライブラリ、Maps JavaScript API**
多くの場所の豊富な詳細をウェブサイトに追加します。ユーザーのクエリにオートコンプリートの結果を提供します。住所と地理座標を変換します。

- **Places API for Web**
HTTP リクエストを使用して、多くの場所の最新情報を取得できます。

- **Geocoding API**
住所を地理的座標に変換したり、地理的座標から住所を特定したりできます。

- **Geolocation API**
携帯電話の基地局や Wi-Fi ノードからの位置データを利用して、GPS に依存せずにデバイスの位置を返します。

- **Time Zone API**
特定の緯度と経度のタイムゾーンを取得します。

PlacesのSDKを使用しました。
公式ドキュメントに書いてあることで事足りましたが、どう使うかを考える必要はありました。
AutoCompleteを実現するときにFragmentやActivityのようなWidgetごと導入するか、
API実行のように導入するか選択できます。
どちらも試してみましたが、UIデザインが決まっている場合は後者の方が自由が効きます。

# まとめ
はじめは、案件で使ったAPIで適当なアプリを作ろうと思ったんですが、
諸々時間が足りずひとまずは記憶のあるうちにメモだけを残しました。
【SwiftUI】NavigationViewの遷移先の画面でtitleの非表示

非表示というか、こんな感じの状態

![SecondVIew_swift_—_Edited.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195882/2d74307e-fc8f-3b53-188a-9c57a8d0236a.png)

以下を遷移先のViewにつけるだけ

```swift
.navigationBarTitle(Text("title"), displayMode: .inline)
```
ソフトウェアテスト手法を読んだメモ①

#この記事は何ぞや&#x1f914;
勧められた「現場の仕事がバリバリ進む ソフトウェアテスト手法」を読んでいて、指定されていた第４章の中から気になった個所などを抜粋したメモ

#テストケースの種類

##機能テスト
<font color="red">機能のバグを見つけること</font>
※例えば 
　⇒プログラムが何らかのバグにより機能が実現しなかった場合
　⇒バグによってパフォーマンスが出なかったとしても、機能が最低限実現されている場合は言わない

そもそも**機能**ってなんだ？:eyes:
　ソフトウェア業界での**機能**とは、そのソフトウェアが<font color="red">何をするか(WHAT)</font>ということ
　⇒NOTどのように動作するのか(HOW)

つまり、	要求されている仕様(目的)を満たしているかどうかを検証する

システムテストの一つとして実施されることが多い
ソフトウェアの外部動作を検証するため、ブラックボックステストに分類される仕様書ベースのテスト技法を用いる

##ドメインテスト
　境界値テストとも言う
　⇒関係性がある複数の変数を同時に検証する
　記述は機能テストと同じ様相を呈する
　
テストケースの規格
　①テストケースを区別する記号
　②テストアイテム
　③入力リスト
　④出力リスト←テスト結果のこと
　⑤環境
　⑥プロシージャ←ケースを実行する上で、特別に行わなければならない事項
　⑦依存テストケース←ケースを実行する上で必ず行わなければならない事項←全てのケースで必要とは限らない

依存テストケースを記述しなければいけないのに、書かない担当者は不適人者とも言える
→テストケースはいつ誰がやっても実行できるようにするポリシーを理解していないと言える

##スペックベーステスト
　書かれたドキュメントに対するテスト
　→要求のドキュメント
　 設計書
　 ユーザーインタフェース仕様書
　 モデル　　　…などなど

Ex：ユーザーマニュアルに書いていることと開発されたソフトウェアが合致するかのチェック
　 テスト設計者に伝わっていないけど、ユーザーマニュアルに持っている機能があるのでそのチェック

##ストレステスト
 システム最大設計負荷およびそれ以上の負荷の元で実行するテストのこと

最大負荷ポイントが境界値で、それをまたぐように最大負荷の前後に対してテストケースを作成していく


ソフトウェアはユーザーに不利益な動作をすべきではない
→プログラムのハングアップによってユーザーが今まで入れてたデータや情報を失わせてはならない
 ハングアップによって再度長いデータを入力し直さなければならない、など

##回帰テスト
 バグが回収されたかどうかを確認するテスト
 改修確認・デグレ確認など

①バグが発見され、開発者が修正し、その修正が正しく修正されているかの確認
②バグの修正により、そのサイドエフェクトがないか、他にバグがないかを調査する

##ユーザーテスト
 ユーザーが実際に行うテスト
 リアルのユーザーがどう言うデータを入力したり出力したりするかを確認できるテスト

ユーザーテストでユーザーが行ったテストについては、記録をとっておき、出荷するまでにさらに十分なテストを行うこと

##シナリオテスト
 ユーザーがどのように製品を使うか、何を目的としてソフトウェアを使うかを想像しながらテストをしていく

ユーザーとは
①一般的なユーザー
②ロクでもないユーザー＝ハッカー
が想定される

##状態遷移テスト
 テストケースが書き難いテスト

ある状態からある状態への遷移を確認するテスト
マトリックス（表）を作成してテストを実施する

ステップを書くのが困難である→バグが見つかっても再現が難しい
自動化テストを作成して、バージョン管理を行うなどの対策が必要となる

テストケースの粒度が揃え難い問題もある

##自動化によるボリュームテスト
①ガリガリ自動的に多量のテストケースを作成する
②その多量のテストケースを短時間で流す
③多量のテストケースをオラクル（賢者）プログラムを作ってソフトウェアが期待する結果の動作を行なっているかを判断する

#スケジューリング
　ドメインテストをどのくらい行い、どのタイミングでシナリオテストを行い、そしていつシステムテストに移って行くのかをテストマネージャーは決めなければならない
　ソフトウェアによっても、品質の悪い物はテストを増やしたり、またその逆もある

・シナリオテストは機能テストより先に行わず、機能テストで十分品質を確保してからの方がいい
・状態遷移テストは機能テストより先に行わない方がいい

しかしいくつか注意点はあるものの、パターン化出来るものがそれほど多くない…


#テストケースの作成
　①より多くのバグを見つける
　　⇒だけど、仕様通り・マニュアル通りにソフトウェアが動くことをも確認する必要がある
　②誰がいつ行っても同じステップで実行できる
　　⇒あいまいな表現や記述をしないことは重要
　③多すぎず、また少なすぎない

・効率的なテストケース
TCE(テストケースの効率性 %)=Ntd(テストケースによって発見されたバグの和)/Ntot(バグの総数)＝100

テストとは品質を向上させる活動の１つである
無理して全てのバグを見つける必要はない(そもそもどだい無理な話だし)

**バグの見つけ方**
①バグデータの収集と解析、バグ防止策の実行
②エラー推測

この2つが効率的なテストケースを書く上で最も重要なこと

#テストケースの管理

##ケース数の管理
・市販のテスト工程管理ツールを導入するのもアリ

**メリット**
・テストケースを書く際に、テスト担当者たちが同じ粒度でテストケースを入れ易い
・テストケースの管理がし易い

テスト工程管理ツールを使用するとテストマネージャーの仕事量は激減する
テストマネージャーは常にテスト担当者がどのくらいテストケースを実行しているか、そのうちいくつのテストケースが失敗する必要があるため、管理ツールは必須となる

#テストケースの実行
実行する際にはログを取る必要がある
・日付（テスト実施日）
・テスト結果
・実施者(実行者)
・ビルド番号(ビルド＝プログラムの元ネタから実際のプログラムを作る作業工程)
・環境
*もしユーザー側で重大なバグが発生した場合、どのような経緯でそれが開発期間中に発見出来なかったのかの分析にも役立つ

<font color="red">どの順番でテストをするか深慮する必要がある</font>
※重要度やリスクを考えながら実行するべき
・より重要な機能が動かず、他のテストが出来ない＝実行がストップしてしまうことが防げる
・重要な機能のバグが早期に発見できる
windows 10 hhkb professional2 でctrl+]->esc,半角英数:かな入力:hotkeyを実現したかった

### できること
左altで英数入力
右altで日本語入力
ctrl + ] -> escape key + 英数入力
space + c -> chrome(active->最小化。最小->active,起動していない->起動)
space + v -> vscode(同じ)
space + t -> ubuntu(同じ)

### 完成品
https://github.com/kajirikajiri/AutoHotKey

### かな入力<->英数入力を切り替え
alt keyとwindows keyを入れ替える(ChgKey.exe)
左alt keyを空打ちで英数(IME OFF)
右alt keyを空打ちで日本語入力(IME ON)
https://kiz.hatenablog.jp/entry/2018/07/22/175504
https://github.com/karakaram/alt-ime-ahk

### hotkeyを作成
hotkeyのプログラム(AutoHotKey)
https://qiita.com/mareku/items/562c95e2afe707989b86

---
mac->windowになりました(thinkpad x2 extreme gen 2)
wslにdocker,ghqいれるの辛かった(できた)
alfredなかったから[keyprinha](https://keypirinha.com/)いれた。おしい感じ
複数のヒストグラムを比較したい場合

#複数の分布をヒストグラムで比較したい場合

思ったようなグラフを書こうと思ったら、色々彷徨ったのでメモ。
できることが多いのはいいけど、どれがベストかすぐに判断しにくいのは厄介。。。

```python
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
import pandas as pd

param = [ ("M01", -75, 4), ("M02", -79, 5), ("F01", -81, 3), ("F02", -82, 5) ]
data = [[name, np.random.normal(loc, scale)] for name, loc, scale in param for i in range(100)]

df = pd.DataFrame(data, columns=["spk","rms"])

print(df)

df.hist(column="rms", by='spk', sharex=True, sharey=True, figsize=(7,7), layout=(2,2))
plt.show()

g = sns.FacetGrid(df, hue="spk", height=7)
g.map(sns.distplot, "rms", label="spk")
g.add_legend()
plt.show()
```

```
     spk        rms
0    M01 -70.771956
1    M01 -71.254004
2    M01 -77.829105
3    M01 -73.486316
4    M01 -71.048432
..   ...        ...
395  F02 -83.557042
396  F02 -81.383104
397  F02 -78.089854
398  F02 -81.057188
399  F02 -93.473633

[400 rows x 2 columns]
```

![index.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455423/e1764f34-76ea-b243-1f6e-0702d79a15ef.png)
![index2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455423/1df2fddc-8c21-a8ec-5f1d-937c6e78ae5f.png)
Vueのデータバインディングを理解する

## どんな記事？

Vue.jsでの**データバインディング**を理解しよう！

## データバインディングとは

データバインディングとは、**データと描画を同期**する仕組み。

## テキストのバインディング

"Mustache"構文（二重中かっこ）を利用した形が基本です。

```vuejs
<span> Message: {{ msg }}</span>
```

こうすると`{{ msg }}`の部分が、対応するオブジェクトの`msg`プロパティの値に置き換えられます。

## HTMLのバインディング

`v-html`ディレクティブを使用すると、HTML文をバインディングできます。

(**ディレクティブ**とは、DOM要素に対して何かを実行することをライブラリに伝達する、マークアップ中の特別なトークン）

```vuejs
<p v-html="text"></p>
```

```vuejs
data: function() {
  retrun {
    text: 'Hello!'
  }
}
```

```:出力
Hello!
```

`p`のコンテンツは`text`プロパティの値に置き換えられ、プレーンなHTMLとして解釈されます。

## 属性値のバインディング

`v-bind`を使用すると、HTML属性値をバインディングすることができます。

```vuejs
<div v-bind:class="{ active: isActive }"></div>
```

```vuejs
data: {
  isActive: true
}
```

以上のようにすると、HTMLはこのように描画されます。

```vuejs:描画結果
<div class="active"></div>
```

`isActive`が`false`になると、`active`属性値は描画されなくなります。

テンプレートをより見やすくする為に、直接オブジェクトを指定してバインディングする方法もあります。

```vuejs
<div v-bind:style="styleObject"></div>
```

```vuejs
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}
```

```vuejs:描画結果
<div style="color: red; fontSize: 13px;"></div>
```

## 「:」の意味

テンプレート内の`v-bind`の後ろについている`:`は、**引数**を意味しています。

```vuejs
<a v-bind:href="url"></a>
```

上記の例で`href`は、`v-bind`ディレクティブに、`url`の値と要素の`href`属性をバインドするように伝える**引数**です。

## 省略記法

`v-bind`に対しては省略記法が提供されています。
`v-bind`を書かずに`:`のみにしても大丈夫なんですね。

```vuejs:完全な構文
<a v-bind:href="url"></a>
```

```vuejs:省略記法
<a :href="url"></a>
```

## 参考

[Vue.js公式](https://jp.vuejs.org/)
[Vue.js データバインディングとはなにか説明します](https://programmingnavi.com/1582/)
[データをHTMLコードとして出力するには v-html ディレクティブを使う](https://sawami.net/2019/07/08/tech/vuejs-v-html/)
【今日のアブストラクト】Neural Tangent Kernel: Convergence and Generalization in Neural Networks【論文 DeepL 翻訳】

1 日 1 回 (努力目標) 論文の Abstract を DeepL 翻訳の力を借りて読んでいきます.

この記事は自分用のメモみたいなものです.
ほぼ DeepL 翻訳でお送りします.
間違いがあれば指摘していだだけると嬉しいです.

翻訳元
[Neural Tangent Kernel: Convergence and Generalization in Neural Networks](https://arxiv.org/abs/1806.07572)

# Abstract

### 訳文

初期化時には, 人工ニューラルネットワーク (ANNs) は無限幅限界のガウス過程と等価であるため, カーネル法に接続されます. 学習中の ANN の進化はカーネルによっても記述できることを証明する: ANN のパラメータの勾配降下の間、ネットワーク関数 $f_θ$ (入力ベクトルを出力ベクトルに写像する) は, 新しいカーネル: the Neural Tangent Kernel (NTK) を参照して, 関数コスト (パラメータコストとは対照的に凸である) のカーネル勾配に従う. このカーネルは, ANNs の一般化機能を記述するための中核である. NTK は初期化時にはランダムであり, 訓練中は変化するが, 無限幅限界では明示的な限界カーネルに収束し, 訓練中は一定である. これにより, パラメータ空間ではなく関数空間での ANNs の学習を検討することが可能となる. トレーニングの収束は, 制限 NTK の正定値性に関連する可能性がある. データが球体でサポートされ, 非線形性が非多項式である場合, 制限 NTK の正定値性を証明する.
次に, 最小二乗回帰の設定に焦点を当て, 無限幅限界において, 学習中のネットワーク関数 $f_θ$ が線形微分方程式に従うことを示す. 収束は入力データの最大カーネル主成分に沿って NTK に対して最速であり, アーリーストッピングの理論的動機を示唆している.
最後に, 数値的に,NTK を調べ, 広いネットワークでの振る舞いを観察し, 無限幅限界との比較を行う.


### 原文

At initialization, artificial neural networks (ANNs) are equivalent to Gaussian processes in the infinite-width limit, thus connecting them to kernel methods. We prove that the evolution of an ANN during training can also be described by a kernel: during gradient descent on the parameters of an ANN, the network function $f_θ$ (which maps input vectors to output vectors) follows the kernel gradient of the functional cost (which is convex, in contrast to the parameter cost) w.r.t. a new kernel: the Neural Tangent Kernel (NTK). This kernel is central to describe the generalization features of ANNs. While the NTK is random at initialization and varies during training, in the infinite-width limit it converges to an explicit limiting kernel and it stays constant during training. This makes it possible to study the training of ANNs in function space instead of parameter space. Convergence of the training can then be related to the positive-definiteness of the limiting NTK. We prove the positive-definiteness of the limiting NTK when the
data is supported on the sphere and the non-linearity is non-polynomial.
We then focus on the setting of least-squares regression and show that in the infinite-width limit, the network function $f_θ$ follows a linear differential equation during training. The convergence is fastest along the largest kernel principal components of the input data with respect to the NTK, hence suggesting a theoretical motivation for early stopping.
Finally we study the NTK numerically, observe its behavior for wide networks, and compare it to the infinite-width limit.
React Native でいろんなメニューを持ったアプリを作る

# 最終形

- タブメニューで画面が切り替わる
- どの画面からでもアクセスできるスライドタイプのメニューを持つ
- イベントトリガーでポップアップ画面が差し込まれる

以下の動画のようになります。
![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43625/fbccf485-2453-805e-9d84-4c3a8b68293b.gif)

このような複数の画面パターンを持ったアプリを実装していきます。

# ナビゲーターの構成

今回の実装では、 [React Navigation](https://reactnavigation.org/) を使っています。
バージョンは v5 です。

スライドメニュー（Drawer）、ポップアップ画面はタブメニューに覆いかぶさる形で実装したいので、
DrawerNavigator > StackNavigator > TabNavigator となる構成で実装します。

それぞれの中身を見ていきます。

### DrawerNavigator

```tsx
const DrawerNavigator = () => {
  return (
    <Drawer.Navigator
      drawerContent={() => (
        <View style={styles.container}>
          <Text>Drawer</Text>
        </View>
      )}
    >
      <Drawer.Screen name="StackNavigator" component={StackNavigator} />
    </Drawer.Navigator>
  );
};
```

スクリーンは１つのみの定義で、`StackNavigator`を呼び出しています。
これにより、自動的に`StackNavigator`の内容が表示されます。

Drawer の表示内容は、`drawerContent`に定義します。

### StackNavigator

```tsx
const StackNavigator = () => {
  const navigation = useNavigation();
  return (
    <Stack.Navigator mode="modal" headerMode="screen">
      <Stack.Screen
        name="TabNavigator"
        component={TabNavigator}
        options={{ headerShown: false }}
      />
      <Stack.Screen
        name="ModalScreen"
        component={ModalScreen}
        options={{
          headerLeft: () => (
            <HeaderBackButton
              labelVisible={false}
              backImage={() => (
                <View style={{ paddingHorizontal: 8 }}>
                  <Icon name="md-close" style={{ fontSize: 18 }} />
                </View>
              )}
              onPress={() => navigation.goBack()}
            />
          ),
        }}
      />
    </Stack.Navigator>
  );
};
```

`TabNavigator`とポップアップ画面を定義しています。
`mode="modal"`の場合は下から浮き上がる形で、`mode="card"`の場合は右から押し出すように画面が挿入されます。

`TabNavigator`と同階層に`ModalScreen`を配置することで、ポップアップ画面がタブに隠れないようにしています。

### TabNavigator

```tsx
const TabNavigator = () => {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Tab1" component={TabScreen1} />
      <Tab.Screen name="Tab2" component={TabScreen2} />
      <Tab.Screen name="Tab3" component={TabScreen3} />
    </Tab.Navigator>
  );
};
```

### アプリからの呼び出し

```tsx

const App: React.FunctionComponent = () => {
  return (
    <NavigationContainer>
      <DrawerNavigator />
    </NavigationContainer>
  );
};
```

`NavigationContainer`の子要素として、`DrawerNavigator`を呼び出します。
これで完成です。


# おわりに
React Navigation では、どちらの Navigator を上位にするかで挙動が異なります。

今回紹介したように、覆いかぶさるポップアップ画面も実装できますし、一方で選択タブ内で詳細画面などの別画面を表示することも可能です。（その場合はタブメニューが隠れない）

どのような画面構成にしたいかを設計し、どのページをどのナビゲーターに配置するかを考える必要があります。


今回は、簡単ではありますがその実装方法について紹介しました。
不明点や間違いなどがありましたらコメントお願いします。

ここまで読んでいただき、ありがとうございました。
React Nativeのリリース時にビルドエラーになった際のTips

# はじめに
iOSリリースしようとしたら色々とエラーになったので、その際の解決方法をまとめておきます。

# DoubleConversion関連
ios/buildを削除するといけるようになります。
ダメならPodsとかも全部削除してやり直せばいつか出来ます。

# node関連
nodeの管理方法によってはnodeが読み込めなくてエラーという事象が発生します。
下記のコマンドで見える場所でシンボリックリンクを貼ると先に進めます。

``` sh
ln -s $(which node) /usr/local/bin/node
```

# IPod関連
App -> Build Phase -> Link Binary With Librariesにいらないリンクが残っているせいなので、

# 終わりに
他にも出てきたら追記していきます。
OANDA REST APIを使用したFXデータ収集

# モチベーション
FXを対象とした自動売買botを作成する際に、どのような戦略で自動売買をしようか考える必要があります。
そしてその戦略はどの程度のパフォーマンスであるかを評価されなければいけません。
この記事では戦略のパフォーマンスチェックのためにOANDA REST APIを使用したFXデータの収集方法について、備忘も兼ねて記載します。

# やりかた
## 1. OANDAの登録
OANDA REST APIはOandaというFX業者が公開しているAPI群のことを指します。
FXのAPIを公開している業者は非常に少なく、またネット上にある情報量を考慮するとFXに関するAPIはOANDA REST APIを使用するのが良いと思います。
APIを使用するにはOANDAに登録し、APIキーを発行して貰う必要があります。
下記のリンクから5分くらいで登録できます

[OANDA JAPAN](https://www.oanda.jp/)

## 2. oandapyV20のインストール
OANDAに登録し、APIキーが払い出されたら次はAPIを叩く環境を作りましょう。
APIキーは別ファイルに出しておくと便利です。

```python

pip install oandapyV20
```

oanda_access_key.py

```python 

ACCOUNT_ID = "xxxxxxxxxxx"
PERSONAL_ACCESS_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```

instruments_candles.py

```python

from oandapyV20.endpoints.instruments import InstrumentsCandles
import oandapyV20
import oanda_access_key as oak

account_id = oak.ACCOUNT_ID
access_token = oak.PERSONAL_ACCESS_TOKEN

api = oandapyV20.API(access_token = access_token, environment = "practice")
```

## 3. データ取得
過去データを取得するにはInstrumentsCandlesを使用します。
[公式ドキュメント](http://developer.oanda.com/rest-live-v20/instrument-ep/)
[oandapyV20のドキュメント](https://oanda-api-v20.readthedocs.io/en/latest/endpoints/instruments/instrumentlist.html)
ざっくり、15分足のデータを取得してデータフレームに突っ込むサンプルです↓
あとはDBに突っ込むなりそのままデータを使用するなり、自由に調理できます。

```python

ic = InstrumentsCandles(
		instrument="USD_JPY", # 通貨ペアを選択
		params={
			"granularity": "M15", # ロウソク足の種類を選択
			"alignmentTimezone": "Japan", # タイムゾーン
			# "count": 5000 # 取得するデータ件数、from-toを指定する場合はcountは指定しない
			"from": start_datetime.strftime(datetime_format),
			"to": (start_datetime + relativedelta(days=date_window) - relativedelta(seconds=1)).strftime(datetime_format)
		}
	)
api.request(ic)
data = []
for candle in ic.response["candles"]:
	data.append(
		[
			candle['time'],
			candle['volume'],
			candle['mid']['o'],
			candle['mid']['h'],
			candle['mid']['l'],
			candle['mid']['c']
		]
	)
df = pd.DataFrame(data)
```
Pythonで毎日AtCoder #12

### はじめに
[前回](https://qiita.com/taxfree_python/items/3c701ec674d86251c8ce)
今日はAGCがあるから書かなくていいかなと思っていたら、一問も解けなかったので書きます。最近はAGC-Aとかもレコメンドに出てくるので疲れる。

### #12
[問題](https://atcoder.jp/contests/agc041/tasks/agc041_a)
1WA。参加したけど解けなかった問題

**考えたこと**
まず考えるのは$B-A$が偶数のときで、偶数のときは$\frac{B-A}{2}$でよい。問題は、$B-A$が奇数のとき。$B-A$が奇数のときはどれだけ近くなっても同卓できることはない。なのでどちらかが1またはNに行って偶奇を調整しなければならない。当然、1、Nに近い方がそれぞれに行った方が同卓するまでの回数は減るので$min(a-1,n-b)$でどちらが近いかを求める。a-1しているのは、卓の数字は1から始まっているから。1、Nまで行くと偶奇を調整するために+1、$B-A-1$が偶数になったので$\frac{B-A-1}{2}$すればよい。

```python
n, a, b = map(int,input().split())

d = b - a
if d % 2 == 0:
    print(d//2)
else:
    print(min(a-1,n-b)+1+(b-a-1)//2)
```
ifで偶奇の判断をして、後は上に書いた通りに計算している。

### まとめ
AGC-Aは難しい。明日のABCは取り敢えずA~Cの三完を目指す!!
では、また。おやすみなさい。
Bondingを確認する

## モードを確認する

```
[root@coffee01 ~]# cat /sys/class/net/bond0/bonding/mode
balance-alb 6
```

## アクティブなNICを確認する

```
[root@coffee01 ~]# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)

Bonding Mode: adaptive load balancing
Primary Slave: None
Currently Active Slave: eno1
MII Status: up
MII Polling Interval (ms): 100
Up Delay (ms): 0
Down Delay (ms): 0

Slave Interface: eno1
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 0c:c4:7a:4a:a3:48
Slave queue ID: 0

Slave Interface: eno2
MII Status: up
Speed: 1000 Mbps
Duplex: full
Link Failure Count: 0
Permanent HW addr: 0c:c4:7a:4a:a3:49
Slave queue ID: 0
```
CentOS8 で virsh console を設定する

### 1. /etc/default/grub の編集

`/etc/default/grub`の`GRUB_CMDLINE_LINUX=`行の最後に`console=tty0 console=ttyS0,115200n8`を追加する。

```
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto resume=/dev/mapper/cl-swap rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet console=tty0 console=ttyS0,115200n8"
GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
```

### 2. grub.cfg を再生成する

`$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg`

### 3. 仮想マシンを再起動させる

### 4. 早速、virsh consoleを使ってみる
`$ virsh console <ホスト名>`
simulator で動画キャプチャを取ろうとした時にエラーが出る

iOS simulator で動画キャプチャを撮る場合、以下のコマンドで実現できます。

```sh
$ xcrun simctl io booted recordVideo output.mp4
```

ある時、開発中の動作をキャプチャしようとしたら、以下のようなエラーに直面しました。
![Screen Shot 2020-03-21 at 10.10.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43625/ee59c255-dfb3-7ff0-b0d0-2bf666dda166.png)

[Stackoverflow](https://stackoverflow.com/questions/57947643/app-preview-recording-with-ios-simulator-cause-nsposixerrordomain-with-code-22-e) で、同じ悩みに直面している人を発見。
どうやら Xcode 11 の [known issue](https://developer.apple.com/documentation/xcode_release_notes/xcode_11_release_notes) とのこと。
<img width="531" alt="Screen Shot 2020-03-21 at 10.10.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43625/e7e138ab-8386-226e-a805-c48157f90098.png">

会社で使ってるパソコンではコマンドが正常に動いてたので、 Xcode のバージョンを 11.3.1 にあげてみました。
<img width="642" alt="Screen Shot 2020-03-21 at 21.58.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43625/af60d375-0658-b233-0938-ac0e971b772c.png">

無事、動くようになりました。
![Screen Shot 2020-03-21 at 22.05.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43625/1587eb3e-3daa-0cc8-3fe1-eba82ea8e157.png)



ご参考になれば幸いです。
アプリづくりを通して、感染症を考えてみた ~一人用のケース編~

コロナです。

今日は、過去記事の続編となります。
元記事はこちら
https://qiita.com/sakuriver/items/7d37595c5ac70aa11d4c

## 独身やボッチ利用するときの想定しているシナリオ

通勤や食事、プライベート等々で外を出るときの判断

<img width="454" alt="4f1bcae3b60f7a6c87a1d4f6984c55f1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45396/71269ad1-83df-e4c4-dd36-77bc9697e508.png">

## 個人的な主観

家族でしっかり者がいるときより、一人で利用するときのほうが類似アプリでも
利用できるのではと考えております


## イラストの利用元

https://www.irasutoya.com/search/label/%E4%BC%BC%E9%A1%94%E7%B5%B5