OmniAICreator/Qiita-1.07M huggingface dataset:
子供にプログラミング教育をするときにやってしまいがちな間違い

私はとあるCoderDojoで道場主をしております。
そこで、数多くの子供にプログラミングの手ほどきをしている経験や、同じように道場を開設している方などのお話を聞き、
プログラミング教育で、やってしまいがちだけどやめたほうが良いことを自分なりにまとめてみました。

あくまで私の個人的なサマライズなので、共感できるポイントだけ参考にしていただければ幸いです。


# テキストだけで学習し続ける
几帳面な方だとテキストを読んで、読み終わるまで実際に動かさないといった方が居ると思います。
子供の場合、テキスト1冊を読み切るのは、たとえ読み聞かせだとしても相当な忍耐が必要なことです。
最悪、パソコンに触れる前から挫折させる原因になり兼ねません。

もしテキストを購入して始めようと思うのであれば、導入部分の基本操作だけをさらっと読んで、早速触れてしまいましょう。
パソコンを全く触ったことが無い子供であれば、この時点でわくわくして色々とやりたいことに心躍らせてしまうことでしょう。

最初は自分の意のままにマウスを扱うということですら、なかなか難しいと思いますので、
いきなり課題に取り組まず、しばらく見守ってあげる時間を大切にしていただきたいと思います。


# テキストで雁字搦めにする

例えばscratchをやってて、「背景はこれ」、「キャラクターはこれ」をテキストに沿わないとダメという教え方です。

子供は沢山並んだキャラクターの一覧を開いた瞬間、目が輝き「たくさんある！どれにしよう！」とわくわくします。
そこで好きなものを選んで自分の世界を作ることで、自分の作品に愛着が沸き、最後まで頑張って仕上げようという意欲につながります。

勘違いして欲しくないのは、決してテキストを否定しているわけではありません。

もちろんテキスト通りに進めるのが好きな子だっています。そういった子は、やりたいように進めていけば良いです。
ただ、教える側の心がけとして、テキスト通りに100%やることを強要すべきでは無いということです。


# カリキュラム至上主義になる

親としては、子供の学習は進捗が見えてほしいという気持ちがあると思います。
その方が確実に前に進んでいることが見え、安心だからです。

しかし、プログラミングはゴールがありませんので、成果が見えにくいものです。

また、次に何をやればよいか決まっている学習ばかりでは、受け身になり、
次第にやらされているという感覚が芽生えてしまって、やめてしまうことになり兼ねません。

それでも右も左も分からず、最初は不安というのであれば、塾など決まったカリキュラムがある場に行けば良いです。

しかし、ゆくゆくは自分で好きなものを作り出していけるようになるために、塾以外でも自分自身で何かを作るという時間を設けることをオススメします。

復習という言葉を使うと勉強的になるので、フリータイムという位置付けにすれば少しハードルが下がると思います。

# 考えることをやめさせる

子供が作品を作っている時に、これはどうしたらよいだろう？と考え込むことがあります。
そういった時に、すぐに答えを教えてしまうと、思考をストップさせてしまいます。

すぐに答えを求めずに、考えて答えを出す姿勢がとても大事なことで。

やってみて失敗しても、幸いプログラミングは簡単にやり直しがきくモノなので、できればチャレンジして欲しいところです。

また、教える側の答えと、子供の答えでは全く別のゴールにたどり着くことが良くあります。プログラミングは過程も答えも無数にあります。

どうしてもわからないときは、答えに導けるヒントを与えてあげて良いですが、
その時は大人の教えるやり方だけが全てでは無いことも教えてあげましょう。

# 対象年齢で与える教材を決めつける

教材には対象年齢がありますが、それに厳密に従う必要はありません。
例えば幼稚園の年長さんに対して、小学１，２年生ぐらいの教材であれば、本人の興味さえあれば与えてしまって良いと思っています。

必ず幼稚園児向けの教材じゃなきゃダメ！ってことはないです。ただ、漢字が読めないとできない教材などは考慮してあげるべきです。

その根底にあるのは、チャレンジしたい子供の気持ちをできるだけ尊重したいということです。
一方、あまりレベルが高い教材から与えてしまうと、初めから挫折してしまう恐れもありますので、
少し上の教材ぐらいであれば、チャレンジさせてみて良いと思います。


# いつまでも専門用語を使わない

わかりやすくすることを心がけるあまり、噛み砕いた言葉をいつまでも使ってしまうことがあります。

「マウスをカチカチしてね」とか「インターネットのソフトを開いてね」など。

本来だったら、「ダブルクリック」や「ブラウザ」という名称があるので、簡単なものなら初めから言葉の定義を教えてしまって構わないと思います。

結局いつかは覚えなくちゃいけないですし、後から教えようと思っても、なかなかその頭から切り替え出来なかったりしてしまいます。
また、テキストなどではちゃんとした名称で書かれていることが多いので、困ることになり兼ねません。

最初は難しいでしょうが、子供は吸収が早いのですぐに覚えていきますので、最初から使ってしまって良いと思います。

基準としては、「一言で説明できることは教える」などにしてみてはいかがでしょうか？



# さいごに

色々と書かせていただきましたが、一貫して言えるのは「子供のやりたいことを応援してあげる姿勢」ということに尽きます。

プログラミングは非常に様々なものを作り出すことができるので、子供の夢や想像力で作っていく世界を表現するのに最適です。

私も教えながらも、時に子供の素晴らしい世界観やアイディアに驚かされることも少なくありません。

そういった姿を一歩下がって見守り、好奇心を育てていってあげたいですね。
強化学習２７　colaboratoryの９０分ルール対策　chainerRL（＋chokozainerRL)

強化学習２６までが終了していることが前提です。
中学から大学までのAI初学者を対象にしています。

google　colaboratoryは無料で、gpgpuもできるスグレモノなのですが、連続使用時間に制限があるようです。書面で見つからなかたので、確認していません。
実際に、使用中に使えなくなることはあるので、長時間の機械学習をするには、途中までのバックアップと途中から再開する手段が必要になります。

さて、chainerRLには、その機構があるのですが、、、１２月３日時点では、それをpipで通常インストールできません。githubには出ているので、いずれリリースされると思いますが。
最新版を使いたい場合は、

```
!pip install git+https://github.com/chainer/chainerrl
```
でインストールできます。
これは面倒なので、関係している一部だけをchokozainerrlにコピーしました。

chokozainerrlは、設定をargsでしています。
checkpoint_freqで、セーブポイントを設定します。例えば、１０００ならば、１０００、２０００、３０００と１０００刻みでセーブしてくれます。セーブされるagentは、3000_checkpointのような名前のフォルダに入ります。
また、途中から開始したい場合は、step_offsetを使います。
３０００stepから開始したいのならば、step_offset=3000とします。
そして、３０００step学習したagentフォルダをload_agentに指定します。
この２つを上手に使えば、途中で中断されても大丈夫。

chokozainerのgithubはこちらです。
https://github.com/chokozainer/chokozainerrl
HandsonTableのドキュメントを見るときの注意点


#HandsonTableとは
HandsonTableは、JavaScriptのEXCELのようなグリッドコンポーネントです。
https://handsontable.com/

## ドキュメントを見るときの注意点

Handsontableを使う際に、公式のドキュメントを見ると思います。
React、Angular、Vue.jsのサンプルも書いてあります。
こちらを見る際に、知っておかないと困ることがあります。

![コメント 2019-12-03 155207.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42567/33821daa-6b2d-9239-0153-7da33a1c6398.png)

サンプルページまでは、簡単に行けます。

![コメント 2019-12-03 155853.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42567/6fd5191b-b2e6-2cd7-4238-4595ecbec1d1.png)


このサンプルページを見てソースコードを読んでいると、
「あれ、vueコンポーネントを呼び出しているところはどこだ？」となると思います。

![コメント 2019-12-03 155853.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42567/a3223a05-2238-ab52-f379-113bd1e03e58.png)

上記のEditボタンを押してください！！！

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/42567/2599689d-2446-2a38-aefe-78a9fd91e2a5.png)

そうするとすべてのソースコードが見えます！！！
当たり前のようですが、気づくのにしばらくかかり困りました。
wordpressで画像が重かったのでプラグインで圧縮するようにしたら割と良かった話

ブログのサイトパフォーマンスの分析を以下に記載したツールで行いましたが、
https://qiita.com/a-nishimura/items/924ff66f596c6e8797be
ボトルネックになっている箇所は割と画像が多かったです。
CDNでキャッシュはさせていますが、そもそもの画像のサイズが割と大きいのは一つの要因のようです。
アイキャッチやキャプチャなどをよく使いますがそんなにデザインとして凝ったものは作れないので解像度や減色はあまり気にしてませんでした。
ただ、以下のプラグインを入れてみたら割と圧縮が簡単にできて便利だったのでメモです。

## WP-Optimize - Clean, Compress, Cache

メディアライブラリのアップロード時に圧縮設定ができるので数クリックでできます。
**Prioritize maximum compression**
をよく使いますが画像によっては三分の一、五分の一以下にもなるので画像を多用したりする人にはおすすめです。
Lookerで表計算結果のランクを動的なフィルタとして使う

