OmniAICreator/Qiita-1.07M huggingface dataset:
【二日目】Unity でモブプログラミング[C01_ToiletPaper]   

# Unity でペアプロ
2019/05/11に開催。勉強会の参加人数が少なかったのでチームは２つ。その１チームの記録を以下に記載します。

# どんなゲームを作るのか？
トイレットペーパーを全て巻き取ったらクリアというゲームです。操作方法は下にスワイプ？フリック？要するに下に画面を擦る（以降はフリックと記載）のがメインです。

上記以外にも「牛の乳しぼり」も案に挙がっていましたが、なんやかんやで「トイレットペーパー」に決まりました。

ちなみに、前回の「B01_ColorPatter」チームと同じメンバーだったので、前回よりもイイモノを作ろうということをになりました。ちなみに前回の内容はシンプルなゲームだったモノの、若干シンプル過ぎたように思われます。そのため、今回はもうちょっとチャレンジしてみることにしました。

# 早速！素材作成に苦しむ！！

前回、他のチームであった素材難が襲い掛かります。特に今回は「トイレットペーパー」をどうやって回して紙を出していくのか、そこらへんのギミックをどうしていくのかがフワフワしていたため、素材づくりに苦労してしまいました。

正直にいうとこの時点では全然ギミックのイメージが出来てません。こういう動きをしたらソレっぽく見えるのではないかと見せ方についてイロイロ検討した結果、以下のようなカンジになりました。

![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412322/a801513e-89e8-acd6-2cd3-197d484d0676.png)


- ペーパーの切れ目を上から下に移動させれば何とか見えるかもしれない。
- トイレットペーパー本体を徐々に細くすれば減っているように見えるかもしれない。


# スワイプの処理はどうする？
下に擦るスワイプの操作も重要です。こちらは別働隊（ペアだから一人）が事前にスワイプの処理を調べ、事前に他のプロジェクトで動作検証をしてもらいました。主に素材の準備などで手間取っている時間で目処がついたようで、そのソースを取り込んでみることに。

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

public class C01_EgdeSlide : MonoBehaviour
{
    float x;
    float y;
    public float StartPos;
    public float EndPos;
    public float movement;
    
    void Update()
    {
        x = Input.mousePosition.x;
        y = Input.mousePosition.y;

        
        if (Input.GetMouseButtonDown(0))
        {
            StartPos = Camera.main.ScreenToWorldPoint(Input.mousePosition).y;
            //Debug.Log(StartPos);
        }
        if (Input.GetMouseButtonUp(0))
        {
            EndPos = Camera.main.ScreenToWorldPoint(Input.mousePosition).y;
            //Debug.Log(EndPos);
            movement = 0;
        }
        if (StartPos > EndPos)
        {
            movement = (StartPos - EndPos)*0.1f;
        }
        else if (StartPos < EndPos)
        {
            movement = 0;
        }

        // TouchPos = Camera.main.ScreenToWorldPoint(new Vector3(x, y, 10.0f));
        //TouchPos.y = Mathf.Clamp(TouchPos.y, -50f, 3.2f);
        transform.position = new Vector3(transform.position.x, transform.position.y - movement, 10.0f);//Y軸のみ動かせる
    }

}

```

# いろいろと最終調整
各チーム１人ずつのメンバーが先に帰宅することになり、いよいよペアプロも際どい状態に。ちょうど各チーム１人ずつ残ったので、チームを統合する形でペアプロを再開しました。

上記のスワイプの処理は実装済みで切れ目のオブジェクトを上下の動作と連携させました。
残すはトイレットペーパー本体を徐々に細くする処理になります。これが悩んだポイントで「スプライトで表示を切り替えていくのか」「その都度オブジェクトを生成して切り替える」か検討しているうちにどんどん内容が混濁してきます。
結果的には統合されたペアプロで相談しながら整理することで無事に解決できました。

# なんとか完成
![G1Y0rc4dd.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412322/1c0f2e33-2668-1065-5c79-a952bd4c1272.gif)

切れ目だけ流すだけでロールしているように見えるモンですね。右側のロールが回転すれば更にそれっぽく見えそうです。

# 振り返り
- やっぱり素材作成に苦しんだ
- 次回までに素材だけ準備してきてもよいかも
- このゲームの演出的にはもうちょっと凝りたいので素材を準備してリベンジ？
じゃばじゃばおぼえがき

引数入力

```java:hikisuu.java
int input = Integer.parseInt(args[0]);
```


シンプルな配列

```java:hairetsu.java
String[] num= new String[7];

		num[0]="zero";
		num[1]="one";
		num[2]="two";
		num[3]="three";
		num[4]="four";
		num[5]="five";
		num[6]="six"
```
ArrayList

```java:arraylist.java
ArrayList
ArrayList<型> リスト名 = new ArrayList<型>();

//例
ArrayList<String> strList = new ArrayList<String>();

```
for文

```java:for.java

for(int i = 0; i<7;i++){
		System.out.print(i+"は英語で");
		System.out.println(num[i]+"です。");
		}
```

拡張forループ

```java:kfor.java

for ( 型　変数名 : 式 )
  文;
}

