OmniAICreator/Qiita-1.07M huggingface dataset:
オフラインのJSON Checker (Validator)

# JSON Checker (Validator) の提供の種類

JSON Checker (Validator)は、記述したJSONの構文が正しいかを検証するツールやサービスのことです。
種類として主に、

- Webブラウザ拡張
- Webサービス
- エディタ拡張
- 専用ソフトウェア

等の形態で提供されています。
通常はこれらから好みのものを利用すればいいのですが、企業ポリシーなどでそう簡単にはできないような作業環境もあります。

厳しい環境だと、

- ホワイトリストで指定されたソフトウェア以外をインストールしてはならない
- Webブラウザやコードエディタに、アドオンツールをインストールしてはならない
- 記述したコードやデータをインターネットへ送信してはならない（チェッカーの利用でも）
- データを編集する作業端末は、インターネットに接続してはならない

等の制限がかけられていることがあります。

## オフラインのJSON Validator

そんな時はオフラインのHTMLファイルです。
アドオンも、追加のソフトウェアインストールも不要で、データをインターネットへ送信もしません。
もちろんWebサービスにあるような広告も表示されず、動作は最軽量です。

## HTMLでの実装例

以下が実装例です。

HTMLをPCのローカルに保存します。（厳しい作業環境にあるオフラインのPCへ保存するには、書き写すしかないかもしれませんが・・・がんばって・・・）

```html
<!DOCTYPE html>
<meta charset="utf-8">
<title>JSON Validator</title>
<body>
<span>JSON Validator</span><br>
<textarea id="area" style="width:80%; height: 30em;"></textarea><br>
<span id="errmsg"></span>
<script>
area.addEventListener("input", () => {
  let area = document.getElementById("area");
  let color;
  try{
    color = "white";
    if(area.value.replace(/[ \n]/g, "").length){
      JSON.parse(area.value);
      color = "#dff";
    }
    document.getElementById("errmsg").innerText = "ok";
  }
  catch(e){
    document.getElementById("errmsg").innerText = e.toString();
    color = "#fac";
  }
  area.style.backgroundColor = color;
});
</script>
</body>
```

特徴として、文字を入力するたびにチェックされます。つまりチェックのボタン操作が不要です。
背景色で判定結果を表示します。**水色(OK)**、**ピンク(NG)**、です。
![JSON_Validator_OKNG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204490/f8ba666c-3ac5-6fa4-e4d3-2528aa916f9e.png)

NGの場合は例外メッセージが下部に表示されます。
ロジックは単純で、Javascript の ```JSON.parse()``` でエラーするかどうかで判定しています。

# 利用ケース

1つ目のケースとして、**既に実装済みJSONの書き換え**が挙げられます。
JSONに慣れていない作業者がJSONの値を書き換えるように指示を受けているが、誤ってダブルクォーテーションやコロンを削除したり、カンマが多かったりしていないか、念のためにチェックをする、という使い方です。

2つ目のケースとして、**JSONの学習用**です。
文字を入力するたびに判定するので、ボタンを押すという手間がなく効率的です。
誤っている箇所を表示しないので、自力で誤りを特定することで、忘れにくいという効果もあると思います。

# YAMLの場合

JSONではなくYAMLの場合の実装例です。
以下のライブラリをダウンロードして、ローカルPCに保存します。

https://cdn.jsdelivr.net/npm/yamljs@0.3.0/dist/yaml.min.js

その後、以下のHTMLを記述して、yaml.min.js と同じ階層に保存します。

```html
<!DOCTYPE html>
<meta charset="utf-8">
<title>YAML Validator</title>
<script src="yaml.min.js"></script>
<body>
<span>YAML Validator</span><br>
<textarea id="area" style="width:80%; height: 30em;"></textarea><br>
<span id="errmsg"></span>
<script>
area.addEventListener("input", () => {
  let area = document.getElementById("area");
  let color;
  try{
    color = "white";
    if(area.value.length > 0){
      YAML.parse(area.value);
      color = "#dff";
    }
    document.getElementById("errmsg").innerText = "ok";
  }
  catch(e){
    document.getElementById("errmsg").innerText = e.toString();
    color = "#fac";
  }
  area.style.backgroundColor = color;
});
</script>
</body>
```

動作仕様はJSONのものと同じです。

![yaml_Validator_OKNG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204490/8ee6a5ae-41a4-7cb6-04d9-2ea9335d63ce.png)
gitエラー No such file or directory Vue.js 超入門 3.2対応 (技術の泉シリーズ（NextPublishing）)

