OmniAICreator/Qiita-1.07M huggingface dataset:
Huobi WalletでIOSTアカウントを作る(iOS/Android共通)

この記事ではIOSTに対応している（それ以外のトークンも使えます）Huobi Walletで
・IOSTアカウントの作成
・IOSTアカウントのインポート
をする方法を解説します。iOS/Androidでそこまで大きな違いは無いので共通の手順として書きます💁🏻‍♂️

#アプリの取得方法
公式サイト👇🏻
https://www.huobiwallet.com/ja/
iOSはここから👇🏻
https://itunes.apple.com/jp/app/id1433883012
Androidはここから👇🏻
https://play.google.com/store/apps/details?id=com.huobionchainwallet

#HuobiWallet自体の作成
アプリを起動するとこんな感じの画面が出てきます。
![Screenshot_2019-03-13-07-52-49-271_com.huobionchainwallet.png](https://qiita-image-store.s3.amazonaws.com/0/39453/a9e17731-f6b4-e94a-35a8-fa0b1518ef3f.png)
ここで言っている「ウォレット」というのはHuobiWalletのことで、IOSTアカウントのことではありません。注意。
1. ウォレットの新規作成
👉**HuobiWalletを今まで使ったことが無い**方はこちらです（IOSTアカウントを持っていたとしてもこちらを選択）
2.ウォレットのインポート
👉**既に他のスマートフォンでHuobiWalletを使っていて**、新しいスマートフォンに移したい場合、はこちらです。

では、「ウォレットの新規作成」をタップして次に進みましょう。
利用規約を同意したら、パスワードの入力を行います。**当たり前ですがこのパスワードを忘れたり他人に教えたりはしないでくださいね。自殺行為です。**
パスワードの入力が終わると復元フレーズでバックアップを取るか確認されます。
![Screenshot_2019-03-13-08-01-04-521_com.huobionchainwallet.png](https://qiita-image-store.s3.amazonaws.com/0/39453/acf155d2-919b-bd65-0e7a-f533d08981f4.png)
パスフレーズとはなんぞや？と思う方もいるかもしれません。Ledger Nano Sを使ったことがある方はご存知かもしれません。
12個の復元フレーズ（単純な英単語）とその並び順を覚えて（紙に書き留めて）おくことで、パスワードを使わなくてもウォレットを復元できる機能です。HuobiWalletはこの機能に標準で対応していますし、かつ**パスフレーズの表示画面はスクショが出来ない徹底ぶり**です。基本的には**パスフレーズ機能、使おうね！**👨🏻

さて、これでウォレット自体の作成は完了しました。ここからIOSTアカウントの作成を行います。

#IOSTアカウントの無料作成
IOSTアカウントは実は通常は無料で作れないのです。20IOSTくらいのコストが必要なんです。が、HuobiWalletは運営のHuobiがその費用を負担してくれるので**期間限定で無料で**作れるのです（1つのお財布アカウントに1つだけ）
太っ腹やなほんと！
※IOSTの値段も上がっているのでいつ無料期間が終わるかはわからないですよ
![InkedScreenshot_2019-03-13-12-10-09-789_com.huobionchainwallet_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/39453/eac75db9-2241-7eb0-7701-559d23b3fe54.jpeg)
画面下のメニューから「総資産」を選んで、IOSTの行の付近に「IOSTを手動で…」という表示があるのでタップしてください。もし出てなかったらとりあえずIOSTのロゴのところをタップすれば出てきます。
![Screenshot_2019-03-13-08-07-13-488_com.huobionchainwallet.png](https://qiita-image-store.s3.amazonaws.com/0/39453/1c08b638-2640-a7b8-b79b-f24580dbd1e9.png)
1.時間限定（期間限定）の無料作成
👉日本語が多少変ですがアカウントの作成はこちらをタップ。別に一定期間経ったらアカウントが消えるとかそういことは無いです。キャンペーン中であることを意味しているだけです。
2.IOSTウォレットをインポート
👉既に他のサービス（IOSTABCとか）で作っている方はこちら。秘密鍵が必要になります。

※IOSTABCでのアカウント作成も記事書いてますのでご参考まで。
IOSTABCでアカウント作成～Chromeのウォレットにインポート
https://qiita.com/RYOHO/items/4e8904418cae503f7bf2

**どちらの選択肢を選んでもHuobiWallet自体のパスワードが必要になります。ご用意下さい。**
![InkedScreenshot_2019-03-13-08-07-42-030_com.huobionchainwallet_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/39453/d671dc61-7aa9-ed55-5319-92208e365f3d.jpeg)
オレンジ枠のところにアカウント名を入力してください。入力ルールは以下。
・5～11文字の文字列
・半角英数字および下線（アンダーバーのこと）である「_」が利用可能
・既存の文字列では登録できません（TwitterのIDと同じです）
入力終わったら提出して作成完了です。簡単ですね！

#IOSTアカウントのインポート
秘密鍵の入力を行って完了です。簡単ですね！

#指紋認証の設定
HuobiWalletのパスワードは今回のようなアカウントの作成・インポート作業やウォレットからの送金などのすべてのアクションで求められます。が、いちいちすべてパスワード入力は面倒くさいので指紋認証機能をオンにしましょう。送金が指紋認証で行えるようになるので便利です（アカウント作成・インポートはどちらにしろパスワード必要）
![InkedScreenshot_2019-03-13-12-10-21-400_com.huobionchainwallet_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/39453/fe60ce44-c497-b444-6246-f60fa2e766ab.jpeg)
画面下部のメニューから「設定」を選択し、「Touch IDの利用を許可」のチェックを入れましょう。


以上でHuobi Walletの導入～基本的な設定は以上です。お疲れさまでした～👨🏻🍵
送金や投票機能も最近増えたのでそちらも適宜使ってみるといいと思います。UIが比較的良くできているので迷うことも少ないと思います。
Dockerお困りごと

Dockerで詰まったところをまとめていく

気が向いたり、見つけたりしたら追記していくと思う。
もしかしたらgithubのtilにまとめちゃって更新しないかもしれない。

# sourceコマンドが使えない

```bash:エラーメッセージ
/bin/sh | source: not found
```
Dockerのビルドでは/bin/shが使われていた。
ubuntuでは/bin/sh -> /bin/dashになっていた。
`source`コマンドや`.`コマンドはbashの組み込み（？）関数なので、そういう設定が必要

```dockerfile:dockerfile
SHELL ["/bin/bash", "-o", "pipeline". "-c"]
```

無理矢理`/bin/sh`を`/bin/bash`に向かせるシンボリックリンクを作ったりすると[hadolint](https://github.com/hadolint/hadolint)に怒られるよ

- DL4005
- SC2039

この辺のエラー

# テキストファイルがビジー云々

```bash:エラーメッセージ
/bin/sh: ./configure: /bin.sh: Text file busy
/bin/sh: ./configure: /bin/sh: 誤ったインタプリタです：テキストファイルがビジー状態です
```

configureファイルの中とかで`chmod`していないですか？
`chmod`コマンド後に`sync`コマンドを使うと解決します。

```dockerfile:dockerfile
RUN find ./ -type f -name * | xargs sed -i /^chmod/a sync
```

これだと行頭の`chmod`コマンドしか見つけられない。
パイプしてるようなのまで見つけようと思ったら`sed`コマンドの内容を変えてね
参照したIssue: [Running chmod on file results in 'text file busy' when running straight after. #9547 ](https://github.com/moby/moby/issues/9547#issuecomment-77547893)
久しぶりにArray.splice()を使って混乱した事

# はじめに

久しぶりにArray.splice()使ってちょっと混乱してしまいました。
思惑通りの操作は直ぐに出来たのですが、MSN等に載っている関数の説明が間違っているのではとしばらく考えてしまいました。
結果、自分の勘違いでした。
単純な事ですがメモとして残しておこうと思います。

# Array.prototype.splice()の簡単な説明

`array.splice(start[, deleteCount[, item1[, item2[, ...]]]])`
Start :
開始位置。
負の場合、array.length - n から開始。
開始位置の要素も削除の対象になる。

deleteCount :
削除する要素の数。
省略した場合、Start以降の要素を削除する。
0または負の場合、何も削除されない。

item1, item2 : この記事では、使わないので省略。

## 勘違いした記述

末尾から4つ消そうと以下のように書いてしまった。

```javascript:javascript
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(-1, 4);
console.log(array);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]; 
```

この記述では、末尾の1つしか削除されません。
動作をしっかり理解すると当然なのが分かります。
末尾から開始して(右側の)4つ要素を削除するとなります。
末尾の後に続く要素は当然ありませんので、末尾1つしか削除されません。

この場合、以下のようにすると想定通りの動きになります。

```javascript:javascript
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(-4, 4);
console.log(array);
// [1, 2, 3, 4, 5, 6];

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(-4);
console.log(array);
// [1, 2, 3, 4, 5, 6];
```

削除する方向が右側固定なのが肝でしたね。

## その他の動作結果

```javascript:javascript
let array = [];
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(0, 1);
console.log(array);
// [2, 3, 4, 5, 6, 7, 8, 9, 0];

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(0, 4);
console.log(array);
// [5, 6, 7, 8, 9, 0];

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(4, 1);
console.log(array);
// [1, 2, 3, 4, 6, 7, 8, 9, 0];

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(4, 4);
console.log(array);
// [1, 2, 3, 4, 9, 0];

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(-1, 1);
console.log(array);
// [1, 2, 3, 4, 5, 6, 7, 8, 9];

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(-4, 1);
console.log(array);
// [1, 2, 3, 4, 5, 6, 8, 9, 0]; 

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(-4, 4);
console.log(array);
//  [1, 2, 3, 4, 5, 6]; 

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(0);
console.log(array);
//  []; 

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(4);
console.log(array);
//  [1, 2, 3, 4]; 

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(-1);
console.log(array);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]

array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
array.splice(-4);
console.log(array);
// [1, 2, 3, 4, 5, 6]
```
drag textreader

- demo https://codepen.io/gnjo/pen/eoZpbL
- encoding https://cdnjs.cloudflare.com/ajax/libs/encoding-japanese/1.0.29/encoding.min.js
- core https://codepen.io/gnjo/pen/ZZWWvp.js?textreader=1

```js
let pre =document.getElementById('x');
textReader(pre,function(fileinfo,text){
  console.log(fileinfo,text)
  pre.innerHTML=text;
})
```
```css
pre{
  width:90vw;
  min-height:500px;
  background-color:orange;
}
```
```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/encoding-japanese/1.0.29/encoding.min.js"></script>
<script src="https://codepen.io/gnjo/pen/ZZWWvp.js?textreader=1"></script>
<!-- core -->
<pre id="x"></pre>
```
半年くらい前に転職しました

# この記事の目的
* 2018年に職場を変えた
* 「なんでやめたの？」とよく聞かれるが、明確に一発で「これだ！」っていう理由が答えられないので、ちゃんと整理しておこうと思う

# 職歴
* 2015年新卒入社
* 2018年退職/今の会社に入社
* 現在に至る

# 前職での業務

## 役割
* システムの構築/運用
    * OSより上
* ソフトウェアの開発

## やっていたこと
* 自社サービスを提供するための各種APIサーバの開発・運用
* ミドルウェアの設定・検証
* デプロイの仕組みの整備

# 本題
## 今まで答えてきた"辞めた理由"
* やってみたいことがあるが、その現場ではできなさそうだった
* やりたいことができなくなった
* 社宅から出なければならない年次だったからちょうどよかった
* みんながやめるから  
など…

## 本当は？
### 1年以上前からずっと転職を考えていた
* 考え始めたきっかけは組織改編で新しく上司になった人間の一言
    * 上司「お前どういうことやりたいの？」
    * ワイ「今までどおりシステムの開発と運用やっていきたい」
    * 上司「お前は馬鹿か」
* 脚色無しで本当にこの会話は存在して、ここにはいられないし、居続けちゃだめな気がした
    * その上司のことは嫌いではなかったけど、方針が合わなかった
* 辞めてすべてを押し付けようと思ってた人が先に辞めてしまい、タイミングを失っていた
* 仲良くしていた仲間はいたので、人間関係を壊すのが嫌だった
* なんだかんだで結局環境を変えることにビビってた

### 転職意欲の再燃
* 2018年になって後輩も育ってきて、仕事に対する意欲がなくなった
    * 以前は毎日いくら働いても楽しかったけど、最後は何をしても楽しくないし、新しい学びも得られない状態だった
    * 暇だったから浮いてる開発タスクやらせてもらおうと手を挙げてもやらせてもらえず、このままここで20代を終えるのはさすがにマズイと認識した

* 自分の市場からの評価を知るために面接受けるだけ受けてみれば？という先輩からの悪魔の囁き
    * 実際に面接受けてみたらわりと早く内定をもらえたので、そこに転職することを決意

## 辞めてみてどうだった？
### 前職からの変化
#### 仕事内容
* 今まで意識しなかった領域への理解も必要になり、学習意欲は増した
* 設計をちゃんとやる文化があるので、ものを作る際の意識が変わった気がする
* 深夜アラートが減った
* 楽しくはなった
    * やりたいと思ったことはやらせてもらえる
    * やりたくないこともやる必要はあるけど…

#### 待遇
* 収入は若干増えた
    * 前職の状況から抜け出せれば多少下がっても構わないと思っていたが、気づいたら上がってた

#### 人間関係
* 仕事終わりにちょっと飲みにいくみたいなことがなくなった
* 仕事をする上では厳しく指導していただいたり議論させていただいたりしていて、めっちゃ刺激はもらってる

# 結論
* 「お金・やりがい・人間関係」のうち2つがなくなったら辞めどきって話をどこかで聞いたが、自分もまさにそれだった
* 最終的には将来への漠然とした不安からえいやで動いてしまった部分はあると思う
* 前職であまり良く思ってなかった部分で、転職しても変わらない部分もある
    * そこはある程度諦めるか、どうしても気に入らなかったらまた転職するんだろうなー
* 前職で築いた人間関係は転職してもそう簡単には崩れないから安心して転職できる
    * 私の前職が特殊でありがたい環境だったのかも…
* まとめようと思ったけどまとまらなかった
    * でもトータルで考えてもあのとき勇気をだして辞めてよかったと今は思う（近い将来どう思っているかはわからない
C言語の時刻・時間を図示してみた

C言語には、扱いにくいと個人的には思っている時間関数があります。
扱いにくかろうと、それ以上のモノを作るスキルはないので大人しく従いますが、どうにも覚えにくかったのでつながりを書いてきます。。

Windows編とかクロックとかタイマーとか増やしていくかも？

[Linuxはこっち見て](https://qiita.com/Riliumph/items/396ff60f4d38cf857ac7)

# tl;dr(too long didn't read)
![time_correlation_diagram.png](https://qiita-image-store.s3.amazonaws.com/0/54925/ae0cb6c9-7ed9-45c1-2bc2-4b2b290444fd.png)


# C言語標準：time_t型

1970年1月1日0時0分0秒(UTC)からの経過秒数を示す型。
つまり、<font color=red>このままでは日付も時刻も分からない</font>。

```C:構造体定義
#include <time.h>
time_t time(time_t *t);
```

C言語標準の時刻取得関数。
以下の２通りの使い方があります。

```C:time()の記法
time_t current_time;
time(&current_time); // バッファを与えるとそこに入れてくれる
or
time_t current_time = time(NULL); // 戻り値でもOK
```

# C言語標準：構造体struct tm型
より詳細な日付情報が欲しい場合に用いる。
ログに日付出すときに大活躍しました。
Linux Kernel内でも`struct timespec`と`struct tm`を変換できます。。

```C:定義
struct tm {
    int tm_sec;        /* 秒 (0-60) */
    int tm_min;        /* 分 (0-59) */
    int tm_hour;       /* 時間 (0-23) */
    int tm_mday;       /* 月内の日付 (1-31) */
    int tm_mon;        /* 月 (0-11) */
    int tm_year;       /* 年 - 1900 */
    int tm_wday;       /* 曜日 (0-6, 日曜 = 0) */
    int tm_yday;       /* 年内通算日 (0-365, 1 月 1 日 = 0) */
    int tm_isdst;      /* 夏時間 */
};
```

# time_t型→文字列型
時刻を文字表現にしたいときに使います。

```C:時刻->文字表記
#include <time.h>
char *ctime(const time_t *timep);  // Thread unsafe
char *ctime_r(const time_t *timep, char *buf); // Thread safe
```

- **C言語標準**：`ctime()`  
内部メモリのポインタを返してしまうため、内部メモリが書き換わると受け取った先も変わってしまうスレッドアンセーフな問題を持ります。
- **POSIX限定**：`ctime_r()`  
ユーザー側に出力バッファを要求しているため、内部で書き換わったとしても値は保障されます。

# time_t型→struct tm型

わざわざtime_t型から変換するのも手間だし、現在時刻の`struct tm`を返す関数ぐらいあってもいいじゃんと思うのは私だけですか？
きっと、私が知らないだけですよね。

```C:変換関数
#include <time.h>
// GMT
struct tm *gmtime(const time_t *timep); // Thread unsafe
struct tm *gmtime_r(const time_t *timep, struct tm *result); // Thread safe
// 地域時間
struct tm *localtime(const time_t *timep); // Thread unsafe
struct tm *localtime_r(const time_t *timep, struct tm *result);  // Thread safe
```

# struct tm型→文字列型

```C:変換関数
#include <stdio.h>
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);
```

出力する場合は`printf`関数にバラバラに突っ込んでもいいかも。
FastAPIでCORSを回避

# はじめに
[FastAPI](https://fastapi.tiangolo.com/features/)を使っていてCORSの問題にぶち当たり
2時間ほど詰まってしまったので、他に困っている人に向けて解決方法を残します。

## 問題のソースコード
問題のソースコードはこのようになっています。
今回は公式でも取り上げられているようなサンプルプログラムを参考に作っています。
https://fastapi.tiangolo.com/tutorial/first-steps/


```main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/users/")
def read_users():
    return {"id": 1, "name": "taro"}

@app.get("/users/{user_id}")
def read_user(user_id: int):
    return {"user_id": user_id}
```

FastAPIの起動

```bash
$ uvicorn main:app --reload --host 0.0.0.0 --port 8000
```

http://localhost:8000 で待機します

# 症状
FastAPIが待機している```http://localhost:8000```に対して
アプリケーションの```http://localhost:8080```からアクセスすると
下記のようなエラーがchromeのコンソール上で確認されました。

```
Access to fetch at 'http://localhost:8000/users/' from origin 
'http://localhost:8080' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
If an opaque response serves your needs, set the request's mode to 
'no-cors' to fetch the resource with CORS disabled.
```

エラーを見てみるとCORSのポリシーによって```http://localhost:8080```はブロックされているようなので、
どうやらサーバ側でアプリケーションURLを許可するかCORSを回避してあげれば良さそうです。

# 解決方法
通常であれば、サーバからのレスポンスヘッダーに
```Access-Control-Allow-Origin: *```を追加してあげればよいのですが、

FastAPIの場合は直接ヘッダー情報を追加するのではなく、下記のような対応をとります。

- 追記
allow_origins=["*"]のみだと、POSTのとき怒られるので、
3つほどパラメータを追加しました。
これで、全メソッドに対応できると思います（POST,PUTしか検証していません

```main.py
from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware # 追加

app = FastAPI()

# CORSを回避するために追加（今回の肝）
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,   # 追記により追加
    allow_methods=["*"],      # 追記により追加
    allow_headers=["*"]       # 追記により追加
)

@app.get("/users")
def read_users():
    return {"id": 1, "name": "taro"}

@app.get("/users/{user_id}")
def read_user(user_id: int):
    return {"user_id": user_id}
```

今回、解決にあたって、こちらの方が実装しているコードを参考にしました。
>https://github.com/tiangolo/full-stack-fastapi-postgresql/blob/b96d78db99d8c4f37f0df64df587ffebda4bfc56/%7B%7Bcookiecutter.project_slug%7D%7D/backend/app/app/main.py


# おわりに
CORSについてエラーが起きたとき、当初はCORSについてまったく知識がなかったので、どう対処してよいかわかりませんでしたが、フィックスしていくに当たって、理解を深めることができよかったです。ただ、２時間消費してしまったのはつらい...
少しでも他の方のお役に立てればと思います。
電子署名を理解する - データに署名するとはどういうことか

# 電子署名の役割

あなたが紙の書類に署名をすると、その書類を受け取った人は、他人がなりすまして書いたものではなく、あなた本人の意思で書かれたものと見なすことができます。

同じように、あなたがデータに署名をすると、その署名は、データがあなた本人から送られてきたものであることを証明します。また、データが第三者に改ざんされていないことも証明します。

# 電子署名の作り方

データに施す署名もまたデータです。
どのようなデータであれば、署名の役割を果たせるのでしょうか？

あなたが電子署名を作るには、まず元のデータを、ハッシュ関数を使って、短い要約（メッセージダイジェスト）に変えます。
その要約を、あなたしか持ち得ない秘密鍵を使って暗号化します。この暗号化された要約こそが、電子署名と呼ばれるものです。
電子署名を施すとは、元のデータにこの暗号化された要約を付けることです。

なぜ、この暗号化された要約が、本人証明と、改ざんされていないことの証明になるのでしょうか。

# なぜ電子署名が、本人証明と、改ざんされていないことの証明になるのか

あなたは、先ほど電子署名を施したデータをAさんに送りました。
受取人のAさんは、届いたデータを、あらかじめあなたから渡されていた公開鍵を使って復号します。

その公開鍵で正しく復号できたということは、そのデータはあなたしか持ち得ない秘密鍵で暗号化されたということです。よって、あなた本人によって作られたデータであると見なすことができます。

このように、受取人は、あなたの秘密鍵に対応した公開鍵を使って電子署名を復号することで、データの本人確認を行うことができます。

さらに、受取人のAさんも、あなたがやったのと同じように、元のデータを、あなたと同じハッシュ関数を使って要約を作ります。
そしてその要約と、電子署名を復号することで得た要約が一致しているかを確認します。
もしも一致していなかった場合は、データを配送する途中で内容が改ざんされたことになります。
一致していれば、改ざんされていないことになります。

このように、受取人は、あなたが使ったものと同じハッシュ関数を使って要約を作り、電子署名を復元して得た要約と比べることで、データが送信時点から改ざんされていないかを検証することができます。

# 参考
[スラスラわかるネットワーク&TCP/IPのきほん](https://www.amazon.co.jp/%E3%82%B9%E3%83%A9%E3%82%B9%E3%83%A9%E3%82%8F%E3%81%8B%E3%82%8B%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF-TCP-IP%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93-%E3%83%AA%E3%83%96%E3%83%AD%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9/dp/4797377038)
[電子署名 - Wikipedia](https://ja.wikipedia.org/wiki/%E9%9B%BB%E5%AD%90%E7%BD%B2%E5%90%8D)
[本当に本人から？見えない相手の真偽がわかる「電子署名」 | グローバルサインブログ](https://jp.globalsign.com/blog/articles/digital_signature_180612.html)
Django REST framework の ModelSerializer の Field Mapping を変えたい

## 概要

- REST framework には `ModelSerializer` という Django の `Model` を指定すると、いい感じにフィールドが生えた `Serializer` を生成してくれる機能があります。
- この `ModelSerializer` は 内部では Django の `Model` の `Field` に応じて restframework の `Field` とマッピングさせています。
- 例えば `django.models.TextField` は `restframwork.fields.CharField` にマッピングされています。
- このマッピングのカスタマイズできるといいですよねという話です。

## 例えば

- 例えば、ローカライズした日時情報を返すカスタムフィールドを作ったとします。
- https://stackoverflow.com/a/30570521

```python
class LocalDateTimeField(serializers.DateTimeField):
    """ localize した時間を扱う DateTimeField
    """

    def to_representation(self, value):
        value = timezone.localtime(value)
        return super(LocalDateTimeField, self).to_representation(value)
```

こういうカスタムフィールドを作ったら、個別の Serializer にそのまま設定すれば利用可能です。

```python
class HogeSerializer(serializers.ModelSerializer):

    created_at = LocalDateTimeField()

    class Meta:
        model = Hoge
        fields = "__all__"
```

ですが、毎回個別の`Serializer`に設定するのは、漏れもあるしちょっと面倒です。 そこで  `ModelSerializer.serializer_field_mapping` の設定を変えるような `MyModelSerializer` を作ってみます。

```python
from django.db import models


class MyModelSerializer(serializers.ModelSerializer):

    serializer_field_mapping = (
        serializers.ModelSerializer.serializer_field_mapping.copy()
    )
    serializer_field_mapping[models.DateTimeField] = LocalDateTimeField
```
- https://stackoverflow.com/a/46620401

`django.models.DateTimeField`　が `LocalDateTimeField` にマッピングされた`MyModelSeriazer` ができました。

あとは下記のように `MyModelSerializer` を継承するだけです。

```python
class HogeSerializer(MyModelSerializer):

    class Meta:
        model = Hoge
        fields = "__all__"
```

これで `MyModelSerializer` を継承している全ての `Serializer` は全ての`DatetimeField`がローカライズされるようになります。

以上です。

## 参考

- https://www.django-rest-framework.org/api-guide/serializers/#serializer_field_mapping
Autoencoder を使った異常検知

# はじめに
Autoencoder での異常検知について話す機会があったので、せっかくなので記事にもしておきます。

※注意
雰囲気を示すために例として celebA データセットを使った結果を出していますが、正常データ内に広いバリエーションがある場合だと今回紹介する手段では難しいです。記事内の結果はチェリーピックしたやつだと思ってください。

# 異常の検知
ここでの異常検知としては外観検査のようなものを想定します。リンゴの画像を正常データ、それ以外のミカン、トマトの画像を異常データとする場合、リンゴの画像をミカンやトマトの画像と区別するような問題を考えます。
## 異常データが入手可能な場合
こんな感じでリンゴ、ミカン、トマトのデータがそれぞれ沢山手に入る場合、それらを学習用データとして使えば (原理的には) 各クラス間の決定境界を決めることができるので、リンゴとそれ以外のものを判別できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/134222/a5484400-5ad9-8f9a-95e6-d0757fe63c36.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/134222/acccbeb0-16f2-aa2b-9461-827932deb73d.png)

## 異常データが入手できない場合
リンゴのデータは入手できるもののミカンやトマトのデータは手に入らないといった場合があります。例えば工業製品の欠陥検査などでは、正常データは多数手に入るものの異常データはほとんど手に入らない (そんなにぽんぽん欠陥品が出るようでは困る) というケースは多いです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/134222/dc4b6941-6108-969b-db33-8eb641936e1b.png)
その場合でも、何らかの方法で正常データの分布を掴むことができればそこから外れたものを異常データとみなすことで正常/異常の判別に使えそうです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/134222/e7812e28-9733-2a6d-d732-3fa43a9872eb.png)

正常データの分布との距離の取り方について、2次元データが実質的に1次元の直線上に分布しているようなケースを考えると下図のようになります。下図左は正常データの分布が1次元の直線上に分布していることを、下図右は判別対象である新しいインスタンスについて正常データ分布から得られた直線との距離を取ることを示しています。
具体的には、正常データについて主成分分析を行って正常データこの距離が近ければ正常、遠ければ異常とすることで異常の判別ができそうです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/134222/e44915a9-6ea2-0fe8-b0c5-3ccd644b1d5d.png)

# 高次元のデータではどうすれば？
データの次元が小さければ主成分分析でもしておけばよさそうですが、画像などの高次元なデータの場合はニューラルネットワークに頼りたいです。今回は Autoencoder を使った場合について紹介しますが、GAN や VAE を使う方法もあります。例えば [Efficient GAN-Based Anomaly Detection](https://arxiv.org/abs/1802.06222) などは GAN を使った異常検知の好例だと思います。

## 使用したニューラルネットワーク
適当な Convolutional Autoencoder です。損失関数は Mean Squared Error。

## 使用したデータ
[celebA データセット](http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html)を glasses 項目を参照して眼鏡あり/なしに分割し、眼鏡なしの画像を学習用データとしました。

## 結果
左から、入力画像、出力画像、入出力差分画像の順に並べています。眼鏡の部分の再構成が上手くできずに差分が大きくなっていることがわかります。髪の毛など、眼鏡以外の場所でも差分の大きい領域は出てきてしまうようです。
<img width="186" alt="180968.png" src="https://qiita-image-store.s3.amazonaws.com/0/134222/38f77eec-8265-655a-c902-2b7e4b20487d.png">
<img width="183" alt="187032.png" src="https://qiita-image-store.s3.amazonaws.com/0/134222/1f6b5b76-8b25-97ec-fd9c-84ac6b3c025a.png">
<img width="182" alt="181254.png" src="https://qiita-image-store.s3.amazonaws.com/0/134222/e09a5063-69c4-cafe-2bd8-6016cdf4b7af.png">
Ubuntu 18.04 の systemd-resolved で local DNS stub listener の利用をやめる

Ubuntu 16.10 以降で `/etc/resolv.conf` の中身を見てみると DNS による名前解決のために 127.0.0.53 を見に行っていることに気づくことがあります。

これは、最近の Ubuntu では systemd-resolved が 127.0.0.53:53 で local DNS stub listener というものを提供しており、これを経由して外部の DNS リゾルバを参照するような設定が行われていることによるものです。local DNS stub listener が利用されるようになった経緯については以下の記事が詳しいです。

[Ubuntu 16\.10 その7 \- ローカルDNSリゾルバーの仕組みが変わる・systemd\-resolvedの採用 \- kledgeb](https://kledgeb.blogspot.com/2016/06/ubuntu-1610-7-dnssystemd-resolved.html)

local DNS stub listener を利用することにはさまざまな利点がありますが、この機能をオフにしたい場合もあります。典型的には BIND や NSD のような DNS コンテンツサーバを起動しようとしたときに local DNS stub listener が53番ポートを先に利用してしまうことで起動できなくなるという問題が起こることがあります。

この問題を解決する方法はいろいろ考えられ、状況によって最適な方法は変わってくるのですが、私は以下の方針で解決しました。参考にしてください。

* local DNS stub listener の利用をやめる
* netplan と systemd-resolved の利用を続ける
* `/etc/resolv.conf` が外部の DNS リゾルバを直接参照するようにする

## local DNS stub listener の利用をやめる

構築しようとしている DNS サーバと local DNS stub listener が競合しないように設定することができる場合もありますが、この方法は難しそうだったのであきらめて、local DNS stub listener の利用をやめることにしました。

local DNS stub listener を利用しないようにするためには `/etc/systemd/resolved.conf` を編集します。

```/etc/systemd/resolved.conf
[Resolve]
DNSStubListener=no
```

設定ファイル変更後には systemd-resolved を再起動して設定を適用したいところですが、このままでは問題が起きるので適用はこの記事の最後まで待ってください。

## netplan と systemd-resolved の利用を続ける

local DNS stub listener を起動しないような設定はできましたが、まだ `/etc/resolv.conf` を変更していないので名前解決を行うために 127.0.0.53 を見に行こうとしてしまいます。

このため `/etc/resolv.conf` を変更したいところですが、方針をよく考えましょう。最近の Ubuntu ではネットワークの設定を行うためのツールのエコシステムが複雑化しており、たとえば Ubuntu 18.04 では

1. `/etc/netplan` 以下の yaml ファイルをもとに netplan が systemd-networkd の設定ファイルを生成する
2. 生成された設定ファイルをもとに systemd-networkd がネットワークの設定を変更する

という流れで設定が適用されます。DNS の設定についても同様で、`etc/netplan` 以下の yaml ファイルをもとに systemd-resolved の設定が変更され、local DNS stub listener が参照する外部の DNS リゾルバが切り替わるようになっています。よって `/etc/resolv.conf` を手動で編集してしまうと「DNS 以外のネットワークの設定は netplan で変更できるけど DNS だけは直接 `/etc/resolv.conf` を編集しないといけない」という状態になり混乱を呼びそうです。

よって、netplan を使い続けたいと考えている場合は `/etc/resolv.conf` を直接編集したり systemd-resolved を disable するのはやめたほうがよいです。

## `/etc/resolv.conf` が外部の DNS リゾルバを直接参照するようにする

とはいえ `/etc/resolv.conf` には外部の DNS リゾルバを直接参照するような設定が必要です。実は `man 8 systemd-resolved` にやり方が書いてあり、`/etc/resolv.conf` を `/run/systemd/resolve/resolv.conf` へのシンボリックリンクとすればよいです。

`/run/systemd/resolve/` には `resolv.conf` と `stub-resolv.conf` という2種類のファイルが含まれています。`resolv.conf` は外部の DNS リゾルバを直接参照するような設定が書かれており、`stub-resolv.conf` は「外部の DNS リゾルバを参照するように設定された local DNS stub listener」を参照する設定（すなわち 127.0.0.53）が書かれています。これらのファイルの内容は systemd-resolved により管理されているので、間接的に、netplan の設定ファイルに書かれた内容が反映されるようになっています。

要するに、以下のようにすればよいです。

```bash
$ cd /etc
$ sudo ln -sf ../run/systemd/resolve/resolv.conf resolv.conf
```

あとは systemd-resolved を再起動して local DNS stub listener を止めます。

```bash
$ sudo systemctl restart systemd-resolved
```

以上の設定によって次のことが実現できるようになりました。

* local DNS stub listener を止めた（他のプログラムが 53番ポートを bind するときに失敗しなくなった）
* `resolv.conf` が外部の DNS リゾルバを直接参照するようになった（127.0.0.53 を参照するのをやめた）
* netplan の設定変更が `/etc/resolv.conf` に自動的に反映されるようになった
Power9 CPUのUsers Manualを読んでいく

さて、これから僕はIBMのPower9アーキテクチャのCPUのドキュメントを読んでいきます。
Power9アーキテクチャについて研究していきたい理由ってのが、ぜひBounty Sourceで出てきたお題を解決してお金をゲットしたいなと思ったというのがあります。
ドキュメントを読んでてもわからんところが多いので、ぜひ強い人に教えてもらいながらドキュメントを読み通していきたいです。

ドキュメントは以下からフリーでダウンロードできます。

https://openpowerfoundation.org/?resource_lib=power9-processor-users-manual

では初めていきます。

>The Power9 processor is a superscalar symmetric multiprocessor designed for use in servers and large cluster systems.

>Power9プロセッサはスーパースカラーシンメトリックマルチプロセッサで、サーバや大規模なクラスターシステムに使われます

superscalarって出てきましたね。スーパースカラーとは、Wikipediaによると、

>複数の命令を同時にフェッチし、複数の同種のあるいは異種の実行ユニットを並列に動作させ、プログラムの持つ命令レベルの並列性を利用して性能の向上を図るアーキテクチャである。

のようです。並列性を利用するんですね。

>1998年以降に開発された汎用プロセッサは基本的に全てスーパースカラーである。

と書いてあるので、スーパースカラーということで、Power9 CPUが特別なプロセッサということはないようです。
Power9 CPU自体は、サーバーやクラスターシステム（分散システムのことかな）に使われるようです。
クライアントには使われないんですね。

シンメトリックマルチプロセッシングとあるんですけど、Wikipediaで調べたら、対称型マルチプロセッシングのようです。コアが対称に割り付けられているようです。

> It uses CMOS 14 nm technology with 17 metal layers. 

CMOS 14nmの技術、17のメタルの層で構成されているようです。多層になってるんですね.

>The POWER9 processor supports direct-attach memory. 

direct-attach memoryって何？ということで調べてみます。Direct-attached storageでヒットしたんだけど、まあメモリが直接接続されているようです。

>It supports a maximum symmetric multiprocessing (SMP) size of two sockets and is targeted for scale-out workloads.

対称型マルチプロセッシングが最大２ソケット使えるようです。スケールアウトした仕事量に標的を絞っているようです。

>The POWER9 processor offers superior cost and performance. 

まあコストとパフォーマンスが良いよと書いてあります。

>Technical Computing: The POWER9 processor provides superior floating-point performance and high-memory bandwidth to address this market segment. It also supports off-chip floating-point acceleration.

Power9 プロセッサは優れた浮動小数点演算のパフォーマンスを提供できる。高いメモリー帯域をこのマーケットセグメントで提供できる。
メモリー帯域って初めてみたんだけど、憶測なんだけど、メモリーにアクセスできる速さのことかなとは思います。
off-chip floating-point accelerationって何と思ったけど、off-chip memoryってのは、外部メモリーのようですね。外部メモリとは何を指してるのかわからないけど、外部メモリにおける浮動小数点演算を加速できるようです。

次は、クラウド開発環境にも使えるよみたいなことが。

>Big Data Analytics: The POWER9 processor with CAPI attach, large caches, and on chip accelerators provides a robust platform for analytics and big-data applications.

CAPIとは、~~Coherent Accelerator Processor Interfaceのようです。CPUと任意のソフトウェア、ミドルウェア、ユーザーアプリケーションを結合して、お互いのメモリを自由に行き来できるようにする技術みたいです。~~プロセッサ用のバスの1種のようです。（指摘ありがとうございます）


on-chip acceleratorという要素もあるようですね。ググってもわからないのでスルーで。

この後、キャッシュやメモリーが頑健なので、業務向けにも使えるみたいなことが書いてあります。

>From a logical perspective, the POWER9 processor consists of six main components:

論理的な視点では、Power9 プロセッサは、６のメインコンポーネントから成り立っているようです。

>POWER9 processing core including the L1 cache

Power9 のプロセッサのコアがL1のキャッシュも含んでいるようです。L1キャッシュとは一番上位に位置するキャッシュのようですね。それより下位にL2キャッシュがあるようです。キャッシュも階層構造になってるんですね。

では今日はこんなもので。
ノウハウの出し惜しみは、開発を失敗させる。

## 技術の開発を委託先と一緒にしていくとき、人によっては自分の持っているノウハウを出し惜しみする。

## でも私は主張したい。「そんな出し惜しみをしていると開発に失敗するぞ。」


## 理由
### 技術の進歩は速くなっている。
５年前の最新技術は、オープンソースの実装で容易に置き換えられる状況などになってきている。

### 開発を成功させたい
競争が激しいのだから、少しでも自分の開発が成功しやすくしよう。
そのためには、ビジネスのパートナーに任せる開発の部分が、少しでも開発しやすくしよう。

### あなたの知見は、開発を成功しやすくする。 
あなたが、ある分野での開発のエキスパートならば、有用な知見を持っているだろう。
それをビジネスパートナーにも伝えて、少しでも成功させやすくしよう。

### ノウハウを隠すメリットは少なくなってきている。
あなたの開発している分野の技術の進歩が速ければ、あなたが持っているノウハウは、簡単に陳腐化してしまう。
ノウハウを隠しても、数年後にはまったく役に立たないか、誰でも知っているレベルのことになってしまう。

だから、開発を成功させるためには、ビジネスパートナーにあなたの知見を伝えて、少しでも開発が成功しやすくなることに徹しよう。


---

私は以下の記事も同感だ。
Qiita [社内ライブラリをオープンソースしないデメリット・リスク](https://qiita.com/ikeyasu/items/804aae1318410b9bab3e)
メモ: laravel で trait を使って static method で Event 登録するような時に Mockery を使って UnitTest を書く方法

よく忘れるので自分用のメモ。

## 何を実現したいか

例えば、以下のような Trait が存在して、 `static::deleted()` の Closure も Mockery を使って UnitTest でカバーしたい時の方法。

```php
trait SomeTrait
{
    /**
     * boot
     */
    public static function bootSomeTrait()
    {
        static::deleted(function ($model) {
            $model->someModelsMethod();
        });
    }
}
```

## どうやって実現するか

以下のようにすると closure 部分も UnitTest でカバーできるようになる。

```php

final class SomeTraitTest extends TestCase
{
    public function testSomeTrait()
    {
        $class = new class {
            use SomeTrait;
            
            public static function deleted($closure)
            {
                $mock = Mockery::mock(stdClass::class);
                $mock->shouldReceive('someModelsMethod')->once()->with();
                $closure($mock);
            }
        };
        
        $class::bootSomeTrait();
    }
}
```

anonymous class 内で `use　SomeTrait` して、  `SomeTrait` が用いる `public static function deleted($closure)` を anonymous class に定義する。

この anonymous class の引数である `$closure` は `SomeTrait` の `static::deleted(function ($model) {...}` の function 部分が引数なので、 callable となる。

なので、ここで適切に Mockery 等を使って何らかの手続を確認するように書けば良い。

## 注意点とか

anonymous class(無名クラス)使ってるので、当然 PHP7 以上じゃないとダメ。

laravel で event を登録する処理を書くなら、素直に Observer 使うべきだと思う。 https://laravel.com/docs/5.8/eloquent#observers

ただ、外部のパッケージで便利なやつがあって、それが Trait で実現されてて…かつ、そのパッケージに少しだけオリジナルな処理を追加したい時とかに、 trait ベースで Event 登録が必要になったりする。

あと `parent::otherMethod();` とかある場合は、このアプローチは使えない。(anonymous class 使ってるので親が居ないので当然。)
NGINX、uWSGI間をソケット通信する場合、/tmpに.sockを置いちゃダメ！(Centos 7)

# 結論から
CentOS 7ではプログラムごとに`/tmp`が別に用意されるらしく、nginxから見える`/tmp`とuwsgiから見える`/tmp`が違うため、`/tmp/uwsgi.sock`がnginxから見つからない、という事態に陥っていた。
→ `/run`を使う
→ そのままだと再起動時に`/run/app`が削除されるため、永続化する

# それぞれの設定

```nginx:nginx.conf
server {
  ...
  location / {
    include uwsgi_params;
    uwsgi_ignore_client_abort on;
    uwsgi_pass unix:///tmp/uwsgi/app.sock -> unix:///run/app/app.sock;
  }
}
```

```ini:uwsgi.ini
[uwsgi]

# ...

#socket file's location
socket = /tmp/uwsgi/app.sock -> /run/app/app.sock

uid = app
gid = app
#pid
pidfile = /tmp/uwsgi/app.pid -> /tmp/app/app.pid

#permissions for the socket file
chmod-socket = 666

logto = /var/log/uwsgi/app.log

# ...

```

`/run/uwsgi`ではなく`/run/app`にしているのは`uwsgi`とは別のユーザーを使いたいから。

```bash
sudo mkdir -p /run/app
sudo chown app:app /run/app
```

```:/etc/tmpfiles.d/app.conf
#Type   Path                    Mode    UID     GID     Age     Argument
d       /var/run/app            0755    app     app     -
```


# 参考
[python - Got 'No such file or directory' error while configuring nginx and uwsgi - Stack Overflow](https://stackoverflow.com/questions/32974204/got-no-such-file-or-directory-error-while-configuring-nginx-and-uwsgi)
[nginx unix domain socket error - Server Fault](https://serverfault.com/questions/463993/nginx-unix-domain-socket-error/464025#464025)

[CentOS 7 : /var/run 直下に作ったディレクトリが消えないようにする - eTuts+ Server Tutorial](https://server.etutsplus.com/centos-7-tmpfiles-d-deleted-outdate-files/)
Qiitaの技術記事を鵜呑みにするのは危険！！

先日はじめて技術的な記事を書いてみて、そのとき凄く思ったことがあったのでパパッと書きます。

一言でいうと情報が正しいか確認しようってことです。

[Committee(Test Assertions)とCommittee::Railsについて](https://qiita.com/motoki4917/items/cb2aa8bdbaca6af9f53c)
という少しにニッチだけど便利なRubyライブラリについて調べて軽くまとめたんですが、その時思ったのは、

##「Qiitaの技術記事を鵜呑みにするのは危険！！」

ということでした。笑
※Qiitaに限らず、ブログとかもそうです。

###間違っている情報は意外にある
なぜかというと、正しくなかったり、正確でなかったりという情報もあるから。
※だいたいは優良な情報だと思います。古い記事はアラート出してくれるし便利。

これは調べていく中で、公式ドキュメントの内容と比較して、Qiitaやブログなどにある情報が間違っている（古い情報だったり、ふつうに間違っていたり）ことが散見されたのでそう思いました。

###正直自分が書いてみて間違えない自信ない。笑
また、これは自分で書いていて思ったんですが、書いていると、公式ドキュメントに記載がなかったり、詳細など読み取れない部分を自分で解釈して、補足してしまいやすい。
まーこれがないと、ただの翻訳になってしまう感もありますが。

騙そうと思って記事をQiitaやブログ書く人はあまりいないと思いますが、やはり結果として、間違ってしまったり、誤解して書いてしまうことがあると思います。

あと、自分が書いた記事も絶対間違いがないという自信はありませんし。笑

###正しい情報を取る or 取った情報の確認はマスト！

故に大事なのは情報を取る側の姿勢だと思います。取った情報の確認をしっかりしましょう。

発信者が正しい記事書けよって思うかもしれませんが、
逆に僕は「Qiita書くなら絶対間違えないでよ！」ってスタンスの読者が多かったら、怖くて記事書けません。笑

発信しやすくなって、優良な記事が増えるためには、情報を取って使う読み手が最終的な責任をしっかり負うという意識は大事かなと思います。

なので、まー当たり前のことかもしれませんが、
やはり技術的なことを学ぶ上での情報源としては**公式ドキュメント**、
または、**古くない技術書**で確認するのがbettterだと思います。

###公式ドキュメント英語じゃん。。。
あと、英語への抵抗がある人がいるとも思いますが、英語で情報を取れることは結構大事だと思うので、ある程度読めるまで勉強はした方がいい気がします。

コードが読みやすくなったり、エラー解決時間も確実に短縮されることでしょう。

どうしてもって嫌って人はGoogle翻訳つかったらいいと思います。
最近久しぶりに使ったらくそ優秀でびっくりしました。
ほとんど、自然な日本語にして返してくれます。

そうでない場合は複数の記事を確認して、間違いないことを確認するのが大事かなと思います。

###僕のおすすめ情報の取り方
僕が一番いいと思うのはQittaでいい感じの記事を2~3こ読んで、概要を理解してから、理解した内容の確認や詳細な点の確認とかと公式ドキュメントで行う。
です。
効率的だし、正確だと思います。

まとめると
####1. 間違っている情報も意外にあるから、学びたい技術は公式ドキュメントか古くない技術書で確認しよう！
####2. 英語はやったっほうがいい。でもどうしても無理って人は、Google翻訳使ったらいい。
####3. まーでも、Qiitaにはとても優良な記事がたくさんあって無料で読めるので、とても素晴らしいサービスだよね！笑

Qiitaさんなめたタイトルつけてすいません。
Qiitaさんには初心者の頃から（今もまだまだですが）とてもお世話になってます。orz
大好きです。
Qiita最高！笑
Linuxにおける時間

Linuxの中には複数の時間の概念があることを最近になって知った。
jiffiesにも綺麗にハメられたことであるし、LinuxとC言語の時間をまとめておく。

※肝心のjiffiesが別記事なったけどｗ

# Linuxの時間概念
Linux Kernelの中には、複数の時間システムが存在する。

- timeval
- timespec
- ktime_t
- jiffies

# 構造体timeval
POSIX環境での時間構造体。
理由は分からないが、どうやら**<font color=red>非推奨</font>**らしい。

```c:構造体定義
#include <sys/time.h>
struct timeval {
    time_t      tv_sec;     /* Seconds. */
    suseconds_t tv_usec;    /* Microseconds. */
};
```

POSIX環境で使用できる時間構造体の一つ。
次に紹介する`struct timespec`と非常によく似た構造体である。

- **tv_sec**  `time()`の戻り値と同値。
- **tv_usec**　範囲は0～999,999

`gettimeofday()`によってUNIX時間を表現した値が入ったインスタンスが取得できる。

## 構造体timespec
C11で採用されたらしい新しい時間構造体。

```c:構造体定義
#include <time.h>
struct timespec {
  time_t tv_sec; /* Seconds.  */
  long tv_nsec;  /* Nanoseconds.  */
};
```

元々、`struct timespec`はPOSIX環境で定義されていた時間構造体らしい（知らん）。

- **tv_sec** `time()`の戻り値と同値。
- **tv_nsec** 範囲は0～999,999,999

こっちの方が、`struct timeval`より記録粒度が細かい。
（細かく正確に測定できるとは言ってない。）
さらには、OSのAPIを直接使わなくていいので、移植性が高い。

……誰か`struct timeval`の方の優位性を教えて欲しい、偉い人よ。

あと、これ何でか知らないけどLinux Kernel上でも使えるよね。
`#include <linux/time.h>`すれば`struct timespec`を`struct tm`に変換したりできる。

# 変数ktime_t
1/100,000,000（ナノ）秒単位での時間または時刻を格納するために使われる。
粒度は`struct timespec`と同じ。

ただし、こっちはKernel空間の変数。
Linux Kernel内でKerel Timerとして使われる。

```c:変数定義
#include <linux/ktime.h>

union ktime {
        s64     tv64;
#if BITS_PER_LONG != 64 && !defined(CONFIG_KTIME_SCALAR)
        struct {
# ifdef __BIG_ENDIAN
        s32     sec, nsec;
# else
        s32     nsec, sec;
# endif
        } tv;
#endif
};
```

複雑な定義だが、以下に分岐する。

- **64bit環境**  
64bit長変数1つだけ。
- **32bit Big Endian 環境**  
32bit長変数2つでメモリ消費量を合わせている。  
元がunion定義なので、64bit <--> 32bitの環境差を吸収している。  
この定義スゴイよな。俺も仕事でやったわ。
- **32bit Little Endian 環境**  
32bit Big Endianの定義の順番を入れ替えただけ。


# 番外編：time_t
C言語は[別記事](https://qiita.com/Riliumph/items/841ebaf0d349ff6e1d79)で。


# 変数Jiffies
ハマったので[別記事](https://qiita.com/Riliumph/items/7de2bc498cb29fb6aecc)にしました。
MariaDB初期セットアップ　-CentOS7-

毎回構築ガイド的なものを見ながらやるのが面倒になったのでまとめました。


# MariaDBのインストール

クライアントソフトウェア類のインストール

```
# yum -y install mariadb-server mariadb
```

文字コードをUTF-8に設定する

```
# vi /etc/my.cnf

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
character-set-server=utf8　←ココを追記
```

# MariaDBの起動と自動起動の設定

```
# systemctl start mariadb
# systemctl enable mariadb
```

# 初期設定

```
# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): ←空欄でEnter
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n] y ←[y]でEnter
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y ←[y]でEnter
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y ←[y]でEnter
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y ←[y]でEnter
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y ←[y]でEnter
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
```

下記に勢いでアカウントのパスワードを入れようものならERRORになります。

```
# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): 
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
```
ALEXAでTELLOを操作

####はじめに

2018年のAlexaスキルアワードで音声によるTELLOドローンの操作（ https://smarthacks.jp/mag/37640#16Tello_Controller ）を間近に見て感激、またコードがgithubに公開されていることを知って、いつかやってみたいと思っていましたが、ついに実現しました。

####仕組み

Alexaスキルでは、通常、コードはバックエンドにAWS Lambdaを使いデプロイするところですが、ドローンを飛ばすには自分のPCをバックエンドにして、発話からのコマンドを受ける必要があります。ドローンが発するwifiをPCで受信するので、PCのネット接続は別の手段で確保します（自分は有線LANで接続）。発話部分（フロント側）はAlexa スキルビルダーで作成し、自分のPCをエンドポイントにします。これを実現するのが**ngrok**です。

####方法

まず、https://github.com/miso-develop/tello-controller-alexa を自分のPCにクローンします（TMさん、公開ありがとうございます）。先に、npm, ngrokのインストールを済ませておきます。

```
npm install
npm install -g ngrok
```
最初、ngrokのインストールのところで、”write access to /usr/local/lib/node_modules” のメッセージが出てうまく行きませんでしたが、こちらを参考に解決しました。https://qiita.com/NaokiIshimura/items/cc07441939b226e779c6

準備が完了したら、ドローンを飛ばす時に、コードファイルを置いたフォルダ上で以下を実行します。

```
node index.js
```
別ターミナルを起動し、同フォルダで以下のコマンドを実行します。

```
ngrok http 3000
```
ngrokが起動できたら、Forwarding https のURLが表示されるのでそれをメモし、スキルビルダー上でENDPOINTに設定します。このURLは起動の度に変わります（継続有効時間は８時間）ので、操作前に設定する必要があります。

####あとがき

TELLOとAmazon ECHOをお持ちの方はぜひお試しください。
Have a nice flight with Alexa!

【関連記事】
https://qiita.com/miso_develop/items/a482dc4d168ec0a33818
【Visual Studio2019】へアップデートする

Visual Studio 2019が本格リリースされました！
さっそくアップデートしようとしましたが、少し調べる必要があったのでやり方をまとめます。

新規インストールはこちらから
https://visualstudio.microsoft.com/ja/vs/mac/

##環境
macOS High Sierra 10.13.6

##アップデート手順
###公式
https://docs.microsoft.com/en-us/visualstudio/mac/update?view=vsmac-2019

###公式読むのめんどい人向け
ここからできます
<img width="331" alt="ScreenShot 2019-04-05 0.48.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/237014/1329a367-2ade-5aac-215e-ec7ed5cc415a.png">

更新チャンネルを「Stable」にして更新プログラムを確認しましょう。
<img width="596" alt="ScreenShot 2019-04-05 0.49.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/237014/defe00d0-088e-1813-33e5-d7e18f94371b.png">

あとは自動で進むと思います。

おわり
Discordでアップロードした画像をGoogleDriveに自動でアップロードするシステム！

タイトルが長い！
python楽しいですね、結構肌にあっていて嬉しいです。
# 環境
Python3.6
Windows10

Pycharmちゃんが便利すぎてダメになりそうです。JetBrainはいいぞ。
あとPythonは3.6じゃないと動かないです、最新の3.7だとdiscord.pyが動かないです。
# 導入
Bot導入は割愛します。大体下記の記事見れば分かると思います。
[Pythonで実用Discord bot(discord.py解説)](https://qiita.com/1ntegrale9/items/9d570ef8175cf178468f)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/391656/320f93a4-a09d-7587-af43-3da7356280e5.png)
導入したカラパリちゃんbot
botは名前をつけると、愛着が湧きます、かわいい！

# Google側の設定
[PythonでGoogleドライブに画像をアップロード](https://qiita.com/akabei/items/f25e4f79dd7c2f754f0e)
またもここを参考に導入。パッケージのインストールがめっちゃ簡単なPycharmはいいぞ。
**クライアントIDとクライアントシークレットをメモして、setting.yamlを同じディレクトリに配置すること。**
先に上記の記事を元にローカルに置いた画像をアップロードするということを実践するとスムーズだと思います。

# bot側の設定
さぁ、料理を始めましょう。

```python:トリガー指定
async def on_message(message):
    if message.content.startswith('/pic'):
```
これで、全体のメッセージで「/pic」が含まれたメッセージをトリガーに入ってくることが出来た。
この処理内に、GoogleDriveにアップロードまでの処理を入れる。

ちなみに、@のメンションだけで設定したい場合は下記の通り。

```python:メンションのみ
    if client.user.id in message.content:  # 話しかけられたかの判定
      if message.content.startswith('/pic'):
```
Client.user.idで自分のIDです。そのIDがメッセージ内に含まれたかどうかを判定しているだけですね。
更にその中で/picが入ってたら反応するって感じです。

# 先に画像ダウンロード出来るようにする
[python3のrequestsを使って画像を保存](https://qiita.com/pollenjp/items/0c39c35120cd60575647)
これまた、上記を参照にしました。参照というか、もろパクリ。下の方を採用しました。これで、download_imgにurlとfilenameを入れれば、ダウンロードしてくれるようになります。汎用性高いですね、他でも使えそうです。

```python:download_img
def download_img(url, file_name):
    r = requests.get(url, stream=True)
    if r.status_code == 200:
        with open(file_name, 'wb') as f:
            f.write(r.content)
```

# ファイル取得
```python:ファイル取得
        filename = message.attachments[0]['filename']
        download_img(message.attachments[0]['url'], "image.png")
```
messageの**attachements**を呼び出すと、メッセージ内にあるコンテンツを取得する。
中身はこんな感じ

```
[{
'width': 1920, 
'url': '[url]', 
'size': 1414002, 
'proxy_url': '[url]', 
'id': '563384196488364043', 
'height': 1080, 
'filename': 'VRChat_1920x1080_2019-03-27_01-11-24.218.png'
}]
```
urlを叩くと、画像だけが出てくるページになる。
これはDiscordで画像を開いて、左下にある「元ファイルを開く」を押したときに出るURLと同じ。
ファイル名とかも取ってるので、これをこのまま`download_img`で投げてあげます。
そうすると、Discordで投げたメッセージを「image.png」という画像形式で保存されます。

# GoogleDriveにアップロード
あとはローカルのファイルをアップロードしてあげるだけです。

```python
        # GoogleDrive接続
        gauth = GoogleAuth()
        gauth.CommandLineAuth()
        drive = GoogleDrive(gauth)

        f = drive.CreateFile({'title': filename, 'mimeType': 'image/jpeg'})
        f.SetContentFile('image.png')
        f.Upload()
```
'title'がファイル名になるので、そのままアップロードされたファイルのファイル名を使いましょう。
また、SetContentFileは必ず、ローカルに保存されているファイルにしてあげてください。イメージ的には、どんどんこのファイルに上書きして、都度GoogleDriveにアップロードする感じです。

記事にもあった通り、初回は認証が必要です。実行時に出てきたURLを叩いて、認証し、キーが発行されたらコンソール画面で打ち込めばOKです。その後は認証が必要になることはない、はず。実装した後に認証ハズレたりしたら、また書きます。

# 完成！おめでとう！
Discordのbot開発楽しいです。
お天気予報とかも実装したので、Qiitaに書けたら良いなぁ。あとは役職付与とかも自動で出来たりします。
結構仕事でDiscordを使う機会が多いので、汎用性の高いDiscordのbot作って、効率化を図っていきたいなぁ。
Pythonの連想配列でトライ木っぽいのを作る

## 説明
トライ木っぽいのが必要になったので作ることにしました。プレフィックス木とも言うらしい。

以下、Wikipediaより引用です。

> トライ木（英: trie）やプレフィックス木（英: prefix tree）とは、順序付き木の一種。あるノードの配下の全ノードは、自身に対応する文字列に共通するプレフィックス（接頭部）があり、ルート（根）には空の文字列が対応している。値は一般に全ノードに対応して存在するわけではなく、末端ノードや一部の中間ノードだけがキーに対応した値を格納している。2分探索木と異なり、各ノードに個々のキーが格納されるのではなく、木構造上のノードの位置とキーが対応している。

今回は文字列ではなく単語列を対象にしてトライ木っぽいのを作ります。

例えば、

- I like cats.
- I like dogs.
- I play the guitar.
- He makes me happy.

という英文があった時、先頭の候補は「I」と「He」、先頭が「I」の場合の次の候補は「like」と「play」、先頭から「I」「play」と続いた場合の次の候補は「the」のみ、となるような構造を作ります。

## 実装

まず、以下のようなファイルを用意します。

```text:sentences.txt
He went to the store.
The pizza smells good.
The music makes me happy.
I like cats.
I like dogs.
I like an apple.
I play the guitar.
```

そして以下のスクリプトで文章の読み込みから単語リストの作成、トライ木の作成を行います。

```python
def addTree(tree, sentence):
    if not sentence[0:]:
        return None   
    
    if sentence[0] not in tree:
        tree[sentence[0]] = {}
        
    tree[sentence[0]] = addTree(tree[sentence[0]], sentence[1:])
    
    return tree


def createTree(sentences):    
    tree = {}
    for sentence in sentences:
        tree = addTree(tree, sentence)
        
    return tree


sentences = []

with open('./sentences.txt', 'r') as f:
    for row in f:
        sentences.append(row.split())

tree = createTree(sentences)
```

ここで得たtreeに対して以下のように単語ごとのアクセスを繰り返すことで、文章を絞り込むことができます。

```python
print(tree['He'])
print(tree['He']['went'])
print(tree['The'])
print(tree['The']['pizza'])
print(tree['The']['music'])
print(tree['I'])
print(tree['I']['like'])
print(tree['I']['play'])
```

```python:結果
{'went': {'to': {'the': {'store.': None}}}}
{'to': {'the': {'store.': None}}}
{'pizza': {'smells': {'good.': None}}, 'music': {'makes': {'me': {'happy.': None}}}}
{'smells': {'good.': None}}
{'makes': {'me': {'happy.': None}}}
{'like': {'cats.': None, 'dogs.': None, 'an': {'apple.': None}}, 'play': {'the': {'guitar.': None}}}
{'cats.': None, 'dogs.': None, 'an': {'apple.': None}}
{'the': {'guitar.': None}}
```

ちなみに、生成された木構造全体は以下のようになっています。

```python:結果
{'He': {'went': {'to': {'the': {'store.': None}}}}, 'The': {'pizza': {'smells': {'good.': None}}, 'music': {'makes': {'me': {'happy.': None}}}}, 'I': {'like': {'cats.': None, 'dogs.': None, 'an': {'apple.': None}}, 'play': {'the': {'guitar.': None}}}}
```

tree['単語1']['単語2']['単語3']... というふうに繰り返すことで、文章を絞り込めます。

## 参考
[トライ木 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%82%A4%E6%9C%A8)
Androidのライブラリプロジェクト内のKotlinクラスを参照するとUnresolved referenceが出る問題対処

Androidプロジェクトから別のAndoridライブラリプロジェクト内のKotlinクラスを参照した時に、Unresolved referenceとなりビルドエラー発生。1hくらいはまったのでメモを残す。

# 原因
ライブラリプロジェクトのbuild.gradleにKotlin用の記述が漏れているため。
(Androidライブラリプロジェクト作成時、Kotlin用の記述は自動生成されない)

# 解決方法
ライブラリプロジェクトを開いて、以下を実施。
Tools -> Kotlin -> 'Configure Kotlin in projects'
(All modules with Kotlin files are configured'を選択してOK。

# 参考
https://stackoverflow.com/questions/49124353/unresolved-reference-errors-for-android-library-module-referenced-in-app-modul
ASP.NET Coreのタグへルパを自作してViewModelの値を出力する

#何をしたいのか

任意の`cshtml`が以下のようなモデルを`@model`で指定されていたとする。

```cs

public class SampleViewModel
{
	public int TheAnswer { get; set; } = 42;
}
```
で、これを以下のようなタグをcshtmlに指定すると

```html
<display-value asp-for="TheAnswer"></display-value>
```

下記のように書き換えてくれる

```haml

<div>TheAnswer:<strong>  42</strong></div>
```

書き換えるタグへルパを作ると起動すれば良いのか備忘録的に。

但し、Asp.net coreを始めて3日目くらいなので、何かと至らない点が多々有るかと。。。
なので、何かあればご指定期頂ければこれ幸い。



##タグへルパを作る

タグへルパは以下の通り

```cs

	public class ValueDisplayTagHelper:TagHelper
	{
		[HtmlAttributeName("asp-for")]
		public ModelExpression Target { get; set; }
		public override void Process(TagHelperContext context, TagHelperOutput output)
		{
			output.TagName = "div";

			output.Content.SetHtmlContent($@"{Target.Name}:<strong> {Target.Model}</strong>");
		}
	}

```

`Target`の別名を`asp-for`にすることで、`cshtml`側でインテリセンスが効く。

##cshtml側での仕込み

アセンブリの名前が、`WebApplication3`として自作タグへルパのスコープを有効にするには、

```html
@addTagHelper *, WebApplication3
```

と記載するして、アセンブリ内の全てのタグへルパを有効化するか、厳密に単一のタグへルパのみ有効にするなら

```html
@addTagHelper WebApplication3.TagHelpers.ValueDisplayTagHelper,WebApplication3
```
と記載する。

##タグの使用方法

ここまで出来たら、以下のように書くことで、ViewModelを表示できる

```html

@model SampleViewModel

@{
	ViewData["Title"] = "Home Page";
}

<value-display asp-for="TheAnswer"></value-display>


```

##参考にしたページ

[ASP.NET Core のタグ ヘルパー](https://docs.microsoft.com/ja-jp/aspnet/core/mvc/views/tag-helpers/intro?view=aspnetcore-2.2)
[How to create TagHelper who's value is a Model Property (without using @Model)?](https://stackoverflow.com/questions/43285590/how-to-create-taghelper-whos-value-is-a-model-property-without-using-model)
[First Dynamic Form Tag Helper Attempt - Tech Dominator](https://blog.techdominator.com/article/first-dynamic-form-tag-helper-attempt.html)
シェルスクリプトでLINEに天気を投稿する

# いきなり本題

よくわからないけどこれで投稿出来た。

[Weather Hacks](http://weather.livedoor.com/weather_hacks/)
[LINE Notify](https://notify-bot.line.me/ja/)
[jqコマンドインストール](http://qiita.com/wnoguchi/items/70a808a68e60651224a4)

```
#!/bin/bash

api=`curl -s http://weather.livedoor.com/forecast/webservice/json/v1\?city\=016010 | jq -r '.forecasts[] | select(.dateLabel == "今日").telop'`
headers={"Authorization":"Bearer"}
ACCESS_TOKEN=line_token
MSG="今日の天気は$apiです。"
curl -X POST -H "Authorization: Bearer $ACCESS_TOKEN" -F "message=$MSG" https://notify-api.line.me/api/notify
```
Cygwinでg++を使用する際にはまったこと 

　Cygwin環境で、c++で書かれたコードから静的・共用ライブラリを作成・リンクした際に嵌ったため備忘録を残そうと思う。

##環境
+ Cygwin (ver. 3.05)
+ gcc (ver. 7.4.0)

##やりたかったこと
+  c++で作成した道具をライブラリにまとめて整理したい。
+ そのために、c++で静的ライブラリ・共有ライブラリを作成したい。
+ ライブラリの作成・リンク時に`-L`, `-I`オプションでパスを指定するのではなく、環境変数で指定したい。

例えば、こうではなく(ライブラリ名はlibname.soとする)、

```
$g++ -L../lib -o main main.o -lname
```

次のようにしたい。

```
$g++ -o main main.o -lname
```

##`-I`で指定せずに環境変数でインクルードパスを指定する
+ ヘッダーファイルのインクルードパスは、__CPLUS_INCLUDE_PATH__で指定すればよい。

##`-L`で指定せずに環境変数でライブラリパスを指定する
+ cygwin環境下では、gccは__LD_LIBARRY_PATH__は読み込まないらしい(__PATH__に書く)。
+ 静的ライブラリの場合は、__LIBARRY_PATH__を読み込む。

##`-l`オプションで指定するライブラリ名についての注意
####e.g., ライブラリ名が、lib{name}.[so|a]の場合、
+ 静的ライブラリの場合は、__-l{name}__で指定
+ 共有ライブラリの場合は、__-llib{name}__で指定    

つまり、共有ライブラリではlibをとっては駄目。
※これは、Linux環境と違うよね...

##その他
+ ライブラリ作成時のライブラリパスと、実行時のライブラリパスは違うとかなんとか    
（この辺は確かめてないです）。
+ 内容に間違いがあるかもしれません。ご指摘いただけると幸いです。
Build TBB (Intel Threading Building Blocks) for RaspberryPi3

**TBBonARMv7**　[![GitHub stars](https://img.shields.io/github/stars/PINTO0309/TBBonARMv7.svg?style=social&label=Stars)](https://github.com/PINTO0309/TBBonARMv7)
<a href="https://github.com/pinto0309/TBBonARMv7"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/pinto0309/TBBonARMv7.png" width="460px"></a>

# １．はじめに
全体の作業含めて１０分ぐらいで終了します。
まともに使えるかどうかは別として。。。
ちなみに私はOpenCVの自力ビルド前にTBBをインストールしておいてOpenCVへ組み込んでいます。

この世に必要とする人がいらっしゃるのかどうかは知りません。

# ２．ビルド手順

```console:事前準備１
$ cd ~
$ wget https://github.com/01org/tbb/archive/2019_U5.tar.gz
$ tar xvf 2019_U5.tar.gz
$ rm 2019_U5.tar.gz
$ cd tbb-2019_U5

$ make tbb CXXFLAGS="-DTBB_USE_GCC_BUILTINS=1 -D__TBB_64BIT_ATOMICS=0"

$ cd ~
$ mkdir libtbb-dev_2019U5_armhf
$ cd libtbb-dev_2019U5_armhf
$ mkdir -p usr/local/lib/pkgconfig
$ mkdir -p usr/local/include
$ mkdir DEBIAN
$ cd ~/libtbb-dev_2019U5_armhf/DEBIAN

$ cat > control

#========== Input below ========================================
Package: libtbb-dev
Priority: extra
Section: universe/libdevel
Maintainer: <Your name>
Architecture: armhf
Version: 2019U5
Homepage: http://threadingbuildingblocks.org/
Description: parallelism library for C++ - development files
 TBB is a library that helps you leverage multi-core processor
 performance without having to be a threading expert. It represents a
 higher-level, task-based parallelism that abstracts platform details
 and threading mechanism for performance and scalability.
 .
 (Note: if you are a user of the i386 architecture, i.e., 32-bit Intel
 or compatible hardware, this package only supports Pentium4-compatible
 and higher processors.)
 .
 This package includes the TBB headers, libs and pkg-config
#========== Above input ========================================
```

<kbd>Ctrl</kbd>+<kbd>D</kbd> でCATコマンドを終了。

```console:事前準備２
$ cd ~/libtbb-dev_2019U5_armhf/usr/local/lib
$ cp ~/tbb-2019_U5/build/*_release/libtbb.so.2 .

$ ln -s libtbb.so.2 libtbb.so
$ cd ~/tbb-2019_U5/include
$ cp -r serial tbb ~/libtbb-dev_2019U5_armhf/usr/local/include

$ cd ~/libtbb-dev_2019U5_armhf/usr/local/lib/pkgconfig
$ cat > tbb.pc

#========== Input below ========================================
# Manually added pkg-config file for tbb - START
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: tbb
Description: thread building block
Version: 2019U5
Cflags: -I${includedir} -DTBB_USE_GCC_BUILTINS=1 -D__TBB_64BIT_ATOMICS=0
Libs: -L${libdir} -ltbb
# Manually added pkg-config file for tbb - END
#========== Above input ========================================
```

<kbd>Ctrl</kbd>+<kbd>D</kbd> でCATコマンドを終了。

```console:debパッケージのビルド
$ cd ~
$ sudo chown -R root:staff libtbb-dev_2019U5_armhf
$ sudo dpkg-deb --build libtbb-dev_2019U5_armhf
```

# ３．インストール

```console:Install
$ sudo dpkg -i ~/libtbb-dev_2019U5_armhf.deb
$ sudo ldconfig
$ rm libtbb-dev_2019U5_armhf.deb
```