OmniAICreator/Qiita-1.07M huggingface dataset:
Keycloak の account console が表示されない理由 / If Keycloak Account Console keep loading

 とある Keycloak が `/realms/master/account/` にログインした後、ぐるぐる画面で表示されない問題がありました。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/0bd0116b-26c5-7624-9493-86682993363e.png)

javascript errorが出ていました

```
GET https://example.com/realms/master/account/?userProfileMetadata=true 403 (Forbidden)
```

いろいろ調べた結果

> Admin console > Realm roles > default-roles-master 

ここに `account.manage-account` がないのが原因でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/9b0520be-5368-18f9-047b-5032c9c34a4d.png)

すっきりした〜
【UiPath】Autopilot for Developersを試してみた（テキストからワークフローを生成する編）

# １．はじめに
　Autopilot for Developersは2024年7月2日にGAされた機能となります。いくつかの機能がありますが、今回はStudio Web上で「テキストからワークフローを生成する」を試してみたいと思います。
　また、[DevDivesというウェビナー](https://start.uipath.com/devdives240726_autopilotfordeveloper.html)で第1弾第2弾の一部内容に触れていますので、そちらも併せてご覧頂けると幸いです。

# ２．前提条件
　Automation Cloudにおいて、以下のいずれかのライセンスを保有していることを前提とします。
　　**・Automation Developer - ネームド ユーザー**
　　**・Citizen Developer - ネームド ユーザー**
　　**・Tester - ネームド ユーザー**
　細かな消費条件や制限については[公式Doc](https://docs.uipath.com/ja/autopilot/other/latest/user-guide/about-autopilot#licensing)をご参照ください。
　また、Integration Serviceの以下コネクションを事前に作成しています。（もちろんStudio Web上でも後からコネクションの作成は可能となります。）
　　**・Microsoft OneDrive & Sharepoint**
　　**・Microsoft Outlook 365**

# ３．使ってみよう
## ３．１．ユースケース
　ユースケースとして、「OneDriveに特定のExcelファイルが作成されたときに、特定の宛先にメールを送り、ファイル連携する」を考えていきます。

## ３．２．プロンプト文実行
　プロンプト文としては以下の2つを用意しました。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301393/aa4a1423-94e3-a688-cd58-f25e0cee5d89.png)
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301393/7a70cd43-8b54-7210-3d75-99c1c0b9a94d.png)

## ３．３．結果
### ケース①
#### 概要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301393/9f7f3d3d-e619-a8db-e3fd-21a135260914.png)

#### 詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301393/5cf382da-0307-5770-41cd-7abc527672aa.png)

#### 所感
　メール送信がOutlookにしたいなと思っていたのですが、Gamilになってしまいました。安定性は課題のある記載内容になっていることがわかります。また、細かい内容指定をしていないのでフォルダー情報などが設定されず、エラーとなっています。

### ケース②
#### 概要
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301393/72d16149-781e-002e-985b-e20924af7b5a.png)

#### 詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301393/9c760651-2f1e-f75d-83b5-910eeb7ee954.png)

#### 所感
　こちらでは指定したアプリケーションを利用して骨組みを作成してくれました。一方で、細かい内容指定をしていないのでフォルダー情報などが設定されず、エラーとなっています。

# ４．纏め
　Autopilot生成機能（テキストからワークフローを生成する）は、ワークフローの骨格しか作ってくれません。少し残念に思う部分もありましたが、文章をもとにアクティビティを選択してくれるので、うまく利用できれば非常に便利な機能となります。また、細かい部分についてはこの後人の手で微調整して、対応することになりますので、大幅に開発時間が短縮できるケースも考えられます。

:::note info
**できること**
- ワークフローの骨格（骨組み）を生成
- 対応するアプリケーションはIntegration Serviceのコネクタが対象（Preview版は未対応）
:::

:::note alert
**できるない**
- フォルダーなどの細かいオプションの指定
- UI Automationの操作
※UI Automation 用Autopilotレコーダーにて提供（Preview機能）
:::

:::note warn
**ベストプラクティス**
- 使用するアプリケーションを選択することで再現性が高くなる
- 箇条書きで記述することにより可読性が高くなる
- 1文は1つの操作を記述することでアクティビティ毎の命令が明確になる
※句読点で文の切れ目を理解してくれますが、意図した部分で明確にすることが重要です。
- UI操作は骨組み作成後にAutopilotレコーダーを利用する
:::

# ５．最後に
　今回のご紹介内容により、少しでもAutopilotに興味を持っていただき、何か1つでもRPAを触ってみるきっかけになれば幸いです。
　本記事はあくまでも個人の見解を述べているものとなりますので、参考情報として頂ければと存じます。
PDFファイルをどうやってオンラインで翻訳しましょうか

　PDFファイルは、日常の仕事でよく見かける形式の一つです。英語のPDFファイルをどうやって迅速に全文翻訳するかについてですが、難しそうに見えて、実際には簡単な方法があります。私が最近使うオンラインPDF翻訳ツールをご紹介します。
　現在、市場に出回っているPDF翻訳ツールの多くは有料ですが、今日はみなさんに無料のAI PDF翻訳ツール「Doclingo」をご紹介します。実際に試してみたところ、PDF文書をアップロードしてすぐ翻訳でき、複数の言語に対応しています。AIによって翻訳して、正確率も高いです。また、さまざまなPDF形式の変換もサポートしています。
 
 　![スクリーンショット_25-7-2024_192215_doclingo.ai.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3825442/09b427e6-c89e-6e29-3f08-4bb97efc4c9f.jpeg)
  
