OmniAICreator/Qiita-1.07M huggingface dataset:
google-images-downloadの使い方


# 概要

機械学習において、学習用の画像を簡単に集めるために
Google画像検索機能を使用し検索対象の画像をまとめて簡単に収集できるツールを見つけました
インストールも簡単にでき、今後また使うことがありそうなため、メモを残しておきます

・環境情報
Windwos10 Pro
Anaconda 1.9
Python 3.X

# インストール・実行手順

1.ツールをインストール
以下のpipコマンドでインストール
pip install google_images_download

2.一括画像取得を実行
例：山の手線の電車の画像を収集する場合
googleimagesdownload -k "山手線" -la Japanese -l 20 -f "jpg" -s medium

オプション
k  : 検索キーワード
la : 検索言語
f  : 画像ファイル形式
l  : 取得画像枚数　※1
s  :画像ファイルサイズ
※1 指定枚数よりも検出枚数が少ない場合はエラーになる

実行すると以下のようにファイルのダウンロード状況が表示される

```:
Item no.: 1 --> Item name = 山手線
Evaluating...
Starting Download...
Completed Image ====> 1. 0133-743x418.jpg
Completed Image ====> 2. large_171218_yamanote_01.jpg
Completed Image ====> 3. nc42901?size=l.jpg
Completed Image ====> 4. large_161021_yamanotesen_01.jpg
Completed Image ====> 5. pixta_4590983_s.jpg

```

# 実行結果

画像ファイルがダウンロードされると、実行パスの配下に「downloads」フォルダが
さらにその配下に検索キーワードの名称のフォルダが作成され、ダウンロードされた画像ファイルが置かれる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172093/9f12aaae-4f83-0a40-77e9-93d1acc37bf2.png)

上記でダウンロードした「山手線」画像の一覧です、山手線の路線図等、関係ない画像もダウンロードされてしまうため、最後は手動で取り除く必要ありです




以上
【Python】Window10にMecabをインストール

##Macabのインストール
MeCabのプログラム本体をダウンロード
（公式の32bit版ではなく、64bit版）

https://github.com/ikegami-yukino/mecab/releases/tag/v0.996

インストール時にUTF-8を選択

##環境変数の変更
スタート→設定→「システムの詳細設定」を検索→詳細設定の「環境変数」
「システムの環境設定」のpathを選択して編集

新規で
C:\Program Files\MeCab\bin
を追加

##mecab-pythonの導入

Anaconda Promptを起動

~~~python
pip install ipykernel
pip install mecab-python-windows
~~~

インストールが完了したら、
C:\Program Files\MeCab\bin
にある"libmecab.dll"を
(Anacondaのインストール先)/Lib/site-packages
にコピー＆ペーストする。

##インストール確認
Spider上で下記を実行

~~~python
import sys
import MeCab
m = MeCab.Tagger ("-Ochasen")
print(m.parse ("すもももももももものうち"))
~~~

すもも     スモモ     すもも     名詞-一般 
も       モ       も       助詞-係助詞
もも      モモ      もも      名詞-一般 
も       モ       も       助詞-係助詞
もも      モモ      もも      名詞-一般 
の       ノ       の       助詞-連体化
うち      ウチ      うち      名詞-非自立-副詞可能
man posix c / c++ stdlib とISO C

# C言語 POSIX 関数

```
# 関数の一覧
man POSIX #macos
man printf
```
## ISO C言語の仕様書
- C11
    - [N1570 Committee Draft — April 12, 2011 INTERNATIONAL STANDARD ©ISO/IEC ISO/IEC 9899:201x Programming languages — C](http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf)
- C99
    - [ISO/IEC 9899:TC3 Committee Draft — Septermber 7, 2007 WG14/N1256](http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf)
