OmniAICreator/Qiita-1.07M huggingface dataset:
Reactで実家の飲食店ホームページ作成してみた

## はじめに

前回の記事で少し話題に上がりました実家の飲食店(都内の寿司屋)のホームページを
Reactで作り直しました。今回は、それについて記事を書きます。

## ~前回のあらすじ~
ある日、父からホームページを作成するようお願いされた。
まずはwordpressで作成してみたが、感覚的にはなんか微妙。。。もうちょっとweb開発に
ついて勉強してみよう！といった流れです。
あらすじ終わり

## 開発環境
言語
JavaScript(React)

サーバーサイド
node.js

DB
今回は使用しておりません。

デプロイする際にAWSを使いました。
(カスタムドメインも簡単に作れるしビルドも自動だしとても便利で感動。)


## まずは競合他店？のホームページ調査から
もはや何から書いていいのかわからないので、同じ業界の個人店のホームページを
いくつか拝見させていただき、参考にしました。
注目した点は
- 背景の使い方
- 文字のフォント
- ページの構成
- キャッチフレーズや何をどんな風に紹介しているのか etc...

ざっくりですがこんな感じで調査しました。

## 実際の開発過程
reactにはReact Routerというライブラリがあって、
これはページを移動するようなサイトを作るときにとても便利なライブラリです。
ターミナルで"npm i react-router-dom"でたたくとモジュールをインストールできます。
今回でいうと、店舗紹介、アクセスなど飲食店のホームページには大体あるようなものを
ページで分けて紹介しようと考えたので、このライブラリを使用しました。

