OmniAICreator/Qiita-1.07M huggingface dataset:
コンポーネント間での値の渡し方について

##classとfunctionの違い

コンポーネント間でのデータの受け渡の方法のことのようですが、
どう違うのかをわかりづらかったので覚書です:pencil2:

###function
```js

function Greeting() {
  return <p>HelloWorld</p>;
}
```

###class
```js

class Greeting extends React.Component {
  render() {
    return <p>HelloWorld</p>;
  }
}
```

###出力

```js
<Greeting />
↓
HelloWorld
//functionでもclassでも同じ表示が出る
```

##classの特徴

functionの方が簡単ですが、classではfunctionで使えないメソッドを使えるようです。

①Stateを使うことができる
#####Stateとは
　- mutable data (可変のデータ)
　- maintained by component (コンポーネントによって保持)
　- can change it (変更可)
　（Propsはただ値を渡すだけ）

②Lifecycle eventを使用できる
#####Lifecycle eventとは
　Componentの状態に合わせてReactが自動的に呼ぶメソッド
　ex)componentDidMount() →ComponentがDOMに追加されたときに自動的に動くメソッド


##classとstateのルール

###class
・ReactComponentを継承していること

```js
class Greeting extends React.Component
```

・renderメソッドで値を返すこと

```js

render() {
    return <p>HelloWorld</p>;
  }
```

###state
・Componentとセットで使うこと
・値を更新するときはsetStateを使うこと


##Stateでコンポーネントに値を渡してみる

```js
<script type="text/babel" data-presets="env,react">
class Clock extends React.Component {

//stateで初期値を設定
    state = {time: new Date().toLocaleTimeString()};

//ComponentにMount（DOMに追加）された直後に動く
    componentDidMount() {
//1000ミリ秒(1秒）ごとにstateを更新する
      setInterval(() => {
       this.setState({ time: new Date().toLocaleTimeString() })
        }, 1000)
      }
        
//出力はrenderメソッド
    render() {
      return (
       <div className="time">
         The time is: {this.state.time}
       </div>
      );
    }
  }

    // Renders the App component into a div with id 'root'
    ReactDOM.render(<Clock />, document.querySelector('#root'));
</script>

<!--The App component above will be rendered into this-->
<div id="root"></div>

```

表示結果
<img width="315" alt="スクリーンショット 2019-05-31 20.36.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325594/84a13d38-09ce-9b4f-ba4d-cb786b02eec1.png">

##参照
https://qiita.com/kyrieleison/items/78b3295ff3f37969ab50
【Windows】【Python】PDFファイルを画像化してOpenCVで扱う

PythonでPDFを画像として取り込みたかったためメモ。

pdf2imageを利用して実現しています。pillowに依存にしているようなため、以下でインストール。

```py
pip install pdf2image
pip install pillow
```



また、PDF閲覧にpopplerライブラリを利用するため、「[Poppler for Windows](http://blog.alivate.com.au/poppler-windows/)」から、poppler-0.68.0_x86.7z(2019/5/31時点最新版)をダウンロードして適当な場所に解凍。


```py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# pyinstaller --onefile pdfcrop.py

import os
import numpy as np
import cv2 as cv
import pdf2image


def main():
    # popplerへの環境変数PATHを一時的に付与 ###################################
    poppler_path = os.path.join(os.getcwd(), "poppler-0.68.0", "bin")
    os.environ["PATH"] += os.pathsep + poppler_path

    # pdf2imageを用いてPDFファイルを画像へ変換 ################################
    filepath = os.path.abspath(os.path.dirname(__file__))
    filepath = os.path.join(filepath, "pdf", "template.pdf")

    pdfimages = pdf2image.convert_from_path(filepath)

    # 読み込んだ画像はRGB形式のためBRGへ変換し画面表示 #########################
    cvimage = np.asarray(pdfimages[0])
    cvimage = cv.cvtColor(cvimage, cv.COLOR_RGB2BGR)
    cvimage = cv.resize(cvimage, (480, 640))

    cv.imshow("pdf2image sample", cvimage)

    cv.waitKey(-1)


if __name__ == '__main__':
    main()

```

以上。
Ansible2.8.0個人的にインパクトの大きかった機能追加、変更点メモ


# はじめに
変更点や機能追加・削除した情報が網羅的にまとまっているページもありますが、自分に影響ある範囲はどこか正確に把握し、まとめておきたかったので今回はメモベースの記事にしました。

### ①PLAYRECAPにskipped,rescued,ignoredの回数表示が追加

冪等性を担保するために、対象インスタンスのファイルの有無で条件を分岐して、ない場合はダウンロード、ある場合はスキップする。みたいなコードを適用したときに、今まではskippedだったかどうかを実行結果を遡らないと何個スキップしたかわからなかったのですが、すぐに回数が確認できるようになってくれました。神！
rescuedに関しては、今までfailedにカウントされていたのが、rescuedにカウントされるようになったので、注意が必要です。

### ②retryファイル生成がデフォルトで無効になった。

.retryで生成されるあれです。GitHubにあげたくないのに、毎度生成されて、なんでこんなの出来るんだろうってずっと思っていたのでありがたいです。今回のアップデート知ったことなのですが、retryファイルが作られないようにする設定もあったみたいですね。

### ③sudo系オプションが``--become``に統一され、他のoptionは削除。

いろいろあったsudo周りのoptionが``--become``統一されました。何使えばいいのかとか、違いがあるんじゃないかとか考える必要がなくなります！


# 参考リンク

[Ansible] Ansible 2.8 リリース、便利機能や注意点まとめ
https://tekunabe.hatenablog.jp/entry/2019/05/16/ansible28

Ansible 2.8 Release Notes
https://github.com/ansible/ansible/blob/stable-2.8/changelogs/CHANGELOG-v2.8.rst#new-modules
gethostbyaddr()って外部と通信するんだね

#【 概要 】

ＰＨＰのあるシステムで、なぜかブラウザ表示が
重くなる現象が起きていました。

調査で、linux の netstat コマンドで見ると、
５３番ポートへの通信が大量に発生していました。

は？ と思い、いろいろ調べたところ、
[gethostbyaddr()](https://www.php.net/manual/ja/function.gethostbyaddr.php) が原因だと突き止めました。

#【 原因 】

最初に言っておきますが、
gethostbyaddr() に罪はありません。
コールの仕方に問題があったのです。

ＰＨＰのソースで、下手な書き方をしていて、
無駄に（大量に）ループしていたところがありました。

そのループ内で gethostbyaddr() をコールしていたため、
サーバからＤＮＳの問い合わせを大量にしていたのです。

コールの回数を少なくする修正をしたところ、
サーバ（ネットワーク）の負荷が減り、
ブラウザ表示が軽くなりました。

#【 そもそも 】

gethostbyaddr() って外部と通信するの？
と思われたでしょうが、言われてみれば、
ＩＰアドレスからホスト名を取得するのだから、
ＤＮＳの逆引きをしてるんじゃ？ と想像できます。

（本当は gethostbyaddr() 自体のソースを見るべきですが、
そんなスキルは無いですし、すみませんが、皆さまに おまかせします。）

例えばこれが mb_send_mail() だったら、メールを送るわけだし、
ループしたらまずいな、と考えるでしょう。

でも gethostbyaddr() が裏で通信しているなんて、
なかなか気付きません。単なる変換関数くらいに思うでしょう。
（サーバやインフラに疎い（うとい）人なら なおさらです。）

#【 まとめ 】

ＰＨＰソースの修正前は、通信先のネームサーバに
Ｄｏｓ攻撃をしていたようなものです。
（申し訳なかったです。）

gethostbyaddr() をコールする回数もそうですが、
同じＩＰアドレスで しつこく何回もコールしないよう、
結果をキャッシュする工夫も必要と思います。

あ でも、ふつうに使う分には問題ありませんよ。
信じられないくらいループしていたから
ネットワーク負荷が高くなっただけです。
JAVAの日本語文字化けの直し方(Arduino IDE含む)

過去にArduinoの文字化けに頭を悩ませたが、それもこれで解決する。
#JAVAソフトの日本語がTofuになる
Ubuntu 18.04のデフォルトフォントはNoto(No more tofu)なわけですが、JAVAで動くソフトの日本語は普通に文字化けしたりします。どうやらこれはJAVAのOpenType対応が不十分なため(おそらく昔のやつの対応が悪かったのをソフト使ってる側が引きずってしまってるのだろう)に文字化けっているようです。
#解決歩
```sudo apt install fonts-takao-gothic```
これをすると、インストールついでにデフォルトのフォントがTrueTypeのフォントであるIPAのTakaoに変わるので文字化けが治る。
Spring4でWhitelabel Error Pageが出た時の対処法


####404 This application has no explicit mapping for /error
解決法:build.gradle にthymeleafのランタイムを導入する一文を入れる。

```gradle:build.gradle
compile('org.springframework.boot:spring-boot-starter-thymeleaf')
```

####500 com.mysql.cj.jdbc.exceptions.MysqlDataTruncation: Data truncation: Data too long for column 'name' at row 1 
Sat Jul 13 00:25:39 JST 2019
There was an unexpected error (type=Internal Server Error, status=500).
could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.DataException: could not execute statement
原因：　
HTMLのフォームのinputタグのname属性に同じものがあったため、正しくはhogeとなるところhogehogeとかになっていた。
既存のinputタグをdiv単位でコピペする時に修正もれした結果。
解決法：Springが吐き出す大量のエラー羅列の一番上の方にどのカラムがおかしいか書いてあるので検索したり最近コピーした辺りのname属性をよく見る。２箇所だけでなく複数箇所コピー元のままになっている事が多いので治るまで探す。
React + TypeScript + Firebase環境を超高速で作る


#React + TypeScriptの環境を作る

基本は以下ドキュメントのままやれば大丈夫。
https://facebook.github.io/create-react-app/docs/adding-typescript

create react-appで雛形を作成。

```console
yarn create react-app my-app --typescript
```

必要なパッケージをインストール。

```console
cd my-app
yarn add typescript @types/node @types/react @types/react-dom @types/jest
yarn add firebase @types/firebase
```

以下コマンドを打つと、ブラウザが起動しサンプルのページが表示される。

```console
yarn start
```

これでReact + TypeScriptの環境ができた！

#Firebase環境のセットアップ

https://console.firebase.google.com へアクセス。
以下のような画面が表示されるので、[プロジェクトを追加]を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242473/78309da8-2461-a58e-0efb-945f5bcfcc79.png)

プロジェクト名、地域、リージョンを選択してプロジェクトを作成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242473/9d1aa27a-4295-a790-9a05-6ccdb233cdb7.png)

