OmniAICreator/Qiita-1.07M huggingface dataset:
日時タプルを文字列に変換

Ecto等で取得した日時は、{ { 2018, 1, 26 }, { 0, 17, 53 } }のような、タプルとなっているため、Web上でそのまま表示できないので、文字列に変換してあげる必要がある

Elixirらしく、値の型を、関数のガード節で呼び分けする

```ex
defmodule On do
	def view( dt_tuple ) when is_tupl( dt_tuple ) do
		dt_tuple 
		|> Timex.to_datetime 
		|> DateTime.to_string 
		|> String.slice( 0..-2 )
	end
	def view( value), do: value
end
```

Phoenix等で実際に使う際は、こんな感じ

```html
<table>
<tr>
<%= for caption <- map_list |> List.first |> Map.keys() do %>
	<th><%= caption %></th>
<% end %>
</tr>
<tr>
<%= for record <- map_list do %>
	<%= for column <- record |> Map.keys() do %>
	<td><%= record[ column ] |> On.view %></td>
	<% end %>
<% end %>
</tr>
</table>
```

p.s.福岡でElixirプロダクション採用を推進するコミュニティ「fukuoka.ex」のMeetUp#5「福岡におけるElixirの進化」は、こんな感じでワイワイやっています（地味に女子率多し）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/155423/5cb7f306-5e5b-bbf1-1173-e07d5f1c3479.png)
PostgreSQLのCOPYコマンドでnullを登録するには

「WITH NULL 'null_string'」を付ける。

```csv:DATA.csv
1,name1,10
2,name2,null_string
```

```sql:example
copy テーブル名 from 'C:\Data.csv' DELIMITERS ',' WITH NULL 'null_string'
```

