OmniAICreator/Qiita-1.07M huggingface dataset:
現場でよく使う Git コマンド集

# 現場でコピペシリーズ Git版リリースです。

## 2.23辺りからの追加変更(以下はcheckoutの代替）
### Checkout従来の複数機能の整理
```
ブランチ作成・切替
修正取消
コミット取消・修正
```
### ファイル取消
```
git restore <ファイル名>
```
### ステージング取消
```
git reset
```
### コミット取消
```
git revert <コミットID>　　# 指定コミットの取消
git restore --source <コミットID> <ファイル名> # 特定のコミットに変更
```
## 従来機能
### リモート設定 
```
git remote -v　　　　　　　　# リモート確認
git remote add origin　　　　# リモート名追加
git remote rm <リモート名> 　# リモートの削除
git remote set-url           # リモート設定 
git fetch origin ブランチ名　# リモート最新情報でローカルorigin/master更新
```
### Clone & Pull
```
git clone <リモートリポジトリURL>/<クローン先のディレクトリ>
git config pull.rebase false   # merge
git config pull.rebase true    # rebase
git config pull.ff only        # fast-forward only
```
### コンフリクト解消後pull
```
git reset --hard HEAD
git pull origin master --rebase
```
### ブランチ
```
git branch -a               # 全てのブランチ閲覧
git checkout <切替えるブランチ> 　 # ブランチ切替（古い）
git switch   <切替えるブランチ>    # ブランチ切替
git checkout -b  <作成ブランチ名>　# ブランチ作成
git checkout -b  <作成ブランチ名> <リモートブランチ> # リモートブランチから作成
git switch -c <作成ブランチ>
git push origin     <追加するリモートブランチ>　# リモートにブランチ追加
git push -u origin  <作成するリモートブランチ名>
git branch -d    <マージ後の削除するローカルブランチ>
git branch -D    <マージしてないローカルブランチ削除>
git branch -m       <旧ブランチ> <新ブランチ>
git push origin    :<削除するリモートブランチ> 
git push origin     <新ブランチ>
```
### マージ (ブランチのコミット履歴を残す（並行）) 
```
git checkout master
git merge <作業ブランチ>
```
### リベース (コミット履歴を一本化する）
```
git chekout <作業ブランチ>
git rebase master　# ブランチ先頭 + マスタ
# rebase 後に
git merge          # マスタにブランチを取り込む
```
### 変更取消（ワーキングツリー（ステージング前））
```
git checkout .
git restore .
```
### ステージング
```
git add .　　　　　　　　　 # 全てステージング
git add -a                  # 変更したもの全て
git add -n    　　　　　　　# ステージング対象表示
git add -u <ステージング対象ファイル>
```
### ステージング取消
```
git reset --hard HEAD　　　 # ワーキングツリ+インデックス＋HEAD 取消し
git reset --mixed           # インデックス＋HEAD 取消し
git soft  --soft            # HEAD 取消し
git reset --soft HEAD^      # 直前のコミット取消し
git reset  --hard HEAD~n    # Ǹ個前まで戻す
git reset --hard ORIG_HEAD  # reset の取消
git restore --staged <ファイル名>
git rm --cached             # ステージング削除
```
###Commit & Push
```
git fetch origin <リモートブランチ名>　
              　　　　　　　# リモートから最新情報をローカル(origin/master)に持ってくる
git merge                   # ローカルorigin/master ローカルmasterマージ
git reflog                  # コミット履歴閲覧
git commit --amend          # メッセージ編集してコミット
git commit -m "メッセージ"   
git archive　　　　　　　　　# 変更のあったものだけ抽出
git push origin HEAD　　　　#リモートにPush
git push oriigin <ブランチ>　#リモートにPush
```
### Commit 取消
```
git log
git revert <コミットID>
git checkout <コミットID>
```
### Push 取消
```
git reset --hard HEAD   # ローカルコミット取消
git push -r origin <リモートブランチ>
```
### タグ
```
git tag    <tag名>          # 最新のコミットにタグを付ける
git tag -a -m <メッセージ>
git tag 
git tag -l 'tag.*'          # 正規表現でtagを検索
git push   <tag名>          # タグ反映
git show   <tag名>          # タグ確認
```
顔認証機能を提供しているOSSについてメモ

業務で顔認証機能を提供しているOSSについて調査する機会があったので、メモを残しておきます。

##1. OpenCV

>OpenCVは、画像処理・画像解析および機械学習等の機能を持つオープンソースのライブラリです。オープンソースですので、基本的に無料で使用することができます。Pythonを始め、C/C++、Java、MATLAB用として公開されており、もともとはインテルが開発・公開しています。

####関連記事
公式ページ,Github
https://opencv.org
https://docs.opencv.org/3.4.3/d1/dfb/intro.html
https://github.com/opencv/opencv
OpenCVで顔認証やってみた
https://qrunch.net/@Atom/entries/Q9fV8JEIQJVCDVId?ref=qrunch
OpenCV だけで顔検出から顔照合まで完結している
https://qiita.com/nonbiri15/items/a970affd90b7a02b2e85
>ただし、OpenCVに現時点で実装されているコードだけでは、商用ライブラリのうち高い水準にあるものとは次の範囲で違いが生じる可能性は高いと思われます。
*隠れのある顔画像
例：マスクをした顔・サングラスをした顔
*正面を向いていない顔
例：３０度ほど斜めを向いた顔
*よくない照明条件
光が均一な当たり方をしていない顔画像


##2. face_recognition

dlibベースのDLを利用した顔認証ライブラリ
※dlibは機械学習のC++ Pythonのライブラリ

####関連記事
公式ページ,Github
https://github.com/ageitgey/face_recognition
https://pypi.org/project/face-recognition/
https://www.cresco.co.jp/blog/entry/9468/
>このモデルはFaceNetにインスパイアされているようなので、詳しい仕組みや理論的な背景はその論文を読むと良いかと思います。

顔識別を行う（Dlib と ageitgey/face_recognition パッケージを使用）
https://www.kkaneko.jp/dblab/dlib/facerec.html
OpenCVとdlibとOpenFaceでの顔検出と知見まとめ
https://vaaaaaanquish.hatenablog.com/entry/2016/06/28/004811

##3. face-net

>FaceNetは2015年にGoogleが発表した顔認証用のニューラルネットワークです。
FaceNetの論文はこちらから参照できます。 https://arxiv.org/pdf/1503.03832.pdf

####関連記事
Github
https://github.com/davidsandberg/facenet
FaceNet(顔認識)を動かしてみた
https://masaeng.hatenablog.com/entry/2019/07/26/234225
>Facenetを使うことでのメリットは、以下が挙げられます。
1. 学習済みモデルが利用できる
2. ベクトルに落とし込むので、検索したい人の画像が少なくてすむ
3. 顔画像に特化している
4. お手軽

FaceNet（顔認証）を使って自動撮影カメラを作ってみた
https://masaeng.hatenablog.com/entry/2019/08/09/235046

##4. OpenFace

>オープンソースの顔認識技術としてOpenFaceというものもあります。http://cmusatyalab.github.io/openface/
こちらはFaceNet論文を元にしたオープンソースの実装です。

あまり調査できていないが、情報は少ない印象。

##まとめ

非DLのOpenCVは、DLを利用している他ライブラリと比べると、顔の写りなどによっては精度が劣るらしい。
関連記事のサンプルは、すべてPythonで実装。
それぞれの実装のし易さ、精度などは実際に動かして検証する必要がありそう。
face_recognition と face-net を検証してみるのがいいかも。

各ライブラリを比較するために↓表に整理しました。情報はまだざっくりしています。
<img width="1508" alt="スクリーンショット 2020-06-29 10.10.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281645/a3f9629a-154a-4094-be6d-9b0385637a14.png">
![スクリーンショット 2020-07-20 21.07.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281645/63e77324-3b59-e566-7018-aca392d6790b.png)
School of Rop - Computing Fundamentalsやってみる - 2

いろいろと正しい、作業環境の作り方、モチベーションの保ち方、新しいことを初めてからスキルを習得するまでのステップ、いろんな内容の
マテリアルがあるけど、そこはさらっと流し読みして、早速Build a Labセクションを始めてみる。

やってみたこと。
1.VM環境構築 - VMwareが推奨されているが、VMBoxでももちろん可。
2.Ubuntuをインストールする。
  - WallPaper変更してみる
  - Google Chromをインストールする
  - Unity Tweak Toolをインストールする
  - VLCプレイヤーをインストールする
  - GIMPをインストールする

ここまでやってみてスナップショットをとってからひとまず終了。
全部コマンドラインでやってみたが、すでに持っていたRemnuxの環境でやると
ChoromのインストールにいろんなDependenciesがないとか、Unity Teak Toolでもあれも、これもインストールが必要と
エラーでぐぐりながらどうにか完了した。

