OmniAICreator/Qiita-1.07M huggingface dataset:
2023/1/8主にITとかセキュリティの記事

EC事業者の6割弱がサイバー攻撃の被害経験 - 半数で情報漏洩
https://www.security-next.com/142602

医療従事者向け求人サイトにサイバー攻撃 - 個人情報が流出
https://www.security-next.com/142687

宅食サービス会社がランサム被害 - 顧客情報流出の可能性も
https://www.security-next.com/142689

23年金融行政　資産所得倍増へ足固め、デジタル金融に力  イチからわかる金融(1/7)
https://www.nikkei.com/article/DGXZQOUB055N20V00C23A1000000/

クッキーに同意、どんな意味？　サイト閲覧者の情報保護 親子スクール・ニュースイチから(1/7)
https://www.nikkei.com/article/DGXZQOUD088MI0Y2A201C2000000/

標的企業をロックオン　ランサムウエア攻撃はなぜ怖い？
ラック　サイバー救急センター「ランサムウエアから会社を守る」（1）(1/7)
https://www.nikkei.com/article/DGXZQOUC125DH0S2A211C2000000/

米システム開発支援のCircleCI、サイバー被害を公表(1/6)
https://www.nikkei.com/article/DGXZQOUC069QR0W3A100C2000000/

Windows 11 22H2でエクスプローラーがランダムにポップアップする問題(1/6)
https://news.mynavi.jp/techplus/article/20230106-2555321/

富士通、人の急な方向転換や加減速にも対応可能な新トラッキング技術を開発(1/6)
https://news.mynavi.jp/techplus/article/20230106-2555421/

Google、Androidの脆弱性に関する2023年1月のセキュリティ情報公開(1/6)
https://news.mynavi.jp/techplus/article/20230106-2555253/

SREの定義・役割・メリットとは？DevOpsと何が違う？(1/6)
https://news.mynavi.jp/techplus/article/20230106-2555366/

Windowsで使うUbuntuのユーザーとは？(1/6)
https://news.mynavi.jp/techplus/article/ubuntu-on-windows-11/

ChatGPTなどのAIで科学論文を書くことが国際会議で禁止に、ただし自分の文章の編集・推敲はOK(1/6)
https://gigazine.net/news/20230106-chatgpt-ai-writing-tool-banned/

「iPhone」や「Android」端末を紛失してしまったら--GPSで追跡して発見するには(1/7)
https://japan.zdnet.com/article/35198244/

「Slack」のソースコードが流出 ～顧客データは無事、サービスにも影響なし
社員の「GitHub」トークンが盗まれる(1/6)
https://forest.watch.impress.co.jp/docs/news/1468575.html

Windows 7、バージョン別シェアで10%を超えたまま2022年を終える(1/6)
https://www.zaikei.co.jp/article/20230106/704645.html

ヤマト運輸、同社をかたる迷惑メールやSMSに注意喚起。SMSによる不在連絡や配達通知は「行っていない」(1/6)
https://internet.watch.impress.co.jp/docs/news/1468291.html

ツイッター個人情報流出か＝２億３５００万人分(1/6)
https://www.risktaisaku.com/articles/-/75725
【C#】DateTimeの和暦表示


# はじめに

`System.DateTime`を`R1.11.23`のように表示したい場面があり，少し苦戦したため備忘録を兼ねて方法をまとめておきます。

# 和暦表示

## 漢字

和暦を表示するだけであれば比較的簡単に行うことができます。
```C#
using System.Globalization;

var cultureJp = new CultureInfo("ja-jp", false);
cultureJp.DateTimeFormat.Calendar = new JapaneseCalendar();

var dt = new DateTime(2019, 11, 23);
Console.WriteLine(dt.ToString("ggy年M月d日", cultureJp));  // 令和元年11月23日
```

このように`g`または`gg`という書式指定子で元号を取得できます。
(この記事を書くときに知ったのですが1年ではなく元年になるのですね…[^1])

[^1]: `"y.M.d"`のようにすると`1.11.23`になりました。どうなってるんだ……

## アルファベット

ところが，RやHのようにアルファベットの略号で元号を表したい場合にはめんどくさいことになります。
アルファベット1文字の元号を表す書式指定子がないのです。

ところが，Microsoftが手を抜いて元号の略称を見なかったことにしたのかと言うとそうではなく，`DateTime.Parse`は元号の略称に対応しています。
例えば
```C#
var dt = DateTime.Parse("R1.11.23");  // [2019/11/23 0:00:00]
```

と言った感じの文字列を認識してくれます。
この非対称性は気持ち悪いのですが文句を言っていても仕方がないので受け入れるしかありません。

### 辞書による置換

極めて単純な解決策として，文字列の置換で強引に対応するというものがあります。
しかし，対応をハードコードしてしまうと改元の度に修正が必要になってしまうため，ベストプラクティスではないでしょう。

### 時代 (年号) を表す整数

.NET Frameworkでは元号を表す整数というものがあるそうです。
これが何かというと明治が1，大正が2，昭和が3……といった感じです。
アルファベット表記を実装するために，この整数を利用します。

