OmniAICreator/Qiita-1.07M huggingface dataset:
初心者エンジニアが案件もらったときのTips

# はじめに
初めまして！織物産業が有名だった(最近盛り上がってきた)とある町のベンチャー企業で学生エンジニアをしているSoです。
ベンチャー企業で外注で案件をいただくようになって１年経ったので案件の取り組み方について備忘録として残します。
あくまで今段階の自分がどうやっているのかまとめたものですので、一般的には異なった方法が取られているということもあるかもしれません。

設計から行う案件はほぼなかったので、ここでは既存のサービスに対する機能追加・各種修正の案件を取り扱います。

## 0. 知っておいたほうがいい基礎知識
- Git
コミットやプッシュ、プルリクエストといった基本的なものに対して、その用語がどのような意味なのか知っておくと良いです。
よく使うもの
  - コミット/Commit
  - プッシュ/Push
  - プルリクエスト/Pull Request
  - ブランチ/Branch
  - マージ/Marge
  - プル/Pull
- ターミナル操作・コマンド
Lunixの操作だけでなく、Dockerを操作するためのコマンドなどがあります。
- データベースを触る場合はSQL文
データベースはSQLが用いられていることが多いため、基本的な構文については知っておいて損はないです。

## 1. プロジェクト・サービス把握
既にプロジェクトについてある程度理解している上で案件に取り組む場合は別にして、初めてのプロジェクトに取り組み場合はサービスについて理解することが重要です。

なぜならサービスを理解しないと実装がうまくいかなかったという実体験があったためです。

案件をもらい、具体的にしてほしい作業が決められていればそれをすればよいだけですが、実装内容にサービス特有の機能が含まれているとそれを理解する必要があります。

ざっくりとサービスを理解するためには、
- 誰に向けたサービスであるのか
- どのような機能を提供するのか

ということを調べます。
Wikiがある場合にはそこにサービス概要が書かれていることがあります。

## 2. 案件理解
サービスを理解したら、次に案件について理解します。

案件の内容が要件だけの場合、実際にどのように実装してほしいかのすり合わせが行われていない状態となっています。
「すり合わせ」というと会議でも開くのかというと、そうではなくSlackやGithubで担当者に確認・質問するだけでよいです。

例えば、案件に「〇〇のリマインド送信」であれば、リマインドは何日前に送るのかとか、どういう媒体でリマインドを送るのかということが実装においては分からないこととなってきます。

流石にこの程度は要件化されていることがほとんどですが、要件から実装・機能を考えたときに分からないことがあれば質問しておきます。

## 3. コード確認・実装前の確認
初めてのプロジェクト・システムの場合、ソースのファイル構造が分からないこともあります。

自分が実際にどこに案件の機能を実装するのか考えておきます。

はじめのうちはメモなどに残しておくと後から見直せて便利です。
実装を進めていくと、コードの構造や１つの実装に頭がいっぱいになるので実装全体の見通しを立てておくと後で「あれ？あとやることなんだっけ」となることが少なくなります。

## 4. 実装
ここまで準備ができたら、いよいよ実装です。
調べ物をして、実装の見通しも立てているので、基本的にこれに沿ってコードを組んでいけば実装はできるでしょう。

コードの書き方、見やすさ、綺麗さはセンスによるところもありますが、経験によるところが大きいので初めのうちはどんどん書いていきます。

見やすさで指摘される部分としては
- インデントが不適切
- 不要なコードをコメントアウトとして残す
- 深すぎるネスト
- あまりに多すぎるコメント

などです。

## 5. テスト
コードの実装が完了したら、実環境でテストを行います。
特に条件分岐をしているところなどはその条件を実環境で再現して、テストを行います。

最終的には利用者がサービスを使うわけなので、そこで念入りにテストしておけばイレギュラーが無ければ本番でもきちんと動くでしょう。

テストコードを書いても良いですが、初めのうちは実際にサービスを使ってみて動くかテストすることが自分は多かったです。テストコードを書けなかったということもありますが...笑

## 6. PR・レビュー
これで本番環境に上げて問題ないという段階までテストを行ったらコミット・プッシュしてPR（プルリクエスト）を出します。
PRを出すときに実装内容や自分で行ったテストを示しておけば担当者の方のチェックが楽になると思います。

PRを出し、担当者がコードレビューをしてくれれば、コードの二重チェックを行えます。

いきなりmainやmasterブランチといった本番環境にプッシュをしてしまうと、CI/CDツールのデプロイやビルドが失敗してしまったり、他の人の開発に影響を与えてしまうため、行いません。

# まとめ
自分が案件をもらっていつも行っている作業をまとめてみました。
まだまだ駆け出しなのでこれからもっとやりやすいやり方があるかもしれません。

Qiitaに初めて書きましたが、なかなかうまくまとめられず汚い文章ですいません！
読んでいただきありがとうございました。
折り返し前の入力確認、Eathernet(7)

謹賀新年：今年の目標
https://qiita.com/kaizen_nagoya/items/8ade72629f62c392576c

今年の半分を過ぎる前に、振り返りはじめ、残りの半分で何をするかを焦点を絞り直す。

# 入力
## C言語規格　最新版再読
これから

## C++言語規格　最新版再読
これから
## IEEE 802.3 再読
IEEE 802.3 Ethernet Working Group Published standard:
https://qiita.com/kaizen_nagoya/items/e68db6b73df668f892e6

IEEE 802.3 Working Group tools and resources
https://qiita.com/kaizen_nagoya/items/f3218f64ab8edd099e8e

IEEE 802.3 Ethernet 単語帳
https://qiita.com/kaizen_nagoya/items/4c31491f1883dd5ecfae

IEEE 802.3 & IEEE 802.11 単語比較
https://qiita.com/kaizen_nagoya/items/58901a172fde85acfc1d

ちなみに、前回企画はこちら。

（５月・お盆・お正月）休みに IEEE Ethernet規格(英文：個人利用無料)を読もう。１日１０００ページ目標。:英語(48)
https://qiita.com/kaizen_nagoya/items/e1a3155a950e799a17f5

## IEEE 802.11 再読
過去の資料は

IEEE 802.11を読む
kaizen_nagoya

IEEE 802 またはEthernet。無線網( Wi-Fi) 空中線(Antenna）(40)
https://qiita.com/kaizen_nagoya/items/7c52dd250097050398ca

IEEE 802。 無線網(Wi-Fi) 空中線(Antenna）(49)
https://qiita.com/kaizen_nagoya/items/8885e5c465b847f786d2

IEEE 802.11とWi-Fi。無線網（Wi-Fi）空中線(antenna)(58)
https://qiita.com/kaizen_nagoya/items/ab36dff0047902713fff

IEEE 802.11, Wi-Fi and C++.無線網（ Wi-Fi）空中線(antenna)(32)
https://qiita.com/kaizen_nagoya/items/a9b97d6031fec6c04ae6

Wi-Fi Related document。無線網（Wi-Fi）空中線(antenna)(29)
https://qiita.com/kaizen_nagoya/items/c484c9f21b9d6fc5481e

Wi-Fiとアンテナの特許を調べてみた。無線網(Wi-Fi)と空中線(antenna)(10)
https://qiita.com/kaizen_nagoya/items/c4a1475025005bdd2a33

## AUTOSAR 再読
AUTOSAR 21-11, 335文書読んだ。2022年6月初旬にFO, AP, CP全部到達。
https://qiita.com/kaizen_nagoya/items/4043e8414f850ce266a4

AUTOSAR文書の読み方（文書番号と発行年）2021-11 改訂版　
https://qiita.com/kaizen_nagoya/items/62f8329c67a4d95d7bcb

AUTOSAR Advent Calendar 2022を計画・記録。AUTOSAR(61)
https://qiita.com/kaizen_nagoya/items/262317aa25204159ad56

AUTOSAR教材作成３年計画, AUTOSAR(19)
https://qiita.com/kaizen_nagoya/items/84d8f1ecbbe7af7803af

AUTOSAR R21-11(0) 仕様ダウンロード一覧。単語帳。参考文献資料作成
https://qiita.com/kaizen_nagoya/items/9b3a1b9b8d1e8d7e288e

過去の記事

## Road Vehicle, Diagnostics
ISO Diagnostics Normative Reference一覧（表題順）
https://qiita.com/kaizen_nagoya/items/75d7e2276bbe1e2026d7

ISO Diagnostics 文献（Normative Reference and Bibliography）集め
https://qiita.com/kaizen_nagoya/items/535a0144a343df2c99df

ISO OSI 7層の実例：自動車用診断通信(diagnostics communication)
https://qiita.com/kaizen_nagoya/items/f52ad61f557f000de2d5

過去の記事

@kazuo_reveさんの「自動車の故障診断に関連するプログラマーになりたての方が参照するとよさそうな情報」の読み方
https://qiita.com/kaizen_nagoya/items/0c6b8373f93ce52def33

@kazuo_reve「AUTOSARのClassic PlatformとAdaptive PlatformにおけるDiagnosticsの違いを整理」で慌てて
https://qiita.com/kaizen_nagoya/items/d3ff6aba9b7402e8bde8

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
情報を取る時に気をつけること

## ネットにある情報は必ず間違っていると思って判断すること

## 情報に触れたらそれを自分の頭で考えること

## その情報に盲目的にならないこと

## 自分が今やろうとしていることを必ず把握しておくこと

## コピペをするだけがプログラマーではない

## 思ったこと
自分で考える訓練なんだな。
これから気をつけて2度とないようにしよう。
同じことを2度言ったかもしれない。
Workato：JavaScriptコネクターの制限事項

Workatoでは、Node.js 14をランタイムとするJavaScriptコネクターが用意されており、レシピ上の処理（アクション）としてJavaScriptを実行することができます。

また、npmやyarnで追加されたライブラリの利用にも対応しており、browserifyでライブラリを含めたJavaScriptファイルを1ファイルにまとめる（バンドルする）ことで、それらのライブラリを含めた状態で、自身で作成されたJavaScriptのコードをWorkato上で実行することができます。

バンドルする手間はありますが、任意のライブラリを追加して使用することができないRubyコネクターやPythonコネクターと比べた場合、JavaScriptコネクターは非常に自由度の高いコネクターであるといえます。しかし、Node.jsで動作するJavaScriptのコードが全て動くものではなく、いくつか制限事項があります。主な制限事項について、以下に示します。

# 1MBを超えるコードはTestやStartが行えない
JavaScriptコネクターで実行可能なコードは最大1MBまでとなっています。1MBを超えるコードがセットされた状態でTestを行おうとしたり、レシピを開始しようとすると、エラーが発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/87aa2e40-d400-d8d4-56b6-3f3fb68c70ee.png)

なお、1MBを超えるコードであってもminify（圧縮・軽量化）することで容量を減らせる可能性がありますので、minifyされていないコードである場合は、コードのminifyを検討ください。

また、minifyを行ってもコードが1MBに収まらない場合は、複数の処理（アクション）に分けるか、AWS Lambdaの利用を検討ください。

# 30秒を超える処理はInternal Errorとなる
JavaScriptコネクターには、最大30秒の実行時間の制限があります。この秒数を超えて処理が継続する場合、Internal Errorとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/69a4ab4d-4905-faab-6a0f-ecfeaf7b873b.png)　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/b4a9ef89-56eb-6918-13d1-c1e42f645380.png)

