OmniAICreator/Qiita-1.07M huggingface dataset:
MacとParallelsで仮想マシンのwin8.1のテンポラリファイルを消す方法２

windows8.1でwindowsupdateのトラブル要因になりやすい
テンポラリディレクトリの無駄ファイルを消す。（方法２）

#１．注意点

自己責任で行って下さい。トラブルや損害について一切責任は取りません。

windows8.1 
win以外に必要な物
Parallels desktop11（最新のParallels desktopに同じ機能があるか不明。）
Mac版シェルスクリプトの知識

長所
windows8.1側にcygwinやmsys2のインストールの必要がない。
Macシェルスクリプトが使える。

欠点。
1.Parallels desktop11にwindowsのドライブ共有機能がある。
Parallels起動後、windowsドライブのマウントに数分かかる。

![ScreenCaptured_20200617.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170956/cbb68991-590f-eb95-54e0-f3f39faa95ef.jpeg)


#２．ソース

UTF8、LFで作成。
数ヶ月の実績あり。

```
#!/usr/local/bin/bash

# this is utf-8

echo '以下はMacのディレクトリです'
echo $PWD
echo " "

if [ -d "/Volumes/C/Users/xxxxxxxx" ]; then
  echo "/Volumes/C/Users/xxxxxxxx is exist . "
  echo "マウント出来てます"
else
  echo "/Volumes/C/Users/xxxxxxxx is NOT exist . "
  echo "windowsをマウント出来てません"
  exit 1
fi
echo
echo

cd /Volumes/C/Windows/temp
echo '以下はwin8.1のディレクトリです'
echo $PWD
ls -lGhtar
VAR1=`du -h -d 0`
echo "元の容量は $VAR1"
rm -f *.log *.tmp *.temp
ls -lGhtar
echo "容量は $VAR1 から $(du -h -d 0)"
sleep 3
cd /Volumes/C/Windows/Logs/cbs
echo $PWD
ls -lGhtar
VAR1=`du -h -d 0`
echo "元の容量は $VAR1"
sleep 1
rm -f *.log *.tmp *.temp
ls -lGhtar
echo "容量は $VAR1 から $(du -h -d 0)"
sleep 3
cd /Volumes/C/Users/xxxxxxxx/Appdata/Local/temp
echo $PWD
ls -lGhtar
VAR1=`du -h -d 0`
echo "元の容量は $VAR1"
sleep 1
rm -f *.log *.tmp *.temp
rm -rf chrome_url*
ls -lGhtar
echo "容量は $VAR1 から $(du -h -d 0)"

echo
echo
cd ~/bin
echo '以下はMacのディレクトリです'
echo $PWD
```

#３．参考リンク