* [PostgreSQL 9.4.5文書](https://www.postgresql.jp/document/9.4/html/sql-copy.html)
cat | while read line のループがうまく回ってくれないとき

やりたいこと
--------


シェルスクリプトで、受け取ったデータについて一行ずつ何らかの処理をしたくなりました。


典型的なやり方
----------

while に標準入力を流し込んで、 read コマンドで一行ずつ受け取れます。

```shell:スクリプト１
printf "a\nb\nc\n" | while read line
do
    echo data: $line
done
```

無事、こんな出力が得られるはずです。

```text:出力１
data: a
data: b
data: c
```

処理を増やしたくなりました。例えば cat を差し込みます。

```shell:スクリプト２
printf "a\nb\nc\n" | while read line
do
    echo data: $line
    cat
done
```

きっと想像がつくと思いますが、このループはあまり思ったとおりには動きません。一度しか回らないです。

```:出力２
data: a
b
c
```

おそらくこんな形で cat をわざわざ挟む人はいないと思います。
しかし、他にも同じような挙動が発生するコマンドは色々ありそうです。
例えば気付かず使いそうになるかもしれないコマンドとして、 **`ssh`** があります。

```shell:スクリプト３
printf "a\nb\nc\n" | while read line
do
    echo data: $line
    ssh sakura "echo from sakura: $line"
done
```

ssh 先で３回コマンドを実行したいと思っていたのですが、一度しか実行されませんでした。

```:出力３
data: a
from sakura: a
```


どうしよう？
--------

データのサイズがあまり大きくないのであれば、 for を使ってしまうのが一つの手です。

```shell:スクリプト４
for line in a b c
do
    echo data: $line
    ssh sakura "echo from sakura: $line"
done
```

```:出力４
data: a
from sakura: a
data: b
from sakura: b
data: c
from sakura: c
```

しかし場合によっては、どうしても標準入力から一行単位ごとにループしたい、あるいは入力サイズがでかすぎてループ前に全部展開したくないというような場合もあるかもしれません。
そういう場合は、標準入力を陽に潰してやることもできます。

```shell:スクリプト５
printf "a\nb\nc\n" | while read line
do
    echo data: $line
    ssh sakura "echo from sakura: $line" </dev/null
done
```

```:出力５
data: a
from sakura: a
data: b
from sakura: b
data: c
from sakura: c
```

思った通りの出力が得られました。


おまけ
----

ssh の標準入出力のやり取りは意外と便利です。

１ファイルを転送するくらいなら、 ssh と cat だけでなんとなくできてしまいます（この例だと SCP を使わない理由があまりありませんが…）。

```shell
cat a.png | ssh sakura "cat >a.png"
```


ディレクトリの転送も頑張ればできます。

```shell
tar -zcf - docs/ | ssh sakura tar -zxf -
```
テレビの番組表(アニメ)取得APIについて色々

#はじめに
この記事は2018年1月26日の情報になっています。
また、こんなサイトもあるよとかあればコメント頂けると非常にありがたいです。

#背景
番組表をAPIとかで取得出来たら面白い事いっぱい出来そうだな…と調べ始めたのがキッカケ
見つけたものを備忘録的な感じでまとめたかったので記事作成

#発見したAPI
##NHK
http://api-portal.nhk.or.jp/
 google先生に聞くと大体これが出てくる。
 
##アニマップ
http://animemap.net/pages/api/
どうやら2015年の春頃から更新が止まっているっぽい…

##しょぼいカレンダー
http://cal.syoboi.jp/
いろいろ探していたらたどり着いた。
ヘルプページ(https://sites.google.com/site/syobocal/home )にjsonで情報取得出来る様な事が書いてある。
情報は手動更新みたいだけど、現時点で更新されているし、使うならここかなと。
モチベーションがあれば簡単な使い方を学んで記事にしたい。

#おわりに
案外無かった。
Yahoo!とかどこからあの情報持って来ているのか。
テレビだと普通に番組表(EGPというらしい)取得できるんだから、何とか取ってこれないんでしょうか…
zaleniumの起動・停止制御を行うスクリプト

自分の環境のみかもしれないけど、Zaleniumとphpunitを長時間稼働、長時間テスト実行しているとメモリ不足でエラーが出まくるので対策として起動・停止を外から管理できるようなbashスクリプトを作ってみた
zaleniumについては以下参照
[zaleniumのgithub](https://github.com/zalando/zalenium)
現状、zalenium止めたらメモリは復活するから原因の特定はやらない予定
※`/opt/docker_volume/`は共有用の場所

```bash:script
#!/bin/bash

# status:
#   stop    : stop zalenium
#   run     : start zalenium
#   running : no touch

function start_zalenium() {
    # 起動してたら止める
    stop_zalenium
    docker pull elgalu/selenium
    docker pull dosel/zalenium
    # start zalenium container
    docker run --rm -i --name zalenium -p 4444:4444 -v /var/run/docker.sock:/var/run/docker.sock -v /opt/docker_volume/zalenium:/home/seluser/videos --privileged dosel/zalenium start --timeZone 'Asia/Tokyo' --debugEnabled true
}

function stop_zalenium() {
    if_value=$(docker ps -a | grep -c "zalenium")
    if [[ "$if_value" != "0" ]]; then
        docker ps -a | grep "zalenium" | awk '{print $1}' | xargs docker stop
    fi
    echo "#---------------#"
    echo "# zalenium stop #"
    echo "#---------------#"
    echo ""
}

function execute() {
    ZALENIUM_SCRIPT_STATUS_FILE="zalenium_script_status"
    touch $ZALENIUM_SCRIPT_STATUS_FILE
    while [[ -f "$ZALENIUM_SCRIPT_STATUS_FILE" ]]; do
        now_status=$(head -n1 $ZALENIUM_SCRIPT_STATUS_FILE)
        if [[ "$now_status" == "run" ]]; then
            start_zalenium &
            echo "running" > $ZALENIUM_SCRIPT_STATUS_FILE
            # 停止まで適当に待つ
            sleep 300
        elif [[ "$now_status" == "stop" ]]; then
            echo "stoped" > $ZALENIUM_SCRIPT_STATUS_FILE
            stop_zalenium
        fi
        sleep 1
    done
}

execute
```

一番最初はこれを起動しておいて、テスト実行するときのスクリプトに`echo "run" > zalenium_script_status`みたいなのを最初に、テスト終了後に`echo "stop" > zalenium_script_status`を実行するように仕込めば動くはず
本当にzaleniumが原因なのかは不明だけど、とりあえずこれで土日放置できる。。。
facet.queryをつかったファセットの操作


検索クエリとは別にfacet.queryを使って、ファセットの絞込ができるのを最近しった。  
実はsolr5.3からついてたみたい。

<!--more-->

### excludeTagによる除外
```
q=動物
fq={!tag=cat}category:ネコ科
facet=true
facet.field={!ex=cat}category
```

fqにタグをつけてfacetのところにexで参照させると、facetカウントから除外することができる。
これをするとクエリ動物での検索結果とそのうちネコ科のステータスを抜いた(exclude)ものがfacetのカウントになる。

### ファセットを更に絞り込んだ値にする。

```
q=動物
facet.query={!tag=q1}category:ネコ科
facet=true
facet.field={!query=q1}category
```
今度は動物の検索結果で、ファセットにはネコ科のものだけがカウントされるようになる。
facet.queryに指定してそれにtagをつけて、それをfacet.fieldのパラメーターの中にlocalparamの要領
で使って行くらしい。ちなみに、pivotとかにもくっつける事ができる。

パフォーマンスはあまりよくないので、いろいろデータを見ているときに利用する感じかな。
スキーマと表示データが固まった状態なら、検索にヒットさせるように加工しておいたほうが本番環境は良さそう。

ファセットを見ていて、特定の属性以外のものだけみたい！とか、データをパッと見るのは便利そう。
覚えておこう。

- [Solr Ref Guide 6.6](https://lucene.apache.org/solr/guide/6_6/faceting.html)  
- [Multi-Select Faceting](http://yonik.com/multi-select-faceting/)
Wright-Fisher モデル（集団遺伝学）

今回は集団遺伝学で最も基本的なWright-Fisher モデルを実装したものを投稿させて頂きました。
現在いる一つの集団の中から、ランダムに選ばれた、
数人からなる子孫たちのただ一人の共通祖先を辿るモデルです。
プログラムでは、離散から連続へ滞在時間の分布が収束することが確認できます。
このモデルでは、親同士によって子孫を産む性質が変わらないという、可換モデルの性質を満たしています。

```{r}
#wright fisher model

 rm(list=ls())

#ancestral process
sample=10
N=1000

G=array(0,dim=c(sample,sample))
for(j in 1:sample){
  
  G[j,j]=prod(c((N-j+1):N)/rep(N,j))
  
  G[j-1,j]=((j*(j-1))/(2*N))*prod(c((N-j+2):N)/rep(N,j-1))

}
G=t(G)

Q_N=array(0,dim=c(sample,sample))
for(j in 1:sample){
  Q_N[j,j]=-(j*(j-1))/(2*N)
  Q_N[j-1,j]=j*(j-1)/(2*N)
}
Q_N=t(Q_N)

order_N=G-diag(sample)-Q_N
#generation_process
time=20 #initial_time=0
matrix=(eigen(G)$vectors)%*% (diag(eigen(G)$values)^time)%*%(solve(eigen(G)$vectors))
matrix[abs(matrix)<(1/10^6)]=0

#waiting_time
wait_time=500
state=8
wait_time_data=data.frame(time=1:wait_time,prob=0,Q_prob=0)

for(j in 1:nrow(wait_time_data)){
wait_time_data$prob[j]=G[state,state]^wait_time_data$time[j]
wait_time_data$Q_prob[j]=exp(Q_N[state,state]*wait_time_data$time[j])
}

plot(wait_time_data$time,wait_time_data$prob,type="p",col=2,xlim=c(min(wait_time_data$time),max(wait_time_data$time)),ylim=c(min(wait_time_data$prob,wait_time_data$Q_prob),max(wait_time_data$prob,wait_time_data$Q_prob)),xlab="time",ylab="prob",main="Wright_Fisher;Red:discrete , Green:continuous")
par(new=T)
plot(wait_time_data$time,wait_time_data$Q_prob,type="p",col=3,xlab="time",ylab="prob",main="Wright_Fisher;Red:discrete , Green:continuous",xlim=c(min(wait_time_data$time),max(wait_time_data$time)),ylim=c(min(wait_time_data$prob,wait_time_data$Q_prob),max(wait_time_data$prob,wait_time_data$Q_prob)))

coalescent_tree=data.frame(sample_number=1:sample,T_MRCA=0,T_total=0) %>% dplyr::mutate(av_T_MRCA=2*(1-(1/sample_number)),av_T_total=0)
T_MRCA=0;T_total=0;av_T_total=0
for(j in 2:nrow(coalescent_tree)){
   k=j
    T_MRCA=T_MRCA+rexp(1,rate=abs(Q_N[k,k]*N))
    T_total=T_total+sum(rexp(k,rate=abs(Q_N[k,k]*N)))
    av_T_total=av_T_total+2/(k-1)
  coalescent_tree$T_MRCA[j]=T_MRCA
  coalescent_tree$T_total[j]=T_total
  coalescent_tree$av_T_total[j]=av_T_total
}

```
Laravel5.5から5.6へのアップデートでやったこと

主にバッチ処理のartisanコマンドとLaravelDuskを使うプロジェクトを試しに5.5から5.6へのアップデートしたのでその作業メモ。
今回のアップグレードは基本部分は数十分程度で可能な模様
[Upgrading To 5.6.0 From 5.5](https://laravel.com/docs/5.6/upgrade)

## ライブラリのアップデート

#### プロジェクトのcomposer.jsonの更新
```
"require": {
    "php": ">=7.1.3",
    "fideloper/proxy": "~4.0",
    "laravel/framework": "5.6.*",       
},
"require-dev": {
    "laravel/dusk": "~3.0",
    "nunomaduro/collision": "~1.1",
    "phpunit/phpunit": "~7.0",
},  
```
#### ついでにcomposer global用のcomposer.jsonで、Laraveのインストーラも更新
```
"require": {
    "laravel/installer": "~2.0",
}
```

## 以下configファイルの差分

#### 新規追加のconfigファイルをコピー
```
config/hashing.php
config/logging.php
```

##### ログ設定が別ファイルに別れたので、config/app.phpの ログ設定部分を削除
```
    |--------------------------------------------------------------------------
    | Logging Configuration
    |--------------------------------------------------------------------------
```

#### config/filesystems.phpに設定項目が追加
```
'disks' => [
    's3' => [
        'url' => env('AWS_URL'),
    ]        
]   
```

#### config/queue.phpに設定項目が追加
```
'connections' => [
    'redis' => [
        'block_for' => null,
    ],    
]          
```

## プログラム的な修正
* Upgrade Guideを元に、Illuminate\Log\Writerクラスが、Illuminate\Log\Loggerに変更となっていたので修正。

これでひとまずartisanコマンドとLaravelDusk動作まで確認した。

2/14日現在だと、PHPUnitでcollisionライブラリを使うのはしばらく待つ必要がありそう。
[nunomaduro/collision Support PHPUnit 7](https://github.com/nunomaduro/collision/issues/41)
7-Zipの解凍パスワードを自動入力

パスワード入力ダイアログが表示された状態でスクリプト実行。
引数はコマンドラインで与える。

パスワードが正しければ「OK」をクリックするところまで自動化。

```python
from pywinauto.application import Application
import zipfile
import sys

fmpath=r'C:\Program Files\7-Zip\7zFM.exe'

def checkpw(path, pw):
    with zipfile.ZipFile(zipfilepath) as z:
        # choosing file of minimum size (> 0)
        fs = 0
        for i in z.infolist():
            if not i.is_dir():
                if fs == 0 or i.compress_size < fs:
                    fn = i.filename
                    fs = i.compress_size
        if fs > 0:
            try:
                with z.open(fn, pwd=pw.encode('utf-8')) as f:
                    return True
            except RuntimeError:
                pass
        return False

if __name__ == '__main__':
    app = Application().connect(path=fmpath)
    pathlist=app.FM.Edit.texts()
    if len(pathlist) > 0:
        zipfilepath=app.FM.Edit.texts()[0].rstrip('\\')

    pw=sys.argv[1]
    if checkpw(zipfilepath, pw):
        app.Dialog.Edit.set_text(pw)
        app.Dialog.OK.click()
```
ancestryが作り出すSQLがちょっとおもしろい

AncestryはActiveRecordと一緒に使うと階層データを簡単に扱うことができますが、そのやり方がちょっとおもしろいのです。
次のような階層的データを作ってみました。

```
+---+----+---------+
|id |name|ancestry |
+---+----+---------+
| 1 | A  |         |
| 2 | B  | 1       |
| 3 | C  | 1/2     |
| 4 | D  | 1/2/3   |
| 5 | E  | 1/2/3   |
| 6 | F  | 1/2/3/4 |
| 7 | G  | 1       |
| 8 | H  | 1/7     |
+---+----+---------+
```

階層を記録しているancestryはString型になっています。なぜString型にしているのか不思議だったのですが、

```ruby:
require "active_record"
require "ancestry"

ActiveRecord::Base.establish_connection(
    adapter: "sqlite3",
    database: "test_ancestry/db/development.sqlite3"
    )

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true
end

class Tree < ApplicationRecord
    has_ancestry
end

ActiveRecord::Base.logger = Logger.new(STDOUT)
p tc=Tree.find_by(name: "C")
p tc.ancestors
p tc.descendants
```

実行してみますと
p tc=Tree.find_by(name: "C")

```
DEBUG -- :   Tree Load (0.6ms)  SELECT  "trees".* FROM "trees" WHERE "trees"."name" = ? LIMIT ?  [["name", "C"], ["LIMIT", 1]]
#<Tree id: 3, name: "C", ancestry: "1/2">
```

上の階層を取り出すと
p tc.ancestors

```
DEBUG -- :   Tree Load (0.5ms)  SELECT  "trees".* FROM "trees" WHERE "trees"."id" IN (1, 2) ORDER BY coalesce("trees"."ancestry", '') LIMIT ?  [["LIMIT", 11]]
#<ActiveRecord::Relation [#<Tree id: 1, name: "A", ancestry: nil>, #<Tree id: 2, name: "B", ancestry: "1">]>
```
ancestryが "1/2"であるからidが1と2を取り出しています。

下の階層を取り出すのはどうするのだろうか？
複数の階層があるのですが、
p tc.descendants


```
 DEBUG -- :   Tree Load (0.2ms)  SELECT  "trees".* FROM "trees" WHERE ("trees"."ancestry" LIKE '1/2/3/%' OR "trees"."ancestry" = '1/2/3') LIMIT ?  [["LIMIT", 11]]
#<ActiveRecord::Relation [#<Tree id: 4, name: "D", ancestry: "1/2/3">, #<Tree id: 5, name: "E", ancestry: "1/2/3">, #<Tree id: 6, name: "F", ancestry: "1/2/3/4">]>
```

なるほど、LIKE '1/2/3/%'と'1/2/3'とすることで、一度に取り出しています。
ancestryがString型なので簡単にできるのか。
EXCELの平方メートル、立方メートルは少なくとも3通りの表記があり文字コードが違う

#実証コード
平方メートルについて作成します
Excel 2010以降ですたぶん。これは後から書きます。

```vb.net
Sub MakeSuqreMeter()
Range("A1:C5").Clear
Range("A1").Select
ActiveCell.FormulaR1C1 = "m" & ChrW(&HB2) '本当は00B2だが00は自動的にカットされる
Range("B1").Value = "ラテン補助文字の2。コードは&H00B2。単体でも文字として扱われる。もともとのExcelはこちらを使用していたらしい。"
Range("A2").Select
ActiveCell.FormulaR1C1 = ChrW(&H33A1)
Range("B2").Value = "記号としての平方メートル"
Range("A3").Select
ActiveCell.FormulaR1C1 = "m2"
With ActiveCell.Characters(Start:=2, Length:=1).Font
.Name = "ＭＳ Ｐゴシック"
.FontStyle = "標準"
.Size = 11
.Superscript = True
End With
Range("B3").Value = "上付き文字に変換。このときの文字コードは&H0032。単体では数字。また行の高さが自動的に拡大する。"
End Sub
```

#3つある理由
##一番古いものはラテン1補助文字か
ラテン1補助ユニコード00B2 名前SuperScript 2
の上付き文字の2が存在する
[１０の３乗の入力方法について](https://oshiete.goo.ne.jp/qa/2802359.html)
IME2002、OfficeXP以降なら
「挿入」「記号と特殊文字」でコード体系を「Unicode(16進)」にして
種類「ラテン1補助」と「上付き/下付きの文字」にある数字を挿入する。
上記はUnicodeにしないと出てきませんのでご注意ください。

[Excel2003の使用で特殊文字の上付き文字](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q119549006)
というのがあるので、こちらが古いもののようだ。

##書式設定で上付き文字にする
これは数字なので、単体では数字になる。コードは&H0032
少なくともExcel2003からできる。

##CJK文字の単位記号
セルの書式設定
[2の3乗のような上付き表示 (tp0031)](http://www.excel.studio-kazu.jp/tips/0031/)
[平方メートルや立方メートルなどの特殊記号を入力する方法]( https://support.microsoft.com/ja-jp/help/882904)
この解説はWordだがExcelでも使える。CJK 互換文字で単位記号として挿入する。このコードは&H33A1。

##3つのコードを取り扱えるのは
おそらく完全にユニコードに移行したWindows7+Office2010以降でないと確実に動かせない。逆にラテン1補助はXpでも上付き文字が表示できる。逆にいうとラテン1補助が一番互換性が高いのかもしれない。

##検索・痴漢で要注意
また、検索・置換でも実はこの文字コードの違いで検索・置換が失敗するので、意識しておかないと単位の上付き数字が検索・置換できないときが発生する。
reactサンプルコード

➀html内のappタグにCounterAppコンポーネントを挿入準備

```react.js
ReactDOM.render(
<CounterApp/>,
document.getElementById("app")
);
```
⓶初期化。constructor(props)、super(props)はおまじないみたいなもん。

```react.js
constructor(props){
  super(props);
  this.state = { count: 0 };
  this.countUp=this.countUp.bind(this);
  }
```
⓷this.state.countでthis.state = { count: 0 };を呼び出し、０にセット。onClick={this.CountUp}でCountUpメソッド実行。this.state.hogeは内部から参照するときに使う。（外部からなら、this.props.hoge）

```react.js
render (){
   return(
      <div>
       <p>count:{this.state.count}</p>
       <button onClick={this.CountUp}>Count Up!</button>
      </div>
    );
```

④this.setStateで、初期化したthis.stateの値を「this.state.count + 1」に更新する。
このとき「this.state＝this.state.count + 1」のようにthis.stateを直接更新してはいけない。


```react.js
CountUp(){
  this.setState({ count: this.state.count + 1 });
  }
```



↓全体の流れ


```react.js
class CounterApp extends React.Component{
 constructor(props){
  super(props);
  this.state = { count: 0 };
  this.countUp=this.countUp.bind(this);
  }
CountUp(){
  this.setState({ count: this.state.count + 1 });
  }
   render (){
   return(
      <div>
       <p>count:{this.state.count}</p>
       <button onClick={this.CountUp}>Count Up!</button>
      </div>
    );
  }
}

ReactDOM.render(
<CounterApp/>,
document.getElementById("app")
);

```
RaspberryPiもろもろ設定

## OSインストール
NOOBSをダウンロード
https://www.raspberrypi.org/downloads/

SDカードをフォーマット
https://www.sdcard.org/downloads/formatter_4/eula_mac/index.html

ダウンロードしたzipファイルを解凍してそのままSDカードに移動

電源ON

なぜかRaspbianぐらいしか表示されないのでそれを選択してインストール

その後なぜか真っ白の画面になって何も操作できないが20分後ぐらいにマウスダブルクリックなどいじりまくったら黒いコマンドを打つ画面に

rebootを打っても再起動しないので、強制的に電源OFF

電源ONでちゃんとデスクトップ画面が起動！

## 初期設定
piのパスワードを変更しておく
システムを上げておく

```
passwd
sudo apt update && sudo apt upgrade
```

## SSH有効化
sudo raspi-config
>Interfacing Options
SSHを適当に選択

## SSH公開鍵認証方式に変更
sudo vi /etc/ssh/sshd_config
>Port xxx
PermitRootLogin no
PasswordAuthentication no

ssh-keygen -t rsa
>パスフレーズを入力

cat id_rsa.pub >> authorized_keys
sudo chmod 600 *
id_rsaをクライアント側に配布
sudo /etc/init.d/ssh restart

## IPの固定する場合（不要でした）
sudo vi /etc/dhcpcd.conf
>interface wlan0
inform 192.168.xxx.xxx
static routers=192.168.xxx.1
static domain_name_servers=192.168.xxx.1

sudo /etc/init.d/dhcpcd restart

## 外部持ち出し時の対策
### 1.iphoneで一度でもテザリングしておくと、その場でテザリングでつながる
arp -aで同一ネットワーク内で探す

### 2.microSDカードに書き込み
```/Volumes/boot/wpa_supplicant.conf
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP

network={
        ssid="SSID"
        psk="pass"
        key_mgmt=WPA-PSK
}
```

取り出すときはdiskutil unmount /dev/disk2s2
その後Raspberry起動時に/etc/wpa_supplicant/wpa_supplicant.confを上書きしてくれる

出先でも書き込んで起動すればwifiにアクセスしてくれるので、
クライアント側で同一ネットワークのそれっぽいやつを探してsshすれば良い。
…が！、まさか出先でアクセスポイントが複数あった場合に詰んだ。
同じwifiを見てるのにアクセスポイントが複数あるからクライアント側にそれっぽいのが出てこない。

### 3.上の2をやった後に起動時にメールアドレスにipを送るスクリプトを仕込んでおく

pip install ipget

```python:send_ip.py

```

ローカルにSMTP立てたい場合、今回はうまくいかなったので中断
<del>sudo apt-get install mailutils
sudo apt-get install postfix
sudo service postfix start
sudo apt-get install telnet→失敗


## mjpgstreamer導入
sudo apt-get update -y
sudo apt-get upgrade
sudo rasps-config
>Enable Camera
カメラを有効化

sudo apt-get install -y cmake libv4l-dev libjpeg-dev imagemagick
git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/
cd mjpg-streamer-experimental/
make
./mjpg_streamer -o "./output_http.so -w ./www" -i "./input_raspicam.so -x 640 -y 480 -fps 30 -q 10"
http://ipaddress:8080 などにアクセス

## motion導入（しょぼい）
sudo apt-get install motion
sudo vi /etc/motion/motion.conf
>stream_localhost off
webcontrol_localhost off

sudo motion -c /etc/motion/motion.conf
http://ipaddress:8080 などにアクセス
【Swift】CellのSliderを操作したときに他のCellを変化させる

# はじめに
特定のUITableViewCell上のUISliderの値を、他のUITableViewCellで使用したいシーンがあったので実装してみました。
また、Storyboardを使用せず、コードのみで実装しています。

# 環境
Xcode 9.2
Swift 4.0.3

# 完成図
![Qiita.gif](https://qiita-image-store.s3.amazonaws.com/0/231880/bd0ab377-8216-8c41-9293-77d4268d5b02.gif)

# コード
```Swift:TableViewController.swift
import UIKit

class TableViewController: UITableViewController {

    let SECTIONS = ["section-1", "section-2"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.register(SliderTableViewCell.self, forCellReuseIdentifier: "cell")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        return SECTIONS.count
    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return SECTIONS[section]
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1 //固定
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        if indexPath.section == 0 {
            let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! SliderTableViewCell
            cell.slider.addTarget(self, action: #selector(self.slide), for: .valueChanged) // UISliderの値が変更された際にslideメソッドを呼び出す
            return cell
        } else {
            return UITableViewCell()
        }
        
    }
    
    @objc func slide(_ sender: UISlider) {
        let indexPath = NSIndexPath(row: 0, section: 1) as IndexPath // 固定
        let cell = tableView.cellForRow(at: indexPath)
        cell?.textLabel?.text = String(sender.value)
    }
}
```

```Swift:SliderTableViewCell.swift
import UIKit

class SliderTableViewCell: UITableViewCell {

    let slider = UISlider()
    
    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        
        // AutoLayout
        self.contentView.addSubview(self.slider)
        
        self.slider.translatesAutoresizingMaskIntoConstraints = false
        
        self.slider.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 50).isActive = true
        self.slider.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -50).isActive = true
        self.slider.centerYAnchor.constraint(equalTo: self.contentView.centerYAnchor, constant: 0).isActive = true
    }

}
```

# 備考
- SliderTableViewCell.swift側で処理を行うように色々試しましたが、実装できませんでした。
- textではなくUISliderの値を変化させることもできます。
- Swiftによる開発は個人の趣味で行なっておりますので、自己流な部分があると思われます。スタンダードな書き方があれば教えてください。
Mac 環境で crowi-plus をビルド＆起動する

# はじめに
ふつうは[公式のREADME](https://github.com/weseek/crowi-plus/blob/master/README.md)読んどけばいいと思う。自分は Mac 環境で実験的にビルド＆起動しようとしたらいろいろハマった。なぜわざわざ Mac かというと、手元の開発環境でビルド＆起動してるものをいろいろいじりたかったから。homebrew でお手軽にやろうとしたら微妙に苦労したりもした。あと MongoDB のことを忘れてたりしてハマった。crowi-plus の README にも書いてなかったので辛かった。

# 前準備
まずソースを入手。

```
git clone https://github.com/weseek/crowi-plus.git
```

README によれば、ビルドツールは yarn が指定されている。また、node 6.x が必要。まずは

```
brew install node@6
```

これで node v6.x をインストールできた。次に

```
echo 'export PATH="/usr/local/opt/node@6/bin:$PATH"' >> ~/.zshrc
```

こうしてパスを通し、node コマンドを使えるようにしておく。次に

```
brew install yarn
```

これで yarn は入手できる...が、この時は node 9.x が依存関係としてインストールされてしまった。
node 9.x は不要。なので

```
vi /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula/yarn.rb
```

として yarn.rb の中をいじる。`brew install yarn` のインストール手続きを変更する。

```
depends_on "node" => :recommended
```

yarn.rb の上の行をコメントアウトする。これで node 9.x がインストールされるのを回避できる(作業後に元に戻したほうがいいとおもう)。

# ビルド＆起動手順
とりあえず上記のような前準備をおこなって、あらためて以下の手続きを行う。

```
cd crowi-plus
yarn global add npm@4
yarn
npm run build
npm run server
```

最後の１行でエラーが出た。以下のような。

```
  crowi:crowi DB Connect Error:  Error: Slash in host identifier
(省略)
  crowi:crowi DB Connect Error:  mongodb://MONGO_HOST:MONGO_PORT/crowi +5ms
```

そういえば MongoDB をインストールしてなかったし当然起動もしてなかった。なので

```
brew install mongodb
mkdir ./mongodb
mongod --dbpath ./mongodb
```

とした。これでうまくいった。MongoDBが起動してないと crowi-plus の起動にも失敗する。無事、http://0.0.0.0:3000 にアクセス成功。めでたし。
macOSで音量を設定する

# サンプルコード

```objc
#import <CoreAudio/CoreAudio.h>
#import <AudioToolbox/AudioToolbox.h>

// デフォルトのサウンド出力デバイスを目標に設定
AudioObjectPropertyAddress addr;
addr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
addr.mScope = kAudioObjectPropertyScopeGlobal;
addr.mElement = kAudioObjectPropertyElementMaster;

// アドレスを元にデバイスIDを取得
AudioDeviceID outputDeviceID;
UInt32 size = sizeof(AudioDeviceID);
OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL, &size, &outputDeviceID);

if (err == noErr) {
    // デバイスの出力マスター音量を目標に設定
    AudioObjectPropertyAddress addr;
    addr.mSelector = kAudioHardwareServiceDeviceProperty_VirtualMasterVolume;
    addr.mScope = kAudioObjectPropertyScopeOutput;
    addr.mElement = kAudioObjectPropertyElementMaster;
    Float32 volume;

    // 音量を取得
    AudioObjectGetPropertyData(outputDeviceID, &addr, 0, NULL, &size, &volume);
    NSLog(@"volume: %lf", volume);
    
    // 音量を設定
    size = sizeof(Float32);
    volume = 0.1;
    AudioObjectSetPropertyData(outputDeviceID, &addr, 0, NULL, size, &volume);
}
```

CoreAudioはC風のAPIなのでObjCで書いたけど、Swiftでも（`UnsafePointer`を駆使することになるが）できないことはないはず。

# 解説

サウンドデバイスはCore Audioでは`AudioDeviceID`によって表される。これは`AudioObject`の一種で、`AudioObject`を対象とする様々な関数の引数として渡すことができる。

`AudioObject`のプロパティの取得・設定には`AudioObjectGetPropertyData`と`AudioObjectSetPropertyData`という関数を使う。これらの関数には`AudioObject`のどのプロパティを対象とするかを`AudioObjectPropertyAddress`というデータを渡すことで指定する。これは3つのフィールドを持つ構造体である（それぞれのフィールドについての詳しい説明についてはヘッダファイル`CoreAudio/AudioHardwareBase.h`を参照のこと）。

`kAudioHardwareServiceDeviceProperty_VirtualMasterVolume`はAudioToolboxのAudio Hardware Serviceで提供されている。他にも`kAudioHardwareServiceDeviceProperty_VirtualMasterBalance`（ステレオ機器の左右の出力バランス）が設定できる。

# 備考

+ 情報が少なくて苦労したが、Audio MIDI設定でできるなら方法があるはずだと信じて探したらなんとかなった
+ `AudioObjectGetPropertyData`と`AudioHardwareServiceGetPropertyData`は何か違うんだろうか？　AHSには制限があるらしいが……

# 参考

[OS Xでのマイク入力キャプチャ Swift版](https://qiita.com/syuhei1008/items/4404f1360863ba8a06ac)
[macOSX10.6AudioVolumeいじいじ - のんべんだらりぃ～ for MacBook](http://d.hatena.ne.jp/chia1220jp/20110216/1297840067)
[HALExamples: ConfigDefaultOutput.c](https://developer.apple.com/library/content/samplecode/HALExamples/Listings/ConfigDefaultOutput_c.html)
解凍した時にディレクトリができないようにzipで圧縮する方法

解凍した時にディレクトリができないようにzipで圧縮する方法を知らなかったのでメモ。
何を行っているかというと、次のように圧縮したい対象ディレクトリ`directory`があったとする。

```bash
$ tree directory           
directory
├── file1.txt
└── file2.txt

0 directories, 2 files
```

これを`zip -r directory.zip directory`で圧縮すると解凍した時に`directory`が出てくる。
そうではなくて、解凍した時に中身のファイルをそのまま出力して欲しい場合は、次のように`j`オプションをつければ良い。

```bash
$ zip -rj directory.zip directory 
  adding: file2.txt (stored 0%)
  adding: file1.txt (stored 0%)
$ ls
directory  directory.zip
```
**追記(2017/2/17)**
**ただし、`-j`は深い階層の場合、ファイルのみがフラットにzipされるみたい。**(ご指摘ありがとうございました。)
この場合一番上のディレクトリのみ除外したい場合は、以下のようにするしかないかもしれない。

```bash
cd directory
zip -r directory.zip *
```
**この記事はディレクトリの外からzipすると一番上のディレクトリも一緒にzipされちゃうから気をつけようねという戒めぐらいに思ってもらいたい。**

# 補足
`-j`オプションは`junk`から来ていて、ディレクトリ名を捨てる(junk)するということみたい。

```
$ zip -h
(略)
-j   junk (don't record) directory names
(略)
```
MacのPHPStormでファイルを開く際に隠しファイルを表示する方法

### ファイル選択ダイアログで隠しファイルを表示する
MacOS Sierraから「cmd+shift+.」をFinder上でキーボード入力すると、.から始まる隠しファイルを表示できるので、PHPStormでファイルを開く際に出てくるファイル選択ダイアログ上でも入力すれば、ここでも隠しファイルを表示できるようになる。
dockerで何ができるの？なんで使うの？を初心者がまとめる

dockerについて初心者なりにわかったことをまとめていきます。

## dockerとは？

> 「Docker（ドッカー）」とは、非常に軽量なコンテナ型のアプリケーション実行環境である。dotCloud社（現Docker社）が開発し、2013年にオープンソースのプロジェクトとして公開された。

引用: http://www.atmarkit.co.jp/ait/articles/1701/30/news037.html

> Dockerは、Linuxのコンテナ技術を使ったもので、よく仮想マシンと比較されます。VirtualBoxなどの仮想マシンでは、ホストマシン上でハイパーバイザを利用しゲストOSを動かし、その上でミドルウェアなどを動かします。それに対し、コンテナはホストマシンのカーネルを利用し、プロセスやユーザなどを隔離することで、あたかも別のマシンが動いているかのように動かすことができます。そのため、軽量で高速に起動、停止などが可能です。

引用: https://knowledge.sakura.ad.jp/13265/

- コンテナ技術

>いまよく使われているサーバー仮想化は、物理サーバーの上に仮想的なサーバー「仮想サーバー」を複数作り出すことができます。この仮想サーバーはまるで本物のサーバーと同じように振る舞います。

>仮想サーバーを実現するには、ハードウェアの機能をすべてソフトウェアで実装するという高度な仕組みが必要です。最近では仮想化機能を支援する機能がサーバーに組み込まれてきているとはいえ、その実装はいまだ複雑なものになっています。

>一方、コンテナ型仮想化はOSの上に“コンテナ”と呼ばれる仮想的なユーザー空間を提供します。ユーザー空間とは、ユーザーがアプリケーションを実行するための、ひと揃いのリソースが提供される空間です。通常は1つのOSの上に1つのユーザー空間があるのですが、コンテナ型仮想化では1つのOSの上で仮想的なユーザー空間であるコンテナを複数提供できます。

引用: http://cn.teldevice.co.jp/column/detail/id/102

つまりはコンテナ技術によって、シンプルに仮想環境を作ることができるようになり、Virtualboxなどに比べて起動速度も速くなったってことですね。

## dockerの何がいいの？

- 環境をコード化して、共有することで複数人での同一な環境構築の手間が短縮される

これがdockerのいいところです。この利点によって

- 開発環境では動いていたけど、本番環境では動かなくなった
- ある人のパソコンだけで出るエラーがある
- 新しい人が入るたびに環境構築がめんどくさい

と行った不便な点を解消することができます。

## dockerの悪いところは？

> 多数のメリットがあるDockerですが、一方でデメリットもあります。1つは、サーバー仮想化では仮想サーバーごとにOSが選択できるのに対して、コンテナ型仮想化はその構造上、すべてのコンテナで同一のOS（カーネル）を利用することが前提であり、個別には選択できないことです。

引用: http://cn.teldevice.co.jp/column/detail/id/102

らしいです。僕は今の所仮想化技術自体を使いこなせていないので、デメリットは感じていません。
int型は2147483647まで。

メモ。

"2173200318"をint(11)に格納しよとしたら


```
Mysql2::Error: Out of range value for column 'office_number' at row 1
```

というエラー。
表題の通り
int型は2147483647までしか入らないようです。

```
TINYINT
  -128から127 (符号無しの場合0から255)

SMALLINT
  -32768から32767 (符号無しの場合0から65535)

MEDIUMINT
  -8388608から8388607 (符号無しの場合0から16777215)

INT
  -2147483648から2147483647 (符号無しの場合0から4294967295)
  別名：INTEGER

BIGINT
  -9223372036854775808から9223372036854775807
  (符号無しの場合0から18446744073709551615)
```
参照： [整数型](https://www.dbonline.jp/mysql/type/index1.html)




データ型をBIGINTにして解決。

```
ALTER TABLE tbl_name MODIFY col_name BIGINT;
```
Lambda(node.js) + Amazon SNSでiPhoneにプッシュ通知を送るサンプルコード

Lambdaを使えばサーバーレスでプッシュ通知ができるのでホント便利です。備忘録がてら上手く行ったLambdaのコードを貼っておきます。予め、LambdaにSNSをPublishする権限を与えるのを忘れずに。

APNSの証明書を云々したりiOS側でエンドポイントを確立したりするのはこちらの記事が参考になりました。
→[AWS SNSを使ってiOSへpush通知](https://qiita.com/ijun/items/2cbff7664e49fb93bf39)

上手く行ったコード

```javascript:index.js
'use strict';
const AWS = require('aws-sdk');
const sns = new AWS.SNS();

exports.handler = (event, context, callback) => {

    const params = {
        TargetArn: endPointArn,//Amazon SNSによって確立されたプッシュ通知を送る端末のendPointArn
        Message: JSON.stringify({
            APNS:JSON.stringify({//開発環境では"APNS"ではなく"APNS_SANDBOX"
                aps:{
                    alert: {
                        title: "プッシュ通知です",//プッシュ通知のタイトル
                        body: "これはプッシュ通知です！"//プッシュ通知の本文
                    },
                    sound: 'default'
                }
            })
        }),
        MessageStructure: 'json'
    };
    sns.publish(params, function(err,data){
        if(err){
            console.log('SNS 送信エラー:', err);
        }else{
            console.log('SNS 送信成功:', data);
        }
    });

}

```

たったこれだけです！超便利！
Google Homeと家電を連携したときに躓いたこと4つ

# 背景
Raspberry PiとirMagicianを使ってGoogle Homeと家電を連携させたのだが、ラズパイ初心者ということもあってかなり初歩的なところで躓いてしまった。
その躓きで得た知見を共有する。

下記記事を参考に連携しました。

Google Home、IFTTT、Firebase、Node.js、irMagicianを使ってシーリングライトを音声操作する
https://qiita.com/miso_develop/items/c2008235cb4a8567cfa9
 
# その1 Raspberry PiにOSをインストールするためには色々必要なものがある
SDカードは必須だし電源だったりキーボードやいろいろ必要です！
自分はその辺知らずにRaspberry PiとirMagicianさえあればなんとかなると思ったので、追加の出費は痛手でした！自分はキーボード買っちゃいましたが、なくてもなんとかなるみたいです

Raspberry Piをディスプレイ・キーボード・マウス無しの三重苦でもセットアップする方法
http://karaage.hatenadiary.jp/entry/2015/07/15/080000

# その2 SDカードの場所がわかりづらい
osを書き込んだsdカードをsdカードリーダーを通してusbに挿してましたが、セットするのは裏面です！
インストール系の記事結構読みましたが、解説している記事はかなり少なかったです。
ハマったのは自分だけなんですかね。。
![4744154-eafbddc16e7992aef97b1d27c70c711f0f9fa658.png](https://qiita-image-store.s3.amazonaws.com/0/19603/6d410adc-c1a6-ec5e-5ba4-eb9847d984f1.png)

# その3 irMagicianを認識してくれない
下記必ず読みましょう。

注意事項必ずお読み下さい
http://www.omiya-giken.com/?page_id=1196

ls /dev/ttyACM0 を実行しても、ttyACM0が見えず、なぜかわからなかったのですが、注意事項に書いてある通り、ケーブルを変えたら一発でした。

#その4 npmでfirebaseをインストールできない
npmのバージョンが低いだけかと思われます。
npm自体のバージョンを上げましょう

以上！
AWS CLIでS3を操作するコマンド一覧

AWS CLIでS3を操作するコマンドの一覧です。
AWS CLIのセットアップについては[こちらの記事](https://qiita.com/uhooi/items/e915873ddabdf6e27fd7)をご覧ください。

## 環境
- OS：macOS High Sierra 10.13.1

```bash
$ aws --version
aws-cli/1.14.36 Python/3.5.0 Darwin/17.2.0 botocore/1.8.40
```

## `aws s3` のコマンド一覧(抜粋)

|コマンド|説明|
|:---|:---|
| `aws s3 ls` |バケットの一覧を表示する|
| `aws s3 ls s3://{バケット名}/{パス}` |バケットの内容を表示する|
| `aws s3 mb s3://{バケット名} ` |バケットを作成する|
| `aws s3 rb s3://{バケット名} ` |バケットを削除する(空でない場合は削除されない)|
| `aws s3 rb s3://{バケット名} --force ` |バケットを削除する(空でなくても削除される)|
| `aws s3 sync {フォルダパス} s3://{バケット名}/{パス} ` |バケットの内容をローカルのフォルダと同期する(追加・更新のみで削除されない)|
| `aws s3 sync {フォルダパス} s3://{バケット名}/{パス} --delete ` |バケットの内容をローカルのフォルダと同期する(削除もされる)|
| `aws s3 cp {ファイルパス} s3://{バケット名}/{パス} ` |ローカルのファイルをバケットにコピーする|
| `aws s3 mv {ファイルパス} s3://{バケット名}/{パス} ` |ローカルのファイルをバケットに移動する|
| `aws s3 rm s3://{バケット名}/{ファイルパス} ` |バケットのファイルを削除する|
| `aws s3 rm s3://{バケット名}/{フォルダパス} --recursive ` |バケットのフォルダを削除する|

`sync` `cp` `mv` はローカルからS3のみでなく、S3からローカル、S3からS3もファイルをやりとりできます。
個人的には `sync` がファイル・フォルダを一括で追加・更新・削除できるので便利です。

## 参考リンク

- [AWS Command Line Interface での高レベルの S3 コマンドの使用 - AWS Command Line Interface](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/using-s3-commands.html)
Google Chrme拡張機能のエディタ

みなさん、こんな場面に出くわしたことはありませんか？

- Chromebookを使ってテキストコードを編集したい

- 諸事情によりVim, Atom, SublimeText等をインストールすることができない。しかしChromeは自由に使える。

まあ、そんな人はあまり居ないと思いませんが、Chromebookでよさ気なエディタを探したので記事にまとめてみました。

とはいえ、自分のChromeに入れておくと、出先のChromeしか無い環境にログインした時に使えたりするので便利です。


今回紹介するエディタは以下の3つです

- [Caret](https://chrome.google.com/webstore/detail/caret/fljalecfjciodhpcledpamjachpmelml?hl=ja)
  高機能で汎用的なエディタ
  SublimeTextに近い感じ
![01_caret.png](https://qiita-image-store.s3.amazonaws.com/0/214526/137c8b04-7967-b4fe-c52b-053cefc98fdc.png)


- [Text](https://chrome.google.com/webstore/detail/text/mmfbcljfglbokpmkimbfghdkjmjhdgbg)
  シンプルさが売り
![02_text.png](https://qiita-image-store.s3.amazonaws.com/0/214526/267b3c86-5c45-0e44-823d-da3e81e4d2b2.png)


- [Web Maker](https://chrome.google.com/webstore/detail/web-maker/lkfkkhfhhdkiemehlpkgjeojomhpccnh)
  Webサイト作成に特化したエディタ
  リアルタイムプレビューに対応している
  Markdownにも対応している
![03_web_maker.png](https://qiita-image-store.s3.amazonaws.com/0/214526/ed89fe7f-6d81-2115-5f38-0f0518890296.png)


## 比較

### テーマ変更

| Caret  | Text | Web Maker |
|--------|------|-----------|
| 約40種 | 3種  | 約50種    |


### タブ

| Caret | Text | Web Maker |
|-------|------|-----------|
| ○     | △    | ×         |

Textはタブではなく、履歴が左のパネルに表示される

### ツリービュー

| Caret | Text | Web Maker |
|-------|------|-----------|
| ○     | ×    | ×         |

### ショートカットのカスタマイズ

| Caret | Text | Web Maker |
|-------|------|-----------|
| ○     | ×    | ×         |

### フォント設定

| Caret | Text       | Web Maker |
|-------|------------|-----------|
| ○     | サイズのみ | ○         |


### タブ文字/改行文字表示

| Caret | Text | Web Maker |
|-------|------|-----------|
| ○     | ×    |           |

### 日本語化

| Caret | Text | Web Maker |
|-------|------|-----------|
| ○     | ×    | ×         |

Caretでは、メニュー等のラベルを定義したファイルを編集することで可能

### vimキーバインド

| Caret | Text | Web Maker |
|-------|------|-----------|
| ○     | ×    | ○         |

### シンタックスハイライト

| type         | Caret | Text | Web Maker |
|--------------|-------|------|-----------|
| Markdown     | ○     | ○    | ○         |
| html         | ○     | ○    | ○         |
| css          | ○     | ○    | ○         |
| javascript   | ○     | ○    | ○         |
| shell script | ○     | ○    | ×         |
| python       | ○     | ○    | ×         |
| ruby         | ○     | ○    | ×         |

## その他
検索バーに`data:text/html, <html contenteditable>`と入力することで、素のChromeでもテキストを編集できます。
変態向けですね。

## まとめ
コード書くならCaret、markdown程度でいいならtextも選択肢に入るという感じでしょうか。

他にもいいエディタがありましたら、コメントいただけると幸いです。
ラズパイの環境構築してみた()

備忘録
# 必要なモノ
* tomcat
* apache2
* jfbterm(日本語表記)

※なぜtomcatとapache2が必要なのか
 [Apache HTTP ServerとApache Tomcatの連携する意味](http://fa11enprince.hatenablog.com/entry/2015/01/19/233740) 


### 何かをインストールする前にすること

```
sudo apt-get update
sudo apt-get upgrade
```

※もしupdateが上手く行かない場合、ミラーリングするサーバーが遠すぎて無理な可能性が高い
```
sudo vi /etc/apt/sources.list
```

```
deb http://ftp.jaist.ac.jp/raspbian stretch main contrib non-free
deb http://ftp.yz.yamagata-u.ac.jp/pub/linux/raspbian/raspbian/ stretch main contrib non-free
```
## apache2のインストール
 [Apache2でラズパイをWebサーバに!](http://usicolog.nomaki.jp/engineering/raspberryPi/raspberryPi_Apache2.html) 
```
sudo apt-get install apache2
```
インストール出来たら、一度確認する
http://[ラズベリーパイのIPアドレス]

## Tomcatの構築方法
 [java8のインストール方法](http://blog.nobuya.mydns.jp/blog/2016/java-installation/) 
 [tomcat8のインストール方法](http://blog.nobuya.mydns.jp/blog/2016/apache-tomcat-installation/) 
### insservのインストール
```
sudo apt-get install insserv
sudo apt-get install chkconfig
```

### ※それ以外の参考資料
 [java8の違うインストール方法](https://qiita.com/kurukurupapa@github/items/c60f1d688a4da15c9684)
[LINK数PATHを設定する](http://www.gatamix.com/article/449121446.html)  
 [Raspbian Jessie Lite の Wi-Fi 設定](https://azriton.github.io/2016/11/25/Raspbian-Jessie-Lite%E3%81%AEWi-Fi%E8%A8%AD%E5%AE%9A/) 
 [Raspberry Pi をディスプレイ/キーボードなしで初期設定する](https://qiita.com/eup42/items/58bf6c336d325eba3ee2#ssh-%E3%81%AE%E8%87%AA%E5%8B%95%E8%B5%B7%E5%8B%95%E8%A8%AD%E5%AE%9A) 
 [RaspberryPiの日本語設定](http://uepon.hatenadiary.com/entry/2016/04/06/225259) 
 [Raspberry Piの初期設定まとめ](https://www.out48.com/archives/895/)
Promiseを使って、高負荷な演算の前にD3でSVGを出力する

#SVGの描画がうまくいかない
以前こんな感じの処理を行おうとしたところ、SVGの描画が思うように行きませんでした。

```javascript
// d3を使ったSVG出力
const svg = d3.select("body").append("svg");
svg.append("circle").attr("cx", 10).attr("cy", 10).attr("r", 3);

// なにかしら重い計算
const a = new Array();
    for(let i=0;i<150000;i++)
        a.unshift(i*i);
```

これを実行すると、意図に反してSVGは重い計算が終わったあとに出力されてしまいます。対処法を調べたらPromiseを用いた良さげなものがあったので、メモしておきます。

#解決策

```javascript
const p = new Promise((resolve, reject) => {
	//時間のかかる処理前にやっておきたい処理
	d3.select("body").append("div").text("hello world");
	resolve();
});

p.then(() => {
	return new Promise((resolve, reject) => {
		//事前処理はここにも書ける
		
		const a = new Array();
		setTimeout(()=>{
			//時間のかかる処理
			for(let i=0;i<150000;i++){
				a.unshift(i*i);
			}
			resolve(a.length);

		}, 100);// 100msは、レンダリングのための猶予の時間
	});
}).then((len) => {
	//次にしたい処理
	console.log(len);
	return;
}).catch(() => {
	console.error('something wrong');
});
```

これで解決です。

#その他Promiseまとめ
promiseを使ったテクニックをまとめておきます

```javascript
function func0(){
	const str = "";
	
	const func1 = (str)=>{
		return new Promise((resolve)=>{
			setTimeout(()=>{
				console.log(str + "Alice ");
				resolve(str + "Alice ");
			}, 1500);
		});
	};

	const func2 = (str)=>{
		return new Promise((resolve)=>{
			setTimeout(()=>{
				console.log(str + "Bob ");
				resolve(str + "Bob ");
			}, 1000);
		});
	};
	
	const func3 = (str)=>{
		console.log(str + "Charlie ");
		return str + "Charlie ";
	};

	func1(str).then(func2).then(func3).then((str)=>{
		console.log(str + "Dan");
	}).catch(()=>{
		console.error("something wrong");
	});
}
func0();
```

実行結果

```
Alice
Alice Bob
Alice Bob Charlie
Alice Bob Charlie Dan
```
DynamoDB StreamをトリガーにしてLambdaを実行する

#DynamoDB Streamとは
DynamoDB Streamは、DynamoDBに対する項目の追加、変更、削除をイベントとして検出できる機能です。DynamoDB Streamを使うことで、項目が追加・変更された時にプッシュ通知を飛ばしたりといった実装が可能になります。今回は、そのイベントをLambdaで受け取ってみたいと思います。

参考：[DynamoDB ストリーム を使用したテーブルアクティビティのキャプチャ](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Streams.html)

#DynamoDB側でStreamを有効化
先んず、DynamoDBの概要のタブにある「ストリームの管理」から、Streamを有効化します。新旧イメージを選択すると、項目の変更時にLambdaが項目のBefore&Afterの両方を受け取ることができます。
![スクリーンショット 2018-02-14 20.52.33.png](https://qiita-image-store.s3.amazonaws.com/0/86468/e5256172-a25b-d920-4ec5-0d106ea275f2.png)

#DynamoDB Streamを受け取るためにLambdaに必要な権限
LambdaがDynamoDB Streamを受け取るためには、読み取りたいテーブルのストリームに対して下記の4つの権限を許可しておく必要があります。ストリームのARNは、`arn:aws:dynamodb:ap-northeast-1:XXXXXXXXX:table/テーブル名/stream/*`とすることで全てのストリームを受け取ることができます。

- GetShardIterator
- GetRecords
- ListStream
- DescribeStream

#Lambda側からDynamoDB　Streamのトリガーを追加
Lambdaのページの「左側からトリガーを追加」というところで、DynamoDBを選択すると設定画面が出てきます。
![スクリーンショット 2018-02-14 21.00.39.png](https://qiita-image-store.s3.amazonaws.com/0/86468/8f926fc8-144b-28ec-7e9a-030241b238d0.png)

設定ではStreamを受け取りたいテーブルとバッチサイズを指定します。開始位置は最新と水平を選択できます。ここでは最新を選択しています。左下の追加をクリックしたあとに変更を保存すると、トリガーとして追加されます。
![スクリーンショット 2018-02-14 21.00.53.png](https://qiita-image-store.s3.amazonaws.com/0/86468/fec1c927-3fdb-5391-120f-5dc11c6b283c.png)


#Lambda関数の中身の雛形
event.Recordsが配列としてイベントを受け取っているので、forEachで一つ一つ処理をしています。eventNameに「INSERT」か「MODIFY」か「REMOVE」が入っていて、変更の種類を教えてくれます。

```javascript:index.js

exports.handler = (event, context, callback) => {

    event.Records.forEach((record) => {
        console.log('イベント種別:', record.eventName);
        console.log('DynamoDB Record: %j', record.dynamodb);

        if(record.eventName == 'INSERT'){
            //項目が追加された時の処理
            const newItem = record.dynamodb.NewImage;

        }else if(record.eventName == 'MODIFY'){
            //項目が変更された時の処理
            const oldItem = record.dynamodb.OldImage;//変更前
            const newItem = record.dynamodb.NewImage;//変更後

        }else if(record.eventName == 'REMOVE'){
            //項目が削除された時の処理
            const deletedItem = record.dynamodb.OldImage

        }else{

        }
    });

};

```

#結果
DynamoDBのコンソール画面から適当に項目を追加、編集、削除してみましょう。下記のログは項目を編集（名前を山田太郎→佐藤太郎に変更）した時のログです。NewImageとOldImageの中にBefore&Afterが入っているのがわかると思います。SとかNとかはデータ型を表しています。

```
{
    "ApproximateCreationDateTime": 1518610740,
    "Keys": {
        "id": {
            "S": "sample"
        },
        "create_at": {
            "N": "1518534000"
        }
    },
    "NewImage": {
        "name": {
            "S": "佐藤太郎"
        },
        "id": {
            "S": "sample"
        },
        "create_at": {
            "N": "1518534000"
        }
    },
    "OldImage": {
        "name": {
            "S": "山田太郎"
        },
        "id": {
            "S": "sample"
        },
        "create_at": {
            "N": "1518534000"
        }
    },
    "SequenceNumber": "24000000000007967212728",
    "SizeBytes": 98,
    "StreamViewType": "NEW_AND_OLD_IMAGES"
}
```
POST で PDF を作らせて F5 すると……？

**Firefox と IE は何故か GET に化けた**。何が起きた。

*本当にさっぱりわけがわからないので、詳しい人教えて。*

# 何があったの？
あるWebアプリケーションでPDF帳票を出力する (あるあるだ) 。
しかしこの帳票出力、出力のプレビュー画面で (つまりレスポンスが Content-Disposition: inline になっている) 更新をかけると**謎のエラー落ちを起こす**。

Spring MVC なのだが、ログによると List を直接インスタンス化しようとして事故っている。
ミッションはこの問題の解決なのだが、そもそもなぜそんな訳のわからん状態が起きているのだ？と調べてみたら余計に訳がわからなくなった。

下の表は、とりあえず手元のブラウザで出力 → F5 をやってみた結果だ。
F5 と書いてる時点で察していると思うが、私は Windows ユーザである (というかどこもかしこも Windows 使ってるせいで Linux を使いづらいんだ) 。このため、Safari はない。

|Browser|Result|
|:------|------|
|Chrome 63|警告後 POST|
|Firefox 58|無警告でGET|
|Internet Explorer 11|無警告でGET|

通常 POST したものをリロードした場合、確認メッセージを出した上で POST するものだが、これに限っては話が違うようだ。
直感的な (……？) 動作をしているのは Chrome だけで、他は無警告で GET する。
……意味がわからない。

# 検証方法
codepen を使ってそれっぽく POST してくれるボタンを作成し確認した。以下のような塩梅である。
https://codepen.io/anon/pen/XZaYOa

接続対象はローカルで適当にサーバおっ立ててなんとかした。

# 仮説1: 別画面向けの POST だと死ぬ
上述の出力は target にある固定の値をセットしていた。これのせいではなかろうか？
**もちろんそんなことはなかった**。
しかし、Firefox で検証したところ (めんどくさかったのでIEはほったらかしである) 重要な事がわかった。

* テキストデータを返した場合: **警告の上 POST する**。
* PDF を返した場合: **無警告で GET する**。

というわけでつまり、**PDF の場合 GET に化けるという可能性が出てきた**。
すると、もう一つ仮説が出てくる。

# 仮説2: Content-type？ Content-Disposition？
もちろん現実問題としていじれば欲しい動作をしたとしてもいじるわけにはいかないのだが、それはそれとしてまあ、という話である。
が、**やっぱり駄目だった**。テキストを PDF っぽくしても GET に化けたし、Disposition を attachment にしてはそもそもプレビューされなくなってしまう。

# 仮説3: もしかしてプレビューできるバイナリ全般死ぬの？
検証できていない。ただ、**大いに有り得るとは思う**。
例えば、**アドオンでプレビュー表示中は通信が全部 GET になるとか**、**表示中の更新はアドオン側でやるけど実装が GET だとか**。

……いやいや、ほんとうにあるのかね、そんなこと。
MatlabでCSVファイル読み込み

自分用のメモ

1行目はヘッダ。

# 入力ファイル
```
h1,h2,h3,h4,h5,h6,h7
1,2,3,4,5,6,7
1,2,3,,,,
1,2,3,4,5,6,7
1,2,3,4,5,6,7
1,2,3,,,,
1,2,3,4,5,6,7
1,2,3,,,,
```


# textscan版
```matlab
filepath = 'C:\data.csv';
fileId = fopen(filepath, 'r');
% 3列目以降を無視
data = textscan(fileId, '%f%f%*[^\n]', 'delimiter', ',', 'headerLines', 1 );
fclose(fileId);
% 戻り値は1×2のcell配列になる
data 
```

# readtable版
```matlab
filepath = 'C:\data.csv';
data =  readtable(filepath, 'delimiter', ',');
% 戻り値は8×9のテーブルになる。勝手にヘッダも認識される。
data
% 簡単に全列読み込めたデータだけに絞り込みできる
truedata = rmmissing(data);
truedata
```

# fgetl版
```matlab
h1 = [];
h2 = [];            
fileId = fopen(filepath, 'r');
row = fgetl(fileId); % ヘッダ空読み
row = fgetl(fileId);
while ischar(row)
  columns = strsplit(row, ',');
  if length(columns) > 4
    % ほかにもっとよい書き方があるのだろうか
    h1 = [h1; str2double(columns{1})];
    h2 = [h2; str2double(columns{2})];
  end
  row = fgetl(fileId);
end
fclose(fileId);

```
Windowsのユーザーのセキュリティ識別子(SID)を取得するプログラム

## このプログラムを作り始めた経緯
最近ずっとセーブデータの暗号化プログラムを考えてたんですが、単に暗号化するだけでもよかったんですが、それだと暗号の意味が破られた時にセーブデータ書き換えられるよなと思いました。
ただ、暗号破りしてクリアした人を暗号破りせず素直にやってる人がいじめをやるとかそういうこと始めたら嫌だなと思いました。なんせ考えた暗号化方法って結構シンプルだったので…。まあ逆にあんまり複雑にしても復号化も面倒だなと思ってたのでいいんですが。

そこで目をつけたのがWindowsのレジストリでした。

Windowsのレジストリは結構暗号のように複雑に文字列が組み合わさってるのでこれの中の何かを暗号化に使えないかなと思い、いろんなところを見てました。そうしたら

HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList

にS-1-5-21で始まる文字列のフォルダでした。
この中を見たら、ユーザープロファイルのフォルダがあり、「あ、これユーザーの識別に関わってるキーじゃないかな」と思いました。ただ、これをデータの暗号化に使うにはさすがに苦でした。そこで思いついたのが、「あ、これをファイル名にしてしまえばいいんじゃないか？」ということでした。
ただ、私のVAIOと家族で使ってるVAIOのレジストリを見比べたら、このキーはPC毎に違うことが分かり、取得のしようがないなと諦めてました。そもそも考えついた時はこの文字列の正体すら分からなかったので…。

調べてみたらこれがWindowsのユーザーのセキュリティ識別子(SID)であると分かり、それを取得するためのAPIもMicrosoftから提供されていたので、セーブデータにこれを使うかどうかは別として、早速このプログラムをまとめてみようと思い、作りました。

```cpp:GetSID.cpp
std::string GetSIDStringA(const std::string ComputerName, const std::string UserName) {
	char sidBuf[256];
	DWORD dwSidLen = 0, dwDomainLen = 256;
	SID_NAME_USE snu;
	LookupAccountNameA(ComputerName.c_str(), UserName.c_str(), NULL, &dwSidLen, sidBuf, &dwDomainLen, &snu);
	PSID psid = (PSID)HeapAlloc(GetProcessHeap(), 0, dwSidLen);
	if (0 == LookupAccountNameA(ComputerName.c_str(), UserName.c_str(), psid, &dwSidLen, sidBuf, &dwDomainLen, &snu))
		throw std::runtime_error("Error in LookupAccountName Function");
	LPSTR lpbuf;
	if (0 == ConvertSidToStringSidA(psid, &lpbuf)) throw std::runtime_error("Error in ConvertSidToStringSid Function");
	std::string s;
	s.resize(std::strlen(lpbuf));
	s = lpbuf;
	return s;
}

std::wstring GetSIDStringW(const std::wstring ComputerName, const std::wstring UserName) {
	wchar_t sidBuf[256];
	DWORD dwSidLen = 0, dwDomainLen = 256;
	SID_NAME_USE snu;
	LookupAccountNameW(ComputerName.c_str(), UserName.c_str(), NULL, &dwSidLen, sidBuf, &dwDomainLen, &snu);
	PSID psid = (PSID)HeapAlloc(GetProcessHeap(), 0, dwSidLen);
	if (0 == LookupAccountNameW(ComputerName.c_str(), UserName.c_str(), psid, &dwSidLen, sidBuf, &dwDomainLen, &snu))
		throw std::runtime_error("Error in LookupAccountName Function");
	LPWSTR lpbuf;
	if (0 == ConvertSidToStringSidW(psid, &lpbuf)) throw std::runtime_error("Error in ConvertSidToStringSid Function");
	std::wstring s;
	s.resize(std::wcslen(lpbuf));
	s = lpbuf;
	return s;
}
```
SIDを知ってる人なんて早々はいないはずなので、ファイル名とかにしておけばセーブデータとかたぶんバレづらいかも？
Geth コンソールコマンド一覧

Gethのコンソールコマンド一覧です。
引数は適宜ご自身で切り替えてください。

##アカウント関連
- アカウントの作成

```
> personal.newAccount("passphrase")
```
- アカウントの確認

```
> eth.accounts
```

- インデックス指定でのアカウントの確認

```
> eth.accounts[index]
```

- コインベースのアカウントの確認　※コインベース： ブロック生成のマイニング報酬を得るアカウント

```
> eth.coinbase
```
- コインベースアカウントの変更

```
> miner.setEtherbase(eth.accounts[index])
```

- 残高確認 (wei)

```
> eth.getBalance(eth.accounts[index])
```
- 残高確認 (ether)　※単位はether以外にも変更可能。

```
> personal.unlockAccount(eth.accounts[index])
```

##マイニング関連

- マイニングの開始　※引数はマイニング処理を実行するスレッド数。

```
> miner.start(num_of_threads)
```

- マイニングの停止

```
> miner.stop()
```

- マイニング中か確認

```
> eth.mining
```
- マイニングHashrateの確認

```
> miner.hashrate
```
- ブロックの内容確認

```
eth.getBlock(blockNumber)
```
##トランザクション関連
- アカウントのロック解除　※送金前に必要。

```
> web3.fromWei(eth.getBalance(eth.accounts[index]), "ether")
```

- 送金 

```
eth.sendTransaction({from: eth.accounts[source_index], to: eth.accounts[destination_index], value: web3.toWei(amount, "ether")})
```

- トランザクションの確認

```
eth.getTransaction("transaction_address")
```

- トランザクションの実行結果（レシート）の確認

```
eth.getTransactionReceipt("transaction_address")
```

#####参考記事
[Ethereum Geth コンソールコマンド一覧
](https://qiita.com/toshikase/items/fa7a826db483177d1e80)
MacのSafari、テキストの太さを自動調整している説

## 要旨

Safariのレンダリングエンジンは、アンチエイリアスの方式を動的に選択しているのではないだろうか。

なぜなら、Safariで、テキストの太さが動的に変わる現象を観測したからだ。

## 背景

### そもそもテキストの太さとは

テキストの見掛けの太さ（濃さ）は、文字そのものの太さ以外に、文字に掛かるアンチエイリアスの方式によっても変わります。

### アンチエイリアスの方式

二種類あります。

* グレースケールレンダリング（細く見える）
* サブピクセルレンダリング（太く見える）

### 方式の指定

これらのレンダリング方式は、CSSで明示的に選択することができます。

```css
<!-- グレースケールレンダリング -->
-webkit-font-smoothing: antialiased;

<!-- サブピクセルレンダリング -->
-webkit-font-smoothing: subpixel-antialiased;
```

そして、明示的に選択しなかった場合の方式が、Safariでは不定なのでは？というお話です。

## 現象

事の発端は、以下の現象を観測したことから始まります。

* 共通ヘッダー内のテキストのアンチエイリアス方式がページ間で異なる


調査を進めたところ、他に以下のような症状を観測しました。

* ヘッダーのテキストはグレースケールレンダリングされ、それ以外のコンテンツはサブピクセルレンダリングされる
* 検証ツールでコンテンツを編集すると、全く別の位置にあるヘッダーのアンチエイリアス方式が変化する
* 同じページでも、JSをONにした場合とOFFにした場合とでアンチエイリアス方式が異なる

ううむ、全然わからない。

font-smoothingの指定はどのCSSからも検出されませんでした。

## 仮説

**MacのSafariのレンダリングエンジン(webkit)が、テキストをアンチエイリアシングする方式をレンダーツリーの内容によって動的に選択し分けているのではないか。**

調べても公式情報が見当たらなかったので仮説止まりですが、この可能性を疑っています。もしご存知でしたらご指摘頂ければと思います。

## 端末

* El Capitan 10.11.5

* Safari 9.1.1

## 参考文献
* [Webブラウザにおける文字のアンチエイリアスの現状の最適解](http://creator.dwango.co.jp/14128.html)

* [font-smoothingでOSXでのフォントのレンダリング方法を調整する](https://qiita.com/htomine/items/3086f30ca09adea2f8e0)