OmniAICreator/Qiita-1.07M huggingface dataset:
import文のjavaxとjakartaのちがいは？

**javaxとjakarta**の違いは、主にJavaのエンタープライズ技術における名前空間やプロジェクトの管理に関連しています。以下で詳しく説明します。

## 1. javaxとは？
##### 【歴史的背景】
　javaxは、かつてのJava EE（Java Platform, Enterprise Edition）で使用されていたパッケージ名です。Java EEは、エンタープライズ向けアプリケーション（特にサーバーサイドアプリケーション）の開発に用いられる標準化されたAPIセットで、Oracleが主導していました。
##### 【主要な技術】
Java EEには、javaxパッケージ内にサーブレット、JSP、JPA、EJBなど、エンタープライズ向けの重要な技術が含まれています。例として、javax.servletやjavax.persistenceなどがあります。
## 2. jakartaとは？
##### 【歴史的背景】
　2017年、OracleはJava EEの権利をEclipse Foundationに移管しました。この移管により、Java EEはJakarta EEという新しい名称で管理されるようになりました。Eclipse Foundationがプロジェクトを管理するようになったことで、いくつかの変更が行われました。その一つが、名前空間の変更です。

##### 【名前空間の変更】
　Oracleとの合意に基づき、Eclipse Foundationは**javaxパッケージを変更できないため、Jakarta EE 9以降、名前空間がjavaxからjakartaに変更されました。例えば、javax.servletはjakarta.servletに、javax.persistenceはjakarta.persistence**になりました。
##### 【技術内容の継続】
　パッケージ名が変わっただけで、技術そのものは基本的にJava EEからJakarta EEに引き継がれています。ただし、Jakarta EE 9以降は新機能や改善が追加され、よりオープンでコミュニティ主導のプロジェクトとなっています。
## 3. 主な違い
##### 【パッケージ名】
・Java EE
　javaxパッケージを使用（例: javax.servlet, javax.persistence）
・Jakarta EE
　jakartaパッケージを使用（例: jakarta.servlet,jakarta.persistence）
##### 【管理団体】
・Java EE
　Oracleが主導
・Jakarta EE
　Eclipse Foundationが主導
##### 【リリースサイクルとコミュニティ】
Java EEはOracleによるリリースサイクルで管理されていたため、リリースが比較的遅かった。
Jakarta EEはEclipse Foundationが管理することで、よりオープンなコミュニティベースの開発が行われ、リリースサイクルも改善されました。
## 4. 実務への影響
##### 【互換性】
　既存のJava EE（javax）を使用したコードは引き続き動作しますが、今後新しいバージョンのJakarta EE（jakarta）を採用する場合は、コードや設定ファイルの変更が必要になることがあります。
##### 【将来性】
　今後のエンタープライズ技術の標準はJakarta EEに移行していくため、新しいプロジェクトではjakartaパッケージを採用することが推奨されます。
## まとめ
**javax**は旧Java EEのパッケージ名で、Oracleが管理していました。
**jakarta**はJava EEの後継であるJakarta EEのパッケージ名で、Eclipse Foundationが管理しています。
名前空間の変更が主な違いですが、技術の進化も今後Jakarta EEを通じて行われていきます。
dockerで立てたViteがなぜかホットリロードしない件

## やりたいこと
dockerで立てたViteでホットリロードさせたい

## 状況
- 使用パソコンはM３チップのMacbookPro
- docker-compose.yamlでdockerを起動させる構成
- docker起動後npm run devコマンドでアプリを立ち上げる仕様
- なぜかホットリロードが効かない（コンテナイメージをビルドし直さないと反映されない）

## 調査したこと
ググった結果Windowsではよくある事例らしいがMacでは出てこなかった。
ChatGPTに聞いてみると考えられる原因の一つにマウント不良があったのでディレクトリ構成を見直した。

## 原因
docker-compose.yamlのマウント設定が不適切だった。
```bash
# ディレクトリ構成
project
├── frontend
│   ├── app
│   └── Dockerfile
├── backend
│   ├── app
│   └── Dockerfile
└── docker-compose.yaml


# project/frontend/Dockerfileのコード
FROM node:20.12.2-bullseye-slim

ENV NODE_ENV=development

WORKDIR /code

COPY . .


# project/docker-compose.yamlのコードの一部（当初）
  project_frontend:
    container_name: project_frontend
    build:
      context: .
      dockerfile: ./frontend/Dockerfile
    volumes:
      - ./frontend:/frontend
    ports:
      - "5173:5173"  # フロントエンドのポート設定
    tty: true
    command: >
      /bin/bash -c '
      cd frontend/app/ &&
      npm ci --cache /tmp/empty-cache &&
      npm run dev
      '
```
マウントの設定を適切にしないとViteの監視がうまくできずホットリロードしないみたい
```bash
# project/docker-compose.yamlのコードの変更部分
    （略）
    volumes:
      - ./frontend:/code
    （略）
    command: >
      /bin/bash -c '
      cd app/ &&
      npm ci --cache /tmp/empty-cache &&
      npm run dev
      '
```
## 解決策
docker-compose.yamlのマウント設定を適切に行う。

## 終わりに
時間がかかったが何とか解決できた。基本的な概念や書き方をしっかり身につけないとこういうとこでハマるんだなと実感した。
Streamlit のチャットテキスト入力コンポーネントをインライン表示する


# 結論
下記のように、チャットコンポーネント `st.chat_input`, `st.chat_messages` 全体を `st.container()` でくくればOK。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3540224/0b35cce3-952e-1cc1-3cad-728348f71efc.png)

上記のコードは下記の Streamlit Playground から確認できます。

https://streamlit.io/playground?example=blank&code=H4sIAAAAAAAAA4VOMW7DMAzc_QpFk7wYAboZyNZ_BEqg2gRqyRBpeJaFBEHHLh06BunWB3TqY4j8o2psAwkyhNPxeMc7aFrnSSB5o5tXIKExLVnWA9UJFFtnSYM1XuVlJtI0BlFXBsXq9lwbqGpaPS2X-UUHL6L1rmlJlKOy1rQG23akJMfA8cgxcjxw3PPwzcPPPx7ez7vT-e2TwweHLw6_PBw47OWUfZ0_Ppw2JTs0XuZF74GMGoPzRx6NCEja0p0xS-1T501H5KySz86axVwi8aN4pv8A-TANBkMBAAA



他にも、`st.sidebar` なり、`st.expander` なりの中にインライン記述できるみたいです。

この機能修正は、下記の Issue であがり、Streamlit 1.31 で実装されたみたいです。

https://github.com/streamlit/streamlit/issues/7296

# おまけ：ネストしていないと？
チャットテキストのインプットコンポーネントが、画面最下部に表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3540224/3e00944e-387a-356e-55c1-bbfb5e0e7be3.png)



https://streamlit.io/playground?example=blank&code=H4sIAAAAAAAAA32OsQrCMBCG9z5FzJQupeAmuPkeEiXagE1K7opzGizF0cXBUXTzAZx8mMP3MKV2Erzp_p__7vt1WVmHDNApWe40MglRJEmpAORWAZtHma2tQamNcqJQelvgfJrnaaI3rHK2rJDNhlQhcalNVaPgFDyFK4VAoaPQUvOg5tnvzel9uL2PF_Jn8nfyL2o68i1PZwmLM3KHZ18leA3K8TTbO41KDND0X14CaEBp8Oeobx27rmpEawRfWKMmIzz6Q3i0P-U31VoeAQAA


# 最後に
それはそうと、Streamlit Playground、めっちゃ便利です。共有もできるとは知らなかった。使っていこう。
【備忘録】Udemy講座まとめ JavaScript vol.1

# 算術演算子

```JavaScript:JavaScript
result = result + 5;
result += 5;
```
上の2つは同じ意味


# クウォートの中の改行
```JavaScript:JavaScript
string = 'Hello\nWorld'
string = `Hello
World`;
```
バッククウォートでは、そのまま改行ができる



# 文字列と型の変換
```JavaScript:JavaScript
const useInput = '10';
let calcResult;
calcResult = Number(useInput) + 10;
```
useInputは、文字列のままなので、Number()を使って数字に型を変換する
XMLとは

### XMLとは
XMLとはデータ形式の一種
データ形式とは、データを扱うルールのこと
例）CSV/XML/JSON
#### どうゆうときに使用するか
システム間のデータのやり取りなどで使用される
#### 例えば
あるECサイトでクレジットカード決済を行うと、ECサイトのシステムがクレジットカード会社のシステムにリクエストを送信します。そのリクエストに対する応答として、クレジットカード会社からXML形式のレスポンスが返されます。このXMLには、決済の結果や取引の詳細が含まれています。
### まとめ
XMLはデータ形式の一種であることを理解しました。今後、業務でXMLを扱う機会があれば、さらに深く理解していこうと思います。その際に学んだことをまた投稿していきます。
NTPとは


# NTPとは
NTPはstratumと呼ばれる階層構造を持っており、最上位のNTPサーバが原子時計やGPSの正確な時刻源から正しい時刻情報を得て、下位のNTPサーバはそれを参照して時刻同期を行う。
最上位のNTPサーバは「stratum 1」であり、階層を降りるごとにstratumの値が増えていく。
最大でstratum 15までNTPサーバを構築できる。なお、stratum 16には同期できません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528926/8fa4ee46-b423-8013-ba7e-37c21ed15faa.png)

引用元：https://www.infraexpert.com/study/tcpip25.html

※　直結している「 Stratum 0 」と「 Stratum 1 」間では、IP通信ではないので当然ながらNTPで時刻同期はしていません。
不要なローカルブランチを一括削除したい

# 結論
```
git branch --format '%(refname:short)' | grep -vE "^(main|release|$(git branch --show-current))$" | xargs -n 1 git branch -D
```
このコマンドで任意のブランチとカレントブランチ以外を一括で削除できます。