![スクリーンショット (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584377/e888d8f0-7d8a-118c-99ed-d4da5c3d2918.png)


とてもすっきりして見やすいです。前回の開発ではコンポーネントごとのファイル管理など
課題になったので気を付けるようにしました。

前回の天気予報アプリ開発よりかは難易度は高くなく、思ったよりすいすい進みました。
しかし、画像のスライドなどは初めてだったので結構時間がかかりました。

複数のページで同じ関数を使いまわしたかったのでSlideShow.jsを作成しました。
ここで私がつまづいた点がいくつかありました。
#### クラス名問題
同じスライド関数を呼び出すときにスライドごとに別にcssを割り当てたかったのですが、どうしてもクラス名が同じなのでどうしよう...と頭を抱えていました(説明が難しい)
解決策として、クラス名を変数にして対応しました。
propsの引数に画像の文字列と変数名にして対応しました。ここで私はpropsの可能性は無限大だ！と感動しました。
![スクリーンショット (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584377/856a113a-09e9-82d2-fd5d-8f555271d132.png)

正直この使い方が正しいのかは分かりませんが、これで乗り切りました。
#### キャッチフレーズ問題
実は私、寿司が嫌いです。本当に親不孝者だと思います。
それで、何が言いたいかというとキャッチフレーズが全く思いつかないのです。
~~普通に考えて嫌いな食べ物を美味しそうに紹介するってなかなか難しい~~
そこで、開発していくうえで、父に相談しながら開発することにしました。
例えば
私「この写真をキャッチフレーズ"A"で書いて....」

父「このキャッチフレーズは"B"にして.....」

↑のように毎週日曜日にウィークリースクラムをしていました(笑)

そして、これって本当に仕事みたいだなと思うと面白いものがありました。
web開発を仕事にしたいとつくづく思うようになりました。

## 工夫した点
#### アニメーションをあまり入れない
これは完全に私の裁量ですが、アニメーションが多いと店の品性が欠けると考えました。
IT企業のホームページならまだしも、都内にあるターゲットが常連様、かつ年齢層高めの寿司屋の
ホームページがアニメーションだらけ　ってどうなのかな。。。と思った次第です。
#### 色の組み合わせとフォント
やはり寿司屋と言えば、「和」を意識し、高級感を出すことが無難だと考え、

![washi5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3584377/b397464b-92f8-5fbb-2f6a-377801394512.jpeg)
このようなシンプルな背景画像を選択しました。

フォントも調べてみると色々なものがあり、和風のフォントもあるのでそれを使用しました。

font-family: "kaisei-tokumin", sans-serif;

↑かなり和風な感じで見つけることができてラッキーでした。

#### お客様からの意見を聞く
父の店は割と常連様がお越しいただくこともあり、ホームページを見ていただいて
ご意見をいただき、改善に取り組んだ。
例えば、
「文字が多いと読む気があまり起きないかも」、
「背景もう少し薄い色がいいかも」などとご意見をいただき、
修正に取り組みました。~~酔いもあってか結構びしばし意見してくれました~~
実際の使用者からの意見を聞いて、修正に取り組む。
こういった経験ができて本当に良かったと今は思っています。


## おわりに
Reactでのホームページ作成は初めてでしたが、とても楽しく開発できたと思います。
父の意見を聞いて、それを設計して開発して～～
アジャイル開発みたいな感じでやっていましたが、とてもいい経験になったとおもいます。
そして何より父に喜んでもらえたことがよかったです。こうやって勉強したことが
人の役に立つとこんなにも素晴らしく、嬉しいことなんだと肌で実感しました。
実際にホームページを載せたいところですが、トラブルがあってはいけないので、
そちらはご了承ください。最後までお読みいただきありがとうございます。
【Powershell】ファイルパスを取得する関数(GUI/CLI両対応)

# はじめに
このツールは以下のフォルダパス取得関数のファイル版のような存在である。
そのため、基本的な仕組みは共通である。

https://qiita.com/Kit-i/items/56ca324c496e936ee975

# 概要
Powershell上で指定したファイルのパスを返す自作関数の紹介。
単体での利用ではなく、他のスクリプトなどの処理から呼び出すことを前提としている。
ファイル選択ダイアログを使ったファイルパス取得にも対応。

## ユースケース
ツールなどで特定のファイルを指定する必要が有る際に呼び出す。
主にインタラクティブなCLIツールとして使用可能。

# 関数紹介
関数名：Select-File

## 機能要件
- 任意のファイルのフルパスを返す
- インタラクティブな処理を可能にする
- ダイアログボックスを使用したGUIでのインタラクティブな処理を盛り込む。
- 指定パスが存在するか判定処理をいれる
- 指定パスがファイルであるか判定処理をいれる

## ソースコード
```powershell:Select-File
###################
#ファイルパス取得関数
###################

function Select-File(){
###################
#<概要>
#指定したファイルパスを呼び出し元に返します。
#<書式>
#Select-Dir [-cliDialog | -guiDialog] [-Path <ファイル名>] 
###################
    Param(
        #オプションの規定値はCLIでのダイアログ表示
        [switch]$cliDialog = $true, #cliDialogのブール値は処理には使わない。デフォルトの動作をわかりやすくするためにあえて記述している。
        [switch]$guiDialog,
        [string]$Path =""
    )

###############
#guiDialogの処理
###############
    if($guiDialog){
        Add-Type -AssemblyName System.Windows.Forms
        $dialog = New-Object System.Windows.Forms.OpenFileDialog -Property @{
            Title = "ファイルを選択してください"
        }
        if($dialog.ShowDialog() -eq "OK") {
                $File_name = $dialog.FileName
                Write-Host "'${File_name}'が選択されました。"
                return $File_name
            }else{
                Write-Host "ファイルは選択されませんでした。"
                return
            }
    }
###############
#cliDialogの処理
###############
    #引数にパスが指定されているか判定
    if($Path -eq ""){
        $File_name = Read-Host "対象ファイルのパスを入力してください。"
        $File_name = $File_name -replace '^"|"$' -replace "^'|'$"
        if($File_name -eq ""){#Read-Hostは何も入力しなかった場合に空文字列が返される(nullじゃない点に注意)
            Write-Host "パスが未指定のため処理を終了します。"
            return
        }
    }else{
        $File_name = $Path
    }
    #対象ファイルの存在確認
    $bool = Test-Path -Path $File_name -PathType Leaf
    if(! $bool){
       Write-Host "対象パスのオブジェクトはファイルではありません。"
       throw "'${File_name}' is not File"
    }
    
    return $File_name
}
```

### 書式
```powershell:書式
Select-Dir [-cliDialog | -guiDialog] [-Path <string>]
```

### Select-Dirとの差異
私が自作したフォルダパス取得用の関数([Select-Dir](https://qiita.com/Kit-i/items/56ca324c496e936ee975 "【PowerShell】フォルダパスを取得する関数(GUI/CLI両対応)"))とコード上以下の点が異なる。

- Open.File.Dialogクラスを使用
- ダイアログで選択された値を参照するためのプロパティ※が異なる。
- Test-Pathコマンドレットの-Pathtypeが"Leaf"(ファイル判定)
※"FileDialog.FileName"


### 今後
相対パスから絶対パスへ変換する仕組みを入れる予定。
ファイルの複数選択を可能とする仕様にするか否か考え中...

## 修正履歴
更新日：2023/11/9
Read-Hostコマンドに入力するパスにクォーテーションが含まれている場合に、
ファイル判定処理でfalseとなりthrowされる問題を修正しました。

# 参考
https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.forms.openfiledialog?view=windowsdesktop-7.0
NextAuth.jsとは

NextAuth.jsは、Next.jsアプリケーションに簡単に認証を追加するためのライブラリです。このライブラリはNext.jsのエコシステムとの統合が深く、サーバーレス環境やサーバーサイドレンダリングのアプローチに適しています。

## NextAuth.jsの主な特徴


__認証プロバイダーのサポート__: Google, Facebook, Twitter, GitHubなど、多くの既存の認証プロバイダーとの統合が容易です。また、任意のOAuthサービスや資格情報を使用した認証もサポートされています。

__セッション管理__: セッション情報はクライアントサイドで使用でき、Next.jsのAPIルートやサーバーサイド関数からもアクセス可能です。

__CSRF保護__: 既定でCSRF攻撃の保護が組み込まれています。

__データベースレス__: NextAuth.jsはデータベースを必要とせず動作しますが、セッションやユーザー情報を保存するためのデータベースとの統合もサポートされています。

__Email認証__: Emailとマジックリンクを使用した認証をサポートしています。

__独自のコールバックとページ__: 認証フロー中の特定のイベントやページ（ログインページ、エラーページなど）をカスタマイズすることができます。

__TypeScriptサポート__: TypeScriptの型定義が組み込まれているので、TypeScriptプロジェクトとの互換性があります。

## NextAuth.jsをNext.jsプロジェクトに導入する方法

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

最初に、NextAuth.jsとその他必要な依存関係をインストールします。

```
npm install next-auth
```

### 2. APIルートの作成
pages/api/auth/[...nextauth].tsという名前で新しいファイルを作成します。このファイルはNextAuth.jsのすべての認証ルートを処理します。

~~~typescript
import NextAuth from "next-auth";
import Providers from "next-auth/providers";

export default NextAuth({
  providers: [
    Providers.Google({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
    // 他のプロバイダーもここに追加できます
  ],
  // その他の設定
});
~~~

### 3. 環境変数の設定

.env.localファイルをプロジェクトのルートディレクトリに作成し、以下の内容を追加します。これはGoogle認証の例です。

~~~
GOOGLE_CLIENT_ID=あなたのGoogleClientID
GOOGLE_CLIENT_SECRET=あなたのGoogleClientSecret
NEXTAUTH_URL=http://localhost:3000
~~~
__注意__: これはローカル開発用の設定です。デプロイ時には適切なURLと認証情報を使用してください。

### 4. アプリに認証を追加する

NextAuth.jsのuseSessionフックを使用して、アプリ内のどこからでもセッション情報にアクセスできます。


~~~tsx
import { useSession } from "next-auth/react";

function Component() {
  const { data: session } = useSession();

  if (session) {
    return <p>こんにちは、{session.user.name}さん！</p>;
  } else {
    return <p>ログインしていません。</p>;
  }
}
~~~
### 5. ログインとログアウト

NextAuth.jsには、ログインとログアウトのための組み込み関数も用意されています。

~~~tsx
import { signIn, signOut } from "next-auth/react";

// ログインボタン
<button onClick={() => signIn("google")}>Googleでログイン</button>

// ログアウトボタン
<button onClick={() => signOut()}>ログアウト</button>
~~~ 

これで基本的なNextAuth.jsの導入と設定は完了です。
ASP.NET CoreにおけるDIコンテナの登録を簡略化する

マニアックですがASP.NET CoreのDIコンテナ登録が冗長なので簡略化して書けるようにしました。

## 従来のDIコンテナの登録方法

以下のようにインターフェース毎にDIコンテナを1つずつ登録する必要があります。コードが肥大化するにつれてDIコンテナも比例して増えていくので簡略化したいと思います。

```c#
builder.Services.AddScoped(serviceType1, implementationType2);
builder.Services.AddScoped(serviceType2, implementationType2);
```
## 設計

むやみやたらに登録するのはよろしくないのでレイヤーを分けて登録できるようにします。近年のアーキテクチャ設計（クリーンアーキテクチャ等）においてレイヤーを明確に分けることが多いと思います。正解は一つではないので全てのアーキテクチャに適用できるわけではありませんが、私の場合は名前空間毎に登録できるようにしました。

## 実装
インターフェースは以下のようにしました。登録するレイヤーは複数対応します。

```c#
builder.Services.AddServiceDynamically(nameof(Namespace1), nameof(Namespace2));
```

内容は以下のように実装しました。ポイントは以下で説明します。

```c#
public static void AddServiceDynamically(this IServiceCollection services, params string[] namespaces)
{
    var assemblies = Assembly
        .GetExecutingAssembly()
        .GetTypes()
        .Where(t =>
            (t.IsClass || t.IsInterface) &&
            !t.IsNested &&
            namespaces.Any(name => t.Namespace?.Contains(name) == true));

    foreach (var implementationType in assemblies.Where(a => a.IsClass))
    {
        var serviceTypes = assemblies
            .Where(a =>
                a.Namespace == implementationType.Namespace &&
                implementationType.GetInterfaces().Any(i => i.Name == a.Name));

        if (!serviceTypes.Any())
            continue;

        foreach (var serviceType in serviceTypes)
        {
            services.AddScoped(serviceType, implementationType);
        }
    }
}
```

```c#
builder.Services.AddScoped(serviceType1, implementationType2);
builder.Services.AddScoped(serviceType2, implementationType2);
...
// ↑が一行になりました👍
builder.Services.AddServiceDynamically(nameof(Namespace1), nameof(Namespace2));
```


### AddScopedのみ対応

理由としては、重複で登録された場合は最後に登録したインターフェースが適用されるため、特定のインターフェースのみシングルトンにする場合は一斉登録した後の行で明示的に適用すれば個別対応が可能なのでAddScopedのみ対応しました。

https://stackoverflow.com/questions/67201332/multiple-registrations-in-net-core-di-possible-implications

### IsNested

IsNestedプロパティをチェックしないと指定した名前空間に含まれるアセンブリ情報が大量に取得されてしまいます。名前空間のアセンブリ情報のみ取得したいので追加しました

## まとめ

クリーンアーキテクチャ等の設計をされたアプリケーションにおいては適用出来る仕様だと思います。いろんな考慮が漏れている可能性がありますし、比較的シンプルに作ったものなのですが参考程度になれば幸いです
AI Builder感情分析モデルでFormsアンケートの結果を分析する

こんにちは！
今回はAI Builder感情分析モデルをフローの中で使用して、Formsアンケートの結果を分析する方法について書きます。

# 感情分析モデルについて
テキストデータから、その文章内容の感情を分類します。
分類先はポジティブ、ネガティブ、ニュートラル、ミックスです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/47ef1b57-d5a7-8735-c2fd-92de7d383db9.png" width=80%>



# フローイメージ
今回はアンケートが提出されたら、そのテキスト内容をAI Builderで分析して、データを保存する流れのイメージで作っていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/61406fb9-c531-184e-0c65-0eb36739fbee.png)


# 作成方法
先にアンケートの内容と分析結果をまとめるテーブルを用意します。

今回データをためるところにDataverseを使用します。
Dataverseテーブルの列は以下のようになっています。

- アンケート文章：アンケートの内容を保存する
- 分析結果：感情分析の結果を保存する
- テキスト全体が肯定的な確率：文章が肯定的な確率を保存する
- テキスト全体が否定的な確率：文章が否定的な確率を保存する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/50c21557-226b-3e05-73cd-18d1a6a3ad1e.png)


フローの流れは以下のようなイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/25271a11-fc10-ed48-5299-0a2caa933eb6.png)

まず、アンケート送信をトリガーとして、その応答の詳細を取得アクションを追加します。
[応答ID]はトリガーで取得した動的な応答IDを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/492ca4f0-2bb3-259f-4892-f428d4a4737f.png)

次にAI Builderの「テキスト内の肯定的または否定的な感情を分析する」アクションを設定します。
言語を選択し、アンケートの分析したい項目を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/ca676cd4-02cf-b098-6378-ac95a540de8a.png)

最後にデータ登録のため、Dataverseの「新しい行を追加する」アクションを追加します。
作成したテーブルを設定し、
アンケート内容と分析結果を保存する列にそれぞれの値を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/4f36927e-1fd2-2cb0-fecd-bd6ad40e900b.png)

