OmniAICreator/Qiita-1.07M huggingface dataset:
CentOS7でKVM(仮想環境)を構築⑤ 仮想マシンのクローン作成

KVMも簡単に仮想マシンのクローンが作成できます。

<br>クローンする仮想マシンをシャットダウンします。

```console:
# virsh shutdown vm1
Domain vm1 is being shutdown

# virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     vm1                            shut off
```

<br>``--auto-clone``を指定すると、デフォルトパス``/var/lib/libvirt/images/``に``-clone``という名前で保存されます。

```console:
# virt-clone --original vm1 --name vm2 --auto-clone
Allocating 'vm1-2-clone.qcow2'                                                             |  30 GB  00:00:00

Clone 'vm2' created successfully.

# ll
total 2781472
-rw-------. 1 root root  1414660096 May 12 20:40 vm1-2-clone.qcow2
-rw-------. 1 root root 32217432064 May 12 20:34 vm1-2.qcow2

# virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     vm1                            shut off
 -     vm2                            shut off
```

<br>サイズを確認すると、Thinで作成されるようです。Thickのオプションらしき``--nonsparse``をしても結果は変わりませんでした。謎。


<br>Macアドレスはデフォルトでランダム書き換えするもよう。

>Fixed MAC address for the guest; If this parameter is omitted, or the value "RANDOM" is specified a suitable address will be randomly generated. Addresses are applied sequentially to the networks as they are listed in the original guest XML.

```console:
# virsh dumpxml vm1 | grep -i "mac address"
      <mac address='52:54:00:3c:53:c1'/>
# virsh dumpxml vm2 | grep -i "mac address"
      <mac address='52:54:00:e9:d3:c0'/>
```
これは便利！1つのコマンドでHaml変換できる【Ruby on Rails】

#目次

+ gemを追記する(Hamlを導入する)
+ html.erbファイルを一括で変換する


##gemを追記する(Hamlを導入する)

```:Gemfile
gem 'haml-rails'
gem 'erb2haml'
```
※(注意点)テスト環境と開発環境以外に追記する

```:ターミナル
$ bundle install
```
gemを記述したらこのプロセスを忘れてはいけませんでしたね！
##html.erbファイルを一括で変換する

```
$ rake haml:replace_erbs
```
この処理が終わり、html.erbファイルが下記のようにHaml変換されていれば成功です。

```
!!!
%html
  %head
    %meta{:content => "text/html; charset=UTF-8", "http-equiv" => "Content-Type"}/
    %title ChatSpace
    = csrf_meta_tags
    = stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload'
    = javascript_include_tag 'application', 'data-turbolinks-track': 'reload'
  %body
    = yield
```
##END
【視聴メモ】What’s New with Chrome and the Web (Google I/O ’19)

この記事は Google I/O '19 のセッションの視聴メモです。
想定読者は自分なので正確性や網羅率には問題があるかもしれません。

---

## Reference

https://www.youtube.com/watch?v=rUUazNIZW7I&list=PLNYkxOF6rcIATmAmz7HcCzongGvQEtx8i

Speaker(s): Ben Galbraith, Dion Almaer, and Dana Ritter

## Abstract

このセッションではGoogleのWeb Platformに関するビジョンを学べます。

## Contents

まずは昔話から

* Webページは描画が始まるまで6秒かかっていた
* 描画が始まってからユーザーの入力を受け付けるまで9秒かかっていた

### Performance Budgets

* Pinterest と Uniqlo Canada の事例
* Lighthouse に `budget.json` を指定してあげることでPerfomance Budgetsのレポートを取得できるようになった
    * CI等で定期的に観測すると良いとのこと
    * https://developers.google.com/web/tools/lighthouse/audits/budgets

### Search Console

* Chrome UX Report の結果からインサイトを得れるようになった
* 具体的に何ができるようになったんだろう…

### Firebase - Performance Monitoring

* Real User のメトリクスが見れます

### Paint holding

* 画面遷移時に何も表示されない画面が表示されるときがある
* そういったときに遷移後の画面をバックエンドで描画してからユーザーに見せることができるようになった
  * Canaryでフラグをオンにすると実行できる

### Portals

* ページ遷移を滑らかなアニメーションで実現することができる
* 動画では4つのドメインを滑らかに移動している
    * 滑らかすぎてページを移動しているようには見えない

下図のデモでは別ドメインのサイトをPortalsを使ってオーバーレイで表示している

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3387/4fb7bd53-c264-1f74-4885-ada1fcdfba07.png)

動画がわかりやすいのでぜひ見てみてください
https://youtu.be/rUUazNIZW7I?t=712

### Web Packaging

* WebページをSigned package化してキャッシュサービスなどに置くことができる
* Canaryで試せるようになった
* Web Packaging はプライバシー安全なプリロードを実現し、Portalsはシームレスな画面遷移を実現する

### perception-toolkit

* バーコードや二次元画像を認識する認識器と認識のためのUIがセットになったライブラリ
* デモでは squoosh.app の画像を読み込んでページ遷移を行っていた

### Desktop PWA

* Google Duo / Twitter / Hulu 等で採用されていますよという話
* Proxx.app
    * 2019年のマインスイーパ
    * フィーチャーフォンでも使える

### Duplex on the Web

* 自分の読めない言語で書かれたECサイトでの買い物をアシスタントが手伝ってくれるというイメージ？
* 旅行中に現地のサイトでレンタカーを借りるとかのシチュエーションでは嬉しそう
* どうやってサービスに組み込めば良いのかというイメージが湧きにくかった
    * Duplex用にテストアカウントを発行する？

### Cookie Changes

* HTTPSでサーブされてないページにはクッキーを送信しないようになる

### WebAuthn

* Yahoo Japan が指紋認証によるサインインを実装したところサインインにかかる時間が37.5%も減少した

## MEMO

* Portals がここまでできるとは思わなかった
    * 現在はCanaryでしか実行できないがハンズオンがあるのでやってみよう
    * web.dev/hands-on-portals
* perception-toolkit が認識器と読み込みUIの両方を持ってるの良いですね
* Desktop PWA が Electron を置き換えるのも遠くなさそう
    * Electron 独自のアーキテクチャを勉強しなくて良いのはとても嬉しい
    * アップデートが簡単にできるのも良い
    * Slack とかすでにWeb版があるものは一瞬で置き換えられるのではないだろうか
* fugu fish

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3387/7b04da10-5708-90fe-d4a0-58725af858c8.png)
ウィンドウサイズ変更時に一度だけjQueryを実行

# 問題提起

レスポンシブデザインをつくりましたが、ウィンドウサイズを変えると、jQueryが意図せず発火したり、されなかったり……という問題が発生しました。