その他、インストールしたUnity Tweak Took、GIMPで少し遊んでみました。

フリーソフトなのにいろいろできて素晴らしや！
Node - Error: unable to verify the first certificate


Using https or wss to create a client connection. And it will create failed.

```
Error: unable to verify the first certificate
```

Added the below code to disable the SSL check.

```
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
```

https://blog.darkthread.net/blog/npm-unable-get-local-issuer-cert-issue/
https://medium.com/nodejs-tips/ssl-certificate-explained-fc86f8aa43d4
School of Rop - Computing Fundamentalsやってみる - 1 

サイバーセキュリティの基礎を再度勉強しようと思い、下のサイトを発見したのでちょっとチャレンジしてみる。

https://academy.hoppersroppers.org/

まずはComputing Fundamentalsという基礎の基礎コースを覗いてみる。

トピック：
Use Password Manager 
https://www.howtogeek.com/141500/why-you-should-use-a-password-manager-and-how-to-get-started/

Use Ad-blocking extention
例）https://chrome.google.com/webstore/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm?hl=en

Basically this first page talks about how to secure ourselves online. 
Let's use Password Manger and use ad-blocker in every machine you use at home and work. 
If you are using Windows machine, keep the machine updated to the latest at all time and turn on Windows Defenders if it is not turned off. 

While these steps seem to obvious, doing fundamentals make you significantly more secure than average internet users.
【CentOS】NFSマウント コマンドまとめ



# NFSファイル共有

 - exportfs：ファイルシステム内の**ディレクトリをエクスポート**するコマンド
 - no_root_squash：クライアントのrootアクセスを**サーバ上にも適用**する
 
|オプション|詳細|
|:--:|:--:|
|rw|読み込み、書き込みを**両方許可**する|
|ro|**読み込みに限り**、許可する|
|sync|**同期書き込み**を有効にする|
|async|**非同期書き込み**を有効にする|
####◆ mountコマンド

```
//serverIPアドレス, マウントポイントを指定
$ mount -F 192.168.0.2:/nfs /tmp/sample
```

#ディスクフォーマット
 - partedコマンド：ディスクを``パーティション分割``する際に使用する <br>
 ※ パーティション管理方式として``MBR``と``GBT``がある <br>
 ※ ``fdiskコマンド``は、``MBR方式``のパーティション限定

####◆ partedコマンド

```
//parted <デバイス名>
$ parted /dev/sdb

//会話形式でパーティション方式を選択する
(parted) mklabel gpt
```

          

#Firewallの許可設定
 - FireWallの設定上、```zone```と```service```の設定が必須
 - permanent：```恒久的```
 - DMZ：```非武装地帯```　外部NWと内部NWを``Firewall``によって隔離されている
 - eth0：``NIC``(ネットワークインタフェースカード)の１つ。``インターネット通信``のみ可能


####◆ firewall zone一覧
|zone|詳細|
|:--:|:--|
|public|**デフォルト**で設定されているルール|
|work|**会社**で設定されているルール|
|home|**家庭**で設定されているルール|
|internal|**内部NW**でFirewallを構築する際に使用するルール|
|external|**外部NW**でFirewallを構築する際に使用するルール|
|DMZ|**DMZ**でFirewallを構築する際に使用するルール|

####◆ firewallコマンド
```
//zone, serviceを各々追加する
$ firewall-cmd --permanent --zone=public --add-service=nfs

//FW設定を反映する
$ firewall-cmd --reload

//FW上のservice一覧を確認
$ firewall-cmd --list-all
```

# RPC設定

 - RPC：```Remote Procedure Call```の略。ネットワークを跨いだ処理の際に、```リクエストを送り、レスポンスを受け取る``流れのこと

####◆ rpcbind関連コマンド
```
//rpcbind.serviceを起動する
$ systemctl start rpcbind.service

//rpcbind.serviceを許可する
$ systemctl enable rpcbind.service

//rpcbind.serviceのステータスを確認する
$ systemctl status rpcbind.service
```

####◆ rpcbind.socket設定例

```:/etc/systemd/system/rpcbind.socket
[Unit]
Description=RPCbind Server Activation Socket

[Socket]
ListenStream=/var/run/rpcbind.sock
ListenStream=111 
# ListenStream=[::]:111     //コメントアウト
# ListenStream=0.0.0.0:111  //コメントアウト
# BindIPv6Only=ipv6-only 　　//コメントアウト

[Install]
WantedBy=sockets.target
```

####◆ rpcbind.socket設定反映コマンド

```
//rpcbind.socketの内容を反映する
$ systemctl daemon-reload

//NFSサーバを起動する
$ systemctl start nfs-server