完成です！！


# 動きの確認
アンケートで「非常に分かりやすい説明ありがとうございました。」という回答を提出すると、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/ae49420d-2083-c8c7-b6df-8be2f116e8a0.png)

Dataverseのテーブルにデータが追加され、[分析結果]に「positive」、[テキスト全体が肯定的な確率]に「1」、[テキスト全体が否定的な確率]「0」が保存されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/af336cde-7382-4936-9613-885c3bce0ff2.png)


アンケートが回答されるたびにデータが追加されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/a49e486d-2029-2132-10c9-077af959af79.png)



https://learn.microsoft.com/ja-jp/ai-builder/flow-sentiment-analysis
Reactでローディングの作り方

# Reactでローディングの作り方

API通信をするときなどに、待つ時間が長いとローディング状態を表示する必要があるときもありますよね〜

そんな時には、useStateでローディング状態を管理します！

まずは
#### API通信するreactコンポーネントを用意します！
今回はjsonplaceholderを使います。
便利なのでぜひ！→https://jsonplaceholder.typicode.com/

```react
import React, { useState, useEffect } from "react";

const Api = () => {
  const [data, setData] = useState(undefined);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((res) => res.json())
      .then((json) => {
        setData(json)
      })
      .catch(() => {
        alert("error")
      });
  }, []);


  // ここを変更
  return (
    <>
      {data === undefined ? "" : <div>{data[0].title}</div>}
    </>
  );
};

export default Api;
```

これでdataの１番目のタイトル名を表示するAPIが叩けましたね！

#### useStateでisLoding状態を管理するstateを設置！
```react
const [isLoading, setIsLoading] = useState(false);
```

isLodingがtrueの時はローディング中です。

#### api通信をしている箇所でtrue,false切り替えをする

```react
  useEffect(() => {
    setIsLoading(true);
    fetch("https://jsonplaceholder.typicode.com/posts")
      .then((res) => res.json())
      .then((json) => {
        setData(json)
        setIsLoading(false);
      })
      .catch(() => {
        alert("error")
        setIsLoading(false);
      });
  }, []);
```

#### 三項演算子でローディング時と非ローディング時の表示を設置
```react
{isLoading ? <p>ローディング中</p> : <p>終わりだピョーン</p>}
```

これでローディング状態を管理できますね！
上手く使えばローディングアニメーションだったり、コンポーネント単位で表示したりすることもできそうです！
EC2が複数VPCにENIを足出しできるように！でもみんな戦々恐々としてるのはなぜ…？

# AWSのVPCに大きなアップデートが！

今週10/26、AWSにこんな機能アップデートが発表され大変話題になりました。

https://aws.amazon.com/jp/about-aws/whats-new/2023/10/multi-vpc-eni-attachments/

簡単に言うと **「EC2インスタンスから複数のVPCに対してENI（NIC）を足出しできるようになった」** という大きなアップデートでした。


# みんな戦々恐々？

しかし、Twitterのオンプレミス経験者たちは口を揃えて懸念を漏らしています。

「これ、クラウド初心者がオンプレからの移行で **"監視セグメントVPC"** みたいなものを作ってしまうんじゃなかろうか…」

今回のアプデを見て「ウッ…😅」と感じた方も、改めて何が問題なの？と聞かれると意外としっかり言語化できないかも知れません。これを機にAWSの代表的なサービスであるマネージド論理ネットワーク「VPC」の基本をおさらいしてみましょう。


# オンプレ時代の基本を振り返る

パブリッククラウド普及前のオンプレミス時代では、企業のシステムを構成するサーバーは以下のように複数のネットワークセグメントへ所属させる設計が当たり前でした。

そのために各サーバーはNIC（ネットワークインターフェースカード）を複数持ち、それぞれの用途のセグメントへ "足を出す" 構成をとっていました。

![スクリーンショット 2023-10-28 20.37.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/2f9ebb3b-9440-a49e-6232-6c6a628ea97f.png)

こんな構成をとるのには理由があります。

- サービス系の経路に不正侵入されても管理系サーバーへの影響を隔離できる
- 夜間バッチなど運用系の帯域消費をしてもサービスに影響を与えない
- 逆にアクセス輻輳によって帯域逼迫してもサーバー監視や管理系操作を継続できる


# クラウドのVPCは「マネージド論理ネットワーク」

一方でAWSのVPC上に同様のアプリケーションを構成する場合、以下のような形になることが多いと思います。

オンプレミスでは用途別の「セグメント」として2種類のネットワークを用意していましたが、VPCは単一のCIDR体系のみを使う形です。

![スクリーンショット 2023-10-28 21.13.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633856/756fa056-8565-8884-c322-41377e3b2b9a.png)

クラウドだとこうなる理由は、オンプレミスのときと責任分担が異なるためです。

- AWSユーザー（＝システム管理者）はVPCを構成する低レイヤーな基盤領域（帯域など）を意識する必要がない ※
- アクセス制御のために物理セグメントを分離する必要はなく、セキュリティグループやNACLを使って論理的に設定するのが基本思想
- 監視や運用機能のためにVPC内にIaaSリソースを構築しなくとも、専用のマネージドサービスが用意されている

ようは、複数のネットワークセグメントをユーザー側が設計・管理する「必要がない」んですね。

※ENIには一応、帯域幅のクォータ（Gbpsレベルと大きめですが）があることは認識する必要があります。


# じゃあ今回のアップデートは一体何のため？

What's Newの本文でも触れられていますが、AWSが想定する "マルチVPC-ENIアタッチ" のユースケースは以下のようです。

- 集中管理型アプライアンスやデータベースのように分離が難しいコンポーネントを複数VPCへENIレベルでアクセスさせたい場合
- 通信事業者のような顧客で「AWS内」と「AWS〜オンプレ間」で異なるタイプの通信を利用する必要があり、論理ネットワークを分離しつつ前述のようなリソースを共有したい場合

https://aws.amazon.com/jp/about-aws/whats-new/2023/10/multi-vpc-eni-attachments/

つまりオンプレミス設備が絡み、かつ特殊な低レイヤーの要件を持つ場合のニーズに応える機能と位置付けられていることが読み取れます。


# まとめ

これまでもクラウド初心者の方がオンプレ→AWS移行を検討する際「現行踏襲で運用監視VPCを作ろう！」と考えてしまう場面は多かったかも知れません。今まではVPCの仕様制約として実現できませんでしたが、今回のアップデートによりそれが可能になってしまいます。

みなさんは是非、周囲でそういった方を見かけたらクラウドにおけるネットワーク設計の根本思想を正しく共有してあげましょう。オンプレミスで頑張っていた方ほど最初は戸惑うかも知れませんが、適切に啓蒙してあげればきっと「クラウドって便利だね！」と思ってくれるでしょう。


# おまけ

早速この新機能を触ってアウトプットくださっている方がいます！ 早いですねｗ

https://dev.classmethod.jp/articles/attatch-ec2-to-multiple-vpc/

https://qiita.com/mksamba/items/15beccc73e647b68d0fa
SeleniumでSBI証券の重要なお知らせを自動で確認する

## やりたいこと
新NISAのタイミングでSBI証券を使い始めようと思ったら重要なお知らせが150件ほどたまっていた。見た感じまとめて確認にするUIもなかったので仕方なく自動化することにした。
※この方法によって重要なお知らせを見落としたことによる損害などについては一切責任を負えません。

## 前提条件
- ChromeDriver
- Python
- Selenium
の実行環境がある




## ソースコード（一部ChatGPTで生成）
``` Python
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
import time

# WebDriverのパスを指定して、ブラウザを開きます（例：Chromeを使用する場合）
driver = webdriver.Chrome()

# ログインページに移動
driver.get('https://sp.sbisec.co.jp/login')

# ログイン処理（自分のユーザー名とパスワードを設定）
username = driver.find_element(By.NAME, 'username')
password = driver.find_element(By.NAME, 'originPassword')
username.send_keys('username')
password.send_keys('password')
password.send_keys(Keys.ENTER)
# 以下負荷を考えて適当にスリープをいれてます
time.sleep(1)

notice_icon = driver.find_element(By.CLASS_NAME, 'icon-tooltip')
notice_icon.click()
time.sleep(1)
href_link = driver.find_element(By.LINK_TEXT, '重要なお知らせ一覧はこちら')
href_link.click()

#重要なお知らせ一覧
driver.switch_to.window(driver.window_handles[1])
time.sleep(1)

# 事前に確認したお知らせ分くりかえす
for i in range(100): 
    #ページ内のリンクを全て洗い出す ※リンクを毎回取り直さないとSeleniumがエラーを吐くのでこのような繰り返し処理にしています
    all_links = driver.find_elements(By.XPATH, "//a[@href]") 
    important_link = ''
    for l in all_links:
        #おしらせようのリンクだけ取り出す
        if 'viewInfo' in  str(l.get_attribute('href')):
            important_link = l
            print(important_link)
            break
    if important_link == '':
        break
    important_link.click()
    time.sleep(1)
    #確認ボタンを押して　閉じる
    confirm_btn = driver.find_element(By.NAME, 'ACT_estimate')
    confirm_btn.click()
    close_btn = driver.find_element(By.NAME, 'ACT_backViewInfoList')
    time.sleep(1)
    close_btn.click()
    time.sleep(1)

# タブを閉じる
driver.close()
# ブラウザを終了
driver.quit()

```
三陸特取得試験（国家試験）の合格体験記