プロジェクトが作成されると、ダッシュボード画面が表示される。
Webアプリを作る場合は、</>ボタンをクリックしてアプリの作成を始める。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242473/f0206e7f-bfb1-aff5-bf24-7144abe9c7d0.png)

アプリができたら、歯車マークをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242473/8ee59159-a5d1-3090-a4d9-c3def747ee1f.png)

プロジェクトの設定画面が表示される。
画面下の方に行くとapiKeyとかの記述があるので、それを元にconfigファイルを作成する。
(apiKeyが表示されない場合は[Firebase SDK snippet]ラジオボックスの[CDN]を選択する。)

```react:/config/firebase.ts
import firebase from 'firebase';

const config = {
  apiKey: "your-api-key",
  authDomain: "your-app-name.firebaseapp.com",
  databaseURL: "https://your-app-name.firebaseio.com",
  projectId: "your-app-name",
  storageBucket: "your-app-name.appspot.com",
  messagingSenderId: "your-messagind-sender-id",
  appId: "your-app-id"
};

firebase.initializeApp(config);

export default firebase;
```

firebaseにコンソールからログインする。

```console
firebase login
```

firebaseの初期設定をする。
画面に従って設定すると自動でいろんなファイルが作られる。
ここではpublicフォルダ配下のファイルを上書きするか聞かれるが、拒否しよう。

```console
firebase init
```

ここまで来ればもうFirebaseが使える。
試しにユーザー作成をしてみる。
[Firebase Console](https://console.firebase.google.com "Firebase Console") にログインし、[Authentication]⇒[ログイン方法]から、[メール/パスワード]を有効にしておく。
その後、React側で以下記述でユーザー作成ができるようになる。

```react:login.tsx
import firebase from 'firebase';
import firebaseConfig from './config/firebase';

firebase.auth().createUserWithEmailAndPassword(email, password)
  .then(user => {
    alert("register complete!")
  })
  .catch(error => {
    alert('firebase error :' + error);
  });
```

#アプリのデプロイ

せっかくなのでアプリをデプロイしよう。
まずはfirebase-toolsをインストールする。

```console
npm install -g firebase-tools
```

アプリをビルドする。

```console
yarn build
```

デプロイする。これで以下URLでアプリにアクセスできるようになる。
https://your-app-name.firebaseapp.com/

```console
firebase deploy
```
MySQLのrootにパスワードを設定した後、rails sができない問題を解決する方法


MySQLにrootパスワードを設定した後に、rails sをしようとするとMySQLにアクセスする事が出来ずに、下記の様なエラーが発生した。


![スクリーンショット 2019-05-31 20.05.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396216/b8e4dfc8-ffa8-ec50-3a04-688894b6506b.png)

こらはパスワードがMysqlにアクセスするパスワードを設定していないが為に起こるエラー。
つまりdatebase.ymlファイル内のpassword:に値を入力することでエラーが解消できる。

**1.まずはconfig/database.ymlを開く**

```
config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password:
  socket: /tmp/mysql.sock
```

ここで注意しなければいけない事はdefaultのpasswordを直接入力してしまうケース。
defaultのpassword:に直接自分のパスワードを書いてしまうと、誤ってGitHubにコミット、プッシュした時に自分のパスワードを悪用されてしまう危険性があります。
その為、このケースではパスワードの代わりに**環境変数**と呼ばれるものを使用します。
環境変数とはコンピュータ自体が持てる変数のようなものです。

・やってはいけない例

```
config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: あなたのMySQLのrootパスワード（例:aiueo1234）
  socket: /tmp/mysql.sock
```

・正しい例

```
config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: <%= ENV['MYSQL_PASSWORD'] %>
  socket: /tmp/mysql.sock
```

この様にpasswordに<%= ENV['MYSQL_PASSWORD'] %>を記入することで、環境変数を利用する下準備が出来ました。
残りは肝心の環境変数自体をターミナルで定義するだけです！

・手順

```

1..ターミナルを開きホームディレクトに移動
 $ cd ~

2.vim .bash_profileを開く
 $ vim .bash_profile

enterを押して画面が切り替わったら
1.[i]を押してインサートモード入り
2.export MYSQL_PASSWORD='あなたのMySQLのrootパスワード'
を入力
3.Escキーを押してインサートモード終了
4.[:wq]と入力して保存&終了
```

上記の手順は 2. でデータベースのパスワードをbash_profileで定義する事でdatabase.ymlから呼び出せる様になるという事です。

そして最後にbash_profileは、

**ターミナルを開き直すか、sourceコマンドで更新しないと反映されないという性質がある** 為、最後にターミナルを開き直すか、以下のコマンドを入力する。


```
$ source ~/.bash_profile 
```

これで設定が反映されたので **rails s** をすると正常に起動する。
データウェアハウスの実装手順について

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257568/a254bb83-5157-c741-0717-8ea31eb07f76.png)

こちらを読んで
データウェアハウスの実装手順について

## データウェアハウス導入の基本戦略
ビジネスリスクを回避するために3つの戦略を採用すると良い

- 企業戦略
- 段階的デリバリ
- プロトタイピング

### 企業戦略
- 現在のアーキテクチャとツールを含む技術を選定する
- データの識別、粒度、マッピング、変換作業を適切に行う

### 段階的デリバリ
- 構築は、対象のサブジェクトに従って段階的に行う必要がある
- 予約データや請求データなどの関連事業のデータは、まずサブジェクト単位で構築してから、相互に統合する
- プロトタイピング
  - 構築に対して大きくアプローチするのではなく、小さく開発とテストを繰り返す

## 具体的な実装手順
|ステップ  |タスク  |成果物 |
|---|---|---|
|1 |プロジェクトのスコープを定義する |スコープの定義書 |
|2 |ビジネスニーズを特定する |論理データモデル図 |
|3 |データストアの要件を定義する |データストアモデル図 |
|4 |ETLツールまたは開発によるデータ取得 |ツールまたは取得システム |
|5 |データウェアハウスのデータ要件の定義 |移行データモデル図 |
|6 |定義したデータ要件の見直し |Todoプロジェクトリスト |
|7 |データウェアハウスにデータストアをマッピングする |データ統合マップ |
|8 |データウェアハウス設計 |データウェアハウス設計図 |
|9 |データストアからデータを抽出する |統合された抽出したデータ |
|10 |データウェアハウスへロードする |初期データロード |
|11 |データウェアハウスの保守 |継続的なデータ抽出とロード |

## データウェアハウス構築のベストプラクティス
- データの一貫性、正確性、整合性のテストプランを決定する
- 適切に統合、定義し、タイムスタンプを設定する
- 設計中は、ツール、ライフサイクル、データのコンフリクトに注意し、間違いを学ぶ準備をする
- 運用システムとレポートはリプレースしない
- データの抽出、クリーニング、ロードに時間をかけすぎない
- データウェアハウスを有用にしたいならビジネス担当者を含むすべての関係者をデータウェアハウスの導入プロセスに必ず関与させる
- エンドユーザー向けのトレーニングプランを準備する

