OmniAICreator/Qiita-1.07M huggingface dataset:
【ブロックプログラミング言語】 Trees に、文字幅の設定機能を実装しました

## はじめに

以前、↓ のように書けるプログラミング言語を開発しました。

https://x.com/SnowEsamosc/status/1765309061241983396

「でも、せっかく見やすいのに、全角文字が入ると表示が崩れるやん！」
「罫線文字って、場合によって全角か半角かが変わるんだぞ？」

**対応しました。**

## 新しいコンパイラオプション
:::note info
この章は機種やフォントの設定によって大きく表示が違います。２つパターン(`Half` と `Full`)があるので、**「一番キレイに見えるプログラム」** の方を見ていただければ。
:::
 
### Half
　さて、例えば、以下のTreesコードは正しくコンパイルされます。(そして、「こんにちは！世界！」を出力します。)

```:正しいTreesコード
┌───────┐
│println│
└──┬────┘
 ┌─┴─────────┐
 │"こんにちは！世界！"│
 └───────────┘
```
 
でもこれはあんまりキレイじゃないですね？以下のように書きたいです。

```:全角を考慮したTreesコード (helloworld_half.tr)
┌───────┐
│println│
└───┬───┘
 ┌──┴─────────────────┐
 │"こんにちは！世界！"│ 
 └────────────────────┘
```

コマンドに `--char-width` オプションを渡せば、このプログラムもコンパイルできます！

```terminal: コンパイルするためのオプション
> trees --char-width half "./helloworld_half.tr"
```

### Full 
上記に加えて、**罫線も全角で表示**されていたらどうでしょう？

```:罫線も全角になっているTreesコード (helloworld_full.tr)
 ┌────┐
 │println │
 └──┬─┘
 ┌──┴───────┐
 │"こんにちは！世界！"│
 └──────────┘
```

`--char-width` オプションに`full`を渡せば、このプログラムもコンパイルできます！

```terminal: コンパイルするためのオプション
> trees --char-width full "./helloworld_full.tr"
```

## どうやって全角か半角か決めてるの？

Unicode には、全角表示か半角表示かを決定する附則があります。これを参考にしています[^1]。
[^1]: なお、実装上は、Rustの`unicode-width`クレートに完全に依存しています。

https://www.unicode.org/reports/tr11/

(全角、半角のリスト)：

https://www.unicode.org/Public/UCD/latest/ucd/EastAsianWidth.txt

:::note info
ところが、文字によっては 半角で表示すべきか全角で表示すべきかが決まっていない場合があります。例えば、罫線文字はその代表例です。

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/496507/bbecda5a-3bbb-d060-cff0-3cee667e2c61.png)
> ↑ セミコロンの直後に注目。"A" (Ambiguous) は場合によって全角の場合も半角の場合もあることを示す。

`--char-width` オプションの、`half` はそのような文字を半角として扱い、`full` は全角として扱うという差があります。これでほとんどのケースをカバーできるはずです。
:::



## 終わりに

文字の全角半角のことを全然知らなかったです。こんな風に決まってたんですね。
さて、Trees の GitHubリポジトリを貼っておきます。

https://github.com/Snowman-s/Trees

以上です。以下はおまけです。

--------------------------

### 補足：文字幅が異なるプログラムがごっちゃになるが～？
前の記事で、「Treesはインタプリタ言語で、ソースコードを直接実行するよ」と言いました。であれば、次の疑問が出てくるのは当然です。

**「結局文字コードを統一しなければいけないじゃん」**...と。

↓

実は、この問題に対応するため、すでに Trees は、Javaめいた中間コードを生成して実行するようになっています！[^2]
[^2]: もちろんそれだけではなく、いちいちソースコードを解析するのにコストがかかるため、という理由もありますよ。

以下のコードはコンパイル結果の中間コード(`*.trm`)を出力します
```terminal:コンパイルコマンド
> trees -m compile <ソースコードファイル>
```

ーそうして、プログラム内部で、こうして生成された`*.trm`を利用できます。[^3]

補足は以上です。

[^3]: 詳しくは、GitHubのwikiにある`include` プロシージャの説明を参照。従来通り`*.tr`も利用できます。
I tried RPAChallenge using selenium for python 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812041/a7949a6e-5049-66a4-7391-87a4d83efea1.png)

Hello! My name is Keita.
As a former QA engineer, I am interested in RPA technology.
Therefore, I tried RPAChallenge using selenium for python.

# Technology
I used python on a site called RPAChallenge (https://rpachallenge.com/).

Briefly summarized below.

### selenium
Selenium is automation tool for webapplication test. You can automation operate webblowser without operate in hand.

### panda
Panda is faumous Python tool, Mainly, data operation and analyze.It can oparate Excel data.

### parallel processing
This technology improves processing speed by executing multiple calculations simultaneously.

### not HardCording
Instead of writing fixed values directly in the code, use constants or configuration files for flexible management.

# result
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1812041/39a6e7c5-35dd-ff35-a6bd-a04483eeb22e.png)

At 8 seconds, it is much slower than the others, but it is a success.

# github
You can find the source in the repository below.
I would like to know if there are any improvements.

https://github.com/ketyia1111/RPAChallenge
Linux ソケットの生成から終了までのプロセスを図にしてみた

socket を のび太の引き出しくらいにしか理解してなかったので教科書と chatGPT の力を借りて図にしてみた。

今日の学び
クライアントから見ると、同じソケットにずっと話しかけているのに実は青から緑へと、違うソケットに話しかけることになっている。

間違ってるところはぜひコメントください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24737/2cc03694-8e23-2b80-c633-820ec7a8082b.png)

青も緑も同じlocal ip address/portを共有している。しかしremote側のip address/portが違うので違うものとして識別できる

オレンジのip address/portはremote側のものなんだけど、それがsocketに紐づいていることを表現したくて緑のソケットにくっつけている。うまい表現が思いつかなかった

TCPのFIN/ACKあたりは諸説あるので適当
機能横断チームか、コンポーネントチームか。 ChatGPTで要約

**スクラム**において、**フロントアプリ**と**サーバーアプリ**を1つのチームで開発するか、別々のチームで開発するかは、次のような要素に左右されます。

### **1つのチームで開発する場合**
スクラムは**小規模なクロスファンクショナルチーム**（開発、テスト、デザインなど、必要なスキルを持つメンバーで構成されるチーム）で運営されることが理想です。このため、**フロントエンドとバックエンドのスキルを持つメンバーが1つのチームで協力して開発**を進めることが推奨される場合があります。

#### **メリット**
1. **迅速なコミュニケーション**:
   - フロントエンドとバックエンドの開発者が同じチームにいるため、意思決定や問題解決が迅速に行われます。
   - ユーザーストーリーに対する統一的な理解が得られ、仕様の変更や調整も柔軟に対応できます。

2. **統合された視点での開発**:
   - フロントとバックエンドの機能がシームレスに統合されるため、チーム全体で共通の目標に向かって効率的に作業できます。
   - 1つのチーム内でユーザー体験の全体像を把握しやすくなります。

3. **継続的なデリバリー**:
   - チームがフロントエンドとバックエンドを統一して開発するため、スプリントの最後に**リリース可能なインクリメント**を一貫して提供できます。

#### **デメリット**
1. **スキルの偏り**:
   - フロントエンドとバックエンドのスキルを持つメンバーが少ない場合、1つのチームでの開発は難しくなる可能性があります。
   - 特定の領域にリソースが集中してしまい、作業が遅れるリスクがあります。

2. **複雑なシステムには負荷**:
   - 大規模なシステムや複雑なアーキテクチャでは、すべての技術領域を1チームで対応することが難しくなることがあります。

---

### **フロントエンドとバックエンドを別々のチームで開発する場合**
スクラムの基本的な原則は1つの小規模なチームがすべての作業を担うことですが、複雑なシステム開発においては、フロントエンドとバックエンドを**別々のスクラムチーム**で開発する場合もあります。この場合、**Scrum of Scrums（SoS）**や**Scaled Scrum**のような大規模開発の管理手法が使用されます。

#### **メリット**
1. **専門性の活用**:
   - 各チームがフロントエンドまたはバックエンドに専念できるため、それぞれの領域での専門性が高まり、技術的な深みを追求できます。
   - チーム内の技術的な問題に素早く対処でき、効率的に開発が進められます。

2. **並行作業の効率化**:
   - フロントエンドとバックエンドが異なるチームで並行して進められるため、開発速度が上がる可能性があります。
   - 大規模プロジェクトでは、依存関係が整理されて進捗管理がしやすくなります。

#### **デメリット**
1. **コミュニケーションのコスト**:
   - フロントエンドとバックエンドが異なるチームに分かれることで、チーム間でのコミュニケーションが重要になります。**情報の共有ミス**や**依存関係の管理**に課題が生じることがあります。
   - チーム間の連携を綿密に取らないと、フロントエンドとバックエンドで仕様が噛み合わない問題が発生する可能性があります。

2. **スプリントの調整が必要**:
   - フロントエンドとバックエンドが別々のタイムラインで進む場合、スプリントの終了時にリリース可能なインクリメントを提供するために、調整が必要です。
   - チーム間での調整や同期が求められます。

---

