OmniAICreator/Qiita-1.07M huggingface dataset:
バッジアイコンを表示

# サンプル

いきなりですが、サンプルです。
シンプルなデザインで2種作りました。

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="QWeGRej" data-pen-title="Untitled" data-user="cjlsrdxi-the-builder" 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/cjlsrdxi-the-builder/pen/QWeGRej">
  Untitled</a> by masayasu_t (<a href="https://codepen.io/cjlsrdxi-the-builder">@cjlsrdxi-the-builder</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

### ポイント
バッジに数値を表示させる際にhtmlのdata属性を使用しました。

htmlにdata属性を用意します。
```html:html
<div id="mailNumberBadge" class="mail-icon badge number-badge" data-badge_number=""></div>
```
cssのcontentでdata属性を参照します。
```css:css
.number-badge::after{
  content: attr(data-badge_number);
}
```
javascriptでdata属性に値をセットします。
```javascript:javascript
document.getElementById('mailNumberBadge').dataset.badge_number = 10;
```

##### 2024/10/11 追記
バッジ要素に「float: right;」を追加して、バッジを付ける要素のサイズによらず、右上に表示するようにしました。
LAN内のどこからでもサーバーにアクセスできるようにしようとしたらCORSエラーが発生した件

## やりたいこと

CORSエラーを解消したい

## 状況

- dockerで立てたバックエンドとフロントエンドの通信においてCORSエラーが発生する。
- CORSの設定はバックエンド（FastAPI）に設定済み
- IPアドレスをホストマシンのIPにバインドし、LAN内の端末からアクセスできるようにしたのでallow_originsをワイルドカードに変更した

## 調査

何が悪いか分からなかったのでdockerのポート設定とFastAPIのコードとどちらが悪いか切り分けることから始めた。結果としては、dockerに不備はなくFastAPI側ということが分かった。

色々ググったが結局わからなかったので開発者ツールでエラーを確認すると理由が載ってた。

<以下エラー文>

Access to fetch at 'http://hoge:8000/api/login' from origin 'http://hoge:5173' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

## 原因

クレデンシャルモードだったためワイルドカードが使えずアクセスチェックで不合格となっていた。

```python
# エラーを出していたコード（バックエンド）
app.add_middleware(
    CORSMiddleware,
    allow_origins = ["*"], #元々は"http:localhost:8000"を指定していた
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
```

```python
# 正しいコード（バックエンド）
app.add_middleware(
    CORSMiddleware,
    allow_origins = ["http://hoge:1234"],  # originを指定
    allow_credentials=True,　#ここがTrueならワイルドカードは使えない
    allow_methods=["*"],
    allow_headers=["*"],
)
```

```jsx
// エラーを出していたコード（フロントエンド（React））
const onSubmit: SubmitHandler<LoginForm> = (data) => {
    fetch('http://hoge:8000/api/login', {
      method: "POST",
      credentials: "include", //ここがincludeならワイルドカードは使えない
      headers: {
        "Content-Type": "application/json",
      },
```

## 解決策

ワイルドカードを使わず、オリジンを指定する。

ワイルドカードを使いたいならクレデンシャルモードを使わない。
　(ただしCookieを使ったログインなどはできなくなる)

## 最後に
解決まで３時間程度かかってしまったが、答えはすぐ近く（ブラウザのコンソール）にあった。エラー文を最初にしっかり読んでおけばすぐに解決できたはず...
今後はまずエラーから確認しよう(^_^;)
ref.の後に手が止まる、、、そんなあなたと私へ送る記事

# はじめに
私は、状態管理のコードを初めてみた時、何かの暗号ではないかと思うくらい複雑に感じました。
ですが本当によく出てくるものなので、覚えたもん勝ちだと思います！
私自身まだまだあやふやな部分があるので、復習がてら記事を書いてみようと思います。
今回は、私が特によく見てよく迷う **ref.read / ref.watch** と **ref.when / ref.maybeWhen** というメソッドについて説明します。

# Riverpodの基本概念
**Riverpod**
は、アプリでデータ（状態）を管理するためのものです。アプリ内のデータを扱いやすくしてくれます。アプリ内で必要な情報を一元管理して、どこからでもアクセスできるようにします。

**Provider**
アプリのデータ（状態）を管理し、他のウィジェットで使えるようにするものです。

**ref**
プロバイダーのデータを取得・監視・操作するための「鍵」のようなものです。
# ref.read と ref.watch の違い
###  ref.read()
ref.read()は、「**読むだけ**」→ 一度だけデータを取ってきます。
プロバイダーから1回だけデータを取得するメソッドです。ウィジェットの再ビルドは行われません。
ボタンを押したときなど、特定のタイミングでデータを取得したいときに使います。
### ref.watch()
ref.watch()は、「**見張ってる**(つまりwatching)」→ データが変わったら教えてくれます。
プロバイダーのデータを監視します。データが変わるたびにウィジェットが再ビルドされるため、リアルタイムに画面を更新したい場合に便利です。
カウンターのように、データが変わったら画面を自動的に更新したいときに使います。
# ref.when と ref.maybeWhen の違い
非同期データ（APIのレスポンスなど）を扱う際に使われます。

**※非同期データとは、処理が完了するまでに時間がかかるデータのことです。**
例えば、Web APIからデータを取得する場合、ネットワークの状況やサーバーの応答時間によって、データが返ってくるまで時間がかかることがあります。このような場合、処理がすぐに終わらず、待たなければならないデータを「非同期データ」と言います。

非同期データは、loading（読み込み中）、data（データ取得成功）、error（エラー）の主に3つの状態を持ちます。

###  ref.when()
ref.when()は、**すべての状態**（loading、data、error）に対して処理を定義するメソッドです。
データ取得中にローディングの表示、成功時にデータの表示、エラー時にエラーメッセージの表示したいときに使います。
### ref.maybeWhen()
ref.maybeWhen()は、
**特定の状態だけ**に処理を定義し、その他の状態には**orElse**で一括処理を適用するメソッドです。
データ取得成功時のみ特別な処理をしたいが、他の状態には共通の処理をしたいときに使います。

# まとめ
簡単にまとめると、
**ref.read / ref.watch** は、プロバイダーのデータを取得・監視するメソッドです。
**read**は1回だけデータを取得し、**watch**はデータが変わるたびに再ビルドします。
**ref.when / ref.maybeWhen** は、非同期データの状態（loading、data、error）に応じて処理を行うメソッドです。
**when**はすべての状態に対して処理を定義し、**maybeWhen**は特定の状態だけ処理を行います。


いかがでしたでしょうか。
**ref.** まで書いて「あれ、どっちだっけ？」と手が止まった時には、ぜひこの記事を見に来てください！
ここまで読んでいただきありがとうございました！
Template Haskellを触ってみた

久しぶりにHaskellを触ってみたくなったので、Template Haskellを試してみました。

本当に数年ぶりにstackを使ってみたら・・・ちゃんとビルドしてくれますね！本当にstackには頭が上がりません。

# Template Haskellとは

Hashellでメタプログラミングを可能にする仕組みです。
Cで言えばマクロに相当するらしいです。

もう少し具体的に言えば、コンパイル時にコードを生成して埋め込む仕組みです。

大雑把な理解としては・・・

1. コンパイラは、コンパイルが開始されたらTemplate Haskellで書かれたところを評価してHaskellコードに変換し、人間が書いたソースコードに埋め込む（これを接合と呼ぶらしい）
1. 接合されて完成形となったソースコードをコンパイルする

という流れです。

# 何が嬉しいのか

Haskellの美点の１つが狭量極まりない型安全性であることを否定する方はおられないでしょう。
Template Haskellは、動的でありながら型安全性を保つ仕組みです。

例えば、SQLのselect文の結果は複数のカラム名から成ります。SQL文を書き直せばカラム名のリストも変化するわけです。
この結果を型安全に取得する方法はいくつかアプローチがあると思いますが、Template Haskellが１つの解決策になります。

１つのアプローチとしてコード生成という手段がありますが、Template Haskellはそれを言語仕様の中に組み込んだものと言えます。

# 考え方

表記の仕方や準備は置いておいて・・・結局のところ **入力の文字列からHaskellのコードを組み立てるプログラムを書く** ことになります。

ということはHaskellのプログラムの構成を知っておく必要があります。
「式」や「定義」など、Haskellプログラム構成要素を押さえていないと、コード生成は難しいでしょう。

ただ、逆に、Template Haskellのライブラリを眺めることで構成要素を知ることが出来るので、調べながら書けば意外と何とかなるものです！

https://hackage.haskell.org/package/template-haskell-2.22.0.0/docs/Language-Haskell-TH.html#t:Type

# 作成した例

実プロジェクトではメッセージを台帳管理して、使う場合はメッセージ番号をキーにして取得する、という仕組みにすることがよくあります。
これを模した仕組みを作ってみました。

手抜きをして、メッセージはファイルではなくてHaskellの中に直接書く形としました。

これが、メッセージを定義してHaskellの関数に置き換えるプログラムです。
[messages|...|]の部分がTemplate Haskellです。
```hs
{-# LANGUAGE QuasiQuotes #-}

module Messages where

import Messages.Internal

[messages|
hoge hoge-messages
piyo ピヨ
|]
```

この```messages```を自作できるのがTemplate Haskellの面白いところです。

# 挑戦したいこと

なぜTemplate Haskellを扱いたくなったかというと、最近SQLに触れる機会が多いからなのでした。
SQLは集合を扱うとても便利で重要な言語ですが、動的な要素が多く、簡単にミスを作り込んでしまうという側面があります。
Tempalte Haskellのような仕組みを使って、クエリを安全に書いたり、結果を安全に取得できたらいいな・・・と思ってTemplate Haskellを触ってみたのでした。

ただ、世の中にはすごい方々がいるわけです。
例えば[VSCodeでSQLを書いていたら、DBからメタデータを持ってきて候補を表示してくれるツール](https://qiita.com/lighttiger2505/items/5782debc59ae163a4d81)を作っている方とか。

あるいは、C#のLINQ+EntityFrameworkも非常に優れた仕組みですね。あれには脱帽します。（状態の追跡は余計だが・・・）

これらの作品には到底敵わないとは知りつつ、しかも車輪の再発明になるということも重々承知しつつ、やっぱりメタプログラミングって楽しいんですよね！

いつかはTemplate Haskellで安全に長大なSQLを書くツールを作って、Haskellでバックエンドを書いてみたい！と思うのでした。

以上。
PythonプログラムのExe化：cx_Freezeの使用

# 概要

* cx_Freezeのモジュールを用いて、Pythonプログラムをexe化する方法を記載
* cx_Freezeの詳細は以下を参照のこと
    * https://cx-freeze.readthedocs.io/en/stable/
* CUI(コマンドプロンプト、ターミナルなど)操作でpythonを実行できる前提で記載


# インストール
* cx_Freezeは、pip、condaどちらでもインストール可能
    
    ```
    pip install --upgrade cx_Freeze
    ```
    ```
    conda install conda-forge::cx_freeze
    ```

# 実行
* Exe化する方法は大きく3通りあるが、個人的に使用しやすいsetupスクリプトを使用する方法を示す
* Exe化の方法
    * https://cx-freeze.readthedocs.io/en/stable/overview.html

        
* cx_Freezeのsetupファイルは以下で作成できる


## 手順

### 1. exe化したいpythonファイルの場所までコマンドプロンプトで移動

### 2. 以下のコマンドを実行

```
cxfreeze-quickstart
```

### 3. 指示に従い、回答する
   1. Project name: 任意のプロジェクト名を入力
   2. Version: バージョンを入力
   3. Description: 本プロジェクトの説明を記載
   4. Python file to make executable from: 実行ファイルを作成するpythonファイルを記載
   5. Executable file name: 実行ファイル名
   6. Console, Gui, Serviceを選択：C/G/S
   7. 保存するセットアップファイル名を記載：ファイル名
   8. build（exe化）このままするか？：y/n

   <br>


### 4. 必要に応じて、setup.pyの中身を確認する

* build_optionsは、ある程度自動的に認識してくれるが、exe化後にパッケージやモジュールがないなどのエラーが表示される場合は、'packages', 'includes'に明示する。
* 'include_files'は、exe化したフォルダにコピーするファイル
* その他の詳細は以下
    * https://cx-freeze.readthedocs.io/en/stable/setup_script.htm

* setup.pyファイルの例


    ```python
    from cx_Freeze import setup, Executable
    
    # Dependencies are automatically detected, but it might need
    # fine tuning.
    build_options = {
        'packages': ['pyautogui', 'pygetwindow', 'pynput'], 
        'excludes': [],
        'include_files': ['setting.txt']
        }
    
    base = 'console'
    
    executables = [
        Executable('hoge.py', base=base)
    ]
    
    setup(name='hoge',
          version = '1.0',
          description = '',
          options = {'build_exe': build_options},
          executables = executables)        
    ```


### 5. exe化(build)

* exe+dlls(portableなexeファイル/フォルダ作成)の場合は、以下を実行すれば、buildのフォルダ下層にexeファイルが作成される

    ```python
    python setup.py build
    ```


* msi(Windowsのインストーラ作成)の場合は、以下を実行すれば、distフォルダ内にmsiファイルが作成される
 
    ```python
    python setup.py bdist_msi
    ```


# その他

exe化する他のモジュールは以下など。
* Pyinstaller
    * https://pyinstaller.org/en/stable/
* py2exe
    * https://pyinstaller.org/en/stable/
minecraftで荒らされたので警察に通報した話

## はじめに

1. かなり特殊な事例のため、大体の人の参考にはならないです。こんなこともあるんだなぁと他人事で済ませてください。
1. 大筋は同じですが細かいところで嘘があったりなかったりします。個人等が特定されない配慮です。一部で不整合が起きるかもしれませんがご了承ください。
1. 年数が経ちすぎて（約7年ほど前）普通に忘れている部分はあります。不十分なところは察してください。

## 前提
当時の僕はバカです。セキュリティとかいう文字は頭の中に一切ございません。

## あらすじ
minecraftの鯖管をしていたら、普通にプレイヤーAにワールドを荒らされた
↓
プレイヤーBから「荒らし対策の便利なプラグインあげますよ！」と言われ、ホイホイとそのプラグインを導入
↓
更に荒らされる
↓
泣きながら荒らしの始末をしていたら、鯖のファイルが消されていることに気づく
↓
自分「これ不正アクセス禁止法(※1)で通報できんじゃね？　#9110(※2)や！」
↓
犯人（B）見つかる

## 結局何が起きたの？
基本的にはあらすじの通りだが、それぞれを詳しく解説していく。

### そもそも荒らしとは？
minecraftの鯖管をやったことがある人であればほとんどの人が経験している荒らし。そのやり方は様々であり、例えばTNTを爆破させワールドを破壊する行為、ボートなどのエンティティを大量に出現させ物理的に鯖を破壊する行為など様々なものがある。
つまり、何かしらの創造物を破壊するなどして、通常のプレイヤーに不快な思いをさせるもの全般を荒らしと呼んで良いだろう。

### 荒らされる経緯
前提にもある通り、当時の自分はそもそもminecraftの荒らしに対する知識が一切と言っていいほど皆無であった。今まではプレイヤー側で遊んでいたのみであり、「そうだ、サーバーを建てよう」レベルの突発的なものだった。
それでいてわざわざJMSに登録するなど人数を集めることには非常に用意周到である。当時は、荒らしというものは完全に他人事に捉えており、性善説を信じきっていた。（ちなみにこの急に思い立って鯖を立てるような行動力が後に活かされる。）
ある時、JMSを見てプレイヤーAが入ってきた。荒らし対策も何もしていないような鯖だったため、いとも簡単に荒らされてしまった。worldGuardなどの基本的な荒らし対策は行っていたが、逆に言えばその程度の対策だと簡単に突破されてしまっていた。


### 変なプラグインを入れちゃった
実は荒らされていた時間とほぼ同時刻に、プレイヤーBから「コマンドのログを管理者権限を持っているユーザーに垂れ流すプラグインあげましょうか？」との申し出があった。ちょうど荒らされていたときにその申し出は非常にありがたく、もらえるものはもらっとけ精神でそのプラグインを導入した。
ちなみに他の人のコマンドの履歴が見れるようにしたかった理由としては、荒らしがワールドを荒らす時に何かしらのコマンドを使うということは把握していたので、それが見れたら少しはマシになるよねというものだった。

### 二度目の荒らし
当時は学生だったため、平日の昼間は鯖には常駐していない。その隙を突かれ（別に突いていないと思う）不在中に荒らされた。学校から家に帰り自分は絶望した。また荒らされていたのだ。しかも、木っ端微塵に。ワールドがぐちゃぐちゃになっているとかそんな生易しいものではなく、そもそもワールドすらなかったのだ。サーバーすら起動していなかったのだ。直感的にやばいと感じ、すぐに被害状況の確認を行った。

### なにもない
被害状況を確認したところ、鯖のファイル群のみならず他のフォルダーも消されていた。
明らかにフォルダーごと消去をかけて、実行中のものだけ消去できずに残っていたような痕跡だった。
綺麗さっぱりファイルたちがなくなっていたのだ。

### そして通報へ...
ここで先ほどの行動力が役に立つ時が来た。何を考えたか法律の条文を読み漁り、なんとかして警察に通報できないか死に物狂いで適用できそうな条文を探したのだ。
結局、この条文に引っかかるんじゃね？ってことで警察に#9110で通報した。

>不正アクセス行為の禁止等に関する法律
>第二条　
>中略
>４　この法律において「不正アクセス行為」とは、次の各号のいずれかに該当する行為をいう。
>三　電気通信回線を介して接続された他の特定電子計算機が有するアクセス制御機能によりその特定利用を制限されている特定電子計算機に電気通信回線を通じてその制限を免れることができる情報又は指令を入力して当該特定電子計算機を作動させ、その制限されている特定利用をし得る状態にさせる行為

→つまり、本来権限がなくてできないことを何らかの手段でその権限外して制限されてることしちゃだめよってこと
今回で言うと、ファイルの削除という本来できないことを制限外してやったことになる。

てな感じで、とりあえず警察に電話をしてみた。
自分「あのー...PCが不正アクセスされたんですけど...」
警察「とりあえずその担当の部署につなぎますね」
ぐらいの割と軽いノリでその部署に繋いでくれた。
110するのは躊躇うけど、#9110は相談前提だから困ったことあったら普通にかけたほうが良いよ、マジで。

その担当部署に繋がれてからは本当に話進むのが早かった印象だ。
容疑者特定までの細かいところは端折るが、実は鯖のデータ丸ごと削除された時にサーバーのログが残っていた。
そのログに残っていたIPとかその他諸々の情報が決め手になり容疑者Bが見つかった。
（例のごとくBはIPにプロキシを噛ましていたらしいが警察は突破して直IPを引っ張ってこれたらしい。）

その後、容疑者Bは無事に「児童相談所に通告された」と警察から聞いた。（このときの言い方は送致では？）

:::note warn
警察への通報から解決までここまで9ヶ月かかりました！
二度とやりたくないです！
:::

### 最初と2度目の荒らしの関連性
知らん。この２名が裏で繋がっていたかマジで無関係なのかは分からん。

## 教訓
度を越すとマジで警察動かせるから荒らしはやめたほうが良いよ。


## 出典
※1：https://laws.e-gov.go.jp/law/411AC0000000128/20121101_423AC0000000074
※2：https://www.gov-online.go.jp/useful/article/201309/3.html
【iPad】連続する - が ——— のように繋がらないようにする方法

iPadで英字入力しているときにで連続でハイフンを入力すると `———` に変換されます。

![ScreenRecording_10-30-2024 23-49-58_1 2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/6c022e29-5ec7-2447-be68-dc0a0684b3b4.gif)

設定 > 一般 > キーボード > スマート句読点 のチェックを外すことで改善されます。
LambdaをVPC内に作成する際、IAMロールに対するポリシーが足りずにエラーになった

# 開発環境

- Lambda
- VPC

# 前提

VPC内にLambdaを作成しようとしたところ、IAMロールに対してポリシーが不十分だよと指摘された。

# 発生したエラー

```basic
The provided execution role does not have permissions to call CreateNetworkInterface on EC2
```

# 内容
このエラーメッセージは、AWS Lambdaや他のサービスがEC2インスタンス上にあるネットワークインターフェース（ENI:Elastic Network Interface）を作成しようとしているが、アタッチされているIAMロールにその操作を行うための適切な権限がないことを示している。

この場合は、IAMロールに適切なポリシーが付与されていないことによるエラーメッセージとなる。Lambda関数がVPC内のリソース（例えば、RDSやEC2）にアクセス または作成される際、ネットワークインターフェースを作成するためにこの権限が必要。

VPC内で動作するLambdaはネットワークインターフェース（ENI）を使用してVPCリソースにアクセスするため、適切なVPCサブネット及びセキュリティグループも必要らしい。

# 試したこと

- ```IAMロールにCreateNetworkInterfaceなどの関連するポリシーをアタッチした```

### IAMロールにCreateNetworkInterfaceなどの関連するポリシーをアタッチした

```jsx
			"Action": [
				"ec2:CreateNetworkInterface",
				"ec2:DescribeNetworkInterfaces",
				"ec2:DeleteNetworkInterface",
				"ec2:AttachNetworkInterface"
			],
```

> **AWSLambdaVPCAccessExecutionRole** を関数の実行ロールにアタッチすることで、関数に必要なアクセス許可を付与できます。
> 

ドキュメントに、[このような記載](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-vpc.html#:~:text=AWS%20%E7%AE%A1%E7%90%86%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC,ec2%3AUnassignPrivateIpAddresses)がありました。

> 独自の IAM アクセス許可ポリシーを作成する場合は、次のアクセス許可をすべて追加してください。
> 
> - **ec2:CreateNetworkInterface**
> - **ec2:DescribeNetworkInterfaces**
> - **ec2:DescribeSubnets**
> - **ec2:DeleteNetworkInterface**

上記ポリシーをIAMロールにアタッチすることで、VPC内にLambdaを作成する事ができました。

# まとめ

Lambdaはデフォルトでは、VPC外に置かれているため、VPC内に置く場合はIAMロールに対してポリシーの設定が必要みたいです。
Sophos Firewallで自宅セキュリティ

## やること
Sophos Firewallを導入してLANのセキュリティを向上する。

## 背景と前提
以前のネットワーク図でSophos Firewallを入れている形としていたが、
FW(UTM)をLANとの接続の間でどうしても入れたかった。
エンドポイントセキュリティとネットワーク的な入口防御を自宅でも入れるべき。
特化したNW機器を入れるのは高額すぎなので安価に実現できる方法とする。

## 導入機器
#### TRIGKEY G5
SophosのためLANを2ポート揃えたもの及び2.5G以上が望ましい。
常時起動のため消費電力の少ないものを考慮したがいい。
上記を考慮するとTRIGLEY G5がちょうど良かった。
intel N100は意外とちゃんと動くからイイゾ。

https://amzn.to/3YMC9IY

![PXL_20241027_143123703.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918883/f4788df5-9cfd-c96f-96e3-b9b1b952aebd.jpeg)

#### VMware Workstation Pro
VMwareがBroadcomに買収されてからPro版が個人利用で無償になったので、
VMware Workstation Playerから卒業。仮想NWが弄れるし制限が少ないから快適。

https://blogs.vmware.com/teamfusion/2024/05/fusion-pro-now-available-free-for-personal-use.html

#### Sophos Firewall Home Edition
UTMしたいけどサブスクライセンスは個人では無理。
PaloAltoを入れたら破産するのを考えるとUTMではこれ一択。
個人として登録すれば2999年まで使えるライセンスを貰える。

https://www.sophos.com/ja-jp/free-tools/sophos-xg-firewall-home-edition

![スクリーンショット 2024-10-30 223608.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918883/146a2723-d76e-d9a1-8b0d-5cbc9e07db99.png)

#### AlmaLinux & ZABBIX
CentOS君が死んだので、その後継としてRHEL系の無料OSでAlmaLinux一択。
今後メーカー系でCentOSベースでソフトウェア提供してたところは、
おそらく全てAlmaLinuxになるか互換があるようになるので理解しておくのが吉。
ZABBIXは自宅内の機器監視と技術が錆びないようになんとなく。

https://almalinux.org/ja/

https://www.zabbix.com/download

## ベース構築
何で直接端末にインストールしていないのかというとSophosの制約。
BIOSがUEFIではなくレガシーモードじゃないとBooting...から進まない。
TRIGKEY G5のCMAでLegacyが選べるがBootしなかったのでライセンス付いてるし、
Windows11で何かするのが良いだろうと以下のような構成です。

![TRIGKEY-G5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918883/4e781cc1-88aa-7f8f-719a-4213658d2a12.jpeg)

## Sophos Firewall導入
VM上への展開方法は個別に調べていただくとして、
Sophos Firewallの制約であるリソースは以下で構築してます。

アドレスもブリッジしている関係上、Sophosのインストール後に、
CLI上からLAN側のIPアドレスはデフォルトから変更している。
変更方法はプロンプトに出てくる英語が読めれば誰でも分かる。

| 項目 | 値 |
|:-:|:-:|
| vCPU | 4コア |
| Mem | 6GB |
| HDD | 100GB |
| NIC | VMnet1(物理eth1のブリッジ)|
| NIC | VMnet2(物理eth2のブリッジ) |

## Sophos Firewall確認
導入完了したら以下のアドレスでブラウザからアクセスする。
ポート番号が4444なのを忘れず。
https://{sophosで設定したLAN IP}:4444/

![スクリーンショット 2024-10-30 232023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918883/e3121b41-38c6-538e-09fc-505adf636987.png)

![スクリーンショット 2024-10-30 222932.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918883/06523bb1-2cd8-d79f-a800-bf3b7a648f53.png)

## Sophos Firewall設定
細かいことは自分でも分からないのでヘルプなりコミュニティなりで、
頑張って個人で調査いただく他ないが、ひとつアドバイスとしては、
適当かつ安易にIPS,APP,wAF,DOSとかSSLinspectとかを設定すべきではないです。

![スクリーンショット 2024-10-30 223024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918883/fd6542ff-3bcc-138d-8351-776d87cb0abf.png)

![スクリーンショット 2024-10-30 223515.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918883/96b7f1cc-e93a-605d-56c8-41a29049618e.png)

## Sophos Firewall所感
メインPC(エンドポイント)で色々していると凄く通信をブロックしてくる。
機能的にも商用を考えてやってる製品なんだと感じる。

レポート内容を見てもらえると分かるがメインPCにNordVPNを導入しているせいで、
結構不審な通信だとSophos君には思われ、NordVPNも何か変な接続の仕方しすぎ。

SSLインスペクションは全部止めるのでこの製品ではオススメしない。
（もちろんSophosでの自己証明書をメインPCに投入済みでもNG）

## 現状の自宅ネットワーク(2024/10/30)

![ysapt20241030.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918883/12d5a2ad-ddd4-2de0-f755-7f7d16b1fbf7.png)
【勉強会レポート】プロジェクト成功への挑戦：IPAモデル契約書とAgile Studioの事例から学ぶアジャイルの本質

-いつも記事を読んでいただきありがとうございます！
モブエンジニア（[@mob-engineer](https://qiita.com/mob_engineer))です！

今回は、10/30（水）に開催された「プロジェクト成功への挑戦：IPAモデル契約書とAgile Studioの事例から学ぶアジャイルの本質」の参加レポートになります！

アジャイル初心者視点で記事を書いておりますので、お気軽に読んでいただければ幸いです。

:::note info
本記事は**プロジェクト成功への挑戦：IPAモデル契約書とAgile Studioの事例から学ぶアジャイルの本質**に関する参加レポートとなります。
connpassイベントページ：https://developer-productivity-engineering.connpass.com/event/330205/
:::

# 目次
1. 参加したきっかけ
1. イベント概要（Connpassページより抜粋）
1. LT（途中参加のためIPAモデル契約については省略）
    1. 受託開発でのアジャイル奮闘記
    1. パネルディスカッション
1. まとめ

## 参加したきっかけ
イベントに参加したきっかけとして3点あります。

1. 開発プロジェクトで用いる契約に関する知識キャッチアップ
1. アジャイル開発のケーススタディをキャッチアップ
1. IPA モデル契約の概要キャッチアップ

## イベント概要（Connpassページより抜粋）
>本イベントではアジャイル開発の契約や実務における課題をテーマに、IPA（情報処理推進機構）が策定した「情報システム・モデル取引・契約書（アジャイル開発版）」の背景や実際の開発事例を深掘りします。
策定に関わった株式会社永和システムマネジメント 木下様より、契約書の重要ポイントやその役割を通じ、プロジェクト成功の鍵となる契約の本質を学びつつ、事業会社におけるPO・開発者間の信頼構築と開発の進め方についても知見を共有いただきます。
また、Agile Studioによる実際の開発現場での経験談から、具体的なアジャイル開発の挑戦と成功の秘訣を坂井様、藤田様よりご紹介いただくことで、あらゆる制約の中でいかにアジャイル開発推進をしていくべきか、糸口がみつかるようなイベントを目指します！

## LT（途中参加のためIPAモデル契約については省略）

### 受託開発でのアジャイル奮闘記
- ポイント：**ユーザ（顧客）との対話をいかに行っていくか**
- 最初のプロジェクト開発
    - ユーザとのコミュニケーションがほとんどない状況
        - 結果として、成果物のすり合わせが行えておらずプロジェクトをうまく推進できなかった
- プロジェクト失敗から見えた対策
    - ユーザとの定期的のミーティング活動（週１回程度）
    - ユーザ先への対面訪問（月１回程度）
    - メンバー主体で業務を任せていく（=チームリーダ主導でプランニング計画を考えない）
    - **双方向コミュニケーション**が行える報告資料を作っていく
        - 単純な業務報告ではユーザは受け身になってしまう
- まとめ
    - プロジェクトによって進め方は変わっていくため適切なアプローチを考えてみる
    - **ユーザ第一**の観点を忘れずにプロジェクトを推進していく

### パネルディスカッション
- 開発プロジェクトでの仕事の進め方について？
    - 複数プロジェクトを掛け持ちしていると**時間単位**でタスクを切り替えていくが、スイッチングコストが都度発生するため非効率
    - 可能であれば、月単位で一区切りをつけていくことが必要
- 顧客との成果物すり合わせについて
    - とりあえず動くもので認識合わせを行い、徐々に要件にすり合わせていく
    - 担当者間での認識合わせだけでなく、**マネージャー間**での認識合わせを行っていくことも必要
- 開発ドキュメントの粒度（何を、どこまで、どのように記述するか）について
    - プロジェクトの状況に代わってくるため、ユーザとのコミュニケーションを通じて粒度合わせを行っていく
- Done（完了条件）の定義について
    - Done定義前の初期段階でユーザとの期待値合わせ（何ができていれば良いかなど）を行っていく必要がある
    - いきなりすべての完了条件を決めきるのではなく、小さな完了条件を決めていくことも大切（小さなことから行っていく）
    - 可能であれば、契約書を取り交わす段階で**Doneの見直し**を行った方がいい

## まとめ
IPAモデル契約に関するLTに参加できなかったのは少し残念でしたが、**アジャイル開発を通じたユースケース**についてキャッチアップすることができたので、有意義だと感じました。
そのうえで、**IPAモデル契約**の全体像を私自身がきちんと把握しきれていないので、キャッチアップしていかないといけないなぁと感じています。キャッチアップした結果に関しては、記事としてアウトプットしていく予定です。

## 参考サイト
[情報システム・モデル取引・契約書（アジャイル開発版）](https://www.ipa.go.jp/digital/model/agile20200331.html)
[アジャイル開発とは？手順から特徴やメリット・デメリットを解説](https://it-trend.jp/development_tools/article/32-0013)

:::note info
最後まで記事をお読みいただきありがとうございます。本記事を通じて、**IPAモデル契約**や**アジャイル開発**に関して少しでも興味を持っていただければ幸いです。
もし、記事の内容を読んで「良かった」と思った方は**いいね**と**ストック**をお願いいたします👍
:::
【MySQL】外部キー制約の制約名をあとから変更する場合

MySQLでテーブル作成時に制約名を省略した外部キー制約に対し、テーブル作成後に制約名を指定するためには、以下の手順で対応します。

## 手順
### 1. **既存の外部キー制約を削除**
   - 最初に、デフォルトで生成された制約名で設定された外部キー制約を削除します。

### 2. **新しい制約名を指定して外部キー制約を追加**

例えば、`orders` テーブルに `user_id` カラムを持ち、`users` テーブルの `id` に対する外部キー制約があるとする

```sql
CREATE TABLE users (
    id INT PRIMARY KEY
);

CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    user_id INT,
    FOREIGN KEY (user_id) REFERENCES users(id)
);
```

ここで外部キー制約にデフォルトの名前がつけられますが、これを後で任意の制約名 `fk_orders_user_id` に変更したい場合の手順は次のとおり。

#### 2-1. 既存の外部キー制約を削除
デフォルトの制約名は `SHOW CREATE TABLE` コマンドで確認できます。

```sql
SHOW CREATE TABLE orders;
```

これにより、現在の外部キー制約の名前が表示されます（例：`orders_ibfk_1` など）。この名前を使って、外部キー制約を削除します。

```sql
ALTER TABLE orders DROP FOREIGN KEY orders_ibfk_1;
```

#### 2-2. 新しい制約名で外部キーを再追加
新しい制約名を指定して外部キー制約を追加します。

```sql
ALTER TABLE orders
ADD CONSTRAINT fk_orders_user_id FOREIGN KEY (user_id) REFERENCES users(id);
```

### 補足
- **制約名の確認**：`SHOW CREATE TABLE` で確認すると、新しい制約名で設定されていることが確認できます。
- **まとめて行うことも可能**：複数の外部キー制約がある場合も、同じ手順で削除と追加を行えます。
基本情報技術者試験　合格体験記(情報系学生向けおすすめ勉強法)

## 基本情報技術者試験とは？

ITエンジニアの登竜門とも言われている試験です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794915/592b4125-fc64-63a2-be4e-092d4995a0e1.png)
以下のように定義されています。IT分野について、幅広く問われる試験です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794915/63a94c4a-af4b-cd95-95d5-c8175d1c1432.png)

## 問題形式について

CBT形式で受けられます。

選択式の問題でA問題が60問、B問題が20問です。A問題は、知識を問うような問題が、B問題では、8割がプログラミングやアルゴリズムに関して、2割りが情報セキュリティについて　少し考えるような問題がでます。

## この記事の対象者
ある程度、大学などでプログラミングやアルゴリズムについての知識はあるが、実務の経験などはない情報系の大学生などにおすすめです。

## 1. 基本情報技術者試験を受験した理由

私がこの試験を受けようと思った理由は二つあります。

自分の大学ではこの試験を合格していると、単位認定される制度がある。
ある程度のIT分野での知識があることの証明になる資格であると思ったから。

以上の二つの理由で受験しようと思ったのですが、結果的には大学では、あまり学ぶことが少ない、ストラテジ系やマネジメント系や経営戦略　などの分野についても学ぶことができて、そういったビジネス的な面での知識もしることができたので良かったのではないかなと思っています。

## 2.勉強法

僕は以下の二つを使って、1週間ほど試験対策の勉強を行いました。
情報系の学生であれば、B問題のアルゴリズム系の問題は難しくないと思いますが、A問題に関しては、知識として覚えることが多いので手を抜かずしっかり勉強しましょう。
個人的には以下の勉強法でかなりコスパよく学べて良かったと思っています。また他の方の勉強法も見つつ参考にしてください。


・すーさん【基本情報技術者試験Youtuber】の動画を見る。
特に以下のA問題を網羅的に解説してくだっている動画を何回か僕は見ました。
アルゴリズム系などで聞かなくてもわかる分野があるなら飛ばしてもいいと思います。

https://youtu.be/oqaBEnhIxk0?si=2FFNr9tt917AzsJC



・過去問道場で過去問を解く

やはり、この過去問演習が一番合格の近道だと思います。試験前はたくさんしましょう。
解説もされているので、そこでも新しい知識を覚えてましょう。


※Ｂ問題に関しては、僕はあまり対策をしませんでした。情報系の学生でそこそこ真面目に授業受けて単位取得していれば聞いたことがある内容が多いです。少し過去問をといてみてもし、不安があれば、基礎的な内容なので、しっかり復習した方がいいと思います。

## 結果と感想
1000点満点で、どちらも600点以上が合格の基準らしいです。A問題は、なかなか知らない問題もでて焦りましたが合格することができました。　個人的には、学校の授業ではあまり学ばないビジネスよりの考え方なども学べて、試験受けて良かったと思っています。

とっておいて損のない資格だと思うので、時間とお金に余裕があれば是非、大学生の内にとってみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3794915/5fd2b998-db79-573f-e18c-e0450187ad6a.png)
【Django REST Framework】swaggerにPageNumberPaginationのレスポンスが表示させる（力技）

# 前置き
初学者なりの知らなかったというお話なので、多くの方には関係のない内容です。

# 問題
実際に返却されるレスポンスは問題ないけど、swaggerにページネーション形式のレスポンスが表示されない
```python
@extend_schema(responses=SongListSerializer, tags=["song"])
class SongListView(views.APIView):
    pagination_class = CustomPaginator

    def get(self: Self, request: Request, *args: Any, **kwargs: Any) -> Response:
        """曲一覧情報の取得"""
        songs = Song.objects.alive().select_related("album", "artist").all()
        paginator = CustomPaginator()
        result_page = paginator.paginate_queryset(songs, request)
        serializer = SongListSerializer(data=result_page, many=True)
        serializer.is_valid()
        return paginator.get_paginated_response(serializer.data)

```
あれ。。

![スクリーンショット 2024-10-30 23.16.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737553/eaf0dd0f-4f07-c139-eeb6-8142c18ac27e.png)

実際にリクエストを送るとページネーション形式のレスポンスが返る
![スクリーンショット 2024-10-30 23.18.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737553/98507ab4-1b11-0fc1-960f-27415c9f6460.png)


# 解決
```python
from drf_spectacular.utils import extend_schema, inline_serializer
@extend_schema(
    responses={
        200: inline_serializer(
            name="PaginatedSongResponse",
            fields={
                "count": serializers.IntegerField(),
                "next": serializers.CharField(allow_null=True),
                "previous": serializers.CharField(allow_null=True),
                "results": SongListSerializer(many=True),
            },
        ),
    },
    tags=["song"],
)
class SongListView(views.APIView):
    pagination_class = CustomPaginator

    def get(self: Self, request: Request, *args: Any, **kwargs: Any) -> Response:
        """曲一覧情報の取得"""
        songs = Song.objects.alive().select_related("album", "artist").all()
        paginator = CustomPaginator()
        result_page = paginator.paginate_queryset(songs, request)
        serializer = SongListSerializer(data=result_page, many=True)
        serializer.is_valid()
        return paginator.get_paginated_response(serializer.data)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737553/e701c4d6-c1dd-0fc7-ee0d-8569478f58c5.png)

えぇ。。。。

こんなデコレータ書かないといけないんですか。。。

なにかいい方法はないものでしょうか？
【MySQL】テーブル作成時に外部キーの制約名を省略すると、、

## 背景
テーブル定義書をもとに、各テーブルを作成する際、FKの製薬名が未定の状態だった。制約名を省略して以下のようなDDLを流した場合、制約名はどうなるのだろう、と思い調べてみた。
```sql:
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    user_id INT,
    FOREIGN KEY (user_id) REFERENCES users(user_id)
);
```

## 結論
外部キー制約（FK）を定義する際、制約名を省略すると、デフォルトの制約名が自動的に生成される。
- デフォルト制約名：<strong>``<テーブル名>_<カラム名>_fk``</strong>

今回の場合は、``orders_user_id_fk``となる。


## 【余談】 制約名を指定してテーブルを作成する場合
```sql:
CREATE TABLE orders (
    order_id INT PRIMARY KEY,
    user_id INT,
    CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(user_id)
);
```
ATtiny85を使用して15分間隔できちんと休憩できる装置を作ってみた

現在プログラミングの仕事をしているが集中すると
ついつい休憩せずにぶっ通しで1時間くらい仕事をしてしまう。

しかし間できちんと休憩をした方が作業効率は上がるみたいだ

ということで今回は15分経過すると休憩を促すような
装置を開発してみた。

使用したのは以下

## ハードウェア
１、余っているLED　１個
２、余っているバッテリケース（単３✕２本）　１個
３、余っているプッシュボタン　１個
４、余っているセレクトスイッチ　１個
５、余っているATTiny85　１個
すべて余り物で作成した

## データ書き込み
ArduinoUNOを書き込み装置に作り変えて
ATTiny85に書き込みをする。
詳細は以下のURLを参照してください。
https://qiita.com/Kurogara/items/23a471cc0037303dcd17

## プログラム
```c
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>

int LED_PIN = 4;
int Button_PIN = 3;

// watchdog interrupt
ISR(WDT_vect) {
  wdt_disable();  // disable watchdog
}

void setup() {
  delay(1000);
  //  ピンの設定
  pinMode(LED_PIN, OUTPUT);
  pinMode(Button_PIN, INPUT_PULLUP);
  digitalWrite(LED_PIN, HIGH);
  delay(500);
  digitalWrite(LED_PIN, LOW);
}

void loop() {
  for (int i = 0; i < 112; i++) {
    myWatchdogEnable(); //8秒スリープ
  }
  
  while(digitalRead(Button_PIN) == HIGH){
    delay(500);
    digitalWrite(LED_PIN, HIGH);
    delay(500);
    digitalWrite(LED_PIN, LOW);
  }
}

void myWatchdogEnable() {
  noInterrupts();  // timed sequence below
  MCUSR = 0;       // reset various flags
  // allow changes, disable reset
  // Le registre a un nom différent par rapport à l'ATmega328 : `WDTCR` % `WDTCSR
  WDTCR = bit(WDCE) | bit(WDE) | bit(WDIF);   // set WDCE (Watchdog Change Enable), WDE (Watchdog System Reset Enable)
  WDTCR = bit(WDIE) | bit(WDP3) | bit(WDP0);  // set interrupt mode and an interval 8s (cf. datasheet p45-46)
  wdt_reset();                                // pat the dog

  byte adcsra_save = ADCSRA;
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  // sleep mode is set here
  ADCSRA = 0;                           // disable ADC
  // Important note! You must use the PRR after setting ADCSRA to zero,
  // otherwise the ADC is "frozen" in an active state.
  power_all_disable();  // turn off all modules
  noInterrupts();       // timed sequence follows
  sleep_enable();
  interrupts();
  sleep_cpu();  // now goes to Sleep and waits for the interrupt

  sleep_disable();       // cancel sleep as a precaution
  power_all_enable();    // turn on all modules L'ordre est important !!
  ADCSRA = adcsra_save;  // stop power reduction
}  // end of myWatchdogEnable
```

setup()の箇所でPINの設定
loop()の箇所でmyWatchdogEnable(); //8秒スリープ
を112回することで約15分の待機を行っています。

待機を抜けるとLEDを点滅。
ボタンが押されるとLOWになるのでまたスリープのループに入ります。

## 配線
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/cea604ad-38e6-549e-7e00-64d07ed9a88b.png)

## 実機
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/bd6f03bc-6618-dd80-4e5e-1b74b894e01b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/bc6cfe99-9faf-5f71-e44c-21dd583578f9.png)

あまりがあれば実質0円で作成できるので
皆さんも15分の休憩を定期的に取りたい方は参考にして作成してください！

休憩は大事ですよ～
【Microsoft Azure】AZ-104 合格体験記

# はじめに
2024年10月にMicrosort社の提供するクラウドAzureに関する試験「AZ-104」を受験し、合格しました。
この記事ではAZ-104を合格するための勉強法について紹介します。

# AZ-104とは
「Azureの基本」いうべき知識や技術を習得しているかを示すための指標となる資格です。
資格名にあるAdministrator（管理者）だけでなく、開発者、ソリューション提案/設計/構築を行うために必要な知識を求められる資格ではありますが、
あくまで基本レベルの話であり、そういった意味ではクラウドサービスやMicrosoft Azure に初めて触れる方を対象にした「AZ-900」と重複する内容も散見されます。

違いとしてはAZ-900が本当の意味で"初めて触れる"人に向けた内容であるのに対し、AZ-104は"これからAzureを使って何かをしていく"人に向けた内容であると言えます。

AZ-104の詳細は下記Microsoftの公式サイトをご確認ください。
[Microsoft Certified: Azure Administrator Associate](https://learn.microsoft.com/ja-jp/credentials/certifications/azure-administrator/?practice-assessment-type=certification)

# 試験範囲
大枠としてはAZ-900で学んだ知識の深彫り、ないしそこからやや範囲を広げた概念・知識に関して出題されます。
具大抵な出題観点としては以下の五つが挙げられます。

- Azure ID とガバナンスを管理する (20～25%)
- ストレージを実装して管理する (15～20%)
- Azure のコンピューティング リソースをデプロイおよび管理する (20～25%)
- 仮想ネットワークを実装および管理する (15～20%)
- Azure リソースの監視と管理 (10～15%)

加えて5、6問程度ですが実際のユースケースを想定した出題もあり、設問によっては解答選択肢に正解がない（全ての設問で"問題解決に至らない"と回答するケース）もあります。


# 学習開始時点での知識
AZ-900に合格しており、大まかな事前知識は揃った状態でのスタートとなります。
AZ-104はそれを深彫りないし発展させた知識に関する習得を目的としておりますが、物によっては既に習得済みの知識の再確認に近いものもあった印象です。

# 学習期間
2023年に一度半年程度の学習期間を経て受験しておりますが、その時は不合格（正答率50%程度）でした。
これは後述する参考書の問題もあったと考えたため、参考書を変えて今年度も同期間学習したところ無事合格出来ましたので、実質的な学習期間は同じと見ております。

AZ-900受験時と同様、基本は土曜または日曜のどちらかに1～2時間、参考書を基に自己学習しておりました。
所用や体調不良等で勉強できなかった時もあったため、実質的な学習期間は21～42時間程度と見ています。

# 学習方法
こちらもAZ-900の時と同様、まずは用語や仕組みについてしっかりと熟読し、自分なりの解釈を得られてから参考問題を解いていくスタイルでした。
間違えてあ問題は元より、解答に悩んだ問題についてもちゃんと理解できていないか何かしら間違えた解釈を行っている事になりますので、そこを再履修していく事をメインに学習を進めております。
言い換えると正解した問題と言うのはきちんと自分の中で意味を落とし込めているという事になりますので、そのような問題は基本見直さず、一～二か月間を開けてから再度解き直して内容を染み込ませていく方針をとっております。

また、AZ-900の時も述べました通り、学習の姿勢として予定日に必ずやるというのは当然ですが、モチベーションが乗らないときは短時間で切り上げるよう意識しておくと、効率良く理解を進めていくことができます。
実際、気が乗らずに短時間で切り上げようとしたところ、その内に興が乗ってきて普段以上に学習を進められた事もありました。

# 参考書について
昨年度の学習時は俗に黒本と呼ばれる「徹底攻略 Microsoft Azure Administrator教科書[Az-104]対応」」を読み解いておりました。
試験を経た感想としましてはこちらは"教本"と言った要素が強い内容であり、仮にこれを試験に持ち込んだとしても正答率は五割程度に収まるのではないかと見ており、率直に言って試験合格を目指すという意味ではあまりお勧め出来ません。
しかしAZ-104の資格保有者として押さえる知識はほぼ全て乗っている印象を受けましたので、試験受験に関わらず手元に所有し、読んでおく分には良い参考書になるのではと考えております。

単に試験合格のみを目的とするのであれば、「合格対策Microsoft認定試験AZ-104:Microsoft Azure Administratorテキスト&演習問題」という参考書をお勧めします。
これは白本と呼ばれるいくつかの参考書の一つであり、試験合格を念頭に置いた実運用を含めた参考事例も乗っており、非常に有益な参考書とみております。

内容の内訳的には黒本を熟読すれば白本の八割方は理解出来るため、時間に余裕があるのであれば黒本の内容を履修した上で、白本の章末問題を解いていく形が最も知識として役立つのではないかとみております。

# 感想
合格ラインの700点に対し、724点で合格することが出来ました。
不得手な分野に関しては理解度が50%を下回るものもありましたが、逆にしっかりと理解出来ている部分は90%に迫る理解度となっておりましたので、この辺りは今後の習得を経て苦手部分を穴埋めしていきたいと思います。

学習観点としましては前述の黒本、白本共に章末問題の正答率を90%以上にする事を目標に進めていけば試験自体は問題無く合格できるのではと思います。
ソフトウェアアップデートでGitHub CLI 更新時に署名エラーが出てた

先日久しぶりにLinuxMintが入ったPCを起動したらソフトウェアアップデートでGitHubCLIの更新時にエラーがでてたのでメモ

## 目的
以前のようにソフトウェアアップデートで更新できるようにする。


## エラー内容
このようなエラーメッセージが表示される


>署名照合中にエラーが発生しました。リポジトリは更新されず、過去のインデックスファイルが使われます。GPGエラー:https://cli.github.com/packages
stable InRelease:以下の署名が無効です:...


<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310625/683810e2-32fe-2acc-0744-8431b19a54ef.png">

## 原因

https://github.com/cli/cli/issues/9569

上記のURLによると9/6にそれ以前まで使用していたGPGキーの有効期限が切れたため、GPGキーを更新したとのこと。
## 解決方法
原因の項目のURLにある**Installed via apt**の項目のコマンドを実行するとGPGキーが更新されて解決する。
【MySQL】テーブル作成時、カラム名が予約語だったときの対処法

## 背景
DDL作成時に、「``key``」というカラム名を持つテーブルに遭遇した。
以下の状態でCREATE文を実行すると、エラーが起きる。

```sql:
CREATE TABLE example (
    id INT PRIMARY KEY,
    key VARCHAR(255) NOT NULL
);
```
## 原因
``key`` はインデックスを示すための予約語として使用されるため、カラム名として使用すると、クエリが正しく解析されない可能性があります。

## 改善策
### 1. バックティックで囲む
もしどうしても key という名前を使用する場合は、バックティックで囲むことで使用可能ですが、推奨はしません。
```sql:
CREATE TABLE example (
    id INT PRIMARY KEY,
    `key` VARCHAR(255) NOT NULL  -- バックティックで囲んでいる
);
```


### 2. 別の名前を使用
より明確で分かりやすいカラム名を使用することをお勧めします。例えば、user_key や api_key などの名前に変更すると良いでしょう。

## まとめ
``key`` というカラム名の使用は可能ですが、予期しない問題を避けるためには、別の名前を使用することが最良の選択です。
MySQLエラー：ERROR 1170 (42000) at line 102: BLOB/TEXT column 'user_uuid' used in key specification without a key length

## 背景
以下のSQL実行時に表題のエラーが発生した。
```sql:
CREATE TABLE IF NOT EXISTS user (
  user_id Integer NOT NULL COMMENT 'ユーザーID',
  user_uuid text NOT NULL COMMENT 'ユーザーUUID',
  user_name text NOT NULL COMMENT 'ユーザー名',
  PRIMARY KEY (user_id),
  UNIQUE KEY (user_uuid)
)
```
```:エラー
ERROR 1170 (42000) at line 102: BLOB/TEXT column 'user_uuid' used in key specification without a key length
```

## 原因
``BLOB``または``TEXT型``のカラムをインデックスまたは外部キーに指定しようとした際に発生する。BLOBまたはTEXT型のカラムをインデックスとして使用する場合、サイズを指定しないといけない。

## 解決策
### 1. インデックス作成時にカラムのキー長を指定する
```sql:
CREATE TABLE IF NOT EXISTS user (
  user_id Integer NOT NULL COMMENT 'ユーザーID',
  user_uuid text NOT NULL COMMENT 'ユーザーUUID',
  user_name text NOT NULL COMMENT 'ユーザー名',
  PRIMARY KEY (user_id),
  UNIQUE KEY (user_uuid(32)) -- TEXT型に対してキー長を指定
)
```

### 2. TEXT型の代わりにVARCHAR型を使用する
インデックスにサイズ制限を設けなくても良くなる
```sql:
CREATE TABLE IF NOT EXISTS user (
  user_id Integer NOT NULL COMMENT 'ユーザーID',
  user_uuid varchar(32) NOT NULL COMMENT 'ユーザーUUID',
  user_name text NOT NULL COMMENT 'ユーザー名',
  PRIMARY KEY (user_id),
  UNIQUE KEY (user_uuid) -- TEXT型に対してキー長を指定
)
```


## まとめ
- VARCHAR型は、サイズが固定されているため、user_uuidのサイズが32文字であることが分かっている場合は、こちらの方が一般的に適しています。
- TEXT型を使用する場合は、キー長を指定することでエラーを回避できますが、パフォーマンスの観点からもVARCHARを使用する方が良い場合が多いです。
ArduinoIDE 2からはATtinyがサポートされていない

久しぶりにATtiny85へ書き込みをしようとしたらできなかった。
調べてみたらArduinoIDE2.3.2では、ボードマネージャURLの
「http://drazzy.com/package_drazzy.com_index.json」を対応していなかった。

代わりに「https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json」を追加して、
ATtiny85に書き込みを行った。

## 設定
1、ArduinoIDEを起動して「基本設定」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/4dc80456-6f3b-c7cd-e7df-1d3e11f47be4.png)

2、追加のボードマネージャのURLに
「https://mesom.de/atflash/package_atflash_index.jso」を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/393b484a-8c0a-3162-7cd6-7d067be973ec.png)


3、ボードマネージャで「ATtiny」と入力して「attiny」をインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/4e386b87-f459-657a-e237-2513785d02eb.png)


4、ArduinoUNOにArduinoISPを書き込み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/0d790a28-5df7-35e8-7dc4-1ea7acc370d8.png)

## 配線
配線方法はこの方のサイトを参考にしました。
https://burariweb.info/electronic-work/attiny85-optiboot-serial-write.html

## ブートローダ書き込み
はじめは、ATtinyは空っぽの状態なのでブートローダを書き込む。
設定は以下で「ブートローダを書き込む」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/1e62f3b2-7947-bb63-9ff7-bc4deb8e0c07.png)


## サンプルスケッチ
以下のサンプルスケッチを書き込む
```c
void setup() {
  pinMode(4, OUTPUT);
}
 
void loop() {
  digitalWrite(4, HIGH);
  delay(1000);
  digitalWrite(4, LOW);
  delay(1000);
}
```
以下の方法で書き込み
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1339052/79f8cf0b-60a9-5846-84b3-be9cf719bafd.png)

これで1秒間隔でLEDが点滅します。
G-SAPを使用してアニメーションを実装する 〜概要編〜

# はじめに
学んだことを忘れないように備忘録として残しています


## **そもそもG-SAPとは**

Web制作・開発においてモダンなアニメーションを作成するためのJavaScriptライブラリです。
筆者はスライドイン、カルーセルパネル、アコーディオンメニューなどの作成時に使用しています。


### 導入方法
色々な方法がありますが、簡単なのは公式サイトからCDNを使ってライブラリをheadタグ内で読み込めば導入することができます。

https://gsap.com/docs/v3/Installation/?tab=cdn&module=esm&method=private+registry&tier=free&club=false&require=false&trial=true#installer



:::note warn
このとき読み込みの順番はG-SAP→JavaScriptファイル
:::

## 基本構文
```javascript

```jsx
gsap.to(".box", {
  x: 100,
});
```
- to：メソッド
- .box：第1引数。アニメーションさせる要素を指定（class名やid名）
- x: 100,：第2引数。変化させたい動き(プロパティ)と設定値を指定

## TweenとTimeline
GSAPを使う上で、基本であり恩恵を最大化するのに必要なものとして「Tween」と「Timeline」があります。

### Tweenとは
要素やオブジェクトのプロパティ（位置、サイズ、色など）を時間に沿って変化させるアニメーションのこと

以下が使用メソッドになります。


| to() | アニメーション終了の状態を指定 |
| --- | --- |
| from() | アニメーション開始の状態を指定 |
| fromTo() | アニメーションの開始から終了までを指定 |



- **toは現在〜未来（未来の時点の状態を書く）**

例：透明状態を記述して、ものがあるところから消えるというアニメーションが多い

- **fromは過去〜現在（過去の状態を書く）**

例：透明状態を記述して、何もないところから出現するというアニメーションが多い


### Timelineとは
「連続するTweenの処理を行うときに、前の処理のアニメーション時間に合わせて遅延させる必要なく、簡潔にタイミングを管理できる」というもの

**【Timelineを使用しないで連続したアニメーションを書く場合】**

```jsx
gsap.to("#id", {x: 100, duration: 1});
gsap.to("#id", {y: 50, duration: 1, delay: 1}); //1秒遅延
gsap.to("#id", {opacity: 0, duration: 1, delay: 2}); //2秒遅延
```

１行目→２行目→３行目の順番で連続したアニメーションを起こす時、２つ目のアニメーションの発生を１つ目のアニメーション時間分遅らせる必要があり、

アニメーションが連続するほど複雑な遅延の計算を行わなければならない。

**【Timelineを使用して連続したアニメーションを書く場合】**

```jsx
var tl = gsap.timeline({repeat: 2, repeatDelay: 1});
tl.to("#id", {x: 100, duration: 1});
tl.to("#id", {y: 50, duration: 1});
tl.to("#id", {opacity: 0, duration: 1});
```


Timelineを用いると、遅延を考えずにそのままつなげるだけで、１行目→２行目→３行目の順番で連続したアニメーションを起こすことができます。


## おわりに
今回はG-SAP導入の概要を解説しました。
Laracsvを使用して、ブラウザからDatabase情報をCSVに出力する

# 概要
Laravelをwebアプリを作成した際、DBのModelからCSVの形式で落とす方式で、
試行錯誤したのでメモとして残します。

## Laracsvについて
Eloquent Modelから簡単にCSVファイルを生成できるライブラリになります。
実際シンプルに実装することができました。
https://github.com/usmanhalalit/laracsv

#### インストール手順
ライブラリを使う際はあらかじめ以下のコマンドでPJ配下に取り込んでおく必要があります

```
$ composer require usmanhalalit/laracsv:^2.0
```

## 実装

### ①インスタンスを生成
名前空間の指定は必要ありません
```
$csvExporter = new \Laracsv\Export();
```

### ②DBモデルから情報を取得し、CSVに変換
例としてUserモデルから情報を取得します
App/Http/ModelsにUser.phpのModelを作成済み("name"と"email"のfieldを持ったDB)
```
// Model Userからデータを取得
$user = User::all();
//CSV変換：第1引数にcollection、第2引数で取得するfieldを指定
$csvExporter->build(Users::get(), ['name', 'email']); 
```
:::note info
Modelから特定の列を抽出したい場合
例として'name'が'hoge'の列のみを抽出する場合は以下のように書きます
:::
```
$user = User::where('name','hoge')->get;
```
:::note info
headerを変更したい場合
headerをfieldの値でなく、独自に変更したい場合は以下のように指定
:::
```
$csvExporter->build(Users::get(), ['name' => '名前', 'email' -> 'メール']); 
```

### ③文字化けを防ぐためBOMの設定
BOMを設定しないと、SJISの文字コードが入っていると文字化けします
```
$csvReader = $csvExporter->getReader();
$csvReader->setOutputBOM(\League\Csv\Reader::BOM_UTF8); 
```

### ④CSVをBODYに入れて、responseを返す
Controller等でreturnとして返せば、ブラウザからダウンロードができます
```
return response((string) $csvReader)
->header('Content-Type', 'text/csv; charset=UTF-8')
->header('Content-Disposition', 'attachment; filename="'.$fileName.'"');
```

## （補足）エラー対応
Laracsv導入後、一部エラーが起きていたので対策手順をメモ
出たエラー文としては以下

:::note alert
Class "Laracsv\Export" not found
:::

どうやらインストールしたはずのLaracsvを認識してくれない...
ひとまずEC2の再起動、webサーバの再起動をしてみるが復活せず
```
sudo systemctl stop httpd
sudo systemctl start httpd
```

### Laracsvパッケージの再インストール
最終的にLaracsvを再インストールすることで解消した
```
composer remove laracsv
composer require laracsv/laracsv
```
WEBページからLIFFを開くときに、外部ブラウザで開くかLINEアプリで開くかを出し分ける方法

# はじめに

LINEを使った案件に携わることが多いのですが、WEBページからLIFFを開いたときに
WEBブラウザとLINEアプリそれぞれでLIFFのテストをしたいのに
　
・LIFFをWEBブラウザで開かせたいのに、LINEに飛んじゃう
・LIFFをLINEアプリで開きたいのに、WEBブラウザで開いちゃう
　
となっている人が結構いらっしゃいました。

やり方をパートナー企業の方に伝えたところ、「Qiitaの記事にできますよ！」と言ったいただいたので書きます。
※WEBページからLIFFを開いた時の挙動を確認したい、けどやれない。というときに役立つ（はず）です。

### ※iPhone限定です。
　
# やりかた
　
### ①まず、ブラウザでYahoo!にアクセスします。
　
![IMG_0457.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3688809/8c7585c9-65e5-e9e4-aba4-df65a7e0b05c.png)
　
### ②何かしら記事を開き、記事全文を開きます。
　
![IMG_0464 2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3688809/0c3ac18e-e5f2-e714-2e68-00fa85328569.png)
　
### ③記事タイトル下辺りにある、「友だち追加」アイコンを長押しします。
　
![IMG_0465.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3688809/20fb5b9d-1cbb-f8ad-68ca-18f8ee7ddd5e.png)


### ④すると、ポップアップメニューが出てきます
　
![IMG_0461.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3688809/daefe909-87c7-55b8-4522-0f2a26f58076.png)

### 「新規タブで開く」を選ぶと、LIFFがWEBブラウザで開くようになります。
### 「LINEで開く」を選ぶと、LIFFがLINEアプリで開くようになります。



# あとがき
ようはiPhoneのユニバーサルリンクを使って出し分けています。

LINEログインをブラウザでさせたいか、LINEアプリ経由でさせたいか、というテストのときも使えます。

※AndroidのChromeでのやり方知っている方いたら教えて下さい〜
　おそらくChrome以外のブラウザじゃないと、Androidはこのやり方で出し分け出来ないかもしれません。。

　
他にも裏技みたいなのあった気がするので、思い出したら書きます！
MyBatisエラー：Invalid bound statement (not found)

MyBatisの「Invalid bound statement (not found)」エラーは、MyBatisが実行しようとしているSQLステートメントが見つからない場合に発生します。このエラーの原因とその解決策について、以下に記す。

## 1. Mapper InterfaceとXMLのファイル名、ファイル階層の不一致

MapperインタフェースとXMLは、以下のように<strong>階層構造</strong>と<strong>ファイル名</strong>が一致している必要がある。
- ```src/main/java/jp/com/example/domain/dao/TestMapper.java```
- ```src/main/resources/jp/com/example/domain/dao/TestMapper.xml```

### 階層構造を同じにしたくない場合
#### ・@MapperScanでインタフェースが存在するパッケージを指定する
```java:
@SpringBootApplication
@MapperScan("com.example.mapper")  // Mapperインタフェースのパッケージ
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
```
#### ・application.yml または application.properties に mapper.xml のパスを指定する
```yaml:application.yml
mybatis:
  mapper-locations: classpath:/mappers/**/*.xml  # XMLファイルのパスを指定

```

## 2. SQLステートメントIDの不一致
Mapperインタフェースで定義されているメソッド名と、XMLファイルに定義されているSQLステートメントのIDが一致していない場合、MyBatisはそのステートメントを見つけられません。

```java:TestMapper.java
@Mapper
public interface TestMapper {
    UserInfoResult selectUserById(String id);
}
```

```xml:TestMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="jp.com.example.domain.dao.TestMapper">
<select id="selectUserById" resultType="com.example.entity.UserEntity">
    SELECT id, name, age
    FROM users
    WHERE id = #{id}
</select>
</mapper>

```

## 参考資料
https://zenn.dev/toranoko114/articles/aaa404687faeb8
TreeSetとHashSetの比較整理およびアルゴリズムの問題を解く

### HashSetとTreeSetの検索速度比較

- **HashSet**  
  `HashSet`は内部で**ハッシュ化**によってデータを保存します。各要素の位置は**ハッシュ関数**で計算され、データの順序は保証されませんが、平均**O(1)**の時間で素早く検索できるため、特定の要素が存在するかどうかを確認する場合に非常に効率的です。

- **TreeSet**  
  `TreeSet`は**二分木構造**（実際には**赤黒木構造**）でデータを**整列された状態**で保存します。このため、要素を追加または削除する際には**O(log n)**の時間がかかり、検索も同様に**O(log n)**の時間が必要です。このような特性から、整列が必要な場合や範囲検索をする場合には適していますが、単純な存在確認では`HashSet`よりも遅くなります。

#### HashSet vs TreeSetの選択理由

- このアルゴリズムでは**整列は必要なく**、**特定の数が存在するかだけを確認**すればよいため、`HashSet`が最も適しています。
- 要素を自動的に整列させる必要があったり、範囲検索が必要な場合には`TreeSet`が有効ですが、連続数列の始点を素早く見つけるためには`HashSet`の方が効率的です。

### アルゴリズムの説明

#### HashSetを利用した連続数列の値を求めるアルゴリズム (TreeSetとの検索速度比較)

```java
public int solution(int[] nums){
    int answer = 0;

    HashSet<Integer> set = new HashSet<>();
    for(int a : nums){
        set.add(a);
    }
    int max = 0;

    for (int num : nums) {
        if (set.contains(num - 1)) {
            int curVal = num;
            int count = 1;
            while (set.contains(curVal)) {
                curVal += 1;
                count++;
            }
            max = Math.max(max, count);
        }
    }
    answer = max;
    return answer;
}
```


このコードは、与えられた配列 `nums`の中で**最も長い連続した数列**を見つけ出すアルゴリズムです。配列内の連続する数値が最も長く続く場合の長さを求めることが目標です。このアルゴリズムでは、`HashSet`を使用して重複を除去し、効率的な検索によって最大の連続数列の長さを計算します。ここでは、`TreeSet`を使用した場合との検索速度も比較して説明します。

1. **重複を除去し検索準備を行う**  
   `HashSet`を利用して`nums`配列の重複要素を取り除き、効率的に検索できるようにします。

   ```java
   HashSet<Integer> set = new HashSet<>();
   for(int a : nums){
       set.add(a);
   }
   ```

2. **最大の長さを保存する変数を初期化**  
   連続した数列の最大の長さを追跡するために`max`変数を初期化します。

   ```java
   int max = 0;
   ```

3. **連続した数列を見つける**  
   各数字`num`に対して以下の処理を行います:

   - **数列の始点を確認する**  
     `num - 1`が`set`に存在するかを確認します。`num - 1`が存在する場合、`num`は連続数列の始点ではないためスキップし、`num - 1`が存在しない場合のみ始点とみなします。

   - **数列の探索と長さの計算**  
     始点`num`から始まり、1ずつ増加する`curVal`を追いかけながら、`set`にその値が存在する限り`count`を増やして連続する数列の長さを求めます。

   - **最大長さの更新**  
     得られた数列の長さ`count`が`max`よりも大きい場合、`max`を更新して現在の最大連続数列の長さを記録します。

   ```java
   for (int num : nums) {
       if (!set.contains(num - 1)) {
           int curVal = num;
           int count = 1;
           while (set.contains(curVal + 1)) {
               curVal += 1;
               count++;
           }
           max = Math.max(max, count);
       }
   }
   ```

4. **結果を返す**  
   最も長い連続数列の長さを`answer`に保存し、返します。

   ```java
   answer = max;
   return answer;
   ```

#### 例
配列`nums`が`[100, 4, 200, 1, 3, 2]`の場合、`1, 2, 3, 4`が最長の連続数列であり、`count`は4となり、返り値も4となります。

### まとめ
このアルゴリズムは`HashSet`を用いて重複を除去し、**O(1)**の検索速度で効率的に探索し、**最も長い連続数列の長さ**を求める方法です。`TreeSet`を使用しても同様の機能は実現できますが、検索に**O(log n)**の時間がかかるため、`HashSet`ほど効率的ではありません。
PaizaCloudをさわってみた②

# PaizaCloudをさわってみた②

https://qiita.com/k_ozw/items/aa0aafa2a1990ab8b410

上記の続き。

# Railsで日記アプリを作ってみた。①

PaizaCloudで簡単なアプリを作成してみようと思い、実施。
PaizaCloud上にサーバを作成して、ターミナルを開いてコマンドを打っていく。

- 新しいアプリの作成

```
rails new diary_app
cd diary_app
```

- modelの作成
データベースのカラムはシンプルに`title` `content` `date`とします。
```
rails generate model Diary title:string content:text date:date
rails db:migrate
```
- controllerの作成
```
rails generate controller Diaries index show new create edit update destroy
```

- ルーティングの設定（config/routes.rb）

```
Rails.application.routes.draw do
  root 'diaries#index'
  resources :diaries
end
```

コントローラーの修正以降は次回にまとめる。
【Azure】CloudShell の使い方

# はじめに

CloudShell とは、文字通りクラウド上で利用できる Shell 環境です。
Azure 関連のモジュールはデフォルトでインストールされているため、手早くコマンドを試したいときには非常に便利です。

今回は Azure 環境を始めて触る人向けに CloudShell の起動方法をまとめたいと思います。

あまり困る部分はないと思いますが、はじめて Azure を触る人はちょっと不安な部分があるかもなので、参考にしてください。

# CloudShell の起動方法

### STEP 1 : [Azure Portal](https://portal.azure.com) にログインする
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/4ef92f0f-e9c6-40b0-6cb4-207f99daa6ed.png)

### STEP 2 : 画面上部の CloudShell のアイコンを選択する
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/e8a80e00-99c3-6f7a-c216-757c19438b5b.png)

    
### STEP 3 : シェルの種類を選択する
    
    お好きな方を選択してください。今回は Bash を選択します。
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/7e3ebb21-c018-1a82-20c5-de497c4464da.png)

    
### STEP 4 : CloudShell の設定をする
    
    パラメータがいくつかありますが、下記の通りに選択してください。
    少し前までは、ストレージカウントとの紐付けが求められていましたが、無くなったので、より気軽に実行できるようになりました。
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/90a3d545-2f00-146e-210b-733e8e74363c.png)

