OmniAICreator/Qiita-1.07M huggingface dataset:
動的コンテンツだけをキャッシュしないようにする (ASP.NET Core)

# 動的コンテンツだけをキャッシュしないようにする (ASP.NET Core)

\# 以下の記事が書かれた時の版数は .NET Core 3.1 (3.1.24) となります.

セキュリティー監査ツールにコンテンツをキャッシュしないようにしろと怒られて、`Web.config` に以下のように記載したところ、静的コンテンツまで巻き込まれてキャッシュされなくなってしまいました.

```xml
--- a/WebApplication1/Web.config
+++ b/WebApplication1/Web.config
@@ -6,6 +6,9 @@
                <httpProtocol>
                        <customHeaders>
                                <remove name="X-Powered-By"/>
+                               <add name="Cache-Control" value="no-store"/>
+                               <add name="Pragma" value="no-cache"/>
+                               <add name="Expires" value="-1"/>
                        </customHeaders>
                </httpProtocol>
        </system.webServer>
```

色々知らべた結果、以下のように UseStaticFiles の後にキャッシュしないようにするレスポンスヘッダを出力するミドルウェアを書けば良さそうでした.

```csharp
--- a/WebApplication1/Startup.cs
+++ b/WebApplication1/Startup.cs
@@ -42,6 +42,18 @@ namespace WebApplication1
             app.UseHttpsRedirection();
             app.UseStaticFiles();

+            app.Use(async (context, next) =>
+            {
+                context.Response.OnStarting(() =>
+                {
+                    context.Response.Headers["Cache-Control"] = "no-store";
+                    context.Response.Headers["Pragma"] = "no-cache";
+                    context.Response.Headers["Expires"] = "-1";
+                    return Task.CompletedTask;
+                });
+                await next();
+            });
+
             app.UseRouting();

             app.UseAuthorization();
```

コントローラに `ResponseCache` をデコレーションして回るのも良さそうですが、`Pragma` が出なさそうです. こんな HTTP 1.0 時代の設定止めたいのですが、監査ツールがゴミなのでしょうがない.
TypeScriptでLaravel製APIのバリデーションエラーのレスポンスボディに型をつける（型ガード付き）

タイトルの通り、Laravel製APIのバリデーションエラーのレスポンスにTSで型をつけていきます。フォームのリクエスト処理とかで便利かと。
まずレスポンスの見本を見ていきましょう。
```json
{
    "message": "The given data was invalid.",
    "errors": {
        "【リクエストボディのプロパティ名】" : ["【エラーメッセージ】","【エラーメッセージ2】]
    }
}
```
**errorsというプロパティ名なのにオブジェクト**なのが紛らわしいのと、 **エラーメッセージの配列が入ってる**あたりに注意が必要です。

```ts
export type ValidationError<T> = {
  message: string,
  errors: Record<keyof T, Array<string>>
}

//あえて"=="で比較するだけでnull&undefinedを最小のコードで検出できる
const isNullOrUndefined = (unknown: unknown): boolean => unknown == null

export const isValidationError = <T>(unknown: unknown): unknown is ValidationError<T> => {
  if (isNullOrUndefined(unknown)) { return false }
  if (typeof unknown !== "object") { return false }
  const validationError = unknown as ValidationError<T>
  if (typeof validationError?.message !== "string") { return false }
  if (typeof validationError?.errors !== "object") { return false }
  return Object.entries(validationError.errors)
    .every(
      ([property, messages]) => {
        return typeof property === "string" &&
          Array.isArray(messages) &&
          messages.every(message => typeof message === "string")
      }
    )
}
```
認識してる欠陥としては、errorsオブジェクトのプロパティ(```keyof T```の部分)が文字列としかチェックしようがないので、全然違うプロパティ名が入っても通ってしまうことです。
もし改善案があればコメントお願いします。
”firebase_options.dart”が生成されない

flutter codelabのfirebase get to know flutter step2のチュートリアル中にこの件でハマったので記録。


## 問題
### `flutterfire configure`を実行しても”firebase_options.dart”が生成されない

flutterfire_cliによって、現在実装中アプリのファイル群を解析し、プラットフォーム依存に関する設定オプションファイルを生成する（勉強中のため理解が間違っているかもしれません）。
そのコマンドが`flutterfire configure`。

ただし、私の環境（VS Code内）では実行してもうまく”firebase_options.dart”が生成されず、
これが影響したのかはfirebaseプロンプト(?)から実行しても同様にNG。
エラーは以下。
> Unhandled exception:
FormatException: Unexpected character (at character 1)
\#
…


## 解決に向けて

どうやら同様のケースはVS Codeに限らず発生しているようで、Stackover flowやflutterfire_cliのgitページにはいくつか同様のissueスレッドがある。
ただし、ズバリこれ、といった解決策は見当たらなかった。
* VS Codeだと動かなかった
* flutterfire_cliを再インストールしたら解決

など。

ここでは、これらの解決案を元に、私が解決までに試した一連を記す。 **あくまで参考として留意されたし**

#### 解決までのステップ

0. flutterfire_cliの再インストール
    * 自分はWindowsで試していたので、exeファイルを差し替え
        * バージョンに変更はなかったが、ファイルサイズが異なっていた
    * ただし、解決には至らず
0. flutterfire_cliの再アクティベーション
    1. `dart pub global deactivate flutterfire_cli`を実行
    1. `dart pub global activate flutterfire_cli`を実行
        * 前提だが、2のactivateは既に実行済である。その上で再度アクティベーションすればよいかと考えたが、既にアクティベート済だから、deactivateしてから再実行しろとエラーが出るため、1→2と実行した。
            * このアクティベーションについては、全く理解できていない。
            * 実行するとflutterfireのコマンドが使えるようになる。この時に、色々と他モジュールなどの情報を収集しているようなので、ある程度環境依存のコマンドで、モジュールの入れ替えなどした場合には再アクティベーションが必要なものなのだろうか。
    * ただし、解決には至らず

0. `firebase --reauth`を実行し、再認証。

0. firebaseプロンプト(?)内で`flutterfire configure`を実行
    > Firebase configuration file lib\firebase_options.dart generated successfully with the following Firebase apps:
...

### 解決!

以上だが、もちろん途中、都度firebaseプロンプト(?)内外で`flutterfire configure`を試して、NGだったため、上記ステップ一通り実行する必要があったのだと思うが、何が要因だったのかはわからない。
アクティベーション後は、firebaseプロンプト(?)内でなくても実行できるという理解だが、もしかしたらその理解が間違っていた？もしくは上手くアクティベーションができていない？
VS Codeではまだ試していない。


### その後、チュートリアルの実行まで
この件とは違うが、android, iosのfirebase側のアプリケーション登録にミスがあったようで、`flutterfire configure`によって、自動的にfirebase側に登録してくれた。
> Firebase android app com.example.gtk_flutter is not registered on Firebase project fir-flutter-codelab-12345.
 Registered a new Firebase android app on Firebase project fir-flutter-codelab-12345.
 Firebase ios app com.example.gtkFlutter is not registered on Firebase project fir-flutter-codelab-12345.
 Registered a new Firebase ios app on Firebase project fir-flutter-codelab-12345.
 Firebase macos app com.example.gtkFlutter is already registered.
 Firebase web app gtk_flutter (web) is already registered.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110354/c9f142ff-c76b-4080-cec3-ac936544d043.png)

#### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110354/ac09df96-02a6-987a-59fc-e0bec18d9a80.png)


以上、終わり。

#### 参考リンク
https://firebase.google.com/codelabs/firebase-get-to-know-flutter#3

https://firebase.google.com/docs/cli

https://firebase.flutter.dev/docs/cli

https://stackoverflow.com/questions/70404936/missing-firebase-options-dart-file-in-course-get-to-know-firebase-for-flutter

https://github.com/invertase/flutterfire_cli
CHAIDで決定木。Pythonで

# はじめに
Pythonを使って、CHAIDの決定木を実行する話。
はまったことも紹介します。

前回の記事のCHAIDやりたい！っていうところから１歩調べてみました。
[前回] sklearnのDecisionTreeClassifierの結果の理解
https://qiita.com/yo16/items/36ec237a574d8ab86a75

使うライブラリはこちら

https://github.com/Rambatino/CHAID

```python
pip install CHAID
```


# 使うデータ＝sklearn.datasets.load_iris
sklearnのirisデータを使ってみます。
```python
from sklearn.datasets import load_iris

iris = load_iris()
X = iris.data
y = iris.target
```

ここで注目。
```python
>>> print(X)
[[5.1 3.5 1.4 0.2]
 [4.9 3.  1.4 0.2]
 [4.7 3.2 1.3 0.2]
 [4.6 3.1 1.5 0.2]
 [5.  3.6 1.4 0.2]
 (～省略～)
 [6.2 3.4 5.4 2.3]
 [5.9 3.  5.1 1.8]]
```
１行ずつ、配列になってます。
使用する Rambatino/CHAID は、1列ごとに配列になってないといけないです。ここに結構はまりました。

# 加工
1列ごとの配列に加工します。
```python
X_t = list(zip(*X))
```
※ `list(zip(*X))`の説明
zip関数に、`*X`を渡します。`*X`というのは、外側の `[ ]`を外して渡すというもの。つまり`[5.1, 3.5 1.4 0.2] [4.9 3.0 1.4 0.2] ～ [5.9 3.  5.1 1.8]`という、行数分の配列（irisの場合は150件）を一気にzipに渡します。そうすると、zipは、1/150から1つ目を、2/150から1つ目を、・・・150/150から1つ目を取り出し、くっつけて150要素の配列にします。つぎに1/150から2つ目を、2/150から2つ目を・・・150/150から2つ目を取り出し、くっつけて150要素の配列にします。・・・を4回繰り返します。
それを`list()`すると、150要素ある配列が4つ、配列になります。

