OmniAICreator/Qiita-1.07M huggingface dataset:
WSL 環境構築

WSL は Windows 上で Linux ベースのツールやアプリケーションの開発、パッケージ管理システム (apt, yum など) を利用する必要がある場合に便利であるため、WSL インストールして VSCode から接続するまでの環境構築メモを残しておきます。

## 事前にやっておくこと
- Linux 用 Windows サブシステム 機能の有効化
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397664/a6178454-8e02-8fbc-e113-1046bd37c9c5.png)
- Windows 再起動
- 以下のコマンドをPoserShellで実行（0x800701bcのエラーコードが出る場合の対策）
```
wsl --update
```

## WSL インストール
- コマンド プロンプトを管理者モードで開く
- 使用可能なディストリビューションを一覧表示 
```
wsl.exe --list --online
```

- wsl インストール
```
wsl --install -d <DistributionName>

例）
wsl --install -d Ubuntu-24.04
```

- OS 再起動

- インストールされているディストリビューションを一覧表示
```
wsl --list --verbose
```

- インストール済のディストリビューションを起動
```
wsl -d <DistributionName>
```

- 実行している WSL のバージョンを確認
```
wsl -l -v
```

## VSCode で WSL 接続
- VSCode 拡張機能の [Visual Studio Code WSL](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl) インストール
- スタート画面等から WSL を起動
![スクリーンショット 2024-05-25 222746.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397664/7e6147c6-33e8-c5e2-2eaa-4a1c63dc91ef.png)

- パスワード設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397664/157291f6-cb8c-4552-8c7b-f7267f9c0420.png)

- WSL から VSCode を起動
```
cd <該当ディレクトリ>
code .
```
![スクリーンショット 2024-05-25 230050.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397664/9033e602-c246-4733-2e46-86f7b57b2248.png)

- もし「WSL から VSCode を起動」がうまくいかなかった場合、VSCode から WSL 接続
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397664/277b8c5b-bd41-60db-c1ba-2476c287f21a.png)
- VSCode の画面が以下のようになっていたら成功
![スクリーンショット 2024-05-25 230258.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397664/ad0a86f3-7f9d-350b-8ce4-bd7e6df8939a.png)


参考）
https://learn.microsoft.com/ja-jp/windows/wsl/install
https://learn.microsoft.com/ja-jp/windows/wsl/basic-commands
https://www.tohoho-web.com/ex/wsl.html
https://leokun0210.hatenablog.com/entry/2021/09/29/WSL2%E3%81%A7Ubuntu%E3%82%92%E7%AB%8B%E3%81%A1%E4%B8%8A%E3%81%92%E3%81%9F%E3%82%890x800701bc%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%8C%E5%87%BA%E3%81%9F%E3%80%82
Excelワークシート関数: 正規表現を扱う新しい関数、既存関数の新機能

2024年5月25日

Excel では VBA でなくワークシート関数で、まもなく正規表現関係の新しい関数が使えるようになるという発表が2024年5月21日付でありました。

技術者だけのものだった正規表現が、ついに、営業でも人事でも経理でも法務でも秘書でも、Excel を使える人なら誰でも特別な設定することなく使える環境になるのです。人類が月に降り立ったときにように画期的なことです！

https://insider.microsoft365.com/en-us/blog/new-regular-expression-regex-functions-in-excel

新しい3つの関数が導入されるようです。

* <a href="https://support.microsoft.com/ja-jp/office/regextest-function-7d38200b-5e5c-4196-b4e6-9bff73afbd31" target="_blank"><code>REGEXTEST</code></a> &mdash; パターンに整合するかどうかを検査する関数
* <a href="https://support.microsoft.com/ja-jp/office/regexextract-function-4b96c140-9205-4b6e-9fbe-6aa9e783ff57" target="_blank"><code>REGEXEXTRACT</code></a> &mdash; パターンに整合する部分を抽出する関数
* <a href="https://support.microsoft.com/ja-jp/office/regexreplace-function-9c030bb2-5e47-4efc-bad5-4582d7100897" target="_blank"><code>REGEXREPLACE</code></a> &mdash; パターンに整合する部分を別の文字列で置き換えた文字列を返す関数

また、既存の <code>XLOOKUP</code> と <code>XMATCH</code> でもパターン整合に正規表現が使えるようになるとのことです。

``REGEXTEST`` の解説記事によれば、使える正規表現は「PCRE2風」だとのことで、近い将来、強力で快適な正規表現生活が待っているようです。
Slackのワークスペースに参加したユーザーにGoogle Driveの権限を渡す方法

# はじめに
「仲間内で開発とかしていきたいなっ！」と思ったので、slack、google drive、gitlabなどを準備して招待を送ろうと思ったのですが、ポチポチして招待送るの面倒だなと思いました。
そこで「GASとslackを使って権限や招待の自動化をしよう！」ってことで実装しました。
※ただ、gitlabのapiは有料プランでしか使えず断念しました。(有料に切り替えたらやるぞ！)


# 実装
まずはコード全体

~~~javascript:権限を自動付与するスクリプト
function doPost(event) {

  const params = JSON.parse(event.postData.getDataAsString());
  if(params.challenge) {
    return ContentService.createTextOutput(params.challenge); 
  };
  
  const email = params.event.user.profile.email; // eventパラメータからメールアドレスを取得
  shareFolder(email);

}

/*
  ユーザーに指定のフォルダの権限を上げる関数
*/
function shareFolder(email) {

  const folderId = "権限を上げたいフォルダ"; // フォルダのID
  const folder = DriveApp.getFolderById(folderId);
  
  folder.addEditor(email);

};
~~~

メインのdoPost関数でユーザーがワークスペースに参加したときのeventパラメータを取得しています。
その中からemailを取り出しています。
shareFolder関数ではまず、`DriveApp.getFolderById(folderId)`でどのフォルダを操作するかを指定しインスタンスを作ります。
そして、`folder.addEditor(email)` addEditorメソッドを作成して、指定のemailに編集権限を渡します。閲覧やオーナー権限なども渡すことができます！

# さいごに

このような面倒だなって作業を自動化したりや、データ活用の分野のお手伝いを個人で承っております。ご興味ある方はご連絡ください！
ABC355をPythonで（A～D）

東京海上日動プログラミングコンテスト2024（AtCoder Beginner Contest 355）の解答等のまとめ

https://atcoder.jp/contests/abc355

# A問題
https://atcoder.jp/contests/abc355/tasks/abc355_a

問題文通りに書く
```python:A
s = {1, 2, 3} - set(map(int, input().split()))
if len(s) == 1:
    ans = s.pop()
    print(ans)
else:
    print(-1)
```

# B問題
https://atcoder.jp/contests/abc355/tasks/abc355_b

AとBをソートして下から順番に見ていく
$a_i$と$a_{i+1}$の間に入る$b_j$が見つからなかったらYes
```python:B
n, m = map(int, input().split())
a = sorted(map(int, input().split()))
b = sorted(map(int, input().split()))

flag = False
i, j = 0, 0
while i < n and j < m:
    if i + 1 < n and a[i + 1] < b[j]:
        flag = True
    if a[i] < b[j]:
        i += 1
    else:
        j += 1

if flag or i + 1 < n:
    print("Yes")
else:
    print("No")
```

# C問題
https://atcoder.jp/contests/abc355/tasks/abc355_c

縦横斜めでいくつ出たか数えて、$n$個出たらそれが何回目か答える
```python:C
n, t = map(int, input().split())

cross = [set(), set()]
for i in range(n):
    cross[0].add(n * i + i)
    cross[1].add(n * (i + 1) - i - 1)

h = [0] * n
w = [0] * n
c = [0] * n

for i, a_i in enumerate(map(lambda x: int(x) - 1, input().split()), 1):
    h[a_i // n] += 1
    w[a_i % n] += 1
    if a_i in cross[0]:
        c[0] += 1
    if a_i in cross[1]:
        c[1] += 1
    # print(h[a_i // n], w[a_i % n], c[0], c[1])
    if max(h[a_i // n], w[a_i % n], c[0], c[1]) == n:
        exit(print(i))

print(-1)
```

# D問題
https://atcoder.jp/contests/abc355/tasks/abc355_d

1. $l$でソートする
1. $i$回目で$l_i$以上の$r$がそれまでにいくつ出たか数える

2.を効率よく行うためにheapqを使って
1. heapqの中にある$l_i$未満の値を取り出す
2. heapqの個数を答えに足す
3. heapqに$r_i$を加える
とすればheapqの挿入・取り出し回数が最大$n$回になるから間に合う

```python:D
from heapq import heappop, heappush

n = int(input())
lst = [tuple(map(int, input().split())) for _ in range(n)]

lst.sort()
q = []
ans = 0
for l_i, r_i in lst:
    while q and q[0] < l_i:
        heappop(q)
    ans += len(q)
    heappush(q, r_i)

print(ans)

```
【TryHackMe】DNS in detail：Walkthrough

# 概要

TryHackMe「DNS in detail」のWalkthroughです。

https://tryhackme.com/r/room/dnsindetail

# Task1

## **Q**.*What does DNS stand for?*

**A**.**Domain Name System**

# Task2

## **Q1**.*What is the maximum length of a subdomain?*