　これは非常に便利で、無料のPDF翻訳ツールです。[doclingo.ai](https://doclingo.ai/ja/)にアクセスすればすぐ使えます。
Git中級者が知っておくべき5つのテクニック

今回は私が実際に現場で使用しているGit中級者向けテクニックを紹介します。

## 1. インタラクティブリベース：コミット履歴の整理

インタラクティブリベースを使用すると、複数のコミットを整理したり統合したりすることができます。

使用例：
```
git rebase -i HEAD~3
```

このコマンドを実行すると、直近3つのコミットを操作できるエディタが開きます。ここで各コミットに対して、pick（そのまま使用）、squash（前のコミットと統合）、edit（コミット内容を編集）などの操作を選択できます。

* 注意点
    * 公開リポジトリの履歴を変更する場合は、チームメンバーに事前に通知することが推奨されます。
    * リベース操作はコンフリクトを引き起こす可能性があるため、慎重に行う必要があります。


## 2. スタッシュの使用：作業コンテキストの迅速な切り替え

git stashコマンドを使用すると、作業中の変更を一時的に保存し、別の作業に切り替えることができます。

特定ファイルのみをスタッシュする：
```
git stash push -m "機能A の作業中" path/to/file1 path/to/file2
```
スタッシュの適用：
```
git stash pop
```
活用シーン：
* 日常的なGit操作の効率化
* 長いコマンドの簡略化

## 3. Git aliasの設定：コマンド入力の効率化
頻繁に使用するGitコマンドにエイリアスを設定することで、入力の手間を削減できます。

.gitconfigファイルの設定例：
```
[alias]
    st = status
    co = checkout
    br = branch
    ci = commit
    unstage = reset HEAD --
    last = log -1 HEAD
    visual = !gitk
```

活用シーン：
* 日常的なGit操作の効率化
* 長いコマンドの簡略化
paizaの問題をPowerShellで解いてみた【長テーブルのうなぎ屋 (paizaランク B 相当)】

この記事はpaizaのプログラミング問題をPowerShellで解いてみようという試みの記事です。

## paizaのプログラミング問題とは？
ブラウザ上でコードを書いて実行できる、無料プログラミング練習問題集です。
1. 難易度別に問題を選ぶ
2. 問題文を読んで、解答コードを書く
3. 提出するとテストケースが実行されて結果をわかる
正解・不正解だけではなく、解答コード例や解説も見ることができるので、プログラミングの習得から復習まで活用できます

## こんな人におすすめ
- プログラミングスキルの腕試しをしたい方
- プログラミングのスキルアップしたい方
- 新しい言語にチャレンジをしたい方

###

通常は問題をc言語やJavaなどで解くのですがPowerShellで解いてみます。

## 問題
長テーブルのうなぎ屋 (paizaランク B 相当)

https://paiza.jp/works/mondai/b_rank_skillcheck_sample/long-table


#### 問題: 
東京の下町に長テーブルで有名な老舗うなぎ屋がありました。

そのうなぎ屋にはとても大きい長テーブルがあり、テーブルの周りにn個の座席が配置されています。
座席には、時計回りに1, 2, …, nと番号が振られています。
座席はテーブルの周りに配置されているので、座席番号nの座席と1の座席は隣接しています。

今、m個のグループの人達が座席に順番に座りに来ます。i番目(1≦i≦m)のグループの人数をa_i人とします。
彼らは、長テーブルに並んだ座席の内、ある連続するa_i個の座席に一斉に座ろうとします。

ただしお客さんは江戸っ子なので、それら座席のうち、いずれか一つでも既に先客に座られている座席があった場合、
一人も座らずにグループ全員で怒って帰ってしまいます。江戸っ子は気が早いんでぃ。

入力では、i番目のグループが座ろうとする連続した座席の位置は、整数b_iにより指定されます。
i番目のグループは、座席番号b_iの座席を始点として、そこから時計回りにa_i個分の座席に座ろうとします。

最後のグループが座りに来た後、無事に長テーブルの座席に着席出来ている人数を出力するプログラムを作成してください。


入力: 入力はm+1行から成ります。
1行目にはn(座席数)とm(グループ数)が半角スペース区切りで入力されます。
i+1行目(1≦i≦m)には2個の整数a_i(グループの人数)とb_i(着席開始座席番号)が半角スペース区切りで入力されます。
入力値最終行の末尾に改行が１つ入ります。
文字列は標準入力から渡されます

出力:
最後のグループが座りに来た後、無事に座席に着席出来ている人数を1行で出力してください。


#### 解き方:
- 空席状況を管理する変数 (配列がよいでしょう) を用意し、すべて空席としてマーク
- グループが来店する度に、そのグループが座れるかどうかを判定
- 座席が円状になり最初の席と最後の席が隣り合っていることに注意


#### コード:
~~~
# 入力を標準入力から読み取る
$n,$m = (read-host).split()
$n = [int]$n
$m = [int]$m

# 座席の使用状況を管理する配列　すべて空席としてマーク（Falseは空いている、Trueは埋まっている）
$seats = @()
(1..$n) | %{$seats += $False}

# 座れた人数のカウンター
$seated_count = 0

# 来店グループの処理
(0..($m-1)) | %{
	$a, $b = (read-host).split()
	$a=[int]$a
	$b=[int]$b
	$b -= 1  # 座席番号を0始まりに変換

	# グループが座ろうとする座席の範囲を計算
	$can_seat = $True
	(0..($a - 1)) | %{
		if( $seats[($b + $_) % $n] -eq $True){
			$can_seat = $False
		}
	}

	# 座れる場合、座席をTrue（埋まっている）に更新
	if($can_seat -eq $True) {
		(0..($a - 1)) | %{ $seats[($b + $_) % $n] = $True}
		$seated_count += $a
	}
}

write-host "$seated_count"
~~~


#### コードの説明:
1.標準入力から読み込む:
~~~
$n,$m = (read-host).split()
$n = [int]$n
$m = [int]$m
~~~

- read-hostを使って標準入力から文字列を読み込み変数に格納します

2.文字列を比較:
~~~
$seats = @()
(1..$n) | %{$seats += $False}
~~~
- 座席の使用状況を管理する配列をすべて空席としてマーク
（Falseは空いている、Trueは埋まっている）

3.座れた人数のカウンター
~~~
$seated_count = 0
~~~
- 座れた人数のカウントを用意。回答用

3.来店グループの処理
~~~
(0..($m-1)) | %{
	$a, $b = (read-host).split()
	$a=[int]$a
	$b=[int]$b
	$b -= 1  # 座席番号を0始まりに変換

	# グループが座ろうとする座席の範囲を計算
	$can_seat = $True
	(0..($a - 1)) | %{
		if( $seats[($b + $_) % $n] -eq $True){
			$can_seat = $False
		}
	}

	# 座れる場合、座席をTrue（埋まっている）に更新
	if($can_seat -eq $True) {
		(0..($a - 1)) | %{ $seats[($b + $_) % $n] = $True}
		$seated_count += $a
	}
}

write-host "$seated_count"

~~~
- 来店グループをread-hostで受け取ります
- 後で処理しやすいように座席番号を-1します
- グループが座れるかどうかを判定
- 座れる場合は座席を埋めます。席数分をseated_countに＋します


4.結果を出力
~~~
write-host "$seated_count"
~~~



### 終わりに
noteにPowerShellのサンプルコードの記事を書いています。そっちも見てね
[PowerShellまとめ](https://note.com/mahalo_/m/m421b17a881c8)

https://note.com/mahalo_/m/m421b17a881c8
自己紹介文を少し変更

お疲れ様です。

以前作成した自己紹介文にて、qiitaさんとgithubさんのマイページの貼り付けをしていなかったなと思い出したので、各ページにてアイコン画像をダウンロードし、少し変更してきました。
また、前回の投稿にてコメントで、markdown記法なるものを教えていただきましたので、そちらも試しにこの投稿で実装できているか確認してみたいと思います！

```diff_css
/* アイコン */
+.Q {
+  width: 40px;
+  height: 40px;
+  position: relative;
+  top: 0;
+  margin: 20px 40px 0 20px;
+}

+.Q:hover {
+  top: -10px;
+ transition: 0.4s;
+}


+.G {
+  width: 40px;
+  height: 40px;
+  position: relative;
+  top: 0;
+}

+.G:hover {
+  top: -10px;
+  transition: 0.4s;
+}
```
![254.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/1c40bd1a-b556-c885-15a8-9107b2d0532a.png)
ということでmarkdown記法も反映できているようですね。
試しに +マークもつけてみたのですが、プレビュー上ではちゃんと緑のラインが引かれ、追記されていることが分かるようになっています。よかった…:relaxed:


そして画像が、マウスをアイコン画像に重ねたときの反応なのですが、ポインターが消えちゃったので、不自然な感じになってしまっていますが、ページ上ではちゃんとマウスが重なったときだけ上に動いています。

思い付きではありますが、こういった感じでたまに更新していきたいと思います。
Proxmox上の仮想マシンのディスク容量を増やす方法

# はじめに
Proxmoxで仮想マシンを動かしていると、ディスクの容量を増やしたいときがあります。
そんなとき、つぎの手順を参考にしていただけると幸いです。

# 実行環境
| 項目 | 内容 |
| ---- | ---- |
| ProxmoxVE | 8.2.4 |
| Kernel | 6.8.8-2-pve |
| ゲストOS | AlmaLinux 9.4 |
| cfdisk | cfdisk from util-linux 2.37.4 |

ディスク容量が16GiBの仮想マシンに、16GiBを追加する場合を考えます。

# 手順
#### 1. ディスク容量の増加

対象のVMのディスクをクリックした状態で「ディスクの動作」→「リサイズ」を選択し、任意の容量を追加する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/835335/3a85115e-a207-5d2e-97db-406fc01a5c5e.png)

#### 2. 物理パーテションの拡張
```bash
# cfdisk
```
上記のコマンドを実行すると、つぎの画面が出力されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/835335/87abf5f8-7ffc-2990-bfa6-916b6c089e7f.png)

画像より、先ほどディスクに追加した16GiBが一番下の「Free Space」にあることが分かります。

今回は/dev/sda2を拡張したいため、矢印キーで「/dev/sda2」にカーソルを合わせ、「Resize」を選択します。すると下の方に
``` bash
New Size: 31GB
```
と出るため、Enterキーで決定します。「Write」→「yes」で変更を確定し、「Quit」でcfdiskから抜けます。

あとは
``` bash
# pvresize /dev/sda2
 Physical volume "/dev/sda2" changed
 1 physical volume(s) resized or updated / 0 physical volume(s) not resized
```
で物理ボリュームのサイズを変更します。

#### 3. 論理パーティションの拡張
拡張したいファイルシステム名を確認するため
``` bash
# df -h
```
を実行します。
```bash
devtmpfs                     4.0M     0  4.0M    0% /dev
tmpfs                        888M     0  888M    0% /dev/shm
tmpfs                        356M  5.0M  351M    2% /run
/dev/mapper/almalinux-root    14G  2.1G   12G   16% /
/dev/sda1                    960M  265M  696M   28% /boot
tmpfs                        178M     0  178M    0% /run/user/1000
```
今回はマウント位置が「/」である「/dev/mapper/almalinux-root」を拡張します。
``` bash
# lvextend -l +100%FREE /dev/mapper/almalinux-root
  Size of logical volume almalinux/root changed from 13.39 GiB (3429 extents) to 29.39 GiB (7525 extents).
  Logical volume almalinux/root successfully resized.
```
あとは
``` bash
# xfs_growfs /dev/mapper/almalinux-root
    :
    :
data blocks changed from 3511296 to 7705600
```
でマウントしたまま拡張を確定します。

ここでもう一度「df -h」を確認すると
``` bash
devtmpfs                     4.0M     0  4.0M    0% /dev
tmpfs                        888M     0  888M    0% /dev/shm
tmpfs                        356M  5.0M  351M    2% /run
/dev/mapper/almalinux-root    30G  2.2G   28G    8% /
/dev/sda1                    960M  265M  696M   28% /boot
tmpfs                        178M     0  178M    0% /run/user/1000
```
「/dev/mapper/almalinux-root」の容量が増えていることがわかります。

# 終わりに
以上が、Proxmox上の仮想マシンのディスク容量を追加する方法になります。
PowerQuery: 休日テーブルを利用した、○○営業日前/後の取得の仕方

# 背景

会社で質問が上がっていたので、たまには触ろうと思った記録

# 結論

休日テーブルがある前提なので、それを利用して、営業日かどうかで減算していく関数を作った
あとは、カスタム関数の適用をすれば、以下な感じになる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6a31960a-905d-7dcb-f0e7-eeb77eddf859.png)

## 関数

### GetPreviousBusinessDayWithHolidayTable

休日テーブルで、土日の定義をやめたほうが楽だと思う。
その場合は、<code>isWeekendOrHoliday</code> をコメントアウトしてあるやつにする