コードやロジックを見直しても30秒に収まらない重たい処理は、複数の処理（アクション）に分けるか、AWS Lambdaの利用を検討ください。

# シェルコマンドは実行できない
child_processモジュールの `exec` や `execSync` メソッドを利用した、シェルコマンドの実行はできません。実行しようとすると、次のようにエラーが発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64876/e866859d-388e-03d5-ca69-50b0fd2d80be.png)


# 参考
JavaScript（Workato Docs）
https://docs.workato.com/connectors/javascript.html
ブートストラップで平均値の区間推定値をt分布と比較する

# ブートストラップ

ブートストラップ法は、データを重複を許してリサンプルし統計量の計算をすることを繰り返す。こうして得られたデータをソートし両端の2.5%ずつを除いた区間をブートストラップ95%パーセンタイル区間と呼び、区間推定とする。

以下のmatlabコードは正規分布からサンプルしたデータの平均値について、ブートストラップ95%パーセンタイル区間を計算する。matlabの関数bootciによる推定値、スチューデントのt分布による計算値と比較を行う。

ブートストラップ法による区間推定値には揺らぎがかなりある。4000回ブートストラップ法を繰り返し推定値の度数分布を描いているがこの形も揺らぐ。このことから安全に推定を行うためには元データのサンプル数N、ブートストラップ標本数Kを適切に設定しなければならないことがわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2517058/6606e869-2416-1b23-8d4e-d243ad560fdf.png)


```matlab 
L = 4000; % L回ブートストラップ法を繰り返す。
K = 400; % ブートストラップ標本の大きさ。
N = 200; % 正規分布からN個のデータをサンプルする。
y = normrnd(1,1,N,1);

ci = zeros( 2, L );
ci2 = zeros( 2, L );

for j = 1:L

ci(:,j) = bootci( K, {@(x)(mean(x)), y}, 'Type','per' );

yy = zeros( 1, K );
for i = 1:K
    yy( i ) = mean( makeSample( y ) );  
end
ci2(:,j) = findci( yy );

end

ci3 = [ tinv( 0.025, N ) * sqrt( var( y ) / N ) + mean( y );
     tinv( 0.975, N ) * sqrt( var( y ) / N ) + mean( y )];

figure( 1 );
subplot( 2, 2, 1 );
histogram( ci(1,:), 20 );
hold on; plot( [ci3(1) ci3(1)], [0 600], 'LineWidth', 2 ); hold off;
title( 'bootciの区間下限(赤線はt分布の計算値)' );
subplot( 2, 2, 2 );
histogram( ci(2,:), 20 );
hold on; plot( [ci3(2) ci3(2)], [0 600], 'LineWidth', 2 ); hold off;
title( 'bootciの区間上限(赤線はt分布の計算値)' );
subplot( 2, 2, 3 );
histogram( ci2(1,:), 20 );
hold on; plot( [ci3(1) ci3(1)], [0 600], 'LineWidth', 2 ); hold off;
title( '区間下限(赤線はt分布の計算値)' );
subplot( 2, 2, 4 );
histogram( ci2(2,:), 20 );
hold on; plot( [ci3(2) ci3(2)], [0 600], 'LineWidth', 2 ); hold off;
title( '区間上限(赤線はt分布の計算値)' );

function yy = makeSample( y )
    yy = zeros( size( y ) );
    ii = zeros( size( y ) );
    imax = length( y );
    for i = 1:imax
        ii(i) = floor( rand*imax+1 );
        yy(i) = y( ii(i) );
    end
end

function ci = findci( yy )
    yy = sort( yy );
    li = ceil( length( yy ) * 0.025 );
    ui = ceil( length( yy ) * 0.975 );
    ci = [ yy( li ); yy(ui ) ];
end
```
ServiceNowにWebhookでデータ連携

## はじめに
みなさんこんにちは、三井情報株式会社です。
ServiceNowにWebhookでデータ連携する際の機能について紹介したいと思います。
Webhookに関しては、以前「[HMAC-SHA256を利用したwebhookメッセージの検証方法](https://qiita.com/sakuma-iho/items/b517cd261aadca85ca23)」というタイトルで投稿しているため、気になる方はご確認ください。

## Script REST APIs
今回紹介させていただく機能はServiceNowにてAPIを作成するための機能です。

ServiceNow Docs 「Scripted REST APIs」：
https://docs.servicenow.com/bundle/rome-application-development/page/integrate/custom-web-services/concept/c_CustomWebServices.html

Scripted REST APIsを使い、他のシステムからデータ受信し、ServiceNowのテーブルにレコードを作成する検証を実施しました。
本題に入る前に、ご存知の方が多いと思いますが、簡単にAPIやRESTAPIについて記載します。

**APIとは？**
・Application Programming Interfaceの略
・ソフトウェアやプログラム、Webサービスの間をつなぐインターフェースのこと

**REST APIとは？**
・RESTの設計原則に基づいて設計されたAPIのこと

**RESTの設計原則とは？**
・URI(HTTPのパス)が名詞形であること
・リソースの操作(作成/閲覧/変更/削除)をHTTPのメソッドにより指定できること
・レスポンス形式がJSONもしくはXMLであること

次に、具体的なServiceNowでの設定項目と検証結果について記載します。

## Script REST APIs 設定項目
①REST APIの作成
System Web Service > Scripted Web Services > Scripted REST APIs > New
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600023/c843eda3-125a-9e3c-74b3-737a1c854c5d.png)
Name：APIの名前
API ID：サービスのIDを設定

上記の項目を入力後Submitすると下記のような画面に遷移します。先ほど指定したIDからBase API pathが自動で作成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600023/5a096cb3-2ebe-19ec-33e7-c5c6882b98bc.png)
画面下部のタブResourcesのNewを押下すると下記の画面になります。
下記の画面で、作成したいAPIメソッドやスクリプトを作成します。

②Resourceの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600023/c938c913-8eb0-0704-bd54-26ac81b09111.png)

検証では、HTTP methodをPOSTにしました。スクリプトでは、POSTされたデータをカンマ区切りで成形し、指定したテーブルのレコードとして新規挿入するようにしてみました。

▼スクリプトイメージ

```javascript:Script Image
var data = request.body.dataString;
var now_GR = new GlideRecord("レコードを挿入したいTable名");
now_GR.initialize();
	
for (var i = 0; i < data.length; i++){

	var data_2 = data[i].split(",");

	if( data[i].indexOf("Hatena") > -1 ){
		now_GR.u_test_column1 = data_2[1];
	}else{
		now_GR.u_test_column2 = data_2[1];
	}
		
}
	
now_GR.insert();
```

## Script REST APIs 検証結果
想定通り、POSTで受けとったデータの情報を基に、レコードを作成することができました！！ 

## おわりに
いかがでしたでしょうか。標準で用意されているREST APIではできない処理を外部システムから起動する際に、是非利用してみてください。今回の検証では、認証を検証しませんでしたが、API実行時にACLでユーザー認証を実施できるようなので、今後は認証の検証にも挑戦したいです。
最後まで読んでいただき、ありがとうございました。
GoでGithub Actionを起動するときのoptional値の挙動

こういうのがあったとする

```yaml:hoge-workflow.yaml
name: hoge-workflow

on:
  workflow_dispatch:
    inputs:
      required_string:
        description: 必須な値
        type: string
        required: true
      optional_boolean:
        description: オプショナルな値
        type: boolean
        default: false
        required: false
```
これをgoから呼び出すとき、こんな感じにしたとする
```go
github.Actions.CreateWorkflowDispatchEventByFileName(ctx, "your-org", "your-repo", "hoge-workflow.yaml", github.CreateWorkflowDispatchEventRequest{
	Ref: branch,
	Inputs: map[string]interface{}{
		"required_value": "hoge",
	},
})
```
`optional_boolean`が必須ではないから渡さなくていいはずだという理屈はわかるが、これだと422エラーを受け取ることになる（え、optionalじゃないの？という気持ちはあるが...）