```python
>>> print(X_t)
[(5.1, 4.9, 4.7, 4.6, 5.0, （～省略～）, 6.2, 5.9),
 (3.5, 3. , 3.2, 3.1, 3.6, （～省略～）, 3.4, 3. ),
 (                （～省略～）                   ),
 (0.2,　（～省略～）                   , 2.3, 1.8)]
```

tは、転置行列という意味で名付けてます。

# CHAIDで決定木
ここまでできればあとは簡単。
```python
from CHAID import Tree, NominalColumn, OrdinalColumn

# OrdinalColumnが４要素入っている配列を作る
cols = [OrdinalColumn(x, name=f'col_{i}') for i, x in enumerate(X_t)]

# 決定木を実施
tree = Tree(cols, NominalColumn(y), {'min_child_node_size': 5)
```
`Tree()`に、説明変数、目的変数の順に入れます。
変数のタイプは、２つあります。
`OrdinalColumn()`は、順序尺度。数字の大小、順序に意味がある数値。irisのサイズは順序に意味があるのでこちら。
`NominalColumn()`は、名義尺度。数字に意味はない。irisの0,1,2の順序は関係ないのでこちら。

変数のタイプは、順序尺度であって連続値ではない点には注意です。（column.pyには`ContinuousColumn()`っていうのがあるんだけど、目的変数にしか使ってないのかも）
数値が、1,2,100の３タイプがあったら、1と2が近くて100は遠いということは意識せず、1,2,3と同じように判断するということになります。危うい。。


# 確認
`print_tree()`ってやると、わかりづらいけどツリーが出ます。とりあえず中かっこに着目すると、0,1,2の数がもともと`{0: 50.0, 1: 50.0, 2: 50.0}`だったものが、col_2、col_0の値によって、分けられてます。
図にしたりする関数もあるけど、そこは別の話なのでこの記事では割愛。
```python
# 確認
tree.print_tree()
#([], {0: 50.0, 1: 50.0, 2: 50.0}, (col_2, p=2.561410449304364e-54, score=256.52173913043475, groups=[[1.9], [3.9, 4.3], [5.2, 6.7]]), dof=4))
#|-- ([1.9], {0: 50.0, 1: 0, 2: 0}, <Invalid Chaid Split> - the node only contains single category respondents)
#|-- ([3.9, 4.3], {0: 0, 1: 48.0, 2: 6.0}, (col_0, p=0.0848944843805779, score=4.9326923076923075, groups=[[4.5], [5.2], [6.8, 7.7]]), dof=2))
#|   |-- ([4.5], {0: 0, 1: 1.0, 2: 1.0}, <Invalid Chaid Split> - the minimum parent node size threshold has been reached)
#|   |-- ([5.2], {0: 0, 1: 25.0, 2: 1.0}, <Invalid Chaid Split> - the minimum parent node size threshold has been reached)
#|   +-- ([6.8, 7.7], {0: 0, 1: 22.0, 2: 4.0}, <Invalid Chaid Split> - the minimum parent node size threshold has been reached)
#+-- ([5.2, 6.7], {0: 0, 1: 2.0, 2: 44.0}, <Invalid Chaid Split> - p-value greater than alpha merge)
```

# まとめ
PythonでCHAIDの決定木（Rambatino/CHAID）を実行する記事は、一貫して説明してるものがあまりなく、少し苦労しました。

注意ポイントは２つありました。
1. 説明変数の行列の方向・次元の順序（CSVを読むにしても、irisを使うにしても、今回の転置変換は必要です）
1. 説明変数の連続値は使えない
Chromeの最小フォントサイズに気をつけろ！【フロント開発でハマった話】

# 問題が発生
SP画面の開発をしていた際、ある箇所のフォントサイズを8pxに設定。
ところが、複数人から「表示崩れしている」との指摘を受けました。
何度確認しても私の画面で表示崩れは起きていない‥。

なぜ？？？🤔

# 原因 ： Chromeの「最小フォントサイズ」の罠だった
とりあえず結論。
Google Chromeには「最小フォントサイズ」というものが存在するようです。

表示崩れしていた原因は
**最小フォントサイズが10pxに設定されているため、10px未満のCSSを設定しても効かない**
ということでした。

なるほど。

それでなぜ私の画面だけおかしかったのかというと、
**Chromeを英語設定で使用していたため**でした。

🙀🙀

英語設定にしていると、最小フォントサイズが設定されていないようです。
日本語設定だと、デフォルトで10pxになっています。

ちなみに日本でChromeをインストールする場合、基本的に日本語設定になるのですが、
私はPCの言語設定を英語にしているため、自動で英語設定になったと思われます。

思わぬ落とし穴でした。


# 最小フォントサイズを変える方法
最小フォントサイズの設定をしていきます。
Chromeのアドレスバーに以下を入力して、フォント設定画面を開きます。

```
chrome://settings/fonts
```

このような画面です。
![Screen Shot 2022-04-14 at 23.57.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1809963/88c0d75e-cd27-149a-ad28-eafa00fba994.png)
最小フォントサイズを**10px**にすれば解決！！🙌🏻


# そもそも、10px未満のフォントは使わないほうが良い
ここまでつらつらと語っておきながらすみません。
こんなことは一般的に知られておらず、デフォルト設定のままの人が多いです。
だから表示崩れを指摘されて「Chromeの最小フォント設定が〜」なんて理由は通用しないはず。

フォントが小さすぎるとUI的にも良くないので、どうしても10px未満にしたい場合は画像などで対応するのが無難そうですね。



# おわりに

最初、原因が全く分からずCSSやライブラリあたりの話だと思っていました。
英語設定、気をつけねば。。

お読みいただきありがとうございました 🐥
いつまでも，古いママやってんじゃねえよって話(3)

https://qiita.com/yatra9/items/a4b58020ebf478b87a1e

ここに書くのも，それでも，Julia 1.7.2 での話。そのうち古くなる。

# 3. サイズが10のゼロベクトルを作成 (★☆☆)

```Julia
Z = zeros(10) # without initialization # ゼロ初期化が必要ない場合
```
まあ，これはいいです。
整数ベクトルか，浮動小数点べくとるかを明示するには，明示すべきでしょう。

```Julia
Z = zeros(Int, 10)     # 整数ベクトル
Z = zeros(Float64, 10) # 浮動小数点ベクトル
```

しかし，以下はだめです。

```Julia
Z = Vector{Float64}(10)
```

undef を指定しなければなりませぬ。

```Julia
Z = Vector{Float64}(undef, 10)
```
いつまでも，古いママやってんじゃねえよって話(2)

https://qiita.com/yatra9/items/a4b58020ebf478b87a1e

ここに書くのも，それでも，Julia 1.7.2 での話。そのうち古くなる。

# 3. サイズが10のゼロベクトルを作成 (★☆☆)

```Julia
Z = zeros(10) # without initialization# ゼロ初期化が必要ない場合
```

整数ベクトルとは言っていないので，まあ，これは許容範囲。

厳密に言えば，整数ベクトルならば

```Julia
Z = zeros(Int, 10)
```

浮動小数点ベクトルならば

```Julia
Z = zeros(Float64, 10)
```

ちなみに，論理値 false のベクトルは
　
```Julia
falses(10)
```
OpenOCD で"Haven't made progress in mpsse_flush() "というWARNが繰り返される

# 背景
ARM-USB-TINY-HというOlimex社のArm用JTAGデバッガとOpenOCDを使ってJTAGのお勉強を始めたところ一番最初にはまった問題

ここでは問題解決ではなく回避策としてその内容を記載

# 解決方法
以下のいずれかで解消
* USBケーブルを抜き差しする
* コマンドによるunbind,bindによりUSB再接続する
* usb_modeswitch によりUSBリセット


# エラー内容
```:エラーメッセージ
Warn : Haven't made progress in mpsse_flush() for 2145ms.
Warn : Haven't made progress in mpsse_flush() for 4185ms.
Warn : Haven't made progress in mpsse_flush() for 8010ms.
Warn : Haven't made progress in mpsse_flush() for 16169ms.
Warn : Haven't made progress in mpsse_flush() for 32233ms.
Warn : Haven't made progress in mpsse_flush() for 64106ms.
Warn : Haven't made progress in mpsse_flush() for 128106ms.
Warn : Haven't made progress in mpsse_flush() for 256107ms.
```
こんな感じ。

JTAG(自分の場合, ARM-USB-TINY-H)に接続したUSBを抜き差しすることで解決したことがあった。
USBのなんらかの接触なのだろうと思い、深追いせず。

しかし、また再現。

どうやら同じ様な問題に遭遇した人もいた。ただこの人はversion 0.10の時に発生していたが、根本には解決しなかった模様。（v0.11では発生したとは書かれていない)
https://qiita.com/hro/items/dc0f8b806e2f4137772f#openocd-010
だが、自分の場合、どちらのバージョンでも再現してしまう。

## さて。
mpsse_flush() のエラーログに関するcommitログはこちら。
>  Add wall clock timeout warning to mpsse_flush()
>
>    I think that libusb_handle_events_timeout_completed is supposed to make    progress or time out, but sometimes we hit a case where it makes no   progress, and mpsse_flush() loops forever. This wall clock timeout   notifies the user that this is going on.
>
>    When I wrote this code, this bug would reproduce every hour or two, but    right now it's not happening for me.

