OmniAICreator/Qiita-1.07M huggingface dataset:
【コメビュ不要】OBSにツイキャスのコメントを表示させる。

> <font color="Red">2020/1/19 ツイキャス仕様変更により、カスタムCSSを修正しました</font>

![image.png](https://qiita-image-store.s3.amazonaws.com/0/283280/54d25703-9170-7558-8f57-7e03eae0b61f.png)
タイトル通り、OBSにツイキャスのコメントを表示させるやり方です。
コメビューを透過させて載せるやり方はあったのですが、Youtube Live みたいな感じにコメビュー無しで出来ないか試してみたので、やり方を載せておきます。

## 1. [ソース] に [ブラウザ] を追加する
####[＋]マークをクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/283280/44ffddb1-2d95-81a6-23a9-4f960ea4836f.png)

####[ブラウザ]をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/283280/4e6a975e-763e-cae2-a03c-1ecb8c56f349.png)

####[OK]をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/283280/5a0186ec-0b0a-02d3-3169-7bd40e9b5b45.png)


## 2. プロパティの設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/283280/62f7d6df-c3bd-d965-bb65-a8937159c163.png)

####プロパティの設定を以下のようにします。

| 項目 | 内容 |
|---|---|
|  URL **\*** |  https\://twitcasting.tv/**<font color="red">ユーザー名</font>**/windowcomment/ |
|  幅 |  500 |
|  高さ | 800  |
|  FPS　　　　　　 | 30  |
|  カスタムCSS **\*** | [下記説明にて記載](#-カスタムcssの項目について)  |

#### * URLの項目について
自分の放送ページのURLの後ろに `/windowcomment/`を足して、入力します。
例えば、放送ページのURLが
`https://twitcasting.tv/zsyama/`
の場合、
`https://twitcasting.tv/zsyama/windowcomment/`
といった感じになります。

#### * カスタムCSSの項目について
下のコードを、そのままコピペしてください。わかる方は弄っても構いません。

```css
/*---ここから---*/
body { background-color: rgba(0, 0, 0, 0); margin: 0px auto; overflow: hidden; line-height: 1.1; }
div#comment-list-app { display: flex; position: fixed; left: 10px; margin: 0; min-height: 0; max-width: none; min-width: 100vw; }

/* いろいろと非表示(1) */
#tcx_commentwindowheader_pc_responsive {display: none;}
#comment-list-app > div:nth-child(1) { display: none; }
.tw-player-page__comment__post {display: none;}
.tw-player-page__component__title {display: none;}
.alert-info {display: none;}
.alert {display: none;}
.tw-player-page__comment__list { overflow: hidden; }
.tw-comment-list-view__scroller { overflow: hidden; }

/* コメント間の設定 */
.tw-comment-item-comment { margin: 0; line-height: 1.2em; }
div.tw-comment-list-view__scroller div { padding: 2px 2px 0px 2px; }

/* いろいろと非表示(2) */
a.tw-comment-item-icon { display:none; }
a.tw-comment-item-icon { margin-right: .1em; margin-top: .7em; }
a.tw-comment-item-icon img { width: 1.5em; height: 1.5em; }
img.tw-comment-item-star { display: none; }
span.tw-comment-item-screen-id { display: none; }
.tw-comment-item::after { display: none; }
.tw-comment-list-view__more { display: none; }

/* ユーザー名のフォント設定 */
.tw-comment-item a.tw-comment-item-name  { color: #cccccc; }

/* コメントのフォント設定 */
.tw-comment-item .tw-comment-item-comment { font-size: 1.4em; color: #ffffff; }

/* 縁取り */
.tw-comment-item { text-shadow: -2px -2px #000000,-2px -1px #000000,-2px 0px #000000,-2px 1px #000000,-2px 2px #000000,-1px -2px #000000,-1px -1px #000000,-1px 0px #000000,-1px 1px #000000,-1px 2px #000000,0px -2px #000000,0px -1px #000000,0px 0px #000000,0px 1px #000000,0px 2px #000000,1px -2px #000000,1px -1px #000000,1px 0px #000000,1px 1px #000000,1px 2px #000000,2px -2px #000000,2px -1px #000000,2px 0px #000000,2px 1px #000000,2px 2px #000000; }

/*---ここまで---*/
```

設定後、[OK]をクリックすれば、表示されるはずです。
シェル — $PATH をスペース区切りにして強引に for で回す例

## 例

```bash
for i in $(echo "$PATH" | sed 's/:/ /g'); do echo $i;  done;
```

- コロンをスペースに置換する
- スペース区切りになった PATH を for にわたす
- for はそれを「複数の引数」と認識して、1個ごとにループしてくれる
  - クォートで区切ってしまうと「一個の引数」と解釈されて期待通りに動かない ( e.g `"$(echo "$PATH" | sed 's/:/ /g')"` )

## 出力例

```sh
bash-4.4$ for i in $(echo "$PATH" | sed 's/:/ /g'); do echo $i;  done;
/Users/yuma/.rbenv/shims
/Users/yuma/.rbenv/bin
/Users/yuma/.rbenv/shims
/Users/yuma/.rbenv/bin
./vendor/bin
/Users/yinaura/google-cloud-sdk/bin
/usr/local/opt/openssl/bin
/Users/yuma/.pyenv/shims
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin
```

## 他の例

### $PATH の最初を取る

```sh
for i in $(echo "$PATH" | sed 's/:/ /g'); do echo $i; done | head -n 1
/Users/yuma/.rbenv/shims
```

### $PATH の最後を取る

```sh
for i in $(echo "$PATH" | sed 's/:/ /g'); do echo $i; done | tail -n -1
/sbin
```

## 備考

awk とか使ったほうがスマートそう。(たぶん)

## Versions

- GNU bash, version 4.4.23(1)-release (x86_64-apple-darwin17.5.0)

## あわせて読みたい？

- [シェルの偽装 — 条件判定 ( if / then / fi ) は実はコマンドの連続に過ぎないので独自構文に書き換えてみるテスト - Qiita](https://qiita.com/YumaInaura/items/eb69cb10d7bb6a090e7e)

## Links

- [Gist](https://gist.github.com/YumaInaura/bec7488cdd654e1221894d7c3d7aa5a8)
- [Medium](https://medium.com/supersonic-generation/bash-example-split-path-and-for-in-620ac021cca5)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
[メモ] CentOS 4.9(32bit)のDockerベースイメージ作成


# 概要

- CentOS 4.9(32bit)のDockerベースイメージ作成
- https:/github.com/blalor/docker-centos4-base (64bitイメージ作成)をベースに修正


- ただ使うだけなら、<br>`docker run -it --rm mt08/centos49:i386 bash`



# 手順

```bash
# クローン
git clone https://github.com/mt08xx/docker-centos4-base -b develop
cd docker-centos4-base

# centos49-i386.tar.gz 作成
docker run -it --rm --privileged -v `pwd`:/srv i386/centos:centos6 /srv/build-i386.sh \
&& gunzip centos49-i386.tar.gz \
&& gzip -9v centos49-i386.tar

# 適当に名前をつける
DOCKER_IMAGE_NAME=centos49base-i386
docker build . -t ${DOCKER_IMAGE_NAME} -f Dockerfile.i386
docker images ${DOCKER_IMAGE_NAME}

# おためし実行
docker run -it --rm ${DOCKER_IMAGE_NAME} bash
```


# 修正内容

`https://github.com/mt08xx/docker-centos4-base` の developブランチ

1. centos4は、archiveとなり、URLが変更<br>`dl.fedoraproject.org/pub/epel/ => archives.fedoraproject.org/pub/archive/epel/`


	```txt:dl.fedoraproject.org/pub/epel/4/README
	ATTENTION
	======================================
	The contents of this directory have been moved to our archives available at:

	http://archives.fedoraproject.org/pub/archive/epel/

	If you are having troubles finding something there please stop by #epel on irc.freenode.net
	```

2. yumのレポジトリを `i386` を使うようにする<
`/etc/yum.repos.d/*.repo` ファイルで、$basearchをi386に置き換え、、など

3. 作成されたtar.gzをそのまま`docker build`で食わすと、エラーが出るので、一度、解凍・圧縮する。
`gunzip centos49-i386.tar.gz && gzip -9v centos49-i386.tar`


# その他
1. yumレポジトリを追加したら、$basearchをi386に置換する<br>
: `sed -i -e 's/$basearch/i386/g'  /etc/yum.repos.d/*.repo`




	```bash:例
	rpm -Uvh http://rpms.remirepo.net/enterprise/remi-release-4.rpm
	sed -i -e 's/$basearch/i386/g'  /etc/yum.repos.d/*
	yum search --enablerepo=remi mysql | grep remi | grep '^mysql.i386'
	```

2. これをベースに、↓こんな感じで、環境をつくる。

	```txt:Dockerfile
	FROM mt08/centos49:i386

	RUN set -x && \
		yum groupinstall -y "Development Tools" && \
		yum clean all

	CMD ["bash"]
	```
	ビルドと実行
	`docker build . -t centos49:i386-dev && docker run -it --rm centos49:i386-dev`
【python】imaplibでGmailを読み取る

最近、Rで解析の学習をする中で、自分のメールからスパムメールを抜き出して、形態素解析をしてみようと思いました。
経緯としては、書籍のサンプルデータじゃなくて、リアルを追求したかったからですね。
あとサンプルデータは英語のものが多くて、いまいち実感が湧きません。

しかし、いざメールを解析できる形で用意しようと思ったところ、思わぬ壁が……
メールクライアントはmbox形式など保存されているため、テキストそのままで保存されているわけではありませんでした……

というわけ、ちょっと前置きが長くなりましたが、imaplibを使用して、Gmailから設定した条件に応じたメールのタイトルと本文をテキストで抽出するスクリプトを作っていきます。

##設定した環境
Windows10
Python 3.6.3

##準備
###imaplibはインストール不要
imaplibの詳しい説明
https://docs.python.jp/3/library/imaplib.html

標準ライブラリとのことで、pipしてインストールは不要でした。

###Gmailの設定をする
Gmailで2段階認証をしていない場合に、imaplib経由でアクセスを試みると“安全性の低いアプリからのアクセス”と見なされて、エラーが表示されることがあります。


自分のアカウント2つで試してみたところ、片方は2段階認証無しで、通常のID、パスワードで普通にアクセスできましたが、もう一つは2段階認証した上で、安全性の低いアプリからのアクセスの許可とアプリケーション用の専用パスワードの発行が必要でした。

細かい条件は分かりませんが、セキュリティ関連のエラー表示されたら、下記ヘルプページを参考に設定してみましょう

https://support.google.com/mail/accounts/answer/78754
https://support.google.com/accounts/answer/6010255

##メールアカウントへのアクセス
自分のメールアカウントのユーザー名とパスワードを指定します。

欲しいメールのラベルや送信者、宛先などをgmail.search()内で条件設定します。

今回は、シンプルにALLを使いましたが、
未読のみを取り出したいときは、UNSEENを使います。
その他、送り主のFROMなどもあります。

```python
import imaplib
import email

UserName = "(自分のメールアドレス)"
PassName = "(自分のパスワード[もしくは、アプリケーション専用パスワード])"

gmail = imaplib.IMAP4_SSL("imap.gmail.com", '993')
gmail.login(UserName, PassName)
gmail.select("(読み込みたいメールのラベルを指定する。空なら全て。)")

# ALLでSearchすると指定したラベルの全てのメールを読み込む
head, data = gmail.search(None, 'ALL')
```


##読み込んだメールのタイトルと本文を表示
ひとつのメールには、宛名やタイトル、本文、エンコード、送り主、送信時間など様々な情報が格納されています。

以下は、そこから欲しい情報を取得するための作業です。
タイトルの取得は少々手間ですが、本文は比較的短いコードで取れます。

ちなみに、メールは複数取れる想定なので、for文で取得したメール分だけ繰り返しタイトルと本文を出力しています。

```python
# ------上のコードからの続き------
# 取得したメール一覧の処理
for num in data[0].split():
	h, d = gmail.fetch(num, '(RFC822)')
	raw_email = d[0][1]
	# 文字コード取得
	msg = email.message_from_string(raw_email.decode('utf-8'))
	msg_encoding = email.header.decode_header(msg.get('Subject'))[0][1] or 'iso-2022-jp'
    # タイトルの情報を抽出
	msg_subject = email.header.decode_header(msg.get('Subject'))[0][0]
    # エンコーディング
	subject = str(msg_subject.decode(msg_encoding))
	print(subject)
        
    # 本文の抽出
	body = msg.get_payload()
	print(body)

# 終了処理
gmail.close()
gmail.logout()

print("メール読み込み完了")

```

これで、メールの情報をテキストで抽出することができました。
自分はこの後は、CSVに書き出しとかやってみました。
Mint 19 Cinnamon インストール済みのテーマの'Window Borders'が見えなくなり変更できない時

#なんかテーマが変・・・
以下の画面をよーく見てください。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/102207/fdafa862-b8d3-8f98-532f-6b4e1317a5fe.png)

あれ？！

ウィンドウボーダーのデザインで現在設定中の「Windows-10-Dark-master」というテーマがありません。
ここではごく僅かなテーマしか表示されていませんが、実際は以下のようにデフォルトで入っているテーマも含め、もっといろいろ入っています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/102207/a712fe84-65f8-2ca5-3fc1-cd49d3c04f28.png)

このテーマたちは一体どこへ行ったのか・・・

#古いMintからアップグレードしたMint19だけ？
どうもMint19では、Metacity-1、Metacity-2のテーマを除外するようになっているようです。
[macOSテーマ配布者のgithub](https://github.com/B00merang-Project/macOS/issues/74)で、この問題について報告されていました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/102207/1095f494-85e1-4853-4d7e-ba2a50c4c9f6.png)

つまり、わたしのMintは18.2の時からアップグレードしており、古いバージョンのテーマと混在しているため、**18.2のデフォルトのテーマ**と一緒にリストから除外されているようです。

#古いテーマでもまだ使える！
上記の配布サイトの報告にも書いてありますが、実際は古いテーマでもMetacity-2のウィンドウボーダーが使われているものは使用できます。
表示されないテーマは**``dconf-editor``**を使うことで強制的に設定することが可能です。

<font color='blue'>公式で排除されている以上、古いテーマは今後使えなくなるという意味だと思いますので以降は自己責任で！</font>
もし dconf-editor がインストールされていない場合、以下のコマンドでインストールしましょう。

```bash
sudo apt install dconf-editor
```

ターミナルから``sudo dconf-editor``と叩いて起動するか、メニューの検索窓で``dconf``と入れると表示されます。
<font color='red'>このツールは痒いところに手が届くありがたいツールですが、Windowsでいうレジストリエディタみたいなもので下手にいじると壊れてしまうので注意してください。</font>
![image.png](https://qiita-image-store.s3.amazonaws.com/0/102207/57174d3e-6a49-1e26-bd5c-0e54c8aa7965.png)

dconf-editorが起動したら「/org/cinnamon/desktop/wm/preferences/theme」を開きます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/102207/0d9ad23b-cfb0-b664-7459-e44277590015.png)

一番下にある**``Custom value``**にテーマの名前を入力します。この名前はインストール済みのテーマの「フォルダ名」になります。
ホームディレクトリの``.themes``か、``/usr/share/themes``にあるフォルダ名です。


#(追記)デフォルトのテーマのMetacity-3用ファイルを追加する
[Linux Mint Forums](https://forums.linuxmint.com/viewtopic.php?f=208&t=272414&p=1506620&hilit=nemo+bar#p1506620)で昔のデフォルトテーマを復帰させる方法が投稿されていました。smurphos氏に感謝！！

```bash
wget https://github.com/smurphos/Window_Borders_Mint_19/releases/download/v.0.4/metacity_for_mint19_cinn.zip

unzip metacity_for_mint19_cinn.zip -d ~/.themes

rm metacity_for_mint19_cinn.zip
```

これによって

Adwaita
AgingGorilla
Atlanta
Bright
Crux
Esco
HighContrast
Metabox
Simple

のほかに

Mint-Y-BB
Mint-Y-Dark-BB
が表示されるようになります。

#参考サイト
- [[Half-Upstream (Mint 19)] Window borders not working on Cinnamon · Issue #74 · B00merang-Project/macOS · GitHub](https://github.com/B00merang-Project/macOS/issues/74)
- [Cinnamon 3.8.x - Mint 19 Additional Window Borders / Metacity Themes - Linux Mint Forums](https://forums.linuxmint.com/viewtopic.php?f=208&t=272414&p=1506620&hilit=nemo+bar#p1506620)
- [GitHub - smurphos/Window_Borders_Mint_19: Additional Metacity Themes from Mint 18.3 Cinnamon Edition tweaked to work in Mint 19 / Cinnamon 3.8.x](https://github.com/smurphos/Window_Borders_Mint_19/)
ReactコンポーネントのJSXでの関数の渡し方メモ

主に下記4つの作戦があるらしいです。
（クラスではなく関数としてコンポーネントを定義した時とかはよくわからないです）

* 1. bind作戦
* 2. arrow function作戦
* 3. render内でbind作戦
* 4. render内でarrow function作戦

3,4 は`render`が呼ばれるごとに関数を作るらしいので、リストとかでこれやってるとたくさん関数を作ってしまい、関数作成はコストもままかかるらしいのでうので、パフォーマンスに良くないらしい。
なので、1か2で悩むところですが、1は関数が増えたら定型文が増えてってちょっと汚いので、2のほうがスマート。まあ、1でも問題はないらしい。


### 1. bind作戦

```jsx
class Form extends Component {

  constructor(props) {
    super(props)

    // bind作戦
　　　　　　　　this.handleSubmit = this.handleSubmit.bind(this)
  }
  
  handleSubmit() {
    ...
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="submit" value="Submit">
      </form>
    )
  }
}
```

### 2. arrow function作戦

```jsx
class Form extends Component {
  
  // arrow function作戦
  handleSubmit = () => {
    ...
  }

 // 引数がある時の場合  
  handleSubmit = (thing) => () => {
    ...
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input type="submit" value="Submit">
      </form>
    )
  }
}
```

### 3. render内でbind作戦

```jsx
class Form extends Component {
  
  handleSubmit() {
    ...
  }

  // render内でbind作戦
  render() {
    return (
      <form onSubmit={this.handleSubmit.bind(this)}>
        <input type="submit" value="Submit">
      </form>
    )
  }
}
```

### 4. render内でarrow function作戦

```jsx
class Form extends Component {
  
  handleSubmit() {
    ...
  }

  // render内でarrow function作戦
  render() {
    return (
      <form onSubmit={() => this.handleSubmit()}>
        <input type="submit" value="Submit">
      </form>
    )
  }
}
```
【記録】Associate Cloud Engineer 模擬試験を受けてみた

# お題
GCPのエンジニアスキルを問う資格の模擬試験が無料で受けられるのでトライしてみた。
https://cloud.google.com/certification/practice-exam/cloud-engineer?hl=ja

# 経緯
[前回](https://qiita.com/sky0621/items/aecc256ee66f68f667ab)、Professional Cloud Architect 模擬試験を受けて惨敗したわけだけど、その時点で「アソシエイトの方はどうだろう？」と気になっていたので、今回、夜の夜中に受けてみた。

# 試験について
↓にある通り、アーキテクト試験に比べると、実務寄り？な印象。
https://cloud.google.com/certification/guides/cloud-engineer/?hl=ja

# 結果
さて、結果ですが、予想と反して、それなり（20問中、16問正解）。
もちろん模擬試験がそれなりで受かる保証はないのだけど、アーキテクトに比べると、こちらの方が現時点でまだ受かりそう・・・。
ただ、模擬試験は、なぜか日本語だったものの、本試験は英語のみらしい。（日本語版は９月？１０月？）
とりあえずは、アーキテクトの方を目指して勉強続けた方がいいかな。
Softmax 関数を Grapher で観察する。Sigmoid も

# 前提

機械学習をやる上で必須の Softmax, Sigmoid 関数を、macOS 付属の Grapher でグラフ化してどういう関数なのか観察しようという記事です。

Grapher、何に使うんだよ、って思ってる人も多いかもしれませんが、式の入力のちょっとしたコツを覚えればいろいろな式を目で観察できるのでおすすめです！

とうわけで、すみませんが、MacOS 向けの記事になっています。

# Sigmoid

手馴しに Sigmoid からやってみます。

Grapher を立ち上げて 2D グラフを作成し、Sigmoid 関数の式を入力します。


```math
y=\frac{e^x}{e^x+1}=\frac{1}{1+e^{-x}}

```

![SS1.png](https://qiita-image-store.s3.amazonaws.com/0/73493/c519c64d-7cd9-103a-fc5e-9bdc2d853b60.png)
（この図は、表示ー＞フレームの制限から、x が -6 から 6、y が -0.5 から 1.5 になるようにしています。）

Sigmoid は入力(x) を 0 から 1 の値(y) になめらかに変換するため、80% 確からしい、というようなことを表現するのに使われます。


# Softmax

Softmax は以下の式で表されます。


```math
y_i = \frac{e^{x_i}}{\sum_{j=1}^N e^{x_j}}
```

これは N 個の変数をもっているので、このままではグラフがかけません。2変数の場合のグラフを見るには、N を 2 に限定して、3次元の式の場合の式を作ります。
分母は 

```math 
e^{x_1} + e^{x_2}
```

になります。

```math
x_1 を x
```

```math
x_2 を y
```

```math
y_1 を z
```
とすると、以下の式になります。

```math
z = \frac{e^y}{e^x+e^y}
```

Grapher で3Dグラフを作成し、上の式を入力してみます。

![SS2.gif](https://qiita-image-store.s3.amazonaws.com/0/73493/28da5c7e-59cf-fed2-41b9-b934b090864a.gif)
（この図は、表示ー＞フレームの制限から、x が -5 から 5、y が -5 から 5 、z が -0.1 から 1 になるようにしています。）

Sigmoid 同様、値は0から1までをなめらかにとります。
このSoftmax を 1 次元にするとSigmoid 関数になることは、z = 0.5 で水平方向にみてみるとSigmoid に見えることで観察できます。

# 終わりに

Softmax と Sigmoid の性質についてはネットにたくさん情報があるので、ここでは書きませんが、3次元グラフを Grapher で表示しながら読むと理解しやすいと思います。
それではー
LDAPとは覚書

#LDAPとは
Lightweight Directory Access Protocol
ディレクトリサービスへアクセスするためのプロトコルのこと

#LDAPの種類
####①　Active Directory
Microsoft製
####②　OpenLDAP
オープンソフトウェア

#LDAPで何をするのか
属性（個人名、部署名など）で構成されたエントリ（関連属性のまとまりのこと）の検索・追加・削除を操作する。

LDAPクライアントがLDAPサーバへ接続するとき、TCPポート389番を使う。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/188636/b66787e6-e0aa-7853-0aee-1af3c4b2f35c.png)

#LDAP識別名とは
LDAPでディレクトリサービスへアクセスする際に、アクセス対象を指定する手段。
識別名(DN = Distiguished Name)とも呼ぶ。



>参考サイト及び画像引用元
[LDAPとは](http://www.infraexpert.com/study/security19.html)
Cocos2d-x 3.17とAndroid Studio 3.1.4

#はじめに
現時点2018/08/23でCocos2d-xのAndroidビルドはeclipseでは難しい状況になっている
またCocos2d-x 3.17ではAndroid Studioのみのビルドになっている
この記事がビルドの参考になれば幸いです

#Cocos2d-xでのパッケージ作成
この部分は今までの作成方法と変わらない。
pythonインストールにより./setup.pyでcocosコマンドを使用出来るようにし、
cocos new (名前) -p (自分の識別名).(名前) -l cpp -d Desktop
自分の識別名と名前を自身で決めて作成する。

#Android Studioインストール
[公式サイト](https://developer.android.com/studio/?hl=ja)からダウンロードしてインストール
ほぼ設定する事はなくどんどんと進んでいくが、AndroidSDKのダウンロードフォルダーが表示されるのでメモっておくと楽になる

#Android Studioプロジェクト読み込み
SDKやNDKなど必要なものをダウンロードするが先にプロジェクトを読み込んでもいい
![img1.png](https://qiita-image-store.s3.amazonaws.com/0/213658/5b6274e5-b49c-f92a-205e-5c4853114ce0.png)
Open an existing Android Studio projectから開き、
作成したパッケージのproj.androidを指定

![img2.png](https://qiita-image-store.s3.amazonaws.com/0/213658/1046d2ca-350b-90ff-5a87-0157f97cafc5.png)
青い矢印がアイコンのSDK Managerを開き
SDK PlatformsによりSDKを追加
SDK Toolsにより Android SDK Build-Tools, Android SDK Platform-Tools,
Android SDK Tools, NDKなどを追加
(ビルドが通らない場合はこのダウンロードが足りない可能性がある)

#プロジェクト設定
![img3.png](https://qiita-image-store.s3.amazonaws.com/0/213658/80c438b3-6fda-48af-5398-5c09c2ad30ec.png)
プロジェクトを読み込むと大体こうなる
プロジェクトとで右クリックしてOpen Module Settingsにより証明書の設定、ビルド設定をしていく
![img5.png](https://qiita-image-store.s3.amazonaws.com/0/213658/5f92b7b0-1f0b-5fd0-1a96-c90ebffe627c.png)
SDK, JDK, NDKの場所を指定する

#ビルド
![img2.png](https://qiita-image-store.s3.amazonaws.com/0/213658/0d2e7546-c75c-2872-80a2-561b2fd1dd75.png)
Runを押すとビルドし始める
USBでの実機または仮想デバイスを選択して待つ
![img4.png](https://qiita-image-store.s3.amazonaws.com/0/213658/25c632c0-e075-ed73-e90b-daeeb548bd44.png)
これに似たwindowがあると思うが左はビルド状況、右がエラー内容が表示される(いじっていなければ)
ビルド状況はビックリマークの赤がエラーや問題箇所を表示
これを見ていくと何がエラーなのかわかるようになっている

空プロジェクトは右に何か表示される
押すと勝手にダウンロード始まったり書き換えが起こるのが、
空プロジェクトは2個くらい押すとビルドが通るようになる

#移植
android:name="com.android.billingclient.api.ProxyBillingActivity"
にてエラーが出るが推奨じゃないためエラーが出るようだ
今は気にしなくていい

2018/09/18 変更不要な箇所もあったので変更不要場所を削除
【Python】Pillowで画像をresizeするときの処理時間の違い

Pillowで画像をresizeするときに使用するフィルタによって，処理時間にどの程度差があるかを比較してみました。

```python:使用するフィルタ
- NEAREST
- BOX
- BILINEAR
- HAMMING
- BICUBIC
- LANCZOS
```

上のフィルタほど低品質・高速，下ほど高品質・低速らしいです。

pipでインストール

```python
pip install pillow
```

importと画像の準備

```python
from PIL import Image

im = Image.open('sample.jpg')
im.size
Out[3]: (4032, 3024)
```

余談ですが，画像を一度だけ読み込んでresizeを複数回実行すると，最初だけ時間がかなりかかって2回目以降は極端に時間が短くなったので，都度画像をopenして比較します。

```python:計測結果
In [5]: im = Image.open('sample.jpg')
   ...: %time resized_im = im.resize(size=(256, 256), resample=Image.NEAREST)
   ...: im = Image.open('sample.jpg')
   ...: %time resized_im = im.resize(size=(256, 256), resample=Image.HAMMING)
   ...: im = Image.open('sample.jpg')
   ...: %time resized_im = im.resize(size=(256, 256), resample=Image.BILINEAR)
   ...: im = Image.open('sample.jpg')
   ...: %time resized_im = im.resize(size=(256, 256), resample=Image.BOX)
   ...: im = Image.open('sample.jpg')
   ...: %time resized_im = im.resize(size=(256, 256), resample=Image.BICUBIC)
   ...: im = Image.open('sample.jpg')
   ...: %time resized_im = im.resize(size=(256, 256), resample=Image.LANCZOS)
   ...:
   ...:
Wall time: 223 ms
Wall time: 241 ms
Wall time: 239 ms
Wall time: 224 ms
Wall time: 264 ms
Wall time: 295 ms
```

ということで，最大で（NEARESTとLANCZOS）処理時間が20～30%ほど変わってきそうです。
GithubにSSH接続をする設定を行う

PCが故障して買い替えざるを得なくなったため、久々に実施した時のメモ。
地味につまづいた点もあったので備忘録としてメモ

# 環境
MacOSX High Sierraで実施

# 手順
### 鍵の生成
1. Macでターミナルを起動する
2. キーペアを作成する

    ```
    $ ssh-keygen -t rsa -b 4096 -C "<自分のメールアドレス>"
    ```

3. 以下のような鍵の保存先を設定するプロンプトが出たらそのままエンターキーを押す（デフォルトから変更する場合は絶対パスで設定する）

    ```
    Enter a file in which to save the key (/Users/<ユーザ名>/.ssh/id_rsa):
    ```

4. 次のようにパスワードの設定を求められるので設定する

    ```
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    ```

### ssh-agentへの秘密鍵の登録
1. ssh-agentをバックグラウンドで起動する

    ```
    $ eval "$(ssh-agent -s)"
    ```

2. `~/.ssh/config`ファイルに設定を記入する。
実はこれでつまづいた。__MacOSX Sierra以降ではこの設定が必要になった。__これを入れないとssh-agentが自動で秘密鍵を読み込んでくれなくなる。

    ```
    $ vi ~/.ssh/config
    ```

    ```~/.ssh/config
    Host *
        AddKeysToAgent yes
        UseKeychain yes
        IdentityFile <使用する秘密鍵のパス>
    ```
3. ssh-agentに秘密鍵を登録する

    ```
    $ ssh-add -K <使用する秘密鍵のパス>
    ```

### Githubへの公開鍵の登録
1. __公開鍵__をコピーする
間違っても秘密鍵をコピーしないように

    ```
    $ pbcopy < <使用する公開鍵のパス>
    ```

2. Githubにログイン後、画面右上のユーザーアイコンをクリックして**Setting**を選択する
3. **SSH and GPG keys.**をクリックする
4. **New SSH key or Add SSH key**をクリックする
5. **Title**と**Key**を設定する
6. **Add SSH key**をクリックする
7. パスワードの入力を求められるので入力する

# 参考
- [Generating a new SSH key and adding it to the ssh-agent](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/)
- [Adding a new SSH key to your GitHub account](https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/)
Volumioでコンピレーション・アルバムの再生ができない場合の対処方法

# 結論

コンピレーション・アルバムに対して，以下のどちらかを実行する．

* `albumartist`と`artist`を同じ名前にする
* 設定`MY MUSIC`の`Compilation Metadata Fields`に`albumartist`を追加する

# 詳細

以下のような現象に遭遇しました．

* アルバム一覧からあるアルバムを選択してアルバムの再生ボタンを押しても，アルバムの再生が始まらない
* アルバム一覧からあるアルバムをキューに追加しようとしても，キューに追加できない
* アーティスト一覧からあるアーティストを選択し，そのアーティストのアルバム一覧からあるアルバムを選択したあと，戻るボタンを押すとエラーが発生して戻れない

問題が発生するのは，複数人のアーティストの作品を集めたアルバム，いわゆるコンピレーションと呼ばれるものだと分かりました．コンピーレーションアルバムの場合

* `artist`が複数あるか，１つの`artist`に複数人設定している
* `artist`と`albumartist`が異なる

という状態になっています．iTunesなんかでもアーティスト毎にアルバムが分離してしまったりすることがあります．

問題を調査するため，[SSHを有効にして](https://volumio.github.io/docs/User_Manual/SSH.html)ログインし，`tail -F /var/log/volumio.log`でログを確認します．

```console
2018-08-22T15:46:33.615Z - info: CorePlayQueue::addQueueItems
2018-08-22T15:46:33.615Z - info: Adding Item to queue: albums://<albumartist>/<album>
2018-08-22T15:46:33.616Z - info: Exploding uri albums://<albumartist>/<album> in service mpd
2018-08-22T15:46:33.620Z - info:
```

空のinfoログが出力され，何かに失敗していることがわかります．

直前のログから，`ControllerMpd.prototype.explodeUri`が呼び出されていることがわかります．

```js:volumio/Volumio2/blob/master/app/plugins/music_service/mpd/index.js#L2049
		if (compilation.indexOf(artistName)>-1) {  //artist is in Various Artists array
			var GetAlbum = "find album \""+safeAlbumName+"\"" + " albumartist \"" +safeArtistName+"\"";
		}
		else {
			var GetAlbum = "find album \""+safeAlbumName+"\"" + " artist \"" +safeArtistName+"\"";
		}
```

`compilation`は`MY MUSIC`の`Compilation Metadata Fields`で設定した値が入っているようです．ヘルプを見ても何に使うのかさっぱりわからなかったのですが，ようやく理解できました．

`compilation`に追加しておかないと，`albumartist`と`artist`が一致している場合以外では正しい結果が得られないのだと思います．実際，`albumartist`と`artist`を同じに設定すると，アルバムを再生できることをすでに確認していたのですが，これが原因のようです．

`album://..`の仕様には改善の余地があると思われますが（例えば，albumartistやartistをクエリーパラメーターにするとか），設定もしくはタグの編集で回避可能だとわかりました．
VPN覚書

#VPN とは ?
Virtual Private Network
パブリックネットワークで安全な通信をする技術のこと

メリットとして、
①コスト削減：ISP利用料とアクセス回線費用のみ
②１対多接続が容易

## VPNの種類
一般的なインターネット回線の
① インターネットVPN

閉域網（閉じたネットワーク）の
② IP-VPN
の２種類がある。

① インターネットVPN：安全性＜低コスト
② IP-VPN：　　　　　    低コスト＜安全性

## ① インターネットVPN の特徴
#### 1. トンネリング技術
パケットにヘッダを付けてカプセル化する

####2. 通信パケットを暗号化する技術
秘密鍵暗号方式と、公開鍵暗号方式を組み合わせて使うことが多い

## ② IP-VPN の特徴
####MPLS
Multi Protocol Label Switching
パケットに2種類のヘッダ情報（＝ラベル）を付与する。
１つは転送経路、もう１つはユーザーのネットワークを識別する。
転送経路が示されることで、ルーターが最短経路を選択する処理が不要となり、高速大容量通信ができる。
ユーザー毎に識別することで、暗号化に頼らないセキュリティを確保できる。




>参考サイト
[5分で絶対に分かるVPN](http://www.atmarkit.co.jp/ait/articles/0204/27/news003.html)
textウィジェットのtagをプレースホルダとして使ってみた。

シリアル通信で送受信したデータをtextウィジェットでバイナリエディタ風に

```
31 32 33 34 35 36 37 38 01 02 03 04 05 06 07 8a | 12345678........
42 43 44 61 62 63 64                            | BCDabcd         
```

みたいに逐次追加で表示しようとしている時にtagを使ってみたので、そのメモ。

最初、『[詳解Tcl/Tk GUIプログラミング](https://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3Tcl-TkGUI%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E9%A0%88%E6%A0%97-%E6%AD%A9%E4%BA%BA/dp/4798000191/ref=sr_1_5?s=books&ie=UTF8&qid=1534951829&sr=1-5&keywords=tcl%2Ftk)』を参考に、textを2つとscrollbarを1つを横並びに配置して、一方に16進数、他方にASCII文字を追記しつつ、1つのscrollbarで両方のtextを同時スクロールするように作り初めたけど、scrollbar絡みのカラクリを理解しきれず訳が分からなくなってしまって挫折しました。

そこでtextとscrollbarはオーソドックスな1:1の関係のままとして、tagをプレースホルダ的に使う方法を考えてみました。

まずtextに16バイト分の空欄を作ります。この時、16進数表示用プレースホルダとしてHEX0, HEX1, ... HEX14, HEX15というtagを、ASCII表示用プレースホルダとしてASCII0, ASCII1, ... ASCII14, ASCII15というtagを付与しておきます。 

```tcl
# $window is path name of the text widget.
for {set i 0} {$i < 16} {incr i} {
    $window insert end "  " HEX$i
    $window insert end " "
}
$window insert end "| "
for {set i 0} {$i < 16} {incr i} {
    $window insert end " " ASCII$i
}
$window insert end "\n"
````

そして以下のように1バイトづつ追記していくと、いい感じに表示が更新されました。

```tcl
# $window is path name of the text widget.
# $lenght is number of shown data.
# $byte is new data.
set column [expr {$length % 16}]
incr length
binary scan $byte H2 hex
$window replace {*}[$window tag range HEX$column] $hex
if {[string is print $byte]} {
    set ascii $byte
} else {
    set ascii "."
}
$window replace {*}[$window tag range ASCII$column] $ascii
```

ここで意外だったのが、replaceでHEX1というtag範囲を置換するとHEX1というtagは範囲を失う(tagとしては存在し続ける)という挙動でした。

今回は別に実害は無いんですが、(labelウィジェットの-textvariableのように)何度も更新する値のためのプレースホルダとして利用したい場合はreplaceコマンドの引数でtagを再定義する必要がありそうです。
【Androidアプリ開発勉強】開発時にハマったこと(XAMLでデザイン編その2)

[前回](https://qiita.com/FORTE/items/550b0820f4798a9850de)に引き続き、
画面のレイアウト系のハマったところの備忘録です。
やっぱり触るといろいろ出てくるので、
このシリーズはまだ続くかも…。

# 前提環境(バージョンとか)

Android Studio Version 3.1.4
Windows 10 HOME Version 1803, OS build 17134.228

# ハマったこと

## TextInputEditTextが改行しちゃう
以下の設定を入れると改行できなくなる。
ただし、画面より長い量を入力すると改行したように見える。
`android:maxLines="1"`

また以下のようにするという記事も見たが、
自分は解決しなかった。

`android:scrollHorizontally="true"
android:ellipsize="start"`



## カーソルとか下線がピンクになる
[この記事](https://qiita.com/chiiia12/items/c02d00f7c4b70cf95a79)の機種によっての部分に、まさに当てはまって悩んでいた。
解決出来たのはこの記事のおかげ多謝。

自分は結果的にこうした。
 <android.support.design.widget.TextInputEditText
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:backgroundTint="@color/default_color"
  android:foregroundTint="@color/default_color"
  android:textCursorDrawable="@drawable/shape_cursor" />
【Access】Runtime版でのAccessの動作確認をしたいとき

Runtime版向けのAccessの開発をしているときに、AccessをRuntime起動して動作確認をする方法


- 対象
    - Runtime版向けのAccess VBAを開発していて、Runtime版をインストールした環境が用意できない人
        - （もしくは環境を用意するのが面倒くさい人）

- 動作環境
    - Windows10
    - Access2016

- 方法
    - 起動する対象のAccessファイルを以下のコマンドで実行する。
        - 頻繁に起動するファイルの場合は、ショートカットを作成し、リンク先を以下のコマンドに書き換えて利用したほうが便利です。
        - MSACCESS.EXEへのパスはインストールしているAccessのバージョンなどで差異があります。

```
  "Accessの実行ファイルのパス（MSACCESS.EXEへのパス。）"  /runtime "起動対象Accessファイルへのパス"
  例："C:\Program Files (x86)\Microsoft Office\root\Office16\MSACCESS.EXE" /runtime "C:\work\test.accdb"
```
【Python】関数呼び出しのコストを計測してみた

関数呼び出しのコストがどのくらいかかるかが気になったので。

```python:関数の準備
# ループ用のリスト
n = [0] * 10000000

# ループで毎回呼び出される関数
def test1():
    1 + 1

# 一度だけ呼び出されて中でループする関数
def test2():
    for _ in n:
        1 + 1
```

まずはループする度に関数を呼び出す場合。
実行する度に時間が異なったのでとりあえず3回実行。

```python:test1（ipython上で実行）
In [57]: %time for _ in n: test1()
Wall time: 1.42 s

In [58]: %time for _ in n: test1()
Wall time: 1.12 s

In [59]: %time for _ in n: test1()
Wall time: 1.18 s
```

次に一度だけ呼び出されて，関数内で同じ回数だけループする場合。
同様に3回実施。

```python:test2（ipython上で実行）
In [60]: %time test2()
Wall time: 362 ms

In [61]: %time test2()
Wall time: 176 ms

In [62]: %time test2()
Wall time: 225 ms
```


このケースだとざっくり3倍以上は違うようですね。
ループ等で何度も関数を呼び出している場合は，パフォーマンス向上のためにやり方を工夫する手もありそうです。
コンボボックスの中身を保持する方法

コンボボックスで選択された情報がAccess（データベース）へ登録され、その情報を表示する一覧画面があります。一度登録された情報を更新するために、更新ボタンを作成し、ページ遷移した時に、元々登録されたいた情報を保持したまま表示させたいのですが、どのようにしたらいいですか？（変更しない情報もある場合手間を省くため）

コンボボックスには２種類あり、１種類はベタ打ちで選択肢を記述したもの、もう１種はAccessにあるデータマスタからSQLで作られています。

ベタ打ちの方は

```asp
Quadruple(strItem,strA,strB,strC,strD,flg,ByRef obj)
    select Case flg
      select "0"
          strCheckA = "selected"
      select "1"
          strCheckB = "selected"
      select "2"
          strCheckC = "selected"
      select "3"
          strCheckD = "selected"
    End select
```
という関数で、

```asp
Call Quadruple("Item01","","A","B","C",DbCur.Fields(0).Value,obj)
```
で呼び出しているのですが、これは登録された情報を維持しながら表示させることができています。
しかし、もう一つのコンボボックスが同じようにできません。

```asp
Combo(strItem,strTable,strSdate,intChange,ByRef obj)
```
という関数で、

```asp
Call Combo("Item02","データマスタ",2003/11/11",True,obj)
```
で呼び出しています。しかし表示されるのは空白のコンボボックスです。

```asp
DbCur.Fields(1).Value
```
をどこかに入れないといけないのはわかりますが、どのようにすればいいのかわかりません。
もし何かヒントでもわかる方いましたらアドバイスお願いします。
TopCoder SRM 736 Div2 Hard MazeWithKeys

http://community.topcoder.com/stat?c=problem_statement&pm=14944


迷路探索の変形。「カギと扉」を追加。
カギ"a"をとると、扉"A"を開くことができる。

ゴールは固定、スタート位置となりうる点を探す。
条件として、扉を一度も開かずにゴールへ行ってはいけない。
カギがなくて扉を開けないのもダメ。

全部で90分かかった。
解法は20分で思いついたが実装に30分ぐらい掛かってしまい、
マップ全体が正方形だと思い込んで40分ぐらいデバッグしたのが痛い。

以下評価方法に従ってスタート地点候補を一つずつ評価する。

```
1. 候補地点から探索開始して、カギとゴールを取れる限り取得
2. その候補地点での初回での探索でゴールを見つけてしまったら失敗（条件に合わない）
3. 何も見つけられなかったら失敗（たどり着けない）
4. カギを見つけられたら、マップを更新して見つけられたカギと扉を消して、再度探索。
5. ゴールを見つけられたらスタート地点になりうる。
```

カギの種類はアルファベットの数だけなので最大26回ループ。
探索はN * M = 50 * 50 = 最大2500個
候補地点も同じく最大2500個

理論的には1億超えてしまうが実際の候補地点は壁があるので半分程度。
問題的にはどうにかなったっぽいが、チャレンジとかされたら多分ダメなんだろうな。
【Swift】 二次元配列をcsvに変換する。

【swift】 二次元配列のデータをcsvに変換してみました。
csvとは、エクセルやナンバーズなどの表計算ソフトの「m × n」表のもとになるデータ形式です。
csvは簡単に言うと「m × n」表を、一本の長〜い文字列（String）に変換したもので、隣り合うセルの区切りを \t （タブ）、改行を \n で表しています。
以下、二次元配列を twoDimArray, csvデータを csvString とします。

```swift
        var twoDimArray = [[String]]()
        for _ in 0 ... 2{
            twoDimArray.append([])
        }
        twoDimArray[0] = ["井上","加藤","田中"]
        twoDimArray[1] = ["鈴木","吉田"]
        twoDimArray[2] = ["遠藤","佐藤","村田","山田"]
        
        var csvString = ""
        for i in 0 ... 2{
            for name in twoDimArray[i]{
                csvString += name
                if name != twoDimArray[i].last{
                    csvString += "\t"
                }
                else{
                    csvString += "\n"
                }
            }
        }
        print(csvString)
```
コンソールには、以下のようにprintされます。
井上	加藤	田中
鈴木	吉田
遠藤	佐藤	村田	山田
これをコピーして、エクセルやナンバーズにペーストすると以下のようにセル毎に収まることがわかります。（上段：エクセル、下段：ナンバーズ）
※エクセルの場合、(右クリック＞形式を選択してペースト＞テキスト)とします。
![ArrayToCSV.gif](https://qiita-image-store.s3.amazonaws.com/0/193431/29387f3d-6d9b-3cc5-65e7-7142fd03f246.gif)
別テーブルの値で計算してCASEで評価するSQLを1文にまとめる

SQLの勉強をしている中で、中々手間取った上に記事にされてる方がいらっしゃらなかったので備忘録的にまとめておきます。

#目的
タイトルの通り、1文で、結合・計算・比較をしてしまおう

##例題
テーブル”売上表”とテーブル”商品情報”から
商品3つ"服(Cloth)""スカート(Skirt)""靴(Shoes)"が
１回の販売（伝票番号別）でそれぞれの目標販売額（ノルマ）を上回ったかを求める
なお、各テーブルと目標値は以下の通り
※（）内は型を意味しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/243794/d2dbfcda-358a-012a-cb89-fa2ed891d9eb.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/243794/36e2c812-1af2-0d0d-f965-43e6fb3b5d58.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/243794/5695b500-ad19-8cd7-4218-7b7498942c4c.png)

##欲しい結果
![image.png](https://qiita-image-store.s3.amazonaws.com/0/243794/91b67046-fdf6-4fb3-519e-6340f92794c2.png)

さて、概要の確認はOKでしょうか、ここからSQL組みます。

##SQLその1：まずはテーブルの結合と計算
```SQL
SELECT 売上表.伝票番号 , 売上表.数量 * 商品情報.価格 As "売上"
　FROM 売上表 LEFT JOIN 商品情報 ON 売上表.商品 = 商品情報.商品 ;
```
ここまでは普通の外部結合なので、いろいろなところで記事を見るかと思います。
これを実行すると

```SQL
伝票番号 ❘　売上  ❘
--------+--------+---
      1 ❘　40000 ❘　
      2 ❘　 4000 ❘　
      3 ❘　11000 ❘　
      4 ❘　20000 ❘
```
こんな感じになっているはずです。

##SQLその2：CASE式
CASEは式でありSELECT,FROM,WHERE,JOINなどの句ではない、という記述をよく見ますよね。
まぁそれは置いておいて、先ほどのノルマを式にします。

```SQL
SELECT CASE
WHEN 売上表.数量 * 商品情報.価格 >= 30000 THEN 'たくさん売れた！'
WHEN 売上表.数量 * 商品情報.価格 >= 10000 THEN 'そこそこ売れた！'
WHEN 売上表.数量 * 商品情報.価格 < 10000 THEN '全然ダメ'
END
```
これで評価はできます。
さて、このCASE式をどこに入れるかで少し時間を食いました。

##SQLその3：式を組み込み
その1とその2をくっつけます。

```SQL
SELECT 売上表.伝票番号 , 売上表.数量 * 商品情報.価格 As "売上"

(SELECT CASE
WHEN 売上表.数量 * 商品情報.価格 >= 30000 THEN 'たくさん売れた！'
WHEN 売上表.数量 * 商品情報.価格 >= 10000 THEN 'そこそこ売れた！'
WHEN 売上表.数量 * 商品情報.価格 < 10000 THEN '全然ダメ'
END)

　FROM 売上表 LEFT JOIN 商品情報 ON 売上表.商品 = 商品情報.商品 ;
```

ただ、これで実行すると以下のようになります

```SQL
伝票番号 ❘　売上   ❘  case
--------+--------+---------------
      1 ❘　40000  ❘　たくさん売れた！
      2 ❘　 4000  ❘　全然ダメ
      3 ❘　11000  ❘　そこそこ売れた！
      4 ❘　20000  ❘　たくさん売れた！
```

caseはノルマに変えたい！
そんなときはCASE式のEND以降に　AS **名称**　を付け加えます

```SQL
SELECT 売上表.伝票番号 , 売上表.数量 * 商品情報.価格 As "売上"

(SELECT CASE
WHEN 売上表.数量 * 商品情報.価格 >= 30000 THEN 'たくさん売れた！'
WHEN 売上表.数量 * 商品情報.価格 >= 10000 THEN 'そこそこ売れた！'
WHEN 売上表.数量 * 商品情報.価格 < 10000 THEN '全然ダメ'
END AS ノルマ)

　FROM 売上表 LEFT JOIN 商品情報 ON 売上表.商品 = 商品情報.商品 ;
```
これで実行するとこのようになるかと思います。

```SQL
伝票番号 ❘　売上   ❘  ノルマ
--------+--------+---------------
      1 ❘　40000  ❘　たくさん売れた！
      2 ❘　 4000  ❘　全然ダメ
      3 ❘　11000  ❘　そこそこ売れた！
      4 ❘　20000  ❘　たくさん売れた！
```

#まとめ

ポイントは通常のカラムはAS句で名称を変える場合、" "でくくらないといけませんが
CASE式にAS句で名称を変える場合はくくる必要がありません。
また、テーブルに保存されていない値で比較する場合は、上記のようにCASE式を、カラム名宣言するSELECT FROMの間に入れることで使えます。

お疲れさまでしたー。
[python]while文を使ったカウントアッププログラムにおけるbreakとcontinueの書く順番

# ①while文で1から10まで数えるカウントアッププログラムを書き、7に達したらbreakで繰り返しを止める

```python
val = 1
while val < 10:
    if val == 7:
        break
    print(val)
    val += 1

```


# ②while文で1から10まで数えるカウントアッププログラムを書き、7に達したら7をスキップして8からまたカウントアップを始める

```python
val = 0
while val < 10:
    val += 1
    if val == 7:
        continue
    print(val)
```

# 順番の違い、わかりました！？

この違いをどう受け止めて良いのか分からないけど、
ニュアンス的にはif文の中の処理を中心にコードを考える必要があって、
その違いによって周りの書く順番も変わってくるのかな？と考えています。

break処理は、
「とりあえず俺のことは一度if文ごと忘れてしまって、
その次の処理をやってくれ！繰り返してifの条件に合致してしまった時に気にしてくれ！」
という性質を持っている処理なのだと。

continue処理は、
「if文の前の`val + =1` と一体の処理として扱って下さい。`val + =1`と離れていたら動けないので。」
みたいな感じで、慣れていくしかないのかなと。

---

僕自身初学者なのでよくわかっていないけど、
プログラミングは数学の方程式にも似ているし英語の文法にも似ているので、
何故こうなのかと細かく理解しようとするよりまずは
「そういうもんなんだ」と受け入れていくしかないと
考えています。
Ubuntu18.04においてpyenvを用いたpythonインストール時に生じたBUILD FAILEDのエラーとその対処

### 変更記録
2018.8.22 設定がすべて完了するまでのプロセスを記述するためpyenvのシェル変数へのPATHの通し方を追記

### 概要
1. Ubuntu 18.04でpyenvを使ってpython3.6.6をインストールしようとしたところエラーが発生した
2. エラーメッセージにzlibが無いとのことだったのでこれをsudo apt-get install zlib1g-devでインストールした
3. Python3.6.6を無事にインストールできた


### 環境
Ubuntu 18.04.1 LTS

### 何をしたか
「PyenvによるPython3.x環境構築(CentOS, Ubuntu)」
https://qiita.com/akito1986/items/be5dcd1a502aaf22010b
の記事を参考に、以下のコマンドを実行（参考記事の環境にUbuntu14.04と書いてあったのを気にすればよかったとあとで思った... ）
途中でエラーが発生したため解決した。以下で手順を説明

#### 必要なファイルのインストール
（結論から言うとこれに足りないライブラリがあった）

```
$ sudo apt-get install git gcc make openssl libssl-dev libbz2-dev libreadline-dev libsqlite3-dev
```
#### pyenvをgithubからインストール
```
$ git clone https://github.com/yyuu/pyenv.git ~/.pyenv
```

#### pyenvのPathをbashrcを介して通す
```
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
$ echo 'eval "$(pyenv init -)"' >> ~/.bashrc
$ source ~/.bashrc
```
#### visudoでsudo時にも同じPathを使用するよう設定
詳細は[sudo時にPATHを引き継ぐ方法](https://qiita.com/akito1986/items/e9ca48cfcd56fdbf4c9d)
を参照すると良い

```
sudo visudo
```
を実行するとnanoで権限に関する重要なsudoresファイルを編集するモードになる。この中で以下のように書き換えた。

```
#Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin
Defaults    env_keep += "PATH"
Defaults    env_keep += "PYENV_ROOT"
```
\#はコメントアウトを表す。何もしていなければ1行目に該当する部分がコメントアウトされずに存在しているのでこれをコメントアウトし2・3行目を追加した。
ctrl+Oで保存、ctrl+Xで終了。（nanoでの操作に慣れていないためググった）

#### pythonインストールを試みる

```
sudo pyenv install 3.6.6
```
#### エラー発生

```
$ sudo pyenv install 3.6.6
Downloading Python-3.6.6.tar.xz...
-> https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tar.xz
Installing Python-3.6.6...

BUILD FAILED (Ubuntu 18.04 using python-build 1.2.7-1-g71902168)

Inspect or clean up the working tree at /tmp/python-build.20180822214932.20950
Results logged to /tmp/python-build.20180822214932.20950.log

Last 10 log lines:
    sys.exit(ensurepip._main())
  File "/tmp/python-build.20180822214932.20950/Python-3.6.6/Lib/ensurepip/__init__.py", line 204, in _main
    default_pip=args.default_pip,
  File "/tmp/python-build.20180822214932.20950/Python-3.6.6/Lib/ensurepip/__init__.py", line 117, in _bootstrap
    return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
  File "/tmp/python-build.20180822214932.20950/Python-3.6.6/Lib/ensurepip/__init__.py", line 27, in _run_pip
    import pip._internal
zipimport.ZipImportError: can't decompress data; zlib not available
Makefile:1103: recipe for target 'install' failed
make: *** [install] Error 1
```
エラーメッセージ中に

```
zipimport.ZipImportError: can't decompress data; zlib not available
Makefile:1103: recipe for target 'install' failed
```
とあったのでこれをインストール

```
sudo apt-get install zlib1g-dev
```

そして再度

```
sudo pyenv install 3.6.6
```
にて無事にインストールができた。
あとはpyenvの使い方に従ってglobalで3.6.6が効くようにしたり自分好みに設定すると良い。
DockerでWekanを試す時に注意すべきこと

# Wekanはシンプルで使いやすそう？
Wekanの記事を見て使ってみよう、という気分になったので、以下のページを参考に立ててみました。
[Install Wekan Docker for testing](https://github.com/wekan/wekan/wiki/Install-Wekan-Docker-for-testing)

でもConnection Refusedで応答しない。
`docker logs`とかでログを見る限り正常に動作してるっぽい。

・・・実はポート80番ではなく8080番で受け付けていたようです。
確かに[dockerfile](https://hub.docker.com/r/wekanteam/wekan/~/dockerfile/)を見てみると8080番しか開いていませんでした。

以下の記事で気づきました。ありがとうございます。
[Wekan を Docker で起動しようとしても起動しない（アクセスできない）場合 - 約束の地] (https://obel.hatenablog.jp/entry/20180817/1534505889)


# 実行環境
- OS: Ubuntu 18.04.1 LTS
- Wekan: たぶんv1.34(実際にはlatestを使用しているため)

# 修正後
というわけで、修正した`docker-compose.yaml`です。(外部のポートは80番で公開するようにしているので必要に応じて変更してください。)
**localhostの部分はホスト名に書き換えておかないと外からアクセスした際に一部が動作しません。**

``` yaml:docker-compose.yaml
version: '2'
services:
  wekan:
    image: wekanteam/wekan:latest
    links:
      - wekandb
    environment:
      - MONGO_URL=mongodb://wekandb/wekan
      - ROOT_URL=http://localhost:80
    ports:
      - 80:8080

  wekandb:
    image: mongo:3.2.14
    volumes:
      - ./data:/data/db
```

dockerを最近あまり使ってなかったからはまってしまった。

# ちなみに(ポート番号の確認と確信した理由)
どのポートがあいているかは `docker ps`の`PORTS`で確認が可能なので、こちらを参考にするといいと思います。

```:修正前
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                          NAMES
5c0a9197a856        wekanteam/wekan:latest   "node /build/main.js"    6 seconds ago       Up 5 seconds        0.0.0.0:80->80/tcp, 8080/tcp   wekan_wekan_1
b2c28e9122c9        mongo:3.2.14             "docker-entrypoint.s…"   32 minutes ago      Up 2 minutes        27017/tcp                      wekan_wekandb_1
```

- なにやら`8080/tcp`というポートが内部ネットワーク向けに開いているけど、外部には公開されていないよ？
  - 8080が実際の受付ポートでした。
- じゃあ、`0.0.0.0:80->80/tcp`は？
  - docker-compose.yamlで指定されている公開ポートで、内部では実は開いていませんでした。
- MongoDBは外部に公開しないため、`27017/tcp`だけで問題ありません。

```:修正後
CONTAINER ID        IMAGE                    COMMAND                  CREATED              STATUS              PORTS                  NAMES
0e25b88cdb31        wekanteam/wekan:latest   "node /build/main.js"    About a minute ago   Up About a minute   0.0.0.0:80->8080/tcp   wekan_wekan_1
b2c28e9122c9        mongo:3.2.14             "docker-entrypoint.s…"   31 minutes ago       Up About a minute   27017/tcp              wekan_wekandb_1
```

# これから
RedmineでToDo管理をやっているのですが、正直ドロップダウンの選択やチケット作成やステータス変更とかが面倒で・・・。
これが代替にならないか試してみようと思ってます。
記録としては汎用性に乏しい感じになりそうだけど、続けるほうがもっと大事なので。
Windowsで多段ssh先のディレクトリをsshfsで手元にマウントする



# 導入
## Sshfs Managerを入れる
[導入手順外部リンク](http://www.maruko2.com/mw/Windows_%E3%81%A7_sshfs_%E3%82%92%E5%88%A9%E7%94%A8%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95)
これを入れるとタスクバーに常駐する。
![taskbar.png](https://qiita-image-store.s3.amazonaws.com/0/45682/3497931c-d937-5f74-0a50-9e2b7c23f355.png)
アイコンをクリックして設定する(赤字の変数は後述)
![sshfs_manager.png](https://qiita-image-store.s3.amazonaws.com/0/45682/1d941633-a788-9286-3f5a-18800129721e.png)
### 備考:失敗したsshfsクライアント
[billziss-gh/sshfs-win](https://github.com/billziss-gh/sshfs-win)

* powershellからProgram Files/SSHFS-Win/bin/sshfs.exeを直に叩く
    * オプションの書式が違うって怒られた
* SiriKali(↑のGUIフロントエンド)
    * CreateVolume→Sshfsで設定入力してAdd押したのに反映されない
    * そもそも設定にdomain欄はあってもport欄がない

## シェルスクリプト
springboardに手作業でsshして下を実行してみて怒られたら$springboard_portを空いているポートに変えてください。

```terminal
 $ ssh -fNL ${springboard_port}:localhost:${target_port} ${target_user}@${target_domain}
bind: Address already in use
channel_setup_fwd_listener: cannot listen to port: 10023
Could not request local forwarding.
```
### init_sshfs.sh
```bash
#!/bin/bash
target_domain=''
target_user=''
target_port=22
springboard_domain=''
springboard_user=''
springboard_port=10023 #適当な空いているポート
client_port=10022 #適当な空いているポート

ssh ${springboard_user}@${springboard_domain} \
	"ssh -fNL ${springboard_port}:localhost:${target_port} ${target_user}@${target_domain}"
ssh -fNL ${client_port}:localhost:${springboard_port} ${springboard_user}@${springboard_domain}
```

- WSLに↑のinit_sshfs.shを保存してchmod +xしておく
    - もしWSLが使えない場合は[Win32-OpenSSH](https://github.com/PowerShell/Win32-OpenSSH/releases)を使う
- {target,springboard,client}_{domain,user,port}の変数を書き換えておく
- 踏み台サーバーにsshできるよう~/.ssh/を設定しておく

### 動作原理
ssh のポートフォーワードを利用している。sshでアクセス可能なら任意のポート同士をつなげることができる。
今回はtargetの22番ポートを踏み台を経由してlocalの10022ポートにつないでいる。
[詳しい解説:京大マイコンクラブ 楽しいトンネルの掘り方](https://www.kmc.gr.jp/advent-calendar/ssh/2013/12/09/tunnel2.html)
![範囲を選択_001.png](https://qiita-image-store.s3.amazonaws.com/0/45682/f74ff455-9f10-4caa-efcc-be5a345ca345.png)

# 実行
- 先にinit_sshfs.shを実行する
- Sshfs Managerから設定したドライブへMountする
- エクスプローラからマウントしたドライブが確認できれば成功

# 後始末
- Sshfs ManagerからUnMountする
- WSLでpgrep -a sshして-fNLオプションのをkillする
    - 踏み台にsshして同様にkillする

後始末もスクリプト書いて自動化したいんですが、killallでオプションとか全一致で殺せませんかね…
後輩たちのためのEV3rt講座①(プログラム編集の準備)

今回は実際にプログラムを書くにあたって知っておきたいことなどを書きます。
#①プログラムのファイル構成#
##基本構造##
![スクリーンショット 2018-08-20 00.16.36.png](https://qiita-image-store.s3.amazonaws.com/0/183170/5b3285db-fc0b-f2b1-6be8-29dc34e73995.png)
`[任意のフォルダ名]`
┣`app.c`
┣`app.h`
┣`app.cfg`
┣`Makefile.inc`
≈≈≈≈≈≈
┗`(任意のヘッダーファイル)`
##それぞれの説明##
###[任意名のフォルダ]###
上記の4つ(もしくはそれ以上)のファイルを束ねるフォルダ。
ここでつけた名前がコンパイル時に必要となる。
###app.c###
**根幹となるファイル。**ここの`main_task()`内にプログラムを書き込む。
また、その他にも変数の定義、includeの処理、関数を書くなどする。
ここに書きすぎて長くなった場合は、ヘッダーファイルを利用して分けることができる。
EV3教育ソフトウェアでいうところの"マイブロック"みたいなもの
詳しくは後ほど。
###app.h###
プログラムを動かすために必要な**裏方的存在**のファイル。
新たなタスクやサイクルハンドラを作るときはこのファイルをいじる必要がある。
###app.cfg###
上記app.h以上に**裏方感増し増し**のファイル。
しかし同様に、新たなタスクやサイクルハンドラを作るときはこのファイルをいじる必要がある。
###Makefile.inc###
もはやなんのファイルかわからないくらいのファイル。
**秘密の魔法**みたいなもん。
いじることは基本的にない。
###ヘッダーファイル###
`XXX.h`のような名前のファイル。

```c:app.c
#include "XXX.h"
```

のように書くことで、app.c内にXXX.hのソースコードを導入できる。

#②プログラムを書く準備#
app.cを書くときに、絶対に書いておかないといけない情報があります。
##書かないとダメ度★★★★★##
```c:app.c
#include "ev3api.h" //絶対必要
#include "app.h"//絶対必要
#include <stdio.h>

#if defined(BUILD_MODULE)
#include "module_cfg.h"
#else
#include "kernel_cfg.h"
#endif

#define DEBUG

#ifdef DEBUG
#define _debug(x) (x)
#else
#define _debug(x)
#endif
```

これですが、サンプルファイルからコピーしたときからあります。
どうも消してはいけないっぽいです。
これだけはmain_taskを書く前に必ず書きましょう。
##書かないとダメ度★★★★☆##
```c:app.c
void main_task(intptr_t unused)
{
    /* コンフィグゾーン　*/
    ev3_motor_config (0, LARGE_MOTOR);
    ev3_motor_config (1, LARGE_MOTOR);
    ev3_motor_config (2, MEDIUM_MOTOR);
    ev3_motor_config (3, LARGE_MOTOR);
    
    ev3_sensor_config (0,COLOR_SENSOR);
    ev3_sensor_config (1,COLOR_SENSOR);
    ev3_sensor_config (2,COLOR_SENSOR);
    ev3_sensor_config (3,COLOR_SENSOR);
```
このmain_taskが始まってすぐのところの`コンフィグゾーン`ですが、ここではEV3に接続するセンサー・モーターを書き込んでおきます。ここに書いたセンサー・モーターの通りに接続しないと、ロボットは全く動きません。
今回の例では、

| ポート | 接続物 |
|:-:|:-:|
| A | Lモーター |
| B | Lモーター |
| C | Mモーター |
| D | Lモーター |
| 1 | EV3カラーセンサー |
| 2 | EV3カラーセンサー |
| 3 | EV3カラーセンサー |
| 4 | EV3カラーセンサー |
のように接続しています。

##書かないとダメ度★★☆☆☆##
これを知ったとき私は衝撃でしたが…
実はEV3rtでの標準Cライブラリは、変数型の**bool**を使うことができません!!
でも

```c:app.c
#include <stdbool.h>
```

これで使えます。

##書かないとダメ度★☆☆☆☆##
もはや**「書いたら便利じゃね？」**くらいの提案みたいなもんです。

```c:app.c
while (ev3_button_is_pressed (4)==false){//真ん中ボタンが押されるまで
    sprintf(str,"%d",ev3_battery_current_mA());//バッテリーからmAの情報を取得
    ev3_lcd_draw_string(str,0,0);//LCDに書き込む
    sprintf(str,"%d",ev3_battery_voltage_mV());//バッテリーからmVの情報を取得
    ev3_lcd_draw_string(str,0,20);//LCDに書き込む
}
```

これをコンフィグゾーンの直後に書くことで、プログラム開始前にバッテリー残量を確認できます。

#③コンパイルのやり方#
EV3でプログラムを動かすにあたって、人間語を機械語に変換する必要があります。
これをコンパイルといいます。
EV3rtは動的ローディング式とスタンドアローン式の2つがあります。
詳しい説明は長くなるので省略しますが、動的ローディングの方が扱いやすいので、今回はこちらでいきます。[(詳しくは公式ページで確認)](https://dev.toppers.jp/trac_user/ev3pf/wiki/SampleProgram#サンプルアプリケーションのビルドと実行)

さてまずはターミナル・Cygwinを起動します。
で、ディレクトリを`ev3rt/hrp2/sdk/workspace`に移動します。
そして、コンパイルしたいプログラムのフォルダ名を使ってコンパイルします。

```
$ cd 〜./ev3rt/hrp2/sdk/workspace/
$ make app=[フォルダ名]
```


これで`workspace`に**app**というフォルダが作られているはずです。

#まとめ#
今回はプログラムを本格的に書くにあたっての準備的なことをしました。
次回からは本題に入っていきたいと思います。

次回:[第2回](https://qiita.com/koushiro/items/46b6a9a29df6d459a6e7)
前回:[第0回](https://qiita.com/koushiro/private/b19a9cce16d2a77e53d3)
【もくじ】後輩たちのためのEV3rt講座

今までの**「後輩たちのためのEV3rt講座」**の投稿をまとめたページです。
このシリーズはあくまで中学・高校生向け(特にうちの部員)に書いております。
初心者の方にでもわかりやすいように努めています。
逆に言うと、物足りない、しょうもない説明が過剰と感じるかもしれませんが、ご了承ください。

###[**第0回 開発環境構築編**](https://qiita.com/koushiro/private/b19a9cce16d2a77e53d3)###
###[**第1回 プログラム編集の準備**](https://qiita.com/koushiro/private/a3fb52f0f1c17f2b1670)###
###[**第2回 モーターを動かす**](https://qiita.com/koushiro/private/46b6a9a29df6d459a6e7)###
###[**第3回 センサーを使う-①**](https://qiita.com/koushiro/items/97d08cf3d863d6f81f2e)###
###[**第4回 センサーを使う-②**](https://qiita.com/koushiro/items/d7fe9cf4f116d1f4f470)###
###[**第5回 インテリジェントブロック**](https://qiita.com/koushiro/items/1845f60c26573db3a9a8)###
###[**第6回 関数を使う**](https://qiita.com/koushiro/items/bd081f0613077addb88d)###
###[**第7回 ファイルを扱う-fprintf**](https://qiita.com/koushiro/items/3d7911b4d6a9477904e1)###
###[**第8回 タスク・周期ハンドラ**](https://qiita.com/koushiro/items/22a10c7dd451291fd95b)###
###[**第9回 Bluetooth環境開発**](https://qiita.com/koushiro/items/578a1d65721b982c55c6)###
###[**第10回 Bluetooth通信実践**](https://qiita.com/koushiro/items/e985c953116c0399bd47)###
###[**第11回 UART通信**](https://qiita.com/koushiro/items/b7a66f0b3c0d7695b53a)###
###[**番外編 HiTechnicカラーセンサーについて**](https://qiita.com/koushiro/items/058c1f18a5f5282e2817)###
###[番外編 EV3シリアルコンソールを起動してみた](https://qiita.com/koushiro/items/772dca79b25ed4e5bfbe)###

また、質問・要望に関しては下記ページからどうぞ
[質問・要望フォーム](https://docs.google.com/forms/d/e/1FAIpQLSfAtlwMKRC7Vx2d94VdgGzG-8WlKJz0UbfiyhxTywevrA-eiA/viewform)
ノンエンジニアにITシステムを説明する方法

#ITシステムとは?
![Screen Shot 2018-08-22 at 4.43.23 PM.png](https://qiita-image-store.s3.amazonaws.com/0/242700/0d62cfd2-510e-5845-8ae2-2d5342901054.png)

#エンジニアが考えていることとは?
![Screen Shot 2018-08-22 at 4.43.40 PM.png](https://qiita-image-store.s3.amazonaws.com/0/242700/45ff4ba7-5b43-4b4e-bbf4-0a93ad25ae7a.png)

#そもそもエンジニアリング(工学)とは?
####「数学と自然科学を基礎とし、ときには人文科学・社会科学の知見を用いて、公共の安全、健康、福祉のために有用な事物や快適な環境を構築することを目的とする学問」

#【参考】
xOps: エンジニアがスタートアップの成長の原動力となる日
https://www.slideshare.net/takaumada/xops

#雑感
DevOpsだけでなく、xOpsの世界が広がって高速に社会実装できる世界になると良いと思う。
RHELインスタンスだとyumが使えない？

# RHELインスタンスだとyumが使えない
という情報をちょっと聞いたので調べてみました。
そのとき得た知見を残しておきます。

# とりあえず試してみる
使用したAMIはAmazon Linux 2 AMI (HVM), SSD Volume Typeです。
EC2ダッシュボードからREHLのAMIを選んでEC2を作成してyum updateしたら
普通にできました。
はて、、、

# RHELインスタンス→スナップショット→AMI→インスタンス作成
調べてみると上記の方法で作成したインスタンスだとyumが使えないという情報を得たので
こちらも試してみました。

確かにこのフローで作成したインスタンスでyumコマンドを使うとエラーになりました。
「Authorization Required」と言われているので認証が必要らしいです。

```shell-session
[admin@ip-10-0-1-10 ~]$ sudo yum search tomcat
Loaded plugins: amazon-id, rhui-lb, security
https://rhui2-cds02.ap-northeast-1.aws.ce.redhat.com/pulp/repos//rhui-client-config/rhel/server/6/x86_64/os/repodata/repomd.xml: [Errno 14] PYCURL ERROR 22 – “The requested URL returned error: 401 Authorization Required”
Trying other mirror.
https://rhui2-cds01.ap-northeast-1.aws.ce.redhat.com/pulp/repos//rhui-client-config/rhel/server/6/x86_64/os/repodata/repomd.xml: [Errno 14] PYCURL ERROR 22 – “The requested URL returned error: 401 Authorization Required”
Trying other mirror.
Error: Cannot retrieve repository metadata (repomd.xml) for repository: rhui-ap-northeast-1-client-config-server-6. Please verify its path and try again
```

作成フローが違うと何が変わってくるのか。

# 原因
メタデータが抜けるのが原因とのことなのでメタデータを確認してみます。
最初にたてたインスタンスと比較すると「billingProducts」の値が「null」になっていました。


```shell-session:スナップショット→AMI→インスタンスで作成した場合のメタデータ

[admin@ip-10-0-1-10 ~]$curl http://169.254.169.254/latest/dynamic/instance-identity/document
{
  "devpayProductCodes" : null,
  "marketplaceProductCodes" : null,
  "privateIp" : "10.0.1.10",
  "version" : "2017-09-30",
  "instanceId" : "i-01cfe26787cd7538f",
  "billingProducts" : [ "null" ],
  "instanceType" : "t2.micro",
  "availabilityZone" : "ap-northeast-1d",
  "kernelId" : null,
  "ramdiskId" : null,
  "accountId" : "554447165874",
  "architecture" : "x86_64",
  "imageId" : "ami-6b0d5f0d",
  "pendingTime" : "2018-08-11T05:28:17Z",
  "region" : "ap-northeast-1"
```

```:通常のRHELインスタンスのメタデータ（billingProducts抜粋）
"billingProducts" : [ "bp-6fa54006" ]
```

# billingProductsとは
ライセンス情報（請求コード？）がここに入ります。
スナップショットからAMIを作成するとライセンス情報が保持されないため、起動後のパッケージ更新等が
出来なります。


# 対策
AMIの作成には以下の二通りがありますが、EC2から直接AMIを作成することで今回の事象を回避することができるそうです。
- EC2から直接AMIを作成する
- スナップショットからAMIを作成する

公式でもスナップショットから手動でAMIを作成することは勧めていませんとありました→[AMI作成について](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/creating-an-ami-ebs.html#how-to-create-ebs-ami)
ライセンス周りの話なので他の商用のディストリビューションでも同様の事象が起こりそうですね。


# 参考
以下のリンクを参考にさせていただきました。

- [redhat instanceでyumが使えない！](https://www.skyarch.net/blog/?p=1367)
- [AWSでWindowsのAMIを作る場合、スナップショットからやるとハマる](https://qiita.com/hotta/items/e55bba9e15f61128e5ea)
- [AWSディスカッションフォーラム](https://forums.aws.amazon.com/thread.jspa?messageID=443651)