OmniAICreator/Qiita-1.07M huggingface dataset:
【Pandoc】Markdown Preview Enhancedでプレビューが表示されない問題

# はじめに
PandocとVS Codeの拡張機能であるMarkdown Preview Enhancedを使って論文を書いています。が、最近新調したMacでプレビューが表示されないというトラブルが発生しました。

Pandocを使った論文執筆環境構築は以下のリンクから読めます。

https://qiita.com/yuya_akamatsu/items/35a28dc0b72d83456e8c

# 結論
Googleドライブのフォルダ名「マイドライブ」がダサすぎてパスが通らなかったようです。シンボリックリンクを作ってパスを通すと解決しました。

# 内容
Markdown Preview Enhancedという拡張機能を使うと、Markdownの内容をPandocを介してプレビュー表示できます。コマンドラインでPandocを実行する前に内容を確認できるため便利です。

`settings.json`に以下の記述を追加することで、各種フィルターやbibtexファイルなどを指定することができます。

```
"markdown-preview-enhanced.pandocArguments": [
        "--filter=pandoc-crossref",
        "--citeproc",
        "--bibliography=/Users/Library/CloudStorage/GoogleDrive-hoge@hoge.com/マイドライブ/bibliography.bib",
        "--csl=/Users/Library/CloudStorage/GoogleDrive-hoge@hoge.com/マイドライブ/styles/hoge.csl",
    ],
```
しかし、プレビュー上で以下のようなエラーが出てしまいました。

```
pandoc: /Users/Library/CloudStorage/GoogleDrive-hoge@hoge.com//styles/hoge.csl: withBinaryFile: invalid argument (cannot encode character '\65533')
```
本当は`GoogleDrive-hoge@hoge.com/マイドライブ/styles`なのですが、どうやらカタカナを読めないみたいです。

# 解決策
名前にカタカナが入っていないフォルダを別に作ってそこにメタデータを入れる、という方法でもいいのですが、Googleドライブで管理したいので、シンボリックリンクを使って解決しました。

ChatGPT曰く、「シンボリックリンクを作成すると、元のファイルやディレクトリの別名として機能し、元の場所にアクセスすることなく別の場所からそれにアクセスできます。これは特に、パスに特殊文字が含まれていたり、長いパスを簡略化したい場合に便利です。」だそうです。

ターミナルで、以下のコマンドを実行し、Googleドライブのシンボリックリンクを作成します。
```
ln -s "/Users/Library/CloudStorage/GoogleDrive-hoge@hoge.com/マイドライブ" ~/Desktop/MyDrive
```

これで、デスクトップ上に`MyDrive`という名前のアイコンが作成されます。あとは、パスをこちらに通すだけです。

```
"markdown-preview-enhanced.pandocArguments": [
        "--filter=pandoc-crossref",
        "--citeproc",
        "--bibliography=/Users/Library/Desktop/MyDrive/bibliography.bib",
        "--csl=/Users/Library/Desktop/MyDrive/styles/hoge.csl",
    ],
```
インプット欄に数字を入れたら"NaN cannot be parsed"とエラー

# はじめに
Reactの課題で学習記録アプリケーションを作っています。
学習内容と数字を入力したところ、数字が入力されずにコンソールを見ると以下のエラーが出てきました。
```
the specified value "nan" cannot be parsed, or is out of range
```

# 原因
めちゃくちゃ単純なことですが、全角入力になっていたためでした！
inputタグでnumber属性を指定した際、非数の入力は受け付けないためある種当然のことですね（笑）

# 解決策
英数入力にて入力する

# 終わりに
自分の性格(性質?)上よくこういったぽかをしてしまうので、当たり前にみんなができているけど意外にたまにやると忘れているようなことも記事にしていきたいです！
CSSのbackground-imageにSVGのXML文字列を埋め込む

Webページの背景に簡単な模様を入れるために`background-image`にSVG画像を指定する場合があります。
通常はSVGのデータを独立のファイルにして `url();`で読み込むのですが、色々な事情で画像ファイルを用意したくない場合に、データURIスキームを使ってCSSファイルの中に画像データを埋め込むことが考えられます。
たとえば、↓の画像の右下にある三角形の場合はこんな感じ。
![svgbackground.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192970/81ac3b7e-8e0e-3732-9eb2-1c9efe2116a3.png)

```css
#hoge {
    background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 100"><polygon points="70,100 100,100 100,80" fill="%23c8c8c8"/><polygon points="80,100 100,100 100,80" fill="%23cf2030"/></svg>');
    background-position: right bottom; /* 画像を右下に配置 */
    background-attachment: fixed; /* 画像を固定 */
    background-repeat: no-repeat; /* 画像の繰り返しを防止 */
}
```
# ちょっとした解説
## `url('data:image/svg+xml;utf8,`の部分
データURIスキームを使って、SVGのデータを読ませます。
utf8を指定しておくことで、`<`や`>`をエスケープする必要がなくなります。ただし、`#`は`%23`にエスケープする必要があるので、色指定などでは一手間かかります。

## `<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 100 100">`の部分
XML宣言（`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>`）は無くても動くようです。
`xmlns`は指定しておかないと動かないようです。
今回は画像を右下に配置したいのですが、どうも`background-position: right bottom;`の指定ではうまくいかないようなので、適用対象のブロック要素全体を覆うSVG画像を用意します。`viewBox`はパーセンテージでは指定できない（ピクセル値？でしか指定できない）ので、ともかくこのSVG画像自体は`width="100%" height="100%"`にした上で、`viewBox`の値を使って位置を指定する感じでやりました。SVGわからん。
あとは、この100x100のviewBox内に、右下角の位置に灰色の三角形と赤い三角形を並べました。上述の通り、データURIスキーム内での色指定は`#c3c3c3`だとダメっぽいので`%23c3c3c3`にエスケープしています。

日本語のネット情報だと、データURIスキームを使う場合はbase64にエンコードする方が多いのですが、可読性のためエンコードせずに文字列で埋め込んでいます。また、英語でチラッと検索した感じだとutf8を指定せず不等号等もエスケープする例が出てくるのですが、エスケープ混じりも可読性が低いし手間なので、utf8を指定してみたら概ねうまく行った次第。
37%アルゴリズムを使って人生をもっと楽しくしよう

こんにちは。エンジニアのハサンです。
今回は、37%のアルゴリズムについて説明します。すでに知っている方はいると思いますが、知らない方もいるので、この記事参考にして少しこの人気のあるアルゴリズムについて勉強していただければなと思います。
<h1>目次</h1>

1. ちょっと歴史
2. 37%ルール（アルゴリズム）の基本概念
3. 実生活への応用
4. まとめ


<h2>1.ちょっと歴史</h2>


<h3>初期の研究</h3>

37%ルールは、最適停止問題（Optimal Stopping Problem）の一例であり、この問題の研究は主に数学と統計学の分野で進められてきました。最適停止理論の初期の研究は17世紀から18世紀にかけて、ギャンブルや財務管理の分野で始まりました。数学者たちは、特定の条件下で最適な意思決定をするための戦略を模索しました。

18世紀のフランスの数学者、Pierre-Simon Laplaceがポアソン分布の概念を発展させ、最適停止問題の基礎を築きました。同時期に、モンモール問題として知られるギャンブルにおける最適停止の問題も研究されました。

<h3>20世紀の発展</h3>

1950年代に入るとリチャード・ベルマン（Richard Bellman）が動的計画法（Dynamic Programming）の概念を提唱し、最適停止問題の数学的枠組みを確立しました。その後、1960年代に入ると、最適停止問題に対する関心が高まり、具体的な問題として「秘書問題」または「婚活問題」が研究されるようになりました。1960年代後半に入ると数学者たちは、秘書問題の最適な解決策として37%ルールを発見しました。具体的には、N個の候補のうち最初の37%を観察し、その後に最初の37%よりも良い候補が現れた場合にその候補を選ぶという戦略です。

<h3>現代への影響</h3>

37%ルールは、最適停止問題の一例として広く知られるようになり、ビジネス、経済、心理学、デートや婚活など、さまざまな分野で応用されています。近年では、データサイエンスやアルゴリズムトレーディングなどの分野でもこの理論が活用されています。

<h2>2. 37%ルール（アルゴリズム）の基本概念</h2>

<h3>　1. 探索と選択の段階</h3>

最初の37%の期間を「探索段階」とします。この期間中は選択を行わず、ただ観察して情報を収集します。残りの63%の期間を「選択段階」とします。この期間中に最初に探索段階で観察したものよりも良い選択肢が現れたら、それを選びます。

<h3>　2. 具体例:</h3>

例えば、あなたがアパートを探しているとします。10件のアパートを見て回る計画があります。この場合、最初の3～4件（10件の37%）はただ観察し、その後に出てくる物件から最初の3～4件よりも良い物件を見つけたらそれを選びます。

<h2>3. 実生活への応用</h2>

<h3>　1. 就職活動</h3>

就職活動において、多くの企業や職種から最適な選択肢を見つけるのは難しい場合があります。この場合、37%ルールを適用することで、効率的に最適な求人を見つけることができます。初めの37%の期間（例：最初の1か月間）で応募先を観察し、情報を収集します。この期間中は積極的に応募せず、企業の情報や仕事の条件を調査します。残りの期間で、最初の37%で得た情報を基に、それらよりも良いと思われる求人に応募します。

<h3>　2. デートや結婚相手探し</h3>

デートや結婚相手を探す際にも37%ルールは有効です。たとえば、10人の候補者とデートする予定がある場合、最初の37%（約3～4人）は観察期間とし、その後に最初の3～4人よりも良いと感じた人を選ぶという方法です。