//NFSサーバを許可する
$ systemctl enable nfs-server
```








# 参考文献

 - [5分で終わらせるNFSファイル共有](https://qiita.com/rikudai/items/f9900e4865ce25a8464e)
 - [exportfs](https://linuxjm.osdn.jp/html/nfs-utils/man8/exportfs.8.html)
 - [Linux NFSサーバの設定](http://www.kuromogu.com/ha/comp/sw/soft_linux_nfs.html)
 - [CentOS 7 firewalld よく使うコマンド](https://qiita.com/kenjjiijjii/items/1057af2dddc34022b09e)
 - [そもそも RPC ってなんだ](https://qiita.com/il-m-yamagishi/items/8709de06be33e7051fd2)
 - [NFSファイルシステムの自動マウント（CentOS7）](http://www.sebegginer.com/article/449338938.html)
 - [parted コマンドについて](https://qiita.com/centipede/items/ae181fcb76f549514918)
 - [NFS : サーバーの設定](https://www.server-world.info/query?os=CentOS_8&p=nfs&f=1)
 - [[Linux] firewalldでfirewallの設定をする](https://qiita.com/suzutsuki0220/items/4a62cc0e676a80ed79f1)
 - [DMZとは](https://it-trend.jp/words/dmz)
 - [2.14 仮想サーバのNIC（eth0、eth1、eth2）で可能な通信を知りたい](https://manual.iij.jp/gp/gpcp/f-2-14.html)
うちはこんなワーキングアグリーメントやってますよ

# はじめに

チーム内の暗黙的な決め事をワーキングアグリーメント(Working Agreement)として明文化してみました。

他のチームではどんな内容を実践しているのかな、と調べてみましたが、あまり具体的な例が出てこないようです。実際決めたり運用していく中で、実際の例があると、参考になるかと思います。

そこで、細かい業務以外の文化的な部分をかいつまんで紹介してみます。

# ワーキングアグリーメントとは

ワーキングアグリーメントについての詳細な説明は参考リンクに譲りますが、

簡単に説明すると「チーム内のお約束」です。

チームメンバーが自律的に働けるようにするという目的の基で、必要最低限のみんなで守っておきたい決め事です。

初版の決め方の流れは、まずはチーム内で重んじる価値観を決めた後に、具体的なルールを決めるのがいいんじゃないかと思います。
大まか素案を作るのはリーダーの采配でいいと思いますが、本決定はチームメンバー全員で話し合うのが良いでしょう。決める過程自体がチームビルディングや自律性の向上に繋がります。

後は、どのように更新して運用するかは決めておくべきでしょう。

## 参考

- [Working Agreementやってる？](https://qiita.com/naoto_koyama/items/95d0012ba481db9fc43b)
- [Working Agreement についてのまとめ](https://qiita.com/FALZ/items/914f892b1308871e68e1)
- [チームの暗黙の了解をWorking Agreementとして定めた話](https://ishitonton.hatenablog.com/entry/2019/02/14/193423)


# 弊チームのワーキングアグリーメント

## ワーキングアグリーメントの管理について

- 月に一度、全員で話し合い、見直しを行う

## 基本方針

- 背景・目的を意識して業務に臨む
- 主体的に業務に取り組む
- 日々の業務の中で品質向上への意識を忘れず、改善ポイントを探す

## 勤怠

- 生産性の低下を避けるため、過度な残業は行わない
    - 好きでやるのは止めないが、体調管理に十分気を付ける
    - 業務上のリスクは、デイリーミーティングかSlackで素早く共有する

- 休暇、遅刻、早退などの勤怠連絡は前週に連絡する
- 休暇、遅刻、早退などの勤怠連絡は前日にリマインドする
- 体調不良による休暇は都度相談する
    - 常に他のメンバーに引き継げるように業務を遂行する

## チーム内イベントに関して

### デイリーミーティング

- 毎日同じ時間(〇時〇分)から開始する
- 各自、以下の項目について話す
    - 前日行った作業
    - 今日の作業予定
    - 共有事項や懸念点など
- 共有を手早く行うため、事前に以下を行っておく
    - 第三者に分かる粒度に話す内容の整理
    - 自分がアサインされたタスクについてタスクボード上で更新
- 15分以内に収める
    - チーム全体に関係ない話はしない
    - どうしても必要な会話は解散後に行う
- 参加できない人がいる場合、進行役以外の誰かが議事録をとり、終了後1時間以内に共有する

### 1on1

- 会話内容はリーダーが見える化し、終了後に内容を送付する
- リーダーが1on1で知った内容は第三者に展開しない
- 1on1で発生したToDoは明示的に記録する
    - 次回にToDo内容を確認する
- アジェンダはメンバーが1時間前に送付する

## ツールに関して

### Slack

- 業務連絡全般は基本Slack上で行う
- センシティブな情報のやり取り以外DMは使わない
    - 都度Publicチャンネルに誘導する
- 承諾やお礼など一文で済むものはスタンプで済ませる
- 相手が見てないこともあるので、時間に余裕を持ったコミュニケーションを行う
- 返信に時間がかかる場合、とりあえず確認したことだけでも伝える
- 無駄なやりとりを減らすため、送付内容は事前に精査した上で投稿する

### Zoom

- ハウリングを回避するため、音声はイヤホン等から出力する
- ホワイトノイズが乗りやすい人は、発言時以外ミュートにする

### メール

- Slackで対応できない時のみメールを利用する
- 状況把握のため、必ずリーダーをCCに入れる

### Jira

- タスク管理全般の責任はリーダーがもち、必要なタスクの作成と全体のステータス状況を確認する
- アサインされたタスクの細かい作業の可視化はメンバーが責任を持つ

### Confluence

- 分析や調査内容、新ツールの使い方やトラブルシューティングなど、業務に影響を与えるナレッジは必ずまとめて蓄積する
    - 典型的なものは指定のフォーマットを使う
- 他者に伝わる内容、表現で記述する
- ページの最適な置き場が分からなくとも、とりあえず作成し、後で整理する

# 関連

- [弊チームのマネジメント・ビルディング取り組み](https://qiita.com/calderarie/items/521e6b077abeaaa2e6d5)
- [コードレビューに関する指針](https://qiita.com/calderarie/items/a447cb0d1b034f951a90)
- [チームで行っているオンボーディングに関する取り組み](https://qiita.com/calderarie/items/1acab74403881ef4a6f9)
- [1on1をするときに意識していること](https://qiita.com/calderarie/items/daa6c82f4cfd687d1c9a)
- [Trelloを使ったタスク管理の運用方法についてまとめる](https://qiita.com/calderarie/items/02cde8530d3227df013f)
SQLSeverのテーブル一覧を出力

特定のカラムを持つテーブルの一覧を出力するSQLです。
よく使うのでメモ。

```sql
SELECT   TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME
FROM     INFORMATION_SCHEMA.COLUMNS
WHERE    COLUMN_NAME='検索したいカラム名'
ORDER BY TABLE_SCHEMA, ABLE_NAME, OLUMN_NAME
;
```
在宅勤務で便利だったzoom機能紹介

# Who am I??
- SIerでシステム開発（基盤）を経験し5年目
- PJ全体で40~50人の案件で8人程度のチームリーダを担って2年目（全体で4チームが連携）

# 在宅勤務状況
4/7の緊急事態宣言に伴い私の所属する組織/PJでも在宅勤務の動きとなりました。
- 4/17から現時点（6/15）まで原則在宅勤務
- 勤務時間はチーム単位の有償版zoomアカウントが開催したMTGルームに原則参加

# Zoom便利機能紹介
2か月間zoomを利用したテレワークをやってみて便利だった機能を紹介します。
- 共同ホスト機能
- ブレークアウトセッション機能
- 招待機能

## 共同ホスト機能

### 機能概要
共同ホスト機能を有効化し、参加メンバに割り当てることでルーム参加者の許可を複数人で実施できる
### ユースケース
別打ち合わせに参加したメンバの再参加時やホストがスピーカーとなり、話すことに集中してしまっている際に別メンバでMTGルーム参加の承認が可能になる
### 公式リンク
https://zoom-support.nissho-ele.co.jp/hc/ja/articles/360025019352-%E5%85%B1%E5%90%8C%E3%83%9B%E3%82%B9%E3%83%88%E3%81%AE%E6%9C%89%E5%8A%B9%E5%8C%96%E3%81%A8%E5%8F%82%E5%8A%A0%E8%80%85%E3%82%92%E5%85%B1%E5%90%8C%E3%83%9B%E3%82%B9%E3%83%88%E3%81%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95

## ブレークアウトセッション

### 機能概要
在宅勤務時のTm内コミュニケーション用に常時参加するMTGルームにおすすめ。MTGルーム内にホストが割り当てた人のみ参加可能（移動操作はゲストが操作可能）な子グループを作成できる。

### ユースケース
- Tm内の限定メンバのみで打ち合わせを実施したい場合
- 気軽な雑談を始めたい場合
1度割り当てをしておくと参加メンバが自由に子グループとメインルームを行き来できるため、メンバ判断で「ブレークアウトセッションで会話しよう」という動きが可能。

### 注意点
ブレークアウトセッション機能を開始すると、新たに子グループは追加できない。
往々にして、Tm内メンバが少人数打ち合わせしているときに他Tmメンバを呼び込んで少し話がしたいというユースケースがあるので、
Tm内メンバを割り当てているセッションとその他のセッションを作成しておくのがおすすめ。

### 利用時例
![ブレークアウトセッション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/640480/843ac4e4-bd10-6397-2460-cd2bfddebdb8.png)

### 公式リンク
https://support.zoom.us/hc/ja/articles/206476093-%E3%83%96%E3%83%AC%E3%82%A4%E3%82%AF%E3%82%A2%E3%82%A6%E3%83%88%E3%83%AB%E3%83%BC%E3%83%A0%E5%85%A5%E9%96%80

## 招待機能

### 機能概要
MTGへの招待を容易にできる。

### ユースケース
- 他Tmメンバとの連携を気軽にしたいとき（別MTGルームに参加しているメンバでも別MTGルームから簡単に呼び出し可能。）

### 公式リンク
https://zoom-support.nissho-ele.co.jp/hc/ja/articles/360025018512-%E9%80%A3%E7%B5%A1%E5%85%88-%E5%85%A5%E9%96%80%E7%B7%A8-


# 振り返り
整理中

## 良かったこと
- 特殊な在宅という環境で如何にコミュニケーションロスを起こさないか真剣に考えることができた。結果として今回はツール（zoom）による解決が大きかったが、「同期コミュニケーション→非同期コミュニケーションへの移行」といったマインドセット部分も変えていこうというチームの取り組みも出来た

## 良くなかったこと
-
メロスは激怒した。必ず、かの乱雑なタスクを管理せねばならぬと決意した【タスク管理ツール】

##メロスはタスク管理ツールが多すぎてわからぬ。
**メロスは村のディレクターである**。UIを描き、フォトショップと遊んで暮して来た。けれども**タスク管理**に対しては、人一倍に敏感であった。**リモートワークが進む昨今、内外のタスク進捗**が全くみえないのだ。

##メロスは村を出発し十里はなれたGoogle市にやって来た
メロスには相談する友人も、ディレクターも**女房も無い。**
メロスは、それゆえ、コスパやらサービスの概要やらを調べに、はるばる市にやって来たのだ。
先ず、その品々を眺め、それからGoogleの大路をぶらぶら歩いた。
歩いているうちにメロスは、まちの様子を怪しく思った。
もう既に日も落ちて(調べすぎ)、まちの暗いのは当りまえだが、
けれども、なんだか、**眼精疲労**のせいでは無く、
**サービスが多すぎて、のんきなメロスも、だんだん不安になって来た。**

##路で逢った若い衆をつかまえて、何が良いのか？と質問した。
若い衆は、首を振って答えなかった(検索下手)
しばらく歩いて老爺に逢い、こんどはもっと、語勢を強くして質問した。
老爺は、あたりをはばかる低声で、わずか答えた。

老爺「**ClickUp**( https://clickup.com )がいいと思いますじゃ・・・」
![名称未設定-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/9e3cfc7f-6d82-7d5d-b000-ec9ebab393fd.jpeg)

メロス「なぜだ。」
老爺「ClickUpは、UIや互換性に優れておるのじゃ。
タスクを**リストビューやパネルビューに加えて、カレンダーやガントビューなど**
好みのタイプに変更でき**無料でも100MBのストレージ、タスクとユーザーが無制限で**
**基本的なタスク管理機能は全て備わっておる**のじゃ・・・」
![02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/e277d061-04bf-5d66-2655-e431ab3c0976.jpeg)
![03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/2dc74364-6084-c5b0-5655-a9808bac5b4a.jpeg)


メロス「本当か。」
老爺「**外部パートナーを特定のプロジェクトにのみ招待する**こともでき、
お主が外注しているパートナーのタスク進捗も容易に管理できるはずじゃ。
さらに有料版にすると、他社サービスからインポートも出来る上、
GoogleDriveなど外部サービスにアクセスもできるのじゃ・・・。
詳しくは公式サイト( https://clickup.com/ )をみると良い。」

メロス「(気前が良すぎて)おどろいた。国王は乱心か。」

##タスクごとのチャットも便利なのじゃ
老爺「タスクにはラベルがつけられており、1クリックで変更できるのじゃ、さらにタスクごとにチャット機能があるので、Slackで色々な話が飛び交う心配もないじゃろうて」
![06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/4b805553-ce22-4b82-5750-7d251038ca17.jpeg)
![07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/fc8ce5ee-bbe5-c2f6-89cd-371b0a036e32.jpeg)


メロス「なんと素晴らしい・・・！
これほどの情報を頂いた礼はせねばならぬ、名を教えてはくれぬか」

すると老爺は、おもむろに覆面を剥がし声高にこう言った。

・・・

・・

・


**「友よ、我が名は整理ヌンティウス！」**
Gitの基本操作(リポジトリの作成方法、コミット&プッシュ、フェッチ&マージ)

# Gitのリモートリポジトリの作り方

### ローカルリポジトリ→リモートリポジトリ

```shell
# フォルダ作成&初期化
mkdir {project_name}
git init

