OmniAICreator/Qiita-1.07M huggingface dataset:
簡単な uwsgi の使い方

簡単な uwsgi の使い方です。

参考ページ
[Quickstart for Python/WSGI applications](http://uwsgi-docs.readthedocs.io/en/latest/WSGIquickstart.html)

## インストール

Arch Linux

```bash
sudo pacman -S uwsgi
sudo pacman -S  uwsgi-plugin-python
```

Ubuntu

```bash
sudo apt install uwsgi
sudo apt install uwsgi-plugin-python3
```

## バージョンの確認

```text
$ uwsgi --version
2.0.21
```

## サーバーのプログラム

```py:foobar.py
#
#	foobar.py
#
#						Jan/13/2017
# 
# ------------------------------------------------------------------
def application(env, start_response):
	start_response('200 OK', [('Content-Type','text/html')])
	rvalue = b"Hello World\n"
	rvalue += b"\tTest\n"
	rvalue += b"\tJan/13/2017\n"
	return [rvalue]
# ------------------------------------------------------------------
```

## サーバーの起動

```bash
uwsgi --plugin http,python --http :9090 --wsgi-file foobar.py
```

クライアントで確認

```text
$ curl http://localhost:9090
Hello World
	Test
	Jan/13/2017
```

## 確認したバージョン

```text
$ python --version
Python 3.11.3
```

## Ubuntu で使う場合

ini ファイルを使います。

```text:ubuntu.ini
chdir=/home/uchida/projects/qiita/get_qiita/p0169
socket = 127.0.0.1:3031
plugins-dir = /usr/lib/uwsgi/
plugins = /usr/lib/uwsgi/plugins/python311_plugin.so
plugins = /usr/lib/uwsgi/plugins/http_plugin.so
wsgi-file=foobar.py
 
# アクセス許可ホスト:ポート
http=0.0.0.0:9090
```

サーバーの起動

```bash
uwsgi ubuntu.ini
```

クライアントで接続

```text
$ curl http://0.0.0.0:9090
Hello World
	Test
	Jan/13/2017
```

ini ファイルを使わないでサーバーを起動する方法

```bash
uwsgi --plugin http,python3 --http :9090 --wsgi-file foobar.py
```
Jupyter + Matplotlib > 手順 > 表示された画像を拡大する (解像度はそのまま)

```txt:動作環境
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
```

### 動機

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/6d667711-cefe-da07-a3c4-4a6087fa0f6c.png)

