OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerfileを活用したDockerイメージの作成

本投稿では、Dockerfileを活用して、Apacheが動作するWebサーバ用Dockerイメージを作成します。

## 1. Dockerfileの準備

Dockerfileに **centos 7.5.1804** をベースとして、Apacheをインストールする処理を記述します。

```
$ cat Dockerfile
FROM centos:7.5.1804
RUN yum install -y httpd iproute && yum clean all
RUN echo "Hello Apache." > /var/www/html/index.html
RUN systemctl enable httpd
```

## 2. Dockerイメージの作成

手順1で作成した Dockerfileを活用して、Dockerイメージを作成します。<br>
Dockerイメージ作成時にDockerfileを利用する場合は、 **-t** オプションで活用するDockerfileを指定します。

### Dockerイメージの作成

```
$ docker image build -f ./Dockerfile -t centos:c75apache01 .
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM centos:7.5.1804
.
.
.
Step 4/4 : RUN systemctl enable httpd
 ---> Running in 24b73348522b
Created symlink /etc/systemd/system/multi-user.target.wants/httpd.service, pointing to /usr/lib/systemd/system/httpd.service.
Removing intermediate container 24b73348522b
 ---> f266477d66c2
Successfully built f266477d66c2
Successfully tagged centos:c75apache01
```

### 作成したDockerイメージの確認

```
$ docker image ls
REPOSITORY                         TAG                    IMAGE ID            CREATED             SIZE
centos                             c75apache01            f266477d66c2        2 minutes ago       257MB
```

## 3. Dockerコンテナの起動