### **結論：スクラムにおける選択肢**
- **小規模または中規模プロジェクト**では、**1つのクロスファンクショナルチーム**がフロントエンドとバックエンドを担当することで、コミュニケーションや調整が容易になるため、これが推奨される場合が多いです。
- **大規模プロジェクト**や**高い専門性が求められる場合**は、**フロントエンドとバックエンドを別々のチームで開発**し、Scrum of Scrums（SoS）などの大規模なプロジェクト管理方法でチーム間の調整を行うのが適切です。

それぞれのアプローチで重要なのは、チーム間の**コミュニケーション**と**調整**が効果的に行われるような仕組みを整えることです。
Pythonでのロギング：logging モジュールの基本と応用

# 概要
Pythonの標準ライブラリである logging モジュールは、プログラムの実行中に詳細な情報を記録するための強力なツールです。特に、デバッグや運用中のエラー検出、情報のトレースに役立ちます。この記事では、現場で使用しているlogging の基本的な使い方をメモします。

# 目次
- logging とは？
- 基本的な使い方
- ログをファイルに保存する方法
- ログフォーマットのカスタマイズする方法
- 複数ファイルにログを分ける方法

# logging とは？
logging モジュールは、Pythonでログメッセージを生成し、コンソールやファイルに出力するための方法です。print() を使ったデバッグよりもはるかに使い勝手が良く、レベルごとにメッセージを整理したり、ログのフォーマットや出力先をカスタマイズできる点が特徴です。

# 基本的な使い方
logging モジュールを使ってログを出力する基本的な方法です。
```python
import logging

# ログの基本設定
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# ログの出力例
logging.debug('デバッグ情報')
logging.info('情報メッセージ')
logging.warning('警告メッセージ')
logging.error('エラーメッセージ')
logging.critical('致命的なエラーメッセージ')
```
- logging.basicConfig(): ログの設定を行うメインの関数です。ここでログのレベルやフォーマットを指定します。
- ログレベル: DEBUG, INFO, WARNING, ERROR, CRITICAL の5つのログレベルがあり、これに応じてメッセージの重要度が変わります。
    - DEBUG: 開発やデバッグ時に役立つ詳細な情報
    - INFO: 通常の動作に関する情報
    - WARNING: 注意すべき動作や状況に関する警告
    - ERROR: エラー発生時のメッセージ
    - CRITICAL: プログラムの継続が危ぶまれる重大なエラー

# ログをファイルに保存する
コンソールに表示されるだけでなく、ログをファイルに記録することができます。ファイルへの出力は、basicConfig() の filename パラメータを使って設定します。
```python
import logging

# ログをファイルに保存する設定
logging.basicConfig(filename='app.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

# ログの出力例
logging.info('ファイルに保存されるログメッセージ')
logging.warning('警告メッセージもファイルに保存されます')
```
## 結果
このコードを実行すると、app.log というファイルにログメッセージが保存されます。ファイルは以下のような形式で出力されます。
```python
2024-10-05 10:00:00,000 - INFO - ファイルに保存されるログメッセージ
2024-10-05 10:00:01,000 - WARNING - 警告メッセージもファイルに保存されます
```
## ログフォーマットのカスタマイズ
logging では、出力されるログメッセージのフォーマットも自由にカスタマイズ可能です。basicConfig() で format パラメータを指定して、ログのフォーマットを設定します。
```python
import logging

# フォーマットをカスタマイズ
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s - [%(asctime)s]')

# ログの出力例
logging.info('フォーマットがカスタマイズされたログ')
```
## 結果
上記の例では、ログレベルとメッセージの後にタイムスタンプを表示するフォーマットを指定しています。
```python
INFO: フォーマットがカスタマイズされたログ - [2024-10-05 10:05:00,000]
```
- %(levelname)s: ログレベル（INFO, WARNING など）
- %(message)s: 実際のログメッセージ
- %(asctime)s: 日時

# 複数ファイルにログを分ける
大規模なシステムでは、エラー用のログファイルと、さらに詳細なエラー情報などとログファイルを分けて管理することが推奨されます。これを実現するには、複数のハンドラーを使ってログの振り分けを行います。
```python
import logging

# ロガーの作成
logger = logging.getLogger('my_app')

# エラーログ用のハンドラー
error_handler = logging.FileHandler('error.log')
error_handler.setLevel(logging.ERROR)

# 通常のログ用ハンドラー
info_handler = logging.FileHandler('info.log')
info_handler.setLevel(logging.INFO)

# フォーマットの設定
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
error_handler.setFormatter(formatter)
info_handler.setFormatter(formatter)

# ロガーにハンドラーを追加
logger.addHandler(error_handler)
logger.addHandler(info_handler)

# ログの出力
logger.info('これはINFOレベルのメッセージです')
logger.error('これはERRORレベルのメッセージです')
```
- info.log には INFO 以上のメッセージが記録されます。
- error.log には ERROR 以上のメッセージが記録されます。

loggerの使用法は現場により異なり、さらに複雑な記述で使用されていると思いますが、基本的なloggerの使用法は上記となるはずです。
ChatGPTが作図した深層学習の仕組み

ChatGPTに、深層学習について解説させて、Mermaid図を作らせてみました。

```mermaid
graph LR;
    Input[入力] --> InputLayer
    
    %% 入力層 - シンプルに整理
    subgraph InputLayer[入力層]
        A1((入力))
        A2((入力))
        A3((入力))
    end
    
    %% 中間層 - 結合線をまとめ、視認性を高める
    subgraph HiddenLayer1[中間層 1]
        H1((○))
        H2((○))
        H3((○))
    end
    
    subgraph HiddenLayer2[中間層 2]
        H4((○))
        H5((○))
        H6((○))
    end
    
    subgraph HiddenLayer3[中間層 3]
        H7((○))
        H8((○))
        H9((○))
    end
    
    %% 出力層 - シンプルでわかりやすく
    subgraph OutputLayer[出力層]
        O1((出力))
        O2((出力))
    end

    %% 入力層から中間層への接続
    A1 --> H1
    A1 --> H2
    A1 --> H3
    A2 --> H1
    A2 --> H2
    A2 --> H3
    A3 --> H1
    A3 --> H2
    A3 --> H3

    %% 中間層1から中間層2への接続（複雑に交差）
    H1 --> H4
    H1 --> H5
    H1 --> H6
    H2 --> H4
    H2 --> H5
    H2 --> H6
    H3 --> H4
    H3 --> H5
    H3 --> H6

    %% 中間層2から中間層3への接続（複雑に交差）
    H4 --> H7
    H4 --> H8
    H4 --> H9
    H5 --> H7
    H5 --> H8
    H5 --> H9
    H6 --> H7
    H6 --> H8
    H6 --> H9

    %% 中間層から出力層への接続（交差）
    H7 --> O1
    H7 --> O2
    H8 --> O1
    H8 --> O2
    H9 --> O1
    H9 --> O2

    %% 出力層から最終出力への接続
    O1 --> 結果[最終出力]
    O2 --> 結果
```

Mermaidは次の通り:

```
graph LR;
    Input[入力] --> InputLayer
    
    %% 入力層 - シンプルに整理
    subgraph InputLayer[入力層]
        A1((入力))
        A2((入力))
        A3((入力))
    end
    
    %% 中間層 - 結合線をまとめ、視認性を高める
    subgraph HiddenLayer1[中間層 1]
        H1((○))
        H2((○))
        H3((○))
    end
    
    subgraph HiddenLayer2[中間層 2]
        H4((○))
        H5((○))
        H6((○))
    end
    
    subgraph HiddenLayer3[中間層 3]
        H7((○))
        H8((○))
        H9((○))
    end
    
    %% 出力層 - シンプルでわかりやすく
    subgraph OutputLayer[出力層]
        O1((出力))
        O2((出力))
    end

    %% 入力層から中間層への接続
    A1 --> H1
    A1 --> H2
    A1 --> H3
    A2 --> H1
    A2 --> H2
    A2 --> H3
    A3 --> H1
    A3 --> H2
    A3 --> H3

    %% 中間層1から中間層2への接続（複雑に交差）
    H1 --> H4
    H1 --> H5
    H1 --> H6
    H2 --> H4
    H2 --> H5
    H2 --> H6
    H3 --> H4
    H3 --> H5
    H3 --> H6

    %% 中間層2から中間層3への接続（複雑に交差）
    H4 --> H7
    H4 --> H8
    H4 --> H9
    H5 --> H7
    H5 --> H8
    H5 --> H9
    H6 --> H7
    H6 --> H8
    H6 --> H9

    %% 中間層から出力層への接続（交差）
    H7 --> O1
    H7 --> O2
    H8 --> O1
    H8 --> O2
    H9 --> O1
    H9 --> O2

    %% 出力層から最終出力への接続
    O1 --> 結果[最終出力]
    O2 --> 結果
```
カレンダーを作るー1

お疲れ様です。

シンプルカレンダーについていろいろ調べていましたが、データが古くletではなくvarが使われていたのもあり、chatGPT先生にコードを書いてもらいました。
まずはそれを見ながら分からないことろを調べ、今自分がどこの部分のコードを書いているか理解しながらやっていきます。

