OmniAICreator/Qiita-1.07M huggingface dataset:
ビギナー開発者向け 依存関係逆転原則の使われ方

## はじめに
知り合いのビギナー開発者に依存関係逆転原則についてちょっとしたレクチャーをしたので、ここにおいておきます

Wikiにあるような定義の解説とは少々異なります

依存関係逆転原則の定義を見ても実際の開発と結びつかないそうなので、そのイメージをつかむためのレクチャーです
まず始めに簡単な問いを投げかけ、そこから例を交えて解説しました

当内容は多くのOOP言語で成り立つものだと思いますが、件のビギナーはJavaを用いているので、この記事もそれに準じたものであると断っておきます


## 問題
まず簡単な問いをさせてください

とあるコンポーネントAとそのプラグインとなるコンポーネントBがある
プラグインを利用するためにAはBを呼び出す必要があるが、特定のプラグインに依存することは避けたいためインターフェースB'を用意することにした

ここで、B'はコンポーネントAに属するべきか、それともコンポーネントBに属するべきか答えよ

###### 選択肢
1. コンポーネントAに属するべき
2. コンポーネントBに属するべき

###### 正解
1. コンポーネントAに属するべき


## 解説
(この手の“原則”を扱って正解だの間違いだのいうのは少々大げさというかおこがましいとも思いますが...)
2だと思ってしまうのは、規約などで機械的にインターフェースを作成していた方によく見られる解答かと思います


依存関係逆転原則について、というよりインターフェースの使い方についての理解が浅い方は、BのインターフェースなのにAに属するってなんやねん、という疑問を持ったかもしれません

実際Javaなら

```java
class B implements B'
```

などと書くことになりますから、そのように思ってしまうのはよくわかります
しかし、依存関係を制御するための道具としてインターフェースを用いる場合、正解は1となります

それは実際のアプリケーションを例にとれば明らかです
例えば、VSCodeなどのエディタとそのプラグイン(シンタックスハイライト機能など)の関係を考えてみるとよいでしょう

もし2が正解だった場合、プラグインを利用するためのインターフェースが各プラグイン毎に存在する、という状態になります
VSCode開発者は様々な人が作成するプラグインのコードをすべて確認し、それぞれに適した呼び出し処理をVSCode本体に用意する必要がでてきます
これではインターフェイスの意味がないですね

1の場合、VSCode本体の開発者がインターフェースを用意して外部に公開し、各プラグイン開発者は公開されたインターフェイズに基づいてプラグインを作成する形になります
すなわち、プラグインがVSCode本体に依存することになります

VSCode側は、以下のような呼び出し処理を記述し、ユーザーが現在選択しているプラグインの実体をインジェクションしてあげることとなるでしょう

```java
// DIコンテナなどでインジェクション
B' hoge

execute() {
    hoge.doSomething();
}
```


VSCodeのようなアプリケーション本体は、拡張機能であるプラグインよりも安定性が求められます
しかし、プラグインの機能を利用するためには当然ですが、プラグインの呼び出し処理の記述が必要になり、プラグインに依存しなくてはなりません
処理を呼び出すとは、その処理に依存するということです

例に挙げたエディタとプラグインの関係のように、安定しているべきものに不安定なものの呼び出し処理を記述しなくてはならないことはよくあります

そのような状況を、依存関係を逆転させることでひっくり返すことを説くのが依存関係逆転原則です

## 依存関係の逆転する<ruby>様<rt>さま</rt></ruby>
AがBに依存することを仮に以下のようにあらわします
A→B

ここにインターフェースB’を挟むと
A→B'←B

