OmniAICreator/Qiita-1.07M huggingface dataset:
C#で「person?.Name」と「person == null ? null : person.Name」は等価じゃない。

C#において

「`person?.Name`」と「`person == null ? null : person.Name`」は等価じゃありません。

違う見方をすると、

null条件演算子 (?.) において、nullとの比較に 「`==`」オペレーターでの比較は行われません。（型に対して`==`で独自定義した処理は呼ばれない）

同様に、null合体演算子 (??)でも同じように、nullとの比較に 「`==`」オペレーターでの比較は行われません。（型に対して`==`で独自定義した処理は呼ばれない）

# 再現・確認コード

これを再現・確認できるコードは次の通りです。

```csharp
// 本当はEqualsとかも実装するべき
class Person {
  public string Name { get; set; }

  public static bool operator ==(Person lhs, Person rhs) {
	Console.WriteLine("called ==");
  	return object.ReferenceEquals(lhs, rhs);
  }

  public static bool operator !=(Person lhs, Person rhs) {
	Console.WriteLine("called !=");
  	return !object.ReferenceEquals(lhs, rhs);
  }
}

void Main()
{
	Person personNonNull = new Person { Name = "Taro" };
	Console.WriteLine(personNonNull?.Name);	
	
	Person personNull = null;
	Console.WriteLine(personNull?.Name);
}
```


このコードを実行すると、「`called ==`」というログは表示されません。`==`オペレーターが呼ばれていないということが確認できますね。

# ILの確認 ==を使った場合


```csharp
void Main()
{
	Person person = new Person { Name = "Taro" };
	string name = person == null ? null : person.Name;
	Console.WriteLine();	
}
```

このコードのILは、こんな感じ。

```
IL_0000:  nop         
IL_0001:  newobj      UserQuery+Person..ctor
IL_0006:  dup         
IL_0007:  ldstr       "Taro"
IL_000C:  callvirt    UserQuery+Person.set_Name
IL_0011:  nop         
IL_0012:  stloc.0     // person
IL_0013:  ldloc.0     // person
IL_0014:  ldnull      
IL_0015:  call        UserQuery+Person.op_Equality
IL_001A:  brtrue.s    IL_0024
IL_001C:  ldloc.0     // person
IL_001D:  callvirt    UserQuery+Person.get_Name
IL_0022:  br.s        IL_0025
IL_0024:  ldnull      
IL_0025:  stloc.1     // name
IL_0026:  call        System.Console.WriteLine
IL_002B:  nop         
IL_002C:  ret
```


```
IL_0015:  call        UserQuery+Person.op_Equality
```

に注目してください。 `== `の実装が呼ばれていますね。


---


# ILの確認 null条件演算子を使った場合

```
void Main()
{
	Person person = new Person { Name = "Taro" };
	string name = person?.Name;
	Console.WriteLine();	
}
```


このコードのILは、こんな感じ。

```
IL_0000:  nop         
IL_0001:  newobj      UserQuery+Person..ctor
IL_0006:  dup         
IL_0007:  ldstr       "Taro"
IL_000C:  callvirt    UserQuery+Person.set_Name
IL_0011:  nop         
IL_0012:  stloc.0     // person
IL_0013:  ldloc.0     // person
IL_0014:  brtrue.s    IL_0019
IL_0016:  ldnull      
IL_0017:  br.s        IL_001F
IL_0019:  ldloc.0     // person
IL_001A:  call        UserQuery+Person.get_Name
IL_001F:  stloc.1     // name
IL_0020:  call        System.Console.WriteLine
IL_0025:  nop         
IL_0026:  ret
```

`UserQuery+Person.op_Equality`が存在しないことに注目してください。`==`で定義したした処理は呼ばれないことに注目してください。


# まとめ

「`person?.Name`」と「`person == null ? null : person.Name`」は等価じゃありません。

違う見方をすると、

null条件演算子 (?.) において、nullとの比較に 「`==`」オペレーターでの比較は行われない。（型に対して`==`で独自定義した処理は呼ばれない）

同様に、null合体演算子 (??)でも同じように、nullとの比較に 「`==`」オペレーターでの比較は行われない。（型に対して`==`で独自定義した処理は呼ばれない）


# こちらもどうぞ