# はじめに
第三級陸上特殊無線技士（通称：三陸特）の国家試験に合格しましたので、あまり記事にする内容でもないと思いますが、合格体験記として残します。

# Who am i ?
しがないエンジニアです。大学の頃は数学寄りの専攻でした。なので無線工学は在学中にほとんど勉強していません。

# なぜ取得しようと思ったのか？
ローカル5Gおよびドローンの無線周波数帯域に対応していることとが主な理由です。

# 本題
前述の通り、ここでは国家試験の試験一発型について述べます。
一言で言うと、難しくない試験です。無線の技術的な所と電波法の周辺をある程度わかっていれば楽勝かと思います。
おそらく学生（高校生～大学の学部生）の方でも十分取得可能な範囲のものです。

https://www.nichimu.or.jp/kshiken/index.html

勉強内容については、公開されている過去問題と以下の本の熟読です。

https://www.amazon.co.jp/%E3%82%84%E3%81%95%E3%81%97%E3%81%8F%E5%AD%A6%E3%81%B6-%E7%AC%AC%E4%B8%89%E7%B4%9A%E9%99%B8%E4%B8%8A%E7%89%B9%E6%AE%8A%E7%84%A1%E7%B7%9A%E6%8A%80%E5%A3%AB%E8%A9%A6%E9%A8%93-%E5%90%89%E6%9D%91-%E5%92%8C%E6%98%AD/dp/4274220281

無線と法規が12×2で合計24問なのですが、合格ラインはそれぞれ6割ないとダメです。試験時間は1hもありますが、私も見直し含めて15分程度で終わりました。対策していれば決して難しくないと思います。（落とす試験ではないと思いますので。）

なお、三陸特はスクールに通い修了試験に合格することでも取得できるようです。
※こちらも免許の申請が必要なようですね。

# 合格後について
合格後2週間～3週間程度で結果がわかりますが、その後に免許の申請が必要です。

https://www.tele.soumu.go.jp/j/download/radioope/

# 終わりに
無線周りは正直あまり詳しくなかったのですが、内容によっては法律や知識をつけていった方が今後のためになると思いました。三陸特の記事はあまりないので、少しでも参考になれば幸いです。
macOS環境にて、gccコンパイルが使えない

# 本記事について
MacBookにて、gccコンパイルが使用できなくなったので、その時に対処した方法について記載したいと思います。

# 実行環境
・macOS Sonoma 14.1
・Xcode 15.0.1
・gcc version 13.1.0 (Homebrew GCC 13.1.0) 
・MacBook Pro 13インチ M2

# 問題概要
上記の実行環境にて、gccコンパイラでコンパイルしようとすると、下記のようなエラーが発生する。
Google先生で調査した限りでは、どうやら<font color="Red">**Xcode 15とHomebrew GCCの相性が良くない**</font>ため、このような<font color="green">**重複したライブラリを無視した**</font>という警告エラーが起きているらしい。
＊~~2023年10月28日（土）時点においても、XcodeもしくはHomebrew GCCが改善される見込みはない…~~
　<font color="Red">**Homebrew GCC 13.2.0にアップグレードした結果、本不具合が解消された**</font>事を確認済み。（2023年11月25日(土)時点）
 
```cpp
domdam007@MacBook-Pro test20221106 % make
g++ -g --sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk main.cpp -o test
-macosx_version_min has been renamed to -macos_version_min
ld: warning: ignoring duplicate libraries: '-lgcc'
0  0x100f03648  __assert_rtn + 72
1  0x100e37fac  ld::AtomPlacement::findAtom(unsigned char, unsigned long long, ld::AtomPlacement::AtomLoc const*&, long long&) const + 1204
2  0x100e4d924  ld::InputFiles::SliceParser::parseObjectFile(mach_o::Header const*) const + 15164
3  0x100e5ae30  ld::InputFiles::parseAllFiles(void (ld::AtomFile const*) block_pointer)::$_7::operator()(unsigned long, ld::FileInfo const&) const + 420
4  0x180e23950  _dispatch_client_callout2 + 20
5  0x180e36ba0  _dispatch_apply_invoke + 176
6  0x180e23910  _dispatch_client_callout + 20
7  0x180e353cc  _dispatch_root_queue_drain + 864
8  0x180e35a04  _dispatch_worker_thread2 + 156
9  0x180fcd0d8  _pthread_wqthread + 228
ld: Assertion failed: (resultIndex < sectData.atoms.size()), function findAtom, file Relocations.cpp, line 1336.
collect2: error: ld returned 1 exit status
make: *** [all] Error 1

```

# 解決方法
2023年10月28日（土）時点において、もしHomebrew GCCでコンパイルしたいならば、<font color="Red">**Xcode 15未満を使用するしかない！！**</font>

本ページでは、<font color="blue">**複数バージョンのXcodeを共存させた方法**</font>について、記載します。

１）過去バージョンのXcodeをDL
下記のURLから、Xcode 14.3.1以前のXcodeをDLします。
https://developer.apple.com/downloads/

２）DLしたXipファイルを解凍
DLしたXipファイルをダブルクリックして、解凍します。
解凍が終わると、`Xcode.app`が生成されます。
あとで他のXcodeと区別がつき易いよう、私は`Xcode.app`から<font color="Green">`Xcode_14.3.1.app`</font>にリネームしました。

３）Applicationフォルダへ移動
<font color="blue">Applicationフォルダへリネームした`Xcode_14.3.1.app`を移動</font>させます。

４）xcode-selectコマンドによる切り替え
<font color="red">`xcode-select`コマンドを用いて自分が使用したいXcodeを選択</font>します！
```cpp
domdam007@MacBook-Pro test20221106 % sudo xcode-select --switch /Applications/Xcode_14.3.1.app 
Password:
domdam007@MacBook-Pro test20221106 % 
```

このように`XcodeのバージョンをHomebrew GCCが使用できたバージョン14.3.1に切り替える`ことで、`Homebrew GCCを用いたコンパイルが再び可能`になります。

```cpp
domdam007@MacBook-Pro test20221106 % make
g++ -g --sysroot=/Applications/Xcode_14.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk main.cpp -o test
domdam007@MacBook-Pro test20221106 % 
```
MSX BASICでbase64エンコーダを実装

# はじめに
皆さん、こんにちは。
さて、前回の投稿までで、MSX BASICにコンソール経由でファイルを転送するスクリプトを実装しました。

https://qiita.com/enu7/items/23cab122141fb8d07c6d

ファイル送信が実装したら、やはり受信も実装しないとねということで、まずはMSX-BASICでbase64エンコーダを実装します。

# 環境
MSX:MSX0Stack
クライアントPC：Windows+WSL,TeraTerm

# エンコーダ実装
以下実装コードです。
```bbcbasic
10 DEFINT A-Z:DIM I$, O$, B$:CLEAR 1000
20 INPUT "Please Input the text for base64 encoding:"; I$
30 GOSUB 100'CALL B64E(I$, O$, B$)
40 PRINT "Result:"; O$
50 END
100 'B64E(I$, O$, B$)
110 DIM B(3), OB(4)
120 DIM T$, C$
130 LET O$ = ""
140 LET B$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
150 FOR I = 1 TO LEN(I$) STEP 3
160   T$ = MID$(I$, I, 1)
170   IF LEN(I$) >= I + 1 THEN T$ = T$ + MID$(I$, I + 1, 1)
180   IF LEN(I$) >= I + 2 THEN T$ = T$ + MID$(I$, I + 2, 1)
190   FOR J = 1 TO 3
200     B(J) = 0:
210   NEXT J
220   FOR J = 1 TO LEN(T$)
230     B(J) = ASC(MID$(T$, J, 1)) 
240   NEXT J
250   OB(1) = B(1) \ 4
260   OB(2) = (B(1) AND 3) * 16 + B(2) \ 16
270   OB(3) = (B(2) AND 15) * 4 + B(3) \ 64
280   OB(4) = B(3) AND 63
290   FOR J = 1 TO 4
300     IF J >= 3 AND LEN(T$) = 1 THEN O$ = O$ + "=" ELSE IF J = 4 AND LEN(T$) = 2 THEN O$ = O$ + "=" ELSE O$ = O$ + MID$(B$, OB(J) + 1, 1)
330   NEXT J
340 NEXT I
350 RETURN
```

