OmniAICreator/Qiita-1.07M huggingface dataset:
MacでVagrant使うときいつも/etc/sudoersに書くやつ

NFS マウントと hostsupdater プラグインを使うときパスワードを入力しなくてもいいようにするには以下を `/etc/sudoers` に追記。

```:/etc/sudoers
    :
    :

# Allow passwordless startup of Vagrant when using NFS.
# https://gist.github.com/joemaller/6764700
Cmnd_Alias VAGRANT_EXPORTS_ADD = /usr/bin/tee -a /etc/exports
Cmnd_Alias VAGRANT_NFSD = /sbin/nfsd restart
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /usr/bin/sed -E -e /*/ d -ibak /etc/exports
%admin ALL=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD, VAGRANT_EXPORTS_REMOVE

# Allow passwordless startup of Vagrant with vagrant-hostsupdater.
# https://github.com/cogitatio/vagrant-hostsupdater#linuxos-x-passwordless-sudo
Cmnd_Alias VAGRANT_HOSTS_ADD = /bin/sh -c echo "*" >> /etc/hosts
Cmnd_Alias VAGRANT_HOSTS_REMOVE = /usr/bin/sed -i -e /*/ d /etc/hosts
%admin ALL=(root) NOPASSWD: VAGRANT_HOSTS_ADD, VAGRANT_HOSTS_REMOVE
```
Leaflet.js を使って GeoJSON データを地図上に表示してみる その１

