OmniAICreator/Qiita-1.07M huggingface dataset:
判別分析（多変量解析入門　小西貞則先生）

判別分析のプログラムを作成してみました。

```{r}

#判別分析(小西貞則 多変量解析入門 p.135)

library(dplyr)
dataA=data.frame(num=1:12,length=c(5,7,6,8,5,9,6,9,7,6,7,9),width=c(5,7,7,6,6,8,6,7,5,5,8,4))
dataB=data.frame(num=1:11,length=c(6,8,7,9,7,10,8,10,9,8,7),width=c(2,4,4,5,3,5,5,6,6,3,6))

myu_A_x1=mean(dataA$length)
myu_B_x1=mean(dataB$length)
myu_A_x2=mean(dataA$width)
myu_B_x2=mean(dataB$width)
Data_A=data.frame(variable=c("x1","x2"),mean=c(myu_A_x1,myu_A_x2),variance=c(var(dataA$length),var(dataA$width)),covariance=c(cov(dataA$length,dataA$width)))
Data_B=data.frame(variable=c("x1","x2"),mean=c(myu_B_x1,myu_B_x2),variance=c(var(dataB$length),var(dataB$width)),covariance=c(cov(dataB$length,dataB$width)))

mean_A=Data_A$mean
mean_B=Data_B$mean
SA=array(Data_A$covariance[1],dim=c(ncol(dataA)-1,ncol(dataA)-1))
diag(SA)<-Data_A$variance

SB=array(Data_B$covariance[1],dim=c(ncol(dataB)-1,ncol(dataB)-1))
diag(SB)<-Data_B$variance

S=((nrow(dataA)-1)*SA+(nrow(dataB)-1)*SB)/(nrow(dataA)+nrow(dataB)-2)

w=round(solve(S)%*%(mean_A-mean_B),digit=2)

b=(1/2)*t(mean_A-mean_B)%*%solve(S)%*%t(t(mean_A+mean_B))
D2=(mean_A-mean_B)%*%solve(S)%*%(mean_A-mean_B)

data=rbind(dataA,dataB) %>% dplyr::select(c(-num)) %>% dplyr::mutate(pattern=0,values=0)

for(j in 1:nrow(data)){
  
data$values[j]=data$length[j]*w[1]+data$width[j]*w[2]-b  
  
data$pattern[j]=ifelse(data$length[j]*w[1]+data$width[j]*w[2]-b<0,-1,1)  
  
}


#plot

plot(dataA$length,dataA$width,xlab="length",ylab="width",xlim=c(min(data$length),max(data$length)),ylim=c(min(data$width),max(data$width)),col=2,type="p",main="Data_plot;red_A;green_B")

par(new=T)

plot(dataB$length,dataB$width,xlab="length",ylab="width",xlim=c(min(data$length),max(data$length)),ylim=c(min(data$width),max(data$width)),col=3,type="p",main="Data_plot;red_A;green_B")

#predict_plot

plot(data$length[data$pattern==1],data$width[data$pattern==1],xlab="length",ylab="width",xlim=c(min(data$length),max(data$length)),ylim=c(min(data$width),max(data$width)),col=2,type="p",main="predict_plot;red_A;green_B")

par(new=T)

plot(data$length[data$pattern==-1],data$width[data$pattern==-1],xlab="length",ylab="width",xlim=c(min(data$length),max(data$length)),ylim=c(min(data$width),max(data$width)),col=3,type="p",main="predict_plot;red_A;green_B")

```
北川源四朗先生　「情報量統計学」

北川源四朗著「情報量統計学」によるサンプルをプログラムしました。
ＡＩＣの使い方を勉強しました。

```{r}

#北川源四朗著「情報量統計学」

library(dplyr)
library(pforeach)

data_A=data.frame(num=1:11,val=c(0.73,-0.06,1.04,2.29,0.51,-0.45,1.03,0.44,0.02,0.11,-2.42))
data_B=data.frame(num=1:8,val=c(0.1,0.56,-1.11,-0.48,3.46,-2.39,0.36,4.56))

normal=function(y,u,sigma){
  z<-(exp(-(y-u)^2/(2*sigma^2)))/(2*pi*sigma^2)^(1/2)
  return(z)
}

#data_A and data_B are following a same normal distribution? 

#Model 1; average and variance are not equal.

mu_1=(1/nrow(data_A))*sum(data_A$val)
mu_2=(1/nrow(data_B))*sum(data_B$val)
var_1=(1/nrow(data_A))*sum(data_A$val^2)-mu_1^2
var_2=(1/nrow(data_B))*sum(data_B$val^2)-mu_2^2


loglikelihood=-(nrow(data_A)+nrow(data_B))*(log(2*pi))/2-nrow(data_A)*(log(var_1))/2-nrow(data_B)*(log(var_2))/2-((nrow(data_A)+nrow(data_B))/2)

AIC_1=-2*loglikelihood+2*4

#MODEL 2; average and variance are equal.

mu=(1/(nrow(data_A)+nrow(data_B)))*sum(c(data_A$val,data_B$val))

var=(1/(nrow(data_A)+nrow(data_B)))*(sum(c(data_A$val^2,data_B$val^2)))-mu^2

loglikelihood=-(nrow(data_A)+nrow(data_B))*(log(2*pi*var)+1)/2

AIC_2=-2*loglikelihood+2*2

AIC_1
AIC_2

if(AIC_1<AIC_2){
  print("MODEL1 is better than MODEL2.")
}else{
  if(AIC_1==AIC_2){
    print("MODEL1 and MODEL2 have a same result.")
  }else{
   print("MODEL2 is better than MODEL1.") 
  }
  }

print(paste0("MODEL1:AIC ",AIC_1))
print(paste0("MODEL2:AIC ",AIC_2))

#MODEL3:
```

```{r}
#情報量統計学p.49

library(dplyr)
library(pforeach)

#model(N(mu,1))

count=0

normal_sample=c()

while(count<1000)({

N=200
#N=sample(100:N,1)

#data samples

samples=rnorm(N,mean=0,sd=1)

normal_sample=c(normal_sample,sum(samples)/sqrt(N))

count=count+1
})

plot(normal_sample,type="o",main=paste0("Random variable:sqrt(N)*mean(N),  mean:",substring(mean(normal_sample),1,6),", var:",substring(var(normal_sample),1,6)))

#平均対数尤度

mu=2

N=100

nsamples=rnorm(N,mean=mu,sd=1)

#乱数から生成した平均対数尤度
rand_mean=N*mean(log(dnorm(nsamples)))
#実際に計算した平均対数尤度
ave_log_likelihood=-(N/2)*(log(2*pi)+1+mu^2)

print(paste0("乱数から生成した平均対数尤度:",rand_mean))

print(paste0("実際に計算した平均対数尤度:",ave_log_likelihood))

log_normal=deriv(~ -log((1/sqrt(2*pi))*exp(-(z-u)^2/2)),c("z","u"),func=T,hessian=T)


# J=-E[(d/du)^(2)(log(f(Z|u)))]
N=100
u=0
Z=rnorm(N,mean=u,sd=1)
hessian=attr(log_normal(Z,0),"hessian")

diff=data.frame(diff=(hessian))

J=mean(diff$diff.u.u)


#l'(u*)=l'(u)-(1/2)*(sqrt(n))*(u*-u)*J*(sqrt(n))*(u*-u)

val1=c();val2=c();count=0
while(count<100)({
N=100
u=2;n=0
l=N*mean(log(dnorm(rnorm(N,mean=u))))
L=N*mean(log(dnorm(rnorm(N,mean=n))))

val1=c(val1,L-(1/2)*sqrt(N)*(u-n)*J*(u-n)*sqrt(N))
val2=c(val2,l)
count=count+1
})

print(paste0("l*(u)=",mean(val1)))
print(paste0("l(u)=",mean(val2)))


```
確率過程とその応用　小和田 正先生　実教出版 

今回は強度関数を用いた非定常ポアソン分布の応用について書きました。
ある道路に対して、時間帯で交通量のことなる道路で何時に何台目の車が通ったときに次の時間まで
どれくらいかかるのかを確率で計算します。