というわけで進捗です↓
![スクリーンショット 2024-10-14 000952.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810013/02b1f9a0-8965-4893-2612-a5e4b581e7aa.png)
cssを書いてない状態なので、全部下に伸びていっちゃってますので、明日cssをあてて見た目を整えたいと思います。

今回コードを読んでいく中で、「テンプレートリテラル」のことをすっかり忘れていましたので、途中で復習をしました:writing_hand:

``で囲んで、${}の中に式などを書くことで、文字列が出来上がるというものでした。
${}を見ると、「jQueryだ！」とか思いましたが、jQueryも言うほどコードを書いたことがないので、良い機会ですし復習しようと思います:sweat_smile:
損益分岐点の覚え方


# はじめに
応用情報技術者試験(AP)の最後のほうに出てくる「損益分岐点が～」とか「限界利益率が～」という問題の計算式が覚えられないのでメモ．
導出できるようになった方が定着すると思います．


# 損益分岐点の導出

売上高の式から求めていきます．

```math

売上高 = 固定費 + 変動費 + 利益 \tag{1} 
```

$利益 = 0$ としたときの売上高が損益分岐点になります．つまり，

```math
損益分岐点 = 固定費 + 変動費※ \tag{2} 
```
となります．

:::note warn
変動費※は売上によって変わるので，式(1)と式(2)の変動費は違う値になります．
:::

式(2)より，$変動費=損益分岐点\times変動費率$として，

```math
損益分岐点 = 固定費 + (損益分岐点 \times 変動費率 )
```

これを整理して

```math
損益分岐点 = \frac{固定費}{1-変動費率} \tag{3}
```

損益分岐点を導出できました．

# 限界利益率について

限界利益は，売上高から変動費を引いたものと説明されています．

式で書くと，
```math
限界利益 = 売上高 - 変動費
```

両辺を売上高で割って，比率で考えると，

```math
限界利益率 = 1 - 変動費率
```
なので，先ほどの式(3)は，

```math
損益分岐点 = \frac{固定費}{限界利益率}
```
とも書けます．

# 実際の問題で確認

令和3年秋の問題です．（令和6年秋でもまったく同じ問題が出ていましたね...）

https://www.ap-siken.com/kakomon/03_aki/q77.html

## A社

```math
変動費率 = \frac{500}{1000} = \frac{1}{2}
```
```math
限界利益率 = 1 - \frac{1}{2} = \frac{1}{2}
```
```math
損益分岐点 = \frac{400}{1-\frac{1}{2}} = 800
```

## B社

```math
変動費率 = \frac{800}{1000} = \frac{4}{5}
```
```math
限界利益率 = 1 - \frac{4}{5} = \frac{1}{5}
```
```math
損益分岐点 = \frac{100}{1-\frac{4}{5}} = 500
```


この問題では「イ」と「ウ」の選択肢は違うとわかりますね．
SwiftUIに欲しい機能5選

# SwiftUIに欲しい機能5選

SwiftUIは徐々に機能が拡充され、iOS17頃からかなり実用的になってきました。UIkitでは癖のあった共有機能なども、SwiftUIでは1行で実現できるようになり、その進化は目覚ましいものがあります。  
今回は、私が個人的にSwiftUIネイティブで実装されて欲しいと思う機能5選を紹介します。


:::note warn
リサーチ不足により、既にSwiftUI単独で実現できる機能が含まれている可能性があります
:::
＊2024年10月時点の情報です

**是非コメントにてSwiftUIに実装されて欲しい機能を教えてください！**

## 1. カメラ機能

iOS17から`PhotosPicker`の導入により、簡単かつ安全に写真アプリから、ユーザーがアプリ内に画像を取り込めるようになりました。一方で、カメラを使用するには依然として`UIImagePickerController`を`UIViewControllerRepresentable`でラップして使う必要があります。

![IMG_2222.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718653/d28d1ae2-13fd-42dd-6fd6-6c95565ff265.jpeg)


写真アプリからの取り込みには`PHPickerViewController`が推奨されていることから、そろそろカメラ機能に対するネイティブAPIの登場を期待したいところです。さらに、アスペクト比の調整などもネイティブUIでできるようになると便利です。

## 2. アプリ内ブラウザ

アプリの利用規約やプライバシーポリシーを、ユーザーをアプリから離脱させることなく表示するために、アプリ内ブラウザはよく使われています。現状では`SFSafariViewController`を`UIViewControllerRepresentable`でラップする方法しかありません。
![IMG_2220.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718653/50446370-d937-e4a6-3006-b0aa85367447.jpeg)

これが`ShareLink`のように数行で簡単に使用できるようになれば、より扱いやすくなるでしょう。

## 3. 選択可能なText

Webページのようにアプリ内の文字列をコピー・共有できる機能は、ユーザー体験の一部として当然のものです。

![IMG_2214.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718653/c40abb57-d9e9-6550-70fa-1b80026566e9.jpeg)

しかし、SwiftUIの`Text`ビューは依然として文字選択に対応していません。`Text`ビューに`.textSelection(.enabled)`を適用することで文字選択が可能になりそうですが、Appleの公式ドキュメントにも記載されている通り、iOSではシステムメニューは表示されても、文字列の一部を選択してコピーすることはできません。

現状では、`UITextView`を`isEditable = false`、`isScrollEnabled = false`として、`UIViewControllerRepresentable`でラップするしかありませんが、この方法にはサイズ調整の癖があり、別途対応が必要です。この解決策については、また別の記事で紹介します。

## 4. プレースホルダー付きのTextEditor

`TextField`はプレースホルダーを設定できますが、`TextEditor`にはそれがありません。現時点では、`TextEditor`の空文字時に`.overlay`を使ってプレースホルダーを重ねる方法や、iOS16以降であれば`TextField`に`axis: .vertical`を設定して複数行入力に対応する方法などが考えられます。

しかし、`TextField`にはスクロール機能がないため、厳密には代替とは言えません。もちろん、自分で拡張することも可能ですが、デフォルトのAPIとして対応してほしいところです。

## 5. Progressive Blur（可変ブラー）

最後はprogressive blur（可変ブラー）です。アプリライブラリやiOS18の写真アプリ、ジャーナルアプリなどで見られる、このボカシ効果は、ブラーの半径が座標によって徐々に変化するというものです。

![IMG_2217.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3718653/1053f89f-530a-d8b5-759a-e2c32cff6d57.gif)

Appleのネイティブアプリでは、iOS17以降で利用可能な`variableBlur`という非公開APIを使用していると考えられますが、UIkitでもSwiftUIでも現状では使用できません。iOS18で公開されるのではと期待されていましたが、まだ実現していません。

---

皆さんが望むSwiftUIの機能や実装を、ぜひコメントで教えてください！
知られざるRaycastの便利機能４選

# はじめに
今回は、"知られざるRaycastの便利機能選"と題しまして、あまり知られていないけど知っていると便利なRaycastの機能を紹介していきたいと思います。

## Googleカレンダーと同期してビデオミーティングに参加 
My Scheduleコマンドを使用して、直近のミーティングの表示、参加ができます。

直近のミーティング予定はApple純正のカレンダーアプリを参照しますが、Googleカレンダーを連携させることもできるのでGoogleカレンダー→Apple純正のカレンダー→Raycastという感じで連携させることが可能です。
ブラウザを経由することなくミーティングへスムーズに参加ができるので、ミーティングに頻繁に参加される方は結構な手間が節約できます。

## ビデオ通話参加時にカメラのプレビューを表示
前項目から繋がるTipsではありますが、Raycastを通してミーティングへ参加する前にRaycastのカメラ機能を使用してプレビューを表示することができます。
身だしなみが整っているかを確認できるのは小さいことですがとても便利です。

設定はMy Scheduleコマンドの詳細設定から、`Preview camera`をONにすることで有効にできます。

## フォーカスされているアプリのメニューバーを検索して実行
Adobeなどの複雑で多機能なアプリを使用しているときに効果を発揮する機能です。
`Search menu items`というコマンドを使用すると、現在フォーカスされているアプリのメニューバーの項目を検索して実行することができます。

↓Chromeの場合
![スクリーンショット 2024-10-13 23.55.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/8a7cbb39-4b46-8f2f-b748-c07ffc769ed4.png)

## `Search ScreenShots`コマンドの参照先を追加
`Search ScreenShots`コマンドは便利ですが、デフォルトだとデスクトップディレクトリしか参照してくれません。

実は、詳細設定から参照するディレクトリを追加することができます。例えばダウンロードやピクチャーディレクトリを追加しておくことで飛躍的に便利なコマンドに変化します。

![スクリーンショット 2024-10-14 0.00.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2778030/0b7c27c8-155b-19f2-da18-bd808d8386b0.png)

### 終わりに
いかがだったでしょうか？一つでも便利だなと思える機能があれば幸いです
こんな機能あるよ！って方はぜひコメント欄にお願いします！
最後までお読みいただきありがとうございました！
【学習記録　2024-10-13】　JavaScript

## 使用した教材など
Udemy：【世界で70万人が受講】Web Developer Bootcamp 2023（日本語版）

## 学習内容
### 学習時間：1h
- 条件式
- String

## 所感
　今日からまたJavaScriptについて学習していきます！すでに学習したことがある内容だったので、サクサク進んでいきます！
JavaScript圧縮program集2