**Hint**.*Remember: A subdomain name has the same creation restrictions as a Second-Level Domain.*

**A**.**63**

## **Q2**.*Which of the following characters cannot be used in a subdomain ( 3 b _ - )?*

**A**.**_**

## **Q3**.*What is the maximum length of a domain name?*

**A**.**253**

## **Q4**.*What type of TLD is .co.uk?*

**A**.**ccTLD**

# Task3

## **Q1**.*What type of record would be used to advise where to send email?*

**A**.**MX**

## **Q2**.*What type of record handles IPv6 addresses?*

**A**.**AAAA**

# Task4

## **Q1**.*What field specifies how long a DNS record should be cached for?*

**A**.**TTL**

## **Q2**.*What type of DNS Server is usually provided by your ISP?*

**A**.**recursive**

## **Q3**.*What type of server holds all the records for a domain?*

**A**.**authoritative**

# Task5

右上の`Viwe Site`を開くと`nslookup`を疑似的に実行できるアプリケーションがあります。

![task5 q1 home.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/70b6437d-9e5b-ce51-27d5-d61c0be31a3a.png)

## **Q1**.*What is the CNAME of shop.website.thm?*

`DNS Type`を`CNAME`に`subdomain`をshopに指定して実行します。

![task5 q1 get answer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/0c0985de-ce06-4365-b697-e46734314ec8.png)

`CNAME`レコードに`shops.myshopify.com`が設定されていることが分かりました。

**A**.**shops.myshopify.com**

## **Q2**.*What is the value of the TXT record of website.thm?*

**Hint**.*No subdomain is needed in the terminal.*

`DNS Type`を`TXT`に設定し、実行するとフラグゲットです。

![task5 q2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/431a9566-f60a-dd8d-d164-eecc856df748.png)

**A**.**THM{7012BBA60997F35A9516C2E16D2944FF}**

## **Q3**.*What is the numerical priority value for the MX record?*

`DNS Type`を`MX`に設定し実行すると優先順位が`30`に設定されているのを確認できました。

![task5 q3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/bc8ee3bb-e6c0-eca4-ed5e-b2d500370ab5.png)

**A**.**30**

## **Q4**.*What is the IP address for the A record of `www.website.thm`?*

`DNS Type`を`A`に、`subdomain`に`www`を設定し実行すると`www.website.thm`のIPアドレスが確認できました。

![task5 q4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/0803ff85-3d08-d385-ee21-8c45780fce4c.png)

**A**.**10.10.10.10**
第３級アマチュア無線技士のススメ（合格体験記も兼ねて）

# はじめに

第三級アマチュア無線技士を取得したので、合格体験記的な意味合いも兼ねて投稿いたします。

# Who am i ?

しがないエンジニア（IT関係）です。仕事では無線従事者資格に関わる業務については関わったことがなく初心者です。

# この記事の想定読者

 - 4アマ取得後に3アマの取得を検討されている方
 - その他 

# 動機

FPVドローンにもともと興味があり4アマを取得しました。ただFPVドローンとは今のところ関係ありませんが、一般の無線機について出力が4アマの範囲の無線機では物足りなさを感じることが多いという記事を拝見したため、上位資格の3アマを取得しました。一般的に3アマはアマチュア無線技士の資格の中で最もコスパが良いという意見が多いです。そのため取得しておいて損はないかなと思っておりました。

4アマについてはこちらでも触れていますので、ご興味ある方は↓をご参照ください。

https://qiita.com/forest_moririri/items/e53fe4fc8e0635969a6b

あとは純粋に仕事で無線を使う機会がないため、趣味でやってみたかったんですよね。アマチュア無線は他の無線従事者免許と違い、業務で使用することはできませんが、それ以外の制約条件を除くとかなり幅広く使える資格だと思っております。個人的にはモールス符号も運用で使えるようになっておきたいです！

3アマは、つむぎさんという方が目指しているそうです。ご参考。

https://www.youtube.com/watch?v=tMoDOVRg1xw&list=RDCMUChf2vWqVItUDRqenP16Zz0w&start_radio=1&rv=tMoDOVRg1xw&t=1121

https://www.youtube.com/watch?v=qGUlMgKwpCE&t=9s

# 3アマの勉強と講習会の様子について（ご参考）

私はJARDの講習会で取得しました。JARD講習会では短縮コースと標準コースがあるのですが、短縮コースの方を選択しました。予習は4アマと同じくかんまるくんを勉強したことに加えてモールス符号の読み込みをしました。講習会の年齢層は幅広く小学生から70歳くらいの方まで幅広くという感じでしたね。


# 最後に

移動局では空中線電力50Wが最大ですので、1アマや2アマでも固定運用を想定していなければ3アマの運用とそれ程の大差はないはずということと、3アマの試験は4アマの内容に近しいところが多いので、全体的にコスパが良いのだと思います。無線機についてもより高性能な無線機を視野にいれることができるのでテンションが上がりますね！この記事が３アマ合格のためにお役に立つことができれば幸甚です。
ドドドドド初心者がPythonでTodoリスト作ってみた

みなさん、はじめまして。
今回はドドドドド初心者がpythonで、Todoリストを作ってみました。
こちらです！

```py
Todo = ['day', 'time', 'do', 'delete', 'end']
list = []
while not Todo[4] == "2":
    Todo[0] = input("日付を入力してください\n")
    Todo[1] = input("時間を入力してください\n")
    Todo[2] = input("やることを入力してください\n")
    print(f'{Todo[0]}   {Todo[1]}\n'
          f'{Todo[2]}')
    list.append(f'{Todo[0]} {Todo[1]}\n{Todo[2]}\n')
    while not Todo[4] == 2:
        Todo[4] = input('続けますか？(続ける場合は1を入力、終了の場合は2を入力してください。\n'
                        'また、修正したい場合は、3を入力してください)')
        if Todo[4] == '1':
            break
        if Todo[4] == '2':
            break
        elif Todo[4] == '3':
            Todo[3] = int(input('修正したい項目を1~3で入力してください。\n'
                    '1:日付\n'
                    '2:時間\n'
                    '3:やること\n'))
            while Todo[3] == 1 or 2 or 3:
                if Todo[3] == 1:
                    Todo[0] = input('日付を入力してください。')
                    break
                elif Todo[3] == 2:
                    Todo[1] = input("時間を入力してください\n")
                    break
                elif Todo[3] == 3:
                    Todo[2] = input("やることを入力してください\n")
                    break
                else:
                    print('不適切な値です。もう一度選択してください')
                    break
            list.pop(-1)
            list.append(f'{Todo[0]} {Todo[1]}\n{Todo[2]}\n')
            pass
        continue
    if Todo[4] == '1':
        continue
    if Todo[4] == '2':
        for todolist in list:
            print(todolist)
        break

```

もっと知識があれば簡略化できると思うのですが、まだ知識全然ないので有能な兄貴姉貴、アドバイスお願いします！！
[Vue3]Supabaseで作ったバックエンドを元にOpenAPIのドキュメントを出力しよう

個人プロジェクトでバックエンドとしてSupabaseを使っている。
SupabaseだとUIをぽちぽちするだけでバックエンドが完成。とても便利だ。
フロントエンドに集中した開発ができる。

今回はSupabaseで設定したバックエンド情報を元にTanStack Queryのエンドポイントメソッドを自動生成してみようと思う。しかし、OpenAPIのドキュメントをいちいち書くのがめんどくさいのでSupabaseさんに生成してもらいたい。

## OpenAPIドキュメント生成
公式ドキュメントやGoogleドキュメントで調べてみてもやり方が見つからず、、
ChatGPT先生に聞いてみた。

>Supabaseは、自動生成されたAPIドキュメントを提供しています。これを取得するには、以下のURLにアクセスします。
```https://YOUR_PROJECT_ID.supabase.co/rest/v1/?apikey=YOUR_ANON_KEY```

これが出ていると言うことは、きっと公式ドキュメントのどこかに書いてそう。

`YOUR_PROJECT_ID`と`YOUR_ANON_KEY`を探しに行く。
メニューから`Project Settings`に入る。

![スクリーンショット 2024-05-25 22.07.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/a244ed7b-4a0c-16f0-e770-d3a30576efec.png)

`General`の`Reference ID`が`YOUR_PROJECT_ID`に該当する。

![スクリーンショット 2024-05-25 22.07.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/53d9c1ec-35ee-9e55-a2cc-2fa42c6528a4.png)

`API`に入ると`YOUR_ANON_KEY`も確認できる。

![スクリーンショット 2024-05-25 22.08.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/4cff8eaf-3005-fd80-bf56-40ac4a489ad3.png)

## 結果

ちゃんとしたものが返ってきた！内容見た限り問題なさそう。

![スクリーンショット 2024-05-25 22.13.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/2071dc77-87f8-956e-c979-b12f0ad8451d.png)

しかし、swaggerのバージョンが`2.0`のため、`3.0`に変換したい。

https://converter.swagger.io/

変換してくれるサイトがあったので使ってみた。
URLを入れると...

見慣れたSwagger UIの画面が出てきた！(エンドポイントのパラメータが表示されないのが少し気になる)
![スクリーンショット 2024-05-25 22.28.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/4940264c-beac-23b0-d2fa-82a285834662.png)

