OmniAICreator/Qiita-1.07M huggingface dataset:
Leetcode: Serialize And Deserialize Binary Tree

```ruby

require 'minitest/autorun'
require 'pry'
class SerializeAndDeserializeBinaryTree < Minitest::Test

  def test_run
    expected = [1, 2, 3, nil, nil, 4, 5]
    tree = TreeNode.new(1)
    tree.left = TreeNode.new(2)
    tree.right = TreeNode.new(3)
    tree.right.left = TreeNode.new(4)
    tree.right.right = TreeNode.new(5)

    serialized_tree = "12XX34XX5XX"
    assert_equal(serialized_tree,
                 serialize(tree))
    deserialize(serialized_tree)
  end

  def serialize(root)
    return "X" if root.nil?

    root.val

    left = serialize(root.left)
    right = serialize(root.right)
    root.val.to_s + left.to_s + right.to_s
  end

  def deserialize(serialized_tree)
    nodes_left = serialized_tree.split('')
    deserialize_helpder(nodes_left)
  end

  def deserialize_helpder(nodes_left)
    value_for_node = nodes_left.shift
    return nil if value_for_node == "X"

    new_node = TreeNode.new(value_for_node)
    new_node.left = deserialize_helpder(nodes_left)
    new_node.right = deserialize_helpder(nodes_left)
    new_node
  end

end

class TreeNode
  attr_accessor :val, :left, :right

  def initialize(val)
    @val = val
    @left, @right = nil, nil
  end
end
【Rails】Docker環境下でbinding.pryを使えないとき確認すべきポイント4つ

## はじめに
Docker環境下でこんなシーンに遭遇したことはありませんか？

**「Railsでバグ発生！デバッグしなきゃ！よーし、`binding.pry`しよう！」**

↓

**「うわ、コンソール出ない！！！これじゃ何も出来ない！！！」**


こんな**やるせない気持ち**になった方のために、自分がこれまで詰まった箇所とその解決法を残しておこうと思います。

## 環境
```yaml
OS: macOS Catalina 10.15.3
Ruby: 2.6.5
Rails: 6.0.2.1
Docker: 19.03.5
docker-compose: 1.24.1
```


## 1.`binding.pry`のコンソールが出ない

`docker-compose up`などで**rails server**を立ち上げていて、`binding.pry`を入力した箇所で動作が止まっているのに、

**「コンソールが出ない！どうしよう！」**

という状態を想定しています。

### 解決法

```shell
$docker container ls
```
でRailsアプリのあるコンテナ名を確認します。
※ここでは`rails_app_web_1`とします。
↓

```shell
$ docker attach rails_app_web_1
```
`docker attach`で該当コンテナに`attach`します。
これで、`binding.pry`したときにコンソールが表示されます。

※もし反応がなければ、`Enter`押下するとコンソールが出るかもです。

## 2.せっかくコンソールが出たのに終了の仕方がわからない

多くの場合は`binding.pry`を一回だけして終了、ということはなく、続けて何度かデバッグ作業を行うかと思います。

下手に`Ctrl + C`で終了してしまうと、コンテナが停止してしまうので、立ち上げ直しになってしまってかなり面倒です。

### 解決法

`pry`の画面から終了するなら**`continue`**と入力して**rails server**を通常動作に戻し、`docker attach`を維持するのが便利です。

この状態であれば、次に`binding.pry`したときもスムーズにデバッグ作業が可能です。

※デバッグが終了してコンテナから抜けたい場合、`Ctrl + P + Q`(Macの場合)でコンテナを停止せずに抜けられます。

## 3.pryで日本語入力出来ない
少し外れますが、そもそも`rails console`で`pry`を使っていて、**日本語が入力できない**パターンもあるかもしれません。

### 解決法

```Dockerfile:Dockerfile
ENV LANG C.UTF-8
```

`Dockerfile`に上記のように追記すれば解決できます。

これを忘れると**pry**で**日本語入力**が効きません。

## 4.コンテナがすぐ落ちる、コンソールに文字が入力できない
### 2020/2/6追記

### 解決法

```yaml:docker-compose.yml
web:
  tty: true
  stdin_open: true