（推測だが）USBからのイベントが返ってこずループに陥ってしまった際に適切に警告メッセージを出すようにしたとのこと（と解釈。）
発生原因は不明だが、USBケーブルの抜き差しにより解決した理屈も納得（？）
ということで、本現象が起きてしまったらUSBを一度抜き、再接続することで回避できそう。

**解決1: USBの抜き差しを行う**

## でも毎回抜き差しするのは面倒。
そもそもなぜこの問題が発生するのか、その理由は不明。気が付いたら再発という始末。

最近はリモート環境が当たり前になり手元に機材が置いてないことも標準なので簡単に抜き差しできるとは限らない。
それだけでなくUSB抜き差しを繰り返すことによる劣化も避けたいところ。

コマンドでUSBの抜き差しする方法があればと思って探したところ、linuxであればbind/unbindにより可能とわかった。

**コマンドで USB をリセットしてみる**
* https://server-setting.info/blog/usb-reset-for-command.html
* http://mkplan.com/memo/2016/03/07/402/

これでも十分なんだが接続しているusbポート番号を確認して正しく指定しなければならず、誤って異なる番号を使ってしまうリスクを考えるとあまり好きではない。（絶対ミスする気がしてならない）


# usb_modeswitchというコマンドがあった！！
 /sys/bus/usb/drivers/usb/bind （or unbind)によるUSBのリセットも可能だけど他の方法はないかと探してたところ、同じページにおまけとして「コマンドで USB をリセットしてみる(usb_modeswitch編)」というのがあった。

前置き長くなったけどこれが一番簡単でミスも少なく安全なのでオススメ

### USBのベンダー番号、プロダクト番号を確認
おなじみlsusbを使って、ベンダー番号/プロダクト番号を確認。
```
$ lsusb | grep ARM-USB
Bus 003 Device 089: ID 15ba:002a Olimex Ltd. ARM-USB-TINY-H JTAG interface
```
今回の場合、ベンダーIDは0x15ba, プロダクト番号は0x002aとなる。16進数なのでご注意。

```bash:usb_modeswitch 実行
$ usb_modeswitch -v 0x15ba -p 0x002a --reset-usb
Look for default devices ...
 Found devices in default mode (1)
Access device 089 on bus 003
Get the current device configuration ...
Current configuration number is 1
Use interface number 0
 with class 255
Warning: no switching method given. See documentation
Reset USB device .
 Device was reset
-> Run lsusb to note any changes. Bye!
```

**解決2: usb_modeswitch実行によりUSB接続のリセットを行う**
Google Apps Scriptでエンドポイント付きAPIを作る

Google Apps Scriptとスプレッドシートだけで簡易的なAPIを作るよ。

# 仕様
<dl>
  <dt>GET /user</dt>
  <dd>ユーザー取得</dd>
  <dt>POST /user/create</dt>
  <dd>ユーザー作成</dd>
</dl>

# 実装

```javascript:main.gs
function toJson(data) {
  console.log(ScriptApp.getOAuthToken())
  return ContentService.createTextOutput(JSON.stringify(data))
    .setMimeType(ContentService.MimeType.JSON);
}

function indexOf(id) {
  const sheet = SpreadsheetApp.getActiveSheet();
  const range = sheet.getDataRange();
  const values = range.getValues();
  return values.find((value) => value[0] == id);
}

function doGet(e) {
  const path = e.pathInfo;
  if (path == "user") {
    const query = e.parameter;
    return toJson(indexOf(query.id));
  } else {
    return toJson(null);
  }
}

function doPost(e) {
  const sheet = SpreadsheetApp.getActiveSheet();
  const path = e.pathInfo;
  const postdata = JSON.parse(e.postData.contents);
  if (path == "user/create") {
    sheet.appendRow([postdata.id, postdata.name]);
  } else {
    return toJson(null);
  }
}
```

# 完成？
作成したプロジェクトを実行者を自分、アクセスできるユーザーを全員にしてデプロイして実行すると・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1470472/1e246b17-e15a-4e28-88fe-6cd0d00530f0.png)
<b>動かない</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1470472/967d26c8-6e0d-a52d-20a0-ef64225fdb3d.png)
アクセスできるユーザーを全員にしているため、本来であれば正常にPOSTできるはずだが、認証画面が帰ってきている。

## 何故正常に動かないのか
`exec/`の後にパスを続けて書くと、どの設定にしても認証が必要になるみたい。
詳しい理由が知りたいが、調べてもリファレンスに何も書いていなかったためよくわからない。

# どうすればいいか
Googleの認証をパスするために、認証情報をパラメーターに加えればいい。

## 手順
### 1. プロジェクトの設定から、「appsscript.json」マニフェストファイルをエディタで表示するをチェックをする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1470472/6e2c4a09-54fc-1381-5a5e-4db15d40e6ac.png)
### 2. appsscript.jsonにスコープを追加する。
```json:appsscript.json   
"oauthScopes": [
    "https://www.googleapis.com/auth/script.external_request" 
]
```
### 3. scriptのOAuthトークンを取得する
```javascript: main.gs
function token() {
  console.log(ScriptApp.getOAuthToken());
}
```
### 4. URLパラメーターに`access_token=取得したトークン`を付けてアクセスする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1470472/331c9893-5c4f-8663-aec0-20677ebbe60b.png)

<b>これで認証をパスして外部からアクセスできる！</b>

# 補遺
<a href = "https://developers.google.com/apps-script/reference/script/script-app#getoauthtoken">getOAuthToken</a>の公式リファレンスを見ると、この関数で取得したアクセストークンは数時間で使用できなくなるみたい。
回避方法としては、アクセストークンを発行するだけの別のプロジェクトを作成し、本命のプロジェクトにアクセスする前にトークンの発行をすれば大丈夫。

# 参考
  <a href = "https://qiita.com/hakaicode/items/0e2bc0e5b5e43ca12b42#google-apps-scriptgas1%E3%81%A7%E9%83%BD%E9%81%93%E5%BA%9C%E7%9C%8C%E3%83%9E%E3%82%B9%E3%82%BF%E3%82%92json%E3%81%A7%E8%BF%94%E3%81%99api">Google Apps Scriptを使ってサーバーレスファンクションを作る</a>
  <a href = "https://zenn.dev/seya/articles/709659242512a7">GAS で OAuth のスコープが足りなくてやったこと</a>
  <a href = "https://blog.beatdjam.com/entry/2020/12/29/174418">【GAS】Drive上のファイルの共有リンクを取得し、ダイアログからダウンロードさせる</a>
生HTMLからタグを除去する

`vue`の`v-html`や`React`の`dangerouslySetInnerHTML`に出力させているHTMLのテキスト部分だけ必要な場面があったので備忘録

# TLDR

```ts
const removalTag = (html: string) => {
 const domParser = new DOMParser()
 const doc = domParser.parseFromString(html, "text/html")
 return doc.body.innerText
}
```

# 解説

## DOMParserの呼び出し

```ts
const domParser = new DOMParser()
const doc = domParser.parseFromString(html, "text/html")
```

第一引数にHTML、第二引数に`text/html`を渡す。
ここについてはドキュメントの通り。

https://developer.mozilla.org/ja/docs/Web/API/DOMParser


`domParser.parseFromString()`からの結果が`<html><head></head><body></body></html>`なのだが、
今回必要なテキスト部はbodyタグ配下に来るので一旦bodyで絞り込む。

## テキストを抽出する

```ts
return doc.body.innerText
```
- もしエスケープ文字（改行やタブ）が欲しい場合は`innerText`を`textContent`にする

# おわりに

別に`replace()`でも実現出来ないことはなさそうだけど、
大なり小なりとかエスケープを完全に考慮できた正規表現に自信が無いときにはアリかと思う。

（そもそもHTML埋め込む要件自体が無ければベスト）
PythonのType Hint(annotation)を自由自在に操る

PythonのType Hintを使ってますか？
最初は苦痛でしか無かったのですが、最近、意図通り使えるようになってきた。

## Type Hint使う理由(利点)
1. 実行前にエラーがわかり、時間節約
2. 思い違いの論理エラーを早くに検出し、時間無駄にしない。
2. 改てコード見直した時、コード内容を思い起こしやすい。

## Type Hintという結論は良さそう
1. 型厳密性が高い言語の方がコンパイルした時の早いじゃないの？、と思ってますし、きっとそうでしょう。ただし、静的型付に比べ、型のstrict性が無がないのでPythonicな書き方を維持できていると思う。
1. annotationのおかげで、Cythonの型指定も楽になりました。(Pure Pythonモードなので20-50%の向上しか無いそうですが。)

```python
# CythonのAnnonationを使った例
@cython.cdef
def main(a:cython.int):
   ...
```

# Type Hintが誤解する箇所の対処方法

書きかけです。優先度が高い情報から記載

## 可読性が高い書き方へ移行
1. 古いPythonを使わないといけない時に便利。下記おまじないを書くとPy3.9以降の記法が適用されるみたい
1. `from __future__ import annotations`

例えば、
1. `typing.Union[int,float]`は`int|float`と書ける
2. `typing.List[int]`も`list[int]`とかける

## SQLAlchemyの場合