これで起動は完了です。少し待つと、コマンドが実行できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513223/61dc0d1f-c353-b469-4eba-18b823ed5154.png)


# さいごに

CloudShell の起動方法をまとめました。（2024/10/28時点）

課金とかは気をつけながら、いろんなコマンドを実行してみましょう！
【備忘録】モデル駆動型とキャンバス

## はじめに
以前 Power Platform 勉強会で登壇させていただいた際に「備品管理アプリ」をモデル駆動型アプリとキャンバスアプリで併用するといった内容で、発表させていただきました。

今回は、登壇の際にデモの前に発表した、モデル駆動型とキャンバスの違いをまとめました。

## デザイン性
- モデル駆動型アプリ
デザインがほぼ決まっています。データを選ぶとほぼ自動的にアプリ画面が作成されるため、デザインの自由さはありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966048/b3d43b92-749c-d967-8158-3b7fa8130461.png)

- キャンバスアプリ
デザイン性に優れていて、アプリの作成者がボタンやアイコンの位置、クリック時の色、文字の大きさなどを自由に指定できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966048/17b5b325-686b-9b73-0eb3-c967e778cba1.png)


## 開発スピード
- モデル駆動型アプリ
デザイン設計は必要ありません。必要なデータが整理されていればほぼ自動で作成されるため、高品質なアプリが作成できる上に開発時間を減らすことができます。