## 書籍情報
クリシュナルンタ, データウェアハウジングを1日で学ぶ
https://amzn.to/2VNt4f0

Krishna Rungta, Learn Data Warehousing in 1 Day: Complete ETL guide for beginners
https://amzn.to/30THw92

## 雑感
翻訳が変な気がするので原書を読んだ方が良さそう
3点の回転方向を調べる

3点 $A,B,C$ が $A → B → C$ の順に動くときの回転方向を調べる。
<img width="300"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384860/28795e81-e2a5-b9d6-a5be-d92800d4f67d.png"> <img width="300"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384860/84eaf371-2f8d-1ebc-5792-635735316951.png">
## 調べ方
点Aを基点にして、線分ABと線分ACの傾きを比較する。

- 線分 AB の傾きは $\dfrac{dy1}{dx1}$
- 線分 AC の傾きは $\dfrac{dy2}{dx2}$

線分 AB の傾きのほうが小さいとき、すなわち、
$\dfrac{dy1}{dx1} < \dfrac{dy2}{dx2}$ のとき 左回り。

線分 AB の傾きのほうが大きいとき、すなわち、
$\dfrac{dy1}{dx1} > \dfrac{dy2}{dx2}$ のとき 右回りとなる。

**但し、線分AB又はACがY軸に平行な場合、$dx=0$となり、傾きを定義することができないので比べることができない。**

<img width="300"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384860/2b7d16d5-e576-b61b-a131-f3066654950b.png">
これを避けるために、各傾きに $(dx1 \times dx2)$ を掛けた数値を使って比較する。

- 線分 AB の傾き $\dfrac{dy1}{dx1} \times (dx1 \times dx2) = dx2 \times dy1$
- 線分 AC の傾き $\dfrac{dy2}{dx2} \times (dx1 \times dx2) = dx1 \times dy2$

$dx2 \times dy1 < dx1 \times dy2$ ･･･ 左回り（反時計回り）
$dx2 \times dy1 > dx1 \times dy2$ ･･･ 右回り（時計回り）

となる。また、

$dx2 \times dy1 = dx1 \times dy2$ の場合は、

