OmniAICreator/Qiita-1.07M huggingface dataset:
C#と.NET 8を活用したコンソールアプリケーションにおける依存性注入の実装

依存性注入（DI：Dependency Injection）は、ソフトウェア開発においてコンポーネント間の結合度を下げ、テストやメンテナンスを容易にするための重要なデザインパターンです。C#と.NET 8を用いたコンソールアプリケーションでの「依存性注入」の実装について説明します。

## 依存性注入コンテナの設定
`.NET Core` および `.NET5`以降では、`Microsoft.Extensions.DependencyInjection`を使用して依存性注入をサポートします。これにより、アプリケーションの様々な部分で必要とされる依存関係を管理しやすくなります。

```cs
var services = new ServiceCollection();
ConfigureServices(services);
```
`ServiceCollection`クラスを使用して依存性注入コンテナを初期化し、アプリケーションで使用するサービスを登録します。

## サービスの登録
依存性注入を利用するには、サービス（この場合はリポジトリ）をコンテナに登録する必要があります。これにより、インターフェースとその実装間の関連付けが行われます。

```cs
private static void ConfigureServices(ServiceCollection services)
{
    services.AddTransient<IUserRepository, UserRepository>();
}
```
ここでは、`IUserRepository`インターフェースとその実装である `UserRepository`をトランジェント（毎回新しいインスタンスを生成）スコープで登録しています。これにより、`IUserRepository`が要求されるたびに `UserRepository`の新しいインスタンスが提供されます。

## サービスプロバイダのビルドとサービスの取得
サービスプロバイダをビルドし、登録したサービスを取得して利用します。

```cs
using (var serviceProvider = services.BuildServiceProvider())
{
    var userRepository = serviceProvider.GetRequiredService<IUserRepository>();
    ...
}
```
`BuildServiceProvider`を呼び出すことで、サービスプロバイダをビルドします。そして、`GetRequiredService`を使用して、`IUserRepository`インターフェースの実装を取得し、利用します。

## サービスの利用
取得したサービス（この場合はリポジトリ）を使用して、ビジネスロジック（ユーザーの保存や検索など）を実行します。

```cs
var user = new User(new UserId("T001"), new UserName("Tom"));
userRepository.Save(user);

var head = userRepository.Find(user.Name);
Console.WriteLine(head.Name.Value);
```

ここでの例では、ユーザーを作成し、リポジトリを通じて保存後、同じリポジトリを使って検索を行い、結果をコンソールに出力しています。

## コード全文
```cs
using ConsoleApp.Classes.Models;
using ConsoleApp.Classes.Repositories.Implementations;
using ConsoleApp.Classes.Repositories.Interfaces;
using Microsoft.Extensions.DependencyInjection;

class Program
{
    public static void Main(string[] args)
    {        
        var services = new ServiceCollection();
        ConfigureServices(services);

        using (var serviceProvider = services.BuildServiceProvider())
        {
            var userRepository = serviceProvider.GetRequiredService<IUserRepository>();

            var user = new User(
                new UserId("T001"),
                new UserName("Tom")
            );

            userRepository.Save(user);

            var head = userRepository.Find(user.Name);
            Console.WriteLine(head.Name.Value);
        }

    }

    private static void ConfigureServices(ServiceCollection services)
    {        
        services.AddTransient<IUserRepository, UserRepository>();        
    }
}
```

## まとめ
依存性注入を適切に利用することで、コンポーネント間の結合度を下げ、アプリケーションのテストやメンテナンスを容易にすることが可能です。

## Reference
- [ServiceProviderServiceExtensions.GetRequiredService メソッド](https://learn.microsoft.com/ja-jp/dotnet/api/microsoft.extensions.dependencyinjection.serviceproviderserviceextensions.getrequiredservice?view=dotnet-plat-ext-8.0)
【jQuery】animateメソッドとは

# animateメソッドとは
`animate`メソッドは、jQueryライブラリのアニメーション効果を適用するためのメソッドです。このメソッドを使用すると、要素のスタイルプロパティをアニメーションさせることができます。具体的には、要素の位置、サイズ、透明度、色などのスタイルプロパティを変更して、スムーズなアニメーション効果を実現します。
# 基本的な構文と書き方
```js
$(セレクタ).animate({'プロパティ':'値'}, アニメーション速度);
```
アニメーション速度はミリ秒で指定するか、`slow`や`fast`といった文字列で指定することができます。例えば`font-size`を変更したい場合は以下のように記述します。
```js
//js
$('h1').animate({
    'font-size':'50px'
},2000);
```
また、CSSの値だけでなく、scrollTopなどの値も変更できます。
例えば、スクロールにアニメーションをつける場合は、`$('html, body').animate({'scrollTop': 0}, 時間);`のように指定します。
```js
//js
$('html, body').animate({
    'scrollTop': 0
}, fast);
```
DX推進パスポートが3月10日に発行された！デジタルバッジが2月9日（12時現在）申請可能に。

DX推進パスポートデジタルバッジの完成形が以下のOpen badge Walletのリンク先です。

https://www.openbadge-global.com/ns/portal/openbadge/public/assertions/unAcquired/eFBHbkpMUXJCQUU1MTJ4cFhZa2hKUT09


ITパスポート、G検定、データサイエンティスト検定リテラシーレベルを合格するとデジタルバッジが申請できるようになるようです（３月１０に発行されました！）。デジタルバッジ申請先は以下リンク先です。まだ申請できないみたいです2月9日午前7時時点。→同日12時点で申請可能になりました。

https://www.dilite.jp/passport


個人的な履歴書の書き方

2024年2月　DX推進パスポート（ITパスポート）

と書こうと思います。私はITパスポートしか持っていませんが3つ持っている人は以下のように書けるのではないでしょうか。求人サイトの合計資格が5つまでとなっているところもあるので枠が足りない人には朗報ですね。

2024年2月　DX推進パスポート（ITパスポート、G検定、データサイエンティスト検定リテラシーレベル）

概要
DX推進パスポートは、デジタルリテラシー協議会が発行するデジタルバッジです。DX推進に必要な基本的スキルを証明するもので、3つの国家試験に合格することで取得できます。

ITパスポート試験: ITに関する基礎知識
DS検定 リテラシーレベル: データサイエンス、データエンジニアリング、ビジネスに関する知識
G検定: AIに関する知識
合格者には、1試験合格で「DX推進パスポート1」、2試験合格で「DX推進パスポート2」、3試験全て合格で「DX推進パスポート3」が発行されます。

取得のメリット
個人: スキルや市場価値の証明、就職・転職活動でのアピール材料
企業: 社内のデジタルスキル保有状況の把握、デジタル人材戦略立案
詳細情報
発行開始: 2023年2月9日
発行元: デジタルリテラシー協議会
種類: 3種類
申請方法: 各試験合格者向けに、デジタルリテラシー協議会のウェブサイト上で受付
発行時期: 申請された月の翌月末までに発行
取得方法
各試験の受験申し込みを行い、合格する。
デジタルリテラシー協議会のウェブサイトでDX推進パスポートの申請を行う。
申請手数料を支払う。
申請された月の翌月末までに、DX推進パスポートが発行される。
例
営業職: 顧客とのコミュニケーションにAIを活用し、提案の精度向上
人事職: データ分析に基づいた人材育成・採用
製造職: IoT技術を活用した設備管理
今後の展望
DX推進パスポートは、今後さらに認知度が向上し、DX人材の登竜門として広く活用されることが期待されています。

追加情報
DX推進パスポートは、オープンバッジ（デジタル証明）です。
世界標準の技術標準規格に沿い、株式会社ネットラーニングが運用しています。
DX推進パスポートは、DX人材育成の一助となる取り組みです。
多くの企業・組織が、DX推進パスポートの取得を推奨しています。
【ReactNative】WebViewを使って、Webページからデータを受け取る方法

今回は、Webページの状況によって、Reactnative側で処理を変更したい場合に、データを受け取る必要があるため、詳細を記載していく。

WebViewのライブラリーを用いて、以下のガイドラインを参考に進めていく。

https://github.com/react-native-webview/react-native-webview

https://github.com/react-native-webview/react-native-webview/blob/master/docs/Getting-Started.md

## Webpageからメッセージを送る

### ディレクトリ・ファイル作成
最初にWebページを用意するために、以下のコマンドを入力します。
```
mkdir WebPage
cd WebPage
touch index.html
```

### htmlファイルの変更　　
index.htmlに以下のコードを加えます。

```index.html
<!DOCTYPE html>
<html>

<head>
     <meta charset="UTF-8">　
</head>

<body>
    <!-- ページのコンテンツ -->　省略
    <h1>Webpage</h1>
    <script>
       if ('ReactNativeWebView' in window) {
            const data = { type: 'example', message: 'Webページからメッセージを送っています' };
            window.ReactNativeWebView.postMessage(JSON.stringify(data));
        }
    </script>
</body>

</html>
```

-  Webpageが開かれた環境を判断するため、`'ReactNativeWebView' in window` を使用して、`React Native WebView`が存在するかを確認しています
- 存在する場合、`Webページからメッセージを送っています` という値を設定しています
- `window.ReactNativeWebView.postMessage(JSON.stringify(data))` を使用して、作成したデータをJSON文字列に変換し、WebView内のReact Nativeアプリにメッセージを送信しています

### ローカルでWebサーバーを立ち上げる

Pythonのhttp.serverモジュールを用いて、ローカルで立ち上げる。

```
python3 -m http.server

出力結果
Serving HTTP on :: port 8000 (http://[::]:8000/) ...
```

アクセスすると、

![スクリーンショット 2024-02-07 5.58.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799713/63f9f14d-a73b-5a5d-db3c-222c15ed77f3.png)

現在は文字が表示されているのみですが、ReactnativeでWebViewから、Webpageを表示した際にメッセージを送ることができます。


## Reactnative側の実装

ReactNative側でデータを受け取り、Consoleに表示するまでを行っていく。

### プロジェクトを作成します。
```
npx create-expo-app WebViewMessage
```

### WebViewのパッケージをインストール
```
npx expo install react-native-webview
```

### App.jsの実装

```App.js
import { WebView } from 'react-native-webview';

const App = () => {
  return (
    <WebView
    // ローカルで立ち上げたWebページのURLを指定
  source={{ uri: 'http://localhost:8000/index.html' }} 
  onMessage={(event) => {
    // メッセージを受信したときの処理をここで行います
    const data = JSON.parse(event.nativeEvent.data);
    console.log('Received message from webpage:', data.message);
  }}
/>
  );
}

export default App;
```

- `import { WebView } from 'react-native-webview';`でWebViewコンポーネントをインポートしています

- WebViewコンポーネントを使って、指定したURL（`http://localhost:8000/index.html`）のウェブページを表示しています。このウェブページは、React Nativeアプリ内でWebViewを介して表示されます

- `onMessage`プロパティを使用して、WebView内のウェブページからメッセージを受信するイベントハンドラを設定しています。ウェブページからメッセージが送信されると、このイベントハンドラが呼び出されます

- `onMessage`イベントハンドラ内では、受信したデータをJSON形式にパースし、`console.log`を使用してコンソールにメッセージを出力しています。これにより、ウェブページからのメッセージをアプリ内で処理できます


## 動作確認　

iOSのシミュレーターを立ち上げた際に、

```
iOS Bundling complete 36ms (node_modules/expo/AppEntry.js)
 LOG  Received message from webpage: Webページからメッセージを送っています
```

と出力され、メッセージを受け取ることができました


以上になります。


## 最後に
他にも良い方法があれば、コメントいただけると大変うれしいです。
良かったと思ったら、いいねやTwitterのフォローよろしくお願いいたします！

https://sites.google.com/view/muranakar

個人でアプリを作成しているので、良かったら覗いてみてください！
社内サーバにVS Code remote ssh する手順

1. ローカルPCで秘密鍵を作成
    1. ex) `ssh-keygen -t rsa -b 4096`
    1. ファイル名は適当につける
        1. 今回は shanai-server とする