右図のNetagive polarization branch ([彗星やC型小惑星の後方散乱で見られる謎の現象](https://www.terrapub.co.jp/journals/EPS/pdf/2011/6310/63101077.pdf))に関係しそうな部分を拡大表示したい。

### 手順

以下の方法はあるようだ。

1. Chromeで別ウィンドウを開く
    - 別タブでなく別ウィンドウの方が作業しやすい
2. Matplotlibの表示画像をドラッグして、手順1のウィンドウにドロップする
    - >> 背景色が透明の拡大画像表示になる
3. Ctrl + マウスwheelでさらに拡大する

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/b9901639-b4f3-97b3-a469-96e38e5df35a.png)

Jupyter+Matplotlibで表示した状態で「Ctrl + マウスwheel」ではコードセルは拡大表示されるが、グラフは拡大されないので検討した。
解像度は変わらない。
【即席】Google Homeにiphoneを探してもらう

[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/HjTA3O6qyAY/0.jpg)](http://www.youtube.com/watch?v=HjTA3O6qyAY)

# もはやダッシュボタンとラズパイは不要
先日、下記の記事を書きましたが、もっと簡単にiphoneを探す方法ができたので投稿しています。

”iphoneを探す”ボタンを作った
https://qiita.com/kyogom/items/25a2b230071ffd76551f　　


# 使うもの 

- IFTTT 
- Twilio APIの利用料金（108円/月）
- Google home / Amazon Echo

# 実装手順

1. Twilioの会員登録をします。クレカ登録してポイントを購入してください。
```
- ACCOUNT SID
- AUTHTOKEN
- 電話番号 
```
が取得できたらokです。

2. （IFTTTの登録は終わってる前提）IFTTTでアプレットを作成します。

this -> google assistantを選択し、下記の設定をする。

```
1.Say a simple phraseを選択
2.What do you want to say? に起動メッセージ「xxxに電話」を入力
3.What do you want the Assistant to say in response? に返事「xxxに電話しています」を入力
4.LanguageでJapaneseを選択 
```


that -> webhookを選択し、下記の設定をする。

```
1.URLに
 https://{ACCOUNT SID}:{AUTHTOKEN}@api.twilio.com/2010-04-01/Accounts/{ACCOUNT SID}/Calls.json
を入力。

↑BASIC認証用とパス用で、SIDを２回入力しています。{}にはあなたの情報を入れてください

2.MethodにPOSTを選択
3.Content Typeにapplication/x-www-form-urlencodedを選択
4.BodyにUrl=http://demo.twilio.com/docs/voice.xml&To={宛先電話番号}&From={Twilioの電話番号}
5.Saveを押して完了！！！！
```

# 詰まったところ 
- Google homeの音声認識はわりとシビアです。特に、珍しい名前は認識されません。iphoneのgoogle homeアプリで音声が認識されているか確認してみましょう  
![IMG_3139.PNG](https://qiita-image-store.s3.amazonaws.com/0/148503/d2f68493-6e7d-5d12-9ad4-2d9bbff9d8aa.png)
TwitterアプリのようにTab選択時にリストを一番上にスクロールする 

## はじめに
リスト表示を行うTwitterクライアントのようなアプリでは、リストの一番上にスクロールする機能が必須ですよね。
今回はTwitterの公式Androidアプリで採用されている以下のような方法のスクロールを実装してみます。

- 選択済みTabをタップしたタイミングでリストの一番上までスクロールさせる
- 現在位置からリストの一番上までどれだけ離れているかで、一瞬で移動するのかスムーズに移動するのかを変える

この記事では以下の構成前提でコードを記載しています。

- MainActivityにTabLayoutとViewPagerを配置してタブ切り替える
- タブ選択で、RecyclerViewをメンバで持つFragmentを切り換える

## 選択済みのTabがタップされたことを検知する
選択済みTabを再選択した際の処理は、OnTabSelectedListenerのonTabReselectedで実装して
TabLayoutに設定してあげればOKです。

```java:MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
    (省略)

	mTab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
	    @Override
	    public void onTabSelected(TabLayout.Tab tab) {
	    }
	
	    @Override
	    public void onTabUnselected(TabLayout.Tab tab) {
	    }
	
	    @Override
	    public void onTabReselected(TabLayout.Tab tab) {
	        // 選択済みTabが再選択された際の処理はここに記載
	        // リストを一番上にスクロールする処理を呼び出す
	        Fragment fragment = mPagerAdapter.getItem(tab.getPosition());
	        ((TestFragment) fragment).scrollToFirstPosition();
	    }
	});
	
   (省略)
}
```

##リスト最上段までスクロールする
RecyclerViewの表示位置取得には、RecyclerViewにセットしているLayoutManagerを使うのがコツです。
現在の表示位置が一定の閾値を超えているか判定し、閾値より離れている場合は一瞬でいちばん上まで移動させ、
そこまで離れていない場合はスムーズに一番上までスクロールさせます。


```java:TestFragment.java
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
		(省略)

        mLinearLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
        mRecyclerView.setLayoutManager(mLinearLayoutManager);

        (省略)
}

public void scrollToFirstPosition() {
    if (mRecyclerView != null) {
        // 表示されているポジションが閾値(ここでは20)より後ろであれば一瞬でスクロール。閾値以下ならスムーズスクロール
        int position = mLinearLayoutManager.findLastCompletelyVisibleItemPosition();
        if (position > 20) {
            mRecyclerView.scrollToPosition(0);
            return;
        }
        mRecyclerView.smoothScrollToPosition(0);
    }
}
```

以上でTwitter公式アプリ風のリストスクロールが実装できます。
ぜひご自分のアプリに取り入れてみてくださいね。
Spring Bootで作ったJarをAWSのElastic BeanstalkですぐにWebにアップする

# ゴール
この記事ではSpring BootでコンパイルしてJarを
AWSのElastic Beanstalkで動かす方法を記載

# あらかじめ実施しておくこと
AWSのアカウントを取得していること
Spring BootでコンパイルしたJarがあること

# 手順
1.AWSでElastic Beanstalkを選択
2.新しい環境の作成を選択
3.ウェブサーバー環境を選択
4.プラットフォームにJavaを選択
5.コードのアップロードで予め用意したJarファイルを選択
6.さらにオプションを選択から【ソフトウェア】の更新を選択（※）
7.環境プロパティに「SERVER_PORT」、「5000」を追加
8.環境を作成→作成するまで結構時間がかかる。

（※）6,7の手順は環境作成後でも設定可能
VSCode WindowsでRubyの文字化け 対処法 pメソッド編

追記 2019/03/28
VSCodeを新たにインストール。

PowerShell 6.2
Ruby 2.6
をインストールするとデフォルトで普通に表示された。
（UTF-8を利用できる設定にすること。）

[Release v6.2.0-rc.1 Release of PowerShell Core · PowerShell/PowerShell](https://github.com/PowerShell/PowerShell/releases/tag/v6.2.0-rc.1)
ダウンロードファイル
PowerShell-6.2.0-rc.1-win-x64.msi

[Ruby Downloads](https://rubyinstaller.org/downloads/)
ダウンロードファイル
Ruby+Devkit 2.6.1-1 (x64)


# 結論
pをputsに変更する。

## 環境
Windows7 64bit
VSCode 1.19.1
Ruby 2.4.0p0 (2016-12-24 revision 57164) [x64-mingw32]
UTF-8

## 症状
putsメソッドなら正常だが、pメソッドだと文字化けして見える

例
puts 'あいうえお' #正常に見える
p 'あいうえお' #文字化け

実行
＞ ruby .\実行ファイル名.rb
結果
あいうえお
"\u3042\u3044\u3046\u3048\u304A"


## 対処方法
ターミナルから
-U オプションを付けて実行する

実行
＞ ruby -U .\実行ファイル名.rb
結果
あいうえお
"あいうえお"

## 半永久的に設定しておきたい場合
コントロールパネル＞システム＞システムの詳細設計
システムのプロパティウィンドウが表示される
環境変数＞XXXのユーザー環境変数
新規

変数名 RUBYOPT
変数値 -U

VSCodeを再起動
※再起動必須
※PCの再起動は必要ない

処方結果
ターミナルから
実行
＞ ruby .\実行ファイル名.rb
結果
あいうえお
"あいうえお"

# その後
ターミナルからなら綺麗に表示されるようになったが、
Run Codeからは別の新たな文字化けが・・・

Run Codeから実行する。
結果
"����������"
����������

~~疲れたよ・・・~~
なので元に戻した。

その後の対処方法
pをputsに変更する。

Rubyの文字コード設定ってどうなっているの？？？
Windowsのシステム環境変数だったり
ターミナルのオプションだったり
ファイルの上の Shebangだったり

WindowsやめてMac使いたいよ・・・
ちょっとずつ読むドメイン駆動設計 第四部 戦略的設計 第十五章 蒸留8 抽象化されたコア/蒸留落ち葉拾い

# 前回までの第十五章

[コアドメイン1](https://qiita.com/YasuhiroKimesawa/items/899d1b3fd58ca91f525a)
[コアドメイン2](https://qiita.com/YasuhiroKimesawa/items/1aee3602d3aea1cb5b91)
[汎用サブドメイン](https://qiita.com/YasuhiroKimesawa/items/be23f3bd11626265f552)
[ドメインビジョン声明文](https://qiita.com/YasuhiroKimesawa/items/75e270b7d9a624823c1a)
[強調されたコア](https://qiita.com/YasuhiroKimesawa/items/9fdf325ab4cdb9e2286d)
[凝集されたメカニズム](https://qiita.com/YasuhiroKimesawa/items/5e87154185dbef763c51)
[隔離されたコア](https://qiita.com/YasuhiroKimesawa/items/ddadf68f1c4533a6754e)

# 抽象化されたコア

蒸留最後のパターン。

サブドメインを分割し、モジュールが増えていくと、サブドメイン間の相互作用が曖昧になったり、複雑になったりする。

そこで、分割を垂直ではなく、水平にすることを検討します。
つまり、**多態性**を利用してインターフェースに括りだす。

例えば、「注文」モデルには、キャンセル後の注文、配送完了後の注文についての情報も含まれていて、大きくなりがち。そこで、「注文」を抽象化し、「キャンセル後注文」「配送完了後注文」など多態性を利用することができます。

こうすることによって、コア自体が整理されるだけでなく、抽象化されたコアを参照するドメインもその相互作用について簡潔に表現できるでしょう。

注意点としては、
1. 機械的にやらないこと。抽象化するためには、概念が果たす役割についての深い理解が必要になります。
2. 相当な量の再設計が必要になる。[前回の隔離されたコア](https://qiita.com/YasuhiroKimesawa/items/ddadf68f1c4533a6754e)でもそうでしたが、モデルの本質的な部分がわかりにくくなってきたときに行うものなので、当然相当な量の再設計が必要になります。

隔離されたコアも抽象化されたコアもある程度大きくなったモデルに対しても行われるもの、モデルが成長すると、なかなかその構造を変更していくのは大変かもしれません。
ただ、ここでやるかやらないかでその後のやりやすさが大きく変わってくるかもしれませんね。

# 蒸留落ち葉拾い
## 深いモデルの蒸留
ここまで、蒸留について見てきましたが、汎用サブドメインや隔離されたコアからコアを蒸留するという意味だけではなく、コアドメインをリファクタリングして改良することも含まれています。

深いモデルは、ドメインの最も本質的な側面を蒸留してシンプルな要素にする。さらに先の蒸留と合わさって、アプリケーションの重要な問題を解決できます。

## リファクタリングの対象を選ぶ
リファクタリングをどこからするか迷う時、つまり、うまく分解されていない巨大なシステムのどこから手をつけるかという話題。

1. どこからでも
2. 困ってるところから

Evansはどちらも否定しています。

1. **コアか、コアと補助的要素の関係を含むものであれば、リファクタリングする**
2. **コアドメインの括りだし、コアの隔離の改善、補助的なサブドメインから不純物を取り除き、汎用サブドメイン化。これを最初に集中してやる。**

迷ったらコアドメインからということですね。
[python]イテレータとジェネレータの違い[これが真実]

# イテレータ？？ジェネレータ？？
Qiitaの記事を漁っていると、
「ジェネレータはイテレータの一種」
「ジェネレータはイテレータを返す関数」
など、相反する記述が見受けられます。

信用できるのはやはり公式ドキュメントだと思い、読み込んできました。

この記事で(pythonにおける)イテレータの意味、ジェネレータの意味をはっきりさせます。

## ジェネレータ(generator)とは
**そもそもジェネレータには２つの意味がある**（！）
ジェネレータは文脈によって意味が異なり、

* ジェネレータ関数(generator function)
* ジェネレータイテレータ(generator iterator)

の2つの意味がある([参考](https://docs.python.jp/3/glossary.html#term-generator))

それぞれの意味は、

* ジェネレータ関数
    * ジェネレータイテレータというオブジェクトを返す関数
    * **yield式を持つ**
* ジェネレータイテレータ
    * ジェネレータ関数で生成されるオブジェクト

このジェネレータイテレータがイテレータの一種。

ではイテレータとはなんなのか。

## イテレータとは

データの流れを表現するオブジェクトである。
以下の2つのメソッドをサポートする。

* iterator.\_\_iter\_\_()...iter(itarator)と等価
    * イテレータオブジェクト自身を返す
* iterator.\_\_next\_\_()...next(iterator)と等価
    * 次のアイテムを返す

## イテレータ(iterator)とジェネレータイテレータ(generator iterator)の違い

まず前提として、\_\_iter\_\_()か\_\_getitem\_\_()メソッドをサポートするobjからiter(obj)によってイテレータを得ることができる。

察しのよいかたはもう気付いたかもしれないが、以上の話をまとめると、

```python:
class Object():
  def __iter__(self):
    ...
object = Object()
```
このときのiter(object)はイテレータであり、

```python:
class Object():
  def __iter__(self):
    ...
    yield hoge
object = Object()
```
このときのiter(object)はイテレータであり、かつジェネレータイテレータでもあります。

要は、もととなるコンテナオブジェクトの\_\_iter\_\_()メソッドにyieldがあるかないかの差なのでした。

### 備考
やはり公式ドキュメントに勝るものはないです。
もしもこの記事に間違った記述を見つけられた方はコメント欄などでご一報下さると幸いです。
在 macOS 配置 Hubot 的開發環境

主要是依照這個頁面的說明配置
> https://hubot.github.com/docs/

或是可以看這個頁面
> https://github.com/hubotio/hubot/blob/master/docs/index.md

兩邊的內容基本上是一樣的

## 前置作業

安裝 Hubot 需要的相依套件

- Homebrew
- node.js, npm
- yeoman

### Homebrew

照著官方說明安裝即可
> https://brew.sh/

```bash
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```

### node.js, npm

照著官方說明安裝即可
> https://docs.npmjs.com/getting-started/installing-node

```bash
brew install node
```

### yeoman

依樣照著官方提供的指令安裝即可
> http://yeoman.io/

```bash
npm install -g yo
```

## 安裝 Hubot 產生器

參考官方的文件
> 網頁 - https://hubot.github.com/docs/
> GitHub 介面 - https://github.com/hubotio/hubot/blob/master/docs/index.md

```bash
npm install -g yo generator-hubot
```

## 生成專案

```bash
mkdir mybot
cd mybot
yo hubot
```

接著在終端機會跳出相關設定的問題，
不過可以先一直按 Enter ，只用預設值即可也不會有問題

## 可能需要的調整

### hubot-scripts.json

> WARNING Loading scripts from hubot-scripts.json is deprecated and will be removed in 3.0 (https://github.com/github/hubot-scripts/issues/1113) in favor of packages for each script.
>
>  1 # Description:
> Your hubot-scripts.json is empty, so you just need to remove it.

雖然 `hubot-scripts.json` 這個檔案即將被棄用，但是生產器還是會把它建立出來
這時候只要把他移除掉即可

```bash
rm hubot-scripts.json
```

### CoffeeScript

新建好的專案裡面沒有設定好 CoffeeScript 的相依，在執行 `./bin/hubot` 就會出現這樣的錯誤訊息：

> npm WARN hubot-help@0.2.2 requires a peer of coffee-script@^1.12.6 but none is installed. You must install peer dependencies yourself.

這時候可以透過指令把 CoffeeScript 的相依加入專案

```bash
npm install coffee-script@^1.12.6
```

## ReferenceError: robot is not defined

會出這樣的錯誤是因為程式中可能有用了不存在的方法之類的錯誤，
導致編譯腳本的時候無法正常使用 robot

## 參考及使用連結總整理

- https://hubot.github.com
- http://yeoman.io/
- https://brew.sh/
- https://docs.npmjs.com/getting-started/installing-node
- Hubot 語法文件： https://github.com/hubotio/hubot/blob/master/docs/scripting.md
Xcode Archive でビルド番号をあげる

#　Xcode Archive でビルド番号をあげる

Archiveのたびにbuild番号をあげるのはめんどいので下記をRun Scriptへ追加します。

Build phaseにあります。

```shell
infoPlistFile="${SRCROOT}/${INFOPLIST_FILE}"
buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${infoPlistFile}")
buildNumber=$((${buildNumber%%.*} + 1))
/usr/libexec/PlistBuddy -c "Set:CFBundleVersion $buildNumber" "${infoPlistFile}"
```

これをコピペします。

その後、Run script only when installing にチェックする。

下記のような感じ

<img width="642" alt="スクリーンショット 2018-01-13 14.43.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/31394/0ff034bf-39e5-fed9-918b-674df24ec1c7.png">


勝手にバージョンアップします。

便利

追加したD&Dでできるだけ上に移動しておいた方が良いようです。

以上

参考サイト

http://frnk.hatenablog.jp/entry/2016/12/07/083000

引用させていただきました~ 🎉🎉🎉

感謝
SAP Cloud PlatformでFioriアプリ開発(環境設定編)

#**はじめに**
SAP Cloud Platform（SAP CP）のトライアルシリーズです。

以下のSAPブログの記事を参考にFioriアプリの開発を行います。

[SAPクラウド演習1. ノンプログラミングでアプリを作ってみよう！Part 1](https://blogs.sap.com/?p=121240)
[SAPクラウド演習1. ノンプログラミングでアプリを作ってみよう！Part 2](https://blogs.sap.com/?p=121327)

今回は上記リンクのPart１(環境設定)について。

※Part２(アプリ開発編)の実施結果については[こちら](https://qiita.com/mahko2/items/22b797ea4016c086480b)を参照。

この記事は2015年2月時点の情報のため、
記事との差分を中心に記述します(2018年1月時点)。

#**手順**
*※ここからは、参照元の記事の項番とリンクした内容で記載します*

##**[Part1](https://blogs.sap.com/?p=121240)**
####**準備 1. Google Chrome ブラウザの確認** ※割愛

####**準備 2. SAP Community Network (SCN) のユーザ登録** ※割愛

####**準備 3. SAP HANA Cloud Platform (HCP) のサービス有効化** ※割愛
※現在は、SAP Cloud Platform (SAP CP)という名称に変更されています。

####**準備 4. SAP HANA Cloud Platform Cockpit**  ※割愛

####**準備 5．データソース登録 – northwind**
メニューが少しだけ変わっていました(私は日本語ログオン)
記事：Destination -> New Destination
今回：コネクティビティ -> 宛先 -> 新規宛先

![スクリーンショット (427)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/2e65e506-148a-bd80-07d5-6fede3b350d7.jpeg)

日本語だとこんな感じ
![スクリーンショット (429).png](https://qiita-image-store.s3.amazonaws.com/0/22526/206c545c-0022-812e-dc3d-999c727d117f.png)

####**準備 6．Gateway デモ・サーバにアカウント登録**
私はSAPTechJamのハンズオンセッションでアカウント登録済でした。
ログオンすると以下のような感じです
![スクリーンショット (433)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/1887f086-2e0f-e37e-11b3-7bd60463245c.jpeg)

![スクリーンショット (434).png](https://qiita-image-store.s3.amazonaws.com/0/22526/91786a71-437e-8138-8123-2c91a6517f70.png)

![スクリーンショット (436).png](https://qiita-image-store.s3.amazonaws.com/0/22526/56605e00-64f7-165a-e802-92cd01facaaf.png)


####**準備 7．データソース登録 – ES4**
日本語だとこんな感じ
![スクリーンショット (438).png](https://qiita-image-store.s3.amazonaws.com/0/22526/ccf969c9-ab14-969f-855a-14e29615ab26.png)


####**準備 8．SAP Web IDE 開発ツール起動**
SAP Cloud Platform Cockpit の左メニューから サービス -> SAP Web IDE を選択
![スクリーンショット (440)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/bd836029-ba42-1178-a99d-7d37906b55ca.jpeg)

記事：Open SAP Web IDE のリンクを選択。
今回：サービスに移動 のリンクを選択。
![スクリーンショット (442)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/72ec8d51-490e-92df-fd85-7492aca9b686.jpeg)

![スクリーンショット (445).png](https://qiita-image-store.s3.amazonaws.com/0/22526/ce848d4a-a3d8-acd0-5ee0-072e9e217929.png)

![スクリーンショット (446)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/186cf1c6-cc67-9144-1e34-55edc631ef61.jpeg)


#**まとめ**
多少のメニュー構成の変更はあるものの、順調に設定が完了しました。
次は、アプリ開発です。
Swift：ローマ字の文字列をひらがな・カタカナに変換するクラス作った

#背景
iOSのCustom Keyboard Extensionでカスタムキーボードを作っている際に日本語入力を行いたくなりました。
しかし、なぜか日本語だけはぶられておりAPIがまともに整っていない状況であることに気づき、絶望しました。
そこで、自然言語処理の単位がCだった残念な自分が、漢字混じり文への変換はできなくてもせめてひらがな・カタカナへの変換くらいはしたいと奮起し、 今回紹介するクラスを作成するに至りました。

#ソースコード
[Japanese](https://github.com/Kyome22/Japanese)というクラスファイルをGithubに載せてあります。
参照・利用ご自由にどうぞ。ただし、商用利用の際は`README`を一読してほしいです。

#用例
```swift:
let jp = Japanese()

// ローマ字 -> ひらがな の時は getHiragana()
print(jp.getHiragana(roman: "axa^~kokorogapyonpyonsurunjaxa^~"))

// ローマ字 -> カタカナ の時は getKatakana()
print(jp.getKatakana(roman: "axa^~kokorogapyonpyonsurunjaxa^~"))

// ローマ字 -> 半角カタカナ の時は getHalfKatakana()
print(jp.getHalfKatakana(roman: "axa^~kokorogapyonpyonsurunjaxa^~"))

// 出力結果
// >> あぁ^~こころがぴょんぴょんするんじゃぁ^~
// >> アァ^~ココロガピョンピョンスルンジャァ^~
// >> ｱｧ^~ｺｺﾛｶﾞﾋﾟｮﾝﾋﾟｮﾝｽﾙﾝｼﾞｬｧ^~
```

#余談
ローマ字を日本語に変換する方法に`CFStringTransform`と`kCFStringTransformLatinHiragana`を用いる方法がありますが、これは完璧ではなかったです。"wye"で「ゑ」と変換できないし、子音続きの場合：例えば"wktksuru"のときは「うくてくする」になってしまいます。（ほんらいなら「wktkする」になってほしい。）
標準入出力でプロセス間通信

[昨日の記事](https://qiita.com/bamchoh/items/9225fef829bb1841c1de) の続きみたいなものですが、`spawn`を使って標準入出力でプロセス間通信ができそうだなぁと思ったので実験してみました。

```rb:parent.rb
require "json"
pin1, pout1 = IO.pipe
pin2, pout2 = IO.pipe

spawn("ruby child.rb", :in => pin1, :out => pout2)
100.times { |i|
  obj = { "val" => i }
  data = JSON.generate(obj)
  pout1.puts data

  obj = JSON.parse(pin2.gets)
  puts obj["ret"]
}
```

```rb:child.rb
require 'json'

begin
loop {
  obj = JSON.parse(gets)
  ret = { "ret" => obj["val"] * 2 }
  puts JSON.generate(ret)
  STDOUT.flush
}
rescue
end
```

`parent.rb`を実行すると、0～198までの数字が羅列されると思います。パイプを2つ作ってそれぞれの片方をくっつける感じで作るのがミソですかね。

別にJSONにこだわらなくても、MessagePackなり、Protocol Bufferなりでデータシリアライズしてあげれば何でもいけると思います。

上の例だと、`gets`のところでブロックしちゃうので、非同期で動作させたい場合は工夫が必要かも。
Vagrant ファイル共有　決定版

# 忘れないためのメモ
デフォルトの位置
hostのフォルダは、[Vagrantfileのあるフォルダ]
guest(vagrant)のフォルダは、[/vagrant]
また、設定することもできる
config.vm.synced_folder "host_path", "guest_path"
私の場合

```:Vagrantfile
config.vm.synced_folder "{Vagrantfileのフォルダ}/workspace" "/home/vagrant/workspace"
```
みたいな感じ

Vagrantfileの横にworkspaceのフォルダを作って
vagrantのホームディレクトリにあるworkspaceと共有する。

## しかし...
これだけでは、おそらく共有されない。
ホストマシンの方で

```:host-terminal
$ vagrant plugin install vagrant-vbguest
$ vagrant reload //再起動、または起動
```
私は、これでいけました。
vagrant楽しい！！
gitの使い方がさっぱりわからないので整理してみる

#自分の知識レベル
CVSを多少触ったことあるレベル
gitについては、学びはじめた始めたばかりで何もわからない

#gitを使ってしたいこと
Laravelを利用そたPHPアプリで以下のことをしたい

1.バージョン管理
2.プロダクション環境へのデプロイ

1はいいとして、主にやりたいのは2の内容。
自分で契約したVPSにリモートリポジトリを構築し、そこに更新を加えることで、プロダクション環境も更新される仕組みを作りたい。


#gitの用語整理

##リモートリポジトリ
cvsやSVNでいう所のリポジトリと同じ
リモートにあるリポジトリ
ただし、自身のローカルに作ることも可能

#ワーキングツリー
cvs的にいえば、チェックアウトしてきたプロジェクト
cvsとは異なり、履歴や管理情報を丸ごとコピーしてくる
リモートリポジトリをローカルにバックアップするようなイメージ?

##ローカルリポジトリ
リモートじゃなくて、ローカルにあるリポジトリ
ワーキングツリー
自分でブロジェクトを始め、ローカルに保存するのであれば、リモートリポジトリ=ローカルリポジトリのリポジトリが１つできる。

#ステージングエリア(index)
コミットする前に、どのファイルをコミットするか選択した情報を保存している場所
複数のファイルが更新されている場合に、コミットすべきものを決められる

#コミット
ワーキングツリーにコミットする
cvsとは異なり、リモートリポジトリに反映はしない

#push
ワーキングツリーにコミットした内容をリモートリポジトリに反映すること

##origin
デフォルトではリモートリポジトりを指す


##master
ブランチを切っていない状態でできるデフォルトのブランチ
ブランチを切っていなければ、ワーキングツリーとイコールになる

##origin/master
リモートリポジトリをローカルに保存したもの(ブランチ)
gitでは、リモートからクローンしてくることで、origin/mastertができる。
それと、作業用のmasterができる。
masterの変更点はorigin/masterと比較することで表示されている(と思われる)


#gitのコマンド整理

##git init
カレントディレクトリでバージョン管理を開始する。

##git add
バージョン管理対象になっているディレクトリにおいて、変更点をインデックス対象にする
`git add ファイル名` ファイル名を個別に指定
`git add .` 変更されているファイルを全て対象に指定

##git commit
インデックス対象のファイルを全てワーキングツリーにコミットする
git commit -m "コミットメッセージ"

##git push
ワーキングツリーの変更をリモートリポジトリにコミットする
`git push [リモートリポジトリ] [ブランチ]`
`git push` だけにするとoriginリポジトリについて、ローカルのマスターをリモートのマスターへ反映するという意味になる。


##git clone
リモートリポジトリから、丸ごと持ってくる

#git diff
ワーキングツリーにどのような変更を加えたかを表示する

#git status
以下の３つの状態を表示する。
-ステージングとして選択されたファイル
-コミット済みのファイル
-どちらも行なっていないが変更が発生しているファイル

#当初目的の実現
デプロイの実現は、ここでは書ききれなかったので、別の記事で記載予定

#参照
http://dqn.sakusakutto.jp/2011/10/git_push_origin_master.html
https://nekosoftware.wordpress.com/2015/02/03/git%E3%81%AE%E3%81%B5%E3%82%8F%E3%81%A3%E3%81%A8%E3%81%97%E3%81%9F%E7%9F%A5%E8%AD%98%E3%82%92%E8%AA%BF%E6%9F%BB%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F/
https://qiita.com/osamu1203/items/cb94ef9da02e1ec3e921
[ 斜方投射 ] 物理演算で任意の場所に衝突させる

[斜方投射](https://ja.wikipedia.org/wiki/%E6%96%9C%E6%96%B9%E6%8A%95%E5%B0%84)の式

```math
\begin{align}
v_x&=v_0\,cos\theta\\
v_y&=-gt+v_0\,sin\theta\\
x&=v_0\,t\,cos\theta\\
y&=-\frac{1}{2}gt^2+v_0\,t\,sin\theta+y_0
\end{align}
```
から、$ \vec{d} $先にある物体に衝突するよう初速$ p $で物体を投げるときの$ \vec{v_0} $を求めることができます。

```
		//-----------------------------------------------------------------------
		//! 力pで距離distに物体を投げるときのVec (retがnullの場合は届かない）
		//! //http://www.sousakuba.com/Programming/algo_dandoukeisan3.html
		//! //http://www.kumamoto-nct.ac.jp/file/knct-kiyou-2013/pdf/no18.pdf
		//-----------------------------------------------------------------------
		static public Vector3[] CalcTargetVec(float _p, Vector3 _dist){
			float _g = Physics.gravity.y;
			Vector3[] ret = null;
			Vector3 distXZ = new Vector3 (_dist.x, 0f, _dist.z);
			float dist_x = distXZ.magnitude;
			float dist_y = _dist.y;
			float a = (_g * dist_x * dist_x) /  ( 2f * _p * _p );
			float b = dist_x / a;
			float c = ( a - dist_y ) / a;			
			float ts = (b*b/4f) - c;
			if ( ts >= 0.0 ) {
				float rt = Mathf.Sqrt( -c + ( b * b ) / 4f);
				float[] ang = new float[2]{Mathf.Atan( ( -b / 2f ) - rt ),Mathf.Atan( ( -b / 2f ) + rt )};
				ret = new Vector3[2];
				for ( int i = 0; i < 2; i++ ){
					ret[i] = distXZ.normalized * _p * Mathf.Cos(ang[i]);
					ret[i].y = _p * Mathf.Sin(ang[i]);
				}
			}
			return ret;
		}

```
衝突可能な場合(届く場合)、 返値$ \vec{v} $は２通りあります。
$ \vec{v} $[0]が直線的に衝突する場合、$ \vec{v} $[1]は山なりに衝突する場合のベクトルです。
値をAddForceで渡す場合はForceMode.VelocityChangeを指定します。

```
Vector3 dir = target.position - transform.position;
float power = 30f;
Vector3[] v0 = CalcTargetVec (power, dir);
if (v0 != null) {
	obj.GetComponentInParent<Rigidbody> ().AddForce (v0[0], ForceMode.VelocityChange);
}
```
![スクリーンショット 2018-01-13 0.51.05.png](https://qiita-image-store.s3.amazonaws.com/0/59911/61294d9c-cb0d-4c47-cdae-ff36532dbbe9.png)

[落下地点を予測する](https://qiita.com/ELIXIR/items/1cdeb4ddef7e45e9aad5)
Debian 9 に SoftEther VPN Server をインストールする

Debian 9 で SoftEther VPN Server を インストールしようとすると `make` が失敗する。

```
make[1]: Entering directory '/opt/vpnserver'
Preparing SoftEther VPN Server...
ranlib lib/libcharset.a
ranlib lib/libcrypto.a
ranlib lib/libedit.a
ranlib lib/libiconv.a
ranlib lib/libintelaes.a
ranlib lib/libncurses.a
ranlib lib/libssl.a
ranlib lib/libz.a
ranlib code/vpnserver.a
gcc code/vpnserver.a -O2 -fsigned-char -pthread -m64 -lm -ldl -lrt -lpthread -L./ lib/libssl.a lib/libcrypto.a lib/libiconv.a lib/libcharset.a lib/libedit.a lib/libncurses.a lib/libz.a lib/libintelaes.a -o vpnserver
/usr/bin/ld: code/vpnserver.a(vpnserver.o): relocation R_X86_64_32 against symbol `StopProcess' can not be used when making a shared object; recompile with -fPIC
~中略~
/usr/bin/ld: lib/libintelaes.a(intel_aes.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
Makefile:18: recipe for target 'i_read_and_agree_the_license_agreement' failed
make[1]: *** [i_read_and_agree_the_license_agreement] Error 1
make[1]: Leaving directory '/opt/vpnserver'
```

どうやら OpenSSL のバージョンが新しくなったのが問題らしい。
https://github.com/SoftEtherVPN/SoftEtherVPN/issues/301#issuecomment-323595911

リリースノートにも書いてあった
https://ja.softether.org/5-download/history
> オープンソース版: SoftEther VPN 4.23 Build 9647 Beta (2017/10/18)
> 製品版: PacketiX VPN 4.23 Build 9647 Beta
> OpenSSL のバージョンを 1.0.2l にバージョンアップ。
> ソースコードが OpenSSL 1.1.x に対応。TLS 1.2 の新たな暗号化方式である DHE-RSA-CHACHA20-POLY1305, ECDHE-RSA-CHACHA20-POLY1305 をサポート。(この新機能を使用するためには、OpenSSL 1.1.x を用いて自前でコンパイルが必要です。)

# 解決策

parrot のリポジトリに softether-vpnserver のパッケージがあったのでこれを使います。

```
echo 'deb http://archive.parrotsec.org/parrot parrot main' > /etc/apt/sources.list.d/parrot.list
wget -qO - https://archive.parrotsec.org/parrot/misc/parrotsec.gpg | apt-key add -
apt update
apt install softether-vpnserver
```
JavaScriptで要ログインサイトのデータ収集サービスを作ってみる(part1)

全くのJavaScript初心者から学習してきた流れとか、方法とか色々書きます。
# 作りたい物
ログインが必要なサイトからデータを集めるサービス。

要は、某アーケード音ゲーのスコアツールを作ってみたいということです。
（他スコアツールを参考にしながら作っています。）

# やること
- ログイン状態で、任意のJavaScriptを実行→part1でやります
- JavaScriptで欲しいデータのあるHTMLの収集・スコアの抽出→part2以降で
- 抽出したスコアを何かしらの形式で出力しDL→part2以降で

# 任意のJavaScriptを実行する方法
とりあえずHTMLのヘッダに処理を書けば、そのページでJavaScriptが動くとのこと。
ということで、ヘッダ内にJavaScriptを追加・リンク先のソースファイルを参照し、データ取得処理を動かすことにします。
## ヘッダへのJavaScriptの追加
「ブックレット」と言うものを利用します。ブックマークみたいなもので、実行するとJavaScriptが動く、みたいな感じのもの？らしいです。(ほとんど他スコアツールの流用)
書き方は以下の感じで。JavaScriptを書くので、先頭に「javascript:」と書いて後は処理する感じで。(実際は1行にします)

```javascript:scoretoolBookret.js
javascript:(function(d,s){
  s=d.createElement('script');   // エレメント作成
  s.type='text/javascript';      // 属性追加
  s.src='sourceURL';             // 実行するソースのURL
  d.head.appendChild(s);         // ヘッダにエレメント追加
})(document);
```
単純にURL先のJavaScriptを実行してもらうようにする処理です。
ただし、実行するソースURLですが、データを取得したいサイトがhttpsならば、実行ソースの配置場所もhttpsじゃないとだめらしいです。（引っかかりました）

# データ抽出
昔Pythonでスクレイピングやっていたので、Pythonでやりたいなとか思ってましたが、JavaScriptでも意外と簡単にできましたのでそちらでやっていきます。
（プロトタイプはpythonで作ってた）

続きはPart2で
Solidityで文字列連結

どうも。
今回、Solidityで文字列連結をしている方がいらっしゃったのですが（下記リンク）、ライブラリを使っていたため、自力でなんとか実装できないかと挑戦してみました。

>  [Solidityの文字列結合
](https://qiita.com/bellbelljp/items/f6f3f17f28c1251d6725) @bellbelljp さんの記事

## 実装

```js:MyStringTest.sol
pragma solidity ^0.4.19;

contract MyStringTest {

    function strConnect() public constant returns(string){
        
        string memory str1 = "abc";
        string memory str2 = "def";
        bytes memory strbyte1 = bytes(str1);
        bytes memory strbyte2 = bytes(str2);
        
        bytes memory str = new bytes(strbyte1.length + strbyte2.length);
        
        uint8 point = 0;
        
        for(uint8 j = 0; j < strbyte1.length;j++){
            str[point] = strbyte1[j];
            point++;
        }
        for(uint8 k = 0; k < strbyte2.length;k++){
            str[point] = strbyte2[k];
            point++;
        }
        return string(str);
    }
}
```

一行ずつ見ていきましょう。


```js
string memory str1 = "abc";
string memory str2 = "def";

bytes memory strbyte1 = bytes(str1);
bytes memory strbyte2 = bytes(str2);
```

まずここで、"abc"という文字列と"def"という文字列をそれぞれstr1とstr2という変数に代入しています。
そしてその後、string型をbytes型に変換しています。
string型とbytes型は、基本的には同じことができるのですが、string型には`.length`メンバがなかったり、添字を使えなかったりなどと、文字列連結をする上で不便な点があります。なので変換をしています。

```js
bytes memory str = new bytes(strbyte1.length + strbyte2.length);
```

次に、bytes型のstrという変数を作っています。bytesは動的配列なので、ここで`new`句を使ってそれぞれ文字数文のバイトを確保しています。mallocみたいなもんですね。

```js
uint8 point = 0;

for(uint8 j = 0; j < strbyte1.length;j++){
    str[point] = strbyte1[j];
    point++;
}
for(uint8 k = 0; k < strbyte2.length;k++){
    str[point] = strbyte2[k];
    point++;
}
```

次は、実際の文字列連結です。strのpoint番目の配列、つまりpointバイトの場所に、それぞれstrbyte1とstrbyte2の文字を一文字ずつコピーしていきます。正確に言うと参照のコピーになるのかな…？
あんまりEthereumのポインタがわかっていないのでそこはよくわかりません。
とりあえずこれでstrに連結した文字が代入されました。

```js
return string(str);
```

最後に、bytes型をstring型に直して値を返しています。

----


以上、無茶がありましたが結構簡単に実装できました。ちなみに、Solidityの文字列連結のライブラリでは、Library句を使ってstring型自体に文字列連結のメソッドを追加しているようです。興味があったら調べてみてください。

また、今回のコードは、連結する変数が2つと固定していることもあり、あまり汎用的ではありません。
文字列型の配列に、それぞれ文字列を代入して、最後に全部を連結する、なんて実装の仕方をすればもう少し綺麗になると思います。が、今回の記事はそこまで求めていないので妥協しました…。

最後まで閲覧いただき、ありがとうございました！
Swift：文字列を一定の文字数ごとに分割した配列にして取得する

#背景
Swift4になって文字列の操作がかなり簡単になりましたが、いまだに文字列を一定の文字数ごとに分割した配列として取得するメソッドが用意されていません。
そこで、`String`の`extension`を作ってみたので記しておきます。

#ソースコード
```swift:
import Foundation

extension String {
	func splitInto(_ length: Int) -> [String] {
		var str = self
		for i in 0 ..< (str.count - 1) / max(length, 1) {
			str.insert(",", at: str.index(str.startIndex, offsetBy: (i + 1) * max(length, 1) + i))
		}
		return str.components(separatedBy: ",")
	}
}
```

#用例
```swift:
let str = "abcdefghijklmnopqrstuvwxyz"
let array = str.splitInto(3)
print(array)
// >> ["abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "vwx", "yz"]
```

#余談
いくつか同様のことを実装している文献を見つけましたが、提案手法はその中でもかなり短くまとまっていると思います。
また、`SubString`や`Character`の配列で取得するよりも`String`の配列で取得できた方が使い勝手が良いと思うのでアレンジしてみました。
自家製仮想マシン起動ツール

# はじめに
macでVirtualBoxを使用して検証とかする場合、いちいちVirtualBox起動→仮想マシン起動→SSHで接続して作業する。
本記事は、スクリプトによりバックグラウンドから仮想マシンを起動し、簡単にSSH接続するための仮想マシン起動ツールです。
## 環境
mac + ターミナル + VirtualBox

## スクリプト
(※)変数の"N"は、IPアドレスを意味する

```bash
#!/bin/bash

clear

#変数
DNS=192.168.N.N
WEB=192.168.N.N
MAIL=192.168.N.N
DB=192.168.N.N

#関数
submenu1(){
 clear
 echo " 1 DNSサーバ"
 echo " 2 Webサーバ"
 echo " 3 Mailサーバ"
 echo " 4 DBサーバ"
 echo -e "\n"
 echo "サーバを選択してください"
}

submenu2(){
 read servernum
 case ${servernum} in
  1) VBoxManage startvm "DNSサーバ" -type headless ;;
  2) VBoxManage startvm "Webサーバ" -type headless ;;
  3) VBoxManage startvm "Mailサーバ" -type headless ;;
  4) VBoxManage startvm "DBサーバ" -type headless ;;
 esac
}

submenu3(){ 
 read servernum
 case ${servernum} in
  1) ssh root@${DNS} ;;
  2) ssh root@${WEB} ;;
  3) ssh root@${MAIL} ;;
  4) ssh root@${DB} ;;
 esac
} 

submenu4(){
 read servernum
 case ${servernum} in
  1) ping ${DNS} ;;
  2) ping ${WEB} ;;
  3) ping ${MAIL} ;;
  4) ping ${DB} ;;
 esac
}

#処理
echo " 1 hostsを表示する"
echo " 2 サーバを起動する"
echo " 3 サーバに接続する"
echo " 4 疎通確認"
echo -e "\n"
echo "実行したい処理の番号を入力してください"

read inputkey

case ${inputkey} in
 1 ) cat /etc/hosts ;;
 2 ) submenu1;submenu2 ;;
 3 ) submenu1;submenu3 ;;
 4 ) submenu1;submenu4 ;;
esac

exit 0
```

## 例
1. macからターミナルを起動し、スクリプトを実行する。  
`./server_conect.sh`
2. 仮想マシンを起動する場合、2を入力してreturnキーを押す。
![スクリーンショット 2018-01-12 23.01.28.png](https://qiita-image-store.s3.amazonaws.com/0/221759/3653d881-f820-b41b-f9e9-9399bdda9453.png)
3. ここでは例として2のWebサーバを起動するため、2を入力してreturnキーを押す。
(※)正常に起動できる場合、「VM "仮想マシン名" has been successfully started.」のようなメッセージが出力される
![スクリーンショット 2018-01-12 23.08.45.png](https://qiita-image-store.s3.amazonaws.com/0/221759/fb1d7b42-a2e5-66f3-6c9a-09cf076359c8.png)
4. 再度、スクリプトを実行する。  
`./server_conect.sh`  
5. SSh接続するため、3を入力してreturnキーを押す。 
![スクリーンショット 2018-01-12 23.12.35.png](https://qiita-image-store.s3.amazonaws.com/0/221759/60f85dab-f1ef-028c-89af-c481d7d68b76.png)
6. 先ほど起動したWebサーバに接続するため、2を入力してreturnキーを押す。パスワード入力が求められるので、ログインユーザのパスワードを入力する。
![スクリーンショット 2018-01-12 23.16.14.png](https://qiita-image-store.s3.amazonaws.com/0/221759/22604575-4cf5-b4d2-b8a6-fdf2879fb05a.png)
(※)当スクリプトのSSH接続は、パスワード認証で接続している
Processing3で閉じるボタンを押した時に終了確認する方法

# はじめに

Processingで閉じるボタン(×ボタン？)を押した時に終了確認をする方法です。

# 実行環境

Processing3.3

# コード

```java:on_close_sample.pde
// 最初に閉じるボタンを押した時のみJPanelの表示までしばらく時間がかかる

import processing.awt.PSurfaceAWT;
import processing.awt.PSurfaceAWT.SmoothCanvas;
import java.awt.Canvas;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

JFrame jframe;
SmoothCanvas canvas;

void setup() {
  // このスケッチのSmoothCanvasを取得
  canvas = (SmoothCanvas) surface.getNative();
  
  // canvasのFrameをJFrameにキャストして取得
  jframe = (JFrame) canvas.getFrame();
  
  // jframeのwindowListenerをremove
  // forで全てremoveしていいのか少し不安
  for (WindowListener evt : jframe.getWindowListeners()) {
    jframe.removeWindowListener(evt);
  }
  
  jframe.addWindowListener(new WindowClosing());
  
  size(400, 400);
}

void draw() {
  background(255);
  ellipse(200, 200, frameCount, 100);
}

// xボタンを押した時に発火するイベント
class WindowClosing extends WindowAdapter {
  public void windowClosing(WindowEvent e) {
    int ans = JOptionPane.showConfirmDialog(
      jframe, 
      new JPanel(),
      "本当に終了しますか？",
      JOptionPane.YES_NO_OPTION,
      JOptionPane.INFORMATION_MESSAGE
      );
    println(ans);
    
    if (ans == JOptionPane.YES_OPTION) {
      println("プログラムによる終了処理の実行");
      exit();
    } else {
      // Yes以外を押した時は何もしない
      jframe.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    }
  }
}
```

# 終わりに

これで実装できますが、最初に閉じるボタンを押した時だけ、表示が遅いのが少し気になります。

なにか改善方法があれば教えていただけるとうれしいです。

# 参考

[Preventing a PApplet closing the calling Java program - Processing Forum](https://forum.processing.org/two/discussion/15692/preventing-a-papplet-closing-the-calling-java-program)
[embedding PApplet in Java JFrame - Processing Forum](https://forum.processing.org/two/discussion/12774/embedding-papplet-in-java-jframe)
[ウィンドウクローズ時の終了確認ダイアログボックス - Javaをはじめよう](https://ameblo.jp/espelion/entry-10783153338.html)
[メッセージタイプを指定して選択ダイアログを表示する - JavaDrive](https://www.javadrive.jp/tutorial/joptionpane/index7.html)
[processingで選択ダイアログを表示する - qiita
](https://qiita.com/doi10070511/items/a3ce41801de7805a00fa)
gulp導入でハマったときの対処メモ

#gulpのインストール時

インストールは下記のコマンドで

```ruby:qiita.rb
$ sudo npm install gulp-sass --save-dev
```

下のようなエラーが出ていた

```ruby:qiita.rb
gyp ERR! configure error 
gyp ERR! stack Error: EACCES: permission denied, mkdir '/Users/***/.nodebrew/node/v9.4.0/lib/node_modules/gulp-sass/node_modules/node-sass/build'
gyp ERR! System Darwin 15.6.0
gyp ERR! command "/Users/***/.nodebrew/node/v9.4.0/bin/node" "/Users/***/.nodebrew/node/v9.4.0/lib/node_modules/gulp-sass/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library="
gyp ERR! cwd /Users/***/.nodebrew/node/v9.4.0/lib/node_modules/gulp-sass/node_modules/node-sass
gyp ERR! node -v v9.4.0
gyp ERR! node-gyp -v v3.6.2
gyp ERR! not ok 
Build failed with error code: 1
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! node-sass@4.7.2 postinstall: `node scripts/build.js`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the node-sass@4.7.2 postinstall script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/***/.npm/_logs/2018-01-12T09_08_16_651Z-debug.log
```
下記コマンドを打つことで解消

```ruby:quiita.rb
sudo npm config set user 0
$ sudo npm config set unsafe-perm true
```
vagrant コマンド一覧（必要最低限）

# 忘れないためのメモ
よければどうぞ

| コマンド | 操作の説明 |
|:----------:|:-----------:|
| vagrant up     | 仮想マシンを起動する            |
| vagrant halt   | 仮想マシンを停止                |
| vagrant suspend| 仮想マシンをスリープさせる        |
| vagrant resume | 仮想マシンをスリープから復帰させる  |
| vagrant reload | 仮想マシンを再起動              |
| vagrant status | 仮想マシンの状態を確認           |
| vagrant destroy| 仮想マシンを破棄                |
| vagrant ssh    | 仮想マシンへログイン             |
RancherOS でホスト追加時に「ERROR: http://[IP address]:[port]/v1 is not accessible (Failed to connect to [IP address] port [port]: No route to host)」がでる

RancherOSで管理サーバーを立ち上げて意気揚々とホスト追加しようとしたら以下のようにエラーメッセージで埋め尽くされました

```
sudo docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.7 http://[Ip address]:8080/v1/scripts/.....

INFO: Running Agent Registration Process, CATTLE_URL=http://[Ip address]:8080/v1
INFO: Attempting to connect to: http://[Ip address]:8080/v1
ERROR: http://[Ip address]:80800/v1 is not accessible (Failed to connect to [Ip address] port 8080: No route to host)
```

## 解決方法
入れたDockerが非サポートのバージョンだったのでDockerをuninstallして入れ直したら解決した。  
RancherOSのドキュメント[Getting Started with Hosts](http://rancher.com/docs/rancher/v1.6/en/hosts/#supported-docker-versions)で対応しているDockerバージョンの一覧を参照出来る。また各バージョンのインストールスクリプトが用意されているのでそれを使うとスムーズにインストールできる。

![](https://i.imgur.com/TGCmk95.png)
えいえい　おこった？　おこってないよ❤　を Swiftで　つくるるるっる

情報が古くなっており、メンテナンスが難しいため、こちらのページはアーカイブさせていただきました。

古い情報でも閲覧を希望される場合は、編集履歴からご覧くださいませ。
メールの送信

メールを送信するプログラムの備忘録

```Python
#メールを送信するプログラム
import smtplib

#SMTPサーバー名とポート番号の設定
smtp_obj = smtplib.SMTP('smtp.gmail.com', 587)
smtp_obj.ehlo()

#TLS暗号化の開始
smtp_obj.starttls()

#SMTPサーバにログインする
smtp_obj.login('ログイン名', 'パスワード')

#メールを送信する
smtp_obj.sendmail('送信者アドレス', '送信先アドレス', 'subject:タイトル\n本文')

#SMTPサーバーから切断
smtp_obj.quit()
```
Swift：「ある数が0以上ならある数、0未満なら0」をスマートに取得する方法

#はじめに
「ある数が0以上ならある数、0以下なら0」を取得したい時が度々あり、毎回この方法でいいのか？という風に腑に落ちない気持ちでコーディングをしてきました。ようやく腑に落ちる方法にたどり着いたので記します。
今まで使ってきた方法を腑に落ちなかった順に載せます。

#1. if文
```swift:
var a: Int = b  // bはある数
if a < 0 {
    a = 0
}
print(a)
```

この方法はやってることが大したことないのに4行も消費してしまって嫌だったのを覚えています。

#2. 三項演算子
```swift:
var a: Int = b > 0 ? b : 0  // bはある数
print(a)
```

この方法は1行で目的の数を取得できるのでマシになったのですが、bと0を二回書いているのが二度手間っぽくて嫌でした。

#3. カレント・ベスト・ソリューション
```swift:
var a: Int = max(b, 0)  // bはある数
print(a)
```

`max()`メソッドを用いれば、bと0を一度しか記述せず、目的を達成できることに気づきました。今まで気づかなかったのが馬鹿みたいです。

#終わりに
熟練のプログラマの方々からしたら今更というか、あまりに稚拙なことなのですが、自分はこの方法に辿り着くまでに長い時間がかかってしまいました。こういう経験、あったという方はぜひコメントの方にて共有していただけると嬉しいです。
2018/01/12 Docuworks：トレンドマイクロのウィルスバスターCEを使用している場合変換が出来なくなる可能性

2018/1/12にメールが来た
トレンドマイクロ社ウイルスバスター コーポレートエディションをお使いのお客様へ
「DocuWorks文書に変換が出来なくなる等の事象に対する回避策」のご案内

現在、トレンドマイクロ社ウイルスバスター コーポレートエディションを
お使いのお客様環境にて、以下の様な事象が確認されております。

■発生する事象
　・DocuWorks文書に変換出来ない
　・署名の付いた文書を開こうとすると、DocuWorks Viewerが異常終了する
　・ページ番号の設定が正常に行えず、DocuWorks Viewerが異常終了する
　・電子印鑑関連の作業が正常に行えない

■事象が発生するDocuWorksのバージョン
　・DocuWorks 7 全バージョン
　・DocuWorks 8 全バージョン

■現時点で考えられる原因
　・セキュリティソフト（ウイルスバスター）により、DocuWorksで使用する
　　プログラムがロックされる事により、上記現象が発生していると考えら
　　れます。

■対処方法
　・以下に記載するトレンドマイクロ社のFAQの手順に沿って、セキュリ
　　ティソフト（ウイルスバスター）側でDocuWorksで使用するプログラムの
　　除外設定を行います。

#またかよ
ウィルスバスターこのてのバグを何回やらかすんだろうか。しかも法人向けのバージョンでしかも法人向けのDocuworksでやらかすなんて普通はあり得ないのだが。海外だと日本人優しいから怒らないけどね。
ggplot2で凡例を消す。


    ## 特定の凡例（colour）を消す１
    p + guides(colour=FALSE)
    ## 特定の凡例（colour）を消す２
    p + scale_colour_discrete(guide=FALSE)
    ## 全ての凡例を消す
    p + theme(legend.position = 'none')

## 例

    library(ggplot2)

    p <- ggplot(mtcars, aes(wt, mpg)) + geom_point(aes(colour = factor(cyl)))
    ## 凡例あり
    p

    ## 凡例なし
    p + guides(colour=FALSE)
    p + scale_colour_discrete(guide=FALSE)
    p + theme(legend.position = 'none')

mtcarsは自動車の燃費等に関するデータセット(32台分)。wt: Weight (1000 lbs)、mpg: Miles/(US) gallon、cyl: Number of cylinders。

## 参考
- [Legends (ggplot2)](http://www.cookbook-r.com/Graphs/Legends_%28ggplot2%29/)
- [Points — geom_point • ggplot2](http://ggplot2.tidyverse.org/reference/geom_point.html)
Rails の validates_uniqueness_of と MySQL の UNIQUEキー制約について

2020年9月追記: Rails6.1 でこの問題に対応するようです。
このあたりに詳しく書かれています。
↓
[Rails 6.0で"Uniqueness validator will no longer enforce case sensitive comparison in Rails 6.1."という警告が出たときの対処法 - Qiita](https://qiita.com/jnchito/items/e23b1facc72bd86234b6)

# はじめに
Rails + MySQL でちょいちょいハマるので少しまとめてみました。

Railsの validation 機能は大変便利ですが、 uniqueness は presence や length よりも少し気を配る必要があります。

まず、「何を持ってユニーク(一意)とするか?」の意識をしなければなりません。
「大文字・小文字を同一視するか?」や「空白の扱いはどうするか?」などです。

ここでは大文字・小文字について考えてみます。尚、全角文字も考慮すると複雑になりすぎるのでここでは考えないことにします。空白問題も同様にここでは考えないことにします。

まず、知っておかなければならないのは **「デフォルトの大文字・小文字の扱いは Rails だと区別し MySQL は区別しない」** ということです。私はこの違いを忘れて何度かミスをしました。

ここでは Team モデルの name 属性について考えてみましょう。
**以降、チーム名 `Dragon` の1レコードが既に入っているとみなして考えてみます。**

# 大文字・小文字を同一視する場合

![validation error](https://qiita-image-store.s3.amazonaws.com/0/24954/c968a0dc-696c-41f1-a2f3-3fa36d753d3d.png "DRAGON は登録させない")


例えばチーム名に `Dragon`があれば `DRAGON` や `dragon` は許さない場合です。これは以下で対応できます。

以下で RDBMS(MySQL)側に UNIQUE 制約を付けています。

```shell
$ rails new uniqueness_test -d mysql
$ rails db:create
$ rails g scaffold Team name:uniq # ← UNIQUE キー制約付けてるよ
$ rails db:migrate
$ rails server
```

以下で `case_sensitive: false` にすることで同一視しています。

```ruby:app/models/team.rb
class Team < ApplicationRecord
  validates_uniqueness_of :name, case_sensitive: false # デフォルトは `true` だよ
end
```

ちなみにここで `case_sensitive: true` にした場合、 `DRAGON` を登録すると以下のようにエラーとなります。私はこの時、「あれ?ちゃんと validation 書いてるのに何で?チェックすり抜けた??」と一瞬混乱しちゃたりします。

![1515725671844.jpg](https://qiita-image-store.s3.amazonaws.com/0/24954/75a4896c-e3a7-91ad-df27-5422cd54c874.jpeg)


# 大文字・小文字を同一視しない場合

例えばチーム名にて `Dragon` と `DRAGON` を別物とする場合です。

![UniquenessTest - http___localhost_3000_teams.png](https://qiita-image-store.s3.amazonaws.com/0/24954/13a59a81-51cb-5faa-cabe-f8d767912df2.png "'Dragon' と 'DRAGON' が共存している状態")

MySQL 側をいじらないといけないので面倒です。
先程の環境にマイグレーションを追加します。

ここでは MySQL ではカラムに対して BINARY 指定をします。[^1]

[^1]: 他にも COLLATE を使うなどの方法があります。詳しくは MySQL のドキュメントを参照して下さい。

```ruby:db/migrate/20180108034452_change_column_name_of_team.rb
class ChangeColumnNameOfTeam < ActiveRecord::Migration[5.1]
  def up
    execute("ALTER TABLE teams MODIFY name varchar(255) BINARY")
  end

  def down
    execute("ALTER TABLE teams MODIFY name varchar(255)")
  end
end
```

個人的にはここで MySQLに依存する形になってしまうので汎用性がなくなるのが嫌です。Rails側でもっとうまい書き方あるのかな？

あとはモデルを以下のようにしてDBと一致させます。

```ruby:app/models/team.rb
class Team < ApplicationRecord
  validates_uniqueness_of :name, case_sensitive: true # case_sensitive はデフォルト true なので省略可
end
```

ちなみにフィールドが BINARY になっているかどうかは db/schema.rb を見ればわかります。(collation の部分が追加されます)

```ruby:db/schema.rbの抜粋
     t.string "name", collation: "utf8_bin"
```

# おわりに
validation の部分って Rails では気軽に書けるので便利ですよね。今回は DBに依存する部分が大きいと感じたので書いてみました。

一般的には例えば validates_length_of なんかも 厳密に定義して Rails のモデルとDB側を一致させるのかな?それだと変更に対応しづらいので DB側の文字列長はデフォルト。Railsのモデルで調整。などとしております。

あと、今回のテーマでは **空白の扱い** についても注意が必要だと感じています。
以下のデータはチーム名として同一でしょうか?それとも異なりますか?登録を許しますか?

```
データ1: "Cat's EYE"     ← 半角スペースが間に1つ
データ2: " Cat's EYE "   ← 半角スペースが先頭と後方と単語中に1つずつ
データ3: " Cat's   EYE " ← 半角スペースが沢山混ざってる
```

これについては別途、私なりの考えを書いてみようかな(気が向いたら...)

----
一貫性のあるハッシュアルゴリズム分析

データベースのサブテーブルや分散キャッシュを実行するときには、必然的に問題が発生します。

ノード間でデータを均等に分散させ、できるだけノードを追加または削除するときに、影響を受けるデータを最小限に抑える方法。

# ハッシュモジュロ
ランダムに配置されていないと言う、多くの問題をもたらすでしょう。考えられる最も簡単な方法は、ハッシュモデリングです。

入ってくるKeyは、index = hash（key）％Nとして計算できます。ハッシュ関数は、文字列を正の整数に変換するハッシュマッピング法です.Nはノードの数です。

これはデータの一様な分布を満たすことができますが、アルゴリズムはフォールトトレランスとスケーラビリティが劣ります。

例えば、ノードの追加や削除の際には、すべての鍵を再計算する必要があり、明らかにそのようなコストが高いため、一様な分布と耐障害性と拡張性を満たすアルゴリズムが求められる。

# 一貫したハッシュアルゴリズム
ハッシュアルゴリズムは、リングによって形成されるすべてのハッシュ値と一致し、その範囲は0〜2 ^ 32-1です。以下に示すように
![image.png](https://qiita-image-store.s3.amazonaws.com/0/32434/c5fad204-f47a-2f10-ad2c-bdff7bd798e5.png)



各ノードがこのリングにハッシュされた後、次のようにハッシュの後に、ノードのIPホスト名フィールドをキーハッシュ（キー）として使用できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/32434/36922543-d72a-18fc-0917-f5fc5fac8acd.png)



同じハッシュ関数キーを使用して、対応するノードにデータを配置する必要がある場合、このリングにもマップされます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/32434/003e47b3-8602-4f97-2591-38164625c18d.png)



このようにして、k1をノードN1に、ノードk2をノードN3に、ノードk3をノードN2に時計回りに配置できます。

# フォールトトレランス
N1のダウンタイムを想定しているこの時点で：
![image.png](https://qiita-image-store.s3.amazonaws.com/0/32434/a10da393-2820-3e0d-78c7-f65910ca9f68.png)



それでも時計回りの方向によれば、k2とk3は変わらず、k1だけがN3に再マッピングされる。これはフォールトトレランスの非常に良い保証です。ノードが停止している場合は、データの小さな部分にしか影響しません。

# 拡張可能
新しいノードを追加する場合：
![image.png](https://qiita-image-store.s3.amazonaws.com/0/32434/03fb7843-3aad-7ce1-2b06-a83f1fc75dc4.png)



N2とN3にノードN4が追加された場合、データの印象はk3になります。データの残りの部分も変更されていないため、スケーラビリティを確保するのにも非常に適しています。

# 仮想ノード
これまでのところ、アルゴリズムはまだまだ問題になります。

ノードが小さい場合、データの分布が不均一になります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/32434/e4107ef8-a846-9ee0-6fbc-576815dd530d.png)



これにより、N1ノードのデータの大半がN2ノードの少量のデータになります。

この問題を解決するために、均一なハッシュアルゴリズムが仮想ノードに導入される。仮想ノードと呼ばれるリング上に配置された複数のノードを生成するために、各ノードを複数回ハッシュする：
![image.png](https://qiita-image-store.s3.amazonaws.com/0/32434/fbe1e7ca-4eef-0d98-032e-10a6b90efa07.png)



計算は、IP番号の後に追加して、ハッシュ値を生成することができます。

このようにして、仮想ノードを実際のノードにさらに元の基準でさらにマッピングするステップだけで、少数のノードが均一性を満たすことが可能になる
cakephp3でajax使う時に400エラーの原因

下記の設定をしているとajaxdeでPOST送信しても400や403エラーが起きる。

```AppController.php
        $this->loadComponent('Security');
        $this->loadComponent('Csrf');
```


対応策として下記のようにすることで回避することが出来るみたい。

```Class.php
    use Cake\Event\Event;

    public function beforeFilter(Event $event) {
        parent::beforeFilter($event);

        if (in_array($this->request->action, ['関数名'])) {
            // $this->loadComponent('Security');
            $this->Security->setConfig('unlockedActions', ['関数名']);

            // $this->loadComponent('Csrf');
            $this->eventManager()->off($this->Csrf);
        }
    }
```
Thymeleaf で HTML を共通部品化してデザイン統一と開発効率の向上を図った

Spring Boot + Thymeleaf な環境において、複数人でフロントエンド開発をすることがあり、
同じ構造とデザインがよく現れる場合において、こんな課題があってこう解決したっていうメモです。
（誰かに引き継ぐとしても共通部品化はアリかも）

### 環境
Spring Boot: 1.3.2 RELEASE
Thymeleaf: 2.14 RELEASE

### Thymeleaf とは
テンプレートエンジンの 1 つであり、Java 環境での使用が推奨されています。
私が気に入っているのは、HTML の中に Thymeleaf 独自の構文を埋め込んで使うことができる点です。
まず ネイティブな HTML を書いて、大まかに構造やデザインを決め、そのコードをあまり破壊せずに
完成させていくことができます。
（私は他のテンプレートエンジンを使ったことがなく……実は世の中そういうものなのかもしれませんが）
Spring Boot と組み合わせると、いろいろできるよ（雑ですが）と言われています。
公式サイト：http://www.thymeleaf.org/

### 私がいた現場での課題
実はこれ 2 年弱前のことで、最近フロントエンドに戻って思い出したので書いてます。
当時、開発の真っただ中で、以下の課題を抱えていました。

* 複数人が画面テンプレートを実装しており、各々が実装した構造やデザインにバラつきがあった。  
（コーディング規約はあったが、残念ながら全員が守っているわけではなかったので、規約を充実させるのは現実的ではないとした（この判断がただしかったのか今でも疑問。後から充実させたが、最初にするべきだったのでは……））
* サーバサイド開発タスクが増えるにつれ、画面テンプレートの実装には少人数での担当（効率）が求められた。  
（最終的には私一人で weekly 数十個の画面テンプレートをつくらなくてはならなかった）

### Thymeleaf でつくる共通部品
結論から行くと、こんな感じでつくります（Thymeleaf の文法については省略します）。

```html:呼出側
<!-- form.html 内にある text-form という部品を呼び出す。
     引数として、templateId, label, required を渡す。
     templateId には "accountName" という文字列を渡す。
     label にはメッセージリソース内で msg.account.name に定義されている文字列を渡す。
     required には false を渡す -->
<div th:replace="form :: text-form(
    templateId = 'accountName',
    label      = #{msg.account.name},
    required   = false)">
</div>
```

```html:共通部品
<!-- text-form という名前の部品である。
     引数として、templateId, label, required を受け取る。 -->
<div th:fragment="text-form(templateId, label, required)">
    <label th:for="${templateId}" th:text="${label}"></label>
    <div>
        <input type="text" th:id="${templateId}" th:name="${templateId}" th:field="*{__${templateId}__}"
               th:required="${required}? required"/>
    </div>
</div>
```

実際は CSS クラスの適用やら Javascript の呼び出しやらがあり、複雑になりますが、共通部品を定義しておけば、
必要な部品に必要なパラメータを渡して呼び出すだけで、デザインの統一が取れた構造を効率よく作っていけます。

### 共通部品化をした後の課題
デザインの統一が取れたうえに効率的に画面テンプレートを開発でき、無事に予定通りリリースすることができました。
しかし、開発が進んでくると、以下の課題がでてきました。

* 多少関わらずデザイン差分単位で共通部品を作ったため、共通部品が大量に生まれてしまい、適した共通部品を探すコストが大きくなった。  
→ これは例えば、引数が変わらない範囲で、共通部品内に switch 構文を書くなどすれば部品数を削減でき改善できると思います。  
→ 本質的には設計の問題なのかもしれません。
* 共通部品にする単位の設計に充分に時間を割いておらず、最適とはいえない単位で作られた共通部品が多々ある。  
→ 上記のコード例ではフォーム単位ですが、これが最適なのか？　という検証はプロダクトごとにあるはず。  
→ layout-dialect 機能（ http://www.ultraq.net.nz/thymeleaf/layout ）を駆使するのは一手ですね。


### 個人的に考えていること
* そもそも自動生成の道があったのではないかということ  
→ 当時は考えもつかなかったが……。今は修正がメインですが、当時は大いに価値があったはず。
* Thymeleaf 3.x にアップデートすると更に効率的な共通部品化の道があるのではないかということ  
→ 共通部品化に使えそうな新機能がいくつか見受けられた。後方互換性があるので、あまり怖くはないはず
仮想通貨XPのUbuntu版ウォレット(GUI)をビルドする

# 要点

* 公式ダウンロードページからダウンロードできるUbuntu Walletが壊れてる(?)
* GithubのReleaseにあるソースコードもそのままではビルドできない
* GUI版ウォレットをビルドしたdockerイメージを作ったよ

# 背景

現時点(2018年1月12日)では、[公式サイト](https://www.xpcoin.io/downloads/)のUbuntu版ウォレットのダウンロードリンクをクリックすると、
18MBあるはずなのに、ダウンロードしたファイルは1MBちょっとになってしまう。

一応実行しようとしてみても、エラーになる。

~~~bash
$ ./xp_linux_latest 
bash: ./xp_linux_latest: バイナリファイルを実行できません: 実行形式エラー
~~~

圧縮されているのかと思ったが、どうもELF形式らしい。

~~~bash
$ file xp_linux_latest 
xp_linux_latest: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), too many program (2573)
~~~

Contactに連絡はしてみたけれども、今の所応答なし。
もしかしたらCDNの不具合かも。

# ビルド時の注意

[GitHubのReleaseページ](https://github.com/eXperiencePoints/XPCoin/releases)にある、Release 1.1.0の「Source code」はライブラリの設定が間違っていてビルドできないので要注意。

リポジトリの最新版は修正されているので、`git clone`でソースコードを落とせばOK。

あとは`doc/readme-qt.rst`に書いてある手順に従えばビルドできる。

# 実環境でのビルド

Ubuntu 16.04では以下のようにして`XP-qt`ができればOK。

~~~bash
sudo apt-get install -y qt4-qmake libqt4-dev build-essential libboost-dev libboost-system-dev \
    libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev \
    libssl-dev libdb++-dev libqrencode-dev git
    
git clone https://github.com/eXperiencePoints/XPCoin.git

cd XPCoin

qmake
make -j4
~~~

# Dockerイメージ作成

ビルドのために余分なパッケージをインストールしたくなかったので、Dockerイメージで固めてしまう。
下記のような`Dockerfile`を作成。

~~~Dockerfile:Dockerfile
FROM ubuntu:16.04
MAINTAINER 330k

RUN apt-get update
RUN apt-get install -y qt4-qmake libqt4-dev build-essential libboost-dev libboost-system-dev \
  libboost-filesystem-dev libboost-program-options-dev libboost-thread-dev \
  libssl-dev libdb++-dev libqrencode-dev git

WORKDIR root

RUN git clone https://github.com/eXperiencePoints/XPCoin.git

WORKDIR XPCoin

RUN qmake
RUN make -j4

ENTRYPOINT /root/XPCoin/XP-qt
~~~

イメージを作成。

~~~bash
$ docker build . -t xpwallet
~~~

コンテナ起動。ウォレットのデータを保存するボリューム(コンテナ側は`/root/.XP`)はお好みの場所に永続化してください。

~~~bash
$ docker run \
  -e DISPLAY \
  -e QT_X11_NO_MITSHM=1 \
  -v ~/.XAuthority:/root/.Xauthority \
  -v ~/.XP-docker:/root/.XP \
  --net host \
  xpwallet
~~~

イメージをDocker Hubに上げたので、
Dockerfileなしでも、以下のコマンドで一発で起動できます(容量多いので注意)。

~~~bash
$ docker run \
  -e DISPLAY \
  -e QT_X11_NO_MITSHM=1 \
  -v ~/.XAuthority:/root/.Xauthority \
  -v ~/.XP-docker:/root/.XP \
  --net host \
  330k/docker-xpwallet-qt
~~~

もしくは下記でも可

~~~bash
$ xhost local:
$ docker run \
  -e DISPLAY \
  -e QT_X11_NO_MITSHM=1 \
  -v /tmp/.X11-unix:/tmp/.X11-unix \
  -v ~/.XP-docker:/root/.XP \
  -p 28192:28192 \
  330k/docker-xpwallet-qt
~~~

# その他の方法

Windows版をダウンロードして、Wineで動かすほうが楽かも。