## Hacker Packer
[Dean Edwards' Packer](http://dean.edwards.name/packer/)の改造版

<p class=codepen data-height="300" data-default-tab="result" data-slug-hash="abepxYr" data-pen-title="Hacker Packer" data-user="xezz" style="height:300px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;border:2px solid;margin:1em 0;padding:1em"> <span>See the Pen <a href="https://codepen.io/xezz/pen/abepxYr">Hacker Packer</a> by xezz (<a href="https://codepen.io/xezz">@xezz</a>) on <a href="https://codepen.io">CodePen</a>.</span></p><script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## Packer 3.0
本家が既に消えてしまったので召喚。file保存buttonがありますが機能していません(本家はphpで実装していたような気が…)

<p class=codepen data-height="300" data-default-tab="result" data-slug-hash="ZEgKbeW" data-pen-title="Packer 3.0" data-user="xezz" style="height:300px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;border:2px solid;margin:1em 0;padding:1em"><span>See the Pen <a href="https://codepen.io/xezz/pen/ZEgKbeW">Packer 3.0</a> by xezz (<a href="https://codepen.io/xezz">@xezz</a>) on <a href="https://codepen.io">CodePen</a>.</span></p><script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## Packer 3.1
[本家?](https://github.com/doekman/base2/tree/master/src/apps/packer)。Packer 3.0の上位版ですが巨大文字列に対して`Bases62 encode`を有効にすると、復元できない事があります。15年以上前の化石programなので、進化したJS構文にも未対応

<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="jOgBNxo" data-pen-title="Packer 3.1" data-user="xezz" style="height:300px;box-sizing:border-box;display:flex;align-items:center;justify-content:center;border:2px solid;margin:1em 0;padding:1em"> <span>See the Pen <a href="https://codepen.io/xezz/pen/jOgBNxo">Packer 3.1</a> by xezz (<a href="https://codepen.io/xezz">@xezz</a>) on <a href="https://codepen.io">CodePen</a>.</span></p><script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## Bookmarkleter
codepenに埋め込むにしては素材が巨大過ぎるので本家の[Demo](https://github.com/chriszarate/bookmarkleter)。[bookmarklet](https://en.wikipedia.org/wiki/Bookmarklet)を圧縮して下さる。ためしに[bookmarkletの骨董品](https://www.squarefree.com/bookmarklets/)でも圧縮してみてはどうでしょうか
Python Djangoを使ってみる その2（自分用）

今回もDjangoについて、使いながら気付いたことを書き留めていく。
⇒ <a href="https://qiita.com/mm02060116/items/13c8b8e7541a3db748ab">前回までの内容</a>

1.ディレクトリ構造を確認
-
メインディレクトリを含めた現在のディレクトリ構造を見てみる。
前回触ったファイルの位置関係だけを確認しておく。

<strong>urls.py:</strong> メインディレクトリ、追加したアプリのどちらにも存在
<strong>settings.py:</strong> メインディレクトリにだけ存在
<strong>views.py:</strong> 追加したアプリにだけ存在
```
myprojectのディレクトリ

myproject/
│
├── __init__.py
├── asgi.py
├── settings.py
├── urls.py
├── wsgi.py
myapp/
├──
└── migrate/
│       └──  __init__.py
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
├── views.py
```
2.settings.pyの設定を変更する
-
よくわからないが、とりあえずここは変更しても問題なさそうなところだけを変更してみる。
```python:settings.py
LANGUAGE_CODE = 'ja'  # en-us ⇒ ja

TIME_ZONE = 'Asia/Tokyo' # UTC ⇒ Asia/Tokyo
```
3.HTMLテンプレートを作成する
-
Djangoでは、HTMLファイルをテンプレートとして使います。まず、テンプレートを保存するディレクトリを作成し、そこにボタンを表示するHTMLを配置します。

<strong>3.1: templates フォルダ、myapp フォルダ、index.htmlを作成する</strong>
```
myappディレクトリ

myapp/
│
├── templates/
│   └── myapp/
│       └── index.html  # HTMLファイル
└── migrate/
│       └──  __init__.py
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
├── views.py
```
<strong>3.2: index.htmlの内容を作成</strong>
試しにボタンを一つ作ってみる。
templates/myapp/index.html に次のコードを記述します。これは、ボタンを表示し、クリックすると /clicked/ というURLに遷移します。
```html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ボタンの例</title>
</head>
<body>
    <h1>ようこそ</h1>
    <form action="/clicked/" method="get">
        <button type="submit">ここをクリック</button>
    </form>
</body>
</html>
```
<strong>3.3: ビューを作成</strong>
myapp/views.py に、ボタンがクリックされた後に表示されるビュー (clicked_view) を追加します。
```python:myapp/views.py
from django.http import HttpResponse
from django.shortcuts import render

# 「ようこそ」とボタンを表示するビュー
def welcome_view(request):
    return render(request, 'myapp/index.html')

# ボタンがクリックされたときに表示されるビュー
def clicked_view(request):
    return HttpResponse("ボタンがクリックされました！")
```
<strong>3.4: ルーティング設定</strong>
次に、urls.py ファイルを編集して、ビューを呼び出せるようにURLを設定します。
```python:myproject/urls.py
from django.contrib import admin
from django.urls import path
from myapp.views import welcome_view, clicked_view  # viewsをインポート

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', welcome_view),  # ルートURLで「ようこそ」を表示
    path('clicked/', clicked_view),  # ボタンがクリックされたときのURL
]
```
4.開発用サーバーを起動
-
<strong>4.1: 開発用サーバーを起動し、<a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>にアクセスする。</strong>
「<strong>ようこそ</strong>」と「<strong>ここをクリック</strong>」というボタンが表示される。
```
python manage.py runserver
```
ボタンをクリックし、「<strong>ボタンがクリックされました！</strong>」と表示されたらOK！
とりあえず、なんとなく使い方のイメージは掴めてきたような気がする。
LeetCodeを1日1題解いてみる (day3)

3日目に取り組んだ問題はこちら！

# 20. Valid Parentheses

https://leetcode.com/problems/valid-parentheses/description/

## 問題文
Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.

An input string is valid if:

Open brackets must be closed by the same type of brackets.
Open brackets must be closed in the correct order.
Every close bracket has a corresponding open bracket of the same type.

## 僕の回答

```py
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next

class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        dummy = ListNode()
        current = dummy  # マージ後のリストを構築するために使用

        p1 = list1
        p2 = list2

        while p1 != None and p2 != None:
            if p1.val <= p2.val:
                current.next = p1
                p1 = p1.next
            elif p1.val > p2.val:
                current.next = p2
                p2 = p2.next
            current = current.next
        
        if p1 is not None:
            current.next = p1
        elif p2 is not None:
            current.next = p2

        return dummy.next
```

## より効率の良い回答例

```py
class Solution:
    def isValid(self, s: str) -> bool:
        stack = deque()

        closeToOpen = {")": "(", "]": "[", "}": "{"}
        for p in s:
            if p in closeToOpen:
                if len(stack) == 0 or closeToOpen[p] != stack.pop():
                    return False
            else:
                stack.append(p)

        return len(stack) == 0
```

### コメント
deque（double-ended queue） は、リストに比べてスタックとしての操作（特に pop や append 操作）が効率的です。
リストの場合、pop() や append() も効率的ですが、特に大量の要素を扱う場合に、deque のほうが最適化されているため、パフォーマンス上の利点があります。
リストの pop() や append(): 平均 O(1) で動作しますが、リスト全体の再配置が必要になることがあり、最悪の場合 O(n) の時間がかかる可能性があります。
deque の pop() や append(): 両端に対する操作は常に O(1) であり、最悪のケースでも効率的です。

### 次回はこちら!
https://qiita.com/h_y_s_d/items/21a4d8d713fabe173c44
【Fastapi】エラー「No module named 'httpx' while import TestClient」の解決方法

# 概要
fastapiのバージョンをアップグレード後、テストを行ったら以下のエラーになりました。

> ModuleNotFoundError: No module named 'httpx' while import TestClient

こちらの原因と解決方法を紹介します。

# 前提
`TestClient`とは、FastAPIのエンドポイントをテストすることができるツールです。

今まで`httpx`というモジュールをインポートせずとも利用できていました。
しかし、`0.73.0`から`0.112.1`にバージョンアップを行なった際に上述のエラーが出ました。

# 原因
原因は、`0.87.0`から`TestClient`は`HTTPX`をベースにするように変更があったため、でした。
以下の通り、従来は`requests`をインポートしていればよかったのが`httpx`をインポートする必要が生じるようになりました。

> Now the TestClient is based on HTTPX instead of Requests.
引用元：https://github.com/fastapi/fastapi/releases/tag/0.87.0

# 解決策
ということで、`httpx`をインストールしてあげれば問題ないです。

```
pip install httpx
```

私はdockerコンテナで`requirements.txt`を利用してライブラリのバージョン指定でを一括インストールしていたので、以下のように追記しました。

```
httpx==0.27.2
```

これで問題なくテストを実行できるようになりました。

参考：

https://pypi.org/project/httpx/
【VSCode】Call Hierarchyを表示する方法

## Call Hierarchyとは

Call Hierarchy（呼び出し階層）は、コード内の関数やメソッドの呼び出し関係を視覚的に表示する機能です。この機能を使用すると特定の関数がどこから呼び出されているのか、またその関数が他のどの関数を呼び出しているのかがサイドバーなどに画像のように表示されます。

![スクリーンショット 2024-10-14 0.03.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/3d74f477-4712-4acc-d6a1-a985657994f6.png)


## サイドバーに表示

以下の方法でCall Hierarchyをサイドバーに表示できます。

### 右クリックで表示

関数名を右クリックし、「Show Call Hierarchy」をクリックします。

![スクリーンショット 2024-10-13 23.54.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/1e5e6864-a7d2-409a-a879-30ec59603090.png)

### コマンドパレットから表示

関数名にカーソルをおいて、コマンドパレットで「Calls: Show Call Hierarchy」を実行しても表示できます。

![スクリーンショット 2024-10-14 0.07.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/5ce55637-6db8-0a80-2c5b-011c32750865.png)

## ピークで表示する

以下の方法でCall Hierarchyをピークで表示できます。

### 右クリックで表示

関数名を右クリックし、「ピーク > 呼び出し階層のプレビュー」をクリックします。

![スクリーンショット 2024-10-14 0.09.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/71e7fa9c-e760-3869-b332-48a570ae7901.png)

### コマンドパレットから表示

関数名にカーソルをおいて、コマンドパレットで「Peek Call Hierarchy」を実行しても表示できます。

![スクリーンショット 2024-10-14 0.09.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/6383bdb8-521a-676e-1a9d-a27d93f6de07.png)
Ansible　基礎2

# 最初に
Ansibleを業務で使用することになりました。
そのため勉強したことをまとめています。

# プレイブック(Playbook)について

- プレイブック(Playbook)とはAnsibleにおける「ターゲットノードに対するオペレーションの設定書兼手順書」の役割をする。
- Ansibleはプレイブック(Playbook)を参照し実行可能なPythonスクリプトを生成する。
- Ansibleはプレイブック(Playbook)を上から下に解釈し順番に実行していくため、どこかの”task”にジャンプなどはできない
- YAML形式で記載するのでフィルの拡張子は.ymlになる。

# プレイブック(Playbook)の書き方

□例文

```
---
- hosts: web_servers
  become: yes
  tasks:
    - name: Update PHP
      yum:
        name: php
        state: latest
```

□例文の解説

- 「---」
プレイブック(Playbook)の先頭に書くもの
これからYAMLフォーマットで書くことを表しているだけで深い意味はない

- 「- hosts: web_servers」
実行対象を指定しており、この場合では”web_servers”というサーバに対して処理を行おうとしている。
実行対象のサーバについてはインベントリ（Inventory）に記述する。
hostsの設定値については下記の通り
all　：　インベントリ（Inventory）に記述したすべてのホストに対して実行
localhost　：　Ansibleを実行しているノード自身に対して実行
<ホスト名>　：　インベントリ（Inventory）に記述した特定のサーバのみに実行
<ホストグループ名>　：　インベントリ（Inventory）に記述したホストグループに所属するサーバ全てに対して実行

- 「become: yes」
権限昇格を行っている。
もし特定のユーザに切り替えしたい場合は”become_user”で指定する。
rootへ昇格する場合は省略可能で、今回は指定していないためrootに昇格している。
また今回は省略しているが”become_method:”で昇格方法を指定することも可能
sudoで昇格する場合はデフォルトなので不要ですがもしsu等で昇格した場合は記載する。

- 「tasks:」
実際に処理する内容を定義する。
1つのプレイブック(Playbook)に複数の”task”を定義可能

- 「- name: Update PHP」
タスクの名前を定義している。
必須ではないため省略することも可能ではあるが、何をしているのかわかりにくくなるため設定したほうが良い

- 「yum:」
Ansibleの「yumモジュール」を使用することを示しており、yumパッケージマネージャーを通じて行うよう指示している。

- 「name: php」
yumモジュールでのアップデート対象を示しており今回はPHPを対象としている。
もし省略するとすべてのパッケージが更新対象になるため注意が必要。


- 「state: latest」
最終的になりたい状態を示しており、今回であればPHPのバージョンを最新にすることとしている。
設定値については他に下記がある。
present/installed　：　パッケージがインストールされていない場合インストールする。既にインストール済の場合は何もせず、またもしアップデート可能でもアップデートしない
absent/removed　：　パッケージがインストールされている場合削除する。既に削除済の場合は何もしない

## 最後に
Ansibleのプレイブック(Playbook)では上記以外にも色々な処理（ループ処理等）ができます。
今回はシンプルで単純な処理を書いて細かく処理内容を記載してみました。
実際業務で書く場合はバージョンの指定が必要だったりが必要なのでもっと複雑になりそうです。
次はインベントリについて勉強したいです。
Javascriptによるアニメーション作成

## anime.jsを使用したアニメーション作成

アニメーションサイトGit共有リンク
https://github.com/ayaka0525/anime/tree/main

anime.jsをサイトで検索して、anime.min.jsのRawをクリックし名前をつけて保存。
自分の作成しているhtml,cssなどと同じ階層に入れたら使えるようになる。

https://github.com/juliangarnier/anime/blob/master/lib/anime.min.js

htmlのscript手前で読み込み
```
 <script src="anime.min.js"></script>
```

javascriptはhtmlのbodyに直接記述した。
先ほど読み込みをしたanimateBlocksを使用している。
```
 <script>
        // ".container" クラスの要素を取得
        const container = document.querySelector(".container");
        
        // ループを使って50個のブロック要素を作成して追加
        for (var i = 0; i <= 50; i++) {
            const blocks = document.createElement("div"); // 新しいdiv要素を作成
            blocks.classList.add("block"); // 作成した要素に"block"クラスを追加
            container.appendChild(blocks); // コンテナにその要素を追加
        }
        
        // ブロックをアニメーションさせる関数
        function animateBlocks() {
            anime({
                targets: ".block", // "block"クラスを持つすべての要素が対象
                // translateX: X軸にランダムに移動させる
                translateX: function() {
                    return anime.random(-800, 700); // -800から700までの範囲でランダムに移動
                },
                // translateY: Y軸にランダムに移動させる
                translateY: function() {
                    return anime.random(-500, 700); // -500から700までの範囲でランダムに移動
                },
                // scale: ランダムにブロックのサイズを変更
                scale: function () {
                    return anime.random(1, 3); // 1倍から3倍の間でランダムにスケール変更
                },
                duration: 2500, // アニメーションの継続時間を2500ミリ秒（2.5秒）に設定
                delay: anime.stagger(15), // 各要素のアニメーションの開始を15msずつ遅らせる
                complete: animateBlocks, // アニメーション完了後、再度同じ関数を実行（無限ループでアニメーションを繰り返す）
            });
        }
    
        // アニメーションを開始
        animateBlocks();
    
    </script>
```

## 参照YOUTUBEサイト
https://www.youtube.com/watch?v=-2dyyzU2O-o

お疲れ様でした！
Pythonでの並列処理：multiprocessing.Pool() の使い方

# 概要
Pythonで大規模データ処理や重い計算処理を行う際に、シングルスレッドでは処理速度がボトルネックになることがあります。そこで役立つのが、multiprocessing モジュールです。この記事では、その中でも特に使い勝手が良い multiprocessing.Pool() を使った並列処理の方法についてメモします。

# multiprocessing.Pool() とは？
multiprocessing.Pool() は、複数のプロセスを使って並列にタスクを実行するための機能です。これを使うことで、同時に複数の処理を効率よく実行できるようになります。

## 基本的な使い方
multiprocessing.Pool() を使うときは、通常以下のような構造で実装します。
```python
import multiprocessing

def タスク関数(引数):
    # 処理の内容
    return 処理結果

if __name__ == "__main__":
    with multiprocessing.Pool(プロセス数) as pool:
        結果 = pool.map(タスク関数, 引数のリスト)
```
- multiprocessing.Pool(プロセス数) は、同時に実行するプロセスの数を指定します。
- pool.map() は、リストなどのデータに対して並列処理を適用するための関数です。

# multiprocessing.Pool() を使った実例
実際に具体的なコードでmultiprocessing.Pool()の使ってみる。ここでは、ファイルを並列処理で読み込むシミュレーションをします。
```python
import multiprocessing
import time

# ファイル処理などの重い処理を模倣する関数
def process_file(file_name):
    print(f"{file_name} の処理開始")
    time.sleep(2)  # ファイル処理に時間がかかることをシミュレート
    print(f"{file_name} の処理完了")
    return f"{file_name} の結果"

if __name__ == "__main__":
    # 処理したいファイル名のリスト
    file_list = ["file1.txt", "file2.txt", "file3.txt", "file4.txt", "file5.txt"]

    # Poolを使って並列処理
    with multiprocessing.Pool(processes=3) as pool:  # プロセス数を3に設定
        results = pool.map(process_file, file_list)  # ファイルリストを並列処理
    
    # 処理結果を表示
    print("すべてのファイル処理が完了しました:")
    for result in results:
        print(result)
```
- multiprocessing.Pool(processes=3): 3つのプロセスを使ってファイルを並列処理しています。システムのコア数に合わせて適切なプロセス数に設定する必要があります。
- with 文: with を使うことで、リソース管理が自動化され、明示的に close() や terminate() する必要がなく、ブロックが終了した時点で自動的にリソースを解放します。
- pool.map(): リストの各要素に対して並列処理を適用します。この例では、ファイル名のリストに対して処理関数 process_file() を実行しています。
## 実行結果
実行すると、以下のようにファイル処理が並列に行われる様子が確認できます。
```
file1.txt の処理開始
file2.txt の処理開始
file3.txt の処理開始
file1.txt の処理完了
file4.txt の処理開始
file2.txt の処理完了
file5.txt の処理開始
file3.txt の処理完了
file4.txt の処理完了
file5.txt の処理完了
すべてのファイル処理が完了しました:
file1.txt の結果
file2.txt の結果
file3.txt の結果
file4.txt の結果
file5.txt の結果
```
# 大規模データの処理
multiprocessing.Pool() は、大量のデータや複数のファイルを並列に処理する場合に非常に役立ちます。これはよく現場で使用されていると思います。
```python
def process_data(data_chunk):
    # 複雑なデータ処理
    return 処理結果

if __name__ == "__main__":
    data_list = 大量データリスト

    with multiprocessing.Pool() as pool:
        results = pool.map(process_data, data_list)
    
    # ここで結果をまとめたり、ファイルに出力
```
このようにデータ分析系のシステムではよく使用されます。
投稿 105 カルーセル 2024/10/13

本日の勉強時間　3H

画像などのコンテンツをスライド表示させる手法をカルーセルと言う。  
別名「スライダー」や「スライドショー」。

カルーセルは限られたエリアで、複数のビジュアルをユーザーに訴求するために使われる。
ユーザーはページ遷移やスクロールを行わずに、複数の情報を確認できる。
【JAWS FESTA 2024 in 広島】参加レポ！！

## はじめに
JAWS-UGが主催する交流イベント**JAWS FESTA 2024 in 広島**に参加してきました！！ オフラインでのJAWS-UGイベント参加は、今回が初めてでとても有意義なものになったので、備忘録として投稿！（Qiita記事初投稿）

## JAWS FESTA 2024 in 広島
日時：2024年10月12日 10:00~15:00
場所：広島大学東広島キャンパス
テーマ：地方イベント侮るなかれ　酔ってきんさい、観てきんさい♪

## セッション
4種類5トラックで、8枠と盛りだくさんの内容でした。
参加したセッションの感想を簡単に！

### ひろしま宣言
オープニングセッションのKeyNoteでは、湯崎英彦 広島県知事から、[「ＡＩで未来を切り開く」ひろしま宣言](https://www.pref.hiroshima.lg.jp/soshiki/264/hiroshimaai.html)について、AIを活用した地域課題解決に向けての取り組みをご紹介して頂きました。

失敗しないように求められるプロジェクトが多い中で、組織のトップ自らが失敗を許容したうえで、AIの利活用に向けたチャレンジを応援しているところが魅力的でした。

### 広島事例
中国新聞社の[「たるポ」](https://tarupo.jp/)という地域共創プラットフォームを題材に、100年以上続く老舗企業の取り組みについて聞きました。
古くから続く地元紙としての信頼を活かしたサービスとサービスの遊び心が印象的に残りました。

### 技術系トラック

普段自分が触っていないサービスや生成AIのセッション中心に参加しました。
以下はメモ。
- Application Signals
- データ分析基盤のためのS3
- ノーコードでの生成AIアプリ開発

### アウトプットが大事
コミュニティ系トラックでは、

- AWS Samurai・AWS Hero経験者
- JAWS FESTA 2023 in Kyushu実行委員長
- 2024 Japan AWS Jr. Champions選出者

それぞれのセッションに参加しました。
AWSコミュニティを運営してからの変化やアウトプットの大切さについて聞くことができました。

私も2024 AWS Jr. Championsに選出され、その活動を通して、AWSコミュニティでの交流やアウトプットの良さが分かってきました。今回のJAWS FESTAに参加を決めたのも、「**AWSコミュニティを楽しみたい**」という思いからでした。

開会式の席では、偶然にも2023年度のJr. Championsの方の後ろになり、思わぬ縁も生まれ、こうしてコミュニティが広がっていくんだなと実感しました。
私のアウトプットの量はまだまだなので、AWSのもろもろを積極的にアウトプットしたくなるセッションでした。

## 参加してみた感想
JAWS FESTA 2024 in 広島オフラインのJAWSイベントに初参加して、技術、そしてコミュニティの学びがありました。セッションの中では、「**難しいより楽しい**」でいいじゃないかと話があり、JAWS FESTA 初参加の私を象徴するフレーズになりました。学びのセッションだけでなく、お祭りトラックやノベルティと盛り沢山で１日を楽しむことができました。

最後には、来年3月に JAWS DAYS 開催の告知がありました。今度は、JAWS DAYS にも参加したいと思います。本編後の懇親会（なんならこっちが本編か？）は、日程の都合で参加できなかったので、次回は懇親会にも参加したいです。

## さいごに
JAWS FESTA 2024 in 広島実行委員会の皆さま、運営ありがとうございました！
ご一緒した皆さんも、ありがとうございました！
次回またどこかのイベントでお会いできたら嬉しいです。
まだ参加されていない方も、次の機会にぜひご一緒しましょう！
Windows11でPythonのvenvを使い仮想環境を構築する際に、"cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170."というエラーに当たった際の解決方法。

# この記事について
https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e
↑の記事に従って環境構築していたところ
```shell:sh
$ .\venv\Scripts\activate 
```
というコマンドで以下のエラーが出て躓いた。
```shell:sh
.\venv\Scripts\activate : File C:\Users\sophytoeat\NeuralClothSim\venv\Scripts\Activate.ps1
cannot be loaded because running scripts is disabled on this system. For more information, see
about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ .\venv\Scripts\activate
+ ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : SecurityError: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess
```

# 環境
Unreal Engine 5.4.4
Python 3.13.0
PowerShell

# 解決方法
エラーメッセージは、PowerShellの実行ポリシーが原因でスクリプトが実行できないことを示しているらしい。デフォルトでは、PowerShellはセキュリティ上の理由からスクリプトの実行を制限しているようだ。

### 解決方法: 実行ポリシーを変更する

以下の手順で実行ポリシーを変更し、スクリプトの実行を許可する。

##### 1. PowerShellを管理者として起動

スタートメニューで「Windows PowerShell」を検索。
「Windows PowerShell」を右クリックし、「管理者として実行」を選択。
現在の実行ポリシーを確認（オプション）

```shell:sh
$ Get-ExecutionPolicy
```
通常は「Restricted」と表示されます。

##### 2. 実行ポリシーを変更

全ユーザーに適用する場合（管理者権限が必要）:
```shell:sh
$ Set-ExecutionPolicy RemoteSigned
```

現在のユーザーにのみ適用する場合（管理者権限は不要）:
```shell:sh
$ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```
コマンドを入力すると、変更の確認を求められます。

「Y」または「A」を入力して、変更を承認します。
仮想環境を再度アクティブ化

```shell:sh
.\venv\Scripts\activate
```

# 注意事項:
セキュリティリスク: 実行ポリシーを変更すると、悪意のあるスクリプトが実行されるリスクが高まります。信頼できるスクリプトのみを実行するようにしてください。

# 元に戻す方法: 
必要に応じて、実行ポリシーを元の「Restricted」に戻すことができます。
```shell:sh
$ Set-ExecutionPolicy Restricted
```

これで仮想環境に入ることが出来ました。
家でco2濃度をモニタリング

CO2濃度と温湿度の測定センサーをユニバーサル基板に実装するにあたり、
回路図を描いたので、手順の覚え書き。


## 使用ハード
本筋ではないが、センサー構成は調べてよく出てくるものを利用。

* ESP32開発ボード
* MH-Z19C：CO2センサー
* DHT20:温度湿度センサー

## 動作検証用のブレッドボード実装
CO2濃度、温度、湿度が計測できることを確認済み。
コード周りはネットで拾ったものの寄せ集め。

![ESP32_co2_temp_ブレッドボード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3909383/aeb072ff-8c1a-56ec-2084-5d6be685da5c.jpeg)


### Fritzingの環境セットアップ
#### 環境
1. ここからwin64.zipをダウンロード
https://github.com/fritzing/fritzing-app/releases/tag/CD-548
1. ファイルを解凍
1. Fritzing.exeを実行

#### Fritzing描画用の素材元

* ESP32開発ボード、ブレッドボード
https://ht-deko.com/delphiforum/?vasthtmlaction=viewtopic&t=1971.0
* H-Z19C
https://forum.fritzing.org/t/mh-z19c-co2-sensor-winsen/22538
#atcoder #プログラミング #Javascript # 本番環境自動判別方法等

**本内容を利用した場合の一切の責任を私は負いません。**

# 概要
初めてまともにやってみて、タイトルのものが欲しくなったんだけど、探しても見つからず、自作したもの。
(ローカルで大量のテストケースに耐えれるか確認するため、標準入力ではなく、1テストごとのファイルを大量に流し込みたい。
本番とローカルとでソースを分けたくない。)
既知だったり、別の方法があったりするかもだけど。
それと、他に気づいた点。

# 本番環境自動判別方法
全部かはわからないが、提出画面の下に下記がある。

![提出画面.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397476/421e9e4f-da76-2c90-372f-6530618648f8.png)

ということは、カレントにこのファイルがあれば本番ということになる。
(ローカルが異なるファイル名であることが前提。)
てことで下記で判別する。

```Javascript
var isSubmit = false;

if (require("fs").existsSync("./Main.js")) {
    isSubmit = true;
}
```

処理分けしたいとこでisSubmitを確認すればいい。

# その他
たまたまなのか、どこかに説明があるのかわからないが。
テストケースが複数ある場合(テストの仕方自体もいろいろあるように思うが、おそらくJavascriptの場合でソースファイルまるごとを実行させる場合)、グローバル変数の扱いが特殊のようである。
例えば、ソースファイルに下記があるとする。

```Javascript
var turn = 0;
```

普通に考えると1テストごとにソースファイルが読み込まれるため、各テストの開始時のturnは0になると思う。
が、実際は各テストで増えた分の累積になる。
どうやってるか不明だが。。。
【VSCode】起動時に前回の設定で立ち上がらないようにする

VSCodeでは終了後、再度開くと前回開いていたフォルダやSSHセッションに自動的に接続するような設定になっていると思います。
この設定をオフにします。

# 背景
デフォルトでは起動した際、前回の設定を復元するため、前に接続していたサーバーに自動で接続しにいく設定になっていると思います。
私はVS CodeをエディタよりもSSHクライアントとして使っており、ネットワーク設定や接続サーバーがコロコロ変わるため、この設定が煩わしく、この設定をオフにしたいと思いました。


# 解決
以下の設定を`setting.json`に追記します。

```
// 前回開いていたウィンドウを復元しない
"window.restoreWindows": "none"
```

# 参考：`window.restoreWindows`
なお、`window.restoreWindows`に指定できる値としては以下のようなものがあるようです。

|  |  |
|:-:|:-:|
| `preserve`  | 常にすべてのウィンドウを前回の状態で開く。|
| `all`       | すべてのウィンドウが再度開かれるが、新規のフォルダ等を指定して起動していた場合は新しいウィンドウとして開かれる。  |
| `folders`   | すべてのウィンドウが再度開かれるが、新規のフォルダ等を指定して起動していた場合はそのフォルダのみが開かれる。 |
| `one`       |  前回最後にアクティブだったウィンドウだけが１つだけ復元。 |
| `none`      |  前回のウィンドウは再度開かず、空のウィンドウを表示。 |


https://learn.microsoft.com/ja-jp/azure-data-studio/settings-list#window-restore-windows
C言語 free関数を使う際の注意点

# はじめに
42tokyoの生徒です。mallocを使う時に、必ず行うfreeですが、freeについてあまり知らなかったので、調べてみたところ、いくつか注意点があるとのことだったので備忘のためにまとめます。

# free関数の定義
```
  void free(void *ptr);
```
free() 関数は、ptr が指すメモリ割り当てを解放する。ptr が NULL ポインタの場合、操作は行われない。※man freeの内容を翻訳

# free関数を使う際の注意点
①二重解放はしない
```
NG例
free(ptr);
// これは誤り！
free(ptr); // 二重解放となりクラッシュの原因となる
```

②NULLポインタの解放はしない
```
NG例
int *ptr = NULL;
// これは誤り！
free(ptr); // NULLポインタの解放はクラッシュの原因となる
```

③動的に確保したメモリ以外を解放しない
```
NG例
int a = 10; // スタック領域に確保された変数
// これは誤り！
free(&a);  // スタック領域のメモリを解放しようとするとエラーになる
```

④メモリの先頭アドレス以外は解放しない
```
NG例
int *arr = (int *)malloc(10 * sizeof(int));
int *ptr = arr + 3;  // arrの4番目の要素へのポインタ

// これは誤り！
free(ptr);  // 配列の一部しか解放できず、メモリリークが発生する
```
spaCy GiNZAに含まれる全てのentity（固有表現）を表示する方法

特定の文章のentityを表示する方法は以下のとおりです。

~~~python
import spacy
                #またはja_ginza_electra, ja_ginza
nlp = spacy.load("ja_ginza_bert_large")
sample_text =  "イタリアでは犬も歩けば猫に出会う。"
doc = nlp(sample_text)

for ent in doc.ents:
    print(ent.text, ent.label_)
~~~
displacyを用いれば視覚的に分かりやすく表示することも可能です。（displayではないのでタイプミスに注意）
~~~python
from spacy import displacy

displacy.render(doc, style="ent", jupyter=True)
~~~


もっとも、文章を指定せずに、**そのモデルで抽出できる全てのentityをprintしたい時**は以下のように記載すれば良い。

~~~python
all_entity = nlp.get_pipe("ner").labels
print(all_entity)
~~~

"ner"によってNamed Entity Recognitionを指定しています。
ゲストユーザーをチームに追加する

## はじめに


Teamsに外部ユーザーのメールアドレスを入れて追加すれば
きちんとユーザーに通知→追加されるのでPowerAutomateでも同じようにTeamsのコネクタのチームのメンバーに追加のみでできるだろう…と見落としがちなのかもしれません。
それはね…、エラーでこけます。
なぜなら、手動で追加すると裏側でEntraIDにゲストユーザーを登録後、チャネルに追加されているからです。

:::note warn
※蛇足ですけどなんというか、
私のようなアプリとか自動化をやっているような者でもEntraIDって本当に切っても切れないものなんですよね。
ここがしっかりできていたら、なんでも楽なんですけどね…
:::

## やり方
じゃあ、EntraIDのコネクタからユーザーの作成アクションを追加すればいいの？ってなると思うのですが、このアクションには外部ユーザーにテナントに追加したよという通知するOr否の項目がないのです。

▽Notifyの項目が見当たらないユーザーの作成アクション、悲しい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/e5c5bb71-cd2b-2e2a-6b15-b4fe97bac96d.png)


よって、困ったときのGraphAPIを利用してゲストユーザーを招待をする必要があります。

https://learn.microsoft.com/en-us/graph/api/invitation-post?view=graph-rest-1.0&tabs=http

そう、簡単に言えばHTTPリクエストアクションがチームにメンバーを追加するアクションの前に必要なんです。
フローだとこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/39edbd8a-390e-935b-7afa-408ae692e3d9.png)

そしてHTTPリクエストは下記のような感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/0a38a2fc-5a77-f328-7aab-0f3b9d12a9de.png)
これでEntraIDにゲストユーザーが登録され、かつ、
"sendInvitationMessage": trueとしておくと、下記のようなメールをテナントが勝手に送ってくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3111714/0436351b-662f-f891-e53a-83766a13882a.png)



:::note

ゲストユーザーにはこのメールのAccept invitationのメールでAcceptをクリックした後、チームに招待されましたの通知も別に届くので最終的には2通、メールが届く形となります。
※このメールがないとテナントに追加されたかどうかもわからずじまいになっちゃうので。
:::


## 最後に
* HTTPリクエストの後、環境がよっぽど整っていない限りは遅延を入れてあげてください。
* 使い方の例としては各部署の担当者から申請(Formsとか)→承認後→自動ゲストユーザー追加などの形にしてあげるのもよいかもしれません。

* 共有チャネルへのゲストユーザー自動追加方法は次回の課題として、もう少し調べてみます…:wave_tone4:
縦横スクロール可能なギャラリー


# はじめに

こんな感じで縦横スクロール可能なギャラリーの作成方法についてです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/b3cac417-f765-c565-cc56-59d075f6ef30.png)

