OmniAICreator/Qiita-1.07M huggingface dataset:
Windows で Open JTalk を使う（Bash on Ubuntu on Windows と コマンドプロンプトでお手軽に）

#はじめに
Windows 10 環境で手軽に Open JTalk を使った音声合成を試してみたいと思います。

#準備
Bash on Ubuntu on Windows を使用できるようにしておきます。

#手順
## Bash on Ubuntu on Windows 上に Open JTalk をインストール
bash を起動した状態で下記のように実行します。
```
sudo apt update
sudo apt install open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001
```

これで使える状態になりました。

```
echo こんにちは | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -ow out.wav
```
とすれば、out.wav ファイルが生成されます。
Ubuntu なので簡単ですね。


## Windows から使う
bash 上で .wav ファイルを再生する方法が分からなかったので、Windows環境から呼び出して簡単に使えるようにしてみます。

- シェルスクリプトの作成

```
vi /usr/local/bin/ojt.sh
```

```ojt.sh
echo $1 | open_jtalk -x /var/lib/mecab/dic/open-jtalk/naist-jdic -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -ow out.wav
```


- 権限変更

```
chmod 755 /usr/local/bin/ojt.sh
```

としておきます。

- Windows 環境から実行

コマンドプロンプト や PowerShell から
```
C:\temp>bash /usr/local/bin/ojt.sh こんばんは
```

と実行するとカレントディレクトリ（この場合、c:\temp）に out.wav が生成されるので、これを再生します。
Windows なので、再生するのはいろいろと手段がありますね。

- その他

.htsvoice を変更して声を変更することもできます。
スクリプトファイルで絶対パス指定にすればファイルはどこに置いても大丈夫なはずです。
TabLayoutでアイコンが設定できない問題

TabLayoutとViewPagerで、アプリを作ろうとしていました

###困っていたこと
```java
tabLayout.getTabAt(0).setIcon(R.drawable.ic_tab0);
```
何故かこのコードでアイコンが設定できませんでした

###解決法
問題点: コードの順番
ViewPagerをセットした**後で**アイコンをセットするようです

###コード
```java
TabLayout tabLayout = (TabLayout)findViewById(R.id.tabLayout);
// set viewPager to TabLayout
tabLayout.setupWithViewPager(viewPager);
// set icons to TabLayout
tabLayout.getTabAt(0).setIcon(R.drawable.ic_input);
tabLayout.getTabAt(1).setIcon(R.drawable.ic_hospital);
tabLayout.getTabAt(2).setIcon(R.drawable.ic_log);
```

###参考
https://stackoverflow.com/questions/30892545/tablayout-with-icons-only
【Swing】Macでメニューバーに任意の名称を表示する方法

とっさに出てこなかったのでメモ。
# 問題

```MainWindow.java
public class MainPanel extends JPanel{
	public MainPanel(){
		JButton button1 = new JButton("ボタン");
		add(button1);
	}
	public static void main(String[] args){
		JFrame frame = new JFrame();
		MainPanel mainPanel = new MainPanel();
		frame.getContentPane().add(mainPanel);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    	frame.setVisible(true);    
	}
}
```

# 解決策
このままでは、メニューバーに`MainWindow`と出てしまうので、次のようにします。
macOS 10.12.6、JRE 9.0.1で確認済み。


```MainWindow.java
public class MainPanel extends JPanel{
	public MainPanel(){
		JButton button1 = new JButton("ボタン");
		add(button1);
	}
}

//別クラスを作る。名前は任意
class Loader{
	public static void main(String[] args){
		//システムのメニューバーを使う
	 	System.setProperty("apple.laf.useScreenMenuBar", "true");
	 	//アプリケーション名の指定
    	System.setProperty("apple.awt.application.name", "test");
		JFrame frame = new JFrame();
		MainPanel mainPanel = new MainPanel();
		frame.getContentPane().add(mainPanel);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    	frame.setVisible(true);    
	}
}
```

# 補足説明
`System.setProperty` でJREにプロパティを指定します。この際、 **Swingが読み込まれる前に指定する** のがポイントです。
JPanelを拡張しているクラスに書くと、Swingが先に読み込まれてしまいます。そのため、Swingと関係しないクラスを別に作り、そこのmainメソッドの先頭に書く必要があります。

--- 

# 追記
Macの画面上部メニューバーに`JMenuBar`を表示する場合、Java VMの引数として`-Dapple.laf.useScreenMenuBar=true`を渡した上で、`JFrame`を継承したクラスで`setJMenuBar()`を呼び出しても同等の効果が得られます。
pyenvを使用してCentOS7にPython3をインストールする

作成したてのCentOS7上でPython3が使えるようにするメモ

https://github.com/pyenv/pyenv

# pyenvをクローン

```
$ cd ~
$ git clone https://github.com/pyenv/pyenv.git .pyenv
```

# パスを通す / 初期化の設定

```
$ vim .bash_profile
```

**bash_profile**

```
export PYENV_ROOT=$HOME/.pyenv
export PATH=$PATH:$PYENV_ROOT/bin

if command -v pyenv 1>/dev/null 2>&1; then
  eval "$(pyenv init -)"
fi
```

# 依存パッケージのインストール

```
$ vim yuminstall
```

**yuminstall**

```
sudo yum install \
bzip2 \
bzip2-devel \
gcc \
openssl-devel \
readline-devel \
sqlite \
sqlite-devel \
xz \
xz-devel \
zlib-devel \
```

```
$ chmod 744 yuminstall
$ ./yuminstall
```

# Pythonのインストール

```
$ pyenv install --version
$ pyenv install 3.6.4
$ pyenv global 3.6.4
$ Python --version
```
（メモ）ES6で遅延評価を書きたかった

ふと遅延評価の使い道をjs内で思いついたものの、
遅延評価を関数を使っていちいち`()`を書きたくなかったので、どうにかならないか考えた。

理想としては

```javascript
const hoge = new Lazy(document.getElementById('text').innerText)
```

みたいに書きたかったけど、思いついた限りだと

```javascript
class Lazy {
	constructor (func) {
  	this._innerFunc = func
    this._value = undefined
  }
  
  get value () {
  	if (this._value === undefined) {
    	this._value = this._innerFunc()
    }
    return this._value
  }
}

// 現実
const hoge = new Lazy(() => document.getElementById('text').innerText)
```

みたいになった。具体的な挙動は下記のjsfiddleに載せました。
定義通り`value`を参照すると遅延評価を実行します。

https://jsfiddle.net/TeraBytes/dLrqn8yr/

### おまけ（宣伝）
qiitaだけでなくブログもやっています。
こっちはメモで、向こうはpythonを中心にがっつりと書くって使い方をしています。

http://terabytes.hatenablog.com/
Qiita ハック with Python#2

Pythonを使ってQiitaをいじる実験です。親記事: https://qiita.com/_____/items/d2d52823ea8ef763e3a7

過去の自分の投稿に、いいね、コメント、ストックしてくれた人をお礼にフォローしてみます。「いいね、コメント、ストック」は記事ごとに情報を取得するので、 

1. 過去の全投稿記事のIDを取得 
2. a各記事ごとにいいね等してくれたユーザ名を取得 
3. まだフォローしてなければフォロー 

という手順を踏みます。2.の手順が記事投稿分になるのでAPI呼び出し数は、 `3*投稿記事数` となることや、たくさんいいねされる人気者は 3.で登録するユーザ数分だけAPI呼び出しが走るので、APIの利用上限に引っかからないようにしましょう。いいねされていない投稿に関してはAPI呼び出しをしないという最適化が可能です。


```python
import urllib, urllib.parse, urllib.request
import json

token = 'XXXXXX'
myname = '_____'

opener = urllib.request.build_opener()
opener.addheaders = [('Authorization', 'Bearer {}'.format(token)),]
urllib.request.install_opener(opener)

def get_mypostids():
  url = "https://qiita.com/api/v2/authenticated_user/items?per_page=100"
  data = json.load(urllib.request.urlopen(url))
  return [x['id'] for x in data]

def wholikes(postid):
  url = f"https://qiita.com/api/v2/items/{postid}/likes"
  data = json.load(urllib.request.urlopen(url))
  return [x['user']['id'] for x in data]

def whocomments(postid):
  url = f"https://qiita.com/api/v2/items/{postid}/comments"
  data = json.load(urllib.request.urlopen(url))
  return [x['user']['id'] for x in data]

def whostocks(postid):
  url = f"https://qiita.com/api/v2/items/{postid}/stockers?per_page=100"
  data = json.load(urllib.request.urlopen(url))
  return [x['id'] for x in data]

def my_following():
  _ = "https://qiita.com/api/v2/authenticated_user"
  uid = json.load(urllib.request.urlopen(_))['id']
  ret = []
  for i in range(3):
    url = f"https://qiita.com/api/v2/users/{uid}/followees?page={i+1}&per_page=100"
    data = json.load(urllib.request.urlopen(url))
    ret += [x['id'] for x in data ]
  return ret

def follow(uid):
  url = f"https://qiita.com/api/v2/users/{uid}/following"
  req = urllib.request.Request(url, method='PUT')
  urllib.request.urlopen(req)

if __name__ == '__main__':
  who = []
  for pid in get_mypostids():
    who += wholikes(pid)
    who += whocomments(pid)
    who += whostocks(pid)
  who = list(set(who))

  following = my_following()
  for user in who:
    if user not in following:
      follow(user)
```
clojureでurlエンコードをする