# 実行結果
では、TeraTermでBASICソースをコピペして実行しましょう。エンコード文字列は「ABCDEFG」です。
```bbcbasic
run
Please Input the text for base64 encoding:? ABCDEFG
Syntax error in 180
Ok
```
はい、エラーです。180行をみてみましょう。

```bbcbasic
list 180
180   IF LEN(>= I + 2 THEN T$ = T$ + MID$(I$, I + 2, 1)
```
たまに転送時に文字が書けることがありますので、ソースコピペ後チェックサムかけるようなことが必要でしょうね…。
```bbcbasic
180   IF LEN(I$) >= I + 2 THEN T$ = T$ + MID$(I$, I + 2, 1)
```
180行目を再度コピペ入力後、気を取り直して実行します。
```
run
Please Input the text for base64 encoding:? ABCDEFG
Result:QUJDREVGRw==
Ok
```
結果がでましたね。「QUJDREVGRw==」です。さて、これをbase64デコードして正常動作の確認を行います。今回はWSL上のbase64コマンドを使用してデコードしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106997/499e4870-d6d3-994e-7680-1a90e7a249eb.png)

「ABCDEFG」とデコードできましたね。
次はちょっと長めの文字列も試してみましょう。
TeraTermからUTF-8の日本語を無理やり流し込んでみます。前回も使用したじゅげむの一節です。

```text
じゅげむじゅげむ　ごこうのすりきれず　かいじゃりすいぎょの　すいぎょうばつ　ふうらいばつ　くねるところにすむところ
```
TeraTeram経由でMSX-BASICでプログラムを実行して、テキストを入力します。TeraTerm上では日本語表示されますが、MSX上はバケバケです。
```bbcbasic
run
Please Input the text for base64 encoding:? じゅげむじゅげむ　ごこうのすりきれず　かいじゃりすいぎょの　すいぎょうばつ　ふうらいばつ　くねるところにすむところ
Result:44GY44KF44GS44KA44GY44KF44GS44KA44CA44GU44GT44GG44Gu44GZ44KK44GN44KM44Ga44CA44GL44GE44GY44KD44KK44GZ44GE44GO44KH44Gu44CA44GZ44GE44GO44KH44GG44Gw44Gk44CA44G144GG44KJ44GE44Gw44Gk44CA44GP44Gt44KL44Go44GT44KN44Gr44GZ44KA44Go44GT44KN
Ok
```
結果がでましたね。出力されたテキストが正しくbase64エンコードできているか。さきほどと同様にWSL上でbase64コマンドで確認してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106997/5071df2d-f579-2389-1169-5a2bbe227041.png)

じゅげむ・・、いけてそうですね。

# 最後に
今回はbase64エンコーダを実装しました。ファイル受信する際にTeraTermを経由するのであればbase64エンコーダは要らないのではという考えもよぎるのですが、base64エンコードして転送する方針で実装すすめたいと思います。

要らないのでは！

現場からは以上です！
Promise.allの性能向上とPromiseバッチ処理のためのライブラリ 

こんにちは、
Promise.allは配列で一番長いプロミスがチャンクの実行時間になります。
このため、最も長いプロミスが完了するまで次のプロミスが何もしないという非効率的な問題が発生します。
私はこの問題を効果的に解決するために"Arehs"を作りました。

**🤔 WHY AREHS?**
Arehsはイベント中心のchunk processingを目指す最高の大規模バッチ処理を保証します。
これは、最初の非同期タスクの呼び出しが完了するのを待つことなく、次の非同期タスクの呼び出しを即座に割り当てることで、密にプロセスを実行します。

**これにより、次のような多くのことを達成することができます：**
プロミスの同時性を設定することで、サービスのスループットを制御することができます。
プロミスの同時性を設定することで、下流サービスの負荷を管理します。
アプリケーションのパフォーマンス向上
CPUアイドル時間の削減など


**Promise.all**
ご覧のように、Promise.allはバッチ内で最も遅いプロミスと同じ時間だけ実行されます。
つまり、メインスレッドは基本的に "何もせず"、最も遅いリクエストが終了するのを待っているのです。
Promise配列の中で一番長いプロミス、4番がチャンクの実行時間になります。
これは、最長のプロミスが終了するまで次のプロミスが何もしないという非効率な問題を引き起こします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586230/c46ce555-ae86-f203-a328-da83d4911305.png)

**Arehs**
Arehsはプロミスプルパターンを実行してNode.jsのメインスレッドを最大限に活用することが重要です。
利用率を高めるためには、APIコール(または他の非同期タスク)を密集して、最も長いコールが完了する間、待機しないようにする必要があります。
待たずに最初の呼び出しが完了するとすぐに次の呼び出しをスケジュールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3586230/051eb393-d45e-1842-39d4-4c8dd2ef17a2.png)


このプロジェクトに興味がある方は、日本語翻訳のためのドキュメントや新機能や問題解決のためにPull Requestすることができます。

詳細は下記のリンクを確認してください。
ありがとうございます。🙏

https://www.npmjs.com/package/arehs?activeTab=readme
optparseの使い方

## optparseとは
コマンドラインのオプションを使うためのライブラリのことです。
プログラムを実行する際に、-の後ろにアルファベットを付け加えことでプログラムの挙動を変えることができます。
Rubyではオプション解析できるライブラリがありそれが`optparse`です
## 使い方
### 基本的な使い方
Rubyのリファレンスより
``` ruby:sample.rb
require 'optparse'
opt = OptionParser.new

opt.on('-a') {|v| p v }
opt.on('-b') {|v| p v }

opt.parse!(ARGV)
p ARGV

```

```:結果
ruby sample.rb -a foo bar -b baz
# => true
     true
     ["foo", "bar", "baz"]
```
`require 'optparse' : ` 組み込みライブラリでない標準ライブラリの読み込み
`opt = OptionParser.new : ` OptionParsserオブジェクト、optを生成

`opt.on('-a') {|v| p v }: ` onメソッドの引数でオプションを定義
ARGVにコマンドラインで渡された引数、オプションが配列として格納されます
`opt.parse!(ARGV): ` 配列ARGVの解析を行う
ARGVからオプションを除く必要がなければ破壊的メソッドを使わなくてよし

`p ARGV: ` ARGVの中身を表示

```:結果
# opt.parse(ARGV)の場合
ruby sample.rb -a foo bar -b baz
# => true
     true
     ["-a","foo", "bar", "-b", "baz"]
```
### 引数のクラスを指定する,引数の指定の有無

``` ruby:sample.rb
# Integerのみ
opt.on('-a',Integer) {|v| p v }
# Stringのみ
opt.on('-b',String) {|v| p v }
# 末尾に任意の文字列を加えると引数必須になる
opt.on('-c int', Integer) {|num| params[:int] = num }
# 必須でない場合
opt.on('-d [val]') {|v| params[:val] = v }
```

### オプションの指定を記憶する
Rubyリファレンスより
> OptionParser 自体は、どのオプションが指定されたかを記憶しません。後の処理の方で、オプションによる条件判断を加えるには、他のコンテナに格納します。

指定されたオプションを以後のコードで使用するにはハッシュを使います
```ruby:sample.rb
require 'optparse'
opt = OptionParser.new

params = {}

opt.on('-a') {|v| params[:a] = v }
opt.on('-b') {|v| params[:b] = v }

opt.parse!(ARGV)
p ARGV
p params
p params[:a]
```
```:結果
ruby sample.rb -a foo bar -b baz
# => ["foo", "bar", "baz"]
     {:a=>true, :b=>true}
     true
```

optionメソッドの末尾に引数の有無がない場合は`true`が返ってくる
optionの引数を後のコードで使う場合は引数必須にすると引数が使える

```ruby:sample.rb
~~~~~~略~~~~~~~

opt.on('-a VAL') {|v| params[:a] = v }
opt.on('-b val') {|v| params[:b] = v }
opt.on('-c int') {|num| params[:int] = num }
opt.parse!(ARGV)
p params
p params[:a]
p params[:b]
p params[:int]
```