テーブルコントロールは既定で縦横スクロール可能なため、出来ればこちらを使うのがいいと思いますが、プレビュー機能ですし、なんらかの理由で採用できない場合もあると思います。
この場合、ギャラリーを使うことになると思いますが、縦横スクロール可能にするためには工夫が必要になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/ff70461f-d734-4af4-6765-afc965bd8998.png)

# 作成方法

まず、部品構造はこのような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/804b58ba-d206-8a0a-ebdd-1075add40dac.png)

水平コンテナーのプロパティは以下のような感じです。`折り返す`をオンにしているのがポイントです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/de19cd8f-b919-26e4-ef82-9d425baf9f57.png)

ヘッダー用のコンテナーのプロパティは以下のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/9395ca46-168c-0317-14ea-59db8b9bb9d3.png)

また、コンテナーの`[Width]`プロパティは以下のような感じで、各ヘッダー用のラベルの`[Width]`の合計と同じにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/26fb74c4-49b7-940c-0a06-af9124bffab8.png)

ギャラリーのプロパティは以下のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/2ac911c2-2f57-5949-e883-47976f501be4.png)

ギャラリー内のラベルの位置や幅は、ヘッダー用のラベルと同じにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/3a280160-98a3-8f9c-9443-ed54b3d9e152.png)
VPCフローログとは