[powershell4でwindows8.1のテンポラリディレクトリの無駄ファイルを消す。 - Qiita](https://qiita.com/shiro_yone/items/4a847e1ff1b2d7466bf7)

以上
オプションなし git pull でデフォルトの挙動が未設定だと警告が出る

## 概要

Git のアップデート後に `git pull` を実行したら警告が出た。

> warning: Pulling without specifying how to reconcile divergent branches is discouraged. You can squelch this message by running one of the following commands sometime before your next pull ...

## 原因

最新版の `2.27.0` から表示されるようになったらしい。

> "git pull" issues a warning message until the pull.rebase configuration variable is explicitly given, which some existing users may find annoying---those who prefer not to rebase need to set the variable to false to squelch the warning.

## 解決策

警告で提示されているように、pull のデフォルトの挙動が `fetch + merge` なのか、`fetch + rebase` なのか、または `fast-forward` なのかを config で設定する。

```sh
git config pull.rebase false  # merge (the default strategy)
git config pull.rebase true   # rebase
git config pull.ff only       # fast-forward only
```

## 参考

- [Git Release Notes ver.2.27.0](https://raw.githubusercontent.com/git/git/master/Documentation/RelNotes/2.27.0.txt)
【heroku】MySQL本番環境のデータベースをリセットさせる方法

#herokuのデータベースリセット

```ターミナル.
heroku run rails db:migrate:reset
```

上記コマンドで、heroku上のデータベースをリセットできます。
しかし、Rails5から本番環境データベース保護機能が追加され，上記コマンドのみだと下記の内容で怒られる。

```エラー.
rails aborted!
ActiveRecord::ProtectedEnvironmentError: You are attempting to run a destructive action against your 'production' database.
If you are sure you want to continue, run the same command with the environment variable:
DISABLE_DATABASE_ENVIRONMENT_CHECK=1
```

環境変数を指定して実行してください〜と

#解決方法
解決方法として、
`RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1`を追加入力でOKです。

```ターミナル.
$ heroku run rails db:migrate:reset RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1
```

ちなみに、、、
`MySQL`でなく`PostgreSQL`を使っている場合は下記でリセット可能です。

```ターミナル.
$ heroku pg:reset DATABASE
$ heroku run rake db:migrate
```

恥ずかしながら僕は、`MySQL`を使っているのに`$ heroku pg:reset DATABASE`を何度も打ってしまい上手くいかず躓いてしましました...

参考になれば幸いです。
ダブルスだけの結果から個人のレーティングとペアの相性を推定する(stan)

前回の続きで、卓球などで試合はダブルスばかりだったり、シングルと統合したい場合に使えると思う。
核はペアの場合のrateを
rate[x]+rate[y]+rate_two[x,y]
と分けて、rate_two（x<yの順序集合）はプラスマイナス200程度になる希望を事前分布に押し込んだ事。
使わない(x,x)や(3,1)などをゼロにする事前分布はなぜか全くうまくいかなかった。つねにx側が勝つ(=inv_logit[p]もほぼ1）なのに、何故か五分五分になりたがるみたいな。


```r
llibrary(rstan)

scode="
data{
  int N;
  int M;
  int x[N,2];
  int y[N,2];
  int one[N];
}

parameters {
  real rate[M];
  real rate_two[M,M];
}

transformed parameters {
    real p[N];
    real tmp1;
    real tmp2;
    real b=0.00575364;
    for(i in 1:N){
      tmp1=rate[x[i,1]]+rate[x[i,2]]+rate_two[x[i,1],x[i,2]];
      tmp2=rate[y[i,1]]+rate[y[i,2]]+rate_two[y[i,1],y[i,2]];
      p[i]=inv_logit(b*(tmp1-tmp2));
      print(p[i])
    }
}

model{
  
  rate~normal(1500,800); #1500がデフォルト
  
  for(i in 1:M){
    for(j in 1:M){
      if(i<j){
        rate_two[i,j]~normal(0,500);
      }else{
        rate_two[i,j]~normal(0,500);
      }
    }
  }

  for(i in 1:N){
    one[i]~bernoulli(p[i]);
  }
  
}

"

#b=Solve[1/(1 + Exp[-x*100]) == 0.64, x]

d=c(1,2,3,4,
    1,4,2,3,
    2,3,4,5,
    2,3,1,5,
    1,3,2,5,
    2,3,1,4,
    1,5,2,4
    )

d2=c(1,2,3,4,
    1,4,2,3,
    2,3,4,5,
    2,3,1,5,
    1,3,2,5,
    1,2,4,5,
    1,3,4,5
)

#12が強いが14だと弱くなるペア
d3=c(1,2,3,4,
     1,2,3,4,
     1,3,2,4,
     1,3,2,5,
     1,2,3,5,
     1,2,3,4,
     2,3,4,5,
     2,3,1,4
     )
#あえてシングル
dsingle=c(1,1,2,2,
          1,1,3,3,
          2,2,3,3,
          2,2,4,4,
          3,3,4,4,
          1,1,2,2,
          1,1,3,3,
          2,2,3,3,
          2,2,4,4,
          3,3,4,4
          )

df=matrix(d3,ncol=4,byrow = T)

x=df[,1:2]
y=df[,3:4]
M=max(df)

lst=list(N=nrow(x),x=x,y=y,M=max(df),one=rep(1,nrow(x)))
fit=stan(model_code = scode,data=lst,
         #init = function(){list(rate_two=rtinit,rate=rep(1500,M))},
         chain=1,iter=2000,warmup =500)

la=extract(fit)

rate=apply(la$rate,2,mean)
M=max(df)
rate_two=matrix(0,M,M)
for(i in 1:M){
  for(j in 1:M){
    rate_two[i,j]=mean(la$rate_two[,i,j])
  }
}

#rate_two
         [,1]        [,2]       [,3]       [,4]       [,5]
[1,] 12.860810 182.5917557 161.011254 -118.22797   4.415395
[2,] 14.088220   1.7288561 139.543518  -72.28733 -87.325399
[3,] -3.235520  -9.7427856  -3.568055  -98.99620 -99.269477
[4,] 14.150042  -0.5098703  18.887168   16.07496 -18.809176
[5,] -3.794969  12.4902216   1.515641   11.94288  -7.983007

#rate
[1] 2059.3576 1887.4912 1863.8897  693.6636  973.8996

```


基本的に1が１番強いようにつくり、d3は(1,2)のペアが最強だが1は4と組んだときに弱くなるのが出ていると思う。

同じノリで対戦相手の相性はaisho[xa,xb,ya,yb]とすれば良いと思う。

ちなみに、deeplerning()とかだとネットワークの中の状態を顕微鏡で見ない限りこういうのは絶対的ないと思うんですけどどーなんですかね。
minecraft で creeper の 破壊活動だけを止めるまで

実を言うとプログラミング技術と関係があるかなって疑問に思って、
投稿をためらっていたのですが、
他に相応しい場所も持っていないし、
遠回りに技術として役に立つのなら良いかなと思い、
投稿するに至りました。

# 0. 理由

mobGriefing falseで爆発してもブロックを破壊しないようにはできるのですが、
村人が農業しなくなってしまって困ったので、
手軽に破壊活動だけを止めれないかと考えて、
この方法に至った次第。

# 1. 環境

- minecraft 1.15.2

# 2. 方法

すべてのmobの持つ、entityデータを編集する。
今回は爆発半径のExplosionRadiusを0にした。

# 3. コマンド

```
/execute as @e[type=minecraft:creeper] run data merge entity @s[type=minecraft:creeper] {ExplosionRadius:0}
```

# 4. 困ったこと

## ログがうるさい

```
/gamerule commandBlockOutput false
```

で黙らせた。

# X. あとがき

ガストの破壊活動も止める。
本当は爆発によるブロックへのダメージをなくせば良いんだけど、
そんなピンポイントな方法知らないので、
今度また考えます。
pluginとかdatapackとか、
今は色々できるみたいだし。

では。
IAM認証のAPI Gatewayを叩く。SigV4署名ヘッダーを作成(python)

#IAM認証のAPI Gatewayを実行する(python)
curl等でAPIの結果を返したいとき、HTTPリクエストのヘッダ（SigV4署名）を算出する必要があるが、資料が見当たらないため備忘
APIGatewayをIAM認証にする方法はほかのサイト参照。
ハッシュ値を算出する方法があるがよくわからないので、必要になったときにbotocoreのライブラリ内を見て作成する。

```python:check_iam.py
import os
from botocore.awsrequest import AWSRequest
from botocore.auth import SigV4Auth
from botocore.endpoint import URLLib3Session
from botocore.credentials import Credentials
import requests

url_ = "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/v1"
### 1. Credential生成  
credentials = Credentials(os.environ['AWS_ACCESS_KEY_ID'], os.environ['AWS_SECRET_ACCESS_KEY'])

### 2. AWSRequest生成
request = AWSRequest(method="GET", url=url_)

### 3. AWSリクエスト署名
SigV4Auth(credentials, 'execute-api', ap-northeast-1).add_auth(request)

### 4. API発行
headers = {
    'Authorization': request.headers['Authorization'],
    'Host':'xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com',
    'X-Amz-Date':request.context['timestamp']
}

response = requests.get(url_,headers=headers)

print(response.text)
```
他人が書いた ようわからんコードを`git blame`で追う

長期インターンが開始から2ヶ月経とうとしており、無事チュートリアルも終了した段階です。

本業務で自社プロダクトのissueを進めていると、**「このソースコード何してるんだろう...？　誰が編集したんだろう...？」**みたいなことがよくあります。

そんな時に**`git blame`**で、ソースコードのコミット履歴から**いつ誰がどのコミットで作成・編集したのか**を追うことが出来ます。

# Git blameコマンド

ターミナルで`$ git blame ファイル名`を実行します。

```terminal
$ git blame app/models/post.rb
435ed96f (TsuboyaTaiki 2020-05-08 17:41:29 +0900  1) # frozen_string_literal: true
435ed96f (TsuboyaTaiki 2020-05-08 17:41:29 +0900  2) 
679dd29e (TsuboyaTaiki 2020-04-30 10:59:39 +0900  3) class Post < ApplicationRecord
d97256ae (TsuboyaTaiki 2020-05-04 18:34:45 +0900  4)   validates :account_id, length: { maximum: 255 }, presence: true
d97256ae (TsuboyaTaiki 2020-05-04 18:34:45 +0900  5)   validates :post_sentence, length: { maximum: 255 }, presence: true
d97256ae (TsuboyaTaiki 2020-05-04 18:34:45 +0900  6)   validates :target_post_id, length: { maximum: 255 }
b8179705 (TsuboyaTaiki 2020-04-30 16:32:40 +0900  7) 
8eccd041 (TsuboyaTaiki 2020-05-04 19:00:07 +0900  8)   belongs_to :account
435ed96f (TsuboyaTaiki 2020-05-08 17:41:29 +0900  9)   has_many :goods, dependent: :destroy
a745018e (TsuboyaTaiki 2020-05-07 10:45:35 +0900 10) 
435ed96f (TsuboyaTaiki 2020-05-08 17:41:29 +0900 11)   has_many :reply_posts, class_name: 'Post', foreign_key: 'target_post_id', dependent: :destroy
a9768c5c (TsuboyaTaiki 2020-05-15 17:12:14 +0900 12)   belongs_to :new_post, class_name: 'Post', foreign_key: 'target_post_id', optional: true
679dd29e (TsuboyaTaiki 2020-04-30 10:59:39 +0900 13) end
```

ソースコードの各行に対して、

- **コミットのハッシュ値**
- **変更者名**
- **コミット日時**

などの情報を得られます！変更者名がわかれば直接質問しに行くこともできます！

コミットの変更内容を詳しく見たい場合は`git show`にかけます（`$ git show コミットのハッシュ値`）。

```
$ git show 435ed96f
commit 435ed96f2b73e4ecc4bc79a676037bc075a626df
Author: TsuboyaTaiki <tsuboyataiki@taiki-mac.local>
Date:   Fri May 8 17:41:29 2020 +0900

    20200508_2

diff --git a/Gemfile b/Gemfile
index ba11cb2..28a4a0c 100644
--- a/Gemfile
+++ b/Gemfile
　　　　　　・
　　　　　　・
　　　　　　・
```

# 行間指定

ソースコードが長い時は、`-L`オプションで行間指定します!

```
$ git blame -L 4,6 app/models/post.rb     # 4行目から6行目
d97256ae (TsuboyaTaiki 2020-05-04 18:34:45 +0900 4)   validates :account_id, length: { maximum: 255 }, presence: true
d97256ae (TsuboyaTaiki 2020-05-04 18:34:45 +0900 5)   validates :post_sentence, length: { maximum: 255 }, presence: true
d97256ae (TsuboyaTaiki 2020-05-04 18:34:45 +0900 6)   validates :target_post_id, length: { maximum: 255 }
```

# GitHubから

GitHubのCodeタブにも、Blameという項目があります。


<img width="965" alt="スクリーンショット 2020-06-17 15.24.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305969/9d210016-dfce-ab8c-7f73-2b03aefaa927.png">

Blameに飛ぶと、

![スクリーンショット 2020-06-17 15.27.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305969/455153d5-8c13-ce80-0aaa-ca22c9c2dc57.png)

こんな感じ！

GitHubからだと、GUIで操作できます。
あと、コミット時のコメントが簡単に見れるのも利点です！

# 終わり
`git blame`は、バグの混入などがあった時などに使われることが多いようです。

でも今回のようなユースケースもあるので有効活用していきたいです...
Blender2.8での設定内容

#### 今までBlender2.7以前を使っていて2.8を触ってみたはいいが、色々と仕様が変わりすぎていたので今まで使用していた設定方法を2.8で適用する内容

※画面レイアウトが大きく変わっているが今までのショートカットキーは通常通り使えるのでまぁそこは見逃しておいてやろう…
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/1d4b4013-eef1-754a-2877-c66d6d087581.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/cb7898d0-89e1-e4f2-0dbd-09ee034442c7.png)

# Tabキーを押したときなどに表示するパイメニュー
Blender2.7以前ではTabキーを押してパイメニューを活用していたが2.8でも使えた。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/7c2e5aa0-e035-6ba9-ea90-c37706584b01.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/90937951-c61d-f667-fa9e-a33cb6d2a67c.png)

**方法：**
①編集メニューのプリファレンスをクリックする。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/a06f0185-5be7-01f4-d9b9-b39bef2cc895.png)

②ダイアログが出てくるので左メニューのキーマップを選択すると『Tab for Pie Menu』というのがあると思うのでチェックする。
※おそらく初期設定では自動保存になっていると思うが、自動保存設定になっていない場合はダイアログ左下のプリファレンスから保存すると次回起動時にも反映されていると思う。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/a426a41c-ad6c-5fc8-6488-c8d95644a404.png)

# 全選択解除
Aキーを押すと全選択ができるのは変わらない。2.7では再度Aキーを押すことで全選択解除ができていたのだが、2.8では挙動が異なり以下の方法でないと全選択解除ができないようだった。
・Alt+A
・選択しないビューポートをクリック
・Aキーを2回押す

# オブジェクト選択をしたときの矢印表示
3Dビューポート画面右上の弓矢みたいなプルダウンをクリックし、オブジェクトギズモ下の移動のチェックボックスをクリックすると表示される
（今まで初期から表示されていなかったっけ…？）
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/1b68edc7-2b16-e6f7-604a-e4c5062aa762.png)

# アニメーションの自動キーフレームボタン
タイムライン画面の再生関連ボタンの隣にあった。
地味にわかりづらく10分くらい探してた。
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/18230f4f-0a30-30e4-bdfe-649499890999.png)

# ヘッダーの位置が上になってる
いやまぁヘッダーだから上にあるのが当たり前なのかもしれないけどさ、今まで君下にいたやん？フッターだったやん？
※右クリックするとメニューが出るので下に移動させることができる
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/8d801d1d-d828-df49-760c-356bf77a00a0.png)