# GitHUB上でリモートリポジトリを作成する

# GitHUB上のリモートリポジトリを追加
git remote add origin {URL}

# URLを確認
git remote -v

# push
git push -u origin/master
```

### リモートリポジトリ→ローカルリポジトリ

```shell

# フォルダを作成してリモートのブランチを複製する方法
git clone {URL}

# リモートリポジトリの追加
git remote add origin {URL}

# URLを確認
git remote -v
```

### ローカルリポジトリの削除

```shell
# 削除実行
# 強制削除のため実行する際は十分注意する
rm -rf {git_folder_name}
```

# コミット&プッシュ

```shell
# 新規ファイルの作成
touch {file_name}
git status

# コミット&プッシュ
git add {file_name}
git commit -m '{comment}'
git push -u origin master

# コミット&プッシュ(ショートカット)
git add --all         # 全ファイルを取得可能
git commit -m ''

# コミット&プッシュ(ショートカット2)
git add .
git commit -am ""     # commit&add

# コミットした変更を取り戻す方法
git reset --hard {HEAD}
```

# フェッチ&マージ

```shell
# リモートリポジトリからローカルにデータを抜き出す
git fetch {repository_name} {branch_name} # git/objectsの中にリモートから取得したデータを保存する

# masterブランチに最新の情報をマージ
git merge {repository_name}/{branch_name}

# git fetchとgit mergeを合体させたもの
git pull
```
【form_with】formはform_withで統一しよう。　

##【ゴール】
form_withを理解する

##【メリット】
■　railsの推奨は「form_with」
■　そんなに難しくないので覚えておくべき


##【開発環境】
■ Mac OS catalina
■ Ruby on Rails (5.2.4.2)
■ Virtual Box:6.1
■ Vagrant: 2.2.7

##【違い】

###■form_for
モデルがある。
DBへ保存したいデータに対して使用

###■form_tag
モデルがない
POSTの処理を行い時に使用

###■form_with
両刀
上記2つの機能を兼ね備えた便利なメソッド

##【実際に使ってみた】

###モデルがある時
※例えば以下のようなモデル

モデル名：Book
カラム名①：name
カラム名②：title


```books/index.html.erb

<% form_with model:Book do |f| %> #model追記
  <%= f.text_field :name %>
  <%= f.text_area :text %>
  <%= f.submit %>
<% end %>
```


###モデルがない時
※モデルがないので指定したpathに情報が渡るだけに【POSTメソッドに】

```hoge.html.erb
<%= form_with url:hoge_path do |f| %>　#path名を追記
  <%= f.text_area :name %>
  <%= f.text_area :question %>
  <%= f.submit %>
<% end %>
```

以上。

**モデルがあれば、model名を指定
モデルがなければ,path名で指定**

私も使用することから逃げていましたが
めちゃくちゃ簡単だったので、よければ使ってみてください。
SASテクニック 処理時間の計測

# SASの処理時間を調べる
重いデータを扱うときなど、効率のよい処理を行うプログラムにした方がいい
※自分としては、通常時は、処理時間よりかは、だれが見てもわかるようなプログラムを心掛けている
※ただし1000万行とかあったらさすがに処理速度考えないとね...
※時間かかっているなら結果ビューアは出力抑制した方がいい

datetime関数で現在の時刻を取って来れる

```sas
%let START_TIME = %sysfunc( datetime() );
/*
処理時間を計測したいpgm
*/
%put 処理時間 = %sysevalf( %sysfunc( datetime() ) - &START_TIME. ); 
```
AdMobをAndroidに組み込んでみよう（全画面広告編）

AdMobをAndroifに組み込んでみようという事で覚書

「AdMobをAndroidに組み込んでみよう（環境設定編）」の続きです。
https://qiita.com/sanoh/items/79d04b021d18bdff0e06
■Step1.画面レイアウトを設定しよう
---
・activity_main.xmlをひらき「Button」を作成、名前を「ｍMyButton」とします。（レイアウトエディタの使い方は省きます）
![2020-06-16 (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/83cbb370-9d9c-d9ac-17b6-8d09d58576b7.png)
ボタンの配置はこのようにしておくとよいでしょう
![2020-06-16 (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/6e23624b-e439-2b80-f86a-07d5350e2338.png)
■Step2.プログラム
---
・MainActivityを編集します。

```kotlin
package com.toox.admob02

import com.google.android.gms.ads.*
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    private lateinit var mInterstitialAd: InterstitialAd
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mInterstitialAd = InterstitialAd(this)
        mInterstitialAd.adUnitId = "ca-app-pub-3940256099942544/1033173712"
        mInterstitialAd.loadAd(AdRequest.Builder().build())

        mMyButton.setOnClickListener {
            if (mInterstitialAd.isLoaded) {
                mInterstitialAd.show()
            }
        }
        mInterstitialAd.adListener = object : AdListener() {
            override fun onAdLoaded() {
            }
            override fun onAdFailedToLoad(errorCode: Int) {
            }
            override fun onAdOpened() {
            }
            override fun onAdClicked() {
            }
            override fun onAdLeftApplication() {
            }
            override fun onAdClosed() {
                mInterstitialAd.loadAd(AdRequest.Builder().build())
            }
        }
    }
}
```
![2020-06-16 (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/e945bc63-bb8e-6cfb-e44e-ef0ad028d489.png)
■Setp3.実行
---
プログラムを実行すると
![2020-06-16 (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/9d3401af-6638-ec76-3bbf-d2a741fb7f1b.png)
ボタンを押すと
![2020-06-16 (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/8c3cbcca-2c87-6411-c06b-babae8eee9e6.png)
となります
Railsでgemのapple_idを使ってSign in with Appleを実現し、AppleのJWKをキャッシュする

RailsアプリでSign in with Appleを行う場合、Sign in with Appleは結局の所OpenID Connectなので、id_tokenの検証をRailsで行う必要があります。
その検証はRubyであれば https://github.com/nov/apple_id このgemを使うとかんたんに行えます。

## apple_idを使ってid_tokenの検証をする

```rb
id_token = AppleID::IdToken.decode(id_token)
id_token.verify!(code: code)
```
こんな感じでid_tokenの検証を行えるのですが、verify!メソッドの中では何が行われているかと言うと、Appleが提供する公開鍵（JWK)をHTTPSで取得し、そのJWKを用いて署名検証をしています。
デフォルトではverifyするたびにAppleにHTTPSで通信をしていますが、この公開鍵はほとんど更新されないためキャッシュすることが可能で、サーバ実装としてもキャッシュしたほうが望ましいです。

gemのapple_idは最近1.0.0がリリースされ、このバージョンアップによってJWKを任意の場所にキャッシュすることが可能になりました。
本記事では、そのキャッシュのやり方を紹介します。

## キャッシュの方法

キャッシュのやり方は至ってかんたんで、引数を一つだけとるfetchメソッドを実装したクラスをAppleID::JWKS.cacheにセットするだけです。
fetchメソッドの中でyieldを呼び出すことで、JWKが取得できます。
例えばプロセスにキャッシュするのであれば以下のようなコードを書きます。

```rb
class ProcessCache
  def initialize
    @cache = {}
  end

  def fetch(cache_key)
    @cache[cache_key] ||= yield
  end
end

AppleID::JWKS.cache = ProcessCache.new
```

AppleID::JWKS.cacheはクラス変数として定義されるので、Cacheクラスの実装としてはインスタンス変数に代入すればプロセスにキャッシュされることになります。
プロセスではなく、ファイルやキャッシュサーバ、DBなどに保存したくなったとしても、同様にfetchメソッドを実装すれば差し替え可能で便利ですね。
Cacheクラスはappやlib以下に実装し、config/initializers/apple_id.rbなどを用意して、そこでAppleID::JWKS.cacheへの代入を行うなどすれば良いでしょう。
Gitの初期設定・ちょっと便利な設定

# 環境変数の設定

環境変数の設定場所は3箇所存在する
以下コマンドで確認できる

```shell
# Gitの全ての設定を確認する
git config --list