### 溜まっていくローカルブランチ
レビューしているとローカルにブランチが溜まっていきますよね？
私は溜まっていました。。

定期的に`git branch -d`で一つずつ削除していたんですが、たまにマージされていないとかでエラーが発生して地味にストレス。。。

しかしまとめて消すのはmainとかカレントブランチとか気にしないといけない。
そんな葛藤を一発で解決するコマンドです！

### 解説

1. ブランチ名のリストアップ
`git branch --format '%(refname:short)'`
ローカルリポジトリ内の全てのブランチ名を短い形式（ブランチ名のみ）で取得します。

1. 特定のブランチを除外
`grep -vE "^(main|release|$(git branch --show-current))$"`
特定のブランチ（`main`,`release`,現在のブランチ）を除外するために、正規表現を使用してフィルタリングします。
・`-v`：一致する行を除外します
・`-E`：拡張正規表現を使用します
・`'^(main|release|$(git branch --show-current))$'`：カッコ内のブランチ名に一致する行を除外します。`$(git branch --show-current)`は現在のブランチを取得するサブコマンドです。
除外するブランチは自由に変更してください。

1. ブランチの一括削除
`xargs -n 1 git branch -D`
フィルタリングされたブランチ名を1つずつ`git branch -D`コマンドに渡して、削除を実行します。
・`xargs`：前のコマンドの出力を引数として受け取ります。
・`-n 1`：1回に1つの引数を渡します。
・`git branch -D`：指定されたブランチを**強制的に**削除します。強制でない通常の削除の場合は`-d`を指定します。

それらをパイプ（'|'）で繋ぎます。

**これであなたも快適なレビューライフを！！！**
【初心者向け】Ruby on Rails webサイトへの表示について

現在、デイトラでWeb開発を学んでおり、その学習において、学んだことを共有させていただきます！

現在は、Ruby on RailsでWebサイトを作成中です。

![スクリーンショット 2024-09-25 15.09.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894345/650a3c5b-d9bd-c4a2-af14-ce07b232e71e.png)

どうやってこれらの文字を表示しているのでしょうか？

```routes.rb
Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  get '/' => 'home#index'
end
```
ブラウザから get '/' リクエストがきたら、routes.rbで処理が開始され、home#indexが実行されます。

home#index が実行されると、home_controller.rb 内のindexメソッドが処理を始めます。

```home_controller.rb
class HomeController < ApplicationController
	def index
        render 'home/index'
		# render 'home/index' この部分は省略することができる。renderは「表示する」の意味
		@title = 'デイトラ'
        # @title はインスタンス変数
	end
end
```

indexメソッドが実行されると、titleに代入した文字列'デイトラ'が表示されます。

```index.html.erb
<h1>HOME</h1>
<h2><%= @title %></h2>
```

ちなみに、h1タグ("HOME")については、通常のHTMLですが、その下のh2タグは違います。

```
<h2><%= @title %></h2>
```
このコードが実行されると、title(インスタンス変数)の内容がh2タグの中に挿入されてHTMLとして出力されます。

結果として...

![スクリーンショット 2024-09-25 15.09.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894345/650a3c5b-d9bd-c4a2-af14-ce07b232e71e.png)

このようにブラウザ上で表示されることになります。

これからも学んだことを随時アウトプットしていきます！
EntityFrameworkの外部キー

## はじめに
SQLをバリバリ操作してのシステム開発しか経験がなく、EntityFrameworkのモデルファーストでデータベースを定義していく方法に慣れないため、整理しておく。

Parentテーブルの1レコードに対して、Childテーブルの複数レコードが関連している場合は、それぞれ以下の通りモデルを定義することで、自動的に関連付けされる。
なお、今回は必ず紐づけできるという前提であるが、それぞれNull許容することも可能。

## 1対1の関係
1対1はシンプルに定義することができる。

### [Parent]クラス
子テーブルのクラスオブジェクトを定義する。
~~~ c#
public class Parent
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Child Child { get; set; }
}
~~~

### [Child]クラス
「親テーブルの名称+Id」の変数と、親テーブルのクラスオブジェクトを定義する。
~~~ c#
public class Child
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
    public Parent Parent { get; set; }
}
~~~

## 1対多の関係
1対多もシンプルに定義することができる。

### [Parent]クラス
子テーブルのクラスオブジェクトを定義する。ただし、子テーブルは複数取得される可能性があるため、ここではリストとして定義する必要がある。
~~~ c#
public class Parent
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Child> Child { get; } = [];
}
~~~

### [Child]クラス
「親テーブルの名称+Id」の変数と、親テーブルのクラスオブジェクトを定義する。
~~~ c#
public class Child
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
    public Parent Parent { get; set; }
}
~~~

## 多対多の関係
多対多は少し追加の定義が必要となる。
というのも、多対多は2つのテーブル定義だけでは完結しなくなるからであり、もし手動でこの関係を定義しようと思うと、ParentテーブルとChildテーブルを繋ぐ中間テーブルが必要となる。
EntiryFrameworkでは追加の定義部分で、その部分を自動的に作成することができる。

### [Parent]クラス
子テーブルのクラスオブジェクトを定義する。ただし、子テーブルは複数取得される可能性があるため、ここではリストとして定義する必要がある。
~~~ c#
public class Parent
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Child> Child { get; } = [];
}
~~~

### [Child]クラス
「親テーブルの名称+Id」の変数と、親テーブルのクラスオブジェクトを定義する。
~~~ c#
public class Child
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<Parent> Parent { get; } = [];
}
~~~

### [ParentChild]クラス
明示的に定義をしなくても動作するが、ParentChildに対して直接インサートするために定義する。
~~~ c#
public class ParentChild
{
    public int ParentId { get; set; }
    public int ChildId { get; set; }
}
~~~

### [DBContext]クラス
~~~ c#
public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }

    public DbSet<Parent> Parents { get; set; }
    public DbSet<Child> Children { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Child>()
            .HasMany(e => e.Parent)
            .WithMany(e => e.Child)
            .UsingEntity<AreaSouvenir>();
    }
}
~~~
エステルとは？その構造と応用について

エステル（Ester）は、化学の世界で非常に重要な有機化合物の一種です。日常生活においても幅広く利用されているエステルは、香料やプラスチック、薬品など、多くの製品の成分として知られています。本記事では、エステルの基本的な構造、製造方法、特徴、そしてその多岐にわたる応用について解説します。
エステルの構造
エステルは、酸（通常はカルボン酸）とアルコールが反応して生成される有機化合物です。この反応を「エステル化」と呼び、反応式は次のようになります。
RCOOH+R′OH→RCOOR′+H2ORCOOH + R'OH \rightarrow RCOOR' + H_2ORCOOH+R′OH→RCOOR′+H2O
この式では、RとR'はそれぞれ炭化水素基を示しています。酸部分（RCOOH）の水素原子がアルコール部分（R'OH）のヒドロキシ基（-OH）と置換され、水分子が生成されることでエステルが形成されます。
エステルの基本的な構造は、カルボニル基（C=O）と酸素原子を介して結合したアルコール残基（-OR'）から成り立っています。この構造がエステルの特性や反応性を決定します。
エステルの製造方法
エステルは、エステル化反応を通じて簡単に合成できます。一般的な製法には、カルボン酸とアルコールを酸触媒（通常は硫酸など）を用いて反応させる方法が挙げられます。この反応は可逆的であり、生成された水を除去することで反応を右に進めることができます。
もう一つの方法として、無水酢酸や酸無水物を使用することもあります。これにより、エステルを効率的に生成することが可能です。また、産業的にはアルコールと酸クロライドの反応を利用してエステルを大量生産しています。
エステルの特徴
エステルは多くの優れた物理的・化学的特性を持っています。以下はそのいくつかの特徴です：
1.	芳香性：エステルの中には、フルーツのような香りを持つものが多く、香料として利用されることがあります。例えば、酢酸エチルは梨やリンゴの香りを持ち、香水や食品添加物として使われます。
2.	揮発性：エステルは一般的に揮発性が高く、液体の状態で存在することが多いです。この特性により、塗料や接着剤の溶媒としても広く使用されています。
3.	疎水性：多くのエステルは水に溶けにくく、油や有機溶媒には溶けやすいという性質を持っています。これにより、エマルジョンの安定剤としても利用されています。
エステルの応用
エステルの応用範囲は非常に広く、多岐にわたります。以下はその代表的な例です：
1.	香料・フレーバー
エステルは自然界で果物や花の香りの原因となる成分です。そのため、香水やフレーバー、食品添加物として使用されることが多いです。例えば、バナナの香り成分である酢酸イソアミルや、パイナップルの香りを持つ酢酸エチルなどが知られています。
2.	プラスチックおよびポリマー
ポリエステルはエステル基を含む高分子化合物の一種で、衣類やペットボトルの材料として知られています。特にPET（ポリエチレンテレフタレート）は、強度や透明性に優れ、リサイクルが可能なため、幅広い用途で利用されています。
3.	溶媒
酢酸エチルなどのエステルは、塗料や接着剤、インクなどの溶媒として広く利用されています。これらのエステルは揮発性が高く、溶媒として使用後に速やかに蒸発するため、製品の硬化や乾燥が速やかに行われます。
4.	医薬品
エステルは医薬品の中間体としても重要な役割を果たしています。例えば、アスピリン（アセチルサリチル酸）はサリチル酸と無水酢酸の反応により生成されるエステルです。また、エステルは脂肪酸のエステル化により体内でエネルギー源として利用されることもあります。
エステルの未来
エステルは、化学工業における重要な素材であり、今後もさまざまな分野での応用が期待されています。特に、再生可能なエネルギーや環境に優しい製品の開発において、エステルの特性を活かした新しい技術が進展していくでしょう。
例えば、バイオベースのポリエステルは、従来の石油由来のプラスチックに代わる持続可能な素材として注目を集めています。さらに、生分解性エステルの研究も進んでおり、環境負荷を軽減する新しい素材の開発が期待されています。
エステルは、香料やプラスチック、溶媒、医薬品など、私たちの日常生活に密接に関わる重要な化合物です。その多様な特性と応用範囲の広さから、エステルは今後もさまざまな分野で活躍が期待される素材と言えるでしょう。