```{r}

#非定常ポアソン過程を用いたヒッチハイク問題(確率過程とその応用p.63)

library(dplyr)

#道に迷った人が田舎の道でヒッチハイクしている。朝7時ごろと昼12時ごろ、夕方8時ごろに何台か通り過ぎることを予想している。
#通過する車の多さを予測し、アピールできる時間帯の確率を考えましょう。

intensity_func=function(s){
  
  intensity1=function(k){
      Z<-2*k*exp(-(k-7)^2)
      return(Z)
  }
  
  intensity2=function(l){
    Z<-2*l*exp(-((l-12)^2))
    return(Z)
  }
  
  intensity3=function(m){
    Z<-2*m*exp(-((m-20)^2))
    return(Z)
    
  }
  
  if(s>=6 & s<9){
    
  z<-integrate(intensity1,6,s)$value
  }else{
    if(s>=9 & s<=16){
      z<-integrate(intensity1,6,9)$value+integrate(intensity2,9,s)$value
    }else{
      if(s>=16 & s<=24){
      z<-integrate(intensity1,6,9)$value+integrate(intensity2,9,16)$value+integrate(intensity3,16,s)$value
      }else{
        if(s>=24){
          z<-0
        }else{
      z<-0
    }
  }
  }
  }
  return(z)
  
}


#非定常ポアソン過程をプロット

non_stationary_pois=data.frame(t=seq(0,24,0.1),pois=0)

for(j in 1:nrow(non_stationary_pois)){
  
  if(j==1){
  non_stationary_pois$pois[j]=rpois(1,lambda=intensity_func(non_stationary_pois$t[j]))
  }else{
  non_stationary_pois$pois[j]=rpois(1,lambda=intensity_func(non_stationary_pois$t[j])-intensity_func(non_stationary_pois$t[j-1]))  
  }
  
}

plot(non_stationary_pois$t,non_stationary_pois$pois,type="o",col=2,xlab="t",ylab="車の通過台数",main="各時刻tにおける通過台数")

non_stationary_pois=non_stationary_pois %>% dplyr::mutate(N=0)

for(j in 1:nrow(non_stationary_pois)){
  
  non_stationary_pois$N[j]=sum(non_stationary_pois$pois[1:j])
  
}

colnames(non_stationary_pois)=c("t","N","pois")

#P(T_{n+1} > t|S_n)

n=sort(unique(non_stationary_pois$pois))

filenames=list.files("~/ヒッチハイク")

for(j in 1:length(filenames)){
  
  file.remove(paste0("~/ヒッチハイク/",filenames[j]))
  
}
 
for(j in 1:(length(n)-1)){
  
  arrived_time=data.frame(t=non_stationary_pois$t,prob=0)
  
  N=n[j]
  
  for(i in 1:nrow(non_stationary_pois)){
   
  arrived_time$prob[i]=exp(-(intensity_func(arrived_time$t[i]+min(non_stationary_pois$t[non_stationary_pois$pois==N]))-intensity_func(min(non_stationary_pois$t[non_stationary_pois$pois==N])))  ) 
    
  if((arrived_time$t[i]+min(non_stationary_pois$t[non_stationary_pois$pois==N]))>24){
    arrived_time$prob[i]=0
  }
  }
  
 
  
 png(paste0("~/ヒッチハイク/ 時刻",min(non_stationary_pois$t[non_stationary_pois$pois==N]),"で初めて",N,"台通過した時、次に到着する車が時刻t以上である確率.png"))
 
  plot(arrived_time$t,arrived_time$prob,type="o",col=2,xlab="t",ylab="prob",main=paste0("時刻",min(non_stationary_pois$t[non_stationary_pois$pois==N]),"で初めて",N,"台通過した時、次に到着する車が時刻t以上である確率"))
  
  dev.off()
  
   plot(arrived_time$t,arrived_time$prob,type="o",col=2,xlab="t",ylab="prob",main=paste0("時刻",min(non_stationary_pois$t[non_stationary_pois$pois==N]),"で初めて",N,"台通過した時、次に到着する車が時刻t以上である確率"))
 
   write.csv(arrived_time,paste0("~/ヒッチハイク/ 時刻",min(non_stationary_pois$t[non_stationary_pois$pois==N]),"で初めて",N,"台通過した時、次に到着する車が時刻t以上である確率.csv")) 
  
}


```
数量化三類（多変量解析入門Ⅰ　河口至商先生）

数量化三類のプログラムを書いてみました。書いたばかりなので、徐々に修正していきます。

```{r}
#数量化3類
data=data.frame(パターン=1:13,個数=c(1,3,2,5,3,2,4,3,1,1,3,1,1),無口である=c(0,0,0,0,0,0,0,1,0,1,0,0,0),生真面目である=c(1,0,0,0,1,0,0,0,0,1,0,0,0),空想を好む=c(1,1,0,0,0,0,1,0,0,0,1,0,1),活発である=c(1,0,0,1,0,0,1,0,0,0,1,1,1),冗談をいう=c(1,1,0,1,0,1,1,0,1,0,0,0,0),きれい好きである=c(0,0,1,0,1,0,0,1,1,0,0,0,0),粘り強い=c(0,0,0,0,1,0,0,1,1,1,0,1,1))
matrix=data[,3:ncol(data)]
matrix=matrix(unlist(matrix),ncol=ncol(matrix),nrow=nrow(matrix))
m=apply(data[,3:ncol(data)],1,sum)
n=data$個数
b=t(matrix)%*%n
C=(1/(t(t(c(sqrt(b))))%*%t(c(sqrt(b)))))*(t(matrix)%*%diag(c(n/m))%*%matrix)
p=sqrt(eigen(C)$values[2])
z=eigen(C)$vectors[,2]
u=z/sqrt(b)
v=c()
for(j in 1:nrow(matrix)){
  v=c(v,sum(matrix[j,]*u)/m[j])
}
```

```{r}
#u:性格のクラス分け

library(dplyr)


x=rep(u,500)

u_data=data.frame(cluster=1:ncol(matrix),L=0)



cluster_num=3

C=c_s=sample(x,cluster_num)

ite=10

Data=data.frame(num=0,C=t(C),L=0)
for(k in 1:ite){

 X=data.frame(x=x,c=0,L=0)
 
for(j in 1:length(x)){
  x_one=x[j]
  c_x=data.frame(num=1:length(C),c=C) %>% dplyr::mutate(L=(x_one-C)^2)
  X$c[j]=c_x$num[c_x$L==min(c_x$L)]
  X$L[j]=min(c_x$L)
}
 
XX=X %>% group_by(c) %>% summarise(Center_of_gravity=mean(x),L=sum(L)) 

C=XX$Center_of_gravity

data=data.frame(num=k,C=t(C),L=sum(XX$L))
Data=rbind(Data,data)
print(paste0("C=",C))
print(paste0("L=",sum(XX$L)))
}

plot(c(1:nrow(X)),X$x,type="p",ylim=c(min(X$x),max(X$x)),col=2,xlab="u_vector",ylab="value",main=paste0("cluster_num:",cluster_num))

for(j in 1:cluster_num){
  
  par(new=T)
  
  plot(c(1:nrow(X)),rep(C[j],nrow(X)),type="l",ylim=c(min(X$x),max(X$x)),col=1,xlab="u_vector",ylab="value",main=paste0("cluster_num:",cluster_num))
}

c_s
```

```{r}
#v:パターンの分類

library(dplyr)







cluster_num=6

num=floor(length(v)/cluster_num)

x=rep(v,300)

C=sample(v,cluster_num)



ite=30

Data=data.frame(num=0,C=t(C),L=0)
for(k in 1:ite){

 X=data.frame(x=x,c=0,L=0)
 
for(j in 1:length(x)){
  x_one=x[j]
  c_x=data.frame(num=1:length(C),c=C) %>% dplyr::mutate(L=(x_one-C)^2)
  X$c[j]=c_x$num[c_x$L==min(c_x$L)]
  X$L[j]=min(c_x$L)
}
 
XX=X %>% group_by(c) %>% summarise(Center_of_gravity=mean(x),L=sum(L)) 

C=XX$Center_of_gravity

data=data.frame(num=k,C=t(C),L=sum(XX$L))
Data=rbind(Data,data)
print(paste0("C=",C))
print(paste0("L=",sum(XX$L)))
}

plot(c(1:nrow(X)),X$x,type="p",ylim=c(min(X$x),max(X$x)),col=2,xlab="u_vector",ylab="value",main=paste0("cluster_num:",cluster_num))

for(j in 1:cluster_num){
  
  par(new=T)
  
  plot(c(1:nrow(X)),rep(C[j],nrow(X)),type="l",ylim=c(min(X$x),max(X$x)),col=1,xlab="u_vector",ylab="value",main=paste0("cluster_num:",cluster_num))
}

c_s
```
Juliaのライブラリの書き方

## はじめに
Juliaという言語は主に数値計算で使われている言語ですが，ライブラリがまだあまり豊富ではないので簡単なライブラリ（パッケージともいう）の書き方を紹介したいと思います．
また，本記事のJuliaのバージョンは0.62を対象としています．

## どのようにつくるのか
PkgDevを使います．
https://github.com/JuliaLang/PkgDev.jl

インストール方法はjuliaを起動するかjupyterのjuliaカーネル内で
**Pkg.add("PkgDev")**　と実行します．
そのあとにusing PkgDevを実行．

**ライブラリのひな形を生成するには以下を実行します．**
**PkgDev.generate(ライブラリ名,ライセンス)**

今回下記で紹介しているライブラリを作成する場合は
PkgDev.generate("AddTwoDigit","ASL")

