OmniAICreator/Qiita-1.07M huggingface dataset:
with openのファイル操作—「../」

with openのファイル構造、操作がよくわからなかった



sample.pyの場所
　Python → robot → hello →　sample.py

hello.txtの場所
　Python → robot → templates → hello.txt

```sample.py
#クラスの一部コードを記載
 def hello(self):
        with open("../templates/hello.txt", encoding="utf-8") as f:
            t = string.Template(f.read())
            contents = t.substitute(robot_name = self.name)
            print(contents)
            user_name = input()
```

「../」を上手く使えばできる
CesiumでSRTMの地形データを読み込ませてみる

## 概要

[SENSYN Robotics(センシンロボティクス)](https://www.sensyn-robotics.com/)の深見です。
主にWebアプリを中心に開発担当しており、最近はCesiumを利用したWebGL系の開発に関わっております。
本日は、その過程で得た、地形データをCesium上に反映させる方法につきまして紹介いたします。
[Cesiumについてはこちら](https://cesium.com/)

## Cesiumに反映する地形データの取得

 - Cesium上で地形データを反映させるためにはいくつか手段はありますが、ここでは[Cesium World Terrain ](https://cesium.com/content/#cesium-world-terrain)と同じく`quantized mesh`で配信する事例とします。
 - 今回利用する地形データは[Nasa SRTM](https://e4ftl01.cr.usgs.gov/MEASURES/SRTMGL3.003/2000.02.11/)(height map)を利用します。
   - 地形データをダウンロード時には認証が求めらるので、[こちら](https://urs.earthdata.nasa.gov/users/new)でログインIDを取得する必要があります。
   - また、データ量が多いため、今回の対象は関東エリア周辺(N35E139.hgt)のみといたします。

## Cesium Terrain Builder
 - Cesium向けにterrainを生成するため[cesium-terrain-builder](https://github.com/tum-gis/cesium-terrain-builder-docker)を利用します。

## 地形データの作成
- cesium-terrain-builderを利用するため、docker imageを取得します。

```shell
$docker pull tumgis/ctb-quantized-mesh
```

- 事前にダウンロードしたheight map(N35E139.hgt)を配置します。

```shell
$ mkdir ~/terrain
$ mv ~/Downloads/N35E139.hgt ~/terrain
```
- dockerコンテナを起動します。

```shell
$ docker run -it --name ctb -v ~/terrain/:/data  tumgis/ctb-quantized-mesh
```

- gdalbuilderで仮想的なレイヤを定義するXMLファイル(vrt)を作成します。また、Cesium上では地形データをquantized meshで展開するため、ファイルを作成します。

```shell
$ gdalbuildvrt tiles.vrt *.hgt
$ ctb-tile -f Mesh -C -N -o terrain tiles.vrt
```

- Cesiumが地形データを認識するための設定ファイルとして、layer.jsonを作成します。

```shell
$ ctb-tile -f Mesh -C -N -o -l terrain tiles.vrt
```
- 地形データとlayer.jsonが作成されているか下記コマンドで確認します。

```shell
$ tree -v -C -L 1 ~/terrain
terrain/
|-- 0
|-- 1
|-- 2
|-- 3
|-- 4
|-- 5
|-- 6
|-- 7
|-- 8
|-- 9
|-- 10
|-- 11
|-- 12
`-- layer.json
```
以上で地形データの作成は完了です。

## 地形データの配信
- webアクセスできる環境を用意します。配信する際にresponseヘッダーの確認が必要です。配信するサーバの環境に合わせ確認してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431134/14725f83-0117-0a0e-388d-cdac266fa2e2.png)
 - Access-Control-Allow-Origin
     - corsで許可して配信する場合には必要、上記の例は特別な理由がないので`Access-Control-Allow-Origin: *`としています。
 - Content-Encording
     - `ctb-tile`のコマンドで作成された地形データは`gzip形式で圧縮`されているため、配信する場合は`Content-Encording: gzip`を指定します。
 - Content-Type
     - `application/octet-stream`を指定します。cesium-terrain-builderで作成されたファイルが`.terrain`の拡張子ファイルであり、一致するMIMEtypeが存在しないので、`Content-Type: application/octet-stream`とします。
- 今回はpythonのSimpleHTTPServerを利用してweb配信します。

 
```shell
$ python SimpleHTTPServer.py
Serving HTTP on 0.0.0.0 port 8000 ...
```

## Cesiumに地形データを読み込ませる
- CesiumのterrainProvidorにurlを設定します。

```javascript
  const viewer = new Cesium.Viewer('cesium', {
    terrainProvider : new Cesium.CesiumTerrainProvider({
      url : 'http://localhost:8000/terrain'
    }),
  });

```

## ブラウザで確認
- chromeで地データが反映されているか確認します。丹沢のあたりですが、地形データは上手く読み込めてそうです。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431134/5e30cff4-6659-0098-59f3-76e8b87b0adf.png)

- 丹沢付近から御殿場方面にかけて確認してみると、地形データが関東エリア周辺に絞ったため、未反映の部分が目立ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431134/28d64413-f800-74cc-df80-0f99d3d9d498.png)

以上になります。
Railsにマークダウン記法を取り入れる方法

## 結論
1,2,3を導入すればいい

**1.** gem 'redcarpet'

**2.**

```rb
module MarkdownHelper
  def markdown(text)
    options = {
      filter_html:     true,
      hard_wrap:       true,
      space_after_headers: true,
      with_toc_data: true
    }

    extensions = {
      autolink:           true,
      no_intra_emphasis:  true,
      fenced_code_blocks: true,
      tables:             true
    }

    renderer = Redcarpet::Render::HTML.new(options)
    markdown = Redcarpet::Markdown.new(renderer, extensions)
    markdown.render(text).html_safe
  end

end
```
**3 .**

```rb
<%= markdown(@article.body).html_safe %>
```
参考
https://musicamusik.hatenablog.com/entry/2018/06/09/181439

### エラーが出た場合
gemlockを確認するとgem 'redcarpet'がバージョン指定されている可能性があります。自分の場合、gemlockのバージョン指定を削除してbundle updateすることで解決しました。
MIT Open CoursewareのPerformance Engineering of Software Systemsをやっていく（２）

前回に続いて、MIT Open CoursewareのPerformance Engineering of Software Systemsをやっていきます。

https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-172-performance-engineering-of-software-systems-fall-2018/

＃データ型とそのサイズ

Cはたくさんのプリミティブ型をサポートしています。それは以下に示すとおり。

```c
short s;        //shortの符合付き整数
unsigned int i; //基本的な長さの符合なし整数
long l;         //longの長さの整数
long long l;    //特に長い符合付き整数
char c;         //1個のASCII文字(1byte)
float f;        //基本精度浮動小数点
double d;       //倍精度浮動小数点
```
付記：ほとんどの６４ビットマシンやコンパイラにおいて、基本的な精度の値(int,float)は３２ビットです。shortはしばしば16ビットであり、longやdoubleはしばしば６４ビットです。しかしながら、それらの型の精度はCの標準においては弱く定義されていて、マシンやコンパイラによって変わります。紛らわしいことに、時々intやlongは同じ精度です。そして、longとlong longも同じ精度であり、それらは共にiniより長いです。時々、intとlong、long longは同じ意味を持ちます。


使い捨ての変数や、精度内におさまる場合は、常にintを使用してください。この精度は違ったwordサイズにおいても機械の最大のパフォーマンスを発揮するように作られています。もしあなたがビットレベルの操作をしているなら、符合なしデータ型である`uint64_t`（unsigned 64 bit int)を使うのがいいでしょう。そうでないなら、明示的ではなく、intを使うのがいいでしょう。
さらに言うと、あなたが、使っているマシンのアーキテクチャを知っているなら、明示的なデータ型を代わりに使ってコードを書くのがいいでしょう。（以下のように）

```c
#include <stdint.h>

uint64_t unsigned_64_bit_int;
int16_t signed_16_bit_int;
```

もっと複雑なデータ型をプリミティブ型からstructに構成することによって定義できます。例えば、以下のように定義できます。

```c

typedef struct{
   int id;
   int year;
}student;

student you;
// 以下のコードでプロパティにアクセスできます。
you.id = 12345;
you.year = 3;
```

では、以下のコードで、データ型ごとのサイズを測ってみます。

```c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

int main() {

  printf("size of int is %lu\n", sizeof(int));
  printf("size of short is %lu\n", sizeof(short));
  printf("size of long is %lu\n", sizeof(long));
  printf("size of char is %lu\n", sizeof(char));
  printf("size of float is %lu\n", sizeof(float));
  printf("size of double is %lu\n", sizeof(double));
  printf("size of unsigned int is %lu\n", sizeof(unsigned int));
  printf("size of long long is %lu\n", sizeof(long long));
  printf("size of uint8_t is %lu\n", sizeof(uint8_t));
  printf("size of uint32_t is %lu\n", sizeof(uint32_t));
  printf("size of uint64_t is %lu\n", sizeof(uint64_t));
  printf("size of uint_fast8_t is %lu\n", sizeof(uint_fast8_t));
  printf("size of uint_fast16_t is %lu\n", sizeof(uint_fast16_t));
  printf("size of uintmax_t is %lu\n", sizeof(uintmax_t));
  printf("size of intmax_t is %lu\n", sizeof(intmax_t));
  printf("size of __int128 is %lu\n", sizeof(__int128));

  return 0;
}
```

実行結果は以下の通り

```
size of int is 4
size of short is 2
size of long is 8
size of char is 1
size of float is 4
size of double is 8
size of unsigned int is 4
size of long long is 8
size of uint8_t is 1
size of uint32_t is 4
size of uint64_t is 8
size of uint_fast8_t is 1
size of uint_fast16_t is 2
size of uintmax_t is 8
size of intmax_t is 8
size of __int128 is 16
```
dockerでnuxtの開発環境作ってみた


atma株式会社インターン生のizumiです。

advent calendarという折角の機会なので、今までチキってやっていなかったqiitaに初投稿してみます。

似たような記事は沢山あると思いますが、とりあえずアウトプットしてみよう！を個人的な目標に書いていきたいと思います笑

## 概要  
dockerのコンテナ上にnuxtの開発環境を作ります。

必要最小限の環境のため、さくっとwebアプリのフロント側を作ってみたい、vueやnuxtを動かしながら理解したい、という人向けです。

今回はざっくりとした流れだけご紹介していきたいと思います。



## 環境構築の流れ  
1. dockerをインストール  
2. **Dockerfile**を書く
3. **docker-compose.yml**を書く
4. dockerのコンテナ作成&起動
5. コンテナ内部でnuxtの開発環境を立ち上げる  

### dockerをインストール  
まずは[Docker Desktop](https://www.docker.com/products/docker-desktop)をインストールします。
インストールできたら、プロジェクト用のディレクトリを作成してプロジェクトに移動しておきましょう。 
 
```
mkdir sample-app
cd sample-app
```
### Dockerfileを書く  
vscodeなどのコードエディタ上で、次のような`Dockerfile`を作成します。

```Dockerfile:Dockerfile
FROM node:10

ENV APP_ROOT /home/node/app

WORKDIR ${APP_ROOT}
COPY . ${APP_ROOT}

EXPOSE 3000
```

### docker-compose.ymlを書く  
続いて`docker-compose.yml`を作ります。

```:docker-compose.yml
version: '3'
services:
  node-app:
    build: ./
    tty: true
    container_name: "sample-app"
    volumes: 
      - ./:/home/node/app
    environment:
      - NUXT_HOST=0.0.0.0
    ports:
      - "3020:3000"
```
この2つのファイルを用意できれば、dockerの**image**および**container**の作成と起動ができるようになります。  
### dockerのコンテナ作成&起動  
まずはdockerのコンテナを立ち上げてみましょう！

```
docker-compose up -d 
```
コンテナが起動できているかは、次のコマンドで確認できます。

```
docker-compose ps
```
コンテナのStateがUpになっていたら、無事にコンテナの作成と起動ができています ;)

```
   Name               Command            State           Ports         
-----------------------------------------------------------------------
sample-app   docker-entrypoint.sh node   Up      0.0.0.0:3020->3000/tcp
```

### コンテナ内部でnuxtの開発環境を立ち上げる

次にコンテナ内部でnuxtの開発環境を立ち上げていきます。

まずは作ったコンテナに潜り込みます。

```
docker exec -it sample-app sh
```
nuxtにはプロジェクトを簡単に始められる[create nuxt-app](https://ja.nuxtjs.org/guide/installation)という足場ツールが用意されているので、今回はそれを使って、カレントディレクトリ`.`にnuxtプロジェクトを作ります。

```
yarn create nuxt-app .
```
そうするといくつか質問されて、それに答えるだけでプロジェクトの設定ができます。

それが終わったら自動的に`package.json`に基づいてnuxtに必要なパッケージをインストールしてくれるでしょう。

そして最後に、、!

```shell
yarn dev
```
と打ち込んでやります。そうすると緑と黄色のプログレスバー(これめっちゃカッコ良くないですか？)が表示され、完了したらnuxtの開発環境が無事立ち上がってます;)

`docker-compose.yml`に記述したポート番号(今回の例では`3020`)のサイトにアクセスしてみましょう。

http://localhost:3020/

nuxtの雛形のサイトが表示されたと思います。

以上で環境構築完了です。お疲れ様でした！


## ひとこと
Dockerfileやdocker-compose.ymlの書き方や意味するところなどは現段階では割愛してますが、必要なところは追記するか、別の記事で書いてみようと思います。

間違ってる点やもっとこうした方がいいよ！っていうのがあればぜひご助言もらえると幸いです！

それでは。
S3のパブリック公開はパブリックじゃない時もあるから気をつけろ！

この投稿は[Global Mobility Serviceのアドベントカレンダー](https://qiita.com/advent-calendar/2019/global-mobility-service)の25日目です。

AWSでの今年の失敗を振り返りたいと思います。
S3のパブリック公開でやらかしました。

# 要約
S3のバケットポリシーによるパブリック公開はオブジェクトの権限によってパブリックじゃない時もあるので気をつけよう

# 失敗について
## 失敗までの経緯

S3のパブリック公開を調べてみると公式ドキュメントで以下の内容が見つかります。

> 匿名ユーザーへの読み取り専用アクセス許可の付与

>次のポリシー例では、任意のパブリック匿名ユーザーに s3:GetObject アクセス許可を付与します。(これによって許可されるアクセスとオペレーションの一覧については、「ポリシーでのアクセス許可の指定」を参照してください。) このアクセス許可はオブジェクトデータを誰でも読み取り可能にするので、バケットをウェブサイトとして設定し、バケット内のオブジェクトをすべての人が読み取れるようにする場合に便利です。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/example-bucket-policies.html#example-bucket-policies-use-case-2

これを見て、以下のようなバケットポリシーをパブリック公開したいバケットに設定しておけば大丈夫と思ってしまいました。

```:パブリック公開のバケットポリシー例
{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"PublicRead",
      "Effect":"Allow",
      "Principal": "*",
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::examplebucket/*"]
    }
  ]
}
```

ちなみに、このバケットポリシーを設定するとAWSコンソール上でパブリックであることがアピールされるので、なんとなくこれで大丈夫だと思ってしまいます。

![スクリーンショット 2019-12-23 16.10.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80244/f7c1b292-5ea8-a7f9-7cee-d775bae3158d.png)

## 失敗したケース

普段利用しているAWS環境はマルチアカウントになっています。
本ケースでは、以下のように別アカウント間でS3にオブジェクトを配置するという流れでした。
![S3パブリック公開失敗例図 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80244/50fbedf9-e588-e684-a82d-4c5805ed8d97.png)

BアカウントからAアカウントのバケットにPutObjectするのに、以下のようなバケットポリシーを適用しました。
特定のロールにPutObjectを許可するポリシーです。

```:パブリック公開と別アカウントからPutObjectを許可するバケットポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::hi1280-public/*"
        },
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::012345678901:role/AAccountAccessRole"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::hi1280-public/*"
        }
    ]
}
```

あとは、Bアカウントの環境からAWS CLIを使ってPutObjectをするだけの簡単なお仕事だと思って、オブジェクトを配置して安心していました。
が、のちに公開したはずのオブジェクトが見れないという連絡が来て焦りました。

実はこのようなケースの場合、PutObjectでオブジェクトを置いてもパブリック公開されません。
その当時は全く見ていなかったのですが、公式ドキュメントにちゃんと書かれていました。

>注記
バケットとオブジェクトの所有者が同じ場合、オブジェクトへのアクセスは、バケットコンテキストで評価されるバケットポリシーで許可することができます。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/access-control-auth-workflow-object-operation.html

つまり、バケットポリシーのみでパブリック公開できるのは、バケットが存在するAWSのアカウントと同じユーザやロールがオブジェクトを配置した時のみでした。

## どうすれば良いのか

さらにこのような記述があります。

>所有者が異なる場合、オブジェクトの所有者はオブジェクト ACL を使用してアクセス許可を付与する必要があります。

AWSのアカウントが異なる場合は、オブジェクトを配置したユーザやロールがACLでオブジェクトに対してアクセス権限を付与しなければいけなかったのです。

AWS CLIを使う場合、以下のコマンドです。

```sh
$ aws s3api put-object-acl --bucket bucket-name --key my_object --acl public-read
```

これで無事にオブジェクトをパブリック公開することができます。

# まとめ
油断大敵。確認を怠らないようにしなければと思いました。
皆様におかれましては、このような失敗が起きないようにS3におけるアクセス権限には十分にお気をつけください。

# おわりに
AWSはやっぱりよく分からないので色々学びあえる[エンジニアを募集](https://www.wantedly.com/projects/381883)しています。
Windows10のWSL上にあるServiceを簡単に自動起動させる

# 概要

Windows Subsystem for Linuxでは調べた限りだとsystemdは動いてないしまともな自動起動の設定がない。(たぶん)
sshdだとかdockerdだとかnginxだとかを自動起動してほしかった。
調べてもなんだか面倒な手順踏むようなやり方しか出てこない。

あんま面倒なことしないで手っ取り早く自動起動を設定する方法はないものか…と模索してたらなんかできた。

## 環境

* Windows10 Home
* WSL 1
* Ubuntu 18.04 LTS

## 自動起動の方法

とても簡単。

まず `Windows + R` キーでファイル名を指定して実行を呼び出す。
`shell:startup` と入力してエンター。（ログインユーザのスタートアップスクリプトとかを入れるディレクトリが開く）

右クリックをして新規作成のテキストドキュメントを選択し、拡張子を `.bat` で作成する。
スクリプトの名前は分かりやすいものに。

作ったbatファイルを右クリックで編集を押してエディタが開くので以下のスクリプトを記入、保存する。

```bat:enablessh.bat
@echo off
wsl -u root -- service ssh start
```

そしてWindowsを再起動すると、何もしてないのにTaskManagerにはsshdの文字が！

## ちょっと解説

WindowsのCMDで `wsl --help` すれば全ての答えが出てくる。

```
Linux バイナリを実行するための引数:
    --user, -u <ユーザー名>
        指定したユーザーとして実行します。

オプション:
    --
        残りのコマンドラインをそのまま渡します。
```

Rootで `service ssh start` を実行させているだけ。
なので自動起動というよりかは疑似的な自動起動をしているような感じ。

## 終わりに

これが一番早いと思います。（個人の意見並感）
ほぼ殴り書き&メモ書きみたいなものです。
いっつもWSL使うときにsshdの起動を忘れるし起動するときはsudoつけるからパスワード聞かれてめんどくさいしで、これで楽になれました。
WSLはさっさとsystemdで動くようにしろ！！！
そしてsystemctlを使わせてくれ。
Web Worker でJavaScriptを並列処理させる

JavaScript のWeb Worker API の使い方についての覚え書きです。

#Web Worker とは
Web Workerは、JavaScriptの処理を、バックグランドで並列に実行するための機能。


#Workerへの処理命令

##呼び出し元の記述例

main.jsから、Worker（worker.js）を呼び出し、処理を投げます。

```index.html
<label for="input1">width: </label><input id="input1" type="number">
<label for="input2">height: </label><input id="input2" type="number">
<input id="btn" type="button" value="Area?">
<output id="output"></output>
```

```main.js
document.addEventListener('DOMContentLoaded', function () {
  document.getElementById('btn').addEventListener('click', function () {
    let width = document.getElementById('input1').value;
    let height = document.getElementById('input2').value;
    let output = document.getElementById('output');
    //Workerオブジェクト
    var worker = new Worker('url_hoge/worker.js');
    //workerへ処理を命令
    worker.postMessage({
      'width': width,
      'height': height
    });
    //Workerから処理結果を受信したときの処理
    worker.addEventListener('message', function (e) {
      output.textContent = e.data;
    }, false);
    //Workerからエラーを受信したときの処理
    worker.addEventListener('error', function (e) {
      output.textContent = e.message;
    }, false);
  })
})
```

* コンストラクタ ```Worker()```の引数で、worker側のjsのパスを指定。
* ```postMessage()```の引数がworker.jsへ渡される。~~引数には文字列しか取れないので、オブジェクトJSONに変換してから渡す。~~ 引数にはJavaScriptのあらゆるオブジェクトを指定可能。
* worker.js側からの処理が返ると、```message```イベントが発火する。このイベントオブジェクトの```data```プロパティとして、処理結果が返される。

##Worker側の記述例

全然重たい処理ではないけど、Worker側でJavaScriptを実行させてみます。

```worker.js
self.addEventListener('message', function (e) {
  if (!Number(e.data.width) || !Number(e.data.height)) {
    self.postMessage('入力エラーです');
  } else {
    self.postMessage(Number(e.data.width) * Number(e.data.height));
  }
})
```

* main.js側からの命令を受けると、worker.js側で```message```イベントが発火する。
* main.jsから```postMessage()```の引数として渡されたデータが、イベントオブジェクトの```data```プロパティに入る。
* ```postMessage()```で、main.jsに処理結果を返す。

##postMessage()
呼び出し元からWorkerへ処理を命令する、あるいは、Workerから呼び出し元へ処理結果を返す。
引数は、メッセージを受け取った側からは、```message```イベントの```data```プロパティでアクセスできる。

##messageイベント
Worker側で呼び出し元からの処理命令を受け取ったとき、あるいは、呼び出し元側でWorkerからの処理結果を受け取ったときに発生するイベント。

##errorイベント
Worker側で実行時にエラーが発生したときに発生するイベント。
エラーイベントは以下のプロパティをもつ。

* ```message```
人間が読み取れるエラーメッセージ
* ```filename```
エラーが発生したスクリプトのファイル名
* ```lineno```
スクリプトファイル内でエラーが発生した場所の行番号

#Workerの終了

##terminate()
```js
worker.terminate();
```
呼び出し側からWorkerを終了させる。Workerは、自身の操作を完了したり、クリーンアップしたりすることなく、直ちに終了する。


##close()
Worker側から自分自身を終了する。

# 参考
* https://developer.mozilla.org/ja/docs/Web/API/Worker
* https://developer.mozilla.org/ja/docs/Web/API/Web_Workers_API
JavaScriptでブラウザの接続状態を取得する

#window.navigator.onLineプロパティ

ブラウザの接続状態を真偽値で表すプロパティ。

* ```true```: 接続されている
* ```false```: 接続されていない

ユーザがリンクをたどる、もしくは、スクリプトがリモートページを要求したときに値が更新される。
例えば、閲覧しているページからユーザがリンクをクリックした時に、インターネットへの接続が切れてていると、プロパティは```false``` を返す。

##ブラウザによる実装状況

###Chrome, Safari
* ``false``: ブラウザがLANまたはルータに接続できないとき
* ``true``: 上記以外（必ずしも、インターネットにアクセスできる状態とは限らない）

###Firefox, IE 
* ``false``: ブラウザがオフラインモードにあるとき
* ``true``: 上記以外

＊irefox 41以降では実際のネットワーク接続状態に従って値を返す

# online / offline イベント

``onLine``プロパティの値更新に準じて、Windowに対しイベントが発生する。
``onLine``プロパティと同様、必ずしも、インターネットにアクセスできる状態であるかを示す値ではないので注意する。

```js
//オンラインになった時
window.ononLine(function() {
//処理内容
)
//オフラインになった時
window.onoffLine(function() {
//処理内容
)
```

# 参考
https://developer.mozilla.org/ja/docs/Web/API/NavigatorOnLine/onLine
Rails6 each文にてeachがメソッドとして扱われて困った話

# 目的

- each文を使用してカラム内容を順に出力したい時にeachがメソッドとして扱われてしまって困ったときの解決法をまとめる

# 結論

- each文で繰り返し処理の対象の変数に格納されている値を配列状態で格納する。

# エラーの内容とエラー時のコード

- 当該ページは`@posts.content`に格納されている内容をeach文で次々渡し、表示する処理がある。
- 当該ページへアクセスしたところ下記のエラーが発生した。

    ```
    undefined method `each' for #<Post:0x00007fac1ebd28e8>
    ```

- エラーに関係するルーティングファイルの内容を記載する。

    ```rb
    get "posts/index/:id" => "posts#index"
    ```

- エラーに関係するpostsコントローラファイルの内容を記載する。

    ```rb
    def index
      @posts = Post.find_by(id: params[:id])
    end
    ```

- エラーに関係するindexビューファイルの内容を記載する。

    ```erb
    <% @posts.each do |post| %>
      <%= post.content %>
      <%= link_to("詳細", "/posts/#{post.id}") %>
    <% end %>
    ```

# 解決方法

- 修正を行なったコードのみ下記に記載する。

    ```rb
    def index
      @posts = Post.where(id: params[:id])
    end
    ```

- find_byメソッドは一致した最初のものを一つだけ返す。
- whereメソッドは一致した全てのものを返す。
かゆいところに手が届くNEM2用開発ツールを作ってる

アドベントカレンダーの日程が空いていたのでねじ込み。
タイトルの通りで、nem2-cliやブラウザでAPIが叩けるので比較的ブロックチェーン上のデータに
アクセスしやすいとはいえ、欲しい情報にたどり着くのに何手か必要な場合があります。

ので、いわゆる十徳ナイフ的な、マイツールを作っています。
といっても、SDKでAPIを叩いて、結果をとりあえずYAML形式で吐いて、
目視できるようにしているくらいのものです。


## デモ

- [nem2 Dev UI](http://nem2-ui-dev.s3-website-us-east-1.amazonaws.com/)

![alt](https://user-images.githubusercontent.com/370508/70846489-2bb1e900-1e9d-11ea-965d-6d46d7d75889.gif)

画面を見ればわかると思うので、とりあえず使ってみてください。


## リポジトリ

- [44uk/nem2\-dev\-ui: nem2\(catapult\) development Utility Interface](https://github.com/44uk/nem2-dev-ui)


## まとめ

`Catapult`のバージョンについてはあまり考えて無く、
新しい`SDK`が対応しているものに対応していると考えてください。
多少バージョンが違っても動くかもわかりませんが。

`Redux`がわからん…となり挫折した`React`をもう一度、頑張ってみています。
`Hooks`も最初はよくわかりませんでしたが、慣れてくるとビューからロジックをどんどん
移して行けて面白いですね。
(とは言え、雰囲気で書いているので、使い方があっているのかどうかもよくわからないんですが)
Windows10でTensorFlow2.0,Keras,MNISTメモ

####動作環境
Windows10 Home
RTX2080

####Anacondaのインストール
https://www.anaconda.com/

####CUDA
https://developer.nvidia.com/cuda-toolkit-archive

####cuDNN
https://developer.nvidia.com/rdp/cudnn-download

####Anacondapromptを起動
conda create -n [仮想環境名] python=3.7 jupyter
activate [仮想環境名]

####tensorflowをインストール
pip install tensorflow-gpu

```python:バージョン確認
import tensorflow as tf
tf.__version__
'2.0.0'
```

####kerasをインストール
pip install keras


```python:バージョン確認
import keras
Using TensorFlow backend.
keras.__version__
'2.3.1'
```

####MNISTで動作確認
```mnist.py
import tensorflow as tf

#MNIST データセットをロードして準備します。サンプルを整数から浮動小数点数に変換します。
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

#層を積み重ねてtf.keras.Sequentialモデルを構築します。訓練のためにオプティマイザと損失関数を選びます。
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

#モデルを訓練してから評価します。
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test,  y_test, verbose=2)
```

####その他必要なものをインストール
pip install Protobuf Pillow lxml
pip install Jupyter
pip install Matplotlib
wslでubuntu その8

# 概要

wslでkernel開発やってみる。
一連の動きを通しでやってみる。

# 環境
windows10 64bit

# １、wslでコンパイルする。

```
gcc -c -m32 -nostdlib test5.S
ld -melf_i386 -e_start -Ttext=0x100000 -otest5.elf test5.o
   
```


# サンプルコード

```
.code32    
.text
.globl _start
.globl multiboot_header

_start:
    movl    $0xb8000, %ebx
    movl    $12, %ecx
    movl    $msg, %esi
loop:
    movb    (%esi), %al
    movb    $2, %ah
    movw    %ax, (%ebx)
    addl    $2, %ebx
    addl    $1, %esi
    subl    $1, %ecx
    jne     loop
    jmp     .

.data
multiboot_header:
    .align 4
    .long   0x1badb002
    .long   0x0 
    .long   -0x1badb002-0x0
msg:
    .ascii "Hello world!"

```

# ２、diskexplorerで、nano1.imgにtest5.elfを入れる。

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/596c3997-0c31-9e6f-6f55-d530994bb0b7.jpeg)

# ３、qemu-0.15.1で、test5.elfをgrubからbootする。

qemu起動。

```
qemu -fda nano1.img
```

grub

```
root (fd0)
kernel /boot/test5.elf
boot
```

# 結果

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/45b4529d-2fcf-9ba3-97dd-73c2e4ca29a7.jpeg)


以上。
[バッチ] 歴史あるソースコードのバラバラの文字コードを一括変換で統一したい

**もくじ**
→https://qiita.com/tera1707/items/4fda73d86eded283ec4f

# やりたいこと
新しいコードから昔の実績あるコードまでいろいろ含んでいるプロジェクトについて、文字コードや改行コードを統一したい。

# やろうとおもった経緯
Gitでコードを管理するときに、リポジトリにpushされるコードは、文字コードが統一されているべき、ということになり、手元のそのあたりバラバラなコードの文字コードを統一したかった。  

また、少数のファイルならエディタで一つずつ開いて変換、ということもできたが、ファイル数が多いため、手でやるのは非現実的、ということで、自動で一括変換かける方法を調べた。  
そのときのメモ。

# 目標の文字コード
下記のように今回は統一したい。

- UTF-8
- BOMあり
- 改行コードはCRLF(Windows形式)

# やり方
サクラエディタのマクロを使用する。

サクラエディタのマクロは、サクラの独自？の.macという形式とやJscript、VBScriptなど、数種類の書き方ができるらしい。([こちら](https://sakura-editor.github.io/help/HLP000204.html)参照)
**→今回はVBScriptを使用。**

バッチファイルからvbsを呼ぶような形で、分担をして処理をする。
具体的には下記のような処理をそれぞれで行う。

- バッチ
  - 自分の階層以下にあるフォルダから、指定の拡張子のファイルパスをすべて取ってくる
  - とってきたパスを、サクラエディタのexeに一つずつ渡して、サクラエディタを開く
  - 渡す際、実行するマクロを指定する(→これが下の「サクラエディタのvbsマクロ」)

- サクラエディタのvbsマクロ
  - 開いたファイルの文字コードをUTF-8/BOMありにする
  - 開いたファイルを、UTF-8のCRLFで上書き保存する

# 前提
- サクラエディタがインストールされていること。
今回試した時のサクラエディタのバージョンは**「Ver.2.2.0.1」**

# 実際のコード

``` convertutf8.bat
@echo off
rem -------------------------------------
rem メイン処理
rem このbatと同じフォルダ(*1)の中にある指定拡張子のファイル(*2)を
rem すべてutf-8のCRLF(BOMあり)に変換する=ファイルパスを引数にしてvbsを呼ぶ
rem -------------------------------------
for /r %%f in (*.h *.cpp *.cs) do (
call:exec_convert %%f
)
goto :convert_end

rem -------------------------------------
rem 変換実施サブルーチン
rem 同じ場所に置かれているマクロ(vbs)を実行
rem -------------------------------------
:exec_convert
echo %1
"C:\Program Files (x86)\sakura\sakura.exe" %1 -M=%~dp0convertutf8.vbs
exit /b

:convert_end
pause
```

``` convertutf8.vbs
' 使用変数
Dim filepath	' 処理対象のファイルパス
Dim splitstr	' 拡張子抽出のための一時変数
Dim extension	' 処理対象のファイルの拡張子
Dim addBOM		' BOMありなし(0:BOMなし 1:BOMあり)

' デバッグ用POPUP作成用WSHShell
set WSHShell = CreateObject("WScript.Shell")
'WSHShell.Popup "Filename is " + GetFilename, 0, "title", 1

' 今Sakuraで開いているファイルパスを取得
filepath = GetFilename

' そのファイルの拡張子を取得(splitstr(1)が拡張子になる)
splitstr = split(filepath, ".")
extension = splitstr(1)

' UTF-8、BOMありにする
ChgCharSet 4, 1

' ファイルを保存(UTF-8、CRLF)
if extension = "cmd" or extension = "bat" then
	' バッチファイルは、UTF-8/BOMなし にする
	addBOM = 0
else
	' その他のファイルは、UTF-8/BOMあり にする
	addBOM = 1
end if

' ファイルを保存する
FileSaveAs filepath, 4, addBOM

' ウインドウを閉じる
WinClose

```

# 使い方  
- 文字コードを統一したいファイルがあるフォルダに`convertutf8.bat`と`convertutf8.vbs`をコピーする。
- `convertutf8.bat`をダブルクリックして実行する。

# memo
以前の記事で試した通り、batを実行する際、BOMがあると、1行目がうまく動いてくれない。
そのため、vbsで変換を行う際、batとかcmdという拡張子のファイルについてはは、BOMなしにするよう分岐させている。

→以前の記事：[[バッチ/git] バッチをgitに上げてそれを他の人がクローンすると、なんか動きませんけどと言われる(gitにコミット時の改行の扱いについて)](https://qiita.com/tera1707/items/f97f90fc10053becf765)

# 参考
サクラエディタ ヘルプ
https://sakura-editor.github.io/help/HLP000001.html
※マクロの使い方は、このページの「コマンド概要」の各項目を開いた中にある各メニュー項目の中に書かれている。

**名前を付けて保存**
https://sakura-editor.github.io/help/HLP000021.html
ここの「FileSaveAs」で保存をするときに文字コード、改行コードを指定する。
(BOMありなしは指定できないので、下の「文字コードセット指定」で指定する)

**文字コードセット指定**
https://sakura-editor.github.io/help/HLP000297.html
(BOMのありなしを指定する)
PHP の RAII は幻想じゃなくなった

だいぶ前にこんな記事を書いていましたけど、

- [PHP の RAII なんて幻想](https://qiita.com/ngyuki/items/576d66110495d5f1d4ee)

どうやら PHP 7.4 では `zend.exception_ignore_args` なるオプションが増えたらしく幻想ではなくなったようです。

- https://3v4l.org/i0gXq

PHP 7.3 以前では `SplFileObject` のインスタンスが `bar` で発生した例外に掴まれて `main` まで飛んでいくので `foo` のスコープを抜けてもファイルは閉じられませんでした。

しかし PHP 7.4 で `zend.exception_ignore_args` を有効にしておけば例外によって関数の引数が掴まれることがないので、`bar` で発生した例外に `SplFileObject` のインスタンスが掴まれることはなく、`foo` のスコープを抜ければファイルは閉じられます。

以前社内で、例外がログられるときにスタックトレースの引数にセンシティブな情報があるとやばいのでそのたぐいの情報はリクエストから取り出した直後にオブジェクトか何かでラップした方が良いのだろうか、とか話題になったんですけど（[このとき](https://twitter.com/ngyuki/status/961470806504095744)）、それもこれで一緒に解決できるということですね（むしろそっちが `zend.exception_ignore_args` の本来の目的ですね）。

- https://3v4l.org/F9nc9

PHP 7.3 以前だと `#0 /in/F9nc9(9): f('ore no himitu')` のように引数が出力されてしまってますけど、PHP 7.4 で `zend.exception_ignore_args` が有効なら `#0 /in/F9nc9(9): f()` のように引数は現れません。
画像ファイルが選択されたらブラウザ上でリサイズしてBase64文字列にして結果をフォームに埋め込んでサーバに送信する(非ajax)

色々と面倒だったので備忘。
アプリケーション設定は`playframework`独自ですが、フロント側は素の`javascript`でいけますし、サーバサイドもどんな言語・Webフレームワークでも道具立てが用意されているはずです。

+ アプリケーション設定
    + `application.conf`でBodyParserのデータ上限を緩和する.
+ HTML
    + input[type='file']タグを用意
    + 上記に対応するcanvasを用意する。表示サイズはwidth指定しておく。(役割はファイル選択時のサムネイル表示とBase64文字列取得)
+ 画像ファイル選択
    + 選択されたら、canvasを初期化する(clearRect)。ファイル内容を読み込む。ファイル種別等をチェック。
    + ファイル読み込みが完了(onload)したらその結果(e.target.result)をimg.srcに設定する
    + img.srcの読み込みが完了(onload)したら、その内容を適宜リサイズしてcanvasに描画(drawImage)する
+ フォーム確定(submit)
    + フロントエンド
        + 選択されたファイルが存在する場合、canvasからBase64化された文字列を取得(`toDataURL('image/jpeg')`)。以降ではイメージ文字列と呼称
        + フォームにhidden属性を追加して値にイメージ文字列を設定する
        + `input[type='file']`に設定された内容を消す ← 無駄なので。そもそも画像リサイズ要件の背景は「通信遅い」から派生しているので
        + submitする
    + サーバサイド
        + multipartでなく通常のフォームパラメタとして読み出す
        + イメージ文字列のデータ部分を切り出して、BufferedImageに変換する。=> このあとはファイルに戻したり、好きに加工
            + `data:image/jpeg;base64,★ここから後=>★/9j/4AAQSkZJRgABAQEASABIAAD/4ge4SUNDX1BST0ZJTEUAAQEAAAeoYFKc5KKbP/2Q==`


ポイントとしては、

- サーバサイドに送信するデータは`canvas`に描画したデータで、`input[type='file']`のデータではないこと
- 非ajax(フォームに埋め込んでサーバに送信)であること。(こういった処理を行う場合は、Blob化して`FormData`に詰めて、ajaxでサーバサイドに送ることが多い模様)

# 参考

- [ブラウザでローカル画像をリサイズしてアップロード - Qiita](https://qiita.com/komakomako/items/8efd4184f6d7cf1363f2)
- [java - Convert base64 string to image - Stack Overflow](https://stackoverflow.com/questions/23979842/convert-base64-string-to-image/51372862)
wslでubuntu その7

#概要

wslでubuntuやってみた。
練習問題やってみた。

#練習問題

wslとpaizaで動く、fizzbuzzを書け。

#サンプルコード

```
.code64
.text
.global main

main:
    mov     $1, %cx
loop:
    mov     %cx, %ax
    mov     $15, %bl
    div     %bl
    cmp     $0, %ah
    jz      loop15
    mov     %cx, %ax
    mov     $5, %bl
    div     %bl
    cmp     $0, %ah
    jz      loop5
    mov     %cx, %ax
    mov     $3, %bl
    div     %bl
    cmp     $0, %ah
    jz      loop3
	mov 	%cx, %ax
loop2:
    push    %cx
	call 	bin2dec
    pop     %cx
loop1:
	add     $1, %cx
	cmp     $101, %cx
    jnz     loop
	ret

loop15:
    mov 	$fizzbuzz, %rsi
    mov     $1, %rdi
    mov     $9, %rdx
    mov     $1, %rax
    push    %cx
    syscall
    pop     %cx
    jmp     loop1
    
loop5:
    mov 	$buzz, %rsi
    mov     $1, %rdi
    mov     $5, %rdx
    mov     $1, %rax
    push    %cx
    syscall
    pop     %cx
    jmp     loop1
    
loop3:
    mov 	$fizz, %rsi
    mov     $1, %rdi
    mov     $5, %rdx
    mov     $1, %rax
    push    %cx
    syscall
    pop     %cx
    jmp     loop1
	
bin2dec:
    mov     $100, %bl
    div     %bl
    push    %ax
    call    putd
    pop     %ax
    mov     %ah, %al
    and     $0xff, %ax
    mov     $10, %bl
    div     %bl
    push    %ax
    call    putd
    pop     %ax
    mov     %ah, %al
    call    putd
    mov     $10, %ax
    call    putd
    ret
    
putd:
    and     $0x0f, %rax
    mov     $num, %rsi
    add     %rax, %rsi
    mov     $1, %rdi
    mov     $1, %rdx
    mov     $1, %rax
    push    %cx
    syscall
    pop     %cx
    ret
	
.data
fizz:
	.ascii 	"Fizz "
buzz:
	.ascii 	"Buzz "
fizzbuzz:
	.ascii 	"FizzBuzz "	
num:
	.ascii 	"0123456789 "
	


```

#成果物

https://paiza.io/projects/nClJLA7kdqyk8Yvmy-nMpw

以上。
tarの中身に対してチェックサムを打ちたい

LinuxやUnixに設定ファイルをリリースするときに、
1. 開発環境で設定ファイルいじる
2. tarで固める
3. ステージングor本番でtarを展開する

という流れはよくあると思いますが、`tarの中身は開発環境と同じか？`とか言われることあります。

また、クラスタを組んでいるサーバ同士で設定が同じかチェックするために、
`sosreport`なりで情報を取得して比較する、というタスクがあります。

そんなときに全ファイルをdiffしていると見づらい。手っ取り早く差分があるか見たい、しかし展開はしたくない、
というニーズが(自分には)あったので、作ってみました。
https://github.com/kuritayu/infra-tools

# 仕様
以下で取得できます。
`go get github.com/kuritayu/infra-tools`
`go install "${GOPATH}"/src/infra-tools/cmd/lstar`

## 引数なし
引数なしで実行するとhelpがでます。

```terminal
NAME:
   lstar - print tar information

USAGE:
   lstar [global options] command [command options] [arguments...]

VERSION:
   1.0

COMMANDS:
   help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --help, -h     show help (default: false)
   --version, -v  print the version (default: false)
```

## 引数あり
引数としてtarファイルを指定すると、こんな感じで出力されます。`tar`と`tar.gz`に対応してます。

```terminal
Permission Owner    Group Size Date                Path             Checksum
-rw-r--r-- kuritayu staff 3584 2019-12-14 23:53:20 test/test.tar    b441b2f9a3e8a6154f60a1ef6509e9bf
drwxr-xr-x kuritayu staff 0    2019-12-09 23:13:54 ./test/          d41d8cd98f00b204e9800998ecf8427e
-rw-r--r-- kuritayu staff 2    2019-12-09 23:14:00 ./test/test2.txt 30cf3d7d133b08543cb6c8933c29dfd7
urw-r--r-- kuritayu staff 16   2019-12-10 08:39:10 ./test.txt       697f3de8175d739661ce5d0f9009eec4
```

チェックサム値はMD5で計算してます。

基本的な処理は、
1. 引数で与えられたファイルに対するvalidate
2. 該当ファイル(tar or tar.gz)を読み込み、`tar.NewReader`に読ませる
3. ヘッダーデータや実データを構造体にセット
4. 実データからチェックサム計算

をしています。
Nutanixのココでハマった！

## はじめに
この記事は[Nutanix Advent Calendar 2019(4枚目)](https://adventar.org/calendars/4475)、12月24日分です。
気づけばNutanix Advent Calendarへの参加は3年連続3回目です。

[Nutanix Advent Calendar 2019(1枚目)](https://adventar.org/calendars/4001)
[Nutanix Advent Calendar 2019(2枚目)](https://adventar.org/calendars/4014)
[Nutanix Advent Calendar 2019(3枚目)](https://adventar.org/calendars/4037)

## お断り
この記事ではNutanixの運用をしていてハマったことの一例を記載します。
「Nutanixのココでハマった！」と少しセンシティブな表題ですが、これらはすべて
・アーキテクチャを理解した設計をする
・マニュアルをきちんと読む
・ベストプラクティスに準拠する
を守っていれば起き得ないことであり、この記事で私が言いたいのもコレに尽きます。

## はまったこと。
なぜかLCMがらみが多いです。
オカルティックなお話しですが、私は10年ほど前からファームウェアと非常に相性が悪いからだと思います。
例えばProLiantサーバで、私がSystem ROMを上げると高確率でボード障害が起きますが、その他のメンバーではこういった事は起きません。
その変わり、同じ事をやると高確率でDVD-ROMが故障する人がいます。(これ、なんでだろ…)

### LCMを使ってFirmwareを上げていたらホストの再起動後、Phoenix が起動した状態で止まってしまいました！①
原因は、IPMIポートにLANケーブルが挿されていなかったからです。(IPアドレスは設定していました)
hypervisor問わず、IPMIポートにLANケーブルを挿し、IPアドレスを設定することがリコメンドされていますね。
LCMはFirmwareをアップデートするとき、ざっくり以下のような動きをします。
・AHVホストを再起動
・Phoenix を起動
・IPMI経由でisoをマウント
・ファームウェアのバージョンアップ
・再起動、しAHVホストが起動したら次のノードへ
せっかくリコメンドされているのに、それをやらないと、こういう罠？にハマります。
なお、IPMIはAHVノードのeth0とShared Portだったはずであり、IPMIポートにLANケーブルが挿さっていない以外にも、何か原因があったかもしれません。

### LCMを使ってFirmwareを上げていたらホストの再起動後、Phoenix (以下略 ②
LCMを利用して、Firmwareを上げていたところ、ホストの再起動後、Phenixが起動した状態で止まってしまいました。
ノードを本番クラスタに入れる前、Single Node Clusterを組んでFirmwareをあげておこうとしたところ、こうなりました。
原因はそのまんま、Single Node Clusterだからです。LCMはSingle Nodeクラスタはサポート外です。マニュアルに書いてあります。

https://portal.nutanix.com/#/page/docs/details?targetId=Web-Console-Guide-Prism-v510:upg-firmware-upgrades-c.html
きちんと読みましょう！(ごめんなさいたま！)

### LCMを使ってFirmwareを上げていたらホストの再起動後、Phoenix (ry ③
この時、ちなみに①を経験していたため、IPMI周りは既に完璧にしています。
LCMの不具合を踏んでいました。この不具合は以下の条件で発生し、私がいる環境ではこれに該当していました。

・ブリッジが2つある
・対向スイッチでLACPまたはStatic LAGを有効にしている

この不具合は、LCM 2.3およびFoundation to 4.5.1で修正されています。
https://portal.nutanix.com/#/page/kbs/details?targetId=kA00e000000PVpbCAG

昔ながらの？仮想インフラの設計において、以下の用途に対して、それぞれ個別のvSwitchを作成し、明示的に通信を分けることはよくあることかと思います。

・Hypervisor(Migrationを含む)
・ストレージ
・仮想マシンのサービス

Nutanix AHVはHCIであるため、上記のHypervisorとストレージはほぼ同義であり、当然同一のブリッジである必要があります。(ブリッジ内では異なるVLANにセパレートすることは可能です)
したがって、AHVの場合、問題になるのがHypervisorと仮想マシンのサービス別のブリッジに分けるか否か？ですが。これを無理に分ける必要ってあるのでしょうか？Nutanixに関して、私はこれに合理的な答えを見つけられずにいます。(私がいる環境の場合、別の要因で分けざるを得なかったのです、、、)
AOS 5.10よりAHVノードに対するブリッジの追加は、クラスタに参加した後にしかできなくなりました。この変更は、「これって無理に分ける必要ってあるの？分けない方がシンプルじゃん」というメッセージのように感じます。Nutanixのアーキテクチャを考えるに、トラフィックごとにブリッジと線を分けるより、線そのものを増やして、LACPなどでロードバランスをした方がパフォーマンスがでるはずです。(間違ってたらごめんなさい)

現在、AHVは仮想マシンに対するネットワークのQoSの機能がありませんが、将来的に実装されるのでは？と個人的には期待しています。
ちなみに、vSANの場合、vSANトラフィックをその他のトラフィック、と同一のvSwitchで処理させる場合、分散仮想スイッチのNetwork I/O Controlでバンド幅を確保するのがベストプラクティスだった記憶があります。
vSANの話を出しましたが、どちらが優れている、という訳でなく、それぞれのアーキテクチャに合わせた設計をしましょう、ということですね。

## おわりに
実名は伏せさせていただきますが、日頃よりお世話になっておりますNutanix社の担当営業およびSEの方々や丁寧に回答をいただけるサポートの方、さまざまな支援をくださる販社の皆さま、技術情報を発信されている方々に敬意を表するとともに、心より御礼申し上げます。ありがとうございます！今後ともよろしくお願いします。



## おまけ
実はNutanix社の株主だったりします。1株。
Nutanix社に限らず、業務で関わった思い出深いプロダクトの株式を1株だけ買う「思い出株」という活動を、昨年から始めました。
円高と株価の下落、1株だけのため割高な手数料で目も当てられないことになっていますが、投資目的ではないので何も問題はないです。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195654/c2cb6625-0aa1-ef69-f288-fada09eb53c4.png)
2019/12/21 Matz氏特別講演に参加して

先日、日本で一番有名なプログラマーであるMatz氏（まつもとゆきひろ氏）の特別講演に参加したのでその内容をここにまとめます。

##講演について
日時：2019年12月21日14:00~16:00
場所：渋谷ソラスタ15F
主催：サポーターズCoLab運営事務局
主題：「若手エンジニアが市場価値を上げるために必要なこと」

##参加したきっかけ
サポーターズ主催でエンジニアを対象にした講演会の案内をよく目にしていました。時間が合えば何かに参加したいと考えており、私自身WEBエンジニアに転職したばかりなため、今後どのようなステップを踏んで自分の価値を高められるのかなぁ？と、ぼんやりと考えている最中にMatz氏の講演情報がメールで届いたので迷わず申し込みました。その内容を下記にまとめてみます。

##講演内容
######一般的に考える市場価値
エンジニアに限らず、まずは「市場価値」について考えていきたい。
市場価値が「高い」と思っている場合、一体どのような利点があるのだろうか。
＊あえて**「思っている」**という書き方の理由はのちに説明しています。
【市場価値が高いと思っている→給料が上がる】
一般的に個人の市場価値が上がれば、給料は上がるとされている。つまり市場価値はお金に直結するものであると考えられている。

【市場価値が高いと思っている→心理的余裕が生まれる】
個人として価値が高まれば、心に余裕ができるとされている。いつでも辞められる気持ちでいると、ストレス耐性が身につくとともに心理的余裕を持った上でお仕事に取り組むことができるのだ。つまり「今の会社以外でも働ける力」を身につけて、逃げ場をもつことが心身的にも大切だという。たしかに選択肢が一つしかない場合と、複数ある場合では心の余裕度合いに大きく差があるように思う。



######Matz氏が考える市場価値
ところがMatz氏は**「市場価値が高いと思っている」**のようにあくまで客観的な価値そのものではなく、主観的な判断を基準にしている点に注目ポイントがある。
主観的判断をする理由は**市場価値とは他人からの評価**であるため自分ではコントロールできないものだと認識しているからである。つまり他人の内心を隅々まで読めないのと同じように、他人が決める自分の市場価値は分からないものなのだ。わからないものを考えるよりも、自分がわかる範囲であれこれと工夫していけば市場価値は高まるはずであると考えている。

だから私たちが自分の市場価値を高いと思うには、少し視点を変えて**他人の目に自分がどう映るのか**を考えなければならない。Matz氏は自分を相手に**どう魅力的に見せるか**を考えて行動するべきだという。

######自分をどう魅力的に見せるか
①目線を変えてみる
「もしあなたが入社したい企業の面接官だとしてどんな人を欲しいだろうか？」のように自分ではない他人の目線で想像してみることをオススメする。そうすることで理想の姿に対して今の自分は何が足りていなくて、また何が身についているのか考えるきっかけになる。理想に近づけるように穴埋めをしていくことで自ずと自分の魅力は相手に伝わる。
世界的に有名な本『7つの習慣』の中にある「win-win」についてこのような記述がある。取引の場面においてどのくらい双方の損得パターンはあるだろうか。「win-win」、「win-lose」、「lose-win」、「lose-lose」の4パターンが考えられる。が、実はこの本によると持続可能な答えは2つしかない。「win-win」もしくは「No Deal」である。もし片方でも損害を被るなら取引をしない選択をすべきだとしている。
つまり、自分と企業にとってもwin-winの関係を築けるようにはどのような能力が必要だろうか考えてみようということだ。loseになる可能性があるのなら取引をしたくないというのが企業の本音ということを忘れてはいけない。

②先入観を取り払う
どんな人でも自分より優れたところがあることを忘れてはいけない。キリスト教の黄金律に「人にしてもらいたいと思うことは何でも、あなたがたも人にしなさい」とある。人への思い込みを取り払って真心で他人と接すれば必ず魅力的に見える。

③情報発信する
「人はあなたを見つけられるだろうか？」自分に問うて欲しい。何もしていないと誰にも探し出してもらえないので、Twitter,Qiita,Quora,GitHubなどで発信してみてはどうだろう。魅力的に見せるために自分でまず動いてみることが肝心。

④自分を知る
自分にはどのような魅力があるのか、まずは自分を知る作業から取り組むのも良い。自分は何ができるのかインベントリー（棚卸し）を行う。自分の得意なこと、好きなこと、興味、傾向、経験など文字におこしてみることで自己認知力を高めてみる。

⑤Connecting the dots
2015年スタンフォード大学の卒業式でのスティーブ・ジョブズのスピーチを知っているだろうか。特に「Connecting the dots」をここで取り上げたい。バラバラの点と点（経験や知識）を繋げて線に、そして3つ以上繋げて面にしていくことで独自の価値が生まれるというものだ。彼は大学中退後もカリグラフィー（日本でいう書道）の授業に潜り込み文字の美しさについて学んだ。その経験がデザインや製品開発にいてかなりの影響を及ぼしたため今のAppleがある。このようにどの経験が身を結ぶかは誰にも分からない。だから得意なことや好きなこと（dots）をたくさん増やして、それぞれの組み合わせが新たなあなたの魅力に繋がる。

⑥人間はストーリーが好き
人間は物語に共感する。その人がどんな過去を歩んできて、今は何に取り組んでいて、この先何をしたいのか。一つの線としてその人の人生を理解できると関心を持ってもらいやすい。そのためには自分語りが大切になる。具体的には芸人さんではないけれど、ネタ帳を作ってみよう。そこには成功談も失敗談もたくさん記録しておこう。

##まとめ
簡単ではありますが講演の内容をまとめてみました。自分の価値は誰かが決めるので自分で意識する必要はなくて、むしろ自分ができる範囲で自分の魅力を高めることが結果的に市場価値を上げる、と教わったので今回語られた「自分をどう魅力的に見せるか」に取り組んでみようと思います。ありがとうございました。
R&統計学[0] 目次、環境構築

## はじめに
この連載(?)はRと統計学を一緒に学ぼうというお気持ちで始めた連載です。
私も学びながら、記事を作っていきますので間違えている可能性があります、もし間違いを見つけた場合にはご指摘ください！

## Rとは
Rは統計学・数値計算・機械学習などに優れた統計ツールです。
詳しくは第一回で触れますが、非常に様々な計算が「1行」で行えます。
ゴリゴリのプログラムというより、本当に手足のように扱える(ようになりたい)ツールといえます。

## なぜ統計学を学ぶか
詳しくは第一回で解説しますが、統計学・確率論を使いこなせるようになると、様々なシーンで役に立ちます。
データを前に、エクセルに取り込んでから適当なグラフを作るだけの人を卒業したい！(もちろんこれも非常に大事なんですが)
ということで、教養的な知識としてRと統計学をしていこうという連載です。
理論にもほどほどに触れますが、数学的証明を与えたり、その正しさを明らかにするというよりは、その**理論を理解して使えるようになる**ことをメインの目標とします。

## 前提知識
前提知識は高校数学程度です。
時々大学レベルの積分も出ますが、ほとんどの意味合いにおいて以下のような面積を求めています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484965/f280a60f-c87f-97a7-1336-f2985b7added.png)
これは、$f(x) = x^2$の関数で、1から3までの間で定積分したものです。
また、この面積はx=1、x=3、x軸、f(x)で囲まれた部分の面積とも言えます。
式にすると

$$ 
  \int_1^3 x^2 dx　　　　\int_1^3 f(x) dx
$$
といったふうに表されます。
厳密なお話は置いておいて、概ねこのような意味があると理解して貰えれば大丈夫だと思います。(わからなかったら飛ばしちゃいましょう)

## 環境構築
どんな環境を使ってもらっても構いませんが、私はRStudioという統合開発環境を使っています。
分かりやすいし高機能で便利です。

### Rのインストール
[統計数理研究所のミラーサイト](https://cran.r-project.org/)というRのサイトからダウンロード出来ます
他にも、[山形大学のミラーサイト](https://ftp.yz.yamagata-u.ac.jp/pub/cran/)などからもダウンロード出来ます

### RStudioのインストール
[RStudioのサイト](https://rstudio.com/products/rstudio/download/)からダウンロードします
Open SourceでFreeのRStudio Desktopで十分でしょう。

後は仰せのままにポチポチすればOkです！
もしRより先にRStudioをインストールするとRが無いよと言われるので、必ずRを入れてからRStudioを入れましょう。

## 連載目次
目次が必要なほど連載が続くかどうか分かりませんが...一応わかりやすく目次をつけておきます。

[1. Rイントロダクション](https://qiita.com/sakarush/items/9cf3488ee48cb09b730d)
[2. 帰無仮説とp検定](https://qiita.com/sakarush/items/65205e9da308530a4530)
3. t分布
4. Rでグラフを描きまくる

### 終わりに
一応目標は機械学習まで行ければなと思っています。
よろしくおねがいします。
データベースの重複をなくす

## 環境
MySQL
MacOS

## やりたいこと
データベース上に特定の組み合わせのカラムが複数できてしまったレコードをユニーク(一意)にする。

## コード

```sql

// 重複の組み合わせはGROUP BYの後ろで調整
> DELETE FROM target_table WHERE id NOT IN (SELECT MIN(id) min_id FROM target_table GROUP BY column1,column2,column3);

```

## 解説
SQLのコードを見るときは、一番内側にあるSQLから見ていくと理解が早いです。

### 1.削除しないIDのリストを作成する
一番内側のSQLはカッコの中に入っている、

```sql
> SELECT MIN(id) min_id FROM target_table GROUP BY column1,column2,column3;
```
ですね。

これは、特定のカラムが同じレコードを一つにまとめて、その中でidが古い(数字が小さい)ものを出力しています。

### 2.上記で作成したID以外のレコードを削除する
そして、それをNOT IN区で使ってあげることで、作ったIDのリスト以外のデータをすべて削除します。

```sql

> DELETE FROM target_table WHERE id NOT IN (SELECT MIN(id) min_id FROM target_table GROUP BY column1,column2,column3);

```

## メリットとデメリット

### メリット
・一発で削除することができる
・GROUP BYを変更すれば様々なパターンに対応できる

### デメリット
・どれを削除したかわからない
・若干SQLが長い

ただ、デメリットのどれを削除したかわからない(ログが残らない)ということに関しては、一度DELETE文ではなくてSELECT文に変更して流すとか、削除しないIDのリストだけ作って、それを置換してSQLを作って上げればいい感じにできます。

```bash
// 例 
// IDのリストを作成
$ echo "SELECT id FROM target_table WHERE id NOT IN (SELECT MIN(id) min_id FROM target_table GROUP BY column1,column2,column3);" | mysql -u root | tee id_list.tsv

$ cat id_list.tsv
id
1
3
5
7
...

// 先頭と行末を置換してSQLを作成(もちろんエディタを使っても良い)
$ cat id_list.tsv | sed 's/^/DELETE FROM target_table WHERE id = /g' | sed 's/$/;/g'
DELETE FROM target_table WHERE id = 1;
DELETE FROM target_table WHERE id = 2;
DELETE FROM target_table WHERE id = 3;
DELETE FROM target_table WHERE id = 4;
DELETE FROM target_table WHERE id = 5;
DELETE FROM target_table WHERE id = 6;
...
→ コピーしてｍｙｓｑｌに流す or シェル芸でmysqlに渡してあげる

```

## 最後に
DELETE文って怖いですよね笑

書いてもいいけど、エンターは誰かに押してほしい。
【効率化】zshエイリアスと関数を晒す

## TL;DR
以前、村上さん(@ryuta69 )の記事を読んで、速攻で導入したエイリアス一覧を晒します。
[【私的最強alias32選】忘れやすいコマンドは、『辞書化＆ショートカット化』しちゃえばいい](https://qiita.com/ryuta69/items/4c3f6d9e86cdcf58a2b7)

こんな人におすすめです。

- コマンドを覚えられない
- コマンド打つのめんどい
- コマンドの打ち間違いが怖い

## zshについて
macOSのCatalinaからzshが標準のシェルになりましたね。
bashから移行する方も多いと思うので、zshのtipsをまとめます。


## zshエイリアスについて
zshのプラグインである[oh-my-zsh](https://github.com/ohmyzsh/ohmyzsh)をインストールすると、gitなどのエイリアスがいい感じに設定されます。

とはいえ

- 一連のコマンドを組み合わせた関数も欲しい。
- 自分にとってわかりやすいエイリアスを作りたい。

なので`~/.zshrc`をいじってオレオレエイリアスを設定しました。

## zshエイリアス設定方法
bashとは記法がちょっと異なります。
例えば、エイリアス名とコマンドをつなぐイコールの間に、半角スペースが入ってはいけない、とか。

単純なエイリアスの設定例は以下。

```zsh:~/.zshrc
alias gitls="alias | grep git"
```

対話型の関数を作るときは`echo`と`read`を使います。
hoge()という関数を作るときの文法は以下の通りです。

```zsh:~/.zshrc
hoge () {
        echo 'Type your favorite food' && read food;
        echo 'Your favorite food is '"${food}"', right?'
}
```

`read`で入力した値が`food`という変数に格納されます。
呼び出すときは`${変数}`という形で使えます。

hoge()のコンソールでの実行結果は以下のようになります。

```
-> % hoge
Type your favorite food    // ここでcurryとタイプする
curry
Your favorite food is curry, right?
```


## オレオレzshエイリアス公開
メインは現在業務でよく使う以下の3種類

 - Firebase
 - npm
 - git

```zsh:~/.zshrc
# zsh aliases
alias vz="vim ~/.zshrc"
alias sz="source ~/.zshrc"
alias rmf="rm -rf"

# Firebase aliases
alias fl="firebase login"
alias fi="firebase init"
alias fs="sudo firebase serve"
alias fd="firebase deploy"
alias fdf="firebase deploy --only functions"

# npm commands
alias nig="npm install -g"
alias nis="npm install --save"
alias nui="npm uninstall"
alias nuis="npm uninstall --save"
alias nls="npm ls"
alias niy="npm init -y"
alias nid="npm install --save-dev"
nvv() { npm view $1 version }

# Show all git alias commands
alias gitls="alias | grep git"
alias gc="git checkout"
alias gcd="git checkout develop"
alias gpd="git push origin develop"
alias gpm="git push origin master"
alias grm="git rm --cached"
alias gdn="git diff --name-only"
alias grh="git reset --hard HEAD^"

gmpd () {
    git pull origin develop
    echo "Type branche name to merge : " && read branch;
    git merge ${branch};
    git status;
    echo "Is it okay to continue?" && read;
    git push origin develop
}

# Push all changes to current branch
gcom () {
    git add . && git status
    echo "Type commit comment" && read comment;
    git commit -m ${comment} && git push origin HEAD
}

mygcre () {
	git init && git add . && git status && git commit -m "First commit"
    echo "Type repository name: " && read name;
    echo "Type repository description: " && read description;
    curl -u YOURID:YOURPASSWORD https://api.github.com/user/repos -d '{"name":"'"${name}"'","description":"'"${description}"'","private":true}'
    git remote add origin https://github.com/deatiger/${name}.git
    git checkout -b develop;
    git push -u origin develop;
}
```

個人的によく使うのは`gcom()`や`mygcre()`です。

gitは作業の流れの中で一連のコマンドを実行しますよね。
それを全て繋げて関数化しています。

「次はなんのコマンドだっけ...」といちいち意識する必要もありません。
うっかりおかしなコマンドを実行する事故も無くなりますね。

## まとめ
シェルを使いこなすと作業効率が段違いですよ。
ぜひ活用してください。
アップルのオープンソース版HomeKitで Lチカ

アップルがHomeKitの開発キットをオープンソース化されたので、早速試してみました。
公式HomeKit Accessory Development Kit (ADK)から、フォークして、ラズパイのGPIO18にピンアサインしています。

## Raspberry Pi 4 4GB
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">NFCタッチでLチカ！動いた！<br>Apple open sources HomeKit with Raspberry Pi <a href="https://twitter.com/hashtag/HomeKit?src=hash&amp;ref_src=twsrc%5Etfw">#HomeKit</a> <a href="https://t.co/WpECgvJ501">pic.twitter.com/WpECgvJ501</a></p>&mdash; Sam Akada@技術書典8(HomeKit技術本) (@sam_akada) <a href="https://twitter.com/sam_akada/status/1208574332282134528?ref_src=twsrc%5Etfw">December 22, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## Raspberry Pi 2 Model B
![IMG_9640.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452335/b3462dc2-5612-2066-7372-3f748854e9f8.jpeg)

## Raspberry Pi Zero WH
![IMG_9652.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452335/6c08e7fe-28a2-4416-7503-2379a68353d9.jpeg)
WiFi設定を手動することで、動作確認できました。ハイスペックなCPUやRAMを必要ないようです。

# 動作環境
- Raspberry Pi 4 4GB(有線LAN接続)
- Raspberry Pi 2 Model B(有線LAN接続)
- Raspberry Pi Zero WH(手動でWi-Fi設定)
- microSD 8GB
- macOS 10.15.1

# ソースコード
https://github.com/SamAkada/HomeKitADK

# セットアップコード： 111-22-333
<img width="703" alt="スクリーンショット 2020-01-01 10.14.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452335/c77f3d1f-a454-e25e-0543-c90c1e1f5fed.png">

# ラズパイへインストール
```
./Tools/install.sh \
    -d raspi \
    -a Output/Raspi-armv6k-unknown-linux-gnueabihf/Debug/IP/Applications/Lightbulb.OpenSSL \
    -n raspberrypi \
    -p raspberry
```
# まとめ
- Siriのレスポンスが良いです。
- 技術書典8向けに[HomePodとHomeKit技術本](https://booth.pm/ja/items/1801723)を書きました。
FortranでUnion-Findモジュールを使う

#FortranでUnion-Findモジュールを使う
この記事ではFortran90でUnion-Find木を使うための知識を共有していこうと思います。
以下のコードは私が実装したUnion-Findモジュールです。機能は初期化(init)、結合(unit)、根の番号を求める(root)を実装してあります。integer(8)を使っているので型に注意してください。1-indexedでの実装です。最後に使用例を載せました。

```fortran
module UnionFind
	implicit none
	public
		type :: Union_Find
			integer(8),allocatable,dimension(:) :: par
		end type Union_Find
	contains
		subroutine init(p,n)
			implicit none
			type(Union_Find)  p
			integer(8) n,i
			allocate( p%par(n) )
			do i=1,n
				p%par(i) = i
			enddo
		end subroutine init
		recursive function root(p,n) result(ret)
			implicit none
			type(Union_Find) p
			integer(8) ret,n
			if(p%par(n)==n)then
				ret = n
				return
			else
				p%par(n) = root(p,p%par(n))
				ret = p%par(n)
				return
			endif
		end
		subroutine unite(p,a,b)
			implicit none
			type(Union_Find) p
			integer(8) a,b
			a = root(p,a)
			b = root(p,b)
			if(a/=b)then
				p%par(a) = b
			endif
		end
end module UnionFind
```
以下で使い方を説明していきます。

###1.useで読み込む
useで読み込むのを忘れないようしましょう。

```fortran
use UnionFind
```

###2.宣言
以下のように宣言するとufという名前のUnion_Find型の変数が宣言されます。

```fortran
type(Union_Find) uf
```

###3.初期化
callでinit関数を呼び出し、ufというUnion_Find型の変数をサイズN(integer(8)型なので注意)で初期化します。初期化は必ず行ってください。初期化は何度でもできます。

```fortran
call init(uf,N)
```

###4.結合
callでunite関数を呼び出し、Union_Find型変数ufのa番目とb番目を結びます。

```fortran
call unite(uf,a,b)
```

###5.根を求める
root関数で、Union_Find型変数ufのa番目の属する集合の根の番号を取得します。返り値はinteger(8)です。

```fortran
root(uf,a)
#　↓使用例
if(root(uf,a)==root(uf,b))then
  処理
endif
```

##最後に
このコードに少し付け足すと、「頂点aの属するクラスタのサイズ」や「最大クラスタのサイズ」なども取得できます。最後に使用例です。
https://atcoder.jp/contests/abc097/submissions/3768108

参考
https://www.slideshare.net/chokudai/union-find-49066733/1
私が課題管理ツールを使う時に気をつけている、たった3つのこと

# はじめに

Merry Christmas！
こちらは [ゆるWeb勉強会@札幌 Advent Calendar 2019](https://adventar.org/calendars/4273) 24日目の記事です。

今回は、課題管理ツール（Redmine、Backlog、JIRA等）を使う時に意識しておくと、ちょっと幸せになれるTipsを3つご紹介します。

それ、Webに関係なくない？というツッコミはご容赦ください。:see_no_evil:

# 課題管理ツールのTips

## 1. ひとつの課題には、ひとつの関心事

![Untitled_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49458/d65f8086-54b4-6cd4-4217-f72a0854dff3.jpeg)

課題を起票するときの「粒度」に悩む方も多いと思います。
いつも私が指針にしているのは、**ひとつの課題ではひとつの関心事しか取り扱わない** という事です。

課題の中でやりとりが続いていくと、「◯◯の件も一緒に対応してください」「そういえば△△はどうなっていたっけ？」など、関心事が増えていったり、他の話題に逸れていくケースをよく見かけます。
そうすると必然的に、課題の内容が埋もれてしまったり、他の課題と内容が重複したり、アウト・オブ・コントロールな状態に陥ってしまいます。

複数の関心事が出てきたら、他の課題に切り出す。重複した内容が出てきたら、元の課題に誘導する。これを意識するだけでも、課題がグッと整理されていきます。


## 2. 完了条件を明確にする

![Untitled_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49458/f557e26c-0adb-5627-aafe-d00a71668396.jpeg)

課題を起票したものの、完了条件が明確になっておらず、いつまでも課題が残り続けてゾンビ化する...という経験はないでしょうか。

完了条件が明確になっていないと、課題がゾンビ化するだけではなく、適切な作業の進め方が判断できない・作業にどのくらいかかるのか見積できない等、たくさんの弊害が生じてきます。課題の引き継ぎなどでも困りますよね。

これは、自分で何かの目標を立てるときに達成基準を決めるのと同じで、 **第三者が見て（=誰が見ても）完了したかどうか判断できる状態にしておく事**が、重要なポイントになります。

## 3. 行間を読まない

![Untitled_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49458/c48a3670-bf3b-f91f-92b7-6ecfa62f9199.jpeg)

課題に書く内容（項目や粒度）は、どうしても人によってバラツキが出てしまいます。
私はできるだけ「5W1H」を明示するよう心がけていますが、時々「例の件、よろしく」レベルのコメントを見かけます。例の件とは...？

相手と長い付き合いになると、阿吽の呼吸でコミュニケーションが取れて「例の件」でも伝わることがありますが、第三者から見ればナニソレ？という状況ですよね。また、勝手に行間を読んでエビデンスを残さずに進めると、いずれ「言った」「言わない」のトラブルになったり、思い込みで進めた結果やり直し！などという事になり兼ねません。とても危険です。

**当事者間には自明な内容だとしても、行間を読まずに、5W1H＋αを課題に明記して、いつでも誰とでも認識合わせできる状態に保っておきましょう。**

# おわりに

以上、課題管理ツールを使う時に意識しておくと、ちょっと幸せになれるTipsを3つ、ご紹介しました。
いかがでしたでしょうか。

適切な課題管理は、健全なプロジェクト運営の第一歩だと思っています。
ぜひツールを上手に活用して、課題管理のプロフェッショナルを目指してください！（私も目指します）
【検証中】複数添付ファイル BCC対応メール送信ロボット

【アルゴリズム】
![aru.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/13d502e6-3b99-6aec-49d5-fb570d29d113.png)

・sendmail.scriptpathname に初期値を指定を指定するが、他にもいろいろ変更したほうがよさそう。

・以下のページと合わせて検証する
https://knowledge.bizrobo.com/hc/ja/articles/360033715371--%E3%83%A1%E3%83%BC%E3%83%AB%E9%80%81%E4%BF%A1-Send-Mail-%E3%82%B9%E3%83%86%E3%83%83%E3%83%97%E3%81%A7-%E6%9C%AC%E6%96%87%E4%B8%AD%E3%81%ABExcel%E3%81%AE%E8%A1%A8%E3%82%92%E8%A8%98%E8%BC%89%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95
https://knowledge.bizrobo.com/hc/ja/articles/360035672532--%E3%83%A1%E3%83%BC%E3%83%AB%E9%80%81%E4%BF%A1-Send-Email-%E3%82%B9%E3%83%86%E3%83%83%E3%83%97%E3%81%AB%E3%81%A6%E8%A4%87%E6%95%B0%E3%81%AE%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E6%B7%BB%E4%BB%98%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95