以下が正解の挙動です。
[![Image from Gyazo](https://i.gyazo.com/6fac043aa1f59f3010103802c4ce6471.gif)](https://gyazo.com/6fac043aa1f59f3010103802c4ce6471)

以下が問題の挙動です。
[![Image from Gyazo](https://i.gyazo.com/8955a1e6f38e68eb2b8c745613ab6e52.gif)](https://gyazo.com/8955a1e6f38e68eb2b8c745613ab6e52)

[![Image from Gyazo](https://i.gyazo.com/52ff1361f2b4be330dbe539e21f5574e.gif)](https://gyazo.com/52ff1361f2b4be330dbe539e21f5574e)


正解では、ウィンドウサイズが大きい時にはjQuery（アコーディオン）を機能させず、ウィンドウサイズが小さい時にjQuery（アコーディオン）を発火させています。

しかし問題の例では、ウィンドウサイズを変えても、初めのウィンドウサイズが適応されてしまっています。

### コードはこちらです
```javascript
if (window.matchMedia( '(max-width: 766px)' ).matches){
    $(".title").on("click", function(){
      $(this).next(".element").slideToggle(200);
    });
    $(document).on("click", ".element__parent", function(){
      $(this).next(".element__child").slideToggle(200);
    });
  };
```
ifの条件が最初のウィンドウサイズにしか適応されないのが問題でした。

つまり、最初のウィンドウサイズが766px以上ならjQueryが機能せず、766px以下ならたとえウィンドウサイズを大きくしてもjQueryが適応されてしまします。

# 解決策

### 正解コードがこちらです
```javascript
$(function(){
  var timer = false;
  $(window).resize(function() {
      if (timer !== false) {
          clearTimeout(timer);
      }
      timer = setTimeout(function() {
      location.reload();
      }, 200);
  });

  if (window.matchMedia( '(max-width: 766px)' ).matches){
    $(".title").on("click", function(){
      $(this).next(".element").slideToggle(200);
    });
    $(document).on("click", ".element__parent", function(){
      $(this).next(".element__child").slideToggle(200);
    });
  };
});
```

ウィンドウサイズを変化させるごとに画面をリロードするコードを足しました。

# コードの説明

```javascript
var timer = false;
  $(window).resize(function() {
      if (timer !== false) {
          clearTimeout(timer);
      }
      timer = setTimeout(function() {
      location.reload();
      }, 200);
  });
```

### 細かいところの説明
・resize()
 　ウィンドウサイズが変わるごとにイベントを通知
・setTimeout()
　　一定時間経過後に処理を一回だけ実行する
・clearTimeout
　　setTimeout()でセットしたタイマーを解除する
・location.reload()
　　ページをリロード（再読み込み）する

### 全体の流れ
まず変数timerをfalseに設定

ウィンドウがresizeされ続けると以下が繰り返される。
・setTimeout()でセットしたタイマーを解除する
・0.2秒後にリロード
・setTimeout()でセットしたタイマーを解除する
・0.2秒後にリロード
・setTimeout()でセットしたタイマーを解除する
・0.2秒後にリロード
・・・

resizeが止まれば最後の「0.2秒後にリロード」が残るので、結果、resize終了時にリロードが一回される。

リロードがされた時のウィンドウサイズによって　

```javascript
if (window.matchMedia( '(max-width: 766px)' ).matches){
    $(".title").on("click", function(){
      $(this).next(".element").slideToggle(200);
    });
    $(document).on("click", ".element__parent", function(){
      $(this).next(".element__child").slideToggle(200);
    });
  };
```

の実行が決まるので、結果、ウィンドウサイズを変えたところでjQueryを適応するか否かを判断される。

# まとめ

ややこしい話になりましたが、要は


```javascript
var timer = false;
  $(window).resize(function() {
      if (timer !== false) {
          clearTimeout(timer);
      }
      timer = setTimeout(function() {
      location.reload();
      }, 200);
  });
```
のコードを入れれば、resize終了時に画面が一度だけリロードされるようになります。
Linuxのファイル権限(written by begginer)

ファイル権限が問題で、タスク進まないことがよくあったので、自分でまとめます。

まず、権限の種類には、
「read」「write」「execute」がある。
それぞれが固有の番号を持っていて、


| 数字         |   モード    |権限|
|-------------|------------|----|
| 4           |  r         |読み取り|
| 2           |   w        |書き取り|
| 1           |  x         |実行|

上のようになっていて、つまり数字だけで表す時はこうなります。

| 数字         |   モード    |権限|
|-------------|------------|----|
| 7           |    rwx       |読み取り/書き取り/実行|
| 6           |   rw-        |読み取り/書き取り|
| 5           |   r-x        |読み取り/実行|
| 4           |  r--         |読み取り|
| -           |  --x         |実行|


ファイル権限を見るためのコマンド。

```
ls -l
```

すると

```
drwxr-xr-x   4 user  staff      128 May  5 21:41 vue
```
左の10文字の文字列を説明します。

1番目の文字はディレクトリかそうでないかを表します。
dならディレクトリ。-ならファイル

2-4番目は「所有者」の権限
5-7番目は「所有グループ」の権限
8-10番目は「その他」の権限

次は権限の変更の仕方です。
次のコマンドで変更できます。

```
chmod 権限の数字　対象ファイル/ディレクトリ
```

上のvueディレクトリの権限を変えたい場合は

```
chmod 764 vue
```

のようになります。
764が以下を表します
1番目の数字は「所有者」が７の権限を持つ。つまりrwxです。
2番目の数字は「所有グループ」が6の権限を持つ。つまりrw-です。
3番目の数字は「その他」が4の権限を持つ。つまりr--です。

こちらのブログを参考にさせていただきました。
こちらの方が、よりわかりやすいと思います。笑
[Linuxの権限確認と変更(chmod)（超初心者向け）](https://qiita.com/shisama/items/5f4c4fa768642aad9e06)
今更だけどSlackBotを作ってみた

作ったツールは、PythonのツールでSlackで単純な受け答えするツール。
使用するPythonのライブラリは、「slackbot」を使用する。

#### ライブラリの場所

https://github.com/lins05/slackbot

## Slack側の設定

### Slackの管理画面

検索から「Bots」入力

![SlackBots.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/ae2b0e89-ff5f-ea09-c31d-79912cceda81.png)

Botsの設定確認

![SlackBots2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/e0e52d7a-f61b-e658-ea00-81236b51d4ef.png)

BotsのAPIトークンをメモする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/6f5ad41d-ab6f-5522-8b13-21a333876abf.png)

### Python側の設定

ライブラリをダウンロード

```
pip install slackbot
```

以下の構造道理作成する

```
slackbot
　└── run.py               :初期起動の設定
　└── slackbot_settings.py :ここに先程の上でメモしたAPI_TOKENをセットする。
　└── plugins
    　└── __init__.py
   　 └── custom.py　　　　　:カスタマイズするファイル

```

Slackでメッセージをやりとりしてみるカスタマイズファイルを作成する。
Githubのサンプルをつかって、「Hi」とメッセージしたら「I can understand hi or HI!」をレスポンスする

```python:custom.py
@respond_to('hi', re.IGNORECASE)
def hi(message):
    message.reply('I can understand hi or HI!')
    message.react('+1')
```

Slackボットを起動するコマンド

```
python run.py
```

コマンドで起動したらSlackでボットに「hi」とメッセージを行う

![SlackMessage.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230829/050a2617-c028-278a-502c-9059cb73cf28.png)

以下にGithubに使用したファイルアップ

https://github.com/harutotanabe09/PythonSlackBot.git
Unityちゃんの頂点データを取得するだけ

# 最初に
点群データを扱う研究をしてたので，3Dキャラクターの点群データもほしいと思ってやりました．
Unityも久しぶりに使うのであまり詳しくないです．
最終的には頂点数*次元数の行列を得ます．
参考にした記事 : http://backbone-studio.com/brog-unity01/

# Unityちゃん
Asset StoreからUnityちゃんをダウンロードし，unitychan.prefabをHierarchyビューにドラッグ＆ドロップします．
unitychan.prefabの構造を眺めてみると以下のようになっています．
![Hierarchy2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332704/387aae16-5e1e-023e-47f7-35f066e2ca9f.jpeg)
mesh_rootという空オブジェクトの子オブジェクトにそれぞれのパーツが入っており，それぞれにSkinned Mesh Rendererという頂点情報が乗ったメッシュがアタッチされています．
ここから取得するとよさそうです．

# コード
以下のコードを書きます．


```PointCloud.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChildAccess : MonoBehaviour {

	public string filename = "test";
	void Start () {
		// 頂点数を数える
		int vtx_num = 0;
		foreach(Transform child in gameObject.transform){
			SkinnedMeshRenderer skin = child.GetComponent<SkinnedMeshRenderer>();
			vtx_num += skin.sharedMesh.vertices.Length;
		}
		Vector3[] vtx_posi_array = new Vector3[vtx_num];
		
		// 頂点座標を取得
		int count = 0;
		foreach(Transform child in gameObject.transform){
			SkinnedMeshRenderer skin = child.GetComponent<SkinnedMeshRenderer>();
			Mesh child_mesh = skin.sharedMesh;
			for(int i = 0; i < child_mesh.vertices.Length; i++){
				float x = child_mesh.vertices[i].x;
				float y = child_mesh.vertices[i].y;
				float z = child_mesh.vertices[i].z;
				vtx_posi_array[count] = new Vector3(x, y, z);
				count++;
			}
		}

		// csvファイルに書き込む
		try{
			filename = filename + ".csv";
			bool append = false;
			using(var sw = new System.IO.StreamWriter(@filename, append))
			{
				for(int i = 0; i < vtx_posi_array.Length; ++i){
					sw.WriteLine("{0},{1},{2}", vtx_posi_array[i].x, vtx_posi_array[i].y, vtx_posi_array[i].z);
				}
			}
		}
		catch(System.Exception e)
		{
			Debug.Log(e.Message);
		}
	}
	void Update () {
		
	}
}

```
簡単に説明すると，mesh_rootの子オブジェクトを順番に走査しつつ頂点座標を取得．座標の配列に格納して，最後csvファイルで出力します．

このファイルをmesh_rootにアタッチして実行するだけです．最終的には11407*3の行列が取得できます．

# おわりに
本当は頂点の色情報も加えて頂点数*(次元数+3色)の行列を得たかったんですが，上手くできませんでした．
なにか別の方法を試してもよさそうです．
あと他の3Dモデルもこのような構造だとこのファイル使い回せるんですがどうなんでしょう．

© UTJ/UCL
プログラミング学習記録85〜スライドショー少しだけ〜

##今日やったこと
- ドットインストール「JavaScriptでスライドショーを作ろう」を半分だけ

今日もまたやる気がなくなってしまったのですが、なんとか少しだけ進めました。

`vertical-align`で位置を調整する方法は初めてやりました。
今の所そこまで使うメリットは感じないのですが、細かい位置の調整に使えそうです。

Progateではよく使っていた`float`は、ドットインストールでは全然使われないですね。

過去にはよく使われたのかもしれないですが、今はあまりメジャーな手法では内容です。

レスポンシブ対応のことも考えると`flexbox`の方が明らかに使いやすいですね。

ということで、また明日からも少しづつ進めていこうと思います。

おわり
CentOS7 公開鍵認証によるssh接続の設定

ID/PASS認証でしかsshを使ったことがないので、鍵認証による接続を学びます。

**フロー**
&nbsp;1. サーバで秘密鍵と公開鍵を作成
&nbsp;2. クライアントに秘密鍵をコピー
&nbsp;3. 秘密鍵を使ってサーバに接続


<br>サーバで鍵を作成します。``-t``は鍵方式、``-b``が暗号強度。2048以上を指定。キーファイルとパスフレーズを聞かれますが、今回はデフォルト、ノンパスで作成。

```console:サーバ
# ssh-keygen -t rsa -b 4096

Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:gNoQTdPhsMwaUrZaglLFCuSRRj+B3PsGJ730Bjz7AJs root@vm1
The key's randomart image is:
+---[RSA 4096]----+
|++O*=...         |
|+Oo*+*.          |
|*o=+O o          |
|.=.@.B .         |
|. o @ * S        |
|   E * o         |
|    . +          |
|       .         |
|                 |
+----[SHA256]-----+
```

<br>デフォルトでは ``id_rsa``:秘密鍵 ``id_rsa.pub``:公開鍵が作成されます。

```console:サーバ
# ls -la ~/.ssh
total 8
drwx------. 2 root root   38 May 12 19:35 .
dr-xr-x---. 3 root root  147 May 12 19:35 ..
-rw-------. 1 root root 3247 May 12 19:35 id_rsa
-rw-r--r--. 1 root root  734 May 12 19:35 id_rsa.pub
```


<br>公開鍵の名前を``authorized_keys``に変更し、権限を``600``に変更します。

```console:サーバ
# mv ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys

# chmod 600  ~/.ssh/authorized_keys

# ls -la ~/.ssh
total 12
drwx------. 2 root root   61 May 12 19:36 .
dr-xr-x---. 3 root root  147 May 12 19:35 ..
-rw-------. 1 root root  734 May 12 19:35 authorized_keys
-rw-------. 1 root root 3247 May 12 19:35 id_rsa
```


<br>``sshd_config``を編集して、鍵認証によるssh接続を有効化します。有効化後はsshdを再起動。

```console:サーバ
# vim -R /etc/ssh/sshd_config
PubkeyAuthentication no

# grep -E Pubkey /etc/ssh/sshd_config
PubkeyAuthentication yes

# systemctl restart sshd.service
```

<br>以上でサーバの設定は終了。秘密鍵をクライアントにコピーします。（ファイルの中身をコピペでも可）

```console:サーバ
# scp ~/.ssh/id_rsa 192.168.100.100:/work
root@192.168.100.100's password:
id_rsa                                        100% 3247     7.3KB/s   00:00
```

<br>クライアントから接続してみます。ログインできれば成功です。

```console:クライアント
# ssh -i /work/id_rsa 192.168.100.137
Last login: Sun May 12 19:41:05 2019 from 192.168.100.100
[root@vm1 ~]#
```

<br>パスワードによるssh接続を無効化する場合は、サーバの``PasswordAuthentication``を``no``に変更します。

```console:サーバ
# grep -E Password /etc/ssh/sshd_config
PasswordAuthentication yes
```

<br>おまけ。sshで接続できない際にフィンガープリントをクリアする方法。

```
# ssh-keygen -R vm1
```
1つのファイルを分割して、任意の範囲を git add したい

Gitでソースコードを管理していて、コミット履歴をきれいに保ちたいときってありますよね。

レビューをお願いするためであったり、変更履歴を理解しやすい形で残すためであったり、理由は様々ですが、意味のある塊でコミットを管理することはチーム開発において不可欠です。

既にソースコードを書き上げてしまったとき、どうすればコミットを分割できるかを、この記事では紹介していきます。


# git add -p を使う

`-p` のオプションを付与するだけで、任意の範囲を `add` することができます。

```
$ git add -p <ファイル名>
```

すると、下図のような画面が開きます。

`hunk` = '塊' です。

`y` を入力すれば、 `+` と `-` が左端に記されている行が `stage` に登録されます。

`n` を入力すれば、何も起きません。

しかし、この塊は自動で認識されるみたいです。

そのため、より細かく `git add` したい場合は、 `e` を入力します。


# 任意の範囲を add する

先ほどの画面で、 `e` を選択すると、 `vi` エディタが立ち上がります。

左端が `+` の場合は追加されたコード、左端が `-` の場合は削除されたコード、何もない場合は変更なしを表しています。

stageに登録したい箇所には変更を加えません。

登録したくない箇所は、 `+` の場合は行をまるごと削除 (viならば `dd`)、 `-` の場合は `-` を空白 ` ` に置換します。

選択が終われば保存し、いつも通り `git commit` します。


# 既に commit したコードを分割したい

該当箇所に `rebase` をかけて、 `reset` したのちに、 `git add -p` します。

```
$ git log --oneline -3
uptod8t 最新のコミット
tosplit 分割したいコミット
1before 分割したいコミットの1つ前

# 分割したいコミットで、 `pick` を `e` に変更して保存する。
$ git rebase -i 1before
e tosplit 分割したいコミット
pick uptod8t 最新のコミット

$ git reset HEAD~
Unstaged changes after reset:
M	main.py

$ git add -p main.py
```

これで、任意の箇所をstageに登録できるようになりました。


## 最後に

勢い余って、ソースコードをガリガリ書いた後に、分割してコミットしたいと思うことがあります。

そんなとき、なかなか `git add -p` を紹介してくれる記事がなかったので、書いてみました。

もし、さらに良い方法等があれば、コメントでご指摘いただけますと幸いです。


# 参考文献
https://git-scm.com/docs/git-add

# 編集履歴
2022年1月25日，画像を削除しました．画像は新規作成予定です．
Python Seleniumでtwitterのログインからリプライするbot

#はじめに
Python Seleniumでログインから特定の投稿に対して自動リプライするbotを作りました。TwitterAPI無しでログインからリプライまで一連の動作です。
投稿のURLの取得も自動で行えば、完全に自動で返答するbotになります。
意外と日本語のドキュメント無かったのでこちらに記載しました。

※あまり頻度多いと、twitterからスパム判定食らう可能性が高いので、用法・用量を気をつけて使いましょう。
参考：[Twitterでスパムに引っかからない対策と判定されないための予備知識 | スタートアップSNS](https://startupsns.com/whats-spamaction-2627)

#環境
Python3.x
Mac OS Mojave
Google Chrome
[Chrome Chrome Web Driver](https://sites.google.com/a/chromium.org/chromedriver/home)

#コード
```python3:python3
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys

# 各種設定
# twitterアカウント
account = 'xxxxxxxxxxxx@xxxxxxxxx'
password = 'xxxxxxxx'
# 返答したい投稿のURL
tweet_url = "https://twitter.com/xxxxxxxx/status/xxxxxxxxxxxxxxxxx"
# 返答したいテキスト
reply_text = '''こんにちは〜！'''

# Twitterログイン実行する処理
def twitterlogin():
    # ログインページを開く
    driver.get('https://twitter.com/login/')
    time.sleep(3)  # 動作止める
    # accountを入力する
    element_account = driver.find_element_by_class_name("js-username-field")
    element_account.send_keys(account)
    time.sleep(3)  # 動作止める
    # パスワードを入力する
    element_pass = driver.find_element_by_class_name("js-password-field")
    element_pass.send_keys(password)
    time.sleep(3)  # 動作止める
    # ログインボタンをクリックする
    element_login = driver.find_element_by_xpath('//*[@id="page-container"]/div/div[1]/form/div[2]/button')
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
    element_login.click()
    time.sleep(3)  # 動作止める

# Tweetリプライ実行する処理
def tweetreply(URL):
    # ツイートIDを取得する
    tweetID = URL[-19:]
    driver.get(URL)
    try:
        # 投稿文を挿入
        driver.find_element_by_id("tweet-box-reply-to-" + tweetID).click()
        time.sleep(3)  # 動作止める
        driver.find_element_by_id("tweet-box-reply-to-" + tweetID).click()
        time.sleep(3)  # 動作止める
        driver.find_element_by_id("tweet-box-reply-to-" + tweetID).send_keys(reply_text)
        time.sleep(3)  # 動作止める
        driver.find_element_by_id("tweet-box-reply-to-" + tweetID).send_keys(Keys.CONTROL + "\n")
    except:
        print("Error")


# selenium起動
options=Options()
driver=webdriver.Chrome(chrome_options = options)

# Twitterログイン処理
twitterlogin()
# Tweetリプライ処理
tweetreply(tweet_url)

# seleniumを終了
driver.close()
driver.quit()
```
Bootstrapのnavbarで右寄せにしたいけど、mr-autoが効かないときの対処法

# はじめに
今回はBootstrapのnavbarについてです。

Webページにナビゲーションバーを作りたいと思い、bootstrapのnavbarを導入してみました。

しかし公式の通りにやってもうまくいかなかったので、同じく悩んでいる方がいたら参考にしてください。

# 公式のやり方じゃ適用されなかった、、、
## Bootstrapをつかったナビゲーションバーの作り方

[Bootstrap公式](https://getbootstrap.com/docs/4.1/components/navbar/)によると、
左寄せと右寄せで`ul`タグを分けて、左寄せの方の`ul`タグのクラスに`mr-auto`を適用すればいいのだそう。

```html
<div class="collapse navbar-collapse" id="XXX">
    <!-- 左寄せ -->
    <ul class="nav navbar-nav mr-auto">
      <li class="nav-item active">
        <a class="nav-link" href="#">XXX</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">XXX</a>
      </li>
    </ul>
　　<!-- 右寄せ -->
    <ul class="nav navbar-nav">
　　　　<li class="nav-item">
        <a class="nav-link" href="#">XXX</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">XXX</a>
      </li>
    </ul>
  </div>
```

Laravelの勉強を[ララ帳](https://laravel10.wordpress.com/2015/03/21/%E5%88%9D%E3%82%81%E3%81%A6%E3%81%AElaravel-5-1-26-%E3%83%8A%E3%83%93%E3%82%B2%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%A1%E3%83%8B%E3%83%A5%E3%83%BC/)でやっていて、ララ帳でもこのような紹介がされていました。

しかしながら私はこのままではすべて左寄せで表示されてしまいました。

しらべてみると、Bootstrapのバージョン等が問題でmr-autoが効かないというような記事もありました。

Bootstrap4をLaravelに導入をしてみるも左寄せのままでした。

# 解決策：`div`タグで無理やり左寄せと右寄せに分ける

```html
<div class="collapse navbar-collapse" id="XXX">
  <!-- 左寄せ -->
  <div class="navbar-left"> <!-- ここを追加（どっちでもいい） -->
    <ul class="nav navbar-nav">
      <li class="nav-item active">
        <a class="nav-link" href="#">XXX</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">XXX</a>
      </li>
    </ul>
  </div>
  <!-- 右寄せ -->
  <div class="navbar-right"> <!-- ここを追加 -->
    <ul class="nav navbar-nav">
　　　　<li class="nav-item">
        <a class="nav-link" href="#">XXX</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#">XXX</a>
      </li>
    </ul>
  </div>
</div>
```

こんな感じにdivタグのクラスに`navbar-right`を追加して、うまく右寄せが適用されました。
jQueryをつかった２段階アコーディオン

# 完成形

[![Image from Gyazo](https://i.gyazo.com/145229819fb988ed440a44cce4229c8c.gif)](https://gyazo.com/145229819fb988ed440a44cce4229c8c)

一度目のクリックによって現れた要素に、さらにjQueryをあてています。

# 完成コード

```javascript
$(".title").on("click", function(){
      $(this).next(".element").slideToggle(200);
    });
    $(document).on("click", ".element__parent", function(){
      $(this).next(".element__child").slideToggle(200);
    });
```

# コードの説明

まずtitleクラスをクリックすることによって以下が発火します。

```javascript
$(this).next(".element").slideToggle(200);
```
slideToggle(200)
　各要素の高さを操作して、slideDown/slideUpの動作を交互に行います。引数はスライドの速さです。

　よって、titleクラスをクリックすることによって、titleクラスの次の兄弟要素であるelementクラスが、slideDown/slideUpの動作を交互に行います。

この流れで２段階目の発火も同じように

```javascript
$(".element__parent").on("click", function(){
      $(this).next(".element__child").slideToggle(200);
```

としたいところですが、これだとうまくいきません。

ですので、

```javascript
$(document).on("click", ".element__parent", function(){
      $(this).next(".element__child").slideToggle(200);
```
とします。

後者の書き方であると追加したHTML要素についてもjQureyが発火します。

# 理由
```javascript
$(".element__parent").on("click", function(){
      $(this).next(".element__child").slideToggle(200);
```
```javascript
$(document).on("click", ".element__parent", function(){
      $(this).next(".element__child").slideToggle(200);
```

上記ふたつの違いはなんなのでしょうか。

　わかりやすい違いは＄（）の中身が".element__parent"であるかdocumentであるかだと思います。

　jQueryの＄（）の中の要素は最初から存在しているものでないと検知されないようです。
　ですので、element__parentクラスは最初はいなかったので検知されず、documentは最初から存在していたので検知されました。

# まとめ
最初は存在していなかったHTML要素にイベント処理をさせたい場合は、$(document).onの形にするとうまくいきます。
プログラミング言語作成 〜1日目〜

# どんな言語？
## 名前
### Jprg(Json ProgRamminG)
# どんなの？
- jsonから派生した言語
- 関数や変数の定義ができる
- コマンドラインで実行
- jsonに変換 → 実行

## 今日やること
- JSON読み込み
- 関数を定義できるようにする

## json読み込み
色々な方法で試す
結果pythonで、```json.loads```でやるようにした
# 次やること
- 関数呼び出し
- 四則演算をできるようにする。

# 追記
結局やめた
CentOS7でKVM(仮想環境)を構築④ 仮想マシン作成

<a href="https://qiita.com/okayadokari/items/b7da6d50f0efe5982a9f" target=new>CentOS7でKVM(仮想環境)を構築③ インストールイメージ作成</a> で作成したISOイメージを利用して、仮想マシンを作成します。

<br>``virt-install``コマンドで仮想マシンを作成します。

```console:
# virt-install \
--name vm1 \
--ram 4096 \
--disk size=30 \
--vcpus 2 \
--os-type linux \
--os-variant rhel7 \
--network bridge=virbr1 \
--graphics none \
--console pty,target_type=serial \
--location /work/CenOS7_6.iso \
--extra-args="console=tty0 console=ttyS0,115200n8"
```


<br> ``[!]``の各設定画面に入り、``[X]``になったことを確認して ``b`` を入力するとインストールが始まります。

```console:
Starting installer, one moment...
anaconda 21.48.22.147-1 for CentOS 7 started.
 * installation log files are stored in /tmp during the installation
 * shell is available on TTY2
 * when reporting a bug add logs from /tmp as separate text/plain attachments
08:30:39 Not asking for VNC because we don't have a network
================================================================================
================================================================================
Installation

 1) [x] Language settings                 2) [!] Time settings
        (English (United States))                (Timezone is not set.)
 3) [!] Installation source               4) [!] Software selection
        (Processing...)                          (Processing...)
 5) [!] Installation Destination          6) [x] Kdump
        (No disks selected)                      (Kdump is enabled)
 7) [ ] Network configuration             8) [!] Root password
        (Not connected)                          (Password is not set.)
 9) [!] User creation
        (No user will be created)
  Please make your choice from above ['q' to quit | 'b' to begin installation |
  'r' to refresh]:

[anaconda] 1:main* 2:shell  3:log  4:storage-lo> Switch tab: Alt+Tab | Help: F1
```

<br>``virsh``コマンドで仮想マシンの状態が確認できます。

```console:
# virsh list --all
 Id    Name                           State
----------------------------------------------------
 4     vm1                            running
```

<br>サブコマンド``console``で仮想マシンのコンソールに接続し、``Ctrl+]``でコンソールから切断できます。

```console:
# virsh console vm1
Connected to domain vm1
Escape character is ^]

CentOS Linux 7 (Core)
Kernel 3.10.0-957.el7.x86_64 on an x86_64

vm1 login:
```

<br>おまけ。仮想マシンの削除は、shutdownしてからundefineします。

```console:
# virsh shutdown vm1
Domain vm1 is being shutdown

# virsh list --all
 Id    Name                           State
----------------------------------------------------
 -     vm1                            shut off


# virsh undefine vm1 

# virsh list --all
 Id    Name                           State
----------------------------------------------------
```

<br>どうにもならなくなったら、destroyで強制削除します。

```console:
# virsh destroy vm1
Domain vm1 destroyed
```
知らないとヤバい！チーム開発で必要な【GitHub Flow】

#はじめに
最近、プログラミングスクールが増えてきましたが、チーム開発の現場で必須のGithubの使い方を学べるところはまだ少ないんではないでしょうか？
趣味で個人アプリを開発する場合は、必要ありませんが有名なWEBサービスは、ほとんどがチーム開発です。そのチーム開発に必要な開発フローについてご紹介します。
##目次

+ Githubのmasterブランチとその他ブランチ
+ ブランチをマージする
+ masterブランチは、常時デプロイできる状態にしておく

###Githubのmasterブランチとその他ブランチ
masterブランチとは、最初にコミットをするとできるブランチです。複数人でアプリを開発する際は、このmasterブランチをクローン(コピー)してそれぞれのブランチで作業します。
そうすることによって、作業を細分化することもできますし、もしコードの書き間違いがあってもmasterブランチに影響がでないのでより効率的に開発を進めることができます。
###ブランチをマージする
開発者がそれぞれのブランチで、開発ができてもその内容をmasterブランチにマージ(結合)しなければ反映されません。
###masterブランチは、常時デプロイできる状態にしておく
ここまででmasterブランチとブランチがどのようなものかだいたい理解できたかと思います。
例えば、それぞれの開発者が、masterブランチにコミットしているとします。もしその開発コードにバグやエラーがあったら稼働中のWEBサービスが止まってしまいます。
それを防ぐためにそれぞれのブランチでコードに問題がないかなど確認した上でmasterブランチにマージします。
###新たな作業をする時は、masterブランチから新しいブランチを作る
機能の追加やバグの修正ごとに新しくブランチを作成します。ここで重要なのですが、ブランチ名には「誰が見てもその作業がわかる」ようにします。
###ブランチを定期的にpush(リモートリポジトリに反映させる)する
各開発者のローカル環境で作成したブランチでは、他の開発者がどのぐらい進んでいるかわからないため定期的にリモートリポジトリにプッシュしましょう。
###プルリクエストでコミュニケーションをとる
プルリクエストは、差分を確認する機能やコードの行にコメントを入れられる機能があります。プルリクエストを使うことによって他の開発者からレビューをもらったりアドバイスをもらったりしてより効率的に開発を進めることができます。

![FireShot Capture 104 - shinpei555_pet_docter - github.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391854/e09e3376-a22c-d62d-e9c1-e004c1730870.png)
画像の【Pull requests】の部分になります。
###他の開発者が確認・レビューが終わればmasterにマージする
ブランチでの作業が完了後に、プルリクエストを通して他の開発者からレビューをもらいます。他の開発者の目を通すことによって、ミスや思い込みによるバグがmasterブランチに混ざることを防ぐことができます。もし作業内容に問題があれば修正します。
###marterにマージしたらすぐにデプロイする
masterブランチへのmergeが行われた時は，マージ直後に必ずmasterブランチの内容が正常にデプロイできるかどうかをチェックする必要があります。もしバグが混入していたとしても、バグの特定が早くなったり、git revertで該当のコミットを打ち消すなど迅速な対応が可能になります。
###おわり
Railsでアプリ開発〜1日目〜

# どんなアプリ？

* * *

### 名前 
 - schedun(スケジュン)

* * *

### 内容
  - 勉強などのスケジュールアプリ。
  - 親と子アカウントを作成し、親が出したスケジュールに対して子供が行動。
  - 親との会話も可。
 
# 今日の目標


#### 環境構築


# 様子
1. どのように環境を構築していくか
  - Docker
  - CentOS
  - Ubuntu

### ubuntu

- 参考書通りにインストール → できない！エラー発生！ → なし

### docker
- dockerのwindows版いれる→ Proじゃないのでできない → なし

### centos
- これしかないので頑張ってインストール

### 1つ目のエラー
Postgresqlを無事にインストールして、
```Rails new schedun -d postgresql```
としてみました。
そうすると、
```pgがありません```
と言われたので書いてある通りインストール → まだエラー
小1時間考えて見て、結局、sqliteにしました。

# 次にやること

- それぞれのビュー、コントローラーなどを作成
- 画面のレイアウトを作成
Kotlin Coroutinesで非同期並列処理をする

非同期な処理を並列させて、それぞれが完了するまで待ち合わせます。onClick() を実行すると処理が始まります。


## コード
並列処理の結果を使って処理を行います。

```kotlin:MainActivityViewModel.kt

class MainActivityViewModel : ViewModel(), LifecycleObserver {

    private val job = Job()
    private val scope = CoroutineScope(Dispatchers.Main + job)

    fun onClick() {
        scope.launch(Dispatchers.IO) {

            val t1 = async { task1() }
            val t2 = async { task2() }

            Timber.d("onComplete: %d", t1.await() + t2.await())
        }
    }

    private fun task1(): Int {
        Timber.d("task 1 START")
        Thread.sleep(2000)
        Timber.d("task 1 END")
        return 1
    }

    private fun task2(): Int {
        Timber.d("task 2 START")
        Thread.sleep(3000)
        Timber.d("task 2 END")
        return 2
    }

    override fun onCleared() {
        super.onCleared()
        job.cancel()
    }
```

## 実行結果

>
task 1 START
task 2 START
task 1 END
task 2 END
onComplete: 3

RxKotlin版もありますので参考にしてください。状況に応じてRxとcoroutinesを使い分けると良いでしょう。
[RxKotlinで非同期並列処理をする - Qiita](https://qiita.com/hikoalpha/items/fc56ad8a034a6828cf71)
Rustのマクロ中で識別子を生成する

[dtolnay/paste](https://github.com/dtolnay/paste)というcrateの紹介記事です。

通常、Rustではマクロ中で新たに識別子を生成することはできません。

```rust
fn f(n: usize) {
    println!("{}", n);
}

macro_rules! call_with_n {
    ( $num:expr ) => {
        fn call_with_$num() {
            f($num)
        }
    };
}

call_with_n!(1); // call_with_1を定義したい
call_with_n!(2); // call_with_2を定義したい

fn main() {
    call_with_1();
    call_with_2();
}
```

これは次のようなエラーになります

```
error: expected one of `(` or `<`, found `1`
  --> src/main.rs:7:22
   |
7  |         fn call_with_$num() {
   |                      ^^^^ expected one of `(` or `<` here
...
13 | call_with_n!(1); // call_with_1を定義したい
   | ---------------- in this macro invocation
```

ちょっとわかりにくいですが、要は`call_with_`を関数名とみなしてるわけですね。

これを可能にするのが `paste` crateです

```toml:Cargo.toml
[dependencies]
paste = "*"
```

これで上のマクロを書き換えます

```rust
macro_rules! call_with_n {
    ( $num:expr ) => {
        paste::item! {
            fn [<call_with_ $num>]() {
                f($num)
            }
        }
    };
}
```

このように`[< ... >]`の括弧でくくられた中の文字列(?)を結合して識別子にします。
正直どうやって動いてるか全く理解できてないのですが、これで当初の目的が達成できます。
しかもこれは[concat_idents!](https://doc.rust-lang.org/std/macro.concat_idents.html)と違いstableで動作します。
WSLからadb接続する際にバージョンを揃えるのが面倒じゃない？

# 経緯
* WSLからadbを使用する際に,Windows側のadbとのバージョンを揃えるのが面倒だった．
* また，Windows側かWSL側のどちらかのadbを更新してしまうと，片方も更新する手間があり，更に面倒．

# 回避策
* WSL側でWindows側のadb.exeを使う

```
adb.exe [command]
```

* 毎回adb.exe と打つのは面倒なので，aliasを追加 ( 場所は.bashrcとかお好みで)

```
alias adb='adb.exe'
```

* これでわざわざ揃えなくても，adbが使える！
* ただし，wslでadbをinstallしている場合は，Removeしておいたほうがよかです．
RxKotlinで非同期並列処理をする

非同期な処理を並列させて、それぞれが完了するまで待ち合わせます。`onClick()` を実行すると処理が始まります。

## 並列処理をただ待ち合わせる場合(戻り値不要)
mergeオペレータを使います。アイテムは何も流さずにonCompleteで処理を行います。

```kotlin:MainActivityViewModel.kt

class MainActivityViewModel : ViewModel(), LifecycleObserver {

    private val compositeDisposable = CompositeDisposable()

    fun onClick() {
        Observable.merge(task1(), task2())
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe({}, {}, { 
                Timber.d("onComplete") 
                // do something...
            })
            .addTo(compositeDisposable)
    }

    private fun task1(): Observable<Unit> {
        return Completable.fromAction {
            Timber.d("task 1 START")
            Thread.sleep(2000)
            Timber.d("task 1 END")
        }.subscribeOn(Schedulers.io()).toObservable()
    }

    private fun task2(): Observable<Unit> {
        return Completable.fromAction {
            Timber.d("task 2 START")
            Thread.sleep(3000)
            Timber.d("task 2 END")
        }.subscribeOn(Schedulers.io()).toObservable()
    }

    override fun onCleared() {
        super.onCleared()
        compositeDisposable.clear()
    }
}
```

## 実行結果

>
task 1 START
task 2 START
task 1 END
task 2 END
onComplete


## 並列処理の結果を使う場合

zipオペレータを使います。

```kotlin:MainActivityViewModel.kt
class MainActivityViewModel : ViewModel(), LifecycleObserver {

    private val compositeDisposable = CompositeDisposable()

    fun onClick() {
        Observables.zip(task1(), task2()) { t1, t2 ->  t1 + t2 }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe { 
                Timber.d("onComplete: %d", it)
                // do something...
            }
            .addTo(compositeDisposable)
    }

    private fun task1(): Observable<Int> {
        return Single.create<Int> { emitter ->
            Timber.d("task 1 START")
            Thread.sleep(2000)
            Timber.d("task 1 END")
            emitter.onSuccess(1)
        }.subscribeOn(Schedulers.io()).toObservable()
    }

    private fun task2(): Observable<Int> {
        return Single.create<Int> { emitter ->
            Timber.d("task 2 START")
            Thread.sleep(3000)
            Timber.d("task 2 END")
            emitter.onSuccess(2)
        }.subscribeOn(Schedulers.io()).toObservable()
    }

    override fun onCleared() {
        super.onCleared()
        compositeDisposable.clear()
    }
}
```

## 実行結果

>
task 1 START
task 2 START
task 1 END
task 2 END
onComplete: 3

RxKotlinでzipを使う場合は `Observable` ではなくて `Observables` を使うと `BiFunction<>` を省略することができます。

Kotlin Coroutines版もありますので参考にしてください。状況に応じてRxとcoroutinesを使い分けると良いでしょう。
[Kotlin Coroutinesで非同期並列処理をする - Qiita](https://qiita.com/hikoalpha/items/76b7f8d74dd2ef5ddb8a)
画像スライド（CSSでフェードイン）

#ポイント
画像の枚数とアニメーションにかける時間によって実装をしよう！
実装の仕方が少し変わるから気をつけよう！

```html:index.html
    <div class="main-slide">
      <img src="images/pic00.png" alt="">
      <img src="images/pic01.png" alt="">
      <img src="images/pic02.png" alt="">
    </div>
```

```css:style.css
* {
  padding: 0;
  margin: 0;
}

.main-slide {
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
}

.main-slide img {
  width: 100%;
  height: auto;
  position: absolute;
  top: 0;
  left: 0;
  opacity: 0;
  animation: slide-animation 24s linear infinite 0s;
}

.main-slide img {
  height: auto;
}

.main-slide img:nth-of-type(2){
  animation-delay: 8s;/*2枚目の開始時間*/
}

.main-slide img:nth-of-type(3){
  animation-delay: 16s;/*3枚目の開始時間*/
}

@keyframes slide-animation {
  0% {
    animation-timing-function: ease-in;/*ゆっくり表示される*/
    opacity: 0;
  }
  12% {
    animation-timing-function: ease-out;/*表示された*/
    opacity: 1;
  }
  30% {
    opacity: 1;/*＊表示期間*/
  }
  43% {
    opacity: 0;/*次の画像で消えている*/
  }
  100% {
    opacity: 0;/*表示されていない時間*/
  }
}
```

[実際の動き](https://gyazo.com/933c0dc3fe7ce00e95f185ae920d0568)
Python3でネスト化されたZipを解凍する

###2019/10/02 改良版のコードを記載
###Python3で2重ネストされたZipファイルを解凍する方法の備忘録
初投稿です。仕事でPythonを使ってデータの成型をしたいと思う機会が増えたため投稿を始めました。よろしくお願いします。

#####ZipFileモジュールで解凍するが、ネストされたZipファイルの解凍メソッドがないため、自作
なお、3重ネスト以上のZipファイルはmain.py部分を参照

#1.開発環境

- Windows10
- Python3.7.3

#2.対象Zipファイル

    work/
        zip_nesting.zip
         ├ zip1.zip
         │    └ text1.txt
         │    └ text2.txt
         ├ zip2.zip
         │    └ text3.txt
         ∟    └ text4.txt

#3.結果(展開後のworkディレクトリ)

    work/
        text1.txt
        text2.txt
        text3.txt
        text4.txt
        zip1.zip
        zip2.zip
        zip_nesting.zip

#4.コード
```python:main.py
import glob
import os
from zipfile import ZipFile

def f_GetZipFileList(arg_path , arg_files=0):
    from glob import glob
    import os

    if arg_files == 0:
        files = glob(os.path.join(arg_path , '*.zip'))
        return files
    else:
        #Calculate Diff "Extracted Zip Files" and "Exist Zip Files" 
        files = glob(os.path.join(arg_path , '*.zip'))
        files_difset = list(set(files) - set(arg_files))
        return files_difset



def f_ExtractZip(arg_path , arg_files):
    from zipfile import ZipFile

    for file in arg_files:
        with ZipFile(file) as zip:
            zip.extractall(arg_path)


dstpath = "./work"
path = "./work/**"

#zipファイルなら解凍、zip以外なら何もしない
for file in glob.glob(dstpath + "/*.zip"):
        with ZipFile(file) as zip:
                zip.extractall(dstpath)

#全てのサブフォルダを対象にzipファイルを展開する
for file in glob.glob(path + "/*.zip"):
        with ZipFile(file) as zip:
                zip.extractall(dstpath)
```

#5.参考にしたサイト
####Pythonでzipファイルを圧縮・解凍するzipfile
#####https://note.nkmk.me/python-zipfile/
Pythonでcsvファイルの内容を標準出力(sys.stdout)に出す

# 概要

ちょっとcsvファイルを確認したくなったときに標準出力(sys.stdout)に出すときのメモ

# コード

```test.csv
12345,あいうえお,abcdefg
56789,かきくけこ,hijklmn
```

```python:csv_out.py
import sys
import csv

with open("test.csv") as f:
    reader = csv.reader(f)
    writer = csv.writer(sys.stdout)
    writer.writerows(reader)
```

```出力
12345,あいうえお,abcdefg
56789,かきくけこ,hijklmn
```

# 解説?

csv.writerにsys.stdoutを渡すと出力先を標準出力にすることができる.
sys.stdoutはファイルオブジェクトなのでcsv.writerに渡すことができる.

```python
import sys
import csv
writer = csv.writer(sys.stdout)
```

また, writerows()は iterable of row objects を受け取れる.
csv.reader()で作成したreaderオブジェクトもiterable of row objectsなのでを渡すことができる.

```python
    reader = csv.reader(f)
    writer.writerows(reader)
```

# 参考
[Use Python to write CSV output to STDOUT - Stack Overflow](https://stackoverflow.com/questions/23665264/use-python-to-write-csv-output-to-stdout)
[csv --- CSV ファイルの読み書き — Python 3.7.3 ドキュメント](https://docs.python.org/ja/3/library/csv.html)
[Python3ではcsvモジュールを使わなくてもCSVを出力できる - Qiita](https://qiita.com/tag1216/items/5b0b54dc0be2eb703a4e)
[Pythonでcsvファイルに出力 - Qiita](https://qiita.com/a_t_a/items/50623aedf7e1dab3b876)
CloudFormationで作成したClowdWatch Eventでエラー

CloudFormationでCloudWatch Eventを作成し、AWSの各サービスがEventを発行したときにLambda経由で通知したいと考えた。
しかし生成したリソースがEventをキャッチした時、エラーが発生。

# 原因

**CloudFormationではAWSの組み込みイベントは利用できない。** (2019/05/12現在)

> 組み込みターゲットでのルール作成は、AWS マネジメントコンソールでのみサポートされています。
> [AWS::Events::Rule](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-events-rule.html#cfn-events-rule-targets)

# 対応
- 手作業
- serverlessを使う

## serverlessのコード

```yaml

  # CloudWatchイベントをSlackに飛ばすLambda + CloudWatchイベント
  EventToSlack:
    handler: handlers/event-to-slack.handler
    events:
      - cloudwatchEvent:
          description: "AWSヘルスでイベントが発生しました"
          event:
            source:
              - "aws.health"
      - cloudwatchEvent:
          description: "CodeBuildのビルドが失敗しました"
          event:
            source:
              - "aws.codebuild"
            detail-type:
              - "CodeBuild Build State Change"
            detail:
              build-status:
                - FAILED
      - cloudwatchEvent:
          description: "Step Functionsでエラーが発生しました"
          event:
            source:
              - "aws.states"
            detail-type:
              - "Step Functions Execution Status Change"
            detail:
              status:
                - FAILED
                - TIMED_OUT
      - cloudwatchEvent:
          description: "EC2ノードが落ちた可能性があります"
          event:
            source:
              - "aws.ec2"
            detail-type:
              - "EC2 Instance State-change Notification"
            detail:
              state:
                - pending
                - shutting-down
                - stopped
                - stopping
                - terminated
```

- 超ざっくりなLambdaのコードは[こちら](https://gist.github.com/sot528/5998ed5762c79795e89ae46623561b89)。

# エラーが発生したCloudFormationのコード

```yaml
    AWSHealthEventRule:
      Type: AWS::Events::Rule
      Properties:
        Description: "AWSヘルスでイベントが発生しました"
        EventPattern:
          source:
            - aws.health
        State: "ENABLED"
        Targets:
          - Arn: !GetAtt AlarmToSlackLambdaFunction.Arn
            Id: "AWSHealthEventRuleTarget"
```

# 所感
いかにもCloudFormationらしい現象。
Anacondaについて

機械学習や深層学習を活用する場合、Anacondaを活用される方が多いと
思います。Anacodaとは、pythonやR等が同梱されているディストリビューションです。

pythonやRのみインストールした場合、外部ライブラリ等をインストールするのは
とても手間がかかります。ライブラリ同士で依存関係もあるのでインストールするのは
至難の業ですね。

Anacondaをインストールした場合、機械学習や深層学習のライブラリもインストール
されています。もしされていない場合、condaコマンド等でインストールすることが可能であり、
依存関係も併せてインストールしてくれるので便利です。Linuxでいつyumコマンドに近いですね。

インストーラーは以下からダウンロードできます。
https://www.anaconda.com/download

基本的にAnacodaは、WindowsよりもMacの方が親和性が良く、パフォーマンスが良いため、
機械学習エンジニアやデータサイエンティスト等の方は、Anacodaを使う場合、
MacOSを使用される方が多いです。

データ分析等を活用する場合、AnacondaのJupyter Notebookを活用される方が多いと
思います。Jupyter Notebookは、ノートブック形式のためデータ分析をした結果を
保存できるのが活用される理由です。私もこのJupyter Notebookを活用してデータ分析等を
活用しています。

R言語も活用できますから便利です。

これから機械学習や深層学習を学習されたい方は、Anacondaを活用すると良いかと
思います。
GCP/GKE/GOのアーキテクチャを理解する

# はじめに
この記事は、GCPとGKEとGOを用いたマイクロサービスの開発初心者が、
個々の技術単体ではなくそれらを組み合わせたアーキテクチャを理解することを目的としています。

私自身がGCPとGKEとGOを用いたマイクロサービスの開発方法を勉強し始めている中で、
「GCPもGKEもGOも概要はなんとなく理解した。しかし合わせて考えるとまだつながっていないな」
という状態になっていました。
そこで、GCP+GKE+GOの環境を構築した上でアーキテクチャを理解しようと思います。

# 環境項築
「[Googleのクイックスタートガイド](https://cloud.google.com/kubernetes-engine/docs/quickstart?hl=ja)」に沿って環境を構築します。
GCPでGKEを有効にし、クラスタを作成してそれにノード3つ用意してGOアプリをデプロイする・・・という流れになっていますね。
特に躓いた箇所は無かったです。

# 動作確認
１．GCPのGoogle Cloud Shellで以下のコマンドを実行
　・hello-server Service を検査
　　`kubectl get service hello-server`

　　【結果】
　　　?????@ cloudshell:~ (level-datum-236008)$ kubectl get service hello-server
　　　NAME　　　TYPE　　　　　CLUSTER-IP　 **EXTERNAL-IP**　 PORT(S)　　　　 AGE
　　　hello-server　LoadBalancer　10.23.248.52　<font color="Red">12.345.678.99</font>　8080:30727/TCP　38d

２．ウェブブラウザで、「１」のEXTERNAL-IP（公開されているポートを指定した外部IPアドレス）を使用し、
　　GOアプリケーションを表示
　　`http://[EXTERNAL_IP]:8080`
　　例　http://<font color="Red">12.345.678.99</font>:8080

　　【結果】
　　　Hello, world!
　　　Version: 1.0.0
　　　Hostname: hello-server-0123456789-01234
                       
これで、コンテナ化されたGOアプリが
GKEにデプロイされたことを確認できました。

# GCP+GKE+GOのアーキテクチャ
![GCP_GKE_GO.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406684/b823716e-fa66-8abd-98ee-dc3958a95711.jpeg)
　・GCP(Google Cloud Platform) 
　　　Google がクラウド上で提供するサービス群の総称。

　・GKE(Google Kubernetes Engine)
　　　GCP上でKubernetesを簡単に使うことができるサービス。

　・Kubernetes
　　　コンテナ（アプリケーション）で構成されたサービスのデプロイやスケーリング、
　　　構成の管理をしてくれるGoogle製のオープンソース。

　・GO(GoLang)
　　　Googleが開発したオープンソースプロジェクトのプログラミング言語。　　　

　・クラスター
　　　ノードを構成しているもの。

　・ノード
　　　コンテナが動くサーバー。

　・コンテナ
　　　作成したアプリケーションを動かすもの。

# おわりに
個々の技術を組み合わせたアーキテクチャを理解することができました。
わけあっていきなりGCP+GKE+GOの組み合わせについて投稿してしまいましたので、
次回はGCPについて投稿しようと思います。
BEMとHamlでViewをマークアップ

BEMの命名規則？大体理解できたと思い、いざHamlでViewを書いてみると、、
ん？？　なんかめっちゃclass名長いんですけど！w
的な感じでおかしなことになってしまったので、備忘録として簡単にまとめておきます。

##BEMとは
Block Element Modifierの略。
classの命名規則の一種で、多くの開発者が取り入れているCSS設計。
```命名が簡単```になり、```メンテナンスが楽になる```という利点がある。
**Block** →　大きな括り（ブロック）
**Element**　→　大きな括りの中にある要素（Blockの子要素）
**Modifier**　→　BlockやElementのバージョン違い（装飾）

##BEMの命名規則
**block\_\_element--modifier**という表記が元となる。
```block　→　element```を繋ぐ際は\_\_(アンダースコア２つ)で繋ぐ。
```block__element　→　modifire```を繋ぐ際は--(ハイフン２つ)で繋ぐ。
```block　→　modifier```を繋ぐ際も同様。
```単語と単語を繋ぐ```　→　-(ハイフン１つ)で繋ぐ。mein-contentsなど
※elementは、大きな括りの中にある要素なので、必ず親要素にBlockを持つ

```index.html.haml
/ヘッダーメニューを例にすると、、
/「menu」はヘッダーメニュー全体の大きな括り（block）
/「menu__list」はヘッダーメニュー全体の中にあるメニューリスト(element)
/「menu__list--red」は赤い文字のメニューリスト(modifier)

.menu →（block）
  .menu__list　→（block__element）
    MENU
  .menu__list
    HOME
  .menu__list
    ABOUT
  .menu__list--red　→（block__element--modifier）
    MAP
```

ここで、私がハマってしまった内容を紹介します。。

##\_\_（アンダースコア）を使えるのは１回のみ

blockからelementを繋ぐのは一回のみというのがルール。
前のblockは切って、繋いでいたelementをblockとし、blockは一つだけにする。
```mein-contents__menu__list```　→NG
```menu__list```　→OK
block__element--modifierの表記の元に、
最初の親要素から馬鹿正直に全てつらつらと繋げ、classを命名するのはNG。
というかこんなことしてたらめちゃくちゃclass名長くなります。w

##まとめ
BEMの命名規則、、
最初、理解したように思えていざ書いてみると、逆にややこしくない？？とか思っていましたが、
慣れてくるとかなり便利というか、可読性が上がります。
誰が見てもわかるclass名にすることは、チームで開発を進める上でかなり大事なことだと思います。
（一人で開発を進める際にも、メンテナンスがかなり楽になると思います）
今回はHamlで実装する際を例にしてまとめましたが、
BEMはCSS設計の為のものなので、次回はCSS設計について書きたいと思います！

##参考サイト
[[Webサイト制作]BEMについての命名規則などのまとめ - Code School](https://code-schools.com/web-bem/)
[BEM(MindBEMding)によるclass命名規則の概要を学ぼう | もえちゃんと ](http://nakano-pixy.hatenadiary.jp/entry/2019/04/01/162109)
Ajax通信によってセレクトボックスを出現させる

# 概要
Ajax通信を利用し、あるアクションによってセレクトボックスを出現させます。

↓完成形
[![Image from Gyazo](https://i.gyazo.com/c1eb370bd9425fffb5ec7b414fed6591.gif)](https://gyazo.com/c1eb370bd9425fffb5ec7b414fed6591)

困ったポイントは、選択するものによってselectタグのoptionの数が違うということです。

今回でいうと、
レディース　トップス/パンツ　の２つ
メンズ　　 トップス/パンツ/バッグ/靴　の４つ

条件によって、ビューに挿入する要素の長さを変えなければいけません。

# 完成コード
　まずは完成コードがこちらです。

```javascript:category
$("#range").change(function(){
    $("#range-second").remove();
    $("#range-third").remove();
    var category = $('option:selected').val();

    function buildHTML(children){
      var option = ``
      children.forEach(function(child){
        option += `<option value="${child.id}">${child.name}</option>`
      });

      var html = `<select name="range-second" id="range-second">
                    <option value label=" "></option>
                    ${option}
                   </select>`

      return html;
    };
    
    $.ajax({
      url: '/users/1/products/new',
      type: "GET",
      data:{category: category},
      dataType: 'json'
      })
      .done(function(data){
        var html = buildHTML(data);
        $(".products_new_container__content__select__box__category").append(html);
      })
      .fail(function(){
        alert('error');
      })
  });
```

このなかで、今回のポイントとなるコードはこの部分です。

```javascript
function buildHTML(children){
      var option = ``
      children.forEach(function(child){
        option += `<option value="${child.id}">${child.name}</option>`
      });

      var html = `<select name="range-second" id="range-second">
                    <option value label=" "></option>
                    ${option}
                   </select>`

      return html;
    };
```

一行目のbuildHTML関数の引数「children」には、selectタグの選択肢が配列として格納されています。

二行目で、まず空の変数optionを宣言します。

その次でforEachメソッドを使用し、childrenに含まれた要素の数だけ変数optionの中にoptionタグを追加していきます。

あとは、必要なだけのoptionタグの入った変数optionを、ビューに挿入する変数htmlのなかに入れるだけです。

# まとめ
まず空の箱を用意して、配列の要素をeachでひたすら詰めていくというのは、Rubyでもよくやりました。
PowerShell - Windowsエクスプローラーと同じ並び順でファイルを取得したい

```powershell
Get-ChildItem "C:\test"
```

```
Mode                LastWriteTime         Length Name             
----                -------------         ------ ----
-a----       2019/05/12     16:08              4 File.txt        
-a----       2019/05/12     16:08              4 File1.txt
-a----       2019/05/12     16:08              4 File11.txt
-a----       2019/05/12     16:08              4 File2.txt
-a----       2019/05/12     16:24              0 File3.txt
```


こういうとき、エクスプローラーで名前昇順で並び替えたのと同じように、File11が最後に来てほしい。
ググった。あった。
[powershell - How to sort by file name the same way Windows Explorer does? - Stack Overflow](https://stackoverflow.com/questions/5427506/how-to-sort-by-file-name-the-same-way-windows-explorer-does)

```powershell
Get-ChildItem "C:\test" |
    Sort-Object { [regex]::Replace($_.BaseName, '\d+', { $args[0].Value.PadLeft(20) }) }
```

```
Mode                LastWriteTime         Length Name         
----                -------------         ------ ----
-a----       2019/05/12     16:08              4 File.txt
-a----       2019/05/12     16:08              4 File1.txt
-a----       2019/05/12     16:08              4 File2.txt
-a----       2019/05/12     16:24              0 File3.txt
-a----       2019/05/12     16:08              4 File11.txt
```


でけた。良さそう。
なるほど、正規表現で連続する数字を桁埋めして置き換えた結果で並び替えればいいのね。
CentOS7でKVM(仮想環境)を構築③ インストールイメージ作成

ゲストOSにインストールするためのOSを準備します。

ホストインストール用のDVDが手元にあるので、isoイメージを作成します。ddするだけです。

```console:
# dd if=/dev/sr0 of=/work/CenOS7_6.iso
8962048+0 records in
8962048+0 records out
4588568576 bytes (4.6 GB) copied, 959.569 s, 4.8 MB/s

# ll /work/
total 4481024
-rw-r--r--. 1 root root 4588568576 May 12 17:20 CenOS7_6.iso
```

<br>``/dev/cdrom``がエイリアスとして存在しています。

```console:
# ll /dev/cdrom
lrwxrwxrwx. 1 root root 3 May 12 17:01 /dev/cdrom -> sr0
```