より多くの洞察を得る - エステル
(https://www.marketwebjournal.com/esters-market-size-and-demand-analysis/)


著者について

市場調査分野のコンテンツ・エディターとして3年以上の経験を持つ。もともとはクリエイティブ・ライターだったが、ライティングの才能と細部への細心の目を融合させ、編集に情熱を注ぐようになった。魅力的なコンテンツを作り上げ、洗練させる彼女の能力は、洗練された魅力的な文章を提供する上でかけがえのない財産となっている。

(LinkedIn: https://www.linkedin.com/in/vaagisha-singh-8080b91)
2年目エンジニアが基本情報技術者試験を受けてみた

# 基本情報技術者試験を受けるか迷っている人へ

先日、エンジニア2年目にして初めて基本情報技術者試験(以下、基本情報)を受けてきました。
資格試験って役に立つの？と思いつつ試験を受けましたが、結果として受けて良かったと感じています。
過去の私と同じように、試験を受けようか迷っている皆様に参考にしていただければと思います。

:::note warn
この記事はあくまでも一個人の意見を述べたものに過ぎません。
試験勉強に役立つ内容ではないですし、自己語りも多めですが辛抱強くお付き合い頂けますと幸いです。
:::

# 基本情報を受けようと思ったきっかけ

基本情報を受けるまでの心境や自分自身の変化について述べておこうと思います。

実はエンジニアになった時から基本情報技術者試験を受けてみようかなという気持ちはありました。が、主に以下の2点のような理由をつけて試験を受けるのをやめていました。

:::note warn
- 資格が何の役に立つのかわからない
- 試験勉強した内容が直接業務に役に立つと思えない
:::

基本情報受けようかなー、でも他にやりたい勉強もあるしなーと言いながら1年と少し経過した時、基本情報を受ける決意が固まるきっかけがありました。

それは…

:::note 
- IT系に就職した友人がさまざまな資格を取ろうとチャレンジしていることを知った
- 業務についていけるようになってきて、業務に直結しない内容でも勉強してみたいと思うようになってきた
:::

他にも小さなきっかけはたくさんありましたが、背中を押したのは主に上記の2つです。

1点目に関しては、大学時代の友人がTwitter(現: X)で「試験勉強がんばるぞー」的な投稿をしていたのを見たのがきっかけでした。彼がIT系の仕事をしているのは知っていますが、業務内容は一切知りませんし、どんなモチベーションで資格取得をしようとしているのかは全く不明です。

ですが、仕事をしながら資格試験という挑戦を続ける彼の姿はかっこいいと感じましたし、自分もエンジニアとして見習いたいと強く思いました。

また、エンジニアとしての自分の力を証明したいという気持ちもありました。私がどんなスキルを持っていて、どんなことができるのかは社内の人ならある程度理解してくれていると思います。しかし、1エンジニアとして私のスキル・知識を社外に証明できるものは何も持っていません。エンジニアとしてのこれからのキャリアを考えた時、基本情報くらい持っていた方がいいのでは…?と自分の中で結論づけました。

2点目に関しては、自身の心の余裕が増えたことが原因です。未経験からエンジニアを始めた私は、1年目は正直余裕がなく、業務で使用する知識やスキルをコスパよく習得することを考えていました。

しかし、2年目になって少し余裕が出てきました。業務に直結しない内容でも、いつか役立てばいいかなと考えることができるようになりました。

その上で、今まで学習してきたことの復習や知らない知識の穴埋めという意味で、基本情報の勉強をするのは今の自分にとって適切な選択なのではないかと考えたため受験を決意しました。

# 試験を受けるまで

試験を受けるまでにどんな勉強をしたのかについて述べておこうと思います。

この本をやりました↓
[【令和６年度】 いちばんやさしい 基本情報技術者　絶対合格の教科書＋出る順問題集](https://www.sbcr.jp/product/4815624262/)

本の内容はごく一般的な参考書です。
各セクションごとに教科書的な解説と、関連する内容の過去問が並べられています。

1週目: 教科書部分を読む→問題を解く
2週目: 問題を解く→まちがえた部分に付箋を貼って教科書部分をもう一度読む
試験直前: 付箋の部分だけ読み直す
というふうに大体3週分くらい使いました。

勉強期間は1ヶ月間くらいです。

# 試験を終えた私が感じたこと

冒頭でも述べた通り、基本情報は受けてよかったと感じました。

その理由は主に以下の2点です。

:::note
- 若手エンジニアがどんなことを勉強すべき、知っておくべきなのかを知ることができた
- 「聞いたことある！」となる単語が増えた
:::

試験勉強を通じて、若手エンジニアが知っておくべき基本的な内容について広く学ぶことができました。特に、知っている単語が増えたように思います。そのおかげで、社内での技術的なコミュニケーションがしやすくなったと感じますし、何か調べ物をする際も以前よりもスムーズに記事やドキュメントを読めるようになったと感じます。広く浅い知識だったとしても、全く知らないよりはかなりアドバンテージになっているのではないかと思います。

また、普段自分が学習しない分野についても知ることができてよかったです。ハードウェアの話なんかは全く知らないことばかりでしたが、興味を持つきっかけになりました。

# まとめ・感想

冒頭に述べた以下の2点について再度振り返ってみたいと思います。

- 資格が何の役に立つのかわからない
- 試験勉強した内容が直接業務に役に立つと思えない

1点目に関しては、正直今もわかりません。資格を持っているからといって、直接的なメリットはまだ感じていないです。

2点目に関しても、勉強した内容全てが業務に直結しているとは感じていません。しかし、前章で述べたように間接的には業務の役に立っていますし、自分の知らない分野に興味を持つきっかけになったことは自分にとって大きな資産だと感じています。

「基本情報を受けるべきか？」という質問にあえて答えるならば、私は受けるべきだと思います。資格がどんなふうに役に立つのかはまだわかっていませんが、少なくとも若手エンジニアにとってはこれから学ぶべき内容が広く網羅された良い勉強になるのではないかと思います。

## おまけ
試験には合格していました。落ちていたらこの記事消そうと思っていたので良かったです。
【資格試験】OSS-DB Silver Ver3.0に合格した話

## 1. はじめに

こんにちは！

2024年7月に**OSS-DB Silver Ver3.0**の試験を受験し、
一発合格することができました（点数は割とギリギリでした💦）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2956452/a9145409-2299-4e3e-3d15-d02eb2f213cc.png)

![スクリーンショット 2024-09-26 102336.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2956452/4783f5a8-6fe6-d1f1-e696-914b69c86f5d.png)


今回は、受験の動機や学習方法、
資格取得のメリットについてお話ししたいと思います。

## 2. OSS-DB Silverとは

OSS-DB Silver（Open Source Software Database Silver）は、オープンソースのデータベース管理システム（DBMS）に関する知識やスキルを証明する資格です。
特にPostgreSQLの基本的な操作や管理に焦点を当てています。

学習期間は3ヶ月から半年が推奨されていますが、私は1ヶ月で受験しました。
受験費用は16,500円（税込）で、試験はコンピュータベーストテスト（CBT）方式で実施され、試験時間は90分、出題数は約50問です。

受験は全国のテストセンターまたはオンラインで可能です。
詳しい情報は、LPI-Japanの公式サイトをご覧ください。

## 3. 受験の動機

私は現在、業務でAmazon Redshiftを使用しており、データの確認や加工にクエリを利用しています。RedshiftはPostgreSQLをベースにしているため、PostgreSQLに関する理解を深めることで業務効率を向上させられると考えました。

また、入社したばかりで経験が浅いため、資格を通じて基礎知識を強化し、早く業務に慣れることを目指しました。資格取得を通じて、エンジニアとしての成長を期待しています。

## 4. 学習方法（勉強時間：3週間）

試験合格のために取り組んだことは以下の3つです。

1. **公認テキストを読み込む**  
   まずは「OSS教科書 OSS-DB Silver Ver.3.0対応」を一通り読みましたが、初心者には難しい部分が多かったです。完璧を目指さず、早めに問題演習に取り組むことを意識しました。

2. **Ping-tで問題を解く**  
   テキストを読み終えた後、資格学習サイトPing-tを利用して問題演習を進めました。Ping-tは多くの資格試験の問題を提供しており、特にOSS-DB Silverに関する問題集は有料ですが、非常に充実しています。

   - **問題演習の流れ**  
     - 1周目：テキストを辞書代わりにして問題を解き、解説を読みました。理解できない部分はChatGPTなどでさらに調べました。
     - 2周目：何も見ずに問題を解いて知識の定着を図りました。
     - 3周目：誤った選択肢の理由をしっかり読み込み、理解を深めました。

3. **ローカル環境にPostgreSQLをインストール**  
   実際に手を動かすことが最も重要だと感じたため、PostgreSQLをローカルにインストールし、実際のコマンドやクエリを実行しました。問題で出題されたクエリを実行し、結果を確認することで理解が深まりました。

## 5. 資格取得のメリット

資格取得によるメリットは以下の3つです。

1. **データベースの知識向上**  
   OSS-DB Silverの学習を通じて、データベースの基本知識やPostgreSQLの技術を段階的に学び、自信を持って業務に取り組めるようになりました。

2. **タスクの理解度と推進力の向上**  
   PostgreSQLやSQLの理解が深まることで、業務でのデータ関連タスクにスムーズに対応できるようになりました。
   具体的なタスクを通じて、資格勉強の成果を実感しました。

3. **自己肯定感の向上**  
   資格を通じて自分の技術力や知識を客観的に証明できたことで、自信がつきました。目に見える成果があることで、さらなる学びへの意欲も高まりました。


## 6. おわりに

ここまでお読みいただき、ありがとうございました。
エンジニアとしての成長には実務経験が重要ですが、
新人としては経験を積むのに時間がかかります。
そのため、資格を取得し、実務に役立つ知識を体系的に学びながらスキルを高めていきたいと考えています。今後も前向きに学び続けていきたいと思います。


## 7. 参考文献
https://www.shoeisha.co.jp/book/detail/9784798180311

https://mondai.ping-t.com/g/contents/premium_plan_introduction

https://oss-db.jp/outline
fargate に ECS Exec を利用してコンテナログインした際にvimを利用すると表示がずれる事象の解消方法

## この記事の対象とする方
fargate に ECS Exec を利用してコンテナログインした際にvimを利用すると表示がずれてしまって困ってる方

## 結論
xtermをインストールしましょう

```
apt install xterm
```
※debian,ubuntuの場合


## 設定

xterm をインストールすると利用できる、resizeコマンドを実行すると、現在開いているターミナルの幅と高さが設定されます。

```
root@fargate:/# resize
COLUMNS=281;
LINES=58;
export COLUMNS LINES;
```

これをログイン時に実行する場合、 ~/.bashrc などに設定してください。

vi ~/.bashrc
```
PATH=/opt/homebrew/bin:$HOME/bin:$PATH
alias ll="ls -la"

resize &>/dev/null ← 追記
```

これで、 fargate に ECS Exec でコンテナログインしてvimを利用しても表示ずれなく利用できます。

※実際の設定は、docker構成に組み込むことになると思います。
【Vue3・TypeScript・Vite】Docker環境構築時、localhostが立ち上がらない躓き

# はじめに
Vue3・TypeScript・Viteの環境構築をDockerで行っていた際、Vueが起動しないエラーに遭遇しました。

# 問題
下記の記事を見ながら、Vue3・TypeScript環境をvite・Dockerで構築し、コンテナの起動までうまくいったが、なぜかlocalhostにアクセスすると下記の画像のようにVueの画面が表示されなかった。

https://qiita.com/genimura/items/88742085294bd0b234a6#dockerfile%E3%81%AE%E4%BD%9C%E6%88%90

![スクリーンショット 2024-09-25 20.48.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533753/c5fe2350-de4d-5de0-d763-e72cef2069c1.png)

# 解決方法
vite.config.tsに下記のコードを追加する。

``` typescript:vite.config.ts
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    vue(),
  ],
  // 下記を追加
  server: {
    host: true, // これにより外部からのアクセスが許可
    port: 5173, // ポート番号
  },
  
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  }
})

```
上記の２行追加後、

![スクリーンショット 2024-09-25 20.54.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3533753/eb228f02-8638-6777-0fd8-b8457439ba7a.png)

## なぜhost: trueを追加したらうまくいったのか？
GPTさんにも助けてもらいながら、理由を理解しました。

コンテナ内部の開発サーバー（Vite）が、外部からのアクセスを許可する設定になったため.

### 1. デフォルトのホスト設定（localhost）による制限

VueやViteで開発サーバーを起動すると、デフォルトでは開発サーバーはlocalhost（127.0.0.1）にバインドされる。
なので、サーバーが動いているPC自身からしかアクセスできないようになっている。

#### •Dockerコンテナ環境
Dockerコンテナは、ホストマシンとは別の仮想的なネットワーク空間で動作している。
この場合、localhostにバインドされた開発サーバーには、ホストマシンからはアクセスできない。

:::note info
Dockerコンテナ内のlocalhostには、ホストマシン（PC）からアクセスできない
:::

### 2. host: trueで外部アクセスを許可
vite.config.tsでhost: trueを設定することで、Viteの開発サーバーが**0.0.0.0**にバインドされるようになる。

0.0.0.0にバインドすると、Dockerコンテナの内部だけでなく、ホストマシンや同じネットワーク内の他のデバイスからもアクセスできるようになる。
これにより、ホストマシンのlocalhostにアクセスすると、コンテナ内で動作しているViteサーバーに接続できるようになる。

# まとめ
1.	デフォルトでViteサーバーはlocalhostにバインドされていたため、ホストマシンからアクセスできなかった。
2.	vite.config.tsでhost: trueを設定することで、サーバーが0.0.0.0にバインドされ、ホストマシンや他のデバイスからアクセス可能になった。
GASを使ってTodoist APIでタスクを更新する方法

[前回の記事](https://qiita.com/mimuramasato/items/d630a8b9bf0841ef3c87)では、Google Apps Script（GAS）を使ってTodoistのタスクを取得する方法について解説しましたが、今回はその続きとして、タスクを更新する方法について紹介します。REST APIとSync APIを使ったタスクの更新方法をそれぞれ見ていきましょう。

## REST APIでタスクを更新する

まず、TodoistのREST APIを使ってタスクを更新する方法です。特定のタスクIDを指定して、そのタスクの情報を更新します。更新内容は`updateData`オブジェクトとして渡され、APIリクエストに含まれます。

```javascript
// REST APIでタスクを更新する関数
function updateTaskInREST(taskId, updateData) {
  const url = `https://api.todoist.com/rest/v2/tasks/${taskId}`;
  _fetchFromTodoistAPI(url, 'post', updateData);
  Logger.log(`Task ${taskId} successfully updated in REST API.`);
}
```

### 関数のポイント
- **taskId**: 更新対象のタスクのIDを指定します。
- **updateData**: 更新するフィールドと値を含むオブジェクトです。例えば、タスクの名前や期日などを変更する際に使用します。
- **POSTリクエスト**: REST APIではタスクの更新に`POST`メソッドを使います。
- **APIリクエストの送信**: `_fetchFromTodoistAPI`関数を用いて、リクエストを送信します。

### 使用例
例えば、以下のようにして特定のタスクの名前を更新できます。

```javascript
const taskId = '1234567890'; // 変更するタスクのID
const updateData = { content: 'Updated task name' };
updateTaskInREST(taskId, updateData);
```

上記の例では、タスクの名前を「Updated task name」に変更します。

## Sync APIでタスクを更新する

次に、Sync APIを使ってタスクを更新する方法です。Sync APIを使うと、より複雑な操作が可能になります。ここでは、Sync APIに「commands」オブジェクトを送信し、タスクを更新するリクエストを行います。

```javascript
// Sync APIでタスクを更新する関数
function updateTaskInSync(taskId, updateData) {
  const url = "https://api.todoist.com/sync/v9/sync";
  const payload = {
    "commands": [{
      "type": "item_update",
      "uuid": Utilities.getUuid(),  // 一意の識別子を生成
      "args": Object.assign({ "id": taskId }, updateData)
    }]
  };
  _fetchFromTodoistAPI(url, 'post', payload);
  Logger.log(`Task ${taskId} successfully updated in Sync API.`);
}
```

### 関数のポイント
- **commands**: Sync APIでは「commands」という形式で一連の操作を指定します。ここでは`item_update`というコマンドでタスクの更新を行います。
- **uuid**: リクエストごとに一意の識別子（UUID）を生成して設定します。これにより、リクエストの重複を防ぐことができます。
- **args**: 更新するタスクIDと、そのタスクに対する更新内容を指定します。

### 使用例
Sync APIを使った例も、REST APIと同様にタスクの名前を変更することができます。

```javascript
const taskId = '1234567890'; // 変更するタスクのID
const updateData = { content: 'Updated task name with Sync API' };
updateTaskInSync(taskId, updateData);
```

この例では、Sync APIを使ってタスクの名前を「Updated task name with Sync API」に変更しています。

## REST APIとSync APIの使い分け

- **REST API**: 単純なタスクの操作や軽量なリクエストを行いたい場合に適しています。タスクの取得や単一のタスクの更新にはこちらが便利です。
- **Sync API**: 同時に複数のタスクを操作したり、リクエストの整合性を保つためにUUIDを管理したりする必要がある場合に適しています。大量のデータや複雑な操作を行う際に力を発揮します。

## まとめ

この記事では、Google Apps Scriptを使ってTodoist API経由でタスクを更新する方法について説明しました。REST APIとSync APIの違いを理解し、状況に応じて適切な方法を選択することで、Todoistのタスク管理がより柔軟になります。
【Python】スライス理解の仕方

Pythonエンジニア認定基礎試験の勉強をしていたところ、
リストのスライスについて躓いたのでメモとして残します。

## スライスとは
下記の通り、開始・終了・ステップを指定することで、リスト（厳密にはシーケンス型）の一部を切り取ることができる記法。

```python
list[start:stop:step]
```

## 公式ドキュメントでの説明

公式ドキュメントでは下記の通り。

>a[i:j:k] は、 x = i + n*k, n >= 0 かつ i <= x < j であるようなインデクス x を持つような a 全ての要素を選択します。

https://docs.python.org/ja/3.12/reference/datamodel.html#sequences

## よくある説明
Pythonチュートリアルをはじめ、初学者向けには下記のように説明されることが多い。

下記の通り、各要素の区切り線に番号をふり、
startとstopで指定された区間に含むものを切り取るという考え方です。

>スライスの使い方をおぼえる良い方法は、インデックスが文字と文字の あいだ (between) を指しており、最初の文字の左端が 0 になっていると考えることです。そうすると、 n 文字からなる文字列中の最後の文字の右端はインデックス n となります。例えばこうです:

```
 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1
```
https://docs.python.org/ja/3/tutorial/introduction.html#lists

## よくある説明の問題点
一見、この説明でほとんどのケースでは問題ありませんが、
stepが負となるケースについては下記の通り、
説明することができません。

```python
list = ['P','y','t','h','o','n']
print(list[5:1:-1])   #['n', 'o', 'h', 't']
```

## たどり着いた理解の仕方

そこで、自分であればどう説明するかと考えたのが下記の理解。

### 各パラメータの意味

start: 開始位置のインデックス(この点を含む)
end:終了位置のインデックス（この点は**含まない**）
step:何個横にずらして値を取得するか(初期値1)

要点としては、下記の通り、区切り線ではなくインデックスで理解をする

```
 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
   0   1   2   3   4   5   6
  -6  -5  -4  -3  -2  -1
```

### スライス操作のイメージ
1. startとendを比較し、区間に値が含まれるか判定する
    - stepが正の場合は `start < end`、負の場合は `end < start`　であればOK
    - 条件を満たさない場合は、空(`[]`)を返す
1. startの値と、startの値にstepを足し続け、「end**以上**」となる**一つ手前**まで値を取得する

### 例：
#### サンプル1（stepが正の場合）
```python
list = ['P','y','t','h','o','n']
print(list[1:5:2])   
```
1. `step > 0` かつ `start < end` なのでOK
1. `list[1]`の`y`を取得
1. [1]にstepの2を足すと[3]となる。[3]はend未満なので、`list[3]`の`h`を取得
1. [3]にstepを足すと、[5]となるが、[5]はendと等しくなるので取得しない

よって`['y','h']`

#### サンプル2（stepが負の場合）
```python
list = ['P','y','t','h','o','n']
print(list[5:1:-1])   
```
1. `step < 0` かつ `start > end` なのでOK
1. `list[5]`の`n`を取得
1. [5]にstepの-1を足すと[4]となる。[4]はend未満なので、`list[4]`の`o`を取得
1. [4]にstepの-1を足すと[3]となる。[3]はend未満なので、`list[3]`の`h`を取得
1. [3]にstepの-1を足すと[2]となる。[2]はend未満なので、`list[2]`の`t`を取得
1. [2]にstepを足すと、[1]となるが、[1]はendと等しくなるので取得しない

よって`['n','o','h','t']`

#### サンプル3（startとendの関係性が逆の場合）
```python
list = ['P','y','t','h','o','n']
print(list[5:1:3])   
```
1. `step > 0` だが `start < end` ではない。したがって、空

よって`[]`




## おまけ（ChatGPTによる説明）

>基本構文：
start: スライスを開始するインデックス（最初の要素は0）。省略するとリストの最初から始まります。
end: スライスを終了するインデックス。このインデックスの要素は含まれません。省略するとリストの最後まで取得されます。
step: 要素を何個飛ばしで取得するかを指定します。省略すると1（順番に取得）になります。

案外わかりやすい気もします。。。。
Apple Script と Automator を使って Notionでの学習を効率化する

## 動機
- macで勉強するとき、見知らぬ単語があったらストックしたい  
- ストック先はNotionのデータベースがいい
- 意味もついでに入力したい
## 手順
### 下準備
データを格納するNotion Databaseを作成します。 
コードをそのまま動かすには、
![スクリーンショット 2024-09-25 21.02.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894679/05314eb5-6134-6e81-bb5c-62577d00b10a.png)
のようなデータベースにしてください。

1. Automatorを開きます。
2. 「新規書類」を選択し、「クイックアクション」を選びます。
3. 左上の検索欄で「AppleScript」と入力します。
その下に「AppleScriptを実行」という項目が出てくるので、ダブルクリックするか、右のエリアにドラッグ&ドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894679/96ac931a-e649-fb0c-bcd5-13183433dc41.png)
4. 「ワークフローが受け取る項目」を「テキスト」に設定します。
5. 「アプリケーション」を「任意のアプリケーション」に設定します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894679/2d0e07ab-e561-e552-e679-44337a2ebe1d.png)

6. 左側のライブラリから「AppleScriptを実行」アクションを探し、ワークフロー領域にドラッグ＆ドロップします。
7. 「AppleScriptを実行」アクション内のスクリプト領域に、下記のコードを貼り付けます
※NOTION_TOKEN_ID, DATABASE_IDについては,自分のtoken id, database idに変更。
参考)
Notion token ID : [NotionAPIインテグレーション - 内部インテグレーションの作成](https://www.notion.so/ja/help/create-integrations-with-the-notion-api)を参考に取得してください。  
DATABASE_ID : 追加先のdatabaseのurlの以下の部分です。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3894679/b342c64a-2a5f-89aa-825d-2c5da0b7c3de.png)
(引用：https://developers.notion.com/reference/retrieve-a-database)
インテグレーションと接続するのを忘れないようにしましよう。接続方法については、https://zenn.dev/kou_pg_0131/articles/notion-api-usage の記事が詳しいです。
8. クイックアクションを名前をつけて保存
8. 任意のアプリケーションで文字を選択し、上でつけた名前が右クリックメニューに表示されることを確認してください。
```applescript
on run {input, parameters}
	set selectedText to input as text
	
	-- ユーザーに説明の入力を求める
	set descriptionText to text returned of (display dialog "この項目の説明を入力してください:" default answer "")
	
	-- Notionのデータベースに追加するためのAPIリクエストを作成
	set notionToken to "NOTION_TOKEN_ID"
	set databaseId to "DATABASE_ID"
	
	-- JSONデータをエスケープ
	set escapedText to do shell script "echo " & quoted form of selectedText & " | sed 's/\"/\\\\\"/g'"
	set escapedDescription to do shell script "echo " & quoted form of descriptionText & " | sed 's/\"/\\\\\"/g'"
	
	set curlCommand to "curl 'https://api.notion.com/v1/pages' " & ¬
		"-H 'Authorization: Bearer " & notionToken & "' " & ¬
		"-H 'Content-Type: application/json' " & ¬
		"-H 'Notion-Version: 2022-06-28' " & ¬
		"--data '{\"parent\": {\"database_id\": \"" & databaseId & "\"}, " & ¬
		"\"properties\": {" & ¬
		"\"Name\": {\"title\": [{\"text\": {\"content\": \"" & escapedText & "\"}}]}, " & ¬
		"\"tag\": {\"multi_select\": [{\"name\": \"word\"}]}, " & ¬
		"\"Description\": {\"rich_text\": [{\"text\": {\"content\": \"" & escapedDescription & "\"}}]}" & ¬
		"}}'"
	
	-- APIリクエストを実行
	set apiResponse to do shell script curlCommand
	
	-- レスポンスを解析してエラーチェック
	if apiResponse contains "error" then
		display dialog "エラーが発生しました: " & apiResponse buttons {"OK"} default button "OK" with icon caution
	else
		display notification "単語「" & selectedText & "」がNotionデータベースに追加されました。"
	end if
	
	return input
end run
```
GASでTodoist APIにアクセスしてタスクを取得する方法

Google Apps Script（GAS）を使ってTodoist APIにアクセスし、タスクの取得を行う方法をご紹介します。REST APIとSync APIを使用し、それぞれからタスクを取得するサンプルコードです。

## スクリプトプロパティにAPIトークンを設定

まず、Todoist APIを使用するためには、APIトークンが必要です。スクリプトプロパティにトークンを保存しておきましょう。

```javascript
// Todoist API トークンの取得
const TOKEN = PropertiesService.getScriptProperties().getProperty('TODOIST_API_TOKEN');
```

## トークンの確認

次に、APIトークンが存在するか確認する内部関数を定義します。

```javascript
// APIトークンの存在を確認する関数（内部関数）
function _checkToken() {
  if (!TOKEN) {
    throw new Error('API Token is not set. Please set TODOIST_API_TOKEN in Script Properties.');
  }
}
```

## 共通オプションの設定

APIへのリクエストの際に使用する共通オプションを設定する関数です。`method`を引数として受け取り、リクエストの種類（GETやPOSTなど）に応じたオプションを返します。

```javascript
// 共通のオプション設定関数（内部関数）
function _getCommonOptions(method) {
  return {
    'method': method,
    'headers': {
      'Authorization': 'Bearer ' + TOKEN,
    }
  };
}
```

## Todoist APIへのリクエスト関数

Todoist APIへリクエストを送信する共通関数です。POSTリクエストの場合は、リクエストボディとして`payload`を指定し、JSON形式で送信します。また、POSTの際には一意のリクエストIDをヘッダーに追加します。

```javascript
// Todoist APIへの共通リクエスト関数（内部関数）
function _fetchFromTodoistAPI(url, method, payload = null) {
  _checkToken(); // トークンの確認

  const options = _getCommonOptions(method);
  
  // POSTリクエストの場合、payloadを設定
  if (payload) {
    options.payload = JSON.stringify(payload);
    options.headers['Content-Type'] = 'application/json'; // JSONデータとして送信
  }
  
  // X-Request-Id を POST のみで追加
  if (method === 'post') {
    options.headers['X-Request-Id'] = Utilities.getUuid(); // 一意のリクエストIDを生成
  }

  try {
    const response = UrlFetchApp.fetch(url, options);

    if (![200, 204].includes(response.getResponseCode())) {
      throw new Error(`Failed to perform ${method.toUpperCase()} request: ${response.getResponseCode()}`);
    }

    return response.getContentText() ? JSON.parse(response.getContentText()) : null; // 応答があれば解析
  } catch (error) {
    Logger.log(`Error in ${method.toUpperCase()} request: ` + error.message);
    Logger.log(error.stack); // スタックトレースをログに出力
    return null;
  }
}
```

## REST APIから全タスクを取得

TodoistのREST APIを使用して全タスクを取得する関数です。この関数では、GETリクエストを使用してタスクを取得します。

```javascript
// REST APIから全タスクを取得する関数
function getAllTasksFromREST() {
  const url = 'https://api.todoist.com/rest/v2/tasks';
  return _fetchFromTodoistAPI(url, 'get') || [];
}
```

## Sync APIから全タスクを取得

TodoistのSync APIを使用して全タスクを取得する関数です。Sync APIは全リソースを同期するため、全てのタスク情報を取得することが可能です。

```javascript
// Sync APIからタスクを取得する関数
function getTasksFromSync() {
  const url = "https://api.todoist.com/sync/v9/sync";
  const payload = {
    'sync_token': '*',  // 全タスクを取得
    'resource_types': '["items"]'
  };
  const result = _fetchFromTodoistAPI(url, 'post', payload);
  return result ? result.items : [];
}
```

## まとめ

このコードでは、TodoistのAPIを用いてタスクを取得する方法を示しました。REST APIは基本的なタスク情報の取得に使用でき、Sync APIはより多くの情報を一度に取得できる強力な方法です。

APIトークンはスクリプトプロパティで管理し、セキュリティを確保しながらGASで簡単にTodoistのデータを操作できます。
paizaラーニング問題集「【連続列】最長減少連続部分列」を解いてみた

https://paiza.jp/works/mondai/dp_primer/dp_primer_lis_continuous_boss

▼考え方：

考え方は、前問「最長増加連続部分列」とほぼ同じです。

異なる点は、以下の2点です。

①リストa[0]に201を代入したこと（201は身長の最大値より大きい値）。人が1(n=1)のときでも計算できるようにするためです。

②人a_i-1と人a_iに逆背の順が成立するならば、dp[i] = dp[i-1] + 1とした点。（dp[i-1]には、人a_i-1以前において、逆背の順が成立した人数が格納されている。）

▼コード：
```py
########## 処理0(準備) インプット,リスト定義など ###########

n = int(input())

a = [0]*(n+1)
a[0] = 201

########## 処理1 漸化式の定義、計算、出力 ##########

dp = [0]*(n+1)

for i in range(1,n+1):
    a[i] = int(input())

for i in range(1,n+1):

    if a[i-1] >= a[i]:
        dp[i] += dp[i-1] + 1
    else:
        dp[i] = 1

print(max(dp))
```

▼気づいたこと：

解答コード例をみるとdp[0]=1でした。私はdp[0]=201としたため、考え方が異なるかもしれません。確認したいと思います。
Windows初期設定&作業コマンド&参考Note【SAP BASIS向け】

作業でよく使う情報の備忘録です。SAPシステム構築を前提として書いています。※随時更新

■初期設定
TCP-IP有効化確認：SQL構成マネージャー ->ネットワーク構成->プロトコル

ユーザ作成(administrators追加)

EBS初期化(AMIからリストア時)
ドライブ確認
wmic diskdrive get size,deviceid

初期化コマンド
fio --filename=\\.\PHYSICALDRIVE0  --rw=read --bs=128k --iodepth=32 --direct=1 --name=volume-initialize

■SAP
移送依頼
移送依頼番号確認(SQL)
SELECT TRKORR FROM <SID>.<sid>.E070L;

移送依頼番号変更(SQL)
UPDATE <SID>.<sid>.E070L SET TRKORR = '<移送依頼番号>' WHERE LASTNUM = 'TRKORR';

■ツール準備
Eclipse
ABAP Development Tools
参考：https://tools.eu1.hana.ondemand.com/
HANA Studio
LINUX初期設定&作業コマンド&参考Note【SAP BASIS向け】

作業でよく使う情報の備忘録です。SAPシステム構築を前提として書いています。※随時更新

■初期設定
ホスト名
hostname

IPアドレス
hostname -i

OS確認
cat /etc/*-release

カーネルのバージョン確認
uname -a

AWSインスタンスタイプ確認
curl http://169.254.169.254/latest/meta-data/instance-type

CPU
lscpu

メモリ
free -h

ファイルシステム
df -h

スワップ
swapon --show

1597355 - スワップ領域の推奨事項 (Linux)

hosts
確認
cat /etc/hosts

バックアップ
cp -p /etc/hosts /etc/hosts.org

fstab
cat /etc/fstab

マウント
アンマウント(強制)
umount -l <ディレクトリ>

ユーザ
cat /etc/pw

ユーザグループ
cat /etc/group

タイムゾーン設定

疎通確認

エイリアス設定ll
echo "alias ll='ls -al'" >> ~/.bashrc
source ~/.bashrc

■作業
SUM実行
./sapinst SAPINST_STACK_XML=<XML>

■AWS
EBS初期化(AMIからリストア時)

インスタンスタイプ確認
MarkDownとその他記述法について比較してみた

## はじめに
こんにちは、ふとMarkDown記法について執筆してみようかと気が向いたので自分で使用し感じた点を比較してみました。

MarkDownは、私たちのようにQiitaで執筆していると非常に身近な存在ですが、社会全体で見ればまだまだ使用頻度の低いマークアップ言語です。

(ちなみにタグ付けは少々ゴリ押ししました、ご了承下さい。)

## 比較対象
今回の記事では以下の3つの記法を比較していきます。
- ビジュアル編集(**Microsoft Word**, Libre Office Writer...)
- MarkDown記法(**Qiita**, Visual Studio Code...)
- Wiki文法(**Wiki Pedia**, 社内Wiki...)

::: note
この記事では箇条書きの太字になっているツールをベースに比較を行います。

なお、Wiki文法についてはほとんど触れた事がないため最低限の知識ですが、お許しください。
:::

## 共通点
まずはじめに、それぞれで共通している点を炙り出しておきましょう。後述の利点・欠点それぞれで重ならない部分があります。その共通点で自分のしたいことが全て満たせるのであれば好きなエディターを使用すれば良いのです。

共通点として、太字にしたり斜体にしたりなど基本的な操作は全てエディター上のツールバーで行えます。
また全てWeb上での編集が可能です。専用ソフトを端末に導入することなく編集が開始できます。

## 利点
次にそれぞれにおける利点を比較します。

### ビジュアル編集
ビジュアル編集では、画像の挿入とその移動が容易である事や文字の大きさをpt単位で微調整できます。

また、他2つでは不可能な**左揃え/右揃え/中央揃え/両端揃えの変更が可能**である事は非常に大きいかと思います。

また、印刷レイアウトに対応しているため特殊な設定等は行わずに印刷が可能です。

またビジュアル編集した文書はローカルに直接保存が可能で、自動保存にも対応しているため、Web上・アプリ上関係なく編集可能であるのが良いですね。

### MarkDown記法
MarkDown記法では、基本的にマウスを操作する事なく文書を完成させる事ができ、非常に効率的な文書作成が可能です。

MarkDownでも`.md`ファイルでローカルへの保存が可能であり、Qiitaなどでは自動保存が利用可能です。

また、Wiki文法と比較したとき、特殊記法のところの文字数が少なく、間違えにくい点は良いです。

画面サイズによって異なりはしますが、基本的に編集画面とプレビュー画面で分かれており、**リアルタイムで**編集状況が確認できるため特殊記法のミスに気付きやすいです。

### Wiki文法
Wiki文法では、画像挿入の際にオプションで右揃え/中央揃え/左揃えとサイズを指定できます。

また、更新後のWikiエディターでは特殊記法の部分がその文法指示に従って表示されるため、ミスには気付きやすいかと思います。

他にもミスを執筆者でない人が訂正できる、又はいつでも情報を更新できるというのは、この情報の流れが速い時代には重要な要素だと思います。

## 欠点
利点があるということは無論、欠点も存在します。それぞれの欠点を見ていきましょう。

### ビジュアル編集
ビジュアル編集は機能が多く、そのうえ直感的な操作で完結できますが、ビジュアル編集ではマウス操作はキーボードの操作に付き物です。つまり手を固定して作業する事ができないため、作業効率が低くなります。

また画像挿入に関しても、**印刷レイアウトに対して位置が固定される**ため、文章を変更したとき、写真の位置が狂ってしまい、微調整に苦しむなんてこともあるでしょう。

他2つは他の文章との前後関係を崩さない位置固定のため、この点は劣ると言えるでしょう。

そしてなにより、コマンドや機能が逆に多すぎ(溢れてい)るため、あまり使わない機能などは「あれどこだっけ…？」ってなってしまいます(笑)

### MarkDown記法
前述の通り、`.md`ファイルで保存が可能なものの、このファイルをOSネイティブで開くと、以下のように表示されてしまいます。
```:例
## 実施要項
日時:◯月◯◯日(□曜日)
集合:**13:00** @□□ビル前
<font color=red>**絶対遅れるな！5分前には集合！**</font>
```
本来ならタイトルを大きく表示したり、赤い太文字で表示したかったりする所の特殊記法の記号をそのまま表示します。

その上、まだ対応アプリが少なく、しかも保存したファイルを直接アップロードできるソフトは少ないため、**GitHubに保存し、GitHubリポジトリとの連携に対応したMarkDownエディターから読み込む**などの方法を取らなければいけません。

### Wiki文法
WikiにはWeb上で執筆し、そのまま推敲を行なった後共有するという1連の流れでセットとなっています。そのため、長い文書を書こうとしたとき、保存できないという問題があります。(他の媒体を通して保存する必要がある)

また、以下のようにMarkDownよりも多い特殊記法の記号を入力する必要があります。
```:例
== Wiki文法の欠点 ==
Wiki文法では入力する際にボールドでは'''太字'''、
イタリックでは''斜体''、であり、
両方を使用するとき、MarkDownでは***太字斜体***であるのに対し、
Wikiでは'''''太字斜体'''''となります。

エディターでのスタイリッシュさに欠ける一面があります。
```
Wiki文法では**とにかく文字数が増えやすい**ため、記号の数をミスしたり、若干の見にくさを感じる方もいるでしょう。

## おわりに
今回は3種類の文章を記述する手段を比較してきました。

個人的にはMarkDownがシンプルなので、1番好みですが皆さんはどうでしょう。

そしてWiki文法なんて久しぶりに使用しましたけど(この記事を書くためだけに3時間くらいWikiを触って感覚を思い出していました 笑)、改めてMarkDownの便利さを実感しました。

なにか追加の意見などあればお気軽にコメントください、お待ちしております。

それではまた〜
AES暗号(ECB/CBC/CTR/XTS)

ファイルを暗号化した時、AES暗号を使用したのですがECB、CBC、XTSなど複数あり、暗号化の方法など違いが分かっていなかったので、調査しました。


# 目次
1. 暗号利用モード
1. AES暗号
    1. ECB
    1. CBC
    1. CTR
    1. XTS
1. まとめ
1. 参考にしたサイト

## 1. 暗号利用モード
　暗号利用モードとは、ブロック暗号[^1]を利用してブロック長よりもメカニズムのことです。
　暗号利用モードには、秘匿用のモードと、データの秘匿性、完全性および認証制を同時に提供する認証用のモードがあります。
　
## 2. AES暗号
　AESはAdvanced Encryption Standardの略で、高いセキュリティ性と高速性を備えた暗号化アルゴリズムとして広く知られています。
　AES暗号化は共通鍵暗号方式の一種で、同じ鍵を使用して暗号化と復号を行います。
　鍵の長さを128ビット、192ビット、256ビットの3種類から選択することができます。長いほうが解読される可能性は低くなるというメリットはありますが、その分暗号化と復号の処理にかかる時間が増えるというデメリットもあります。
　今回使用したECB、CBC、CTR、XTSについて暗号化の方法などの違いを調べました。

### 1. ECB
　ECBはElectronic Codebookの略で、もっとも単純な暗号利用モードです。
　128ビットのデータブロックごとに同じ暗号化キーを使用して暗号化します。
　プレーンテキストと呼ばれる暗号化されていない同じブロックのデータが同じ方法で暗号化されるため、データパターンを隠せず、セキュリティ上の脆弱性があります。

 <img width="500" alt="CBC_encryption" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871987/8e4657ae-1af0-3bc4-25a9-53bc89310c55.png">

>画像引用元: wikipedia
https://ja.wikipedia.org/wiki/%E6%9A%97%E5%8F%B7%E5%88%A9%E7%94%A8%E3%83%A2%E3%83%BC%E3%83%89
  
### 2. CBC
　CBCはCipher Block Chainingの略で、最も広く用いられている暗号利用モードです。
　ECBの弱点を解決するため、プレーンテキストの各ブロックは前の暗号文とのXORを取ってから暗号化されます。
　各々の暗号文ブロックはそれ以前のすべての平文ブロックに依存することとなり、メッセージごとのユニーク性を確保するため、最初のブロックの暗号化には初期化ベクトル[^2]が用いられます。

 #### 暗号化の流れ
 
 <img width="500" alt="CBC_encryption" src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/80/CBC_encryption.svg/1024px-CBC_encryption.svg.png">

>画像引用元: wikipedia
https://ja.wikipedia.org/wiki/%E6%9A%97%E5%8F%B7%E5%88%A9%E7%94%A8%E3%83%A2%E3%83%BC%E3%83%89

### 3. CTR
　CTRはブロック暗号を同期型のストリーム暗号[^3]として扱う暗号モードです。
 「カウンター」と呼ばれる値を暗号化することで鍵ストリームブロックを生成します。
 カウンターは単調増加であり値の重複がなければどのような関数でも用いることができます。1ずつ増加するものがもっとも単純でありもっとも一般的です。

#### 暗号化の流れ
 <img width="500" alt="CBC_encryption" src="https://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/CTR_encryption_2.svg/601px-CTR_encryption_2.svg.png">

>画像引用元: Kingston
https://www.kingston.com/jp/blog/data-security/xts-encryption

### 4. XTS
　XTSは最新のブロック暗号モードで、IronKey ドライブで使用されています。
　2つの独立したAESキーを使うため、２重暗号化と近い状態になります。
　各ブロックが独立していてチェーニングを使用しないため、保存された暗号文が壊れたとき復元不可能になるデータはそのブロックのみに制限されます。

 <img width="500" alt="CBC_encryption" src="https://media.kingston.com/kingston/content/solutions/ecb-figure4.jpg">

>画像引用元: Kingston
https://www.kingston.com/jp/blog/data-security/xts-encryption

[^1]: 共通鍵暗号の一種。
    固定長のデータ(ブロック)を単位として処理する暗号の総称 
[^2]: ビット列。
    ストリーム暗号またはブロック暗号を任意の暗号利用モードで実行するとき、同じ暗号鍵でストリームを生成しても毎回異なるストリームを生成するのに必要とされる。これにより、毎回暗号鍵を替えるといった時間のかかる作業を省くことができる。
[^3]: 共通鍵暗号の一種。
    暗号の種類の一つで、データを1ビット単位あるいは1バイト単位で逐次暗号化していく方式

## まとめ
　AES暗号化は複数ありますが、ECBは解読されやすいため使わないほうがよく、CBC/CTRはECBの欠点を解消していて広く使用されていることがわかりました。
　最新のブロック暗号モードはXTSで、CBC/CTRよりも強力な暗号化モードです。
 今回調べた以外にも暗号利用モードは種類があるので、必要に応じて使いこなせるようになりたいと思いました。

## 参考にしたサイト
https://ja.wikipedia.org/wiki/%E6%9A%97%E5%8F%B7%E5%88%A9%E7%94%A8%E3%83%A2%E3%83%BC%E3%83%89
https://study-sec.com/aes/#1-1_AES
https://www.kingston.com/jp/blog/data-security/xts-encryption
OutputDebugStringを使ったDebugViewのログ取得

実行ファイルなどのログ取得をしたいときにDebugViewを使うのですが、時間がたつと使い方を忘れてしまうことが多いので、すぐ使えるようにまとめようと思います。

## OutputDebugString
OutputDebugStringを使用したログ取得方法です。
この関数を使用するには、アプリケーションにWindows.hヘッダーを含める必要があります。

```c++
void OutputDebugStringA([in, optional] LPCSTR lpOutputString);
```
lpOutputStringで指定した文字列を取得します。
関数名にDebugと入っていますが、Releaseビルドしたものでも出力されます。

## format

文字列だけをログ表示したい場合は上記の方法で良いですが、値もログ出力したい場合はFormatを使用します。

```c++
namespace std {
  template<class... Args>
  string format(format_string<Args...> fmt, Args&&... args);

  template<class... Args>
  wstring format(wformat_string<Args...> fmt, Args&&... args);

  template<class... Args>
  string format(const locale& loc, format_string<Args...> fmt, Args&&... args);

  template<class... Args>
  wstring format(const locale& loc, wformat_string<Args...> fmt, Args&&... args);
}
```
argsを書式文字列fmtに従って設定し、文字列を返します。

formatはC++20以降で使用できるため、C++17などを使っている場合はC++言語標準を変更する必要があります。
C++言語標準はプロジェクトのプロパティ＞全般のC++言語標準で変更できます。

formatライブラリをインクルードしないと使用できないため、忘れずに追加してください。

```c++
#include <format>
```

以下、aとbの和をログ表示する処理と結果になります。
OutputDebugStringAは

```c++
int a = 5, b = 2;
int sum = a + b; 

auto test = format("sum: {}", sum);
OutputDebugStringA(test.c_str());
```
<img width="500" alt="result" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2871987/31c1cbdd-d0df-3529-aab9-fa31d6134159.png
">


# 参考にしたサイト
https://learn.microsoft.com/ja-jp/windows/win32/api/debugapi/nf-debugapi-outputdebugstringa
https://learn.microsoft.com/ja-jp/windows/win32/api/debugapi/nf-debugapi-outputdebugstringw
https://cpprefjp.github.io/reference/format/format.html
Linux ディストリビューションやバージョンによる標準リポジトリの違い

### はじめに

Linux には様々なディストリビューションがあり、各ディストリビューションごとに独自の標準リポジトリが設定されています。同じディストリビューションでもバージョンによって標準リポジトリの内容や構成が異なります。あるパッケージをインストールしようとしたのに、パッケージが存在しないという経験をされたことがあるのではないでしょうか。
この記事では、`dnf`（または`yum`など）の標準リポジトリがディストリビューションやバージョンによってどのように変わるのか、そして外部リポジトリの追加方法について説明します。

#### 1. 標準リポジトリとは？

標準リポジトリは、各ディストリビューションの開発チームによって管理され、安定性と互換性が確保されたパッケージを提供するためのリポジトリです。これらのリポジトリは、`dnf` や `yum` などのパッケージマネージャを通じてパッケージのインストールやアップデートを行う際に使用されます。

#### 2. ディストリビューションごとの標準リポジトリの違い

各ディストリビューションは独自のリポジトリを持ち、含まれるパッケージやバージョンはそれぞれ異なります。ここでは、主要なディストリビューションについて説明します。

##### 2.1 Amazon Linux

- **Amazon Linux 2**:
  - 標準リポジトリ: `amzn2-core`, `amzn2extra`
  - 安定したパッケージを提供し、公式リポジトリを通じて更新されます。
  - Node.js や PHP などの特定のバージョンをインストールするには、`amzn2extra` リポジトリを有効化する必要があります。

- **Amazon Linux 2023**:
  - 標準リポジトリ: `amazonlinux`
  - `dnf` を使用し、更新されたパッケージを提供します。
  - Amazon Linux 2 に比べて、標準で提供されるパッケージのバージョンが異なります。

##### 2.2 CentOS / RHEL

- **CentOS 7**:
  - 標準リポジトリ: `base`, `updates`, `extras`
  - パッケージマネージャは `yum` を使用。
  - 安定性重視で、比較的古いバージョンのパッケージが多い。

- **CentOS 8**:
  - 標準リポジトリ: `BaseOS`, `AppStream`, `Extras`
  - `dnf` を使用し、リポジトリの構成が CentOS 7 から変更されました。
  - より新しいバージョンのパッケージが含まれています。

##### 2.3 Fedora

- **Fedora**:
  - 標準リポジトリ: `fedora`, `updates`
  - 常に最新の技術を取り入れ、最新のパッケージが提供されます。
  - 開発者や新しい技術を試したいユーザー向け。

##### 2.4 Oracle Linux

- **Oracle Linux**:
  - 標準リポジトリ: Oracle が提供するリポジトリ。
  - RHEL と互換性があり、Oracle 独自のパッケージも提供されています。

#### 3. バージョンごとのリポジトリの違い

同じディストリビューションでも、バージョンが異なるとリポジトリの構成や内容が異なります。

- **CentOS 7 vs CentOS 8**:
  - CentOS 7 では `yum` が使用され、リポジトリ構成はシンプルです。
  - CentOS 8 では `dnf` に変更され、リポジトリの構成も大きく変わり、モジュールストリームや AppStream などが導入されています。

- **Amazon Linux 2 vs Amazon Linux 2023**:
  - Amazon Linux 2 は `amzn2-core` や `amzn2extra` などのリポジトリを使用し、`yum` で管理されます。
  - Amazon Linux 2023 は `amazonlinux` リポジトリを使用し、`dnf` を使ってパッケージ管理を行います。

#### 4. 外部リポジトリの追加

標準リポジトリに含まれていない最新のパッケージや特定のバージョンをインストールしたい場合、外部リポジトリを追加することができます。

##### 4.1 NodeSource リポジトリの追加例

Node.js の最新バージョンをインストールするには、NodeSource リポジトリを追加します。

```bash
# NodeSource リポジトリの追加
curl -fsSL https://rpm.nodesource.com/setup_20.x | bash -

# Node.js 20.x のインストール
dnf install -y nodejs
```

この手順により、標準リポジトリにはない最新の Node.js バージョンをインストールできます。

##### 4.2 EPEL リポジトリの追加例

EPEL（Extra Packages for Enterprise Linux）は、RHEL や CentOS 用の追加パッケージを提供します。

```bash
# EPEL リポジトリの追加
dnf install -y epel-release

# リポジトリの確認
dnf repolist
```

EPEL リポジトリを追加することで、標準リポジトリにはない多くの便利なパッケージをインストールできるようになります。

#### 5. リポジトリの確認方法

現在システムに追加されているリポジトリを確認するには、以下のコマンドを使用します。

```bash
# 有効なリポジトリの一覧を表示
dnf repolist

# すべてのリポジトリ（無効も含む）を表示
dnf repolist all
```

これにより、どのリポジトリがシステムに設定されているかを確認できます。

#### 6. まとめ

- `dnf` の標準リポジトリは、Linux ディストリビューションやそのバージョンによって異なる。
- 標準リポジトリに含まれていないパッケージや最新バージョンをインストールするには、外部リポジトリを追加することが一般的
- 外部リポジトリを追加する際は、その信頼性やセキュリティについて十分に確認することが重要

これで、Linux ディストリビューションやバージョンによって異なる `dnf` の標準リポジトリの仕組みについて理解が深まったと思います。

---
MAUI Tips - AOTCompileエラーが出た場合の対処方法

# 概要
アップデートによってビルドが通らなくなることがよくある.NET MAUIさん。
どこぞの投稿にも、自動アップデートは止めておこうという記載があった💦
それはさておき、片っ端からアップデートしてたら、ビルドが通らなくなった時に起こったエラーと
その時の対処方法を備忘のために記録。

# 起きた現象
何をどこまでどうアップデートかけたか定かでないんですが、
IPAファイルをプロビジョニングしようと思ったら大量のエラーが吐き出される。

1行目のエラーはこんな感じ。

```
usr/local/share/dotnet/packs/Microsoft.iOS.Sdk.net8.0_17.5/17.5.8030/targets/Xamarin.Shared.Sdk.targets(1270,3): error MSB4018: "AOTCompile" タスクが予期せずに失敗しました。 [/Users/XXXXXXXX/Projects/XXX/XXX/XXX.csproj::TargetFramework=net8.0-ios]
```

AOTCompile・・・って？？？
検索してもそれらしい解決策が見つからず・・・。

2行目のエラーはこんな感じ。
めちゃ長い・・・。
やたらとOne or more errors occurred.が表示されてる。
けど、よく見ると、No such file or directoryという文言が。

```
/usr/local/share/dotnet/packs/Microsoft.iOS.Sdk.net8.0_17.5/17.5.8030/targets/Xamarin.Shared.Sdk.targets(1270,3): error MSB4018: System.AggregateException: One or more errors occurred. (One or more errors occurred. (One or more errors occurred. (An error occurred trying to start process '/usr/local/share/dotnet/packs/Microsoft.NETCore.App.Runtime.AOT.osx-arm64.Cross.ios-arm64/8.0.7/Sdk/../tools/mono-aot-cross' with working directory '/Users/XXXXXXXX/Projects/XXX/XXX'. No such file or directory))) (One or more errors occurred. (One or more errors occurred. (An error occurred trying to start process '/usr/local/share/dotnet/packs/Microsoft.NETCore.App.Runtime.AOT.osx-arm64.Cross.ios-arm64/8.0.7/Sdk/../tools/mono-aot-cross' with working directory '/Users/XXXXXXXX/Projects/XXX/XXX'. No such file or directory))) (One or more errors occurred. (One or more errors occurred. (An error occurred trying to start process '/usr/local/share/dotnet/packs/Microsoft.NETCore.App.Runtime.AOT.osx-arm64.Cross.ios-arm64/8.0.7/Sdk/../tools/mono-aot-cross' with working directory '/Users/XXXXXXXX/Projects/XXX/XXX'. No such file or directory))) (One or more errors occurred. (One or more errors occurred. (An error occurred trying to start process '/usr/local/share/dotnet/packs/Microsoft.NETCore.App.Runtime.AOT.osx-arm64.Cross.ios-arm64/8.0.7/Sdk/../tools/mono-aot-cross' with working directory '/Users/XXXXXXXX/Projects/XXX/XXX'. No such file or directory))) [/Users/XXXXXXXX/Projects/XXX/XXX/XXX.csproj::TargetFramework=net8.0-ios]

```

該当フォルダを見てみると、確かに8.0.7のフォルダがない。
代わりに8.0.8のフォルダはある。

.NET Coreのランタイムのインストールリストを見ると

```
.NET Core Runtimes:
  8.0.7   (arm64)  [Used by Visual Studio for Mac or SDKs. Specify individually or use —-force to remove]
  7.0.9   (arm64)              
  7.0.20  (arm64)  [Used by Visual Studio for Mac or SDKs. Specify individually or use —-force to remove]
  7.0.13  (arm64)              
  7.0.10  (arm64)              
  7.0.1   (arm64)              
  6.0.32  (arm64)  [Used by Visual Studio for Mac or SDKs. Specify individually or use —-force to remove]
  6.0.24  (arm64)              
  6.0.21  (arm64)              
  6.0.20  (arm64)  
  6.0.12  (arm64) 
  ```

8.0.8がない。
バージョンの不整合が起きている？

# 実施したこと
ということで、.NETの最新版を再インストールしてみる。
以下のURLからダウンロード
https://dotnet.microsoft.com/ja-jp/download

再度プロビジョニングしたところ、無事IPAファイルが生成できました！

# 余談
エラーは1行目だけじゃなくて2行目以降もちゃんと読もうね💦
web上のJavascriptで作られたボタンをクリックしたい・・・(UWSC or VBS or BAT)

あるホームページの更新を楽しみにしているのですが、
ページ上に更新ボタンなるものがあり、
それをクリックしないと、
更新された記事が読めないようにしてあり、
とても面倒なので、
UWSC や　VBS　や　BAT
で、
直接クリックを思い、色々やってみようと試みたのですが・・・
既に二カ月も経ちました^^;

どなたか、ブックマークレットでも何でも良いので、
ご教示願えませんでしょうか？

ソースなどを確認すると、
ボタンは
javascript:
となっています。。

どうか、宜しくお願いいたします。
AWS NAT Gatewayの使い方(AWSホワイトペーパーから)

## NATゲートウェイとは
簡単に説明するとアドレス変換サービスです。
インターネットと通信をする際にプライベートアドレスでは通信ができないため、インターネットに出る際はNATゲートウェイをかませてアドレスをパブリックアドレスに変換し通信をします。

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-nat-gateway.html

## 料金
AWSを学ぶものなら経験した方もいるかもしれません
個人のアカウントでNATゲートウェイをデプロイしたままにして一か月1万円近く持っていかれたことが。

執筆時の料金
時間あたりUSD 0.062(デプロイ)
処理データ1GBあたりUSD 0.062
放置した場合以下のお金が掛かります。
0.062 x 24 x 30 x 140.5 = 6,271円

しかも障害耐性を上げるためマルチAZにすれば2倍、、
さらにシステムごとにデプロイしてしまうとさらにお金が掛かります、、

ランニングコストは発注側が特に気にしますので設計に関して提案する際はしっかり配慮したいですね

### Tips
:::note info
料金はドル支払いなので長い期間プロジェクトでの見積もりに関しては為替リスクに気を付けたほうがいいです、、
自分が昔いたプロジェクトだととんでもない額になってしまい予算がかなりきついといったことになったりしました。
円安おそるべし
:::

https://aws.amazon.com/jp/vpc/pricing/

## VPCごとにNATゲートウェイ

NATゲートウェイをそれぞれのシステムごとにデプロイするといろいろなデメリットやリスクがある。(もちろんユースケース次第ですが)

簡単にデメリットをあげます。
<dl>
  <dt>料金</dt>
  <dd>上記でも記載しましたがデプロイするごとにランニングコストが膨らみます</dd>
  <dt>セキュリティ</dt>
  <dd>それぞれのシステムで勝手に外部と通信をしてしまう、一元管理ができない</dd>
</dl>


## NAT ゲートウェイ共有
Transit Gatewayを利用して複数のVPCを連携して一つのVPCにあるNAT Gateway利用します。

※以下簡単な構成図
(命名とか線がないとかには突っ込まないでください、ちょっと面倒だった、、)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3473825/6627aaab-c604-177f-b006-8fd0b4a39ac5.png)

もう少し書きたいんですがここで終わりにします。


以下参考
https://docs.aws.amazon.com/ja_jp/whitepapers/latest/building-scalable-secure-multi-vpc-network-infrastructure/building-scalable-secure-multi-vpc-network-infrastructure.pdf