3点は同一直線上の点である。
[（3点が同一直線上の点か調べる）](https://qiita.com/tydesign/items/ab8a5ae52eb9c50ad26a)

## 計算例
1. $A=(2,3),  B=(8,5), C=(5,9)$ のとき

<img width="300"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384860/f128781c-0ed8-8ca6-79a6-61a2aba0e186.png">

$dx2 \times dy1 = 3 \times 2 = 6$
$dx1 \times dy2 = 6 \times 6 = 36$
$dx2 \times dy1 < dx1 \times dy2$ なので左回り（反時計回り）

## プログラム
**3点が時計回りに配置されているかどうか調べる**
( AutoLISP )

```scheme
(defun point:IsClockwise (a b c)
    (<
        (* (- (car  b) (car  a)) (- (cadr c) (cadr a)))
        (* (- (cadr b) (cadr a)) (- (car  c) (car  a)))
    )
)
;; < Example >
(point:IsClockwise '(2 3) '(8 5) '(5 9))
;; -> nil
(point:IsClockwise '(2 3) '(5 9) '(8 5))
;; -> T
```

## 応用
[2本の線分の交差判定](https://qiita.com/tydesign/items/405f1345a437b03b6403)
pyenvでのanacondaの仮想環境の設定について

pyenvの仮想環境でjupyter-notebookを開くにあたって詰まったのでまとめる．
(pyenvはインストールされているものとします)

ターミナルにjupyter notebookを実行した際に以下のエラーが出る．

```
the 'jupyter' command exists in these python versions envs.
  "anaconda3-5.0.0"
```



```
$ pyenv global anaconda3-5.0.0
$ pyenv  versions 
  system
* anaconda3.5.0.0
  anaconda3-5.0.0/envs/py32
```
となっていることを確認する．


```
$ source activate py32
```

仮想環境がactivateされていればOK．
Macでファイルの文字コードの確認 / 変更の仕方

# 文字コードの確認
- **コマンド**
`file --mime <ファイル名>`

- **使用例**

```
$ file --mime hoge.csv 
hoge.csv: text/plain; charset=utf-8
```

# 文字コードの変更(上書き)

- **コマンド**
`nkf [オプション] --overwrite <ファイル名>`

- **使用例 (shift-jisに変換)**

```
$ nkf -s --overwrite hoge.csv
$ file --mime hoge.csv       
hoge.csv: text/plain; charset=unknown-8bit
```
# 備考(nkfコマンドのインストール / オプションの種類)

nkfコマンドをインストールしていない場合はhomebrewからインストールできます。

```
$ brew install nkf
```

オプションはこんな感じです

```
-j	JISコードに変換する
-e	EUCコードに変換する
-s	シフトJISコードに変換する
-w	UTF8コードに変換する
-r	ROT13/47の変換する
```

もっと詳しい使い方はこちらも参考になるかと思います。
[macにnkfコマンドがないだと！？じゃあ入れよう！ - Qiita](https://qiita.com/kou_bacchus/items/6448608ee03b0a71dcd4)
AndroidStudioでKotlinからCをCからKotlinを

せっかくJavaからKotlinにうつったので、Cを使う

■Setp1：プロジェクト作成。
---

![2019-05-30 (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/4c3c867c-cab4-91ab-27df-ef810b6e669a.png)
「File」「New」「New Project」かプロジェクト作成に入ります。
![2019-05-30 (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/9e4aca06-6588-1b32-af2e-b4748d27a71a.png)
Cを使うので「Native C++」を選択してから「Next」を
![2019-05-30 (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/9738e56e-8948-fbbc-5c36-7f84864102fe.png)
今回はNameを「test01」に
Save locationは作業ディレクトリーを
Languageは「Kotlin」を設定して「Next」を
![2019-05-30 (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/7198ca4d-b756-b4c5-8063-8a88d7c250be.png)
最後「Finish」を選択して
![2019-05-30 (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/a817809d-d9df-c58f-0769-21749c4cb016.png)
こんな画面が出たら完成

■Setp2：KotlinからC
---

プロジェクト作成した時点で、KotlinからCを呼び出すソースになっています。
実行すれば「MainActivity.kt」のなかから「stringFromJNI()」をよんでいるので、native-lib.cppの「Java_l_toox_test01_MainActivity_stringFromJNI」が呼ばれています。
（細かい話は、別途勉強しましょう）

■Setp3:CからKotlin
---

[MainActivity.kt]にCから呼ばれる関数「testFunc」を追加します。

```kotlin:MainActivity.kt
package l.toox.test01

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

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

        // Example of a call to a native method
        sample_text.text = stringFromJNI()
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    external fun stringFromJNI(): String

    companion object {

        // Used to load the 'native-lib' library on application startup.
        init {
            System.loadLibrary("native-lib")
        }
        @JvmStatic
        fun testFunc(){
        }
    }
}
```

呼ばれる「testFunc」は「compaion object」の中に必要なので注意です。

```kotlin
    companion object {
          :
        @JvmStatic
        fun testFunc(){
        }
    }
```

次にCからKotlinを読みだす部分。[Native-lib.cpp]を以下のように修正します。

```c:Native-lib.cpp
#include <jni.h>
#include <string>

extern "C" JNIEXPORT jstring JNICALL
Java_l_toox_test01_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject in_thiz) {

    jobject my_class = env->NewGlobalRef(in_thiz);
    jclass clazz = env->GetObjectClass(my_class);
    jmethodID mobj = env->GetStaticMethodID( clazz, "testFunc", "()V" );
    env->CallStaticVoidMethod( clazz, mobj );
    env->DeleteLocalRef( clazz );

    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}
```

「AndroidStudioでJavaからCをCからJavaを」の時と、少し呼び出し関数が変わっているので注意
https://qiita.com/sanoh/items/ef0b99fc1dd2f1484d7a

（引数が　jobject in_thiz　となっている事を注意してください。）

これで実行すればCからKotlinを呼び出しています。
![2019-05-30 (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/4c0074e1-f1c3-7b79-16c5-a8daeed53028.png)
デバッグ実行でブレークもはれます。
Google Play App Signing有効化して、脱apk->aabにする際にハマったポイント

## GooglePlayAppSigningについて

（**注意！：GooglePlayAppSigningを有効にすると戻せないので注意！**）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/095f4b8e-17b8-0557-e8bc-6fa9ee5316f8.png)

めちゃくちゃ推奨してくるこれです。

僕の場合は、既存アプリをアップデートする際に、「Googleでアプリ署名鍵を管理」を有効にしました。

有効にするとこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/2c9aad68-dbaf-f80a-55f5-945072e1542c.png)

@rkowase さんのサイトがとても参考になりました！
https://qiita.com/rkowase/items/90cdc4e8c6fc449d8276
普通はそのサイトを参考にしていれば問題ないかと思いますが、
[公式サイト](https://qiita.com/rkowase/items/90cdc4e8c6fc449d8276)見ながらやっていたのですが、全体像がさっぱり入ってこず、とりあえず流れでやってしまっておりました。
なので、そこらへんはスルーします。。:scream_cat:

## で、ぶつかったのがこのエラー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/d7f6eae3-1015-6a07-bd9f-71f99a581a79.png)
> Android App Bundle が誤った鍵で署名されています。 app bundleを正しい署名鍵 (SHA1:〜〜〜)で署名して、もう一度お試しください。

、、、、汗

```
$ keytool -list -v -keystore upload-keystore.jks 
```

該当の```SHA1:〜```を確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/7b9e864b-cc81-8c00-9400-0f4aac9c1242.png)
※赤い部分を照らし合わせる

・・・・・・
一致してる。。

・・・
原因がわからなくなってしまい、

心当たりがある、```.keystore``` ```.jks``` ```.pem``` ```.der```ファイル を片っ端から、
Android Studioで指定して、
aabファイルや
apkファイル（v1やv2、v1＆v2両方）、
をチェックしたり、
build.gradleでkeystoreを指定したり。。。
それでもだめ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/283075ac-d2cc-9441-f853-5b063fd0ee26.png)

何か手順を間違えたかで証明書がおかしいんじゃないかと思い。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/8a5bb1d0-4727-9d75-3d5b-87c5b1b1ffcf.png)


Googleさんにアップロード鍵のリセットで、問い合わせ、、、！泣 m( _ _ )m
しかも２回もしちゃいました。。（**新しい鍵が有効になるまで２日ぐらいあける必要がありました。**）

色々しらべて、、
aabファイルの署名って確認できないかなと、思ったらこういうコマンドがあったのね。。。！！！w

```
$ keytool -list -printcert -jarfile app/release/app.aab 
```

printcert神！

で内容を確認してみると！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/1df3a949-2664-04e2-df85-f11bfce9bffa.png)

署名と違う。。
よくみると以前つかっていた、keystoreの署名になっている。。。！

そういえば、Android Studio、出力ばっかりやってて、
クリーンアップしてなかったなと思い、、Clean Project。。。！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/0cf2dcb5-451b-465c-cb80-56b6df0eef51.png)

で、再度aabファイルを出力してみると、、、！

新しい署名に更新されてました！！！:joy:

長期戦、疲れた。。ｗ



## 便利コマンドTIPS

keystoreファイルの内容を確認するコマンド

```
$keytool -list -v -keystore upload-keystore.jks 
```

aabファイルの署名を確認するコマンド

```
$ keytool -list -printcert -jarfile app/release/app.aab 
```

署名がない、aabファイルを署名するコマンド

```
$ jarsigner -verbose -keystore upload-keystore.jks ./app/release/app.aab alias
```
※ちなみに既に署名がある場合に署名を追加してしまうと、google playにアップする際に署名を１つにしてエラーになります。




## 参考にさせて頂いたサイト

https://qiita.com/rkowase/items/90cdc4e8c6fc449d8276

https://qiita.com/n_morioka/items/746b32b934d768cbc560

https://github.com/mag0716/Google_IO_2018_CatchUp/blob/master/App%20Bundle/upload_flow.md

https://github.com/google/bundletool/issues/27

※aabファイルを実機テスト（DeployGateにあげれなかったので）
https://qiita.com/ikemura23/items/9b6064cb123edc1e233f
Salesforce Lightningの便利ポイント纏め

## Salesforce Lightning切替にあたり

Salesforce Lightningとは何か？はここでは解説しませんので公式URLを参照してください。
https://developer.salesforce.com/docs/atlas.ja-jp.lightning.meta/lightning/intro_lightning.htm

ClassicからLightningへ切替プロジェクトを進めています。
社内での利用人数が多く影響が大きい為、切り替え時に現場が使ってくれない事が
ないよう様々な策を講じました。

というのも、以下の点から現場インストールの難易度が高いと感じたからです。

- ClassicのUIに現場が慣れてしまっている。
- Lightningの画面表示速度がかなり遅い。Classicで2～3秒で表示される画面がLightningでは5秒以上表示される事も・・・
-  Classicへはいつでも戻せるのでよほど便利な機能がないとすぐに戻されて利用されなくなりそう。

という事で便利ポイントを纏めて、デモを行ったりして何とか使ってもらうところまで持っていけました。

なかなか骨が折れる作業でした。
## Ligtningの便利機能
ウケが比較的良かった便利機能を紹介したいと思います。

### セールスコンソール
Lightningの通常UIでは、オブジェクト毎にタブが表示されていますが
それとは別に**セールスコンソール**という表示形式があり通常の表示と見え方が異なっています。
このモードだと、レコード毎に新しくタブが開いていくような動きをします。

セールスコンソールで使えるビューのモードは、通常の「テーブル」「カンバンビュー」に加え「分割ビュー」が利用出来ます。

このモードが現場受けが良かったです。
左側で一覧を見ながら処理したいデータを選択すると右側に出てきます。
![SalesConsole.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180473/95ff1ce5-e8cf-686a-3f17-f4b31e2552e5.png)


これにより**画面遷移無く、１画面で様々なデータを修正する事が出来ます！**

# カンバンビュー
上でもちらっと触れましたが、**カンバンビュー**という表示モードがあります。
カンバンビューは、↓のような表示でステータスやフェーズという軸を１つ決めて、どのステータスにどのデータがあるのか一目瞭然で分かるようになっています。
![KanbanView.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180473/8d98eb05-c995-33bf-445e-ddd106f0001d.png)
担当顧客の営業状況などを管理するのに非常に便利なUIになっています。
グループ化された単位で集計する機能もあるので、ステータス毎に金額をサマリーして集計するという事も可能です。

# 画面遷移しなくてもできる事が多い
関連リストの編集など画面遷移せずとも出来る事が多くなっています。
編集した後に一覧に戻ったりするオペレーションが削減出来ます。
![ListEdit.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180473/f96fc690-e48f-156c-54b3-0c38b77a32c8.png)

# 画面下に常駐するユーティリティーバー
ユーティリティーバーという機能があり、これをONにする事で画面に便利なツールを常駐させておく事が出来ます。
ここは何を配置するかは、設定出来るようになっています。
この例では、History・Note・Macroを設定しました。
ノートは文字通りメモを残しておく事が出来ます。共有機能もあります。
![UtilityBarNote.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180473/620596ed-e116-399f-e93f-2e4685b2d6ff.png)

# レポート／ダッシュボードのUIが改善された
レポートとダッシュボードのUIが大幅に改善されました。
見た目もなのですが、以下が良い点かと思います。

- ドリルダウンが容易に出来る。
- グラフの拡大表示が柔軟に出来る。
 
<img width="1284" alt="Report.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180473/a4470a0e-6a9f-6e43-b55b-9c7be0e4e1c2.png">

# アプリケーションビルダーによる柔軟な配置
LightningコンポーネントというUIコンポーネントが標準で容易されておりそれを**画面上の操作から簡単に配置する事が出来ます。**
また、**コンポーネントを表示する条件を設定する事が出来ます。**
これにより、ある特定の状態になった時にコンポーネントを表示させる事が出来ます。
対応注意状態の顧客だったら表示、みたい事も出来そうです。

↓左側がLightning標準コンポーネントで右側のエリアにドラッグ＆ドロップで自由に配置する事が出来ます。色々ありますね。
![AppBuilder.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180473/44506f46-f829-78bb-5c52-e25dcf4637a1.png)
今の所よく使っているのは、

 - 関連リスト
 - 関連リストのクイックリンク（関連リストにすぐジャンプ出来て便利）
 - タブ
 - Chatter
 - レコードの詳細
 - パス

くらいなのですが、色々と使えるコンポーネントはありそうです。
# まとめ
Lightningの便利機能如何でしたでしょうか。
まだまだありますが、一旦ユーザーに関連する主要な部分という事で紹介させて頂きました。

便利な機能は良かったのですが
やはり、ボトルネックはClassicからかなり遅くなった画面表示速度でした。
こちらは引き続き改善を続けております。

他にも便利な機能ありましたら共有頂けますと幸いです。
[AWS] awscli: aws s3 mv コマンド実行に必要なIAMポリシ

同一バケット内で aws s3 mv コマンドを実行する場合、S3的にはキーの変更だから PutObject だけでできるかな？
→ 確認したら DeleteObject も必要でしたという話。

| mv元                     | mv先                     | 必要なAction |
|:-------------------------|:------------------------|:------------------|
| S3                       | S3(同一バケット内)        | GetObject <BR> DeleteObject <BR> PutObject    |
| S3                       | S3(別のバケット)          | GetObject(mv元) <BR> DeleteObject(mv元) <BR> PutObject(mv先) |
| S3                       | ローカル(ファイルシステム) |        GetObject <BR> DeleteObject       |
| ローカル(ファイルシステム) | S3                       |         PutObject        |

mv元と先で表のパターンが考えられますが、それぞれ以下の通りでした。

# 同一バケット内のmv

DeleteObject 無しでできるかな？とやってみたらエラーになりました。

```shell-session
$ aws s3 mv s3://＜バケット名＞/demo-file1.txt s3://＜バケット名＞/demo-file2.txt
move failed: s3://＜バケット名＞/demo-file1.txt to s3://＜バケット名＞/demo-file2.txt An error occurred (AccessDenied) when calling the DeleteObject
```

最低限のポリシとしては以下になります。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:DeleteObject",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::＜バケット名＞/*"
            ]
        }
    ]
}
```

これでmvできるようになりました。

```shell-session
$ aws s3 mv s3://＜バケット名＞/demo-file1.txt s3://＜バケット名＞/demo-file2.txt
move: s3://＜バケット名＞/demo-file1.txt to s3://＜バケット名＞/demo-file2.txt
```

# 別バケットへのmv

先ほど使ったActionのうちGetObject, DeleteObjectはmv元に、PutObjectはmv先に付与が必要です。以下がポリシです。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::＜mv元バケット名＞/*"
            ]
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::＜mv先バケット名＞/*"
            ]
        }
    ]
}
```

