OmniAICreator/Qiita-1.07M huggingface dataset:
Checkboxのトグルスイッチをシンプルに書く

こんにちわ。

作成中のWebページでトグルスイッチを実装しようと調べていた所...
いずれの解説サイト様も参考にはなったのですが、親要素やセレクタが複雑な構造をしていて、素人には難解でした。

と言う事で、勉強も兼ねて、自力で出来るだけシンプルにトグルスイッチを実装してみようと思います。


# 書いてみる
## HTML
```html:Main
<input type="checkbox" id="mycheck"/>
<label class="check" for="mycheck"><div></div></label>
```
たったこれだけ。
`<div>`や`<label>`で囲う必要は一切ありません。
`<label>`を`for="id"`無しで囲うのは精神衛生的に良くないですからね...


## CSS
```css:Checkbox本体を隠す
input[type="checkbox"] {
    display: none;
}
```
どうぞ隠れて下さい。

```css:基本設定
input[type="checkbox"] + label.check {
    position: relative;
    cursor: pointer;
    display: inline-block;
    width: 60px;
    height: 28px;
    color: #969696;
    border: 1px solid #a3a3a3;
    border-radius: 3px;
    background-color: #ffffff;
}
```
ポイントは`position:relative`で、この要素を基準として子要素の位置が調整出来るようになります。
`width/height`を変更すると、トグルスイッチの大きさを調整出来ます。

```css:チェック時の基本設定
input[type="checkbox"]:checked + label.check {
    border: 1px solid #4db4e4;
    background-color: #4db4e4;
}
```
チェック時は枠線もON色にする事でイマドキさがUP(?)

```css:擬似要素(OFF文字)
input[type="checkbox"] + label.check::before {
    content: "OFF";
    position: absolute;
    top: 4px;
    left: auto;
    right: 6px;
}
```
```css:チェック時の擬似要素(ON文字)
input[type="checkbox"]:checked + label.check::before {
    content: "ON";
    position: absolute;
    left: 6px;
    right: auto;
    color: #ffffff;
}
```
`::before/::after`は独立した要素として機能します。
なので`label::before`を`position:absolute`にしても、`label`自体には影響ありません。
結果、`label`基準で文字位置だけを自由に調整出来ます。

```css:トグル部品
input[type="checkbox"] + label.check > div {
    position: absolute;
    top: 2px;
    left: 2px;
    width: 12px;
    height: 22px;
    border: 1px solid #a3a3a3;
    border-radius: 3px;
    background-color: #ffffff;
    transition: 0.2s;
}
```
```css:チェック時のトグル部品
input[type="checkbox"]:checked + label.check > div {
    border: 1px solid transparent;
    left: 44px;
}
```
これも`position:absolute`とする事により、`label`基準で位置調整が可能になります。
`width/height`は、可動部の大きさになります。
`left`を非チェック時とチェック時で別々にする事で、移動させています。
`transition`で遷移時間を遅延させる事により、スライド感が増します。
しかし、あまり遅延させすぎるとUXが損なわれかねないので程々に。

px単位でサイズ決め打ちなので、長さや大きさを変更する時は、移動距離や余白調整に多少のカットアンドトライが発生してしまいますが、まぁトグルスイッチなんて1個作ってしまえば使い回せるので大丈夫でしょう(適当)


