OmniAICreator/Qiita-1.07M huggingface dataset:
ESLint でパッケージからの import は拡張子不要だが、相対パスからの import は拡張子を必要にする場合の設定

下記のページを読みながら、ESLint で node_modules 下のパッケージからの import (`import express from 'express';`)は拡張子不要で、相対パスからの import (`import Users from './users.js';`) は拡張子必要の設定を試みた。

* [import/extensions - Ensure consistent use of file extension within the import path](https://github.com/benmosher/eslint-plugin-import/blob/v2.17.2/docs/rules/extensions.md
)

最初は以下のように設定した。

```json
{
  "rules": {
    "import/extensions": ["error", "ignorePackages"]
  }
}
```

だが、相対パスの import で拡張子なしのような記載(`import Users from './users';`)でエラーが起きなかった。

前述のページの一番下の**「The following patterns are not considered problems when configuration set to ['error', 'always', {ignorePackages: true} ]:」** の項と、[benmosher/eslint-plugin-import](https://github.com/benmosher/eslint-plugin-import) の [Issue #1083](https://github.com/benmosher/eslint-plugin-import/issues/1083)をみて、以下のように記載したところ、期待する動作を満たせた。

```json
{
  "rules": {
    "import/extensions": ["error", "always", { "ignorePackages": true }]
  }
}
```
【ASP.NET】「JSON リクエストが大きすぎるため、逆シリアル化できませんでした。」の対応

# はじめに
前記事「[【Oracle】クエリパラメータ(バインド変数)を使うとパフォーマンスが悪くなることもあるバインドピーク問題](https://qiita.com/yaju/items/dc0df5f32c0ea1a131b5)」で対応したことで一覧が出るようになり、対象のリストにチェックボックスを付けて送信ボタンをクリックしたところ、通信エラー「HTTP500内部サーバーエラー」となりランタイムエラーとなってしまった。

クライアント上だと正しいエラーが出ないことに気が付き、ホスト上で実行してみると「JSON リクエストが大きすぎるため、逆シリアル化できませんでした。(The JSON request was too large to be deserialized.)」エラーが出ていました。

# 調査
エラー名でネット検索「JSON リクエストが大きすぎるため、逆シリアル化できませんでした。」で下記サイトがヒット。

* [ASP.NET MVCのActionメソッドでのJSONデータの制限](https://blog.nextscape.net/archives/Date/2013/08/3091)
* [ASP.NETでJSON形式のリクエストが「The JSON request was too large to be deserialized」というエラーになる場合の対処方法](https://qiita.com/rryu/items/a3e122ffc29ef6354256)

# 原因
エラーメッセージからするとデータのサイズではなくペイロードの制限（JSONのkeyとvalueのペア数による制限）のようです。

Microsoft セキュリティ更新プログラム MS11-100 によってリクエストに含まれるキー数が最大 1000 に制限されているためです。おそらく多量のキーを含むリクエストを送るDoS攻撃への対策ではないかと思われます。

* [多くのフォーム キー、ファイル、または JSON ペイロード メンバーを含む ASP.NET 要求が例外が発生して失敗する](https://support.microsoft.com/ja-jp/help/2661403/an-asp-net-request-that-has-lots-of-form-keys-files-or-json-payload-me)

今回はPOSTしたJSONデータが多くなったことで、このエラーに引っ掛かってしまった。

# 対応
この上限は、Web.configのappSetting要素に以下の要素を追加することで指定することができます。

```xml:Web.config
<configuration>
　　<appSettings>
　　　　<add key="aspnet:MaxJsonDeserializerMembers" value="100000" />
　　</appSettings>
</configuration>
```

# 最後に
検索すれば情報が見つかるのにあえて書くか迷ったんですが、下記サイトの記事を読んで「ドッグフーディング」しようと書いてみました。

>「あー、これ既にやったことあるなー。なんだっけ？」とググった先が自分のブログであってほしい、そんな思いで書いてみてください。
一番最初の利用者が自分、すなわちドッグフーディングしましょう。
[初めての「技術ブログ」書き方のご紹介](https://blog.soracom.jp/blog/2018/04/18/howto-techblog/)
Go言語 × AWSIoT × Raspberrypi やってみた

前の記事ではRaspberrypiとAWSIoTを通信させる時、サンプルのPythonプログラムで動かしました。
その際、他にも通信をする方法あるのかなと探してみたところ、Goでも出来そうだったので試してみることにしました。
記事自体は環境構築含めたメモ程度に。

# 参考ページ
以下のページを参考にしています。

[golang+MQTTでAWS IoTにPubslish](https://qiita.com/sat0ken/items/249b1f01da4dd2cc5b4f)

[Raspberry PiにGo言語をインストールする](https://qiita.com/Brutus/items/cdf077a4d161bd32a34b)

[AWS IoT × Raspberrypi でやったことメモ](https://qiita.com/ikeponsu/items/99e2d8bf0357314d2bae)


# Raspberrypi側でGo開発環境をセットアップ

Goをインストール。（任意のバージョンで）

```
$ wget https://storage.googleapis.com/golang/go1.9.linux-armv6l.tar.gz
$ sudo tar -C /usr/local -xzf go1.9.linux-armv6l.tar.gz
```
インストール確認とバージョン確認を行う。

```
$ ls -l /usr/local/go
$ cat /usr/local/go/VERSION
```

パスの追加。
~/.bashrcファイル末尾に以下を追記。

```
export PATH=$PATH:/usr/local/go/bin
```
設定したパスの確認

```
$ source .bashrc
$ echo $PATH
$ which go
```

# 必要ライブラリのインストール

```
$ go get github.com/eclipse/paho.mqtt.golang
$ go get golang.org/x/net/websocket
$ go get golang.org/x/net/proxy
```

# ソースコード
今回はお試しなので、参照サイトのものをそのまま使用。
GoPath等の設定は任意で設定してください。
（今回は分かりやすいように、home直下に全ファイル置いた書き方をしています）

__main.go__

```GO
package main

import (
    "crypto/tls"
    "crypto/x509"
    "fmt"
    "io/ioutil"

    MQTT "github.com/eclipse/paho.mqtt.golang"
)

func NewTLSConfig() *tls.Config {
    // CA証明書を設定
    certpool := x509.NewCertPool()
    pemCerts, err := ioutil.ReadFile("xxxxxxxxx.pem")
    if err == nil {
        certpool.AppendCertsFromPEM(pemCerts)
    }

    // クライアント証明書とキーペアを設定
    cert, err := tls.LoadX509KeyPair("xxxxxxxxx-certificate.pem.crt", "xxxxxxxxx-private.pem.key")
    if err != nil {
        panic(err)
    }

    cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
    if err != nil {
        panic(err)
    }

    // config設定
    return &tls.Config{

        RootCAs: certpool,
        ClientAuth: tls.NoClientCert,
        ClientCAs: nil,
        InsecureSkipVerify: true,
        Certificates: []tls.Certificate{cert},
    }
}

var f MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
    fmt.Printf("TOPIC: %s\n", msg.Topic())
    fmt.Printf("MSG: %s\n", msg.Payload())
}

func main() {
    tlsconfig := NewTLSConfig()

    opts := MQTT.NewClientOptions()
    opts.AddBroker("ssl://xxxxxxxxxxxxxxxxxxx.amazonaws.com:8883")
    opts.SetClientID("ssl-sample").SetTLSConfig(tlsconfig)
    opts.SetDefaultPublishHandler(f)

    // 接続をする
    c := MQTT.NewClient(opts)
    if token := c.Connect(); token.Wait() && token.Error() != nil {
        panic(token.Error())
    }
    fmt.Println("AWS IoT Connect Success")

    if token := c.Publish("$aws/things/ESP32/shadow/update", 0, false,
        `{"state":{"reported":{"welcome":"I am gopher!!!"}}}`); token.Wait() && token.Error() != nil {
                panic(token.Error())
    }
    fmt.Println("Message Publish Success")

    // 切断
    c.Disconnect(250)
}
```

# 実行結果
![result.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308887/875deb0d-39e9-1784-8e84-5292efe588c4.png)

<img width="1119" alt="result2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308887/32a1a5a0-d4bd-ca74-a009-634fe097c3d6.png">

こんな感じで通信出来たみたいです。
Goは環境構築楽なので助かります。
Git 基本的なコマンド

# Gitについて、事前に知っておくべきこと

- 現在のプロジェクトファイルがある「Working Directory」。
- Commitした、ソースコードを保存する「Repository」。
- 「Working Directory」と「Repository」間のバッファarea「Staging Area」。
- 「HEAD」は現在のブランチの最新のコミットを意味する。
- 既定のリモートリポジトリは、「origin」。

# 基本的なコマンド

```
git --version   //現在のgitのバージョンを確認
git clone {url} //リモートリポジトリからクローンする
git status      //Localの変更を確認
```

# Log

```
git log            //Commit Logを参照
git log --oneline  //Commit LogのCommit IDを表示
git log --decorate //Commit LogのHEADを明示
git log --graph    //Commit Logを縦グラフで表示
```

# Checkout
```
git checkout [branch]  //ブランチを変更
git checkout -b [branch] //ブランチを作成＆変更
git checkout -b [branch_B] [branch_A] //branch_Aから、branch_Bを作成＆変更
```

# Add
```
git add //ファイルをadd
git add [file]//ファイルをadd

git commit -m “[comment]” //Commit messageを同時に指定
```

# Commit
```
git commit //ファイルをCommit
git commit -m “[comment]” //Commit messageを同時に指定
```

# Push
```
git push  //Repositoryで変更を反映
git push [repository] [branch] //リモートリポジトリに変更を反映
```

# Fetch
```
git fetch //Remote Repositoryの最新データを取ってくる
```

# Pull
```
git pull //Remote Repositoryの変更インポートしてリモートブランチを更新
```

# Reset
```
git reset --soft HEAD^      //commitをcancelして、ファイルは「staged status」で、Working Directoryに保存
$ git reset --mixed HEAD^   //commitをcancelして、ファイルは「unstaged status」で、Working Directoryに保存
$ git reset HEAD^           //commitをcancelして、ファイルは「unstaged status」で、Working Directoryに保存
$ git reset HEAD~2 　       //最後の二つのcommitをcancel
$ git reset --hard HEAD^    //commitをcancelして、ファイルは「unstaged status」で、Working Directoryから削除
```

# Revert
``` 
git revert [commit id]      //commit idのcommitをcancel
```

# Rebase
``` 
git rebase [branch]     //branchにrebaseする
git rebase --abort      //直前のgit rebaseの編集を中止
git rebase --continue   //rebaseを続ける
```

# Merge
``` 
$ git merge [branch]    //現在のbranchを指定したbranchとMerge
```
[Mac]GMT6とGMT4系orGMT5系を共存させる[Homebrew]

GMT中国語コミュニティさんのHPがやってることを殆ど引用させてもらいました。
https://gmt-china.org/blog/install-gmt6/

Homebrewを使って異なるバージョンのGMTを共存させた備忘録です。

##環境
Mac OS Mojave 10.14.5
Mac mini(2018)

##前提条件
Homebrewを導入済み
HomebrewでGMT6を入れているとする[（ここ](https://qiita.com/juror/items/f68adc56d396f5836187)参照）
どうしても新たにGMT5系を導入したいとする

##GMT5系の導入方法
ターミナルで以下を実行します。
GMT6のリンクを外してから、GMT5をインストールするだけです。これでGMT5系が使えるようになります。

```ruby:Terminal
$ brew unlink gmt6 
$ brew install gmt
```

これで`Terminal`から`gmt --version`を入力してみましょう。GMT5系である旨が表示されるはずです。
GMT6に戻りたくなったら、`Terminal`から下記↓の操作を行ってください。

```ruby:Terminal
$ brew unlink gmt 
$ brew link gmt6
```

またまたGMT5系を使いたくなったら、逆の操作を行えばOKです。

```ruby:Terminal
$ brew unlink gmt6 
$ brew link gmt
```

##GMT4系の導入方法
GMT5系の時と殆ど同じですが、GMT4系をインストールした場合はPATHを通す必要があります。
前提条件は`GMT5系の導入方法`と同じく、HomebrewでGMT6が導入されている事とします。

まずはGMT6のリンクを切ってGMT4系を導入します。

```ruby:Terminal
$ brew unlink gmt6 
$ brew install gmt@4
```

インストール自体は成功しますが、下記のような文が吐き出されます。

```ruby:Terminal
gmt@4 is keg-only, which means it was not symlinked into /usr/local,
〜中略〜

If you need to have gmt@4 first in your PATH run:
  echo 'export PATH="/usr/local/opt/gmt@4/bin:$PATH"' >> ~/.bash_profile
```

パスを通せって事らしいので、最後の文章を`Terminal`にコピペしましょう。

```ruby:Terminal
$ echo 'export PATH="/usr/local/opt/gmt@4/bin:$PATH"' >> ~/.bash_profile

$ source ~/.bash_profile  # この代わりにターミナル再起動でも良いです
```

これでGMT4系が使えるようになりました。`gmt --version`を入力して確認してみましょう。

バージョンの切り替えはGMT5系の時と同様です。（gmt→gmt@4に読み替えてください）
ただしGMT4系を入れた状態だと、GMT4系のリンクを切ってGMT6にしても`gmt --version`で反映されませんでした。
まぁこの状態でもPygmt（GMT6が必要）が動いたので、様子見とします。
Reactのversionを上げるためにyarnを実行したらfseventsでERRORが発生した

久しぶりに個人で作っているPortfolioのversionを上げようとしたら`fsevents`が原因でエラーが発生したのでメモ。

`yarn`を実行したら下記のようなエラーが発生する

```
warning Error running install script for optional dependency: "/Users/minusfive/dev/oss/ember-cli-sass-variables-export/node_modules/fsevents: Command failed.
Exit code: 1
Command: node install
Arguments:
Directory: /Users/minusfive/dev/oss/ember-cli-sass-variables-export/node_modules/fsevents
Output:
node-pre-gyp info it worked if it ends with ok
node-pre-gyp info using node-pre-gyp@0.6.39
node-pre-gyp info using node@10.4.0 | darwin | x64
node-pre-gyp info check checked for \"/Users/minusfive/dev/oss/ember-cli-sass-variables-export/node_modules/fsevents/lib/binding/Release/node-v64-darwin-x64/fse.node\" (not found)
node-pre-gyp http GET https://fsevents-binaries.s3-us-west-2.amazonaws.com/v1.1.3/fse-v1.1.3-node-v64-darwin-x64.tar.gz
node-pre-gyp http 404 https://fsevents-binaries.s3-us-west-2.amazonaws.com/v1.1.3/fse-v1.1.3-node-v64-darwin-x64.tar.gz
node-pre-gyp ERR! Tried to download(404): https://fsevents-binaries.s3-us-west-2.amazonaws.com/v1.1.3/fse-v1.1.3-node-v64-darwin-x64.tar.gz
node-pre-gyp ERR! Pre-built binaries not found for fsevents@1.1.3 and node@10.4.0 (node-v64 ABI, unknown) (falling back to source compile with node-gyp)
node-pre-gyp http 404 status code downloading tarball https://fsevents-binaries.s3-us-west-2.amazonaws.com/v1.1.3/fse-v1.1.3-node-v64-darwin-x64.tar.gz
node-pre-gyp ERR! Tried to download(undefined): https://fsevents-binaries.s3-us-west-2.amazonaws.com/v1.1.3/fse-v1.1.3-node-v64-darwin-x64.tar.gz
node-pre-gyp ERR! Pre-built binaries not found for fsevents@1.1.3 and node@10.4.0 (node-v64 ABI, unknown) (falling back to source compile with node-gyp)
node-pre-gyp http Connection closed while downloading tarball file
gyp info it worked if it ends with ok
gyp info using node-gyp@3.6.2
gyp info using node@10.4.0 | darwin | x64
gyp info ok
gyp info it worked if it ends with ok
gyp info using node-gyp@3.6.2
gyp info using node@10.4.0 | darwin | x64

以下略
```

`yarn start`もERRORが発生してしまい、1~6の解決策がyarn側から提示されたがうまくいかなかった。

これは`fsevents`と`Node.js`のversionが対応していないために起こるエラーで、`fsevents`の`v1.2.9`で解決されている。

versionを上げるには`package.json`にて以下のように記述して、`yarn`を実行する。

```package.json
"resolutions": {
  "**/**/fsevents": "^1.2.9"
}
```

これ以外の解決策で見つけたのは以下の通り

- `rm -r /node_modules` => `rm yarn.lock` => `yarn`
- `yarn cache clean` => `yarn upgrade`
- `yarn upgrade`を実行すると解決するといったissueが多かった

fseventsに関する解決策の参考URI: https://github.com/yarnpkg/yarn/issues/5962
クリックイベントを createEvent で発火させると getSelection は取れない

ドキュメントで確認が取れたわけではないけれど、動作確認をするとそのように感じるのでメモ。

例えば以下のように `createEvent` で任意の座標をクリックさせるイベントを発火させる。そしてクリックした位置にあるテキストの Range オブジェクトを取得するために `window.getSelection()` を使う。が、これだと Range オブジェクトは取得できない。

```javascript
const elm = document.getElementById('hoge')

elm.addEventListener('click', () => {
  const sel = window.getSelection()
  sel.getRangeAt(0) // error
})

const evt = document.createEvent('MouseEvents')
evt.initMouseEvent('click', true, true, window, 0, 0, 0, 100, 200, false, false, false, false, 0, null)
elm.dispatchEvent(evt)
```

`createEvent` で発火されたイベントの `isTrusted` は `false` になっている。つまりユーザ自身が能動的に起こしたイベントではない。推測だがセキュリティ的な問題で Range オブジェクトが取得できないのかもしれない。

## 回避策というか普通はこちら

わざわざ `window.getSelection()` を使わなくても `caretPositionFromPoint` / `caretRangeFromPoint` を使えば指定座標の Range オブジェクトが取得できる。

```javascript
if (document.caretRangeFromPoint) {
  const range = document.caretRangeFromPoint(x, y)
  const elm = document.elementFromPoint(x, y)
} else {
  // Firefox は caretRangeFromPoint がないのでこちら
  const pos = document.caretPositionFromPoint(x, y)
  const elm = document.elementFromPoint(x, y)
  const range = document.createRange()
  range.setStart(pos.offsetNode, pos.offset)
}
```
laravel　manp 初期画面　localhost

laravelのインストールしたら
#初期画面を出したいけど上手くいかない時の設定方法
laravelのインストールして、初期画面を出したいけど上手くいかない時

```
localhost
```
とURLを入力しても上手く表示されない場合

manpの設定(preferences...)のWebSeverの中にある、Documents Root を、

```DocumentsRoot
{laravelのディレクトリー}¥public
(例)
C:\MAMP\htdocs\laravel\public
```

と設定すると上手くいく。

上記の例だとLaravelがMAMPの設定上だが本来はあまりお勧めされない。
理由はMAMPを消すとデータが消えるため。
MAMPのバージョンに依存しないフォルダーに保存しておくことが望ましい。
自分用勉強メモ11日目

# 調べた知識

## Pythonで"*"を使用してリストの引数展開

リストを関数の引数に渡すときに，リストの前に"\*"をつけると，中身を展開してから渡すことができる．

- 参考：[Pythonで関数の引数にリスト、タプル、辞書を展開して渡す](https://note.nkmk.me/python-argument-expand/)

リストとタプルの場合は"\*"を，辞書の場合は"\**"をつけると展開できるらしい．

```Python
>>> arg_list = ['a', 'b', 'c']
>>> print(arg_list)
['a', 'b', 'c']
>>> print(*arg_list)
a b c
# print('a', 'b', 'c') と同じ
```
Flutterをやってみた

## TL;TR

1. 公式ドキュメントが充実しているのでそれを読む。
2. 英語については頑張れ。
3. 公式チュートリアルで簡単なページ遷移まで説明してくれるが、複雑なデータ構造とそれに沿ったページ管理は別に勉強する必要がある。(redux…)

## 参考

- https://flutter.dev/
- https://medium.com/flutter-jp/flutter-learning-c5640c5f05b9
- https://techblog.scouter.co.jp/entry/2019/01/30/135004
- https://qiita.com/BingSyu/items/5398e440b22c44aa1927
- https://qiita.com/ko2ic/items/97aeaa4bdbaa6a7e6cbe
- https://shikajiro.github.io/blog/2018/08/24/flutter_mvvm/

## 環境構築

- https://qiita.com/Alex_mht_code/items/493c47bb749edfc8918c

基本的には公式のGet startedの通りにやる。

Mac環境だがHomebrewにはSDKのbrewは無い様子。(2019年5月現在)

### Install

flutter doctorの実行によって、現在の環境の問題点が列挙される。各項を良く読んで対処する。ほとんどの問題は解決方法が記されており、そのまま実行すれば解決する。

```
[!] Connected device
    ! No devices available
```

については、シミュレータなり実機なりがPCに繋がっていないことが原因。なので、

```
% open -a Simulator.app
```

とかして、シミュレータを立ち上げておけば警告は消える。

### Set up an editor

今回はAndroid Studioを使うことにした。
PluginsでFlutter pluginとDart pluginを入れて、IDEを再起動する。
(ついでにFlutter i18n pluginも入れておいた)

### Test drive

サンプルを立ち上げてみる。とりあえず何も指定しなくてもサンプルプログラムが作れる。すぐに実機(今回はAndroid)上でDebugが出来た。
ホットリロード速いなぁ。

## Write your first Flutter app, part 1

https://flutter.dev/docs/get-started/codelab

に書いてあるまま。
最近のSDKはチュートリアルが丁寧だね…

## Write your first Flutter app, part 2

おまけ。

https://codelabs.developers.google.com/codelabs/first-flutter-app-pt2/#0
【Macの方におすすめ】スクショを素早く開く方法

## 【Macの方におすすめ】スクショを素早く開く方法
エンジニアの方であればスクショはよく使う機能だと思います。
このように、Docsの右の方にフォルダをドラッグアンドドロップすると、ダウンロードフォルダのようにDocsからフォルダ内を確認することが出来ます。
<img width="1063" alt="Screen Shot 2019-05-25 at 23.49.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250231/7f4a739d-4765-4751-ad89-75e6340ca83e.png">
そこでスクショを保存するフォルダをDocsの右に配置するのがとてもおすすめです。
便利ですので、ぜひ試してみて下さい。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
roscoreが正常に起動しない

とても久しぶりにROSを起動しようとしてroscoreをコマンドを打ったら


```
... logging to /home/reo/.ros/log/a097bcd8-7ef5-11e9-8bc6-d47bb04d8ebf/roslaunch-reo-FMVWWA27B-23664.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

Unable to contact my own server at [http://192.168.1.38:45611/].
This usually means that the network is not configured properly.

A common cause is that the machine cannot ping itself.  Please check
for errors by running:

	ping 192.168.1.38

For more tips, please see

	http://www.ros.org/wiki/ROS/NetworkSetup

The traceback for the exception was written to the log file
```

とエラーが出てしまった．




解決法としては

.bashrcにある

```
export ROS_MASTER_URI=http://192.168.1.34:11311
export ROS_HOSTNAME=192.168.1.38
```
を変えてやれば良い．

特に別のPCとROSで通信することが無いなら

```
export ROS_MASTER_URI=http://localhost:11311
export ROS_HOSTNAME=localhost
```
とすれば良い．

通信するなら

```
export ROS_MASTER_URI=http://192.168.122.105:11311    (192.168.122.105はマスタのipアドレス)
export ROS_HOSTNAME=192.168.122.100　　　(192.168.122.100は自分のipアドレス)
```

自分のipアドレスは
ifconfig
コマンドで調べるべし．
【Django】モデルのフィールド名リストを取得する

##概要

- Djangoモデル(≒テーブル)に定義しているフィールド名の一覧を取得する
- 確認環境：Windows10、Python 3.7.2

可変長のCSVデータの取り込みに対応したいという動機から、Djangoのモデルに定義しているフィールド名の一覧を取得したくなりました。そのサンプルロジックを記します。

### 1.Modelの内容
ここではサンプルとして、8項目(col1～col8)を持つ「CSVData」モデルを定義しました。


```python:models.py
from django.db import models

class CSVData(models.Model):
    # CSVデータ取込テーブル
    col1 = models.CharField(verbose_name='001(A)列', max_length=254, null=True, blank=True)
    col2 = models.CharField(verbose_name='002(B)列', max_length=254, null=True, blank=True)
    col3 = models.CharField(verbose_name='003(C)列', max_length=254, null=True, blank=True)
    col4 = models.CharField(verbose_name='004(D)列', max_length=254, null=True, blank=True)
    col5 = models.CharField(verbose_name='005(E)列', max_length=254, null=True, blank=True)
    col6 = models.CharField(verbose_name='006(F)列', max_length=254, null=True, blank=True)
    col7 = models.CharField(verbose_name='007(G)列', max_length=254, null=True, blank=True)
    col8 = models.CharField(verbose_name='008(H)列', max_length=254, null=True, blank=True)
```

### 2.フィールド名取得関数
ググった結果、下記の参照リンク先の内容から「_meta API」の「.get_fields()」でフィールドのメタデータが取得できるらしいと分かりました。

 - [Djangoドキュメント Model _meta API](https://docs.djangoproject.com/ja/2.2/ref/models/meta/)
 - [Djangoモデルのフィールドがクラスから消える話](https://qiita.com/tell-k/items/616133d94fc36ad8ba97)


### 3.取得と整形のロジック

次に、views.pyに次のような関数を定義して実行しました。

```python:views.py
from django.views import View
from .models import CSVData

def getfnames(self, models):
        meta_fields = models._meta.get_fields()
        print(meta_fields)  # ※1

        ret = list()
        for i, meta_field in enumerate(meta_fields):
            if i > 0:
                ret.append(meta_field.name)
        print(ret)   # ※2
        return ret
```

### 4.メタデータの確認
printで出力（上記※1）したところ、「meta_fields」には以下の値が入っていました。
(注記：見やすく並べるため、カンマの後ろに改行を加えています）

```
(<django.db.models.fields.AutoField: id>,
 <django.db.models.fields.CharField: col1>,
 <django.db.models.fields.CharField: col2>,
 <django.db.models.fields.CharField: col3>,
 <django.db.models.fields.CharField: col4>,
 <django.db.models.fields.CharField: col5>,
 <django.db.models.fields.CharField: col6>,
 <django.db.models.fields.CharField: col7>,
 <django.db.models.fields.CharField: col8>)
```

### 5.メタデータの分解と、名前の取得
enumerate関数で分解し、「.name」で取得できたフィールド名を１つずつリストに流し込みました。

### 6.取得結果の確認
結果をprintで出力（上記※2）したところ、以下の値が入っていました。

```
['col1', 'col2', 'col3', 'col4', 'col5', 'col6', 'col7', 'col8']
```
以上。
システム構築プロジェクトで要件定義〜リリースまで経験して感じた反省と次のアクション


この記事は、筆者が小売業の業務改善・システム刷新プロジェクトの要件定義から設計・開発・テスト・リリースまで経験して感じた、反省と次のアクションについて雑多に書いたメモである。
※完全自分用メモですが、ほんの少しでも同業の方々のプラスになったらいいなと思い公開しました。


#要件定義
- できれば要件定義前に、顧客の業界を全力でキャッチアップする。
    - 業界本2冊くらい読めばだいぶ詳しくなれるはず。このスタートダッシュは超重要。顧客の業界や業務について何も知らない状態では何も革新的な発想なんてできやしない。少しでも情報があれば、ふとした瞬間の課題に対するアプローチの幅が広がるはず。

- このフェーズでどれだけ顧客と気軽にコンタクトを取れる状況を作っておけるかが、後続フェーズでは鍵となる。


#基本設計

- サブ、チーム間で線を引いて設計してしまった。そのためシステム間で仕様の認識があっていないところがあった。最低でもチームリーダーはシステム間のつながりや仕様を考えた設計を意識しなければならない。システム全体としてあるべきは何か？から逆算して自サブ機能を設計すべき。
  
- リーダー的な役割を担う、システム間のつながりを意識してチーム全体の設計を見るなら、自分でタスクを持たない方がいい。（タスク抱えすぎてボトルネックに。。。）　要件決めまでやって、あとばざっくり設計にとどめてメンバーにパスすべきだった。

- DFD,ERDは縦に線を引いて見てはいけない、他サブ、横のつながりで見ないと。

- DFD,ERDはチーム全体でウォークスルーすべき。
    - SDの中盤でやったけど、その時点では各機能の使用が詰まっていなかった。おそらく、PG入る前とかでもう一回やるべきだった。これをやっておけば、サブ間で仕様の認識齟齬とか、課題を早い段階で見つけることができる。

- 顧客相手に、要件と各機能の設計レベルのウォークスルーをやらなかったこと。
    - プロジェクトリーダーがは、大きなリスクであることを認識し、PGフェーズとかでもやるべきだった。
    - 今後は、SDフェーズ完了後、内部と顧客それぞれで業務要件と付き合わせた設計レベルのウォークスルーをやる。

- 画面を設計するときは、業務パターンを全網羅した設計を考え抜く。
    - 期限的にもタイトだったため、業務オペレーションの考慮漏れの多い設計になってしまった。
    - かっちりと時間内で決められたアジェンダで、ということを意識しすぎると、結果としてあまりいい設計はできないかも。気軽に業務の質問とかできるようにならないと品質上がらない。

- 1機能に要件を詰め込みすぎない、複数のことができるようにしない。
    - 要件を詰めに詰め込んだ画面を設計してしまったことで、機能の難易度が跳ね上がった。スキルのあるメンバーしか開発できない画面になってしまったし、パフォーマンス面の課題も最後まで解決できなかった。
    - 要件を分解して適切な機能分割を提案できるようにならないと。

- SQL考えるときは、各テーブルのレコード件数を意識する。できるだけ駆動表が小さくなるように設計する。

- 画面の検索条件の必須項目設定に関しては、顧客のオペレーションを具体的に想像して、ヒアリングして、パターンにあったように設定する。検索した時に、この条件だとレコードが何件帰ってくるか具体的に想像して設計しないと。
    - サクッと画面モック作って、早めに触ってもらったほうが後の仕様変更のリスクが小さくなる


#開発・単体テスト
- パフォーマンスを意識したSQLを書くように意識する。
    - 駆動表が小さくなるように意識してクエリを書くべし。
    - 具体的にSQL実行時の処理イメージを持ちながら実装するとパフォーマンス良いSQLが作れるはず。

- 機能単体の品質が後続フェーズでは響いてくる。単体テストパターンは省略せず妥協せずやりきって品質を高める。


#結合テスト
- 初めからテストパターンをしぼってはいけない。
    - 初めは全パターン洗い出す。その後に、残りの工数見合いで各テストパターンの実施要否を決めていくのがベスト。全ケース洗い出してかつテストケースの優先順位や色付けをしておくと、どこまでのテストを実施すればどの程度の品質が保証できるのか示すことができる。


#システムテスト
- このフェーズでは、基本的に仕様変更は受け付けてはいけない。
    - このタイミングでの仕様変更はとてもリスクが高い。
    - 仕様変更を対応する場合は、顧客にきちんとリスクを説明した上でお金と時間をいただく。

・システム間の重要なパターンをもれなく検証する。

・あらかじめシステム間結合で怪しそうなところは意識しておく


#リリース直前
- 胸を張って「リリースして問題ない」と言え得るレベルになっているか？ 言えないなら懸念点を名文化する。一人で抱え込まない。プロジェクトメンバーと課題は共有して、一丸となって課題解決に当たる。壁はつくらない。顧客調整が必要な場合は早急に行う。

- 現行システムからの移行を伴うプロジェクトの場合は、移行専任チームが組まれることが多い。このチームには絶対に業務とアプリの仕様に詳しいメンバーが必要。チームにいないなら、積極的に業務・アプリを知っている外部メンバーがフォローしないとリリースやばい。
RaspberryPiのDocker環境構築

久しぶりに環境を再セットアップしたのでメモです。

- Raspberry Pi 3
- Rasbian Stretch with Desktop (2019/April版)
- microsd 32GB

#イメージ書き込み (macos)

昔はNOOBSを使っていましたが、めんどくさくなってきたのでrasbianを直接書き込みます。Liteでも良かったのですが、なんとなくdestop版を入れておきます。

https://www.raspberrypi.org/downloads/raspbian/

Etcherというツールを使っていたのですが、いつのまにか[balenaEtcher](https://www.balena.io/etcher/)という名前に変わり、少し見た目も変わっていました。zipしたままのイメージでも書き込み可能なので便利です。

<img width="912" alt="スクリーンショット 2019-05-25 23.39.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14768/3f127edb-159c-2fb0-83be-779713527dc2.png">

#SSHの起動設定

sshが最初はdisableになっているので、raspi-configからSSHをEnableにします。（Jessieの頃ははデフォルトでenableになってた気がします）

<img width="738" alt="スクリーンショット 2019-05-25 22.32.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14768/35c8a67d-5da9-dac2-6f93-c567e06083c4.png">

設定しないとあとでログインできなくてハマります（自分。

#SSH鍵のコピー

再セットアップの理由がパスワードを忘れたためなので、早めに認証鍵でログインできるようにしておきます。本当はkrypt.coを使いたいのですが、まだ未対応なので。

```ssh-copy-id pi@raspberry```

ssh-copy-id便利ですね。

#監視設定の追加

[mackerel.io](https://mackerel.io/)の監視設定を追加します。５台までならFreeプランで使えます。

[Raspberry Pi を Mackerel で監視する](https://qiita.com/ww24/items/5409aefd87f14beff504)

ほぼここの通りなのですが、バージョンが新しくなっているので最新版（v.0.59.3）をダウンロードします。

```
curl -sL https://github.com/mackerelio/mackerel-agent/releases/download/v0.59.3/mackerel-agent_linux_arm.tar.gz | tar xz
```

これ以外は上記の手順のコピペで設定可能です。

特に落ちてもいいのですが、グラフで出るとステキですよね。

<img width="893" alt="スクリーンショット_2019-05-26_9_27_21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14768/68c6fbc3-a6b2-6fa4-3ecd-907fcd704a76.png">


#Dockerのインストール

だいたい再インストールしたくなるのは環境が壊れたりして初期状態がわからなくなる時なので、今回は最初からdockerを導入しておきます。

```
curl -sSL https://get.docker.com/ | sh
sudo usermod -aG docker pi
sudo systemctl enable docker
```

#その他

最近はDockerでクロスコンパイル環境を作ったりしているため、実機の出番は少ないのですが、やはり検証したい時があるので再構築しておきました。

Dockerが便利すぎて、最近は他の環境もOS側にはあまり入れずに環境はDockerにまとめるようにしています。そのあたりは別記事で。
CircleCI Orbsを用いてGoogle App Engine へデプロイ

# CircleCI Orbs とは何か？
CircleCIの設定(jobやcommand)を共有可能なパッケージにしたもの
以下、[公式ドキュメント](https://circleci.com/docs/2.0/orb-intro/)抜粋
>CircleCI Orbs are shareable packages of configuration elements, including jobs, commands, and executors.

ちなみにOrbsは[ココ](https://circleci.com/orbs/registry/)から検索できる。

# Orbs を使うと何が良くなる？
(思い付くところ)

- パッケージを活用することでき、CIフローの実装スピード向上につながる
- コード量を削減でき、config.ymlのメンテナンス性向上につながる

# 実際に Orbsを使ってみる
今回はシンプルに、[Google Cloud CliのOrb](https://circleci.com/orbs/registry/orb/circleci/gcp-cli)を用いて以下の処理を実装した。
1.GitHubのレポジトリからコードをチェックアウト
2.gcloud CLIの初期化　(GCPのプロジェクトID, Compute Zone, Service Keyの設定。**※環境変数の事前設定要**)
3.Google App Engineへテストアプリをデプロイ

### 環境変数の設定
CircleCIの対象プロジェクトでBUILD SETTING -> Enviroment Variablesにて以下の項目を設定

- GOOGLE_COMPUTE_ZONE
- GOOGLE_PROJECT_ID
- GCLOUD_SERVICE_KEY

### Config.ymlの記述
version情報の直後に以下の内容を記載。
`orbs:
   gcp-cli: circleci/gcp-cli@1.3.0`

CLIの初期化処理は以下の1行のみの追加でOK！
`- gcp-cli/initialize`


Config全体は以下の通り

```config.yml
version: 2.1
orbs:
  gcp-cli: circleci/gcp-cli@1.3.0

jobs:
  build:
    working_directory: ~/repo
    docker:
      - image: google/cloud-sdk:latest

    steps:
      - checkout
      - gcp-cli/initialize
      - run:
          name: Deploy to Google App Engine
          command: |
            gcloud --quiet app deploy app.yaml --version=test

```

実行結果
![ci0525.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234000/c17fda7d-6399-f743-dcf3-33fc919b37df.png)

# 所感
Orbsを利用する前は、GAEにデプロイするため、
環境変数の情報をjson形式で出力し、`gcloud auth activate-service-account` を実行。
`gcloud --quiet config set project`でプロジェクトIDの設定を行っていた。
上記の内容が`- gcp-cli/initialize`の1行でできるのはとてもうれしい。

今後はできるだけOrbsを活用することで、configファイルをシンプルに保ちながら、CI/CDの品質・スピードを高めることができそうだ。


# その他参考にしたサイト
https://circleci.com/docs/2.0/using-orbs/
【Spring】bindingResultを手動で操作する。

#やること
 - BindingResultをController側で操作する際のコードを書く。
 - 本当は自作のバリデータを用意すべきだが、納期的に厳しいので。

# エラーを追加する。
```java
    // フィールドのエラーを表し、Formクラス名，フィールド名，エラーメッセージを渡す。
    // getObjectNameではフォームクラス名が取得できる。
    FieldError fieldError = new FieldError(bindingResult.getObjectName(), "fieldName", "エラー");
    
    // エラーを追加する。
    bindingResult.addError(fieldError);
```

# エラーメッセージを取得する。
```java
    public String addAllErrors(BindingResult result) {
        String errorMessages = "";
        for (ObjectError error : result.getAllErrors()) {
            // ここでメッセージを取得する。
            errorMessages += error.getDefaultMessage();
        }
        return errorMessages;
    }
```

# アノテーションなしに行ったすべてのエラーをBindingResultに追加する。
```java
	public static BindingResult addAllErrors(BindingResult bindingResult, Map<String, String> errorMap) {
		for (Map.Entry<String, String> entry : errorMap.entrySet()) {
			FieldError fieldError = new FieldError(
                           bindingResult.getObjectName(), entry.getKey(), entry.getValue());
		    bindingResult.addError(fieldError);
		}
		return bindingResult;
	}
Unixmen #1

最近、英語を扱う力の低さに嫌気が指し、勉強をはじめました。
でも、単語の勉強とかだと、辛いだけなので、
英語の記事を速読しよう！と決意しました。

完全に自己満足で、Outputしようと思います。
なお、記事は最新ではないです。

# Learn file management command line required for RHCSA
https://www.unixmen.com/learn-file-management-commnad-line-required-rhcsa

RHCSAにおけるFHS(Filesystem Hierarchy Standard)に関する記事です。
FHSは、[Wikipedia](https://ja.wikipedia.org/wiki/Filesystem_Hierarchy_Standard)に詳しくのっていますね。
あんまり、深掘りすることはなかったですね。

# Install Apache OpenMeetings On CentOS 6.5
https://www.unixmen.com/install-apache-openmeetings-centos-6-5/
Apache OpenMeetingsをインストールして使ってみよう、という記事です。
OpenMeetingsは使ったことがないのですが、簡単に言うと、
オープンソースのテレビ会議、Web配信システムみたいですね。
記事タイトルはCentOS 6.5ですが、
公式ページの最終更新日が2019/03/29だったので、
まだまだ現役みたい。(Flash使っているから、いつまで現役扱いするのか微妙・・・)

すごく多機能そう。日本語にも対応してる。
[このサイト](https://blog.scimpr.com/2014/04/29/apache-openmeetings%E3%81%A7%E3%82%AA%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E3%83%93%E3%83%87%E3%82%AA%E4%BC%9A%E8%AD%B0%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/)が詳しかった。

ただ、インストールのめんどくささと、メンバに使わせる決意が必要そうですね。
と思ったら、dockerイメージ落ちてた。インストールは瞬殺ですね。
https://hub.docker.com/r/fjudith/openmeetings/

普通に開発するだけなら、巷のコミュニケーションツール(slackとか)で十分じゃね？という印象。


# Speed Up WordPress Using Redis And Varnish On Ubuntu
https://www.unixmen.com/speed-wordpress-using-redis-varnish-ubuntu/
WordPressをvarnish(HTTPアクセラレータ)とredis(NoSQL)で高速化しちゃおうぜ！って記事です。
vanish使ったことない。[この記事](https://qiita.com/koudaiii/items/6a0efa024842cd48e2fb)見て、勉強になりました。

言わずとしれた、NoSQLですね。仕事では使ったことないですが・・・
[この記事](https://qiita.com/gold-kou/items/966d9a0332f4e110c4f8)見て、勉強になりました。

# おしまい
macでFinderのみに見えないファイルを作る

## 動機

皆さんは作業していて、このフォルダ邪魔だなと思うことありませんか？

例えば、

 `~/Pictures/写真ライブラリ.photoslibrary` や `~/Music/iTunes` のようなシステムフォルダや

それ以外もClipStuidoPaintが作る`~/Documents/CELSYS`のエイリアスのような、

サードパーティ製アプリが作る名称変更不可のファイル・フォルダはあると思います。

（クリスタを責めているわけではない）



そんな時にシステム上では一切の変更を与えず

（`ls`コマンドや`FileManager`などでのアクセスに関してはそのままで）

Finderのみから見えなくなる方法があったので、ここに書きます。



## 手法

`chflags`というLinuxのファイルフラグをいじるコマンドを使います。

目的のパスに対して

```shell
chflags hidden 目的のパス
```

とするとファイルが不可視になります。

しかし、`ls`  を実行した場合はそのまま表示されます。



今度は目的のパスに対して

```shell
chflags nohidden 目的のパス
```

とすると不可視ファイルが出現します。



その他も

```
chflags -h hidden エイリアスのパス
```

とするとエイリアスが消失します。



その他も色々とWindowsのファイルシステムのようにいじれるので、

使ってみると便利かもしれません。
GCP Stackdriver Agent 起動が失敗するケース Marketplace 経由で作成したVMは注意

[@koshi_life](https://twitter.com/koshi_life) です。

最近 Stackdriver Monitoring を使い始めました。

[公式ガイド](https://cloud.google.com/monitoring/agent/install-agent?hl=ja)に従い、GCE VMインスタンスにAgent導入したが、メトリクスが送信できたインスタンス、されないインスタンスがあり、ハマったので備忘です。

# 事象

GCEのVMインスタンスに手順通り、Monitoring Agentをインストールしたが、メトリクスが送信されていないインスタンスがあった。

# Monitoring Agent のログ

Agentのインストール時に関連ログは `/var/log/syslog` に吐かれると出力されたので確認した。[^1]

[^1]: 2019/05/24にDebian系のディストリビューションにインストールした時の振る舞い。

```/var/log/syslog

May 24 06:04:07 {VM_NAME} systemd[1]: Starting LSB: start and stop Stackdriver Agent...
May 24 06:04:07 {VM_NAME} stackdriver-agent[26346]: mesg: ttyname failed: Inappropriate ioctl for device
May 24 06:04:07 {VM_NAME} stackdriver-agent[26346]: Starting Stackdriver metrics collection agent: stackdriver-agentDisabled via metadata ... (warning).
May 24 06:04:07 {VM_NAME} stackdriver-agent[26346]:  (warning).
```

>Starting Stackdriver metrics collection agent: stackdriver-agentDisabled via metadata ... (warning).

この１行に注目すると、Agentサービスの起動に失敗していることが判明。

# 原因

>[エージェントのインストールのトラブルシューティング](https://cloud.google.com/monitoring/agent/troubleshooting?hl=ja)より
>
>再起動に失敗し、ログ出力に「Disabled via metadata」と表示されている場合、Cloud Marketplace からのイメージを実行している可能性があります。Cloud Marketplace では Monitoring エージェントがデフォルトで無効になっています。
>
>エージェントがメタデータによって無効化されている場合は、エージェントを再インストールしてください。

当該インスタンスは Cloud Marketplace を使って作成したインスタンスだったので、まさにこれだった。

# 対応

- 当該インスタンスの詳細画面で `Stackdriver Monitoring API`の権限設定を確認。無効になっていたので、書き込み権限を付与した。  
<img width="400" alt="Screen Shot 2019-05-25 at 22.30.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51734/568064ca-f97a-e93d-c401-b2f38fec4846.png">
- Stackdriver Agent を再インストール

これでAgentから各種メトリクスがStackdriverコンソールで確認できるようになり解決しました。

GCPはドキュメントが充実していますね。有り難いです。
VMware ESXi 上仮想マシンの日付をホストと同期させる。

[この環境で](https://qiita.com/sicksixrock66/items/d96e74da1bcd382208ff)VMware ESXi 6.7.0 Update 2をインストールしハイパーバイザーで仮想マシンを建てていたが、ゲストOS（仮想マシン）の日時がホストマシンとうまく同期されずに困ったのでメモ。

#環境
ホスト:VMware ESXi 6.7.0 Update 2
ゲスト:Windows10 Pro
　　　 Red Hat Enterprise Linux 8

※VMware Toolsをそれぞれインストール済み。

#事象
何も考えずそれぞれのOSデフォルトインストーラで仮想マシンをインストールすると
ホストとゲストOSの時間が１２時間ぐらいずれていた。。。
検証時にログを取得する際のタイムスタンプずれの問題やそもそも気持ち悪いのでどうにか直したかった。

#修正方法
調べると[こちらの記事](https://qiita.com/ine1127/items/edb0a46b638265186650)や[こちらの記事](https://go-journey.club/archives/3887)があったので参考に修正してみる。

#BIOSの時刻がずれてる説
そもそもホストのBIOS時刻がずれているのでゲストマシンの時刻が変に同期されているかも？
と思ってBIOSを確認。なぜか１時間だけ時間がずれていたので修正。（でも１２時間とか大幅にずれているわけではない）

#VMware Toolsによる時刻同期がうまくできていない説
ESXiからVMware Toolsの設定を確認する。
![スクリーンショット 2019-05-25 22.15.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257241/0bdd750a-affe-e751-fd0e-3f44ec70beb4.png)
どうやらデフォルトだと	”ホストとゲスト時間を同期”の項目が有効じゃないぽい。
有効にして仮想マシンを再起動にして解決じゃん！と思ったらWindows１０側が同期されない。。。

#VMwareのナレッジを確認
NTPサーバを建てるのが必須？とか思いましたが
VMwareのナレッジを確認します(~~最初からそうするべきなのでは~~)
[ゲスト OS とホスト OS 間の時刻同期の構成](https://docs.vmware.com/jp/VMware-vSphere/6.0/com.vmware.vsphere.vm_admin.doc/GUID-C0D8326A-B6E7-4E61-8470-6C173FDDF656.html)


>時刻同期の発生後、VMware Tools は 1 分に 1 回ゲスト OS の時計がホストの時計に一致しているかどうかを確認します。一致していない場合は、ゲスト OS の時計がホストの時計と一致するよう同期がとられます。
ゲスト OS の時計がホストの時計より遅れている場合、VMware Tools はゲストの時計を進めてホストの時計と同じになるようにします。ゲスト OS の時計がホストの時計よりも進んでいる場合、VMware Tools は両方の時計が同期するまで、ゲストの時計が進む速度を遅くします。
Linux および Mac OS X 用の NTP （Network Time Protocol） や、Windows 用の Win32Time （Microsoft Windows Time Service） といったネイティブの時刻同期ソフトウェアは通常、VMware Tools の定期的な時刻同期よりも正確であるため、それらの使用が推奨されます。

つまりNTP建てるのがベターだけどホストの時計にVMware Toolsが合わせてくれる方法でもOKらしいです。

#VMware Toolsで時刻同期させてもずれる？？
解決したかと思いましたが時刻が同期されてもしばらくすると半日ぐらい時間がずれてしまう事象が発生。。。
[調べるとこういう記事](https://server.etutsplus.com/vm-clock-synchronization-trouble/)が出てきましたので時刻を同期させたいならNTPサーバは必須ぽいです。（そもそも商用環境でNTPサーバが存在しないってほぼほぼないような気がしますが、、、）

#インターネットに出ていけるならOS側で公開NTPサーバと同期させれば解決
今回の場合はNTPサーバ建てずにVMware Toolsの時刻同期を解除して
nictとかの公開NTPサーバに時刻をゲストOS側で同期させることで解決しました。
MacからOculusQuestの内部ストレージにアクセスする

# MacでOculusQuestの内部ストレージにアクセスする
どうやらOculusGoと同じ方法らしい。
## MacとOculus本体をUSB接続する
USB-C搭載のMacならOculus付属のケーブルで直接接続できる。
非搭載のMacは別途ケーブルを購入してください。
(USB-AからUSB-Cへの変換ケーブルは規格違反なので使い方には要注意)
接続したらOculus本体から内部ストレージへアクセスを許可する。
## Android File Transferをダウンロード
以下のリンクからAndroid File Transferをダウンロード。
[Android File Transfer](https://www.android.com/filetransfer/)

## Android File Transferを起動する
<img width="691" alt="スクリーンショット 2019-05-25 22.17.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197222/afd95b08-8120-9ce4-3a66-41ba153d8e70.png">
起動すると勝手にマウントされるので、撮ったスクリーンショットをMacへ保存したりできる。
ちなみに、スクリーンショットはOculusというファイルを開きScreenshotsへ保存されている。
録画した動画はOculus → VideoShotsだ。

### あとがき
初投稿です。
OculusQuestを買ってプレイ動画を共有したかったのですが、本体からはオンラインストレージ等にアップロードできない仕様だったので同じような境遇に陥ってる人がいるのではないかと投稿した次第です。
もしかするとアップロードできるのか？アップロードできるなら教えてください。
よろしくおねがいします。

### 参考にさせてもらったサイト
https://ipod.item-get.com/2018/05/vroculus_gousb.php
Node.jsでニュース記事をWebスクレイピングしてみよう

今回はNode.jsでニュース記事をWebスクレイピングをやってみたので共有します。

## ゴール
「ニュース一覧から本日投稿された記事のタイトルと内容をCSVファイルに出力する」
を実現するにあたり、以下の流れで行います。
ニュース一覧ページにアクセスする
↓
一覧ページに掲載されている記事に対して詳細ページのURLを取得する
↓
各記事に対して投稿日が本日のものである場合、記事詳細ページからタイトルと本文を取得する
↓
取得した記事情報をCSVに出力する

## 事前準備
今回は以下のライブラリを使用しました。
・ request-promise
リクエストを非同期で送信してくれるライブラリ
・ cheerio
取得したHTMLサーバー上でjQueryのようにHTML要素を加工できる。Seleniumのようなブラウザではなく、どちらかというとPhantomJSに似た類のもの
・ csv-writer
取得したデータをCSVに書き込むことができる
・ moment.js
JavaScriptの`Date`オブジェクトをラップするオブジェクトを生成して、そのオブジェクトに日付処理を任せることが出来る。記事の投稿日を比較するために使用する

また、スクレイピングする際は事前にそのサイトの構造について調査する必要があります。

## 実装方法
まず各ライブラリを以下コマンドでインストールします。

```bash
npm install --save request request-promise cheerio csv-writer moment
```
次にjavascriptファイルを作成して、流れに沿ってプログラムを記述します。

```index.js
const rp = require('request-promise');
const cheerio = require('cheerio');
const createCsvWriter = require('csv-writer').createObjectCsvWriter;
const moment = require('moment');

const csvWriter = createCsvWriter({
  path : './file.csv',
  header : ['date', 'title', 'context']
});

async function scrapePage() {

let records = [];　// CSV出力対象の記事
let date;
let title;
let context;

// 記事一覧画面のURL
const url = 'http://www.example.com'; // 必要に応じて書き換える

// 記事一覧画面のHTMLを取得する
html = await rp(url);
$ = cheerio.load(html);

// 記事詳細URLを取得、なければ終了する
const postUrls = $('#news', 'a').attr('href');  // 必要に応じて書き換える

if(!postUrls) {
    console.log('記事URLが見つかりませんでした');
    return;
}
// 各記事詳細のHTMLを取得
postUrls.forEach(postUrl => {
    html = await rp(postUrl);
    $ = cheerio.load(html);

    // 各投稿に対してHTMLから日付(YYYY/MM/DD)を取得
    date = $('.date').text();　// 必要に応じて書き換える

    // 投稿日が当日かどうかチェック
    if(new Date(date).getDate == new Date().getDate) {
        /* 取得した日付が当日のものであれば以下を取得
        2. タイトル
        3. 内容（複数の要素で構成されていれば結合）
        */
        title = $('.title').text();　// 必要に応じて書き換える
        context = $('.context').text();　// 必要に応じて書き換える
        
        // CSV出力対象に追加
        records.push({
            'date' : date,
            'title' : title,
            'context' : context,
        });
    }
});
console.log(records);

// CSVに出力する
csvWriter.writeRecords(records).then(() => console.log('Done'));
};

scrapePage();
```

あとは以下コマンドでプログラムを実行するだけです。

```bash
node index.js
```

## 補足
上記のコードはこれでも動作はしますが安全でありません。例えば

```js
html = await rp(postUrl);
```
ですがエラーハンドリングが行われていません。今後このような書き方は非推奨になるので

```js
html = await rp(postUrl).catch(() => console.log('エラーが発生しました'));
```
といった感じに書き直すといいでしょう。
Scala.jsのCIでの複数バージョンビルドの方法

Scala.jsのバージョン1.0がいつリリースされても良いように0.6系と1.0系でCIで確認をしたい。

しかし、Scala.jsはsbt pluginでScala.jsのバージョンを指定することになるので、同一のsbtセッションで複数のバージョンが扱えない。

scala-js-domでは`sbt-scalajs`のバージョンを環境変数 SCALAJS_VERSION で切り替え可能にし、CIで両バージョンでビルドするようになっていた。一応、これで目的は達成できそうである。

参考 https://github.com/scala-js/scala-js-dom/commit/a37bdc56fe250c42b497bee8b195305e3b6d2393#diff-ff7d8159fb5e896132e441a18d319f80
なぜデザインパターンが必要なの

# デザインパターンとは
過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものであるーby [デザインパターンwiki](https://ja.wikipedia.org/wiki/デザインパターン_(ソフトウェア))。要するに、コーディングにおいて定石となる手法をパターン化したものです。 

# なぜデザインパターンが必要なの
デザインパターンを活用することで、よいコードを書くことができます。（機能の実現だけでわなく、読みやすく保守しやす）

## 保守しにくいコード例
```js
var makeSound = function( animal ){
  if ( animal instanceof Duck ) {
    console.log( 'ガアガア' );
  } else if ( animal instanceof Chicken ) {
    console.log( 'ピョピョ' );
  }
};

var Duck = function(){};
var Chicken = function(){};

makeSound( new Duck() ); // ガアガア
makeSound( new Chicken() ); // ピョピョ
```

この例で、鴨と雛の鳴き声を出せるようにしました。
また他の動物を追加する時に(例えばいぬ)、makeSound()はこうなります：

```js
var makeSound = function( animal ){
  if ( animal instanceof Duck ) {
    console.log( 'ガアガア' );
  } else if ( animal instanceof Chicken ) {
    console.log( 'ピョピョ' );
  } else if ( animal instanceof Dog ) { // 追加する部分
    console.log( 'わんわん' );
  }
};
```
他の動物を追加する時に、makeSound()に修正をかけないといけないことになっちゃいます。既存のコードを修正すればするほど、バグになる確率が高くなります。

## 保守しやすいコード例
```js
// 不変部分
var makeSound = function( animal ){ 
  animal.sound();
};

// 可変部分
var Duck = function(){}
Duck.prototype.sound = function(){
  console.log( 'ガアガア' );
};

var Chicken = function(){}
Chicken.prototype.sound = function(){
  console.log( 'ピョピョ' );
};
makeSound( new Duck() ); // ガアガア
makeSound( new Chicken() ); // ピョピョ
```
この例で、どんな動物でも共通的な「鳴き声を出せる」部分を隔離させ、各動物によって別々の鳴き声をそれぞれをカプセル化することで、他の動物を追加しても、既存ソースの編集が要らなくなります。

### デザインパターンと保守しやすいコードの関連性
保守しやすいコードの方法論は**不変部分を隔離させ、可変部分をカプセル化**ということです。
どんなデザインパターンでも、上記の目標を達成するためのベストプラクティスであることです。

# まとめ
なぜデザインパターンが必要なのかを簡単にまとめてみましたが、コーディング中にデザインパターンを意識しなくても「不変部分を隔離させ、可変部分をカプセル化」さえを常に意識できれば、より良いコードを書けるかと思います。
mecab インストール時に "Could not symlink" と表示された場合の対処法

#はじめに
仕事にて自然言語処理の案件に配属となり、「とりあえず自然言語処理と言えば、mecabでしょ！」と思いインストールをしたところ、エラーにつまづいたので、備忘録として投稿します。

# 問題："Could not symlink ●●"というエラーにつまづいた
まずはmecabを下記の通り実行しインストールをしました。
※brewの使い方は別途ググってください。

```
$ brew install mecab
```

すると下記エラーが発生し、mecabと入力をしても実行することができませんでした。

```
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink include/mecab.h
/usr/local/include is not writable
```

そしてこの問題の原因は、フォルダを確認したところ/usr/local内にincludeのフォルダが無く、またその権限も無いということが判明しました。

#解決：(1)フォルダの作成 (2)アクセス権限の付与
よって下記2点を実施することで解決ができました。

(1)フォルダの作成 （/usr/local 内に include フォルダの作成）

```
$ cd /usr/local
$ sudo mkdir /include
```

(2)アクセス権限の付与
※usernameにはご自身の登録されているusernameを入力してください。

``` :/usr/local
$ sudo chown -R username:admin include
```

上記により無事に解決ができたので、mecab-ipadicという辞書をインストールすることで、mecabを実行することができました！

```
$ brew install mecab-ipadic
$ mecab
今日は良い天気だ

今日	名詞,副詞可能,*,*,*,*,今日,キョウ,キョー
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
良い	形容詞,自立,*,*,形容詞・アウオ段,基本形,良い,ヨイ,ヨイ
天気	名詞,一般,*,*,*,*,天気,テンキ,テンキ
だ	助動詞,*,*,*,特殊・ダ,基本形,だ,ダ,ダ
EOS

```

20分近く格闘しましたが、解決するとスッキリしますね。これで自然言語処理の勉強ができる。。

#参考文献
下記サイトを参考に解決ができました。ありがとうございます！
https://blog.kozakana.net/2018/09/homebrew_link_error/
http://kawatama.net/web/1510
VisualStudioCodeでGoogleAppsScriptを補完機能を使いながら開発する方法

#概要
通常サーバー側でスクリプトを保存・管理している GoogleAppsScript をローカルで開発するための連携ツール [clasp](https://github.com/google/clasp) を使用して、ローカルにインストールした VisualStudioCode で GoogleAppsScript を書く。
オンラインのスクリプトエディターとなるべく環境を合わせるために、**あえて TypeScript からのトランスコンパイル機能は使わない。**

※2020/02/13 追記
Google Apps Script 側で V8 ランタイムを使用することができるようになったため、TypeScript を使用しなくても ES6 以降の仕様に準拠したスクリプトが書けるようになった。

#準備
- 以下をあらかじめインストールしておく
 - [VisualStudioCode](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)
 - [Node.js](https://nodejs.org/ja/)
- スクリプトを保存するためのディレクトリを作成しておく<br>コマンドラインで操作するのでユーザーディレクトリ内にしておくと後で楽

#clasp のインストール
コマンドラインを開き以下のコマンドを実行する。
(npm は Node.js 付属のライブラリー管理ツール)

```
npm install -g @google/clasp
```

インストールが完了したら、以下のコマンドを実行して Google にログインの上で、 clasp との連携を許可しておく。

```
clasp login
```

#連携のための設定
コマンドラインであらかじめ作成しておいたスクリプト保存用フォルダーに移動する。

```
cd gas
```

プロジェクト用のディレクトリを作成する。

```
mkdir test
cd test
```

VisualSudioCode で GoogleAppsScript 固有クラスの補完を行うために TypeScript 用の型定義ファイルを追加する。

```
npm init -y
npm install -S @types/google-apps-script
```

GoogleAppsScript のプロジェクトを作成する。
--rootDir オプションを使用することでスクリプト本体の保存先ディレクトリをプロジェクトの設定ファイルなどから分離することができる。

```
clasp create --rootDir ./src test
```

ただし、--rootDir オプションが正常に動作しないことがあるため、その場合には手動で設定する必要がある。

**【手動設定】**
プロジェクトフォルダー内の appsscript.json を対象のディレクトリーにコピー。

```
mkdir src
mv appsscript.json ./src
```
更に .clasp.json の内容をエディターを使用して以下のように編集する。

```text
{
    "scriptId":"スクリプトID",
    "rootDir": "./src"
}
```

プロジェクト自体はこれで作成が完了するが、一度 Web ブラウザでプロジェクトを開かないとサーバー側にデフォルトのスクリプトファイルが生成されない模様。
以下のコマンドで Web ブラウザでプロジェクトを開くことが可能。

```
clasp open
```

#clasp による同期
####サーバー上のスクリプトをローカルにダウンロードする
コマンドラインでプロジェクトフォルダーに移動した状態で以下のコマンドを実行する。

```
clasp pull
```

####ローカルのスクリプトをサーバーにアップロードする
コマンドラインでプロジェクトフォルダーに移動した状態で以下のコマンドを実行する。

```
clasp push
```

#作成済みのプロジェクトをローカルで開発したい場合
clone することで作成済みのプロジェクトをローカルにダウンロードして紐つけることも可能。

```
clasp clone --rootDir ./src スクリプトID
```

#V8 ランタイムの使用 (2020/02/13 追記)
V8 ランタイムを使用したい場合は appsscript.json に「"runtimeVersion": "V8"」を追加する。
なお、clasp で新規作成したプロジェクトでは、タイムゾーンが「"America/New_York"」に設定されている場合があるため、こちらも修正しておくと良い。
appsscript.json 修正後は、clasp push でサーバー側に内容を反映させる必要がある。

```text
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}
```

#Windows 環境において PowerShell で clasp コマンドを使用する際の注意点 (2020/02/13 追記)
PowerShell では clasp.ps1 というスクリプトファイルによって clasp コマンドが提供されている。
PowerShell の初期設定ではセキュリティポリシーにより、スクリプトファイルの実行が許可されていないため、clasp コマンドを使用するためにはスクリプトファイルの実行を許可する必要がある。
**※セキュリティポリシーの変更を伴うため、実施には細心の注意を払う必要がある。**

####PowerShell でのスクリプトファイルの実行の許可
PowerShell を管理者権限で起動し、以下のコマンドを実行する。

```text

Set-ExecutionPolicy RemoteSigned
```

#開発
VisualStudioCode で clasp を使って準備したスクリプトを開くと読み込んだファイルが通常の .js ファイルでも types/google-apps-script の型定義を読み込んで GoogleAppsScript 固有クラス等の補完を行ってくれる。非常に便利。

~~なお、clasp は TypeScript のトランスコンパイルに対応しているので、モダンな環境で開発したスクリプトを GoogleAppsScript 仕様に変換してアップロードすることも可能となっている。
ローカルメインの開発を考えるのであれば TypeScript を使用する方が多いかと思われる。~~ (2020/02/13 修正)

#参考
[GAS のGoogle謹製CLIツール clasp](https://qiita.com/HeRo/items/4e65dcc82783b2766c03)
[Google Apps ScriptsでTypescriptが超簡単に使えるようになった！](https://tech.actindi.net/2018/09/10/083314)
VBSからPowerShellへ　(4)配列

```vb
'VBSで配列の例
Dim singouArr(3)
singouArr(0) = "red"
singouArr(1) = "yellow"
singouArr(2) = "green"
```


```powershell
#PowerShellで配列の例
$singouArr = @(1..3)
$singouArr[0] = "red"
$singouArr[1] = "yellow"
$singouArr[2] = "green"
```
【Spring】自作バリデーションの作成

#やること
2項目間の値の一致チェックを行うバリデーションクラスを作成する。


#はじめに
バリデーションを実装する場合は、
 - バリデーションの対象に宣言する「アノテーション」
 - 「アノテーション」に対してのチェック処理を行う「バリデータ」が必要。

## アノテーション
```java:CompareEquals.java
/**
 * ２項目の値の一致チェックを行う。
 */
@Constraint(validatedBy = {CompareEqualsValidator.class})
@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CompareEquals {

	//　バリデーションを実装する際の必須定義。
    Class<?>[]groups() default {};
    Class<? extends Payload>[] payload() default {};
    
    String value1();
    String value2();
    String message();
    
    @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface List {
    	CompareEquals[] values();
    }
}
```

 - @Constraint(validatedBy = {CompareEqualsValidator.class})でバリデータクラスを指定する。
 - groups, payloadは必須項目。省略した場合は、下記例外が発生する。<br>
   `javax.validation.ConstraintDefinitionException: HV000074: com.example.demo.com.annotation.CompareValue contains Constraint annotation, but does not contain a payload parameter.`


## バリデータクラス
```java:CompareEqualsValidator
/**
 *  ２つのパラメタの一致判定を行う。
 */
public class CompareEqualsValidator implements ConstraintValidator<CompareEquals, Object> {

	private String value1;
	private String value2;
	private String message;

	/**
	 * 初期化処理
	 */
	@Override
	public void initialize(CompareEquals annotation) {
		//　アノテーションの引数情報を設定する。
		this.value1 = annotation.value1();
		this.value2 = annotation.value2();
		this.message = annotation.message();
	}

	/**
	 * 比較処理
	 */
	@Override
	public boolean isValid(Object value, ConstraintValidatorContext context) {

		// 2つの値を取得して比較する。
		BeanWrapper beanWrapper = new BeanWrapperImpl(value);
		Object value1 = beanWrapper.getPropertyValue(this.value1);
		Object value2 = beanWrapper.getPropertyValue(this.value2);

		//　比較処理
		//　同値でも型が違う場合はfalseを返却する。
		boolean matched = ObjectUtils.nullSafeEquals(value1, value2);

		if (matched) {
			return true;
		}

		//　メッセージを設定する。
		context.disableDefaultConstraintViolation();
		context.buildConstraintViolationWithTemplate(message).addPropertyNode(this.value1).addConstraintViolation();
		return false;
	}
}
```
 - ObjectUtils.nullSafeEqualsはSpringのUtilityクラス
 - isValidの引数valueにはFormクラスが渡される。
 - beanWrapper.getPropertyValue()で誤ったフィールド名を渡した場合は下記例外が発生する。<br>
 `org.springframework.beans.NotReadablePropertyException: Invalid property 'aaa' of bean class [com.example.demo.app.form.TestForm]: Bean property 'aaa' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
`
エッジを近似

# はじめに
　某KEY***E社の画像検査装置などにはトレンドエッジと
いうエッジを回帰直線として検出する機能があったりします。
OpenCVでもエッジを近似した直線として扱いたい。

# 課題
画像中エッジの回帰直線を求めてみます。

##サンプル画像
![test_hline4_sd2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391380/e12338d9-bf6a-336d-fe79-1a4adb987aab.png)
画像は作成。ノイズは標準偏差2.0で発生。

# 手順
・2値化
・Cannyエッジ検出実行後に画像の端に余計なエッジが出てしまうので、
　それを避けるため、画像端より2画素をマージンとし、その内側を処理対象とします。
・Cannyエッジ検出を実施、エッジ座標を回帰分析します。
・回帰分析については、他に多数説明するWebページがございますので
　そちらを参照下さい。

・直線式　<math xmlns="http://www.w3.org/1998/Math/MathML"><mi>y</mi><mo>=</mo><mi>a</mi><mi>x</mi><mo>+</mo><mi>b</mi></math>

　上記式の回帰分析を行い、a傾き, b切片を求めます。
　numpyのpolyfit()で回帰計算をします。これについても他に
　多数説明があるため、そちらを参照して下さい。

# 実行環境
　・Python 3.7.3　 Anaconda 
　・OpenCV 3.4.1
　・numpy 1.16.3

# コード

```python:hline.py
import cv2
import numpy as np


def main():
    # 入力画像の読み込み
    img = cv2.imread("images/test_hline4_sd2.png")
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ret, bin0 = cv2.threshold(gray, 128, 255, cv2.THRESH_BINARY)

    height = img.shape[0]
    width = img.shape[1]

    # エッジ画像取得
    edgcanny = cv2.Canny(bin0,50,100)
    edgimg = np.zeros(bin0.shape, dtype=np.uint8)
    sp = 2
    edgimg[sp:height-sp,sp:width-sp] = edgcanny[sp:height-sp,sp:width-sp]

    #cv2.imwrite('images/edgcanny.png', edgcanny)
    #cv2.imwrite('images/edgimg.png', edgimg)

    # 白色位置の座標を抽出
    yl, xl = np.where(edgimg == 255)

    # 回帰計算
    p = np.poly1d(np.polyfit(xl,yl,1))
    #print(p)

    # 結果描画
    resimg = cv2.cvtColor(bin0, cv2.COLOR_GRAY2BGR)

    # 回帰直線を描画
    x1 = 0
    y1 = int(p(x1))
    x2 = width-1
    y2 = int(p(x2))
    cv2.line(resimg, (x1, y1), (x2, y2), (0,0,255), 1, lineType=cv2.LINE_AA)
    cv2.imwrite('images/resimg.png', resimg)

    # 結果表示
    cv2.imshow('Image', resimg)
    cv2.waitKey(0)

if __name__ == '__main__':
    main()


```

# 結果画像
![resimg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391380/5853c6e4-350d-8824-d7f1-cea257774824.png)
赤線が回帰直線です。

# 結果
直線式  y = -0.09705 x + 58.86

いい感じ。

# おわりに
エッジなどを回帰計算で扱うことは一般的だと思っていたのですが、
そうでもないようで、他にこんなことを書いているページも
見つけられなかったので書いて見ました。

ちなみに、KEY***E社のは、エッジ部分をセグメントで分けて、セグメント区間内で
平均的エッジ位置を求め、セグメント単位で計算して回帰直線を求めているようです。
おそらく処理を安定化させるためでしょう。
Django + Docker チュートリアルはじめからコケたはなし

# 構成
Mac(macOS High Sierra 10.13.6)
|
VirtualBox(CentOS Linux release 7.5.1804)
|
コンテナ

# あらすじ
Django をこれから使うので、いつも通り Docker コンテナたててー
最初の開発用サーバーをたてて（下記）、Chrome から見れる！

```
$ python3.6 manage.py runserver
~ 中略 ~
Django version 2.2.1, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
```
と思ったものの、見れない！！
なんで！ パッケージ足りないの！ そもそも Django に嫌われてる！？
と思っていたら、Flask とかでもはまった、公開する時に 0.0.0.0 にすることを忘れていました。。。

下記に直してちゃんと見れました！ 焦りは禁物ですね。。
Django さんこれからもよろしくお願いします m(_ _)m

```
$ python3.6 manage.py runserver 0.0.0.0:8000
~ 中略 ~
Django version 2.2.1, using settings 'mysite.settings'
Starting development server at http://0.0.0.0:8000/
Quit the server with CONTROL-C.
```

# 参考
https://docs.djangoproject.com/ja/2.2/intro/tutorial01/