# 使うライブラリ
javaでもやれそうですが、とりあえずこれを使いました。

```clojure
[ring/ring-codec "1.1.0"]
```

# サンプル

```clojure
(ns foo.bar
  (:require [ring.util.codec :as codec]))

;; NG
;; これだと「ほげ」以外もエンコードされてしまう
;; "https%3A%2F%2Fqiita.com%2Fsearch%3Fq%3D%E3%81%BB%E3%81%92"
(codec/url-encode "https://qiita.com/search?q=ほげ")

;; OK
;; "https://qiita.com/search?q=%E3%81%BB%E3%81%92"
(str "https://qiita.com/search?q=" (codec/url-encode "ほげ"))
```
レイアウトxmlでカスタムビューに子ビューを入れる

# 要点
カスタムビューのaddViewをオーバーライドする

# レイアウトxml

## カスタムビューを使うほうのxml
カスタムビューWrapViewをこんな感じで使いたい。

```xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="nittyan.childview.MainActivity"
    >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

    <nittyan.childview.WrapView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        >
        <!-- カスタムビューに子ビュー入れる -->
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="aaa"
            />
    </nittyan.childview.WrapView>

</android.support.constraint.ConstraintLayout>
```

## view_wrap.xml
色とかパディングの値は適当で特別意味はないです。
上記xmlのTextViewをrootの子要素として追加されるようにしたい。

```xml
<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android"
    >

    <android.support.constraint.ConstraintLayout
        android:id="@+id/root"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:background="#00ff00"
        android:paddingTop="20dp"
        >

    </android.support.constraint.ConstraintLayout>

</layout>
```

# WrapView.java
rootの子要素に追加されるようにするにはaddViewをオーバーライドしてbindingが初期化されてないときは親クラスのaddViewを使用して、bindingが初期化されていたらrootの子ビューとして追加するようにする。

```java
package nittyan.childview;

import android.content.Context;
import android.databinding.DataBindingUtil;
import android.support.constraint.ConstraintLayout;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import nittyan.childview.databinding.ViewWrapBinding;


public class WrapView extends ConstraintLayout {

    private ViewWrapBinding binding;

    public WrapView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WrapView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        binding = DataBindingUtil.inflate(LayoutInflater.from(getContext()), R.layout.view_wrap, this, true);
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        if (binding == null) {
            super.addView(child, index, params);
        } else {
            binding.root.addView(child, index, params);
        }
    }

}

```
ChoreonoidのBodyライブラリを使用してVRMLで記述されたロボットモデルのリンク情報を取得する

自分の備忘録としても兼ねてchoreonoid関連に関して書くことにしました.

## 今回行うこと
choreonoidのライブラリ群を使用してVRMLで記述されたロボットモデルからリンク情報(位置・姿勢など)をC++から取得してみます.

## 環境
OS: ubuntu 16.04 LTS  
version: choreonoid 1.6.0  