# 完成
![toggle.gif](https://qiita-image-store.s3.amazonaws.com/0/253070/16244a40-2925-3844-6d08-13c3465bfc43.gif)
イマドキっぽいオシャレなトグルスイッチが出来上がりました!


# おわりに
CSSは記述多めでしたが、1個ずつ見ていけば、意外と大した事はありませんでした。
かなりシンプルに仕上られたと思います。
エピソードを使ったINTER-Mediatorのハンズオン 3 - 機能拡張 (バリデーション)

#はじめに
大勉強会のハンズオンのエピソードです。全員でエピソードに沿ってハンズオンを行います。マシンは各自持参したマシンかイベントで用意したマシンを1名1台使用します。

『[エピソードを使ったINTER-Mediatorのハンズオン 1 - 基本機能](https://qiita.com/motofumi/items/4aa15b519285e5a8fa55)』を拡張します。前段階で作成した、『page02.html』と『def02.php』をそれぞれ、『page04.html』と『def04.php』にコピーして機能拡張します。

ここでは、バリデーションを追加して入力支援できるようにします。

#シナリオ
##背景
外回り営業マンに完成したWebアプリを見せたら、機能は満たしているので合格でした。ただ、入力支援の機能や件数がふえてきたら検索や集計ができると助かるとのこと。つまり、機能拡張の依頼です。

![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f35343433392f37653835376639322d666239322d316536612d376339392d3438373532633736623364642e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/54439/0f1d263f-7208-bbe0-408d-6ee4d57de650.png)

##機能拡張(バリデーションを追加する)
データの型の整合性を取るために、日付と出金の値のチェックをとる機能を実装します。



# 課題
コンテキストの『Validation』キーを指定することによってバリデーションを設定できます。『Validation』キーには、『field』、『rule』、『message』、『notify』の要素があります。

## 課題1: 日付の入力を『yyyy-mm-dd』にバリデーションで限定する

手順1: 『def04.php』を開き、『Show All』をクリックする。

![スクリーンショット 2018-07-30 13.38.24.png](https://qiita-image-store.s3.amazonaws.com/0/54439/51e93c9d-42fe-edbf-c325-88278d16a229.png)

手順2: 『validation』をクリックする。

![スクリーンショット 2018-07-30 13.38.37.png](https://qiita-image-store.s3.amazonaws.com/0/54439/5dad7453-4a02-4307-0634-24cf5eb5abf6.png)


手順3: 『validation』へ値を追加する。

```text:Validationの値
field: date
rule: test(value, '^([0-9]{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$')
message: YYYY-MM-DDの形式(半角)で入力してください
notify:
```

手順4: いろいろな日付を入れてみる

ここでは、全角で、『２０１８−０７−３０』と入力。正規表現にマッチしないので、『YYYY-MM-DDの形式(半角)で入力してください』と表示される。

<img width="1558" alt="スクリーンショット 2018-07-30 15.45.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/54439/84b5b91a-b1d3-46a5-e3ec-b8ee799f12b9.png">



## 課題2: 出金の入力を『整数』にバリデーションで限定する

手順1: 『Validation』へ値をもう一つ追加する。

![スクリーンショット 2018-07-30 15.51.29.png](https://qiita-image-store.s3.amazonaws.com/0/54439/a6a04180-aa01-6abe-7317-8493eca4fe2d.png)



手順2: 『Validation』へ値を追加する。

```text:Validationの値
field: withdraw
rule: test(value, '^[0-9]+$')
message: 正整数(半角)で入力してください
notify:
```

<img width="1539" alt="スクリーンショット 2018-07-30 15.57.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/54439/b17ce806-2278-0277-be49-91efb957e20c.png">
W10+Anaconda2+pythonOCCでビュワーがフリーズする問題の場当たり的解決策

#これはなに
講義でAnaconda2+pythonoccを扱うことになった．環境は，Anaconda2+pythonocc0.16.1．
Anacondaに含まれるSpyder2.7からスクリプトを走らせ，pythonoccのビュワーを起動しようとしたところ画面がイニシャライズされるところでフリーズしてしまった．

##対策
Githubのコミュニティに該当issueを発見．
https://github.com/tpaviot/pythonocc-core/issues/408

https://github.com/tpaviot/pythonocc-core/issues/408#issuecomment-333499160
"Interactively"ってなんだ？？？

スタート->Anaconda->Anaconda commmand promptから`ipython src.py`ではうまく走らない．`ipython`から`run src.py`とすると走った．

もしくは，`python -i ($src.py)`として実行後にインタラクティブモードに移行させるとうまく走る．この方法はSpiderのpython consoleでもうまくいくようだ．

フリーズしたらプロンプトでエンターを押すとだいたい動く．動かないときもある．

##原因
上のissueを見ると，IfcOpenShellの中で無限ループに入ってる，という記述があったがどこのことかよくわからない．
講義レポートをやっつける用なのでこれ以上の深入りはしないことにした．
Ethereum gas priceの計算

# GasPriceのestimate
Ethereumのgas priceはその時の状況に応じて変化します。
そのため、Gaspriceの適正値を探すことはとても重要です。

そこで、gas priceのestimateに使えるAPIを探してみました。

※2018年7月30日時点での調査結果です。  

## 調査方法
[ethgasstation](https://ethgasstation.info/index.php)のウェブサイトの  
- SafeLow (<30m)
- Standard (<5m)
- Fast (<2m)  

をベースに考えてみました。


|SafeLow|Standard|Fast|
|:---:|:---:|:---:|
|1.1|1.1|4|

### [ethgasstation](https://ethgasstation.info/index.php)  
有名なEthGasStationが提供しているAPIです。  
https://ethgasstation.info/json/ethgasAPI.json

|SafeLow|Standard|Fast|
|:---:|:---:|:---:|
|11|11|40|

APIは、ウェブサイトと比べて10倍大きいです。

### [mycrypto](https://mycrypto.com/account)  
myetherwalletと分裂したmycryptが用いているapiです。  
[ソースコード](https://github.com/MyCryptoHQ/MyCrypto/blob/develop/common/api/gas.ts)  
https://dev.blockscale.net/api/gasexpress.json

|SafeLow|Standard|Fast|
|:---:|:---:|:---:|
|1|1|4|

大体Ethgasstationのウェブサイトの値と同じくらいです。

### [etherchain.org](https://www.etherchain.org/)
ethgasstationの[gas price oracle](https://github.com/ethgasstation/gasstation-express-oracle)を元に取得しています  
https://www.etherchain.org/api/gasPriceOracle  

|SafeLow|Standard|Fast|
|:---:|:---:|:---:|
|1|1.001|3.1|

大体Ethgasstationのウェブサイトの値と同じくらいです。

## 結果
現時点で、ethGasStationのgas価格が高すぎるので、GasPriceの算出には他のAPIを利用することを検討に入れてもいいかなと思います。
TECHPLAY女子部：私がエンジニアになるまでLT大会♡に参加してきた

TECHPLAY女子部でLTしてきました！人生初の外部LT。緊張した。

## 勉強会概要

* [【再増枠】TECH PLAY女子部♡今の自分が一番好き！私がエンジニアになるまでLT大会♡ ](https://techplay.jp/event/681282)
* [togetter](https://togetter.com/li/1250508) 

当日の雰囲気はtogetterみてもらうとよくわかるかと思います！
ゆるふわな感じで、女の子50人くらい？いて、超いい感じ（雑


会場のみなさんも席のみなさんも運営のみなさんもすごく優しくて
おかげで発表もしやすかったし、懇親会でもいろいろお話できました＼(^o^)／

女子エンジニアがめっちゃたくさんいて、どなたのお話も面白くて、
ほんとうにあっという間の時間でしたー
いろんな名言とかたくさん飛び出した気がしてる（togetterとかレポブログ参照）

女子系のイベント過去にも行ったことありますが、そのたびに自分がいる世界は狭い世界だと実感しますね。


## 発表スライド

せっかくなので発表資料あげました。（web公開用にNG箇所ちょっといじってます）
QiitaがGoogleスライドの埋め込みできないので
今回はじめてslideshareとかいろいろ調べてやってみた。
読み込み早いのでspeakerdeckにしました。

[speakerdeck：20180724 TECHPLAYgirls「私がエンジニアになるまで」LT大会_LT06](https://speakerdeck.com/chamma___/20180724-techplaygirls-si-gaenzinianinarumade-ltda-hui-lt06)
![スライド](https://qiita-image-store.s3.amazonaws.com/0/36590/1925e84f-3874-56ee-ec65-14e926c26fd2.png)


きっかけの話を結構ふざけて紹介させてもらってますがｗ、
社長には人生を変えてもらったのでほんとに感謝以外の言葉はないです。

やりたくて始めた仕事じゃなくても
こうやって素敵な仕事と思えるものに出会えることもあるし、
その選択がまた新たな道に繋がっていくこともあるし、
今日の発表が誰かのちょっとした選択の後押しになったら嬉しいなと思って話しました。

当日、どなたかがつぶやいておられましたが、
今日の発表聞いてると1つ1つの決断って実はそんな重要じゃないんじゃ？？というような言葉があって（うろ覚え）
それにはとても共感したりしてます。
とりあえずやってみるとか飛び込んで見るとか、自分が大事にしてることだったりしてます。

あと、LINE APIのやつもまた時期をみてアップします！
これはちょっと頑張ったやつなので。。笑

## まとめ

* LT出るの初めてだったけど、発表するといろいろな方からお声掛けしてもらえたり、話が広がったりというのが嬉しかった
    * いつもイベント行くと人見知りでなかなか輪に入っていくの勇気いたりして。。
* 登壇者の方の中には、起業されたりフリーランスで働いておられたり…という方たくさんいたが、登壇者以外でも同じテーブルの半分の方が起業されてて、女子強い！と思った。みんなバイタリティすごい。
* 後日談ですが、名刺交換した方や連携先交換した方からメッセージいただいて、またお会いすることになったりと、今回のイベントをきっかけに自分の世界が1.5倍広がった気がする
* なんとなく関西弁多かった気がする

ということで、また女子部イベントあればぜひ参戦してみたい(｀･ω･´)！
あと今回のイベントテーマがエンジニア人生という、非技術寄りだったので
次はもっと技術的なことなども、どこかでアウトプットしたり情報交換していきたいと感じました。

とくに、マーケの領域のエンジニア寄りデータ分析になると
なかなかそこ専任でやってる方との出合いまで漕ぎ着けられてなかったりして
もう一歩世界を広げたいなと思っているところです。

最後になりましたが、運営のみなさま、
今回は素敵な機会をありがとうございました(* ・ω・ *)！
Ubuntu上にRancherを使ってKubernetesを構築する

# はじめに

RancherOS + RancherでKubernetesを構築していたのですが、Storage系のアプリケーションがまだまだまともに動かなかったので、一旦Ubuntuに移行して構築しているのでメモ程度に。

# 利用するもの

- Ubuntu 16.04
  - Clusterにするので3インスタンス
  - バージョンは[RancherのDoc](https://rancher.com/docs/rancher/v2.x/en/installation/ha-server-install-external-lb/#1-provision-linux-hosts)を参照して選択。
- Docker 17.03.2
  - こちらもRancher基準で。
- Rancher 2.x

# インストールしていく

## Ubuntu

適当にどうぞ。  
インターネットアクセスだけ確保しておいて下さい。

Root以外のユーザでDockerを動かしたいなら、特定のユーザに対してDockerグループ権限を付与しておいて下さい。
DockerにアクセスするためのUnixソケットへの権限が必要です。

```
user@rancher01:~$ ll /var/run/docker.sock
srw-rw---- 1 root docker 0 Jul 23 20:36 /var/run/docker.sock=
```

```
# usermod -a -G docker <Username>
```

## Docker

指定のバージョンをインストールするためのスクリプトがRancherにあるのでこちらを。

```
wget https://releases.rancher.com/install-docker/17.03.sh
sh 17.03.sh
```

直接実行してもらってもOKですが中身をチェックしたかったので一旦wgetして確認後に実行してます。
実行ログは省きますが、docker versionの結果が表示されていればOK。

```
+ sudo -E sh -c docker version
Client:
 Version:      17.03.2-ce
 API version:  1.27
 Go version:   go1.7.5
 Git commit:   f5ec1e2
 Built:        Tue Jun 27 03:35:14 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.03.2-ce
 API version:  1.27 (minimum version 1.12)
 Go version:   go1.7.5
 Git commit:   f5ec1e2
 Built:        Tue Jun 27 03:35:14 2017
 OS/Arch:      linux/amd64
 Experimental: false
```

手動でも一発叩いてみると良いと思います。

## Rancher

Dockerが動いたらRancherアプリケーションを起動します。

```
$ sudo docker run -v /opt/mysql:/var/lib/mysql -d --restart=unless-stopped -p 8080:80 -p 8443:443 rancher/rancher
```

Rancherが使うmysqlのデータをノード側に保管することで、コンテナ上のデータライフサイクルから切り離します。
ノードで8443がListenされたらブラウザから開くとRancherのWebUIに接続されます。

## Kubernetesクラスタの構築

WebUIの画像まで貼っていくと面倒なので適当に書きますが、クラスタの追加で「Custom」を選択して、各ノードのCLIで画面上に表示されるコマンドを流し込めばあとは勝手にRancherのAgentが構築を行ってくれます。

- グローバルメニューから、「クラスタの追加」ボタンを押下
  - 「Custom」を選択して、クラスタ名を入力し下部の「次へ」
  - ノードロール枠でControllerとEtcdもチェック。
  - ノードアドレスにIPアドレスを入力
    - ノード間で通信するために利用するので疎通が取れるものにしましょう。
- ページ真ん中にある投入用コマンドをコピーして、CLIで各ノードに叩き込む。

これによってRancher-agentコンテナが起動して、Kubernetesクラスタを自動的に構築してくれます。

問題なく起動してきたらダッシュボードがオールグリーンな感じになります。


![x-3.png](https://qiita-image-store.s3.amazonaws.com/0/100270/00fb97fe-dfec-3380-0a49-3b2f3c1e9309.png)

# おわりに

Kubernetesを簡単に構築するためのツールは様々ありますが、個人的な興味でRancherを取り上げてみました。

正直Rnacherのダッシュボードからじゃ見れない情報が結構あるので結局kubectlと併用している状況ではありますが、大分視覚的で楽なのは確かですね。

HELMなども含めて、もっともっと発展して安定してくるとサービスで利用しやすくなるので今後に期待！という気持ちであります。
Spark (-shell) からPostgreSQL にアクセスしてみる

Sparkの対話式シェル Spark-shellからPostgreSQLにアクセスして少し触ってみる手順を、覚書的に纏めました。

実行環境は次の通りです。なお、PostgreSQLのインストール、Setup手順は省略しています。

・CentOS 7.5
・PostgreSQL 9.2.23
・Apache Spark 2.3.1

#<b>Apache Spark</b>
各種データストア（Hadoop/Cassandra/RDB）からのデータの取り出し、加工、受渡しをインメモリで行うOSSのフレームワーク


#<b>Apache Sparkのインストール</b>
[こちら](https://qiita.com/oic0310/items/d708639b9fe4d92b6d79/)を参考に、Java環境のインストール

```
yum search openjdk
yum install java-1.8.0-openjdk
yum install java-1.8.0-openjdk-devel
```

Apache SparkのInstall

```
wget http://ftp.jaist.ac.jp/pub/apache/spark/spark-2.3.1/spark-2.3.1-bin-hadoop2.7.tgz 
tar zxvf spark-1.6.1-bin-hadoop2.6.tgz -C /usr/local/lib/

ln -s /usr/local/lib/spark-2.3.1-bin-hadoop2.7 /usr/local/lib/spark
```

環境変数の設定とSpark-shellの起動確認

```
vi /etc/profile.d/spark.sh
export SPARK_HOME=/usr/local/lib/spark
export PATH=$SPARK_HOME/bin:$PATH

source /etc/profile
spark-shell --version
```

![Spark.JPG](https://qiita-image-store.s3.amazonaws.com/0/251519/5cda6ec5-65f8-65e6-a9ab-d162725d5f19.jpeg)


JDBCドライバのインストール

```
yum -y install postgresql-jdbc
find / -name postgre*.jar
```

#<b>spark-shellからPostgreSQLへのアクセス</b>　
対話式シェルの起動とCLASSPATH指定

```
spark-shell --driver-class-path=/usr/share/java/postgresql-jdbc.jar 
```

例）PostgreSQL mydbのpublic.account表のデータをロードする

``` Scala
val jdbcDF = spark.read.format("jdbc").option("url", "jdbc:postgresql://localhost:5432/mydb").option("dbtable", "public.account").option("user", "postgres").load()
```

``` Scala
jdbcDF.filter(jdbcDF("id")<10).show()
```

![Scala_1.JPG](https://qiita-image-store.s3.amazonaws.com/0/251519/6f4fb6db-1122-5ff7-ec10-3677bdfb06a5.jpeg)


例）public.account表のデータをpublic.account_bk表にコピー（追加）する 

``` Scala
val prop = new java.util.Properties
prop.setProperty("driver", "org.postgresql.Driver")
prop.setProperty("user", "postgres")
prop.setProperty("password", "postgres") 
jdbcDF.write.mode("append").jdbc("jdbc:postgresql://localhost:5432/mydb", "public.account_bk", prop)

val jdbcDF1 = spark.read.format("jdbc").option("url", "jdbc:postgresql://localhost:5432/mydb").option("dbtable", "public.account_bk").option("user", "postgres").load()
jdbcDF1.show()
```

public.account表のデータがpublic.account_bk表に複製された
![Scala_2.JPG](https://qiita-image-store.s3.amazonaws.com/0/251519/4b19f9a5-a1d7-99ac-7d71-54344d2d9db3.jpeg)

#<b>Spark-shellの終了</b>

```
scala>Press (Ctrl+D)
```
developers summit 2018 summer - Neural Networkについて

# はじめに

7月27日 [developers summit 2018 summerでSONYが開催していたセミナー](https://event.shoeisha.jp/devsumi/20180727/session/1756/)に参加してきました。
![スクリーンショット 2018-07-30 11.28.11.png](https://qiita-image-store.s3.amazonaws.com/0/170923/8675baac-7872-3f8a-57bf-17d20d6b8b5f.png)


せっかくなので

- 行きたかったけど行けなかった人
- Neural Networkって具体的にどういうものか知りたい人

へ向けて記事を書こうと思います。

# 当日行われた流れ

1. 成平 拓也さん自己紹介
2. なぜDeep Learningなのか
3. 導入事例紹介
4. プログラムを用いたデモンストレーション
5. SONY「Neural Network Console」最新情報
6. まとめ

上記からいくつかの重要な点だけ抜粋して記述します。

# なぜDeep Learningなのか

![スクリーンショット 2018-07-30 11.16.01.png](https://qiita-image-store.s3.amazonaws.com/0/170923/87d7d944-c5ee-3d02-a269-a4cf58339ef8.png)

もっとわかり易く、ディープラーニング(深層学習)はその他の機械学習手法とどう違うのか
https://products.sint.co.jp/aisia/blog/vol1-5

# SONYの提供する「Neural Network Console」と「Neural Network Libraries」について
- Neural Network Console
  - https://dl.sony.com/ja/
- Neural Network Libraries
  - https://github.com/sony/nnabla

「Neural Network Console」は
研究や、商用レベルの技術開発に対応したDeep Learningツール。
GUIによるビジュアルな操作。

- 主なターゲット
 - 特に開発効率を重視される方
 - 初めてディープラーニングにふれる方

「Neural Network Libraries」は
Deep Learning研究開発者向けオープンソースフレームワーク。
コーディングを通じて利用。

- 主なターゲット
 - じっくりと研究・開発に取り組まれる方
 - プログラミング可能な研究、開発者

# デモンストレーション 1
画像認識機能によるデモンストレーション
![スクリーンショット 2018-07-30 14.30.40.png](https://qiita-image-store.s3.amazonaws.com/0/170923/8b3be9f4-c870-bf55-a8f4-0c067471f649.png)

上記のような画像と正解の数字の２つのデータを用意しNeural Network Consoleにて学習させます。
そしてそこで学習し終えたモデルをNeural Network Librariesで作成した画像認識システムにて使用します。

画像認識システムは手書きで書いた数字をなんの数字であるかを判別していました。

# デモンストレーション 2
距離空間学習 ~Siamese Network~
![%2Fstorage%2Femulated%2F0%2FSilentCameraSoft%2F1532655357755.jpg](https://qiita-image-store.s3.amazonaws.com/0/170923/b340ab3b-5c69-60df-7419-df0dff6ae7c9.jpeg)
![%2Fstorage%2Femulated%2F0%2FSilentCameraSoft%2F1532655608578.jpg](https://qiita-image-store.s3.amazonaws.com/0/170923/ef93a336-63db-df8e-dde8-6b8242abd4c6.jpeg)

手書きの画像を二次元に飛ばし数字と数字の間の距離を求め最も類似する文字列は何かを判定するというデモンストレーションを行っていました。
...どう距離計算してるのか全くわからん（；＾ω＾）

# 感想
セミナーを聞いてて一番のミソだなあと思った所なんですがDeep Learningの開発者が不足していてその育成にConsoleとLibrariesが使われればとおっしゃっていました。

もちろん儲けベースで利用者が増えればという側面もあるかと思いますが、私のような機械学習初心者も引き込んでくれそうな可能性を感じたため画像認識システム作って見ようと思いました。
SONYさんの使うかわかんないけどw
Dockerのログが大きくなりすぎたから最新のだけ見たい

立ち上げっぱなしのDockerだとログがずっと累積していくため、

```bash
$ docker logs -f <container-name>
```

上記コマンドで出力したとき最新のログにたどり着くまでに数分かかってしまうことが・・・。サクッと見たい・・・。
ログの削除で調べたが、うまく削除できずに困っていたところ、以下の情報を発見

![image.png](https://qiita-image-store.s3.amazonaws.com/0/103475/0a1183d9-e0cb-f1f0-59b2-295315238636.png)

## つまり

```bash
$ docker logs -f --tail=500 <container-name>
```

**--tail=500**をつけることでサクッと見ることができる

>参考：https://github.com/moby/moby/issues/24998#issuecomment-234941293
わかりやすいプルリクを目指して

# わかりやすいプルリクを目指して

みなさんGithub使ってますか？
Githubのプルリクエスト（略してプルリク）、使ってますか？

使ってても結局セルフマージしちゃったり、プルリク内でやってることが最終的にとっちらかったりしてないですか？

大体の人が自分なりのプルリクルールを持ってたり、プロジェクトでルール決めてたりすると思うのですが、
私が使ってきてこれは良かったと思うプルリクルールについて、共有していきたいと思います。

## そもそもプルリクって？

[ここ](https://backlog.com/ja/git-tutorial/pull-request/pull-request1_1.html)がわかりやすくまとまっています。

簡単に言えば、
*複数人で開発してるときに、実装したブランチの作業をチームメンバーに共有し、レビューしあい、事故なくわかりやすく変更をマージしていくための機能*
です。


## わかりやすいプルリクの条件

１にも２にも、「**レビューしやすいこと**」だと思います。
そもそもプルリクは、自分がやった作業内容を、他のメンバーや後から確認したときにわかりやすくするためのもの。
様々なルールは、全てレビューのしやすさに繋がります。

そんな中で、これは共通でどんなプロジェクトでも使えるはず、と思えるルールを以下にまとめます。

- **１プルリクに１機能**
   - 複数の機能をプルリクに入れてしまうと、変更点が何に対するものなのか分かりにくくなるため、プルリク１つには１機能のみ入れるべきです。
- **１コミットに１作業**
   - プルリク内のコミットも、できれば細かく分けたほうが良いです。特にリファクタリングと実装は別コミットにしたほうが分かりやすいです。
- **プルリクの概要には、目的と実装した機能内容を必ず記載**
   - 例えば、目的：どこどこのバグ修正、実装内容：なになにクラス内がこうなってたのがダメだったのでこうした、など。
- **LabelsやMilestoneを使って後からソートしやすいようにする**
   - 新しいバージョンにどの機能を入れたのか、Milestoneさえキチンと設定しておけば絞り込みソートで簡単に機能一覧を探せます。


## プラスあるふぁ

他に積極的に使っていきたいなと思うのは、スクショやアニメーションGifを使って実装内容を説明することです。
実装内容が目に見える機能の時のみ使える手ですが、文字をみるより圧倒的に分かりやすいです。

私はMacなので、動画を撮りたい時は [GIPHY Capture](https://giphy.com/apps/giphycapture) を使ってます。
とても簡単にキャプチャーができるので重宝します。

実装中の機能がアニメーションとか新しいUIとか、そういうものだった場合、エンジニア以外にも共有しやすくてオススメです。


## レビューについて

このポストは「レビューのしやすいプルリク」を目指してますが、レビューはレビューで「プロジェクトの雰囲気を明るくするレビュー」とか「喧嘩しないレビュー」とかあったりします。
[IMO]とかの略語を使って受け取られかたをマイルドにしてみたり、
LGTMや:thumbsup: の絵文字などを使ってお互いに褒めてみたり、
かわいいイラストやおもしろ画像を引用してきてちょっとふざけたLGTMで楽しくプルリクを盛り上げたり

少し工夫するだけで、毎日のコーディング作業が楽しくなり、チームの一体感も増します。
レビューの心得はそれだけで本１冊になったりするのでここでは詳しく書きませんが、プルリクをわかりやすくしたあとは、分かりやすいプルリク内容をさっと確認して楽しくレビューしていきたいですね。
AmazonLinux2で、native extensionな ruby gemのinstallに失敗する場合

AmazonLinux2で、native extensionな ruby gemのinstallに失敗する場合

以下をインストールする

```bash
sudo yum install ruby-devel
sudo yum groupinstall 'Development Tools' 
```

※AMIままだと、`Development Tools` も入っていないので注意
メンテナンスを考慮したコーディング 

今までサイト制作って渡してしまったら終わりで刹那的なもので寂しかったりしました。
ここ数年は1つのサイトにずっと携わっていて、そのサイトとずーっと付き合っていくためのコーディングってなんぞや？という事を徐に考えてます。

# **誰が見ても分かる**ように作る
- ソースコードを見やすく探しやすく
- モジュールも見やすく探しやすく
- 同じ書き方で統一する
- 命名規則を統一する

## HTML編
### **モジュール名は分かりやすく**
（段組みレイアウトは置いておいて、個々のコンテンツの話となります。）
パッケージとかだと汎用的な名前になると思いますが、更新をし続ける前提の場合、何を表示しているソースコードなのか、モジュール名見ただけで分かるようにしておくと良いですよね。
モジュール名も具体的にすると独自性が高まり、汎用的にすると反復して使えるものになりますので、モジュールの内容によりメリットデメリットを考慮して命名してあげてください。
<br>私たちのチームでは、「カテゴリ名-単語はキャメルケース」で命名しています。（例：category-tangoTango）

### **htmlタグの閉じタグは入れる**
html5でコーディングの際、閉じタグが省略できるものもあるかと思います。
しかし、liなどの閉じタグがないと見難かったり個人的に気持ち悪かったりするので入れるようにしています。
**少しでもコードを軽くしたい**ので、この辺りは臨機黄変に。

### **モジュールは区切りとしても使う**
(ここで言うセクションはsectionタグの事ではありません)
モジュール間は空けるようにしています。
1行とか2行とか決めておくと視覚的に綺麗です。私の場合は2行空けです。

### **htmlは後からcssでデザインしやすいように作る**
サイトの規模が大きく構造が複雑だったりすると、製造の過程でフロントチームからサーバーサイドのチームへhtmlを渡す場合があります。
一度渡したHTMLに再度修正かけるのがなかなか大変なので、見た目だけなら後からcssで補正できるようHTML組んでいきます。
そのため、HTMLは二度と修正できない、くらいの意気込みで作ります（）

例：

```html
<!-- foodMenu -->
<div class="foodMenu">
	<div class="parts-01">
		<h2><span>果物のリスト</span></h2>
		<ul>
			<li class="li01">りんご</li>
			<li class="li02">メロン</li>
			<li class="li03">キウイ</li>
		</ul>
		<p>残数が残り<em>1</em>になると締め切ります。<span>残り数にご注意ください。</span></p>
	</div>
</div>
<!-- //foodMenu -->
```

シンプルな例ですが、

- foodMenu
    - 料理のメニューだと分かる名前。他にも野菜・肉などの**カテゴリで他にも使いまわしたい**ので今回は「foodMenu」という名前にしました。
- parts-01
    - **foodMenuが反復しても良いよう**に、セクション区切りの用途でfoodMenuを使います。そのため、中身の調整をparts-01のdivでグループ化します。

### **モジュールの中でもグループ化を意識する**
自分流の解釈では大きな箱は揺るがない、という概念ですすめます。大きな箱”ごと”無くなってしまっても、前後の大きな箱には影響しない、もしくはガチッと箱でレイアウトを決めてしまうと中身の要素に左右されにくく、レイアウト崩れしにくい、という事が前提になります。従って、大外にはレイアウト目的以外の用途で余計なプロパティは付与しないようにします。<br>こちらの記事の考え方に近いです。（→[【CSS】CSSプロパティの記述順について考えてみた：イメージ図解の所](http://unitopi.com/css-order/)）

### **要素の中にインライン要素を仕込む**
前述したとおり、**階層を意識して、モジュールHTMLも大きなグループから段々と小さくしていくイメージで作成**します。<br>例では「foodMenu」という大きなボックスから、parts-01、h,ul,pと落ちていき、完成させていきます。cssプロパティも同じように考えます。ですので、大外の要素は極力重複しない（箱の役割）ように作っていきます。

#### **hの中にも仕込む**
ボックスの概念で作成しますので、hの中にも何かしらのインライン要素を埋めておいた方が、後々cssでデザインの補正がしやすくなります。（例えばhそのものに対してcssでデザイン調整は複数可能ですが、「大きな箱は揺るがない」という概念が基本ですので、hが無くなって前後の要素が影響をうけるような作り方になってしまわないよう、spanなどを入れておきます。もちろんデザインにもよりますが。

#### **liにクラスをつける**
デザインでアイコンが個別に指定されている場合はつけておきます。固有の名前にせず要素ベースにするのは、**使いまわせる**ように、という理由です。<br>隣接セレクタなどで指定できなくはないですが、li要素が消えた際に前後の要素に左右されないように作るのが目的です。<br>また、固有指定する必要がない場合は、ul class="ul01"
などとし、liには何もつけません。<br>気付いたらdivばかりになっていた、という事がないように、なるべくhtmlもシンプルに書くようにしています。

#### **span**
レスポンシブや、後々改行をしたい場合に使用します。あえて「ここで改行する」というような指定がリクエスタからあった場合は、brタグを使用します。

#### **htmlタグはシンプルに(divだらけにしない)。**
いくら保険とはいえ、文書構造に関係のない無駄なHTMLは極力減らし、シンプルに。
divの代わりに他のブロックタグに置き換えれないか、など考える（文書構造を意識すれば自然と減るはず）。

## ガイドラインを設ける
最後にCSS、html、sass、javascript、実作業に関わる書き方の統一など、複数人で行う上で必須と言えるほどあった方が良いです。
長くサイトに携わっていく場合、メモ帳程度でもいいので共有し、やり方を統一するようチームで行っていく事をおすすめします。

ここまで読んでくれた方はありがとうございました。
何かお気づきの点がありましたらご教授いただければ幸いです。
<br><br><br><br><br>
...(-。-)ﾎﾞｿｯ 今度はガイドラインやsass、cssの記事を書こうかなぁ。書けるといいなぁ.....
[VBA]いい加減Markdownの表を作るのに疲れたのでExcelの表を変換するツールを作った話

# はじめに
皆さん、MD記法スラスラ書けますか？
私は記事を書くたびにググりながら色々やってます。
その中でも特に表って難しくないですか？
セル内改行とか全然直感的じゃないし。
ということでExcel表をそのままMD形式に変換できるツールを作りました。

# そもそも…

表の書き方ってどんなんだったっけ？ってところから。

|th 1|th 2|th 3|
|:-----|:----:|-----:|
|td 1|td 2|td 3|
|td 4<br />td 4|td 5|td 6|
|dummy message.|dummy message.|dummy message.|

```markdown:table
|th 1          |th 2          |th 3          |
|:-------------|:------------:|-------------:|
|td 1          |td 2          |td 3          |
|td 4<br />td 4|td 5          |td 6          |
|dummy message.|dummy message.|dummy message.|
```

こんな感じですね。
1行目がタイトル、2行目が文字位置、3行目以降が内容といった具合。
...小さなテーブルだといいんですが、肥大化しちゃうとすごくメンテしづらい。

# と、いうことで
![image.png](https://qiita-image-store.s3.amazonaws.com/0/165355/40edc357-77a8-8a44-eba6-baa6b6945306.png)
こんな感じに変換してくれるツールを作りました。
ダウンロードは [**こちら**](https://github.com/tosite0345/vba_tools/tree/master/table_to_markdown_tool) からご自由にどうぞ。
TypeORMのリレーション定義に気をつけよう。死ぬぞ。

いつものように[あら便利カレンダー](https://benri2018.rnd.cloudpack.jp/)らしく、死んだ話です。

[TypeORM](http://typeorm.io)というTypeScriptで使えるORMがあるんですが、
OneToManyなリレーションを作ったら死んでしまいました。

## tl;dr

```typescript
@ManyToOne(type => User, user => user.interests)
user: User;
```

このデコレータの中の引数かかないとts的なエラーを吐かずにMySQLがSyntaxError吐いて死にます。


## 原因

```typescript
class Interest {
    @ManyToOne(type => User, user => user.interests)
    user: User;
}
```

これどうなっているかもぐっていくと `SelectQueryBuilder.ts` にたどりつきます。
createJoinExpression()というJOINされる部分のクエリを組み立てる実装がどうなっているか見てみる。

```typescript
const condition = relation.inverseRelation!.joinColumns.map(joinColumn => {
    return destinationTableAlias + "." + relation.inverseRelation!.propertyPath + 
    "." + joinColumn.referencedColumn!.propertyPath + "=" +
    parentAlias + "." + joinColumn.referencedColumn!.propertyPath;
}).join(" AND ");

return " " + joinAttr.direction + " JOIN " + this.getTableName(destinationTableName) + " " + 
    this.escape(destinationTableAlias) + " ON " + this.replacePropertyNames(condition + appendedCondition);
```

このONのあとのJOIN条件を組み立てる部分が動きません。

```
SELECT ... 
FROM ... 
LEFT JOIN ... 
ON
```

でクエリが終わってしまってそりゃSyntaxError出るよなっていう話でした。
jsレイヤーでエラー吐けや！！！


## 余談

なんとこのクエリ、たまたま1480文字で死んでいたので最初はクエリがちゃんと送信できてない！みたいにしてネットワーク周りの見直しをしてました。
開発環境がdockerなのでMTUが問題になってるんじゃ！？みたいな勘違いぶちかまして情けないことに２人日くらいまるまるふっとびました。
マジなさけねえ...

ちなみに、もう一回ちゃんと調べてみようってことでTypeORMをcloneしてちゃんとデバッグした結果わかったことなので社内では誇らしい顔しながら土下座しました。
[初心者] Cloud9でPythonを動かそうとしてつまずいたところ

# やりたかったこと
Progateの「Python 学習コース Ⅳ」で完成したコードを[Cloud9](https://c9.io/login)で写経&動作させる。

# 写経→動作がしたかっただけなのに3回躓く
Progateの「Python 学習コース Ⅳ」で理解が追い付かなくなってきていると感じたため、お手軽にCloud9でコードを写経して動作させようと思ったのがそもそもの発端です。
「写経さえ正確にやればコードは動くはず」と思った私の見通しは甘かったf^^;

今回躓いたところ
- 文字コード
- モジュール (ファイル) が見つからない
- bashに入力できない
## エラー1!!! ASCII文字列じゃないのが入ってるよ!
エラー文

```
SyntaxError: Non-ASCII character '\xe3' in file filename.py on line 12, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
```
→原因
Pythonはソースコード内の文字列をasciiと想定して処理する。そのため、マルチバイトである日本語がコード内 (たとえコメント内であっても) にあればエラーが起きる。
→対処方法
コード先頭に`# -*- coding: utf-8 -*-`を挿入
[http://yono.cc](http://yono.cc/python/python_basics/japanese.html)さん、ありがとうございます!


## エラー2!!! memu_item?そんなモジュールはないよ?
エラー文

```
Traceback (most recent call last):
  File "py4page17_scrypt.py", line 2, in <module>
    from memu_item import MenuItem
ImportError: No module named memu_item
```
→原因
モジュール名 (ファイル名) をmemu_item.pyからpy4page17_menu_item.pyに変更したことを忘れていた。
そういえばProgateからコードをダウンロードしたときにファイル名を変更してたなー。あはは。

→対処方法
「from py4page17_menu_item import MenuItem」に変更

## エラー3!!! ん? cloud9のbashに入力できなくなった!
→原因
bash画面で［Ctrl］＋［s］キーを押したから。
→対処方法
［Ctrl］＋［q］キーを押す。
[atmarkIT](http://www.atmarkit.co.jp/flinux/rensai/linuxtips/225nokeyinpt.html)さん、ありがとうございます!

# [編集提案]コードの前後には空行を:coffee:

[khsk](https://qiita.com/khsk)さん、編集提案ありがとうございました!
~~バッククオート * 3 の前に「+」をつけるとコード部分が黒く反転して見やすくなる、ということを初めて知りました(ﾉ*ﾟ▽ﾟ)ﾉ~~
空行をいれたらブロックとして認識され、+は差分表示だったのですね:open_mouth:

もしかして[人間性をさがせよ QiitaのTypo検出](https://qiita.com/khsk/items/085db0947c650e2db463) のTypo修正プログラムで引っかけてくれた。。。? 私もこんな風にプログラム書けるようになりたい:rocket:
【&#5147;】 JSでHTML10進コードをデコードする記事が見つからなかった

# まとめ
## コピペ用１
data に文字化けが入っていて、data に結果が反映される

```javascript

while(match = data.match(/&#(\d{2,5});/)) {
    data = data.replace(match[0], String.fromCharCode(match[1]));
}
```

## コピペ用２
引数に文字化けをとり、結果が返される

```javascript

function decodeSJIS(data) {
    if (typeof data !== "string" || data === "") return false;
    while(match = data.match(/&#(\d{2,5});/)) {
        data = data.replace(match[0], String.fromCharCode(match[1]));
    }
    return data;
}
```

# 経緯

phpを使ってサーバ上に入れたmp3(m4aもある)のID3v2タグ情報を取得してきたとき、
(いまだ原因は不明だが)本記事タイトルのようなHTML10進数コードがとびだしてきた。

いつも通りGoogleでググってみたがUTF8→ShiftJISのエンコードだったり、decodeURIだったり、10進数→16進数のjsサンプルしか出てこなかったので、うんともすんともだった。

どうやらHTML10進数コードというものがあるらしく、変換ツールまでは見つかったので、できるらしいことはわかった。
そして、がんばったらものの数分で実現した。

検索して出てこなかったので記事にまとめました。
まとめしかないまとめ。
MindMup 2 > Google DriveからMindMup Cloudへの移行ツール > Import from Google Drive

```txt:動作環境
Windows 10 Pro (64bit) バージョン 1803 (April 2018 Update)
Google Chrome バージョン: 67.0.3396.99（Official Build） （64 ビット）
```

### ファイルの移行

GoogleのRealtime API機能の提供廃止([Google Drive > 3rd パーティへのRealtime API capabilities の停止 (2018-12-11)](https://qiita.com/7of9/items/a328fd0f331f9f1feaa2))に伴うファイル保存先の変更。

https://www.mindmup.com/resources/google_realtime_deprecation.html
の下の方にある「Key actions you may need to take」が参考になる。

移行ツールとして下記が紹介されている。

> To move files from Google Drive to MindMup Cloud, use the [Import from Google Drive](https://app.mindmup.com/migrate_from_google.html) page.

MindMupファイルは280個程度ある (2018年7月30日現在)。

移行時は移行元ファイルを今後間違って修正しないように、名前を変更するなどの工夫は必要だろう。
(例: 「`[MindMupCloud移行前]WRF_XXX_161109`」)

### 移行したファイルかどうか

開いているマップが移行済ファイルであれば、ファイル名が`https://app.mindmup/com`で始まる。


### 関連

- [Google Drive > 3rd パーティへのRealtime API capabilities の停止 (2018-12-11)](https://qiita.com/7of9/items/a328fd0f331f9f1feaa2)
- [MindMup2 > Collaborative maps will stop working in December 2018 > Google Drive integrationの変更(2018-12-11)に関係](https://qiita.com/7of9/items/1e1b1d75dcde07ae5d7a)
LeapMotionで3Dモデルの手を動かす

# **はじめに**
はじめまして。都内の大学院でVRの研究をしているichita([@ichita_cs](https://twitter.com/ichita_cs))と申します。学部までは材料系の学科にいました。
LeapMotionで3Dモデルの手を動かそうとしたら色々と詰まったので備忘録です。ポンコツなミスが目立ちますが、初学者の方の参考になれば幸いです。
# **参考資料**
[@aflkさんの記事](https://qiita.com/afjk/items/e2c9617e937528feba6e)を参考にさせて頂きました。時間が経って色々と変わっているところがあるのでそこを書き足していきます。
# **必要なもの**
- [Leap Motion Orion SDK](https://developer.leapmotion.com/get-started)：インストールする
- [Unity Assets for Leap Motion Orion Beta](https://developer.leapmotion.com/unity#5436356)：インストールしてProjectにインポート(執筆時Ver4.4.0)
- [Final IK](https://assetstore.unity.com/search?q=FinalIK&k=FinalIK)：買う($90)→インポート(執筆時Ver1.7)

# **やり方**
## **シーンを開く**
Assets→LeapMotion→Core→Examples→Capsule Hands (Desktop)のシーンを開く(※今回はデスクトップモードを使用)
## **Cubeを手の子オブジェクトにする**
HandModel→RigidRoundHand_L→Palmの下にCubeを配置し、その下に更にCube(以下、子Cube)を配置する。(※**利き手の逆の手**に配置しないと後述のパラメータ調整でめちゃめちゃ作業しづらい。) 位置を概ねLeapMotionの手の位置に合わせる。

## **3Dモデルを配置**
今回は[これ](https://www.cgtrader.com/free-3d-models/character/man/basic-bandit)を用いた。インポート後PrefabをSceneに配置し、Leap Motion Controllerが胸の前あたりに来るように位置を合わせる。
![2.PNG](https://qiita-image-store.s3.amazonaws.com/0/211526/6f986818-b049-2924-e189-8eb9d514162e.png)
## **モデルにIKを入れる**
Hierarchy内の3Dモデル(今回はBasic_BanditPrefab)に"Full Body Biped IK"のコンポーネントを追加。Right Arm→Right Hand Effector→Targetに子Cubeを適用し、Position Weight, Rotation Weightを1にする。

## **手の設定**
再生しながら、子CubeのPositionとRotationを調整して3Dモデルの手とLeap Motionの手を合わせる。
再生を止めると**PositionとRotationが元に戻る**ので、再生中にInspector→Transform→Copy Componentし、再生を止めてからPaste Component Valuesする。
合わせるとこんな感じ。
![07261731.gif](https://qiita-image-store.s3.amazonaws.com/0/211526/12aa1f25-a2d0-4b88-d364-5e139627feb4.gif)


## **指の設定**
### Rigged Finger
3Dモデルの指の**第三関節(根元)**にあたるGameObjectにRigged Fingerを設定し、Finger Type: TYPE_(指の名称)
Element 1: 第三関節のGameObject
Element 2: 第二関節のGameObject
Element 3: 第一関節のGameObject
を設定する。
![5.PNG](https://qiita-image-store.s3.amazonaws.com/0/211526/11f0b6e1-3bf9-b5a8-62b7-093d6e9c3476.png)

### Rigid Hand
RigidRoundHand_L→Rigid HandのElement0~4に、先ほどRigged Fingerを設定したGameObjectを適用（親指~小指の順）。
![7.PNG](https://qiita-image-store.s3.amazonaws.com/0/211526/7f439cd6-478a-befc-f4c4-96963900c3b9.png)

### 動かしてみる
知ってた。
![07261748.gif](https://qiita-image-store.s3.amazonaws.com/0/211526/436d6cc0-bffb-2443-e62b-72dde378f482.gif)
### 再設定
Model Finger PointとModel Palm Facingの設定がまだでした。この値はモデルによって異なるようなので、再生しながら値を変えて合わせていく。（上記の画像は既に合わせてある。）
## **完成**
今度こそ完成。なんか怪しい感じもしますが…。原因が突き止められたら追記します。
![07261834.gif](https://qiita-image-store.s3.amazonaws.com/0/211526/43642e52-cfb4-f208-9bb3-07ffb8db1723.gif)

## **おわりに**
間違いやアドバイス等あればご指摘頂けると幸いです。ありがとうございました。
Yamahaルータを利用してパケットループ時に音を鳴らす

パケットループを検知・遮断してくれる製品は数あれど、現場の人間に音でお知らせしてくれる製品はそんなに多くないような気がします。

ということで、ヤマハさんのスイッチも検知と遮断はしてくれるものの警報音が出ないわけですが、それならばルータで鳴らしてしまえ。というお話 ：）

# サンプル構成
[ RTX830 : LAN1 ]  --- [SWX2100-5PoE]

# 仕組みと設定

SyslogのInfoレベルで
`[SWCTL] lan1:1(ac:44:f2:xx:xx:xx): PORT1 loop detect`
こんなログが出るのでsyslogwatchしてるだけ

## スイッチの設定(物理)
ディップスイッチの4番をONにして電源投入！

## ヤマハルータの設定

```
switch control use lan1 on
lua use on
embedded file LoopDetect.lua <<EOF
  CHECK_INTERVAL = 3

  function Beep()
    local bz, err = rt.hw.open("buzzer1")
    bz:tone("B4")
    rt.sleep(1)
    bz:off()
    bz:close()
  end

  function Check_Looppacket(port, hub)
    while true do
      local cmd = string.format("switch control function get status-loopdetect-port %d %s", port, hub)
      local rtn, portstate = rt.command(cmd)
      if (not rtn) then
        break
      end
      if ( portstate:find("normal", 1, true) ) then
        break
      end
      Beep()
      rt.sleep(CHECK_INTERVAL)
    end
  end

  function main()
    local rtn, logcode = rt.syslogwatch("loop detect")
    if (rtn) then
      local hub, port = logcode[1]:match(/\[SWCTL\]\s(.+)\(.+\sPORT(\d+)/)
      Check_Looppacket(port, hub)
    end
  end
  
  while true do
    main()
  end
EOF
```

# 実行コマンド

`lua emfs:/LoopDetect.lua`で実行
スケジュール登録は
`schedule at 1 startup * lua emfs:/LoopDetect.lua`
こんな感じで。

# 最後に

~~EMFS使いたすぎて わざわざRTX830を選定しましたｗ~~
<a href="http://www.rtpro.yamaha.co.jp/RT/docs/emfs/index.html" target="_top">EMFS機能</a>はとても便利ですね。
TFTPでわざわざ送ったりする事も減ります。
あとは対応ルータが増えてくれれば・・・。

ただ、今回の設定だと音が鳴るのはルータなので
知らない人からするとルータが壊れたって思われてしまうのかなぁ。
でも音が小さいからラックとかに入ってると聞こえないだろうナァ。orz
Clovaスキルをngrokを使ってローカルでテストする

# はじめに

Clovaスキルの開発を始めようと思った時に真っ先に読むのが[公式チュートリアル](https://clova-developers.line.me/guide/#/CEK/Tutorials/Build_Simple_Extension.md#Step1)だと思います。
ただ、この公式チュートリアルで最初に躓くのが外部からアクセスできるサーバーを立てないといけないということろです。
練習段階なのにわざわざ外部のサーバーを自分で立てるのは面倒だと思います。
ということで、ローカルでテストする方法を書きたいと思います。

# 仕組み

ngrokというものを使います。
ngrokとは、localhostで動いているサーバーを外部に公開できるツールです。
これを使って公式チュートリアルをローカルでテストして見たいと思います。

# スキルの作成

公式と全く同じスキルを作成して試して見たいと思います。

インテント: `ThrowDiceIntent`

```text:ThrowDiceIntent
サイコロを振って
```

詳しくは、[こちら](https://clova-developers.line.me/guide/#/CEK/Tutorials/Build_Simple_Extension.md#Step1)

# ソースコードのダウンロード

ここも、公式通り行きます。

```
$ git clone https://github.com/line/clova-extension-sample-dice.git
$ cd clova-extension-sample-dice
$ git checkout tutorial1
$ npm install
$ node app.js

Server is running on 3000 port
```

`node app.js`を実行すると立ち上がったサーバーのポート番号が表示されると思います。
***のちにngrokを起動する時にポート番号が必要なのでメモしておきます。
上記ですと、`3000`です。***

次に`ngrok`を使って外部からのアクセスを可能にしたいと思います。

# ngrokのインストール


こちらを参考にしました。
[ngrokを使用してローカル環境を外部に公開する](https://qiita.com/kitaro729/items/44214f9f81d3ebda58bd)

```
$ brew install ngrok
```

上記のでうまくいかなかった場合

```
$ brew cask install ngrok
```

# ngrok起動

先ほどメモしたポート番号と、コマンド一発で起動します。

```
$ ngrok http メモしたポート番号
```

今回の場合、ポート番号が3000だったので以下のように起動します。

```
$ ngrok http 3000
```

すると、URLが生成されるのでメモします。
***httpsの方を使用します。***
***また、起動毎にドメインが変わってしまうので注意です。***

<img width="840" alt="1__ngrok.png" src="https://qiita-image-store.s3.amazonaws.com/0/195882/c72fdc6e-f747-bee0-2121-9e5b76e03ae8.png">

# CEKとローカルを紐づける

上記でメモしたURLに`/clova`を付け加えてCEKの方のサーバー設定画面で設定します。
上記のURLだと、`https://9cc7705c.ngrok.io/clova`になります。

<img width="1192" alt="Clova_Developer_Center_β.png" src="https://qiita-image-store.s3.amazonaws.com/0/195882/2a9a3d2a-cbe2-ba8a-494a-744b052dda1a.png">

# テストしてみる

完成です。
実機でも、ブラウザからでもどっちでもいいのでテストして見てください。
うまく言っているはずです。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Clovaスキルのテストをngrokを使ってローカルで試してみました！の図<a href="https://twitter.com/hashtag/CEK?src=hash&amp;ref_src=twsrc%5Etfw">#CEK</a> <a href="https://twitter.com/hashtag/Clova_CEK?src=hash&amp;ref_src=twsrc%5Etfw">#Clova_CEK</a> <a href="https://t.co/dDFXNcK7EW">pic.twitter.com/dDFXNcK7EW</a></p>&mdash; imajo (@imasirooo) <a href="https://twitter.com/imasirooo/status/1023797854513463296?ref_src=twsrc%5Etfw">2018年7月30日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# Invalid application id:

ちょっとハマったのですが、チュートリアル通りだとExtension IDに`my.clova.extension.sampledice`を入力すると思うのですが、Extension IDはユニークなので怒られます。
そこで、自分の好きなIDに変更すると思うのですがそうすると以下のようなエラーが返されると思います。

```
Invalid application id: your-id
```

これはcloneしたコード上ではExtension IDの設定を変更しないといけないからです。

`config.js`の`ExtensionId`をご自身で設定したIDに変更してもう一度試して見てください。
画像の URL から画像データを Base64 にエンコードして取得する

# 方法

```js
const request = require('request'); // yarn add request
const imageUrl = 'http://liz-bluebird.com/img/character/natsuki.png';

request
  .defaults({ encoding: null }) // encoding に null を指定すると、body として buffer が返される。
  .get(imageUrl, (error,{ statusCode, headers }, body) => {
    if (error || statusCode !== 200) return
    
    const contentType = headers['content-type'];
    const base64Str = new Buffer(body).toString('base64');
    
    console.log(`data:${contentType};base64,${base64Str}`); // Base64 エンコードされた画像
  });
```

# おまけ

async 関数の中で同期的に取得する。

```js
const request = require('request');

const getImageSrc = async (imageUrl) => {
  const { statusCode, headers, error, body } =
    await util.promisify(request.defaults({ encoding: null }))(imageUrl);

  if (error || statusCode !== 200) return null;

  const contentType = headers['content-type'];
  const base64Str = new Buffer(body).toString('base64');

  return `data:${contentType};base64,${base64Str}`;
});
```
MindMup 2 > 手順 > MindMup Cloudからファイルを開く (MindMup Goldユーザとして)

```txt:動作環境
Windows 10 Pro (64bit) バージョン 1803 (April 2018 Update)
Google Chrome バージョン: 67.0.3396.99（Official Build） （64 ビット）
MindMup 2
```

Google Drive上のMindMup 2ファイルが2018年12月11日頃からread-onlyになるであろう件の対処。

MindMup Cloudにファイルを置くとして、そのファイルへのアクセス方法が分かりにくい。
(MindMupの公式ページからはリンクが複雑。MindMup2のリンクからはメニューが「Open Google Drive」になる、など)。

下記のようにする。

1. キーワード「Mindmup app」でgoogle検索
2. MindMup 2 ( `http://app.mindmup.com` )をクリック
3. 「OPEN FROM MINDMUP GOLD」をクリック
4. 希望のファイルをクリック

Google Driveからアクセスしていた時と比べて手間が増える。


### 関連

- [Google Drive > 3rd パーティへのRealtime API capabilities の停止 (2018-12-11)](https://qiita.com/7of9/items/a328fd0f331f9f1feaa2)
複数フォルダの指定から、右クリックで各フォルダを RAR 圧縮するサービスを macOS の Automator で作る



## RAR のインストール

```shell:
$ brew cask install rar
```
うまくインストールできないときは以下のオプションで対応する

```shell:
$ brew cask install --force rar
```


## RAR コマンドのパスを調査

```shell:
$ which rar
/usr/local/bin/rar
```
rar コマンドは /usr/local/bin/ に存在した。

## サービスの作成

1. 「Automator」の「新規作成」で「サービス」を選択
2. 「サービスは、次の選択項目を受け取る：」には「フォルダ」を指定、「検索対象：」には「Finder」を指定
3. 左ペインの「アクション」から「シェルスクリプトを追加する」を検索・選択し、ドラッグ・アンド・ドロップで右ペインへ入力
4. 「シェル：」には「/bin/bash」を指定、「入力の引き渡し方法：」には「引数として」を指定
5. 入力欄に以下のシェルスクリプトをコピー＆ペースト
6. 好きなサービス名を付けて保存

```shell:rar-comp.sh

USRBIN="/usr/local/bin/"
TITLE="RAR圧縮"
MESSAGE="完了"

for f in "$@"
    do
        EXEDIR="${f%/*}"
        DIRNAME="${f##*/}"
        cd "${EXEDIR}"
        "${USRBIN}"rar a -m5 -rr5p "${DIRNAME}".rar "${DIRNAME}"
        osascript -e "display notification \"${DIRNAME} ${MESSAGE}\" with title \"${TITLE}\""
    done

```




[参考 URL： Terminal を Automator でよく行う処理を簡単サービス化](https://0017.org/1469.html)

## 使用方法
1. フォルダ選択後に右クリック、プルダウンメニューから RAR 圧縮サービスを実行する
2. RAR圧縮が完了する毎に「通知」で表示される


## サービスの削除

1. システム環境設定>キーボード>キーボードショートカット>サービスを選択
2. 削除したいサービスを選択して右クリック
3. プルダウンメニューの「Finder に表示」を選択
3. Finder 上で該当ファイルを削除

以上
「pipenv + direnv」で脱「pyenv virtualenv + pyenv local」

# はじめに
最近話題の pipenv はいろいろと便利なところも多いのですが、単体だと `pyenv local` 相当のコマンドがありません。
毎回 `pipenv run` を頭につけるのは面倒だし、`pipenv shell` だと別の shell が立ち上がるからこれも面倒。

やっぱり、`pyenv local` みたいに `cd` したら勝手に環境が切り替わって欲しい。
そんな方は direnv を併用しましょう。

# 使用例

```bash
$ which python
/usr/bin/python

$ mkdir my_project

$ cd my_project

$ pipenv install --python=3.7 numpy matplotlib  # ≒ pyenv virtualenv 3.7.0 my_project
.....

$ echo 'layout_pipenv' > .envrc && direnv allow  # ≒ pyenv local my_project
direnv: loading .envrc
direnv: export +PIPENV_ACTIVE +VIRTUAL_ENV ~PATH

$ which python
/home/kzm4269/.local/share/virtualenvs/my_project-9qDNSaIH/bin/python
```


# 必要なもの

## Python

Python 2.7 もしくは Python 3.4 以降ならなんでもいいです。

## pipenv

普通に pip でインストールできます。`apt` や `brew` でもインストールできるようなのでお好みで。

```bash
pip install pipenv
```

詳しくは以下のURLを参照してください。

- https://pypi.org/project/pipenv/
- https://pipenv-ja.readthedocs.io/ja/translate-ja/install.html#installing-pipenv

## direnv

インストール方法は以下のURLを参照してください。
コンパイル済みのバイナリを使う方法とソースからコンパイルする方法があります。

- https://github.com/direnv/direnv#from-binary-builds
- https://qiita.com/kompiro/items/5fc46089247a56243a62

# 補足1. pyenv が不要になるわけではありません

pipenv はあくまでも実行環境の構築が主な機能で、Python本体のインストールは管轄外です。
pyenv をインストールしておくと、 pipenv が裏で連携して Python 本体のインストールもしてくれるようになります。

# 補足2. 複数のディレクトリで virtualenv を共有するのは面倒になります

完全に別の場所にあるディレクトリどうしで同じ virtualenv を共有するのは「pipenv + direnv」だと難しいです。
pipenv なら `pipenv local` で同じ virtualenv を指定するだけなので楽なんですが...。
以下の例のように、片方のプロジェクトの virtualenv のディレクトリに、もう片方のそれへのシンボリックリンクを貼れば一応同じ環境で動かせますが、お行儀の良い使い方ではないと思います。

```bash
$ mkdir my_project1 my_project2
$ cd my_project1
$ pipenv install
$ ln -s $(pipenv --venv) ../my_project2/.venv
```

# おわりに
pipenv を使うと実行環境の構築が `pipenv install` 一発で済んで非常に便利です。
依存パッケージの一括アップデートも `pipenv update` でできます。感動的。
他の人に同じ環境を用意してほしいときは `Pipfile` と `Pipfile.lock` を渡すだけです。楽です。
pyenv もインストールしておくと、`pipenv install` するときにPython 本体のインストールもよしなにやってくれます。
「でも `pyenv local` みたいなのできないんでしょ？」って方は direnv をインストールしましょう。できるようになります。

それでは、良いPythonライフを。
ラウンドロビンとは？

# 概要

例のごとくわからんかったので、更新

# ラウンドロビンとは？

ラウンドロビンとは、際限のあるリソース（資源）を順繰りに割り振ってゆく方式
DNS（Domain Name System）のサーバーにおいて用いるDNSラウンドロビン方式を指す場合が多い。

# ネットワークにおける負荷分散の技法であるDNSラウンドロビン

インターネット通信においてドメイン名とIPアドレスを相互変換する装置であるDNSにおいて、

ひとつのドメイン名に対して複数のIPアドレスをあらかじめ割り当てられるというものである。クライアント（ユーザー）が同じドメイン名を用いてアクセスするたびに、ホスト（DNS）は異なるIPを持つサーバーにアクセス先を順番に割り振ってゆくことで、ドメイン名の同一性は保持されたままでサーバーコンピューターのアクセス集中によるトラブルを防ぐことができる。


## 分散対象サーバに均等にリクエストを振り分ける方式

各サーバで処理するリクエストの数が均等になるため、平均的にはサーバの負荷も均等。 

### 前提

分散対象サーバの全てが、同じ処理能力を持っている事



# ラウンドロビンという言葉の別の使われ方

マルチタスク処理やタイムシェアリングシステムなどにおけるコンピューター処理の並列化の意味でも用いられる。
前述したように際限のあるリソースを順繰りに割り振って行くことをさすため、ドメインに限らず、CPUの処理系にも適用できるため。


ひとつのCPU（処理装置）に対して複数の処理要求が出されている場合に、各処理は一定時間ずつ分割して順番に実行されてゆく。
一定時間の割り当てを終えたプロセスは中断され、再び順番が回ってくるまで待機する。
このとき各プロセスに割り当てられる時間（の断片）は、タイムスライスないしはタイムクォンタムと呼ばれる。
マルチタスク処理などでは処理時間が必ずしも一定ではないが、ラウンドロビン方式では例外なくすべてのプロセスが均等に扱われる。





# 参考

[Weblio 辞書 > コンピュータ > IT用語辞典 > ラウンドロビンの意味・解説](https://www.weblio.jp/content/%E3%83%A9%E3%82%A6%E3%83%B3%E3%83%89%E3%83%AD%E3%83%93%E3%83%B3)
Kotlin1.3-m1での変更、追加点とinline classについて

1.3のm1きましたわーい

# Kotlin1.3 m-1での変更、追加点
* `coroutines`がexperimentalからstableになった
* `when`の`()`の中で変数宣言できるようになった
* `@JvmStatic`と`@JvmField`を`companion object`内で使えるようになった
* `annotation calss`をネストして宣言できるようになった。
* 新たに`inline class`が追加
* 符号なし整数型の追加
* `SuccessOrFailure`クラスの追加
* Multiplatform random number generator
* `Boolean`型に`companion object`を追加
* `Collection`,`Map`,`Array`型の拡張関数`isNullOrEmpty`の追加と`Sequens`型の拡張関数`orEmpty`の追加

## 詳細
詳細については、`inline class`についてをピックアップしたいと思います。

## 1.3-m1を使うには
`kotlin-eap`のリポジトリを見に行く必要があります。
とりあえず、gradleのスクリプトをぺたり

```build.gradle.kts
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    kotlin("jvm") version "1.3-M1"
}

repositories {
    maven { setUrl("http://dl.bintray.com/kotlin/kotlin-eap") }
    mavenCentral()
}

dependencies {
    compile(kotlin("stdlib-jdk8"))
}

tasks.withType<KotlinCompile> {
    kotlinOptions.jvmTarget = "1.8"
}

```

こんなかんじ、GradleのスクリプトをKotlinで書いてるけどgroovyの方でもまぁ大体一緒

## inline classについて
`inline class`には通常のクラスとは違って以下の制約があります。

* `primary constructor`に必ず一つの`read-only`な`property`のみを持つ必要がある
* `backing field`を持つ`property`は定義できない  
* `initializer block`を持てない
*  `===`での比較は不可能

等など、インライン展開されるので当然といえば当然の制約です。
なんか色々あるから漏れがあるかもしれない😔

簡単な例と、あとはコンパイルされた時のイメージをコードで表したいと思います。

```Age.kt
inline class Age(private val value: Int) {
    fun birthYear(): LocalDateTime {
        //todo 雑
        val now = LocalDateTime.now()
        return LocalDateTime.of(now.year - value, now.month,
                now.dayOfMonth, now.hour, now.minute)
    }
}

```

```Main.kt
fun main(args: Array<String>) {
    val age = Age(14)
    println(age.birthYear())
}
```
実行結果はこんなかんじ

```
2004-07-30T13:38
```

なんか`primary constructor`のプロパティは`private`にもできるみたい
なぜ

`main.kt`をコンパイルした際の動作の簡単なイメージとしてはこんな感じになります。

```compiled.kt
fun main(args: Array<String>) {
    val age = 14
    val var1 = Age$Erased.birthYear(age)
    println(var1)
}

```

`inline class`が持っているプロパティをその場に展開をして、メソッド呼び出しは関数呼び出しに置き換える感じ？(語彙力が無い)

なんでプロパティに`private`を当てられるようになっているのかはよくわかんない。

`typealias`に似てますけど、代入互換性はありません。
`typealias`やプロパティへの命名と違ってある程度の制約を設けることが可能なので、使用用途としては既存の型のロールとそれに対する操作をまとめたりするのに便利そうだなぁという感想

#### 追記
`SuccessOrFailure`クラスが`inline class`だったなぁと
こういう使い方ならたしかに`inline class`のプロパティに`private`が当てられるようにされてるのも納得しました
Karabiner-ElementsでViカーソル移動(Ctrl+hjkl)+範囲選択(Shift)を使えるようにする

## 概要

* OSがSierraになってから[Karabiner](https://pqrs.org/osx/karabiner/)が使えなくなって[英かな](https://ei-kana.appspot.com/)を使っていた
* Karabiner-Elementsに出戻りしようとしたときにShift+hjklによる範囲選択が出来なかったので戻れなかった
* いつの間にか使えることを発見してやっと出戻り出来たメモ


## 方法

Complex ModificationsのAdd ruleでルールを選択する画面に遷移し、以下を選択する。

<img width="998" alt="スクリーンショット 2018-07-30 13.49.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/8105/3fb28848-4927-5fd4-5fd8-10c3826abce4.png">
git grepでperl互換の正規表現を使えるようにする

- [Git - git-grep Documentation](https://git-scm.com/docs/git-grep#git-grep--P)

perl互換の正規表現をつかってgit grepする場合は `-P` オプションをつけると出来るが、
これはgitのインストール時に`USE_LIBPCRE` フラグをたててないと使えない

> $ git grep -P ',,,\D'
> fatal: cannot use Perl-compatible regexes when not compiled with USE_LIBPCRE

これまでmacだと `brew install git --with-pcre` とすればよかったらしいが
この方法はdeprecatedになったとのこと

> Now in March 2018: Warning: git: --with-pcre was deprecated; using --with-pcre2 instead! So you'll have to brew reinstall --with-pcre2 git

2018年だと下記のオプションでいれることになる

```
$ brew reinstall --with-pcre2 git
```

### 参考

- [git-grepでPerlの正規表現を使えるようにする（Homebrew) - Qiita](https://qiita.com/checkpoint/items/5178df5f9fb6915e9f7b)
- [macos - How to install Git with PCRE support on OSX with homebrew? - Stack Overflow](https://stackoverflow.com/questions/22055390/how-to-install-git-with-pcre-support-on-osx-with-homebrew)
Ionic 4とFirebaseでチャットアプリ ~事前準備~

# 事前準備

この記事の内容は、[Ionic 4とFirebaseでチャットアプリ](https://qiita.com/s_kozake/private/6c7a0cec75c957606a33)の事前準備です。
ハンズオンは、Git、Node、Ionic、Visual Studio Codeのインストールが必要です。

## Gitのインストール

ターミナル、もしくはコマンドプロンプトで次のコマンドを実行してください。

```
git --version
```

gitのバージョン表示がされた場合は、すでにGitがインストール済みのため、インストールは必要ありません。   
インストールされていない場合、次のサイトにアクセスしてインストールをお願いします。

https://git-scm.com/downloads

## Nodeのインストール

ターミナル、もしくはコマンドプロンプトで次のコマンドを実行してください。

```
node -v
```

バージョンが表示された場合は、、すでにNodeがインストール済みのため、インストールは必要ありません。   
インストールされていない場合、次のサイトにアクセスしてインストールをお願いします。    
サイトのLTSと表記されたバージョンをインストールして頂ければ、問題ありません。

https://nodejs.org/ja/

## Ionicのインストール

ターミナル、もしくはコマンドプロンプトで次のコマンドを実行してください。

```
ionic --version
```

バージョンが表示された場合は、Ionicはすでにインストール済みです。   
インストールされていない場合、次のコマンドを実行してインストールをお願いします。   

(Mac OSの場合)
```
sudo npm install ionic -g
```

(Windowsの場合)
```
npm install ionic -g
```

## Visual Studio Codeのインストール

ハンズオンではVisual Studio Codeを用いて開発を行います。   
インストールされていない場合、次のサイトにアクセスしてインストールをお願いします。   

https://code.visualstudio.com/

※ VSCodeの拡張機能で「Ionic Extension Pack」をインストールすると便利です。ハンズオンでは必須ではありませんが、興味のある方はインストールしてください。


# 事前準備後の確認

事前準備後の確認として、Ionicのサンプルプロジェクトが作成します。
任意のディレクトリで次のコマンドを実行してください。

```
ionic start handson-check blank --type=angular
```

`Integrate your new app with Cordova to target native iOS and Android? (y/N) `の問い合わせは、`N`を選択してください。

`Install the free Ionic Pro SDK and connect your app? (Y/n)`という問い合わせが表示された場合は、`N`で構いません。

成功した場合、次のコマンドを続けて実行してください。

```
 cd ./handson-check
```

```
ionic serve
```

Ionicのサンプル画面が起動したら、事前準備後の確認は完了です。
知らないと少し損してそうな、attrを使った擬似要素

割と知らない人もいたので共有。

##概要
メニューボタンを作っていたら、構造がよろしくなかったのでそういえばattrってあった気がすると思い使ったら、スッキリ書けていい感じになった。

##実装
<p data-height="208" data-theme-id="0" data-slug-hash="gjoYYy" data-default-tab="result" data-user="mild-tanama" data-pen-title="button hover animation" class="codepen">See the Pen <a href="https://codepen.io/mild-tanama/pen/gjoYYy/">button hover animation</a> by mild-tanama (<a href="https://codepen.io/mild-tanama">@mild-tanama</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

##やったこと
上のようなボタンのアニメーションをかける時って、色違いのボタンを用意して重ねて、表示領域をアニメーションさせる、といったような実装が主流かと思います。その重ねるのって大方擬似要素の出番ですよね。もともとは以下のような感じで実装していました。

```html:html
<ul class="menu">
  <li class="apple">APPLE</li>
  <li class="orange">ORANGE</li>
  <li class="banana">BANANA</li>
  <li class="pigeon">PIGEON</li>
</ul>
```

```css:css
/* 諸々略 */
.menu li:before {
  /* 色々なスタイル・略 */
}
.menu li.apple:before {
  content: "APPLE";
}
.menu li.orange:before {
  content: "ORANGE";
}
.menu li.banana:before {
  content: "BANANA";
}
.menu li.pigeon:before {
  content: "PIGEON";
}
```

長い…
クラスがたくさんできてしまい、contentに文言を入れるだけの単調なcssが並んでしまう…
こんな風に、contentにいろんな文字が入るタイプのボタンだと面倒かつcssが長くなってしまいます。
そこで、今回紹介するattrを。

```css
content: attr(data-text);
```

これを使えば、要素のカスタムデータ(今回の例ではdata-text)から文字を拾ってこられる…！
以下のような感じで簡単に文字を取ってきてくれます。

```html:html
<ul class="menu">
  <li data-text="APPLE">APPLE</li>
  <li data-text="ORANGE">ORANGE</li>
  <li data-text="BANANA">BANANA</li>
  <li data-text="PIGEON">PIGEON</li>
</ul>
```

```css:css
.menu li:before {
  content: attr(data-text);
  /* 色々なスタイル・略 */
}
```

さっきみたいにクラスをだらだら書かなくて済むのでコード短縮にもなり、また文言変更になった場合もhtmlの編集だけで済むのでかなり便利。

（2018/07/30追記）
コメントで頂いたように、attr(class)でつけてあるクラス名も取れます。ただ、スタイル当てたいわけではないので今回のような場合はカスタムデータを利用しています。
基本的にjQueryのattrと同じような感じで、指定してあげればその要素の指定した値が取得できるので有難い。。

##メリット

- コード短縮
- 文言変更に強い（運用しやすい）

##デメリット
パッと浮かばないですね…何かあればお教えいただきたいです。

https://developer.mozilla.org/en-US/docs/Web/CSS/attr
一応全ブラウザ対応しております。（ただしcontentに使う場合のみ）

##まとめ
とっても便利なので使っていきましょう！！
MindMup2 > Collaborative maps will stop working in December 2018 > Google Drive integrationの変更(2018-12-11)に関係

```txt:動作環境
Windows 10 Pro (64bit) バージョン 1803 (April 2018 Update)
Google Chrome バージョン: 67.0.3396.99（Official Build） （64 ビット）
```

### 上部メッセージ > Collaborative maps will stop working in December 2018

2018年7月30日現在、Google Drive上のMindMup2ファイルを編集時、下記のようなメッセージが上部に表示される。

> Collaborative maps will stop working in December 2018

「MORE INFO」というボタンをクリックすると下記が表示される。
https://www.mindmup.com/resources/google_realtime_deprecation.html

> Google announced that they will stop providing the Realtime API capabilities for Google Drive files to third party applications (such as MindMup).

GoogleのRealtime API機能の変更と関係している([Google Drive > 3rd パーティへのRealtime API capabilities の停止 (2018-12-11)](https://qiita.com/7of9/items/a328fd0f331f9f1feaa2))。

> The change will take effect from December 11th 2018, 

2018年12月11日までに移行作業が必要になる。

<!--
### 移行ツール

リンク先の下の方にある「Key actions you may need to take」が参考になる。
下記の移行ツールもあるようだ。

> To move files from Google Drive to MindMup Cloud, use the [Import from Google Drive](https://app.mindmup.com/migrate_from_google.html) page.

あと4カ月ちょっと。
そろそろ試用をすべき時期かもしれない。

MindMupファイルは280個程度ある (2018年7月30日現在)。

移行時は移行元ファイルを今後間違って修正しないように、名前を変更するなどの工夫は必要だろう。
-->

### 残念な点

これまではGoogle Driveから色々なファイルがアクセスできた。

今後はサービスごとにそれぞれのストレージなどを使うとなると利便性が低下するだろう。

draw.ioはどうなるのか?
udev ルールファイルの参考サイト

* ファイルの書き方

https://docs.oracle.com/cd/E39368_01/E41138/html/ch07s03.html

https://www.novell.com/ja-jp/documentation/sles11/book_sle_admin/data/sec_udev_rules.html

http://www.usupi.org/sysad/115.html


---

* 設定の反映方法

 sudo /etc/init.d/udev reload

http://d.hatena.ne.jp/pyopyopyo/20160223/p1