OmniAICreator/Qiita-1.07M huggingface dataset:
TouchDesignerでGLSLを書かずにGPU Instancingしてみる

TouchDesginerでGPUを使ったParticle Systemを作れるContainer群『[PixelStorm](https://github.com/ToyoshiMorioka/PixelStorm)』を公開しました。
![スクリーンショット 2018-01-31 0.49.31のコピー.png](https://qiita-image-store.s3.amazonaws.com/0/152718/39539772-59cc-9cfc-2623-549733e6cf6c.png)

今回はこのPixelStormのExampleに入れたGPU Instancingを紹介してみようと思います。
ファイルは[これ](https://github.com/ToyoshiMorioka/PixelStorm/tree/master/Example/Instance)。
GPU Instancingの仕組み自体は以前紹介した[GPGPU Particle System](https://qiita.com/ToyoshiMorioka/items/91c4e1427c2b4296c2a4)とほぼ同様です。
Shader上での大きな差異は4点、

+ vertexIDごとの処理ではなくInstanceIDごとの処理にしていること
+ SOPを引数として持ち、それをInstancingすること
+ TOPからScaleを計算すること
+ TOPからRotationを計算すること

です。これらはTOPtoInstancePhongに全て記述されています。
これにより、
 
+ 大量のInstancingしたオブジェクトを
+ 1つずつ色、スケール、位置、回転の4要素で
+ 個別に操作すること

が、可能になります。
このExampleではさらに4つのContainerを使ってGPU InstancingなParticle Systemを作りました。
処理内容を左から説明していきます。
# 1. SOPtoTOP Containerを使い、Sphereから発生源とVelocityを作る
一般的なParticle Systemと同様にParticleの発生源と進行方向をオブジェクトから作成します。
まず、Sphere SOPからSOPtoTOPを使ってVertexの座標をTOPのRGBとして画像化し、これを初期位置として利用します。
また、Normalのベクトルも画像化し、これをVelocity、というか移動方向とオブジェクトの回転方向に利用します。
![001.png](https://qiita-image-store.s3.amazonaws.com/0/152718/b334f42c-a579-e53b-88e7-d220d2bb1ecf.png)

# 2. AgeLoopTOPでInstancing Objectに寿命をつける
Instancing Objectは一定時間で初期位置かたまた生まれるようにしたいので、AgeLoopTOPで寿命のループを作るTOPを作成します。
![002.png](https://qiita-image-store.s3.amazonaws.com/0/152718/6cd5f01d-ae4c-8c7f-ae57-e457d57a13c0.png)

# 3. POSCalculatorでInstancing Objectの現在座標を計算する
PosCalculator Containerを使って現在座標を計算させます。
初期位置はVertex座標、そしてVelocityが1フレームごとの移動量となります。
基本的には1フレームごとにVelocityをどんどん加算していくわけですが、AgeLoopTOPの見ているピクセルが真っ白になった場合はInstancingの寿命が尽きた、ということで初期位置に戻します。
Velocityはそのまま使うとすごい勢いで移動しているため、VelocityControllerというもので適当に速度を落としています。
![003.png](https://qiita-image-store.s3.amazonaws.com/0/152718/c4c27252-56e9-9332-9e17-7026285cdb97.png)

# 4. Instancing Objectが時間経過で消えるように、AgeLoopTOPからScaleを作る
これだとInstancingしたObjectの消え方もちょっと工夫したいので、AgeLoopTopをLevel TOPを使ってポジネガ反転させます。
こうすると発生したての若いObjectはRGB値が1に近く、逆に年老いたObjectは0に近い値になるTOPができあがります。
これをScaleに入力することで発生時は大きいが、だんだん小さくなり、寿命が尽きると同時に消えて無くなってしまうObjectになります。
![004.png](https://qiita-image-store.s3.amazonaws.com/0/152718/745071bf-3c0f-3631-b733-d0cd285dfc81.png)

# 5. GPU Instancingを行う

出来あがた3つのTOPをTOPtoInstancingPhongに入力します。今回ColorはPosCalculatorの値をそのまま利用しています。
![005.png](https://qiita-image-store.s3.amazonaws.com/0/152718/dea4ca19-31b1-4536-5705-02c766e2393d.png)

# 6.動きをカスタムしたければ・・・
基本的exampleはこれで以上です。もっとランダムな動きをさせたい場合はnull_rotate TOPのあとにAddを設定したComposite TOPとNoise TOPを置いて見てください。
GPU Instancingの場合はほぼ全て画像で計算を行うため、TOP系の処理をInsertすることで値を任意の値で任意のタイミングで動きや向き、サイズやスケールを変化させることが可能です。

# まとめ
いかがでしょうか。
『GPUの恩恵は受けたいけどGLSLは書きたくない！』という方はぜひさわってみてください。
Raspberry Pi Zero WでNode.js＋SQLite3を動かしてみた

# はじめに

Raspberry Pi Zero WでNode.jsが動くのは確認してたんですが、SQLite3って動くのかなということで、動作確認した手順のメモです。

ZeroWには執筆時点最新の、「[RASPBIAN STRETCH LITE](https://www.raspberrypi.org/downloads/raspbian/)」をインストールしておきます。
Wifi(もしくはOTG)やSSHの有効化などは事前に行っておいてください。

# nodebrewで最新のNode.jsをインストールする
LITE版にはNode.jsは入っていないので、nodebrewでLTSバージョンをインストールします。
まずはnodebrewから。

```
$ curl -L git.io/nodebrew | perl - setup
```

パスを通します。

```
$ echo "export PATH=\$HOME/.nodebrew/current/bin:\$PATH" >> ~/.bashrc
```

環境変数を適用します。

```
$ source ~/.bashrc
```

nodebrewが使えるようになっている事を確認します。

```
$ nodebrew -v
nodebrew 0.9.8
```

リモートのバージョンを確認します。
現時点でLTSバージョンはv8.9.4です。

```
$ nodebrew ls-remote
...
v8.9.1    v8.9.2    v8.9.3    v8.9.4    
...
```

バイナリモードでインストールします。

```
$ nodebrew install-binary v8.9.4
...
Installed successfully
```

カレントのバージョンをv8.9.4にセットします。

```
$ nodebrew use v8.9.4
use v8.9.4
```

nodeとnpmが使用できる事を確認します。

```
$ node -v
v8.9.4
$ npm -v
5.6.0
```

# Node.jsのプロジェクトを作成する
適当にプロジェクトディレクトリを作成し、npm initでpackage.jsonを作っておきます。

```
$ mkdir Projects
$ cd Projects
$ mkdir sqlite-test
$ cd sqlite-test
$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (sqlite-test) 
version: (1.0.0) 
description: 
entry point: (index.js) 
test command: 
git repository: 
keywords: 
author: 
license: (ISC) 
About to write to /home/pi/Projects/sqlite-test/package.json:

{
  "name": "sqlite-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes) yes
```

node-sqlite3をインストールします。
package.jsonに追加するよう、--saveをつけておきます。

```
$ npm install sqlite3 --save
```
コンパイルが始まるようで、すごく時間がかかります・・・。

node-sqlite3公式のサンプルプログラムを書いてみます。

```
$ nano index.js
```

```javascript
'use strict';

var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(':memory:');

db.serialize(function() {
  db.run("CREATE TABLE lorem (info TEXT)");

  var stmt = db.prepare("INSERT INTO lorem VALUES (?)");
  for (var i = 0; i < 10; i++) {
      stmt.run("Ipsum " + i);
  }
  stmt.finalize();

  db.each("SELECT rowid AS id, info FROM lorem", function(err, row) {
      console.log(row.id + ": " + row.info);
  });
});

db.close();
```

# 動作確認

動くか確認します。

```
$ node index.js
1: Ipsum 0
2: Ipsum 1
3: Ipsum 2
4: Ipsum 3
5: Ipsum 4
6: Ipsum 5
7: Ipsum 6
8: Ipsum 7
9: Ipsum 8
10: Ipsum 9
```

動きました！
[Unity][Chartboost]com.unity3d.player.UnityPlayerNativeActivity activity is missing from your android manifest. 

Chartboostをインポートした状態でビルドすると、次のエラーが発生。

`com.unity3d.player.UnityPlayerNativeActivity activity is missing from your android manifest. Add "<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />" to your activity tag so that Chartboost can forward touch events to the advertisements.`

・・・のでAndroidManifestに
`"<meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />"`
を追記してビルドするもエラーは変わらず。

ぐぐるとUnityフォーラムで次の質疑を発見。
https://answers.unity.com/questions/993527/comunity3dplayerunityplayernativeactivity-activity.html

Chartboostのエラーらしい・・。

CBManifestEditor.csの
>XmlElement unityActivityElement = FindElementWithAndroidName("activity", "name", ns, unityNativeActivityName, dict);

から始まるブロックと

>XmlElement forwardNativeEventsToDalvikElement = FindElementWithAndroidName("meta-data", "name", ns, "unityplayer.ForwardNativeEventsToDalvik", unityActivityElement);

から始まるブロックをコメントアウトしたらビルドが通った。

ちなみにChartboostは v7.0.1 for Android です。
[2018年度版]ITイベントサイトの一覧

##概要
自分で行きたい勉強会を探すために、まとめてみました。

私のニーズは、以下の点を満たしてくれるサイトです。

* 企業/コミュニティ/個人が主催の
*の小規模で無料な勉強会が1カテゴリとして存在
* 企業/コミュニティ主導の大規模な展示会/勉強会が1カテゴリとして存在
* 研修などの有料のイベントが1カテゴリとして存在
* 場所からサーチできる
* ITイベント以外の登録は禁止

しかし、どこのサイトも一長一短でしたので、今後は、自分で自分の要件を満たすアプケーションを作ってみたいです。やはり、今はなきIT勉強会カレンダーが至高ですね。


##イベントサイト

###01.(定番)様々なイベントが集まるイベントサイト
小規模なイベントは主にこのようなサイトに集まっているようです。

[IT勉強会カレンダー - サポーターズCoLab](https://supporterzcolab.com/calendar/)
[イベント開催支援ツール アテンド : ATND](https://atnd.org/)
[セミナー・勉強会・イベント管理ツール | Doorkeeper](https://www.doorkeeper.jp/)
[connpass - エンジニアをつなぐIT勉強会支援プラットフォーム](https://connpass.com/)
[こくちーず（告知's） - イベント・セミナー集客を支援する無料サービス](http://kokucheese.com/)
[AZusaar!!](http://azusaar.appspot.com/)
[TECH PLAY［テックプレイ］ - IT勉強会・セミナーなどのイベント情報検索サービス](https://techplay.jp/)
[Peatix (ピーティックス）| グループ・イベント管理、チケット販売・集客サービス | Peatix](https://peatix.com/)
[upmeetup.info | 勉強会一覧 イベント一覧 ランキング](http://upmeetup.info/)


###02.エンタープライズ/コミュニティ主導の展示会の一覧が載っているサイト
[ ＠ITイベント＆セミナー - ＠IT](http://www.atmarkit.co.jp/ait/subtop/features/seminar/)
[atmarkit](https://event.atmarkit.co.jp/)


###03.有料の研修系や、エンタープライズでの製品紹介イベント
[イベント情報 - ZDNet Japan](https://japan.zdnet.com/event_info/)
[イベント・セミナー情報｜ビジネス+IT](https://www.sbbit.jp/eventinfo/)
[IT関連イベント−2017年](http://www.josan.jp/event17.html)


###04.有名な勉強会
小規模な勉強会の中でも、有名なものがまとめられています。
こちらについては、大変よくまとまった記事があるので、リンクのみ。

[IT勉強会に参加しよう！人気の勉強会・おすすめサイトまとめ | TECH::NOTE | プログラミングをはじめる全ての人に](https://tech-camp.in/note/engineer/27971/)
[「行っておくべき有名IT系勉強会」と、その開催日をチェックする方法 | さくらのナレッジ](https://knowledge.sakura.ad.jp/489/)


###参考
[IT勉強会を探すために捗るサイトまとめ【10選】](https://qiita.com/kobaboy/items/6c80511a10122aa87d02)
[エンジア向けの勉強会とかイベントを探す](https://qiita.com/nightyknite/items/0c7ba27bf3baa87d262a#_reference-92de5d1414b1a97346b4)
二段階認証設定したGitHubアカウントでAndroid Studioからpushできない場合の対処法

二段階認証設定したGitHubアカウントでAndroid Studioからpushできない場合の対処法メモです。

## 結論
API Tokenを発行する。

## 環境
Android Studio: 3.0.1

## 手順
1. `Preferences` > `Version Control` > `GitHub`を開く  
![Screen Shot 2018-01-31 at 12.46.26 AM.png](https://qiita-image-store.s3.amazonaws.com/0/123122/bd79f184-3900-0edb-b47b-20f911f1196c.png)
2. `Auth Type`を`password`から`token`に変更  
![Screen Shot 2018-01-31 at 12.49.23 AM.png](https://qiita-image-store.s3.amazonaws.com/0/123122/19517f4f-9097-734b-602d-825a394245f4.png)
3. `Create API Token`押下  
![Screen Shot 2018-01-31 at 12.50.19 AM.png](https://qiita-image-store.s3.amazonaws.com/0/123122/33086695-3070-73be-468d-0117c51e84b2.png)
4. 認証コードを入力してToken発行
5. `Test`押下  
![Screen Shot 2018-01-31 at 12.51.21 AM.png](https://qiita-image-store.s3.amazonaws.com/0/123122/d99ba6da-6cf2-acfb-b062-4242014a0da2.png)
6. Successが出ればOK  
![Screen Shot 2018-01-31 at 12.51.39 AM.png](https://qiita-image-store.s3.amazonaws.com/0/123122/cc3733b9-520f-ede1-9c9d-f8e7f97f8826.png)

## 補足
Token発行以外にpushできる方法がパっと調べた限りだとわからなかったのですが、とりあえずこの方法でpushできました。
JavaScriptでビンゴをつくる

社内でビンゴ大会があり、ビンゴの仕組みをJavaScriptで作成したので、その共有です。

## 必要な機能
ビンゴのシステムを作るにあたり、必要な機能を考えます。

- 数字がランダムに表示される
- 同じ数字は二度でない
- 出た数字が確認できる

こんなところでしょうか。
上記、3つの機能を備えたプログラムを作っていきます。

## 書いてみる
上記の３つの機能を網羅したプログラムを書いてみました。

```javascript:jQuery
let gameState = true; // ゲームの状態
let preArray = []; // 抽選箱
let postArray = []; // 過去ログ

const itemLength = 10; // ビンゴの最大数
for (let i = 0; i < itemLength; i++) {
  preArray.push(i); // 抽選箱の中に整数を格納
}

for (let i = 0; i < preArray.length; i++) {
  let rand = Math.floor(Math.random()*(i+1)); // 乱数を作成
  [preArray[i], preArray[rand]] = [preArray[rand], preArray[i]]; // 整数をランダムに並べ替え
}

$('button').on('click', function(){
  if (0 < preArray.length) {
    let current = preArray.shift(); // 抽選箱の先頭の要素を取得し、削除
    postArray.push(current); // 過去ログに格納
    console.log(current);
    console.log(postArray);
  } else {
    if (gameState) {
      gameState = false;
      console.log('終了');
    } else { // gameState が false ならなにもしない
      return false;
    }
  }
});
```

## 解説
上から解説していきます。

```javascript:jQuery
let gameState = true; // ゲームの状態
let preArray = []; // 抽選箱
let postArray = []; // 過去ログ
```
`gameState`はBINGOが終わったときに`false`にして、if文の分岐条件にします。
まだ空っぽですが、抽選箱に見立てた`preArray`に数字を入れておき、取り出して`postArray`に入れます。
実際のビンゴと同じシステムです。

```javascript:jQuery
const itemLength = 10; // ビンゴの最大数
for (let i = 0; i < itemLength; i++) {
  preArray.push(i); // 抽選箱の中に整数を格納
}

for (let i = 0; i < preArray.length; i++) {
  let rand = Math.floor(Math.random()*(i+1)); // 乱数を作成
  [preArray[i], preArray[rand]] = [preArray[rand], preArray[i]]; // 整数をランダムに並べ替え
}
```
出したい数字の最大数を決め、その数だけfor文を回し、抽選箱こと`preArray`に整数を格納します。
`preArray`をもう一度for文で回し、中の数字をランダムに並べ替えます。
並べ替えは、以下を参考にさせていただきました。

参照：[JavaScript 簡単に配列をシャッフルする](https://qiita.com/artistan/items/9eb9a0fb14f4ec3a8764)

[フィッシャー–イェーツのシャッフル](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%83%E3%82%B7%E3%83%A3%E3%83%BC%E2%80%93%E3%82%A4%E3%82%A7%E3%83%BC%E3%83%84%E3%81%AE%E3%82%B7%E3%83%A3%E3%83%83%E3%83%95%E3%83%AB)です。

```javascript:jQuery
$('button').on('click', function(){
  if (0 < preArray.length) {
    let current = preArray.shift(); // 抽選箱の先頭の要素を取得し、削除
    postArray.push(current); // 過去ログに格納
    console.log(current);
    console.log(postArray);
  } else {
    if (gameState) {
      gameState = false;
      console.log('終了');
    } else { // gameState が false ならなにもしない
      return false;
    }
  }
});
```
`button`要素をクリックしたら、抽選箱`preArray`の先頭の要素を`current`に代入し、抽選箱`preArray`から削除します。
そして、`current`を過去ログ用配列の`postArray`に格納します。
抽選箱`preArray`の中身がなくなったら、if文で終了を通知し、その後なにも起こらないようにします。

## 確認
コンソールを開き、「ぼたん」をクリックしてご確認ください。
<p data-height="265" data-theme-id="0" data-slug-hash="bLNWXo" data-default-tab="js,result" data-user="boltkeep" data-embed-version="2" data-pen-title="BINGO" class="codepen">See the Pen <a href="https://codepen.io/boltkeep/pen/bLNWXo/">BINGO</a> by Otsuka Yuhi (<a href="https://codepen.io/boltkeep">@boltkeep</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>
URLからタイトルがリンクになっているMarkdown記法のリンク文を作成する

##概要
QiitaのMarkdownでリンクを作成する際、タイトル名がリンクになっているようにするには、以下の記載でする必要がある。
これを、URLから簡単に生成したい。

```console

[title](http://...)

```

##方法

###01.URLからタイトル取得
まず、以下のサイトで、URLを入れる

[URLからタイトルゲット君](http://atomii.com/)

すると、以下のCSV形式で結果を受け取れる
(この例では、上記サイトのURLをインプットにしている）


```
http://atomii.com/,URLからタイトルゲット君
```

###02.取得した文字列をMarkdown形式に加工
デスクトップ適当なファイルで保存し、以下のようなawkコマンドに食わせてあげればいい感じで出力される。

```awk

cat list.txt   | awk 'BEGIN {FS=",";OFS=","} {print "["$2"]""("$1")"}'
```

##追伸
URLからタイトルを取得するやり方は、いくらでもやりようがありますが、
markdownとして、標準の機能があったり、Qiitaが独自に変換してくれる記法などがあったら、誰か教えてください。
（皆さんどうやってるんだろう。。。）
Rocket.ChatのCustom CSS

対象 : Ubuntu Server 16.04.1 LTS上にsnapでインストールしたRocket.Chat

Rocket.Chat は 2017/10/18 にリリースされた Ver. 0.59.0 から新UIになりました。
そこで気になった箇所を Custom CSS 機能で一部スタイル変更して使っているのでメモとして残します。
CSSの追加は管理者メニューの「レイアウト」＞「Custom CSS」で行えます。

## コンテキストメニュー項目hover
### 事象
マウスオーバーしても項目の色が変わらなくなりました。
どれを選択しようとしているのかわかりにくいです。

before
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154744/93f4b54b-a482-5e88-ed23-1fb198c3a62e.png)

### 対応
以下のCSSを追加

```css
.rc-popover__item:hover {
  background-color: rgba(0, 0, 0, 0.05); /* @transparent-dark */
}
```

after
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154744/5d2e879b-bce2-2f77-f20d-57ace8b5fdde.png)

## 検索結果パネルの幅が広がる事象対応（解消済）
### 事象
これは Ver. 0.61.0 に更新後、Firefoxのみで事象が発生しています。
(Windows 10, Firefox 58 で確認)
(CentOS 7, Firefox ESR 52 で確認)
通常このくらいの幅なのが、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154744/7374a3c7-b59c-7eba-095a-b46e78a9dc07.png)


検索結果によって幅が広がることがあります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/154744/7ac2bb90-7be2-cb4d-03d1-2594369679ca.png)

### 対応
以下のCSSを追加

```css
.contextual-bar-wrap {
  width: 400px !important;
}
```

### 解消
Ver.1.2.3時点で解消されていることを確認
(Windows 10, Firefox 68 で確認)


## 絵文字が常時大きくなる事象
### 事象
Ver. 1以降だったかと思います。（Ver.1.2.3で継続中）
メッセージ＞Markdown＞Markdownパーサーが「Marked」の時に、絵文字が常時大きくなる事象が発生しています。

before
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154744/17e606d3-94d9-481c-2a70-be954b081734.png)

### 対応
以下のCSSを追加。
ただし絵文字単体時も通常の大きさになってしまいます。
逆に単体時に大きくしたくない場合もこれを使えばよいです。
設定後、ブラウザリロードで適用されます。

```css
.emoji.big,
.emojione.big {
  width:22px;
  height:22px;
}
```

after
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154744/e6e368ef-a83d-d17f-35c0-d08ad2c61b61.png)
2018年に開催される全国のPHPカンファレンスのまとめ

# 2018年に開催される全国のPHPカンファレンスのまとめ

## [PHPerKaigi 2018](https://phperkaigi.jp/2018/)
- 開催日 : 3月9日(金)～3月10日(土)
- 開催場所 : [練馬区立区民・産業プラザ Coconeri ホール](http://coconeri.jp/access.html)
- Twitter : https://twitter.com/phperkaigi
- ハッシュタグ : [#phperkaigi](https://twitter.com/hashtag/phperkaigi?src=hash)

## [PHPカンファレンス福岡 2018](http://phpcon.fukuoka.jp/2018)
- 開催日 : 6月16日(土)
- 開催場所 : [福岡ファッションビル FFB HALL](http://www.ffb.jp/access/)
- Twitter : https://twitter.com/phpcon_fukuoka
- ハッシュタグ : [#phpconfuk](https://twitter.com/hashtag/phpconfuk?src=hash)

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">PHPカンファレンス福岡2018の開催日が2018年6月16日（土）に決定しました。開催に先立ちスポンサー様の募集を開始いたします。ご興味、ご関心ございましたら、まずは募集サイトの方をご覧いただけると幸いです。みなさま、来年もどうぞご協力のほどよろしくお願いいたします。<a href="https://t.co/0JzCCZg3xp">https://t.co/0JzCCZg3xp</a></p>&mdash; PHPカンファレンス福岡 (@phpcon_fukuoka) <a href="https://twitter.com/phpcon_fukuoka/status/945464890281508866?ref_src=twsrc%5Etfw">2017年12月26日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## [PHPカンファレンス関西2018](https://2018.kphpug.jp/)
- 開催日 : 7月14日(土)
- 開催場所 : [グランフロント大阪北館タワーC8階](https://www.kc-space.jp/accessmap/conference/towerc.html#jump)
- Twitter : https://twitter.com/phpcon_kansai
- ハッシュタグ : [#phpkansai](https://twitter.com/hashtag/phpkansai?src=hash)

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr"><a href="https://t.co/liAVztrK1c">https://t.co/liAVztrK1c</a><br>明けましておめでとうございます！年明けと共に、PHPカンファレンス関西2018のティザーサイトが公開されました！😄今年もワクワクがいっぱいのイベントとなるようスタッフ一同全力を尽くしますので、ぜひたくさんの方にお越し頂ければと思います！😋</p>&mdash; PHPカンファレンス関西 (@phpcon_kansai) <a href="https://twitter.com/phpcon_kansai/status/947761189265620993?ref_src=twsrc%5Etfw">2018年1月1日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## [PHPカンファレンス 2018](http://phpcon.php.gr.jp/)
- 開催日 : 12月15日(土)
- 開催場所 : [大田区産業プラザ Pio](http://www.pio-ota.net/access/)
- Twitter : https://twitter.com/phpcon/
- ハッシュタグ : [#phpcon2018](https://twitter.com/hashtag/phpcon2018?src=hash)
- Facebook : https://www.facebook.com/pcon.japan/

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">来年のPHPカンファレンス2018は、2018年12月15日 (土) に開催します。<br>来年もよろしくお願いします！<a href="https://twitter.com/hashtag/phpcon2018?src=hash&amp;ref_src=twsrc%5Etfw">#phpcon2018</a> <a href="https://twitter.com/hashtag/php?src=hash&amp;ref_src=twsrc%5Etfw">#php</a> <a href="https://twitter.com/hashtag/phpcon?src=hash&amp;ref_src=twsrc%5Etfw">#phpcon</a></p>&mdash; phpcon (@phpcon) <a href="https://twitter.com/phpcon/status/916939565125877760?ref_src=twsrc%5Etfw">2017年10月8日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 過去のPHPカンファレンスまとめ
- [2017年に開催される全国のPHPカンファレンスのまとめ](https://qiita.com/akase244/items/274e11da0196a4c26b2a)
- [2016年に開催される全国のPHPカンファレンスのまとめ](http://qiita.com/akase244/items/a390b775267ab095e912)
- [2015年度 全国の PHP カンファレンス のまとめ](http://qiita.com/mukaken/items/71dbe2dde462d459adc8)
macOSでgitprompt.shを使ってコマンドプロンプトを良い感じに設定する


https://github.com/magicmonty/bash-git-prompt#installation
ここにある通りなんだけど
* `brew`で`bash-git-prompt`を入れる
* `~/.bash_profile`でプロンプトを設定する
の2行程

## brewでbash-git-promptを入れる

ついでに `bash completion` も追加しておく

```sh:cli
brew update
brew install bash-git-prompt bash-completion
```

## ~/.bash_profileでプロンプトを設定する


```sh:~/.bash_profile
if [[ -f "$(brew --prefix)/opt/bash-git-prompt/share/gitprompt.sh" ]]; then
  __GIT_PROMPT_DIR=$(brew --prefix)/opt/bash-git-prompt/share
  source "$(brew --prefix)/opt/bash-git-prompt/share/gitprompt.sh"
fi

[[ -f $(brew --prefix)/etc/bash_completion ]] && . $(brew --prefix)/etc/bash_completion
```
Containerを作る/Containerを使う

# はじめに
TouchDesignerには一連のパッチを再利用したい場合に、Containerを使ってパッチ群を再利用可能な状態で保存し、再利用する仕組みがあります。
チームで制作を進める場合に必須になるであろうContainerの使い方、作り方を説明していきます。

# 1. Containerを作る
## 1-1. Base Containerを用意する
パッチ一覧からBase Containerを選び、設置します。
![スクリーンショット 2018-01-30 23.37.49.png](https://qiita-image-store.s3.amazonaws.com/0/152718/74a260e7-4408-2df4-0e24-7565fb89f7c0.png)

## 1-2. Base ContainerにIn/Outを設置する
Base ContainerにIn/Outを設置します。
中に再利用したいパッチを一通り入れ込みます。
![スクリーンショット 2018-01-30 23.50.56.png](https://qiita-image-store.s3.amazonaws.com/0/152718/1f38f448-da34-093c-3fc9-382d14f9b95c.png)

## 1-3. Base Containerに外出しのパラメータを設定する
Base Containerを右クリックし、「Customize Component...」を選びます。
![スクリーンショット 2018-01-30 23.38.01.png](https://qiita-image-store.s3.amazonaws.com/0/152718/22192d77-fc5f-aaa4-46d2-2b7f71cacf71.png)
PageとParameterを編集するダイアログが開くので、まずはPageを設定します。
森岡はSettingsという名前で作ることが多いですが、ちゃんと名前を考えた方が良いかも。名前を設定したあと「Add Page」ボタンでページが追加されます。
![スクリーンショット 2018-01-30 23.41.20.png](https://qiita-image-store.s3.amazonaws.com/0/152718/7cef5975-0e0a-5547-f23e-6cd5e7bf8fba.png)
その後、パラメータを追加していきます。
Float、Toggleなど色々なパラメータが設定できます。
こちらも名称を設定後、「Add Par」でパラメータが追加されます。
今回はとりあえずOpacityを作ってみました。
追加すると下で設定値のminやmax、デフォルト値など、取りうる範囲の設定が可能です。
![スクリーンショット 2018-01-30 23.41.49.png](https://qiita-image-store.s3.amazonaws.com/0/152718/1d69790a-4c20-d93b-5d59-84c3e9d74faf.png)
設定が終わるとparameter内にSettingsページとOpacityパラメータが追加されています。

## 1-4. Parameter CHOPで外出しのパラメータの値を受け取る
それではContainerの外で設定されたパラメータを実際にContainerの中で受け取るようにしましょう。
Parameter CHOPを設置すると追加したページ内のパラメータが全て受け取れます。
![スクリーンショット 2018-01-31 0.07.01.png](https://qiita-image-store.s3.amazonaws.com/0/152718/309e45ce-60d2-e1cb-77a1-76c0a165da0f.png)

## 1-5. .tox形式で保存する
Base Container単体の保存はtox形式となります。
tox形式で保存するにはBase Container上で右クリックし、「Save Component...」を選択し、保存します。
![スクリーンショット 2018-01-30 23.37.56.png](https://qiita-image-store.s3.amazonaws.com/0/152718/cf9854c6-ee89-a0f3-efc5-22349cb8e42f.png)

# 2. Containerを使う
## 2-1. とりあえず利用する
保存したtoxファイルを利用したいProjectのNetwork Editor上にDrag&Dropします。
## 2-2. 自分のTouchDesigner IDEに保存してから利用する
TouchDesigner IDEの左にあるPalleteにtoxは保存可能です。保存しておけば何時でも呼び出せます。
ただしMy Components以下にフォルダを作成し、その中にDrag&Dropする必要があります。
![スクリーンショット 2018-01-31 0.11.49のコピー.png](https://qiita-image-store.s3.amazonaws.com/0/152718/b63a318f-00c3-955b-6304-f77203e01c76.png)

## 2-3. 相対パスを使って利用する
2-1.と同様にNetwork Editor上にDrag&Dropします。
その後、このBase ContainerのCommonタブにあるExternal .toxにtoxのパスを指定します(今、作っているプロジェクトと同じフォルダ、同じ階層にあるのでパスっぽくなってませんが・・・)。
![スクリーンショット 2018-01-30 23.43.08.png](https://qiita-image-store.s3.amazonaws.com/0/152718/3b0f5623-1a68-f218-c7fc-4b3042e72028.png)

Base Containerの中に入ったときに左上に「External Tox」のマークがあれば成功です。
![スクリーンショット 2018-01-31 0.15.19.png](https://qiita-image-store.s3.amazonaws.com/0/152718/d806641e-3a4b-79cf-babe-7a2ebd05100e.png)

ちなみにExternal .toxの下のReload .tox on StartをONにすると、プロジェクトを起動時にBase Containerが最新の状態かどうか見に行ってくれるようになります。
誰かが絶賛更新中のtoxを利用する場合はこちらをonにしておくと良いでしょう。
また、その下のSave Backup of ExternalをONにすると、「プロジェクト自体がtoxのバックアップも含めての保存を行い、パス先が消失してしまった場合もバックアップしていた以前のtoxで起動されるようになります。
最終成果物のプロジェクトなどではonにしておくと良いでしょう。
逆にみんなで作っているときにonにしておくと、Container名の変更に気づけないかもしれません。
性能調査で使うコマンド


美貌です


- ps -ef
  - PPIDはこっち
- ps aux 
  - CPU, VSZ, RSS なら
  - ps auxf : PPIDもこれで付く
- iostat -w 1
  - disk I/O を詳細にみるなら
- vmstat 1
  - cpu, memory, swap, disk I/O, Network I/O をまとめて見るなら
- sar -n DEV
  - Network I/O を詳細にみるなら


### ps -ef

TBC

### ps aux

TBC

#### ps auxf

TBC

### iostat -w 1

TBC

### vmstat 1

TBC

### sar -n DEV

TBC
Laravel5.5＋react-router-dom クイックスタート


公式の[QuickStart](https://reacttraining.com/react-router/web/guides/quick-start)を参考にやっていきます。
※私自身もReact始めたてなので、こうやって開発した！という備忘録的な意味もあります。

#前提
Laravel5.5 ＋ Reactの初期設定が完了していること
（[前回の記事](https://qiita.com/yamatox/items/35adb1f00195bb111a57)参照ください）

#Laravelのルータ設定
react-router-domで定義したURLで直接アクセスしてもちゃんと表示されるように設定を変更します。
これをやらないと、「127.0.0.1:8000/」はアクセスできても「127.0.0.1:8000/about」にアクセスできません。
（[ここ](https://stackoverflow.com/questions/40719951/how-to-use-react-router-with-laravel)に記載されていました）

```diff:router/web.php
+ Route::get('/{path?}', function(){
+     return view('welcome');
+ } )->where('path','.*');

- Route::get('/', function () {
-     return view('welcome');
- });
```

#React-router-dom インストール

```
npm install --save react-router-dom
```

```diff:resources/assets/js/components/Example.js
※ほぼQuickStartのママです。 前回のExample.jsをちょっとマージしてます。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import {
  BrowserRouter as Router,
  Route,
  Link
} from 'react-router-dom'

const Home = () => (
  <div>
    <h2>Home</h2>
  </div>
)

const About = () => (
  <div>
    <h2>About</h2>
  </div>
)

const Topic = ({ match }) => (
  <div>
    <h3>{match.params.topicId}</h3>
  </div>
)

const Topics = ({ match }) => (
  <div>
    <h2>Topics</h2>
    <ul>
      <li>
        <Link to={`${match.url}/rendering`}>
          Rendering with React
        </Link>
      </li>
      <li>
        <Link to={`${match.url}/components`}>
          Components
        </Link>
      </li>
      <li>
        <Link to={`${match.url}/props-v-state`}>
          Props v. State
        </Link>
      </li>
    </ul>

    <Route path={`${match.url}/:topicId`} component={Topic}/>
    <Route exact path={match.url} render={() => (
      <h3>Please select a topic.</h3>
    )}/>
  </div>
)

const BasicExample = () => (
  <Router>
    <div>
      <ul>
        <li><Link to="/">Home</Link></li>
        <li><Link to="/about">About</Link></li>
        <li><Link to="/topics">Topics</Link></li>
      </ul>

      <hr/>

      <Route exact path="/" component={Home}/>
      <Route path="/about" component={About}/>
      <Route path="/topics" component={Topics}/>
    </div>
  </Router>
)
export default BasicExample

if (document.getElementById('example')) {
    ReactDOM.render(<BasicExample />, document.getElementById('example'));
}

```

#結果
「127.0.0.1/8000」にアクセスするとリンクが表示され、クリックすると画面遷移できました。
アドレスが変わっていることも確認できると思います。



##○127.0.0.1:8000/
![01.png](https://qiita-image-store.s3.amazonaws.com/0/108431/89fb7ea9-430e-2462-5d78-c3699f65413e.png)
##127.0.0.1:8000/about
![02.png](https://qiita-image-store.s3.amazonaws.com/0/108431/9339f9bb-592f-2027-f83f-b62f379de26a.png)
##127.0.0.1:8000/topics
![03.png](https://qiita-image-store.s3.amazonaws.com/0/108431/b3474e4b-b213-5c61-4038-9712355baf05.png)

今回はひとまずここまで。。。
要素ごとにランダムに抽出される確率（重み付け）を設定する

# なんだこれ
いわゆるガチャテーブル、『 **重み付き乱択** 』をes6で実装してみました。
特定のバナー画像だけ他のバナー画像よりも少し多めに表示させたり、簡易的に負荷分散をさせたり、、と使う場面は多そうです。

# 1. 実装
```js
// ダーツ投げる
const throwDarts = awards => {
  const hit = rand(1, dartboard(awards));
  return dartboard(awards, hit);
}

// ダーツ盤
const dartboard = (awards, hit) => {
  let area = 0;
  for (let key in awards) {
    area += awards[key];
    if (hit && (area >= hit)) return key;
  };
  return area;
}

// 乱数(min ~ max)
const rand = (min, max) => {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

// 賞品テーブル
const awards = {
  'たわし': 7,
  '温泉旅行': 2,
  'パジェロ': 1
}

// 実行
console.log(throwDarts(awards)); // たわし
```
メインとなる関数は `dartboard()` ですが、たったこれだけです。
おわかりいただけたでしょうか。

『関口宏の東京フレンドパークII』の最後にやっていた、回転するダーツ盤にダーツを打ち込むイメージです。
![849be8af-a664-4452-9615-d7455ca77ce9.jpg](https://qiita-image-store.s3.amazonaws.com/0/223109/413d8ea2-3b07-eec8-072b-da8238fceb85.jpeg)


# 2. 解説
```js:throwDarts()
const hit = rand(1, dartboard(awards));
```
ここでの `dartboard(awards)` は 賞品テーブル `awards` の **合計値(10)** を返します。
乱数 `hit` はダーツの **着弾地点(1~10)** を示します。

```js:dartboard()
  let area = 0;
  for (let key in awards) {
    area += awards[key];
    if (hit && (area >= hit)) return key;
  };
```

`area` はダーツ盤における **賞品の面積** です。
各賞品の面積を `for` ループで加えていき、 `hit` が `area` の範囲内ならば賞品名を返します。
当然、面積が広い賞品ほど刺さりやすく、逆に狭い賞品には刺さりにくくなります。

![goods_tawashi.png](https://qiita-image-store.s3.amazonaws.com/0/223109/0fdb4fa6-e522-32ca-19ac-4a700ab30a61.png)
例えると簡単ですね。
ロジックは分かったので精度を検証してみましょう。

# 3. 検証
### 100万回投げた
```js
const awards = {
  'たわし': 50,
  '画力': 8,
  '筋力': 8,
  '集中力': 8,
  '健康': 8,
  '優しい性格': 8,
  '5000兆円': 8,
  'パジェロ': 2
}

const results = {
  'たわし': 0,
  '画力': 0,
  '体力': 0,
  '集中力': 0,
  '健康': 0,
  '優しい性格': 0,
  '5000兆円': 0,
  'パジェロ': 0
}

for (let i=0; i<1000000; i++) {
  results[throwDarts(awards)]++;
}

console.log(results);
```

### 結果
```js
Object {
  5000兆円: 79486,
  たわし: 500800,
  パジェロ: 20037,
  健康: 79943,
  優しい性格: 79549,
  画力: 80002,
  体力: 79774,
  集中力: 80409
}
```

### よさそう
よさそうです

# 4. 参考
* [《JavaScript》範囲指定したランダムな値を得るスクリプト。](https://qiita.com/uto-usui/items/7193db237175ba15aaa3)
Rubyのmapメソッドの使い方例

Rubyのmapメソッドは便利でいろんな使い方があるのですが、その使用例を自分の備忘録も込めて残しておきます。

## 基本
```rb
p [1, 2, 3].map { |a| a * 2 } 
=> [2, 4, 6]
```

## 条件付きで
```rb
# 奇数の時のみ3倍にして配列に入れる
# 該当しない場合はnilを返す

p [1, 2, 3].map{ |a| a * 3 if a.odd? }    
=> [3, nil, 9]
```

## selectメソッドで条件を絞って
```rb
# 奇数の時のみ3倍にして配列に入れる
# 上の条件付きと違う点は該当しない場合にnilを返さなくなる

p [1, 2, 3].select { |a| a.odd? }.map { |selected| selected * 3 }
=> [3, 9]
```
GoogleAppScriptでSpreadSheet操作、メール送信、定期実行を簡単実装

GoogleSpreadSheetにプログラミングに関わる用語で知らなかったものをメモしているのですが、その中からランダムに１日1回自分のメールに送信して覚えられるようにしたかったのでGASを使って仕組みを作りました。

#結論
めちゃ簡単だった。

#コード
メソッドの抽出をした方がいいですが調査しながら一旦動作出来るところまで実装したので、リファクタリングはしてません。

```javascript
function fetchTechnicalTermAndSendToMe() {
  //現在のspreadsheetの取得
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();

  //現在のsheetの取得
  var sheet = spreadsheet.getActiveSheet();

  //データが存在する一番下の行番号
  var lastRow = sheet.getLastRow();

  //データが存在する一番右のカラム番号(A,B,C...が1,2,3...に置き換えられて数値が入ります)
  var lastColumn = sheet.getLastColumn();

  //読み取る最初のセルの行番号
  var startRow = 4;

　//読み取る最初のセルのカラム番号
  var startColumn = 3;

  //読み取るセルの範囲を指定
  var range = sheet.getRange(startRow,startColumn,lastRow - (startRow - 1),lastColumn);

  //指定した範囲内の値を配列で取得
  var values = range.getValues();
  
  //ランダムに１行を抽出
  var randomValue = values[Math.floor(Math.random() * values.length)]
  
  //メール文作成
  if(randomValue.length === 0){
    var err = "空行です";
    Logger.log(err);
    exit;
  }
  var term = "用語：" + randomValue[0];
  var description = "説明：" + randomValue[1];
  
  //メール送信
  MailApp.sendEmail({
     to: "your-mail@example.com",
     subject: "今日の用語",
     htmlBody: term + "<br>" + description,
   });
}

```
リファレンスと以下の記事を参考にしました。
・[リファレンス(SpreadSheet)](https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app)
・[リファレンス(MailService)](https://developers.google.com/apps-script/reference/mail/)
・[【Google Apps Script入門】セルの取得・変更をする](http://uxmilk.jp/25841)
※メール関連では`MailService`と`GmailService`があるのですが、メール送信だけなら`MailService`で十分です。

#定期実行する
定期実行はスクリプトではなく、GASアプリの機能で実現します。
以下の記事をそのまま実施すればOKです。

(参考)[Google Apps Scriptを使って定期実行するcronを作る](https://www.sakana.tech/entry/make-cron-use-googleappsscript#i-5)

GASはやりたいなーと思いつつも、やる理由がなく手をつけてなかったのですが、今回やってみて手軽さ半端なかったので、他にも色々やってみたいと思いました。

以上。
仮想通貨について調べはじめたら、「P2Pって何？」となった

#導入
コインチェックのニュースをよく目にするので、仮想通貨について調べてみました

その導入部分に現れたP2Pの文字

聞いたことはあるけど、何かはよく分からない

とりあえず調べて分かったことを備忘録として記します

#P2Pとは

Peer tp peerの略

※Peerは同格者の意味

つまり、同格のPC同士を繋いでいるという意味です

##そもそも同格って何？

例えばみんな大好き、Youtube

動画をみたい時はYoutubeのURLを叩いてアクセスします

そして、その先にある動画の数々はYoutubeのサーバー上に全世界のYoutuberがアップロードしたものです

一つのPCに色々な動画が保管してあり、それを全世界のユーザーが閲覧しにいくイメージですね

これに対し、P2Pの場合は、各Youtuberが自分のPC上に動画を保存しており、動画をみたい人はそのPCに直接アクセスし、閲覧します

前者はクライアントサーバー方式と呼ばれています

##何に使われているの？

P2Pの例としてよくあげられるのがSkypeですね

あとサッカーゲームのオンライン対戦でも使われています

##P2Pのメリットは？

一つのサーバーにアクセスが集中するといったことが起きにくいため、負荷を分散することが可能です
EclipseからのSAP ERPのDB操作

こちらを参考に、EclipseからSAPERPのデータベース操作を行ってみます。

[Display database content and run SQL queries]
(https://www.sap.com/developer/tutorials/abap-display-data-queries.html)

今回は、上記参照元のSTEP.1～8(データ照会)を行います。


#**前提**
EclipseとSAPERPが接続済であること

接続方法については[こちら](https://www.sap.com/developer/tutorials/abap-create-project.html)を参照



#**手順**
##Step 1: Open the Data Preview
メニューよりRun ABAP～を選択
![スクリーンショット (698)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/298b8507-96dd-01cd-9167-7af8fb32ca06.jpeg)

##Step 2: Select a database table
私の環境ではsnwd_so_inv_itemにデータが存在していなかったため、毎度おなじみSFLIGHTを指定
![スクリーンショット (699)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/4ee7ac13-85b0-8fdd-2ce0-6f290941353c.jpeg)


##Step 3: Data preview
簡単にデータが照会できました。
続いて「列の選択」
![スクリーンショット (700)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/43c835db-2e05-065c-9c13-0b7ade33b821.jpeg)

##Step 4: Select columns
![スクリーンショット (701)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/7701c8a7-9d21-85c0-0e9a-f82abf1e34aa.jpeg)

選択した列のみ表示されました
![スクリーンショット (702).png](https://qiita-image-store.s3.amazonaws.com/0/22526/ebe1e604-e867-ae2e-ecc1-5494773ebfc5.png)

##Step 5: Add a filter
次にフィルターを追加
![スクリーンショット (703)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/7295999e-bf27-76ef-ee8a-9faf5ccb13fd.jpeg)

##Step 6: Enter filter criteria
![スクリーンショット (704)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/cef67fd6-a2d2-1e8d-7132-e9c9cb7679c0.jpeg)

![スクリーンショット (705)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/864fe73c-0e4c-9884-a1b5-e9857ed37bd5.jpeg)

##Step 7: Open the SQL Console
![スクリーンショット (695)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/10b081e2-a605-fcbe-ced5-547131065f18.jpeg)

##Step 8: Initial SQL SELECT statement
こんな感じ
![スクリーンショット (707).png](https://qiita-image-store.s3.amazonaws.com/0/22526/09ea8da7-454b-02d0-3af2-c81fc637822f.png)

おまけで、ちょっとだけイジってみます。
条件を追加して、実行
![スクリーンショット (709)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/93d2cfaa-1454-5f01-a3ff-31da011fbb43.jpeg)

ちゃんと条件がきいています

![スクリーンショット (710)_LI.jpg](https://qiita-image-store.s3.amazonaws.com/0/22526/724cb07f-7a12-541f-1466-88ded09c22ca.jpeg)


#**まとめ**
非常に簡単にデータ照会ができました。
今回は未実施ですが、データの更新もできるみたいです。

Eclipseの操作に慣れるのには、HelloWorldよりこちらからやったほうがいいですね。
シェルスクリプトで複数のコマンド出力を結合する

# やりたいこと
[SoftwareDesignのシェルスクリプト記事](http://gihyo.jp/magazine/SD/archive/2018/201801)を読んでから、シェルスクリプトがちょっとブーム。
いっぱいパイプにつないで喜んでたら、ふと疑問が浮かんだ。
コマンド出力の分岐は伝家の宝刀teeコマンドがある。
じゃぁ結合は？

# 方法１ 一時ファイルに書く

```shell
$ TMP=`tempfile`; echo hoge > $TMP; echo fuga >> $TMP; cat $TMP; rm $TMP
```
まぁ、できてるけども。。。

# 方法２ bashのプロセス置換を使う

```shell
$ cat <(echo hoge) <(echo fuga)
hoge
fuga
```
スマート。
でもbash限定。
そして出力が継続するコマンド~~（何て呼べばいいんだろう）~~に対してはうまく行かない。
 （追記："a continuous streaming command"と言うそうです。@7of9さん、ありがとうございます。）

# 方法３ fifoを使う

```shell
$ mkfifo /tmp/shout
$ echo hoge > /tmp/shout | echo fuga > /tmp/shout | cat /tmp/shout
hoge
fuga
```

fifoだと入力があるまでブロックしてくれるので、バックドア的な使い方ができる。
例えば、標準入出力しかI/FがないインタラクティブなCUIアプリ（QEMUのようなシミュレータとか）に対して、CIから自動テストのトリガをかける時などに使える。

１． CUIアプリ起動時に標準入力を/tmp/shuoutを経由するようにしておく
（CUIアプリの例として下記ではbashにしている）

```shell
$ mkfifo /tmp/shout
$ cat > /tmp/shout | cat /tmp/shout | bash
uname -r
4.13.0-32-generic
```

２．別のターミナルから、/tmp/shoutにコマンドを流しこむ

```shell
$ echo uname -r > /tmp/shout
```

３. １．で起動したCUIアプリにコマンドが入力される
（今回の例ではbash上でコマンドが実行される）

```shell
4.13.0-32-generic
```

手順２．で`nc -lk`などと繋げば他のホストから入力することも可能。
もちろん`echo $'\cC' > /tmp/shout`などとしたら制御文字を送りつけることもできる。

# 結論
bashで単発のコマンド出力を結合するときは、プロセス置換。
bashじゃない、または終わらないコマンド("a continuous streaming command")の出力を結合するときは、fifo。

# 雑感
シェルスクリプトは限られたコマンドを組み合わせて目的を達成するパズル的な楽しさがあるなー。

# 参考
- [シェルの入出力制御あれこれ](https://qiita.com/tag1216/items/7ce35b7c27d371165e56)
- [mkfifoコマンドって使ってますか？](https://qiita.com/richmikan@github/items/bb660a58690ac01ec295)
Kafkaを使ってPDIでリアルタイム処理を実装する

# はじめに
PDIでなるべくリアルタイムに近いタイミングで処理を行ないたいというリクエストがあったので、Pentaho8から実装された「Kafka Consumer」ステップを検証してみました。
これにより、通常バッチ的に利用することを想定しているPDIでもリアルタイムに親しい処理が可能となり、PDIの利用用途が広がるのではないかと思いますので、似たような問題をお抱えの方の役に立てば幸いです。

# Kafkaの準備
Kafkaについては、有益な記事がネット上にたくさんあるのでそれらを活用させていただきました。
今回はMAC上で検証しているので[こちら](http://blog.amedama.jp/entry/2017/04/29/184607)を参考にkafkaの環境を構築しました。

環境構築後、サービスを起動した状態で、トピックを作成しておきます。

```
$ kafka-topics --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test
Created topic "test".
```

# PDIの準備
[こちら](https://qiita.com/mik/items/8a36e8efb06367c82b41)を参考にPDIをインストールし、PDIのETL処理をデザインするクライアントツール(Spoon)を起動します。

# Kafka Consumerステップの設定を行う
## Kafka Consumerステップを配置する
下図のようにKafka Consumerステップを配置して、Transformationを保存します。
名前は、"kafka_test.ktr"としておきます。
![kafkatest1.png](https://qiita-image-store.s3.amazonaws.com/0/186651/661ba25b-ad06-6547-f849-acf166c5c38d.png)

## Kafka Consumerでメッセージを受け取った後に実行するTransformationを作成する
今回は、プロデューサから書き込んだメッセージを受け取った後、そのメッセージをファイルに出力するところまでの検証としたいので、下図のようにTransformationを設定しておきます。
名前は、"kafka_test_sub.ktr"としておきます。
![kafka_test_sub_mod.png](https://qiita-image-store.s3.amazonaws.com/0/186651/7f33292f-a04d-6946-d2c4-c4023d78f1e5.png)

## Kafka Consumerステップの設定を行う
Kafka Consumerステップをダブルクリックすると下図のような画面が表示されるので、設定を行ないます。
それぞれ、左から「Setupタブ」、「Batchタブ」、「Fieldsタブ」の設定となります。
「Batchタブ」では実行タイミングを設定しており、今回は1件でもメッセージを受け取った時点でTransformationを実行するように設定しています。
![kafkatest5_mod.png](https://qiita-image-store.s3.amazonaws.com/0/186651/2edaea4b-b297-bf9e-810d-f977b371d882.png)

# 動かしてみる
Spoon上で"kafka_test.ktr"を実行します。
実行すると、下図のように実行状態で待機します。
![kafka_test_run1.png](https://qiita-image-store.s3.amazonaws.com/0/186651/101b000a-f297-20ae-258b-e6ed02241cc6.png)

この状態で、プロデューサーからメッセージをいくつか投入してみます。

```
$ kafka-console-producer --broker-list localhost:9092 -topic test
> Hello!
> HelloHello!
> HelloHelloHello!
```

すると、以下のようにTransformationが実行されます。
![kafka_test_run2.png](https://qiita-image-store.s3.amazonaws.com/0/186651/1f10be5e-e053-4e84-703f-d6896fd9dafe.png)


出力したファイルの内容を確認してみると、、

```
$ cat output.txt
Hello!
HelloHello!
HelloHelloHello!
```
のようになっており、メッセージを受け取って、Transformationを実行し、ファイルに出力していることが分かるかと思います。
実際に手元で動かすと、ほぼほぼリアルタイムにデータが書き込まれることが確認できると思います。

# まとめ
今回の検証としては以上ですが、動かすだけであれば難しい設定も必要なく実装することができました。
また、パーティションを増やして、今回作成した"kafka_test.ktr"をPan.shで多数起動しておくことで、分散処理も可能になります。
続・Pythonの計算を早くするには

先日投稿した記事 [Pythonの計算を早くするには](https://qiita.com/horitaku1124/items/b6b3e266aed362dcd3bc) の内容についてPythonのコードがC言語に比べて大分遅かった為、改善策はあるのか検証します。

### 最初のコード

```wallis_v2.py
from numpy import *

def f(x):
    return sin(pi*x)

product_array = [0 for i in range(10)]


n = 1000000
inv_n = 1.0 / n
for k in range(n):
    x = k * inv_n
    y = f(x)
    z = y
    for m in range(10):
        product_array[m] += z
        z *= y

product = prod(list(map(lambda x: x * inv_n, product_array)))
result = 1.0/product
print(result)
```
初回の実行時に最適化が動くようなので、２回目以降の値を参考にします。

```
$ time python3 wallis_v2.py
36722.3621743
python3 wallis_v2.py  8.96s user 0.05s system 99% cpu 9.050 total
```

### importの最適化
まず`import`の部分を使用するモジュールに限定します。

```.py
from numpy import prod
from math import sin, pi
```

```
$ time python3 wallis_v2.py
36722.3621743
python3 wallis_v2.py  7.67s user 0.06s system 99% cpu 7.755 total
```
1秒以上早くなりました。

### Cythonの使用
#### pyxファイルへの分割
次にCythonを導入します。その為に処理自体をpyxファイルに分割します。

```wallis_v3.py
import pyximport
pyximport.install()

from integral_lib import integral

print(integral(1000000))
```

```integral_lib.pyx
from numpy import prod
from f import f

def integral(n):
  product_array = [0 for i in range(10)]
  inv_n = 1.0 / n
  for k in range(n):
    x = k * inv_n
    y = f(x)
    z = y
    for m in range(10):
      product_array[m] += z
      z *= y

  return 1 / prod(list(map(lambda x: x * inv_n, product_array)))
```
```f.pyx
from math import sin, pi

def f(x):
  return sin(pi * x)
```


```
$ time python3 wallis_v3.py
36722.3621743
python3 wallis_v3.py  1.05s user 0.06s system 98% cpu 1.134 total
```
大分早くなりました。

#### 静的型付
```f2.pyx
from math import sin, pi

def f(double x):
  cdef:
    double res = sin(pi * x)
  return res
```
```integral_lib2.pyx
from numpy import prod
from f2 import f

def integral(int n):
  product_array = [0.0 for i in range(10)]

  cdef:
    double inv_n = 1.0 / n
    double x,y,z
    int k
  for k in range(n):
    x = k * inv_n
    y = f(x)
    z = y
    for m in range(10):
      product_array[m] += z
      z *= y

  return 1.0 / prod(list(map(lambda x: x * inv_n, product_array)))
```

```wallis_v3.py
from integral_lib2 import integral
```

```
$ time python3 wallis_v3.py
36722.3621743
python3 wallis_v3.py  0.80s user 0.06s system 97% cpu 0.884 total
```
早くできました。
参考にした記事中にlibcを呼び出す方法が紹介されていたので試して見ました。一応早くなっています。

```f2.pyx
from libc.math cimport sin,M_PI

def f(double x):
  cdef:
    double res = sin(M_PI * x)
  return res
```

```
$ time python3 wallis_v3.py
36722.3621743
python3 wallis_v3.py  0.72s user 0.06s system 97% cpu 0.802 total
```

初期のコードでは22秒だったものが、0.8秒ほどまで高速化することはできましたが、コードの保守性などを考えるとこれがベストと云うわけではありませんので、適宜選んでください。


### 参考
[Cython : C との融合による高速化](http://qh73xebitbucketorg.readthedocs.io/ja/latest/1.Programmings/python/LIB/cython/main/)
ESPr DeveloperにESP8266 Arduino Core 2.4.0を使ってスケッチを書き込んだら不具合が起きた時の直し方

## ESP8266 Arduino Core 2.4.0の不具合
[ESPr Developer](https://www.switch-science.com/catalog/2500/)をArduinoでプログラミングする場合、通常Arduinoのボードマネージャから[ESP8266 Arduino Core](https://github.com/esp8266/Arduino)を使います。
ところが、つい最近(2018/1/30現在)リリースされたバージョン2.4.0をインストールした場合、このバージョンでコンパイルしたスケッチをESPr Developerに書き込んだところ、2.3.0のときまで問題なく動いていたものが正しく動かなくなりました。

## 不具合の事例

2.4.0を使ったらこんな不具合が起きました。

* 電源を供給した後、明示的にESPr Developer本体のリセットボタンを押さないと起動しない。
* `WiFi.mode(WIFI_STA)`のあとに`int n = WiFi.scanNetworks()`とした場合、アクセスポイントが見つかれば`n`は`1`以上になるはずなのに、常に`0`になってしまう。`WiFi.begin()`なども失敗する。

## 直し方
2.4.0で動きがおかしくなったときにはこうします。

- **ボードマネージャでesp8266 by ESP8266 Communityのバージョン2.4.0rc1をインストールする。**
- **当該スケッチを書き込み直す**

特に2.4.0にしてからWi-Fi接続がうまくいかない場合には、いきなり以前使っていた2.3.0に戻しても症状は変わらず、2.4.0rc1にして再度スケッチを書き込むことでのみ復旧させること出来ました。
(他にesptoolでフラッシュを書き換える方法があるのかも知れませんが試していません)
Node.jsでCPUコアをフルに使って負荷の高い処理ができるかなと思ったらできた

ちきさんです。

Node.jsでCPUコアをフルに使って負荷の高い処理ができるかなと思ったのでやってみました。
cluster APIを使って書いています。

APIの使い方が正しいかどうかはわかりませんが、`loadSize`を大きい数字にするとCPUファンがガンガン回るので楽しいです。

```super-power.ts
import * as cluster from 'cluster'
import { Subject } from 'rxjs/Rx'
const numCPUs = require('os').cpus().length

interface Message {
  pid: number
  value: number
}


function superPower(): Promise<number[]> {
  const queue$: Subject<number[]> = new Subject()
  let finishCount: number = 0

  for (let i = 0; i < numCPUs; i++) {
    cluster.fork()
  }

  cluster.on('exit', (worker) => {
    console.log(`worker ${worker.process.pid} died`)
  })

  cluster.on('message', (worker, message) => {
    console.log(`message: ${JSON.stringify(message)} from ${worker.id}`)
    queue$.next(message.value)
    if (++finishCount === numCPUs) {
      cluster.disconnect() // Workerをシャットダウンする。
      queue$.complete() // このタイミングでこの関数の戻り値が返される。
    }
  })

  return queue$
    .startWith([])
    .reduce((p, value) => p.concat(value))
    .toPromise()
}


function workWorkWork(): void {
  const loadSize: number = Math.round(Math.random() * 10000000000)
  let temp = 0
  // CPUコアに負荷をかける。
  for (let i = 0; i < loadSize; i++) {
    temp = temp + i
  }
  const message: Message = { pid: process.pid, value: loadSize }
  process.send!(message)
}


if (cluster.isMaster) {
  superPower()
    .then(value => {
      console.log('result:', value)
    })
} else {
  workWorkWork()
}
```

出力はこんな感じ。

```txt:OUTPUT
message: {"pid":79291,"value":1039512909} from 5
message: {"pid":79289,"value":2097703303} from 3
message: {"pid":79287,"value":3289584265} from 1
message: {"pid":79290,"value":4997136338} from 4
message: {"pid":79288,"value":6719233976} from 2
message: {"pid":79292,"value":7072344527} from 6
message: {"pid":79293,"value":8830078665} from 7
message: {"pid":79294,"value":8978470370} from 8
result: [ 1039512909,
  2097703303,
  3289584265,
  4997136338,
  6719233976,
  7072344527,
  8830078665,
  8978470370 ]
worker 79288 died
worker 79291 died
worker 79290 died
worker 79292 died
worker 79293 died
worker 79289 died
worker 79287 died
worker 79294 died
```
macOSでcat, echoでシリアル通信する

catやechoでファイルに読み書きするみたいにシリアルポートを扱えると、簡単なシェルスクリプトからシリアル通信を行えるセンサ, 測定器, Arduinoでつくった自作のハードウェアなど通信ができて便利そうなので、やり方を検証してみました。

# 用意したもの

- Mac: MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports), macOS Sierra
- USBシリアル変換: スイッチサイエンスの[FTDI USBシリアル変換アダプター Rev.2](https://www.switch-science.com/catalog/2782/)
  - Amazonなどでゴミのような値段のも出回ってますが、やはり素性がはっきりしてるものを使うのが安心です
  - 小さいArduinoに似てますが、これ自体はArduinoではありません（ArduinoUnoのATMega328がパソコンとUSBで通信する部分だけを抜き出したようなもの）

# デバイスの準備

実験用に通信相手を用意するのがめんどくさかったので、写真のようにTxとRxを直結して信号をループバックさせます。

![IMG_3552.jpg](https://qiita-image-store.s3.amazonaws.com/0/26038/d6a4f826-366c-0f04-e44e-02d92203d081.jpeg)

こうすると、Macから送信した通信内容がそのままMacで受信できます。


# 通信してみる

macOSではシリアルポートが`/dev/tty.usbserial-DN0123RB`と`/dev/cu.usbserial-DN0123RB`のように2つのデバイスとして認識されますが、今回は`cu`がついているほうを使います。


**受信側**

```shell-session
$ sudo stty -f /dev/cu.usbserial-DN0123RB raw 9600    # シリアルポートの設定を行います
$ cat /dev/cu.usbserial-DN0123RB
```

**送信側**

```shell-session
$ echo 'Hello, World!' | sudo tee /dev/cu.usbserial-DN0123RB
Hello, World!
```

受信側に、

```
Hello, World!
```

と出てきたら成功です。


# 余談

以前、メディア芸術をやっている人を意識して[ArduinoとProcessingの通信方法の記事を書いたら](https://qiita.com/miminashi/items/491ff1968725eec45d84)少し反響があったのですが、複数個のArduinoをMacからの指示で動かすみたいな作品を作りたくなったとき、現状だとMaxとかを使うんでしょうか、とにかく高価なソフトなので、シェルスクリプトでちょいちょいっとできたら安上がりだし便利そうかなと思いました。
シェルスクリプトだと展示するときはMacを安価なRaspberryPiなんかに置き換えることもできますね。
そのうちそういう感じの記事も書いてみようと思います。
iOSのSpotlight検索でアプリがHitしなくなった時の対応

# 環境

iOS 11.2.2

# 対応方法

- 「設定」→「Siriと検索」で画面下部に表示されているアプリ一覧から対象アプリを選択する
- 「検索と"Siriからの提案"」をONにする

# 雑記

設定変更した覚えは無いんだけど「オフ」になってた。
たまにしか使わないので設定方法を忘れないようにメモしておく。
大きさの異なる1列に並んだ結合セルから連続で値を抽出


大きさの異なる1列に並んだ結合セルから連続で値を抽出した際のノート．

## 結果 

![イメージ: 大きさの異なる並んだ結合セルから連続で値を抽出](https://qiita-image-store.s3.amazonaws.com/0/43136/434b39cc-4286-5419-857d-055919196ade.png)


- 結合セル（抽出対象）: **B3:B29**
- インデックス（直接入力）: **D3:D9**
- 抽出結果（配列数式）: **E3:E9**

## 数式 
<pre>=OFFSET(
  $B$3, 
  SMALL(
    IF(
      ISBLANK($B$3:$B$29), 
      9E+9, 
      ROW($B$3:$B$29)-ROW($B$3)
    ), 
    D3
  ), 
)</pre>

以上をE3セルへ配列数式として入力（Ctrl+Shift+Enter）．
E4セル以下はE3セルのコピー＆ペーストで可能．
##### 補足: 
- 9E+9は入力されると9000000000に自動で変換されます．
- セル行数よりも十分に大きな値を簡単に入力するため9E+9としています．十分に大きな値であれば他の値でも問題ありません．

## 解説
### 前置き
- セルアドレスを文字列に置き換えて表現  
<pre>=OFFSET(
      結合セル全体の先頭セル, 
      SMALL(
        IF(
          ISBLANK(結合セル全体), 
          9E+9, 
          ROW(結合セル全体)-ROW(結合セル全体の先頭セル)
        ), 
        インデックス
      ), 
)</pre>
- 結合セルについて  
結合セルはそれぞれの結合セルの先頭のセルしか値を保持しておらず，残りのセルは空白になっています．これはセルの結合を解除すると解ります．  
![2018-01-28_22h46_00.png](https://qiita-image-store.s3.amazonaws.com/0/43136/026f555d-c8b7-b549-5267-7a4d2dcee537.png)


以下，数式処理の流れに沿って内側の関数から順を追って数式を説明します（IF > SMALL > OFFSETの順）．

### (1) オフセット行数配列の取得  
IF関数を使用し，空白ではないそれぞれの結合セルの先頭セルについて，その行番号を元に結合セル全体の先頭セルからのオフセット行数配列を取得します．空白セルについてはオフセット行数の代わりに9E+9を取得します．
<pre>IF(
      ISBLANK($$結合セル全体),                       <- セルが空白か判別
      9E+9, 　　　　　　　　　　　　　　　　　　　　　  <- セルが空白の場合，9E+9とする
      ROW($$結合セル全体)-ROW($$結合セルの先頭のセル)  <- セルが空白ではない場合，オフセット行数配列を取得
)</pre>  


IF関数を使用した場合と使用しない場合の例を以下に示します．
※どちらも配列数式です．

  - IF関数を使用した場合  
     <pre>IF(
      ISBLANK($B$3:$B$29), 
      9E+9, 
      ROW($B$3:$B$29)-ROW($B$3)
    )
    > {0; 9E+9; 9E+9; 9E+9; 9E+9; 9E+9; 9E+9; 7; 9E+9; 9E+9; 9E+9; 11; 9E+9; ...}</pre>
  - IF関数を使用しない場合  
     <pre>ROW($B$3:$B$29)-ROW($B$3)
> {0; 1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12;  ...}</pre>


### (2) 取得されたオフセット行数配列から指定番目に小さなオフセット行数を取得
指定番目に小さなオフセット行数を取得するためSMALL関数を使用します．
SMALL関数の書式は次のとおりです．
書式: `SMALL(範囲,順位)`
[SMALL 関数 - Office サポート](https://support.office.com/ja-jp/article/small-関数-17da8222-7c82-42b2-961b-14c45384df07)

SMALL関数の内部処理は不明ですが，実際に配列を昇順に並び替えて考えるとわかりやすいと思います．
並び替えた際に先程振り分けた"9E+9"は全てのオフセット行数よりも十分に大きいため，配列の後方に配置されます．

- 並び替え前 
{<font color="red">0</font>; 9E+9; 9E+9; 9E+9; 9E+9; 9E+9; 9E+9;    <font color="red">7</font>; 9E+9; 9E+9; 9E+9;   <font color="red">11</font>; 9E+9; ...}  
  
- 並び替え後 
{<font color="red">0</font>;    <font color="red">7</font>;   <font color="red">11</font>;   <font color="red">12</font>;   <font color="red">18</font>;   <font color="red">19</font>;   <font color="red">21</font>; 9E+9; 9E+9; 9E+9; 9E+9; 9E+9; 9E+9; ...}  

次に，1~7のインデックス値が入力されたセル（D3:D9）を利用して，指定番目のオフセット行数を取得します．

  1. `SMALL((1)で取得されたオフセット行数配列, D3) > 0`  
  2. `SMALL((1)で取得されたオフセット行数配列, D4) > 7`  
  3. `SMALL((1)で取得されたオフセット行数配列, D5) > 11`  
  ︙


### (3) 取得されたオフセット行数を元に結合セルの値を取得
最後にOFFSET関数を使用して，先程取得された結合セルの先頭セルからのオフセット行数を元に結合セルの値を取得します．
書式: `OFFSET(基準, 行数, 列数, [高さ], [幅])`
[OFFSET 関数 - Office サポート](https://support.office.com/ja-jp/article/offset-%E9%96%A2%E6%95%B0-c8de19ae-dd79-4b9b-a14e-b4d906d11b66)

`OFFSET($B$3, (2)で取得されたオフセット行数, ) > 結合セルの値`

  1. `OFFSET($B$3,  0, ) > A`  
  2. `OFFSET($B$3,  7, ) > B`  
  3. `OFFSET($B$3, 11, ) > C`  
  ︙