# 概要
VPCのIPトラフィック情報をキャプチャする機能

# 出力先
- Amazon Cloud Watch Logs
- S3

# 収集する単位
- VPC
- サブネット
- ENI

# 記録されること
- 送信元/送信先IPアドレス
- 送信元/送信先ポート番号
- プロトコル番号
- 通信の許可/拒否の結果
- 転送パケット数
- バイト数
など

# 使用例
- トラブルシューティング（EC2インスタンスの通信トラブルなど）
- セキュリティの脅威検出
- ネットワークACL/セキュリティ脅威の検出
RequestParamとRequestBodyの違い

## 1.はじめに
webアプリを開発している中で、RequestParamとRequestBodyを使用する機会があったのですがこの２つの違いって何かという疑問をもったため記事を書いていこうと思います。

## 2.RequestParamとRequestBody
まずはそれぞれがどういう役割をもつかを理解していきます。

**~RequestParam~**
HTTPリクエストのクエリパラメータやURLパスから特定の値を取得します

例えば、/users?id=123 というリクエストURLから、クエリパラメータ id=123 を取り出す場合に使われます
```java
@GetMapping("/users")
public String getUserById(@RequestParam("id") int id) {
    return "User ID: " + id;
}
```
この例では、URL /users?id=123 にアクセスすると、id パラメータが取得されて "User ID: 123" が返されます。


