OmniAICreator/Qiita-1.07M huggingface dataset:
05Arduinoでシリアル通信を簡単にしてみる

Arduinoを使うととても簡単にシリアル通信が出来ます。
シリアル通信に関しては以下のサイトで詳しくまとめられていますので、ありがたく紹介させていただきます。
　[電子工作初心者が シリアル通信方式を分かりやすくまとめてみた](https://qiita.com/Gri_Gra/items/b6f901b35d3917ffc580)

##シリアル通信の準備
Arduinoとpcとの接続については、特別なケーブルなどを用意しなくても大丈夫です。
プログラム書き込みに使用しているCOMポートをそのまま利用できます。

また、ArduinoIDEにはちゃんとシリアルモニターの機能もあるのでPC側のソフトも特別に用意しなくて済みます。

では、簡単なプログラムです。

##シリアル通信の初期化と文字列の送信
シリアル通信を行うときはvoid setup() に Serial.begin(9600);を書きます。
引数は通信ボーレートと言って、通信速度の単位［bps］（bit/sec）です。この値をPC側の設定と合わせないとタイミングが合わず、通信できません。

```cpp:robot19
void setup() 
{ 
   Serial.begin(9600);
   delay(300);

   Serial.print("MOTOR MODE");       // 文字列を表示
  　Serial.print("\n");              // 改行を表示
} 
```
 Serial.print("MOTOR MODE");は"　"間の文字列を送信しています。文字列はASCIIコードです。
Serial.print("\n");は\nという改行文字を送信しています。、
また、Serial.println("MOTOR MODE"); とすると、改行も行います。
##シリアル通信のモニタ
プログラムを書き込み終わると直ちに通信が始まります。
IDEのシリアルモニタを起動します。
![シリアル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/6c7c8738-e574-5a05-24c1-837665ca4837.png)

シリアルモニタで確認すると
![シリアル２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/355420/304051fb-780c-a1e6-1c72-e8c94646ee5e.png)


 Serial.print("MOTOR MODE"); で送った文字列が表示されました。
ローカルホストを外部公開,ベーシック認証もかけられるツール「ngrok」

開発中のページを一瞬人に見せたいとき、重宝するお。
## 確認環境
Mac OS 10.14.4
iTerm2

## 導入方法
1. 公式サイトにログイン
https://ngrok.com/
Google or Github アカウントが使える

2. 公式サイトの手順通りに進める。
![スクリーンショット 2019-04-17 19.27.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235781/f02c759b-dd48-b020-2548-11a4c0f7668f.png)

	1. ダウンロード
	2. 解凍
	3. アカウントとの紐づけ（サイト上で提示されるコマンドをそのまま打てばおけ


3. 解凍してできたファイルを `Macintosh HD/usr/local/bin`に置く。（どのディレクトリからコマンドを叩いても動くように（別の方法あったら求む

4. コマンドを叩く

```bash:
$ ngrok http 3000
```

3000がポート番号。
なぜかhttpじゃないと動作しない…httpsはだめ？

以下のようにhttpとhttpsのリンクが生成される。

<img width="581" alt="スクリーンショット 2019-04-17 19.38.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235781/959679ec-84a7-168e-89b8-b94057aa174c.png">


## ベーシック認証のかけかた
以下のようにコマンドを叩く。

```bash
$ ngrok http -auth='user:pass' 3000
```
user がユーザー名、 passがパスワード。
任意の文字列を指定可能。


## 参考
1. [ngrokが便利すぎる - Qiita](https://qiita.com/mininobu/items/b45dbc70faedf30f484e)
2. [https://parashuto.com/rriver/tools/secure-tunneling-service-ngrok](https://parashuto.com/rriver/tools/secure-tunneling-service-ngrok) 
※2では無料でサブドメインをつけられるような言い方をしているが、コマンドを叩くとフリープランなのでダメですよ〜と言われる、注意。
【Unity】Zバッファとレンダリング順の仕組み

## 概要
3DCGで透明なオブジェクトを扱う上で抑えておきたいトピックです。
レンダリングの基礎。

## 透明なメッシュのレンダリング順
![MakotoNoMegane.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/dc45c520-aa85-2a9c-00ee-f9968afd63c2.gif)

このシーンは 赤・青・透明 の３種類のメッシュで構成されています。
しかし、透明なメッシュを青いメッシュより手前に描画しているにもかかわらず、透明なメッシュの後ろに青いメッシュが描画されてません。何故でしょうか？

## CGで奥行きを認識する仕組み
![Zバッファ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/866e4fda-0a21-ac57-6bbb-1fc4bb93c65d.png)
CGでは、オブジェクトの奥行きに関する位置を**Zバッファ(または深度バッファ)**という方法で管理しています。
これはオブジェクトをレンダリングした時に、レンダリング結果とは別にオブジェクトの位置(深度情報)も保存しておきます。
再びスクリーンの同じ個所をレンダリングする時、今からレンダリングするオブジェクトと、前にレンダリングしたオブジェクトの深度を比較して、今からレンダリングオブジェクトが奥であるのならレンダリングをスキップします。
この工程をZテスト(または深度テスト)といいます。
この仕組みによって、オブジェクトの前後関係が正しいレンダリング結果を得る事ができます。

<a target=”_blank” href="https://ja.wikipedia.org/wiki/Z%E3%83%90%E3%83%83%E3%83%95%E3%82%A1">Zバッファ - Wikipedia</a>

## 半透明の場合どうなるか？
<a target=”_blank” href="https://youtu.be/wUx_Y9BgC7k?t=945">Unity道場 2019.2 シェーダを書けるプログラマになろう #1 シェーダを理解しよう</a>
上記動画の**15:45～の解説**が分かりやすいです。（そこから再生します）

端的に言うと…
**不透明のオブジェクトしか存在しないの場合、**Zブァッファの前後関係を比較すれば絵に矛盾は起きません。
しかし、半透明のオブジェクトが混ざってしまうと…**半透明のオブジェクトの奥に、不透明のオブジェクトを描画してほしいのに、Zバッファは不透明のオブジェクトが奥になるので描画されない**という事が起こりえるのです。

そのため、**半透明のオブジェクトと不透明のオブジェクトはそれぞれ分けて管理して、不透明のものを全てレンダリングしてから半透明のものをレンダリングすると順番が決まっており、**正しく表示できるわけです。
では、改めて先ほどのプロジェクトを見てみましょう。

![RenderQueue.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149449/a34df516-afe4-1455-24f6-fe328bfd0415.png)

RenderQueueの値が若い順にレンダリングされるので、
「2000のred → 2001のMegane → 2002のBlue」の順番でレンダリングされることになります。
そのため、青をレンダリングする時に既にMeganeのZバッファがあるので…Meganeの部分だけBlueがレンダリングされずに、透過して見えてしまう。という仕組みなんですね。
これは、Zバッファの学習用にレンダリング順を変更したプロジェクトなわけです。

<a target=”_blank” href="https://docs.unity3d.com/ja/2018.2/ScriptReference/Rendering.RenderQueue.html">RenderQueue</a>
Materialのレンダリング順に関する定義

## 透明オブジェクトのシェーダー
```c:MakotoNoMegane.Shader
Shader "Custom/MakotoNoMegane"
{
	Properties
	{
		_LensColor("Color", Color) = (0, 0, 0, 0.1)
	}

	SubShader
	{
		Tags
		{
			"RenderType" = "Transparent"
			"Queue" = "Geometry+1"
		}
		LOD 100
		Blend SrcAlpha OneMinusSrcAlpha

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"

			fixed4 _LensColor;

			struct appdata
			{
				float4 vertex : POSITION;
			};

			struct v2f
			{
				float4 vertex : SV_POSITION;
			};

			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				return _LensColor;
			}
			ENDCG
		}
	}
}
```
こちらが、透明オブジェクトのShaderです。色が設定できます。
実際にプロジェクトを再現してみて、よりZバッファとレンダリング順の理解を深めるために、自由にお使いください。
WebpackでUglifyJSPluginを使ってminifyしようとするとUnexpected token: name (Dom7)が出る場合の対処法



# TL;DR 
- Swiperを普通に読み込むとDom7が原因でエラーが出る。
- コンパイルされたes5のファイルを読み込むか、WebpackでDom7をexcludeすることで回避できる。

# 関連パッケージのバージョン
- @babel/core: 7.1.2
- @babel/polyfill: 7.0.0
- @babel/preset-env: 7.1.0
- babel-eslint: 10.0.1
- babel-loader: 8.0.4
- mini-css-extract-plugin: 0.4.5
- swiper: 4.5.0
- uglifyjs-webpack-plugin: 2.0.1
- webpack: 4.25.1
- webpack-cli: 3.1.



# Webpack
```webpack.config.js
const path = require("path"),
  webpack = require("webpack"),
  UglifyJSPlugin = require("uglifyjs-webpack-plugin")
... 
module.exports = (env, argv) => {
  const IS_DEVELOPMENT = argv.mode === "development"

  return {
    entry: ["@babel/polyfill", "./src/js/main.js"],
    output: {
      path: path.join(__dirname, "./dist/"),
      filename: "js/bundle.js"
    },
    devtool: IS_DEVELOPMENT ? "source-map" : "none",
    optimization: {
      minimizer: IS_DEVELOPMENT
        ? []
        : [
            new UglifyJSPlugin({
              uglifyOptions: {
                compress: {
                  drop_console: true
                }
              }
            })
          ]
    },
    ...
    module: {
      rules: [
        {
          test: /\.js$/,
          exclude: /node_modules/,
          use: [
            {
              loader: "babel-loader",
              options: {
                presets: [["@babel/preset-env", { modules: false }]]
              }
            }
          ]
        }
      ]
    }
    ...
  }
}
```

# エラー内容
```bash
ERROR in js/bundle.js from UglifyJs
Unexpected token: name (Dom7) [js/bundle.js:10622,6]
```

# 解決策

## UMD版のみ読み込む
[Swiper](https://github.com/nolimits4web/Swiper)はES6を使用しているため、コンパイルされたES5のUMD版を使用すれば問題ないようで、読み込み方を変えれば問題なくビルドされる。
ただしこの方法だと当然Tree Shakingが使えない。

```js
import Swiper from "swiper/dist/js/swiper.js"
```

## WebpackでDom7をexcludeする
```webpack.config.js
module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /node_modules\/(?!(dom7|swiper)\/).*/,
      use: [
        {
          loader: "babel-loader",
          options: {
            presets: [["@babel/preset-env", { modules: false }]]
          }
        }
      ]
    }
  ]
}
```


```js
import Swiper from "swiper"
```

### Tree Shakingを使いたい場合
`swiper/dist/js/swiper.esm.js`から使いたいものだけimportすれば良い。

[Swiper API#Custom Build](https://idangero.us/swiper/api/#custom-build)

```js
import { Swiper, Navigation, Pagination, Scrollbar } from 'swiper/dist/js/swiper.esm.js'
```

# おまけ
- Tree Shaking適用前: 495 KB
- Tree Shaking適用後: **433 KB**


# 参考
[Webpack Production Bundling fails because of UglifyJS Error with Dom7 #2263](https://github.com/nolimits4web/Swiper/issues/2263#issuecomment-339919428)
Python 3.7.4 からGC対象オブジェクトのメモリ使用量が8バイト増えるかも

x86-64 の ABI では、 int128 や long double 型は 16byte 境界に配置することになっています。

しかし Python がもっている pymalloc 実装は 8 バイト境界のメモリブロックを返すようになっています。。。大丈夫か？
16byte alignment を要求する型が入った構造体を malloc しようとすると 16byte の倍数になるはずなので、malloc(sizoef(構造体)) ならセーフで、 malloc(sizeof(構造体)＋16の倍数じゃないバイト数) みたいなケースでは問題になりそう。

それよりも問題なのがGCヘッダ。64bit環境でのGCヘッダは 24byte です。「ヘッダ」という名前が示すとおり、GC対象オブジェクト（循環参照を構成するかもしれないオブジェクト。tuple,list,dictなど。)の先頭に配置されます。

GC対象オブジェクトを生成するときは、 `malloc(sizeof(GCヘッダ) + オブジェクトサイズ)` のようにメモリ確保してからGCヘッダ分ずらしたアドレスを `PyObject*` 型のポインタに利用します。なので malloc が 16byte 境界アドレスを返しても、 +24byte したアドレスに Python オブジェクトが格納されることになり、そのオブジェクトの構造体に int128 や long double 型があると 16byte 境界をまたぐように配置されてしまいます。

最近のコンパイラは実際に 16byte 境界を前提にした命令を利用するようになっているようで、「理論上は違反しているが実際は問題なく動いている」ではなく「本当にセグフォで落ちる」問題になってしまいました。

最近まで気づかなかったのですが、 Python 2.7 で先にこの現象が報告されていて、 2.7.15 でGCヘッダが 24byte から 32byte に増やされていました。 ([changelog](https://github.com/python/cpython/blob/2.7/Misc/NEWS.d/2.7.15.rst), [commit](https://github.com/python/cpython/commit/0b91f8a668201fc58fa732b8acc496caedfdbae0), [issue](https://bugs.python.org/issue33374))

最近 Python 3.7 でも同様の問題が報告された ([クラッシュのissue](https://bugs.python.org/issue36618), [昔からあったubsanエラーのissue](https://bugs.python.org/issue27987)) ので、ABI互換を破壊しない他の良い方法が見つからない限りは同じ修正を適用するしかなさそうです。 long double とか int128 とかいったレアな型のために、大量にある＆それらの型を絶対に入れることがないタプルのメモリ消費を+8バイトしないといけないのは、ケチな私からすると惜しいです。

ところで、Python 3.8 ではGCヘッダの中身を3ワード(64bit環境で24byte)から2ワード(同16byte)に削って、GC対象オブジェクトstr,bytes,int,floatなどは対象外）のメモリ使用量を8バイト削ることに成功していました。そのためこの問題の影響を受けることなく、余計なパディングは必要ありません。結果的に Python 2.7.15 以降や多分 3.7.4 以降に比べると16byteの削減になります。この改善に成功していて本当に良かった。
IBM Cloud Databases（ICD） で鍵を持ち込んでディスクを暗号化する方法

IBM Cloud Databasesでは通常、ランダムに生成された鍵を使ってディスクが暗号化されていますが、自分で鍵を持ち込んで暗号化することもできます。鍵はKey Protectというサービスで管理します。新規に鍵を生成出来る他、既存の鍵をインポートして利用することが可能です。

Key Protect自体は裏側でHSM（ハードウェア・セキュリティー・モジュール）という非常にセキュリティの高い仕組みで鍵を保管しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/88149fb0-17b9-af47-04db-002b21df1ba5.png)

# Key Protect サービスの生成
IBM CloudのカタログからKey Protectサービスを作成します。地域はどこでも良いですが、後ほどDBをデプロイする予定の地域にしてください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/48cb6853-4c04-bb88-9379-48f1f2631f11.png)

作成できたら、Manageタブへ遷移すると鍵の管理画面が表示されます。ここから鍵を生成、もしくはインポートをします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242688/3c319694-96ae-d968-ce5e-60f02403b032.png)

## 鍵の生成
Add Keyをクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/233a74f6-0d00-f848-ef57-2b5a63e54437.png)

Key Typeは2種類あります。

- ルート鍵 (Root key)
 - ルート鍵は、Key Protectの1次リソースです。 データ・サービス内に保管されている他の鍵をラッピング (暗号まです。Key Protectでルート鍵の作成、保管、およびライフサイクルの管理を行うことができます。これにより、クラウド内に保管された他の鍵を制御できます。 標準鍵とは異なり、ルート鍵はKey Protectサービスから外に出ることはできません。
- 標準鍵 (Standard key)
 - 標準鍵は、パスワードや暗号鍵などの機密事項を永続化する手段です。Key Protectを使って標準鍵を保管すると、機密事項用のハードウェア・セキュリティー・モジュール (HSM) ストレージ、Cloud Identity and Access Management (IAM) を使用したリソースへのきめ細かいアクセス制御、および Activity Tracker を使用したサービスへの API 呼び出しの監査機能が使用可能になります。

ICDの暗号鍵にはルート鍵を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/f9e29405-b7d0-1b08-086d-dcdc9991d8ab.png)

鍵の生成ができました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/c4db4bf5-c604-794a-4504-36aa913d38a1.png)


## サービス認証
ICDがKey Protectを使えるようにするために、アクセス権を付与します。

上部のメニューから「Access(IAM)」 → 「Authorizations」 → 「Create」 で新規にアクセス権を作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/19cd90f1-f18a-38aa-bb6f-81dd2f6f6b46.png)

アクセスを許可するサービスを指定します。Source ServiceにはICDのサービスを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/5c4e7a16-7e14-4794-9798-9468f34a9b84.png)

付与する役割はReaderを選択します。（というかそれしか選べない）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/ec250f28-1ffa-3353-b770-be0d3864a12a.png)

権限付与ができました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/194840de-e648-583f-3d1c-3ab1bcaf1db7.png)

