OmniAICreator/Qiita-1.07M huggingface dataset:
ElixirでElixirインタプリタを作成していく(第1回 文字列からモジュールと関数を導き出す)

#ElixirでElixirインタプリタを作成していく
##第1回 文字列からモジュールと関数を導き出す
本記事はElixirでElixirのインタプリタを作成していく．
その中で文字列中のモジュールと関数を抽出していくことを目標とする

###文字列をモジュールと関数，および引数に分割する
今回は文字列をモジュールと関数，および引数に分割する関数を作成する．そのことより以下の関数を定義することを目的とする
####定義
関数名:`to_function`
引数:`String`
返り値:`%{module: Module, function: Atom, argments: String}`
ここでモジュールが`Module`,関数が`Atom`であるのはapply関数を用いる際に都合が良いからである
####実装
初めにElixirの関数は次のような記述を行う．

```elixir
String.split "hello world"
# ["hello", "world"]
```
又は

```elixir
String.split("hello world")
```
と記述する

今回は上記をメインの記述として開発を進めていく
すると確実にモジュールと関数の集合体と引数の二つの部分に分割することが可能なことに気づくだろう

そう，最初のスペースで分割すれば大まかな二つの部分に分割が可能だ
よって次のようになる

```elixir:core.ex
defmodule ElixirInterpreter.Core do
  def to_function(str) when is_binary(str) do
    [order, args] = str |> String.split(" ", parts: 2)
  end
end
```

このうち，分割した2つ目の要素はすでに引数のみの文字列となっているためこのまま返せばいいことがわかる
次に，モジュールと関数を分割していく，その中で`String.split`は

```elixir
String.split # =>
Elixir.String.split
```
である．つまり，モジュール内にモジュールは定義されるが，関数内にモジュールは定義されない.
よって`.`で区切った文字列のうち一番最後が関数であり，それ以外はモジュールである．
つまり`.`で区切ったのち，最後とそれ以前を分けることができればよい．
次のようになる

```elixir:core.ex
defmodule ElixirInterpreter.Core do
  def to_function(str) when is_binary(str) do
    [order, args] = str |> String.split(" ", parts: 2)

    {func, module} =
      order
      |> String.split(".")
      |> List.pop_at(-1)
   end
end
```
これで関数を文字列として取り出すことができた
残りはモジュール部分を`Module`,関数部分を`Atom`として返すことができれば目的を達成することになる
関数部分は簡単である
`func`として帰ってきた部分を`String.to_atom`を用いることで`Atom`にすればよい
ところで`module`として帰ってきた部分を考えてみよう
これは文字列のリストとなっていることに気づくだろうか
`String.split`が元になっている場合，`["String"]`,
`Elixir.String.split`が元の場合，`["Elixir", "String"]`となっている
この形式から`Module`を直接求められる関数が存在する．
それは`Module.concat`である．この関数は文字列およびアトムのリストを引数として，それにあう`Module`として返す関数となっている
このことから最終的な`to_function`関数の形式が次のようになる

```elixir:core.ex
defmodule ElixirInterpreter.Core do
  def to_function(str) when is_binary(str) do
    [order, args] = str |> String.split(" ", parts: 2)

    {func, module} =
      order
      |> String.split(".")
      |> List.pop_at(-1)

    module = Module.concat(module)
    func = String.to_atom(func)
    %{module: module, function: func, argments: args}
  end
end
```
これを実行すると次のようになる

```
iex(1)> ElixirInterpreter.Core.to_function "String.split "hello world™"
%{argments: ""hello world™", function: :split, module: String}
iex(2)> ElixirInterpreter.Core.to_function "Enum.reverse [1, 2, 3]"
%{argments: "[1, 2, 3]", function: :reverse, module: Enum}
```
定義どおりに実装できていることが確認できる
***
今回は文字列からモジュールと関数を導き出した．これはまだ始まったばかりだ．
次回からは引数部分をリストに変換するが現時点で厳しい道のりなのは明白である．