1. .ssh/config にホストを追加
    1. ex)
    ```
    Host shanai-server
      HostName 192.168.2.10
      ForwardX11 yes
      User hoge
      IdentityFile ~/.ssh/shanai-server_rsa
    ```
1. 社内サーバの.sshにauthorized_keysを追加
    1. ローカルで作成した公開鍵をコピーして、authorized_keys に追記
1. VS Code の Remote Explorer に .ssh/config の中身が表示されるので、そこから接続する
コマンドのインストール状況を確認するバッチファイル

# 概要
任意のコマンドのインストール状況を確認するバッチファイルのサンプルです。
インストール済みならバージョン情報を表示。
存在しないコマンドは「NOT INSTALLED」を表示します。

# 実行結果
実行結果です。
コマンドのjava mvn quasar npm awsが入っています。  
コマンドのnot_found(架空のコマンド)が入っていません。  
![スクリーンショット 2024-02-09 021500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1618333/aaec8cda-7cce-21c2-2a21-04ad1b7acee7.png)
注意：コード表示の問題で制御文字が消えてしまうため文字の色を変えたい人は[色を変えたい人へ。](#色が変えたい人へ。)を確認してください。

```Batchfile
@echo off
setlocal enabledelayedexpansion

echo [94m----------------------------[0m
echo [94mVerify command installation.[0m
echo [94m----------------------------[0m

REM 確認するコマンドのリスト
set "commands=java mvn quasar npm aws not_found"

REM 各コマンドのバージョン情報を取得するためのオプション
set "version_options=java:-version mvn:-v quasar:--version npm:-v aws:--version not_found:--version"

REM 確認するコマンドが存在するかをチェック
for %%i in (%commands%) do (
    set "version_option="
    for %%v in (%version_options%) do (
        for /f "tokens=1,2 delims=:" %%a in ("%%v") do (
            if "%%a"=="%%i" set "version_option=%%b"
        )
    )

    where "%%i" >nul 2>&1
    if not errorlevel 1 (
        echo [32mINSTALLED    %%i[0m

        set "version_info="
        for /f "delims=" %%x in ('%%i !version_option! 2^>^&1') do (
            if "!version_info!"=="" (
                echo              %%x
            ) else (
                echo              %%x
            )
        )
    ) else (
        echo [91m[1m[7mNOT INSTALLED %%i[0m
    )
)

cmd /k echo end file.
```

# 他のコマンドの追加方法
commandsに調べたいコマンドを追加します。
version_optionsに調べたいコマンドのVersionチェックオプションを追加します。
例えばこの例だとjavaはjava -version、mvnはmvn -vが実行されます。
```Batchfile
REM 確認するコマンドのリスト
set "commands=java mvn quasar npm aws not_found"

REM 各コマンドのバージョン情報を取得するためのオプション
set "version_options=java:-version mvn:-v quasar:--version npm:-v aws:--version not_found:--version"
```

# 色を変えたい人へ。
このコードは文字の色を青色にして---を出力、文字の色を白に戻す処理です。
本当は[94mの前にEscコード(\x1b)が入っていますがコード表示の仕様でEscコードが消えてしまいます。
```Batchfile
echo [94m----------------------------[0m
```
本当はこんな感じで [94m の前にEscコード(\x1b)がいる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1618333/93ec614c-6657-26d2-f26b-d7b242e11357.png)

Gitにも置いてあるのでここから取るか、サクラエディタか何かの正規表現で置き換えてください。
>https://github.com/new-sankaku/command-check-bat-file

サクラエディタでの変更は以下参照。
>https://qiita.com/kurooolong/items/d31917e28645115d705a
開発環境が検索エンジンに誤って表示される問題とその解決策

## 事象

開発環境と本番環境を区別して構築しているにもかかわらず、`Google`などの検索エンジンに開発環境のURLが意図せず表示されてしまう問題が発生しました。この状況は、開発中の機能が外部に不用意に公開されることやセキュリティ上の問題を引き起こすリスクを持ちます。原因としては、`Webクローラー`が開発環境のURLを誤って`インデックス`してしまっていることが挙げられます。ここでは、`Next.js（Pages Router）`を使用したプロジェクトでこの問題に対処する方法をご紹介します。

## 対処法（実装）
サイトページの`head`タグ内に`noindex`メタタグを設定することで、ウェブクローラにインデックス登録されないよう指示することができます。以下は、`Next.js`の`_app.tsx`ファイルでの実装例です。ここでは、環境変数`FRONTEND_ENDPOINT`を用いて開発環境かどうかを判断し、開発環境の場合にのみ`noindex`を追加します。環境変数`FRONTEND_ENDPOINT`は、開発環境では開発用のドメインを、本番環境では本番用のドメインを含むように設定しております。

```tsx:pages/_app.tsx
import type { AppProps } from 'next/app';
import Head from 'next/head';

const basePath = process.env.FRONTEND_ENDPOINT;

export default function MyApp({ Component, pageProps }: AppProps) {
  const isDevEnvironment = basePath?.includes("dev");
  return (
    <>
      <Head>
        {isDevEnvironment && <meta name="robots" content="noindex" />}
      </Head>
      <Component {...pageProps} />
    </>
  );
}
```

## 対処法（Google Search Consoleの使用）

実装をデプロイした後、`Google`によるドメインのクロールをリクエストするために`Google Search Console`を開いてドメインを入力します。そのあとご利用のドメイン名プロバイダにログインし、発行される`TXTレコード`をDNS設定に追加します。  

`Google Search Console`にログインし、検査結果ページでデータが反映されたら`[インデックス登録をリクエスト]`をクリックします。そのあと`Google`の検索窓に`site:https://あなたのドメイン名`と入力して検索し、開発環境のURLが検索結果に表示されなければOKです。私の場合、変更がクローリングされて反映されるまで3~4週間はかかりました。

## 参照

https://developers.google.com/search/docs/crawling-indexing/block-indexing?hl=ja

自らの備忘録のために投稿してますが、なにかお役に立てましたら幸いです！:clap:
また、なにか間違ってましたらご指摘いただけますと幸いです！:pray:
自作キーボード入門にErgo68を購入したのでレポ(後半)

[自作キーボード入門にErgo68を購入したのでレポ(前半)](https://qiita.com/ikentoh/items/9d5b05ee68c67c4642ec)の続きです。

とはいえ公式ドキュメントを見ればもうつまづくところはほとんどないはずなので、主にdvorak配列利用者を対象とした小技をまとめたような内容です。


# 達成したいこと
- dvorak-qwertyで入力できること
    - アルファベットと記号はdvorak
    - 修飾キーを押下中のみqwertyに切り替わる
        - qwertyにチューニングされたショートカット配列の恩恵を受けられる
    - 日本語入力がdvorakJPで行えること
- ゲームやblenderなどのために、まるごとqwertyにスイッチできること
- カーソルキーの操作をラクに行えること

現在はwinではDvorakJ、macではKarabinerを使ってソフトウェアでこれを実現しているんですが、ハードでやれるならハードでやりたいと思っていました。
特にDvorakJは動作が不安定で、dvorak利用中に突然qwertyに切り替わり再起動までうんともすんとも言わなくなる等の現象が多発しておりストレスになっていました。

# 設計

```plantuml
dvorak -> qwerty: 修飾キー押下中のみ
dvorak <- qwerty: 修飾キーを離す

dvorak -> qwerty: トグル用キー押下
dvorak <- qwerty: トグル用キー押下

dvorak -> カーソル操作用レイヤー: 任意キー押下中のみ
dvorak <- カーソル操作用レイヤー: 任意キーを離す
```

こう書くとレイヤーは3つあれば十分そうですが、remapでの設定では以下の制約によりいくつかを諦めなければいけませんでした。

- 設定できるレイヤーは4つまで
- MOによるレイヤー切替時、押下中のキーにはキーを割り振ることができないため、修飾キー同士でレイヤーを共通化することができない

https://remap-keys.app/configure
さっぱりした設定を書くならものすごく使いやすいんですけど、ちょっとだけ勿体ない。

他にもキーリマップの方法はあるものの、一旦remapだけで完結することを目指して以下の形を目指すことにしました。
検討の結果、自分自身ではaltやwinなどのショートカットを使う機会がほとんどないので、ctrl(cmd)のみ対応することにしました。
なにかあればまるごとqwertyにトグルして対応すればOKという判断です。

```plantuml
layer0.dvorak -> layer1.ctrlとqwerty: ctrlキー押下中のみ
layer0.dvorak <- layer1.ctrlとqwerty: ctrlキーを離す

layer0.dvorak -> layer2.qwerty: トグル用キー押下
layer0.dvorak <- layer2.qwerty: トグル用キー押下

layer0.dvorak -> layer3.カーソル操作用レイヤー: 任意キー押下中のみ
layer0.dvorak <- layer3.カーソル操作用レイヤー: 任意キーを離す
```

# できたもの
歴史的経緯でlayer2とlayer3が逆転していますが気にせず。

▼layer0 dvorak
F23/F24は後述
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529606/1b99b137-83c0-d1d7-13aa-2f8885bb1545.png)

▼layer1 ctrl + qwerty
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529606/548c6c67-29f5-94b0-c7fc-060033d3bde8.png)

▼layer2 カーソル操作など
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529606/64566f8b-d9d5-41ce-7e62-8373d013be01.png)