この整数は，[`Calendar.GetEra`](https://learn.microsoft.com/ja-jp/dotnet/api/system.globalization.calendar.getera?view=net-7.0)メソッドにより取得できます。
```C#
var index = cultureJp.DateTimeFormat.GetEra(dt);  // 5 など
```

この整数を利用してアルファベットの略号を取得するのですが，その対応をハードコードしてしまっては意味がありません。

この整数は，[`DateTimeFormatInfo.GetEra`](https://learn.microsoft.com/ja-jp/dotnet/api/system.globalization.datetimeformatinfo.getera?view=net-7.0)なるメソッドでも取得することができます。
これは先ほどの`DateTime.Parse`と同様に略号を認識してくれるため，`"R"`を食わせると`5`を返してくれます。
このメソッドを利用して，整数と略号の対応を作っておきます。
```C#
var eras = new Dictionary<int, string>();
for (var e = 'A'; e <= 'Z'; e++)
{
    var E = e.ToString();
    var index = cultureJp.DateTimeFormat.GetEra(E);
    if (index > 0)
        eras.Add(index, E);
}
```

このメソッドはinvalidな元号(の略号)に対しては-1を返すため，整数と略号の対応を作ることができます。

このようにして対応を作っておけば，あとはこれを参照するだけです。
```C#
var e = cultureJp.DateTimeFormat.Calendar.GetEra(dt);
eras[e] + dt.ToString("y.M.d", cultureJp);  // R.1.11.23
```

# さいごに

元号周りは元々ややこしい話ではあるのですがもう少し使い勝手のいいライブラリが欲しいものです。

[JapaneseCalendar](https://referencesource.microsoft.com/#mscorlib/system/globalization/japanesecalendar.cs,26eaf83314817558)の実装を見てみるとすごいなぁという気持ちになります。

# 参考文献

- [カスタム日時形式文字列 | Microsoft Learn](https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/custom-date-and-time-format-strings#gSpecifier)
- [日付の年号を略称で表示するには？［C#、VB］：.NET TIPS - ＠IT](https://atmarkit.itmedia.co.jp/ait/articles/1506/10/news022.html)
Youtubeで音楽を聴いているときに出てくる「動画が一時停止されました。」を駆逐する

# Youtube「動画が一時停止されました。続きを視聴しますか？」←は？？？？？

作業中、youtubeを作業BGM代わりに使っている人は多いかと思います。こんな時、再生は止まってほしくないものです。ところが、しばらくバックグラウンドで再生していると、アレ、再生が止まったゾ...

>動画が一時停止されました。続きを視聴しますか？[OK]

__ふざけんな！！！！！(声だけ迫真)__

# Chormeの拡張機能を試す。

クロームの拡張機能(アドオン)を探したところ、下記がヒット。

https://chrome.google.com/webstore/detail/youtube-nonstop/nlkaejimjacpillmajjnopmpbkbnocid

当該ポップアップを消してくれるアドオンのようです。早速入れてみましたが、やはり停止される模様...。これはマクロを自作するしかないですね。JavaScriptはかけないので、アドオンを作るのは諦めて、pythonで実装することにしました。

# コード
プログラムは非常に単純です。例のポップアップの[OK]が出る場所を3秒に一回、自動でクリックするというものです。今回はマウスポインタを自動で動かすので、そのことを警告する画面も出します。また、Escキーでプログラムを終了する機能も付けようと思います。

```python:StopSkip.py
import time
import MouseControll
import keyboard
from concurrent.futures import ProcessPoolExecutor
import tkinter

# クールタイム
time.sleep(3)

# クリック連打したい座標
coo = [832, 448]

def win_disp() :
    # 無効化機能お知らせウインドウ表示
    root = tkinter.Tk()
    root.attributes("-topmost", True)
    w = tkinter.Label(root, text='Auto click macro is running!!!\nPush Esc key to quit', font=("normal", 20), fg = 'red', bg = 'black')
    w.pack()
    # ウィンドウを保持
    root.mainloop()

# 実際にクリックプロセス
def myclick() :
    while True :
        # 座標を引数にとってクリックする関数
        MouseControll.mouse_controll(coo)
        # 3秒間隔で連打
        time.sleep(3)

# ボタン待ち受けプロセス
def btn_detc() :
    while  True:
        # ESCキーを押すまでクリックし続ける
        if keyboard.read_key() == 'esc' :
            ############# 問題の箇所
            # ここでプログラムを終了させたい
            break


# マルチプロセス開始!!!
if __name__ == '__main__' :
    with ProcessPoolExecutor(3) as executor :
        executor.submit(myclick)
        executor.submit(win_disp)
        future = executor.submit(btn_detc)
        time.sleep(3)
        while True:
            if not future.running():
                break
        for process in executor._processes.values():
            process.kill()
```

```python:MouseControll.py
import pyautogui

def mouse_controll(coo) :
    pyautogui.click(coo[0], coo[1])
```

ファイル配置は、上記2つのpythonファイルを同じ階層(同一のフォルダ)に設置します。

コード内のクリックする座標`coo`は自分で特定する必要があります。

# 完成!!

完成しました。これ以降、例のポップアップに出会っていません＾＾

# 謝辞
こちらで有益な回答を頂きました。この場を借りて感謝申し上げます。

https://qiita.com/Jikao1919/questions/d6fc95e92ca92d6513b3#answer-56affc63487f5cc0b3ce
ラズパイにWordPressを構築するためのPHPモジュールを導入する

# 機能要件
WordPress構築に必要な機能要件は、以下のページに記載されている。

https://make.wordpress.org/hosting/handbook/server-environment/


| 必須モジュール | 初期導入済 | 内容 |
|:-:|:-:|:-|
| json | ○ | 他のサーバーとの通信やJSON形式のデータの処理に使用。PHP8.0以上なら標準でインストール済み。 |
| mysqli | ○ | MySQLやMariaDBとのデータ連携に必要。 |

| 必要モジュール | 初期導入済 | 内容 |
|:-:|:-:|:-|
| curl | | httpリクエストを扱うためのモジュール。 |
| dom | | DOM操作を可能にするためのモジュール。 |
| exif | ○ | 画像に保存されているメタデータを操作する。これを利用するためには関連モジュールであるmbstringのインストールも必要。 |
| fileinfo | ○ | ファイルのMIMEタイプ検知に使う。 |
| hash | ○ | パスワードや更新パッケージなどのハッシュ化に使用される。 |
| imagick | | メディアアップロードで使用されるらしい。 |
| mbstring | | UTF8の文字コードを適切に処理させるために必要。 |
| openssl | ○ | SSL通信に必要。 |
| pcre | ○ | コード検索でのパターンマッチングのパフォーマンスが向上するらしい。 |
| xml | △ | XML解析に使用される。上の方のモジュールを入れていたら、いつの間にか導入されていた。どのモジュールかの関連モジュールなのかな？ |
| zip | | プラグインやテーマ、WordPressの更新パッケージの解凍に使用される。|

| 推奨モジュール | 初期導入済 | 内容 |
|:-:|:-:|:-|
| memcached | | 分散型キャッシュシステムを構築する。 |
| opcache | | OPcacheとはコードをコンパイルし、共有メモリへ保存しておく仕組みだそう。 |
| redis | | Redisを扱うために使うそう。 |
| bc | | 任意精度の数値の計算ができるようになるらしい。 |
| filter | ○ | データの検証や除去に使うらしい。 |
| image | ○ | 画像系のモジュールみたい。画像の取り扱いや描いたり。|
| iconv | ○ | エンコードに使うみたい。 |
| intl | | ロケール関連の操作を行うものらしい。 |
| simplexml | | XML解析に使うらしい。 |
| sodium | ○ | 暗号化、復号化、署名、パスワード ハッシュなどで使う。 |
| xmlreader | | XML解析に使うらしい。 |
| zlib | ○ | Gzip圧縮や解凍に使う。 |
| ssh2 | | ファイル転送などに使う。 |
| ftp | ○ | FTPアクセスを実装する。 |
| sockets | ○ | ソケット通信に使うらしい。 |

推奨モジュールはなくてもいいのかな。

# 初期インストールされているモジュールを調べる
必須モジュールである、jsonとmysqliが標準で用意されていることが分かる。
```
# php -m
[PHP Modules]
calendar
Core
ctype
date
exif    # 必要モジュール
FFI
fileinfo    # 必要モジュール
filter    # 推奨モジュール
ftp    # 推奨モジュール
gettext
hash    # 必要モジュール
iconv    # 推奨モジュール
json    # 必須モジュール
libxml
mysqli    # 必須モジュール
mysqlnd
openssl    # 必要モジュール
pcntl
pcre    # 必要モジュール
PDO
pdo_mysql
Phar
posix
random
readline
Reflection
session
shmop
sockets    # 推奨モジュール
sodium    # 推奨モジュール
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
Zend OPcache
zlib    # 推奨モジュール

[Zend Modules]
Zend OPcache
```

# 足りないモジュールをインストールする
足りてないのはおそらく以下のモジュール。
推奨モジュールは入れてない。
Nginxを使いたい場合は、php-fmpを入れてもよい。
```
# apt install -y php8.2-curl
# apt install -y php8.2-dom
# apt install -y php8.2-mbstring
# apt install -y php8.2-imagick
# apt install -y php8.2-zip
# apt install -y php8.2-fpm
```
express error

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

https://casualdevelopers.com/tech-tips/how-to-fix-the-error-of-cannot-set-headers-after-they-are-sent-to-the-client/

この記事を参考にしました。

if文で、res.redirectしたとしても、returnしていなければ
if文後の処理も実行されている。
Java 入出力と例外

<h4>・入出力とは</h4>
　多くのプログラムは、そのプログラム単体で完結することが少なく、多くの場合は、データをプログラムの外から受け取り、そのデータを処理した結果をプログラムの外に出力する。さらに外部とのやりとりでは、プログラムが想定しないデータが入力されたり、そもそもデータが見つからないことがあります。これらの場合は例外として対応します。
        
<h4>・ファイルアクセスと例外</h4>
<h5>・ファイル書き込みの方法</h5>
　　ファイル書き込みのためにまず、ファイルを読み込む必要があります。そのために使われるメソッドは`Path.of`メソッドである。使い方としては引数に作りたいファイルのファイル名を指定します。ここに指定したファイル名のファイルがJavaのフォルダに作成されます。
<br><br>
　　次にファイルを書き込みしていきます。ファイル書き込みは`Files.writeString()`を使います。このメソッドは、ファイルに文字列を保存するメソッドです。引数の1番目にどのファイルに保存するか（Path.ofで設定する）、引数の2番目に書き込む文字列を設定します。
例：`Files.writeString(Path.of("OutPut.text"), "こんにちは、あるいはこんばんは")`

<h5>・ファイル読み込みの方法</h5>
　次にファイル読み込みの方法について述べていきます。ファイルの読み込みは同じく`Path.of`メソッドを使い、テキストの場所、名前を読み込みます。次に`Files.readString()`メソッドを使い文字列を読むことができます。
例：`Files.readString(Path.of("OutPut.text"))`

<h5>・ファイル操作に関するメソッドの例</h5>

| メソッド名 | 説明 |
|:----------|:-----|
|String readString(Path)|ファイルを文字列として読み込む|
|Path writeString(Path, String)|ファイルに文字列を書き込む|
|long size(Path) |ファイルサイズを得る |
|FileTime getLastModifiedTime(Path) | 最終更新日時を得る |
|boolean exists(Path) | ファイルがあるかどうかを確認する |
| boolean isDirectory(Path) | フォルダかどうか確認する |
| Stream<Path> list(Path) | ファイル一覧を得る |

<h4>・例外処理</h4>
　　　例外は、プログラムを動かしたがうまく動かなかった状態のことをいいます。そしてそれをthrowsで例外を押し付けたり、tryで例外に対処することを例外処理といいます。

<h5>・throws</h5>
　　　throwsは上の通り、例外を押し付けるものである。

```Java:throws.java
    void ThrowingException() throws 例外クラス名 {
      //処理
}
```

<h5>・try文、catch文、finally文</h5>
　　　try文、catch文は例外が起こった時にする処理を書くものである。try文では例外が起こらなかったときの処理を書いて、catch文では例外が起こったときの処理を書く。finally文は、例外が起きても起きなくても絶対にしたい処理を書く。

```Java:tryCatch.java
      void ThrowingException() throws 例外クラス名 {
                try {
        //例外が起きなかったときにしたい処理を書く
                } catch {
        //例外が起きた時の処理を書く
                } finally {
        //例外が起きても起きなくてもしたい処理を書く
    }
}
```
ABC284 F - ABCBAC ローリングハッシュ解法

# はじめに

見た瞬間に「あ、ローリングハッシュだ」と思ったものの、「実装どうするんだっけ…」で1時間椅子を温めました。ライブラリ貼り付けで済むならまだしも、ちょっといじろうとすると手になじませる必要がありそうなので、記事にしつつ理解を深めようと思います。

2023/1/8 19時ごろ追記:公式解説の通り後半を反転させる方が実装は楽ですね。まあ部分ハッシュを考えるというアイデアはどこかで活かせそうなのでこれはこれ、ということで。

## 問題

https://atcoder.jp/contests/abc284/tasks/abc284_f


## ACコード

https://atcoder.jp/contests/abc284/submissions/37856468

## 前提知識

ローリングハッシュ
https://qiita.com/hirominn/items/80464ee381c8d400725f

## 考察

さて、本問題ではTには左の文字列・真ん中の文字列（以下M）・右の文字列の3つの文字列が存在していますが、
左の文字列と右の文字列を結合した文字列（以下X)と、Mが一致するものが存在するかを問われている問題です。

愚直にやるのであれば、分割位置をずらしながら確認していくことになりますが、
1回ずらすごとに生成された長さNの文字列同士を一文字ずつ確認していくことになるので、O(N**2)になり間に合いません。
この文字列に対してハッシュを取ることで、文字列同士の一致を確認することを考えます。

まずは文字列Mについては、Tを反転させて考えるとローリングハッシュをそのまま適用でき、
1文字ずつずらした文字列のハッシュ列をO(N)で生成することができます。


次に、文字列Xについて考えます。
ここも工夫をするとハッシュを効率よく計算することが出来ます。

まず、ローリングハッシュの算出式を眺めてみます。
ローリングハッシュ算出用の素数をB,Mとし、
文字列`S`に対するローリングハッシュ関数`H(S)`は以下のようになります。

```math
H(S)=(S_1B^{N-1}+\cdots+S_{N-1}B^{1}+S_{N}) \ mod \ M
```

さて、具体的にN=4で、結合文字列`X`に対してハッシュを計算します。

```math
H(X)=(X_1B^{3}+X_2B^{2}+X_3B+X_{4}) \ mod \ M 
```
さらに、LをTの前半N文字、RをTの後半N文字とすると、問題文中のiを変化させていったときのH(X)は下記の通りになります。
```math
(L_1B^{3}+L_2B^{2}+L_3B+L_{4}) \ mod \ M\\
(L_1B^{3}+L_2B^{2}+L_3B+R_{4}) \ mod \ M\\
(L_1B^{3}+L_2B^{2}+R_3B+R_{4}) \ mod \ M\\
(L_1B^{3}+R_2B^{2}+R_3B+R_{4}) \ mod \ M\\
(R_1B^{3}+R_2B^{2}+R_3B+R_{4}) \ mod \ M\\
```
LとRと部分を足すことができるので、それぞれ個別に算出します。
```math
\begin{align}
(&L_1B^{3}+L_2B^{2}+L_3B+L_{4}&) \ mod \ M\\
(&L_1B^{3}+L_2B^{2}+L_3B&) \ mod \ M\\
(&L_1B^{3}+L_2B^{2}&) \ mod \ M\\
(&L_1B^{3}&) \ mod \ M\\
\end{align}
```
```math
\begin{align}
    (&&&&+R_{4}) \ mod \ M\\
    (&&&+R_3B&+R_{4}) \ mod \ M\\
    (&&+R_2B^{2}&+R_3B&+R_{4}) \ mod \ M\\
    (&R_1B^{3}&+R_2B^{2}&+R_3B&+R_{4}) \ mod \ M\\
\end{align}
```
※うまく整形できない…

これらは累積的に実行することで、O(N)で算出可能で、ローリングハッシュの部分ハッシュみたいなものが生成できます。
最後に、上記部分ハッシュから生成されたXのハッシュ列とMのハッシュ列が一致するかを確認すればＯＫです。
各計算はO(N)で実行可能なので、全体としてもO(N)になります。

## おわりに

ハッシュを部分的に算出できる、というのは面白い性質だなと思いました。
可能ならコンテスト中に解ききりたかったですが、苦労した分忘れないと思うので次に生かしたいと思います。
Vue Routerでログインしていないユーザーをログイン画面に遷移させる

## やりたこと
ログインを必要なページにログインしていないユーザーがアクセスした際にログイン画面に遷移させたい。

## 実現方法
Vue Routeでは、各ルートごとに任意の情報をmetaプロパティに設定できる。
ログイン必要有無(requiresAuth)を持たせて、ログインが必要なページにログインしていないユーザがアクセスした際は、beforeEachの処理でログイン画面に遷移させる。

```javascript
import { createRouter, createWebHistory } from 'vue-router'
import LoginView from '../views/LoginView.vue'
import TodoListView from '../views/TodoListView.vue'
import { authStore } from '../stores/auth'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/login',
      name: 'login',
      component: LoginView,
      meta: { requiresAuth: false }
    },
    {
      path: '/todos',
      name: 'todolist',
      component: TodoListView,
      meta: { requiresAuth: true }
    },
  ]
})

router.beforeEach((to, from) => {
  const auth = authStore()
  if (to.meta.requiresAuth && !auth.isLogin) {
    return {
      path: '/login',
      query: { redirect: to.fullPath },
    }
  }
})

export default router
```

## 公式ドキュメント
https://router.vuejs.org/guide/advanced/meta.html
Windows11 で JIS配列キーボード と US配列キーボード を共存させる

## 目標
- JIS配列の内臓キーボードで刻印通りに入力できること．
- US配列の外付けキーボードで刻印通りに入力できること．

## 注意
- Windows Updateなどで設定が戻ってしまう可能性がある．
- レジストリをいじるのは自己責任で．

## 設定方法
### 1. デフォルトを英語配列にする．
1. 設定>時刻と言語>言語と地域 を開く．
1. 「日本語」と書かれ，その下に「言語パック，音声認識．．．」などが書いてある行の右側にある「...」をクリックし，「言語のオプション」をクリックする．
1. 後半部分の「キーボードレイアウト」で，「英語キーボード (101/102キー) 」を設定する．
1. 再起動を求められるので再起動する．

### 2. 内臓キーボードをJIS配列として認識させる．
1. レジストリエディタを起動する．
1. `Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters`まで移動する．
1. この中の`OverrideKeyboardType`を`OverrideKeyboardType.bak`に，`OverrideKeyboardSubtype`を`OverrideKeyboardSubtype.bak`などに変更することにより無効化する．
1. 簡単のために外付けキーボードをすべて外す．
1. デバイスマネージャーを開く．
1. 「キーボード」から内臓キーボードと思われるものをダブルクリックする．
    - 外付けキーボードを外しているので内臓キーボードだけが表示されるはず．
1. 詳細タブで，プロパティから「デバイスインスタンスパス」を選択する．
1. `Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\デバイスインスタンスパス\Device Parameters`まで移動する．
1. 次のパラメータを設定する．
    - OverrideKeyboardType : 7
    - OverrideKeyboardSubType : 2
1. 再起動する．
VSCodeのRemote SSHのJupyter Notebookをバックグラウンドで走らせる

VSCodeのRemote SSHでJupyter Notebookを動かしていると、サーバー側が元気でもこちらの画面を閉じるとカーネルが死んでまう。それを防ぐ。

# TL;DR
1. Remote SSHでSSH接続する
2. (Optional) `pip`, `conda`等で`env`に入る
3. (Optional) Jupyterのサーバーがない場合は立てる
4. Jupyter Connectionを選択
5. カーネルを選択
6. 安心して寝落ちる

# 説明
:::note
**クライアント側**
macOS Monterey, VSCode 1.74.2
**サーバー側**
Ubuntu, 22.04 LTS
:::

### 1. Remote SSHでSSH接続する
VSCodeの拡張機能Remote SSHを使う。

### 2. (Optional) `pip`, `conda`等で`env`に入る
カーネルの`env`になる。

### 3. (Optional) Jupyterのサーバーがない場合は立てる

UNIX系なら、端末を閉じてもログアウトしても処理を続ける`nohup`コマンドを使う。
```[shell]
$ nohup jupyter notebook &
```

`nohup.out`というファイルができているので、そのファイルの一番下のURLをコピーする。
```
To access the notebook, open this file in a browser:
        file:///home/hogehoge
    Or copy and paste one of these URLs:
        http://localhost:8871/?token=hogehoge ## <-これをコピー
     or http://127.0.0.1:8871/?token=hogehoge ## <-これでも良い
```


#### `nohup`その他
`jobs`で現在処理中のプロセスが表示できる。
```[shell]
$ jobs
[1]  + running    nohup jupyter notebook
```
`fg id`(zshなら`fg %id`)でジョブをフォアグラウンドに持ってこれる。ジョブを切りたい場合はフォアグラウンドにしてから`^C`。
```[shell]
$ fg %1
[1]  + 905549 running    nohup jupyter notebook
^C
```

### 4. Jupyter Connection
VSCodeに戻り、適当なNotebookを開くと右下に`Jupyter Server: Local`と表示されている。これをクリックする。
![Screen Shot 2023-01-08 at 0.02.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658828/f5e32d08-2f04-075c-5214-0e86409e5aaa.png)
Existingを選択。
![Screen Shot 2023-01-08 at 0.04.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658828/4d758a14-eaae-cc9f-f82e-e562b145df46.png)
URLをペーストし、適当な名前を入れてエンター。

### 5. カーネルを選択
処理したいNotebookを開き、右上のカーネル(Pythonのバージョンやenvが書いてある)をクリック。
![Screen Shot 2023-01-08 at 0.10.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658828/0e4000a5-c5e3-6883-c6de-8d80d7addc58.png)
Jupyter Sessionと書かれたカーネルを選択する。
![Screen Shot 2023-01-08 at 0.51.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2658828/69d08a50-1cae-3a20-fbb2-bcd9e6cdf386.png)

ここで、私の場合はJupyter Sessionが表示されない場合が多かった。Notebookを開きなおすとJupyter Kernelの方は表示された(Jupyter Sessionは表示されない)ので、Jupyter Kernelを選択してから一度適当なセルを実行し、もう一度見にいくとJupyter Sessionが追加されていた。

https://github.com/microsoft/vscode-jupyter/issues/1378
NATインスタンスをUbuntuで自作する

## はじめに

NATゲートウェイをプライベートで使うとなると、料金が少し高いなと思い、NATインスタンスをつくってみた。
調べてみると、AWS公式のNATインスタンスのAMIは、サポートが終了したAmazon Linuxをベースにしている様。

> https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_NAT_Instance.html
> NAT AMI は、2020 年 12 月 31 日に標準サポートが終了した Amazon Linux の最新バージョン 2018.03 に基づいて構築されています。

また、自作するのを調べてみた感じAmazon Linux 2でNATインスタンスを自作するものは多くあったが、UbuntuでNATインスタンスをつくるものはあまり多くなかった気がする。

UbuntuでNATインスタンスが動くところまではできたので記事として残す。
なお、検証したのはUbuntu 22.04。

## 手順

概ねAmazon Linux2でのNATインスタンスの作成と同じで、違うところは再起動後もiptablesの設定を保持してくれるように`iptables-persistent`を使うところ。

他はほぼ同じなので、iptablesに追加するルールのところの`192.168.0.0/24`、`ens5`は環境に合わせたものにすれば動く（はず）。

```
$ sudo sh -c 'sysctl -w net.ipv4.ip_forward=1 | tee /etc/sysctl.d/99-sysctl.conf'
$ sudo sysctl --system

$ sudo apt update
$ sudo apt install iptables-persistent -y

$ sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o ens5 -j MASQUERADE
$ sudo netfilter-persistent save
$ sudo systemctl enable netfilter-persistent.service
```

PackerテンプレートにしてAMIを焼いておけば複数の構築も楽かもしれない。
（僕は複数のNATインスタンスが必要なことをやってないので、不要だが...）

```hcl
# 略...

build {
  sources = [
    # 略...
  ]

  provisioner "shell" {
    inline = [
      "sudo sh -c 'sysctl -w net.ipv4.ip_forward=1 | tee /etc/sysctl.d/99-sysctl.conf'",
      "sudo sysctl --system",

      "sudo apt update",
      "sudo DEBIAN_FRONTEND=noninteractive apt-get install iptables-persistent -y",

      "sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o ens5 -j MASQUERADE",
      "sudo netfilter-persistent save",
      "sudo systemctl enable netfilter-persistent.service"
    ]
  }
}
```

## Ref

- [NAT インスタンス - Amazon Virtual Private Cloud](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_NAT_Instance.html)
- [令和なのに NAT インスタンスを手作りして使ってみた | DevelopersIO](https://dev.classmethod.jp/articles/nat-instance-handmaid/)
- [NAT インスタンス用の AMI を Packer で作ってみた | DevelopersIO](https://dev.classmethod.jp/articles/nat-instance-ami-packer/)
- [sysctl - ArchWiki](https://wiki.archlinux.jp/index.php/Sysctl)
- [iptables - ArchWiki](https://wiki.archlinux.jp/index.php/Iptables)
- [NAT ゲートウェイの設定 | シンプルなステートフルファイアウォール - ArchWiki](https://wiki.archlinux.jp/index.php/%E3%82%B7%E3%83%B3%E3%83%97%E3%83%AB%E3%81%AA%E3%82%B9%E3%83%86%E3%83%BC%E3%83%88%E3%83%95%E3%83%AB%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB#NAT_.E3.82.B2.E3.83.BC.E3.83.88.E3.82.A6.E3.82.A7.E3.82.A4.E3.81.AE.E8.A8.AD.E5.AE.9A)
- [雑記 - iptablesによるNAT](https://ult.riise.hiroshima-u.ac.jp/~nagato/?iptables%E3%81%AB%E3%82%88%E3%82%8BNAT)
- [Ubuntu20.04でルータを作成 | 日々修行](https://ytsuboi.jp/archives/642#NAT%28IP%E3%83%9E%E3%82%B9%E3%82%AB%E3%83%AC%E3%83%BC%E3%83%89%29%E3%81%AE%E8%A8%AD%E5%AE%9A)
- [送信元/送信先チェックを無効にする | NAT インスタンス - Amazon Virtual Private Cloud](https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/VPC_NAT_Instance.html#EIP_Disable_SrcDestCheck)
- [NATインスタンスをAmazonLinux2で構築する - 雲のメモ帳](https://www.cloudnotes.tech/entry/nat-instanse-amazonlinux2)
- [NATゲートウェイが高いのでNATインスタンスを立てる【金欠シリーズ】 - Qiita](https://qiita.com/NetCabb/items/dc7e7ea41f3494038d81)
【SwiftUI】リストのスクロールを検知する方法

# はじめに
SwiftUIでリストのスクロールを検知する方法を調べました。

# 環境
Xcode 14.1

# 内容
リストの1番上に配置した`Text`の位置が変わったタイミングを検知して、
`Text`が見えているかどうかを確認できるか試してみました。

##### 画面イメージ
<img width="300" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/4c3503eb-a7e2-6e0a-b125-b29095633a4b.png"><img width="300" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631585/80b338a1-7789-23f7-cc39-32fed8631eca.png">


##### 実装
```swift
struct ContentView: View {
    @State private var isShowToast: Bool = false
    
    var items: [SampleItem] = [
        SampleItem(text: "りんご"),
        SampleItem(text: "バナナ"),
        SampleItem(text: "なし"),
        SampleItem(text: "いちご"),
        SampleItem(text: "スイカ"),
        SampleItem(text: "メロン"),
        SampleItem(text: "みかん")
    ]
    
    struct SampleItem: Identifiable {
        let id = UUID()
        let text: String
    }
    
    var body: some View {
        ZStack {
            List {
                Text("くだもの")
                    .font(.largeTitle)
                    .frame(maxWidth: .infinity, alignment: .center)
                    .listRowSeparator(.hidden)
                    .overlay(
                        GeometryReader { geo -> AnyView in
                            DispatchQueue.main.async {
                                isShowToast = geo.frame(in: .global).minY < CGFloat.zero
                            }
                            return AnyView(EmptyView())
                        }
                    )
                ForEach(items) {
                    Text($0.text)
                        .frame(height: 150)
                }
            }
            .listStyle(.plain)
            if isShowToast {
                Text("タイトルが見えなくなった")
                    .foregroundColor(.red)
                    .frame(height: 30)
                    .padding(10)
                    .overlay(RoundedRectangle(cornerRadius: 30)
                        .stroke(Color.red, lineWidth: 1))
                    .clipShape(RoundedRectangle(cornerRadius: 30))
                
            }
        }
    }
}
```

`GeometryReader`の中を変えることで別の条件の検知もできる

```swift
    .overlay(
        GeometryReader { geo -> AnyView in
            DispatchQueue.main.async {
                isShowToast = geo.frame(in: .global).minY < CGFloat.zero
            }
            return AnyView(EmptyView())
        }
    )
```

# おわりに
より複雑なものを作った場合、うまく動作するのか不明ですが、この程度の簡単な条件であれば問題なさそうです。

# 参考

https://blog.personal-factory.com/2021/06/29/void-method-in-geometryreader/

https://yosshiblog.jp/swiftui_geometry/
草莽Erlang ── 13. ループと反復処理

口で言うより行うことがErlang習得への近道と信じています。

https://qiita.com/mnishiguchi/items/9237780e849d80a85e11

## ループと反復処理

Erlangには他の言語でいうforループや whileループは存在しません。代わりに、再帰処理やリスト操作用の備え付けの関数を使って反復処理を行います。

試しに「1、2、3」を印字するだけのシンプルなループを書いてみます。

https://youtu.be/AWxwmqzbOaw

https://youtu.be/FSz7N5hCltw

https://note.com/awesomey/n/n4d8c355bc8f7

### 再帰処理

`toukon:print_list/1`関数を定義します。

1. リストを受け取る
2. 一個を印字する
3. リストが空でなければ、`toukon:print_list/1`関数を呼び出し残りのリストを渡す
4. リストが空になったら終了

```erlang
-module(toukon).
-export([print_list/1]).

print_list([H | T]) ->
  io:format("~p~n", [H]),
  print_list(T);
print_list([]) ->
  ok.
```

試しに上述のモジュールを実際に作ってみます。

OSのシェルを開きます。

```bash
# 遊び用に一時ディレクトリを作成
$ mkdir tmp

# 一時ディレクトリの中に入る
$ cd tmp

# toukon.erlファイルを作ってモジュールを定義
$ cat <<EOF > ./toukon.erl
-module(toukon).

-export([print_list/1]).

print_list([H | T]) ->
  io:format("~p~n", [H]),
  print_list(T);
print_list([]) ->
  ok.
EOF

# toukon.erlファイルをコンパイル
$ erlc toukon.erl

# toukon.beamが生成されたことを確認
$ ls
toukon.beam toukon.erl
```

Erlangシェルを開きます。

```erlang
$ erl

> toukon:print_list([1, 2, 3]).
1
2
3
ok
```

:tada:

https://www.erlang.org/doc/reference_manual/functions.html 

https://learnyousomeerlang.com/recursion#hello-recursion

## lists:foreach/2

ちょっとしたリスト操作なら、Erlang備え付けの`lists:foreach/2`が便利です。

https://ja.wikipedia.org/wiki/リスト内包表記

https://www.erlang.org/doc/programming_examples/list_comprehensions.html

https://learnyousomeerlang.com/starting-out-for-real

https://www.ymotongpoo.com/works/lyse-ja/ja/03_starting_out_for_real.html

```erlang
> lists:foreach(fun(C) -> io:put_chars([C, $\n]) end, ["1", "2", "3", "ダー！"]).
1
2
3
ダー！
ok
```

:tada:

https://www.erlang.org/doc/programming_examples/funs.html#foreach

リスト処理のための関数は`lists`モジュールにあります。

https://www.erlang.org/doc/man/lists.html#foreach-2

マップ処理のための関数は`maps`モジュールにあります。

https://www.erlang.org/doc/man/maps.html#foreach-2

## リスト内包表記

既存のリストから新しいリストを生成したい場合、リスト内包表記を使うとすっきり書ける場合があります。

```erlang
> io:format([[X, $\n] || X <- ["1", "2", "3", "ダー！"]]).
1
2
3
ダー！
ok
```

:tada:

## Elixirにも挑戦したい

闘魂ElixirシリーズとElixir Schoolがオススメです。

https://qiita.com/torifukukaiou/items/3b65e5c04fa8c55f526e

https://elixirschool.com/ja

https://qiita.com/piacerex/items/09876caa1e17169ec5e1
ABC284-F ABCBAC (Python)

# 問題
https://atcoder.jp/contests/abc284/tasks/abc284_f

## 解き方
ローリングハッシュ。
クラス化したものを自分で持っとくとラクそう。あとでやろ。
ローリングハッシュの説明自体は、他の記事だったり本だったりにおまかせします。

### 具体的な方法
入力例1の「abcbac」でやってみます。
最初は、左半分の「abc」と、右半分を反転させた「cab」が一致してるかどうかを見る。
ここからローリングします。i(1≦i≦N)回目の操作では、
・左半分の「abc」→ 右からi番目の文字を消す「ab」→さっき消した位置に今度は元の文字列の右からi番目の文字を挿入する「abc」
・右半分を反転させた「cab」→ 先頭の文字を消す「ab」→末尾に元の文字列のN-i+1文字目を挿入する「abc」
のように文字列を動かして、同じかどうか判定します。
細かいことはコードを見てください。


## ACコード
```python
import random

N = int(input())
T = input()

# hash_dic[(英小文字)] = 乱数
hash_dic = dict()
for i in range(26):
    alp = chr(97 + i)  # chr(97)='a'だよ
    rd = random.randint(1, 2 ** 60)
    hash_dic[alp] = rd

a = random.randint(2, 2 ** 60)
mod = random.randint(2 ** 63, 2 ** 64)

# rui_a[i]: a^iをmodで割ったあまり
rui_a = []
num = 1
for _ in range(N):
    rui_a.append(num)
    num = num * a % mod

# 最初は、文字列Tがf_N(S)かどうかの確認をしてみる。
# ということで、文字列Tの左半分をローリングハッシュ
val_base = 0
for i in range(N):
    t = T[i]
    val_base += rui_a[N - 1 - i] * hash_dic[t] % mod
    val_base %= mod

# 文字列Tの右半分を「反転させたもの」をローリングハッシュ
val_rev = 0
for i in range(N):
    t = T[2 * N - 1 - i]
    val_rev += rui_a[N - 1 - i] * hash_dic[t] % mod
    val_rev %= mod

# 入力例3みたいなパターンだけ先に個別で処理しとく。
if val_base == val_rev:
    print(T[:N])
    print(N)
    exit()

for i in range(N):
    # val_baseは、末尾のT[N-1-i]を取り除いて、末尾にT[2*N-1-i]をつけ加える。
    val_base -= rui_a[i] * hash_dic[T[N - 1 - i]] % mod
    val_base += rui_a[i] * hash_dic[T[2 * N - 1 - i]] % mod
    val_base %= mod

    # val_revは、(右側を先頭として)先頭のT[2*N-1-i]を取り除いて、末尾にT[N-1-i]をつけ加える。
    val_rev -= rui_a[N - 1] * hash_dic[T[2 * N - 1 - i]] % mod
    val_rev %= mod
    val_rev *= a  # 文字列の先頭の位置が1つ左にずれてるから、各項の係数をそれぞれa倍してあげる。
    val_rev += rui_a[0] * hash_dic[T[N - 1 - i]] % mod
    val_rev %= mod

    if val_base == val_rev:
        print(T[:N - 1 - i] + T[2 * N - 1 - i:])
        print(N - 1 - i)
        exit()

print(-1)

```
ChatGPTを使って論文を翻訳・校正する方法

今まで英語の論文を執筆する際はDeepL+Grammarlyを活用していました。
しかし今流行のChatGPTを使うことで、DeepL+Grammarlyよりも高い水準で英語論文を作成できることを発見しました。

https://chat.openai.com/chat

## 英文を校正する方法
英文を構成したい場合次のように入力します。

>Please be an English spelling corrector and improver. I ask you to make my sentences more scientific, elegant, and academic, with use of upper-level English words, keeping the meaning same. Please keep the structure of my sentences and correct grammatical errors. Please only reply the revised sentences. 
Sentence is "【ここに校正したい文章】"

![スクリーンショット 2023-01-07 23.56.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840684/1cbbbd57-60b5-7f92-2528-b27323a427c8.png)

## 日本語の文章を論文として適した形で英訳する方法
DeepL+Grammarlyで行っていた翻訳と校正は次のように実現できます。

>文章を英訳してください。上品に、学術的に、上級の英単語を使いながら、意味はそのままに翻訳してください。完成した文章のみ返信してください。私の文章は"【ここに翻訳したい文章】"

![スクリーンショット 2023-01-08 0.06.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2840684/ca305f16-0c91-f16b-8f76-7a0431c8d5da.png)

## まとめ
これを使ったことがない人はぜひ使ってみてください。
きっとこの良さに気づきますよ。

ただ、GhatGPTを使って1から論文を書くことは禁止のようです。

https://gigazine.net/news/20230106-chatgpt-ai-writing-tool-banned/

## 参考記事

https://riklog.com/research/chatgpt/

https://note.com/genkaijokyo/n/n77cb87613a5b
SSSDとpam_pwquality.soモジュールに指定できる主なオプション

●SSSD（System Security Services Daemon）
LDAPやActiveDirectoryなどのリモートにある認証システムへのアクセスをクライアントシステムに提供する。
SSSDはリモートにある認証システムから得た情報をキャッシュ。そのため、認証システムの負荷を減らしたり、接続が切断されても（オフラインでも）クライアント側でユーザの認証を行えます。

SSSD（System Security Service Daemon）は、認証情報などをキャッシュし、障害時やオフライン時などでもこの情報を使って認証等を行うことができる環境を提供。SSSDをPAMとともに利用する場合、PAMの設定ファイルとともに、SSSDの設定ファイルであるsssd.confにも、利用するサービスとしてのpamの指定と、関連するパラメータの設定が必要になります。また、sssd.confでは、許可されるログイン試行の失敗回数なども制限することができます。


●pam_pwquality.so
パスワードの書式を制限し、安全性を向上させるPAMのモジュール。pam_cracklib.soの後継で、RHEL7やCentOS7から使用。

pam_pwquality.soモジュールに指定できる主なオプション

オプション　デフォルト　説明
・retry 1 パスワードの作成を試行できる回数
・minlen 9 パスワードに最低必要な文字数
・difok 5 変更前のパスワードと異ならなければならない文字数
・dcredit 1 文字の数
・ucredit 1 英大文字の数
・lcredit 1 英小文字の数
・ocredit 1 その他の文字(記号)の数
【Ruby】Setクラスの使い方

Setクラスの使い所があまり理解できませんでしたが、少し掴めた気がしたので使いどころと使い方について簡単にまとめておきます。

# Setクラス

Rubyの要素の集合を表したい場合、`Setクラス`を使用することができます。

集合は重複のないオブジェクトの集まりを指します。要素の間に順序関係はありません。

## 使い方
`setクラス`は標準ライブラリのため、requireすることで使用することができます。

以下のように定義して使います。
```ruby
require 'set'

set1 = Set.new(["Alice", "Bob", "Nick"]) # =>()は省略可能
p set1 #=> <Set: {"Alice", "Bob", "Nick"}>
```
`Set.new()`に配列を渡してSetオブジェクトを定義できます。

```ruby
set2 = ["Jone", "Rian", "Tom"].to_set
p set2 #=> <Set: {"Jone", "Rian", "Tom"}>
```
`to_set`メソッドを使用すると、配列からSetオブジェクトを生成することができます。

```ruby
p Set["Yamada", "Ito"]
 #=> <Set: {"Yamada", "Ito"}>
p Set[40, 10, 10, 20, 30]
 #=> <Set: {40, 10, 20, 30}>
```
`Set[]`に直接オブジェクトを定義することで、Setオブジェクトを生成することもできます。この時同じ要素はまとめられていることが確認できます。

## 使いどころ
`Setクラス`を使用して集合を生成できることがわかりました。

では、これが何の役に立つのか、です。

Setクラスは、要素数が多い場合で早い処理が必要とされる場面で活躍します。

例えばSetオブジェクトの中身に、任意のオブジェクトが存在しているかを確かめる`include?メソッド`を使用したい場合、できるだけ早く見つけ出したい、、、こんな時に使います。

また、Arrayにも集合機能があり`includeメソッド`が存在します。

同じように要素検索を行うことができますが、処理速度で考えると`Setクラス`の方が効率よく処理することができるようです。

これについては@an_sonyさんの記事がとても参考になったので引用させていただきます。
https://qiita.com/an_sony/items/708c47d073ad709431d6


## 参考
- Effective Ruby
- [【Ruby on Rails】Set#include?がなぜ速いのかを理解する](https://qiita.com/an_sony/items/708c47d073ad709431d6)
【読書メモ】プロになるためのWeb技術入門

## はじめに 

[プロになるためのWeb技術入門](https://www.amazon.co.jp/gp/product/4774142352/ref=oh_aui_detailpage_o01_s00?ie=UTF8&psc=1)を読みました。
こちらは個人的な読書メモです。

## 2章 Webはどのように発展したのか

■ RFC
インターネット上で利用される仕様や規約

■CGI
動的コンテンツを作成してWebクライアントに返す仕組み

■サーブレット
Web開発をサポートするための機能で、Javaのオブジェクト指向により大規模開発に適している。
また、Webコンテナ内で実行するため新たなプロセスを起動する必要がない。
→CGIの問題点を補っている

■JavaVM
仮想的なコンピュータの言語。Javaは直接機械語に翻訳されるのではなくJavaVMにコンパイルされる。
そのため、異なるプラットフォームでの開発がしやすくなる。

■Javaアプレット
JavaプログラムをWebブラウザの画面上で実行できる技術。

###### サーブレットの問題点
- プログラム担当者とデザイン担当者が同じファイル編集するので修正しにくい

■JSP
JSP内部のプログラムを`<%= %> `(スクリプトレット)で囲うことでプログラムの部分を明示する。
サーブレットはJavaコードの中にHTMLを埋め込むのに対して、JSPはHTMLの中にJavaコードを埋め込む。

## 3章 HTTPを知る
##### 3.4 Webサーバへの要求をどのように伝えるか

・GETメソッドによる値渡し
通常のURLに`?`からはじまるクエリ文字列つけることでサーバー側にパラメータを渡す。
サーバー側では`?`が存在すれば、そこに含まれるパラメータをアプリケーションに渡す。

・POSTメソッドによる値渡し
メッセージボディでパラメータを渡すため、第3者に見られる心配が少ない。

→検索結果などパラメータを保持したほうが良いものはGET、それ以外はPOSTを使う

## 4章 CGIからWebアプリケーションへ

■リダイレクト
最初に要求したURLと異なるURLに誘導すること。
ブラウザはステータスコード`302 Found`を受け取ると、LocationヘッダのURLに再度リクエストを発行する。

ログイン画面の例ではログイン成功時には成功画面、失敗時には失敗画面をLocationヘッダに書き込む。

##### 4.5 ログイン状態をどのようにして記憶するのか
HTTPはステートレスなプロトコル(状態を保持しない)
→**Cookie**を利用する
##### 4.6 安全に状態を保存するための技術
・Cookieの問題点
簡単に盗聴することができる
→**セッション**の利用
セッションIDをCookieでやり取りすることで安全にセッションごとの状態を保持できる。

## 5章 Webアプリケーションの構成要素

サーブレットやJSPはコンピュータが直接実行するのではなく、JavaVM上の**アプリケーションサーバー**が動かしている。CGIは使い捨てなのに対して、アプリケーションサーバーは常に起動している点が異なる。

・Webサーバーとアプリケーションサーバーの連携
Webサーバーに**Tomcat**、アプリケーションサーバーに**Apache**を利用する場合**mode_jk**という連携モジュールを使う。
Webサーバーとアプリケーションサーバーを連携させる場合、静的コンテンツはWebサーバーに動的コンテンツはアプリケーションサーバーに配置する。

最低限の構成である
・Webサーバー
・データベースサーバー
・アプリケーションサーバー
は**三層構成**と呼ばれる

## 6章 Webアプリケーションを効率的に開発する仕組み

サーブレットとJSPを連携させる際はHTMLの表示をJSPに任せて、アプリケーションはサーブレットに担当させる。

■フォワード
サーブレットからJSPへの遷移。
リダイレクトは2回のHTTPリクエストが発生するのに対して、フォワードはアプリケーションサーバー内で完結するため1回のHTTPリクエストで済む。

■リクエストスコープ
フォワード元とフォワード先で情報を共有する仕組み。
サーブレット、JSPともに読み書き可能。(リクエストパラメータはそれぞれの読み込みのみ可能)
リクエストスコープはレスポンスが返ると削除される

■セッションタイムアウト
一定時間を過ぎたセッション情報がアプリケーションサーバーから削除されること。

・なぜ、リクエストスコープが必要か
セッションですべての情報を保持するとメモリを多く消費するため。

■アーキテクチャ
設計スタイルと設計に基づく全体構造。

■IPO
入力、出力、処理のサーバーサイドの基本的な処理

■MVCモデル
アプリケーションを**Model**,**View**,**Controller**の3つの役割に分けるモデル。
ロジックの部分をModelが、デザインの部分をViewが担当し、Controllerが2つを繋ぐ役割をする。

## 7章 セキュリティを確保するための仕組み

■サニタイジング
特殊文字を文字参照に置き換える(XSS対策)

■ワンタイムトークン
フォームを送信する際に生成してアクセス時に自サーバーのものか確認、hiddenタグで送信する(CSRF対策)
達人に学ぶSQL徹底指南書 1章 CREATE, INSERT文まとめ

[達人に学ぶSQL徹底指南書](https://www.amazon.co.jp/%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6SQL%E5%BE%B9%E5%BA%95%E6%8C%87%E5%8D%97%E6%9B%B8-%E7%AC%AC2%E7%89%88-%E5%88%9D%E7%B4%9A%E8%80%85%E3%81%A7%E7%B5%82%E3%82%8F%E3%82%8A%E3%81%9F%E3%81%8F%E3%81%AA%E3%81%84%E3%81%82%E3%81%AA%E3%81%9F%E3%81%B8-CodeZine-BOOKS/dp/4798157821)
1章：CASE 式のススメ

本文中に書かれている内容を実行したかったので、自分用にメモ。
※本のサンプルと行の順序が異なる場合あり

https://www.db-fiddle.com/

## CREATE
``` SQL:
CREATE TABLE CourseMaster (
  course_id int,
  course_name varchar(255)
) charset utf8mb4;

CREATE TABLE OpenCourses (
  month varchar(255),
  course_id int
) charset utf8mb4;

CREATE TABLE StudentClub (
  std_id varchar(255),
  club_id int,
  club_name varchar(255),
  main_club_flg varchar(1)
) charset utf8mb4;

CREATE TABLE PopTbl2 (
  pref_name varchar(255),
  sex int,
  population int
) charset utf8mb4;
```

## INSERT
``` SQL:
insert into StudentClub values
(100, 1, '野球', 'Y'),
(100, 2, '吹奏楽', 'N'),
(200, 2, '吹奏楽', 'N'),
(200, 3, 'バドミントン', 'Y'),
(200, 4, 'サッカー', 'N'),
(300, 4, 'サッカー', 'N'),
(400, 5, '水泳', 'N'),
(500, 6, '囲碁', 'N');


insert into CourseMaster values 
(1, '経理入門'),
(2, '財務知識'),
(3, '簿記検定開講講座'),
(4, '税理士');

insert into OpenCourses values
(201806, 1),
(201806, 3),
(201806, 4),
(201807, 4),
(201808, 2),
(201808, 4);

INSERT INTO PopTbl2 VALUES 
('tokushima', '1', '60'),
('tokushima', '2', '40'),
('kagawa', '1', '100'),
('kagawa', '2', '100'),
('ehime', '1', '100'),
('ehime', '2', '50'),
('kouti', '1', '100'),
('kouti', '2', '100'),
('hukuoka', '1', '100'),
('hukuoka', '2', '200'),
('saga', '1', '20'),
('saga', '2', '80'),
('nagasaki', '1', '125'),
('nagasaki', '2', '125'),
('tokyo', '1', '250'),
('tokyo', '2', '150');
```
(SwiftUI) .background()がSafeAreaに侵入しちゃう

# はじめに
VStackに`background`モディファイアを使用した際に，SafeAreaにまで背景色が反映されていました．
自分としては，SafeAreaには背景色は反映されず，VStack内のみで背景色が変わることが理想でした．

<img width="300" alt="スクリーンショット 2023-01-07 20.13.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092467/86ce4a5e-1e58-2717-ef82-e7bd689f598d.png">

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [原因](#原因)
1. [解決方法](#解決方法)
1. [まとめ](#まとめ)
1. [参考文献](#参考文献)

# 原因
原因としては
iOS15からは，VStack等がSafeAreaに接している際，接しているVStack等に`background`モディファイアを適用すると，SafeAreaにも背景色が反映されるらしい

```
struct ContentView: View {
    var body: some View{
        VStack {
            Text("Hello, world!")
            Spacer()
            Divider()
        }
        .background(Color.orange)
    }
}
```

ちなみに，上記コードでは，`Spacer()`と`Divider()`によって無理やりSafeAreaにVStackを触れさせています．

# 解決方法
もしSafeAreaには背景色を反映させたくないのなら，普通にZStackを使用して背景色を指定するのが良さそう．

```
struct ContentView: View {
    var body: some View{
        ZStack {
            Color.orange
            Text("Hello, world!")
        }
    }
}
```
<img width="300" alt="スクリーンショット 2023-01-07 20.11.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092467/bddd0b48-3860-9d3f-0f13-736788e7e747.png">

また，上記コードの`Color.~`に，`.ignoresSafeArea()`を追加することで，SafeAreaを無視して全体に背景色を指定することができます．

<a id="#conclude"></a>
# まとめ
SafeAreaにVStack等が触れていると，`background`モディファイアを使用した際にSafeAreaに背景色が侵食しちゃいます．
注意しましょう．

# 参考文献
- [iOS 15 safe area background color unexpected change](https://developer.apple.com/forums/thread/697138)
- [SwiftUI - How do I change the background color of a View?](https://stackoverflow.com/questions/56437036/swiftui-how-do-i-change-the-background-color-of-a-view)
介護職からでもプログラマーは目指せるという話

初めまして。初投稿です。

私は7年前に、介護職から未経験でプログラマーに転職しました。
現在は色々な現場に派遣され、主に社内システム開発に携わっています。

今回は私自身が、どうやって未経験からこの業界に転職できたのか。
こんなケースもあるのだ程度で見て頂けると嬉しいです！

目次
-
- 突然プログラマーを志す
- 経験0からいきなりIT系派遣会社の面接を受ける
- IT系派遣会社から最低でもこの資格を取るよう指示頂く
- 一週間後に対象資格を2つ取得→やる気を買われ内定を勝ち取る
- 終わりに


突然プログラマーを志す
-
その当時は介護職だったのですが、介護現場には夜中の勤務があります。
場所にもよりますが、結構な長時間労働です。（16:30~9:00など）
呼び出し頂いた方の排泄介助や話し相手、そして寝返りを打てない方への寝返り介助（体交といいます）などを行います。

特にこの体交が、利用者にとっても介助者にとってもなかなか大変な作業でした。以下のような問題点があったのです。
　利用者…2時間おきに体を左右に勝手に動かされ目が覚めやすい
　介助者…中腰の作業のため腰や腕への負担が大きい

体交を行わなかった場合、腰など体重のかかる場所の血流が悪くなってしまい床ずれの原因になってしまうため、必ず行わなくてはいけません。

そんなある日、職場に自動体交ベッドというものが導入されました。
これが1時間や2時間おきにベッド自体が角度を変えてくれる優れモノでした。
単純ですが、こういう人の役に立つものを作れる人になりたい！
　→プログラマーになろう！と思い立ち、転職活動を開始しました。


経験0からいきなりIT系派遣会社の面接を受ける
-
「転職 IT」で検索をかけ、その日のうちにIT転職サイトに登録。
「未経験歓迎!」のタグが付いているIT派遣会社に応募しました。
1週間後に面接を取り付け、面接までの期間は無料でプログラミングが学べるWebサービスを登録。
HTML、PHP、Javascriptの初歩の構文を憶えていきました。

そして面接当日。
正直何を話したのかあまり覚えていないのですが、
- 自動体交ベッドに感動したこと。
- 現在PHPなどを勉強していること
- 携帯の解体や、音楽プレーヤの解体をしたことがある話(?)

等を話したようで、3つ目の解体の話に興味を持ってくださった当時の上司にチャンスを頂きました。
5年目位にその時の話をして頂き、主語も要点もめちゃくちゃな面接だったようです。。
運がよかったのだと思います。また、すぐに行動したのも良かったのだと思います。

介護職仲間や上司からは、「介護からの転職なんて絶対無理だ！辞めといた方がいい。」と、当時何度も言われました。
転職というと、止めてくる人達も多いです。
でも自身がやりたいなら行動しないと、後悔してしまいます。動いてよかった。

派遣会社から最低でもこの資格を取るよう指示頂く
-
当たり前のことですが、未経験＋何の資格も持っていない＝現場採用は難しい　です。
そのため、まずはMOS(マイクロソフト オフィス スペシャリスト）の、
ExcelとWordの資格を取るよう派遣会社から指示がありました。

現場にもよりますが、ExcelやWordを使用する機会はとても多いです。
製造されたプログラム用のテスト仕様書や、基本/詳細設計書にも使われています。
この時に勉強した内容が現場で役立つことも多いです。

この指示は、自身のやる気を見せるチャンスだと感じました。
この資格を早めに取れば取るほど、相手も前向きに動いてくれると考えました。
早速「MOS 最短 合格」で検索をかけ、おススメと書かれた参考本を2冊購入し勉強を始めました。

一週間後に対象資格を2つ取得→やる気を買われ内定を勝ち取る
-
できるだけ早く合格を伝えた方が、相手にも驚きを与えられると思い
当時の職場で有休を取得。1週間後に資格試験の申し込みをし、PCに6日間かじりつきました。

1週間後、同日にExcelとWordの試験を実施。
1000点満点中、両方とも1000点で合格しその日のうちに派遣会社へ合格の旨とスコア結果とを送信しました。

実は当時、上司としては1か月～2か月での合格を想定されていたようで、ここまで本気ならば内定させなければと思って頂いたと聞きました。
結果、見習いプログラマーとして入社し現在もプログラマーを続けています。

終わりに
-
自身がITへの転職を志した時、「IT転職」で調べても
- 有料でプログラミングスクールに通って卒業後
- まずは1からプログラムを作成後

という記事が多く、
こういう形で入ったという記事が見当たらなかったため、この記事を書かせて頂きました。
行動すれば上手くいくこともあります。
未経験から転職を考えている方にとって、ひとつの参考となれれば嬉しいです。

次回以降は、技術的な記事にもチャレンジしていきたいです。
ご意見などありましたら、コメント頂けますと喜びます。

こんな拙い文章を最後まで読んでいただき、ありがとうございました！
Mac に Metasploit をインストールするまで

## はじめに

homebrew でインストールして使っていましたが、brewletによる更新の通知の頻度がMetasploitだけ非常に多かったので気になっていました。
もしかしたらbrewletの設定でmetasploitの通知だけ来ないようにできたのかもしれませんが、一度metasploitを削除して他の方法でインストールし直そうと思いました。
走り書きですが参考になればと。

## インストーラをダウンロード

https://osx.metasploit.com/metasploitframework-latest.pkg

手順に従ってインストール

## パスを通す

```shell-session
echo 'export PATH="/opt/metasploit-framework/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

msfconsole
起動すれば終了!
```

## 参考

公式のドキュメント

https://docs.metasploit.com/docs/using-metasploit/getting-started/nightly-installers.html

アップデートは今後以下のコマンドで

```shell-session
msfupdate
```

おわり
QEMU/KVMでブリッジ接続

# 概要

- QEMU/KVMを使って仮想マシンを作るときに、ゲストOSを、ホストと同じネットワークに接続します。ゲスト側でDHCPクライアントが動いていれば、DHCPからIPアドレスをアサインすることも可能です。
- VirtualBoxだと、ネットワークアダプタをブリッジアダプタにするだけですが、QEMU/KVMだと多少設定が必要です。
- 同じ内容の記事はたくさんあるのですが、情報が古かったりするので、まとめておきます。

# 環境構築

ホストOSはFedora37です。
セットアップは以下のようにします。

```
$ sudo dnf install -y libvirt virt-manager
$ sudo systemctl enable libvirtd --now
```

# 仮想ブリッジ作成

ブリッジ接続のためには、仮想ブリッジを作成します。
ここの部分は、Dockerコンテナをブリッジ接続する場合と同じなので、下記の記事の「仮想ブリッジ環境構築」の通り仮想ブリッジを作成します。

https://qiita.com/yas99en/items/6f527e9f4ccc3085fd88#%E4%BB%AE%E6%83%B3%E3%83%96%E3%83%AA%E3%83%83%E3%82%B8%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89

# QEMUの設定

QEMUで作成したブリッジを使えるよう設定します。
ここでは/etc/qemu/bridge.confに、「allow br0」を追記しています。

```text:/etc/qemu/bridge.conf
allow virbr0
allow br0
```

# 仮想マシン作成

インストールが終わったら、仮想マシンマネージャーを起動して、仮想マシンを構築します。
```
$ virt-manager
```

ポイントになる部分は、ネットワーク選択の際に、ブリッジデバイス「br0」を設定しておく点です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/eb61cace-0859-3b53-731b-e7decee36a77.png)

既存のインスタンスも設定画面からブリッジデバイスに変更することもできます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147328/c5650acd-2a4e-2290-58a7-62e158a520c4.png)
MailSlotでネットワークセグメントを超える方法

# 背景
業務で新規のWindowsデスクトップアプリケーションを作成することになりました。既存の他システムとの連携が前提ですが、その通信方法がMailslotによる通信だったために新規アプリケーションでもMailslotを送受信できるようにしなければならなくなりました。

# そもそもMailSlotsとは
Microsoftのドキュメントには以下のように記載があります。
https://learn.microsoft.com/ja-jp/windows/win32/ipc/mailslots
>mailslot は、一方向のプロセス間通信 (IPC) のメカニズムです。アプリケーションは、mailslot にメッセージを格納できます。 mailslot の所有者は、そこに格納されているメッセージを取得できます。 通常、これらのメッセージは、指定したコンピューターまたは指定したドメイン内のすべてのコンピューターにネットワーク経由で送信されます。プロセス間通信には、mailslot の代わりに名前付きパイプまたは Windows ソケットを使用できます。 （一部抜粋）

MailSlotを利用する場合には上記にもあるようにコンピューター名もしくはホスト名を指定する必要があります。詳細は以下のURLを参照ください。
https://learn.microsoft.com/ja-jp/windows/win32/ipc/mailslot-names

# 今回発生した問題
今回の場合、他システムが別のネットワークセグメントに属していたため、MailSlotでの通信ができない（MailSlotを送信しても受信できない）状態になりました。

# 解決法
今回通信できない問題をクリアするために以下の二つの対応を行いました。
## (1)NetBIOS over TCP/IPをONにする。
以下のサイトを参考にしました。
https://wiki.mcneel.com/ja/zoo/writemailsloterror

## (2)lmhostファイルを作成する。
今回のセグメントを超えられない原因はこれでした。どうやらMailSlot（NetBIOS over TCP/IPの通信）でネットワークセグメントを超える場合はhostsファイルによる名前解決が出来ないようで、セグメント外のホストを見つけることができませんでした。なので対処としてはNetBIOS over TCP/IPの通信で名前解決が出来るようにlmhostsファイルを「%windir%\system32\drivers\etc」に作成しました。
以下のサイトを参考にしました。
https://emuyama.cocolog-nifty.com/emulog/2004/08/hostslmhosts_bff5.html

# まとめ
現在の世の中でMailSlotが使用されているシステムはごくわずかなような気もしますが、もしMailSlot（NetBIOS over TCP/IPの通信）でネットワークセグメントを超えなければならない場合はlmhostsファイルを作成しましょう。
Rust　所有権

## メモリの概要
|Heap(ヒープ)|Stack(スタック)|Static(静的領域)|Text(コード)|
|------------|--------------|----------------|-----------|

* Text(コード)…アプリケーションをコンパイルすると機械語のバイナリコードが生成される。そのコードを保存する領域
* Static(静的領域)…const(定数)や文字リテラルの実体などを保存。
* Stack(スタック)…コード実行時に動的にメモリ領域を確保・解放。
* Heap(ヒープ)…コード実行時に動的にメモリ領域を確保・解放。メモリアクセスはスタックよりも遅くなる。

スタックメモリは、変数や配列など（あらかじめデータサイズがわかっているもの）をスタック上に積んでいき、解放する際は一番最後に積まれたものから解放する。最後にpushしたものが、一番最初にpopされる性質上、 取得する場所を探す必要がないことに加えて、スタック上のデータはすべてコンパイル時にサイズが決まっていないといけないため、高速に動作することができる。
~~~ 
                    push⇘        pop⇗
                        |スタック|
                        |スタック|
                        |スタック|
                        |スタック|
~~~
逆に、コンパイル時にサイズがわからないものや可変データはヒープメモリに格納する。ピープメモリは、スタックメモリに比べて低速で容量が大きい。ヒープにデータを格納する際、十分なサイズのメモリスペースを確保し、その場所のポインタを返す。十分なメモリスペースを確保したり、ポインタを追って目的の場所に行かないといけない等の理由から、低速になる。
※スタックに値を積むことをメモリ確保とは言わない。

コードのどの部分がピープ上のデータを使っているのか、ピープ上の重複するデータを最小化すること、メモリ不足にならないようにピープ上の未使用のデータを掃除することはすべて所有権が解決する問題である。

## 各言語のメモリ管理方法
メモリの管理において、あると望ましい特徴
* メモリをプログラマの任意のタイミングで解放すること
↳メモリ消費の管理
* 解放済みのオブジェクトへのポインタを使ってしまわないこと。
↳未定義動作につながる (クラッシュ、セキュリティーホール)

ポインタが存在するうちに値を開放するとポインタの参照先がなくなる
↳<b>ダングリングポインタ</b>
↳上記の条件を満たすことは困難か？
↳主要なプログラミング言語では、どちらかをある程度妥協して、メモリの制御を優先するか、安全性を重視するかをしている。

C, C++
…メモリの解放権限をプログラマに任せる。プログラマのミスがなければ、うまくいくが…

Python, JavaScript, Ruby, Java　など
…ガベージコレクションを用いてメモリ管理を行う。オブジェクトに到達できるポインタがなくなったら、メモリを開放する。ガベージコレクタにメモリ解放の権限を渡してしまい、プログラマからは見えない。

⇒<b>Rustはポインタの使い方に制約を加えることで、安全性の高いシステムを構築した。</b>

## 所有者規則
* Rustの各値は所有者と呼ばれる変数と対応
* いかなる時も所有者は一人
* 所有者がスコープから外れたら所有されている値も一緒に削除される。
⇒ブロック内で宣言された変数はブロックを抜けたところで破棄される。
* 値を所有者から新しい所有者へ移動することができる。移送もとは所有者ではなくなる。（移動元は未初期化状態となる。）Rustでは、未初期化状態の変数は使うことができない。
* Copy型といわれる単純な型（整数、浮動小数点、文字など）は、所有権を持たない。
~~~Rust
fn main() {
    let x = 1; // ブロック内でｘを初期化
} // xがスコープから抜ける。
~~~
~~~Rust
fn main() {
    let x = [1, 2, 3, 4, 5]; // ｘを初期化
    let y = x; // yに所有権がわたる
    for i in y {
        println!("{}", i)
    }
}
// print!("{}", y); // エラー yが存在しない
~~~
~~~Rust
fn main() {
    // Copy型には所有権はない
    let x = 10; 
    let y = x; 
    println!("{}", x);
    println!("{}", y);
}

>>>
10
10

~~~
## 参考文献
* プログラミングRustオーラリージャパン
* [The Rust Programming Language 日本語版](https://doc.rust-jp.rs/book-ja/ch04-01-what-is-ownership.html)
LinuxでGoogle Chromeをダークモードにする。

```sh
sudo apt update
sudo apt upgrade

yay -Syu
```
したらいちいちダークモードじゃなくなりますよね。どうにかならないんですかね....。

# 解決策
```sh:google-chrome-darkmode.sh
chmod 777 /opt/google/chrome/google-chrome

sudo sed -i '$ d' /opt/google/chrome/google-chrome

sudo echo 'exec -a "$0" "$HERE/chrome" "--enable-features=WebUIDarkMode" "--force-dark-mode" "$@"' >> /opt/google/chrome/google-chrome
```
これを実行すればOKです！

#### 解説
一行目は権限がたりないのでchmodしてます。
二行目にファイルの一番最後の行を削除しています。
三行目にファイルの一番最後に追記しています。
草莽Erlang ── 12. ガード節

口で言うより行うことがErlang習得への近道と信じています。

https://qiita.com/mnishiguchi/items/9237780e849d80a85e11

## ガード節

ガード節を用いて、パターン内の変数に対して簡単なテストや比較を行うことができます。

練習してみます。

以下の例では引数の数字を比較してどう処理すべきかを決定します。この無名関数をErlangシェルに貼り付けてみてください。

```erlang
PN = fun 
  (Number) when Number > 0 -> 
    positive; 
  (Number) when Number < 0 -> 
    negative;
  (Number) ->
    zero
end.
```

引数のパターンに応じて処理を切り替えることができました。

```erlang
> PN(0).
zero

> PN(1).
positive

> PN(-1).
negative
```

以下の例では引数の型に基づいてどう処理すべきかを決定します。この無名関数をErlangシェルに貼り付けてみてください。

```erlang
CheckType = fun 
  (X) when is_list(X) -> 
    io:format("~pはリストです。~n", [X]); 
  (X) when is_tuple(X) -> 
    io:format("~pはタプルです。~n", [X]); 
  (X) ->
    io:format("~pはタプルでもリストでもありません。~n", [X])
end.
```

引数の型に応じて処理を切り替えることができました。

```erlang
> CheckType([]).
[]はリストです。
ok

> CheckType({}).
{}はタプルです。
ok

> CheckType(#{}).
#{}はタプルでもリストでもありません。
ok
```

Erlangのビルトイン関数（BIFs）にガードとして使える便利な関数がいくつかあります。

https://www.erlang.org/doc/reference_manual/expressions.html#guard-expressions

https://www.erlang.org/doc/man/erlang.html

## Elixirにも挑戦したい

闘魂ElixirシリーズとElixir Schoolがオススメです。

https://qiita.com/torifukukaiou/items/3b65e5c04fa8c55f526e

https://elixirschool.com/ja

https://qiita.com/piacerex/items/09876caa1e17169ec5e1
npm/yarn/pnpm コマンド比較

# npm/yarn/pnpm コマンド比較

以下は、npm、yarn、および pnpm のコマンドの比較です。

|npm command|Yarn command|pnpm equivalent|
|-|-|-|
|npm install|yarn|[pnpm install](https://pnpm.io/cli/install)|
|npm install [pkg]|yarn add [pkg]|[pnpm add [pkg]](https://pnpm.io/cli/add)|
|npm uninstall [pkg]|yarn remove [pkg]|[pnpm remove [pkg]](https://pnpm.io/cli/remove)|
|npm update|yarn upgrade|[pnpm update](https://pnpm.io/cli/update)|
|npm list|yarn list|[pnpm list](https://pnpm.io/cli/list)|
|npm run [scriptName]|yarn [scriptName]|[pnpm [scriptName]](https://pnpm.io/cli/run)|
|npx [command]|[yarn dlx [command]](https://yarnpkg.com/cli/dlx)|[pnpm dlx [command]](https://pnpm.io/cli/dlx)|
|[npm exec](https://docs.npmjs.com/cli/v8/commands/npm-exec)|[yarn exec [commandName]](https://yarnpkg.com/cli/exec)|[pnpm exec [commandName]](https://pnpm.io/cli/exec)|
|[npm init [initializer]](https://docs.npmjs.com/cli/v8/commands/npm-init)|yarn create [initializer]|[pnpm create [initializer]](https://pnpm.io/cli/create)|

# 参考

https://refine.dev/blog/pnpm-vs-npm-and-yarn/
【200円IoTボタン】BT Shutterを買わない方がいい理由【スマホシャッターリモコン】4571527711848

ジェネリックAB Shutter 3がダイソーで売ってたので買ってみた。左がみんな大好き300円IoTボタンです。
![PXL_20230107_083804447.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/321c1c25-3756-2b61-502d-bd521d1785cb.jpeg)

# 音量下げの実装がなくなる YC1386

コストダウンのためか、音量下げのピンがなくなってました:rolling_eyes: Kindleのページめくりができなくなりました🥺

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/fc747886-def6-63ef-7f0e-63a808562c87.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/45570327-db54-35e5-1fd0-aa2f2ec81a5c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/a52b0fab-1094-7206-2044-544da09a77a3.png)


いかがだったでしょうか？みなさんは安物買いの銭失いしないようにしてくださいね

参考

https://twitter.com/rhotta/status/1601545045538402304

https://twitter.com/rhotta/status/1601504788738641920

https://twitter.com/rhotta/status/1601219755989676032

https://www.pizaman.com/entry/btv52-remote-shutter-review/#toc2

http://gijin77.blog.jp/archives/21309033.html

PS

現状、**Bluetooth Keyboard & Mouse**をPixel 4aにいれてKindle Fire HD 10をページめくりしてます。無料のアプリがあったら教えてちょ

https://play.google.com/store/apps/details?id=io.appground.blek&hl=ja&gl=US