**~RequestBody~**
HTTPリクエストのボディ部分に含まれるデータをサーバー側で受け取るために使用

例えば、JSONデータを受け取る場合のコードは次のようになります。
```java
@PostMapping("/createUser")
public String createUser(@RequestBody User user) {
    // Userオブジェクトにリクエストボディのデータがマッピングされる
    return "User created: " + user.getName();
}
```

```json
{
  "name": "John",
  "age": 30
}
```
※@RequestBody で送信される JSON データが User クラスに対応するためには、User クラスのフィールドが JSON データのキー（プロパティ名）と一致している必要があります

クライアントは、通常、POSTリクエストを使用してデータをボディに含めて送信します。例えば、JavaScriptのfetch関数やPostmanなどのツールから送信できます。

## 3.RequestParamとRequestBodyの違い

```java:@RequestParam
データソース：HTTPリクエストのクエリパラメータやフォームデータ
用途：簡単なデータ（検索条件）を取得時に使用
```

```java:@RequestBody
データソース：HTTPリクエストのボディ部分
用途：JSONなどの複雑なオブジェクトデータを取得する場合に使用
```

簡単にまとめると、@RequestParamはURLやフォームから、@RequestBodyはリクエストボディからデータを取得するということです。

## 4.まとめ
違いを理解できたので、次からは用途にわかえて使用していければと思います。
JavaScriptのURLコンストラクタでハマった話