▼layer3 qwerty
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529606/1a6a8142-fba3-0ee6-82de-546103871637.png)

## キーボードをUS配列として認識させる
このままだと「`」が入力できず、プログラミングにおいて不便を被ることになります。
なので以下の手順でUS配列として認識させました。

▼日本語の右側にある「…」をクリック -> 言語のオプション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529606/9fc49e8d-f8d8-1a10-66e9-0203a16fd93f.png)

▼レイアウトを変更する -> 英語キーボードを選択
※接続するすべてのキーボードがUS配列扱いになることに注意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529606/418e49c8-429b-aada-e93a-3ceabd356796.png)


## 日本語/英語の入力切り替え

当初は変換/無変換に割り当てていたんですが、US配列として認識させると変換/無変換を認識しなくなるので、ファンクションキーの端っこを間借りすることにしました。

▼「あ」を右クリック -> プロパティ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529606/72ac420c-ba8c-2303-45e0-c02574eb7f94.png)

▼一般 -> キー設定の選択 -> 編集
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529606/2d73860d-ef89-6ae3-5d12-49723195458a.png)

▼すべての状態でF23をIME無効化、F24をIME有効化に設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/529606/9f753e25-0513-d24b-f912-cb284625d32d.png)

F13~F24は物理キーとして存在するキーボードはほとんど無いはずなので、事実上こういうソフトウェア上のキーアサインを自由に中継するのに使えます。便利。


# TODO
おおむねやりたいことは達成できたんですが、修飾キー周りが万全ではないので、もっとリッチなキーマップツールを使って再挑戦する予定です。
[Unity:Android] VideoPlayerで指定したURLの動画を再生する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/ef036fe6-c10b-0aa5-a852-a414e62f22a2.png)

VideoPlayerでURL指定をしても再生されない場合、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/eec814c8-fbef-724b-0a22-fa517b4a243a.png)

CustomMainManufestにチェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/8453d47b-15b9-5a1d-c29d-61223246ce74.png)

AndroidManifest.xmlが生成される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/90d7e51a-2339-6bae-8e21-b27b2b4dc16c.png)

```<uses-permission android:name="android.permission.INTERNET" />```
```android:usesCleartextTraffic="true"```
を追加
```
<?xml version="1.0" encoding="utf-8"?>
<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
	<uses-permission android:name="android.permission.INTERNET" />
	<application>
        <!--Used when Application Entry is set to Activity, otherwise remove this activity block-->
        <activity android:name="com.unity3d.player.UnityPlayerActivity"
				  android:usesCleartextTraffic="true"
                  android:theme="@style/UnityThemeSelector">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>
        <!--Used when Application Entry is set to GameActivity, otherwise remove this activity block-->
        <activity android:name="com.unity3d.player.UnityPlayerGameActivity"
                  android:theme="@style/BaseUnityGameActivityTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
            <meta-data android:name="android.app.lib_name" android:value="game" />
        </activity>
    </application>
</manifest>

```

buildして確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/a29de692-acc1-93c5-8d97-992952c212b3.png)
BlueSkyの機能について整理してまいりましょう

> BlueSkyの機能について整理してまいりましょう
・ホーム
・検索
・フィード
・通知
・リスト
・モデレーション
・プロフィール
・設定
・新しい投稿

上記の機能について2024年２月９日現在でどのような機能があるか具体的な例を挙げて説明してください

2024年2月9日現在、BlueSkyのプラットフォームに実装されている機能について、以下に具体的な例を挙げて説明いたします。BlueSkyは、オープンソースで分散型のソーシャルネットワークを目指しており、ユーザーがよりコントロールを持てるよう設計されています。

1. ホーム
ホームは、ユーザーがフォローしているアカウントからの最新の投稿をタイムライン形式で表示するセクションです。このフィードには、テキスト、画像、ビデオなど、さまざまな形式のコンテンツが含まれます。

2. 検索
検索機能では、特定のキーワードやハッシュタグ、ユーザー名でコンテンツや他のユーザーを検索できます。この機能は、新しい興味やトレンド、人々を発見するのに役立ちます。

3. フィード
フィードは、ユーザーの興味や活動に基づいてカスタマイズされたコンテンツを提供します。これには、フォローしているアカウントの投稿のほか、おすすめのコンテンツやトレンドが含まれることがあります。

4. 通知
通知機能を通じて、他のユーザーからのインタラクション（いいね、リポスト、コメントなど）や新しいフォロワーに関する情報を受け取ります。また、重要なアップデートやお知らせもここで確認できます。

5. リスト
リスト機能では、ユーザーが特定のトピックや関心ごとに基づいてユーザーやコンテンツを分類し、オーガナイズすることができます。これにより、特定の分野に関する情報を効率的に追跡することが可能になります。

6. モデレーション
モデレーション機能は、コミュニティや個々のフィード内でのコンテンツの質を保つために重要です。ユーザーは、不適切なコンテンツを報告したり、自分の投稿に対するコメントを管理したりすることができます。

7. プロフィール
プロフィールセクションでは、ユーザーが自己紹介文、プロフィール写真、背景画像、公開しているコンテンツなど、自分自身に関する情報をカスタマイズし、表示することができます。

8. 設定
設定メニューでは、プライバシー、通知、アカウントのセキュリティ設定など、プラットフォーム内でのユーザー体験をカスタマイズするためのオプションが提供されます。

9. 新しい投稿
新しい投稿機能を使用して、テキスト、画像、ビデオなどの形式でコンテンツを作成し、共有することができます。この機能は、アイデアや体験を即座に世界と共有するための主要な手段です。

BlueSkyは、分散型ソーシャルネットワークとして、ユーザーがより多くの自由とコントロールを持てるように設計されています。これらの機能を通じて、ユーザーは情報を共有し、コミュニティを形成し、オンラインでのインタラクションを楽しむことができます。

https://bsky.app/profile/bsky.app/post/3kkv3clm3su2h

> One million new users since we opened Bluesky yesterday!
Welcome to Bluesky!!! 🎉

和訳

> 昨日Blueskyを開設してから、100万人の新規ユーザーが増えました！
Blueskyへようこそ!!! 🎉 

現在、1,000,179人の方々が利用されているようです。
X：元Twiiterの機能について整理してまいりましょう

> X：元Twiiterの機能について整理してまいりましょう
・ホーム
・話題を検索
・通知
・メッセージ
・リスト
・ブックマーク
・コミュニティ
・プレミアム
・もっとみる

上記の機能について2024年２月９日現在でどのような機能があるか具体的な例を挙げて説明してください
X（元Twitter）の機能について、2024年2月9日現在の情報を基に整理いたします。Xは、ユーザーが情報を共有し、世界中の出来事について意見を交わすことができるプラットフォームです。以下に、主要な機能について詳細を記します。

## 1. ホーム
ホームは、フォローしているアカウントからのツイートやおすすめのコンテンツがタイムライン形式で表示される場所です。ユーザーはこのセクションで、最新のニュース、トレンド、友人や興味のあるアカウントの更新情報を見ることができます。


## 2. 話題を検索
「話題を検索」機能を使用すると、特定のハッシュタグやキーワード、ユーザー名でツイートを検索できます。また、トレンドセクションでは、現在最も話題になっているトピックやハッシュタグを確認することができます。


## 3. 通知
通知では、他のユーザーがあなたのツイートに対して行ったアクション（いいね、リツイート、コメント）や、新たにフォローされた際の通知を受け取ります。また、あなたに関連する重要なアクティビティやおすすめのツイートもここで確認できます。


## 4. メッセージ
いわゆるダイレクトメッセージ（DM）機能を通じて、プライベートに他のユーザーとメッセージのやり取りをすることができます。グループメッセージ機能もあり、複数のユーザーと一つの会話を持つことが可能です。

## 5. リスト
リスト機能では、興味のあるトピックやグループごとにユーザーを整理し、カスタマイズされたフィードを作成することができます。この機能を使えば、特定の分野や人々からのツイートのみを集中して閲覧することが可能になります。

## 6. ブックマーク
気に入ったツイートや後で読み返したいツイートを保存しておくための機能です。ブックマークしたツイートは、プロフィールのブックマークセクションからいつでもアクセスできます。

## 7. コミュニティ
特定の興味やトピックに焦点を当てたユーザーグループを作成・参加するための機能です。コミュニティ内では、そのトピックに関連する投稿を共有したり、ディスカッションを行ったりすることができます。

## 8. プレミアム
有料サブスクリプションサービスで、広告なしでの閲覧、高度な分析ツールへのアクセス、特別なカスタマイズオプションなど、追加の機能や特典を提供します。

## 9. もっとみる
その他の機能や設定にアクセスするためのセクションです。アカウント設定、プライバシー設定、ヘルプセンターへのリンクなどが含まれています。

Xの機能は、ユーザーが情報を発信し、交流するための多様な方法を提供しています。これらの機能を通じて、ユーザーは世界中の人々とつながり、様々なトピックについて意見を交わすことができます。
p5.toio を使ったシンプルな p5.js のプログラム：接続中の toio の数の表示や move()、rotate() などによる走行

過去に以下の記事を書いたことがあったり、その後、モノ作り系の展示イベント用の作品作りに利用している [p5.toio](https://tetunori.github.io/p5.toio/) の話です。

●toio をブラウザ上から簡単制御！ p5.js用ライブラリの p5.toio の始め方（p5.js Web Editor上からの利用） - Qiita
　https://qiita.com/youtoy/items/0544183ed0f0dba65f51

上記の記事ではセットアップ方法と、以下の動作をさせるシンプルなプログラムを掲載していました。

- toio との接続
- toio で音を鳴らす
- toio をその場で回転させる（モーターの制御、move() を利用）
- 上記の回転動作を停止させるモーターの停止

## 今回の内容
今回は、以下の内容を試してみます。

- toio との接続
- 接続中の toio の数をキャンバス上に表示
- move() を使い toio がある円周上を走るような動き
   - 円の半径を異なる 2種類の大きさにする
- rotate() を使い toio をその場で回転させる
- stop() で上記のモーターを使った動作を停止させる

なお、前回の記事で書いていたセットアップ周りの話は省略します。

### プログラムの内容
それでは、今回作ったプログラムの話です。

今回のプログラムの内容は、以下のとおりです。

```javascript
const gCubes = [];