### SQLAlchemyのobjの型補完
下記でうまくいく？エラーで解析できてないだけ？
- ~~自動解決されてないので、型を記す。~~
- ~~例: `registration_datetime:datetime.datetime= Column(DateTime)`~~
- SQLAlchemyはstubがあるけど効かない。どう使うのだろう...import?
- sessionやengineのTypeHint。これをするとPyCharmでは、メソッド候補がホバーされる。
```python
connection_string: str = "sqlite:///:memory:"
engine = create_engine(connection_string)
session = Session(bind=engine)
print(type(engine))   # sqlalchemy.engine.base.Engine
print(type(session))  # sqlalchemy.orm.session.Session
```
- src: [Type hints for SQLAlchemy engine and session objects](https://stackoverflow.com/questions/56118095/type-hints-for-sqlalchemy-engine-and-session-objects)

### SQLAlchemyのデータ型に対するTypeHintの書き方。
```
reg_dtt: sqlalchemy.Mapped[datetime.datetime] = sa.Column(sa.DateTime, nullable=False)
```
上記の通り`Mapped`で型指定すると、下記通りbetweenでMyPy由来のエラーでない。確認PyCharm2021.1.MyPy0.951.
```
MyTable.reg_dtt.between(start, end))
```

## Noneから初期化されている事を示す / 型が適切である事を示す。
- assertと併用する
- `assert 変数 is not None, "変数は初期化されてない"`

### castを使う

## mypyは異なるvenvの物を利用しない
1. 結果が正確でなくなるから。おそらく、同venvのパッケージを解析する方が正確なのだろう。
1. PyCharmで、高速化を期待してmypyをdaemonとして登録したが、異なるvenvのmypyでは正確ではない事に気づいた。

## stub/typesパッケージのインスト
1. これらパッケージを入れると、型やら記述された.pyiファイルがインストールされて、IDEなどで型情報が補完されるらしい
1. 例
    1. [wearepal/data-science-types](https://github.com/wearepal/data-science-types)
       - Mypy type stubs for NumPy, pandas, and Matplotlib
    2. [sqlalchemy-stub](https://github.com/dropbox/sqlalchemy-stubs/tags)
        2. どちらを使う方がいいのかな[sqlalchemy2-stubs](https://github.com/sqlalchemy/sqlalchemy2-stubs)


## enum.auto
下記で上手くいく？
1. `var : Enum型Class名|str`
[python]タイピングゲームでのライフハック的なもの

# イータイピングマジで最高
タイピングゲームといわれて、何をみなさんは思い浮かべますか？
ほとんどの方が寿司打、<strong>e-typing</strong>を思い浮かべるかと思います。
（WEB上のものだけ）
小学生のころからタイピングの練習のために私もよく利用していました！

今回は、題名にもある通りe-typingについての話なのですがこのゲーム非常にやり直しがめんどくさい。。

どういうことかというと、特にノーミスタイプを目指してゲームを行う際に

ゲームスタートー＞タイプミスー＞ESCキー押すー＞マウスでもう一回ボタンを押すー＞・・・

という流れが通常動作になりますが<strong>マウスを動かすのが非常にめんどくさい！！！</strong>

今回、これを解決するためにpythonを扱ってキーボードだけで完結するようなプログラムを作りたいと思います！

# 環境
- Win11
- Python 3.9.7

## 使用モジュール
- keyboard
- pyautogui
以下のコマンドをプロンプト上で入力してあげてください。
<br>
キーボードの入力を検知するために扱うモジュール

```
pip install keyboard
```
マウスの操作につかうモジュール

```
pip install pyautogui
```

# 解決方法
HTMLやらの構造を見ていろいろいじくる方法も考えたのですがあまり気が進まなかったので、もう一回のボタンを物理的に押してやるコードを書くことにしました。

自分の場合、左shiftキーを使わないのでそのキーが押されたときに左クリックが押されるようにプログラムを記述することにしました。

（`マウスは"もう一回"の場所に合わせておくことを想定しています。`）

# コード

``` python
import pyautogui
import keyboard

while True:
    # 左側のShift keyを押したときに、クリックボタンが押される
    # 右側はreft shift
    if keyboard.read_key() == "shift":
        pyautogui.click()

```
# 感想
マウスはもう一回のところに合わせておく必要がありますが、マウスを動かす必要がなくなるのであまりストレスを感じずにゲームをすることができるようになりました！

ちなみに、シフトキーではなくスペースキーに右クリックを割り当てる（スペースキーとしても同時に入力されます。）とスペースキーを二回連打するとすぐにリプレイできるのでおすすめです。

自分はイータイピングのスコア目標が600越えなのでさらに練習したいと思います！
ぜひ、なにかタイピングのコツなどがあれば教えていただけると嬉しいです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2261324/235590d1-1f01-0312-f8d0-65e07b28907e.png)

# 参考
【自動化】Pythonでマウスとキーボードを操る
https://qiita.com/konitech913/items/301bb63c8a69c3fcb1bd
改行無しの標準出力最終行がプロンプトで消えてしまう

# 問題
MacのzshでPreztoを利用していたのですが、OSをMontereyにアップグレードしたタイミングで、
標準出力の最終行が改行無しだった場合に、一瞬表示された後にプロンプトが表示されるタイミングで消えてしまう現象になりました。
# 対応方法
下記を.zshrcに追記することで、改行無しの最終行が表示されるようになりました。
```
setopt prompt_cr
setopt prompt_sp
```
# 参考url
https://michimani.net/post/develop-zsh-prompt-remove-last-line/
Spring構造紹介

# Springのアキテクチャ
Springフレームワークは分層フレームワークで、沢山のファンクションを持ち、約20モジュールがあります。以下の図のように
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648622/ef9e22e5-142c-07c6-7991-6ebfc0fa458c.png)

主に以下の５つの部分に分けられます。
## Core Container
Core Containerには、Core、Beans、ContextとExpression Languageがあります。CoreとBeansは基盤の部分で、IoCとDIのファンクションを提供します。ここでは、BeanFactoryという概念がありまして、Factoryパターンを実装してシングルパターンができ、依頼関係と設置を分離することができます。
- Coreモジュールは主にSpringフレームワークのCoreツールクラスを含む、SpringのほかのモジュールはCoreモジュールのクラスをよく使って、Coreモジュールはほかのモジュールの基盤です。
- Beansモジュールは全てのアプリケーションが使うものです。例えば、設置ファイルのリーディング、beanの構造や管理、またInversion of Control /Dependency Injection（IoC/DI）に関わるクラスです。
- ContextモジュールはCoreとBeansを用いて構築されたものです。ContextはJNDIに似てるものを提供してインスタンスをリーディングします。ContextはBeansの特徴を継承し、大量のファンクションを提供します。
- Expression Languageは強大な言語表現式を提供し、インスタンスの操作を行います。

## Data Access/Integration
Data Access/Integration層はJDBC、ORM、OXM、JMSとTransactionを含んでいます。
- JDBCモジュールは抽象的なJDBCを提供します。このJDBCモジュールは全てのJDBCのクラスを含んでいます。
- ORMモジュールは流行っているORMにAPI層を提供します。

Springは若干のORMフレームワークツールを提供します。例えば、JDO、HibernateとiBatisSQL Map。これらはSpringトランザクションやDAOの構造に従います。
- OXMモジュールはObject/XMLの抽象的な層を提供します。Object/XMLにはJAXB、Castor、XML-Beans、JiBXとXStreamを含んでいます。   
- JMS（Java Messaging Service）モジュールはメッセージのPub/Subの特性を含んでいます。
- TransactionモジュールはトランザクションのAPIを提供します。

## Web
Webモジュールはアプリケーションコンテストの上で、ウェブに基づくアプリケーションのコンテストを提供します。Web層にはWeb、Web-Servlet、Web-StrutsとWeb-Porletを含んでいます。
-　Webモジュールは基盤Web特性を提供します。例えば、ファイルのアップロード、servlet listenersの使いなどです。
-　Web-Servletモジュールweb.servlet.jarには、Springのmodel-view-controller（MVC）の実現を含んでいます。
-　Web-StrutsモジュールにはStrutsの実現を含んでいます。ただ、Spring 3.0からもう廃棄されました。
-　Web-PorletモジュールはPortlet環境やWeb-ServletモジュールのMVCの実現を含んでいます。

## AOP
AOPモジュールはAOP標準に基づいて、Pointcutインターフェースを提供しています。また、AOPモジュールにはトランザクションも提供しています。
-　AspectsモジュールはAspectJの実現を含んでいます。
-　Instrumentationモジュールはclass instrumentationやclassloaderの実現を含んでいます。

## Test
TestモジュールはJUnitとTestNGの実現を含んでいます。
Python の input( ) と同様の挙動を JavaScript, Node.js で再現する

私と同じ悩みを持つ方のために、共有させていただきます。
以下のQAにてご指導頂いた内容ですので、経緯等は以下のページを参照ください。

https://qiita.com/watanabe-tsubasa/questions/07131f97fa0a48897ab2#answer-7d6b619e11e5876f6023

## 動作

<img src = 'https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2100048/f52dad5d-2a4a-485f-6816-fb398c294654.png' width = 70%>

実行すると数字１を聞かれます（今回は10を入力）。

<img src = 'https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2100048/eb6b7384-41e8-33f3-c1a9-05609c8963a2.png' width = 70%>

入力すると数字2を聞かれます（今回は20を入力）。

<img src = 'https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2100048/998b11d8-fe59-8a06-8f94-c55f2ad74ab0.png' width = 70%>

コンソールに入力した数字と、その和を出力してくれます。
つまり、`Python`の`input()`のように使えます。

## サンプルコード
```js
const readline = require('readline/promises');

const input = async (name) => {
    const readInterface = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
    });
    let string = await readInterface.question(name)
    readInterface.close();
    return string
}

(async () => {
    let a = Number(await input('数値1>'));
    let b = Number(await input('数値2>'));
  
    console.log(a);
    console.log(b);
    console.log(a + b);
  })();

// ※何も書かない方が良い
```
::: note
*以降は何も書かない方が良いです。async以下実行されてしまいます。
:::

## 動作環境
> Node.js v18.1.0
::: note warn
'readline/promises' モジュールを仕様しているのでNode.jsのバージョンは17.0以上が必要かと思います。
:::

version 16 以下の場合はこちら
<details><summary> Promise を利用したコード</summary>


```js
const readline = require('readline');
 
const input = prompt =>{
    const readInterface = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
    });
    return new Promise( resolive =>readInterface.question(prompt,
        input=>{
            readInterface.close();
            resolive(input);
        }));
};
 
(async () => {
    let a = Number(await input('数値1>'));
    let b = Number(await input('数値2>'));
  
    console.log(a);
    console.log(b);
    console.log(a + b);
  })();

```
</details>


## 最後に

Pythonで書くとこうなります。

```Python
a = int(input('数字1>'))
b = int(input('数字2>'))

print(a)
print(b)
print(a + b)
```

Python流行る理由がなんとなくわかりました。
ですが、JavaScriptも魅力的な言語なので、引き続き勉強していきます。
シェルスクリプトで配列をコピーする

シェルスクリプトで配列をコピーするには、`dst=(${src[@]})`のようにすればOK

```sh:test.sh
src=(aaa bbb ccc ddd eee) # コピー元配列
dst=(xxx)                 # コピー先配列
dst=(${src[@]})           # コピー処理
echo ${dst[@]}            # 出力
```

実行結果

```sh
bash test.sh 
aaa bbb ccc ddd eee
```

# 参考

https://atmarkit.itmedia.co.jp/ait/articles/1905/29/news006_2.html
Dockerコマンド検索方法

・Dockerコマンド検索方法
●方法1
①docker referenceをググる
②dicker docsのDockerfile referenceページへ移動
③左上のCommand-line referance
④Docker CLI(docker)
⑤コマンド一覧が表示される

●方法2
①ターミナルにdocker --helpを入力
【Git】コマンドメモ(普段使うコマンド集)


gitを使わなくなると途端に忘れてしまうのでメモする。

## git clone

リポジトリにあるソースをローカルチェックアウトする。

```sh
git clone <url>
```
## git add

変更した内容をステージングに登録する
`add .`カレントのすべての変更ファイルをステージングに登録する

```sh
git add .
```
## git status

ステージングされたファイルの一覧を表示する

```sh
git status
```
## git commit

```sh
git commit -m 'コメント'
```
テキストエディタを起動して複数行コメントを入れる場合
以下でデフォルトで設定されているエディタが起動される
起動したエディタでコメントを入力後保存して閉じるとコミットが実行される

```sh
git commit
```
## git push

```sh
git push origin <branch>
```
## git branch

ローカルブランチのみ表示する

```sh
git branch
```

リモート・ローカルブランチ全部表示する

```sh
git branch -a
```

## git checkout

リモートからブランチをチェックアウトしてローカルブランチを新たに作成する

```sh
git checkout -b <local branch> <remote branch>
```
:::note info
現在は`git swich`コマンドが良いらしい
別途記載予定
:::

## git swich 

記載予定

## 参考にしたサイト

- [チートシート](https://training.github.com/downloads/ja/github-git-cheat-sheet/)

- [Git Docs](https://docs.github.com/ja)
CNNの特性を知らずに使って，あなたがCNNに畳み込まれるその前に

# はじめに
以前先人様の忠告により [vim を矢印キーで利用していたせいで命を狙われた経験](https://qiita.com/fasahina/items/2767891134028648f288)をしたので，失態は犯すまいと思っていたのだが，今度は仲間だと思っていた CNN に命を狙われてしまうことになったのでこれを遺言として書き記しておく．

私が背負ってしまった罪とは，**CNN の畳み込み層とは画像内で行列ライクな窓を掛け算しながらただラスタスキャンっぽく動かすと画像の特徴が得られる便利屋だと思っていた**というものである．5 年以上も CNN を使っておきながら，完全に特性を忘れてしまっていたのである．

あなたが今これを読んでいるということは，私と同じ罪を犯していたということであろうか．今すぐ CNN から離れて今一度 CNN の特性を学ばなければあなたは **3dConvolution によって執拗に畳み込まれて人間かどうかを判定するだけのバイナリ情報として一生を終える** ことになってしまう．

# CNN の畳み込み層で忘れてはいけない特徴
もちろん，CNN の畳み込み層では窓と局所領域との積を基に特徴を取り出していたのだが，私は彼らの真の姿を失念していたのである．
1. **受容野**
2. **パラメータ共有**

これらの特性なしで CNN を語ることはできない．

## 1. 受容野について
もしも CNN のことを
> CNN とは画像内で行列ライクな窓を掛け算しながらラスタスキャンっぽく動かすと特徴が得られる便利屋

だと本当に考えたとしよう．この時に必要なパラメータ数はいくつになるだろうか？一つの層を遷移する度に必要なパラメータ数を検討しよう．
```math
\mbox{(パラメータ数)} = W × H × C × \mbox{(次層のノード数)}
```
ということになる．例えば $640×480$ の画像を入力したとして，次のノード 1 つあたり $307200$ のパラメータが必要になる．こんなことをしていては，**使っている PC のメモリのヒートシンクが溶け出してしまい，PC のマザーボードにガウシアンフィルタが掛かってしまう．**
そのため，CNN で畳み込みを行うときは各遷移先のニューロン (ノード) の受容野の大きさを制限するのである．**遷移先に全ての情報を入れるわけでは決してない．**
そのため，例えば $640×480$ の画像を入力したとしても，受容野の大きさを $3×3$ にしていれば，ノード1つあたりたった $9$ のパラメータで済むのである．~~これには肖像権周りで抗議を起こしている Lenna さんもサンプル画像の時のような笑顔を取り戻してくれるに違いない．~~

## 2. パラメータ共有について
さらに罪が深いのはパラメータ共有に関しても失念してしまっていたことである．
この役割は簡単に言えば **ある目的に使われたフィルタは，場所に拠らず再利用できる可能性がある** というものである．パラメータを共有しないということは，小学校で使った "お道具箱" を授業のたびに買い換えているようなものである．そんなことをしている間に**あなたの使っている CPU のグリスが溶け出してマザーボードにソーベルフィルタが掛かってしまう**．そのまま利用したお道具箱を次の授業でも引き続き使えばいいのである．
つまり， **同じ畳み込み層においては受容野を適用する場所それぞれに対して重みを更新するのではなく，共通のものを使えばいい**ということである．丸を検出するために用いられるフィルタがあったとして，それは画像内の他の位置の丸を検出するのにも有用な可能性が高いのだ．

## 使っているものの特性を忘れると牙を剥く
便利な PyTorch や Tensorflow といったパッケージばかりを利用していると，どうしてもその内部がどうなっているか感謝を忘れてしまうものである．
この記事を読んだ人は今回のカルマを通じて学び得た教訓を活かし，周囲の人に感謝を伝えるようにしよう．そして，あなたが畳み込まれてしまうその日までに一緒に画像データとして写真を生成しておきましょう．

感謝

2022.05.04

# 参考文献：Vim を矢印キーで操作してしまったせいでこの世を去った先人様の記事
https://qiita.com/fasahina/items/2767891134028648f288
【WebRTC】基本事項まとめ(STUN, TURN, SDP, ICEなど)

# はじめに
最近、アプリでTwilio通話を実装したり、リモートワークやインサイドセールス向けのサービス開発のお話をいただくことがあったり、何かとWebRTC関連に縁があったので、GWに改めて勉強してみました。
今回は基本事項のまとめとなります。

# WebRTCとは
WebRTCは、ブラウザやアプリ間で音声や映像など大容量のデジタルデータをリアルタイムに送受信する(P2P)技術で、HTMLのAPIのひとつです。
また、不特定多数の人がファイルなどを送受信することが可能な仕組みが備わっており、ZoomやGoogle Meet、Discordなどで使われています。


# 構成
WebRTC接続に必要な構成は以下のようになります。
![スクリーンショット 2022-05-04 20.50.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/be673755-725c-8bfa-cd08-29af1dff3f38.png)

## Signalingサーバ
Signalingサーバは、接続を確立したいユーザ間で、通信に必要な情報(SDP, ICE candidates)を交換するのをサポートする役割を担います。
情報のやりとりには、WebSocketやXMLHttpRequestを使用することができます。

## STUN(Session Traversal Utilities for NAT)サーバ
STUNサーバは、外部ネットワークから見た際の自端末のIPアドレスを返します。
NAT内にいる場合は、自端末の知っているIPアドレス(プライベートIP)とSTUNサーバの返すIPアドレス(パブリックIP)が異なるため、これによってNATの有無を判別することができます。
NATが存在する場合、P2P通信の確立にTURNサーバが必要となります。

## TURNサーバ
TURNサーバは、NATが存在する場合にP2P通信をしたい端末間でデータをリレーするものです。

## SDP(Session Description Protocol)
SDPは、セッションの告知や招待を目的として、マルチメディアセッションの開始に必要な情報を記述するためのフォーマットです。
端末間の差異を吸収して最適な通話設定をするために、SDPのやりとり(通信要件のすりあわせ)を行う必要があります。

## ICE(Interactive Connectivity Establishment)
ICEは、STUNサーバやTURNサーバを相互で使いながら端末間で接続を行う技術です。
P2P通信を確立するには，端末間でSDPとICE candidatesの交換が必要となります。

ICE candidatesには以下が含まれます。

- IPアドレス
- プロトコル(TCP/UDP)
- ポート番号
- コンポーネント
- タイプ
- 優先度
- ファウンデーション
- ベース
など

# 接続フロー
接続までのフローを簡単にまとめると以下のようになります。

- WebRTC offer(Caller→Callee)
- WebRTC answer(Callee→Caller)
- ICE candidatesの交換
- 接続

![スクリーンショット 2022-05-04 21.11.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/a194b419-0be7-77f5-c48f-8b86b3d23d4b.png)

# 参考資料

https://www.udemy.com/share/105jzc3@hGHRmfKCMpZUnY0WB4nESzkVe_uwNAB2KT4rUY0mAPUpgiZls1oK-GyDKOcgjp70/

https://qiita.com/okyk/items/a405f827e23cb9ef3bde

https://jp.vcube.com/sdk/blog/webrtc-general-server-configuration-signaling-turn-sfu.html
Jetson AGX で Ethernet が途切れるメモ

Jetson AGX で
 
```
[ 5145.015350] eqos 2490000.ether_qos eth0: Link is Up - 1Gbps/Full - flow control rx/tx
[ 5275.326210] eqos 2490000.ether_qos eth0: Link is Down
```

と頻繁にでる...

チップセットとスイッチ周りとかとの問題っぽい?

https://forums.developer.nvidia.com/t/ethernet-connectivity-issues/49020/25

とりあえず接続スピードが重要でなければ, 100 Mbps に落とすので解決できるっぽい.

```
sudo ethtool -s eth0 speed 100 duplex full autoneg off
```
<備忘録>Git初期設定とGitHub

こんにちは
未経験でweb系エンジニアに転職を目指すものです。

今回はGitの初期設定をしてGitHubにデプロイしていこうと思います。
よろしくお願いします。

# Git初期設定
※GitHubに登録してあることを前提にしています。

まず、
PCにgitで使用する名前を登録します。

```
$ git config --global user.name "[GitHubで登録したユーザーネーム]"
```

次にメールアドレスを登録します。
```
$ git config --global user.email "[GitHubで登録したメールアドレス]"
```

登録されたことを確認します。
```
$ git config --list
user.name=[GitHubで登録したユーザーネーム]
user.email=[GitHubで登録したメールアドレス]
```
この初期設定はPC１台につき一回で大丈夫です。

# ローカルリポジトリ作成

ローカルリポジトリを作成します。

が、その前に
このままリポジトリを作成してしまうと、
デフォルトのブランチ名がmasterになってしまいます。
昔はmasterを使っていたらしいのですが、
今はmainを使うのが正しいというか、
好ましいそうです。

```
$ git config --global init.defaultBranch main
```
で変更し
```
$ git init
```
で作成します。

# リモートリポジトリ作成
続いて、
リモートリポジトリをGitHubに作っていこうと
思います。

１GitHubにログインします。
２右上の「＋」から[New repository]を選択します。
３「Repository name」に好きなリポジトリーの名前を入力します。
４「Public」または[private]を選択します。（文字通りみんなに公開するか未公開にするか）
5「Create　repository」を押す。
以上でリモートリポジトリが作成されました。

続いて、
リモートリポジトリを
現在の作業ディレクトリに紐づけます。
HTTPSとSSHで繋げる方法がありますが
今回はHTTPSでやっていきます。

先ほど作成したリモートリポジトリを
GitHubで開きます。
```
$ git remote add origin https://github.com/[ユーザーネーム]/[リモートリポジトリ名]
```
という行を見つけて、
ターミナルにコピペして叩きます。



## git addとcommit
gitはローカルリポジトリにコミット（変更を反映）させる前に
ステージングエリアという場所に変更内容を追加します。
この移動させる作業を「git add」で行います。
```
$ git add -A
```
-Aとは「git add」のオプションで全てのファイルの変更を
追加します。

ステージングエリアの内容をローカルリポジトリに
反映させるのが「git commit」です。
```
$ git commit -m "コメント"
```
-mはコメントを追加できるオプションです。

#push
いよいよリモートリポジトリ（GitHub）に
pushしていきます。
```
# git push -u origin main
```
詳しく解説すると
このコマンドを打ったディレクトリの
ローカルリポジトリの内容を
origin（リモートリポジトリ）の
main（デェフォルトのブランチ）に
pushしてね。
あと-uというオプションで
以降pushするときは
origin mainの部分を省略して
git pushだけにできる
という意味です。

GitHubを見てみてください
成功していれば
ローカルリポジトリの内容が反映されているはずです。

# 最後に
お疲れ様でした。
コードのバージョン管理や、
もしものこと
変更の履歴を残すことが
gitの役割だと思っています。

適切なpushをしていきたいと思います。
ありがとうございました。
C言語開発環境をDocker+VS Codeで構築する


## 環境
- Windows 11 WSL2 Debian bullseye
- Docker version 20.10.11
- VS Codeバージョン: 1.66.2

VS Codeには[Remote \- Containers 拡張機能](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)をインストールしておきます。ほかは必要ありません。

## 手順
### DockerでC言語を実行

まず`Dockerfile`を用意します。

```Dockerfile:Dockerfile
FROM debian:bullseye-slim
WORKDIR /app

RUN apt-get update && apt-get install -y \
    git \
    gcc \
    gdb \
  && apt-get clean \
  && rm -rf /var/lib/apt/lists/*

CMD /bin/sh -c "echo '準備完了' && sleep infinity"
```

`apt-get`はお好みで`build-essential`で必要なものをまとめて入れてもいいと思います。

適当なプログラムを記述します。

```main.c
# include <stdio.h>

int main()
{
  printf("Hello, world.\n");

  return 0;
}
```

Dockerでコンテナをビルドして、実行してみます。

```sh
$ docker build . -t myclang
$ docker run --name myclang --interactive --tty --rm --volume $(pwd):/app myclang bash
```

コンテナ内で、`gcc`コマンドでプログラムをコンパイルして実行できます。

```
# gcc main.c -o main
# ./main
```

`Hello, world.`と表示されたら成功です。

### VS CodeでC言語の開発

Dockerコンテナが実行中の間に、VS Codeを起動して、コマンドパレットを起動（Ctrl+Shift+P）して、`>Remote-Containers: Attach to Running Container...`を実行すると、VS Codeを起動中のコンテナにアタッチできます。

[C/C\+\+ Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools-extension-pack)拡張機能をコンテナ内にインストールします。`.vscode/extensions.json`をセットしておけば再度コンテナをビルドした時も推奨の拡張機能として表示されます。

```.vscode/extensions.json
{
  "recommendations": [
    "ms-vscode.cpptools-extension-pack"
  ]
}
```

VS Codeのコマンドパレットから`>View: Show 実行とデバッグ`を実行し、サイドパネルから「実行とデバッグ」→`C++ (GDB/LLDB)`→`C/C++: gcc-10`で、デバッグできます。ブレークポイントを貼ったりできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50391/ecfa362d-fd5e-baad-d006-17bb66f892ed.png)

今回構築したプロジェクトのソースコードはGitHubにあります。

https://github.com/s2terminal/clang-sandbox

## 参考
- [放送大学「アルゴリズムとプログラミング（’２０）」](https://bangumi.ouj.ac.jp/v4/bslife/detail/15704201.html) 印刷教材
iPaas/Make（旧Integromat）で「そろそろあの打ち合わせの準備しないとね」とLINE通知してもらう

# Make（旧Integromat）×Google Calender／「そろそろ例の準備しないと」を必要な人たちに自動でお知らせ
iPaas「[Make](https://www.make.com/en)」を使って、必要な書類を事前に揃えておかなきゃいけないなど、「**重要な打ち合わせ予定を必要なメンバーにLINEでリマインドしてくれる**」を自動化してみたよ。
[Make](https://www.make.com/en)を使った自動化のパート１記事はこちら↓
[Make(元Integromat)×Google Driveで「皆、締め切りまでにファイルを共有にアップして！」の確認ストレスをゼロに](https://qiita.com/7ENDO/items/24d93d2876fd50533c26)
## Google Calenderの特定ワードを拾って、予定をLINE通知してくれる
私は会社を経営しているが、経費周りの事務処理が壊滅的に苦手。
奇しくもまもなく税理士さんとの超重要打ち合わせがあり、それまでに私は色んな領収書や書類を整理しなければならない。（苦行）しかも私だけでなく、関わる全員がこれを準備しておかないといけない。こういう、**事前にけっこうな量と手間の準備が必要な打ち合わせ**を、全員に勝手にお知らせしてくれたら！「仕方ない。今日からやるか…」ときっとなる（かもしれない）。

### モジュールでカンタン紐付け
左がGoogle Calender、右がLINE Notify（今回はテストでNotifyにしたけど、特定のLINEグループに送れる）
![スクリーンショット 2022-05-02 225433.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2573810/7ebe7a27-2e40-e087-fd5d-91c409a6cb13.png)
Google Calenderから指定のワードの予定を拾ってくるよう指示。今回は「税理士さんの名前」をキーワードにした。
![スクリーンショット 2022-05-02 225541.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2573810/826d7b72-8f6a-6647-8337-054d8a72fa8b.png)
LINE Notifyと紐付け。
![スクリーンショット 2022-05-02 225612.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2573810/f8dd852d-e754-a3df-62d3-6fffc7e83934.png)
これだけ！！！！
## コレ便利じゃない？～フィードバックもらった～
### デザイナー兼写真家の友人
プロフ：断食リトリートで出会った友人。精神的安定感半端ない。
**・自分に対してリマインド来るのはいい**
**・他の人にも勝手にリマインドが行くのはどうかな…**
みんなでお話をして、スケジュールを決めて、「ここでいったんリマインド入れますね」という話があるならいいけど、何もなく突然ラインが来ると急かされているみたいでイヤ。
**・自分の進めるペースでやりたい**
やらなきゃいけないのはもちろんわかってるけど、誰かのペースで決めた「何日前」に準備を促すようなLINEが来ると、ペースを乱される。
**・遠い予定なら効果的かも**
もしグループLINEにするんだったら、「長期的なプロジェクト」かつ「遠い予定」かつ「関わる人数が多い」とかだったら効果的だと思う。ただし、これも全員合意の上で。
**・心配ごと**
時と場合によっては、コレ（グループで使っちゃうと）追い詰めることにならない？
# プレゼンしてみた感想
「急かされてるみたいでイヤ」「ペースを乱される」「追い詰めかねない」は、盲点でした。良いことしかないじゃーん、と思ってた。でも友人の意見を聞いて、確かにあり得るな、と。
すごい気づき。

# プレゼンしてみて気が付いた改善点
「長期的なプロジェクト」「遠い予定」「関わる人数が多い」など、使用するTPOは必要かもしれないと思った。便利ではあるけど、扱い注意な自動化だったかも。
パワハラ体質の人に渡したら乱用されそう・・・
ARKitの３次元座標を画面上の２次元座標に変換する

# AR３次元座標が画面上の２次元座標のどのポイントに当たるのか

# ARKitで一発で取得

```swift
func session(_ session: ARSession, didUpdate frame: ARFrame) {
    let pointInDisplay = frame.camera.projectPoint(node.simdWorldPosition, orientation: .portrait, viewportSize: view.bound.size)
}
```

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLやARKitを使ったアプリを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
シェルスクリプトで、入力ファイルの２行目以降１行づつ扱いたい場合の備忘録

シェルスクリプトで、以下のようなファイルの２行目以降１行づつ扱いたい場合、

```csv:test.csv
player
xxx
yyy
zzz
```

以下のようにヒアドキュメントを利用して入力する

> https://e-words.jp/w/ヒアドキュメント.html
> ヒアドキュメントとは、プログラミング言語などの機能の一つで、特殊な記号などを含む文字列リテラルをソースコード中に記述するための特別な記法のこと。

```sh:test.sh
#!/bin/bash
DATA=`cat test.csv | tail -n +2`
while read line
do
  echo $line
done << FILE
$DATA
FILE
```

実行結果

```sh
$ bash test.sh
xxx
yyy
zzz
```

# 参考

https://www.server-memo.net/shellscript/read-file.html

https://qiita.com/take4s5i/items/e207cee4fb04385a9952
KeyError: Factory not registered:の解決方法

# この記事で伝えたいこと

`KeyError: Factory not registered: ...`というFactoryBotのエラーが出てこの記事にたどり着いた方へ。
あなたが作っているアプリはRailsアプリではありませんか？
もしそうなら、Gemfileに以下のように書いていませんか？

```ruby:Gemfile
# これは間違い!
gem 'factory_bot'
```

どちらもYesなら、以下のように **factory_bot_rails** を使うようにすることで `KeyError: Factory not registered` が起こらなくなると思いますので、お試しください。

```diff_ruby:Gemfile
- gem 'factory_bot'
+ gem 'factory_bot_rails'
```

# もっとくわしく

## この記事を書いた経緯

RailsにFactoryBotを入れる場合、本来は **factory_bot_rails** を使うべきですが、**factory_bot** を使ってしまったことで `KeyError: Factory not registered` が起こりました。
このエラーに対して当初は誤った対処をしてしまいましたが、有識者の方に教えていただいたことで正しい対処方法が分かりました。
そこで、もし私と同じようなルートを辿る方がいらしたら、この記事が役に立つといいなと思って書きました。

## やりたかったこと

RailsアプリでFactoryBotを利用したい。

## やったこと

1. Gemfileに`gem 'factoy_bot'`を追加する 👈**ここが間違い**
1. ファクトリを作成する
1. テストファイル（またはスペックファイル）を書く
   ※この時に私が使ったのはMinitestでしたが、RSpecでも同様の事象が発生することを確認しました
1. テスト（またはスペック）を実行する

## 発生したエラー

```console:minitestの場合の例
KeyError: Factory not registered: "user"
    test/models/user_test.rb:8:in `block in <class:UserTest>'  

rails test test/models/user_test.rb:7
```

```console:RSpecの場合の例
KeyError:
 Factory not registered: "user"
# ./spec/models/user_spec.rb:5:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# KeyError:
#   key not found: "user"
#   ./spec/models/user_spec.rb:5:in `block (2 levels) in <top (required)>'
```

## 誤った対処

テストでファクトリを呼び出す前に `FactoryBot.reload` すると良いという情報にたどりつき、その情報が自分の状況に合ったものかよく確かめないまま真似しました。
確かに動くようになるものの、毎回リロードしないといけないなんて何だか変な気が…🤔

### minitestの例

```ruby
# これは間違い!
setup do
  FactoryBot.reload
  @user = create(:user)
end
```

### RSpecの例

```ruby
# これは間違い!
RSpec.configure do |config|
   config.before(:all) do
     FactoryBot.reload
   end
end
```

## 正しい対処

Rails向けに作られた**factoy_bot_rails**を使うようにすることで、`FactoryBot.reload`がなくても動くようになりました。[^1]

```diff_ruby:Gemfile
- gem 'factory_bot'
+ gem 'factory_bot_rails'
```

# 教訓

実はfactoy_botのREADMEには、しっかりこの事が書いてありました。

[thoughtbot/factory_bot: A library for setting up Ruby objects as test data.](https://github.com/thoughtbot/factory_bot#factory_bot---)
> If you want to use factory\_bot with Rails, see [factory\_bot\_rails](https://github.com/thoughtbot/factory_bot_rails).
拙訳：もしあなたがRailsでfactory_botを使いたいなら、factory_bot_railsのページを見てください

gemにしても何にしても、誰かが作ってくれた仕組みを使わせてもらう時はREADMEの冒頭くらいは目を通しましょう、という事を身をもって理解できた出来事でした

# 最後に

この記事で書いた一連の流れは、フィヨルドブートキャンプの課題に取り組んでいる際にぶつかり、提出した課題をレビューしていただいたことで分かった事です。
今回レビューしてくださった @jnchito さん、ありがとうございます。
課題の方はまだ終わってないので引き続き取り組みます💪

[フィヨルドブートキャンプ](https://bootcamp.fjord.jp)よいとこ一度はおいで[^2]


[^1]: 正確には、factoy_bot_railsがリロードなども含めてRailsでFactoryBotを使うために必要な部分の面倒を見てくれているので、一々自分で書く必要がなくなるということのようです
[^2]: [草津よいとこ一度はおいで 草津節 歌詞の意味 草津温泉 湯もみ唄](http://www.worldfolksong.com/songbook/japan/minyo/kusatsubushi.htm)
猫のトイレ回数をLINEで送信し、自動でGoogleスプレットシートに転記する仕組みを作りました。

こんにちは。

私は猫を飼っています。（こっちゃん ♀ 10歳）
うちの猫はとても便秘気味です。
お薬を飲んだり、食事療法を取り入れていますが、便秘状態は変わらず・・・
通院する際に日々のトイレ回数を先生に報告していますが、
スケジュール帳に手書きで書いているため、スケジュール帳を忘れがちできっちり報告できずにいます。
（なんだったら、記入するのも忘れがちです。）

なので、毎日使用するLINEからトイレ回数を送信し、
自動的にGoogleスプレットシートに転記してくれる仕組みを作りました。

## 作成したもの・使用したもの
今回はMakeを使用して作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/efb5774e-22d6-c692-822f-33de16437a5b.png)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/3a9ef1b0-ec94-8a41-d12c-cdebfc0aee25.png" width="400" height="200">

**LINEで送ると・・・**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/32f07fdd-b68d-f524-a298-cba8b34efd40.png)
**このようにGoogleスプレットシートに転記されます。**



## 事前に準備すること
Make・LINE Developersの登録をしてください。

:::note alert
**Makeを登録する際、Googleアカウント等の別アカウントでログインする場合は、
絶対にログアウトをしないでください。**
ログアウトすると再ログインできなくなりました・・・
Makeを登録する際は、ご自身でパスワード・メールアドレスを新規登録をすることをお勧めします。
:::

また、LINE Developersの登録後、チャネル作成が必要です。

https://www.youtube.com/watch?v=NMdgJ3MuDTM&t=943s

今回はチャネル・LINEBot作成はこちらのYouTubeの8分00秒～14分45秒を参考にしました。



## LINE Watch Eventsの設定
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/a5cb4a6f-bc1e-df41-8da0-c1951400508e.png" width="400" height="200">

## LINE Send a Reply Messageの設定
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/66f8d840-e486-125c-c1b3-087a0b624b7c.png" width="400" height="200">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/91b906dd-0aa7-91e8-7fe6-3a29ef44166b.png" width="400" height="200">

## Google Sheets Add a Rowの設定
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/1f2c6ae4-fc39-cd9a-5621-528901eabe2e.png" width="400" height="200">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/178c6eaa-9f94-02a9-ee64-4abe63b87b04.png" width="400" height="200">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1811930/cd54324f-399e-dfed-668b-da9be7956331.png" width="400" height="200">

## 家族と最近ペットを飼い始めた友人からFBもらいました。
・猫のトイレ確認でなくてもいろんなところに応用できそう。
（成長記録とか書けそうだよね。思いついたことを書けるのでもいいよね。）
・メモと一緒に写真も送って記録残したいなー
・複数ペット飼っている場合はどうするの？
　LINEのメッセージを分けて記録するのもめんどくさいから、
　1つのLINEページで複数のペット記録を書けると助かるな～


## 最後に

一旦完成したときに、
LINEからメッセージを送ってGoogleスプレットシートに転記するだけでは、
本当に転記されているのか不安になり、
LINEBotから「入力しました！」と返信が来るように設定。
これでちゃんと転記されたんだな！という気持ちになります！

あと、FBもらいながら、私もいろんなことに応用できそうだなって思いました。
LINE繋げるが苦手で今まで本当にできなかったから、
こんな簡単に繋げられるのがありがたい・・・
次は、写真も一緒に転記できるようにしたと思います！！

Make使いこなせるようになると本当に便利ですね。
最後まで読んでいただきありがとうございました。
Apache / Nginxを調べたまとめ

# ミドルウェア
ミドルウェアは、ソフトウェアの一種であり、コンピュータの構成する一つの要素となっています。
ミドルウェアの働きがあることで、コンピュータは複雑な処理を行うことできます。



![Apache_nginx-コンピュータ構成要素.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237088/30d0a2ec-5616-5be7-9c4a-59f94e818b41.png)




コンピュータ（ハードウェア）には、OSが搭載されています。
OSは汎用的な機能を担いますが、それだけでアプリケーション（chromeやExcelなど）を動かしているわけではなく、ミドルウェアが中間に入ってOSとアプリケーションの橋渡しをしています。


## ミドルウェアの種類
ミドルウェアには「webサーバー」、「アプリケーションサーバー」、「データベース管理サーバー」の三種類があります。
上記をweb三層構造と呼んだりします。

### webサーバー
我々が普段パソコンやスマホで見ているコンテンツは、webサーバーにアクセスして送られてきた文字・画像の集まりです。
「このページが見たい」とリクエストすればwebサーバーが返してくれます（レスポンス）。
誰が見ても同じ内容である「静的コンテンツ」や、ショッピングサイトのカートのような見る人によって内容が変わる「動的コンテンツ」も返してくれます（動的コンテンツはwebサーバーがアプリケーションサーバーへコンテンツを要求する必要がある）。

![Apache_nginx-webサーバーとの連携.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237088/ab5a8577-51a8-7366-4283-41fd2defa49b.png)



そして、webサーバーで代表的な製品が**Apache**と**nginx**です。


# Apacheとは

無料（オープンソース）で使用可能なwebサーバーソフトウェア。
正式には、「Apache HTTP Server」という名称である。
1995年に公開されて現在でも利用されていることから、人気のwebサーバーであることがうかがえる。

（技術の移り変わりが激しい業界で、それだけ使われているのはすごいことだなと思います）

## メリット

### 無料で利用可能
先ほど述べた通り無料で使えるので、コスト面でメリットがある。

### 主要なOSで使用できる
Mac / Windows / Linuxといった主要なOSで使える汎用性の高さもメリットの一つ。

### 豊富な機能
長年人気を博してきたApacheには拡張機能のためのモジュールが数多く用意されています。

### 処理が早く安定している
処理速度が速く安定していることから、ホームページの表示やコンテンツの動作についてもスムーズ。

## デメリット

### リクエストが多いと動作が重くなりがち
Apacheはマルチプロセスであり、リクエストが大量の場合にプロセスが同時に複数起動する。そうなるとオーバーヘッド（負荷処理）が大きくなりメモリを大量消費することになる。
結果動作が重くなったりする(※C10K問題)。

（※サーバー性能に問題がなくてもクライアントの同時接続数が一定数を超えるとサーバーがパンクして応答が遅くなること。「C」はクライアント、「10K」は1万台を表す。だからといって、クライアントの同時接続数が1万台に達したら起こるわけではないですが、、）

### サポートや保証がない
オープンソースであるため、トラブル発生時の対応はユーザーに求められる。（ただ、長きにわたり多くの方に利用されている分、webで検索すれば対応方法がヒットすることもあり、自己でトラブルシューティングが可能かも）

# Nginx（エンジンエックス）とは

webサーバーのシェア率はApacheと同じくらい普及しており、AdobeやCyberAgentといった企業も利用しています（細かく述べると[Nginx Plus](https://www.nginx.co.jp/products/nginx/) を利用）。
OSS（オープンソースソフトウェア）で無料版を使用することができ、OSSの機能を拡張した有料版（先ほどの[Nginx Plus](https://www.nginx.co.jp/products/nginx/)）もあります。

## メリット

### OSSなら無料で使える
無料版があるので、とりあえず使ってみるのもあり。有料版との機能の比較はNginx Plus で確認できる。

### 大量のリクエストを処理できる
Apacheとよく比較されているところですが、Nginxは大量同時接続に対して強い。（C10K問題に対応している）

### リバースプロキシとしても動作する
設定ファイル（/etc/nginx/conf.d）にプロキシ設定を記載して、リバースプロキシとして使用する。

## デメリット

### CPUリソースを沢山消費する処理に弱い
アプリケーション実行や動画などの処理には不向き。

### Nginx単体で完結させるのは難しい
PHPなどのスクリプト言語処理の機能がない。


# Apache・nginxのメリット・デメリットのまとめ表

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237088/415f77e1-94f0-d27e-0790-b04ef9ae25d6.png)
【新卒必見】エンジニアにいる２つの人種

エンジニア３年目の人間として新卒に教えたい、エンジニアには２つの種類の人間がいるってことを。
# ソースコードを組む人
一般的にエンジニアとかプログラマーと言われるとこのソースコードお組む人ばかりであると感じる人も多いかもしれない。実は案外このエンジニア、使い捨て扱いされてしまうことも多々ある。結構面倒なコードでもスパゲッティコードになっていることさえ許容してしまえば、案外誰でも組むことは可能であったりする。ただし、スパゲッティコードの最大のデメリットは計算回数が多くなってしまったり、意図しない動作が発生することであり、今のAIの技術では全然プログラマーには叶わない。

# 設計書ばっかり書く人
実は目立たないが、こういう設計書を起こせる人のほうがソースコードを書く人よりも社会的な評価は高かったりする。ソースコードは誰でも指示さえしてくれれば書くことはできるかもしれないが、設計書をちゃんと組んで、それをプログラマーに指示を出せる人は少なかったりする。
いわゆる社内SEと言われる人達もここに含まれることも多い。

# どっちのほうがいいの？
設計書ばっかり書く人のほうが会社としてはよい評価をもらえる場合が多い。ソースコードをうまく書ける人の評価は案外低い場合もある。なので、、、。でも、恐ろしく早いソースコードをなるべく計算量をすくなくするように書くことができる一部の人やポインター制御をうまくできる人など特殊な技能に関して今後も重要視されるのではないかと考える。
Kali Linux2022.1 でハッキングラボをつくってみる 7　Metasploitable2をハッキングする1 Metasploitableの導入

# はじめに
今回から、Metasploitable2へのハッキングを行っていく。
Metasploitable2は、セキュリティの学習用に作られた脆弱性のあるLinuxディストリビューションです。
基本的に、「ハッキング・ラボのつくりかた」(IPUSIRON著)に沿って進めるが、余裕があれば、同書では取り上げられていないハッキングや同ディストリビューションの後継であるMetasploitable３へのハッキングも行っていきたい。
今回は、同書のP.366-370を参考にした。

:::note alert
注意事項
記事で紹介されている行為を他人や団体、インフラなどの許可を得ずに行った場合、犯罪となる可能性が有ります。
あくまでも、記事の内容は情報セキュリティの学習です。読者様の所有・管理の機器、システムでのみ実行してください。
また、読者さまのシステムにトラブルが起きたとしても、私は責任を負いかねます。
:::
# Metaspoitable2の導入
まずは、Metasploitable2をダウンロードする。
[ダウンロードページ](https://sourceforge.net/projects/metasploitable/files/latest/download)
ダウンロードした圧縮ファイルを解凍した後、vmdkファイルが展開後のフォルダ内にあることを確認する。
VirtualBoxでマシンを新規作成する。
設定ウィザードでハードディスクを選択する際には、"Metasploitable.vmdk"ファイルを選択する。また、マシン作成後にネットワークを「ホストオンリアダプタ」に指定する。

- 起動とログイン

起動する。
ログイン画面になったら、 IDを"msfadmin",パスワードを"msfadmin"と入力してログインする。
- 日本語キーボードにする

この方法でも、再起動後にもとに戻る。
```
sudo loadkeys jp
```

- 静的ローカルIPアドレスを設定する

```
sudo vim /etc/network/interfaces
```
interfacesファイルを以下の内容に変更する
```shell:/etc/network/interfaces
auto lo
#iface eth0 inet dhcp
iface eth0 inet static
address 192.168.56.5
netmask 255.255.255.0
gateway 192.168.56.1
```
"iface eth0 inet dhcp"はコメントアウト、addressには適当なホストオンリアダプタのローカルIPアドレスを指定した。
次のコマンドで、networkingを再起動して、ipアドレスが変更されているかを確認する。
```
sudo /etc/init.d/networking restart
ifconfig
```
:::note
Metasploitable2には、デフォルトではsystemdは導入されていない。
`systemctl`コマンドは利用不可。

`loadkeys jp`を自動起動したいなら、"/etc/rc.local"ファイルの最終行"exit 0"の前の行に`loadkeys jp`を追加しておく。
:::

ネットワーク構成は次のようになる
- 攻撃(KaliLinux2022.1)
    - ホストオンリーアダプタ(必須) : 192.168.56.2 静的
    - NAT : 10.0.3.15

- やられ・ターゲット(Metasploitable2)
    - ホストオンリアダプタ（必須) : 192.168.56.5 静的

- ホストOS
    - ホストオンリアダプタ : 192.168.56.1

それぞれのマシンにpingが通るか確認する。
```
ping 192.168.56.1
ping 192.168.56.2
```