関連記事 : [Reshaper/Riderの「Possible unintended bypass of lifetime check of underlying Unity engine object」って何ぞや？](https://qiita.com/RyotaMurohoshi/items/5821f4776f3599797c40)
PHPでブラックジャックを実装してみた

# はじめに

[プログラミング入門者からの卒業試験は『ブラックジャック』を開発すべし](https://qiita.com/hirossyi73/items/cf8648c31898216312e5)
上記の記事があったので、今更ながらPHPでブラックジャックを実装してみました。

# ブラックジャックのルール

今回は以下のルールに則って実装しています。
以下引用
> - 初期カードは52枚。引く際にカードの重複は無いようにする
- プレイヤーとディーラーの2人対戦。プレイヤーは実行者、ディーラーは自動的に実行
- 実行開始時、プレイヤーとディーラーはそれぞれ、カードを2枚引く。引いたカードは画面に表示する。ただし、ディーラーの2枚目のカードは分からないようにする
- その後、先にプレイヤーがカードを引く。プレイヤーが21を超えていたらバースト、その時点でゲーム終了
- プレイヤーは、カードを引くたびに、次のカードを引くか選択できる
- プレイヤーが引き終えたら、その後ディーラーは、自分の手札が17以上になるまで引き続ける
- プレイヤーとディーラーが引き終えたら勝負。より21に近い方の勝ち
- JとQとKは10として扱う
- Aはとりあえず「1」としてだけ扱う。「11」にはしない
- ダブルダウンなし、スプリットなし、サレンダーなし、その他特殊そうなルールなし

# 開発

開発する際はできるだけオブジェクト指向エクササイズ(別記事参照)に従って書く努力をしています。
が、全部は従えていません。。。
コードを全部載せると長くなってしまいそうなのでgithubのURLだけで貼ります。
https://github.com/gigosa/php_blackjack

以下、臭いコードだけ抽出して書きます。

1. 
```PHP
class Player implements PlayerInterface
{
    /**
     * @var Hand
     */
    private $hand;
    private $name;

    public function __construct(Hand $hand, string $name)
    {
        $this->hand = $hand;
        $this->name = $name;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }
```
まず一点、ゲッターメソッドを作ってしまったところ。
オブジェクト指向エクササイズ的には名前のクラスを作るべきなのでしょうが、クラスにしてもあまり旨味がなさそうでやめてしまいました。
なので結局ゲッターを作ることに落ち着いてしまったのですが、どうなんでしょう。。。

2. 
```PHP
class GameMaster
{
    /**
     * @var Deck
     */
    private $deck;
    /**
     * @var Dealer
     */
    private $dealer;
    /**
     * @var Player
     */
    private $player;

    public function __construct(DeckInterface $deck, PlayerInterface $dealer, PlayerInterface $player)
    {
        $this->deck = $deck;
        $this->dealer = $dealer;
        $this->player = $player;
    }

    /**
     * ブラックジャックを実行
     */
    public function start()
    {
        $this->deck->shuffle();
        $this->dealCard($this->player);
        $this->dealCard($this->player);
        $this->dealCard($this->dealer);
        $this->dealCard($this->dealer);
        $canHit = true;
        while (!$this->player->isBust() && $this->askDraw()) {
            $this->dealCard($this->player);
        }
        if ($this->player->isBust()) {
            echo $this->player->getName() . 'はバーストしました' . "\n";
            return;
        }
        while (!$this->dealer->isBust() && $this->dealer->wantsToDraw()) {
            $this->dealCard($this->dealer);
        }
        if ($this->dealer->isBust()) {
            echo $this->dealer->getName() . 'はバーストしました' . "\n";
            return;
        }
        echo $this->player->getName() . 'の得点は' . $this->player->currentScore() . 'です' . "\n";
        echo $this->dealer->getName() . 'の得点は' . $this->dealer->currentScore() . 'です' . "\n";
        $this->judgeWinner();
        return;
    }
}
```
スタートメソッドが長い。
また、ゲームマスタークラスが表示に関わるところも持ってしまっている。
途中の`while`文あたりはもう少し抽象化すればいいような気がするのですが特に良い方法が思いつかず。
表示周りを外だしするにもこちらも良い方法が思いつかず。。。
結局ここにごちゃごちゃ書くことに落ち着いてしまいました。
たぶん今回の開発の一番の悔い。

上記以外にもちょいちょいインターフェイスに定義していないメソッドを呼び出したり、プロパティを３つ以上入れてしまったりしてしまいましたがここらで一旦出そうと思いました。
いつまでも手元に置いていても仕方ないですしね。

# おわりに

はじめてオブジェクト指向っぽく書いて見ました。できているか不安ですが。
なんとなくオブジェクト指向で書くってこういうことかな？　という感じが掴めた気がしたのでだいぶ収穫があったと思います。
まだまだ修行中の身ですのでアドバイス等いただけますと幸いです。
秋月のESP32-Devkit CをArduinoIDEでLチカの儀。

#はじめに
![IMG_6667.JPG](https://qiita-image-store.s3.amazonaws.com/0/193066/ad43dee9-bec0-9e2d-64f7-808200047f7f.jpeg)

2018年8/4と8/5に東京ビックサイトで開催された**Maker Fair TOKYO2018**に参加してきました。たくさんのMakerと情報交換させてもらい、そこでたまたまEPS32の存在を知ったのでその足で秋月電子通称八潮店に赴きESP32-Devkit CをGet。

本記事はそのLチカの儀の報告です。

#環境について
僕の開発環境はほぼプレーン状態といって良いです。今年初めごろに新たにIntel Core-i7 8700Kで組んでからほぼAmazon Prime専用機と化していたのです。


#ソフトウェア
- [ArduinoIDE](https://www.arduino.cc/en/Main/Software)

さて、では開発環境を整えましょう。使用するのはArduinoIDEです。理由はGoogleで最初にヒットしたから。いくつかInstall方法はあるようですが、オーソドックスにArduinoIDEのページ経由、Microsoft StoreでDL.

- [CP210x USB - UART Bridge VCP Driver](https://jp.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers)

つぎはこれ。CP2102というUSB-UART変換ICのドライバです。頭空っぽにしてESP32 DevkitをPCに接続するとデバイスマネージャで謎デバイス的な感じで認識されたので、ドライバをインストールしてあげてください。そうするとArduinoIDEでもポート設定ができるようになります。

- [Arduino core for the ESP32](https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide/boards_manager.md)

最後にArduinoIDEにEPS32系のボード情報をサポートさせてあげましょう。ArduinoIDEはその名の通り、Arduino系ボードのみをデフォルトでサポートしています。サポートするボードを拡張してあげるために下記の作業を行いました。

画像のURLをCtrl+Cでクリップボードにコピーして、
![Capture3.JPG](https://qiita-image-store.s3.amazonaws.com/0/193066/b6ab0805-69ff-c885-0b6e-3fe5e3ef789c.jpeg)

ここにCtrl+Vでペースト。
![Capture4.JPG](https://qiita-image-store.s3.amazonaws.com/0/193066/f279e393-0748-dfe1-f6b8-67541d910cd1.jpeg)

ArduinoIDEメイン画面の
Tools > Board: "hogehoge" > Boards Manager... を選択。

![Capture5.JPG](https://qiita-image-store.s3.amazonaws.com/0/193066/1a8d67de-4093-0729-c47c-35d22fea3be9.jpeg)

EPS32で検索してヒットしたこれをインストールしてください。

#ハードウェア
今回のLチカはIO4ピンに接続されたLEDを300msec周期で点滅させます。
なので写真にあるように、適当なブレッドボードとLED,抵抗を拾ってきてIO4とGNDに接続しました。回路図は省略します。くねくねしてますね。

![IMG_6717.JPG](https://qiita-image-store.s3.amazonaws.com/0/193066/53eedbd2-f29d-db27-d5df-b814c299a393.jpeg)

#Code
```LED_blink.ino
void setup() {
  pinMode(4, OUTPUT);
}

void loop() {
  digitalWrite(4, HIGH);
  delay(300);
  digitalWrite(4, LOW);
  delay(300);
}
```

#結果
動作OK

#まとめ
今回は本当に初歩の初歩でした。次は手元に[AE-BME280](http://akizukidenshi.com/catalog/g/gK-09421/)があるので、これを使って温度、湿度、気圧を取得したいと思います。
Web Workerによる並列処理をRxJSを用いて実装する

# はじめに

JavaScriptはシングルスレッドだけど、時々、並列処理をしたくなります。
RxJSを使うと綺麗に書けたので紹介します。

# やり方

```ts:ホスト
import { Observable, from } from 'rxjs'
import { bufferCount, mergeMap } from 'rxjs/operators'

const enum InputType {
  InitialData,
  Direction,
}

interface InitialData {
  type: InputType.InitialData
  // 初期化のためのデータを追加
}

interface Direction {
  type: InputData.Direction
  // 並列化する処理のためのデータを追加
}

function start(initialData: InitialData, directions: Direction[], threads: number) {
  const chunkSize = Math.ceil(directions.length / threads)
  return from(directions)
    .pipe(
      bufferCount(chunkSize),
      mergeMap(directions => createWorker(initialData, directions)),
    )
}

const enum ReturnType {
  CalculationResult,
  Finished,
}

interface CalculationResult {
  type: ReturnType.CalculationResult
  // 計算結果を追加
}

interface Finished {
  type: ReturnType.Finished
}

function createWorker(initialData: InitialData, directions: Direction[]) {
  return new Observable<CalculationResult>(observer => {
    const worker = new Worker('worker.js')

    worker.addEventListener('message', e => {
      const data: CalculationResult | Finished = e.data
      switch (data.type) {
        case ReturnType.CalculationResult:
          observer.next(data)
          break
        case ReturnType.Finished:
          observer.complete()
          break
      }
    })

    worker.addEventListener('error', e => {
      observer.error(e)
    })

    worker.postMessage(initialData)
    worker.postMessage(directions)

    return () => {
      worker.terminate()
    }
  })
}
```

```ts:ワーカー
onmessage = e => {
  const data: InitialData | Direction[] = e.data

  if (!Array.isArray(data)) {
    // 初期化処理
  } else {
    data.forEach(direction => {
      // 計算
      postMessage({ type: ReturnType.CalculationResult })
    })

    postMessage({ type: ReturnType.Finished })
  }
}
```

# 解説

ポイントは２つです。

一つは、スレッド数からチャンクサイズを計算して `bufferCount` で `directions` を分割することです。ほぼ均等な数に分割できます。

もう一つは、 `Observable` のコンストラクタ引数では関数を一つ渡しますが、その関数の戻り値として　`worker.terminate()` を実行する関数を返すことです。これで、購読が終わった時に必ずワーカーが止まります。これを知らなかった時は、計算が終了した数を自分で計算してワーカーを停止していました。


# 参考にしたページ
https://qiita.com/_likr/items/d382dc120a942ba4c6fe
HoloLensが文鎮化（ただし電源は入る）したときのTips ～ ダメ元で復帰を祈る編 ～

# 最近、HoloLens日本語版RS5が出たこともあり
色々検証もかねて「Windows Device Recovery Tool」でイメージの焼き直ししたりInsider Preview版で更新したりと色々HoloLensいじっていたんですが。。。
とある不運に見舞われHoloLensが一時文鎮化しました。何があったかというとWindows Device Recovery Toolでセットアップ中にPC本体のOSが落ちてしまったという状況です。結果、USBをつないでもHoloLensとして認識しなくなりました。合わせて「Hello」と表示されて速攻で電源が切れる事態に。。。
ということで、一応その時の対処方法を残しておきます。
通常の「Windows Recovery Tool」で実施するリカバリについては以下の記事が参考になります。基本的にはツールで復旧するので一読しておくといいと思います。

[HoloLensの工場出荷状態への戻し方、またはHoloLensを33万3千円の首飾りにする前にやった3つのこと](https://qiita.com/takashijona/items/be5e23c0f3cc91435426)

## 試した方法

通常HoloLensをUSB接続し「Windows Device Recovery Tool」を立ち上げると以下のようにHoloLensとして出てきます。

![image](https://qiita-image-store.s3.amazonaws.com/0/152548/879bbf93-bbdc-d8e3-39c8-0ff8a296c4e1.png)

が今回はイメージが壊れているのでUSBで繋いでもHoloLensだと思ってくれません。よって以下のままになります。

![image](https://qiita-image-store.s3.amazonaws.com/0/152548/f45247bb-1bbf-2ee1-7957-fad190a8ac42.png)

こうなった場合の回避策は下の「電話が検出されませんでした」というボタンです。これを押すと各デバイス毎に特殊なオペレーションでデバイスを起動する方法が提示されます。
HoloLensの場合は「ボリュームの大」を押下したまま「電源ボタンを長押しする」です。これでHoloLensを起動すると電源ボタン付近のLEDの中央１点だけが点灯します。
この状態で、再度USBを接続してみてください。おそらく運がよければHoloLensとして認識してくれるでしょう。。。
なぜ、運がよければというと私の場合以下の状態から永遠に待たされる事態になりました。

![image](https://qiita-image-store.s3.amazonaws.com/0/152548/96ab7888-a6f2-c103-81a0-f2c8b90961cb.png)

一見何も解決していないように見えますが実がそうでもありません。この状態で<font color="red">さらに「電話が検出されませんでした」ボタンを押下し、もう一度選択肢の中からHoloLensを選びます。</font>
すると、見慣れた画面が表示されます。

![image](https://qiita-image-store.s3.amazonaws.com/0/152548/9291750a-817b-1597-98bb-2d8cbe62442b.png)

おそらくこの状況はUSBから自動的にHoloLensを検出できていないので「<font color="red">手動でHoloLens</font>」だと主張することで無理やりイメージを書き込む方法と思われます。

## 結果
無事に復旧はしました。その後ちゃんとHoloLensも立ち上がりUSBでもHoloLensとして認識してくれます。

## 注意点
上記の対応を行うためには以下は守ってやった方がいいと思います。

* バッテリーはしっかり充電しておく<br />せっかくリカバリ目的で実施している作業途中で電源断するとさらに状況が悪化します。一応ツールでも警告はしれくれますが、バッテリー劣化のことも考えて40%以上は確保を。すでに半文鎮化して残量確認できない場合はHoloLens純正ACアダプタ＆コネクタで1日餌やりを。
* USB接続はHoloLens純正のケーブルでPC本体と直結<br />ハブなどを挟んだり他の機器をつなぐとそれが原因でトラブルになるかもしれません。できるだけ余計なものは外して対処を。

## 最後に
私はこの方法で戻せましたが、必ず解決するかはわかりません。特に後者の「HoloLensとみなしてリカバリーする」は結構危ない機能ではあるので実施の際はご自身のHoloLensとよく相談の上、自己責任で対応をお願いします。
Data URL scheme で世界最小のモーションタイポグラフィ

タイトルは釣りです。かつ一発ネタです。
下記コードをブラウザのアドレスバーに入力して Enter! すると、ちゃっちいのが流れます。

```html
data:text/html,<style>*{margin:0;}marquee{font-size:256px;line-height:100vh;}</style><marquee>Hello, world!</marquee>
```

![motiontypography1.gif](https://qiita-image-store.s3.amazonaws.com/0/248832/90bd1b78-0c8f-a0bc-bdfe-00390c03e245.gif)


[こちらの記事](https://coliss.com/articles/build-websites/operation/work/tiny-editor-into-your-browser.html)を読んでいて、「そうか、 data URL は HTML もいけるのか」と思ったのがきっかけです。「そりゃブラウザの認識できるメディアタイプなら何でもいけるやろ」と直後にセルフツッコミをかましましたが、 `text/html` は盲点でした。これは何かしらのシチュエーションで役に立つかもしれませんね。 `window.open()` で作ったウィンドウに DOM を構築したい時とか。稀なシチュエーションですけど。

ところで、「待てよ…これは北斗の拳の“アレ”が作れるのでは？」と思い立ち、作った第二弾が下記コードです。
_※ ~~Chrome ではマルチバイト文字列が化けてしまうので Firefox でお願いします。 URL エンコードしてもダメでした。~~ `meta[charset="utf-8"]` を付けたら大丈夫でした。_

```html
data:text/html,<meta charset="utf-8"><style>*{margin:0;}body{background-color:black;}marquee{color:white;font-size:100vh;font-style:italic;line-height:100vh;}</style><marquee>世紀末救世主伝説</marquee>
```

![motiontypography2.gif](https://qiita-image-store.s3.amazonaws.com/0/248832/8066132c-8a02-332b-5f85-304f0503baf3.gif)


すばらしい。子供の頃の思い出が蘇るようです。工夫すれば「絶対無敵ライジンオー」もいけると思います。
それにしても `font-size` に `100vh` をブチ込んだのは人類史上私が初めてではないでしょうか。ってゆうか効くんですね、 `font-size: 100vh;` 。これも何かしらのシチュエーションで役に立つ、わけないか。はい。

なお、 `data:text/html,...` はあくまで URL なので、本来はちゃんと URL エンコードするべきです（上記コードは簡便のために素のままで掲載しています）。最初はカラーコードを `#000` としていましたが、 `#` が入っているので叱られちゃいました。

以上。 Twitter なんかで小さいコードを載っける時にも役に立つかもしれませんね。
リモートデスクトップ接続で「ネットワークレベルの認証が必要です」と出た場合

# はじめに

先日まで問題なくリモートデスクトップで接続出来ていた遠隔マシンに接続しようとしたら下記のようなダイアログが出てきた。

<img src="https://qiita-image-store.s3.amazonaws.com/0/165884/361eb02a-b7c3-4b6c-e362-636fce7695b2.png" width=80%>

## 環境

接続元: Windows10
接続先: Windows10

## 解決策

接続先のマシンで下記の手順を行うと接続出来るようになった。


<img src="https://qiita-image-store.s3.amazonaws.com/0/165884/227daa44-acbe-6caf-edfc-f925678ae7c7.png" width=80%>

![2018-08-09_22h04_27.png](https://qiita-image-store.s3.amazonaws.com/0/165884/aa547b71-e5a9-b092-e2e7-d990444c6836.png)


遠隔マシンなのでなにかの拍子に設定が変更されてしまったのかもしれない。
jQueryでタグを入れ替える例(p ⇔ textarea)

## 要件
・p要素の時クリックするとtextareaに
・textareaの時にblurするとpに

## コード

```html
<div class="container">
<p class="text js-click"></p>
</div>
```

```javascript
$(document).ready(function () {
    // p要素の時クリックすると編集出来るtextareaになる
    $('div.container').on('click', 'p.js-click',function () {
        $(this).replaceWith(function () {
            $(this).replaceWith("<textarea class=\"text js-click-term\">" + $(this).text() + "</textarea>");
        });
        // ここでfocusしないと、次のblurイベントが起きない
        $('textarea.js-click-term').focus();
    });
    // textareaの時フォーカスを外すとp要素に戻る
    $('div.container').on('blur', 'textarea.js-click',function () {
        $(this).replaceWith(function () {
            $(this).replaceWith("<p class=\"text js-click\">" + $(this).text() + "</p>");
        });
    });
});
```

## 補足
このコードだと、textareaで編集した内容はpに戻った時に反映されないのでVueのv-modelとかでやると楽そう。
【Rails】renderメソッド

##レンダリングとは

実際に画面に表示される内容を生成する作業。

>参照
[レンダリングとは](https://wa3.i-3-i.info/word1359.html)

>例)
render plain:　--表示するテキスト--
と言うものがあれば、そこに用意された値をテキストデータとして扱うことを示す。


##HTMLのソースコードをレンダリングしたい際は？

通常通りに、HTMLのソースコードを書いてもRailsの特質上「HTMLは基本的に全て自動的にエスケープ」されてしまいます。
つまり、ブラウザ上で見た際に文字化けした状態で見えると言うことです。

ここで、登場するのが「html_safe」です。

###  HTMLを表示するアクション

```ほにゃらら_controller.rb

def アクション名
   render html: '・・・HTMLのソースコード・・・'.html_safe
end
```

これで、表示されるでしょう。
PHPでRSSを作成

rdf拡張子のRSSを表示させる場合は以下の行が書かれた「.htaccess」を作成して、表示させたいrdfのディレクトリに置いてください。
「.htaccess」を作成させる場合はサーバーにアップしてからリネームすると「.」がついたファイルを作成できます。

```text:.htaccess
AddType application/xml .rdf
```

SimpleXMLElementを使う事で、簡単にRSSを作成できます。
今回は作成したRSSをすぐに表示させていますが、一度ファイルとして保存したものを表示する方法でもいいと思います。
表示されない場合はhtmlspecialchars()で文字をエスケープしてから表示してみてください。
myblog.rdfを保存する場合は、サーバーの公開ディレクトリ直下にrssフォルダを作成してください。

```php:rss.php
<?php

	try{
	
		$RSS = <<<EOT
<?xml version="1.0" encoding="UTF-8"?>
	<rss version="2.0">
		<channel>
			<language>ja</language>
		</channel>
	</rss>
EOT;

		$rssFileName = 'myblog.rdf';
		
		$XML = new SimpleXMLElement($RSS);
		$XML->channel->addChild('title', "ブログタイトル！");
		$XML->channel->addChild('link', 'http://' . $_SERVER['HTTP_HOST'] . '/rss/' . $rssFileName);
		$XML->channel->addChild('description', "ブログの更新情報です");
		
		$item = $XML->channel->addChild('item');
		$item->addChild('title', "記事タイトル");
		$item->addChild('link', 'http://' . $_SERVER['HTTP_HOST'] . "/page/mypage.html");
		$item->addChild('category', "カテゴリ");
		$item->addChild('description', "記事についての説明");
		$item->addChild('content', "記事の中身");
		$item->addChild('date', date('Y-m-d H:i:s'));
		
		
		header('Content-Type: text/xml');
		ob_end_clean();
		echo $XML->asXML();
		
		$file = fopen($_SERVER['DOCUMENT_ROOT'] . '/rss/' . $rssFileName, "w");
		fwrite($file, $XML->asXML());
		fclose($file);
	
	}catch ( Exception $e ) {
	}
	
	
?>

```

ポイントとしてはob_end_cleanを使用することで、作成したRSSを直接表示させることが出来ます。
VRIK(FinalIK)を適用するとVRMの揺れもの(VRM Spring Bone)の動きがおかしくなる時の対処


# 原因

VRIKの`FixTransforms`によって、揺れものの計算結果が上書きされていることによるものでした。

VRIKの`FixTransforms`がどういうものかというと、ソースコードには以下のように書いてありました。

> If true, will fix all the Transforms used by the solver to their initial state in each Update. This prevents potential problems with unanimated bones and animator culling with a small cost of performance. Not recommended for CCD and FABRIK solvers.

IKで計算されない各Transformの値を毎フレーム初期値でリセットする機能でしょうか。
これによって、揺れもののTransform値が上書きされてしまったようです。

外せるならそれで解決しそうですが、私の場合はオフだとメッシュがプルプルしてたのでつけたままでの対処を考えました。

# 解決方法

Spring Boneの実行順を`FixTransforms`よりも後に設定する。

`ProjectSetttings>ScriptExecutionOrder`を以下のように設定してください。

![aaaaaaa.PNG](https://qiita-image-store.s3.amazonaws.com/0/55365/34465a25-fc59-2529-5a1d-74e4cd5c081f.png)

FinalIKはインポート時にデフォルトより後に実行されるように設定されています。
なので、SpringBoneをそれよりも後に実行するように指定してやれば良いです。

# その他気にするところ

Animatorが設定されている場合は、それによって制御されている場合があるので確認してみてください。
(AnimatorコンポーネントのControllerがnullなら何もしてこないはずです。)


# 参考

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">SmoothJointってアセットで髪揺れ設定したら、昨日は揺れてたのに今日は揺れないやんけ！と思ったら、なんかVRIKと競合してスクリプト実行順で動いたり動かなかったりしてたっぽい。SmoothJointのScriptExecutionOrderをFinalIKより後にしたら動いた。VRIKのFixTransform機能が髪揺れを止めちゃう感じ</p>&mdash; 海行プログラム (@kaigyoPG) <a href="https://twitter.com/kaigyoPG/status/958271307124064256?ref_src=twsrc%5Etfw">2018年1月30日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ほぼこれと同じ内容でした。
Nuxt.js on Flask on Dockerの環境をサクッと作ってみる

試した環境
Docker for Mac

## ディレクトリ構成
Nuxt-Flask-app/
├── app/
│　　└── main.py
├──　　uwsgi.ini
├── Dockerfile
└── docker-compose.yml

```main.py
from flask import Flask, render_template,jsonify
from flask_cors import CORS

app = Flask(__name__)
cors = CORS(app, resources={r"/*": {"origins": "http://127.0.0.1:3000"}})

@app.route('/api')
def api():
  message = {}
  data = {}

  message['message'] = 'Hello World from Flask!'
  data['status'] = 200
  data['data'] = message

  return jsonify(data)

if __name__ == '__main__':                        
    app.run(host="0.0.0.0", port=80, debug=True)

```

```uwsgi.ini
[uwsgi]
module = app.main
callable = app
```


```Dockerfile

FROM tiangolo/uwsgi-nginx-flask:python3.6

COPY ./app /app

RUN apt-get update -y 
RUN curl -sL https://deb.nodesource.com/setup_10.x | bash -
RUN apt-get install -y nodejs

RUN npm update -g npm

RUN npm install -g vue-cli
RUN npm install -g nuxt

RUN npm install -g create-nuxt-app

RUN pip install -U flask-cors

ENV HOST 0.0.0.0
```

```docker-compose.yml
version: '3'
services: 
  web: 
    build: .
    ports:
      - 80:80
      - 3000:3000
    volumes:
      - './:/app'
    environment:
      - NGINX_HTTP_PORT_NUMBER=80
```
## 手順
```shell

# on mac
docker-compose build
docker-compose up -d
docker-compose exec web bash

# in container
create-nuxt-app ./
# 色々選択肢が出てきますが、とりあえずNuxtアプリを作りたい場合は全てEnterを押す。
npm run dev
```
http://localhost:3000
にアクセスしてデフォルト画面が出れば、いったんは構築完了。

## Nuxt.jsの編集

```pages/index.vue
<template>
  <div>
    <h1>{{ data.message }}</h1>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  async asyncData () {
    let data = await axios.get('/api')
    console.log(data)
    return data.data
  }
}
</script>
```

```nuxt.config.js

// 追加
  env: {
    HOST_URL: process.env.HOST_URL || 'http://localhost:5000'
  },
```

http://localhost:3000
にアクセスしてデフォルト画面が出れば以下の画面が出れば構築完了。
<img width="385" alt="スクリーンショット 2018-08-09 21.03.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/133718/433f88be-940d-2e42-b409-4842a2764344.png">

## 参考
https://www.codementor.io/lautiamkok/creating-a-nuxt-application-with-python-frameworks-kd2yjqsfx
MySQLのプロシージャでトランザクション処理

最初はPHPに備わっているPDOのトランザクションを利用しようとしたんですが、
beginTransaction()、rollBack()をするもDBがなぜか更新されてしまうという事が起きました。
autocommitも切って、inTransaction()でトランザクション内かどうかを調べるもちゃんと「true」
という事で、MySQLサイドで直にトランザクションが行われているかを調べるために作成しました。

実際に作成したプロシージャ

```sql
DROP PROCEDURE IF EXISTS SQLEXE;

DELIMITER //
CREATE PROCEDURE SQLEXE(
    IN EDITSQL TEXT,
    OUT ERRFLG INT,
    OUT MESSAGE VARCHAR(255)
)
BEGIN
    DECLARE EXIT HANDLER FOR SQLWARNING, NOT FOUND, SQLEXCEPTION
    BEGIN
        SET MESSAGE := CONCAT(MESSAGE, "エラーです!");
        ROLLBACK;
    END;

    SET ERRFLG := 1;
    SET MESSAGE := "";

    SET AUTOCOMMIT := 0;
    START TRANSACTION;

        SET @EDITSQL := EDITSQL;
        PREPARE stmt FROM @EDITSQL;
        EXECUTE stmt;

        SET ERRFLG := 0;

    IF ERRFLG = 0 THEN
        SET MESSAGE := CONCAT(MESSAGE, "COMMITしました!");
        COMMIT;
    ELSE
        SET MESSAGE := CONCAT(MESSAGE, "ROLLBACKしました!");
        ROLLBACK;
    END IF;

END;
//
DELIMITER ;
```

SQLEXEプロシージャでは受け取った文字列をSQLとしてただ実行するだけです。
正常に処理が完了するとOUTとしてMESSAGEにCOMMITかROLLBACKのメッセージが入るはずです。
ECLARE EXIT HANDLERを利用すると、MySQLでのプロシージャ内のエラーを制御する事ができます。

PHPでの実装

```php:test.php
    $sql = <<<SQL
    CALL SQLEXE("UPDATE BLOG SET BLOGNAME = 'てすと' WHERE BLOGID = 1;",@ERRFLG, @MESSAGE);
SQL;

    $stmt = null;
    $stmt = $GLOBALS['MYDB']->prepare($sql);
    $stmt->execute();


    $sql = <<<SQL
    SELECT @ERRFLG AS ERRFLG, @MESSAGE AS MESSAGE FROM DUAL;
SQL;

    $stmt = null;
    $stmt = $GLOBALS['MYDB']->prepare($sql);

    $stmt->execute();
    $row = $stmt->fetch(PDO::FETCH_ASSOC);
    var_dump($row);
    
```


「BLOG」がテーブルで「BLOGNAME」「BLOGID」がカラムです。
SQLEXEに文字列のSQLを渡して、SQLを実行させます。
処理が完了した際に「@ERRFLG」と「@MESSAGE」にそれぞれ処理の結果が保存されているので確認してみます。
そして実行完了後にERRFLG=1でわざとロールバックさせると
きちんと@MESSAGEに「ROLLBACKしました!」の文字が入っていました。
そしてDBを確認してみるとなぜか更新されています。。。

## 結論から言うと

そもそも**ストレージエンジンがMyISAMなのでトランザクション機能をサポートしていない。**という事でした。
そしてロックにおいてもMyISAMの場合はテーブル単位、InnoDBの場合は行ロックだそうです。
MySQLのファンクションでパスワードの暗号化、複号化


DBのストアドプロシージャ／ファンクションの覚え書き
PHPでやるより管理が楽＆共通化ということでパスワードファンクションを作成。

```sql

DROP FUNCTION  IF EXISTS GET_PASSWORD;

DELIMITER //
CREATE FUNCTION GET_PASSWORD(
	IN_MODE INT,					/* 1：暗号化 2：複号化 */
	IN_PASSWORDKEY VARCHAR(100)		/* 1：暗号化、複号化する文字 */
)
RETURNS VARCHAR(100) DETERMINISTIC
BEGIN
    DECLARE STR_AESKEY 		VARCHAR(10)  DEFAULT NULL;
    DECLARE STR_PASSWORD 	VARCHAR(100) DEFAULT NULL;
	DECLARE EXIT HANDLER FOR SQLWARNING, NOT FOUND, SQLEXCEPTION
	BEGIN
		RETURN NULL;
	END;
	
	SET STR_PASSWORD := NULL;
	SET STR_AESKEY := 'TEST'; /* 共通AESキー */
	
	IF IN_MODE = 1 THEN /* 暗号化 */
	
		SET STR_PASSWORD := HEX(AES_ENCRYPT(IN_PASSWORDKEY, STR_AESKEY));
	
	ELSEIF IN_MODE = 2 THEN /* 複号化 */
	
		SET STR_PASSWORD := AES_DECRYPT(UNHEX(IN_PASSWORDKEY), STR_AESKEY);

	END IF;
	
	RETURN STR_PASSWORD;
	
END;
//
DELIMITER ;

```

ファンクションが作成されたかの確認

```sql
SHOW FUNCTION STATUS;
```

実際に使ってみる。

```sql
	SELECT GET_PASSWORD(1,'pass') FROM DUAL
	
	SELECT GET_PASSWORD(2,'555939D89BE849A54A2BCD6084AD0BE6') FROM DUAL

	--1
	SELECT COUNT(*) FROM DUAL
	WHERE 'pass' = GET_PASSWORD(2,'555939D89BE849A54A2BCD6084AD0BE6')
```

カウント１取れました。今回のDBファンクション作成は成功です！
各OSごとの標準システムフォント

見つけられなかったのでまとめてみた。古い環境は無視している。

|  | 日本語フォント | 日本語UIフォント | 欧文フォント |
|:-----------|:------------:|:------------:|:------------:|
| Windows 8.1以降 | Yu Gothic( 游ゴシック )   | Yu Gothic UI  | Segoe UI |
| Windows7 | Meiryo ( メイリオ )	   | Meiryo UI  | Segoe UI |
| Mac OS El capitan 以降/iOS | Hiragino Sans |   | Sanfrancisco |
| Mac OS 10.10以前 | Hiragino Kaku Gothic ProN  |   | Helvetica Neue |
| Android    | Noto Sans CJK JP       |  | Roboto      |

時間があったらwebのfont-family指定方法まとめる
第28話 完全数

この記事は[仮面ライダービルドの数式](https://qiita.com/izmktr/items/e26a624e79bce3edccc9)の第28話です。

```math
1+2+4+7+14=28
```

28は完全数という意味です。
完全数とは、自身未満の約数の和が自身と等しい値になる数です。
たとえば、28の自身未満の約数は1,2,4,7,14ですから、それらを足すと28になります。

完全数は無限にあることがわかっていて、以下の形で計算できます。

```math
2^{n-1} (2^n-1)\     但し、2^n-1は素数
```

約数の和を求めるには、その数を素因数分解できれば簡単な式で求めることができます。

```math
x=A^a B^b C^c  \\
S(x)=\frac{A^{a+1}-1}{A-1}  \frac{B^{b+1}-1}{B-1}  \frac{C^{c+1}-1}{C-1}
```

先程の完全数の式をこの式に当てはめるとこうなります。

```math
S(2^{n-1} (2^n-1))=\frac{2^n-1}{2-1} \frac{(2^n-1)^2-1}{(2^n -1)-1}\\
=\frac{(2^n-1)  (2^{2n}-2\cdot 2^n+1-1)}{2^n-2}\\
=\frac{(2^n-1)  2^n (2^n-2)}{2^n-2}=2^n(2^n-1)=2\cdot 2^{n-1} (2^n-1)
```

この約数の和は自分自身も含むので、元の値の2倍になっていれば完全数になります。
$2^n-1$が素数でないと約数の和の式も変わってしまい、完全数にはなりません。

なお、偶数の完全数は先程の式で網羅できますが、奇数の完全数に関しては未解決です。
現在は300桁以下の数の中にはない、少なくとも9個以上の素因数を含む、
みたいな条件は見つかっているので、あるとしたら相当大きい数になるでしょう。
cURLの並行リクエストを使っていいね数・ツイート数・はてブ数を取得する


自分の環境ではいいね数がなぜか取得できないのでコメントの部分を使っています。

```php:sns.php
	//―――――――――――――――――――――――――――――――――――
	//SNSシェア数取得
	//―――――――――――――――――――――――――――――――――――
	$PAGEIINE 	= 0;
	$PAGETWEET 	= 0;
	$PAGEHATEBU = 0;
	
	$urls = array();
	$chlist = array();
	
	$PAGEURL = "https://www.google.co.jp/";
	
	//いいね数	
	$urls['IINE'] = "http://graph.facebook.com/?id=" . urlencode($PAGEURL);
	//$urls['IINE'] = "https://www.facebook.com/plugins/like.php?&layout=button_count&href=" . urlencode($PAGEURL);
	
	//ツイート数
	$urls['TWEET'] = "http://urls.api.twitter.com/1/urls/count.json?url=" . urlencode($PAGEURL);
	
	//はてブ数
	$urls['HATEBU'] = "http://b.hatena.ne.jp/entry/jsonlite/?url=" . urlencode($PAGEURL);
	
	$mh = curl_multi_init();
	
	foreach ($urls as $sns => $url) {
		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);		//変数に保存する
		curl_setopt($ch, CURLOPT_TIMEOUT, 10);				//実行にかけられる時間の最大値
		curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; Touch; rv:11.0) like Gecko');
		curl_multi_add_handle($mh, $ch);
		$chlist[$sns] = $ch;
	}
	
	//―――――――――――――――――――――――――――――――――――
	//並行リクエスト実行
	//―――――――――――――――――――――――――――――――――――
	do {
	    $mrc = curl_multi_exec($mh, $active);
	} while ($mrc == CURLM_CALL_MULTI_PERFORM);
	
	while ($active && $mrc == CURLM_OK) {
		if (curl_multi_select($mh) != -1) {
			do {
				$mrc = curl_multi_exec($mh, $active);
			} while ($mrc == CURLM_CALL_MULTI_PERFORM);
		}
	}
	
	//―――――――――――――――――――――――――――――――――――
	//リクエスト結果を取得
	//―――――――――――――――――――――――――――――――――――
	foreach ($chlist as $sns => $ch) {
		
		$contents = curl_multi_getcontent($ch);
		
		switch($sns){
			case 'IINE' :
				$json = json_decode($contents, true);
				$PAGEIINE = isset($json['shares']) ? intval($json['shares']) : 0;
				//if(preg_match('/<span class="pluginCountTextDisconnected">([0-9]+)<\/span>/', $contents, $match)){
				//	$PAGEIINE = intval($match[1]);
				//}
			break;
			case 'TWEET' :
				$json = json_decode($contents, true);
				$PAGETWEET = isset($json['count']) ? intval($json['count']) : 0;
			break;
			case 'HATEBU' :
				$json = json_decode($contents, true);
				$PAGEHATEBU = isset($json['count']) ? intval($json['count']) : 0;
			break;
		}
		curl_multi_remove_handle($mh, $ch);
		curl_close($ch);
	}
	
	curl_multi_close($mh);
	
	echo 'PAGEURL：' . $PAGEURL . '<BR>';
	echo 'PAGEIINE：' . $PAGEIINE . '<BR>';
	echo 'PAGETWEET：' . $PAGETWEET . '<BR>';
	echo 'PAGEHATEBU：' . $PAGEHATEBU . '<BR>';
	
````

結果がこんな感じです

```:result
PAGEURL：https://www.google.co.jp/
PAGEIINE：84428
PAGETWEET：135793
PAGEHATEBU：918
```

複数のSNSのAPIを叩くならやっぱり並行処理のほうが効率良いですね。
ajaxでオブジェクト指向を実現する


今まではajaxの結果に処理を直接書いていましたが
クラスを使ってインスタンスごとに制御させる方法が見つかったのでメモ

```javascript:request.js

	var REQUESTLIST = [];

	$(document).ready(function(){

		sendMSG();

	});

	function sendMSG(){

		var msglist = ["あいうえお", "かきくけこ",  "さしすせそ"];

		for(var i=0; i < msglist.length; i++){

			var req = new REQUEST("SEND", msglist[i]);
			req.sendReq();

			REQUESTLIST.push(req);

		}

	}


	//クラス
	function REQUEST(sta, msg){

		this.sta = sta;
		this.msg = msg;
		this.result;

		this.sendReq = function(){

			var oya = this;

			$.ajax({url: 'msg.php?msg=' + this.msg, type: 'GET'
			}).done(function(data, status, xhr) {

				oya.sta = "COMP";
				oya.result = data;
				requestComp();

			}).fail(function(xhr, status, error) {
			}).always(function(arg1, status, arg2) {
			});

		}

	}

	function requestComp(){

		var ALLCOMPFLG = 1;

		for(var i=0; i < REQUESTLIST.length; i++){

			var req = REQUESTLIST[i];

			if(req.sta == "SEND"){
				ALLCOMPFLG = 0;
			}

		}

		if(ALLCOMPFLG == 1){

			for(var i=0; i < REQUESTLIST.length; i++){

				var req = REQUESTLIST[i];

				console.log(req.result);

			}

		}

	}
	
```

php側はmsgを表示するだけです。

```php:msg.php
	
	echo $_GET['msg'] . 'を表示しました';
	
```

ポイントとしてはvar oya = thisとする事で親のプロパティー(作成したREQUESTクラスの事)にアクセス出来ます。

作成したREQUESTというクラスではphp側との通信が完了したら
そのクラスの中のプロパティーのsta(ステータス)を更新しています。
実際に通信する場合は作成したインスタンスをREQUESTLISTに格納後
requestCompを呼ぶことでインスタンスごとのstaを見て、すべての通信が終わっているかを確認しています。
Rustのmysql (rust-mysql-simple)で何故かUNIX Socketを見に行く問題

追記。タイトルが良くなかったので変えました。r2d2もr2d2_mysqlも関係なくて、rust-mysql-simpleの部分でハマってました。

RustでWebアプリケーションを作っていて、RDBMSとしてMySQLを使おうとしていたところ、問題が。

こんなコード（サンプルをほぼ丸パクリ）で

```rust
extern crate mysql;
extern crate r2d2_mysql;
extern crate r2d2;
use std::env;
use std::sync::Arc;
use std::thread;
use mysql::{Opts,OptsBuilder};
use r2d2_mysql::MysqlConnectionManager;

fn main() {
    let db_url =  env::var("DATABASE_URL").unwrap();
    let opts = Opts::from_url(&db_url).unwrap();
    let builder = OptsBuilder::from_opts(opts);
    let manager = MysqlConnectionManager::new(builder);
    let pool = Arc::new(r2d2::Pool::builder()
                       .max_size(4)
                       .connection_timeout(std::time::Duration::new(2, 0))
                       .build(manager)
                       .unwrap());
}
```

実行すると

```terminal
$ DATABASE_URL="mysql://root:password@127.0.0.1:3306/nanntoka" cargo run
   Compiling hoge v0.1.0 (file:///home/tmatsushima/Project/hoge)                                                                                        
    Finished dev [unoptimized + debuginfo] target(s) in 1.89s
     Running `target/debug/hoge`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error(Some("DriverError { Could not connect to address `/var/run/mysqld/mysqld.sock\': No such file or directory (os error 2) }"))', libcore/result.rs:983:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.
```

「 `mysqld.sock` が見つからなかったよ、てへぺろ」

## じゃぁどうするの

「接続先URLの後ろに `?prefer_socket=false` オプションつけて」っということらしいです。
https://github.com/blackbeam/rust-mysql-simple/issues/150

だから、さっきみたいに `cargo run` するときに渡す環境変数を変更して、こんな感じ。

```console
$ DATABASE_URL="mysql://root:password@127.0.0.1:3306/nanntoka?prefer_socket=false" cargo run
```

なんだそりゃ。接続先指定してるのに。
VirtualCastのサウンド出力デバイスを変更する方法

# はじめに
2018/8/9現在、VirtualCast自体にはサウンドデバイスの入力・出力の指定が出来ません。
そのため、マイクやスピーカーはWindows側で指定されている、既定のデバイスが選択されるようです。
一般的な環境ではそこまで困らないと思いますが、複数のサウンドデバイスを使っていたり、ミキサーを経由している場合には、アプリ毎にサウンドデバイスを指定できる方が都合が良いです。

# たとえば
コラボ放送等していると、凸者の声が大きかったり小さかったりすることがあります。
VirtualCast内に凸者毎の音量調整機能はありますが、それでは調整しきれないケースがよくあります。
既定のデバイスの音量を変更してしまうと、棒読みちゃんやBGM等その他サウンドの音量にも影響が出てしまうため、今回はVirtualCastのサウンドデバイスを既定以外に指定し、ミキサー側でそのデバイスの音量を調整する方法を採用してみることにしました。

# 方法1　Windows10の機能を利用する
**結論：この方法は使えませんでした**

Windows10にはアプリ毎にサウンドデバイスを変更する機能があるため、その機能を利用します。

1. Windowsのサウンド設定から、「アプリの音量とデバイスの基本設定」を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/887fcf3e-4fc8-03ca-0f42-a476fcc807b5.png)

2. VirtualCast.exeの出力指定を、目的のサウンドデバイスに変更する
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/70edf5c4-b9bf-c5ea-b9a9-e54a646339ea.png)

本来はこれだけで出力先が変わるはずなんですが、何度やっても変更が反映されませんでした。。
※VirtualCast以外で試したところ、変更可能でした

# 方法2 Audio Routerを使う
**結論：変更可能　ただし設定保存不可**

下記GitHubにて、公開されているAudio Routerというソフトを使います。
https://github.com/audiorouterdev/audio-router

ソフトを起動し、VirtualCast設定内のRouteを選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/98a327eb-ee9a-afe9-8ab2-380abcdf08b1.png)

目的のサウンドデバイスを指定します
![image.png](https://qiita-image-store.s3.amazonaws.com/0/279041/c8fc0d6b-9df6-61e7-bebc-b3229f52fac8.png)

以上で、設定は終わりです。
テストしてみたところ、正常にサウンドデバイスが切り替わっていました。

ただし、下記のような欠点があります。

- 利用時にAudioRouterを起動させておく必要がある
- 設定が保存できないので、起動のたびにデバイスの指定が必要

# 方法3 CheVolumeを使う
**未検証です**

http://www.chevolume.com/
CheVolumeというソフトもアプリ毎のサウンドデバイス変更が可能なようです。
ただ、シェアウェアなので、今回試していません。

# 最後に
あまり満足のいく方法はありませんでしたが、
将来的にはバーチャルキャスト側で機能実装されることを期待します。
Flutterにふれてみる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/110859/7034a1a0-e0fa-f5fc-0508-52302ed9f4e2.png)


## Flutterとは
https://flutter.io/

* クロスプラットフォームでアプリ開発するフレームワーク
* 言語はDart
* Googleが開発してるOSS
* Material DesignのUIライブラリが豊富
* Hot Reloadなどの開発環境が整ってる

## setup
自分の環境はMacなので、事前にXcodeは入れとく

```sh
$ git clone https://github.com/flutter/flutter.git
$ export PATH=`pwd`/flutter/bin:$PATH # 必要であれば.bashrcとかに書いとく

$ flutter doctor # 依存関係やらいい感じにしてくれるらしい(困ったらこれ叩くとアドバイスくれるっぽい)
# 色々やれとのこと
$ brew install --HEAD libimobiledevice
$ brew install ideviceinstaller
$ brew install ios-deploy
$ brew install cocoapods
$ pod setup
```

## try

```sh
$ flutter create flutter_sample && cd flutter_sample
$ open -a Simulator
$ flutter run # コードの変更はターミナル上でrを押すと反映される
```
動いた！
<img width="382" alt="スクリーンショット 2018-08-09 18.38.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/110859/fa6bbcfe-33cf-4f3e-93cb-1194f43134d1.png">


## other
* VSCodeとか使うともっといい感じにHot Reloadできる  
https://qiita.com/ozaki25/items/e765cc90cd6ace675e69
* フォーマッターもある `flutter format <filename>`（IntellijとVSCodeならプラグインがやってくれる）
* エディタのサポートが手厚く、閉じタグの後にこんな感じでフォロー（ // AppBar）が入る  
<img width="284" alt="スクリーンショット 2018-08-11 23.43.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/110859/f405c4bb-bf7d-9227-c054-643dba36966c.png">
Android Studio のエミュレータが動かないと思ったらdockerのvisualizationが邪魔をしていたらしい

# Android Studio のエミュレーターが動かない
windows10

```
18:30	Emulator: emulator: ERROR: x86_64 emulation currently requires hardware acceleration!
18:30	Emulator: CPU acceleration status: Unable to open HAXM device: ERROR_FILE_NOT_FOUND
18:30	Emulator: Process finished with exit code 1
```

2,3日前は動いていたけど、windows update とか Android Studio のupdate とか bios の更新とか、いろいろした気がする。
bios で acceralerator が動いていることは確認。
HAXM がインストールされているか以下で確認。

```
PS C:\Users\***\AppData\Local\Android\Sdk\extras\intel\Hardware_Accelerated_Execution_Manager>.\silent_install.bat
Intel HAXM updated successfully!
```

問題なさそう。

# 対応

##accel check

https://developer.android.com/studio/run/emulator-acceleration
windows でも同様にできる。

```
c:\Users\***\AppData\Local\Android\Sdk\tools>emulator.exe -accel-check
accel:
15
Please disable Hyper-V before using the Android Emulator. Start a command prompt as Administrator, run 'bcdedit /set hypervisorlaunchtype off', reboot.
```

Hyper-が邪魔らしい。設定した記憶はないんだけど。

```
c:\Users\***\AppData\Local\Android\Sdk\tools>bcdedit /set hypervisorlaunchtype off
```

再起動すると、あれ、docker for windows が警告画面をだした（SS忘れてた)。
visualization で Hyper-V が必要らしい。こいつが元凶か。

エミュレータは無事起動。
AndroidStudio上でSpekとJUnit4の共存

https://spekframework.github.io/spek/docs/latest/#setting-up-legacy

ここに従って、JUnit4でもSpek実行できるようにすると、逆にJUnitで書いてあったテストが
Android Studio上で `Empty test suite.` と出て実行できなくなる。
`./gradlew test` では実行できる。

調べてみると、

``` Spekが実行できる状態のログ.txt
〜/mockable-android-27.v3.jar" com.intellij.rt.execution.application.AppMainV2 com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 -junit5 <テストクラス>
```

``` Spekが実行できない場合のログ.txt
〜/mockable-android-27.v3.jar" com.intellij.rt.execution.application.AppMainV2 com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 <テストクラス>
```

と、Spekが実行できる場合にコマンドのオプションで `-junit5` というのがついている。

どうやら、JUnit5上でテストを実行しているようなので、 [公式](https://junit.org/junit5/docs/current/user-guide/#migrating-from-junit4-running) を参考に、JUnit5上でJUnit4形式のテストを動かすエンジンを入れたらテストの実行は出来た

## ToDo
他に確認しといたほうがいいこと
- Robolectricがちゃんと動くのか？
- espressoがちゃんと動くのか？
iOSでvideoタグの周りに枠線がつく問題の対応

普通にvideoタグをplaysinlineで入れただけなのに、なぜか周りに枠線がついていた問題の対処方法です。
iOS 11.3のiPhone 8 PlusのSafariで発生した現象ですが、同じバージョンで同じモデルの別端末ではこの現象が発生せず、端末によって現象が変わるようです（何が違うのかは謎）。

今回僕が対応した方法としては、以下のようにcss filterのdrop-shadowをつけたことで線を消すことができました。
この設定は実際は何も変わりませんが、要素の周りのスタイルを変える設定なので、その影響で線が消えたのだと思います。

```
video {
  filter: drop-shadow(0px 0px #000);
}
```

CodePenにfilter前と後のものを置いたので、もしこの現象が発生する場合はこれで確認してみてください。
<p data-height="400" data-theme-id="0" data-slug-hash="gjQqvb" data-default-tab="html,result" data-user="wintyo" data-pen-title="gjQqvb" class="codepen">See the Pen <a href="https://codepen.io/wintyo/pen/gjQqvb/">gjQqvb</a> by TakanoriOnuma (<a href="https://codepen.io/wintyo">@wintyo</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

ちなみにoverflow: hiddenとかbox-shadowとかoutlineとかも試してみましたが、どれも消すことができませんでした。
Macでgoのpluginをlinux向けにクロスコンパイルする

##結論

プラグインファイル（以下、甲とする）とプラグインを読み込む実行ファイル（以下、乙とする）をまとめてDocker内でビルドする。

##手順
###requirement:

- Docker

プラグインファイルのあるディレクトリに移動

```shell
$ cd <甲のディレクトリ>
```

ディレクトリをマウントして甲と乙をビルド

```shell
$ docker run --rm -v "$PWD":/usr/src/app -w /usr/src/app golang:stretch /bin/bash -c "go get 乙 && go build 乙 && go build -buildmode=plugin"
```
実行し終わったら、カレントディレクトリに乙のlinuxバイナリと`app.so`ができているので、それらを所望の環境に`scp`などで送って使用する。

おしまい

---
##ホストでやればいいじゃん？と思うけど…
macで以下のコマンドを実行してlinux向けにpluginをビルドしようとすると、

```shell
$ GOOS=linux GOARCH=amd64 go build -buildmode=plugin
```

```
loadinternal: cannot find runtime/cgo
/usr/local/Cellar/go/1.10.3/libexec/pkg/tool/darwin_amd64/link: running clang failed: exit status 1
ld: unknown option: -z
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```
`ld`コマンドの`-z`オプションがないと言われて怒られる。`-z`オプションの入った`ld`コマンドを入れ直せばMacOSホストでビルドできそうな感じもするが、環境を汚したくないので、こういう時はDockerが便利。
UiPathで過去の新高値更新 年初来高値更新 銘柄を取得するまでの道のり

会社のほうでUiPathに力を入れるから勉強してみて！と言われたので勉強中。
せっかく勉強したので実際に何かしてみようかな。といった感じの内容です。

# なにをするのか

[株ドラゴン](https://www.kabudragon.com/ranking/takane.html)　こちらのページからとりあえず今日のデータを取ってくる。
エクセルファイルとして保存する
実装時間は30分くらい

# 実装していくよ

## ブラウザを起動する

ブラウザを起動するため、シーケンス内にOpen browserアタッチメントをドラッグ
URLに "https://www.kabudragon.com/ranking/takane.html" を指定

ちなみに時代遅れのIEで行います。理由は単純で、UiPathがchromeで動作しないからです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/165191/798fd1c6-cc44-d1c4-a71d-06ded91d0b6c.png)

こんな感じです。

## データを取ってきてもらう

DataScrapingを使用。適当にクリックする。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/165191/52828a2a-f7b8-b2d0-d2ca-12dbae209b4f.png)

なんか出てきた。はいを押す。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/165191/3dd1272f-63a5-f6e8-c05a-552f7b46bada.png)

自動生成してくれた！なにこれすごくない！

楽してデータを取得できた喜びに浸りつつ、Finishをクリック。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/165191/91541679-635b-44f0-cbb6-288ec5006353.png)

するとまたダイアログが。「ページまたぐ？またぐなら次へボタン教えてくれ。」ということ。またがないと信じてNo。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/165191/81df2e9b-e21b-9abb-603c-a0aa8f5076c4.png)

取得したデータテーブルを格納する変数が自動的に追加される。必須ではないが、わかりやすく変数名を変えておく。Variablesタブをクリックし、ExtractDataTableを変更する。私はNewHightValueTableにした。
ちなみに、Variablesタブから変更しないと、シーケンス内の変数名が変更されないので注意。

## CSVファイルで保存する
エクセルで閲覧できるようにCSVファイルで保存する。
ActivitiesでCSVと検索する。すると出てこない。意味不明。

チュートリアルに存在するにもかかわらず、パッケージのインストールをする必要があるのだ。なんでやねん。

Activitiesの上のほうにある箱をクリックする。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/165191/43021b06-8a43-69d9-c7ac-cb4afa3b26ab.png)


Availableをクリック。Excelと検索

![image.png](https://qiita-image-store.s3.amazonaws.com/0/165191/837d089c-d362-8c47-8bd5-f05dbb998f19.png)

インストールボタンを押してインストール


インストール後に、再度Activitiesにて"CSV"と検索。Write CSVが出てくるのでそいつをシーケンスに追加。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/165191/ed25ea0f-8947-6b8c-2ba3-c97f8bb0f786.png)

ファイル名とテーブル名を入力。
ファイル名に拡張子を忘れずに。画像では忘れています。
テーブル名はDataScrapingで取得したデータを格納している変数名です。


## 実行してみよう！
![image.png](https://qiita-image-store.s3.amazonaws.com/0/165191/c1f69372-3ba7-8509-c373-83b8f6067aa5.png)

いいね！


# 所感

思っていたよりも簡単にできた
簡単すぎてエンジニアの存在意義が薄れそう。それくらい簡単

次回はこれを拡張し、過去のデータも一緒に保存できるようにしたいと思います。
URLの仕組み

1. URLはネット上の住所
2. URLを指定することで、相手のPCへファイルを要求する
3. ポート番号は通信を通す入り口の番号
4. 「このポート番号はHTTP通信しか受け付けない」という形で制限できる
5. ポート番号で制限することで悪意のある通信から守れる
6. URLのドメイン名は相手先PCの場所をさす
7. ドメイン名をIPアドレスに置き換えることも可能

>[ウェブカツ！！](https://webukatu.com/?afid=p5lxu1kvh03rayd2ctjsw4e9bgzq8nom)
ElastiCacheのクラスタエンドポイントにCNAMEはるときは、「.cfg」を含むようにすること

# やろうとしたこと

EC2上で動作しているWebアプリケーションで、セッションの保存先をElastiCache（memcached）にしようとした。
また、可用性・負荷分散のため、クラスタ化しようとした。

その際、ElastiCache（memcached）の設定エンドポイントが長く、短いFQDNでアクセスしたかったので [^1]
Route53で以下のようにCNAMEを作った。

```shell-session
$ dig cname +short session.example.home
session.xxxxxx.cfg.apne1.cache.amazonaws.com.
```
※ `example.home` は Private type の ドメイン

# ハマったこと

セッションデータはElastiCache（memcached）に保存されるが
サイトを操作していると、時々セッションが切れたような動作になった。
（セッションデータが取れていない）
memcachedの各クラスタに入って調べてみると、
同一セッションなのにアクセスのたびに異なるクラスタに割り振られていた。

# 解決した方法

CNAME にあてたドメインを「.cfg」を含むものに変更した。

```
session.example.home
 ↓
session.cfg.example.home
```

# 詳細

ちゃんと公式ドキュメントに書いてあった。

https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/mem-ug/AutoDiscovery.Using.html#AutoDiscovery.Using.ModifyApp

> クラスターの設定エンドポイントを指定する際は必ず、ここに示す設定エンドポイントのアドレスに「.cfg」が含まれていることを確認してください。「.cfg」のない CNAME またはエンドポイントは使用しないでください。

公式ドキュメントはちゃんと読みましょう。
（でも、この記述ちょっとわかりにくいと思う…）

[^1]: もう1つの理由として、本番/ステージ/テスト環境でAWSアカウントを分けていて、全環境に `example.home` という同じ名前でPrivate ドメインを作って、全環境同じドメイン名でアクセスできるような作りにしていた。
Railsアプリケーションの中身メモ【初心者向け】

#1.Railsアプリのファイルについて

デフォルトでは以下のようなファイルが見つかるでしょう。

##.gitignore

バージョン管理システム、ソースコード共有システムの「Git」のためのファイル。本格的な開発の際、チームになって開発を進める際などに用いる。初心者の際はまずほとんど使わない。

##config.ru

Railsで使われる「Rack」と言うプログラムで使われる。Railsアプリをその場で実行するときに必要になる。

>参照：(not初心者向け)
[Rails開発におけるwebサーバーとアプリケーションサーバーの違い（翻訳）](https://qiita.com/jnchito/items/3884f9a2ccc057f8f3a3)

##Gemfile

Rubyのパッケージマネージャー「Gem」を利用するためのもの。
Railsを勉強すると度々出てくるgem ~はこちらのファイルに記載します。

##Gemfile.lock

Gemのためのファイルだが、Gemfileでパッケージ等がインストールされた際に自動生成される。

>参照：(not初心者向け)
[gemspec と Gemfile と Gemfile.lock との違い．
](https://qiita.com/tnoda_/items/a04e761d595a742fcdca)


##Rake.file

「Rake」と言うrubyのビルドツールで利用する。

>参照：
[Rakeとは](http://www2s.biglobe.ne.jp/~idesaku/sss/tech/rake/)

##README.md

自分で作ったアプリケーションを配布するときのテンプレになるもの。色々内容を追記して配布する。
ちなみに、「md」はマークダウンの略。

>参照：
[わかりやすいREADME.mdを書く
](https://deeeet.com/writing/2014/07/31/readme/)




#2.Railsアプリのフォルダの役割について

Railsアプリケーションを作成する際によく用いるフォルダは「app」フォルダと「config」フォルダと「db」フォルダになります。
今回はそれ以外のフォルダの説明も一緒に見ていきましょう。

##「app」フォルダ

アプリケーション本体。このフォルダの中にアプリケーションで使うファイルを用意し、ファイルを編集し開発を行う。
開発でよく用いる「controllers」フォルダ、「models」フォルダ、「views」フォルダなどがある。

##「bin」フォルダ

これはRailsで使うプログラムを配置しているところ。

>参照：
[binってなに？railsとrakeってなに？](http://song-of-life.hatenablog.com/entry/2017/04/24/224116)



##「config」フォルダ

アプリケーションの設定ファイルをまとめてあるところ。RubyのプログラムやYAMLと言う設定を記述したテキストファイルなどが用意されている。
ルーティングを設定するためのファイル、「routes.rb」もこちらのフォルダ内にある。

##「db」フォルダ

データベース関係のファイルがまとまっているところ。
マイグレーションファイルなどを含む「migrate」フォルダや、「seed」といった最初に組み込まれるデータを記述したものなどが用意されている。


##「lib」フォルダ

ライブラリフォルダ。アプリケーション全体で利用するプログラムを設置する場合に用いられる。

##「log」フォルダ

ログの保管場所。アプリケーションの実行時のログファイルが保存される。


##「public」フォルダ

公開フォルダ。Railsの仕組みとは関係なく、外部からアクセスできるようにしたいものはここに用意する。


##「test」フォルダ

アプリケーションの動作をテストするためのテストプログラムが用意されるところ。

##「temp」フォルダ

キャッシュファイルのように一時的に作成されるファイルはここに用意される。
>参照：
[tempフォルダとは](https://wa3.i-3-i.info/word11509.html)

##「vendor」フォルダ

ソフトウェアベンダーなどが作成するプログラムを設置するための場所。
プラグイン的に機能を拡張するようなときに用いる。


以上です。これからRailsアプリケーションを初めて開発してみようと思う方の参考になれば幸いです。
「Ruby On Rails5超入門」を主に参考にさせていただきました。
MySQLの文字列と照合順序について

# 概要
CREATE文についている`utf8`や`utf8_general_ci`なる文字
なんとなく理解しつつももやっとしていたので調べてメモしました。

# 指定方法
文字列の指定はcharsetで、照合順序についてはcollationで指定する。
指定はDB単位でもテーブル単位でもカラム単位でもできる。
charsetだけ指定すると、collateはデフォルトのものがつく

### ciって？
ci：大文字小文字を区別しない
cs：大文字小文字を区別する
bin：バイナリ、大文字小文字を区別する

[【MySQL】照合順序とは？](https://qiita.com/kazu56/items/6af85ffcf8d3954455ad)
[MySQLのCollationを理解するためにまとめてみた。](http://blog.6vox.com/2014/05/mysqlcollatoin.html
)

# TIPS
### utf8_general_ciを設定しているテーブルで、大文字小文字を区別して検索したい場合
**collationには同じ文字コードのものしか指定できません**

```
select * from user where id collate utf8_bin = 'Tom'
```

### 指定可能なcollationを確認する
下記のコマンドを実行すると一覧が表示されます

```
show collation;
または
show collation like 'utf8%';
```

### mysqlのUTF8の４バイト問題について
charsetにutf8を指定すると４バイトを使用する文字（絵文字など）が格納できない
対応するにはutf8mb4を指定することで対応する

その際に、MySQLのバージョンが5.7.8以下の場合には、別途オプションを指定する必要がある。
詳しくは以下のサイトを参照
[MySQL(InnoDB) で charset を utf8mb4 にする注意点の現在](https://dev.to/seizans/mysqlinnodb--charset--utf8mb4--1451)

# 何を指定しておけばいい？
utf8mb4_general_ciを指定（charsetにutf8mb4でOK）して、
大文字小文字の区別がしたい時だけSELECT文でcollate指定する。
理由；パフォーマンスがいい、大文字小文字区別する必要がある頻度少ない。



# お願い
良かったと思った場合は、「いいね」を教えていただけると励みになります。
最後まで読んでいただきありがとうございました。
ブラウザとサーバー

1. ブラウザで動くプログラム言語は HTML, CSS, JavaScriptなど
2. サーバーで動くプログラム言語は Java, PHP, Rubyなど
3. ブラウザとサーバーとの通信を何度も繰り返すことでブラウザにページが表示される
4. ブラウザからはリクエスト、サーバーからはレスポンス
5. 通信は、テキスト（文字列）を送り合ってるだけ
6. 通信は、文字が機械語に変換され送られる
7. ブラウザとサーバーとの通信形式を取り決めているのがHTTP

>[ウェブカツ！！](https://webukatu.com/?afid=p5lxu1kvh03rayd2ctjsw4e9bgzq8nom)
SOLID原則まとめ

## はじめに
SOLID原則とは SRP, OCP, LSP, ISP, DIPの5つの原則の頭文字を綴ったものです。
これら5つの原則はとても大切なようで、沢山の有名なアーキテクチャを支えているようですね。
それぞれどのような原則なのでしょうか？
せっかくなのでプログラミング初心者である私が頑張って説明してみようと思います。

## おねがい
もし修正・補足・図を提供してくれる方がいらっしゃいましたら、気軽に編集リクエストをお願いできればと思います！

## SRP: 単一責務の原則
単一責務の原則は、「どのモジュールもたったひとつのことだけを行うべき」と誤解されます。
確かにそのような原則も存在します。ひとつの関数はたったひとつのことだけを行うべきというものです。

正しくは、**モジュールはたったひとつのアクターに対して責務を負うべき**です。

ここで言うアクターとは、変更を望む人たちをひとまとめにしたグループの事です。

## OCP: オープンクローズドの原則
オープンクローズドの原則とは、ソフトウェアの構成要素は拡張に対しては開いていなければならず、修正に対しては閉じていなければなりません。
この原則を達成すると、そのソフトウェアの特定の構成要素は、他の構成要素の影響を全く受けなくなります。また、機能追加をする際も既存の構成要素が受ける影響は限りなく少なくなります。

## LSP: リスコフの置換原則
リスコフの置換原則で望まれるのは、下の例で登場するような置換可能な性質だそうです。
クラスAはクラスBを使っていて、そのBをCに置き換えた際にAの振る舞いが変わらない場合、CはBの派生形である。 と言えます。
もうちょっと詳しく知りたい方は[この記事](https://qiita.com/UWControl/items/98671f53120ae47ff93a#%E3%83%AA%E3%82%B9%E3%82%B3%E3%83%95%E3%81%AE%E7%BD%AE%E6%8F%9B%E5%8E%9F%E5%89%87)が割と詳しく解説していたのでどうぞ。

## ISP: インターフェイス分離の原則
インターフェイス分離の原則では、必要としないものとの依存を切り離し、予期せぬトラブルの発生を抑えれます。
例えば以下のようなクラスがあったとします。
User1はこのSampleクラスのmethod1に対して依存しているとします。
しかし、User1のソースコードは実際に使っていないmethod2にも意図せず依存しています。なぜなら、method1とmethod2は同じSampleクラスに対して詳細な実装がされているからです。

```typescript
class Sample {
  method1() {}
  method2() {}
}
```

この問題を解決するには、各操作をインターフェイスに分離すれば良いです。

```typescript
interface User1Sample {
  method1: () => void;
}

interface User2Sample {
  method2: () => void;
}
```

こんな感じですね。
User1の依存をUser1Sampleインターフェイスにしたら、User1はmethod2との意図しない依存関係から開放されました。

## DIP: 依存関係逆転の原則
依存関係逆転の原則は柔軟なシステムの作り方を教えてくれます。
最も柔軟なシステムは、ソースコードの依存関係がインターフェイスだけを参照している場合です。

## さいごに
2018年の今SOLID原則はもう時代遅れなのでしょうか？
数あるGoFのデザインパターンはもう時代遅れなのでしょうか？
いえいえ、そんなはずはありません。なぜなら、今も昔も「順次」「選択」「反復」を組み合わせてコードを書いているのです。
多少シンタックスシュガーでヒューマンフレンドリーになったりした所で、結局は使われている素材は同じです。

## 参考資料
* [クリーンアーキテクチャ](https://www.amazon.co.jp/Clean-Architecture-%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%81%AE%E6%A7%8B%E9%80%A0%E3%81%A8%E8%A8%AD%E8%A8%88-Robert-C-Martin/dp/4048930656/ref=sr_1_1?ie=UTF8&qid=1533801583&sr=8-1&keywords=clean+architecture)