OmniAICreator/Qiita-1.07M huggingface dataset:
gokartを使ってデータパイプライン上のpandas関連をテストする。

# 書くこと
- gokartを使ってpandas関連の確認をする方法
- 1つ目はinputのpd.Dataframeがemptyだったときに正常終了をするかの確認
- 2つ目はdumpするときに各columnが想定通りの型になっているかの確認

# gokartとは?
- エムスリーやfringe81などが開発しているOSS
- Spotifyが開発しているluigiをラップして使いやすくしている。特にコードを書く量が減る。


# 対象バージョン
- [0.3.11](https://pypi.org/project/gokart/0.3.11/)

# inputのpd.Dataframeがemptyだったときに正常終了をするかの確認
- 下記のコードはpd.Dataframeがemptyのときにエラーが発生する。
- 単体テストを書くことは前提だが、拾いきれないことが多々あった。

```python
class DataTask(gokart.TaskOnKart):
    task_namespace = 'sample'

    def run(self):
        df = pd.DataFrame(dict(user=[1, 2], item=['a', 'b']))
        self.dump(df)


class TaskA(gokart.TaskOnKart):
    task_namespace = 'sample'

    def requires(self):
        return DataTask()

    def run(self):
        df = self.load_data_frame()
        # dfが空のときは`KeyError`が発生する。
        df['user'] = df['user'].apply(lambda x: f'user_{x}')
        self.dump(df)


if __name__ == '__main__':
    gokart.run()
```
- 下記を実行するとemptyでも動くかどうかが確認できる。
- `--test-run-pandas`と `--test-run-namespace=sample`とつける。

```sh
$ python main.py sample.TaskA --local-scheduler --test-run-pandas --test-run-namespace=sample
```

- メッセージ

```
gokart test results:
status=OK; namespace=sample; name=DataTask; id=10f87ddcf3df71d786a023ae5e0bbc98;
status=NG; namespace=sample; name=TaskA; id=44e9690a4d2182a9bed6b6d9730291bd; message=<class 'KeyError'>: user
```

# dumpするときに各columnが想定通りの型になっているかの確認
- pandasの型が意図しない操作により変わっていないかを確認する。
- taskごとに確認してもいいが、namespaceごとにcolumn_nameとtypeの組み合わせを定義する。
- `gokart.PandasTypeConfig`を’継承し、namespace内でのルールを定義する。

```python
class SamplePandasTypeCheck(gokart.PandasTypeConfig):
    task_namespace = 'sample'

    @classmethod
    def type_dict(cls) -> Dict[str, Any]:
        return {'user': int}


class DataTask(gokart.TaskOnKart):
    task_namespace = 'sample'

    def run(self):
        df = pd.DataFrame(dict(user=[1, 2], item=['a', 'b']))
        self.dump(df)


class TaskA(gokart.TaskOnKart):
    task_namespace = 'sample'

    def requires(self):
        return DataTask()

    def run(self):
        df = self.load_data_frame()
        # userの型がintからstrに変更されている。
        df['user'] = df['user'].apply(lambda x: f'user_{x}')
        self.dump(df)


if __name__ == '__main__':
    gokart.run()
```

- 普通にtaskを実行すれば自動的に型がチェックされる。
- この場合だと`user`が`str`に変更されているので、`TaskA`が失敗する。

```shell
$ python main.py sample.TaskA --local-scheduler
```

- メッセージ

```
gokart.pandas_type_config.PandasTypeError: expected type is "<class 'int'>", but "<class 'str'>" is passed in column "user".

...

===== Luigi Execution Summary =====

Scheduled 2 tasks of which:
* 1 ran successfully:
    - 1 sample.DataTask(...)
* 1 failed:
    - 1 sample.TaskA(...)

This progress looks :( because there were failed tasks

===== Luigi Execution Summary =====

```
初級：Rubyでファイルの読み込みクラスを作ろう。

ファイル操作の基礎中の基礎、ファイルの読み込みクラスを作り読み込むだけの処理となります。


・Rubyの参照の基礎

今回はsub.rbに定義したFilereadクラスをmain.rbで使用するため、main.rbの方でsub.rbをrequireで参照します。main.rbとsub.rbは同一ディレクトリに置いてあります。

```main.rb
require './sub.rb'
#この下に、定義したFile処理クラスのインスタンスを生成します。

```
```sub.rb
#ここにFile処理のクラスを定義します。
```
main.rbのrequireのディレクトリはカレントディレクトリを示していますが、'./'を記述することによりカレントディレクトリを明示的なものとしています。この'./'が無い場合はファイルが正しく読み込まれず、次のようなエラーが表示されます。```
require': cannot load such file -- sub.rb (LoadError)
```
・sub.rbにファイル読み込みクラスを定義する
ファイルの読み込みには、ファイルアクセスのためのFileクラスのopenメソッドとreadメソッド、closeメソッドを用います。
基本的な記述はこのようになります。
```
file = File.open("ファイルの名前", "r")
puts file.read
file.close
```
Fileオブジェクトに対してopenメソッドを使います。第一引数にファイル名、第二引数はファイルの読み込みを意味する"r"(readの意味)を与えます。この処理の戻り値をfile変数に格納します。
putsメソッドを用いて、先ほどの処理に対してreadメソッドで処理結果を出力します。
最後に、openメソッドに対してcloseメソッドを用いて、上記の処理を終了させます。


次に、上記の処理をFilereadクラスとして定義します。
initializeメソッドについてです。
main.rbでFilereadクラスのインスタンスがnewメソッドにより生成された際、
一番最初に呼び出されるのがこのメソッドです。
newメソッドに引数が与えられると、このinitializeメソッドに引き渡され、
クラス内で変数として使えるように初期化されます。
したがって、この初期化された変数@filenameはFilereadクラスのスコープ内で有効となります。
newメソッドより引き渡される変数finenameは読み込み処理のためのファイルの名前となります。

次に、readfileメソッドについてです。
initializeメソッドにより初期化された変数@filenameはopenメソッドの引数として用いられています。
readfileメソッドがFilereadクラスのスコープ内に存在するため、この変数を使えます。

```sub.rb
class Fileread
    #initializeメソッドで変数を初期化
    def initialize(filename)
        @filename = filename
    end
    #ファイルの読み出し処理
    def readfile
        file = File.open(@filename, "r")
            puts file.read
        file.close
    end
end
```
最後にmain.rbファイルでFilereadクラスのインスタンスを生成します。

````main.rb
require './sub.rb'

#ファイルの読み込み
file = Fileread.new("./test.txt")
file.readfile
```
sub.rbで定義されたFilereadクラスにnewメソッドを用いて、指定されたファイルを読み込むためのインスタンスを生成します。このファイルの指定の仕方はnewメソッドの引数に読み込みたいファイルの名前と場所を与えることで指定できます。生成されたインスタンスに対して、Filereadクラス内で定義されたreadfileメソッドを用いて、ファイルを読み込むための処理が実行されます。

以上となります。
PHP 2進数, 8進数, 10進数, 16進数の変換

####たまにしか触れなそうなので備忘録としてメモしておきます。

まず、英単語の確認から、、、

2進数　【binary number】
8進数　【octal number】
10進数　【decimal number】
16進数　【hexadecimal number】

```php:qiita.php
$number1 = 55;
    echo decbin($number1)."\n"; //10進数→2進数 110111
    echo decoct($number1)."\n"; //10進数→8進数 67
    echo dechex($number1)."\n"; //10進数→16進数 37
    echo base_convert($number1, 10, 16); //任意の基数を変換 37

$number2 = 100110;

    echo bindec($number2)."\n"; // 2進数→10進数　38
    echo octdec($number2)."\n"; //8進数→10進数　32840
    echo hexdec($number2)."\n"; //16進数→10進数　1048848
    

```
printf()とかはよくわからないので今後暇見つけて勉強します。
react-redux の Hooks API に Generics は要らない

`react-redux` でも、Hooks を利用した API が普及しましたね。この API を利用するうえで、型定義注入方法にコツがありますので共有します。１つのプロジェクトにつき、１つの Store のはずなので、その前提で話を進めます。

```store.ts
export type StoreState = {
  hoge: { hoge: 'hoge' }
  fuga: { fuga: 'fuga' }
}
```

StoreState の型定義方法は数通りありますが、この様な型定義があることが前提です。




## 普通に書くとこうなる

この条件で`useSelector`を利用してみます。`useSelector`の Generics に従い、都度`StoreState`を import し、それを注入しています。なんだかあまりイケてません。

```tsx
import { useSelector } from 'react-redux'
import { StoreState } from '../store'
const Container: React.FC = () => {
  // const _hoge: "hoge"
  const _hoge = useSelector<
    StoreState,
    StoreState['hoge']['hoge']
  >(state => state.hoge.hoge)
  return <Component _hoge={_hoge}>
}
```



## 求めている・実現できるもの

次の様に`useSelector`の Generics は指定しません。そして、`StoreState`の import も不要です。それでいて、型推論がきちんと導かれている状態です。

```tsx
import { useSelector } from 'react-redux'
const Container: React.FC = () => {
  // const _hoge: "hoge"
  const _hoge = useSelector(state => state.hoge.hoge)
  return <Component _hoge={_hoge}>
}
```

これは、実現することができます。





## Ambient Module 宣言で overload する

`StoreState`はライブラリが知ることのできない、プロジェクト固有の定義ですね。`DefaultRootState` という型定義が`@types/react-redux`内に用意されていますので確認してください([v7.1.7](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-redux/index.d.ts#L47))。これを次の様に interface overload すれば、DefaultRootState を参照している内部の API 型定義に StoreState が行き渡る様になります。


```typescript
import 'react-redux'
import { StoreState } from '../store'
// ______________________________________________________
//
declare module 'react-redux' {
  interface DefaultRootState extends StoreState {}
}
```

DefaultRootState の元定義は空っぽですが、この様な注入手法に向けてあらかじめ宣言されています。interface 宣言結合を利用したテクニックであり、様々なライブラリ型定義でも採用されています。この DefaultRootState も styled-components の DefaultTheme をインスパイアしたという旨のPRから生まれています。https://github.com/DefinitelyTyped/DefinitelyTyped/pull/41031



## 他の API にもプロジェクト固有の型定義を注入する

`useDispatch` や `useStore` を利用するたび、プロジェクト固有の型定義を import し Generics 注入するのはスマートではないので、こちらも対応します。

先のコードから新たにプロジェクト固有の型定義として追加しているのは`Actions`です。String Literal Type である `type`プロパティで厳格に識別できるこの型は UnionTypes で表現されます。

```store.ts
export type Actions = { type: "INCREMENT" } | { type: "DECREMENT" }
```

これらも次の様に Ambient Module 宣言していれば、普段型定義を意識しなくとも、`useDispatch` や `useStore` に型推論が適用されます（例えば、プロジェクトに存在しない Action を dispatch することを防ぐなど）。以下は`"@types/react-redux": "7.1.7"`時点で最適と思われる Ambient Module 宣言です。

```typescript
import 'react-redux'
import { Store, Dispatch } from 'redux'
import { StoreState, Actions } from '../store'
// ______________________________________________________
//
declare module 'react-redux' {
  interface DefaultRootState extends StoreState {}
  export function useDispatch<TDispatch = Dispatch<Actions>>(): TDispatch
  export function useStore<S = DefaultRootState>(): Store<S, Actions>
}
```

プロジェクトにおいて１つしか存在しえないインスタンスは、この様に Ambient Module 宣言を積極的に活用しましょう。
Pythonを使ったデスクトップ通知の実装

# はじめに
- ここでは pythonを使ったデスクトップ通知についてまとめます。
- pythonのライブラリーを用いることで簡単に実装できます。
- 以下、使用例（あくまでもこういうに使えるかもといった一例であり、もっと汎用的に使えると思います）
   - ある製品のバッテリー量がリアルタイムに格納されているデータベースがあったとして、バッテリー量のxx％を切った場合に通知。
   - あるサーバーのメモリ使用量がリアルタイムに格納されているデータベースがあったとして、メモリ使用量が80％を超えた場合に通知。
- うまく使うことで作業効率化にも役立てると思います。

# 実行環境

- Windows10
- Python3
    - 使用ライブラリー
        - psycopg2
        - schedule
        - plyer

# 実装例
- 以下のソースコードを実行することで、次のことが実現可能です。
    - 10秒ごとにDBのテーブルに対してSQLを発行して値を取得し、閾値を超えていた場合はデスクトップに通知。
- 今回は例なので、以下のような時間とデータが入っているシンプルなテーブルですが、Viewなどを使って１時間平均にしたデータにするなど様々な形に展開できると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264860/79faab70-ff35-b0b0-ddb7-8c9ac0d1705e.png)

- ソースコード

```python

from plyer import notification
import psycopg2
import schedule
import time

def job(cur):
    alert = ""

    cur.execute("select data from sample order by time desc limit 1;")
    rows = cur.fetchall()
    hoge = rows[0][0]

    if int(hoge) >= 98:
        alert += "hogeが100%に近付いています。"

    if alert != "":
        notification.notify(
            title = "警告",
            message = alert,
            app_name = "モニター監視"
        )


print("監視を開始します。\n基準値付近になるとデスクトップ通知を行います。")

# 接続情報作成
con = psycopg2.connect("host=xxx.xxx.xxx.xxx port=xxxx dbname=xxxx user=xxxx password=xxxx")
cur = con.cursor()

# 指定時間ごとにjobを実行（今回は10秒ごと）
schedule.every(10).seconds.do(job, cur)

while True:
    try:
        schedule.run_pending()
        time.sleep(1)
    except KeyboardInterrupt:
        print("中断しました。")
        cur.close()
        con.close()
        break
```
# 実際の通知画面
- 以下のようなデスクトップ通知が閾値を超えた場合に行われる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264860/06eac956-632b-2c4f-16d0-cd70fdbbecf0.png)
ページを読み込んだ初回にだけ何かしらの処理を実行する方法

#実装方法
javaScriptでページ読み込みをしてクッキー情報を更新する。
１日たったらcookieから指定のデータを消す。

```javascript
if (!document.cookie.match(/name=modal;/)) {
  console.log("クッキーがないからモーダルの処理をします");
}

var one_day = 86400; /* 削除時間を一日の秒数にする */
document.cookie = "name=" + encodeURIComponent('modal'); + "max-age=" + one_day;
```

・参考サイト
[JavaScriptでcookie処理（読み・書き・削除）](https://qiita.com/takanorip/items/4e23b803bb1393176636)
メールを令和化し【添付ファイルのZIP暗号化とパスワード別送】から脱出しようぜ！あと誤送信ミスも！！

## はじめに

**送信先間違ったらワンナウト:point_up:**
**納品物ZIP添付してたらツーアウト:v:**

暗号化ZIPしてたらセーフ:ok_woman:・・・と見せかけて
#### パスワード書いたメールも誤送してたら業務委託先チェンジ！！

そもそも、この運用だと一連の流れがセットで起こりやすいじゃん。。バズ記事にいまさらのっかるようでアレなんだが

[平成のうちにやめたかった『ITの7つの無意味な習慣』](https://qiita.com/spaces/items/39a822050b6e22d35123)

コメント欄の通り致し方なしのもある。ただ、はっきりとデメリットを言えるものとして令和ではパスワードは選手交代してくべきでしょう。PPAP運用を、のほほんと継続してるとその間コンピューターは性能向上するので突如ディスラプションを喰らうわけです。

[GPUでZIPパスワードを解析する](https://qiita.com/lumin/items/cf1e10cccfe5727f8180)

```
秒間100億回と1.8億回試していることになります。
```

**ヒエ～ッ**

誤送信したらパスワード運用してようがガーキャンされる。爆速マシンを一時間だけとかクラウドの力でカジュアルにぶん殴る事もできちゃう(笑)。16文字ぐらい使っててもTwitterやらSNSから情報抜いてAIでパスワード予測もやろうと思えばできるでしょう。逃げれる気がしない。。

注意喚起や啓発記事も大事だ。そもそもSaaSとかOffice365、Gmailとか送信後キャンセルできるの使わないのが悪い。わかる。たしかにそう。
でも僕は手を動かしてもっとほかの選択肢を作ってみたい！！

## こんな仕組みです

![flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/8bf15ad4-2b88-e5ee-d9fe-09ea658dabd4.png)

 - 送信フォームからいつも通りメールします
 - 受信。ただ、受信者にはタイトルとURLがだけ送られてきます
 - 開くとQRが載ってます。受信者がアプリでQR読むと
 - 該当メールに可読フラグがたつので内容が読めます。**やったね！**

実装した技術的には

 - スマホ Cordova + React
 - サーバー Golang + redis + Hyperledger
 - メール表示画面 React + typescript

という無駄な大所帯です。笑　

<details><summary>雑魚コードはこちら</summary>
 - [Hyperledger](https://github.com/yasutakatou/fabcar)
 - [Android apk](https://github.com/yasutakatou/Android-qrscan_and_fetch)
 - [Golang Server](https://github.com/yasutakatou/qrmail_golang_server)
 - [Web画面](https://github.com/yasutakatou/qrmail_web_view)
</details>

## 動作な画面

(ヘボッな)フォーム画面から送信します
![0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/ed7b3cdc-616c-b16d-e8bb-a9b31062d40e.png)
宛先の人がメールを受信します
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/12c0fd63-e374-c772-264e-4dfecdfa3ed1.png)
URLを開くとQRが出てます
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/881a7cfc-bcbd-2c54-26c1-52b25c3fe44c.png)
スマホアプリからメールアドレスを入力します
![00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/17bcc03f-8c98-fec7-b361-be82a5d2641c.png)
QR読ませます
![33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/274ef536-2488-2f0a-e77d-7f437eb83af0.png)
読めました！あと添付ファイルもHTTPS配下で守られています
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/126cded7-1b49-c786-3c29-080951ad0deb.png)

## やっべ！誤送したーの場合

送信時に送り元にQRが届いています。スマホのアプリからメールを入力し、QRを読ませます
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/8116b9f1-6ee4-6023-afe2-821ff3436425.png)
証拠隠滅されました！
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189193/241c0754-da0a-28e4-a953-49e4e5425a13.png)

この仕組みなら通信全体がHTTPSなので添付ファイル付けても安全に取得できるし、削除用QR付ければ誤送信後に取り消しする仕組みも可能。IMEIが危ないってならYubikeyとかFIDOに対応すれば強化できるね！
こんなかんじで既存のメールシステムをラップすれば冒頭の泥試合も無くなるとおもうんだ。どうでしょうかね。

## イキりポイント

<details>
個人的にイキりたいのはHello worldレベルの実装ではあるものの、他のエコシステムと組み合わせることで暗号化をしないでも認証強度を高める部品としてブロックチェーンを使えた事で、これはこれまで「ただのKVSじゃん！」とか「(ブロックチェーンを)使う意味がない」というのとは別次元じゃないっすかね？
見ようと思えば見れちゃう。けどエコシステム上改ざんできないから問題無いよね。しかも利用者側がどんな値か確認できるから運用側まかせじゃない、各自の責でサービス使うよね。って建付けが出来ている。これだ！
なんでブロックチェーンって凄いの？の一片を実装できた気がする。スマートコントラクトには情シスは要らんのさ。満足満足じゃ。
え！？普通無いAPIサーバーの運用はどうするんだって？？？？
</details>
vimrcを晒す

```
syntax on
colorscheme ron

set encoding=japan
set fileencodings=utf-8,iso-2022-jp,cp932,euc-jp
set termencoding=utf-8
set fileencoding=utf-8
set encoding=utf-8

autocmd BufNewFile,BufRead *.js set filetype=javascript
autocmd BufNewFile,BufRead *.es6 set filetype=javascript

autocmd FileType ruby :set ts=2 sw=2 expandtab
autocmd FileType erb :set ts=2 sw=2 expandtab
autocmd FileType slim :set ts=2 sw=2 expandtab
autocmd FileType rake :set ts=2 sw=2 expandtab
autocmd FileType sh :set ts=2 sw=2 expandtab
autocmd FileType javascript :set ts=2 sw=2 expandtab
autocmd FileType yml :set ts=2 sw=2 expandtab
autocmd FileType yaml :set ts=2 sw=2 expandtab

filetype plugin indent on
```
WSLとVSCode使用時にnpm installするとEACCESエラーではまる。

WSLとVSCodeを利用してReact+firebaseアプリの作成中にエラーに遭遇しました。

```bash:functions
npm install --save firebase
...中略...
npm ERR! Error: EACCES: permission denied, rename
'/home/~/functions/node_modules/grpc' 
-> '/home/~/functions/node_modules/.grpc.DELETE'
```

npm install --save firebaseのコマンドを叩くと、上記の権限エラーが発生しインストールが出来ませんでした。

##環境
- Windows 10 Home 1903
- WSL Ubuntu 1804 LTS
- VSCode 1.41.1
    - Remote - WSL 0.41.7

##解決策
**結論から言うと**、VSCodeを閉じて、

```bash:functions
npm install --save firebase
```
 コマンドを打てばインストールできました。


```bash:functions
[grpc] Success: "/home/~/functions/node_modules/grpc/
src/node/extension_binary/node-v57-linux-x64-glibc/grpc_node.node" is installed via remote
+ firebase@7.8.0
```

[こちらのスレッド](https://forum.openzeppelin.com/t/npm-err-error-eacces-permission-denied-rename-wsl-with-vs-code-open/1549/2)によると、
Remote - WSLがファイルをロックしているようです。

ls -laでnode_modules以下の権限を見ると特にrootユーザーになっておらず、また、node_modulesを削除、nodeのバージョンを変えたり、nodebrewを削除してnvmを入れなおしても解決しなかったので、拍子抜けしました。

##参考
[Npm ERR! Error: EACCES: permission denied, rename (WSL with VS Code open)](https://forum.openzeppelin.com/t/npm-err-error-eacces-permission-denied-rename-wsl-with-vs-code-open)
[Resolving EACCES permissions errors when installing packages globally](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally)
[npm installでError:EACCESがでたら](https://qiita.com/Gaddict/items/8c76d92bd0adec2bfb6a)
tmux.confを晒す

```
# option prefix
unbind C-b
set-option -g prefix C-t

# key bind
bind k kill-pane
bind K kill-window
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# mouse
set-option -g mouse on

# Vi風キーバインド
set-window-option -g mode-keys vi
bind v copy-mode \; display "Copy Mode!"
bind -T copy-mode-vi v send-keys -X begin-selection
# `tmux` のコピペとクリップボードの連携
# Linux with xsel
if "which xsel" "bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'xsel -bi'"
if "which xsel" "bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel 'xsel -bi'"
if "which xsel" "bind-key ] run 'tmux set-buffer -- \"$(xsel -bo)\"; tmux paste-buffer'"
# Mac
if "which pbcopy" "bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel 'pbcopy'"
if "which pbcopy" "bind-key -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel 'pbcopy'"
if "which pbpaste" "bind-key ] run 'tmux set-buffer -- \"$(pbpaste)\"; tmux paste-buffer'"

# vim <=> tmux 間でクリップボード利用を可能にする
set-option -g default-command ""

# color
set-option -g default-terminal screen-256color
set -g status-fg cyan
set -g status-bg black
set -g pane-active-border-style "bg=default fg=cyan"

# status bar
set-option -g status-interval 1

# status box left
set -g status-left-length 120
set-option -g status-left '#[fg=cyan,bg=#303030]#{?client_prefix,#[reverse],} #H[#S] #[default]'

# status box right
set -g status-left-length 120
set-option -g status-right '%Y/%m/%d(%a) %H:%M'

# window
bind -n C-S-Left run "tmux swap-window -t -1 && tmux previous-window"
bind -n C-S-Right run "tmux swap-window -t +1 && tmux next-window "

# scroll lines
set-option -g history-limit 10000
```
Pepper SDK入門(10) Animation Browser

これまでは実装方法の話題を続けてきましたが、Pepper SDK PluginにはPepperのアニメーションを作成できるツールやサンプルアニメーションも充実しています。今回からは、そうしたPepper SDK Pluginの使い方を勉強していきたいと思います。

#1.Animation Browserの起動
Animation Browserを利用して、サンプルアニメーションを自分のプロジェクトにインポートする方法を見ていきます。



FileメニューのNewから、Import animation…を選択してください。
![2019-05-16 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574697/28d67360-9ce4-9728-a0af-6bd7b143946d.png)



すると、Animation Browserが起動します。
![2019-05-16 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574697/cf6e264b-3ad6-a613-fb24-f931350924af.png)



#2.アニメーションのプレビュー
アニメーションファイルを選択すると、Animation Browserの右側にアニメーションのプレビューが表示されます。
![2019-05-16 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574697/c0aff0bb-95e1-84fb-4695-3cd58a89fd2c.png)



#3.プロジェクトへアニメーションファイルをインポートする
Animation Browserから選択したアニメーションファイルは、プロジェクトにインポートすることが可能です。アニメーションファイルを選択してSelectボタンを押下、もしくはダブルクリックすることで、プロジェクトのrawディレクトリの下にインポートされるのが確認できます。インポートされたファイルの拡張子は、.qianimです。
![2019-05-24 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574697/ca360c79-29ad-68a1-a556-1ef37c790efe.png)





#4.プロジェクト内アニメーションファイルのプレビュー
Androidプロジェクト内のアニメーションファイルは単独でプレビューが可能です。アニメーションファイルを右クリックし、Previewをクリックしてください。
![2019-05-24 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574697/4148f6b4-58f1-a830-1ceb-27d768f8d3c1.png)



するとAnimation viewerが起動し、選択したアニメーションのプレビューが表示されます。
![2019-05-16 (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574697/50b28d89-5b49-db4d-6604-372126ef4eae.png)





以上で、Animation Browserの使い方が確認できました。
torchvision.transformasで画像をクロップせずにリサイズする

関数名から、`transforms.Resize()`を素朴に使った方が良いのに、なぜか`transforms.RandomResizedCrop()`で、強引にリサイズしていた。

### オリジナル
![dog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578852/1fb380ef-5b86-1d17-98d8-36ae77f994b1.png)

## よく使われているやり方？
scaleとratioに(1.0, 1.0)を入力する。

```
transforms.Compose([
    transforms.RandomResizedCrop(size, scale=(1.0, 1.0), ratio=(1.0, 1.0)),
    transforms.ToTensor(),
])
```
![dog_rc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578852/8659143d-87ad-5941-9f1f-aee2fa74ff56.png)
クロップされている。

## クロップされないやり方
```
size = (244, 244) # 縦横を揃えたい場合はtupleで入力
transforms.Compose([
    transforms.Resize(size),
    transforms.ToTensor(),
])
```
![dog_r.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578852/084bd698-b6d4-1ad6-ee44-8cb772d25f5a.png)
クロップされていない！


データセットの性質によってはクロップした方が良い場合もあると思うので、ケースバイケースで。
【2つの解決法】rails コマンドのエラーincompatible library version ~~~~~(LoadError)

環境
ruby 2.7.0
Rails 5.2.0


突然rails コマンドが動かなくなりました。


今回ですと常に下記のエラーが付き纏います。

```
incompatible library version - /Users/shogo/environment/insta-clone/vendor/bundler/ruby/2.6.0/gems/msgpack-1.3.1/lib/msgpack/msgpack.bundle (LoadError)
```

msgpackかと思い、調べてみたのですがなかなか見つからず。

incompatible library version で検索しても見つからず。




## 原因：incompatible library version（ライブラリの互換性）

incompatible＝互換性という意味になります。

library version＝ライブラリのバージョンです。

つまりディレクトリ（現在作業しているアプリ）で使っているrubyのバージョンとgemに互換性がないから


・エラーでてるgemを削除しろ
・またはrubyのバージョン上げろ
・またはrubyのバージョン下げろ

って話。

下記記事をみつつ、バージョンを上げたり下げたりしてみましょう。
https://qiita.com/pipi_taro/items/9c9a6ccc110b159b967b


ローカル環境のrubyを使っている際（つまりエラーでてるアプリにインストールされているrubyとローカル環境で設定しているrubyのバージョンが異なる場合）には、パス指定でうまくいく可能性もありますね。

パス指定する

```
[[ -d ~/.rbenv  ]] && \
export PATH=${HOME}/.rbenv/bin:${PATH} && \
eval "$(rbenv init -)"
```


which rubyでパスが変更したか確認する

```
/Users/shogo/.rbenv/shims/ruby
```


エラー文にmsgpackと記載してあるのに、原因は互換性の問題らしい。非常にわかりにくい。


## 原因②:bundle installをする際にパスを指定していない

原因1では解決しなかったので、エラー文をもう一度みると

```
~vendor/bundler/ruby/2.6.0/gems/msgpack-1.3.1/~
```

ruby/2.6.0と書いてあります。
実際にアプリ内で使用しているバージョンは2.7.0です。

実際にvendor/bundler/rubyをみてみると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568461/bbe88bf6-34da-2628-459e-c3db46b47024.png)

2.6.0と2.7.0があるわけですね。

とりあえずバージョンがずれているので下記記事をみつつ、bundleinstallする際にパスを指定することにしました。
https://qiita.com/okuramasafumi/items/1aea3ed27763315328a3

```
$ bundle install --path vendor/bundle
```

そしてrails sが成功。

どうやら```--pathオプション```をつけるのは開発時においては必要ないが、異なるバージョンのgemが混ざるのが嫌な人はつけた方が良いとのこと。

プロジェクト下のディレクトリ（例えばvendor/bundle）にgemをインストールすることで、グローバルにインストールされたgemと、bundlerが管理するgemを分離することと書いてあります。


要はrubyのインストールでいうlocal設定とglobal設定と分けることによって作業するディレクトリによってrubyのバージョンを変えられますよ的な話に近しいものだということだと思います。（もう少し理解できれば書き加えます。）

もうちょいわかりやすいエラー文にして欲しいところ。


なぐり書きなので疑問がありましたらコメントください。
ReactRouter v4 でpathに変数と正規表現を用いる方法



```javascript

<BrowserRouter>
  <Switch>
    <Route path={`${hoge}/fuga/:id(\d+)`} component={MyComponent} />
  </Switch>
</BrowserRouter>
```

ReactRouterでpathに変数と正規表現を用いたい時、
上のように、テンプレートリテラル(文字列の中に変数を含める書き方)を用いて、
pathに変数を含め、正規表現のチェック(:idが整数である)を行おうとしてもうまく行かない現象でハマりました。
 
###原因

JavaScriptのテンプレートリテラルではバックスラッシュをそのままでは扱えない(エスケープする必要がある)
###解決策
```javascript

<Route path={`${hoge}/fuga/:id(\\d+)`} component={MyComponent} />
```
バックスラッシュを2個にしてあげると、うまく動作します。


参考URL: https://stackoverflow.com/questions/43067371/react-router-v4-regex-dont-like-template-literals
ChromeでうまくいったものをIEにするとうまくいかなかったこと事例

###はじめに

WEBページ制作においてどのブラウザでも表示できることはとても大切だと思います。
今回Chromeでうまく表示できていたものがIEではうまくできなかったことと、解消方法を備忘録として記載します。事例が追加されれば追記したいと思います。

##① 画像が表示できない

Chromeでは問題なく表示できていた画像がIEだと出てこない。。。。orz

####解決方法
調べるとカラーモードが **「CMYK」** になっているとIEでは表示されないとのこと。
画像軽量化ツールを利用し画像を軽量化することで解決できました！

■参考サイト
[JPGなどの画像が表示されない原因、チェックしたいこと まとめ](https://for-someone.com/blog/4799/)

##② flex-directionを指定すると余計な余白が発生する

Chromeでは出なかった不自然な余白がIEで発生し、確認したところflex-directionを指定している箇所でした。

どうやら `flex-direction` に `column` や `column-reverse` を指定した子要素に画像があると、その子要素に画像の元サイズの高さ分のスペースができてしうとのことです。この元サイズの高さ分のスペースを消す必要があります。


####解決方法
`min-height: 0%;` を指定することで解決できました！

■参考サイト
[flex-directionを指定した時に IE11で表示がおかしくなる](https://web-pixy.com/flex-direction-ie/)


###まとめ

まだまだ初心者なのでブラウザごとに表示状況が変わっていることにかなりストレスを感じていましたが、きちんと調べて対処していけば解消できる（と思う）ので、これからもトライしていきます。

また、これからまだまだたくさんでてくることだと思うので随時更新していきます！
Laravel: artisanコマンドで値を取るオプションがコマンドラインで指定されていたかどうかを判定する

# 目的

値をとるオプションを持ったコマンドでオプションがコマンドラインで与えられなかった場合とオプションがあったが値が省略された場合を区別したい。

```console
% php artisan foo
```

```console
% php artisan foo --hoge
```

たとえばこのコマンドのsignatureが以下のようだったとすると

```php
protected $signature = 'foo {--hoge=default}';
```

`$this->option('foo')`はどちらの場合も`'default'`を返し区別がつかない。

# 回答

`\Illuminate\Console\Command`にはこれを区別できるメソッドは用意されていないが、`input`プロパティに入っている`\Symfony\Component\Console\Input\Input`の`hasParameterOption`が使える。

```php
<?php
namespace App\Console\Commands;

use Illuminate\Console\Command;

class Foo extends Command
{
    protected $signature = 'foo {--hoge=}';

    public function handle()
    {
        if ($this->input->hasParameterOption('--hoge')) {
            $this->line('--hogeオプションが与えられています');
        } else {
            $this->line('--hogeオプションは与えられていません');
        }
    }
}
```

```console
% php artisan foo
--hogeオプションは与えられていません
% php artisan foo --hoge
--hogeオプションが与えられています
```

# 余談

実は'hasParameterOption'は省略可能な第2引数`$onlyParams`(デフォルトは`false`)があって、これによって`--`から先のコマンドライン引数を含めるかどうかを指定できるようなことが書いてありますが、そもそもLaravelの場合に`--`で引数を区切ってそこから先は無加工で受け取るようなコマンドの書き方がわからないのでとりあえず無視しています。
HTML & CSS超入門

#1．はじめに
タイトルとして超入門とつけたがここではHTML&CSSについて全くと言っていいほど網羅しておらず、私としてややこしいがwebサイトを作り上げていこうとする際に必須になるであろう知識についてまとめた。申し訳ないが網羅的に学ぼうと訪れた方にはこのページは向いてないので他のサイトを参考にしてほしい。しかしHTML&CSSの基礎をある程度学んだうえで納得できないもしくは理解できない部分がある際にはこのサイトが役に立つと信じている。ここでは大きく3つの重要事項についてまとめた。
#2.HTML&CSS
１．**margin: 0 auto;とtext-align: center;の違い**

この2つは要素を中央寄せにしたいときに使う。2つの大きな違いはインライン要素に使うかブロック要素に使うかということである。margin: 0 auto;の場合は初期値としてコンテンツエリア親要素の100%目いっぱいに広がるので同時にwidthも指定しないと中央寄せが適用されているのかわからない。


２．**rgba、opacityの違い**

要素を透過させるにはrgbaもしくはopacityを用いる。しかし両方とも同一の働きをするのではなく、それぞれ違いがある。opacityには要素のすべてを透過してしまうという性質があるのに対し、rgbaには背景色のみを透過する性質がある。この2つは場面場面で使い分けなければならない。


３．**positionプロパティの使い方**

positionプロパティは要素の位置を決定するときに用いる。値の種類にはstatic,relative,absolute,fixedがある。staticは初期値で、absoluteはサイト全体の右上を基準にして、要素を移動させることができるプロパティ、relativeはその要素の親要素に指定することで親要素の右上を基準にして、要素を移動させることができるである。fixedを用いることで常に要素を画面上の指定した位置に固定させておくことができる。これらのプロパティはtop,left,right,bottomを用いて指定する。positionを使用することで要素同士が重なり合うということが発生する。この重なりはz-indexプロパティを使用することでコントロールすることができる。このプロパティの値に数字を指定することでその数字の大きい順に要素が上から配置されていく。position: relative;は子要素の位置を決定する際に基準となる親要素の位置を決定するものであったが、要素の位置の変更に用いることもできる。position: relative;topやleftと同時に指定することでもともとその要素があった位置から指定した分だけずらすことができる。

  

#3．参考
サルワカ https://saruwakakun.com/html-css/basic/relative-absolute-fixed

Webpark http://weboook.blog22.fc2.com/blog-entry-282.html

progate https://prog-8.com/
【Linux/資格】 linuC102　受験記録とlinuC レベル１認定

表題でほぼすべてですが。
いちおう結果と感想です。

###結果
800点満点中666点。(60問中50問正解？)
合格でした。

###勉強法、期間
直前にOracle認定Java Programmer試験を受験していたので、linuC102の学習期間としてはほぼ１週間もない程度でした。
使用したのはping-tのWeb問題集のみです。
コマンドを実際に打って確認してみるような環境も特に用意しませんでした。

ping-tの使い方としては
１．最初の１単元をランダムに20-30問繰り返し解く
　　↓その単元全体の回答率・正解率が８０％程度
２．次の単元を加えてまたランダムに20-30問繰り返し解く
　　↓全体の回答率・正解率が８０％程度
３．次の単元を加えて・・・
　　↓最後の単元までの全体で回答率・正解率が８０％程度
４．模擬試験モード(60問)
　　↓安定して正解率が85%以上
５．コマ問(コマンド入力形式の問題)で”選べる”→”書ける”へ

という感じです。

コマ問を完璧に解ける、というレベルは時間的に厳し過ぎたのと、
選択式がきっちり押さえられていれば合格はカタイ、という判断で、
コマ問は試験前日の午後からのんびりやりました。

###感想
体感としてlinuC101の時より、「あ、これping-tで見た」という問題が多かったです。（試験対策の問題集として、良問が多かったというコトだと思います）
linuC101の時もping-tを使って試験対策しましたが、「こんなトコ意識してない／勉強してない！」っていう問題が多く結果もギリギリでの合格だったので、linuC102はそれに比べると問題解いてる最中から「これはいける」という確信もあり、気持ち的にラクでした。

あとはlinuCは101,102セットで「レベル１認定」という認識がなく、101に合格したのにEDUCOに認定の表示が出ないので困惑していましたが、102に合格して無事レベル１認定が表示されるようになりました。

<img width="359" alt="スクリーンショット 2020-02-03 14.41.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126315/626d3973-d197-2223-328d-0d05f91b17be.png">

ひとつの認定で２つの試験受けないといけないの大変ですが、頑張ってレベル２、レベル３取っていきたいと思います。
Rubyでバージョン番号の比較をする

# はじめに
Rubyでバージョン番号を比較したいと考えた時に、そのままの比較では正しく動作しません。たとえば、以下のケースです。

```ruby
# 文字列同士の比較は辞書順
'3.10' >= '3.2'
# => false

# 文字列と数値の比較
'2.3.0' >= 2.2
# ArgumentError: comparison of String with 2.2 failed

# Rubyのバージョン比較
'2.8.0-dev' > '2.8.0'
# => true
```


バージョン番号については[Gem::Version](https://docs.ruby-lang.org/ja/latest/class/Gem=3a=3aVersion.html)を用いることで、上記のケースを考慮しなくてもよくなります。それを利用して、下記のようにバージョン番号の比較が行えます。

```ruby
Gem::Version.create('3.10') >= Gem::Version.create('3.2')
# => true

Gem::Version.create('2.3.0') == Gem::Version.create(2.2)
# => false

Gem::Version.create('2.8.0-dev') > Gem::Version.create('2.8.0')
# => false
```

しかし、逐一``Gem::Version.create``を利用して比較するのは大変なのでメソッドにしてみました。


# 作ったもの
```ruby
ALLOWED_OPERATORS = %w(> >= == < <=)

def compare?(target_version, operator, comparison_version)
  raise "invalid operator: #{operator}" unless validate_operator(operator)
  version(target_version).send(operator, version(comparison_version))
end

def validate_operator(operator)
  operator.is_a?(String) && ALLOWED_OPERATORS.include?(operator)
end

def version(number)
  Gem::Version.create(number)
end
```

# 使い方
```ruby
compare?('3.10', '>=', '3.2')
# => true

compare?('2.3.0', '==', '2.2')
# => false

compare?('2.8.0-dev', '>', '2.8.0')
# => false
```
並び順も意識しているので見た目としても分かりやすいと思います。


# 参考
[Rubyでバージョン番号を比較するするときはGem::Versionでできる - コード日進月歩](https://shinkufencer.hateblo.jp/entry/2018/09/13/235900)
[omichelsen/compare-versions: Compare semver version strings to find which is greater, equal or lesser.](https://github.com/omichelsen/compare-versions)
Google HomeでAirPlayが使えればHomePodがいらないんじゃないか説

# はじめに
こんにちは。Apple信者です。
今回は、**Google HomeをAirPlay経由でワイヤレススピーカーにしてみた**ので、記事にしてみました。

なお事項から僕のどうでもいい自分語りが始まりますので、興味ない方は本文へ

## HomePodってイマイチ説

僕はAppleユーザーの一人です。
パソコンはMac。iPhoneとiPadを使い、アマプラはAppleTVで見る。イヤホンはAirpods、腕時計はもちろんApple Watch。
AirDropやContinutityなどのAppleエコシステムにどっぷり染まっています。

僕にとってAppleにお布施をするのはもはや使命なんですが、いまだに買えていないApple製品があります。
[HomePod](https://www.apple.com/jp/homepod/)です。

いろいろなレビューサイトで見てはいるんですが、結論、個人的にあまり魅力を感じないのです。
個人的な評価はこんな感じ

* 僕自身、音質に強いこだわりはない
* Siriの使い勝手が悪い
* AppleMusicしか使えないのは❌
* **高い**

自分のニーズポイントにフィットしないので、イマイチ買う気になれません。

## Google Home使ってます

最近のスマートハウスの流行に乗って、昨年家電の一部をスマート化させました。
その時、音声インタフェースとして**Google Home**を選択。

`Nature Remo`との相性も良く、音質も悪くなく（個人主観）、なにより誤認識が少ない。
エアコンや電気をつけるなど、日常的にGoogle Homeを使っています。

## モニターにスピーカーがついていない

パソコン用とAppleTV用で机に２枚のモニターを置いているのですが、ケチったせいもあってどっちも**スピーカーがついてない**んです。

「音出したいしスピーカー欲しい」
「Apple使っとるし、AirPlay対応スピーカーがええな」
「でもHomePodは高いしなぁ……」
「今使っとるGoogle Homeが、AirPlay使えたらええんやけどなぁ……」

というわけで、Google HomeでAirPlayを使ってみよう。というのが今回のもくろみ。

# 本題

お待たせしました。ここからが本文です。

普通にググったら出てきました。こちらです。

https://github.com/philippe44/AirConnect

UPnP対応機器や、ChromecastなんかをAirPlayとして使えるようにするらしい。素晴らしいじゃないか。

## 使ってみる

自宅のホームサーバーで動かしてみます。といってもただのmacOSなので、バイナリを起動するだけでした。

https://github.com/philippe44/AirConnect/tree/master/bin

ここから環境に合うものをダウンロードしてきます。僕の場合はmacosで、かつGoogle Homeが目的だったので、[aircast-osx-multi](https://github.com/philippe44/AirConnect/raw/master/bin/aircast-osx-multi)でした。

起動方法も、ダウンロードしたバイナリファイルに対して

```sh
./aircast-osx-multi
```

とするだけ。
え、本当に認識するの？

と疑りながら見てみると…

<img width="100%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265811/dc895ba9-b381-1198-5d61-de59ce5c4e6e.png">

出ました。GoogleHomeがおる。

もちろん接続できますし、音量調整なんかもできます。

### OS起動時に自動実行させる
こちらもReadmeに書かれていました。
macの場合は、`~/Library/LaunchAgents/`に以下のファイルを配置するだけ(pathは書き換えてください)。

```xml:com.aircast.bridge.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.aircast.bridge</string>
    <key>ProgramArguments</key>
    <array>
        <string>/[path]/aircast-osx-multi</string>
	<string>-Z</string>
        <string>-x</string>
        <string>/[path]/aircast.xml</string>
        <string>-f</string>
        <string>/[path]/aircast.log</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>LaunchOnlyOnce</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
</dict>
</plist>
```

Linuxの方法はREADME見てください。

## docker上で動かす

自分用サービスを一通りdockerで動かしているので、管理をしやすくする為にdockerで動かしました。

といってもイメージが配布されていますので、ちょっと`docker-compose.yml`を書いただけです。

```yml
version: "3"

services:
  airconnect:
    image: 1activegeek/airconnect
    restart: always
    network_mode: "host"
```

ホストのIPをそのまま使用するので、`network_mode: host`を入れています。

これを

```sh
docker-compose up -d
```
するだけ。超簡単。素敵。

# 〆

MacからもAppleTVからもiPadからもiPhoneからも、好きな端末でサクッとGoogle Homeから音楽が流せるようになりました。
今回はGoogleHomeでしたが、好きなUPnPデバイスや、Chrome Castを使ってAirPlayできるみたいなので、是非お試しください。

Siriは使えなくとも、優秀なGoogle Assistant使いながらAirPlayでサクッと音楽流せるし、HomePodいらないんじゃないですかね。

ん？ 信仰心が足りない？ 
……ｳﾙｾｴ
AKSのコンテナログをLogAnaliticsから検索

AKSのモニタリングアドオン有効化(要LogAnaliticsのワークスペース)するとコンテナの標準出力が自動的にCotainerLogというテーブルに入って過去のいないPodのログも見られるけど、構造化されてないログをKustoでパースすると正規表現で頑張るしかなかったのでcsvかjsonでログを吐くようにLogFormatの設定変えたほうがいいんじゃないかと思いました。
ContainerInventoryテーブルとCotainerIDでjoinしたらImage名とれました。

```
ContainerLog
| where LogEntry !contains "kube-probe/1.1"
| join kind = inner
(
    ContainerInventory
)
on ContainerID
| extend HttpStatusCode = extract(" ([2-5][0-9]{2}) ", 1, LogEntry)
| extend Serverity1 = extract(" \\[([a-z]*)\\]", 1, LogEntry)
| extend Serverity2 = extract(" (DEBUG|TRACE|INFO|ERROR|WORNING) ", 1, LogEntry)
| project Image1, LogEntry, HttpStatusCode, Serverity1, Serverity2
//| where Image1 == "<my-image-name>"
//| limit 50

```
つかえるっぽい正規表現
https://github.com/google/re2/wiki/Syntax
関数
https://docs.microsoft.com/en-us/azure/kusto/query/extractfunction
パースマニュアル
https://docs.microsoft.com/en-us/azure/azure-monitor/log-query/parse-text
SQL脳チートシート
https://docs.microsoft.com/ja-jp/azure/azure-monitor/log-query/sql-cheatsheet

あとomsagentはnamespace単位で出したり出さなかったりの制御はできるらしいconfigmapの設定方法をみた↓
https://docs.microsoft.com/ja-jp/azure/azure-monitor/insights/container-insights-agent-config
namespaceを制御するとかはできるけどそれ以外何か細かいフィルタしたい場合、出す側でなんかするか別のlogshipperで飛ばすという話になるのかなと思いました。
もしomsagentで収集したPrometheusのNodeデータをAzureLoganalyticsのInsightMetricsテーブルに入れたいという場合はNodeExporterを別途入れて、そのポート番号を設定ファイル側と合わせて設定をするとよい模様。メトリクスの取得間隔 (interval) や、収集するフィールドの設定 (fieldpass/fielddrop) は制御できる模様。


前月を出したい場合は、以下のような感じにすると2,4,6,9,11月もきっちり1か月分でます。

```
let now = now();
let requireMonth = datetime_add('month', -1, todatetime(now));
let startDate = startofmonth(requireMonth);
let endDate = endofmonth(requireMonth);
ContainerLog 
| where LogEntry !contains "kube-probe/1.15"
| where TimeGenerated between(startDate .. endDate)
...
```
JSONをTypeScriptの独自型定義にさっくり変換

## 独自型定義

```ts
const obj: MyObj = JSON.parse('{"name": "jack", "age": 8}'); 

interface MyObj {
  name: string;
  age: number
}
```

## Array<独自型>

```ts

const objList: Array<MyObj> = JSON.parse('[{"name": "jack", "age": 8}, {"name": "john", "age": 10}]'); 

interface MyObj {
  name: string;
  age: number
}
```

他にいい方法があれば教えてクレメンス
開発プロパガンダ10の法則

戦争プロパガンダ10の法則
戦争プロパガンダ10の法則とは、第一次大戦から現在の第二次湾岸戦争までの戦争の歴史の中で戦争プロパガンダには１０の法則があり、それが戦争の度に巧妙に使われているということを歴史家アンヌ・モレリがまとめたものである。10の法則とは以下の通りである。
[1] 我々は戦争をしたくない。
[2] しかし、敵側が一方的に戦争を望んだ。
[3] 敵の指導者は悪魔のような人間だ。
[4] 我々は領土や覇権のためではなく、偉大な使命のために戦う。
[5] 我々も誤って犠牲を出すことがある。だが、敵はわざと残虐行為におよんでいる。
[6] 敵は卑劣な戦略や兵器を用いている
[7] 我々の受けた被害は小さく、敵に与えた被害は甚大。
[8] 芸術家や知識人もこの戦いを支持している。
[9] 我々の大義は神聖なものである。
[10] この戦いに疑問を投げかける者は裏切り者である。

開発プロパガンダ10の法則
[1] 関数型言語を使え。
[2] 開発はスクラムで進めろ。
[3] ミーティングには名前をつけろ、アルファベット3文字が効果的だ。
[4] AWSを使わないエンジニアは時代遅れだ。
[5] 質問には「それはもう既にありますね」とだけ答えればよい、どうせ質問者も知らないのだから。
[6] 最新のJavascriptフレームワークを使え、これを使うだけで時代の最先端だ。
[7] XMLはクソだ、JSONは冗長だ、YAMLは最高だ。
[8] ビジネス職を納得させるのは簡単だ、グーグルがやっていると説明すればよい。
[9] 並列に計算させろ、大規模にシステムを組め、過大なシステムコストからスタートだ、伸びしろは残しておけ。
[10] スライダーを右に動かせ、システムは信じられないほど高速に動作するぞ。
Play framework の scheduled jobs と crontab



play framework では、ある処理を定期実行できる Jobクラスがありその間隔は以下のように `@On()`　のカッコ内に書く

```java

import play.jobs.Job;
import play.jobs.On;

@On("*/2****")
public class xxxxx extends Job<Void>

```

時間間隔の設定にはcrontabの表記が使えて、以下のサイトがめちゃわかりやすい。

[https://crontab.guru/#*/15_*_*_*_*](https://crontab.guru/#*/15_*_*_*_*)

※後ろのアスタリスク（*）は間にスペースが必要なことに注意。


crontab コアンド初めて知ったが、めちゃクチャ便利では
BiometricPrompt 対応機種

アプリを生体認証させるためのAPIである「BiometricPrompt」についてまとめます。

## 対応バージョン

Android 9 以降

Android 9 未満の場合は、AndroidXのサポートライブラリを使うことにより、Android 6 以降であれば使えるみたいです。（未確認）

## 対応機種

認証機能が搭載されていても、BiometricPromptに対応していないものがありましたので分かり次第まとめておきます。

| Model | Biometric Authentication | 備考 |
| --- | --- | --- |
| Pixel 3 / 3XL | 顔認証OK |
| Xperia XZ1 | 指紋認証OK |
| AQUOS sense2 | 顔認証NG | 顔認証はプリインされているが画像処理 |

### Reference

ドコモ対応機種
https://www.nttdocomo.co.jp/service/bio/compatible_model/security_face_attestation.html

## Sample Code

これで動きました。ただ、生体認証を予めOSで設定しておく必要があります。

```Kotlin
package sec.co.jp.biometrics

import android.content.DialogInterface
import android.hardware.biometrics.BiometricPrompt
import android.os.Bundle
import android.os.CancellationSignal
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity

class SubActivity : AppCompatActivity() {

    private lateinit var cancelSignal: CancellationSignal

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sub)
    }

    override fun onResume() {
        super.onResume()
    }

    private fun auth_check() {
        Log.d("test", "auth_check")

        cancelSignal = CancellationSignal()
        val builder = BiometricPrompt.Builder(this)
        builder.setTitle("生体認証します")
        builder.setNegativeButton("キャンセル", mainExecutor, DialogInterface.OnClickListener { dialogInterface, i ->
            cancelSignal.cancel()
            Toast.makeText(this@SubActivity, "キャンセル", Toast.LENGTH_SHORT).show()
        })
        builder.build().authenticate(cancelSignal, mainExecutor, object: BiometricPrompt.AuthenticationCallback() {
            override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                when (errorCode) {
                    BiometricPrompt.BIOMETRIC_ERROR_NO_BIOMETRICS ->
                        Toast.makeText(this@SubActivity, "非対応です。", Toast.LENGTH_SHORT).show()
                    else -> {
                        Toast.makeText(this@SubActivity, "その他のエラーです。", Toast.LENGTH_SHORT).show()
                        // 所定回数失敗すると生体認証ダイアログすら出なくなる
                    }
                }
            }

            override fun onAuthenticationHelp(helpCode: Int, helpString: CharSequence) {
                throw RuntimeException("Stub!")
            }

            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                Toast.makeText(this@SubActivity, "認証成功です。", Toast.LENGTH_SHORT).show()
            }

            override fun onAuthenticationFailed() {
                Toast.makeText(this@SubActivity, "認証失敗です。", Toast.LENGTH_SHORT).show()
            }

        })
    }

}
```

## Reference
【Android】BiometricPromptと指紋認証機能の実装方法について
https://qiita.com/hotdrop_77/items/75fa88fbcb1594338047

[Android / Kotlin] BiometricPrompt(生体認証)をちょっとだけ
https://qiita.com/takusan_23/items/ef58699924cf3e07e377

Android 9 PieのBiometricPromptをさらっと試した
https://qiita.com/devnokiyo/items/1fa9ad291a6211ef1595
Cognos Analyticsレポートでリストのセル内に棒グラフ表示

#Cognos Analyticsレポートでリストのセル内に棒グラフ表示
つまりこういう表示のレポートの作り方です。
最近質問されましたので、ついでに投稿しておきます。
<img width="273" alt="010.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/dc737a76-0e1d-e223-7355-9b00f9d74e88.png">


#手順
レポートを「GOデータウェアハウス(クエリー)」パッケージで新規作成し、リストに「製品ライン」「製品タイプ」を置きます。
※リストのクエリーが「クエリー1」
<img width="393" alt="001.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/078ac403-bf78-4910-860d-e7c3e2048823.png">

リストの右端の列（※リスト外ではない）に、「視覚化」をドロップします。
<img width="633" alt="002.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/7620d83c-7268-5315-55b4-0a678b4ed9d2.png">

プルダウンから「グラフ」を選択し、「マイクログラフ」の中から「横棒グラフ」を選択します。
<img width="688" alt="003.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/8faf5063-72f4-5e1e-4f4c-08cef50967cb.png">

この状態にして下さい。
ずれてリスト外に横棒グラフが配置されてしまった場合は、横棒グラフの左上部分をつかんで、リストの右端列にドラッグ&ドロップしてください。
※横棒グラフのクエリーが「クエリー2」
<img width="286" alt="004.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/58771afc-f322-7346-a275-36547ef13474.png">

以下のように、X軸に「数量」、Y軸に「製品ライン」「製品タイプ」を置きます。
<img width="640" alt="005.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/85f06369-aff4-cfe0-b6bb-9cb9a4a4d700.png">

横棒グラフのプロパティから「マスター/詳細の関係」を選択し、「リンクを新規作成」ボタンでリンクを作成し、「製品ライン」同士、「製品タイプ」同士を図のようにリンクさせます。
※マスター「リスト(クエリー1)」と詳細「横棒グラフ(クエリー2)」の間で、「製品ライン」「製品タイプ」同士で関係を持たせています。
<img width="672" alt="006.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/8aea4826-60bf-33aa-1ebe-8dc06cfbb3df.png">

「サイズおよびオーバーフロー処理」から、幅を「125px」、高さを「25px」とします。
<img width="593" alt="007.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/6f4680f0-9c34-dc06-e25f-97791c83923d.png">

「組み合わせグラフ」のプロパティの「テキスト」で「数量」と入力します。
<img width="714" alt="008.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/69daf149-365b-f02f-08ac-f8119b31679c.png">

レポート実行すると、以下のようにリストのセル内に、「製品ライン」「製品タイプ」の「数量」に応じた長さの横棒グラフが表示されます。
横棒グラフにカーソルをあてると、Tipsで実際の数量の値が見れます。
<img width="343" alt="009.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147246/74ea9770-3a2d-1b64-8cb7-f887e55ef308.png">

ご活用下さい！

#参考
過去の以下のようなJavaScriptを使ったやり方も投稿しています。
**Cognos レポートでリストのセルに棒グラフを表示するお手軽なやり方**
https://qiita.com/shinyama/items/2c64d8167c3324ae9700
Vue.jsで親から子のコンポーネントにデータを渡す方法4つ

props、$children、ref、slotがある。

# props
```html
<!DOCTYPE html>
<title>props</title>