- キャンバスアプリ
デザインの設計から全て手動で行うため、開発時間がかかります。設計が十分でないと手戻りも発生する可能性があります。

## レスポンシブル性
- モデル駆動型アプリ
レスポンシブルなデザインはモデル駆動型アプリにはありません。モデル駆動型アプリはビジネスロジックが複雑な場合に適しています。

- キャンバスアプリ
ユーザーが使用するPCやスマートフォン、タブレットなどの画面サイズに合わせて自動で最適化されるデザインを採用できます。

## おわりに
もし需要があれば、デモの内容も記事にしようかなと思います。
TensorFlow Liteでの「Created TensorFlow Lite XNNPACK delegate for CPU.」メッセージを理解する【備忘録】

PythonでTensorFlow Liteを使用する際に、特にXNNPACKを利用したモデルの最適化が行われる場合に「Created TensorFlow Lite XNNPACK delegate for CPU.」というメッセージが表示されることがあります。本記事では、このメッセージが意味する内容や、XNNPACKの役割について詳しく解説します。

## 1. TensorFlow Liteとは

TensorFlow Liteは、Googleが開発した軽量ニューラルネットワークライブラリで、モバイルデバイスや組み込みデバイスのようなリソースが限られた環境でも高速かつ効率的に機械学習モデルを実行するために設計されています。多くの組み込みアプリケーションでTensorFlow Liteは利用されており、特に画像処理や音声認識などのリアルタイムアプリケーションに適しています。