```powerquery: 休日スキップ用
// GetPreviousBusinessDayWithHolidayTable
(currentDate as date, businessDays as number, holidays as list) as date =>
    let
        // 初期値の設定
        dayCount = 0,
        dateCheck = currentDate,

        // 営業日を数える関数
        countBusinessDays = (dateToCheck as date, daysToCount as number) as date =>
        let
            // 日付を逆に進める
            previousDay = Date.AddDays(dateToCheck, -1),
            // 土日と休日をスキップする
            // isWeekendOrHoliday = Date.DayOfWeek(previousDay, Day.Monday) > 4 or List.Contains(holidays, previousDay),
            // 休日のみスキップする
            isWeekendOrHoliday = List.Contains(holidays, previousDay),
            // カウントする日数を調整
            newDaysToCount = if isWeekendOrHoliday then daysToCount else daysToCount - 1,
            // 営業日を減らす
            newDayCount = if isWeekendOrHoliday then daysToCount else daysToCount - 1,
            // 終了条件
            result = if newDaysToCount = 0 then previousDay else @countBusinessDays(previousDay, newDayCount)
        in
            result,

        // 初期関数呼び出し
        resultDate = countBusinessDays(dateCheck, businessDays)
    in
        resultDate
```

### GetPreviousBusinessDay

比較用に、土日だけスキップするやつ
休日テーブルなんて面倒だぜ！って場合はこれで。

```powerqyer: 土日のみスキップ
// GetPreviousBusinessDay
// 3営業日前を計算する関数
 (currentDate as date, businessDays as number) as date =>
let
    // 初期値の設定
    dayCount = 0,
    dateCheck = currentDate,

    // 営業日を数える関数
    countBusinessDays = (dateToCheck as date, daysToCount as number) as date =>
    let
        // 日付を逆に進める
        previousDay = Date.AddDays(dateToCheck, -1),
        // 土日をスキップする
        isWeekend = Date.DayOfWeek(previousDay, Day.Monday) > 4,
        // カウントする日数を調整
        newDaysToCount = if isWeekend then daysToCount else daysToCount - 1,
        // 営業日を減らす
        newDayCount = if isWeekend then daysToCount else daysToCount - 1,
        // 終了条件
        result = if newDaysToCount = 0 then previousDay else @countBusinessDays(previousDay, newDayCount)
    in
        result,

    // 初期関数呼び出し
    resultDate = countBusinessDays(dateCheck, businessDays)
in
    resultDate
```

## 参考データ

### 休日定義

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/700dce68-29c5-ca2b-aef1-58c12068112d.png)


# あとがき

Rest API か、Web Contents で、どっかに公開されてる祝日情報さえ取れれば定義も不要なんだけどね
とはいえ、社内用で提供していることは難しいかな。
あるとしたら、Excel定義が多そう。まぁ、それも Excel.Contents で、か
【BigQuery】クエリキャッシュを使うなら半角スペースひとつ変えてはいけない

# クエリキャッシュとは
BigQuery は従量課金制のため、クエリを実行するたびにコストがかかります。
ただし SELECT クエリを実行すると結果がキャッシュに保存され、24時間以内に同じクエリを実行した場合はキャッシュから結果を取得できます。その場合はコストがかかりません。

初回のクエリ実行時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/b2ad8e4c-590d-145a-c4f9-66f9e671eb81.png)

キャッシュ利用時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1217064/cc5608c1-9159-e0c5-5a6c-5900b7c84c69.png)

# クエリキャッシュが効かなくなるケース
クエリ内で CURRENT_DATE() 等を使うとキャッシュが効かなくなるのもそうですが、ここで伝えたいのは記事タイトルの通りです。