```:結果
ruby sample.rb -a foo -b bar -c 3
# => {:a=>"foo", :b=>"bar", :int=>3}
     "foo"
     "bar"
      3
```
## 終わりに
以上が私が学習したことを自分なりにまとめてみました。
間違え等ございましたらご教授願います。

https://docs.ruby-lang.org/ja/latest/library/optparse.html
機能安全規格

機能安全規格の利点と課題


 <この項は書きかけです。順次追記します。>

利点は、安全規格が、ソフトウェアまで言及していないことがある。
機械、電気について、計算機で制御していれば、ソフトウェアが安全に関連していることがあるかもしれない。

機械制御、電気制御していた機能をソフトウェア制御に変えた場合に、どのような条件が成立すれば、同じ安全性が確保できるかどうかを記述するとよい。

たとえば、電源容量が、１時間以上確保できている。
電磁雑音の瞬時値、短時間合算値が、規定水準以下である。

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
systemdによるサービス作成（Ubuntu起動時処理）

## はじめに
raspi起動時にFastAPIを立ち上げるにあたって、
Ubuntuのサービス作成で詰まった。
メモ的だが、色々と手順をつらつら。


#### 使った環境
- Description:    Ubuntu 22.04.3 LTS
- RaspberryPi 4B

## Step.1 起動方法選択
ubuntuで取りうる手段は3つ。･･･rc.local、init.d、systemd 
⇒今回はsystemdを選択

## Step.2 shellファイルを準備
ワンライナーでpyファイル実行まで書く
```shell:/home/ubuntu/python/homeAPI/start.sh
cd /home/ubuntu/python/homeAPI; python3 main.py
```

shellファイルに実行権限を付与する
```bash:bash
chmod +x /home/ubuntu/python/homeAPI/start.sh
```

## Step.3 Serviceファイル作成
```/etc/systemd/system/bootstrap.service
[Unit]
Description=bootstrap service
After=network.target

[Service]
User=ubuntu
ExecStart=/bin/sh /home/ubuntu/python/homeAPI/start.sh
Restart=no
Type=simple

[Install]
WantedBy=multi-user.target
```
単にshellファイル作成ではNG。`ExecStart=/bin/sh hoge.sh`で書かないと動かず。IoTなどネットワーク前提のServiceの場合は、`After=network-online.target`にする。（ネットワーク疎通できてないのにService起動してしまい、ハマった）

## Step.4 Service確認
サービス開始、サービスステータスを確認
```bash:bash
sudo systemctl daemon-reload
sudo systemctl start bootstrap
sudo systemctl status bootstrap.service
```
コンソール出力（正常時）
```bash:bash
● bootstrap.service - bootstrap  service
     Loaded: loaded (/etc/systemd/system/bootstrap.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2023-10-28 11:01:27 UTC; 24min ago
   Main PID: 717 (sh)
      Tasks: 3 (limit: 4416)
     Memory: 57.5M
        CPU: 9.415s
     CGroup: /system.slice/bootstrap.service
             ├─717 /bin/sh /home/ubuntu/python/homeAPI/start.sh
             └─742 python3 main.py
　#以下省略
```
失敗時はsyslogを確認。ログが長いのでタイムスタンプで探すと良い。
```bash:bash
less /var/log/syslog
```
失敗例：`/bin/sh`を忘れていたり、実行権限が無いなど。

## Step.5 Serviceを登録
無事サービスの開始が確認出来たら、サービスを登録する。
解除時はdisable。
```bash:bash
sudo systemctl enable bootstrap
```
## 最後に
簡潔にまとまった。これは･･･覚えてられない。
【Swift】CIFilterを使用して画像をピクセル画像に変換する

# はじめに
CIFilterで画像をピクセル化することができるっぽいのでやってみました

# サンプルアプリ
![Simulator Screen Recording - iPhone 15 - 2023-10-28 at 20.32.34.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d6a3604c-ba56-e76e-9628-068c0fbebb3f.gif)

# 実装
```swift
import SwiftUI

struct ContentView: View {
    private let image = UIImage(named: "sample1")!

    @State private var uiImage: UIImage?
    
    @State private var scale: CGFloat = 0

    var body: some View {
        ScrollView {
            VStack {
                if let uiImage {
                    Image(uiImage: uiImage)
                        .resizable()
                        .scaledToFit()
                } else {
                    Image(uiImage: image)
                        .resizable()
                        .scaledToFit()
                }

                HStack(spacing: 15) {
                    Button {
                        applyPixellate()
                    } label: {
                        Text("適用")
                    }

                    Button {
                        uiImage = nil
                        scale = 0
                    } label: {
                        Text("リセット")
                    }
                }
                
                VStack {
                    Text("粒度: \(scale)")
                    Slider(value: $scale, in: 0...50)
                }
            }
            .padding(.horizontal, 20)
        }
    }

    func applyPixellate() {
        let context = CIContext()
        let inputImage = CIImage(image: image)!

        guard let filter = CIFilter(name: "CIPixellate", parameters: [
            kCIInputImageKey: inputImage,
            kCIInputScaleKey: scale
        ]) else { return }
        guard let outputImage = filter.outputImage else { return }
        guard let cgImage = context.createCGImage(outputImage, from: outputImage.extent) else { return }
        self.uiImage = UIImage(cgImage: cgImage)
    }
}
```

# おわり
これだけで簡単なアプリが作れそうですね
Containerd のインストール

> [!NOTE]
> Docker ⇒ Containerd へ移行中のメモです。nerdctl コマンドを実行するユーザの権限を調査中です。

# インストール

## Containerd

1. Download containerd

    ```bash
    wget https://github.com/containerd/containerd/releases/download/v1.7.7/containerd-1.7.7-linux-amd64.tar.gz
    sudo tar zxvf containerd-1.7.7-linux-amd64.tar.gz -C /usr/local/
    ```

2. Configure containerd

    ```bash
    sudo wget \
        https://raw.githubusercontent.com/containerd/containerd/main/containerd.service \
        -O /etc/systemd/system/containerd.service

    sudo systemctl daemon-reload
    sudo systemctl start containerd
    sudo systemctl enable containerd
    ```


## nerdctl

1. 関連ツールのインストール

    ```bash
    sudo apt install -y rootlesskit
    ```

2. nerdctl のインストール

    ```bash
    wget https://github.com/containerd/nerdctl/releases/download/v1.6.2/nerdctl-1.6.2-linux-amd64.tar.gz
    sudo tar zxvf nerdctl-1.6.2-linux-amd64.tar.gz -C /usr/local/bin/
    containerd-rootless-setuptool.sh install
    ```

3. BuildKit の有効化

    * BuildKit のインストール

        ```bash
        wget https://github.com/moby/buildkit/releases/download/v0.12.3/buildkit-v0.12.3.linux-amd64.tar.gz
        sudo mkdir /usr/local/buildkit
        sudo tar zxvf buildkit-v0.12.3.linux-amd64.tar.gz -C /usr/local/buildkit

        echo "export PATH=$PATH:/usr/local/buildkit/bin" >> $HOME/.bashrc
        source $HOME/.bashrc
        ```

    * BuildKit の有効化

        ```bash
        CONTAINERD_NAMESPACE=default containerd-rootless-setuptool.sh install-buildkit-containerd
        ```

4. ranc のインストール

    ```bash
    sudo wget https://github.com/opencontainers/runc/releases/download/v1.1.9/runc.amd64 -O /usr/local/bin/runc
    sudo chmod +x /usr/local/bin/runc
    ```

5. CNI Plugin のインストール

    ```bash
    wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz
    sudo mkdir -p /opt/cni/bin
    sudo tar -zxvf cni-plugins-linux-amd64-v1.3.0.tgz -C /opt/cni/bin
    ```

6. 動作確認

    * nerdctl コマンド

        ```bash
        sudo nerdctl run -d -p 8080:80 --name nginx-test nginx
        ```

    * nerdctl compose コマンド

        ```yaml:docker-compose.yaml
        version: "3"
        services:
          nginx:
            image: nginx:latest
            restart: always
            ports:
              - "8080:80"
        ```

        ```bash:コンテナの起動
        sudo nerdctl compose up -d --build
        ```

    ブラウザや curl コマンド等で `http://localhost:8080/` を参照すると nginx のデフォルト画面が参照できると思います。  

    コマンドオプションを見る限りでは docker コマンド ⇒ nerdctl コマンドは、実行するコマンドを変更する程度で移行できそうです。`docker compose` コマンドについても `nerdctl compose` で同じ YAML ファイルが使用できそうです。


