OmniAICreator/Qiita-1.07M huggingface dataset:
今日学んだ事

# 7/7(日) 21:30〜0:20

###●タグ

```html.erb
<span>〜</apan>
```
・span囲った部分をインライン要素としてグループ化することができるタグ。
グループ化する事で、指定した範囲にスタイルシートを適用できたりする。

```html.erb
<i>〜</i>
```
・フォントを「イタリック体」にする


###●averageメソッド
・ActiveRecordクラスのメソッド
使用例
カラム=score
テーブル=students
クラス=Student
scoreカラムのaverageを求める

```
students = students.all
students.average.(:score)
#scoreの平均を小数点ありの状態で返す
```
小数点を四捨五入する場合

```
students = students.all
students.average.(:score) round
#roundメソッドを使用すると小数点を四捨五入する
```

###●present?メソッド
・配列の中身がなければfalseを返す
・レビューの評価の平均など出すときに、レビューがない作品にfalseを返したい時などに使う
例

```index.html.erb
<% if product.reviews.present? %>
```
このコードでレビューがない場合でもエラーが回避できる

###●レシーバ
・インスタンスメソッドを利用するインスタンス自身の事
例

```
products = Product.all
#以下の式のレシーバはproducts
products.limit(5)
```
1.Productクラスからproductsインスタンスを生成
2.productsインスタンス自身がlimitメソッドを利用している
3.この時productsがレシーバとなる
ち・な・み・に
メソッドの呼び出しを「オブジェクト（インスタンス）にメッセージ（メソッド）を送る」と表現する。
今回の場合
「products（オブジェクト）にlimit（メッセージ）を送る」となる


###●selfメソッド
・インスタンスメソッド内にselfを記述すると、そのメソッドを利用したインスタンス（レシーバ）が代入された変数のように扱う事ができる
例

```
def review.average
 self.review.average(:rate).round
```

うーん、よく分からない。。。。

###●コントローラ内に記述されているlayout 'レイアウトファイル名'について
例

```
1.class MovieController < ApplicationController
2.  layout 'movie'
3.  
4.  def index
5.    @movies = Movie.all
6.  end
7.end
```
・MovieControllerのindexアクションが呼ばれたときに表示されるレイアウトはmovie.html.erbとなる。
・なにも指定しないとレイアウトファイルはapplication.html.erbとなる

以上
メモ: Ubuntu18.04-desktop 仮想マシンに ruby v2.4.5環境を作る時に実行する一連のコマンド等

自分が再度同じ作業をする時に再利用するためのメモ。
以下ではデスクトップPC上で使用する仮想化ソフトで作る仮想マシンを前提にしてるけど、クラウドPlatform系でもだいたい同様。

※なお、この記事では apt で管理されている rbenv は使わずに github から clone してセットアップする方法を扱う。

## 1. Ubuntu 18.04-desktop の iso イメージを入手

下記URL等から任意に欲しいisoイメージを取得する
http://cdimage-u-toyama.ubuntulinux.jp/releases/

![20190707_ubuntu_1804_release.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424762/009b1b48-0f89-32ed-075d-bd8b2265939f.png)

## 2. VMware や VirtualBox 等の仮想化ソフトを使ってVMを起動する

新規仮想マシンの作成とかそんなメニューから、インストーラディスクイメージファイルとして上記で取得したisoイメージを指定してインストールを進める。
仮想化ソフト側で「簡易インストール」みたいな機能を持ってれば、それを使うと楽ちん。

## 3. 作業に必要なパッケージをセットアップする

* 仮想マシンのコンソールでターミナルソフトを起動して以下を実行

```bash
ip addr show          # 母艦からsshでログインする時に指定するIPアドレスを確認
sudo apt install tasksel
sudo tasksel install openssh-server
service ssh status    # sshサーバの起動状態を確認
ss -ln -t4            # sshサーバの使用ポート番号を確認
exit
```

* 母艦から ssh でログインして以下を実行

```
cd    # HOMEディレクトリで作業
sudo apt install mysql-client libmysqlclient-dev    # mysqlを使うrubyプロジェクトだから入れておく
sudo apt install git
sudo apt install curl
sudo apt install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm5 libgdbm-dev
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
. .bashrc
~/.rbenv/bin/rbenv init
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
. .bashrc
curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash    # rbenvの状態確認
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 2.4.5
curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash    # rbenvの状態確認
rbenv rehash
rbenv shell 2.4.5
gem install bundler

```

# あとはプロジェクト次第

ソースをGitリポジトリから取得したり、
母艦とディレクトリを共有する設定をしたり、
RubiMine等のリモートインタープリタ設定などなど、
プロジェクトに応じてあれこれやる。

今回の記事は以上です。
SQLアンチパターン-5章 EAV-まとめ

## EAVについて
例えばイシューというデータを扱うモデルを考えてみましょう。

イシューモデル

|issue_id|title|
|:--:|:--:|
| 1|フォームが送れない|
| 2|ログインができない|
| 3|決済ができない|

イシューそれぞれに対して、例えば「いつ起きたか」「どのバージョンのコミットに関係するものか」「詳しい内容は何か」といった情報を付与したいと考えたとします。

イシュー属性要素モデル

|issue_id|attr_name|attr_value|
|:--:|:--:|:--:|
| 1|status|NEW|
| 1|description|全ての情報を入力して、送信ボタンを押しても、ページが遷移しません。|
| 1|version_affected|1.5|


このように、汎用的な属性をテーブルで管理する設計をEAV(Entity-Attribute-Value)といいます。このようなテーブルを作成する事で

- イシューにつける情報量を減らせる（列を減らせる）
- 新しい属性を追加しようとした時に、イシュー属性要素モデルの行を増やせば良いだけ
- 仮にイシューモデルのテーブルだけで属性要素を扱おうとした時に、NULL値が入る事を防ぐ事ができる。例えば、イシューによってはdescriptionは必要なかったり。（極論ですが・・・）


## EAVを使う事のデメリット

### 属性に必須という設定をする事ができない
attr_name毎に、その値が必須なのかどうか、設定することはできません。

### データ型を上手く扱えない
attr_valueに入る値はattr_nameによって変わります。つまりデータ型も変わります。
そのため、attr_valueにはどのような型の情報でも入れられるようにしなければなりません。
そのため、attr_valueは文字列型で扱うのがスタンダードな設定となります。
attr_value列を拡張して、列を増やし、それ毎に型を設定する方法もありますが、クエリが冗長になってしまいます。

### 参照整合性を強制する事ができない
後ほど執筆

### 属性名の規定を設定できない
原則的にはattr_nameにはどんな情報も入れる事ができる。
つまりissue_dateなのか、date_issueなのか、それを定めるためにまた別の参照テーブルを作成することが必要になってしまいます。

### 行を再構築しなければならない
EAVを使わなければ、イシューモデルに対して属性要素が全て格納されています。
EAVを使った場合、イシュー属性要素テーブルを結合するために、データをJOINする必要があります。必要な情報を結合しようとすると、その分クエリもJOIN文が増え、実行コストが増えていってしまいます。

## EAVを使うのはどういう時か
EAVを使う事を正当化できるようなケースはまだ思いつきません・・・
「属性要素が10個くらいあるが、属性要素自体はこれ以上増えないと確定している」時でしょうか・・・


## EAVの解決方法

### シングルテーブル継承
全ての属性要素を、別のテーブルとかに分けず、一つにまとめるという事。
つまり、冒頭の例でいうと、イシュー属性要素モデルを作成せず、イシューモデルで全て扱うようにする、という事である。
しかし、この場合、属性要素を増やす時には列を増やす必要があります。
また、イシューの種類によっては不必要な列も出てきてしまう可能性もあります。

### 具象テーブル継承
シングルテーブル継承に改良を加えたものです。
イシューの種類によって不必要な列が出てきてしまう可能性があるので
そのイシューの種類毎に属性要素のテーブルを作成するという方法が良さげです。

例えばイシューにも「ユーザー側」と「管理画面側」と2種類に分ける事ができたとします。
その際、IssueUserAttrとIssueAdminAttrの2種類のモデルを作成する事で
属性要素をそれぞれ扱う事ができ、イシューの種類によって不必要な列が生まれる、という事を防ぐ事ができます。

### クラステーブル継承
具象テーブル継承にて、IssueUserAttrとIssueAdminAttrの2種類のモデルを作成した際に、両方のモデルに共通の要素（列）ができることもあるかもしれません。
その際は共通の要素を抜き出して、基底となるモデルを作ることもできます。
クラスのように、親クラスを作成して、そこからサブクラスを作成するようなイメージですね。


### 半構造化データ
LOB(Large Object型の総称)列を追加し、XMLやJSONデータとして扱う方法です。
テーブルに分けてわざわざ行を増やしたり、列を増やしたりする必要がありません。
一方で、LOB列で扱うデータを元に検索などするにはとても不向きになります。
ただ出力するというだけでしか扱われないような情報であれば良いのですが・・・
[nuxt.js その３] firebaseのセットアップ

# firebaseのセットアップ
当初作り始めるときはもともとVue.jsで作成済みのものをnuxtに乗せ換えることを考えてましたが、どうせならなんか作ってみようと思います。
といっても、何を作るかまだはっきり決まっていないのでひとまずバックエンド（firebase）のセットアップからやっていきます。