function setup() {
  createCanvas(640, 480);
}

function draw() {
  background(0);

  drawToioNum();
}

function drawToioNum() {
  fill(255);
  textSize(32);
  textAlign(LEFT, CENTER);
  text(`toioの接続数： ${gCubes.length}`, width * 0.1, height * 0.4);
}

function keyPressed() {
  if (key === "f") {
    P5tCube.connectNewP5tCube().then((cube) => gCubes.push(cube));
  } else if (key === "1" || key === "2") {
    const rate = key === "1" ? 0.3 : 0.6;
    const speed = 80;
    moveCube(rate, speed);
  } else if (key === "3") {
    rotateCube(60);
  } else if (key === "a") {
    stopCube();
  }
}

function moveCube(rate, speed) {
  console.log("move");
  gCubes[0]?.move(speed, speed * rate, 0);
}

function rotateCube(speed) {
  console.log("rotate");
  gCubes[0]?.rotate(speed, 0);
}

function stopCube() {
  console.log("stop");
  gCubes[0]?.stop();
}
```

キーの押下時に、以下の動作をさせるようにします。

- f： toio との接続
- 1、2： toio がある円周上を走るような動き（円の半径は 2種類）
- 3： toio をその場で回転させる
- a： toio のモーターを静止させる

この処理を動作させた時の様子は、以下のとおりです。

<iframe width="560" height="315" src="https://www.youtube.com/embed/BVPRh6H7jzA?si=ZY0lsWCfeX3UrpbQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

また、toio の接続台数をキャンバスに表示する処理を入れているので、キャンバス上の表示は toio が接続されているかどうかによって、以下のように変化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/23bad661-57f0-dc36-c5c3-1328ffe3d4e5.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/771de025-d47c-40b5-2696-e2e28fb4c2c1.png)

## 公式ドキュメントの関連部分
以下は、公式ドキュメントの記載の中で、今回用いた処理が書かれた部分のリンクです。

●P5tCube | p5.toio ＞ move
　https://tetunori.github.io/p5.toio/docs/cube/classes/p5tcube#move

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/5a539fa5-969c-329e-0372-712e12658d87.png)

●P5tCube | p5.toio ＞ rotate
　https://tetunori.github.io/p5.toio/docs/cube/classes/p5tcube#rotate

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/7952a440-40e9-558b-50be-ec4fdfd8a03f.png)

●P5tCube | p5.toio ＞ stop
　https://tetunori.github.io/p5.toio/docs/cube/classes/p5tcube#stop

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/8b3177a0-42bb-26ba-634c-7713b3b33dee.png)
【実践編】Swiftの教科書というアプリ開発｜Sp1スプリントプランニング

## スプリントプランニング
やることリスト
- [x] スプリントゴールの決定
- [x] スプリントバックログの作成
- [x] チームでの作業の見積もり

### スプリントゴールの決定
スプリントゴールとは、そのスプリントで達成するべき具体的な目標を指します。この場合、スプリントゴールは「Swiftの教科書アプリの初期バージョンの完成」です。これは、このスプリントで完成させることを目指すアプリの基本的なバージョンを示しています。
そして本スプリント内でできることで言うと、、、Sp1でどこまでできるのかを査定する

### スプリントバックログの作成
- スプリントバックログとは、スプリントで達成すべきゴールに向けて実施するタスクのリストを指します。この場合、スプリントバックログには以下のタスクが含まれます：
    1. - [x] 基本的な構文解説ページの作成
    2. - [ ] クイズ機能の実装
    3. - [ ] 演習問題ページの作成
    4. - [ ] 進捗管理機能の設計
    5. - [ ] ブックマーク機能の実装
    6. - [ ] デザインの最終調整
    7. - [ ] テストと品質確認
    8. - [ ] ドキュメンテーションの作成
    9. - [ ] リリース準備
    10. - [ ] 次のスプリントの計画

### チームでの作業の見積もり
- スプリント期間中に各タスクの完成に必要な作業時間とリソースを見積もり、スプリント期間内に実装可能な範囲を確認するプロセスを指します。具体的な見積もりは、チームの経験と能力、作業の複雑さなどに基づいて決定されます。この見積もりにより、スプリントの期間と作業量が適切にバランスを保つことができ、オーバーワークを防ぎ、品質を維持することが可能になります。
またチームで行う場合は、それぞれのチームの中で誰が担当するかも決めてそれぞれの担当者が見積りを元に調整を行いストーリーポイントを見積もっておきます。

具体的にこれまでのタスクの見積りを行なっていきます
### タスク見積もり詳細

1. **基本的な構文解説ページの作成**：約20時間 sp10
 - Swift言語の基本的な構文の研究と説明文の作成、サンプルコードの作成などが含まれます。
2. **クイズ機能の実装**：約25時間 sp13
 - クイズの問題文と選択肢を作成し、ユーザーの回答を受け付けるロジックの開発、ユーザーインターフェースの設計などが含まれます。
3. **演習問題ページの作成**：約15時間 sp8
 - 演習問題の作成と説明文の作成、ユーザーがコードを入力して回答できる機能の開発などが含まれます。
4. **進捗管理機能の設計**：約10時間 sp5
 - ユーザーの学習進捗を管理するデータモデルの設計と進捗管理画面のユーザーインターフェースの設計が含まれます。
5. **ブックマーク機能の実装**：約15時間 sp8
 - ユーザーが特定のページやコンテンツをブックマークできる機能の開発と、ブックマークしたコンテンツを表示する画面の設計が含まれます。
6. **デザインの最終調整**：約10時間 sp5
 - アプリの全体的なデザインの見直しと修正、ユーザーフィードバックを反映しての改善などが含まれます。
7. **テストと品質確認**：約20時間 sp10
 - 実装されたすべての機能のテストとバグの特定、修正、アプリの全体的な品質確認と最終調整が含まれます。
8. **ドキュメンテーションの作成**：約15時間 sp8
 - アプリの使用方法や機能の説明を含むドキュメンテーションの作成、ユーザーガイドやFAQの作成などが含まれます。
9. **リリース準備**：約10時間 sp5
 - App Storeへの提出準備、プロモーションの計画作成などが含まれます。
10. **次のスプリントの計画**：約5時間 sp2
 - 次のスプリントで実装する機能や改善点の決定、優先順位の決定などが含まれます。

※以上の見積もりは、一般的な作業時間を基にしており、具体的なプロジェクトの要件やチームの経験により変動する可能性があります。

## お問い合せ
プログラミングラボ：DMまで

https://twitter.com/PLab2020
WinFormsの備忘録 

今まで業務で定期的に使ってたwinForm環境をしばらく離れることになりそうなのでメモを残しておきます。
現場で見たことないけど知ってると便利な機能たちです。もっといっぱいあったはずだけど思い出そうとすると意外と出てこなかった…
個人的にWinFormsあんまり好きじゃないのでもう２度とこのメモを見なくて良いほうが嬉しい。業務でBlazorとか使いたいなあ

+ タブオーダー
コントロールをクリックすると順番にTabIndexを設定してくれる機能。
1つ1つクリックしながらTabIndexを設定しなくて良くなる。
表示→タブオーダーから表示できる

+ ドキュメントアウトライン
同じ場所に複数コントロールを重ねて配置してEnableで制御している画面とかで便利。
Ctrl+Alt+Tで表示できる

+ TransactionScope
トランザクションを自力で制御しなくて良くなる。
これを知らないころ複数のファイルアクセスとDBアクセスを一緒にしてトランザクションの制御がめんどいことになった記憶がある。

+ ComboBox.Format、DataGridView.CellFormattingイベント
データバインドとセットでコンボボックスやデータグリッドビューの表示を変えられる。
データセットからコントロールにデータ詰めてSelectIndexからデータセットに戻す作業をしなくて良くなる。

+ ErrorProvider
現場で使われてるの見たことないWinForms備え付けのバリデーション。
そんなに好きでもないけど自力バリデーションは実装がひどくなりがちなのでできれば使いたい。

ほかに思い出したら追記していきます。
[TypeScript] Expressをやってみる（10分で？）

# はじめに
typescriptでAPIを作ってみたいなぁと思い、expressを始めてみました。そこで、めっちゃ初期のところは簡単だったので、書いてみる

# Step1: フォルダの作成

最初に、プロジェクト用の新しいフォルダを作成します。任意の名前をつけてください。
今回は`express-ts-app` を使用します。

```bash: bash
mkdir express-ts-app
cd express-ts-app
```

# Step2: npmプロジェクトの初期化

プロジェクトフォルダ内で、以下のコマンドを実行してnpmプロジェクトを初期化します。
これにより、`package.json`ファイルが作成されます。

```bash: bash
npm init -y
```

ちなみにこのときの `-y`は、**yes**の略です。すべての質問に自動的に「はい」と回答します。`npm init`だけを実行した場合には、プロジェクト名、バージョン、説明、エントリポイント、テストコマンド、gitリポジトリ、キーワード、ライセンスなどについて、入力や回答を求められますが、`-y`オプションによって、デフォルトの`package.json`ファイルを生成します。

# 3. TypeScriptとExpressのインストール

ExpressとTypeScript、およびTypeScriptの型定義ファイルをインストールします。

```bash: bash
npm install express
npm install --save-dev typescript @types/express @types/node
```

# 4. TypeScriptの設定ファイルの作成

プロジェクトフォルダの中に`tsconfig.json`を作成します。以下のような形で十分だと思います。

```json
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "rootDir": "./src",
    "outDir": "./dist",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}