# システム全体
git config --system --list

# HOMEディレクトリ配下の.gitconfig  cd ~/.gitconfig
git config --global --list

# ローカルリポジトリ内の.git/config
git config --local --list

```

最低限必要な初期設定は以下の通り。

```shell
git config --global user.name {username}
git config --global user.email {emailaddress}
git config --global --list
```


# ちょっと便利な設定(Tab補完機能など)

Linuxシェル上での設定。

```shell
sudo mkdir -v /usr/local/etc/bash_completion.d

sudo wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-completion.bash -O /usr/local/etc/bash_completion.d/git-completion.bash

sudo chmod 755 /usr/local/etc/bash_completion.d/git-completion.bash

sudo wget https://raw.githubusercontent.com/git/git/master/contrib/completion/git-prompt.sh -O /usr/local/etc/bash_completion.d/git-prompt.sh

sudo chmod 755 /usr/local/etc/bash_completion.d/git-prompt.sh
```

Linuxの設定ファイルに記載しておくと良い設定。
※Terminalの起動シェルが.bashrcであることを事前に確認しておく。
(.zshrcの設定されている場合は変更が必要)

```shell
# bashrcファイルの編集
vim ~/.bashrc

# bashrcファイルに追記
# git settings
source /usr/local/etc/bash_completion.d/git-prompt.sh
source /usr/local/etc/bash_completion.d/git-completion.bash
GIT_PS1_SHOWDIRTYSTATE=true
GIT_PS1_SHOWSTASHSTATE=true
GIT_PS1_SHOWUNTRACKEDFILES=true
GIT_PS1_SHOWUPSTREAM="auto"
GIT_PS1_SHOWCOLORHINTS=true
export PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '

# 環境をリロード
source ~/.bashrc
```

# ちょっと便利な設定(エイリアスなど)

ローカルのgitプロジェクト配下に.gitconfigファイルを作成して設定。

```shell
# ファイルを作成
touch .gitconfig

# ファイルを編集
vim .gitconfig

# エイリアスの設定を追記
[alias]
	st = status
	co = checkout
	ri = rebase -i
	lv = log --graph --branches --tags --remotes --pretty=format:'%Cred%h%Creset - %s%C(yellow)%d%Creset %Cgreen(%cr:%cd) %C(bold blue)<%an>%Creset' --abbrev-commit --date=iso
	b = branch
	ba = branch -a
	fap = fetch --all --prune
	pff = pull --ff
```

※git lvの意味

HEAD -> (master, origin/master, origin/HEAD)
ローカルの現在地 -> (ローカルのmasterブランチ, 追跡中のローカルブランチ, gitHub上のデフォルトリモートブランチ)

# プッシュ時のユーザー名・パスワードの自動化

```shell
### ファイルとして認証情報を保存
# cloneもしくはpushすると、~/.git-credentials配下にパスワードファイルが生成される
git config --global credential.helper store

### キャッシュとして一定期間、認証情報を保存
# .git > configに情報が保存される。(--localでも問題ない。その場合は対象のプロジェクトのみに有効)
git config --global credential.helper cache
git config credential.helper 'cache --timeout=300'

### 登録した情報の削除
# ~/.gitconfigで登録した情報を削除
git config --global --unset credential.helper

# .git > localで登録した情報を削除
git config --local --unset credential.helper
```
vimで、特殊文字を文字列置換する

# vimで、特殊文字を文字列置換する
業務で、サーバーのログから特定の文字列だけ除去する作業が発生した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499375/6d1090a2-b0be-9c11-32cb-fc82e959180b.png)
今回削除したい文字列は、バックスラッシュ\ と、タブのセット。
現状１行あたりのログには、バックスラッシュ\ とタブ２つが入っている状況。
実現したいこととしては、下記のように全ての行に対してバックスラッシュ\ と、タブを１個削除したい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499375/58b34ce4-6cdd-8628-c687-3dcc0fce7f8b.png)

## 手順

### 【vimでの文字列置換】 
```
:%s/置換前の文字列/置換後の文字列/c
```
cオプションをつけることによって、置換するかどうか１回１回聞いてくれる。
全て一斉置換したい場合は、cオプションをつけない。

バックスラッシュ\ とタブのセットを変換前の文字列とすると、うまく置換できそう。
今回のケースを上記に当てはめて考えてみると、

```
:%s/{{バックスラッシュ/}}{{タブ}}/{{何も入れない}}/c
```

文字にするとこうなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499375/c01af615-9be4-fe1a-4e1b-6287dba6df33.png)

バックスラッシュ\ は、特殊文字となるため、特殊文字を条件にマッチさせたい場合は```\```でエスケープが必要になる。
エスケープが必要な特殊文字は、```^ $ . * [ ] / ~ \```となる。

vimの:を押すモード内でtabを表示するには、
tab+control　で出せます。**水色表示されれば成功**となります。



以上の点を踏まえると、```/```と```^I```のセットを削除するには、

```
:%s/\\^I//c
```
で削除が可能となる。

##　参考にさせていただいた記事
[正規表現の置換で特殊文字をエスケープする方法](https://howpon.com/21196)

[メタ文字の効果を消すエスケープ処理](https://vim.jp.net/stepuptonovice_others_regularexpression_escapemetacharacter.html)
接続元IPv4アドレスがAWS CloudFrontかを検証する方法

## はじめに

[Amazon CloudFront](https://aws.amazon.com/jp/cloudfront/)を使ってアクセスした際は接続元IPアドレスが「[X-Forwarded-For](https://ja.wikipedia.org/wiki/X-Forwarded-For)」ヘッダに格納されます。
このヘッダには複数IPアドレスが列挙されることがあり、先頭からひとつずつ検証する必要があります。
このクラスは「CloudFront IPアドレスに一致するか」を[AWS IPアドレスの範囲](https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-ip-ranges.html)に基づいて検証しています。

HTTP接続用に[Guzzle](http://docs.guzzlephp.org/en/stable/)を使っていますので、必要に応じて[インストール](http://docs.guzzlephp.org/en/stable/overview.html#installation)してください。

## 検証用クラス

```
<?php
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;

class AmazonAddress
{
    const AMAZON_IP_RANGES_URL = "https://ip-ranges.amazonaws.com/ip-ranges.json";

    /**
     * 対象IPv4アドレスがAWS CloudFrontのIPv4かを判定する
     * 
     * @param string $remote_ip 対象IPv4アドレス
     * @return bool 判定結果(true=CloudFront)
     */
    public static function isCloudFrontIPv4Address($remote_ip)
    {
        $prefixes = static::getAwsIPv4Addresses('CLOUDFRONT');
        foreach ($prefixes as $prefix) {
            list($accept_ip, $mask) = explode('/', $prefix);
            $accept_long = ip2long($accept_ip) >> (32 - $mask);
            $remote_long = ip2long($remote_ip) >> (32 - $mask);
            if ($accept_long == $remote_long) {
                return true;
            }
        }
        return false;
    }

    /**
     * AWS IPv4レンジリストを返却する
     * リクエストコストを考慮する必要がある場合は、リクエスト結果キャッシュなど対策すること
     * サービス名は以下を参照：
     *   https://docs.aws.amazon.com/ja_jp/general/latest/gr/aws-ip-ranges.html
     * 
     * @param string $service_name サービス名
     * @return array IPv4レンジリスト
     */
    public static function getAwsIPv4Addresses($service_name)
    {
        $ip_prefixes = [];
        $client = new Client();
        $response = $client->get(
            static::AMAZON_IP_RANGES_URL,
            [
                RequestOptions::ALLOW_REDIRECTS => false,
                RequestOptions::TIMEOUT => 10,
                RequestOptions::CONNECT_TIMEOUT => 1
            ]
        );
        // 200以外が返却された場合は空配列を返却する
        if ($response->getStatusCode() != 200) {
            return $ip_prefixes;
        }
        $response_body = (string)$response->getBody();
        $response_json = json_decode($response_body);
        // JSONパースに失敗した場合は空配列を返却する
        if (json_last_error() !== JSON_ERROR_NONE) {
            return $ip_prefixes;
        }
        foreach ($response_json->prefixes as $item) {
            // 対象サービスを限定
            if ($item->service != $service_name) {
                continue;
            }
            $ip_prefixes[] = $item->ip_prefix;
        }
        return $ip_prefixes;
    }
}
```

## 使い方

```
AmazonAddress::isCloudFrontIPv4Address('52.46.54.119') // → true
AmazonAddress::isCloudFrontIPv4Address('1.1.1.1') // → false
```
LaravelでGraphQLサーバーを作成できるLighthouseの解説(ディレクティブ)


前回（導入）　https://qiita.com/muu33/items/118949635416ed0a6dae
今回はLighthouseの特徴的な機能であるディレクティブの基本的な利用例。
命名規則を守ることでLaravelのEloquent Modelをスキーマと連携することができる。

# Lighthouse
公式:https://lighthouse-php.com/
LaravelでGraphQLを利用するためのライブラリ。

# 取得更新系
## all

全てのModelのコレクションを取得。

``` php
type Query {
  users: [User!]! @all
}
``` 

## find
指定したIDのModelを取得。

``` php
type Query {
  userById(id: ID! @eq): User @find
}
``` 

## first
指定された条件に一致する最初のModelを取得。

``` php
type Query {
  userByFirstName(name: String! @eq): User @first
}
```

## create
指定したレコードを作成。

``` php
type Mutation {
  createUser('name': String!): Post @create
}
```

## delete
指定したレコードを削除。
リスト型にすることで複数削除することが可能。

``` php
type Mutation {
  deleteUser(id: ID!): User @delete
}