あとはOrvalで自動生成するだけ。

https://zenn.dev/hrbrain/articles/3ca5d37dd0b80e
誰も教えてくれないメダリオンアーキテクチャの デザインメソッド：JEDA データエンジニア分科会 #1

## 概要

JEDA データエンジニア分科会 #1 集まれデータエンジニア！というイベントにて、誰も教えてくれないメダリオンアーキテクチャの デザインメソッドというタイトルで発表をしたため、その内容を整理します。あまりイベントで発表することはないため、Speake Deck やドクセルなどの利用に少し苦戦しました。

https://jedai.connpass.com/event/316240/

## 発表内容

### 発表資料

<script async class="docswell-embed" src="https://www.docswell.com/assets/libs/docswell-embed/docswell-embed.min.js" data-src="https://www.docswell.com/slide/5ENP4E/embed" data-aspect="0.5625"></script><div class="docswell-link"><a href="https://www.docswell.com/s/manabian/5ENP4E-2024-05-24-152846">誰も教えてくれない メダリオンアーキテクチャの デザインメソッド by @manabian</a></div>

#### 発表概要

レイクハウスを実装する際のデータアーキテクチャとして、下記図のように構築することがおすすめですという話をしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/bc6451e6-eac4-5f21-624c-09abb251b605.png)

そのアーキテクチャをベースとして、下記図のように Databricks で開発を実施しています。処理の共通化を図り、データエンジニアリングの開発者に対する要件技術要件を下げることで開発生産性向上を実施しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c0ab9160-8940-3ee3-6558-22795b6173bd.png)


### 関連情報

#### データ分析基盤について

下記のようなデータ分析基盤を前提としています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/30c7d120-d36a-e716-a6f9-e0fa7996ace7.png)

引用元：[最強のデータ分析基盤を目指して～汎用的なデータ分析基盤の選定方法の提案～ #AWS - Qiita](https://qiita.com/manabian/items/e689daf5cc006eced737)

#### データアーキテクチャ

下記図のレイヤー詳細項目を組み合わせました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/5d2ef4c6-8fab-2ecc-ac91-ff73fb6bc06a.png)

