OmniAICreator/Qiita-1.07M huggingface dataset:
ZedのGPUIで日本語を確認

まだまだ暑い日が続きますね。一時期台風の接近で涼しくなったのですが、残念です。それでも夜はエアコンの無いところで寝ることができるようになってきました。エアコン苦手なんです。
半年くらいサボってしまいました。おもしろそうなものが出てきたので紹介です。

# RustでGUI
Rustっていろいろ良い話を聞くのですが、GUIの開発ではコレというものがまだ無いのではないかと思っています。そんな中で前々からWindows版出てこないかなと待っていたものがありました。Rustで作られたエディタ Zedです。

https://github.com/zed-industries/zed.git

この中に[GPUI](https://github.com/zed-industries/zed/tree/main/crates/gpui)があって、Zedとともに開発されています。
ZedはWindows版がまだリリースされていないのですが、手元のPCの display driver を最新にして、ソースからビルドしたらとりあえず起動して、使うことができそうでした。実は最初デバイスが無いとか言われて起動できなかったんですが、vulkan を使っているためか最新のドライバを必要としているようです。

# GPUIのサンプルを試してみる
Zedのリポジトリからソースを落としてくると、GPUIにサンプルがいくつかあるので試してみることができます。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132817/a579086a-fb25-581a-c214-20109b0f4ecb.png">

gpuiの場所まで移動して、ビルドできます。
```
C:\.....\zed\crates\gpui>cargo run --example input
```
最初のビルドは時間がかかります。PCのスペックを信じて待ちましょう。

# 日本語はどうか？
いよいよ本題ですね。
RustとかのGUIフレームワークを試すときに必ず見るのは
- 日本語を表示できるか
- 日本語を入力できるか

日本語をメインに使うので外せない要件です。GPUIはどうでしょうか。

あらかじめ、先程のサンプルのinputのソースを修正して日本語を入れておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132817/9615f8fb-70b5-ff58-0394-78f78e59aac9.png)