[公式ドキュメント](https://cloud.google.com/bigquery/docs/cached-results?hl=ja#limitations)には制限事項として次のように書かれています。

> 同じクエリを重複して実行すると、BigQuery はキャッシュに保存された結果を再利用しようとします。キャッシュからデータを取得するには、重複するクエリテキストを元のクエリと同じにする必要があります。

「元のクエリと同じ」とは実質同じではなく、**完全に一致する**ということです。
下記のパターンは全部NG。クエリキャッシュが効かなくなってしまうので注意しましょう。

- AS句でテーブル or カラムに別名をつけた
- クエリに改行やスペースを入れた or 消した
- 予約後を小文字から大文字に変えた（逆も然り）
- クエリにコメントを入れた or 消した

# 安全な方法
クエリキャッシュが効くかどうかをクエリ実行前に知ることはできません。
大きなクエリを複数回実行して余計コストをかけたくないですよね。
そんな時はジョブ履歴から前回実行のクエリを探しましょう。

https://cloud.google.com/bigquery/docs/managing-jobs?hl=ja#view_job_details_2

ジョブ履歴なら前回実行したクエリを確認できるのはもちろん、その結果が格納された[一時テーブル](https://cloud.google.com/bigquery/docs/writing-results?hl=ja#temporary_and_permanent_tables)にアクセスすることもできます。
積極的に利用しましょう。
yukicoder No.35 タイパー高橋　解説

[問題文](https://yukicoder.me/problems/no/35)
# 解説
i個目の質問に関する解はこんな感じ。
i番目の打てるタイプ数は
$min(floor(T_i*12/1000),|S_i|)$

$min$の左は、問題文の計算式の$x$に$T_i$を代入したものである。
ただ、$floor(T_i*12/1000)$はいくら大きかろうが、結果打てる限界値は$|S_i|$なので、結果打てるタイプ数は上記二つの最小値となるわけだ。

i番目の取り逃すタイプ数は
$|S_i|-打てるタイプ数_i$
こうして、$\sum_{i=1}^N打てるタイプ数_i$つまり、打てるタイプ数の総和と
$\sum_{i=1}^N取り逃すタイプ数_i$つまり、取り逃す数の総和を求めればOK。
ちなみに余談だが、このような割り算が来る問題は私の場合いつも誤差のことで不安になるので、自作のfloor関数という割り算の誤差を確実になくすための関数を使っている。
こんなやつ。
```C++
int floor(int x, int m) {
  int r=(x%m+m)%m;
  return (x-r)/m;
}
```
これをつかえば、[こんな問題](https://atcoder.jp/contests/abc334/tasks/abc334_b)でのWAを防げる。
# C++での解答例
```C++
#include <bits/stdc++.h>
using namespace std;

int floor(int x, int m) {
  int r=(x%m+m)%m;
  return (x-r)/m;
}

int main(){
  int n,ok=0,ng=0;cin>>n;
  //ok=打てるタイプ数、ng=取り逃すタイプ数
  for(int i=0;i<n;i++){
    int t;string s;cin>>t>>s;
    int e=min(floor(t*12,1000),(int)(s.size()));
    ok+=e;
    ng+=s.size()-e;
  }
  cout<<ok<<" "<<ng<<endl;
}
```
【JavaScript 】アロー関数の省略記法について

# はじめに
reactでtodoアプリを作成しているのですが、アロー関数の省略記法についての理解が不足していると感じたので今回の記事を書いてみます。今回は省略記法に絞った記事のためアロー関数とは何かについては書いておりませんのでよろしくお願いします。また、もし間違いなどがあればコメント頂けますと私の勉強になりますのでよろしくお願いします。

# 省略記法の書き方
+ **引数が1つだけの時はカッコを省略できる**

```js
//通常の書き方

const hello = (word) => {
 return word
}

console.log(hello("こんにちは") //出力結果　こんにちは
```
省略記法を使うとこのように書くことができます。
```js
//省略した書き方

const hello = word => {
 return word
}

console.log(hello("こんにちは") //出力結果　こんにちは
```
引数のカッコがなくなりました。


+ **関数の処理が式を直接返す場合**
```js
//通常の書き方

const hello = (word) => {
 return word
}

console.log(hello("こんにちは") //出力結果　こんにちは
```
省略記法を使うとこのように書くことができます。
```js
//省略した書き方

const hello = word => word

console.log(hello("こんにちは") //出力結果　こんにちは
```
{}とreturnがなくなりました。

このように省略記法を使うとすっきりと書くことができます。一方で省略記法を知らないと、これがアロー関数なのかよく分からないと思います。

# 私の場合
冒頭でtodoアプリ作成時に、アロー関数の省略記法についての理解が不足していると書きました。私の場合は何が問題であったのか記載します。

こちらではtodoアプリに記入した勉強時間の合計時間を計算する処理を行っていました。特にコンソールにエラーは出ていないのですが、合計時間が表示されていないという現象が起きていました。
```js
//修正前
const totalTime = time.reduce((totalTime, currentTime) => {
  totalTime + currentTime;
}, 0);
```
**returnが抜けていたのです。**（もしくは{}が不要）
```js
//修正後
const totalTime = time.reduce((totalTime, currentTime) => {
  return totalTime + currentTime;
}, 0);
```
省略ができるということは覚えていたのですが、returnを省略するなら{}の省略する必要がありました。しかしなんとなくでしか覚えていなかったので、ここに気がつくまでにかなり時間がかかってしまいました。

# 最後に
エンジニアになって4年目になります。お恥ずかしい話ですが、変数に関数が代入してあるときなどに「なんでこれがアロー関数なのだろう？」と思っていました。()も{}もないのになぜ関数なのか、今まではよく分かっていませんでした。

今まで私が関数としっかり認識できていなかったのは、省略記法を知らなかったからです。JavaScriptは省略したがる言語とのことなので、省略記法をしっかりと使うことでさらに理解を深めたいと思います。

またこのようなjsの細かい基本知識の不足が、私のreact学習が今までうまくいっていなかった根本的な原因だと改めて再認識しました。
【F#8】F#でプログラミング課題に挑戦しました

# はじめに
F#8でプログラミング課題に挑戦しました

## 問題
文字列を1行ずつ2つ、標準入力で入力し、２つの文字列の長さが同じなら「Yes」、違う場合は「No」を標準出力に出力してください。

## 実装したコード
今回は即興でコーディングしたので、命名規則はぐちゃぐちゃです。
```F#
let str1 = System.Console.ReadLine()
let str2 = System.Console.ReadLine()
let num1 = str1.Length
let num2 = str2.Length
if num1 = num2 then
  System.Console.WriteLine("Yes")
else
  System.Console.WriteLine("No")

```

# 最後に
実務でF#を使うことはないのですが、Microsoftが開発した言語ということで挑戦しました。
第一回LinuCコミュニティ説明会

## 本日の勉強会
勉強会ではなく、かつコミュニティ限定のためオープンなものではないのですが、コミュニティ参加がオープンなので、勉強会もオープンです。
公開して問題ない、ということでお話がありましたので、活動発信ということで出していきます！

## コミュニティ説明会
- 4つのプロジェクトやってます
  - 認定試験開発
  - 教材開発
  - 地域創生
  - 受験者勉強会

受験者勉強会から入ったメンバーが多かったようで、コミュニティ自体の説明の機会は今回が本格的な話になったのかな？

## 参加者自己紹介
人数が人数だったのでざっくりまとめますと

- これからLinuC勉強したい
- 一人情シス
- すでにプロジェクト持ってる人

が多かった印象。特に宇宙開発の話で盛り上がっていたので、この辺に興味があれば一度は聞いて欲しい！

## 参加者ディスカッション
### テーマ１：コミュニティへの期待
- みなさんのコミュニケーションを促進したい！
- アウトプットが課題
  - マネジメント面でも成長を期待
- 資格勉強を独学でやってる→モチベーション管理が課題
  - 101勉強会などで刺激をうけている
- インプット＋アウトプットの場がほしい
  - Slackをはじめコミュニティの活用方法や試験勉強のコツなどを伝授！

#### 以下、フリートーク
- 新規参加者→今開発の登壇者の方へ、教えるロールになった時の話

#### 他チームの意見など
- 循環させたい！
  - 若い方・初学者の方へ：まずは資格を取って活躍しよう！
  - ↑これを広めていく方針にしたい
- 地方創生プロジェクトも良さそう！
- 気軽に集まりたい（Slackではない）
  - Slackハドル使えるよ！
- コミュニティの成功例・失敗例から考える
  - いつもの自分と違う自分を出せる

### テーマ２：気になる技術
- AI(RAG)
- ブロックチェーン

が主

#### 他チームの意見など
- クラウドフレア
  - 講習会になってた
  - 勉強会とか？共有できる場が欲しいね

↑Slackハドル使えると良さそう！

## 放課後
Slackハドルハンズオンをやってみたけど、気軽に話したいという要望を満たすならdiscordかなぁ
複数の会話が同時に発生しなければ当面は大丈夫そう

## 所感
本日が初回でしたが、最近参画された方から積極的な発言があったのが非常に好印象！
ぜひ継続してやっていきたいなぁ、と思う反面（特に私が）常連会みたいにならないようにしないとなー、というのもありました。

新規参入会と常連会を分けてうまーいことやりたい、という要望を置いておきます。

## 次回
リアル会のようです。
来月できたらいいねー、という事だったので続報を待ちます。
【Drupal】JSON:API で Reference先のフィールド値を取得する方法

1度のリクエストで、参照先のデータまで全部がほしいって時普通にありますよね？

例えば、記事に紐づくタグ名や、記事の投稿者のユーザー名など...。

## includes
クエリパラメータに`include`を用いると参照先のデータを取得することができます。
```txt
/api/pokemon--pokemon?include=field_ref_type
```

## fields
`includes`を乱用するとデータ量が大きくなりすぎるので、必要なフィールドのみを指定しましょう。
`fields`パラメータを利用すると、データ量の増大制御できます。
```txt
/api/pokemon--pokemon?include=field_ref_type&fields[type--type]=title
```
**※ あまりにデータが大きくなりすぎる場合は、Fetchをわけてもいいかもですね。**

## 参考
https://www.drupal.org/docs/core-modules-and-themes/core-modules/jsonapi-module/includes
Ubuntuでモニタごとに個別に倍率調整できるようにする

## はじめに

4kモニタを買ったので、デスクトップ版のUbuntu22.04でセカンドモニタとして使うことにした。
ただ、4kモニタだと文字が小さすぎるため、倍率の変更を試みた。

## 問題

しかし、GUIの設定からサイズ調整を"200%"にすると、すべてのモニタが一括で200%になってしまう。
これだと、4kではないモニタの文字が大きくなりすぎてしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1223968/85f92ea3-0e7c-a53b-8e4a-ad1d7cf0a712.png)

xrandrコマンドでscaleオプションを設定してみたが、うまく表示されなかった。

## 解決策

以下のコマンドでGSettingsの値を変更すると、GUIの設定で、モニタごとにサイズが調整できるようになった。

<pre>gsettings set org.gnome.mutter experimental-features "['x11-randr-fractional-scaling']"</pre>
【1分でわかる】Webサイトに載せられる手書き風アニメーションを作ってみよう！

## 前置き
以下の動画で扱った内容です

<iframe width="800" height="400" src="https://www.youtube.com/embed/JC-cPES3gHc" title="【1分でわかる】Webサイトに載せられる手書き風アニメーションを作ってみよう！" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
高評価とチャンネル登録の方、どうぞよろしくお願いします

## 内容
### 手順
1. 書きたい内容を決める
1. 使いたいフォントを選ぶ (手書きフォント系 or 筆記体系がおすすめです)
1. その文字を上から塗りつぶす感じでパスを作成する (直線ツールとアンカーポイント追加ツールのみで可能です)
1. パスの線に着色する（塗りを着色すると少し違う動作になるのでお気をつけください）
1. 元の下書き文字を削除
1. SVG形式で出力
1. [SVG Artista](https://svgartista.net) にてモーションをつける
1. SVGをhtmlに貼り付けられる形で出力し、貼り付け
1. 同時に生成されるcssもコピーして貼り付け
1. 完成！

### 詳細説明
#### 3. その文字を上から塗りつぶす感じでパスを作成する
動画では一本パスで描画していますが、一本でなくても構いません
多本に分ける場合は、レイヤーツールを使用して、再生したい順にそのパスを並べていただき、SVGとして書き出していただければその後の動きは一本パスの場合と同じです
> メモ : 
> 文字のアウトラインを作成してそれを直接使えばいいのではないか、と考えたのですが、それは塗りつぶしの方の要素のため、うまくいきませんでした

#### 8. SVGをhtmlに貼り付けられる形で出力し、貼り付け
動画にある通りの動作で、右上の [＜/＞Get Code] の部分をクリックし、左部分のSVG形式のところをコピーして、webサイトの使いたい部分に貼り付けていただければ大丈夫だと思います

#### 9. 同時に生成されるcssもコピーして貼り付け
8 の動作と同じように、css部分を丸のままコピーしてwebサイトのcssファイルに貼り付けていただければ大丈夫です

***

まさか、告知・SNS拡散一切なしの初投稿の動画を投稿後2分で20回も再生していただけるとは思いませんでした
みなさん、本当にありがとうございます
しかしながら、この動画を見てくださった方から「こんなに短い動画でやり方がわかるわけがない」とのお言葉をいただいたため、短文ながら、Qiitaの記事にまとめました
Youtubeの方も見ていただけると幸いです

なお、この内容でも不足している、もっと詳しく述べてほしい、と考える方がいらっしゃいましたら、コメント欄 (Qiita側でもYoutube側でも結構です) にその旨を書いていただけると幸いです

今後ともよろしくお願いします
AtCoder 勉強記録[C++] その31

AtCoderで入茶を目指して勉強しています。
勉強を継続するために投稿を始めました。
もともとアカウントを作成していましたが、今年の4月から本格的に勉強を始めました。
一応自分用に解法を書いていますが雑です、自分で読み返して困ったら修正します。
[私のアカウント](https://atcoder.jp/users/nanami_brother)
[解いた問題](https://kenkoooo.com/atcoder/#/table/nanami_brother)
# 本日解いた問題
## B - Explore
[B - Explore](https://atcoder.jp/contests/abc265/tasks/abc265_b)
解答
```c++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vec = vector<ll>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)


int main() {
  ll n, m, t;
  cin >> n >> m >> t;
  vec a(n);
  rep(i, n-1) cin >> a[i];
  vec bo(n, 0);
  rep(i, m) {
    ll x, y;
    cin >> x >> y;
    bo[x-1] = y;
  }
  for(int i = 0; i < n; i++){
    t += bo[i];
    t -= a[i];
    if(t<=0) {
      cout << "No" << endl;
      exit(0);
    }
  }
  cout << "Yes" << endl;
}
```
### 解法
すべての部屋の要素数を持つ配列`bo`を用意しておく。ボーナス部屋の要素を`Yi`にし、それ以外の要素を0にする。ループで待ち時間に`bo`を加え、`Ai`を引くことで結果が求まる。
## C - Jumping Takahashi
[C - Jumping Takahashi](https://atcoder.jp/contests/abc240/tasks/abc240_c)
解答
```c++
#include <bits/stdc++.h>
using namespace std;
using ll = unsigned long long;
using vec = vector<ll>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define m 998244353

int main() {
  ll n, x;
  cin >> n >> x;
  vector<ll> a(n);
  vector<ll> b(n);
  vector<vector<bool>> dp(n+10,vector<bool>(x+10, false));
  rep(i, n) cin >> a[i] >> b[i];
  dp[0][0] = true;
  for(int i = 0; i < n; i++) {
    for(int j = 0; j <= x; j++){
      if(j >= a[i] && dp[i][j-a[i]]) dp[i+1][j] = true;
      if(j >= b[i] && dp[i][j-b[i]]) dp[i+1][j] = true;
    }
  }
  if(dp[n][x]) cout << "Yes" << endl;
  else cout << "No" << endl;
}
```
### 解法
動的計画法を用いて解いていく。[こちらの記事](https://drken1215.hatenablog.com/entry/2024/07/05/015244)と[こちらの記事](https://qiita.com/drken/items/a5e6fe22863b7992efdb)を参考にして解いた。
DPは今まで勉強したことがなかったため、勉強するきっかけとなってよかった。
### 参考文献
[AtCoder ABC 240 C - Jumping Takahashi (3Q, 茶色, 300 点)](https://drken1215.hatenablog.com/entry/2024/07/05/015244)
[典型的な DP (動的計画法) のパターンを整理 Part 1 ～ ナップサック DP 編 ～](https://qiita.com/drken/items/a5e6fe22863b7992efdb)
Reactアプリをpush時に自動でテストを実行させる

# はじめに
以前はReactアプリをpush時にfirebaseにデプロイしました。今回はpush時に自動テストも走らせていきます。jest,testing-libraryの環境が整っていることが前提になります。

https://qiita.com/bisketoriba/items/be9ae07ac72e98ac517f

# 早速やってみる
まず適当にsrc/tests/sample.spec.jsを作ってください。今回はサンプルとしてtrueがtrueであることをテストしていきます。
```js
/*---sample.spec.js---*/
describe("Sample Test", () => {
    it("should return true", () => {
      // 成功させる場合
      expect(true).toBe(true);
      // 失敗させる場合
    　　　　// expect(true).toBe(false);
    });
  });
```

以前のymlファイルのコードを少し修正します。supabaseでの環境変数を利用しているのでテスト時もこれを指定してあげないとエラーになります。
```diff_yaml
name: Deploy to Firebase

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Setup Node.js
        uses: actions/setup-node@v2
        with:
          node-version: "18"

      - name: Install dependencies
        run: npm install

-    　　- name: Run build
-       run: npm run build
-       env:
-         VITE_SUPABASE_URL: ${{secrets.VITE_SUPABASE_URL}}
-         VITE_SUPABASE_ANON_KEY: ${{secrets.VITE_SUPABASE_ANON_KEY}}

+     - name: Run build and tests
+       run: |
+         npm run build
+         npm run test
+       env:
+         VITE_SUPABASE_URL: ${{secrets.VITE_SUPABASE_URL}}
+         VITE_SUPABASE_ANON_KEY: ${{secrets.VITE_SUPABASE_ANON_KEY}}

      - name: Install firebase-tools
        run: npm install --save-dev firebase-tools

      - name: Deploy to Firebase
        uses: w9jds/firebase-action@master
        with:
          args: deploy --only hosting
        env:
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
```
これでpushしたらテストが実行され、firebaseへのデプロイも行われるはずです。

# おわりに
前回と今回の記事で簡単なCI/CDを構築できました。今回は簡単なテストを書きましたが今後はもっと実用的なテストも書いていきます。

# JISOUのメンバー募集中
プログラミングコーチングJISOUではメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？

気になる方はぜひHPからライン登録お願いします:point_down:

https://projisou.jp
【Angular】Materialのmat-buttonを共通化してみる

コーヒーが大好きで頻繁に飲むのはいいが、いつもお腹を下す泉（[@izumin_0401](https://twitter.com/izumin_0401)）です。

# Angular Materialのコンポーネントを共通化したい
Angularを触っていると、色んなところにMaterialの部品が散らかってしまい、収拾がつかないことありますよね？（僕はある）

ということで、とりあえずmat-buttonを共通化する際のサンプルを書いてみた。

# ソースコード
## 共通ボタンコンポーネント
```typescript:button.component.ts
import { CommonModule } from '@angular/common';
import { Component, EventEmitter, Output } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';

@Component({
  selector: 'app-button',
  standalone: true,
  imports: [CommonModule, MatButtonModule],
  template: `
    <button mat-button (click)="click()">
      <ng-content></ng-content>
    </button>
  `,
  styles: [
    `
      button {
        /* 何かしらのCSS */
      }
    `,
  ],
})
export class ButtonComponent {
  @Output() event = new EventEmitter();

  click() {
    if (this.event) {
      this.event.emit();
    }
  }
}
```

## 呼び出し側
```html:app.component.html
<app-button (event)="click()">ボタン</app-button>
```

共通化するだけなら簡単だから、なるべく早めにやっちゃおうね！

# まとめ
Angular Materialの共通ボタンコンポーネントを作ってみた。

コンポーネントを共通化するとCSSとかをまとめられるので嬉しいピヨ。

それにしても、スタンドアロンコンポーネント、、、好き♡

https://traveler0401.com/angular-mat-button-common/

# 最後に
暇つぶしに[Twitter](https://twitter.com/izumin_0401)と[ブログ](https://traveler0401.com/)もやってるので見てね。
なぜ私はプロダクトおよびプロジェクト管理に関する記事を書き始めたのか

私が記事を書き始めた理由はいくつかありますが、その中でも特に強い動機となった3つの理由があります。

まず第一に、プロジェクトマネージャーやプロダクトマネージャー、その他どのような役割でも、自分の仕事を常に振り返り、反省することが重要です。多くの書籍を読み、数多くのオンラインコースを受講しますが、時間が経つと忘れてしまいやすく、その知識が曖昧になることもあります。中国には「吾三省吾身」という言葉があり、「毎日自分の仕事を振り返り、他人との関わりを見直すことが大切だ」という意味です。囲碁には「覆盤」という言葉があり、「対局後に自分の手をすべて見直し、どの時点で強くなり、どこでミスをしたかを分析する」という意味です。定期的な自己反省は学習を強化し、継続的な成長を促進します。

次に、書くことは優れた脳内運動であり、日常の業務経験から得た知識や思考を整理するのに役立ちます。説得力やコミュニケーション能力はどのプロダクトマネージャーにも必要なソフトスキルであり、その基礎は論理的思考です。私は既に4～5年のプロダクトマネージャーの経験がありますが、複雑なユーザーの状況や製品の問題を明確に説明するのに時々苦労することがあります。書くことで、思考をより明確にし、複雑なアイデアを分解し、構造化された形で提示することができます。このプロセスは、明確さと効率が重要な高圧状況下で非常に価値があります。書くことはコミュニケーションスキルを向上させるだけでなく、情報に基づいた意思決定を行い、効果的に製品目標を達成する能力も高めます。

最後に、書くことで世界中のトップレベルのプロダクトマネージャーとつながることができます。自分の考えや経験を共有することで、さまざまな地域の専門家と有意義な議論をすることができます。このアイデアの交換は貴重な洞察を提供し、個人的および職業的な成長に貢献します。書くことで、グローバルな対話に参加し、他人の成功と失敗から学び、それを自分の仕事に応用することができます。また、キャリアの発展に不可欠なコラボレーションとネットワーキングの機会も生まれます。経験豊富なプロダクトマネージャーとつながり、業界のトレンドを最新の状態に保つことで、継続的にスキルを向上させ、競争力を維持することができます。書くことは私の個人ブランドを構築するだけでなく、思想的リーダーとしての地位を確立するのにも役立ち、新しい機会を追求し、プロダクトマネジメントのキャリアを前進させるのを容易にします。

これからは、定期的に記事を更新し、さまざまな業界のプロダクトマネージャーと積極的に交流することを心掛けます。この継続的な努力は、私の知識とスキルを高めるだけでなく、専門的なネットワークを広げ、プロダクトマネジメント分野での将来の機会を創出するでしょう。

ここから始めます。グローバルなプロダクトマネジメントコミュニティと共に、共有し、学び、成長していくことを楽しみにしています。この旅が私たちをどこに連れて行くのか、見てみましょう！
Windows11 でパスワードなし共有を実現する

かつてよく使った Guest 共有。パスワードなしでアクセスを実現するものでした。
Windows11では Guestユーザはなくなっていますが、同様な共有をなるべく手間なく実現してみます。


# 環境

Windows11 Pro

# Strategy

レジストリをアレコレしたりしても WindowsUpdate でよく調子が悪くなる。Windowsの標準機能を応用した方法だと、少しは安定しているかな?

Windows の標準機能として、「パブリックフォルダーの共有」機能を使います。

# 「パブリックフォルダーの共有」を有効にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/96008f2a-862b-908a-69df-ed743ca4877b.png)

このようにすると、各ユーザフォルダのパブリックフォルダがパスワードなし共有されるらしい。しかしながら適切に設定すると、他のフォルダでも同様にパスワードなし共有が可能になる。

# 任意のフォルダを共有する

共有に供したいフォルダを右クリックし、共有の詳細からアクセス許可を Everyone を対象にフルアクセスに設定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/b533f4e4-9e7f-94cc-9978-1e28502b9b69.png)


# トラブルシューティング

以下のようなエラーが出て共有リソースにアクセスできない場合がある。

```
「・・・・ にアクセスできません。このネットワークリソースを使用するアクセス許可がない可能性があります。アクセス許可があるかどうかこのサーバーの管理者に問い合わせてください。

参照されたアカウントは現在ロックアウトされているため、ログオンできない可能性があります。」
```

これは、アクセス元からアクセスに使うユーザ名がアクセス先にも存在し、パスワードが2つの間で異なっている場合に起こる。
アクセス元からアクセスに使うユーザを適当に Guest などとすればいいのであるが、アクセス資格情報を記憶してしまったときは以下のようにしてアクセス資格情報を編集する。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/aa8032a3-01d5-5184-19ea-a1d727fb509f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/280dd255-f02e-8253-2f3a-b3051dec2ed9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/5445ef07-c79b-60aa-9d62-f74cb8a83302.png)

ユーザ名をGuest などと適当に入れ、パスワードは空白にして 「OK」するとアクセスするようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/e771fc9d-3438-cf1a-ecc5-b787884af218.png)
【SwiftUI + SwiftData】List の一つの View だけを #Preview で簡単に表示したい。

よくある List 的な View。

![sc 2024-07-25 at 19.21.21.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588914/14b47b56-f05f-eedf-06ad-7598238a0c2c.gif)

この 一つのアイテムの View を #Preview で簡単に表示したい。



# 🤔 使い方
一つ入れ子でクロージャ。

```swift
#Preview {
  PreviewOneModelView { item in
    ItemView(item: item)
  }
  .modelContainer(for: Item.self)
}
```
# 🤔 引用

https://android.benigumo.com/20240725/preview-one-item/
MPAndroidChart の description位置調整

Androidアプリで利用されているグラフライブラリの [MPAndroidChart](https://github.com/PhilJay/MPAndroidChart) で、グラフのdescriptionの位置を調整したときのメモです。

[Speed Test/ネット回線速度測定](https://play.google.com/store/apps/details?id=com.hnimrod.speedtest)というAndroidアプリでヒストグラムをBarChartで描画したのですが、デフォルトで設定したdescriptionが以下のようにグラフに重なるように表示されていました。

![before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59203/95b78d2f-6df1-a10d-159c-02d5f88a311f.png)

赤枠のdescriptionをグラフに重ならないように表示するために、BarDataの`yOffset`と`xOffset`を設定して位置調整できました。

```kotlin
BarData(dataSetWorld, myDataSet).apply {
    val desc = description.apply {
        yOffset = -8f // 下方向がマイナス, 単位px
        xOffset = -16f // 右方向がマイナス, 単位px
    }
    description = desc
}
```

https://javadoc.jitpack.io/com/github/PhilJay/MPAndroidChart/v3.1.0/javadoc/com/github/mikephil/charting/components/ComponentBase.html#setXOffset-float-


![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59203/959ba25f-1da8-038d-4972-7ceaba0851a6.png)
未経験でもわかるオブジェクト指向

# はじめに
　私が未経験エンジニアになって、Javaの基礎の基礎を学ぶなかで抱いた疑問は、「**オブジェクト指向ってなんだ？**」でした。:confounded:
　この記事では、中山・国本著の『スッキリわかるJava入門第4版』（以降では参考書と記載）を参考にしながら、オブジェクト指向について、個人的な理解とはなりますができるだけわかりやすくまとめます。:bulb:
 
# オブジェクト指向ってなんだ？
参考書によると…:book:

 1. オブジェクト指向の定義：**ソフトウェアを開発するときに用いる部品化の考え方**　（ここで開発者が作成する部品はクラスを指します）
 2. オブジェクト指向のメリット：**「ラクして、楽しく、良いものを」作れる**
 3. オブジェクト指向の本質：**現実世界の登場人物とそのふるまいを、コンピュータ内の仮想世界で再現する**
 
# さらにわかりやすく
つまりどういうことか…:confused:

　オブジェクト指向とは、 **大規模で複雑なプログラムをクラスという単位にわけて、各クラスに役割を与えるという考え方**です。
 
 　ここで、開発者が作成した**クラスは設計図となり、その設計図をもとに作成される実体がオブジェクト**です。各オブジェクトは設計図に基づいて、属性と操作（処理の内容）を保持します。
　オブジェクトが保持する操作（＝メソッドの具体的な処理）は、特定の指示が送られる（＝メソッドを呼び出す）ことによって実行されます。
　
　イメージは、クラスが「人間」であれば、属性は「名前」や「年齢」、操作は「食べる」や「眠る」、指示は「食べてください」「眠ってください」といった感じです。
  
　すなわち、これは**私たちが現実世界において、なんらかの役割をもつモノや人を作り、なんらかの指示によってそれを動かすのと同様の考え方**です。

# オブジェクト指向がもつ機能
参考書で説明される**オブジェクト指向の三大機能**が以下の３つです。

**1. 継承**
**2. 多態性**
**3. カプセル化**

ここでは詳細に説明しませんが、、、
　例えば継承は、**もともとあるクラスになんらかの変更を与えた形のクラスが必要な際、元のクラスを引き継いで新たな類似クラスを作成できる機能**で、これによって、継承元のクラスの変更が自動的に継承先のクラスに適応されます。

　継承は、オブジェクト指向のクラスという設計概念によって成り立つといえます。

# オブジェクト指向言語
ちなみに、オブジェクト指向言語には以下のようなものがあります。
* Java
* Python 
* C#
* Ruby
* PHP
* TypeScript

# おわりに
ここまで読んでいただき本当にありがとうございます！:relaxed:
　私も未経験でわからないことばかりですが、基礎から学べることを一緒に楽しめたら幸いです。
[Vagrant][VirtualBox][Mac] Mac環境でVagrantからVirtualBoxを起動する

# 環境
MacBook Pro (2.3 GHz 8コアIntel Core i9)
macOS 14.0（23A344）
Homebrew 4.3.8
gh 2.52.0

# 目次
- [ディレクトリ構成](#ディレクトリ構成)
- [手順](#手順)
- [SSH接続情報を~/.ssh/configファイルに設定して、sshコマンドで仮想マシンへSSHログインできるようにする](SSH接続情報を~/.ssh/configファイルに設定して、sshコマンドで仮想マシンへSSHログインできるようにする)

# ディレクトリ構成
~~~:directory_structure
drive/ ←ルートディレクトリ
├── Applications/
├── Syetem/
└── Usr/
│   ├── shared/
│   └── personnel(ex. Jochun)/　←ホームディレクトリ
│       ├── MyVagrant/
│       │   └── MyTest001/
│       │       └── Vagrantfile (viniciusfs/centos7) ←今回インストールしたVagrantboxによって作成されたVadrantfile
│       │       └── .vagrant (仮想マシン)
│       ├── Desktop/
│       ├── Downloads/
│       ├── Documents/
│       ├── .config/
│       ├── .ssh/
│       ├── .zshrc/
│       └── .local/
│       │   ├── .bin
│       │   ├── 
~~~

# 手順
~~~bash:terminal
// Vagrantで管理する仮想マシン用にホームディレクトリ直下にディレクトリを作成する
mkdir MyVagrant

// 作成したディレクトリに移動する
cd MyVagrant

// 仮想サーバ１台につき、１つのディレクトリが必要なため、ディレクトリを作成する
mkdir MyTest001

// 作成したディレクトリに移動する
mkdir MyTest001

// 使用したいVagrantboxをインストールする
// vagrant box add [box-name] [URL※1]
vagrant box add viniciusfs/centos7 https://atlas.hashicorp.com/viniciusfs/boxes/centos7/

// 仮想マシン設定用のVagrantfileを作成する
// vagrant init [box-name]
vagrant init viniciusfs/centos7

// 仮想マシンを起動する
vagrant up

// 仮想マシンの状態を確認する
// running※2となっていれば正常に動作している
vagrat status

~~~

VirtualBoxを開くと下記のように、仮想マシンが作成されていることが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955010/b9c1ee32-db7d-d9a5-a4ff-576ace8acf05.png)


**※1**：URLは[ここ](https://www.vagrantbox.es)のURL列から取得できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955010/52dcdf66-115d-7f7e-1249-9dd11c099ef8.png)

**※2**：下記の表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955010/29e3c0e2-ff64-29b9-3172-cab9cd3f68e7.png)


# 仮想マシンにSSH接続する
~~~bash:terminal
// 仮想マシンにログインする（SSH接続する）
vagrant ssh

// ログアウトする
vagrant@localhost$ exit

~~~

# SSH接続情報を~/.ssh/configファイルに設定して、sshコマンドで仮想マシンへSSHログインできるようにする
~~~bash:terminal
// 仮想マシンへのSSH接続情報を確認する
vagrant ssh-config
~~~
SSH接続情報が表示される（Host名はdefaultであることが確認できる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2955010/265a2c5f-a396-6597-2030-1d65b553dde8.png)

~~~bash:terminal
// SSH接続情報を~/.ssh/configファイルに追記する
vagrant ssh-config >> ~/.ssh/config

// 仮想マシンにログインする（SSH接続する）-sshコマンド
ssh default

// ログアウトする
vagrant@localhost$ exit

~~~



# 参考リンク
- [MacでのVagrantの使い方とコマンドについて（VirtualBoxに仮想マシンを作成）](https://www.task-notes.com/entry/20150527/1432695600)
- [【Mac版】VirtualBoxとVagrantでローカル開発環境を構築する方法](https://engineer-life.dev/mac-local-development-environment/)
- [vagrantで起動した仮想マシンにsshコマンドで接続する](https://it-jog.com/khow/vag/vag-sshconnection)
Selenium3系から4系へ切り替えた際に遭遇したエラー

久しぶりにスクレイピングの勉強をしようと思い、SeleniumやWebDriverを最新のものにしようと調べていたところ下記の情報を目にしました。

>Selenium4.6以降はドライバを、4.11以降はブラウザを(ブラウザがインストールされていない場合)自動でダウンロードされる。

従来はダウンロードサイトからドライバをダウンロードし、コードの中でパスを指定する必要があったため、「これは楽になる！」と早速ウキウキでSeleniumをアップグレードしました。
ところが以前までと同じようにコーディングした所、思わぬエラーに遭遇してしまいました。

## 突然の「AttributeError: 'WebDriver' object has no attribute」
Webスクレイピングの際、基本的にはHTMLの要素を取得し、操作することになります。
そこで以前スクレイピングを勉強した時と同様、下記のようにコードを記述しました。
```Python:scraping.py
from selenium import webdriver

driver = webdriver.Chrome()
driver.get('URL')

el = driver.find_element_by_class_name('XXX')
```
上記を実行した所、下記のエラー文が出力されました。
```Python:エラー文
AttributeError: 'WebDriver' object has no attribute 'find_element_by_class_name'
```
**「'WebDriver'は'find_element_by_class_name'という属性を持っていません」**
いやいやいや…スクレイピングで必須のメソッドをSeleniumが持ってないはずないやん…
ということで調べてみましたが、結論はシンプルなものでした。

## 結論
結論としては、
**「Selenium4以降では"find_element_by_"のメソッドは使えない」**
というものでした。
※正確にはもっと細かいバージョンで使用不可になったのかもしれません。
従来の`by_class_name`の部分は`find_element`の後ろの`()`内に、第一引数としてBy.～の形で記述します。
そして従来のクラス名などに当たる部分を第二引数に記述します。
```Python:scraping.py
from selenium import webdriver
from selenium.webdriver.common.by import By # Byの定義の為に追加

driver = webdriver.Chrome()
driver.get('URL')

el = driver.find_element(By.CLASS_NAME, 'XXX') # この部分を4系の書き方に修正
```
これでエラーを解消することができました。
今回当たったエラー以外に、他にも色々と変わっているのかもしれません。

## 最後に
プログラミングの世界は日々変化していき、新しいやり方が生まれたり、逆に以前使えたものが使えなくなったりといったことがスピーディーに移り変わっていきます。
といっても今回のは2年くらい前にはすでに変わっていたようなので、単なる私の怠慢ですが…
アンテナは常に高く張っていなければと実感した出来事でした。

## 参考
[Selenium4ではfind_element_by_id、nameは非推奨](http://holiday-programmer.net/selenium_ver_check/)
Pythonを使ってWord文書からマクロを一括削除する方法

Word文書は最も一般的な電子文書形式の一つとして、内容を共有するためのツールとしてよく使用されます。これらの文書はネットワークやデバイス間で転送されるため、その安全性も重要です。マクロは、Word文書に埋め込むことができるVBAのミニプログラムで、自動化操作を実行するために使用されます。マクロは作業効率を向上させることができますが、悪意のある行為者がマクロを利用してユーザーのコンピュータで有害なコードを実行する可能性があるため、大きなセキュリティリスクも伴います。この記事では、**Pythonを使ってWord文書からマクロを一括検出して削除する方法**を紹介します。

- **[PythonでWord文書のマクロを検出して削除する方法](#pythonでword文書のマクロを検出して削除する方法)**
- **[PythonでDocm文書をDocx形式に変換してすべてのマクロを削除する方法](#pythonでdocm文書をdocx形式に変換してすべてのマクロを削除する方法)**

この記事で使用する方法には[Spire.Doc for Python](https://jp.e-iceblue.com/download/spire-doc-for-python.html)が必要です。PyPIからインストールできます：`pip install Spire.Doc`。

[無料ライセンスの申請](https://www.e-iceblue.com/TemLicense.html)

## PythonでWord文書のマクロを検出して削除する方法
`Document.IsContainMacro`プロパティを使用してWord文書にマクロが含まれているかどうかを検出し、結果がTrueの場合は`Document.ClearMacros()`メソッドを使用してマクロを削除できます。
以下は操作手順です。
1. `Document`と`FileFormat`モジュールをインポートします。
2. `Document`のインスタンスを作成します。
3. `Document.LoadFromFile()`メソッドを使用してWord文書を読み込みます。
4. `Document.IsContainMacro`プロパティを使用して文書にマクロが含まれているかを確認し、マクロが含まれている場合は`Document.ClearMacros()`メソッドを使用してマクロを削除します。
5. `Document.LoadFromFile(string: fileName, FileFormat.Docm)`を使用して文書を保存します。
6. リソースを解放します。

**コード例**
```python
from spire.doc import Document, FileFormat

# Documentクラスのインスタンスを作成
doc = Document()

# Word文書を読み込む
doc.LoadFromFile("Sample.docm")

# マクロを検出して削除
if doc.IsContainMacro:
    doc.ClearMacros()

# 文書を保存
doc.SaveToFile("output/DocmToDocx.docm", FileFormat.Docm)
doc.Close()
```

## PythonでDOCM文書をDOCX形式に変換してすべてのマクロを削除する方法
マクロが含まれているDOCMファイルを直接DOCXファイルに変換して、文書内のすべてのマクロを削除することもできます。
以下は操作手順です。
1. `Document`と`FileFormat`モジュールをインポートします。
2. `Document`のインスタンスを作成します。
3. `Document.LoadFromFile()`メソッドを使用してWord文書を読み込みます。
4. `Document.LoadFromFile(string: fileName, FileFormat.Docx)`を使用して文書をDOCX形式で保存します。
5. リソースを解放します。

**コード例**
```python
from spire.doc import Document, FileFormat

# Documentクラスのインスタンスを作成
doc = Document()

# Word文書を読み込む
doc.LoadFromFile("Sample.docm")

# 文書を保存
doc.SaveToFile("output/DocmToDocx.docx", FileFormat.Docx)
doc.Close()
```

この記事では、Pythonを使ってWord文書からマクロを削除する方法を示しました。

さらに多くのWord文書処理のコツについては、[Spire.Doc for Pythonのチュートリアル](https://www.e-iceblue.com/Tutorials/Python/Spire.Doc-for-Python/Program-Guide/Spire.Doc-for-Python-Program-Guide-Content.html)をご覧ください。
RSS 基盤の AI 情報要約ツール、CJK 混在対応、本日 Product Hunt で公開

![digest.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3793311/f5b5b75d-94a8-5dc0-d81d-906bd45e396e.jpeg)
![magic-filter.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3793311/535fe76e-bced-02f6-9ac9-8a63d46a386f.jpeg)


注意欠如・多動症（ADHD）を持つ私にとって、気を散らすことやFOMO（見逃し恐怖症）との戦いはよくわかります。従来のRSSリーダーではうまくいかなかったので、読書を簡素化し、圧倒感を減らすためにTidyreadを作りました。

1. AIがRSSフィードをフィルター、要約、翻訳して、簡潔なダイジェストにまとめます。
2. 強力なAIフィルターで重要なことに集中できます。
3. トピック、ソース、またはアプリ全体をいつでも一時停止できます。
4. CJKおよび他の言語の混在に対応し、優れた読書体験を提供します。

本日、Product Huntでローンチします！どうかサポートをお願いします。毎日のインスピレーションのためのカスタムProduct Hunter Digestをこちらから入手してください：https://www.producthunt.com/posts/tidyread

ご支援ありがとうございます！🙏
効率的なデータ共有と更新 React use Queryが便利だ。

# React Query: 効率的なデータ共有と更新

React Query は、React アプリケーションでのデータフェッチングと状態管理を簡素化する強力なライブラリです。その特徴的な機能の一つに、異なるコンポーネント間でのデータ共有があります。この記事では、同じクエリキーを使用することで、どのようにして効率的にデータを共有し、更新できるかを一般的な例を用いて説明します。

## キーポイント

1. 同じクエリキーを使用すると、React Query は内部的に同じキャッシュを共有します。
2. 一方のコンポーネントで自動再フェッチを設定すると、共有しているすべてのコンポーネントにデータが反映されます。
3. これにより、アプリケーション全体でのデータの一貫性が保たれ、パフォーマンスも向上します。

## 実装例

以下に、ユーザー一覧ページとヘッダーコンポーネントで同じユーザーデータを共有する例を示します。

### API関数（src/api/users.js）

```javascript
export const fetchUsers = async () => {
  const response = await fetch('https://api.example.com/users');
  if (!response.ok) {
    throw new Error('Failed to fetch users');
  }
  return response.json();
};
```

### ユーザー一覧ページのコンポーネント（src/components/UserListPage.js）

```javascript
import React from 'react';
import { useQuery } from '@tanstack/react-query';
import { fetchUsers } from '../api/users';

export const UserListPage = () => {
  const { data: users, isLoading, error } = useQuery({
    queryKey: ['users'],
    queryFn: fetchUsers,
  });

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
};
```

### ヘッダーコンポーネント（src/components/Header.js）

```javascript
import React from 'react';
import { useQuery } from '@tanstack/react-query';
import { fetchUsers } from '../api/users';

export const Header = () => {
  const { data: users } = useQuery({
    queryKey: ['users'],
    queryFn: fetchUsers,
    refetchInterval: 60000, // 1分ごとに再フェッチ
  });

  const userCount = users ? users.length : 0;

  return (
    <header>
      <h1>My App</h1>
      <p>Total Users: {userCount}</p>
    </header>
  );
};
```

## 動作の説明

1. 両方のコンポーネントが同じ `queryKey` (`['users']`) を使用しています。
2. `Header` コンポーネントでは `refetchInterval: 60000` を設定し、1分ごとにデータを再フェッチします。
3. データが更新されると、React Query は内部のキャッシュを更新します。
4. このキャッシュは両方のコンポーネントで共有されているため、`UserListPage` も自動的に最新のデータを受け取ります。
5. 結果として、ヘッダーのユーザー数と一覧ページの内容が同時に更新されます。

## メリット

- コード重複の削減: データフェッチのロジックを複数の場所に書く必要がありません。
- パフォーマンスの向上: 不要な API リクエストを避けられます。
- データの一貫性: アプリケーション全体で常に最新のデータを維持できます。

## 結論

React Query の共有キャッシュ機能を活用することで、少ないコードで効率的なデータ管理が可能になります。一箇所でデータを更新するだけで、関連するすべてのコンポーネントに変更が反映されるため、開発者の負担が軽減され、ユーザー体験も向上します。この方法は、大規模なアプリケーションでのデータ管理を大幅に簡素化し、保守性を高めることができます。
AWS cognito とVue.js 3でamplifyを使わないで、EmailでOTP認証させる方法

## はじめに
今回は、Vue.js 3を用いてCognitoをamazon-cognito-identity-jsとaws-sdkで使用し、EmailからOTP(ワンタイムパスワード)認証させる方法について記載します。

## Pluginを作成する
https://blog.u-chan-chi.com/post/vue-cognito/ の記事を参考に、Vue.js 3用にPluginを作成します。
大まかな点は変更ありませんが、installの部分についてはVue 3で破壊的な変更があったため、以下のように記載し直してください。

```plugins/cognito.js

static install = (app, options) => {
    const cognito = new Cognito();
    cognito.configure(options);
    app.provide('cognito', cognito);
  }
  
```
```main.js

app.use(Cognito, config)

```

## Cognitoを作成する
https://dev.classmethod.jp/articles/cognito-custom-auth-non-password/ などの記事を参考にUserPoolとIdPoolを作成してください。

作成が完了したら、アプリクライアントの設定から認証フローを「ALLOW_CUSTOM_AUTH」に設定してください。

## Lambdaを作成する
https://docs.aws.amazon.com/ja_jp/cognito/latest/developerguide/user-pool-lambda-challenge.html に記載のある通り、3つのLambdaを作成する必要があります。

具体的な実装内容としては、https://devnote.tech/ja/2023/08/email-mfa-using-cognito-user-pool-custom-authentication-challenges/ の記事の内容などを参考にします。

## Lambdaトリガーを設定する
作成した3つのLambda関数をCognitoのユーザープールのプロパティからLambdaトリガーを設定していきます。

トリガーする際は、「認証チャレンジの定義」「認証チャレンジの作成」「認証チャレンジレスポンスの検証」にそれぞれ作成した関数を割り当てていきます。


※「カスタム認証」ではなく、「認証」のLambdaトリガーを選択してしまうと、Lambdaに入るRequest値が変わってしまうので、間違えないように注意してください。

## Custom認証を使用する際のハマったポイント
上記の設定を行い、SESへのアクセス権やCognitoのLambdaトリガーなどを問題なく、行ったがログイン実行時にCognitoがLambdaをトリガーせず、認証用のメールが飛ばない状態となってしまった。
以下のようにsignIn関数内で、AuthenticationFlowTypeを設定することでCustom認証を行えるように設定することが出来ました。

参考: https://aws.amazon.com/jp/blogs/mobile/customizing-your-user-pool-authentication-flow/#:~:text=Client%20SDK%20considerations

```plugins/cognito.js
signIn (username, password) {
    const userData = { Username: username, Pool: this.userPool }
    const cognitoUser = new CognitoUser(userData)
    cognitoUser.setAuthenticationFlowType('CUSTOM_AUTH') // ここがポイント！
    const authenticationData = { Username: username, Password: password }
    const authenticationDetails = new AuthenticationDetails(authenticationData)
    return new Promise((resolve, reject) => {
      cognitoUser.authenticateUser(authenticationDetails, {
        onFailure: (err) => {
          //　割愛
        },
        newPasswordRequired: (userAttributes, requiredAttributes) => {
         // 割愛
        },
        customChallenge: () => {
         // 割愛
        }
      })
    })
  }
```

もし、私と同じように正しく設定していてもLambdaが発火しない場合は上記の設定を確認してみてください。

## まとめ
今回はVue.js 3にamplifyを使用せずにAWS Cognitoの認証にEmailでのOTP認証を行う方法について記載しました。
aws-sdkのみでの方法はVue.js 2での記載の資料が多いため読み替えに手間取りました。Vue3でamplifyを使用できない要件の際の参考になれば幸いです。
また、EmailでOTPを行うのがAWSの公式サポートではないため、早く公式サポートになればいいなと思います。
メールの内容をカスタムしたりとまだまだ楽しめそうなポイントは多いので、深掘りしていきたいです！
外部システム連携に役立つ！kintoneアプリのフィールド名とIDを取得して一覧化するスクリプト

# 課題

kintoneで外部システムとの連携を設定するときなどに、
外部システムでフィールドIDだけで表示/指定することがあるが、
IDを英数字で設定している場合、ぱっと見ではそれが何を表しているか分からない。
（自分で付けたものの130個以上あったので私は覚えきれない…）

しかし、kintone上のGUIで下記のように1個1個確認していくには大変すぎる。
他人に共有するのも大変だし。。。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211946/ec783564-15e7-b36e-09d0-884b1e34e9bf.png"  width="350">

そのため、フィールド名とフィールドIDが並んだ一覧を取得したい。
（ついでに、チャットGPTにID名を含むSQLを書かせたい）
JavaScriptを使ってかんたんに取得できる方法を記載していく。


## 事前準備（必要なパッケージのインストール） ※初回のみ

ターミナルから必要なパッケージをインストールしておく

```
npm install axios json2csv
```


## 取得用コードの作成

以下のコードを新しいJavaScriptファイルとして作成してください。
なお、subdomain、appId、apiTokenの値は対象のアプリのものに変更してください。
- [kintoneサブドメイン確認方法](https://jp.cybozu.help/k/ja/trouble_shooting/registration/confirm_companycode_domain.html)
- [アプリID確認方法](https://support.kincone.com/hc/ja/articles/4411880749081-kintone%E9%80%A3%E6%90%BA-%E3%82%A2%E3%83%97%E3%83%AAID%E3%81%AE%E7%A2%BA%E8%AA%8D)
- [APIトークン生成方法](https://jp.cybozu.help/k/ja/user/app_settings/api_token.html)


```javascript:getKintoneFieldsToCSV.js
const axios = require('axios');
const { Parser } = require('json2csv');
const fs = require('fs');

const subdomain = 'subdomain'; // 対象kintoneサブドメインを指定
const appId = 'app-id'; // 対象アプリIDを指定
const apiToken = 'api-token'; // 対象アプリで作成したAPIトークンを指定

const url = `https://${subdomain}.cybozu.com/k/v1/app/form/fields.json`;

// フィールド情報を取得し、CSVに書き出す関数
async function fetchAndExportFields() {
    try {
        const response = await axios.get(url, {
            headers: { 'X-Cybozu-API-Token': apiToken },
            params: { app: appId }
        });

        const fields = response.data.properties;
        const csvData = Object.keys(fields).map(fieldCode => ({
            "Field Name": fields[fieldCode].label, 
            "Field ID": fieldCode 
        }));

        // フィールド名で昇順にソート
        csvData.sort((a, b) => a["Field Name"].localeCompare(b["Field Name"]));

        // JSONデータをCSVフォーマットに変換
        const json2csvParser = new Parser({ fields: ["Field Name", "Field ID"] });
        const csv = json2csvParser.parse(csvData);

        // CSVファイルに書き込む
        fs.writeFileSync('kintone_fields.csv', csv);
        console.log('CSV file successfully written: kintone_fields.csv');

    } catch (error) {
        console.error('Error:', error);
    }
}

// 関数を実行
fetchAndExportFields();
```
完了したらデスクトップなどのわかりやすい場所に、
「getKintoneFieldsToCSV.js」という名前で保存します。


## 実行

まず、先ほど設定したJavaScriptと同じディレクトリまで移動する
下記はデスクトップに移動するコマンド

```
cd ~/Desktop
```

移動後、下記を入力し、JavaScriptを実行

```
node getKintoneFieldsToCSV.js
```

問題なく完了すれば、
デスクトップ上に**kintone_fields.csv**という名前で、
フィールド名とフィールドIDの一覧のCSVが生成されるので確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211946/27a1aad6-5261-8b4d-d7ca-ec71ddea693f.png)

## 応用

これをチャットGPTなどのAIにUPして学習させれば、
つどアルファベットのIDを記載することなく、フィールド名でSQLを書かせられるので、
IDの確認方法だけでなく、分析用クエリの制作にも有用である。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211946/669e8906-0b61-89d7-ed9c-14fd30c7d6d7.png)