# ICD（Databases for PostgreSQL） インスタンスの作成
カタログからICDサービス（今回は[Databases for PostgreSQL](https://cloud.ibm.com/catalog/services/databases-for-postgresql)）を選択します。

ディスクの暗号化に使う鍵を選べるようになっているので、鍵を保管しているKey Protectのインスタンスを選択します。DBをデプロイする地域とKey Protectのリージョンがと同じ時しかインスタンスが選べないので注意してください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/7db96b63-269a-e613-3216-6a0679c06346.png)

インスタンスを選択すると、サービスが管理している鍵が表示されます（図右側）。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/2097d592-f0d0-fadc-8246-b050ea885a3f.png)

プロビジョンが完了し、DBのサービス詳細画面を見てみると
![image.png](https://qiita-image-store.s3.amazonaws.com/0/242688/3a06566f-ffe1-0c14-130b-9f30e98da5b7.png)

先ほど指定した鍵で暗号化されていることがわかります。
容量不足でもinode数の枯渇でもないのに No space left on device のエラーが出た [ext4]

# 結論
- `ext4`の`dir_index`のhashの衝突が原因のようである。
- 解決方法はいくつか見つかったが、良い解決法は見つからなかった。
- ディレクトリを分けることで対応することにした。

# 状況
同じフォルダに大量にファイルを生成している途中で(1505406ファイル目で発生)`No space left on device`のエラーが出ました。
調べたところ、ストレージの容量不足でもinode数の枯渇でもなさそうです。

# 環境
OS：Ubuntu 16.04.6 LTS
ファイルシステム：ext4

# ストレージの残量とinode数の確認
まずは`No space left on device`の原因の多くであるストレージの容量不足かどうか、inode数が枯渇しているかどうかを調べました。

ストレージの残量は`df`、inodeは`df -i`で調べられます。
結果はどちらも該当していませんでした。


# 原因はdir_indexのhashの衝突か？
よく調べると[ext4: Mysterious “No space left on device”-errors](https://blog.merovius.de/2013/10/20/ext4-mysterious-no-space-left-on.html)というサイトに行き着きました。

曰く、`ext4`は`dir_index`のハッシュのメカニズムとして`half_md4`を使っているが、`half_md4`はアルゴリズムは`md4`を使うものの32ビット分しか使用しないため、十分なファイル数があった時は衝突する可能性が高いとのこと。

`dir_index`は`ext3`から導入され、その名の通りインデックスで検索を高速化させるためのものですが、上記サイトによると、インデックスに使うハッシュの衝突が原因の可能性がありそうです。

# dir_indexの調査

まず、`dir_index`が有効化されてるかを調べます。
`df`を打ち、`Filesystem`の行にある調べたいファイルシステム名をメモします。
次に以下を打ち込みます。`YOUR_FILE_SYSTEM_NAME`は先ほど調べたファイルシステム名を入力します。

```sh:dir_indexが有効かの確認
sudo tune2fs -l YOUR_FILE_SYSTEM_NAME| grep -o dir_index
```

実行後に`dir_index`と出てくれば`dir_index`が有効化されていることになります。

# 対策
対策としては以下の三通りを思いつきました。
1. ハッシュのアルゴリズムを変更する
2. `dir_index`を無効化する
3. ディレクトリを分ける

1は[tune2fsのマニュアル](https://manpages.debian.org/stretch/e2fsprogs/tune2fs.8.en.html)を見ると`half_md4`の他に`tea`が選べるようです。
以下で`hash_alg`を変更できますが、先程の[ext4: Mysterious “No space left on device”-errors](https://blog.merovius.de/2013/10/20/ext4-mysterious-no-space-left-on.html)には`tea`に変更してもハッシュの衝突は発生したと書いてあるのであまり期待しないほうが良さそうです。

```sh:hash_algの変更
sudo tune2fs -E "hash_alg=tea" YOUR_FILE_SYSTEM_NAME
```

そもそもパフォーマンスの面で`hash_md4`が選択されており`tea`に変更するとパフォーマンスに影響が出るとも書いてあるので、その面でもしないほうが良さそうです。

2は以下で`dir_index`の無効化ができますがインデックスを無効化するとパフォーマンスに大きく影響が出るのでこれもしないほうが良さそうです。

```sh:dir_indexの無効化
sudo tune2fs -O "^dir_index"
```

3はインデックスはディレクトリ毎に作成されるのでディレクトリを分ければ衝突は回避できますが、分けたディレクトリでまた衝突する可能性はあります。

1,2,3番の対策を考えた結果、迂闊にファイルシステムを変更してパフォーマンスに影響が出ては困るので今回は3のディレクトリを分けて対応することにしました。

# 何か良い解決方法はないものか...
調べてもこれ以上の解決方法は見つかりませんでした。
どなたか良い解決方法をご存知の方いらっしゃいましたらご教授いただけると幸いです。
Android Studioでのエミュレータ(AVD)起動エラーの対処法

#症状
　AVDの起動画面で、起動ボタンを押しても反応がない。
![エミュレータ起動失敗.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400489/dbd5084f-04ec-0708-8b7d-300bd9524072.png)

IDE側に戻るとEvent Logに以下のエラーが出ている。

```EventLog
18:03	Emulator: emulator: ERROR: x86 emulation currently requires hardware acceleration!

18:03	Emulator: Process finished with exit code 1
```

以下の記事の対処を試そうとしたがIntel Hardware Accelerated Execution Manager(以下Intel HAXM)は、「Remove」しか選べない(インストール済み)ので症状が違う模様。

https://www.javadrive.jp/android/emulator/index9.html

記事には「インストールする」とあるが選べない
![Hardware_Accelerated_Executionインストーラ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400489/c254575b-c593-82d9-3dae-9dc493621e46.png)

#解決策
どうやら「BIOS側でIntel HAXMを有効にする」必要があるらしい。

私の環境では「Advanced」→「Intel Vertualization Technology」という項目を「Enabled」にしたところ、エミュレータが起動するようになった。
![bios画面.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400489/bab61f49-3801-0dfe-5a8a-c5e662985665.jpeg)

無事に起動した。
![エミュレータ―.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/400489/bf8b1287-e5af-a0f1-54f1-668b4d2a4b69.png)
SpringBootでのローカルファイルダウンロード覚書

#ファイルダウンロード実装手順

##はじめに
業務のためのメモ代わりの殴り書き。あとできちんとした記事にする。

##ファイルダウンロード

最終的にはControllerから Resouce型のファイルをreturnすればいい
ローカルのファイルをDLさせるのであれば

```AnyController.java
Resource resource = new FileSystemResource("ここにファイルパス");
return resource;
```

##ファイルを任意の名前でダウンロードさせたい

Controllerの引数に HttpServeletResponse response　を追加。
responseのフィールド変数(header)に適切な値をセットする。
return 等はそのままでいい。Spring側がよしなに対応してくれる。

```AnyController.java
// 引数の記述は省略
Resource resource = new FileSystemResource("ここにファイルパス");
response.setHeader("Content-Disposition", "attachment; filename=" + "ここにファイル名");
return resource;
```

##全角文字をファイル名に使いたい

ファイル名をURLエンコードされたものにすればOK

```AnyController.java
// 引数の記述は省略
Resource resource = new FileSystemResource("ここにファイルパス");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("ここにファイル名", "UTF-8"));
return resource;
```
Selenium IDEのTips

この記事は移行しました！[最新の内容はこちら](https://naoqoo2.github.io/blog/Selenium-IDE%E3%81%AETips/)をご覧ください😀

久々に新しくなったSelenium IDEを触りました。
https://github.com/SeleniumHQ/selenium-ide
chromeで使えていい感じですね。まだ試してないですがデフォルトでif文とかもできるようになったそうな。

ここではちょっとしたテクニックを記載します。（随時追加予定）

## コマンド系

### 現在日時を使う

テストデータにユニークな名称を付けたいときや、期間などを扱う時に重宝します。

まず、扱いやすいように日付関数を宣言。

| Command | Target | Value |
|:---|:---|:---|
|execute script|※1をコピペ||

```js:※1
getDateTime = function(format, add_day){if (format == null) format = null;if (add_day == null) add_day = 0;var obj = {};var dt = new Date();dt.setTime(dt.getTime() + add_day * 60*1000*60*24);var week_jp = ['日','月','火','水','木','金','土'];obj.Y = dt.getFullYear();obj.m = ('0'+(dt.getMonth() + 1)).slice(-2);obj.n = dt.getMonth() + 1;obj.d = ('0'+dt.getDate()).slice(-2);obj.j = dt.getDate();obj.H = ('0'+dt.getHours()).slice(-2);obj.G = dt.getHours();obj.i = ('0'+dt.getMinutes()).slice(-2);obj.s = ('0'+dt.getSeconds()).slice(-2);obj.w = dt.getDay();obj.w_jp = week_jp[dt.getDay()];if(format != null){var str = format;str = str.replace('w_jp', obj.w_jp);str = str.replace('Y', obj.Y);str = str.replace('m', obj.m);str = str.replace('n', obj.n);str = str.replace('d', obj.d);str = str.replace('j', obj.j);str = str.replace('H', obj.H);str = str.replace('G', obj.G);str = str.replace('i', obj.i);str = str.replace('s', obj.s);str = str.replace('w', obj.w);return str;}else{return obj;}};
```

用途に応じて様々なフォーマットで。
[JavaScriptで現在日から前後x日を取得する](https://qiita.com/naoqoo2/items/c768c3bae47b28da0125#%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89)のワンライナーなので詳しくはこちらを参照ください。

下記は一例。

| Command | Target | Value |
|:---|:---|:---|
|execute script|return getDateTime('Ymd');|date|
|execute script|return getDateTime('Y/m/d H:i:s');|datetime|

それぞれ`${date}`、`${datetime}`で使えます。

### 属性値を変数に格納する

画面からURLを取得したいときなど。
（別ウィンドウで開く系は操作が難しくなるので、URL取得してopenコマンドで開くをよくやります）

| Command | Target | Value |
|:---|:---|:---|
|store attribute|xpath=//div/div/a@href|url|

### 変数を使う

`${hoge}`の形式で使えます。文字列連結なども不要。

| Command | Target | Value |
|:---|:---|:---|
|open|${url}|
|open|example.com?id=${id}|


## 全般

### プロジェクト保存時はファイル拡張子を「.side」にする

保存しようとするとなぜかデフォルト「.txt」なのですが、このまま保存しても開けないので「.side」に変更しましょう。


### 1つのテストスイートに同じテストケースを複数入れる

UI上からはテストスイートの中に同じテストケースを複数回実行することはできませんが、プロジェクトファイルを直接編集すれば可能です。

```sample.side
  "suites": [{
    ：
    ：
    "tests": ["43a345b3-5cdc-2b31-eb4c-41a345bfd231"]
  }, {

↓ testsを直接増やす

    "tests": ["43a345b3-5cdc-2b31-eb4c-41a345bfd231", "43a345b3-5cdc-2b31-eb4c-41a345bfd231"]

```


同じテストケースを実行したいときなんてあるの？と思うかもしれませんが、例えば下記のようなテストケース★の場合です。

- 在庫の増減（testsuite）
    - 在庫が3であること★
    - 在庫を1減らす
    - 在庫を1増やす
    - 在庫が3であること★

### ダブルクリックした行（コマンド）だけ実行したい

テストケース作るとき確認のため旧SeleniumIDE時代よくやってたのですが、
新になって、できる時とできない時がある。。。なぜ？？
（どなたかご存知の方いましたら教えてください）
PNGからM5Stackで表示できるBitmapのテキストデータに変換するPythonツール

M5Stackを買いました！
どうやら人気らしくネットでの在庫がなくなっているようです。(2019.04現在)
![DSC_1633.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399547/c5c1e951-ac4e-3564-bd71-fc4d73be3983.jpeg)

何をしてよいのか分からなかったのですが、SDカードに入ったjpeg画像は簡単に表示できるということを知って、早速表示してみました。
ArduinoIDEはすでに入っていたので簡単なスケッチを書くだけです。

```C 
void setup(void) {
  M5.begin();
  M5.Lcd.drawJpgFile(SD, "/miku.jpg");
}
```
![DSC_1632.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399547/09d1f7f6-b685-4730-4b28-49da7cf1d04c.jpeg)
コードを書くよりも、16GB以下のマイクロSDカードを部屋で探す方が時間がかかりました(笑)

次はM5.LCD.drawRGBBitmapを使って、ドット絵などの小さい画像を表示させます。
画像を切り替えてアニメーションさせるために、SDカードの画像ファイルではなくプログラム内に画像データとして置きます。
[![M5Stack Animation Test](http://img.youtube.com/vi/WiFNp25VBtM/0.jpg)](https://youtu.be/WiFNp25VBtM)

このときに画像をテキストデータに変換するのですが、適当なツールが見つけられなかったので、簡単なコンバータをPythonで作りました。
ソースコードはこちら。
https://github.com/iikagenlabo/png2img

```
python png2img.py <pngfile>
```
とすると、画面にテキストデータが表示されます。
コピペするかリダイレクトでファイルにしてコードに埋め込んでください。

```C
//  例
const unsigned short img0[] = {
  0x0000,0x0000,0x0000,0x3800,0xD800,0xC800,0xC800,0xC800,
  0xC800,0xC800,0xC800,0xC800,0xC800,0xC800,0xC800,0xC800,
  0xC800,0xC800,0xC800,0xC800,0xC800,0xC800,0xC800,0xC800,
  0xC800,0xC800,0xC800,0xC800,0xC800,0xC800,0xC800,0xC800,
};
```
PCへのOfficeアカウントの追加でエラー(801C0003)が出たときの対処方法

厳密にはプログラミング関係ないけど運用技術なので。

# 問題事象

Windows 10で、職場または学校のアカウントを追加(設定＞アカウント＞職場または学校にアクセスする)しようとするとき、以下のようなメッセージが出ました。

<img width="489" alt="2019-04-16_12h13_37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14499/db4c0c63-f684-e284-96c3-9b9c79317920.png">

なお、使用しているOffice 365は、Office 365 Business Premium(いわゆるひとりOffice)です。

## ググってみると…

ググってみるとAzure Active Directory関連の記事ばっかり出てきて「え、Azure Active Directoryなんか使ってないぞ」と思っていたのですが、Office 365 Businessのアカウント管理は内部的にAzure Active Directoryを使っているため、このエラーが出てきていたようです。

# で、解決策

今回の場合、一人が利用可能なデバイスの数を超えていたのが原因。初期設定で一人が使えるデバイスの数は20個だが、PCを初期化したりPC名を変えたりすると同じPCが複数個認識されてしまう場合がある。

このため、いつのまにかPCを20台管理していることになってしまっていた

１. Office 365の管理センターから、Azure Active Directory管理センターに潜る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14499/d32667ee-8eac-17b6-dd8e-5e719f086ae1.png)

２. お気に入りの下のユーザー＞すべてのユーザー＞トラブルが起きているアカウントの名前＞デバイス から、そのユーザーが利用しているデバイスの一覧を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14499/feda3b38-32d0-808e-8135-e5d4a17e0772.png)

３. 使ってないマシンがあったら削除し、項目数を19台以下にしてから、問題が起こっているPCで再度サインイン

## どれも大事なマシンなので消せないよ！という場合

左ペインにある「デバイスの管理」から「ユーザーごとのデバイスの最大数」をいじることで端末数を増やすこともできる はず。

# これに限った話ではないが…

このような管理画面では大抵PCをマシンにつけた名前で識別することになるので、原則購入したPCには判別しやすい名前をつけておきましょう。

わたしは古今東西天使・悪魔の名前からつけています(実際は女神転生やペルソナシリーズなどATLUSゲームに出てくる天使・悪魔・ペルソナの名前)
ld: library not found for -lgfortran と出た時の対処法(Mac OS Mojave 10.14.3)

##背景

Rで統計用パッケージ([TSSS](https://cran.r-project.org/web/packages/TSSS/index.html))をインストールしようとした時に色々と手間取ったのでその備忘録．

##問題点

RでTSSSをインストールしようとすると

```
> install.packages("TSSS",dependencies=TRUE)
```

`-lgfortran` がないと怒られてしまう

```
ld: library not found for -lgfortran
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [TSSS.so] Error 1
ERROR: compilation failed for package ‘TSSS’
* removing ‘/Library/Frameworks/R.framework/Versions/3.5/Resources/library/TSSS’
* restoring previous ‘/Library/Frameworks/R.framework/Versions/3.5/Resources/library/TSSS’
```

##解決法

`gcc` `gfortran` のver.を落として，シンボリックリンクを作成してあげれば良い

まず `brew` で 'gcc-4.9' をインストールする．

```
brew install gcc@4.9
```

次にシンボリックリンクを作成する．

```
#gccなどのver.を4.9に揃える
ln -fs /usr/local/bin/gcc-4.9 /usr/local/bin/gcc
ln -fs /usr/local/bin/g++-4.9 /usr/local/bin/g++
ln -fs /usr/local/bin/gfortran-4.9 /usr/local/bin/gfortran

#lgfortranを使えるようにする．
ln -fs /usr/local/lib/gcc/4.9/libgfortran.dylib /usr/local/lib/libgfortran.dylib
ln -fs /usr/local/lib/gcc/4.9/libgfortran.a /usr/local/lib/libgfortran.a
ln -fs /usr/local/lib/gcc/4.9/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib
ln -fs /usr/local/lib/gcc/4.9/libgfortran.spec /usr/local/lib/libgfortran.spec

#TSSSのインストールしようとしたらld: library not found for -lquadmathとも怒られたのでシンボリックリンク作成．
ln -fs /usr/local/lib/gcc/4.9/libquadmath.0.dylib /usr/local/lib/libquadmath.0.dylib
ln -fs /usr/local/lib/gcc/4.9/libquadmath.a /usr/local/lib/libquadmath.a
ln -fs /usr/local/lib/gcc/4.9/libquadmath.dylib /usr/local/lib/libquadmath.dylib
```

##結果

```
installing to /Library/Frameworks/R.framework/Versions/3.5/Resources/library/TSSS/libs
** R
** data
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (TSSS)
```

やったねヽ(・∀・)ノ
CoreUIを既存のNuxtプロジェクトに導入したメモ

# 前提条件
npx create-nuxt-app
で既に作成されたnuxtプロジェクトがありました。
一部、ディレクトリ構成などがカスタマイズされており、
新規プロジェクトとして作成することが難しかった。

# STEP0 準備 テンポラリのプロジェクトを作成
https://github.com/muhibbudins/nuxt-coreui
ここからソースを取得する。

vue-cliが必要なのでインストールしておく。

```
yarn global add @vue/cli
```

nuxt-coreuiインストール

``` bash
vue init muhibbudins/nuxt-coreui my-project 
yarn install
yarn dev
```

localhost:3000にアクセスし確認する。

# STEP1 必要なモジュールを取得する。
既存のpackage.jsonとインストールしたnuxt-coreuiのpackage.jsonを比較する。

```json
  "dependencies": {
    "@nuxtjs/style-resources": "^0.1.1",
    "chart.js": "^2.7.1",
    "flag-icon-css": "^2.9.0",
    "font-awesome": "^4.7.0",
    "simple-line-icons": "^2.4.1",
    "vue-chartjs": "^3.1.1"
  },
```
この辺りが不足していた
node-sass, sass-loader, boorstrap-vueは既存プロジェクトに入っていた
chart系は今回利用しないので、それ以外をpackage.jsonに追記

```
yarn install
```

# STEP2 コンポーネント、SCSSのコピー
インストールしたnuxtーcoreuiプロジェクトのcomponentsのcharts以外のファイルとディレクトリを
既存のプロジェクトのcomponentsの中にコピーする。

インストールしたnuxtーcoreuiプロジェクトのassetsのファイルとディレクトリを
既存のプロジェクトのassetsの中にコピーする。

同様に進めるが、layouts, pages, staticはdefault.vueなど既存のファイルと名前が衝突しがちなので気をつける。
衝突したらdefault-coreui.vueなどと変更して保存しておく。


# STEP3 設定の変更
cssのビルドが通るように nuxt.config.jsを変更する。

```js
  css: [
    /* Import Font Awesome Icons Set */
    '~/node_modules/flag-icon-css/css/flag-icon.min.css',
    /* Import Font Awesome Icons Set */
    '~/node_modules/font-awesome/css/font-awesome.min.css',
    /* Import Simple Line Icons Set */
    '~/node_modules/simple-line-icons/css/simple-line-icons.css',
    /* Import Bootstrap Vue Styles */
    '~/node_modules/bootstrap-vue/dist/bootstrap-vue.css',
    /* Import Core SCSS */
    { src: '~/assets/scss/style.scss', lang: 'scss' }
  ],
```

これで yarn devし、localhost:3000/register などを見てみる。
うまく表示されていたら、既存のページにcore-uiのコンポーネントをimportして利用することが可能。
ROSでのpythonのプログラムからロボットのゴールを指定する。

# はじめに
rosで目的地まで自律移動させる際に使っているrvizの「2D Nav Goal」をプログラム上から指定することを目的としています。個人的にpythonで処理をしてから目的地の決定をしたいと思ったのでpythonでやる方法を調査しました。

# コード
以下ソースコードです。

```python:sample.py
#!/usr/bin/env python

import rospy
import actionlib
import tf
from nav_msgs.msg import Odometry
import math
from move_base_msgs.msg import MoveBaseAction, MoveBaseGoal

def goal_pose(pose):
    goal_pose = MoveBaseGoal()
    goal_pose.target_pose.header.frame_id = 'map'
    goal_pose.target_pose.pose.position.x = pose[0][0]
    goal_pose.target_pose.pose.position.y = pose[0][1]
    goal_pose.target_pose.pose.position.z = pose[0][2]
    goal_pose.target_pose.pose.orientation.x = pose[1][0]
    goal_pose.target_pose.pose.orientation.y = pose[1][1]
    goal_pose.target_pose.pose.orientation.z = pose[1][2]
    goal_pose.target_pose.pose.orientation.w = pose[1][3]

    return goal_pose


if __name__ == '__main__':
    rospy.init_node('patrol')
    listener = tf.TransformListener()

    client = actionlib.SimpleActionClient('move_base', MoveBaseAction)
    client.wait_for_server()
    listener.waitForTransform("map", "base_link", rospy.Time(), rospy.Duration(4.0))

    pose = [(-24.1430511475,-1.39947879314,0.0),(0.0,0.0,0.712479235583,0.701693194255)]
    goal = goal_pose(pose)
    client.send_goal(goal)

```


# 参考
https://github.com/HotBlackRobotics/hotblackrobotics.github.io/blob/master/en/blog/_posts/2018-01-29-action-client-py.md
https://hotblackrobotics.github.io/en/blog/2018/01/29/action-client-py/
https://www.robotech-note.com/entry/2018/04/16/080816
本番API server に graphql を段階導入

[@_nishisuke](https://twitter.com/_nishisuke) です！

フリーランスやってます！

ある案件で本番iosのAPI serverとして既に動いてる rails にgraphqlを導入しました。

(この案件では実装の全権限をもらってます。)

いきなりclient側の実装を変えるのは変更が大きすぎると判断しました。

第一段階としてサーバーのシリアライザーレイヤーだけをgraphqlに置き換えようとしました。

api serverはrequest specが書いてあり、json-schemaによりresponse jsonが担保されています。

https://github.com/ruby-json-schema/json-schema

一部の読み込みqueryだけをターゲットにし書き込み処理は最初のスコープに入れませんでした。

## rails で graphql

https://qiita.com/nishisuke/items/c4f6065b069b2c1f3083

## install
```
gem 'graphql'
```

## before

```app/controllers/users_controller.rb
class UsersController < ApplicationController
  def index
    user = User.where(適当なコンディション).includes(適当なアソシエーション)
    render json: UserSerializer(user)
  end
end
```

## after

```app/controllers/users_controller.rb
class UsersController < ApplicationController
  USER_SCHEMA = <<~USER_SCHEMA
    {
      users { name }
    }
  USER_SCHEMA

  def index
    gql_res = MyApplicationSchema.execute(USER_SCHEMA).to_h

    raise SomeError unless gql_res['errors'].nil?

    render json: gql_res.to_json
  end
end
```

## 結果
serializer layerだけ変えたかったが、controllerも変更を余儀なくされました。
MVC -> M + graphql
のイメージです。

## gemの注意点
- graphql-rubyのqueryはdefaultでcamelcase
- graphql-rubyは200 statusでerror jsonを返そうとする

## 所感

思ったより簡単にできた。
実態と実装の構造が近くなって、変更を加えるのが容易になった。
ContainerRegistry(GCR)に登録されたDockerイメージをGCE上で動かす

#ContainerRegistryに登録したDockerイメージをGCE上で動かしたい！
※以前書いた下記記事の続きです

・ローカルからContainerRegistry(GCR)にDockerイメージをpushする
https://qiita.com/issei_0403/items/c27b2c30adf0455a6218

・werckerのdocker-pushでDockerイメージをContainer Registry(GCR)に登録する
https://qiita.com/issei_0403/items/d2197a7756cbd1de5b49


####............ContainerRegistry（GCR）に登録されているDockerイメージをGCEに乗っけてJavaのバッチ処理を動かしたいです！！！！！！！
というわけで本題に入ります。

#GCEインスタンス作成
何はともあれインスタンスを作りましょう。
『このVMインスタンスにコンテナイメージをデプロイする。』にチェックをつけ、ブートディスクの種類はContainer-Optimized OSを選択します。
![スクリーンショット 2019-04-17 17.55.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262530/0f8f641f-564c-88cc-7a63-6b2cdd73077d.png)

コンテナイメージについては、GCRの画面上で確認して入力してください。『gcr.io/【プロジェクトID】/イメージ名』って感じです。
![スクリーンショット 2019-04-17 18.06.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262530/6232b46d-0596-13ab-835d-e340ac19873f.png)

サービスアカウントについては、本インスタンスから他サービスに対する権限がないとダメなので、適宜設定してください。私の場合DB接続したりするので、下記の通り設定しました。
![スクリーンショット 2019-04-17 18.36.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262530/bb4e8d08-82fe-ce57-84cb-ff0a27323ca0.png)

#cloud-initの設定
GCEインスタンス上にのせたDockerコンテナがどういう挙動をするかをここで設定します。
![スクリーンショット 2019-04-17 18.12.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262530/db96a9e3-5986-0322-a0be-6e212bc622b2.png)

key、valueの組み合わせで設定します。
具体的には、、、
######google-logging-enabled

```
true
```

######user-data

```
#cloud-config
users:
- name: cos-user

runcmd:
- sudo usermod -aG docker cos-user
- sudo -u cos-user docker-credential-gcr configure-docker
- sudo -u cos-user docker run -it gcr.io/【プロジェクトID】/【イメージ】 > /var/log/cloud-init.log
- shutdown -h now
```

######gce-container-declaration

```spec:
  containers:
    - name: 【イメージ】
      image: gcr.io/【プロジェクトID】/【イメージ】
      stdin: false
      tty: false
  restartPolicy: Never

# This container declaration format is not public API and may change without notice. Please
# use gcloud command-line tool or Google Cloud Console to run Containers on Google Compute Engine.
```

※今回は一度切り動いてくれればいいbatch的な処理なので、restartPolicy: Neverとしています。Alwaysにすると、Dockerコンテナのプロセスが終了→起動を繰り返すような動きになります。

インスタンスが作成されると、一覧に表示されます。
![スクリーンショット 2019-04-17 18.08.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262530/55a1bc18-5e73-6959-14c7-b609749ddae8.png)

#ほんとに動いてるか確認する
インスタンス一覧のSSHをクリックしてインスタンス内に入ります。

```
$docker ps -a
```
でcontainer idを確認して、

```
$docker logs 【container id】
```
でログが見れるはずです。
また、/var/log/cloud-init.logにログを出力するよう設定しているので、
インスタンス一覧の右側にあるボタン→ログを表示でstack driverでも確認できます。

![スクリーンショット 2019-04-17 18.24.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262530/784f5c7f-1976-dfb3-1da5-502127f4f7b6.png)
【VisualStudio】VisualStudioでワイルドカード検索

検索と置換の
検索オプションで「正規表現を使用する」にチェック入れる

ワイルドカード検索

```:検索する文字列
<summary>.*</summary>
```

ワイルドカード部分の文字を残して置換したい場合

```:検索する文字列
<summary>(.*)</summary>
```

```:置換後の文字列
<remarks>$1</remarks>
```

上記の場合だと

```:
<summary>サンプル</summary>
```

のような記載が

```:
<remarks>サンプル</remarks>
```

に置換されます
Windowsでネットワークのポートを使っているプログラムを特定して始末するまでをコマンドプロンプト上で行う


Powershellに馴染めない者です。


### netstatでプログラムのプロセスIDとネットワークのポートの利用状況を確認する

Windowsにもnetstatがあり、似ているオプションがある。（Linuxでは`netstat -naop`とすると同等な情報が得られる。）

`-a`で全部の接続が分かる。
`-o`でプロセスIDが見れる。
`-n`を付けると逆引きがなくなり早く表示できる。

>netstat -nao

```
アクティブな接続

  プロトコル  ローカル アドレス      外部アドレス           状態            PID
  TCP         0.0.0.0:135            0.0.0.0:0              LISTENING       1044
  TCP         0.0.0.0:445            0.0.0.0:0              LISTENING       4
  TCP         0.0.0.0:5040           0.0.0.0:0              LISTENING       9512
  TCP         0.0.0.0:5357           0.0.0.0:0              LISTENING       4
  TCP         0.0.0.0:9000           0.0.0.0:0              LISTENING       14832
  TCP         0.0.0.0:49664          0.0.0.0:0              LISTENING       700
  TCP         0.0.0.0:49665          0.0.0.0:0              LISTENING       1848
  TCP         0.0.0.0:49666          0.0.0.0:0              LISTENING       2096
```

多すぎるのでfindで絞る。

WindowsのfindはLinuxのgrepみたいな動作をするが、検索文字列にダブルクォートが必要なのと、パターンは使えない。

```
>netstat -nao | find "9000"
  TCP         0.0.0.0:9000           0.0.0.0:0              LISTENING       14832
  TCP         [::]:9000              [::]:0                 LISTENING       14832
```

### tasklistでどんな実行ファイルか確認する

tasklistでざっくり取れる。ここでもfindで絞ると良いです。

```
>tasklist | find "14832"
minio.exe                    14832 Console                    1     21,200 K
```


### taskkillで終了させる

taskkillでプロセスを終了させることが出来る。
`/F`を付けると強制終了で、これが無いとなかなかコロコロできない事が多い。

```
taskkill /PID 14832 /F
```

なお、minio君に罪はないです。
51歳からのﾌﾟﾛｸﾞﾗﾐﾝｸﾞ　備忘　laravelで複数モデルを変数に格納して操作してみたい

**認証されたuserのIDに対応する、他の従テーブルのフィールド情報を取得したい**
--
・　複数の従テーブル名を、
　　`laravel\config\model_name.php`に、配列`model_name`で用意。
　　`model_name=>['user_info','user_profile,'company','etc']`

・　foreachで従テーブル名を取り出し、`App\\'.$value`で成形して変数`$model_field`に格納

```php:app\Http\Controllers\Controller
public function getTest()
{
$user=Auth::user();
$model_name=config('model_name.model_name');
foreach($model_name as $value)
{
$model_app='App\\'.$value;
$model_field=$model_app::where('user_id',$user->id)->first();
}
```
TD_TIME_PARSEについて

https://support.treasuredata.com/hc/en-us/articles/360001450828-Supported-Presto-UDFs#TD_TIME_PARSE
prestoエンジンでサポートされているTD関数について。(部分意訳・要約)

## TD_TIME_PARSEとは
タイムストリングをUNIXタイムスタンプに変換するもの

## 利用背景
大量データ前提のDBに対して時間を指定しないと、クエリの実行に時間がかかる
where条件にtimeカラムで特定日時を指定する時などに使用

## 構文
```
long TD_TIME_PARSE(string time
                   [, string default_timezone = 'UTC'])
``` 

### 例
```
# 28日前の月初を指定
WHERE time = TD_TIME_PARSE(TD_TIME_FORMAT(TD_TIME_ADD(UNIX_TIMESTAMP(), '-28d'), 'yyyy-MM-01'))
```

## ポイント
タイムストリング形式は複数パターンで指定可能

```
文字列のyyyy-MM-dd
文字列のyyyy/mm/dd HH:mm:ss
文字列のタイムスタンプ
文字列のタイムスタンプとタイムゾーン
```

## 雑感
この指定では1ヶ月前の月初という仕様を実行日によっては満たせない
herokuのsendgridでエラー

# herokuとsendgridのエラー
herokuを使っていてaddonとしてsendgridを追加したのですがAPIを設定してもメールが飛ばず、、、、。
管理画面にログインするとエラーが出てました。

<img width="1268" alt="スクリーンショット 2019-04-16 19.37.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145608/357877a1-fcad-c088-31c0-66ec43fcf498.png">
赤字の部分でしかもそこがという、、、、。
文字が見えません。下記のようなエラーが出ていました。

```
Your account has been suspended. Please contact Support to regain access. 
```
あなたのアカウントは使用できなくなっているのでサポートに連絡するようにとのことです。特に何か設定したというわけでもなく？？？となります。ネットの情報によるとサポートに連絡するとなおるとのことですがここからもわかりにくい、、、、。

# サポートへの連絡
隠れてしまっている上の青いボタンを押してコンタクトセンターへアクセスします。
<img width="1260" alt="スクリーンショット 2019-04-17 17.52.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145608/7fcaf7ef-0199-bd1c-42ef-4b290755121b.png">
左のコンタクトサポートをクリックします。

<img width="1235" alt="スクリーンショット 2019-04-17 17.55.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145608/0993d196-b93e-0cff-b527-d9f40a8e13a5.png">

次の画面で検索項目が出てきますが下の方に行くとコンタクトボタンが出てきます。
open a support requestボタンを押します。

<img width="1244" alt="スクリーンショット 2019-04-17 17.55.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145608/11530d35-cdec-0079-f321-45c06139a611.png">
このフォームに各種項目を埋めてsubmitをします。

自分の場合はだいたい２〜3時間でアカウントが有効になりました。
JenkinsからGithubに自動コミットさせるためにやること

備忘です

JenkinsからGithubに自動コミットさせるためにやること

## 作業

1. githubに鍵でログインできるようにする
2. Jenkinsにプラグイン入れる
    - "git branch"
    - "sshagent"
3. groovy書く


## 注意点

* sshの秘密鍵をjenkinsに登録するときは、最後に改行が必要
    - [ssh-agent/ssh-credentials-plugin failing because ssh-add expects a newline in the keyfile](https://issues.jenkins-ci.org/browse/JENKINS-50181)

* パスフレーズが必要。sshagent のプラグインが対応していないっぽい。(おそらく)


## サンプルソース

* 以下のバージョンで実施
```

```
SSH Agent Plugin : 1.17
SSH Credentials Plugin : 1.15
Git plugin : 3.9.3
```

* cloneは以下の感じ
    - cloneはsshでやる
    - その際は httpsではないので気を付ける

```
stage('GitClone') {
  steps {
    git_url = "git@github.com:xxxxxx/xxxxxxxxxxxxxx.git"
    git branch: "develop", credentialsId: "xxxx-github-key", url: "${git_url}"
  }
}
```

* push は以下の感じ
    - sshagentでpushする必要アリ

```
stage('GitPush') {
  steps {
    sshagent (credentials: ['xxxx-github-key']) {
        sh('git push origin develop')
    }
  }
}
```
koaでサーバ開発クイックスタート

Node.js の lightweight web framework の一つに [koa](https://github.com/koajs/koa) というフレームワークがあります。
koa でサーバを開発するときの(私がよく使う)主要なライブラリと使い方を軽くまとめました。

## 目次
- koa
- @koa/router
- koa-static
- @koa/cors
- koa-bodyparser

## [koa](https://github.com/koajs/koa)
koa 本体です。執筆時点でバージョン `2.7.0` です。

### Install
``` sh
npm i koa
```

### Usage
``` js
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {
  ctx.body = 'hello';
});
app.listen(3000); // port 3000 でリッスン開始
```

## [@koa/router](https://www.npmjs.com/package/@koa/router)
URL のパスによって処理を分岐させるミドルウェアです。

### Install
``` sh
npm i @koa/router
```

### Usage
``` js
const Koa = require('koa');
const Router = require('@koa/router');
const router = new Router();
router.get('/a', async (ctx, next) => {
  ctx.body = '/a だよ';
});
router.get('/b', async (ctx, next) => {
  ctx.body = '/b だよ';
});
router.get('/b/:id', async (ctx, next) => {
  ctx.body = `/b/${ctx.params.id} だよ`;
});
const app = new Koa();
app
  .use(router.routes())
  .use(router.allowedMethods());
app.listen(3000);
```

## [koa-static](https://github.com/koajs/static)
静的ファイルをホストするミドルウェアです。

### Install
``` sh
npm i koa-static
```

### Usage
``` js
const Koa = require('koa');
const serve = require('koa-static');
const app = new Koa();
app.use(serve('./public')); // 公開したいディレクトリを指定
app.listen(3000);
```

`./public/nice.png` というファイルがあれば `http://localhost:3000/nine.png` で取得できる。

## [@koa/cors](https://github.com/koajs/cors)
CORS (Cross-Origin Resource Sharing) のためのミドルウェアです。

### Install
``` sh
npm i @koa/cors@2
```

### Usage
``` js
const Koa = require('koa');
const cors = require('@koa/cors');
const app = new Koa();
app.use(cors());
app.use(async ctx => {
  ctx.body = 'hello';
});
app.listen(3000);
```

## [koa-bodyparser](https://github.com/koajs/bodyparser)
HTTP リクエストの body をパースするミドルウェアです。
ざっくりいうと、 POST したときのデータを読むために使います。

### Install
``` sh
npm i koa-bodyparser
```

### Usage
``` js
const Koa = require('koa');
const bodyParser = require('koa-bodyparser');
const app = new Koa();
app.use(bodyParser());
app.use(async ctx => {
  const body = ctx.request.body; // パースされたものがここに入る
  ctx.body = body;
});
app.listen(3000);
```

## おわり
増えたら適宜加筆します。

よき koa ライフを。
Stripe ConnectのCustomアカウントで、子アカウントへの入金情報などを取得する方法(アカウントヘッダー)

## Stripe Connectでの子アカウントに関する情報をAPIで取得したい
ドキュメントが少しわかりづらかったので記事を書きました。
プラットフォーム上で子アカウントの情報(例：決済情報、入金情報)を取得し、マイページなどで表示する方法です。
Stripe APIには[アカウントヘッダー](https://stripe.com/docs/connect/authentication#stripe-account-header)という機能があり、APIを呼び出す上で、どのAccountに紐づいた情報を取得するのかを指定できます。このアカウントヘッダーを使用しない場合は、デフォルトで親アカウントが指定されるようです。

```Ruby
  # 例) 子アカウント(ID: acct_xxxxxxxxxx)に対して行われた最新の入金を3件取得する
    Stripe::Payout.list(
      {limit: 3},
      {stripe_account: "acct_xxxxxxxxxx"}
    )
```
このように、第一引数にパラメータ、第二引数にacct_idを指定することで、特定のアカウントに基づいた情報を取得できるようになります。

## 例) ある月の売上の入金額を取得する
私が開発しているCtoCサービスでは、子アカウントの売上の入金スケジュールを月末締め、翌月末払いにしています。そこで欲しい情報は、毎月の入金情報です。
例えば2019年3月に作成された入金情報を取得したい場合は、以下のようにします。

```Ruby
    beginning_of_month = Date.new(2019, 3).to_time.to_i
    end_of_month = Date.new(2019, 3).end_of_month.to_time.to_i

    payout = Stripe::Payout.list(
      {created: {gte: beginning_of_month, lte: end_of_month}}, #gteが以上、lteが以下。日時の範囲指定が独特w
      {stripe_account: "acct_xxxxxxxxxx"}
    )

    # 入金額
    payout.data[0].amount
    # 入金予定日
    Time.at(payout.data[0].arrival_date).strftime("%Y/%m/%d")
```

間違いなどあればご指摘頂けると嬉しいです。
React.useEffectで非同期処理をする場合の注意点2つ（変更あり）

## はじめに

React 16.8から導入されたhooksにはuseEffectがあります。

詳細は[公式サイト](https://ja.reactjs.org/docs/hooks-intro.html)をまず参照しましょう。

useEffectを使うと、コンポーネントのレンダリングとは別に処理を書くことができます。useEffectでしばしば非同期処理を書くことがあります。例えば、サーバからのデータ取得の処理などがあります。

以下では、useEffectで非同期処理を書く場合の注意点を2つ紹介します。ケースによっては注意点はこの2つだけではない可能性が高いので、ご留意ください。

## promiseを返さない

useEffectに渡す関数の戻り値はcleanup関数です。

```javascript
useEffect(() => {
  console.log('side effect!');
  const cleanup = () => {
    console.log('cleanup!');
  };
  return cleanup;
}, []);
```

cleanup関数は次のeffectが呼ばれる前やアンマウントする場合に呼ばれます。(depsが`[]`なのでこの例では後者のみ）

よって、下記は間違いです。

```javascript
useEffect(async () => {
  await new Promise(r => setTimeout(r, 1000));
  console.log('side effect!');
}, []);
```

このコードはcleanup関数の代わりにpromiseを返してしまっています。
正しくは、下記のようにします。

```javascript
const sleep = ms => new Promise(r => setTimeout(r, ms));

useEffect(() => {
  const f = async () => {
    await new Promise(r => setTimeout(r, 1000));
    console.log('side effect!');
  };
  f();
}, []);
```

## ~~アンマウントのフラグを持つ~~

~~非同期処理を書く場合、コンポーネントが削除された後にコールバックが呼ばれる場合があります。この時、コンポーネントのステートを変更しようとするとワーニングがでます。~~

（追記2021/8/20: このワーニングは、今後でなくなります。ワーニングを消す目的でアンマウントのフラグを持つのはそもそも回避策であり、今後はこの対応は非推奨になります。[参考](https://github.com/reactwg/react-18/discussions/82))

```javascript
const [count, setCount] = useState(0);
useEffect(() => {
  const f = async () => {
    await new Promise(r => setTimeout(r, 1000));
    setCount(c => c + 1);
  };
  f();
}, []);
```

~~これを回避するには次のようにアンマウントのフラグを持ちます。~~

```javascript
const [count, setCount] = useState(0);
useEffect(() => {
  let unmounted = false;
  const f = async () => {
    await new Promise(r => setTimeout(r, 1000));
    if (!unmounted) {
      setCount(c => c + 1);
    }
  };
  f();
  const cleanup = () => {
    unmounted = true;
  };
  return cleanup;
}, []);
```

## おわりに

React HooksのuseEffectについて非同期処理を使う場合のよくあるケースの注意点について紹介しました。React Hooksはまだベストプラクティスが溜まっていないため、今後違う方法が主流になる可能性はある点についてはご注意ください。
Javaで新元号試してみた

# Java SE 8 が新元号に対応したらしい

2019年4月17日公開の Java SE 8 Update 211 にて検証。

```java:Sample.java
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("GGGGy年M月d日")
        .withChronology(JapaneseChronology.INSTANCE)
        .withLocale(Locale.JAPAN);

JapaneseDate jd = JapaneseDate.of(2019, 4, 29);

for (int i = 0; i < 5; i++) {
    System.out.println(dtf.format(jd.plus(i, ChronoUnit.DAYS)));
}
```

```:実行結果
平成31年4月29日
平成31年4月30日
令和1年5月1日
令和1年5月2日
令和1年5月3日
```

令和になりました。やりましたね。

# ところで、もうすぐゴールデンウィークですね

元号ばかり気にしていて、新元号の最初の年を「元年」と呼ぶのをすっかり失念していましたよ。トラブルにならないといいですね。

楽しいゴールデンウィークをお過ごしください。

# 一応「元年」も対応してみた

```java:Sample2.java
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
        .appendText(ChronoField.ERA, TextStyle.FULL)
        .appendText(ChronoField.YEAR_OF_ERA, Collections.singletonMap(1L, "元"))
        .appendLiteral("年")
        .appendValue(ChronoField.MONTH_OF_YEAR)
        .appendLiteral("月")
        .appendValue(ChronoField.DAY_OF_MONTH)
        .appendLiteral("日")
        .toFormatter()
        .withChronology(JapaneseChronology.INSTANCE)
        .withLocale(Locale.JAPAN);
```

もういっそ西暦にしませんか？（結論）
タイムラプス動画をffmpegで作る

# TL;DR

* タイムラプス動画（特定の時間間隔で抜き出した画像でつくるコマ落ち動画）を，ffmpegで作る方法を紹介します．
    * ffmpegは，[GPU(NVEnc)対応FFmpegのポータブルなDockerfile](https://qiita.com/myoshimi/items/3309c964594f6b5d32bd)で作ったコンテナベースのコマンドで実行します（GPUが無くても動きます）

# 作成手順

1. 動画を一定時間ごとに切り出した画像群を生成します
1. 画像群を結合して，新しい動画（タイムラプス動画）を作る

# 実行

* サンプル動画は，[Pixabay](https://pixabay.com)の動画を使用しました（Coverr-Free-Footageさん感謝）
    * [人-コマース-ショップ-忙しい-6387](https://pixabay.com/ja/videos/%E4%BA%BA-%E3%82%B3%E3%83%9E%E3%83%BC%E3%82%B9-%E3%82%B7%E3%83%A7%E3%83%83%E3%83%97-%E5%BF%99%E3%81%97%E3%81%84-6387/)の720p(60fps)動画をPeople6387.mp4としてダウンロードしました

## 動画からコマ落とし画像を作成

* 入力動画から，コマ落としした画像群を生成します

```bash
mkdir out
docker run --rm \
    -v ${PWD}:/tmp/ \
    ffmpeg-docker:latest \
    -r 60 -stats -i /tmp/People6387.mp4 \
    -r 15 /tmp/out/out_%04d.png
```

* コマンド説明
    * ```ffmpeg-docker:latest```: [GPU(NVEnc)対応FFmpegのポータブルなDockerfile](https://qiita.com/myoshimi/items/3309c964594f6b5d32bd)で作ったffmpegコンテナ
    * ```-r 60``` : 入力ファイルを60fpsとして扱う
    * ```-r 15 /tmp/out/out_%04d.jpg``` : 
        * 動画から画像を15フレームごとに切り出します
        * 連番ファイル```out_0001.jpg```などの名前で，```out```ディレクトリ以下に出力します
* 実行が完了すると，以下のように多数のコマ落とし画像が生成されます．

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309617/7689f48c-9366-e193-c281-3a3d7d0df8d7.jpeg" width=80%>

## コマ落とし画像を結合してタイムラプス動画を生成

* コマ落とし画像を結合して，タイムラプス動画を生成します
    * 前節からの続きで，outディレクトリに連番ファイルが作成されているものとします

```bash
docker run --rm \
    -v ${PWD}:/tmp/ \
    ffmpeg-docker:latest \
    -i /tmp/out/out_%04d.png \
    -vcodec libx264 -pix_fmt yuv420p \
    -r 60 /tmp/output.mp4
```

* コマンド説明
    * ```-i /tmp/out/out_%04d.png``` : 入力ファイルを60fpsとして扱う
    * ```-r 15 /tmp/out/out_%04d.jpg``` : コマ落とし画像のファイル名パターンを指定
    * ```-vcodec libx264 -pix_fmt yuv420p``` : H.264動画を生成
    * ```-r 60 /tmp/output.mp4``` : output.mp4のファイル名で60fpsの動画を作成
* 実行が完了すると，実行ディレクトリに```output.mp4```が作られています．
    * このoutput.mp4が，元のPeople6387.mp4の動画を4コマ落ちした動画になっています．

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309617/498ded0c-4569-11bd-85df-cbb36b725f2a.gif)

* 上記コマ落ち動画は，[FFmpegで動画をGIFに変換](https://qiita.com/wMETAw/items/fdb754022aec1da88e6e)を参考に，作成したmp4ファイルをアニメーションgifに変換したものです．

# 参考

* [GPU(NVEnc)対応FFmpegのポータブルなDockerfile](https://qiita.com/myoshimi/items/3309c964594f6b5d32bd)
* [Pixabay](https://pixabay.com)
    * [人-コマース-ショップ-忙しい-6387](https://pixabay.com/ja/videos/%E4%BA%BA-%E3%82%B3%E3%83%9E%E3%83%BC%E3%82%B9-%E3%82%B7%E3%83%A7%E3%83%83%E3%83%97-%E5%BF%99%E3%81%97%E3%81%84-6387/)
* [FFmpegで動画をGIFに変換](https://qiita.com/wMETAw/items/fdb754022aec1da88e6e)
レポート内のレイアウトを整える

Cognosのレポートで、リスト表やグラフを複数配置するために、あらかじめ表を配置してサイズを設定することでレイアウトを整えるという方法について手順を紹介します。



①レポートに表を配置する。

レポート編集画面の＋をクリックして、表（テーブル）を選択することもできますし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/84fcbd7f-a168-b232-8ff3-ef3c1430d251.png)

昔ながらのように上のアイコンから作成することもできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/5d803295-ed6a-0f69-7e4a-656c2266702b.png)

配置すると以下のようにデフォルトで横幅が100%となっています。
なお、幅の割合をもう少し狭くしたいと思ったら、テーブル全体を選択した状態のまま、枠をドラッグすることでサイズ変更可能です。（CA11.1からの機能）

横方向
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/af3bba02-6a9a-1a42-4265-91f04e620452.png)
縦方向
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/21ffc8bb-725b-5841-8dfd-9324d76ed221.png)

更に細かなサイズ調整はテーブルのプロパティから設定可能です。
プロパティは、テーブルを選択した状態で右上のプロパティーアイコンをクリックして表示させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/f8869949-f9b7-2e16-b593-353588a22688.png)

プロパティの「位置決め」→「サイズおよびオーバーフロー処理」で行います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/0f2918f0-c56e-b11b-467b-edffcc65cd60.png)


②　テーブルのセル単位で調整して背景色を変えます。

セルを一つ選択した状態で、背景色のアイコンの隣にある↓をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/b1329491-0845-6cf1-ac76-5c200d66a9e7.png)

今回は黄色を選びます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/88378ab7-86d5-deee-6fde-de3052703c0e.png)

セルが黄色に変わりました。セルのプロパティを表示してみると、「色と背景」の背景色も黄色になっていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/16e69999-d6c1-aeac-b741-7e3b410e19cb.png)
黄色いセルだけ幅を変えるので、セルを選択したままプロパティの「サイズおよびオーバーフロー処理」で以下のように指定し、OKボタンで確定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/f6abb187-e400-e3e5-131c-d18bcc5a71ef.png)
指定した通りサイズが変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/3ed64b91-6790-19d6-6d78-7860a6e40a0f.png)

残りのセルの色とサイズをこんな感じに変えてレポートを実行してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/54f56fd1-1b63-b87e-d4fc-d333dd052a79.png)

こんな結果になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/1adbc753-bff5-1bbf-d522-cac675eba4a6.png)

全体の幅100％（デフォルト）はサイズを変更していないのでそのままですが、黄色のセルで幅と高さを変更しているので青色の高さも合わせて変わっています。
また、緑いろのセルと灰色のセルは見えなくなりました。これは、これらのセルに高さが設定されていない（ゼロ）ためです。
残りのセルにも同じ値（幅200px 高さ400px）で設定して実行してみます。

すると画面いっぱいにセルが表示されます。
ブラウザのウインドウ自体を大きくすると、そのサイズに合わせてさらに大きく横幅が変更されてしまいます。これはテーブルの横幅が100％となっているためです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/f9b347bb-f552-e942-79ba-d73fb17ed560.png)


この場合、横幅の指定をブランクにすることで指定したサイズが有効になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/c474d360-a2d1-36b8-af03-d30313af1ac1.png)

今度はブラウザのサイズを変更しても大きさが変わらないと思います。
横幅はデフォルトで入っている値なので、指定したサイズにするには横幅をブランクすればよいということを覚えておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148873/d4fb5adb-dd33-0e79-7d31-c1f74c2e7f5b.png)

また、CA11.1からの新機能のサイズ調整機能でテーブルのサイズを小さくした場合も、テーブル全体の横幅を指定していることになるので、やはりブラウザの大きさに合わせてサイズが変わる動きとなります。

以上