```

# 5. ソースファイルのディレクトリ構造

`src` ディレクトリを作成し、TypeScriptで書かれたソースファイルをこのディレクトリに配置します。

```bash
mkdir src
```

例として、`src`ディレクトリ内に`index.ts`という名前のファイルを作成し、以下の内容を記述します。

```typescript
import express from 'express';

const app = express();
const port = 3000;

app.get('/', (req, res) => {
  res.send('Hello World!');
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});
```

### 6. ビルドスクリプトの設定

`package.json`ファイルにビルドスクリプトを追加して、TypeScriptコードをJavaScriptにコンパイルできるようにします。

```json
"scripts": {
  "build": "tsc",
  "start": "node dist/index.js"
}
```

### 7. アプリケーションのビルドと実行

以下のコマンドでアプリケーションをビルドします。

```bash
npm run build
```

ビルドが完了したら、アプリケーションを以下のコマンドで起動します。

```bash
npm start
```

これで、ブラウザから`http://localhost:3000`にアクセスすると、"Hello World!"が表示されます。

以上で、TypeScriptを使用したExpress.jsプロジェクトの基本的なセットアップが完了しました。これを基に、さらに機能を追加していくことができます。


いえーい！！

続きもまた別の記事で書きます！！
テストの心理学

[徹底攻略 JSTQB Foundation教科書&問題集 シラバス2018対応](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-JSTQB-Foundation%E6%95%99%E7%A7%91%E6%9B%B8-%E5%95%8F%E9%A1%8C%E9%9B%86-%E3%82%B7%E3%83%A9%E3%83%90%E3%82%B92018%E5%AF%BE%E5%BF%9C/dp/4295017671/ref=asc_df_4295017671/?tag=jpgo-22&linkCode=df0&hvadid=654833321247&hvpos=&hvnetw=g&hvrand=7317531869461544354&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009293&hvtargid=pla-2199686852302&psc=1&mcid=140f9d5d8ea8321d9cdbe1b981b50a4c&th=1&psc=1)を勉強しているので、自分のメモとしてまとめています。第６弾。

# 人の心理とテスト
## 人の心理がテストに及ぼす影響
#### 確証バイアス
確証バイアスとは、自分の思い込みによって正しい判断ができなくなることの総称である。
> 後知恵バイアスとは、ある事が起こった後に「そうなると思っていたんだ」と自分は予想していたと思い込んでしまう認知バイアス。
正常性バイアスとは、詐欺や災害などの異常な事態に直面した際に「自分は大丈夫だ」と異常な事態を過小評価しがちな傾向のこと。
確証バイアスは認知バイアスの一つである。

テスト担当者が要件レビューなどで欠陥を見つけることや、操作確認中に故障を見つけることが、プロダクトの開発者に対する非難と解釈される事がある。
開発担当者は「コードは正しい」と思いこみたい確証バイアスがあるため、それが正しくないという指摘を受け入れがたく感じてしまう。開発担当者だけでなく、プロダクトオーナーやアナリスト、設計担当者もそれぞれの立場で情報を解釈する傾向がある。
そのため、テスト担当者は建設的な方法で欠陥や故障に関する情報を伝え、メンバーそれぞれの緊張を緩和する事が大切である。
#### 動的テスト・静的テスト
ソフトウェアを動作させて故障を見つけ、その原因を探って欠陥を見つけることを**動的テスト**、動作させずに直接欠陥を見つけることを**静的テスト**と呼ぶ。
要件のレビューなどは静的テストにあたる。
## コミュニケーションを適切に行う方法
### 対決ではなく、協調姿勢で始める
チーム全員のゴールが高品質のシステム構築であることをみんなで共有する。
### テストのメリットを共有し、理解してもらう
欠陥情報が作業成果物の品質向上や開発担当者のスキルアップにつながることを理解してもらう。
コストや納期のために、テストを時間と経費がかかるものと捉えられがちだが、テストで欠陥を発見、検出、修正することで、むしろ時間と経費を抑えて品質リスクを低減できることを理解してもらう。
### 中立な立場で事実に焦点を当てて伝える
テスト結果や他の発見事項は、中立な立場で事実に焦点を当てて伝える。
担当者を非難することなく、客観的かつ事実に基づいたレポートを書いたり、発見事項をレビューしたりする。
### 他人の気持ちを理解する
提出したテスト情報に対して、相手が否定的に反応した理由を理解するようにする。

# テスト担当者と開発担当者のマインドセット
両者はそもそもの目的が違うため、考え方も異なる。
| テスト担当者 | 開発担当者 |
|:-:|:-:|
| プロダクトの検証と妥当性の確認、リリース前の欠陥の検出etc...  |プロダクトを設計・開発すること|
## マインドセットの違い
両者のマインドセットをうまく組み合わせることで、より高いレベルのプロダクト品質を実現できる。
シラバスでは、テスト担当者のマインドセットとして以下を挙げる。
- 好奇心
- プロとしての悲観的な考え
- 批判的な視点
- 細部まで見逃さない注意力
- 建設的コミュニケーションを保つモチベーション
- 経験を積むに従って成長し成熟する傾向がある
など。

開発者のマインドセットとしては、以下を挙げる。
- 解決策に問題があるかを考えるよりも、解決策の設計と構築により大きな関心がある
- 確証バイアスが、自分自身ノオ化したエラーに気づくことを困難にする
など。

## マインドセットの違いを理解して適切に判断する。
開発担当者とテスト担当者のマインドセットは異なるため、特に大規模で複雑、または、セーフティクリティカル(絶対にエラーが起こってはならない)なシステムにおいては、開発担当者とは別に独立したテスト担当者がテスト活動を行うことが多い。

# 次回
https://qiita.com/1225/items/0ceef2c866bad3e9a604
【実践編】Swiftの教科書というアプリ｜アプリの機能と構造の計画＠開発はアジャイル開発で実行する

> Swiftの教科書というアプリ

https://qiita.com/sunstripe2011/items/7bf94fdf5bb267dcf566

### アプリの機能と構造の計画
アプリにどのような機能を実装するかを決定します。例えば、Swift言語の基本的な構文や機能の解説、コードのサンプル、クイズや演習問題など。

アプリの機能と構造の計画を決定してください。
また、開発はアジャイル開発で実行していきます。
１スプリント目で行うことを　スプリントプランニングしてください。
また、プロダクトバックログのリストを作成してください

#### アプリの機能と構造の計画

### 基本的な構文解説

Swift言語の基本的な構文や文法を解説するページを用意します。例えば、変数の宣言方法、制御構文（if文、for文）、関数の定義などを説明します。

### コードのサンプル

各構文や機能に関連するサンプルコードを提供します。これにより、ユーザーは実際のコードを見ながら学習できます。