# S3からローカル(ファイルシステム)へのmv

mv元バケットに対するポリシが必要となります。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::＜バケット名＞/*"
            ]
        }
    ]
}
```

# ローカル(ファイルシステム)からS3へのmv

同様に、mv先バケットに対するポリシが必要となります。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::＜バケット名＞/*"
            ]
        }
    ]
}
```

これだけのポリシではaws s3 lsコマンドも実行できないので、実際にはListBucketとか追加して使うと思いますが、最低限のポリシとしては以上です。
rails/seedファイルを分割してディレクトリで階層化する

# やりたかったこと
 - `db/seeds` 配下のファイルが増えてきたので、ディレクトリで階層化したかった

# 問題点
 - 単純にディレクトリ作成しても `rake -vT` で一覧に出てこなかった

# 修正内容
## 修正前
```ruby:seed.rake
Dir.glob(File.join(Rails.root, 'db', 'seeds', '*.rb')).each do |file|
  desc "Load the seed data from db/seeds/#{File.basename(file)}."
  task "db:seed:#{File.basename(file).gsub(/\..+$/, '')}" => :environment do
    load(file)
  end
end
```

## 修正後
### コメントコードレビュー前
```ruby:seed.rake
Dir.glob(File.join(Rails.root, 'db', 'seeds', '**/*.rb')).each do |file|
  file_path = file[%r{db/seeds/.+$}].gsub(/\.rb/, '') # db/seeds/<dir>/<file>
  desc "Load the seed data from #{file_path}."

  task_command = file_path.gsub(%r{/}, ':') # db:seeds:<dir>:<file>
  task task_command.to_s => :environment do
    load(file)
  end
end
```
### コメントコードレビュー後
```ruby:seed.rake
Rails.root.glob('db/seeds/**/*.rb').each do |file|
  path_name = file.relative_path_from(Rails.root).sub_ext('').to_s  # db/seeds/<dir>/<file>
  desc "Load the seed data from #{path_name}."

  task_command = path_name.tr("/", ":")  # db:seeds:<dir>:<file>
  task task_command.to_s => :environment do
    load(file)
  end