# 参考サイト

* containerd
    * [containerdとは](https://www.designet.co.jp/faq/term/?id=Y29udGFpbmVyZA)
    * [Containerd, Docker, Kubernetesの関係について](https://forum.ficusonline.com/t/topic/458)

* nerdctl
    * [containerdを使用したコンテナ開発](https://tech-lab.sios.jp/archives/28641)
    * [Containerdとnerdctlで個人検証環境のDockerを置き換えた](https://zenn.dev/igeta/articles/1507f1c3311814)
    * [Dockerからcontainerdへの移行 (NTT Tech Conference 2022発表レポート)](https://medium.com/nttlabs/docker-to-containerd-4f3a56e6f2b6)
WindowsでRubyのRMagickをインストールする

# 追記(2024-1-19)
どうやらこの方法は必ず正しくはないようです。私の環境では上手く行きましたが、もしかしたら別の問題の可能性があります。その上で、この記事をお読みください。

# はじめに
ふとRubyでRMagickを使いたいと思い、`gem install rmagick`を実行。すると、
```powershell:cmd
ERROR: Can't install RMagick 5.3.0. 
Can't find the ImageMagick library. 
Retry with '--with-opt-dir' option.
```
と怒られちゃいました。原因はImageMagickのバージョンらしいです。
このバージョンを7以外にすれば解決します。

# 解決
[アーカイブ](http://ftp.icm.edu.pl/packages/ImageMagick/binaries/)から適切なbitの6.xバージョンのImageMagickをダウンロードしてインストールしてください。
(例:ImageMagick-6.9.12-98-Q16-HDRI-x64-dll.exe)
このとき、**必ず**dllのものを選択してください。

次に、ダウンロードしたインストーラーを起動し、以下のオプションを有効にしてインストールしてください。

・Add application directory to your path
・Install development headers and libraries for C and C++


インストールが完了したら、コマンドプロンプトを起動し、以下のコマンドを適切に書き換えて実行します。
```powershell:cmd
gem install rmagick --platform=ruby -- --with-opt-lib="パス/lib" --with-opt-include="パス/include"
```

ここで、パスの部分にはさきほどインストールしたImageMagickのパスを指定してください。
(例:"C:/Program Files/ImageMagick-6.9.12-Q16-HDRI")
また、環境によってはエラーになる可能性があるためバックスラッシュではなくスラッシュを使ってください。

これで正常にRMagickがインストールできると思います。

# FAQ
・ImageMagickをインストールしたのに認識されない
→コマンドプロンプトを再起動してください。

・RubyInstaller2 を使っているが、うまくいかない
→ImageMagickのdllファイルを、`Ruby/rubyinstaller-xx/bin/`にすべてコピーしてください。

# 参考文献
翻訳元:https://medium.com/ruby-on-rails-web-application-development/install-rmagick-gem-on-windows-7-8-10-imagemagick-6-9-4-q16-hdri-5492c3fef202
TypeScriptでCanvas

結論：下記のように書く
今回は斜線をcanvasで描いている


```typescript
import { FC } from "react";


export const Canvas:FC = () => {



    const canvas= document.getElementById("canvas-in") as HTMLCanvasElement;
    if (canvas) {
        
        canvas.width = 200;
        const ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
        canvas.width = 300;
        canvas.height = 300;

        ctx.beginPath();
        ctx.moveTo(50,50);
        ctx.lineTo(150,150);
        ctx.stroke();


    }else if(!canvas){
        console.log('canvasを取得できません');
    }




    return(
        <div className="border border-gray-300">
            <h1>Canvas</h1>
            <canvas id="canvas-in" className="border border-blue-300"></canvas>
        </div>
    );
}


```

実行結果
![cあ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3332453/5519e3ea-df04-ccbb-2437-7fba5d393b86.png)
ChatGPTのプロンプトの仕組みってどうなっているの？PythonとAPIを使って説明します。簡単なので非エンジニアもわかります。

ChatGPTの質問（プロンプト）するときにどんな風に使っていいかわかりますか？多くのサイトやSNSなどでプロンプトの紹介をしている人達がいますが、仕組みを知ってしまえば簡単なので自分で考えて作ることができます。
そうすると、プロンプトを探す手間が省けるのでChatGPTを使う時間が増え、より効果的なプロンプトを作ることができますよ。
プログラミングがわからなくても大丈夫です。

## まずはChatGPT
**プロンプト:**
あなたは俳人を演じてください。春についての俳句を作ってください。テーマは喜びです。

**ChatGPT:**
春の風
花が笑顔咲く
心踊る

この俳句は、春と喜びのテーマを探求しています。"春の風"は春が近づいているという暗示であり、新しい始まりと希望に満ちています。次に、"花が笑顔咲く"は自然界が目覚め、喜びに満ちていることを象徴しています。最後に、"心踊る"はこの美しい季節に触れたときの人々の喜びを表現しています。全体として、この俳句は春の喜びと美しさを称賛しています。

重要なものはプロンプトの”あなたは俳人を演じてください。春についての俳句を作ってください。テーマは喜びです。”
これがどうなっているかを知るのが今回のテーマです。それでは行ってみましょう！


    import openai
    
    openai.api_key = "secret key"
    
    def get_completion_from_messages(messages, 
                                     model="gpt-3.5-turbo", 
                                     temperature=0, 
                                     max_tokens=100):
        
            response = openai.ChatCompletion.create(
                model=model,
                messages=messages,
                temperature=temperature, # this is the degree of randomness of the model's output
                max_tokens=max_tokens, # the maximum number of tokens the model can ouptut 
            )
            
            return response.choices[0].message["content"]
    
    messages =  [  
        {'role':'system', 
        'content':"あなたは俳人です"},
        {'role':'system', 
        'content':"春"},
        {'role':'system', 
        'content':"喜び"},         
        {'role':'user', 
        'content':"俳句を作って"}
        ] 
    
    response = get_completion_from_messages(messages, temperature=1)
    print(response)

プログラミングがわかる方はこれで一回試してくださいね。

で重要なところはここ。

    messages =  [  
        {'role':'system', 
        'content':"あなたは俳人です"},
        {'role':'system', 
        'content':"春"},
        {'role':'system', 
        'content':"喜び"},         
        {'role':'user', 
        'content':"俳句を作って"}
        ] 


ここに何やらズラーっと文字があります。ここで、GPTの役割を設定しています。
例えば、 {'role':'user', 'content':"俳句を作って"}
というのは、GPTに質問をするプロンプトです。


- role = 役割

- content = 指示

ここではユーザー、つまり、私がGPTに指示したいことを設定しています。
ChatGPTのプロンプトで言うと「俳句を作ってください」のところです。

で、次はこれ。

    {'role':'system','content':"あなたは俳人です"},
    {'role':'system','content':"春"},
    {'role':'system','content':"喜び"},

ここでのroleはシステム。これはモデルに対してどんな役割を演じてもらいたか、どんなことをしてもらいたいかを指示しています。

ChatGPTでは
"あなたは俳人を演じてください。"
"春について"
"テーマは喜びです。"
の部分になります。

こうやってひとつひとつ役割を設定することでより詳細に返信を調整することができるのです。

## ひとつで良くない？

実際に {'role':'user', 'content':"俳句を作って"}でもGPTは出力されますし、 {'role':'user', 'content':"あなたは俳人を演じてください。春についての俳句を作ってください。テーマは喜びです。"}でも大丈夫です。

### ではなぜ分けるのか？
例えば、ChatGPTに最初に”あなたは英語教師を演じてください！”と入力することで、それ以降の質問は全て英語教師を演じてくれます。
そして、その後に、わからない英単語を何回質問しても英語教師として答えてくれます。
そうすることで”あなたは英語教師を演じてください！Userの日本語を教えてください。”と何回も入力する必要がなくなります。

コードの方でいうと"system"で一度だけ設定しておくと、何回質問を入力されても俳人を演じて、春の喜びをテーマに俳句を作ってくれるようになるのです。

ちょっと難しかったですかね。質問、疑問があったらコメントをよろしくお願いします。

## まとめ
ChatGPTのすごく長いプロンプトを見たことがあると思いますが、あれも"role"を追加していくと。すごく長くなってしまったということなのです。
ChatGPTのプロンプトを作るときにはより具体的に誰を演じてもらいたくて、何をやってもらいたいのかを考えて入力するのがおすすめです。
質問の質が上がるとChatGPTからの返事もすごく良くなりますよ！
XO プラットフォームからメール送信方法

XOプラットフォームからサードパーテイのAPIを使用してメール送信ができます。
以下SendGrid APIを使用してメール送信を紹介します。


Step１：SendGridの無償アカウントを作成します

Step２：SendGridのWeb API選択

以下のURLをアクセスしてWeb APIを選択します。

https://app.sendgrid.com/guide/integrate

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/3233adc3-ca42-c3be-db61-d375da9a0578.png)


Step３： cURLを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/bc3ec757-361f-308c-18a6-bd5ef790bb00.png)


Step４：画面上でMy First API Key Nameの項目にAPIキーの名前を設定します



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/aab8adfc-a8b3-598f-96fb-ec937f6e9ffe.png)

例えば　TestAPI1を入力してCreate Keyボタンを押します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/12cca686-e7f2-e653-2163-9b99b04cfbd0.png)

ボタン押してから以下画面上でAPIキーが作成されます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/efbce491-6c7b-2d61-a8f9-29ee84d72501.png)



次 I have executed the codeのチェックボックスを選択して Verified Integrationボタン押します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/74bca86c-555a-ee77-b60f-1b54613d2921.png)