- その他
    - [https://port70.net/~nsz/c/](https://port70.net/~nsz/c/)

# C++ stdlib
### 参考サイト
- [stack overflow - how to get c++ man pages on os x?](https://stackoverflow.com/questions/32301363/how-to-get-c-man-pages-on-os-x)
- [jeaye/stdman](https://github.com/jeaye/stdman)

```
#brew install stdman #macos
man std::string
man std::cin,wcin
```
【初心者】UNIXコマンド

## はじめに
UNIXコマンドは使えて当たり前
当たり前だからこそ、しっかり覚えとかないとマズイですね。
ここでは自分なりによく使うコマンドをメモがわりに記述しています
**※UNIXコマンドとは？とかなぜ使えた方が良いか？などは割愛しています。本記事はシンプルにコマンド集となっております**

## ls
ディレクトリ(フォルダ）配下のファイルを一覧するコマンド
使い方

```
$ ls ディレクトリ（フォルダ）名
```
でフォルダの配下にあるファイル一覧を表示します

## tab補完
### ディレクトリ名、ファイル名の補完
例

```
$ /etc/
```
etcというディレクトリが存在した場合
tabキーを一回押すと、
**etc/の配下にあるディレクトリ、ファイル名一覧が表示される。**
また、例えば

```
$ /etc/d
```
上記の状態でtabキーを一回押した場合、dから始まるディレクトリ、ファイル一覧が表示される。
もちろん、無い場合は反応しない。
ここではディレクトリ、ファイル名補完の使い方のみの説明にしておく。

## pwd
現在のディレクトリを表示してくれる

```
$ pwd

$ 現在のディレクトリ
```

## cd
ディレクトリを移動するコマンド
作業したいディレクトリに移動するときに使います。

```
$ cd 移動したいディレクトリ名
```

## mkdir
ディレクトリを作成するコマンド

```
mkdir 任意のディレクトリ名
```
で作成することができます

## rmdir
ディレクトリを作ったということは消すこともできるはずです。
その時にはこのコマンド
**※ただし空のディレクトリのみ削除できます**

## rm -rf
じゃあ中身がある時は？ってなりますね！
そういった場合はこれです

## cat
```
$ cat ファイル名
```
ファイルの中身を閲覧できる
もっと便利な使い方はあるが、とりあえずシンプルにここまで

## tail
自分が特に便利だと思った機能のみ紹介なので他にも使い方はあるが割愛しています
便利だと思ったのは**ログ監視**です
使い方

```
$ tail -f ファイル名
```
これでリアルタイムでログの監視が可能です
エラーがでた際にすぐ分かるのでお世話になっています

## まとめ
まだまだコマンドはたくさんあり、その使い方もたくさんあるが、独断と偏見で紹介してみました

## 参考文献

https://qiita.com/mtakehara21/items/43785df359eb276adee2

https://qiita.com/n_oshiumi/items/df73687f18d2e1d2ad94
Alexaで音声ショッピングを開始する為に、ユーザー側がアプリ上で必要な設定があるんや




Alexaスキル内課金を使うには、利用者自身がAlexaアプリで「音声ショッピングを解除」する設定が必要です。さらに、それだけでなく、「1-click設定」もしておかないとダメなのです。
現状のAlexaアプリのガイダンスだけでは絶対わからないので、通しのフローをメモっときます。



## Alexaで音声ショッピングを開始する為のユーザー設定

alexaアプリの左上の三本線をタップ
↓

<img width="300" alt="a_1IMG_5262.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/d0c1f005-dc92-21e5-5283-931adfc95750.png">
「設定」をタップ
↓

<img width="300" alt="a_2IMG_5263.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/21783ba7-59dd-4451-647e-156367f37ccb.png">
「Alexaアカウント」をタップ
↓

<img width="300" alt="a_3.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/c185496a-092c-c550-5c95-6adf63d2c2b2.png">
「音声ショッピング」をタップ
↓
<img width="300" alt="a_4.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/09022f1d-0f00-7da7-fadc-76ec9e30576c.png">
「音声による商品の注文」をオンにし、
**「1-click設定を確認」 をタップ（ここが大事）**
↓

下記はすでに設定済みの場合の画面なんでちょっと違いますが、
「お支払い方法を編集」というボタンは共通なので、それをタップして、
クレジットカード情報を入力してください。
<img width="300" alt="a_5.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/588d6b94-f8aa-92fe-c419-c14aa27d5a70.png">

これでAlexaでの音声ショッピングが可能になります。

## ついでにセキュリティ対策を入れようぜ

主題とはそれますが続けます。

ここまでの設定だけでは、パスワード的なものを聞かれずに「買いますか？」「はい」だけでショッピングが完結してしまい、便利なんですが若干怖いですね。
一人暮らしなら問題ないけど、家族で共有してる場合、知らないうちに買い物されてしまってた。。という事は避けたいでしょう。

「決済直前に、アレクサが必ず4桁の確認コードを聞いてくるようにする」という設定ができるので、確実に入れておいた方が良いと思います。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/af3df36e-b41d-d9d3-8d27-ce180c1dc24f.png">


<img width="300" alt="a_6.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/bad153f8-7579-43b8-b324-586fd8f7750e.png">
4桁の数字を入力。


さらに、毎回入力するのがかったりぃという人の為に、
**「登録済みの音声からの命令だったら２回目以降は確認コードを聞いてこない」というハイテクな設定もできます。**


<img width="300" alt="a_7.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/137d9194-d49a-fc29-a90f-d921c4bf3795.png">

この機能をオンにすると、何回か決まったセリフを喋るように指示され、音声（声紋？）を登録するフローに進むはず。
私は以前音声登録しちゃってたので、そこのスクショは取れませんでした。あしからず。



## 開発者のジレンマ

* 音声ショッピングをONにする
* 1-clickを設定する

これをユーザーさんに設定してもらう事が、ここ数ヶ月でリリースされる課金スキルではハードルが高そう。人柱。

自分も、[AAJUGの勉強会で、せーのさんが「ここ大事！1-clickの設定が必要ですよおおおお！」と絶叫してた](https://aajug.connpass.com/event/135040/)のに忘れてて、翌日に開発用の別アカウントで以下のエラーが出てハマりました。

```
"name": "Upsell",
"payload": {
"purchaseResult": "ERROR",
"productId": "amzn1.adg.product.ほげほげ",
"message": "Upsell was blocked due to lack of purchase permission."
},
```


ちなみに、音声ショッピング自体がオフになってた場合は、Alexaが自動で以下のガイダンスを出してくれるのを確認しました。

![スクリーンショット 2019-06-23 13.57.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173392/63a95aae-350d-eb96-1d52-491955bd3e3f.png)

**1-click未登録の時のエラーも自動で拾ってくれないかなぁ。。アマゾンさん。。（チラッチラッ）**

違うんじゃねーかとか、何かおかしいところとかあったらご指摘ください。
（そもそも出たばっかりなので、数日経ったら仕様変わってるかもしれんですが、確認しまっす！）

現場からは以上です！
決定版！Macbook Wi-Fi安定化スクリプト

MacbookのWi-Fiが不安定で悩まされ続けてきましたが、不具合を自動検出してWi-Fiをoff/onするスクリプトによって安定化に成功しました！

たいした内容ではないですが、効果てきめんだったので共有します。

<font color="Red">2019/12/1更新 Macがスリープ復帰した直後かどうかを判定して無駄にWi-Fi再起動しないように修正するとともに、自分で最適と思ったタイマーチューニングをしました。ソースのみ変更しています。</font>

<font color="Red">2020/9/6更新 若干の最適化、メッセージの追加修正、ゲートウェイアドレスとWi-Fiデバイス名の自動取得、など対応しました。ソースのみ変更しています。</font>

<font color="Red">2022/7/4更新 かなり品質が悪いWi-Fiネットワークに接続した際、起動直後のゲートウェイ取得ができなくて止まってしまう状態を改善しました。ソースのみ変更しています。</font>

<font color="Red">2022/10/13更新 バグを修正しました。ソースのみ変更しています。</font>

# 1. Wi-Fi不安定の症状

こんな症状です。

+ MacBook Pro (13-inch, 2018, Four Thunderbolt 3 Ports)。購入時はHigh Sierraでしたが、Mojaveにアップデートした以降に症状がひどくなった気がします。
+ Wi-Fiルータは、Buffalo WSR-2533DHPL。
+ 使用中のWi-Fiが突然接続できなくなり、しばらく回復しません。Wi−Fiルータとの間のpingが疎通できない状態になります。
+ Macbookか接続できない時に、同じWi−Fiをスマホとかで利用できています。そのため、Macbook固有の症状であることがわかります。
+ Macbook側の上部メニューバーからWi-Fiを手動でoff/onすると復旧します。
+ 発生頻度はバラバラで、数時間発生しないこともあれば、10分以内に再発することもあります。
+ ネットでも類似症状は多数報告されていますが、対策として書かれている手段（bluetooth off、IPv6 off、DHCP off、SMCリセット、Wi-Fiルータ側のチャネルを固定する、等）はいずれも効果ありませんでした。

# 2. 安定化スクリプト

何をやっても解決しなかったのですが、このスクリプトを仕掛けることで、スッキリ解決しました。Wi-Fi不安定時に手動でWi-Fi off/onして復旧させていた動作を、スクリプトで自動化したことになります。

+ 以下のスクリプトを、ホームディレクトリ等に置いて、実行可能にして、ターミナルから　./auto_network_recover.sh などで実行してください。あとはターミナルを閉じないで放置しておくだけで、Wi−Fi不具合を自動検出して復旧します。
+ sleepタイマーや、ping繰り返し数などは、必要に応じてチューニングしてください。

```bash:auto_network_recover.sh
#!/bin/bash

restart_wifi()
{
	while :
	do
		echo 'Try to restart Wi-Fi network.'
		networksetup -setairportpower $device off
		networksetup -setairportpower $device on
		echo 'Restarted Wi-Fi network. Wait a while to recheck.'
		sleep 10	
		target=`networksetup -getinfo Wi-Fi | awk '/^Router/{print $2}'`
		device=`networksetup -listallhardwareports | awk '/Wi-Fi/{getline; print $2}'`
		if [[ -n "$target" ]]
		then
			result=`ping -c 2 $target`
			if [[ $result =~ 100.0% ]]
			then
				echo $result
				echo 'Failed to ping to gateway.'
			else
				echo $result
				echo 'Succeeded to restart Wi-Fi network.'
				break
			fi
		else
			echo 'Failed to detect gateway.'
		fi
		echo 'Restarting Wi-Fi network again.'
	done
}

while :
do
	target=`networksetup -getinfo Wi-Fi | awk '/^Router/{print $2}'`
	device=`networksetup -listallhardwareports | awk '/Wi-Fi/{getline; print $2}'`
	[[ -n "$target" ]] && break
	echo 'Cannot detect gateway at' `date`
	restart_wifi
done

echo 'Start monitoring gateway:'$target 'via device:'$device 'at' `date`
lasttime=`date +%s`
keep_failed=0

while :
do
	if [ $(( $(date +%s) - $lasttime )) -lt 60 ]
	then
		lasttime=`date +%s`
		result=`ping -c 2 $target`
		if [[ $result =~ 100.0% ]]
		then
			echo $result
			echo 'Error detected at' `date`
			restart_wifi
		fi
	else
		echo 'Wakeup Detected at' `date`
		sleep 60
		lasttime=`date +%s`
	fi
	sleep 1
done
```
新しい記事と古い記事の更新

新しい記事を書くのと古い記事を更新するのと、
どれくらい力を配分するとよいか検討中。

新しい記事の方が、新しい読者が得られる可能性がある。

古い記事を更新せずに、新しい記事だけ追加していくと、
歴史的には辿れても、新しい記事と古い記事との間の不整合がどんどん増えていく可能性がある。

新しい記事には、古い記事のURLを書いておけば、新しい記事から古い記事は辿れる。
逆に、古い記事にも、新しい記事から連携していることは、記事の最後に表示される。
辿れないことはない。

それだけでよいかどうか。

新しい記事の作成に９割、古い記事の更新に１割。
新しい記事の作成に８割、古い記事の更新に２割。
新しい記事の作成に７割、古い記事の更新に３割。

記事は１日で書き上げる場合と、
一旦書きかけで公開して、１週間から１ヶ月くらいかけて書き上げる場合がある。

ここでは、１日から１ヶ月くらいまでの書き上げたと思うまでの間を新しい記事の作成とする。
１ヶ月以上経った場合は、古い記事の更新に分類する。

＜この記事は書きかけです。順次追記します。＞
# 文書履歴(document history)
ver. 0.01 初稿 20190623
ver. 0.04 URL追記　20230302

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
Warning: Your Xcode (10.1) is too outdated. Please update to Xcode 10.2.1 (or delete it). Xcode can be updated from the App Store.

<img width="391" alt="スクリーンショット 2019-06-23 13.51.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59604/4310963f-cf46-e6ba-58d2-ffbec127e297.png">


[Xcodeインストールメモ(Xcode-10.2.1) - Qiita]
(https://qiita.com/leo1109/items/0f4c0b343b1515bbc90d)
>
Xcode-10.2.1のダウンロード
https://developer.apple.com/download/more/
から Xcode_10.2.1.xip をダウンロードする。6Gbyteくらいあったので気長に待つ。

[XcodeをAppStoreを使わずインストールしたときのメモ - xykのブログ]
(http://xyk.hatenablog.com/entry/2016/12/14/153207)
>
で、ダウンロードした xip ファイルをそのまま展開しようとすると
GateKeeperによるファイルの検証が始まりこれがまた時間がかかる。
これは xattr コマンドでファイルの拡張属性com.apple.quarantineを削除することでスキップすることができる。

```
xattr -d com.apple.quarantine Xcode_8.2.xip
```

を現在のヴァージョンにして、

```
xattr -d com.apple.quarantine Xcode_10.2.1.xip
```

# 次にやること

SpotifyAPI
VSCodeのMarkdownからのPDF変換エラー解決＆改ページ

# 概要
* PDF生成にchromiumを指定する方法
* PDF上で改ページするためにCSSを設定する方法

# 環境
* macOS Mojave 10.14.5
* Visual Studio Code 1.35.1
* Markdown PDF 1.2.0
    * https://github.com/yzane/vscode-markdown-pdf

# PDFを生成できるようにする
VSCodeで書いたMarkdownファイルからPDF生成しようとするとnewpageエラーで，tmpのHTMLが生成された状態で止まってしまう．今までは不便に思いつつもHTML生成を実行した後，ブラウザで開いてPDF化していた．

## homebrewでchromiumをインストール
```bash
$ brew cask install chromium
```
（ブラウザはお好みで．元々入れていたGoogle Chromeを指定しても動作した）

## VSCodeのsettings.jsonに以下を追記
```json
"markdown-pdf.executablePath": "/Applications/Chromium.app/Contents/MacOS/Chromium"
```

これで，`Export (pdf)`した時にエラーで終了しない．

<img width="368" alt="Export_pdf.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35035/883c900b-7563-6e7c-359f-2651fdb7ff6a.png">

# 水平線を改ページにする
調べると，以下をMarkdown中に記述することで改ページできることは分かったが，スニペットとか使いこなせていないので，Markdownだけで実現したい．

```html
<div style="page-break-before:always"></div>
```

## PDF用のCSSを用意する
```css
hr {
    border: none;
    page-break-after: always;
}
```
これを任意の場所に保存する．（ここでは，`/Users/sampleuser/Documents/markdown-pdf.css`）

## VSCodeのsettings.jsonに以下を追記
```json
"markdown-pdf.styles": ["/Users/sampleuser/Documents/markdown-pdf.css"]
```

## 使い方
以下のように水平線`---`を入れたところがPDFでは改ページになる．

```markdown
1ページ目

---

2ページ目
```
あなたのLinuxインスタンスは大丈夫？ AMIからのリストア時にcloud-initが初期化してしまう設定集

## この記事で紹介する内容
AWSでは、大抵のLinuxインスタンスに自動構成ツール「cloud-init」がインストールされています。
cloud-initの既定設定には、AMIの初回起動時に初期化を実行する項目があります。
既定設定をそのままにすると、通常利用時は問題ありませんが、リストア時にAMIから起動すると幾つかの項目が初期化されてしまいます。

この記事では、AMI起動時にユーザーデータが初期化する項目とそれを防ぐ方法を紹介します。

## 検証環境
- リージョン：ap-northeast-1
- AMI：RHEL-7.6_HVM-20190515-x86_64-0-Hourly2-GP2 - ami-04eb805483f5607a7
- インスタンスタイプ：t2.micro

## AMI起動時にユーザーデータが初期化する項目
- ホスト名（ip-XX-XX-XX-XXというPrivate IPを元にしたホスト名に設定される）

- デフォルトユーザー（ec2-userが作成される）

-  ロケール（en_US.UTF-8に設定される）

- パッケージ（セキュリティアップデートが実行される）

## 初期化を防ぐ方法

以下のコマンドで初期化防止用の設定ファイルを作成するだけです。
（タイムゾーン設定は念のため加えてますが、RHEL 7.6では初期化されませんでした）

```bash
cat >> /etc/cloud/cloud.cfg.d/99_preservesetting.cfg << EOF
repo_update: true
repo_upgrade: none
preserve_hostname: true
locale: ja_JP.UTF-8
timezone: Asia/Tokyo

system_info:
  default_user:
    name: cloudinit-user
    lock_passwd: true
    gecos: Cloudinit User
    groups: [ adm, wheel, systemd-journal ]
    sudo: [ "ALL=(ALL) NOPASSWD:ALL" ]
    shell: /bin/bash
EOF
chmod 644 /etc/cloud/cloud.cfg.d/99_preservesetting.cfg
chown root:root /etc/cloud/cloud.cfg.d/99_preservesetting.cfg
```

#### 解説
- **repo_update**：ローカルにキャッシュされたリポジトリのメタデータを更新する（true）/更新しない（false）
- **repo_upgrade**：（repo_upgrade_excludeの値を除く）全アップデートを適用する（all, on, true）/セキュリティアップデートを適用する（security）/アップデートを適用しない（none, off, false）
- **preserve_hostname**：ホスト名を維持する（true）/維持しない（false）
- **locale**：ロケール設定をする（ロケール）
- **timezone**：タイムゾーンを設定する（タイムゾーン）
- **default_user**：デフォルトユーザーを設定する（デフォルトユーザーの情報）


以上です。
OpenCVでのK-means 法による2次元座標クラスタリング


C++ OpenCVのkmeansメソッドを使用し、K-means法の使用例でよくある
2次元座標上でのクラスタリングのサンプルを作成したので、情報を残しておきます

以下は、500×500の２次元座標上にある任意の8点に対しk-meansにより3グループに分けるサンプルです

実行環境
OpenCV 2.X

```doKmeans.cpp

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <list>

using namespace std;
using namespace cv;

//２次元のクラスタリング
void main()
{
	//プロット用画像を生成
	Mat imgMark = Mat(500, 500, CV_8UC3);

	//クラスタリング表現の色（3パターン）
	Scalar colorTab[] =
	{
		Scalar(255,100,100),
		Scalar(255,0,255),
		Scalar(0,255,255)
	};

	//クラスタリング対象ポイントを設定
	int pointCount = 8; //8ポイント分確保
	Mat points(pointCount, 1, CV_32FC2);

	//クラスタリング対象2次元座標を設定
	points.at<Point2f>(0) = Point2f(100, 200);
	points.at<Point2f>(1) = Point2f(200, 300);
	points.at<Point2f>(2) = Point2f(350, 250);
	points.at<Point2f>(3) = Point2f(450, 150);
	points.at<Point2f>(4) = Point2f(200, 100);
	points.at<Point2f>(5) = Point2f(200, 200);
	points.at<Point2f>(6) = Point2f(420, 350);
	points.at<Point2f>(7) = Point2f(450, 450);

	//クラスタリング数を定義
	int clusterCount = 3;
	vector<Point*> centerPointList(clusterCount);

	//ラベルごとのポイントリストのインスタンスを確保
	vector< vector<Point*>*> labelPointList;
	for (int i = 0; i < clusterCount; i++)
	{
		labelPointList.push_back(new vector<Point*>());
	}

	//K-means実施
	Mat centers;	//各グループの中心座標を受け取る変数
	Mat	labels;		//各グルーピングごとのポイントを受け取る変数
	kmeans(points
		, clusterCount
		, labels
		, TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0)
		, 3
		, KMEANS_PP_CENTERS
		, centers);

	//各ラベルのポイントを取得(各Labelがrows)
	for (int i = 0; i < points.rows; i++)
	{
		//分類のインデックスを取得
		int labelIndex = labels.at<int>(i);
		//分類元の座標を取得
		Point ipt = points.at<Point2f>(i);

		vector<Point*>* pointList = labelPointList[labelIndex];

		pointList->push_back(new Point(ipt.x, ipt.y));

		//位置に分類を色別に表示
		circle(imgMark, ipt, 10, colorTab[labelIndex], 2, 4);
	}

	//各ラベルの中心を取得(各Labelがrows)
	double sse = 0;
	for (int labelIndex = 0; labelIndex < centers.rows; labelIndex++) {

		//中心座標を取得
		int centersX = centers.at<float>(labelIndex, 0);
		int centersY = centers.at<float>(labelIndex, 1);

		//位置に分類を色別に表示
		Point* centerPoint = new Point(centersX, centersY);
		circle(imgMark, *centerPoint, 20, colorTab[labelIndex], 8, 8);
	}

	//クラスタリング結果を表示
	namedWindow("Kmeans", WINDOW_NORMAL);
	imshow("Kmeans", imgMark);
	waitKey(0);
	destroyAllWindows();
}
```

上記を実行すると以下のように各グループごとに色わけされた結果が表示されます
小さい円はグルーピング対象の座標の位置を示し、大きい円は各グループの中心位置を示しています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172093/8bc50bf6-dd17-03a5-7517-6d2609aa8630.png)
Java1.4でのJsonシリアライズ・デシリアライズ

#概要
今の時代Java1.4を使用しているは少ないかもしれせんが、
Java1.4で作られた業務アプリにてJsonのシリアライズ、デシリアライズをする必要があり、調査した結果を記載します。

#結論
ObjectMapper（Jackson）はJava1.4では使えないので以下を使用すれば可能です。

* xstream-1.2.2
* jettison-1.0
* stax-api-1.0.1

#ライブラリの追加
Mavenを使用している場合は以下の依存関係追加してください。
jarが欲しいかたは以下URLから取得してください。

```
<!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
<dependency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.2.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.codehaus.jettison/jettison -->
<dependency>
    <groupId>org.codehaus.jettison</groupId>
    <artifactId>jettison</artifactId>
    <version>1.0.1</version>
</dependency>

<!-- https://mvnrepository.com/artifact/stax/stax-api -->
<dependency>
    <groupId>stax</groupId>
    <artifactId>stax-api</artifactId>
    <version>1.0.1</version>
</dependency>
```

#シリアライズ
ServletにてリクエストのJsonをPersonクラスにシリアライズするサンプルです。

```java
// 省略
BufferedReader r = new bufferedReader(request.getReader())
string rewuest = r.readLine()
XStream x = new XStream(new JettisonMappedXmlDriver())
Person s = (Person)xstream.fromXML(x)
```

#デシリアライズ
Personクラスをデシリアライズしてレスポンスを返すサンプルです。

```java
response.getWriter().xstream.toXML(Person)
```

#参考サイト
https://x-stream.github.io/json-tutorial.html
Unsupported config option for web service: 'container_name'

## エラー内容

`Unsupported config option for web service: 'container_name'`

container_nameがサポートされていない……？

## 原因

docker-composeのバージョンが古い。
container_nameは[1.4.0から](https://docs.docker.com/compose/release-notes/#140)。

## docker-composeのバージョンを調べるには

`docker-compose -v`


```
# docker-compose -v
docker-compose version: 1.3.1
CPython version: 2.7.9
OpenSSL version: OpenSSL 1.0.1e 11 Feb 2013
```

## docker-composeのバージョン

`1.3.1`

https://docs.docker.com/release-notes/docker-compose/#131
によると、2015-06-21とのこと（ちなみに今日は2019-06-23。4年経過）。なんでこんなに古いんだ……

## docker-composeのバージョンアップ

https://docs.docker.com/release-notes/docker-compose/#131
で見たところ、最新は1.24.0のようなので、それをURLに組み込んでcurlを実行。

`curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose`

## docker-composeのバージョンを再度確認する

`docker-compose -v`

```
docker-compose version 1.24.0, build 0aa59064
```

表示内容がdocker-composeだけになってますね。
YAMLから要素を削り取って軽量化するnpmパッケージ作った

# YAMLから要素を削り取って軽量化するライブラリ作った
YAMLファイルを軽量化するnpmモジュールを作りました。指定した要素を削除または空白にします。

以下に公開してあります。

- [npm / yaml-scraper](https://www.npmjs.com/package/yaml-scraper)
- [GitHub / yaml-scraper](https://github.com/segurvita/yaml-scraper)

`scraper` というのは削り取るというニュアンスの言葉です。
ちゃんと Travis CI のバッジも付けてます！


# なにができるのか？

こんな感じのYAMLファイルがあるとします。

```yaml
sample:
  hoge: これは消したい
  fuga: これは空白にしたい
  hogehoge:
    hoge: これも消したい
    fuga: これも空白にしたい
    hogera: これはこのまま
  piyopiyo:
    piyo: これの親を消したい
```

↑のYAMLに対し、以下のようなことができます。

- key が `hoge` の要素はいらないから削除する
- key が `fuga` の要素はいるけど、value はいらないから空白に置換する
- key が `piyo` の要素の親要素はいらないから削除する

処理結果として、以下の文字列を出力します。

```yaml
sample:
  fuga: ''
  hogehoge:
    fuga: ''
    hogera: これはこのまま
```

不必要な要素を削り取って、だいぶYAMLファイルが軽くなりました！
階層のどこにあっても見つけだして削り取ります！



# なぜ作った？

普段 Swagger を使って、WebAPIのドキュメントサイトを作っています。
このSwaggerファイルをAmazon API Gatewayにインポートしたところ、容量制限のエラーが発生しました。
このエラーを回避するために、不要な要素を削り取るライブラリを作りました。



# インストール方法

本ライブラリの仕様にはNode.jsが必要です。

Node.jsがインストール済みであれば、以下のコマンドでインストールできます。

```bash
npm install yaml-scraper
```


# サンプルコード
先ほどの処理のサンプルコードは以下の通りです。

```javascript
// ライブラリを追加
const fs = require('fs');
const scraper = require('yaml-scraper');

// YAMLファイルを読み込み
const input = fs.readFileSync('./sample.yaml', 'utf8');

// hogeを削除、fugaを空白に置換、piyoの親を削除
const output = scraper(input)
  .delete('hoge')
  .empty('fuga')
  .deleteParent('piyo')
  .toString();

// 結果を表示
console.log(output);
```

御覧の通り、 `delete`, `empty`, `deleteParent` はメソッドチェーンとして提供しています。



# さいごに

開発するにあたり、以下の記事を参考にしました。
とてもわかりやすい記事ありがとうございました。

- [JavaScriptでメソッドチェーンを作る](https://qiita.com/sawapi/items/279531c88709700d0ff1)
- [初めてのnpm パッケージ公開](https://qiita.com/TsutomuNakamura/items/f943e0490d509f128ae2)
webページって大まかに、どんな風に作られてるの？(超初心者)

webページって、なんだかすごくかっこよく見える。
でも、自分のワードとかに書いてるメモ書きって、
なんだか味気ない・・・

これってなんで！？
webページってどうやって作られてるの？？

どうやらwebページは、
HTML
と
CSS
という２つの言語を主に使っているらしい。

HTMLはコードで、
CSSはHTMLで書かれたものを目に見えるようにする働きを持つ。
じゃあ具体的に、どういう風に作るかっていうと、
保存する時に、
.htmlとか、.cssっていう感じに語尾をつけることで、その言語が書かれたファイルを作ることができるよ。

webページっていうのは、すごーく簡単に言っちゃうと、
設定したスペースの中に、文字を入れることで作ることができるんだ。

で、「こんな風なスペースを作りました！」って教えてるのがHTMLで、
「じゃあこう表現すりゃいいのね？」
って実際に色だとか、文字のサイズとか間隔とか、そういうのを決めて形にするのがCSS。

例えていうなら、家の間取りを考えるのがHTMLで、そこにある壁紙とかを配置するのがCSS。


つまり！
私が
(Webページってなんかかっこいいすごーい)
とか思ってた正体は、
スペースの中に文字を入れるアレコレをうまい具合に配置してたから！！
なんじゃないかな？って思いました。

今日学んだこと
2019.6/23(土)
webページは主にhtmlとcssという言語が使われていて、
大まかな設定はhtmlで、具体的な設定はcssで作られる。
PowerShellでアクティブウィンドウのプロセスを拾う

プレイ中にゲームが非アクティブになる！
[My Window Logger](http://hohsho.web.fc2.com/mwl/)でも原因となっているアクティブになったウィンドウがわからない！
…というフレンドの要請があったので、原因調査のためにPowerShellでアクティブウィンドウになっているプロセスを拾うスクリプトを作りました。

##コードの実装
```powershell:check_activeprocess.ps1
$code = @'
    [DllImport("user32.dll")]
     public static extern IntPtr GetForegroundWindow();
    [DllImport("user32.dll")]
    public static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out int ProcessId);
'@

Add-Type $code -Name Utils -Namespace Win32
$myPid = [IntPtr]::Zero;

while(1){
    $hwnd = [Win32.Utils]::GetForegroundWindow()
    $null = [Win32.Utils]::GetWindowThreadProcessId($hwnd, [ref] $myPid)
    Write-Host (Get-Process | Where-Object ID -eq $myPid | Select-Object Name,processName,Id,Path,MainWindowTitle)
    Start-Sleep -Milliseconds 500
}
```

##コードの説明
`Add-Type $code -Name Utils -Namespace Win32`
`$myPid = [IntPtr]::Zero;`
無限ループに入る前にAddt-Typeで読み込みと変数($myPid)の初期化をしておきます。

`[Win32.Utils]::GetForegroundWindow()`
でアクティブになっているウィンドウハンドルを拾い、

`[Win32.Utils]::GetWindowThreadProcessId($hwnd, [ref] $myPid)`
で上記で拾ったウィンドウハンドルを元にプロセスIDを拾い、

`Get-Process | Where-Object ID -eq $myPid`
Get-Processで該当のプロセスIDと同じものを検索しています。

なお、上記のスクリプトではログには出力せず、ただただ結果を吐き続けるだけです。
「アクティブウィンドウになっているプロセスを拾う」という目的は達しているので、
ログとして出力が必要となれば、それなりに編集しておく必要があります。

##技術参考
[How to Get Active Process Name in C#?](https://stackoverflow.com/questions/6569405/how-to-get-active-process-name-in-c)
上記はC#ですが、PowerShellで実行出来るように編集しています。

##余談
非アクティブの原因はマカフィーのmcUIcnt.exeでした。
どうもこの非アクティブになる(フォーカスが外れる)のは昔からあるようで、マカフィーのコミュニティにおけるベストアンサーも「I gave up on this, and I switched to another virus scanner (paid).」となっていました。
参考：[McUICnt.exe steals the current windows focus every 3 hours. How can I stop this?](https://community.mcafee.com/t5/Consumer-General-Discussions/McUICnt-exe-steals-the-current-windows-focus-every-3-hours-How/td-p/462843)

My Window Loggerで検知できなかった理由はわかりませんが、WindowTitleが設定されていなかったからとかでしょうか。
他のプレイヤーの調査では上記ソフトで発見出来ていたようなので、今回が稀な例なのだと思われます。
gulpを使わないpug/scssのコンパイル

自分は基本的にhtml/cssをマークアップする際は、pug と Scss を使ってコーディングしています。

pug/Scssからhtml/CSSにコンパイルする際は、普段はgulpを使ってプレフィックスや圧縮まで一気にやっていますが、単発のLPを作るときなんかはgulpの環境を作るのが面倒だったりします。（1ページのためにgit管理するファイルが超増えるのが嫌だったり。）

そんなわけでpugとScssをgulp環境を入れずにコンパイルと監視することもたまにあります。

その時のオプションの書き方とか結構忘れるので覚書。
※global環境に pug-cli が入っている前提です。

## pug → html

```
$ pug index.pug -P -w  -o ./html
```


基本形は

```
$ pug index.pug
```


下記はオプション
`-P`： --prettyの省略記法。書き出すhtmlが整形される。
`-w`： --watchの省略記法。監視状態。監視を解くまで、ファイルを変更する度にコンパイルしてくれる。停止は Ctrl + c
`-o`： --outの省略記法。htmlを書き出すディレクトリを指定。pugとhtmlを同階層に置く場合は必要なし。

## Scss → CSS

```
$ sass --watch -t expanded style.scss:style.css
```

基本形は

```
$ sass style.scss:style.css
```

後半部分を

```
$ sass scss/style.scss:css/style.css
```

みたいな感じに変えることで、読み込むディレクトリ、書き出すディレクトリを変更。

下記はオプション
`--watch`： 監視状態。省略記法はないっぽい。停止はCtrl + c
`-t`： --style の省略記法。書き出すCSSの整形方法を指定できる。
`expanded` が自分がいつも使う見た目の整形方法。
`compressed` で圧縮版の書き出し。


pugとかScssのコンパイルのことを調べようとするとほぼgulpの記事ばかりなので、gulpを使わないコンパイルのことを書きました。
みんな、1~2ページのコーディングの時とかはどうしてるんだろう。
そもそも1ページとかだとpugとかScss使わないかな？

pugとかScssはやってる感がすごいから、1ページとかでも使いたいからなぁ。
実際に生産性上がってるかは知らんけど。

pugの環境構築は下記のサイトが良さげだったので参考までに。
[Pug（Jade）って何だ？特徴や基本的な使い方の解説](kumaweb-d.com/web/basics-of-pug/)
Let's Encrypt で "ImportError: cannot import name _remove_dead_weakref" になって ./certbot-auto renew ができない時

# 現象
エラーはこんなかんじ

```bash:
./certbot-auto renew
Requesting to rerun ./certbot-auto with root privileges...
./certbot-auto has insecure permissions!
To learn how to fix them, visit https://community.letsencrypt.org/t/certbot-auto-deployment-best-practices/91979/
Error: couldn't get currently installed version for /opt/eff.org/certbot/venv/bin/letsencrypt: 
Traceback (most recent call last):
  File "/opt/eff.org/certbot/venv/bin/letsencrypt", line 7, in <module>
    from certbot.main import main
  File "/opt/eff.org/certbot/venv/local/lib/python2.7/site-packages/certbot/main.py", line 5, in <module>
    import logging.handlers
  File "/usr/lib/python2.7/logging/__init__.py", line 26, in <module>
    import sys, os, time, cStringIO, traceback, warnings, weakref, collections
  File "/usr/lib/python2.7/weakref.py", line 14, in <module>
    from _weakref import (
ImportError: cannot import name _remove_dead_weakref
```

# やってみた対処方法
Let's Encrypt のコミュニティのフォーラムの記事 [Cannot renew certificate “ImportError: cannot import name _remove_dead_weakref”](https://community.letsencrypt.org/t/cannot-renew-certificate-importerror-cannot-import-name-remove-dead-weakref/58148)の bmw さんの投稿を参考に、とりあえず本体の方を消してみる

```bash:
sudo rm -rf /opt/eff.org
```

# なおった！
```
./certbot-auto renew
Requesting to rerun ./certbot-auto with root privileges...
Bootstrapping dependencies for Debian-based OSes... (you can skip this with --no-bootstrap)
Hit:1 http://ppa.launchpad.net/certbot/certbot/ubuntu bionic InRelease
Hit:2 http://ports.ubuntu.com/ubuntu-ports bionic InRelease
Get:3 http://ports.ubuntu.com bionic-security InRelease [88.7 kB]
Hit:4 http://apt.postgresql.org/pub/repos/apt bionic-pgdg InRelease            
Fetched 88.7 kB in 2s (46.0 kB/s)                                              
```

bmw さん、ありがとう！

# 感想
前述の bmw さん、お名前が **Brad Warren** さんっておっしゃるそうなんですが、m ってどこからきてるんだろう？
jQuery-menu-aim.jsの使い方とカーソルアウトで閉じるオプション

jQuery-menu-aim.jsはamazonのような操作性の良いメガメニューを簡単に実装できるjQueryライブラリです。

何がどう使いやすいかは[こちら](https://gigazine.net/news/20130307-amazon-mega-dropdown/)に詳しく書いてあります。

ざっくり言うと、子のメニューを選びにカーソルを動かした時に多少ずれても大丈夫な作りになっているという感じですね。


jQuery-menu-aim.jsの使い方
まずはjQuery本体とjQuery-menu-aim.jsを読み込み、

```html:sample.html
<script src="js/jquery-1.9.1.min.js"></script>
<script src="js/jquery.menu-aim.js"></script>
```

次に着火スクリプトと、アクションの記述。

jQuery-menu-aim.jsは、メニューを使いやすくするライブラリであって、メガメニューを開いたり、閉じたりするするのは、メニューの状態に合わせた記述が必要です。

```sample.js

$("#menu").menuAim({ // #menuの部分がメガメニュー全体の親要素
	activate: activateMenu,  // メニューにカーソルがホバーした時のアクション
	deactivate: deactivateMenu,  // メニューからカーソルが外れた時のアクション
	exitMenu: exitMenu // trueを返すとメニュー全体からカーソルが外れた時にメガメニューを閉じる。デフォルトは閉じずに最後に合っていたメニューが開いたままになっている
 });

    //  メニューにカーソルがホバーした時のアクションの中身
    function activateMenu(row) {
        var $row = $(row),  // カーソルの合ったラベルのjQueryオブジェクトを取得
            menuId = $row.data('menuId'), // ラベルのデータ属性を取得
            $menu = $('#' + menuId); // ラベルと紐づいた表示したいメニューのIDを取得
        $menu.css({
            display: 'block', // メニューを表示
        });
        $row.addClass('is-hover'); // 表示以外にもスタイリングしたいのでクラス付与
    }

    // メニューからカーソルが外れた時のアクション
    function deactivateMenu(row) {
        var $row = $(row),  // カーソルの合ったラベルのjQueryオブジェクトを取得
            menuId = $row.data('menuId'), // ラベルのデータ属性を取得
            $menu = $('#' + menuId); // ラベルと紐づいた表示したいメニューのIDを取得
        $menu.css('display', 'none'); // メニューを非表示
        $row.removeClass('is-hover'); // ホバークラス削除
    }

    // trueを返して、メニュー全体からマウスが離れた時にメニューを閉じるように設定
    function exitMenu(row) {
        return true;
    }
```

exitmenuの挙動がデフォルトだとメニューが閉じない設定になっているのが詰まりポイントでした。

日本語のブログだとオプションの設定まで書いていなくて設定するのに時間がかかってしまった。

やっぱり公式のリファレンスを読むのは大事だなって改めて思いました。
RaspberryPi Zero Wのセットアップ


## 概要

RaspberryPi Zero Wのセットアップを外部ディスプレイやキーボードがない環境で行う必要がありました。その際に、手元のPCとRaspberryPiをUSBケーブルのみで接続し、初期設定を行った時のメモです。
最終的に下記のような手順を踏みました。

1. RaspberryPiの起動時にSSHが起動するように設定する。
1. RaspberryPiのIPアドレスを固定する。
1. RaspberryPiがCOMで認識された場合は、RPI Driver OTGを設定する。
1. sshで固定IPに接続する。

## 環境

* PC: Windows10
* Raspberry Pi Zero W

## 手順

1. Raspbian OSをインストールしたSDカードを用意します。
1. RaspberryPiにSDカードを挿入する前に、下記の設定を行います。
    1. boot内容を書き換えOTG(On the go)を有効にする。

        ```sh
        $ touch /boot/ssh
        $ vi /boot/cmdline.txt

        dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait modules-load=dwc2,g_ether quiet init=/usr/lib/raspi-config/init_resize.sh quiet splash plymouth.ignore-serial-consoles
        ```
    1. IPアドレスの固定。実際のIPなどは適時変更してください。

        ```sh
        $ vi /etc/dhcpcd.conf

        interface eth0
        static ip_address=192.168.10.100/24
        static routers=192.168.10.1
        static domain_name_servers=192.168.10.1
        ```
1. RaspberryPiにSDカードを挿入し、PCとUSBで接続します。
    * 電源側ではないほうに接続します。
1. デバイスマネージャでRaspberryPiをCOMとして認識した場合は、[RPI Driver OTG][caron]を設定する。
1. `ssh pi@192.168.10.100`で接続する。

[caron]: https://caron.ws/

## その他

### Bonjour

幾つかのサイトを確認するとBonjourが必要と書かれていますが、おそらく固定IPにしてしまえば不要と思います。
もし必要であった場合は、Bonjourをインストールし、ファイアーウォールでUDP5353の通信を許可してください。

### RPI Driver OTG

ドライバがあるサイトは非常にドライバの探し方が難しいです。私の場合は、下記の手順でドライバのダウンロードページへのアクセスリンクを見つけられました。

1. 検索窓で、`rpi driver otg`と入力します。
1. `Pi Zero OTG Ethernet`というページが検索できるのでクリックします。
1. 真ん中あたりに`Télécharger les drivers suivant: RPI Driver OTG`とあってRPIドライバのダウンロードページへのリンクがあります。

### windows環境下でのext3の書き換え

windows環境ではext3でフォーマットされていると読み書きができません。幾つかのソフトがありますが、ext2fsdではマウントできなかったので、Paragon soft][lfswin]のお試し版でマウントしました。

[lfswin]: https://www.paragon-drivers.com/en/lfswin/
UnityでVRMデータに自動的にコライダーを生成する

##自己紹介
こんにちはゆずです。@Yuzu_Unity


#はじめに
VRMにはコライダーを保存する機能がないため
3Dゲームで使おうとすると当たり判定が取れません。
せっかくの統一フォーマットなので自動でコライダーを割り当てるものを作成しました。（ランタイム）
VRMを用いた[オンラインFPSゲームを作成しようかと…](https://twitter.com/Yuzu_Unity/status/1141774603456356357)
※メッシュデータを読み込んでいないので、かなりあいまいな実装です。
あくまでも、とりあえず使えればいいというレベルのものです。
[SAColliderBuilder](https://assetstore.unity.com/packages/tools/sacolliderbuilder-15058)レベルの精度は出ません
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/346e31a4-463b-0f57-16bf-103bcb183b97.png)

#実装内容
VRMファイルはHumanoid形式であるので
各HumanoidのボーンのTrasnformを取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/73dd70bc-10a1-4369-2f16-d11845abcf88.png)
[HumanBodyBones](https://docs.unity3d.com/ja/2019.1/ScriptReference/HumanBodyBones.html)
[Animator.GetBoneTransform](https://docs.unity3d.com/jp/460/ScriptReference/Animator.GetBoneTransform.html)

この各ボーンのTransformから体系等を推定し配置していきます。

基本的には
1. 各ボーンの親子の差のベクトル
2. 肩幅
3. 脚の付け根の左右の幅
の3つのデータから推定しコライダーを配置します。
（これしかない…）

#データ公開(ライセンスはフリーです。)
UnityPackage
https://github.com/yuzu-unity/HumanoidCollider/raw/master/HumanoidCollider.unitypackage

#使い方
AnimatorがついているオブジェクトにHumanoidColliderBuilderをAddComponentして
public void SetCollider()を実行します。
Debug用のbool isSetをInspectorで押すだけでも可


現状の機能
頭のサイズは肩幅より推定
腕、脚のサイズは脚の付け根の左右の幅から推定
しているので、特に頭のサイズはおかしくなることがあります（等身がわからないので）
UpperChest等必須ボーンがない時にも対応

Head,Body,Arm,Legの４つに分類され各コライダーに
レイヤー、タグを指定可能

実際の実行
<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">test <a href="https://t.co/qwwfEQf377">pic.twitter.com/qwwfEQf377</a></p>&mdash; ゆず (@Yuzu_Unity) <a href="https://twitter.com/Yuzu_Unity/status/1142510444684275712?ref_src=twsrc%5Etfw">2019年6月22日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308905/320a6387-677c-ee69-c4f9-71f9713c827b.png)
TECH ~Day 1~

昨日はtech入校初日でした。
今年の３月に大学を卒業し、また新しい学校の入学式の気分でした。
緊張からか前日から軽く風邪気味で１日体調があまり優れない状態だったため気分的に少し下がっていました。

入校２週間前から事前学習を行えたのでHTML、CSSまでは終わらせていたので初日はRubyからスタートしました。

昨日の学習内容としては、
　・Rubyを書く基本的な手順
　・ターミナルの書き方
　・コマンドとパス
　・irbの機能性
　・文字列、数値、メソッド、演算子、変数
　・返り値

・Rubyを書く基本的な手順
rubyを書く手順としは、
　1.rubyを書くためのファイルを作る
　2.いざプログラムを書く
　3.書いたrubyプログラムをいざ実行する
簡単にこの流れである。
ファイルはhtmlやcssを書く時に使った「vscode」で大丈夫。
書いたプログラムを実行させる時に使うのが「ターミナル」である。　


・ターミナルの書き方
ターミナルはpcに命令を出すためのリモコンのような存在。
ファイルに書いたプログラムを読み込んで実行するには、「コマンドライン」というツールが必要になる。ターミナルはもともとMacに導入されているコマンドラインであるため、使用している。


・コマンドとパス
ターミナルでpc操作をする際にコマンドを用いる。このコマンドのことを「linuxコマンド」という。
ターミナルを操作する際には最初に「linuxコマンド」を打ち込まなければならない。
「linux」は、pcの種類という意味。つまり最初にpcの種類を指定しなければいけない。
代表的なコマンドは二つ
　・lsコマンド・・・listの略。フォルダやファイの一覧を表示するコマンドである。現在進行中のカウントディレクトリの中にあるファイルやフォルダをを一覧にして表示できる。例えば、今デスクトップというディレクトリの状態でlsコマンド使うとデスクトップの中にあるフォルダやファイルが一覧として表示されるということ。

　・cdコマンド・・・ディレクトリ（フォルダ）を移動するために使うコマンド。例えばダウンロードというフォルダからデスクトップというフォルダに移動したいときなどに使う。！これはよく使う！
ここでの移動方法として「絶対パス」と「相対パス」が存在する。
絶対パスは、ルートディレクトリから移動するフォルダを指定するパス。絶対パスで指定する時は、
（例）cd /users/desktop 
　このようにcdの後に「/」をつけなければいけない。

相対パスは、現在進行中のカウントディレクトリからの指定方。これの場合は最初に「/」は必要ない。
基本的に相対パスの方が使い方はラクである。
結果この二つだ。


・irbの機能性
は今までvscodeでプログラムを書いていたが、ターミナルに「irb」を打ち込むことで、ターミナルに直接プログラムを打ち込むことができる機能である。


・文字列、数値、メソッド、演算子、変数
文字列…数字などを除いた文字そのもの。ダブルコーテーションかシングルコーテーションで囲み記述する。

数値…数値は文字列の逆で数字。コーテーションで囲わなくて良い。

メソッド…メソッドとは文字列や数値に、ある働きかけを行うもの。メソッドを使う際はメソッドの前にドットをつける。
（例）「length」これは文字列の文字数を求めてくれるメソッド。
　　「to_s」これは数値を文字列に変換してくれるメソッド。
　　
演算子…一般的な数式記号「＋足し　−引き　*掛け　/割 　%剰余（例）１７を５で割った時のあまりを求められる」
比較演算子（>,<,,>=,<=,==)…値同士を比較する時に使用する。返り値は、true or false。

not演算子（！）…（例）2 * 3 != 6 =false これはビックリマークをつけることによってこの式は等しくない！と言いたいことを表す。それによって返り値も変わる。

変数…何らかのメソッドで出た数字に簡単に名前をつけ、またその数字を出したい時、ラクに出せるもの。
（例）変数　＝　格納するオブジェクト　！変数の名前は自由だが基本小文字から始める！
　 num　＝　"hello".length
   =5←この５にnumという名前がつけられた事になる。
定数…定数の使い方は変数とほぼ変わらない。
　　　変数と違うことは、一度代入したものに再代入はできない。定数の場合、名前の戦闘は大文字。

・返り値
そもそも返り値というのは、「文字列、数値、メソッド、演算子、変数」これらで求めて出た答えのことである。


以上が昨日行った主な学習内容です。
Rubyは思っていた以上に複雑なものが多く感じたのでじっくり丁寧に要点を押さえていかなければいけないと思いました。難しいことだらけですが、自分に負けずに頑張りたいです！
一枚の画像からDCGANでtwitterアイコンを生成したい！！


　僕のtwittwrアイコン、苗字が「すみ」なので炭の画像なんですが、かわいいイラストとかイケメンの自分の画像とか使ってる人にはどうにもインパクトが劣るなと思ってどうにかならないものか…と考えたときにAIにアイコン書かせました！！って出来たら面白そうだなと思ってはじめてみました。この記事を書く時点でまだ写真を一枚用意しただけなんですけど、うまくできたらいいなとおもってます。

##画像の準備
　まあね、機械学習なので元の画像がいるわけなんですが、大したデータも持っていないのでせっかくならと一枚の画像からデータを作ってやろうとおもいまして、とりあえず600×600の画像を用意しました。
![0257.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278116/3391eee7-9718-bd56-1a86-efd21f4bd073.jpeg)

方針としては、こいつから400×400の画像を一万枚切り出して学習のたねに使ってやろうという魂胆です。環境はGoogle Colaboratoryを使います。（GPUマシンなどという高価なものは持ち合わせていないのです.....）
<br>
<br>
こっからコードを書いていくよ！

```python
#google driveをマウント
from google.colab import drive
drive.mount('/content/drive')
#必要なライブラリをインポート
import numpy as np
import cv2
# 画像を読み込む
imgs = cv2.imread('drive/My Drive/0257.jpg')
```

0257.jpgってのがさっきの600×600の画像です。<br>
次に、x成分とy成分（表記は適切でないかもしれません。）で乱数を百個ずつ生成します。ただし、百個の乱数が互に同じものが生まれないようにset()でうまく管理してやります。
<br>

```python
x = []
check_set = set()
while True:
  n = np.random.randint(0,200)
  if n in check_set:continue
  x.append(n)
  check_set.add(n)
  if len(x) >= 100:break
    
y = []
check_set = set()
while True:
  n = np.random.randint(0,200)
  if n in check_set:continue
  y.append(n)
  check_set.add(n)
  if len(y) >= 100:break
print(len(x),len(y))
#100 100
```

こんな感じでxとyの配列には乱数で生成された数字（重複なし）が入りました。

```python
count = 0
for i in x:
  for j in y:
    count += 1
    clipp = imgs[i:i+400,j:j+400,:]
    with Image.fromarray(clipp) as img:
      img.save('drive/My Drive/炭画像'+"/{}.jpg".format(count))
```
最後に400×400の大きさで切り取ってあげてドライブに作った炭画像フォルダに保存してやります。これ終わったら大体500MBくらい消費しました。正直この先できる気がしませんが何とか頑張ってみます。失敗しても報告はします。

と、言った感じで最初はやろうと思ったんですけど、400×400のカラー画像を使用するとメモリ消費が半端なかったので100×100にしました。

###追記
　夏休み中に頑張ります。
コードレビューの大切さを普及する活動

入社５年目を迎えて自分でプログラムを書く機会よりマネージメントしたり、レビューする機会が増えて来ました。
私のいるSIerでは軽視されがちな**コードレビュー**ですがとても大切なことだと思っています。
今私が自社で取り組んでいることについて書いていきたいと思います。
アドバイスありましたらコメントお願いします。

#なぜコードレビューをしないのか？
なぜSI業界ではコードレビューをしないのか考えてみました。
SI業界の完全な作業分業制に原因があると思います。
コードレビューをするのにはそのプログラムの仕様を理解していないといけません。
しかし作業が完全に分業されてしまい、担当者以外プログラムレベルの仕様を理解している人がいないということが多いと思います。
これはコードレビュー以前に仕事の属人性を高めてしまいます。

#コードレビューをする機会作る
以下の場面でコードレビューをするようにしました。
１．業務内で作ったプログラム
２．研修として作ったプログラム（SIでは案件がなくて暇な時間ができる）

１については社内の人も時間があればやる（優先度が低め）くらいの認識はあったのですが、私はむしろ最優先にしました。
時間がなくて他のレビューはできなくてもコードレビューはやる！

２についてはレビューするという習慣がありませんでした。
むしろ書いたコードも研修期間が終わるとPCを初期化するので消えてしまいます。
理由としては「お客さんに納品するわけじゃないしそこまでやらなくてもよい」というところです。
**練習でできないことは本番でできない**と私は考えているのでこの考えを全く理解できませんでした。
研修で**クソコード**を量産させてそれをスルーして、現場でOJTと称して指導する。
この二度手間になんの意味があるんでしょうか？
とくに弊社では未経験で入ってくる人が多いので研修＝「はじめてのプログラム」と言う人も多いです。
それなのに変な癖をつけないでほしいというのが本音です。

#コードレビューで見ているポイント
大まかな流れとして以下のポイントを中心に確認します。
・プロジェクトでのコーディング規約を守っているか？
・変数名、コメント等がわかりやすいか？適切か？
・オブジェクト指向で作られているか？
・処理効率が悪くないか？

この内容で記事が一本かけそうな気がするので**その２**の記事を書きたいと思います。

#逆にコードレビューで見ないポイント
アウトプットの結果や詳細は確認していません。
確認している人がいてそれを悪いというつもりはないですが、それは目視で確認してもあまり意味がないことでテストプログラムで確認するべきと思っています。
ただプログラムは一度動かしてみます。
これは詳細な中身を見たいわけではなくコードだけだとどうしても見落としてしまう部分が出てしまうからですね。

#その他で気をつけているポイント
##指摘の仕方・伝え方
コードレビューは人対人で行うものです。
そのためある程度、主観的な情報も入ってしまいます。
なので指摘の伝え方には注意を払う必要があります。
**この書き方は間違っている！すぐ直せ！！**みたいな高圧的な言い方は良くないと思います。
また口頭で伝えてしまうと直し忘れが出てきてしまいますね。
ケースバイケースで適切な方法を考える必要があると思います。

##気になった点はできるだけ伝える
レビューではこれを直してほしいという点以外に少しでも不思議に思った点は伝えるようにしています。
私が理解できなかったということは何かしら改善の余地があるポイントだと思います。
※私の理解力が低いだけかもしれません
レビューはレビューワーの私がレビューイの人をテストするような場だとは思っていません。
より良いプログラムを作るための工程だと思っているので
**こうしたほうがいいんじゃない？**
**でもそうするとここで問題が発生するんだ**
**じゃあここをこう変えよう**
みたいな議論をするのが理想かなと思っています。

#コードレビューを必須にして得られたもの
まだ初めて間もないのですが大きく分けると２つあります。
・チームメンバーのレベルアップ
・コードを直接書いていない自分のレベルアップ

今までなんとなくでプログラムを書いていた後輩たちがちゃんと考えてプログラムを書いてくれるようになったと思います。
「よくわからないけどこうすると動きます」みたいなことをしているとレビューで引っかかりますからねｗ
あと自分は直接手を動かしていないのですが、作ったプログラムすべてに目を通しているいるので処理を考えたりする時間はむしろ増えたように思います。
Raspberry Pi のNode-REDをアップデートorインストールする方法

記念すべき初記事。

YOUTHCAMPを開催するに当たってRaspberry PiのNode-ReEDがクソ遅かったのでnodo.js含めアップデートしようとしたときにあたふたしてたのでメモ的なやつ。


#Raspberry PiのNode-REDはRaspberry Pi用のがある。

要はリファレンスよめって話だったんですが最初確認したときNode.jsのバージョンが古かったので
nvmコマンドやらをつかって消したりアップデートしたりして無駄な時間を過ごしたので戒めを込めて。。

とりあえずアップデート前は

```
$ node -v
v8.16.0
```

「Raspberry Pi　Node-RED　アップデート」とかの検索ワードで来た方が居ればおそらく下記コマンド一発でアップデートorインストールが完了するはずです。
**※このコマンドじゃないとRaspberry Pi用のGPIOを使うNodeが入らないので注意**

```Rasbian
$ bash <(curl -sL https://raw.githubusercontent.com/node-red/raspbian-deb-package/master/resources/update-nodejs-and-nodered)

Running Node-RED update for user pi at /home/pi

This can take 20-30 minutes on the slower Pi versions - please wait.

  Stop Node-RED                       ✔
  Remove old version of Node-RED      ✔
  Using N to manage Node.js           +
  Update Node.js LTS                  ✔   Node v10.16.0   Npm 6.9.0
  Clean npm cache                     ✔
  Install Node-RED core               ✔   0.20.6 
  Move global nodes to local          -
  Install extra Pi nodes              -
  Npm rebuild existing nodes          -
  Add shortcut commands               ✔
  Update systemd script               ✔
                                           
```
こんな感じで自動的にストップからアンインストール、アップデートまでやってくれます。（ネ申）
※途中 y/N 聞かれるところはｙを入れてEnterで！

参考　https://nodered.jp/docs/hardware/raspberrypi

基本的にはココまでで完了するはず！

##もしいろいろnvmやらapt-getやら使って試してたら各コマンド内でアンインストールした方が良い

node.jsのアンインストール

```
$ sudo apt-get autoremove nodejs
```

これでNode.jsもNode-REDも消える。
ちなみに**以前作っていたフローがあった場合それは消えない。**

その後最初のコマンドをターン！！って打てばアップデート完了するはず。

##Node-REDアップデートしたら早くなった。
ひとまず目的のクソ遅いNode-REDは解決した。
【PHP】オブジェクト指向を学ぶ[その]5

#インターフェイス
抽象クラスと似ています。
実装だけ可能です。

```index.php
class 新クラス名 implements インターフェイスクラス名{}

```

実際のコードはこちら。

```index.php
class Greet{
    // 定数
    const MORNING = 'おはよう';
    const NOON = 'こんにちは';
    const NIGHT = 'こんばんは';
}

class Time{
    // 定数
    const MORNING = '朝です';
    const NOON = '昼です';
    const NIGHT = '夜です';    
}

interface Common1{
    public function setGreet1($str);
    public function getGreet1();
}

interface Common2{
    public function setGreet2($str);
    public function getGreet2();

}

class Introduction implements Common1, Common2{
    private $name;
    private $greet1;
    private $greet2;

    public function __construct($name, $greet1, $greet2){
        $this->setName($name);
        $this->setGreet1($greet1);
        $this->setGreet2($greet2);
    }

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

    public function setGreet1($str){
        $this->greet1 = $str;
    }
    public function getGreet1(){
        return $this->greet1;
    }

    public function setGreet2($str){
        $this->greet2 = $str;
    }
    public function getGreet2(){
        return $this->greet2;
    }

    public function getIntroduction(){
        return $this->getName().$this->getGreet1().$this->getGreet2();
    }

}

$user = new Introduction('太郎', Greet::NOON, Time::NOON);
echo $user->getIntroduction(); //太郎こんにちは昼です
```
・インターフェイスで定義したクラスはインスタンスを生成することはできない。
・インターフェイスは抽象クラスと違って一個以上実装することができる。
・publicやprivateなどの修飾子は`public`のみ。
・インターフェイスで定義したメソッドは継承先で必ず実装しなければならない。
これらの特徴があります。

なのでこちらのコードはインターフェイスで定義したメソッドを実装先で定義していないのでエラーとなります。

```index.php
interface Name{
     public function UserName();
     public function UserAge();
}

class User implements Name{
    public function UserName(){
        echo '太郎です';
    }
    
    //定義されていない
    //public function UserAge(){
        //echo '29才でちゅ！';
    //}
}

$hoge = new User;
$hoge->UserName();
//$hoge->UserAge();

```
簡単ですが以上です。
MacbookをWindowsだけにする

# Outdated
https://qiita.com/Utsumi_Re/items/3d8e717b656bd93cbb13 代わりにこの記事をおすすめします。
Pre Installed ISO: https://drive.google.com/file/d/1Adqtcg6Ctv2B9sHBf944BYTGk-rke6eI/view?usp=sharing
https://qiita.com/rerymd/items/638a4fcf8f23ce8aab2d
## おそらく動作しないです。
## いつかアップデートします。

たぶんMacOSのファームウェアが最新だとこの方法は無理です。
Windowsのブートローダーがインストールできない問題が起きます。

もともとLinux+MacOSにしようと思ってたのですが
新しめMacbookにはT2セキュリティーチップのせいでWindowsしかはいんないみたいです｡
Linux使う気満々だったので激おこぷんぷん丸です｡
なので使いづらいMacOSを消してWindowsだけにしようとしました｡
理由は激おこぷんぷん丸なのとMacOSが単純に使いづらいし対応していないソフトが多かったからです。
(MacOSを消すとリカバリーパーテションが消えるのでインターネットリカバリーをいちいちすることになります。macには30gb程容量をあげてもいいとおもいます。)
結構手間がかかります。 
写真は無いです。

#### 注意

~~***先にMacosでインストールメディアを作って下さい。もし何かあったり戻したい時にstoreにもってかなきゃならなくなります。***~~
嘘です。Macが死んでたのでリカバリーが出来なくなっただけでした。Appleのサポートに持ち込むと1時間ほどで直ります。(UEFI関連を直してくれたのかなぁ)

すごく手間がかかります(1時間~1時間半くらい)

手順が複雑なので初心者さんには少し難しいかもです。すいません

ストレージの無駄って理由がなかったら普通にBootcamp使えばいいです。(通常インストールだと自由に決められますがbootcampだと最低37g占領されます)

USBのストレージがいります(ないならexfatでssdを10gくらい)




## 手順

手順A,Bは少し面倒くさいのです。ですがABならインストール時にキーボードとトラックパッドが使えます。（boot.wim）
bootcampアシスタントの上から簡単にドライバなどがDLできます。

~~A. 普通にBootcampを使って一旦Windowsをインストします(ライセンスコードは後で認証にしましょう)
B. インストし終わるとBootcampソフトウェアをインストールというのが出てきます｡そこでインストールをせずにエクスプローラーを開きます｡
そしたらXドライブがあるはずなのでクリックしたらBootcampフォルダとWindows\boot.wimをUSBにコピーします~~


3. MacOSにてWindowsのインストールisoをDLします
（私も躓いたのですがInsiderは使わないほうがいいです。エラーが出たりします。）
4. Bootcampアシスタントを開いて上のアクション --> DL
5. USBをFAT32かexfatでフォーマットしてDLしたisoをマウントして中身をUSBのルートにコピーします。 
7. 再起動を実行してOption(Alt)キーを押してたらEFIbootが出来るのでBoot
8. あとは普通にインストールすればいいです

何か間違ってたりできなかったら言ってください
BootcampソフトウェアのDLは結構止まるので根気強くやってみてください。どうしても駄目だったら -> http://bit.ly/WindowsSupport-dmg


# こんな感じになる

NTFSだけのストレージを見ると､､//

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387170/a19f21a5-ea2e-e590-cd22-ccf5c8e599d1.png)

参考にしたサイト:
https://twocanoes.com/create-a-windows-10-bootable-usb-flash-drive-on-a-mac/
JavaScriptを使い、Webブラウザでデバイスを振動(バイブレーション)させる

# はじめに

A-Frameを使いWebVR制作をしていたのですが、画面内のアイテム選択時にデバイスを振動させたくなりました。
が、A-Frameにコントローラーを振動させるメソッドは無さそうです。

結果、デバイスごとに振動させる方法を見つけましたが、日本語ドキュメントが全然なかったのでQiita投稿しておきます。

# スマホの場合

かなりシンプルに実装できます。

```javascript
var duration = 200; // 振動時間
navigator.vibrate(duration);
```

[Vibration API - 開発者ガイド | MDN](https://developer.mozilla.org/ja/docs/Web/Guide/API/Vibration)

Can I useによると、IEやOperaはまだしも、Safari未対応はキツい…
ブラウザ未対応なので、Safariで振動させることは現状できなさそうですね。
[Can I use... Support tables for HTML5, CSS3, etc](https://caniuse.com/#feat=vibration)

# VRコントローラー、ゲームコントローラーの場合

本来やりたかった本命はこちら。
VRでWebブラウザを開き、コントローラーで狙ったターゲットを選択した時に振動させる方法。

シンプルに振動させるだけなら、このコードでいけます。

```javascript
var duration = 200; // 振動時間（ミリ秒）
var value = 0.5; // 振動の強さ(0.0〜1.0)
var gamepads = navigator.getGamepads && navigator.getGamepads();
for (var i = 0; gamepads.length; i++) {
  var gamepad = gamepads[i];
  gamepad.hapticActuators[0].pulse(value, duration);
}
```

ドキュメントはこちら
[GamepadHapticActuator.pulse() - Web API | MDN](https://developer.mozilla.org/ja/docs/Web/API/GamepadHapticActuator/pulse)

# A-Frameを使ったサンプル

WebVRを簡単に構築できるA-Frameで導入してみましょう。

```html
<html>
  <head>
    <script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
    <script>
      AFRAME.registerComponent('vibration', {
        schema: {
          duration: {type: 'int', default: 200},
          value: {type: 'number', default: 0.5}
        },
        init: function() {
          this.onClick = this.onClick.bind(this);
          this.el.addEventListener('click', this.onClick);
          this.el.setAttribute('class', 'collidable');
        },
        onClick: function(e) {
          navigator.vibrate(this.data.duration); // スマホ用振動
          // oculus touch等のコントローラー振動
          var gamepads = navigator.getGamepads && navigator.getGamepads();
          for (var i = 0; gamepads.length; i++) {
            var gamepad = gamepads[i];
            gamepad.hapticActuators[0].pulse(this.data.value, this.data.duration);
          }
        }
      });
    </script>
  </head>
  <body>
    <a-scene>
      <a-sky color="black"></a-sky>
      <a-entity cursor="rayOrigin: mouse"></a-entity>
      <a-entity laser-controls raycaster="objects: .collidable; far: 5;"></a-entity>
      <a-plane vibration width="1" height="1" position="0 0.5 -2"></a-plane>
    </a-scene>
  </body>
</html>
```

Oculus QuestのWebブラウザで見たところ、こんな感じで右手コントローラーからレーザーが出て、白い四角を狙ってボタンを押すと振動します。

![vr.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/be2cfc92-5135-8713-d63b-42e5a4840e5b.jpeg)
Scrapbox to Speech (Web Speech APIでScrapboxの内容を喋らせる)

# Demo
[![デモはこちら](http://img.youtube.com/vi/IF1s1K3DRhc/0.jpg)](https://www.youtube.com/watch?v=IF1s1K3DRhc)



# 機能
スクラップボックスで選択したテキストを喋らせる。喋っている最中に中断すること可能(動画の2回目の再生は途中でキャンセルしてる)

# コード
https://scrapbox.io/wordbook/yamato

```script.js
 // 選択した文章に対してボタンを追加
 scrapbox.PopupMenu.addButton({
 	title: 'Speach',
 	// ボタンをクリックして選択した文章の内容を取得(Plain textで取得するのが望ましい)
 	onClick: text => {
 		// https://qiita.com/hmmrjn/items/be29c62ba4e4a02d305c
 		// https://app.codegrid.net/entry/2016-web-speech-api-1
 		// こちらを参考にWeb Speech APIを使う
 		const uttr = new SpeechSynthesisUtterance(text);
 		if (speechSynthesis.speaking == false) {
 			speechSynthesis.speak(uttr);
 		} else {
 			speechSynthesis.cancel();
 		}
 	}
 })
```