手順2で作成したDockerイメージをコンテナで起動します。<br>
以下のコマンドでは [**--tmpfs** オプション](https://docs.docker.com/storage/tmpfs/)を活用し、 /tmp と /run フォルダをメモリ上に展開するようにします。<br>
**-p** オプションではポートを指定して、ホストOS上で8081番ポートを参照するとDockerコンテナの80番ポートへポートフォワードするように設定することができます。

```
$ docker container run \
> -itd \
> --tmpfs /tmp \
> --tmpfs /run \
> -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
> --stop-signal SIGRTMIN+3 \
> --name web0001 \
> -h web0001 \
> -p 8081:80 \
> centos:c75apache01 /sbin/init
6e97f6a5313703a2c5c5aa30b741164f096e6a4b97f9c52af2ec5b928a26f512
$ docker container ls -a
CONTAINER ID        IMAGE                COMMAND                   CREATED             STATUS                     PORTS                  NAMES
6e97f6a53137        centos:c75apache01   "/sbin/init"              9 seconds ago       Up 8 seconds               0.0.0.0:8081->80/tcp   web0001
$ docker container stats --no-stream
CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
6e97f6a53137        web0001             0.01%               11.94MiB / 1.952GiB   0.60%               5.35kB / 3.25kB     6.67MB / 4.1kB      12
```

### コンテナへのログイン

コンテナ起動後に、 **docker container exec** コマンドでコンテナへログインし、Apacheが起動していることとドキュメントルートにファイルが展開されていることを確認します。

```
$ docker container exec -it web0001 /bin/bash
[root@web0001 /]# systemctl status httpd | grep active
   Active: active (running) since Sun 2019-06-09 04:53:57 UTC; 3min 9s ago
[root@web0001 /]# cat /var/www/html/index.html
Hello Apache.
[root@web0001 /]#
```

### Apacheの動作確認

ホストOS上で、8081番ポートへhttpアクセスすると上記手順で作成したコンテナ上にあるApacheにアクセスできることが確認できます。

```
$ curl http://localhost:8081/
Hello Apache.
$
```

## 参考文献
1. 古賀政純, "Docker実践ガイド 第２版", 2019.
2. Use tmpfs mounts _ Docker Documentation, https://docs.docker.com/storage/tmpfs/, Online; accessed 9-June-2019.
TruffleとReactのチュートリアルでエラー

## TruffleとReact組み合わせたチュートリアルやったんだけど

https://www.trufflesuite.com/tutorials/getting-started-with-drizzle-and-react

最新のnode.js version　だとtest時に以下のエラーが出る。

```
 TypeError [ERR_INVALID_REPL_INPUT] 
 Listeners for `uncaughtException` cannot be used in the REPL 
```
## 原因
node version 12.3.0 にてREPLがアップデートされ、以下のリンクのエラーExceptionが追加。
![Screen Shot 2019-06-09 at 16.52.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91514/e67d7db1-d4b9-4f6f-dedf-7bdb6f8da54e.png)
https://nodejs.org/api/repl.html#repl_repl


nodeのダウングレードにて対処。
https://www.surrealcms.com/blog/how-to-upgrade-or-downgrade-nodejs-using-npm.html

でも後々チュートリアルの方をアップデートしないと行けないはず。
Truffleの運営に言わないとな。
windows10でgit bashを使った際、pushできないエラーについて

# 環境
- windows10
- git version 2.9.0.windows.1
- Git bash

※Git bashを使ってください。

# 追記(2019/11/30)
こちらのやり方の方が良かったかも

C:\Program Files\Git\etc\sshにあるssh_configを変える
一度ssh_configファイルをデスクトップなどにコピーしてから以下のように末尾に追加

```
Host github.com
  User git
  HostName github.com
  IdentityFile C:\Users\{USER_NAME}\.ssh\id_rsa
  IdentitiesOnly yes

```
そしてもとの場所へ上書きする。


参考: [git for windows利用時のgithub接続にPermission denied (publickey)が出た時の対応](https://qiita.com/umema4/items/d31f0161188ae3b0a76d)
追記は以上。


# エラー内容
いろいろとありますが、主には秘密鍵の登録がうまくいっていない、
及びgithubに登録した公開鍵が受け付けてくれない。

```bash
$ ssh -T git@github.com
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.
```

# 解決法



key-genをSSH keyを作る

```bash
ssh-keygen -t rsa -C xxxxxxx@gmail.com
```

詳細は省略しますが、ほぼエンターキーだけでも(すでにキーがない場合は)OK。
sshエージェント起動できないかもしれないので以下のコマンドを実行する

```bash
eval `ssh-agent -s`
```

pidが表示されればOK
秘密鍵登録する

```bash
ssh-add ~/.ssh/id_rsa
```

これでOK

```bash
ssh -T git@github.com
Hi devinoue! You've successfully authenticated, but GitHub does not provide shell access.
```

# 参考
[GitHubとのssh接続が切れて、ハマったのでメモ](https://batapy88.com/post/github_ssh_connect_denied/)
[WindowsのGitbashで、Githubをssh経由で操作できるようにセットアップした](https://blog.yuheikagaya.com/entry/2012/12/11/224216)
string.Compareの挙動がおかしい [C#]

#"1-1"と"101"、"111"の比較結果が変

ファイル名のソート順がなんか変だなと思って原因を調べてみたらどうもstring.Compareがおかしいっぽい。

"-" < "0" < "1" なので、"1-1" < "101" < "111"になるはずだけど、"101" < "1-1" < "111"になってしまう。~~謎。~~

**追記**: string.Compare はカルチャ依存の比較を行い、ハイフンを無視した文字列で比較を行っている模様。string.CompareOrdinal を使えば良いらしい。

###テストコード

```
using System;

class StringCompare
{
    static void Main()
    {
        Console.WriteLine("string.Compare(\"-\",\"0\") = {0}", string.Compare("-","0"));
        Console.WriteLine("string.Compare(\"-\",\"1\") = {0}", string.Compare("-","1"));
        Console.WriteLine("string.Compare(\"0-\",\"00\") = {0}", string.Compare("0-","00"));
        Console.WriteLine("string.Compare(\"0-\",\"01\") = {0}", string.Compare("0-","01"));
        Console.WriteLine("string.Compare(\"1-\",\"10\") = {0}", string.Compare("1-","10"));
        Console.WriteLine("string.Compare(\"1-\",\"11\") = {0}", string.Compare("1-","11"));
        Console.WriteLine("string.Compare(\"0-0\",\"000\") = {0}", string.Compare("0-0","000"));
        Console.WriteLine("string.Compare(\"0-0\",\"010\") = {0}", string.Compare("0-0","010"));
        Console.WriteLine("string.Compare(\"1-0\",\"100\") = {0}", string.Compare("1-0","100"));
        Console.WriteLine("string.Compare(\"1-0\",\"110\") = {0}", string.Compare("1-0","110"));
        Console.WriteLine("string.Compare(\"1-1\",\"101\") = {0}", string.Compare("1-1","101")); // これのみ 1 他 -1
        Console.WriteLine("string.Compare(\"1-1\",\"111\") = {0}", string.Compare("1-1","111"));
    }
}
```

###実行結果

```
string.Compare("-","0") = -1
string.Compare("-","1") = -1
string.Compare("0-","00") = -1
string.Compare("0-","01") = -1
string.Compare("1-","10") = -1
string.Compare("1-","11") = -1
string.Compare("0-0","000") = -1
string.Compare("0-0","010") = -1
string.Compare("1-0","100") = -1
string.Compare("1-0","110") = -1
string.Compare("1-1","101") = 1
string.Compare("1-1","111") = -1
```
はろわ

Qiita登録しました。
日常で使っているプログラミングの内容を備忘録としてまとめようかと思ってます。

使い方わからないので、Qiita上でHello world（お試しの投稿）してみます。


〇自己紹介
名前　　　　：椎茸といいます。名前の由来はC++からですがあとは適当。
仕事　　　　：某大手メーカーで技術者してます。工場で扱っている量産データの活用などの業務をしてます。
使える言語　：業務ではVBA、SAS、自宅ではPython使ってます。あとはC++など。QiitaではVBAとPythonが主になりそう。
興味ある分野：データ分析、画像処理、統計、機械学習など。大学院時代は画像処理の研究をしていてなんやかんやで特許を取得し、こんな適当な研究で特許が取れるのかとドン引きした程度には不真面目でした。

Qiitaに登録した理由：
会社で半期ごとにテーマの設定を行うのですが、チャレンジテーマ（業務とは直接関係ないが、自己啓発として行うテーマ）の欄に
「Pythonを使ったデータ分析技術の習得」的なことを書いた結果、上司から「Pythonって何？そういう業務と関係ないことは趣味でやれ」
と指摘され、腹が立ったので趣味でやってやろうと開き直る。
製造業はシステムに詳しい人少ないので、自分が詳しくなって見返してやろうというネガティブなモチベーションで始めました。



だいたいこんな感じです。

挙げるのは主にVBAとPythonになるかと思います。
興味があったらのぞいてくだい。
RaspberryPiでWebCameraを利用する


## 概要

RaspberryPiでUSBカメラから画像を撮影する環境を構築しました。fswebcamを利用して撮影できることを確認しています。
最終的な環境は下記の手順で実現できます。

```sh
$ sudo apt install -y fswebcam
$ sudo usermod -aG vidoe $USER
$ fswebcam -p YUYV -r 640x480 -F 1 -S 20 --no-banner ./image.jpg
```

## デバイスの接続状態確認

`lsusb`でデバイスが接続されているかどうかが確認できます。

## fswebcamのインストール

下記コマンドでfswebcamをインストールできます。

```sh
$ sudo apt install -y fswebcam
```

上記コマンドで導入しただけだと、fswebcamのコマンドで`/dev/video`にアクセスできない場合があります。その場合は、Permission Deniedが発生するので下記コマンドでユーザを`video`グループに追加します。初期設定のpiユーザだと不要かもしれません。

```sh
$ sudo usermod -aG vidoe $USER
```

## 撮影

画像の取得には下記のようなコマンドで実行します。

```sh
$ fswebcam ./image.jpg
```

fswebcamの設定では色々できるようですが、今回は下記のようなコマンドを利用して指定した解像度で取得するようにしました。

```sh
$ fswebcam -p YUYV -r 640x480 -F 1 -S 20 --no-banner ./image.jpg
```

* `-p YUYV`: カメラによっては、これがないと保存できない場合があるようです。
* `-r 640x480`: 640x640画素の画像を保存します。好きな値を設定してください。
* `-F 1`: 撮影するフレーム数です。おおよそ露光時間に関係する値のようです。
    大きくすると露光時間が長くなり、動きがあるとぶれた画像になります。
* `-S 20`: 撮影前のパラメータ調整が行われるようです。
    大きいほうが調整がいい場合があるようなのですが、時間がかかるようになります。
* `--no-banner`: バナーは邪魔なので削除。

## docker環境

上記まででRaspberry Pi上での環境構築は完了なのですが、直接環境構築すると何かあった時に大変になるのでdockerで実現するための方法です。単純にfswebcamだけをインストールしたimageを用意し、コマンドを実行しています。

### Dockerfile

ラズパイのイメージとしては[balenalib][balenalib]を利用しています。

```Dockerfile
FROM balenalib/raspberry-pi:latest

RUN set -x \
  && apt-get update \
  && apt-get autoremove \
  && apt-get install -y fswebcam \
  && apt-get clean \
  && rm -rf /var/lib/apt/lits/*

WORKDIR /workspace
CMD ["fswebcam"]
```

実行には下記のようなコマンドを利用すれば撮影できます。`localhost:fswebcam`は上記Dockerfileでビルドしたイメージを指します。

```sh
$ docker run --rm -v ./:/workspace --device=/dev/video0:/dev/video0 -u $(id -u):44 localhost:fswebcam fswebcam -p YUYV -r 640x480 -F 1 -S 20 --no-banner image.jpg
```

* `--device=/dev/video0:/dev/video0`: videoデバイスをdockerコンテナに接続します。
    * 環境によっては`/dev/viceo0`の末尾番号が異なる可能性があります。
* `-u $(id -u):44`: コンテナ内の実行ユーザIDとグループIDを指定します。
    * 設定せずに起動すると、rootユーザで画像が保存されます。
    * グループIDはvideoデバイスに接続できるグループです。
        `cat /etc/group | grep video`で確認できます。
        設定が正しくないと、videoにアクセスできずPermissionエラーが発生します。

[balenalib]: https://hub.docker.com/u/balenalib

### docker-compose.yml

上記のコマンドを毎回利用してもよいのですが、大変なのでdocker-composeを用意します。

```yml
version: "2"
services:
  fswebcam:
    image: localhost:fswebcam
    user: 1000:44
    devices:
      - /dev/video0:/dev/video0
    volumes:
      - .:/workspace:rw
    working_dir: /workspace
    command: fswebcam -p YUYV -r 640x480 -F 1 -S 20 --no-banner image.jpg
```

上記ファイルを用意して下記のコマンドを実行することで、`docker run`と同様に動作します。

```sh
$ docker-compose run --rm fswebcam
```
公式GUIツールでGitHub入門 （GitHub Desktop）


同僚への共有を前提とした、GitHub入門用メモです。

# ①まずは公式動画で世界観を知ろう
> What is GitHub?
> https://www.youtube.com/watch?v=w3jLJU7DT5E  


# ②仕組みの概要を理解しよう（日本語で）
YoutubeでわかりやすいGit・Githubの仕組み解説動画がありました。

> - Gitってなにが便利なの？   
> https://www.youtube.com/watch?v=7GFF5e9HHaM
> - Gitの仕組み   
> https://www.youtube.com/watch?v=pHfmdBZ2g9o
> - GitHubってなに？   
> https://www.youtube.com/watch?v=UaISTwFCe-Q  
> ※補足：GitHubの非公開リポジトリ機能は現在は無料で使えます。

[※動画制作者の未経験エンジニア様チャンネルはこちら](https://www.youtube.com/channel/UChZuQh8Ofv_oLYcbp4AgN_Q)


# ③GitHubのユーザー登録
> **GitHub**
> https://github.co.jp/
> ※サブスクリプションプランはまずはFreeで大丈夫です。


# ④GitHub Desktopをインストール
> **GitHub Desktop** | Simple collaboration from your desktop
> https://desktop.github.com/


# ⑤公式チュートリアルで使い方を覚えよう
日本語訳ページがまだ開発中となっていたので、英語でやるしかない。（2019/6/9時点）
英語、かつ長いのでやる気が失せそうですね。同僚にはハンズオンしたほうがよさそうです。
> - Getting Started with GitHub Desktop  
> https://help.github.com/en/desktop/getting-started-with-github-desktop
> - Contributing to projects with GitHub Desktop  
> https://help.github.com/en/desktop/contributing-to-projects


以上
ユーザー権限でシンボリックリンクを作成できるようにする


Professional Edition以上のみ

1. 『グループポリシーの編集』を開く
1. 『コンピュータの構成』→『Windowsの設定』→『セキュリティの設定』→『ローカルポリシー』→『ユーザー権利の割り当て』を開く
1. 『シンボリックリンクの作成』を開き、ユーザー権限で作りたいユーザー or グループを追加する。

*要再起動*

## 試してみる

ユーザー権限追加前

```powershell
PS G:\tmp> echo "this is test" > h:/tmp/test.txt
PS G:\tmp> New-Item -Type SymbolicLink -Value H:\tmp\test.txt -Path . -Name test.txt
New-Item : Administrator privilege required for this operation.
At line:1 char:1
+ New-Item -Value H:\tmp\test.txt -Path . -Name test.txt -Type Symbolic ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : PermissionDenied: (H:\tmp\test.txt:String) [New-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : NewItemSymbolicLinkElevationRequired,Microsoft.PowerShell.Commands.NewItemCommand

PS G:\tmp>
```

ユーザー権限追加後

```powershell
PS G:\tmp> New-Item -Type SymbolicLink -Value H:\tmp\test.txt -Path . -Name test.txt


    Directory: G:\tmp

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a---l        2019/06/09    15:03              0 test.txt

PS G:\tmp> (ls .\test.txt).LinkType
SymbolicLink
PS G:\tmp> (ls .\test.txt).Target
H:\tmp\test.txt
PS G:\tmp> cat .\test.txt
this is test
PS G:\tmp>
```

`New-Item`の最初の引数を `-Type SymnbolicLink -Value H:\tmp\test.txt` にすると `ln` と間違いづらいかも
Node.jsでCSVを読み込んでDBに保存する

## はじめに
Node.jsでCSVを読み込んでDBに保存するサンプルコードを作成しました。
コードの解説等はありませんので、あしからず。

## 前提条件
事前に以下をインストールしておいてください。
- nodejs
- yarn
- sqlite3

実際に試した環境のバージョンはとおりです。

``` sh
$ node --version
v12.4.0
$ yarn --version
1.16.0
$ sqlite3 --version
3.16.0 2016-11-04 19:09:39 0e5ffd9123d6d2d2b8f3701e8a73cc98a3a7ff5f
```

## 環境構築
``` sh
$ mkdir sample && cd sample
$ yarn init -y
$ yarn add csv sequelize sqlite3
```

## DB作成
``` sh
$ sqlite3 ./sqlite3.db
sqlite> CREATE TABLE users(id integer primary key autoincrement, name text, email text);
```

## テストデータ作成
``` sh
$ cat <<EOF >> ./test.csv
yamada,s-yamada@sample.com
hayashi,y-hayashi@sample.com
tanaka,t-tanaka@sample.com
EOF
```

## ソースコード
以下の内容を index.mjs というファイル名で保存する。

``` js:index.mjs
"use strict;"

import csvparse from 'csv-parse';
import fs from 'fs';
import Sequelize from "sequelize";
import transform from 'stream-transform';

const db = new Sequelize(
	'database', '', '', {
		dialect: 'sqlite',
		storage: './sqlite3.db',
	}
);

const User = db.define(
	"user", {
		name: Sequelize.STRING,
		email: Sequelize.STRING
	}, { timestamps: false }
);

const source = fs.createReadStream('test.csv');

const csvParser = csvparse({ columns: false });

const dataRegister = transform(async (record, callback) => {
	const user = {
		name: record[0].toUpperCase(),
		email: record[1]
	};
	await User.create(user);
	callback(null, user);
}, { parallel: 5 });

const resultLogger = async () => {
	const users = await User.findAll();
	console.log("[result]");
	for (let user of users) {
		console.log(JSON.stringify(user));
	}
};

db.transaction(async (t) => {
	await User.destroy({ where: {}, truncate: true });
	source.pipe(csvParser).pipe(dataRegister).on('finish', resultLogger);
});
```

## 実行
``` sh
$ node --experimental-modules index.mjs
(node:58762) ExperimentalWarning: The ESM module loader is experimental.
Executing (7d95a3db-c374-4ca5-9ae8-21f4cc263d54): BEGIN DEFERRED TRANSACTION;
Executing (default): DELETE FROM `users`
Executing (7d95a3db-c374-4ca5-9ae8-21f4cc263d54): COMMIT;
Executing (default): SELECT `id`, `name`, `email` FROM `users` AS `user`;
Executing (default): INSERT INTO `users` (`id`,`name`,`email`) VALUES (NULL,$1,$2);
Executing (default): INSERT INTO `users` (`id`,`name`,`email`) VALUES (NULL,$1,$2);
Executing (default): INSERT INTO `users` (`id`,`name`,`email`) VALUES (NULL,$1,$2);
[result]
{"id":6,"name":"YAMADA","email":"s-yamada@sample.com"}
{"id":7,"name":"HAYASHI","email":"y-hayashi@sample.com"}
{"id":8,"name":"TANAKA","email":"t-tanaka@sample.com"}
```
## 結果確認
``` sh
$ sqlite3 ./sqlite3.db
sqlite> select * from users;
6|YAMADA|s-yamada@sample.com
7|HAYASHI|y-hayashi@sample.com
8|TANAKA|t-tanaka@sample.com
```
Circle Ciで、pythonのunittestを実行する。pyramidプロジェクト

## slackと連携する

以下のxxxを自分のSlackの名前に変更してアクセス

https://xxx.slack.com/apps/manage?utm_source=in-prod&utm_medium=inprod-apps_link-slack_menu-click

Circle Ciを検索して追加する
この画面に表示されるWebhookURLをコピーしておく

Circle Ciにログインする
Add Projectで連携したいプロジェクトを選択する
歯車マークをクリックして
<img width="283" alt=" 2019-06-09 15.34.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/1cd33578-0784-24f9-f7b7-49bd7f54a28d.png">
Chat Notificationsから、Slackを選択してコピーしておいたWebhookURLを入れて保存する

## 実装する

pyramidのサンプル用のプロジェクトを作成する
こちらを参考にしてください
https://qiita.com/noracorn92/items/07f5f7dbad8f551c3c45

miniappというプロジェクト名で作成しました

```
cd miniapp
pip freeze > requirements.txt
vi requirements.txt
```
requirements.txtを編集して、git clone している部分を削除します

Circle Ciで使用する設定ファイルを作成する

```
mkdir .circleci
cd .circleci
vi config.yml
```

```config.yml
version: 2
jobs:
  build:
    docker:
      - image: python:3

    steps:
      - checkout
      - run: apt-get update && apt-get install -y libgmp3-dev
      - run:
          name: Install dependencies
          command: pip install -r requirements.txt
      - run:
          name: setup miniapp
          command: pip install -e .
      - run:
          name: Run tests
          command: cd miniapp/pages/tests;python -m unittest
```
※ miniapp/pages/testsにテストケースがあるとします。

## 結果を確認する

masterにプッシュした時点で、テストが走ります。
<img width="1257" alt="CircleCI.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52386/f46110db-af75-568d-19d9-6955cb8b25af.png">
docomoの形態素解析apiを使ってみる

## 動機

Docomoにもいろいろ自然言語処理のAPIがあることを知りました。
せっかくなので形態素解析をしてみましょう

## ソース

```python
import re
import sys
import json
import requests

target_url = "https://api.apigw.smt.docomo.ne.jp/gooLanguageAnalysis/v1/morph?APIKEY="
api_key = "api_key"

def parse(sentence):
    headers = {
        "Content-Type": "application/json",
    }
    data = {
        "sentence": sentence,
    }
    r = requests.post(target_url+api_key,
                      headers=headers,
                      data=json.dumps(data))
    return r.json()

sentence = "私はその人の記憶を呼び起すごとに、すぐ「先生」といいたくなる"
response = parse(sentence)

for line in response["word_list"][0]:
    print("{} = {}".format(line[0], line[1]))
```

## 出力結果
```
私 = 名詞
は = 連用助詞
その = 連体詞
人 = 名詞
の = 格助詞
記憶 = 名詞
を = 格助詞
呼び起 = 動詞語幹
す = 動詞接尾辞
ごと = 補助名詞
に = 格助詞
、 = 読点
すぐ = 連用詞
「 = 括弧
先生 = 名詞
」 = 括弧
と = 格助詞
い = 動詞語幹
い = 動詞活用語尾
た = 動詞接尾辞
く = 形容詞接尾辞
な = 動詞語幹
る = 動詞接尾辞
```

## まとめ
少し返ってくる形が違いますが、NTT研究所の成果を使ってるなら、
COTOHA APIと返ってくる結果も同じでしょうか。
後日調べてみたいと思います。
jsonで返ってくることと、認証がいらないことはいいと思います。
GoのListenAndServeからsync.Poolを使ったら、意図に反してオブジェクトが大量に生成された件

Golangでコネクションプーリングを実現するためにsync.Poolを使ってみたら意図しない挙動があったのでメモしておきます。Goのバージョンは1.12.5です。

※database/sqlだと内部的にプーリングされているためこういう実装は必要ないのですが、今回は別のもの、具体的にはstreadway/amqpだったため、実装が必要になりました。ただし、普通のオブジェクトでも再現したため、AMQPかどうかは関係ないと思います。

## 経緯

HTTPでアクセスを受けてAMQPにメッセージをパブリッシュするというAPIを作ろうとしていました。その際のAMQPのチャンネルのプーリングとして、標準ライブラリーにある[sync.Pool](https://golang.org/pkg/sync/#Pool)を使ってみました。

sync.Pool自体は、単純にプールから取り出す、プールに戻す、プールにない場合は作って返すという機能しかありません。さらに、GCによってプールに入っているオブジェクトが勝手に捨てられてしまうため、コネクションプーリングには厳しそうな感じがしました。

しかし調べたところ、[この辺](https://github.com/golang/go/issues/23216#issuecomment-356111581)を見ると[runtime.SetFinalizer](https://golang.org/pkg/runtime/#SetFinalizer)を使っても良さそうなので、GCに回収された時にCloseする挙動をSetFinalizerで実装し、コネクションプールとして使用してみました。（実際にはチャンネルのプールですが。）

## 何が起こったか？

性能の測定のために負荷をかけて動作したので満足していたのですが、ふとRabbitMQのWeb UIを確認すると、**数百個のチャンネルが開きっぱなしに**。その後もアクセスするたびにチャンネルは増え、**明らかにチャンネルが足りるはずの状況でもなぜかチャンネルは増えていきます**。（1000以上チャンネルを持っている状態で数百回のアクセスを発生させるなど。）

最初はSetFinalizerを疑ったものの、runtime.GCでGCを発生させるとチャンネルは綺麗に無くなりました。また、Finalizerの中でメッセージを表示させるようにしたら表示されたので、SetFinalizerは正常に動作しているようでした。

さらに、AMQPのチャンネルではなく、適当なオブジェクトをsync.Poolに入れるようにして試験してみたところ、問題が再現。どうやらAMQPとは関係なさそうでした。

## 原因は不明…

IntelliJのデバッガーで追ってみましたが、結局分からず…並列処理にまつわる挙動なのかなとは思います。ただ、その割に手でポチポチ連打する程度のリクエストでも再現してしまうのが不思議なところです。

とりあえずsync.Poolはバージョン1.3からある機能のようなので今更バグもないでしょうし、GetとPutしかないインターフェイスからしてみても、コネクションプーリングに使うものではなかったのだと解釈しました。現状の実装だとGCが走ると全部捨てられるらしいですしね。

## 余談

AMQPのChannelは論理的なものなので、毎回開いて閉じたらどうかと思いましたが、負荷をかけて大量のアクセスをしたら反応しなくなりました（笑）

なお、for文の中でGoルーチンを生成して、その中からsync.Poolにアクセスしても特に再現はしませんでした。
辞書をkeyとvalueのリストに分解する

タイトルそのまま。

普通にやるならこう。

~~~Python
>>> D = {"a":1,"b":2,"c":3}
>>> D
{'a': 1, 'b': 2, 'c': 3}

>>> [*D.keys()] #[*D]でも可
['a', 'b', 'c']
>>> [*D.values()] 
[1, 2, 3]
~~~

癖の強い書き方

~~~Python
>>> key,value = [*zip(*D.items())]
>>> key
('a', 'b', 'c')
>>> value
(1, 2, 3)
~~~

リストじゃないじゃん。
(以下はshiracamusさんにご指摘いただき簡潔に修正致しました。)

~~~Python
>>> key,value = map(list,zip(*D.items()))
>>> key
['a', 'b', 'c']
>>> value
[1, 2, 3]
~~~

他人に見せないコードならなんでも1行でやっちゃいたい人。

以上。

  
追記。

shiracamusさんにコメントで以下のような書き方も教えていただきました。

~~~Python
>>> (*key,),(*value,)=zip(*D.items())
>>> key
['a', 'b', 'c']
>>> value
[1, 2, 3]
~~~

なぜこう書けるのかはコメント欄にて。
mac  pyenv  + OpenCV 環境設定

##pyenv でPythonをインストールしている mac でのOpenCVのインストールと動作確認


### python3.7 インストール
どうもpython3.7以上でないと OpenCVがうまく動かないっぽい。
3.7未満の場合はアップデートしておく。 
`zlib not available`のエラーを回避するために`macOS_SDK_headers_for_macOS_10.14.pkg`を手動でインストールしておく。

```
$ sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
$ git clone git://github.com/yyuu/pyenv-update.git ~/.pyenv/plugins/pyenv-update
$ pyenv update
$ pyenv install 3.7.3
$ pyenv global 3.7.3
```

### openCVインストール
brewでインストール。　オプションはいらなかったです。

```
$ brew update
$ brew upgrade
$ brew install opencv3 
```

### シンボリックリンク作成
pythonをpyenvでインストールしているため、自動的にシンボリックリンクが貼られない。
手動で貼るしかない。

```
$ ln -s /usr/local/Cellar/opencv/4.1.0_2/lib/python3.7/site-packages/cv2/python-3.7/cv2.cpython-37m-darwin.so /Users/[ユーザー名]/.pyenv/versions/3.7.3/lib/python3.7/site-packages/
```

### 動作確認
OpenCVのサンプルでグレースケールの画像を表示してみる。
sample.pyの名前でこんなのを作成。

```python
import numpy as np
import cv2

img = cv2.imread('idol.jpg',0)
cv2.imshow('image',img)
k = cv2.waitKey(0) & 0xFF
if k == 27: # wait for ESC key to exit
  cv2.destroyAllWindows()
elif k == ord('s'): # wait for 's' key to save and exit
  cv2.imwrite('idol.png',img)
  cv2.destroyAllWindows()
```
`python sample.py` で実行

|実行前|実行後|
|---|---|
|![main.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/e46713fd-6198-f534-f731-165821c11708.jpeg)|<img width="412" alt="スクリーンショット 2019-06-09 15.06.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266239/8cfb71e6-cb56-f345-761f-0c1a1c658151.png">|


## CentOS 6.9の場合

`
# yum install opencv
# pip install opencv-python
jQueryフォーム追加削除


思った以上に使う機会があるのでメモ

```js
// 追加
$('#demo-plus').on('click', function(){
  var inputCount = $('#demo-area .unit').length;
  if (inputCount < maxCount){
    var element = $('#demo-area .unit:last-child').clone(true);// 末尾をイベントごと複製
    // 複製したinputのクリア
    var inputList = element[0].querySelectorAll('input[type="text"], textarea');
    for (var i = 0; i < inputList.length; i++) {
      inputList[i].value = "";
    }
    $('#demo-area .unit').parent().append(element);// 末尾追加
  }
});
// 削除
$('.demo-minus').on('click', function(){// イベントごと複製しているのでonのselectorは未設定
  var inputCount = $('#demo-area .unit').length;
  if (inputCount > minCount){
    $(this).closest('.unit').remove();
  }
});
```




# 構造

```
.unitが複製単位

#demo-area
  .unit
    .demo-minus
  .unit
    .demo-minus

#demo-plus
```


<p class="codepen" data-height="700" data-theme-id="0" data-default-tab="result" data-user="horikeso" data-slug-hash="RmXqmJ" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="RmXqmJ">
  <span>See the Pen <a href="https://codepen.io/horikeso/pen/RmXqmJ/">
  RmXqmJ</a> by horikeso (<a href="https://codepen.io/horikeso">@horikeso</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
SeleniumJava+ChromeDriverでconsole.log()の出力値を取得する

KotlinでSeleniumを使ってみようと思ったら、console.log()の内容をとるのにちょっと苦労したのでメモ。

## 環境
* MacOS 
    * 1.14
* Kotlin 
    * 1.3.21
* Selenium-Java 
    * 2.53.1
* ChromeDriver  
    * 75.0.3770.8

## build.gradle

```
plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.3.21'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
    //implementation "org.seleniumhq.selenium:selenium-java:3.141.59"
    implementation "org.seleniumhq.selenium:selenium-java:2.53.1"
}

compileKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
    kotlinOptions.jvmTarget = "1.8"
}
```
## コード

```kotlin
import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeDriverService
import org.openqa.selenium.chrome.ChromeOptions
import java.util.logging.Level
import org.openqa.selenium.remote.CapabilityType
import org.openqa.selenium.logging.LogType
import org.openqa.selenium.logging.LoggingPreferences
import org.openqa.selenium.remote.DesiredCapabilities


fun main(args: Array<String>) {
    val capabilities = DesiredCapabilities.chrome()
    val logPreference = LoggingPreferences()
    val options = ChromeOptions()

    // ログレベルを設定
    logPreference.enable(LogType.BROWSER, Level.ALL)
    capabilities.setCapability(CapabilityType.LOGGING_PREFS, logPreference)

    // ヘッドレスモード
    options.addArguments("--headless")
    capabilities.setCapability(ChromeOptions.CAPABILITY, options)

    val driver = ChromeDriver(capabilities)

    driver.get("https://***")

    driver.executeScript("console.log('hoge');")
    val logs = driver.manage().logs().get(LogType.BROWSER)

    logs.forEach { logEntry ->
        println(logEntry)
    }

    driver.quit()
}
```

### ポイント

``driver.setLogLevel(Level.ALL)``じゃだめ、でLoggingProferenceオブジェクトを渡してやらないとダメだった。

あとSelenium-Javaの最新版は3.x系なんですが、3系だとどうもうまく行かなかったので時間があるときに原因を調べて3系で動くように直します。
Manjaro Linux に CardWirthPy Reboot をインストール

## はじめに

Windowsで大人気だったゲーム CardWirth (CardWirthPy Reboot) を Manjaro　Linux　にインストールした。

## 環境

* Manjaro Linux 18.0.4 Illyria

## インストール＆起動

```
$ sudo pacman -S unzip
$ sudo pacman -S mercurial python-pip
$ pip3 install --user pathlib2
$ pip3 install --user wxpython
$ pip3 install --user pygame
$ pip3 install --user lhafile
$ hg clone https://bitbucket.org/k4nagatsuki/cardwirthpy-reboot
$ cd cardwirthpy-reboot
$ wget https://bitbucket.org/k4nagatsuki/cardwirthpy-reboot/downloads/skin_classic_20180303.zip
$ unzip skin_classic_20180303.zip
$ ./cardwirthpy.sh
```

## コメント

* LANG=en_US.UTF-8 ではフォントが見つからずにエラーになるので、 ```LANG=ja_JP.UTF-8 ./cardwirthpy.sh```として起動
* もしかしたらフォントを入れる必要があるかもしれない。その時は、以下のようにフォントを入れる。

```
# フォントをインストール
$ mkdir ~/.fonts
$ cp Data/Font/*.ttf ~/.fonts
$ fc-cache -fv
```

* フォントを入れると、Firefoxなどの日本語が表示されなくなることがあるので、そのときは再起動すると直る。

## 参考

* [Windows以外のOSで動かす方法](https://bitbucket.org/k4nagatsuki/cardwirthpy-reboot/wiki/OtherOS)
Leetcode #143: Reorder List

```swift
func reorderList(_ head: ListNode?) {
    var slow = head
    var fast = head
    while fast != nil && fast!.next != nil {
        slow = slow?.next
        fast = fast?.next?.next
    }
    var stack = [ListNode]()
    var current = slow?.next
    slow?.next = nil
    while current != nil {
        stack.append(current!)
        current = current?.next
    }
    
    current = head
    while !stack.isEmpty {
        let tmp = current?.next
        let node = stack.popLast()!
        current?.next = node
        node.next = tmp
        current = tmp
    }
}
```
Google Apps Script で Calendar を扱うときの書き方

# trigger となる event source を From Calendar にしたときの引数

(言語設定を変えるの面倒なので、 event source とか From Calendar の日本語名が分かる人教えてください)

例として、実行される function を

```javascript
function doFromCalendarUpdated(args) {
}
```

のようにしてみる。

trigger の設定画面で、こうやって 

* `Choose which function to run`: (前述の) `doFromCalendarUpdated`
* `Select event source`: `From calendar`
* (ちなみに `Calendar owner email` には、 calendar id を入れればよい。)

<img width="749" alt="スクリーンショット 2019-06-09 14.32.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117087/725ffce5-ac37-0a07-a709-8f5183d2caf9.png">


このとき args には、

```json
{"calendarId": "xxxx", "authMode": "FULL", "triggerUid": "xxxx"}
```

が入っている。 CalendarId は分かるが、なんの変更があったかは分からないっぽい。

## Permission

Script が所属するプロジェクト[^1]が Calendar のデータにアクセスすることを許可しないといけない。

[^1]: script を作れば勝手にプロジェクトが作られてると考えても差し支えないと思います。

設定していない場合、
>
The script does not have permission to perform that action.
Required permissions: (https://www.googleapis.com/auth/calendar || https://www.googleapis.com/auth/calendar.readonly || https://www.google.com/calendar/feeds)

というエラーが出る。 Trigger で実行する前にテストで実行したりして許可しないといけない


# カレンダーのイベントを検索
過去24時間のイベントを検索するコード例

```javascript
function doFromCalendarUpdated(args) {
  if (!args || !args.calendarId) {
    Logger.log("No arguments");
    return;
  }
  handleCalendar(args.calendarId);
}

var handleCalendar = function(calendarId) {
  var calendar = CalendarApp.getCalendarById(calendarId);
  var endTime = new Date();
  var startTime = new Date(endTime.getTime() - 24 * 60 * 60 * 1000);
    
  var events = calendar.getEvents(startTime, endTime);

  var event;  
  for (var i = 0, l = events.length; i < l; i++) {
    event = events[i];

    // この event の使い方は
    // https://developers.google.com/apps-script/reference/calendar/calendar-event
    // を参照

    // たとえばイベント名をログ出力するには
    Logger.log(event.getTitle());
  }
}
```

テストするには

```javascript
function testHandleCalendar() {
  var email = Session.getActiveUser().getEmail();

  handleCalendar(email);
}
```

とかやればいいはず
PlantUMLでシーケンス図を書いてみよう

# はじめに
皆さん、シーケンス図は書きますか？
「書くよ！」と答えた皆さん、何を使って書いていますか？
今回は**PlantUMLを使ったシーケンス図の書き方**をご紹介いたします。

## PlantUMLって何？
さらっとタイトルに出てきたPlantUMLですがどんなものか皆さんはご存知でしょうか。
そこから簡単にさらっていきましょう。

### そもそもUMLとは？メリットは？
UMLとは`Unified Modeling Language`の略称で、直訳すると**統一されたモデリング言語**となります。
分かりにくいので**ソフトウェアやアプリケーションの構造を表す図を表現できる言語**、とご理解いただいても差し支えありません。
ここで言う「アプリケーションの構造を表す図」というのはクラス図やシーケンス図、ER図などを指しますので、
つまりは**設計図がプログラムと同じようにソースで表現できますよ！**という代物ですね。

バージョン管理システムでの管理が容易になりますので、
導入されている現場も多いです！

### ではPlantUMLとは？
PlantUMLとは**オープンソースでDSL(ドメイン特化言語)をコーディングすることでUMLが描ける、Java製のツール**です。
UMLをテキストベースで扱いやすくしたもの、と思っていただければよいかと思います！

説明はここまでにして、次はPlantUMLを書くためのエディタを準備していきましょう！

# エディタの準備
今回は**Atom**を使用します。

## Atomのインストール
1. [Atomの公式ページ](https://atom.io/)にアクセスします。
2. `Download`をクリックし、インストーラを起動しましょう。
3. 手順に従ってインストールを完了させます。

続いてPlantUMLの表示に必要なpluginをインストールします。
**plantuml-viewer**というpluginです。

## pluginのインストール
1. Atomを開きます。
2. `File`>`Setting`>`Install`をクリックします。
3. `plantuml-viewer`で検索しましょう。
4. 該当pluginの`Install`をクリックします。
5. 念のためAtomを再起動しておきましょう。

これで準備完了です！簡単！

# 実際に書いてよう
ライフラインやメッセージの書き方については既にネットに転がっているので割愛しますが、
一旦例として以下のようなファイルを作ってみましょう。

``` uml
title sample

actor "caller" as caller
participant "application" as app
database "DB" as db

caller -> app : request
activate app

app -> db : retrieve by id
app <-- db

caller <-- app : response
deactivate app
```

上記をAtomにコピペし、`Package`>`PlantUML Viewer`>`Toggle View`をクリックしてみましょう。
すると…
![atom.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188440/7c543c37-c03e-6fca-554b-af5039faab29.png)

**こんな感じで自動的にUMLを作ってくれます！**
十数行だけでこの設計書が作れてしまうので本当に便利です！

# 最後に
設計書がソースで管理できるようになるとプロジェクトに含むことができ管理が簡単になったり、
プログラマ側としても作業フローがコーディングと大差なくなったりと良いことずくめです。
また筆者の主観ではありますが、学習コストもかなり低いので全く知らない状況からでもある程度は形にできると思います。

細かい書き方については割愛させていただきましたが、[筆者がよく使うサイトのリンク](http://plantuml.com/ja/sequence-diagram)を貼っておきます！
「こっちの方が分かりやすいよ！」というサイトがあればコメントにてご紹介いただけると助かります！

PlantUML、是非触ってみてください！
ご覧いただきありがとうございました！
問い合わせ処理２：ハッシュ結合、割り算、集合積、集合和

# 関係演算アルゴリズムとコスト

前回 -> https://qiita.com/s0t00524/items/a4f57f7568f2784464a0
この記事は大学の期末試験勉強のために作成したものです。間違い等は悪しからず。

## 関係データベース演算の種類
- 入力演算
    - 選択（Selection）
    - 射影（[Delta] Projection)
    - 集約（Aggregation）
    - 整列（Order-By)
    - 重複除去（Duplication Elimination）
    - グループ化（Group-By）
    - 結合（Join）
    - 準結合（Semi-Join）
    - 集合積（Intersection）
    - 集合差（Difference）
    - 集合和（Union）
    - 直積（Cartesian Product）
    - 商（Division）

## 演算のコスト見積もり
**比較回数（CPUコスト）**と**ディスクI/O**によって見積もる。また以下の議論では、関係代数Rのサイズを以下で定義する。

- Rのタプル数：$\\{R\\}$
- Rのディスクページ数：$|R|$

## 各選択演算とコストの見積もり

### GRACEハッシュ結合とそのコスト

分散フェーズと結合フェーズの各フェーズで独立のハッシュ関数を使用。合計で２個使う。

<img width="373" alt="スクリーンショット 2019-06-09 1.18.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430644/95d36fe8-6142-b176-df18-6d3f843246e1.png">

- ハッシュ適用回数：$2(\\{R\\} + \\{S\\})$
    - 各フェーズで$\\{R\\} + \\{S\\}$

- 比較回数：$\sum\\{S_i\\} = (\\{S\\}/n) \times n = \\{S\\}$
- ディスクI/O回数：$3(|R|+|S|)$

### ハイブリッドハッシュ結合

<img width="346" alt="スクリーンショット 2019-06-09 1.30.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430644/30fe34ac-ea91-1253-cf85-a116e439d7e0.png">

- 比較回数とハッシュ適用回数：GRACEと同じ
- ディスクI/O回数：$3(|R|+|S|) - 2(|R|+|S|)/L = (3 - 2|M|/|R|) \times (|R|+|S|)$

メモリ不足の場合の三種類のハッシュ結合のコストを以下にまとめる。

<img width="400" alt="スクリーンショット 2019-06-09 1.40.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430644/0e62d774-96a6-9114-dedb-1decc13c1e20.png">

<参考>
http://www.ocw.titech.ac.jp/index.php?module=General&action=T0300&GakubuCD=4&GakkaCD=342300&KeiCD=&KougiCD=201902434&Nendo=2019&lang=JA&vid=05

### 割り算

割り算（$R_a[X] \div R_b[Y]$）に対するアルゴリズムを考える。

#### 直接法

##### ソートを利用する場合

$R_a$の$X$をマイナー、$X_c$をメジャーでソートし、$R_b$も$X$でソートする。このとき、$X_c$が変わる毎に$X$を付き合わせて最後まで一致すれば商に追加。

<img width="340" alt="スクリーンショット 2019-06-09 14.07.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430644/16555dda-492e-619d-7cb0-e14890424eb2.png">

##### ハッシュを利用した場合

$R_b$に対応したハッシュテーブル$H_1$と商の候補のハッシュテーブル$H_2$に$R_b$に対応したbitを用意する。すなわち、$R_a$をハッシュし$H_1$のエントリを調べ、$H_2$のbitを立てる。

<img width="339" alt="スクリーンショット 2019-06-09 14.10.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430644/fe444bd3-04e1-c49f-ce69-2dd4c8638b33.png">

#### 間接法

集約演算を用いる。すなわち、$R_a$をGroup-Byし、$R_b$と同じCountか調べる。あらかじめR_aをR_bでSemi-Joinしておくことが必要。

<img width="342" alt="スクリーンショット 2019-06-09 14.14.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/430644/cffb1aa2-85a6-c48c-61b4-474125edb68a.png">

### 準結合（Semi-Join）

> 準結合とは、リレーションRとSの自然結合結果から、Sにのみ存在する属性を射影演算にて除去する演算である。

<参考>
https://www.slideshare.net/shoheiyokoyamaac/04-27443570

等結合の結果が一方の関係のみ。このとき基本的なコストは等結合と同じであり、集合演算や、分散データベース等で転送データを絞り込む時に用いられる。

### 集合積

全ての属性に対する等結合または準結合

### 集合和

２つの関係の結合後の重複除去。または、一方の関係と集合差との結合で表される。

### 集合差

全ての属性に対して準結合の結果の補集合タプルを選択（Anti-Semi-Join）。コストは等結合と同じ。
Windowsのロングファイルパスを有効にする

すぐ忘れるのでメモ

## Windows 10 Professional 以上

1. 『グループポリシーの編集』を開く
1. 『コンピュータの構成』→『管理用テンプレート』→ 『システム』 → 『ファイルシステム』を開く
1. 『Win32の長いパスを有効にする』を『はい』にする。

## Windows 10 Home

1. 『レジストリエディタ』を開く
1. 『HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem』をアドレスバーに入力
1. 『LongPathsEnabled』の値を1にする。
3rd Gen AMD Rizen Memo

https://youtu.be/jy0Q75xCwDU?t=4272

# CPU SPEC
* 3700X 8-Core(16 Thread), 4.4/3.6GHz, 65W
* 3800X 8-Core(16 Thread), 4.5/3.9GHz, 105W
* 3900X 12-Core(24 Thread), 4.6/3.8GHz, 105W

# Notable SPECs
* PCI-e Gen4 (X570 M/B と共に)
    * 40 Lane (16 from Chipset / 20 from CPU)
    * 24 Lane CPU から出ているが、4 Lane が Chipset とのリンク用
    * 16 for GPU + 4 for SSD みたいな感じになる？
    * 

# X570 M/B 

ここら辺が詳しい
* https://4chunks.com/2019/05/27/x570-mobos/
* https://g-pc.info/archives/9660/

世代的には、3 x M2.SSD Slot が主流っぽいですね。
（CPU とどう接続されるのかは気になる。1つが直結、他の2つはチップセット経由のはずではある）

# USB
* 3.1 Gen 2 が主流になってはいる。
    * SATA 6.0 Gbps より早い。。。時代だ
GithubのPullRequestを直接チェックアウトする

# GithubのPullRequestを直接チェックアウトする

自分にレビュー依頼が来たPullRequestどうやってチェックしていますか？
複雑なものだと, そのPullRequestをローカルに落としてきて, 実行しないといけないかもしれません。

そうなるとどうやってそのPullRequestを落としてくるかですが…
わざわざ他人のリモートを追加して, 手動マージしていませんか？

実はGithubのPullRequestは（デフォルトでは見れない）ブランチとして存在しています。（自動マージチェックとかしてるじゃんあれは裏で自動でブランチ作ってマージしているからできます。）
なのでPullRequestを落としたければそのブランチをチェックアウトしてあげればいいです。

# 具体的な方法

以下[fastlaneのリポジトリ](https://github.com/fastlane/fastlane)を使ってやってみます。

fastlaneのリポジトリを落としてくると.git/configファイルは次のようになっているはずです。
(sourcetreeで落としてきました。)

```
[core]
	repositoryformatversion = 0
	filemode = false
	bare = false
	logallrefupdates = true
	symlinks = false
	ignorecase = true
[remote "origin"]
	url = https://github.com/fastlane/fastlane.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master

```

fetchの部分を「+refs/pull/*:refs/remotes/origin/pr/*」に書き換えてフェッチし直すと…

```
[core]
	repositoryformatversion = 0
	filemode = false
	bare = false
	logallrefupdates = true
	symlinks = false
	ignorecase = true
[remote "origin"]
	url = https://github.com/fastlane/fastlane.git
	fetch = +refs/pull/*:refs/remotes/origin/pr/*
[branch "master"]
	remote = origin
	merge = refs/heads/master

```

こんな感じでPullRequestの番号に対応したブランチが出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77177/ea9e79b7-431b-4406-6226-58db4e254c3e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77177/491228fc-82dc-3c42-3cff-026a39897ab0.png)

ちなみにheadがPRしたそのもののブランチでmergeがマージ後になります。

以上

# これなに？

[refspec（参照仕様）](https://git-scm.com/book/ja/v1/Git%E3%81%AE%E5%86%85%E5%81%B4-%E5%8F%82%E7%85%A7%E4%BB%95%E6%A7%98%EF%BC%88Refspec%EF%BC%89)ってやつです。
要するにブランチを検索するときのフィルタみたいなやつ（今回はそういう用途で使っています）

今まではrefs/heads/以下にあるものを参照するようにしていましたが, refs/pull以下を参照するように変えました。

# 注意点

1から全部のPRを持っているのでメインのローカルリポジトリに設定たさないで新しいの作ったほうがいいとおもいます。
それでも重ければrefspec調整してください。
PHPでXML読み込み

# 全部読み込み

[simplexml_import_dom](https://www.php.net/manual/ja/function.simplexml-import-dom.php)や[simplexml_load_string](https://www.php.net/manual/ja/function.simplexml-load-string.php)で[SimpleXMLElement](https://www.php.net/manual/ja/class.simplexmlelement.php)を作る

[要素へのアクセスの仕方](https://qiita.com/horikeso/items/dd8bd2995e880ca7cb8a#simplexmlelement%E3%82%92%E4%BD%BF%E3%81%86)

# ストリーム

メモリを気にするならこっち

[XMLReader](https://php.net/manual/ja/class.xmlreader.php)を`open`でファイルを指定して使う
`XMLReader::expand`を使えば[DOMNode](https://www.php.net/manual/ja/class.domnode.php)に変換できるので`DOMDocument::importNode`で[DOMDocument](https://www.php.net/manual/ja/class.domdocument.php)を作ることもできます。

```php
$xmlReader = new XMLReader();
$xmlReader->open('test.xml', 'UTF-8', LIBXML_NOBLANKS);

while ($xmlReader->read())
{
    $xmlReader->name;
    $xmlReader->getAttribute('属性');
    $xmlReader->value;
}

$xmlObject->close();
```
# その他

## XXE対策

libxmlのバージョンによっては外部実体参照がデフォルトで無効になっていないものがる。

[libxml_disable_entity_loader](https://php.net/manual/ja/function.libxml-disable-entity-loader.php)

## CDATA

XMLの要素には、特殊文字を直接記述することができない。
直接記述したい場合は`<![CDATA[`～`]]>`を記載することでその間に記述することは可能。（間に終了の`]]>`を含めることは出来ない）
`<![CDATA[`～`]]>`を使わない場合はエスケープする。

```xml
<element><![CDATA[XXXXXXXXXX<p>XXXXXXXXXX]]></element>
```

```xml
<element>XXXXXXXXXX&lt;p&gt;XXXXXXXXXX</element>
```
DataTablesで画面切り替え時にLayzrで画像遅延表示

# 概要
DataTablesを使った画像のあるテーブルで、画面切り替え時に画像の遅延表示がうまくいかなかったので試行錯誤した結果メモ。

[DataTablesの詳細はこちら。](https://www.datatables.net/download/index)

# 注意点
・Bootstrap v3.3.7
・jqueryは別途必要
・DataTablesではthead,tbodyは必須なので忘れないように
・画像遅延は[Layzr.js](https://github.com/callmecavs/layzr.js)
・Layzrはversion2系は動かし方が分からないので1.4.3です

# html側
```html
<html>
<head>
  <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs-3.3.7/dt-1.10.18/af-2.3.3/b-1.5.6/fh-3.1.4/kt-2.5.0/r-2.2.2/sc-2.0.0/sl-1.3.0/datatables.min.css" />
  <!-- 他のstyle処理 -->
  <!-- jquery.cssやjquery.js -->
  <!-- bootstrapもここでいれる -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/layzr.js/1.4.3/layzr.min.js"></script>
  <script type="text/javascript" src="https://cdn.datatables.net/v/bs-3.3.7/dt-1.10.18/af-2.3.3/b-1.5.6/fh-3.1.4/kt-2.5.0/r-2.2.2/sc-2.0.0/sl-1.3.0/datatables.min.js"></script>
</head>
<body>
  <table id="main-table">
    <thead>
      <tr>
        <th>img</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><img data-layzr="/img/sample.jpg"></td>
      </tr>
      <tr>
        <td><img data-layzr="/img/sample.jpg"></td>
      </tr>
      <tr>
        <td><img data-layzr="/img/sample.jpg"></td>
      </tr>
      <!-- 以下、trの繰り返し -->
    </tbody>
  </table>
</body>
</html>
```

# javascript側
```html
<!-- 初期読み込み -->
<script>
    window.addEventListener('load', function () {
        var layzr = new Layzr();
    }, false);
</script>

<!-- 画面切り替え時 -->
<script>
    $(function(){
        $("#main-table").DataTable(
            {
                drawCallback: function(){
                    new Layzr();
                }
            }
        );
    });
</script>
```
競馬データベース作るためのスクレイパー書いた

# 何を作ったか
[netkeiba](https://www.netkeiba.com/?rf=logo)からデータを取ってきて競馬データベースをつくるプログラム。
[これ](https://github.com/watanta/netkeiba-scrapy)

こんな感じのデータベースができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132734/3854023f-adb0-2566-9ce7-91d3ad57998a.png)

# 特徴
クローラをスクレイパーを分けた。一緒くたに処理するよりもエラーに対して損失がすくないはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132734/abda1e12-984d-afd3-94a8-58201fd6f8f9.png)


クローラは[scrapy](https://scrapy.org/)を使用している。

#
arduino ideからesp8266ボードが消えた。

#概要

arduino ideからesp8266ボードが消えた。

#環境

arduino ide 1.8.5

#対処1

ボードマネージャーで、再インストールしたが、コンパイル時esp8266が無いと言う。

#対処2

AppData\Local\Arduino15\packages\esp8266\hardware\esp8266フォルダを削除して、再インストール。

以上。
プログラミングが気になる人向けのまずは触ってみ講座(事前準備編)

#書いた経緯
友人の交換条件でプログラミングを教えて欲しいという話になったので教科書がわりに書くことにしました。

#注意事項
プログラマーに転職して間もない僕が独断と偏見による記述をしていますので、決して鵜呑みにしないでください。詳細は基本省くので各自検索をお願いします。今回は習うより慣れろを重視します。

#用意するもの
##パソコン
正直これが無いと始まりません。買うかレンタルして、どうぞ。
##エディタ
文章を編集するためのソフトですね、メモ帳でも確かいけますがみにくいので別途用意しましょう、macならsublinetext、winならvscodeあたりをオススメします。
インストールが必要です。
##ターミナル
phpをインストールするのに必要です。macは標準装備。
##html css
見た目に関わる言語ですね、ファイルを作成するだけでいいので特に事前準備はいりません。
##php
主に計算に関わる言語です、種類は他にも色々ありますが今回はphpで。
インストールが必要です。
#MAMP
phpの開発環境に必要です、他にもあります。
これを経由してブラウザに表示させます。インストールが必要です。
#javascript jquery
見た目を動かすときに関わる言語のひとつです、見た目に拘りたいあなたに。　jqueryはファイルのダウンロードが必要です。

これだけあれば初めて触るには十分かなと思います。
次回はhtml cssから試しに触ってみましょう。
swift置き換え

# 電卓アプリで置き換えに困ったので備忘録として記載
参照元:[Swift実践入門 〜 今からはじめるiOSアプリ開発！ 基本文法を押さえて、簡単な電卓を作ってみよう](https://employment.en-japan.com/engineerhub/entry/2017/05/25/110000)

```swift:ViewController.swift
private func formatFormula(_ formula: String) -> String {
    // 入力された整数には`.0`を追加して小数として評価する
    // また`÷`を`/`に、`×`を`*`に置換する
    let formattedFormula: String = formula.replacingOccurrences(
        of: "(?<=^|[÷×\\+\\-\\(])([0-9]+)(?=[÷×\\+\\-\\)]|$)",
        with: "$1.0",
        options: NSString.CompareOptions.regularExpression,
        range: nil
        ).replacingOccurrences(of: "÷", with: "/").replacingOccurrences(of: "×", with: "*")
    return formattedFormula
}
```

replacingOccurrences(日本語:置換発生) = 置き換えをすること
of を with に変更する
例


```swift:ViewController.swift
private var str:String = "aaa" {
        of: "aaa",
        with: "bbb",
        }
    print(str)
// "bbb" が出力される
}
```


of: 置き換え前
with 置き換え後
options:完全一致等
例:NSString.CompareOptions.regularExpression(string型.完全一致.半角)
(何もオプションがない場合には.literal)
range:どの範囲を指定するか
指定しない場合には、 nil 

## 参考サイト
参照元
[Swift実践入門 〜 今からはじめるiOSアプリ開発！ 基本文法を押さえて、簡単な電卓を作ってみよう]()
[Swift 3.0でStringはどうなったか ](https://samekard.blogspot.com/2016/09/swift30string_13.html)
[stringをこねくり回すネタ集 swift 3.0](https://qiita.com/Saayaman/items/6c98fd27e2469df4b1c0)
[NSString 比較系メソッド覚書](https://qiita.com/ktysne/items/bfb313df8c7e3d62f688)
ブラウザで長時間処理を行う際の設定(Nginx PHP-FPM)

# ブラウザで504が出る場合に確認する設定

XXXは数字

## nginx.conf（リバースプロキシ）

proxy_connect_timeout XXX;
proxy_send_timeout XXX;
proxy_read_timeout XXX;

## nginx.conf（PHP-FPM）

※locationの内側
fastcgi_send_timeout XXX;
fastcgi_read_timeout XXX;

keepaliveは再コネクションなので関係ないらしい

## php-fpm.conf

※[global]の外側
request_terminate_timeoutの設定があれば無制限か伸ばす

request_terminate_timeout = XXX


## php.ini

max_execution_timeの設定があれば無制限か伸ばす

max_execution_time = XXX

## 反映

```
systemctl restart php-fpm
systemctl restart nginx.service
```

## その他

ELBのアイドルタイムアウトの設定 default 60s なので XXXに変更する必要がある。
[個人的備忘録]GoogleDrive内のファイルを特定する際のMIMEタイプについて

# 背景

GoogleDriveに保存しているファイルをGoogleAppsScriptで処理かけようとしたときに、
ファイルの拡張子で処理対象のファイルだけイテレーションまわしたくなり、
APIドキュメントで getFilesByType() を確認したら、拡張子じゃなく、「MIMEで指定してね！」と書かれていたので、都度、調べるのも面倒なので備忘のため。

# 結論

GoogleAppsScriptでのMIMEは特に悩む必要はなく、
下記APIにある通り、`MimeType`というEnumで提供してくれている。
https://developers.google.com/apps-script/reference/base/mime-type

上記のEnumを使わなくとも、`image/png`みたいな形でも良い。

```ts:例
var gifFiles = DriveApp.getFilesByType(MimeType.GIF);
while (gifFiles.hasNext()) {
 var gif = gifFiles.next();
 Logger.log(gif.getName())
}
```

# 疑問

以下は、暇な時に調べておく。

- `.py`とか、MIMEでは特定できないものはどう特定するかは調べておきたいな。
電源ボタンで安全にシャットダウンさせる方法

# はじめに

Linuxを実機で動かしている時に、Windowsと同じように「電源ボタンをポチっと押しただけでシャットダウンできないか？」と思い立ち、ちょっと調べてみたら簡単に実現できることが分かりました。

この設定を活用すれば、ネットワーク周りの設定でミスした際に「モニターとキーボードを繋いで再起動」せずに済むので、覚えておくとちょっと便利かもしれません。

# 使用した環境

* OS：CentOS 6.10

# 設定方法

1. acpidという電源管理に関するパッケージをインストールします。
2. `/etc/acpi/events/power.conf`を編集して、「電源ボタンが押された際に、シャットダウンコマンドを実行する」と設定します。
3. acpidの自動起動設定を済ませた後、acpidのサービスを起動して完了です。

```
[root@akagi ~]# yum install acpid

[root@akagi ~]# vi /etc/acpi/events/power.conf 
-------------------------------------------------------------
# ACPID config to power down machine if powerbutton is pressed, but only if
# no gnome-power-manager is running

event=button/power.*
#action=/etc/acpi/actions/power.sh
action=/sbin/shutdown -h now
-------------------------------------------------------------

[root@akagi ~]# chkconfig acpid on
[root@akagi ~]# service acpid start
```
javascriptのSingletonパターン

# Singletonパターンとは
そのクラスのインスタンスが1つしか生成されないことを保証するデザインパターンのことである

## Singletonパターン例
```js
var singleton = function( name ){
  this.name = name;
};
Singleton.prototype.getName = function(){
alert ( this.name );
};
Singleton.getInstance = (function(){
  var instance = null;
  return function( name ){
    if ( !instance ){
      instance = new Singleton( name );
    }
  return instance;
}
})();

var a = Singleton.getInstance( 'instance1' );
var b = Singleton.getInstance( 'instance2' );

console.log(a === b); // true
```

上記の例、if ( !instance )文で何度getInstance()を呼び出しても常に同じインスタンスが返されることを保証できます。
が、上記の例では芳しくないところもあります：
上記の例でインスタンス取得方式はstatic的なgetInstance()が、new Class名()でインスタンスを取得するのが一般的です。

## Singletonパターン例-その二

```js
var Create = (function(){
  var instance;
  var Create = function( html ){
    if ( instance ){
      return instance;
    }
    this.html = html;
    return instance = this;
  };
  return Create;
})();
var a = new Create( 'instance1' );
var b = new Create( 'instance2' );
console.log(a === b); // true
```
上記の例も何度new CreateDiv()を呼び出しても常に同じインスタンスが返されることを保証できます。
が、この例も完璧とは言えないです。

* 読みにくい
* 同じインスタンスが返されることを保証できるロジックとクラス本体初期化処理が混ざる

## Singletonパターン例-その三

```js
var Create = function( html ){
  this.html = html;
  this.init(); // 初期化処理
};
CreateDiv.prototype.init = function(){
  // do something
};

// 同じインスタンスが返されることを保証するロジックを切り出す
var SingletonCreate = (function(){
  var instance;
  return function( html ){
    if ( !instance ){
      instance = new Create ( html );
    }
    return instance;
  }
})();
var a = new ProxySingletonCreateDiv( 'instance1' );
var b = new ProxySingletonCreateDiv( 'instance2' );
console.log(a === b); // true
```
やっといい感じになりました、
インスタンス返す処理とクラス本体処理を分けることで、

* 読みやすい
* 修正しやすい
* Createみたいな他のクラスを追加される時に、SingletonCreateを流用できる

# Singletonパターンのユースケース
I/O処理(ファイル出力のストリームを複数持つことはできません)などの単一インスタンスの数を制限したい場合

# 参考
1. zeng tan.2015. Design Pattern And Development Practice Of JavaScript
Unity Editor拡張 選択履歴の戻る･進む

こちらの記事の選択戻るが便利でした
[[Unity] Editor拡張でInspectorの"戻る"を実現する](https://qiita.com/lycoris102/items/b2ffc86f94e904fd50fd)

修正をしまして､履歴内｢進む｣もできるようにしました

AssetStoreを利用するのを勧められていましたが
私にとっては､これぐらいの機能でちょうど良いと感じています


## 実行方法

### 実行環境
Unity 2019.1

### コンパイル後
メインメニューに
Editor/SelectionHistory/Back
Editor/SelectionHistory/Forward
が作成されます

メニューからの起動では､便利ではない(むしろ面倒くさい)ので
ショートカットキーを割当ててください

## コード

```
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;

namespace SelectionHistory.Editor
{
    public static class SelectionHistory
    {
        private static List<Object[]> _history;
        private static int _currentPosition;

        [InitializeOnLoadMethod]
        public static void Init()
        {
            _history = new List<Object[]>();
            _currentPosition = -1;
            Selection.selectionChanged += () => Set(Selection.objects);
        }

        private static void Set(Object[] objects)
        {
            if (objects.Length == 0) return;

            // 同じなら追加しない
            // Objects内容が同じでも順番が異なる場合は違うものとして判定される
            if (_currentPosition != -1 && objects.SequenceEqual(_history[_currentPosition]))
            {
                return;
            }

            // 追加する場合
            // カレントが途中にある場合､最後まで削除する
            if (_currentPosition != _history.Count - 1)
            {
                // 削除
                var n = _history.Count - (_currentPosition + 1);
                _history.RemoveRange(_currentPosition + 1, n);
            }

            _history.Add(objects);
            _currentPosition++;

            // 100より大きい場合､最初を削除する
            if (_currentPosition > 100)
            {
                _history.RemoveAt(0);
                _currentPosition--;
            }
        }

        [MenuItem("Edit/SelectionHistory/Back")]
        public static void Back()
        {
            if (_currentPosition <= 0) return;
            _currentPosition--;
            Move(_history[_currentPosition]);
        }

        [MenuItem("Edit/SelectionHistory/Forward")]
        public static void Forward()
        {
            if (_currentPosition >= _history.Count - 1) return;
            _currentPosition++;
            Move(_history[_currentPosition]);
        }

        private static void Move(Object[] objects)
        {
            Selection.objects = objects;
        }
    }
}
```