end
```


いつもQiitaには感謝しております。
Akkaの[ERROR]Outgoing request stream error (akka.stream.AbruptTerminationException: Processor actor [Actor[...]] terminated abruptly)エラーについて

```scala
[ERROR]
[on-akka.actor.default-dispatcher-4]
[akka.actor.ActorSystemImpl(on)]
Outgoing request stream error 
(akka.stream.AbruptTerminationException: 
Processor actor [Actor[akka://on/system/StreamSupervisor-1/flow-0-0-PoolFlow#......]]
terminated abruptly)
```

アクターが切られた！とエラーを吐いています。 が、これは無害です。

アクターとは？ という方はこちらの記事をどうぞ。
https://qiita.com/kazhit/items/610bb7d0e1145ff8f423

このエラーが何故問題ないかというと、大体これが出る理由は ActorSystem をシャットダウンしたために Actor のコネクションが止まります。
その時に Actor側が 「何者かに止められた」 とエラーを吐いてきます。そのメッセージですね。
アクターは基本的に存在し続けるためこのようにエラーと表示されます。

まぁイメージだとPCをきちんと内部からシャットダウンして欲しいのに電源ブチ消しされてシステム側で怒ってるみたいな感じですね。そんなに気にしなくて良いです。

ERROR ではなく WARNING とかにして欲しいですね
vagrant + docker + browserSync と setcookie でハマった話

vagrant と docker についてはまだ検証不足で関係あるのか分かりません

# なにがあったのか
vagrant + docker + PHP(apache) で構築したローカル開発環境にて、PHP の `setcookie()` を用いているサイトの実装をしていたところ、ドメインの cookie 総サイズが 2k を超えたあたりから `setcookie()` を実行した際にレスポンスが返ってこなくなってしまった。

## 解決法
BrowserSync を挟んでアクセスしていたのが原因だったようで、BrowserSync なしでアクセスすると問題なく動作するようになった。なんなのなの。

## 原因の詳細
BrowserSync が原因らしいことは分かったけれど、この開発環境や cookie に不慣れなこともあり、なぜレスポンスが帰ってこないのかは分かっていないまま……引き続き調査中。

## 戒め
**困ったときは BrowserSync なしでアクセスしてみよう！！！！**
RedHatSummit2019で学んだたった一つの大切なこと

## 1.はじめに
この記事はRed Hat Summit 2019に登壇および参加をした際に 学んだ事を共有するための記事です。 なお、RHEL8やOpenShiftの技術製品の発表がありましたが、それをあえて排除し非エンジ ニアの方にも有用な学びを共有いたします。

## 2.Red Hat Summit2019とは?
Red Hat社が毎年1度行うイベント担っており、毎年参加者が増加しているとのこと 今年は8,300名以上が参加されたそうです!

[Red Hat Summit 2019 公式ページ](https://www.redhat.com/en/summit/2019)

## 3.目玉ポイント1: general session 

著名な重要人物が、登壇するgeneral sessionは注目度が高いです。 特に

- IBM CEO ​Ginni Rometty とRed Hat CEO im Whitehurstの対談
- MS CEO Satya NadellaとJim Whitehurstの対談 

は歴史的瞬間の立会いと言っても過言ではないと感じました。
実際に、会場の熱気が凄かったです(小学生並みの感想)

## 4.目玉ポイント2: 数々のグッズゲットのチャンス 

サミット開催中は、至る所でグッズ入手のチャンスがありました。 Tシャツ、充電ケーブル、バックパック、シャンパングラス..etc なんと言うか海外のイベントだからか派手な印象です。

## 5.目玉ポイント3:Summit 5K Run 
開催地のBostonは大学が多く、大学へのチャリティとして、コモンズの周りを5km走ると言 うイベントがありました。
朝5:30集合し、6:00に走る。。。と。
疲れますが、終わると非常にスッキリして良い気分になります。 
そこで、Jim Whitehurstと写真を撮りました^^;


*----- ここからSummitからの学びの共有です。*


## 6. Culture Transformation
今回は技術製品の発表(RHEL8やOpenshift4など)があったものの 技術の話だけではなく
*文化を変えた*
 と言う言葉が共通して何度も出てきたのが印象的でした。
その一例として

- Lockheed Martin社 は 毎日アプリケーションをリリースする。 
- DBS は伝統的銀行から世界一のデジタルバンクへ 
- BMW は Connected carの試験環境をRed Hat製品を使って構築 を実現しています。

特にDBSは面白い。

DBSのDavidとはAPAC Media Round Tableで同席したこともあり、非常に興味深い内容で した。 DBSのデジタル化については、以下の記事によくまとまっていると思うのでご参考ください。

[シンガポールDBS銀行のデジタルバンク化はなぜ成功したのか？](https://www.dappsway.com/entry/dbs-bank)

この記事の中で

- Become digital to the core.(会社の芯までデジタルに)  

- 「人とスキルに投資する」


「人とスキルに投資する」​では、「徹底した顧客第一主義」、「データドリブン」、「リスクを取って、実験 に挑む」、「アジャイル型」、「学ぶ組織になる」の5つの指針を掲げ、そのための学びのスペースや スタートアップとのコラボスペースの設置などを行っていった。
と言う言葉が印象的です。


### 6-1 なぜ、文化を変える必要があったのか。
それはすなわち
*変化し続ける組織に変えるため*
でした。
日々進化し続ける環境の中で
企業競争力を保つには、変化し続ける事がもはや前提にあるんだなと感じました。

Summitとは無関係ですがLeanとDevOpsの科学では 

- 『本書では「速度か安定性か」という2分化の考え方に異論を投げかけるエビデンスを示す。 
- 「速度は安定性に依存する。効果的なプラクティスを実践すれば速度も安定性も高められる」と主 張』
とされています。
速度が安定性に依存し
変わり続ける事が安定を産む事と理解しています。
       
そして、ここで言う”効果的なプラクティス”を実践するためにOpenShiftなどがあるのだな と感じました。

### 6-2  海外の企業は、どうやって文化を変えたのか。
恥ずかしながら勝手な思い込みで
海外の企業はトップダウンで意思決定し、一気に舵をきって文化を変えるもんだ
と思ってました。(「逆らうものはクビだ!!」と言った具合に)


*しかし実際はそうではなかったです。* 


OPTUS社の方とお話しする機会があり「どのように文化を変えたのか」と聞いたところ 

- ステークホルダーにやり方を変える際にメリットを説明する。 
- もちろんその時に反対するメンバはいる。しかし、やってみて小さくても成功事例を作れ ば、そのメンバも変化に積極的になっていく。
- そう言う小さなチャレンジを積み重ねる事で文化は変わっていく

と言う答えでした。

general sessionでも
*文化は変えようとして変えるものではない*

とあったので正にその通りですね。 小さなチャレンジができる機会、環境を用意さえすれば、文化を変える事に繋がっていくん だなと感じました。

そして、海外も日本も関係なく、変革に必要なアプローチは変わらないんだなと感じました。(スピードは全然違うが。。。)


DBSも10年かかっているので、まだまだ諦めるには早いですね。
しかし、文化を変えて変化に強い企業にしないと
競争力が弱まり淘汰されていきます。

今回登壇された企業はその危機感から文化を変えざるを得なかったのでしょう。

これから日本で、どんな企業が文化を変えた事例を発表していくかが楽しみになりました。

そんな学びを得られたRed Hat Summitは素晴らしいですし 是非来年も参加したいと思います。


読んでくださりありがとうございました。
覚書：htaccessの正規表現で部分的に抜き出したいときの記述

RewriteEngine On
RewriteCond %{QUERY_STRING} (^|&)p=([0-9]+)(&|$)
RewriteRule ^/(.*)/index.php?$ /test/test.html?pg=%2 [L,R=302]

RewriteCondで()でくくった2番目のp=([0-9]+)の数字部分だけをとってきています。
RewriteRuleの(.*)のところを取ってきたい場合は$1を使用する
[Rails]aタグでも「data-method="delete"」を設定すればlink_toと同じ挙動

#概要
railsにおいてCSRF対策の学習中、ヘルパーを使わないとエラーになるとのことで、試しにクロームでlink_toのフォームの検証をしてaタグでdeleteを記述したところ、エラーにならなかったので、いろいろと調べて見ました。

結論は、CSRF対策の本質はlink_toではなく、カスタムデータ属性にありました、ということです。

#問題提起
```ruby
<%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %>
```

上記をクロームで検証したところ、

```html
<a rel="nofollow" data-method="delete" href="/tweets/10">削除</a>
```

となっていました。

CSRF対策ではlink_toとヘルパーをつかうとトークンが発行されて、問題のないリクエストかを判断するとのことでしたので、このaタグに書き換えたらトークンは発行されないのでは？　と思い、実際にファイルを書き換えたところ・・・・・。

結局、トークンが発行され、link_toとなにも変わりませんでした。


aタグでもいけるじゃん！
と思ったのが今回いろいろ調べたきっかけです。


※冷静に考えると、クロームでの検証が本物で、ファイルを書き換えて検証結果と同じにすることに意味はなかったのですが、そこのツッコミはご容赦いただきたいです。

#発見した記事

最初に発見した記事です。
[link_toで突然methodが効かなくなって困ってるあなたへ](https://qiita.com/nilinomiya1222/items/e50b1dcc3da0da36988b)

ここからmethodにjQueryが関わっているらしいことがわかりました。
そういえば、aタグにカスタムデータ属性が設定されています。

この辺に、link_toのカラクリがありそうです。

#rails.js

```javascript
// Handles "data-method" on links such as: |
// <a href="/users/5" data-method="delete" rel="nofollow" data-confirm="Are you sure?">Delete</a> 
    handleMethod: function(link) { 
      var href = rails.href(link), 
         method = link.data('method'), 
         target = link.attr('target'), 
         csrfToken = rails.csrfToken(), 
         csrfParam = rails.csrfParam(), 
         form = $('<form method="post" action="' + href + '"></form>'), 
         metadataInput = '<input name="_method" value="' + method + '" type="hidden" />'; 

       if (csrfParam !== undefined && csrfToken !== undefined && !rails.isCrossDomain(href)) { 
        metadataInput += '<input name="' + csrfParam + '" value="' + csrfToken + '" type="hidden" />'; 
      } 

       if (target) { form.attr('target', target); } 
  
      form.hide().append(metadataInput).appendTo('body'); 
       form.submit(); 
     }, 
```

jquery-ujsのgithubからです。
https://github.com/rails/jquery-ujs/blob/master/src/rails.js

ここからカスタムデータ属性の値を取得してメソッドを決定、またトークンをくっつけていることがわかります。

また、ブラウザがDELETEのHTTPメソッドをサポートしていないことから、

```html
<input type="hidden" name="method" value="delete">
```
としてform タグから _method を指定してdeleteメソッドを再現していることもわかります。

#まとめ
まだしっかり理解したわけではないのですが、アプリケーション外からのリクエストだとこのrails.jsを通さないのでCSRFを防げるということなのでしょうか。

補足、訂正がありましたら、教えていただけると幸いです！

以下、参考記事。
https://cre8cre8.com/rails/get-post-delete-put-match-routes.rb.htm
https://spitfire-tree.hatenadiary.org/entry/20120323/1332477590
Ruby/Railsで土日＋祝日＋α営業日計算

この記事は
===

* Ruby/Railsで土日＋祝日＋α営業日計算をやる必要があったのでメモです

やりたかったこと
===

* 今日から10営業日前の日付だとかを取得したかったです
* 営業日の定義としては下記
    * 土日以外
    * 祝日以外
    * 年末年始以外
        * 12/29-1/3まで

やり方
===

* ありがたくライブラリを入れます
    * [営業日計算: business_time](https://github.com/bokmann/business_time)
    * [日本の祝日: holiday_jp](https://github.com/holiday-jp/holiday_jp-ruby)

```rb:Gemfile
gem 'business_time'
gem 'holiday_jp'
```

* 結構試行錯誤しましたが、こんな感じで初期化をしました

```rb:config/initializers/business_date.rb
# 2000/1/1から翌年末までの営業日を範囲とする
start_date = Time.zone.parse('2000-01-01 00:00:00')
end_date = Time.zone.now.next_year.end_of_year

# 営業日計算ライブラリの営業時間を終日に指定
BusinessTime::Config.beginning_of_workday = "00:00:00 am"
BusinessTime::Config.end_of_workday = "11:59:59 pm"

# 営業日計算ライブラリへ日本の祝祭日情報を読み込み
HolidayJp.between(start_date, end_date).each{|h| BusinessTime::Config.holidays << h.date }

# 追加で独自の年末年始休暇を取り込み
# 12/29-1/3まではお正月休みとする
(start_date.year..end_date.year).each do |year|
  BusinessTime::Config.holidays << Date.new(year, 1, 2)
  BusinessTime::Config.holidays << Date.new(year, 1, 3)
  BusinessTime::Config.holidays << Date.new(year, 12, 29)
  BusinessTime::Config.holidays << Date.new(year, 12, 30)
  BusinessTime::Config.holidays << Date.new(year, 12, 31)
end
```

やってること
===

* business_timeが営業日だけでなく営業時間まで見ている緻密な仕様なので、00:00:00-23:59:59までを営業時間と指定している
* holiday_jpの祝祭日情報をごっそりbusiness_timeに引き渡している
* 独自の年末年始休みを追加している

結果
===

* 1日ずつ遡っていったら、ゴールデンウィークで時が消し飛んでいてびっくりした

```rb
pry(main)> 18.business_days.ago.beginning_of_day
=> Tue, 07 May 2019 00:00:00 JST +09:00
pry(main)> 19.business_days.ago.beginning_of_day 
=> Fri, 26 Apr 2019 00:00:00 JST +09:00
```

終わりに
===

* キングクリムゾン！
ML-AgentsのSetRewardとAddRewardの違い

# はじめに
強化学習で用いられるML-Agentsの`SetReward`メソッドと`AddReward`メソッドの違いについて調べてみました。

# 実行環境
Unity 2019.1.4f1

ML-Agents 0.8.1

# 説明

> `SetReward` : 現在のステップの報酬量を**設定**します。もし同じステップにSetRewardを何度も呼び出した場合は最後のものだけが有効になります。

>`AddReward` : 現在のステップの報酬量を**調整**します。

## 例
```C#
SetReward(0.3f);      // normal step reward 0.3
if (gotBonus)
    AddReward(0.1f);  //   adjust reward to 0.4
else if (gotPenalty)
    AddReward(-0.1f); //   adjust reward to 0.2
if (reachedGoal)
    SetReward(1.0f);  // reset step reward to 1.0
```

# 参考

- [Unity ML Agents - AddReward and SetReward · Issue #631 · Unity-Technologies/ml-agents · GitHub](https://github.com/Unity-Technologies/ml-agents/issues/631)
Blazorで令和表示する

# 概要

今年開催されていたde:code2019のセッション[MW51 C# ドキドキ・ライブコーディング対決 @ de:code - ONLY C#!! Blazor Web 開発バトル -](https://www.microsoft.com/ja-jp/events/decode/2019session/detail.aspx?sid=MW51)を受けてきました。
4人の掛け合いが楽しい素敵なセッションでございました。

その中で出たお題に対して、Blazorの勉強がてらやってみようと思った次第です。
ちなみに、お題はこちら（これは問題2ですが、問題1は元年なし）
![IMG_2510.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365084/b41aedd4-b10e-fabe-1656-51793313ae28.jpeg)

# Blazor環境構築

[ここ](https://docs.microsoft.com/ja-jp/aspnet/core/blazor/get-started?view=aspnetcore-3.0&tabs=visual-studio-code)に全部書いてあるんですけど、一応やります。
ちなみに、今回はVisual Studio Codeを使います。

## [NET Core 3.0 Preview SDK のインストール](https://dotnet.microsoft.com/download/dotnet-core/3.0)

* 環境にあったやつをダウンロードしてインストールするだけ。

## Blazor拡張機能のインストール

* PowerShellで以下を実行する。

```powershell
dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview5-19227-01
```
## [Visual Studio Code向けのC#の拡張機能インストール](https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp)

* これはVisual Studio Code立ち上げてインストールした方が早い。

## Blazorの最小テンプレートインストール

* @jsakamotoさん製の[Blazor最小テンプレート](https://github.com/jsakamoto/BlazorMinimumTemplates)インストール
* 最小構成でプロジェクト作れるので凄い便利！

```powershell
dotnet new -i Toolbelt.AspNetCore.Blazor.Minimum.Templates::3.0.0-preview5-19227-01
```

## プロジェクト作成

```powershell
md blazor-reiwa
cd blazor-reiwa
dotnet new blazormin
```
Blazorのプロジェクトができました。良いですね。

# 実装

* `App.razor`を書き換える。
* セッションでは、`CultureInfo`使った後、`平成`を`令和`書き換えようとしてたのでそれを踏襲。
* 元年表示はチェックボックスにしてみた。
* バリデーションはとりあえず考えない。

```CSharp:App.razor
@using System;
@using System.Globalization;

<form onsubmit="@OnSubmit">
    <div>
        <label>
            <input type="checkbox" bind="@IsGannen" />元年表示
        </label>
    </div>
    <input type="text" bind="@InputText" />
    <button>変換</button>
    <div>
        @OutputText
    </div>
</form>

@functions {
    public bool IsGannen { get; set; }

    public string InputText { get; set; }

    public string OutputText { get; set; }

    public void OnSubmit()
    {
        var cultureInfo = new CultureInfo("ja-JP", true);
        cultureInfo.DateTimeFormat.Calendar = new JapaneseCalendar();

        var inputDate = DateTime.Parse(InputText);
        var gengo = inputDate.ToString("gg", cultureInfo);
        int year =  int.Parse(inputDate.ToString("yy", cultureInfo));

        if (inputDate >= new DateTime(2019, 5, 1))
        {
            gengo = "令和";
            year = year - 30;
        }

        OutputText = $"{gengo}{(year == 1 && IsGannen ? "元" : year.ToString())}{inputDate.ToString("年M月d日", cultureInfo)}";
    }
}
```

# 実行

```powershell
dotnet run
```

サーバーが立ち上がるので、http://localhost:5000/ をブラウザで開く。

![GIF.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365084/93d1780e-94e6-dc87-e98d-a44fd50c5e22.gif)
いいですね。

# まとめ

これをあの状況で10分でやるのは無理ゲーやで…。

# ソースコード

https://github.com/obuchi3/blazor-reiwa
さくらのレンタルサーバで.htmlをphpで動作させたい

#さくらのレンタルサーバでハマった
さくらのレンタルサーバー上でhtmlファイルにPHPを記述し、
.htaccessファイルに以下の2行を記述した。

`AddType application/x-httpd-php .php .html
AddHandler application/x-httpd-php .php .html`

**が、動かなかった!**
以下は対応内容を備忘のため、記述しました。

##1.php.cgiファイルと.htaccessの作成
php.cgiファイルと.htaccessの2ファイルを作成する。
このファイル作成時、下記の2点を注意する。
1.ファイルの文字コードは<font color="red">**EUC-JP**</font>にすること！
2.改行コードは<font color="red">**LF**</font>にすること！


```text:php.cgi
#!/bin/sh
exec /usr/local/bin/php-cgi
```

```text:.htaccess
Action myphp-script /php.cgi
AddHandler myphp-script .php .html
```

このとき、.htaccess1行目はphp.cgiを配置するフォルダパスになるように記述すること。

##2.ファイルを配置する
ファイルを`/home/アカウント名/www/`以下の任意の場所に配置する。

##3.ファイルのパーミッションを変更する
php.cgiのパーミッションを705 or 755に変更、
.htaccessのパーミッションを644に変更する

```text:php.cgi
chmod 705 php.cgi
chmod 644 .htaccess
```

これで対応完了です。
なお、ファイルの文字コードがUTF-8になっているのに気づかず、1時間くらいハマってました。
【SpringBoot】テストクラスで@Autowiredを動かすまで【JUnit5】

# やること
`SpringBoot + JUnit5`で、テスト時にコンストラクタパターンのインジェクションを動かすまでやります。

# やり方
`@ExtendWith(SpringExtension.class)`と`@SpringBootTest`を付与すれば動きました。

## サンプルコード
```java
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@DisplayName("コンストラクタパターンを動かすテスト")
@ExtendWith(SpringExtension.class)
@SpringBootTest
class AutowiredTest {

    private final AutowiredClass autowiredClass;

    private final String hoge;
    private final String fuga;

    @Autowired
    AutowiredTest(AutowiredClass autowiredClass) {
        this.autowiredClass = autowiredClass;

        hoge = "文字列";
        fuga = "文字列";
    }

    @Test
    @DisplayName("何らかのテスト")
    void uploadFile() {
        assertEquals(hoge, fuga);
    }
}
```

## 補足
JUnit5なので、クラス中では`public`を付けないで色々書けます。
また、コンストラクタは`private`でもインジェクションしてくれます。
OculusQuest向けに地雷踏みまくった話。

#先まとめ
unityhubに全部任せましょう（大敗北）

#OculusQuest向けに踏んだ地雷
・unityhubをインストールしておらずunity2019のアセットストアで
　古いアセットしか使わせてもらえなかった

・unityhubをインストールして最新アセットにしたにもかかわらず
　OVRIputが見つからないと言われビルドできない

・空のプロジェクトから初めてビルドは出来たが
　libOculusAudioSpatilizerがみつからないとかいうエラーでアプリ起動せず。
　もちろんそのファイルはある。

#解決策
・unityHubで新しいunity入れて、Android向け環境も一緒に入れた。終わり。悔しい。
[Xcode]初期化してたMacbook Air(2017) のXcodeがインストールできない

#問題
ある時自分のMacbookが突然壊れて困っていたところ、ひょんなことから使用済みのもの(Macbook Air 2017)を譲っていただけることになったのですが、
`Xcode`がインストールできなくて少しつまづきました。
![xcodeCannnotInstall-190531.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427937/5099c8e4-7628-1797-315a-cc8859744a6b.png)
#解決策
OSのバージョンをアップデートする(だけ)
#やり方
困ってこの記事に行き着いた方は、アップデートぐらいやろうとしたさ！
でもこんな感じでできねんだ、、、という方だと思います
![appstoreUpdateList-190531.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427937/e27e7b4d-f8b7-b0f8-63a4-96988cd34194.png)
ただ`このMacについて`でよく見るとこいつのバージョンは
`Mojave(執筆当時最新)`ではなく`Sierra`でした
(2017製のものが初期化されてるんだから最新でないのは当たり前ですね)
![macCurrentVersion-190531.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427937/8a7171a3-4890-b256-b7a5-f0332e8a40e9.png)
同じように思い当たる節があった場合はAppStoreか[ブラウザ](https://www.apple.com/jp/macos)で
`Mojave`とか`macOS`で検索してOSを最新版にアップデートしましょう

アップデートできたら`Xcode`がダウンロードできる状態になってるはずです

お疲れ様でした
Python3+djangoで環境構築

#はじめに
自身のPCに**Python**の環境構築する。

##PC環境
macOS Mojave version 10.14.15
Homebrew(macOS用パッケージマネージャー)

##**Python**のインストール
macOSにはデフォルトで**Python2.7**がインストールされているようなので、念の為確認します。

```
$ python -V(Vは大文字なので注意)
Python 2.7.10
```

確認した上で、**Python3**をインストールします。

```
$ brew install python3
```

これで**Python**のインストールは完了。

##**pyenv**をインストール
**pyenv**とは、**Python**のバージョンを管理するコマンドラインツールです。
これをインストールしないと、**Python3**をインストールすることはできても、バージョン変更ができないため、結局**Python3**が使えないようです。

```
$ brew install pyenv
Updating Homebrew...
```

念の為、**pyenv**のバージョンを確認。

```
$ pyenv -v
pyenv 1.2.11
```

**Python**のバージョンに合わせたものをインストールする。（私の場合3.6.3をインストールしました。）

```
$ pyenv install 3.6.3
python-build: use openssl from homebrew...
```

ここでエラーが発生。

```
BUILD FAILED (OS X 10.14.5 using python-build 20180424)
```

色々調べた結果、マニュアルでパッケージ？のようなものをインストールする必要がある模様。

```
$ sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
```

これでもう一度**pyenv**をインストール。

```
$ pyenv install 3.6.3
```

全体の環境に反映させる場合は、

```
$ pyenv global 3.6.3
```

で適用されます。

##**django**のインストール
**Python**のフレームワークの**django**をインストールします。
**django**をインストールするには、**pip**というパッケージ管理システムをインストールする必要があります。

PAHTを通す必要があるようなので

```
$ export PYENV_ROOT="$HOME/.pyenv"
$ export PATH="$PYENV_ROOT/bin:$PATH"
$ eval "$(pyenv init -)"
```

次に**pip**をインストールします。

```
$ easy_install pip
```

これで**pip**のインストールが完了。
次に、**django**をインストールします。

```
$ pip install django
```

これで一通りの環境設定は完了です。

##最後に
**Python**の環境構築に関して基本的な流れを紹介しました。
ご自身の環境に合わせて参考にしてください。

##参考にした記事
[macOSのデフォルトPythonでpipを使う](https://qiita.com/tom-u/items/134e2b8d4e11feea8e12)
[[MacOS Mojave]pyenvでpythonのインストールがzlibエラーで失敗した時の対応](https://qiita.com/zreactor/items/c3fd04417e0d61af0afe)
[]()
2019/05/31 JaSST'19 Tohoku

# 1. Conference Outline

05/31(金) に仙台においてテストカンファレンス "JaSST'19 Tohoku"がありました
http://www.jasst.jp/symposium/jasst19tohoku.html

<IMG SRC="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/76df661c-23b3-d490-a51f-924f5c3e955c.jpeg" width=80%>


今回のテーマは、「明日のテストを楽にする」です。
このカンファレンスで発表する機会を頂きまして、テスト自動化で直面した課題に対してどのようなことをチームで改善活動行ってきたかを発表しました。


# 2. My Presentation outline

<A HREF="https://www.slideshare.net/SadaakiEmura/20190531-jasst19-tohoku-148204446"><IMG SRC="https:////image.slidesharecdn.com/20190531-jasst19tohoku-pub-190530015726/95/slide-1-1024.jpg" WIdth=80%></A>

## 2-1. チームの変遷で直面したテスト自動化の課題

- 2016年、QAチーム立ち上げとあわせて、テスト自動化を導入した
 - 担当したサービスは主に１つ
 - リードがTA(Test Analyst), TM(Test Management), Automationを担当
 - リードはマニュアルテスト、自動化テスト両面把握できていた
- 2018年ころから組織拡大
 - 担当サービス増える
 - マニュアルと自動化でチームが分かれる
 - マニュアルチームには、それぞれのサービスにリードを立て、TM,TA担当
 - 自動化チームは、全サービスを基本的にリグレッションデサポート
- 拡大によって課題が発生
 - テスト自動化の質を維持するための工数増加
 - マニュアルチームから見て、自動化で何を品質担保しているかが不明
 - プロジェクトスピードにテスト自動化が追い付かない


## 2-2. 課題を改善する活動

- テスト自動化設計書のテンプレート作成
 - マニュアルチームから見て、自動化がどういった処理でなにを品質担保しているかわかるようにテスト観点等を記載
 - 自動化担当者にとって、なにを実装するべきか（validateすることなど）を明確化
 - データドリブンする箇所を切り出す（テスト条件、パラメータ等）
 - テスト自動化でやらないこと（品質担保できないこと）を明確化し、マニュアルテストでカバーしないといけないことを明確化
 - CIで動かす想定で実装に組み込まないといけないこと（CI条件）を記載
- プロジェクトでマニュアルと自動化のレスポンシビリティを定義
 - テスト自動化がすでにカバーしている既存機能で、修正が入るところを最優先に対応
 - テスト自動化でカバーしていない新規機能は、次回以降のプロジェクトのリグレッションテストとして対応

## 2-3. 効果

- テスト自動化の質の向上と工数削減
- マニュアルチームから見て、テスト自動化が明確化
- 短期プロジェクトに自動化が追従




 
 <IMG SRC="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/4032484b-1181-0e6f-e0a2-5dc9b5eb8728.jpeg" width=80%>


# 3. 皆さんのテストでのお悩みと、解答例
事前アンケートで集められたテストに関するお悩みと、参加者たちで回答を記載するコーナです


<IMG SRC="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/4f06472f-deb6-27ad-ef6e-4faae2b2e5f0.png" width=80%>


# 4. 手土産
248 Pageの大作！！
テストの教育に使えそうです！

<IMG SRC="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/cfbe6e39-b27a-cb97-4524-2ca86e544052.png" width=80%>

<IMG SRC="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/fc99a016-5491-7f3c-a143-2202c791e401.png" width=80%>
TypeScript(JavaScript)でArrayのtranspose(転置・行列入れ替え)をする

![スクリーンショット 2019-05-31 17.39.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47823/4084bc6e-f0b2-11aa-d17a-061e703c4b8f.png)

の行列を入れ替えたい時ってありますよね。

```typescript
const table = [
  ['www.apple.com', 'www.apple.com'],
  ['www.amazon.com', 'www.amazon.com', 'www.amazon.com'],
  ['www.google.com'],
].sort((a, b) => b.length - a.length);

table[0]
.map((_, idx) => table.map (row => row[idx]));
```
![スクリーンショット 2019-05-31 17.26.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47823/0c299fcd-bdee-3cf2-1157-fb462a43a5ca.png)

undefinedが嫌な時もありますよね。

```typescript
const table = [
  ['www.apple.com', 'www.apple.com'],
  ['www.amazon.com', 'www.amazon.com', 'www.amazon.com'],
  ['www.google.com'],
].sort((a, b) => b.length - a.length);

table[0]
.map((_, idx) => table.map (row => row[idx]))
.map(row => row.filter(v => v));
```

![スクリーンショット 2019-05-31 17.32.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47823/575c0002-d9ad-9c17-7f31-591ac7c8fde5.png)

まとめると

```typescript
transpose = <T>(table: T[][]): T[][] => {
    return table
        .sort((a, b) => b.length - a.length)[0]
        .map((_, idx) => table.map(row => row[idx]))
        .map(row => row.filter(v => v));
}

```

via https://qiita.com/kznr_luk/items/790f1b154d1b6d4de398