問題無さそうですね。IMEを使って入力してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132817/41472cf1-b720-bfed-6129-774b6716c856.png)
入力に[CorvusSKK](https://nathancorvussolis.github.io/)を使っているので特徴的な表示になっていますが、問題は無さそうです。日本語入力したときにキーストロークをカウントしてくれませんが、大目に見てもいいのではないでしょうか。

# おわりに
日本語のフォントを設定しないと □ になってしまうとかも無く、うまく表示と入力ができました。けっこういいヤツだと思います。
残念ながらコレを書いている時はドキュメントが揃ってなくて、当面はサンプルやZed本体を参考にしながらの利用になりそうです。
今回は(も)サラっとしか紹介できませんでしたが、ボチボチ何か作ることができるといいなと思っています。その前になにか作りたいものを持つか、声がかかるのを待つか。
TypeError: Keyv is not a constructorの対処法

今まで普通に使えてたKeyvが動かなくなったので対処法メモ
```
npm remove keyv
npm remove @keyv/sqlite
npm i @keyv/sqlite@3.6.7
npm i keyv@4.5.4
```
keyv v5のゴミアプデのせいでうごかなかったっぽいゴミゴミゴミ。
RAGの精度を上げるために参考にした文献や情報など



チートシート
https://www.llamaindex.ai/blog/a-cheat-sheet-and-some-recipes-for-building-advanced-rag-803a9d94c41b

![IMG_0186.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/63b6b133-6eae-578b-8333-87ce74574c35.jpeg)


チャンク数分割についての話題
https://techcommunity.microsoft.com/t5/ai-azure-ai-services-blog/azure-ai-search-outperforming-vector-search-with-hybrid/ba-p/3929167


Meta Knowledge for Retrieval Augmented Large Language Models
https://arxiv.org/abs/2408.09017

![IMG_0185.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43766/7bf9f10d-6cbf-267d-1c85-a245355c58b6.jpeg)
terraform tips 

今更なものも多いが、改めて必要な場面で知ると便利なのでメモしておく

## countとfor_eachの併用
- 通常countとfor_each併用できない。
- ただし、環境差異などで差分が発生する場合にcountでリソース作成要否を判定してから、for_eachで繰り返しリソースを作成したい場合がある。
    - NG例
    ```
    resource "aws_kinesis_firehose_delivery_stream" "aws_to_datadog" {
      count var.environment.inputs.env_name == "prod" ? 1 : 0
      for_each    = local.kinesis_streams
      destination = "http_endpoint"
      name        = each.value.kinesis_streams_name
      ///略///
    ```
    - 以下ならOK
    ```
    resource "aws_kinesis_firehose_delivery_stream" "aws_to_datadog" {
      for_each    =  var.environment.inputs.env_name == "prod" ? local.kinesis_streams : {}
      destination = "http_endpoint"
      name        = each.value.kinesis_streams_name
      ///略///
    ```

## dynamic_blockによる複数リソースの構築

- 一つのリソースブロック中のパラメータブロックで環境ごとの差分を表現したい。
- dynamicを利用することで必要な数だけループもしくは、環境ごとに作成要否を判定できる。

```
resource "aws_lb" "alb" {
  ///略///
   dynamic "access_logs" {
    for_each = var.environment.inputs.env_name == "prod" ? [1] : []
    content {
      bucket  = data.aws_s3_bucket.alb_log[0].bucket
      prefix  = "logs"
      enabled = true
    }
  ///略///
```
DBのメモリについて簡単にまとめてみた

DBの勉強の一環でDBメモリについて調べてみた。
SQL実践入門を読んでいて少し公式を調べつつ自分なりにまとめた記事です。

## DBのバッファの種類

バッファは基本的にメモリに領域を保持している

DBはストレージの遅さをメモリを活用してカバーしているため、

ユーザーが用途に応じて割り当てサイズを変更することができるがそれぞれに対してトレードオフが存在する

### データキャッシュ

アクセス時にディスクにあるデータ(テーブルデータやインデックスデータ)をキャッシュする領域。

ディスクからデータを取得する場合はメモリよりも遅く、SQL文のパフォーマンスが下がる。

キャッシュとしてメモリにデータを保持していれば高速でデータを返すことが可能になるため、

主にパフォーマンスのために用いられる。ここに保持されていない場合はディスクにデータを探しにいく。

基本的にDBはデータの検索を重視しているため、データバッファの方がログバッファよりも多いメモリ割り当てがされていることが多い(更新よりも取得の方がデータの対象数が多い傾向にあるため)

名称

| PostgreSQL | MySQL |
| --- | --- |
| 共有バッファ | バッファプール |

詳細に知りたい場合

参考URL:

[MySQL :: MySQL 8.0 リファレンスマニュアル :: 15.5.1 バッファプール](https://dev.mysql.com/doc/refman/8.0/ja/innodb-buffer-pool.html)

[第101回　InnoDBバッファプールの状態を確認するさまざまな方法 | gihyo.jp](https://gihyo.jp/dev/serial/01/mysql-road-construction-news/0101)

**MySQLのバッファプールの詳細**


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3795660/dabce4c2-c10a-d574-7b13-f3e4331c8da7.png)

バッファプールはLRU(最低使用頻度)アルゴリズムが採用されている。

大容量読み取り操作の効率を高めるため、バッファープールは複数行を保持できるページに分割される。ページとはディスクとメモリーの間で一度に転送するデータ量を表す単位であり、[ページ](https://dev.mysql.com/doc/refman/8.0/ja/glossary.html#glos_page:~:text=%E3%82%B9%E3%83%86%E3%82%A3%E3%83%83%E3%82%AF%E3%82%82%E5%8F%82%E7%85%A7-,%E3%83%9A%E3%83%BC%E3%82%B8,-InnoDB%20%E3%81%8C%E3%83%87%E3%82%A3%E3%82%B9%E3%82%AF)には1つ以上のレコードを含めることができる。バッファプールはページのリンクリストとして実装される。

図で言うと使用頻度の高いデータほど上にいき、使用頻度の低いデータほど下にいく。

- バッファプール(データキャッシュ)の5/8を最近アクセスされた新しいデータをNewSublistとして領域が割り当てられる
- バッファプール(データキャッシュ)の3/8を最近アクセスされていない古いデータをOldSublistとして領域が割り当てられる

ここで新しいページを挿入する際にはOldSublistの先頭に新しいページを挿入する。(OldSublistとNewSublistの中間の位置)

新しいデータであるが、まだあまり使われていないデータとみなし、OldSublistの先頭に挿入する。

データが読み込まれるとNewSublistの先頭に移動する。逆にアクセスされないデータはOldSublistの下層に追い込まれ、そのうち新しいページの挿入の領域確保のため、削除される。

### ログバッファ

更新処理の実行時のキャッシュである。一旦この領域に更新データを溜めて、後でまとめてディスクに書き込みに行く(コミット)。低速なディスク書き込みを後回しにすることでユーザーからはすぐに書き込みが完了したとレスポンスを返すことができる。よってデータのディスクへの書き込みは非同期となる。

ログバッファはデータキャッシュに対してメモリ割り当てサイズが小さい。更新系の処理がメインの使用用途であれば、こちらの割り当てを大きくした方が望ましい。メモリ資源は有限なため、検索と更新のどちらに重きを置くかは使用するアプリケーションに依存する。

名称

| PostgreSQL | MySQL |
| --- | --- |
| トランザクションバッファ | ログバッファ |

参考URL:

[MySQL :: MySQL 8.0 リファレンスマニュアル :: 15.5.4 ログバッファ](https://dev.mysql.com/doc/refman/8.0/ja/innodb-redo-log-buffer.html)

### ワーキングメモリ

ソートやハッシュなどの特定の処理に利用される作業用の領域である。

ORDER BY, 集合演算, ウィンドウ関数などを利用する際に使用される。

データ量が多くなり、メモリ領域が不足した場合はDBはディスクのストレージを利用する。

よって、低速なディスクを利用することによるパフォーマンスの低下が突然起きることとなる。(TEMP落ち)

| PostgreSQL | MySQL |
| --- | --- |
| ワークバッファ | ソートバッファ |

### MySQLでの確認方法

```sql
SHOW GLOBAL VARIABLES WHERE Variable_name IN (
	'innodb_buffer_pool_size', 
	'innodb_log_buffer_size',
	'sort_buffer_size',
	'tmp_table_size',
	'join_buffer_size'
);
```

まとめ

- データキャッシュの領域が多ければ、その分、キャッシュを多く保持できるため検索性能が上がる
- ログバッファの領域が多ければその分、ディスク書き込み頻度が下がり更新性能が上がる。(障害時にダウンするとメモリが消えるため、データ不整合のリスクは上がる)
- ワーキングメモリの領域が多ければ、TEMP落ちしにくくなり、処理がメモリ内で完結するため高速な処理を実現できる。(メモリ資源は有限のため、適切に設定)
README.mdにgithub actionsのワークフロー状態バッジをつける

# README.mdにgithub actionsのワークフロー状態バッジをつける

## はじめに
最近、github actionsを使い始めました。github actionsを使って、ユニットテストを行なっているのですが、オープンソースなどを見ると`passing`といったバッジがREADMEに付けられています（下のようなやつ）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526717/6bb1af3e-3eb2-a2e3-78c6-f1fc0f4aad68.png)


これカッコいいので真似したいと思い調べてみました。メモレベルですが、誰かの役に立てばいいなと思い記事にしました。

## バッジの付け方（メモ）

一応、公式ページにきちんと手順が書かれていますが、手っ取り早く知りたい方向けになります。

GitHub Docs: [ワークフロー状態バッジの追加](https://docs.github.com/ja/actions/monitoring-and-troubleshooting-workflows/monitoring-workflows/adding-a-workflow-status-badge)

**結論**

以下のファイルを画像としてリンクするだけで、OKです。オーナー名、リポジトリ名は自分のgithubでの名前とリポジトリ名です。yamlファイル名はActionsのファイル名です。

```markdown
https://github.com/[オーナー名]/[リポジトリ名]/actions/workflows/[yamlファイル名]/badge.svg
```

具体的には、`![...](URL)`の形式でREADME.mdに埋め込みます。


**markdown**への記述
```markdown
![ワークフロー名](https://github.com/[オーナー名]/[リポジトリ名]/actions/workflows/[yamlファイル名]/badge.svg)
```

これだけで、Actionsの結果をバッジにしてREADME.mdに挿入できます。
BingのCopilotすごい

# AIが全部解決してくれた（追記：エラーは）
『セイト先生が教えるプログラミング入門』最終章の写経が第9節まで終わり、一応日報アプリが出来ました。しかし正しく動きません。F12でコンソールを見てみたところ、CORSに関して何か問題があるようです。おそらく1-3節で説明された環境構築のどこかで間違えたのだろうと思い、原因をBingのCopilotに尋ねてみることにしました。以下にこのAIと私との会話を記します。

# 1. ローカルファイルの直接読み込み
>私はWindows PCでCursor, Vite, Firebaseを使ってwebアプリを作ろうとしています。ところが、index.htmlをChromeで開き、Consoleを確認したところ、以下のようなエラーが出ていました。HTMLファイルとJavaScriptファイルのバグ以外で考えられる原因を教えてください。
index.html:1 Access to script at 'file:///C:/main.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, isolated-app, chrome-extension, chrome, https, chrome-untrusted.

>ローカルファイルの直接読み込み:
file:// プロトコルでファイルを開くと、CORSポリシーによりスクリプトの読み込みがブロックされます。
対策: ローカルサーバーを使用してファイルを提供する。例えば、Viteの開発サーバーを使用することで、http://localhost:3000 のようなURLでアクセスできます。
# 2. パスの書き方の問題
そこで、LiveServerを使ってみました。ところが別のエラーが出ました。
>ローカルサーバーを立ち上げたところ、その問題は解決しました。しかし、今度は以下のようなエラーが出てきました。どうすればいいですか？
index.html:1 Uncaught TypeError: Failed to resolve module specifier "firebase/app". Relative references must start with either "/", "./", or "../".

>相対パスを使用:
インポート文を相対パスに変更します。例えば、import { initializeApp } from 'firebase/app'; を import { initializeApp } from './node_modules/firebase/app'; のように変更します。

# 3. キャッシュの問題
指示通りにmain.jsのインポート文のパスを書き直しました。ところが、「GoLive」ボタンを押して再びファイルを開くと、また別のエラーが出てしまいました。
>インポート文を相対パスに変更したところ、上述のエラーは解決しました。ところが、新たに以下のようなエラーが出ました。どうすればいいですか？
Failed to load resource: the server responded with a status of 404 (Not Found)

>ブラウザのキャッシュ:
ブラウザのキャッシュが原因で古いファイルを参照している可能性があります。キャッシュをクリアして再度試してみてください。

同じブラウザの同じアカウントで同じURLを入力していたためかもしれないと思い、別のアカウントを使ってみました（シークレットウィンドウは使ってみたのですがキャッシュは反映されているようでした）。すると、ようやくエラーの無いコンソールが見られました。

ChatGPT-4、すごい！！！

# 追記：エラー以外の問題

エラーは直りました。けれども履歴ページにもCloud Firestoreのデータにも送信が反映されません。この問題は昨晩、一度main.jsを書き終えたつもりになった段階ですでにありました。
下記のミスを見つけた時点で写経は終わったのですが、その前にCloud Firestoreのデータを消してしまったり、npmコマンドをデタラメに打ち込んだりしました。多分そのせいです。やはり環境構築の問題だったか......

```js
// Cloud Firestoreにデータを送信する
const dJsForm = document.getElementById("js-form");
if (dJsForm) {
  dJsForm.addEventListener("submit", (e) => submitData(e, addDoc, collection));
}; // submitData関数にe以外の引数を渡しているのは、submitData関数の中でそれらを改めて定義しなくてよいようにするため
```
（修正後のコード。修正前はsubmitData()の括弧の中にeしか書いていませんでした）

まだNode.js, npm, Vite, Firebass, それからCursorのTerminalの使い方がよく分かっていないので、今の自分の場合、解決したいなら教科書の指示に従って最初からやり直した方が早い気がします。
まだ「リファクタリング」と「ホスティング」の章が残っていますが、ひとまず別の教科書に"""転進"""することにしました。
【生成AI】パワポ作成めんどくさ... からおさらばだっ!

どうもこんにちは。

突然ですがそこのあなた。

「 <font color="red">**PowerPointで資料作成するのってめんどくさくないですか？**</font> 」

「 **めんどくさい！！** 」と答えたあなた。

正直者ですね。

今回は、生成AIツール 「[gamma](https://gamma.app/)」というツールを使用して資料作成を勝手にやってもらいます！

https://gamma.app/

# gammaって何？

呼び方は、「**ガンマ**」です。

アルファ　→ ベータ　→ ガンマです。

gammaは、**簡単にPowerPointの資料やWebサイト、ドキュメントを作成すること**ができます。今回は一番ユースケースの高そうなPowerPointの資料を作成します。

gammaは**Googleアカウント**を持っていれば、簡単にはじめられます。

無料プランとPlusプラン,Proプランがあります。料金は以下の通り。

![スクリーンショット 2024-09-10 17.19.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/e8b4da5a-c7b9-ba5d-2537-4b3b22d5bedd.png)

# 早速やってみます。

今回、gammaさんに作成していただく資料のお題は以下です。

```
title: 私の自己紹介
contents: 
私の名前はTaroです。北海道生まれ沖縄育ちの25歳です。誕生日は1月1日です。
沖縄育ちなのに北海道で生まれたせいで暑さにめっぽう弱いです。
現在は、東京で生成AIのエンジニアをしています。ずっとデスクワークなので、動きたくてモゾモゾしています。

setting: スライドの構成は表紙1枚、自己紹介1枚。
```

ということでやってみましょう！

## 1. お題貼り付け

![スクリーンショット 2024-09-10 17.27.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/a0fd98e9-291c-9096-3f69-664cbb77b673.png)

## 2. プロンプト設定

画面左でプロンプトを設定します。
資料に貼り付ける画像の指定もできます。

![スクリーンショット 2024-09-10 17.29.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/08804688-3adc-b68c-4939-5f8cea8782a6.png)

## 3. スライドのデザインを設定

可愛い感じにしちゃいます。

![スクリーンショット 2024-09-10 17.30.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/56edc8d4-428b-c338-2422-d52af5f9b781.png)

テーマを選んだら、「生成」をクリック！

# いざ、お披露目！

まず、スライドは2枚と最初に指定しましたが、8枚出てきました...
まぁいいでしょう。

まず、一枚目。
東京タワーが湘南の海に位置しているような絵ですね。良い雰囲気かと。

![1_私の自己紹介.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/875e0284-1a6d-44c2-5094-876ace11a12a.png)

2枚目。
漢字？何語？やはり画像生成では文字はちゃんと生成されないですね。雰囲気は良いでしょう。

![2_基本情報.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/ac9f3edb-927c-ee23-aac7-a80986a7c58e.png)

3枚目。
少しの情報から「北海道の雪景色の中で...」とか「沖縄の青い海と...」って...
すごいな。

![3_ユニークな経歴.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/fcd696d0-c7b9-b564-ec2f-6d8e240ce185.png)

4枚目。
矢印とか使ってもう少しわかりやすく書いて欲しかったな。でも十分に理解はできる。好き。

![4_気候適応の悩み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/7fc1f20b-f6ac-61ca-0862-58820ba4a8db.png)

5枚目。
ちゃんとアイコンも自動で選んでくれているのすごい。「動きたくてモゾモゾ」が採用されてるの嬉しい。

![5_仕事と趣味.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/26a0af0c-d80f-128c-3511-20a9cef34505.png)

6枚目。
1日のスケジュールが勝手に考えられていますね。頑張り屋さんですね。
右の漫画の文字が気になります。左下のイラストは、スマホから腕が生えている？？
右上の子はMac使ってますね。

![6_AIエンジニアの日常.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/d4a0c969-3caf-baa8-c32c-8df93747b272.png)

7枚目。
Taroくんヨガやるらしいです。Taroくん髪の毛長いっすね。左に写っている人ドン引きしてる。

![7_趣味の探索.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/8e1fe32b-c8d5-1681-3a3e-e840b0d35c03.png)

8枚目。
またヨガやってるんかい。めっちゃスタイル良くなってるジャン。
目標設定も勝手に決められてるけど、まあ悪くない。

![8_未来への展望.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711491/dfde8631-a953-5d9c-ab21-07e65884f55d.png)

# 生成したら...

生成後は自分で手直しもできますし、AIによる手直しもできます。
エクスポートは、pptx形式・PDF形式・PNG形式でできます。

pptx形式で出力して、会社指定のデザインテンプレートを適用すれば、すぐにプレゼンで使用できそうですね。

# まとめ

本気のプレゼン資料作るなら、もっと内容を書かないといけない。

でもかなりクオリティの高い資料ができましたね！

以上。
【Python】自動車学校のweb予約を自動化してみよう！

<h2>なぜ作ろうと思ったか</h2>
自動車学校を転校した先が技能や講義が、webでの予約でした。21時に1週間の予約が解放され、
一斉アクセスが起こり、アクセスエラーが起こり、予約画面に移れなかったり、予約画面に入れても、予約が取れるのは先着順。。。。（笑）
予約がとれないのは珍しいことではなく、1週間のスケジュール調整が必要となることが多々ありました。予約のキャンセルが出るのを定期的に予約画面で確認することもできますが、中々キャンセルになることはないです。
そんなシステムにストレスを感じていた私は、ＩＴに興味を持ち、pythonを独学していたのでpythonを使った自動予約システムを作ることにしました。

<h2>なぜpython</h2>
私自身、最初に勉強したのがpythonだからです。pythonは、最初に習う言語として習得しやすく、プログラミング言語に苦手意識を持たずに始められました。

<h2>webスクレイピングについて</h2>
Webスクレイピングとは、Webサイトから特定の情報を自動的に抽出する技術のことです。
この技術を使って、以下の流れで自動ログインを試みました。

1.Edgeの起動（Driverのあるブラウザであればどのブラウザでも大丈夫です。）
↓
2.サイトにアクセス
↓
3.ログイン
↓
4.講習の選択
↓
5.ページ内の特定エレメントのクリックとスクロール

<h2>1.Edgeの起動</h2>

まず、使っているブラウザのバージョンを最新版にします。最新版でなくてもDriverのverを合わせれば使えると思いますが、余計なエラーが発生してしまうと面倒なので、最新版にすることをお勧めします。私は、このエラーの処理時間を取られてしまいました。
使いたいブラウザのDriverをインストールを行ったら、ブラウザを起動するコードを書いていきます。

↓Edge Driverのインストール
https://developer.microsoft.com/ja-jp/microsoft-edge/tools/webdriver/?form=MA13LH#installation

↓起動のコード
※コピペの際は、driverのファイルパスを指定する必要があります。
```
# Edgeブラウザのオプションを設定するためのオブジェクトを作成
options = Options()

# GPUを無効にするオプションを追加
options.add_argument('--disable-gpu')

# ブラウザの拡張機能を無効にするオプションを追加
options.add_argument('--disable-extensions')

# プロキシを直接接続に設定し、プロキシを無効にする
options.add_argument('--proxy-server="direct://"')

# 全てのホストに対してプロキシをバイパスするオプションを追加
options.add_argument('--proxy-bypass-list=*')

# ブラウザを最大化した状態で起動するオプションを追加
options.add_argument('--start-maximized')

# EdgeDriverの実行ファイルのパスを指定
driver_path = r"your_path"

# 指定したパスのサービスオブジェクトを作成
service = Service(executable_path=driver_path)

# EdgeDriverのインスタンスを作成
driver = webdriver.Edge(service=service, options=options)
```

<h2>2.サイトにアクセスと3.ログイン</h2>


↓サイトへのアクセスとログインのコード
※URL、USER_ID、PASSWORDを入力してください。
```
# 指定されたURLにアクセスしてログインページを開く
driver.get("URL")

# ログインフォームのID入力欄を探し、ユーザーIDを入力する
driver.find_element(By.NAME, "ID").send_keys(USER_ID)

# ログインフォームのパスワード入力欄を探し、パスワードを入力する
driver.find_element(By.NAME, "Pass").send_keys(PASSWORD)

# ログインボタンを探し、それをクリックしてログインを実行する
driver.find_element(By.ID, "login_btn").click()
```

<h2>4.講習の選択</h2>
最初に技能予約か座学講習の選択をします。
以下のコードでは、XPath式を使って、Webページの要素の中から、value属性が「技能予約」である最初の要素を検索しています。
XPathは、webページ内の検証を使ってXPath式を取得しました。

```
# WebDriverのインスタンスを使用して「技能予約」ボタンをクリックする

# 講習のボタンをXPathを使って見つける

button = driver.find_element(By.XPATH, "//*[@value='技能予約']")

# 見つけたボタンをクリックする
button.click()
```

<h2>5.講習時間の選択</h2>
講習時間の選択の際、スクロールする必要がありました。そのため、スクロールするコードを入れてから講習時間のボタンをクリックするようにします。

```
win_height = driver.execute_script("return window.innerHeight")
last_top = 1
last_height = driver.execute_script("return document.body.scrollHeight")
top = last_top
top += int(win_height * 10.5) 
driver.execute_script("window.scrollTo(0, %d)" % top)
submit = driver.find_element(By.XPATH, "/html/body/div[2]/table[2]/tbody/tr[6]/td[6]")
submit.click()
```
<h2>最後に</h2>
↓以下の記事を参考にさせていただきました。

https://qiita.com/tkdayo/items/5a110e24abad85822b8f

私の記事が参考になれば幸いです。
何か気になることがあれば教えてくれる嬉しいです！
Cloud LaTeXをVSCodeで使ってGit管理する

## 対象
cloud latexのアカウントを持っていることを想定する。また、Gitも使える前提。

## やり方
### Cloud LaTeXをVSCodeで使う
1. [公式](https://github.com/cloudlatex-team/cloudlatex-vscode-extension/blob/main/docs/README_ja.md#%E6%BA%96%E5%82%99) を参考にして、Cloud LaTeX側の準備をする
1. **ローカルに空のプロジェクト用フォルダを作成し、VSCode でそのフォルダを開く** 
（これを忘れるとVSCode で開いた場所に勝手にcloneされる）
1. [公式](https://github.com/cloudlatex-team/cloudlatex-vscode-extension/blob/main/docs/README_ja.md#%E8%A8%AD%E5%AE%9A) を参考にして、VSCode側の設定をする

### Git管理する
#### 最初にやること
```
cd プロジェクト用フォルダ
git init
```
#### 編集後にやること
```
git status  # check the changes
git add .   # stage the changes
git status  # check the staged changes
git commit -m "comment"   # the comment can be anything
```
[T-DASH] PDFの情報（文字列）を取り出す

# Outline

帳票出力したりするサービスでは、PDFがよく用いられる。
そのPDFをT-DASHにて検証したい。

尚、T-DASHでPDFを検証するには以下のような条件がある

- PDFをローカルにダウンロードできる
- PDFに含まれる文字列を文字として認識できる（範囲指定して文字をとれるかどうか）
- 検証できるのは文字列のみである（表示イメージを検証したい場合は、画像比較でおこなってください）

https://service.valtes.co.jp/t-dash/?qiita

# 技術的な情報

RPA.PDF のライブラリを使用します。

https://robocorp.com/docs/libraries/rpa-framework/rpa-pdf


robotframeworkの命令はシンプルで、以下のkeywordsを用いる。

```
${text} =  Get Text From PDF  $PDF_FILE_PATH
```

これで得られる結果は、json形式になります。

例えば、以下のような3ページのpdfの場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/df0b8d1e-ffa5-80a7-2468-ee7d6cfff642.png)

${text} は、以下のようなjsonが得られます。

```
{1: 'T-DASHManual', 2: 'How to use PDF by robot framework• pip install rpaframework-pdf\n• Keywords Get Text From PDF', 3: 'Thanks'}
```

この場合、情報が多いため、ページを指定することができます。

${text[2]} ：　このように [] を用いてページ番号を指定すると、指定したテキストを取得することができます。

```
How to use PDF by robot framework• pip install rpaframework-pdf• Keywords Get Text From PDF
```

# T-DASHの手順

## カスタム動作

以下設定内容を PDF.yamlのファイル名で保存する

```
ACT-CAT-CUSTOM-64f80d83-a7c0-4f8f-8a61-da2485109d1a:
  action_category_name: PDF
  icon: ''
  color: '#fa1b86'
  custom_data:
    file_name: PDF
    pip_list:
    - rpaframework-pdf
    library_list: []
  actions:
    ACT-CUSTOM-2c53fffe-8cb1-421e-80f2-3f9ce3920c9e:
      action_name: PDFの文字列抽出
      action_type: operation
      action_format: パス「設定値1」のPDFを読み出し、「設定値2」ページの文字列を変数「設定値3」に入れる
      action_note: ''
      action_args:
      - value1
      - value2
      - value3
      action_def:
      - - '${text} = '
        - Get Text From PDF
        - ${value1}
      - - Log
        - ${text[${value2}]}
      - - Set Suite Variable
        - ${${value3}}
        - ${text[${value2}]}

```

次に、作成された PDF.yamlをT-DASHの動作定義 -> カスタム動作 -> カスタム動作をインポート にてインポートする

ライブラリを追加をクリックし、ライブラリの情報を確認する。
今回、MySQLを使うため、"pip install rpaframework-pdf" となっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/ea33c801-1016-454b-52ab-4a26044f4380.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/16f5f924-6014-7d9f-bc77-628c95bf4765.png)

カスタム動作の説明になります

この動作を呼び出すの引数の説明です
| 引数| 説明 | 
|:-----------|:------------|
| 設定値1       | PDFのパスを設定します        |
| 設定値2       | PDFの読み出したいページ番号を指定します        |
| 設定値3       | 読み出した情報を入力する変数名を指定します        |

## スクリプト

今回のテストステップは、単純にローカルにあるPDFを読み出し、２ページ目の情報を変数 ＄{pdf_string} に代入するものとします。
後続の処理で、変数 ＄{pdf_string}を用いて文字列検証などに使ってください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/7865154b-ba9c-14b9-51b2-31013986c04e.png)

## テスト実行結果

詳細ログを確認していただくとわかるように、PDF２ページ目の文字列情報が変数＄{pdf_string} に代入されていることが確認できると思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/3a877d6f-ff11-d10f-f1c4-f80237f762c9.png)
【Day1】Oracle CloudWorld 2024 現地レポート

はじめまして、みなとと申します。
訳あって今回 Orale CloudWorld 2024 に参加することが出来たので、
Oracle初学者なりに現地の様子をお届けできればと思います。

# Oracle CloudWorld 2024 とは
Oracle製品のユーザー、パートナー向けに Oracle が開催するグローバルイベントで、
今年は 9/9 〜 9/12（現地時間）にかけて、アメリカのラスベガスで開催されます。

![IMG_0059.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882447/ffd910a3-a1bc-779e-6a37-4382ad0f3ffc.jpeg)
↑会場（Venetian Convention）へ向かう様子

1,760 人の登壇者による 1,000 以上のセッションが開かれ、
サービス、製品の最新情報、サービスを活用した課題の解決事例などが学べるようです。

# イベントにチェックイン
会場に着いたらまずチェックインをしました。
指示に従ってQR コードと身分証明書（自分の場合はパスポート）を見せるだけなので、
英語が苦手な自分でも1分程度ですんなりチェックインできました。

![IMG_0079.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882447/03fc051d-da0f-8ab6-e4bf-36e77ff12bf7.jpeg)
↑ 参加者用のパスと一緒にスタンプラリーカードをもらいました。
スタンプを全て集めると豪華賞品がもらえるようです。

# Day1の内容
Day1はセッションの数が少なく目立ったイベントもありませんでした。
イベント当日はかなりの人数が会場に足を運ぶので、
チェックイン待ちによる混雑を防ぐための予備日のような位置付けとなっているようです。
特に理由がなければチェックインはDay1で済ませておくのが良さそうです。

午後からは初学者向けのセッションが開かれていたのですがやはり人気なようで、
参加しようと思った時にはすでに満員御礼でした。
人気なセッションはすぐに予約が埋まるので2、3日前には予約を入れておくべきです。
（Day2、Day3のセッションはその後すぐに予約しました。）

その後は会場内を歩き回ってセッションが開かれる場所を確認したり食事会場の下見をして帰りました。

![IMG_0061.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3882447/7dbb7db7-8325-c1a6-235a-51be030bb735.jpeg)
↑フロアは5階層まである

# Day1の振り返り
Day1はやることが少なく、会場に留まる人も少ないためゆっくりと会場を周ることができました。
自分のようにイベント初参加の方はDay1に参加して、翌日以降の膨大なコンテンツ量に備えておくことをオススメしたいです。
Day2は Oracle CEO のサフラ・キャッツ氏のセッションから始まり、その後もCTO、副社長と主要なセッションが続くので、その様子もお届けしていこうと思います。
Next.js + MUIでページネーション機能の実装

## はじめに
Next.jsとsupabaseを用いた記事投稿一覧ページを作成の中で、ページネーション機能を実装したくなったので、まとめました。
主にMUI(Material UI)の公式ドキュメントを元に作成しています。

## 公式ドキュメント
https://mui.com/material-ui/react-pagination/

## 動作環境
・`next: "^14.2.5"`
・`@mui/base: "^5.0.0-beta.40"`
・`@mui/material: "^6.0.0"`
・`@mui/material-nextjs: "^6.0.0"`
・`tailwindcss: "^3.4.1"`
・`@supabase/ssr: "^0.4.0"`
・`@supabase/supabase-js: "^2.45.1"`

## 本題
今回はページネーション機能がメインのため、db等の説明は省きます。
```
"use client";
import { createClient } from "@/utils/supabase/client";
import { Pagination, PaginationItem } from "@mui/material";
import { redirect, useRouter, useSearchParams } from "next/navigation";
import { useEffect, useState } from "react";
import Link from "next/link";

const ITEMS_PER_PAGE = 20; //１ページあたりの記事の表示数

export default function Articles() {
    const supabase = createClient();
    const searchParams = useSearchParams(); // クエリパラメータを取得
    const page = parseInt(searchParams.get('page') || '1', 10);
    const [totalCount, setTotalCount] = useState(0);
  
    useEffect(() => {
      const fetchArticles = async () => {
        const start = (page - 1) * ITEMS_PER_PAGE;
        const end = start + ITEMS_PER_PAGE - 1;

        // 合計記事数を取得
        const { count: totalArticlesCount } = await supabase
        .from('articles')
        .select('*', { count: 'exact', head: true });

        setTotalCount(totalArticlesCount || 0);

        // 記事データを取得
        const { data: articlesData, error } = await supabase
        .from('articles')
        .select(`
          article_id, title, updated_at,
          users (
            username, avatar_url
          )
        `)
        .limit(limit)
        .range(start, end)
        .order('updated_at', { ascending: false });

        fetchArticles();
    }, [page, limit, router, supabase]);
    
    const handlePageChange = (event: React.ChangeEvent<unknown>, value: number) => {
    router.push(`/articles?page=${value}`); // ページ変更時にクエリパラメータを更新
  };

    return (
      {articles.map((article) => (
        <Link href={`/articles/${article.article_id}`} key={id}>
          <div>{article.title}</div>
          <div>{article.updated_at}</div>
        </Link>
      )}
      
      <Pagination
        page={page}
        count={Math.ceil(totalCount / ITEMS_PER_PAGE)}
        onChange={handlePageChange}
        renderItem={(item) => (
          <PaginationItem
            component={Link}
            href={`/articles${item.page === 1 ? '' : `?page=${item.page}`}`}
            {...item}
          />       
        )}
      />
    )}
```

## ちょこっと解説
・dbから記事総数を取得し、1ページに表示したい数で割ってあげることでページネーションのMax値を動的に設定
・後はほとんど公式通りの実装でいける

## 終わりに
MUIやshadcn,chakraUIなど色々触ってみたが、どのUIライブラリも同じような感覚でした。
デザインが綺麗なのでデフォルトでもいいのがとても助かります。
ぜひおすすめのUIコンポーネントや使い方があれば教えてください!
【TypeScript】5分で導入するpre-commitのすすめ w/ husky + lint-staged

## はじめに

誰もが開発で使ったことのあるESLintとformatter。
コード品質を保つために、コミット前などの任意のタイミングで自動実行したくなることがよくあります。

本記事では、***爆速(5分くらい)で*** TypeScriptプロジェクトにpre-commitを導入し、ESLintとPrettierを使用してコード品質を自動で管理する方法をご紹介します。

## 使用するパッケージのバージョン

本ガイドでは、以下のバージョンのパッケージを使用しています：

- husky: 9.x
- lint-staged: 15.x
- eslint: 9.x

最新のバージョンを使用する場合は、各パッケージの公式ドキュメントを参照し、設定方法に変更がないか確認することをお勧めします。

## 必要なパッケージのインストール

プロジェクトのルートディレクトリで以下のコマンドを実行し、必要なパッケージをインストールします：

```bash
npm install --save-dev husky@9 lint-staged@15 eslint@9 prettier
```

## package.jsonの設定

package.jsonファイルに以下の設定を追加します：

```json
{
  "type": "module",
  "scripts": {
    "prepare": "husky",
    "lint-staged": "lint-staged"
  },
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "**/*.{jsx,js,tsx,ts}": [
      "npx prettier --write",
      "npx eslint --fix"
    ]
  }
}
```

この設定により、コミット前にlint-stagedが実行され、変更されたTypeScriptファイルに対してPrettierとESLintが適用されます。

## ESLintの設定

プロジェクトのルートディレクトリに`eslint.config.js`ファイルを作成し、以下の内容を追加します：

```javascript
export default [
    {
        files: ["**/*.{js,jsx,ts,tsx}"],
        ignores: [".config/*"]
    }
];
```

この設定では、すべての.tsファイルをESLintの対象とし、.configディレクトリ内のファイルを除外します。

## Huskyの初期化とpre-commitフックの設定

Huskyを初期化し、pre-commitフックを設定します：

```bash
npx husky init
```

次に、`.husky/pre-commit`ファイルを開き、以下の内容を追加します：

```bash
npm run lint-staged
```

これにより、コミット前にlint-stagedが自動的に実行されます。

## 動作確認

設定が正しく機能しているか確認するために、以下の手順を実行します：

1. サンプルのTypeScriptファイルを作成します。
2. 変更をステージングし、コミットを試みます。

```bash
git add .
git commit -m "Initial commit"
```

正しく設定されていれば、コミット前にlint-stagedが実行され、コードがフォーマットされ、リントチェックが行われます。

## まとめ

pre-commitフックを活用することで、コード品質の管理を自動化し、開発プロセスを効率化することができます。この基本的な設定を土台として、プロジェクトの要件に応じてカスタマイズすることをお勧めします。

継続的なコード品質の向上は、長期的なプロジェクトの成功につながります。この設定を活用し、より効果的な開発ワークフローを実現してください。

:::note warn
React, Vueなどのフレームワークに導入する場合には追加で、プラグインに合わせたESLintのカスタマイズが必要です。
:::

## 参考リソース

詳細な情報や高度な設定については、以下の公式ドキュメントを参照してください：

- [Husky公式ドキュメント](https://typicode.github.io/husky/#/)
- [lint-staged公式ドキュメント](https://github.com/okonet/lint-staged)
- [ESLint公式ドキュメント](https://eslint.org/)
『CSS設計の教科書』をエンジニア歴1週間の人間が読んで学んだこと


　エンジニアの第一線で活躍しようと志し、現在カリキュラムを学習をさせていただいている者です。
　この1週間模写コーディングをしながら、WEBページの作り方を学んでいますが、カリキュラムとして「谷 拓樹(2014)　『Web制作者のためのCSS設計の教科書 モダンWeb開発に欠かせない「修正しやすいCSS」の設計手法』　インプレス」を読む機会がありました。
　下記に、エンジニア歴1週間の人間の視点から、この本を読んで学んだこと、感想を**備忘録的に抜粋**してまとめていきます。
　専門知識がほとんどないため、文章がかなり稚拙になっています。用語の解釈にも誤りがあるかもしれません。また、あくまで私個人が学んだこと、感想であり、この本の内容、主張を代弁しているわけではない点につきましても、予めご了承ください。
 
# cssにおける設計とは
　さまざまな人がコード設計に携わるため、また複雑・リッチなWEBサイトが求められているため、誰がみてもわかりやすいコードを作る必要があります。
そのためには、
　1. コードを変更しても期待通りの変化が起こせるか（**予測しやすい**）
　2. **再利用しやすい**コードになっているか
　3. 新しいコードを追加した時に、それが古いコードに支障をきたさないものか（**保守しやすい**）
　4. 後から**拡張しやすい**コードになっているか
これらを満たすコードを書く必要があります（これらが守れないと破綻しやすいcssになってしまう）。

**破綻しやすいcssの特徴**
* クラスを使わず、htmlのタグにcssを適用させている（書く量が増え、タグを変更したい時にcssも変更しなければならない）
　 →自分はcssのコードを書く際にhtmlの属性をめちゃめちゃ使っていたので、クラスを積極的に使えるようにしたいと思いました。
* pxのような絶対値を多用している（一つの文字の大きさを変更しただけで全体の視認性が崩れるため、すべてのpxを変更しなければならなくなる）
　  →pxをめちゃめちゃ使っていたので、emなどの相対値も使えるように学習していきます。

**→小さな変更が大きなバグに繋がることがあるので、修正しやすいcssを書く必要があります。**

# cssの基本を振り返る
　修正しやすいcssを書くために、cssの基本を押さえておく必要があります。下記に、自分なりの気づきとともにまとめてみました。

* 後に書いたコードが、前に書いたコードを上書きする
←めっちゃ重要。メディアクエリを実装して、スマホ版のレイアウトを作る時、大事なことは先に書こうと思っていたので、メディアクエリのコードが一切適用されず、何度も先輩に相談し、時間がかかってしまった。

* セレクタの詳細度の理解
詳細度は
　1. !important（意図的に使うならOK。使いすぎ＝破綻。私も使って注意されました...）
　2. htmlのstyle属性（htmlにスタイル変更のコードを書くよりcssでスタイル変更を一元化したいので、避けた方が良い。使ったことはないですが）
　3. IDセレクタ（＃を使って記述。現実的に使える一番詳細度の高いセレクタ。一度使ったIDは同一ドキュメントでしか使えない。一要素にIDは一つだけみたいなもの）
　4. クラスセレクタ（.を使って記述）属性セレクタ（[ ]を使って記述。使ったことはない）擬似クラス（:first-childなど）
　5: 要素セレクタ（htmlの<>の中に記述されている、いわゆるタグ。p・li・a・h1などたくさん。cssでは無印）擬似要素（::afterなど）
　6: ユニバーサルセレクタ（*を使う。すべての要素に変更を加える。）
私はよく、
```css
*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: "游ゴシック", sans-serif;
}
```
これで全体の余白を整えたり、フォントを指定したりしています。

* 詳細度の計算について
基本上記の強さ順にコードが適用されるが、３〜５番のセレクタに関しては、書いたセレクタの数だけ強さが１ずつ増えていくイメージ。

**感想：セレクタめっちゃ多い！！ややこしい！！**

1週間プログラミングしてみてそう感じましたが、その上でこの本を読んで学んだことを下記にまとめます。

* 要素セレクタは、詳細度を上げるだけなので、基本cssでは省略できるところは省略する！
* クラスセレクタを活用しよう！
例えば、
以前私が書いたコード
```css
nav li a{
    color: white;
}
```
この”li”要らなくない！？
そもそもクラスをhtmlで割り当てればクラスセレクタ１つで済むのでは？
どうしても書きたければコメントで表現して煩雑なコードを避けよう！
...といった気づきを得ました。

* 不等号を用いた子供セレクタで、冗長化や事故を避けよう！
先程のコードを
```css
nav > li > a{
    color:white
}
```
に変更すると、詳細度が押さえられ、他のコードの詳細度を上げる必要がなくなるだけでなく、他のaタグにも影響しないので事故が抑えられるようです。今後ぜひ参考にしたいです!
# コンポーネント
　修正しやすいcssを書くうえで大事なことで、ここまで学んできたことをざっくりまとめると、

　**・冗長になりすぎないコードを書くこと
　・他の要素に影響しないコードを書くこと**

こうなりました。
　これらを実現させるために、コンポーネントを意識したコードを書く必要があります。
　コンポーネントには、さまざまなアイデアがありますが、私はその中でも「BEM」をおすすめします。これを使うことで、煩雑になりやすいクラスセレクタを、一目で役割がわかる&他に影響しにくいコードが書け（ると信じて）ます！
　詳しくは、下記に記載するサイトの方の記事が大変参考になりましたので、共有させていただきます。

 https://qiita.com/takahirocook/items/01fd723b934e3b38cbbc

# まとめ
　今までは、とりあえず理想の形に近づけようというスタンスで、効率度外視・パワープレーでコードを組んでいました。
　しかし、実務ではさまざまな方と一緒にコードを組んでいくため、効率的で汎用的でローリスクなコーディングが求められていることに気づきました。
　そのために必要なことをこの本から学べたと思っているので、まずはカリキュラムを通して実践していきたいと思いました。

# 参考にさせていただいた本・記事

https://book.impress.co.jp/books/1113101128

 https://qiita.com/takahirocook/items/01fd723b934e3b38cbbc
Revit api FilteredElementCollector CheetSheet

#目次
[1.はじめに](#1-はじめに)
[2.内容い](#2-内容い)
[3.エリア境界線　AreaSchemeLines](#3-エリア境界線　AreaSchemeLines)
[4.内容は](#4-内容は)
[5.おわりに](#5-おわりに)

# 1.はじめに
### FilteredElementCollector関数とは
FilteredElementCollector は、Revit API で要素（エレメント）を収集するために使用される強力なクラスです。このクラスは、Revitドキュメント内の様々なエレメントをフィルタリングし、特定の条件に合致するエレメントのリストを取得するために使われます。
RevitApiにおけるElementとは”全ての要素（物理オブジェクトや注釈オブジェクト、システムファミリなど）”を表す基本的なクラスです。そのため、なにかを取得したい時は、ほぼ必ずFilteredElementCollectorを使用することで解決します。

### FilteredElementColectorの基本構造
1\. コレクターのインスタンス化
ドキュメントを引数にして FilteredElementCollector のインスタンスを作成します。
```cs:qiita.cs
FilteredElementCollector collector = new FilteredElementCollector(doc);
```
2\. フィルタリングの追加
OfCategory や OfClass メソッドを使用して、収集するエレメントの種類を絞り込みます。
```cs:qiita.cs
collector.OfCategory(BuiltInCategory.OST_Walls);  // 壁カテゴリをフィルタリング
```

3\. 結果の取得
ToElements メソッドや ToList メソッドを使って、フィルタリングされた結果を取得します。
```cs:qiita.cs
IList<Element> elements = collector.ToElements();
```

# 2.壁 walls
```cs:qiita.cs
FilteredElementCollector areaBoundaryCollector = new FilteredElementCollector(doc, activeView.Id)
    .OfCategory(BuiltInCategory.OST_Walls) 
    .WhereElementIsNotElementType();
```

# 3. エリア境界線　AreaSchemeLines
```cs:qiita.cs
FilteredElementCollector areaBoundaryCollector = new FilteredElementCollector(doc, activeView.Id)
    .OfCategory(BuiltInCategory.OST_AreaSchemeLines) 
    .WhereElementIsNotElementType();
```

# 4. 一般注釈 GenericAnnotation
```cs:qiita.cs
FilteredElementCollector collector = new FilteredElementCollector(doc)
    .OfCategory(BuiltInCategory.OST_GenericAnnotation)
    .OfClass(typeof(Family));
```

# 5. 今後自身のチートシート用として、追加していく予定です。
# 参考文献

https://www.revitapidocs.com/2024/6359776d-915e-f8a2-4147-b31024671ee1.htm

https://revitapiyasan.com/filteredelementcollector/
『&quot;』や『&amp;』などの謎の文字列がでてきた【特殊文字】

## 解決策
HTMLを覗いていると時々出会う **```&quot;```** や **```&amp;```** などの "&~~~;" は特殊文字と呼ばれるもの。

HTMLから情報を取得する際は下記のように置き換えよう。

~~~ ruby
# 出現頻度が高い文字

# ダブルクォーテーションを変換
.gsub('&quot;', '"')
.gsub('&#34;', '"')

# アポストロフィを変換
.gsub('&apos;', "'")
.gsub('&#39;', "'")

# アンパサンド（アンド）を変換
.gsub('&amp;', '&')
.gsub('&#38;', '&')
~~~

## 特殊文字とは
HTMLで " **<** " や " **"** " などを文字列として表したいときに使う方法
「**文字実体参照**」と「**数値文字参照**」の2種類の表示方法がある
<br>

代表的なものは以下
| 文字 | 文字実体参照 | 数値文字参照 | 説明 |
| --------- | ------------- | -------------- |----------------- |
| **&lt;** | ```&lt;``` | ```&#60;``` | 不等号（小なり）
| **&gt;** | ```&gt;``` | ```&#62;``` | 不等号（大なり）
| **&amp;** | ```&amp;``` | ```&#38;``` | アンパサンド（アンド）
| **&quot;** | ```&quot;``` | ```&#34;``` | ダブルクォーテーション（二重引用符）
| **&apos;** | ```&apos;``` | ```&#39;``` | シングルクォーテーション（引用符）、アポストロフィ
| **&sol;** | ```&sol;``` | ```&#47;``` | スラッシュ
| **&percnt;** | ```&percnt;``` | ```&#37;``` | パーセント

## 実際に使ってみると

~~~ html
<p> 例文だよ </p>
&lt;p&gt; 例文2だよ　&lt;&#47;p&gt;
~~~
<p> 例文だよ </p>
&lt;p&gt; 例文2だよ &lt;&#47;p&gt;


## 参考
https://weblan3.com/html/special-character
[GCP]リソースについて

# 1. リソースの階層
GCPの「リソース」は階層的に編成されている。

|![x](https://cloud.google.com/static/resource-manager/img/cloud-hierarchy.svg?hl=ja)|
|---|
|出典: [Google Cloud リソース階層の詳細](https://cloud.google.com/resource-manager/docs/cloud-platform-resource-hierarchy?hl=ja)|

上位から順に以下4つの分類になる。


**1. 組織**
複数のフォルダリソースを束ねる単位。会社などを表す。

**2. フォルダ**
複数のプロジェクトリソースを束ねる単位。社内の部門、チーム、プロダクトをモデル化できる。

**3. プロジェクト**
複数のサービスリソースを束ねる単位。環境ごと(本番, テスト, 開発 など)のサービスリソース群を管理。

**4. サービス**
GKE, GCSといったGCPのサービスレベルのリソース。単にリソースという言葉が出てきたら、このレベルを挿していることが多い印象

## 1.2. 各リソースに対して設定したIAMポリシー
下位のリソース階層すべてに引き継がれる。
IAMの概要は以下を参照。

https://qiita.com/WisteriaWave/items/a52661732abbd56a889d



# 2. リソースの配置
リソース(ここでは各GCPサービスのインスタンス・マシンタイプといったサービスレベルのリソースよりも細かな単位)に応じて、どのような地理的なエリアの単位(リージョン, ゾーン)で配置できるかが異なる。

## 2.1. リージョンとゾーン
## リージョン
地理的なエリア。複数のゾーンで構成される。

## ゾーン
リソースを配置するリージョン内のデータセンターの単位。
同リージョン内のゾーン同士は、広帯域・低レイテンシのNWで接続されている。

# 2.2. グローバルリソース, リージョンリソース, ゾーンリソース
配置するエリアの大きさごとに、グローバルリソース > リージョンリソース > ゾーンリソース という分類になる。

## グローバルリソースの例
アドレス、イメージ、スナップショット、VPCネットワーク、FW

## リージョンリソースの例
アドレス、サブネット

## ゾーンリソースの例
インスタンス、永続ディスク、マシンタイプ 　

参考:

https://cloud.google.com/compute/docs/regions-zones?hl=ja

https://www.fsi.co.jp/blog/5679/


# 所感
公式ドキュメント内でも文脈によってリソースという言葉のニュアンスが違うような気がしててややこしい。
リソースの階層については、理解していないと以下のような場面でつまづく
- IAMの理解
- TerraformのGoogle Providerで各種Resourceを設定
コストパフォーマンスの観点から見たRPCノードサービスの選び方について

こんにちは。
Doと申します。Cabinet株式会社でCTOを務めています。よろしくお願いします。

# テーマ
ブロックチェーンにリクエストを投げるための開発に、RPCノードプロバイダーサービスを利用する方法は便利で、よく採用されています。

たくさんのプロバイダーサービスの中で、どのように選べば良いのでしょうか？今回の記事では、コストパフォーマンスの観点から考えてみたいと思います

# 結論
RPCノードサービスの良いコストパフォーマンスは、以下の構成図のようになると考えています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3871132/a2c5012e-1b88-5fb3-9f34-ba859aa2e797.png)


# 解説
それぞれ詳細を説明していきます。

### 高い無料上限
高い上限の無料プランがあると、開発・テストの段階では上限内で収まることが多く、利用を有料プランに移行するまでの時間を延ばせるため、お金の節約につながります。

### 安いプラン料金
同じ利用量であれば、当然ながら安いプランの方が望ましいです。

### 高いレート制限
レート制限とは、一定のタイムフレーム内に最大で処理できるリクエスト数や負荷のことです。
高いレート制限を確保できると、アプリケーションのパフォーマンス向上につながります。

#
どのプロバイダーでも、上記の情報はプラン・料金ページに明記されているはずですので、利用する前に比較してみることをお勧めします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3871132/4b50e869-fa17-3ce0-d2e3-053d89a6a0c0.png)

# 参考
当社Cabinetが提供しているRPCノードサービスの料金体系については、以下のリンクをご参考ください。
https://cabinet-node.com/ja/plans-and-pricing
OpenSearch IngestionでネストされたJSONの中のフィールドを削除する方法

## 前置き
OpenSearch Ingestionは、OpenSearchドメインにデータを取り込む部分をマネージドで実施してくれる機能です。これを利用することで、Lambdaなど作成することなく取り込みが設定できます。また、コンピューティングは勝手にスケールしてくれます。

https://docs.aws.amazon.com/ja_jp/opensearch-service/latest/developerguide/ingestion.html

このIngestionですが、取り込む際の加工処理もProcessorを使って記載できます。

https://opensearch.org/docs/latest/data-prepper/pipelines/configuration/processors/processors/

このProcessorの中で、**delete_entries**というものがあります。これはフィールドを指定しておくことで取り込む際にそのフィールドを削除してくれます。公式ドキュメントにあるように、以下のように動作します。

- 設定値
```yaml
  processor:
    - delete_entries:
        with_keys: ["message"]
```

- 元データ
```yaml
{"message": "hello", "message2": "goodbye"}
```

- 処理後の取り込んだデータ
```yaml
{"message2": "goodbye"}
```

https://opensearch.org/docs/latest/data-prepper/pipelines/configuration/processors/delete-entries/

## 本題
**delete_entries**を使う際に、ネストされたJsonの中のフィールドを削除する際、普通にドットで指定するとうまくいきません。

- 上手くいかない例
```yaml
  processor:
    - delete_entries:
        with_keys: ["message.key1"]
```

以下のように、スラッシュで区切るとうまく削除されます。

- 上手くいく例
```yaml
  processor:
    - delete_entries:
        with_keys: ["message/key1"]
```
８．スプレッドシートの値をもとにGoogleFormの選択リスト値を自動的に更新する

# 今日の目標：スプレッドシートが更新されたが、GoogleFormの選択肢が自動で最新化されるようにする！

## 0．前回の振り返り
https://qiita.com/LoAMiat/items/6e883f12741be844d7f3

キーワード検索ができるようになりました。

## 1．スプレッドシートを準備する
今回はトライアルが決まっていない猫のみを抽出できるように、あらかじめQuery数式を書いたシートを準備しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782982/2fc437cd-8d6a-641a-422f-70b065d9b479.png)


## 2．GoogleFormを準備する
新規フォームを作成し、リスト項目・複数選択項目を用意します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782982/ca1fa40e-0eea-a05a-fbba-c0ab293a119d.png)

## 3．GASコードの準備
スプレッドシートからGASを作成し、下記コードを用意します。
```javascript: UpdateFormSelect.gs
function updateFormOptions() {
  // スプレッドシート情報取得
  const spreadSheetId = 'もとになるスプレッドシートID';
  let sheet = SpreadsheetApp.openById(spreadSheetId).getSheetByName('指定のシート名');

  // B列の2行目～最後まで猫名取得（行番号、列番号、範囲）
  let cats = sheet.getRange(2, 2, sheet.getLastRow() - 1).getValues();

  // 選択リスト、複数選択チェックボックスを更新
  const satooyaEntryId = '更新したいフォームID';
  setSelect(satooyaEntryId, cats);
  const eventReserveId = '更新したいフォームID';
  setSelect(eventReserveId, cats);
}

/**
 * Googleフォームのプルダウン内の値を上書きする
 **/
function setSelect(id, cats){
  let form = FormApp.openById(id);

  // 質問項目が選択リスト・複数選択チェックボックスのもののみ取得
  let listItems = form.getItems(FormApp.ItemType.LIST);
  let checkItems = form.getItems(FormApp.ItemType.CHECKBOX);

  listItems.forEach(function(item){
    // 質問項目が「お迎え希望の猫」を含むものに対して、スプレッドシートの内容を反映する
    if( item.getTitle().match(/お迎え希望の猫.*$/) ){
      let listOptions = item.asListItem();
      let choices = [];

      cats.forEach(function(name){
        if(name != ""){
          choices.push(listOptions.createChoice(name));
        }
      });

      // プルダウンの選択肢を上書きする
      listOptions.setChoices(choices);
    }
  });

  checkItems.forEach(function(item){
    // 質問項目が「面談ご希望の猫」を含むものに対して、スプレッドシートの内容を反映する
    if( item.getTitle().match(/面談ご希望の猫.*$/) ){
      let listOptions = item.asCheckboxItem();
      let choices = [];

      cats.forEach(function(name){
        if(name != ""){
          choices.push(listOptions.createChoice(name));
        }
      });

      // プルダウンの選択肢を上書きする
      listOptions.setChoices(choices);
    }
  });
}
```
今回は2つのフォームを更新したかったので、2回呼び出しています。

## 4．トリガーの設定
今回はデプロイを行いません。
コードを保存し、うまく実行できたらトリガーを設定します。
サイドメニューからトリガーを選択し、下記ような設定をすればもうすぐに動きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782982/fb44dba6-e1b6-fd57-1918-65a1962b05a3.png)

---
今日はここまで
nRFConnectSDKを基盤としたSesameの暗号通信 #10 Hello_tse without viscode

![sesame](https://scontent-nrt1-2.xx.fbcdn.net/v/t39.30808-6/459246707_10221395434475590_1638247866188116630_n.jpg?_nc_cat=100&ccb=1-7&_nc_sid=127cfc&_nc_ohc=MScOKHBj-DoQ7kNvgH7aT20&_nc_ht=scontent-nrt1-2.xx&oh=00_AYDQPP9xv6Rf9zx9UgQDKj0qJn_2l1C0DS8rWBVilEhe3w&oe=66E5AAC9)


# 目的
「Hello, World!」を再練習。

# 技術
- Hello World フォルダをコピーして新しいフォルダに貼り付けます
- コピーしたフォルダ内の CMakeLists.txt ファイルを編集します```set(BOARDnrf5340dk_nrf5340_cpuapp)```
- west build
- west flash

# 雑談
基礎練習を大量に行うことは、とても重要なステップです。やるべきプロジェクトが多すぎて、よく帰ってきたら組み込みシステムの書き方を忘れてしまいます。その時には、基礎練習で記憶を呼び戻す必要があります。
Google ビジネスプロフィール ID

Googleビジネスプロフィールについての個人的メモです。

## cid
Customer ID、顧客ID。
ビジネスプロフィール上の一意となる識別子。

## place id
プレイスID。
Googleマップ上の場所を表すID。
Googleは12ヶ月以上経ったプレイスIDは更新することをおすすめしており、変更される可能性のある識別子。

## Googleマップ上のプレイスIDを検索する

↓のサイトで住所を入力することでプレイスIDを取得できる。

https://developers.google.com/maps/documentation/places/web-service/place-id?hl=ja

![z.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1114606/e5bf657c-e71e-569a-a59d-e96fb69c8e37.png)

## cidからURLを取得する

以下の[XXX…]の部分にcidを設定する
https://maps.google.com/?cid=[XXXXXXXXXXXXXXXXX]
Azure ハイブリッド特典メモ 

Azure ハイブリッド特典 (Azure Hybrid Benefit) は、Microsoft Azure のクラウドサービスを利用する際に、既存のオンプレミスのライセンスを活用してコストを削減できるプログラムです。主な特徴は以下の通りです：

1. **既存のライセンスの活用**:
   - 既存の Windows Server または SQL Server のライセンスを持っている場合、Azure 上での仮想マシンやデータベースの料金を割引することができます。

2. **コスト削減**:
   - Azure ハイブリッド特典を利用することで、通常の料金よりも安価に Azure のリソースを利用できます。これにより、クラウド移行のコストを抑えることができます。

3. **ライセンスの持ち運び**:
   - オンプレミスのライセンスを Azure に持ち込むことで、既存のライセンスを再利用し、追加のコストなしでクラウド環境に移行できます。

4. **適用対象**:
   - 主に Windows Server や SQL Server のライセンスが対象となります。これには、Software Assurance（SA）が付いているライセンスが含まれます。

5. **利用方法**:
   - Azure ポータルで仮想マシンやデータベースを作成する際に、Azure ハイブリッド特典を適用するオプションを選択します。

この特典を活用することで、オンプレミスからクラウドへ移行する際のコストを削減し、効率的な運用が可能になります。
文系プログラマが簿記3級を2週間で合格した話

# 1. 簿記を取ろうと思ったきっかけ
以前かかわった基幹システムリプレースプロジェクトで、同然経理関係システムも移行対象だったのですが、当時の私は経理も簿記も何にもわからない！という知識量だったのでかなり用語に苦戦したことがありました。
そこからいつかは簿記を勉強しようと参考書だけ買って、はや数年。

転職にあたって、1カ月半の空白期間ができたのでその間に取得しようと腰を上げて合格してきました。

# 2. スケジュール
2024/8/23(Fri)：試験予約。勉強計画・開始。
2024/8/24~9/6：14日間がメインの勉強期間。一日3~4時間勉強し、中数日は丸っと勉強しない日あり。
2024/9/7(Sat)：受験

# 3. お世話になった教材
今回は[CPAラーニング](https://www.cpa-learning.com/home)をベースに学習していきました。
講義も教材も無料で利用できるなんて、なんて破格！講座もすべてわかりやすかったです。
- メイン
  - [日商簿記3級](https://www.cpa-learning.com/courses/90002)コース（全23講義、15時間51分）
  - 上記講座の教科書
  - 上記教科書に準ずる問題集
  - [日商簿記3級 ネット模擬試験](https://www.cpa-learning.com/courses/360011)
- 補助
  - [簿記3級ネット試験対策](https://www.cpa-learning.com/courses/420025)
  - [スマ簿記3級](https://sumaboki3.nayutari.com/)

# 4. 勉強計画、実際の進め方
基本的にはまず**講座を受講し、その日のうちに関連する問題集の基本編に取り組みました**。

講義の際にはPC上でPDFに直接マーカーしつつ、手書きでノートをとっていました。とにかく自分で仕訳・勘定・P/L、B/Sを書いて貸し借りを徹底して身に着けました。
また、普段電卓をたたいて計算することがほとんどないので、**電卓に慣れるためにも例題・練習問題で叩けるところはすべて叩きました**。（M+、M-は全く使いこなせてないです）

**勘定科目の暗記はほとんどしておらず**、学習を進めたり、問題を解くうちに自然と身につくものと、**試験問題の選択肢を見比べれば迷うことはほとんどありません**でした。

かなりぎりぎりの日程で、受験4日前の9/3にすべての受講が終わりました。
翌日以降は毎日1つずつ模試を受験し、**点数が低かったので第1問対策のみ、問題集の対策問題を解きました**。第2問・第3問の対策問題は解いても解説読んだりもしていません。

ネット対策講座は毎日の散歩のときと、当日試験会場までの間に聞いていました。心構えや解くときのコツがわかるのでラジオ的に使うのが私には向いてました。

勉強できない日なども、隙間時間にスマ簿記3級というアプリで、簡単な仕訳問題だけでも解いていました。
何か知識がつくというよりは、慣れのため＆安心のためです。

# 5. 模試の記録
- 2024/9/4 第1回模試：65/100点
  - 第1問：27/45点
  - 第2問：12/20点
  - 第3問：26/35点

合格点に達しなかったので、苦手だった勘定科目・仕訳をノートに再整理し、第1問のみ試験対策問題を問題集から取り組みました。
  
- 2024/9/5 第2回模試：88/100点
  - 第1問：45/45点
  - 第2問：18/20点
  - 第3問：25/35点

第3問の点数が低かったので、模試の問題自体を使って、再整理し解きなおしました。

- 2024/9/6 第3回模試：98/100点
  - 第1問：42/45点
  - 第2問：18/20点
  - 第3問：32/35点

おおむね満足が行ったので、翌日朝の試験に向けて早寝～

# 6. 受験結果
何とか合格してきました！割と健闘したほうではないでしょうか！
点数：94/100点
　第1問：45/45点
　第2問：18/20点
　第3問：31/35点
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782982/1a4cfb2f-63a7-4ff3-dd3d-c8dd2e232f69.png)

簿記関連の勉強は社会人10年目にして初めてしましたが、本当におすすめです。
単純に会社で働くことに対する解像度が高くなりますし、今後のシステム開発でも基礎になる知識を厚くすることができました。以前のシステムリプレースも今すれば、異なるデータモデルにしていると思います。

ーーー
今は継続して簿記2級の勉強を進めています。
勉強なさっている方、一緒に頑張りましょう！
Slackのスタンプを集計してサイネージに表示した話

## 概要
社内のSlackチャンネルからスタンプを集計して、オフィスフロアのモニターにサイネージとして表示してみました。

## きっかけ
弊社のブランディングのサービスの一つとして「社内エンゲージメント向上に作用するサイネージ」を作ろう！という思いがきっかけです。また、弊社ではいわゆる Jamstack と呼ばれるモダンな開発手法の導入をすすめており、その技術検証を行いたいという思いもありました。

## 仕組み
- Slackに投稿されたメッセージのリアクションで押されたスタンプを集計する
- 主にアクティブなチャンネル10個から集計する
- 毎日0時に、前日1日間に押されたスタンプを集計する
- 集計したスタンプをサイネージにワードバブルのように表示する

## 実際にできたもの
![tech_blog1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704872/a32f94ec-bc34-69d1-5fe3-812af54265e3.png)

![tech_blog2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/704872/061fa35a-75ae-ca0b-439c-78235a3871a2.jpeg)



## 実装方法
### バックエンド
#### Strapi
オープンソースのヘッドレスCMS。今回はデータベースとして、集計したスタンプのデータをStrapiに保存します。Amazon Lightsailにセルフホスティングしています。

#### n8n
こちらもオープンソースの自動化ツール。毎日決まった時間にSlackからスタンプを抽出し、Strapiに保存する役割を担っています。こちらもAmazon Lightsailにセルフホスティングしています。n8nをセルフホスティングした詳しい話はこちらの記事にまとめています。

https://qiita.com/NKM_DAS_IS/items/3853c96f1cb460757eda

### フロントエンド
#### Astro.js
Strapiから集計データを取得し、サイネージに表示するHTMLを生成するフレームワークとして、Astro.jsを使用しています。いわゆる Jamstack 構成で、毎日決まった時間に集計結果を反映した静的なHTMLが自動的に生成され、表示されるようにしています。デプロイ先には AWS Amplify もしくは Vercel を使うことが多いです。

#### d3.js
スタンプの画像をワードバブルのように表示するために使用しているデータビジュアライザーションライブラリです。
d3.jsの中の`circle`や`circle packing`という機能を使用しました。

【参考】

https://old-pine.net/html/d3js%E3%81%A7%E7%B0%A1%E5%8D%98%E3%81%AA%E3%83%90%E3%83%96%E3%83%AB%E3%83%81%E3%83%A3%E3%83%BC%E3%83%88%EF%BC%88bubble-chart%EF%BC%89%E3%81%AE%E4%BD%9C%E6%88%90

## まとめ
今回は、社内のSlackチャンネルからスタンプを集計して、オフィスフロアのモニターにサイネージとして表示してみた話を紹介しました。
ぜひ参考になれれば幸いです。
SqlAlchemyテーブル定義を書く時に配列(ARRAY)を格納するカラムがある場合の書き方

## 配列を格納するカラムのテーブル定義を書く方法の例

忘れない様にメモ

「test_tags」のカラムが配列を格納する書き方になっています。

```
from sqlalchemy import ARRAY, TIMESTAMP, Boolean, Column, Integer, String, text
from sqlalchemy.sql import func
from ..settings.db import Base

class TestTableModel(Base):
    """テスト用テーブルのモデルクラス"""

    __tablename__ = "test_table"

    id = Column(Integer, nullable=False, primary_key=True)
    test_name = Column(String(256), nullable=False)
    test_tags = Column(ARRAY(String(256)), nullable=False)
    test_judge = Column(Boolean, nullable=False)
    delete_flag = Column(
        Boolean,
        nullable=False,
        server_default=text(false),
        index=True,
    )
    create_datetime = Column(
        TIMESTAMP, nullable=False, server_default=func.current_timestamp(), index=True
    )
    update_datetime = Column(
        TIMESTAMP,
        nullable=False,
        server_default=func.current_timestamp(),
        index=True,
    )
```
jspをthymeleafに

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title>登录</title>
    <link href="@{/css/login.css}" rel="stylesheet" type="text/css"/>
    <script type="text/javascript">
        function promptChangePass() {
            // 这里是你的 JavaScript 逻辑
            if (/* 你的条件 */) {
                window.location.href = "/changePassword/index";
            } else {
                window.location.href = "/menu/index";
            }
        }
    </script>
</head>
<body onload="promptChangePass()">
    <div id="logo">
        <table>
            <tr>
                <td>
                    <img th:src="@{/img/logo.gif}" alt="SB Payment Service" width="306px" height="31px"/>
                </td>
            </tr>
        </table>
    </div>

    <div id="main">
        <div id="contents">
            <h1>ログインページタイトル</h1>
            <div class="error-message" th:if="${not #lists.isEmpty(errors)}">
                <font color="red" th:text="${errors}"></font>
            </div>
            <form th:action="@{/login}" method="post" onsubmit="return clickSubmit()">
                <table align="center">
                    <tr>
                        <td>ログインID</td>
                        <td>
                            <input type="text" id="id" name="id" maxlength="20" size="22" style="ime-mode: disabled;"/>
                        </td>
                    </tr>
                    <tr>
                        <td>パスワード</td>
                        <td>
                            <input type="password" id="password" name="password" maxlength="20" size="20" style="ime-mode: disabled;"/>
                        </td>
                    </tr>
                </table>
                <br/>
                <input type="submit" name="login" value="ログイン" onclick="clientValidate=true"/>
                <input type="reset" value="クリア"/>
            </form>
            <div class="error-message" th:if="${message}">
                <font color="red" th:text="${message}"></font>
            </div>
        </div>
    </div>

    <div id="footer">
        <!-- フッター内容 -->
    </div>
</body>
</html>