https://qiita.com/sunstripe2011/items/73967121460fa70b2c6e

### クイズ機能

ユーザーが学習内容を確認するためのクイズ機能を実装します。例えば、複数選択肢から正しいコードを選ぶ問題や、コードの出力結果を予測する問題などを提供します。

### 演習問題

ユーザーが実際にコードを書いて学習を深めるための演習問題を用意します。これにより、ユーザーは理論だけでなく実践的なスキルも身につけることができます。

### 進捗管理機能

ユーザーが学習した内容やクイズの結果、演習問題の進捗状況などを確認できる機能を提供します。これにより、ユーザーは自身の学習状況を把握し、目標に向かって進むことができます。

### ブックマーク機能

ユーザーが重要なページやコンテンツをブックマークしておくことができる機能を提供します。これにより、ユーザーは必要な情報を素早くアクセスすることができます。

# スプリントプランニング（１スプリント目）

### 基本的な構文解説ページの作成

- [x] [Swift言語の基本的な構文を解説するページを作成する。](https://qiita.com/sunstripe2011/items/73967121460fa70b2c6e) 2024/02/08
- [x] [各構文の説明とサンプルコードを追加する。](https://qiita.com/sunstripe2011/items/73967121460fa70b2c6e) 2024/02/08

### クイズ機能の実装

- [ ] クイズ機能のユーザーインターフェースを設計する。
- [ ] クイズの問題文と選択肢を表示し、ユーザーの回答を受け付ける機能を実装する。

### 演習問題ページの作成

- [ ] ユーザーが演習問題に取り組むためのページを作成する。
- [ ] 演習問題の説明文とコード入力欄を提供する。

### 進捗管理機能の設計

- [ ] ユーザーの学習進捗を管理するためのデータモデルを設計する。
- [ ] 進捗管理画面のユーザーインターフェースを設計する。

### ブックマーク機能の実装

- [ ] ユーザーがページやコンテンツをブックマークできる機能を実装します。
- [ ] ブックマークしたコンテンツを表示するための画面を作成します。

### デザインの最終調整

- [ ] アプリのデザインを最終調整し、使いやすさや視覚的な魅力を向上させます。
- [ ] ユーザーのフィードバックを反映して、必要な修正を行います。

### テストと品質確認

- [ ] 実装された機能をテストし、バグや問題を特定して修正します。
- [ ] アプリの品質を確認し、ユーザー体験を向上させるための最終調整を行います。

### ドキュメンテーションの作成

- [ ] アプリの使用方法や機能の説明を含むドキュメンテーションを作成します。
- [ ] ユーザーガイドやFAQなどを作成して、ユーザーがアプリを効果的に利用できるようにします。

### リリース準備

- [ ] アプリのリリースに向けて準備を行います。これには、App Storeへの提出やプロモーションの計画などが含まれます。

### 次のスプリントの計画

- [ ] 次のスプリントで実装する機能や改善点を決定し、計画を立てます。
- [ ] ユーザーからのフィードバックやアプリの利用状況を考慮して、優先順位を決定します。


以上が、初期のスプリントプランニングとプロダクトバックログのリストになります。これらのタスクを実行することで、アジャイル開発の手法を活用しながらSwiftの教科書アプリの開発を効果的に進めることができます。

[2/9 sp1｜スプリントプランニング実践会議について](https://qiita.com/sunstripe2011/items/db7c542fb72ae2862c4b)

## お問い合せ
プログラミングラボ：DMまで

https://twitter.com/PLab2020
AZ-140：Microsoft Azure Virtual Desktop の構成と運用合格備忘録


今回はMicorosoftの認定資格であるAZ-140(Microsoft Azure Virtual Desktop の構成と運用)を受験し、Microsoft Certified: Azure Virtual Desktop Specialtyの認定を受けたのでその合格体験記について書いていきます。


スコアは935/1000で合格できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616483/d5a8c985-fbd1-e6aa-e9e6-a6c333c67e2b.png)

学習期間は学習方法を模索に時間がかかり、合計して一か月ほどです。
特に試験前の2週間は集中的に学習していました。
また、前提知識としてAZ-104を取得しています。
業務経験としてのActive Directoryの知識、Windows ServerのOS知識がかなり役立ちました。

### AZ-140: Microsoft Azure Virtual Desktop の構成と運用
まずはAZ-140の概要です。
ネットで検索していたら名前が似ているAZ-104の記事が多く出てきてますが別の試験です。


試験のページには以下のように記載があります。
>任意のデバイス向けの Microsoft Azure Virtual Desktop エクスペリエンスとリモート アプリの設計、実装、管理、メンテナンスに関する専門知識を有するサーバーまたはデスクトップ管理者

平たく言えばMicrosoft Azure Virtual Desktop(AVD)の知識が試される試験です。

基本的にはAVDの構築と関連する設定を問われますが、関連してAzureポータルの上でのポリシー操作やActive DirectoryのGPO設計、Azureのユーザー権限や使用するライセンスも学ぶ必要があります。


これだけではなく、英語が苦手で問題演習をたくさんこなしたい私には以下の問題がありました。
- 日本語問題集の不足
    AWSの試験と比較して、Micorosoftの認定は全体的に試験の問題集が少ない。
    AZ-104やAZ-305と比較しても専門的な内容のため試験のナレッジがさらに不足。
    UdemyでもAZ-140を調べても英語の問題集しか出てない
    解説もあまり詳しくない。(正解の解説のみで間違いの理由などはないです。)
- 検証用のライセンスが料金がかかる
    実機を触って勉強したいなと思ってもライセンスが別途必要
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/616483/8dcbe17f-87e7-de38-122c-618c9ac36de2.png)
(https://learn.microsoft.com/ja-jp/azure/virtual-desktop/prerequisites?tabs=portalより引用)
執筆時点でおそらく一番安いライセンスでEducationなど除けばWindows E3ライセンスが該当。

Azure Virtual Desktopの狭い範囲を学習したら大丈夫だと油断していたら思いのほか問題集と実機それぞれの学習リソースにボトルネックとなりそうな要素がありました。

そのため、日本語リソースを何度も繰り返し読み込み、英語部分は翻訳ツールや生成AIに詳しく解説をしてもらおうとしました。

### 参考サイト
学習に活用したサイトをいくつか紹介します。

https://www.cloudou.net/azure-virtual-desktop/avd031/

一番目にしてもっとも活用したのはこちらのサイトです。
こちらのページで紹介されているリンクは全部目を通して不明点はMicrosoftのドキュメントで詳しくみるということをひたすら繰り返しました。
構築手順など画像で説明されており非常にわかりやすかったです。
公式ドキュメントだけだと文字が多いため初めにイメージを頭にたたきつける意味も込めて読むことをおすすめします。

https://learn.microsoft.com/ja-jp/azure/virtual-desktop/

続いてはMicrosoftの公式ドキュメントです。
言わずもがな公式ドキュメントのため、情報の量は多いです。
文字が多いですが操作方法やトラブルシューティングは全部読んで、あとは問題演習や生成AIの回答で不明なところを詳しく見ていました。


https://www.udemy.com/course/microsoft-az-140-certification-exam-practice-tests-2023/

続いては問題演習です。
英語ではありますがこれしかないと思って買いました。
類似問題の的中率が高いかと言われたらそんなことはありませんでした。
演習と理解を深めるという目的の方がいいかもしれません。

問題は解いてみたらわかりますが、的中をするというより、知識を問うものになっています。
そのため、以下の生成AIを活用して学習を進めました。

### 生成AI活用
学習方法に模索をしており、今回初めて試験対策に生成AIを活用してみました。
使用したのはBing Chat(現Copilot)です。

Udemyの試験問題はDeeplで翻訳し、テキストで翻訳された内容をBing Chatに質問
- 詳しい解説
- 間違えてる理由

この2点をひたすら問い合わせました。
また、生成された回答が間違っている、違和感がある場合はドキュメントを調べて間違いを見つけていくことも行いました。
こちらもかなり勉強になったので紹介しておきます。

## まとめ
以上、学習に使った資料の連携でした。
日本語のドキュメントや解説は数が少ないながらも非常に参考になるものが多かったのでひらすらに読み込むことが重要でした。
また、今回試験対策に生成AIを初めて活用しましたが、満足のいく回答を引き出すってところに時間がかかりがちなのも今後の課題かなと思いました。
不正解の理由など自分なりに整理するうえで役に立ったツールだったと思います。

試験概要を読んだだけでは気づかないほどAzureのアカウント権限やストレージの知識、Active Directoryの知識が求められました。業務経験に助けられたところも大きいので、上記の知識は多少あったほうがスコアは伸びやすいかと思いました。
ROS2 Launch Tips  パラメータファイルと個別パラメータの共存方法

# はじめに
* ROS 2のLaunchファイルで、パラメータファイル(YAML)と個別パラメータ設定を両立させる方法
* 使いどころ
  * 変更の少ないパラメータはパラメータファイル(YAML)で管理したいが、機能切り替えなどは個別パラメータにしたい場合などに有効

# 動作確認環境
* ROS 2 Foxy

# 方法

　パラメータファイル(params.yaml)に記載のパラメータと、個別のノードパラメータ(```double_number```)を設定する。

パラメータファイルの例 (```your_package/config/params.yaml```)
```yaml
your_node:
  ros__parameters:
    bool_value: True
    int_number: 1
```

　以下に、launch.pyとlaunch.xmlの方法をそれぞれ示す。

## launch.py (Python)

```python
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    ld = LaunchDescription()

    config = os.path.join(
        get_package_share_directory('your_package'),
        'config',
        'params.yaml'
    )
        
    node=Node(
        package = 'your_package',
        name = 'your_node',
        executable = 'your_node_exe',
        parameters = [
          config, 
          {
            "double_number": 0.1
          }
        ]
    )

    ld.add_action(node)
    return ld
```


## launch.xml (XML)

```xml
<launch>
  <arg name="config" default="$(find-pkg-share your_packge)/config/params.yaml"/>
  <node name="your_node" pkg="your_package" exec="your_node_exe">
    <param from="$(var config)"/>
    <param name="double_number" value="0.1"/>
  </node>
</launch>
```

# 注意点

個別パラメータを設定しても、同じパラメータがパラメータファイル内にあるとそちらが優先される 
* 下記の場合、double_number=0.2になる  
    ```yaml
    your_node:
      ros__parameters:
        bool_value: True
        int_number: 1
        double_number: 0.2
    ```

# まとめ
　上記方法により、パラメータファイル(YAML)と個別パラメータ設定を両立させることができた。

# 参考

https://roboticsbackend.com/ros2-yaml-params/

https://docs.ros.org/en/foxy/How-To-Guides/Launch-file-different-formats.html
「Swiftの教科書というアプリを作る」今年の目標とした時 どのように進めていくか

> 「Swiftの教科書というアプリを作る」今年の目標とした時
どのように進めていくか

ChatGPTに相談してみることにした

Swiftの教科書というアプリを作るという目標を達成するために、以下のステップを提案します

## アプリの機能と構造の計画

- [x] アプリにどのような機能を実装するかを決定します。例えば、Swift言語の基本的な構文や機能の解説、コードのサンプル、クイズや演習問題など。[→ 📖](https://qiita.com/sunstripe2011/items/5d9a5d3fa7e277bfb271)
- [ ] アプリの画面遷移やユーザーインターフェースの設計を行います。

## データ収集とコンテンツ作成

Swift言語の基本的な情報やサンプルコードを収集し、アプリに組み込むためのコンテンツを準備します。
ユーザーが学習を深めるための追加情報やリンクなども収集します。

## アプリの開発

- [ ] Xcodeを使用して、アプリの開発を行います。Swift言語を使用してアプリのロジックを実装し、UIを設計していきます。
- [ ] データベースやファイルシステムを使用して、コンテンツを管理する機能を実装します。

## テストとフィードバック

- [ ] 開発中にアプリをテストし、バグや不具合を修正します。
- [ ] 仲間やテストユーザーにアプリを試してもらい、フィードバックを収集して改善します。

## リリースとフィードバック収集

- [ ] アプリをリリースし、App Storeなどのプラットフォームに公開します。
- [ ] ユーザーからのフィードバックやレビューを収集し、アプリの改善やバージョンアップを行います。

## マーケティングと宣伝

- [ ] アプリの宣伝やマーケティングを行い、ターゲットユーザーにアプリを知ってもらいます。SNSやウェブサイト、コミュニティなどを活用します。

## 継続的な改善とアップデート

- [ ] ユーザーからのフィードバックやアプリ利用状況を分析し、必要な改善点や新機能の追加を行います。
- [ ] Swift言語や関連技術のアップデートに追従し、アプリの機能やコンテンツを継続的に改善します。

これらのステップを踏んで、Swiftの教科書というアプリを作成し、目標を達成していくことができます。

## お問い合せ
プログラミングラボ：DMまで

https://twitter.com/PLab2020
【JavaScript】snake_caseをcamelCaseに変換する方法

以下のライブラリをインストールします。

https://github.com/sindresorhus/camelcase-keys

```shell
$ yarn add camelcase-keys
```

以下のように使用します。

```js
import camelcaseKeys from 'camelcase-keys'

// オブジェクトを変換
camelcaseKeys({'foo_bar': true});
//=> {fooBar: true}

// オブジェクトの配列を変換
camelcaseKeys([{'foo_bar': true}, {'bar_foo': false}]);
//=> [{fooBar: true}, {barFoo: false}]

// ネストしている場合
camelcaseKeys({'foo_bar': true, nested: {unicorn_rainbow: true}}, {deep: true});
//=> {fooBar: true, nested: {unicornRainbow: true}}
```
Swiftの課題についてAIで作成してみる

> Swiftの課題について

・大きな目標（１つ）
・中くらいの目標（３つ）
・小さな目標（５つ）
・今週の課題（１０つ）

上記を提案してください

# 大きな目標

- [ ] AIと共にiOSアプリを開発するための基本的なスキルを身につける。
- [ ] 開発チームメンバーとアプリを作る工程を学ぶ。
- [ ] 開発チームメンバーが就職、転職、などそれぞれのキャリアップにつなげる

# 中くらいの目標

- [ ] MVC（Model-View-Controller）アーキテクチャの理解と実装を行う。
- [ ] アプリ内での画面遷移の実装方法を習得する。
- [ ] ネットワーク通信を行うためのAPIの使用方法を学ぶ。
- [ ] 開発チームメンバーと成長する。

# 小さな目標

- [x] [Swift言語の基本構文を理解する。](https://qiita.com/sunstripe2011/items/73967121460fa70b2c6e) 2024/02/08
- [ ] 開発チームメンバーを確保する
- [x] [Xcodeを使ったプロジェクトの作成と管理方法を学ぶ。](https://qiita.com/sunstripe2011/items/512c61824d1742a81c92) 2024/02/10
- [ ] UIKitフレームワークを使用して基本的なUIを作成する方法を習得する。
- [ ] データの保存や読み込みについて学ぶ（例：UserDefaults、Core Dataなど）。
- [ ] TableViewやCollectionViewなどのリスト表示の実装方法をマスターする。

# 今週の課題
- [x] [Swiftの基本構文を学ぶ。](https://qiita.com/sunstripe2011/items/73967121460fa70b2c6e) 2024/02/08
- [x] 開発チームメンバーの募集を開始する [プログラミングラボ](https://twitter.com/PLab2020) 2024/02/08
- [x] Xcodeで新しいプロジェクトを作成してみる。 [プログラミングラボ](https://twitter.com/PLab2020) 2024/02/08
- [x] Githubで新プロジェクトの管理を始めてみる。 [プログラミングラボ](https://github.com/GlobalProgrammingLaboratory/SwiftLesson) 2024/02/09
- [ ] UILabelやUIButtonなどの基本的なUI要素を配置してみる。
- [ ] ユーザーが入力したデータを保存してみる（例：UserDefaultsを使用）。
- [ ] TableViewを使ってリストを表示してみる。
- [ ] ViewController間の画面遷移を実装してみる。
- [ ] データの取得や送信を行うためのAPIを調査してみる。
- [ ] ネットワークリクエストを送信してみる。
- [ ] 取得したデータを解析して表示してみる。
- [ ] 週末までに完成したアプリのデモを行う。

## お問い合せ
プログラミングラボ：DMまで

https://twitter.com/PLab2020
GitHub Actionsを使ってデプロイ環境を簡単に自動化する

### GitHub Actionsを使ってDockerイメージのビルドとACR（Azure Container Registry）へのプッシュをさせてデプロイ環境を簡単に自動化する

参考にした記事

https://learn.microsoft.com/ja-jp/azure/app-service/deploy-github-actions?tabs=applevel%2Caspnetcore

https://learn.microsoft.com/ja-jp/azure/container-instances/container-instances-github-action?tabs=userlevel

#### workflows配下に作るymlファイル 
`.github/workflows/docker-deploy.yml`

```yaml
# パイプライン名。GitHub Actionsのタブで一覧表示される時にこの名前が出る
name: CI to Azure Container Registry

# ワークフローが実行されるトリガー条件。
# mainブランチへのpushしたときに発動させてる
on:
  push:
    branches: [main]

# ジョブの定義。ビルドとプッシュを一つのジョブで実行させる
jobs:
  build:
    # 実行環境はUbuntuを指定
    runs-on: ubuntu-latest
    steps:
      # GitHubリポジトリのコードをチェックアウトする
      # これがないと、リポジトリのコードにアクセスできないエラーでたから要る。
      - uses: actions/checkout@v3
        name: Checkout source code

      # Dockerにログインする。ビルドとプッシュ作業の前に必要
      - name: Log in to Azure Container Registry
        uses: docker/login-action@v2
        with:
          # ACRのドメインを指定。
          #※AzureでACRを事前に作っておく。↓画像参照
          registry: <レジストリ名>.azurecr.io
          # GitHub Secretsからユーザー名とパスワードを取得。
          username: ${{ secrets.ACR_USERNAME }}
          password: ${{ secrets.ACR_PASSWORD }}

      # ここでDockerイメージのビルドとACRへのプッシュする。
      - name: Build and push Docker image
        run: |
      #DockerビルドとタグにはGitHubのcommit SHAを使用。
          docker build . -t <レジストリ名>.azurecr.io/<アプリ名>:${{ github.sha }}     
      # ビルドしたイメージをACRにプッシュ。
          docker push <レジストリ名>.azurecr.io/<アプリ名>:${{ github.sha }}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3655530/c4a66b6f-ce7b-c689-877b-60164c214e4a.png)


ワークフローを設定することで、githubにpushするたびに自動的にDockerイメージがビルドされるのでかなり楽になった。
【ビット演算】2値の平均をオーバーフローなしで求める方法

# はじめに
日本語の記事がパッと見つからなかったので、メモ代わりに書きます。
ビット長ギリギリの大きな値で二分探索する際などに欲しくなります。

# 結論
以下の通りです。
```c
// ^  := 排他的論理和
// &  := 論理積
// >> := 算術シフト
((x ^ y) >> 1) + (x & y)
```

# なぜ
ふんわりした説明を与えます。

整数値 $a, b$ の足し算を考えます。
$\land$ は値を２進表示した際の各桁の論理積、$\oplus$ は各桁の排他的論理和。
各ビットの繰り上がりについて注目すると、以下の等式が成り立ちます。
```math
a + b = 2 * (a \land b) + a \oplus b 
```
両辺を $2$ で割ります。
```math
(a + b) / 2 = (a \land b) + (a \oplus b) / 2 
```
$a \land b$ および $a \oplus b$ は各桁についての演算なので、オーバーフローしません。


# 注意
結果が __負の値__ かつ __２で割り切れない__ 場合、以下の式２つは違う値を評価します。
```c
(a + b) / 2
```
```c
((a ^ b) >> 1) + (a & b)
```
上の式は絶対値の切り捨てを行うのに対して、下の式は切り上げを行います。
負数の補数表現のためにこのような結果になります。


```cpp:C++ でのサンプル
#include <iostream>

using namespace std;

int naive_avg(int a, int b) {
    return (a + b) / 2;
}

int smart_avg(int a, int b) {
    return ((a ^ b) >> 1) + (a & b);
}

int main(void){
   
    int a = -3, b = -6;
    cout << naive_avg(a, b)<< endl;
    cout << smart_avg(a, b) << endl;

}
```
```txt:結果
-4
-5
```

# 注意２
C++ における負値の右シフトが論理シフトであるか、算術シフトであるかは処理系依存である、という有名な話があります。そんなバカな。
ポータブルな実装ではないよ、という注意書きでした。

この話題は別の記事にしようと思います。↓

https://qiita.com/gandalfr-KY/items/6afb5d1d02fa7521df28

# 参考
https://github.com/keon/awesome-bits
データベースのロックについて

## 2種類のロック：共有ロック-占有ロック(排他ロック)
- 共有ロック
  - データを参照していることを示すためのロックで、SELECT文に付加できる
  - ロックされたレコードは更新できなくなる。参照は可能（今見てるから更新しないで～）
  - 同一レコードに対して複数のトランザクションからかけられる
- 占有ロック
  - データを更新するためにかけるロックで、UPDATEやDELETE文の実行時にかかる
  - ロックされたレコードは参照も更新もできなくなる（更新するからそれまで見ないで～）
  - 同一レコードに対して1つのトランザクションからのみかけられる
- トランザクションが終了したタイミングでロックも解除される

## データの整合性をどうとるかの方針：楽観ロックと悲観ロック
ロックの方式ではなく、排他制御の戦略の分類。
- 楽観ロック
  - 同一レコードの同時更新は起こらないという前提に立つ
  - データ更新の際ロックは行わず、データ読み取り時と更新直前の取得時とでデータに齟齬がなければ更新をかけちゃう
- 悲観ロック
  - 同一レコードの同時更新が起こりうるという前提に立つ
  - 更新時のデータ読み取りと同時にロックをかける


## デッドロック
ロックが解放されるのがトランザクションの終了後であるとき、トランザクション内に他トランザクションのロック解放を待たなければならないような処理があると「お互いがお互いのロック解放＝トランザクション終了待ち」の状態となり、トラザクションが終わらなくなる。

#### 変換デッドロック
2つのトランザクションが共有ロックをかけているときに、両トランザクションで占有ロックをかけようとすると発生するデッドロック。


#### サイクルデッドロック
2つのトランザクションの中で、互いに、相手が先に占有ロックをかけた行の更新待ちの処理が発生して発生するデッドロック。

#### デッドロックが起こらないようにするには
- 新時は占有ロックを取得する
- 更新順序を一定にする
例えば、以下の処理ではデッドロックが発生しうる（AとBの処理はそれぞれ1トランザクション内の処理）
```
mysql(A)> select * from numbers where id = 1 for update;
mysql(B)> select * from numbers where id = 2 for update;
mysql(A)> select * from numbers where id = 2 for update;
-- id=1・2の処理終了を互いに待ち続け、サイクルデッドロック発生
mysql(B)> select * from numbers where id = 1 for update;
```
が、こうすると発生しなくなる
```
mysql(A)> select * from numbers where id = 1 for update;
-- BがA待ち状態に入る
mysql(B)> select * from numbers where id = 1 for update;
mysql(A)> select * from numbers where id = 2 for update;
mysql(A)> commit;
-- Aの処理完了 --
-- Bが後続の処理を流せるようになる
mysql(B)> select * from numbers where id = 2 for update;
...
```

## まとめ
- 複数のトランザクションが同時に実行される状況でデータの整合性を保証するための方針が楽観ロック - 悲観ロック
- 悲観ロックを前提に、実際にかけるロックが共有ロック - 占有ロック
- トランザクション間で互いの共有ロック/占有ロックの解除待ちになってしまう現象がデッドロック

## 参考
[データベースのロックの基礎からデッドロックまで](https://zenn.dev/gibjapan/articles/1d8dfb7520dabc#2%E7%A8%AE%E9%A1%9E%E3%81%AE%E3%83%AD%E3%83%83%E3%82%AF)
[排他制御（楽観ロック・悲観ロック）の基礎　](https://qiita.com/NagaokaKenichi/items/73040df85b7bd4e9ecfc)
p5.js でのシェーダーを使った描画に WebGL 2.0（GLSL ES 3.0）を使う 〜その3：JavaScript側から時間の情報を渡す、createFilterShader() を併用〜

以下の記事で試してきた、p5.js でのシェーダーを使った描画に WebGL 2.0（GLSL ES 3.0）を使う話の、さらに続きのお試しです。

●p5.js でのシェーダーを使った描画に WebGL 2.0（GLSL ES 3.0）を使う - Qiita
　https://qiita.com/youtoy/items/af009f7401fd3ce861dd

●p5.js のフィルター用シェーダー「createFilterShader()」で WebGL 2.0（GLSL ES 3.0）を使う ＋ 色・座標情報に関わる書き方を WebGL 2.0対応にする - Qiita
　https://qiita.com/youtoy/items/8b22073f2666ac0c8a3e

上記の 2番目と同様に、[フィルター用シェーダー「createFilterShader()」](https://p5js.org/reference/#/p5/createFilterShader)を使うことにします。
そして、今回は p5.js のプログラムからシェーダーに時間情報を渡して、それをシェーダーで利用してみます。

## プログラムの内容と実行結果
それでは、前回の記事の 1つ目のお試しを流用して、プログラムを作ってみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/c4b62ec8-2fb9-99ce-7f2d-e85b48886613.png)

今回、試しに作った内容は以下の 2パターンです

### パターン1： mod() を使う

```javascript
let s;

function setup() {
  const fragSrc = `#version 300 es
  precision mediump float;

  out vec4 outColor;

  uniform float time;

  void main() {
    float modTime = mod(time, 2.0);
    float colB = modTime > 1.0 ? 2.0 - modTime : modTime;

    vec4 myColor = vec4(0.1, 0.3, colB, 1.0);
    outColor = myColor;
  }`;

  createCanvas(500, 400, WEBGL);
  pixelDensity(1);

  s = createFilterShader(fragSrc);
}

function draw() {
  s.setUniform("time", millis() / 1000.0);

  filter(s);
}
```

時間の情報の受け渡しは、シェーダー側は `uniform float time` の部分、JavaScript側は `s.setUniform("time", millis() / 1000.0)` の部分です。

それを、以下の処理で 0 から 1 の間を往復する値にして、青の色の値に用いています。

```c++
    float modTime = mod(time, 2.0);
    float colB = modTime > 1.0 ? 2.0 - modTime : modTime;
```

これを実行すると、色が時間変化する描画が行われるのが分かります。

### パターン2： 三角関数を使う
次は、三角関数を組み合わせてみます。

まず、作ったプログラムは以下のとおりです。

```javascript
let s;

function setup() {
  const fragSrc = `#version 300 es
  precision mediump float;

  out vec4 outColor;

  uniform float time;

  void main() {
    float colB = (sin(time*1.5) + 1.0) / 2.0;

    vec4 myColor = vec4(0.1, 0.3, colB, 1.0);
    outColor = myColor;
  }`;

  createCanvas(500, 400, WEBGL);
  pixelDensity(1);

  s = createFilterShader(fragSrc);
}

function draw() {
  s.setUniform("time", millis() / 1000.0);

  filter(s);
}
```

時間の情報の受け渡し方は、パターン1 と同じやり方です。
それをシェーダー側で使う際に、以下のようにしています。

```c++
    float colB = (sin(time*1.5) + 1.0) / 2.0;
```

大まかなところを言うと、-1 から 1 の値をとる sin() の値を、0 から　1 の間の値になるように補正しています。
上記のとおり、1 を加算して 0 から　2 の値の範囲になったものを、2 で除算して 0 から 1 の値の範囲にするという、シンプルな計算です。

変化のしかたについては、パターン1 と異なり sin() を使っているので線形の増減とは少し違った増減になります。

## 利用例
上記の 2つは、プログラムの内容をシンプルにするため、簡素な処理にしています。
（キャンバス全体が単色で塗られ、その塗りの色が時間変化するという描画）

最後に、今回の時間情報を使って、シェーダーの処理に反映させた場合の描画例を紹介してみます。

以下は、シェーダー側でグローエフェクト（光るエフェクト）をかけているのですが、その光り方の強さを、時間で変化させています。

https://twitter.com/youtoy/status/1755263804735414518