OmniAICreator/Qiita-1.07M huggingface dataset:
Microsoft Flowの Do Untilを使うときに気を付けたいこと

# 今日の投稿背景
承認フローを作成するために、Microsoft Flowを作っていて
多段承認なので、Do Untilとスイッチを活用する事になるわけですが
それに伴いとんでもないことに陥ったので備忘録的に纏めてみました。

# Do Untilとは
指定の条件を満たすまで、処理を繰り返す。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/269159/8421649d-db9a-c478-032d-ce90d97ad82e.png)
当然無限ループに陥らないように、回数制限やタイムアウトをもうけられるようにしてある。

# Do Untilの問題点
## 内部ロジックの処理がエラーを起こしてもループが終了しない。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/269159/1ba93b93-425a-c0e0-a156-0c2fddc6b22a.png)
内部ロジック側でエラーが起きても、Do Until自体は異常終了しないため
同じ処理が繰り返し実行されてしまう。

## エラー発生中に見ることが出来ない
![image.png](https://qiita-image-store.s3.amazonaws.com/0/269159/c87139fd-aa80-b0e5-bcf7-dc5efd669700.png)
実行中にDo Untilの状況を見ることができない為
何が起こっているのかが全く分からない状態になる。

## キャンセルしても見る事が出来ない
![image.png](https://qiita-image-store.s3.amazonaws.com/0/269159/c5492c50-f323-281d-23f4-18d20be31f85.png)
キャンセルしてもDo Untilの中を参照することができない為
何が起こっているのか推測できない。

## Do Until内に強制終了を入れることが出来ない。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/269159/2d13d6b9-bd65-a999-8ef5-a4645f8979dd.png)
調査のために強制終了を割り込まそうとしても、保存が出来ない。

# どうしたらいいのか
Do Untilの回数を1にすると、エラー内容を見ることが出来ます。
Do Untilでいつまで経っても状態が変わらないといった現象に陥った場合は
是非お試し下さい。
ansible-containerのインストール時にエラー

# 問題

ansible-containerをインストールしようした際に、下記のようなエラーが発生。

```
[root@localhost ~]# pip install ansible-container
Collecting ansible-container
  Using cached https://files.pythonhosted.org/packages/bc/2a/b1252de3931173d26a30fc965be33c9cc0044cf7b23ce4c707f55d86830c/ansible-container-0.9.2.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/tmp/pip-install-la0j9y/ansible-container/setup.py", line 10, in <module>
        from pip.req import parse_requirements
    ImportError: No module named req

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-la0j9y/ansible-container/
```

# workAround

* githubのissue
  * [Support for pip 10 - breaking changes introduced.](https://github.com/ansible/ansible-container/issues/919)

* 回避策
「この方法で突破できたぜ！」という意見がいろいろ出ていますが、私の場合は↓のpipのダウングレードでいけました

```
pip install --force-reinstall pip==9.0.3
```

# 所感

* pipのバージョンとansible-containerの相性の問題だろうか？
* ansible-container自体がまだv.1.0にはなってないので、いろいろ起きそう。
ライブラリlodash　よく使うものをまとめておく （バンドルサイズ抑える記述方法も）

#ユーティリティライブラリlodash
[lodash公式サイト](https://lodash.com/docs/)
javascriptで配列・オブジェクトの操作をするときに使うライブラリlodashを使用することが多いので、まとめておく。

cdnも用意されているみたいですので、気軽に使うことができます。

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
```

webpack環境が整っているのであればimportするのも良いです。

```npm
npm install lodash
```

##### lodashすべての関数を使う時
```javascript
import _ from 'lodash';
```

lodashライブラリーは高機能のため、ライブラリすべてを読み込むとコンパイル時にバンドルサイズが肥大化してしまうことが懸念されます。ですので、使いたい機能のみを抜粋する記述も下記に示します。
##### lodash一部の関数を使う時
```javascript
import _delay from 'lodash/delay';
```


本題に戻り、以降はよく使用する機能を紹介していきます。

##._reduce
####使用例
- 　配列の中のある要素で一番大きいものはどれかを検索する

```js
var lists= [
{id:'1',name:'高田',age:35},
{id:'2',name:'山下',age:73},
{id:'3',name:'垣田',age:77},
{id:'4',name:'前島',age:15},
{id:'5',name:'杉嶋',age:25},
];

var aaa = _.reduce(lists,function(a,b){
	return (a > b.age)? a:b.age;
},0);

console.log(aaa);
//オブジェクト{id:'3',name:'垣田',age:77}を返す
```

####使用例
- 　配列の中のある要素の合計値を計算する

```js
var lists= [
{id:'1',name:'高田',age:35},
{id:'2',name:'山下',age:73},
{id:'3',name:'垣田',age:77},
{id:'4',name:'前島',age:15},
{id:'5',name:'杉嶋',age:25},
];

var aaa2 = _.reduce(lists,function(result, value){
	return result + value.age;
},0);

console.log(aaa2);
//225を返す

```

##_.orderBy
####使用例
- 　配列の中のある要素を降順、昇順に設定する。

```js
var lists= [
{id:'1',name:'高田',age:35},
{id:'2',name:'会田',age:77},
{id:'3',name:'垣田',age:77},
{id:'4',name:'前島',age:15},
{id:'5',name:'杉嶋',age:25},
];

var ord = _.orderBy(lists,'age','desc');
console.log(ord);
//ageで降順に並べ替えられた配列

```


####使用例
- 　要素を2つ選択して降順、昇順に設定する。

```js
var lists= [
{id:1,name:'高田',age:35},
{id:2,name:'山下',age:77},
{id:3,name:'垣田',age:77},
{id:4,name:'前島',age:15},
{id:5,name:'杉嶋',age:25},
];
var ord2 = _.orderBy(lists, ['age', 'id'], ['desc', 'desc']);
console.log(ord2);
```


##_.delay
####使用例
- 　◯◯秒間遅らせて、実行をする

```json
console.log("何もしないで実行");

_.delay(function() {
    console.log("lodashで実行を遅らせる");
}, 3000, 'later');
//秒数は好きな時間を記述できる

```
Mbed OSで複数のスレッドからのmailを待つ方法

# 開発環境

IDE：e2studio
マイコンボード：GR-LYCHEE
使用OS：Mbed OS

# 結論
複数のスレッドから異なる型のmailを送る方法が分からなかったので、
試行錯誤してみた結果、できた。

共用体は使っても使わなくてもどっちでもいいけど、
メモリ節約のためには使ったほうがいい。

本当にこの実装でいいのかは、検証が必要。

# 仕様

mailを送信するスレッドは、下記3スレッド。
それぞれ、異なる型のmailを送信している。

- send_thread
- send_thread2
- send_thread3

mailを受信待ちするスレッドは、下記スレッド。

- receive_thread


send_thread・send_thread2・send_thread3
のうち、どのスレッドがmailを送信してきたかは、
mail_typeで識別している。

#コード


```cpp:main.cpp
#include "mbed.h"

Serial pc(USBTX, USBRX);

typedef struct {
	uint32_t count1;
	uint32_t count2;
	uint32_t count3;
	uint32_t count4;
} a_mail_t;

typedef struct {
	uint8_t count13;
	uint8_t count14;
	uint8_t count15;
} b_mail_t;

typedef struct {
	char *msg;
} c_mail_t;

/* Mail */
typedef struct {
	uint32_t mail_type;
	union {
		a_mail_t a_mail;
		b_mail_t b_mail;
		c_mail_t c_mail;
	};
} mail_t;

Mail<mail_t, 32> mail_box;
Thread thread;
Thread thread2;
Thread thread3;
Thread thread4;

void send_thread3(void) {
	int i = 0;
	while (true) {
		i++;
		mail_t *mail = mail_box.alloc();
		mail->mail_type = 3;
		if (i % 2) {
			mail->c_mail.msg = "aaaaaaa";
		} else {
			mail->c_mail.msg = "bbbbbbb";
		}
		mail_box.put(mail);
		Thread::wait(3000);
	}
}

void send_thread(void) {
	uint32_t i = 3000000;
	while (true) {
		i++; // fake data update
		mail_t *mail = mail_box.alloc();
		mail->mail_type = 1;
		mail->a_mail.count1 = i;
		mail->a_mail.count2 = i * 2;
		mail->a_mail.count3 = i + 2;
		mail->a_mail.count4 = i % 6;
		mail_box.put(mail);
		Thread::wait(500);
	}
}

void send_thread2(void) {
	uint32_t i = 0;
	while (true) {
		i++; // fake data update
		mail_t *mail = mail_box.alloc();
		mail->mail_type = 2;
		mail->b_mail.count13 = i;
		mail->b_mail.count14 = i % 3;
		mail->b_mail.count15 = i * 5;
		mail_box.put(mail);
		Thread::wait(1000);
	}
}

void receive_thread(void) {
	while (true) {
		osEvent evt = mail_box.get();
		if (evt.status == osEventMail) {
			mail_t *mail = (mail_t *) evt.value.p;

			if (mail->mail_type == 1) {
				pc.printf("mail_type%d:%d,%d,%d,%d\n", mail->mail_type,
						mail->a_mail.count1, mail->a_mail.count2,
						mail->a_mail.count3, mail->a_mail.count4);
			} else if (mail->mail_type == 2) {
				pc.printf("mail_type%d:%d,%d,%d\n", mail->mail_type,
						mail->b_mail.count13, mail->b_mail.count14,
						mail->b_mail.count15);
			} else if (mail->mail_type == 3) {
				pc.printf("mail_type%d:%s\n", mail->mail_type,
						mail->c_mail.msg);
			}
			mail_box.free(mail);
		}
	}
}

int main(void) {
	thread.start(send_thread);
	thread2.start(send_thread2);
	thread3.start(send_thread3);
	thread4.start(receive_thread);

	while (true) {

	}
}

```
ansibleで登場する概念的なやつの個人的メモ


# これは何？
私の技術メモです。

# 概要
 * ansibleホストから管理したいサーバやサーバ群に対して自由に操作を発行できる
 * 構成管理ツールというよりサーバに関わる定例作業やシステム関連のタスクの自動化ツールといったほうが良い印象
 * 構成管理される側にはansible用に特別なものが必要ない・エージェントレス
 * 冪等性

## 前提
 * ホスト、管理対象サーバ共にpythonは必要
 * ansibleの管理サーバから管理対象のサーバへはssh接続可能であること

## 構成要素
 * hosts(inventory)
     * ansibleで管理対象とするサーバやサーバをグループ化した定義を書く
     * `ansible-playbook`のdefault実行時の参照場所は`/etc/ansible/hosts`
 * ansible.cfg
     * inventoryの位置を指定したり、対象ホストによって読み替える必要のある設定を書く
 * playbook
     * どのホストにどのモジュールを実行するかの組み合わせ
     * yaml形式
     * play領域
         * hosts
         * remote_user : 操作実行ユーザ
         * become : sudo実行
         * order : hostsへの実行順序。デフォルトはinventoryの定義順
         * vars : 変数宣言し、{{変数名}}で呼べるようにする
         * tasks
             * task領域 : taskを並べて書く。基本的は`-name+module`の組み合わせ
             * task領域だけを別ファイルに切り出してincludeすることもできるらしい
                 * name : タスク名
                 * module : モジュール
                 * notify : このタスクで何らかの変更があると、`handlers`を実行
         * handlers
             * taskの`notify`でなんらかの変更が行われると、最後に一回だけ呼ばれる
             * notifyで変更が無かった場合は実行されない

## モジュール
 * tasksに設定されるモジュール。
     * user
     * yum
     * service
     * file
     * copy
     * with_items : 他のモジュールと併用する。あるモジュールに渡す`name`を複数並べて記載することで冗長な表現を避けられる
     * notify
     * mysql_db
     * mysql_user
     * ini_file : ファイル編集
     * shell : 既存のモジュールで対応できない場合にshellを書く
     * unarchive
     * get_url
 
## role
 * 役割をできるだけ最小単位にして定義する。例：ミドルウェア単位とか
 * rolesディレクトリ配下に、role毎に名付けたディレクトリを切る。各々が`main.yml`を持つ
 * メインとなるplaybookから、基本的なroleについてはこれらが呼ばれてあてがわれる
     * tasks
         * 必須。taskの定義
     * files
         * copyでセットアップされるファイルを配置
     * templates
         * templateでセットアップされるテキストファイルを配置
     * vars
         * 変数を定義します。 基本的に環境毎に変わる固定値など
     * defaults
         * 変数の初期値。
     * handlers
         * 特定taskに対してnotifyし、実行したいイベント
     * meta
        * Roleのメタ情報。roleの依存関係？

## (コマンド)ansible-playbook
 * playbookをもとに実行する、ansibleの核となるコマンド
 * オプション
     * --syntax-check : 記法のチェック
     * --list-task : taskの一覧を表示
     * --check : 実際には変更しない、どうなるかをシミュレートする
         * --check -v : デバッグ的な情報を表示する。vを重ねる度に詳細になる
"myCAMELCase" から "my", "CAMEL", "Case" を抽出する正規表現

Elasticsearch の [Pattern Capture Token Filter](https://www.elastic.co/guide/en/elasticsearch/reference/6.5/analysis-pattern-capture-tokenfilter.html) で欲しくなったので書いた。

# TL;DR
```
/([a-z]+)|([A-Z][a-z]+)|([A-Z]+)(?=[A-Z])/g
```

（A-z の範囲外を扱う場合は `[A-Z]`, `[a-z]` の代わりに `\p{Lu}` （対応する小文字がある大文字）、 `\p{Ll}` （対応する大文字がある小文字）を使うほうが適切なケースもある）

# 解説
```
/
  ([a-z]+)       # 小文字の連続 (my)
| ([A-Z][a-z]+)  # 大文字に続く小文字の連続 (Case)
| ([[A-Z]+)      # 大文字に続く大文字の連続 (CAMEL)
  (?=[A-Z])      #   最後の連続する大文字はマッチせず、また消費しない（先読み）
/g
```

- `/([a-z]+)|([A-Z][a-z]+)|[A-Z]+/g` だと、`"MyAPIDocs"` からは `"My"`, `"APID"`, `"ocs"` のような結果が得られてしまう（Docs の D まで食われてしまう）
- そこで、大文字の連続のキャプチャグループ `([[A-Z]+)` の後ろに `[A-Z]` をひとつだけ置いておくことで最後の大文字（上の例ならば Docs の D）にマッチさせず、またそれを肯定先読み (positive lookahead) `(?=)` にしておくことで、消費もさせない
ライブラリの使い方

ライブラリを自分のプロジェクトで使う手順です。
[ライブラリの作り方](https://qiita.com/matsujirushi/items/dc246c200f11e2c1d485)で作ったLibrary1を使用します。

# プロジェクトを作る

新しいソリューションとライブラリを呼び出すアプリケーションのプロジェクトを作成します。
プロジェクトテンプレートはBlank Application for MT3620 RDBを選んでください。

**ファイル > 新規作成 > プロジェクト**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/9cd548ba-ac00-b8bd-d4af-c60edc5ea662.png)

# ライブラリのファイルをコピー

ライブラリのヘッダファイルとアーカイブファイルを、任意のフォルダにコピーしてください。
ここでは、ソリューションフォルダにlibフォルダを作って、そこにコピーしました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/4522066b-7e2a-9c5a-2dc9-24caaeb3322c.png)

# プロジェクトからライブラリを参照

プロジェクトに、ライブラリへの参照を設定します。
これは、ヘッダファイルのフォルダ指定と、アーカイブファイル指定の２つをやる必要があります。

## ヘッダファイルのフォルダ指定

プロジェクトのプロパティを開いて、Additional Include Directoriesにヘッダファイルのフォルダを追加します。

**プロジェクト > プロパティ、　構成プロパティ > C/C++ > General > Additional Include Directories**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/7d167ac0-f4bc-535e-dcdf-d87d5fa85f11.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/1e0a48fe-54d0-8b3b-98c0-02c173c3489a.png)
> 絶対フォルダ名の代わりに、`$(SolutionDir)`マクロで指定しています。

## アーカイブファイル指定

プロジェクトのプロパティを開いて、Additional Dependenciesにアーカイブファイルを追加します。

**プロジェクト > プロパティ、　構成プロパティ > Linker > Input > Additional Dependencies**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/82746230-9f15-23ef-a7b5-33a8e985728d.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/cebf06af-8f40-84bf-794e-0cfcb210ea2e.png)
> 絶対フォルダ名の代わりに、`$(SolutionDir)`マクロで指定しています。

# アプリケーションからライブラリを呼び出す

```c:main.c(断片)
...
#include <Library1.h>
...
int main(int argc, char *argv[])
{
...
    // Main loop
    const struct timespec sleepTime = {1, 0};
	int val = 0;
    while (!terminationRequired) {
        Log_Debug("%d %d\n", val, pow2(val));
		val++;
        nanosleep(&sleepTime, NULL);
    }
...
}
```

# 実行結果

![image.png](https://qiita-image-store.s3.amazonaws.com/0/109634/a5f07c59-b662-ebb1-5f96-058eb3f05aa9.png)
グラフ問題色々

ダイクストラ法→残っている頂点の中から、始点からの距離が最も小さいものを選んでその頂点から1辺を通っていける頂点の距離を更新する。

```
d[I]=(始点から頂点Iへの最短距離)
```
となるように意図する。簡単のため始点は頂点０としよう。初期化はd[0]=0,d[I]=INF(I!=0)としておく。

ベルマンフォード法→ダイクストラ法と同じく単一始点経路問題に有効だがベルマンフォード法は負の経路を持っていてもよいダイクストラ法が頂点に注目していたのに対しベルマンフォード法では辺に着目する。つまり、辺についてのループである。上と同じようにd[I]を定義する。初期化も同様。

```
d[I]=(始点から頂点Iへの最短距離)
```
辺を向き付けして辺e,頂点I,頂点jが下のような関係だとしよう。
(頂点I)....(辺e)....>(頂点j)
この時、dが更新できそうな頂点はjである。
すでにそれまでに計算してあるd[j]よりも、d[I]+eのコストが小さければ、d[j]を更新できる。

```
if(d[j]>d[I]+eのコスト)
   d[j]=d[I]+eのコスト
```

ワーシャルフロイド法→シンプルな三重ループのアルゴリズムであるが、計算時間がo(V^3)になるので頂点の数が200以下など少ないときにだけ使える。頂点についての動的計画法である。

```
d[I][j]=(頂点Iとjの最短距離)
```

もしも頂点Iとjを結ぶ最短経路は別の頂点kを通るか、通らないかのどちらかである。この事実について考えるともしも頂点Iと頂点jを結ぶ最短経路が頂点kを通るなら次の等式が成立する。

```
d[I][j]==d[I][k]+d[k][j]
```
改めて以下のように考える。

```
d[I][j][k]=(頂点０から頂点kまでだけを通ってよいときの頂点Iとjの最短距離
```

```
d[I][j][k]=min(d[I][j][k-1],d[I][k][k-1]+d[k][j][k-1])
```

例題
来春卒業するAさんは、就職を機に引越しをすることにしました。就職する会社は、オフィスがいくつかの町にあって、日によって出勤するオフィスが違います。そこでAさんは,どこのオフィスに 行くにも時間の短い町に住もうと考えました。 
そこであなたは、Aさんを助けるため、住むのに一番便利な町を探すことになりました。 
町には 0 から始まる番号が振られており、町と町の間には道があります。それぞれの道に対して通勤時間が決まっています。Aさんがある町に住んでいる場合に、自分の町のオフィスまでの通勤時間は 0 とします。このときに全ての町までの通勤時間の総和を考えます。道の数と、全ての道の情報を入力とし、それぞれの町に住んだ場合の通勤時間の総和を計算し、それが最小となる町の番号と、そのときの通勤時間の総和を出力するプログラムを作成してください。ただし、通勤時間の総和が最小となる町が複数ある場合は、一番小さい町の番号及びその時の通勤時間の総和を出力してください。町の総数は 10 以下、道の総数は 45 以下とし、全ての道は双方向に移動でき、通勤時間は方向によって変わらないものとします。また、どの町からでもその他全ての町への 経路があるものとします。 １行目に道の数 n (1 ≤ n ≤ 45) が与えられます。続く n 行に i 番目の道の情報が与えられます。 ai, bi (0 ≤ ai, bi ≤ 9) は i 番目の道がつないでいる町の番号、ci (0 ≤ ci ≤ 100) はその道の通勤時間を表します。 

```
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<list>
#include<cmath>
#include<map>
#include<queue>
#define F first
#define S second
#define mp make_pair
#define pb push_back
using namespace std;
using ll = long long;
using T = tuple<ll, int, int>;
const int INF = 1e9;
#define rep(i,n)for(int i=0;i<(n);++i)
#define p pair<int,int>
struct edge { int from, to, cost; };
edge es[45];
vector<int>G[10];
int dp[10][10];
int V;
int main() {
	cin >> V;
	rep(i, V)rep(j, V) {
		dp[i][j] = INF;
	}
	for (int i = 0; i < V; ++i) {
		int a, b, c;
		cin >> a >> b >> c;
		dp[a][b] = c;
		dp[b][a] = c;
	}
	for (int i = 0; i < V; ++i) {
		for (int j = 0; j < V; ++j) {
			for (int k = 0; k < V; ++k) {
				dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
			}
		}
	}
	int sum[10];
	for (int i = 0; i < V; ++i) {
		sum[i] = 0;
		for (int j = 0; j < V; ++j) {
			if (i != j && dp[i][j] != INF) {
				sum[i] += dp[i][j];
			}
		}
	}
	int ans_i = 0;
	for (int i = 1; i < V; ++i) {
		if (sum[i] < sum[ans_i] && sum[i] != 0) {
			ans_i = i;
		}
	}
	cout << ans_i << " " << sum[ans_i] << endl;
	return 0;
}
```

例題２
N頭の牛がいて、映画の「共演距離」を考える。まず、自分自身との共演距離は0である。ひとつの映画で牛iと牛jが共演していたら、牛iと牛jの共演距離は1である。また、牛iと牛jがどの映画でも共演していないが、牛iと牛kがひとつの映画で共演していて、牛kと牛jが別の映画で共演していれば、共演距離は2である。共演距離3,4,...も同様に定める。
ほかの牛たちとの共演距離の平均が最小となる牛について、その平均を100倍した整数を出力せよ。
2 <= N <= 300
1 <= M <= 10000 (Mは映画の本数)
RxJSハマりポイント（初心者向け）

# はじめに
Angularを使っているとRxJSは避けて通れないと思いますが、
初めて使った時にそれなりに戸惑ったので、
役にたつかわかりませんが、自分が理解でハマったポイントをまとめようと思います。

※解説記事ではありません。

# バージョンの違い
RxJSはバージョン6.0から各関数のインポートパスが変更になっています。
[RxJS 6.0 変更点まとめ（適宜更新）](https://qiita.com/ponday/items/7966787fa0bc8f3e2dde)

自分が関わったプロジェクトではバージョン6.xを使っているのですが、
6.xは現行のバージョン（2018/11/20時点）で新しいため、検索すると当然6.0よりも前のバージョンの記事の方が多くヒットします。
ここで6.x以降と6.0より前では記述の仕方がかなり違うため、戸惑いました。（調べた書き方では全然動かない）
調べるときはバージョンに気をつけましょう。

（今考えればバージョンくらいちゃんと気にしろよと過去の自分に言いたいですが、
当初はそこまで考えが回っておらず、結局ライブラリの中身を見渡してみてどうやらバージョン違いのようだというとこで自分の中では落ち着きました。）

この件以外にも言えますが、破壊的変更が加わるバージョンアップにはちゃんと気をつけておきたい。。。。（PHPとかPHPとかPHPとか。。。）

# Observable? Observer? Stream?
新しい概念を表すには当然それを表す用語が必要なのはわかりますが、急にいろんな単語が出てきて困りました。
概念自体が多少抽象的（？）なので、調べてみてもふわっとした感じの解説が多い印象。
Observerパターンというデザインパターンがもとになっています。
結局自分でガシガシ実験してみて体感的に理解しました。
結果、これが一番の近道だったと思います。

いろんな解説サイトを回るよりも自分で試すのが一番！
なのですが、参考は必要なので自分的に理解の助けになったサイトをいくつか載せておきます。
[Reactive Extensionsのはじめかた](https://blog.okazuki.jp/entry/2015/03/23/203825)
[Practical RxJS In The Wild 🦁— Requests with concatMap() vs mergeMap() vs forkJoin() 🥊](https://blog.angularindepth.com/practical-rxjs-in-the-wild-requests-with-concatmap-vs-mergemap-vs-forkjoin-11e5b2efe293)
[Learn to combine RxJs sequences with super intuitive interactive diagrams](https://blog.angularindepth.com/learn-to-combine-rxjs-sequences-with-super-intuitive-interactive-diagrams-20fce8e6511)
[RxJS Operators for Dummies: forkJoin, zip, combineLatest, withLatestFrom](https://scotch.io/tutorials/rxjs-operators-for-dummies-forkjoin-zip-combinelatest-withlatestfrom)

# なんとなく理解したあたりで登場するSubject
ObservableかつOvserverな奴。
しかもHotとColdという違いもあるらしい。
わかってきたなーと思いはじめたあたりでSubjectの概念が登場して「どういうこと？」となりました。
わかってしまえば単純なのだけれど、混乱のもとになったのは確か。。。

最初はSubjectについてはあまり触れない方がいいかもしれない（？）

# たくさんあるoperator
RxJSにはof()やfrom()、timer()などのObservableを生成する関数の他に、
ストリームに流れてくる値を加工するためのoperatorと呼ばれる関数がありますが、
この数がまた多い。。。
普段使うものはそんなに多くないのですが、複数のストリームを扱ったりしようとする場合は様々なoperatorを使う必要が出て、それぞれの動きを理解するのがちょっと大変になります。
とりあえずはmapやfilter、mergeMapなどの基本的なものに絞って覚えるのが良いと思います。

# まとめ
色々書きましたが、Rxは概念さえ覚えてしまえばストリームを自在に操ることができるようになって便利です。
この記事がRxJSを初めて使う人の役に立てば幸いです。
Asus T100-HAにWindows10をクリーンインストール

##経緯
Thnikpadを買ってから1年半ほどT100-HAを使ってなかった。
久しぶりに電源を入れると、バージョンが古すぎてWindowsUpdateができなくなっていた。:cry:
Windows10 2018 October Updateが出たのを機会にクリーンインストールを実行。

##インストーラ準備
###インストーラ作成ツールのダウンロード
###ツールを実行しインストールUSB作成
USBとISOが選択できるが、今回USBを利用

##クリーンインストール

###USBを接続
###電源ON
###そのままだとUSBから起動できないのでBIOSでBootを変更
1. F2でBIOS画面に入る
2. 「Save & Exit」タブの「Override Boot」でUSBを選択しENTER

###セットアップ
2in1なので、縦長画面(90度回転)になって、マウス操作がやりにくい。
画面タッチもきかないのでトラックパッドでなんとか操作する。
デフォルトでLANが認識しないのでMicrosoftアカウントが使えない。ローカルアカウントを利用
1. そのまま次へ
2. 今すぐインストール
3. ライセンスに同意して次へ
4. カスタム
5. インストール場所は領域を全部削除してから割り当てられてない領域を指定
6. インストールが始まり自動的に再起動
7. 地域を指定（日本）
8. キーボードレイアウトを指定（IME）
9. ネットワーク接続をスキップ
10. ユーザ名を指定。パスワードはなし
11. Cortanaを拒否
12. アクティビティの教育はいいえ
13. プライバシーはとりあえずデフォルトで同意

##ドライバインストール
###Asusのホームページよりドライバ群をダウンロードし解凍しておく
外付HDDに入れておき接続
###チップセットドライバをインストール
　SOCPacageなんとかのSetup.exeを実行。画面に従いインストール。
　インストールの最後で画面が横になうる。
　Finishをクリックすると再起動

###ATK(多分Asustekの略)ドライバ
　ファンクションキーを使った画面輝度の変更はこのドライバが必要
　Setup.exeを実行。途中で画面が180度回転する。
　再起動。回転角度を設定し戻す。。。
　起動の毎に画面が回転するのでアンインストール。。。
###Asus Smaart Gestureドライバ
　タッチパッドの設定に必要。
　Setup.exeを実行。再起動。

##Microsoftアカウントに変更
###ユーザ変更
　設定＞アカウント＞ユーザーの情報から、「Microsoftアカウントでのサインインに切り替える」
　OneDriveの設定はしない。PINを設定。
　本人確認を実施。
　ライセンスが自動認証される。
　再インストール前もMicrosoftアカウントで実行していたため。
　認証後にローカルアカウントに変更しても問題なし

♯#Windows Update
結構ある。Display DriverのUpdateも。
コンビニで買った育てるサラダをrasPiで撮ってKinesisに流してゴニョゴニョする 後編

さて、都合により後編が3つに分かれてしまいましたがいよいよこれで最後となります。

[コンビニで買った育てるサラダをrasPiで撮ってKinesisに流してゴニョゴニョする 前編](https://qiita.com/ikegam1/items/0785b1723f2ae6ea310b)
[中編](https://qiita.com/ikegam1/items/64bb55704cf94891a9ce)
[後の前編](https://qiita.com/ikegam1/items/a6a01d3c1475d06ed956)
[後の中編](https://qiita.com/ikegam1/items/115b5929be146b82a556)

##これまでのあらすじ
### 前編
使ってなかったラズパイを引っ張り出してきてみて、kinesis video stream設定して、c++のsdkを落としてきてビルドしてみるとこまで

### 中編
kinesis vieo streamのプロデューサーSDKを使ってkinesis video streamにラズパイから動画を流す所まで。・・を試行錯誤しながら。

### 後の前～中編
フロントエンド部分。cognito設定して、vuejsのプロジェクト作って、lambda関数とapi gatewayを設定して、s3やcroudfrontも使う。cognite <-> api gateway <-> lambdaのあたりでけっこう時間を取られたが、kinesis video streamのエンドポイントが取得できるとこまではできた。

## そんなわけで後編

あとは、kvs(kinesis vieo stream)のエンドポイントからURLを取らなくちゃいけなかったっぽいのでそれをやるのと、取得したURLをフロントでvideoJs使って流すだけ。再生と停止ぐらいができればそれでいい。何気にSPAです。(←ただ機能が少ないだけ）

### まずはkvsのhlsストリーミング用のURL

難しい事は特にない。lambda関数に少し追記して返却値をストリーミング用のURLにします。
使うのはこれ
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/kinesis-video-archived-media.html#KinesisVideoArchivedMedia.Client.get_hls_streaming_session_url

```Python：app.py
        kvam = boto3.client('kinesis-video-archived-media',endpoint_url=endpoint.get('DataEndpoint'))
        url = kvam.get_hls_streaming_session_url(
            StreamARN=streamarn,
            PlaybackMode="LIVE"
        )
```

こんな感じでURL取れた。あとは再生するだけ。

### あとは再生するだけ

こんな感じでやりたい

[[小ネタ] Video.jsのvideojs-contrib-hlsを使ってHLS形式のライブ配信を再生する最低限度の設定](https://dev.classmethod.jp/client-side/javascript/videojs-contrib-hls-livestreaming-minimum-setting/)

でもvue.jsで動かすのでちょっと変更がいる
このあたりをインスパイアさせていただく。
https://github.com/savokiss/vue-videojs-demo/tree/master/src

```
$ npm install --save video.js
$ npm install --save videojs-contrib-hls.js
```

で、だいたいできたかなってあたりでVIDEOJSに ```VIDEOJS: ERROR: (CODE:4 MEDIA_ERR_SRC_NOT_SUPPORTED) No compatible source was found for this media.```っていわれる。対応してない系？

確かにこのページにURLぶっこんでみてもダメだ。
http://savokiss.me/vue-videojs-demo/#/

で、試しにCDNのjsをダイレクトで使ってみると再生できた。
使ってみたcdn( https://vjs.zencdn.net/6.6.3/video.js ) のは6.6.3で、npmだと7.3.1とかになる。むしろnpmの方が新しい。
videojs-contrib-hlsの方はというとnpmだと3.2.0、cndの方は5.14.1でnpmが古い。

あ、なんだ。こっちにすればいいのか。

```
$ npm install --save videojs-contrib-hls
```

こっちにするとver5.15.1になって無事再生されました。video.jsの方はvideojsっていうパッケージがあったけどこっちはver1.0.0だった。みたら ```This is not the official video.js package. Please use video.js.``` って書いてあったけど。

なんにせよ、いけました！

![21.png](https://qiita-image-store.s3.amazonaws.com/0/308709/1663189d-6fb0-d18f-4dd0-a40efbc31a42.png)

サラダ、ぼちぼち育ってます。
画質は悪いし、ラズパイはたまに固まりますけどね。。
ちなみにカメラはラズパイ用のを発注済。

動けばいいって程度で突っ走ってるのでかなり無駄はありそうですが、ソースはこちらです。

https://github.com/ikegam1/raspi-kvs-amplify-lambda-frontend
https://github.com/ikegam1/raspi-kvs-amplify-lambda-backend

小さいですが一応、lambdaとvueに分けてあります。

さて、我が家カメをお迎えする準備が整ったぜ。
【iOS】iPadで縮小表示される

## react native/swiftでiPhoneのemulatorだと正常に表示されるが、iPadだと拡大表示されてしまう

Universalアプリになっておらず、iPhone専用アプリになっている。
xcodeのTARGETの設定で、`General` - `Deployment Info`のDevicesを**Universal**にする。

## Universalアプリにすると
scalingが必要になるので、React Nativeならば↓など参考にscalingするがよし。
[Scaling React Native apps for Tablets – React Native Training – Medium](https://medium.com/react-native-training/scaling-react-native-apps-for-tablets-211de8399cf1)

## refs
[iOS - xcodeでのiPad用アプリ開発について｜teratail](https://teratail.com/questions/90619)
【小技】awkコマンドの -vオプションでコマンド実行前に変数を定義する。

##awkコマンドの小技
非同期化やメトリクス監視が進む昨今、15年前くらいのスクリプトを読んで、部活の朝練のごとくコード化を毎朝の日課にしている、パシリみたいな新卒のエンジニアもいると思います。僕です。さて今日は、2000年代に書かれたスクリプトを読んでいて勉強になったことを書きます。

#awkコマンドの-vオプション
今回ご紹介したいのは、awkコマンドの `-vオプション` です。
この `-vオプション` を使えば、変数で取得してきた値の、名前を変えて再利用したりできます。
昔の、メール発砲、監視マネージャのコンソール表示のbodyなんかに使われていました。

###まずは試運転
awkコマンドの-vオプションの使い方は見ればわかる感じのあれのあれなので、とりあえず試運転したものをペタりします。

```
[root@ef16029eef68 test]# test1=10
[root@ef16029eef68 test]# test2=20
[root@ef16029eef68 test]#
[root@ef16029eef68 test]# result=`echo|/bin/awk -v used=$test1 -v max=$test2 '{print int((used / max) * 100)}'`
[root@ef16029eef68 test]#
[root@ef16029eef68 test]# echo $result
50
```


test1に代入した値 10と、test2に代入した値20ですが、
Awkコマンドの `-vオプション` でいい感じに変換されましたね。
test1は、 `used` 
test2は、 `max` 
にそれぞれ代入できちゃいました。
そしてもう一つ注目して頂きたいのがこちらです。

```
'{print int((used / max) * 100)}'`
```

そうなんです。awkで持ってきているため、intで型変換ができちゃうのです。
再計算もここでできてしまうのですね〜。

##さらに
ここにはまだ続きがありまして、なんとawkは、**変数の展開タイミングも選べる**のです。
それが `BEGIN 〜 ENDブロック` を使った書き方です。

**BEGIN ～ ENDの文法**

```
# awk 'BEGIN { 最初の行を読み込む前の処理 } { なにかしらの処理 } END { 最後の行を読み込んだ後の処理 }'
※ENDは書かなくてもいいです。
```

これ知らなかったなぁ～。

#別ファイルからもいける
最後に、AWKの `-vオプション` と、**BEGIN 〜 ENDブロック**を使った書き方で、スクリプトを作ったので、ぺたりして終わります。

今回は、5時に夢中!の月曜〜金曜のメンバーを一覧でチョロと出すスクリプトを作成しました!!
5時に夢中!のProgram information APIとかあれば、ソフトでも書けるようになると思いますが、残念ながら今はハードで記述します。

##いざモックさてモックやれモック

```
[root@f8a03c52ae61 work]# cat test.sh 
cat ./in.txt | awk -v mc="メインMC" -v ac="番組アシスタント" -v com="コメンテーター"  '
        BEGIN { FS=" "; }
        {
                print mc ,$1 ,ac ,$2 ,com ,$3 $4
        }
END{ end }'
[root@f8a03c52ae61 work]# 
[root@f8a03c52ae61 work]# 
[root@f8a03c52ae61 work]# cat in.txt 
ふかわりょう 上田まりえさん 若林史江さん マツコさん 
ふかわりょう 上田まりえさん 岩下尚史さん コーヘン会
ふかわりょう 上田まりえさん おおたわ史絵さん 江原啓之さん
ふかわりょう 上田まりえさん 中瀬ゆかりさん 岩井志麻子先生
原田龍二　　 ミッツさん　　 中尾ミエさん 堀江さん
```
test.shが実行ファイル
In.txtが番組情報ファイルです。

###さて戻りはいかがかな〜。

```
[root@f8a03c52ae61 work]# bash test.sh 
メインMC ふかわりょう 番組アシスタント 上田まりえさん コメンテーター 若林史江さんマツコさん
メインMC ふかわりょう 番組アシスタント 上田まりえさん コメンテーター 岩下尚史さんコーヘン会
メインMC ふかわりょう 番組アシスタント 上田まりえさん コメンテーター おおたわ史絵さん江原啓之さん
メインMC ふかわりょう 番組アシスタント 上田まりえさん コメンテーター 中瀬ゆかりさん岩井志麻子先生
メインMC 原田龍二　　 番組アシスタント ミッツさん　　 コメンテーター 中尾ミエさん堀江さん
```

ふむいい感じですね。

##詳しく知りたければman　　
>演算処理、設計哲学、僕はそのすべてを、manコマンドから学んだ。

```
[root@localhost sandbox]# man awk
       -v var=val
       --assign var=val
              Assign the value val to the variable var, before execution of the program begins.  Such variable values are available to the BEGIN block of an AWK program.
```

#参考
若林史江さんオフィシャルWeb
http://www.fumie-w.com/
https化してない!!僕にやらせて下さい!!

5時に夢中！｜バラエティ｜TOKYO MX
https://s.mxtv.jp/goji/

[初心者向け]Awkの使い方
https://qiita.com/tofu511/items/3ecf9c5361d08b5c6eae#beginend
この方のQiitaがありがたかった。

awkを実行する
http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_15.html#SEC136
権限付与済ディレクトリで"Permission denied"発生時はAppArmorの設定ファイルを確認

# 0. 要約
UnixではAppArmorでソフトウェアごとに動作の制限を管理しているため、
ファイル、ディレクトリの権限付与済アカウントでソフトウェアを実行した場合でも、
"permission denid"のエラーが発生する場合がある。

（エラー対処方法）
/etc/apparmor.d/<設定ファイル>
設定ファイル内へ実行権限を与えたいディレクトリのパスを追加する。

## １．問題
mysqlのdatadirを権限付与済のディレクトリへ変更したとき、下記エラーが発生した。
`can't create <ディレクトリ> (Errcode: 13 - Permission denied)`

## 2. 対処
Apparmorがソフトウェアの動作制限を管理しているので、
設定ファイル(/etc/apparmor.d/usr.sbin.mysqld)に変更先のディレクトリを追記した。

```diff
# Allow data dir access 
- /var/lib/mysql/ r,
- /var/lib/mysql/** rwk,
+ /mysqldb/data/ r,
+ /mysqldb/data/** rwk,
```

##　参考
・__AppArmor__
https://ja.wikipedia.org/wiki/AppArmor
http://www.usupi.org/sysad/220.html
https://matoken.org/blog/2018/02/18/i-changed-mysqls-datadir-and-it-got-scolded-by-apparmor-and-it-not-start/
tensorboardXの簡単な使い方まとめ

#TensorboardXとは
pytorchでtensorboardを使いたい人向けのライブラリ

##簡単なイメージ
tensorboardを使ったことがない人向けに説明すると

モデルの学習中に出てくるlossなどをAPIを使ってファイルに出力

```
pathは出力されたファイルのディレクトリ
$ tensorboard --logdir="path"
```
コマンドでtensorboard起動

ブラウザでhttp://localhost:6006
にアクセスすると(localhostなどはリモートPCの場合適宜変えてください)

こんな画面が出てくる

![1.png](https://qiita-image-store.s3.amazonaws.com/0/306426/2177c7f4-2e0b-a434-8402-2902f3e919d6.png)

データはリアルタイムに更新される

便利！！

##使い方

```python
import tensorboardX as tbx
import torch

#出力先のファイル名指定
writer = tbx.SummaryWriter("runs/exp-1")

for i in range(20):
    writer.add_scalar("group/epoch", torch.randn(1).item(), i)
writer.close()
```

これを実行すると

![2.png](https://qiita-image-store.s3.amazonaws.com/0/306426/95fe8517-6b38-94d4-0fda-deec546d9578.png)

こんな感じのファイルが出来て

これを読み込むために

![3.png](https://qiita-image-store.s3.amazonaws.com/0/306426/9e7980e8-13ef-9095-318a-c2b5ee09f308.png)

コマンド実行

あとはhttp://localhost:6006

にアクセスするだけ！

###注意事項

起動したtensorboardは強制終了するとポートが占有されたままになってしまいます

必ずCTRL + C で終了させましょう

もし間違えてしまったら

```
$ tensorboard --logdir="path" --port=6007
```
などしましょう

###よくあるミス
tensorboardを起動するディレクトリと参照先のディレクトリがうまく対応していないとブラウザで見てもINACTIVEになります

tensorboard コマンドを実行したディレクトリからのpathになっているか確認してください(体験談)

###参照
reference
https://tensorboardx.readthedocs.io/en/latest/tutorial.html
Visual Studio CodeでSSHごしにファイルを編集する

以下の内容はすでに古くなっています。いまから利用するのであれば [Visual Studio Code Remote Development SSH](https://code.visualstudio.com/docs/remote/ssh) を利用するのが正道です。ただ、この方法はポートフォワードが有効でないと使えないため、ポートフォワードが無効なサーバーでは以下の方法はいまだに有効です。

# はじめに

Visual Studio Codeはリモートにあるファイルをあたかも手元に存在するかのように編集することが可能です。これによりEmacsやVimに慣れてなくともSSHごしにファイルを編集できます。また、Visual Studio Codeの優秀な補完機能の恩恵に預かることもできます。

# SSH FSをインストールする

このSSH FSはFuseを用いたSSHFSではなく、Visual Studio Codeのプラグインとしての[SSH FS](https://marketplace.visualstudio.com/items?itemName=Kelvin.vscode-sshfs)です。SSHとFSの間にスペースが入ります。まずは、「[SSH FS](https://marketplace.visualstudio.com/items?itemName=Kelvin.vscode-sshfs)」で機能拡張を検索してインストールします。

![Screenshot from 2018-11-23 15-20-24.png](https://qiita-image-store.s3.amazonaws.com/0/56302/b0fa2d97-c0ca-e03b-84bb-233cf446ee4e.png)

インストールするとリロードを促されるので、リロードします。

![Screenshot from 2018-11-23 15-20-36.png](https://qiita-image-store.s3.amazonaws.com/0/56302/d873c0c8-d373-2ff5-6a07-37eaea6797ad.png)

また、Windowsの場合にはPuttyも必要ですので、インストールしておきます。（スクリーンショットはUbuntu 18.10です）

# 接続情報を設定する

インストールが完了するとファイル一覧のでるペインの一番下に「SSH FILE SYSTEMS」というものが現れているので、これを開き何もないところで右クリックして「Create a SSH FS Configuration」を選択します。

![Screenshot from 2018-11-23 15-21-20.png](https://qiita-image-store.s3.amazonaws.com/0/56302/ed01134d-11b0-e583-6cc7-be5e0db0e54e.png)

接続先の名前を聞かれるのでわかりやすい名前をつけてあげます。

![Screenshot from 2018-11-23 15-21-50.png](https://qiita-image-store.s3.amazonaws.com/0/56302/ed9898ed-413e-b843-d1bb-38f5873d5458.png)

するとデフォルトの設定値が入ったファイルが生成されます。

![Screenshot from 2018-11-23 15-22-39.png](https://qiita-image-store.s3.amazonaws.com/0/56302/902c86f8-0a1f-72c6-7fc8-d75f5208424e.png)

ここから必要な情報に書き換えていきます。「label」は左のリストに表示されるときの名前なので適当にわかりやすいものをつけます。「root」は接続したときのトップディレクトリになります。「host」やその他の項目は接続情報なので、普通にsshをするときと同じように設定すればよいのですが、パスワードをファイルに書きたくないときには「true」を設定しておくことで接続時にパスワードを聞いてくるようになります。

![Screenshot from 2018-11-23 15-23-11.png](https://qiita-image-store.s3.amazonaws.com/0/56302/7fab9880-6483-02bb-d0f4-75ac021d5433.png)

設定を保存すると左下の「SSH FILE SYSTEMS」に接続先が現れているので、ここを右クリックして「Connect as Workspace folder」を選択します。

![Screenshot from 2018-11-23 16-01-41.png](https://qiita-image-store.s3.amazonaws.com/0/56302/84479a4c-18e3-1fb9-c350-ab902d7979e6.png)

するとパスワードを聞いてくるので、パスワードを入力して接続します。

![Screenshot from 2018-11-23 15-23-23.png](https://qiita-image-store.s3.amazonaws.com/0/56302/e6d982d1-d670-5266-489e-e73d1d7abfa8.png)

接続されると「SSH FILE SYSTEMS」の表示が緑になり、ファイル一覧のところに接続先のファイルリストが出てきます。

![Screenshot from 2018-11-23 15-23-45.png](https://qiita-image-store.s3.amazonaws.com/0/56302/d58ccf0c-e2d0-4e00-f4d1-71cb81f58e54.png)

# 公開鍵認証を用いる場合

公開鍵認証を用いる場合には「password」の代わりに「privateKeyPath」を指定します。同時に、秘密鍵のパスフレーズは「passphrase」に設定します。ここでも「true」にしておくことで、接続時に聞かれるようになります。

![Screenshot from 2018-11-23 15-26-07.png](https://qiita-image-store.s3.amazonaws.com/0/56302/ce576942-17b1-af2a-216b-0c412de16704.png)
Arch linuxでAWS Consoleに繋がらなくなった件

少し前に自宅の作業環境をMacからArch linuxに変えたんですが、なぜかAWS Consoleにまともに接続できなくなって結構困っていたのですが、とりあえず解決したようなのでメモがてら残しておきます。

### 事象
ブラウザでAWS ConsoleにつなぐとすぐにDNSエラーになる(Chromeだと `DNS PROBE FINISHED NXDOMAIN` といわれる奴）

実際ターミナルでも

```
$ curl ap-northeast-1.console.aws.amazon.com
curl: (6) Could not resolve host: ap-northeast-1.console.aws.amazon.com
```

名前解決できてないようで。

ネットワーク関連で特別何かを導入しているわけでもなく、Arch Wikiの[systemd-networkd](https://wiki.archlinux.jp/index.php/Systemd-networkd#.E5.BF.85.E8.A6.81.E3.81.AA.E3.82.B5.E3.83.BC.E3.83.93.E3.82.B9.E3.81.A8.E8.A8.AD.E5.AE.9A) を参考に `systemd-networkd` と `systemd-resolved` を立ち上げてWikiに記載の通りに `/etc/nsswitch.conf`の`hosts`に`resolve`を追加したくらいです。

```
hosts: files mymachines myhostname resolve [!UNAVAIL=return] dns
```

ちなみにsystemdのバージョンは`239.300-2`です。

### 結論

結構いろいろ調べた結果、結論としては `/etc/systemd/resolved.conf` の [Resolve]セクションのDNSSECを明示的に
`DNSSEC=no`として`systemd-resolved`を再起動したら解決しました。

これでとりあえず名前解決できるようにはなりましたがこのオプションの意味をちゃんと調べてないのでこの対応が良いのかは正直分かりません。

### 結論までの途中経過
一応、結論に至るまでの途中経過をざっくり記載しておくと

* `/etc/nsswitch.conf`の`hosts`から`resolve`を消すと問題が解消したので`systemd-resolved`関連で何か問題があるっぽいと推測。

* `systemd-resolve`コマンド経由で`ap-northeast-1.console.aws.amazon.com`の名前解決ができない。

```
   # systemd-resolved ap-northeast-1.console.aws.amazon.com
   ap-northeast-1.console.aws.amazon.com: resolve call failed: DNSSEC validation failed: no-signature
```

* 上記エラーを元にググって以下のissueを発見  
https://github.com/systemd/systemd/issues/9771
C++ Builder XE4 > TeeChart > フォント > グラフタイトル | 左軸ラベル | 下軸 (時間軸)ラベルのフォントサイズを大きくするコード

```txt:動作環境
C++ Builder XE4
```

### 処理概要

- TeeChartのフォントサイズを変更する
    - グラフタイトル
    - 左軸ラベル
    - 下軸ラベル


### 参考

- [axis title/labels not using Arial font](https://www.steema.com/support/viewtopic.php?t=13638)

### 実装

```Unit1.h
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
#include <Vcl.ExtCtrls.hpp>
#include <VCLTee.Chart.hpp>
#include <VCLTee.Series.hpp>
#include <VCLTee.TeEngine.hpp>
#include <VCLTee.TeeProcs.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TChart *Chart1;
	TFastLineSeries *Series1;
	TButton *Button1;
	void __fastcall Button1Click(TObject *Sender);
private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
```

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include <DateUtils.hpp>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
	// ダミーデータ作成

	Chart1->Series[0]->XValues->DateTime = true;
	Chart1->BottomAxis->DateTimeFormat = L"nn:ss";

	TDateTime dt;

	dt = Now();

	double yval;
	for (int idx=0; idx < 10; idx++) {
		yval = (1+ idx) % 2;
		Series1->AddXY(dt, yval, "", clRed);
		dt = IncSecond(dt, 1);
	}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	// グラフタイトル
	Chart1->Title->Font->Size += 2;

	// 左軸
	Chart1->Axes->Left->LabelsFont->Size += 2;

	// 下軸 (時間軸)
	Chart1->Axes->Bottom->LabelsFont->Size += 2;
}
//---------------------------------------------------------------------------
```

### 動作例

起動直後
![2018-11-23_16h38_05.png](https://qiita-image-store.s3.amazonaws.com/0/32870/6f863896-d891-78da-8f22-51919d4f879f.png)

Button1を五回押下後
![2018-11-23_16h38_10.png](https://qiita-image-store.s3.amazonaws.com/0/32870/5455db0d-5564-3ed2-0026-1e1b5092abb3.png)
オブジェクト指向でなぜつくるのか 第3章 ~補足~

## はじめに

![image.png](https://qiita-image-store.s3.amazonaws.com/0/186009/7bf8dcaf-d077-9b43-805e-7f6bcad83dc9.png)

Amazon: https://www.amazon.co.jp/dp/4822284654

「オブジェクト指向でなぜつくるのか-第2版-」の第３章に書かれているプログラミング言語の進化の歴史をまとめたのですが、そこで書かなかったことを補足としてまとめます。

記事: [オブジェクト指向でなぜつくるのか 第3章](https://qiita.com/items/9c06aee4b24767834fa3)

## プログラミング言語の進化

![oop01.png](https://qiita-image-store.s3.amazonaws.com/0/186009/2305c84e-e4ba-1978-e1ad-2d8f3c673b61.png)

## 構造化プログラミング

ソフトウェア危機に対応するために様々なアイデアやプログラミング言語が提案されるなか、当時最も注目されたのが **構造化プログラミング** です。

正しく動作するプログラムを作成するために、わかりやすい構造でプログラムを書くという考えに基づいています。

具体的には、プログラムを複雑化させている元凶である **GOTO文** を廃止し、ロジックを **基本三構造** だけで書くことを提唱しました。

### キーワード: GOTO文

GOTO文とは、処理を指定した位置へと移動させるためのジャンプ文の一種です。

GOTO文を乱用してしまうと、処理が順次進行ではなくなり、プログラムを行ったり来たりするようになるため、複雑になってしまいます。

そういった複雑化を避けるため、構造化プログラミングではGOTO文を廃止しました。GOTO文を廃止したプログラミングということで、構造化プログラミングは **GOTOレスプログラミング** とも呼ばれます。

### キーワード: 基本三構造

基本三構造とは、 **順次進行**・**条件分岐**・**繰り返し** の3つの構造のことを指します。

![oop02.png](https://qiita-image-store.s3.amazonaws.com/0/186009/ee4fb20a-13f3-aed9-8f81-215cedfb14a5.png)

- **順次処理**: 上から順に命令を実行していく
- **条件分岐**: ある判定の結果を元に、実行する命令を変える
- **繰り返し**: ある条件が成立する間、特定の命令を繰り返し実行する

構造化プログラミングで提唱された **基本三構造** の理論は、非常に強力でシンプルであったため、広く支持されました。

## サブルーチンの独立性強化

構造化プログラミングが提唱される一方で、もうひとつ **サブルーチンの独立性強化** に向けた動きもありました。これはコードの再利用性を向上し、プログラムを保守しやすくすることが目的です。

**グローバル変数** はプログラムのどこからでもアクセスできるため、値を変更するときは広範囲での影響調査が必要になります。**ローカル変数** と **引数の値渡し** を実現すれば、複数のサブルーチンで共有する **グローバル変数** の使用を最小限に抑えることができます。

![oop03.png](https://qiita-image-store.s3.amazonaws.com/0/186009/ca5dca92-5c07-74aa-45f2-5920739759df.png)

つまり、そういった **グローバル変数** の使用が、 **サブルーチンの独立性強化** により最小限に抑えられることで、プログラムの保守性が向上します。

### キーワード: ローカル変数

**ローカル変数** とは、サブルーチンの中でだけアクセスすることができる変数のことです。

この変数は、あるサブルーチンに制御が移ったときに作られ、そのサブルーチン以外に制御が移ったときに消える仕組みになっています。

### キーワード: 引数の値渡し

**引数の値渡し** とは、サブルーチンに引数として渡したい変数の値をコピーして、その変数の代わりにコピーした値を引数として渡すことを言います。

この仕組みを活用することで、引数として渡した値を変更しても、呼び出し側が参照している変数には影響が及びません。
オブジェクト指向でなぜつくるのか 第3章

## 本について

![image.png](https://qiita-image-store.s3.amazonaws.com/0/186009/7bf8dcaf-d077-9b43-805e-7f6bcad83dc9.png)

Amazon: https://www.amazon.co.jp/dp/4822284654

題材として選択したのは、「オブジェクト指向でなぜつくるのか-第2版-」という本です。13章で構成されており、今回は第3章について、まとめました。

## ゴール

オブジェクト指向プログラミング以前のプログラミング技術で「実現できること」と「実現が難しいこと」がわかる

## プログラミング言語の進化

下図はプログラミング言語が機械語からアセンブリ言語、高水準言語、構造化言語へと進化していく歴史を図式化したものです。

![oop.png](https://qiita-image-store.s3.amazonaws.com/0/186009/2305c84e-e4ba-1978-e1ad-2d8f3c673b61.png)

以降はそれぞれの言語の特徴や改善された点、課題点という切り口でまとめています。

## machine language（機械語）

**特徴**

- コンピュータが解釈できる2進数もしくは16進数での記述

**課題**

- 数字の羅列を理解できる極少数のエンジニアしか書けなかった
- 人間にとってわかりづらいため、修正することも非常に困難だった

## assembly language（アセンブリ言語）

**特徴**

- 機械語を人間にも理解できそうな記号で記述する
- アセンブラを使って機械語にコンパイルする

**改善された点**

- 数字の羅列ではなく、人間にも理解できそうな記号に置き換わったので可読性が向上した
- 間違いが減り、修正も非常に簡単になった

**課題**

- 専門家でないと読めないレベルの可読性
- コンピュータへの命令をひとつひとつ記述する必要があった
- 命令を少し間違っただけでもコンピュータが暴走した

## high-level programming language（高水準言語）

**特徴**

- より人間が理解しやすい表現形式で記述できる

**改善された点**

- コンピュータへの命令をひとつひとつ記述する必要がなくなった
- プログラミング言語を知らない学生でも、なんとなく理解できるまで可動性が向上した

**課題**

- コンピュータの需要がさらに増え、さらなる生産性の向上が求められた（ソフトウェア危機）
- プログラムの可読性を追求するだけでは、生産性を向上することが難しくなってきた

## structured programming language（構造化言語）

**特徴**

- 基本三構造が明示的に記述できる
- GOTO文が使用できない（一部残っている言語もある）
- ローカル変数や引数の値渡しの機能をもつ

**改善された点**

- 基本三構造が明示的（if文・case文, while文, for文）に記述できるようになり、シンプルな構造でプログラムを実装できる環境が整った
- GOTO文が使用できなくなったことで、プログラムのシンプルな構造を保てるようになった
- ローカル変数や引数の値渡しによりサブルーチンの独立性が強化され、コードを再利用して重複をなくせるようになった

**課題点**

- 影響範囲が広く、修正が困難にある原因のグローバル変数を完全になくすことはできなかった
- サブルーチンしか再利用できず、その効果は複雑化するアプリケーションの前では微々たるものだった

## まとめ

下記がオブジェクト指向プログラミング以前のプログラミング技術でもできることだと思います。

- 基本三構造の明示的な記述できる
- ローカル変数を使用できる
- 引数の値渡しができる

下記がオブジェクト指向プログラミング以前のプログラミング技術では実現が難しいことだと思います。

- グローバル変数をなくすこと
- サブルーチンよりも広い範囲でコードの再利用をすること

## 所感

私はときどき業務をしていて、うっかり重複するコードを書いてしまうことがあります。プログラミングの生産性を向上するために、コードを再利用して重複をなくす技術ができたにも関わらず、そういった時代背景を逆行することをしてしまっていたのだなと今更ながらに気づかされました。

こういった時代背景や先人の考えを知ったからこそ、「コードの重複をなくすこと」や「人間がわかりやすいコードを書くこと」といった基本的なことに対して、より意識的に取り組めるようになるのかなと感じました。

## 備考

「基本三構造」や「GOTO文」、「ローカル変数」、「引数の値渡し」などの文言については、別の記事でまとめようと思います。

記事: [オブジェクト指向でなぜつくるのか 第3章 ~補足~](https://qiita.com/items/1b0808602e8fecf0a1da)
gulpでJS,SCSSコンパイル環境

#gulpのバージョン
```
❯ gulp -v                                                                                                                      (git)-[dev/threejs]
[16:21:15] CLI version 2.0.1
[16:21:15] Local version 4.0.0
```

#gulp実行方法
下記のgulpfile.jsとpackage.jsonを置いて

```
$ npm install
$ gulp watch
```
で実行!
assets/js/とassets/scss/内のファイルを更新すると
assets/main-js/bundle.jsとassets/css/style.cssにそれぞれファイルが書き込まれる．

```json:package.json
{
  "name": "dev",
  "version": "1.0.0",
  "description": "",
  "main": "gulpfile.js",
  "dependencies": {
    "gulp": "^4.0.0",
    "gulp-sass": "^4.0.1"
  },
  "devDependencies": {
    "gulp-concat": "^2.6.1",
    "gulp-header": "^2.0.5",
    "gulp-plumber": "^1.2.0",
    "gulp-uglify": "^3.0.1",
    "gulp-webserver": "^0.9.1"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
```

```js:gulpfile.js

// gulpプラグインの読み込み
const gulp = require('gulp');
// Sassをコンパイルするプラグインの読み込み
const sass     = require('gulp-sass');
const plumber  = require('gulp-plumber');
const concat   = require('gulp-concat');
const uglify   = require('gulp-uglify');

// style.scssをタスクを作成する
// concat
gulp.task('scss.concat', function () {
    return gulp.src('assets/scss/*.scss')
    .pipe(plumber())
    .pipe(concat('style.scss'))
    .pipe(gulp.dest('assets/main-scss/'));
});
gulp.task('scss.compile', function () {
    // style.scssファイルを取得 ※return必須
    return gulp.src('assets/main-scss/style.scss')
        .pipe(plumber())
        // Sassのコンパイルを実行
        .pipe(sass({
            outputStyle: 'expanded'
        }))
        // cssフォルダー以下に保存
        .pipe(gulp.dest('assets/css'));
});

// jsファイル用
// concat
gulp.task('js.concat', function () {
    return gulp.src('assets/js/*.js')
    .pipe(plumber())
    .pipe(concat('bundle.js'))
    .pipe(gulp.dest('assets/main-js/'));
});
// コードを見にくくuglify
gulp.task('js.uglify', function() {
    return gulp.src('assets/main-js/bundle.js')
      .pipe(plumber())
      .pipe(uglify('bundle.min.js'))
      .pipe(gulp.dest('assets/main-js/'));
});
gulp.task('js', gulp.series('js.concat', 'js.uglify'))
gulp.task('scss', gulp.series('scss.concat', 'scss.compile'))



gulp.task('watch', function () {
    gulp.watch('assets/scss/*.scss', gulp.task('scss'));
    gulp.watch('assets/js/*.js', gulp.task('js'));
});

gulp.task('default', gulp.series( gulp.parallel('scss', 'js')));
```

#使い方
HTMLファイル内で下記を追加

```html:index.html
<head>
  <link rel="stylesheet" href="./css/style.css">
  <script src="./main-js/bundle.js"></script>
</head>
```
[Lightning Network] 接続用のノード文字列の正規表現

`<nodeid>@<ip or domain>:<port>` とマッチする。

javascript 用なので、適宜読み替えて使ってください。

```javascript
let rxId = "^[0-9a-f]+" // hex string
let rxDomain = "(?!:\/\/)([a-zA-Z0-9-_]+\.)*[a-zA-Z0-9][a-zA-Z0-9-_]+\.[a-zA-Z]{2,11}?"
let rxIp = "(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"
let rxPort = "([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])"
let rx = new RegExp(`${rxId}@(${rxDomain}|${rxIp}):${rxPort}`)

let nodeText = "02009947c197575f5a948e1e4343c41dc2e6122a9bd644629afb919f30e1115ff8@cln.green:9735"

console.log(nodeText.match(rx) != null) // true
```
Symfony3/Symfony4の認証エラー時のメッセージを変更する

## 概要
Symfonyのデフォルトの機能で認証処理を実装するとエラーメッセージが「資格が無効です。」となりユーザーフレンドリーではないため変更する。
UserAuthenticationProviderクラスでSymfony3までは「Bad credentials.」と返しており、Symfony4では、「Invalid credentials.」と返しているため、これを翻訳している。
ここのメッセージを変更するためだけに独自Providerを作るのはカナリ手間なので翻訳を書き換えて対応する。

## 環境
- PHP → 7.1.23
- symfony/symfony → v3.4.18 / v4.4.0

## Configの言語指定の確認
「jp」ではなく「ja」である事に注意

### symfony3
```app/config/config.yml
parameters:
    # デフォルトだと「en」
    locale: ja
```

### symfony4
```%kernel.project_dir%/config/packages/translation.yml
framework:
    default_locale: ja     # デフォルトだと「en」
    translator:
        default_path: '%kernel.project_dir%/translations'
        fallbacks:
            - ja     # デフォルトだと「en」
```

## 翻訳の書き換え

### Symfony3
```app/Resources/translations/messages.ja.yml
# ログインエラー時のメッセージがユーザーフレンドリーではないため
Bad credentials.: "ユーザー名もしくはパスワードが間違っています。"
```

### Symfony4
```%kernel.project_dir%/translations/security.ja.yml
# ログインエラー時のメッセージがユーザーフレンドリーではないため
Invalid credentials.: "ユーザー名もしくはパスワードが間違っています。"
```

## エラーメッセージ表示の準備
```app/Resources/views/admin/login_sample.html.twig
<body>
    <div class="login-form" >
         <h1>管理画面ログイン</h1>
        {% if error %}
            <div class="alert-danger p-2">
                {{ error.message | trans }}
            </div>
        {% endif %}
        <form action="" method="post" >
            {# ... #}
        </form>
    </div>
</body>
```
"rails g devise:install" 実行時、"Could not find generator" というエラーになる時

しょうもないミスですが、軽くハマったので書きます。

# やろうとしたこと
Railsで作成するアプリケーションに、認証機能を追加しようと、
簡単に、多彩なログイン機能をつけることができる"devise"というgemを導入しようとしてました。


deviseについての詳細はリファレンスマニュアルをご参照
 https://github.com/plataformatec/devise

# 事象
導入手順に従い、Gemfileにgem 'device'と記載し、bundle install後、
以下コマンドを実行したところ、 **「Could not find generator」** と表示され、正しくインストールされない。

```
$ rails g devise:install
Running via Spring preloader in process 24017
Could not find generator 'devise:install'. Maybe you meant 'css:assets', 'assets' or 'generator'
Run `rails generate --help` for more options.
```

# 原因
Gemfileの記載ミス
正しくはGemfileに「gem **'devise'** 」と記載する必要があり。

# どうしてこうなった（推測）
「devise」と「device」どちらも正しい英語として存在します。

devise・・・工夫する、考案する、案出する、発明する、遺贈する
https://ejje.weblio.jp/content/devise

device・・・装置、考案物、からくり、爆破装置、爆弾、工夫、方策、趣向、修辞的技巧、比喩表現
https://ejje.weblio.jp/content/device

「デバイス」という単語を聞いてイメージするのはdevice(装置)なので、間違って書いてしまうのではないでしょうか。
私も「認証機能を提供する装置」みたいなイベージを勝手に持っておりました。（言い訳）

ですが、正しくは「devise」であることから、「認証機能を開発（考案）する」といった意味が込められているのかもしれないですね（知っている方いれば教えてもらえると嬉しいです）

以下、deviseのドキュメントから引用
>Devise is a flexible authentication solution for Rails based on Warden. It:
https://www.rubydoc.info/github/plataformatec/devise/

## あとがき
「Could not find generator 'devise:install'」でググると以下の記事（複数バージョンのspringを使用しているとできことがある）という記事があり、確かにspringのプロセスがたくさん上がっていた(平行で複数のRailsアプリを触っていた)ので「spring　stop」　をしてみるも解決せず、色々調べたところそんなレベルの話ではなかった。

Deiviceにてrails g device:installを実行後エラー
https://teratail.com/questions/51554


また、Qiitaで「Rails device」で検索すると結構出てくるので皆間違えるんだなぁと思い書きました。

![スクリーンショット 2018-11-23 14.51.19.png](https://qiita-image-store.s3.amazonaws.com/0/261321/93516a34-7830-ddc8-ba8c-5a4dd019794f.png)

※片っ端から編集リクエスト投げようと思いましたが、キリがないのでスクショの方々のみリクエストさせていただきましたm(_ _)m
Inkscapeで作ったSVG画像がVectorDrawableで表示されない時に見直した場所

# 概要

Android向けアイコン画像を作るために、[Inkscape](https://inkscape.org/ja/)でSVG画像ファイルを作成し、Vector AssetでSVGを取り込もうとしたところ、サンプルイメージにSVG画像が表示されませんでした。実際に取り込んでみても、アイコンは表示されませんでした。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/78503/21020872-6759-9ae7-3116-5dfb79639230.png)

Inkscapeでオブジェクトの設定を2カ所変更したところ、表示されるようになったので、その内容について書きます。

# 作業

## ストローク設定の変更

Inkscape上で表示されないオブジェクトを選択し、フィル/ストロークの「ストロークの塗り」タブを開きます。ここで一番右の「？」が選択され、「塗りは定義されていません」と表示されている場合は、一番左の「×」を選択します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/78503/6235a36d-ccce-7fee-cf04-a1cd19c2f34d.png)

## パスの分解・結合

Inkscape上で表示されないオブジェクト単体を選択し、[パス] -> [結合]を選択します。今回の事象では、ここでオブジェクトが消失しました（普通は何も変化しない）。
この場合、一度Undoで戻して、同じように[パス] -> [分解]をした後、[パス] -> [結合]を実施します。
この辺りは詳しくないので、原因がよく分かっていないのですが、とりあえずこれでオブジェクトが消失することはなくなりました。

# 結果

無事、Vector AssetでSVG画像が取り込めるようになりました。下に出てる警告はとりあえず無視です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/78503/b12555af-b7c3-a239-234d-aa04ee6c9ee4.png)

# 補足

今回問題を起こしたアイコンは、昔作ったSVG画像を加工したものなので、どこかのサイトから取得したものや、真っ新な状態から作ったものではありません。なので、恐らく普通は発生しない状況かと思いますが、参考までに書き残しておきます。

ちなみにこの問題については、エラー等は何も表示されないので原因が全く分からず、設定のおかしな箇所を一つ一つ虱潰しに確認しました。今回は複合要因だったので、解決するまでに2時間以上費やしてしまいました…。
GoでHello, world!を表示させる in AWS Cloud9

# 環境
- Amazon Linux2(シンガポールリージョンのEC2上で動作）
- Cloud9
- bash

# やりたいこと
1. Cloud9でgoのコードをかき、コンソール上にHello, world!と表示させる
2. Cloud9でgoのwebサーバを立ち上げ、ブラウザ上にHello, world!と表示させる

# コンソール上にHello, world!と表示させる
## テンプレートからgo fileを作成する
Cloud9では新しいファイルをテンプレートから作成できる
<img width="1270" alt="go_new_file_from_template.png" src="https://qiita-image-store.s3.amazonaws.com/0/272298/e5534b5a-b764-44c6-63e3-b3407a762e7c.png">
Go　Fileを選んで作成すると初期設定では以下のコードが書かれたGoのファイルが作成される

```go
package main

import "fmt"
	
func main() {
	fmt.Println("Hello from AWS Cloud9!")
}
```

これを保存しようとすると、名前を聞かれるので`main.go`として保存する

## main.goを実行する
「Run」ボタンをクリックするか、Option-F5を入力すると実行されます（次回以降はF5を入力するだけで実行：runlast)
<img width="1275" alt="main_go_exec.png" src="https://qiita-image-store.s3.amazonaws.com/0/272298/6732217e-b12c-34dc-c9d9-a8bc3cffee7f.png">

# goのwebサーバを立ち上げ、ブラウザ上にHello, world!と表示させる
続いてgoの簡単なWeb serverを立ち上げます
server.goを新たに作成し、以下のように書いて、RunもしくはOption-F5で実行します

```go
package main

import (
    "fmt"
    "log"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, world!")
}
func main() {
    http.HandleFunc("/", handler)
    log.Fatal(http.ListenAndServe(":8080", nil))
}
```
server.goが実行される
<img width="1272" alt="server_go_running.png" src="https://qiita-image-store.s3.amazonaws.com/0/272298/54b3add4-9b24-f2b9-0cfc-3e52e8d4bb38.png">

実行中の状態で「Preview」→「Preview Running Application」をクリック
<img width="1276" alt="server_go_previewer.png" src="https://qiita-image-store.s3.amazonaws.com/0/272298/bd5e4206-7b5e-b68b-c76c-5069ef18e757.png">

するとCloud9上にブラウザが立ち上がり、"Hello, world"がブラウザ上に表示されました
<img width="1271" alt="go_server_result.png" src="https://qiita-image-store.s3.amazonaws.com/0/272298/2d4a6e02-602b-7ee0-aa1e-ade88e542a75.png">

previewerのURL欄の右側にあるボタンをクリックすると、ブラウザ上で別タブで表示することができます
android studioでattributesが表示されなくなったとき

# はじめに

個人的にandroidアプリ開発に興味があって一昨日からドットインストールを見ながらAndroidStudioで勉強してたんだけど、クッソしょうもないことでハマった。
こんなことで詰まるのは自分くらいだと思ったけど、もしかしたら自分のようなAndroidStudioに慣れてない初心者の内1000人に1人くらいは自分と同じことで時間を無駄にするかもしれないので戒めの意味も込めてメモを残しておく。

# 起こった現象

何か誤操作をしてしまったらしくDesignタブからattributesが消えてしまった。

![android1.png](https://qiita-image-store.s3.amazonaws.com/0/307279/a7f55fd6-3673-e29c-a5b1-f4f65cad10f2.png)

元々こんな画面だったのが

![android2.png](https://qiita-image-store.s3.amazonaws.com/0/307279/4272dc14-272b-ed99-7afb-0d5f7f190be5.png)

こんな風にattributesが画面上から消滅してしまった。
どこをいじってもうんともすんとも言わず、
「android studio attributes 消えた」とか「android studio attributes 表示されない」
とかで調べてもイマイチ分からなかった。(´・ω・｀)

# 原因

**実は見ていた画面はDesignタブ画面じゃなかった。**

![android3.png](https://qiita-image-store.s3.amazonaws.com/0/307279/bdc31da3-fa9f-2854-718f-378591be9391.png)

**Designタブ画面によく似たPreview画面だった。**

#### Designタブ画面を表示させる

上の画像の赤い矢印の`Previewと表示されてある所をクリック`する。


![andoroid4.png](https://qiita-image-store.s3.amazonaws.com/0/307279/ed0e8289-0c8e-1ad9-12c2-49c8d11604ea.png)

するとアプリのコードが表示されているTextタブ画面に遷移すると思うので、`左下にあるDesignタブをクリック`する。
この時まれに下のタブが表示されないときがあるので、その時は画面の適当な所をクリックなりすると表れると思う。

![android1.png](https://qiita-image-store.s3.amazonaws.com/0/307279/a5550add-d62e-7847-b6d3-3a6f7550df12.png)


はい、元のDesignタブ画面に戻ってこれました！attributesも表示されています！

# Designタブ画面でattributesが表示されない

![android5.png](https://qiita-image-store.s3.amazonaws.com/0/307279/d80e4e9e-5dd9-e8ce-c552-dc47275ba433.png)

attributesを非表示にしている可能性があります。上の画像の矢印の所をクリックすると表示がされると思います。


# おわりに

クソ記事過ぎない？と思ったけど開発環境に慣れてないと起こるかもしれないので残しておく。