## choreonoidのインストール
```
$ sudo apt-get update
$ sudo apt-get install choreonoid libcnoid-dev
```
Open-RTMなどを使いたい方は別途インストールしましょう([こちら](http://www.jvrc.org/tutorials/html-ja/)に詳しい話が書いてあります)．

## サンプルコード
ここではChoreonoidに付属されているサンプルモデル「SR1」を使用します．VRMLモデルはgithubにサンプルが上がっているのでそちらから拝借しましょう．apt-getで持ってきていれば/usr/local/choreonoid-1.6/model以下にモデルファイルが存在するのでそれを読み込めれば出来ると思います．ここでは，コードと同じ階層にmodelディレクトリを作成しその中にVRMLファイルがあると仮定します．

```c++:get_link_info.cpp
#include <iostream>
#include <cstring>

#include <cnoid/Body>
#include <cnoid/BodyLoader>

using namespace std;
using namespace cnoid;

int main()
{
	BodyLoader bodyloader;

	std::string model_path("model/SR1.body");
	BodyPtr robot = bodyloader.load(model_path.c_str());

	cout << "dof: " << robot->numJoints() << endl;
	cout << "base link name: " << robot->rootLink()->name() << endl;
	cout << "base link pos: \n" << robot->rootLink()->p() << endl;
	cout << "base link rot: \n" << robot->rootLink()->R() << endl;

	return 0;
}
```

軽くコードの解説をしますが，まずchoreonoid内部のコードではGUI周辺をとりもつ部分と運動学・力学計算といった演算部分をとりもつ部分があります．今回扱うBodyクラスは運動学・力学計算やモデル構造管理などを扱う部分です．  
BodyPtrはBodyクラスを扱うためのスマートポインタであり，このポインタを経由することで指定のVRMLモデルを読みBodyクラスの関数からモデルへのアクセスが出来ます．  

BodyLoaderは先の通りVRMLモデルファイルを読み込み，BodyPtrのインスタンスへ返します．これでVRMLモデル内のリンク位置・姿勢や重心位置などをAPIで取得できるようになります．  
 
以下では，ロボットの自由度，基底リンクの名前，位置，姿勢を取得して表示しています．

```cpp
cout << "dof: " << robot->numJoints() << endl;
cout << "base link name: " << robot->rootLink()->name() << endl;
cout << "base link pos: \n" << robot->rootLink()->p() << endl;
cout << "base link rot: \n" << robot->rootLink()->R() << endl;
```
robot->link(ロボットのリンク名)とすることで指定のリンクの情報を取得できるようになります．

コンパイルするためにchoreonoidのライブラリをリンクしてあげます．

```cmake:CMakeLists.txt
project(get_link_info)

include(CheckIncludeFiles)

set(CMAKE_CXX_FLAGS "-std=c++11")

pkg_check_modules(CHOREONOID REQUIRED choreonoid-body-plugin)
include_directories(${CHOREONOID_INCLUDE_DIRS})
link_directories(${CHOREONOID_LIBRARY_DIRS})

add_executable(get_link_info get_link_info.cpp)

target_link_libraries(get_link_info ${CHOREONOID_LIBRARIES})
```

## まとめ
choreonoidのライブラリを使ってVRMLモデルファイルのリンク情報をC++のAPI経由で取得してみました．次あたりは運動学あたりを…
XEM（NEM）ハーベストの停止をServerlessに自動検知＆通知する

# はじめに
本記事は、XEM(NEM)のデリゲートハーベスティング（委任）をしている際、リモートノード（Super Node）の状態変化によってハーベスティングが停止してしまっていることを検知・通知するためのServerlessアプリケーションを紹介するものです。

Super Nodeによっては、結構、切断が発生してしまうのですが、確認するためにはNano Walletを開いて確認しなければならず、気が付かない間はハーベストが完全に止まってしまいます。ですので、久しぶりに開いて悲しい思いをすることになります・・・。それをナルハヤで気がつけるようにしよう！という試みです。

![WS000093.png](https://qiita-image-store.s3.amazonaws.com/0/179480/c6baf359-731e-beb2-9d2f-86c47c800dec.png)


いわゆるガチホする方で条件を満たす方は、できるだけハーベストの機会を逃したくないですよね！


# 利用の前提
- XEMのデリゲート(委任)ハーベスティングを行っていること
- AWSアカウントがあること

#アーキテクチャ&動作概要
![XemHarvestChecker.png](https://qiita-image-store.s3.amazonaws.com/0/179480/943d29c0-e5f1-9a28-8972-4e6ea1a158ff.png)

1. CloudWatch Eventsのスケジュール（cron）で定期的にLambda Functionをトリガー。
2. デリゲートハーベスティング委任先のリモートノード（Super Node)へリモートアカウントのステータスを確認。有効でない場合、SNS TopicへPublish。 
3. SNSから利用者へE-mailを送信。

# 実装
以下を利用しています。
- デプロイ ⇒ [Serverless Framework](https://serverless.com/)
- ステータス確認 ⇒ [NEM NIS API](https://nemproject.github.io/#requesting-the-account-status)

以下の用にリモートノードへリクエストを送ると
`const URL = 'http://' + IpAddress + ':7890/account/status?address=' + RemoteWalletAddress;`

次のようなJSONオブジェクトがresponseとして返ります。このオブジェクトのstatusがUNLOCKED以外の場合は、ハーベストが有効になっていない状態となり、これをチェックしています。

```json
{
    "cosignatories": [ ],
    "cosignatoryOf": [ ],
    "status": "LOCKED",
    "remoteStatus": "ACTIVE"
}
```

コーディングのレベルが低すぎて恥ずかしいのですが、[GitHub](https://github.com/second113/XemHarvestChecker)に置いています。

#使い方
Serverless.ymlのcustomセクションの項目をセットし、デプロイ（`serverless deploy`）します。

- emailAddress
    - 通知先のメールアドレスを設定
- accountId:
    - AWS Account ID(12桁の数値)
- IpAddress
    - リモートノードのIPアドレス or ホスト名
- RemoteWalletAddress
    - 委任ハーベスト用のリモートアカウント
    - nano Walletで`サービス⇒デリゲートアカウント管理⇒デリゲートアカウントの有効化/無効化`で確認。
 ![remoteAcc.png](https://qiita-image-store.s3.amazonaws.com/0/179480/69aa4ef0-960a-4d40-ab5a-a543a1dd8ad9.png)



リモートノードと接続が切れた場合は、上記をLambdaの環境変数にしていますので、IpAddressを新しいリモートノードへ更新すればOKです。

# おわりに
XEMのAPIは他にもたくさんあり、結構ドキュメントも揃っていますし、拡張も控えていますので、これからどんどん盛り上がりそうですね！いろいろ作ったり、こういった機能もサービス化してみたいところです。

XEMほしい・・・(*ﾉ∀`*)
JavaとPerlで文字列の扱い方の違い

# JavaとPerlの文字列
## Javaでの文字列
基本的に「"」(ダブルクォーテーション)で括ったものが文字列となる。
例 "java"

変数として扱う場合はString型を宣言したのち、代入する。
例 String str = "java1";

## Perlでの文字列
「'」(シングルクォーテーション)、若しくは「"」(ダブルクォーテーション)で
括ったものが文字列となる。
例1 'perl1'
例2 "perl2"

変数として扱う場合、型の概念を意識しなくてそのまま変数に代入出来る。
例3 my $str1 = 'perl1';
例4 my $str2 = 'perl2';

また、Perlではヒアドキュメントと呼ばれる記述方法を用いて、変数に文字列を
代入することも可能。
例5 my $str3 << 'EOD'
abc
defg
hijkl
EOD
(「abcdefghijkl」が変数に格納される)

# JavaとPerlで文字列連結をする。
## Javaでの文字列連結
Javaで文字列の連結をする際は、「+」演算子や「concat」メソッド、
StringBufferクラスやStringBuilderクラスを使用したりします。
例6 String str4 = "java1" + "java2"; ⇒ 変数str4には「java1java2」と
いう文字列が入っている。

## Perlでの文字列比較
Perlで文字列の連結をする際は、「.」記号を使用する。
例7 my $str5 = "perl1"."perl2"; ⇒ 変数$str5には「perl1perl2」と
いう文字列が入っている。

# JavaとPerlで文字列比較をする。
## Javaでの文字列比較
Javaで文字列の比較をする際は、「equals」メソッドを使用する。
例8 "java1".equals("java2"); ⇒ 結果はfalse(偽)

Javaで「==」記号を使用した比較するとコンパイルエラーとなっていまう。

## Perlでの文字列比較
Perlで文字列の比較をする際は、「eq」や「ne」といった文字列を
比較するための演算子を使用する。
例9 "perl1" ne "perl2"; ⇒ 結果はtrue(真)

# JavaとPerlの違い。
## 宣言と代入
Javaは変数の型を決めダブルクォーテーションを使用しないといけないのに対し、

Perlは変数の型の指定は必要なく、ダブルクォーテーションじゃないといけない訳ではない。
何より、Perlにはヒアドキュメントという記述方法を使用して文字列を代入が出来るが
Javaにヒアドキュメントは存在しない。

## 文字列連結
Javaでよく使用される文字列連結は「+」記号が使用される。
Perlでの文字列連結は「.」記号が使用される。

## 文字列比較
Javaは「equals」メソッドを使用される。
Perlは「eq」や「ne」といった文字列比較用の演算子使用される。
※「eq」や「ne」といった演算子はJSPで使用できるEL式の比較演算子と同じ。

最後に
Javaでの開発でWebアプリケーションに携わっていたからPerlの比較演算子には
馴染みがあるけど、「.」記号で文字連結とヒアドキュメントで代入出来るという点は
中々慣れなさそう。
エンジニアの転職を企業側のコストという観点から考える

友人が転職活動をしているので、エンジニアの転職・採用について企業が支払うコストという観点から知っていることを書いておきます。個人が伝聞をベースに書いているのでもっと詳しい人がいらっしゃれば、もっとしっかりした記事か編集リクエストを書いていただければ幸いです。

## ほとんどの転職サービスは採用決定時に年収の3割前後の費用が発生するという点から転職を考える

転職サービスの大半は成功報酬である。シンプルかつ重大な話です。

企業が転職サービスから紹介された人の採用を決めたら、その人に支払う年収の3割前後(具体的な数字はサービスによって違う)を転職サービスに払います。

例外としてよく名前が上がるのがWantedlyで、[月額制](https://www.wantedly.com/about/pricing)です。(左記Wantedlyの価格ページの「よくある質問」では、成功報酬ではないことを示す質問が2回繰り返されています)

## 転職サービスが成功報酬だから起こること

* 転職サービス経由より直接応募の方が採用されやすい
* 転職サービス経由の応募者に対して、直接応募に比べて年収を安くする動機が通常より強い
* 長く務めてもらう方が企業にとって特
* 転職サービス経由の場合ジョブホッパーは嫌われる
* 企業としてはリファラル採用や直接応募を増やしたい
* 載せるだけならタダor安いので、人が欲しい企業はそこら中の媒体に求人を出す
* 採用力がある企業は転職サービスに求人を出さない

### 上記を踏まえて成功報酬型転職サービスについて

そういうわけで日本で転職活動を行う場合、転職サービスを経由しない方が特なことが多いです。新卒の初任給レベルで100万円くらい企業側の費用が変わるから当然ですね。

転職サイトで求人が出されていることを確認してから直接応募することが規約上許されているかはよく確認しましょう。エンドユーザー側にその制限を課している媒体は少ないでしょう。ただし、企業が転職サービス経由の応募を受け付けてから自社サイトに誘導することは、人材業界全体を敵に回すことなので、ほぼありません。

### ジョブホッパーについて

仕事を短期間で転々とする人が嫌われやすいのは、価値観の問題以上に転職市場のシステムと正社員をやめさせづらいという事実によるところが大きいです。

* 先述の通り転職サービスは採用のたびに費用がかかります。社員が辞めると次の採用時に費用として年収の1/3がかかる可能性が高いため、すぐ辞める人は嫌われがちです。
* 日本では従業員が辞める権利はがっつり保証されている反面、企業がやめさせる権利は制限されるため、正社員の採用には慎重にならざるを得ないようです。

## まとめ

* 転職サービスに注意
CircleCI2.0ハンズオン！目次

# [はじめてのCircleCI2.0](https://qiita.com/sawadashota/items/09b37b303e63f3b897a9)

> CircleCI2.0をこれからはじめて使おうという方向けのチュートリアルです。
>
> この記事では、とにかく簡単にCircleCIを動かしてみます。

https://qiita.com/sawadashota/items/09b37b303e63f3b897a9

# [CircleCI2.0でアプリケーションをビルドする](https://qiita.com/sawadashota/items/d1382b1e1b9a5595ab66)

> [はじめてのCircleCI2.0](https://qiita.com/sawadashota/items/09b37b303e63f3b897a9)の続編です。
>
> 今回はCircleCIで[Nuxt](https://nuxtjs.org/)のビルドをやってみます。

https://qiita.com/sawadashota/items/d1382b1e1b9a5595ab66

# [CircleCI2.0のWorkflowを試してみる](https://qiita.com/sawadashota/items/ba89382d563bc90bb5cd)

> CircleCI2.0の特徴のひとつであるWorkflowを触ってみます。

https://qiita.com/sawadashota/items/ba89382d563bc90bb5cd

# [CircleCI2.0でDockerをビルドしてDocker HubにPushするまで](https://qiita.com/sawadashota/items/1ce611e834c6dc2b3c05)

> 今回はCircleCI2.0でDockerをビルドしてDocker HubにPushするまでやってみます。

https://qiita.com/sawadashota/items/1ce611e834c6dc2b3c05

# [CircleCI2.0でDatabaseを使ったテストをする](https://qiita.com/sawadashota/items/2fbed5ef4f1341624a04)

> Circle2.0ではDatabaseのDocker imageを使ってテストをすることが可能です。
>
> MySQLを使ったテストをやってみます。

https://qiita.com/sawadashota/items/2fbed5ef4f1341624a04
Python3 + subprocess > crontabの設定を読取り、実行するスクリプト > string not in ... | string.lower() | subprocess.getoutput()

```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
```

### Crontab

```bash
$crontab -u yasokada -l
...
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
35 23 * * * /home/yasokada/BACKUP_TOOL_180128/yasokada_back_180128_exec
```

### 処理内容

- crontab設定のコマンドを読取る
    - `# m h  dom mon dow   command`**の次の行だけ**読取る
- 読取ったコマンドを実行する

### code v0.1

```run_crontab_command_180128.py
# from subprocess import getoutput
import subprocess as sb
import sys

'''
v0.1 Jan. 28, 2018
  - add [SHELL]
  - add main()
  - add find_command()
  - add [CMD]
  - add [USER]
'''

# tested on Python 3.5.2
# tested on Ubuntu 16.04.3 LTS
# coding rule:PEP8

USER = "yasokada"
CMD = "crontab -u %s -l" % USER
SHELL = "bash -x"


def find_command():
    lists = sb.getoutput(CMD).split('\n')
    hasRead_m_h_line = False
    for elem in lists:
        if "m h  dom" in elem:
            hasRead_m_h_line = True
            continue
        # print(elem)
        if hasRead_m_h_line:
            return elem.split(' ')[-1]
    return None


def main():
    # 1. get command written in crontab
    cron_cmd = find_command()
    if cron_cmd is None:
        sys.exit(-1)

    # 2. confirm to execute command
    print('\ncommand is')
    print(cron_cmd)
    #
    wrk = input('Run[y/N]?')
    if len(wrk) == 0 or 'y' not in wrk.lower():
        print('Canceled')
        return

    # 3. execute command with bash
    run_cmd = '%s %s' % (SHELL, cron_cmd)
    sb.call(run_cmd.split())


if __name__ == '__main__':
    main()

```

```txt:run
$ python3 run_crontab_command_180128.py 
command is
/home/yasokada/BACKUP_TOOL_180128/yasokada_back_180128_exec
Run[y/N]?
...
```

'y'か'Y'を入力するとコマンドが実行される。

### 備考

- 一つのコマンドしか実行しない
- こちらのcodeを実行するより、crontab -l 実行してコピペしたコマンドを実行するほうが早い
- Pythonの勉強のつもりで実装してみた

### 学んだ事項
(復習分も含む)

- not in ...
- string.lower()
- sb.getoutput()
- string not in ...
    - NOT: not string in ...
        - [`E713 test for membership should be 'not in'`](https://stackoverflow.com/questions/24671925/pep8-e713-test-for-membership-should-be-not-in)

### リンク
(追記 2018/01/29)

https://docs.python.jp/3/library/subprocess.html#subprocess.getoutput
https://docs.python.jp/3/library/subprocess.html
https://docs.python.jp/3/library/string.html
個人的お役立ち/参考URL集

# Python

* 公式チュートリアル -> [Pythonチュートリアル- Python 2.7.14 ドキュメント](https://docs.python.jp/2.7/tutorial/index.html)
* 例外について -> [Python基礎講座(11例外) -Qiita](https://qiita.com/Usek/items/53527feba2adcb386aa8)
* ヒアドキュメント -> [Pythonのヒアドキュメント](https://qiita.com/ykhirao/items/c7cba73a3a563be5eac6)
* doctoring -> [pythonのコメントの書き方（ハズレ日記）](http://catbot.net/blog/2011/09/python_docstring.html)

# vim

* vimの基本機能類 -> [人類はもっとvim本来の機能を使うべきだった](http://maxmellon.hateblo.jp/entry/2015/12/11/133136)
* 画面分割 &タブページ -> [Vimの便利な画面分割＆タブページと、それを更に便利にする方法](https://qiita.com/tekkoc/items/98adcadfa4bdc8b5a6ca)
* 


#bash

* [vim色に染まれ.機能紹介のついでにbashをvi仕様に.](https://qiita.com/Pseudonym/items/2cb442ff257a2f9f9d70)
* [bash vi最強ですね、わかります。](http://d.hatena.ne.jp/yamazakiccs/touch/20081207/1216817670)
* [bashをviモードで使うススメ。](http://blog.livedoor.jp/okashi1/archives/51816924.html)
* 

# troff

* [troffメモ/カビパン男と私](http://www.kabipan.com/computer/troff/)
* (とりあえず突っ込んでおく) [Man page of Groff - JM Project](https://linuxjm.osdn.jp/html/GNU_groff/man7/groff.7.html)


# manページ作成

* markdownから自動生成する -> [RubyのコマンドラインツールのMan Pageを作る | SOTA](https://deeeet.com/writing/2014/03/17/gem-man/)
* そもそもmanコマンドについての解説含 -> [6 わからなかったらコンピュータに聞こう -manコマンド](http://cai.cs.shinshu-u.ac.jp/sugsi/Lecture/HowToUnix/6-1.html)
Google Apps Script でスプレッドシートから Rails の Seed（seed-fu）を生成する

こんなスプレッドシートがあるとして、

<img width="547" alt="スクリーンショット 2018-01-28 12.00.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/1668/b90dd9ff-398f-0772-be69-d18c2b5df7e6.png">

「スクリプトエディタ」から、

<img width="273" alt="スクリーンショット 2018-01-28 12.04.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/1668/864a584e-e07c-7d60-5d65-3ac9bf4741f1.png">

以下のような関数を作って実行する。

```
function companySeed () {
  const COL_INDEX_COMPANY_ID = 0;
  const COL_INDEX_COMPANY_NAME = 1;
  
  var sheet = SpreadsheetApp.getActiveSheet();
  var lastRowNumber = sheet.getLastRow();
  var lastColNumber = sheet.getLastColumn();
  
  // 見出し行は除く
  var range = sheet.getRange(2, 1, lastRowNumber - 1, lastColNumber);
  var values = range.getValues();
  
  var seeds = values.map(function(row) {
    var output = "";
    output += "Company.seed do |s|\n"
    output += "  s.id = " + row[COL_INDEX_COMPANY_ID] + "\n";
    output += "  s.name = '" + row[COL_INDEX_COMPANY_NAME] + "'\n";
    output += "end\n";
    return output;
  });
  
  Logger.log(seeds.join("\n"));;
}
```

実行後、ログを表示すると、

<img width="313" alt="スクリーンショット 2018-01-28 12.06.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/1668/41126966-6d40-670e-faf8-60fe23558d08.png">

できあがり。

<img width="715" alt="スクリーンショット 2018-01-28 12.11.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/1668/cccbd3b2-5757-9bdb-a2dc-1461c22f80dc.png">

最終的にログからコピペなのがかっこ悪いので、もうちょいなんとかしたいが…。
フェイスブックの物体検知アルゴリズム「Detectron」に関するAzure関連

# フェイスブックの物体検知アルゴリズムをAzureで動かすときの参考URLリンク

フェイスブックが、画像認識で画像の中の物体を検知する基盤の「Detectron」をOSSにて公開したので、Azureで動かすための Caffe2 環境についての関連リンク

## Facebook open sources Detectron / Facebook Research
https://research.fb.com/facebook-open-sources-detectron/

## Facebook Open-sources ‘Detectron’ Computer Vision Algorithm for AR Research / Road to VR
https://www.roadtovr.com/facebook-open-sources-detectron-computer-vision-algorithm-for-ar-research/

## Azure 仮想マシンについて
https://azure.microsoft.com/ja-jp/pricing/details/virtual-machines/linux/
ND、NC、NCv2など、Nが付いて入るものを参照

### Data Science VM (Caffe2が含まれるVirtual Machineイメージと起動のテンプレ)
https://azuremarketplace.microsoft.com/en-us/marketplace/apps/microsoft-ads.linux-data-science-vm-ubuntu?tab=Overview

### Caffe2 Template
https://azuremarketplace.microsoft.com/en-us/marketplace/apps/jetware-srl.caffe2?tab=Overview

### 自動シャットダウン
GPUを搭載したインスタンスは費用が大きいので、自動シャットダウンを設定することを推奨
https://azure.microsoft.com/ja-jp/blog/announcing-auto-shutdown-for-vms-using-azure-resource-manager/

## Azure BatchAI ＋ Caffe2レシピ
https://github.com/Azure/BatchAI/tree/master/recipes/Caffe2

## Azure上の類似のサービス

この機能は、APIで提供されます。
画像をクラウドに送信すると、画像内にあるビジュアル コンテンツに関する情報が、かえってきます。
画像に対してタグ付け、キャプション説明ができます。
画像が、成人向け/わいせつな描写かどうかの判定も可能。
画像の種類や写真内の配色もしてくれます。


###Computer Vision API

https://azure.microsoft.com/ja-jp/services/cognitive-services/computer-vision/
Chainerの活性化関数を可視化

[Chainerの活性化関数](http://docs.chainer.org/en/stable/reference/functions.html)を可視化する。

# 動作環境
- Ubuntu 16.04
- Python 3.5.2
- Chainer 3.2
- numpy 1.13.3
- opencv-python 3.2

# ソースコード

全体は[ここ（Github）](https://github.com/ka10ryu1/activation_func.git)。main部は以下で、`actfun`に普段使うor使いそうな活性化関数を設定し、それを順次画像化していく。`args.out_path`は出力先のフォルダ名。

```python3
import matplotlib.pyplot as plt
import chainer.functions as F

def main(args):
    actfun = [
        F.relu, F.elu, F.clipped_relu, F.leaky_relu, F.selu,
        F.sigmoid, F.hard_sigmoid, F.tanh, F.softplus,
    ]
    x = np.arange(-10, 10, 0.2)

    for af in actfun:
        file_name = getFilePath(args.out_path, af.__name__, '.png')
        print(file_name)
        y = [i.data for i in af(x)]
        f = plt.figure()
        a = f.add_subplot(111)
        a.plot(x, np.array(y))
        plt.savefig(file_name, dpi=200)
```

# 実行結果

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/227399/2790c5a3-d5a2-954f-6204-e2aa0518efb6.png)

以上。
webアプリケーションを個人開発する上で役立ったサービス、ツールまとめ

# この記事は個人で開発するにあたって助かったなあと思ったサービスやツールをまとめる記事。逆にこれいいよというのがあったらコメントして欲しい。僕の環境が下記なのでこの環境で使えるものがメイン

* mac
* heroku
* postgres
* rails
* ruby
* vue.js

# DB(postgres)の確認

herokuのDBを確認するにあたって使用したツール。もっと編集を直にしやすいツールを知っている人がいたら教えて欲しい。

## postico

https://eggerapps.at/postico/

DBの中身を少し修正したい時に役立っている。多分macでしか使えないはず。

## DB browser for sqlite

http://sqlitebrowser.org/

.sqlite3ファイルを読み込んで使っている。posticoでfileを読み込む方法が分からないので使っているが一本化したい。。。

# サーバー

サーバーは基本的には最初はherokuで試している。AWSは料金が怖い。

## heroku

## AWS

# editor

## atom
NIS/NFSが設定されているサーバー間をカレントディレクトリを維持して行き来したい

# やりたいこと

LAN内に複数台のLinuxサーバーがあって、それらがNIS/NFSでユーザー・ディスク（/home とか）を共有しています。
例えば各サーバーの計算リソースが取り合いになっていて、あるサーバーが使われているから別のサーバーで作業しようとなると、（少なくとも私は）こういうことがしたくなるのですが…

```bash:terminal
$ cd ~/foo/bar
$ pwd
/home/user/foo/bar
$ top
# 誰か計算回してるみたい。別のサーバーで作業しよう
$ ssh serverA
user@serverA's password:
Last login: Mon Jan  1 12:34:56 2018 from 192.168.1.1
$ ./do_something.sh
-bash: ./do_something.sh: そのようなファイルやディレクトリはありません
# さっきの場所が自動的にカレントディレクトリになったらいいのにorz
$ pwd
/home/user
```

まあ、そうなりますよね。
些細なことではありますが、回数が重なると精神的によろしくないので、今のうちに手を打ちましょう。
（ちなみに、ログイン時刻とかユーザー名とかサーバー名とかはすべて架空のものです）

# ログイン後にコマンドを実行させたい

ログイン後に自動的に``cd``コマンドを実行してさっきの場所に飛べないかなー、というのは、（どうやって実現するかは別にして）割とすぐに思いつく方針だと思います。
では、どうすればログイン後にコマンドを実行させられるのでしょうか？

## Expect

シェルで「何かが出力されたら自動的に何かを入力する」ということができるツールです。
>Expect is a tool for automating interactive applications such as telnet, ftp, passwd, fsck, rlogin, tip, etc. Expect really makes this stuff trivial. Expect is also useful for testing these same applications. And by adding Tk, you can also wrap interactive applications in X11 GUIs.
(http://expect.sourceforge.net/)


- パスワードプロンプトに対応して自動的にパスワードを入力するとか
- yes/noを聞かれたら自動的にyesと答えるとか

そして用事が済んだ後は、ユーザーが普通に作業を続けられるように設定できます。
今回はこういうのを作ってみましょう。

- パスワードを聞かれたら自動的にパスワードを入力
- ログインに成功したら自動的に ``cd <ログイン前のカレントディレクトリ>`` を入力

本当は、パスワードを入力するときだけユーザーに制御を返してもらえるといいですが、その後にもう一度制御を預ける方法がよくわからなかった（できないかも？）なので、今回はパスワードも入力させるようにします。

Expectは正直今回の用途以外に使ったことがないので、詳しい解説とかはできません。
いろいろ試行錯誤してできた方法を載せてみます。
5行目の ``send "password\n"`` の部分に、実際のパスワードを入れます。正直あまりベタ書きしたくないので、パスフレーズなしの公開鍵を設定するとかのほうがいいかも。

```bash:sshwd
#!/bin/bash
expect -c '
        spawn ssh serverA
        expect "s password:"
        send "password\n"
        expect "\\\$"
        send "cd '${PWD}'\n"
        interact
'
```

- ``s password:`` という文字列が見えたら ``password\n`` を入力する
- その後 ``$`` という文字列が見えたら ``cd <ログイン前のカレントディレクトリ>\n`` を入力する

ということをやってくれます。
あとは``sshwd``に実行権限を付けて、置いた場所にパスを通しておくと、こんな感じで使えるようになります。

```bash:terminal
$ cd ~/foo/bar
$ pwd
/home/user/foo/bar
$ top
# 誰か計算回してるみたい。別のサーバーで作業しよう
$ sshwd
spawn ssh serverA
user@serverA's password: # ここは自分で入力しなくても勝手に進む
Last login: Mon Jan  1 12:34:56 2018 from 192.168.1.1
$ cd /home/user/foo/bar # これも勝手に表示されて勝手に進む
# ここから自分で操作できる
$ pwd
/home/user/foo/bar
```

地味にこういうのが欲しかった！

# ログイン先を外部から与えたい

さて、今回はログイン先のサーバーが決め打ちになっていますが、普通は多数のサーバーが存在していて、引数で指定したサーバーに入りたい、ということになるはずです。

```bash:sshwd2
#!/bin/bash
set -u # 引数が足りなかったらエラーにする
SERVER=$1
expect -c '
        spawn ssh '${SERVER}'
        expect "s password:"
        send "password\n"
        expect "\\\$"
        send "cd '${PWD}'\n"
        interact
'
```

シェルスクリプトで引数を取ってexpectの引数に渡すように変えただけです。
使い方は以下。

```bash:terminal
$ cd ~/foo/bar
$ pwd
/home/user/foo/bar
$ top
# 誰か計算回してるみたい。別のサーバーで作業しよう
$ sshwd2 serverA
spawn ssh serverA
user@serverA's password: # ここは自分で入力しなくても勝手に進む
Last login: Mon Jan  1 12:34:56 2018 from 192.168.1.1
$ cd /home/user/foo/bar # これも勝手に表示されて勝手に進む
# ここから自分で操作できる
$ pwd
/home/user/foo/bar
```

# 参考サイト
- https://qiita.com/ine1127/items/cd6bc91174635016db9b
- http://zacodesign.net/blog/?p=2077
多重継承についてのメモ

# そもそも多重継承とは？
## 継承とは？
まず、前提として継承には以下の目的があります。（参考：http://equj65.net/tech/java8mixin/）
1. 実装の継承（使い回し）
2. 仕様の継承（継承したクラスが、あるメソッドを持つことを明示的に指定する。つまりクライアント側から見ると、あるメソッドが必ず実装されていることが確約されている状態）

実際の継承パターンとしては、以下の二パターンです。
1. 仕様と実装を両方継承する
2. 仕様のみ継承する。


```仕様と実装の継承.kt
open class Person {
    fun greet() { System.out.print("こんにちは") }
}

class Japanese: Person{ }

fun main(args: Array<String>) {
    val taro = Japanese()
    taro.greet()
}
```

```仕様のみ継承.kt
interface Person {
    fun greet()
}

class Japanese: Person{ 
    override fun greet() { System.out.print("こんにちは") }
}

fun main(args: Array<String>) {
    val taro = Japanese()
    taro.greet()
}
```

上記の通り、仕様のみを継承する場合はinterfaceを継承します。
interfaceは実装を含むことができないためです。（_Java8で実装を持てるようになったようですが、ここでは触れません_）

## 多重継承とは？
文字通り複数のクラスから継承することを指します。

# What? 問題は？ 
菱型問題（Diamond problem）と呼ばれる現象がある。
以下のコードを見てください。

```diamondProblem（実装の多重継承ができるとしたら）.kt
interface Person {
    fun greet()
}

open class Japanese: Person {
    override fun greet() { System.out.print("こんにちは") }
}

class American: Person {
    override fun greet() { System.out.print("Hello") }
}

// もしこのような多重継承が可能だとしたら
class Half: Japanese(), American { }

fun main(args: Array<String>) {
    val karl = Half()
    karl.greet()
}
```

果たしてkarlはどんな挨拶をするのでしょうか？
これは実際にはコンパイルエラーになります。Javaでは複数の親クラスを持つことはできないためです。

なぜ複数の親クラスを持つことができないのでしょうか。
上記の例のように継承した親クラス（Japanese, American）が同一名称のメソッドを実装していた場合を考えます。
継承するクラス（Half）からgreetメソッドを呼び出したときにどちらのメソッドが呼ばれるのかをコンパイラは解決することができません。

このため、コンパイラ的な都合でJavaでは複数のクラス（!= interface）を継承することはできません。

# 多重継承を実現するためには
実装クラスを継承する代わりにinterfaceを継承します。
ただし、この場合は継承する先のクラスに実装を書かなければなりません。
そのため、実装の使い回しは行えず、仕様の継承のみが可能になります。

# 考察
仕様の継承は、Rubyで言う所のDuck Typingに通じるものがありそう。ただし、以下の点で仕様の継承の方が優秀だと思う。
1. クラスの作成者に実装を強制できる
2. クライアント側は実装があることが前提であるため、余計なエラーハンドリングなどを考える必要がない
3. 型チェックも行えるので、より確実な開発が行える

実装の継承は、Rubyで言う所のMix-inに通じるものがありそう。ただし、Mix-inの方が継承構造が複雑にならない点でより気軽に使える。

# 参考
http://equj65.net/tech/java8mixin/
https://docs.oracle.com/javase/tutorial/java/IandI/multipleinheritance.html
https://en.wikipedia.org/wiki/Multiple_inheritance
https://en.wikipedia.org/wiki/Mixin
zaif api (python)でcancel_orderを働かせる

# 注文取り消し(cancel_order)が機能しない．
zaifapiを1.6.2にアップデートしてから発見した．
"order not found"の例外をドカドカ飛ばしてくる．

```python3:cancelOrder.py
# -*- coding: utf-8 -*-
from zaifapi import ZaifTradeApi
key = '自分のkey'
secret = '自分のsecret'
order_id = 100  # 注文ID
zaifp = ZaifTradeApi(key, secret)
zaifp.cancel_order(order_id)  # 注文取り消し
```

BCH/BTCとか，XEM/BTCとかで起こる．

[公式ドキュメント](https://techbureau-api-document.readthedocs.io/ja/latest/trade/2_individual/8_cancel_order.html)はなんとv1.1.1までしか見つからない．v1.6.2まで変化はないということなのか・・・？

# 解法は「通貨ペアまで指定」

```python3
zaifp.cancel_order(order_id, 'bch_btc')  # 注文取り消し
```

たぶん，指定した通貨ペアの中で注文IDを探しているのだろう．

公式ドキュメントでは「必須でない」とされていたが，
きっとそれはBTC/JPYの話なのだろう．わかりにくい．

少なくともBCH/BTCとかの通貨ペアはv1.6.2において指定必須だった．

active_ordersみたいにデフォルトで全部探してほしい

# 文句（ポエム）
関係ないがactive_ordersで貰える注文IDはなぜかstr型．

おそらく辞書の長所を活かしているんだろうが，
cancel_orderではintをよこせと怒られるので複雑な気分．
rsyncとcronによるバックアップ | バックアップは大切

```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
```

## バックアップ

### rsync

rsyncを使う。

参考: [rsync --delete で泣かないために](https://qiita.com/QUANON/items/2953c52df7f65f2ecee5)

https://explainshell.com/explain?cmd=rsync+-av+--delete


以下のbashスクリプトを作成しておきます。
（Note: 下記例は/home/7of9以下のすべてのディレクトリを対象としていますが、バックアップの重要度にあわせて適宜固有のサブディレクトリをバックアップするなど処理を分ける方がいいかもしれません。)

```bash:/home/7of9/BACKUP_TOOL_180128/backup_180128_exec
#!/usr/bin/env bash

rsync -av --delete  /home/7of9/ /backupHDD/auto_backup_180128
```

そのbashスクリプトに実行権限を付けておきます。

```bash
$ chmod +x backup_180128_exec
```

### crontab設定

23時45分に実行するようにする。
(Note: 作業してない時間帯です。数値計算処理は実行中ですが）。

参考: [cronの設定方法](https://qiita.com/hikouki/items/e744b3a4d356d2af12cf)

```bash
$ crontab -u 7of9 -e
...
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
45 23 * * * /home/7of9/BACKUP_TOOL_180128/backup_180128_exec
```

## バックアップは大切

GitHubにもBitbucketにもQiitaにもesa.ioにもバックアップしてない野良コードが見つかった。
そのコードが消えると手戻りが半端ない。

関連データもあるため、別ディスクにコピーすることにした。

バックアップできるものは適宜バックアップしましょう。

久しぶりに起動した[Gigabeat MEV-30K](https://support.toshiba.com/support/modelHome?freeText=2288418)(HDDで200番組録画したやつ）がエラーを吐いている。

> Portble Media CenterをPCに接続してください。
> Connect the Portable Media Center to a PC.

100歳の元料亭のおじいさんがおばあさんのために作る甘い玉子焼きの話（百歳バンザイ! ）や、町工場ドリルガールズなどのドキュメントはもう見れない。。。
【はじめてのプログラミング】Ruby on Rails_ データベース構築。あとrailsとrakeの違い。


##Ruby on Railsにおけるデータベース構築

Ruby on RailsでWebアプリケーションを作成していると、MVCモデルに気を取られてデータベースのことを忘れてしまうこともしばしば。
ただ、非常にかんたんにデーターベースを作成、してまた操作もSQLではなくRubyでできます。

##(1)マイグレーションファイル(設計図)の作成
マイグレーションファイルとは、データベースのもととなるの設計図のようなものです。
このマイグレーションファイルを実行すると、それに沿ったデータベースができあがる。

ex) ユーザが投稿する内容を保管しておくためのデータベースを作る

まずコンソールで以下のコマンドを実行する

```
rails g model Post content:text
#マイグレーションファイルを作成する
```

ここで注意なのが、postsテーブルを作成する場合にはPostと単数形にすることです。
contentはカラム名(Excelでいうところの列の名前)で、textはデータの型(text以外にもstringやintegerなど)

先程のコマンドを実行することで、db/migrateフォルダの下にマイグレーションファイルが作成されます。

##(2)マイグレーションファイル(設計図)を使ってデータベース(目的物)に変更を加える

コンソールで以下のコマンドを実行する

```
rails db:migrate
```

ここでよくあるミスとして、(1)でマイグレーションファイルは作ったけど、その後データベースに反映させていないというケース。
その場合マイグレーションエラーが発生してしまうので、上記のコマンドでマイグレーションファイルを反省させましょう。

##(参考)rails と rakeの違い
【参考リンク】
[binって何？railsとrakeって何？？（後編）](http://song-of-life.hatenablog.com/entry/2017/04/28/111445#railsとrakeの違い)

マイグレーションファイルを適用させるときのコマンドとして、参考先によっては以下の２つの方法が存在しています。
しかし結論から言うと、今の段階ではどちらでもOK。できるならrailsのほうがいいかも。という状況です。

```
#(A)rails を使う
rails db:migrate

#(B)rake を使う
rake db:migrate
```

railsは
>アプリケーションに最低限必要なフォルダやファイルを自動的に作成

であり

rakeは
>Rakeとは Rubyで記述されたビルドツールです。

です。

できることはほとんど同じです。
ただしRuby5からはrake→railsに統一されたため、今後はrailsをメインとして使っていく方向のほうがいいかと思います。
(もしrakeつかえ！みたいなご指摘あればいただけると助かります。)
sprintfのフォーマット文字列の変数にマッチする正規表現

sprintfのformatの変換指定の数をカウントしなければならなくなったので、正規表現書いたメモです。

とりあえず、phpのsprintfのドキュメントに載ってる例にはすべてマッチします。
https://regex101.com/r/EM27Au/1

# 結論


```
//簡易(位置指定子と型s,dのみ)
(?:^|[^%])(?:%%)*(%(?:\d+\$)?[sd])
```



```
//完全版(たぶん)
(?:^|[^%])(?:%%)*(%(?:\d+\$)?(?:\+)?(?:0|'.)?(?:\-)?(?:\d+)?(?:\.\d+)?[bcdeEufFgGosxX])
```



```php
//php上で使うときは/と$をエスケープ

//簡易(位置指定子と型s,dのみ)
$reg1 = "/(?:^|[^%])(?:%%)*(%(?:\\d+\\\$)?[sd])/u";

//完全版(たぶん)
$reg2 = "/(?:^|[^%])(?:%%)*(%(?:\\d+\\\$)?(?:\\+)?(?:0|'.)?(?:\\-)?(?:\\d+)?(?:\\.\\d+)?[bcdeEufFgGosxX])/u";

```

# 正規表現を組み立てた手順

正規表現そのものだけだと合ってるんだか自分でも判別つきがたく、
あとで修正入れようにもよくわからなくなるので、組み立てた手順を書きます。
間違いなどあれば突っ込んでいただければ喜びます。

## 1. `%s` にマッチさせる
まず単純に`%s`にマッチすることを目指します。
正規表現を使わなくても大丈夫に見えますが、エスケープに注意しなければいけません。
`"%"+"s"`ではなく`エスケープされてない% + "s"`です。


エスケープされてない: `%s` 、　`%%%s` 、　`%%%%%s`
すべてエスケープ済み: `%%s` 、 `%%%%s`

こう分けてみるとエスケープされてない`%`というのは、奇数個連続した`%`の末尾と言い換えることができそうです。

奇数=偶数+1　であり、
偶数個の`%`は正規表現で、`(?:%%)*`と書くことが出来そうです。
>`(?:)`はグループ化の意味です。
>`%%`のグループが0個以上ある = 偶数個の`%`

しかし実行してみると`(?:%%)*`は奇数個の`%`にもマッチしてしまいます。
なぜなら、`%%%`などの最後の二文字にマッチしてしまうから。
`(?:%%)*`には「 文の始めである or `%`以外の文字から連続する」という条件が必要なようです。

「 文の始め or `%`以外の文字 」　は`(?:^|[^%])` で表現できます。
>`^` => 行の始め
>`|` => or
>`[^%]` => `%`以外の文字

合わせると、エスケープされていない`%`は、`(?:^|[^%])(?:%%)*%`　ということになります。
よって、`%s`にマッチする正規表現 は

```
(?:^|[^%])(?:%%)*(%s)
```

## 2. `%d`にもマッチさせる
`%s`だけでなく`%d`も必要です。これは簡単で、`s`を`[sd]`に変えるだけです。

`(?:^|[^%])(?:%%)*(%[sd])`

## 3. 位置指定子に対応させる。
sprintfに複数の変換指定を使うとき、`%1$s``%2$s`のように位置指定子を使って順序の指定をします。

位置指定子は`数値+"$"`ですので、`(?:\d+\$)`と表現できます。

位置指定子は必ず`%`の直後と決まっているので、次のようになります。

`(?:^|[^%])(?:%%)*(%(?:\d+\$)[sd])`

ただし`%s`など位置指定子を使わない場合も対応しなければなりません。

よって最終的には、

```
(?:^|[^%])(?:%%)*(%(?:\d+\$)?[sd])
```

>`[sd]`の直前に`?`が増えています。
>`(?:パターン)?`のように末尾に`?`を付けると在っても無くてもよいという意味になります。

## 3.すべての変換指定子に対応する
sprintfのformatは次のようになっています。
`%``位置指定子``符号指定子``padding指定子``align指定子``幅指定子``精度指定子``型指定子`
この順序は固定なので、それぞれの指定子のパターンを前述の位置指定子の場合と同じように並べていけば良さそうです。

| 名称 | 正規表現 |内容|
|:-:|:-:|:-:|
|位置指定子|\d+\$|数値(ゼロパディング可)と$| 
|符号指定子|\\+| + |
|padding指定子|0&#124;'.]| 0 または　`と任意の1文字|
|align指定子|\\-| - |   
|幅指定子|\d+|数値(ゼロパディング可)|
|精度指定子|\\.\d+ |ピリオドと数値(ゼロパディング可)|   
|型指定子|[bcdeEufFgGosxX]|特定のアルファベット|

一覧にしてみると思ったよりシンプルですね。
これを合わせてみたら完成です。

````
(?:^|[^%])(?:%%)*(%(?:\d+\$)?(?:\+)?(?:0|'.)?(?:\-)?(?:\d+)?(?:\.\d+)?[bcdeEufFgGosxX])
```

#疑問点
[PHPマニュアル/sprintf](http://php.net/manual/ja/function.sprintf.php)のページに次のような説明があります。

>オプションの精度指定子 (ピリオド (.) に続けてオプションで桁数指定文字列を書いたもの)。 これは、浮動小数点数に対して数字を何桁まで表示するかを指定します。 文字列に対して使用した場合は、これは切り捨て位置として働きます。 この文字数を超える文字を切り捨てられます。 さらに、数値の桁埋めに使う文字を指定することもできます。桁埋め文字は、ピリオドと数値の間に指定します。

ピリオドの後に桁埋め文字が書けるというので、試してみたのですが、結果は次のようなものでした。

```php
echo sprintf("[%'.9d]" , 123); // → [......123]
echo sprintf("[%'.09d]", 123); // → [000000123]
echo sprintf("[%'.#9d]", 123); // → [9d]
```

他の言語のprintfのリファレンス見てもピリオドの後に桁埋め文字というのは見当たらないので、マニュアルの間違いなんじゃないかと思うんですが……。
Botkit+Glitchで作るSlack用bot（2018年1月版）

# はじめに
BotkitでSlackのBotを作る手順が、古いAPI仕様のモノしか出てこないので、
備忘も兼ねてまとめておく。

基本的には以下の日本語版（のつもり）
https://github.com/howdyai/botkit/blob/master/docs/provisioning/slack-events-api.md

# Slack Appを新規作成
1. https://api.slack.com/apps
にアクセスして、左上の「新しいアプリを作成する」を押す。
2. アプリ名は任意。　ワークスペースはbotを追加したいslackワークスペースを選ぶ。
3. アプリを作ると アプリの認証情報 として、クライアントIDとクライアントシークレットが出てくるので、控えておく。

# botkitで新しいbotを作る

1. https://studio.botkit.ai/ にログイン
2. 必要事項を入力するとホスティング先を選ぶ画面が出るので、Glitchを選ぶ。  
（この過程で、先に控えた クライアントIDとクライアントシークレットが必要になる）
3. 別窓でGlicthのサイトに飛ばされるので、アプリが立ち上がるまで待つ　（書いてある説明を読んでいるうちに終わる）
4. 元の窓に戻ると、 Glicthでデプロイされた旨が表示されている
5. 次に進むと　oauthのリダイレクトURLとイベントフック用のURLが表示される

# slack側を設定
1. slackの画面に戻り、 左のメニューから「Oauth & 権限」を選ぶ
2. 少し下の方に　リダイレクトURL　という欄があるので、そこに先ほど表示されたURLを入れる  
（　URLは https://xxxxxxxx.glitch.me/oauth という形式。 xxxxxはglichでデプロイされたアプリの名前 ）
3. 左のメニューから　ボットユーザ　を選び、　ユーザを追加する。  
私のボットを常にオンラインで表示する  も　オンにしておく
4. 左のメニューから　インタラクティブコンポーネント　を選ぶ
5. リクエストURLの欄にイベントフック用のURLを入れる  
( URL は https://xxxxxxxx.glitch.me/slack/receive という形式 ）
6. 左のメニューから イベントの購読 を選ぶ
7. リクエストURLを入れる　  
( URL は https://xxxxxxxx.glitch.me/slack/receive という形式 ）
8. 少し下に行って「ボットのイベントに参加する」の欄で以下のイベントを追加
 - message.channel
 - message.groups
 - message.im
 - message.mpim
9. ｢変更を保存する」を押す　（ここだけボタンが画面下部にあるので注意）
10. 左メニュー一番上「基本情報」に行く
11. ワークスペースにアプリをインストール　をクリックして、自分のワークスペースにbotを追加する

# 動作確認
1. botを追加したワークスペースにログインし、 botユーザにDMで hello と送る
2. 返事が返ってきたら動作確認完了
3. botを稼働させたいチャンネルに botユーザをinvite
4. @botユーザ hello で同様に返事が来ることを確認

# 動かない場合の確認
- glitch上でbotが動いているか
 - 左上のサングラスの横に　[Live] と表示されている
 - サングラスをクリックしてリンク先でエラーが出ていない
- webhookイベントが届いているか
 - botkit studio の Console 画面で、自分の発言（hello）が表示されている
 - されていない場合、Slack側の設定でwebhookのイベントがONになっているか。通知先URLが正しいか。を確認  
（自分は保存ボタンの押し忘れで設定が反映されておらず、イベントの購読がOFFのままだった）
Laravel5.3 × Redisで複数のキューを扱いたかったときのメモ

# 実装したクラスをキューのジョブとして宣言するには 
Illuminate\Contracts\Queue\ShouldQueueをimplementsしている必要がある。
なぜならhandlerShouldBeQueuedでimplementsしているかのチェックをしているからである。
基本的には下記コマンドでクラスを作成するので自前でimplementsして実装する以外は特に気にする必要はない。

```
php artisan make:job hoge --queued
```
# キューのpush箇所 
Illuminate\Events\Dispatcher::createQueuedHandlerCallable

# キー名について 
Illuminate\Queue\RedisQueue::getQueueで返却されるキーが
実際にキューで使用するキー名になる 。
デフォルトは`queues:default`
設定を変えるには今のところ3パターンわかってます。
まだあったら追記予定

# 方法１
app\config\queue.phpのqueueをdefaultから任意のキーに変更する。
下記の設定だとqueues:hoge:fooのキー名になる。

```
 'redis' => [
              'driver'     => 'redis',
              'connection' => 'default',
              'queue'      => 'hoge:foo',
              'expire'     => 60,
            ],
```
# 方法２
Job側のコンストラクタでonQueueメソッドを実行し、設定を上書く。
ポイントはhandle()が呼び出される前に記述すること 。
下記の設定だとqueues:hogehogeのキー名になる。

```
<?php
namespace App\Jobs;
use App\Jobs\Job;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Bus\SelfHandling;
use Illuminate\Contracts\Queue\ShouldQueue;
class MyJob extends Job implements SelfHandling, ShouldQueue
{
    use InteractsWithQueue, SerializesModels;
    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->onQueue('hogehoge');
    }
    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {

    } 
}
```

# 方法3
方法2に似ているがonQueueメソッド実行タイミングがちょっと違う。
ジョブ呼び出し側でJobインタンス生成時にonQueueメソッドを実行し、設定を上書く。
これだとジョブ呼び出し側で同じジョブでも違うキューに設定することが可能。
Unity備忘録、STG制作7:タッチパネル操作その２

※この記事は2016年当時に在籍していた某社内での（略）、結論から言うとVR事業は大大大失敗に終わった。取れると言っていた案件は数か月放置された挙句に失注、何の戦略もなく闇雲に作った自社制作VRアプリは悲惨なDL数、それが原因でボーナスカット、昇給も無し、人の話を全く聞かない＆他人事の上役、当然だがこんな待遇ではソフト屋さんも営業も一人二人と去っていき、俺が辞めた時には某社におけるソフトウェア事業は設立３年を待たずに崩壊しましたとさ。教訓としては本業を疎かにして何の考えも無く新規モノにちょっかいだすと痛い目見るよ！ってことかな。

![dl_kaisuu.png](https://qiita-image-store.s3.amazonaws.com/0/162164/bec1e595-3b10-c80a-9754-c6cc5264116e.png)
個人製作アプリでもこんな悲惨なDL数見たことないわ。

という訳でこれが社内投稿最後の記事となりました。これがトラウマで一年以上Unityに触る気力が起きませんでしたorz
STG以外にも色々ネタ（VRとか）はあったんだけど、他のは公開する意義も気力も無いです。
じゃ、次からSTG制作再開と記事書下ろしを頑張るぞい！


#背景
[STG制作5](https://qiita.com/CAP_GOCHO/items/091714c6c04ec82ca7a9)でキャラをタッチ操作で動かせるようになったが、操作感がイマイチだったので別の方法を考えることにした。

#やりたいこと
![01.png](https://qiita-image-store.s3.amazonaws.com/0/162164/ff22f3de-3798-824a-10c6-0f116533ba53.png)


メリット：
(1)好きな場所をタッチできるので、オブジェクトが指で隠れて見づらいということが無くなる。
(2)ドラッグしたとおりにキャラが動くので、直感的に操作できる。

デメリット：
(1)特にない、と言いたいところだが、たまにドラッグ操作であることに気付かない人がいる（実際にテストプレイでそういう人がいた！）。そこは取説などでカバーする。
(2)常にドラッグ操作なので指が痛くなる。タッチペン推奨。

#サンプルコード
```csharp:Move.cs
	void Move(){
		if (Input.GetMouseButtonDown (0)) {
			//タッチ押下直後は座標のみ保存する
			screenPos1 = Input.mousePosition;
			worldPos1 = Camera.main.ScreenToWorldPoint(screenPos1);
		}

		if (Input.GetMouseButton(0)) {
			//タッチ操作中は前回タッチ位置との差分を取る
			screenPos2 = Input.mousePosition;
			worldPos2 = Camera.main.ScreenToWorldPoint(screenPos2);
			Vector2 touchDeltaPosition = worldPos2 - worldPos1;

			//キャラ移動
			transform.Translate (touchDeltaPosition.x, touchDeltaPosition.y, 0);

			//タッチ座標前回値を更新
			worldPos1 = worldPos2;
		}
			
	}

```

#実行結果
意図通りの動きになり、操作性向上が確認できた。

#参考サイト
http://gupuru.hatenablog.jp/entry/2014/05/21/192658
Django サイト管理に関するメモ

##この記事について

Djangoでは認証機能が追加パッケージ無しで利用できます。
プロジェクトには「サイト管理」というＷＥＢアプリケーションが最初から付属しており、そこでユーザー登録をし、登録したユーザーだけが認証を受けられるという仕組みです。

「サイト管理」には汎用データメンテナンス機能もあります。モデルを定義するだけで適切な登録フォーム画面が生成されるので、これだけでアプリとして運用することも可能です。
基本的な情報とカスタマイズ方法について調べた情報をメモとしてまとめました。

## 概要
###サイト管理とは
[Django公式](https://docs.djangoproject.com/ja/2.0/ref/contrib/admin/)
[参考：CodeLab Djangoで管理サイトを作成する](https://codelab.website/django-admin/)

Djangoに付属するユーザ管理用＋αのアプリケーション。
デフォルトではアプリ起動後に「サイトのURL/admin/」でアクセスできる。
アクセスするためには、ユーザーにスタッフ権限かスーパーユーザー権限が必要である。

### サイト管理でできること

- ユーザー管理

 - 個人情報の変更
 - パスワードの変更
 - 権限管理
  
- データ管理
 - アプリケーションで定義したモデルの追加・変更・削除

- 操作履歴
 - 上記操作でデータ変更した場合、操作履歴を残す

### 権限管理

サイト管理の各機能に対してパーミッション（アクセス制限）を設定できる。
パーミッションは最初から登録済みのものと、新しいモデルがマイグレーションで追加するたびに自動作成されるものがある。

パーミッションをユーザーに付与する方法は２つ。

 - ユーザーに直接付与する
 - グループにパーミッションを与え、ユーザーをグループに所属させる

## 定義

サイト管理で扱われる基本モデル

### ユーザー
認証に使用するアカウント情報。

・ユーザーのメイン属性

| フィールド名 | 内容 |
|:--|:--|
|id|ユニークキー（シーケンス）|
|username|ログインID ※1|
|password|パスワード(ハッシュ値)|
|is_active|論理削除フラグ|
|is_staff|スタッフ権限 ※2|
|is_superuser|スーパーユーザー権限 ※2|
|first_name|名字|
|last_name|名前|
|email|メールアドレス|
|last_login|最終ログイン時間|
|data_joined|登録日|


 - ログインIDは作成後に重複しない範囲で変更可能
 - サイト管理にアクセスするには スタッフ権限（is_staff)かスーパーユーザー権限is_superuserが必要
 - スタッフがサイト管理の各機能を使うためにパーミッションが必要。スーパーユーザーは暗黙的に全パーミッションを持つとみなされる。
 - 自分のパスワードの変更についてはパーミッション無しでも可能。

### パーミッション

  ユーザーに対してＮ対Ｎのリレーションを持つ。
  一つのパーミッションはサイト管理内での３つのモデル操作「追加、変更、削除」にそれぞれ対応しており、ユーザーから見てリレーションを持つ操作が許可される。

  パーミッションは、新規モデルのマイグレーション時に自動作成される。

  デフォルトでパーミッションの効果が及ぶのはサイト管理内だけだが、「django-guardian」というプラグインを使うことで通常のアプリケーションにもパーミッションをかけることができる。

  このほか手動でパーミッションを追加することができる。このパーミッションは、アプリケーションのロジックで明示的を読み込んで使う。

### グループ

パーミッションとははＮ対Ｎの関係があり。パーミッションのコンテナーとして機能する
ユーザーにグループを付与させると、グループに属するパーミッションが全て適用される。
グループの付与はユーザーの管理画面より行う。

##構造

管理サイトを構成するパッケージの本体は以下の２つ

- 'django.contrib.auth' ： 認証に必要な中核処理
- 'django.contrib.admin' ： ウェブアプリケーション部分

基本モデルはauthにある。

- django.contrib.auth.models.User
- django.contrib.auth.models.Permission
- django.contrib.auth.models.Group

### カスタマイズ方法

#### ユーザーのカスタマイズ

[参考] https://torina.top/detail/350/

ユーザーの項目やメソッドをカスタマイズで追加・修正することができる。
まず、以下のクラスを継承した自作Userクラスをアプリケーションに定義する。

django.contrib.auth.models.AbstractUser ※追加のみを行う場合
django.contrib.auth.models.AbstractBaseUser ※基本属性の修正をする場合

そして、settiing.pyに以下のように定義する
AUTH_USER_MODEL = 'app.User' ※自分で定義したUserモデル

サイト管理でカスタムユーザークラスを使うには、admin.pyの修正も必要である。

#### サイト管理画面のカスタマイズ

サイト管理の一覧画面、編集画面はカスタマイズ可能。
項目を表示するか、編集させるかを変更できる。

[Django 管理画面逆引きメモ](https://qiita.com/zenwerk/items/044c149d93db097cdaf8)

## 私見

サイトは便利ですが以下の欠点があります。

- デザインの変更が難しい。
- 以下のような中間的なパーミッションの設定が困難。
 - 自分や所属部署のデータのみ変更できる、行レベルのパーミッション
 - 付与されたパーミッションを他人に付与する

カスタマイズできなくはないですが、アプリケーションで同様の制御をするより複雑になってしまいます。
ですので、サイト管理の利用は全データにアクセスして問題ない特権的なユーザーに限定し、それ以外のユーザーで必要となる機能はアプリケーションで実装するという方針にします。

authのモデルやadminのフォームは部品化しており、自作のアプリケーション内で利用することもできます。
Cronにbundleのタスクを登録するときは気をつけよう

# Cronにbundleのタスクを登録するときは気をつけよう

何故か、Cronから下記のスクリプトを実行したときに詰まったので、色々試した結果どうやればCronに設定できたかのメモ

▼プロジェクトの場所

```
$ pwd
/var/www/html/xxx/
```

▼Cronに設定したいスクリプトの実行コマンド

```
$ bundle exec ruby hoge.rb
```

▼Cronに設定する

```
$ crontab -e

0 10 * * * su - root -lc 'cd /var/www/html/xxx/ && bundle exec ruby hoge.rb'
```

※注意としては、実行ユーザがちゃんとbundleコマンドが打てる状態になってないといけない

これで、Cronに設定できました！

## Cronログの確認

実行されたかどうかの確認は下記にログが書き込まれているか確認する。

```
$ tail /var/log/cron
```
Javaで負荷のかかっているプロセスから対象クラスを探してくれるプログラムを作ってみた

# はじめに

アプリケーションの負荷を調べるためにこの記事を試したところ
負荷をかけているプログラムが見つかりました。

https://qiita.com/tnakagawa/items/4d7d891af4913e2b5865

ただ、毎度コマンド打つのが大変なのでプログラムで自動でだせるようにしました。
githubで公開してありますのでどなたかのお役に立てれば幸いです。
ささっと作ってしまったのでとりあえず感満載でなんですがご了承ください・・・

https://github.com/ewai/check-java-process

# 動作確認済み環境
CentOS 6.7 
java8

# 実行方法

## 実行

対象システム内で以下を実行してください。
実行した直下のディレクトリにlogディレクトリが作成されてそこにログが出力されます。
アプリケーションと同じ権限での実行が必要かと思います。

```shell

java -jar check-java-process.jar 50 30 packageName

```
https://github.com/ewai/check-java-process/tree/master/build/libs
ここに置いてあるjarを使ってもいいですし、
eclipseにgradle projectとしてインポートして微調整して使ってもいいと思います。

## パラメーター

| # | 設定値 | default | 尾行 |
|:---|:---|:---|:---|
| 1 | CPU(%) | 50 | この設定値以上のプロセスを探す |
| 2 | 処理時間(秒) | 10 |  この設定値以上のプロセスを探す  |
| 3 | keyword | 無し | stacktraceにこのキーワードが入っているプロセスのみログに出力します |

## プログラムで何をしているか

1. javaのプロセスを探す
1. 1のスレッドダンプを取得する
1. 1の子プロセスを探す
1. 2と3をマッチングして子プロセスごとのstacktraceを出す。
1. パラメータの閾値を超えているプロセスのみにする。
1. パラメータのキーワードを含むプロセスのみにする。
1. ログに出力する。 

以上です。