```
ざっと目を通しておきたいbashコマンド

## はじめに
bashを勉強する上で抑えておくと楽になる数々をメモしました。
徐々に増やしていく予定です。

## 基本的な構文

### ファイル読み込み
```bash
source "./env.ini";
# . "./env.ini"でも動作はする
```

### 条件文

#### 引数の判別
```bash
if [[ $# != "1" ]]; then
  echo "引数を１つ渡して下さい";
fi;
```

#### フォルダ存在チェック
```bash
if [ ! -e "./tmp" ]; then
  echo "tmpフォルダは存在しません";
fi;
```

#### なんちゃって三項演算子
```bash
[[ $count == "0" ]] && echo "OK" || echo "NG" ;
```

#### 直前のコマンド判別
```bash
rm -rf ./tmp

# 成功時は０が返る
if [[ $? != "0"]]; then
  echo "削除に失敗しました";
fi
```

### 表示

#### 普通の表示
```bash
echo "こんにちは";
```

#### フォーマット表示
```bash
printf "%s %s \n" "1" "2";
```

「\」を挟むことでコマンドを改行し、見通しを良くすることができます。

```bash
printf "%s %s \n" \
  "[error]" "ファイルが存在しません";
```

### ファイル操作

#### 文字コード変換
```bash
iconv -f cp932 -t UTF8 nzn.csv > utf8_nzn.csv;
```

#### とあるフォルダ内ファイル一覧を取得
```bash
ls ./tmp 
```

#### とあるフォルダ内ファイル一覧取得を変数格納
```bash
file_list=$(ls ./tmp); 
```

#### とあるフォルダ内ファイルを降順にして一覧表示
```bash
ls -tr ./tmp; 
```

#### とあるフォルダ内csvファイル、更新日の絞り込みを降順にして一覧表示（lsと同じ形で）
```bash
find ./tmp -type f -mmin +5 -print0 | xargs -0 ls -tr | sed 's!^.*/!!' | grep ".*.csv"; 
```

#### CSVの１行目を取得＆表示
```bash
arr_first_line=$(sed -n "1p" nzn.csv | tr ',' '\n');
# --以降をすべて引数とみなす
set -- $arr_first_line;

id=${1};
name=${2};
price=${3};
```


### ファイル分、ループ
```bash
file_list=$(ls ./tmp); 
for file in $file_list; do
  echo $file;
done;
```

### mysqlの実行
```bash
mysql="mysql -u $USER -h ${HOST}";
eval $mysql -e "SELECT * FROM users;";
```

### trap
プロセスを強制終了した際などをトリガーに、後始末をさせるコマンド。
一時フォルダ内をバッチ後は全て消しておかなければいけないなどに便利。

```bash
trap "
rm -rf tmp/*;
" 0
```
ド・モルガンの法則で条件をリファクタリング

条件文をわかりやすく書きたいときに、ド・モルガンの法則が使えるパターンがある。

ド・モルガンは
「真と偽を入替え、論理和を論理積を入替えた論理体系」は、元の論理体系と同一視できる」という法則。

` NOT(X) OR NOT(Y) `
は
`NOT(X AND Y)`
と同じ

コードで書くと

```ruby
if !a || !b
```

は

```ruby

if !(a && b)
```
に書き換えられる。


`NOT(X) AND NOT(Y)`
は
`NOT(X OR Y)`
と同じ

コードで書くと

```ruby

if !a && !b
```

は

```ruby

!(a or b)
```
に書き換えられる。
51歳からのプログラム　備忘　リロードによる二重投稿

休みの日に、簡単なチャットアプリを作ったのだけれど、リロードによる二重投稿に嵌ったよ。制作中のアプリにも搭載する予定の機能なので、備忘必須。

二重投稿の防止
--
laravelのグローバルなsessionヘルパを使います。

・　blade.phpから、乱数をpostでcontrollerに送信し、sessionにも登録しておく。
・　controller側では、受信したpostの値と、sessionの値を比較して、両者が異なっていたら処理を中断する。

```php:sam1
<?php
//if(!(session_start()) { session_start(); }

  try{ session_start();}catch(Exception $ex){}

$token = rand();
session(['token'=>$token]);
?>

<form action="/sam2" method="post">
{{csrf_field()}}
  <input type="text" name="name">
 
  // 目印を　POSTで送信する                                     
  <input type="hidden" name="token" value="<? echo $token ?>">
</form>
```
```php:controller
public function sam2(Request $request)
{
  //if(!session_start()){ session_start(); }
  
  try{ session_start(); }catch(Exception $e){}

   // 同値判定
   // セッションの目印と、POST送信された目印が同じかどうか判定
   try
   {
       if($_POST['token'])
       {
           if($_POST['token']==session('token'))
           {
               session(['token'=>'']);

               // formされた情報に、必要な処理をする
           }
       }
    }catch(Exception $e){}
}
```

controllerのtry-catch
--

#unset処理に関して
上記ではsession(['token'=>'')として初期化しているが、グローバルヘルパではなく、グローバルセッションを使う場合、\$\_SESSION['pass']　と　\$\_POST['pass'] の同値判定をした後に、リロードや連続投稿を防止するために、\$\_SESSION（若しくは\$\_POST）をunsetするが、高速リロード、高速連続投稿の時には、unset後、すぐに同じ同値判定を行おうとして、unsetした\$\_SESSION（若しくは\$\_POST）を評価し、undefineエラーが投げつけられることがあった。これを回避するためにtryで処理したら大丈夫だった！

同値判定を関数にして風通しよくする

```php:controller
public function ReceiveForm(){
  $result = $this->sessionCheck($request);
  if( $result == "" ){ return false; }
  
  // 処理

}

function sessionCheck($request){
  try{ session_start() }catch(Exception $e){}
  try{ if( session('token') ){
           if( session('token') === $_POST['token'] ){
               $form = $request->all();
               session(['token'=>'');
               unset($form['_token']); // これはcsrf_field()のtokenを削除してる
               unset($form['token]);   // これはPOST送信されてきたtokenを削除してる
               return $form;
           }
  }catch(Exception $e){}
  $form=[];
  return $form;
}
```
これからVue.jsをはじめる方におすすめするvue-admin-template

# はじめに
最近ではフロントエンドの技術としてReactやVueといったフレームワークを利用したアプリケーション開発が盛んに行われていますね。

その中でもVue.jsは **学習コストの低さ** であったり **高パフォーマンス** をウリにしたフレームワークです。
ここでは、なぜVueなのかは一旦置いておき、とりあえずアプリを作るためにどうやったら早く習得できるのかをメインに書いていきたいと思います。

# 対象となる方々
- Vueを効率よく勉強しようとしている方
- VuexやRouterなどの周辺知識も合わせて勉強したい方
- バックエンドとの通信や認証・認可を含めた実用的なアプリケーションサンプルを求めている方
- チュートリアルはやったけど次どうしようか悩んでいる方

# 効率のよい習得方法とは
これは個人によって様々ですが、ぼくの場合は **とりあえずOSSのソースを読む** です。
感覚としてはダッシュボード系のテンプレートが以下の要素を含んでいて非常に参考になるのでおすすめです。

- ログイン・ログアウト処理
- 各コンポーネントの切り方（構成）や、処理の書き方
- 各ページでのAPI通信
- 利用しているUIライブラリの使い方
- 利用しているグラフ系ライブラリの使い方

そこから作りたいものに対して必要なことを、逆引き的に公式サイトや検索を通して勉強することが多いです。
チュートリアル規模のアプリケーションだとなかなか効果を実感できない機能とかもありますが、そこそこの規模のアプリケーションを動かしながらここを変えたらこう変わるというのを試行錯誤しながら身につけていくのもひとつのやり方だと思います。

## なぜvue-admin-templateか
やっと本題ですが、ぼくがVueを勉強しはじめたときはこちらのPanJiaChen氏が作られているOSSから入りました。
https://github.com/PanJiaChen/vue-admin-template
（起動方法はReadmeをご参照ください）

なぜこのOSSにしたかというところですが、 **盛り盛りではなくシンプルなテンプレート** と **ログイン・ログアウトの処理がちゃんと書かれている** が大きな理由です。
UIはElementUIを利用されていて、router-viewやvuexなど基本的な部分ももちろん入っていますが、APIとの通信込みで書かれているプロジェクトは少なく、カスタマイズ性が高いという意味でこちらを選びました。

（ちなみに全部盛りのプロジェクトは https://github.com/PanJiaChen/vue-element-admin で公開されています。）

学びになったポイントまとめ

- SPAプロジェクトのシンプルなテンプレート
- バックエンドのスタブAPI通信も込みで書かれているので参考になる
    - ログイン判定をちゃんとやっている
        - 未ログインならアクセストークンを取得してvuexにストアし、各ページで参照している
        - ついでにaxiosの使い方もわかる
            - interceptors便利やん
            - エラーハンドリングもちゃんとやってる
    - ログイン以外にもAPIから取得した一覧をテーブルに表示したりとかもやっている
- ルーティングの書き方や、コンポーネントの遅延読み込みのやり方がわかる
    - RouterのbeforeEach便利。ページ単位で権限制御したいときはこれを使えばいけそう、とか考えるきっかけになる
- router-viewをネストしている意味がわかる（https://router.vuejs.org/ja/guide/essentials/nested-routes.html）
    - コンテンツ部分のみに絞って更新したいから使ってるんだというのがわかる
- コンポーネントの書き方がわかる
    - 自作コンポーネントの使い方
    - ディレクティブの作り方、使い方
- ファイル構成も参考になる
- vuexでの状態管理がわかる
- ElementUIに詳しくなる（https://element.eleme.io/#/en-US）
- 体系的なアプリケーションの組み立て方が想像できる

# さいごに
今回は vue-admin-template を使っていますが、モチベーションは何でもよいと思います。
画面がきれいだからとかetc.

チュートリアル終わったけどいまいちピンと来てないなと思った方や、どう使っていけばいいか悩んでいる方はOSSのプロジェクトを眺めているのはいかがでしょうか？
ヒントはたくさんもらえると思います！
これさえ知ってればGitも怖くない(コミットするまで)

# 今回記事を書いたきっかけ
バージョン管理にGitを使っているところは多いと思うが、使ったことがない人も多いと思う。
かくいう自分も、今の現場に入るまで使ったことがなかった。
あまりにも基本的な知識なので誰も教えてくれなかったため、本も買って読んでみたが、「どれが実際に使うコマンドなのか」というのがよくわからなかった。
今回は実際に業務で使った(調べた)コマンドをまとめて、基礎知識として定着させておきたいと思う。

## そもそもGitとは
ファイルをバージョン管理するためのシステム。
履歴や作業ログなどが残るので、「誰がどういう更新をしたか」ということがわかる。

### リポジトリ
ファイルやディレクトリの状態を管理する場所。
この中にあるファイルが、バージョン管理の対象となる。
リポジトリには、「リモートリポジトリ」「ローカルリポジトリ」という種類が存在する。

#### リモートリポジトリ
専用のサーバに配置される。
ここで変更内容を管理することで、複数人で資材管理をすることが可能になる。

#### ローカルリポジトリ
自分のローカル端末に配置される。ユーザ1人が変更内容を管理する。
「ローカルリポジトリ内で個人で作業を行い、その変更内容をリモートリポジトリに反映」という流れで利用する。

ローカルリポジトリは、

- 新規リポジトリをローカルで作成する
- リモートリポジトリをローカルにコピーする

のいずれかで作成する。


## リポジトリでの作業
### コミット
ファイルやディレクトリの追加／変更をリポジトリに記録することを*コミット*という。

### ワークツリーとインデックス
実際に作業をしているディレクトリを、*ワークツリー*という。
リポジトリとワークツリーの間には、*インデックス*という場所が存在している。
リポジトリにコミットする際には、「インデックスにコミットしたいファイルを登録」してから、コミットを行う。

## 基本コマンド(コミットまで)
### 作業したファイルをインデックスに登録する(git add)
ローカルで作業したファイルは、コミットするためにインデックスに登録する。
その際にはaddコマンドを使用する。

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

# カレントディレクトリ以下のファイルを登録(.gitignoreで指定されたファイルは除く)
$ git add .

# Git管理されているファイルのうち、変更されたファイルを全て登録
$ git add -u

# -uオプションで登録されるファイルと、未追跡のファイル(新規ファイルなど)を登録
$ git add -all
```


### ワークツリーとインデックスの状態確認(git status)
インデックスに登録したファイルや、ワークツリー内で変更されたファイルを確認することができる。
コミット前にはこのコマンドで、「コミットしたいファイルに漏れがないか、余計なファイルは含まれていないか」などを確認する。

```
$ git status
```

### addしてしまったファイルを取り消したい(git reset)
間違えてaddしてしまうことはよくある。   
余計なファイルを含めてしまった場合は、resetコマンドを使う。

```
# git addしたファイルをインデックスから削除
$ git reset HEAD .

# ファイルを指定してインデックスから削除
$ git reset HEAD <ファイル名>
```

### コミットする(git commit)
ここまで準備ができたら、commitコマンドを使ってコミット。
コミットにはコメントをつけることができるので、変更内容がわかりやすいコメントをつける。
チームによってはルールもあると思うので、それは要確認。   

```
$ git commit -m “commitコメント”
```

### コミット履歴を確認する(git log)
コミットした履歴を確認するときにはlogコマンドを使う。

```
$ git log

# 各コミットで変更のあったファイル名を表示
$ git log —-name-only

# 一行表示する
$ git log —-one line
```

## 次は...
次の記事では、ブランチの操作、リモートへの反映などをまとめる予定。
ComboBoxがはげしくめんどいので覚え書き

ComboBox QMLタイプですが、複雑すぎたので調べたことをメモに残しておきます。
Qt 5.11.2あたりの情報です。

```qml
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Window 2.11 //アプリのウィンドウサイズを取得するのに使う

ComboBox {
    id: control

    background: Rectangle {}//Popup開く前、元の状態の背景
    contentItem: Text {}//Popup開く前、元の状態の文字
    indicator: Image{}//Popup開く前、元の状態のときに出てくる記号

    delegate: ItemDelegate {//Popupの子のListViewで羅列するデリゲート
        contentItem: Text {}//デリゲートに表示させる文字
        background: Rectangle {}//背景
    }

    popup: Popup {//ComboBoxをクリックしたときに出てくるポップアップ
        y: control.height
        width: control.width

        //Popupのheightは最大で、アプリのウィンドウサイズまで広がる。
        height: Math.min(contentItem.implicitHeight, control.Window.height - topMargin - bottomMargin)

        contentItem: ListView {//ポップアップの中にあるListView。ComboBoxのdelegateが並ぶ。
            ScrollIndicator.vertical: ScrollIndicator {//さらにスクロールインジケーターを配置
                contentItem: Rectangle {}//スクロールインジケータはほっそいRectangleなどで作ろう
            }
        }
    }
}
```
もちろん、TextだのRecangleだのImageだのは好きなものに置き換えても動作します。

ComboBoxのpopupのcontentItemのScrollIndicator.verticalのcontentItemのRectangle…？
俺はスクロールインジケーターの形と色を変えたかっただけなんだ。
なのになぜこんな遠いところまで来てしまったんだ…。
VOICEROIDで変換した声を聞きながらDiscordで通話する

# VOICEROIDで変換した声を聞きながらDiscordで通話する

自分の声をVOICEROIDのボイスに変換しながらDiscordで通話してみました。
その際に、変換後のボイスが、自分では聞くことができなかったので、聞けるようにする方法を調べてみました。
これから機械音声系VTuberを始める方の参考になれば幸いです。

# 構成

今回は以下のような構成です。

- 自分の声をマイクで録音
- それをゆかりねっとでテキスト化
- それをVOICEROIDで音声化
- それをVB-AUDIOに入力
- それをDiscordの入力デバイスに指定

# 事前準備
マイク→ゆかりねっと→VOICEROIDまでのフローは構築できているものとします。

こちらの記事が非常に参考になりました。
https://ariemonn.net/entry/2018/01/22/131410

# 仮想オーディオデバイスのインストール

仮想オーディオデバイス **VB-CABLE** をインストールします。
https://www.vb-audio.com/Cable/

こちらが参考になりました。
https://arutora.com/archives/20180516223000/

# 仮想オーディオデバイスの設定

次に、VOICEROIDの `オプション` → `その他` → `オーディオデバイス` で `CABLE Input (VB-Audio Virtual Cable)` を指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/8ef9562d-3cf3-dade-4c8a-ee447da75d2c.png)

そして、Discord側の 歯車のアイコン → `アプリの設定` → `音声・ビデオ` → `音声設定` → `入力デバイス` を `CABLE Output (VB-Audio Virtual Cable) に設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/a460fb02-1f37-78bb-1e80-870cec2d954e.png)

これで、VOICEROIDの声で通話をすることはできます。
しかし、その声を自分で聞くことはまだできません。

# ボイスを聞きながら通話する


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/979fe682-4c0c-b3e2-db72-c7b24a3323b9.png)

Windows10の場合、デスクトップ右下の通知領域（いわゆるタスクトレイ）の **スピーカーのアイコン** :speaker: を右クリック → `サウンド` → `録音`タブ → `CABLE Output` を右クリック → `プロパティ` → `聴く`タブ → `このデバイスを聴く` のチェックをONにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/7ed91c57-c97d-045a-b0e6-5ca359096c29.png)

これで、変換後の声を聞くことができるようになりました。

# さいごに

Discordの部分をVRChatにすれば、VRワールドで会話することもできるようになりますね！
【Chapter 2.2】文系大学生が読み解くDeep Learning Book

# 【Chapter 2.2】文系大学生が読み解くDeep Learning Book

## 概要

数学的素養がほとんど高校生止まりの
とある文系大学生が著名な[Deep Learning Book](http://www.deeplearningbook.org/)
を読み解いていきたいと思います。（＝翻訳・まとめ・解釈）

## Chapter 2.2 Multiplying Matrices and Vectors / 行列とベクトルの掛け算

### 行列演算

行列演算（行列と行列の掛け算）

を行うためには、

Aの形が $i \times k$

Bの形が $k \times j$

でなければなりません。

$$
C_{i,j} = \Sigma_{k} A_{i,k}B_{k,j}
$$

### Element-wise Product / Hadamard Product / アダマール積

行列の成分ごとの積 = Element-wise Product を、

$$
A \odot B
$$

### Dot Product / 内積 / ドット積

行列やベクトル同士の積 = Dot Product を、

$$
\mathbf {x} ^{\mathsf {T}}\mathbf {y}
$$

とTのような表記をします。

### その他の行列演算に関する公式

$$
A(B+C) = AB + AC
$$

$$
A(BC) = (AB)C
$$

$$
\mathbf {x} ^{\mathsf {T}}\mathbf {y}
= \mathbf {y} ^{\mathsf {T}}\mathbf {x}
$$

$$
(\mathbf {AB}) ^{\mathsf {T}} =
\mathbf {B} ^{\mathsf {T}}
\mathbf {A} ^{\mathsf {T}}
$$

$$
\mathbf {x} ^{\mathsf {T}}\mathbf {y}
= (\mathbf {x} ^{\mathsf {T}}\mathbf {y})\mathsf {T}
= \mathbf {y} ^{\mathsf {T}}\mathbf {x}
$$

### 単位行列

$$
A_{m,1}x_{1} + A_{m,2}x_{2} + ... + A_{m,n}x_{n} = b_{m}
$$

の時、

単位行列$I$は、

$$
I=
\begin{pmatrix}
1 & 0 & 0 \\\\
0 & 0 & 1 \\\\
0 & 0 & 1
\end{pmatrix}
$$

## 最後に

間違いやご指摘などが御座いましたらご教示願います！

## 参考文献

http://www1.kiy.jp/~yoka/LaTeX/latex.html
Pythonで楽天APIを使ったジャンル一覧リストの作成

## はじめに

楽天ショップのジャンルを知りたくて、
[PythonのRequestsモジュールで楽天APIを使ってみる](https://bty.sakura.ne.jp/wp/archives/1157)　を参考に
楽天APIとRequestモジュールを使って楽天商品の全ジャンルを取得してみた


環境：Windows7,Python3

## サイトの調査

全ジャンルの取得をしているサイトを探したけど、
以下の表のように、親階層を意識せず、
下記のようなリストしか見つからなかった。

| GenreLevel | GenreID       |  GenreName     |
|-----------:|--------------:|:--------------|
|1           | 510915        |  ビール・洋酒   |
|2           | 100324        |  ビール・発泡酒 |
|3           | 567652        |  ノンアルコール |

僕は、階層を考慮した表を作りたい。

| GenreID：1 | GenreName：1   |・・・|GenreID：N   |  GenreName：N |
|-----------:|:--------------:|:---:|------------:|:--------------|
| 510915     |  ビール・洋酒   |・・・|567652      | ノンアルコール  |


## やったこと

親階層のジャンルID,ジャンル名を保持した状態で、ジャンルを取得し、
一覧を作成できるようにしてみた。

その際のスクリプトを、自身の振り返りもかねて記載。
※動いているから、ひとまず大丈夫そう

```python:test.py
item_url = 'https://app.rakuten.co.jp/services/api/IchibaGenre/Search/20140222'
item_parameters = {
            'applicationId': ***ApplicationID***,
            'format': 'json',
            'formatVersion': 2,
            'genreId': 0,
}

# 最上位階層の取得
r = requests.get(item_url, params=item_parameters)
item_data = r.json()
sleep(1)

# 取得したジャンル情報を保持するデータフレームを用意
df_genre = pd.DataFrame()

# 階層を掘ってジャンル情報を取得する
for i in item_data["children"]:
    # 最上段ジャンル情報
    parent_genre_level = i["genreLevel"]
    parent_genre_id = i["genreId"]
    parent_genre_name = i["genreName"]

    # 最上段ジャンルに紐づく、子ジャンル情報の取得
    genre_list = []
    df_genre = loop_get_genre(df_genre, genre_list, parent_genre_level, parent_genre_id, parent_genre_name)
    df_genre.to_csv("genreList.csv", index=False)

```


【loop_get_genre】関数はこちら

```python:test.py
def loop_get_genre(df, genre_list, genre_level, genre_id, genre_name):
    """
    ジャンルID,ジャンル名を取得する
    :param df: 取得ジャンル情報
    :param genre_list: 対象ジャンル情報
    :param genre_level: ジャンル階層
    :param genre_id: ジャンルID
    :param genre_name: ジャンル名
    :return: 取得ジャンル情報
    """
    
    # 関数内のリストにのみ反映させる
    temp_genre = copy.deepcopy(genre_list)

    # ジャンルID
    temp_genre.extend([genre_level, genre_id, genre_name])
    
    # 追加しようとするリストのサイズがDFの列サイズより小さいと警告が出るため、対処
    add_null = 0
    if len(df.columns) > len(temp_genre):
        while len(df.columns) > len(temp_genre):
            temp_genre.append("")
            add_null += 1

    df = df.append([temp_genre])
    
    # 列サイズの対処処理を実施していた場合、元の列数に戻す
    if add_null > 0:
        for i in range(add_null):
            temp_genre.pop()

    # 現階層に対する子ジャンルが存在するかをチェックする
    item_parameters["genreId"] = genre_id
    get_api = requests.get(item_url, params=item_parameters)
    temp_list = get_api.json()
    sleep(1)

    try:
        # 子ジャンルが存在する場合、階層を下げてジャンル情報を取得する
        child_genre_id = temp_list["children"]
        for j in child_genre_id:
            df = loop_get_genre(df, temp_genre, j["genreLevel"], j["genreId"], j["genreName"])
    except:
        pass
    return df

```

## 　まとめ
楽天APIの実行のルール（1秒間に1回まで）のため、全件取得に時間がかかりそう。
※まだ実行中(4時間経過)

あと、ヘッダーの設定をしていないので、
「GenreID：1」とかも、階層にあわせて設定できるようにしていきたい。

今後は、今回取得できるリストを使って、楽天商品をジャンル別に取得できればと思う。


以上。
RubyのGemを作ったので、TravisCIでCIを回す

## はじめに
どうも都内でエンジニアしている[@emono](https://twitter.com/emono_dev)です。
`TravisCI`初めて使ってみたのでメモです
CIツールはいろいろあるがメジャーどころだと`TravisCI`は`OSS向け`、`アプリケーション開発`には`CircleCI`が向いているっぽい（[参考](https://sue445.hatenablog.com/entry/2018/12/07/114638)）


## やりたいこと
RubyのGemを作ったので、CIを使って↓のCIのstatusをラベルを付けたかった（OSSっぽいじゃん？）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116518/bd22aeef-26de-c933-f85e-bbc69af159e8.png)

ラベルつけたGemはこちら

- [LineのAPIクライアント](https://github.com/emono/line-notify-client)
- [Githubのcontriburion数をカウントするclient](https://github.com/emono/contribution_count)

Gemを作ったときの話はこちら

- [仕事してなかったら通知するスクリプトを作った](https://qiita.com/emono/items/043b10f2ce3a24ee614e)
- [勢いでgemを作ってみた話](https://qiita.com/emono/items/043b10f2ce3a24ee614e)

## やること
- [TravisCI](https://travis-ci.org/)にログイン（Githubでログインする。これでgithubのリポジトリと連携できる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116518/9b6fb205-0af9-852b-008d-b30e51b756fc.png)

- [リポジトリ一覧のページで](https://travis-ci.org/account/repositories)CI対象にしたいものを洗濯
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116518/6e87bda9-abd9-ff69-5531-019648600faa.png)

- travis.ymlを追加
    - 今回はspecを実行したいので（`script: bundle exec rake spec` を追加。このスクリプトを実行してテストしてねってことっぽい）

```
# これはGem作ったときにすでに作成されてた
---
sudo: false
language: ruby
cache: bundler
rvm:
  - 2.5.0
before_install: gem install bundler -v 2.0.1
script: bundle exec rake spec # ここを追加
```

- 上記で設定はOK
- あとはpushするとCIが回る
- 画面上部のラベルをクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116518/4d3338f7-1165-6e3d-19ed-689207bbfaf7.png)

- markdownを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116518/17e29521-6487-2d22-3b25-d25ebf124df3.png)

- リンクをREADMEに貼る（それっぽくなった！！！！）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116518/a3b28ce6-7662-6140-b22b-04e61e713e5e.png)

## 備考
- 環境変数を設定したい場合は、CIを回りたいソースがあるディレクトリで
    - `$ gem install travis`
    - `$ travis encrypt DB_PASSWORD='hogehoge' --add`
    - みたいな感じでymlに記述してくれる（便利！！！）
    - https://qiita.com/gonzaemon111/items/0e3cb3d7ccf5e45135a2

以上、さっくり`TravisCI`を触ってみたメモでした！！！！！！
Image ocrを実行する環境を作る

# 目的

Kerasのドキュメントで公開されているimage ocrの実行をWindowsでできるようにする

# 環境
　os: windows 10
　rpu: rtx 1080 ti
　python: 3.6

# 公開されたimage ocrとは
　直接公開されているのはソースコードで、論文も掲載されている。
　https://keras.io/examples/image_ocr/
　・An End-to-End Trainable Neural Network for Image-based Sequence Recognition and Its Application to Scene Text Recognition
　https://arxiv.org/pdf/1507.05717.pdf

# 参考にしたページ
　https://stackoverflow.com/questions/44847446/how-can-i-use-the-keras-ocr-example
　windowsでcairocffiをインストールする必要があるらしい

# 止まったエラー箇所
　`OSError: dlopen() failed to load a library: cairo / cairo-2 / cairo-gobject-2 / cairo.so.2`
　
　cairoが必要だけど、そのためには「GTK+-2」と「GTK+-3」が必要なのでダウンロードする
　WeasyPrintのインストールができると上のエラー箇所がなくなるので、このページに従ってインストールしていく
　https://weasyprint.readthedocs.io/en/latest/install.html#linux
　https://weasyprint.readthedocs.io/en/latest/install.html#msys2-gtk
　https://github.com/tschoonj/GTK-for-Windows-Runtime-Environment-Installer

　GTX+-2はcドライブ直下、GTK+-3はC:/Program Files/GTK3-Runtime Win64にある。
　なぜか、GTX+-2のbin直下にはものがなかったけども、コードの方は実行できたので良しとする。

# これで実行ができた

# 検討したこと
　windowsの環境にubuntuを入れたりできる、Windows Subsystem for Linux (WSL)なるものがあった。
　実際にインストールしてapt getで入れてみたけど、osの共有？のようなものができなくてGTKが認識されなかったので、別のホスト環境ができたようだった。
　すぐにやめてWeasyPrintのインストールに注力した。
【JSメモ】文字列と数値に演算(+, ==, ===)を行うときの関係

#概要
JavaScriptの文字列と数値に演算(+, ==, ===)を行うときの関係

#文字列と数値の足し算
文字列と数値を足すと全てのものは文字列に変換される．
空文字を足せば数値を文字列に変換できる．

```
>'1' + 2;
'12'

>12 + '';
'12'
```
#二重イコール演算
異なる型を比較すると型強制を行ってから比較する．

```
>12 == '12';
true

>1 == true;
true
```

#三重イコール演算
型強制を行わない厳密な比較を行う．

```
>12 === '12';
false

>1 === true;
false
```
VSCodeでパンくずエリアにフォルダ階層を表示させる(Breadcrumbs)

# 2019/06/06追記
version 1.35で標準で設定できるようになりました。
https://code.visualstudio.com/updates/v1_35#_breadcrumbs-displayed

on/off
`View->Toggle Breadcrumbs`
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/ee99833b-cfe4-a2b7-730f-4e8458db5da8.png)

詳細な設定は下記から可能です。
`settign->User->Workbench->Breadcrumbs`
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/27780691-a40a-4c63-a6b8-d362d8995d41.png)


# はじめに
VSCodeでパンくずでファイルの階層を表示できる設定です。

フォルダ階層を瞬時に確認ができ便利です。
また、パンくずからフォルダ移動・ファイル選択が可能となり、サイドバーを開く必要もないためエディタ画面が広く使えるようになりました🙌

<img width="595" alt="スクリーンショット 2019-05-20 21.58.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/226008/52f1d839-ab71-aecf-89a1-b3ee34d48b34.png">

# 設定

`settings.json`に下記を追加します。
詳細なオプションについては[公式ドキュメント](https://code.visualstudio.com/docs/getstarted/settings)で確認できます。

```json
{
  "breadcrumbs.enabled": true,
  "breadcrumbs.filePath": "on",
  "breadcrumbs.symbolPath": "off",
  "breadcrumbs.symbolSortOrder": "position",
}
```
VPN Gate

VPNでは痛い目にしか会ったことがないかもしれない。

Virtual Private Network

いろいろな会議の際に、ネットワーク設営担当をしてきた。

臨時で運営するネットワークでは、利用者がVPNで接続したい場合がある。

ある特定の資料は、ある特定のVPNの先にしかない場合、どうやって接続するかを聞かれる。


#VPN Gate の概要
https://www.vpngate.net/ja/about_overview.aspx


#VPN Gate 公開 VPN 中継サーバーへの接続方法
https://www.vpngate.net/ja/howto.aspx


<img width="504" alt="vpn1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/b148ee00-7d0c-9706-4e46-9a5245100672.png">

手順通りやったつもりだったが、エラーが出た。

触るもの、触るもの、必ずエラーを出す神の手。
iOS12 Swift4 UIView＆UIControlの角丸方法

##コードで設定方法：
**1.UIViewの場合**
view.layer.cornerRadius = 25;

**2.UILabel，UIButton，UIImageViewの場合**
label.layer.cornerRadius = 15;
label.layer.masksToBounds = true;

##XIB（Xcode Interface Builder）の設定方法：##
![スクリーンショット 0031-04-13 午後4.19.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369482/0cc4271b-7c21-bcad-1fb3-d4943a5d3b1b.png)
[Qt for Python] Qt for Pythonはじめました

# はじめに
Qittaはじめました。
最近、Qt for Python(pyside2)を使っているので忘備録として記事にしていこうかと。
気が向いたら他の話題も書いていくかも。

#開発環境
私の開発環境はこんな感じ。

##OS
Windows10 Home Edition 64bit

##Python
PythonはPython3。[公式](https://www.python.org/)から落としたもの。
Anacondaとかいろいろディストリビューションあるけど、公式のシンプルなのにした。
最初からvenvで仮想環境作って使ってる。venvについては[この記事](https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e)とか見た。

```
(py3env) C:\work>python -V
Python 3.7.2
```

さっと使えるように(仮想環境のパス)\py3env\Scripts\Activate.bat のショートカットをデスクトップに置いてる。
でも実際はVS Codeでしか触ってない。

##IDE、エディタ
最近はやりの[VSCode](https://code.visualstudio.com/)使用。
使ってみて自分的に一番しっくり来ている。
VSCodeでvenv環境使うときは[この記事](https://qiita.com/some-nyan/items/7f20fa5fa0b6e451a42b)参考にした。

###エクステンション
とりあえずPython公式のエクステンション入っていれば問題ない。
Python関連では一応下記を入れている。

- Japanese Language Pack for Visual Studio Code ←日本語化
- Python ←Lintやデバッグ環境
- Python Preview ←使っていない
- PySide2-VSC ←Qt Designer用に少し使う

# Qt
QtはGUIのライブラリ。Pythonには他にもGUIのライブラリがあるけどQtの構成がしっくりくるのでQt一択！
PythonでのQtのバインディングとして下記があるらしい

- PyQt
- PySide
- Qt for Python(PySide2)

公式が出しているとのことらしいのでQt for Python(PySide2)を使うことにした。
(廃れずに生き残って欲しいのでどんどん記事を書いて普及したいところ…)

インストールは簡単

```
pip install PySide2
```

情報は[Qt Wiki](https://wiki.qt.io/Qt_for_Python)見ればいろいろ分かる。

# 終わりに
次回からはいろいろQUIなプログラムを書いていくつもり。

今までMarkdownということで苦手意識あったけど、Qiitaのエディタ使いやすいね。
右側にプレビュー出るし、(？)クリックしたら書き方すぐ分かるし。
あ、見出し1と見出し2の違いがほとんどわからない。
Leetcode #76: Minimum Window Substring

```swift
func minWindow(_ s: String, _ t: String) -> String {
    if t.isEmpty {
        return ""
    }
    var s = Array(s)
    var tDict = [Character: Int]()
    for char in t {
        if let value = tDict[char] {
            tDict[char] = value + 1
        } else {
            tDict[char] = 1
        }
    }
    var startIndex = 0
    for i in stride(from: startIndex, through: s.count-t.count, by: 1) {
        if tDict[s[i]] == nil {
            startIndex += 1
        } else {
            break
        }
    }
    var endIndex = -1
    var sDict = [Character: Int]()
    var ar = [Int]()
    for i in stride(from: startIndex, to: s.count, by: 1) {
        if tDict[s[i]] != nil {
            ar.append(i)
            if let value = sDict[s[i]] {
                sDict[s[i]] = value+1
            } else {
                sDict[s[i]] = 1
            }
            if tDict.keys.count == sDict.keys.count {
                var bigger = true
                for key in tDict.keys {
                    if tDict[key]! > sDict[key]! {
                        bigger = false
                    }
                }
                if bigger {
                    endIndex = i
                    break
                }
            }
        }
    }
    if endIndex == -1 {
        return ""
    } else {
        var minLength = endIndex - startIndex + 1
        var answer = String(s[startIndex...endIndex])
        while endIndex < s.count && !ar.isEmpty {
            let index = ar.removeFirst()
            sDict[s[index]] = sDict[s[index]]! - 1
            var bigger = true
            for key in tDict.keys {
                if tDict[key]! > sDict[key]! {
                    bigger = false
                }
            }
            if bigger {
                if minLength > endIndex - ar[0] + 1 {
                    minLength = endIndex - ar[0] + 1
                    answer = String(s[ar[0]...endIndex])
                }
            } else {
                for i in stride(from: endIndex+1, to: s.count, by: 1) {
                    endIndex += 1
                    if tDict[s[i]] != nil {
                        ar.append(i)
                        sDict[s[i]] = sDict[s[i]]! + 1
                        var bigger = true
                        for key in tDict.keys {
                            if tDict[key]! > sDict[key]! {
                                bigger = false
                            }
                        }
                        if bigger {
                            if minLength > endIndex - ar[0] + 1 {
                                minLength = endIndex - ar[0] + 1
                                answer = String(s[ar[0]...endIndex])
                            }
                            break
                        }
                    }
                }
            }
        }
        return answer
    }
}
```
【JSメモ】変数宣言のlet，const，varの違い

#概要
JavaScriptの変数宣言まとめ

- let
宣言したブロック内**のみで**使用可能な変数

- const
宣言したブロック内**のみで**使用可能な定数
初期化必須
定数なので上書きはできない

- var
宣言したブロック**以降で**使用可能な変数

#使用例
```js:let
let a;
a = 1;

let b = 1;
b = 2;

for(let i=1;i<10;i++){
	//この中だけで i にアクセスできる
	console.log(i);
}

console.log(i); //ブロック外なのでエラー
```

```js:const
const a = 'hello';
a = 'world'; //上書きしてるのでエラー

const b; //初期化してないのでエラー

```

```js:var
var a;
a = 1;

var b = 1;
b = 2;

for(var i=1;i<10;i++){
	//この中は i にアクセスできる
	console.log(i);
}
//ここでも i にアクセスできる
console.log(i);
```

#まとめ
let, constは宣言したブロック内でしか使えない．
var はどこでも使えるが，使わない方が無駄なエラーは回避できる．
Kibanaでデータフレームを作成

# はじめに

相変わらず、いつの間にやら色々な機能が追加される 7.x/master ブランチです。
Machine Learningのところに、データフレームを作成する機能が紛れ込んでいました。
＃以前から、Issueとかでは見かけてましたが。

# 使い方

APIの説明は以下にあります。
https://www.elastic.co/guide/en/elasticsearch/reference/master/configuring-tls-docker.html

が、面倒なのでGUIを使います。

# 使って見る

## 準備

データが無いと意味ないので、まずはサンプルデータをロードしておきます。

![Screenshot_2019-05-20 Kibana.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221612/bcaf8170-3736-2033-d377-db3601c28850.png)

## Data frame作成画面の表示

まずは、ML Appを起動して、Data frame job作成画面を表示します。

![Screenshot_2019-05-20 Kibana(1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221612/f63f0b85-45ec-17e2-ec30-30e1b4f15763.png)

当たり前ですが、なーんもありません。

## Data frame jobの作成

では、jobを作ります。
先ほどの画面で「Create data frame」ボタンを押すと、使用するインデックスを選択する画面が表示されます。

![Screenshot_2019-05-20 Kibana(2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221612/31172158-7dbf-9c81-9500-e2a8960d5b9c.png)

「kibana_sample_data_ecommerce」を選択します。

![Screenshot_2019-05-20 Kibana(3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221612/f8ff1d0a-8055-fd3c-7158-9a6d3155d4a5.png)

次の画面で、少なくとも一つの「Order by」と「Aggregations」を選択します。上手では、Order byに

- category.keyword
- region_name

Aggregationsに、

- avg(taxful_total_price)

を選択しています。そして「Next」ボタンを押します。

![Screenshot_2019-05-20 Kibana(4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221612/73711d0d-4123-800c-e551-f01c0debc7cf.png)
 
ここではジョブ名とデータフレームを格納するインデックス名をしています。そして「Next」ボタンを押します。

![Screenshot_2019-05-20 Kibana(5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221612/9a1f1c41-b95f-b866-55a9-ffdbfe8d3051.png)

ここまでできたところで、データフレームの作成を行います。データフレームを作成するだけ（Create data frame）、データフレームを作成してデータを読み込み（多分・・・）（Create and start data frame）を選びます。
「Create data frame」を選んでも、ジョブのスタートを選ぶ必要があるので、ここでは「Create and start data frame」ボタンを押します。

![Screenshot_2019-05-20 Kibana(6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221612/6ec11928-5453-5f49-907d-77a74510a95a.png)

右下に、インデックスパターンの作成成功とかデータフレームジョブのスタート成功とか出てますね。

## Discoverでの表示

インデックスパターンができているので、Discoverで表示してみます。

![Screenshot_2019-05-20 Discover - Kibana.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221612/10e2dfa2-bbf5-bd56-26ae-10a6a42ae157.png)

商品カテゴリ、リージョン名、トータル金額が集計表示されているのがわかります。
Visualizeとかで、色々と加工して見るのも面白いかもしれません。

# おわりに

簡単に試して見ましたが、いかんせんドキュメントが無いので（たぶん・・・）使いこなすまではできてません。
早くドキュメントこーい！
Pydubを使う音声認識ことはじめ

環境：macOS Mojave 10.14.4
目標：一からmp3やwavをnumpy内の配列データに落とし込み, いじれるようにする.

<h1>ffmpegのインストール</h1>
ターミナル上でffmpegをインストールします.
<code>brew install ffmpeg</code>
ffmpegは結構容量が大きくて, 一部のモジュールだけを取り込む人も多いですが最初の段階ではとりあえず全部入れておくのが後々面倒がなくていいと思います.

<h1>pydubの使い方</h1>
<h3>pydubのインストール</h3>

```ターミナル
$ pip install pydub
```
<h3>モジュールをインポート</h3>

```エディタ
from pydub import AudioSegment
import numpy as np
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
```
<h3>mp3の読み込み</h3>
formatをいじればwavを読み込むこともできる.

```
sound = AudioSegment.from_file("xxx.mp3", format="mp3")
#"xxx.mp3"は同じディレクトリにあるようにする.
```
<h3>可視化</h3>

```
data = np.array(sound.get_array_of_samples())
x = data[::sound.channels]
plt.plot(x[::100000]) #数はmp3の容量により適宜調整の必要あり.
plt.grid()
plt.show()
```
例えば, このコードである曲のmp3を可視化したところ次のようになった.
![worldismine.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366427/48c8fca0-9de4-d7b0-6cc3-abfad1723692.png)


<h2>参考</h2>
<p>以下にjupyter上でのコードを掲載しているので、是非参考にしてください.</p>
<a>https://github.com/yohei-freelance/Audio_Transform/blob/master/tutorial_pydub.ipynb</a>
AWS CLI でセキュリティグループの詳細を参照する (EC2 Classic, VPC, RDS)

株式会社オズビジョンのユッコ (@terra_yucco) です。
今日はライトに、今日の業務で直面した AWS CLI コマンドを。

# AWS CLI でセキュリティグループの詳細を参照する方法
## EC2 Classic のセキュリティグループ

- セキュリティグループ名で参照可能

```terminal
aws ec2 describe-security-groups --group-names <sg-name>
```

# EC2 VPC のセキュリティグループ

- セキュリティグループ ID で参照可能

```terminal
aws ec2 describe-security-groups --group-ids sg-<sg-id>
```

## RDS のセキュリティグループ

- コマンド、引数とも微妙に異なる

```terminal
aws rds describe-db-security-groups --db-security-group-name <sg-name>
```

## AWS CLI マニュアルを読んでみる

【】内は訳する際に補ったものとなります。

### [aws > ec2 > describe-security-groups](https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-security-groups.html)

#### Synopsis (要約)

```
  describe-security-groups
[--filters <value>]
[--group-ids <value>]
[--group-names <value>]
[--dry-run | --no-dry-run]
[--cli-input-json <value>]
[--starting-token <value>]
[--page-size <value>]
[--max-items <value>]
[--generate-cli-skeleton <value>]
```

>--group-ids (list)
>
>The IDs of the security groups. Required for security groups in a nondefault VPC.
>
>Default: Describes all your security groups.

`--group-ids (list)`

セキュリティグループの ID。デフォルトでない VPC 内のセキュリティグループ【を特定する場合】において必要。
デフォルト【未指定】ではすべてのセキュリティグループを詳細表示する。

>--group-names (list)
>
>[EC2-Classic and default VPC only] The names of the security groups. You can specify either the security group name or the security group ID. For security groups in a nondefault VPC, use the group-name filter to describe security groups by name.
>
>Default: Describes all your security groups.

[EC2-Classic 及びデフォルト VPC のみ] セキュリティグループの名称。セキュリティグループの名称と ID どちらも指定可能。デフォルトでない VPC 内のセキュリティグループに対しては、セキュリティグループ名で詳細表示したい場合には `group-name` フィルタを利用する。
デフォルト【未指定】ではすべてのセキュリティグループを詳細表示する。

#### 整理

|VPC|--group-names|--group-ids|
|:--|:--|:--|
|Classic|指定可能|指定可能|
|Default VPC|指定可能|指定可能|
|Non-default VPC|指定不可能|指定可能|

### [aws > rds > describe-db-security-groups](https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-security-groups.html)

#### Synopsis (要約)

```
  describe-db-security-groups
[--db-security-group-name <value>]
[--filters <value>]
[--cli-input-json <value>]
[--starting-token <value>]
[--page-size <value>]
[--max-items <value>]
[--generate-cli-skeleton <value>]
```

>--db-security-group-name (string)
>
>The name of the DB security group to return details for.

`--db-security-group-name (string)`

詳細を知りたい DB セキュリティグループの名称。

## Conclusion

業務で特定のリソースへのアクセス権限を調査していたのですが、同じ Security Group という言葉でも調べ方からして異なっていて困ったので、自分用にメモをしました。
Rubyにはメソッドが２種類ある(備忘録)

メソッドについて、少しまとめてみました。
#1.定義しないメソッド
**１つの命令**しか出来ないもの
例）

```
puts  ●●● 　
●●●.to_s
```

putsは●●●を出力
.to_sは数値（●●●）を文字列に変換

#2.定義したメソッド
上記のメソッドを組み合わせ、**オリジナル（多数）の命令**ができるもの

def メソッド名　（引数１,引数２・・・）
   やりたい処理1
   やりたい処理２
　　　　：
　　　　：

例）

```
def sabakan (sabakan_money)
if sabakan_money < 500
puts "買います"
else
puts "買いません"
end

sabakan(300)  

#=>買います

```

#まとめ
メソッドを定義するとは、
**メソッドを組み合わせて,オリジナルのメソッドを作ったり再利用すること**

[【七海有里佳とRubyの基礎】Lesson12 メソッドは自分で作れるんです](https://www.youtube.com/watch?v=WK_5y1TtJz4&t=8s)
RustでLLVMするためのcrate、Inkwellを触ってみた

RustでLLVMを使った言語処理系を作りたかったので、とりあえずInkwellを動かすところまでやりました。

Inkwellはllvm-sys.rsのラッパーで、"淡々とunsafeな関数をラップしてsafeな関数にしていくという面倒な作業がなくなるというのは大変ありがたいです"とのことです。良さげですね。

- [RustでLLVM IRを出力するためのcrate「inkwell」について \- Qiita](https://qiita.com/rchaser53/items/d291ed35b33f6ed000e7)

## Cargo.toml

以下を追加します。LLVMの最新版は3月にリリースされたLLVM 8ですが、まだ対応ブランチがないので、LLVM 7を使うことにします。

```Cargo.toml
[dependencies]
inkwell = { git = "https://github.com/TheDan64/inkwell", branch = "llvm7-0" }
```

## LLVM 7を入れる

これだけだと、cargo buildしてもLLVMがないというエラーになりました。ということで `brew install llvm@7` でLLVM 7.0.1を入れます。 (llvmenvも試したけどコンパイルできなかった)

インストール後、inkwell(というかllvm-sysかな)が見つけられるようパスを通してやる必要があります。

```
export PATH="/usr/local/opt/llvm@7/bin:$PATH"
```

## サンプル

これで、[README](https://github.com/TheDan64/inkwell)にあるサンプルがcargo runできるようになりました。

```shell-session
$ cargo run
   Compiling shiika v0.0.1 (/Users/yhara/Dropbox/proj/shiika)
warning: unused imports: `InitializationConfig`, `Target`
  --> src/main.rs:95:24
   |
95 | use inkwell::targets::{InitializationConfig, Target};
   |                        ^^^^^^^^^^^^^^^^^^^^  ^^^^^^
   |
   = note: #[warn(unused_imports)] on by default

    Finished dev [unoptimized + debuginfo] target(s) in 1.85s
     Running `target/debug/shiika`
1 + 2 + 3 = 6
```

このサンプルではメモリ上でLLVM IRを作ってそれを実行するところまでやっていますが、やりたいのは実行ファイルの生成なので、そのやり方もまた調べてみたいと思います。
flac音楽ファイルのメタデータをmp3に付ける

# やりたいこと
* flacからmp3に変換するときにメタデータが消えるのを何とかしたい
* よくよくググったら出てきた。

という話です。
[ID3タグとflacファイルメタデータとRust](https://qiita.com/hakua-doublemoon/items/db7b3a970ba7c34add96)でRustでやることも考えましたが、今回の発見でこの計画は凍結です。

# 解決法
ここにありました。
https://wiki.archlinux.jp/index.php/Flac_%E3%82%92_Mp3_%E3%81%AB%E5%A4%89%E6%8F%9B
flacのツールとlameを使います。lameでmp3に変換するときにタグのデータを入力できたのです。
ただ、上記のサイトだと私の欲しい次のフレームが欠落していたので、それぞれ追加対応しました。

* アルバムアーティスト
    * アルバムアーティストはID3の規格では`TPE2    [#TPE2 Band/orchestra/accompaniment]`でした。
    * なので `--tv "TPE2=${ALBUMARTIST}"`のオプションを付けます。
* 作曲者。これはそのままComposerだったので、
    * ` --tv "TCOM=${COMPOSER}"`

というわけでシェルスクリプトの改訂版は下記です。

``` meta_flac2mp3.sh
#!/bin/bash

for a in *.flac; do
  # give output correct extension
  OUTF="${a[@]/%flac/mp3}"

  # get the tags
  ARTIST=$(metaflac "$a" --show-tag=ARTIST | sed s/.*=//g)
  TITLE=$(metaflac "$a" --show-tag=TITLE | sed s/.*=//g)
  ALBUM=$(metaflac "$a" --show-tag=ALBUM | sed s/.*=//g)
  GENRE=$(metaflac "$a" --show-tag=GENRE | sed s/.*=//g)
  TRACKNUMBER=$(metaflac "$a" --show-tag=TRACKNUMBER | sed s/.*=//g)
  DATE=$(metaflac "$a" --show-tag=DATE | sed s/.*=//g)
  ALBUMARTIST=$(metaflac "$a" --show-tag=ALBUMARTIST | sed s/.*=//g)
  COMPOSER=$(metaflac "$a" --show-tag=COMPOSER | sed s/.*=//g)

  # stream flac into the lame encoder
  flac -c -d "$a" | lame -V0 --add-id3v2 --pad-id3v2 --ignore-tag-errors \
    --ta "$ARTIST" --tt "$TITLE" --tl "$ALBUM"  --tg "${GENRE:-12}" \
    --tn "${TRACKNUMBER:-0}" --ty "$DATE" \
    --tv "TPE2=${ALBUMARTIST}" --tv "TCOM=${COMPOSER}" \
    - "$OUTF"
done
```
Javaでのごく単純な入力受取り

暫く書いていなかったため，全く忘れておりました．入力受取りを脳死で行うメモです．

## 共通項
import文でScannerを呼んでくる．

```java:
import java.util.*;
```

``Scanner``クラスに``System.in``を渡す．

```java:
Scanner sc = new Scanner(System.in);
```

## 文字列の受取り
$S$を文字列とする．

```java:
String S = sc.next();
String S = sc.nextLine();
```

ただし，``next``は入力値を改行まで認識し，``nextLine``は空白まで認識する．たとえば
> $S_1$　$S_2$
> $S_3$

という入力があった場合，``next``では$S_1$ $S_2$を読み取り，``nextLine``では$S_1$を読み取る．
## 数値の読み取り
$x$を数値とする．パースを``Integer.parseInt()``で行うと2倍程度速いらしい．

```java:
int x = Integer.parseInt(sc.nextLine());
int x = sc.nextInt();
```

## 配列の読み取り
$V_1, V_2, \cdots V_n$を配列``V``とする．

```java:
Integer V[] = new Integer[N];
for (int i=0; i<N; i++) {
    V[i] = sc.nextInt();
}
```

以下だと可読性が低い．

```java:
String a = sc.nextLine();
String[] b = a.split(" ");
int[] c = Stream.of(b).mapToInt(Integer::parseInt).toArray();
```

## Listの読み取り
$V_1, V_2, \cdots V_n$をList``V``とする．

```java:
ArrayList<String> V = new ArrayList<String>();
for (int i=0; i<N; i++) {
    V[i] = sc.nextInt();
    ary.add(word);
}
```

``Scanner``を自作することでより高速化が望めるらしい．
メール返信時の引用記号を自動付与する

メール以外のコミュニケーションツールが徐々に普及しつつありますが、やはりまだ主流はメールではないかと思います。

そんなメールの返信時によく目にする「＞」のマーク。
例えばこんなケース。
> いつもお世話になっております。
> ○○商事の△△です。
> 
> ご質問頂きました件について回答差し上げます。
>
> ＞・・・・・
> これにつきましては、・・・・・・ 

一文程度なら苦ではないのですが、複数行に渡って引用する場合、この引用記号を付けるのは結構面倒です。
（メーラーやメールの形式によっては自動で引用記号をつけてくれる場合もあるようですが、そうでない場合もあります。）

そこで、簡単に引用記号をつけることができるスクリプトを作成しました。

```python
import tkinter as Tk
import subprocess

text = Tk.Text().clipboard_get()
p = subprocess.Popen(['clip'], stdin=subprocess.PIPE, shell=True)
p.stdin.write("＞".encode('shift-jis') + text.replace("\n", "\n"+"＞").encode("shift-jis"))
p.stdin.close()
```

使い方は簡単！
引用記号を付けたい文章をコピーしてスクリプトを実行するだけ。
クリップボードを内容を加工しているので必要な操作はコピー操作だけです。

是非、お試しあれ～


#### ※留意点※
HTML形式のアウトライン文章など、コピー内容によっては期待通りに動作しないケースもあります。
BigQueryでTIMESTAMPを５分単位で丸める



### timestampを5分単位に丸める

### 例

2018-04-07 03:17:42 → 2018-04-07 03:15:00

### SQL

```SQL
SELECT
  my_timestamp AS org_timestamp,
  TIMESTAMP_TRUNC(TIMESTAMP_SUB(my_timestamp, INTERVAL MOD(EXTRACT(MINUTE from my_timestamp), 5) MINUTE) ,MINUTE) AS rounded_timestamp
FROM
  `table`
```

* MOD(EXTRACT(MINUTE from my_timestamp), 5)  →　分を抜き取り、5で割った数
* TIMESTAMP_SUB(my_timestamp, INTERVAL __N__ MINUTE) → ${N}分前。つまりこれで「5分で割ったあまりの数」分前のTIMESTAMPになる
* TIMESTAMP_TRUNC( __TIMESTAMP__ ,MINUTE) → 分に丸める
チャットでじゃんけんを平等に行いたい

##公平に先攻後行決めたいですよね？

"じゃんけんで負けたほうが〇〇ね！"
日常的な会話でありますよね。
最近(?)、Lineの台頭によりチャット上で友人と会話することが増えました。しかし、チャットでじゃんけんをするのはとても難しいです。
せーので手(グー、ちょき、ぱー)を出せないからですね。
そこで、２つの素数を使ってじゃんけんに代わる平等なゲームがありますので紹介します

##素因数分解の一意性と難しさを使う
例えば、
36を素因数分解すると、
2*2*3*3以外の分解の仕方がないですよね。そういうことです

素因数分解の難しさとは、大きな数-例えば1234567を素因数分解してくださいと言われてもすぐ出来ないですよね。
大きな数の素因数分解はコンピュータを持ってしても長い時間が経ってしまいます。

##素因数と合成数の関係
まず、素数は２を除けば皆奇数であり
奇数を4で割ったあまりは1,3のどちらかである
4で割ったあまりが等しい奇数同士を掛けると、その積になる合成数を４で割ったあまりは1になります

```math
p=1 mod4,q=1 mod4 \Rightarrow pq=1 mod4\\
p=3 mod4,q=3 mod4 \Rightarrow pq=1 mod4\\
p=1 mod4,q=3 mod4 \Rightarrow pq=3 mod4
```
これを使います。
ぼくとあなたがこのじゃんけんをするとしましょう。
僕が4で割ったあまりが等しい2つの素数を選びます。
5と13としましょう。
$5 \times13=65$ なのであなたに65とチャットを送ります。
あなたは1か3を答えてください(今は例なので一瞬で素因数分解出来てしまいますが、本来もっと大きい数なので素因数分解するのは諦めて当てずっぽうで答えてね)

あなたが選んだ数(1or3)を僕にチャットで送ったら、勝ち負けの判定です。
僕は5,13を開示し、掛け算をすると65になることを示し、5,13をそれぞれ4で割ったあまりが１であることを伝えます。
あなたが僕に送った数が１ならあなたの勝ち。３なら僕の勝ちです。
完全に平等院鳳凰堂です。

こんど僕とこれでじゃんけんしましょうね！！
##おまけ
もし、素数でなく合成数を２つ選ぶと。。。
$?  \times?=1365$　で1365をあなたに伝えます。
あなたが1と答えたら 15,91を開示しあまりが3なので僕の勝ちです
あなたが3と答えたら 21,65を開示しあまりが1なので僕の勝ちです
Ruby入門2　・配列　・ハッシュ

Ruby入門2を書きます。アウトプット用。

配列とは、オブジェクトをまとめて扱う部品である。
それを、変数に代入して配列に名前をつけることができる。

``drinks = ["カフェラテ","モカ","コーヒー"]``
``puts drinks[0]``
↑要素を取得する　0,1など。　drinks.first(最初)   drinks.last(最後)
でも、最初と最後の要素を取得することができる。


要素の追加,削除の方法

先頭に追加したい場合
``drinks.unshift("モカ")``
先頭だけ削除する場合
``drinks.shift

末尾に追加したい場合
``drinks.push("カフェラテ")``
末尾だけ削除する場合
``drinks.pop``


配列を繰り返し処理する

```
drinks = ["コーヒー","カフェラテ"]
drinks.each do |drink|
 puts drink
end
```

オブジェクトを組で扱う　ハッシュ
ハッシュは複数のオブジェクトをまとめることができる入れ物です。
キーと値のセットでデータを扱うことができる。
２つのハッシュの基本構造  キーの所をシンボルと呼びます。　
``menu = {:coffee => 300, :caffe_latte => 400}`` ハッシュロケット
``menu = {coffee: 300, caffe_latte: 400}``
上は文字列がキーに入るときに使う。
下はみやすくて書きやすいが、文字列が入らない。

ハッシュの値を取得する
``puts menu[:coffee]``
上のどっちの書き方でも、これで要素を取得する

配列の時と同じように、キーと値を追加する
``menu[:mocha] = 400``
新しいキーと、値

ハッシュの要素の削除
``menu.delete(:caffe_latte)``


ハッシュを繰り返し処理する

```
menu = {"コーヒー" => 300, "カフェラテ" => 400}
menu.each do |key,value|  　←2つの値を入れる
 puts "#{key}は#{value}円です"
end
```
コーヒーは３００円です
カフェラテは４００円です
と表示される
AWS IoT × Raspberrypi でやったことメモ

AWS IoTの使い方を知るために、Raspberrypiと繋げてみることにしました。
その際やったことをメモベースでまとめています。
基本的にRaspberrypi側の設定です。

# 参考ページ
以下のページを参考にしています。

[Raspberry PiにUbuntu MATEをインストール + リモート接続](https://qiita.com/sasayabaku/items/ff96f700d2b65fdf085e)

[Raspberry Pi（Raspbian）Python3インストール](https://hirazakura.hatenablog.com/entry/raspberrypi/setup/python)

[AWS IoT Device SDK for Pythonを使ってRaspberryPiとAWS IoTをつないでみる](https://dev.classmethod.jp/hardware/raspberrypi/aws-iot-device-sdk-for-python-raspberrypi-aws-iot/)

[AWS IoT にデバイスを登録してテストする](http://ino-h.com/blog/2017/02/04/aws-iot-post.html)

主に[こちら](https://dev.classmethod.jp/hardware/raspberrypi/aws-iot-device-sdk-for-python-raspberrypi-aws-iot/)を主軸に自分に当てはまる環境構築をしていきました。

# pip3のインストール等

前準備で以下のコマンドを実行。

```
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install build-essential tk-dev libncurses5-dev libncursesw5-dev libreadline6-dev libdb5.3-dev libgdbm-dev libsqlite3-dev libssl-dev libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev libffi-dev libc6-dev
```

python3、pip3をインストール。
(インストールのバージョンは任意)

```
$ wget https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tgz
$ tar -zxvf Python-3.6.6.tgz
$ cd Python-3.6.6
$ ./configure --prefix=/usr/local
$ sudo make
$ sudo make install
$ sudo pip3 install -U pip
$ sudo pip3 install -U setuptools
```

自分がインストールしたバージョンか確認。

```
$ python3 -V
$ pip3 -v
```

# 動作環境構築

AWSの不足モジュールをインストール。
(既にある場合は無視)

```
$ wget https://pypi.python.org/packages/b8/41/ec9d0786b4ae9f6d205a68cf96ade89414337ebaabb88740f02477d840fa/AWSIoTPythonSDK-1.0.0.tar.gz
$ tar xfvz AWSIoTPythonSDK-1.0.0.tar.gz
$ cd AWSIoTPythonSDK-1.0.0
$ chmod +x setup.py
$ sudo python3 ./setup.py install
```

SDKをインストール。

```
$ sudo pip3 install AWSIoTPythonSDK
$ git clone https://github.com/aws/aws-iot-device-sdk-python.git
$ cd aws-iot-device-sdk-python
$ cd samples
$ mkdir cert
```

また、以下のようにcertの直下に証明書を置きます。

```
cert
|-- xxxxxxxxxx-certificate.pem.crt  xxxxxxxx-private.pem.key  rootCA.pem

```

# 動作確認
以下のコマンドでサンプルを動かすことで、AWS IoTとの接続が確認出来ます。

```
$ cd samples/basicPubSub
$ python basicPubSub.py --endpoint xxxxxxxxxxxx.iot.ap-northeast-1.amazonaws.com --rootCA ../cert/rootCA.pem --cert ../cert/xxxxxxx-certificate.pem.crt --key ../cert/xxxxxxx-private.pem.key
```
因みにエンドポイントは以下の場所に書いてありました。
![aws-iot1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308887/34bfee37-0c1b-2a1a-03c6-2d8a07b6a174.png)

# まとめ
<img width="1041" alt="スクリーンショット 2019-05-20 20.40.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308887/c7f174bc-36eb-7a62-ab56-194a8644a9dd.png">
色々サンプルを動かしてみると、こんな感じで通信出来ていることが確認できました。
ただ、まだ繋いでしかいないので、AWSIoTを使って何かしらやってみたいと思います。
一般作業時の理想のフォルダ構成

#はじめに
ここから書くことはすべて個人的な妄想です。
プロジェクトのフォルダ構成を考えてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172695/f4585a8b-fae7-75e3-4b09-68e5252b9bc3.png)

#子フォルダの構成
実際に書類（ファイル）が入っているフォルダを想定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172695/6cc7b271-484a-af85-5563-5dd9703aa9be.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172695/7d8c58b4-7230-1fea-ebba-7542b94b7bf9.png)

##届けこの想い
###正式な書類、運用をしている書類
以下正式書類と呼称。

正式書類は題名の最終日付や、【最終】といった言葉で定義されるべきではない。これは以下理由による。

- 探すのに時間を要する
- 最終が2つあった場合確認が困難になってしまう
- 記入されている日付が数年前だと、不安に感じてしまう
- ファイルを変更する際に、他のファイル名も変更する必要が生じる（前のファイルの【最終】を消すなど）

正式書類についてはむしろ**それらが記載されていない**ことで定義する。

###作業中のファイル、編集中のファイル

以下作業書類と呼称。
作業書類については「work」や「作業中」というフォルダを作成して、作業書類であることを明示するべき。
フォルダで文化されることで、以下利点がある。

- workや作業中というフォルダに**入っていない**書類は正式書類と示される。
- ある程度のサンドボックス（=砂場）感が出るので、新規にフォルダを作成しやすい。例えば「20190512_○○編集」というフォルダを作成しやすい。
- 作業が終わった作業書類が集まっているため、容量の削減がしやすい（作業フォルダを圧縮や削除すればよい）。

また、正式書類について日付や最終と記入しないことで、以下利点も生じる。

- マニュアルにファイルパスとファイル名を記入しておくと、よほどのことがない限りそれが変わることがない。
- ロボットフレンドリーも期待できる。「ここのファイルパスのこのファイル名のファイルを印刷する」などの命令が書きやすい。命令が書きやすいということは、ツールやRPA、業務システムが作成しやすい。

###他に便利なフォルダジャンル

- bkフォルダ。バックアップを意味し、古い書類を格納しておく。
- oldフォルダ。bkよりもさらに「古い」というイメージが強くなる。でもbkでいいかも。
- photoフォルダ。写真を入れてると一目瞭然。
- otherフォルダ。参考資料を入れておく。ただし、集計に使ったExcelなど、作業に伴う書類はworkの方がよい。

#親フォルダの構成
実際に書類が入っているフォルダまでの、中間フォルダを想定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172695/fed93bd0-d90b-21ea-1e7b-7bf8c5a8cbc2.png)

##届けこの想い
- 各フォルダの冒頭に数値が付いている。この数値は書類やプロジェクトの番号であるべきではない。
    - 新しい書類やプロジェクトが自然と最後尾に格納されてしまい、「当初の分類順」+「時系列順」が入り交じる構成となってしまう。
- 分類番号が一番望ましい？新規フォルダが作成されても、当初の分類理念が保持される。
- 分類番号例
    - 010_企画書
    - 020_計画書
    - 030_当日書類
    - 040_振り返り

などなどなど。作業順に並んでるのが一番良いかも。
同一分類のフォルダ（取材資料など）は時系列を採用するのがいい。「20190505_東京取材」など。

#その他命名規則

- 半角スペースや全角スペースを入れるのはやめよう。ロボットの命令はだいたい英語と似てくるが、その時スペースがあると違う単語と認識してしまうことがある（「大阪 ○☓」を「大阪」と「○☓」の2つと誤認する）
- なるべく変更を加えないほうがいいかも（フォルダ名でどのプロジェクトのことかわかっていれば、ファイル名ではプロジェクト名は必要ないかも。ただこれは宗派による予感）

#ロボットフレンドリーについて
ここも妄想です。
[RPA](https://winactor.com/column/about_rpa)（自動で業務を行うシステム）などが広がってきたことで、「RPAやシステムが作業しやすい環境つくり」が重要になってきた。
その、「作業しやすさ」をロボットフレンドリーという。
具体的には以下指標を指します。

- 取得・設定するフォルダやファイル名に一律のルールがある
- 取得・設定するファイルのテンプレートが定まっている（ファイル内のどこから情報を取得するか？どこに情報を設定するか？がきちんと定まっている）


#最後に
色々書きましたが、その場その場の状況によると思っています。なるべくそこの組織のメリットが最大化されるように、よかったら適用してみてくださいね。
ISO, IEC, ITUの国際規格を読むには

WTO/TBT協定では、技術的な仕様を記述する際に、非関税障壁とならないようISO, IEC, ITUの国際規格を参照し、その差を明確に記述することを推奨しています。

では、そのISO、IEC、ITUの国際規格の文書をどのようにして閲覧すればよいか。


#図書館等の所蔵
愛知県立図書館では、十年くらい前までISO国際規格を所蔵していました。
月１くらいで訪問し、読み漁っていました。

現在、どこの図書館で所蔵しているか調査中です。

残念ながら、国立国会図書館は日本で発行したものを所蔵するため、ISO国際規格は揃っていません。


#日本規格協会

日本規格協会では、ISOを購入することができるだけでなく、閲覧も可能でした。
過去形なのは、最近訪問してないからだけで、後で調べて補足します。

# Public Available
ISO制定時に、無償公開することを決めた規格は、無料で閲覧できます。


#Liaison
国際規格団体と情報交換協定を結び、相互に情報交換をする団体があります。
例えば、ISO/IEC JTC1とIEEEとはA Liaisonとして、相互の規格を持ち寄って審議することがあります。

Liaison担当は、相互の規格を閲覧し、統合、修正、補間など、両方の規格を矛盾がなく、無駄がない状態にするように努めるため、相互の規格を閲覧します。

私は、ISO/IEC JTC1 SC7から ISO/IEC JTC1 SC22へのリエゾンと、
ISO/IEC JTC1 SC7からISO TC22SC4


#委員限定
ISOを審議する委員は、審議のために、審議対象国際規格のほか、申請すればその国際規格でNormative Referenceで参照している規格も配布されることがあります。

ただし、審議専用であり、外部への発信は審議する委員会での合意に基づいて行う必要があります。

ISO/IEC TR 15504の審議の際には、試行のため