## 2. XNNPACKとは

XNNPACK（eXtended NN PACK）は、Googleが開発したニューラルネットワークの演算処理を高速化するための最適化ライブラリです。TensorFlow Liteで使用されるXNNPACKは、主にCPU上でのニューラルネットワーク推論の処理を加速させるために使われます。

### XNNPACKの特徴
- **CPU向け最適化**：XNNPACKは特にCPU上での実行を高速化するように設計されており、モバイルデバイスやリソースが限られたデバイスで高効率で動作します。
- **計算効率の向上**：畳み込みや活性化関数など、頻繁に使用されるニューラルネットワーク演算を最適化し、計算時間を短縮します。
- **低消費電力**：モバイルデバイスのバッテリーを節約しつつ、高速な処理を実現します。

## 3. メッセージの意味：「Created TensorFlow Lite XNNPACK delegate for CPU.」

TensorFlow Liteでモデルを実行する際に「Created TensorFlow Lite XNNPACK delegate for CPU.」というメッセージが表示されるのは、TensorFlow LiteがXNNPACKを利用してCPUでの処理を最適化することを示しています。このメッセージが表示される場合、以下のような効果が期待されます。

1. **推論速度の向上**：XNNPACKがサポートする最適化により、モデルの推論速度が向上します。
2. **電力消費の低減**：計算効率が上がるため、特にモバイルデバイスなどで電力消費が抑えられます。
3. **CPUリソースの有効活用**：GPUがない環境でも、高速にモデルを実行できます。