## はじめに
JavaScriptのURLコンストラクタを使っているときに、初歩的なミスにハマってしまったので、備忘として残しておきます。

## 何が起きたか
ある場所においてあるファイル名を取得する処理を以下のように記述していました。

```javascript
const base = "http://example.com/test.pdf";
const url = new URL(base);
const fileName = url.pathname.split("/").pop();

console.log(fileName); // test.pdfと出力される
```
一見なんの問題もないように見えますが、日本語ファイル名が入ってくると様子が変わってきます。

```javascript
const base = "http://example.com/テスト.pdf";
const url = new URL(base);
const fileName = url.pathname.split("/").pop();

console.log(fileName); // %E3%83%86%E3%82%B9%E3%83%88.pdfと出力される
```

それもそのはずで、URLコンストラクタは引数で渡された文字列をエンコードしてURLオブジェクトを返します。

https://developer.mozilla.org/ja/docs/Web/API/URL#%E4%BD%BF%E7%94%A8%E4%B8%8A%E3%81%AE%E6%B3%A8%E6%84%8F

上記ページにも
> URL は、RFC 3986 にあるルールに従ってエンコードされます。

と記載されています。

## どのように対処したか
単純にデコードすればよいだけなので、以下のようにしました。

```javascript
const base = "http://example.com/テスト.pdf";
const url = new URL(base);
const fileName = decodeURIComponent(url.pathname.split("/").pop());

console.log(fileName); // テスト.pdfと出力される
```

## まとめ
蓋をあければなんてことのない話ですが、この現象に遭遇したときは結構テンパりました。

もともと別の処理で書いていたものを、URLコンストラクタを使用して書き換えた際にこの事象が発生していたのですが、運の悪いことに（？）別の処理でURLのエンコード/デコードを行うロジックを記載していたために、その修正による影響なのでは、というところで混乱が発生していました。

まったく関係ない場所での処理なのに、なぜ影響が起きたのか、というところで調査が難航していたのですが、実際には全然関係ない修正が原因だった、というオチでした。

修正対応する場合には、根本原因をきちんと見極めることが大事ですね
AlmaLinuxにKnowledgeを構築

# はじめに
https://information-knowledge.support-project.org/ja/

KnowledgeをLinuxサーバー上に構築し、外部ネットワークからアクセスできるようにします。

# 環境
- AlmaLinux release 9.4

# ポート解放
```
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --reload
```

# Javaインストール
```
dnf install -y java-1.8.0-openjdk-devel.x86_64
```
### PATHを通す
```
vi /etc/profile
```
以下を追記
```
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.422.b05-2.el9.x86_64/
export PATH=$PATH:$JAVA_HOME/bin
```
再読み込み
```
source /etc/profile
```

# Tomcatインストール
ユーザーの追加
```
useradd tomcat
passwd tomcat
```
```
cd /home/tomcat

wget https://archive.apache.org/dist/tomcat/tomcat-8/v8.5.99/bin/apache-tomcat-8.5.99.tar.gz
tar -xzvf apache-tomcat-8.5.99.tar.gz

mv /home/tomcat/apache-tomcat-8.5.99 /opt

chown -R tomcat:tomcat /opt/apache-tomcat-8.5.99
```

# Knowledgeインストール
```
cd /opt/apache-tomcat-8.5.99/webapps
wget https://github.com/support-project/knowledge/releases/download/v1.13.1/knowledge.war
```

# Tomcatのユニットファイル作成
```
vi /etc/systemd/system/tomcat.service
```
```
[Unit]
Description=Apache Tomcat 8
After=network.target

[Service]
User=tomcat
Group=tomcat
Type=oneshot
PIDFile=/opt/apache-tomcat-8.5.99/tomcat.pid
RemainAfterExit=yes

Environment=JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.422.b05-2.el9.x86_64/
Environment=JRE_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.422.b05-2.el9.x86_64/jre
Environment=CATALINA_HOME=/opt/apache-tomcat-8.5.99
Environment=CATALINA_BASE=/opt/apache-tomcat-8.5.99
Environment='CATALINA_OPTS=-server -Xms1024M -Xmx1024M -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512M'

ExecStart=/opt/apache-tomcat-8.5.99/bin/startup.sh
ExecStop=/opt/apache-tomcat-8.5.99/bin/shutdown.sh
ExecReStart=/opt/apache-tomcat-8.5.99/bin/shutdown.sh;/opt/apache-tomcat-8.5.99/bin/startup.sh

[Install]
WantedBy=multi-user.target
```

### サーバー起動時に自動的に起動するように
```
systemctl enable tomcat
systemctl start tomcat
```
S3 オブジェクトの暗号化

# 概要
S3ではオブジェクトを暗号化して安全に保存することが可能。
暗号化する場所とキーによって使い分けを行う。

# 暗号化の場所
暗号化の場所は以下の2箇所で実施できる
- クライアントサイド暗号化（CSE:Client Side Encryption）
- サーバーサイド（SSE:Server Side Encryption）

以下、それぞれを詳しく整理する。

## クライアントサイド暗号化
### 実施方法
オブジェクトをS3へ保存する際に暗号化を行う。
アップロードをリクエストする際にパラメータとして指定して実施する。

### キーの種類
キーは自由に選択できる。
オンプレミスのキー、AWS KMSので管理するキーでも暗号化が可能。

## サーバーサイド暗号化
### 実施方法
オブジェクトをS3へアップロードする前に暗号化を行う。
EC2やLambda、オンプレミスのアプリケーションなどで処理にて暗号化を実施する実施する。

### キーの種類
以下の3種類がある。

|キー|管理場所|説明|操作|使用時|
|-|-|-|-|-|
|SSE-S3|S3|オブジェクトにアクセスできる権限があればキーへのアクセスは可能。|- `s3:PutObject`：アップロード<br>- `s3:GetObject`：複合されたオブジェクトがダウンロード可能|オブジェクトが実際に保存されているディスク上で暗号化されていれば良い場合|
|SSE-KMS|AWS KMSのCMK（Customer Master Key）|ローテーション、無効化、削除などの操作が可能。<br>CMKにアクセスできるユーザーは以下で制御ができる。<br>- リソースベースのキーポリシー<br>- AIMポリシー<br>|アップロード時には以下の制御が必要<br>- `s3:PutObject`<br>- `kms:GenerateDataKey`の許可<br>ダウンロード時には以下の制御が必要<br>- `s3:GetObject`<br>- `kms:Decrypt`の許可|暗号化キーの管理、制御が必要な場合|
|SSE-C|オンプレミス|オンプレミスで生成したキーを使用してS3が暗号化を実施|- アップロード時：リクエストで暗号化に使用するキーを指定<br>- ダウンロード時：リクエストで暗号化に使用したキーを指定|- 組織のポリシーで独自に生成したキーを使用する必要がある<br>- AWSには暗号化キーを保存したくない場合|