### 使用可能なライセンスの種類
[MITライセンス](https://ja.wikipedia.org/wiki/MIT_License) ： "MIT", 
[BSDライセンス](https://ja.wikipedia.org/wiki/BSD%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9) ： "BSD", 
[ISCライセンス](https://ja.wikipedia.org/wiki/ISC%E3%83%A9%E3%82%A4%E3%82%BB%E3%83%B3%E3%82%B9) : "ISC", 
[Apacheライセンス](https://ja.wikipedia.org/wiki/Apache_License) : "ASL", 
[Mozilla Publicライセンス](https://ja.wikipedia.org/wiki/Mozilla_Public_License) : "MPL", 
[GPLバージョン2.0ライセンス](https://ja.wikipedia.org/wiki/GNU_General_Public_License) : "GPL-2.0+", 
[GPLバージョン3.0ライセンス](https://ja.wikipedia.org/wiki/GNU_General_Public_License) : "GPL-3.0+", 
[LGPLバージョン2.1ライセンス](https://ja.wikipedia.org/wiki/GNU_Lesser_General_Public_License) : "LGPL-2.1+", 
[LGPLバージョン3.0ライセンス](https://ja.wikipedia.org/wiki/GNU_Lesser_General_Public_License) : "LGPL-3.0+"

使用可能なライセンスの一覧は次のコマンドで表示できます．
**PkgDev.license()**

## 実際に作ったライブラリ
AddTwoDigit.jl
構造を理解するために世界一簡単であろう数字（Float64）を２つ足すだけの単純なライブラリです．
（PkgDevを使用せずに作ったので一部ファイル構造が異なります．）
https://github.com/Ooshita/AddTwoDigit.jl

## ライブラリの構造
関数群であり自分で作成する．
ここでは数字を足すだけ．

```src/add_two.jl
# Float64型の数字を足すだけの関数
function add_two_digit(d1::Float64, d2::Float64)
    return d1 + d2 
end 
```

こっちはファイル名を指定される．PkgDevを使えば自動生成．

```src/AddTwoDigit.jl
module AddTwoDigit
    export add_two_digit # add_two_digit関数を使えるようにする．複数の関数がある場合はカンマ(,) で区切り宣言する．
    include("add_two.jl") # add_two.jlを読み込み関数を使えるようにする．
end
```

### 簡単なテスト
テストは基本的にはruntests.jlに書きます．
今回は簡単な数字を足すライブラリなので，1.0＋2.0が3.0だったらOKという簡単なテストです．
詳しいテストの書き方は以下を見てみてください．
https://docs.julialang.org/en/stable/stdlib/test/

```test/runtests.jl
using AddTwoDigit

try
    @assert add_two_digit(1.0,2.0) == 3.0
catch e 
    throw(string(e.msg))
```

テストを書いたらPkg.test()で実行してみましょう．

[追記]
@bicycle1885 さんコメントのように@testを使用して書くほうが現在だと一般的のようです．

### 作ったライブラリのインストール方法
Pkg.publish() でjuliaの組織に登録するように申請することができるそうです．
受諾されるとPkg.add()でインストールできるようになります．
（実際に申請していないので詳しくは分かりません．）

Githubにあげている野良ライブラリの場合は
**Pkg.clone(git@github.com:Ooshita/AddTwoDigit.jl.git)**などでインストールすることが出来ます．
[追記]
また、コメントでの指摘のようにattobotを使う方法もあるそうです．そちらを使うほうが良さそうです．

##最後に
どうでしょう，簡単だという印象を持っていただけたでしょうか．
私自身，Juliaは素人ですが想像以上に簡単に作れることを知りました．
複雑なライブラリを作るのも今回紹介した方法を基礎にしております．トライしてみてはいかがでしょうか．
またJuliaのユニットテストにしろ使い方にしろ書籍がほぼないので誰か書いてください．

現在だと以下の書籍があるようです．

日本語
Anshul Joshi (著),‎ 石井 一夫 ら (翻訳)
[Juliaデータサイエンス―Juliaを使って自分でゼロから作るデータサイエンス世界の探索](http://amzn.to/2FzLVpN)

英語
Zacharias, Ph.D. Voulgaris (著)
[Julia for Data Science](http://amzn.to/2DcWqtX)

Sandeep Nagar (著)
[Beginning Julia Programming: For Engineers and Scientists](http://amzn.to/2oWDvhY)

Ivo Balbaert (著)
[Getting Started With Julia](http://amzn.to/2FsPGKz)


宣伝ですがブログも書いてます．
https://whispon.com
IntelliJ IDEA でimport文の自動削除をオフにしたい

# import文が自動で消えて辛い
使用していないimport文が勝手に消えてしまうために、import文をコピペしたのに消えてしまったり、クラスから先に書かなければ行けなくなったり。

IntelliJでimport文の自動削除をオフにするやり方のメモです。

- メニューの「IntelliJ IDEA」から「Preferences」
- Editor > General > Auto Import
- Optimize imports on the fly　のチェックを外す

これでOKです。もう飛んでいかなくなります。
参考画像はJava/ScalaのOptimize imports on the fly。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/151904/cede8467-da5f-615b-d14f-650bb185e40f.png)
モザイクを消すプログラム(改良版) ※Python、PIL使用

#モザイク除去するまえの画像
![モザイク 消す方法.png](https://qiita-image-store.s3.amazonaws.com/0/240301/85c56f7c-d70d-fb21-46d9-acae53cdf37a.png)

　
  
　
#モザイク除去したあとの画像
![モザイク 消し方.png](https://qiita-image-store.s3.amazonaws.com/0/240301/01f38f0b-9dd0-3a62-ee33-cdeb58b7b4cc.png)



前回つくったプログラムは一度画像を切り取ってからでないとモザイクの処理ができなかったのですが、今回はそのままの画像でモザイクを消すことができるようになりました。

プログラムと解説は次回、投稿する予定です。
ApacheでのFastCGIによるInternal Server Error

##突然のInternal Server Error

Webシステムで長時間処理を行っていた際、なぜか唐突にリクエストが中断され、Internal Server Errorとなった。
サーバー環境としては、以下の通り。

- Windows Server
- Apache2.4
- PHP7
- FastCGI


###メモリ上限

タイムアウトにしては設定時間前にエラーが返ってきている。かなり重めの処理を行っているので、メモリの使用上限をphp.ini上で解除して再度実行してみたけれど、状況変わらず。

###ログ
何かそれらしい情報がないかと思って探ってみるも、全くエラーの情報が出力されておらず。

###mpm_winnt
設定ファイルを読み込むようにしてみたのだけれど、結果変わらず。

###httpd.conf
設定ファイルの見直し。タイムアウトの設定は十分だし、リクエストの問題でもない。

```
<IfModule fcgid_module>
   FcgidInitialEnv PHPRC "c:/php"
   FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 0
   FcgidMaxRequestLen 30000000
   FcgidIOTimeout 1800
   FcgidConnectTimeout 1800
</IfModule>
```

公式のドキュメントを見てみると、それらしき設定を発見。
https://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html#fcgidbusytimeout
確かに時間的にもデフォルトの時間でエラーとなっているっぽいし、重めの処理だから中断されてしまったのかもしれない。そもそもの作りがよくないのだとも言えるけれど。

早速追加して再度実行してみるとエラーは回避された。
最終的に以下のように。

```
<IfModule fcgid_module>
   FcgidInitialEnv PHPRC "c:/php"
   FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 0
   FcgidMaxRequestLen 30000000
   FcgidIOTimeout 1800
   FcgidConnectTimeout 1800
   FcgidBusyTimeout 1800
</IfModule>
```
[CircleCI 2.0][Docker] CircleCI のローカル実行

macOS High Sierra では、コンソールから下記のコマンドで Docker をローカル実行できます。 

``` run-circleci.sh
$ cd /path/to/circleci # .circleci/config.yaml を 設置しているディレクトリに移動
$ curl -o /usr/local/bin/circleci https://circle-downloads.s3.amazonaws.com/releases/build_agent_wrapper/circleci && chmod +x /usr/local/bin/circleci
$ circleci update
$ circleci build
```

ローカルに Docker が入ってないと

`docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?. See 'docker run --help'.`

みたいな感じで怒られるので、その場合は下記のコマンドで Docker をインストールして

``` install-docker.sh
$ brew cask install docker
```

こうするとアプリケーションに Docker がインストールされるので、 Docker のアイコンをクリックして起動。その後、以下のコマンドで立ち上げ。

``` run-docker.sh
$ docker ps
```

参考: 
- [Cannot connect to the Docker daemon on macOS](https://stackoverflow.com/questions/44084846/cannot-connect-to-the-docker-daemon-on-macos)
- [CircleCI2.0でGoをCIする](https://gist.github.com/k-hoshina/3193afdbee67fef7faa7c5586c5311e8)
Windows環境のPHPでLaravelを手っ取り早くデバッグする

PHPの環境を作って、Laravelインストールして、デバッグするまでの一連の手順をメモ。

## 環境
OS:Windows10
IDE:VSCode
Shell:Powershell(cmdでも可)

PHP:7

## 環境構築

### VSCodeのインストール
普通にダウンロードしてインストールします。

### PHPのインストール
[ここ](http://windows.php.net/download)から環境に合ったものをダウンロードして適当なフォルダに展開し、パスを通します。
以下のコマンドで正しくインストールできたか確認しましょう。

```powershell
> php -v
PHP 7.2.3 (cli) (built: Feb 28 2018 05:47:26) ( ZTS MSVC15 (Visual C++ 2017) x64 )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
```

### vscodeの設定
vscodeのユーザー設定に、以下を書かないとダメらしいです。パスは適当に読み替えてください。

```json
  {
    "php.validate.executablePath": "D:\\php-7.2.3-Win32-VC15-x64\\php.exe",
    "php.executablePath": "D:\\php-7.2.3-Win32-VC15-x64\\php.exe",
    "php.suggest.basic": false,
  }
```

### php.iniの設定①
展開したphpフォルダのphp.iniを編集します。
opensslの設定は後でLaravelをインストールするときに必要だったような…忘れましたが。

```diff:php.ini
-; extension_dir = "ext"
+extension_dir = "ext"

-;extension=openssl
+extension=openssl
```

### Composerのインストール
Windowsなので[ここ](https://getcomposer.org/)からインストーラーをダウンロードしました。多分、コマンドラインからでもインストールできると思います。
以下のコマンドで正しくインストールできたか確認しましょう。

```powershell
> composer -V
Composer version 1.6.3 2018-01-31 16:28:17
```

### xdebugの入手
[ここ](https://xdebug.org/download.php)から環境に合ったものをダウンロードして、先ほど解凍したphpフォルダのextフォルダ内に置きます。

### php.iniの設定②
xdebug用の設定を追加します。dllのバージョンは読み替えてください。

```ini:php.ini
[xdebug]
zend_extension="php_xdebug-2.6.0-7.2-vc15-x86_64.dll"
xdebug.remote_enable=1
xdebug.remote_autostart=1
```

### npmのインストール
すみません省略します。。。普通にnodejsのインストーラを使うか、nodistを使ってnodejsをインストールしてください。

## laravelプロジェクト作成

### laravelインストール
laravelのインストールにはcomposerのcreate-projectを使う方法と、composerでlaravelインストーラーを落とす方法があるらしいのですが、今回は後者を使用します。
まずは、laravelインストーラーをグローバル領域にダウンロード。

```powershell
> composer global require "laravel/installer"
```

これでlaravelコマンドが使えるようになりますので、プロジェクトを作成します。

```powershell
> laravel new hello-laravel
```

カレントディレクトリの直下にプロジェクトフォルダ`hello-laravel`が作成され、必要なファイルがコピーされます。フォルダさえできてしまえば、あとはvscodeでそのフォルダを開き、`ctrl+@`でターミナルを開いて操作するのがおすすめです。

### 必要なモジュールをインストール
以下を実行して必要なモジュールをlaravelにインストールします。

```powershell
> composer install
> npm install
```

### vscodeのデバッグ設定
vscodeでプロジェクトフォルダを開き、画面左の虫マークを選択してデバッグモードに入り、歯車マークを押して`PHP`を選択すると、PHP用のlaunch.json`が生成されます。私はデフォルトのままです。

```json
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000
        },
```

### サーバー実行
ターミナルから以下を実行し、開発サーバーを立ち上げます。

```powershell
> php artisan serve
Laravel development server started: <http://127.0.0.1:8000>
```

この状態で、`http://localhost:8000`にてlaravelのトップページが表示できるようになっていると思います。

### デバッグ実行

vscodeでF5を押します。ステータスバーがオレンジになったでしょうか？
後は適当なところにブレークポイントを置いて、サーバーにアクセスすればブレークできます。とりあえず試すなら、`/route/web.php`の`return view('welcome');`の行にブレークポイントを置いて、トップページにアクセスしてみれば確認できます。

## おわりに
最初はdockerでapache立ててphp入れて、とかいろいろやっていたんですが、PHPはビルトインサーバーが普通に使えるので、ちょっと試すだけならローカルでデバッグしちゃったほうが簡単な気がしました。
Processingをコマンドラインから実行する

processing-javaを使ってProcessingをコマンドラインから実行する際に、
引数の順番やパスの指定方法でつまずいたのでメモ。
パスは絶対パスで渡して、`--build`, `--run`, `--present`, や `--export`オプションは最後に渡す。
`--output`などは任意。

```bash
processing-java --sketch=/PATH/TO/SKETCH_DIRECTORY --output=/PATH/TO/SKETCH_DIRECTORY/output --build
```

# 参考

- https://github.com/processing/processing/wiki/Command-Line
- http://hoshi-sano.hatenablog.com/entry/2013/08/01/213236
reflectとinterface型の威力

# 目的
非常に簡単な例を用いて、[reflect](https://golang.org/pkg/reflect/)と[interface{}](https://golang.org/ref/spec#Interface_types)の便利さを知る

# 簡単な例
例えば、こんな感じにstructが定義されているとする。

```go
type ParamA struct {
    UserID   string
    Contents string
}

type ParamB struct {
    UserID string
    Price  int
}

type ParamC struct {
    UserID string
    IsLike bool
}
```

この時、**UserIDを抽出する処理**をどう書くか、という話

## 普通の書き方
単純に書くとこうなる

```go
func A_API(p ParamA) {
    uid := ParamA.UserID
}

func B_API(p ParamB) {
    uid := ParamB.UserID
}

func C_API(p ParamC) {
    uid := ParamC.UserID
}
```

## reflectとinterface{}を使った書き方
「*paramからUserIDの値を抜き出す処理*」を**メソッド化**してみる

```go
func A_API(p paramA) {
    uid := getUserID(p)
}

func B_API(p paramB) {
    uid := getUserID(p)
}

func C_API(p paramC) {
    uid := getUserID(p)
}

func getUserID(s interface{}) string {
    ref := reflect.ValueOf(s)
    userID := ref.FieldByName("UserID").Interface()
    uid, err := userID.(string)
    // TODO: エラーハンドリング

    return uid
}
```
jsでメディアクエリ制御したい時はwindow.matchMediaがいいみたい

CSSでのメディアクエリ制御`@media (max-width: 768px)〜`みたいなのには慣れているけどjsで制御する時に`innerWidth`の幅を取得して〜resizeイベントで幅を比べて〜resizeイベントが発火しまくるのを防ぐためにsetTimeoutで間引いて〜とかやったりしててわーーっとなってた人はwindow.matchMedia使うといいよっていうメモです。

window.matchMediaの使い方
---

[window.matchMedia](https://developer.mozilla.org/ja/docs/Web/API/Window/matchMedia)

[DEMO](https://codepen.io/shirahama_mika/pen/NyGWaw)

```javascript

$(function() {
  var mq = window.matchMedia('(max-width: 768px)');// 横幅768px以下の時
  function checkBreakPoint(mq) {
    if (mq.matches) {
      $('.menu').text('SPです');
      $('.menu').css('background', '#000');
    } else {
      // PC向け
      $('.menu').text('PCです');
      $('.menu').css('background', '#f00');
    }
  }
  // ブレイクポイントにイベント設定
  mq.addListener(checkBreakPoint);

  // 初回チェック
  checkBreakPoint(mq);
});


```
画像の出し分けだけならhtml5のpicture要素を使うのもあり
[HTML 5.1の新要素picture入門](https://qiita.com/tonkotsuboy_com/items/8c7c7b5f4794c95db805)

ただしIE11が未対応でポリフィルを使わないといけないのが個人的にはネックなのでまだあまり使ってないです。

参考
---
* [window.matchMedia をそろそろ活用してもいい頃](https://qiita.com/amamamaou/items/a29b29f5267196a5e4ea)
* [$(window).resize()は使わず、window.matchMediaを使って、jsでのメディアクエリー的な事をしてみよう的なお話](http://watanabeyu.blogspot.jp/2015/08/windowresizewindowmatchmediajs.html)
AWSのEC2インスタンスでNode.jsのアプリを作った時のメモ

#はじめに
Node.jsで書いたアプリをローカルだけでなくサーバーで動かしたかった．
AWSのEC2の無料枠を使ってうまいことやりたい．
一旦リンクとつまづいたところをメモしておく（後日整形して綺麗にまとめたい）

#EC2インスタンス立ち上げ
- サービス -> コンピューティング -> EC2 -> インスタンスの作成
- Amazon Linux AMI 2017.09.1 ~ のやつ選択
- インスタンスのセキュリティグループ設定を編集 -> インバウンドにHTTPを追加

##SSH / SFTP 接続の仕方
- pemファイルをダウンロード（なぜか.txtなので.pemにする）
- `chmod 400 [ファイル名].pem`をやっておく

```terminal:
$ ssh -i [.pemへの絶対パス] ec2-user@[パブリック DNS (IPv4)]
$ sftp -i [.pemへの絶対パス] ec2-user@[パブリック DNS (IPv4)]
```

##SSH接続時，$より前の部分の名前を変える方法
`/home/ec2-user`ディレクトリの中の`.bashrc`を編集

```shell:
# .bashrc

PS1="\[\033[36m\]ユーザー名とか:\W $ \[\033[0m\]"

# Source global definitions
if [ -f /etc/bashrc ]; then
	. /etc/bashrc
fi

# User specific aliases and functions
```

こんな感じにする． 
`# Source global ~`より後の部分より先に`PS1~`のコマンドを書かないと反映されない

#SSH接続してとりあえずやること
- `$ sudo yum update` システムアプデ
- `$ sudo yum -y install gcc-c++` gccインスコ
- `$ sudo yum -y install git` gitインスコ
- `$ git clone https://github.com/creationix/nvm.git ~/.nvm` nvmインスコ
- nvmのパスを通す

```.bash_profile:追記する
# nvm
if [[ -s ~/.nvm/nvm.sh ]] ; then
        source ~/.nvm/nvm.sh ;
fi
```

#node.jsの導入
- `$ nvm install [バージョン番号]`
- `$ nvm use v[バージョン番号]`

#forever.jsの導入
`$ npm install forever -g`

##Nodeのデーモン化
- `$ forever start [nodeファイル.js]` 開始
- `$ forever stop [nodeファイル.js] or ジョブ番号` 停止
- `$ forever list` ジョブ一覧

##Apache2.4の導入
```shell:
yum list | grep httpd24
sudo yum install -y httpd24
sudo service httpd start
```
#バーチャルホストの設定
- ドメインを手に入れる（お名前.comを使う場合は）
- Apacheをセットアップする
 - `$ sudo yum install httpd`
 - `$ sudo chkconfig httpd on`
- `/etc/httpd/conf/httpd.conf`を編集

末尾に追加

```shell:
NameVirtualHost *:80
<VirtualHost *:80>
    #DocumentRoot /var/www/[ディレクトリパス]
    ServerName [とったドメイン]
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/
</VirtualHost>
```

3000はnodeアプリを動かすポート番号

Apacheの再起動
`sudo service httpd restart`

##ImageMagickのインストール
[ImageMagickの最新版をEC2にインストールする](https://qiita.com/tak74/items/ad319e5af95dbd8fdf31)

#参考
[AWS EC2でNodeを動作させる](https://qiita.com/oishihiroaki/items/bc663eb1282d87c46e97)
[Linux上でNode.jsを常駐化する方法](https://qiita.com/koheishingai/items/264887a447aca1f8eac3)
[Amazon EC2でnode.js,Expressアプリケーションを立ち上げる](https://qiita.com/Sugima/items/670924901e38cf9eb84a)

[Amazon LinuxにApacheをセットアップする方法](http://promamo.com/?p=2924)
[[Sy] Amazon Linux + Apache2.4系 でのバーチャルホストの設定方法](https://utano.jp/entry/2016/10/amazon-linux-apache-24-virtualhost/)
MacでRuby on Rails環境構築

Railsの勉強を始めたので環境構築メモ。

# 環境
macOS Sierra バージョン 10.12.6

## 手順
ざっくり以下の手順で進めます。

- Homebrewのインストール 
- rbenvのインストール
- Railsのインストール
- アプリケーションの作成

ターミナル上でコマンド実行していきます。

# Homebrewのインストール
```
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
環境によってはWarning出るかもなので以下も参考に。
[MacにHomebrewをインストールする手順とWarningの解決方法 - Qiita](http://qiita.com/unsoluble_sugar/items/6ac1848ba1933ac05c76)
[Homebrewのアップデート時に出た5つのWarningと解決方法 - Qiita](http://qiita.com/unsoluble_sugar/items/acaffa6d0e28c3c24934)

# rbenvのインストール
複数バージョンのRubyをインストールしたり切り替えるためのツール。

```
brew install rbenv ruby-build
```

## rbenvがインストールされたか確認
```
rbenv --version
```

## ターミナル起動時にrbenvの初期化が自動実行されるよう設定
```
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
```

# Rubyのインストール
必要なバージョン番号を指定する。

```
rbenv install 2.3.0
```

## インストールされているRubyの確認
```
rbenv versions
```
![スクリーンショット 2018-03-07 01.28.32.png](https://qiita-image-store.s3.amazonaws.com/0/6380/2fd21f71-7c59-15b6-fd7a-b4db72d05468.png)

## 使用するRubyバージョンの切り替え
```
rbenv local 2.3.0
```
バージョン切り替え後にターミナルを再起動しないと反映されないっぽい。

# Railsのインストール
```
gem install rails --version "4.2.1" --no-rdoc --no-ri
```

## Railsのバージョン確認
```
rails -v
```

# アプリケーションの作成
```
rails new sample
```

## アプリケーションサーバーの起動 
```
cd sample
bin/rails s
```
![スクリーンショット 2018-03-07 01.21.42.png](https://qiita-image-store.s3.amazonaws.com/0/6380/dd507fb9-649b-4aee-b601-4a17c2285b21.png)


ブラウザで [http://localhost:3000](http://localhost:3000)にアクセス。Railsアプリケーションの初期画面が表示されれば成功。
![スクリーンショット 2018-03-07 01.22.32.png](https://qiita-image-store.s3.amazonaws.com/0/6380/53f83b0e-7ee9-e2be-6cba-275802659b1e.png)

ここからコントローラーとアクションを作成していく。

### sqlite3のエラーが出た場合

サーバー起動時に以下のエラーが出る場合は、追加で対応が必要です。
![スクリーンショット 2019-03-11 09.46.02.png](https://qiita-image-store.s3.amazonaws.com/0/6380/114cb395-a773-f8a1-3686-d9eb5fe3f2b2.png)

エラーメッセージを見てみると、ActiveRecordのdatabaseに指定しているsqlite3に問題があるようです。

```
Specified 'sqlite3' for database adapter, but the gem is not loaded. Add `gem 'sqlite3'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord).
Extracted source (around line #316):
```

どうやらGemfileに記述されているsqlite3にバージョン指定がないため、最新バージョンがインストールされていました（今回の環境ではv1.4.0）。sqlite3 v1.4.0はActiveRecordが未対応のため、本エラーが発生する模様。

[Ruby on Rails - Error loading the 'sqlite3' Active Record adapter. Missing a gem it depends on?エラーで困ってます｜teratail](https://teratail.com/questions/172993)

Gemfileのバージョン指定で、sqlite3のバージョンを1.3.6まで落とすと起動できるようになります。

```:Gemfile
# gem 'sqlite3'
gem 'sqlite3', '~> 1.3.6'
```
Gemfileの記述を変更後、`bundle install`を実行しましょう。

```
$ bundle install
```

ブラウザを再読込み（もしくはサーバー再起動）すると、画面が表示されるはずです。
もし別のエラーが出る場合は、エラーメッセージを見ながら対応しましょう。
PHP でテストコードを意識したコーディング

どれもこれも常識的な話で恐縮ですが、レガシーシステムと格闘する中で感じることのメモです

## 1. exit をベタベタ書かない

テスト対象に`exit`があると、当然 PHPUnit もそこで終了してしまいます
まずは`exit`の代わりに`return`で代用できないか考えます

ただ、どうしても`exit`が必要な場合があります
例えば [header()](http://php.net/manual/ja/function.header.php) した直後の`exit`などの場合です

その場合はフラグを持たせてやり、phpunit 実行時にはフラグを true にしてやることで exit しないようにしています

こんなイメージです

~~~php
class Example
{
    // テストフラグ
    private $isTest = false;

    public function sample()
    {
        header("Location: http://www.example.com/");
        // テストじゃなかったら exit させる
        if (!$this->isTest) {
            exit;
        }
    }
}

~~~

もちろん、フレームワークを使用している場合はフレームワークが用意してくれているリダイレクトメソッドなりを使用することで、そちらに`exit`しないフラグも用意されていると思いますので、自前でテストフラグを作る機会は少なくなると思います

## 2. time() をベタベタ書かない

テスト対象に`time()`があると テストが成功したり失敗したりします
テストコードで`time()`した期待値と、テスト対象の`time()`でズレる可能性があるからです

ありがちなのが、DB に登録日時や更新日時を登録する際に、Model 内で`time()`しちゃってそのまま登録している例です

こういう場合は`time()`の結果は引数などで外から渡してやるようにするか、`time()`する箇所を 1 箇所にするかした方がテストしやすいですね

~~~php
class ExampleModel
{
    public function sample($time)
    {
        // $time を引数で外から渡してもらう
    }

    public function getCurrentTime()
    {
        // もしくは time() 専用の function を作って他では time() しないようにする
        // テスト実行時はこの function を runkit で上書きして固定値にしちゃう
        return time();
    }
}
~~~

ただ、既存のほとんどの Model が Model 内で`time()`していた場合で、"俺様"が作った Model だけ外から`time()`の結果を渡してもらったりすると、"日時"の仕様が変わってきてしまい、なかなか難しいですね

なのでリファクタリングできない場合は、テスト実行時に`time()`を runkit で上書き、とかが多い気がします・・

## 3. require_once をベタべタ書かない

`require_once`をあちこちにベタベタ書くと、接着剤をぶちまけたように疎結合でなくなり、スタブやモックを注入し辛くなり、結果テストがし辛くなりますね

なのでできるだけフロントやコントローラーで必要な class を require してやります
もしくはオートローダーを使用し、テスト実行前にスタブやモックをロードしてやれる仕組みを作るのがいいと思います

## 4. 1 つの function は 1 つの責務で短く

長い function を書いてしまうと、まずテストをするための準備コストが増大しますね
また、色々なテストケースを詰め込んでテストするため、保守もし辛い
その結果、テストコードのテストに時間がかかるようになってしまっては本末転倒だと思います

function が長くなる理由は if 文で全て何とかしようと思うことに原因があると思うので、ポリモーフィズムや DRY を常に意識しています

また、エラーフラグの変数を用意してエラー処理・・とかも 1 function が長くなりがちなので、基本は例外で書くようにしています

1 function を短くするコツはやはり命名にあるので、日頃からセンスを磨いていきたいなあと思います

## 参考

「現在時刻」を外部入力とする設計と、その実装のこと
http://techlife.cookpad.com/entry/2016/05/30/183947
Windows Subsystem for LinuxのUbuntu 16.04にRailsをインストールする

# はじめに
Windows Subsystem for LinuxのUbuntu 16.04にRuby on Rails (5.1.5)をインストールした際に何点かハマりました。最終的に上手くいった手順を備忘録としてメモしておきます。

誤りや修正点等ございましたらコメントしていただけると嬉しいです:bow:

# 実行環境
- Windows 10 Home (Fall Creators Update適用済)
  - Windows Subsystem for LinuxでUbuntu 16.04.4 LTSを起動
- 新規UNIXユーザー作成直後からスタート

# Rubyのインストール
Rubyをビルドする際に必要なパッケージをインストールします。

```console:console
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install -y git build-essential libssl-dev libreadline-dev
```

rbenv、ruby-buildをインストールします。

初めはここで`sudo apt install rbenv ruby-build...`としてaptでインストールしたのですが、どうやらインストールされるrbenv、ruby-buildのバージョンが古い？ようで、インストールできるRubyのバージョンの選択肢が少ないという事象に陥りました。

以下の通り公式のレポジトリから直接持ってくると上手くいきました。

```console:console
$ git clone https://github.com/rbenv/rbenv.git ~/.rbenv
$ git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
```

`~/.profile`を編集し以下の行を追加します。

```~/.profile
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"
```

`~/.profile`をリロードします。

```console:console
$ source ~/.profile 
```

記事執筆時点での最新版`2.5.0`をインストールします。

```console:console
$ rbenv install 2.5.0
$ rbenv global 2.5.0
```

以上でRubyのインストールができました。

```console:console
$ ruby --version
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]
```

# Railsのインストール
Railsを動かす際に必要なパッケージをインストールします。

```console:console
$ sudo apt install -y libsqlite3-dev nodejs
```

（2018/11/05 追記）上記コマンドでインストールされるNode.jsのバージョンが古いため、Railsで使用するgemでエラーが出ることがありました。Node.jsをアップデートすることで解決しました。

参考「[とりあえず Ubuntu で新しい Node.js, npm をインストール - Qiita](https://qiita.com/kerupani129/items/60ee8c8becc2fe9f0d28)」

---

Railsをインストールします。

```console:console
$ gem install rails
$ rbenv rehash
```

以上でRailsのインストールができました。
確認のためアプリを起動してみます。

```console:console
$ rails new rails-test --skip-bundle
$ cd rails-test
$ bundle install --path vendor/bundle
$ bundle exec rails s
```

ブラウザで`localhost:3000`にアクセスします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/179574/4cb1297a-25e5-c612-8d1f-56353718451a.png)
Yay！⌒°( ･ω･)°⌒:train::train::train:

# 参考URL
- [Ubuntu 16.04にrbenvでRubyのバージョンを管理する](https://symfoware.blog.fc2.com/blog-entry-2073.html)
メールサーバの構築でポートが開かなくてハマった

# 現象

環境はConoHaのVPS、CentOS7.4
Postfixの設定をしたが、外部から見れない

Firewallも設定した
![image.png](https://qiita-image-store.s3.amazonaws.com/0/71557/0f4a129b-d664-8c84-9f53-48eeeb594810.png)

ConoHaのコンパネからも設定した
![image.png](https://qiita-image-store.s3.amazonaws.com/0/71557/f66c749f-4b68-a547-21da-fbcff2158245.png)

ローカルなら開いてる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/71557/a0cb019c-35fb-8e5b-e52f-c7917c0aa961.png)

外部から見ると開いていない
![image.png](https://qiita-image-store.s3.amazonaws.com/0/71557/2cdbeb0b-4cdf-f91f-5e5e-f43d520c2225.png)

？？？！？？！:thinking_face::thinking_face::thinking_face::thinking_face:

# 原因究明

## なんとなくnmapをtcpdumpしてみた
問題のサーバA側で
`tcpdump port 465 -w mailtest.dump`
を実行し、別のサーバBで
`nmap AのIPアドレス -p 465 -ttl 64`
として、ダンプされた`mailtest.dump`をWiresharkで見てみると、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/71557/4d38becf-374f-177f-8e06-dfdb614c3831.png)
となり、`[SYN]`に対し、`[RST,ACK]`が返されているのでやっぱりポートは閉じている。
ちなみにAが受信した時点でのttlは50。

比較のため、
Aで
`tcpdump port 80 -w httptest.dump`
を実行し、別のサーバBで
`nmap Aアドレス -p 80 -ttl 64`
として、ダンプされた`httptest.dump`をWiresharkで見てみると、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/71557/a6a16695-0985-a781-6a50-2544af3a910c.png)
となり、`[SYN]`に対し、`[SYN,ACK]`が返されているのでやっぱりポートは開いている。
ちなみにAが受信した時点でのttlは50。

よくわかんない結果となったが、ここで注目したのはTTLの値で、両方同じ値であることから、`[SYN]`をはじいているのは**途中にあるルータとかではなく、サーバ自身**であることがわかる。

## 初心に帰って`netstat`してみる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/71557/fa01ba3c-635e-e679-852d-c7a0575cbaaf.png)
`smtps`と`smtp`、`LISTEN`はしてるけど`127.0.0.1`でしか聞いてない…！？:thinking_face:

# 原因
`/etc/postfix/main.cf`
![image.png](https://qiita-image-store.s3.amazonaws.com/0/71557/18ce77b4-974b-3253-e3c9-d942c83d0224.png)
それはそうの舞:dancer::dancer:

# 感想
`tcpdump`のくだり必要だった？

この記事を書いていたら`3306`番が開いているのに気付いた。調べたらMySQLってFirewallの設定に関係なくデフォルトで3306番をLISTENしているらしい。ちょっと怖い。
riot.jsでマウスムーブイベントでグリグリ動かす方法

# 最初
riotとsvgを使って手軽にぐりぐりできないかと思った。

# onclickイベント？
[公式のドキュメント](http://riotjs.com/ja/guide/)とかを見ていると日本語ではonclickとかoninputとかのイベントしか記載がない…
試しにonmousemoveを下記のようにしてみたら動いた。

```html
<circle onmousemove={move} cx="10" cy="20" r="20" fill="blue" />
```

# マウスの場所…
通常、マウスのイベントの戻り値としてマウスの情報が飛んで来るのだが、riotは...？
適当に引数を追加し参照したところそれっぽい物が戻ってきていた。

```javascript
move(e){
  console.log(e);
}
```

# 要素への参照
マウスイベントの戻り値のpathに要素をみつけたので下記のように記載

```javascript
    move(e){
      e.path[0].setAttribute("cx",e.offsetX);
      e.path[0].setAttribute("cy",e.offsetY);
    }
```
これでうまく動きました。

#全体のソース

```sample.tag
<sample>
<svg id="svg" width="300" height="340" style="border-width: thick; border-color: #EEE; border-style: solid; display: block; margin: auto;">
    <circle onmousemove={move} onmousedown={down} cx="10" cy="20" r="20" fill="blue" />
</svg>
  <script>
    var self=this;
    move(e){
      e.path[0].setAttribute("cx",e.offsetX);
      e.path[0].setAttribute("cy",e.offsetY);
    }
  </script>
</sample>
```

```index.html
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <sample></sample>
    <script type="riot/tag" src="sample.tag"></script>
    <script src="https://cdn.jsdelivr.net/npm/riot@3.8/riot+compiler.min.js"></script>
    <script>riot.mount('sample')</script>
  </body>
</html>
```
Spring Data MongoDBでオレオレSSL証明書を突破する

# 経緯

MongoDBのDBaaSである[Compose for MongoDB](https://www.ibm.com/jp-ja/marketplace/compose-mongodb)は通信がSSL必須になっていますが、それがオレオレ証明書のため、Javaではkeytoolを使ってルート証明書をkeystoreにインポートし、システムプロパティでそのkeystoreを使うよう設定する必要があります。

>[How-to: Connecting to Compose MongoDB with Java and SSL](https://www.compose.com/articles/how-to-connecting-to-compose-mongodb-with-java-and-ssl/)

しかし面倒なのでサーバ証明書の検証を無効にしてしまいます。今回はSpring Data MongoDBの例です。

検証環境
- Spring Boot 2.0.0

# 手順

## 証明書検証の無効化

Spring Data MongoDBを有効にし、AbstractMongoConfigurationのサブクラスを作成します。このとき、SSL証明書の検証を無効化したTrustManagerをSocketFactoryに追加します。

```MongoConfiguration.java
@Configuration
@EnableMongoRepositories
public class MongoConfiguration extends AbstractMongoConfiguration {

	@Value("${spring.data.mongodb.database}")
	private String databaseName;

	@Value("${spring.data.mongodb.uri}")
	private String uri;

	@Override
	protected String getDatabaseName() {
		return databaseName;
	}

	@Override
	public Mongo mongo() throws Exception {
		MongoClientOptions.Builder builder = MongoClientOptions.builder();
		builder.sslEnabled(true);
		SSLContext sslContext = SSLContext.getInstance("SSL");
		sslContext.init(null, new X509TrustManager[] { new MongoTrustManager() }, new SecureRandom());
		builder.socketFactory(sslContext.getSocketFactory());

		return new MongoClient(new MongoClientURI(uri, builder));
	}

}

class MongoTrustManager implements X509TrustManager {

	@Override
	public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		return;
	}

	@Override
	public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
		return;
	}

	@Override
	public X509Certificate[] getAcceptedIssuers() {
		return null;
	}

}
```
本当はkeystoreを使わずにルート証明書を使った検証を実現したかったのですが、それはまた後日研究するかもしれません。
改行を含むcsvをimportしたい

Db2には外部ファイルを読み込んでバルクインサートする機能としてimportが用意されています。importはいくつかのファイル形式に対応しているのですが、もっともよく利用される形式のひとつであるCSVについて、改行を含むcsvをimportするにはどのようにすべきでしょうか?

まずCSVそのものは以下のルールにのっとるものとします。

- 行の区切りはOS依存の改行文字。つまりWindows系ならCRLF(`\r\n`)、UNIX系ならLF(`\n`)。
- フィールドの区切り文字はカンマ(`,`)。
- フィールドにカンマ(`,`)、ダブルクオーテーション(`"`)、改行文字を含む場合は必ずそのフィールドをダブルクオーテーションで囲む。
    - このとき`,`は`","`、`"`は`""`としてそれぞれエスケープする。

基本的にはRFC4180に準拠していますが、違いは2点ほどあります。

- RFC4180では行の区切り文字をCRLFに限定するが、今回はOS依存。つまりUNIX系の場合はLFを改行文字とする。
- RFC4180では「カンマ、ダブルクオーテーション、改行文字を含まないフィールドはダブルクオーテーションで囲っても囲わなくてもよい」とするが、今回はそのようなフィールドについてはダブルクオーテーションで囲まない。
    - 「`modified by chardel"`」とした場合、つまりimportのデフォルトの場合、Db2はダブルクオーテーションで囲まれたフィールドを文字列として認識するため、そのようなフィールドを数値型のカラムにimportしようとすると、失敗する場合があります。
    - 要はいろいろ考えるのが面倒なだけです(´・ω・｀)

このような規則にのっとり、かつフィールドに改行文字を含むCSVファイルは、たとえば以下のようにしてimportします。

```sql
import /hello/world/sample.csv of del 
modified by delprioritychar 
insert_update into sample_table
```

重要なのは`delprioritychar`オプションです。このオプションをしていしない場合、区切り文字の優先順位は以下の通りになります。

1.行の区切り文字 = 改行文字
2.文字列の区切り文字 = `"`
3.フィールドの区切り文字 = `,`

つまり改行文字を見つけた場合、それがフィールドの一部である可能性を考えず、問答無用で行の区切り文字であると認識します。一方`delprioritychar`オプションを指定すると、この優先度が次のように変化します。

1.文字列の区切り文字 = `"`
2.行の区切り文字 = 改行文字
3.フィールドの区切り文字 = `,`

1と2が入れ替わるわけですが、これによりcsvパーサが改行文字を見つけた場合、それがフィールドの一部なのか、行の区切り文字なのかをまず考えてから処理を進めてくれます(´・ω・｀)

参考:

- http://www.kasai.fm/wiki/rfc4180jp
- https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_10.5.0/com.ibm.db2.luw.admin.cmd.doc/doc/r0008304.html
Webの言語とは 〜Bashをwebの言語にする〜

（元記事はこっち：[http://www.hakopako.net/entry/2018/03/07/001400](http://www.hakopako.net/entry/2018/03/07/001400)）

# Webの言語とは


<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Goへのコメントが&quot;Webの言語じゃないですよね？&quot;というスライドを見たワシ「Webの言語？！？！？！？！」</p>&mdash; アチク (@_achiku) <a href="https://twitter.com/_achiku/status/970876035355955200?ref_src=twsrc%5Etfw">2018年3月6日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>



身内でも話題になったので。
webの言語とはなにを指しているのだろうと考えたのだけれど、
__ブラウザを介した通信で実行できる言語__ のことを言っているのかなと解釈した。   
　  

# ＞　Bash も webの言語になれるかもしれない　＜

bashでjsonを返してみようと思う。  


- body.sh

```sh
#!/bin/bash
# body.sh

echo '{"message": "Hello World !!!"}'
```

- header.sh

```sh
#!/bin/bash
# header.sh

echo 'HTTP/1.1 200 OK;'
echo 'Content-Type application/json;\r\n'
```

- webサーバ起動

```sh
$ while true; do { sh header.sh; sh body.sh; } | nc -l 8080; done
```


　  

webの言語になれました。
<img width="498" alt="webbash.png" src="https://qiita-image-store.s3.amazonaws.com/0/43218/23df7912-01e6-c715-8c14-15f131c28fb2.png">



以上、~~bashでwebサーバを起動する方法~~ Bashをwebの言語にする方法でした。
install4jが起動しない場合のログ取得方法


インストーラーがinstall4jで作成されているが，そのインストーラーがうまく起動できない場合の対処法。
ただ実行しただけだと何もエラー出さずに落ちるので原因がわからない。

## 環境
macOS 10.13

## 手順
環境変数`INSTALL4J_LOG=yes`を設定してinstall4jのランチャーを起動する。

例：

```sh
INSTALL4J_LOG=yes myLauncher.app/Contents/MacOS/JavaApplicationStub
```

```sh
(省略)
<JAVA_HOME>/lib/ext exists, extensions mechanism no longer supported; Use -classpath instead.
.Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
```
エラーメッセージを取得することができました。
ここから長いデバッグの旅が始まります。

## 参考
[The executable generated by install4j doesnt start](https://stackoverflow.com/questions/27238616/the-executable-generated-by-install4j-doesnt-start)
Phalcon3.xでカスタムバリデーションを書く

* コンテナ起動

```
docker run --rm -it phalconphp/php:alpine-php7-min ash
```

* 実装

```php
/ # cat test.php
<?php

use Phalcon\Validation;
use Phalcon\Validation\Validator;
use Phalcon\Validation\Message;

class CustomValidation extends Validator {
        public function validate(Validation $validator, $attribute) {
                $value = $validator->getValue($attribute);
                $expect = $this->getOption('expect');
                if ($value !== $expect) {
                        $validator->appendMessage(new Message('invalid value', $attribute));
                        return false;
                }
                return true;
        }
}

$validation = new Validation();
$validation->add('hoge', new CustomValidation(['expect' => 1234]));
echo "validation 'hoge'\n";
print_r($validation->validate(['hoge' => 999]));

$validation = new Validation();
$validation->add('fuga', new CustomValidation(['expect' => 1234]));
echo "validation 'fuga'\n";
print_r($validation->validate(['fuga' => 1234]));
```

* バリデーション実行

```
/ # php test.php
validation 'hoge'
Phalcon\Validation\Message\Group Object
(
    [_position:protected] => 0
    [_messages:protected] => Array
        (
            [0] => Phalcon\Validation\Message Object
                (
                    [_type:protected] =>
                    [_message:protected] => invalid value
                    [_field:protected] => hoge
                    [_code:protected] => 0
                )

        )

)
validation 'fuga'
Phalcon\Validation\Message\Group Object
(
    [_position:protected] => 0
    [_messages:protected] => Array
        (
        )

)
```
Nginxでメソッド制限

# Nginxで許可するメソッドを制限する方法

## limit_exceptで簡単に許可するメソッドを制限できる

```nginx
location / {
    limit_except GET HEAD POST { deny all; }
}
```

## 複数locationに設定したい場合

serverディレクティブにこのように書いてあげると良い

```nginx
        if ($request_method !~ ^(GET|HEAD|POST)$ ) {
                return 444;
        }
```

## 参考

- <http://nginx.org/en/docs/http/ngx_http_core_module.html#limit_except>
dockerコンテナの起動・停止をちょっと楽にするシェル関数

dockerコンテナの起動と停止するたびに名前の指定が面倒になってきたので、fzfを使ってシェル関数を作った。

※私はたまたま[peco](https://github.com/peco/peco)より[fzf](https://github.com/junegunn/fzf)派なだけなのでpeco派の人は適宜書き換えていただければいいかと。

※私はシェル関数を`~/.zshrc`に追記してます。

## docker-start

![image.gif](https://i.gyazo.com/231a9f039f6d4f370dd63d42ebf98dbe.gif)

起動していないコンテナを選んでからスタートさせる。

```sh
docker-start() {
  local container
  container="$(docker ps -a -f status=exited | sed -e '1d' | fzf --height 40% --reverse | awk '{print $1}')"
  if [ -n "${container}" ]; then
    echo 'starting container...'
    docker start ${container}
  fi
}
```

## docker-stop

![image.gif](https://i.gyazo.com/aaef1c626d6745c10d4088ab1758d5ac.gif)

起動しているコンテナを選んでからストップさせる。

```sh
docker-stop() {
  local container
  container="$(docker ps -a -f status=running | sed -e '1d' | fzf --height 40% --reverse | awk '{print $1}')"
  if [ -n "${container}" ]; then
    echo 'stopping container...'
    docker stop ${container}
  fi
}
```

## docker-exec-bash

![image.gif](https://i.gyazo.com/afb8295de184c7af6f304cb61eaefb58.gif)

コンテナにbashでつなぐ。
（bashでつなぐことがよくあるので、ついでに作った。）

```sh
docker-exec-bash() {
  local container
  container="$(docker ps -a -f status=running | sed -e '1d' | fzf --height 40% --reverse | awk '{print $1}')"
  if [ -n "${container}" ]; then
    docker exec -it ${container} /bin/bash
  fi
}
```

## docker-logs

コンテナの直近のログを見る。

```sh
docker-logs() {
  local container
  container="$(docker ps -a -f status=running | sed -e '1d' | fzf --height 40% --reverse | awk '{print $1}')"
  if [ -n "${container}" ]; then
    docker logs -f --tail 100 ${container}
  fi
}
```

## docker-rm

起動していないコンテナを選んでから削除させる。

```sh
docker-rm() {
  local container
  container="$(docker ps -a -f status=exited | sed -e '1d' | fzf --height 40% --reverse | awk '{print $1}')"
  if [ -n "${container}" ]; then
    echo 'removing container...'
    docker rm ${container}
  fi
}
```

## docker-rmi

(追記）ディスクいっぱいになってイメージ削除するときにも使えた。

```sh
docker-rmi() {
  local image
  image="$(docker images -a | sed -e '1d' | fzf --height 40% --reverse | awk '{print $3}')"
  if [ -n "${image}" ]; then
    echo 'removing container image...'
    docker rmi ${image}
  fi
}
```

## 参考

fzfのExamplesを参考にしました。
https://github.com/junegunn/fzf/wiki/Examples
SlackBotで電車の運行情報を通知してもらう

毎朝電車の遅延を調べるのが辛いので、個人用Slackに通知してもらうことにしました。

#概要
SlackBotを作成し、決まった時刻に電車の運行情報を通知する。

#使用技術
サーバーを立てているわけではないし、VPSを契約している訳でもないため、GoogleAppScriptを使用。

SlackにBot用ユーザーを作成し、GASのスクリプトを動作させています。

#手順
##１．SlackAppを作成してAPIを取得する

[Slack API](https://api.slack.com/)から、StartBuildingをクリック。

![スクリーンショット 2018-03-26 23.04.11.png](https://qiita-image-store.s3.amazonaws.com/0/92194/f77dbd61-ded6-7329-e71f-3863b1a03d92.png)


アプリ名を入力。  
作成するワークスペースを選択して作成。

とりあえず、Basic InformationのApp Credentialsにある`Verification Token`をメモっておきましょう。  
Verification Tokenの内容を後ほどGASでスクリプトを書く際に必要になります。

##２．SlackAppの設定
画面はそのまま引き続き、今作成したSlackAppをWorkSpaceにインストールします。

アプリをWorkSpaceにインストールするためには権限を設定する必要があるため、

![スクリーンショット 2018-03-26 23.07.08.png](https://qiita-image-store.s3.amazonaws.com/0/92194/03e39eab-1813-4484-24a1-183f3987fc29.png)


上写真部分の `permission scope` をクリック。  
`Send messages as <アプリ名> chat:write:bot`を選択。  
今回はSlackに投稿してもらうだけで大丈夫なので、メッセージを投稿する権限のみ設定しています。

その後`Install App to WorkSpace` が押せるようになるため、押してWorkSpaceにインストール。

これで投稿してもらうBotの準備が整いました。

##３．Google App Scriptでスクリプトを書く

以下のライブラリを使用させて頂きました。  
[Slack BotをGASでいい感じで書くためのライブラリを作った](https://qiita.com/soundTricker/items/43267609a870fc9c7453)

ソースは以下の通り。

```JavaScript:TrainInfo.gs
var slackAccessToken = 'slackappToken';
function test() {
  var slackApp = SlackApp.create(slackAccessToken);
  // 対象チャンネル
  var channelId = "#general";
  var options = {
    // 投稿するユーザーの名前
    username: "TrainInfo"
  }
  
  //電車遅延情報をJSON形式で取得
  var json = JSON.parse(UrlFetchApp.fetch("https://rti-giken.jp/fhc/api/train_tetsudo/delay.json").getContentText());
 
  var name="名古屋本線";
  var company="名古屋鉄道";
  
  // 投稿するメッセージ
  var currentDate = new Date();
  var date = Utilities.formatDate( currentDate, 'Asia/Tokyo', 'M月d日 HH時mm分');
  var message = "◆電車遅延情報 (" + date + "現在)\n 電車遅延情報はありません。";
  
  for each(var obj in json){
 
    if(obj.name === name && obj.company === company){ 
      
      message ="<@U8U7H4KE0|yuina> \n ◆電車遅延情報 (" + date + "現在)\n" + company + name + "が遅延しています。\n詳細はこちら→ http://top.meitetsu.co.jp/em/";

    }
  }
  
  slackApp.postMessage(channelId, message, options);
}
```

今回[鉄道遅延情報のJSON](https://rti-giken.jp/fhc/api/train_tetsudo/)を使用し、遅れている場合にメンションとURLを追加しています。  
１路線しか使っていないためベタ書き状態ですが、複数路線を使用している場合はSpreadsheetを活用するともっとスマートに書けそうです。

##４．GoogleAppScriptのトリガーを設定
GooGle App Scriptに時間帯を指定して指定時刻周辺にSlackにポストしてもらうようにします。

![スクリーンショット 2018-03-27 23.33.03.png](https://qiita-image-store.s3.amazonaws.com/0/92194/14da8eea-497d-f4f1-f471-cf2e3f1e7b66.png)

今回は朝７〜８時と夕方４〜５時にポストしてもらうよう設定しています。


#完成物

![スクリーンショット 2018-03-24 18.43.39.png](https://qiita-image-store.s3.amazonaws.com/0/92194/e59821f6-fc72-dbf9-0652-152f0fe1de8c.png)


こんな感じで通知してくれます。今後改修を進めます。
Flashairをやってみた

Flashairを買ってみたのでこれからいろいろやってみる

まず初めにflashairに固定のIPアドレスを割り当ててpingを送ってみる

CONFIGファイルを以下のように書き換える
書き換えるところをコメントしている
プライベートデータを「*」で伏せる

```c

DHCP_Enabled=NO
IP_Address=192.168.**.* #ipconfigで自分のIPアドレスを調べて最後を1足したものを入力する
Subnet_Mask=255.255.255.0
Default_Gateway=192.168.**.* #手持ちのwifiルータのIPアドレスを入れる 
Preferred_DNS_Server=8.8.8.8
Alternate_DNS_Server=192.168.**.*
UPLOAD=1
CIPATH=/DCIM/100__TSB/FA000001.JPG
APPMODE=5 #4を5にする
APPNAME=flashair17
APPNETWORKKEY=******** #手持ちのwifiルータのパスワードを入れる
VERSION=FA9CAW3AW3.00.02
CID=02544d535731364731d8b4eb7900f601
PRODUCT=FlashAir
VENDOR=TOSHIBA
APPSSID=elecom2g-***** 手持ちのwifiルータのSSIDを入れる
LOCK=1
WEBDAV=1
TIMEZONE=36
DNSMODE=1
BRGSSID=elecom2g-*****
BRGNETWORKKEY=******** #手持ちのwifiルータのパスワードを入れる
APPAUTOTIME=0
```

SDスロットに差しコマンドプロンプトからpingを飛ばす

```shell

C:\Users\user>ping 192.168.**.*
192.168.**.* に ping を送信しています 32 バイトのデータ:
192.168.**.* からの応答: バイト数 =32 時間 =912ms TTL=255
192.168.**.* からの応答: バイト数 =32 時間 <1ms TTL=255
192.168.**.* からの応答: バイト数 =32 時間 =3ms TTL=255
192.168.**.* からの応答: バイト数 =32 時間 =3ms TTL=255

192.168.**.* の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 0ms、最大 = 912ms、平均 = 229ms

C:\Users\user>
```