OmniAICreator/Qiita-1.07M huggingface dataset:
Micro Frontendsメモ

## 解説記事
### 解説１
[martinfowler.comの解説記事](https://martinfowler.com/articles/micro-frontends.html)
[同じ著者Cam Jackson氏の別記事](https://microfrontends.com/)

### 解説その２
[Micro Frontends in Actionという本の作者ページ](https://micro-frontends.org/)
和訳
https://micro-frontends-japanese.org/

## 実現フレームワーク
https://bit.dev/

## 理解棚卸し
* WebComponents
* Event伝搬はPub/Subパターン
SafariBooksOnline で読める本リンク

* [リーダブルコード]
(https://learning.oreilly.com/library/view/the-art-of/9781449318482/)

* [人月の神話]
(https://learning.oreilly.com/library/view/mythical-man-month-the/0201835959/)

* [リファクタリング]
(https://learning.oreilly.com/library/view/refactoring-improving-the/9780134757681/)

* [エンタープライズ アプリケーションアーキテクチャパターン]
(https://learning.oreilly.com/library/view/patterns-of-enterprise/0321127420/)

* [アナリシスパターン―再利用可能なオブジェクトモデル]
(https://learning.oreilly.com/library/view/patterns-of-enterprise/0321127420/)

* [クリーンアーキテクチャ]
(https://learning.oreilly.com/library/view/clean-architecture-a/9780134494272/)

* [ZENデザイン3版]
(https://learning.oreilly.com/library/view/presentation-zen-simple/9780135897751/)

* [マイクロサービスパターン]
(https://learning.oreilly.com/library/view/microservices-patterns/9781617294549/)

気が向いたら更新します。
kube-proxyをipvsモードに変更する方法。

CentOS8でkubernetews v1.19を構築中に、kube-proxyのモードをデフォルトのiptablesから、ipvsに変更する方法に苦戦したため。 

### 1. configmapを変更する
```
$ kubectl edit configmap kube-proxy -n kube-system
```

### 2. modeをipvsに書き換える
```
mode: ipvs
```
【Nuxt.js + Firebase】FirebaseStorageへの画像アップロードでハマったところ


Firebaseを使って画像を使った何かを作ろうとして、Storageへ画像をアップロードする機能を実装するのにハマった点をつらつらと書きます。


##前提条件
すでにFirebaseで何かプロジェクトを作ってること。


##エラー
公式サイトや、こちら記事を参考に、Firebaseに画像のアップロードを試みましたが、

- [Firebase公式ドキュメント「ウェブでストレージ参照を作成する」](https://firebase.google.com/docs/storage/web/create-reference?hl=ja)
- [nuxt.js × firebase で画像保存処理実装してみた]
(https://qiita.com/teratadokoro810/items/7c7ba55cc7fa7ad62e98)
- [【Nuxt.js】Firestore Storageに画像アップロード・削除する方法](https://mintaku-blog.net/nuxt-storage/)


<BR>
こんなエラーが出て立ち往生

```
TypeError: firebase_app__WEBPACK_IMPORTED_MODULE_3___default.a.storage is not a function
```

<BR>
##原因
結論からいいますと、とても恥ずかしいのですが、Firebaseでストレージの設定をしてないだけでした。
<BR>
##設定方法

ストレージの設定方法は公式を見ながらやりました。
- [Firebase公式ドキュメント「ウェブで使ってみる」](https://firebase.google.com/docs/storage/web/start?hl=ja)
<BR>
##設定でハマった点

公式を見ながらやりましたが、色々とハマりました。

###セキュリティ設定
セキュリティは何もしなければ「デフォルト」設定なのですが、それでは通らないので、「公開」で設定します。
以下の公式にあるコードを Firebaseコンソールの「Strage < Rules」にコピペしてください。
https://firebase.google.com/docs/storage/security/start?authuser=0#public


###config設定

```
const config = {
  apiKey: "YOUR_APIKEY",
  authDomain: "YOUR_AUTHDOMAIN",
  databaseURL: "YOUR_DATABASEURL",
  projectId: "YOUR_PROJECTID",
  storageBucket: "YOUR_STORAGEBUCKET",
  messagingSenderId: "YOUR_MESSENGINGSENDERID",
  appId: "YOUR_APPID",
  measurementId: "YOUR_MEASUREMENTID"
  };
```

このstorageBucketで、ややハマりました。

storageBucketは、
Firebaseのコンソールの Storage >　Files　の　gsから始まるURLです。
（以下画像）
![スクリーンショット 2020-09-06 14.38.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/291592/5e3c675e-149a-92d7-16e7-dd2558e45ad0.png)

で、私がハマったのが、
storageBucket: "abcdef1234.appspot.com"
としたため。

正解は
storageBucket: "<B><font color="RED">gs://</font>abcdef1234.appspot.com</B>"


gs:// が入ります。

 


### import

そして、importを追加すること

```
import 'firebase/storage';
```
<br>
import 'firebase';　だけではダメのようです。

こちらの記事に助けられました。
[TypeError: _firebase2.default.storage is not a function](https://qiita.com/eyexx/items/cde6321ef9dba25ac33a)

ありがとうございました。


### コード
※アップロードするところを抜粋


```vue:index.vue

methods: {
    post(pic){
        const file = pic.target.files[0];
        const storageRef = firebase.storage().ref(file.name)
        //Firebaseストレージに保存
        storageRef.put(file);
        //保存先のURL
        picurl = "gs://"storageRef.location.bucket +"/"+storageRef.location.path_
        //FirestoreにURLを保存 　保存はされるが、もっといいやり方があると思う。
        const setAda = docRef.set({
            picurl: picurl
        });
    }
}
```
Laravelでフォームのデータを処理する（２／２）DBのデータをトップページに表示する

#はじめに
この記事は**[Laravelでフォームのデータを処理する（１／２）フォームで送信されたデータを取得しDBに挿入する](https://qiita.com/kakudaisuke/items/379d34c8be25168c5212)**の続きです。

今、掲示板のようなWebサービスを作成していて、Laravelで下記のような機能を実装したいです。
（１）フォームで送信されたデータを取得し、DBにデータとして挿入する。
（２）DBのデータをトップページに並べて表示する。

こんな初歩的な機能ですが、頭を抱えまくったのでメモしておきます。Laravelでこれを実現するには、色々な方法があるみたいですが、初心者の時速40kmの走行方法（教習所内）をメモしておきたいと思います。今回は（２）を実装していきます。

環境：Laravel 7、MAMP 5.7
MAMP以外をご利用の方はそこだけ貴方の環境に合わせて変換していただければと思います。

#１）DBにデータが入っていることを確認する
言わずもがなですが、DBが空だと何も表示できないので、ダミーでいいのでデータを入れます。

#2）トップページを用意し、プログラムを埋め込む
今回はBladeテンプレートを使用し、/resources/views直下に置いています。。（非常に簡略化しています）
例はライブの感想を投稿する掲示板なので、ライブの日付(live_date)や、ミュージシャン(musician)、会場(venue)、感想(text)などを表示したいです。

```html:index.blade.php
    <div>
     @foreach ($items as $item)
       <p>{{$item->live_date}}</p>
       <p>{{$item->musician}}</p>
       <p>{{$item->venue}}</p>
       <p>{{$item->text}}</p>
     @endforeach
    </div>
```
ポイント↑：

* いきなり`{{$item->live_date}}`みたいなプログラムを埋め込んでしまっていますが、最初は普通にHTMLだけで静的なサイトを準備して、ダミーでデータも書き込んでおいて、あとでその部分をプログラムで書き換えるのがいいと思います。
* @はディレクティブと呼ばれ、Blade内でここに構文（ifなど）的なプログラムを書くよーという合図です。
* foreachで`$items`という配列変数を受け取り、それを$itemとして一つずつ抜き出していきます。
* その$itemは`{{$item->live_date}}`で使用されます。
* が、ここに$itemsという変数を渡して上げないといけません。それが次のコントローラの役割です。

#３）コントローラ
２で作ったページに渡す変数を定義し、そのページ自体を返すという設定をします。[第１話](https://qiita.com/kakudaisuke/items/379d34c8be25168c5212)で作ったControllerで、/app/Http/Controllersフォルダに配置しています。

```php:PostController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use Illuminate\Support\Facades\DB; //DB接続のクラス

class PostController extends Controller
{
    //こちらを追加
    public function index(Request $request)
    {
        $items = DB::select('select * from reviews');
        return view('index', ['items' => $items]);
    }
```
ポイント↑：

* DB::selectでDBの全てのデータ`*`を呼び出し、index.blade.phpに渡す変数$itemsに代入します。
* Viewsフォルダ直下にあるindex(.blade.php)を呼び出し、第二パラメータで`items`という名前で、`$items`の値をindex(.blade.php)に渡してねと指示しています。この`'items'`がview（index.blade.php）内の`$items`と値が一致していないときちんとリンクしません。$のあるなしでややこしいことになっていますが...
* あとはこのコントローラとアクションメソッドを呼び出す設定をしてあげればよくて、それをRoutingで行います。

#４）ルーティング


```php:web.php
<?php

use Illuminate\Support\Facades\Route; //デフォルトで書いてあるクラス

Route::get('/', 'PostController@index'); //こちらを追加
```
ポイント↑：

* 第１パラメータは`'/'`、つまり、トップページ（＝Document Rootを設定しているアドレス）にアクセスがあったらという条件設定
* 第２パラメータ、PostControllerを呼び出し、そこにあるindexメソッドアクションを、、
* 呼び起こしなさい（＝Route::get）という命令文

#５）成功
この状態でドキュメントルートに設定しているページにアクセスすると、DBの情報が存在しているだけ全てトップページに表示されるはずです。

#うまく行かない場合のヒント

* 私は当初、ルーティングのRoute::getをRoute::postにするという、ブレーキとアクセスを踏み間違えるようなミスで、エラーを起こしていました。
* `$items`や`$item`などの複数形のsのあるなし、$の付け忘れ、その他スペルミスはないか。


#最後に
もし何かご指摘などありましたら、コメント欄などで頂戴できますと幸いです。
CentOS8にsamba4をソースコードからインストール

CentOS8でソースコードからsamba v4.13.0を導入する方法

### 1. まずはepelレポジトリを導入
```
$ sudo dnf -y install epel-release
```

### 2. 必要なライブラリを導入
```
$ sudo dnf install python36 python36-devel zlib-devel lmdb-devel gnutls-devel perl-Parse-Yapp jansson-devel libacl-devel openldap-devel pam-devel dbus-devel
$ sudo dnf install --enablerepo=PowerTools gpgme-devel libarchive-devel rpcgen
```

### 3. ビルド
```
$ sudo ./configure --prefix=/usr/local/samba-4.13.0/
$ sudo make -j2
$ sudo make -j2 install
```

### 4. systemdの設定
```
$ sudo cp -a bin/default/packaging/systemd/smb.service /lib/systemd/system/
$ sudo cp -a bin/default/packaging/systemd/nmb.service /lib/systemd/system/
$ sudo systemctl daemon-reload
```

### 5. sambaの起動および自動起動の有効化
```
$ sudo systemctl start smb
$ sudo systemctl start nmb
$ sudo systemctl enable smb
$ sudo systemctl enable nmb
```
How to Win a Data Science Competition: Learn from Top Kagglers サマリー Week 1《重要なところだけ》: データ処理

コースリンク：　https://www.coursera.org/learn/competitive-data-science/
提供：　[National Research University, Higher School of Economics](https://www.hse.ru/en/)

# はじめに
Kaggle初心者（[@ntszw](https://twitter.com/ntszw)）です。Kaggle Expertを目指して勉強しています。この講座を[Kaggle初心者ガイド](https://kaggler-ja-wiki.herokuapp.com/kaggle%E5%88%9D%E5%BF%83%E8%80%85%E3%82%AC%E3%82%A4%E3%83%89)で見つけ、面白そうだったので受けてみました。

読み返す価値のありそうな内容を集約しました。

# 主なアルゴリズムの種類（復習）
* Linear Models 線形モデル
* Decision Trees 決定木
* K Nearest Neighbors (kNN) k近傍法
* Neural Networks ニューラルネットワーク

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334026/b4d526fb-b546-f390-d759-7adcb87a2652.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/334026/0e2f69e7-e1eb-ac57-a47f-85ed44e2d800.png)

**ポイント： それぞれのアルゴリズム固有の性質を理解する。図を見ると直感的に理解できる。**

# 特微量全処理・生成 

* データが数字だからNumerical Featureだとは限らない。
* Ordinal FeatureはCategorical Featureの中でも意味のある順序で並んでいる場合。

例えば、１等２等の差と２等３等の差は一定でないため、等級はCategorical Feature。また、順序があるためOrdinal Feature。

### Numerical
Decision Trees系以外のモデルでは重要。ほとんどの場合、全ての特微量を同等に扱いたいので用いる。

* MinMax Scaling `(x - min) / (max - min)`: (0,1)内に変換、データ分布は保たれる
* Standard Scaling `(x - mean) / stddev`: 平均0, 標準偏差1に変換
* Rank: データの中で何番目に小さいか。外れ値の修正に役立つ。Pythonでは[scipy.stats.rankdata](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.rankdata.html)
* `np.log(1+x)`、`np.sqrt(1+x)`: 外れ値の修正に役立つ変換

別々の全処理を行ったデータを混ぜることも可能。

### Categorical・Ordinal

Decision Trees系の場合：

* label encoding: 一番シンプル。ラベル（文字列）から数字へのマッピング。
* frequency encoding: ラベルの頻度に基づいたマッピング。

その他の場合：

* One-hot label encoding: sparse arrayへのマッピング
* 複数の特微量を合わせたone-hot encoding

### 時間

* 周期性に基づいたデータ（曜日、月など）
* ある出来事から何時間経ったか
* ２つの日付・時間同士の差

### 座標

* 重要な地点からの距離
* 地域に関する統計情報

### データが欠けている場合

平均・中央値・定義域外の値で埋めるか、元の値を予測する。ただ、特微量生成を行う場合に悪影響が出ないように細心の注意を払う。（生成の後にやったほうが良い）

### テキストデータ

1. 前処理: lowercase, lemmatization/stemming, stopwords
2. bag of words (ngrams, TFIDF)またはword embedding

### イメージデータ
CNNをfine tuneする。Image Augmentationを行う。
アロー関数とasync/awaitを使った非同期処理の書き方を整理しよう

# はじめに
昨今のモダンブラウザ、スマフォではアロー関数や、Acync/Awaitを利用したPromiseの利用は、Babelでトランスパイルする必要がない。
これらのJavaScriptを利用の仕方を個別で調べると古い書き方が混在して、今風に書くにはどう書いたら動くのか混乱した。

自分が知りたかった

1. アロー関数で関数を定義して、その中でasync/awaitを利用した場合の書き方
1. async/awaitが入れ子で呼ばれた場合どういう動きをするのか
1. 非同期実行するもの複数実行してその結果を待つにはどうすればいいか

を調査しサンプルコードを書いてまとめた。

各関数のブラウザの対応

* [アロー関数](https://caniuse.com/#feat=arrow-functions)
* [async](https://caniuse.com/#search=async)
* [await](https://caniuse.com/#search=await)

下記をリンクから動作を確認できる。値を変えながら動作を確認すると理解しやすい
[DEMO](https://playcode.io/656439/)


# アロー関数を使ったasync/awaitの書き方

## 数100msスリープするメソッドの例

fetchメソッドなどで非同期にデータを取得するような例を再現するためダミーの関数として利用する

```js
// sleep するメソッド　fetchなどの時間がかり結果をpromiseで返す関数
const sleep = (m) => new Promise( _ => setTimeout(_, m))

// promiseをasync awaitを使ってpromise終了後に文字を出力する
// ランダムに数100ms待つ
const asyncFunc = async (mes) => {
    const waitTime = Math.floor((Math.random() * 100) + 1)
    await sleep(waitTime)
    console.log(mes)
    return `result_${mes}`
}
```

asyncをメソッドの頭につけて囲い、`const asyncFunc = async (mes) => {` 

非同期実行するメソッドの完了を待つ際にawaitをつける　`await sleep(waitTime) `

このように定義すると、asyncFunc自体実行した結果`result_${mes}`を得るためにはawaitする必要がある。ここが非常にややこしい。
メソッドの最後にreturnしているだけなのに、その時の返り値は文字列ではなくPromiseオブジェクトなのだ。この仕様はややこしくしている原因だ。

returnの結果を得るためには、呼び出し元で`await asyncFunc("message")`と`await`を先頭につけてあげる必要がある。


# async/awaitが入れ子で呼ばれた場合どういう動きをするのか

下記の例のようにawaitを実行するためにはasyncを使ったparentFuncを作成し、その中で実行する必要がある。
この関数内で基本、基本2、基本3の動作を確認し、どういう値が返ってくるか確認してもらいたい。

逐次実行されるように、この関数の一番最後の行実行時にそれ以前の命令した結果がすべて完了させるには基本3のように書けば良い。

端的に言えばasyncで定義している関数の手前にawaitを書いてあげるだけである。

```js
const parentFunc = async () => {
  // asyncを使っているメソッドはpromiseが返ってくるので、asyncを使って呼び出さないとawitが使えず非同期処理になる
  const async = asyncFunc
  const sync = asyncFunc
  
  // 基本
  console.log(async("async")) // Promiseオブジェクトが返ってくるだけ
  console.log("---1---") // 1
  console.log(await sync("sync")) // 2

  // 基本2
  console.log(await sync("sync2")) // 1
  console.log(async("async2")) // Promiseオブジェクトが返ってくるだけ
  console.log("---2---") // 2

  // 基本3
  const resultSync = await sync("sync3") // 1
  console.log(await sync(resultSync)) // 2 resultSyncの結果を待ってから実行する
  console.log("---3---") // 3
}

parentFunc() //ここで上で定義したparentFuncを実行
```

## 無名関数でasyncで定義した関数を実行する

上記のようにparentFuncを定義せずに、下記の例のように無名関数で実行することもできる。
個人的にはわかりにくいカッコをたくさん書く必要があり書き方が直感的ではない。おまじないと考えてもいいかもしれない。こういうのはあまり好きじゃないなぁ

```js
(async () => {
  console.log(await asyncFunc("無名関数をasyncで定義して非同期実行するpromiseのメソッドを動かす"))
})()
```

-----

# 非同期実行するもの複数実行してその結果を待つにはどうすればいいか
残念なことにせっかくasync/awaitで隠蔽化したPromiseをコードに書く必要がある。
そのキーワードは`Promise.all`。
感覚的にはスレッドの完了をすべて待つ処理に似ている。

```js
const parentFunc = async () => {
  // asyncを使っているメソッドはpromiseが返ってくるので、asyncを使って呼び出さないとawitが使えず非同期処理になる
  const async = asyncFunc
  const sync = asyncFunc
  
  // map関数内で非同期処理が入る場合
  // idの配列を受け取って各idをパラメタにWeb apiにアクセスするような場合
  const arr = [1, 2, 3, 4, 5]

  // mapの中の各メソッドが実行完了する順番が変わっても結果の配列の順番はarrの順
  const result_arr1 = await Promise.all(arr.map((id)=>{
    return sync(id);
  }))
  console.log(result_arr1)
}

parentFunc()
```
メールサーバのテスト

下記にメールを送るとDKIM,Sender ID,SPF等のチェックをしてレポートとして返信してくれる。

- 返信先を“mail_from”とする場合
    - `check-auth@verifier.port25.com`
- 返信先を“from”ヘッダーとする場合
    - `check-auth2@verifier.port25.com`
- 返信先を任意(`xxx@xxx.xxx`)とする場合
    - `check-auth-jsmith=xxx@xxx.xxx@verifier.port25.com`
   
https://www.sparkpost.com/email-tools/authentication-checker/
なぜか上がらないnpmのバージョン

</h3>開発環境</h3>
npm : 3.5.2
Ubuntu :18.0.03

<h2>問題</h2>
npm insatll を実行しようとした際にエラーが表示しました。

```console
npm ERR! Linux 5.4.0-45-generic
npm ERR! argv "/usr/bin/node" "/usr/bin/npm" "update"
npm ERR! node v8.10.0
npm ERR! npm  v3.5.2
npm ERR! code EMISSINGARG

npm ERR! typeerror Error: Missing required argument #1
npm ERR! typeerror     at andLogAndFinish (/usr/share/npm/lib/fetch-package-metadata.js:31:3)
npm ERR! typeerror     at fetchPackageMetadata (/usr/share/npm/lib/fetch-package-metadata.js:51:22)
npm ERR! typeerror     at resolveWithNewModule (/usr/share/npm/lib/install/deps.js:456:12)
npm ERR! typeerror     at /usr/share/npm/lib/install/deps.js:457:7
npm ERR! typeerror     at /usr/share/npm/node_modules/iferr/index.js:13:50
npm ERR! typeerror     at /usr/share/npm/lib/fetch-package-metadata.js:37:12
npm ERR! typeerror     at addRequestedAndFinish (/usr/share/npm/lib/fetch-package-metadata.js:82:5)
npm ERR! typeerror     at returnAndAddMetadata (/usr/share/npm/lib/fetch-package-metadata.js:117:7)
npm ERR! typeerror     at pickVersionFromRegistryDocument (/usr/share/npm/lib/fetch-package-metadata.js:134:20)
npm ERR! typeerror     at /usr/share/npm/node_modules/iferr/index.js:13:50
npm ERR! typeerror This is an error with npm itself. Please report this error at:
npm ERR! typeerror     <http://github.com/npm/npm/issues>
```

意味としてはnpmのパッケージのバージョンが要求されているものと合ってないよ～」ということでネット上にはバージョンを最新に上げれば直るということで色々試したのですが。。。。


```console
npm --version 
3.5.2

sudo npm install -g npm@latest
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
/usr/local/bin/npx -> /usr/local/lib/node_modules/npm/bin/npx-cli.js
+ npm@6.14.8
updated 1 package in 5.5s

sudo npm install -g npm@nex
/usr/local/bin/npm -> /usr/local/lib/node_modules/npm/bin/npm-cli.js
/usr/local/bin/npx -> /usr/local/lib/node_modules/npm/bin/npx-cli.js
+ npm@6.14.8
updated 1 package in 5.5s

npm --version 
3.5.2

```

上記のコマンドで一見上がっているように見えるのですが、実際にもう一度npmのバージョンを見てみると上がってない！！
なんじゃこれ状態ですね～

<h2>解決方法</h2>
調べてみるとnpmのリポジトリがサポートしなくなっているみたいなので、手動で落としてきましょう～

```console
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -       
sudo apt -y install nodejs make gcc g++
```

これでいけるかな～と思ったのですが、、

```console
npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /home/administrator/.npm/_cacache/content-v2/sha512/5b/ec
npm ERR! errno -13
npm ERR! 
npm ERR! Your cache folder contains root-owned files, due to a bug in
npm ERR! previous versions of npm which has since been addressed.
npm ERR! 
npm ERR! To permanently fix this problem, please run:
npm ERR!   sudo chown -R 1000:1000 "/home/administrator/.npm"
npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /home/administrator/.npm/_cacache/content-v2/sha512/bd/c5........
```

前のバージョンのキャッシュが残っていて、「なんや！！　このファイルは？」となっているみたいなので、キャッシュを消しときましょう

```console
sudo npm cache clean --force 
```

あとは普通にnpm installをたたけばいけますよ～

```console
sudo npm install
```

<h2>まとめ</h2>
今回の問題は発生するのは主にUbuntu系の環境で作業されている方だと思います。
それ以外の方はおそらくlatestやnextを実行したときに上がっていると思うので、単純にUbuntu環境ではnpmリポジトリのサポートが3.5.2できれてしまっているのが原因ですかね～

<h2>参考資料</h2>
https://github.com/npm/cli/issues/681
Flutter で Dynamic Links を解釈する

# Dynamic Links
Dynamic Links 便利ですよね。
簡単に説明すると 1 つの URL で最終的にいきつくリンクを条件によって決めることができるリンクのことです。

主にアプリをインストールされていなければストアに飛ばしたり、インストールされていればアプリを起動といったような分岐に使われます。

以前 Android で実装したことがあったので雰囲気はわかっていたのですが Flutter で動くか心配だったので検証した記録です。

# 結論
Flutter でも動きます。
ネイティブ実装も不要です。
以下のパッケージを使うとすべて Flutter で完結します。

https://pub.dev/packages/firebase_dynamic_links

基本的に以下のハンドラーを main.dart なりに書いておくと未インストールの場合でもどの画面にいたとしても Dynamic Links を解釈できます。

```dart

/// 未インストールの場合
/// dynamicLinksHandlerNonInstall を main() 内で実行
void dynamicLinksHandlerNonInstall() async {
  final data = await FirebaseDynamicLinks.instance.getInitialLink();
  final Uri deepLink = data?.link;
  /// do something...
}

/// インストール済みの場合
/// main() 内に定義しておく
FirebaseDynamicLinks.instance.onLink(
      onSuccess: (PendingDynamicLinkData dynamicLink) async {
    final deepLink = dynamicLink?.link;

    if (deepLink != null) {
      /// do something...
    }
  }, onError: (OnLinkErrorException e) async {
    print(e.message);
  });
```

以下に検証の記録を記します。（特に未インストール時の検証が面倒だった…）

# インストール済みのとき
これは上に記した `FirebaseDynamicLinks.onLink` を定義しただけ。
`/// do something` のところに画面遷移なり書いてあげれば良いです。

# 未インストールのとき
未インストール時にストアに飛ばすこともすごいのですが、
ストア経由でインストールし、アプリを立ち上げた場合でもディープリンクなどの情報が引き継ぐことができます。

引き継いだディープリンクを取り出す方法が上に記した `dynamicLinksHandlerNonInstall` です。

ただ、公開していないアプリや開発段階のアプリで未インストール時の動作を確かめるのに少し手間です。

## 未公開のアプリで Dyanimic Links をデバッグする方法
手順は以下です。

1. Dynamic Links を動的に生成（ちょっと工夫が必要）
2. リンクをクリックしストアを開く
3. `flutter run` でスマホにアプリをインストールする

### Dynamic Links を動的に生成

Dynamic links を動的に生成する方法があります。
https://firebase.google.com/docs/dynamic-links/rest?hl=ja

以下のパラメータを POST してあげるとリンクを得ることができます。

ポイントは `公開されているアプリのストア上のページ` です。
別のアプリのものでも構いません。

```json
{
  dynamicLinkInfo: {
    domainUriPrefix: 'Firebase 上で定義した Dynamic Link のドメイン',
    link: 'ディープリンク',
    androidInfo: {
      androidPackageName: '自分のアプリのパッケージ名',
      androidFallbackLink: '公開されているアプリのストア上のページ'
    },
    iosInfo: {
      iosBundleId: '自分のアプリのバンドルID',
      iosFallbackLink: '公開されているアプリのストア上のページ'
    }
  }
}
```

生成されたリンクに `?d=1` をつけてブラウザ上でアクセスし、以下のような画面が現れたら成功です。
※ iOS は設定していない例です

![スクリーンショット 2020-09-06 14.11.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119099/c36a5ff7-bf11-4600-215d-280897e1d5f5.png)

これをスマホ上でクリックすると、指定したアプリのページが開きます。
その状態で自分のアプリをビルド ＆ インストールしてあげると擬似的にストアからインストールした状態を再現することができ、
 `dynamicLinksHandlerNonInstall` 内でディープリンクなどの情報を取得できました。
cloud firestoreのデータをコレクションとドキュメントを同期処理で取ってくる

使い道は置いておいて、今回非同期処理の部分で詰まったので知識置き場としておいておきます。
resolveの置き場所に要注意です。
改良点等ありましたらコメントよりお願いしますm(_ _)m
# 初期化
npmからfirebase-adminをインストールしておく。

```javascript:main.js
const admin = require('firebase-admin');
let serviceAccount = require("APIキー");
admin.initializeApp({
    credential: admin.credential.cert(serviceAccount)
});
```

#main関数
非同期関数に注意

```javascript:main.js
var main = function(){
    const db = admin.firestore();
    const collenction = 'users';
    const doc = "alovelace";
    getData(db, collenction,doc)
    .then( function(result){
        console.log(result);
    },
    function (value) {
        console.log("error:", value);
    });
}

main();
```

# データの取得
今回はコレクションとドキュメントを指定してその中のデータを取ってくることにする。

```javascript
var getData = function(db, collection, doc){
    return new Promise(function(resolve,reject){
        let recieved_doc = db.collection(collection).doc(doc);
        /*recieved_doc.getは非同期なのでこの中でresolveを書く必要があります*/
        recieved_doc.get()
            .then( snapshot => {
                resolve(snapshot.data());
                reject("error");
            })
            .catch((err) => {
                console.log('Error getting documents', err);
            });
    })
}
```

以上！！
scikit-learnにない評価指標 (specificity, NPV) を計算するメソッドを実装してみた

# はじめに
とある論文に記載されている指標について、scikit-learn で計算しようとしたところ、sensitivity, recallについては単独で計算するメソッドが用意されていたが、specicity、NPVの2つについては、classification_reportは出力されるものの、単独で計算するメソッドが用意されていなかったので実装してみたメモ。

# 計算方法
ぶっちゃけ、ここ見てください、ハイ。
https://en.wikipedia.org/wiki/Sensitivity_and_specificity

用語の関係を整理するとこんな感じ。暗記の必要はなし。

- PPV = precision
- TPR = sensitivity = recall
- TNR = specificity
- NPV = とくに他の呼び方なし

# ソース
confusion matrixを使って計算します。

```python
from sklearn import metrics

def calc_metrics_derived_from_confusion_matrix(metrics_name, y_true, y_predict):
    tn, fp, fn, tp = metrics.confusion_matrix(y_true, y_predict).ravel()
    #  PPV, precision
    #  TP / TP + FP
    if metrics_name in ["PPV", "precision"]:
        return tp / (tp + fp)

    #  NPV
    #  TN / TN + FN
    if metrics_name in ["NPV"]:
        return tn / (tn + fn)

    # sensitivity, recall, TPR
    #  TP / TP + FN
    if metrics_name in ["sensitivity", "recall", "TPR"]:
        return tp / (tp + fn)

    # specificity
    #  TN / TN + FP
    if metrics_name in ["specificity"]:
        return tn / (tn + fp)
```

#使い方
こんな感じ。

```python
calc_metrics_derived_from_confusion_matrix("sensitivity",[0,0,1], [1,0,1])
calc_metrics_derived_from_confusion_matrix("PPV",[0,0,1], [1,0,1])
calc_metrics_derived_from_confusion_matrix("specificity",[0,0,1], [1,0,1])
calc_metrics_derived_from_confusion_matrix("NPV",[0,0,1], [1,0,1])
```
Tyeの構成ファイルの tye.yaml のスキーマ定義を見てみる

マイクロサービス開発ツールであるTyeはYamlファイルで構成を定義します。ファイル名は `tye.yaml` です。  
今回はこの `tye.yaml` のスキーマについて学びます。

`tye.yaml` のスキーマはGitHubで管理されており、誰でも閲覧することができます。   
https://github.com/dotnet/tye/blob/master/docs/reference/schema.md
 
# Visual Studio Codeで `tye.yaml` を書く準備
こちらのドキュメントに沿って環境を整えることで、Visual Studio Codeで `tye.yaml` を書く際にインテリセンスが表示されるようになります。  
[https://github.com/dotnet/tye/blob/master/src/schema/README.md]

1. Visual Studio Codeに[Yaml拡張機能](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml)をインストールする
2. Visual Studio Codeの設定画面を起動する (`Ctrl+,`)
3. 「Yaml: Schemas」の設定を探し、settings.jsonを編集する
4. `"yaml.schemas"`にTyeのスキーマファイルを指定する

```json
{
  "yaml.schemas": {
    "https://raw.githubusercontent.com/dotnet/tye/master/src/schema/tye-schema.json": [
      "tye.yaml"
    ]
  }
}
```

# スキーマの定義
過去記事のサンプルアプリケーションで使用している `tye.yaml` を例に説明します。  
https://github.com/tsubakimoto/project-tye-sample/blob/master/tye.yaml

```yaml
name: microservice
registry: tsubakimoto
services:
- name: backend
  project: backend\backend.csproj
- name: frontend
  project: frontend\frontend.csproj
- name: redis
  image: redis
  bindings:
  - port: 6379
    connectionString: "${host}:${port}"
- name: redis-cli
  image: redis
  args: "redis-cli -h redis MONITOR"
```

## `name` プロパティ
Tyeでのアプリケーションの名前となります。このプロパティが使われることはほとんどないですが、Kubernetesにデプロイした場合はラベル名に使用されます。  
このプロパティが指定されない場合は `tye.yaml` のあるディレクトリ名（小文字）が使用されます。

## `registry` プロパティ
コンテナーレジストリの名前を指定します。DockerHubもしくはAzure Container Registryの名前を指定することができます。  
ここで指定したコンテナーレジストリに、イメージやタグがプッシュされます。

## `namespace` プロパティ
Kubernetesへのデプロイ時に、Kubernetesの名前空間(namespace)として使用されます。  
以前のサンプルアプリケーションでは `namespace` プロパティを使用していないので、後日検証してみようと思います。

## `services` プロパティ
アプリケーションを構成するサービスを指定します。少なくとも1つは必要です。  
`services` プロパティでは以下のプロパティを定義することができます。

### `name` プロパティ
サービス名となり、DNS名として利用可能な文字種である必要があります。

- 最大63文字
- 英数字または「-」のみ
- 英数字で始まる
- 英数字で終わる

### `project` プロパティ
`.csproj` ファイル、もしくは `.fsproj` ファイルのパスを指定します。ファイルパスは `tye.yaml` からの相対パスです。  
このプロパティに指定されたプロジェクトは、ローカルでのビルドや実行の対象となり、パッケージ化の対象となります。

### `image` プロパティ
Dockerイメージを使用する場合にイメージ名とタグを指定します。  
上記のサンプルの `image: redis` は、`redis` というイメージの `latest` タグとなります。

### `bindings` プロパティ
ドキュメントには「サービスによって公開されるバインディングのリスト」とあります。  
該当のサービスが公開（実行）されるときのプロトコルに関する設定です。

- `port` プロパティ
  - ポートバインディングに使用するポート番号。
- `connectionString` 
  - サービスにバインドされる接続文字列。参照元のサービス側でどのように解釈されるかは[サービスディスカバリ](https://github.com/dotnet/tye/blob/master/docs/reference/service_discovery.md)という仕組みがあるみたいです。

### `args` プロパティ
サービスの起動時に使用するコマンドライン引数となります。

---

他にも https://github.com/dotnet/tye/blob/master/docs/reference/schema.md には、スキーマ定義が記述されているため気になるものは後日検証してみようと思います。
Kubernetes 入門


# Kubernetesとは
<img width="200" alt="k8s" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386017/5c9cdc20-a0e9-4c29-5fdd-d768dc99fe1b.png">

Google主導で開発された、OSS(Open Source Software)のコンテナオーケストレーションツールです。読み方は「クーベネティス/クーベルネティス/クバネティス/K8s（ケーハチエス）/kube（クベ）」などと呼ばれます。ギリシャ語で航海長またはパイロットという意味があるらしいです。
2018年にGoogleからクラウドネイティブを推進する組織、CNCF([Cloud Native Computing Foundation](https://www.cncf.io/))に寄贈されました。

コンテナオーケストレーションツールとは、コンテナを運用する上で必要なアプリのデプロイやDockerホストの管理、スケーリングなどの仕組みを備えたツールで、操作のためのAPIやCLI（kubectl）を提供しています。

# 使うための前提条件
Kubernetesは前述したとおり、コンテナを運用するためのツールです。
このため、アプリはコンテナ化されていることが前提になります。コンテナ化とは、アプリがDockerイメージ化されている状態になります。

# 使うと何が良いのか
自分なりに想定している`Kubernetesを導入することで得られるメリット`について書きたいと思います。

## コンテナの更新（リリース）が楽になる
現状、クラウドはAWSを使用しているのですが、今までKubarnetesを使用せずにEC2に直接Dockerコンテナを起動してました。そうすると、EC2にSSHしてdocker-compose（またはDockerfile)を使ってコンテナを起動して・・・をコンテナ数×サーバ数の回数やらなくてはいけません。Kubernetesを使用すれば、ローカルからkubectlコマンドを叩くだけでアプリのデプロイが可能になります。

## コンテナの状態管理が楽になる
ローカルでKubectlコマンドを叩くだけで全コンテナの状態が一覧でパッとわかるため、コンテナの状態管理が楽になります。

## オートヒーリングでコンテナ数が維持される
Kubernetesにはオートヒーリング機能が備えられていて、何らかの原因でコンテナがダウンした場合にも自動で代わりのコンテナを起動し、設定した数のコンテナを維持してくれます。（ReplicaSet機能)

## ロールバックで前のバージョンに切り替え可能
コンテナのイメージを更新してKubernetesでデプロイした場合、問題があればすぐに古いバージョンにロールバックすることが可能です。（Deployment機能）

# Kubernetesのアーキテクチャ概要
Kubernetesを導入する場合、どんなアーキテクチャになるのか？をざっくり解説します。

![Untitled Diagram (33).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386017/e9d5c64c-a5af-8cd1-0cdc-103b606b2dcc.png)
なぜクラウドネイティブが求められるのか

# なぜ今、クラウドネイティブが求められるのか
もはや、ビジネスとITは切っても切れない関係になりつつあります。DXが叫ばれる昨今では、ビジネスをローンチするスピードと共にIT活用のスピードも高速化しています。
アジャイル開発に代表されるように、アジリティの高い開発手法が求められており、それを実現するためにはシステムのアーキテクチャや開発プロセスを抜本的に見直す必要があったのです。
これらの要求にハマったのがポータビリティの高いコンテナ技術とリソース調達に柔軟性のあるクラウド技術を活用した、クラウドネイティブです。

# クラウドネイティブって何？
クラウドネイティブを推進する[Cloud Native Computing Foundation](https://www.cncf.io/)(通称CNCF)という非営利の団体があり、クラウドネイティブについて、次のように定義しています。
※[CNCF Cloud Native Definition v1.0](https://github.com/cncf/toc/blob/master/DEFINITION.md)から引用


>クラウドネイティブ技術は、パブリッククラウド、プライベートクラウド、ハイブリッドクラウドなどの近代的でダイナミックな環境において、スケーラブルなアプリケーションを構築および実行するための能力を組織にもたらします。 このアプローチの代表例に、コンテナ、サービスメッシュ、マイクロサービス、イミュータブルインフラストラクチャ、および宣言型APIがあります。

>これらの手法により、回復性、管理力、および可観測性のある疎結合システムが実現します。 これらを堅牢な自動化と組み合わせることで、エンジニアはインパクトのある変更を最小限の労力で頻繁かつ予測どおりに行うことができます。

>Cloud Native Computing Foundationは、オープンソースでベンダー中立プロジェクトのエコシステムを育成・維持して、このパラダイムの採用を促進したいと考えてます。 私たちは最先端のパターンを民主化し、これらのイノベーションを誰もが利用できるようにします。

重要なキーワードは、`クラウド(パブリック/プライベート/ハイブリッド)の技術を活用`して`回復性`、`管理力`、および`可観測性`のある`疎結合システム`を実現すること、でしょうか。


# とりあえず、クラウドを使えば良い？
クラウドネイティブの目的は、「クラウド技術を使うこと」ではなく、「クラウド技術を活用してビジネス価値をユーザーに提供すること」です。
まずは目指すべきビジネス価値を測り、その上で技術を選定するべきであり、新しいプロダクトに飛びつくだけだったり、趣味で選択しないことが重要です。
ビジネス価値の測り方の１つに、「デリバリパフォーマンス」という指標があります。

* リードタイムの削減
* デプロイ頻度の増加
* MTTR(平均修復時間)の短縮
* 変更失敗率の低減

これらの指標について目標を定めておき、それに見合うアーキテクチャやプロダクトを採用することが重要です。

# これはクラウドネイティブではない
いずれも、「クラウド技術を活用してビジネス価値をユーザーに提供すること」ができていないパターンです。

* ただクラウドを使っているだけ
* クラウド特性を設計や運用に反映してない
* 役割と運用プロセスが変わらない
* 手作業の運用プロセスへの依存


# クラウドネイティブを実現するための考え方

### サービスベースアーキテクチャ
マイクロサービスアーキテクチャもその１つ。
小さい独立したコンポーネントに分割することにより、可用性、アジリティ、スケーラビリティを向上させる。
開発者はビジネスロジックの開発に専念できる。

### API
軽量かつ特定の技術に依存しない接続方法。
シンプルでアジリティも担保できるしスケールしやすい。

### コンテナオーケストレーション
アプリのポータビリティを確保し、AWSでもGCPでもそのまま動く・使えるのが理想。

### アプリ設計時の方法論

The Twelve-Factor-App
By [Heroku](https://jp.heroku.com/)

次のようなSoftware as a Serviceを作り上げるための方法論。

* セットアップ自動化のために 宣言的な フォーマットを使い、プロジェクトに新しく加わった開発者が要する時間とコストを最小化する。
* 下層のOSへの 依存関係を明確化 し、実行環境間での 移植性を最大化 する。
* モダンな クラウドプラットフォーム 上への デプロイ に適しており、サーバー管理やシステム管理を不要なものにする。
* 開発環境と本番環境の 差異を最小限 にし、アジリティを最大化する 継続的デプロイ を可能にする。
* ツール、アーキテクチャ、開発プラクティスを大幅に変更することなく スケールアップ できる。

# 具体的にどうすれば良いの？
CNCFが[Cloud Native Landscape](https://github.com/cncf/landscape#trail-map)を定義しており、どのようなStepでクラウドネイティブを導入していくのが良いか示しています。
今回は詳細について触れませんが、まずはアプリケーションをマイクロサービス単位でコンテナ化して、CICDでビルド、テスト、デプロイまでを自動化して、Kubernetesなどのオーケストレーションで管理して・・という流れになっています。

また、役割別のおすすめプロダクトについては[こちら](https://landscape.cncf.io/)にまとまっています。
Ghostscript で PDF ファイル中の Font を Outline 化して別の PDF に保存する

# PDF 中の Text を outline 化する必要性

例えば PDF ファイルを inkscape で読み込んで再編集するとき、テキストの大きさやフォントが崩れてしまうことがあります。こうした場合、PDF のテキストをアウトライン outline 化して、全て図形にしてしまうという回避策があります。この変換により、テキストとフォント情報が失われるので、文字として編集することはできなくなりますが、正確な図形として編集することができるようになります。

# 環境

## Ghostscript
Windowsの人は、Windows Subsystem for Linux (WSL) にインストールするのが気軽です。


```shell
sudo apt update
sudo apt install ghostscript
```

# 実行

```shell
gs -dNOPAUSE -dBATCH -dNoOutputFonts -sDEVICE=pdfwrite -sOutputFile=out.pdf input.pdf
```
PST 修復ツール Outlook .pstの損傷からメールを回復するには

Outlookの.pstファイルの損傷を修復したいですか? すごい！あなたは正しい場所に着陸しました。今日は、PSTから電子メールを回復する最も簡単な方法を紹介します。PSTの修復ツールを探しているユーザーはたくさんいます。どうして？自動化ソリューションとして、手作業と時間を削減します。

この記事の最後で、破損または破損したOutlook .pstファイルからメール、連絡先、カレンダーデータにアクセスできるようになります。それでは始めましょう.

まず、お使いのコンピューターに <b>Advik <a href="https://www.adviksoft.com/ja/pst/recovery.html" target="_blank">PST 修復ツール</a></b> をダウンロードしてインストールします。このプログラムは、PSTファイルから電子メールを即座に回復するように設計されています。エラーに直面することなく、大きなPSTファイルを修復できます。また、PSTメールをMBOX、PDF、EML、MSG、DOC、HTMLなどのさまざまな適切な形式にエクスポートできます。

ダウンロード : https://www.adviksoft.com/dl/advik-outlook-pst-converter.exe

##PST 修復ツール を使用して.pstから電子メールを復元する

<b>ステップ1.</b> PCでAdvik PST修復ソフトウェアを実行します。
![pst repair tool 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526912/cd749a65-3147-4296-4c1f-31fa69918789.png)


<b>ステップ2.</b> 追加 PSTをクリックし、.pstファイルをソフトウェアに配置します。
![pst repair tool 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526912/e8bdb273-d3c6-701c-fe98-17f486265986.png)


<b>ステップ3.</b> リストから保存オプションとしてPSTを選択します。
![pst repair tool 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526912/d0f4225f-0f98-d3aa-5019-41e11bf271f9.png)


<b>ステップ4.</b> [変換]ボタンをクリックして、ファイルの修復を開始します。
![pst repair tool 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526912/5cdfc8de-efe6-35f5-991a-8ebaab15aa2c.png)


完成しました！これは、PSTを修復する方法です。

Outlookのインストールは必要ありません。ファイルを追加して変換するだけです。試してみて、情報を失うことなくOutlookデータファイルを修復してください。
【AWS】課金料金をなるべくなくす【初心者】

## はじめに（ターゲット層の方）
・初めてWebアプリケーションをAWSを使いデプロイした後、料金が発生してしまい困っている方
・ポートフォリオとして使っていたWebアプリを転職成功などの理由により使用しなくなった方

## CloudTrail、CloudWatch
・課金が発生したリージョンを選択。
・「CloudTrail」「CloudWatch」該当ページに行き、以前設定したファイルを削除するだけでいい。

## EC2
料金画面
### Amazon Elastic Compute Cloud running Linux/UNIX
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481640/1a34d0a1-0e69-756f-3d55-45576b645e5f.png)
実行しているインスタンスを停止するだけでOK。

### EBS
料金画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481640/bd40d143-14c5-b942-9599-2b76e855c0ea.png)
停止されたものも含めてインスタンスが４つ以上あり、容量オーバーによって料金が発生している。
４つ以上から料金が発生してしまう模様。３つ以下にインスタンスを減らすこと。
参考：https://gattsu09.hatenadiary.com/entry/2017/11/11/094102

### Elastic IP Addresses
料金画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481640/4c6821ff-d387-fe99-2430-db2da35529f4.png)
・Elastic IPによる料金が発生している。インスタンスに関連づけられていたElastic IPを開放すればOK。使用していないEIPを解放しないまま放置してしまうと料金が発生してしまうため注意
・自動的にEC2内でスナップショットを保存している時があるため、そちらを削除する。
→紐づけられているAMIがあるため削除できないと言われたら、EC2内の左選択バー内にあるAMIを選択し、該当のAMIを削除すればスナップショットを削除できるようになる。
参考：https://qiita.com/Yuji-Ishibashi/items/bb1c0042fd16a9350c5a

## RDS
料金画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481640/7958c7bc-4d4e-5b3f-90d4-018cbda1db77.png)
・起動しているRDSを削除すれば課金が止まる。停止しても７日間経てば自動的に起動してしまうため注意。
・削除する際、スナップショット（バックアップのようなもの）を作成すること。
参考①：https://dev.classmethod.jp/articles/aws-rds-startandstop/
参考②：https://sys-guard.com/post-7264/

## Route53
料金画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481640/63449843-794c-8662-8ec5-682bbbf2c847.png)
Route53の画面に行き、該当のホストゾーンを削除すればOK。

## S3
料金画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481640/7735798e-1f8b-7401-25cf-7e7b027c489c.png)
該当のリージョンにあるS3のバケットを削除すればOK。
「映像の作成方法　PP」

「映像の作成方法　PP」

題名

アジェンダ

内容

事前説明

操作説明
パターン１　動画で説明（声は出ないがテロップで説明する）
パターン２　動画と一緒にテロップを出して説明する。
パターン３　動画は無しで、スライドで説明する


素材も準備する（動画を見なくても、テキストで終えるように
校正（文章も提供する）。


テクニック
　マウスなどで場所を占めす
　動画は動画で始める、前提の説明は前のスライドで
　

まとめ

・準備物・
PowerPoint
画面の動画　PowerPoint


「マイクロソフトムービーメーカーでの撮影」
トリミングして説明を入れる
タイトルで説明を詳しく入れる
速度を遅くする
音も除去してくれる
PyTorchのTensorのmax, minの仕様が不便

# はじめに
PyTorchのTensorは基本的にNumPyのndarrayのように扱えますが、ところどころに異なる部分があります。

特にTensorの最大値、最小値を求める`max()`, `min()`はよく使うのにNumPyと挙動が異なっていて扱いづらいです。
この違いを緩和するためにNumPyと同じようなスタイルでTensorの最大値、最小値を求められる関数を書きました。

# PyTorchの`max()`とNumPyの`max()`の違い
Tensorまたはndarrayの全体の最大値を求めたい場合は両者の違いはありません。
つまり、以下の式は両方とも（型は違いますが）同じ値が返ってきます。

```python:PyTorch
torch.tensor([1,2,3,4,5]).max()
```

```python:NumPy
np.array([1,2,3,4,5]).max()
```

しかし、NumPyで言うところの`axis`を指定する場合、すなわち特定の軸に沿って最大値を求めたい場合の挙動が異なっています。

NumPyではaxisに複数の軸をタプルなどでまとめて指定でき、例えば画像のチャンネル毎に最大値を求めるといった使い方ができます。

```python:NumPy
x = np.array([[[8, 2, 2],
               [6, 2, 3],
               [8, 2, 4]],
              [[8, 4, 9],
               [0, 3, 9],
               [5, 5, 3]],
              [[6, 5, 5],
               [4, 8, 0],
               [1, 6, 0]]])
x.max(axis=(1,2))    # -> [8, 9, 8]
```

しかし、**Tensorの`max()`では一度に一つの軸しか指定できません**（しかも引数名が`axis`ではなく`dim`）。

更に、Tensorの`max()`では**最大値とその位置を示すインデックス（=argmax）がタプルで返ってきます**[^1]。

この仕様がとても扱いづらく、上記のNumPyと同じことを行いたい場合は返り値の0番目を取り出してmaxを重ねがけするという、とても不格好なことをしなくてはなりません。

```python:PyTorch
x = torch.tensor([[[8, 2, 2],
               [6, 2, 3],
               [8, 2, 4]],
              [[8, 4, 9],
               [0, 3, 9],
               [5, 5, 3]],
              [[6, 5, 5],
               [4, 8, 0],
               [1, 6, 0]]])
x.max(dim=2)[0].max(dim=1)[0]
```

また、上記のコードのようにする場合、dimを指定する順番によってはmax()を行う度に軸のインデックスがずれていくため、意図した通りの軸の最大値が求まらないといったバグの温床にもなりえます。

# 書いた関数

```python
from typing import Sequence, Union
from torch import Tensor

def tensor_max(x: Tensor,
               axis: Union[int, Sequence[int], None] = None,
               keepdims: bool = False
               ) -> Tensor:
    if axis is None:
        axis = range(x.ndim)
    elif isinstance(axis, int):
        axis = [axis]
    else:
        axis = sorted(axis)

    for ax in axis[::-1]:
        x = x.max(dim=ax, keepdim=keepdims)[0]

    return x

def tensor_min(x: Tensor,
               axis: Union[int, Sequence[int], None] = None,
               keepdims: bool = False
               ) -> Tensor::
    if axis is None:
        axis = range(x.ndim)
    elif isinstance(axis, int):
        axis = [axis]
    else:
        axis = sorted(axis)

    for ax in axis[::-1]:
        x = x.min(dim=ax, keepdim=keepdims)[0]

    return x
```

例えば`x`の最大値を求めたいときは`tensor_max(x)`のように書きます。
引数にはNumPyと同様に`axis`, `keepdims`を指定できます。

`axis`を複数指定した場合でも、降順でmax (min)をかけていくため、指定する順番によって結果が変化することはありません。

これを使うことで、PyTorchで複数の軸に渡る最大値、最小値もシンプルに書けるようになります。

```python
x = torch.tensor([[[8, 2, 2],
               [6, 2, 3],
               [8, 2, 4]],
              [[8, 4, 9],
               [0, 3, 9],
               [5, 5, 3]],
              [[6, 5, 5],
               [4, 8, 0],
               [1, 6, 0]]])
x.max(dim=2)[0].max(dim=1)[0]    # before
tensor_max(x, axis=(1,2))        # after
```

# おわりに
PyTorchは便利ですが、Tensorの仕様がNumPyと似ているようで微妙に異なるので戸惑うことが多いです。
統一されてほしいものです。

[^1]: https://pytorch.org/docs/stable/generated/torch.max.html
インターフェースと抽象クラスの違い

#インターフェースと抽象クラスの違い


#抽象クラス
抽象クラスはabstractメソッドを付ける事で強制出来る、メソッドは通常通り作れる
⇒継承させることで、サブクラスのメソッドを強制的に付ける事が出来る。
　つまり、派生したクラスに同一のメソッドを持たせる事と強制的にメソッドを作らせる事で
　強制力を持たせるクラスが作れる

　チームには、Aというクラスの中にはみんなが使う税率メソッドをつかって共通化されているけど
　地域の税金は、地域によってちがうから個々の派生したクラスでメソッドを作ってね。


#インターフェース
⇒インターフェースをimplementしたクラスは、インターフェースの箱に入れる事ができるつまり、インターフェースをimplementしておけば、条件によってAとBと切り替えが出来る。

サンプル（インターフェース）

```
public interface ControlPanelIf {
    void play();
    void pause();
    void stop();
    void forwardFast();
    void backwordFast();
}
これを実装するクラスは以下のコードになります。

実際はもっと複雑になることが多いですが、サンプルということで書いていきましょう。

public class DvdDeck implements ControlPanelIf {
    @Override
    public void play() {
        System.out.println("DVD再生");
    }

    @Override
    public void stop() {
        System.out.println("DVD再生停止");
    }

    @Override
    public void pause() {
        System.out.println("DVD一時停止");
    }

    @Override
    public void forwardFast() {
        System.out.println("DVD早送り");
    }

    @Override
    public void backwardFast() {
        System.out.println("DVD早戻し");
    }
}
このDVDDeckクラスを使うクラスが以下とします。

public class DeckUser {
    public static void main(String[] args) {
        ControlPanelIf myDeck = createDeck(args[0]);

        myDeck.play();
        myDeck.forwardFast();
        myDeck.pause();
        myDeck.play();
        myDeck.backwardFast();
    }

    private static ControlPanelIf createDeck(String deckType) {

        ControlPanelIf deck;
        if(deckType.equals("DVD") {
            deck = new DvdDeck();
        } else if(deckType.equals("BluRay") {
            deck = new BluRayDeck();
        } else if(deckType.equals("HDD") {
            deck = new HddRayDeck();
        } else {
            deck = new DvdDeck();
        }
        return deck;
    }
}
```

参考資料
https://www.slideshare.net/graminmakeall/java-43178044?qid=6a49c149-fcb0-4aa8-87d0-2e4e2c18362b&v=&b=&from_search=5
CentOS7で時間がずれる際のchronyの設定方法

## CentOS7で時間がずれる際のchronyの設定方法

- chronyとは？

```
CentOS7で標準で導入されているNTPクライアント(CentOS6まではntpdが導入されていた)
それぞれ違いはあるが、
chrony : 仮想感想など、NTPサーバと常時通信できない環境で有用
ntp : NTPサーバと常に通信できる環境で有用
```

## chronyの設定

- インストール

```sh
$ sudo yum install chrony
読み込んだプラグイン:fastestmirror
Loading mirror speeds from cached hostfile
 * base: ftp-srv2.kddilabs.jp
 * extras: ftp-srv2.kddilabs.jp
 * updates: ftp-srv2.kddilabs.jp
パッケージ chrony-3.4-1.el7.x86_64 はインストール済みか最新バージョンです
何もしません
```

標準でインストール済みで最新バージョンのようです。

- 設定ファイルの変更

```sh
$ sudo vi /etc/chrony.conf 
# コメントアウト
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst

# 追加
server ntp.jst.mfeed.ad.jp iburst
server ntp.nict.jp iburst 
```

- chronyの再起動

```sh
$ sudo systemctl restart chronyd
```

- 同期の確認

```sh
$ chronyc sources
210 Number of sources = 2
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
^- ntp1.jst.mfeed.ad.jp          2   6    17     7  -1686us[-1785us] +/-   61ms
^* ntp-k1.nict.jp                1   6    17     7    -84us[ -183us] +/-   10ms
```

`^` はサーバを表す
`-` は受け入れ可能なサーバ
`*` は現在同期しているサーバ

- 時間の確認

```sh
$ date
2020年  9月  1日 火曜日 21:00:25 JST
```

## 参考

- [CHRONY の使用](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-using_chrony)
- [【Linux】Chrony による時刻同期の設定および操作手順【Chronyd】](https://go-journey.club/archives/12037)
- [CentOS7で時間のずれを調整してみた](https://qiita.com/one-kelvin/items/36c59c674a82ff903143)
google vision apiをhocalhostでリファラーの制限を設定する

google vision api を開発環境で実行すると↓のエラーになります。
```ruby

'"message"=>Requests from referer <empty> are blocked.' '"status"=>"PERMISSION_DENIED",
```

APIのリファラーの制限をしている
開発環境でリファラーの制限しても動作させる方法

header にRefererを設定するとhocalhostでも動作する

https://qiita.com/kasajei/items/78f934b943ebdff7ef08
headers = {
    'Content-Type': 'application/json',
    'Referer': 'your domain here'
}
macOSの NFS automount設定

#はじめに
NFSサーバはCentOSで立てて、/home/export ディレクトリをマウントできるようにしてある。
ところが、マウントしてみるとなぜかhomeが書き込み不可で、exportには入れない始末。

というわけで調べてみた。

※macOSのバージョンは10.15.6, NFSサーバはCentOS 7.8

#サーバ側設定
クライアントがmacOSの場合は使用するポート番号の関係でinsecureオプションが必要。
また、元々の問題の原因はsubtree_checkオプションがなかったこと。

以上のことから、現在の/etc/exports はこのようになっている。（実際には*の代わりにネットワークアドレスが書いてある）

>/home/exports *(rw,no_root_squash,insecure,subtree_check)

#クライアント側設定
automountでマウントするようにする。以下の作業が必要。

- sudo su でrootになってから、/etc/auto_master を編集、/net行のコメントを外す。
- /etc/hosts にnfsサーバのIPアドレスとホスト名を追加（名前引きできれば要らないが、ドメイン名まで入力するのが面倒な場合は書いておくと良い）
- automount -cv を実行

これで、cd /net/＜hosts記載のホスト名＞ でマウントできるはず。
macOSのアップデートで/etc/auto_masterが元に戻ってしまうことがある。マウントできなくなったら確認すると良い。

#firewalld設定
CentOS7 デフォルトだと閉じている。
> firewall-cmd --add-service=nfs --permanent

でうまくいくかと思ったが、少なくともmacOSからはマウントできなかった。
20048/tcp, udp, 111/tcp, udp, 2049/tcp, udp を許可したところマウントできた。
重要な文字の特定―itemgetterとTfidfVectorizer―

#きっかけ
[メルカリコンペ1位のコード](https://www.kaggle.com/lopuhin/mercari-golf-0-3875-cv-in-75-loc-1900-s "Qiita")に出てきたitemgetterとTfidfVectorizerが良く分からなかったから。

#まとめ
itemgetter→イテラブル(リスト,文字列などfor文のinに書き込めるオブジェクト)から任意の要素を抜き出すことができる。

TfidfVectorizer→文章内の重要な文字を算出する際に使用する。スコアが高いほど文書内の出現頻度が高く、ほかの文書には出現しにくい文字であることを示す。

#itemgetter

name要素を取得する呼び出し可能なオブジェクトが一行目で返されている。
二行目でname要素だけを抽出している。	

```ruby:qiita.rb
from operator import itemgetter

item=itemgetter("name")
item({'name':['taro','yamada'], 'age':[5,6]})
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/2019922b-ac51-3577-22bd-af9eb6d184e2.png)


#TfidfVectorizer

[TF-IDF](https://qiita.com/AwaJ/items/5937665d5a4152cc24cf "Qiita")を算出する際に使用する。
TF-IDFは文書の中で重要な文字列は何かを特定する際に使用する。
コンペ内では、出展されている商品のブランド名を数値化するために使用されている。
以下の例ではfive,six,taro,yamadaの出現頻度が高く、他の文書には登場していない為、スコアが高くなっている。

```ruby:qiita.rb
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer as Tfidf

sample_string= np.array(['taro is five years old','yamada is six years old'])
tfidf=Tfidf(max_features=100000, token_pattern='\w+')
x=tfidf.fit_transform(sample_string)

pd.DataFrame(y.toarray(), columns=tfidf.get_feature_names())
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/744846fc-ebc1-dac6-9c64-9bb9ae4e4364.png)

#itemgetter, TfidfVectorizer, Pipelineの併用

itemgetter("name")のインスタンスとTfidfのインスタンスをパイプライン化している。
.transformでname要素の抽出が行われたのちに、name要素の中での重要度の算出が実行されている。
[パイプライン化はこちら](https://qiita.com/asparagasu/items/0cff067626ad7802aa75 "Qiita")

```ruby:qiita.rb
from sklearn.pipeline import make_pipeline, make_union, Pipeline
from sklearn.feature_extraction.text import TfidfVectorizer as Tfidf
from operator import itemgetter
from sklearn.preprocessing import FunctionTransformer
import pandas as pd

def on_field(f: str, *vec) -> Pipeline:
    return make_pipeline(FunctionTransformer(itemgetter(f), validate=False), *vec)

df=pd.DataFrame({'string':['taro is five years old','yamada is six years old'], 'age':[5,6]})
Pipeline=on_field('string', Tfidf(max_features=100000, token_pattern='\w+'))
Pipeline.fit(df)
data=Pipeline.transform(df)

pd.DataFrame(data.toarray(),columns=tfidf.get_feature_names())
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/1aa90f0d-7057-37d5-e637-fa203b7452f2.png)
Docker × Laravel コードを自動整形するコンテナを構築する

## PHP CS Fixer とは

[PHP CS Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) (PHP Coding Standards Fixer) とは、その名の通りPHPのコードをコーディング規約に沿うよう修正してくれるツールです。

## 前提

- [最強のLaravel開発環境をDockerを使って構築する【新編集版】](https://qiita.com/ucan-lab/items/5fc1281cd8076c8ac9f4)
- https://github.com/ucan-lab/docker-laravel

当記事は上記の記事の補足になる記事です。

## docker-compose.ymlの編集

```yml:docker-compose.yml
services:
  cs:
    image: herloct/php-cs-fixer
    volumes:
      - ./backend:/project
```

`services.cs` を追記します。

## コマンド

```shell-session
# 自動整形しない(差分表示のみ)
$ docker-compose run cs fix --dry-run -v --diff --diff-format udiff .

# 自動整形する
$ docker-compose run cs fix -v --diff --diff-format udiff .
```

## Makefile

コマンドが長いのでMakefileを用意しておくと良いです。

```
dry-cs:
	docker-compose run cs fix --dry-run -v --diff --diff-format udiff .
fix-cs:
	docker-compose run cs fix -v --diff --diff-format udiff .
```

下記のコマンドで実行できるようになります。

```shell-session
$ make dry-cs
$ make fix-cs
```

## 参考

- [Laravel PHP-CS-Fixer のルール設定](https://qiita.com/ucan-lab/items/7d4180462347a42009d5)
- [お手元のPHPファイルをphp-cs-fixerでチェックする](https://qiita.com/ucan-lab/items/37d8a9545d9d7fa1f06d)
アノテーションコメント


# はじめに
今回はアノテーションコメントについて。
コメントを書く際に、アノテーションコメントについて知らなかった(`TODO`や`FIXME`などは聞いたことがあったが、他に存在しているものが多くあった)、使えていなかったことがあったのでまとめればと思います。



# アノテーションコメントとは
アノテーションコメントとは`コメントにメタデータを付加するもの`。


### アノテーションキーワード

```ruby

# TODO: 不足している機能や、後日追加すべき機能を記す

# FIXME: 修正が必要なコード

# OPTIMIZE: パフォーマンスの問題を引き起こす可能性のあるコードや非効率なコードを記す

# HACK: 疑わしいコーディング方法が使用されていたコードの匂いを記す

# REVIEW: 意図した通りに動作しているかどうかを確認するためにレビューすべきもの
```

他にも

```ruby

# XXX: 危険！　大きな問題がある

# CHANGED: コードをどのように変更したか。

# NOTE:	なぜ、こうなったという情報を残す。

# WARNING: 注意が必要。
```


### アノテーションコメントを書く場所

``` ruby
# bad
def hoge
  baz(:quux) # NOTE: 
end

# good
def hoge
  # NOTE:
  baz(:quux)
end
```
### アノテーションコメント フォーマット
キーワードの後には、コロンとスペースを入れましょう。

```ruby
# bad
def bar
  # NOTE
  baz(:quux)
end

# good
def bar
  # NOTE: hogehoge
  baz(:quux)
end
```

### アノテーションコメント一覧をターミナルで表示する方法
検索したいキーワードを入力することで、任意のものが表示されます。

```
$ rake notes
$ rake notes:custom ANNOTATION= アノテーションキーワード
```

# 最後に
アノテーションコメント一を用いることでレビューしていただく人、後からチームにジョインされる方にとって疑問を解消する手助けにもなったり、レビューの負荷を下げることができるので積極的に使っていきたいですね。ただ何でもかんでもコメントを使いましょうというわけではなく、コードで解決できることが一番だと思うので、そこは念頭に置いてやっていければなと思います。

# 参考

The Ruby Style Guide
https://rubystyle.guide/

TODO: 以外のアノテーションコメントをまとめた
https://qiita.com/taka-kawa/items/673716d77795c937d422
入力した値段を非同期的に表示したい

【概要】
----------------------------------------
<b>1.結論</b>

<b>2.どのように記述するのか</b>

<b>3.ここから学んだこと</b>



1.結論
----------------------------------------
<b>javascript(jquery)</b>で、<b>inputイベント</b>を使う！

<br>
2.どのように記述するのか
----------------------------------------

```javascript:app/javascript/price.js
$(function(){
  $('#item-price').on('input', function(){
    let tax = $('#item-price').val();
    $('#tax-price').text(Math.ceil(tax * 0.1));
    $('#benefit').text(Math.ceil(tax - (tax * 0.1)));
  });
});
```
自分が書いたプログラムはこのようになります！

即時関数宣言をしています。
item-price/tax-price/benefit はHTMLの各表示部分の”id名”になります！価格が表示される部分と繋がっています。

inputイベントは値が変更された時に発火するもので、
item-priceに2000円と入力すればtax-price（200円)/benefit(1800円）と表示されるようになっています！

またtext(Math.ceil(tax * 0.1))の部分で、
textは'#tax-price'の中身を取得し、Math.ceilは小数点を切り上げています！

valも'#item-price'の中身を取得しています！


助けていただいたURL：
<a href="https://ja.javascript.info/events-change-input">イベント: change, input, cut, copy, paste</a>

<a href=http://js.studio-kingdom.com/jquery/attributes/val#0">.val()について</a>

<br>
3.ここから学んだこと
----------------------------------------
最初はinputイベントの部分をchaengeイベントで使用していました。そうすると、changeイベントでは、入力したあとでページのどこかしらを一度クリックしないと金額変更が反映されないことに気づきました。なのでinputイベントに変更しました。ただ戻るボタンを押して以前入力した金額を残した状態で金額変更を反映させる部分についてはキャッシュも絡んでくるので、もっと勉強しておきます！
<br>
Office365 でメールが開けない、と聞かれたらチェック箇所３つ

まれに、Office 365 のメールでつながらないと問い合わせを受けるケースがあります。「なんか、メールが開けない」とうふわっとした質問が来ます。

メールを開けないと聞かれたときに確認してることを3つまとめてみました。


#1.メールボックスの問題か、デバイス環境の問題か？

切り分けのために、これらを5つ確認します。これでアカウントの問題か、デバイスに問題か切り分けできます。

- 問題が起きているアカウントで、同じPCの別のブラウザで開けますか？
- 問題が起きているアカウントで、同じPCの同じブラウザの、プライベートブラウズで開けますか？
- 問題が起きているアカウントで、同じPCの同じブラウザで、テザリングして開けますか？
- 問題が起きているアカウントで、正常に使えている方のPCの、プライベートブラウズで開けますか？
- 問題が起きていない方のアカウントで、問題が起きているPCの、プライベートブラウズで開けますか？

別の環境で使えれば環境の問題だし、別の環境でもだめならアカウントに問題があると、切り分けできます。


#2.Exchange Onlineに障害が出ていないか？

365のリージョンあるいは365全体でトラブルが発生しているケースの可能性もあるので、変更して情報収集しておきます。

私が確認するところは主に3つ。

- Microsoft 365 Status
https://twitter.com/MSFT365Status

- Microsoft 365 管理センター - サービス正常性（※管理者権限必要）
https://admin.microsoft.com/AdminPortal/Home#/servicehealth

- Twitter検索。
「Office365 障害」とかで検索する。

未確認でも怪しいかな、と思うときはTwitter検索。日本語で数が増えてるな…ってときは日本リージョンで影響が出始めている、なんてことが多い印象。日本リージョンじゃない場合はあまりヒットしないかもしれないけど。
速報性だと、Twitter検索が最速。詳細性だと365管理センターですね。

365で障害が出てれば障害の解決待ち。そうでなく、デバイスが原因の場合はクライアントデバイスの状況を確認します。

#3.クライアントアプリは正しいか？

上記１でデバイス側に問題があるってことなら、この3つで解消するものがほとんどです。代替えPC渡せば、多くの場合メールは使えるはず、です。

ブラウザのキャッシュが悪さしてた　→　キャッシュクリア
サポートされてないブラウザ使ってた　→　サポートしてるブラウザ使って
ブラウザが古かった　→　アップデート

メールボックス側に原因だったこともないことはないけど、デバイスが原因だったことが多いです。
 



#4.まとめ
レアケースはありますが、ユーザーからのメール不具合に関する問い合わせは「開けない」と「送受信できない」でほとんどという印象。メールが開けないって聞かれたときの参考になれば幸いです。


---