参考：https://chaika.hatenablog.com/entry/2019/01/21/113000

## firebase CLIのインストール

```
$ npm install -g firebase-tools
```

## firebaseアカウントの連携

```
$ firebase login
```

## プロジェクト内でのfirebaseの初期化

```
$ firebase init
```

## firebase接続情報の追加
Nuxt.jsではdotenv-moduleを使って環境個別の設定を.envファイルに切り出すことでプロジェクトの環境依存情報を切り離すことができるようです。
.env内で定義された変数はNuxtプロジェクト内にて`process.env.XXXX`のような形で参照できます。
[公式ページ](https://ja.nuxtjs.org/guide/plugins#%E5%A4%96%E9%83%A8%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E5%88%A9%E7%94%A8)

### ＠nuxtjs/dotenvのインストール

```
$ yarn add @nuxtjs/dotenv
```

### dotenvモジュールの使用を設定

```
module.exports = {
  /*
  ** Nuxt.js modules
  */
  modules: [
    '@nuxtjs/dotenv',
  ],
}
```

### .envファイルにfirebase接続情報の追加

```vuejs:.env
FB_API_KEY=<FIREBASE_API_KEY>
FB_AUTH_DOMAIN=<FIREBASE_ AUTH_DOMAIN>
FB_DATABASE_URL=<FIREBASE_DATABASE_URL>
FB_PROJECTID=<FIREBASE_PROJECT_ID>
FB_STORAGE_BUCKET=<FIREBASE_ STORAGE_BUCKET>
FB_MESSAGING_SENDER_ID=<MESSAGING_SENDER_ID>
```

### firebase接続処理の追加
~/plugins/に追加していきます。

```vuejs:~/plugins/firebase.js
import firebase from "firebase";

const config = {
  apiKey: process.env.FB_API_KEY,
  authDomain: process.env.FB_AUTH_DOMAIN,
  databaseURL: process.env.FB_DATABASE_URL,
  projectId: process.env.FB_PROJECTID,
  storageBucket: process.env.FB_STORAGE_BUCKET,
  messagingSenderId: process.env.FB_MESSAGING_SENDER_ID
}

if (!firebase.apps.length) {
  firebase.initializeApp(config)
}

export default firebase
```
初投稿

#目的
当面は自身の知識のインターネット上での公開のためにこのブログを使うかな。。。

#試し書き
```visualbasic:test01.xlsm
    Public Sub MakeApplicationHolidayWork()
    Dim i As Integer
    Dim fPath As String
    Dim fName As String
    Dim area As Range
    Dim temp As Range
    
    Set area = Worksheets("休出予定社員一覧").Range("B3").CurrentRegion
    Set area = area.Offset(1).Resize(area.Rows.Count - 1)
   
    'シートをコピーして新規ブックを作る
    

        'ブックの保存
    For Each temp In area.Rows
        fPath = ThisWorkbook.Path
        fName = ThisWorkbook.Path & "休日出勤届" & "_" & temp.Cells(1, 2).Value
        '週間予定表シートを最終シートにコピーする
        Worksheets("休日出勤届").Copy
        Workbooks(Workbooks.Count).Close SaveChanges:=True, Filename:=fName
    Next
            

End Sub

```
#気になっている事
後から記事の修正ってどうやるんだろう、、、
go-ginでサクッとRESTAPIを構築する

# ginとは
ginは、Go言語のフレームワークの中においてメジャーで歴史あるフレームワークで、軽量かつシンプルなインターフェイスが特徴です。

今回はそんなginを使って、簡単なRESTAPIを構築していきます。

# ginを導入
go getで。

```bash
 go get -u github.com/gin-gonic/gin
```

公式githubサンプルを動かしてみましょう。

```golang
package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run() // listen and serve on 0.0.0.0:8080
}
```
```bash
go run main.go
```
http://localhost:8080/ping へアクセスしてみてください。
message":"pong"と表示されています。

	r := gin.Default()
こちらの処理でデフォルトのミドルウェアで新しいルーターを作っています。

# RESTAPIの構築

それでは新しく、RESTAPIを構築していきます。
サンプルとして作るのは、タイトルとディスクリプションだけ持ったArticleをPOST,GETできる機能になります。

またディレクトリ構造は下記になります。

```bash
src
┣article 
┃   ┗article.go
┃
┗httpd
 ┣handler
 ┃ ┗articleFunc.go   
 ┗main.go

```

まずはArticleを定義します。
書いてある通りですね。

```golang:article.go
package article

type Item struct {
	Title       string `json:"title"`
	Description string `json:"description"`
}

type Articles struct {
	Items []Item
}

func New() *Articles {
	return &Articles{}
}

func (r *Articles) Add(item Item) {
	r.Items = append(r.Items, item)
}

func (r *Articles) GetAll() []Item {
	return r.Items
}

```

続いて上記ファイルで定義したArticleのfunctionをまとめたファイルです。
こちらもそのままな処理ですね。

```golang:articleFunc.go 

package handler

import (
	"net/http"

	"restAPI/article"

	"github.com/gin-gonic/gin"
)

func ArticlesGet(articles *article.Articles) gin.HandlerFunc {
	return func(c *gin.Context) {
		result := articles.GetAll()
		c.JSON(http.StatusOK, result)
	}
}

type ArticlePostRequest struct {
	Title       string `json:"title"`
	Description string `json:"description"`
}

func ArticlePost(post *article.Articles) gin.HandlerFunc {
	return func(c *gin.Context) {
		requestBody := ArticlePostRequest{}
		c.Bind(&requestBody)

		item := article.Item{
			Title:       requestBody.Title,
			Description: requestBody.Description,
		}
		post.Add(item)

		c.Status(http.StatusNoContent)
	}
}
```

最後はメインとなるmain.goです。

```golang:main.go
package main

import (
	"restAPI/httpd/handler"

	"restAPI/article"

	"github.com/gin-gonic/gin"
)

func main() {
	article := article.New()
	r := gin.Default()
	r.GET("/article", handler.ArticlesGet(article))
	r.POST("/article", handler.ArticlePost(article))

	r.Run() // listen and serve on 0.0.0.0:8080

}
```
ここまで構築をしたら下記で起動してみてください

```bash
go run httpd/main.go
```

http://localhost:8080/article
へのPOSTとGETが利用できるようになっているはずです。

試しにPostmanを用いて行ってみます。

POST(HeadersにContent-Type：application/jsonを設定)
<img width="1130" alt="Screen Shot 2019-07-08 at 12.35.47 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265549/ae9b52f6-e137-cba2-6eb8-737482c3c19b.png">

GET
<img width="1145" alt="Screen Shot 2019-07-08 at 12.35.57 AM.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265549/e36b052e-3395-8de8-d1e0-c1330936eded.png">

以上になります。

# 参考資料
https://github.com/gin-gonic/gin
https://gin-gonic.com/ja/docs/
【初学者向け】MacでDockerを使うための最低限の事

<!-- MacでDockerを使うための最低限の事 -->
# はじめに
今更ですがDockerの魅力を知ったので、
ローカル環境(Mac)にインストールしてみました。

その際に行った初期設定などを、備忘録を含めてまとめます。

ローカル環境でMacOSを使用している前提とします。
また、dockerをインストールした後の操作などは対象外です。

## 開発環境
- Macbook Pro (Core i5)
- MacOS


# DockerをMacで使う
macにアプリケーションをインストールするだけです。
(カップラーメンを作るより早く終わります。)

## Dockerのインストール
### 1.Docker for MacのDL & Install
https://hub.docker.com/editions/community/docker-ce-desktop-mac
上記のdockerhubより、**Get Docker**をクリックし、**Docker Desktop for Mac**をDLする。
(dockerhubにログインしないとDL出来ません。登録&ログインを済ませておいてください。)
![dockerhub_docker_for_mac.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251749/2d7b9799-0c98-5012-90ec-ad7b464d3912.png)

DLした**docker.dmg**ファイルを開き、**Docker.app**を**Applications**へ追加する。
![install_docker_for_mac.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251749/102f26eb-88fa-7c9d-5b46-d30609cdca2c.png)

アプリケーションからDockerを開くとメニューバーにdockerアイコンが追加される。
![docker_menu_icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/251749/fc6d421c-a574-d629-acce-f05c50ceba14.png)

アイコンをクリックし、緑色で**Docker Desktop is running**と表示されたら正常に動いています


## 2.Dockerのバージョン確認
MacのTerminalより下記のコマンドでバージョンを確認する。

```
$ docker --version
Docker version 18.09.2, build 6247962

$ docker-compose --version
docker-compose version 1.24.0, build 0aa59064

$ docker-machine --version
docker-machine version 0.16.1, build cce350d7
```

上記のような出力がされれば、dockerが正常作動しているのでOK！

# まとめ
これだけで、macでdockerを使用出来ます。
今回は本当に**最低限の事**のみを記事にしました。
docker,docker-composeの操作などは、別記事にて更新予定です。
debian buster (arm64) に docker install

## 古いバージョンの docker を削除

```
# apt-get remove docker docker-engine docker.io containerd runc
```

## arm64 は docker本家のリポジトリを設定する

```
# apt-get update
# apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg2 \
    software-properties-common
# curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
OK
# add-apt-repository \
   "deb [arch=arm64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"
```

## docker インストール

```
# apt-get update
# apt-get install docker-ce docker-ce-cli containerd.io
```

## docker-compose インストール

```
# apt-get install python-setuptools python-pip
# pip install docker-compose
# pip uninstall backports.ssl-match-hostname
# apt-get install python-backports.ssl-match-hostname

vi /etc/sysctl.conf
net.ipv4.ip_forward=1
```
ローカルのWSL(WSL1/WSL2)にTeraTermのショートカットからパスワードなしで接続する

(WSLをバージョンアップして確認できましたので、修正しました。)

- WSL1, WSL2ともにUbuntu20.04 (20.04.3)
- TeraTerm 4.106

で確認済です。

下記に記載している、パスワードなし・公開鍵使用のsshログインは、
**ログイン元の秘密鍵のセキュリティ保持が大前提** 
です。それができない人は使わないこと。

# やっていることの全体像
- WSLに（この例ではRSAの）公開鍵・秘密鍵をインストール
- localhostにパスワードなし・公開鍵使用でsshログインできる環境をセットアップ
- その秘密鍵をTeraTermのsshログインに使用

# 準備 - WSLでのsshログイン確認
WSLで、
1. sshのインストール
2. RSAの公開鍵・秘密鍵のインストール
3. localhostにRSAの公開鍵をコピー

```
$ ssh-copy-id -i ~/.ssh/id_rsa.pub localhost
```

上記を実施すれば、Ubuntuアイコンのターミナルで、

```
$ ssh localhost
```

が、パスワードなしでログインできることを確認しておく

# TeraTermでのログイン確認
次に、teratermを立ち上げて、下記の手順でWSLにログインできることを確認する
1. 「新しい接続」ウィンドウで、
- TCP/IPを選択
- ホスト：localhostを入力
- サービス：SSHを選択
- SSHバージョン：SSH2を選択
2. 「SSH認証」ウィンドウで、
- ユーザー名：WSLのログインユーザー（WSLインストール時に指定したもの）
- パスワード：空欄のまま
- RSA/DSA/ECDSA/ED25519鍵を使うを選択
- 秘密鍵ボタンを押して、「公開鍵・秘密鍵のインストール」でインストールした（RSAの）秘密鍵を指定

```
WSL1 (Ubuntu16.04)の場合の秘密鍵の指定
(Windowsのホームディレクトリ)\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu16.04onWindows_79rhkp1fndgsc\LocalState\rootfs\home\[username]\.ssh\id_rsa
```
```
WSL2 (Ubuntu18.04)の場合の秘密鍵の指定
\\wsl$\Ubuntu-18.04\home\[username]\.ssh\id_rsa
```

（ここで`[username]`はWSLのログインユーザー名）

# TeraTermのショートカット作成
TeraTermのショートカットを作成し、右クリックして出てくるプロパティウィンドウで
- ショートカットタブを選択
- リンク先を下記に変更

```
WSL1 (Ubuntu16.04)の場合
"%ProgramFiles(x86)%\teraterm\ttermpro.exe" [username]@localhost /auth=publickey /keyfile=%USERPROFILE%\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu16.04onWindows_79rhkp1fndgsc\LocalState\rootfs\home\[username]\.ssh\id_rsa
```

```
WSL2 (Ubuntu18.04)の場合
"%ProgramFiles(x86)%\teraterm\ttermpro.exe" [username]@localhost /auth=publickey /keyfile=\\wsl$\Ubuntu-18.04\home\[username]\.ssh\id_rsa
```
（`[username]`はWSLのログインユーザー名）

このショートカットをダブルクリックすれば、WSLにログインできるはず

# 補足（蛇足）
同様の準備と手順で、localhostをリモートのsshサーバーのホスト名に変更すれば、
リモートのsshログインのショートカットになる
JavaFX　初期状態

JavaFX初期状態
**Main.java**

```Main.java
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{
        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

```

**Controller.java**

```Controller.java

package sample;

public class Controller {
}


```
**sample.fxml**

```sample.fxml


<?import javafx.scene.layout.GridPane?>

<GridPane fx:controller="sample.Controller"
          xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10">
</GridPane>


```
slack自作スラッシュコマンドで簡単リマインダー文生成

##前置き

@marogoma　様の記事
[slackで「投稿ルールが守られない問題」を自作のスラッシュコマンドで解決する(設定編)](https://qiita.com/marogoma/items/e3003564c1b8b7b09e29)
[slackで「投稿ルールが守られない問題」を自作のスラッシュコマンドで解決する(GASコード解説編)](https://qiita.com/marogoma/items/93c1825454e03ee79523)

を見た時、小さい会社で業務効率化大臣(自称)としてGAS周り（とSlackもちょっと）の連携に燃える私は
**こ、こんなことも出来るんや…！！はよ導入せな！！！！**
とめちゃくちゃワクワクしたのですが、ふと弊社の備品購入申請チャンネルを見てみると割とルール守られてて(人数が少ないので)そんなに必要ない気がしたので、自分的に必要な場面を考えてみました。

そこで思い起こしたのがSlackのリマインダー機能。
私は自分のDMをTodoリストとして使ってるのもあり、割とリマインダーも使っているのですが、
日付指定をするときに妙に色々入れ方があって、しかも**英語圏仕様の入力規則**のため感覚的に入れて認識されないことが多く絶妙に使いづらい。
あと投稿後のオプションでも一応登録も出来ますが、「明日」とか「1時間ごと」とかで物凄い大雑把で使い物にならなくないですか。

先の記事の応用でこれが解決できそうな気がしたのでやってみました。


##実際の画面
![remindeasyINTERFACE2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304716/9b53ca88-a198-21a4-c895-299ad11cabfd.jpeg)

こちらが生成されるダイアログ。
曜日や毎日などの繰り返し指定と、日付で単発指定が出来ます。(例は単発)
![remindeasyPOST.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304716/ae6a9341-cc76-096c-e533-60610ab2f08c.jpeg)
そして「生成」ボタンを押すとbotがリマインダー用のメッセージを作ってくれるので
あとはこれを投稿すればOKです！手動でね…

##やりたかったことと無理だったこと

まず理想は

**「誰に」「いつ」「何を」リマインドするかを簡単に指定して、「登録」ボタン一発でリマインダ登録！！**

でしたが、今回色々やってSlackAPIの基礎の無さにより一旦保留にしたのが以下の仕様です

**①リマインド先を選んで他人やチャンネルにも送れるようにしたい。できれば自動補完のある入力欄で**
入力欄を選択形式にするとき、そのワークスペースのチャンネルとDM全てを動的に取得して検索まで出来る`conversations`という理想的なプロパティがあるにも関わらず、取得されるのがチャンネルIDで、そこからどうチャンネル名を取得すればいいか分からず挫折
まぁ基本は自分メモ用なので、text形式で基本の値を`me`にしました…

**②ダイアログの投稿ボタン一発でリマインダ登録まで完了**
いや投稿文章の頭に「/remind」ってつければ行けるっしょよゆーよゆーと思ってたら、そのままメッセージとして投稿されましたね…
なのでこの記事は「簡単リマインダー」ではなく「簡単リマインダー文生成」となってます。
要するにbotで文章つくるからコピペして自分で再投稿しろよ！という…力及ばず申し訳ありません。


しかし先の記事のおかげでSlackAPIの可能性にも目覚めたため、これからそちらも勉強して行く中で上記も実装出来たらなと思います。（本音：コメント欄で教えて貰えるとありがたいですとても）




##実際のコード
長いのでこちらはGithubに載せました。
@marogoma　様のコードを適宜改変して作ったので、コメントアウトとかも割とそのままです
https://gist.github.com/tama441/5582941d975ed3303d55f9f8b7ccc65e

###カスタマイズした部分
最終的なコードを見てみると、結局のところ全チャンネルで使用できるようにチャンネル判定の部分を削ったくらいな気もします。
途中は入力欄のAttributesを追加して色々やろうとしてたんですが、そもそもSlackAPIを根本的に理解してないため小難しい改変は無理！と気付いたので…

多少工夫した点としては、
日付をフォーマットできるGASメソッド`Utilities.formatDate()`を使用して
ダイアログ作成時は当日の日付を初期値にして
`Utilities.formatDate(new Date(), 'JST', "yyyy/MM/dd")`

Slackに飛ばすときは同じ方法で英語圏形式の日付順に直したところかな
`Utilities.formatDate(new Date(s.date), 'JST', "MM/dd/yyyy") || "";`

あとこれはSlackリマインダーの入力法則の話ですが、
![remindeasyPOST2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/304716/6734a813-c484-c8ae-7d48-7b200fefec5c.jpeg)


こんな感じで「繰り返しの指定(毎日/毎週など)」をした後に「ピンポイントの日時指定」を並べた場合、後者は無視されるので、
初期値に設定したに当日の日付は使わない場合も消す必要はありません。


##個人的にかなり便利になりました

参考にさせてもらった記事、物凄く丁寧で分かりやすく、とてもありがたいです。(謝辞)
Gitサーバー初期設定

# １．Gitサーバーにて
1. gitディレクトリ作成
 - フォルダ名.git
2. bare repositry 設定で初期化
 - git init --bare 

# ２．ローカルにて
1. local repositry設置
 - mkdir [folder]
2. local repositryでinit
 - git init
3. リモートリポジトリ設定
 - コマンド例 -> git remote add [alias] [user]@[host]:[dir path]
 - 削除 -> git remote rm origin


4. first push
 - readmeファイル等を作ってpush
 - エラー時には、サーバー側の権限、sshを確認

# ３．Gitサーバーにて
1. logコマンドで確認
 - git log
WindowsTerminal (Preview)でGitBashを使用する

# はじめに
WindowsTerminlaのプレビュー版が、MicrosoftStoreで公開さたので、チョロチョロ遊んでみていますが本リリースが楽しみですね。
コマンドラインインターフェースもこれ一つに統合できそうですが、普段使っているGitBashはデフォルトで設定されないため、profiles.jsonに設定を追加してみました。

# GitBashの追加
1. `Ctrl` + `,` でprofiles.jsonを開く
2. "profiles" : []に、GitBahs用のObjectを追加する。以下設定例  
{  
    "acrylicOpacity" : 0.75,  
    "colorScheme" : "Campbell",  
    "commandline" : "C:\\Program Files\\Git\\bin\\bash.exe",  
    "cursorColor" : "#FFFFFF",  
    "cursorShape" : "bar",  
    "fontFace" : "Consolas",  
    "fontSize" : 11,  
    "historySize" : 9001,  
    "icon" : "C:\\Program Files\\Git\\mingw64\\share\\git\\git-for-windows.ico",  
    "name" : "Git Bash",  
    "padding" : "0, 0, 0, 0",  
    "snapOnInput" : true,  
    "startingDirectory" : "%USERPROFILE%",  
    "useAcrylic" : false  
}

Pathに関しては自己環境に合わせてください。今回は、Gitインストール時についてくる、GitBash For Windowsを利用した場合の設定です。
/Git/git-bash.exeは、別Windowで立ち上がってしまうので、/Git/bin/bash.exeを利用しています。
不足している、Aliasは、/Git/etc/bash.bashrcに追加。

追加例
alias ll='ls --color=auto -al'
alias ls='ls -F --color=auto --show-control-chars'

# おわりに
デフォルトをGitBashにしたい場合は、"globals"."defaultProfile"に対象プロファイルのguidを設定する。
guidは、保存時に自動で付与されます。
それでは、良いターミナルライフを。
AtCoder Beginner Contest 133の復習

# [B - Good Distance](https://atcoder.jp/contests/abc133/tasks/abc133_b)

## 問題文

```
D次元空間上に N個の点があります。i 番目の点の座標は (Xi1,Xi2,...,XiD) です。
座標 (y1,y2,...,yD) の点と座標 (z1,z2,...,zD) の点の距離は √(y1−z1)2+(y2−z2)2+...+(yD−zD)2です。
i番目の点と j 番目の点の距離が整数となるような組 (i,j) (i<j) はいくつあるでしょうか。
```

## 入力例

```
3 2
1 2
5 5
-2 8
```

```
3 4
-3 7 8 2
-12 1 10 2
-2 8 9 3
```

## 自分の考えた解答

多次元配列にあたふたしてしまった
全然スマートにできなかった反省
できるかなと思ったけど通せなかった　死にたみが増す

```Python
import math
#Nこの点　D次元
N, D = map(int, input().split())
points = []
count = 0
for i in range(N):
    points.append(list(map(int, input().split())))

def combinations_count(n, r):
    return math.factorial(n) // (math.factorial(n - r) * math.factorial(r))

#一次元を考える
if D == 1:
    print(combinations_count(N, 2))

else:
    #number0のとりうるあたいは0からN-1
    for number0 in range(0,N):
        ans = 0
        if number0 != N-1: 
            for number1 in range(0,D):
                #print("先",number0,number1,"後",number0+1,number1)
                ans = ans + pow(abs(points[number0][number1]) - abs(points[number0+1][number1]),2)
        else:
            for number1 in range(0,D):
                #print("先",number0,number1,"後",0,number1)
                ans = ans + pow(abs(points[number0][number1]) - abs(points[0][number1]),2)

        #print("ans",math.sqrt(ans).is_integer())
        if math.sqrt(ans).is_integer() == True:
            count = count + 1

    print(count)
```

## 参考にした解答
https://atcoder.jp/contests/abc133/submissions/6300881

```Python
N, D = map(int, input().split())
X = [[int(i) for i in input().split()] for i in range(N)]

print(X)

ans = 0
##関数にするのがよい
def dis2(x,y):
    #配列に詰めておく
    T = []
    for i in range(len(x)):
        T.append((x[i]-y[i])**2)
    #配列の合計をここでかえす
    return sum(T)

for i in range(N):
    for j in range(i+1,N):
        print("i",i,"j",j)
        print("X[i]",X[i],"X[j]",X[j])
        #それぞれの次元の配列の合計を返す
        R = dis2(X[i],X[j])
        for k in range(R+1):
            #これで整数かどうかをみている
            if k**2 == R:
                ans +=1

print(ans)

```

## 敗因
多次元配列の扱いに苦戦してしまった
模範解答のように、配列を渡して処理をする関数を作ればよかったなと思った

#[C - Remainder Minimization 2019](https://atcoder.jp/contests/abc133/tasks/abc133_c)

## 問題文

```
非負整数 L,Rが与えられます。 2つの整数 i,jを L≤i<j≤Rを満たすように選びます。 (i×j)mod 2019
の最小値を求めてください。
```

## 入力例

```
2020 2040
```

##　自分で考えた解答

```Python
L, R = map(int, input().split())
small = 1000
if L+1 == R:
    print(L*R)
else:
    for number in range(L,R-1):
        ans = number*(number+1)%2019
        if small > ans:
            small = ans

    print(small)
```

絶対計算量すごいことになるだろうなと思いながら書いたのでダメだった

## 参考にした模範解答

```Python
L,R=map(int,input().split())
 
R=min(R,L+2019)
#print(L,R)  
 
COUNT=2019
NUMBER=0
 
for i in range(L,R+1):
  for j in range(i+1,R+1):
    print("i",i,"j",j)
    
    NUMBER=i*j%2019
    #print(i,j,NUMBER)
    if COUNT>NUMBER:
      COUNT=NUMBER
      #print(i,j,NUMBER)
 
    
print(COUNT)
```

二重ループは使うけど、あまりは2019以下でさがしていけばいいのかとなった
うーんくやしい
三平方の定理をtex記法で書いてみよう！

こんにちわ！サーモンだけは絶滅してほしくないこうぴかです。
この記事はtexで簡単な数式を書きたい人に向けて書いています。

目標は下のような「三平方の定理」を書くことです！

```math
 a^2 + b^2  =  c^2
```



目次
1.はじめに入力すること
2.二乗の書き方
3.演算をいれる
4.その他


##はじめに入力すること

まず初めに「どこからどこまで」をtexで書くのかを

```tex:はじめてのtex

```math ```


```

と入力します。
次は「‘‘‘math」と「‘‘‘」の間に式を入れていきます。

##二乗の書き方

aの二乗は


```tex:はじめてのtex

a^2


```

と書くので先ほどの「‘‘‘math」と「‘‘‘」の間に入れて

```tex:はじめてのtex

‘‘‘math 
a^2
‘‘‘


```

とすると



```math 
a^2
```

でけたーーー！

【注意】「はじめてのtex」の画面では半角「```」を全角「‘‘‘」と表記していますが半角で入力してください

同様にして

```math

a^2,b^2, c^2

```

##演算をいれる

あとは＋と＝を間に入れていきましょう！

```tex:はじめてのtex

‘‘‘math 
a^2　+ b^2 = c^2
‘‘‘


```


と書けば…

```math
 a^2 + b^2  =  c^2
```

三平方の定理のできあがり！！


【注意】「はじめてのtex」の画面では半角「```」を全角「‘‘‘」と表記していますが半角で入力してください

##その他

ちなみに「a^2」「b^2」「c^2」をそれぞれ「\sin^2 x」「\cos^2 x」「1」にかえると

```math
 \sin^2 x + \cos^2 x  =  1
```

三角関数の関係式が書けます。

##まとめ
今回は、二乗の書き方と演算子を使って三平方の定理を書いてみました。意外と簡単にかけたから、次は積分のインテグラルを書いてみたいな。では！
個人的に気になって読んだ自己啓発本などを紹介

# はじめに
軽く自己紹介となります。

- IT技術者12年（13年目）（近々転職して辞めると思われる（金=Nothing )）
- 自社は正社員で、派遣（いわゆる、SESか・・・）
 - 4社ぐらいで、今の所が8年と最長
   ※途中、サブプライムローン問題とかで、1社目2年ぐらいで金がねぇ！ってなって切られました（大企業でしたが、4桁後半億円赤字って言われても現実味がないが、仕事無くなったのが一番の現実だ）。詳細は、また別のときにでも。そこからは1日だけの仕事したり（※自社は開発業務やっていないというより、色々とヤヴァカッタんですねｗ）して、体育会系の所に行って精神を病み、夜勤有りのオペ職に4か月逝って4キロ太ったりし、今現在働いているところに落ち着く。（精神面も安定した気がします）

その、精神面が安定するまでに読んだ本を紹介したいと思います。


## マネジメント エッセンシャル版
P・F・ドラッガー 著 （故）

皆さんご存じ（？）、マネジメント系の書物となります。
ただ、この本を読む前に、当時話題になったもしドラを読んでから読みました。

※なお、もしドラは・・・アニメはそれなり、小説今一（話の流れがね）っていうのが個人的感想です。

ただ、読み始めて、1章ぐらいで辞めました。
が、別のやる気が出てきました。

「今のままだとダメなので、どうにかせねば」
と。
※なので、実は最近になって初めから読み直しております。m(_ _)m

## 実践するドラッカー 思考編/行動編

上に続き、ドラッカー関連の本です。
ドラッガーの今までの書籍などの考えを、各編事に分けて作成された書籍となります。

IT系ですが、会社に全否定された気もしますので、思考などを変えるにはという事で
読むことにしました。
ただ、元が阿呆の子なので、多少は思考ルーチンが変わった気がします。

※自社の部長と面談で本について話してたらまた全否定受けて沈んだけど、ねぇ？

## プロフェッショナルの条件 はじめて読むドラッカー (自己実現編)

すでにこの時点で、ドラッガー氏の書物にハマってます。
今まで考えもしなかった事が書かれており、新しい事って楽しいってなってました。

さて、この本は、仕事や、プロってなんだろう？と悩んでいたので手に取った本となります。
今までの仕事のやり方を見直したり出来ればと！

・・・普通に、歴史書みたいな感じで面白かった♪

## プロフェッショナルの原点

ドラッカー氏の今までの本の名言集、みたいなものですね。
本の内容を一部引用し、それに対する取るべき行動と身に付けるべき姿勢について書かれています。
見開き２Pで94の名言について書かれており、上の本の内容も紹介されており、
「ああ、そうゆうことだったのか」と再認識させてくれます。
※ドラッカー関連を読むならこれだけでもいいかもしれませんね。

## 明日を支配するもの

これも、ドラッカー氏の本です。
結局のところ、自分を律する（マネジメントする）という考えに帰結しているのではないでしょうか？
と、いう感想となりますね。

## 7つの習慣

とりあえず、書いていること試すのは、環境セット出来ないと無理だろう。
書かれている内容と、見ている視点が変われば起こるだろうパラダイムシフトという話は
面白かったな。
後は、後輩についてちょっと悩んでいたり、その他人間関係に悩んでいるなら読んでも
いいと思います。その人の個人ではなく、人格主義という考え方は、確かに色々と思い当たる節があった。

## 転職の思考法

去年末ぐらいから転職を考えてましたが
（今の所終わったらやめるって考えてましたが終わらないし、こっちの人生終わりそうだし？）
仕事で暇なときはダイヤモンドオンラインを読みますが、
そこで紹介されていたので気になって買いました。

転職の思考法というより、考え方の切り替えってところかな？という感想です。

# まとめ
感想文とか、他の人に伝える等、まだまだ未熟なため、中途半端な紹介となってしまいました。

自己啓発本は、読んでて面白いです。
が、実践までつながらないと意味がないので小説と思って読まない方がいいですね。

ただ、折れた心は戻らないけど、やる気は出してはくれたと思います。

# 補足
え？心病んだなら病院行け？
全く持ってその通り。ただ部長と話してて「精神科は結局、薬処方されて終わるだけだー。うんぬんかんぬん（詳細忘れました。）」という一言で行かなかったんですよね。
割と、信頼寄せてたんですよね、部長には。
まぁそれだけでなく、薬も余り飲みたくなかったってのもありますけどね。
AmazonLinux2へCloudMapperをお試し導入

# 目的
CloudMapperというツールを利用すれば、自動で構成図を書いてくれるとの記事を見かけたため試しに導入。

# 記事レベル　記載理由
理解せずにツールを利用している場面が多々あるため、試しに導入する際の参考程度。
他にも参考サイトがあるにも関わらず、本記事を載せたのはcloudmapperのバージョンアップに伴い利用するコマンドが若干異なっていたため。

# 参考サイト
（公式）https://github.com/duo-labs/cloudmapper
https://dev.classmethod.jp/cloud/aws/cloudmapper-install/

# 導入時期　環境
導入日：2019/07/07
AMI ID：amzn2-ami-hvm-2.0.20190618-x86_64-gp2 (ami-0c3fd0f5d33134a76)

# 前提
EC2はパブリック環境で、パブリックIPを付与する。
rootアカウントで作業する。

# 導入手順
##Githubソースのダウンロード

```
yum install git -y
git clone https://github.com/duo-labs/cloudmapper.git
```

##　必要パッケージダウンロード
マニュアルに載っている「python3.7-dev」「python3-tk」が存在しないため
```yum list```で近い名前のパッケージ名を検索し「python3-tkinter.x86_64」「python3-devel.x86_64 python3-pip.noarch」を導入。
マニュアル上必須要件であるpythonの3.7が未導入のため「python3.x86_64」を導入。
※Pipfile（pipenv導入対象記載ファイル）ではpython_version = "3.7"　と記載されている。
pipも後ほど利用するため、「python3-pip.noarch」を導入。

```
yum install autoconf automake libtool jq
yum install python3.x86_64 python3-tkinter.x86_64  python3-devel.x86_64 python3-pip.noarch
```

##　pip関連モジュール　インストール
pipenvを利用し、Pipfileの中身を導入。
マニュアルだと実行コマンドに```python3 -m```がついていないため、省略する方法があるはず。
調査不足により下のコマンドを利用。

```
python3 -m pipenv
python3 -m pipenv install --skip-lock
```

##　policy権限付与
cloudmapper利用時に以下のpolicyが必要とのことなので、ec2のroll作成して付与し、作業対象のEC2にアタッチした。
AWS環境の情報取得で必要なポリシーと思われる。マッピングする対象が決まっているなら、絞り込んでもよいかも。

    arn:aws:iam::aws:policy/SecurityAudit
    arn:aws:iam::aws:policy/job-function/ViewOnlyAccess

##　構成情報取得
ようやく構成情報取得。
「demodemo」は適当な名前。

```
aws configure
 # おそらく不要な手順）　region のみ ap-northeast-1 を設定。他はEC2のroleで対応
python3 -m pipenv shell
python3 cloudmapper.py configure add-account --config-file config.json --name demodemo --id 【自身のAWSアカウントID】
python3 cloudmapper.py collect --config config.json --account demodemo
python3 cloudmapper.py prepare --config config.json --account demodemo
```

##　構成情報をブラウザで確認準備
ブラウザで情報確認のため、nginxを導入。
nginxは```yum```ではなく```amazon-linux-extras```で導入。
```amazon-linux-extras list```を見て分かったが、導入パッケージ名は```nginx```ではなく```nginx1.12```であった。

```
amazon-linux-extras install nginx1.12
systemctl enable nginx
systemctl start nginx
unalias cp
cp -rf web/* /usr/share/nginx/html/
```

##　構成情報をブラウザで確認
利用中のブラウザから、パブリックIPに対してアクセスする。
アクセスに失敗する場合は、セキュリティグループなどのアクセス経路を確認するとよいかも


# その他
・pipenv利用が必須となっている
過去には「requirements.txt」（pip導入リスト）を利用しているためpipコマンドで導入しているが、現時点では「Pipfile」を利用しているためpipenvが必要となる。
リリースログを見ていないが、便利になる理由があるのだろうか。
・情報取得対応サービスの範囲
EC2やS3は対応しているが、どこまで対応しているかが不明。
もしかしたらまだ対応していないサービスもあるかも
・複数アカウントに対応しているか不明
CloudMapper情報を取得する際に、AWSアカウントで他のAWSアカウントの参照権限を含めたら構成図に含めてくれるのだろうか。
調査予定はなし
vimでマークダウンファイルをリアルタイムプレビューする

これまで使っていたマークダウン関連のプラグインが何故か動作しなくなっていて、原因探るのも面倒くさかったので、何か新しいプラグインとか開発している人がいるんじゃないか、と思って探したら、ありました。

[https://github.com/iamcco/markdown-preview.nvim:embed:cite]

starもいっぱい付いてるし、READMEも充実してるし、ということで試してみました。

# インストール
プラグインの管理にはvim-plugを使っているので、設定ファイルに以下の記述を追加して、:PlugInstallします。

```
" markdown plugin
Plug 'iamcco/markdown-preview.nvim', { 'for': ['markdown'], 'do': 'cd app & yarn install'  }
```

## 注意事項
公式サイトにはインストール方法が２つ紹介されていて、１つは以下の記述。<br>

```
Plug 'iamcco/markdown-preview.nvim', { 'do': { -> mkdp#util#install() } }
```
こちらの方法だと自分の環境ではインストールに失敗しました。原因は不明。

仕方がないので上記のyarn installの手法でのインストールにしたところ、うまく動作するようになりました。
もちろん、こちらは予め、nodejs環境とyarnがインストールされていることが前提となります。

# 使い方
テキトーなマークダウンファイルを開いて編集後、:MarkdownPreviewコマンドを叩きます。
ブラウザのタブが開いてプレビュー開始。
毎回、MarkdownPreviewを打ち込むのはツライので、ノーマルモードで;;pと打ち込むとプレビューを開始するようにしました。

```
" ---------------
" markdown-preview.vim setting
" ---------------
nnoremap <silent> ;;p :MarkdownPreview<CR> " ;;pでプレビュー
```

# 感想
編集位置に合わせてスクロールも追随してくれるし、GitHub Flavored Markdownのテーブル記法などにも対応していて、機能としては十分だと思いました。


試していませんが
（試しました）mermaid記法とか、そのあたりの記法にもしっかり対応しているようで、starがたくさん付いてるのもうなづけます。

動作としては特にこれまで使っていたプラグインとは特に差はないんですが、プラグインだけインストールすれば、とりあえず動作する、とか導入が簡単なのは良いな、と思いました。
【MongoDB】リストの中身があるドキュメントだけ抽出する

# 前提
以下のようなcollectionから`"numbers"`の中身があるドキュメントだけ抽出したい．

```json
{
   "numbers": [1,2,3,4]
},
{
   "numbers": [1,2]
},
{
   "numbers": []
}
```

# 解決策
これが一番簡単だと思う．

```console
> db.collection.find({"numbers.1": {$exists: true}})
```

カウントするならこれ．

```console
> db.collection.count({"numbers.1": {$exists: true}})
```
docker内のmysqlの文字コードが反映されていない時の対処

my.cnfを変更してローカルのmysqlを確認するとちゃんと反映されていたのに、dockerのmysqlが反映されていなかった。
原因はずっとdockerを立ち上げたままで変更前のmysqlで確認していたから。
なので

```
docker-compose down
↓
docker build mysql
```
そしてまたdocker内のmysqlに入る。

```
mysql> show variables like 'chara%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
```
変更されている

###教訓
設定をいじったら起動しているdockerを閉じて再びbuildする。
Java SE 8 Silver 資格取得に向けての日記

#Java SE 8 Silver 資格取得に向けて
シンプルにまとめますと
自分の足元を固めていきたいと思い、~~また会社から報酬金が出ると聞き、~~
資格取得しようと決めました。

##なぜ投稿する？
先日、ITパスポートを取得しましたが、（625点、ギリギリでした、、）
モチベーションの維持がなかなか難しく、
人の目に触れるようにするとできるかな、と思い投稿を決めました。
**⇒モチベーション維持のため！**

よろしければアドバイスや激励のおことばいただけますと嬉しいです。

##取得したい時期
**2019年8月中**
その時点でむずかしそうであればまた考えようと思っています。

##学習方法
###会社での研修
**・Javaの道**
[Javaの道](https://www.javaroad.jp/)：先輩社員のおすすめのサイト
この[基本](https://www.javaroad.jp/index_basic.htm)の読解
**・北ソフト工房の練習問題**
[北ソフト工房](http://www.kitako.tokyo/)の[Java練習問題集](http://www.kitako.tokyo/lib/JavaExercise.aspx)

###自分での学習
**・いわゆる黒本の読解**
[黒本とは？(Amazonへのリンク)](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-Java-Silver-%E5%95%8F%E9%A1%8C%E9%9B%86-1Z0-808/dp/4844339931/ref=asc_df_4844339931/?tag=jpgo-22&linkCode=df0&hvadid=295658314765&hvpos=1o1&hvnetw=g&hvrand=15560104839583524400&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009309&hvtargid=pla-526914835838&psc=1&th=1&psc=1)
**・progate(無料でできる範囲まで)**
[progate](https://prog-8.com/dashboard)
Markdownをプレビューなしで見たまま編集できるOSSを発見！

## 何がMarkdownプレビューの問題か？
多くのマークダウンエディタは、エディタとプレビューが分かれているのが当たり前になっています。対応関係を考えなら編集する不便があります。長くなるに連れてスクロール同期の質なども影響してきます。LaTeXで論文書くときも同じ苦労があります。例えば、Microsoft WordやScrapboxのように**WYSIWYG = What You See Is What You Get**だとより書きやすくなります。

"見たままの編集"とエンジニアに優しいMarkdownの融合はとても強力だと思います。

## OSSのMarkdownエディタ - HyperMD
念願だった見たまま編集できるHyperMDというOSSのプロジェクトを発見しました！

![hyper-md-top-for-qiita.mp4.opt.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84451/7ab73120-af38-fc1d-4f51-b904d982b1ad.gif)

### GitHubリポジトリ
<https://github.com/laobubu/HyperMD>

#### Typoraという存在
[Typora](https://typora.io/)という同じような目的のプロジェクトは以前から知られていますが、OSSでないことが欠点だと思っていました。それがHyperMDによって解決していてそこがHyperMDの魅力だと思います。

## 表（テーブル）の編集

表の編集もすごくスムーズです。
![hyper-md-table.mp4.opt.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84451/2350e1fd-48d1-2bd9-cbdd-1267a935a95b.gif)
表の編集は見たままの編集がすごく発揮するのではないかと思います。

## 数式の対応
Qiita同様MathJaxで数式に対応しています。
![hyper-md-math.mp4.opt.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84451/7fb77384-998c-e7a3-fbc0-2340e660a11e.gif)


## HTMLの編集
Markdownで併用できるHTMLもパカっと開いて編集できます。
![hyper-md-html-open.mp4.opt.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84451/979aca24-e4b5-f4a6-ff1d-0074ad30a40d.gif)
嬉しいことに、公式READMMEに"And more"に"HTML in Markdown -- WYSIWIG MDX is possible"という項目があるためHTMLの編集もより見たままで編集できるようになる可能性があります。

今日見つけたばかりで、かゆいところに手が届く感じしてて、まだまだ便利だなと思う機能が沢山ありそうです。

## 手元でHyperMDを試したい！

Glitchで手軽に試します。以下がnpmのプロジェクトです。HyperMD公式にあったものを利用してます。[Parcel](https://parceljs.org/)が使われていて短い設定でHyperMDが試せます。
GitHubリポジトリ: <https://github.com/nwtgck/nwtgck-hypermd>
実際のアプリケーション: <https://nwtgck-hypermd.glitch.me>

上記のリポジトリをcloneしたりして、自分でいろいろ試していけると思います。

### もっと例が見たい

以下がオンラインで動く例のまとめです。
<http://laobubu.net/HyperMD/docs/examples/>

実際のコードはこちらにあります。
<https://github.com/laobubu/HyperMD/tree/master/docs/examples>

最初の例だと、HyperMDの見たままの編集と通常のエディタ（CodeMirrorが使われている）に切り替える例です。
![hypermd-example1.mp4.opt.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84451/932a6c86-d636-9a5b-d9ab-3f3013940bcc.gif)
例には、その他絵文字のサジェスト機能とか、Mermaidによるフローチャートやシーケンス図を書いたりする例などいろいろ見つかります。

## きっかけのツイート
きっかけになった自分のツイートです。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">TyporaみたいにMarkdownの編集とプレビューの境目がないOSSついに発見！<a href="https://t.co/h2cB2Gfj6B">https://t.co/h2cB2Gfj6B</a> <a href="https://t.co/2eEOk6u0ZN">pic.twitter.com/2eEOk6u0ZN</a></p>&mdash; Ryo Ota (@nwtgck) <a href="https://twitter.com/nwtgck/status/1147780720716161024?ref_src=twsrc%5Etfw">July 7, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

Twitter上では、「HyperMDでローカルファイル編集したいな」などの声も上がっていて、HyperMDから色々と派生アプリ作られたらいいなと思っています。
ホワイトボックステストを勉強しました。

# ホワイトボックステストを勉強しました。

## ホワイトボックステスト???

高品質のソフトウェアを開発するためには、確認と検証が必要です。

- 開発された製品が正常に動作することを確認する作業（Verification）
- 製品が顧客が望む適切な製品なのかを検証する作業（Validation）

確認と検証のため、テストケースを用意してテストを行います。

ホワイトボックステストは、
ソフトウェアの内部のソースコードを確認する手法です。

ホワイトボックステストをする理由は、
内部のソースコードの動作を開発者が追跡することができるので、
動作の有効性だけでなく、実行される過程を見ることで、
コードがどのようなルートで実行され、不要なコードやテストされていない部分を調べることができます。

簡単に言うと、アプリケーションの内部構造と動作をチェックするソフトウェアのテスト方式です。

## ホワイトボックステスト技法

ホワイトボックステスト技法は、4つの技法があります。

- Statement Coverage
- Branch Coverage
- Condition Coverage
- Multiple Condition Coverage

![1123123.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421654/be11f986-4f4d-8990-b454-e965ba29bc1b.jpeg)


### Statement Coverage

プログラムを構成する文章が、
少なくとも、一度は実行可能な入力値をテストケースとして選定する。

上にある図を見ると、
【1-2-3-4-5-6-7】の流れで、
全ての文章を1回実行するように変数をKより大きな正の整数を用意します。

### Branch Coverage

プログラム中の分岐を
少なくとも、一度は実行するようにするテスト方法
たとえば、if文が2つあれば、4つの流れ（4種類の入力）を作成します。

上にある図を見ると、一つの例で、
【1-2-3-4-5-6-7】や【1-2-3-4-5-6-1】の流れで、
選択した分岐を一度は実行するようにします。

### Condition Coverage

簡単に言うと、実行可能なすべてのパスのチェックする方法です。

上にある図を見ると、一つの例で、
【1-2-3-4-5-6-7】や【1-2-3-4-5-6-1】、【1-2-4-5-6-7】、【1-2-4-5-6-1】の流れで、
全ての条件をテストします。

### Multiple Condition Coverage

IF文または、While文の内条件式を調査します。
if（x>1 or y<10）の場合、x>1の条件とy<10の場合
すべてをテストします。

##　ホワイトボックステストの必要性

- ブラックボックステストだけでは、プログラムのすべての実行可能なステートメントが実際に実行されるか不明
- ブラックボックステストだけでは副作用を予測する困難
- ホワイトボックステストプログラム内に不要な機能がある場合、これを見つけることがあります。
- ホワイトボックステストプログラムに誤字（Type Error）がある場合は、これを見つけることがあります。
Rails初心者がActiveRecordの結合や複数条件に苦戦した話

ActiveRecordに苦戦しながらテーブル結合したりしてデータ取得した話です。

## 背景
Rails初心者がデータの更新や、複数テーブル、複数条件で指定する時があるかと思います。
今回はその時に調べたことを簡単にまとめていますので、興味がある方は是非。
なので、今回はRails初心者向けの内容ですね。

## 結論
まずはテーブルの結合、条件指定のやり方

```ruby
TableA.joins(:table_b)
  .where(:table_b {id: 1})
  .where(id: 1)
```

joinsで内部結合しつつ、そのテーブルで条件を指定しています。
.where().where()でAND条件になっています。

そして、条件でorを使用するパターン
今回はvalueの範囲指定をorで繋げます。

```ruby
TableA
  .where(foreign_id: 1)
  .where('value >= ?', 0)
  .or(TableA.where(foreign_id: 2 ).where(value: 0..100))
  .order(:sort)
```

foreign_idが1で、valueが0以上のデータと、
foregin_idが2でvalueが0以上100以下のデータを取得します。

以下は.whereで取得したRerationに対して更新しています。

```ruby
relation.each do |data|
  # ここでdataの値を変更する

  data.save!
end
```

こうして変更したいデータ群の抽出と、それらのデータ更新を行いました。

## 何が大変だったか
ActiveRecordを使いながら知っていくのが大変でした。
.where()などを使うとrerationが返却されてきているので、.firstや.each()などを使用しないと例え1件しか取得していなくてもデータアクセスができません。それに、.load()を明示的に呼ばない限りはまだqueryを発行していないこともありますので、logger.debugの出力タイミングが意図しない順番になったりなど知っていないと難しい部分がありました。

基本だとは思いますが、クラスを調べれば大体なんとかなります。今回で言えばRelationクラスについて調べることで基本的に解決できました。
今後も複雑な条件が必要になってきたりすると思うのですが、その度に調べることになりそうです。
楽しみつつのRailsとの格闘はまだまだ続きそうです。
Makefileでファイルの中身を一行ずつ処理する方法

ファイルの中身を一行ずつ処理する場合、シェルで処理するだけだったら、これでおｋ。

```bash
cat a.txt | while read line
do
    echo $line
done
```
ところが、Makefileでこれをやると怒られる。
怒られずに同じことをやるには、`xargs`を使うとよい。
以下のように書くと、ファイルの中身が一行ずつ`echo`の引数に渡されて実行される。

```bash
cat a.txt | xargs -L 1 -i echo {}
```

```a.txt
1+1
2+2
3+3
```

```bash:出力
1+1
2+2
3+3
```
引数としてではなく、標準入力として渡したい場合、`echo`を経由してパイプすればよい。

```bash
cat a.txt | xargs -L 1 -i echo {}|bc
```

```a.txt
1+1
2+2
3+3
```

```bash:出力
2
4
6
```
後者はちょっと回りくどいので、いい方法を知っていたらぜひ教えてください。
php-master-changes 2019-07-06

今日は JIT での VM 割り込みの修正、ビルドシステムのリファクタリングがあった！

# 2019-07-06
## nikic: Always generate interrupt check in jit
- https://github.com/php/php-src/commit/da8b583ac13aab669e7a86215530bdcdce9ef453
- ext/opcache/jit で、zend_interrupt_function がセットされていなくても（timeout の処理のため）VM の割り込みチェックを行うよう修正

## petk: Remove PTHREADS_ASSIGN_VARS
- https://github.com/php/php-src/commit/1c9e8e8f6a7d0180d312aa76ae87435619935780
- [7.4~]
- ビルドシステムで、PTHREADS_ASSIGN_VARS を削除し TSRM のビルドの単純化

## petk: Move footer to the end of configure output
- https://github.com/php/php-src/commit/539b577827879f600899ad078abb8e42328453de
- [7.4~]
- ビルドシステムで、configure の出力末尾にライセンス出力を付けるよう修正
API-Platform の紹介

[API-Platform](https://api-platform.com/) は PHP で作成されている API 専用のフルスタックフレームワークです。Symfony フレームワークをベースとして構築されています。

## 背景
スマホアプリや React.js, Vue.js と行った SPA(Sinble Page Application)の登場、マイクロサービスの登場などにより、バックエンドの Web フレームワークは API サーバーとして使用されることが多くなってきました。そういった流れの中で、[API-Platform](https://api-platform.com/) は登場してきました。
https://api-platform.com/

同様なものに nodo.js で実装された IBM の [LoopBack](https://loopback.io/) があります。

## 特徴

- RESTFull API(CRUD) をビルトイン機能で簡単に作成（Entity クラスを作成するだけ）
- カスタム API の作成（ビルトインではなく Controller を作成して自分仕様の API の作成）
- 業界標準の様々なレスポンス形式に対応（json, ld+json, xml, etc.）
- Symfony のバリデーション機能と連動した RFC7807 準拠のエラーレスポンス
- Swagger UI に準拠した API仕様書の自動生成
- API に必要な各種機能（バリデーション、ページネーション、フィルタリング、ソート）
- 認証機能（JWT, OAuth）
- GrapQLのサポート
- React.js ベースのダイナミック Admin ツール
- React.js, Vue.js ベースの Progressive Web App の雛形生成（Scafolld）
- 2種類の配布方法
  - Dockerでコンテナ化されたオールインワン環境の提供
  - Symfony プロジェクトへ Composer コンポーネントとして追加

> つまり API を作成する時に決めなければならない仕様や
> 作成しなければならない基本的な機能がオールインワンで提供されています。
> 利用者はアプリの仕様やビジネス仕様の実装に専念できるわけです

## デモ画面

- デモ画面トップ：https://demo-client.api-platform.com/
- Swagger UI（API 仕様書）：https://demo.api-platform.com/
- Admin ツール：https://demo-admin.api-platform.com/

## 動画

https://youtu.be/M2Hxwi-qNQs
ちょっと動画が長いのと、フランス語訛りが強い英語で聞き取りづらいですが...

## Getting Started

#### オフィシャルサイトの Getting Started
https://api-platform.com/docs/distribution/
Installing Framework のところは２つのインストール方法が書かれています。

1. Using the Official Distribution (Recommended)
2. Using Symfony Flex and Composer (advanced users)

1つ目がオフィシャルディストリビューションである Docker を使ったインストール方法で
2つ目が Symfony を使ったインストール方法です。
どちらか一方をやるだけでよいです。

Docker や Symfony の知識があるとより理解できると思いますが、上からコピペでやっていっても出来るかと思います。

#### Symfony4とAPI Platformを使って5分でAPIサーバを作る

@ippey_s さんの Qiita の記事です
https://qiita.com/ippey_s/items/9cceec252babe8057047

Symfony と Composer を使ったインストール方法が説明されています。

## まとめ

API-Platform はドキュメントもしっかりしていますし、品質も高そうです。オフィシャルサイトのトップページを見ると様々なオープンソースで採用されていますし、すでに多くの企業で採用実績があります。

API-Platform は、ちょっとワクワクする API フルスタックフレームワークです。
個人的には Rails や Laravel を初めて見た時と同じ感動がありました。
ブレイクする予感。Symfony ふたたび。
MQTTブローカ Shiftr.io の設定備忘録

#概要

MQTTブローカの "**Shiftr.io**" を使い始めるための備忘録です。
Shiftr.ioについては↓URLを参照してください。
https://shiftr.io/about

#手順
###１．アカウント作成
Shiftrにアクセスして「Sign up」からアカウントを作成します。
https://shiftr.io/


![0_トップページ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/921d46ee-f103-6cc3-aeff-c85716958b7d.png)
###２．namespace作成
siftrはnamespaceと呼ばれるプロジェクト単位でMQTTブローカを管理できるようです。
ログイン後、**New Namespace**からnamespaceを作成します。
![01_namespace.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/3b01cde9-27b1-d913-59ea-6af9a6b29c96.png)

###３．namespace設定
namespaceの名前と公開設定を行います。テスト用なので、公開設定をPrivateにするためチェックを入れています。
Desciptionはnamespaceの説明で、必要に応じて設定します。入力後、**Create Namespace**で設定を完了しnamespaceを生成します。
![1_namespace作成.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/e6c16ee4-8287-a592-0685-9ff4da81bcca.png)

###４．token作成
namespaceの生成後、MQTTブローカの状態が表示されます。
次に接続トークンを追加します。
まずは**Namespace Settings**を開きます。
![11_namespace生成後 - コピー.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/137379cb-5fde-e28a-3fbe-b6cdb82156c9.png)

Namespace settingを開いたら、**Add Token**を選択します。

![namespace setting画面.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/3ff3a9d2-4ac9-2a72-3c45-af60feef94bf.png)

Add Token画面が開くと、デフォルトのKeyとSecretが入力されています。
ここはそのままにして、Permissionを選択します。
"full-acess" か "reead -onry"が選択可能です。

Descriptionに接続トークン名を入力します。今回は「send」としています。
入力が終わったら"**Create Token**"をクリックしてトークンを生成します。
![2_token作成キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/9942a6af-b43b-b8d3-e1f8-bbd4ec1e733d.png)

###５．トークンのURL確認
トークン生成後、Namespace Settings画面に遷移します。
トークン名の下部に接続URLが表示されています。
このURLをMQTTのpub/subに設定します。
![トークン生成後.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/013e625d-94ba-9fdc-1b73-be85d092236d.png)
[Python] 型の把握は大事です

# はじめに

最近Pyhonを勉強し始めた新人です。

今回はAtCoderを解いているときにはまってしまったことについて書きたいと思います。

# はまってしまった問題

以下に問題を載せます。
[B - Ordinary Number](https://atcoder.jp/contests/abc132/tasks/abc132_b)

### 問題
{1, 2, ..., n}の順列p={p1, p2, ..., pn}があります。
以下の条件を満たすようなpi(1 < i < n)がいくつあるかを出力せよ。  

* pi-1, pi, pi+1 の3つの数の中で、piが2番目に小さい。

### 制約
* 入力はすべて整数である。
* 3 <= n <=20
* pは{1, 2, ..., n}の順列である。



# 考え方
pi-1, pi, pi+1の3つの数の中で、piが2番目に小さい。
すなわち以下の条件を満たせばよいと考えました。

- pi-1 < pi < pi+1 または　pi-1 > pi > pi+1

また、nの最大値が20のため、全部見ていっても問題ないですね。

# 実際に書いたコード



```python
from sys import stdin


def main():
    n = int(input())
    p = stdin.readline().split()
    count = 0
    for i in range(1 , n-1):
        if p[i-1] > p[i] >p[i+1] or p[i-1] < p[i] <p[i+1]:
            count +=1    
    print(count)

if __name__ == "__main__":
    main()

```
入力例では、正しく出力できたので提出してみましょう。

# 結果
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443032/371ea56f-de51-72f5-a5cb-5c646b596705.png)

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443032/d152ab4a-3c9b-5c5d-27ac-13a98545f9a2.png)

WAです。
どうやら通らないテストケースがあるようです。
コードを見直してみると、**pの中身がint型ではなく、str型になっている**ことがわかりました。
以下のように修正します。

```python
from sys import stdin


def main():
    n = int(input())
    p = [int(x) for x in stdin.readline().split()]
    count = 0
    for i in range(1 , n-1):
        if p[i-1] > p[i] >p[i+1] or p[i-1] < p[i] < p[i+1]:
            count +=1    
    print(count)

if __name__ == "__main__":
    main()

```
提出してみると
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443032/26309181-c7d5-0a3c-ef95-cfa136bd52da.png)

無事ACです！

# 反省
型の把握が甘かったことが今回の反省点です。
また、string型の比較である程度通ってしまったが故に、気づくのが遅くなってしまいました。

# ちなみに
今回間違えてstring型で比較をしてしまいましたが、string型の比較はどのような挙動になるのか調べてみると、以下のサイトが見つかりました。
https://note.nkmk.me/python-str-compare/

上記のサイトによると、
> Python3では文字列strはUnicodeであり、文字列の大小関係（順番）は文字のUnicodeコードポイント（文字コード）で判定される。

> 文字列も数値などと同様に<, <=, >, >=演算子で比較できる。1文字目が同じなら2文字目、3文字目...と順番に比較される。

以下はUnicode表の一部です。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443032/f693c096-3063-03f3-feef-6321e030d426.png)

そのため、同じ桁同士だとint型と同じ結果になりますが、桁が違うと、異なる結果になってしまいますね。
Houdini環境変数のスナップショットとセットスクリプト

# はじめに

ランチャーやバッチスクリプトなどを使って、Houdiniを起動している際、それで作ったHIPファイルをレンダーファームのリモートクライアントなどで走らせたい場合は、その環境変数の状態のスナップショットを取って、それを設定した上で走らせる必要がある。その時のためのスクリプトのメモ。

注：現在、以下は個人的なメモで、実行結果を完全に保証しているものではない。



# 環境変数の書き込み

Shelf Toolや、HoudiniのSaver、レンダーファームへのSubmitツールなどに仕込む。

```write_env_snapshot.py
import os, sys
import json
import hou


hip_file_dir = os.path.dirname(hou.hipFile.name())
hip_name, ext = os.path.splitext(hou.hipFile.basename())
json_file = os.path.join(hip_file_dir, '{}_env.json'.format(hip_name))

envs = os.environ.copy()

with open(json_file, 'w') as f:
    json.dump(envs, f, ensure_ascii=False, indent=4, sort_keys=True, separators=(',', ': '))
    print('Wrote environment snapshot :: {}'.format(json_file))
```

# 環境変数の読み込みと設定

Houdiniの起動時に、次のスクリプトを実行。

```read_env_snapshot.py
import os, sys
import json
import argparse
import subprocess

HOUDINI_EXE = "" #<houdini_exe_path>
 
def open_hip(hip, envs):
    cmd = 'HOUDINI_EXE {}'.format(hip)
    subprocess.call(cmd, envs=envs)

def main():

    parser = argparse.ArgumentParser(description="Open hipfile with custom environment variables")
    parser.add_argument("--hip", type=str, help="Specify Houdini file")
    args = parser.parse_args()

    if not args.hip:
        return

    if not os.path.exists(json_file):
        print("Coudn't find environment snapshot :: {}".format(json_file))
        return

    hip_file_dir = os.path.dirname(args.hip)
    json_file = os.path.join(hip_file_dir, '{}_env.json'.format(hip_name))

    with open(json_file, 'r') as f:
        envs = json.load(f)

    open_hip(hip, envs)

if __name__ == "__main__":
    main()
```
【Java】Fizz Buzz問題を解いてみる

# はじめに

仕事でJavaを触る機会がすっかり無くなってきたので、Javaを使って様々な方法で「Fizz Buzz問題」を解く方法を考えてみました。

# Fizz Buzzとは

[Fizz Buzz - Wikipedia](https://ja.wikipedia.org/wiki/Fizz_Buzz)

* 英語圏で長距離ドライブ中や飲み会の時に行われる言葉遊びのこと。
* 最初のプレイヤーは「1」と数字を読み上げる。
* 以降のプレイヤーは、次の数字を読み上げる。
 * ただし、3で割り切れる場合は「Fizz」、5で割り切れる場合は「Buzz」、3と5の両方で割り切れる場合は「Fizz Buzz」と発言する。

# For文を用いた一般的な方法

```java:FizzBuzz.java
	/**
	 * for文を使った一般的な方法。
	 * @param end FizzBuzzを終える数。
	 */
	public static void useForLoop(int end) {
		for (int i=1; i<=end; i++) {
			if (i%3==0 && i%5==0) {
				System.out.println("Fizz Buzz");
			} else if (i%3==0) {
				System.out.println("Fizz");
			} else if (i%5==0) {
				System.out.println("Buzz");
			} else {
				System.out.println(i);
			}
		}
	}
```

# For文＋三項演算子を用いた方法

```java:FizzBuzz.java
	/**
	 * 三項演算子を活用した方法。
	 * @param end FizzBuzzを終える数。
	 */
	public static void useForLoopWithTertiaryOperator(int end) {
		for (int i=1; i<=end; i++) {
			System.out.println(
					(i%3==0 && i%5==0) ? "Fizz Buzz" : (i%3==0) ? "Fizz" : (i%5==0) ? "Buzz" : i
					);
		}
	}
```

# Stream APIを用いた方法

```java:FizzBuzz.java
import java.util.stream.IntStream;
...

	/**
	 * Stream APIを活用した方法。
	 * @param end FizzBuzzを終える数。
	 */
	public static void useStreamAPI(int end) {
		IntStream.rangeClosed(1, end)
			.mapToObj(i -> (i%3==0 && i%5==0) ? "Fizz Buzz" : (i%3==0) ? "Fizz" : (i%5==0) ? "Buzz" : i)
			.forEach(msg -> System.out.println(msg));
	}
```

# まとめ

* 一番古臭い書き方である「For文を用いた一般的な方法」が、一番見やすく理解しやすい感じ。
 * 三項演算子を重ねると、どうしても見づらくなってしまうのが難点。
 * Java Silver SE 8の試験では、「多重の三項演算子」に関する問題が出てきましたが、実際に使おうとすると可読性に問題があると改めて感じました。
* ちょっとした頭の体操をしつつ、さらにStream APIの復習になって一石二鳥。
 * 最近は業務でJavaから離れているので、Stream APIを触る機会もどんどん減っている気が...
 * 少し前に調べた、[rangeClosedメソッド](https://qiita.com/nkojima/items/dc1775049715bcfbd29e)の情報も役立ちました。