試しに明示的に`optional_boolean`へ`nil`を渡してみるも、今度は`For 'additionalProperties', nil is not a string.`というエラーで422エラーになる。

仕方ないのでoptionalだが値を渡すしかないっぽい。
```go
Inputs: map[string]interface{}{
	"required_value": "hoge",
    "optional_value": false,
},
```
これなら動きそうだが、実はこれもダメで正解はひとつしかない。

```go
Inputs: map[string]interface{}{
	"required_value": "hoge",
    "optional_value": "false",
},
```
はい、これで動きます。booleanの値を文字列にして渡すのが正解でした〜... わかるかこんなもん。

optionalなのにoptionalな挙動じゃないのも解せないわ
ゾンビ化した親プロセスをすべてのノードから一掃したい

# 状況
japanクラスターにjapan{01..10}.jpy.netという名の１０つのノードが存在するとする。
mpd.pyというプログラムが正常終了せずに実行可能状態のまま残ってしまうとき、演算能力が著しく低下することがわかった。
そのため、以下のスクリプトを定期実行することで解決した。

# コード
```shell
  #!/bin/sh
 
  NAME=`hostname`
  HOST=`echo $NAME|rev|cut -c 11-|rev`
  echo "## hostname ##"
  echo $HOST
  echo " "
  NODES=(`cat /etc/hosts|grep $HOST|awk '{print $2}'|rev|cut -c 9-|rev|grep $HOST`)
  
  echo "Kill mpd.py !!!"
  for j in ${NODES[@]}
  do
  echo " "
  echo " "
  echo "##   $j   ##"
  cnt=`/usr/bin/rsh $j ps aux --sort start_time |grep mpd.py|wc -l`
  echo "jobcount  $cnt"
  
  cpucnt=`/usr/bin/rsh $j grep processor /proc/cpuinfo | wc -l`
  echo "nodecpus $cpucnt"
  
  jobremain=`expr $cpucnt + $cpucnt`
  echo "jobremain count $jobremain"
  
  jobkillcnt=`expr $cnt - $jobremain`
  echo "killjob count $jobkillcnt"
  
  if [ $jobkillcnt -le 0 ]; then
    echo "no remaining processes"
    continue
  fi  
  
  killjoblist=(`/usr/bin/rsh $j ps aux --sort start_time|grep mpd.py|awk '{print $2}'|head -n $jobkillcnt`)
  flag=(`/usr/bin/rsh $j ps auxf --sort start_time|grep mpd.py|grep -v grep|head -n $jobkillcnt|fgrep "\_"`)

  if [ -n "$flag" ]; then
    echo "Exist child processes"
    continue
  fi  

  killcnt2=`expr $jobkillcnt + 1`
  flag2=(`/usr/bin/rsh $j ps auxf --sort start_time|grep mpd.py|grep -v grep|head -n $killcnt2|tail -n 1|fgrep "\_"`)

  if [ -n "$flag2" ]; then
    echo "Exist child processes"
    continue
  fi  

  for i in "${killjoblist[@]}"
  do  
    chk=`/usr/bin/rsh $j ps aux|grep mpd.py |grep $i`
    if [ -z "$chk" ]; then
      continue
    fi  
    /usr/bin/rsh $j kill $i
  done
  wait
  #TCPポート枯渇対策
  sleep 1m
done
```

# コード解説
## 例外処理
```
 killjoblist=(`/usr/bin/rsh $j ps aux --sort start_time|grep mpd.py|awk '{print $2}'|head -n $jobkillcnt`)
 
 flag=(`/usr/bin/rsh $j ps auxf --sort start_time|grep mpd.py|grep -v grep|head -n $jobkillcnt|fgrep "\_"`)
```
killjoblistはその名の通りkillする予定のPID配列です。flagは例外処理で消すリストの中に子プロセスが存在したらskipするようにしてあります。flag2は消すリストの最後尾が親プロセスで子が隠れているコーナーケースを考えた処理です。
<br>
## TCPポート枯渇対策
```
 slepp 1m
```
これをつけないとAll port usedみたいなエラーを吐いて異常終了します。1mの意味はCentOSではデフォルトのTCPのタイムアウト時間が1mだからです。

xargsを使ってkillするほうが楽かもしれないけど、rootでkillコマンドをスクリプトで実行する危険性を考えると、本当に消してもよいか丁寧にチェックしたいので用いませんでした。その他もっと良い書き方がありましたらコメントで教えてください。


# 定期実行したい

rootのcrontabに以下を追記してやればよい。日曜日と木曜日の午前０時に実行する設定
```
0 0 * * 0,4 /usr/local/bin/mpdestroy 2>> /var/log/mpdestory_log/log_mpdestory_error_$(date +\%Y\%m\%d).log
```
君はマジックナンバーファイルを知っているか

私は20年近くプログラマとして飯を食べてます。
Linuxの知識もプロとして恥ずかしくない程度には持ち合わせているつもりです。
そんな私にもまだまだ知らないことは多いもので、
つい昨日、また知らないことに出くわしました。
「マジックナンバーファイル」です。

マジックナンバーファイルの説明の前に、まず `file` コマンドの説明が必要です。
Linuxの `file` コマンドはファイルの種類を調べるときに使うコマンドで、こんな風に使います。

```
$ file some_text_file
some_text_file: ASCII text
```

上の例ではファイルの種類がアスキーテキストだと教えてくれています。

そして、 `file` コマンドがファイルの種類を特定するときに使うのがマジックナンバーファイルと呼ばれるものです。
マジックナンバーファイルは一般的には `/usr/share/file/magic` ディレクトリに置かれていることが多いです。
そのディレクトリの中を見ると様々な種類のマジックナンバーファイルが存在することがわかると思います。

このマジックナンバーファイル、中身はテキストファイルなので自分で作ることも可能です。
試しに今回は、37バイト目に `Ruby` という文字列を見つけたら `I love Ruby` と表示するマジックナンバーファイルを作ってみます。

`37ruby` というファイル名で以下の内容を持つファイルを作ります。
たった1行のファイルだが、これもれっきとしたマジックナンバーファイルです。

```
36    string    Ruby    "I love Ruby"
```

次に、動作確認用に、37バイト目に `Ruby` という文字列をもつファイル `sample.txt` を作ります。

```
123456789012345678901234567890123456Ruby1234
```

準備が整ったので試してみます。
以下の様に期待通りの出力が得られたら成功です。

```
$ file -m 37ruby sample.txt
ruby: "I love Ruby"
```

`-m` オプションによって自作のマジックナンバーファイルを認識させています。

マジックナンバーファイルについてはここに詳しいことが載ってます。（とても難解な書き方では有るが）
http://manpages.ubuntu.com/manpages/bionic/ja/man4/magic.4.html

ここまで書いておいて何ですが、この知識を使うことは多分一生無いと思います。
【MediaPipe】顔と手の座標データを正規化する(CSVファイル)

>MediaPipeで取得した座標データの統一化

手の座標の見本です。
![aa.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2702119/71f06798-30b7-baef-2a11-b9d786e6fd4f.jpeg)

顔の座標データの見本です。
![A6E6F3D5-545A-4FE2-9596-8D4F5942D2F1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2702119/40c316cf-f1d5-a6f8-6b74-b1b19ba32d16.jpeg)

2つのポイントを決定する。具体的にはP0(WRIST)を絶対動かない基準として設定する。それとP9(MIDDLE_FINGER_MCP)からP0までの距離が1になるように大きさを揃える。(P9以外でも大丈夫です。)
※z軸はあってもなくても大丈夫です。