# 使用した書籍
>[Vue.js 超入門 3.2対応 (技術の泉シリーズ（NextPublishing))](https://www.amazon.co.jp/Vue-js-%E8%B6%85%E5%85%A5%E9%96%80-3-2%E5%AF%BE%E5%BF%9C-%E6%8A%80%E8%A1%93%E3%81%AE%E6%B3%89%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA%EF%BC%88NextPublishing%EF%BC%89-%E7%88%B0%E6%B2%B3-ebook/dp/B0BRZJKB41/ref=sr_1_6?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=24CZ7T3JK7VXM&keywords=vue.js&qid=1694734507&sprefix=vu.js%2Caps%2C158&sr=8-6)

## 動作環境
Windows 10
git version 2.42.0.windows.2

# はじめに
今回、こちらの書籍を使用した背景としてVue3に対応した書籍がまだまだ少ない中、kindleUnlimitedで読めるとの事だったので手を出してみました。
その中で、自分みたいに経験が浅い人が読むと誤解しそうな表現があったので備忘録として残すことにしました。

(書籍の序盤でも書かれていますが、完全な初心者向けの本ではない為、この本の内容を理解するにはある程度javascriptの知識が必要です。)

# 該当箇所
第3章 3.2 「ソースを連携する」のターミナルにコマンド入力する下記の箇所
```
$git init
$git add .
$git commit -m "first commit"
$git branch -M main
$git remote add origin git@github.com:< リポジトリー名 >/my-vite-todo.git
$git push -u origin main
```
# gitエラーの内容
```
$ git remote add origin git@github.com:<my-vite-todo>/my-vite-todo.git
bash: my-vite-todo: No such file or directory
```
そんなファイルとディレクトリは存在しないといわれます。
# 原因
```
$ git remote add origin git@github.com:<my-vite-todo>/my-vite-todo.git
```
ここの記載方法が罠でoriginから後ろの表現
```... origin git@github.com:< my-vite-todo >/my-vite-todo.git ```

ここの "git@github.com:< リポジトリー名 >" をそのまま鵜呑みにして 
```git@github.com:<my-vite-todo>```
こんな記述をしていたことが原因でした。

# 解決方法
```
$ git remote add origin git@github.com:<my-vite-todo>/my-vite-todo.git
↓
$ git remote add origin git@github.com:gitのユーザ名/my-vite-todo.git
```
上記の通りに"git@github.com:ユーザ名/my-vite-todo.git"としてあげるとうまくいきます。

# 参考リンク
* [gitのエラー　fatal: remote origin already existsの解決方法](https://qiita.com/hatorijobs/items/1cae1946656ece954c63)
* [remote: Repository not found.となった時の対応方法](https://qiita.com/ponsuke0531/items/4fe191b7bed03342cff2)
noteのユーザー情報を取得ー覚え書き1

WEBサービスnoteからユーザー情報を抽出して
コンソールで表示するJavascriptの覚え書き

検索窓からキーワードで検索
検索結果のページでユーザー情報を取得します

※TOPページでは機能しない
![u3er298ur89u8fd3u8fwu32ur8f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3520459/14dc9e2f-a40c-eb11-b909-c49d8c375ee9.png)
**【取得する情報】**
・ユーザーネーム
・ユーザーID
・ユーザープロフィールのURL
``` Javascript
// XPathの一般的なパターン
const xpathPattern = '//*[@id="__layout"]/div/div[1]/main/div[3]/div/div/div/div/div/div[2]/div/div/section/div/div[3]/div/div[1]/a';

// XPathの一般的なパターンに一致するすべての要素を取得
const elements = document.evaluate(xpathPattern, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

// 取得した要素に対して処理を繰り返す
for (let i = 0; i < elements.snapshotLength; i++) {
  const element = elements.snapshotItem(i);

  // 要素のテキストを表示
  console.log('要素のテキスト:', element.textContent);

  // 要素のURLを取得
  const url = element.getAttribute('href');
  console.log('要素のURL:', 'https://note.com' + url);

  // ユーザーIDの取得
  const userId = url.match(/\/([^/]+)\/?$/)[1];
  console.log('ユーザーID:', userId);
}
```
**※メモ**
これだけではあまり使い勝手の良い物では無い
Docker Desktopのインストールでつまづいた話

# 不具合の内容
Docker Desktopをインストールする際、
以下のような画面までは表示されるけど、エラー表示もなくいきなり落ちる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918692/42ec4f58-8b72-d10e-9603-4148a698c05f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/918692/0f637fec-b960-72f3-b906-6956c17915e2.png)

# 原因
私の場合、ストレージの残容量が少なかったことが原因でした。
(私の場合は残32GBでインストール失敗した。何GBだといけるのかは不明)

https://docs.docker.jp/docker-for-windows/install.html#win-system-requirements
こちらのシステム要件にはストレージのことが書かれてないのでつまづきポイント

# 対処法
不要なファイルを削除してからインストールしてください。
その際、前回インストールのゴミが残っている可能性がある＆wslのアップデートが必要な可能性があるので、以下の手順でインストールする

(1)不要なファイルを削除して、ストレージ領域を確保する

(2)コマンドプロンプトを「管理者として実行」で開く

(3)`wsl --update`、`wsl --shutdown`をコマンドプロンプトで実行する

(4)以下のフォルダを削除する
　・C:\Users\<USER>\AppData\Roaming\Docker
　・C:\Users\ProgramData\Docker
　・C:\Users\ProgramData\DockerDesktop
　・C:\Program Files\Docker

(5)インストーラーの実行


# 参考URL
https://zenn.dev/seiya0/articles/tech-docker-desktop-for-win-troubleshoot
Schema builder 

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)


# Schema builder で設定したカスタムオブジェクトが表示されない

+ [Custom Object Created in schema builder not displayed in Dashboard](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007Uq9Xp)

:::note
Please check this article.

Create a Custom Object Tab
https://help.salesforce.com/s/articleView?id=sf.creating_custom_object_tabs.htm&type=5
:::

# 項目のドロップダウンができない

+ [【未解決】Can't drag fields into Schema Builder](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cmD4U)

# エラー

+ [Schema builder reports an invalid "le" parameter on save, how to solve it?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007I69Hf)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/14d86965-5e4b-0030-6197-6416fc2367e9.png)


:::note
The problem went away in the same way as it appeared - out of nothing. After couple of page refreshes and unsuccessful tries afterwards on the n-th try the Schema Builder managed to save the object. What was causing the problem and why it resolved itself I don't know. 

問題は、見た目と同じように、何も起こらずに解決しました。数回ページを更新し、その後 n 回目の試行で失敗した後、スキーマ ビルダーはオブジェクトを保存することに成功しました。何が問題を引き起こしたのか、そしてなぜそれが自動的に解決されたのかはわかりません。
:::

+ [I can't open Schema Builder.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007UsC0x)

:::note
it finally came up. 
:::

+ [Work with Schema Builder: Error while creating an object](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007bLVOB)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/253032d4-2663-be35-c405-c204262981d8.png)


# 印刷機能の代わり

+ [ I wonder if there is the ability to print / export the schema builder? ](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007agpIV)

:::note
Salesforce Schema Lister

This tool uses the Salesforce Metadata API to build a list of objects, fields and field attributes from within your Salesforce Org.

None of your organisation information or data is captured or kept from running this tool.
https://schemalister.herokuapp.com/
:::
SeleniumのChromeバージョンアップ時のエラーを回避する②（WebDriverManagerの使い方）

# 概要

Seleniumを使うときの一番の問題はChromeのバージョンアップにより、ChromeDriverとバージョンが違うことで起こるエラーです。Chrome For Testingを使う方法を以前記事にまとめました。

https://qiita.com/Rui010/items/10e69690146f7752968e

新たに、「WebDriverManager-for-VBA」を見つけたので、紹介する記事になります。

Testingを使ったところ、WindowsDefenderの警告が表示されたため、現在はこちらを使っています。

# WebDriverManager-for-VBAとは

VBAで動作するプログラムであり、Seleniumを使用する際に、WebDriverを起動するタイミングでChromeのバージョンとChromeDriverのバージョンをチェックし、不一致の場合は、自動でダウンロードとWebDriverの配置までを自動化してくれるプログラムになります。

ライブラリのGithub
https://github.com/yamato1413/WebDriverManager-for-VBA

# 使い方

1. WebDriverManager-for-VBAのGitHubにアクセス

https://github.com/yamato1413/WebDriverManager-for-VBA

1. 右上の「Code」から「Download Zip」を押す

   ![ss1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119135/47095afe-13cc-d5a1-92a5-c9e7c7eac030.png)

1. ダウンロードした、Zipファイルを展開する

1. 展開したフォルダ内、「WebDriverManager4SeleniumBasic.bas」をインポート
   - 標準モジュールのところにドラッグアンドドロップ
   - 標準モジュールを右クリックして、「ファイルのインポート」
      ![ss2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119135/d486c24e-6e73-4f8d-c0b6-262ab44ecb50.png)

1. ソースコードの書き換え

```
' WebDriverの宣言
' Dim Driver As New Selenium.ChromeDriver
Dim Driver As New Selenium.WebDriver

' Driverのスタート
' Driver.Start
SafeOpen Driver, Chrome
```

- ChromeDriverが見つからないときは、自動的にダウンロードされます
※少し動作が止まりますが、エラーが出ない限りは、正常に動いています
Flutter DEXファイル 参照メソッドの上限を増やす方法(Multidexを有効化)

# はじめに
前回はminSdkVersion指定によるエラー解決法について投稿しました。
これで無事エラーが解決したと思いきや、今度はまた別のエラーが発生しました。

# 本題
プログラムを実行したところ、以下のエラーが出て来ました。
> ERROR:D8: Cannot fit requested classes in a single dex file (# methods: 93262 > 65536)
com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: 
The number of method references in a .dex file cannot exceed 64K.
Learn how to resolve this issue at https://developer.android.com/tools/building/multidex.html 　　　　　　　　　　　　　　　　　　　　　　　　　　以下省略

エラーの原因を調べてみたところ、参照メソッドの数が上限(65536個)を超えているから実行できないとの事です。

# 解決方法
前回minSdkVersionを変更した時と同じファイル(C:\Users\ユーザ名\AndroidStudioProjects\プロジェクト名\android\app\build.gradle)
を以下の文言を追加しました。
```dart:build.gradle
android {
  defaultConfig {
      multiDexEnabled true //この1行を追加
  }
}'
```

これでfirebaseを使用した簡単なサンプルプログラムを実行することが出来ました。
参考([64K を超えるメソッドを使用するアプリ向けに Multidex を有効化する](https://developer.android.com/studio/build/multidex?hl=ja)
)
【高先さんの電子工作】第18回：可変抵抗器を使ってLEDを調光する

https://youtu.be/dXHf2Bz-yzk

可変抵抗器（ポテンショメーター）を使ってLEDを調光するプログラムです。

```python:main.py
from machine import ADC, Pin, PWM
import utime

potentiometer = ADC(28)
led = PWM(Pin(15))
led.freq(1000)

while True:
    value = potentiometer.read_u16()
    print(value)
    led.duty_u16(value)
    utime.sleep_ms(200)

```
Python で連番を利用する

連番は急に欲しくなることが知られている。

データの処理、ループの制御、ファイル名の生成といった用途で連続した整数のリストはとても役に立つ。

## range()とリスト内包表記

基本的には range() が手軽で良い。
```python
# range(N) は 0 オリジンの連番を作る
for i in range(3):
    print(f"{i}")
# 0
# 1
# 2

# range(N,M) は N から M -1 の区間の連番を作る
# range(N,M) の終了は M ではなく M - 1 であることに注意
for i in range(1,13):
    print(f"{i}月")
# 1月
# 2月
# 3月
# 4月
# 5月
# 6月
# 7月
# 8月
# 9月
# 10月
# 11月
# 12月
```

ただし、 range(N) の返り値は range 型なので list[int] 型がほしいときは list() を使う。
```python
print(type(list(range(10)))) # <class 'list'>
print(type(range(10))) # <class 'range'>
```

奇数がほしいなど注文がある場合はリスト内包表記が便利だ。
```python
# 2 の倍数を飛ばしている
[i for i in range(10) if i%2!=0] # [1, 3, 5, 7, 9]
```

### 使用例：ディレクトリが揃っているか確認する

次のようなディレクトリがあるのを想像してほしい。このディレクトリは 1957  年から 1988 年の記事を年度ごとに直下のディレクトリにファイリングしている。

```ls.txt
$ ls
1957  1958  1959  1960  1961  1962  1963  1964  1965  1966  1967  1968  1971  1972  1973  1978  1979  1980  1981  1982  1983  1984  1985  1986  1987  1988
```

70 年代を見れば分かるように、いくつかあるべきディレクトリが抜けている。このくらいの数ならディレクトリを人力で数えてもいいだろう、ただ数が増えると間違えることはわかる。

わかりきった問題なら、年数が増えても良いようにあらかじめプログラムで解決しておこう。

次のプログラムは 1957-89 区間の連続した(serial)な年リストと当該ディレクトリのリストの差を求めるプログラムだ。そしてその差分こそが欠落した年のリストである。

```python
"""欠落しているディレクトリを求めるプログラム"""
DIR:str = "1957  1958  1959  1960  1961  1962  1963  1964  1965  1966  1967  1968  1971  1972  1973  1978  1979  1980  1981  1982  1983  1984  1985  1986  1987  1988"

# DIR.split() だと文字列のリストになるので型を変換する
dirs:list[int] =  [int(i) for i in DIR.split()]
serial:list[int] = list(range(1957,1989))

lacked_dirs:list[int] = [i for i in serial if i not in dirs]
print(lacked_dirs)
# [1969, 1970, 1974, 1975, 1976, 1977]
```

## 結論

- print するなら range() を、変数に投げ込むならリスト内包表記を使うと良い
- 複雑な条件分岐をするならば、リスト内包表記は読みづらくなるので使うべきではない

## Link

- [5. データ構造 — Python 3.11.5 ドキュメント](https://docs.python.org/ja/3/tutorial/datastructures.html#list-comprehensions)
    - リスト内包表記についての公式ドキュメント
- [組み込み型 — Python 3.11.5 ドキュメント](https://docs.python.org/ja/3/library/stdtypes.html#typesseq-range)
    - range() についての公式ドキュメント
Solanaバリデーターをわずか10分で立ち上げるオープンソースツール"solv"

![HowToStartSolanaValidatorJA.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2780317/4056a45e-89af-e782-d4eb-c3d9941afc86.png)


gm! Epics DAO Co-founderのkishi.solです。

今回はEpics DAOが開発したオープンソースツールの"solv"について書かせていただきます。

solv は、Solana バリデーターのセットアップと運用を簡略化するためのオープンソース CLI ツールです。solv を使うことで、バリデーターのセットアップ、運用、モニタリング、アラート、アップグレード等、バリデーターとしての業務を簡単に行うことができます。

https://solv.epics.dev/ja/

新しく Solana バリデーターに参加する方はもちろん、既にバリデーターとして活動されている方も簡単に solv の利用へ移行いただき、以後の運用をより手間なくスムーズに行うことができます。

solv の主な狙いは以下の通りです。

- **Solana ネットワークの分散化を促進:** solv は、多くのユーザーが Solana ネットワークに容易に参加できるように設計されています。これにより、ネットワークの分散化と誰も取り残さない技術革新社会に貢献します。
- **バリデーター業務の手間や負担を削減:** solv の利用者は、多くの設定やアップデートを一つのコマンドで簡単に実施できます。これにより、高度な技術への理解を持つ Solana のバリデーターたちはより多くの社会的価値を生み出すことができます。
- **オープンソースコミュニティのリソースを強化:** solv は、バリデーターとして参加するためのハードルを下げ、より多くのオープンソース開発コミュニティがバリデーター報酬を得て、持続可能なオープンソース開発環境を構築することを目指しています。

このツールは、元々私たちの開発チーム・コミュニティ全体の運用効率化のために開発されましたが、その価値を Solana コミュニティ及びオープンソースコミュニティ全体に広めるためにオープンソースとして公開されています。

セットアップから稼働開始までを解説した YouTube 動画についても公開しておりますので、ぜひご覧ください。

【10 分で稼働開始】solv を使った Solana バリデーターのはじめかた (YouTube): 

https://www.youtube.com/watch?v=zdN4yaPkoa0
フロントエンド開発の変遷④ JavaScriptライブラリ乱立時代


フロントエンド開発の変遷シリーズ第4回です。
第3回はこちら。

https://qiita.com/yusuke2310/items/411c6fd4cce9eba084f2

---


:::note
2009年ごろからWebアプリケーションはSPAを代表に、複雑な要件を求められる傾向にあり、フロントエンド開発のパラダイムシフトが起きていました。jQueryは次第に影をひそめ、MVC/MVVMを活用したBackbone.js、AngularJSなどの新たなWebアプリケーションフレームワーク、ライブラリが次々と出現しました。
:::


この時期フロントエンド開発でJavaScriptが担う役割は飛躍的に大きくなりました。この状況でフレームワークなどが提供する設計指針なしに実装を進めると、非常に**複雑でレガシー化を引き起こしやすいコード**になってしまう。

そこでMVC設計という従来サーバーサイドで普及していた概念がフロントエンドに導入されました。


MVCフレームワークとして人気の高かったのが**Backbone.js**でした。

:::note
MVCモデルを導入することでビューとモデルが直接関連することがなくなり、フロントエンドのコードの役割が明確にし、疎結合な実装が実現できるようになった。フロントエンドフレームワークのアーキテクチャが、メンテナンス性の高いフロントエンド開発を支えることが認知されていきます。
:::



Backbone.jsの流行後、MVVMフレームワークが乱立し始めます。

▼著名なライブラリ
* AngularJS
* KnockoutJS
* Riot.js
* Vue.js

MVVMとはデータを管理するModel、画面表示に関するView、そしてデータと表示の橋渡しをするViewModelを用いたアーキテクチャです。

| MVVM |役割 |
|:-:|:-:|
|Model   | データの管理  |
| View  | 画面表示  |
| ViewModel  | データと表示の橋渡し  |

jQueryでは、データの変更に応じてDOMを操作するコードの記述する必要がありました。MVVMではモデルからビューへのデータ連携、ビューからモデルへのデータの双方向バインディングを行うアーキテクチャで、DOM操作のコード不要でUIにデータの変更を反映させることができる。またUIからの情報入力がデータを自動的に同期されるため、生産性の高いフロントエンドの実装が可能になりました。


2015年ごろまでフロントエンドのライブラリ乱立時代が続き、今でも上記のフレームワークのWebアプリケーションがスマートフォンのブラウザの中で当たり前のように動作しています。

このライブラリ乱立時代に登場したのがReactです。（次回に続く、、、）


今回も以下の書籍を参考にしました。
書籍「TypeScriptとReact/Next.jsで作る実践Webアプリケーション開発」

https://www.amazon.co.jp/TypeScript%E3%81%A8React-Next-js%E3%81%A7%E3%81%A4%E3%81%8F%E3%82%8B%E5%AE%9F%E8%B7%B5Web%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E9%96%8B%E7%99%BA-%E6%89%8B%E5%B3%B6-%E6%8B%93%E4%B9%9F/dp/4297129167
【Git】stashコマンド：checkoutし忘れて変更を行ってしまった場合

## checkoutをし忘れて変更を行ってしまったときに

自分がよくやらかすので、備忘録として。。。

以下のようなときに使いこなせると便利
- 実装した内容をまだ作成していないブランチに移動させたい
- 作業途中だけど少しだけ別のブランチに移動したい

### 実装した内容をまだ作成していないブランチに移動させたいとき

1. `git stash`で変更を退避
2. ブランチを作成しcheckout
3. `git stash list`で復元したい退避内容を探す
4. `git stash apply stash@{0}`で退避内容の復元を行う(stash@{0}は手順3で探した復元したい退避)
5. 最後に退避情報が不要となった場合は`git stash drop stash@{0}`で削除する

```
$ git stash

$ git checkout {移動先のブランチ}

$ git stash list
stash@{0}: WIP on hogehoge: 1234567 fugafuga

$ git stash apply stash@{0}

$ git stash drop stash@{0}
```

### stashまとめ(よく使うコマンド)

#### ① git stash

追跡中の変更を退避する
以下のようにsaveを付けるとメッセージ付きにできるのでわかりやすくなる
```
git stash save "stashメッセージ"
```

#### ② git stash -u

untrackedファイルも含めて退避する
→新しいファイルなどを作成した時はこっち

#### ③ git stash list

退避の一覧を確認する
→退避内容を探す場合に使う

#### ④ git stash pop

最新の退避を復元し退避情報を削除する
→退避情報が削除されるので注意

#### ⑤ git stash apply

最新の退避を復元し退避情報も残す
→いきなり削除されるのは怖いので個人的にはこっちが好み

#### ⑥ git stash apply '退避番号(stash@{3})'

指定した退避番号の内容を復元し退避情報も残す
→連続で退避を行ってブランチを移動しまくっているときとかに使える？

#### ⑦ git stash drop

最新の退避情報を削除する

#### ⑧ git stash drop '退避番号(stash@{3})'

指定した退避番号の退避情報を削除する

#### ⑨ git stash clear

全ての退避情報を削除する

#### ⑩ git stash show

最新の退避との差分を確認する

#### ⑪ git stash show -p

最新の退避との差分を確認する(詳細バージョン)

#### ⑫ git stash show '退避番号(stash@{3})'

指定した退避番号との差分を確認する

### 参考
[【Git】stashコマンドのまとめと使い方 〜変更差分の一時退避〜](https://qiita.com/nakaji0210/items/330f6dcb361da074c2c0#-stash%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%BE%E3%81%A8%E3%82%81)
Chromeデベロッパーツール　NetworkのTimingセクションの見方



Google Chromeの開発者ツールの「Network」タブの「Timing」セクションは、リクエストのライフサイクルの各段階での時間を視覚的に示しています。以下は、このセクションで表示される主な項目とその説明です

![スクリーンショット 2023-09-15 0.25.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169789/87abeed6-3f02-22b7-cdc0-03ce7315e077.png)

1. **Queued / Stalled / Blocking**:
   - **Queued**: リクエストが開始されるまでの待機時間。
   - **Stalled/Blocking**: リクエストが開始される前に発生する遅延。これは、既存の接続が再利用されるのを待っているか、CORSプリフライトリクエストがある場合などに発生します。

2. **DNS Lookup**:
   - ドメイン名のIPアドレスへの解決にかかった時間。キャッシュされている場合、この時間は非常に短くなることがあります。

3. **Initial Connection / Connecting**:
   - TCPハンドシェイクにかかった時間。これには、TCPの3ウェイハンドシェイクや、再接続の場合のTCPの再利用も含まれます。

4. **SSL / TLS Negotiation**:
   - SSL/TLSハンドシェイクにかかった時間。安全な接続の確立に必要な時間です。

5. **Request Sent / Sending**:
   - リクエストデータが送信されるのにかかった実際の時間。

6. **Waiting (TTFB: Time To First Byte)**:
   - 最初のバイトを受信するまでの時間。これは、サーバーがリクエストを処理して応答を開始するまでの時間を示しています。

7. **Content Download / Downloading**:
   - 応答データをダウンロードするのにかかった時間。

「Timing」セクションのバーは色分けされており、各段階の時間を視覚的に理解するのに役立ちます。これらの情報を使用して、リクエストのどの段階で遅延が発生しているかを特定し、パフォーマンスの最適化のための手がかりを得ることができます。
Power Automate For Desktop(PAD)を使う時に調べたことメモ/リンク(備忘録)

# 概要/学習サイトまとめ

https://qiita.com/maekawawawa/items/b9c7b866f5ee31d2acd3

https://support.asahi-robo.jp/

# ループを使い分ける
https://cravelweb.com/rpa/power-automate-desktop/how-to-use-loop-action-on-power-automate-desktop

# 「ラベル」アクションと「移送先」アクション
ブロックエラー発生時に任意の動きになるように使用します。（「サブフローの実行」/「ブロックの先頭(末尾)に移動する」アクションなど）

https://docs.microsoft.com/ja-jp/learn/modules/pad-flow-control/2-flow-control-actions

# その他のアクションの概要
## マウス
https://zenn.dev/natsuki/articles/b93a534590f084

## キーボード
UI要素での操作が難しい場合、キーボードで画面を操作すると良い。

https://blog-tips.sekenkodqx.jp/2021/05/18/power-automate-desktop-action-send-keys-mouse-and-keyboard/

- キーを押す/離す …キーを既定の状態に戻すには、もう一つ別のこのアクションを使用する必要がある
- キーの状態を設定 …CapsNumLock/NumLock/ScrollLockの有効・無効の設定など
 
## アクション「アプリケーションを起動する」
### アプリケーションのコマンドライン引数を調べる方法

https://www.yosato.net/?p=4060

## 取得したExcelデータの行と列の扱いについて

https://support.asahi-robo.jp/tutorial/power-automate-desktop/beginner/datatable

## ファイル操作
### ファイルの選択ダイアログ

- ```*.[拡張子名]``` 
     - ファイルフィルターでユーザーに許可するファイルの種類を限定することができる。

## API連携

https://rpa.bigtreetc.com/column/api-for-powerautomatedesktop/

👇実践してみる👇

https://internet.watch.impress.co.jp/docs/column/shimizu/1318358.html

### Teamsと連携したい
https://qiita.com/maekawawawa/items/76cc0e7754fdcdf8bd7c

# UI要素をうまく掴もう
https://webs-studio.jp/rpa/power-automate-desktop/1705/

## Webページからデータを抽出するとき
https://blog-tips.sekenkodqx.jp/2021/06/06/power-automate-desktop-extract-data-webautomation/

### セレクタービルダーに慣れよう
https://papasensei365.com/pad-selector-contains/#toc3

# 入力変数と出力変数について
フローを連携する際や、Power Platformの他製品とのデータ交換の際に使用する。
詳しくはこちらでまとめました。

https://qiita.com/fsgwmhr/items/d6ebaa23b2a57c07bcfc

# 例外処理（エラー）を使いこなす
こちらでまとめています。

https://qiita.com/fsgwmhr/items/6bc5175e26cbef98739d

# デバッグの工夫
https://qiita.com/spumoni/items/eccd0606be506eb1cf95#%E5%AE%9F%E8%A1%8C%E9%80%9F%E5%BA%A6%E3%82%A6%E3%82%A4%E3%83%B3%E3%83%89%E3%82%A6%E3%81%AE%E8%A1%A8%E7%A4%BA%E6%96%B9%E6%B3%95
住所の表記ゆれを生成AIで何とかできないか（お試し編－補足）

# 振り返り
[前回](https://qiita.com/mine820/items/e59be646da7efb6be6a7)、表記ゆれと不正解を見分けられそう（表記ゆれを一致と判断できそう）という結論にしたのですが、よくよく見なおしてみれば、不正解のデータは値を2つ「も」変えていました。

これはいかんということで、変更は「1つ」にして、確認してみます。

# データ
ということで、こんなデータで確認することにしました。
```python
sentences = [
    # 正解
    "東京都港区海岸一丁目２番３号",
    # 表記ゆれ
    "東京都港区海岸一丁目2番3号",
    "東京都港区海岸一丁目二番三号",
    "東京都港区海岸1丁目2番3号",
    "東京都港区海岸１丁目２番３号",
    "東京都港区海岸1-2-3",
    "東京都港区海岸１－２－３",
    # 不正解
    "東京都港区海岸一丁目１番３号",
    "東京都港区海岸一丁目1番3号",
    "東京都港区海岸一丁目一番三号",
    "東京都港区海岸1丁目1番3号",
    "東京都港区海岸１丁目１番３号",
    "東京都港区海岸1-1-3",
    "東京都港区海岸１－１－３",

    "東京都港区海岸一丁目１番１号",
    "東京都港区海岸一丁目1番1号",
    "東京都港区海岸一丁目一番一号",
    "東京都港区海岸1丁目1番1号",
    "東京都港区海岸１丁目１番１号",
    "東京都港区海岸1-1-1",
    "東京都港区海岸１－１－１"
]
```

# 結果発表♪
|  |  | 東京都港区海岸一丁目２番３号 |
|---:|---|---:|
| 1 | 東京都港区海岸一丁目2番3号 | 2.22044605e-16 |
| 2 | 東京都港区海岸一丁目二番三号 |  6.11741123e-02 |
| 3 | 東京都港区海岸1丁目2番3号 | 7.29590979e-03 |
| 4 | 東京都港区海岸１丁目２番３号 | 7.29590979e-03 |
| 5 | 東京都港区海岸1-2-3 | 5.00328437e-02 |
| 6 | 東京都港区海岸１－２－３ | 5.00328437e-02 |
| 7 | 東京都港区海岸一丁目１番３号 | 5.38945823e-02 |
| 8 | 東京都港区海岸一丁目1番3号 | 5.38945823e-02 |
| 9 | 東京都港区海岸一丁目一番三号 | 9.56757672e-02 |
| 10 | 東京都港区海岸1丁目1番3号 | 5.95731232e-02 |
| 11 | 東京都港区海岸１丁目１番３号 | 5.95731232e-02 |
| 12 | 東京都港区海岸1-1-3 | 7.40203657e-02 |
| 13 | 東京都港区海岸１－１－３ | 7.40203657e-02 |
| 14 | 東京都港区海岸一丁目１番１号 | 2.45641245e-01 |
| 15 | 東京都港区海岸一丁目1番1号 | 2.45641314e-01 |
| 16 | 東京都港区海岸一丁目一番一号 | 2.57492124e-01 |
| 17 | 東京都港区海岸1丁目1番1号 | 2.58257453e-01 |
| 18 | 東京都港区海岸１丁目１番１号 | 2.58257453e-01 |
| 19 | 東京都港区海岸1-1-1 | 2.06726289e-01 |
| 20 | 東京都港区海岸１－１－１ | 2.06726289e-01 |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/b52e00c5-ee26-7e53-669d-773f7e028882.png)

ほぼ表記ゆれと同じ値になってしまいました（泣）

# 今後の課題
ということで、「表記ゆれ」vs「数字1つ違い」が次のテーマになります。
「表記ゆれ」のコサイン距離を縮めるか、「数字1つ違い」のコサイン距離を大きくするか、ちょっと考えてみます。
FRRでOSPFの設定をしてみる

## 目的
Containerlabで構築したFRRで、OSPFの設定をしてみる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2738475/dcff5159-294e-0d57-1f21-adc2905a219a.png)

## IP設定
router1
 - eth1: 192.168.1.1
 - eth2: 192.168.3.1

router2
 - eth1: 192.168.1.2
 - eth2: 192.168.2.2

router3
 - eth1: 192.168.3.2
 - eth2: 192.168.2.1



## OSPF
OSPFの有効化
/etc/frr/daemons
```bash
ospfd=yes
```

FRRの再起動
```bash
/usr/lib/frr/frrinit.sh restart
```
or
ホスト側で実行
```bash
docker restart frr1
```

ログイン
```bash
vtysh
```

IPアドレスの設定
```bash
conf t
interface eth1
ip address 192.168.1.1/24
```
```bash
conf t
interface eth2
ip address 192.168.3.1/24
```

OSPFの設定
```bash
conf t
router ospf
router-info area 0.0.0.0
network 192.168.1.0/24 area 0.0.0.0
network 192.168.3.0/24 area 0.0.0.0
```

OSPFにおけるコストの変更
```bash
conf t
int eth1
ip ospf cost 500
```

## configの確認
最終的に生成された設定
```bash
Building configuration...

Current configuration:
!
frr version 7.5.1_git
frr defaults traditional
hostname router1
no ipv6 forwarding
!
interface eth1
 ip address 192.168.1.1/24
 ip ospf cost 500
!
interface eth2
 ip address 192.168.3.1/24
!
router ospf
 network 192.168.1.0/24 area 0.0.0.0
 network 192.168.3.0/24 area 0.0.0.0
 router-info area
!
line vty
!
end
```

router2
```bash
Building configuration...

Current configuration:
!
frr version 7.5.1_git
frr defaults traditional
hostname router2
no ipv6 forwarding
!
interface eth1
 ip address 192.168.1.2/24
 ip ospf cost 500
!
interface eth2
 ip address 192.168.2.2/24
!
router ospf
 network 192.168.1.0/24 area 0.0.0.0
 network 192.168.2.0/24 area 0.0.0.0
 router-info area
!
line vty
!
end
```

router3
```bash
Building configuration...

Current configuration:
!
frr version 7.5.1_git
frr defaults traditional
hostname router3
no ipv6 forwarding
!
interface eth1
 ip address 192.168.3.2/24
!
interface eth2
 ip address 192.168.2.1/24
!
router ospf
 network 192.168.2.0/24 area 0.0.0.0
 network 192.168.3.0/24 area 0.0.0.0
 router-info area
!
line vty
!
end
```
Discord.pyで賢くEmbedを作ろう

# はじめに
pythonファイルに文章を置くと邪魔なので、今回はjsonファイルを用いて内容を記述していきます。


# 1.jsonファイルの作成

今回はmanコマンドのようなものをテーマに作っていきます。

```json:manual.json
{
    "time": {
        "description": "Get current time.",
        "usage": [
            {
                "name": "使用方法",
                "value": "```time```"
            },
            {
                "name": "引数",
                "value": "なし"
            }
        ],
        "color": "0x00ff00"
    },
    {
        ...
    }
}
```

# 2.jsonファイルを読み込む

変数名は自由にどうぞ。

```python:main.py
with open("manual.json", "r") as json_file:
    man_data = json.load(json_file)
```

# 3.値の取得

pythonの方で値を読み取ります。

```python:main.py
@client.event
async def on_message(message):
    if message.author == client.user:
        return
    # always on

    if not message.content.startswith(PREFIX):
        return
    # only with prefix

    args = message.content[len(PREFIX) :].strip().split()
    command = args.pop(0).lower()

    # 中略

    if command == "man":
        if not args:
            await message.channel.send("コマンド名を指定してください")
        else:
            cmd = args[0]
            if cmd in man_data:
                embed = discord.Embed(
                    title=cmd,
                    description=man_data[cmd]["description"],
                    color=int(man_data[cmd]["color"], 16)
                    if "color" in man_data[cmd]
                    else 0x0000FF,
                )
                for i in range(len(man_data[cmd]["usage"])):
                    embed.add_field(
                        name=man_data[cmd]["usage"][i]["name"],
                        value=man_data[cmd]["usage"][i]["value"],
                        inline=False,
                    )
                embed.set_author(name=client.user, icon_url=client.user.avatar.url)
                embed.set_footer(
                    text="made by someone",
                    icon_url="https://xxx.hoge.com/sample.png",
                )
                await message.channel.send(embed=embed)
            else:
                await message.channel.send("コマンドが見つかりませんでした")
```

注意点として、colorは16進数のint型で指定する必要があります。
その他の要素を追加したい場合は以下の記事を参照してください。


https://qiita.com/hisuie08/items/5b63924156080694fc81

以下の記事も参考にしました。

https://qiita.com/yuta_vamdemic/items/f706d6029490d94fc1b7
【Rails】【Ruby】ENV[]とENV.fetch() {}の違い

## `ENV[]`と`ENV.fetch() {}`の違い
`ENV[]`と`ENV.fetch() {}`の違いは指定した環境変数が存在しない場合に`nil`を返すかデフォルト値を返すかの違いです。

例えば、以下の場合には、`RAILS_MAX_THREADS`、`DB_USER_NAME`、`DB_USER_PASSWORD`が存在しない場合にはnilとなります。
```detabase.yml

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV["RAILS_MAX_THREADS"] %>
  username: <%= ENV["DB_USER_NAME"] %>
  password: <%= ENV["DB_USER_PASSWORD"] %>
  host: db

```

以下のように記述すると`RAILS_MAX_THREADS`、`DB_USER_NAME`、`DB_USER_PASSWORD`が存在しない場合には{}内に記述したデフォルト値となります。

```detabase.yml

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("DB_USER_NAME") { root } %>
  password: <%= ENV.fetch("DB_USER_PASSWORD") { rootpass } %>
  host: db


```
Windows11で WSLインストール

# 結論
インストールする前に、WSLを有効にする（後述）必要があった。

# WSL2インストール

powershellで下記実行
```
新機能と改善のために最新の PowerShell をインストールしてください!https://aka.ms/PSWindows

PS C:\Windows\system32> wsl --install
インストール中: Linux 用 Windows サブシステム
[                           0.0%                           ]
```
ここで止まって進まない。。。


# PowerShellを最新版に
バージョン確認したところ最新版ではないので、 https://aka.ms/PSWindows より最新版をダウンロードしてインストール
```
PS C:\Windows\system32> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.22621.1778
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.22621.1778
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
```

# WindowsStoreで Ubuntuをインストール
これもエラーに。。。

# Windowsの機能で WSLを有効にする(これを最初にやるべきだった）
「Linux用 Windows サブシステム」が無効になっていたのでチェックして「OK」押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33343/16c9a251-961b-276f-89cb-a33ec8cb6644.png)

# WSL有効後にインストールされていた
有効化した後、再起動するとUbuntuがインストールされ使えるようになっていた
【Bash】$RANDOMを使って任意の範囲までの乱数 / ランダムな浮動小数点数を生成

# 概要
Bashシェルスクリプト`$RANDOM`を使って、任意の範囲までの乱数を生成したり、小数点以下の範囲で生成したりしましたのでまとめます。

# `$RANDOM`とは
Bashシェルスクリプトで使用できる特殊な環境変数。
`$PATH`とかと同じ組み込み変数ですね。

0から32767までの範囲の疑似乱数を生成します。
16ビット符号なし整数（2の16乗 - 1）の範囲に相当。
システムの現在時刻をシード値として使用し、それに基づいて乱数を生成するとか。

# サンプルスクリプト

```test-random.sh
#!/bin/bash
# 現在の日付の時刻
echo `date "+%Y/%m/%d %H:%M:%S"`

# 0 〜 32767 の間でランダムな数値を取得
echo $RANDOM

# 0 〜 65535 の間でランダムな数値を取得
echo $((RANDOM + RANDOM))

# 1から6までのランダムな整数を生成 (サイコロの目)
echo $((RANDOM % 6 + 1))

# 0からNまでの範囲の乱数を生成
N=10  # Nを設定
echo $((RANDOM % (N + 1)))

# ランダムな浮動小数点数を生成
echo $(bc <<< "scale=5; $RANDOM/32767")
```

出力結果：

```
2023/09/14 23:17:59
19929
40718
5
1
.34003
```

## 小数点以下5桁までの精度で0から1の間の乱数を生成

```sh
echo $(bc <<< "scale=5; $RANDOM/32767")
```

上記について。

- `bc`コマンド: 任意の精度で計算を行うためのコマンドライン
- `<<<`演算子: ヒアストリング（here string）を提供。ヒアストリングを使用すると、文字列をコマンドに渡すことができる。
- `"scale=5; $RANDOM/32767"`: ヒアストリングによって、bcに渡される計算式。
    - `scale=5`: 小数点以下5桁を指定
    - `$RANDOM`:0から32767までのランダムな整数を生成
    - `/32767`:32767で割って、0から1の範囲の浮動小数点数を生成

これにより、小数点以下5桁までの精度で0から1の間のランダムな浮動小数点数を生成できます。

5桁を指定しない場合は、`-l`オプションをつける必要があります。これは、`"load"`を意味し、`bc`コマンドが起動するときに数学ライブラリを読み込むためのオプションです。

```sh
echo $(bc -l <<< "$RANDOM/32767")

# 結果
# .02777184362315744499
```
pydantic.errors.PydanticUserError: If you use `@root_validator` with pre=False (the default) you MUST specify `skip_on_failure=True`. Note that `@root_validator` is deprecated and should be replaced with `@model_validator`.

# mlflowが動かなくなった。
```
mlflow ui
```
を実行すれば、mlflowが実行できるはずだが、以下のようなエラーがでてきた。
```
Traceback (most recent call last):
  File "/usr/local/bin/mlflow", line 5, in <module>
    from mlflow.cli import cli
  File "/usr/local/lib/python3.10/dist-packages/mlflow/cli.py", line 683, in <module>
    import mlflow.gateway.cli
  File "/usr/local/lib/python3.10/dist-packages/mlflow/gateway/__init__.py", line 1, in <module>
    from mlflow.gateway.fluent import get_route, search_routes, query, create_route, delete_route
  File "/usr/local/lib/python3.10/dist-packages/mlflow/gateway/fluent.py", line 4, in <module>
    from mlflow.gateway.client import MlflowGatewayClient
  File "/usr/local/lib/python3.10/dist-packages/mlflow/gateway/client.py", line 8, in <module>
    from mlflow.gateway.config import Route
  File "/usr/local/lib/python3.10/dist-packages/mlflow/gateway/config.py", line 64, in <module>
    class OpenAIConfig(ConfigModel):
  File "/usr/local/lib/python3.10/dist-packages/mlflow/gateway/config.py", line 77, in OpenAIConfig
    @root_validator(pre=False)
  File "/usr/local/lib/python3.10/dist-packages/pydantic/deprecated/class_validators.py", line 228, in root_validator
    raise PydanticUserError(
pydantic.errors.PydanticUserError: If you use `@root_validator` with pre=False (the default) you MUST specify `skip_on_failure=True`. Note that `@root_validator` is deprecated and should be replaced with `@model_validator`.
```
今まで動いていたのに...
いつも大変お世話になっております、[stack overflow](https://stackoverflow.com/questions/76934579/pydanticusererror-if-you-use-root-validator-with-pre-false-the-default-you)によると原因はpydanticのアップデートらしい。
[pydantic本家](
https://docs.pydantic.dev/latest/version-compatibility/)でも、v1からv2へのメジャーアップデートで、影響出るかもということが掲載されてた。
あれ、pydanticなんてinstallしてたっけな？って思って
```
pip freeze
```
すると、
```
pydantic==2.0.3
```
あっ！いたっ！！

# 対処法
古いバージョンのpydanticをインストールしてあげればよいだけ。
```
pip install pydantic==1.10.12
```
### mlflow復活っ！！
# 補足
バージョン1.10.12は2023/9/14でのv1の最新バージョンです。それぞれinstallする際に最新バージョンを確認するのがよいと思います。あと、v1のサポート期限はv2のリリース後1年間となっています。2023/6/30にv2.0がリリースされているので、2024/6/30まではv1もサポートされます。
【SwiftUI】カスタムのTextFieldStyleを作成する

# はじめに
LabelStyleやButtonStyleは使ったことがあったのですが、TextFieldStyleは使ったことがなかったので使ってみます。

# Twitterの検索バー的なのを作ってみる
![simulator_screenshot_A963A173-1BDD-4AF4-A4DB-F0480C762401.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/4dff5fdc-1e32-3563-1f4b-3e7973249b4f.png)

# 実装
```swift
struct WithCancelTextFieldStyle: TextFieldStyle {
    @FocusState private var isFocused
    
    func _body(configuration: TextField<Self._Label>) -> some View {
        HStack(spacing: 8) {
            HStack(spacing: 8) {
                Image(systemName: "magnifyingglass")
                
                configuration
            }
            .padding(.vertical, 10)
            .padding(.horizontal, 12)
            .background(.secondary.opacity(0.3), in: Capsule())
            
            Button {
                isFocused = false
            } label: {
                Text("Cancel")
            }
            .foregroundStyle(.primary)
        }
    }
}

extension TextFieldStyle where Self == WithCancelTextFieldStyle {
    static var withCancel: WithCancelTextFieldStyle {
        .init()
    }
}
```

# 使い方
```swift
struct SampleView: View {
    @State private var text = ""

    var body: some View {
        VStack {
            TextField("検索", text: $text)
                .textFieldStyle(.withCancel)
        }
        .padding(.horizontal, 16)
    }
}
```

# おわり
`body`に`_`がついてるのが気になります。
macを買ってから初期設定でやったこと

# 概要
この度macbook air 15inchを購入したので、初期セットアップでやった事を書いていきます。完全に自分のメモです。
macbookは2台目のため、今後また買い替えたときや仕事での端末交換などがあった際に便利かなと思います。

# セットアップ
※随時追記します。

|やること|参考情報など|
|---|---|
|CotEditorをインストール|今回はやる事を残しておこうと思い最初にインストールしました。標準のメモアプリでも良いですが、まぁどうせ入れるでしょう、という感じです。|
|キーボード、マウスをBluetoothで接続|大抵の場合前使っていた端末とのペアリングを切って、接続するガジェット側の接続ボタン的なものを長押しするといけます。|
|キーボードの設定変更|キーボード：win風の変換とか、ctrlとcommand入れ替えとか、入力ソースのABCを削除するとか。ここでトラックパッドの軌跡を早くする設定を入れておく。またトラックパッドをタッチでクリックにする設定もする。mac本体のキーボード設定も変えておきたい。|
|マウスの設定|設定アプリをDLして、アカウントログイン後バックアップの復元みたいなことをやるといい感じにできそう|
|google chromeのダウンロード|Googleアカウントにもログインしておく|
|時計の秒数を表示する。バッテリーの%を表示する。|[参考](https://pc-karuma.net/mac-menu-bar-date-time/)|
|Dockから不要なアプリを消す||
|ターミナルの設定を変える|透過設定とか色とか。背景は黒っぽく、文字は全部白にする。|
|finderの細かい設定をする|[参考](https://ushigyu.net/mac-finder-configuration/) 拡張子の設定も忘れずに。|
|slackをDLする||
|python3と打つとCommand line toolsのダウンロードをしますかと言われるのでする||
|zshrcを整備する|Githubのdotfileか前の端末からコピる|
|vscodeを入れる||
|intellijを入れる|intellijでプロジェクトを作成するときにJDKも入れる。競プロ用。|
|homebrewを入れる。|[参考](https://zenn.dev/shichi18/articles/20230325-01-50eb75b9096004)|
|nodebrewを入れてnodeを入れる||
【GOT】GDデバイス（GOT内部デバイス）とは？【三菱PLC】



GDデバイスとは、GOT本体内部に用意されている記憶領域を使用してGOTから書き込んだりできるデバイスです。
これを使用すると、簡単な値を使った処理はPLC本体を経由せずともGOTでのみ完結できます。
GOTを使用する際このGDデバイスを多く使用するようにすれば、PLCのDデバイスの記憶領域を圧迫せずにある程度の操作がGOTでできるようになります。

複数台のGOTを用意していれば、同じPLCにそれぞれ接続されていてもGOTごとに別のGD領域を持っています。
そのため、PLCでGOT操作用のDデバイスをそれぞれ用意する必要がなく、GOTで同じGDデバイスを指定してGOTごとに別々の動作をさせることが可能になり、複製が容易です。

https://fa-faq.mitsubishielectric.co.jp/faq/show/23214


# GDデバイスの使用方法
スイッチを押したときに値を格納するデバイスを**GD100**などに指定すれば、GOT本体に値が格納されます。
この時点ではこのデバイスの値とPLCはリンクされていないため、GOT本体でのみ扱えます。

GOTから操作してGOT画面に表示する項目などを変えたい場合、この値によって、GOT画面に表示する項目を変えれたりするのに使えます。

PLCに値を送信して別の処理がしたい場合は、**GD100**の値をスイッチなどで別のDデバイスに書き込みましょう。


# 特殊レジスタ(GS)

GOTに用意されているデバイスには、特殊レジスタというものがあり、GOTの現在の状態を知らせる値が入っています。
例えば**GS1400**には、現在GOTに接続されているクライアント(端末)の数が格納されているので、値を取得することであと何台の端末を追加で接続することができるかなどを調べることができます。

また、値を書き込むことで、GOTに特定の動作をさせることができるGSもあります。

![img_gt27_front.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3535456/5dcbfc7b-7c7e-23d3-34a0-74860733e08e.jpeg)


# その他

#### GDの現在の値をモニタする（調べる）方法
GOT内部デバイスモニタは、「診断」タブからGOT診断を選択し、「モニタ開始」をクリックすると実行できます。

https://fa-faq.mitsubishielectric.co.jp/faq/show/25126


#### GOTの電源を消しても、GDの値を停電保持する方法
通常は、GOTの電源を消したりリセットしたりするとGDの値が0にリセットされます。それを防ぐにはGOTの内部デバイス保持機能を利用します。

https://fa-faq.mitsubishielectric.co.jp/faq/show/25107


#### GOT起動時に、PLCのDデバイスの値を自動でGDに転送する方法
デバイスデータ転送機能を用いて、起動と同時にDデバイス等の値をGDデバイスに転送するように設定します。

https://fa-faq.mitsubishielectric.co.jp/faq/show/12637


### GOTでワードデバイスに設定できる値の種類
https://qiita.com/PockTTY/items/ed0558c727cbb6a9c198
GoとSpannerでフラグをビット管理

## はじめに

ふと大量のフラグを持っているテーブルを見かけて、どうにかできないかなーと考える機会がありビットで管理することで保守性が高くなるのではと思い考えの整理とアプトプットのため記事を書きました。

## 利用言語/ツール

- Go
- Spanner

## サンプルコード

https://github.com/boxkot11p/bit-flag-pattern

## bool値でのフラグ管理

テーブル定義を行い際にフラグを持たせるとすると下記のようなパターンが一般的だと思います。

```sql
CREATE TABLE Users (
  UserId STRING(64) NOT NULL,
  Name STRING(128) NOT NULL,
  EntranceNormalFlag BOOLEAN NOT NULL,
  EntranceSpecialFlag BOOLEAN NOT NULL,
  EntrancePremiumFlag BOOLEAN NOT NULL,
) PRIMARY KEY(UserId);
```

カラムが何の意味を持っているのかわかりやすいですね。
しかし要件によってはフラグの増減が定期的にある可能性もあります。
その場合に都度マイグレーションをかけるのは辛いですね。
またSQLで検索する際に多数のフラグを使う場合に何をしているのかわかりずらくなります。


## 2進数でのフラグ管理

ビット演算でフラグの管理をする場合は下記のようなSchemaになります。

```sql
CREATE TABLE Users (
  UserId STRING(64) NOT NULL,
  Name STRING(128) NOT NULL,
  EntranceFlag INT64 NOT NULL
) PRIMARY KEY(UserId);
```

Flagを管理するカラムに何種類のフラグが存在して、実際に登録されたデータを見てもわからないと思います。
しかしフラグの増減が発生してもマイグレーションの必要がないのがメリットです。
またフラグ管理はアプリケーション側のコードで行うのでDB上で視覚的にわかりやすくすることを捨てています。
では次にアプリケーション側でどのようにフラグを管理するのか紹介します。

## フラグ管理のコード

フラグ管理を行うコードは下記になります。

```go
type EntranceFlag int64

const (
	EntranceFlag_UNSPECIFIED EntranceFlag = 0b000
	EntranceFlag_NORMAL      EntranceFlag = 0b001
	EntranceFlag_SPECIAL     EntranceFlag = 0b010
	EntranceFlag_PREMIUM     EntranceFlag = 0b100
)

func HasEntranceFlag(dst int64, src EntranceFlag) bool {
	return dst & int64(src) == int64(src)
}

func MergeFlag(flags []EntranceFlag) int64 {
	result := int64(0b0)
	for _, v := range flags {
		result = result | int64(v)
	}
	return result
}
```

フラグの種類は型定義で行い必要分のフラグを用意します。
今回紹介しているコード上では特定のフラグを持っているか、また複数のフラグをマージして返却する関数を定義しています。
アプリケーション上で必要なロジックに応じて関数を定義してフラグ単体のロジックをまとめていけばいいと思います。

## メリット

- 1カラムでフラグ管理ができるのでマイグレーション頻度を落とせる可能性がある
- 複雑なフラグ検索をする場合に高速に検索が可能
- アプリケーション側に検索ロジックを持たせることが可能
    - SQLでは単純な検索を行う


## デメリット

- フラグを2進数で管理するため保守性が低下する可能性がある
    - 特にEntranceFlagのコードは読み辛い
- DBの値を見た時に何のフラグが立っているのかわかりずらい
    - 気軽にSQLで検索をする際の運用コストが高い

## まとめ

いかがでしたでしょうか？
特段真新しい手法ではないと思いますが、実装のHowとして選択肢として持っておくのはありなのかなと思います。

実装の具体についてはサンプルコードのテストコード上で表現していますので、興味があればご一読ください
記事を読んでいただきありがとうございました。
自作の「かな入力」のタイピングソフトで作業効率化を図りたい

# 概要

巷では、「ローマ字入力」より「かな入力」のほうが入力するキーが少ないので、タイピングが速いといわれていますよね。

しかし、「かな入力」で仕事の効率化を行っている人に出会ったことがありません。

そこで、「かな入力」を練習しようと思ったら、有名なウェブ上でのタイピングソフトの「寿司打」や「イータイピング」は、「かな入力」が対応していませんでした。
そのため、`JavaScript`で **「かな入力」のタイピングソフトを自作**してみました。

今回は、「かな入力」のタイピングソフトを作成して分かったことを紹介できたらと思います。

# 作ったタイピングソフト

### Githubのリポジトリ

https://github.com/ishi720/keyboardUI

### 実際の動作

まだ開発途中ではありますが、入力補助機能を使ってタイピングの練習ができます。
(黄色ボタンが次の入力ボタン、赤色ボタンが実際に入力したキーです）


![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473097/8aa81edb-c297-2ca5-4fe5-3deb8f5e051d.gif)

(なんとか、**こんにちはせかい**をタイピングできるようになりました)


# 本当にタイピングが速くなるのか考察


### キーボードの操作範囲について

知っていたことですが、
「ローマ字入力」(26文字)より「かな入力」（約50文字）と覚えるキーや入力範囲が広いため単純にタッチタイピングを習得するのに時間がかかりそうです。

単純に広がった範囲として、**右手の小指の仕事が多い**のが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473097/bc2656da-ff8f-c014-cc05-23fb92555490.png)


### Shiftキーが必要な文字について

**小文字** や **「」** や **句読点**についてはShiftキーの入力が必要です。

(はじめは、「を」が入力できないのではないかと焦りました）

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473097/7656d446-7b45-0944-7e52-5502d740fae9.gif)


### 入力文字数について

入力文字に対するキータイプ数を表にまとめました。

|入力文字|かな（キータイプ数）|ローマ（キータイプ数）|
|:-:|:-:|:-:|
|**あ**<br>(母音のみ)|1<br>[あ]|1<br>[a]|
|**か**<br>(子音+母音)|1<br>[か]|2<br>[k]→[a]|
|**が**<br>(濁点・半濁点)|2<br>[か]→[゛]|2<br>[g]→[a]|
|**を**<br>(かな入力時Shiftあり)|2<br>[shift]+[を]|2<br>[w]→[o]|
|**ひょ**<br>(小文字あり)|3<br>[ひ]→[shift]+[ょ]|3<br>[h]→[y]→[o]|

子音+母音のひらがなのみキータイプ数が少なくなりました。
それ以外は、タイプ数が同じという結果になりました。

### かな入力では入力できない文字について

かな入力では入力できない文字が存在します。
**数字**や **+*(){}~|￥@** など記号のキーが入力できません。
これが結構致命的な気がします（入力できる方法があれば教えてほしいです）

# 結局、「かな入力」で作業効率化できるの？

現在、「かな入力」を練習中なため、習得できたらどこかで報告します。
ちなみに **こんにちは** は、「かな入力」のほうが速いです。

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/473097/95f81646-d994-01bc-35b4-dd90dcfd071d.gif)


開発途中ではありますが、このタイピングソフトを使って「かな入力」をマスターしましょう！！
（9/14現在は、「**きょうは、りんごをたべる**」が入力キーワードとして設定しています)

タイピングソフトへのリンク → https://ishi720.github.io/keyboardUI/keyboard.html

今度、機会があればコードの説明でもしようかと思います。
ここまで読んでいただきありがとうございました。
awkコマンドで簡単にjpgファイルを一括で連番でリネーム

# 概要
jpgを一括で連番でリネームする想定で記載します。

# 背景
ファイル名一括変更のアプリなどダウンロードして使えますが、エンジニアなのでコマンドなどでできるとスマートですよね。

以下で出来ます。

事前に

```
cd {作業フォルダ}
```

でファイルがあるフォルダに移動しておいてください。

また、そのフォルダにリネーム対象のファイルを置いて、かつ、それ以外のファイルは置かないようにしてください。

# 作業
## 対象ファイル確認

以下のコマンドで、対象のファイルを、そのファイルがどの名前にリネームされるか確認できます。
```
ls | awk '{ printf "mv %s %02d.jpg\n", $0, NR }'
```

## リネーム実行
問題なければ以下のコマンドでリネームしてください。

```
ls | awk '{ printf "mv %s %02d.jpg\n", $0, NR }' | sh
```

うん、簡単！

## その他

ファイル名に全角括弧があると実行エラーになる可能性あります
AmongUsのMODは作るな

# AmongUsのMODは作るな
AmongUsのMODは作らない方がいいです。
(AmongUsだからダメというわけでもありませんが)
# どういうことや
「そんなことはどうでもいい！俺はAmongUsが好きだから作るんだー！！！！」って人はページ閉じて作りましょう。
## MOD開発はむずかしい
まあむずかしいから面白いんですが、舐めてかかると沼ります。
もうわかんないところで沼ります。
## Unityでゲーム作るより難しいところがある
Unityで作ってるとアセットとか自由に入れられますが、MOD開発だとそうは行かない。
全部コードで書きます。Componentの初期状態とかも設定できないですね。
たいへん。
## アプデ対応大変
アプデね。3ヶ月に一回くらいは来ますね。
普通の人は好きかもしれんけどMOD開発に回るとむっちゃ大変。
ことごとく破壊していくのでその度に何日、何週間かけて対応しなきゃならんのですよ。
めんどくさいね。まあでもコレ結構楽しいけどね。
## サポートが大変
もうこれ。MODの種類によるけどサポートに送られてくる内容が...。
いい内容がほとんどだけど偶に礼儀とか、形式に沿ったりとかせずに送ってきたりするのがあります。初対面でそれってなんで！？って感じの礼儀があるのでちゃんとしよう。
## 得られるもの
C#とUnityの知識はそこそこ得られますが、そこら辺です。
あんまり。
## 競合多すぎ
最近はTOH系列のMODが多すぎて、自分のMODが埋もれたりもします。
その分みんなに遊んでもらえるチャンスが減ったり
昔は今と比べると少なかったんだけどね。
## そもそもなんかAmongUsのエンジン変わりそう
Unityのロイヤリティの話でAmongUsが激おこでUnityから変えるかも的なこと言ってたから、
変わる場合全部さようならだよ。
# でもやっぱりおもしろい
MOD開発は面白いです。バグ修正とか役職作り含めて全部面白い。
# おわり
ハマる人はとことんハマります。面白いからね。
でも、ただ単に人気者になってチヤホヤされたい！って人には向いてないよ。
アモ好きな人はぜひ開発しよう。むっちゃ面白いよ。
面白いよ。面白いよ。
色々やりようがあるし。
後フォークよりもプルリクのほうがむっちゃ楽だからプルリクおすすめ。
リリースとかサポートは全部そのMODがやってくれるしね。
思い立って雑に書いたやつなのでスマソ
データ分析やコーティングなどを自動的に実施するOSS：Open-Interpreter

最近すごい話題になったOSS、Open-Interpreter（わずか1週間でGitHubでStar数が500から18000くらいまで上がりました）について共有したいと思います。


Open-Interpreterとは自然言語によるプログラミングをローカルで実現するオープンソースです。

GPTも似たような機能（Code Interpreter）がありますが、インターネットに接続できない、一部のライブラリやパッケージしかインストールできないなどの利用制限があるために、実際に活用している状況は限られています。
ですが、Open-Interpreterはローカル環境で実行しますので、もちろんインターネットにアクセスできますし、パッケージやライブラリの利用にも何の制限もないので、非常に使いやすいです。
これを活用することでは、まったくコーティング知識がない方でも、普通にデータ分析をできるようになります。


私も試しに使ってみました。"各都道府県の2013年~2022年のスーパーマーケット店舗数データ（オープンデータ）"を使ってOpen-Interpreterから簡単なデータ分析をやってもらいました。（以下は指示文とOpen-Interpreterが考えた進め方）
![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/a9eafc0d-4504-0721-6278-46357267bd14.png)

特にすごかったと感じたのは、エラーと間違っているところを自分で気づいて直してくれるところです。
下の通りに、店舗数が最も多い都道府県を集計して、結果が"合計"になってしまったですが、それが間違ってることを自分で気づいて、自動的に"合計"を無視してもう一回集計して、正しい結果"東京"をゲットできました。
![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/d2b48b62-72f7-def4-4f20-045da0fe638e.png)


途中で一度切れてしまいましたので、最後までできてなかったですが、データクレンジングまではできました。欠損値なども検出すると中央値で補完してくれます。
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/05ba5823-a9f5-64c5-d7a0-e5348c4c627c.png)

![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/58262efe-74b8-dac5-f8d4-c8c64242e5a6.png)

もちろん全てのコーディングや処理はOpen-Interpreterが自動で行ってくれるので、ユーザーは特に何もする必要がありません。


興味ある方はこちらをご覧ください
https://github.com/KillianLucas/open-interpreter/
【GAS】3分でできるカレンダー処理がchatGPTで2時間かかったので共有しておく

情けない失敗談なんですが、ググっても意外と答えが得られなくて、
chatGPT(3.5)と一緒に右往左往しました。

犠牲者が増えないようにここに完成したコードをまとめておきます。

なお、以下は前提として、Googleフォームで送られてきたデータについて、スプレッドシートの対象行を読み直した値が `formData` に入っています。
```
    /* カレンダーに登録 */
    var myCalendar = CalendarApp.getCalendarById(カレンダーのID);
    var event = {
      summary: formData[イベント名の項目名],
      description: formData[イベント概要の項目名]+ "\nイベントID:"+eventId,
      location: formData[イベント会場の項目名],
      start:new Date(formData[イベント開催日の項目名]),
      end:new Date(formData[イベント開催日の項目名])
    };
    var editEvent = getEventWithKeyword(カレンダーのID, eventId)
    if(formData[イベント開演時間の項目名]){
      event.start.setHours(formData[イベント開演時間の項目名].getHours());
      event.start.setMinutes(formData[イベント開演時間の項目名].getMinutes();

      if (formData[イベント閉演時間の項目名]) {
        event.end.setHours(formData[イベント閉演時間の項目名].getHours());
        event.end.setMinutes(formData[イベント閉演時間の項目名].getMinutes();
      } else {
        //終了時間が省略されている場合は、とりあえず90分で登録
        var tempDate = Moment.moment(event.start);
        var tempDate2 = tempDate.add(90, "minutes");
        event.end = tempDate2.toDate();
      }
      Logger.log("event:"+JSON.stringify(event));
      if(!modeEdit){
        myCalendar.createEvent(event.summary, event.start, event.end, event);
      } else if(editEvent) {
        // イベント情報を更新
        editEvent.setTitle(event.summary);
        editEvent.setDescription(event.description);
        editEvent.setLocation(event.location);
        editEvent.setTime(event.start, event.end);
      }
    } else{
      // 終日イベント
      Logger.log("event:"+JSON.stringify(event));
      if(!modeEdit){
        myCalendar.createAllDayEvent(event.summary, event.start, event);
      } else if(editEvent) {
        // イベント情報を更新
        editEvent.setTitle(event.summary);
        editEvent.setDescription(event.description);
        editEvent.setLocation(event.location);
        editEvent.setAllDayDate(event.start);
      }
    }
    Logger.log("イベントをカレンダーに登録しました。");
```
登録済みのイベントを見分けるために、イベント概要に特定のキーワードを埋め込みました。以下は対象イベントを検索する関数です。
```
function getEventWithKeyword(calendarId, keyword) {  
  // カレンダーを取得
  var calendar = CalendarApp.getCalendarById(calendarId);
  
  // 検索範囲＝現在起点で後1年間
  var now = new Date();
  var startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 365);
  var endDate = now;
  endDate.setDate(startDate.getDate() + 365);

  // カレンダー内のイベントを取得
  var events = calendar.getEvents(startDate, endDate, {search: keyword});
  
  // キーワードを含む最初のイベントを取得
  if (events.length > 0) {
    var firstEventWithKeyword = events[0];
    return firstEventWithKeyword;
  } else {
    Logger.log("概要にキーワード '" + keyword + "' を含むイベントは見つかりませんでした。");
    return null;
  }
}
```

# 何がつまりやすいのか
* 上記コードでは、Momentを使っていますが、GASが素のままだと時間系の処理に弱いのを、chatGPT3.5は分からないようで、いろいろ架空のコードを提案してきました。
* GASでカレンダーを登録する関数、引数の組み合わせについても、chatGPTはきちんと理解していないようです。