引用元： [Databricks ( Spark ) における Spark テーブル（データレイク）のディレクトリ構成の検討 #Python - Qiita](https://qiita.com/manabian/items/599f821a1afaae6a3f41)

#### データエンジニアリングパイプラインの実装方法

パイプラインを実装する際には下記のように実装しています。

- [Bronze テーブルから Silver テーブルへのデータローディングパターン #SQL - Qiita](https://qiita.com/manabian/items/611997aeb01f15776bbe)
- [Silver テーブルへ差分連携する際の Bronze テーブルからデータを抽出方法の注意事項 #SQL - Qiita](https://qiita.com/manabian/items/e8157f4fb5a1e3f92695)


#### テストの実施方法

pytest にてパイプラインで利用しているテーブルなどを作成後に`dbutils.notebook.run`によりパイプラインのノートブックを実行し、実行結果の確認を実施しています。

- [Databricks Workspace 上で pytest によるテストケース作成とテスト実行を行う方法 #Python - Qiita](https://qiita.com/manabian/items/c31a6498b2db1b78ac1b)
【JavaScript】兄弟要素を取得する方法

## 直前の要素を取得する

`previousElementSibling`を使用するとその要素の直前の兄弟要素を取得できます。

```js
const previousSibling = elem.previousElementSibling;
console.log("prevSibling", previousSibling);

```

https://developer.mozilla.org/ja/docs/Web/API/Element/previousElementSibling



## 直後の要素を取得する

`nextElementSibling`を使用するとその要素の直後の兄弟要素を取得できます。

```js
const nextSibling = base.nextElementSibling;
console.log("nextSibling", nextSibling);

```

https://developer.mozilla.org/ja/docs/Web/API/Element/nextElementSibling
4・大当選

今日は一日免許スクールが行っている祭りイベントにてパンフレットを配るバイトに行ってきました。
その中のオオトリであるくじ引きにて一番の賞を引き当てました。
神は私を愛しすぎてる。
明日は一日フリーなので本腰を入れる。
iPhoneでホーム画面からApp Storeを誤って削除してしまった時の復活方法

ぜんぜん本件に関する記事がなかったのでメモ的にここに記録します。

- ホーム画面で一番右まで、アプリライブラリの画面まで移動します。(ホーム画面で右から左に何度もスワイプします。)
- アプリライブラリの画面でApp Storeを検索します。
- App Storeのアイコンを長押しするとホーム画面に追加することができます。
【BizRobo!・DA】古いサイト/アプリを操作する方法【RPA】

## はじめに
官公庁、金融業界、大企業などは昔ながらのサイトやシステム（JavaScriptなどで作成されているもの）を使用している事が多いと思います。

そのようなサイト・システムを **BizRobo!** のDAを用いて操作する時、普通にロボットを作成していっても、サイト・システムの要素が取れずに操作ができない場合があります。

今回は、上記のような場合に活用できる方法を記載していきます。

２つの方法があるので、１つ目を試してみて改善が見られない場合は２つ目を試してください。

## 方法１
１．DAのエディター画面を開く

２．画面左にある「TreeModes」を開く

３．TreeModeで「Windows」を選択する

４．チェックを全て外し、「Legacy Depth+Index」にだけチェックを入れる

## 方法２
１．DAのエディター画面を開く

２．画面左にある「TreeModes」を開く

３．TreeModeで「ISA」を選択する

ISAに関しては公式ナレッジに詳しい解説がありますので、併せてご参照ください。

https://knowledge.bizrobo.com/hc/ja/articles/360028154751-ISA-Intelligent-Screen-Automation-%E3%81%AE%E8%AA%AC%E6%98%8E
【バッチ】大量のテキストファイルに行番号を挿入したい

## やりたいこと

- テキストファイルの各行に、行番号を挿入したい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/c5f75acf-2f6c-a3ca-15d9-bf5e69b8bf95.png)

## 前提条件

- Windows環境とする
- なるべく単純な方法で実現したい
- テキストファイルは大量にあり、なるべく短時間で処理したい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/7e420aad-b40c-c0ff-8c99-d4402b94c2e2.png)

## 方法①：Windowsコマンドを使用する方法

`findstr`コマンドの`\n`オプションが、行番号を追加する機能であることを利用したもの
これに`for`コマンドを組合わせることで、大量のテキストファイルを処理する

### Windowsコマンド

同じファイルに上書き保存する方法が分からなかったので、元のファイル名に「_」を付けたファイルに出力しています。

　元のファイル名　　　：C:\work\files\filename.txt
　出力されるファイル名：C:\work\files\\_filename.txt

``` sh
for /r %i in (*.*) do (findstr /n /r .* %~fi > %~pi_%~ni%~xi)
```

- `for`コマンド
    - `/r`オプション：サブディレクトリを再帰処理する
- `findstr`コマンド
    - `/n`オプション：行番号を追加する
        - ※参考：`find`コマンドにも同様のオプションがある
    - `/r`オプション：正規表現を使用する
    - その他（オプション構文）
        - %~fi：フルパスを意味する
        - %~ni：ファイル名を意味する
        - %~xi：拡張子を意味する

> - **補足**
>     - 本コマンドをバッチファイルとして実行する場合、変数名の`%`を1つ増やして、`%%i`にする必要があります

## 方法②：サクラエディタとWindowsコマンドを組合わせたもの

サクラエディタの機能「選択範囲内全行行番号付きコピー Ctrl+:」を利用したもの
これにWindowsコマンドを組合わせることで、大量のテキストファイルを処理する

### サクラエディタのマクロ

1つのテキストファイルに、行番号を入れるマクロです。
キーマクロの記録で生成したコードを一部修正して作成しました。
引数`(0)`が多いですが、決まり文句みたいなものらしいです。

``` c
//ファイル名：addLineNum.mac

S_SelectAll(0);					// すべて選択
S_CopyLinesWithLineNumber(0);	// 選択範囲内全行行番号付きコピー
S_Paste(0);						// 貼り付け
S_ReDraw(0);					// 再描画
FileSave();						// 上書き保存
WinClose();						// 閉じる
```

### Windowsコマンド

サクラエディタのマクロを、大量のファイルに再帰的に実行するためのものです。
各パスは実行環境に合わせて修正が必要です。

``` sh
cd C:\work\files
for /r %%i in (*.*) do (call :method %%i)
exit
:method
"C:\Program Files (x86)\sakura\sakura.exe" %1 -M=C:\work\addLineNum.mac
goto :eof
```

## 引用元

- [サクラエディタのマクロをバッチファイルで複数ファイルに対して実行](<https://cyzennt.co.jp/blog/2019/04/13/%E3%82%B5%E3%82%AF%E3%83%A9%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%81%AE%E3%83%9E%E3%82%AF%E3%83%AD%E3%82%92%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%A7%E8%A4%87%E6%95%B0/>)
- [Windowsコマンド虎の巻](<https://windows.command-ref.com/>)
TypeScript勉強してみた③

# はじめに
初めまして！
エンジニアになって数年、今まで本を読むだけでしたが、もっとプライベートで楽しみながら成長したい！自分が学んだ足跡を残していきたい！と思い記事を書きました！
最終的には自在に開発できるようになりたいと思っています。:triumph:
いろいろな記事を参考にさせてもらっています。:bow_tone2:

**「いいね」か「ブックマーク」**
を頂けると僕のモチベーションアップになります！:thumbsup:
少しでも気に入っていただけたらよろしくお願いいたします！:thumbsup:


# 今回の目的
TypeScriptがわからなくてやばたにえんなので、ハンドブックで学んでみました。
（前回）

https://qiita.com/mr_noppo/items/1df10dd7a68d403427ba

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

https://www.typescriptlang.org/docs/handbook/intro.html

### コンパイラ
前回の例ですが、エラーを出しているファイルがあってもコンパイルは実行されているので注意
TypeScriptでエラーがある時にコンパイラが動作しないようにするには下記のオプションをつける
```ts
tsc --noEmitOnError hello.ts
```
### 明示的な型宣言
誤った引数の型が来ないように定義できる。
```ts
function greet(person: string, date: Date) {
  console.log(`Hello ${person}, today is ${date.toDateString()}!`);
}
```
コンパイルするとこんな感じ
```js
function greet(person, date) {
    console.log("Hello ".concat(person, ", today is ").concat(date.toDateString(), "!"));
}
```

型が推測できる場合は省略可能されます。型を定義しなくてもエラーが出ない時は推論で解決されている。
```ts
const msg = "hello";
```

# Everyday Types
非同期処理はpromiseを返します。
```ts
async function getFavoriteNumber(): Promise<number> {
  return 26;
}
```
※promiseは、promiseオブジェクトを返し、結果が取得出来次第格納します。同期処理後に結果が返ってくることも特徴。
```ts
async function getFavoriteNumber(): Promise<number> {
  return 26;
}
// Promise: {} 
let test = getFavoriteNumber()
// 同期処理後にPromiseが返されるため遅れて実行される。
test.then((number) => {
    console.log('a')
})
```

### Optional Properties
?を使うと存在しない可能性のある変数も記述できます
```ts
function printName(obj: { first: string; last?: string }) {
```
ただし、?がついた変数についてはundefinedの可能性があるため事前の検証が必要になります。
```ts
if (obj.last !== undefined) {
```

### Union Types
Stringでしか扱えないメソッドを使うとエラーが発生する。
```ts
// Property 'toUpperCase' does not exist on type 'string | number'.
function printId(id: number | string) {
  console.log(id.toUpperCase());
}
```
toUpperCaseに限らずメソッドの説明を読んで型を確認すること
```
(method) String.toUpperCase(): string
```


解決策は、typeOfで判定すること。（配列の場合はisArray)
```ts
function printId(id: number | string) {
 if (typeof id === "string") {
    console.log(id.toUpperCase());
  }
}
```

### typeとinterfaceの違い
interfaceは宣言後も新しいフィールドを追加できます。(typeの方が宣言で把握できるからいいかも）
```ts
interface Animal {
  name: string;
}

interface Animal {
  honey: boolean;
}

const bear:Animal = {name:"kuma", honey:true};
bear.name;
bear.honey;
```

# 次回の予定
型アサーションから
Expoでreact-native-firebaseを使う

## はじめに

[Expo](https://expo.dev/)を使ったアプリ開発で[firebase-js-sdk](https://www.npmjs.com/package/firebase)を使っていたのですが、[Crashlytics](https://firebase.google.com/docs/crashlytics?hl=ja)やその他機能を利用できるように[react-native-firebase](https://rnfirebase.io/)に乗り換えました。今回のようにExpoでネイティブコードに依存するライブラリを使う場合、[Expo prebuild](https://docs.expo.dev/workflow/prebuild/)や[EAS build](https://docs.expo.dev/build/introduction/)を使うことでExpoをejectすることなく、問題なく動作確認しながら進めることができます(執筆時に使っていたExpoのバージョンは`v50.0.8`）。

## 必要なライブラリのインストール

必要な`react-native-firebase`ライブラリを一通りインストール。
```bash
npx expo install @react-native-firebase/app @react-native-firebase/auth @react-native-firebase/firestore @react-native-firebase/crashlytics
```

iOSの設定向けに[expo-build-properties](https://docs.expo.dev/versions/latest/sdk/build-properties/)をインストールする必要があります。
```bash
npx expo install expo-build-properties
```

## 設定ファイルまわり

### Googleログインの有効化

FirebaseのプロジェクトでGoogleログインを有効化していないと、後述の`GoogleService-Info.plist`ダウンロード時に`CLIENT_ID`と`REVERSE_CLIENT_ID`がファイルに含まれない問題があるため、googleログインを使う予定がなくても一時的に有効化するのが良さそうです（後で無効化にできる）。

https://github.com/invertase/react-native-firebase/issues/7338#issuecomment-1748440060

### Google Serviceファイルの取得

[Firebase Console](https://console.firebase.google.com/)の該当プロジェクト画面から`アプリを追加`をクリックし、iOS、androidアプリをそれぞれ作成。作成後にiOSアプリから `GoogleService-Info.plist`、androidアプリから`google-services.json`をダウンロードし、プロジェクトのroot配下にそれぞれを設置（別のパスに設置する場合はそちらのパスを下記`app.json`にも反映させる）。

### app.jsonの更新

```json
{
  "expo": {
    "ios": {
      ...
      "googleServicesFile": "./GoogleService-Info.plist"
    },
    "android": {
      ...
      "googleServicesFile": "./google-services.json"
    },
    "plugins": [
      "@react-native-firebase/app",
      "@react-native-firebase/auth",
      "@react-native-firebase/crashlytics",
      [
        "expo-build-properties",
        {
          "ios": {
            "useFrameworks": "static"
          }
        }
      ],
      ...
    ]
  }
}
```

設定は以上で、各ライブラリを使った実装が進められるようになります。
```ts
// Firestore
import firestore from '@react-native-firebase/firestore';

const usersCollection = firestore().collection('Users');
```

ローカルのシミュレータで確認しながら実装を進める場合は、`npx expo prebuild`(`ios`と`android`ディレクトリが作られる)した後に、`npx expo run:ios`（もしくは`npx expo run:android`)することで、シミュレータが立ち上がり、コード変更時にホットリロードします。実機で確認しながら進める場合は、[expo-dev-client](https://docs.expo.dev/versions/latest/sdk/dev-client/)が便利です。

## まとめ
少し設定周りの理解が必要でしたが問題なく`firebase-js-sdk` から `react-native-firebase`にスムーズに移行ができました。今後も依存するライブラリは定期的に見直しの検討をしようと思います（結果長期的な恩恵を受けるため）。
Google Cloud 認定 Professional Machine Learning Engineer資格認定に向けての取り組み

# 要約

この度、**Google Cloud 認定 Professional Machine Learning Engineer** 試験に合格しましたので、その過程で得られた知見を整理しました。

**この記事で伝えたいこと**

- **生成AI時代の必須スキル、機械学習を学ぶことの重要性** ChatGPTなど、私たちの生活を変える生成AI。その裏側にある機械学習を学ぶことで、AIを使いこなし、新しいチャンスを掴むことができます
- **機械学習の習得・スキルの可視化を目指すなら、PMLE認定資格はおすすめ** Google Cloudが提供する Professional Machine Learning Engineer(PMLE)認定資格は、機械学習エンジニアとしてのスキルを証明し、キャリアアップに役立ちます

![Screenshot 2024-05-25 at 18.48.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55793/903417d8-917e-4778-57eb-feacbbc46e2c.png)


# 生成AI時代の必須スキル 機械学習

近年急速に利用が進んでいるChatGPTは、「機械学習」の進化が生み出した「生成AI」と呼ばれる技術の一例であり、生成AIは、私たちの生活やビジネスを大きく変えようとしています。

**機械学習を学ぶことは、この変化の波に乗り遅れないための第一歩です。**

機械学習を理解することで、

- **生成AIの仕組みを深く理解し、より効果的に活用できるようになります。**
- **AI技術を活用した新しいビジネスチャンスを見つけ出すことができます。**
- **AI時代に求められる人材としての価値を高めることができます。**


# Google認定資格 「Google Cloud - Professional Machine Learning Engineer(PMLE) 」とは

Google Cloud Platform (GCP) 上での機械学習ソリューションの設計、構築、運用に関する専門知識とスキルを認定するものです。試験対策を通じて、機械学習モデルの開発、データパイプラインの構築、MLOpsの実践、分散学習など、機械学習について、本番環境での運用まで含めた幅広い知識を深めることができます。

## 試験概要（試験形式、実施方法等）について
[Google Cloud Certification - Professional Machine Learning Engineer](https://cloud.google.com/learn/certification/machine-learning-engineer)

## 試験の評価項目について
https://cloud.google.com/learn/certification/guides/machine-learning-engineer


# 受験にむけての取り組み

学習に使ったリソースは、以下の２つです。期間は約４ヶ月かけて準備しました。

- 基礎教材
- 過去問題

## 基礎教材
Google Skill Boostの [Machine Learning Engineer Learning Path](https://www.cloudskillsboost.google/paths/17)で機械学習の基礎から応用まで体系的に学習しました。

なお、Google Skill Boostsのコースは教材の量が比較的多かったため、時間の都合で私は以下を学習した段階で過去問を解き、受験に挑みました。

コースActivity番号: 01(A Tour of Google Cloud Hands-on Labs) - 07, 10 - 13

## 過去問試験

試験合格に向けて、どのような問題が出題されるか傾向を把握するため、過去問をできるだけ多く解きました。教材には以下を使用しました。

- [Google 模擬試験](https://docs.google.com/forms/d/e/1FAIpQLSeYmkCANE81qSBqLW0g2X7RoskBX9yGYQu-m1TtsjMvHabGqg/viewform)
	無料であるが問題数が約20問程度なので、追加で下記のUdemyのコースを受講しました

- Udemy 過去問試験問題 [Google Professional Machine Learning Certification Exam 2024](https://www.udemy.com/course/google-professional-machine-learning-certification-exam-2023/)


# 資格勉強を通じて学んだこと

- アルゴリズムの検討や MLモデルの作成は、MLプロジェクト全体作業の約5%程度に過ぎず、MLプロジェクトは「モデルを作り、学習して予測」で終わりではない
- MLプロジェクトにおいて本質的に重要なことは、継続して運用すること。そのためには、運用をある程度自動化することが不可欠。MLOpsは重要なキーワード
- データ収集から予測までのパイプラインだけでなく、再学習 Continuous Training(CT)を行うパイプラインも重要
- トレーニングおよび本番環境におけるパイプライン構築において、Vertex AIは非常に有用なMLサービス
- 学習に関して、生成AI時代には分散学習の知識やスキルも必要になる
- 本番環境における End-to-End のパイプラインや分散学習の実装の必要性を考慮すると、 TFX(TensorFlow eXtended) や KubeFlow の習得を検討する価値はある


# 今後の展望
[Parul Gautamさんのツイート](https://twitter.com/Parul_Gautam7/status/1748935248874733797)にて、Data Engineer, Data Scientist, Data Analyst, Machine Learning Engineer の違いについて述べられています。
今回の認定資格学習を経て、私は、データ分析、データエンジニアリング、データサイエンスに加え、機械学習分野の知識やスキルを習得することができました。
今後は、これまでに得た知識やスキルをもとに、TFXや分散学習の実装、生成AIなどより発展的な領域にチャレンジしていきます。

![role.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55793/91584250-402c-5547-87a1-78551d916b31.jpeg)
画面(widget)の比較がしたかった

画面を実装していて、変更すると動作がおかしくなった。
変更前と変更後で、何が違うのか確認したいが結構難しい。
一応、Flutterのインスペクタで現在実行中のwidgetの階層情報をGUIで確認できますが、
膨大な階層を目視で比較はちょっとしんどい。
ログに出力するdebugDumpAppはあるが、比較するには使い勝手が良くない。
比較するならプレーンな状態の文字列したい。
ということで、debugDumpAppの中身をそのまま持ってきました。
debugDumpAppの出力そのままだと、実行中のインスタンス情報も入ってしまい
比較が難しいので、インスタンス情報っぽいものは削除するようにしてあります。

```dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

/// widget構造を文字列として取得する
/// debugDumpApp()は、ログに出力されて都合が悪い場合用
///
/// * bool [ignoreInstance] インスタンス情報を含めるかどうか
String getWidgetNodeInformation([bool ignoreInstance = true]) {
  const String mode = kDebugMode ? 'DEBUG MODE' : kReleaseMode ? 'RELEASE MODE' : 'PROFILE MODE';
  final StringBuffer buffer = StringBuffer();
  buffer.writeln('${WidgetsBinding.instance.runtimeType} - $mode');
  if (WidgetsBinding.instance.rootElement != null) {
    buffer.writeln(WidgetsBinding.instance.rootElement!.toStringDeep());
  } else {
    buffer.writeln('<no tree currently mounted>');
  }
  var result = buffer.toString();
  if (ignoreInstance) {
    // インスタンス情報に一致するものを削除
    RegExp regex = RegExp(r'#.*?(?=[)\]])');
    result = result.replaceAll(regex, '');
  }
  return result;
}
```

使い方は、画面表示後の処理の何処かで取得してファイルに出力するなり、別のログシステムに投げ込む感じです。
iOSのブラウザにて、TDタグ内で勝手に追加される電話リンクを無効にしたかったが妥協した


## 確認した環境

iOS 17.4.1
Chromeアプリ 125.0.6422.80

## 本文

iOSのChromeアプリやSafariでは10桁前後の数字が存在していると勝手にリンクが貼られるという大きなお世話機能がある。

https://mubouan.hatenablog.com/entry/2021/06/12/133600

https://support.google.com/chrome/thread/241545938/ios%E3%81%AEgoogle-chrome%E3%81%AB%E3%81%A6%E3%80%81%E3%82%B5%E3%82%A4%E3%83%88%E3%81%ABtelephone-no%E3%81%8C%E8%A8%AD%E5%AE%9A%E3%81%97%E3%81%A6%E3%81%82%E3%81%A3%E3%81%A6%E3%82%82%E9%9B%BB%E8%A9%B1%E7%95%AA%E5%8F%B7%E3%81%AE%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AB%E4%B8%8B%E7%B7%9A%E3%81%8C%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%82%8B%E3%80%82?hl=ja

で、TDタグ内の数字に対して、その現象が発現したため以下の対応をしようとしたのだが…

https://qiita.com/megurock/items/edbd9db255eb167712c6

https://gri.jp/media/entry/28900

https://irodori-design-web.com/blog/blog-1890/#google_vignette

全く効果がなかった…

```html:index.html
<meta name="format-detection" content="telephone=no">

```

```vue:疑似コード(Vue)
<td>{{item.kaine}}</td>
<td>{{item.urine}}</td>
```

```css:style.css
/* 効果なし */
td {
  text-decoration: none;
  pointer-events: none;
}

/* 効果なし */
td a {
  text-decoration: none;
  pointer-events: none;
}

/* 効果なし */
td a[href^="tel:"] {
  text-decoration: none;
  pointer-events: none;
}
```

以下のようにしたら効果があったがバッドノウハウすぎる…

```vue:疑似コード(Vue)
<td><a>{{item.kaine}}</a></td>
<td><a>{{item.urine}}</a></td>
```

```css:style.css
td a {
  text-decoration: none;
  pointer-events: none;
}
```

<details><summary>ちなみにAタグではなくDIVタグを使うと効果なしだった</summary>

```vue:疑似コード(Vue)
<td><div>{{item.kaine}}</div></td>
<td><div>{{item.urine}}</div></td>
```

```css:style.css
td div {
  text-decoration: none;
  pointer-events: none;
}
```
</details>


## 結局どうしたのか

しょうがないのでカンマ区切りにしてお茶を濁した。

```vue:疑似コード(Vue)
<td>{{item.kaine.toLocaleString()}}</td>
<td>{{item.urine.toLocaleString()}}</td>
```

終わり。
【AWS】 「This XML file does not appear to have any style information associated with it. The document tree is shown below.」への対応方法。(CloudfrontとS3の紐づけ時)

事象：CoudfrontでS3を配信設定をしたが、ディストリビューションドメイン名でアクセスしても以下エラーが出てしまい、アクセスしたいオブジェクト(index.html)にアクセスできない
<エラーメッセージ>
This XML file does not appear to have any style information associated with it. The document tree is shown below.

原因：デフォルトルートオブジェクトの設定誤り。
index.htmlがindex.comとなっていた。

解消方法：Cloudfront→対象のディストリビューション→一般→設定→編集でデフォルトルートオブジェクトを修正
【BizRobo!・DS】Excelのセルに関数・数式を入力する方法

## はじめに
BizRobo!でExcel操作をする時、セル内に**関数**や**数式**を入力したい場合が出てくる時もあるかと思います。

今回は、変数に数式を入れて、それをセル内に入力する方法を取り上げます。

## 実際の作り方
1. 変数に入れる数式を、「=」で始まる形で作成

2. 「セルのコンテンツ設定」で、対象セルに変数を入力

3. 「コンテンツ」を「コンバータ」で取得するよう変更

4. 数式が入った変数を取得

5. 「エンコードとデコード」＞「アンパサンドエンコード」を選択

6. フォーマットはGeneralか入力したい書式を記載

7. 対象セルに入力

以上が手順になります。

もし数式が反映されない場合は、変数の型を確認してください。
short text型の変数に入れてしまった場合は、その時点で文字列として認識されてしまうので、integerなどの型に変更してください。

当たり前の事ではありますが、変数で値を扱う時は、 **「値の情報は変数の型に依存する」** という事を基本ルールとして認識しておきましょう。
Linux ディレクトリ削除コマンド

ディレクトリ削除のコマンドが必要な時、いつも忘れるので記録する。

## 空ディレクトリ削除

```
rmdir ディレクトリ名
```

:::note warn
中身があると削除できない。
:::

## ディレクトリ中身丸ごと削除

```
rm -rf
```

:::note info
-r (recursive) フォルダー削除のため再帰的削除を実行するオプション
-f (force) 権限に関係なく実行するオプション
:::
【Terraform 】Terraform でS3のバケットを構築してみるハンズオン

# はじめに
本記事はTerraformについて初心者の私が、新規にS3のバケットを構築した際の手順をまとめたハンズオン形式の記事になります。
手探り状態で作成したのでより良い書き方等はまた勉強しておきます。


# Terraformとは？
Terraformは、インフラストラクチャをコード（Infrastructure as Code、IaC）として管理するためのツールです。マルチクラウド（AWS、GCP、Azureなど）に対応しています。

https://www.terraform.io/


# 本記事のゴール
TerraformでS3のバケットを構築してみる

# 前提
本記事ではTerraformでの環境構築が終わっている事を想定しています。
まだ終わってない方は下記の記事から環境構築をお願いします。

https://qiita.com/enumura1/items/992ddc20a607c5eb8a6d

# 環境
- Terraform v1.7.4
- PowerShell


# IAMアカウントを準備する
リソースを作成する用のIAMアカウントを準備します。
コンソールからIAMを選択し、アクセス管理 > ユーザ > ユーザの作成 を選択します。
アタッチするポリシーとしては、S3のフルアクセス権限（AmazonS3FullAccess）を設定しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/566bfd0e-1ab7-aa7c-5df2-0d70643f8312.png)

続いてプロファイル名を設定するため、作成したIAMアカウントのアクセスキーとシークレットキー情報を取得します。

セキュリティ認証情報タブからアクセスキー > アクセスキーを作成 > ローカルコードにチェックを入れアクセスキーを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/d2da0d84-18e7-40e0-b9db-24a1f88a7b32.png)

アクセスキーが作成出来たら、アクセスキーとシークレットキーをメモしておいてください。

:::note warn
アクセスキー、シークレットキーについては表示画面を閉じると再度確認はできないので、忘れないように保存しておく事に注意してください。
:::

# プロファイルの設定

続いてAWSの`credentials`ファイルにアクセスキーとシークレットキーの情報を追記していきます。
本記事で使用する用のプロファイル名を新たに作成します。
プロファイル名はなんでもよいですがここでは `terraform_tt`とし、以下のように先ほど取得したアクセスキーとシークレットキーを記載しておきます。

```:credentials
～～～

[terraform_tt]
aws_access_key_id = XXXXX
aws_secret_access_key = WWWWW

～～～
```

記載が完了したら保存してファイルをとじておき、以下のコマンドで問題なくプロファイル名の設定を追記できているか確認します。

```
cat ~/.aws/credentials
```

新しく追記したプロファイルが表示される事を確認し、次にソースの作成を進めていきます。



# ソース
詳細はコメントアウトの通りです。
`sample-bucket-terrafomr-test-0524`という名前のバケットを作成します。

```terraform:main.tf
terraform {
  // terraformのバージョンを指定
  required_version = ">= 1.5.1"

  // awsプロバイダーのバージョンを指定
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.16"
    }
  }
}

// awsプロバイダーの設定
provider "aws" {
  // 東京リージョンを指定
  region = "ap-northeast-1"
  // 上記で作成したプロファイル名を指定
  profile = "terraform_tt"
}

// s3バケットを作成
resource "aws_s3_bucket" "sample" {
  bucket = "sample-bucket-terrafomr-test-0524"
}
```

:::note info
**vscodeの拡張機能について**
vscodeを使用している場合は、`HashiCorp Terraform`という拡張機能をインストールしておくと、シンタックスハイライトや補完機能を使えて便利です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/72dd9426-8597-a388-8b7d-68e4b71b0d80.png)

:::


# 実行 & 結果確認
ここまでできたら、下記のコマンドを順に実行しS3バケットのリソースを作成します。

Terraformプロジェクトの初期化を行います。
```powershell
terraform init
```

変更内容を確認します。今回はS3バケットを新規構築するので、想定通りの内容になっているか確認いたします。
```powershell
terraform plan
```

最後に下記コマンドでリソースを構築します。
```powershell
terraform apply
```

上記コマンドを実行した後に、AWSのコンソールからS3のバケットを確認すると対象のリソースが作成されていることを確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/c2dc9af6-9408-4287-27e2-7bbb74bc5d79.png)
初めてのPython - Python環境構築編

Pythonを実行するには、Pythonというインタープリタ（ソースコードをマシン語に翻訳するプログラム）が必要です。Pythonを実行することができる環境・快適にプログラミング開発を行える環境の作り方を解説します。

今回紹介するPythonの開発環境は2種類です。

- [1. Google Colabを使用したブラウザベースのクラウド開発環境](#1-google-colabを使用したブラウザベースのクラウド開発環境)
- [2. VS Codeを使用したローカルの開発環境](#2-vs-codeを使用したローカルの開発環境)

## 1. Google Colabを使用したブラウザベースのクラウド開発環境

こちらはグーグルアカウントさえあればどのパソコンでも動かせます（学校パソコン含め）。作成したファイル（ソースコード）はグーグルドライブ上に保存されます。インストール不要なのでお手軽に始めることができますが、拡張性が少し欠けています。初心者の方がPythonを勉強するには申し分ない環境です。

では、実際にGoogle Colabを使う方法を紹介します。

グーグルドライブの画面から、新規→Google Colaboratoryをクリックします。
![alt text](https://raw.githubusercontent.com/Xiaolin-s-Techclub/qiita-tech-academy/main/image-2.png)

グーグルアカウントにログインすれば、新しいノート（ジュピターノートファイル形式）が作成されます。
![alt text](https://raw.githubusercontent.com/Xiaolin-s-Techclub/qiita-tech-academy/main/python-basic-101/image-3.png)

セルにPythonコードを入力して実行（Run）ボタンを押せば、セルの中のコードが実行されます。

### 注意点　<!-- omit in toc -->
グーグルドライブのファイルにアクセスするには、次の文をセルに打ち込んで実行する必要があります（マウント作業）。
` python
from google.colab import drive
drive.mount('/content/drive/')
`
認証画面が出てきたら、手順に沿ってマウントを許可してください。
ツールバーのフォルダ欄にdriveというフォルダが出てきたら完了です！
driveフォルダ内のファイルは、Google Colabのセッションが終わっても消えません。

おめでとうございます！
これでPythonの開発をスタートできます。

## 2. VS Codeを使用したローカルの開発環境

こちらはご自身のパソコンにPythonを実行する環境を作成する方法です。特別重い処理を行わない限りパソコンのスペックは不要ですが、いくつかのプログラムをインストールする必要があります。インストールするものは主に二つです。開発に本腰を入れる方はこちらをお勧めします。

- Python（3.10）
- IDE/コードエディター/統合開発環境（開発に便利な機能を持ったテキストエディタ―）

    **おすすめはVS Code**というエディターです。

詳しくはこちらの記事を参考にしてください。

https://qiita.com/kotattsu3/items/30af03266a61ece4740e
Simulinkのシミュレーション結果をcsvで保存

Simulinkのシミュレーション結果をcsvで保存するスクリプトをここに記しておく。
（毎回作ったり探したりするのめんどくさいから、ここに書いておく。）


### モデル側について

今回は、以下のようにsimuout、simuout2という変数名でワークスペースに出力した変数について、
CSV化することを考える。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/ceb9a740-0651-63f7-0dd2-220f575559cc.png)


### スクリプト
以下のスクリプトを実行すると、csvファイルが作れます。

```MATLAB
% 時間情報とデータを取得
time = out.simuout.Time;
data1 = out.simuout.Data;
data2 = out.simuout2.Data;

% 出力データを結合
testes = [time, data1, data2];

% CSVファイル名を定義
savefile = 'test.csv';

% ヘッダー情報を定義
header = {'time', 'data1', 'data2'};

% ヘッダーとデータをCSVファイルに書き込み
writecell(header, savefile, 'WriteMode', 'overwrite'); % ヘッダーを書き込み
writematrix(testes, savefile, 'WriteMode', 'append'); % データを追記

```

### 動作確認結果
こんな感じで、意図通りにできてました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/f88c1699-7d87-9dd9-9fdf-5638ba7d4fb9.png)
【Python CLI】青空文庫のXHTML本からEPUBに変換するツールをforkした

## はじめに

青空文庫からテキストを取得してePubに変換するプログラムは [AozoraEpub](https://github.com/hmdev/AozoraEpub3) やその改造版 [AozoraEpub3](https://github.com/kyukyunyorituryo/AozoraEpub3/wiki)が有名だが、Java なしでできないかと調べたところ、Python に [ebooklib](https://github.com/aerkalov/ebooklib)というライブラリがあり、すでにこれを利用したプログラム[pyaozora](https://github.com/ymndoseijin/pyaozora)があったため、forkして欲しい機能を追加するなどした。

https://github.com/pipin68k/pyaozora

## 変更点
1. JIS X0213 対応表を利用した外字対応
2. 青空文庫上で目次がない図書への対応
3. 青空文庫へのアクセスをキャッシュ化
4. ePubのスタイルをシンプルに
5. 目次を変換しない

### JIS X0213 対応表を利用した外字対応
下記を参考に外字対応を追加した。

https://qiita.com/kichiki/items/bb65f7b57e09789a05ce

### 青空文庫上で目次がない図書への対応
元プログラムでは、青空文庫上の目次リンクからコンテンツを取得しているため、目次がないとコンテンツが取得できなかった不具合の対応。

### 青空文庫へのアクセスをキャッシュ化
requests ではなく、requests_cache を利用。

### ePubのスタイルをシンプルに
ebooklib で縦書き右綴じにするには、directionの指定と、cssでのライティングモードだけで良さそうだったので、そのように修正。

```python
book.set_direction("rtl")
```
```css
html {
    -epub-writing-mode:   vertical-rl;
    -webkit-writing-mode: vertical-rl;
}
```

https://www.jepa.or.jp/ebookpedia/201701_3378/

### 目次を変換しない
コードをシンプルにしたかったので、目次リンクの変換は除いた。

## 使い方

`-t`が縦書きの設定です。 デフォルトは横書き。
`-o`プログラムの出力ファイルの設定です。デフォルトは `$題名.epub` です。

```
python pyaozora -t https://www.aozora.gr.jp/cards/000096/files/2381_13352.html
```

## 表示確認
以下のリーディングシステムで縦書き右綴じとなること、外字が表示されることを確認した。

* Thorium Reader
* Apple Books
* Kindle Paperwhite

## 参考

* [青空文庫](https://www.aozora.gr.jp/)	
* [プロジェクトX0213](https://x0213.org/)	
* [【Python CLI】青空文庫のXHTML本からEPUBに変換するツールを作った](https://qiita.com/ymndoseijin/items/88548a90c0ff06287f7c)
* [青空文庫の外字をPythonでUnicodeに置換](https://qiita.com/kichiki/items/bb65f7b57e09789a05ce)
* [ライティングモード](https://www.jepa.or.jp/ebookpedia/201701_3378/)
【AWS】生成AI体験ワークショップの良いところ気を付けるところ【生成AI】

## はじめに
近年では生成AIが注目を集め、実際に利用したい個人や企業が増えています。
ただ、実際に生成AIで何ができるのか？どれくらいの精度のものが得られるのか？は実際に使用して気が付くことも多いです。
AWSで生成AIを用いた機能を気軽に体験するために、「生成AI体験ワークショップ」というものがAWSから提供されています。
今回の記事ではこの生成AI体験ワークショップを使用するときの良いところと気を付けるところについて、個人の見解を投稿しています。


## 生成AI体験ワークショップとは
### 【提供サイト】

https://catalog.workshops.aws/generative-ai-use-cases-jp/ja-JP

### 【構成図】
![生成AI構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192949/49be450f-bee2-8304-8b88-1bdc000a58b2.png)

### 【特徴】
- CloudFormationテンプレートで提供されている
- 難しい設定が不要でテンプレートを実行するだけで生成AIに関するWebアプリケーションが利用できる
- 生成AIに関する機能として、「チャット」「RAGチャット」、「文章生成機能」、「要約機能」、「構成機能」、「翻訳機能」、「Webコンテンツ抽出機能」、「画像生成機能」が利用できる
- AIモデルが最新のものが選択できる(2024年5月時点 anthropic.claude-3-opus,anthropic.claude-3-sonnet,anthropic.claude-3-haiku)


## 生成AI体験ワークショップの良いところ
Cloudformationで構成のすべてが定義されているため、スタック作成と削除が一括で行えます。
そのため、必要な時だけ作成して不要になった時点で削除ができ不要なコストの発生が防止できます。
また、関連するAWSサービスの作成権限がユーザに付与されていれば他の準備不要でCloudFormationの実行から開始でき、WAF用のテンプレートとそれ以外のサービスのテンプレートを実行するだけなのでスタック作成中の待ち時間を含めて2時間未満で生成AIを試す環境が構築できます。

## 生成AI体験ワークショップを使用する際に気を付けること
### ①生成AIワークショップのURLがスタック作成のたびに変更される
生成AIワークショップはAWSのサイトからダウンロードできるCloudFormationテンプレートを実行して各種AWSサービスのリソースを作成しますが、そのリソースの名前が重複しないようにランダムな値が付与された形で作成されます。
URLについてもスタックを作成するたびにランダムな値で生成されるため、例えば社内で初回のスタック作成時にURLを展開していても、再度スタックを作成した際には別のURLを展開する必要が出てきます。

### ②CloudFormationで一括削除されるのでデータや登録したユーザも削除される
#### ②－1：RAGファイル保存先のS3バケットが削除される
RAGチャット機能を使用するためにはS3バケットに検索対象のファイルをアップロードし、そのバケットをデータソースとしてkendraによるデータ同期を行う必要があります。
CloudFormationのスタック削除時にこのS3バケットの削除も行われるため、次回スタック作成時にファイルの再アップロードが必要になります。
#### ②－2：Cognitoユーザプールが削除される
ワークショップの機能を使用するためにはスタック作成時に出力されるURLで指定された画面でユーザのサインインを行ってからチャットなどの機能を利用します。
このユーザ情報を管理しているCognitoのユーザプールもCloudFormationに定義されているため、スタック削除と同時に削除され、再度スタック作成後は再度ユーザ登録が必要になります。

## 生成AI体験ワークショップのデータ保持方法の案
### CloudFormationを分割する or 一部リソースを手動管理する
生成AI体験ワークショップは一時的に利用できる環境を作成するものでカスタマイズや本稼働は目的にされていない印象です。気軽に使えて不要になったら気軽に削除されるのが最大にメリットだと思うのでこれはこれで仕方ないところかなと思います。
ですがある程度多くのユーザが使用する場合に再登録やURLの再定義を行いたくない場合は、テンプレートからCognitoとAmazonS3、CloudFrontを元のテンプレートから別のテンプレートに移して運用するか、テンプレート管理ではなく手動でAWS環境に反映させ運用することでCloudFormationの一括削除からURL変更やユーザ再登録の手間を減らすことができます。
新しいCloudFormationテンプレートをダウンロードして反映させるときにそのテンプレートからCognitoやCloudFrontを外すなどの編集する手間は発生するのでテンプレートの管理方法は検討の必要があります。

## さいごに
生成AI体験ワークスペースは生成AIの機能のお試し環境として構築が非常に楽で様々なユースケースを試せるため非常に素晴らしいものだと思います。
一通りのユースケースが揃っているので、ここから不要な機能を絞ったり機能の改修をしたりするようなより発展的な活用の計画も立てやすいと思います。しかしその際に必ずリソース管理方法をしっかりと検討するようにしてください。
生成AI体験ワークスペースで提供されている内容はあくまで体験のためのもので、実際にそれを自分のものにして活用していくためにはワークスペースで提供されているリソース同士のつながりなどの構成や特徴をしっかりと理解し、どうすれば運用が楽になるか、意図しないことでリソースが消えてしまうことがないか、消えないようにするにはどうするかの対策を立てる必要があります。
生成AIのシステムを1から完璧なものを作るのは難しいことだと思います。そのため以下のような段階で徐々に作っていくのが良いのではないかと思います
- ①生成AI体験ワークショップで生成AIでできることや精度を確認する
- ②自分たちに必要な機能やユースケースを整理する(要件定義、設計)
- ③生成AI体験ワークショップのリソースや機能の一部を自分たちで管理する(提供されたテンプレートからの離脱)
- ④自分たちで管理している範囲を増やして生成AI体験ワークショップから完全離脱する
- ⑤自分たちで独自の機能改修などを続けて生成AIを活用する

生成AIは人の生活を拡張してくれるとても良いものですが、どの人にも必ず必要なものかと言われるとそうではないと思います。まずは何ができるのか生成AI体験ワークショップで確かめて、活用すべきかどうかを試してみてください。
Private API Gatewayの仕様および使い方

API Gatewayと言えば、REST APIを利用してLambda関数を呼び出してサーバーレス構成を実現すると思われますが、最近はPrivate API Gatewayを利用したことがありますので、解説いたします。
# API Gatewayの種類
API Gatewayは、4種類あります。
![9.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600067/c4b9547e-c246-b3b6-2acb-d1c801f0f625.jpeg)
# Private API Gatewayについて
プライベートAPI Gatewayのプライベートとは、パブリックから直接アクセスできないとなるだけで、あなただけがアクセスできるプライベートネットワーク内のAPIという意味ではありません。（だって、それってVPCですよね。API GatewayはVPCに属しません）
なので、AWSのプライベートネットワーク内においては特に制限をしない限り、誰でもアクセスできるAPI Gatewayです。
![10.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600067/d5248875-7486-8d9a-6400-754731cbcdff.jpeg)
# Private API Gatewayにアクセスするための設定
プライベートAPI GatewayはInterface Endpoint経由でアクセスしているので、内部といってもリソースポリシーが必要です。

:::note info
リソースポリシー
:::
```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "arn:aws:execute-api:ap-northeast-1:809449918173:dd75nu3d01/*"
    },
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "arn:aws:execute-api:ap-northeast-1:809449918173:dd75nu3d01/*",
      "Condition": {
        "StringNotEquals": {
          "aws:SourceVpce": "vpce-0c76e9272ffbeef67"
        }
      }
    }
  ]
}
```
:::note info
Private API Gatewayの作成
作成時、エンドポイントの入力は求められています。
:::
![11.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600067/9ad27148-7f5a-7055-572e-f9f41c4c8b84.jpeg)
![12.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600067/ddb0ff6a-74e6-4e96-ab6d-e2f1e20b99b3.jpeg)

:::note warn
上記の設定では、アベイラビリティーゾーン二つ跨いでいる構成となり、各ENIに対して適切なセキュリティグループの作成が必要ですのでご注意ください。
:::

# まとめ
簡単ながら、Private API Gatewayの構築例を解説いたしました。実際サーバーレス構成で良く使うと思うので、ご参考になれば幸いです。
ネットワーク理論の用語まとめ



次数、平均次数、次数分布、隣接行列は、ネットワーク理論において重要な概念です。それぞれについて説明します。

## 次数 (Degree)
- ノードの次数とは、そのノードに接続されているリンクの数のこと
    - 無向ネットワークでは、各ノードの次数は接続されているリンクの総数になる
    - 有向ネットワークでは、以下に分けられる
        - 入次数（そのノードへ向かうリンクの数）
        - 出次数（そのノードから出ていくリンクの数）

## 平均次数 (Average Degree)
- 平均次数 ⟨k⟩ は、ネットワーク全体のノードの次数の平均値
    - 有向ネットワークでは、平均入次数と平均出次数が等しくなる
    - 無向ネットワークでは、平均次数は以下の式で計算される
        - ⟨k⟩ = (2 × リンクの総数) ÷ ノードの総数

## 次数分布 (Degree Distribution)
- 次数分布 P(k) は、ネットワーク内でランダムに選択したノードが次数 k を持つ確率
- 多くの現実のネットワークでは、次数分布がべき乗則に従う
    - これはスケールフリーネットワークと呼ばれる

##  隣接行列 (Adjacency Matrix)
- ネットワークの構造を表現する行列
- N 個のノードを持つネットワークの隣接行列 A は、N × N の正方行列で表される
- 隣接行列を使用することで、ネットワークの数学的な表現が可能になり、行列演算を用いたネットワーク分析が行える


## 最短経路 (Shortest Path)
- ネットワーク内の2つのノード間を結ぶ最短のパスのこと
- パスの長さは、通過するリンクの数（ホップ数）や、リンクに割り当てられた重みの合計で測る
- 最短経路を見つけるアルゴリズムとしては、Dijkstra法やBellman-Ford法など

## ネットワーク直径 (Network Diameter)
- ネットワーク内の任意の2つのノード間の最短経路の長さの最大値
    - つまり、ネットワーク内で最も離れた2つのノード間の最短経路の長さ
- ネットワーク直径は、ネットワークのサイズや情報伝達の効率性を示す指標の1つ

## 平均経路長 (Average Path Length)
- ネットワーク内の全ノードペア間の最短経路長の平均値
- ネットワーク内の典型的なノード間の距離を表し、ネットワークの「スモールワールドネットワーク性」を示す指標の1つ
- 平均経路長が小さいネットワークでは、情報がより迅速に伝達されると考えられる

## 循環 (Cycle)
- ネットワーク内で始点と終点が同じノードであるパスのこと
    - あるノードから出発し、他のノードを経由して元のノードに戻ってくるパスを指す

## Euler経路 (Eulerian Path)
- ネットワーク内の全てのリンクを一度だけ通過するパスのこと
    - 始点と終点が異なる場合はEuler道 (Eulerian Trail)
    - 始点と終点が同じ場合はEuler閉路 (Eulerian Circuit)
    
## Hamilton経路 (Hamiltonian Path)
- ネットワーク内の全てのノードを一度だけ通過するパスのこと
    - 始点と終点が異なる場合はHamilton道 (Hamiltonian Trail)
    - 始点と終点が同じ場合はHamilton閉路 (Hamiltonian Circuit)


## 幅優先探索アルゴリズム (Breadth-First Search Algorithm, BFS)
- 幅優先探索は、グラフやネットワークの探索アルゴリズムの1つ
- ある始点ノードから出発し、そのノードに隣接する全てのノードを探索してから、さらにその隣接ノードに隣接する全てのノードを探索するという過程を繰り返す
- この探索方法では、始点ノードからの距離が近いノードから順に探索されます。幅優先探索は、最短経路問題や連結成分の発見などに利用される

## 連結成分 (Connected Component)
- 無向グラフにおいて、
    - 連結成分とは、グラフ内の任意の2つのノードが少なくとも1つのパスで結ばれているノードの集合のこと
    - 連結成分内のノードは互いに到達可能であり、異なる連結成分のノード間には到達可能なパスが存在しない
- 有向グラフの場合は
    - 強連結成分と弱連結成分に分けられます。
        - 強連結成分：任意の2つのノード間に双方向のパスが存在する部分グラフ
        - 弱連結成分：有向グラフを無向グラフとみなした場合の連結成分

## クラスター係数 (Clustering Coefficient)
- ネットワーク内のノードがどの程度密にクラスター化しているかを測る指標



## 多重グラフ、単純グラフ
- 多重グラフは、2つのノード間に複数のリンクが存在することを許すグラフ
- 単純グラフは、2つのノード間に最大1つのリンクしか存在せず、自己ループも許されないグラフ

## 完全グラフ
- 全てのノードがお互いにリンクで直接つながっているグラフ
- n個のノードを持つ完全グラフは、n(n-1)/2本のリンクを持つ

## 重みつきネットワーク
- リンクに重みが割り当てられたネットワーク
- 重みは、リンクの強度、距離、コストなどを表現するために使用される

## 大域的クラスター係数
- ネットワーク内に存在する三角形の数を、可能な三角形の総数で割った値として定義される
- これは、ネットワーク全体がどの程度クラスター化しているかを表す

## 巨大連結成分
- ランダムグラフにおいて、ノード数が増加するにつれて突然出現する最大の連結成分を巨大連結成分と呼ぶ
- これは、ランダムグラフのリンク確率がある臨界値を超えると出現する

## 亜臨界領域、臨界点、超臨界領域
- ランダムグラフにおいて、リンク確率が臨界値より小さい領域を亜臨界領域、臨界値を臨界点、臨界値より大きい領域を超臨界領域と呼ぶ
- 亜臨界領域では巨大連結成分が存在せず、超臨界領域では巨大連結成分が出現する

## 連結領域
- ランダムグラフにおいて、リンク確率が大きくなるにつれて、孤立したノードや小さな連結成分が減少し、大きな連結成分が形成される領域を連結領域と呼ぶ
Uncaught SyntaxError: Identifier 'mouseoverCard' has already been declared 解決

問題が解決した要因としては、以下のポイントが考えられます：

1. **即時関数の使用 (IIFE)**:
    - コードを即時実行関数（Immediately Invoked Function Expression, IIFE）で囲むことで、スコープが閉じられ、他のスクリプトとの干渉が防がれます。これにより、同じ変数名や関数名を持つ他のスクリプトとコンフリクトすることがなくなります。
2. **`window` オブジェクトへの関数の追加**:
    - `window.mouseoverCard` として関数を定義することで、グローバルスコープに関数を追加しました。これにより、関数が複数回定義されることを防ぎつつ、どのスクリプトからもアクセス可能になります。
3. **関数の存在チェック**:
    - `if (typeof window.mouseoverCard === 'undefined')` で関数が既に定義されているかどうかをチェックしました。これにより、同じ関数が再定義されることを防ぎました。

以下に、重要な変更点をまとめます：

### 変更前

1. 関数定義がグローバルスコープにあり、他のスクリプトとの干渉が発生する可能性がありました。
2. 関数がページの再読み込みや他のイベントで再定義されることがありました。

### 変更後

1. コード全体を即時実行関数で囲むことで、スコープを限定しました。
2. `window` オブジェクトに関数を追加し、再定義を防ぎました。
3. 関数の存在チェックを行い、既に定義されている場合は再定義しないようにしました。

### 変更点の例

### 変更前

```jsx
/**
 * 取得投稿一覧のホバー時
 */
const mouseoverCard = (target) => {
  // 関数内容
};

```

### 変更後

```jsx
(function() {
  /**
   * 取得投稿一覧のホバー時
   */
  if (typeof window.mouseoverCard === 'undefined') {
    window.mouseoverCard = function(target) {
      // 関数内容
    };
  }

  // 他のコードも含めて即時実行関数内に配置
})();

```

### まとめ

これらの変更により、スクリプトの安定性が向上し、ブラウザの戻るボタンなどの操作に対する耐性が高まりました。同じ名前の関数が再定義されることも防がれました。

![スクリーンショット 2024-05-25 20.54.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3655291/5f053982-f0d8-c8a1-ad83-d3e28f8f9239.png)
【SwiftUI】ブラウザを開くリンク記述

2つだけでいい。

これらをベースの変形でどうにかなるようです。

# 🧑🏻‍💻 テキストリンクから

```swift
Link(
  "【SwiftUI】ブラウザへのURLリンク", 
  destination: URL(string: "https://android.benigumo.com/20240525/browser-link/")!
)
```

# 🧑🏻‍💻 アクションとして

```swift
  @Environment(\.openURL) private var openURL

  var body: some View {
    Button("【SwiftUI】ブラウザへのURLリンク") {
      openURL(URL(string: "https://android.benigumo.com/20240525/browser-link/")!)
    }
  }
  ```

# 🧑🏻‍💻 参考

https://x.com/maochanz/status/1794304523802140932