表示しようと思うデータは[静岡県掛川市 施設検索](http://www.city.kakegawa.shizuoka.jp/map.html)の「[市役所・支所などのオープンデータ](http://www.city.kakegawa.shizuoka.jp/data/open/cnt/3/1877/1/siyakusyosisyo.csv)」

まずは下準備として、このCSVファイルをGeoJSONに変換。
#Step 1: Select your input
[CSV To GeoJSON Converter](http://www.convertcsv.com/csv-to-geojson.htm)
を開いて
paste into Text Box below
にコピーしたCSVデータをペースト

#Step 2: Choose input options
First row is column names にチェック
Limit # of lines:にデータの行数を入力（必要？）
Field Separator:　"," を選択

#Step 3: Choose output options (optional)
Latitude Field #
Longitude Field #
それぞれに
Latitude（緯度）
Longitude（緯度）（日本だと'137.988683'のように桁数が長い=Longの方がこちら ）
の列番号を入力（1列目は１）

#Step 4: Generate output
Converter CSV To GeoJSON ボタンを押して、生成されたGeoJSONをコピペ OR DownLoad する。

＊今回使用したデータの列見出しに ':' が入っていて、Leaflet.jsで読み込んだ時に不具合があったので、あらかじめ ':' 等は取り除いておいた方がよいかも。
MacとUnity2017.4.1f1とMadMapperでプロジェクションマッピング

# 概要
* Unityで生成した画面をプロジェクションマッピングとして投影する
* 映像を書き出して投影するのではなく、Unity製実行ファイルの画面を投影するので、インタラクション演出やデバッグが可能
    * 例 : 任意のトリガーで適用しているMaterialを変更することで見た目を変える
* マルチディスプレイ設定になっていることが前提  
→ [Unity 2017\.4\.1f1 と Mac でマルチディスプレイ実行 \- Qiita](https://qiita.com/reona396/items/e10e2c0fdef9263cc939)  
**【2018/12/03 追記】 上記の記事に書いている [Player 設定](https://qiita.com/reona396/items/e10e2c0fdef9263cc939#player-%E8%A8%AD%E5%AE%9A) を設定せずに動かすとMadMapperに正常に映像が送られませんでした。設定をおすすめします。**

# 実験環境
* Mac High Sierra 10.13.4
* Unity 2017.4.1f1
* MadMapper 3.3.0 Demo版(※あくまでDemo版なので色々と制限があることに注意)
* 任意の台数のプロジェクター

# 設定

## UnityからMadMapperへの接続
Funnelを利用した
[keijiro/Funnel: A Syphon server plugin for Unity](https://github.com/keijiro/Funnel)

1. 上記からUnity用plugin packageをダウンロード
2. 適用したいUnityプロジェクト上でpackageを展開
3. プロジェクタで投影したいCameraにFunnel.csをアタッチ  
    * 画面サイズを設定できるので適切に設定しておく(ここが合っていないと投影時にぼやける)
4. UnityプロジェクトをBuild And Run  
    * Build Settings > Player Settings > Resolution and Presentation > Run in Background にチェックを入れること  
    * 指定したい画面サイズが実行開始時のダイアログのリストにない場合、以下を参考に任意の大きさのサイズで生成する  
[[Unity] PC実行時のWindowsサイズの設定の仕方＆起動時フック - Effectiveさお](http://h-sao.com/blog/2016/05/08/change-unity-window-size/)
5. MadMapperを起動し、右メニューに表示されている素材サムネイルの Syphon 欄に実行中のUnityの画面があることを確認  
    * 先ほどFunnel.csをアタッチしたCameraの数だけあるはず

## MadMapperの使い方

### プロジェクタの設定

1. 左メニューのプロジェクタアイコンをクリック  
![スクリーンショット 2018-04-25 19.11.34.png](https://qiita-image-store.s3.amazonaws.com/0/67311/3465d7a9-6d98-2519-0015-48234c4fc7c1.png)
2. プラスアイコンをクリックしてプロジェクタの台数分増やす
3. それぞれのプロジェクタの Output Destination 欄で出力先を設定する
4. 中心の画面上で黄色い枠線を重ならないように並べ替える

### 素材の設定

1. 左メニューのなんか4つ丸がついてる四角アイコンをクリック  
![スクリーンショット 2018-04-25 19.11.52.png](https://qiita-image-store.s3.amazonaws.com/0/67311/fd4d3ac5-bf88-4659-6890-a42ac22588c8.png)
2. 右メニューの素材サムネイルから配置したい素材を中央のプロジェクタ枠(黄色い枠)内に向かってドラッグ&ドロップ
3. メニューバー > Output > Full Screen Mode をクリック
4. 配置された素材の四隅を実際に投影しながら形を合わせていく
    * マウスで頂点を選択して動かしたり、十字キーで少しずつ合わせていく

# 参考URL
* [【続】Unityで3Dテレビ向けに視差映像を作ってみる【Unity×openFrameworks】 \- Qiita](https://qiita.com/KentaKato/items/e929b637d4a2ada88e1c)
* [MadMapperプロジェクター設定 – hal](http://hal.wp.xdomain.jp/?p=685)
* [プロジェクター2台連結で超ワイドスクリーン作ってみた。 : 最新VJ機材とVJソフトの情報](http://blog.livedoor.jp/vdmx5/archives/26765591.html)
Google Code Jam 2018 Qualification Round - Go, Gopher!（IOUArray版)

# O(1)のリスト（配列）アクセス

IOUArrayを使うとO(1)での要素アクセスが実現できるそうです

IOモナド環境に限定されてしまいますが、どうせ対話式でIOモナドのなかで動作しているので都合は悪くなさそうです。

# 実装

リスト版とほとんど同じですね

```gcj.hs
import Control.Monad
import System.IO
import Data.Array.IO

type IOField = IOUArray (Int,Int) Int

solve :: Int -> IOField -> Int -> IO ()
solve a f n = do
    putStrLn $ shows n " 2"
    (x:y:_) <- (map read.words) <$> getLine
    writeArray f (x,y) 1
    s<-(\a b c->a+b+c)<$>readArray f (n-1,1)<*>readArray f (n-1,2)<*>readArray f (n-1,3)
    case s of
        3 | n < a  -> solve a f $ n+1
        3 | n == a -> s2 $ n+1
        otherwise  -> solve a f n

s2 n = do
    putStrLn $ shows n " 2"
    (x:y:_) <- (map read.words) <$> getLine
    case (x,y) of
        (0,0) -> return ()
        (_,_) -> s2 n

main = do
    hSetBuffering stdout NoBuffering
    t <- readLn
    replicateM_ t $ do
        a <- readLn
        area <- newArray ((1,1), (67,3)) 0 :: IO IOField
        solve ((a+2) `div` 3 -2) area 2
```

## type宣言

型：IOUArray (Int,Int) Intはいかにも長いので別名を宣言しておきます。
O(1)でアクセスできるので普通に2次元配列にしています
Javaのお勉強 ～その0～ 概要

# 1. はじめに
これからJavaの基本的な処理の流れから構文について記事を書ければなぁと思ってます。
Javaを一から知りたい、勉強したい方に向けてということで、、

今回は、Javaが動く上での流れを説明します。
概要のようなものですね。
~~この回は詳しく知っていても知らなくても案外なんとかなります 笑~~

プログラミングについては、次回から書き始めたいと思います。

# 2. プログラミングの流れ
ざっくりですが、Javaのプログラムの作成から動きについて

## 2-1. プログラムの作成
まずはファイルの作成からですね。
Javaですと、[.java]という拡張子が決まりなので、例で Hoge.java のようなファイルを作るわけです。
そして、プログラムを書いたファイルのことを「**ソースコード**」と言います。
プログラムを記述していくわけですが、詳細は後の記事にて記述していきます。

ソースコードの作成と編集は、基本的にOSに入っているテキストエディタでも可能ですが、統合開発環境(IDE)と呼ばれるプログラム開発用ソフトウェアを使うと非常に便利です。例）Eclipse, NetBeans etc...
IDE使うと、綺麗にフォーマットしてくれたり、予測変換を出してくれたり、ファイル管理がしやすくなる等のメリットがあり、開発現場ではよく使われています。

## 2-2. コンパイル
ソースコードはあくまで人間が理解するためのものであり、コンピュータはソースコードのままでは処理を実行することができません。
ですので、コンピュータが理解できるように変換する必要があります。

変換する作業のことを、「**コンパイル**」といいます。
コンパイルするためのコマンドは、「javac ファイルパス/ファイル名.java」(IDEを使っていればスルーでOK)

そして、コンパイルされたソースコードのことを「**バイトコード**」といい、[.class]ファイルが作成されます。
このバイトコードは、JVM(Java Virtual Machine)上で実行する中間的な言語になります。

JVMはプログラムとコンピュータの間にある仮想的なコンピュータです。
JVMがあるおかげでWindows, Mac OS, Linuxなどで特殊な設定なしに動かせます。

「Write Once, Run Anyware」(一度プログラムすればどんな環境でも動く)
これはJavaのコンセプトですが、これはJVMで実現しているような感じです。
~~ちょっと脱線したかな？ 笑~~

## 2-3. 実行
JavaではバイトコードをJVM上で、「**ネイティブコード**」に変換しコンピュータは、このネイティブコードを理解し実行します。
実行するためのコマンドは、「java class名」(IDEなら「実行」ボタンをポチッ)

# 3. おわりに
まとめると、

>ソースコード (.java)
>　↓　コンパイル
>バイトコード (.class)
>　↓　JVM
>ネイティブコード
>　↓　コンピュータ
>実行

という流れになります。

基本的にプログラミング言語は、インタプリタ方式やコンパイラ方式などに分かれるのですが、
Javaは他の言語とは異なり、インタプリタ方式とも、コンパイラ方式とも...
どちらの性質も兼ね備えている気がします。

今回は実行までのプロセスだけを記述して、プログラミングには触れていませんが、次回以降はプログラミングを始めて行きたいと思います。

次回 →「[Javaのお勉強 ～その1～ Hello World](https://qiita.com/koukonko/items/98d36c3bae2f5e119bd7)」
Vagnrat Ubuntu16.04 apt upgrade のGRUBで更新が止まる時の対策

どうも、ゆうきゃんです。
初めてUbuntuの環境を構築したらOSの更新で初っ端つまづきました。
対処法を考える。LinuxはCentOS7を少し触る程度です。

# 環境

- Ubuntu16.04.4
- Vagrant 2.1.1
- VirtualBox 5.2.12r122591

# 実施コマンド等

## VagrantでUbuntuの環境を構築

```
$ vagrant init -m bento/ubuntu-16.04
$ vagrant up
$ vagrant ssh
$ sudo su -
```

rootユーザーで作業する。

## 問題

```sh
# apt update
# apt -y upgrade
```

![スクリーンショット 2018-05-22 12.56.47.png](https://qiita-image-store.s3.amazonaws.com/0/52879/fd1eb518-b32e-47e9-c97b-56690f312b77.png)
![スクリーンショット 2018-05-22 13.47.39.png](https://qiita-image-store.s3.amazonaws.com/0/52879/97942cc2-6095-7276-cab2-fc573f44061c.png)

謎のGRUB設定画面が表示されました。

```
A new version (/tmp/grub.KhDEMU4OUc) of configuration file /etc/default/grub is available, but the version installed currently has been locally modified.

What do you want to do about modified configuration file grub?
- install the package maintainer's version
- keep the local version currently installed
- show the differences between the versions
- show a side-by-side difference between the versions
- show a 3-way difference between available versions
- do a 3-way merge between available versions (experimental)
- start a new shell to examine the situation
```

```
GRUB install devices:

[ ] /dev/sda (68719 MB; VBOX_HARDDISK)
[ ] - /dev/sda1 (510 MB; /boot)
[ ] /dev/sda5 (68205 MB; VBOX_HARDDISK)
[ ] /dev/dm-0 (67129 MB; vagrant--vg-root)
```

うーん、謎です。Ubuntuは難しい。。
最終的にシェルでプロビジョニング化したいので、非インタラクティブでなんとか完結させたい。

# 対策

軽く調べたところ、GRUBとはOSを起動するために必要なブート・ローダだそうです。
https://www.express.nec.co.jp/linux/distributions/knowledge/system/grub.html

別に最新である必要は今の所なさそうなので、GRUBの更新はスキップさせる方針にします。

## 実施コマンド

grub-pc を apt upgrade 時に除外する設定をします。

```sh
# echo grub-pc hold | dpkg --set-selections
```

再度、 apt upgrade する。

```sh
# apt update
# apt -y upgrade
```

問題なく正常終了。

# 参考

- [apt-get upgradeから特定パッケージを除外する](https://qiita.com/strsk/items/c933a661c077a666073a)
- [Vagrantで、apt-get upgradeを含んだプロビジョニングで発生するエラーについて](http://stupiddog.hatenablog.com/entry/2014/08/10/003527)

# あとがき

本当はちゃんとアップデートできるといいのですが、私の知識では良い方法を見つけられませんでした。。。
また、Ubuntuは日本語情報が少なくて英語読めない私にはちょっとつらいOSですね...
WSLでfishをログインシェルにすると起動しない

## 問題
`chsh`でfishを設定する。又は、.bashrc内で`exec fish`で呼ぶと`Welcome to fish, the friendly interactive shell`が表示された後、プロンプトの表示まで辿り着きません。
.bashrc内で`exec fish -d 3`以上で確認すると、何かを試し続けている様子が見られます。

## 環境
+ Ubuntu 18.04
+ fish 2.7.1

## 対処
fishのPIDが2の時に問題があるようなので、それを回避します。[^1]
既にログインシェルをfishにしてしまった場合は、ubuntuを2つ起動すると片方はプロンプトが表示されるので、そちらで作業してください。

### シェルスクリプトの作成
`sudo vim /bin/fish-starter`等でシェルスクリプトを作成。

```shell:/bin/fish-starter
#!/bin/bash
fish "$@"
exit $?
```

### 実行権限を付与
``` shell
sudo chmod 755 /bin/fish-starter
```

### shellsに追記
fish-starterをログインシェルにするために/etc/shellsに下記を追記します。

```shell:/etc/shells
/bin/fish-starter
```

### ログインシェルの変更
```shell
chsh -s /bin/fish-starter
```

### 起動確認
ウィンドウを閉じてubuntuを起動すると無事プロンプトが表示されると思います。
`ps`で確認するとPIDが3になっています。

```shell-session
$ps
  PID TTY          TIME CMD
    2 tty1     00:00:00 fish-starter
    3 tty1     00:00:00 fish
   13 tty1     00:00:00 ps
```

## 終わりに
このバグはmasterブランチでは既に修正されています。[^2]
fishのバージョンが上がるのを待ちましょう。

### issue
[Bracketed paste mode causes fish to hang on WSL if started as PID=2 #4582](https://github.com/fish-shell/fish-shell/issues/4582)

[^1]: 詳しくはissueを見て下さい。
[^2]: [該当コミット](https://github.com/fish-shell/fish-shell/commit/52627199952b35b65d0b6135361e365fb9f2dfc1)
PostgreSQL の pg_restore でリストアしたくないテーブルを除外する

[`pg_restore -l` と `pg_restore -L` を使う。](https://www.postgresql.jp/document/9.6/html/app-pgrestore.html)

# 手順

## 1. リストアされる内容の一覧を出力

```bash
pg_restore -l dump_file_name > content_list
```

## 2. リストアされる内容の一覧の確認と修正

```bash
vim content_list
```

リストアされる予定のテーブル定義やレコードが確認できるので、除外したい部分をコメントアウトする

```
;いらんテーブル
;000 000; 000 0000 TABLE public unused_table ...

...

;いらんデータ
;0000; 0 00000 TABLE DATA public unused_records ...
```

## 3. リストアする

```bash
pg_restore -L content_list dump_file_name
```

便利！

# 参考ページ

- [Exclude Table during pg_restore - Stack Overflow](https://stackoverflow.com/a/39831653)
    - ここの通りやってたらできた
- [pg_restore - PostgreSQL 9.6.5文書](https://www.postgresql.jp/document/9.6/html/app-pgrestore.html)
    - 公式ドキュメント
CUDAをローカルにインストールして好きなCUDAを呼び出す

(2020年10月更新: 設定画面が変わっていたため最新版のも更新)

近年はGPUとディープラーニング技術の発展により幅広いタスクに適用できるようになってきました (それに伴ってGPUの太さも幅広くなってきました)。

さて皆さんは自分の環境でsudoが使えますか?
会社に勤めている方などは使えないことが多いでしょう。

最近はディープラーニングフレームワークの発展によってpipやcondaのみでsudoを使わず、GPUが簡単に使えるようになってきていますが、それでも依然としてCUDAをインストールする必要性に迫られることもあるでしょう。

CUDAは欲しいけどsudoなんて使えないし、システムのCUDAを変更するなんて怖いぜって時はローカルにインストールだ!

ファイルのダウンロードは古いやつと同じですが、10.x以降はかなり操作が変わっているので、その手順を説明します。

# runファイル起動後

`sh cuda_**_linux.run`

をした後、以下のような画面となります。

![Screen Shot 2020-10-28 at 22.21.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90422/a9bf4ab6-80aa-6d18-2efb-08e71993a3c6.png)

`accept`とタイプします。

その後は以下の画面になりますので、Enterを押して、以下のように`CUDA Toolkit 10.1`のみインストールするようにしてください。

![Screen Shot 2020-10-28 at 22.22.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90422/2a6a5e72-d9da-9f9e-c06f-e14f57160643.png)

次に`CUDA Toolkit 10.1`にカーソルを合わせて`A`をタイプします。
そうすると次の画面に遷移するので`Change Toolkit Install Path`にカーソルを合わせEnterを押すと、インストールパスを入力できるようになるので、入力します。
その後、以下のように全てのチェックを外してください (/usr/localのファイルはsudoが必要なので、できません)。

![Screen Shot 2020-10-28 at 22.26.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90422/1fd4a25d-cef0-5aa0-0ede-f0f3e72bab52.png)

そして`Done`→`Install`でインストールを行えるはずです。

# 古いやつ (9.xより古い場合)

想定環境,前提は以下の通りとなります。
- Ubuntu 16.04
- Nvidia-driverは入っている
- CUDA9.1は`/usr/local`とかにあるけどCUDA9.0が欲しい
- **sudoは使えない**

## インストール

sudoは使えない前提なので当然`apt`やらは使いません。

まずは公式ページへいきLegacy Releasesへ
[https://developer.nvidia.com/cuda-downloads](https://developer.nvidia.com/cuda-downloads)

![スクリーンショット 2018-05-22 1.37.46.png](https://qiita-image-store.s3.amazonaws.com/0/90422/dbb536d5-8916-3ae7-66c4-e5b4c1a89372.png)

重要なのは`runfile(local)`を選ぶこと。
でBase Installerでダウンロードしてください。

![スクリーンショット 2018-05-22 1.43.19.png](https://qiita-image-store.s3.amazonaws.com/0/90422/e10fccd1-3c42-025f-c1b9-b4485a9bab07.png)

んで好きなところにおいて起動。
Instructionsにsudoって書いてるやんけ!っていう人,
焦らないでください。これはこのrunfileのデフォルトインストール先が`/usr/local`
なだけで起動自体にはsudoは必要ありません。
なのでsudoを外して起動しましょう。

```
sh cuda_**_linux.run
```

そうすると利用規約が出ます。
もう一回読んでるって方は`q`を押すことでスキップできます。
そして`accept`とタイプ。

そしてこんな感じで設定。  
  
```

# ドライバーいる? (いるならyで)
Install NVIDIA Accelerated Graphics Driver for Linux-x86_64 375.26?
(y)es/(n)o/(q)uit: n

# CUDA 9.0インストールする? (ここ重要1,絶対y)
Install the CUDA 9.0 Toolkit?
(y)es/(n)o/(q)uit: y

# パスを指定してね(ここ重要2)
Enter Toolkit Location
 \[ default is /usr/local/cuda-9.0 \]:/home/hogehoge/cuda-9.0

# symbolic linkいる? (たぶん作れないのでn)
Do you want to install a symbolic link at /usr/local/cuda?
(y)es/(n)o/(q)uit: n

# サンプルいる? (煙がもやもやするやつ。好きならどうぞ)
Install the CUDA 9.0 Samples?
(y)es/(n)o/(q)uit: n
```

しばらく待ちます。
これでOK。

# パス通し
インストールしたcudaを環境変数の$LD_LIBRARY_PATHを通しましょう。

# CuDNNのインストール
Tensorflowなどのフレームワークを使う場合大抵CuDNNを入れる必要があるため入れましょう。

公式ページ(会員登録が必要です)
[https://developer.nvidia.com/rdp/form/cudnn-download-survey](https://developer.nvidia.com/rdp/form/cudnn-download-survey)

```
tar xzvf cudnn-**.tgz 
cp -a cuda/lib64/* /home/hogehoge/cuda-9.0/lib64/
cp -a cuda/include/* /home/hogehoge/cuda-9.0/include/
```

[参考](https://qiita.com/JeJeNeNo/items/05e148a325192004e2cd)

これで完了!
お疲れ様でした。
フィッシャールールのチェスクロック

# フィッシャールール is 何
* チェス用の持ち時間ルール
* 5分切れ負け
* 但し着手一回ごとに残り時間に5秒加算

[30秒めいっぱい使って一手一手打つ]みたいな事が出来る秒読みと違って、決断即着手した方が結果有利になるので、試合がスピーディに進むらしいです

[羽生善治永世七冠が着想　超早指し「AbemaTVトーナメント Inspired by 羽生善治」開催　6月17日から放送開始
](https://abematimes.com/posts/4242035)


# CodePenでの実装がコレです

<p data-height="265" data-theme-id="0" data-slug-hash="xjBYMQ" data-default-tab="js,result" data-user="ys951357" data-embed-version="2" data-pen-title="フィッシャールールのチェスクロック" class="codepen">See the Pen <a href="https://codepen.io/ys951357/pen/xjBYMQ/">フィッシャールールのチェスクロック</a> by ys951357 (<a href="https://codepen.io/ys951357">@ys951357</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

たいしたもんじゃないのでライセンスはMITで
お好きにどうぞ
DockerにSonatype Nexus Repository Managerをインストールをする

# したこと
* Dockerを用いて、Nexusインストールを行った。
* 正確には、
    * macOSに、Dockerをインストールし、
        * Dockerコンテナを作成し、Ubuntuを起動する。そして
            * Ubuntu内に、Javaをインストールし、
            * Ubuntu内に、Nexusをインストールする。

## 環境
* macOS: 10.13.6
* Docker: 18.09.0, build 4d60db4 (最新を使用)
* Ubuntu: 16.04 (プロダクトコード名: xenial)
* Nexus: 3.15.0-01 (最新を使用)
   * https://download.sonatype.com/nexus/3/latest-unix.tar.gz

## コマンド
### Dockerをインストールする・Ubuntuを起動する
```bash
$ brew install docker # dockerのインストール
$ type docker # インストールの確認
docker is hashed (/usr/local/bin/docker)

$ brew cask install docker # /Applications/Docker.appのインストール
$ open /Applications/Docker.app # Docker.appの起動 (30秒くらいかかる) (メニューバーでステータス確認出来る)

$ docker pull ubuntu:xenial # UbuntuのDocker imageをダウンロードする
$ docker run -it ubuntu:xenial /bin/bash # コンテナを作成し、Ubuntuを起動する (自動的にコンテナ内にログインもされる)
```

### Oracle Java 8をインストールする
```bash
$ apt update # aptを最新にする
$ apt install software-properties-common # add-apt-repositoryなどが入っている

$ apt update
$ add-apt-repository ppa:webupd8team/java # apt sources.list にJavaを追加する

$ apt update
$ apt install oracle-java8-installer # インストールする

$ apt install oracle-java8-set-default # Java 8をデフォルトに設定する
$ java -version

# 自分でJavaのPathを通す (oracle-java8-set-default で上手くいかない場合など)
$ cat >> /etc/environment <<EOL
> JAVA_HOME=/usr/lib/jvm/java-8-oracle
> JRE_HOME=/usr/lib/jvm/java-8-oracle/jre
> EOL

$ java -version
java version "1.8.0_191"
Java(TM) SE Runtime Environment (build 1.8.0_191-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.191-b12, mixed mode)
```

### Nexusをインストールする・起動する・停止する
```bash
$ cd /opt
$ wget https://download.sonatype.com/nexus/3/latest-unix.tar.gz # Nexusをダウンロードする
$ ls
latest-unix.tar.gz

$ tar xvzf latest-unix.tar.gz # 解凍する
$ ls
latest-unix.tar.gz  nexus-3.15.0-01  sonatype-work

$ nexus-3.15.0-01/bin/nexus run # nexusを起動する
...
...
Started Sonatype Nexus OSS 3.15.0-01 # これが出れば起動成功

# Nexusを停止するには
Control + C を入力
```

### Dockerコンテナを停止する・削除する
* [Dockerコンテナの作成、起動〜停止まで - Qiita](https://qiita.com/kooohei/items/0e788a2ce8c30f9dba53) が参考になります。

## 参考にしたページ

* Dockerのインストール
    * [Docker環境をHomebrewで手軽に作成](https://qiita.com/digitalm/items/49b7099554bdbff5ed8e)
* UbuntuのインストールとDocker containerの作成
    * [Mac上でdocker、ubuntu、MySQLと環境を構築していく](https://qiita.com/ldap2017/items/ef2ea6f86b383a8af566)
        * **mysqlのインストールは不要**
* Docker containerの操作
    * [Dockerコンテナの作成、起動〜停止まで - Qiita](https://qiita.com/kooohei/items/0e788a2ce8c30f9dba53)
* Oracle Java 8のインストール
    * [How to Install JAVA 8 on Ubuntu 18.04/16.04, LinuxMint 18/17 - TecAdmin](https://tecadmin.net/install-oracle-java-8-ubuntu-via-ppa/)
    * [Ubuntu Linuxで、add-apt-repositoryしようとして「コマンドがない」って言われたら - CLOVER🍀](https://kazuhira-r.hatenablog.com/entry/20160116/1452933387)
    * OpenJDKでなく、Oracle Java 8を推奨している。Nexus公式ドキュメントより
* Nexusのインストール
    * [Repository Manager 3 - Sonatype Help](https://help.sonatype.com/repomanager3/)
MySQLの接続数や起動プロセスを確認するコマンド


DBへの接続数を調査した際のまとめです。
数値は凡例です。

## 最大接続数設定

### コマンド
```
mysql > show global variables like 'max_connections';
```

### 結果
|Variable_name|Value|
|----|----|
|max_connections|66|

## DBが起動してからこれまでの累積接続数

### コマンド
```
mysql > show global status like 'Connections';
```

### 結果
|Variable_name|Value|
|----|----|
|Connections|569611|

## DBが起動してからこれまでの最大同時接続数

### コマンド
```
mysql > show global status like 'Max_used_connections';
```

### 結果
|Variable_name|Value|
|----|----|
|Max_used_connections|14|

## Threads 関連ステータス

### コマンド
```
mysql > show global status like 'Thread_%';
```

### 結果
| Variable_name| Value |意味|
|----|:----:|----|
|Threads_cached|6|キャッシュされたスレッド数|
|Threads_connected|3|現在の接続数|
|Threads_created|503|生成されたスレッド数|
|Threads_running|1|実行中のスレッド数|

## 起動中のプロセス

### コマンド
```
mysql > show full processlist;
```

### 結果
|Id|User|Host|db|Command|Time|State|Info|
|----|----|----|----|----|----|----|----|
|42916|rdsadmin|localhost:29736|mysql|Sleep|1||NULL|
|569581|uralogical|hogefuga.tokyff01.ap.so-net.ne.jp:xxxxx|uralogicaldb|Query|0|starting|show full processlist|
|569582|uralogical|hogefuga.tokyff01.ap.so-net.ne.jp:xxxxx|NULL|Sleep|11||NULL|
## プロセスの終了

### コマンド
```
mysql > KILL processlist_id;
```
Laravel + SendGrid Web API でメール送信する


## 環境
- PHP 7.2
- Laravel 5.5
- SendGrid Web API V3

## まえがき
Laravel でメール送信する方法はいくつかあるが、今回は SendGrid を使用する。
会員登録が必要だが、12,000 通/月 までは無料。

SendGrid には [SMTP](https://sendgrid.kke.co.jp/docs/API_Reference/SMTP_API/getting_started_smtp.html) を使用する方法と、[API](https://sendgrid.kke.co.jp/docs/API_Reference/Web_API_v3/index.html) を使用する方法がある。
今回は API を使用する。
両方試したが、圧倒的に API の方が使いやすい。

## 手順

### API キーを作成する
[公式サイト](https://sendgrid.kke.co.jp/docs/API_Reference/Web_API_v3/How_To_Use_The_Web_API_v3/authentication.html)の手順に従って作成し、API キーをメモしておく。

### メールが送信できるかテストする

```
curl --request POST \
  --url https://api.sendgrid.com/v3/mail/send \
  --header 'Authorization: Bearer ここにAPI Keyを入れる' \
  --header 'Content-Type: application/json' \
  --data '{"personalizations": [{"to": [{"email": "test-to@gmail.com"}]}],"from": {"email": "test-from@gmail.com"},"subject": "Hello, World!","content": [{"type": "text/plain", "value": "Heya!"}]}'
```

### [SendGrid のライブラリ](https://github.com/sendgrid/sendgrid-php)をインストール

```composer.json
"require": {
	"sendgrid/sendgrid": "~6.2"
},
```

### ライブラリを使用してメールを送信する

```app/Http/Controllers/MailController.php
use SendGrid\Content;
use SendGrid\Email;
use SendGrid\Mail;

...

$from     = new Email('From名', 'Fromアドレス');
$to       = new Email('To名', 'Toアドレス');
$subject  = 'テストタイトル';
$content  = new Content(
    'text/plain',
    'テスト本文'
);
$mail     = new Mail($from, $subject, $to, $content);
$sendGrid = new \SendGrid('APIキー');
$response = $sendGrid->client->mail()->send()->post($mail);
```

これで届いていれば OK!

### メール本文に Blade テンプレートを使う場合

以下のように文字列に変換すればそのまま使える。
もちろん値も渡せる。

```app/Http/Controllers/MailController.php
...

$sendData = [
    'id' => $request->get('id'),
];

$content = new Content(
    'text/plain',
    strval(
        view(
            'emails/templates/test_mail',
            $sendData
        )
    )
);
```
configureのビルドオプションで、簡単にCプログラムのカバレッジを取ろう！

単体テストコード、書いてはいるけど本当にテストケースは足りてるかな？
そんな時の目に見える指標である**カバレッジ**、Linuxには標準で`gcov`というライブラリが含まれています。
せっかくなのでビルドオプションで切り替えていつでも利用出来るようにしましょう！

## **カバレッジ取得: gcov**

### **使い方**

手順は簡単です。

- ビルドオプションに `-fprofile-arcs -ftest-coverage`を付ける。
- ライブラリリンク `-lgcov`を設定する。

これでビルドしなおせばOKです。

### **ビルドオプションに追加しよう！**

色々なビルドオプションによる切り替え方法があると思いますが、今利用している自作configureでのやり方を紹介。
configureを導入される場合は[こちら](https://qiita.com/developer-kikikaikai/items/433d69c4bcbf52b249a1)等を参考にしてください。

まずは**`--enable`オプション**を追加します。

1. AC_ARG_ENABLE(オプション名、[ヘルプ文言],[オプション指定時のスクリプト], デフォルト値)でオプション追加
2. オプションが有効なら`AC_CHECK_LIB`で`gcov`ライブラリオプションと、`AC_SUBST([GCOV_OPT])`でgcov用のビルドオプション`GCOV_OPT`を追加。

```shell:configure.ac
###
# Unit test option
AC_ARG_ENABLE(coverage,
[  --enable-coverage      enable coverage test, only for developer of this package. Please "Don't" use this package if you install it, gcov is GPL license [[default=no]]],
[\
case "${enableval}" in
 yes) enable_coverage=yes ;;
 *)   AC_MSG_ERROR(bad value for --enable-) ;;
esac],
enable_coverage=no)

#check flag, and add gcov option
if test x"${enable_coverage}" = x"yes"; then
  AC_CHECK_LIB([gcov], [main])
  GCOV_OPT="-fprofile-arcs -ftest-coverage"
  AC_SUBST([GCOV_OPT])
fi
```

後は、Makefile.am等にgcov用に設定した`GCOV_OPT`オプションを渡せばOK。デフォルトは空なので追記でOKです。
この例ではMakefile.amに読み込ませる共通設定に仕込みました。

```Makefile:am.conf
AM_CPPFLAGS=-I$(top_srcdir)/design_pattern_util/include/ -I$(top_srcdir)/design_pattern_util/include/ $(GCOV_OPT)
```

ヘルプで見るとこんな感じ。ヘルプが出ると楽しいですね。(AC_HELP_STRINGで文言を書くと、もっときれいに出力できます)

```shell:
$ ./configure --help
  --enable-coverage      enable coverage test, only for developer of this package. Please "Don't" use this package if you install it, gcov is GPL license [default=no]
```

うまくgcovが利用できていれば、ビルド後のコード横にこんな`*.gcno`ファイルが出来ます。

```
$ ls chain_of_responsibility/lib/
chain_element.c     chain_element.h   chain_element.o            chain_of_responsibility.gcno  chain_of_responsibility.map  libchainofresp.la  Makefile.am
chain_element.gcno  chain_element.lo  chain_of_responsibility.c  chain_of_responsibility.lo    chain_of_responsibility.o    Makefile           Makefile.in
```

後はテストを実行すれば、カバレッジがわかります。これで自動カバレッジ取得も出来そうですね。

## **カバレッジの確認: lcov**

さあテストしました。結果を見よう！となっても、結果はバイナリデータで出力されるので、人が見ることのできるようにしないときついです。
一番結果がわかりやすい方法が`lcov`を使ったもの。

[こちら](http://d.hatena.ne.jp/t-kado/20100622)の手順を参考に、

1. [本家サイトのtar.gz](http://ltp.sourceforge.net/coverage/lcov.php)をダウンロード、展開。
   中はbuild済みでした。`make install`でインストール
2. コード直下で以下を実行。コード内にバーっとhtmlファイルが作成されます。

```
$lcov -c -d . -o XXX.info
$genhtml -o . XXX.info
```

`index.html`を開いてみるとこんな感じにカバレッジ率が見えます。Line CoverageがいわゆるC0カバレッジってやつです。

<img width="650" src="https://qiita-image-store.s3.amazonaws.com/0/252277/68061962-6b4b-b9f9-8700-7eafad8a0757.png">

この例だとテストコードはもちろんエラーなしなので率が低いですが、libは90%以上。
中を開くと通っていないコードが確認出来るのですが、それもmalloc失敗のような異常系なので、カバレッジからみたテスト網羅は問題ないといえます。
みたいな感じですね。

## **感想**

次触る時は、もう少し掘り下げてテストスクリプトと連動させてC0カバレッジ率も自動チェックできるようにしたい！

## **参考**

gcov
http://iyukki.blog56.fc2.com/blog-entry-154.html

lcov
http://d.hatena.ne.jp/t-kado/20100622
Web3.js 1.0 で Infura を使用する

* Web3.js 1.0 では、HTTP provider が deprecated - 非推奨 - となっており、Websocket provider を使用する必要があります。
* Infura の HTTP provide URL は `https://mainnet.infura.io` ですが、Websocket では `wss://mainnet.infura.io/ws` を使用します。

したがって、Web3 の初期化は次のように行います。

```js
var web3 = new Web3('wss://mainnet.infura.io/ws');
```
ChainerでNDL手書き平仮名を認識（Colaboratory+GPU）

# NDL
- NDLラボは、国立国会図書館の実験的なサービスを提供するサイトです
- 手書き平仮名データが公開されています
 - http://lab.ndl.go.jp/cms/hiragana73
- Chainerで学習するサンプルプログラムが公開されている
 - Chainerが古い、1.9.0向け
 - 学習・検証した結果を利用するサンプルはない
 - CPUのみでGPUを使えない
 - 手書き漢字データも公開されているけどサンプルプログラムはない

# GPU対応する
### 先に結果
- [train.py](https://github.com/kfjt/ndl_hiragana73_demo_gpu/blob/master/train.py)
 - Chainer4対応
 - GPU対応
- [ndl.ipynb](https://github.com/kfjt/ndl_hiragana73_demo_gpu/blob/master/ndl.ipynb)
 - google-drive-ocamlfuse導入
 - /content/driveにGoogle Driveをマウント
 - Chainerとcupyをインストール
 - トレーニング
 - 学習結果を可視化

### やったこと
- Google Colaboratoryで実行前にGoogle Driveの準備
 - NDL記載の手順をローカル端末でダウンロード、解凍、Google Driveにアップロードしておく

```console:NDL記載の手順
$ wget http://lab.ndl.go.jp/dataset/hiragana73.tar.gz
$ tar xfz hiragana73.tar.gz
$ wget http://lab.ndl.go.jp/dataset/example/train_ndlkana.tar.gz
$ tar xfz train_ndlkana.tar.gz
```

- train.pyを編集
 - ベースは前記事『[「not only 数字 but also 平仮名 ～MNIST だけでなく NDL もまた～」Chainerで手書きを認識](/kfjt/items/d90dced6d5cf36f6b669)』のtrain.py

```diff:train.py
-                                        help='ratio of test data')
-args = parser.parse_args()
+                                        help='ratio of test data')
+parser.add_argument('--gpu', '-g', type=int, default=-1,
+                    help='GPU ID (negative value indicates CPU)')
+args = parser.parse_args()

-xp = np
+xp = np
+if args.gpu >= 0:
+    # Make a specified GPU current
+    chainer.backends.cuda.get_device_from_id(args.gpu).use()
+    model.to_gpu()  # Copy the model to the GPU
+    xp = chainer.backends.cuda.cupy

-optimizer.setup(model)
+optimizer.setup(model)
+if args.gpu >= 0:
+        optimizer.target.to_gpu(args.gpu)
```

# 次の一歩
- 漢字もやってみてもよい（分類が多いだけで本質は変わらないから楽しくはないか）
- 複数の文字、というか文字列というか、文書をOCRさせるには？
- 文字でなく単語を学習する必要が合る？
- ノートやホワイトボードのように自由な場所に書く場合はbboxが必要？

おわり
VBAにおける、連想配列のindexアクセス


Keys(i)やItem(i)で、i番目の要素にアクセスという情報があるが、

	property let プロシージャが定義されておらず、property get プロシージャからオブジェクトが返されませんでした。

というエラーが出る場合の話。

    Debug.Print dic.Keys()(0), dic.Items()(1)

とすればOK。原因は

    Set dic = CreateObject("Scripting.Dictionary")

としているから。


参照設定に

		Scripting.Runtime

を追加して

	Set dic = New keyword

とすれば、

    Debug.Print dic.Keys(0), dic.Items(1)

で利用可能。
Visual Studio でクライアント側のデバッグをしない

## 現状

ASP の開発を行っている場合、Visual Studio 上でサーバー側のデバッグも、クライアント側 JavaScript のデバッグもおなじ画面、おなじ UI でデバッグできます。

しかし最近ではブラウザ側の「開発者ツール」も優れたものになってきて、クライアント側はそちらでデバッグを行いたいということもあるかと思います。

そのまま開発者ツールを起動すると「スクリプトデバッガーはターゲットプロセスに接続できませんでした。デバッガーは既にアタッチされています。」というエラーが表示されてデバッグできません。

Visual Studio 上でクライアント側のデバッグも**したい**という情報は結構あるのですが、**したくない**場合はどうすればいいのかについて情報が少なかったので記します。

## 参考

[visual studio 2008 - IE8 and VS2008: How do I disable script debugging? - Stack Overflow](https://stackoverflow.com/questions/664208/ie8-and-vs2008-how-do-i-disable-script-debugging)

## 手順

1. いつもどおり、F5 キーなどでデバッグを開始します。
1. Visual Studio の「デバッグ」メニューをクリックし「ウィンドウ > プロセス」の順に選択します。
1. プロセスウィンドウが開くので、その中からブラウザのプロセスを見つけ、右クリックして「プロセスのデタッチ」を選択します。
OGPの情報が更新されない（古いOGP情報が表示される）

豆メモ。

wordpressでサイトを公開した時に、Facebookでシェアすると、OGPの情報が古いものが表示される。

そんな時は、シェアデバッガーで問題のURLを入力して「デバッグ」
https://developers.facebook.com/tools/debug/sharing/

スクレイピングの実行時間がかなり古い状態なら、「もう一度スクレイピング」を押す。

![20180522.png](https://qiita-image-store.s3.amazonaws.com/0/76660/6c123966-37f4-e9f9-8bc9-ee99ad5117d6.png)


そうするとOGP情報が最新になります。

Facebookが覚えてたんですね。以外な盲点。
MACのXAMPPでMySQLが起動しない時の解決策

1) 以下のサイトを参照する
　　https://qiita.com/masakinpo/items/8b686047c741a8332576

2）それでも動かなかったら、すでにMysqlが裏で動いている可能性がある。
　そのため、 次のコマンドを打つ
　　ps aux | grep sql 
　このコマンドで、Mysqlがバックエンドで動いているかを確認し、動いていたらそのプロセスをkillする。次のコマンドで、
  kill プロセスid (複数可能)

3)通常通りXAMPPからMysqlサーバを起動
ComposerとFuelPHPをクラウドにインストール

 GoogleCloudPlatforのApp EngineとPaizaのクラウドに、ComposerとFuelPHPをインストールしました。

#Composerのインストール 
https://webbibouroku.com/Blog/Article/php-composer-setup
こちらの記事が、参考になります。
でも、
```
$ mv composer.phar /usr/local/bin/composer
```
を実行するとエラーになります。
そのため、このコマンドを実行しないで、Composerを使うようにすると良いです。
ターミナルやshellを起動した時のまま、直下のディレクトリでインストールすると、composer.pharができています。
このままコマンドで、
```
$ composer
```
と実行すれば、バージョン確認できます。

#FuelPHPのインストール

次のページが参考になります。
http://fuelphp.jp/docs/1.9/installation/instructions.html#command
この中の”GitHub から最新のリリースを clone する”の項目を参考にしてください。
私は、最初のCDのコマンドは、実行しませんでした。
二行目の
```
$ git clone git://github.com/fuel/fuel.git .
```
から実行しました。
でも、最後のドットは、つけませんでした。
App Engineで例のまま入力すると、エラーになりました。
そのため、ドットを除いて入力実行しました。

fuelのディレクりに移動してから
```
$ composer install
```
を実行しました。

#エラー対応
実は、
```
$ composer install
```
を実行すると下記の記事で紹介されているエラーが出ます。
http://tnamao.hatenablog.com/entry/2015/07/05/223707
このページで書かれているcomposer.jsonを作る方法を試したら、イントールできました。

#プロジェクトを作ることができた
実は、この記事を書いた後に、
```
FuelPHP No composer autoloader found. Please run composer to install the FuelPHP framework dependencies first!
```
という下記の記事と同じエラーが出たので、悩んでいました。
http://appstars.jp/archive/752

色々と検索する中で、フォルダーとパーミッションを確認した方が良いことを知りました。
この他、ディレクトリの指定が間違っている場合でも、このエラーは出ます。
私の場合は、ディレクトリの指定も合っているようなので、パーミッションを確認しました。
そして、次のコマンドを実行しました。
```
$ composer update
```
この後サンプルプロジェクトができるか試しました。
```
$ oil create hoge_project
```
無事に、プロジェクトができました。
そして下記の記事を知ったので、解説にあったファイルの追加や修正を行いました。
https://qiita.com/HikaruYokogoshi/items/29d583f242c6f0407ab3
私は、ローカルではなく、クラウドで作っています。
そのため、ローカルのテストサーバーを使うことができないです。
こちらにも、記事を見つけました。
この記事には、ローカルのテストさーバーの起動のことが、書かれています。
https://cloud.google.com/php/getting-started/hello-world?hl=ja

私は、先の記事でファイルを修正した後デブロイしました。
![スクリーンショット 2018-05-23 17.52.31.png](https://qiita-image-store.s3.amazonaws.com/0/20977/aa1f001a-5ef1-eef1-ab3b-12e416d12347.png)
ページ一行目が怪しいですが、でも、サンプルのページを表示できました。



#まとめ
本当は、ローカル環境にインストールするようなのですが、ローカルで環境を作ることがでいないので、クラウド環境にで色々と作業をしています。
それからComposerは、rootにインストールすることを推奨されていないようです。
GAEは、開発の全てをクラウドで行うと、確かに面倒です。
毎回デブロイしないといけない感じです。
でも、Angularの時は、ngコマンドでアプリを起動できました。
PHPの場合は、面倒ですね。
私も、Macの内蔵SSDの空き容量に余裕があれば、ローカルで開発したいです。
【PHP】日付のサマリー（DateTime）


# DateTime クラス

DateTimeの使い方を出来る限り纏めていきます。(随時更新)

## 現在日時

### フォーマット(秒精度) YYYY-MM-DD HH:MM:SS

```php5:Today 
// 今日の日付
$today = new \DateTime ();
// 今日の日付 フォーマット YYYYMMDD
$today_Ymd = $today->format ( 'Ymd' ); // string(8) "20180522"
// 今日の日付 フォーマット YYYY-MM-DD HH:MM:SS
$today_YmdHis = $today->format ( 'Y-m-d H:i:s' ); // string(19) "2018-05-22 17:25:28"
```

### フォーマット(マイクロ秒精度) YYYY-MM-DD HH:MM:SS.U

```php5:Today 
// 現在日時 マイクロ秒精度
$now = \DateTime::createFromFormat('U.u', sprintf('%6F', microtime(true)));
// 現在日時 フォーマット YYYY-MM-DD HH:MM:SS.U
$now = $now->format('Y-m-d H:i:s.u');  // string(26) "2018-05-22 08:25:28.406171"
```


## 指定日時

```php5:DateTime 
// 先月の初めての水曜日 フォーマット YYYY-MM-DD HH:MM:SS
$date_fsolm = new \DateTime ( 'first wednesday of last month' );
$date_fsolm = $date_fsolm->format( 'Y-m-d H:i:s' ); // string(19) "2018-04-04 00:00:00"

// 今月の最後の金曜日 フォーマット YYYY-MM-DD
$date_lfotm= new \DateTime ( 'last friday of this month' );
$date_lfotm= $date_lfotm->format( 'Y-m-d' ); // string(10) "2018-05-25"

// 今日から一ヶ月前 フォーマット YYYY-MM-DD
$date_1ma = new \DateTime ( '1 months ago' );
$date_1ma = $date_1ma->format( 'Y-m-d' ); // string(10) "2018-04-22"

// 今日から一ヶ月後 フォーマット YYYY-MM-DD
$date_nm = new \DateTime ( 'next months ' );
$date_nm = $date_nm ->format( 'Y-m-d' ); // string(10) "2018-06-22"

// 今日から20日後 フォーマット YYYY-MM-DD
$date_20d = new \DateTime ( '20 day' );
$date_20d = $date_20d->format( 'Y-m-d' ); // string(10) "2018-06-11"

// 今日から一週間前 フォーマット YYYY-MM-DD
$date_b1w = new \DateTime ( '-1 weeks' );
$date_b1w = $date_b1w->format( 'Y-m-d' ); // string(10) "2018-05-15"

// 現在から次の曜日  フォーマット YYYY-MM-DD
$dayname = new \DateTime ( 'Monday' );
$dayname = $dayname->format( 'Y-m-d' ); // string(10) "2018-05-28"

```

## 指定日時（比較）

```php5:DateTime 

// 指定日付 フォーマット YYYYMMDD
$date = "20180522";
$dateTime = new \DateTime ( $date );
$dateTime = $dateTime ->format ( 'Ymd' );

// 日付の比較　($dateは DateTime 形式ではないので、比較不可。)
if ($today > $dateTime ) {
	// 指定日付は過去です。
} else {
	// 指定日付は今日より未来です。
}
```


## 指定日時（時間間隔計算）

```php5:DateTime 
// 先月の初日 0時0分0秒　フォーマット YYYYMMDD 00:00:00
$dateFrom = new \DateTime ( 'first day of last month' );
$dateFrom->setTime ( '00', '00', '00' );
$from = $dateFrom->format ( 'Ymd H:i:s' ); // string(17) "20180401 00:00:00"

// 先月の末日 23時59分59秒　フォーマット YYYYMMDD 23:59:59
$dateTo = new \DateTime ( 'last day of last month' );
$dateTo->setTime ( '23', '59', '59' );
$to = $dateTo->format ( 'Ymd H:i:s' );  // string(17) "20180430 23:59:59"

// 先月の初日～末日の時間間隔
$diff = $dateFrom->diff($dateTo);
// 時間間隔　フォーマット [+]/[-] X days
$diff_days = $diff->format('%R%a days');  // string(8) "+29 days"
// 時間間隔　フォーマット HH:MM:SS
$diff_HIS = $diff->format("%H:%I:%S");   // string(8) "23:59:59"
// 時間間隔 フォーマット X month, Y days
$diff_month = $diff->format('%m month, %d days'); //string(16) "0 month, 29 days"
```




*参考：*
[さまざまな相対日付/時刻フォーマット](http://php.net/manual/ja/datetime.formats.relative.php)
[new DateTime](http://php.net/manual/ja/class.datetime.php#class.datetime)
ACMでDNSによるドメイン検証する方法

## **前提条件** 　Amazon Route 53でドメイン名を取得していること



####1. セキュリティ、 アイデンティティ、 コンプライアンス欄のCertificate Managerを選択
![screenshot.40.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/ac84905e-83a1-8783-32d9-f19e95daa037.jpeg)

####2. 証明書のリクエストを選択
![screenshot.41.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/309c9784-0dba-78a2-867f-2e2f5ad1350d.jpeg)

####3. パブリック証明書のリクエストを選択
![screenshot.42.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/66b3645b-ac10-8495-ee7f-f6d49d545a1f.jpeg)

####4. ドメイン名を入力　■ドメイン名の手前に*を付けるとワイルドカード証明書となりドメイン名の前に「www」や「site」を付けられる
![screenshot.43.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/8caf789a-3ced-8f50-9c87-5f569e11850b.jpeg)

####5. DNSの検証を選択
![screenshot.44.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/79e169ec-7a84-e185-c98e-e52928fc92c9.jpeg)

####6. 確定とリクエストを選択
![screenshot.45.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/879a098f-06aa-6802-5233-0481d7902da5.jpeg)

####7. ここでDNSの設定が可能だが一旦スキップする
![screenshot.46.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/76d2fee2-133a-3df9-a246-4279051f106a.jpeg)

####8. ドメインの名前と値をRoute 53のNAMEとValueに入力する
![screenshot.47.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/1e39a7fd-5458-72b8-954d-c21c61a20ecb.jpeg)

　　　　　　　　　　　　　　　　　　　　　　　　　　　↓
Route 53へ移動してcreate record setを選択　　　　    
![screenshot.52.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/4483b443-6e71-e44b-0773-cc5b17f62d3a.jpeg)
　　　　　　　　　　　　　　　　　　　　　　　　　　　↓　
 create record setのNameには先ほどの名前を入力
 TypeをCNAMEに変更　
 Valueに先ほどの値を入力してCreateする
![screenshot.54.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/51f7b8a2-1fb1-392f-82da-4ab85499b648.jpeg)

####9. Route 53への書き込みが成功したら反映するまで数分~30分程かかるので待つ
![screenshot.49.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/c959fc0a-a6c6-4a7f-64fc-9484e264f5d6.jpeg)

####10. 検証が無事完了すると状況が発行済みとなりELBで証明書を選択できるようになる
![screenshot.50.jpg](https://qiita-image-store.s3.amazonaws.com/0/255810/67812962-fa07-7a05-4474-419866233711.jpeg)
commitした後にgit管理から外したい場合


commitした後にgit管理から外したい場合

```
git rm --cached hoge.file
```

この後commitすると、ローカルのhoge.fileはgit管理から外れ、
リモートのhoge.fileは、ファイルごと削除される。

*--cashedオプションを付けないと、ローカルでもファイルごと削除される事に注意する
rbenvとruby-buildの正しいインストール方法

Rubyのセットアップをしていて、`rbenv`と`ruby-build`の設定で少しハマったので、備忘録。
なぜか知らないけど、ググってみてその通りに設定しても動かない。
**あろうことか、公式ドキュメントでさえ微妙に間違っている!**

以下のコマンドでインストールできるはす。

```
$ RBENV_ROOT=[***任意のrbenvのインストールPATH***]    # e.g. /usr/local/rubyenv ("/"で終わってはいけない)
$ git clone https://github.com/rbenv/rbenv.git $RBENV_ROOT
$ git clone https://github.com/rbenv/ruby-build.git $RBENV_ROOT/plugins/ruby-build
$ echo "export PATH=\$PATH:$RBENV_ROOT/bin" >> /etc/bashrc
$ echo "export RBENV_ROOT=$RBENV_ROOT" >> /etc/bashrc
$ echo 'eval "$(rbenv init -)"' >> /etc/bashrc
```

ポイントは、下2行の環境変数の設定あたり。
**特に、環境変数`RBENV_ROOT`を設定しないと、ruby-buildへのPathが通らずに`rbenv install`が実行できない。**

設定確認

```
# curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash
Checking for `rbenv' in PATH: /usr/local/rubyenv/bin/rbenv
Checking for rbenv shims in PATH: OK
Checking `rbenv install' support: which: no rbenv-install in (/usr/local/rubyenv/shims:/usr/local/rubyenv/shims:/usr/local/rubyenv/shims:/usr/local/rubyenv/shims:/usr/local/rubyenv/shims:/usr/local/rubyenv/shims:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/local/rubyenv//bin:/root/bin:/usr/local/rubyenv/bin)
/usr/local/rubyenv/plugins/ruby-build/bin/rbenv-install (ruby-build 20180424)
Counting installed Ruby versions: none
  There aren't any Ruby versions installed under `/usr/local/rubyenv/versions'.
  You can install Ruby versions like so: rbenv install 2.2.4
Checking RubyGems settings: OK
Auditing installed plugins: OK
```
赤文字の警告が出なければOK!
VBAで指定したセルに写真を一括で張り付けるマクロ

ネットでゴロゴロと出回っている内容ではあるが、備忘録として置いておきます。
ちなみに貼り付け先のセルについては結合されておりなおかつ縦横の幅が等幅であることが条件です。

```vb:画像挿入
sub 選択画像挿入()
 On Error Resume Next
    Dim i As Integer
    Dim filename As Variant
    Dim gazou As Shape
    Dim cell, celladd, cellcnt, cellarry As Variant
    i = 1 'filenameに格納されるのが1から
    Set cell = Application.InputBox("画像を貼付たいセルを選択してください。" & vbCrLf & "選択した順番に写真が挿入されます。", "選択画像挿入", , , , , , 8)
    If TypeName(cell) = "Range" Then 'セルが選択されていればcellはRangeオブジェクトになる
        filename = Application.GetOpenFilename("画像,*.emf;*.wmf;*.jpg;*.jpeg;*.jfif;*.jpe;*.png;*.bmp;*.did;*.rle;*.gif;*.emz;*.wmz;*.pcz;*.tif;*.tiff;*.cgm;*.eps;*.pct;*.pict;*.wpg;", MultiSelect:=True)
        Application.ScreenUpdating = False
        If TypeName(filename) = "Variant()" Then
            cell.Select '選択されたセルを選択する
            celladd = cell.Address '選択されたセルのアドレスを取得
            cellarry = Split(celladd, ",") '選択されたセルのアドレスを配列に格納
            cellcnt = UBound(cellarry) + 1 '配列の大きさを取得　要は画像の枚数を取得　+1しているのは配列が0から始まる為
            Do While i <> cellcnt + 1 '選択されたセルの数だけループする　+1はfilenameが1から配列の番号が始まっている為
                Range(cellarry(i - 1)).Select '-1しているのはcellarryは0から、filenameは1から配列の番号が始まる為
                If jidou = 2 Then
                    yokohaba = Range(cellarry(i - 1)).Width * Range(cellarry(i - 1)).MergeArea.Columns.Count '現在の書式は列幅は等倍だから単純にかけている必要に応じて変更
                    tatehaba = Range(cellarry(i - 1)).Height * Range(cellarry(i - 1)).MergeArea.Rows.Count
                End If
        
                Set gazou = ActiveSheet.Shapes.AddPicture(filename(i), False, True, Selection.Left, Selection.Top + 1, yokohaba, tatehaba)
                
                i = i + 1
                
            Loop
        Else
            MsgBox ("キャンセルしました")
        End If
    Else
        MsgBox ("キャンセルしました")
    End If
    
    ActiveWindow.SmallScroll Down:=-2000
    Range("A1").Select
    Application.ScreenUpdating = True
```
あとがき
自分で作っといてあれですが、どういう動きをしているか全くわからなくなってしまいました。
恐らくSplitで配列に一気にセル番地をcellarryに叩きこんでWhileで回して画像をセットしているはずなのだが・・・。
どこかのサイト様を参照して作ったはずだがこれも忘れてしまった・・・。
もし色々と引っかかるものがございましたらご指摘ください。すぐに消します。
Xcode: codesignのunknown errorは本当にわけがわからないよ

## 現象
Xcodeでビルドすると以下のようなエラーが発生する。

```
 /usr/bin/codesign --force --sign QWERTYUIOPASDFGHJKLL --entitlements /Users/hoge/Library/Developer/Xcode/DerivedData/Unity-iPhone-qwertyuiopasdfghjkl/Build/Intermediates.noindex/ArchiveIntermediates/Unity-iPhone/IntermediateBuildFilesPath/Unity-iPhone.build/Release-iphoneos/Unity-iPhone.build/hoge.app.xcent --timestamp=none /Users/hoge/Library/Developer/Xcode/DerivedData/Unity-iPhone-qwertyuiopasdfghjkl/Build/Intermediates.noindex/ArchiveIntermediates/Unity-iPhone/InstallationBuildProductsLocation/Applications/hoge.app
/Users/hoge/Library/Developer/Xcode/DerivedData/Unity-iPhone-qwertyuiopasdfghjkl/Build/Intermediates.noindex/ArchiveIntermediates/Unity-iPhone/InstallationBuildProductsLocation/Applications/hoge.app: unknown error -1=ffffffffffffffff
Command /usr/bin/codesign failed with exit code 1

** ARCHIVE FAILED **
```

## 対応
検索すると色々解決策が上がってはいるが…

### Xcodeを再起動する
Xcodeを再起動すると解決する、事があるらしい。

### DerivedDataディレクトリを空にする
`/Users/hoge/Library/Developer/Xcode/DerivedData/`に溜まっているデータを削除すると解決する、事があるらしい。
[command/usr/bin/codesign failed with exit code 1- code sign error - Stack Overflow](https://stackoverflow.com/questions/29242485/command-usr-bin-codesign-failed-with-exit-code-1-code-sign-error)

```sh
cd /Users/hoge/Library/Developer/Xcode/DerivedData
xattr -rc .
```

### キーチェーンアクセスのパスワードの更新
キーチェーンアクセスのパスワードを同じで良いので更新すると解決する、事があるらしい。
[Jenkins: Command /usr/bin/codesign failed with exit code 1 - Stack Overflow](https://stackoverflow.com/questions/42290444/jenkins-command-usr-bin-codesign-failed-with-exit-code-1)
[Getting this error command /usr/bin/codesign failed with exit code 1 with xcode 9.1?](https://stackoverflow.com/questions/47409062/getting-this-error-command-usr-bin-codesign-failed-with-exit-code-1-with-xcode)

### Xcodeでサインインしてプロファイルを更新
Xcodeでサインインしてプロファイルを同期すると解決する、事があるらしい。
[command/usr/bin/codesign failed with exit code 1- code sign error - Stack Overflow](https://stackoverflow.com/questions/29242485/command-usr-bin-codesign-failed-with-exit-code-1-code-sign-error)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/9104/de00c64f-d9f5-ff90-5be0-aef98909cc9f.png)

### マシンの再起動
マシンを再起動すると解決する、事があるらしい。
[Install on Device give Error : Command /usr/bin/codesign failed with exit code 1 - Stack Overflow](https://stackoverflow.com/questions/10750154/install-on-device-give-error-command-usr-bin-codesign-failed-with-exit-code-1)

結局、上記すべて試した結果、マシンの再起動で解決した。
【BigQuery】分析・データセット作成過程

#はじめに
BigQueryでの分析ってしている人は居るような気がするが
どんな手順で行っているのかは見つからず、着手に苦労。。
自分がBigQueryを使ってGAのローデータ分析をやってきた手順・やり方についてまとめる。
※細かいSQLについては今回は触れない。
※今回扱うデータはGAのデータ。

#アジェンダ
・分析の各工程
・データ抽出の進め方
・例
・まとめ

#分析の各工程
おおよそ以下の工程
①分析テーマ決め / 分析対象決め
②抽出条件定義 / 対象項目決定
③データ抽出　★
④ビジュアライズ
⑤結果共有 / ディスカッション
ー　①~⑤の繰り返し　ー
⑥GOAL（最終アウトプット作成 / 施策の決定等）

一番時間をかける、かつ、BigQueryの性質も考慮した分析手順として、
データ抽出の箇所を深掘る。

#データ抽出の進め方
BigQueryのポイント
①"何単位"のデータ？
**取得したい項目が何単位のデータ（ユーザー・セッション・ヒット）なのか**
**最終的に分析・可視化したいデータが何単位なのか**
を意識してデータを作成することが大切

![2018-06-26_162737.png](https://qiita-image-store.s3.amazonaws.com/0/200029/68d702c3-263f-07f7-9cf7-feb746c24a51.png)

②テーブルを分けて分析を進める
分析過程がわかりやすい、データの検証がしやすい

##何単位のデータか？
アクセス解析のデータには、
「ユーザー」、「セッション」、「ヒット（PV）」の概念がある。

![2018-05-22_162747.png](https://qiita-image-store.s3.amazonaws.com/0/200029/d3a4e215-d51e-7128-1630-f4b578b2fdd2.png)


BigQueryのデータ構造は**1レコード1セッション**単位ですが、
中にはヒット（PV）の情報が入れ子のような形で含まれている。

そのため、セッション単位の情報・ヒット単位の情報を合わせてみたい！と言った場合、
『セッション単位の情報』と『ヒット単位の情報』を分けて取得し、
セッションの一意キーで結合してデータセットを作成していくイメージとなる。

###カスタムディメンション
GAのデータは原則Googleが定義した箱の中にデータを設定していくイメージですが、
カスタムディメンションでは、個別サイトで任意の項目を設定・取得することが出来ます。
こちらもヒット・セッション毎で設定可能です。
カスタムディメンションはRECORD型のデータとなるので、取得の際には、「どのまとまりで取得するか」「最終、どのデータセットに結合しにいくか」を考慮します。

#例
![image.png](https://qiita-image-store.s3.amazonaws.com/0/200029/d7d681e1-eb0f-2fb1-2a04-4bd68b738348.png)
※今回使ったデータでは、デモグラ(ユーザーの属性値)をカスタムディメンションで取得している。
　会員登録情報はヒットで取っている。CV/LP/セッションについてはおおよそ標準の通り。

#まとめ
・**何単位のデータ（ユーザー・セッション・ヒット）なのか**　がとても重要
・一個一個情報を確認しながら進めるのが大切
・最後にデータセットとしてまとめられる用に、どれをキーにJOINするか、頭で設計しておくべし
エクセルに写真を一括で張り付けるマクロ

下のような台帳に写真を一括で張り付けるマクロ
私が働いている会社は建築系なので、施工前と施工後で2回に分けて張り付けるマクロになっています。
きれいに動作する前提条件としては、結合されているセルの縦、横幅がすべて同じサイズでないと写真の大きさがうまくはまりません。
ありきたりなマクロではありますが何かの参考になれば・・・。

施工後の部分に張り付けるマクロについてはcntの変数を17に設定すれば動きます。
要はセルの開始行番号をcntに設定すればいけます。


![エクセルフォーマット.PNG](https://qiita-image-store.s3.amazonaws.com/0/237388/076004b7-af6c-92a3-e436-6d6cb1bf125e.png)

まずはコードから

```vb:写真一括挿入
Sub 一括画像挿入前()
Application.ScreenUpdating = False
On Error Resume Next
Dim yokohaba, tatehaba As Double
Dim place, filename, mo As Variant
Dim fname As String
Dim icount, i, i2, cnt, addcnt As Integer
Dim gazou As Shape

mo = Array("B", "J", "R", "Z")


    i = 1 'filenameに格納されるのが1から
    cnt = 4
    icount = 0
    filename = Application.GetOpenFilename("画像,*.emf;*.wmf;*.jpg;*.jpeg;*.jfif;*.jpe;*.png;*.bmp;*.did;*.rle;*.gif;*.emz;*.wmz;*.pcz;*.tif;*.tiff;*.cgm;*.eps;*.pct;*.pict;*.wpg;", MultiSelect:=True)
    If TypeName(filename) = "Variant()" Then  '写真が選択されていればfilenameはvariantの配列型になるはず
        Do While i <> UBound(filename) + 1    '写真の数だけループする +1はfilenameの配列が1番から始まる為
            Range(mo(icount) & cnt).Select
            yokohaba = (ActiveCell.MergeArea.Columns.Count * ActiveCell.Width) - 2
            tatehaba = (ActiveCell.MergeArea.Rows.Count * ActiveCell.Height) - 2
            Set gazou = ActiveSheet.Shapes.AddPicture(filename(i), False, True, Selection.Left + 1, Selection.Top + 1, yokohaba, tatehaba)
            fname = filename(i)
            
            If fname = filename(i + 1) Then '同じ写真の名前が来たら終了
                Exit Do
            End If
            
            If i = 40 Then
                MsgBox ("写真が取込きれませんでした")
                End
            End If
            
            If icount = UBound(mo) Then
                icount = 0
                cnt = cnt + 28
            Else
                icount = icount + 1
            End If
            
            i = i + 1
        
        Loop
    Else
        MsgBox ("キャンセルしました")
    End If
    
    ActiveWindow.SmallScroll Down:=-2000
    Range("A1").Select
    Application.ScreenUpdating = True
flg = 0
End Sub
```

簡単なコードの解説
1．まずはmoの配列に写真を挿入したいセルの左上の列文字を入れておき、ループで文字を切り替えられるように設定します。
2．i の初期値が1で設定されているのはapplication.getopenfilenameでfilenameの配列に格納されるのが0ではなく1から格納されるため、1を設定しています。
0だと参照先がエラーになる。（On Error Resume Nextが設定されているため、最初のセルがスルーされる）
3．同じ名前の写真が来たら終了という部分だが、ここはOn Error Resume Nextの力を借りて無理やり終了させている節はある。
写真を貼付終わった後、配列を＋１するとインデックスがありませんというエラーになり、Resume Nextの力を借りて強制的にExit Doへ進んでしまっている。
コード的には美しくはないが動いているので現状はこれで使用しています。　ここはTypeNameか何かを利用すればスマートに動くと思います。
TypeName(filename(i+1)) = エラー的な処理ができれば・・・。
4.写真が取り込みきれませんでしたのiの部分については写真の最大取込数を数値にて設定してください。



あとがき
コード解説を書いていて3番の問題点に初めて気が付きました・・・。
容易にOn Error Resume Next等々の強制的に処理を進めるように作ってしまうと思わぬところでエラーになりそうだなぁと。
いつかはセルの幅が等幅でなくても写真のサイズをぴったりにできればいいなとは思っています。
コードにはうまく書けないですが、結合しているセルの数を取得して各幅を取得して写真のサイズに当てはめればいけそう・・・？
社内簡易プログラマーのメモ書きでした。
VB.NetでExcelファイルをPDF出力し、Zip圧縮する

# 追記
この記事のソースには問題があるようです。
具体的には開放処理が足りない模様。
[Excelファイルを C# と VB.NET で読み込む "正しい" 方法](https://qiita.com/midori44/items/acab9106e6dad9653e73)

# 前提
有り物の古い環境で確認しているので諸々古い場合があります。
というか環境が古く.NET Framework 4.0だったのでZIP圧縮周りを動かせていません。
また軽い検証用なのでエラー処理などは適当です。

# やりたかったこと
- 既存のExcelファイルを開き、内容を変更して別名保存
- 同じ内容をPDFにExport
- 別名保存したExcelファイルとPDFファイルをまとめてZip圧縮

# 環境
Windows7
Visual Studio 2010
.NET Framework 4.0
Office2010

# 実装

## 1. 参照の追加
[参照の追加]-[COM]-[Microsoft Excel xx.x Object Library]
→ うちはMicrosoft Excel 14.0 Object Libraryでした。
[参照の追加]-[.NET]-[System.IO.Compression.FileSystem]
→ .NET Framework 4.5以降の資材なので環境に無かったです。

参考
[Office プライマリ相互運用機能アセンブリ](https://msdn.microsoft.com/ja-jp/library/15s06t57.aspx)
[System.IO.Compression 名前空間](https://msdn.microsoft.com/ja-jp/library/system.io.compression(v=vs.110).aspx)

## 2. Imports
``` VB.Net
Imports Microsoft.Office.Interop
Imports System.IO.Compression
```

## 3. 各種値をなんとかする
``` VB.Net
' 日時とっとく
Dim nowYMDHMS As String = Now().ToString().Replace("/","_").Replace(" ","_")
' 第一引数にExcelファイル名をフルパスでもらう予定
Dim oldDir As String = args(0).Substring(0, arg(0).LastIndexOf("\") + 1)
Dim newDir As String = oldDir & nowYMDHMS & "\"
Dim xlsxFileName As String = args(0).Substring(arg(0).LastIndexOf("\") + 1)
Dim pdfFileName As String = xlsxFileName.Substring(xlsxFileName.LastIndexOf(".")) & ".pdf"
Dim zipFileName As String = xlsxFileName.Substring(xlsxFileName.LastIndexOf(".")) & ".zip"
' 新しい出力先を作っておく
System.IO.Directory.CreateDirectory(newDir)
```

## 4. Excelを開く
``` VB.Net
Dim xlsxBook As Excel.Workbook = Nothing
Try
  xlsxBook = (New Excel.Application).Workbook.Open(oldDir & xlsxFileName)
  ' 続きの処理はここに追加していく
Catch ex As Exception
  Console.WriteLike(ex)
Finally
  If Not xlsxBook Is Nothing Then
    xlsxBook.Close()
  End If
End Try
```
## 5. Excelの内容をいじる
``` VB.Net
  With xlsxBook.Sheets(1)
    .Range("1:1").Insert()
    .Cells(1,1) = nowYMDHMS
    .Cells(1,2) = "プログラムで値を入れたよ。"
    .Columns("A:B").AutoFit()
  End With
```
## 6. Excelに内容を保存する
``` VB.Net
  ' 上書き保存
  xlsxBook.Save()
  ' 別名保存
  xlsxBook.SaveAs(newDir & xlsxFileName)
```
## 7. PDFに内容を保存する
``` VB.Net
  ' 別名保存したExcelと同じフォルダに出力する
  xlsxBook.ExportAsFixedFormat( _
    Type:=Excel.XlFixedFormatType.xlTypePDF, _
    Filename:=newDir & pdfFileName)
```
参考
[Workbook.ExportAsFixedFormat メソッド (Excel)](https://msdn.microsoft.com/ja-jp/vba/excel-vba/articles/workbook-exportasfixedformat-method-excel)

## 8. ZIP圧縮する
``` VB.Net
  ' ここ確認できてない
  ' System.IO.Compression.ZipFile.CreateFromDirectory(newDir, oldDir & zipFileName)
```
参考
[ZipFile.CreateFromDirectory メソッド (String, String)](https://msdn.microsoft.com/ja-jp/library/hh485707(v=vs.110).aspx)

# 結果
- Excel開く、保存するのは簡単にできる
- PDFへの出力は簡単にできる
- Zip圧縮も簡単にできる
- 良い時代になったものだ

以上