<h3>　3. 住居探し</h3>

最初の37%の物件（例：10件のうち最初の3～4件）は見学するだけにし、契約はしません。この期間中は市場の状況や物件の特徴を理解するために情報を収集します。残りの物件から、最初の37%で見た物件よりも良いと思われる物件を選びます。

<h3>　4. 購入決定</h3>

高価な商品や重要なサービスの購入決定にも37%ルールを活用できます。最初の37%の候補（例：10個の製品のうち最初の3～4個）は購入せずに観察し、各商品の特徴や価格を比較します。観察期間後に最初の37%よりも良いと感じた商品が見つかれば、その商品を購入します。

<h3>　5. 投資決定</h3>

投資の際にも37%ルールを適用することで、効率的な意思決定が可能です。最初の37%の投資機会は観察し、市場の動向や企業のパフォーマンスを分析します。観察期間後、最初の37%の投資機会よりも良いと感じた場合、その機会に投資します。

<h1>4. まとめ</h1>

37%ルールは、限られた時間やリソースの中で効率的に最適な選択をするための実用的な戦略です。就職活動、デート、住居探し、購入決定、投資など、さまざまな実生活の場面で応用することができます。このルールを用いることで、情報収集と意思決定のプロセスを効率化し、より良い結果を得ることが期待できます。
ヘルプデスク業務で意識していること

こんにちは、水野と申します。
私は普段ある企業のヘルプデスクとして
主に電話対応をしています。

半年ほど教育に携わらせていただいた際、
電話対応でどんなことを大切していたかを振り返る機会があったので、
幾つかある内、こちらで3つほど紹介させていただければと思います。

### 1.おうむ返し
会話の中で人の話を聞く上でも有効な手段かと思うのですが、
こちらの聞き間違いを防ぐというメリットの他に、
ユーザ側に対して「問い合わせ内容を
こちらは聞き取ることができていますよ」
と言うアピールにもなります。
自分の言いたいことが伝わっているのか不安に感じるユーザもいるため、とてもおすすめです。

### 2.球持ちの意識
これは、問い合わせを受けるにあたって情報を自分の所で止めないようにするという意味になります。
問い合わせを受けて、内容次第では
別の部署・管轄しているグループに対して
確認依頼をする機会があるかと思います。

その場合、ユーザと担当部署との間に立つことになり、他の問い合わせと並行して対応を続けていくと
問い合わせの進捗状況が分からなくなってしまうなんてことが起こり得るので
そういった事態を避けるためにも業務管理の一つとして徹底するといいと思います。


### 対応内容の記載
現場によって異なるかとは思うのですが、
特定の問い合わせに対して、「どこの部署は確認し、どのような連携を受けたか」
などの証跡は、同じような問い合わせを自分以外の人が受けた場合に役立つため、
ヘルプデスク全体の財産になります。

また、こまめに対応内容を控えておくことで、
休暇を取る際、他の人は引き継ぎをお願いするときにも役立ちます。

### まとめ
今回記載させていただいた３つの項目は
いずれもヘルプデスク業務に限らないものかとは思いますが、
振り返ってみた際、改めて大切さに気付いた項目となります。
ぜひ機会があれば、ご自身の業務を遂行する上で重要なポイントを洗い出してみていただければと思います。

以上、水野でした。
Excel関数でちょっと躓いた話(VLOOKUP編)


こんにちは！エンジニアの篠原です:penguin:
先日、業務でExcelを使用していた際に
データを参照しようとVLOOKUP関数を使用したところ
意外と躓くポイントがいくつかありましたので
備忘録として残しておこうと思います。


## ①検索値セルと検索範囲セルの型違い

これは検索値セルが数値の場合に良く起こるエラーで
個人的にこれが一番ひっかかる確率が高いと思います。

例として以下のような書き方をした時、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/40a08f54-d74b-692c-1479-83191c725c9e.png)

検索値セル(<font color="red">赤枠</font>)はセルの型が<INS>数値</INS>に対して、
検索範囲セル(<font color="#1e90ff">青枠</font>)はセルの型が<INS>文字列</INS>です。

この場合セルの型が不一致の為、検索に引っかからず<INS>#N/A</INS>となってしまいます。

検索値セルが数値の場合で、エラーが表示された場合は
まず型が一致しているかどうか確認しましょう:ok_hand:


## ②検索値セルの項目が検索範囲の1列目ではない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/cffdd24b-7587-d2db-14bf-a207ea295fe8.png)

上図のように、社員ID(<font color="red">赤枠</font>)を検索値とし、
<font color="#1e90ff">青枠</font>で囲った部分を検索範囲とした場合、結果は<INS>エラー</INS>となります。
原因としては、<INS>検索値は検索範囲の1列目にする必要があるから</INS>です。

必ず、検索値＝検索範囲の1列目になっているか確認しましょう:ok_hand:


## ③近似一致（TRUE）で検索しようとしている
VLOOKUP関数の引数で一番最後に渡すものが

・**近似一致（TRUE）**
・**完全一致（FALSE）**

のどちらかになります。

それぞれどういうものかというと…

・**近似一致（TRUE）**
　検索値と合致する値があればその行を参照する
　合致する値がなければ値を超えない範疇での
 　最大値が入っている行を参照する
  <br>

・**完全一致（FALSE）**
　検索値と完全に一致するものを探し、あれば表示し無ければエラー
 <br>

上記を理解せず、TRUEを入れてしまうと
想定している結果を表示してくれない場合があります。
また、検索値が文字列の場合は前方一致での検索になるので
これもまた結果が変わってきてしまいます。




## まとめ
今回は使えると便利ですが、データの形式や検索方法によっては
簡単には動いてくれないVLOOKUP関数を紹介しました。
他関数でも見つけ次第、まとめていきたいと思います:memo:




以上、篠原でした:penguin:



## 参考

https://www.mouse-jp.co.jp/mouselabo/entry/2023/12/13/100020

https://www.r-staffing.co.jp/sol/cont/biz_oa_6/
[paiza]N倍の文字列

# 下から順に。。。

https://paiza.jp/works/mondai/d_rank_skillcheck_archive/square