必要な座標データです。
[・landmark_hand21_face4.csv](https://drive.google.com/drive/folders/10yytVY-0LR-fA7255X6oI5C1wO-Z05BV)

まず全体のソースコードです。
```python:standard_hand_face.py
import csv
import numpy as np
import math

with open("./result/landmark_hand21_face4.csv") as file_name:
    array = np.loadtxt(file_name, delimiter=",").ravel()
    #print(array)
    
x1 = array[::3]
y1 = array[1::3]
z1 = array[2::3]
    
x2 = []
y2 = []
z2 = []
for i in range(0,25):
    a = x1[i] - x1[0]
    x2.append(a)
    b = y1[i] - y1[0]
    y2.append(b)
    c = z1[i] - z1[0]
    z2.append(c)
#print(x2, y2, z2)

#k = math.sqrt((x2[1] - x2[0])**2 + (y2[1] - y2[0])**2)
k = math.sqrt((x2[1] - x2[0])**2 + (y2[1] - y2[0])**2 + (z2[1] - z2[0])**2)
print(k)

x = []
y = []
z = []
for i in range(24):
    d = x2[i] / k
    x.append(d)
    e = y2[i] / k
    y.append(e)
    f = z2[i] / k
    z.append(f)
#print(x, y, z)

"""
#xy = []
xy.extend(x)
xy.extend(y)
np.savetxt('./result/distance_hand_face.csv', xy, delimiter=',')
"""

xyz = [] 
xyz.extend(x)
xyz.extend(y)
xyz.extend(z)

np.savetxt('./result/distance_hand_face.csv', xyz, delimiter=',')
```

出力されたデータです。
72行あります。
[・distance_hand_face.csv](https://drive.google.com/drive/folders/10yytVY-0LR-fA7255X6oI5C1wO-Z05BV)
```distance_hand_face.csv
0
-0.75175872
..........
..........
-4.8186489
-4.467570984
```
>他の記事
・[MediaPipeで顔と手の座標データを出力する方法[CSV]](https://qiita.com/netineti512/items/cd642e130887a4636ec1)
・[[MediaPipe]手の座標データ(21個)と特定の顔の座標データ(4個)を結合させる。](https://qiita.com/netineti512/items/64bf47d5a61b474a55b5)
・[【MediaPipe】顔と手の座標データを正規化する(CSVファイル)](https://qiita.com/netineti512/items/34fb10a172588a71fe01)
BigQueryのschema json を bigquery.SchemaField に変換するpythonスクリプト

# 背景
pythonでBigQueryへのLoadJobConfigを書く場合、[bigquery.SchemaField](https://googleapis.dev/python/bigquery/latest/generated/google.cloud.bigquery.schema.SchemaField.html)が必要になる。

bigqueryのschemaは `bq show --schema --format=prettyjson` などで取得できるjson型で取り扱うことが多い。

json型のschema情報を bigquery.SchemaField　の形にconvertする機会が多いので、そのpythonスクリプトをメモしておく.


# 実装

```py
    # jsonからbigquery.SchemaFieldを生成する
    def _get_field_schema(self, field):
        name = field['name']
        field_type = field.get('type', 'STRING')
        mode = field.get('mode', 'NULLABLE')
        description = field.get('description', '')
        fields = field.get('fields', [])

        if fields:
            subschema = []
            for f in fields:
                fields_res = self._get_field_schema(f)
                subschema.append(fields_res)
        else:
            subschema = []

        field_schema = bigquery.SchemaField(
            name=name,
            field_type=field_type,
            mode=mode,
            description=description,
            fields=subschema
        )
        return field_schema

    # jsonを読み込んで bigquery.ScheaField の配列を返す
    def get_schema(self, path_to_schema_file):
        schema = []
        with open(path_to_schema_file, 'r') as f:
            jsonschema = json.load(f)

        for field in jsonschema:
            schema.append(self._get_field_schema(field))

        return schema
```


# 参照
https://stackoverflow.com/questions/36127537/json-table-schema-to-bigquery-tableschema-for-bigquerysink

https://cloud.google.com/python/docs/reference/bigquery/latest/google.cloud.bigquery.schema.SchemaField
WindowsのJDKでwildflyのwebアプリにアクセスできないとき 


執筆(2022/06/14)時点で日本語の情報が少ないため、メモしておきます。

#### 問題点
Windows上でOpenJDK 11.0.15やOracle Java 11.0.15などで、WildflyやJBossで、
ブラウザでWebアプリにアクセスすると、以下のエラーが出ました。

エラーの内容は↓です。
```sh
11:21:05,200 ERROR [io.undertow.request] (default task-1) UT005071: Undertow request failed HttpServerExchange{ GET /hoge}: java.io.IOError: java.io.FileNotFoundException: Invalid file path
 -- 
UT005071: Undertow request failed HttpServerExchange{ GET /mta-ui}: java.lang.NoClassDefFoundError: Could not initialize class org.xnio.channels.Channels
```

#### 状況
調べて見ると、既に対応して頂いてました。
https://bugs.openjdk.org/browse/JDK-8285445

正直、細かいところはわからないですが、NTFS Alternate Data Streamsの修正で、
意図せず、エラーになるケースがあったみたいです。。

Red Hatの記事にも同じ事象と回避策の記載がありました。
https://access.redhat.com/solutions/6953431

#### 回避策

JDKのバージョンをあげる　または JavaVMの起動オプションに以下を渡すことで回避可能でした。

```sh
set "JAVA_OPTS=%JAVA_OPTS% -Djdk.io.File.enableADS=true"
```
JDKのバージョンをあげるのが一番良いと思います。

#### ダメなバージョンと大丈夫なバージョン

・ダメだったバージョン
```sh
> java -version
java version "11.0.15" 2022-04-19 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.15+8-LTS-149)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.15+8-LTS-149, mixed mode)
```

・大丈夫だったバージョン
```sh
> java -version
java version "11.0.15.1" 2022-04-22 LTS
Java(TM) SE Runtime Environment 18.9 (build 11.0.15.1+2-LTS-10)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.15.1+2-LTS-10, mixed mode)
```
RFC 8707 - Resource Indicators for OAuth 2.0 メモ	


* OAuth2.0におけるクライアントがアクセス要求する保護リソースを認可サーバーに明示的に通知するための仕様についてメモする。

## Resource Parameter

* アクセスを要求するリソースを指定するパラメータ

### Authorization Request

* `resource`:アクセス対象の保護リソースのID

  * 省略時：認可サーバーはリソース特定なし、もしくは事前定義されたデフォルトのリソース値を使用してリクエストを処理する。
  * 認可サーバーは、クライアントに対してアクセス対象のリソースを指定することを要求し、`invalid_target`エラーでパラメーターを省略したリクエストを失敗させる場合もある。

* **インプリシットフロー認可リクエスト例**
  * <https://api.example.com/app/>へアクセスするためのアクセストークンを要求する例

  ```http
  GET /as/authorization.oauth2?response_type=token
      &client_id=example-client
      &state=XzZaJlcwYew1u0QBrRv_Gw
      &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
      &resource=https%3A%2F%2Fapi.example.com%2Fapp%2F HTTP/1.1
  Host: authorization-server.example.com
  ```


* **認可コードフロー認可リクエスト例**
  * リソース所有者のカレンダーと連絡へのアクセスを要求する例
  ```http
  GET /as/authorization.oauth2?response_type=code
          &client_id=s6BhdRkqt3
          &state=tNwzQ87pC6llebpmac_IDeeq-mCR2wLDYljHUZUAWuI
          &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
          &scope=calendar%20contacts
          &resource=https%3A%2F%2Fcal.example.com%2F
          &resource=https%3A%2F%2Fcontacts.example.com%2F HTTP/1.1
  Host: authorization-server.example.com
  ```

### Access Token Request

* クライアントがアクセストークンを使用する予定のターゲットサービスもしくは保護リソースを指定する。

* リクエスト例
  * `https://cal.example.com/`へのアクセスにアクセストークンを使用することを示す。
  ```http
  POST /as/token.oauth2 HTTP/1.1
  Host: authorization-server.example.com
  Authorization: Basic czZCaGRSa3F0Mzpoc3FFelFsVW9IQUU5cHg0RlNyNHlJ
  Content-Type: application/x-www-form-urlencoded
  
  grant_type=authorization_code
  &redirect_uri=https%3A%2F%2Fclient.example.org%2Fcb
  &code=10esc29BWC2qZB0acc9v8zAv9ltc2pko105tQauZ
  &resource=https%3A%2F%2Fcal.example.com%2F
  ```

  * レスポンス例

    ```json
     {
    	"access_token":"eyJhbGciOiJFUzI1NiIsImtpZCI6Ijc3In0.eyJpc3MiOiJodHRwOi8vYXV0aG9yaXphdGlvbi1zZXJ2ZXIuZXhhbXBsZS5jb20iLCJzdWIiOiJfX2JfYyIsImV4cCI6MTU4ODQyMDgwMCwic2NvcGUiOiJjYWxlbmRhciIsImF1ZCI6Imh0dHBzOi8vY2FsLmV4YW1wbGUuY29tLyJ9.nNWJ2dXSxaDRdMUKlzs-cYIj8MDoM6Gy7pf_sKrLGsAFf1C2bDhB60DQfW1DZL5npdko1_Mmk5sUfzkiQNVpYw",
        "token_type":"Bearer",
        "expires_in":3600,
        "refresh_token":"4LTC8lb0acc6Oy4esc1Nk9BWC0imAwH7kic16BDC2",
        "scope":"calendar"
     }
    ```

    



## セキュリティに関する考慮事項

* 他リソースへの不正アクセス対策
  *  `resource`パラメーターを指定することで、アクセストークンが使用される保護リソースを提示する。
* 別テナントが所有するリソースへの不正アクセス対策
  * パスコンポーネントなど、テナントを識別するURI部分を含むリソースURIを使用する。
* `resource`パラメータの単一指定
など


## 参考情報

* [RFC 8707 - Resource Indicators for OAuth 2.0 日本語訳](https://tex2e.github.io/rfc-translater/html/rfc8707.html)
RFC 7009 - OAuth 2.0 Token Revocation メモ


## Token Revocation 

* トークンが不要になったことを認可サーバーに通知し、認可サーバーはそのトークンに関連付けられたデータ（セッションデータなど）をクリーンアップすること。
  * このような処理により、エンドユーザーが認識していない特定クライアントへの有効な認可が残留する状況を回避できる

* 失効対象トークン
  * アクセストークン：推奨
  * リフレッシュトークン：必須

### Revocation Request
リクエスト例
```http
POST /revoke HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW

token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token
```

* `token` : 失効対象トークン。必須。
* `token_type_hint` : トークン種別。任意。
* 指定されたトークンがリフレッシュトークンで、認可サーバーがアクセストークンの失効をサポートしている場合、認可サーバーは、紐づけ関係に基づき全アクセストークンを無効にする必要がある。
* リクエストに渡されたトークンがアクセストークンの場合、認可サーバーはそれぞれのリフレッシュトークンも取り消す場合がある。

### Revocation Response

* 失効に成功した場合、200応答を返却する。
* エラーコード`unsupported_token_type`
  * 認可サーバーが、提示されたトークンタイプの取り消しをサポートしていない

## セキュリティに関する考慮事項

* 認可サーバーがアクセストークンの取り消しをサポートしていない場合、対応するリフレッシュトークンが取り消されても、アクセストークンはすぐに無効にはならないことがある。
* DoS攻撃
  * 無効なトークンを指定された場合にも、データベース参照を行うような場合。
* トークンの推測
  * 潜在的なトークン文字列に対して失効リクエストを行うことで、当該エンドポイントで有効なトークンを推測されること。
* トークン・クレデンシャルの詐取
  * 偽造Revocationエンドポイントを利用し、有効なセキュリティトークンを取得されること。

## 参考情報

* [RFC 7009 - OAuth 2.0 Token Revocation 日本語訳](https://tex2e.github.io/rfc-translater/html/rfc7009.html)
データベースの現在値を元にフォームの入力値をチェックする方法

フォームに入力された値をチェックするときに、すでにDBに保存済みの値と比較する方法がわからなかったのでメモ。

    self.instance.モデルフィールド名

で取得できる。

models.py

    class Order(models.Model):
        quantity = models.IntegerField(verbose_name='注文数')

forms.py

    def clean_quantity(self):
        new_val = self.cleaned_data['quantity']
        if new_val > self.instance.quantity + 10:
            raise forms.ValidationError("注文数の追加は10までです")
        return new_val
SPLIT関数を使用して / で区切られた値を抽出する

SQLを使い始めてまだ四ヶ月くらいの新米エンジニアです。
最近Treasure Dataを使用することが多いのですが、こうクエリを記載すれば良いのか！と思ったことを備忘録として残します。


# 「/」で区切られた値が数パターンある場合
例えば以下の表のように、 １つのカラムに「/」が1個、2個、または3個というデータがあり、
|test    |
|:-------|
|FURNITURE/KITCHEN|
|FURNITURE/BEDROOM/TABLE|


この中から「/」の一個目の値、2個目の値をそれぞれ別カラムで抽出したい場合は以下のように記載できます。
```ruby
CASE 
  WHEN (LENGTH(test) - LENGTH(REPLACE(test, '/', ''))) / LENGTH('/') = 1 THEN SPLIT(test, '/')[1]
  WHEN (LENGTH(test) - LENGTH(REPLACE(test, '/', ''))) / LENGTH('/') = 2 THEN SPLIT(test, '/')[2]
END AS split1
```
```ruby
CASE 
  WHEN (LENGTH(test) - LENGTH(REPLACE(test, '/', ''))) / LENGTH('/') = 1 THEN SPLIT(test, '/')[1]
  WHEN (LENGTH(test) - LENGTH(REPLACE(test, '/', ''))) / LENGTH('/') = 2 THEN SPLIT(test, '/')[2]
END AS split2
```


抽出結果は下記になります。
|test                   |split1   |split2 |
|:----------------------|:--------|:------|
|FURNITURE/KITCHEN      |FURNITURE|KITCHEN|
|FURNITURE/KITCHEN/CHAIR|FURNITURE|BEDROOM|
業務日という概念

## これはなんですか
ギョーカイでいうところの「業務日」とはなにか、また、その概念が実装されている目的。

この記事で書かれている時刻はすべて 24 時間表記です。

## 業務日の謎に迫る
業務日とは本番運用されている環境下では、通常は「今日」のことである。
今日の日付は2022年6月14日です。

ただ、２４時を超えてもデイリーバッチが走るまでは・・・
たとえば、ソシャゲのログボ配ったりする時や、自分が寝て起きるまでが今日と認識してるあまりよろしくない生活をしている場合など、
概念的に「昨日」を「今日」として処理したほうが都合がよいものがもろもろあります。

図に書いてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/570665/c8b41a26-3583-77e3-3c22-eaf951ba07ed.png)

なんか寝てる時間とか不規則そうですねこの人。
(呼符はきちんともらいましょう）

あるシステムの場合、たとえば2022年6月15日01時であっても、04時にバッチが走ったことを条件に業務日が切り替わるのであれば、その業務システム上で 2022年6月14日は、2022年6月1４日04時から、2022年6月15日04時(正確には03時59分59秒なのかもしれないけど、概念なのでざっくりでよいもよう、もしかしたら04時を過ぎてもバッチが完了するまでは「昨日」かもしれない）

これを一律ファイルやDBに格納して管理していることを「業務日の概念が実装されている状態」と言う。　いや、なんと呼んでもいいんだけど。

で、これなにが嬉しいかと言うと、開発工程でデイリーバッチが動いたあとの状態などを確認するときに便利だったり、１ヶ月後の処理をすぐサーバのクロックを書き換えることなく実行できたりするのに便利なのです。

また、有益かどうかは存じ上げませんが、タイムゾーンの概念を無視することもできると思いますが、実際にそれをやってるシステムにはお目にかかったことがないです。きっと世界のどこかにあるのでしょう。

私が見てきた中で、５つくらいのシステムはこの概念を実装していたので、割とポピュラーなやり口なのかと思います。

おわり。
Elastic Beanstalkの廃止予定（リタイアメント）プラットフォームっていつまで使えるの？

# 0. 序文

みんな大好きAWSのElastic Beanstalkですが、本当にみんな大好きならもっと情報があるはずだからこんな記事書くまでもないんじゃないの？（挨拶）

とは言え、全く日本語の記事が無いかと言えばそんなこともないので少数ながらも利用者はいるだろうし、同じような疑問を持ってる人もいるかもしれないのでそんな人のお役に立てれば。

さて、[Amazon Linux 1を利用した各プラットフォームがもうすぐリタイアを予定](https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/platforms-support-policy.html#platforms-support-policy.depracation)していますが、リタイアを迎えたプラットフォームはどうなるのか、またそれを利用した環境はどうなるのか、という点についてはちょっと分かりにくい書き方になっています。
それをざっくりと説明してみます。

# 1. リタイアを迎えたら

まずここですね。
リタイアを迎えたらどうなるのか。

## 1-1. 新規EB環境の作成ができなくなる

リタイアを迎えたプラットフォームを利用した新規環境の作成ができなくなります。
また「リタイアを迎えたプラットフォームを利用している既存の環境」をクローンを作成する際も「環境を新規に作成する」ことになるので、そちらも行えなくなります。

## 1-2. 当該プラットフォームへのセキュリティ更新やサポートが終了する

OSやミドルウェア等のセキュリティ更新等が終了し、更新されなくなります。
また、サポートプランが何であれ、Beanstalkとしてのサポートは行われなくなり[^support]ます。

# 2. リタイア日から90日間

次がここ。
リタイアを迎えてからの90日間、移行猶予が与えられます。

## 2-1. 既存のEB環境は利用し続けられる

ここでの「利用し続けられる」というのはElastic Beanstalkが利用している各種リソース（EC2等）を「Beanstalkの持ち物のまま」利用を継続できるという意味になります。
`EB CLI`を使用したり、`BeanstalkのWebコンソール`から実行したり、今まで通り利用することができます。

ただし、リタイアを迎えた環境なのでセキュリティ更新等が行われないことには留意する必要があります。

この90日間は主に「サポートされるプラットフォームへの乗り換え猶予期間」としてのみ考えておくべきかもしれません。

# 3. リタイア日から90日が経過

最後がここ。
完全なる終焉です。

## 3-1. 各種リソースがBeanstalk管理下から外れる

Beanstalkから作成された各種リソースが削除されることはない（＝アプリケーションは動き続ける）ものの、Beanstalkというものとは一切の関わりがなくなります。
例えばアプリケーションのデプロイにCodePipelineを使っていた場合はそれが利用できなくなりますし、`EB CLI`や`BeanstalkのWebコンソール`からも操作・参照できなくなり、Beanstalkを使用していたメリットのすべてがなくなります。

個人的にはこの段階での最大のデメリット[^maximum]は「環境の終了」ができなくなることだと思っています。
サポートされるプラットフォームへの乗り換えをこのタイミングでやったとしても、既存リソースの削除時にElastic Beanstalkが生成したリソースをすべて自分の手で削除する必要があります。

[^support]: Beanstalkで使用している個別のリソースについての問題（例えばEC2）としては受け付けてもらえる
[^maximum]: 本当の「最大のデメリット」は「リタイアを迎えた環境なのでセキュリティ更新等が行われない」ですが・・・
[Android] 丸角Buttonを簡単に作ってみる

# はじめに
丸ボタンを作るときに、XMLを自分で作成してStyleを適応する方法などいろいろとあり、悩むときもあると思います。
そんな中、結構前になりますが、スタイルがparent="Theme.MaterialComponents.DayNight.DarkActionBar"に変えたことにより、より便利なボタンの設定項目を使えるようになったらしい。
それを使ってみようと思う。

<b>Styleを自分で作らなくて見やすいコードを書こう！！</b>



# 丸角ボタンを作る
![キャプチャ1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1209385/a074d15f-f66b-6b7a-cafc-761d0535a14f.png)

### 内容

```xml

<Button
        android:id="@+id/tellButton1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"

        android:backgroundTint="#FCDDEC"

        android:text="TELL"
        android:textColor="#EF5DA8"
        android:textSize="20sp"

        app:cornerRadius="25dp"
        app:strokeColor="#EF5DA8"
        app:strokeWidth="2dp"

        app:icon="@android:drawable/stat_sys_phone_call"
        app:iconTint="#EF5DA8"

        app:layout_constraintBottom_toTopOf="@+id/tellButton3"
        app:layout_constraintEnd_toStartOf="@+id/tellButton2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
         />

```

### 分解して見てみる
コードの部分にコメントをかけなかったので下で解説
##### 最初の部分

・IDの指定
```
android:id="@+id/tellButton1"
```
・その要素の大きさを指定
```
android:layout_width="wrap_content"
android:layout_height="wrap_content"
```

##### 背景のいろ
・背景の色を指定　※今回は薄ピンクを指定
```
android:backgroundTint="#FCDDEC"
```

##### 文字の設定
・表示する文字の内容の指定
```
android:text="TELL"
```
・文字の色の指定　※今回は濃いピンクを指定
```
android:textColor="#EF5DA8"
```
・文字の大きさを指定
```
android:textSize="20sp"
```

##### アイコンをつける
・アイコンの指定　※今回は自分が<b>インターネットから落とした</b>電話マークを指定
```
app:icon="@android:drawable/stat_sys_phone_call"
```
・アイコンの色を指定 ※今回は濃いピンクで設定
```
app:iconTint="#EF5DA8"
```

##### ConstrainLayoutにおける設定
・この要素をどこと結びついているかを教えるための部分。
```
app:layout_constraintBottom_toTopOf="@+id/tellButton3"
app:layout_constraintEnd_toStartOf="@+id/tellButton2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
```
TD Presto関数 #1（MAX BY, SPLIT）

備忘録としてTreasue Dataで使用したPretoの関数を記載しておきます。

# MAX BY(A, B)
B列が最新の値の場合のA列を反映する
```ruby
（例）最新timeのguid列を反映
MAX BY(guid, time) as time
```

# SPLIT(string, '記号')[n]
'記号'で区切られているstring列の値から、n番目の値を反映する。
例えばcategoryというカラムに以下のように/で区切られた値がある場合
|category                   |
|:--------------------------|
|FURNITURE/KITCHEN/CHAIR|

```ruby
SPLIT(category, '/')[2] as test
```
抽出結果は以下のようになります。
|SPLIT                   |
|:--------------------------|
|KITCHEN|


※ちなみに数字を[]で指定しないと結果は以下のようになります。
|SPLIT(数字指定しない場合)|
|:--------------------------|
|["FURNITURE","KITCHEN","CHAIR"]|
Rails6 Heroku デプロイで発生したエラーとその対処法

RubyとRailsの最新の安定版（2022年6月14日現在での最新の安定版）でherokuへのデプロイを行なった。
その際に発生したエラーをまとめてみました。

## 環境
- mac OS
- ruby 3.1.2 （2022年6月14日現在での最新の安定版）
- rails 6.1.6 （2022年6月14日現在での最新の安定版）
- node 16.13.0 （12以上にしといたほうがいいらしい）
- yarn 1.22.19　（1以上にしといたほうがいいらしい）
## 発生したエラー

### ****Failed to install gems via Bundler****

このエラーは`git push heroku main`コマンドを実行したときに発生。
下記記事の通りでうまくいく。
(https://qiita.com/m6mmsf/items/fb8a8672df98bdb59c9c)

### you don't have net-smtp installed in your application. please add it to your gemfile and run bundle install

このエラーはデプロイが成功した後、`heroku run rails db:migrate`を実行すると発生する。
エラー文の通りに必要なgemをインストールすると治るが、追加で必要なgemがある。

```
gem 'net-smtp'
# 下の二つも追加したほうがいいらしい
gem 'net-imap'
gem 'net-pop'
```

上記のように編集しbundle install を実行する。
#### 注意点
アプリケーションに変更を加えた場合は、
- git add
- git commit
- git push heroku ブランチ名

の3つを実行しないと本番環境に変更が反映されないので注意。
このエラーに関しては詳しくは下記記事。
(https://qiita.com/jnchito/items/4ef331281f0050428716)
ESP32で再接続する方法（認証Webサイトの場合）

現在ESP32でWeb認証機能を設けたシステムを構築しているんだが、
APがなにかの問題で再起動した場合、
WiFiに再接続する機能を設けていなかったのでその機能をつけた。

#### そこで問題が発生だ！！

```c
void loop() {
  //接続が切れた場合の処理
  if((WiFi.status() != WL_CONNECTED)) {
    chkCount += 1 ;       // ｶｳﾝﾄ
    if (chkCount > 10) {  // 10回目(5秒) で切断/再接続
      ESP.restart() ;     // 再起動
    }
  }else{
      chkCount = 0;
  }
  delay(500);
}
```
以上の処理で5秒間接続が行われない場合は、ESPをリスタートするようにしたのだが、
この機能を追加すると何故かWeb認証機能で正しいID、PASSを入力しても
認証ができない。

#### なぜだ？！

調べてみたら認証機能を設けている場合「delay(500);」を入れると正常に
認証ができないみたい。。。


しょうがないので以下の方法で接続が切れたイベントを取得して、
ESPをリスタートかけ、APに再接続するようにした。

```c

// ■■■■■■■■■
//　WiFiが切断された時の処理
// ■■■■■■■■■

void WiFiStationDisconnected(WiFiEvent_t event, WiFiEventInfo_t info){
  ESP.restart() ;     // 再起動
}

void setup(){
    //WiFi設定
    IPAddress ip(192,168,0,99);
    IPAddress gateway(255,255,255,0);
    IPAddress netmask(192.168.0.1);
    
    WiFi.mode(WIFI_STA);              //ルータ接続モード
    WiFi.config(ip, gateway,netmask); //ルータ接続設定
    WiFi.disconnect(true,true);       //既に接続が合った場合、解除
    delay(1000);
    WiFi.onEvent(WiFiStationDisconnected, SYSTEM_EVENT_STA_DISCONNECTED); //接続解除イベント
    WiFi.begin(buf.ssid, buf.pass);   //ルータ接続処理
    int lpcnt=0;
    int lpcnt2=0;
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);                            // 0.5秒毎にチェック
      lpcnt += 1 ;                           // ｶｳﾝﾄ
      if (lpcnt > 10) {                      // 10回目(5秒) で切断/再接続
        WiFi.disconnect(true,true) ;         // 
        WiFi.begin(buf.ssid, buf.pass); 
        lpcnt = 0 ;                          //
        lpcnt2 += 1 ;                        // 再接続の回数をカウント
      }                                      //
      if (lpcnt2 > 3) {                      // 3回 接続できなければ、
        ESP.restart() ;                      // 再起動
      }                                      //
      Serial.print(".");                     //
    }
  
    // Print ESP Local IP Address
    Serial.println(WiFi.localIP());

}

void loop() {

}
```
しかし、なぜ「delay(500);」がloopのところにあったら正常に動作できないかは、
謎のままです。。。
Shpify CLI で開発者ストアの shopify theme pull ができない

Shopify Store 2.0 に対応するため Shopify ThemeKit から Shopify CLI に移行したのですが、テーマのダウンロード（`shopify theme pull`）で下記のようなエラー（警告）が出てテーマをダウンロードできず時間を取られたため、解決策を残します。
![shopify_CLI_theme_pull_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406761/0698ef6c-4f17-99d8-8b2b-8bf5b547b7dd.png)

> You can't use Shopify CLI with development stores if you only have Partner staff member access. If you want to use Shopify CLI to work on a development store, then you should be the store owner or create a staff account on the store.
If you're the store owner, then you need to log in to the store directly using the store URL at least once (for example, using xxx.myshopify.com.myshopify.com/admin) before you log in using Shopify CLI. Logging in to the Shopify admin directly connects the development store with your Shopify login.

## 原因は？
> You can't use Shopify CLI with development stores if you only have Partner staff member access. If you want to use Shopify CLI to work on a development store, then you should be the store owner or create a staff account on the store.
訳：パートナースタッフのアクセス権しかない場合、開発用ストアでShopify CLIを使用することはできません。開発店舗でShopify CLIを使用したい場合は、店舗オーナーになるか、店舗にスタッフアカウントを作成する必要があります。

とのことなので、どうやら自分で立ち上げた開発者ストアであるにも関わらず、自身がオーナーとして認識されていないようです。
[設定] -> [ユーザーと権限] を確認してみると、所有者は「Admin \<ストア名\>」となっています。

以上のことより、パートナーアカウント（開発者アカウント）と開発ストアがうまく紐づいておらず、Shopify CLI で上記のようなエラー（警告）が出ていると考察します。


## 解決策
* パートナーアカウント（開発者アカウント）及び Shopify CLI から一度ログアウトします。
* 普段は [Shopify Partners](https://www.shopify.com/partners) のページからログインしてストア管理画面に飛んでいると思いますが、[一般アカウントのログインページ](https://www.shopify.com/)からパートナーアカウントのオーナーアカウントでログインします。
* URLを直打ちで開発ストアへ入ります。(例：https://xxx.myshopify.com/admin)

上記の手順を踏むと、開発ストアの所有者がパートナーアカウント（のオーナーアカウント）に変更されていると思います。
この状態で再度 Shopify CLI でログインして `shopify theme pull` を実行すると問題なくダウンロードすることができました。



## 追記
github にこの件に関する issue がありました。

https://github.com/Shopify/shopify-cli/issues/1361
カンタンCSSでいろいろな上下中央ぞろえ

# 上下中央ぞろえはどんな時に使う？
ログイン画面など、ページな中で、強調したいものが一つ決まっている時。

# いろいろな実装方法

### 共通のhtml
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>上下中央ぞろえ</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
	<div class="chuuou">この要素が中央になる</div>
</body>
</html>
```
### 1. 親要素をdisplay:flexにすることで、子要素を中央ぞろえ
```css:style.css
body {
    min-height:100vh;//これは、bodyの高さを画面いっぱいに引き伸ばしている
    margin:0;
    padding:0;
    display:flex;
    justify-content:center;
    align-items:center;
}
```
### 2. 子要素のtop,left
これは、子要素の大きさが決まっている時だけ使える。
ここでは、子要素横縦300px幅500pxにしている。
```css:style.css
body {
    min-height:100vh;
    position:relative;
    /* 実は、bodyにこれをする必要はないが、親要素がbody以外の時にも対応できるように書いておく */
}
.chuuou {
    width:500px;
    height:300px;
    position:absolute;
    top: calc(50% - ( 300px / 2 ));/*50%は行き過ぎてしまうので、要素の縦の半分の長さ戻るようにする。*/
    left: calc(50% - ( 500px / 2 ));
    background-color:blue;/* 幅が設定されていることが分かりやすいように色を付けた */
}
```
### 3. 子要素のtop,leftとtransform
これは、子要素の大きさが決まっていなくても使える。
例えば、子要素がdisplay:inline-blockの時とか便利。
これは、https://qiita.com/yukinaka/items/1da62535553b62cc50aa
から引用。
cssで上下中央したいときに、この方のqiitaから、何度もコピペさせてもらっていた。

ここでは、子要素をinline-blockにしている。
これが結構実用性高そう。
もちろん、子要素の中に、複数の要素を入れても大丈夫。
```css:style.css
body {
    min-height:100vh;
    position:relative;
    /* 実は、bodyにこれをする必要はないが、親要素がbody以外の時にも対応できるように書いておく */
}
.chuuou {
    position:absolute;
    display:inline-block;
    top: 50%;
    left: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
    outline: 2px solid black;
    padding: 10px 25px;
}
```
VBAテンプレート　ファイルを順番に開いて操作する

## VBAテンプレート
自分用です。
Excelにパスを記載したファイルを上から順番に開いて、処理を実施します。
処理部分は記載していません。

Excelシート
「ファイル一覧」シートを作成
下記の表を作成します。
A列：操作の要否（操作不要なら×を記載）
B列：操作したいファイルのパス
C列：操作の成功可否を記載するセル

Moduleは2つ作成します。


Module1
ファイルを開き処理を実施する関数を呼び出す

```
Sub OpenFile()
'Application.ScreenUpdating = False
Dim ファイル一覧シート As Variant
Set ファイル一覧シート = ThisWorkbook.Sheets("ファイル一覧")
Dim 操作ブック As Workbook
Dim 結果 As Boolean

On Error GoTo エラー

For filei = 2 To ファイル一覧シート.Range("B10000").End(xlUp).Row

ファイル一覧シート.Range("C" & filei).Value = "未処理"

 If Not ファイル一覧シート.Range("A" & filei).Value = "×" Then
    Workbooks.Open ファイル一覧シート.Range("B" & filei)
    Set 操作ブック = ActiveWorkbook
    結果 = ファイル操作(操作ブック)
    操作ブック.Close SaveChanges:=False
    ファイル一覧シート.Range("C" & filei).Value = 結果
  End If
  GoTo skip

エラー:
    ファイル一覧シート.Range("C" & filei).Value = "ファイル開かず"
skip:
Next
End Sub

```


Module2
処理を記述

```
Function ファイル操作(ByRef 操作ブック As Workbook) As Boolean

On Error GoTo エラー

'好きな処理を記載




ファイル操作 = True
Exit Function

エラー:
ファイル操作 = False

End Function


```
【Jquery】【javascript】現場で使うJqueryの文・メソッド・擬似クラス・イベントまとめ

# 文
```javascript       
each           

Object.keys
```

# メソッド
```javascript
find()

val()

closest()

eq()

html() 

index()

get()

includes()

removeClass()

parseInt()

is()

empty() 

addClass()

append()

map()

pop()

slice()

clone(true)

```
:::note info
* [clone()](https://qiita.com/panda-chibi/items/5016ed76049bc7eefa27)
:::



# 擬似クラス
```javascript
:visible
```

# イベント
```javascript        
$('セレクタ').on('click',function(){
---何らかの処理---
});       
```
Python-MIPのLinExprTensor.astype()をDataFrameの列に追加したときの考察

## 概要

Python-MIPの`LinExpr`を要素に持つ多次元配列の`LinExprTensor`を考えます。
この`LinExprTensor`は、`astype(float)`により要素を`LinExpr`からfloatに変換してくれます。
ただし、型自体は`LinExprTensor`のままです。
これをDataFrameの列に追加すると、**一見floatの多次元配列に見えて実は異なる型になる**ので、その説明をします。

## 説明

まずは、実際のコードを実行して確認してみましょう。
下記の数理モデルは、非負の連続変数が1つで制約条件なしの最小化問題なので自明の最適解（値は0）を持ちますが、解に意味はないです。
型が興味の対象です。

```py
import pandas as pd
from mip import Model

m = Model()
df = pd.DataFrame()
df["Var"] = m.add_var_tensor((1,), "Var")
m.optimize()
df["Val"] = df.Var.astype(float)
print(f"{df.Val.dtype = }")
print(f"{repr(df.Val[0]) = }")
print(f"{repr(df.Val.max()) = }")
```

出力

```
df.Val.dtype = dtype('float64')
repr(df.Val[0]) = '0.0'
repr(df.Val.max()) = 'LinExprTensor(0.)'
```

`df.Val`は要素が`np.float64`のSeriesです[^1]。
`df.Val[0]`を確認すると`0.0`と出力されます。
しかし、`df.Val.max()`は、`0.0`にならずに`LinExprTensor(0.)`と出力されます。
これは、Seriesの内部構造で持つ多次元配列が`np.ndarray`ではなく`LinExprTensor`だからです。`type(df.Val.values)`とすることで確認できます。
多くの場合、このままでも特に問題になりませんが、ときとして警告が出ることがあります。具体的には下記を実行すると警告がでます。

[^1]: `import numpy as np`を想定しています。

```py
df.Val.max() == 0
```

出力

```
（中略）
FutureWarning: using `dtype=object` (or equivalent signature) will return object arrays in the future also when the inputs do not already have `object` dtype.
  return np.equal(self, other, dtype=object)
LinExprTensor(True)
```

これを解決するには、下記のように`LinExprTensor`を`np.ndarray`に変換すればOKです。

```py
df["Val"] = df.Var.astype(float).to_numpy()
# 下記も同じ
df["Val"] = df.Var.to_numpy().astype(float)
```

ちなみに、`df.Var.astype(float).to_numpy()`は`np.ndarray`ですが、`df.Var.astype(float).values`は`LinExprTensor`なので注意しましょう。

以上
問いを立てるプロセスこそ、プロダクトマネージャーの腕の見せどころ

## はじめに
* 問いを立てるって難しいですよね
    * この記事を書く自分自身もまだまだ見習いでひよっこです
* 取り組んでいる中で、ちょっとわかったことを今回記載します
    * 見習いでひよっこだからこそ、しくじりを交えて
* 俺の屍を超えてゆけ


## 問いを立てるってどういうこと
問いを立てるとは、「[解決すべき問題を設定する](https://note.com/souchido/n/n26c5d85fa136)」であったり、「明らかにしたいことを決める」と言い表せるのではと思います。


つまり問いを立てることは、問題解決のはじめの一歩です。

良い問いを立てることができれば、理想や狙いを叶える可能性が高まります。
しかし問いを間違えると、この後に続く「仮説」「検証」「判断」「実行」のプロセスが全て無駄になってしまう恐れがあります。

これまで何度問いを間違えてきたことか…。それだけでなく、その後に続くプロセスも大失敗をしてきていますが、今回は正しい問いを立てるヒントを、自身のしくじりを交えて3つ共有＋1つおまけを紹介します。

## 1. 問いを問う
なんだかキャッチーな言い方をしましたが、簡単に言えば「そもそもなんでこれを解決したいんだっけ？」と問いを立てる理由を明らかにすることです。
プロダクトマネジメント（≒必要な製品を生み出すことと解釈）においても、「問いを問う」ことはメンバーの納得感と共感を生み出し、生産性に大きな変化が出てくると考えています。

いわゆる[インセプションデッキ](https://blog.nextscape.net/research/agile/inceptiondeck
)にある「我々はなぜここにいるのか」のように、「我々はなぜこれを問いとして立てるのか」を決める。これが起点となって、最終的にはプロジェクトやIssueなど実行フェーズに進んでいきます。

個人的な意見ですが、この「問いを問う」ことは最重要だと考えています。
何を目指し、どこに今回焦点を当てるのか、これを間違えると前述の通りこの後のプロセスが無駄になってしまいます。

ここから問いを間違えた時のシーンを思い出し、しくじりを書いていきます。


## 2. 問いをふわっとさせない
1つ目のしくじり、それは問いをふわっとさせてしまうことです。
例えばメディアを運営していて、PVが伸び悩んでいるという問題があるとします。

この問題のまま「PVを伸ばすためにはどうすれば良いか」と問いにしてしまうことはないでしょうか？恥ずかしながらありました。
解像度が低いまま投げてしまうと、解決策も多く出ますが焦点がぼやけてしまいます。これは経験上良い問いとは思えません。

問いを立てる際には、この2点に重きを置いています。

* とにかく具体的にしていくこと（解像度を上げること）
* さまざまな視点で眺めること

PVが伸び悩んでいる原因はなんなのか、PVを分解していくとどんな要素があり、具体的にどこがボトルネックなのか、あるいはどこが伸び代なのか。さらには方程式も何種類も用意してみて、最もレバレッジのかかるポイントを発見していく。

この作業によって焦点が定まり、この後に続く「仮説」や「検証」のスコープも最小限となることで無駄な工数を使わずに進められます。小さなコストで大きな成果を掴むために、問いをなるべく具体的にしましょう。

## 3. 率直に議論する
声がでかい人がいると、（思っていることと違うけど、議論するのも面倒だし、まあ良いか。）と思いがちですが、絶対ダメです！その後地獄が待っています。

* いやいやそんなことやっても全然上手くいかないでしょ、という実行が待っている
* 案の定上手くいかなくてプロダクトの成長が伸び悩む
* たらればが組織に蔓延して、関係の質が下がり負のループへ
    * [成功循環モデルのバッドサイクル](https://www.salesforce.com/jp/blog/2016/06/success-theory.html)へ突入

…と、メンバーに諭すのではなくマネージャーとしてどうしていくと良いのかをここでは考えていきたいと思います。
そうです、マネージャーとしてこういう雰囲気を作ってしまった（ている）という自分自身のしくじりです。

心理的安全性とは、率直な意見や素朴な疑問、そして違和感の指摘がいつでも、だれでも気兼ねなく言える状態、というのが個人的に1番しっくり来ます。

https://style.nikkei.com/article/DGXZZO66551940U0A121C2000000/

誰もが最初から率直に意見を言えるわけではないはずです。さまざまな性格の人がいて、さまざまなスペシャリティを持っています。
それぞれの力を最大限に発揮できる機会やきっかけを提供し、行動を観察してフィードバックしていく、このプロセスを丁寧に進めてこそ心理的安全性は築き上げられるのではと痛感します。

自分自身は相手に対して率直に意見が言えるから、相手も自分自身に意見が言えるわけではないですし、メンバー自身にも答えを伝えるのではなく問いを提供していくことが役目なのだろうと思います。雄弁は銀、沈黙は金と言いますが、まさに多くを語りすぎないことが気兼ねなく意見を言える状態を作り上げるのだろうと思います。

必要な声でかもありますが、常に声がでかい人になっていないか、は注意していかねばなりません。
心理的安全性の高さは、さまざまなスペシャリティを持っているメンバーを最大限に活かす武器であり、良い問いを生み出す有効な要素です。


## おまけ. 因果関係と相関関係を正しく理解する
問いを立てるプロセスというよりも、その後のプロセスである仮説や検証でのしくじりです。
因果関係と相関関係を正しく理解して使っていますか？混同して使っていませんか？

…はい、正しく使えていませんでした。お恥ずかしい‥。

https://www.nttcoms.com/service/research/dataanalysis/causation-correlation/

## まとめ
* 正しい問いを立てるヒント
    * 問いを問う
    * 問いをふわっとさせない
    * 率直に議論する / 率直に議論できるチームを作る
    * （おまけ）因果関係と相関関係を正しく理解しないと、その後の仮説や検証でメンバーの足を引っ張ることになる

良い問いを設定し、プロダクトを、そして事業を成長させていきましょう！
コマンドラインの where コマンドが無いときの代替スクリプト

```python:
#!/usr/bin/env python3
import os, sys
len(sys.argv) < 2 and sys.exit(print('Usage: where file [file...]') or 1)
x = list(filter(lambda q: os.access(q, os.X_OK),
                [p + '/' + n for n in sys.argv[1:]
                 for p in os.environ['PATH'].split(':')]))
len(x) and print('\n'.join(x))
```
Git認証を求められる対処法


以下のような認証を求められるため、一度打った認証情報の保存をする

```
$ git pull origin master
Username for 'https://gitlab.com':
Password for 'https://user@example.com@gitlab.com'
```

# 対応方法

まず、以下を打つ。

```
$ git config --global credential.helper cache
```

その後、認証を突破する

```
$ git pull origin master
Username for 'https://gitlab.com':
Password for 'https://user@example.com@gitlab.com'
```

もう一度実行すると認証を聞かれなくなる。

```
$ git pull origin master
From https://gitlab.com/directory/project
 * branch                master -> FETCH_HEAD
Already up to date.
```
git add解説

以下は社内向け勉強会のLT枠で話した内容をベースにして編集増補したものである。と言ってもgit addに関しては追加で書きたいこともあまりないので増補部分は少ない。

## git addコマンドの概要

git addはワークツリーからインデックスへのファイルの登録を行うコマンドであり、それ以外の機能はほとんどない。

ワークツリーおよびインデックスの説明は[git checkoutの方で行っている](https://qiita.com/yunano/items/f3133ea64efed762df2f#インデックスとワークツリー)。

## git addの対象範囲

`git add [--] <ファイル名>`で指定したファイルを対象としてインデックスに登録する。

ファイル名には複数指定、ワイルドカード、「.」（そのディレクトリとサブディレクトリにあるすべてのファイル、の意味）も指定可能である。「.」を使って「dir/.」のような指定も可能であり、この場合dirとそのサブディレクトリのすべてのファイルが対象になる。

ファイル名の直前の「--」はこの後の引数をオプションとして使用しない、という意味であり、ファイルパスがマイナスで始まるものを指定する場合に有用であるが、特にそういうのがなければ省略しても良い。習慣として付ける人もいるし、バッチの中で不特定のファイルを処理する場合は付けるべきだろう。

.gitignoreで指定されたファイルは対象外である。ただし-f（あるいは--force）オプションが指定されている場合は対象になる。

また、ファイルが新規追加されたものか更新されたものか削除されたものかのファイル状態ステータスを使用して対象範囲を絞り込むいくつかのオプションもある。

* -A(--all)

新規追加、更新、削除のファイルが対象になる。つまり、この点においてはオプションがない場合と同じである。オプションがない場合との違いはファイル名の指定を省略できることで、省略した場合リポジトリ内のすべてのファイルをファイル名に指定した場合と同じになる。つまりリポジトリ内のどこのディレクトリにいようとも、そのディレクトリとサブディレクトリだけを対象とする「.」とは違って、リポジトリ内のすべての新規追加、更新、削除が対象になる、ということである。

* -u(--update)

更新、削除のファイルが対象になり、新規追加のファイルは対象にならない。-Aと同様にファイル名を省略可で、その場合リポジトリ内のすべての更新、削除のファイルが対象となる。

* --no-all

新規追加、更新のファイルが対象となり、削除のファイルは対象にならない。ファイル名は省略できない。

上述の通りオプションなしのこれらのファイル状態ステータスでの範囲は-Aと同じであるが、かつては--no-allと同じであった。また、-Aや-uのファイル名を省略した場合は「.」を指定した場合は同じであった。これらの情報はWeb検索で古い記事を見ると書かれているが現在は変わっているので混乱しないように。

-N(あるいは--intent-to-add)という、更新のファイルには何もせず、削除のファイルは削除され、新規追加のファイルは空でインデックスに登録される、というオプションもある。このオプションは`git diff`で差分を表示させる対象にしたり、`git commit -a`でコミット対象にしたりするのが目的である。-Nオプションで登録された新規追加のファイルは登録後に変更を行うと、もはや新規追加のファイルではなく更新のファイルである。

## ファイル名を一覧で指定

「--pathspec-from-file <ファイル名>」オプションを指定した場合、直接ファイル名を指定する代わりに、このオプションで指定したファイルの中に書かれている、改行区切りのファイル名のリストを参照して、それらのファイルをインデックスに上げる対象にすることができる。

ここでファイル名に「-」を指定すると標準入力から取得するので、パイプ等で標準入力経由で対象となるファイルのリストを渡すことができる。

追加で--pathspec-file-nulオプションも指定すると、改行区切りではなくNUL文字区切りでファイルを読み込む。これはもはや完全に標準入力から読むつもりしかなさそうなオプションである。例えばfindの-print0オプションでNUL文字区切りのファイルのリストが返ってくるのでそれをパイプで渡す時に使用することになる。

なお、先に記事にした[git checkoutあるいはgit restore](https://qiita.com/yunano/items/f3133ea64efed762df2f)や[git reset](https://qiita.com/yunano/items/c8ae1f165d6af2899281)にもこれらのオプションはあるのだが、使用頻度の面でgit addよりはかなり低いだろう。

## ファイルの一部だけ追加する

[git checkoutやgit restore](https://qiita.com/yunano/items/f3133ea64efed762df2f#ファイルの一部だけ復元する)等と同様に-p（あるいは--patch）オプションが存在するのでファイルの一部だけ追加することができる。

git checkout/git restoreの時との違いとして、以下のように各種メッセージの「discard」の部分が「stage」になっているのはともかく、

```text
(1/1) Stage this hunk [y,n,q,a,d,s,e,?]? ?
y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help
```

eを押した時に入れる、エディタを立ち上げてdiffを編集するモードにて追加したい部分に「+」を付ければ良いのは、消す方に「+」を付けるgit checkout/git restoreと違ってわかりやすい。つまり、例えばインデックス側の今の内容が、

```text
a
b
```

でワークツリーの内容が、

```text
a
1
b
2
```

であり、最終的にインデックスを、

```text
a
b
2
```

としたい場合、eで編集に入った先で次のように変更し、保存すれば良い（コメント行省略）。

```text
@@ -1,2 +1,4 @@
 a
+1
 b
 2
```

なお、git addには最初からエディタ立ち上げによるdiffを編集するモードにする-e（あるいは--edit）オプションもある。