# オブジェクトにボーンが重なるとボーンが見えなくなる
2.7では『レントゲン』というチェックボックスだったが、2.8では『最前面』となっている。
チェックを付けるとボーンが見えるようになる。
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/cfc45a3d-b528-d913-b905-e19c5adfaf22.png)

# X軸ミラーどこ…ここ…？
メッシュ編集時、ボーン編集時ともにプロパティ画面のドライバー&スパナタブにチェックボックスがあるので適宜チェックを付ける。
**メッシュ編集**
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/ce6ee777-2fbe-bd8a-e5e1-03f10ec58877.png)
**ボーン編集**
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/03035d11-b9c6-7f22-a55a-d1245c5a1643.png)

# 頂点結合
2.7ではAlt+Mで結合できたのだが、2.8ではMキー単体になっている。プリファレンスでもしかしたらキーを変更できるのかもしれないがせっかくだしこのままで進めてみようと思う。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/461861fd-125a-aeaa-e50f-7a5013524973.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501431/3c1a0812-ffea-31be-06b8-3986fbe5ed5a.png)

ちなみに2.7の『重複頂点を削除』機能は2.8では上記マージでの『距離で』に置き換わったみたい。
[Ruby] コンソールから入力を受け取る

Progate学習メモ

# `gets.chomp`を使う

```.rb
puts "名前を入力してください"

# コンソールから入力を受け取り、変数nameに代入する
name = gets.chomp
puts "こんにちは、#{name}さん"
```

コンソール↓

```console
名前を入力してください　# 入力待機状態になってる
```
「太郎」と入力すると、

```console
こんにちは、太郎さん
```

`gets.chomp`は文字列で受け取るので、数値で受け取りたい場合は、
`count = gets.chomp.to_i`というようにする。