XOプラットフォームにログインして、SendEmail名前のタスクボットを作成します。
ボットアクション「sendEm」を追加します。
sendEm ボットアクション内にスクリプトノードを追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/6f568e46-24cb-1214-af23-263236e8866f.png)

スクリプトノードを以下のように設定します

```ruby:Script.rb
context.entities.EmailMsg = "お客様の予約内容が以下になります。" + context.session.BotUserSession.name + "様、" + context.session.BotUserSession.address + "、"+context.session.BotUserSession.address+ "、" + "、" + "。";
puts 'code block.'
```
EmailMsg Entityノード追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/52bab6fe-35b2-14b2-78f1-5c8b7887374c.png)


最後に新しいボットアクションノードを追加して、Serviceノード設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/97cef199-1325-2d02-b8e7-761c7844d48e.png)


ヘッダーは以下のように設定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/52dbd720-a3a8-d4fd-cd61-a60255efc6af.png)


ボデイの場合は、application/jsonを選択し、以下のコードを設定して保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/10bc9c3d-3c02-41dc-2732-ceb8af4c7ecc.png)


```ruby:title.rb
{
  "personalizations": [
    {
      "to": [
        {
          "email": "sandeep.s@z.com"
        }
      ]
    }
  ],
  "from": {
    "email": "sand.s@p.com"
  },
  "subject": "予約メール",
  "content": [
    {
      "type": "text/plain",
      "value": "{{context.entities.EmailMsg}}"
    }
  ]
}
puts 'code block.'
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556493/cacf463c-3ca8-bb21-f9b7-dbae5b623dc7.png)

以上
Expo > supabase > URL.hostname is not implemented となる場合


![185299634-90910da3-3b1e-47df-bca9-8c4ad82f610a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49910/3ea94405-7e13-0559-b04f-1975b7bb6e55.png "185299634-90910da3-3b1e-47df-bca9-8c4ad82f610a.png")



# 結論

`URL.hostname is not implemented`と表示される場合には、`react-native-url-polyfill`を導入する。

```
yarn add react-native-url-polyfill          
```

以下のようにsupabaseを使うところで、importする

```
import 'react-native-url-polyfill/auto';
import { createClient } from '@supabase/supabase-js';
```



# 参考

[URL\.hostname is not implemented · Issue \#8464 · supabase/supabase](https://github.com/supabase/supabase/issues/8464#issuecomment-1221448428)
.NETにて、自己署名証明書を発行し、開発中にHTTPSを使用できるようにする

## 参考記事
https://learn.microsoft.com/ja-jp/dotnet/core/tools/dotnet-dev-certs

## 環境
- Windows10 Pro
- Visual Studio 2022
- .NET 7.0

## コマンドの説明
`dotnet dev-certs`コマンドを実行することで自己証明書が生成され、ローカルWebアプリ開発中にHTTPSを使用できるようになる。dotnet dev-certsコマンドの主な機能は以下の通り
- 開発中にHTTPSエンドポイントで使用する証明書を生成する
- ローカルコンピュータで生成した証明書を信頼する
- ローカルコンピュータから生成した証明書を削除する
- 証明書をさまざまな形式でエクスポートして、他のツールで使用できるようにする
- ツールによって生成された既存の証明書をローカルコンピュータにインポートする

## 使用方法
`dotnet dev-certs`には1つのコマンド`https`しかなく、`dotnet dev-certs https`コマンドを実行することで、開発証明書がマシン上の現在のユーザーの証明書ストアに存在するかどうかを確認する

#### 自己署名証明書を作成
- 作成コマンドを実行
```
dotnet dev-certs https
```
- 既に証明書が存在する場合は以下のようなメッセージが表示される
```
A valid HTTPS certificate is already present.
```
- 証明書がなく、正常に作成ができた場合はコマンドでは次の例のようなメッセージが表示される
```
The HTTPS developer certificate was generated successfully.
```
コマンドで開発証明書が見つからない場合は、現在のユーザーの証明書ストア (CurrentUser という場所にある My という名前のストア) に開発証明書が作成され、証明書の物理的な場所は、.NET ランタイムの実装の詳細であり、いつでも変更可能。

- 証明書を信頼
**※規定では、新しく作成された証明書は信頼されていないため、証明書を信頼するには`--trust`オプションを使用する必要あり**
```
> dotnet dev-certs https --trust
Trusting the HTTPS development certificate was requested. A confirmation prompt will be displayed if the certificate was not previously trusted. Click yes on the prompt to trust the certificate.
```
- 翻訳するとこんな感じ
> HTTPS 開発証明書を信頼することが要求されました。証明書が以前に信頼されていない場合は、確認プロンプトが表示されます。プロンプトで「はい」をクリックして証明書を信頼します。

- 画面上で表示されているダイアログにて「はい」をクリックして、証明書をインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2711955/d2fa6180-dd29-f2a4-9f77-587dc2d04e06.png)

#### 自己署名証明書の確認
- 信頼された開発証明書がローカル コンピューターに存在するかどうかを確認。`A valid certificate was found:`が表示されていればOK
```
> dotnet dev-certs https --check --trust
A valid certificate was found: ~
```
以上です。
[入門] Raycastの拡張機能開発

## 拡張機能のReactプロジェクトを作成

Raycastからプロジェクトを作成可能になっています。

![スクリーンショット 2023-10-28 12.16.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/e30f39ea-cbbc-434f-2b41-9b71380c69d4.png)

Raycastにて`create extension`と入力するとプロジェクトを作成するフォームが出てきます。

![スクリーンショット 2023-10-28 11.39.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/71219688-f2f0-3bc3-a23a-f2a2fe2396c8.png)

各フォームを入力して拡張機能用のReactプロジェクトを作成していきます。

下記にフォームの詳細を記載します。

### 各フォームについて

- Organization：組織設定。
- Template：様々テンプレートを選んでプロジェクトを作成できる。下記に一部のテンプレートを紹介
    - None：テンプレートを使用せず、自分自身で拡張機能を開発したい場合に使用するテンプレート
    - Detail：オプション`markdown`にマークダウン記法表示出来るテンプレート
    - Form：そのままで入力した値からデータ取得することが出来るテンプレート
    - List and Detail：データやファイルをリスト表示出来るテンプレート
- Extension Name：拡張機能名に使用
- Description：作成する拡張機能の説明を記入
- Categories：作成した際にRaycast Storeで公開時に使用するカテゴリーを設定
- Location：プロジェクトを作成するディレクトリーを設定

![スクリーンショット 2023-10-28 18.33.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311195/68182699-a5f2-8027-8c5b-39c18bb2ea42.png)

- Command Name：Raycastで検索時に表示されるコマンド名
- Subtitle：「Command Name」の横に表示されるタイトル
- Description：「Raycast Settings」の「Extensions」で作成したコマンドを確認した際に表示されるコマンドの詳細

### パッケージインストール

作成した拡張機能のプロジェクトまで移動をして`yarn`または`npm install`を実行してパッケージをインストールしていきます。

最低限、必要なパッケージはインストールされます。

他に作成したい拡張機能で必要なパッケージがある場合は個々でインストールをしてください。

### コードを書きながら拡張機能をホットリロード

npmスクリプトに記載されている`dev`を実行すると今までのReactでのWeb開発と同様にホットリロードが効いて開発がしやすいです。

## 最後に

基本的な開発方法を記載してきました。

開発でしようしている言語はReactとTypeScriptのため扱いやすい言語のためユニークな拡張機能や作業効率の向上に繋げてみてください。

公式ドキュメントは下記に添付いたします。

https://developers.raycast.com/