OmniAICreator/Qiita-1.07M huggingface dataset:
BlazorでGoogleFontsを試すサイトを作る

Blazorで フリーで使用できるGoogleFontsから、日本語のフォントを試すサイトを作ってみたいと思います。

[Google Fonts](https://fonts.google.com/)
https://fonts.google.com/

[Google Fonts + 日本語](https://googlefonts.github.io/japanese/)
https://googlefonts.github.io/japanese/

[Demo](https://blazorappfonts.firebaseapp.com/)

[サンプルコード](https://github.com/kimux8/BlazorAppGoogleFonts)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/38327462-3f1d-44ed-3ccb-46fa41e9e335.gif" width=65%>

# Google Fontsの取り込み
BlazorでGoogleFontsを取り込むには、`index.html`に記述します。

EarlyAccess版は、`linkタグ`で指定します。GoogleFontsで提供されているものは必要なものをピックアップして、`@import`します。

```html:wwwroot/index.html
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>BlazorAppGoogleFonts</title>
    <base href="/" />
    <link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
    <link href="css/site.css" rel="stylesheet" />

    <!--EarlyAccessフォント-->
    <link href="https://fonts.googleapis.com/earlyaccess/hannari.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/earlyaccess/nikukyu.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/earlyaccess/nicomoji.css" rel="stylesheet">
    <link href="https://fonts.googleapis.com/earlyaccess/kokoro.css" rel="stylesheet">
    <!--通常のフォント-->
    <style>
        @import url('https://fonts.googleapis.com/css?family=Kosugi|Kosugi+Maru|M+PLUS+1p:100,300,400,500,700,800,900|M+PLUS+Rounded+1c:100,300,400,500,700,800,900|Noto+Sans+JP:100,300,400,500,700,900|Noto+Serif+JP:200,300,400,500,600,700,900|Sawarabi+Gothic|Sawarabi+Mincho&display=swap');
    </style>
</head>

```

# 使い方
使いたいところでスタイルに`font-family`や`font-weight`を指定します。

```html:
<p style="font-family:Kosugi;font-weight:bold;">おはようございます</p>
```

日本語のフォントは少ないですが、いい感じに使っていきたいと思います！
C++11 or later で epoch time から時刻の文字列を作るメモ

## 背景

epoch time などから, 時刻の文字列を作りたい.

なにやらいろいろ関数あってどれをつかえばいいかわからない.

C とかですと, `strftime` がよく使われているでしょうか?

https://en.cppreference.com/w/cpp/chrono/c/strftime

## C++11 でナウな感じで文字列を作る

C++11 から, stream 用に `std::put_time` がつきました.

https://en.cppreference.com/w/cpp/io/manip/put_time

std::stringstream と組み合わせてあげましょう.

`iomanip` に定義されているので注意です!

## 速度が気になる?

locale が絡むと処理が非常にかかるという話も噂でききますので, 時差とかも少しおかしてもよくて単に year/month/day くらい表示したいのであれば, epoch 時刻から自前で計算する手もあるでしょう.

https://stackoverflow.com/questions/1692184/converting-epoch-time-to-real-date-time

## 文字列から時刻データに変換する.

https://en.cppreference.com/w/cpp/io/manip/get_time

`get_time` で行けるやも?
jest の toBe と toEqual の違いを比較

1時間ほどハマったのでメモを。

# toBe と toEqual の使い所

- number, string の比較ならどちらでも良さそう。
- object を比較する場合は、 toEqual 。


number, string 
-----

どちらも期待通りの結果に。

```typescript
    it('number', () => {
      expect(1 + 1).toBe(2) // ok
      expect(1 + 1).toEqual(2) // ok
    })
```


```typescript
    it('string', () => {
      expect('d' + 'b').toBe('db') // ok
      expect('d' + 'b').toEqual('db') // ok
    })
```


object
----

同じデータが入っていても toBe だと Fail します。

```typescript
    it('object', () => {
      const user = { name: 'Hoge', age: 30 }
      // expect(user).toBe({ name: 'Hoge', age: 30 }) // Fail
      expect(user).toEqual({ name: 'Hoge', age: 30 })
    })
```

もともと日付の比較でハマってました。 Date は toEqual を利用しましょう。

```typescript
    it('date', () => {
      const date = new Date('2020/01/01 00:00:00')
      // expect(date).toBe(new Date('2020/01/01 00:00:00')) // Fail
      expect(date).toEqual(new Date('2020/01/01 00:00:00'))
    })
```

new したインスタンスの比較も同様です。

```typescript
    it('class', () => {
      class User {
        age: number
        constructor(age:number) {
          this.age = age
        }
      }
      const user = new User(30)
      // expect(user).toBe(new User(30)) // Fail
      expect(user).toEqual(new User(30))
    })
```

object の id が異なるからでしょうか。


参考
---
- https://gist.github.com/shts/ecaeaa09e7ae948eb47e9f22a85b423a
- https://jestjs.io/docs/ja/using-matchers
C言語　再帰を使って配列の合計値を求める、文字列を出力する。

※2020/03/09　コメントを受けて追記

再帰についての理解を体に染み込ませるためにいろいろ再帰を使ったコードを考えてみる。

####配列の合計値を出すコード

```c
#include <stdio.h>

int arraySum(int *a, int b, int i)
{
    if(b > 0){
        --b;
        i +=a[b];
        return arraySum(a, b, i);;
    } else {
        return i;
    }
}

int main(void)
{
    int a[6] = {1,3,4,5,7,8};
    int b = 6;
    int i = 0;
    printf("%d\n", arraySum(a,b,i));

    return 0;
}
```

#####気づいたこと
- int型の配列と再帰の組み合わせは、__アドレス__の他に__配列数__、__シード値__が必要。
    - 渡すものが多いので野暮ったい印象。 


####文字列を出力するコード

```c
#include <stdio.h>

void printstr(char* str)
{
    if(*str != '\0'){
        printf("%c", *str);
        str++;
        printstr(str);
    }
}

int main(void)
{
    char str[] = "Aiueo";
    printstr(str);
    printf("%c", '\n');

    return 0;
}
```

#####気づいたこと
- 文字列は終点のデータが存在するという部分において__リスト構造__と同じデータ構造。だから、再帰的な処理を書くときに文字列は__int型の配列__に比べて__シンプルに定義__できる。
- __帰納的定義__と__再帰__の関係への理解が深まった。


##追記
以下のような書き方もあるとコメント頂いた。

```c
int arraySum(int *a, int n)
{
    if(n <= 0) return 0;
    return *a + arraySum(a + 1, n - 1);
}
```

配列をインクリメントできる仕様を使ったスマートな書き方。
与えられた配列数をカウントのみに使用して、再帰的に書いている。
自分の書いたコードは見た目に違和感があったのだが、このコードでは解決されている。
ROSを使ってロボットとパソコンをつなげる方法

今回は、ロボットを動かすための環境構築について説明します。

必要なものとしては、対象となる**<font color="Red">ロボット</font>**とそれを制御する**<font color="Red">パソコン</font>**の２つです。

また、この２つの機器をつなげるための**<font color="Red">無線ネットワーク環境</font>**も必要となります。

<br>

ロボットを制御する方法として、最も広く使われているのがROS（Robot Operating Systems）というものです。

まず、私の開発環境を書きます。


PC：**<font color="Red">Ubuntu 18.04</font>**

ROS version：**<font color="Red">melodic</font>**


ROSにはいくつかのバージョンがありますが、私はmelodicを使っています。

ROSのインストール方法は[公式ホームページ](http://wiki.ros.org/melodic/Installation/Ubuntu)を参考にしてください。

<br>

次には今回の制御目標であるロボットについて説明します。

私が使っているのは、ROBOTIS社の**<font color="Red">Turtlebot3 waffle pi</font>**というものです。

http://emanual.robotis.com/assets/images/platform/turtlebot3/overview/turtlebot3_with_logo.png

<br>

名前の通り、平べったい形をしているロボットです。

センサとしては、カメラ、LDS、IMUが装備されており、ラズベリーパイによって制御されます。

詳細情報は[公式ホームページ](http://emanual.robotis.com/docs/en/platform/turtlebot3/overview/)を参考にしてください。

<br>

ロボット側もROSをインストールする必要があります。

これに関しては、ROBOTIS社のホームページから既にROSがインストールされているラズパイのOSイメージを[ダウンロード](https://www.robotis.com/service/download.php?no=1738)することができます。

<br>

次は、無線ネットワークを使ってパソコンとロボットをつなげる必要があります。

ロボットのセンサから取得した情報をパソコン側に送ったり、ロボットにコマンドを送ったりするためです。

２つの機器をつなげるためには，それぞれのIPアドレスを調べる必要があります．

まずターミナルを開いてください．

ショートキーは，**<font color="Red">「Ctrl + Alt + t」</font>**となります．

コマンドが入力できる状態になりましたら，**<font color="Red">「ifconfig」</font>**を入れてください．

~~~
$ ifconfig
~~~

すると，色んな情報が出てきますが，

**<font color="Red">「wlan0」</font>**というところの**<font color="Red">「inet」</font>**というところに書かれた数字を確認してみてください．

~~~
192.168.0.10
~~~

のような数字が書かれていると思います．

これがパソコンのIPアドレスとなります．

ロボットのラズパイの方も同じ方法で調べることができます．

今回は，例としてパソコンとロボットのIPが次のようになっていると想定します．

<br>

・パソコンのIP：**<font color="Red">192.168.0.10</font>**

・ロボットのIP：**<font color="Red">192.168.0.20</font>**

<br>

ここまで出来ましたら，あとはROSの設定ファイルを開いて上記の情報を書き込みます．

ROSの設定は，**<font color="Red">「.bashrc」</font>**というファイルで出来ます．

ターミナルを開いて次のようにコマンドを入力してください．

~~~
$ gedit ~/.bashrc
~~~

すると，テキストエディターが開くと思います．

上記のコマンドの「gedit」というのは，テキストエディターの名前であって，それを使って「~/.bashrc」ファイルを開いたということです．

パソコンによっては，色んなことが書かれていると思いますが，

~~~
export ROS_MASTER_URI=http://localhost:11311
export ROS_HOSTNAME=localhost
~~~

と書かれたところを探してください．

パソコンの場合は，**<font color="Red">「localhost」</font>**のところを消して先程の**<font color="Red">IPアドレス</font>**を書いてください．

つまり，

~~~
export ROS_MASTER_URI=http://192.168.0.10:11311
export ROS_HOSTNAME=192.168.0.10
~~~

こうなるようにしてください．

<br>

次に，ロボットのラズパイの方は，

**<font color="Red">「ROS_MASTER_URI」</font>**の方は**<font color="Red">パソコンのIPアドレス</font>**を，「**<font color="Red">ROS_HOSTNAME」</font>**の方は**<font color="Red">ラズパイのIPアドレス</font>**を入れてください．

つまり，

~~~
export ROS_MASTER_URI=http://192.168.0.10:11311
export ROS_HOSTNAME=192.168.0.20
~~~

こうなるようにしてください．

変更内容を保存して，テキストエディターを閉じてください．

ただ，このままだとOSに変更内容が反映されないので，次のコマンドを入力してください．

~~~
$ source ~/.bashrc
~~~

以上でロボットとパソコンを無線ネットワークでつなげる設定は終了です．

次回は，実際にロボットが計測した情報をパソコン側が受け取る方法を説明します．
HTML&CSS　ブロック配置

# floatプロパティ
指定された要素を左または右に寄せて配置する際に使用。
副作用
・親要素の高さは子要素のheightの合計
・子要素にfloatを使用すると、その子要素は浮いたような形になる
・親要素は高さを持てなくなり、消えてしまう
解決方法
floatの副作用を防ぎたいクラスに付与することで問題が解決。

css

```
.clearfix::after {
  content: "";
  clear: both;
  display: block;
}
```
html

```
<div class="contents clearfix">
 <div class="left-content">
 </div>
 <div class="right-content">
 </div>
</div>
```
# after
HTMLに書かなくても要素を後付けできる

# contentプロパティ
擬似要素afterによって作成された要素の中身を指定するためのプロパティ。
afterを利用する際は必須になるので、何も表示したくない場合は値を""とし空白とする。

# clearプロパティ
clearプロパティは、floatによって無くなる要素の高さを正常に戻してくれるプロパティ。
手前の要素をfloatしたあと、floatによって回り込ませたくない要素に対して使う。
値は both とすることが多い。

# displayプロパティ
displayプロパティは、要素の種類(ブロック要素、インライン要素)を変更することができるプロパティ。
値には、変更したい要素の種類を取る。

# marginプロパティ
箱の外側に余白を取ります。pxで指定。上下左右4方向に指定できる。
指定方法　　　　　　　　　　　説明
margin: 1px;　[上下左右]の余白をまとめて1pxに指定
margin: 1px 1px;　[上下][左右]の余白をそれぞれ1pxに指定
margin: 1px 1px 1px;　[上][左右][下]の余白をそれぞれ1pxに指定
margin: 1px 1px 1px 1px;　[上][右][下][左]の余白をそれぞれ1pxに指定

# paddingプロパティ
箱の内側に余白を取る。指定方法はmarginと同様pxになる。
指定方法　　　　　　　　　　　説明
padding: 1px;　[上下左右]の内側の余白をまとめて1pxに指定
padding: 1px 1px;　[上下][左右]の内側の余白をそれぞれ1pxに指定
padding: 1px 1px 1px;　[上][左右][下]の内側の余白をそれぞれ1pxに指定
padding: 1px 1px 1px 1px;　[上][右][下][左]の内側の余白をそれぞれ1pxに指定

# borderプロパティ
箱の境界線の幅や色を変更できる。

# ボックスモデルの中央寄せ
marginプロパティで、左右の値をautoに指定することで、ブロック要素を中央に配置することができる。
指定方法　　　　　　　　　　説明
margin: 0 auto;　[左右]に対して中央に配置

# justify-contentプロパティ
justify-content: 〇〇;といった形で、display: flex;に併記する。
すると横並び方向の詳細を決めることができる。

```
・左寄せ
justify-content: flex-start;

・右寄せ
justify-content: flex-end;

・中央揃え
justify-content: center;

・両端が左右に寄り等間隔
justify-content: space-between;

・両端が左右に寄り等間隔で両端の余白と要素間の余白が1:2
justify-content: space-around;
```

# position: absolute;
要素の配置を絶対指定する。ブラウザの左上を基準として、top/right/bottom/leftで位置を指定。
例）上側と左側に、それぞれ30pxの空間ができる。

```
  position: absolute;
  top: 30px;
  left: 30px
```

# position: relative;
親要素に付与すると、子要素の基準を自身の要素として指定することができる。

# align-items
display: flex;が付与された子要素について、縦方向の詳細を決める
例）上下中央に配置

```
align-items: center;
```

# flex-direction
display: flex;が付与された子要素について、並び順を決める
例）上から下に並んでいく

```
flex-direction: column;
```

# background-image
背景画像を指定する

```
background-image: url(xxxxxxxx);
```

# background-size
背景画像のサイズを決めることができる
例）全体を覆うサイズになる

```
background-size: cover;
```

# background-position
背景画像の配置を決めることができる
例）上下左右中央に配置される

```
background-position: center;
```

# :hover
マウスが当てられたときに機能する疑似要素

```
.cta-btn:hover {
  box-shadow: 0 0 10px #ffa201;
}
```
pythonのisdigit()はマイナスの整数を判定できない

## 事の発端
pythonのisdigit()でマイナスの整数を判定しようとしたら、出来なかったので調査した。調査時間10分程度。

## 参考サイト
https://or3.hatenablog.com/entry/2017/10/08/034955
参考サイトを見たほうがいいです。

## サンプルコード
``` python3
def is_num(a):
    try:
        int(a)
    except:
        return False
    return True


def main():
    s = '-1'
    print('s =', s)
    print('isdecimal:', s.isdecimal())
    print('isdigit:', s.isdigit())
    print('isnumeric:', s.isnumeric())
    print('is_num:', is_num(s))


if __name__ == "__main__":
    main()
```
## 実行結果

![isdigit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262477/cf8e0f54-ca37-11dc-ba12-2709eccc74a6.png)

## 感想
isdigitが残念すぎる。
bashのcurlで簡単にBacklogにAPI起票する

# 目的

BashスクリプトやCrontab,LogrotateでエラーなどをトリガーにBacklog起票する。

# どうやるか

bashのcurlコマンドでBacklog APIを叩いて起票。特に凝ったことはしない。

# コマンド

[Backlog 課題起票API](https://developer.nulab.com/ja/docs/backlog/api/2/add-issue/#%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%83%BC)

[Backlog ユーザー一覧取得API](https://developer.nulab.com/ja/docs/backlog/api/2/get-user-list/#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E4%B8%80%E8%A6%A7%E3%81%AE%E5%8F%96%E5%BE%97)

ユーザー一覧取得コマンド（管理者じゃないと無理）

※スペースIDは起票するプロジェクトのドメイン部分 -> https://〇〇〇.backlog.jp/

```bash
curl -X GET https://${スペースID}.backlog.jp/api/v2/users?apiKey=${APIキーは管理者ユーザーの個人設定ページから適宜発行してください}
```

起票コマンド

```bash
curl -X POST -d "projectId=${画面右上ユーザーアイコン→プロジェクト設定のURLにある}&summary=${課題チケットのタイトル}&description=${課題チケットを開いた際に表示される詳細}&startDate=${yyyy-mm-dd}&dueDate=${yyyy-mm-dd}&issueTypeId=${画面右上ユーザーアイコン→プロジェクト設定→種別の一覧→選択した種別のURLにある}&priorityId=3&assigneeId=${上記ユーザー一覧のAPIから取得(管理者にAPI叩いてもらうしかない)}" https://${スペースID}.backlog.jp/api/v2/issues?apiKey=${APIキーは起票するユーザーの個人設定ページから適宜発行してください}
```
Photon Realtime を C++ でコーディングするところまで辿りつくためのメモ

C++でも使ってみようと思ったのにPhotonの情報を調べるとほぼUnityの情報しか出てこなくて辛かったので、とりあえず動かせるようになるまでの記録。
※当記事は筆者がググっても全然情報が出なかった、あるいは理解に時間がかかったところを重点的に書いてるので、ところどころ端折ってます。また、記事内においてPhotonについての詳細は省いていますので、Photonについての概要に関する情報をお求めの方は別の記事を検索してみてください。

本記事の想定環境は「OS X」「C++」「v4.1.15.2」です。Windows等でも大きな差はないはずですが、適宜読み替えてください。

#SDKをダウンロードする
https://www.photonengine.com/ja/sdks
ここから目的のプラットフォームのSDKを落とします。
ちゃんと動くDEMOがzipの中に付いているので頼りになります。しかし複雑で読んでても全然分からん状態になるので、ほどほどに読む程度にしておくことをおすすめします。動作確認はできますね。

ここから具体的にどうやってパスを通すかなどはdocにドキュメントが入ってるので、それを読んだりして気合いでどうにかします。というか気合いで解決したので何をどうやったのか詳しく覚えてないです…

<https://doc-api.photonengine.com/en/cpp/current/a05867.html>

#AppIDを取得する
Photonの公式サイトでIDを作っておきます。あとで入力します。20人接続までなら無料です。
https://www.photonengine.com/

#公式ドキュメントの紹介

### APIリファレンス
https://doc-api.photonengine.com/en/cpp/current/index.html
docフォルダの中身と同じです。ところで、当記事執筆時点ではLoadBalancing-cppの中身が何も書かれていません。未完成では…？下のAPIの方はありますが…

これを見つつ手探りで進めてたらわけわからなくなったので最初に見るのはおすすめできません。理解してきたら使うとよいでしょう。

### Realtimeイントロ 
https://doc.photonengine.com/ja-jp/realtime/current/getting-started/realtime-intro
一見C#のサンプルに見えますが、クリックするとC++のコードが見れます。
<img width="324" alt="スクリーンショット 2020-03-05 17.39.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212031/978c3e0c-179f-f6a4-8961-b2e9d0415b40.png">
これがプルダウンメニューになってます

段階を追って組み上がっていくので理解しやすいです。最もおすすめ。（他の選択肢がほとんどないんですけどね…）

#仕様についてのメモ

だいたい上の「Realtimeイントロ」に書いてあることのまとめです。v4.1.15.2時点。
多くの動作をコールバックで記述することになるので、特に現在の状態の把握などには工夫がいります。(状態の扱いについては、DEMOが参考になったのでおすすめです。)

###とりあえず動かすまで

#### ExitGames::LoadBalancing::Listener を継承したクラスを実装する
このクラスがPhotonのコールバックを受け取ります。**これを継承したクラスは、以降記事内でListenerクラスと呼ぶことにします。** 純粋仮想関数がたくさんあるので、IDEの機能でオーバーライド関数を一括作成すると楽ですね。Realtimeイントロでは継承クラスは実装されていないのでコピペしただけだとエラーが出ます。要注意です。

コールバックの中で、最初に使うのはconnectReturn()になると思います。

実装例

```cpp
void connectReturn(int errorCode,
                       const ExitGames::Common::JString& errorString,
                       const ExitGames::Common::JString& region,
                       const ExitGames::Common::JString& cluster)
{
//エラーを弾くならこう
   if(errorCode){ std::cout << "connect error\n"; return; }
   std::cout << "connected\n";
}
```

errorCodeが0以外ならエラーがある、ということのようです。（DEMOの実装より）
このif文を超えられれば接続はできているはずなので、ひとまずここに到達できるよう頑張りましょう

#### ExitGames::LoadBalancing::Clientを用意する

「用意する」と書きましたがインスタンスのことです。
connect()で接続したりします。具体的な通信開始はこのクラスが行います。コンストラクタに、上で作ったListenerクラスやAppIDなどを渡せば生成できます。
　DEMOでは、Listenerクラスの中にClientクラスのインスタンスを作り、Clientにthisを渡す設計をしています。これだと確かにクラスがひとつにまとまり、その後の実装もスムーズに進むんですが、クラスが肥大化していて非常に分かりづらかったです。
　Realtimeイントロのコードでは、継承済みクラスが実装されてない罠があるものの、別々のクラスになっています。分離されていて役割分担が見えやすいのでまずはこの実装方法の方がよいでしょう。

#### (ExitGames::Common::Loggerを用意する)

必須ではありません。ログがここに流れてくるようです。最初は無視でいいでしょう

#### 毎フレーム Client.service()を呼ぶ

通信は非同期処理で行われるので、内容がPhoton側でキューに蓄積されます。
ExitGames::LoadBalancing::Client.service()を呼ぶことでそれが消化され、Litenerクラスのコールバックが発火します。この関数を定期的に呼ぶようゲームループに仕込んでおきましょう。これを呼び忘れると、接続成功しても、どんなに待ってもうんともすんとも通知が来ないので注意です。

---

ここまで準備して、ExitGames::LoadBalancing::Client.connect();を呼ぶとたぶん接続できると思います。私は出来ました。勉強しつつ大急ぎで執筆しましたので、記事中に大きな間違い、勘違いがあればご教示のほどお願いします。

~~そしてこれを読んだみなさんもPhoton C++をガンガン使いこなして日本語の記事を充実させていってください。私はやりました。~~
[swift]カスタムメニュー、ハンバーガーメニューで使いたい表示方法 備忘録

これを作ります。

![スクリーンショット 2020-03-05 18.13.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/cf150553-812d-80db-fe62-9252458cd711.png)
![スクリーンショット 2020-03-05 18.13.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/a01f12a9-f98a-6c70-a62a-9cf9ec92b951.png)
###作り方
まずは右に新しいviewを貼りましょう。
そこからは画像の通りに、、

![スクリーンショット 2020-03-05 18.19.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/6a5f2352-c938-6349-52fe-5c7c797f343f.png)

<img width="594" alt="スクリーンショット 2020-03-05 18.03.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/58bd903e-a3ea-0ab3-071e-aa9c52572999.png">
<img width="507" alt="スクリーンショット 2020-03-05 18.11.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/4ef3114c-d0a7-ffe7-7d36-651058cf15ad.png">

メイン画面とメニュー画面を接続して、、
<img width="849" alt="スクリーンショット 2020-03-05 18.07.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/26662965-c900-6b20-9df9-73437f232345.png">

おしまい
リモート輪読会のすゝめ

# はじめに

こんにちは、株式会社プラハ エンジニアの @harhogefoo です。

今回は弊社の勉強会の一環として**リモート輪読会** を開催し、
約3ヶ月が経過したので、そのやり方と効果について紹介したいと思います！

# リモート輪読会とは？
リモート輪読会とは、文字通り **リモートで輪読会をすること** です。

輪読会のやり方は多々ありますが、
弊社では

**1. 読みたい書籍を1冊決める**
**2. 毎週その本を1章ずつ読む**
**3. 読んだ章の感想や考察をSlackのリモート輪読会用チャンネルに投稿する**

こんなやり方で進めています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32950/dcd7e0a5-7bc1-0a58-9247-a692a108ca8e.png)

# なぜリモート輪読会なのか？
弊社は週に1日木曜日のみ対面で集まる、月額定額の受託開発と自社サービス開発をするスタートアップです。
木曜日以外は、基本リモートで働いています。

こういう会社なので、**リモートでできるものはなるべくリモートでやりたい**という思想が常にあり、
そこで考案した勉強会が **リモート輪読会** でした。

---

（宣伝です）
弊社のHPはこちら！
https://www.praha-inc.com/

ものづくりが大好きなITエンジニアに特化したプロダクト起点のSNS「PRANET」も宣伝！
https://www.lp.pranet.tech/

---

# リモート輪読会を実際にやってみて

初回に選択した書籍は、「**レガシーコードからの脱却**」です。

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32950/673509ad-b335-7e48-f695-2a99dcac2440.png)](https://www.oreilly.co.jp/books/9784873118864/)
https://www.oreilly.co.jp/books/9784873118864/


社内のあるエンジニア **Y氏** がこう言いました。

**Y氏** 「レガシーコードからの脱却を読了したけれど、個人で適用できるプラクティスよりも、チームで適用できるプラクティスの方が多いと感じたので、ぜひ社内のエンジニア全員に読んで欲しいです。輪読会、やりませんか？？」

**ワイ** 「やりたいですね！輪読会、どう進めるのがいいですかね :thinking: 」

**Y氏** 「じゃあ、後はお願いします！」

**ワイ** 「（丸投げやん...:thinking:）」

ここからリモート輪読会は始まっています。

## リモート輪読会の良い点

- 時間に縛られない
- 好きな時間に読み進められる
- 毎週読む章が決まっているので、継続的に本を読み続けられる
- 難しい技術書でも読み続けられる
  - **積読ならない**
- 1章をじっくり読んでSlack上で意見交換ができるので、理解が深まる
  - **なんとなく読んだ** にならない
- 他者の意見から、**他者の読み手の観点を知る**ことができる
  - （なるほど、こういう観点を気にしながら読んでいるのか！次からこの観点を気にしながら読んでみよう)等

## リモート輪読会の難点
- (リモート輪読会のルール決め次第ですが) 読み切るのに時間がかかる

# リモート輪読会で得られたもの
- ページ数の多い書籍を読み切れる
- 本を読む習慣がつく
- 意見、感想を投稿することで **自分や社内に適用できないか？** を考える週間が身につく


## 輪読会を踏まえて起こった社内の変化
リモート輪読会に限らず輪読会で起こる変化だと思いますが、参考までに記載しておきます。
また、今回選定した書籍「レガシーコードからの脱却」の内容に寄っています。

- 社内で毎週木曜日に1時間の**ペアプログラミング**を始めた
  - ペアプログラミングの具体的なやり方はレガシーコードからの脱却に書いてあります
- 小さく作る（Issueに対する**見積もりが3時間以内**になるように分割して作る）
- ブランチ戦略の改善（全ての機能実装をdevelopmentブランチにマージする）

#### 既に行っていること
- テスト駆動開発
- ユニットテストを書く
- リファクタリング期間を設ける

# 終わりに

ここまで読んでいただきありがとうございました。

フルリモートな組織や、読むモチベーションが中々上がらない書籍を読みたい場合に
リモート輪読会を試してみてはいかがでしょうか？


参考までに私個人のNoteに投稿した感想をまとめていますので読んでみて下さい。
https://note.com/harhogefoo/n/n89223e0a9872

Happy Coding!
アウトプットPart2

# 3月5日勉強でやったこと
##1.PHPでHello Worldを出力した

![スクリーンショット (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596056/8d1bec65-f69b-aa6c-19d8-75b7239813b4.png)

出力などはわかっていたのだが、ApacheとPHPを関連付けるのが難しかった。
無事に出力できてよかった。

##2.Gitを知ろう
Gitはコードの変更履歴が残るため、ファイルがかさばらないすごい技術です。
どうしてもプログラムにしてもパワーポイントにしても、名前を別に変えることによりファイルが増えていきどれがどれだかわからない状態になってしまうことが多いのでこの技術はすごくありがたいなと思いました。
しかも仲間たちとファイルが共有できるし、その人の変更履歴を選べるので使い勝手がいいなと思いました。

##3.よく使うファイル
今日は、プログラムを組む上で必ず使うであろうファイルを調べました:rolling_eyes:
**・JSON**
　　　配列とオブジェクトをネスト構造で表現できるため、どんな複雑なデータ構造でも規定可能
　　　文字だけのファイルなので軽い
**・CSV**
　　　ファイルが小さい
　　　アプリやシステムでの取り扱いが簡単
**・Yaml**
　　　構造化されたデータを扱うフォーマット
　　　計算もできて変数も宣言できる器用なファイル

どれもすごく使いやすいファイルで、今後お世話になるファイルです。

　　　　　　　　　　　　　　　　　　　　　　　　　　　以上、ありがとうございました！
devise のパスワードカラム名は「encrypted_pa​​ssword」だけど不可逆

## 「ハッシュ化」と「暗号化」

今まで

ハッシュ化 → 元に戻せないやつ。英語だと hash。
暗号化 → 元に戻せるやつ。英語だと encrypt。

だと思って生きてきました。
今でもそう思っています。

ところが、、、

## devise のパスワードカラム名・・・encrypted_pa​​ssword！？

先日ふと気づいたのですが、gem devise のパスワードカラムの名前が「encrypted_pa​​ssword」になってます。

えっ、これってもしかして復号できちゃうの？？

## 実装を見てみる

普通にハッシュ化してるっぽい。

```/lib/devise/models/database_authenticatable.rb
      def password=(new_password)
        @password = new_password
        self.encrypted_password = password_digest(@password) if @password.present?
      end

      ...

      def password_digest(password)
        Devise::Encryptor.digest(self.class, password)
      end
```


```/lib/devise/encryptor.rb
require 'bcrypt'

module Devise
  module Encryptor
    def self.digest(klass, password)
      if klass.pepper.present?
        password = "#{password}#{klass.pepper}"
      end
      ::BCrypt::Password.create(password, cost: klass.stretches).to_s
    end

    ...
```

## まとめ

カラム名は「encrypted_pa​​ssword」だけどやってることはハッシュ化（不可逆）だから安心していい。

--

ちなみに、過去にカラム名をリネームする案も出たことがあるようですが、
「既存の利用者に与える影響でかすぎ。名前変更のリスクに見合うメリット無い（超意訳）」
との理由により close されていました。


The word 'encrypted_password' raises red flags; time to rename?
https://github.com/heartcombo/devise/issues/5025
【VBA】処理の最後に部分一致に戻す

VBA記述中にFINDメソッドの「完全一致」検索

【例】
```Cells.Find(what:="xxx", LookAt:=xlwhole)
```

を入れていると、処理終了後もExcelが完全一致の設定を保持している。
（置換ダイアログで、「セルの内容が同一～」にチェックが入ったまま）

このためVBAの終了処理に、部分一致に戻す処理を入れることで、
処理終了時に「部分一致」に戻すことができる。
以下の構文であれば、併せて検索欄を空白にリセットすることも可能。

【例】
```Cells(1, 1).Find What:="", LookAt:=xlPart
```
※　構文の【cells(1,1)】は任意の場所でOK
チーム開発でコードの書き方やクラス設計の認識を合わすためにやったこと

# 対象のユーザ
- チーム開発をしている人
- チーム開発に悩んでる人
- レガシーコードをなんとかしたい人
- コード全体を一気にリプレイスできない人

# はじめに
今プラハという会社で[PRANET](https://pranet.tech)というエンジニアのSNSを開発している[revenue-hack](https://github.com/revenue-hack)です。
PRANETはフロントにVue.js, Nuxt, バックエンドにTypeScript, Express, DBにNeo4j, Cloud Firestoreを採用しています。

# 課題について

- コードを書く場所が人によってバラバラ
- 変数名やカプセル化の加減が人によって違う
- PRで一度議論が起きたことが他のPRでも起きていて、チーム全体の認識が合わない

このようなことが起きていて、チームの開発スピードが一向に上がらないという問題が起きていました。

## どのように解決したか？
弊社ではPR道場というものを取り入れました。

PR道場とは

- 誰かのPRで起きた議論は他のPRでも起きていく可能性が高い
- どこに書くべきか、どう書くべきか人によって意見が分かれる

そういったものを解決するために弊社で週1で行っている提案会議です。

ではPR道場での実例を2つほど紹介します。

### コミットメッセージに関する提案

```
(課題) resolve conflictした時、どこを修正したのかわからない
(提案)
　　・’resolve conflict’ってコミット名は禁止
　　・fix:の記法に沿って、どこを修正したのか記載する
```

背景として最近conflict修正を失敗してバグを生んでいたため、コミットメッセージでどの部分のconflictがおかしくなっていたのか追えなくなっていました。
そこでコミットメッセージを正すことで、conflictの変更もコミットメッセージからわかるようにしました。

こういったライトなものでも共通認識を持つことで、問題解決につながっていきます。

### エラーハンドリングの方法について
また実装レベルの提案だとエラーハンドリングの仕方についての提案です。

```
Repository層でfindしてDBからリソースが取得できなかったときはundefinedを返す（エラーを返すのではなく）
　・配列は空配列を返す
　・SettingRepoImplでユーザの設定が取得できないときにエラーを吐いていた
　・Repoではundefinedを返して、ルーター辺りでhttp response errorを作るように変えた
　・理由
　　・404なのか500なのか区別つかない
　・異なるハンドリングされる可能性のあるエラーには気をつける（404と500）
```

エラーハンドリングは1つ必ず決まった正解があるわけではなく、チーム単位やプロジェクト単位また個人単位でも異なってきて、処理の方法に差が出る部分です。
その部分をチームで提案という周知することで、コードの品質を担保することができます。
また今回のケースでは議論が発展し、404や500だけでなく400のケースもチェックするべきではないか？その場合はどのように処理するのが良いか？
など更に深ぼった話に発展し、結果的にRepository層では400, 500, 404のエラーを区別できるようにエラーclassを作り、それをthrowするようにしました。
この提案でチーム全体のコード規約を決めることができ、また提案の背景を知ることで個々の設計力や、コーディング力が上がってきました。


## PR道場(改)
ただPR道場をやっていて一点課題が出てきました。
それはPR道場をやっていると設計に詳しい人やTypeScriptやVueに詳しい人など、喋る人が偏っていて、
これだと結局話さない人がどの程度理解しているかわかりません。
そこで、PR道場で出されたお題を、出した人以外の人が話すことにしました。
メリットとしては

- 発言者が偏らないことで、全体の周知度が見えやすくなる
- 理解していない人がなにが理解できていないのかはっきりわかるようになる
- 誰が読んでも説明できるぐらい後世に伝えやすい形で残るドキュメントが残る

があります。
こうすることでコード規約の決め事の場から、全員が理解してコードを書けるよう成長する場にすることができました。

## まとめ
今回チーム開発を改良したことで良かったこととして、

- 全体としてのコードを書く上での共通認識がある程度固まった
- (どうしてこの提案をしたのか背景を知ることで)チーム全体の設計力が上がった
- 共通認識を作ったことでPRレビュー時の意見割れが減りPRレビューが開発スピードのボトルネックになりにくくなった

です。
是非チームで取り入れて、チーム全体の開発力向上につながれば良いなと思います。
[Swift] コードで書くUIView、 ボタンを押すと画面遷移 備忘録

```swift

override func viewDidLoad() {
  super.viewDidLoad()
  Button()
}

func Button() -> UIView?{
  let button = UIButton(frame: CGRect(x:self.view.frame.maxX - 50, y:0, width:50, height: 50))
  button.backgroundColor = UIColor.black
  button.setTitle("追加", for: .normal)
  //追加ボタンがタップされた際に画面遷移をする(buttonTappedはタップされた際に呼び出される関数)
  button.addTarget(self, action: #selector(ViewController.buttonTapped(sender:)), for: .touchUpInside)
  view.addSubview(button)
  return view
}

@objc func buttonTapped(sender:UIButton){
  let storyboard: UIStoryboard = self.storyboard!
  let second = storyboard.instantiateViewController(withIdentifier: "secondView")
  self.present(second, animated: true, completion: nil)
}
```

StoryboardIDを記入
<img width="741" alt="スクリーンショット 2020-03-05 17.49.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517291/72115873-1a4f-5982-d256-9594e1ee4209.png">

以上

追記
このやり方よりも、R.swiftは画面遷移にとても便利
[R.Swift使い方　備忘録](https://qiita.com/akidon0000/items/cadaf7c1b61e78f81a7c)
CSSの基本

# セレクタ
セレクタの構造は、セレクタ/プロパティ/値からなっている。
基本の形はセレクタ { プロパティ: 値; }となり、セレクタ構造を示すために{}を、
プロパティの値を指定する場合は、 :（コロン）を使い、値の最後には;（セミコロン）を書く。

```
p {
  color: black;
}
```

# class属性
HTML要素に対して個別に名前を付けることができる機能。
例えば、＜p＞...＜/p＞に対して"message"というclass名を付与する場合は、以下のように記載。

```
<p class="message">
  aaa
</p>
```

# classセレクタ
HTMLで指定したclass名をセレクタとして使用することができる。
classセレクタを指定する場合は、.クラス名のような形で指定。

```
.message {
  color: black;
}
```

# id属性
class属性同様に、HTML要素に対して個別に名前を付けることができる機能。
例えば、＜p＞...＜/p＞に対して"message"というid名を付与する場合は、以下のように記載。

```
<p id="message">
  aaa
</p>
```

# idセレクタ
HTMLで指定したid名をセレクタとして使用することができる。
idセレクタを指定する場合は、#id名のような形で指定。

```
#message {
  color: red;
}
```

# classとidの使いどころの違い
class
同じclass名のものを複数回使用できる
一般的なセレクタとして使用できる

id
同じid名のものは複数回使用できない
ある特徴的な部分など、ここぞというタイミングで使用するセレクタ

# コメントアウト
プログラムの中に、「メモ」を埋め込むための機能。
コメントアウトされた文字列は、コードとしては認識されない。

# リセットCSS
インターネットを閲覧するためのブラウザにはいくつかの種類があるが、それぞれ独自のCSSをデフォルトで持っている。つまり、同じ＜h1＞...＜/h1＞で指定しても、ブラウザごとに文字の大きさが異なったり上下の幅が異なったりする。
何らかのトラブルで、Webページ作成者が用意したCSSファイルが読み込まれなかった時、
ブラウザ側で最低限の見た目を保障するために、各ブラウザが独自のデフォルトCSSを持っている。
しかし、これが時に、Webページ作成者が用意したCSSファイルと影響しあって見た目を崩してしまうことがある。
これを防ぐため通常、各ブラウザが用意しているデフォルトのCSSを上書きするCSSを書いておく。

```
body {
  background-color: #f0f0f0;
  font-size: 14px;
  color: #333;
  margin: 0 auto;
}
h1,h2,h3,h4,h5,h6,p {
  padding: 10px 0;
  margin: 0;
}
```
【iOS】FirebaseのFriendly-Chatチュートリアルの pod install でエラーが出るとき


FirebaseのCodelabでのチュートリアル Friendly Chat で pod install でエラーが出るのは、Podfileが古いからのようだった。
https://codelabs.developers.google.com/codelabs/firebase-ios-swift/?hl=ja#2

```
Pod::StandardError - [Bug] Failed to find known source with the URL "trunk"

[!] Oh no, an error occurred.
```

一度、Podfile, Podfile.lockを削除して、そのディレクトリで`pod init`し、そこに元の情報を正しくコピペしてやると成功した。

<img width="591" alt="スクリーンショット 2020-03-05 17.03.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/60799e2a-d2f7-9f43-6bd3-d49da4e9e70a.png">

```file:podfile
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'FriendlyChatSwift' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for FriendlyChatSwift
  # FriendlyChat Codelab

pod 'Firebase/AdMob'
pod 'Firebase/Analytics'
pod 'Firebase/Auth'
pod 'Firebase/Database'
pod 'Firebase/RemoteConfig'
pod 'Firebase/Storage'
pod 'Firebase/Crashlytics'
pod 'GoogleSignIn'


end

```
bootstrapでdropdownが正常に動作しない場合

デベロッパーツールで見ると、cosoleのところに下記のようなエラーが出ていた。

```
Uncaught Error: Bootstrap's JavaScript requires jQuery at
```

要は先にjQueryを読み込めということらしいです。

```html
<header>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</header>
```


上記の場所で下記を挿入してjqueryを読み込めば正常に動作するようになりました。

```html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
```
STM32CubeIDEを使ってみよう How To STM32CubeIDE 日本語版 (12) ADCを使ってみよう

STM32CubeIDEを使ってみよう How To STM32CubeIDE 日本語版の続きです。
今回は、ADCです。
初めにDigiKey社のYoutubeと記事があるのでこちらをお勧めします。
https://www.digikey.com/en/maker/projects/getting-started-with-stm32-working-with-adc-and-dma/f5009db3a3ed4370acaf545a3370c30c

**投稿準備していたのですが、月刊トランジスタ技術2020年3月号にSTM32特集が組まれSTM32CubeIDEのプログラミングガイドブックもついていましたので、こちらを踏まえて修正しています。
(特集の話は昨年の夏ごろから聞いていただけにやっと・・・）

## ADCとは
まずは、ADCとは何かです
今までSTM32においてスイッチなどの値を1か0として扱ってきました。
しかし、世の中にはアナログの値というものが存在します。
例えば、照度などです。
これらを電圧に変換し一定の分解能において、デジタルデータとして見える化します。
これがアナログデジタルコンバート　ADCです

なお、分解能を上げることで細かい値を知る事も可能です。
今回は12bit　4096段階とします。

マイコンでは、アナログ⇒デジタル変換できるポートは限られています
仕様を見てみましょう。

STM32F401REの仕様から抜粋しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/db238b1b-c78c-8c57-6654-f6ca5df98c4c.png)

4. FT = 5 V tolerant except when in analog mode or oscillator mode (for PC14, PC15, PH0 and PH1)

PC14, PC15, PH0、PH1以外は５V入力でも使えるようです
マイコンは3.3Vなので、５Vを入れても最大値の4096などになりますが、5V対応ならば、0~5Vまで計測可能です。


##配線
今回は可変抵抗を使用します。
左右のピンを3.3vとGND、真ん中のピンをA0につなぎます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/416d9db1-81e2-9012-a35d-4e543f26353c.png)

前回の続きの場合は、こうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/27ff2911-80a8-aec9-04f9-7e29b7d844ed.png)

##Pinout&Configuration
それでは、設定しましょう。

まずは、ピンマップからPA0にADC1_IN0を設定します。
左のADC1 Mode and ConfigurationのIN0にチェックを入れても同じです、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/4ca7bf2c-87ae-6522-abb1-fa7367c97e23.png)
これでコード生成をします。

##コード追加
追加するのは以下です

```
float adcval;
uint8_t adcout[12];
```

adcvalとadcoutという二つの値を用意します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/bdea0b29-cb83-c687-4456-ce5aace64813.png)

```
HAL_ADC_Start(&hadc1);
HAL_ADC_PollForConversion(&hadc1, 100);
HAL_ADC_Stop(&hadc1);
adcval= HAL_ADC_GetValue(&hadc1);
```

最初にADCをスタートします。
ADCの変換をします。
*Timeの100は適宜変更しましょう。
そして、ADCをストップします。
*これも無くても良いと思います。
最後に、値を出力します。

```
sprintf((char*)adcout,"ADCVAL %u \n\r",
  (unsigned int)adcval);
printf(adcout);
HAL_Delay(500);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/fb14be97-5a6e-d6a2-8128-e1caa70ab5a4.png)

最後に、値をシリアル出力します。

この状態でコンパイルします。
すると、温度や湿度は変化しますが、ADCの値が変化しません。
これは、While分の中にADCを読み取る機能がないからです。
それでは、Whileの中に追加してみましょう。

すると、
無事変化しますね。

##OLEDへ表示しよう
次はOLEDに表示させてみましょう。

```
/*ADC VAL*/
ssd1306_SetCursor(5,45);
ssd1306_WriteString(adcout,Font_11x18,Black);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/cb2785cf-c171-dbd6-4a21-98e8efe149ea.png)

これで完成です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/a109b09b-d25f-7266-0846-f126698b1682.png)

一定周期で温度湿度、ADCの値を表示するようになりましたね。
未経験エンジニアが覚えておきたい用語

概要
--
IT業界に飛び込んで約半年、いろいろな技術を勉強してきました。
ただ、これやったけどなんだっけという事が多くなったので、備忘録として基本的なことを書いていきます。

JAVA
--------
・オーバーライド
　→スーパークラスで定義されているメソッドをサブクラスで上書きする
・オーバーロード
　→引数や戻り値が異なるが名称が同一のメソッドを定義する
・ポリモフィズム
　→同じ操作でも扱う対象によって振る舞いが異なる仕組み
・継承
　→あるクラスを基に新しいクラスを定義する
・オブジェクト
　→クラスを複数定義しクラスから生成したオブジェクトを利用。
　【特徴】　再利用性が高い、仕様変更に強い
・抽象クラス
　→抽象メソッド１つ以上定義したクラス　
　【特徴】　abstractを指定、メソッドを定義できる、インスタンス化出来ない、実装は持たない
・カプセル化
　→publicやprivateなどのアクセス修飾子を適切に設定し、クラスに対するアクセス制限を行う
　【特徴】　クラスのアクセスが統一されるため、独立性が高まる、バグを未然に防げる、クラスの変更が簡単
・ArrayListとLinkedListの違い
　→ArrayListはアクセスに強い、LinkedListは追加や削除に強い
　【理由】　
　①ArrayListはListインターフェイスを実装しており、配列の要素番号があるため検索が容易にできる。
　②LinkedListは要素同士が前後に持っているリンク情報で数珠状態でつながっているため情報の追加などは容易にできる。
DB周り
--
・SQL内部結合と外部結合の違い
　→inser joinは条件が一致していて、テーブルに値があるものを持ってくるが、outer join は値が一方のテーブルにしかなくても取得ができる。
・インデックス
　→インデックスを使うとデータの参照が高速になる
・シーケンス
　→データを一位に特定する列を作る時に使う（ID・学生番号などの重複させたくない時）
WEBアプリケーションの脆弱性
--
・アプリケーション・バッファーオーバーフロー
　→大量のファイルを送りつけてシステムダウンを起こす
・XSS
　→ユーザがwebページにアクセスすることで不正なスクリプトが実行されてしまう。その結果不正ログインなどが実行される。
・CSRF クロスサイトフォージェリー
　→webアプリケーション利用者が意図しない処理が実行されてしまう。意図しないWEBアプリケーション上の処理実行。
そのほかいろいろ
--
・バッチ処理
　→複数のプログラムからなる作業を一連の手順を登録しておいてまとめて連続的に実行すること。集計処理とかバッチ処理！
・デプロイ
　→特定の環境下でアプリケーションやシステムを使えるようにすること。

最後に
--
ほんとに初期の部分をまとめてみました。
言葉はわかるけど説明してっていわれたら出来なさそうとか思う用語がちょいちょいありました。
根拠を持って実装ができるといいね！
リストなどのアイテムが無い時に「ありません」を表示させる

頭にアイテムの無い時の状態を入れておいて、アイテムが追加されたらその表示だけにする。

```html:html
<ul>
  <li>ありません</li>
  <li>アイテム1</li>
  <li>アイテム2</li>
  <li>アイテム3</li>
</li>
```
```css:css
ul > li:first-child() {
  display: none;
}
ul > li:last-child() {
  display: inherit;
}
```
アイテム1,2,3があれば、

>
+ アイテム1
+ アイテム2
+ アイテム3

なければ、

>
+ ありません

という表示になる。
laradockで作成したプロジェクトがgithubで開けない

こちらの記事を参考に環境構築
[LaradockをWindows 10 Homeにインストール](https://pg-happy.jp/laradoc-windows10-home-install.html)

デイレクトリ構成はこんな感じ
>
laradockpjt/
├app(laravelのプロジェクト)
├laradock

ローカルでの環境構築を終えてgithubにpush

しかしlaradockpjt直下のappフォルダが開けない（非活性？になってる）

## 原因
最初にlaradockをsubmoduleとしてクローンしてない
（gitのサブモジュール機能に関して全くの無知だった…）

```
git clone -b LaraDock-ToolBox https://github.com/LaraDock/laradock.git
//こっちだと開けない
git submodule add　https://github.com/LaraDock/laradock.git
//こっちのコマンドでlaradockをサブモジュール化
```

後は手順通りに進めるとOK！


すでに環境構築済みだったので巻き戻しにかなり時間食ってしまった…
カメラで撮影した写真をリサイズしてOneDriveに保存する＆Teamsに投稿

# 何がしたかったか
スマホのカメラで撮影した写真を、会社で使っているOneDrive for Businessにアップロードしてメール/Teamsで通知というようなことをやりたいとき、スマホのカメラの画像だとどうしても大きくてメールや投稿につけたときに読み込みが遅くなる/ダウンロードに時間がかかってしまう。
というようなことがあるかなと思います。(と、Twitterの友人が言っていました)

そのような場合に、写真をリサイズ/軽量化したくなるんだけど、Office 365の枠内だとそういうコネクタやアクションがないんですよね。。
Encodian (3rd party) 使えばいいのですが、純正以外禁止されているパターンもあり。

今回はリサイズや軽量化とはちょっと違うけど、目的を達成できるFlowをご紹介です。

**Power Automate**をつかって、**ファイルのサムネイル**を保存しなおします。

# Flow
超簡単です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/5a356766-d106-5c17-1839-8ea330339fbf.png)


これだけ。最初にアップロードした写真のサムネイルを取得して、それを保存しなおすことで、サイズを小さくしたファイルをOneDriveに残せます。
**[2020/3/5:修正]**
Teamsに通知したい場合、HTMLのメッセージでは画像のリンクしか載せられないので、**Adaptive Cardを使います**


ちょっとだけ、数式を使わないと取れない部分があるので記載します。

**- 添付したファイル名**

```
triggerBody()?['file']?['name']
```
取れそうな気もするのですが、私の環境だと表示されなかったので念のため。

**- 保存先のパス＋ファイル名**
ここは用途に応じてですが、私はOneDriveのルート(直下)に、**幅(px)-高さ(px)ファイル名.拡張子** の形式で保存しました。
その際の数式は、以下のようになります。

```
concat('/',body('Get_file_thumbnail')?['Width'],'-',body('Get_file_thumbnail')?['Height'],triggerBody()?['file']?['name'])
```
**- Adaptive Card用のJSONとdatauri**
ここでは単純にカードの中にImageだけが入ったものを送ります。
その場合

```message.json
{
    "type": "AdaptiveCard",
    "version": "1.0",
    "body": [
        {
            "type": "Image",
            "altText": "",
            "url": "@{datauri(body('Get_file_content_using_path'))}"
        }
    ],
    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json"
}
```
この短いAdaptive CardをComposeしておいて、あとはTeamsのメッセージ部分に挿入します。


# 通知部分
**[2020/3/5:大幅修正]**
Teamsへの投稿で写真を載せたい場合、サムネイルのUrlだとあとから表示されなくなる、そもそもSharePoint/OneDriveの画像は表示されない などの制限があります。
そこで、Adaptive Cardを利用します。(**ここポイント！！**)
Adaptive Cardにすると、画像のコンテンツのdataUriをCardのImageブロックに表示させることができます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/92eb8487-e2c3-42a2-4840-8d849cb319f5.png)

実行すると・・・
![out1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/f5520e4a-71ef-14b6-32c9-4edfe1233d43.gif)

やったぜ！！
# 補足
作成したファイル (もともとサムネイル)は、ダウンロードしたらJPEGに拡張子を変更すれば写真ビューワーなどで表示できるようになります。
(900KBくらいの写真から、生成されたサムネイルは60KBほどでした)
【随時更新】Markdown記法とTyporaショートカット【はてな、Qiita対応】

この記事やQiitaで使われている
Markdown記法の備忘録を残します

また、僕が使っているMarkdownが捗るエディタも載せておきます

iphoneから書きたい人[>> #Type](https://apps.apple.com/jp/app/type/id1214613873)

Macから書きたい人[>> Typora](https://typora.io/)

## 段落と改行(Enter、**⇧**+Enter)

段落はEnterで一行分空白を作る
改行は改行したい行の末尾にスペース2つで表現できます
なお、はてなブログに関しては
Typoraから貼り付けを行う際に
末尾にスペース×2がないと改行されません
※Qiitaは**⇧**+Enterのみで改行できます

#### 記述例

```
ここで改行  ＃ここにスペースが2つあります
前の行で改行しています
＃Enterで段落分けができます
これは段落です
```

#### 表示例

ここで改行
前の行で改行しています

これは段落です

## 見出し(⌘+1~5)

見出しは行頭にシャープをつけることで表現できます
シャープの個数が見出しのレベルに値します

#### 記述例

```
# 見出し1
## 見出し2
### 見出し3
#### 見出し4
##### 見出し5
```

#### 表示例

# 見出し1
# 見出し2
### 見出し3
#### 見出し4
##### 見出し5

## 強調(⌘+I、⌘+B)

文字の強調はアスタリスクもしくは
アンダーバーで文字を囲うことで表現できます
囲う個数が1つでitalic、2つでbold
3つでitalic+boldを表します

#### 記述例

```
これが*italic*です
これが**bold**です
これが***italic+bold***です
```

#### 表示例

これが*italic*です
これが**bold**です
これが***italic+bold***です

## コードブロック(⌥+⌘+C)

コードブロックはバッククォート3つで
文字を囲うことで表現できます

#### 記述例

```
​```
これがコードブロックです
​```
```

#### 表示例

```
これがコードブロックです
```

## 区切り線(⌥+⌘+-)

区切り線は3つ以上の連続した
ハイフン、アンダーバー、アスタリスクで
表現できます

#### 記述例

```
この行の下で区切ります
---
ここから新しいセクションです
```

#### 表示例

この行の下で区切ります

------

ここから新しいセクションです

## リンク(⌘+K)

リンクは角カッコの中に表示文字列
丸カッコの中にURLで表現できます

#### 記述例

```
[>> Markdownのwikiです](https://ja.wikipedia.org/wiki/Markdown)
```

#### 表示例

[>> Markdownのwikiです](https://typora.io/)

## 引用(⌥+⌘+Q)

引用は行頭の大なりによって表現される
なお2つ連続することで二重引用も表現できます

#### 記述例

```
>これが引用です
>>これは二重引用です
```

#### 表示例

> これが引用です
>
> > これが二重引用です

Markdownを使えるようになると
ドキュメントの編集が捗るので
ぜひ使えるようになりましょう

はてなブログやQiitaに関しては
ここで紹介しているものでほぼ事足りますが
また頻繁に使うものが増えてきたら
随時更新していきます
Solidityでの文字列比較

# 記事の内容
solidityでstringの値が一致するかを確認する方法をメモ
String Equality Comparisonパターンというデザインパターンみたいです。

# 普通にやってみる
とりあえず、普通に比較してみます。

~~~
    function equals(string memory a, string memory b) pure public returns (bool) {
        return a != b;
    }
~~~
この比較方法だとコンパイルエラーが出てしまいます。

~~~
TypeError: Operator != not compatible with types string memory and string memory
return a != b;
~~~

bytes型に変換してやってみます。

~~~
    function equals(string memory a, string memory b) pure public returns (bool) {
        return bytes(a) != bytes(b);
    }
~~~
これもコンパイルエラーになります。

~~~
TypeError: Operator != not compatible with types bytes memory and bytes memory
return bytes(a) != bytes(b);
~~~

# やり方
文字列のハッシュ同士を比較する

~~~
    function hashCompareWithLengthCheck(string memory a, string memory b) pure internal returns (bool) {
        if(bytes(a).length != bytes(b).length) {
            return false;
        } else {
            return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
        }
    }
~~~

一文字ずつ比較する方法もあるようですが、文字列が長くなった場合に消費するGasが増えてしまうようです。
その為、それぞれのハッシュ同士を比較することでGasの消費を抑えて効率的に文字列の比較が出来るようです。

# StringUtils
JavaなどにもあるStringUtilsが提供されているようです。
こちらをインポートすることで実装することなく、色々な文字列操作が出来るようです。

[StringUtils](https://github.com/Arachnid/solidity-stringutils)
【Rails】/users/:id ではなく/:username にする

# 理想
<img width="571" alt="スクリーンショット 2020-03-05 16.54.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212678/519534f4-03f0-83a5-e6ff-9ddd25f110b0.png">

---
## やり方
to_paramを使用する

```ruby:user.rb
class User < ActiveRecord::Base
  validates_presence_of :username
  validates_uniqueness_of :username, case_sensitive: false

  def to_param
    username
  end
```
---
```ruby:users_controller.rb
class UsersController < ApplicationController
  def show
    @user = User.find_by(username: params[:id])
  end
end
```

```ruby:routes.rb
  resources: users, path: '/', only: [:show]
```
ASP.NET Core MVCでFullCalendarを表示

# はじめに
ASP.NET Core MVC(.NET Core 3.1)でFullCalendarを表示する方法について説明します。

# プロジェクト作成
1. VS2019で「ASP.NET Core Web アプリケーション」のプロジェクトを選択。
2. 種類の選択で「Web アプリケーション（モデル ビュー コントローラー）」を選択。

# FullCalendarのダウンロードとセットアップ
1. https://fullcalendar.io/ からzipファイルのダウンロード。
2. zipを解答し、packages内のディレクトリを作成したプロジェクトの「wwwroot\lib」内にコピー。  
例：wwwroot\lib\fullcalendar-4.4.0\packages

# FullCalendarの設定
今回は解答したzip内の「examples\daygrid-views.html」を参考に設定。
表示するカレンダーの種類によって、参照するcssとjsが変わる。

_Layout.cshtml内の設定。

```_Layout.cshtml
<head>
    ～
    <link href="~/lib/fullcalendar-4.4.0/packages/core/main.css" rel="stylesheet" />
    <link href="~/lib/fullcalendar-4.4.0/packages/daygrid/main.css" rel="stylesheet" />
    <link href="~/lib/fullcalendar-4.4.0/packages/timegrid/main.css" rel="stylesheet" />
    <link href="~/lib/fullcalendar-4.4.0/packages/list/main.css" rel="stylesheet" />
</head>
<body>
    ～
    <script src="~/lib/fullcalendar-4.4.0/packages/core/main.js"></script>
    <script src="~/lib/fullcalendar-4.4.0/packages/interaction/main.js"></script>
    <script src="~/lib/fullcalendar-4.4.0/packages/daygrid/main.js"></script>
    <script src="~/lib/fullcalendar-4.4.0/packages/timegrid/main.js"></script>
    <script src="~/lib/fullcalendar-4.4.0/packages/list/main.js"></script>

    @RenderSection("Scripts", required: false)
</body>
```

Index.cshtmlの設定

```Index.cshtml

@*どこか適当な場所に記述。ここにカレンダーが表示される*@
<div id="calendar"></div>

@section Scripts {
    <script type="text/javascript">
        document.addEventListener('DOMContentLoaded', function() {
            var calendarEl = document.getElementById('calendar');

            var calendar = new FullCalendar.Calendar(calendarEl, {
                plugins: [ 'interaction', 'dayGrid', 'timeGrid', 'list' ],
                header: {
                    left: 'prev,next today',
                    center: 'title',
                    right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth'
                },
                defaultDate: '2020-02-12',
                navLinks: true, // can click day/week names to navigate views
                businessHours: true, // display business hours
                editable: true,
                events: '@Url.Action("GetAllEvents")'
            });

            calendar.render();
        });
    </script>
}
```

HomeController.csの設定
HomeController内に追記する。

```HomeController.cs
public IActionResult GetAllEvents(DateTime start, DateTime end)
{
    var events = new List<Event>
    {
        new Event
        {
            Title = "てすと",
            Start = DateTime.Parse("2020-02-18 00:00:00"),
            End = DateTime.Parse("2020-02-20 00:00:00"),
        }
    };

    return new JsonResult(events);
}
```

Eventクラス

```Event.cs
public class Event
{
    public string Title { get; set; }

    public DateTime Start { get; set; }

    public DateTime End { get; set; }
}
```

# FullCalendarの表示

あとは実行すればカレンダーが表示されます。
GetAllEventsのstartとendには表示されるカレンダーの始まりと終わりの日付が入ってくるので、
それを利用すればGetAllEvents内で範囲内のイベントの取得が可能になります。（DBを参照するなど）

# ハマったこと
GetAllEventsで返すJsonResultは配列の必要があるのですが、
それに気が付かずにずっとEventクラスをそのまま返していて、なかなかイベントが表示されずにハマりました。
HANSONTABLEのセル入力における日本語対応について

# HANSONTABLEの２バイト入力への対応

ハンズオンはブラウザ上に表形式のインターフェイスを提供するありがたい部位です。
これを使用するにあたり、日本特有である日本語入力時の不具合があり
かなりハマったので、備忘録として残しておきます。

---
まずはハンズオンテーブルとは・・
https://handsontable.com/

JavaScript data grid that looks
and feels like a spreadsheet.
Minimalistic, Excel-like grid component for web apps.
Available for pure JavaScript, React, Vue, and Angular.

---
## 問題点
そもそも英語圏の部品なので、日本のように全角半角がある場合の対処ができていない。
### 現象
ハンズオンで表示したテーブルのセル（テキスト）に対して、フォーカスを当てただけの状態で、ＩＭＥをＯＮ（日本語入力）した際、最初の１文字が入力されない。


| col1 |col2|col3|
|:-----------------:|:------------------:|:------------------:|
| inputText|readonly|dropdown|
| inputText|readonly|dropdown|

上記でcol1のinputTextにフォーカスだけを当て、「あいう」と入力すると
実際にセットされる値は「いう」となる。
ＩＭＥＯＦＦの場合は問題なく動作します。
「abc」と入力するとそのまま「abc」とセットされます。
ちなみに、セルをダブルクリックし、入力モードにすると日本語でも問題ありません。

### 解決策
色々考えた結果、フォーカスだけが当たった状態をなくしました。

```javascript:afterSelectionEnd
afterSelectionEnd: function (r, c, r2, c2) {
	//単一セルが選択されたとき
	if (r != r2 || c != c2) {return;}

	//セルエディタが'textEditor'のみ強制的に入力モードにする
	//あらかじめ入力テキストのEditorをそろえて
	var celleditor = this.getCellEditor(r, c)
	if (celleditor == null) {return;}
	if (this.getCellMeta(r, c).readOnly) {return;}
	if (celleditor != 'textEditor') {return;}

	//強制入力モード
	var acteditor = this.getActiveEditor();
	var cellval = this.getValue();
	acteditor.beginEditing();
	this.setDataAtCell(r, c, cellval, 'system');
}
```
本来は、acteditor.beginEditing();するだけでよさそうなものでしたが、なぜか入力していた文字が消える現象が発生します。それも、消えるときと消えない時がある・・。
なので
var cellval = this.getValue();
で現在値を取得しておき、強制入力モードにしてから、再度現在値をセットしました。
これで、動き的には違和感がなくなりました。矢印キーでの移動も可能です。

ちなみに、acteditor.enableFullEditMode();を使えばよいという掲示板も見かけましたがそれだとうまく動作しません。
また、afterSelectionのイベントもありますが、afterSelectionEndのイベントでしかうまく動作しませんでした。

たぶん、hansontableを使うと同じ壁にぶつかる人がいてるとおもうので、何かのお役にたてればと思います・・。
[git] 複数のリモートリポジトリを扱う&サブモジュール&複数のリモートリポジトリのサブモジュール

複数のリモートリポジトリを扱うための説明です．
さらにサブモジュールの扱い方も説明し，サブモジュールのリモートリポジトリを複数にする方法までまとめます．

GitHub＋GitLabなどにしてサーバーダウンに備えましょう！

# 複数のリモートリポジトリを登録，同時にpushする
GitHub＋GitLabとか，サーバーダウン対策にもなると思います．次のコマンドを1回だけ操作すると`.git/config`が追加されます．

```bash
git remote set-url origin --add (2つめのリモートリポジトリのurl)
```

# fetchしてくるリポジトリ
上記の方法でやると，`.git/config`が

```
[remote "origin"]
	url = git@(1つめのリモートリポジトリのurl):username/hoge.git
	fetch = +refs/heads/*:refs/remotes/origin/*
	url = git@(2つめのリモートリポジトリのurl):username/hoge.git
```
のようになるが，この順番に注意．

```bash
$ git remote -v
origin	git@(1つめのリモートリポジトリのurl):username/hoge.git (fetch)
origin	git@(1つめのリモートリポジトリのurl):username/hoge.git (push)
origin	git@(2つめのリモートリポジトリのurl):username/hoge.git (push)
```
1つめの方をfetchしてくるようになっている．remote-tracking branchの設定に起因？


# リポジトリ内に別のリポジトリ
リポジトリ内で別のリポジトリを管理したいとき．特定のcommitを参照できます．

- リポジトリにサブモジュールを追加する

```bash
git submodule add (リモートリポジトリのurl) (必要ならディレクトリ名)
```
`.gitmodules` にそのサブモジュールの情報が入ります．

## 別のローカルリポジトリで，追加済みのサブモジュールを追加する
```bash
git submodule update -i
```

- リポジトリ内のサブモジュールを全てmergeする
大元のリポジトリでgit pullするとサブモジュールのリポジトリもfetchのみされるので，それを全て一括mergeしたい場合

```bash
git submodule foreach git merge
```

- サブモジュールを最新のブランチにする（全てgit pullする）
- 
```bash
git submodule foreach git pull origin master
```

(参考)
-- https://qiita.com/sotarok/items/0d525e568a6088f6f6bb
-- https://qiita.com/kinpira/items/3309eb2e5a9a422199e9

# submoduleで複数のリモートリポジトリ
同様にsubmoduleのリポジトリ内で

```bash
git remote set-url origin --add (2つめのリモートリポジトリのurl)
```
してやればよい．（大元のリポジトリの）`.git/modules/hoge/config`に`.git/config`と同様の情報がある．
undefined local variable or method で嵌まった

rails testの勉強をしつつ
下記のエラーで嵌まり
contorollerのどこが悪い‥‥‥のかと見ていて嵌まったのですが
復習しつつ上から追っていったところ
routesの　get 'welcome/index'を#で
動かさないようにしていたということ忘れ恐ろしく時間をかけてしまった

$ rails test
Run options: --seed 48513

# Running:

..E

Error:
WelcomeControllerTest#test_should_get_index:
NameError: undefined local variable or method `welcome_index_url' for #<WelcomeControllerTest:0x000000000b951ba8>
    test/controllers/welcome_controller_test.rb:5:in `block in <class:WelcomeControllerTest>'


bin/rails test test/controllers/welcome_controller_test.rb:4
@Builder(Lombok)の使い方

#Lombokの@Builderアノテーションとは？
- JavaのClassに@Builderを付与することで、Builderメソッドを生成してくれる。
- 引数のながーいコンストラクターを用意しなくてすむ。

```Java
import lombok.Builder;

//呼び出される側のJavaClass
@Builder
public class Employee {
	private String name;
	private int syainId;
	private int age;
	private String position;
	private String status;
}
```

```Java
//Builderを呼び出す側
Employee employee = Employee.builder()
        .name("Kohei Sato")
        .syainId(101)
        .age(32)
        .position("developper")
        .build();
```

#初期値は？？
上記の例では、statusを指定していない。→ statusはnullになってしまう。
Stringなのでnullになっているが、intは０, booleanはfalseになるっぽい。


#初期値の指定方法１：内部クラス
- 以下の通り,```ClassName+Builder```のクラスで、デフォルト値を指定可能

```Java
@Builder
public class Employee {
    private String name;
    private int syainId;
    private int age;
    private String position;
    private String status;
    
    public static class EmployeeBuilder {
    	private String status = "Active";
    }
}
```

#初期値の指定方法2：Defaultアノテーションを利用
- アノテーション付与で変数宣言時に初期値を指定可能。

```Java
@Builder
public class Employee {
	@Builder.Default private String name = "No Name";
	@Builder.Default private int syainId = 0;
	@Builder.Default private int age = 30;
	@Builder.Default private String position = "Normal";
	@Builder.Default private String status = "Active";
}
```
こっちの方が個人的に見やすい。

# 参考
https://reinhard.codes/2016/07/13/using-lomboks-builder-annotation-with-default-values/
CWLでblastをかける

CWL初級者にとってよく詰まる部分にfileの入出力がある。

```shell
python hogehoge.py -in infile -out outfile
```
のようにコマンドラインで指定するようなシンプルな場合は簡単だが、入力ファイルがちょっと特殊な場合一気に難しくなる。

生物学分野では広く使われるblastだが、blastではindexファイルを以下のように指定する。

```shell
blastn -query hoge.fasta -db huga.fasta
```

ここで注意しなければいけないのは`huga.fasta`の部分で、blastを走らせるためには `huga.fasta` だけでなく `makeblastdb` コマンドで作った以下のようなindexファイルを`huga.fasta`を同じディレクトリに用意する必要がある。 

```
huga.fasta
huga.fasta.nsd
huga.fasta.nsi
huga.fasta.nhd
huga.fasta.nhi
huga.fasta.nhr
huga.fasta.nin
```

CWLではホスト側のデータは明示的に読み込まないとマウントしてくれないため、単に`huga.fasta`だけinputしても`indexファイルが見つかりません`と言われてしまう。

色々試行錯誤した結果、[NCBIのPGAPパイプライン](https://github.com/ncbi/pgap/blob/master/progs/taxonomy_check_16S.cwl)に参考となる記法が見つかったのでそれを参考にした。

```blast.cwl
cwlVersion: v1.0
class: CommandLineTool
baseCommand: /root/ncbi-blast-2.10.0+/bin/blastn
requirements:
  - class: InitialWorkDirRequirement
    listing:
      - entry: $(inputs.blastdb_dir)
        writable: False

inputs:
  blastdb_dir:
    type: Directory?
  blastdb:
    type: string?
    inputBinding:
      prefix: -db
      valueFrom: $(inputs.blastdb_dir.path)/$(inputs.blastdb)
  blastinput:
    type: File
    inputBinding:
      prefix: -query
  outfmt:
    type: string
    inputBinding:
      prefix: -outfmt 
  outfile:
    type: string
    inputBinding:
      prefix: -out 
  evalue:
    type: string
    inputBinding:
      prefix: -evalue
  max_target_seqs:
    type: string
    inputBinding:
      prefix: -max_target_seqs
  num_threads:
    type: string
    inputBinding:
      prefix: -num_threads

outputs:
  blast_out:
    type: File
    outputBinding:
      glob: blast_result.tsv
```

`InitialWorkDirRequirement` でディレクトリをワークフロー実行時にマウントしているのがポイント。
[@manabuishiirb さんのエントリ](https://qiita.com/manabuishiirb/items/8a4385cefdae996c943b)とかをみると `InitialWorkDirRequirement`は


> あくまで ステージング用途で使うものである。
ホスト側のディレクトリを、ワークフロー実行時にマウントするという用途のためにあるわけではない。

とか書いてあるのでもっとスマートな書き方があるのかもしれない。