<div id="app">
  <app-component v-bind:message="parentMessage"></app-component>
  <button v-on:click="onClick">クリック</button>
</div>

<script src="https://unpkg.com/vue@2.5.17"></script>

<script>
Vue.component('app-component', {
  template: '<h1>{{ message }}</h1>',
  props: {
    message: {
      type: String,
      default: 'これは子のコンポーネント'
    }
  }
})

new Vue({
  el: '#app',
  data: {
    parentMessage: '親から渡してるよ'
  },
  methods: {
    onClick: function () {
      this.parentMessage = 'クリックしたら変わるよ'
    }
  }
})
</script>
```

# $children
```html
<!DOCTYPE html>
<title>$children</title>

<div id="app">
  <app-component></app-component>
  <button v-on:click="onClick">クリック</button>
</div>

<script src="https://unpkg.com/vue@2.5.17"></script>

<script>
Vue.component('app-component', {
  template: '<h1>{{ message }}</h1>',
  data: function () {
      return {
        message: 'これは子のコンポーネント'
      }
  }
})

new Vue({
  el: '#app',
  methods: {
    onClick: function () {
      this.$children[0].message = 'クリックしたら親から渡すよ'
    }
  }
})
</script>
```
> $children に対して順序の保証がなく、リアクティブでないことに注意してください。

公式ドキュメント https://jp.vuejs.org/v2/api/index.html#vm-children より引用。

# ref
```html
<!DOCTYPE html>
<title>ref</title>