type Mutation {
  deleteUser(id: [ID!]!): [User] @delete
}
```

## update
指定したレコードを指定したnameで更新。

``` php
type Mutation {
  updateUser(id: ID!, name: String): User @update
}
```

# リレーション
Eloquentの公式ドキュメント対応例
https://readouble.com/laravel/7.x/ja/eloquent-relationships.html
スキーマのフィールドとModelのメソッド名が同じ必要がある

## 1対1

``` php
// User Model
class User extends Model
{
    /**
     * ユーザーに関連する電話レコードを取得
     */
    public function phone()
    {
        return $this->hasOne('App\Phone');
    }
}

// Phone Model
class Phone extends Model
{
    /**
     * この電話を所有するUserを取得
     */
    public function user()
    {
        return $this->belongsTo('App\User');
    }
}
```


スキーマ

``` php
type Query {
  userById(id: ID! @eq): User @find
  phoneById(id: ID! @eq): Phone @find
}

type User {
	id: ID!
	name: String!
	phone: Phone! @hasOne 
}

type Phone {
	id: ID!
	number: String!
	user: User! @belongsTo
}
```

## １対多

``` php
// Post Model
class Post extends Model
{
    /**
     * ブログポストのコメントを取得
     */
    public function comments()
    {
        return $this->hasMany('App\Comment');
    }
}

// Comment Model
class Comment extends Model
{
    /**
     * このコメントを所有するポストを取得
     */
    public function post()
    {
        return $this->belongsTo('App\Post');
    }
}
```
スキーマ

``` php
type Query {
  postById(id: ID! @eq): Post @find
  commentById(id: ID! @eq): Comment @find
}

type Post {
	id: ID!
	name: String!
	comments: [Comment!]! @hasMany
}

type Comment {
	id: ID!
	message: String!
	post: Post! @belongsTo
}
```

## 多対多
``` php
// User Model
class User extends Model
{
    /**
     * userに所属する役目を取得
     */
    public function roles()
    {
        return $this->belongsToMany('App\Role');
    }
}

// Role Model
class Role extends Model
{
    /**
     * 役目を所有するユーザー
     */
    public function users()
    {
        return $this->belongsToMany('App\User');
    }
}
```

スキーマ

```php
type Query {
  userById(id: ID! @eq): User @find
  roleById(id: ID! @eq): Role @find
}

type User {
	id: ID!
	name: String!
	roles: [Role!]! @belongsToMany
}

type Role {
	id: ID!
	name: String!
	users: [User!]! @belongsToMany
}
```

# まとめ
LighthouseのディレクティブはEloquentと連携することでシンプルに実装することができてすごい（小並感）
まだまだ勉強中なので次回があったらもう少し踏み込むかも。
SASテクニック %putと%sysfuncで今日の日付などを出力

# %put 文字列;で文字列をログに書き出す
```sas
%put %sysfunc( mean( 1 , 2 , 3 ) );
%put %sysevalf( 50 * 12 + 200 + 250 );
```

など,ちょっとした計算やチェックなどに使える
%sysevalfや%sysfuncと併用するといろいろ計算できる


# 今日の日付

```sas
%put %sysfunc( date() , yymmddn8 );
%put %sysfunc( date() , yymmdd10 );
%put %sysfunc( datetime() , e8601dt );
```

# ログを外部ファイルへ書き出す

```sas
%let PROGRAM_DATE = %sysfunc( compress( %sysfunc( transtrn( %sysfunc( compress( %sysfunc( datetime() , e8601dt. ) , - ) ) , T , _ ) ) , : ) );
dm 'log; file "パス\プログラム名_&PROGRAM_DATE..txt" replace;';
```

でプログラムのログをテキストファイルに出力する
(ファイル名に実行した日時をいれている)

時間いらないなら(日付のみ)

```sas
%let PROGRAM_DATE = %sysfunc( date() , yymmddn8 );
```
AdMobをAndroidに組み込んでみよう（バナー広告編）

AdMobをAndroifに組み込んでみようという事で覚書

「AdMobをAndroidに組み込んでみよう（環境設定編）」の続きです。
https://qiita.com/sanoh/items/79d04b021d18bdff0e06
■Step1.画面のレイアウトを設定しよう
---
・activity_main.xmlを編集します。
　（最初画面は「Design」モードなので「Code」モードで編集してください）

```text:
androidx.constraintlayout.widget.ConstraintLayout
```
を

```text:
RelativeLayout
```
に変更した後にバナーを表示するタグを追加します。（ca-app-pub-***はデモ用なので本番は登録したものを）

```text:
    <com.google.android.gms.ads.AdView
        xmlns:ads="http://schemas.android.com/apk/res-auto"
        android:id="@+id/adView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        ads:adSize="BANNER"
        ads:adUnitId="ca-app-pub-3940256099942544/6300978111">
    </com.google.android.gms.ads.AdView>
```
![2020-06-16 (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/7ec1c8e5-503b-19d3-5461-ab4aacf16114.png)
■Setp2.プログラム
---
・MainActivityの編集

```kotlin:
package com.toox.admob01

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.google.android.gms.ads.*

class MainActivity : AppCompatActivity() {
    lateinit var mAdView : AdView
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        MobileAds.initialize(this) {}

        mAdView = findViewById(R.id.adView)
        val adRequest = AdRequest.Builder().build()
        mAdView.loadAd(adRequest)
        mAdView.adListener = object: AdListener() {
            override fun onAdLoaded() {
                //  広告読み込み
            }
            override fun onAdFailedToLoad(errorCode : Int) {
                //  広告読み込み失敗
            }
            override fun onAdOpened() {
                //  広告を開く
            }
            override fun onAdClicked() {
            }
            override fun onAdLeftApplication() {
                //  広告を開く
            }
            override fun onAdClosed() {
                //  広告から戻ってきた
            }
        }
    }
}
```
![2020-06-16 (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/3e229b6a-8a3b-f193-25af-dc9c0f42fbcd.png)
このように編集してください。
■Step3.実行
---
実行するとこんな感じで下にバナーが表示されます。
![2020-06-16 (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122121/782c6bd9-f800-4c66-66b3-8c79bd9066ca.png)
AndroidStudio:flutter(dart)で現在日時をマイクロ秒の粒度で表示


# やりたいこと

* AndroidStudio:flutter(dart)で、現在日時をマイクロ秒の粒度で表示する。

# 実装

### main.dart

```dart

import 'package:flutter/material.dart';
import 'dart:async';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _ClockState();
  }
}

class _ClockState extends State<MyHomePage> {
  String _time = '';
  @override
  void initState() {
    Timer.periodic(
      Duration(microseconds: 1000), // 1000000で1秒
      _onTimer,
    );
    super.initState();
  }

  void _onTimer(Timer timer) {
    setState(() => _time = DateTime.now().toString());
  }

  @override
  Widget build(BuildContext context) {
    return Text(
      _time,
      style: TextStyle(
          fontSize: 50.0,
          color: Colors.yellow,
          backgroundColor: Colors.blue
      ),
    );
  }
}

