OmniAICreator/Qiita-1.07M huggingface dataset:
コンソールの色付けにはgookit/colorが便利

[Goアドベントカレンダーその6](https://qiita.com/advent-calendar/2019/go6)が投稿されなかったので代理投稿です。Go界は殺伐しているので、隙を見せるとやられます。みなさんもお気をつけください。

GoでCLIツールを作るときにはいつも["github.com/fatih/color"](https://github.com/fatih/color)パッケージを使っていたのですが、これが長らく[メンテナンスされない宣言](https://arslan.io/2018/10/09/taking-an-indefinite-sabbatical-from-my-projects/)がされているため、移行先を探していました。で、最近使うようになったのが["github.com/gookit/color"](https://github.com/gookit/color)です。

gookit/colorは多彩なモードをサポートしています。256色にも対応しています。僕は試していないですが、基本16色ならWindowsでも動作するようです。

# 基本色の使い方

fatih/colorと似た感じで使えます。fatih/colorの基本色の関数はPrintf相当で、gookit/colorはメソッド名が必須なのでちょっとコードは長くなりますが、みんながよく知るfmtと同じ体系のメソッドが提供されているので可読性は悪くはないでしょう。 ``.Printf`` を挟み込めば移行は難しくないです。

ちなみに、fatih/colorの方も、color.Newで作ったColor構造体はfmtと同じメソッドを持つので、こちらの書き方をしていれば移行はもっとかんたんです。

```go
// github.com/fatih/color
color.Red("We have red")
color.Magenta("And many others ..")

// github.com/gookit/color
color.Red.Println("Simple to use color")
color.Green.Print("Simple to use color")
color.Cyan.Printf("Simple to use %s\n", "color")
```

# 前景色・背景色・スタイルの合成

ちょっとシグネチャは違いますが、似たような感じで初期化して、同じように使えます。

```go
// github.com/fatih/color
redOnWhite := color.New(color.FgRed).Add(color.BgWhite)
redOnWhite.Println("Red text with white background.")

// github.com/gookit/color
whiteOnBlack := color.New(color.FgWhite, color.BgBlack).Println("custom color style")
whiteOnBlack.Println("White text with black background.")
```

# テーマ

これはgookit/colorにのみにあるモードです。Redなどの代わりに、Warning/Error/Suc(Successのこと)などを使うと、より抽象的にプログラミングすることができます。

* `Info`
* `Note`
* `Light`
* `Error`
* `Danger`
* `Notice`
* `Success`
* `Comment`
* `Primary`
* `Warning`
* `Question`
* `Secondary`

こんな感じで使います。

```go
// github.com/gookit/color
color.Success.Println("Success message")
```

# タグモード

これもgookit/colorにのみにあるモードです。スタイルをタグで書くと、それを整形してくれます。基本色や基本のスタイル（boldとか）はそのまま文字で書けますし、テーマの名前もそのまま使えます。前景色・背景色・スタイルを自由に組み合わせるときは、fg=/bg=/op=を組み合わせて書きます。

```go
// github.com/gookit/color
color.Print("<red>Red Text</>")
color.Print("<error>Error</>\n")
color.Print("<fg=yellow;bg=black;op=underscore;>Warning</>\n")
```

`Print()`などの代わりに`ClearTag()`関数を使うと、タグ抜きのテキストが出力されます。ユニットテストではスタイルは無視して中身のテキストの一致だけみたい、というケースでとても便利に使えます。

```go
color.ClearTag("<red>Red Text</>")
// Red Text
```

注意点も少しあります:

* 閉じタグは開きタグの種類の限らず必ず `</>`
* タグのネストはできない
* 本文に似た形式のタグ（HTMLやXMLのタグ）があると、正常に出力されないことがある

# まとめ

ということで、github.com/gookit/colorの紹介でした。
QiitaAPI |> Marp-cli |> PPTX = 秒殺でLT資料(の元)をつくる

この記事はfusicアドベントカレンダー10日目の記事です。

どうもこんにちは。
会社の先輩により、パワハ...めいれ..どうしても明日と交代してくれと、お願い(脅迫)されて、この記事を書き殴っています。うそです。

今回は、marp cliというjavascriptのツールを使って、あの面倒極まりないスライド作成を爆速。。もとい、秒殺してやろうとおもいます。

## 前提
- nodeの環境が整っていること
- ある程度の文章の体裁が整っていること
- power pointが使えること(必須ではない)

## marp cliの導入
そもそもmarpとは、markdownの記法を使ってslide資料をつくるためのライブラリです。
有名どこだと、reveal.jsとか、remarks.jsとかあるとおもいますが、まあ、その亜種だとおもっておけばいいです。
と、いったら怒られそうなので、神ツールであると、ここに宣言します。

さて、導入ですが、

```
＄ npm i -g @marp-team/marp-cli
```
でいれたら終わりです。簡単ですね！

### 使い方
というか、ぶっちゃけ、https://github.com/marp-team/marp-cli のREADMEみたら一発です。
なにか、slide用のmarkdownを作成して`marp slide-deck.md`を実行すればよいです！
超簡単ですね！
ちなみに中身ですが、例えばこんな感じでかいとけばいいです。

```
---
title: QiitaAPI |> Marp-cli |> PPTX => 秒殺でLT資料をつくる
theme: uncover
class: invert
image: https://marp.app/og-image.jpg
---

## QiitaAPI |> Marp-cli |> power point => 秒殺でLT資料をつくる

---

```

もうね。テーマとか、いい感じにしてくれた時点でなかなかいいとおもいます。
一回書いた内容を2回として書きたく無いですもんね。

## QiitaAPI
そこで登場するのが、QiitaAPIです。
Qiitaで一度書いた記事をSlideへ変換し、スライド資料まで一気に作ってみましょう。

### 記事の取得
[ここ](https://qiita.com/developer-kikikaikai/items/037d38c16ac20a182e15)がいい感じにまとまってます！
今回は、「ある記事をスライド資料へ変換する」ことが目的なので、`https://qiita.com/api/v2/items/:item_id`で取得しましょう。
例えば、僕の以前の記事を取得すると、以下のようにとれます。
「IDA*探索(pattern database)でパズルを解く」

<img width="1421" alt="スクリーンショット 2019-12-09 23.14.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397374/0167a2d4-c458-0d66-186b-761ea056f04b.png">

こんな感じでとれるので、このbodyの部分をつかうことにします！


## QiitaAPI |> Marp-cli
取得したデータを一旦ファイルヘ保存する必要があります。
まずは、その処理を書きましょう。

```
$ curl -O https://qiita.com/api/v2/items/7cb49607ce0d146c6697
$ cat 7cb49607ce0d146c6697 | jq -r ".body" >> 7cb49607ce0d146c6697.md
```
ここで書き込まれたmarkdownファイルをmarpに食わせましょう。

```
$ marp 7cb49607ce0d146c6697.md
```

こうすることで、うまくいく。そんなわけないですね！（笑）

`#`の文字が入る度にmarpにおける改ページ処理をいれなければなりません。

### markdownを整形する
とはいえ、`#`の文字がでてくるたびに、改行処理のための`---`を挟み込むだけです！

```shell

sed -i '/^$/d' 7cb49607ce0d146c6697.md

IFS=''
while read line
do
  if [ ${line:0:1} = "#" ]; then
    echo "" >> slide.md
    echo "---" >> slide.md
    echo "" >> slide.md
    echo $line >> slide.md
    echo "" >> slide.md
  else
    echo $line >> slide.md
  fi
done < 7cb49607ce0d146c6697.md
```

スライド作成に当たって、空白行はいらないので、sedで消しておきましょう。
ここまでした後に`marp slide.md`を実行しましょう！

### 結果がこちら！

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397374/22f12ced-6c91-98fc-e70b-68431017557c.gif)

写真についてはなんだか、うまくいってないみたいです。
ここはローカルで挟み込むか、なんやかんやしてがんばるしかないですかね、たぶん。

## Marp-cli |> PPTX
`marp slide.md -o pptx`を実行するか、`marp -s .`でサーバーをたてれば、以下のように画面から取得できます。

<img width="841" alt="スクリーンショット 2019-12-10 1.31.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397374/0808f514-07f9-47c3-7c12-b313165c8356.png">

# おまけ
## netlifyで発表資料をUpload
`package.json`へ`script { "build": "./build.sh" }` を追加して、スクリプトを準備してあげれば良いです！
試しにこのページをUploadしてみました！
みてやってください。
https://5deedeca334c7decadf6d0d4--infallible-sinoussi-3abb48.netlify.com/

# おわりに
まあ、完璧とはいきませんが、めんどくさい作業を少し減らせたと思うといいのかな。。。？

リポジトリです！ ＞ https://github.com/TsuMakoto/marp2pptx
startsWithメソッド/endsWithメソッド、splitメソッド、appendメソッド

初学者ですが、個人的な勉強のためまとめました

##startsWithメソッド/endsWithメソッド

・文字列が引数で指定された文字で始まるか（終わるか）どうかを調べるためのメソッド
・調べた結果は**真偽値**で返される

##splitメソッド

・文字列を**分割**するためのメソッド
・分割する箇所は、**正規表現**で指定

##appendメソッド

・文字列に新しい文字列を追加する**StringBuilderクラス**のメソッド
・文字列リテラルと変数の値を使って動的に文字列組み立てるときに使う
　※**リテラル**・・・ソースコード内で変数に代入される**値**のこと
・オーバーロードされ、様々な種類の引数を受け取ることができる
　①**プリミティブ型**（８種類すべて）
　※**プリミティブ型**・・・boolean、char、byte、short、int、long、float、double
　②**String**
　③**char配列**
　④**オブジェクト**
　など

・プリミティブ型はすべて文字列に変換。例えば、trueという真偽リテラルは"true"という文字列になる
・Stringやchar配列は範囲も受け取ることができる
　例）Stringやchar配列の範囲を指定

```Sample.java
public class Sample {
	public static void main(String[] args) {

		StringBuilder sb = new StringBuilder();
		sb.append("abcde", 1, 3);
		System.out.println(sb);//実行結果:bc

		StringBuilder sb2 = new StringBuilder();
		char[] array = { 'a', 'b', 'c', 'd', 'e' };
		sb2.append(array, 1, 3);
		System.out.println(sb2);//実行結果:bcd
	}
}
```

・オブジェクトを追加する場合、appendメソッドは、そのオブジェクトの**toStringメソッド**を呼び出し、オブジェクトの文字列表現を文字列に追加する
　例）toStringメソッドの**オーバーライド**


```Sample.java
class Sample {
		@Override
		public String toString() {
			return "hello";
		}
}
```

　例）appendメソッドによる文字列の追加


```Sample.java
		StringBuilder sb=new StringBuilder();
		sb.append(new Sample());//toStringメソッドの結果を追加
```
gossテストシナリオ作成 その1

まずgossでテストを実行する前に、テスト項目を作成する必要がある。


テストシナリオ作成第一歩
--------
最もお手軽且つ個人的に最初に実行するのはgoss autoaddサブコマンドである。

**前提としてgossは`/usr/local/bin`にインストールされ、PATHが通っているものとする**

```
goss autoadd [サービス名やユーザ名など]
```
[サービス名やユーザ名など]にはSystemdに登録されているservice名などを入力する。
すると、対象のサービスのSystemd上の状況(enable/disableやrunning/stoppedなど)の現在の状態を正とするテストシナリオをカレントディレクトリのgoss.yamlに出力する。

さらに対象サービスの実行ユーザの/etc/passwd上に載っているUIDやGIDなど、プロセスのステータス、ポートのListen状態などを現在の状態を正としてgoss.yamlに出力する。

またユーザ名を指定すれば、そのユーザが所属しているGroupに関する内容も引っ張ってきてテストシナリオとしてgoss.yamlに出力する。

さらにテストを作成する
----------
この後もさらに `goss autoadd keyword` でテストを作成していくが
既にテストシナリオファイルがあると、上書きにならず**どんどんテストシナリオを追記**していく。

例えば

```
goss autoadd httpd
goss autoadd mariadb
```
と実行すると
goss.yamlにhttpdとmariadbのテストが両方書かれた状態となる。
後述するaddサブコマンドでのテスト追加でも同様です。

テストシナリオをファイル出力する際に、既にファイルがあれば一度読み込んでautoaddやaddの内容を追加した上で項目を並べなおしてファイル出力するようです。
~~ソース読めば確実にわかりますよ!~~
ただしこれはデメリットも一部ある（後述）ので注意は必要です。

この仕様のため、とりあえずautoaddでザクザクと実行するだけでざっくりとしたテストシナリオは出来上がります。

出力ファイル名を変える
-----------
テストシナリオファイル名は-gオプションで変更可能です。

```
goss -g WebServer.yaml autoadd httpd
```
またとりあえずデフォルトのgoss.yamlで出力しておいて、mvでファイル名を変更した後に
-gで変更後ファイル名にしてもちゃんと追記してくれます。

```
goss autoadd httpd
mv goss.yaml WebServer.yaml
goss -g autoadd mariadb
```

個人的には残していくテストシナリオファイル名は-gで何らかgoss.yaml以外のファイル名を付け、goss.yamlは試しで作成したテストや動作確認用として使うようにしています。

長くなってきたので続きは[その2](https://qiita.com/kyou5963/items/c17d2943bb78f38e4a8b)へ
WindowsServer2016　Networking　その①

#IPV4アドレスの構成

1. IPV4アドレスの概要

IPV4アドレスはTCP/IPネットワーク上で1つのホストを一意に識別する32ビットの数値
2進数表記：11000000.10101000.00000001.11001000
10進数表記：192.168.1.200

ネットワークアダプタごと一意なIPアドレスを割り当てる必要がある。
1台のホストに対し、複数のネットワークアダプタが装備されている場合は、
各ネットワークアダプタごとにIPを割り当てる必要がある

IPアドレスは以下の2つで構成されている
　　　　　　XXX.XXX.XXX.XXX
ネットワークアドレス＋ホストアドレス

・ネットワークアドレス
　ネットワークを識別するアドレス
　同一ネットワークに接続されているホストは同じネットワークアドレスを割り当てる必要がある

・ホストアドレス
　ネットワーク内のホストを識別するためのアドレス
　同一ネットワークに接続されているホストは、一意のホストアドレスを割り当てる必要がある

ネットワークアドレスとホストアドレスの区分けはサブネットマスクの値で決まる

同じネットワークアドレスを持つホスト同士は直接通信可能
別のネットワークアドレスを持つホストに接続する場合は、データ中継用のネットワーク機器が必要

〇アドレス指定のルール
・予約されているアドレスがある
　第1オクテット127
　ネットワークアドレス・ホストアドレスにすべてのビットが1
　※すべてのビットが1の場合は、ブロードキャストアドレス
　ネットワークアドレス・ホストアドレスにすべてのビットが0
　※すべてのビットが1の場合は、ネットワークアドレス

ブロードキャストアドレスは、ネットワーク内のすべての機器に対して
一斉にデータを配信するために利用される特殊なアドレス

〇ネットワーククラス
クラスA～Eまで利用可能
クラスA～Cまでが一般ユーザー利用可能
クラスDはマルチキャスト用
クラスEは実験用

クラスによって第1オクテットの先頭の値が決定されている
クラスA　0
　1～126まで利用可能
　第2～4オクテットまでがホストアドレス
クラスB　10
　128～191まで利用可能
　第3～4オクテットまでがホストアドレス
クラスC　110
　192～223まで利用可能
　第4オクテットまでがホストアドレス

〇サブネットマスク
ネットワーククラスは管理体系の話であり、実際にネットワーク部とホスト部を識別するには
サブネットマスクを利用します

2進数表記：11111111.111111111.111111111.00000000
10進数表記：255.255.255.0
プレフィックス表記：/24
1ビットの部分がネットワークアドレス

〇サブネット化
サブネットマスクを利用し、ネットワークを分割し、ニーズに合ったネットワークの構築を行う
オクテット単位での分割：クラスフルサブネット化
ビット単位でのサブネット化：クラスレスサブネット化

〇スーパーネット化
ルーティングの効率を上げるために開発された技術
連続するネットワークアドレスを持ついくつかのサブネットをまとめ、
より大きなネットワークにすることでルーティング情報を集約することができる

〇ルーティングの構成
TCP/IPでは基本的には同一ネットワークアドレスでないと通信がとれない
ただし、ネットワーク上にルータが配置されている場合は、ルータのルーティングによって、
異なるネットワーク間でも通信を行うことが可能

すべての通信パケットには、送信元アドレス、あて先アドレスが含まれる
ルータはこの情報を利用し、送信先を判断し、送信することができる
パスや経路に関するメトリック情報を利用して、適切な経路選択を行う
ルータがパケットを送付する際は、近隣ルータの情報も必要でこの情報はルーティングテーブルに格納される
ルーティングテーブルの情報は手動・自動で設定される

〇静的ルーティング
経路情報がルーティングテーブルから自動削除されることはない
ルーター間の経路情報交換のトラフィックやCPU処理が発生しない
ただし、あて先ネットワークがなくなった場合は、古い情報に基づくトラフィック転送が行われる
管理が大変

〇動的ルーティング
柔軟なネットワーク構築が容易
直接ルーティングテーブルの変更は実施しない
ルーター間でネットワーク情報を伝搬することで適切なルーティングテーブルを自動更新
経路途中で障害があった場合は、自動でう回路を再構成可能
ルーティングテーブル用のパケットがネットワークに流れてしまう

〇ルーティングプロトコル
RIP
ホップ数を使用し、最小メトリック経路を最適経路とする
経路情報を30秒周期で近隣ルータにアナウンスし、情報更新

〇OSPF
大規模環境で利用される
回線の帯域などをコスト値の考え方とする
WindowsServer2008以降のルータ機能からは削除された

〇ルーティングテーブルの管理
ルータだけでなくコンピュータもテーブルを利用し通信を行う
route printでテーブルを確認
DGWを設定するとあて先が登録されていない場合は、DGWにパケット送信するようにエントリが追加される
0.0.0.0

ルーティングを直接設定する場合は、route -p add コマンドを利用する
FirebaseのCustom Claimを利用する



## Custom Claimとは

Authenticationの認証で利用するユーザー属性に独自の情報を追加できるものと理解しています。

例えば、下記のようにuidを指定して属性をセットすると、

```
admin.auth().setCustomUserClaims(uid, {admin:true}).then()
```

ユーザーチェックの際に、下記のように利用できます。

```
firebase.auth().onAuthStateChanged(user => {
	if(user){
		user.getIdTokenResult(true).then((result) => {
			if(result.claims.admin === true){
				//admin処理
			}
		}
	}
})
```

また、firestore等のルールの中で、

```
allow read, wirte: if request.auth.token.admin == true;
```

といった感じで利用できるようになります。

多くの場合管理者とユーザーの区別等に利用されますが、もちろんadminというキーワード以外も利用できます。

## Custom Claimの制限

Custom Claimにはいくつかの制限というか条件があります。

admin権限でしか利用できないので実運用ではfunctionsと組み合わせて利用することになるでしょう。

* admin権限じゃないと付与・管理できない（クライアントライブラリからは操作できない）
* 1000バイト以下

## Custom Claimの設定

では実際に設定してみます。
ここではuid直設定していますが、実際はプログラム中で取得することになるでしょう。

>functionを作ればuidを引数で受けとるとか。

```js
const admin = require('firebase-admin');
const serviceAccount = require('/path/to/key.json');

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: 'https://test-xxxxx.firebase.com'
});

const uid = "2E6OjMO6uVT3QilaibPC7mosc1x2";

admin.auth().setCustomUserClaims(uid, { admin: true, premium: true }).then(() => {
    console.log("set customClaim");
})
```


## Custom Claimの利用

クライアントで使う場合、例えば下記のようにします。

```js
const firebase = require('firebase');

//環境に合わせて
const firebaseConfig = {
    apiKey: "AIzaSyD7HtQGZhfL4T1ttrElxsgDwqolAWxxxxx",
    authDomain: "test-xxxxx.firebaseapp.com",
    databaseURL: "https://test-xxxxx.firebaseio.com",
    projectId: "test-xxxxx",
    storageBucket: "test-xxxxx.appspot.com",
    messagingSenderId: "250622200000",
    appId: "1:250622212741:web:ff33a2e77b61e8990xxxxx",
    measurementId: "G-VVQ2BXXXXX"
};

firebase.initializeApp(firebaseConfig);

( async ()=>{
    await firebase.auth().signInWithEmailAndPassword("test@test.com","testtest");
    const result = await firebase.auth().currentUser.getIdTokenResult(true);
    console.log(result.claims);
})()
```

>user直下にはなく、getIdTokenResult()で取得しなければならないようです。

下記のような結果が得られます。admin, premiumが設定されています。


```bash
{ 
  admin: true,
  premium: true,
  iss: 'https://securetoken.google.com/staging-a5946',
  aud: 'staging-a5946',
  auth_time: 1575931924,
  user_id: '2E6OjMO6uVT3QilaibPC7mosc1x2',
  sub: '2E6OjMO6uVT3QilaibPC7mosc1x2',
  iat: 1575931925,
  exp: 1575935525,
  email: 'test@test.com',
  email_verified: false,
  firebase:
   { identities: { email: [Array] }, sign_in_provider: 'password' } }
```

実際にはif(result.claims.admin){}というような感じで利用することになります。


## Custom Claimの削除

nullをsetするといいみたいです。

```js
admin.auth().setCustomUserClaims(uid, { admin: null, premium: null })
```


## Custom Claimを利用するか普通のdocumentを使うか

多くの場合、SignUp時にAuthenticationへの（自動）登録と同時に普通のfirestore等にもデータを書き込みます。認証時にそちらを利用することもできますが、Custom Claimを使うPros, Consとしては、下記のような感じかなと。

### Pros

* 認証の一部として使える
* dbへのアクセスが発生しないためオーバーヘッドが少ない、ミスが無い、read費用が発生しない


### Cons

* admin権限が必要（逆に言えば安全）。設定用のfunctionsを設定する必要がある。
* 1000バイト以上の情報が持てない


## 参考

* [本家のサイト](https://firebase.google.com/docs/auth/admin/custom-claims?hl=ja)
* adminテーブルに登録したユーザーをtriggerを利用して自動的にadminとして登録する[サンプル](https://lnly.hatenablog.com/entry/2019/01/25/012744)
react nativeのtextで文字を折り返す

# TL;DR
- [numberOfLines](https://facebook.github.io/react-native/docs/text#numberoflines)を使う
- 特定の条件下でしかうまく動作しない模様

# OK
```javascript
<Text numberOfLines={2}>
  {this.state.bodyText}
</Text>
```
```javascript
<View>
  <Text numberOfLines={2}>
    {this.state.bodyText}
  </Text>
</View>
```
# NG
```javascript
<Text>
  <Text numberOfLines={2}>
    {this.state.bodyText}
  </Text>
</Text>
```
```javascript
<Text style={styles.bodyText}>
  {this.state.bodyText}
</Text>

const styles = StyleSheet.create({
  bodyText: {
     numberOfLines: 2
  },
});
```

# 補足
- [nested textにnumberOfLinesが当たらない問題はネイティブレベルで実装が難しくて出来ないらしい](https://github.com/facebook/react-native-website/pull/724)
- [文字列の行数を取得する](https://stackoverflow.com/questions/51610538/is-it-possible-to-know-how-many-lines-of-text-are-rendered-by-react-native-when?rq=1)
【Unity】設計手法

# エンティティコンポーネント
・Unityの開発思想で、必要に応じて機能（コンポーネント）をオブジェクトに付加する。
・従来のゲームオブジェクトで発生しがちな複雑な継承関係も生まれにくい。
  
# AMVCC (Application-Model-View-Controller-Component)
・1.の参考サイトでの設計手法。(一般的なものではない。)
・Unityは参照地獄になりやすく、どこに何がアタッチされているのかが複雑になりやすい。
　⇒　それを解決すべくApplicationからすべてのMVCを参照できるようにしてしまえという考え。 
・MVCに属さないUtility的な機能はComponentに位置する。
・データの通知は
　①View -> Application (onclickなどのアクションをトリガーとして通知する。
　②Application -> Controller (viewから受け取った通知をすべてのControllerに伝達する。)
　③Controller  -> view or model (Controllerで対象となる通知を受け取った際はviewやmodelを更新する。)

# MVC設計
・Model, View, Controllerの3層からなる。
・TriggerはControllerの呼び出し。
・ModelからViewへ通知するタイプ
　　⇒ Model, Viewの依存が発生する
・Controllerを介してModelを更新後Viewへ通知する。
　　⇒ Model と Viewの仲介を果たすので役割が大きくなる？(と記事にはあるが、あまりその感覚がない。）

# MVP設計
・Uni(Rx)と呼ばれるUnityのフレームワークが必要となる。
・Model, View, Presenterの3層からなる。
・PresenterはViewとModelの連動をフレームワークを用いて登録する？
・TriggerはUni(Rx)の機能を使って登録する。（簡単なサンプルを見ただけなのでだいぶ憶測）

# 現状どうしているか
・現在作成しているカードゲームでは、AMVCCもどきで
　ルートのGameManagerに必要なController全て突っ込んでいる。(GetComponentを使えば、ModelとViewも取得できてしまう。)
・イベント通知はせず、必要に応じてGameManagerからデータを取得し、そのコントローラを呼び出している。
  (ModelとViewを直接更新しないようにはしている。)
<b><font color="red"> その他問題点があれば随時記載。</font></b>
・model側で値の編集が必要になった際、modelとcontrollerに値を変更する同一メソッドを二つ定義しなければならないのが手間である。

# 参考サイト
1.[Unity with MVC: How to Level Up Your Game Development](https://www.toptal.com/unity-unity3d/unity-with-mvc-how-to-level-up-your-game-development)
[UniRxでMV(R)Pパターンをやってみた](https://www.slideshare.net/torisoup/unirxmvrp)
[Web出身のUnityエンジニアによる大規模ゲームの基盤設計](https://developers.cyberagent.co.jp/blog/archives/4262/)
[若輩エンジニアから見たUniRxを利用したゲーム開発](https://www.slideshare.net/HirohitoMorinaga/unirx)
[Webアプリケーション開発者から見たMVCとMVP、そしてMVVMの違い](https://qiita.com/shinkuFencer/items/f2651073fb71416b6cd7)
子シーンのContextから親シーンのContextへ　データを渡すフロー

<img width="720" alt="withZenject_child_to_parent_data_flow.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12129/f64458bf-6efc-0562-7969-4676ea009fd1.png">


この記事は「[Unity Advent Calendar 2019](https://qiita.com/advent-calendar/2019/unity)」11日目の記事です。

前回は[gremito](https://qiita.com/gremito)さんの[個別オーダーメイドカリキュラムは難しいがもの作り感があって面白い！](http://gremito.hateblo.jp/entry/2019/12/11/033933)でした

## 子から親へのデータの受け渡し

やりたいときありませんか？
僕はやりたかったのでやりました。

## MAURUNについて

https://7name.site/maurun.github.io/

https://youtu.be/9yx-3RXG8rI
VTUBERが作る同人ゲームです。僕はそのお手伝いしてたのでその話をします。どんなゲームかは遊んでください。Boothからダウンロード出来ます。声有りバージョンが有料ですがあります。

ZenjectとかUniRxとかUniTaskとかよくあるやつは使ってます。便利ですよね


## 要件

データの受け渡しをしたかったんですよね。
MAURUNのゲームシーンはこんな感じでマルチシーンになってます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12129/d97be0cb-4170-230f-49ae-c9467c08237c.png)

### メインシーンにあるもの

・HPとかのUI
・ゲーム全体の状態管理

### ステージシーンにあるもの

・障害物とか回復アイテムとか得点アイテムとかの配置
・スタート地点の配置
・ゴール地点の配置

## やりたかったこと

・ステージごとにスタート地点を変えたい
・ステージのデータからスタート地点を取得してプレイヤーキャラクターを配置したかった。

## 設計

そんな難しい事はしないです。Zenject使ってるからこの辺めっちゃ楽だった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12129/55b1d0ca-85c4-cba9-c471-b3a97dbc503f.png)


参照関係はこんな感じ

### 実際はこんな感じの処理

```cs:StartPoint.cs
   public class StartPoint : MonoBehaviour, IStageEntryPoint
    {
        [Inject] private SetupStartPointUseCase usecase;

        void Start()
        {
            usecase.In(this.transform.position);
        }
    }
```
```cs:StageBuilder.cs

    public class StageBuilder : IStageBuilder
    {
// 省略

        // Initializerから呼ばれる
        public async UniTask SetupGame(IMovable character)
        {
            var startPoint = await usecase.Out().Where(x => x != null).First();
            character.SetPosition(startPoint);
        }
    }
```

多分こんな感じ
無事にステージごとに違う感じにできました。実際にスタート位置とかだけだとあんま利用されなかったです…でもやりたい時にできないのはだるいし実際ステージ事に変わるデータなんでこれで良い…

## 親から子も行ける

親が子のContextのクラス参照するのは大変ですけどこのUseCaseは親のContextにあるんで当然親が子にデータを流すことも出来ます。UseCaseって名付けが適切かの余地はありそうだけどまあこれでいいんじゃないでしょうか。

## おわりに（そして宣伝）
Zenjectわからんって言いながらMAURUNってゲーム作ってました。
Zenjectわからない人は[いもさん](https://twitter.com/adarapata?lang=ja)の[ZenjectチョットワカルBook](https://booth.pm/ja/items/1520608)おすすめです（勝手に宣伝）

それと冒頭にも書きましたけどMAURUNってゲーム作って公開してます。
遊んでください。
https://7name.site/maurun.github.io/

あと今週末に技術書同人誌博覧会2って同人誌即売会があるんですけどそこでモバイルゲームを100本くらい触ってライセンス表記の有無とかクレジット表記の有無を調べて回ったポエム集を頒布します。物申したい人は遊びに来てください。
[技術書同人誌博覧会2 ながら工房](https://gishohaku.dev/gishohaku2/circles/iwHySxhIFT5hSShn4OwU)

ついでに既刊とか[Booth - ながら工房](https://nagara-studio.booth.pm/)でダウンロード販売もしてます。気になったら是非手にとってください。


### 明日は・・・？

明日は[Kan_Kikuchi](https://qiita.com/Kan_Kikuchi)さんの[「12日、もう一度来て下さい、最高のAudio Managerをお見せしますよ」]()です。
[Unity] ビルド時にシーンが参照されたときのコールバック

### Unityバージョン
2019.2.14f


## 問題提起

`IProcessScene` というインターフェースがかつていたらしい[^1]。
が、リファレンスをあさる限り、2018.1以降"Method group is Obsolete"[^2]、つまり古いと書かれている。

では、代わりは一体何か。

## 探求

<details><summary>`IProcessScene`が`IProcessSceneWithReport`になっていました。</summary><div>
とりあえず`IProcessScene`でぐぐると、ドンピシャなのではというQ&Aを発見。
> Remote Settingsを利用する際、Asset Storeからパッケージをインポートすると、次のようなコンパイルエラーが発生します。
>
> ```
> Assets/Editor/RemoteSettings/RemoteSettingsLinker.cs(23,18): error CS0535: `UnityEngine.Analytics.RemoteSettingsLinker' does not implement interface member `UnityEditor.Build.IPreprocessBuild.OnPreprocessBuild(UnityEditor.BuildTarget, string)'
> 
> Assets/Editor/RemoteSettings/RemoteSettingsLinker.cs(23,18): error CS0535: `UnityEngine.Analytics.RemoteSettingsLinker' does not implement interface member `UnityEditor.Build.IPreprocessBuild.OnPreprocessBuild(UnityEditor.BuildTarget, string)'
> ```
> [^3]

読み進めると、`IProcessScene`が`IProcessSceneWithReport`に置き換わっている様子なので、スクリプトリファレンスを見てみる。

https://docs.unity3d.com/ja/2019.2/ScriptReference/Build.IProcessSceneWithReport.OnProcessScene.html

ビンゴ。恐らく、引数に`Build.Reporting.BuildReport`が加わってあたらしくなったためだろう。
</div></details>

## 結論

インターフェース`IProcessSceneWithReport`を継承し、`OnProcessScene`を実装すべし。


[^1]: [【Unity】エディタ拡張で使用できるコールバックを40個まとめて紹介 - コガネブログ](http://baba-s.hatenablog.com/entry/2017/12/04/090000)
[^2]: [Build.IProcessScene - Unity スクリプトリファレンス](https://docs.unity3d.com/ja/2018.1/ScriptReference/Build.IProcessScene.html) - 2018.1のドキュメント。
[^3]: [Unity2018以降でRemote Settingsをインポートするとコンパイルエラーになる場合の対処法 &ndash; ユニティ・テクノロジーズ・ジャパン合同会社](https://helpdesk.unity3d.co.jp/hc/ja/articles/360032362271-Unity2018%E4%BB%A5%E9%99%8D%E3%81%A7Remote-Settings%E3%82%92%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B%E3%81%A8%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%AB%E3%81%AA%E3%82%8B%E5%A0%B4%E5%90%88%E3%81%AE%E5%AF%BE%E5%87%A6%E6%B3%95)
ハッシュ関数で伏せ字するサービス

# はじめに

伏せ字をするとき、「わかる人にはわかるだろうけど、間違われるのは困るな…」ということ、ありませんか？

「それって、〇〇社ですよね」みたいなリプライが来て、しかも全然違う答えだったりすると、風評被害だし迷惑ですよね。でも「残念、ハズレです」なんて一々送っていたら、さらに的外れなリプライが付くことは目に見えています。

「わかる人にだけわかればいいし、答え合わせは自分たちでやってくれ…！！」という人に便利なのが、この「[Hashtter（はしゅったー）](https://splamp.info/shed/hashtter/)」です。

Hashtter（はしゅったー）
https://splamp.info/shed/hashtter/

# 使い方

<img width="320" alt="screenshot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/218499/79875fde-cdd9-766b-e002-08cbfb4e570b.png">

上の部分に文章を入力し、ハッシュ化したい部分を`[角括弧]`で囲みます。
ハッシュ関数を`md5`、`sha1`、`sha256`から選び、「はしゅる」ボタンを押すと変換できます。

はしゅられた文字の答えにピンと来たら、Hashtterを使ってハッシュ値を調べてみましょう。一致していればそれが答えです。黙ってましょう。

# 作った経緯

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">お行儀の悪い人でも働けた <br>40ca44bea734298494a8ce86f2850c3b7130c948 社も、だいぶ人が抜けちゃったよね。</p>&mdash; 伊藤 祐策(パソコンの大先生) (@ito_yusaku) <a href="https://twitter.com/ito_yusaku/status/1202454550029852672?ref_src=twsrc%5Etfw">December 5, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

こちらのツイートを見て作りたくなったので作りました。直接ツイートしてないからバレてもセーフ！！多分！！

# 技術的な話

JavaScriptではハッシュ関数を使えないので、PHPを使って変換しています。

```php
if($_POST['text'] != '' && $_POST['algo'] != '')
{
	$text = $_POST['text'];
	$algo = $_POST['algo'];
	if(!in_array($algo, ['md5', 'sha1', 'sha256'], true)) {
		$algo = 'sha1';
	}
	$text = preg_replace_callback(
		'/(\[(.+?)\])/',
		function($matches) use($algo){
			return hash($algo, $matches[2]);
		},
		$text
	);
	echo nl2br(htmlspecialchars($text, ENT_QUOTES));
	echo '<div style="text-align: right"><a href="https://twitter.com/intent/tweet?text='.urlencode($text . "\n#hashtter https://splamp.info/shed/hashtter/").'" target="_blank" class="tweet">ツイート</a></div>';
	return;
}
```

大体こんな感じです。~~この項書かないと投稿できない~~

# さいごに

これを使えばエゴサで有名な b475a8bedbfc784d3c1f12fb33e1e9c2f76d0695 大臣にもバレない！ありがとうございました。
C# ボタン連打の対応策その３

# 問題
C#において、ページスクロールボタンに対応する処理が以下のようなケース

・ボタンコントロールを非活性
・ページデータを取得して表示（１秒弱）
・ボタンコントロールを活性化

ボタン連打で後続のイベントが無視されず、連打回数分のスクロールが実行されてしまいます。

ネットで検索してもいまいち自分好みの対応方法が見つかりません。

# 解決策
で、ひねり出したのが以下のコードです。


```
/// 保留されているイベントを破棄してからコントロールのEnabledをtrueにする。
public void EnableControl(Control co)
{
    System.Threading.Thread thread = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(DoEnable));
    thread.Start(new object[] { co });
}

private void DoEnable(object args)
{
    Control co = ((object[])args)[0] as Control;
    if (co.InvokeRequired)
    {
        // メッセージキューの最後に当関数を呼び出す処理を追加する
        co.Invoke((MethodInvoker)delegate {
            DoEnable(args);
        });
        return;
    }
    // このタイミングでは保留されていたイベントはすべて破棄されているはず
    co.Enabled = true;
}
```


# 呼び出し例

```
private void btnNext_Click(object sender, EventArgs e) {
    Cursor.Current = Cursors.WaitCursor;
    this.Enabled = false;
    try
    {
        NextPage();
    }
    finally
    {
        //this.Enabled = true;
        EnableControl(this);
        this.Cursor = Cursors.Default;
    }
}

```
# 解説？
## なぜボタン連打で後続のイベントが無視されなかったか（推測）
・クリックイベントはとりあえずキューに登録される。
・イベント処理は順番に呼び出される
・ボタン非活性化してもイベントを破棄するのはイベント処理呼び出し直前
つまり、１つめのイベント処理で非活性化しても２つめ以後のイベントは登録され、後続のイベント実行時には１つめのイベント処理は終了している（ボタンは活性化されている）ので実行されてしまう。

## コントロール.Invokeの仕掛け（推測）
・処理の呼び出しはイベントキューに登録されるのであろう

したがって、以下のような流れとなるのだろう
（１）１回目ボタンクリック処理（ボタン非活性化）
（２）２回目ボタンクリックイベント登録
（３）コントロール.Invokeの呼び出し登録
（４）１回目の処理終了
（５）２回目ボタンクリック処理（破棄）
（６）（３）で登録された処理ボタン活性化の実行


注意、マイクロソフトの正式ドキュメントでの確認はしていません。
IchigoJamの新しいWS.LEDとCOPYでピカピカ


IchigoJam BASIC 1.4で実装されたばかりのWS.LED命令。開発者の福野さんお手製の10連フルカラーLEDを頂いたので、ピカピカ光らせてみました。楽しい！
![IMG_7788.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155579/639e1e69-c4f0-49b7-75f0-61ca4e1d432e.jpeg)
WS.LED命令は、赤緑青それぞれの輝度を数値0〜255で配列[0][1][2]にセットして、WS.LED1とすれば一番手前のLEDを光らせることができるというもの。（数値を大きくすると不安定になる。50くらいが無難？）
同じように赤緑青を[3][4][5]にもセットしてWS.LED2とすれば手前から2個分の色を指定できるし、[29]まで全部セットしてWS.LED10とすれば10個全部を色々な色で光らせることができる。

WS.LED命令のクックブック的なの→[福野さんのブログ記事](https://fukuno.jig.jp/2695)

じゃあ手前から先へと色を順送りに動かしてみようと、配列を後ろへ後ろへとコピー。
最初のLEDのRの輝度が[0]に、2番目のLEDのRの輝度が[3]に保存されているので3つ先の配列要素にコピーしていけば色が順繰りに送られていくはず。

```BASIC
FOR I=29 TO 3 STEP -1
[I]=[I-3]
NEXT
```
みたいにFORを使っても良いけど、COPY命令を使った方が一行で書けて実行速度も速そう。

[0]のアドレスは#800。配列の1要素は2バイトなので[3]は#806。この2つのアドレスをコピー元とコピー先の先頭として指定、コピーする長さは最初の1個を除いたLED9個分x3（RGB）x2バイトで54バイト。

```BASIC
10 CLV
20 COPY #806,#800,54
30 A=INKEY()
40 [0]=A&1*40
50 [1]=A&2*20
60 [2]=A&3*10
70 WS.LED10
80 WAIT5:GOTO20
```
0〜7キーで色を指定して、手前のLEDから奥へと順に染まっていくプログラムを書いたつもり。しかし実行すると2つめ以降のLEDがすべて同じ色になってしまう…。なぜかというと、COPY命令は先頭から順にコピーするので

```BASIC
FOR I=3 TO 29
[I]=[I-3]
NEXT
```
と同じこと。[3]=[0]してから[6]=[3]して、[9]=[6]して…結局全部同じになってしまう。

そこで、こうするとうまく行った。

```BASIC
20 COPY #800+58,#800+52,-54
```
第三引数をマイナスにすることで、メモリアドレスを逆走しながらコピーしてくれる。そうだったらいいなーと思ってやってみたら出来た。ただしその分、アドレス指定は先頭でなく末尾を指定しないとなので計算を間違いやすい。変なとこコピーしないように気をつけよう。例えばLED5個バージョンならこう。

```
20 COPY #800+28,#800+22,-24
```

完成したプログラム。

```BASIC
10 CLV
20 COPY #800+58,#800+52,-54
30 A=INKEY()
40 [0]=A&1*40
50 [1]=A&2*20
60 [2]=A&3*10
70 WS.LED10
80 WAIT5:GOTO20
```
で、満足げにピカピカを眺めていて気づいたのだけれど、手前からじゃなく奥からにすれば簡単なのだった。

```BASIC
10 CLV
20 COPY #800,#806,54
30 A=INKEY()
40 [27]=A&1*40
50 [28]=A&2*20
60 [29]=A&3*10
70 WS.LED10
80 WAIT5:GOTO20
```

まー手前から奥に行く方が気持ちいいけどね。

自分でも作ってみた。ここでも参考にした[福野さんのブログ記事](https://fukuno.jig.jp/2692)
配線に向きがあるので気をつけよう。10連フルカラーLED楽しくてオススメです。メリークリスマス！
![IMG_7786.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155579/da3d316a-cc37-65a6-df2a-d8aa7762d399.jpeg)
LibreOffice CalcのFILTERXML関数とXML名前空間について

この記事は[LibreOffice Advent Calendar 2019](https://adventar.org/calendars/4230)の10日目の記事として書かれました。昨日の記事は、baffclanさんの「[LibreOffice 起動時に表示される 今日のヒント の一覧](https://wiki.documentfoundation.org/User:Baffclan/Tip_of_the_Day)」でした。
# FILTERXML関数
LibreOffice Calcには、FILTERXML関数というものがあります。WEBSERVICE関数でサーバーから貰ってきたXMLデータから値を取り出したいといった場合に使います。
パラメーターは2つあり、1つ目のパラメーターにXMLを、2つ目にXPath式というものを取ります。
次の数式をCalcのセルに入力すると、値「1」が表示されます。

```
=FILTERXML("<ROOT><VALUE>1</VALUE></ROOT>","//ROOT/VALUE")
```

# 実験してみる
それでは、IPA文字情報基盤データベースのMJ文字情報取得APIを使って、MJ文字図形名の情報を取り出してみましょう。[文字情報基盤データベースのページ](https://mojikiban.ipa.go.jp/search/help/api)の情報によると、次の様に書けば良さそうです。
A1セル

```
=WEBSERVICE("https://mojikiban.ipa.go.jp/mji/MJ010057.xml")
```

A2セル

```
=FILTERXML(A1,"//MJ文字情報一覧表/MJ文字情報/MJ文字図形名")
```

うまく動きません。

```
#N/A
```

A1セルにはXMLが表示されているので、WEBSERVICE関数はうまく動いているようです。
#EXCELで試す
Microsoft Excelにも、WEBSERVICE関数とFILTERXML関数があります。
Excel 2019で同じことをしてみます。

```
MJ010057
```

値が取れました。
XPath式が間違っている訳でもない様です。
#XML名前空間
LibreOffice Calcに戻ります。WEBSERVICE関数で取ってきたXMLの中に次の要素があると思います。
`<MJ文字情報一覧表 xmlns="urn:mojikiban:ipa:go:jp:mji" version="005.02">`
この`xmlns=...`の部分をごっそり削除します(XMLをコピーしてから、形式を選択して貼り付け→テキスト等の操作を行った後、XMLを編集する)。
値が取れました。

```
MJ010057
```

XMLには名前空間があって、ダグの重複を避けるために名前空間を指定することができる様です。
Wikipediaによると、
>XMLの名前空間は、要素名などが重複することのないように整理された空間。xmlns属性などで名前空間を宣言する。例えば、「<html:p>」と記述されたタグでは、「html」が名前空間接頭辞で「p」が要素名を表す。

また、[ここ](https://toyoda-eizi-ja.blogspot.com/2014/06/xpath.html)にe_toyodaさんが書いてくれている様に、＊[name()='タグ']を使えば良い様です。
次の様に書いてみました。

```
=FILTERXML(A1,"//*[name()='MJ文字情報一覧表']/*[name()='MJ文字情報']/*[name()='MJ文字図形名']")
```

値が取れました。

```
MJ010057
```

#### **でも、これ面倒臭くないですか？**
という訳で書いた誰得なパッチが[これ](https://gist.github.com/ytmknd/50d34e2ee237971958f1f60fa2eee1e7)です。[^1]
LibreOfficeにこのパッチを当てると、FILTERXML関数の動作が変わります。名前空間ありでXPath式を評価して値が取得出来なかった場合、再度、与えられたXMLの名前空間を無視してXPath式を評価する動作になります。
先の実験では、A2セルに次の様に入力すれば、

```
=FILTERXML(A1,"//MJ文字情報一覧表/MJ文字情報/MJ文字図形名")
```

値が取れる様になります。

```
MJ010057
```

自分で使ってみて意外と便利だったので記事を書いてみました。
FILTERXML関数にも、Ignore namespaces with XPath的なオプションはあって良いかもと思った次第です。[^2]

[^1]: 中で使っているXSLTは、確かStack Overflowから貰ってきたので、パッチのライセンスはCC BY-SAになります。
[^2]: 或いは、こう書けば楽だよ、みたいなのがあれば教えて欲しいです。
PythonとヘッドレスChromeを使って障害情報チェッカーを作ってみた

##概要
RSS配信されてない障害情報ページをPythonでHTMLを取得して文字列判定するコードを書いてみた。

他にいい方法あればコメントなどで教えてください。

##コード概要
- URLにアクセスしてHTMLを取得
- HTMLの文章を抜き出す
- 文章チェック（指定の文字列があるかどうか）
- 異常があればSlackに飛ばす

##参考サイト
[PyEnv](https://github.com/pyenv/pyenv)
[Chrome Driver](http://chromedriver.chromium.org/)
[SlackのWebhook作成手順](https://qiita.com/kakiuchis/items/1d9ade2ef83709209dc4)

#事前準備
Amazon Linux2を前提としています。

- インスタンス作成（t2.microとか適当に）
- Python環境の用意

もう環境がある人は適当に読み飛ばしましょう。
 
```sh
sudo yum update -y

#Pyenvを取得
sudo yum install git -y
git clone git://github.com/yyuu/pyenv.git ~/.pyenv

#環境変数を設定してリロード
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
source ~/.bash_profile

#Pythonビルド関連の準備
sudo yum install gcc -y
sudo yum install @development zlib-devel bzip2 bzip2-devel readline-devel sqlite sqlite-devel openssl-devel xz xz-devel libffi-devel findutils -y

#インストール出来るバージョンの一覧を取ってインストール
#Pyenv global 3.7.5とかするとサーバ全体に反映される
pyenv install --list
pyenv install 3.7.5
pyenv local 3.7.5
```
- ヘッドレスChromeのインストール

```sh
sudo yum -y install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm
#テスト
google-chrome --headless --disable-gpu --window-size=1024,768 --hide-scrollbars --screenshot='yahoo.png' https://www.yahoo.co.jp
```

- Pythonのライブラリインストール

```sh
pip install --upgrade pip
pip install selenium
pip install beautifulsoup4
pip install slackweb
pip install chromedriver-binary==78.0.3904.70
```

 注意点ですがChromeDriverが対応しているバージョンと、Chromeのバージョンが違うとエラーを起こします。

```sh
/opt/google/chrome/chrome --version
```

上記でChromeのバージョンを取れるので、
[このページ](http://chromedriver.chromium.org/downloads)
でバージョンを確認して指定するほうが安全です。

## コード
本編です。
「vim check.py」とかで編集します。
最後２行は稼働を確認したらコメントアウトしておきましょう。

```py
# coding: UTF-8
# URLにアクセスしてHTMLを取得
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import chromedriver_binary

options = Options()
options.binary_location = '/opt/google/chrome/chrome'
options.add_argument('--headless')
options.add_argument("--no-sandbox");
driver = webdriver.Chrome(options=options)
driver.get('チェック先URL')
html = driver.page_source
driver.quit()

#HTMLの文章を抜き出す
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, "html.parser")
html=soup.find('div').get_text()

#文章チェック
word = '障害情報現在、正常にサービスをご利用いただけます。'.encode('utf-8')
pos=html.find(word.decode("utf-8"))

#異常があればSlackに飛ばす
import slackweb
slack = slackweb.Slack(url="SlackのWEBHOOKURL")
if pos == -1:
    slack.notify(text="異常が発生しているようですURLを確認してください\nURL")
#else:
#    slack.notify(text="現在、正常です")
```

## 動作確認
```sh
python check.py
```


## おまけ
cronに登録する場合はこんな感じ
pyenvの下のPythonを見に行くように書きましょう。

```sh
*/10 * * * * /home/ec2-user/.pyenv/shims/python /root/check.py >> /var/log/check.log 2>&1
```
Laravel備忘録02－ファイル構成－

# フォルダ・ファイル構成

## appフォルダ

アプリケーションに関するクラスを管理
モデルに関するファイル
デフォルトで作成されるUserモデルは、ユーザー管理しない場合は削除
コントローラに関しては`Httpフォルダ`の中の`Controllers`に入れていく

## Configフォルダ

## databaseフォルダ
ZXingのバーコード読み取り画面を縦方向にしたい

ZXingを使用する際にデフォルトだと横方向になってしまうのを縦方向に表示するようにした自分メモです。

##結論
CaptureActivity を継承した、空の Activity 作成し、 IntentIntegrator の captureActivity に渡してあげる。

```kotlin
// 空の Activity を作成
private class PortraitActivity : CaptureActivity()
```

```kotlin
// 自分の場合は Fragment 内で使用していたので、forSupportFragment(this) としてあげています。
val integrator = IntentIntegrator.forSupportFragment(this).apply {
            setPrompt("QRを読み込んでください")
            captureActivity = PortraitActivity::class.java // ここで渡してあげる
        }
integrator.initiateScan()
```

とりあえず、これだけ行えばバーコードリーダーを開いた際に縦画面になります。

##最後に
今は ZXing は initateScan() ですぐに読み取りが行えるのですが、情報が英語の方が多い気がしています。。
今後はドキュメントの豊富な Firebase の方に移行するかもです。
移行した時はまた記事を書きたいと思います。
見ていただきありがとうございます。
# PHPカンファレンス2019東京 自分用まとめ

初投稿です。
さすがに技術的な記事を最初に書いて投稿するのはハードルが高かったので(勝手につくってるやつ)、
2019年12月1日に行われたPHP カンファレンスを勝手にカテゴライズして、勝手にまとめてみました。
※一部php7.4に関する記事も入ってます。

懇親会にも参加しましたが、すごく勉強になりました！
来年も東京で参加するつもりです



## PHP 7.4 について
### 追加
https://medium.com/@kim.jangwook/php-7-4-%E6%96%B0%E6%A9%9F%E8%83%BD%E3%82%B5%E3%83%9E%E3%83%AA%E3%83%BC-d74ecb2582fb
### 削除 
https://medium.com/@kim.jangwook/php-7-4-deprecations-479293acbfe4

## セッション
### 技術系
* [PHP における並列処理と非同期処理入門](https://speakerdeck.com/memory1994/php-niokerubing-lie-chu-li-tofei-tong-qi-chu-li-ru-men)
* [Kubernetes で構築する PHP 開発環境](https://speakerdeck.com/shin1x1/php-development-environment-on-kubernetes)
* [Composerって何？どう動くの？読んでみました！](https://speakerdeck.com/o0h/lets-read-composer)
* [REST 6+4の制約](https://speakerdeck.com/koriym/rest-6-plus-4falsezhi-yue)
* [PHP on AWS Lambda!](https://slide.seike460.com/slides/phpcon2019#/0/3)

### 運用系
* [MVCとはなにか/What MVC is](https://speakerdeck.com/tenjuu99/what-mvc-is)

### テスト系 
* [PHPerのための テストコード入門](https://speakerdeck.com/cocoeyes02/phperfalsetamefalse-tesutokotoru-men)
* [15年続くWebサービスへのCI/CDとテストコードの導入](https://speakerdeck.com/9bo9bo/cdtotesutokodofalsedao-ru)
* [自作してみようxUnitフレームワーク / try-to-self-made-xunit](https://speakerdeck.com/hgsgtk/try-to-self-made-xunit)

### チーム・組織系
* [改善失敗して学ぶ、レガシープロダクトに立ち向かうチーム作り。](https://speakerdeck.com/oogfranz/gai-shan-shi-bai-sitexue-bu-regasipurodakutonili-tixiang-kautimuzuo-ri)
* [余裕を生み出すコードレビュー 〜レビュイー編〜](https://speakerdeck.com/fortkle/code-review-phpcon-2019)
* [設計文化のないチームに文化を広めたが冴えない一手で混沌を招いた話を聞いてほしい](https://speakerdeck.com/mashirou1234/she-ji-wen-hua-falsenaitimuniwen-hua-woguang-metagahu-enai-shou-dehun-dun-wozhao-itahua-wowen-itehosii)
* [コードレビューで心がけている3つのこと](https://tech.connehito.com/entry/heartful-code-review)

### その他
* [PHPは何を捨て、どんな力を手に入れてきたのか](https://www.pixiv.net/fanbox/creator/105589/post/691574)
* [Apache から LiteSpeed に乗り換えてみませんか？](https://speakerdeck.com/kunit/php-conference-japan-2019-track5-hello-litespeed)
* [罠と呼ぶには大したことのない(フィクションの)MySQL 8.0のはなし](https://speakerdeck.com/yoku0825/min-tohu-bunihada-sitakotofalsenai-huikusiyonfalse-mysql-8-dot-0falsehanasi)
* [5ヶ月でカバレッジを20%から90%にあげた話](https://speakerdeck.com/yahiru/5keyue-tekaharetusiwo20-percent-kara90-percent-niaketahua)
* [【PHPカンファレンス2018 フォローアップ】Cygamesにおける長期運用のこれまでとこれから〜負荷対策とPHP7への道〜](https://tech.cygames.co.jp/archives/3198/)
* [「CPUとは何か」をPHPで考える / What is a CPU?](https://speakerdeck.com/tomzoh/what-is-a-cpu)
* [PHPでgRPCって どこまでいけるの？](https://speakerdeck.com/sgeengineer/phpdegrpctute-dokomadeikerufalse)
* [Webサービスのトラブルの現場 ~ Webサービスの今と昔 ~ / web-server-is-dead](https://speakerdeck.com/soudai/web-server-is-dead)
* [思想と理想の果てに](https://nrslib.com/phpcon-2019-proposal/)
SpringBoot最速体験

所要時間　初心者15分。ベテラン5分。

## 目的

SpringBoot と Gradle で最速で Hello World! する。

## 手順概要


#### 1．プロジェクトのひな形を作る
[Spring Initializr](https://start.spring.io/) を使って、Gradle のひな形をダウンロードする。
※ちなみに Maven のひな形もダウンロードできる。

#### 2．IDE(IntelliJ) でプロジェクトのひな形を開く
ひな形フォルダを開けばOK。

#### 3．文字列「Hello World!」を返すRestAPIを実装する
下記2つのアノテーションを設定し、文字列を返すメソッドを作ればOK。
<code>@RequestController</code>
<code>@RequestMapping</code>

#### 4．起動（Gradleビルド）する
Gradleのタスク「bootRun」を実行する。
http://localhost:8080 にアクセスする。

## 手順詳細


## 所感

これは簡単！
目的がスピード重視過ぎるため、実践レベルではspringのその他諸々の機能を扱えるようになる必要はあるが、Webアプリケーションが起動する状態に持って行くまで5分、慣れればそれ以下というのは侮れないと思う。
Javaのアノテーションを自作する

# アノテーションとは
クラスやメソッド、パッケージなどに対して付加情報を付与する機能。

## アノテーションを自作する
```java
import static java.lang.annotation.ElementType.TYPE;
import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Target;

@Retention(RUNTIME)
@Target(TYPE)
public @interface TestAnnotation {
    String testValue();
}
```

### `@Retention`
アノテーションの情報が保持される範囲を指定します。

- `SOURCE` コンパイラによって破棄される。
- `CLASS` コンパイラによってクラスファイルに記録されるが、実行時には読み込まれない。(デフォルト)
- `RUNTIME` コンパイラによってクラスファイルに記録され、実行時に読み込まれる。

### `@Target`
アノテーションの適用可能場所を指定します。

- `TYPE` クラス、インターフェースまたは列挙型宣言
- `FIELD` フィールド宣言
- `METHOD` メソッド宣言
- `PARAMETER` メソッドの引数宣言
- `CONSTRUCTOR` コンストラクター宣言
- `LOCAL_VARIABLE` ローカル変数宣言
- `ANNOTATION_TYPE` アノテーション宣言
- `PACKAGE` パッケージ宣言
- `TYPE_PARAMETER` 型引数宣言
- `TYPE_USE` 型が使用されている場所
- `MODULE` モジュール宣言

### `@interface`
アノテーションを定義します。

## 自作したアノテーションを付与する

```java
@TestAnnotation(testValue = "test value")
public class AnnotatedClass {
}
```

今回はクラスに対してアノテーションを付与しています。

## アノテーションの情報を出力する
```java
public class GetValue {
    public static void main(String[] args) {
        try {
            Class<?> targetClass = Class.forName("AnnotatedClass");
            var testAnnotation = (TestAnnotation) targetClass.getAnnotation(TestAnnotation.class);
            System.out.println(testAnnotation.testValue());
        } catch (Exception e) {
            // 例外に対する処理
        }
    }
}
```

実行するとtest valueが出力されます。
cronでコマンドがエラーなしで実行されない現象

# はじめに
railsでサーバ構築をしてて，wheneverを使ってcronでコマンドを実行させようとしていました．
しかし．．．
### >>>**何も出ない**<<<

エラーすら出てくれないのです．ネットで「cron 実行されない」など検索してもイマイチ自分と同じ状況ではなさそうでした．

# プロセスを確認しよう

まずはこれを確認してください

```sh
$ ps aux | grep cron
```
すると以下のような**"感じ"**の表示(**これは解決した後の表示なので一緒ではないです**)がされると思います．ここで，項目が３つくらいだったら良いのですが，もしかして2~30個あったりしませんか？それが私の場合のエラー(?)でした．

```
xryuseix            27205   0.0  0.0  4270216    280 s001  S+    2:48AM   0:00.00 tail -f /Users/xryuseix/Desktop/cron.log
root             26516   0.0  0.0  4288124    544   ??  Ss    2:42AM   0:00.02 /usr/sbin/cron
xryuseix            27434   0.0  0.0  4277496    684 s003  S+    3:14AM   0:00.00 grep --color=auto cron
```

これは今動いているcronのプロセス一覧で，なんらかのエラーで正常終了できないものの一覧となっています．そこで，一旦プロセスをkillします．いろんな方法がありますが，これが便利です．

```sh
$ sudo kill -9 `pgrep -f cron`
```

# crontabを書き換えよう

プロセス一覧にcronは実行しようとしていることがわかるので，問題があるのはcrontabです．crontabの書き方が悪くてうまく命令を実行できていないものと考えました．これがですね，私の調べ不足かもしれないのですが(多分そう)，wheneverで生成されたcrontabではうまく動かないんですよね．そこでこのコマンドを実行します．

```sh
$ crontab -e
```

とりあえず中身は以下のように書き換えてください．

```
SHELL=/bin/zsh
* * * * * echo "a" >> ~/Desktop/a.txt
```

これは，zshというシェルを使って，毎分デスクトップにあるa.txtファイルに「a」を追記するという意味です．このような簡単なコマンドで実行しましょう．**zshではなくbashを使っている方は適宜変えてください．**

するとどうですか，できていますか？私はこれでできました．

# 最後に
これでもできなかったらすみません><
他のサイトも見てみてください><
adbコマンドで端末を操作する

# adbコマンドとは
android開発者にはお馴染みですが、それ以外の人にとってはあまり知名度が高くないかもしれません。
>Android Debug Bridge（adb）は、デバイスと通信するための多用途コマンドライン ツールです。adb コマンドを使用すると、アプリのインストールやデバッグなど、さまざまなデバイス操作を実行できます。また、デバイス上でさまざまなコマンドを実行する際に使用する Unix シェルにアクセスできるようになります。
---------- androidstudioユーザーガイドより

ざっくりいうとPCからAndroid端末に直接コマンドを送って色々出来ます。
尚、開発者オプションからUSBデバッグを有効にしておく必要があります。

# 端末を操作するコマンド
## テキスト入力
```
adb shell input text hogehogehoge
```
端末でキーボードが表示されている状態で入力すると選択欄に`hogehogehoge`で指定した箇所を入力できます。
長い文字列を手入力したくない時や、複数の端末で同じ文字を入れる必要があるときに便利。
尚、デバイスのキー入力設定でそのまま入力されてしまうので注意が必要です。

同時に複数端末を接続している場合はこのままだとエラーが出るので、

```
adb -s device_id shell input text hogehogehoge
```
のような感じで端末を指定することで実行可能です。
`device_id`については`adb devices`コマンドで調べてください

## 設定画面の呼び出し
adbコマンドではアプリの起動も可能なため、コマンドで設定アプリを呼び出すことも可能です

```
adb shell am start -a android.settings.SETTINGS
```
`SETTINGS`の箇所は`WIFI_SETTINGS`や`DISPLAY_SETTINGS`などに変更することで各設定画面を直接呼び出すことも可能です。
設定できるパラメータについては[こちら](https://developer.android.com/reference/android/provider/Settings)を参照

## ディスプレイを操作する
ディスプレイのタップ、スワイプなどもadbから可能です

```
adb shell input touchscreen tap X Y
adb shell input swipe X1 Y1 X2 Y2
```
座標については左上が(0, 0)で右方向、下方向に対して値が増えていきます

# 組み合わせると・・・？
アニメーションや画面遷移の時間を考慮して適度にsleepの処理を追加したスクリプトを組んでやれば設定の自動化とかできたり。
`adb devices`で取ってきたdevice_idをいい感じにしてやれば複数端末のまとめて設定もできますね。

# おわりに
開発の場面ではよく(？)利用するadbコマンドですが、調べてみると想像以上に様々なことができたりします。
限られた場面ではありますが、有益なものも多いので継続して色々まとめていきたいところです。
Noodl x PlayCanvasで一つ上の表現力を手に入れる

Noodlアドベントカレンダー16日目の記事です。

爆速でアプリなどのプロトタイプが作れるNoodlですが、今回はweb上でお手軽に使えるゲームエンジン[PlayCanvas](https://playcanvas.jp/)を使って一つ上の表現にチャレンジしてみます。

#PlayCanvas
PlayCanvasは、デスクトップとモバイルブラウザ向けに作られたWebGL/HTML5ゲームエンジンです。豊富な機能を揃えた3Dエンジンとクラウドホスティングされた開発環境およびツールセットを備えています。

うれしいことに無料から使える**フリーミアムモデル**となっています。

GMOさんで定期的にHands-Onが開催されているので、PlayCanvas自体の導入はHands-Onからだと入りやすいと思います。

このPlayCanvas、Javascriptベースというだけでなく、**ワンクリックでWebGLアプリケーションのホスティング**ができるためNoodlと相性抜群です。

#PlayCanvasからのPublish

Editor画面のメニューにある[Publish/Download]から[Publish you project publicly on PlayCanvas]を選んで名前などの情報を打ち込んでPublishします。

PlayCanvasは自分でホスティングしたい場合にZIPでDownloadすることもできますが、その場合は2580円/月～の有料となります。
![2019-12-10 (4)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491945/9560375b-4dce-5e99-7d42-e703e18bbf79.jpeg)
![2019-12-10 (5)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491945/c590aab9-3ebd-9148-c9ff-b6b09352ce50.jpeg)

Publishが済んだら2枚目の画像の[BUILDS]からPublish済のゲームを開くことができますので、そのURLをメモしておきます。

私の場合は下記のURLになりました。（開くとTankゲームが始まります）
https://playcanv.as/b/HP21rQe5/

＜ゲーム操作＞
　矢印キー：Tank移動
　スペースキー：砲撃
#Noodl
Noodl側は`HTML Content`ノードを使うといたって簡単にできます。

`HTML Content`ノードをクリックし、Properties > Content > HTMLにあるEditボタンをクリックするとエディタが開くので下記のコードを記載します。
*****はPublishされたゲームのURLを記載します。

```HTML:HTMLノード
<!DOCTYPE html>

<iframe src="********************"
         frameborder="0" width="100%" height="100%"></iframe>
```
`HTML Content`ノードを青いノードの下にぶら下げるとPlayCanvasのゲームが表示されます。
![2019-12-10 (7)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491945/efdd8601-d0f9-8d16-9e3f-11774450e2f6.jpeg)

**HTML Contentノードを使うときのポイント**
1. iframeのwidth, heightは100%にする
2. `HTML Content`ノードの親に`Group`ノードを挟み、`Group`ノードのDimensions, Placementでサイズと位置を調整する
3. `HTML Content`ノードのDimensionsでサイズを小さくすれば余白を作ることができる
4. `Rectangle`ノードを挟むことで好きな色の額縁を作ることができる
5. ゲーム画面は`Page`ノードで切り替えると良いが、簡易的に画面のON/OFFを試したい場合、`States`ノードで親の`Group`ノードのOpacityを制御することもできる（このときリロードされる）

#まとめ
- PlayCanvasは作ったゲームを無料でWeb上にPublishできた
- NoodlではHTMLが使えるので特定のページの埋め込み、調整、制御が簡単にできた
【UE4】C++のコンストラクタからブループリントのアセットをロードする方法


# 最初に

間違いや更に良い方法があった場合にはそっとTwitter( [@ろっさむ](https://twitter.com/4_mio_11) )やコメント、修正リクエストなどでお知らせ頂けるととても有難いです。 



# 作業環境

記事内で使用する作業環境は以下の通りとなります。

- Unreal Engine：4.23.1
- Visual Studio：Community 2017 or Community 2017 for Mac or Enterprise 2019


## BPのパスを取得する



ロードしたいBPを右クリックでメニューを表示し、`Copy Reference`を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/977cbd4d-7c53-95e5-177a-82ae9fec83aa.png)




## コンストラクタでBPをロードする

```c++
ACPP_StartGameMode::ACPP_StartGameMode()
	:Super()
{
    // ロードを行いたいBPのパスを指定. これは
    // C++からBPのクラスを参照する際には末尾に_cを付け足す.
	FString CharacterPath = "/Game/ThirdPersonBP/Blueprints/ThirdPersonCharacter.ThirdPersonCharacter_c";
        
    // ConstructorHelpersはコンストラクタ内でオブジェクトやオブジェクトのクラスを検索する機能を持つ.
	// アセットが存在しないかエラーでロードできない場合、プロパティにはnullptrが入る。
	static ConstructorHelpers::FObjectFinder<UClass> CharacterBP(*CharacterPath);
	TSubclassOf<AActor> ThirdPersonCharacter = CharacterBP.Object;

	if (ThirdPersonCharacter != nullptr)
	{
		DefaultPawnClass = ThirdPersonCharacter;
	}
}
```

ここでパス名が間違っている（「'」が文頭、文末についていたり、「_c」が入っていない）場合には、`ConstructorHelpersInternal`の`FindOrLoadObject`でブレイクされてしまう可能性があります。注意しましょう。



この場合のロード方法だと、コンストラクタで上記のようなロードを行っているアセットを生成した際に、記述しているアセットも一気にロードされるため、メモリ使用量が膨れ上がることがあります。

こういった場合に、ランタイムでタイミングを見てロードするかどうか決める方法があるのでそちら次の記事で確認していきます。

次の記事：後程リンクを作成します
背景画像の可変背景のやり方

タイトル通り背景画像background-colorを用いた可変背景のやり方の実装を書いていく.
可変背景とはつまり、ウィンドウを大きくしても小さくしても縦横比が変わらないようになる状態です。

HTMLを以下の様に記述する

```html
<div class="main"></div> 
```

cssを以下の様に記述する

```css
.main{
  background-image: url('参照パス');
  background-size:cover;
  padding-top: 62.75%;
}
```

解説
1.**background-size:cover;を必ず指定する**
  指定しなければ、ブラウザが画像サイズ以上に大きくなった際にリピートしてしまうため。
2.**padding-topの指定**
  値の指定には計算をします。
  **画像の縦幅÷画像の横幅×100 = %**
  これらの数値は画像を右クリックで選択し情報を見るから閲覧出来ます。
　例)1004÷1600×100 =62.75%

参照記事↓
[background-imageでレスポンシブに対応した可変背景の作り方](https://kutarosan.com/background-image-responsive/)
PycharmでDangoプロジェクトをサーバー起動するまでの設定

## はじめに
開発環境を最初から構築することになったので概要だけ記録。

## 環境
Windows 10 Home
PyCharm Community Edition 2019.1.3
python 3.7.3
Django 3.0


## 手順
#### PyCharmのインストール
https://www.jetbrains.com/ja-jp/pycharm/

#### Pythonのインストール
https://www.python.org/downloads/windows/

#### Djangoのインストール 
pycharmの下部にterminalタブがあるので、そこで下記コマンドを実行。
バージョン指定無しで最新版をインストール（今回は3.0）

```terminal:
$ pip install django[==バージョン番号]
```

#### Djangoプロジェクトの作成
今回はプロジェクト名をsandbox_projectにします。
注意点としてはプロジェクト名はunderscore(_)で単語を繋ぐこと

```terminal:
$ django-admin startproject プロジェクト名
```
プロジェクトディレクトリに移動して下記コマンドを叩けばもう動きます。

```terminal:
$ python manage.py runserver
```

ですが、せっかくpycharmにGUIでrunserver(通常/デバッグ)ができるボタンが右上にあるのでその設定をします。
▽ボタンをクリックするとEdit configrationsの画面を開けます。
設定は写真の通り。これで『再生マークを押せば実行』『虫マークを押せばデバッグ実行（ブレークポイントが有効）』が簡単にできるようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/8b0e2aa7-dd5a-af70-f36b-47ce7fb6ac61.png)

## おわりに
Anacondaは邪教
Flutterの公式ページでお目当てのWidgetをビャッと見つける方法

#前置き
やあ
素晴らしい記事が並んでいるアドベントカレンダーだウェッヘッへ…
だが、濃い味の記事の連続では胃もたれをするだろう？ここで箸休めといこうじゃあないか。

あぁ、明日は@koheiyamaguchi0203さんの記事ですぜ！ぜひお楽しみに～！

#だいぶ悪ふざけだぞ！

Hello Engineers
君はもう、たっぷりFlutterでアプリを作ったかな？
Flutterで開発たくさんした君も、まだまだの君も（僕も！）
Widgetの名前言えるかな？に挑戦だ！

How's your mouth rolling today!

Column Table Stack Row
Wrap Container Expanded ListView GridView…  

ラ・ラ・ラ言えるかな？
キ・ミ・は言えるかな？
ラ・ラ・ラ言えるかな？
Widgetの名前～♪

はい、これが言いたかっただけ！

#でも実際さ

現実問題Widgetはすんごいいっぱいある。本当にいっぱいある。
で[Widget Catalog](https://flutter.dev/docs/development/ui/widgets)をあたるんだが、これがまた癖がある。

カテゴリー別に分かれていて一見わかり易いと思うだろう？実際わかりやすいのだが
こいつは `カテゴリー別`だ。どうあがいても`カテゴリー別`だ。
便利ではあるし、**Widgetがどういった単位で作られているのか**ざっと把握するには十分だと思う。

でもいざ探すときに**このWidgetさっき見たやつだ！**みたいな問題に結構すぐにぶち当たる。

でだ（アレ？こういうWidget有りそうなもんだけどなぁ…）
**うぇーい！そのカテゴリーにあったんかい！**

みたいなことになることが結構ある。
僕は結構ありました（小声）

#WidgetCatalogのページには…
ほぼすべての組み込みWidgetが列挙されている[Widget Index](https://flutter.dev/docs/reference/widgets)のリンクがあるのだ！

<img width="869" alt="スクリーンショット 2019-12-10 1.17.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82799/9dc0d1fd-87cb-f1f0-1b23-06994483ea34.png">

このページはカテゴリー別ではなくアルファベット順に列挙されている。つまりそれっぽい単語をページ内検索なり何なりすればそれっぽいWidgetにありつけるって寸法でさぁ！

もちろん、Widget Catalogにあるすっごくわかりやすい画像もついていて見ているだけで欲しいWidgetがだいたい見つかるし、何より楽しくなること間違いなしだ！

<img width="864" alt="スクリーンショット 2019-12-10 1.35.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82799/b0f363d5-b55d-34fe-6985-c725b11365fe.png">

お目当てのWidgetが見つからないときはとにかく[Widget Index](https://flutter.dev/docs/reference/widgets)を見てみると良いだろう。

#もっと楽しくWidgetを探したいか？もっとWidgetでワクワクしたいか？

結構、ではますます楽しくなりますよ。さあどうぞ。
[今週のWidget](https://www.youtube.com/playlist?list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG)
flutterは公式サイトのドキュメントの充実ぶりもさることながら、youtubeチャンネルもとても良いのだ！その中でも[今週のWidget](https://www.youtube.com/playlist?list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG)…グレートですよこいつはァ

この中の動画を通学、通勤、帰宅中に見ようものなら学校で、勤務先で、自宅ですぐにでも試してみたくなることウケオイってもんでさぁ！

#長々と書いたが、まとめると
はい…ドキュメントちゃんと見ましょうってことですね。ごめんなさいでした。