<div id="app">
  <app-component ref="ac"></app-component>
  <button v-on:click="onClick">クリック</button>
</div>

<script src="https://unpkg.com/vue@2.5.17"></script>

<script>
Vue.component('app-component', {
  template: '<h1>{{ message }}</h1>',
  data: function () {
      return {
        message: 'これは子のコンポーネント'
      }
  }
})

new Vue({
  el: '#app',
  methods: {
    onClick: function () {
      this.$refs.ac.message = 'クリックしたら親から渡すよ'
    }
  }
})

</script>
```

# slot
```html
<!DOCTYPE html>
<title>slot</title>

<div id="app">
  <app-component><h1 slot="message">{{ parentMessage }}</h1></app-component>
  <button v-on:click="onClick">クリック</button>
</div>

<script src="https://unpkg.com/vue@2.5.17"></script>

<script>
Vue.component('app-component', {
  template: '<div><slot name="message">これは子のコンポーネント</slot></div>'
})

new Vue({
  el: '#app',
  data: {
    parentMessage: '親から渡してるよ'
  },
  methods: {
    onClick: function () {
      this.parentMessage = 'クリックしたら変わるよ'
    }
  }
})
</script>
```
ansible事始め

CentOS7にて

# インストール

```
sudo yum install ansible
```

# コンフィグ

```:/etc/ansible/ansible.cfg
[defaults]
fact_caching = jsonfile
fact_caching_connection = /var/tmp/ansible/cache
fact_caching_timeout = 315360000
forks = 50
gathering = smart
inventory=<< YOUR GIT REPOSITORY >>
log_path = /var/log/ansible/ansible.log
retry_files_enabled = False
private_key_file = << YOUR PRIVATE KEY >>
[inventory]
[privilege_escalation]
[paramiko_connection]
[ssh_connection]
[persistent_connection]
[accelerate]
[selinux]
[colors]
[diff]
always = yes
context = 3
```

ディレクトリ掘る

```
mkdir -p /var/log/ansible
mkdir -p /var/tmp/ansible/cache
```

インベントリの`hosts`ファイルに記述する

対象のサーバのauthorized_keysに.pubの中身を追記する。

試しにやる

```shell
ansible all -m shell -a "uname -n"
```

成功したら、セットアップ

```shell
ansible all -m setup
```

# Tips

* ansible.cfgの中でdiffをalwaysにしておくと、いちいちdry runの時に-Dのオプションをつける必要がなくてよい
* ansible.cfgの中でinventoriesをあらかじめ設定しておけば、ansibleを使ったオペレーションも本番とステージングで分ける必要がなくてよい。
Visual Studio Codeの日本語化手順

# はじめに
前回インストールしたVSCodeを日本語したいと思います。
[Visual Studio Codeのインストール手順](https://qiita.com/ta_morimoto/items/ad0d8018d5b70174c41e)

# 環境
- OS：macOS Catalina v10.15.1
- VSCode：v1.41.1

# 日本語化手順
画面左のアクティビティバー内にある四角アイコンを選択する。
![VSCode#ja#1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90440/9aa7983f-35f4-7561-6e70-80e39185c02b.png)

テキストボックスに「Japanese Language Pack for Visual Studio Code」を入力する。
![VSCode#ja#2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90440/0b32b0a5-3bf5-46d9-1d31-4128bae26a66.png)

Microsoftから提供されている言語パッケージを一覧から選択して「install」ボタンをクリックする。
![VSCode#ja#3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90440/4256fbf4-04d7-e7bc-b782-d0f9dab779ea.png)

インストール完了後、「command + Shift + p」でコマンドパレット表示する。
テキストボックスに「Configure Display Language」を入力する。
![VSCode#ja#4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90440/974297eb-7a9d-9c6d-0d12-4a41045ef758.png)

言語が選択可能になるので「ja」を選択する。
![VSCode#ja#5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90440/ebeb69b7-92ba-380b-61f9-ab42608ade17.png)

言語選択後、再起動するかを聞かれるので「Restart」ボタンをクリックする。
![VSCode#ja#6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90440/34798e9b-ffe4-f340-9fc1-d709f9ee5630.png)

再びVSCodeが立ち上がると日本語化されています。
![VSCode#ja#7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90440/743c50f8-da45-0e0e-8f67-edb0ae8a2317.png)
papaparseでPromiseを使う(TypeScriptも有)

# 基本の書き方

```js
Papa.parse(file, {
  complete: function(results) {
    console.log("Finished:", results.data);
  }
});
```

## Promise使って書く

```js
function readCsv(file) {
  return new Promise((resolve, reject) => {
    Papa.parse(file, {
      complete: (results) => {
        resolve(results.data);
      }
    });
  });
}