※タイトル通り＆ほとんど[この記事](https://help.looker.com/hc/en-us/articles/360023638494-Dynamic-Rank-in-Visualization-Using-Parameter)の和訳です。

## やりたかったこと
事前にviewで定義しておくのではなく、粒度や集計軸を動的に変えられるランクをフィルタとして使いたかった。

## ハードル
* 事前にviewで定義したrank dimensionを使うと、集計軸ごとに複数dimensionを作らなければいけない。
* Explore上でTableCalcurations機能を使って作った計算結果はフィルタとして使えない。

## 使っているテクニック
* [parameter](https://docs.looker.com/reference/field-params/parameter)
* [Table Calculations](https://docs.looker.com/ja/exploring-data/using-table-calculations)
* [Hide from Visualization](https://docs.looker.com/exploring-data/visualizing-query-results#specifying_lookml_fields_to_include_in_the_visualization)
* Hide "No"s from Visualization

## やり方
①viewに type: [numberのdimension](https://docs.looker.com/reference/field-reference/dimension-type-reference#number) と [parameter](https://docs.looker.com/reference/field-params/parameter)の2つを追加する。この時、dimensionのsql句ではparameterの名前を指定する。（この例ではmax_rank） 

```
parameter: max_rank {
 type: number
}

dimension: rank_limit {
 type: number
 sql: {% parameter max_rank %} ;;
}
```
②Exploreに移動。好みの粒度で集計し、ソートをかけたところにさっき作成したdimension(例ではrank_limit)を追加。max_rankはfilterとして追加し、<b>上位何件表示したいか</b>を入力しておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77126/b6fc62b0-62b6-8392-8cc6-9fca3f4d00a2.png)
(max_rankで入力した値はrank_limitに渡され、固定値として表示される)

③表計算を2つ作成。1つ目はRankで、どの指標でランキングを作成するかを指定。2つ目はBooleanで、前に作成したRank計算結果とrank_limitを比較するもの。戻り値はyesno型。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77126/1ea261f2-73dc-dd46-b0d0-034f47472eaf.png)
（この時、表計算を利用するため表の中に使っていないmeasureを使うことはできないので注意）

④作成した2つの表計算は[Hide from Visualization](https://docs.looker.com/exploring-data/visualizing-query-results#specifying_lookml_fields_to_include_in_the_visualization)する。

⑤表計算結果であるshow_in_visualizationの設定から、<b>Hide "No"s from Visualization</b>を選択すると、Noが返ってきている行がVisualizationに出てこなくなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77126/edf03a0b-d8dd-5b77-b425-274c0ecd6616.png)

## 解説
データベース上に存在しない値でもユーザー側から任意の値を入力できるparameterフィールドを予め作成しておき、
そのフィールドと表計算結果を比較することでyesno列を作成。
yesnoフィールドだとHide "No"s from Visualizationが使えるため、
ランキング上位のみ表示が実現しかつ何位まで表示したいかもユーザー側が制御できるようになる。

なので、厳密に言うとFilterとして使っているというよりは、Visualizationに表示していない、
というだけなんだと思う。

Hide "No"s from Visualizationは知らなかったし、parameterとの合わせ技としては
良いスキルアップ問題になりそうな内容だった。
parameterの拡張性の高さを考えると、まだまだ応用の余地がありそうですね。

## （Appendix）Tableauだとこうやってた
rank関数かindex関数で計算フィールドを作って、フィルタとして適用。
viewには不連続値で入れて、フィルタには連続値として入れていた記憶がある。
（連続値じゃないとスライダーの見た目で操作できなかった）


## 参考文献(再掲)
https://help.looker.com/hc/en-us/articles/360023638494-Dynamic-Rank-in-Visualization-Using-Parameter
いまさらMacTeXの更新

# はじめに
Catalinaにしたついでに，今更ながらTeX Live 2019へのアップグレードをしましたのメモ

### 状況
OS X v10.15.1
TeX Live 2018が入っているけど面倒なことはしないで2019にしたい．

### 参考にしたページ
いつものって感じだけど参考にしたページ
- [TeX wikiのMacTeXのページ](https://texwiki.texjp.org/?MacTeX)
- [TeX wikiのヒラギノのページ](https://texwiki.texjp.org/?%E3%83%92%E3%83%A9%E3%82%AE%E3%83%8E%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88)
- [MacTeX 2019 のインストール＆日本語環境構築法](https://doratex.hatenablog.jp/entry/20190502/15567750260)
- [TeX Live 2018 から 2019 へのアップグレード](https://text.baldanders.info/remark/2019/06/upgrade-texlive-from-2018-to-2019/)

# MacTeXをいれるところ

[TeX wikiのMacTeXのページ](https://texwiki.texjp.org/?MacTeX)から，ミラーサイトにとんで，インストーラを落として起動．
アプリケーションは競合しないようにしてくれるらしい？ので，ここまでは簡単．

# tlmgrの更新

ちょっと躓いたのでメモ．
上記記事等には，

```
sudo tlmgr update --self --all
```

を実行とだけ書いてあるけど，これをやると，ローカルのtlmgrのバージョン（2018）とリモートリポジトリのバージョン（2019）が違うので怒られる．
そこで，

```
sudo tlmgr path remove
```

で現在のtlmgrのパスを切ってやったところ，tlmgrの2019版が勝手に選ばれるようになった．
もしかしたら去年のわたしが変な設定をしただけかもしれないけど，一応メモしておく．

この更新が時間かかるからTeX Liveの更新きらい．

# ヒラギノ対応
[TeX wikiのヒラギノのページ](https://texwiki.texjp.org/?%E3%83%92%E3%83%A9%E3%82%AE%E3%83%8E%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88)に従ってコマンドを順次コピペしていくだけ．

一応，現在のフォントマップの設定は

```
kanji-config-updmap-sys status
```

で見られるので，これで

```
CURRENT family for ja: hiragino-highsierra-pron
```

が返ってくればOK！

# おわり！
偉大な先人の知恵をお借りすることでつつがなく更新できた．最高！
おわり
Terraformで構築するAmazon SNSからAWS Lambdaを呼び出すためのトリガ

## はじめに
こんにちは、SREエンジニアやっています、@hayaosatoです。
今回はAmazon SNS(以下、SNS)からAWSLambda(以下、Lambda)を呼び出すためのトリガをTerraformで構築してみようと思います。
コードは[こちら](https://github.com/hayaosato/advent-calendar-2019/tree/master/aws-sns-lambda)

[前回](https://qiita.com/hayaosato/items/381ee4b5d657206de1e9)、似たようなことをSQSからのトリガ設定をTerraformで実装したのですが、
その際に利用した[lambda_event_source_mapping](https://www.terraform.io/docs/providers/aws/r/lambda_event_source_mapping.html)では、一部のリソースでしかLambdaのトリガを設定することができませんでした。
そこで、今回はLambdaにおけるそのほかのリソースへをトリガにする[lambda_permission](https://www.terraform.io/docs/providers/aws/r/lambda_permission.html)を利用してSNSからのトリガを構築してみようと思います。

## Lambda
アプリケーションはSQSの時と同様、Slack通知を行うアプリケーションにしています。
`arvhive_file`でLambda関数用のzipファイルを作成して、生成したzipファイルをLambda関数としてアップします。

```tf
data archive_file "default" {
  type        = "zip"
  source_dir  = "src"
  output_path = var.output_path
}

resource "aws_lambda_function" "default" {
  filename         = var.output_path
  function_name    = var.service_name
  role             = aws_iam_role.default.arn
  handler          = "lambda_function.lambda_handler"
  source_code_hash = data.archive_file.default.output_base64sha256
  runtime          = "python3.6"
  environment {
    variables = {
      SLACK_API_KEY = var.SLACK_API_KEY
    }
  }
}
```
また、SlackのAPIトークンは環境変数から利用しているので、Lambdaにも環境変数を定義します。

### IAM
Lambdaを実行するためのIAM Roleも定義する必要があるので、このリソースも合わせて作っておきます。

```tf
resource "aws_iam_policy" "default" {
  name        = var.service_name
  description = "IAM Policy for ${var.service_name}"
  policy      = file("${var.service_name}-policy.json")
}

resource "aws_iam_role_policy_attachment" "default" {
  role       = aws_iam_role.default.name
  policy_arn = aws_iam_policy.default.arn
}
```

## SNS
SNSに関しては、サブスクリプションでLambda関数を指定してリソースを作成してあげる必要があります。

```tf
resource "aws_sns_topic" "default" {
  name            = var.service_name
  delivery_policy = file("sns_delivery_policy.json")
}

resource "aws_sns_topic_subscription" "default" {
  topic_arn = aws_sns_topic.default.arn
  protocol  = "lambda"
  endpoint  = aws_lambda_function.default.arn
}
```

## 連携
ここからが本題で、Lambda関数に対してSNSからのトリガを設定してあげます。

```tf
resource "aws_lambda_permission" "default" {
  statement_id  = "AllowExecutionFromSNS"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.default.function_name
  principal     = "sns.amazonaws.com"
  source_arn    = aws_sns_topic.default.arn
}
```
もし、S３からのトリガを設定したい場合は

```tf
resource "aws_lambda_permission" "s3_trigger" {
  statement_id  = "AllowExecutionFromS3Bucket"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.default.arn
  principal     = "s3.amazonaws.com"
  source_arn    = aws_s3_bucket.default.arn
}
```

のようになります。

## 結果
sample.tfvarsにSlackのAPIトークンを記入して、

```
$ terraform apply -var-file sample.tfvars
```
すると
<img width="1598" alt="スクリーンショット 2019-12-03 15.49.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312728/4c9f280d-7f65-526f-5acf-8c58e7fe0038.png">
できました。

## 最後に
Lambdaへのトリガ設定もTerraformで設定できるようになりました。
サーバレスが捗りますね

## 参考
- [Terraform Documentation](https://www.terraform.io/docs/index.html)
yahoo広告運用

#yahoo広告の運用
1ページ目上部掲載に必要な入札価格よりも、入札価格が低くても
表示回数は少ないが、表示はされる。

インプレッション数=表示回数

#検索キーワード
より多くの人に検索してもらい、広告を表示させるためには、
マッチタイプ「部分一致」にするのが一番良い。
でも、キーワード+他のキーワードで検索してもらいたい場合はフレーズ一致で。

https://promotionalads.yahoo.co.jp/online/matchtype.html



・設定したキーワードに「検索数の少ないキーワード」の表示有り

ほとんど表示されないので、マッチタイプを変更するか
キーワードの変更を検討する。

このキーワードが出てしまうと、品質パフォーマンスの低下に繋がるので
オフにしておくと良い。


・検索されたキーワードの閲覧方法

広告グループを開く　→　検索クエリーを表示
「すべてのキーワード」を選択

検索されたくないキーワードを対象外キーワードに追加することも可能。
その場合、右下に「完全一致」と表示されていることを確認する。

一度キーワードなどを変更したら、10日間程様子を見て、
今後の運用方法を決める。
[GCP]Cloud ShellからDatalabを利用する方法

# はじめに
Cloud Datalabの「クイックスタート」にはCloud ShellからDatalabを利用する方法が記載されていませんでしたので、「Chromebook での Cloud Datalab の起動」を参考に、Cloud ShellからDatalabを利用する方法をまとめました。

クイックスタート
https://cloud.google.com/datalab/docs/quickstart?hl=ja

Chromebook での Cloud Datalab の起動
https://cloud.google.com/datalab/docs/how-to/datalab-using-shell?hl=ja

# 手順
## 1. GCP プロジェクトを選択または作成
https://cloud.google.com/datalab/docs/how-to/datalab-using-shell?hl=ja
に記載の内容と同じです。

## 2. Google Cloud Platform プロジェクトに対して課金が有効になっていることを確認
https://cloud.google.com/datalab/docs/how-to/datalab-using-shell?hl=ja
に記載の内容と同じです。

## 3. Google Compute Engine と Cloud Source Repositories API を有効にする
https://cloud.google.com/datalab/docs/how-to/datalab-using-shell?hl=ja
に記載の内容と同じです。

## 4. Cloud Shell から Cloud Datalab を起動する
Cloud Shellを起動した後、以下のコマンドを実行し、Cloud Datalab VM インスタンスを作成します。

```
datalab create <instance-name>
```

以下が表示されたらパスフレーズを入力します。

```
Enter passphrase for key '/home/user/.ssh/google_compute_engine':
```

しばらくすると以下のメッセージが表示されます。
表示されたら次の手順に進んでください。

```
The connection to Datalab is now open and will remain until this command is killed.
Click on the *Web Preview* (square button at top-right), select *Change port > Port 8081*, and start using Datalab.
```

## 5. Cloud Datalab ホームページを開く
[ウェブでプレビュー] ボタンを選択したのち、[ポートを変更]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/173bb70b-7957-45d4-7a25-0c5b2fa2c588.png)

ポート番号に8081と入力して、[変更してプレビュー] を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/2451fd6c-d4c7-1004-2e13-9bf44bcd87eb.png)

## 6. Datalabの画面が開く
Datalabの画面が開きます。
docsの中にサンプルやチュートリアルが入っていました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402872/0d3b24fe-aeaa-6d50-e321-28f630c2584d.png)

切断するにはCloud Shell側で `Ctrl + c` を押します。

## 7. 再接続方法
以下のコマンドで再接続が可能です。

```
datalab connect --zone <zone> --port 8081 <instance-name>
```

# エラー対応
## Quota 'NETWORKS' exceeded
Cloud Datalab VM インスタンスを作成時に以下のエラーが発生した場合は、VPCネットワークの作成可能上限数に達しているものと思われます。
そのため不要なVPCネットワークを削除すれば上記のコマンドが成功します。

```
Creating the network datalab-network

ERROR: (gcloud.compute.networks.create) Could not fetch resource:
 - Quota 'NETWORKS' exceeded.  Limit: 5.0 globally.

A nested call to gcloud failed, use --verbosity=debug for more info.
```
Jetson AGX Xavier developer kit で aarch64 + Vulkan 開発環境を整える

## 背景

Android + Vulkan 開発案件, aarch64 で機械学習やグラフィックス(可視化, レンダリング, 描画)開発案件などがある.
AWS などのクラウドでは, グラフィックスの確認が困難(画像を転送して手元で確認しなくてはならない).
エミュレータでは実行が遅すぎる.
性能のよい x86 でクロスコンパイルする手もあるが, いろいろなライブラリの cross-compile がめんどい.

RockPro64 は 4 core a72 + 2 core で CPU 性能はそこそこ良いが,  Vulkan 対応していない(GLES も mesa の llvmpipe で CPU 実行?)
Raspberry Pi 4 も Vulkan 非対応(GLES は HW 対応らしいが).

いずれにせよ, 両者ともグラフィックス開発マシンとしてはメモリが少なく(4GB)コンパイルが out-of-memory でこけやすい.

Jetson AGX Xaviar developer kit は 8 core ARMv8.2(A72 相当?) + メモリ 16GB + Volta グラフィックス(Vulkan 対応)があるのでよい.

AGX Xavier の廉価版(?) Jetson Xavier NX が 2020/03 くらいから販売予定ですが, メモリ 8GB です.

そのうち RTX core 搭載 Xavier 出てほしいですね(優秀な小学生さま向けレイトレーシング学習キット用, リアルタイムレイトレーシングで自律運転用)

## HW まとめ情報

https://elinux.org/Jetson_AGX_Xavier

## 利点

* 8 core AARCH64 + 16 GB mem で開発(C++ コンパイル)が快適なことが予想される
* Vulkan 1.1 が使える
* 一応 NVIDIA が定期的にドライバアップデートなどしてくれているので, 2,3 年くらいは使えそう.
* 2019/12/02 時点では, 税込み 10 万円以下で買えるので, 消耗品費として扱えよい.

## 欠点,  注意事項

* 内臓 eMMC(?) は 32 GB しかないので, 開発用領域などに M.2 あたりで SSD 追加必須.
  * アップデートで OS 更新すると disk 初期化されてしまうので注意
  * M.2 スロットは **NVMe SSD に対応**. SATA ではないので注意 > Install NVMe SSD on NVIDIA Jetson AGX Developer Kit https://www.jetsonhacks.com/2018/10/18/install-nvme-ssd-on-nvidia-jetson-agx-developer-kit/
  * M.2 を挿した場合でも, x16 PCIex スロットと共有できるとは思われる(x16 スロットが x8 接続, M.2 が x4 接続と思われる) https://developer.nvidia.com/embedded/develop/hardware
* USB ポートが少ない(A 一つ. USB-type C 一つ)
* PCI-ex は x16 Gen4(!)ですが, RTX 20180 Ti などの NVIDIA GPU 挿して dGPU として使うのはできません(今後予定はあるようですが... https://devtalk.nvidia.com/default/topic/1063568/jetson-agx-xavier/what-card-can-i-insert-on-jetson-xavier-pcie-/)

## セットアップ

初期状態では, 4 コアのみで有効クロック低め(1.2 GHz)なので, リミットを外します.

Jetson Xavier を動かしてみた。
http://takesan.hatenablog.com/entry/2018/09/13/233334

を参考にします.

```
$ sudo nvpmodel -m 0

# optional
sudo jetson_clocks
```

jetson_clocks は optional です. 設定すると最高性能モード(?)になるようですが, そのかわり URL 先のようにファンがうるさくなります.

`nvpmodel -m 0` だけでもいいかもしれません. 冬場だとほんのりあったかで多少 Jetson 暖房としても活用できます.

 
## Vulkan

vulkaninfo で version 1.1.70 でした.
また, vulkan-smoketest が動作するのを確認しました.
ただし, 使える NV 拡張はさほど多くはありません.

## アップデート

そのままでは CUDA などが入っておらず, firmware も古いので, 
開発を始める前にまずはアップデートをおすすめします.

https://developer.nvidia.com/embedded/jetpack

GUI があるのでアップデートは楽です.
　
ただ, OS image をアップデートする場合, 内臓 disk 初期化されてしまいますのでご注意ください

## コンパイル速度

embree-aarch64 を Release でコンパイルしてみました.

RockPro64 : 5 分ほど
AGX Xavier : 2 分ほど(4 コア低消費電力モードだと 10 分)

なかなか良いのではないでしょうか.
ちなみに Threadripper 1900X(8 cores)だと 42 秒でした.

## NVMe 速度

Crucial SSD M.2 1000GB P1(1 TB. Gen3 x 4)を追加しました.

hdparm でテストしてみます.

```
$ sudo hdparm -t /dev/nvme0n1

/dev/nvme0n1:
 Timing buffered disk reads: 4038 MB in  3.00 seconds = 1345.92 MB/sec
```

1.3 GB/s でした. 仕様上は read 2 GB/s ですのでいくらか遅いようですが, 実務上は十分な速度かと思います. NVMe(SSD)に適した計測ツール変えたらより正確に速度を算出できるかもしれません.


## TODO

* [x] 最新ドライバ, 最新 JetPack インストール
* [ ] Sascha 先生の Vulkan サンプル https://github.com/SaschaWillems/Vulkan など, 各種 Vulkan アプリの動作検証 
* [ ] 今後のドライバアップデートで Vulkan cooperative matrix にもし対応したら,  Vulkan から Tensor core を叩けるか試す
* [x] Jetson PyTorch(arm64 + CUDA 対応) を試す
  * とりあえず動くの確認しました. 
* [x] PyTorch のコンパイルを試す
  * non-CUDA ビルドは確認しました.
kotlinでビット演算した際にハマったこと

``` kotlin
val data: ByteArray = listOf<UByte>(0x80, 0x01).map { it.toByte() }.toByteArray()
val v: Int = data[0].toInt() + (data[1].toInt() shl 8)
assertEquals(0x0180, v) // <- ここでエラー
```
こうすると、 `data[0]` が実はマイナスの値として扱われてしまうのでエラーになる

``` kotlin
val data: ByteArray = listOf<UByte>(0x80, 0x01).map { it.toByte() }.toByteArray()
val v: Int = data[0].toUByte().toInt() + (data[1].toUByte().toInt() shl 8)
assertEquals(0x0180, v) // <- OK
```
こんな感じに一度 `toUByte()` してあげればOK
Python for .NETを使ってPandas DataFrame から System.Data.DataTableへ変換する

# Pythonと.NETの表データ交換

そもそもPython -> .NETでデータフレームを交換する場合、.NET側はDataTableという標準ライブラリのクラスがあるので、それが適しています。決してPandasやdplyrのような高機能なデータ処理能力は無いのですが、とりあえずマッピングすることができます。
BayesServerでPythonからも呼びたい場合は、以下にあるようにJPypeを使ったJavaライブラリへのアクセスを推奨されているようです。

[Setup Python](https://www.bayesserver.com/code/python/setup-py) 

一方で、pythonnetでもいいよ、と一言書いてあり、何で.NETネイティブなのに、Javaラッパーを通さないといけないのかよくわからないので、そちらで行くことにしました。RのラッパーもJavaラッパーを通します。これだと、APIリファレンスを2種類見ないといけない羽目になります。(どっちみち.NETライブラリに改造を加えて、再ラップするので）
最初からPythonにしておけば良かった。。。

# pythonnet

pythonnet はPython for .NETと呼ばれる、Pythonから.NETのアクセスライブラリです。
http://pythonnet.github.io/
Pythonから.NETを呼び出す場合、.NETからPythonを呼び出す場合の双方で使えますね。

Python + .NETですと、IronPythonを思い出す人もいるのでしょうけども、そちらは.NET上で動くCLI言語です。これだと、データサイエンスなどで定評のあるライブラリも対応は限られます。というかnumpyが動きません。

pythonnetは言語間の接続を行うだけなので、両者の良いところを残したまま使えます。最新の.NET Coreなどにも対応します。
感覚的に言うと、

* Pythonから、.NETのライブラリを using ではなく importで使える。

```Python
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import Form
```

import clrというのが趣があります。

* .NETから、Pythonのライブラリを .NET 上でimportできる

```C#
dynamic np = Py.Import("numpy");
var x = np.cos(np.pi * 2);
```

こっち方向は、 @hogegex さんの記事があります。

[.NET (C#)からpythonを呼び出す](https://qiita.com/hogegex/items/3743225a7af13e93df78)


用途としては、Pythonから.NET独自のライブラリ（ビジネス系など）を呼び出したり、.NETから数値演算のタスクを投げたりなどが考えられます。Python上で.NETのGUIライブラリを使って、アプリを作れるのは中々良さそうですね。
ただ、私の用途はあくまでBayesServerのライブラリをPythonから呼ぶだけなので、以下のことができれば、おおむね完了です。

# Python DataFrame -> .NET DataTable変換 

BayesServerのリファレンスにはヘルパークラスとして、jpype1を使ったデータフレームのマッピングヘルパー関数が用意されています。

[Pandas DataFrame helper functions](https://www.bayesserver.com/code/python/data-frame-utils)

おそらく、jpype1を使った変換は癖があるので、こういったものを用意してくれていると思うのですが、pythonnetだともっとストレートに書けます。
ほぼ、コピペで.NET向けに書き直してみました。

``` Python
# %%
import numpy as np
import pandas as pd
import clr
from System.Data import *
# %%
def _to_net_class(data_type):
    """
    Converts numpy data type to equivalent .NET class
    :param data_type: the numpy data type
    :return: The Net Class
    """
    if data_type == np.int32:
        return clr.GetClrType(Int32)  
    if data_type == np.int64:
        return clr.GetClrType(Int64)  
    if data_type == np.float32:
        return clr.GetClrType(Single) 
    if data_type == np.float64:
        return clr.GetClrType(Double) 
    if data_type == np.bool:
        return clr.GetClrType(Boolean) 
    if data_type == np.object:
        return clr.GetClrType(Object) 

    raise ValueError('dtype [{}] not currently supported'.format(data_type))

# %%
def to_data_table(df):
    data_table = DataTable()

    for name, data_type in df.dtypes.iteritems():
        net_class = _to_net_class(data_type)
        data_table.Columns.Add(str(name),net_class)

    for index, row in df.iterrows():
        xs = [None if pd.isnull(x) else x for x in row]
        data_table.Rows.Add(xs)

    return data_table

```

これで、pandasのデータをするっと.NETライブラリに持ち込めるので、いわゆるExcel表のようなGUIや、データベースとの交換も楽になるかもです。
clr.GetClrType()というのがtypeof(やObject.GetType())の代わりみたいなものだと思ってください。
【GitHub】ローカル環境にあるフォルダをリモートリポジトリにアップロードする際に詰まった話

## はじめに

[2019新卒 エンジニア Advent Calendar 2019](https://qiita.com/advent-calendar/2019/2019-graduates) 2日目の記事です。

今年入社したkitaです。

GitHubへの登録は大きく分けて「GitHub側でNewボタンを押してリポジトリを作り、それをgit clone パスでローカルに持ってくる」というやり方と「ローカルでGitリポジトリを作り、それをGitHubに新規リポジトリとしてpushする」というやり方が考えられるが、今回は


`ローカルでGitリポジトリを作り、それをGitHubに新規リポジトリとしてpushする`

でやっていこうと思う。

## なぜこれをやるのか

* Webサイトを公開したかった
* GitHub Pagesで公開する課題が与えられたので

## GitHubのQuick setupに表示されたコマンドライン通りにやってみる
```
echo "# mytest" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin URL
git push -u origin master
```

## 詰まったところ（エラー）

* コミットできない
* `git remote add`って何？
* originって何？
* `git push`できない

## 原因と解決

### 1. コミットできない→`git add`していなかった


Git管理しないとコミットできないじゃん。
コミットできない〜と嘆いていたのはこれが原因だった。


### 2. `git remote add`の意味を知らなかった

逆に`git remote remove`がある。リモートを追加(add)したり、削除(remove)したり出来る。

### 3. `git remote add name URL` となっていた部分のnameがoriginだと思わなかった

originは、GitHubがリモートリポジトリにデフォルトで付ける名前である。
リモート、橋の向こう側にいるのはorigin。
僕は複製された存在だ。

### 4. `git push` ができなかった

```
$ git push
fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use
    git push --set-upstream origin master
```
メッセージにあるように、`git push --set-upstream origin master`すれば解決


あと`git remote add origin URL`としたときに、別のリポジトリが存在していた。

リポジトリを消す：`git remote remove origin` リモートリポジトリは消えない。ローカルの情報だけ。

リポジトリのURL変更：`git remote set-url origin https://github.com/ユーザー名/リポジトリ名.git`



## 振り返り

まだまだGitについての理解が足りていないし、一晩寝たら忘れてしまう。
使い続けるor自分で解決できる能力を育てていく必要がある。


[【関連】git config に関する記事はこちら](https://qiita.com/kitagawa_shouri/items/c956141aeb608d5cfccc)
開発環境の構築で挫折することのない優しい世界【 Gitpod という選択】

# やる気をいっきに削ぎ落とす「環境構築」
私が学生の頃プログラミンをやりたい！と思ったときの話です。
フリーランスという言葉がちらほら聞かれるようになり、海外在住で仕事とかできたら最高じゃん！と安易な考えからプログラミングを勉強しようとネットで調べ始めました。
パソコンとか機械ものは好きな方だったし、iPhone 3GSの日本発売と同時に買って「僕って異端か？」と自負があったり。。（後に「パソコンの大先生」というワードを知り、これやん！となります）

**「プログラミングするならMacだよね」**

まずここで一度折れかけます。世の中にWindows以外のOSがあることを知ります。まあMacという昔カラフルだったパソコンがノートでもあるよ、程度のことは知っていましたが、違うソフト？で動いているとは知らなかったです。当時は「スタバでMBP」というトレンドが出来上がる直前の頃でした。
でもまあ調べているとWindowsでもいけそうかな？..

**「 黒い画面（ターミナル）を開いて..」**
**「Virtual VOX を用意して仮想がｔｈｈ；ｈｆｌｋｓｈｄ..」**

ここで諦めます。「皆さんご存知の〜」みたいな感じで紹介されているのでその一つ一つを調べる気力もなく。。まあ調べれば出てきたんですが、文章だけじゃよくわからんのよ。あとメモリ５１２MのPCでまず動かない。（大学１年生のときに秋葉原の石丸電気で１５万くらいで買ったPCです。）そして時間をかけて同じ手順でやってみても同じ画面にならない。同じ結果にならない。そして何より自分が何をやっているのかわからない。

# 熱のある内に思い立ったらすぐに始められる。素晴らしい時代
先日 Docker （仮想化というものを実現する技術のひとつです。厳密には仮想化というよりプロセスと捉えなさいと怒られたりしますが。。）関係のソリューションを提供している海外スタートアップの方にお話を聞く機会がありました。

その方のお言葉..
>「これからは開発環境を構築するという概念はなくなる。安いPCやラズベリーパイ、あるいはスマホ>で誰でもすぐにHello World画面から開発を始められる」

という言葉を聞き、いい時代になったものだなあと、また同時にこれからのデジタルネイティブ世代が仕事を全部かっさらっていく日も近いなと焦燥感を覚えました。

とまあ前置きが長くなりましたが、
**"開発環境構築" で挫折する人はいなくなるよ。高価なPCがなくてもブラウザ一つで始められるよ。** という内容について書いていきます。

# 用意するもの
ネットが見れるもの（PC, スマホ, ..）

以上。
あとは [GitHub](https://github.com/) のアカウントを作りましょう。
（具体的には ["GitPod"](https://www.gitpod.io/) というサービスを使います。同じようなサービスを自分のPCや借りたサーバー上に構築することも可能です。そちらについては別の記事で紹介しております。）

# 手順（WEB開発を始められる状態まで）
1. ブラウザで [GitHub](https://github.com/) にサインインします。（Chrome推奨です。）
2. PC版のChromeを使っている方は「Chrome ウェブストア」で「Gitpod Online IDE」という拡張機能を追加しておきましょう。
3. GitHub のマイページで、左上の方にある「New」というボタンを押してリポジトリを作成しましょう。
![github-my-page.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332187/a74e7a0d-fa15-82c1-0080-2b0910a14116.png)
ここでは「nodejs」（任意です）という名前にします。（「Private」を選択したいところですが、無料の範囲では使えないので「Public」を選択します。）
![repository-create.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332187/ff881103-1a8b-e715-e394-1f4325505bc6.png)

4. リポジトリ作成後以下のような画面になります。ここで前述の拡張機能を入れておくと右上に「Gitpod」というボタンが表示されているはずなので押します。![pod-before-run.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332187/59e20456-5864-9584-221c-bc6cfdc4aa36.png)

5. 立ち上がるまで少し待ちます。。その後以下のような画面が表示されます。（VScodeですね！）![pod-after-run.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332187/46144391-f5e2-58e4-af72-bf82169764f6.png)

6. 一通りの開発言語がセットアップされています。（プラグインは自分で追加も可能ですが、VScodeとは勝手が違い少し面倒です。）![pod-language-useable.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332187/3b9ac83e-6086-15cb-ab5d-eb8aa113581f.png)

7. さらにプレビュー機能も使えます。試しにhtmlファイルを作成してプレビューのボタンを押すとブラウザの表示画面を出してくれます。![html-preview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332187/59624f92-d997-df5b-c911-4b61f29db550.png)


# とりあえず勉強したい！という用途なら十分ですが。。
無料でここまでできるのは本当にすごいことだと思いますが、やはり制約もあります。

- 環境を起動できる時間は月100時間まで
- 前述の通り「Public」（公開される）しか選べない →月9$ の有償版で「Private」選択可能
- インフラ部分を操作できない →ミドルウェアやカーネル部分は触れないので Docker とかは使えない
- （基本的に）作成したものをサービスとして提供できない

ただ、教本片手にテストコードを打ち込んでいくには十分すぎる環境だと思います。

# 最後に
Cloud IDEと呼ばれるこのようなサービスは、以前からいろいろあります。特に現Amazon提供のCloud9とかが有名です。ただGitHubは遅かれ早かれ使用すると思いますし、同アカウントでこのようなサービスを利用できるので、とてもシンプルに勉強を始められるのがいいですね。
ブラウザから使用できるのでタブレットなどでもOKで、「パソコンを持たない世代」の方も思い立った日にすぐ勉強を開始できるので素晴らしいと思います。
PythonのBayesianOptimizationを使ってみた

https://github.com/fmfn/BayesianOptimization

こちらのベイズ最適化を使ってみました。ちょっとだけ工夫が必要だったので、残しておきます。

# maximizeしかない

```
optimizer.maximize(
    init_points=2,
    n_iter=3,
)
```
READMEより。
最適化のメソッドが`maximize`しか用意されていないように見えました。僕がやりたかったのが、検索ランキングの最適化（よりランキングの上位でヒットするようにしたい）だったので、単純に順位にマイナスをつけて最適化するということをしました。

```
optimizer = BayesianOptimization(
    f=foo,
    pbounds=pbounds,
)
```
この`foo`の返り値を負にしたということです。`maximize`や`optimizer`側でやり口があるかもしれませんが、見つけられませんでした。

# 最適化対象の関数の引数が限定される
```
def foo(x, y):
    return -x ** 2 - (y - 1) ** 2 + 1
```
これが最適化対象の関数。

```
pbounds = {'x': (2, 4), 'y': (-3, 3)}
```
こんな感じで引数の範囲を与えて、その中で最適な値を探しに行くという仕組みです。僕のところでは`foo(x, y, z)`という感じでもう一つ引数を与えたいということがあって、そのまま`maximize`に食わせたらエラーとなった、というお話です。対策としては`z`をグローバル変数にして無理やり渡しました。正しいかはわかりません。

# 二つの値の合成比率を決めるときの注意
これはベイズ最適化関係ないのですけれど、xとyの最適な合成比率を決めるときに、最初以下のように書いていました。

```
def foo(a):
   return a*x+y 
```
で、

```
pbounds = {'a': (0, 100)}
```
なんてやっちゃってました。だめだめですね。

```
def foo(a):
   return a*x+(100-a)*y 

```
こうして

```
pbounds = {'a': (0, 100)}
```
こうすることでうまくいきました。
エクスプローラーにDVDドライブが表示されなくなった！

##環境
Windows 10 19033.1
内蔵DVDドライブ使用
winであれば今回の原因に環境はあまり影響ないと思います。

##背景
ウキウキでCDを買って帰ってCDを入れてみると...
エクスプローラーにDVDドライブが表示されてない！？
少しはｶﾀｶﾀ言ったし、DVDドライブ自体は壊れてないはず...!
これじゃあ買ったCD聞けれへんやん！！！！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269181/3be7774c-011c-7dba-b9fe-df3ffe4d78f2.png" width=50%>

##状況確認
デバイスマネージャー上問題なし！(DVDドライブは表示されており、エラーマークもない）
念のためドライバを一度アンインストールし、再起動したものの変化無し
ついでに公式ドライバを探したけど見当たらなかった
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269181/1810d9aa-0d97-0114-b11c-abbd2dd42487.png" width=50%>


泣く泣くPCケースを開けてコードを抜き差し
こちらも変化なし

いろいろググってレジストリが原因と思い弄る
（Windows10 ver1511以降は効果ないらしいことを後で知った)
参考:https://freesoft.tvbok.com/tips/windows/dvdbd.html
変化なし

おそらくハードウェアではなくソフト側の問題だろとほぼ確信した。
そして唐突にひらめいた

##原因
ドライブ文字が割り当てられてない！
win10ならwinアイコン右クリして、ディスクの管理を起動
下へスクロールするとDVDを発見!!

DVDを右クリックして、ドライブ文字の変更して適当なドライブ名で割り当て！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269181/f8cf282c-efaf-3101-3912-018e97fcbb68.png" width=50%>

そりゃあ割り当てられてなかったら表示されませんわ...
いつから消えてしまったのかは謎
完全に盲点だった。めでたしめでたし。
俺の正規表現は長い

この記事は[株式会社ACCESS Advent Calendar 2019](https://qiita.com/advent-calendar/2019/access)の7日目の記事です。が、内容は個人的なものです。

# まえがき

皆さん正規表現は好きですか？僕は嫌いです。

そんなある日、[「7の倍数」を表す正規表現](https://qiita.com/jkr_2255/items/8bae27d026754d4e2474) という記事を見つけました。
ちょっと分かりづらかったですが、「7の倍数」という言語を受理するDFAを作り、そこから機械的に正規表現を作っていったわけですね。

DFA -> 正規表現 の変換は StackExchange の[この質問ページ](https://cs.stackexchange.com/questions/2016/how-to-convert-finite-automata-to-regular-expressions)の図で分かりやすく表現されています。

しかし、なんとこの正規表現、期待通りに動いてくれません。Chrome DevTool で `(問題の正規表現).test('7')` を評価すると `false` になってしまいました。

正規表現自体は正しいはずなのに。

僕がいつも使ってる Elixir くんならうまくやってくれるはず…

```elixir
$ iex
Erlang/OTP 20 [erts-9.3.3.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]

Interactive Elixir (1.9.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> ~R/\A((...中略...))+\z/ \
...(1)> |> Regex.match?("7")
** (Regex.CompileError) regular expression is too large at position 19647
    (elixir) lib/regex.ex:209: Regex.compile!/2
    (elixir) expanding macro: Kernel.sigil_R/2
    iex:1: (file)
    (elixir) expanding macro: Kernel.|>/2
    iex:1: (file)
```

`regular expression is too large` と悲鳴を上げて死んでしまいました。

JavaScriptでダメだったのも実は正規表現が長すぎたためかもしれません。

こうなると悪戯心に火が付きます。

# 正規表現の長さの限界は？

僕の検索力が足りず、明確にいくつみたいなのが書いてあるドキュメントが見つかりませんでした。
(Elixir -> Erlang の `re` -> PCRE という依存までは見えましたがPCREでの制限がどうなってるのかよく分からず…)

なのでテキトーに二分探索してみます。結果は環境に依存する可能性があります。

## JavaScript

```js
const testN = (n) => {
  const source = Array(n).fill('a').join``;
  try {
    return new RegExp(source).test(source);
  } catch(_) {
    return false;
  }
};

testN(50000);
// false

const tryAndContinue = (previousN, currentN) => {
  const diff = Math.abs(currentN - previousN);
  if (diff <= 1) {
    return [previousN, currentN];
  }
  const nextN = currentN + (testN(currentN) ? 1 : -1) * (diff >> 1);
  return () => tryAndContinue(currentN, nextN);
}

let continuation = tryAndContinue(50000, 25000);

while(typeof continuation === 'function') {
  continuation = continuation();
}

continuation
// (2) [32765, 32766]

testN(32766);
// true
testN(32767);
// true
testN(32768);
// false
```

`a` を 32768個並べるだけでアウト、ということが分かりました。

## Elixir

```elixir
test_n = fn n ->
  source = String.duplicate("a", n)
  case Regex.compile(source) do
    {:ok, regex} -> Regex.match?(regex, source)
    _            -> false
  end
end

Stream.unfold({50000, 25000}, fn {previous_n, current_n} ->
  diff = abs(current_n - previous_n)
  cond do
    diff <= 1 ->
      nil
    test_n.(current_n) ->
      next_n = current_n + div(diff, 2)
      {next_n, {current_n, next_n}}
    :else ->
      next_n = current_n - div(diff, 2)
      {next_n, {current_n, next_n}}
  end
end) \
|> Enum.take(-3)
# => [32768, 32765, 32764]

test_n.(32764)
# => true
```

こちらは `a` を 32765個並べるとアウト。JavaScriptに近いですがちょっとだけ違いがありますね。

# もっと短く壊す

`((((((((((a))))))))))` みたいな感じで `()` を多用したりして複雑にすると上限がもっと短くなります。
最初の正規表現は `()` だけでなく `|` や `[`、 `*`、`+` も使っているのでダメだった感じですね。

追記: Elixirだと `~R/(){8192}/` が知る限り最短でこのエラーを出せるようでした。

みなさんもぜひお気に入りの言語で試してみてください。

---

QAの人に前後を挟まれたためか、奇しくも「コーナーケースのテスト」みたいな話になりました。明日の記事は @illypong さんが数多のバグをワンパンしてくれそうな雰囲気です。お楽しみに！
Excelって名前しか知らないPCに不慣れな感覚派22歳プログラミング完全未経験者がRubyを習得するまでの軌跡。Part4

【HTML-CSS編】
--
はじめはpart2,3のように用語の説明や文型をまとめようとおもったがprogateの説明だけで完成されており、理解することが可能。最低限大事なことだけまとめる。

1.HTMLとCSSってなんなのか　CSSは色、大きさ、形などデザインに関するプログラミング　HTMLが素材でCSSが職人。
2.CSSはHTMLとは別にファイルを作って記述する。
3.プロパティはCSSの機能　ex.color.font-size,background-color,width,height

やってて感じたこと
--
HTML-CSSはRubyと比べると内容自体はすごく簡単で意味がわからないということはほぼないと想う。ただRubyが詩だとするとHTML-CSSは単文といった感じで1文1文で完結していて面白みはあまりない。
[GraphQL] 基礎 1

ShopifyがGraphQLを採用していくということで、まとめました、次回は具体的な例をC#で書いてみます。今回はまとめだけ。

# GraphQLとは？

例えば下記のエンドポイントに対して
`/admin/api/2019-10/graphql.json`

下記のJsonをPOST

```json
query {
  product(id: "gid://shopify/Product/10079785100") {
    title
    handle
    createdAt
  }
}
```

レスポンスは下記

```json
{
  "data": {
    "product": {
      "title": "The T-Shirt",
      "handle": "the-t-shirt",
      "createdAt": "2017-03-27T19:24:10Z"
    }
  }
}
```

SQL Queryを投げているようなイメージ

# なにがいい？

## 複数のendpointをたたく必要がない

RestAPIの場合は1Pもしくは1体験を生成するために、複数のendpointを呼ぶ必要があるケースがあります。ですが、GraphQLだと1 endpointで解決することができます。


## 余分なデータを呼ばなくてもいい

一般的に1APIをたたくと、1セットのデータが返ってきます、中にはいらないデータもあり非効率ですね。GraphQLを使うと必要なデータのみを抽出することができます。

## ドキュメンテーションが自動かついけている！？

ここはあとで確認しますが、自動かついけているそうです。

# 次

- Queries
- Mutations
- Variables
- Pagination

に関してまとめていきます。
nginxとlaravelでlog rotateをしてみる

## ログローテートで対象のlogファイルをrenameする

**_logファイルをrotateしたかったか　理由↓↓_**

サイトのフォーム等で離脱があったり（アナリティクス）とかをlogに書き込み、そのログを1日1回解析するシステムにログファイルを読ませる必要があったため

その際に解析するシステム側には同じlogファイル名を参照するようにしたかったから！！！！！

**では　コード例から**

フレームワークはlaravel、ミドルはnginxを使用してます。

``` 
# 対象のログファイル
/var/www/laravel/shared/storage/logs/analyze.log {
su nginx nginx
  # 毎日ローテートする
  daily
  # 30世代分古いログを残す
  rotate 30
  # ログファイルがなくてもエラーを出さない
  missingok
  # ログファイルが空ならローテーションしない
  notifempty
  # ログファイルをコピーし、内容を削除
  copytruncate
  
  # dateフォーマットを任意のものに変更する
  dateformat %Y-%m-%d
  
  # ログローテーション後に実行
  postrotate
  /bin/kill -HUP `cat /var/run/syslogd.pid 2> /dev/null` 2> /dev/null || true
  endscript
}

```

これをプロジェクトソース内でテキストファイルとして持っておけばサーバーに配置された後に

**cp analyze.txt /etc/logrotate.d/analyze**

でlog rotateに設定完了。

テストしたいときは
**logrotate analyze**
なり
**logrotate -f analyze**


de

実行してください。

これで毎日、

```
analyze.log2019-09-04
analyze.log2019-09-05
analyze.log2019-09-06
analyze.log
```

といった具合にファイルが作らて、

analyze.logが本日付のファイルで次の日になったら

analyze.log2019-09-07が作成されます。


**以上**
Rustのfilter()について

# TL;DR
本稿で述べるような処理においてはループの中で`if`を使用した方が速いという話．

# 本題

`filter()`を用いた以下のコードは1以上100未満の偶数を出力する．

```rust
for i in (1..100).filter(|&x| x % 2 == 0) {
    println!("{}", i);
}
```

本稿では`0 ... 10000`という等差数列`vec`の要素のうち，偶数である要素を足し合わせる処理したい．

```rust
const MAX: u32 = 10000;

fn main() {
    let vec: Vec<u32> = (0..MAX).collect();
}
```

そこで，`filter()`を用いた/用いない場合についてその速度を比較する．

## `filter()`を使わずに`if`を使用した場合


```rust
let mut result = 0;
for i in &vec {
  if i % 2 == 0{
    result += i;
  }
}
```

## `filter()`を用いる
### イテレータとしてループで使用した場合

```rust
let mut result = 0;
for i in vec.iter().filter(|&x| x % 2 == 0) {
  result += i;
}
```

### ループ前に使用した場合

```rust
let mut result = 0;
let vec: Vec<u32> = vec.iter().cloned().filter(|&x| x % 2 == 0).collect();
for i in &vec {
  result += i;
}
```

# 数値解析

10000回繰り返すのにかかる時間を計測した．
## ソースコード

```rust
use std::time::{Instant};

const TRIAL: u32 = 10000;
const MAX: u32 = 10000;

fn main() {
    let vec: Vec<u32> = (0..MAX).collect();

    // (a)
    let mut result = 0;
    let start = Instant::now();
    for _ in 0..TRIAL{
        for i in &vec {
            if i % 2 == 0{
                result += i;
            }
        }
    }
    println!("\n(a) Result: {}, elapsed:{:?}", result, start.elapsed());

    // (b)
    result = 0;
    let start = Instant::now();
    for _ in 0..TRIAL{
        for i in vec.iter().filter(|&x| x % 2 == 0) {
            result += i;
        }
    }
    println!("\n(b) Result: {}, elapsed:{:?}", result, start.elapsed());

    // (c)
    result = 0;
    let start = Instant::now();
    for _ in 0..TRIAL{
        let vec: Vec<u32> = vec.iter().cloned().filter(|&x| x % 2 == 0).collect();
        for i in &vec {
            result += i;
        }
    }
    println!("\n(c) Result: {}, elapsed:{:?}", result, start.elapsed());
}
```

## 結果

```bash
$ cargo run --release
   Compiling filter_if v0.1.0 (/Users/scstechr/Works/projects/filter_if)
    Finished release [optimized] target(s) in 1.88s
     Running `target/release/filter_if`

(a) Result: 841896832, elapsed:124.80438ms

(b) Result: 841896832, elapsed:130.393264ms

(c) Result: 841896832, elapsed:157.500689ms
```

## 結論
今回の場合においてはループの中で`if`分岐した方が速い．
(というより`filter()`は遅い?)

### todo
`cargo`にはベンチマーク機能があるらしいので，そちらを記事に追加して更新する．
vscodeのLaTeX Workshopで「chkTeX」による日本語エラーが頻出する


# はじめに

- http://msz006aeug.hatenablog.com/entry/2019/02/08/160404
- https://blog.mktia.com/create-environment-to-edit-latex-easily/
- https://qiita.com/skikkh/items/707e8a5def368a69e9a6

などを参考にして、

「VSCodeで　LaTeXによる論文書きを行いたい！」
という時があると思います。

私も、これらの記事などを参考に、VSCodeで卒論書きを始めたのですが
chkTeXをオンにすると、日本語エラーが頻出しました。


できれば、chkTeXを利用して、TeXをLintしながら使いたいです。
日本語エラーが出ないように修正する必要があります。

# 修繕策

日本語エラーは19番のLintで、ひっかかっています。
（本当は別のエラーなのですが、英語以外を想定していないため、日本語だとエラーがでることがあります。）


そこで、
`.chktexrc`という設定ファイルを、PDF化したいTeXファイルがあるディレクトリと同じ場所に作成し

```
CmdLine
{
    -n19
}
```

としてください。

こうすることで、$19$番目のLintのみを無効化することができます。

# 参考サイト

- [chktexによるダッシュに関する警告を黙らせる方法](https://qiita.com/kaityo256/items/e6af33b985f27864c97d)
ディレクターあるあるからのケーススタディ

ディレクター勉強会アドベントカレンダー３日目。
ネットに散らばるディレクターの体験談から学びに繋がりそうなポイントを見つけていきます。

<h2>CASE.　作成者不在のスパゲッティコード改修

制作スタッフが嫌がることの一つに「他社（他人）が作ったシステムの改修業務」があります。
作った本人が改修した方が効率は良いですから当然と言えば当然。

ただし、どうしようもない状況もありえます。
例えば...サイト構築した制作会社はすでに消えている...とか。

今回のケースはまさにそれ。ある制作会社でのお話です。
![code.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154934/779de696-bce7-2e92-71eb-2ce8a60c2ca6.jpeg)

>ある日ディレクターが「既存サイトに新機能を加える」という依頼を受け、詳細を会社に持ち帰ってエンジニアと中を見てみると...後付けされた機能が満載！負荷がものすごいことになっていたそうな。
例えるなら、プレハブ住宅に後から壁に穴をあけて、窓を無理やり作り、屋根に煙突と梯子を取り付けた、みたいな状態。しかも機能が複雑に絡みあっているため、使われていないシステムも落とせない..と。

>制作スタッフからは“後付けは構わないが、さらに重くなる”、“動作確認にかなり時間取られると思うから、納期に間に合わせるのは100％無理。…っていうか、このシステムダメダメじゃない？”と大ブーイングの嵐。ディレクターはそっかー、そうだよね……と返事をしつつ、どうしたものかと考えあぐねてしまいました。

>実は、クライアントからは「軽くしたい」という要望も一緒にもらっていたのです。

>そこで考えたのが、現状システムに新機能を後付けするコストと理由に加えて、「システムをまるごと作り直す」という提案。特に現状では使っていない機能が多く、その反面、クライアントの要望に合致するサイトは非常にシンプルで、全取っかえした方が制作スタッフの負担も少なかったのです。

>ということで、全取っかえの見積もりを後付けの見積もりより若干安く出したそうです。軽くなるし安い、ということでクライアントも納得、制作スタッフもご機嫌を直し、めでたしめでたし。ということでした。

話は以上です。
ここからディレクターの学びにつながるポイントをピックアップしてみます。

<h3>POINT.　常にクライアントの望みの本質を考え、それに合う提案をする

今回はクライアントの注文をそのまま実行には移しませんでしたが、代わりに「要望の本質に応える提案」ができたところがポイントです。言われた通りにやるケースもありますが、別の提案をした方が良いケースもあります。
クライアントの要望が不可能だったり間違ったりしている場合は、なるべく否定はせずに新しい提案で流れを変えることが望ましいですね。

<h3>POINT.　ディレクターが売るのはサイト（成果物）じゃなくて「成果」

「今は使っていない機能が多い」という状況を踏まえると、依頼通りに改修するよりも新しく作った方が条件が良かったんですね。制作スタッフの意見もきちんと吸い上げつつ、社内の負担軽減にも成功しています。　

<h3>POINT.　成果≒クライアントの満足

ディレクターのミッションは成果を上げることですが、それと等しくクライアントを満足させることも重要です。同じ提案をするにしても、どう提案するかで全くイメージが変わってしまうこともあります。
今回は当初の依頼である「現状システムに新機能を後付けする作業」と「システムをまるごと作り直す」見積もりを両方出し、きちんと理由とコストを説明してクライアントを納得させたところもポイントです。
　

常にクライアントの側に立っていると思ってもらうことがディレクターの役目....
常に制作スタッフの側に立っていると思ってもらうこともディレクターの役目....

つまりみんなをハッピーにする仕事ってことですね！

お読みいただきありがとうございました！
【GAS】すでに同じフォルダ内に同一ファイル名が存在した時、連番をふって命名する

Driveは最近、ファイル自体をIDで管理するようになったので、ファイル名自体の重複を気にしなくなった。ひとえに不便なので機能を @acro5piano と協力して作成した。

```js
function fileExists(files) {
  return files.hasNext()
}

function getNextFileNameFromOutputFolder(outputFolder, fileName, index) {
  index = index || 0
  var maybeFileName = index === 0
    ? fileName 
    : fileName + "（" + index + "）"
  if (fileExists(outputFolder.getFilesByName(maybeFileName))) {
    return getNextFileNameFromOutputFolder(outputFolder, fileName, index + 1)
  }
  return maybeFileName
}

function incrementFileNumber(OutputFileName, folderId) {
  var OutputFolder = DriveApp.getFolderById(folderId);
  return getNextFileNameFromOutputFolder(OutputFolder, OutputFileName)
}
```
AI渋滞予知の紹介

NTTドコモ 先進技術研究所 赤塚です。この記事では、当日の人出から午後の渋滞を予測し、交通分散を促す、サイバーフィジカル融合の取り組みであるAI渋滞予知を紹介します。

とはいったものの、AI渋滞予知については、ドコモR&Dの広報誌 テクニカル・ジャーナルに詳しくまとめたのでそちらをご覧ください。

https://www.nttdocomo.co.jp/corporate/technology/rd/technical_journal/bn/vol27_2/006.html


この記事では、AI渋滞予知が従来の渋滞予測技術とどう違うのかについて触れたいと思います。


渋滞による経済損失は日本だけでも年間10兆円規模になると試算されており、ハード/ソフトの両面から様々な対策が進められてきました。その中でも、将来の渋滞を予測することは、予測情報を配信することで交通分散を促すなど、ソフト的な対策において重要となるため、数多くの研究が進められています。

<h1>従来の渋滞予測技術</h1>
従来の渋滞予測技術は、「どんなデータを使って渋滞を予測するか」という観点から、例えば下記の2種類に分けることができます。

<li>1．道路に設置されたセンサから得られるデータ</li>
<li>2．プローブカーデータ</li>

<h3>道路設置センサ</h3>
道路に設置したトラフィックカウンターという機器から得られるデータや、カメラ映像の解析結果などから、道路上を走行する車両の台数や平均速度を算出し、それをもとに渋滞を予測します。道路に設置されたセンサから得られるデータを使用するのは、下記のメリット、デメリットがあります。

<ul>
<li>メリット：非常に細かく正確なデータが得られる</li>
<li>デメリット：設置した場所に関してしか得られない</li>
</ul>

得られた台数や速度からどのように渋滞を予測するのかには、統計ベース、交通パターンベース、交通理論ベース、機械学習ベースなど様々な手法があり、歴史も長いです。

<h3>プローブカーデータ</h3>
最近話題のビッグデータというやつで、1台1台の車両（のカーナビなど）に内蔵されたGPSセンサから得られる、車両の速度などのデータをもとに渋滞を予測します。このデータを使用するのは、下記のメリット、デメリットがあります。

<ul>
<li>メリット：規模・範囲が非常に大きなデータを得られる</li>
<li>デメリット：センサを搭載した車両のデータのみなので交通量などは正確ではない</li>
</ul>

道路センサが設置された道路だけではなく、プローブカーデータが走行したあらゆる道路区間についてのデータが得られ、それをもとに渋滞を予測します。ただ、車両やカーナビのメーカー各社がバラバラにデータを持っているため、プローブカーデータだけから、道路を走行する車両の台数などを知りたい場合、その手法自体が研究対象になります。


<h1>従来手法の課題</h1>
従来の渋滞予測手法で用いられている道路設置センサから得られるデータや、プローブカーデータは、何れも「現在走行中の車両」についてのデータしか得られません。今はエンジンが切れていても、将来的に走行状態になる車両のデータは得られません。そのため、予測する未来が先になればなるほど精度が劣化します。

<h1>AI渋滞予知</h1>
AI渋滞予知は、渋滞のそもそもの原因である「人」に着目することで、現在走行状態にない車両が未来の交通状態に及ぼす影響までを加味して渋滞を予測します。手法の中身自体は過去の人口と渋滞のデータから、「人口から渋滞を予測するモデル」をつくるという、一般的な機械学習です。

ですが、現在走行状態にない車両の影響までを加味したモデルを作成することができるため、お昼時点の人口の分布から、その日の午後の交通状況（何時に帰れば何時に目的地に着くか）を高精度に予測することができます。「お昼時点」で午後の交通情報を知ることができるので、観光地に来ている人が「もう帰ろうか、もう少し遊んでいくか」という意思決定に活用することができ、交通分散や滞在先の経済活性化（一般的に遅くまで滞在した方が渋滞は避けられる）などの効果が期待できます。

ということで、テクニカル・ジャーナルをご覧ください。

https://www.nttdocomo.co.jp/corporate/technology/rd/technical_journal/bn/vol27_2/006.html
Vue.jsでYouTubeプレイヤーを埋め込む方法

#はじめに
Vue.jsでYouTubeを埋め込んだので、その方法を簡単にまとめていきます。(めちゃくちゃ簡単にできます！)

vue-youtubeというすぐれものが存在し、開発初心者の私でも容易に実装できました！！
[参考リンク](https://www.npmjs.com/package/vue-youtube)

YouTubeの埋め込みのみの記事ですので、他の部分は記載していません。ご了承ください。


#1.vue-youtubeをインストール
まずはvue-youtubeをインストールします。

```
npm install vue-youtube
```
#2.YouTubeを埋め込む
もう最終ステップです！！
あとはyoutubeタグを入れるだけ！めっちゃ簡単じゃないですか！？

`<template>`内にはこちらを。

```
<youtube :video-id="videoId" />
```

`<script>`内にはこちらを。
videoIdにはYouTubeIDを入れてください。URLのv=以降の11個のところです!

```
export default {
  data() {
    return {
      videoId: 'fHuO3Xaje98'
    }
  }
}
```

#最終的な全体コード
なんの装飾もない一番質素な状態ですが完成です！！

```ruby:App.vue
<template>
  <div>
    <youtube :video-id="videoId" />
  </div>
</template>

<script>
import Vue from 'vue'
import VueYoutube from 'vue-youtube'

Vue.use(VueYoutube)

export default {
  data() {
    return {
      videoId: 'fHuO3Xaje98'
    }
  }
}
</script>
```

#おまけ
youtubeタグ内にひと手間加えることで、プレイヤーのステータスをトリガーにイベントを発火することが出来るようです。

公式によると...
>Events
>The component triggers events to notify the parent component of changes in the player. For more information, see YouTube IFrame Player API.
![スクリーンショット 2019-12-02 17.41.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264523/4d88be40-a12a-674c-3ccc-feff3c6fc903.png)

なんとこんなにあるんですね！！

せっかくなので再生した時にconsole.logに「再生中です」と出してみましょう〜

`youtubeタグ`内にはplayingを、`<script>`内にはmethodsを追加します。

```ruby:App.vue
<template>
  <div>
    <youtube :video-id="videoId" @playing="playing" />
  </div>
</template>

<script>
import Vue from 'vue'
import VueYoutube from 'vue-youtube'

Vue.use(VueYoutube)

export default {
  data() {
    return {
      videoId: 'fHuO3Xaje98'
    }
  },
  methods: {
    playing() {
      console.log('再生中です')
    }
  }
}
</script>
```
動画を再生すると...
![スクリーンショット 2019-12-03 12.18.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264523/a1829265-2002-1990-33fa-cb2a1e0292cb.png)

やったー！大成功です！！:v_tone1:
Probability Distributions for Wireless Communications

お久しぶりです，濱です．
公開タイミングに間に合わせることができず，リアルタイム編集中です．

さて本記事では通信理論について，確率統計の学問とのかかわりに触れながら，簡単に紹介したいと思います．


# 通信理論と学問

最近はやりのAIは，まさに「確率統計」の基盤の上に構築されている分野だと思いますが，
実はそれ以上に通信の世界は理論によって体系づけられているのです．

そのために学ぶべき科目は，
- 確率統計
- 線形代数
でしょう．

1900年代前半に情報理論を確立したシャノンによって，確率統計の基に無線通信の理論も成り立っています．
また線形代数は，近年コア技術となっている送受信機で複数のアンテナを用いて通信する「MIMO」の確立により，欠かせないものとなりました．

今回は特に，無線通信の世界を理論的にモデル化するにあたり登場する，確率分布についてお話ししたいと思います．

# 確率分布

前回お話ししたシャノンによって導出された通信速度の限界値，

$ C = B \log_{10} (1 + SNR) $

ですが，これは送信信号がガウス変数であることを仮定して導出されるものです．
ガウス変数は文字通りガウス分布に従う確率変数ですが，このガウス分布が極めて重要な意味を持ちます．


## ガウス分布（正規分布）

ガウス分布は最も基本的な確率分布ですよね，あらゆるところで登場します．
一般的に自然発生する変数は，このガウス分布に従うとされています．
例えば，人間の身長とか体重とか，ある平均$\mu$にたいして$\sigma^2$の分散で正規分布に従います．

通信の世界でも最もよく出てくる分布の一つです．
その理由は何といっても中心極限定理によるもので，具体例は次に示します．

### AWGNチャネル

無線通信においては送受信機の間の伝搬環境のことを，チャネルと呼びます．
このチャネルは当然多くの環境から影響を受けて時々刻々と変化するのですが，最もシンプルにモデル化したものが「加法性白色ガウス雑音」を意味するAWGNチャネルです． 

一般に受信信号を$r$，送信信号を$s$とすると，ガウス分布に従う雑音$n$を用いて次式で与えられます．

$r = s + n$

ここで$n \sim \mathcal{CN}(0, N_0)$とすると，平均受信信号電力$E_s$を用いて，前回の記事でも触れていた$SNR$は次式で表現されます．

$SNR = \frac{E_s}{N_0}$

一般に$N_0$は温度や通信帯域幅によって定数とされますので，実環境において$SNR$は送信信号に依存するとも言えます．

### フェーディングチャネル

先ほどは雑音のみの影響を考えていましたが，実際には伝搬環境の反射やブロックなど多くの要素で信号の振幅や位相が変化します．
これをフェーディング(fading)と呼びますが，通信理論ではよくこの分布を中心極限定理により近似します．（実際には場所や時間での依存性が極めて高く，一般化するためです．）

フェーディングを考慮した受信信号は次式で与えられます．

$r = h s + n$

ここで$h$がフェーディングを与える項であり，$h \sim \mathcal{CN} (0, 1)$などと設定されることが多いです．
ここで$\mathcal{CN}$は複素ガウス分布を意味しますので，実部・虚部がそれぞれガウス分布に従います．
このようなフェーディングのことをレイリーフェーディングと呼びますが，この理由は次に示します．


## レイリー分布

レイリー分布は複素ガウス分布に従う変数の絶対値の分布です．
すなわち先ほどの$h$の振幅の分布，それがレイリー分布となるわけです．
（多次元ガウス分布を解けば出てきます．）

情報理論の世界では，フェーディングをレイリーフェーディングと仮定し，解析することが多いため，よく出てきますね．

実環境とのつながりでいうと，送受信機が見通し環境になく，極めて多数のパス（電波の経路）が存在するとき，実際にレイリー分布に従います．
これは先ほど述べたように中心極限定理に基づくものです．

## 指数分布

先ほどのレイリーフェーディング環境下において，$SNR$を考えたいとき出てくるのが指数分布です．

$SNR = \frac{|h|^2 E_s}{N_0}$

でSNRが与えられますから，$|h|^2$の分布を知る必要があり，これが指数分布になるわけです．

## カイ二乗分布

指数分布を次元拡張したのが指数分布です．
ダイバーシティを考慮した場合に出てきますが，説明が複雑になるので割愛です．

## ライス分布

では今度は，送受信機が見通し環境にあるときはどうなるでしょうか．
それがライス分布です．

式で書くと，
$\Re [ h ] \sim \mathcal{N} (a, \sigma^2_h)$
$\Re [ h ] \sim \mathcal{N} (0, \sigma^2_h)$
としたときの$h$の振幅の分布です．

これ以上は説明辞めます．


# おわりに

おそらくここまで読んでいる人はいない気もしますが，時間に追われこんな感じになってしまいました．
時間を見つけてグラフとかいろいろ加筆したい気持ちはありますが，やるかはわかりません．

お付き合いいただきありがとうございました！
SPAってページ遷移するの？

## 概要

- SPAにおけるルーティングについて簡単に紹介します
- SPAを作ったことがない人が対象読者です
- 知ってる人からすると、そんな当たり前なことを・・と思うかもしれません


## SPAとは？

- Single Page Applicationの略です
- 対義語はMultiple Page Applicationです
- つまり単一ページで構成されるのがSPAで、複数ページで構成されるのがMPAです
- SPAは最初に画面(HTML)を取得した後は、JavaScriptによって画面の書き換えを行うことで単一ページでありながらアプリケーションを構築することができます
- これは言い換えると`SPAはページ遷移しない`ということ？本当にそうでしょうか？

## SPAはページ遷移しない？

- 2つのデモページを用意しました
    - https://spa--mdc-2019.netlify.com/
    - https://mpa--mdc-2019.netlify.com/
- それぞれのページのGIFです

#### SPA

![spa.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/363f367e-0ab1-ff2c-b028-2c751fb13825.gif)

#### MPA

![mpa.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/58ef3449-58f0-8672-fbe7-5a6fb5975e62.gif)

- どちらのページもリンクをクリックするとURLが切り替わってページ遷移しています
    - どういうことでしょう？？？

## SPAにおけるページ遷移

### URLの書き換え

- SPAはJavaScriptで画面を操作することになりますが、実はアドレスバーのURLはJavaScriptで操作できるんです
    - ブラウザにはHistoryAPIというJavaScriptのAPIが実装されており、それらを使うことでブラウザの履歴を操作できます
    - アドレスバーのURLは`history.pushState()`で書き換えられます
- 試しに開発者ツールで実行してみた例

![pushstate.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/811d6062-cb84-c328-2b39-46aa02d9c2f5.gif)

- 実行するとURLが書き換わるのが分かると思います
    - ブラウザのHistoryを操作しているためブラウザバックにも対応します
    - この関数はあくまでURLを書き換えるだけなので画面に表示されている内容に変化はありません

### 画面の書き換え

- SPAにおける画面の書き換えは、「ボタンをクリックしたこと」や「通信が完了したこと」などのイベントを検知して処理を実行します
- 「URLが書き換わったこと」もイベントの1つに過ぎず、それを検知して画面全体を書き換えているというわけです
- 実際の開発では[React Router](https://reacttraining.com/react-router/)や[Vue Router](https://router.vuejs.org/ja/)といったライブラリを用いることが多いです
    - どのURLに変更されたらどのコンポーネントを表示するかマッピングしておくことで、MPAの画面遷移のように扱うことができます

## まとめ

- SPAってページ遷移するの？
    - ユーザ視点で見た場合、MPAと同じようにページ遷移することができます
- SPAってどうやってページ遷移してるの？
    - ブラウザのHistoryをJavaScriptで操作することでURLを書き換えることができます
    - URLの更新を検知して画面を書き換えることでページ遷移を表現しています

## 余談

- 途中紹介したSPAとMPAのサンプルは全く同じ挙動をするわけではありません
- SPAは`/home`などでリロードすると404(Not Found)となってしまいます

![404.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/ae95ab37-3fee-0fbd-f9c2-2c01554d564b.gif)

- 仕組みを考えるとあたりまえで、サーバ上には初回アクセス時に取得する`/index.html`しかなく`/home.html`などは存在しないためです
- 404を出さないためには、SPAを配信するホスティング側の設定で404が出た場合に`/index.html`にforwardしてあげればOKです
- 今回サンプルで使っている[Netlify](https://www.netlify.com/)では`_redirects`というファイルを作成し以下のように設定すればOKです

```:_redirects
/*    /index.html   200
```

- この辺はホスティングサービスごとに異なるのでそれぞれ調べてみてください
- URLダイレクトアクセスにも対応したサンプル
    - https://spa2--mdc-2019.netlify.com/
- ここまでできるとユーザ視点ではSPAもMPAもほとんど変わらないてすね！