```

上記が`docker-compose.yml`のRailsに関係する箇所に書かれているかどうか確認します。（今回は`web`としています。）

- `tty: true` ポート待受などをしていないコンテナを**起動させ続ける**オプション
- `stdin_open: true` **標準入力**出来るようになるオプション

## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

どなたかの参考になれば幸いです:relaxed:
Vagrant+VirtualBox6.1.0+CentOS7な環境でyum updateするとカーネルパニックが発生する（ことがある）件

# はじめに
初めての方もそうでない方もご無沙汰しております。
気がつけば前回の投稿から2年半が経ち、しがないSIerだった私も気付けばフリーランスのエンジニアとしてどうにかそれなりにもっともらしく生きております。

今日はVagrant+VirtualBox6.1.0+CentOS7な環境でyum updateした際に（カーネルのバージョンが上がったことによる）カーネルパニックが発生しちゃった時のお話です。

# 本文
久々にお仕事でWindowsを触ることになり、Vagrant+VirtualBoxでローカル検証用の環境を作成することに。
サクッと`vagrant up`して検証用の環境コンテナを作成して、既に他の人が用意してくれたVagrantFileを使って、`vagrant provision`してミドルウェアのアップデートとかまで済ませて、ここまでは非常にサクサク進んでVagrant便利だなーとか呑気に考えていました。

ところがprovisionした内容を反映させようと思ってコンテナを再起動してからどうもおかしい。
いつまで経ってもコンテナが立ち上がらなかったのでVirtualBoxの子ウィンドウを覗いたらカーネルパニックが発生orz

カーネルパニックのログをよく見るとspec_ctrl_cpu_initうんたらかんたらみたいなメッセージが出ており、「CPU？？？？？？」と思いながらググってみるとVirtualBoxのフォーラムに同様な事例の報告例が数件。
https://forums.virtualbox.org/viewtopic.php?f=3&t=93990

# さっくりまとめると
どうもVirtualBoxの不具合っぽいらしく、VirtualBox6.0.6より新しいバージョンでyum updateなどでカーネルのバージョンを上げた際に、次回起動時にアップデートしたカーネルで起動させようとするとカーネルパニックが発生しちゃう模様。（問題なのはこれが必ず起こるわけではなく、古いCPUのマシンだと同じような手順を踏んでも同じ症状が起こらないことがあるらしい）

回避策ですが、2020/2/5現在の6.0/6.1系の最新Verでも発生するとのことなので、以下のような手順を取るしかなさそう。

1. VirtualBoxを6.0.6にダウングレードする
2. yum updateの際に"--exclude=kernel*"オプションを付けてkernelをアップデートさせないようにする
3. 毎回手動で古いカーネルを選択する

# 最後に
取り急ぎ雑な記事ですみません。そのうちちゃんと推敲してもうちょい読める文章にします。（するとは言っていない）
Excelマクロで画像ファイルのリンクを設定する

JPEG形式の画像ファイル名を入力したExcelシートがある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/60ba77f7-e2f4-d1e5-5afd-40d8f45797df.png)
画像ファイル名をクリックするだけで画像を表示できるよう、実ファイルへのリンクをセルに設定したいところだが、画像ファイルの数が１万件以上あったので、手作業で進めるのは現実的では無かった。

ということで、リンクを自動で設定するマクロを書いてみた。

```vb
Sub リンク設定()
    Dim wb As Workbook, ws As Worksheet, r As Range
    Dim s画像フォルダパス As String, sファイル名 As String
    
    Const 画像フォルダ名 As String = "画像"

    ' 対象Excelファイルのチェック
    Set wb = ActiveWorkbook
    If ThisWorkbook Is wb Then
        MsgBox "Excelファイルが選択されていません", vbCritical
        Exit Sub
    End If
    
    s画像フォルダパス = ThisWorkbook.Path & "\" & 画像フォルダ名

    ' 全シートの
    For Each ws In wb.Sheets
        ' 全セルを調べる
        For Each r In ws.UsedRange
            
            sファイル名 = LCase(Trim(r.Text))
            
            If sファイル名 Like "*.jpg" Then  ' JPEGファイルなら
                If Dir(s画像フォルダパス & "\" & sファイル名) <> "" Then  ' ファイルが存在したら
                    ws.Hyperlinks.Add r, 画像フォルダ名 & "\" & sファイル名  ' 相対パスでリンクを設定
                End If
            End If
        
        Next
    Next
End Sub
```

マクロ本体と、対象のExcelファイルを開き、`[Alt]+[F8]` で実行する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/03cffb2b-d651-a822-9759-cd19c1b0762d.png)

一瞬でリンクに早変わり！ :blush:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236222/086d7cce-78ee-2064-aec2-cf6a29710a64.png)
相対パスでリンクしているので、フォルダ構成を変えない限り、別環境に移しても問題ない。

ちなみに、**Microsoft Windows Image Acquisition Library (WIA)** を使えば、画像ファイルの撮影日時（**Exif**）をVBAから読み取ることも容易だが、今回はExif情報が記録されていない画像だったのでやらなかった。
Macからwindowsへlaravelを移した際の.env→_envになり505エラー　

Macからwindowsへlaravelを移した際、.envファイルが_envになっていたが、.envではないとwebページが505エラーとなるので注意が必要です


#.env作成
```
$ cp .env.example .env
```
でもいいが、シンプルに_env.exampleを複製して.envに名前変更してもOK!

その場合、.envのdatabase名が初期値のままなのでご自身のDBを指定してください。


```
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel //ここをご自身のDB名に変更
DB_USERNAME=root
DB_PASSWORD=
```


.envを作成した状態でページを開いたら鍵が指定されてないと怒られます。
![キー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543413/d3386a25-3f2e-2d47-6a0e-b8db8669f2a2.png)


#鍵指定

```
$ php artisan key:generate
```

その後反映をさせます．（どちらでもいいです。）

```
$ php artisan config:clear
$ php artisan config:cache
```
PUN2 でRoom のリストを作ろうとしたけどOnRoomListUpdate が呼び出されない

# 症状

こんな感じのコードを書いた。
このアプリを起動した状態で、
他のプロセスで同じPhoton のApp ID でPhotonNetwork を使ってルームを生成しているにもかかわらず、
ルームリスト更新のメソッドOnRoomListUpdate が呼び出されない。。。

```
public class NetworkInterface : MonoBehaviourPunCallbacks
{
     // ルームリストに更新があった時
    public override void OnRoomListUpdate(List<RoomInfo> roomList)
    {
        Debug.Log("OnRoomListUpdate");
        _roomList = roomList.Where(s => s.IsOpen).Select(s => RoomToString(s)).ToList(); 
    }
}

```

# 原因

PUN にはAuto Join Lobbyというプロパティがあって、アプリが起動したら勝手にロビーに入ってくれるような機能があったので、その時の感覚でやってたのがまずかった。
どうもPUN2 になってからAuto Join Lobby が廃止されたようで。。。

https://answers.unity.com/questions/1560130/photon-auto-join-lobby.html

によると、"PhotonNetwork.autoJoinLobby is gone. Unless you need a lobby, don't join them." らしい。
ロビーに入らなくても部屋には入れるようです。むしろ必要ないならロビーに入るな、らしい。
一方、

https://stackoverflow.com/questions/52793933/how-can-i-list-rooms-in-unity-pun2

によると、部屋の一覧を取得するには

"The OnRoomListUpdate() method is called only when you've explicitly joined the lobby via PhotonNetwork.JoinLobby()."

つまりロビーに入ってなければならないとのこと。ルームに入れる状態であってもロビーに入ってないと部屋の一覧は分からないらしい。そりゃそうか。
ということで、明示的にロビーに入るようにコードを追加。

```
public class NetworkInterface : MonoBehaviourPunCallbacks
{
    // マスターサーバーへの接続が成功した時に呼ばれるコールバック
    public override void OnConnectedToMaster()
    {
        PhotonNetwork.JoinLobby();
    }

    // ロビーに入った時
    public override void OnJoinedLobby()
    {
        Debug.Log("OnJoinedLobby");
    }

     // ルームリストに更新があった時
    public override void OnRoomListUpdate(List<RoomInfo> roomList)
    {
        Debug.Log("OnRoomListUpdate");
        _roomList = roomList.Where(s => s.IsOpen).Select(s => RoomToString(s)).ToList(); 
    }
}

```

無事OnRoomListUpdate が呼び出されました！
ReasonMLのListでは、Maximum call stack size exceededに気を付けよう

# 現象

ReasonMLにて、`List.map`の使用中に

> Maximum call stack size exceeded

が発生しました。

再帰呼び出しでおなじみのエラーです。

# 原因

僕が書いていたコードに、無限再帰が発生するようなコードが無かったため、

`List.map`の中身を疑ったところ、**内部で再帰呼び出しをしていました**。

ちなみにこちらが、`List.map`の中身です。

```javascript
function map(f, param) {
  if (param) {
    var r = Curry._1(f, param[0]);
    return /* :: */[
            r,
            map(f, param[1])
          ];
  } else {
    return /* [] */0;
  }
}
```

明らかに、`f()`が再帰になっています。

つまり、大量の要素数の`List`を扱う場面では、エラーが発生します。

# 解決

`Array`を使うしかないと思われます。

**`Array`はJavaScriptの配列**なので、問題なく利用できます。

`for`もつかえますが、`List`だとインデックスによるランダムアクセスが遅いので、使わない方が良いです。

# おわり

ということで、

> **ReasonMLの`List`には気をつけよう**

という話でした。
SRE Next 2020 参加メモ

- 2020年1月25日に開催された[SRE Next 2020](https://sre-next.dev/)の参加メモです

# [freee のエンジニアは障害から何を学び、どう改善しているのか？](https://speakerdeck.com/manabusakai/what-do-freee-engineers-learn-and-improve-from-failures)
- 坂井 学さん、freee株式会社


## 障害にどう立ち向かってきたか
- 昔は
  - 障害対応フローはなかった
  - 根本的な対応は後回しになっていた
- 障害のレベル分けをするようになった
  -  すぐ対応しなくていいものが分かるようになる
-  2018の障害
   -  データ不整合から
   -  ここの障害からの学び
-  対応の明確化
   -  誰が何をするか
-  障害対応エリアを作成
   -  情報集約のため

## 学びの広め方
- freeeの文化
  - **失敗して攻める！**
- 失敗.js
  - ポストモーテム
- 割れ窓改善
  - 小さな問題が大きくなる前の活動
- アラートを振り返る
  - 属人的対応の改善

## まとめ
- 対応フローを作る
- **障害は学びの宝庫**
- 障害対応が属人的にならないようにする  

# [SREがセキュアなWebシステムを構築、維持するためにやれることはなにか](https://speakerdeck.com/isaoshimizu/what-can-sre-do-to-build-and-maintain-a-secure-web-system)
- 清水 勲さん、株式会社ミクシィ

## SREとセキュリティ
- SREcon
- 脆弱性のバジェット
  - 対応期限を表す
- レガシーバジェット
  - ライブラリのアップデート
- Google SREのtwitterアカウント
  - [**セキュリティに焦点を当てた本**](https://landing.google.com/sre/resources/foundationsandprinciples/srs-book/)がearly releaseされている
- **障害対応時のマニュアル、チェックリスト的なものがあるとよい**

## セキュリティの取り組み事例

- チームでヒアリングを実施
  - ライブラリの管理
  - アプリ内に秘匿情報を持っていないか
  - TLSのバージョン
  - ログに個人情報がないか
- IaC
  - コードレビューを経てSGやIAMのチェックを行う
- ログ
- ライブラリのアップデート
  - **アップデートも自動化できると最高**
- モニタリング、定期レポート    
- ポストモーテム
  - 小さくても問題が起きたら残すべき
  - 作成者を賞賛する文化

## セキュリティ対策(AWS)
- Well-Architected Framework
  - AWSの人が無料？でチェックしてくれる
- AWSのセキュリティチェックサービスを積極的に使おう
- IAMの管理
- AMIはオフィシャルのものを使用する

## まとめ
- **信頼性だけでなくセキュリティも意識する**
【PHP】配列を文字列(EDI情報)化

#はじめに
EDI情報作成時に使ったロジックなので備忘録として残します。

#サンプルコード

```php
class TestA
{
	public function __construct()
	{
	    $this->test1 = "00";
	    $this->test2 = "          ";
	    $this->test3 = "00";
	    $this->test4 = "          ";
	    $this->test5 = "GG";
	}
	public function getTest1()
  {
      return $this->test1;
  }
  public function setTest1($test1)
  {
      $this->test1 = $$test1;

      return $this;
  }
	・・・(省略)
}


class TestB
{
	$test;
	
	public function build()
	{
		$this->setTest(new TestA());
		$test = $this->getTest();
		
		$testMessage = 'AAA'.'|'.
		$test->getTest1().'|'.
		$test->getTest2().'|'.
		$test->getTest3().'|'.
		$test->getTest4().'|'.
		$test->getTest5();
		var_dump($testMessage);
	}

	public function getTest()
	{
		return $this->test;
	}
	
	public function setTest()
	{
		$this->test = $test;
		
		return $test;
}
```

#var_dumpの結果
```php
"AAA|00|          |00|          |GG"
```
OpenCVを使って複数動画を一発で連結する！

強化学習結果などの沢山の動画を一発で連結したかったので作ってみた．
# シチュエーション
複数の動画が入ったディレクトリあり，その中の動画を全て連結した一つの動画を作成するプログラム．


# ソース

```python
import cv2
import glob

def comb_movie(movie_files,out_path):
    
    # 形式はmp4
    fourcc = cv2.VideoWriter_fourcc('m','p','4','v')

    # 動画情報の取得
    movie = cv2.VideoCapture(movie_files[0])
    fps = movie.get(cv2.CAP_PROP_FPS)
    height = movie.get(cv2.CAP_PROP_FRAME_HEIGHT)
    width = movie.get(cv2.CAP_PROP_FRAME_WIDTH)


    # 出力先のファイルを開く
    out = cv2.VideoWriter(out_path, int(fourcc), fps, (int(width), int(height)))
        
        
    for movies in (movie_files):
        print(movies)
        # 動画ファイルの読み込み，引数はビデオファイルのパス
        movie = cv2.VideoCapture(movies)

        # 正常に動画ファイルを読み込めたか確認
        if movie.isOpened() == True: 
            # read():1コマ分のキャプチャ画像データを読み込む
            ret, frame = movie.read() 
        else:
            ret = False
        
        while ret:
            # 読み込んだフレームを書き込み
            out.write(frame)
            # 次のフレーム読み込み
            ret, frame = movie.read()

# ディレクトリ内の動画をリストで取り出す
files = sorted(glob.glob("./movie_dir/*.mp4"))

# 出力ファイル名
out_path = "movie_out1.mp4"

comb_movie(files,out_path)


```
STマイクロエレクトロニクスより~Lora用1チップマイコンSTM32WLE5が発表~インプレッション

STマイクロエレクトロニクスは、Lora用マイコンSTM32WLE5を発表した。
https://newsroom.st.com/ja/media-center/press-item.html/p4208.html

Lora通信を行うためには、Lora変調をサポートする通信チップ（セムテック社のSX127xやSX126xシリーズ、またはRFM95等）とマイコンを併用する必要があったが
STM32WLE5は1つのSOCの中にLora通信機能を搭載した。
2チップから1チップへと部品点数が減ることにより低消費電力、低価格化並びにモジュールサイズの小型化が行えると考える。

さらに、現在のLoraモジュールは主にSTM32の、STM32F103(RAK811）やSTM32L0（CMWX1ZZABZ-078）を使用しており低性能であった。
STM32WLE5は現在のメインストリームであるCortex-M4を採用することで、CPUの処理についての問題が減少している。（M4で足りない人は、別CPUを使用するので）
特に、RTOSなどを使用することを考えるとメリットが大きいと考える。

##仕様
Arm Cortex-M4　48MHz

ラインナップ3種はメモリサイズの違い
STM32WLE5J8（64KB)
STM32WLE5JB(128KB)
STM32WLE5JC（256KB) 

##パッケージ
UFBGA73 (5x5 mm)

##価格
10K時　3.457ドル（STM32WLE5JCI6）

##ハード部
GPIO：43本(最大）
USBはサポートしない(残念）

##テストボード
NUCLEO-WL55JC1が発表されているが価格等が全くわからない状態である。

##最大の特徴は？
繰り返しになるが、1チップでLora通信が行える事が特徴である。

##課題は？
最新のCortex-M33を採用しなかったのは、セキュリティ面としては痛い
（2020年はセキュリティ元年になると推定されており、順次CortexM33系が標準になると思われる）
ただし、Cortex-M33はまだ時期尚早である事を考えるとCortex-M4で問題ないと思われる。
(2021年にはCortexM33で新チップが出る可能性は捨てきれない）
また、Loraの端末は、直接グローバルネットワークに接続するものではないために、端末にこれ以上の機能が必要なケースは少ない為、Cortex-M4で十分であると私は思う(2020年においては）

##今後の展開？
村田のモジュール（CMWX1ZZABZ-078）においてSigfoxのサポートを行ったことを考えると、STM32WLE5もSigfox用プロトコルスタックの提供が行われるものと考える。

また、CPUのパッケージは、UFBGA73であり、サードパーティーまたは、STマイクロとしてモジュールが提供されることを前提にしていると思われ、2020年の6月ごろには小型かつ低価格、そして高機能なモジュールが提供されるのではないかと思われる。
(データベース)「ER図」の"E"はEntity(エンティティ)の"E"

じゃあ、"Entity（エンティティ）"って？

ということで調べてみると「実体」という意味だそうです。

余計に分からないです。。。

もっとフワッとした感じで調べてみるとデータベースのサービスの中で管理する
必要のある概念（情報）指す。




・・・ようです。

もう少し勉強します。
三角形をオブジェクト表面に張り付ける

#概要
今回、卒業制作で使用する組木細工のアニメーションに使った手法について質問が多かったので記事にします。

![EPbnH9KVUAA_hUl.jfif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/0681a7fc-2446-84a7-06da-8355bcee3b60.jpeg)


硬く書こうと思ったんですが無理なんで適当に行きます。
##組木細工
![wafuu.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/e786e5ea-a5bf-becb-f4ea-f83c86fa2bee.jpeg)
日本の伝統技能で、主に障子や小物に使用される、木を組み合わせて作られる形状。六角形の形が多い。
この画像は去年Mayaで作ったものです。

六角形で出来ているがほとんど正三角形を組み合わせて出来ているので、正三角形で幾何学形状を作成します。
L-system使うと簡単。
#方法
まず、Remesh等を使用して望んだ濃度の三角形を作成します。
その三角形それぞれにこの今作った形状を添わせればいいだけです。仕組みとしてはそれだけ。
![Desktop Screenshot 2020.02.05 - 21.22.22.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/9de9c7a9-73d6-c544-fd95-6d81f4340dd2.png)
じゃあそれをどうやるのか、ポリゴン中心点と方向合わせてコピーする、VDBにしてコピー等色々考えましたが、一番簡単に出来たのは「Point deform」を使用した方法でした。
![Desktop Screenshot 2020.02.05 - 21.23.46.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/147319ae-0e2e-dab4-b741-fba324b4ed8e.png)

point deformはその名の通りポイントをデフォームしてくれるノードです。
変更するオブジェクト、ガイドするオブジェクト、移動先で入力し、ガイドと移動先は同じポリゴン数である必要があります。
![danceTOmy_133.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/6782c6d3-6ec6-5d87-a82b-b255e39b18a1.jpeg)

こんな感じに別で作ったアーマーをアニメーションする人に着せたりすることができます。
ちなみに佐久間先生の授業で知りました感謝。
method studioのMVも多分コレかxyzdist使って作ってるんじゃないかな。重いけど応用が結構効く楽しいノード。

#添わせる
では、まず敷き詰めたい三角形状のオブジェクトを作ります。
今回、僕はこれで行きます。
![Desktop Screenshot 2020.02.05 - 21.19.30.81.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/90ba055a-5875-de61-f586-af399334a3a1.png)

まず、ForEachPrimitivノードでプリミティブ１つ１つに処理が出来るようにします。
次に、それで取り出した３角形をデフォームしたい形状と同じ形にします。
![Desktop Screenshot 2020.02.05 - 21.35.39.86.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/8447dc9d-e630-4b99-8b45-29a0cba3e647.png)

自分はVEXで書きました。
@P=point(1,"P",@ptnum);
で添わせることができます。
これでpoint deformに必要な変更するオブジェクト、ガイド、移動先が出来ました。
これらを繋いで完成です。
ね？簡単でしょう？
![Desktop Screenshot 2020.02.05 - 21.36.32.71.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/18e42723-cbd2-08f7-78fb-f8b83c9db327.png)

#応用
![pig_lightning.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/545265/ad05c0e8-45b2-e38d-8a0d-b479a22aab86.jpeg)
応用でアニメーションタイミング変えるとこんなのが出来る。
コレは評判が良かったり、気が向いたら書きます。

質問や意見があれば遠慮なく。
【Java】BeanValidationでURL形式をチェックする場合HibernateValidatorの@URLは使わない方がよいかもしれない

内容は大体タイトルの通りです。

# 理由
`org.hibernate.validator.internal.constraintvalidators.hv.URLValidator`の実装では「`http:`」と入力しただけの状態でもバリデーションが通ってしまいます。
「入力される内容は`http`/`https`といったプロトコルだけ、最低限ドメインまで入っていてほしい」など、URLはURLでも限られた内容しか入力されない場合は`@Pattern`アノテーションを使って正規表現でチェックした方が良いでしょう。

# 補足
[Maven Repository: org\.hibernate\.validator » hibernate\-validator » 6\.1\.2\.Final](https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator/6.1.2.Final)で検証しました。
Rails、hamlでFontAwesomeを使う

今日、だいぶつまいたので、メモ程度に書いておきます。

①ハッシュロケットをシンボル型に直す。

ハッシュロケットは時代遅れになっているようで、 取り残されないようにシンボル型に書き換えます。  

基本形
ハッシュロケット
:rocket => "rocket"

シンボル型
hash: "hash"

 書き換えてみる
ハッシュロケット
 %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/

シンボル型
%meta{content: "text/html; charset=UTF-8", "http-equiv": "Content-Type"}/

②link_toでFontAwesomeを表示

a(href)を
= link_to "#" doに変更


= link_to new_group_path do  
= fa_icon 'edit'
claspを使ったGASコーディングローカル環境構築


## インストール

```
npm i @google/clasp -g
```

## 認証
### コンソールから
```
clasp login
```

### ダッシュボードでGoogle Apps Script APIを許可
[Apps Script – Google Apps Script](https://script.google.com/u/0/home/usersettings)

## プロジェクトの作成
```
clasp create "ClaspSample"
```

ダッシュボードを見るとClaspSampleができていることが確認できます。

## ローカルへのデフォルトスクリプト(Code.gs)の反映
```
clasp pull
```
自分の場合はこれだけではできず、一度ダッシュボードからプロジェクトを開いてから実行するとローカルにCode.jsができた。

## ローカルの変更を反映させる
Code.jsを以下のように編集して見る。  

```
function myFunction() {
  Logger.log("Hello World!");
}
```
以下のコマンドを実行する。  

```
clasp push
```
ダッシュボードでプロジェクトを開くと変更されていることが確認できる。

## 既存プロジェクトをローカルへ反映
```
clasp clone <script id>
```
Script id はスクリプトをブラウザで開いた時のurlを参考にする
![9A309747-7873-437A-A824-51F5FD3AAACEのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149698/7f24e0e3-aad5-8485-0ac1-3d5a14d6b8ff.png)



# 参考
[Google Apps Script のモダンな開発環境を求めて](https://kenchan0130.github.io/development/2018/12/03/1.html)
Google OAuth 2.0 認証を使ったGoogle Sign-Inの実装（サーバー編）

#概要

今回はこちらの記事の続きです。
[Google OAuth 2.0 認証を使ったGoogle Sign-Inの実装（JS編）](https://qiita.com/biy0ganba/items/6c3a886759254e0e942c)
クライアントサイドでログインしてバックエンドサーバーで認証といった感じでやります。

前回の記事でユーザー情報などをレスポンスで取得することができました。
ただこれをこのままサーバーサイドに送ったりするのは危険です。
例えば、ユーザーIDをサーバーに送信する際にユーザーを偽装できちゃったりします。。

なので、その代わりに検証可能なIDトークンを使用して、サーバー側でサインインしているユーザー情報を安全に取得します。

さっそく実装していきましょう。
#フロントサイドの実装

まずJSの部分を書きかえます。

```javascript:JavaScript

function onSignIn(googleUser) {
  var id_token = googleUser.getAuthResponse().id_token; // IDトークンを取得
  // IDトークンをサーバー側に送る処理
}

```

ここのサーバー側に送る処理はAjax使ったり、hidden属性で送ったりいろいろなやり方があると思いますが、
今回はAjaxのXMLHttpRequestを使用してHTTPリクエストを発行する方法でサーバーとの通信をやって来ます。

先ほどの処理に追加して

```javascript:javaScript

var req = new XMLHttpRequest();
req.open('POST', '[URL]’);
req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
req.onload = function() {
req.send('idtoken=' + id_token);

```

こんな感じでサーバー側に送信しましょう。
***[URL]***の部分にはサーバー側のURLを入れましょう。

#サーバー側の実装

今回は、JavaのSpring bootを使って実装していきます。

まずは依存関係の追加です。

```gradle:build.gradle

dependencies {

implementation("com.google.api-client:google-api-client:1.30.5")

}

```
Googleクライアントライブラリを使えば簡単にIDトークンの検証ができます。


```java:Java

 GoogleIdTokenVerifier verifier =
        new GoogleIdTokenVerifier.Builder(
                new NetHttpTransport(), JacksonFactory.getDefaultInstance())
            .setAudience(Collections.singletonList("YOUR_CLIENT_ID.apps.googleusercontent.com"))
            .build();

 var idtokenStriing = getIdToken(); // 取得したIDトークン

 GoogleIdToken idToken = verifier.verify(idTokenString); // IDトークン検証
 

```
YOUR_CLIENT_IDには自分のクライアントIDを入れてください。

もしGoogleクライアントライブラリを使わない場合はGoogleの公開鍵（PEM形式）を使用して、トークンの署名を検証する方法もありますが、GoogleでもGoogleクライアントライブラリを使って検証することを推奨しているので使いましょう。

あとはユーザー情報を取得するだけです。

```java:Java

  Payload payload = idToken.getPayload();

  String userId = payload.getSubject(); // ユーザーID
  String email = payload.getEmail(); // ユーザーメールアドレス
  String name = (String) payload.get("name"); // ユーザー名
  String pictureUrl = (String) payload.get("picture"); // ユーザープロフィール画像
  
```

こんな感じで取得できちゃいます。


#まとめ

今はいろんなサイトでOAuth認証使ってるところが増えてますね。
今回はGoogleですがFacebookやAppleなどのOAuth認証もまたあげていこうと思います。
Zephyr > debug > double型をprintk()で出力する: sprintf("%f")を使う [CONFIG_NEWLIB_LIBC_FLOAT_PRINTF] | double型使用時の注意点 > loggingサブシステムはdouble型変数をサポートしない

```txt:動作環境　
Ubuntu 18.04 LTS
ボード: STM32L476 Nucleo_64 (以下、STM32L476)
Zephyr 2.1.0-rc1
放射温度計センサー: MLX90632 (CLICK-IRThermo)
ロジック確認: Analog Discovery 2 (AD2)
```

### 状況

- double型の値をprintk()したい
- printk("%f")は機能しない
    - "%f"という文字が表示される
- そうだsprintf("%f")で文字列にしてからprintk("%s")しよう
- sprintf("%f")が機能しない

教えておじいさん〜。教えておじいさん〜。

SlackのZephyrプロジェクトで聞いたら４分で回答が来ました。
ありがとうございます。

### 対応 > CONFIG_NEWLIB_LIBC_FLOAT_PRINTF

sprintf("%s")でdouble型を渡すにはprj.confに以下を追加する。

```
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
```

- https://docs.zephyrproject.org/latest/reference/kconfig/CONFIG_NEWLIB_LIBC_FLOAT_PRINTF.html

```c
	char szbuf[20];
	sprintf(szbuf, "%f", (float)res);
	printk("2020-02-05: %s\n", szbuf);
```

以下のようにMLX90632の係数を表示できた。

```
2020-02-05: 23734.050781
```

### CONFIG_NEWLIB_LIBC_FLOAT_PRINTFの注意点

Slackで別の人に注意点を教えていただいた。

(意訳)
> printsとdoubleには注意が必要。loggingサブシステムはdouble型変数をサポートしない。

- https://docs.zephyrproject.org/latest/reference/logging/index.html#limitations
MacのPostfixのログが出ない。見れない。見たい。

# Postfixのログが出なかったので調べました

## 以下のコマンドを打つと、ログが閲覧できます。

```
/usr/bin/log stream --predicate  '(process == "smtpd") || (process == "postfix") || (process == "smtp")' --info
```

logってコマンドでいいんですが、自分がlogをエイリアスで使っているので絶対パス
CentOSの6や7でDrushを導入してみるテスト

drushを動かせる環境を作ってみたいと思い、動作する環境を構築してみました
以下メモ書きです

1.「composer.phar」入手

```
$ curl -sS https://getcomposer.org/installer | php
$ mkdir ~/.composer
$ mv ./composer.phar ~/.composer/
```

2.composerの環境変数の登録(＝PATHを通す)

```
$ vi ~/.bash_profile 
最下行に下記追加
alias composer='php $HOME//.composer/composer.phar'
```

3.composerの動作確認

```
$ composer help
```


4.composerでdrushをインストール

```
$ composer global require drush/drush:dev-master
```

5.composerのパッケージ関連のupdate

```
$ composer global update
```

6.「.bash_profile」に「$HOME/.composer/vendor/bin」以下の環境変数を登録する(＝PATHを通す)

```
vi ~/.bash_profile
以下を「.bash_profile」の最下行に追加

export PATH="$HOME/.composer/vendor/bin:$PATH"
```

7.drushの動作確認
一旦ログアウトの後、再接続する
ログイン後、drushのバージョン確認

```
$ drush --version
Drush Commandline Tool 10.2.1-dev
```

2020年2月現在のdrushの最新版は10となっていました

ご参考まで
Gmail経由で、Macでメールを送る

# Macでメールが送りたい

とどけ！この想い！

## 前提

20202年2月5日

MacOS Mojave
10.14.06

postfixはインストールしておいてね。


## 設定ファイルの変更

設定ファイルの末尾に以下を入れる


```/etc/postfix/main.cf
smtp_tls_security_level        = may
smtp_sasl_auth_enable          = yes
smtp_sasl_password_maps        = hash:/etc/postfix/sasl_passwd
smtp_sasl_mechanism_filter     = digest-md5 cram-md login plain
smtp_sasl_tls_security_options = noanonymous
```

## Gmail、アプリで使用するパスワードを作成する

[このGoogleアカウントのセキュリティページにアクセス](https://myaccount.google.com/security)

<img width="874" alt="Google_アカウント.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/f899c9f5-686d-b15f-a49d-f9f434f5a708.png">

アプリのパスワードから、メールとMacを選択して生成を押す

<img width="685" alt="アプリ_パスワード.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/23f1e79d-64de-3a78-5f0b-affea350a443.png">

<img width="650" alt="アプリ_パスワード.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/41a7ed8f-c697-6529-c0da-e948ed862f92.png">

上で出来たパスワードをメモるか、覚えてください

## パスワードマップを作成

mymailaccount@gmail.com
は、自分のメールアドレスを入れてね。

xxxxpasswordは、Gmailのページで作成したパスワードを入れてね。
/etc/postfix/sasl_passwdを作成する

```
smtp.gmail.com:587      mymailaccount@gmail.com:xxxxpassword
```

```
sudo postmap /etc/postfix/sasl_passwd
```

## 権限などを設定する

```
sudo chmod 600 /etc/postfix/sasl_passwd
```


## 再起動

```
sudo postfix check
sudo postfix stop
sudo postfix start
```

## メールの送信確認

```
echo test mail from Mac! | mail -s test myaccount@gmail.com
```

届いたかな！
DualシステムとDuplexシステムの覚え方

情報処理試験で良くみますがいつもどっちがどっちだっけ？となっていたので調べてみました

## Dual

[2 の、2 を表わす、二者の、二重の、二つの部分から成る、二元的な、両数の](https://ejje.weblio.jp/content/dual)

[having two parts or aspects](https://www.oxfordlearnersdictionaries.com/definition/english/dual?q=dual
)
## Duplex

[重複の、二連の、二重の、部屋の中で上下 2 階になっている、複式の](https://ejje.weblio.jp/content/duplex
)

[(of a flat) with rooms on two floors](https://www.oxfordlearnersdictionaries.com/definition/english/duplex_1?q=duplex)

なるほど
Dualは二重なんだけど、
Duplexは二階建てという感じなんだな

## 語源

[du - al](https://eigogen.com/word/dual/)

[du - plex](https://eigogen.com/?s=duplex)

### du

[ラテン語の２ L.duo=two(2)](https://eigogen.com/gogen/146/)

Duの部分はdualもduplexも一緒で

### al

は[名詞、形容詞、副詞にする接尾語](http://gogengo.me/roots/334)


### plex

は[ラテン語でL.plicare = fold(重ねる)](https://eigogen.com/gogen/412/)


## 理解したこと

Dualシステムはシステムを一緒に動かし、結果を比較するなど高い信頼性が得られる
また、一つのシステムが落ちても他方のシステムが処理を続行できる

Duplexシステムはシステムが折り重なっていて、一つのシステムが動いているが、障害発生時のために、
ホットスタンバイ、ウォームスタンバイ、コールドスタンバイという形でもう片方のシステムが待機してる

もう、大丈夫。
Elasticsearchのトライアルライセンスを有効するコマンド


以下コマンドで有効化ができます。
＃localhostの値は環境に応じて変更してください

```
curl -XPOST  'http://localhost:9200/_license/start_trial?acknowledge=true'
```


以下コマンドで有効期限が確認できます。

```
curl -XGET  'http://localhost:9200/_license/' 
{
  "license" : {
    "status" : "active",
    "uid" : "e08feb53-b220-40a7-8275-db53e8f44664",
    "type" : "trial",
    "issue_date" : "2020-02-06T10:35:16.362Z",
    "issue_date_in_millis" : 1580985316362,
    "expiry_date" : "2020-03-07T10:35:16.362Z",
    "expiry_date_in_millis" : 1583577316362,
    "max_nodes" : 1000,
    "issued_to" : "sb_hitachi",
    "issuer" : "elasticsearch",
    "start_date_in_millis" : -1
  }
}
```
ABC134-Dから学んだ計算量の求め方

## 問題
https://atcoder.jp/contests/abc134/tasks/abc134_d

難しかった。というか問題文を読むことが難しかった。


## 今回の学び
1. 任意の整数＝全ての整数のようなニュアンス
2. 後ろから順に解いていくと一意に確定する
3. $O(\sum(N/i)) = O(NlogN)$ 

## 計算量の求め方

発生した疑問：$O(\sum(N/i))$って間に合うの？

今回の問題では任意のiにおいて$N/i$を求める必要がある。これを考えるとき、積分を行うと良い。$\int(1/N) = logN$であることから最悪でもlogNで押さえつけることができる。

## まとめ
1. 数学的な文章になれる
2. 配列を前もしくは後ろから判定するのはよくあるし気づかなければいけない
3. **積分を考えると面積から計算時間を求めることができる。**

## コード
```python
N = int(input())
a = list(map(int, input().split()))
a.insert(0, 0)
b = [0] * N
M = 0
for i in range(N, 0, -1):
    ball = 0
    for j in range(i + i, N + 1, i):
        ball ^= b[j - 1]
    b[i - 1] = ball ^ a[i]
M = sum(b)
print(M)
for i in range(N):
    if b[i]:
        print(i + 1, end = ' ')

```
PowerShellで関数を実行したら、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されません。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行してください。となった時の対応方法

- 環境
    - Windows10 Pro 64bit バージョン1803
    - PowerShell 5.1.17134.858

# 事象 : 初めて関数を書いて実行したら怒られた
```powershell:hoge.ps1
get-sheet-name

function get-sheet-name() {
    # 処理...
}
```

```bash
> ./hoge.ps1
get-sheet-name : 用語 'get-sheet-name' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されません。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行してください。
発生場所 C:\path\to\hoge.ps1:1 文字:1     get-sheet-name
+     ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (get-sheet-name:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException
```

# 原因 : 呼び出しより前に関数を定義していないから
あ・・・そうなんだ・・・

## 対応 : 呼び出すより前に関数を定義する
```powershell:hoge.ps1
function get-sheet-name() {
    # 処理...
}

get-sheet-name
```

```bash
> ./hoge.ps1
動いた!
```
Prettierとstylelintで保存するときに自動整形する

#概要
CSSの記述をPrettierとstylelintで保存するときに自動整形できるようにします。
最小限の設定です。
プロパティの並びはアルファベット順にします。

#手順
##インストールと設定ファイル作成

1. `npm i -D stylelint stylelint-config-recommended`でインストール
2. `npm i -D prettier stylelint-config-prettier@7.0.0 stylelint-prettier `でインストール<br>バージョンを指定しないとstylelint-plusとの組み合わせ時に動作しないため<br>[参考](https://blog.isonishi.com/2019/12/20/npm-scripts-3-1/)
3. `npm i -D stylelint-order stylelint-config-recess-order`でインストール
2. ルートディレクトリに`.stylelintrc.json`ファイルを作成し、中身を記述↓

```json:.stylelintrc.json
{
    "extends": [
        "stylelint-config-recommended",
        "stylelint-config-recess-order",
        "stylelint-prettier/recommended"
    ]
}
```

##package.jsonにscriptを追加

```json:package.json
"scripts": {
    "lint:css": "stylelint --fix ./**/*.css"
}
```


##VScodeにExtensionを追加

1. インストールするExtension`stylelint-plus`
2. setting.jsonを開く
3. 下記を追加

```json:setting.json
{
  "css.validate": false,
  "scss.validate": false,
  "stylelint.autoFixOnSave": true,
  "[css]": {
    "editor.formatOnSave": false
  },
  "[scss]": {
    "editor.formatOnSave": false
  }
}
```

これで保存時に自動で整形されます。
[エラー] [Spring security]There was an unexpected error (type=Forbidden, status=403). Forbidden

#起きたこと
Spring-securityを利用して認証機能を実装。
ログイン処理成功後、検索フォームのsubmitを押下した際に表題のエラーが発生。

#原因
```
<form action="/find">
```

Thymleafでtemplateを作成していたが、検索フォームのアクションの指定を

```
<form th:action="@{/find}">
```

に変更することで遷移可能となった。

#終わりに
権限が無いってエラーだったのでconfigやController、Serviceを中心にデバッグしてたけどまさかのHTML内での出来事だったと・・・
なかなか気がつけなかったので備忘録として
Bot開発（Node.js）のDBアクセスライブラリは knex がオススメ！

Bot開発でNode.jsを使うことが多く、DBアクセスがある要件で `pg` などで素のクエリを書いていて辛いなーと感じている時に、 `knex` に出会ったので紹介します。

公式ドキュメント http://knexjs.org/
GitHub https://github.com/knex/knex

# 使い方
インストール

```terminal
$ npm install --save knex pg
```

knex初期設定

```terminal
$ knex init
```

すると、以下のファイルが自動生成されます。

```javascript:knexfile.js
// Update with your config settings.

module.exports = {

  development: {
    client: 'postgresql',
    connection: {
      database: 'linebot-dev',
      user:     'zyyx-kubo',
      password: ''
    },
    pool: {
      min: 2,
      max: 10
    },
    migrations: {
      directory:'./db/migrations',
      tableName: 'knex_migrations'
    }
  },

  staging: {
    client: 'postgresql',
    connection: {
      database: 'my_db',
      user:     'username',
      password: 'password'
    },
    pool: {
      min: 2,
      max: 10
    },
    migrations: {
      directory:'./db/migrations',
      tableName: 'knex_migrations'
    }
  },

  production: {
    client: 'postgresql',
    connection: {
      database: 'my_db',
      user:     'username',
      password: 'password'
    },
    pool: {
      min: 2,
      max: 10
    },
    migrations: {
      directory:'./db/migrations',
      tableName: 'knex_migrations'
    }
  }

};
```

マイグレーションファイルの作成

```terminal
$ knex migrate:make create_user
Using environment: development
Created Migration: ./db/migrations/20190214205707_create_user.js
```

## マイグレーション
### 実行

```terminal
$ knex migrate:latest
```

### ロールバック
```
$ knex migrate:rollback
```

## シード
### ファイル作成

```terminal
$ knex seed:make test_users
Using environment: development
Created seed file: ./db/seeds/test_users.js
```

### 実行

```terminal
$ knex seed:run
```

## Herokuでの実行

```terminal
$ heroku run knex migrate:latest --app app-name
```
RSpecの導入【備忘録】

#準備
###Gemfileを編集
RSpecを使用するアプリのGemfileを以下の通りに編集する
・「group :development, :test do 〜 end」に「gem 'rspec-rails'」を追加
・「group :development do」に「gem 'web-console'」を追加

```
group :development, :test do
  gem 'rspec-rails'
end

group :development do
  gem 'web-console'
end
```
###インストール
・ターミナルで「bundle install」を実行

```
# RSpecを使用するアプリのディレクトリへ移動
cd ~/projects/sample-app

# 「bundle install」を実行
$ bundle install
```

#RSpecの設定
###RSpec用の設定ファイルを作成
・下記のコマンドを実行

```
$ rails g rspec:install
```
###.rspecを編集
・下記を追加

```
--format documentation
```

#RSpecのディレクトリ
・specフォルダ以下にモデルやコントローラーごとにフォルダを作成し、specファイルを管理する。

sample-app
└ spec
　└ models
　　└ specファイル
　└ controllers
　　└ specファイル　　
##specファイルの命名規則
**対応するクラス名_spec.rb**
(例)post_spec.rb

#テスト実行
・ターミナルで以下のコメントを実行

```
bundle exec rspec
```
3章.LiDARを動かす

## 本章のながれ
　本章ではLiDARの概要について触れた後、実際に使ってみるところまでを記載致します。

## 実施環境
OS  　　:　Ubuntu16.04LTS. , Ubuntu18.04LTS.
ROS環境 ：　kinetic    , melodic
対象PC　：LattepandaAlphaによる動作（Intel Core m3-7y30 程度の動作）を想定

## 1. LiDARとは
　LiDARとは“Light Detection and Ranging、Laser Imaging Detection and Ranging、「光検出と測距」ないし「レーザー画像検出と測距」光を用いたリモートセンシング技術の一つで、レーザーをパルス状に照射し、その散乱光による反射時間(発光後に反射光を検出するまでの時間)から距離を算出する技術です。　以前までは価格が高く、個人として購入することが難しいセンサでしたが、$100程度で購入できるLiDARセンサも出てきており、その中でも今回ご紹介するRPLiDARは取り扱いも簡単なうえ、価格も比較的安く個人でも何とか購入できるセンサとなります。更にライブラリも多くあるため安心して使いこなせるLiDARセンサとなっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212663/a67c4d2f-a89c-f7be-d89e-039976c7810d.png)
　SLAMTECより参照
## 2. LiDARを使ってみよう
RPILDARをROSで動かす際、以下のページがとても参考になりました。初めてROSで動かしたのもこのノードからでした！安心して動かせるので頼もしいです！
[空飛ぶロボットのつくりかた　RPLIDAR A1をROSで動かしてみる](http://robonchu.hatenablog.com/entry/2018/09/15/092733)
ここの内容とほぼ同じですが、以下のコマンドを一行ずつ実行していけば、初めてROSをインストールして使おうとしている人でも動かせるはずです。

```bash:ROS用RPLIDARのインストール方法
cd ~/catkin_ws/src
git clone https://github.com/Slamtec/rplidar_ros.git
cd ..
catkin_make
source devel/setup.bash
sudo chmod 666 /dev/ttyUSB0
roslaunch rplidar_ros view_rplidar.launch
```

## 3. LiDARを使う時、向きってあるの？
　ここで一つ、、、$\huge{後悔しないRPLIDAR　A1の取り付け方向}$についてお教えします。
**この向きです！！**
![LIDAR取り付け方向.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212663/6e31e029-c86c-75c6-a41a-02cff2f8bc17.png)

なぜこの向きが正しいかと言うと、こちらにも書いてある通り、X方向が進行方向となます。
![屏幕快照-2018-11-08-上午10.19.47-768x529.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212663/822db89b-2e78-9c01-8c3e-b03f5523574b.png)
　　　　　　　　　　　　SLAMTECより参照

https://blog.seeedstudio.com/blog/2018/11/09/rplidar-and-ros-the-best-way-to-learn-robot-and-slam/

これを逆方向にして取り付けると、**自動航行を行う際にドハマりする**場合があります。

もう一度言います。
$\huge{自動航行を行う際にドハマりする（泣;;）}$場合があります。
もちろん、逆に取り付けてしまった場合でも対処方法(static_transform_publisherでパラメータを変える方法)はありますので、ご安心下さい。SLAMについては今後の章で書かせてもらいますので、お楽しみに。

## 次は4章.urdfを作成する
次回はurdfを作成してみます。自分で作ったロボットが、rviz上で表示されモチベーションが一気に上がってきます！こうご期待！
[4章.urdfを作成する](https://qiita.com/motoms/items/a67b272313d7737a6b43)

## 今までの道のり
[作って分かった「ROSを使う前のロボットと、ROSを使った後のロボットの変化」](https://qiita.com/motom0509/items/1e1b6866eba52dcdf90b)

目次： [ROSを使った自動航行ロボットをつくるまでの道のり　ー序章　概要ー](https://qiita.com/motom0509/items/ea297fffbd6865b85bdb)
 　　 　[1章.ロボットのROS対応](https://qiita.com/motom0509/items/c81d85b2e7967a780eb9)
 前章 ：[2章.ロボットを操作する](https://qiita.com/motom0509/items/e5b3310c248b23f36ef7)
嘘つき族と正直族の問題

[嘘つき族と正直族の問題](https://teratail.com/questions/239646)を`Python`で解いてみた。
答え合わせはしていない。`Python`楽。

```Python
import itertools

# 嘘つきなら反対を答える
def ans( person, liars, b):
    if person in liars:
        b = not b
    return b

def print_res(liars, cards):
    print('-----')
    for i in range(4):
        print( '{}:{} {}'.format('ABCD'[i], '嘘' if i in liars else '正', cards[i]))

# 嘘つきな人 と カードの組み合わせ
liars_g = itertools.combinations(list(range(4)),2) # 嘘つきな人
cards_g = itertools.permutations(list(range(1,5))) # カード
for liars, cards in itertools.product(liars_g,cards_g):
    # Ａさん：私のカードは，偶数です．
    # Ｂさん：私のカードは，３か４のどちらかです．
    # Ｃさん：Ｂさんは，正直族です．
    # Ｄさん：私のカードは，１です．
    if  ans( 0, liars, cards[0] % 2 == 0) and \
        ans( 1, liars, cards[1] in (3,4)) and \
        ans( 2, liars, 1 not in liars) and \
        ans( 3, liars, cards[3] == 1):
        print_res(liars, cards)
```

答え

```
-----
A:嘘 1
B:正 3
C:正 2
D:嘘 4
-----
A:嘘 1
B:正 3
C:正 4
D:嘘 2
-----
A:嘘 1
B:正 4
C:正 2
D:嘘 3
-----
A:嘘 1
B:正 4
C:正 3
D:嘘 2
-----
A:嘘 3
B:正 4
C:正 1
D:嘘 2
-----
A:正 4
B:嘘 2
C:嘘 3
D:正 1
```
【エラー】ssh: Could not resolve hostname github: nodename nor servname provided, or not known fatal: Could not read from remote repository.

# 発生したエラー

```shell

 % git clone https://github.com/xxx/yyy.git
```

を実行すると以下のエラーメッセージが

```shell

Cloning into 'yyy'...
ssh: Could not resolve hostname github: nodename nor servname provided, or not known
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```

# 解決策

.gitconfigが悪さをしていそうなので削除


```shell

ファイルの存在確認
 % ls -la ~/ | grep git
-rw-r--r--   1 mo    staff        84  2  4 08:07 .gitconfig

発見したので削除
% rm ~/.gitconfig
```

# 参考
* [カスタマイズはほどほどにしましょう - Aikの技術日記](https://aik0aaat.hatenadiary.jp/entry/2018/07/11/003419)
Kaggle:Introduction to Manual Feature Engineering その2

https://www.kaggle.com/willkoehrsen/introduction-to-manual-feature-engineering

列(Series）がどのデータタイプかをざっくり知りたい時は

```
df.dtypes
```

よく忘れる。

agg_funcやcount_categoricalなど
なんでも関数にしていくというのは、見やすさでも再利用という点でも優れていると思うが、特徴量エンジニアリングで果たしてそこまで関数化する必要があるかというとまだ実感はできていない。が、これもロングランでcompetitionを戦っていくのは必須なんだろうという想像はつく。


pandaでgroupbyしてaggrigationを"mean"に指定すると、どのレベルで平均を取っているのがイマイチ掴みづらい。。
が、途中でcategoricalのaggrigationをしているところで、

```
categorical[categorical['SK_ID_CURR'] == 100001]
```

と7つ行があり、

```
categorical.groupby('SK_ID_CURR').agg(['sum', "count",'mean'])
```
で、SK_ID_CURRが100001のデータはcountが7なのだから、
sumが3の列はmeanが0.428571、sumが7の列はmean=1という至極簡単なことであった。


> The correlations between variables can show if we have collinear variables, that is, variables that are highly correlated with one another.

> Often, we want to remove one in a pair of collinear variables because having both variables would be redundant. 

ここらへんは何度もやったからなんとなく分かる。

![download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11563/a605479a-238d-2754-975f-f5af5d6d4853.png)

targetでない変数同士のcorrelationsが高かったら冗長だから1個にしといたら、という話。多い分には学習が捗るような気もするのだが、そこはインプットが少ないうちは実際にfitさせて確かめられるのだ。
100個も200個もcorrelationsが相互に高いものがあったりしたら、確かにそれは「次元の呪い」的なものなのかもしれないが。

とはいいつつも

> As the number of variables increases, the number of datapoints needed to learn the relationship between these variables and the target value increases exponentially.

などともある。datapointsとは・・？


欠損値を計算して今回は90%以上データがない場合はその特徴を消そう、ということになった。

続きは

- Calculate Information for Testing Data

から。
PySparkDataFrameからPandasDataFrameへの変換でメモリエラーになるときの対処法

# はじめに

SparkのDataFrameで作ったデータをPythonの各モジュールで使いたい時、`toPandas()`メソッドを利用してPandasのDataFrameに変換するが、その際にメモリエラーが起きる場合がしばしばある。
メモリに載せられるように試行錯誤した中で、有効そうなものをまとめた。

もっといい手段がありそうなので、ご存じの方は是非教えてください！

# やり方

## daskを利用して変換する

sparkによる変換は、`spark.driver.memory`や`spark.driver.maxResultSize`の影響を受けるが、daskの場合はそれがないため、エラーを回避しやすい。

```python:daskを利用した変換
import dask.dataframe as dd

df.write.parquet(parquet_path)
dask_df = dd.read_parquet(parquet_path)
pandas_df = dask_df.compute()
```

## データ型を変更する

バイト数を削減するように、変数のデータ型を変更する。

※勿論、バイト数を削減することで、その後の演算の精度は損なわれる

```python:データ型を変更
# 例えば、int32型(4バイト)をint8型(1バイト)へ変換する
dask_df = dask_dt.astype({k: 'int8' for k in dask_df.dtypes[dask_df.dtypes == 'int32'].index})
```
【SAPUI5】ライブラリのmessagebundleをアプリケーションで使う方法

## はじめに
[【SAPUI5】i18nをライブラリ化する](https://qiita.com/tami/items/76c798d5190b291ada05)の記事で、ライブラリのi18nファイルを別のアプリに取り込む方法を紹介しました。もっといい方法があることがわかったので書きたいと思います。

## messagebundleとは
ライブラリ単位で持っている、翻訳可能なテキストのファイルです。書き方はi18nと同じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/2fb3294f-e99c-bd87-15d0-b0928428442b.png)

## messagebundleのテキストをアプリケーションから呼ぶには
### コントローラーから呼ぶ方法
コントローラーの中だけで使いたい場合は、この方法が簡単です。

`sap.ui.getCore().getLibraryResourceBundle("ライブラリ名（フルパス）").getText("テキストID")`
参考：[APIリファレンス](https://sapui5.hana.ondemand.com/#/api/sap.ui.core.Core%23methods/getLibraryResourceBundle)

```javascript
		onSayHello: function () {
			//ライブラリからテキストを取得
			var sText = sap.ui.getCore().getLibraryResourceBundle("demo.library.zdemolibrary").getText("SAY_HELLO");
			MessageBox.alert(sText);
		}
```
結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/33008f71-0453-d202-780a-d754f81b25a6.png)

### ビューから呼ぶ方法
ビューから呼ぶ方法は2つ考えられます。

1. [【SAPUI5】i18nをライブラリ化する](https://qiita.com/tami/items/76c798d5190b291ada05)と同じように、アプリケーション本体のi18nとマージする
2. 独立したリソースモデルを作る

####アプリケーション本体のi18nとマージする
Component.jsで以下のように書きます。

```javascript
			//ライブラリのリソースを取り込み
			var oBundle = sap.ui.getCore().getLibraryResourceBundle("demo.library.zdemolibrary");
			this.getModel("i18n").enhance(oBundle);
```
ビューは以下のようになります。

```xml
<Text text="{i18n>SAY_HELLO}"/>	
```

#### 独立したリソースモデルを作る
manifest.jsonにリソースモデルを追加します。以下では、"msg"という名前で追加しています。
こうすると、アプリケーションのi18nとライブラリで同じテキストIDを使っても問題ありません。

```json
		"models": {
			"i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "demo.Train_17_UseLibraryText.i18n.i18n"
				}
			},
			"msg": {
				"type": "sap.ui.model.resource.ResourceModel",
				"settings": {
					"bundleName": "demo.library.zdemolibrary.messagebundle"
				}				
			}
```

ビューは以下のようになります。

```xml
<Text text="{msg>SAY_HELLO}"/>
```
CrowiからGrowi移行時にcreateIndex errorが出たとき

# 背景
社内運用Wikiを[Crowi](https://site.crowi.wiki/)から[Growi](https://docs.growi.org/ja/guide/)へ移行するため、[こちら](https://docs.growi.org/ja/admin-guide/migration-guide/from-bakudankun-crowi.html#%E6%A6%82%E8%A6%81)を参考に作業を進めていた。

# 問題
DBのデータ移行のセクションで、`mongorestore`コマンドを実行すると、以下のようなエラー文が出て、データ移行がうまくいかなかった。

>  Failed: growi.users: error creating indexes for growi.users: createIndex error: Index with name: username_1 already exists with different options

# 対処法
`mongorestore`コマンドのオプションに`--noIndexRestore`を付けて実行するとうまくいった。

# 参考URL
+ [bakudankun/crowi からの移行](https://docs.growi.org/ja/admin-guide/migration-guide/from-bakudankun-crowi.html#%E6%A6%82%E8%A6%81)
+ [Mongo restore problem with indexes](https://forums.meteor.com/t/mongo-restore-problem-with-indexes/14514)
初心者によるプログラミング学習ログ 230日目

100日チャレンジの230日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

230日目は
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>230日目<br>・udemyで、css＋javascript講座<br>・webサイト部分的模写<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1224785648504066048?ref_src=twsrc%5Etfw">February 4, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
API BlueprintでAPIドキュメントからHTML生成、モックサーバ、テストを実行する。

# 背景・動機

業務でクローズドのAPIを開発していますが、APIの仕様書は人がMarkdownで作成していました。
最初のうちはよかったのですが、ドキュメントの劣化や面倒で作らない人も出てきたので、API Blueprintを導入し仕様書を作成するルールを作りました。
仕様書からテストやモックもできるようにしたので、備忘録も兼ねて共有します。

# 今回利用したツール

名称 | 説明
---- | ----
API Blueprint | Markdownを拡張したAPIドキュメントの仕様。
aglio | API Blueprintで作成された仕様書から静的HTMLを生成する。
drakov | API Blueprintで作成された仕様書からモックサーバを作成する。
dredd | API Blueprintで作成された仕様書どおり動くか自動テストする。

# 各種ツールのインストールと実行

今回、各ツールの環境をメンバーに配布したかったので、Dockerを使って構築しました。

## ディレクトリの構成

```
/
  /apib
    /hoge
      fuga.apib      ...API仕様書。
    index.apib       ...目次ファイル。各ディレクトリに分割した仕様書をまとめる。
    dredd.yml        ...テスト用の設定ファイル。(今回は説明を割愛します。)
  Dockerfile         ...Dockerの設定ファイル。
  docker-compose.yml ...Dockerの設定ファイル。
```

## Dockerで環境の構築

**Dockerfile**

```dockerfile
FROM node:latest

WORKDIR /projects

RUN npm install -g aglio --unsafe-perm
RUN npm install -g drakov
RUN npm install -g dredd
```

**docker-compose.yml**

```yml
version: "3"

 services:
   aglio:
     build: .
     ports:
       - "5000:5000"
     volumes:
       - "./apib:/projects"
     tty: true
     command: aglio --theme-variables slate -i index.apib -s -h 0.0.0.0 --port 5000
   aglio-compile:
     build: .
     volumes:
       - "./apib:/projects"
     command: aglio -i index.apib -o compile.apib --compile
   drakov:
     build: .
     ports:
       - "5001:5001"
     volumes:
       - "./apib:/projects"
     tty: true
     command: drakov -f compile.apib --public --watch --p 5001
   dredd:
     build: .
     volumes:
       - "./apib:/projects"
     working_dir: "/projects"
     tty: true
```

## コンテナ起動

```
docker-compose up -d
```

## テストの設定ファイル作成

```
docker-compose exec dredd /bin/bash -c "dredd init"
```

- コンソールで色々聞かれますので、適宜設定します。
- dredd.ymlが生成されていればOKです。

## ドキュメントの閲覧

Dockerコンテナの起動後、`http://localhost:5000`にアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127338/b8115b4e-c977-9318-d23b-fd332907ed20.png)

## モックサーバ

Dockerコンテナの起動後、`http://localhost:5001`にリクエストすると、仕様書通りのレスポンスを返してくれます。

```
$ curl http://localhost:5001/api/sample/hoge
{
  "message": "Hello, World!"
}
```

## テストの実行

以下コマンドで仕様書通りにAPIが動くのかテストしてくれます。

```
docker-compose exec dredd /bin/bash -c "dredd"
```

**テストの実行結果**

<img width="1080" alt="スクリーンショット 2020-02-05 20.00.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/127338/c7a6c3a8-b235-80b1-db60-4a2a4998905e.png">

※今回はAPIは用意していませんので、エラーばかりですが。
SIRモデルを使って新型肺炎の感染を予測してみた: ☓武漢編 ○湖北省編


最近，新型肺炎が流行っていますね．
以前にSIRモデルという感染症の数理モデルを使った研究をしていたので，新型肺炎のモデルに当てはめてみました．数理モデルを使うと，感染症の未来を予測できます．

今回は，発生の中心である ~~武漢~~***湖北省***(武漢を含む省) に注目して，感染症のモデル化と感染症の未来を予測します．

## keyword
疫学, SIR model, nCoV-2019, 新型肺炎, 新型コロナウィルス

## SIRモデル
SIRモデルは，感染した人数の推移を微分方程式として表したモデルです（[Wikipedia](https://ja.wikipedia.org/wiki/SIRモデル)でもわかりやすく解析されています）． SIRモデルでは，感染症に対して人は3つの状態を取ると考えられます．

1. 感染する可能性がある人 : S
2. 感染している人：I
3. 感染から治って免疫を獲得した人，または死亡した人 : R

時刻tにおける感染する可能性のある人，感染している人と感染から治った人をそれぞれS(t), I(t)とR(t)表記すると，SIRモデルは，

$$
\dot{S}(t) = -\beta S(t)I(t),\\
\dot{I}(t) = \beta S(t)I(t) - \gamma I(t)\\
\dot{R}(t) = \gamma I(t)
$$

と記述されます．
ここで，βは感染率を表し，γは回復率(+死亡率)を表しています．
感染者の増え方は，感染率β，感染する可能性がある人S(t)と感染している人I(t)に比例します．

死亡した人も感染を引き起こさないので，感染から治った人と同一視することに注意してください．

ここで， 
$$
S(t) + I(t) + R(t) = N
$$
は一定となり，その地域の人口と一致します．
今回は，~~武漢~~ 湖北省の人口を使います．

~~武漢~~ 湖北省における新型肝炎の感染データをつかって，感染率βと回復率γを学習し，武漢の未来を予測します．

## 使ったデータ

感染データはkaggleに公開されている[こちら](https://www.kaggle.com/sudalairajkumar/novel-corona-virus-2019-dataset/data)から引用しています．
また，~~武漢~~ 湖北省の人口データは，[こちら](https://en.wikipedia.org/wiki/List_of_Chinese_administrative_divisions_by_population)のに記述されている2017年の人口統計データを用いています．

## SIRモデルを使ったパラメーターの学習

~~武漢~~ 湖北省における，2020年1月22日から2月4日までの感染の推移は，以下のようになります．


![Hubei_time_dose.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245708/efd47fa2-78d5-4cc8-ccfa-8ae4a4337289.png)



青線が感染者数，オレンジ線が死者数，緑線が回復した人数です．
回復した人数と死者数がだいたい同じであることは，少しおかしいかな？と思います．


このデータを表現できるように，SIRモデルでフィッティングしてみました．

![SIR_model_Hubei.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245708/dfb14a13-5eca-909b-e236-2b8f8c7c807d.png)


Recovered peopleは回復した人と死者数の和としています．
また，青点が実際に観測されている感染者数，青線がSIRモデルで近似した結果です．
オレンジ点とオレンジ線は回復した人数の実測値と予測値です．

十分に近似できていそうです．


## ~~武漢~~ 湖北省の感染の未来を予測

十分に近似できていそうなので，学習したパラメータを使って， ~~武漢~~ 湖北省の感染の未来を予測してみました．

次の図が，2月4日から10日間の予測になります．

![Hubei_10days_future.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245708/1fba04a6-417d-9adf-dd82-bf4ba2216721.png)

点が実測値，線が予測値です．
SIRモデルよれば，まだまだ増加するようです．

次が2月4日から一年間の予測になります．

![Hubei_365days_future.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245708/81cdaead-2725-3ae8-2f43-9994acbe9b00.png)

感染が全然止まらいようです．

## 考察

- SIRモデルを用いて~~武漢~~ 湖北省における新型肺炎の感染の拡大を予測してみましたが，拡大が止まらないという予測結果になりました．
- ~~武漢~~ 湖北省において回復した人数が正確に計量されていないことが原因だと思われます．
- 他のデータを用いて，回復率γを正確に測定できれば，より良い予測ができると考えられます．

## 今後の課題
次は，交通量をもとに，中国全土の感染の広がりを予測しようと思います．


## 追記： 基本再生産数 R0
病気の感染力は基本再生産数R0によって評価されます．
R0は無次元化した感染率β_hatと無次元化した回復率γ_hatの比で与えられます．よって，湖北省の基本再生産数R0は，

$$
R_0 = \frac{\hat{\beta}}{\hat{\gamma}} = \frac{\beta N^2}{\gamma N} \approx 17.54
$$

となります．
この値は麻疹（はしか）などの空気感染する病気と同じぐらいです.この感染力の強さは，考察で述べたように回復率が低く見積もられているからだと考えられます．

## コード

https://github.com/yuji0001/2020nCoV_analysis
Linux で uim ツールバーをシステムトレイ (?) に移動

X11 の画面右端に uim の小さなウインドウが出ていて邪魔なので、タスクバー (?) に移動させる方法。
リンクのみ、覚書です。

https://forums.ubuntulinux.jp/viewtopic.php?pid=119365
Xcode archive時にimport不可のエラー

##はじめに
FlutterでAPL開発を行い、APPLEの申請を行っていたのですが、思わぬところでつまずいたので、備忘録として保存しておきます。
　
通常のビルドは、実施可能ですし、シュミレーターの起動や実機での起動も上手く行ってたにも関わらず、appleでの申請用にarchiveしようとしたら内部で使用しているライブラリをimportできないとエラーになりました。

この[記事](https://i-app-tec.com/ios/app-upload.html)を参考にarchiveしており、エラーになりました。この記事は何も悪くはなく、素晴らしい記事です。

##試した内容
* クリーンして再ビルド。　→ NG
* [これ](https://github.com/flutter/flutter/issues/22821)を参考に、Podfileを削除して、`pod install`からやり直し。　→NG
* [これ](https://teratail.com/questions/99422)を参考に、deployment target を変更してみる。　→NG
* [これ](https://teratail.com/questions/62702)を参考に、読み込みのパスを変更。　→NG

##結局解消した方法
[これ](https://github.com/flutter/flutter/issues/42745#issuecomment-542638225)を参考にしました。

`Runner.xcproject` ではなく`Runner.xcworkspace`でXcodeを開いてarchiveする必要があったみたいです。
下記のコマンドで開けるので、お試しください。
```open Runner.xcworkspace
``` 
## 結局の原因
[これ](https://qiita.com/rockname/items/bbe73a001568f0f5e801) にこの２つの開き方の違いが記載されているのですが、複数プロジェクトの依存関係を解決できていなかったみたいです。