```

# 画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75451/e7b4ea1e-12a1-d9c1-8f8b-0a4ff9091867.png)
GitHubから共存関係の脆弱性を指摘されたときの対処法

#はじめに
GitHubからセキュリティ警告を受けて少し詰まったので備忘録として書いていきます。

#GitHubから脆弱性の指摘
<img width="975" alt="スクリーンショット 2020-06-16 15.41.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624775/e4fd0b9e-6807-416e-c24f-506c6751204f.png">
>**We found a potential security vulnerability in one of your dependencies.*
Only the owner of this repository can see this message.
`依存関係に潜在的なセキュリティ脆弱性が見つかりました。
このリポジトリの所有者だけがこのメッセージを見ることができます。`

右の[ View Dependabot alert ]を押してみると
<img width="770" alt="スクリーンショット 2020-06-16 15.49.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624775/e4ee5cf0-968b-8a60-ccea-2e4f6077d550.png">
どうやらセキュリティアラートが発生しているので詳細を確認してみます。




<img width="758" alt="スクリーンショット 2020-06-16 15.47.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624775/7f1dabb6-e6d6-b80c-b3dc-e4d4013878f0.png">
>**Dependabot cannot update to the required version**
View details about this error or learn more about Dependabot security updates.
`Dpendabotでは必要なバージョンにアップデートできません。
このエラーの詳細を表示するか、Dependabotのセキュリティ更新の詳細を確認してください。`

>**Remediation**
Upgrade **websocket-extensions** to version 0.1.4 or later. For example:
`websocket-extensionsを次のようにバージョン0.1.4以降にアップグレードする`
>>websocket-extensions@^0.1.4:
  version "0.1.4"

とあるので、websocket-extensionsのバージョンを0.1.4にしましょう。
#websocket-extensionsのバージョンアップ
websocket-extensionsとはソケット通信においてサーバー側が許可する拡張機能のことです。
ディレクトリ内のyarn.lockにあるこのコードを

```yarn.lock
websocket-extensions@>=0.1.1:
  version "0.1.3"
  resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" 
```
次のように書き換えます。

```yarn.lock
websocket-extensions@^0.1.4:
  version "0.1.4"
  resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
  integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
```

これでコミットしてプッシュすればGitHubからの脆弱性の指摘は無くなります。
Unity で「情報落ち」を再現してみる

# 情報落ち
浮動小数点数では、大きな数と小さな数の足し算を行うと結果として小さな数が足されなかったことが起きます。

```c#
 c = a + b // a:Large Number ,b:Small Number
 c == a // True  (??)
```

## Unity で再現してみる
[[Github] note-nota/InformationLoss](https://github.com/note-nota/InformationLoss)

![RotationCube.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93253/ccef6cb0-3fb5-8f6b-3bff-514d8c5b16a1.gif)

カメラの前に四角い箱があってクルクル回るシーン。
Cube には下記のスクリプトがアタッチされています。

```C#:RotaionError.cs
        void Update()
        {
            rotation_deg += speed_deg * Time.deltaTime;
            transform.rotation = Quaternion.Euler(0f, rotation_deg, 0f);
        }
```

これにより、y 軸周りの回転だけがスムーズに行われる…と思いきや、あるとき回転が止まる。
`speed_deg` を大きくするとまた動き出します。

## 説明してみる
先人の知恵を拝借して、少しばかり説明してみる。

* [浮動小数点数型と誤差](https://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html)
* [[Qiita] 浮動小数点って何?](https://qiita.com/angel_p_57/items/24078ba4aa5881805ab2)

浮動小数点型では「指数部」と「仮数部」に分けて実数を表現する。

```math
float\mbox{ の表す値}　＝　(-1)^{符号部} × 2^{指数部-127} × 1.\mbox{ 仮数部}
```

float であれば 4 バイト（32 ビット）であり、２のべき乗以下の数を表現する仮数部は 23 ビットの精度でしか表現できない。$2^{23} = 8,388,608$ なので、おおむね７桁程度の精度しかもっていないことになる。そのため、７桁以上の大きな開きがある足し算をするとこの仮数部では表現できない、という状況が発生します。これが、「情報落ち」。

今回の Unity の例では、`rotation_deg` が非常に大きな値 (1.677 e+07) のため、足す値 `speed_deg * Time.deltaTime` が $\mathcal{O}_{(1)}$ 程度で「足し算の結果、足した値が反映されていない！」状況になります。
powershell4でwindows8.1のテンポラリディレクトリの無駄ファイルを消す。

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

#１．注意点

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

必要な物
windows8.1 powershell_4.0
管理者権限
.ps1ファイルを実行できるようにしておく。

長所
cygwinやmsys2のインストールとメンテの必要がない。

欠点
1.linuxやMacと違いpowershellにdu -shコマンドがない。
2.powershellコンソールを管理者権限で実行するとホームディレクトリでなく
windows/sysytem32のディレクトリで始まる。
重大なセキュリティインシデントではないのか？
3.powershellの実行結果のログがとても汚い。

対象
[外部サイト、内田システムぷらんにんぐ（http://usp.mydns.jp/diet_c_drive.html）](http://usp.mydns.jp/diet_c_drive.html)
などを参考に対象となるディレクトリとファイルは次の通り。
/windows/temp
/Windows/Logs/cbs
/Users/(ユーザー名)/Appdata/Local/temp
のログやテンポラリファイルなど。
cabファイルはプログラム中では消さない。

注意
[外部サイト、Cドライブの空き容量不足の原因が、WindowsUpdateだった!(https://www.nedia.ne.jp/blog/tech/2017/11/28/10909) - 株式会社ネディア │ネットワークの明日を創る。](https://www.nedia.ne.jp/blog/tech/2017/11/28/10909)
（/Volumes/C/Windows/SoftwareDistribution/DataStore/）も消さない。
ここを消すのは最後の手段でプログラム中では消さない。


#２．ソース

UTF16、CRLFで作成のこと。
powershell起動後、ps1ファイルに保存した以下を実行。
数ヶ月の実績あり。

```
$OutputEncoding='utf-8'
Write-Host "さようなら文字化け"
echo "Hello Script!!"

ls
cd /windows/temp
ls
rm *.log
ls
Start-Sleep -s 3

cd /Windows/Logs/cbs
ls
rm *.log
ls
Start-Sleep -s 3
echo ""
echo ""
echo ""

cd /Users/xxxxxxxxx/Appdata/Local/temp
ls
rm *.log
rm *.dat
rm PhotoCache
rm chrome_url*
echo ""

ls
Start-Sleep -s 3
echo ""
echo ""
cd ~/
pwd

```

#３．参考リンク

[PowerShell のスクリプトが実行できない場合の対処方法 - Qiita](https://qiita.com/Targityen/items/3d2e0b5b0b7b04963750)


[日本語を含む Powershell スクリプトを UTF-8 で書く - Qiita]
(https://qiita.com/watahani/items/3cb6a9d00d5dc1e2ba73)

[Windows 10 の PowerShell で起動時にコマンドのエイリアスを設定 (Set-Alias) するには]
(https://mseeeen.msen.jp/windows-10-set-alias-automatically-in-powershell/)

（Set-Alias -name open -value explorerなど。）

以上
自分がよく使うGitHub, GitLabを使うときの開発の流れ(フロー)

# ⚠️このドキュメントっぽいものについて

+ もともとは弊社の社員向けにGitを用いた開発フローを説明するためのドキュメントの目的で作られています
+ このドキュメントで解説するフローはGitHubFlowなどから一部変更をしています
+ これが必ずしも正解であるとは限りません
+ GitHub(GitLab)が有効活用できればそれでOK　このドキュメントはその一例として見てください
+ Qiitaかどこかでこのフローの元の記事を見た覚えがありますが見つかりませんでした。もしご存じの方がいらしたらリンク付をしようと考えているのでコメントで教えて頂けると幸いです
+ 既に固定のフローをお持ちの方々はそのフローで大丈夫だと思います

# 📄tl;dr

1. 消化しないといけないタスク(バグ、新規実装項目)をIssueに網羅する。実装における質問や議論などもIssueに立てて書くと良き
2. 実際にコードを書く際は専用のbranchを切る。branch名は必ず`Add_DogeIcon#12`のような形にする。(Issueのだいたいの英訳+Issue番号)
3. 実装が終了したらpush→PR(MR)を発行する。プルリクの名前は割と適当でも良いと思う。ただし必ず概要文に該当Issueのリンクを貼る。
4. 必要に応じてコードチェックなどをして、最終的に通ればMergeする。

# 🤔なんでフローを制定するの？

`master`に直Pushしてコードを書いていくスタイルをしていると、以下の問題が発生することがある

+ (連休明け)**あれ先週の自分ってどこまでコード書いたっけ……**😅
+ あのひとが書いてるコードって自分のものに影響しそうな気がするんだけど確認できんのかな😫
+ タスクがテキストメッセージで書かれてて確認しようにも探しづらい🤮
+ 前に同じようなことをして実装した気がするけど、どうやってたっけ…覚えてないや🤕

これらは以下の要因に起因する

1. **タスク管理が集約できておらず**、テキストメッセージ内に散乱している
2. 自分が調べたりしたときに覚えておくための**Wikiのようなものが存在しない**
3. **他人の実装概要、内容が誰でも見られる状態になっていない**

これらの問題点はGitHub(GitLab)をフル活用した開発フローで解決できる。


# 👩‍💻🧑‍💻実際のフロー