### メッセージが表示されるタイミング
このメッセージは、TensorFlow LiteがXNNPACKの適用可能な環境（主にCPUを使ってモデルが実行される場合）で自動的にこの最適化を有効にした場合に表示されます。

## 4. XNNPACKデリゲートの利用が推奨される場面

TensorFlow Liteは、様々なハードウェアの種類に応じて異なる「デリゲート」と呼ばれる最適化プラグインを持っています。XNNPACKデリゲートは、特に以下の環境で推奨されます。

- **CPUしか使用できない環境**：GPUや専用のAIアクセラレーターがない場合でも、高速にモデルを実行可能です。
- **モバイルデバイスや組み込みデバイス**：リソースが限られた環境でも、高速かつ省電力でモデルが実行できるようになります。

TensorFlow Liteでは、XNNPACKが自動的にデリゲートとして選択されるため、特に手動での設定は不要です。ですが、必要に応じてXNNPACKをオフにすることもできます。

## 5. XNNPACKデリゲートの無効化方法

デフォルトではXNNPACKが有効になっていますが、無効化したい場合には、以下のように設定します。

```python
import tensorflow as tf

# TFLiteインタープリタのオプションでXNNPACKデリゲートを無効化
interpreter = tf.lite.Interpreter(model_path="model.tflite", experimental_delegates=[])
interpreter.allocate_tensors()
```
## まとめ  
「Created TensorFlow Lite XNNPACK delegate for CPU.」メッセージは、TensorFlow LiteがCPUでのモデル推論をXNNPACKデリゲートにより最適化することを示すものです。このデリゲートは、リソースが限られた環境での推論効率を高め、電力消費を抑えつつ計算速度を向上させるため、非常に有用です。組み込みデバイスやモバイル環境でTensorFlow Liteを使用する場合、XNNPACKによる最適化は非常に大きな利点となります。