第0回　[目次](https://qiita.com/Sepi110902/items/10e5f0645cacfc322bd4#_reference-08b7184ee12141f375b2)
第2回　[基本的な引数の分割](https://qiita.com/Sepi110902/items/63a302ecf52afbf5737a)

以下ソースコード(マスターでゴリゴリ開発してるので悪しからず．）
GitHub: [ElixirInterpreter](https://github.com/SeitaHigashi/elixir_interpreter)
Windows で Alfresco 6.0 を試す（Docker も同時に導入するよ編）

Alfrescoは最新版になって、Dockerイメージでの配布になりました。お試しという意味では楽になったんですが、そもそも、Dockerに馴染みがないとどうすればいいのかわからないかもしれません。手持ちのマシンが Windows 10 Pro なのでこれをローカルにつくってみます。

## Dockerを入れる

Docker を入れます。 Windows での Docker 環境は悩みがつきません。現在二つの選択肢があります。

* [Docker for Windows](https://docs.docker.com/docker-for-windows/)（新しい。内部でHyper-Vを使う）
* [Docker Toolbox on Windows](https://docs.docker.com/toolbox/toolbox_install_windows/)（古い。内部でVirtualBoxを使う）

いくつか制限があって、それをふまえてどちらかを選ぶ必要があります。

1. VirtualBox 環境が必要な場合は Docker Toolbox
Hyper-V と VirtualBox は共存できません。 VirtualBox 上で別途古い Alfresco を動かしたいときは、Docker Toolbox のほうがよいです。古い Alfresco も Docker イメージ化するという手もありますが、それができるなら Docker for Windows でもいいですね。

2. OSがWindows 10 Home なら Docker Toolbox
Windows 10 Home には Hyper-V がないので、必然的に Docker Toolbox になります。

3. minikube 使いたければDocker Toolbox
今回は Docker だけですが、Kubernetes のローカル版である minikube でお手軽に試したいみたいなことを考えている場合はDocker Toolboxのほうが安定しているようです。

なお、細かい違いですが Docker Toolbox と Docker for Windows では、ホスト（ブラウザでアクセスするときとか）からアクセスするときのデフォルトIPなども異なります。

Docker がインストールできたら [DockerHub](https://hub.docker.com/) のアカウントをとっておきます。 Alfresco のイメージなどがそこからダウンロードされるため、これは必要になります。

アカウントをとったらコマンドラインからログインしておきます（-pがセキュリティ的に許容できないのであれば、片方だけにして標準入力から入れましょう）

`docker login -u ユーザ名 -p パスワード`

ちなみにコマンドライン環境については標準の PowerShell からでも使えますが、使い勝手が良いのでぼくはGit Bashを使ってます。

## Alfresco起動

 Alfresco を入手します。[GitHubにDockerCompose設定ファイル群](https://github.com/Alfresco/acs-community-deployment/) がありますのでこれをGitのクライアントを使ってクローンします。

```
git clone https://github.com/Alfresco/acs-community-deployment.git
```

クローンしてきた、`acs-community-deployment/docker-compose` フォルダの中で、

```
docker-compose up
```

します。

必要なコンテナが全て起動され、 Alfresco が立ち上がるはずです。ブラウザからアクセスして確かめます。

なお、

* Docker Toolbox の場合のデフォルト　 http://192.168.99.100:8080/share
* Docker for windows の場合のデフォルト　http://10.0.75.1:8080/share

これらのIPアドレスなんですが…… Mac だと起動時に hosts を書き換えてくれたりするので、エイリアスが入るみたいなことがある（？）ようですが、 Windows 環境ではそれはなさそうです。なので、常駐している Docker Descktop（Docker for windows の場合）かコンパネのネットワークを見ます。そこに仮想アダプタがつくられていて、IPが設定されてるようです。それを参照してみてください。

追記：

Ubuntuとかに導入される方は[オープンソース警察のnicoさんのこちらの記事](http://labo-blog.aegif.jp/2019/04/alfresco-6.html) が参考になるでしょう
RailsのActiveRecordにおける、日付期間の重複チェック

参考によると

```
比較開始日付 <= 対象終了日付 AND 比較終了日付 >= 対象開始日付
```
で重なっていると判断されるらしいので

```
matched_dates = Hoge.where('start <= ? and end >= ?', self.start, self.end)
```
みたいな感じにすればよい

参考：
https://qiita.com/yaju/items/a58a78f41ee41258a5fe
Excelで横長の表を分割して縦に並べる一番早い方法

## そもそもExcelの表は横長になりやすい
Excelの表は横長になりやすいですし、むしろ横長に伸ばしたほうがオートフィルがうまく使えるので便利です。

しかしその計算結果を計算書等に載せるとき、分割して縦に並べたいということが往々にしてあります。

すぐ出て来そうで意外と気づくのに時間がかかったのでここにメモとして残しておきます。

## 「コピー」→「形式を選択して貼り付け」→「書式貼り付け」→「リンク貼り付け」

これを繰り返せば簡単に計算式を保持したまま表を成形できると思います。

僕の環境では行の幅は反映されなかったりしたので、適宜調整が必要かもしれません。
Istioが作るサービスメッシュ~サンプルアプリのデプロイ~

# サンプルアプリ
題材: [BookInfo アプリケーション](https://istio.io/docs/examples/bookinfo/)
※ 事前にIstioをKubernetesにデプロイしておいてください．
## 構成
![image.png](https://qiita-image-store.s3.amazonaws.com/0/192927/fcbb9b91-7253-7fc1-d45c-f29c9e0268dd.png)

# サンプルアプリのデプロイ
```shell
istio-1.0.6 directory
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
```

## bookinfo.yaml
取り敢えず，一部分を抽出してみました．
普段なら**targetPort**を指定していますが，サイドカーインジェクションのため，指定しなくても大丈夫と言うことなのでしょうか．
それ以外は差し当たっていつも通りのyamlかなと思いました．それでは次に行きましょう！

```yaml
##################################################################################################
# Details service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: details
  labels:
    app: details
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: details
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: details-v1
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: details
        version: v1
    spec:
      containers:
      - name: details
        image: istio/examples-bookinfo-details-v1:1.8.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
```

# Ingress Envoy(Gatewayのデプロイ)
```shell
# ingressのデプロイ
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
```

## bookinfo-gateway.yaml
いきなり**apiVersion**に注目ですね．
**networking.istio.io/v1alpha3**が使われています．
Istioによる拡張APIでしょうか．
GatewayとVirtual Serviceどちらも初めて聞きました．
筆者はGatewayに対するDeploymentとConfigMapがこの二つかなと解釈しました．

```yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway
  http: # /api/v1/products/ + /productpage or /login or /logout だとリクエストを，productpageに流すみたいですね．
  - match:
    - uri:
        exact: /productpage
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        host: productpage
        port:
          number: 9080
```

# まとめ
istioに利用するにあたって増えたAPIを理解する必要がありそうです．
次は，カナリアリリースのドキュメントでも見ていきましょう．
terraform-jp.slack.com を作ったのと招待リンク

# tl;dr

* [terraform の日本語ユーザコミュニティ](https://terraformjp.github.io/)作りました
* slack の招待リンクが急に管理者の承認が必要、みたいになってると報告を受けた
* 普通に設定を見ると招待リンクかメールアドレスのドメイン指定かしか選べない
* 無制限リンクがあったのでメモ

# terraform-jp.slack.com

かねてから terraform について気軽に話ができるところが欲しいなぁと思っていたので作りました。

個人的には実務担当者がこそこそ集まって知見を相談できればいいと思ってるんだけど、それはそれ人が集まらないと知見も集まりにくいなと思って [twitter アカウント](https://twitter.com/terraform_jp)を作ったら午前中だけで人数が三倍になるとか。。。

コミュ障なぼっちには厳しい＞＜

# 招待リンク

## 普通はメール

![image.png](https://qiita-image-store.s3.amazonaws.com/0/44420/58460706-3df9-b1df-fa2c-dc6899b7ca98.png)

こういうの届くじゃないですか。で、このリンクを貼っておいたんだけど、@chaspy から管理者からinviteもらわないと入れないようになってるって教えてもらって調べたわけです。

## 設定はこうじゃん？

ワークスペースの管理者設定のその他管理項目の設定と権限だと

<img width="734" alt="slack01.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/44420/0c35c10b-5388-533c-76da-e80d961e8e0f.png">

いけると思うじゃないですか。でも先のようにダメだといわれる。

## 以下のドメインを持つメールアドレス

*.com は消えるし、*.co.jp や *.ne.jp は通るけど、 *.jp はドメインとして違うとか言われて登録できないし（怒

まぁslackの設定とかをちゃんと理解してないこっちが悪いんですけどね？


## 無制限リンクは

ほんのちょっと下の招待リストから

<img width="749" alt="slack02.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/44420/e122fc58-0e47-bccb-e78a-e19453310e0a.png">

新しいメンバーの招待をクリックして

<img width="556" alt="slack03.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/44420/bc20f7ac-eb85-d813-bc06-6178ca5822f6.png">

招待リンクを共有するをクリックして

<img width="544" alt="slack04.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/44420/c5c044d5-eb20-1e91-3c79-9b89eb5e6d22.png">

こんなところに。。。

# というわけで

[terraform-jp.slack.com](https://t.co/WWWOQFs9i7)は、今のところHashiCorpさんとは直接関係ありませんが、誰でも入れるオープンなコミュニティとして細々と知見を共有していくべく活動していきます。

terraformerな皆様の参加をお待ちしています。


# 蛇足

terraform 以外の知見もたまる素敵コミュニティと呼ばれているので、slackのこんな些細なネタでも誰かの役に立てばと思い、作業記録的に書いてみました。
iBook Clamshell Firewire SE (466 MHz, DVD) に Ubuntu MATE 16.04 LTS 入れる

もはや、かなり厳しい状態になってしまいますが、iBook Clamshell Firewire SE (466 MHz, DVD) に Ubuntu MATE 入れるというお話。

まず、Server 版であっても、現在入手できる Ubuntu PowerPC のバージョンだと ISO イメージが 640 MB を超えているので、それを 700 MB CD-R に焼いて内臓 CD ドライブで読み込ませようとしても、かなりの高確率で読めないか途中で読み込みエラーになります。

つぎに、iBook Clamshell / Dual USB では USB ブートができないので、外付けドライブでブートするには Firewire が必要になります。

このため、iBook Clamshell の場合は実質 "Firewire SE 466 MHz" の DVD ドライブ搭載モデルでないと「インストールするのがかなり厳しい」です。

||概要|
|:--|:--|
|マシン|iBook Clamshell SE (Firewire)|
|CPU|PowerPC 750cxe 466 MHz|
|メモリ|64 MB (OnBoard) + 512 MB (PC-100)|
|内臓ディスク|PATA/IDE 2.5" HDD (4200 rpm) 10 GB|
|内臓 DVD|4x DVD-ROM|

|要件|
|:---------|
|1. インストール中にアップデートなどの取得を行う場合は、iBook の内臓 Ethernet でインターネットにつながること。|
|2. インストール DVD ディスクはあらかじめ焼いておくこと。([ubuntu-mate-16.04.1-desktop-powerpc.iso](http://cdimage.ubuntu.com/ubuntu-mate/releases/16.04/release/ubuntu-mate-16.04.1-desktop-powerpc.iso)) *1|
*1 →[Ubuntu MATE 16.04.6 LTS (Xenial Xerus)](http://cdimage.ubuntu.com/ubuntu-mate/releases/16.04/release/)

### 1. LIVE ディスク起動
[option] を押しながら電源入れてブート選択が出てからディスク入れて起動するか、手早くディスクをセットして [c] キー押しながら起動。

デスクトップにアイコンが見えてから Welcome が表示されるまで、3 分ぐらいかかります。Welcome が出る前に何か操作しても激遅いだけで大したことはできないと思われるので、おとなしく何もしないで待ちましょう。

### 2. インストール

1. "ようこそ" で日本語を選んでからインストールを開始。
2. "Ubuntu のインストール準備" で、[Ubuntu MATE のインストール中にアップデートをダウンロードする] と [グラフィックス、Wi-Fi機器、Flash、MP3やその他のメディアに必要なサードパーティーソフトウェアをインストールする] の両方のチェックを ON にするほうがいいのですが、このオプションを選んだ場合のインストール時間は 150 分越えになるかと思います。
3. "インストールの種類" で、[ディスクを削除してUbuntuをインストール] するしかないでしょう。ディスクは 10 GB しかありません。
4. "キーボードレイアウト" は、日本語 - 日本語。

### 3. インストール後のいろいろな設定
iBook Clamshell の場合は何もしなくても内臓スピーカーから音が出るので、その点はラクですね。

#### 0. 最新の状態にする
60 分越えます。

```
sudo apt update
sudo apt upgrade
```

#### 1. AirMac Classic (PCMCIA) で Wifi 接続可能にする

AirMac カードを持っている場合はそれを使えるようにしてみましょう。使えるようにするにはいろいろな方法があるみたいなのですが、だまされてはいけないのは b43-fwcutter を入れるというものです。PCMCIA の AirMac カードには Broadcom は入っていないと思います。いろいろ調べていくとわかるかと思いますが、結果的につぎのことをするのが一番確率が高いのではないかと思います。

```
sudo apt install wicd
sudo apt remove network-manager
```
その後、再起動します。

#### 2. mouseemu を入れる

iBook Clamshell の場合、トラックパッドはマウスとして認識されています。これを普通にトラックパッドとして使うには、かなり面倒な作業になる感じのようです。そこで、mouseemu を入れて右クリックをキーボードのキーに割り当てることによって、手っ取り早く不便利な状況を切り抜けるのがラクかと思います。

```
sudo apt install mouseemu
```
その後、再起動します。デフォルトで、マウスの右ボタンは [F12] に割り当たっています。

#### 3. Mozc が見つからないのであきらめて Anthy 入れる

Ubuntu 16.04 LTS の場合は、日本語入力で Fcitx + Mozc がデフォルトということなんだけど、PowerPC だとどう見ても Mozc が入ってない。定番の sudo apt install ibus-mozc やってもダメ。仕方がないので ibus + anthy を入れてみます。

```
sudo apt install ibus-anthy
```

#### 4. Firefox をカスタマイズする
とにかく動きが遅いので、カスタマイズして動作を軽くしておくほうがいいかと思います。
・起動時に空白ページを開く。
・新しいタブを空白にする。
・ホームを about:blank にする。
これだけでもかなり状況は変わるのではないかと思います。

#### 5. 最後に
300 MHz の機種では結果的にダメでした。xorg.conf どれだけいじり倒してもダメでした。ATI Rage 128 か Rage Pro LT あたりが最低要件っぽい感じですね。
Vagrant　エラーログの確認の仕方

##エラーログの確認の仕方

```
sudo tail -n 100 /var/log/httpd/error_log
```
このコマンドをvagrant上で打つとエラーログを確認できます！

***
[Thu Mar 14 11:26:50.224093 2019] [php7:emerg] [pid 4207] [client 192.168.33.10:48758] PHP Parse error:  syntax error, unexpected '"place"' (T_CONSTANT_ENCAPSED_STRING), expecting ']' in /vagrant/scraping/api/hotels.php on line 10
[Thu Mar 14 11:32:24.043945 2019] [php7:emerg] [pid 4212] [client 192.168.33.1:59081] PHP Parse error:  syntax error, unexpected '"place"' (T_CONSTANT_ENCAPSED_STRING), expecting ']' in /vagrant/scraping/api/hotels.php on line 10, referer: http://192.168.33.10/scraping/api/index.php

***
僕の場合はこのようなエラーログが出ました。

ちなみにエラー箇所としては、


自作のAPIのデータをvagrant上で、curlコマンドでGETしようとしたところ、

何も表示されず、エラーも表示されないという感じに。


```
[vagrant@localhost api]$ curl http://192.168.33.10/scraping/api/hotels.php?target_date=20190205\&place=osaka\&order=low\&list=10
```

こんな感じ↑でGETしようとした。

エラーログ確認したらすぐ解決できました〜。
RedshiftのDatabaseをcloneする

検証用に本番と同じデータが入ったRedshiftを作りたい。
個人情報とか入っていないのでそのままcopyしたい。

Databaseやuserは事前に作成しておいてください。

```
export PGPASSWORD=xxx
export PGHOST=xxx
export PGUSER=xxx
export PGPORT=xxx(defaultだと5439)

export SOURCE_DATABASE=copy元のDatabase
export DEST_DATABASE=copy先のDatabase
```

またs3を使うのでkeyの作成やbucketsも事前に準備が必要

```
export AWS_ACCESS_KEY_ID=xxx
export AWS_SECRET_ACCESS_KEY=xxx

# 作業用のs3 bucket。適当につくってください
export S3_BUCKET_NAME=xxx
# 作業ディレクトリ。ここにsrcのデータをunloadで出力して、destにcopyする
export S3_BUCKET_WORK_DIR=tmp
```

なおschemaがpublic出ない場合は適宜修正してください

### schemaのcopy

srcのtableとかを全部destにcopyします

```
pg_dump $SOURCE_DATABASE -c -n public -s -f dest.pgsql
psql $DEST_DATABASE -f dest.pgsql
rm dest.pgsql
```

### テーブル一覧の取得

```
TABLES=`
psql -A -F, -t $SOURCE_DATABASE -c"""
SELECT
  tablename
FROM 
  pg_catalog.pg_tables
WHERE
  schemaname = 'public';
"""`
```

### テーブルを一つづつcopy

```
TABLE_ARRAY=(`echo $TABLES | tr " " "\n"`)
for table in "${TABLE_ARRAY[@]}"
do
  echo $table

  psql $SOURCE_DATABASE -c"""
  unload ('select * from $table')
  to 's3://$S3_BUCKET_NAME/$S3_BUCKET_WORK_DIR/${table}_'
  credentials 'aws_access_key_id=${AWS_ACCESS_KEY_ID};aws_secret_access_key=${AWS_SECRET_ACCESS_KEY}';
  """

  psql $DEST_DATABASE -c"""
  COPY ${table} FROM 's3://$S3_BUCKET_NAME/$S3_BUCKET_WORK_DIR/'
  credentials 'aws_access_key_id=${AWS_ACCESS_KEY_ID};aws_secret_access_key=${AWS_SECRET_ACCESS_KEY}';
  """

  s3cmd del s3://$S3_BUCKET_NAME/$S3_BUCKET_WORK_DIR/ --recursive
done
```

### まとめ

```
export PGPASSWORD=xxx
export PGHOST=xxx
export PGUSER=xxx
export PGPORT=xxx

export SOURCE_DATABASE=xxx
export DEST_DATABASE=xxx

export AWS_ACCESS_KEY_ID=xxx
export AWS_SECRET_ACCESS_KEY=xxx

export S3_BUCKET_NAME=xxx
export S3_BUCKET_WORK_DIR=xxx

# COPY SCHEMA
pg_dump $SOURCE_DATABASE -c -n public -s -f dest.pgsql
psql $DEST_DATABASE -f dest.pgsql
rm dest.pgsql

TABLES=`
psql -A -F, -t $SOURCE_DATABASE -c"""
SELECT
  tablename
FROM 
  pg_catalog.pg_tables
WHERE
  schemaname = 'public';
"""`

TABLE_ARRAY=(`echo $TABLES | tr " " "\n"`)
for table in "${TABLE_ARRAY[@]}"
do
  echo $table

  psql $SOURCE_DATABASE -c"""
  unload ('select * from $table')
  to 's3://$S3_BUCKET_NAME/$S3_BUCKET_WORK_DIR/${table}_'
  credentials 'aws_access_key_id=${AWS_ACCESS_KEY_ID};aws_secret_access_key=${AWS_SECRET_ACCESS_KEY}';
  """

  psql $DEST_DATABASE -c"""
  COPY ${table} FROM 's3://$S3_BUCKET_NAME/$S3_BUCKET_WORK_DIR/'
  credentials 'aws_access_key_id=${AWS_ACCESS_KEY_ID};aws_secret_access_key=${AWS_SECRET_ACCESS_KEY}';
  """

  s3cmd del s3://$S3_BUCKET_NAME/$S3_BUCKET_WORK_DIR/ --recursive
done
```
バッククオートの出し方 for mac

備忘録として。


バッククオート「`」の出し方は

**シフト➕＠マーク**


qiitaで記事書くなら、バッククオートを使ったソースコード表示したいよね。

例：

```php:index.php

<?php 

echo "Hllo World";

?>
```
Pythonにおけるファイルディスクリプタ上限設定

# Pythonにおけるファイルディスクリプタ上限設定

## 問題
以下のような、Too many open filesのエラーは、現在開いているファイル数が、ファイルディスクリプタの上限に達してしまっていることが原因で発生している。


```
 pipe creation failed (24): Too many open files
E0314 13:15:11.940766000 123145865863168 ev_poll_posix.cc:981]         pollset_work: {"created":"@1552536911.940755000","description":"OS Error","errno":24,"file":"src/core/lib/iomgr/wakeup_fd_pipe.cc","file_line":41,"os_error":"Too many open files","syscall":"pipe"}
E0314 13:15:11.940766000 123146633117696 completion_queue.cc:1036]     Completion queue next failed: {"created":"@1552536911.939034000","description":"OS Error","errno":24,"file":"src/core/lib/iomgr/wakeup_fd_pipe.cc","file_line":41,"os_error":"Too many open files","syscall":"pipe"}
```

` open('file_path') `の周辺でエラーが起きているときは、きちんと`close`しましょうという対策となるが
マルチスレッドや、プロセス間通信をするときにもファイルディスクリプタを消費するので、そういうケースには上限値を設定するのも有効な手段である。

## ファイルディスクリプタの上限値設定
ファイルディスクリプタの上限には複数種類がある
- Linux/mac側のファイルディスクリプタ上限（ソフトリミット、ハードリミット）
- Pythonのファイルディスクリプタ上限（ソフトリミット、ハードリミット）

## Linux/mac側のファイルディスクリプタ上限（ソフトリミット、ハードリミット）の変更
以下のコマンドで、現在、１つのプロセスが使えるファイルディスクリプタの上限が確認できる

```
$ ulimit -n
1024
```


以下のコマンドで、現在、１つのプロセスが使えるファイルディスクリプタの上限が変更できる。
以下の例では`8192`に変更している

```
$ ulimit -n 8192
```

## Pythonのファイルディスクリプタ上限（ソフトリミット、ハードリミット）
同様にPython内でも、１つのプロセスが使える上限のファイルディスクリプタが設定されている。
以下のコマンドで、現在Pythonから使用しているファイルディスクリプタ（FD）が確認できる

```
lsof -c python
```


以下のコマンドで、プログラム中から、現在のファイルディスクリプタのソフトリミット／ハードリミットが確認できる。

▼公式解説
https://docs.python.org/ja/3/library/resource.html

```python
import resource
print(resource.getrlimit(resource.RLIMIT_NOFILE))
```

以下のコマンドで、ファイルディスクリプタのソフトリミット／ハードリミットを変更できる。

```python
import resource
resource.setrlimit(resource.RLIMIT_NOFILE, (8192, 9223372036854775807))
```
SQLエラー：SQLSTATE[42000]〜check the manual that corresponds to your MySQL 〜

**curlコマンド**で自分で作ったAPIのデータを取得しようとしたところ次のようなエラーがでて落ち込む。

```
"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INNER JOIN price AS p ON h.id = p.hotel_id
WHERE
  p.target_date = '20190205'
  ' at line 9"
```

ただ読んでみると、意外と簡単に解決できそうで要は
「オメ--SQLの書き方間違ってんだよ！」

ということで調べてみると

```
$sql = "
SELECT
  p.target_date,
  h.name,
  h.area,
  p.min_price,
  h.link
FROM
  hotel AS h
  INNER JOIN price AS p ON h.id = p.hotel_id
WHERE
  p.target_date = ?
  AND h.place = ?
";
        if (!empty($condition["order"]) && ($condition["order"] == "high")) {
               $sql .= " ORDER BY p.max_price DESC ";
           } elseif (!empty($condition["order"]) && ($condition["order"] == "low")) {
               $sql .= " ORDER BY p.min_price ASC ";
           }
           if (!empty($condition["list"]) && ($condition["list"] <= 20) && (is_numeric($condition["list"]))) {
               $sql .= " LIMIT " . $condition["list"];
           } else {
               $sql .= " LIMIT 20 ";
           }
```

このSQL文の

```
$sql .= " ORDER BY p.max_price DESC ";
```

ORDERの前に空白が入っていないのが問題でした（上は修正後）

皆さんも空白忘れやカンマ忘れに気をつけましょう。
unity2018でslnが見つからなくインテリ補完されなかったのを直した

#先まとめ
VisualStudio更新するだけで治る

#症状
・unity2018にしたらVisualStudioで参照切れててunity向けインテリ補完が表示されない
・unity2018をいくらバージョンアップしても解決しない
・slnが見つからないと怒られる（そもそも生成されてない）

#修正方法
[Unity 2018とVisual Studio2017でインテリセンスが起動しなかったり、slnファイルを作れなかった時の対処](https://ookumaneko.wordpress.com/2018/06/26/unity-2018%E3%81%A8visual-studio2017%E3%81%A7%E3%82%A4%E3%83%B3%E3%83%86%E3%83%AA%E3%82%BB%E3%83%B3%E3%82%B9%E3%81%8C%E8%B5%B7%E5%8B%95%E3%81%97%E3%81%AA%E3%81%8B%E3%81%A3%E3%81%9F%E3%82%8A%E3%80%81sl/)
こちら参考にVSの方を更新しただけ
条件で一番多い配列を取り出す。

配列の中から一番多いを取り出す。

```ruby:0,1,2で一番多い配列は？
m = [[0, 0, 0, 0], [1, 1, 12, 2], [4, 5, 6, 4, 3], [2]]
m.max_by{|i|i.count(0)} => [0, 0, 0, 0]
m.max_by{|i|i.count(1)} => [1, 1, 12, 2]
m.max_by{|i|i.count(2)} => [1, 1, 12, 2]
```
数が同じ場合は、先頭の配列が呼び出される。

```ruby
m = [[0, 0, 0, 0], [1, 1, 12, 2], [4, 5, 6, 4, 3], [2]]
m.max_by{|i|i.size} => [4, 5, 6, 4, 3]

a=["abc","abcd","abcde"]
a.max_by{|i|i.size} => "abcde"
```
配列や文字列の長さも取り出せる。
Node.jsの環境構築に疲れた。Node.jsだけ切り出して楽したい

# Docker再インストールしてイメージを作り直したらNode.jsがアップデートされていた
Node.jsの環境構築面倒なのでもうイメージを使用して楽する

## docker-compose.yml
```yml
version: '3'
services: 
  nginx:
    ...
  php-fpm:
    ...
  mysql:
    ...
  node:
    image: node:8.15.1-alpine #8が使いたいので8を指定
    user: node
    working_dir: /home/node/app
    volumes:
      - ./:/home/node/app #package.jsonがあるディレクトリをmountすること
```
あとは

```
docker-compose run node npm install
docker-compose run node npm run dev
```
でおけ。
2019年参加予定の海外技術系カンファレンス(updated 2019.3.15)

2019年チームのメンバーが仕事でまたは個人で参加する予定の海外技術系カンファレンスをまとめました。メッセージング、Pythonにフォーカスしています。

### [M3AAWG 45th General Meeting](https://www.m3aawg.org/)
- 日時	2019.2.18(Mon) - 21(Thu)
- 会場	Fairmont San Francisco, San Francisco, California, United States
- 参加費  $400
- [https://www.m3aawg.org/](https://www.m3aawg.org/)

### [Apricot 2019](https://2019.apricot.net/)
- 日時 2019.2.23(Sat) - 28(Thu)
- 会場 Daejeon Convention Center, Daejeon, South Korea
- 参加費 $150 ~ 500 (Early Bird, APNIC memeberの割引あり）
- [https://2019.apricot.net/](https://2019.apricot.net/)

### [M3AAWG 46th General Meeting](https://www.m3aawg.org/upcoming-meetings)
- 日時 2019.6.3(Mon) - 6(Thu)
- 会場 Corinthia Hotel, Budapest, Hungary
- 参加費 未定
- [https://www.m3aawg.org](https://www.m3aawg.org)

### [Python Conference Korea 2019](https://www.pycon.kr/)
- 日時 2019.8.15(Thu) - 18(Sun)
- 会場 COEX Grand Ballroom, Seoul, South Korea
- 参加費 未定
- [https://www.pycon.kr/](https://www.pycon.kr/)

### [M3AAWG 47th General Meeting](https://www.m3aawg.org/upcoming-meetings)
- 日時 2019.10.14(Mon) - 17(Thu)
- 会場 Fairmont The Queen Elizabeth, Montreal, Canada
- 参加費 未定
- [https://www.m3aawg.org](https://www.m3aawg.org)

### [AWS re:Invent](https://reinvent.awsevents.com/)
- 日時 2019.12.2(Mon) - 6(Fri)
- 会場 Las Vegas, Nevada, United States
- 参加費 未定
- [https://reinvent.awsevents.com/](https://reinvent.awsevents.com/)
- [※去年参加した弊社社員の参加レポート](https://www.facebook.com/QualitiaCo/posts/575708856242029)
git逆引きメモ

~~業務でのアウトプットの記録ともいう。~~追加予定あり。

アレゲなコマンドレットもありますので、意味を一旦でいいので考えてから実行ください。

## カレントディレクトリ以外のgitリポジトリを使用する

COMMAND以下は可変。tarコマンドと同様ですね。

```
git -C /path/to/repo COMMAND...
```

## Initial Commitを取得する

```
git rev-list --max-parents 0 origin/master
```

## あるリビジョンでのファイルを表示する

```
git show REVISION:FILE
```

## あるブランチのある日時における直前のコミットを取得する

BRANCHはorigin/等がついていても可。DATEは"2019-01-01 00:00:00"みたくする。+09とかがついていなければデフォルトでローカル時間になるようです。

```
git rev-list -n 1 --first-parent --before=DATE BRANCH
```

## あるファイルが追加されたコミットを取得する

```
git log --pretty=format:%H --diff-filter=A BRANCH -- FILE
```

## 日時を指定してコミットする

最後のコミット日時から前の日付を指定するテストはしてません(できなさそうですが)

```
GIT_COMMITTER_DATE=DATE git commit --date=DATE

GIT_COMMITTER_DATE=DATE sh -c 'git commit "--date=$GIT_COMMITTER_DATE"'
```

## commit dateを書き換えずにrebaseする

OTHER_BRANCHにHEADより新しいコミットが存在する場合はテストしてません

```
git rebase OTHER_BRANCH --committer-date-is-author-date
```
iPad Pro有効活用サブディスプレイ化のススメ

#iPad Proを有効活用するための施策
iPad Proだけでリモートワークをできないかと思い、会社で導入をしました。
結果はどうせiPad Pro持ち歩くならMacBookProを持ち歩くです。
なんとか、iPad Proを有効活用したい。いろいろな記事みるとiPadをサブディスプレイにする記事を参照。
早速やってみました。

#評価したアプリ
今回のポイント**お金をかけない**　（これ以上経費かけると怒られそう）

- WiDisplay Lite
- Yam Display FREE
- VNC Viewer
- Luna Display (こいつは有償)
- Duet Display（こいつも有償）

#WiDisplay Lite
AppStoreのレビューで結構酷評があります。Windowsが起動しなくなっただったりとかメモリのアクセス違反がとか、画面が真っ暗になったなど・・・（怖い）

Mac版だとなんとか使えそうなのでとりあえずやってみます。
まずはHost用のソフトをインストール
<img width="629" alt="スクリーンショット 2019-03-14 11.32.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/375988/1908feb2-78bd-7770-bafa-d5770f7fb5f3.png">

起動すると、メニューバーに真っ黒のアイコンが！（最初起動していることにまったく気づきませんでした）
<img width="331" alt="スクリーンショット 2019-03-14 11.56.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/375988/ca5915c4-fe27-eee9-6b45-a43e92786c13.png">

iPad側にアプリをいれていざ！
<img width="424" alt="スクリーンショット 2019-03-14 11.56.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/375988/ddc068cc-4743-8aee-7bfa-36df9917cb90.png">

**落ちた！！**
想像以上に動作が不安定・・・
何回かトライしたらディスプレイは共有できました。
レビューにあるように解像度が貧弱
もうあぶないのでこのアプリケーションは消しておきましょうかね・・・

#Yam Display FREE
AppStoreのレビューはなかなか良い。
ただしフリー版は７分毎に警告が出る模様。

WiDisplayと同じようにまずはホストをインストール
<img width="379" alt="スクリーンショット 2019-03-14 13.19.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/375988/e503849c-beda-0b39-be5b-31dbb966f75a.png">

iPadにアプリをいれて検証
<img width="684" alt="スクリーンショット 2019-03-14 13.21.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/375988/1f1ee37f-c356-4fe2-126a-75f81153a0ef.png">

**どーん！**
**これはいい！！**

有料版だとUSBでなくWiFiでも外部ディスプレイとしてつかえるよう。
しかも、使ってびっくりしたのがSamrtKeybordが使える。

のちにChromeリモートとかVNCとかでリモートも試してたんですが、ミラーリングの設定でこいつで操作したらほぼリモートでの操作も解決なのでは？？

あとは電源をどうやっていれるかだけが課題になってしまう。

#まとめ
**Yam Displayお買い上げですね**
**レビューでもみましたが、まさに神アプリ**
これと似たアプリ作成してみようかなぁ
cssでイラレの合成フォントみたいなことをする。

合成フォントで指示が来たので調べました。
一カ所ずつ指定するとかではなく、全角はこのフォント、数字はこのフォント、みたいなやつです。

ex.)
全角文字：ヒラギノ角ゴ Pro W3
半角文字：Lato Reguler

ヒラギノはブラウザ標準で指定可、Latoはないのでfont-faceでつくります。

```
@font-face {
  font-family: "Lato-Light";
  src: url("/fonts/Lato/Lato-Light.eot");
  src: url("/fonts/Lato/Lato-Light.ttf") format("truetype"),  
       url("/fonts/Lato/Lato-Light.woff2") format("woff2"),
       url("/fonts/Lato/Lato-Light.woff") format("woff");
  unicode-range: U+0030-0039, U+0041-007A;
}
@font-face {
  font-family: "Lato-Regular";
  src: url("/fonts/Lato/Lato-Regular.eot");
  src: url("/fonts/Lato/Lato-Regular.ttf") format("truetype"),  
       url("/fonts/Lato/Lato-Regular.woff2") format("woff2"),
       url("/fonts/Lato/Lato-Regular.woff") format("woff");
  unicode-range: U+0030-0039, U+0041-007A;
}
```

`unicode-range: U+0030-0039, U+0041-007A;`

この記述で、フォントを適応する文字を指定しています。

`U+0030-0039`が数字
`U+0041-007A`が英字

あとはfont-familyで、適応を絞ってるフォントを先に指定します。

```
body {
  font-family: "Lato-Regular", "ヒラギノ角ゴ ProN W3", "Hiragino Kaku Gothic ProN", Arial, Helvetica, sans-serif;
}
```
PHPⅡで自動化を学びました

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている[りく](https://qiita.com/rikukaikuu)です。

今回は、プログラミングが愛される理由のひとつである自動化について書き記していきます。

#ついに知った自動化
Progateさんからいただいた知識を元に、何か作ってみました。

```php:index.php
<?php require_once('data.php') ?>

<!DOCTYPE html>
<html>
<form method="post" action="confirm.php">
    <?php foreach ($menus as $menu): ?>
        <h3><?php echo $menu->getName() ?></h3>
        <input type="text" value="記入せよ" name="<?php echo $menu->getName() ?>">
    <?php endforeach ?>
  <input type="submit" value="提出する">
</form>
</html>
```

```php:data.php

<?php
require_once('menu.php');

$Profession = new Menu('職業');
$type = new Menu('属性');
$myname = new Menu('名前');
$age = new Menu('年齢');

$menus = array($Profession, $type, $myname, $age);

?>
```

```php:menu.php

<?php
class Menu {
  public $name;
  public $orderCount;

  public function __construct($name) {
    $this->name = $name;
  }

  public function getName() {
    return $this->name;
  }

  public function getOrderCount() {
    return $this->orderCount;
  }

  public function setOrderCount($orderCount) {
    $this->orderCount = $orderCount;
  }
}
?>
```

```php:confirm.php

<?php require_once('data.php') ?>

<!DOCTYPE html>
<html>
  <meta charset="utf-8">
    <h2>記入内容</h2>
    <?php foreach ($menus as $menu): ?>
      <?php
        $orderCount = $_POST[$menu->getName()];
        $menu->setOrderCount($orderCount);
      ?>
      <p>
        <?php if($orderCount=="記入せよ"){
          $orderCount="記入しろっていったでしょうが";
        }?>
        
        <?php echo $menu->getName() ?>
        ：
        <?php echo $orderCount ?>
      </p>
    <?php endforeach ?>
</html>

```
このコードは、自分の経歴みたいな物を書いて送信するものですが、そんなことはどうでもいいです。
ありがたい機能は**menu.php**にあるメソッドたちです。
いろいろありますが、中でも**__construct**は、newを用いてインスタンスを生成するときに、このメソッドが自動的に呼びだしをします。
つまり、newを持つインスタンスが生成させる度に、勝手に出てくるので、ここで言う「職業」とかを書き出してくれます。
また、index.phpにあるforeachによって、「記入せよ」とか、テキストを書くボックスの設置を1回書いただけで何回も表示してくれます。
#まとめと感想
menu.phpやdata.phpにどうするかの指示を書いて、index.phpのところに「foreach」などで型を作ったら、1から全部書かなくてもいいというのがすばらしいなと思いました。
このコードだと4つだけなので特に恩恵が得られるわけではないですが、100個とか1000個とかになると、こうやってまとめないと重くなったりするので、やはり必須であるコードです。
もし、誤りや無駄な文があれば修正するので、指摘してくれると助かります。
【Rails】$rails db:rollbackしたい時の間違えない手順

#はじめに
初心者の僕は、よくmigration周りでやらかします。
一人でやっているときは「ロールバックしちゃえ〜」「migrationファイル消しちゃえ〜」
とかやってもあまり問題ないと思いますが、
チームでやっているとそんなことは許されません・・・

なので
今回丁度勉強で作っていたサンプルで失敗したので、ロールバックの正しいやり方？を学びました。

##migration周りの注意
そもそもなぜこのあたり注意しないといけないのか？

今更気づいたので一応書いておきます。
migrationファイルを書き換えたり削除した場合、
当然次回$rake db:migrateした時にテーブル構造が変わってきます。

一人でやっている分には大して支障はないですが、
これをチームでやっている場所なんかにあげたりしてしまうと・・・ 
それが他の方の環境まで変わってしまい、

最悪「コードの辻褄が合わない！」なんてことになりかねません。

ということで、この辺のファイルがどれほど恐ろしいものか気づいたので
今後は普段から取り扱いに注意する癖をつけようと思いました。


##rollbackの手順
さて本題です。前述の通りこの辺は取り扱い注意なので、

失敗しない手順を学びました。 

現在の状況を確認する
まずはどこまでmigrateが実行されているかを確認しましょう。

$rails db:version
このコマンドで確認できます。 

```
$ rails db:version
Current version: 20190225214835
```
こんな感じで出てきます。

20190225214835まで実行されていることが分かります。 

##ロールバック
次に戻したいところまでロールバックします。

```bash:一つ前まで戻す
$ rails db:rollback
```

```bash:任意のファイルまで戻す
$ rails db:rollback STEP=○
```

現在地を含めた○個前までなかったことにしてくれます。

（つまり○+1個前のファイルまで実行された状態） 

##migrateされていないファイルを確認
念のためどのファイルが実行されていないか確認します。

```
$ rails db:abort_if_pending_migrations
You have 1 pending migrations:
20190225214835 UsersAddColumnProfile
```
20190225214835のProfileカラムが作られていないようです。 



##ファイルを修正
```
class UsersAddColumnProfile < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :profile, :text  #profileカラムを追加
  end
end

```
今回は例ですがUsersテーブルにprofileカラムを追加したかったので
`add_column`で追加します。


##migrate
修正が完了したらマイグレートを実行します。

```
$ rails db:migrate
== 20190225214835 UsersAddColumnProfile: migrating ============================
-- add_column(:users, :profile, :text)
   -> 0.0193s
== 20190225214835 UsersAddColumnProfile: migrated (0.0194s) ===================
```
これで無事修正完了です。

参考
http://song-of-life.hatenablog.com/entry/2017/11/12/234703
画面幅とユーザーエージェントで読み込む画像を変える

# 画面幅とユーザーエージェントで読み込む画像を変える


PCとスマートフォン(以下SP)ワンソースのページで、
jQueryを利用し簡単に画像の出し分けをする方法のメモになります。

:warning: 今回はタブレットの判別はせず、PCまたはSPの2種で分けています。

画面幅またはUAのいずれかで判別をする方法により、
PCブラウザのデバック機能でもチェックが行えるようにしました。

<b>:cat: 手順の概要</b>
(1) PC用の画像とSP用の画像ディレクトリを分けて格納
(2) 画像のパスを取得
(3) 画面幅とユーザーエージェント(以下UA)を取得
(4) 取得した画面幅とUAを利用して画像のパスを書き換え

##(1) PC用の画像とSP用の画像ディレクトリを分けて格納

:small_orange_diamond: <b>初めに画像を格納するディレクトリを決めておきます。</b>
今回は「imeges」ディレクトリ配下に格納します。
PC用の画像は「pc」ディレクトリ、SP用の画像は「sp」ディレクトリとしました。

閲覧環境を考慮し、デフォルトでは「sp」ディレクトリにしています。
変換の対象から外す画像は、「pc」と「sp」以外のディレクトリに格納します。

```html:
<!doctype html>
<html lang="ja">
</head>
<body>
<ul>
  <li><img src="./images/common/photo_01.jpg" alt="PCとSP共通画像"></li>
  <li><img src="./images/sp/photo_02.jpg" alt="切替画像"></li>
  <li><img src="./images/sp/photo_03.jpg" alt="切替画像"></li>
</ul>

<!-- まずjQueryを読み込む -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
 // ここに処理を書いていく
</script>
</body>
</html>
```

##(2) 画像のパスを取得

ページ内の全ての画像の数ぶんだけ処理を繰り返し、パスを取得していきます。

```javascript:
for (var i = 0; i < $('img').length; i++) {
  // i番目の画像のパスを取得
  // 使用関数：「.eq(インデックス番号の要素指定)」、「.attr('取得対象')」
  var imgPath = $('img').eq(i).attr('src');
}
```

##(3) 画面幅とUAを取得

画面の幅と、UAを取得します。

```javascript:

// 画面幅（スクロールバーを含んだ幅）を取得
// 使用関数：「.outerWidth()」
var winWidth = $(window).outerWidth();
// UAを取得
// 使用関数：「.userAgent」
var navUA = navigator.userAgent;
```

##(4) 取得したUAと画面幅を利用して画像のパスを書き換え

(2)、(3)をまとめると以下の様になります。

```javascript:
$(function () {

  // 画像のパス置換
  function imgChange(ua1, ua2){
    for (var i = 0; i < $('img').length; i++) {
      // ★1: 画像パスをスラッシュ「'/'」で分割
      // 使用関数：「.split('分割する文字')」
      var imgPath = $('img').eq(i).attr('src').split('/');
      // ★2: 画像パス内の「ua1」を、「ua2」に置換
      // 使用関数：「.replace('対象','置き換える値')」
      var pathCange = $('img').eq(i).attr('src').replace('/' + ua1 + '/', '/' + ua2 + '/');

      // もし★1で分割した画像パスの中に文字列「ua1」が見つかれば実行する
      // 使用関数：「.indexOf('検索する文字列','開始位置')」
      if (imgPath.indexOf(ua1) != -1) {    
        // 画像に対して、★2の置換を実行
        $('img').eq(i).attr('src', pathCange);
      }
    }
  }

  // 画面幅とUAを取得してimgChange()を実行
  function uaCheck() {
    var winWidth= $(window).outerWidth();
    var navUA= navigator.userAgent;

    // 画面幅が640px以下、または UAがiPhone 又は Androidスマートフォンの時
    if (winWidth<= 640 || navUA.indexOf('iPhone') > 0 || navUA.indexOf('Android') > 0 && navUA.indexOf('Mobile') > 0) {
      // 画像のパスにpcが含まれるものがあれば、spに変換する
      imgChange('pc', 'sp');
    } else {
      // それ以外の時に画像のパスにspが含まれるものがあれば、pcに変換する
      imgChange('sp', 'pc');
    }
  }
  
  // ページ読み込み時に実行
  uaCheck();

  // ウィンドウをリサイズした時にも実行
  $(window).on('resize', function () {
    uaCheck();
  });
});
```
##まとめ

画像を背景設定にしたり非表示にしたりなどの手間がないので製作時間が短縮できました。

ページ読み込み時に一瞬デフォルトの画像が読み込まれてしまう為、
ファーストビューの画像だけはCSSによる出し分けをしています。
スマホweb開発で役立つサイトメモ

見つけたら更新していきます。

# Chrome関連

### *コマンドライン API リファレンス*
Chrome Dev Toolのコンソールにて入力できるコマンド一覧
https://developers.google.com/web/tools/chrome-devtools/console/command-line-reference?hl=ja

### *DevTools Snippets*
Chrome Dev ToolのSnippetに登録しておくと便利そうなもの
https://bgrins.github.io/devtools-snippets/

# Android関連

### *Android Developer用ポータルサイト*
https://developer.android.com/

### *↑の中のDesignに関するガイド*
https://developer.android.com/design?hl=ja
Istioが作るサービスメッシュ~環境構築~

# サービスメッシュとは
サービスメッシュという用語は，マイクロサービスのネットワークが構築するアプリケーションの相互作用を表します． 
※　複数のPodが相互接続しているイメージだと解釈しています．
## サービスメッシュが抱える問題
サービスメッシュの規模が大きくなるにつれて，管理が難しくなる．それは，サービスディスカバリ[1]，負荷分散，障害回復，ログ収集などが挙げられます．
> [1]: どのサーバ上でどのようなサービス（アプリケーション）が動作しているかに加え、そのポート番号、IPアドレス、ホスト名などを見つけること

### その他にも
A/Bテスト[1]，カナリアリリース[2]，レート制限[3]など、より複雑な運用要件も挙げられる．

#### [1] A/Bテスト
ホームページの一部のデザインやページそのものを複数パターン用意し，それらを不規則に表示させ，どちらがより多くクリックされたか，より多く申し込みがあったかなどを検証する行為のこと

#### [2] カナリアリリース
- 新規プロダクトやサービスを本番環境の一部分にデプロイし，先に一部のユーザに提供することで新機能のフィードバッグをいち早く得ることで機能としての必要性を受け取ったうえで，全てのデプロイを行うという方法
- 複数のノードで構成された運用サーバの一部分のノードにのみリリースを行い、デプロイされた一部のノードにてテストを実施してから、全てのノードへのデプロイを行うといった方法

#### [3] レート制限
ここはむしろ自分が知りたい内容でもあります．
APIのリクエスト数を制限する方法

# Istioとは
これらの要件に対し，サービスメッシュ全体に関する運用管理を提供してくれます．
## Istioのメリット
既存のコードを変更することなく，サービスメッシュの管理をすることができる．
※ Podの先頭にEnvoyというプロキシをサイドカーとして配置することでメッシュサービスを管理します．
※ Podからなるサービス間通信もセキュアに行ってくれる

# Istioお試し
## Istioのリリース版をダウンロード
```shell
curl -L https://git.io/getLatestIstio | sh -
```
※ この後にパスを通しますが自分の環境だとshellがぶっ壊れました．curl後に推奨されるパスを通すと上手くいきました．

## minikubeの起動
```shell
minikube start --memory=8192 --cpus=4 --kubernetes-version=v1.10.0 \
    --extra-config=controller-manager.cluster-signing-cert-file="/var/lib/localkube/certs/ca.crt" \
    --extra-config=controller-manager.cluster-signing-key-file="/var/lib/localkube/certs/ca.key" \
    --vm-driver=`your_vm_driver_choice`
```
※ your_vm_driver_choice = virtualbox

## カスタムリソースのデプロイ
```shell
# in istio-1.0.6 directory
kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml
```

## Istioのデプロイ
```shell
# k8s定義ファイルの出力
helm template install/kubernetes/helm/istio --name istio --namespace istio-system > istio.yaml
# Namespaceの作成
kubectl create namespace istio-system
# デプロイ
kubectl apply -f istio.yaml
```

## インジェクションの確認
```shell
# サンプルアプリのデプロイ
kubectl apply -f samples/sleep/sleep.yaml
# Podの確認
kubectl get pods
# まだ，　Pod内のコンテナは一つ・・・
NAME                     READY   STATUS    RESTARTS   AGE
sleep-79cc87b6b9-cjgbk   1/1     Running   0          4m
```
※ ここで何故かminikubeだと，Podが生成されなかったため，Docker for Desctopにて，kubernetesを起動しました．

### サイドカーインジェクションを名前空間単位で有効にする
```shell
# ラベリング
kubectl label namespace default istio-injection=enabled
# 確認
kubectl get namespace -L istio-injection
```
### インジェクションが有効になっているか確認
```shell
# Podを一度消去
kubectl delete pod ポッド名
# 無事にできていそう！
NAME                     READY   STATUS    RESTARTS   AGE
sleep-79cc87b6b9-gwxz9   2/2     Running   0          38s
```

# まとめ
今回は，サービスメッシュが抱える問題とlstioのアプローチそして，lstioの環境構築を行いました．
次は，公式の例を元にlstioをガシガシ使ってみたいと思います！

# 参照
- [Istio](https://istio.io/docs/concepts/what-is-istio/)
- [A/Bテスト](https://ferret-plus.com/888)
- [カナリアリリース](https://clonos.jp/knowledge/detail14/)
- [レート制限](http://service.sakuraweb.com/fuyutiger/blog/2010/07/apiapi-rate-limit.html)
[Ruby] 整数に万億兆などの単位をつける

# 概要

n 番煎じです。[Rubyで大きい数字に対して億万などの単位をつける方法](https://qiita.com/ToshioAkaneya/items/0f4fd276a1cc1a212b54) という記事を拝見し、自分ならどう書くかを考えてみました。

例えば 1,234,567,890 を 12億3456万7890 に変換したいです。"千" は付けません。

# 方法

## コード

```rb
module ToJ
  UNITS = %w[万 億 兆 京 垓 𥝱 穣 溝 澗 正 載 極 恒河沙 阿僧祇 那由多 不可思議 無量大数].freeze

  refine Integer do
    def to_j
      sign = negative? ? '-' : ''
      splitted = abs.to_s.reverse.each_char.each_slice(4).map(&:reverse).map(&:join).map(&:to_i)
      j = splitted.zip([nil, *UNITS]).reject { |n, _| n.zero? }.reverse.join
      j.empty? ? '0' : sign + j
    end
  end
end
```

## 実行例

```rb
using ToJ

1234567890.to_j #=> "12億3456万7890"

# マイナスを再現する。
-1234567890.to_j #=> "-12億3456万7890"

# 余計な 0 は省く。
100000010000000000.to_j #=> "10京100億"

# 0 は "0"。
0.to_j #=> "0"
```

## 解説

まず、整数 n を 4 桁ずつに分割した配列にします。このとき、次の処理に備えて配列を逆順にしておきます。

```rb
n = 10023456700000890
splitted = n.abs.to_s.reverse.each_char.each_slice(4).map(&:reverse).map(&:join).map(&:to_i)
#=> [890, 0, 4567, 23, 1]

# ちなみにこんな書き方もできる。
splitted = n.abs.to_s.reverse.gsub(/\d{4}/, '\0 ').reverse.split(' ').reverse.map(&:to_i)
#=> [890, 0, 4567, 23, 1]
```

そして単位の配列と組み合わせます。

```rb
splitted.zip([nil, *UNITS])
#=> [[890, nil], [0, "万"], [4567, "億"], [23, "兆"], [1, "京"]]
```

ここで 0 の桁は省きます。

```rb
splitted.zip([nil, *UNITS]).reject { |n, _| n.zero? }
#=> [[890, nil], [4567, "億"], [23, "兆"], [1, "京"]]
```

最後に配列を結合して文字列にし、並び順を戻せば完成です :tada:

```rb
splitted.zip([nil, *UNITS]).reject { |n, _| n.zero? }.reverse.join
#=> "1京23兆4567億890"
```

なお `0` の場合は上記の結果が `""` になるので、その場合は `"0"` を返すようにします。

## 参考

* [Rubyで大きい数字に対して億万などの単位をつける方法](https://qiita.com/ToshioAkaneya/items/0f4fd276a1cc1a212b54)
  * インスパイア元の記事です :pray:
* [Refinement で追加したメソッドが irb で呼べない？](https://qiita.com/scivola/items/42c8bcb44d3b5bc04849)  
  * irb で [Refinements](https://docs.ruby-lang.org/en/trunk/syntax/refinements_rdoc.html) を使うために参考にしました :pray:
Githubに.env （SendGrid） あげちゃった。

#まとめ
![スクリーンショット 2019-03-14 12.24.54.png](https://qiita-image-store.s3.amazonaws.com/0/354233/97caa3e6-275b-50bb-6650-495eb3c586b6.png)

#Lv.1 (やべぇ 奴だ。)
![スクリーンショット 2019-03-14 12.20.43.png](https://qiita-image-store.s3.amazonaws.com/0/354233/d943ca35-7dd4-0fc7-5dee-7d058506091b.png)
SendGridだな。
→.envだな。

#Lv.2 やっちゃってるなぁ〜
```
$ git log
```
Githubにあげた時に、
いつの分のcommitで.envをあげてしまったのか

![スクリーンショット 2019-03-14 12.34.07.png](https://qiita-image-store.s3.amazonaws.com/0/354233/a79afb1f-bb2c-70a5-4d84-5993b4e3149f.png)

自分の場合ここだな。
commitの隣の黄色い所コピー（暗号？）

```
$ git reset --soft コピペした暗号
　　　　①　　②
```
①無かったことにするよ
②ファイルは消さないオプションだよ
　（コミットのみ消すよ。 便利だね。）

#Lv.3 いつも通り
```
$ git add -A
$ git commit -m"あと少し！！　ファイト！！！"
$ git push origin master
```
今回のケースだと
gitignoreファイルに
.envを記載してから
上記をやったよ。
#Lv.4 やったか？

![スクリーンショット 2019-03-14 12.48.14.png](https://qiita-image-store.s3.amazonaws.com/0/354233/720fe218-8186-228d-e8bd-3d0362e3688f.png)

commitsをクリック
![スクリーンショット 2019-03-14 12.52.42.png](https://qiita-image-store.s3.amazonaws.com/0/354233/2643d565-aefb-6915-ad26-b0f03212f34f.png)

できてる！！
（CIAの極秘ファイルみたいなのにちゃんとなってる。）
【Kotlin】Spigot プラグイン 参考リンク集

KotlinでSpigot プラグインを作るにあたって参考にしたサイト一覧です。Kotlinでの解説サイトは非常に少ないので、Javaも含めてまとめてみました。サイトは適宜追加していきます。おすすめのサイトもあれば教えてください。

## 開発環境構築・導入
Kotlin reference http://kotlinlang.org/docs/reference/
環境構築手順解説 https://qiita.com/ReyADayer/items/ca3f42dbb5b59d150f7e
IntelliJ IDEAのインストール https://pleiades.io/help/idea/install-and-set-up-product.html
gradleの設定 https://www.spigotmc.org/wiki/how-to-use-kotlin-in-your-plugins/


## 参考になるかもしれないGithubソース
KotlinPlugin（小規模） https://github.com/deanveloper/KotlinPlugin
TitleManager（中規模） https://github.com/Puharesource/TitleManager
Dynmap（大規模） https://github.com/webbukkit/dynmap

## Javaだけど見たほうが良いサイト
Spigot公式(英語) https://www.spigotmc.org/wiki/spigot-plugin-development/
Spigot API https://hub.spigotmc.org/javadocs/bukkit/overview-summary.html
bukkit公式 開発チュートリアル(英語) https://bukkit.gamepedia.com/Plugin_Tutorial
bukkit公式 開発チュートリアル(日本語訳) https://mcmodding.jp/modding/index.php/Plugin_Tutorial
Bukkitプラグインの作り方講座 http://densyakun.hateblo.jp/entry/2018/02/10/231339
Bukkitプラグイン制作講座 https://jyn.jp/bukkit-plugin-development-1/
Azure AD カスタムドメインを取得せず ADFS を構成

#概要
　[Azure AD の検証で ADFS を構成](https://docs.microsoft.com/ja-jp/azure/architecture/reference-architectures/identity/adfs)する場合、通常はカスタムドメインを取得する必要があります。これはドメイン取得の手間もあり気軽に試すことが出来ないかと思いますが、もっと手軽に ADFS を検証する方法として [tenant].onmicrosoft.com の標準ドメインのサブドメインをカスタムドメインとして利用する方法があります。

#詳細
　Azure AD は、フェデレーションに使用するドメインとして[サブドメインをサポート](https://docs.microsoft.com/ja-jp/azure/active-directory/connect/active-directory-aadconnect-multiple-domains#support-for-subdomains)しています。サブドメインの名前規則は、**[sub].[tenant].onmicrosoft.com** となります。例えば Azure AD テナント名が mycompany で、サブドメイン名を sales とした場合、**sales.mycompany.onmicrosoft.com** がサブドメイン名となります。

#手順
1. Azure ポータルで Azure Active Directory の [カスタム ドメイン名] を選択します。
2. [+カスタム ドメインの追加] にてカスタムドメイン名をサブドメイン名として入力し追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/166732/17421eec-6e5e-1ecf-8157-fe4d7ba1da9c.png)
3. 出来上がったカスタムドメイン（サブドメイン）でフェデレーションのところに、[Azure AD Connect](https://docs.microsoft.com/ja-jp/azure/active-directory/hybrid/whatis-azure-ad-connect) のダウンロード リンクが表示されているのがわかります。これによりオンプレミスで同じサブドメイン名を持つドメインコントローラとフェデレーションを組むことが可能です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/166732/1b7aa6ac-97db-0b0f-846d-d6d6f2f55120.png)
Dockerとはなにか？Dockerfileとはなにか？

# Docker とは
Dockerとは、コンテナを用いたアプリケーションの実行環境を構築/運用するためのプラットフォームです。

...と言われても僕は「なにそれ？コンテナ？聞いたことはあるけどなんだっけ...???」となったのでコンテナの説明をします。

## コンテナとは
ホストOS上に区画を作って、アプリを動作するためのライブラリなどを一つにまとめ、まるで個別のサーバのように使うことができるようにしたもの。
アプリケーションの実行に必要なモジュールをコンテナとしてまとめられるので、複数のコンテナを組み合わせるマイクロサービス型のアプリケーションと親和性が高い特徴を持っています。
[参考：コンテナ技術の基礎知識](https://thinkit.co.jp/story/2015/08/11/6285)


# Dockerの必要性
僕なりの解釈ですが、「環境」が変わってもそのアプリケーションは正常に動作するのか？という点で必要だと思います。環境といってもテスト環境やステージング環境、プロダクション環境があります。テスト環境で動作したとしても、いざそのアプリをデプロイすると動かないこともあります。

Dockerではこれらの環境をすべて「コンテナ」として管理していきます。アプリケーションに必要なすべてのファイルをコンテナとしてまとめて、このコンテナのもとになるDockerイメージをDocker Hubなどのレポジトリで共有します。これによって、Dockerをインストールしている環境であれば、上記で説明した「```テスト環境で動作したとしても、いざそのアプリをデプロイすると動かない```」というリスクは減少すると思います。そしてDocker上で動作させるコンテナの構成情報を記すのが```Dockerfile```です。

# Dockerfile とは
Docker上で動作させるコンテナの構成情報を記述するためのファイルです。

## 主な構成情報
- ベースとなるDockerのイメージ
    - OSの設定
    - ミドルウェアのインストール
- Docker上で行うコマンド
- 環境変数の設定
- Dockerコンテナ上で動作させるためのデーモン実行

※デーモン ... OSにおいて動作するプロセスで、主にバックグラウンドで動作するプロセス。
[参考：デーモン(daemon)【Wikipedia】](https://ja.wikipedia.org/wiki/%E3%83%87%E3%83%BC%E3%83%A2%E3%83%B3_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2))

Dockerfileに記述された情報をもとにして、```docker build```コマンドにてDockerのイメージを作成します。

# Dockerfileの構文
命令は大文字でも小文字でもどちらでもいいらしいです。（大文字のほうしか見ないので、大文字で記載します。）

| 命令 | 説明 |
|:-----------|:------------|
| FROM | ベースイメージの指定 |
| RUN | コマンド実行 |
| CMD | コンテナの実行コマンド |
| LABEL | ラベルの設定 |
| EXPOSE | ポートを指定 |
| ENV | 環境変数 |
| ADD | ファイル(ディレクトリ)の追加 |
| COPY | ファイルコピー |
| ENTRYPOINT | コンテナの実行コマンド |
| VOLUME | ボリュームのマウント |
| USER | ユーザの指定 |
| WORKDIR | 作業ディレクトリ |
| ARG | Dockerfile内の変数 |
| ONBUILD | ビルド時に実行される命令 |
| STOPSIGNAL | システムコールシグナルの設定 |
| HEALTHCHECK | コンテナのヘルスチェック |
| SHELL | シェルの設定 |

コメントはpythonみたいな感じで```#```を使うことができます。

```python
FROM centos:centos7 #ベースイメージの指定
```

# DockerfileからDockerイメージを作成
以下のコマンドで作成します。
```docker build -t [イメージ名]:[タグ名] Dockerfileの場所```

例：「sample」というイメージを作りたい。
```docker build -t sample:1.0 /home/docker_sample/sample```

# まとめ
ざっくりまとめました。イメージがつきやすいように図とか用意して更新していきます。
次回はDockerをインストールして、DockerfileからDockerイメージを作成する流れを紹介します。
CircleCIのChromeとchromedriver-helperのchromedriverのバージョンを揃える

### 現象
CircleCIで自動テストを動かしていたところ、以下のようなエラーでfeature specが通らなくなった

```
     Selenium::WebDriver::Error::SessionNotCreatedError:
       session not created: This version of ChromeDriver only supports Chrome version 74
         (Driver info: chromedriver=74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}),platform=Linux 4.4.0-141-generic x86_64)
```

これはCircleCIが用意しているコンテナ内にあるChromeとchromedriver-helperでインストールされるchromedriverのバージョンが違うために起こっているようだった
SSHログインを試して確認した

```
circleci@hogehoge:~$ google-chrome --version
Google Chrome 72.0.3626.121
circleci@9hogehoge:~$ ls .chromedriver-helper/
74.0.3729.6
```

### 解決策
以下の2つの方法があると思う

1. Chromeのバージョンを上げる
2. chromedriverのバージョンをchromeに合わせる

今回は2の方法を採用した

#### chromedriverのバージョンをChromeに合わせる
やっていることは
- Chromeのバージョンを取得
- 対応するchromedriverのバージョンを問い合わせる
- chromedriver-helper経由でchromedriverのバージョンを変える

```
      # Align chrome-driver's version installed by chromedriver-helper
      - run:
          name: Update ChromeDriver Version
          command: |
            CHROME_VERSION=$(google-chrome --version | sed -r 's/[^0-9]+([0-9]+\.[0-9]+\.[0-9]+).*/\1/g')
            CHROMEDRIVER_VERSION=$(curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE_$CHROME_VERSION)
            bundle exec chromedriver-update $CHROMEDRIVER_VERSION
```

#### webdrierを使用する(※追記)

chromedriver-helperがdeprecatedになったのでwebdriversを使わなければいけない
その場合は以下のように書き換えれば良い

```
bundle exec rake webdrivers:chromedriver:update
```

参考:
[Version selection with LATEST_RELEASE is deprecated #79](https://github.com/flavorjones/chromedriver-helper/issues/79#issuecomment-472367092)

#### chromeのバージョンを上げる
下記URLが参考になると思う。
[Circle CIでHeadless Chrome 解決編](https://blog.piyo.tech/posts/2018-05-09-chrome-on-circleci/)
[CircleCIのChromeを最新版に](https://ryotah.hatenablog.com/entry/2017/01/16/214215)
【AWS】Use Origin Cache Headersの設定をしてcache-controlしてるのにキャッシュされない【CloudFront】

# Last-ModifiedをHeaderに設定しよう

どうやらLast-Modifiedの日付からcachecontrolで設定した時間までという計算式になっているみたいです。

```:PHP
Header("Last-Modified: D, d M Y h:i:s e");
#format部分はdatetimeとかでちゃんと変換してください
```

クラウドフロントプロからすると常識？なんですかね。
割と調べてもまったく出てこなくて
nginxとかapatchとかの設定何度も見直したり、変な所でcache-control設定してないかとかめっちゃ調べた。


[cachecontrolが設定しているのに反映されない](https://qiita.com/noob1234/items/a91576b660dcc923d1da)

# それでも反映されない
pagespeed.conf
が存在している場合はこいつが邪魔しています。問題ないのであればファイル名変更してnginxを再起動すれば反映されるはずです。
Android RecyclerView.AdapterのonBindViewHolderでpositionが0で返ってきてしまう

# 概要

RecyclerView.Adapterでlistとbindして、bindしたデータに更新があった際にUIも更新する。という仕様の実装をしているとき ※1
listの0番目のデータが更新されたときには0番目が正しく更新されるが、1番目や2番目を更新した際も0番目が更新されてしまう。という事象が起きてしまった。

その原因と対処法を以下に示す。

※1.例えば、メールの一覧を表示して、一覧の中のセルに含まれるお気に入りボタンを押下した際、UIでお気に入りボタンの色を変える、など

# 原因

原因はlistのデータ更新をUIに反映するために、 `notifyDataSetChanged()` していたことだった。
本来、このメソッドはすべてのデータを更新するときや、RecyclerViewを初めて表示する際に使うが、listに含まれる複数件のうちの1件のUIの更新のときに呼び出すと、更新したデータの位置に問わず、onBindViewHolderにてpositionが0で返ってくるようだった。

# 対処法

1件のデータの更新の際は、 `notifyItemChanged(int position)` によって行う。
こうすることで適切なpositionが更新される

# 参考記事

以下の素晴らしい記事に助けられました。ありがとうございます！

[RecyclerView.Adapterのnotify系メソッド 〜 notifyDataSetChangedで…いいの？](https://qiita.com/sutchan/items/e7d68a208f71b3b95f8f)

# 備考

UIのスクショとか貼ったほうが親切と思いつつ、業務で触っているときに気づいたので、スクショなどなしです。
不親切ですみません。
同じ事象で困った方が、日本語で検索した際に多少でも助けになれば幸いです。
ParallelsでopenSUSE

#openSUSEを入れようと思った理由
オープンソースカンファレンスで知って、面白そうだったから


#記事を書こうと思った理由
opensuseをParallelsに入れようと思ったら、日本語記事がなかった。
他にも入れようとして、わからない人の助けになりたいと思ったから。


#実行環境
自分の環境は下記のようになっています。

- MacBook Pro 13-inch 2017年モデル
- macOS Mojave ver 10.14.3
- Parallels  14 for Mac ver 14.1.2
- openSUSE Tumbleweed 20190219


#Parallelsのインストール

下記サイトにアクセスして、インストール。
[Parallels desktop-lite](https://itunes.apple.com/jp/app/parallels-desktop-lite/id1085114709?mt=12)

#openSUSEのインストール

下記サイトにアクセスすると、TumbleweedとLeapがあるがどっちでもいい。
[openSUSE](https://software.opensuse.org)

#Parallelsの準備

Parallelsのインストールが終わったら、空の仮想マシンを作っていく。
手順は
1.右上の+ボタンをクリック
2.DVD/イメージファイルからをクリック
3.左下のソースなしで続行をクリック
4.OSを選ぶ画面でopenSUSE Linuxではなく、Debian/GNU Linuxを選択する
こうしていくと、空の仮想マシンの作成でき、自動で起動してisoファイルを探して、インストールまでしてくれる。

#最後に

なんでopenSUSEを選んで作成できないかはわからないけど
Macで仮想環境下でopenSUSEを使いたい人は、このやり方ならきっと
環境構築ができるからやってみてほしい。