---
参考
[Progate](https://prog-8.com/)
[Ruby] initializeメソッド

Progate学習メモ
initializeメソッドはインスタンスが生成された直後に呼び出される

# 引数がないinitializeメソッド

```.rb
class Menu
attr_accessor :name
attr_accessor :price

  # menuインスタンスが生成されたあと呼び出される
  def initialize
    self.name = "スープ" # インスタンス変数nameにスープという情報が入る
    self.price = 500 # インスタンス変数priceに500という情報が入る
  end

  def info
    return "#{self.name}: ¥#{self.price}"
  end
end

# Menuクラスからmenuインスタンスが生成される
menu = Menu.new
puts menu.info
```

結果

```console
スープ: ¥500
```

# 引数があるinitializeメソッド

```.rb
class Menu
attr_accessor :name
attr_accessor :price

  def initialize(name:, price:)
    self.name = name
    self.price = price
  end

  def info
    return "#{self.name}: ¥#{self.price}"
  end
end

# ここでinitializeメソッドの引数に情報をセット
menu = Menu.new(name:"カレー", price:850)
puts menu.info
```

結果

```console
カレー: ¥850
```

---
参考：[Progate](https://prog-8.com)
【Mac】不安定なTimeMachineでバックアップ・復元を成功させるポイント

## 前置き

Macの標準バックアップ機能、「TimeMachine」。
Appleの標準機能とは思えないほど失敗しやすく不安定な機能ですよね。
今回、Macを修理に出していたものが返ってきたので、「TimeMachine」でのバックアップ、復元を行いました。
苦戦したので、少しでも成功率を上げるポイントを残していこうと思います。

### 環境
* 移行元：MacBook Pro
* 移行先：MacBook Pro (13-inch, 2017, Four Thunderbolt 3 Ports)
* macOS Mojave ver 10.14.6
* NAS(バックアップの保管先)
* ESET(アンチウイルスソフト)

## バックアップ編
目的：移行元のMacのデータをNASへバックアップ

* 不要なファイルを削除しておく
    * バックアップに掛かる時間の短縮のため
* アンチウイルスソフトを切る(deamonもkill)
    * 私の場合はESETです。どうもTimeMachineでのバックアップと相性が悪いみたいです。よく失敗していました。
* 有線LANでMacを接続
    * 無線だとネットワークが切れる可能性がある。
    * 有線だと少なからず安定して高速にバックアップできる。
* TimeMachineのリミッターを解除する
    * TimeMachineはデフォルトで他の作業を邪魔しないように、使うリソースの量が制限されています。
    * 高速にバックアップが取れるように以下コマンドでリミッターを解除できます。
    * 体感的にはバックアップに使うリソースは2割増しぐらいだったので他の作業は邪魔されませんでした。
    * この設定はMacの再起動で自動でデフォルトに戻ります。

```sh
$ sudo sysctl debug.lowpri_throttle_enabled=0
```

## 復元編
目的：NASのバックアップデータを元に移行先Macに復元

* 移行先のMacのハードディスクを初期化する
    * 工場出荷状態にします。
* バックアップのmacOSと同じバージョンのmacOSをインストール
    * OSのバージョンは揃えておくと成功しやすい
* 有線LANでMacを接続
    * バックアップ編と同じ理由
* OSインストール後の初期設定最中の「移行アシスタント」画面から「Mac, TimeMachine」を選択して全てのデータを移行 

## まとめ
それでも1,2回失敗することがあります。
私は最終的に上記方法でバックアップ・復元が出来ました。
ご参考迄に。
Macのライブ変換がおかしくなった。

# 起こったこと
日本語で文字入力をしている際にアルファベットをshift押しながら文字入力すると入力した
アルファベットじゃなくて、別の文字列に変換が行われる。

例：
打ちたい文字「サイバイマン<font color="red">J</font>」
勝手な変換で出た文字「サイバイマン<font color="red">HTML</font>」
みたいに　「shift」押しながら「J」などをアルファベットを打つと「J」が「HTML」というように全く違う文字にライブ変換されてしまった。

というのが今回悩んだことでした。

# 解決策
ライブ変換機能のバグなので
**変換学習のリセット**を行えば良いです。

詳しい手順は、[画像つき手順サイト](https://tomoyuki65.com/how-to-solve-character-input-bugs-on-mac/)　←にあります。

とてもわかりやすかったです。ありがとうございました。
php7.3以下からのphp7.4

Qiitaのログイン方法忘れてて放置してました＞＜

php7.4に移行中に発生した問題

https://www.php.net/manual/ja/migration74.incompatible.php
> 古いPHPバージョンでシリアル化されたペイロードはまだ復元可能であることを意味しますが、
> PHP 7.4 で生成された新しいペイロードを、古いバージョンは理解しないことを意味します。

複数台のphp7.3(以下)環境を徐々にphp7.4環境にしていこうかと思ったら
ArrayObjectをシリアライズしたものが共有できない罠（キャッシュ等に保存で使用）
php7.4では保存しない等の対応では余計なコスト発生するので諦め。。。

→php7.3以下でserializeしたArrayObjectはphp7.4でunserialize可
→php7.4でserializeしたArrayObjectはphp7.3以下でunserialize不可
CentOS 7 + TORQUE + NUMA

CPUソケット2基を有するマザーボードにCPUが2個インストールされているNUMA計算機を想定する．
例えば，CPUとしてXeonが2個インストールされているとする．
`lscpu`コマンドで確認すると，

```bash
$ lscpu
アーキテクチャ: x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                32
On-line CPU(s) list:   0-31
コアあたりのスレッド数:1
ソケットあたりのコア数:16
Socket(s):             2
NUMAノード:         2
ベンダーID:        GenuineIntel
CPUファミリー:    6
モデル:             85
Model name:            Intel(R) Xeon(R) Gold 6242 CPU @ 2.80GHz
ステッピング:    7
CPU MHz:               1200.048
CPU max MHz:           3900.0000
CPU min MHz:           1200.0000
BogoMIPS:              5600.00
仮想化:             VT-x
L1d キャッシュ:   32K
L1i キャッシュ:   32K
L2 キャッシュ:    1024K
L3 キャッシュ:    22528K
NUMAノード 0 CPU:   0-15
NUMAノード 1 CPU:   16-31
```

のように表示される場合である．
[ここ](https://www.intel.co.jp/content/www/jp/ja/products/processors/xeon/scalable/gold-processors/gold-6242.html)にもあるように，Xeon Gold 6242は16コアであり，確かにNUMAノード0に0番から15番の16コアが認識されている．
2個目はNUMAノード1として16番から31番の16コアが認識されている．
つまり計算機としては32コアの資源を有する．
(ハイパースレッディングテクノロジはオフにしてある)

## <font color="Blue">ジョブ管理システムのセットアップ</font>

OSはCentOS 7で，ジョブ管理システムとしてThe Terascale Open-source Resource and QUEue Manager (TORQUE) を使いたい．

まず[CentOS 7でTorqueのセットアップ](https://qiita.com/yf_xa/items/6042619a5d1a3decf8eb)に従いTORQUEサーバとクライアント，スケジューラをインストールする．

上述の記事に従って設定すると，`pbsnodes`コマンドでは1ノード (16コア) しか表示されていないはずである．
今の場合は2つのNUMAノードがあるので，
以下のように設定を一部書き換える必要がある．

```bash:/var/lib/torque/server_priv/nodes
HOSTNAME num_node_boards=2 numa_board_str=16
```

```bash:/var/lib/torque/mom_priv/mom.layout
nodes=0
nodes=1
```

ここで`HOSTNAME`のところには計算機のホストネームが書き込まれているはずである．
`num_node_boards`にはNUMAノードの個数を設定する．
`numa_board_str`にはNUMAノードあたりのCPUコア数を設定する．

以上を設定してtorqueをリスタート：

```
# systemctl restart pbs_server
# systemctl restart pbs_sched
# systemctl restart pbs_mom
```

再び`pbsnodes`コマンドを実行し，`np=16, state=free`なノードが2個表示されれば成功．
ノードの名前は`HOSTNAME-0`と`HOSTNAME-1`のようになっていると思う．

例えばOpenMPで32並列の計算を行う場合は，
ジョブスクリプトに以下のようなオプションを追加する：

```bash
#PBS -l nodes=2:ppn=16
```

この例では，2つ全てのNUMAノードとコア (合計32コア) が予約され，
このジョブの実行中(`status:R`)は他のジョブは待機状態(`status:Q`)となる．
Kotlin で BCrypt する

Kotlin でバックエンドを組むときなど、BCrypt が欲しくなることがあります。安定なのは Spring Security Web を使うことです。

`BCryptPasswordEncoder` を使う方法はたくさんの方が書いてくださっているのでそちらを参考にしてもらうとして、この記事では `BCrypt` を使う方法を書いてみたいと思います。

## 依存関係の追加

Gradle を使っているのなら、次のようにして依存を追加します。
最新のリリースは [こちら](https://mvnrepository.com/artifact/org.springframework.security/spring-security-web) から確認してください。

```gradle
def spring_security_version = "5.3.3.RELEASE"

dependencies {
    compile "org.springframework.security:spring-security-web:$spring_security_version"
}
``` 

## 自分で用意した salt を使いたい

`BCryptPasswordEncoder` の `createHash()` 関数は、平文のパスワードのみを受け取って暗号化します。つまり、こちらで salt を生成したい、もしくは、papper を使いたい... というようなケースには適していません。

そこで `BCrypt` の出番です。

### salt の生成

```kotlin
import org.springframework.security.crypto.bcrypt.BCrypt

val salt: String = BCrypt.gensalt()
```

簡単ですね。
このようになにも引数を渡さない場合はデフォルトの実装となりますが、長さの変更や接頭辞の付与、乱数アルゴリズムの変更をサポートしているようです。詳細は [API ドキュメント](https://spring.io/projects/spring-security#learn) を参照してください。

### salt を使って暗号化

```kotlin
val plain = "foo"            // 平文のパスワード
val salt = BCrypt.gensalt()  // salt の生成

// 平文と salt を使って暗号化
val encrypted: String = BCrypt.hashpw(plain, salt)
```

こちらもすごく簡単。String ではなく byte[] を渡せるオプションもあります。

### パスワードの検証

```kotlin
println(
    if (BCrypt.checkpw(plain, encrypted))
        "Success!"
    else
        "Failure!"
)
```

はい簡単。
もう `BCryptPasswordEncoder` いらなくね？ と思いますよね？ 私もそう思います。

おわり
Laravelのプロジェクトをxamppのサブドメインで配信してみる

####xamppのhtdocs直下に新規ディレクトリの作成

#####ディレクトリ名をdevelop-sampleとして作成

####新規に作成したディレクトリに移動してLaravelのプロジェクトの作成

```
 composer create-project "laravel/laravel=6.*" laravel-dev
```

####次にLaravelのプロジェクトをxamppのサブドメイン上で配信する為に C:\xampp\apache\conf\httpd.confファイルに追加する
 
```
// Alias/任意のドメイン名 /xampp/htdocs/任意のディレクトリ名/任意のプロジェクト名/public
Alias /sample-dev /xampp/htdocs/develop-sample/laravel-dev/public

//<Directory "C:/xampp/htdocs/任意のディレクトリ名/任意のプロジェクト名/public">
<Directory "C:/xampp/htdocs/develop-sample/laravel-dev/public">

    Options Includes ExecCGI FollowSymLinks
    AllowOverride All
    Require all granted
    Order allow,deny
    Allow from all
</Directory>

<Directory />
   #AllowOverride none
    AllowOverride All
    Require all granted
   #Require all denied
</Directory>
```
####Laravel側のプロジェクト/public/.htaccessファイルに変更を加える

```
 # Redirect Trailing Slashes If Not A Folder...
     RewriteCond %{REQUEST_FILENAME} !-d
     RewriteCond %{REQUEST_URI} (.+)/$

 //  RewriteRule ^(.*)/$/任意のサブドメイン名/$1 [L,R=301]
     RewriteRule ^(.*)/$/sample-dev/$1 [L,R=301]

 //  RewriteBase /任意のサブドメイン名/
     RewriteBase /sample-dev/
     RewriteRule ^index\.html$ - [L]
```

####最後にxamppを再起動をかける

 再起動後、確認の為(http://localhost/任意のサブドメイン名/) にアクセスしてみよう
　アクセス時にlaravelのTOP画面が表示されればOK お疲れ様です。

###参考にしたサイト
 https://minory.org/laravel-subdirectry.html
【Ruby on Rails】chrome上で文字が反映されない！

# 【Ruby on Rails】chrome上で文字が反映されない！
現在、未経験でアプリ開発を試みているものです。

###　環境
- windows10
- vscode

## 対象
- 未経験
- rubyを最新版でダウンロードした方

## 状況
初めて開発を進めようとし、vscodeでブラウザ上にコードを反映させようとしたが、うまく反映されない。
"Yay!You're on Rails!"という画面は表示されたが、更新しても画面が切り替わらないという問題が発生した。

## 対処
Rubyが最新バージョンだと上手くいかないのではと思い、
vscodeのターミナル上で、
"gem install rails -v 5.2.4.1"
と入力したらうまく更新されるようになりました。

参照サイト
[Railsのバージョン指定の方法を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/22193)


## まとめ
私もこれから開発を進めていきますので、こんな状況でも頑張りましょう！
全く同一のルートファイルシステムを利用する複数のディスクレスクライアントで、クライアント固有の ssh ホストキーを設定する

# 序: 本稿の対象読者

+ 複数のディスクレス Linux で何らかのクラスタを構築したい人
+ 10〜20台以上のノード数のクラスタを構築する場合は LDAP サーバを1台立ててユーザー/ホスト管理したほうが圧倒的に楽になりますので、LDAP サーバを立てるまでのノード数ではない人
+ NFS サーバのディスクを圧迫したくないので、全ノード同一の NFS 共有にある OS イメージを利用したい人
+ 全ノードで SSH サーバを立ち上げたいものの、全ノードで共通の SSH ホストキーは利用したくない(=各ノード固有のホストキーを利用したい)人

全てを満たす人向けの情報となります。

# 問題の本質

1. 複数マシンで同じルートファイルシステムを利用しているので、デフォルトの sshd_config ファイルを利用すると全マシンの sshd が同じホストキーファイル(/etc/ssh/ssh_host_*_key )を読み込んで起動してしまう。
2. /etc を ルートと別パーテーションに分離することは Linux 的に不可能
3. NFS 利用のディスクレスクライアントで、overlayfs の利用はほぼ無理( overlayfs は NFSv3 未対応)
3. sshd 起動前に /etc/ssh 配下にあるホストキーを変更してしまうと、他のホストのキーまで変わってしまう。そもそもディスクレスクライアントなので、/etc 配下のファイルは変更不可なので無理

# 解決策
以下の方法で、上記の問題を解決することができます。

1. 保存場所はどこでも構わないので、予めそれぞれのノード固有ホストキーを全て保存しておく(ノードホスト名を持つサブディレクトリを作り、その中に全部入れていくと良い)
2. 書き込み可能ディレクトリを1つ用意(例: /var/lib/sshd を作り、/etc/fstab では tmpfs としてマウント)
3. sshd_config で、2. で作成したディレクトリ配下のホストキーを読み込む設定とする
4. 起動時、IP取得後(自ホスト名が判明した状態)、なおかつ sshd が起動させる直前に、1. の中から自ホスト向けのサブディレクトリに保管されているホストキーを 2. のディレクトリにコピー

この手法は sshd のみならず、他の、ホスト固有情報を利用するデーモンを起動する際にも利用可能です。
(ただ、IPやホスト名に関しては DNS や DHCP でどうにでもできます。) 

# 具体的な方法
作業は全部 NFS サーバで、ノードに配布するOSイメージに chroot して行います。
以下、ディスクレスノードのホスト名を host1 〜 host4 であるとします

## 1. 個別ホストキーの生成方法
安全のために、全キーの保管場所を /root/host_keys とします。

```shell-session
# mkdir /root/host_keys; cd /root/host_keys
# for N in `seq 1 4`; do HN="host${N}"; mkdir ${HN}; for T in rsa ecdsa ed25519; do ssh-keygen -h -t ${T} -C ${HN} -N '' -f ${HN}/ssh_host_${T}_key; done; done
```

## 2. ディスクレスクライアントでも書き込み可能なディレクトリの作成
```shell-session
# mkdir /var/lib/sshd
# vim /etc/fstab
(変更内容は下記)
#
```
/etc/fstab に以下の行を追加

```config
tmfps /var/lib/sshd tmpfs defaults,mode=700 0 0
```

## 3. sshd_config ファイルの変更
```shell-session
# vi /etc/ssh/sshd_config
(変更内容は下記)
#
```

変更内容(デフォルトだとコメントアウトされている HostKey エントリを有効化して変更)

```config
(省略)
HostKey /var/lib/sshd/ssh_host_rsa_key
HostKey /var/lib/sshd/ssh_host_ecdsa_key
HostKey /var/lib/sshd/ssh_host_ed25519_key
(省略)
```

## 4. 適切なタイミングでホスト固有キーファイルをコピーする処理の作成
タイミングを適切に処理するために、systemd の新規 unit ファイルを作成、ここから専用スクリプトを呼び出す形式にします。

### 4.1 専用シェルスクリプトの作成
ファイル名は何でもいいんですが、/usr/local/sbin/copy_sshkeys とします。

```shell-session
# vim /usr/local/sbin/copy_sshkeys
# chmod 700 /usr/local/sbin/copy_sshkeys
```
スクリプトの内容は以下となります。systemd でエラーを判定可能とするために、戻り値を設定します。

```shell
#!/bin/bash
HN=`hostname`
RETVAL=0

if [ "${HN}" != "" ]
then
  cp -pf /root/host_keys/${HN}/ssh_host* /var/lib/sshd/
  RETVAL=$?
else
  # ホスト名取得に失敗
  RETVAL=2
fi

exit $RETVAL
```

### 4.2. systemd Unit ファイルの作成
/etc/systemd/system 配下に新規の Unit ファイルを作成します。拡張子を .service にする決まりさえ守れば、このファイルの名前も何でもいいんですが、解りやすいように ssh_hostkey_copy.service とします。

```shell-session
# vi /etc/systemd/system/ssh_hostkey_copy.service
(内容は下記)
# systemctl enable ssh_hostkey_copy.service
(出力結果省略)
#
```

Unit ファイルの内容は以下となります。

```ini
[Unit]
Description=SSH Hostkey copy process for diskless clients
After=network.target local-fs.target
# ディストリビューションによっては sshd.service の場合も有り
Before=ssh.service

[Service]
ExecStart=/usr/local/sbin/copy_sshkeys
Type=oneshot

[Install]
WantedBy=multi-user.target
RequiredBy=ssh.service
```

これで、ディスクレスクライアントでも固有ホストキーを利用した sshd が起動するようになります。
Python製のCLIアプリのインストールはpipx使っとけばOK (2020年時点)


# TL;DR

```
brew install pipx
pipx ensurepath
pipx install インストールしたいアプリ名
```

これだけでいい感じになる。


# はじめに

Python製CLIアプリのインストールはpipを使えばできてしまうのですが、Macには標準でPython2とPython3が同居していたり、自分でPython環境を別途構築しているとpipが一体どこのpipなのかが訳わからなくなりがちだと思います。

こんな記事があったり。

[Why you should use `python -m pip`](https://snarky.ca/why-you-should-use-python-m-pip/)

pipを使うならちゃんとインタプリタを明示しようということですね。でも面倒だ。

上記の記事を読むとCLIアプリ管理に特化した[pipx](https://github.com/pipxproject/pipx)というツールがあることを知りました。

使ってみると確かにいい感じ。ちょっとした解説を踏まえて記事にしました。

# 環境

* MacOS 10.14.6

# pipx をインストールする。

([公式README](https://github.com/pipxproject/pipx/blob/master/README.md)と同じ内容です。)

pipx自体はHomebrewでパパっとインストールします。

```terminal
brew install pipx
```

```terminal
pipx ensurepath
```

上記の`pipx ensurepath`を実行すると以下のようなメッセージがでます。

```
Success! Added /Users/shintaro.ikeda/.local/bin to the PATH environment variable.
Consider adding shell completions for pipx. Run 'pipx completions' for instructions.

You likely need to open a new terminal or re-login for the changes to take effect. ✨ 🌟 ✨
```

どうやら$PATHに新しい参照先を刺したようです。

```terminal
echo $PATH
(略..):/Users/shintaro.ikeda/.local/bin
```

たしかに出てきました。pipxで勝手にやってくれるので自分でbashrc等で設定しなくて良いので便利です。

# Python製アプリのインストール

Pythonで作られている[virtualenv](https://github.com/pypa/virtualenv)をインストールしてみます。

```terminal
pipx install virtualenv
```

以下の出力が表示されます。

```
  installed package virtualenv 20.0.23, Python 3.8.3
  These apps are now globally available
    - virtualenv
done! ✨ 🌟 ✨
```

Mac自体にあるPythonは最新のPython3.8.3ではないのですが、pipxが独自で$HOME/.local/以下に保持しています。

```terminal
which virtualenv
/Users/shintaro.ikeda/.local/bin/virtualenv
```

virtualenvがインストールされています。

またpipxではCLIアプリごとにPythonインタプリタと利用しているライブラリを独立で管理しています。下記のように確認できます。

```terminal
ls $HOME/.local/pipx/venvs/virtualenv
bin                include            lib                pipx_metadata.json pyvenv.cfg
```

インストール後は、`pipx list`, `pipx uninstall`, `pipx upgrade`など他のパッケージ管理ツールと同様にアプリを管理することができます。
【Swift】日付(文字列)を別の日付形式(文字列)に変換する処理【DateFormatter】

Date→Stringの日付変換は良く見かけるが、
String→Stringは見当たらなかったので備忘録

#環境
- Xcode: 11.3.1
- Swift5

##・変換したい文字列、日付フォーマットを指定
```Swift:
    /// 日付文字列を別のフォーマットに変換し返却
    /// - Parameters:
    ///   - dateString: 変換したい文字列
    ///   - fromFormat: 変換前の文字列の形式(dateFormat)
    ///   - toFormat: 変換後の文字列の形式(dateFormat)
    func getFormattedDateString(dateString: String, from fromFormat: String = "yyyyMMdd", to toFormat: String = "yyyy/MM/dd") -> String? {
        let dateFormatter = DateFormatter()
        // DateFormatterのロケールやその他指定は各自変えて下さい
        dateFormatter.locale = .current
        dateFormatter.dateFormat = fromFormat
        guard let date = dateFormatter.date(from: dateString) else { return nil }
        dateFormatter.dateFormat = toFormat
        return dateFormatter.string(from: date)
    }
    
    
```
##使い方
```Swift
if let date = getFormattedDateString(dateString: "20200617") {
    print(date) // 2020/06/17
}
```

##追記
デフォルト引数は自身が良く使う、変換する日付フォーマットを設定しておくと楽かなと。
JavaScript　条件分岐を使った変数宣言と結果表示

先日メンバーのJSのコードをみたときに

`A&&B`,`A||B`これをif文の条件式に当てはめないで利用している。。。。。。だと？！

こんな書き方があったのか〜ってなったので個人的にメモしておく。  

知ってる人からしたら当たり前じゃんって思うかも。。。。


### 条件分岐と変数を組み合わせた書き方 
下記みたいなコード

```
const num =1;

num>0 && console.log("&&の条件："+num);
// 結果:&&の条件：1

num>0 || console.log("||の条件："+num);
// 結果：何も返さない
```



### まとめ

```

A&&B　AがtrueならBの条件を走らせる 

A||B Aの条件がfalseならBの条件を走らせる
```


Javaをやっていた自分としてはintやstringなど変数宣言して〜〇〇の場合はifやelseで条件分岐して〜ってなってたけど、JavaScriptは変数宣言と一緒に条件分岐を合わせて利用できるので、これは便利ですね。
wget のファイル名エスケープ --restrict-file-names

wget では `--restrict-file-names` を使用することで、ファイル名をエスケープして指定したファイルを保存することができます。

どのようにファイル名が変換されるのかをまとめたいと思います。

# 1. 指定できるモード

カンマ区切りで併用可 (一部モードは不可) 。

- `unix`, `windows`
    - OS 用にファイル名を制限。複数 OS 併用は不可 (モードが上書きされる)
- `lowercase`, `uppercase`
    - 全てのアルファベットを小文字・大文字に変換する
    - もともとアルファベトである文字も、% エンコードされて出力されるアルファベットも、どちらにも適用される
- `nocontrol`
    - 制御文字をエスケープ**しなく**なります
    - UTF-8 のファイル名が使用できる環境で、UTF-8 の制御コードをそのまま保つために使用するようです
- `ascii`
    - ASCII 文字以外を全てエスケープします

# 2. OS モードごとのファイル名エスケープの規則

## 2.1. Unix

`/` と制御文字が % エンコードされます。

- `/` -> `%2F`
    - ディレクトリの区切り文字でなく、 `?` の後ろに続くクエリパラメータにある `/` が % エンコードされる
    - 例：`test?param/` -> `test?param%2F`
- 制御文字 `0–31`, `128–159` -> `%00-%1F`, `%80-%9F`

## 2.2. Windows

- Windows でファイル名に使用できない記号 `\ / : * ? " < > |`
    - 基本的にすべて % エンコード (例外有り。後述)
- 制御文字 `0–31`, `128–159` -> `%00-%1F`, `%80-%9F`
- クエリパラメータの区切り文字の `?` -> `@`
    - 区切り文字の `?` のみ `@` に置換
    - クエリパラメータに含まれる `?` は % エンコード
    - 例：`test?param?` -> `test@param%3F`
- ホスト名とポート番号の区切り文字の `:` -> `+`
    - ホスト名のディレクトリを作成するオプションを使用しているとき、ホスト名とポート番号を指定している場合に適用される
    - ファイル名やクエリパラメータに含まれる `:` は % エンコード
    - 例：`example.com:8000/test:?:` -> `example.com+8000/test%3A@%3A`

参考「[‘--restrict-file-names=modes’ - GNU Wget 1.20 Manual](https://www.gnu.org/software/wget/manual/wget.html#index-file-names_002c-restrict)」
Gulpでの環境構築まとめ～Pug/Sass/TypeScript/BrowserSync～

<h2>はじめに</h2>
フロントエンドの開発をする際に、なるべく現場に近い環境を構築して開発したいなと思ったのでまとめました。

<a href="https://github.com/chobi1125/gulp-dev">リポジトリ</a>←公開しています。

使う場合
<pre>git clone https://github.com/chobi1125/gulp-dev.git // ローカルにダウンロード
npm i // 諸々インストール
gulp // 起動・自動コンパイル</pre>
下記と組み合わせれば割と環境構築はOK！(と思いたい。)

https://chobimusic.com/babel-webpack/

※windowsで環境構築しています。

<strong>✅参考</strong>
<p class="it-Header_title"><a href="https://qiita.com/ararie/items/e4d70fadafe0f5a8f28b">Gulp4設定まとめ(Pug/Sass)</a></p>
各プラグインについてまとめてくれている。
<p class="it-Header_title"><a href="https://qiita.com/bakira/items/3c4e2d10aae085767817">gulpとbabelとwebpackというフロント開発３銃士</a></p>
概要掴める。※実際に環境構築するまではちんぷんかんぷんでした。
<h2>環境構築</h2>
<strong>✅概要</strong>

今回は以下の機能を使えるようにしていきたいと思います。

HTMLはPug

CSSはSass

JavaScriptはTypeScript

サーバーはBrowser-sync

上記をGulpで実行管理していこうと思います。

<strong>✅環境構築</strong>

package.jsonの作成
<pre>npm init -y</pre>
プラグインのインストール
<pre>npm install -D gulp gulp-sass gulp-pug browser-sync gulp-typescript typescript</pre>
gulpfile.jsを作成
<div>
<pre>const gulp = require('gulp');
      pug = require('gulp-pug');
      sass = require('gulp-sass');
      typescript = require('gulp-typescript');
      browserSync =require("browser-sync");

// サーバー起動
gulp.task("browser-sync", () =&gt; {
  browserSync({ server: {
      baseDir: "./dist",
      index : "index.html"
    }
  })
})
gulp.task('pug', () =&gt; {
  // .pugファイルを取得
  return gulp.watch('./src/**/*.pug', function(){
    // gulp.src('取得するファイル') タスクの対象となるファイルを取得
    return(
      gulp.src(
          ['./src/**/*.pug', '!./src/**/_*.pug']
      )
        // pipe() 1つ一つの処理をつなげる。
        .pipe(pug({
            pretty: true
        }))
        // gulp.dest('保存先フォルダー') 処理を行ったファイルを指定の場所に保存
        .pipe(gulp.dest('./dist'))
    );
  })
});
// style.scssをタスクを作成する
gulp.task("sass", function() {
  return gulp.watch('./src/scss/*.scss', function(){
    // style.scssファイルを取得
    return (
      gulp
        .src('./src/scss/*.scss')
        // Sassのコンパイルを実行
        .pipe(sass())
        // cssフォルダー以下に保存
        .pipe(gulp.dest("./dist/css"))
    );
  })
});
gulp.task('ts', function() {
  return gulp.watch('./src/ts/*.ts', function(){
    return(  
      gulp
        .src('./src/ts/*.ts')
        .pipe(typescript())
        .pipe(gulp.dest('./dist/js'))
    );
  })
});
gulp.task('default', gulp.series( gulp.parallel('browser-sync', 'sass', 'pug', 'ts')));</pre>

<p>http://localhost:3000/へアクセスして確認。</p>

</div>
<img class="alignnone size-full wp-image-3510" src="https://chobimusic.com/wp-content/uploads/2020/06/12-2.jpg" alt="" width="576" height="322" />

<h2>おわりに</h2>
ちゃんとメモったので次からスムーズに環境構築できるようにしたい。

言い訳はできなくなったので、ちゃんとPug/Sass/TypeScriptを使ってアプリ制作取り組んでいこうと思います。笑
『Apple Developer Program』 に登録してみた

無料の開発者アカウントを使用してテストをしていたが、色々なサンプルを適当に試していたところ７日間で１０個までしかAppIDを作れない制限に引っかかったので、有料登録することに。7日間で10個までとか知らんがな。 
BundleIDとか適当に入れてビルドできた、良かったくらいしか考えて無いよ。。

購入してから有料アカウントになるまで、不安な時間を過ごしたのでメモ
**すぐには有料アカウントにならなかった。とりあえず待つのが正解。**

以下、流れ

- Apple DevelopperのAccountからEnrollの状態に。
- 購入後、以下のメールが届く。  (21:00頃)
  - ご注文ありがとうございます。
  - ソフトウェアのダウンロードはオンラインのご注文状況をご利用ください。
  - ダウンロード製品
  - Apple Developer Program - 1年間のメンバーシップ
  - ￥11,800
- **Enrollでpendingのまま（何回か再度購入しようか悩む）**
- 翌朝8:45に以下の2通のメールが届く。
 - Welcome to the Apple Developer Program
 - Welcome to App Store Connect.

登録されました。
双方向のバインディング！v-model使う？使わない？(Vue.js,Vuex)

#初めに
Vueインスタンス内のデータをテンプレートに表示したり、
テンプレートから入力を受けて、Vueインスタンス内のデータを更新したり、
双方向でバインディングしてくれるのですが、双方向のバインディングについて深掘りしていきます！

#v-model
双方向でバインディングと言えば、まずぱっとv-modelが出てくると思います！


```html
<template>
  <div>
    <input type="number" v-model="apple.number" />
    <p>{{ apple.number }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      apple: {
        number:0
      }
    };
  }
};
</script>
```
これだけで入力した値がVueインスタンス内のリンゴの個数(apple.number)を更新してくれて、
更新された内容がしっかりテンプレートにも反映されています。
双方向のバインディングを簡単に出来ますね！

###computedのset,get
双方向のバインディングをもっと柔軟にやる方法が他にもあるので紹介します。
computedにはdefallutでgetter関数の役割を果たせしてくれていますが、setterも使うことが出来ます。

```html
<template>
  <div>
    <input type="number" v-model="appleNumber" />
    <p>{{ apple.number }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      apple: {
        number: 0
      }
    };
  },
  computed: {
    appleNumber: {
      get() {
        return this.apple.number;
      },
      set(value) {
        this.apple.number = value;
      }
    }
  }
};
</script>
```

###Vuexとの連携

とくにVuexと連携させると力を発揮してくれます！

```html
<template>
  <div>
    <input type="number" v-model="appleNumber" />
  </div>
</template>

<script>
export default {
  computed: {
    appleNumber: {
      get() {
		//storeで管理された値を取得(ゲット)する
        return this.$store.getters.appleNumber;
      },
      set(value) {
		//storeで管理された値を更新(コミット)する
        this.$store.commit('appleCalculate',value)
      }
    }
  }
};
</script>
```

#v-bindとv-on:input(v-on:change)
そもそもv-bindとv-on:input(v-on:change)を簡潔に書く方がv-modelなんですが、簡潔に書ける分柔軟性が欠けたりなんてことはあるあるです。
例えば、Vuex使ってかつfor文の中でv-model使ってテンプレートからVueインスタンスにindex番号指定して、storeで管理してる値を更新したいなってなった時にv-bindとv-on:input(v-on:change)を使って解決したいと思います。(v-forのkeyの値にindexは使わないで下さい。ユニークな値を使って下さい)
※下記のサンプルコードはVuex使わずに書いてます。

```html
<template>
  <div>
    <div v-for="(fruit,index) in fruits" v-bind:key="fruit.name">
      {{ fruit.name }}:
      <input
        type="number"
        v-bind:value="fruit.number"
        v-on:input="fruitsNumber(index,$event.target.value)"
      />
      <p>{{ fruit.number }}</p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      fruits: [
        {
          id: 1,
          name: "apple",
          number: 0
        },
        {
          id: 2,
          name: "orange",
          number: 0
        },
        {
          id: 3,
          name: "grape",
          number: 0
        }
      ]
    };
  },
  methods: {
    fruitsNumber: function(index, value) {
      this.fruits[index].number = value;
    }
  }
};
</script>
```


###補足　v-on:inputとv-on:changeの使い分け
inputはイメージ的に入力なので、文字が入力された時に使う。
例えばtextやtextareaに文字が入力された時

changeはイメージ的に変化なので、状態が変化した時に使う。
例えばcheckboxやradioboxやselectが変化した時

#まとめ
簡潔に書ける時はv-model
簡潔に書けない時はv-bindとv-on:input(v-on:change)
Vuexが登場したらcomputedのsetterとgetter
Photoshopのアクションを移行する

##導入
先日photoshopをアップデートしたら
「データが消えますがよろしいですか？」→キャンセルしたら
何故か結局アップデートが始まった挙げ句、アップデートに失態した上で
アンインストールされて秘伝のアクションが消えたため。

#アクションの移動方法
###1.ファイルごと上書きする
C:\ユーザー\＜ユーザー名＞\AppData\Roaming\Adobe\Adobe Photoshop （バーション）\Adobe Photoshop CC Settingsに
Actions palette.psp
というファイルがあるのでこれを上書きする。
ただし初期アクションも全て保存されている上に、移行先のアクションは消える。

###2.移行するアクションをセットでまとめる
アクションでセット（フォルダみたいなやつ）を作ってそこに移行したいアクションをまとめる。
ポップアップメニュー（三みたいなボタン）からセットアクションの保存（.atnファイル）を行う。
移行先のphotoshopでatnファイルを読み込む。


今回はたまたま2台のPCで同じアクション作ってたので事なきを得ましたが
一台のみだと詰んでた…
学習の吐き出し１(Python編１)

学習の吐き出しです。
今回主に学んだのは、文字列についてでした。

### エスケープ
\のこと。文字列の改行***\n***でよく使われる。
こんな感じ。

```py
>>> palindrome = 'A man, \nA plan,\nA canal:\nPanama'
>>> print(palindrome)
A man, 
A plan,
A canal:
Panama
```
また、***\t***でテキストの位置調整ができる。

```py
>>> print('\tabc')
	abc
>>> print('a\tbc')
a	bc
>>> print('ab\tc')
ab	c
>>> print('abc\t')
abc	
```

そしてクォートを文字として使いたい場合も、\が必要。

```py
>>> testimonyb = "\"I did nothing!\" he said. \"Not that either! Or the other thing.\""
>>> print(testimonyb)
"I did nothing!" he said. "Not that either! Or the other thing."
```
本来、シングルクォートとダブルクォートは、文字列を文字列だと認識・表示させるための特殊な記号。
test = ""a"iueo"と変数に入力するとsyntax errorになる。
「これは、""として表示したいの？　それともaを文字として表示したいの？　書き方が変だからわからないよ！」
とpythonくんに怒られているわけです。

特にダブルクォートを文字として使用したい場合は、上記のコードのように\"で『文字だよ』と教えてあげましょう。

ダブルクォートの部分をまとめると、\は特殊文字の特殊性を打ち消す能力があるのです。


### +で連結
文字列は***+***記号で文字列同士を連結できる。
基本的には下記。

```py
>>> 'Release the kraken! ' + 'At once!'
'Release the kraken! At once!'
```

文字列だけなら、+を使わなくてもOK。

```py
>>> "My word! " "A gentleman caller!"
'My word! A gentleman caller!'
```

ただし変数を使う場合は、***+が必須***。

```py
>>> a = 'Duck.'
>>> b = a
>>> c = 'Grey Duck!'
>>> a + b + c
'Duck.Duck.Grey Duck!'
```

もちろん使わないとエラーが出る。

```py
>>> a = 'Duck.'
>>> b = a
>>> c = 'Grey Duck!'
>>> abc
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'abc' is not defined
```
これは変数をどうしたいかという指示がないため、エラーになる。
+は『変数の中の文字列を足して表示してくれ』と指示している。
下のprint(a,b,c)は、『変数の中の文字列を(a,b,c)の順に表示してくれ』と指示している。

ちなみに、これでも同じ結果を得られる。

```py
>>> print(a,b,c)
Duck. Duck. Grey Duck!
```

### *による繰り返し
*を使うと変数内の文字列を繰り返し表示できる。

```py
>>> start = 'Na ' * 4 + '\n'
>>> middle = 'Hey ' * 3 + '\n'
>>> end = 'Goodbye.'
>>> print(start + start + middle + end)
Na Na Na Na 
Na Na Na Na 
Hey Hey Hey 
Goodbye.
```
startの部分を解体すると、
１、『start』という変数
２、=で代入
３、文字列'Na'を格納
４、『*4』で４回繰り返しを指示
（文字列での表示指示ではないのでクォートは必要ない。むしろクォートで囲むと、文字列になっちゃうので計算ができません。）
５、'\n'で改行指示
（文字列として使用するためクォートで囲む）

というような感じです。

ちなみに、「+を使わなくても表示されるんじゃないの？」と思ったあなた！
こんな感じになります。

```py
>>> print(start,start,middle,end)
Na Na Na Na 
 Na Na Na Na 
 Hey Hey Hey 
 Goodbye.
```

1文字分ずれます。
些細なんですけど私は気になるので、+をちゃんと使うことをお勧めします。
理由は……あとで調べておきます。

---
とりあえず、一旦ここまで。
抽出や簡単な関数まで勉強したので、一気にやるとかなり長い記事になってしまうので。

この後もアウトプット含め頑張ります。
ユーザーとベンダーを繋ぐ！kintoneプラグインのリクエスト＆シェアサービス


ノベルワークスではkintoneユーザーと開発ベンダーを繋ぐ「リクシェア」というシェアリングサイトを運営しています。


![8f1ad314996a60f37628ee87672fffaf1ce56434ab230698919a5c3c1d1d33f231fc3328e20b3147856b3349add4d989268ca56303c1207f3661d0879d9457c0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605275/d6dd8c98-5be7-eb57-f11b-53c2fc373305.png)
https://reqshare.com/

**こんなプラグインあったらいいのにが実現します！**

#概要 
ユーザーが、リクシェア上で欲しい機能を投稿・共有し、同じ課題に悩むユーザーか
らの共感(いいね!)を集めます。たくさん「いいね!」を獲得すると開発ベンダーがkintoneプラグインとして開発・提供します。


![リクシェア.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605275/14a40328-97e6-2e56-d5e1-dec4c034a43f.png)
（実際の投稿画面）



#リクシェアを作った背景

kintoneはノンプログラミングで自社に合わせたオリジナル業務システムを誰でも簡単に作成できますが、細かい部分はなかなか難しくプラグイン（拡張機能）を利用したり
利用したいイメージに沿うプラグインがない場合は個別で開発依頼をする必要があります。
個別での開発となると、どうしてもかかる費用が高くなってしまいます。

ノベルワークスでも開発相談を多数お受けしているうちに、
**みんな同じような課題や要望を持っているのでは？**
という事に気づきました。
共通するのであれば、それをシェアし合ってプラグインとして安価で提供できれば
ベンダーもユーザーも双方が幸せになるのでは？と

**ベンダーはユーザーが本当に必要なプラグインを開発できる。**
**ユーザーはシェアすることで安価で課題が解決できる。**

『リクシェア』というシェアリングサービスが、我々開発ベンダーとエンドユーザー
を繋ぎ、オープンイノベーションの一歩になることを願って。


#リクシェアから誕生したプラグイン

実際に開発したプラグインからいくつかご紹介します。
無料試用も可能です！

<a href="https://www.novelworks.jp/kintone_plugin/data_synchronize">**アプリ間更新プラグイン**</a>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605275/1125d9be-4892-7f2a-e67f-25c3d941501a.png" width="40%">

活動履歴アプリと顧客管理アプリ両方でステータスを管理するフィールドがあるが、
それぞれで更新する必要があるので、どうしても漏れが生じてしまう・・
どちらかを更新したらもう一方のアプリの指定フィールドが自動で更新されたらいいのに
というお声から誕生しました！
<a href="https://www.novelworks.jp/kintone_plugin/subtable_change">**サブテーブルソートプラグイン**</a>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605275/ffb46964-c0f5-6763-a1ab-9271057e4ff3.png" width="40%">

案件のタスク管理をサブテーブルで行っています。
作業ステータスが「未着手」「作業中」「完了」とあるが、「未着手」が上に来るように
並び替える事はできないでしょうか？
タスク（行）が１０個くらいなら気にならないが、２０個くらいになると上位に表示される行はどんどん「完了」になっていくなか、スクロールして作業中（未着手）タスク行に辿り着くのが面倒です。というお声から誕生しました！

<a href="https://www.novelworks.jp/kintone_plugin/subtablecalc_plugin">**サブテーブル集計プラグイン**</a>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605275/cb1d1eaa-8ca7-454b-fea3-b839a7d5cf6f.png" width="40%">
日報アプリで1日の作業を1レコードとして登録し、
業務別の詳細はサブテーブルに記入しています。（案件番号・作業概要・稼働時間）
→日報登録時に、案件番号が同一の案件管理アプリレコードへ、稼働時間の集計を行いたい！
というお声から誕生しました！
 
 
 
 
#これからのリクシェア

リクシェアは、まだまだこれからのサービスです。
2020年6月にあらたに3つ（※）プラグインが誕生しましたがもっともっと
使いやすい、使いたいサービスになるよう日々改善していきます。
無料で会員登録できますので皆様ぜひ、利用してみてください！
皆様のお力をお借りしてもっと大きなサービスにしていきたいと思っています！！！

https://reqshare.com/




※あらたに誕生したプラグイン

<a href="https://www.novelworks.jp/kintone_plugin/interappcopy_plugin">アプリ間コピープラグイン</a>
<a href="https://www.novelworks.jp/kintone_plugin/excelimport_plugin">Excel読み込みプラグイン</a>
<a href="https://www.novelworks.jp/kintone_plugin/subtablecalc_plugin">サブテーブル集計プラグイン</a>
MAMPでのMySQL接続する時に、気をつけるべきhostの記述

最近UdemyにてPHPの入門講座を受けていたのだが、いざ「新たにアプリを開発するぞ！」といったところに差し掛かって、気合が入って来ていたさながら、MySQLにPHPのプログラムを接続しようとしてPDO~のコードを書いていた時に、**Connection Refused**と表示され、やる気をへし折られてしまった。。。(笑)

##最終的にPHPをMySQLに接続できたときのコード

```php:index.php

try {
        $db = new PDO('mysql:dbname=mydb;host=localhost;charset=utf8', 'root', 'root');
    } catch(PDOException $e){
        echo 'DB接続エラー: ' . $e->getMessage();
    }

```

##失敗したときのコード

```php:index.php

try {
        $db = new PDO('mysql:dbname=mydb;host=127.0.0.1;charset=utf8', 'root', 'root');
    } catch(PDOException $e){
        echo 'DB接続エラー: ' . $e->getMessage();
    }

```


##原因はなんだったのか

上記の２つのコードを見比べて、違いに気づいていただけただろうか。

その違いとは**host**の部分だ。

**筆者が使用している教材では、XAMPPが使用されているだが、筆者はMAMPユーザーなのでその辺の違いでエラーが出たようであった。**

どうやらMAMPでは

**host=127.0.0.1**

ではなく、

**host=localhost**

にしないといけないらしい。。

コードを間違えたのかとばかり考えて何度も見直して時間を食ってしまった。
間違えたら、秒速で検索しようと誓った瞬間であった。
[iOS] UITableViewのtableHeaderView/tableFooterViewをAutoLayoutに対応

この記事は `UITableView` の `tableHeaderView/tableFooterView` にAutoLayoutを利用する方法について書いていきます。

> ちなみに元々は[岸川さん](https://qiita.com/kishikawakatsumi)の[ツイート](https://twitter.com/k_katsumi/status/1255456988944912387?s=20)を参考に（というか丸パクリ）した旨をツイートするとどこかに書いておいてくれとの依頼があった物です。

元々のコードは[こちら](https://gist.github.com/kishikawakatsumi/612cbcf756ce6c0a1a0afd8fb5bb2825)です。
わかる人が見れば元のコードを見るだけで分かるかと思いますので、この記事ではどうしてこれで対応が可能なのか分からない人向けの説明をしようと思います。

```swift
headerView.translatesAutoresizingMaskIntoConstraints = false
tableView.tableHeaderView = headerView
NSLayoutConstraint.activate([
    headerView.topAnchor.constraint(equalTo: tableView.topAnchor),
    headerView.widthAnchor.constraint(equalTo: tableView.widthAnchor),
    headerView.centerXAnchor.constraint(equalTo: tableView.centerXAnchor)])
headerView.layoutIfNeeded()
tableView.tableHeaderView = headerView
```

上記のコードで気になるのは高さに関する制約が無いことです。
それによって最初に `tableHeaderView` に設定してAuto Layoutを有効化し、レイアウトを再計算する際に高さが自分自身の高さになります。
その後 `tableHeaderView` に再代入する際には `headerView` の高さが確定しているので正しい高さが表示されるということです。
また、[こちらのツイート](https://twitter.com/omochimetaru/status/1255470607636070400?s=20)にあるように `viewDidLayoutSubviews` で `headerView.layoutIfNeeded()` を実行するだけで画面回転にも対応しています。

簡単な[コード](https://gist.github.com/fromkk/fde679d0f9e06fe509cfde9b0f350b4e)で検証してみましたが、画面回転にも対応しているということが分かるかと思います。

![IMG_0008.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2846/42462c34-0261-eedc-eb4f-092bdaca3662.gif)

# まとめ

`tableHeaderView` はこれまでは事前に高さを計算した上で

```swift
tableView.tableHeaderView = nil
tableView.tableHeaderView = headerView
```

のような指定をすることが多かったかと思います。
`headerView` にAuto Layoutを利用している場合はこちらの手法が有効そうですね。
最初にツイートをしてくれた[@omochimetaru](https://qiita.com/omochimetaru)さん[@k_katsumi](https://qiita.com/kishikawakatsumi)さんありがとうございました。
【初心者向け】Chrome Developer Tools の Console でのJavaScript実行

Chrome Developer Tools の Console パネルでは JavaScript が実行できる（`var`や`function`を定義すると`undifined`と返ってきたので定義できてないのかと思ったら、そうではなかった）。

##練習

```javascript

function add(a, b=20) {
  return a + b;
}
// undifined と返ってくる

add(25);
// 45
```

##検索窓フォームの値を変更してみる

<img width="921" alt="スクリーンショット 2020-06-17 12.25.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/7b11138f-1984-228d-5c6e-ee018d80277c.png">

より実践に近い練習のために検索フォームの値を変更するコードを書きたいときに、Consoleを使って確かめながら開発するケースを想定する。

先に結論から言うと以下のコードで書き換えができる。

```javascript

var parent = document.getElementsByClassName('search-form');
// undefined
parent[0].getElementsByClassName('search-field')[0].value = 'bbb';
// "bbb"

```

ただ上記のコードをに辿り着くまでには、Consoleで以下のようなお試しを行っている。
<img width="1404" alt="スクリーンショット 2020-06-17 12.21.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242610/9e9d7a82-493b-183c-b251-bd311da8ef8a.png">

実行したコードを1行ずつ見ていく。

```javascript

var parent = document.getElementsByClassName('search-form');
// undefined ← これは今まで未定義だったという意味っぽい

parent
// HTMLCollection [form.search-form] ←ちゃんと変数に値が入っている
// 0: form.search-formlength: 
// 1__proto__: HTMLCollection

parent.children
// undefined ← よくみるとparentはCollectionなのでundefinedとなる

parent[0].children
// HTMLCollection(2) [label.screen-reader-text, input.search-field, s: input.search-field]

parent[0].getElementsByClassName('search-field');
// HTMLCollection [input.search-field, s: input.search-field]

parent[0].getElementsByClassName('search-field')[0].value = 'bbb';
// "bbb"
```

これで導き出したコード（プログラム）を本ちゃんのファイルに記述する。普段ChromeのConsoleによる操作をしてこなかったので、もっと良い試し方やデバッグ方法があれば教えてほしいです。

##公式ドキュメントでちゃんと学んだほうがいい

Chrome DevTools で JavaScript をデバッグする
https://developers.google.com/web/tools/chrome-devtools/javascript?hl=ja

Consoleの使用
https://developers.google.com/web/tools/chrome-devtools/console/javascript?hl=ja


##参考
脱jQuery
https://wemo.tech/2101
vagrant環境でCentOS7のgitを2.xにアップデートする【備忘録】

#概要
CentOS7内のGitのバージョンが古いため2.xにアップデートしたい。

####開発環境
macOS:Mojave
Vagrant:2.2.9
CentOS:7.8

##きっかけ
VSCODEを用いてvagrant環境下のファイルをremote直接いじれるようにしたい。
しかし、Vagrant下のファイルをVSCODEを開いた際にGitのバージョンが古いのでアップデートしてねと言われてしまう。

cf.【VagrantでVScodeのRemote Developmentを使おう！】
https://qiita.com/hppRC/items/9a46fdb4af792a454921

###やったこと
Qiita等でいくつか参考となる記事が見られたが

インストール時に接続切れになりインストール出来ない。
or

```
sudo make prefix=/usr/local all
sudo make prefix=/usr/local install
```
のところでいずれもエラーとなってしまう。


##解決策
海外の記事を参考に、以下の3つのコードを実行することでバージョンアップできた

```
sudo yum remove git*
```
```
sudo yum -y install https://packages.endpoint.com/rhel/7/os/x86_64/endpoint-repo-1.7-1.x86_64.rpm
```
```
sudo yum install git
```

cf.
https://computingforgeeks.com/how-to-install-latest-version-of-git-git-2-x-on-centos-7/
denoにlintツールが追加されました

#ESlintより高速なリントツール
　私は仕事で大規模なjs/tsプロジェクトに参加したことがないので、lintツールを使ったことがありません。個人開発でも入れようと思っていたんですが、後手後手に回っていました。ちょっと面倒そうだな…という逃げの精神ですね。
　しかし、6/13の1.1.0アップデートでdenoがCLIツールとしてlintツールを導入してくれました。もうこれで逃げることはできません。そこで、さっそく使ってみたので、この記事では概要をご紹介しようと思います。
　詳細はこちらを読んでください。→[Linter](https://deno.land/manual/tools/linter)

##良い点
　正直、私はESlintを使ったことがないので比較は出来ないのですが、良かった点を書いてみます。
###動作が早い
　rustで書かれているからか、高速で動くそうです。私が実際に図ったわけではないので、未検証ではありますが、公式によると下記のような結果が出たそうです。

>"runsAvgMs":2.4468227999999725,
>"runsAvgMs":2282.9389232,
>https://github.com/denoland/deno_lint

試行回数5回
denolint→平均約0.00245秒。
ESlint→平均2.28294秒

　おおよそ1000倍以上の差が出ています。条件によって色々変わることは想定されますが、相当の性能差です。まぁこんなにEslintが2秒かかるから困る

###環境構築が簡単（不要）
　deno v1.1.0なら特に追加の設定なく使えます。
　因みにdenoはアップデートも簡単です。

```bash
#latestへアップデートされます。
deno upgrade 
#因みにバージョン指定もできるので、バージョンダウンも簡単です。
deno upgrade --version 1.0.5
```
###利用方法も簡単
　コマンドを叩くだけです。

```bash
#まだテスト機能なので、unstableフラグが必要です。
#そのうち必要なくなると思います。
deno lint --unstable
```

###lint対象外にするのが簡単
　プログラムの記述前に下記の様にコメントを差し込むだけで、lintの対象外にすることができます。またlintのルールをコメントの最後にいれることで、特定のルールのみ無視することも出来ます。

```typescript
// deno-lint-ignore-file 対象ルール名
const main = () =>{/*more*/}
```
ルールに関しては、公式ドキュメントを確認して下さい。

##おわりに
　開発中ではありますが、便利だと思います。モダンなサーバサイドjsであるdenoにlintツールが標準付属するのも、これからの時代を感じさせますね。まだきちんと使いこなせてはいないので、色々調べてまた記事にするかもしれません。