# 面倒くさいので画面パタメータをListでもらった後のFunctionだけ
ちなみに引数のListを作ってる箇所は[こっちの記事](https://qiita.com/AsilHatake/items/842548e48ae4a0eae119)に書いてあるYO!!

```javascript:square.js
// [問題文（原文）]
// 整数 N が入力されるので、N 個の*を繋げた文字列を出力するプログラムを作成しましょう。
// 例えば N = 3の場合
// ***
// のように出力してください。
function square(lines) {
  if (!Array.isArray(lines) || lines.length !== 1) {
    console.log("1行入れろや！");
    return;
  }
  const repCnt = Number(lines[0]);
  if (!Number.isInteger(repCnt) || repCnt < 0 || repCnt > 100) {
    console.log("1～100の整数入れろや！");
    return;
  }
  console.log('*'.repeat(repCnt));
}

module.exports = {
  square
};
```

repeat関数を使えば、forを書かなくてもスグに同じ文字の連結ができちゃうね。
`"給料上げて！".repeat(∞)`
[解決済み]503 Service Temporarily Unavailable

**[解決しました](#解決20240802)**

# 目的
webサイトをHTTPS化したい。

# 問題
- nginxのエラーログで`FastCGI sent in stderr: "Primary script unknown"`というエラーが発生。
- httpsで接続すると`503 Service Temporarily Unavailable`というエラーだけ表示される。
- EC2のターゲットグループ内でヘルスステータスが`Unhealthy`、詳細が`Request timed out`となっている。
![SCR-20240731-pjta.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798584/71c5dc62-8236-2435-65f2-340315a2bcef.png)

# 状況
正直なところ、初学者なりにいろいろ構って今どんな状況なのか理解できていない。

今日構ったのは
- nginx.conf
- ロードバランサー作成
- ターゲットグループ作成
- セキュリティグループのインバウンドルール設定

主にいじっていたnginx.confでやっていたこととしては、GPTやPerplexityに聞きながら以下を追加。
```:nginx.conf
    if ($http_x_forwarded_proto = 'http') {
    return 301 https://$host$request_uri;
}

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass unix:/var/run/php-fpm/www.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
```
server項目内のlistenを`80`から`10080`に変更
server_nameを`_;`から`dogtype.net www.dogtype.net;`に変更

# 次回
自分でもさまざまな記事を参考にしてAWSの設定をしたため、なぜ`ポート番号10080`なのかとかわかっていない。
なので次回は`ポート番号80`で設定してみようと思う。

ちなみにセキュリティグループで10080の許可、ロードバランサーのリスナーで`HTTP:10080`を設定しHTTPSにリダイレクトするように設定、ターゲットグループのポートは10080と統一しているつもり。

プログラミング歴5ヶ月ほど、まだまだ初学者にはAWS難しすぎて苦しい…。

# 解決(2024/08/02)
直接的な原因はわからなかったものの、ポート変更とロードバランサーのリスナーとルールを編集することで解決しました。

一度ロードバランサー、セキュリティグループ、ターゲットグループ、VPCを作り直しポート番号を`10080`から`80`にしました。
その時点でwebサイトへhttp接続はでき、https接続をすると　**「504 Gateway Time-out」**　と出るようになりました。

次にロードバランサーのリスナーとルールですが、
`HTTP:80`リスナーでは`HTTPS(443)`へリダイレクトするルールを。
`HTTPS:443`リスナーでは`ポート番号80`のターゲットグループへ転送するルールを設定します。
![SCR-20240802-ohqn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798584/8d3d1e88-fab6-bcae-8406-92c7d3f4a1c6.png)
これにて無事HTTPS接続ができるようになりました！

結果として[問題](#問題)のnginxのエラーは出なくなり、503エラーも表示されなくなり、異常のあるターゲットグループは使わないことになりました。

ただ今や当たり前のようにGPTやPerplexityに頼るが、これでは実力が身につかないと危機感を抱いている…。
サイバー攻撃による国内クレジットカード情報漏えいインシデントまとめ/2024年7月公表分

## 概要

- 2024年7月に公表されたクレジットカード情報漏えいインシデントのまとめです

## notes
- この月間に公表したものなので、各インシデントごとの被害発生期間は別です
- どの程度のインシデントと被害が月ごとに発生しているかの備忘録であり報道記事ではないので、当事者等の個別具体的名称は書きません
- 被害に遭った可能性のある人には事業者等より個別に連絡があると思われます


## 当月の被害の概要

- この月は、3件のクレジットカード情報漏えいインシデントが国内で公表されました
- 合計で、68,522件ほどのクレジットカード情報について漏えいの可能性があるそうです

## 当月のインシデント

### 1. リノベーション・住宅用家具建材販売サイト

- 割賦販売法における、クレジットカード情報非保持化タイプと推測されます
- 原因は、当該サイトの脆弱性の放置と推測されます
- 21,398名の個人情報の漏えいの可能性について公表された内容に記載されています
- 1,432名のセキュリティコードを含むクレジットカード情報について漏えいした可能性があります
- クレジットカード情報の漏えい期間は、2021年5月27日～2024年1月15日とのことです
- 2024年1月16日に、警察より漏えいの可能性の連絡を受けてインシデントが発覚したそうです
- 当該インシデントの情報公開について、この事業者には情報隠蔽の傾向が観測されました


### 2. 食品販売サイト

- 割賦販売法における、クレジットカード情報非保持化タイプと推測されます
- 原因は、当該サイトの脆弱性の放置と推測されます
- 27,561名の個人情報の漏えいの可能性について公表された内容に記載されています
- 1,703名のセキュリティコードを含むクレジットカード情報について漏えいした可能性があります
- クレジットカード情報の漏えい期間は、2021年3月1日～2024年4月9日とのことです
- 2024年3月11日に、クレジットカード会社より漏えいの可能性の連絡を受けてインシデントが発覚したそうです


### 3. 菓子食品販売サイト

- 割賦販売法における、クレジットカード情報非保持化タイプと推測されます
- 原因は、当該サイトの脆弱性の放置と推測されます
- 73,961件の個人情報の漏えいの可能性について公表された内容に記載されています
- 65,387件のセキュリティコードを含むクレジットカード情報について漏えいした可能性があります
- クレジットカード情報の漏えい期間は、2021年3月18日～2024年5月28日とのことです
- 2024年5月28日に、警察より漏えいの可能性の連絡を受けてインシデントが発覚したそうです


## 感想

この数年間の傾向と比べて、今月公表されたインシデントの数は平均的ですが被害規模は大きいと思います


## おまけ

### 「クレジットカード・セキュリティガイドライン」

- [経産省：「クレジットカード・セキュリティガイドライン [5.0版]」](https://www.meti.go.jp/press/2023/03/20240315002/20240315002.html)
- [(一社)日本クレジット協会:関連資料](https://www.j-credit.or.jp/security/document/index.html)


### 今月発表された主な脆弱性と修正アップデート

- [JVN#48324254 EC-CUBE 4系におけるプラグインインストール時の入力値チェックの不備](https://jvn.jp/jp/JVN48324254/)
- [JVN#26225832 EC-CUBE 4系用プラグイン「EC-CUBE Web API プラグイン」における格納型クロスサイトスクリプティングの脆弱性](https://jvn.jp/jp/JVN26225832/)
【GitHub】リポジトリ名を変更する

# はじめに

リポジトリ名を変更するとそのリポジトリのリモートリポジトリURLが変更されるので、ローカル環境においても参照するリモートURLを更新する必要がある。


## 手順１．GitHubのウェブサイト上でリポジトリ名を変更する

リポジトリの `settings` から `rename` する。

https://docs.github.com/ja/repositories/creating-and-managing-repositories/renaming-a-repository

## 手順２．ローカル環境でのリモートURLを変更する

```terminal: 以下を順番に実施
$ git remote -v
$ git remote set-url origin <新しいリポジトリ名のURL>
$ git remote -v
```

```terminal: set-urlの後にリポジトリURLが変わってたらOK
$ git remote -v
origin  https://github.com/<username>/<新しいリポジトリ名>.git (fetch)
origin  https://github.com/<username>/<新しいリポジトリ名>.git (push)
```

これでおしまい。

# おわりに

リポジトリ名変更すると、古いURLから新しいURLへのリダイレクトされるんだね、へ～
Azure BastionのSKU紹介

#### はじめに
Azureで仮想マシンを使用するなら、ほぼ使うといっても過言ではないAzure Bastionですが、意外と構成についてはあまり深く考えないですよね。そんなBastionについてざっくり各SKUの特徴をまとめてみようと夏の暑さでオーバーヒートした頭で思ったので記事を書きます。


## SKUの種類
Bastionには以下の4つのプランがあります。
それぞれ見ていきましょう。
1. [Developer SKU](#developersku)
1. [Basic SKU](#basicsku)
1. [Standard SKU](#standardsku)
1. [Premium SKU](#premiumsku)

#### 参考文献
[Docs|Bastionの構成設定について](https://learn.microsoft.com/ja-jp/azure/bastion/configuration-settings)

## DeveloperSKU
+ 無料の軽量SKUという立ち位置
+ 仮想マシンへSSLやRDPで接続ができる
+ 必要最低限の機能といった感じで、追加機能は基本的に使えない
+ 日本リージョンには存在しない
 
#### 利用可能なリージョン（2024/07/31現在）
+ 米国中部 EUAP
+ 米国東部 2 EUAP
+ 米国中西部
+ 米国中北部
+ 米国西部
+ 北ヨーロッパ

## BasicSKU
+ 基本はこのBasicを選択するのが無難。
+ Bastionを自動デプロイするとこれになるっぽい
+ Peeringしている仮想ネットワーク内の仮想マシンにも接続可能
+ 仮想マシンへSSLやRDPで接続ができる
#### 利用可能な追加機能
+ コピー貼り付けが規定で可能

## StandardSKU
+ 使いたい追加機能があるならこのSKUを選択
+ Basic SKUでできることは基本的にStandard SKUでもできる
#### 利用可能な追加機能
+ コピー貼り付け（BasicSKUと違って不使用にもできる）
+ Kerberos認証
+ ネイティブクライアントサポート
+ IPベースの接続
+ 共有可能なリンク
+ Bastionの冗長化

## PremiumSKU
+ Bastionの最上位SKU
+ クライアント-Bastionサーバー間の通信が完全プライベートな環境で利用するケースにおいて使用

#### 利用可能な追加機能
+ コピー貼り付け（BasicSKUと違って不使用にもできる）
+ Kerberos認証
+ ネイティブクライアントサポート
+ IPベースの接続
+ 共有可能なリンク
+ Bastionの冗長化
+ セッションの記録(Preview)
+ Private専用のIPデプロイ
Seleniumでブラウザが立ち上がらなくなったので対処した

## ブラウザが立ち上がらない
最近までwebdriver_managerを使用していたのですが、chrome のバージョン 127.0.6533.72になったことでOSErrorが出たので思い切ってwebdriver_managerは使わずにSeleniumだけでChromeを操作することにしました！


## 前まで使用してたコード

|モジュール名| バージョン |
|:-----------|------------:|
| webdriver_manager| 4.0.1 |
| selenium | 4.2.0 |


```
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.service import Service as ChromeService


options = webdriver.ChromeOptions()
options.add_argument('--lang=ja-JP')

browser = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()), options=options)

browser.set_window_size(2000, 3000)
browser.implicitly_wait(10)

# Googleのホームページにアクセス
browser.get('https://www.google.com/')

# ブラウザを閉じる
browser.quit()
```

※2024/07/31時点ではwebdriver_manager=4.0.2にしたらブラウザ立ち上がりました。


## Seleniumだけに変えたコード

|モジュール名| バージョン |
|:-----------|------------:|
| selenium | 4.23.1 |


```
from selenium import webdriver
from selenium.webdriver.chrome.webdriver import WebDriver

options = webdriver.ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-logging'])
options.add_argument('--lang=ja-JP')
options.add_argument('--window-size=2000,3000')


browser: WebDriver = webdriver.Chrome(options=options)

# Googleのホームページにアクセス
browser.get('https://www.google.com/')

# ブラウザを閉じる
browser.quit()
```

誰かの参考になればと思います！
起動中の docker コンテナのシェルに入る方法

## 背景
起動中のdockerコンテナ内でビルド（yarn build）したかったが、やり方を忘れていたので、備忘録。

## dockerコマンド

まず、そもそもどのコンテナに入ればいいんだという迷子の子猫ちゃん状態なので、実行中のコンテナのリストを表示していく。

```terminal:$
docker-compose ps
```

このコマンドは、現在実行中のコンテナの一覧を表示してくれる。必要なコンテナのCONTAINER IDまたはNAMESを確認。

そして、ターゲットのコンテナを見つけたら、ぽん！

```terminal:$
docker exec -it <CONTAINER ID or NAME> /bin/bash
```

または、コンテナのOSによっては、以下のように異なるシェルを使用する場合もある。その場合用はこちら。

```terminal:$
docker exec -it <CONTAINER ID or NAME> /bin/sh
```

もちろん、`<CONTAINER ID or NAME>` は先ほど自分で確認したコンテナのIDまたは名前に置き換える必要がある。

これで、そのコンテナ内でシェルが開き、ターミナル上で操作を行うことができる。最高だ！

ちなみに、シェルを抜けたい場合は。

```terminal:$
exit
```

簡単だぜ。

## お疲れ様でした。
わからないところ、間違っているところ、もっといい方法がある場合は、コメントでもDMでも教えてください。
[paiza]文字の一致

# 同じ文字かどうかチェック
https://paiza.jp/works/mondai/d_rank_skillcheck_sample/diff_str

# 面倒くさいので画面パタメータをListでもらった後のFunctionだけ
ちなみに引数のListを作ってる箇所は[こっちの記事](https://qiita.com/AsilHatake/items/842548e48ae4a0eae119)に書いてあるYO!!


```javascript:sameStr.js
// [問題文（原文）]
// 2 つの文字列 a, b が入力されます。文字列が一致していれば "OK" 、異なっていれば "NG" と出力してください。
function sameStr(lines) {
  if (!Array.isArray(lines) || lines.length !== 2) {
    console.log("2個の文字を入れろや！");
    return;
  }
  if (!lines.every(line => line.length > 0 && line.length < 101)) {
    console.log("1～100文字を入れろや！");
    return;
  }
  console.log(lines.every(line => line === lines[0]) ? "OK" : "NG");
}

module.exports = {
  sameStr
};
```

コレがJavaだと初心者がよくやりがちな「==」で比較して一致しない問題が合ったりするけど、JavaScriptの文字の比較は超簡単。
とりあえず小難しく書くためにeveryとか使って、配列の１つ目と全部一致かどうかという判定方法で記載してみました。
※今後の保守とかで複数来てもコレならスグに対応できるような柔軟な書き方、保守とかありえんけど
yukicoder No.48 ロボットの操縦　解説

[問題文](https://yukicoder.me/problems/no/48)
# 解説
まず、いったん次の問題について考えよう。
> 太郎君はロボットを遠隔で操縦している。
このロボットは現在$(0,0)$の座標に立っていて北の方向を向いている。
太郎君はいまこのロボットを$(X,Y)$の座標に移動させたいと思っている。
ロボットに出来る命令は、$1$回につき以下のうちいずれかの命令を選んで指示することができる。
・向いている方向に $K$距離だけ前進する。$K$は、$1\leqq K\leqq L$ の範囲で、命令のたびに指定することができる。
また、**好きな回数だけ向いている向きを変えることができる**。
このとき、あり得る最小の操作回数を求めよ。

まず、$x$座標と$y$座標はそれぞれ独立である。よって、それぞれを一次元のように考えると、**No.46 はじめのn歩と同じような問題になる**([はじめのn歩](https://yukicoder.me/problems/no/46))。この問題でも、できるだけ$K$を$L$に近づけて歩かせるのがいいだろう。

では、本題に戻る。
回転回数に関して、じつは**高々2回で完結する**。
$0\leqq Y$なら、先に$Y$を動かしてから$X$が0かどうかによって回転すればよい。このとき、回転回数は$0$または$1$。
$0> Y$なら、先に$X$を動かしてから$Y$を動かせばよい。この時、回転回数は$2$回。
では、回転回数はどのように求まるか。これは、次のように求まる。
・$Y\geqq 0$&$X=0$なら回転回数は$0$。
・$Y\geqq 0$&$X!=0$なら回転回数は$1$。
・$Y<0$なら回転回数は$2$。
よって、回転回数及び移動回数の総和を求めれば完結する。
$X=10^9,Y=10^9,l=1$のとき答えが32bit型に収まらないので、long long型を使おう。

# C++での解答例
```C++
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
//upfloorは移動回数を正確に求める関数
ll upfloor(ll x, ll m) {
  ll r=(x%m+m)%m;
  return (x-r)/m+(bool)(x%m);
}

int main() {
  ll x,y,l;cin>>x>>y>>l;
  ll idou=upfloor(abs(x),l)+upfloor(abs(y),l);
  ll kai;
  if(y>=0&&x==0)kai=0;
  else if(y>=0)kai=1;
  else kai=2;
  cout<<idou+kai<<endl;
}
```
Lockクラス（.NET 9）

## 参考
この記事は、以下の動画を参考にしています。
詳しくは、動画をご覧ください。

https://youtu.be/b4sUebHOTi4?si=83ct795dplZqYFxB

また、以下の記事も参考になります。

https://ufcpp.net/blog/2024/4/lock-class/

リファレンス

https://learn.microsoft.com/ja-jp/dotnet/api/system.threading.lock?view=net-9.0

## lock文のためのLockクラス
.NET 8までは、`object`のインスタンスを使って、ロックを掛けていました。
```C#
// .NET 8まで
class Example
{
    // lockをかけるためのインスタンス
    private static readonly object _lock = new();

    public void Method()
    {
        lock (_lock)
        {
            // 複数スレッドが競合する処理
        }
    }
}
```

.NET 9では、`System.Threading.Lock`クラスのインスタンスを使って、ロックを掛けることができるようになります。
`System.Threading.Lock`を使うと、ロックが速くなります。
```C#
// .NET 9
class Example
{
    // lockをかけるための Lockクラス のインスタンス
    private static readonly System.Threading.Lock _lock = new();

    public void Method()
    {
        lock (_lock)
        {
            // 複数スレッドが競合する処理
        }
    }
}
```

`lock`文を使わずに、ロックを掛けることも可能です。
```C#
// .NET 9
class Example
{
    // lockをかけるための Lockクラス のインスタンス
    private static readonly System.Threading.Lock _lock = new();

    public void Method()
    {
        using (_lock.EnterScope()) // Lock.Scope構造体を利用
        {
            // 複数スレッドが競合する処理
        }
    }
}
```
```C#
// .NET 9
class Example
{
    // lockをかけるための Lockクラス のインスタンス
    private static readonly System.Threading.Lock _lock = new();

    public void Method()
    {
        _lock.Enter(); // TryEnterもある
        try
        {
            // 複数スレッドが競合する処理
        }
        finally
        {
            _lock.Exit();
        }
    }
}
```
HTTP接続 セキュリティグループ設定

# はじめに
HTTP接続とか、セキュリティグループのインバウンド設定のソースってなんだ？
何をしたらいいんだ？ってなったので、調べたことをまとめておきます

# 今回作成したい条件
- セキュリティグループで、HTTPを許可する
- EC2のパブリックIPにHTTP接続が「できる」ことを確認する
- セキュリティグループからHTTPの許可を削除する
- EC2のパブリックIPにHTTP接続が「できない」ことを確認する

# セキュリティグループとは
AWS（Amazon Web Services）における仮想ファイアウォールです
インスタンスの通信を遮断する目的で使用されます
1つのセキュリティグループには、複数のアクセス許可ルールを設定できます
今回の使用目的は、特定のIPアドレスにのみ通信を許可するために使用します

# インバウンドルールとアウトバウンドルールの違い
#### インバウンドルールとは
外部からEC2インスタンスに向かってくるトラフィックを制御します
これにより、特定のIPアドレス、ポート、プロトコルに対するアクセスを許可または拒否することができます

#### アウトバウンドルールとは
C2インスタンスから外部に向かって出て行くトラフィックを制御します
これにより、インスタンスから外部のIPアドレス、ポート、プロトコルに対するアクセスを許可または拒否することができます

# ルール設定
今回は、SSHとHTTPの2つルールを作成します

![スクリーンショット 2024-07-31 16.51.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/47536640-526f-f712-bc6f-d60de5306f49.png)

ソースで悩みました…😭
ここは、許可したい通信のソース（送信元）を指定するのですが
クラウドの勉強をしていると至る所にIPアドレスが出てくるので、どのIPアドレスなのか最初わかりませんでした💦
結論ここは、自身の使用しているネットワークのIPアドレスです！

家のWifiに繋いでいる場合はWifiのIPアドレス、実家のWifiなら実家のWifiのIPアドレスといった具合に接続しているネットワークによってIPアドレスは変化します

そんなんわからんよー！という方もいらっしゃるとは思うのですが、とても簡単です
このマイIPというのをクリックすればAWSが確認して自動入力されます（便利！）

![スクリーンショット 2024-07-31 16.57.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/677600ad-6bb9-18f6-eb3f-bd66a61b039a.png)

こちらのサイトで自身が利用しているIPアドレスを確認することも可能です！

https://www.cman.jp/network/support/go_access.cgi

ちなみにこのソースに0.0.0.0/0を入力するとどのIPアドレスからも接続が可能になってしまいます！

![スクリーンショット 2024-07-31 17.02.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/e039d9b4-2f07-7c80-14c6-aca909e41900.png)

# HTTP接続確認
HTTP接続確認って何すればいいだろう？と一瞬わからなかったんですが、
めっちゃ簡単でブラウザにIPアドレスを入力して表示されるかっていう話でした！（笑）

- EC2を確認してパブリックIPアドレスを確認します

:::note warn
該当のインスタンスを起動しているか確認する！
:::

![スクリーンショット 2024-07-31 17.09.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/e3866b77-61f3-b9c9-9896-77516b1b12d0.png)

あとは好きなブラウザでIPアドレスを入力するだけです

![スクリーンショット 2024-07-31 17.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/96690098-5ce5-55f2-2f87-33a497010649.png)

無事接続できました！（NGINXの導入は完了しております）

![スクリーンショット 2024-07-31 17.12.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/9afd77d9-b655-3b51-ed14-9afdf610e118.png)

# HTTPの許可を削除し、再度HTTP接続確認

![スクリーンショット 2024-07-31 17.13.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/c46c2c97-c08b-aa08-cd0c-5af17eb1f160.png)

HTTP接続許可を削除したところ、先ほどのIPアドレスを入力しても接続できなくなりました！

![スクリーンショット 2024-07-31 17.18.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782860/ffb223bd-061e-b269-d7b4-aba137570dbc.png)

# おわりに
初めて学習することは、単語もわからないことが多いので理解が遅くなります💦
誤り等ございましたら、ご教示いただけますと幸いです！

# 参照記事
参考にさせていただきました！ありがとうございました！

https://qiita.com/yuyanstart/items/9614c5af4e99ac6f8173
kubernetesのImagePullSecretsの中身を確認する

# はじめに
プライベートレジストリからコンテナイメージをPullする際に、ユーザー名やパスワードなどを登録してImagePullSecretsを作りますが、その中身を確認します。

# 確認

```
$ kubectl get secret image-pull-secret -o yaml
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJucnQub2Npci5pbyI6eyJ1c2VybmFtZSI6Im5yemtmNWtycm93My9BdXRoRG9tYWluL2djb2NpZ2VuZXJhbHVzZXJAZ21haWwuY29tIiwicGFzc3dvcmQiOiJbdilubVhaN083NTJjbClVMVlFQiIsImVtYWlsIjoiYWFAZXhhbXBsZS5jb20iLCJhdXRoIjoiYm5KNmEyWTFhM0p5YjNjekwwRjFkR2hFYjIxaGFXNHZaMk52WTJsblpXNWxjxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx==
kind: Secret
metadata:
  creationTimestamp: "2024-07-25T01:38:13Z"
  name: image-pull-secret
  namespace: default
  resourceVersion: "9662178"
  uid: 63da924b-f76e-4fd4-9c37-6949c315b6cd
type: kubernetes.io/dockerconfigjson
```
Base64でエンコードされてます。

`.dockerconfigjson`をデコードします。

```
$ kubectl get secret image-pull-secret --output="jsonpath={.data.\.dockerconfigjson}" | base64 -d
{"auths":{"nrt.ocir.io":{"username":"nrzkxxxxxxx/xxxxDomain/aa@example.com","password":"XXXXXXXXXX","email":"aa@example.com","auth":"bnJ6a2Y1a3Jyb3czL0F1dGhEb21haW4vZ2NvY2lnZW5lcmFsdXNlckBnbWFpbC5jb206W3XXXXXXXXXX="}}}
```
ユーザー名やパスワード（トークン）などが確認できます。

`auth`以下の値をさらにデコードすると、`ユーザー名:パスワード（トークン）`の形式で出力されます。

```
$ echo "bnJ6a2Y1a3Jyb3czL0F1dGhEb21haW4vZ2NvY2lnZW5lcmFsdXNlckBnbWFpbC5jb206W3YpbXXXXXXXXXXXX=" | base64 -d
nrzkxxxxxxx/xxxxDomain/aa@example.com:XXXXXXXXXXXXX
```

簡単に確認できますので、暗号化などの対応が必要ですね。
Swallow-MS 7Bを試す

# Swallow-MS 7Bを試す

## 前提
　Swallow-MS 7Bとは、Mistral社のLLMを東京工業大学が日本語特化にチューニングしたもの。
https://tokyotech-llm.github.io/swallow-mistral
https://huggingface.co/tokyotech-llm/Swallow-MS-7b-v0.1

## セットアップ
　基本的にはHuggingFaceに記載されたとおりに実施すれば良いが、そのまま実施するとCPUでの動作となってしまい、非常に遅い。
　そのためセットアップは少し工夫が必要。

1. CUDA Toolkitをインストール
2. cnDNNをインストール
3. venvを作成
4. 公式requirements.txtから「torch」を除去
5. pytorch公式サイトから環境に応じたtorchをインストール
6. pip install -r requirements.txt

## 実行
ソースコードはサンプルのまま実行可能

## 必要スペック
瞬間的にVRAMを13GBくらい使うので、RTX3060だと若干苦しい？

## 実行結果
※warningがいっぱい出てる・・・
※プロンプトが悪いからか、内容はかなり怪しい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960081/19fc740f-b23d-74e3-5bd7-1b67a33f035f.png)
Python で JSON をきれいにフォーマットする方法

<!--
JSON を整形する手軽な方法として Python に標準装備されている json.tool が知られており、私は使う度にググっています。
しかし、`python3 -m json.tool` で上位に出てくる記事が古くなってきているので、新しくまとめてしまおうという記事です。
-->

JSON をフォーマットする手軽な方法として Python に標準装備されている json.tool が知られていますが、この機能に更新が入るようなので記事も更新しました。

## 何が変わる？

`-m json.tool` ではなく `-m json` からも起動するようになるようです。
また、`-m json.tool`からもこれまで同様に起動できるようです。

https://discuss.python.org/t/allow-python-m-json-to-work-in-addition-to-python-m-json-tool/59835

https://github.com/python/cpython/issues/122873

この変更の提案者の方が `json.tool` の歴史的経緯を調査したブログです。
この記事はこちらを紹介するために更新したようなものです。興味深いので読んでみてください。

https://treyhunner.com/2024/08/why-does-python-m-json-not-work/

Reddit における議論:

https://www.reddit.com/r/Python/comments/1ehsdpz/the_history_behind_why_python_m_json_doesnt_work/


## 基本的な使い方

`-m` は `sys.path` が指定するディレクトリに置かれたモジュールを呼び出すためのオプションです。

```bash
$ echo '{"name":"Alice","job":"Engineer","id":"101"}' | python3 -m json.tool
# {
#     "name": "Alice",
#     "job": "Engineer",
#     "id": "101"
# }
```

日本語を使うと文字がエスケープされることに注意

```bash
$ echo '{"name":"花子","job":"営業","id":"201"}' | python3 -m json.tool
# {
#     "name": "\u82b1\u5b50",
#     "job": "\u55b6\u696d",
#     "id": "201"
# }
```

## オプション

- 日本語がエスケープされないようにする `--no-ensure-ascii`

```bash
$ echo '{"name":"花子","job":"営業","id":"201"}' | python3 -m json.tool --no-ensure-ascii
# {
#     "name": "花子",
#     "job": "営業",
#     "id": "201"
# }

```

- キーをソートする `--sort-keys`
```bash
$ echo '{"name":"Alice","job":"Engineer","id":"101"}' | python3 -m json.tool --sort-keys
# {
#     "id": "101",
#     "job": "Engineer",
#     "name": "Alice"
# }
```

- インデントの数を変更する `--indent N`
```bash
$ echo '{"name":"Alice","job":"Engineer","id":"101"}' | python3 -m json.tool --indent 12
# {
#             "name": "Alice",
#             "job": "Engineer",
#             "id": "101"
# }
```

- ミニファイする `--compact`
```bash
$ echo '{"name":"Alice","job":"Engineer","id":"101"}' | python3 -m json.tool --compact
# {"name":"Alice","job":"Engineer","id":"101"}
```

## Link

- [json — JSON encoder and decoder — Python 3.13.0b4 documentation](https://docs.python.org/3.13/library/json.html#json-commandline)
    - 作成時点で最新の公式ドキュメント
connectrpc/connect なら gRPC 互換で curl も叩ける

タイトルまま。

最近、利用し始めたのですが開発体験もとてもよくなったので記事を小出しにしていく。
https://github.com/connectrpc/connect-go

## どんなもの？

https://connectrpc.com/docs/introduction/#seamless-multi-protocol-support

抜粋して意訳すると

- pro仕様のシンプルさ
便利な middleware などもなにもないプロ仕様のため、欲しいものは利用者で実装する必要はあります。
- マルチプロトコル
gRPC,gRPC-Web と connect 独自のプロトコルをサポートしています。

## なにがよかった？
connect 独自のプロトコルがよい仕事をしているらしく、みんな大好き curl で動作検証が出来ます。

https://connectrpc.com/docs/curl-and-other-clients/#curl

その他にもいろいろ利点はあるけども、 port-forward したり微妙にめんどくさい gRPC での動作確認が curl で出来るという感動。
Liff開発でメッセージ送信まで

# 目次

[1 - アプリ](#1-アプリ)
[2 - 準備](#2-準備)
[3 - 開発開始](#3-開発開始)
[4 - 最後に](#4-最後に)


# 1 アプリ

liffとは

https://developers.line.biz/ja/docs/liff/overview/

Liffでメッセージを送信するだけのアプリを作成しました。
lineで開く事を前提に開発しているのでログイン機能などは実装していません。
2024年7月に作成しています。バージョンなどによって動かない可能性があります。

https://github.com/e23007/line-q

# 2 準備

![Screenshot from 2024-07-31 14-50-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3746411/9825bc7b-7817-e04d-5dce-353091501d08.png)

.gitignoreに .envを追加します。
.envを作成して
REACT_APP_LIFF_ID=作成したLIFFID
で準備はできました。

# 3 開発開始

1-liffで作成したアプリにあるgitのliff-q/src/App.jsから抜き出しています。
下記のようにすると初期化ができます。

``` Diff_js
//liffの初期化とのLiffID指定
  useEffect(() => {
    const create=async ()=>{
    console.log("start liff.init()...");
    await liff
      .init({ liffId: process.env.REACT_APP_LIFF_ID })
      .then(() => {
        console.log('init() OK')
      })
      .catch((error) => {
        console.log(`liff.init() failed: ${error}`);
      });
    }
    create()
  }, []);
  ```
そして、簡単に入力した文字を送信するプログラムを書きます。
``` Diff_js
  const [message,setMessage]=useState("") //メッセージ
  //メッセージ送信関数
  const post=()=>{
    liff.sendMessages([
      {
        type:'text',
        text:`${message}`,
      }
    ])
  };
```
出来たらnpm startで動かしてみましょう。
まずLiffIdがちゃんとセット出来ていると適当なところで右クリックして検証が出るとコンソールというところに「init.OK()」と出るはずです。
まだメッセージは送信できません。

__次にデプロイですが、環境変数にkey[REACT_APP_LIFF_ID]value[liffid]を設定しましょう。__
忘れがちで私は変数を設定せずに長い時間悩まされました。気をつけてください。

liffのエンドポイントを設定するところにデプロイできたURLを設定します。

そのURLを適当なLine上のトークに貼ります。
クリックして文字を入力送信するとライン上に入力した文字が表記されていたら成功です。

お疲れ様でした。

# 4 最後に

:::note alert
Keepメモで使用しないでください
エラーが起きます。
エラー内容：不正な受信
:::

また、携帯の画面でエラーメッセージの内容が見たい場合は
console.log()では無くwindow.alertで出るはずです。少なくともiphoneは
例
```
//liffの初期化とのLiffID指定
  useEffect(() => {
    const create=async ()=>{
    console.log("start liff.init()...");
    await liff
      .init({ liffId: process.env.REACT_APP_LIFF_ID })
      .then(() => {
        window.alert('init() OK') //console.log(init() OK')を変更
      })
      .catch((error) => {
        window.alert(`liff.init() failed: ${error}`);//ここも変更
      });
    }
    create()
  }, []);
```

今回はメッセージを送るだけなので、意味がないのですが、
私は割り勘アプリを作成してみました。

https://liff.line.me/2005903156-xvzMMPQv

gitはプライベートに設定しているので質問や改善点がありましたら遠慮なくお願いします。
皆さんのなにか作ったものがありましたら教えてください。
Ubuntu 24.04 SSH設定 でパスワード禁止にする

## Ubuntu 24.04でのSSH設定トラブル解決記録

この記事では、Ubuntu 24.04を使用してLAMP環境を構築している際に直面したSSH設定の問題と、その解決方法について説明します。

### 背景
研究の一環として、Ubuntu 24.04でLAMP環境をセットアップしました。その際、SSHアクセスのセキュリティを強化するために、/etc/ssh/sshd_configファイルでパスワード認証を無効にする設定を行いました。

### 問題
設定後もパスワード認証が有効のままになっていました。具体的には、パスワード認証をオフにするために`PasswordAuthentication no`を設定したにもかかわらず、依然としてパスワードでログインが可能でした。

### 試したこと
1. **SSHDの再起動**: 
```bash
sudo systemctl restart sshd
```
コマンドでSSHDを再起動しましたが、状況は変わりませんでした。
2. **OSの再起動**: サーバー自体を再起動しても問題は解決しませんでした。
3. **設定ファイルの確認**: /etc/ssh/sshd_configファイルの設定を再確認しましたが、誤りは見つかりませんでした。

### 原因
問題の原因は、/etc/ssh/sshd_configでインクルードしていた別の設定ファイルにありました。そのファイル内でパスワード認証が有効に設定されていたため、メインの設定ファイルの設定が上書きされていました。具体的には、
```
Include /etc/ssh/sshd_config.d/*.conf
```
という設定を見落としていたため、/etc/ssh/sshd_config.d/配下のファイルが読み込まれていました。そこで確認したところ、デフォルトで設置されていたファイル内に
```
PasswordAuthentication yes
```
と設定されているものがありました。

### 解決方法
インクルードされた設定ファイルも含め、すべてのSSH設定ファイルを確認し、
```
PasswordAuthentication no
```
を明確に設定しました。その後、再度SSHDを再起動することで、無事にパスワード認証を無効化することができました。

### 教訓
SSH設定を変更する際は、メインの設定ファイルだけでなく、インクルードされるすべてのファイルを確認することが重要です。特にセキュリティ関連の設定では、思わぬ場所で設定が上書きされることがあるため、全体を見渡した確認が必要です。

---

この記事が同様の問題に直面している方の助けになれば幸いです。
Vant のコンポーネントがPCで動かない件について

フロントエンド開発初めて1年未満のひよっこエンジニアです。

今回は`Vant` というモバイル Web アプリ用のUIフレームワークをつかっての開発で困ったこと紹介していきます。

公式さまは[こちら](https://vant-ui.github.io/vant/#/en-US)。

## 前提として

環境はこちら。

>Windows
>Nuxt3

## 仮想キーボード動かない問題

Vantを使っていい感じに数字入力の機能ができたっ！

さっそくテスト～、とか思った時に発覚したこの問題…。

実際にみていただきますとこんな感じです。

### スマホ画面での動き

よし、ちゃんとうごく...。

![スマホ対応のみ.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3643677/f4474606-104a-b263-964c-0af5685e0420.gif)

### PC画面での動き

キーボードが出てこない（表示されない）問題...。

![PC画面.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3643677/12124282-fa0c-9557-3d16-98e2ff11cc73.gif)

## 解決方法

### ①キーボードを表示させる

これは`Vant` の設定をコピペして、処理のトリガーをタッチイベントにしていたのが原因でした。

```html:変更前
<!-- 変更前 -->
<van-cell @touchstart.stop="show = true">入力された値は：{{number}}</van-cell>
```

タッチイベントをクリックイベントで動くように変更します。

```html:変更後
<!-- 変更後 -->
<van-cell @click="show = true">入力された値は：{{ number }}</van-cell>
```

これで何とか表示されるように！

...。しかしキーボードをおしても反応しない...。

![PC画面 キーボードのみ修正.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3643677/fe0558f9-5efc-145a-82df-459e21fc71ba.gif)

### ②キーボードが押した！を分からせる

どうやらキーボードを`押した`というイベント自体が内部で認識されていない様子...。

しょうがないので、処理を自前で作成しました。

```vue
<template>
  <div class="default-container">
    <van-cell @click="show = true">入力された値は：{{ number }}</van-cell>

    <van-number-keyboard
      v-model="number"
      theme="custom"
      :show="show"
      :extra-key="['.']"
      delete-button-text="削除"
      close-button-text="閉じる"
      @blur="show = false"
    />

    <van-number-keyboard
      theme="custom"
      v-model="number"
      :show="show"
      :extra-key="['.']"
      @click="onClickKeyboard($event, 'numValue')"
      delete-button-text="削除"
      close-button-text="閉じる"
      @blur="show = false"
    />
  </div>
</template>
<script setup lang="ts">
const show = ref(false)
const number = ref('')

const onClickKeyboard = (eVentValue: any, valueName: string) => {
  // 閉じるボタン押下の場合
  if (eVentValue.target.outerText == '閉じる') {
    if (valueName == 'numValue') {
      show.value = false
    }
    return
  }
  // 削除ボタン押下の場合
  if (eVentValue.target.outerText == '削除') {
    if (valueName == 'numValue') {
      // 後ろから一文字削除
      number.value = number.value.slice(0, -1)
    }
    return
  }
  // 数字入力の場合
  if (valueName == 'numValue') {
    if (number.value) {
      number.value = number.value + eVentValue.target.outerText
    } else {
      number.value = eVentValue.target.outerText
    }
  }
}
</script>
```

これでやっと動くように！

![完成版.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3643677/3afb5cb5-37af-a149-a9a4-837f230e80b8.gif)


長い道のりでした...。

## まとめ

今回は`Vant`を使用した、仮想キーボードの作成で困ったことを書きましたが、

他にもPC画面で動かないコンポーネントがちらほらありました。

その話はまたどこかでっ！

真相は謎ですが、`Vant`は公式さまも言ってるように **モバイル Web アプリ用** のUIフレームワーク！

PCでは動かない処理があるのかもですね...。
[DRF]Serializerって何やってるのか

# Serializerとは

Djangoの勉強をすると出てくる(正確にはDjango REST framework)シリアライザーさん。
<br>
書き方がスッキリしててわかりやすいのですが、なんとなくブラックボックス的でもあるので自分の勉強のまとめとして記事を書きます。

# Serializerの役割
簡単にいうとモデルに格納するとか、viewsでリクエストを処理するとかそういう時に呼び出されています。

もう少し具体的にいうと
Pythonオブジェクト(models.pyの記述とか)→JSONやXMLなどに変換
という役割を担っています。

## APIとの関係について
APIとどのような関係で動くか、と考えるとわかりやすいです。
### データの出力
データベースからデータを取得し、そのデータをserializerに渡します。その際、前述のようにオブジェクトからJSONなどの形式に変換してAPIレスポンスとして返します。

### データの入力
APIで入力を受け付けた後、serializerはそのデータの検証を行なってデータベースへの保存を行います。

# 例
実際にどういう感じで定義していくのか、例を示します。


```python:models.py
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)

class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    publication_date = models.DateField()
    isbn = models.CharField(max_length=13, unique=True)
    price = models.DecimalField(max_digits=6, decimal_places=2)
```
著者データと書籍データを格納するテーブルを定義しています。
著者データは名前とEメール、書籍データはタイトル、著者(Autherのテーブルの外部キーでもある)、出版日、ISBN、価格を保存します。



```python:serializers.py

from rest_framework import serializers
from .models import Author, Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['id', 'title', 'author', 'publication_date', 'isbn', 'price']

class AuthorSerializer(serializers.ModelSerializer):
    books = BookSerializer(many=True, read_only=True, source='book_set')

    class Meta:
        model = Author
        fields = ['id', 'name', 'email', 'books']
```

これでAPIをつかって書籍のデータと著者データを呼び出すことができる。
AuthorSerializerクラスでbooks = BookSerializer~~として呼び出していて、さらにsource='book_set'としているので、Authorモデルから逆参照をすることができます。そのため著者データを呼び出した時には著者の書籍情報が併せて取得されます。(複数の著書がある場合を考慮してmany=True)になっています。

たとえば、下のような感じのデータで取得することができます。
```json
{
  "id": 1,
  "name": "ATOM00",
  "email": "atom@example.com",
  "books": [
    {
      "id": 1,
      "title": "本タイトル",
      "publication_date": "2024-07-31",
      "isbn": "0000000000",
      "price": "1000"
    },
    // 他の本のデータ...
  ]
}
```

ちなみにfieldsの記述方法については、今回全てのフィールドを呼び出してるので```fields = __all__```としても同一の内容になる。

# 参考文献
[Django REST framework - Serializers](https://www.django-rest-framework.org/api-guide/serializers/)
'rubygems/user_interaction' を使うと、外部 Gem 無しで簡単なプロンプト UI を実装できる

RubyGems 内には、 `rubygems/user_interaction` という (RubyGems 用の) プロンプト UI を実装するためのヘルパーがあります。

```ruby
require 'rubygems/user_interaction' # 標準ライブラリなので、これ自体のインストールは不要

ui = Gem::ConsoleUI.new

ui.ask('What is your name?')
# What is your name?  tomoasleep
# => "tomoasleep"

ui.ask_yes_no('Are you ok?')
# Are you ok? [yn]  y
# => true

ui.ask_yes_no('Are you ok?', true)
# Are you ok? [Yn]
# => true

ui.choose_from_list('What is your favorite food?', ['ramen', 'sushi', 'tempura'])
# What is your favorite food?
#  1. ramen
#  2. sushi
#  3. tempura
#
# > 1
# => ["ramen", 0]
# > 2
# => ["sushi", 1]
```

RubyGems 内での利用を想定しているので、基本的には [tty-prompt](https://github.com/piotrmurach/tty-prompt) や [cli-ui](https://github.com/Shopify/cli-ui) などの gem を使う方が安定していて良いと思いますが、使い捨てのコードで gem をどうしてもインストールしたくない場合は覚えておくと良いかも知れません。

## おまけ: [tty-prompt](https://github.com/piotrmurach/tty-prompt) を使う場合

```ruby
require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'tty-prompt'
end

prompt = TTY::Prompt.new

prompt.ask('What is your name?')
# What is your name? tomoasleep
# => "tomoasleep"

prompt.yes?('Are you ok?')
# Are you ok? (Y/n)
# => true

prompt.select('What is your favorite food?', ['ramen', 'sushi', 'tempura'])
# What is your favorite food? (Press ↑/↓ arrow to move and Enter to select)
# ‣ ramen
#   sushi
#   tempura
# => "ramen"
```

## おまけ2: [cli-ui](https://github.com/Shopify/cli-ui) を使う場合

```ruby
require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'cli-ui'
end

# または、
# require 'cli/ui'

CLI::UI.ask('What is your name?')
# ? What is your name?
# > tomoasleep
# => "tomoasleep"

CLI::UI.confirm('Are you ok?')
# ? Are you ok? (Choose with ↑ ↓ ⏎)
# > 1. yes
#   2. no
#
# ? Are you ok? (You chose: yes)
# => true

CLI::UI.ask('What is your favorite food?', options: ['ramen', 'sushi', 'tempura'])
# ? What is your favorite food? (Choose with ↑ ↓ ⏎, filter with 'f')
# > 1. ramen
#   2. sushi
#   3. tempura
#
# ? What is your favorite food? (You chose: ramen)
# => "ramen"
```
【Rails】【JavaScript】RailsでJavaScriptを利用する方法について

Rails初学者の学習内容の備忘録です。
間違いや補足等あればご指摘いただけると幸いです。

学習を進めている中で「importmap?webpacker?なにが違うんや...」となったので、今回はRailsでJavaScriptを利用する方法についてまとめました。

# RailsでJavaScriptを利用する主な方法
**1.Sprockets**
・主にRails6以前に利用されていた。
・JavaScriptファイルはapp/assets/javascriptsディレクトリに置かれる。
```application.js
//= require rails-ujs
//= require_tree 
```

**2.Webpacker**
・Rails6より導入され、JavaScriptをモジュールとして管理するために使われる。
・app/javascript/packsディレクトリにJavaScriptファイルを置かれる。
```application.js
import Rails from "@rails/ujs"
Rails.start()
```

**3.importmap**
・Rails 7から導入された新しい方法。
・JavaScriptモジュールをブラウザで直接importできる。
・config/importmap.rbでJavaScriptパッケージのマッピングを設定する。

要件に応じて、適切な方法を選ぶことが大事ですね。
Numlockキーの無効化

Numlockでテンキーの使い方が変わるのが嫌なので、備忘録がてら。

## batファイルの作成
バッチファイル作成して以下をメモ帳にコピペしてください。（詳しくはbat作成などで検索）

```dosbatch:Numlockキーの設定.bat
@echo off
set /p input_key="Numlock設定(0:無効化 1:有効化)=

if "%input_key%" == "0" (
    reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout" /v "Scancode Map" /t REG_BINARY /d "0000000000000000020000007a00450000000000" /f
    echo NumLockを無効にしました。次回サインイン後に適用されます。
) else if "%input_key%" == "1" (
    reg delete "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout" /v "Scancode Map" /f
    echo NumLockを有効にしました。次回サインイン後に適用されます。
) else (
    echo 操作をキャンセルしました。
)
pause
```

## 作成したbatファイルを実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804239/f90a58c4-f4fb-4336-d1d0-4f0d2c5af4d4.png)

**0を入力してEnter→無効化**
**1を入力してEnter→有効化**

0を入力して無効化します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804239/40bda039-86f0-ab7a-3204-388b184fe39f.png)

## サインアウトして、再度サインイン
反映させるには一度サインアウトしてから、再度サインインする必要があります。
スタートメニューからサインアウトしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804239/12bbf2bd-c264-283c-54dc-40f6da442c19.png)

再度サインインしたら、反映されていることを確認して完了。
有効化する場合も実行時1を入力して、あとの操作は同様です。
配列からデータを取り出す方法

# 配列からデータを取り出す方法

## 1. データの構造を理解する

- **配列（Array）**:
  - **説明**: 複数のデータを順番に並べたリストです。例えば、成績表に記載された点数が「80, 90, 70」のように、データの順序が重要な場合に使用します。
  - **用途**: データの順序が重要な場合や、同じ種類のデータが複数あるときに適しています。

- **オブジェクト（Object）**:
  - **説明**: データを名前（キー）とその値（バリュー）のセットで管理します。例えば、学生の情報を「名前、年齢、成績」のようにまとめるときに使用します。
  - **用途**: 複数の異なる情報をひとまとめにする必要があるときに便利です。

## 2. 特定のデータを探す

- **方法**:
  - 配列の中に複数のオブジェクトが含まれている場合、特定の条件に合うオブジェクトを探すために `find()` メソッドを使用します。
  - **`find()` メソッド**: 配列の中から条件に合う最初のオブジェクトを見つけるためのメソッドです。条件に合うオブジェクトが見つからない場合は `undefined` を返します。

## 3. 条件を指定する

- **説明**:
  - `find()` メソッドには「どの条件でデータを探すか」を指定します。この条件は「関数」として記述します。
  - **関数の役割**: 配列の各要素に対してこの関数が実行され、条件に合うかどうかをチェックします。

## 4. 特定のデータを取り出す

- **方法**:
  - 条件に合ったオブジェクトが見つかったら、そのオブジェクトから必要なデータを取り出します。これは、オブジェクトの特定のプロパティ（属性）にアクセスすることで行います。
小ネタ： CancellationTokenはどうやって作られるか？

主に備忘録的な小ネタシリーズ。

# 疑問
`CancellationToken`ってアチコチで使う。
大体が`CancellationTokenSource.Token`で作るんだけど、プロパティだから何回参照しても同じ？

# 回答
`CancellationTokenSource.Token`って見た目はプロパティなんだけど、ソースを見てみたらこんな感じだった。

```C#:CancellationTokenSource.cs より
    public CancellationToken Token
    {
        get
        {
            ThrowIfDisposed();
            return new CancellationToken(this);
        }
    }
```

__おい、毎回Newしとるやんけ！！！__

でも、
```C#:hoge
    CancellationTokenSource tokenSource = new CancellationTokenSource();

    CancellationToken token1 = tokenSource.Token;
    CancellationToken token2 = tokenSource.Token;

    Assert.Equal(token1, token2);
```

なんてテストを書くとAssertは通る。つまり`token1 == token2`は`true`になる。

これは単純に`CancellationToken`が`IEquatable<CancellationToken>`を継承しているから。
で、何をもって同じと判断しているかというと、元になる`CancellationTokenSource`が同じ(`Equal()`)であれば「同じ」と見なされている。

蛇足で、`GetHashCode()`もしっかりOverrideされていて、元になる`CancellationTokenSource`の`.GetHashCode()`を引っ張ってくるようになっている。

ついでに、`CancellationToken`って`struct`なのね。知らんかった。
ってことはメソッドの引数にしたりすると`struct`は値型(Value Type)なのでコピー渡しされるってことかね？？

`Assert.Same()`で`CancellationToken`同士の参照を比較しようとしても、「Assert.Same()にValue Typeを入れないでね。」とレコメンドが出る。ま、そうだよね。

もしかするとCLR Runtime側で何か特別扱いしているのかもしれないけど、メソッドの引数にセットしたりするとコピー渡しされるんだろうなー。パフォーマンス原理主義者は怒るんだろうな～。
とか、考えてみる。

# Register()は？？
ってことは、だ、
メソッドの引数に`CancellationToken`渡して渡し元と渡し先で
`token.Register(() => { ほげほげ}`
とかやるとどうなるんだろう？？

ちなみに`CancellationToken.Register()`は、そのToken(正確にはTokenSource)でキャンセルを行った後に実行したいActionを登録しておくことができるメソッドです。

……ってことで調べてみました。ソースを。

* `Register()`は戻り値として`CancellationTokenRegistration`というClassのオブジェクトを返す。
* `Register()`の中で、作った`CancellationTokenRegistration`を、Tokenの元のTokenSourceに登録している。(大雑把に言えば、`CancellationTokenSource.Register()`へのショートカットですね。どっちにRegister()しても結局同じ。)
* `CancellationTokenRegistration`を`CancellationTokenSource`や`CancellationToken`から`.Unregister()`すると、キャンセルされたときにそのCallbackは __実行されなくなる__。
* もうひとつ、`CancellationTokenRegistration`自体を`Dispose()`すると`Unregister()`されたのと同じ効果がある。
* キャンセル時のCallbackは`CancellationTokenSource`から実行される。
* キャンセル済みの`CancellationTokenSource`や`CancellationToken`に`.Register()`すると、Callbackは即時実行される。

なるほどね。
＃18　『ファイル』を検索してコピーするバッチを作ってみました

## はじめに
業務中に導入できそうな場面があったため、今回初めてバッチファイルを作成してみました。
ファイルを検索しコピーする簡単なものですが、備忘録として残します。

## 今回のバッチについて
### やりたいこと
今回は以下のことを行うバッチを作成します。

* 指定したフォルダの配下から、検索ワードと合致するファイルを探し出す
* 探し出したファイルを指定した別フォルダにコピーする

これによりフォルダ間を行き来せずに効率的に作業を行えるようになります。

### バッチの中身
バッチファイルの中身は以下の通りです。

```bat
@echo off

echo ファイル名を検索し指定ディレクトリへコピーします。
pause

rem 検索ワード(SearchStrの部分)をセット
set str=SearchStr

rem ファイルコピー元パスをセット
set src=C:\ParentDirA\ChildDirA

rem ファイルコピー先パスをセット
set dest=C:\ParentDirB\ChildDirB

echo ファイルをコピーします。

rem コピー元ディレクトリへ移動
cd %src%

rem 検索ワードと部分一致するファイルを探して名前をリスト化する
rem リストの作成場所はDドライブ直下を指定しています。
dir /b *%str%* > C:\Users\hoge\Desktop\list.txt

rem ファイルコピー
for /f %%a in (C:\Users\hoge\Desktop\list.txt) do (
    copy "%src%\%%a" "%dest%\%%a"
)

rem 一時ファイルを削除
del C:\Users\hoge\Desktop\list.txt

echo 終了します。
pause
```

### コマンドの説明
```plaintext
@ …
先頭に『@』をつけることでバッチ実行時にそのコマンドが表示されなくなる
```

```plaintext
@echo off 
『@echo off』を指定するとそれ以降のコマンドもバッチ実行時に表示されなくなる 
```

```plaintext
echo 文字
バッチ実行時に『文字』の部分がコマンドプロンプトに出力される
```

```plaintext
pause
バッチ実行時、記述箇所で一時停止する
```

```plaintext
rem コメント
バッチに影響を与えずコメントを残す
```

```plaintext
set 環境変数名=値
環境変数に値を設定する
```

```plaintext
cd パス
『パス』へ移動する
```

```plaintext
%~%
両端に『%』を記述するとsetした変数の中身が呼び出せる
```

```plaintext
dir 検索内容 > ファイル名
カレントディレクトリ内で検索内容と一致する結果をファイルに保存する 
今回は『C:\Users\hoge\Desktop\』に『list.txt』を作成しています
```

```plaintext
dir /b
ファイル名のみ出力する
```

```plaintext
*%str%*
『%str%』はsetした文字列
『*』はワイルドカード
```

```plaintext
『*』(ワイルドカード) 
『Ａ*』なら始まりがＡのときヒットする
『*Ａ』なら終わりがＡのときヒットする
『*%str%*』は『*Ａ*』の形なので『%str%』と部分一致するものがヒットする
```

```plaintext
for …
ループ処理を行う
```

```plaintext
for /f …
in ()で指定したファイルの中身の1行1行に対しループ処理を行う
```

```plaintext
%%a
forの中で使用する変数名
一文字で指定される、今回は『a』で指定しています
今回は『list.txt』の何行目かを示していると考えるとわかりやすいです
```

```plaintext
copy コピー元ファイル コピー先ファイル
ファイルをコピーする
```

```plaintext
"%src%\%%a"
『%src%』と『\』と『%%a』を一つにつなげています
今回は『C:\ParentDirA\ChildDirA』『\』『list.txtのn行目』となります
```

```plaintext
del 名前
フォルダやファイルを削除する 
使わなくなった『list.txt』を削除しています
```

### バッチが実行時に文字化けしたら
文字コードが『UTF-8』になっていませんか？
メモ帳でバッチを編集するとき、右下に文字コードが表示されるので確認してみてください。
メニューバーの『名前を付けて保存』を押下、『エンコード』から文字コードを確認・変更することができるので、『ANSI』に設定して保存してください。


## 最後に
今回は簡単な内容でしたが、より簡潔に書く方法など引き続き学んでいきたいです。
みなさんも、バッチを作成して作業を効率化してみてください！
それでは。

出典：
https://www.tohoho-web.com/ex/bat.html
https://jj-blues.com/cms/quick_search/wanttodo/
OS標準機能だけでジョブを単発スケジュール実行したい

ログインしてなくても夜中に実行して、諸々の情報は勝手に揮発して欲しい。

# Windows

`Administrators` で実行する

```bat
set sched=%time%
set yyyymmdd=%date:/=%
set name=job_%yyyymmdd%

rem 実行したい処理を TEMP に作る
echo echo 1 > %TEMP%\%name%.bat

rem 最後にタスクを削除する処理を入れておく
echo schtasks /delete /tn %name% /f >> %TEMP%\%name%.bat

rem 削除される名前でタスクを作成する
schtasks /create /tn %name% /tr %TEMP%\%name%.bat /sc once /st %sched% /sd %date% /ru SYSTEM  /f
```

ジョブの管理

```bat
rem 一覧を表示
schtasks /query | findstr job

rem 削除
schtasks /delete /tn %name%
```

`powershell` でタスク作っても良いが、手数が多くなってしまうので今回は `cmd/bat` で作った。


# RHEL

伝統的な `at` を使うが、日付のフォーマットに癖があるので注意する

`root` で実行する。

```bash
sched=23:00
mmddyy=$(date +%m/%d/%y)
name=job_$(date +%F)

# 実行したい処理を /tmp に作成する
echo echo 1 > "/tmp/${name}.sh"

echo "/tmp/${name}.sh" | at $sched $mmddyy
```

ジョブの管理

```bash
# 登録したジョブの一覧を表示する
atq

# 削除する
atrm $id
```
Turbowarpの『カスタム拡張機能』を使おう【３】

# 本記事について
Turbowarpのカスタム拡張機能をる方法の説明、その３です。

前記事までで、外部Javascriptファイルを読み込み、Turbowarpの再起動無しでJavascriptの変更を反映させる方法を解説しましたが、外部Javascriptファイルの場所（名前）が固定でした。

外部Javascriptファイルの場所（名前）を変更できるようにしたいと思います。


# やりたいことの解説

JSファイルのURL をブロックの引数として与えることで、JSファイルを切り替えられるようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/47349ce7-f351-2295-5810-0c08b7d472c2.png)


#### 『JSファイルを指定する』ブロック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/f72683a4-32dc-5f60-ded6-6e2e301edb9e.png)

JSファイルのURL を指定するブロックです。

#### 『JSファイルを指定する』ブロック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/7f200de8-8b14-0133-1cef-97ddef0f264c.png)

指定された URL にある JSファイルをロードするブロックです。
ロードが終わったら、JSファイルに書かれているテスト用のクラスを使って インスタンスを作ります。

#### 『JSファイルを指定する』ブロック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/ad8258dc-2041-1c1a-6ac4-49ba671fa1e9.png)

作られたテスト用クラスのインスタンスを使って、テスト用のメソッドを実行します。

## テスト用のクラス ( sub.js )
```javascript:sub.js
const TestJS = class{
    method01() {
        console.log( 'TestJS.method01', '実行しましたよーん' );
    }
}
export {TestJS};
```
## テスト用のクラス ( sub2.js )
```javascript:sub2.js
const TestJS = class{
    method01() {
        console.log( 'TestJS.method01', 'SUB2 の method01でーす' );
    }
}
export {TestJS};

```

## ブロックを使ったスクリプト

sub2.js を指定するようにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/4e8047cf-9c7d-6194-ddf6-155eaaa5117d.png)


## 実行結果

sub2.js を実行していることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294946/0bf78899-b6b5-3bb0-313f-ea16aeca12e8.png)

# 拡張機能のJS

[コードGITHUB](https://github.com/amami-harhid/turbowarpExtensions/blob/main/_03_extension/Extension.js)


# 続き

[次の記事【４】](https://qiita.com/harhid/private/65fbc3cc05bcff6336de)へ続きます。