サンプルに使ってるRepos: https://github.com/huequica/soundrop_OtogibaraEra

## 1. 💬タスクをIssueに網羅する。

![Issueを網羅していく](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320738/5abad3cb-131a-1264-c669-bd803c8ff5f0.png)

まずは消化しないといけないタスク、バグ報告などをリポジトリのIssueに書き出す。
これにより**タスクの集約、及びそれに対しての連絡や相談など**が可能になる。
ただし以下の点に気をつけること。

+ Issueは粒度を細かく、目的別で作る。たとえば「ここの文言の記述変更のIssueだけどめんどいから画像差し替えのIssueも同じでええやろw」はアウト

+ 実装においてAssignされたIssueページの使い方は**個人の自由**にする。メモ帳でもチラシ裏でも本人には重要だからIssueに書いている。ただし議論は別。

## 2. 🧑‍💻💦branchを切ってコードを書く

Issue内容をコードに実装する際は専用の命名規則を持った上でbranchを作り、そこでコードをいじる。
弊社の場合は `Add_DogeIcon#12` のようにIssue概要の英訳＋Issue番号(システム側が連番で振ってくる`#`から始まる番号)で命名をしている。

また、実装を途中で一旦保留にしたりする(連休が来たなど)場合はIssueに「ここまで書けた」という感じで一旦Issueページに加筆してbranchをpushしておくと再開するときにスムーズだと思う

## 3. 🚀コードが書けたらPushしてPullRequestを出す

まずはコードが書き終わったら一回休憩しよう。適当にコーラとかコーヒーとかでいい。
そうしたらリモートのReposにpushして、PRを出す
PRのタイトルは割と適当だけど概要が分かれば問題ではない。
ただしPRの説明文にIssueへのリンクを貼る。これは必ずしておいて頂きたい。
リンクを貼ることによって元のIssueにも「このPRにリンク付けされたぞ」というメッセージが出てくるので過去の実装を探すときに探しやすくなる。

![PRの提出　Issueへのリンクを絶対つけること](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320738/9a3e9579-a5ad-5766-c0bf-be46e6b43830.png)

あとは適宜コードのレビューをしたりして問題がなければMergeする。

-----

以上の3行程を繰り返すことによって快適かつ安全に開発ができる。Git使いたての人などには非常におすすめ。

# 👀他の恩恵

+ CIなどを使うことでPRが出た際にテストやLinterを走らせてコードが問題ないかを自動チェックさせることができる。
+ 上記に加え、Mergeしたら自動デプロイをさせるみたいなのもできる
+ Revert(Commitのロールバック)をする際、確実に該当のCommitが探しやすくなる
+ 若干草が盛れる(不純)

# 🕺まとめ

実際にやってみると大変なように見えてかなり快適です。特にタスク管理を集中させ、そのままコードを書いてPR提出までスムーズに移行することができるのでみなさんもやってみてください。
docker環境のLaravelでnpm run hotを動かしホットリロード

# Docker x Laravel x Vueを使ってHMRをやってみる

## webpack.mix.jsを編集

- プロキシはビルドインサーバのデフォルトポート8000を指定。
- ホストは0.0.0.0を指定。ホスト機からDockerコンテナにアクセスできるようにするため。

```js:webpack.mix.js
const mix = require('laravel-mix');
・・・・・・
・・・・・・
//// ここから ////
mix.webpackConfig({
  devServer: {
    host: '0.0.0.0',
    proxy: {
      '*': 'http://localhost:8000'
    }
  }
});
//// ここまで ////
・・・・・・
・・・・・・
```

## docker-compose.ymlを編集

ホストとコンテナのポートは8080を指定。webpack-dev-serverのデフォルトポート。
ホットリロードを利用するときはこちらのポートからアクセスする。

```yaml:docker-compose.yml
version: '3'
services:
  php:
    container_name: php
    build:
・・・・・・
・・・・・・
    #### ここから #####
    ports:
      - 8080:8080
    #### ここまで #####
    volumes:
・・・・・・
・・・・・・
#  nginxなどのWebサーバは使わず、ビルドインサーバを使うのでコメントアウト。
#  nginx:
#    image: nginx
#    container_name: nginx
#    ports:
#      - 80:80
```

## 動かしてみる

ターミナルを2つ用意する。

```bash:bash1
docker-compose up -d
# xxxxxはコンテナ名を指定。
docker-compose exec xxxxx php artisan serve
```

```bash:bash2
docker-compose exec xxxxx npm run hot
#  DONE  Compiled successfully と表示されるまで待つ
```

http://localhost:8080/ にアクセスしてホットリロードできました。
簡単に日記が公開できるアプリ「公開日記」をリリースした。

またまたwebアプリを公開したので紹介（宣伝）をして、今回の教訓？のようなものも紹介しようと思います。

https://public-diary.herokuapp.com/

### 使ったもの

言語・フレームワーク...いつものruby、そしてrailsです。
サーバー...heroku
独自ドメイン...いまは取得していません。

つかったgem 

```ruby:gemfile
gem 'devise'  #新規登録・ログイン
gem 'carrierwave'  #画像アップロード
gem 'kaminari'  #ページネーション
gem 'devise-i18n'  #devise 日本語化
gem 'devise-i18n-views'  #devise 日本語化
gem 'activeadmin'  #管理画面
gem 'rails-i18n'   #日本語化
gem 'rack-attack' #IPアドレス認証
```

このほかはほぼ初期のままです。そろそろdevise卒業したいですね。

##紹介
![公開日記top.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480294/a4eedac5-d415-6d33-3438-42e9f8a8bbeb.png)

水色をアクセントカラーにしたシンプルなデザインにしています。
ちなみにカラーコードは#82aaaaです。

![公開日記show.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480294/1991bda3-ef7d-6cbc-20c1-ea61afe4b71a.png)
showページですトップページと同じくとにかくシンプルにしています。

##今回学んだこと

###webpacker

今回はじめてwebpackerでboostapを導入しました。今までrails6でやってきたにもかかわらずassetsでやっていました。しかしそれのせいで本番環境構築のときすごく苦戦することとなりました。最初webpackerで導入したにもかかわらずrails assets:precompileばかりやって「反映されねえじゃん」っとずっと困っていました。
そもそもwebpackerが原因だとわかっていなかったので解決するまで無駄に時間がかかりました。
最終的にはこのサイトを見つけて解決しました。
[Webpacker使うなら最低限これだけは知っておいてほしいこと](https://qiita.com/chimame/items/8d3d6f4afea675cffa7d)

```
rails webpacker:compile RAILS_ENV=production
```

後今回、無駄にrails assets:precompileをやりすぎたのが原因なのか

```
rails assets:clobber
```

をしてassetsをリセットしないと動かない時がありました。いくらやっても本番環境でcssが反映されないという人はrails assets:clobberをやりリセットするのも一つの手かもしれません。

###管理画面

これは完全に好みですが
rails_admin
active_admin
Administrate
をつかってきて僕は一番、active_adminがいいなと思いました。初期のままでも十分使いやすくカスタマイズ性もそこそこいい。僕はこれから自作するとき以外は管理画面はactive_adminで行こうと思います。管理画面関係の記事は以下がおすすめです。

[rails管理画面系gem比較してみた](https://qiita.com/baban/items/f751fb05c4d2367878aa)
[Railsで最速で管理画面を作る！](https://qiita.com/enomotodev/items/5f6d9348207124a41bf9)

###heroku

僕はいままで最初からhobbyプランを契約していましたが最初はそんなに人が来ることはあまりないと思うので、最初は無料版でいいなと思いました。1000時間分もありますからね（1000時間じゃ足りなくなるくらいになってほしいな...）

##まとめ

今回は[togmarks](https://qiita.com/UTOG/items/89e2e6b9ad13e1cb5f7f)のときのものをそのまま流用するなどかなりの効率重視でやりましたが[togmarks](https://qiita.com/UTOG/items/89e2e6b9ad13e1cb5f7f)より時間がかかりました。次回からはwebpackerをちゃんと調べてから使おうと思います。読んでくれてありがとうございました。

https://public-diary.herokuapp.com/

~~あとはスマホがまだ未対応なのでなんとかします。~~
6月17日、スマホに対応しました。
Rubyにおけるハッシュとシンボルのまとめ

# ハッシュとシンボルの書き方まとめ
　学習していく中で、ハッシュの実装方法の違いが出てきたためまとめます。

``` test.rb

# キーが文字列の書き方
test{"subject" => "Math" , "score" => 60}
# キーがシンボルの書き方
test1{:subject => "Math" , :score => 60}
# キーがシンボルの書き方(省略系)
test2{subject: "Math" , score: 60}

# それぞれの出力方法
puts test["subject"]
puts test1[:subject]
puts test2[:subject]
```

実行すると、全て同じ値が出力されました。
学習するたびに、投稿していこうと思います。。。