readCsv("./hoge.csv").then(res => {
  console.log(res);
});
```

## TypeScriptで書く

```ts
import { parse } from "papaparse";

function readCsv(file: string) {
  return new Promise<string>((resolve, reject) => {
    parse(file, {
      complete: (results: any) => {
        resolve(results.data);
      }
    });
  });
}

readCsv("./hoge.csv").then(res => {
  console.log(res);
});
```

## 参考

- [Papa Parse](https://www.papaparse.com/)
- [How to use Promises with PapaParse?](https://stackoverflow.com/questions/31375531/how-to-use-promises-with-papaparse)
（メモ）Java便利メソッド


・isMatchメソッド

```java
public class Sample{

public static void main(String[] args){
	String str1 = "HelloWorld";
	String str2 = "e";

	if(isMatch(str1,str2) == true) {
		System.out.println("true");
	}
	else {
		System.out.println("false");
	}
}//出力結果:『true』


//文字列部分判定メソッド
//str1の中にstr2が含まれていればtrue
public static boolean isMatch(String str1, String str2) {
    if(str1.matches(".*" + str2 + ".*")) {
        return true;
    }
    else {
        return false;
    }
}
}

```

・substringメソッド

```java

substring(int biginIndex)
//引数目の位置から文字列を取り出す
```