さらに、インターフェースがどこに属するかを踏まえると
(A→B')=A

となるので
A←B
となります

最初の依存関係と逆転していますね
これが依存関係の逆転する<ruby>様<rt>さま</rt></ruby>です

不安定なBが安定したAに依存する、という望ましい状態となりました

ここまで述べた依存関係逆転原則の考え方は、Javaでいうjar/Rubyでいうgemのような大きな枠組みに適応できるものです
例えばレイヤードアーキテクチャのレイヤー間のやり取りの処理で、インターフェイスが用いられることが多い理由も見当がついたのではないでしょうか

ビギナーの場合、JavaでいうClassファイル間の関係で物事を捉えることが多い印象ですが、コンポーネント単位などのより大きな枠で物事を捉えてみると、依存関係逆転原則についての理解が進むかと思います
terrafromでaws acm作成 cloudfrontの場合バージニアで作成しないといけないんだけどどうやるの？

providerの設定を変更したものを用意して、aliasを使うことで解決

```terraform
provider "aws" {}

provider "aws" {
  alias  = "virginia"
  region = "us-east-1"
}
```


```terraform
# 証明書発行リクエスト
resource "aws_acm_certificate" "cert" {
  domain_name       = "${lookup(var.domain_name, "${terraform.workspace}.value")}"
  validation_method = "DNS"
  provider          = "aws.virginia"

  lifecycle {
    create_before_destroy = true
  }
}

# DNSによる検証用レコードの登録
resource "aws_route53_record" "cert_validation" {
  name    = "${aws_acm_certificate.cert.domain_validation_options.0.resource_record_name}"
  type    = "${aws_acm_certificate.cert.domain_validation_options.0.resource_record_type}"
  zone_id = "${aws_route53_zone.xxxxxx.zone_id}"
  records = ["${aws_acm_certificate.cert.domain_validation_options.0.resource_record_value}"]
  ttl     = 60
}

# 検証
resource "aws_acm_certificate_validation" "cert" {
  certificate_arn         = "${aws_acm_certificate.cert.arn}"
  validation_record_fqdns = ["${aws_route53_record.cert_validation.fqdn}"]
  provider                = "aws.virginia"
}
```

```terraform
resource "aws_cloudfront_distribution" "xxxxxx" {

  # ~~略~~

  viewer_certificate {
    acm_certificate_arn      = "${aws_acm_certificate.cert.arn}"
    ssl_support_method       = "sni-only"
    minimum_protocol_version = "TLSv1"
  }

  # ~~略~~

}
```

## 参考URL
[amazon web services - How to specify a ACM certificate in a specific region for a data source? - Stack Overflow](https://stackoverflow.com/questions/45027175/how-to-specify-a-acm-certificate-in-a-specific-region-for-a-data-source)
[TerraformによるAWS Certificate Manager(ACM)からの証明書取得とドメイン検証 - Qiita](https://qiita.com/Toshinori_Hayashi/items/08bd5a12bc7d87d9ba18)
IUIAutomationElement::GetCurrentPatternで返されるpatternObject(IUnknown)が、QueryInterfaceをまともに実装していなかったせいでハマった

こんなことにはまったのは自分だけかもしれないが、忘備録代わりに残しておく

##忙しい人に
結論から言うと、QueryInterfaceなんて律儀に呼ばずにキャストしてしまえばいい。

##長々としたハマった経緯
とある他プロセスが生成したウィンドウ内にある、エディットコントロールを外部から操作するためにUIAutomationを利用して操作しようとUI Spyを使って、そのエディットコントロールをいろいろ調べたところ。
エディットコントロールはControl Patternとして、IValueProviderを実装しており、IValueProviderのSetValueを使えば文字列を書き換えられると分かったので、さっそく自分のプログラムに実装してみた。
問題のエディットコントロールのIUIAutomationElementを取得して、GetCurrentPatternを呼び出すところまでは大丈夫だったのだが、

````C++
CComPtr<IUIAutomationElement> editElm = 何とか見つけた;
CComPtr<IUnknown> spUnk;
editElm->GetCurrentPattern(UIA_ValuePatternId, &spUnk);
CComQIPter<IValueProvider> spValueProvider = spUnk;
````

spUnkに値は入っていて、GetCurrentPatternの呼び出しは成功していたのだが、
spValueProvider へ代入(代入時にQueryInterfaceが呼ぶようになっている)時に、spValueProviderがNULL になってしまうのだ。
UI Spyでの操作は問題ないのにどうしてこうなったのか１時間ほど悩み
いろいろ試行錯誤した結果、簡単に言ってしまえば、

````C++
CComPtr<IValueProvider> spValueProvider;
editElm->GetCurrentPattern(UIA_ValuePatternId, (IUnknown**)&spValueProvider);
````

律儀にQueryInterfaceなんて呼ばずに、無理やりキャストしてしまえばよいだけの話だった…。

その後は無事
`spValueProvider->SetValue("書き換えたい文字列");`
することができて
めでたしめでたし。

C++からUIAutomationなんてものをわざわざ使う人が少ないのか、情報が少なくて困った
この情報が、もし誰かの役に立てば幸いである。
golangで手軽に行列のランク（階数）を取得する

Goで行列のランクを取得する簡単な方法がパッと調べて出てこなかったのでメモ。

**行列のランクはその非零な特異値の個数と一致する**ことが知られているので、行列を特異値分解（Singular Value Decomposition; SVD）し、非零な特異値の個数を求めれば良い。
便利なことに、Goでは[gonum.org/v1/gonum/mat](https://github.com/gonum/gonum/tree/master/mat)に特異値分解専用のstruct `mat.SVD`があるので、それを利用する。

```golang
// 浮動小数点のずれを考慮して、十分小さい値を0とみなす
const epsilon = 1e-15

func rank(m mat.Matrix) int {
	svd := new(mat.SVD)

	// 特異値分解
	svd.Factorize(m, mat.SVDNone)
	// 特異値を取得
	svs := svd.Values(nil)
	// 非零な特異値を数えて返す
	var count int
	for _, v := range svs {
		if v > epsilon {
			count++
		}
	}
	return count
}
```

これだけでランクを得ることができる。以下は検証用コード。

```golang
func main() {
	m := mat.NewDense(4, 5, nil)
	m.SetRow(0, []float64{1, 1, 1, 1})
	m.SetRow(1, []float64{0, 1, 1, 1})
	m.SetRow(2, []float64{0, 0, 1, 1})
	m.SetRow(3, []float64{0, 0, 0, 1})
	m.SetRow(4, []float64{0, 0, 0, 1})
	fmt.Println(rank(m)) // 4

	m.SetRow(3, []float64{0, 0, 1, 1})
	m.SetRow(4, []float64{0, 0, 1, 1})
	fmt.Println(rank(m)) // 3
}
```
素のPDOとPDOStatementでもスタブ・モックでテストしたい

本格的なDBのテストは`dbunit`を使うんだけど、DBを含めたテストじゃなくて何らかのデータがあれば良くて、でもORM的なものは使ってないからデータ取得メソッドのスタブを作りづらい場合。ちょっとした`PDO`の処理も`createMock`で簡単にテスト出来ないもんだろうか。

https://php.net/pdo.query

```php

<?php

namespace Sample;

use PDO;
use PDOStatement;

class Sample
{
    private function parseRows(PDOStatement $stmt){
        $ret = [];
        foreach ($stmt as $row) {
            $ret[] = $row['name']
                   . "\t" . $row['color']
                   . "\t" . $row['calories']
                   . "\n";
        }
        return $ret;
    }

    public function getFruit(PDO $conn) {
        $sql = 'SELECT name, color, calories FROM fruit ORDER BY name';
        $stmt = $conn->query($sql);
        return $this->parseRows($stmt);
    }
}
```

マニュアルのコードから持ってきた。
`PDO`を直接使ってる簡単なコードと思いきや、型がしっかり書いてあったりして。
ちょっとしたキーバリューデータがメインのロジックに少し入っているだけといった場合に。


```php
<?php

declare(strict_types=1);

namespace Sample;

use PHPUnit\Framework\TestCase;
use PDO;
use PDOStatement;
use IteratorAggregate;
use ArrayIterator;

final class SmapleTest extends TestCase
{
    public function testGetFruit()
    {
        $stub = $this->getMockBuilder(PDO::class)
              ->disableOriginalConstructor()
              ->disableArgumentCloning()
              ->disallowMockingUnknownTypes()
              ->getMock();
        $stub->method('query')
            ->willReturn(new class extends PDOStatement implements IteratorAggregate {
                    function getIterator(){
                        return new ArrayIterator([
                            [
                                'name' => 'apple',
                                'color' => 'red',
                                'calories' => 150,
                            ],
                            [
                                'name' => 'banana',
                                'color' => 'yellow',
                                'calories' => 250,
                            ],
                        ]);
                    }
                });

        $target = new Sample();
        $ret = $target->getFruit($stub);

        $this->assertEquals("apple\tred\t150\n", $ret[0]);
        $this->assertEquals("banana\tyellow\t250\n", $ret[1]);
    }
}
```

そいうときは`PDO`の返却値で`PDOStatement`を継承したクラスを返せばいける。


`PDOStatement`は`Traversable`を直接実装しているというPHPのコードでは有り得ない状態になっているんだけど、`IteratorAggregate`を実装すれば問題なくイテレーターを置き換えられるみたい。

検索したら`PDOStatement`を継承したテスト専用モッククラスを作るとか見かけたけども、今なら`new class`でいいよね。
E2E テスト自動化ツールをざっと調べたまとめ

E2E テストの自動化に挑戦するためにツールを調べた結果をまとめました。

「Selenium、Puppeteer くらいは聞いたことがあるけど、他にも良さそうなものがないか調べておこう」という軽い気持ちで調べ始めたところ、想像していた以上に色々ありました。。。

※ Web フロントエンドの E2E テストが主な対象です。それ以外は、調べて出てきたことだけまとめています。モバイルは調査対象外です

※ E2E テストに詳しくなく、いろいろ間違いがあるかもしれません。お気付きの方はご指摘お願いします。

# ざっくりググると ...
Selenium, Geb, Concordion, WebdriverIO, Nightwatch.js, Testium, Protractor, Puppeteer, jsdom, Nightmare ,Cypress.io, TestCafe, Intern, Postman, Karate, Pact, Ghost Inspector, etc ...

と、とにかくたくさん出てきました。

# 分類してみた

何がなんだか全然分からないので、まずは頑張って分類してみました。
「[ブラウザ自動化ツール カオスマップ風 - STAC2018 LT](https://www.slideshare.net/hnisiji/stac2018-lt-125349647)」というスライドを参考にしつつ、独自に分類しています。

- Web フロントエンドの E2E テスト系
	- WebDriver 系
	    - Selenium (Geb, Selenium WebDriver with Concordion), WebdriverIO, Nightwatch.js, Testium, Protractor
	- (ヘッドレス) ブラウザ自動化系
	    - Puppeteer, jsdom, Nightmare
	- (ヘッドレス) ブラウザ自動化 + テスト系
	    - Cypress.io, TestCafe, Intern
	- Chrome 拡張
	    - Ghost Inspector
- API テスト系
    - Postman, Karate, Pact

上記の「Web フロントエンドの E2E テスト系」のうち、代表的 (と思われる) ものだけざっくり紹介していきます。

# WebDriver 系

## Selenium

E2E テストでもっとも有名なのは Selenium だと思います。
ただ、最近はフロントエンドの非同期処理や SPA には強くないらしく、Selenium から他のツールに乗り換える話が結構あるようです。

## Selenium WebDriver with Concordion

Concordion は『[リーン開発の現場 カンバンによる大規模プロジェクトの運営](https://www.amazon.co.jp/dp/427406932X)』に書かれていたため調べてみましたが、そもそも GUI のテストツールではなく仕様整理の補助ツールのような位置付けのようでした。
ただし、[FAQ](https://concordion.org/questions/java/markdown/#how-do-i-automate-web-browser-testing-with-concordion) によると Selenium と連携すれば E2E テストも可能なようです。

# (ヘッドレス) ブラウザ自動化系

## Puppeteer

Puppeteer も E2E テストのツールとしてかなり有名だと思います。
ヘッドレスで Chrome や Chromium を操作でき、画面キャプチャも簡単に取得できるようです。

参考: https://developers.google.com/web/tools/puppeteer/

# (ヘッドレス) ブラウザ自動化 + テスト

Puppeteer のようなブラウザ自動化系のツールで E2E テストを行うには、Jest、Mocha、AVA といったテストツールも導入することになります。
一方で、別途テストツールを導入する必要がないものあり、その一例が Cypress.io です。

## Cypress.io

調査前は Puppeteer を使っておけば大丈夫かなと思っていましたが、「[E2EテストをSelenium Webdriver からCypress.io に移行した話](https://user-first.ikyu.co.jp/entry/2019/04/23/090000)」や、「[Cypress: The future of end-to-end testing for web applications](https://medium.com/tech-quizlet/cypress-the-future-of-end-to-end-testing-for-web-applications-8ee108c5b255)」といった、Cypress.io を押す記事も結構ありました。

また、「[cypressを触ってみた](https://qiita.com/okitan/items/b44882e28006c1be32b7#%E9%80%94%E4%B8%AD%E3%81%AE%E7%8A%B6%E6%85%8B%E3%81%AE%E5%86%8D%E7%8F%BE%E3%82%92%E3%81%99%E3%82%8B)」という記事によると

> しかし、このcypressのすごいところは、操作のたびに（xhrリクエストがあるたびに）DOMのスナップショットをとってくれているということです。

とのことです。これはすごすぎる。。

# Chrome 拡張

## Ghost Inspector

「[Ghost Inspectorを使ってコードを書かずにE2Eテストを自動化する](https://dev.classmethod.jp/etc/ghost-inspector-introduction/)」の通り、Ghost Inspector は、コードを書かずにテストできるようです。

Chrome 拡張だと CI で使えないのでは ... ? と思いましたが、「[Ghost Inspector を使って E2E テストしてみる](https://qiita.com/mtomokazu/items/fbe0e252c4f20e7d28dd)」によれば CI でも使えるようです。

# 感想

Puppeteer でいいんじゃないかと思っていましたが、調べた結果、Cypress.io に魅力を感じました。
操作のたびにスナップショットをとってくれるのは衝撃です。まずはさわってみようと思います。
Leetcode #122: Best Time to Buy and Sell Stock II

Time Complexity: O(n), one pass
Space Complexity: O(1). Only one variable is needed

```swift
func maxProfit(_ prices: [Int]) -> Int {
    guard prices.count > 1 else {
        return 0
    }
    var maxProfit = 0
    for i in 1..<prices.count {
        if prices[i] > prices[i - 1] {
            maxProfit += prices[i] - prices[i - 1]
        }
    }
    return maxProfit
}
```
Reactでyamlを読み込む

# やりたいこと

yamlで書かれたデータをReact Appで使いたい

# やったこと

`js-yaml-loader` を利用する

# くわしく

1 `js-yaml-loader` をインストール

```sh
$ yarn add js-yaml-loader
```

2 Webpackの設定ファイルを更新

```js:webpack.config.js
      { test: /\.(ya?ml)$/, loader: "js-yaml-loader" }
```

3 React Appから読み込む

例は `./data.yml` というyamlファイルを読み込み、内容をyamlという連想配列に保存している。

```js:yaml-parser.js
import yaml from './data.yml';

console.log(yaml);
```

# 補足

`yaml-loader` は動かなかったので使用せず。

# バージョン情報

```
        "babel-core": "^6.25.0",
        "babel-loader": "^7.0.0",
        "babel-preset-es2015": "^6.24.1",
        "babel-preset-react": "^6.24.1",
        "css-loader": "^0.28.4",
        "file-loader": "^0.11.2",
        "js-yaml-loader": "^1.0.1",
        "react": "^15.6.1",
        "react-dom": "^15.6.1",
        "react-redux": "^5.0.5",
        "redux": "^3.7.0",
        "redux-devtools": "^3.4.0",
        "semantic-ui-css": "^2.2.12",
        "semantic-ui-react": "^0.71.4",
        "style-loader": "^0.18.2",
        "url-loader": "^0.5.9",
        "webpack": "^2.6.1",
        "webpack-dev-server": "^2.4.5",
        "webpack-init": "^0.1.2",
```
DatePickerDialog で キャンセル を押したときに何か処理をしたい

#目的
**OKを押したときだけでなく、キャンセル(Cancel)を押したときにも処理をしたい**

# 環境
- Kotlin 1.3.21
- Android 8.0 (Oreo)
- AndroidStudio 3.3.2

# 動作イメージ
Buttonを押したらDialogFragmentを表示します。
DialogFragmentでOKを押したら入力日付をButtonのテキストに表示し、キャンセル(Cancel)を押したらButtonのテキストに"指定なし"を表示します。
![dataTest.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398440/257d2bdc-ed9a-e95e-24a6-730421fc1585.gif)

# 実装
## layoutファイル
シンプルにButtonだけの画面にします。

```xml:activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    <Button
            android:text="指定なし"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/date_button"
            android:layout_marginTop="16dp" app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="8dp" android:layout_marginRight="8dp"
            app:layout_constraintStart_toStartOf="parent" android:layout_marginLeft="8dp"
            android:layout_marginStart="8dp"/>
</android.support.constraint.ConstraintLayout>
```

## activityファイル
DialogFragmentのonCancelに処理したい内容を書くだけです。
OKを押したときの処理については、[こちらの記事](https://qiita.com/curry_rohio/items/6ebd65495e75e22f822e)に書いています。

```kotlin:MainActivity.kt
package com.example.kanehiro.datetest

import android.app.DatePickerDialog
import android.app.Dialog
import android.content.DialogInterface
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.v4.app.DialogFragment
import android.widget.Button
import java.text.SimpleDateFormat
import java.util.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val mDate = findViewById<Button>(R.id.date_button)

        /* 日付を入力する時に使用するinnerクラス
           DialogFragmentで日付を入力できるカレンダーを表示する  */
        class DateDialogFragment() : DialogFragment() {
            /* DatePickerDialogを返却する関数
               この関数で、日付を選択した後の処理や、選択できる日付範囲、Dialogのタイトルを設定する */
            override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
//                省略
            }

            /* DialogFragmentでキャンセルを押した際の処理 */
            override fun onCancel(dialog: DialogInterface?) {
                super.onCancel(dialog)
//                ここにキャンセルを押したときにしてほしい処理を書く
                mDate.text = "指定なし"
            }
        }

        /* 日付を指定するボタンを押したとき */
        mDate.setOnClickListener {
//            DialogFragmentを生成し、表示
            DateDialogFragment().show(supportFragmentManager, mDate::class.java.simpleName)
        }
    }
}

```
LinuxのCLI操作をプロっぽく使うためのショートカット

先輩が魔法のようにショートカットを駆使していてカッコイイので調べてみました。

**履歴**
``Ctrl+r``：コマンド履歴の検索 `Esc`でキャンセル
``Ctrl+p``：履歴を見る（↑キーと同じ）
``Ctrl+n``：履歴を見る（↓キーと同じ）
``Ctrl+l``：画面をクリア

**カーソル移動**
``Ctrl+a``：カーソルを行頭に移動
``Ctrl+e``：カーソルを行末に移動

``Ctrl+f``：カーソルを右方向へ移動
``ESC+f``&nbsp;&nbsp;：カーソルを右方向へ一単語移動 [^1]
``Ctrl+b``：カーソルを左方向へ移動
``ESC+b``&nbsp;&nbsp;：カーソルを左方向へ一単語移動 [^1]

**文字列削除**
``Ctrl+d``：カーソル上の文字を削除
``Ctrl+h``：カーソルの一文字前を削除
``Ctrl+w``：カーソル前一単語を削除

``Ctrl+u``：カーソルから行頭まで削除（切り取り）
``Ctrl+k``：カーソルから行末まで削除（切り取り）
``Ctrl+y``：貼り付け（切り取りのUNDO）

[^1]: Altキーでも可能との記事があるがTeratermではアプリのショートカットになる。残念。

 キーバインドは下記で確認可能。

 ```bash:
 bind -p | grep -E '^"\\[CeM]b'
 ```
(WIP)ML Ops/DevOps観点で「機械学習のインフラ」について考える

4月からML Ops/DevOpsに専念することになった。
https://mazgi.github.io/posts/2019.04/my-role-in-dena-was-simplified/

ちょうど連休なのもあってふんわりと色々考えていて[機械学習環境や体制についてTwitterに垂れ流した](https://twitter.com/mazgi/status/1122797350009720832)のだけど、少し整理したいのでqiitaに書いてみる。
思考整理なのでまとまりはありません。
また全ては私の捉え方と考えなので、正確あるいはこうすべきという主張でもありません。

----

# Todo

- 想定している組織図あると読みやすそう
- WebアプリケーションとML環境を図で対比できると伝わりやすそう

----

# 機械学習のインフラの特徴

「機械学習のインフラ」は個々の技術に着目すると決して特殊なものではない。
しかし全体として俯瞰するとWebアプリケーションのインフラとは異なる。

- GPUを扱う
- Webアプリケーションが動くことは少ない
- 公開されるエンドポイントも少ないあるいは無い
- 多くの処理はバッチとして動く
- 1回のバッチは数時間〜数日かかる
- 近しいが異なる処理を何度も行う
- 使用言語は主にPython
- (CV)数GB * 数万ファイルを扱う
- (DS)分析基盤と接続することがある

# 機械学習に携わる人とRole

## ビジネス

- 機械学習で解決できる/解決すべき課題か判断する
- 利用者の期待値を実現可能な範囲と精度とすり合わせる

## リサーチャー

## データサイエンティスト

## ML Ops/DevOps

私のRoleはこれ。

- 機械学習ロジックを実用アプリケーションでwrapする
- リサーチャー/データサイエンティストがロジックに集中できる環境を設計/構築/運用する
- 妥当なコストで効率よく機械学習処理を行える仕組みを設計/構築/運用する

# リサーチャー/データサイエンティストに意識してほしいこと

自明な以下については記載しない。

- 各自の専門分野の知識
- 参画したプロジェクトで求められる業務知識
- チームワークやプロジェクトマネジメント上必要なこと

## 必須なITエンジニアリングの知識と技術

ML Ops/DevOps等が適切に十分なリソースを持って動けたとしても身につける必要がありそうなものを書き出す。
完全にWebブラウザだけで仕事でできるようにでもならない限りはこれらは避けて通れないと考えている。

- セキュリティ/SSH
    - 鍵の取り扱い
    - ファイルと機密情報の取り扱い
        - 特にCVで現実世界を撮影した画像/動画を扱う場合
    - 使われている認証方式
    - 接続経路
- バージョン管理とチーム開発
    - Git
        - 除外すべきファイルと除外方法
        - Branch
        - Commit粒度
    - GitHub
        - Issue
        - Pull Request
- Linux
    - シェル操作
    - ファイル操作
    - パーミッション
- コンテナ/Docker
    - VMとの違い
    - Dockerfile
    - Docker Registry
- IaaS
    - リージョン
    - レイテンシ
    - コスト把握
- 関係の深いIaaSリソース
    - リージョン/VPC
        - ネットワークレイテンシは意識せざるを得ないので
    - AAA/IAM
    - VM
    - オブジェクトストレージ
        - ローカルストレージ/NFSとの違い

## 知っていると便利な知識と技術

世の中の全ての知識と技術は知らないよりも知っていた方が便利だと思う。
その中でも特に知っていると捗りそうなこと。
例えばML Ops/DevOpsが支援または代行できるが知っているとより円滑に依頼できるなど。

- セキュリティの考え方
- シェルの操作とカスタマイズ
- HW/OS/VM/コンテナ概要
    - 「Docker上でプロセスを実行する」までの概要くらい
    - わかっていると見通し良くなるしトラブル遭遇時の対応や支援要請が行いやすい
- CI/CD
- 通知の制御/Slack Webhook
    - 自分でSlack通知を設定できると捗ること多い
- 各種ログの在りかと問題箇所の特定
    - トラブルシュートを依頼しやすくなる
- コーディング規約

## 知らなくても良さそうな知識と技術

適したポジションの人たちに丸投げして良さそうなこと。
居ない場合はポジションを作って採用してもらうよう提案すると良さそう。

- 折衝/渉外
    - 「ビジネス」の人にやってもらう
- IaaS自体の選定/設計/設定/構築
    - 「ML Ops」にやってもらう
    - 選定や設計は要件が伝えられれば十分そう
    - aws cliやgcloudの操作は使うものだけわかれば十分そう
- IaaSの全サービス
    - きっと誰も知らない
- Webアプリケーション開発
    - 「ML Ops」にやってもらう
- k8sそのもの
- 認証認可サービスそのもの/LDAP/Active Directory
    - 「ML Ops」あるいは情シスにやってもらう
    - トラブル遭遇時の問い合わせ先が判断できれば十分そう
Webアプリ「CostBox」を公開しました。

# アプリを公開しました
登録、インストール不要なシンプル支出記録アプリ「[CostBox](https://darumock.github.io/costbox/)」を公開しました。PWAにも対応しています。
お試しに使ってもらえると嬉しいです！

まだまだ実装したい機能も色々とありますが、平成も終わるので一区切りとして公開です。
今回は、初めてのWebアプリの制作だったのもあり結構時間がかかりました...。平日の夜2時間くらいを制作の時間にあてて、中だるみやライブラリの変更等もあり、2ヶ月くらいはかかったと思います。今回は時間が掛かりすぎため、次回に活かしていきたいところです。

動作対象はモダンブラウザを対象としていまが、EdgeとAndroidは動作確認ができていないので、不具合があったらお知らせいただけると助かります。

[https://darumock.github.io/costbox/](https://darumock.github.io/costbox/)

# アプリケーションの構成
極力シンプルな構成にしたかったため、アプリはクライアントサイドで完結するようにしました。

## フレームワーク： Vue.js
アプリっぽくしたかったため、VueCLIを利用してSPA、PWAの初期設定をお任せしました。
PWAに関してはiOS用の記述が追加で必要なため、そこは「PWACompact」で対応しました。

## UI： Vuetify
UI周りを省力化をしたかったので、UIコンポーネントのVuetifyを採用しました。
ハンバーガーメニュー、カレンダーなどなど、実用的なライブラリが一通り揃っていてます。
とはいえ、UIの最適化はまだまだできていないため、追々詰めていきたいところです...。

## データベース： indexedDB（Dexie.js）
前述の通りシンプルな構成に合わせて、データベースの置き場所もサーバーサイドではなく、クライアントサイドに置くことにしました。クライアントサイドなら、GithubPagesやNetlifyにデプロイするだけで動作するのでお手軽です（しかも無料！）。
というわけで、クライアントサイドのデータベースは「indexedDB」を採用し、さらにそのラッパーライブラリである「Dexie.js」で扱いやすくしています（IndexedDBは素で使うにはややこしいので）。

## ホスティング： Github Pages
Javascriptさえ動けばいいのでわざわざレンタルサーバーを借りる必要もないかなと思い、「Github Pages」で公開することにしました。
SSLも標準で対応しているので、軽いWebアプリくらいならこれで十分なんじゃないかと思ってます。公開URLは「https://[ユーザー].github.io/[リポジトリ]/」のようなサブディレクトリでの公開になるのでそこだけ気にならなければ。
プログラミングが分からない【効果的な質問の仕方】

こんにちは、アキトです。

プログラミング学習をしていると分からないことばかりですよね。

そこで、メンターなどに質問したいと考えると思うのですが、質問の仕方が非常に大切になってきます。

抽象的な質問は、相手へ負担を与えてしまいますし、得られる回答も抽象的になります。

これが会社だと、質問の仕方一つで「適切な質問ができないのだから、仕事もできないんだろうな」といったレッテルまで貼られてしまうことでしょう。

たかが質問一つですが、相手の立場にたった質問は知性の高さを感じます。

以下の3つに気をつけて質問すると良いでしょう。

## 解決したいことを明確にする

・何をしたらこうなったのか
・どのような現象が起きているのか
・どこまでは理解できていて、どこから理解できていないのか

まず「ゴール」を明確にして、到着点を定めます。

## 自分で調べた内容

分からないことが出てきたら、即質問して丸投げしてはいけません。

分からないけども、まず自分で調べてみる。この過程がもっとも大切だと思います。

ただし、自分で調べても解決できないのならそれ以上自分で悩んでも時間の無駄になるので質問します。

自分で調べたことを箇条書きにするなどして、質問する際の背景の一つとして質問者に伝えましょう。

## 仮説と検証作業の結果

問題を解決するために自分は何を考え、何を調べ、何を試してみたのかを伝えます。

この部分を質問者に伝えることで、理解できていない部分が浮き彫りとなり指導してもらえるでしょう。

この部分が曖昧だと、ただ解決策を提示してもらえるだけなので、応用力がつかずに同じようなところで躓いてしまい相手に同じ質問をしてしまうことになるでしょう。


以上まとめると
①問題点をはっきりさせる
②自分で調べてみる
③調べたこと試したことの結果を伝える


この3つが質問する際のマナーですね。
Node.js,Expressメモ⑤の4

エンドゲームみてきました。深夜に終わる回なのに満席。すごい。こんにちは。


こちらのチュートリアルPart5のサブページ4番目です。
https://developer.mozilla.org/ja/docs/Learn/Server-side/Express_Nodejs/Displaying_data/Home_page

ここからはcatalog/からアクセスするwebページの作成のようです。

# 作る必要があるもの
①すでに記述していあるコントローラー関数の更新
②レンダリング用の.pugファイルの作成

# catalogのルートぺージ書き換え
このチェートリアルはBookに対するページの作成なのでcatalog/のルートページはbookController.jsに書くようです。
さらにそこのページをそう指定しているのはroutes/catalog.jsの前半に書いてある
`router.get("/", book_controller.index);`こちらの記述。

`127.0.0.1:3000/catalog/`にアクセスしたら`book_controller.index`関数に飛ぶといる設定みたいです。


Bookのindexページに必要な記述をします。
このページにはこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199642/37ca359e-ffec-3461-cf99-1df5b6fc96b6.png)

・左にメニューバー(前回のページで書いたサイドバー)
・右側は固定のテキストと、データベースから取得した各要素の総数

ということでデータベースからは各テーブルの総数だけ動的に取得できればいいかなと思います。

ここの処理は同期が必要なさそうなのでasync.parallelを使うようですが、まだ全然勘所がわかりません笑
最初にrequireで必要なモデル(book, author, genre, bookinstance)を読み込んだ状態で記述していきます。
あ、asyncも忘れずにrequireします。

```
exports.index = function(req, res){
    async.parallel({
        book_count: function(callback){
            Book.countDocument({}, callback);
        },
        book_instance_available_count: function(callback){
            BookInstance.countDocument({status: "Available"}, callback)
        }
        //一部抜粋
    },
    function(err, results){
        res.render("index", {title: "Local Library Home", error: err, data: results})
    }
}
```

カウントするためにはモデルに用意されているcountDocumentという関数を使えばいいようです。
第一引数はクエリなのかな？statusが`Available`のものだけをカウントすることもできるようです。

※pythonと書き方が違うのでちょっと戸惑います(syntax errorになっちゃう)


最後にrender関数でレンダリングテンプレートに値を渡して終わり。


# index.pug
indexのためのpugファイルです。
layout.pugを継承します。(記述的には拡張なのかな)

```
extends layout
block content
```
これで継承 + content部分だけ置き換えになるみたいですね。

ここで使える変数はtitle, error, dataの3つです。
dataにはcountDocumentの値が入っていると思いますがerrには何が入っているかわかりません。。
※要確認

さてindex.pugが以下になります。写経したものです。

```
extends layout

block content
  h1= title
  p Welcome to #[em LocalLibrary], a very basic Express website developed as a tutorial example on the Mozilla Developer Network.

  h1 Dynamic content

  if error
    p Error getting dynamic content.
  else
    p The library has the following record counts:

    ul
      li #[strong Books:] !{data.book_count}
      li #[strong Copies:] !{data.book_instance_count}
      li #[strong Copies available:] !{data.book_instance_available_count} 
      li #[strong Authors:] !{data.author_count}
      li #[strong Genres:] !{data.genre_count}
```
※ここら辺の説明は前のチュートリアルにもありましたが笑

上の表示されたページと比べてみると、、、
h1, p, liはhtmtlのタグのように思えます。

\#[]は行中に含まれるタグでしょうか、、。うーん。わかりにくいです。
emは協調(イタリック)
strongは太字のように見えます。

if 分の後は字下げがあって{}内のものは変数のようですがtitleとかerrorとかないのはなぜ、、。
=で繋ぐものはこうじゃなきゃダメみたいです
o h1=title
o h1= title
x h1 =title
x h1 = title

なるほど。
テンプレートの解説を見ていた時はちんぷんかんぷんでしたがほどいてみると納得です。

つづく
データベースとテーブルを作成する方法！

# この記事で分かること
- データベースとテーブルの作成方法について

# データベースとテーブルの作成手順

- ECサイトを作る場合を想定して、次のような構造でデータベース、テーブルを作ります。

![スクリーンショット 2019-04-29 19.01.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392565/4e18c5de-4412-47b8-62c5-8a96294f7abd.png)


## テーブルの設計を考える
- 作成するアプリケーションを元に、データを保存するためにどのテーブルが必要でどの項目に保存するのかを考えます。
- 次のような流れでテーブルを作成していきます。

### 手順1.必要なカラムを洗い出す
- 保存するデータを元に、必要なカラムを洗い出します
- 例えば、ECサイトを作成する場合、「会員番号」「名前」「メールアドレス」「電話番号」の4つの項目が必要と考えます。

### 手順2.カラムごとの型を設定する
- カラムにそれぞれどんな内容が入るのかを設定します。
- 例えば、「名前」のカラムは文字列が入るので、「VARCHAR」が入ります

#### データ型の種類

|  型名  |  データ型  |  値の範囲  |  備考  |
| ---- | ---- | ---- | ---- |
|  INT  |  整数型  |  -2147483648～+2147483647  |  UNSIGNEDを指定した場合：0～4294967295|
|  VARCHAR  |  文字列型  |  m（バイト数指定）：0～65535バイト  |  -  |
|  DATETIME  |  日付時刻型  |  'YYYY-MM-DD HH:MM:SS'  |  データを取得した日時を自動的に取得できる  |

※「UNSIGNED」はデータ型に対して付与するもので、負の値が入らないように設定するもの。（0と正の値のみ）

### 手順3.文字列や値の長さを設定する
- カラムの型に文字列や数字を入力するものを指定した場合、値の長さを設定する必要があります。
- 例えば、文字列型の「VARCHAR」を設定した場合、何文字まで入力可能なのかを設定する必要があります。

### 手順4.AUTO_INCREMENT（オートインクリメント）とPRIMARY KEY(主キー)について
- 最後に2つの設定項目について解説します。

#### AUTO_INCREMENT（オートインクリメント）
- AUTO_INCREMENT（オートインクリメント）とは、カラムに値が指定されなかった場合に、自動で1から順番に数字が割り振られるように設定することです。
- 例えば、会員番号を割り当てるとき、AUTO_INCREMENT（オートインクリメント）を設定すると自動で1から順番に数字が割り振られます。

#### PRIMARY KEY(主キー)
- PRIMARY KEY(主キー)とは、カラムに対してデータを重複させない一意の値のみ入るように設定することです。
- PRIMARY KEY(主キー)を設定することで、同じテーブルの中で、カラムの値は他と重複しないようになります。
- 例えば、お客様の中で偶然同じ名前の人がいる可能性はあります。

![スクリーンショット 2019-04-29 19.40.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392565/a21f636c-a6d6-a668-d6d7-2b0e0815b945.png)

- それに対して、会員番号はお客様一人一人に別々の番号が割り当てられているので、同じ名前でも会員番号から一人のお客様を特定することができます。

![スクリーンショット 2019-04-29 19.45.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392565/ea9c9664-cd27-ce87-2562-a60b59f14915.png)

- このようにデータと値が重複することがないようにPRIMARY KEY(主キー)を設定します。


## 手順5.SQLでテーブルを作成する
- 手順1~4で設定した内容を表にしてまとめます。

|    |  カラム名  |  データ型  |  長さ/値  |  A_I|
| ---- | ---- | ---- | ---- | ---- |
|  会員番号  |  id  |  INT  |  11  |  あり  |  詳細  |
|  名前  |  name  |  VARCHAR  |  255  |  -  |
|  メールアドレス  |  email  |  VARCHAR  |  255  |  -  |
|  電話番号  |  tel  |  VARCHAR  |  255  |  -  |

### SQLコマンド
- 上記のテーブルをSQLで書くと次のようになります。

```sql
CREATE TABLE `ec`.`users` ( `id` INT(11) NOT NULL AUTO_INCREMENT , `name` VARCHAR(255) NOT NULL , `email` VARCHAR(255) NOT NULL , `tel` VARCHAR(255) NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;
```
毎日占いをみて士気を高める

# 毎日の指針とは何か
仕事の中で自分の芯となる部分それは・・・
そう毎日の占いである。
その日の占いが良ければ気分は上がるし、低ければ悪いことが起きないよう注意して過ごす。
なんと有用なのだろう。
しかし占いを毎日見るのはめんどくさいし、チームのメンバーにも共有したい。
そんな時のために作りました。

今回はファイルにはいていますが、メールで送るも良し。slackに送るも良しです。

今回は[こちらのサイト](http://gqjapan.jp/horoscope/daily-fortune/)を毎日確認することにしました。

## 準備
```
python --version
-> Python 3.5.2 :: Anaconda custom (x86_64)

pip install selenium
pip install phantomjs

python FortuneTelling.py ./    # 引数はファイルの出力先
```

以下のようなURL構成になっています。
/daily-fortune/2019/4/29/aries

```py3:FortuneTelling.py
import lxml.html
import requests
import datetime
import re
import urllib.parse
from selenium import webdriver
import os, sys
FileName = "FortuneTelling.txt"
#占いサイトのurl
FortuneTellingUrl = '{サイトURL}/daily-fortune/'
#星座一覧
Constellations = {'aries':'おひつじ座', 
'taurus':'おうし座', 
'gemini':'ふたご座', 
'cancer':'かに座', 
'leo':'しし座', 
'virgo':'おとめ座', 
'libra':'てんびん座', 
'scorpio':'さそり座', 
'sagittarius':'いて座', 
'capricorn':'やぎ座',
'aquarius':'みずがめ座', 
'pisces':'うお座'}
Today = re.sub(r'-0|-', '/', datetime.datetime.now().strftime('%F')) +'/'
outputPath = sys.argv[1]
if os.path.exists(outputPath):
    os.remove(os.path.join(outputPath, FileName))
else:
    os.mkdir(outputPath)
output = open(os.path.join(outputPath, FileName), 'a')
output.write('★'*20 + '\r\n今日のうらないです。確認をお願いします。\r\n')
for constellation, name in Constellations.items():
    siteUrl = FortuneTellingUrl + Today + constellation
    print(siteUrl)
    driver = webdriver.PhantomJS()
    driver.get(siteUrl)
    root = lxml.html.fromstring(driver.page_source)
    output.write(name + ':' + root.cssselect('.star_ranking > span')[0].text + "\r\n")
    output.write(root.cssselect('.advice_area > p')[0].text + "\r\n")
output.write('★'*20)
output.close()

```

## 出力結果
```FortuneTelling.txt
★★★★★★★★★★★★★★★★★★★★
今日のうらないです。確認をお願いします。
いて座:No.5
全体運は平凡・安定。お金を貯めるためのテクニックを学べそう。得意な人のその秘訣を聞いてみて。
みずがめ座:No.3
全体運は好調。普段交流がないのであれば、今日は上司や先輩を積極的に誘ってみて。味方につけることで、格段に仕事の進み方が変わります。
しし座:No.1
全体運は快調。仕事、恋愛、どちらの場面においても頭一つ抜け出すチャンスがやってきそうです。前に出るタイミングは逃さないで。
おうし座:No.8
全体運は吉凶混合。精神的に疲れてしまい、それが原因で人に優しくできないかもしれません。気分転換をするのであれば、一人で自然の多い場所に足を運びましょう。
てんびん座:No.4
全体運は好調。一を聞いて七ぐらいまで理解できそうな日。頭の回転が速く、処理能力も上がっています。
かに座:No.9
全体運は自重。外出をすると調子に乗って散財をしてしまいそう。お金を節約したければ、家に籠った方が無難です。
うお座:No.10
全体運は自重。男らしい身体を手に入れるために、トレーニングをしている人は注意。怪我をしやすい星回りです。
おひつじ座:No.2
全体運は快調。女性の相談に乗ってあげましょう。アドバイスをしなくても、話を聞いてあげるだけで相手は満足してくれるでしょう。
おとめ座:No.11
全体運は波乱。ラフプレーで警告を受けてしまいそうな日。反則を犯してまで、人に厳しいチェックをする必要はありませんよ。
ふたご座:No.7
全体運は吉凶混合。笑顔で一日を過ごしましょう。脳内に幸せホルモンが溢れ、あなたの笑顔につられて周囲の人も笑顔になるでしょう。
さそり座:No.6
全体運は平凡・安定。家がくつろげる場所ならば家で、そうでなければゆっくりとくつろげるお店で過ごしましょう。本が１冊あると良さそうです。
やぎ座:No.12
全体運は低調。取引先とのトラブルが発生しそうな星回り。熱くならずに冷静に対応をすれば、すぐに鎮静化するでしょう。
★★★★★★★★★★★★★★★★★★★★
```

#　結果
チームのメンバーに毎日送っていたらうざがられて中止しました。
僕だけ毎日見ます。
最高のvpnのお得な情報

この記事を読んでいるのは、VPNサービスへの加入を検討しているからです。それで、まず最初に、私達はあなたの決定についてあなたを祝福したいです！これらのアプリケーションは、あなたが完全なオンライン匿名性を達成するのを助け、ISPが課すスロットルとの戦い、あなたがNetflixのブロックを解除するのを助けます - そしてもっとたくさん。しかし、彼らは代償を払ってくる。いつものように、あなたは賢くあなたのお金を使い、あなたにその価格のために十分な価値を与えるVPNサービスを選びたいです。そしてそれこそまさにこの記事でお話しすることです。これを踏まえて、私たちはあなたが今見つけることができる最良のVPN取引を紹介します。

VPN取引の推奨事項から始める前に、簡単に迂回しましょう。あなたはおそらくVPNがサブスクリプションサービスであり、これらの大部分は月までにあなたに請求することを知っています。これは、VPNの世界に参入するための最も手頃な方法でもあります。そのため、通常は急激な割引が伴う長期計画を検証します。それをしている間、私達は私達の広範なハンズオンテストに基づいて、最高のVPNだけを推薦することを忘れないでいます。あなたが今最良のVPN取引について決心する前に、我々は完全なレビューを読むことを勧めます。また、幸いなことに、多くのVPNには返金ポリシーが付いています。つまり、失うものは何もありません。

オンラインのプライバシーとセキュリティは、すべてのネチズンにとって最優先事項の1つです。これらは、ハッキング、プライバシーの盗難、フィッシング、その他のセキュリティ上の問題が発生し、身元と財政に混乱をもたらすまでは、通常のインターネットユーザーが当たり前のことと見なしていることの一部です。

適切なVPNを使用すると、オンラインのプライバシーとセキュリティが損なわれないように保証できます。以下のリストは、価格と顧客が提供する信頼に見合った最高のVPNサービスを特徴としています。それぞれに独自の機能セットと価格設定オプションがあります。もう1つ重要なことは、これらのVPNサービスのほとんどは、顧客がそのサービスを満足できず、ニーズに合わないと判断した場合に、一定期間に適用可能な返金オプションを提供することです。

VPNサービスを選択する前に、自分の優先順位を確認する必要があります。カスタム料金設定オプションについてVPNサービスチームのカスタマーサービス担当者に相談することも素晴らしいアイデアです。
Source: https://www.bestvpn.co/
concrete5のブロックカスタムテンプレートからrequireAsset()する

concrete5でJSのライブラリなどを読み込ませたい場合、[アセットを登録](https://concrete5-japan.org/help/5-7/developer/assets/registering-an-asset/)して読み込む。

で、ブロックの一部のカスタムテンプレートでjsのちょっとしたライブラリを読み込みたい時(たとえば、PageListブロックにスライダーライブラリを入れたいとか)があるけど、カスタムテンプレートのview.phpで

```application/page_list/templates/with_slider/view.php
$this->requireAsset('javascript', 'hogehoge')
```
みたいにしたら、一応読み込まれる。

一応読み込まれるんだけど、それはブロックキャッシュがオフになってるときだけのことで、ブロックキャッシュがオンになってる状態だと読み込まれない。エラーも出ない。
例えば、ログインしてるときは読み込まれて、ログアウトした途端に読み込まれなくなるみたいなことが起こって悩む。悩んだ。

悩むのはまだいいほうで、最悪、本番環境だけで読み込まれなかったりしてやばい。

[本家コミュニティ(英語)](https://www.concrete5.org/community/forums/5-7-discussion/requireasset-in-custom-template)に解決法が載っていた。view.phpに書くのはやめて、ブロックのcontroller.phpのほうでカスタムテンプレートを判別して出し分けするしかないらしい。

```application/page_liset/controller.php
<?php
namespace Application\Block\PageList;

class Controller extends \Concrete\Block\PageList\Controller
{
    public function registerViewAssets($outputContent = '')
    {
      // カスタムテンプレートごとにassetの呼び出しを行う
      if (is_object($this->block) && $this->block->getBlockFilename() == 'with_slider') {
        $this->requireAsset('javascript', 'hogehoge');
      }
    }
}
```

のようにしたら、動くようになった。
Windows版gVimでConsolas+メイリオを使う

#はじめに
Windows版gVim[^1]のフォントに、英数字にはConsolas、日本語などその他の文字にはメイリオを使いたい。しかし、Windows版gVimのフォント(`guifont`, `guifontwide`)にはプロポーショナルフォントを指定することができないため、プロポーショナルフォントであるメイリオを指定することができない。メイリオの代わりにMeiryoKeを使えば目的は達成できるが、フォントファイルの改変にはライセンス上の問題がある。
そこで、MeiryoKeは使わず、gVim側でどうにかすることにした。
[^1]: https://github.com/vim/vim/issues/3170#issuecomment-403293037

#結論
`FEAT_PROPORTIONAL_FONTS`を有効にしてgVimをビルドすればよい。フォントが等幅かどうかのチェックが行われなくなる。
![Consolas+メイリオ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27766/0f338160-1abc-188f-0e3b-1b56639f23dd.png)

#手順
Kaoriya版の`gvim.exe`を置き換える形にする。そのため、あらかじめKaoriya版(g)Vimは使えているものとする。
ビルド環境はVisual Studioがインストールされていて`nmake`, `rc`等にパスが通っていればよい。この記事ではVisual Studio 2019の"x64 Native Tools Command Prompt for VS 2019"を使っている。
パスやパッチのあて方は環境に合わせて適宜読み替えてほしい。

##vimのソースコードを入手
Kaoriya版パッチをあてるために少し前のバージョンに戻す。現在リリースされているKaoriya版ビルドは8.2.1287なので、そのコミットをチェックアウトする。

```
d:\work>git clone https://github.com/vim/vim.git
d:\work>cd vim
d:\work\vim>git checkout v8.2.1287
```

##Kaoriya版vim相当にする
パッチはKaoriya版の`patch`フォルダに入っている`*.diff`を使わせていただく。

```
d:\work\vim>git apply -p 1 < d:\work\vim82-kaoriya-win64\patch\0000-kaoriya_marks.diff
　:
　:
```

##ビルド
基本的に[vim-jpの説明](https://vim-jp.org/docs/build_windows_msvc.html)の通りだが、`nmake`時に`DEFINES=-DFEAT_PROPORTIONAL_FONTS`を指定する。
なお、現在は`ICONV=yes`がデフォルト、`MBYTE`は常時有効になったため廃止されているので、これらは指定しなくてよいはずだ。
今回はとりあえずConsolas+メイリオさえできればよかったので、LuaやPythonなどは指定していない。

```
d:\work\vim\src>nmake -f Make_mvc.mak GUI=yes IME=yes DEBUG=no DEFINES=-DFEAT_PROPORTIONAL_FONTS
```

`src`フォルダに`gvim.exe`が生成されるので、これをKaoriya版`gvim.exe`と差し替える。
また、Kaoriya版の`switches\catalog\utf-8.vim`を`switches\enabled\utf-8.vim`に移動する。

##gvimrc

`.gvimrc`などgVimが読み込む設定ファイルに以下のように記述する(`renderoptions`を設定しない場合は表示上のゴミが発生したりベースラインより下が欠けたりするが、設定するとフォントによってはベースラインの位置が上にずれてしまう)。

```vim:.gvimrc
"set renderoptions=type:directx
set ambiwidth=double
set guifont=Consolas:h14
set guifontwide=メイリオ:h14
```

#さいごに
この方法が通用するのは、メイリオのような非ASCII文字が実際には等幅となっているフォントのみであるので、すべてのフォントについてこの方法で正しく描画できるとは限らない。とはいえたいていの日本語フォントは等幅であると思われる。

(例) Yu Gothic UIの場合
![Yu Gothic UI](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27766/00950d3f-55b7-29b7-a6b8-e56bbec0af93.png)


#Consolas+メイリオ以外のサンプル
ミンニアム (メイリオ日本語部分と同じデザイナーによる明朝体風フォント)
![ミンニアム](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27766/e10d03d4-d478-7d1d-72d2-ddf75e03a04e.png)

ヒラギノ角ゴ
![ヒラギノ角ゴ W4](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27766/8fa82ea7-3ee3-fdce-4df4-578fd5c40e7f.png)

たぬき油性マジック
![たぬき油性マジック](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/27766/02923389-778a-0e00-f725-d8287555b7e1.png)
Unityでの画像、サウンドの扱い方


#画像とサウンドの管理について
主にUnityでスプライトとサウンドの設定などを行い、できるだけ品質を保ちつつアプリの容量を減らす方法についてまとめる

##画像
###スプライトアトラス
アトラス化は基本的に行ったほうが良い
しかし将来追加されるようなキャラクターなどはアトラス化しない
複数のスプライトをまとめるから画像の呼び込みが命令が少なくてすみ描画効率が良くなる
参考
https://docs.unity3d.com/ja/2018.2/Manual/SpriteAtlas.html

###圧縮テクスチャ
アトラス化しているかどうかに関わらず圧縮テクスチャを使用して軽量化した方が良い
デバイスにより2048を超えるサイズのテクスチャが扱えないことがあるので、2048サイズまででの2のべき乗で作る
####Android
AndroidならETC2が良い
Crunced ETC2はファイルを圧縮していることから読み込み時間が通常のテクスチャより長くなるので注意しなければいけないが、画像が少ないなら最善であると思う
####IOS
iosはどこまで古い機種にも対応するかで変わってくる
・PVRTC
全てに対応するならPVRTCであるが画質が悪いので推奨しない
またPVRTC正方形でかつ2のべき乗のサイズでないと圧縮できないから注意
POTで2のべき乗に規制できるが、Unity2018.2.0a7以降出ないとバグがあって使えない
・ETC2
Unity2017以降かつiphone5SGPU APIがMetal、OpenGL ES 3.0)以降にするならばETC2が使える
・ASTC
さらにiphone6以降対応にすればASTCが使えるのでグラフィック重視のアプリなどはこれを考慮すべきである
基本6*6か8*8ブロック

プラットフォーム別オーバーライドのためのテクスチャ圧縮形式
https://docs.unity3d.com/ja/2017.3/Manual/class-TextureImporterOverride.html
Power of 2のバグ
https://issuetracker.unity3d.com/issues/enabling-non-power-of-2-feature-in-sprite-import-settings-results-into-ui-image-not-being-rendered

##サウンド
###サウンドフォーマット
サウンドはまずフォーマットに気をつけないと音質が劣化する
例えばmp3は非可逆圧縮のフォーマットで元のデータより劣化するから非推奨
Unityでは内部的にoggが使われているからmp3の圧縮と重なってノイズなどが入る場合もある
よってwavなどの可逆圧縮ファイルを使用するのが良い
参考
https://techblog.kayac.com/unity_advent_calendar_2016_17

###音声波形
次に音声の波形データは44.1kHzや48.0kHzなどがあるが統一した方が良い
どちらがいいというわけでなく片方だけ聞こえないということもあるから注意する
音楽などは44.1kHzが主流でビデオ系では48.0kHzが主流になってるからと聞いたことがある

###その他Unityでの設定
BGMはステレオで良いがSEはジングルでない限りは容量削減のためモノラルが良い
メモリの展開方法について
SEの「LoadType」はすぐ再生する必要があるから「Decompress On Load」
BGMでは遅延してもいいから「Streaming」
参考
https://docs.unity3d.com/ja/2018.1/Manual/class-AudioClip.html
php-master-changes 2019-04-28

今日は LLP64 だと PDOStatement::getColumnMeta() で BIGINT の pdo_type が誤っていた問題の修正、AppVeyor で pdo_mysql のテストがスキップされていた問題の修正、opcache ビルド時の shm API の検出コードの修正、SplFileObject::__toString() が READ_CSV の場合に配列を返す問題の修正、古いドキュメントを削除する修正があった！

# 2019-04-28
## cmb69: Fix [#77944](https://bugs.php.net/bug.php?id=77944): Wrong meta pdo_type for bigint on LLP64
- https://github.com/php/php-src/commit/16609880f8338134db08daf6bdcc42025f938fcd
- [7.2~]
- ext/pdo_mysql で、LLP64 だと [PDOStatement::getColumnMeta()](https://www.php.net/manual/ja/pdostatement.getcolumnmeta.php) で BIGINT の pdo_type が誤っていた問題の修正

## cmb69: PHP, meet MySQL
- https://github.com/php/php-src/commit/57d5dc5688a898be705053819519815b122c5ab7
- [7.2~]
- AppVeyor で pdo_mysql のテストがスキップされていた問題の修正
- DSN のスペース区切りをセミコロンにしてるんだけど、どうしてこうなった感がある

## devnexen: Little detection change proposal.
- https://github.com/php/php-src/commit/bb06030bf7ac8aa3a39a9f7bed03c357cff543d9
- [7.4~]
- ext/opcache で、ビルド時の shm API の検出コードの修正
- [先月修正した](https://qiita.com/sj-i/items/f52ca62f332826d7042b#devnexen-fix-shm-api-detection-test-for-opcache-module-on-freebsd)箇所だったけど、よく見たらこっちは shm_open() でなく open() でしたね、みたいな

## duncan3dc: Fix [#77024](https://bugs.php.net/bug.php?id=77024): SplFileObject::__toString() may return array
- https://github.com/php/php-src/commit/91c6fb881e7b98c968d270bdf7f0051b4c2b2c9c
- [7.2~]
- ext/spl で、[SplFileObject::__toString()](https://www.php.net/manual/ja/splfileobject.tostring.php) が READ_CSV の場合に配列を返す問題の修正
- 1 行分文字列で取り出す挙動になってる

## petk: Update NEWS
- https://github.com/php/php-src/commit/6d8892aacda5a24362ed5368812cba6427006c5d
- [7.2~]
- ↑の NEWS への追記

## petk: [ci skip] Remove outdated and redundant Apache README
- https://github.com/php/php-src/commit/807901072d6e09406b592976ea44e9aac2148d51
- [7.4~]
- sapi/apache2handler で、更新されていない古いドキュメントの削除
ReduxのcreateStore()の処理を追う(Middlewareを使わない場合)

Node.js初心者がRedux勉強中です。よく分からなかったのでソースを読んでます。
# createStore.jsのソース
最初に使うcreateStore()は、createStorejsにあります。
https://github.com/reduxjs/redux/blob/v4.0.1/src/createStore.js

createStore()は、Middlewareを使う場合と使わない場合で処理の流れが違っています。この記事では"Middlewareを使わない場合"の処理を追っかけます。"Middlewareを使う場合"の記事は~~そのうち書こうと思っています。~~ 書きました。[ReduxのcreateStore()の処理を追う(Middleware有りの場合)](https://qiita.com/paming/items/0f660a382aae2125818c)

この記事で解説する流れは、呼び出し元がこんな風に呼び出している場合を想定しています。

```javascript
 // stateの初期状態無し
 let store = createStore(reducerA);
 // stateの初期状態あり
 let store = createStore(reducerA, preloadedState);
```
# createStore()でやっている処理
## 引数の整理と型チェック
createStore()の最初は、引数preloadedStateとenhancerの内容を確認して、第二引数のpreloadedStateがfunctionだった場合には、これをenhancerとみなして変数の置き換えをやっています。
これは"Middlewareを使う場合"の呼び出し方に対応するためなので、Middlewareを使わないこの記事分では関係ありません。

## 関数の定義と変数の束縛
```javascript
  let currentReducer = reducer
  let currentState = preloadedState
  let currentListeners = []
  let nextListeners = currentListeners
  let isDispatching = false
  function getState() {...}
  function subscribe(listener) {...}
  function dispatch(action) {...}
  function replaceReducer(nextReducer) {...}
```
createState()内で変数を保持しつつ、関数内関数としてgetState()、subscribe()、dispatch()、replaceReducer() を定義し、それぞれの関数の中で変数を束縛していきます。
こうすることで、同じ変数を中に持つ関数群が作成できます。
(この"束縛"関連の説明は、自分がJavaScriptの知識が曖昧なので自信がありません）

## stateの初期化
```javascript
 dispatch({ type: ActionTypes.INIT })
```
ActionTypes.INITは、redux組み込みのアクションのようです。ソースは[utils/actionTypes.js](https://github.com/reduxjs/redux/blob/v4.0.1/src/utils/actionTypes.js)です。
通常Reducerは「変更前stateがnullだったらデフォルト値を設定する」「知らないアクションが来たらstateをそのまま返す」実装のはずなので、ActionTypes.INITで初期化されます。

面白いのは、ActionTypes.INITはランダムな文字が付与されています。おそらく、ユーザの定義と被らないようにしているのだと思います。
またActionTypes.REPLACE や ActionTypes.PROBE_UNKNOWN_ACTION というアクションも定義されています。これらは[combineReducers.js](https://github.com/reduxjs/redux/blob/v4.0.1/src/combineReducers.js)の中で使われています。

## Storeオブジェクトを組み立てて返す

```javascript:createStore.js
   return {
     dispatch,
     subscribe,
     getState,
     replaceReducer,
     [$$observable]: observable
   }
```
戻り値としては、関数内関数をオブジェクトに割り当てて返しています。
この戻し方で、呼び出し元では store.dispatch(〜)という、「オブジェクトのメソッド呼び出し」のような見た目で各関数にアクセス出来るようになります。各関数は共通の変数を束縛しているので、あたかも「Javaのクラスをnewして作るオブジェクト」のように扱えます。

ここで返される関数のうち、最後の```[$$observable]:observable```は奇妙です。ここは今は追いかけない事にしています。

JavaScriptの仕様だと思うのですが、

```javascript:
  return {
     "dispatch": dispatch,
     "subscribe": subscribe,
     "getState": getState,
     "replaceReducer": replaceReducer,
     [$$observable]: observable
   }
```
と書かなくても、ちゃんと関数名で呼び出せるようになるのですね。この辺はまだ良くわかっていません。
AWSでEC2インスタンスを立て、SSH接続する

EC2を立てたら、キーペアがダウンロードできるので、ダウンロード先のディレクトリをターミナルで開く

## SSH接続
```
$ ssh -i [キーペア名.pem] ec2-user@[パブリックIPアドレス]
```
すると、

```
Are you sure you want to continue connecting (yes/no)? yes
```
と聞かれるので、yesと答える

しかし、許可が下りず失敗する

```
Permission denied (publickey).
```

```
$ chmod 400 [キーペア名].pem
```
権限を変更し、もう一度コマンドを実行すると接続できる

```
$ ssh -i [キーペア名.pem] ec2-user@[パブリックIPアドレス]
```

接続後、Webサーバーが入っていないことを確認する

```
$ yum list installed | grep httpd
```

何も入っていないので、Apachをインストールする

```
$ sudo yum install httpd
```

これでWebサーバーをインストールできたので、サーバーを起動する

```
sudo service httpd start
```

これで、IPアドレスをブラウザで開くと、サーバーが起動しているのが確認できる
LINE Things x micro:bitで2回目以降で繋がらない場合の対処 #linedc #linethings #gwアドベントカレンダー


> [LINE Developer Community GWアドベントカレンダーの二日目](https://gw-advent.9wick.com/calendars/18)です。
> https://linedevelopercommunity.connpass.com/

前に開催した[LINE Things触ってみようハンズオン](https://linedevelopercommunity.connpass.com/event/124842/)で発生した、`1回は繋がったんだけど2回目以降で繋がらない場合`の対処法です。

元のハンズオン記事は[こちら](https://qiita.com/n0bisuke/items/b8800bc46bab76cc1c29)になります。

少なくとも僕はこれで回避できました。

## 一回繋がったんだけど2回目以降で繋がらない現象

microbitの仕様なのか接続情報のキャッシュのようなものが残っててうまく繋がらない場合があります。

>![スクリーンショット 2019-04-29 17.53.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/4871a038-f253-e2ca-3ffe-67433cf377f1.png "スクリーンショット 2019-04-29 17.53.48.png")

こんな感じで`正常に処理できませんでした。しばらく経ってからもう一度お試しください。`となるやつです。

## 起動時にA+Bの同時押し

ハンズオン終了後に`中の人`に聞いてみてコードをよくみたら、LINE Things Starterのコードの41行目周辺に **起動時にAとBボタンを同時するとキャッシュクリアされる** といった内容の記載がありました。

> https://github.com/line/line-things-starter/blob/master/microbit/arduino/sample/sample.ino#L41-L49

ということで起動時に同時押しです。(撮影しながらだと手がつらい)

> <img src="https://i.gyazo.com/cbcf111d2b9e3e6957e8c0e3d941fade.gif" width="600px">
> https://www.instagram.com/p/Bw1TtqEDR8p/

成功すると`Cleared bond store`とArduinoのシリアルモニタにも表示され、再度接続しようとすると問題なく接続できました。

## まとめ

micro:bit x LINE Thingsでハマった人は一度試してみると良いと思います。

BLE周りは他の原因もあるかもしれないので、[前回の連携削除](https://qiita.com/n0bisuke/items/0c09ae5da43b551e98b1#step2-%E5%89%8D%E5%9B%9E%E3%81%AE%E9%80%A3%E6%90%BA%E5%89%8A%E9%99%A4%E5%BF%85%E8%A6%81%E3%81%AA%E3%81%84%E4%BA%BA%E3%81%AF%E5%BF%85%E8%A6%81%E3%81%AA%E3%81%84)なども試しつつ色々とリセットしてみるとうまく行く可能性が上がると思います。

ではでは！
Linux上でのCargoビルドで`Could not find directory of OpenSSL installation`と言われたときの対処法

```
sudo apt install libssl-dev pkg-config
```

- OpenSSLのライブラリ(`libssl-dev`)自体をインストールする必要があります
- Cargoがライブラリのインストール場所を探すために、`pkg-config`が必要です
メモ Vue.extendでpropsのObjectとArrayに型をつける

vue-property-decoratoを使わずにpropsに型をつけたかった際のメモ
## Object
```vuejs
<script lang="ts">
import Vue, { PropType } from 'vue'

type Pet = {
  name: string
}

export default Vue.extend({
  props: {
    pet: {
      type: Object as PropType<Pet>,
      required: true
    }
  },
  mounted() {
    // Type Pet
    console.log(this.pet) 
  }
})
</script>
```
### Array
```vuejs
<script lang="ts">
import Vue, { PropType } from 'vue'

type Pet = {
  name: string
}

export default Vue.extend({
  props: {
    pets: {
      type: Array as PropType<Pet[]>,
      required: true
    }
  },
  mounted() {
    // Type Pet[]
    console.log(this.pets)
  }
})
</script>
```
エモーション・クリエイターズ　映写を利用する

●GUIのプログラミング
　エモーション・クリエイターズ（R18指定）は、ゲーム用のプログラミング言語です。言語といっても全部GUIで操作するので、スクリプトを書くことはありません。ゲームを作るとゲーム内でアップロードができ、他人がダウンロードでき、ゲームを楽しめます。

●Step1　マップ作成
　キャラクタを前から見た時のゲームの映像を、別の角度から同時に見たいときがあります。そのためのアイテムが映写です。スクリーンとスマホの二つが用意されています。
　「メイク」->「マップ」を選び、マップ作成に入ります。「add」をクリックすると、いろいろなアイテムが選択できます。アイテム追加の画面で、フィルタをクリックします。カテゴリーを全解除します。カテゴリの一番下にある「映写」をクリックして、「決定」ボタンを押すと、二つのアイテムが見つかります。
　スクリーンはとても大きく、スマホは小さいです。もちろん選択後にリサイズができます。アイコンを1回押すと、作業用エリアに張り込まれます。デフォルトの画面でははみ出しているので見えていないです。何度も押さないでください。いや、三つぐらい使うのもありです。もう一度「add」をクリックすると、アイテムの追加は終了します。
　マウスの右ボタンを押して上下にマウスを動かすと、スクリーンが見えます。中央上部に丸いポインタがあるので1回押します。アイテムの設定パネルが左上に出ます。これは何をするものでもありません。さわりません。
　操作しやすいように、環境を変更します。F1を押し、コンフィグパネルのその他を選びます。「操作軸設定」が「小」付近にあるのを「大」がわに2/3ほど動かし、戻るボタンをクリックします。

●Step2　スクリーンの大きさを変更
　丸を一度クリックすると、x,y,z方向の矢印が出ています。画面いっぱいに出ていると思うので、カーソルキーの下向きを押し続けると、縮尺率が変わり、アイテムのスクリーンの全貌が見えてきます。カーソルキーで、アイテムを見ているカメラの視点が変わります。
　画面右下に四つのアイコンが出ていて、今、移動の左から二つ目の移動アイコンになっています。xyzのそれぞれをマウスで選択すると、その方向に移動します。中央付近をクリックするとグレイの四角が出た時は、それをマウスで動かすと任意の方向に移動ができます。
　四つのアイコンの左から3番目を選ぶと、回転アイコンに変わります。一番右のアイコンを選ぶと、拡大縮小のアイコンに変わります。このアイコンをクリックして選択すると、xyzの矢印の先が矢印から立方体に変わります。どれかを選んでマウスを動かすと、アイテムの拡大縮小ができます。

●Step3　mapを張り付ける
　メーカが用意したものは「map」アイコンから読み込めます。ユーザがアップロードしたマップは、systemの読み込みからロードできます。
　「map」に表示された中から公園を一度だけクリックすると、作業画面に張り込まれます。このデータは一体になっていて個々のアイテムを分離できません。
　自分で作成したmapデータは、複数のアイテムを合成し、グルーピングできるので、数百のアイテムを組み合わせるのは、きっと容易でしょう。
　現在、公園の中にスクリーンが浮かんでいる状態です。スクリーンの上部のバーしか見えていないときは、移動アイコンの上向き（緑色）で引き上げると、全体が見えてきます。
　ここで、カーソルキーの上は全体の拡大、下矢印は縮小。PageUpは画面を下向きにずらす、PageDwonはその反対、など。移動や見え方の変更作業は慣れるしかありません。
　スクリーンを適当な位置に設置できたら、systemから保存を選びます。ファイル名を付けて保存したら終了します。

　間違ってアイテムをマップ内に置いてしまった場合、「work」をクリックしてワークスペースを表示し、不要なアイテムをマウスで選択し、選択状態でごみ箱アイコンをクリックして削除します。

●Step4　シーンの作成
　シーンから新規を選択します。初期設定画面でマップ登録で、今作ったのを追加のボタンで選択します。ゲームに登場するキャラクター登録を行います。一度登録した人は後で変更はできますが、その後、追加はできません。キャラクタは、メーカが用意した人、ネットワークのメニューからダウンロードした人のどちらでもかまいません。扱いは同じです。
　次へをクリックすると、プログラミングを行う作業用ワークスペースが出てきます。これにHパート追加をクリックし、開始と終了と結線します。最低限、これで動くものが作れます。Hパートの編集をクリックします。
　左の一覧から、メインの右にある人のアイコンをクリックします。ここからは、チュートリアルに書かれている手順でプログラムを作っていきます。
　例えば、キャラクタを選択して、「待機」の編集をクリックします。ブルー画面にキャラクタが中央に配置されています。左のメニューの「パート毎情報」をクリックします。左のメニューにマップが出るので、クリックして先ほど作った公園を読み込みます。このメニューのカメラの下にスクリーンカメラの項目が存在します。これを、スクリーンに映すときに使います。
　スクリーンに映したい状況になるように、キャラクタを動かし、カメラの方向を動かしていきます。「スクリーンカメラ」のメニューをクリックすると「反映」ボタンが出てきます。これを押したときの情景がスクリーンに反映されます。
Windows10同士のリモートデスクトップが死ぬほど遅いのを直した話

# はじめに
旅先から自宅のWindows10マシンにリモートデスクトップで入ると、操作のレスポンスが返ってくるのに数十秒かかります。
リモートデスクトップのUDP通信を無効化すると症状が改善しましたので、方法を記録しておきます。
サーバ側かクライアント側、どちらか片方の設定を変更します。

# 方法1: サーバ側でUDP通信を無効化する
### ローカルグループポリシーエディタを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212876/ab0864f3-d0d7-169d-1a8a-1f05ebeebdc0.png)

### "RDP トランスポートプロトコルの選択"を開く
コンピューターの構成>管理用テンプレート>Windows コンポーネント>リモート デスクトップ サービス>リモート デスクトップ セッション ホスト>接続
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212876/0e503d9b-97ff-154d-d9c0-019adfad80a9.png)

### ポリシーを"有効"、トランスポートプロトコルを"TCP のみ使用"に設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212876/b4527cf8-4dec-8ae3-5ad3-98606af93711.png)

### コンピュータを再起動
再起動しなければ変更が反映されません。

# 方法2: クライアント側でUDP通信を無効化する
### ローカルグループポリシーエディタを開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212876/ab0864f3-d0d7-169d-1a8a-1f05ebeebdc0.png)

### "クライアントの UDP を無効にする"を開く
コンピューターの構成>管理用テンプレート>Windows コンポーネント>リモート デスクトップ サービス>リモート デスクトップ接続のクライアント
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212876/f6c735e9-005f-a48b-4d03-9481c16318e6.png)

### ポリシーを"有効"に設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212876/54f64bf0-abb6-2cc6-b550-89382880f93c.png)

### コンピュータの再起動は不要です
設定後、次回のリモートデスクトップ接続からUDPを使用しなくなります。

# まとめ
モバイル回線のせいなのか、自宅のルータのせいなのか、ネットワークインターフェースのせいなのか、切り分けていませんが、こんな方法もあるということで。
本来、UDP通信は回線状況がよろしくない状況で効力を発生するような気がするのですが…。
メインフレーム5年の経験しかない金融系SEがiOSエンジニアとして転職した話

定期的に読まれてる記事だったんですが、Qiitaに載せる内容としてはやはり適していなかったので、[個人ブログ](https://www.shetommy.com/articles/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A05%E5%B9%B4%E3%81%AE%E7%B5%8C%E9%A8%93%E3%81%97%E3%81%8B%E3%81%AA%E3%81%84%E9%87%91%E8%9E%8D%E7%B3%BBSE%E3%81%8CiOS%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E3%81%97%E3%81%A6%E8%BB%A2%E8%81%B7%E3%81%97%E3%81%9F%E8%A9%B1)に移しました。
Markdownチートシート



|分類|記述|備考|
|:-:|:-:|:--|
|見出し|# ~ ###### [見出し]|数が少ない方が文字が大きくなる|
|リスト|* or + or - |インデントで階層表現が可能|
|順序リスト|1.|全部同じ数字でも連番になる<br>インデントで階層表現が可能|
|表||ここに記述できなかったので下記(もしくはリンク)参照|
|引用| > |複数書けば多重引用が可能|
|コード| \`[コード]\` or \`\`\` [コード] \`\`\` | 1行分（インライン）の時は\`で囲う <br> 複数行の時は\`\`\` で囲う|
| チェックボックス | - [ ] or -[x] | xを書くとチェックが入っている状態になる|
|斜体|\*斜体\*|例) *斜体*|
|太字|\*\*太字\*\*|例) **太字**|
|斜体＋太字|\*\*\*斜体＋太字\*\*\*|例) ***斜体＋太字***|
|取り消し線|\~\~取り消し\~\~|例) ~~取り消し~~|
|水平線|--- or ***||
|画像|\!\[\](画像アドレス)||
|リンク|\[タイトル\]\(URL\)||
|改行|  |文末に半角スペース2個で改行する|
|段落|  |空行を1行挟むと段落が分かれる<br> リストとかも分けれる|
|エスケープ| \ |バックスラッシュ(円記号)でエスケープできる|

### 表

```
| 列タイトル1 | 列タイトル2 | 列タイトル3 | 列タイトル4 |
|-------------|:------------|------------:|:-----------:|
| 左揃え      | 左揃え      | 右揃え      | 中揃え      |
```
| 列タイトル1 | 列タイトル2 | 列タイトル3 | 列タイトル4 |
|-------------|:------------|------------:|:-----------:|
| 左揃え      | 左揃え      | 右揃え      | 中央揃え    |

2列目のセミコロンの位置でアライメントを設定できる
テーブル中では`<br>`で改行が可能

---

## 前書きにしたかったけど、邪魔だから後ろに置いたら後書きになった

- エディタ(ATOM)を入れたらMarkDownが書きやすそうだった
- Qiita登録してみたら記事の作成がMarkDownだった。

ということで、MarkDownの勉強と投稿の練習を兼ねて記事を作成しました。
不足しているところがあったら徐々に書き足したいと思います。

※この記事はATOMでMarkDownを書くことを想定しています。