OmniAICreator/Qiita-1.07M huggingface dataset:
【Unity】Adressables な AudioMixer を使いやすくする AudioMixerManager

# 概要

Addressables 化した AudioMixer を Addressables 外から扱うには、LoadAssetAsync で取得する必要があります。
その手間をシングルトンで解決した```AudioMixerManager```を作りました。
    Group や Parameter を Enum で指定したり、複数の Parameter をまとめて変更したりできます。

``` 使用例.cs
// audioSource に SE の AudioMixerGroup を代入
audioSource.outputAudioMixerGroup = AudioMixerManager.GetMixerGroup(AudioMixerGroupEnum.SE);
// 音量を 1 に変化（5秒の InSine に合わせて）
AudioMixerManager.SetVolume(AudioMixerParameterEnum.SeVolume, 1f, 5f, Ease.InSine);
// BGM と SE のピッチを 1.2 に変化（2秒の OutBounce に合わせて）
AudioMixerManager.SetParameters(1.2f, 2f, Ease.OutBounce,
    AudioMixerParameterEnum.BgmPitch,
    AudioMixerParameterEnum.SePitch);
```

# コード

https://github.com/yamara-mh/CodeStorage/blob/main/Codes/AudioMixerManager.cs

# 導入方法

1. DoTween と Addressables と UniTask を導入します（無くても修正すれば使えます）。
2. AudioMixerManager.cs をプロジェクト内に置きます。
3. AudioMixer にある```AudioMixerGroup, Snapshot, Exposed Parameters```を AudioMixerManager.cs 内の3つの Enum に反映します。
4. AudioMixer を "AudioMixer" という名前で Addressables に登録します。

# 関数説明


|関数名|説明|
|-|-|
|GetMixerGroup|Enum の名前と一致する AudioMixerGroup を取得|
|GetMixerGroups|Enum の名前と一致する AudioMixerGroup を全て取得|
|GetSnapshot|Enum の名前と一致する AudioMixerSnapshot を取得|
|TransitionToSnapshot|特定の Snapshot の weight を変更|
|TransitionToSnapshots|複数の Snapshot の weight を個別に変更|
|TransitionToSnapshots|複数の Snapshot の weight をまとめて変更|
|TransitionBeTweenSnapshot|fromSnapshot の weight を 0 に、<br>toSnapshot の weight を 1 に変更|
|GetParameter|Enum の名前と一致する Parameter の値を取得|
|SetParameter|Enum の名前と一致する Parameter を変更|
|SetParameters|複数の Parameter をまとめて変更|
|GetVolume|Enum の名前と一致する Parameter の値を<br>デシベルから音量に変換して取得|
|SetVolume|Enum の名前と一致する Parameter の値を<br>音量からデシベルに変換して変更|
|SetVolumes|複数の Parameter を<br>音量からデシベルに変換してまとめて変更|
Javaで「ファイルのサイズを取得する(Files.size)」の動作を確認してみた

# 概要
Javaで「ファイルのサイズを取得する(Files.size)」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/file/index9.html

# 実装
以下のファイルを作成しました。
```JSample9_1.java
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.io.IOException;
import java.util.stream.Stream;

class JSample9_1{
  public static void main(String[] args){
    Path dirpath = Paths.get("doc");

    try (Stream<Path> stream = Files.list(dirpath)){
      stream.forEach(p -> {
        try{
          System.out.print(p.getFileName() + " : ");
          System.out.println(Files.size(p) + " byte");
        }catch(IOException e) {
          System.out.println(e);
        }
      });
    }catch(IOException e) {
      System.out.println(e);
    }
  }
}
```
以下のコマンドを実行しました。
```
$ javac JSample9_1.java 
$ java JSample9_1 
memo.txt : 0 byte
report.txt : 0 byte
```

# まとめ
何かの役に立てばと。
Next.jsのstand alone buildを利用したdocker imageのbuild

# Next.jsのstand alone buildとは

### 公式
- 要約すると最小限のファイル出力できるよ

> これにより、.next/standaloneにフォルダが作成され、node_modulesをインストールすることなく単独でデプロイできるようになります。`
> 
> さらに、next startの代わりに使用できる最小限のserver.jsファイルも出力されます。これらのフォルダは手動でstandalone/publicフォルダとstandalone/.next/staticフォルダにコピーすることができ、その後server.jsファイルが自動的にこれらのフォルダを提供します。


https://nextjs.org/docs/pages/api-reference/next-config-js/output#automatically-copying-traced-files

### Docker image作成
開発で作成するDocker imageは極力軽くしたいため、Next.jsのstand alone buildを実行してbuildする

### Dockerfile
monorepoで「client」と「packages/trpc」があると仮定したときのサンプル

解説
1. マルチステージのbuilder側にpackage.jsonをコピーしpackageをインストール
1. コードをコピーしbuildを実行
1. マルチステージのproduction側に「next.config.js」と「public」をコピー
1. build結果の「.next/static」と「.next/standalone/」が最小限必要なフォルダーになるため、コピーする
1. 起動コマンドをnode server.jsにする

```Dockerfile:Dockerfile
FROM node:18-alpine as builder

WORKDIR /app

COPY package.json yarn.lock ./
COPY client/package.json ./client/package.json
COPY packages/trpc/package.json ./packages/trpc/package.json
RUN yarn install --non-interactive

COPY . .
RUN yarn build && yarn cache clean

FROM node:18-slim as production
ENV NODE_ENV=production
WORKDIR /app

COPY client/next.config.js ./client/
COPY client/public/ ./client/public/
COPY --from=builder /app/client/.next/static ./client/.next/static
COPY --from=builder /app/client/.next/standalone/ ./

CMD ["node", "./client/server.js"]
```
【PUN2】アプリケーションIDの削除/再設定

Assets/Photon/PhotonUnityNetworking/Resources/PhotonServerSettings.asset
のApp Id PUNを変更すれば再度設定できます。

Gitなどを使ってUnityプロジェクトを公開したい時や、他人にデータを共有したい時にはこのIDを削除すれば、問題ないと思われます。

![スクリーンショット 2023-08-17 20.38.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/f3a7f794-5a43-7186-a8f7-5f13072d30a4.png)

![スクリーンショット 2023-08-17 20.42.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1865650/f2e48f27-530f-88a9-9142-e846ca26b521.png)
階層型アーキテクチャ - ドメインレイヤについて

# はじめに

Googleが推奨する階層型アーキテクチャの中にはドメインレイヤというものがあるので調べてみた。

# 階層型アーキテクチャ

ドメインレイヤを除いたアーキテクチャは
View (Fragment, Activity) → ViewModel → Data Layer
の構造になっている場合が多い。
![arch.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/914937/84573431-57a9-0dae-7403-77d3dd1dc7b6.png)


ドメインレイヤを入れる場合はRepositoryとViewModelの間に挟まってくる。
![arch.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/914937/84573431-57a9-0dae-7403-77d3dd1dc7b6.png)

# ドメインレイヤ

命名規則は　○○UseCase

ドメインレイヤは基本的にViewModelのビジネスロジックを代わりに受け持つ役割。

ViewModelが行っているRepositoryからデータを取得してUI側で利用可能なデータに変換する処理を行うパターンが多くなりそう。

Android Developerにはドメインレイヤを使うメリットとして下記のようにまとめられていた。

- コードの重複を回避できます。
- ドメインレイヤ クラスを使用するクラスの読みやすさが向上します。
- アプリのテストのしやすさが向上します。
- 役割を分担することで、クラスが大規模になることを回避できます。

https://developer.android.com/jetpack/guide/domain-layer?hl=ja

# ドメインレイヤの例

```kotlin
// 取得したアイテムの中で有効なもののみを取り出す
class GetAvailableItemsUseCase(
	private val itemsRepository: ItemsRepository
) {
	operator fun invoke(id: Int){
		const items = itemsRepository.get(id)
		return items.filter{ it.available }
	}
}

```

上記では取得したアイテムの中でavailbaleがtrueのものだけを取り出している。

上記の処理は単純でドメインレイヤに分けるメリットは大きくないかもしれないが、このロジックが複雑になってきたり、様々な場所で再利用されるようになるとメリットは大きくなると考えられる。

また、ドメインレイヤの中で複数のリポジトリからデータを取得して1つのデータにまとめたりすることもある。

```kotlin
/**
 * Android develoeprsのコードを引用 (<https://developer.android.com/jetpack/guide/domain-layer?hl=ja#combine-repositories>)
 * This use case fetches the latest news and the associated author.
 */
class GetLatestNewsWithAuthorsUseCase(
  private val newsRepository: NewsRepository,
  private val authorsRepository: AuthorsRepository,
  private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) {
    suspend operator fun invoke(): List<ArticleWithAuthor> =
        withContext(defaultDispatcher) {
            val news = newsRepository.fetchLatestNews()
            val result: MutableList<ArticleWithAuthor> = mutableListOf()
            // This is not parallelized, the use case is linearly slow.
            for (article in news) {
                // The repository exposes suspend functions
                val author = authorsRepository.getAuthor(article.authorId)
                result.add(ArticleWithAuthor(article, author))
            }
            result
        }
}

```

# マンガアプリにおけるドメインレイヤ利用例

弊社が手掛けているマンガアプリの中での利用例を考えると、作品ダウンロード機能が挙げられる。

サーバーから取得した作品一覧とローカルに保存されている作品一覧を取得し、ダウンロード済みの作品とそれ以外の作品とで表示を分けるためのデータ処理をドメインレイヤで行うことで、複数リポジトリアクセスの複雑な処理をまとめることができる。

## 使いどころまとめ

- 複数のRepositoryを組み合わせる場合
    - 複雑になりがちなので、UseCaseにまとめるのが良いと思われる
- フロント側で複雑なデータ変換処理を行う場合
    - 特にローカルで持っているデータを使ってリモートのデータを加工する場合
- 同じ処理を何度も再利用する場合
【Ruby】クラスとモジュール、継承とミックスイン

# 目次
1. イントロ
2. クラス(Class)
3. 継承(Inheritance)
4. モジュール(Module)
5. ミックスイン(Mixin)
6. 比較
7. まとめ

# イントロ
ダイナミックでオープンソースのプログラミング言語、Rubyはそのエレガントでシンプルなシンタックスが特徴です。Rubyはオブジェクト指向言語として、クラス、モジュール、継承、ミックスインなどの重要な概念があります。この記事では、これらの概念を解説し、Rubyプログラミングでの役割と特性について紹介します。

# クラス(Class)
クラスは、オブジェクト指向プログラミングにおける中心的な概念で、データの抽象化とカプセル化を提供します。クラスは属性とメソッドの集合で、特定のオブジェクトの振る舞いと構造を定義します。クラスによって定義されたインスタンスは、実行時にその属性とメソッドにアクセスすることができます。

```ruby
class Animal
  def breathe
    puts "Breathe!"
  end
end

animal = Animal.new
animal.breathe  # "Breathe!"
```

# 継承(Inheritance)
継承は、あるクラスが別のクラスの特性を受け継ぐプロセスです。これにより、コードの再利用性と維持性が向上し、既存のクラスを拡張して新しい機能を追加する能力を提供します。継承は階層的なクラスの関係を形成し、共通の特性を共有することを可能にします。

```ruby
class Animal
  def breathe
    puts "Breathe!"
  end
end

class Dog < Animal
  def woof
    puts "Woof!"
  end
end

class Cat < Animal
	def meow
		puts "Meow!"
	end
end

dog = Dog.new
dog.breathe  # "Breathe!"
dog.woof     # "Woof!"

cat = Cat.new
cat.breathe  # "Breathe!"
cat.meow     # "meow!"
```

上記の例では、`Dog`クラスとCatクラスは`Animal`クラスを継承するサブクラスなので、`Animal`クラスで定義された`breathe`メソッドを使用することができます。

# モジュール(Module)
モジュールは、メソッドと定数の名前空間を提供する独立したコンテナです。クラスと異なり、モジュールはインスタンス化されませんが、クラスにミックスインされることでその機能が取り込まれます。これによって、異なるクラス間で共通のメソッドを効率的に共有できるようになります。

```ruby
module Movable
  def move
    puts "Move!"
  end
end
```

# ミックスイン(Mixin)
ミックスインは、モジュールの機能をクラスに取り込むメカニズムで、多重継承の問題を解決するRubyの特徴的な手法です。クラスにモジュールを取り込むと、そのモジュールのメソッドがクラスのインスタンスメソッドとして利用可能になります。これにより、構造化されたコードの組織と、複数のクラス間での機能の共有が可能になります。

```ruby
module Movable
  def move
    puts "Move!"
  end
end

class Dog
  include Movable
end


class Human
  include Movable
end

dog = Dog.new
dog.move      # "Move!"

human = Human.new
human.move    # "Move!"
```
上記の例でDogクラスと`Human`クラスは`Movable`モジュールを含んでいるので、`Movable`モジュールで定義された`move`メソッドを使うことができます。

# 比較
| 機能 | クラス | モジュール |
| --- | --- | --- |
| メソッドの定義 | O | O |
| 定数の定義 | O | O |
| インスタンス化 | O | X |
| 継承 | O | X |
| ネームスペース役割 | O | O |
| ミキシンすること | O | O |
| ミキシンされること| X | O |

# まとめ
Rubyのオブジェクト指向プログラミングを使いこなすには、クラス、モジュール、継承、ミキシンを理解することが重要です。これらのコンセプトを理解することで、明快で効率的な **DRY（Don't Repeat Yourself）** なRubyコードを書くことができるようになります。
ビンゴゲームの確率シミュレーション（改良版）

原著者のやる気を削いでしまうかもしれませんが，一般的にプログラムの改良（?）のポイントを提示するという題材とさせてもらいました。

ポイントは
1. 関数化，サブルーチン化する（わかりやすくなる...改良すべき箇所が明瞭になる）
1. 無駄な設定を省く。
1. 余分な変数は使わない（アルゴリズムの改良にもなる）
1. for ループを避ける（1. にも該当）
1. その他...細かすぎるので，プログラム参照（Rstudio の reformat code に文句を言わせないようにする）

```R
一枚がビンゴか = function(M, N, Y) {
    # 1枚のビンゴカード X が抽選結果 Y によりビンゴかどうかを判定する
    # ビンゴだったマス目を 0 にし，最後に縦横斜めに 0 が並ぶか判定結果を返す
    X = matrix(sample(M, 25), ncol = 5) # 用紙
    X[3, 3] = 0
    for (i in 1:N) {
        X[X == Y[i]] = 0
    }
    return(0 %in% c(colSums(X), rowSums(X), sum(diag(X)), sum(diag(X[5:1,]))))
    
}

何枚がビンゴか = function(A, M, N, Y) {
    # A 枚のビンゴカードでビンゴになったかどうかを調べ(sub2)，ビンゴだったカード数を返す
    bingo = 0
    for (a in 1:A) {
        bingo = bingo + 一枚がビンゴか(M, N, Y)
    }
    return(bingo)
}

シミュレーション結果の記録 = function(A, B, M, N) {
    # シミュレーションを B 回繰り返し，毎回のビンゴカード枚数を記録する
    # 関数にする（平均値を知りたいなら，平均値を計算して返す方がよい）
	bingos = numeric(B) # シミュレーション結果保存
    Y = sample(M, N) # 抽選番号
	for (b in 1:B) {
		bingos[b] = 何枚がビンゴか(A, M, N, Y) # ビンゴ枚数の記録
	}
	return(bingos)
}

A = 50 # 用紙枚数
B = 5000 # シミュレーション回数
M = 75 # 数字の最大値
N = 25 # 抽選回数

set.seed(123)
system.time({
	print(mean(シミュレーション結果の記録(A, B, M, N)))
})

# 当初プログラム
# [1] 3.2378
#    user  system elapsed 
# 12.008   0.078  12.084 
# 抽選番号は全参加者に対して 1 回のみ（共通） Y が一定になったので，結果は別のものになる
# 3.2084
#    ユーザ   システム       経過  
#     11.062      0.055     11.224 
# 穴あけを X に対して行い，ビンゴ判定も X 自体で行う
# [1] 3.2084
#    ユーザ   システム       経過  
#     10.024      0.032     10.056 
# 要素が 0 を含むかどうかを 0, 1 で返す方法を変える
# [1] 3.2084
#    ユーザ   システム       経過  
#      9.838      0.024      9.861 
# ビンゴのチェックでの二重 for ループをやめる　==> 劇的変化（倍速）
# [1] 3.2084
#    ユーザ   システム       経過  
#      4.742      0.026      4.769 
# 当初の 2.5 倍くらい速くなったかな?
    [1] 3.2084
       ユーザ   システム       経過  
         4.748      0.036      4.785 

system.time({
	print(mean(シミュレーション結果の記録(30, 10000, M, 50)))
})
    [1] 24.4023
       ユーザ   システム       経過  
         7.550      0.034      7.585 
```
tRPCのドキュメント生成trpc-panel紹介

# tRPCのドキュメント生成

### 本記事の対象者
- tRPCを使っていてI/Fのドキュメントを作りたいと考えている人

### tRPCとは
tRPCとは、フルスタックのTypeScript開発者向けのフレームワークです。
APIエンドポイントを静的に型付けし、クライアント・サーバ間で共有することが可能です。

### trpc-panelとは
Swagger UIのようにI/Fのドキュメントを表示できます
tRPCバックエンドを手動でテストするためのUIを、オーバーヘッドなしで自動的に生成します

## 準備
### tRPCのセットアップ(Next.js)

create next-app実行後に以下のリンクに従ってファイルを作成していくだけ

https://trpc.io/docs/client/nextjs/setup

## trpc-panelのインストール

```
yarn add trpc-panel
```
https://github.com/iway1/trpc-panel


## trpc-panelの設定

```ts:server/trpc.ts
import { initTRPC } from "@trpc/server";
import { TRPCPanelMeta } from "trpc-panel";

const t = initTRPC.meta<TRPCPanelMeta>().create();
export const router = t.router;
export const procedure = t.procedure;
```

- describeでパラメータの説明追記
```ts:server/routers/_app.ts
import { z } from 'zod';
import { procedure, router } from '../trpc';
export const appRouter = router({
  hello: procedure
    .input(
      z.object({
        text: z.string().describe("The name to say hello too."),
      }),
    )
    .query((opts) => {
      return {
        greeting: `hello ${opts.input.text}`,
      };
    }),
});
// export type definition of API
export type AppRouter = typeof appRouter;
```

```ts:pages/api/panel.ts
import { appRouter } from '@/server/routers/_app';
import type { NextApiRequest, NextApiResponse } from 'next';
import { renderTrpcPanel } from 'trpc-panel';

export default async function handler(_: NextApiRequest, res: NextApiResponse) {
    if (process.env.NODE_ENV === 'development') {
        return res.status(200).send(renderTrpcPanel(appRouter, {
            url: 'http://localhost:3000/api/trpc',
        }));
    }
    return res.status(404);
}
```

## 起動して動作確認

http://localhost:3000/api/panel
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476893/25ea94ed-9f9d-7603-7dd8-005f4b6e5c39.png)

## リクエストを送ってみる

QUERY > hello のinputに文字を入力してExecute
→  Responseが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476893/48f83b75-f182-ebcd-6b44-d6c6b4d4d49b.png)
夏季休暇にしたエンジニアっぽいこと

## はじめに

どうも社会人3年目です。

なんと夏季休暇が10日もありました!!!!(ホワイト企業バンザイ)

「エンジニアたるもの休暇も勉強するのが普通」[^1] ということで、夏季休暇を利用して私が取り組んだエンジニアっぽいことを共有します。

[^1]: 大袈裟に表現しただけで、決して**普通**とは思っていません。実際、平均2時間程度は勉強しましたが、ちゃんとダラダラしたり、遊んだりして休暇を満喫しました。

---

## 読書

### 1. マスタリングTCP/IP 入門編（第6版）

https://amzn.asia/d/40TDjM9

「マスタリングTCP/IP 入門編（第6版）」という書籍を読みました。この本はTCP/IPに関する詳細な解説がされており、ネットワークの基本から応用まで幅広い内容が書かれていたため、ネットワークの仕組みや通信の基本について学ぶことができました。

もともとNW周辺の知識が乏しいと感じていたので、読んでよかったです。
(入門編とありましたが、ネットワークの知識が乏しい私には難しかった(小声))

このくらいの知識はついたと思ってます↓

```txt
知らない ---------------- NW完全に理解した ---------------- NWちょっと分かる
        ↑       ↑
        ここから  ここまで成長
```

### 2. SSL/TLS徹底入門

https://amzn.asia/d/4bB8HxH

また、「SSL/TLS徹底入門: わかりやすい図解解説 インターネット技術」という書籍も読みました。セキュアな通信の仕組みであるSSL/TLSについて、図解を交えて詳細に解説されていてとてもわかりやすかったです。TLSに関する書籍なので当然セキュリティに関する知識を深めることができました。

ちなみにこの書籍はPrime Readingで無料&ページ数も少ないのでサクッと読めたのでその辺もよかったです。

## イベントへの参加(聞くだけ)

### 並列処理をGo/Rust/Kotlin/Python/JSで解説！思想の違いを体感しよう

オンラインイベント「[並列処理をGo/Rust/Kotlin/Python/JSで解説！思想の違いを体感しよう](https://jtx.connpass.com/event/289233/)」に参加しました。複数の言語での並列処理のアプローチや思想の違いについて学ぶことができる貴重な機会でした。

[ライブアーカイブ](https://www.youtube.com/live/m-1Drlk2G8w?feature=share)も公開されているので是非。

## Udemyの動画講座

### 1. Echo/Go + Reactで始めるモダンWebアプリケーション開発

「Echo/Go + Reactで始めるモダンWebアプリケーション開発」というコースを受講しました。

私自身、以前の業務でこの講座と同じような技術スタックで開発をしたことがあったので、運命を感じて受講しました。Goのコードはクリーンアーキテクチャの思想に従って実装を進めていくため、クリーンアーキテクチャについても学ぶことができます。なのにコースの時間はたった2時間半という!

すごくよかった。

https://www.udemy.com/course/echo-go-react-restapi/

### 2. ChatGPTの使い方入門

また、ChatGPTの使い方入門-最新AIビジネス活用 プロンプトエンジニアリングでより良い回答を得よう【2023年最新版】」というコースも受講しました。

今更感が否めないけど、ChatGPTってすごい....

会社で使うには色々な障壁があるけど、プライベートではどんどん使ってきたいですね。

https://www.udemy.com/course/how-to-use-chatgpt-for-business/

## その他の学びと取り組み

### Goの学習

Goは業務で1年半ほど使っていましたが、ここ1年くらいはPythonばかりでごGoの書き方を忘れかけていたので、最近プライベートでGoを触るようにしました。

ちょうど夏季休暇中にGo1.21がリリースされたので、その[リリースノート](https://tip.golang.org/doc/go1.21)を読みました。(maps,slices,cmpなどのパッケージが追加されましたが目玉は[slog](https://pkg.go.dev/golang.org/x/exp/slog)ですかね。実際に使ってみるまではできなかったですが..)

また、HTTP周りの知識を深めたかったので、HTTPクライアントの参照実装をGo書いたりしました。

## まとめ

この記事が皆さんの刺激になれば幸いです。 :fire: 

とはいえ、こういう記事を書いときながらなんですが、休暇はちゃんと休みましょう。
Windows9はなぜ存在しないのか？

みなさんはふとこう思ったことはことはないでしょうか？

**なぜWindows9は存在しないのか？**

2012年、Windows8が発売されました。

そして2015年、Windows9が発売されると思いきや

まさかの発売されたのはWindows10。なぜ9と飛ばされたのでしょうか？

Windows9が存在しない理由は公式、つまりMicrosoftは公表していません。

しかし、いくつか思い当たるフシがあるので説明しようと思います。

### 1.Windows9x系と混同するのを防ぐため
Windowsの歴史について軽く説明します。1995年に発売されたWindows95、

1998年に発売されたWindows98、2000年に発売されたWindows Meは<strong>9x系</strong>と呼ばれています。

この9x系と9が混同してしまうのを防ぐためにWidows9がない理由としての１つ目の仮説です。

以前アメリカ最大級の掲示板サイトredditにこのような投稿があります。

![l_tm_1410win10_1_03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3534014/d4dfe895-a36c-7ac1-88ad-e0ad92ad3caf.jpeg)

上記の画像から、Windowsの内部プログラム上で9x系の処理は<strong>"Windows 9"で始まるバージョン</strong>として処理されます。

つまり、<strong>Windows9も9xと同じように処理されてしまうのです。</strong>

このようなプログラムがWindows上にいくつもあり、誤作動を防ぐために

Windows9がない理由の１つとして考えられます。

また、<strong>SEOなどのマーケティング的な理由</strong>も考えられます。

例えば、Windows9と検索してWindows95の情報が出てきたり、Windows95と検索してWindows9の情報が出てくる可能性があります。

こういった混同を防ぐためにWindows9を飛ばした理由の仮説として考えられます。

### 2.Windows 8.1のリリース
2つ目に、Windows 8.1のリリースが関係しています。まずはWindows8.1リリースの経緯から説明します。

2012年、Windows8がリリースされたのですがめちゃくちゃ不評でした。不評の原因は

・スタートボタン、スタートメニューが消えたこと
・初心者にとってショートカットキーが使いにくい

などがあります。この問題を解決するために、Microsoftは2013年、Windows8.1がリリースされます。

このWIndows8.1がWindows9が消えた理由と言われています。

どういうことか？

先程、1990年代に発売されたWindows95や98は9x系と呼ばれると説明しました。

実は1990年代、9x系の他に<strong>NT系</strong>と呼ばれる系統がありました。

NT系はワークステーション向けのOSです。

90年代のMicrosoftはNT系と9x系の両方をサポートしていたのですがこの2つのOSはWindowsXPで統一されます。

NT系のほうが安定性に優れていたため、WindowsXPから内部プログラム、カーネルなどは従来のNT系のものが使われています。

ここで、WindowsにはXP、Vista、7、8、10などのバージョンの他に内部バージョンというものがあります。

内部バージョンは従来のNT系のバージョンから数字が更新されています。

|バージョン|内部バージョン|法則|
|--------- |-------------|----|
Windows 7 | NT 6.1|6 + 1 = 7?
Windows 8| NT 6.2|6 + 2 = 8?
<strong>Windows 8.1| <strong>NT 6.3|<strong>6 + 3 = 9?
Windows 10| NT 6.4|6 + 4 = 10?

上記の表は各OSのバージョンに対する内部バージョンを示す表です。

表を見ると内部バージョンの数字を足すとOSのバージョンになっています。

しかし、Windows8.1も内部バージョンに更新があったため、Windows8.1の次世代のOSは10となるわけです。

これがWindows9が存在しない理由のもう１つの仮説として考えられます。

ネットを見ると他にも
「Windows10は事実上最後のOSとしてリリースされたためキリがいい数字にしたかった」

「7,8,9 → seven,eight,nine → seven,ate,nine → 7が9を食べた、というアメリカンジョーク」

などの理由もありましたが、納得できる理由としては上記の２つの仮説だと思います。

Microsoftが公表していないのであくまで仮説です。真意はわかりません。。

そういえば、iPhone 9もなかったような気がするな・・・
Splideのアクセシビリティの意識が高くてついていけなかったのでゆっくり咀嚼する

Splideは「アクセシビリティに配慮した軽量・高機能スライダー」と謳っています。
使ってみると、その謳い文句に劣らず、確かにアクセシビリティに非常に気をつかわれていることが分かります。

このSplideの公式ドキュメントにはアクセシビリティに関するページが単独で存在し、（当たり前ですが）そもそもWebアクセシビリティに明るくないと半分も理解できません。少なくとも私は完全に理解した状態でした。



そこで、W3Cのドキュメント等も踏まえカルーセルのアクセシビリティについて理解を深めつつ、Splideについても噛み砕いていきたいと思います。（かなり時間がかかった）

カルーセルのW3Cデザインパターンを確認
バージョン4から、W3CのCarousel Design Patternに準拠した上で、スクリーンリーダーが動的にコンテンツを読み上げられるようライブリージョンも導入しました。

まずは、Splideが準拠しているという、W3Cのカルーセルのデザインパターンを確認していきます。
今後の話は、これを前提に進められていきますので、ここが理解できないことには何も始まりません。



WAI-ARIAについても記載がありますが、こちらのセクションにはまとめず、Splideの説明に組み込みながら見ていきます。

“十分な”カルーセル制御に必要なもの
カルーセルに必要な機能は以下の通りであると示されています。

前と次のスライドを表示するためのボタン
オプションとして、表示する特定のスライドを選択するためのコントロール、またはコントロールのグループ
カルーセルを自動スクロールさせる場合
回転を停止・再開するためのボタンがある
キーボードのフォーカスがカルーセルに入ると回転が停止する
マウスがカルーセルの上に乗っている間は回転を停止する
キーボードインタラクション
自動スクロールさせる場合
カルーセル内の要素にキーボードのフォーカスが当たった時は、スライドの自動スクロールは停止させます。
ユーザが自動スクロールの再生・停止ボタンを押さない限り、回転は再開されません。

TabキーとShift + Tab
通常のタブ順序によって指定されたカルーセルのインタラクティブ要素にフォーカスを移動します。
Tabキーのためのスクリプトは必要ありません。

ボタン要素
ボタン要素は、ボタンパターンで定義されたキーボードインタラクションを実装します。

自動スクロールの開始・停止、スライドを次・前へ動かすボタンは、何度でも繰り返し押せるようにします。

自動スクロールの開始・停止コントロール
自動スクロールコントロールは、カルーセル内のタブ順序中で最初の要素にします。
回転するコンテンツの前に置くことが重要です。

ページネーションをタブ要素で使う場合
ここで言うページネーションは、カルーセルの下についてるドットなどで表示される、任意のスライドに移動できるコントロールのことです。

これをタブ要素で使う場合は、Tabsパターンで定義されたキーボードインタラクションを実装します。
初心者備忘録①：テキストをクリックしてラジオボタンが反応するようにしたい

みなさん、こんにちは。
プログラミングの勉強中に気づいたことや気になったことなどを備忘録的に記事にしていこうと思います。
今回はHTMLの**labelタグ**と**inputタグ**、そして**id属性**と**for属性**についてです。

# ラジオボタンとテキストを関連付けたい
様々なサイトのお問い合わせフォーム等でラジオボタンを見かけたことがあるかと思います。
例えばこのようなものですね。
![スクリーンショット 2023-07-26 175055.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2150221/a1ed1b9e-1ee2-118a-99b8-401d84bf47f9.png)
コードは下記のようになります。
```html
<p>ペットとして飼いたい動物は？</p>
<input type="radio" name="pet">犬
<input type="radio" name="pet">猫
<input type="radio" name="pet">うさぎ
```
ただし、この時点ではテキスト部分をクリックしてもラジオボタンは反応しません。
![ペットとして飼いたい動物は.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2150221/370fa3ca-2d84-7392-b251-cf890315719d.gif)
しかし、ユーザビリティを考えた場合、ラジオボタンとテキストどちらをクリックしても反応するようにしたいですよね。
では、実際どのように実現するかというと方法は主に2つあります。

# 方法その1：input要素をlabelタグで囲む
1つ目の方法はinput要素をlabelタグで囲む方法です。
本来ならばinput部分をクリックすると反応するものをlabelの範囲内に入れてしまう、要するにクリックできる範囲を広げようという考え方ですね。
下記のようにコードを修正します。
```html
<p>ペットとして飼いたい動物は？</p>
<label><input type="radio" name="pet">犬</label>
<label><input type="radio" name="pet">猫</label>
<label><input type="radio" name="pet">うさぎ</label>
```
テキストクリックでラジオボタンが反応するようになりました！
※デザインが若干変わりますが、CSSでの調整部分になりますので割愛します。
![ペットとして飼いたい動物はlabel.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2150221/ad3bbace-5fe8-0796-1253-f840d8240acf.gif)
コーディングとしてもシンプルにlabelタグで挟むだけなので、非常に簡単ですね。

# 方法その2：inputタグとlabelタグをidとforで関連付ける
2つ目の方法はidとforを使ってinputタグとlabelタグを関連付ける方法です。
先程のクリックできる範囲を広げる方法とは異なり、こちらはバラバラの物を紐で結び付けるようなイメージですね。
下記のようにinputタグ内にidをlabelタグ内にforをそれぞれ記述します。
```html
<p>ペットとして飼いたい動物は？</p>
<input id="dog" type="radio" name="pet"><label for="dog">犬</label>
<input id="cat" type="radio" name="pet"><label for="cat">猫</label>
<input id="rabbit" type="radio" name="pet"><label for="rabbit">うさぎ</label>
```
これにより先程と同様にテキストクリックでラジオボタンが反応するようになりました！
![ペットとして飼いたい動物はidfor.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2150221/bf1c2e7c-56ee-222b-0415-35174ea4081d.gif)
labelタグで囲むことと比較して記述が増えるので最初は多少とっつきにくいですが、「**inputとidがセット**」、「**labelとforがセット**」という組み合わせをよく覚えましょう。
また、注意点として「id=""」と「for=""」の**内容を一致させる**必要があります。
例えば今回の犬のラジオボタンのコードでは`id="dog"、for="dog"`となり、記述内容が一致しています。
この記述内容が一致していないと、テキストをクリックしても反応しなくなってしまうため、注意しましょう。
idとforを使う場合の特徴としては、inputタグとlabelタグが文字通り**紐付けられている**という点が挙げられます。
なので、例えばinputとlabelの間に別のdiv要素が入っていたり、離れた場所に記述したとしても反応させることができます。
何だかデザインの幅が広がりそうですよね。(私はまだ使いこなせる気がしませんが・・・)

# まとめ
今回はフォーム画面の作り方を勉強していく中で学んだ、テキストをクリックしてラジオボタンを反応させるための2つの方法をご紹介させていただきました。
2つの方法にはそれぞれどんなメリット・デメリットがあり、どういった場面で使い分けるべきなのかという事に関してはまだまだ勉強中です・・・。
より理解を深められた際に改めてご紹介させていただければと思います。
勉強がんばっていきましょう！

# 参考
[HTMLのinputとlabelを使用してidとforを紐付けしてみる](https://shu-sait.com/input-label-id-for/#outline__1)
GitHub APIでrate limitでリクエストが失敗した時の対処法

公式ドキュメントにも手厚く記載されている内容ですが、備忘録も兼ねて記載しておきます。

## TL;DR
- GitHub APIをリクエストする時は認証する
- GitHub Actionsの場合はGITHUB_TOKENかGitHub Appを使って認証する

## GitHub APIのレート制限について
以下のようにレート制限があるので認証せずにリクエストしてるとCIが失敗することがある。

> 認証されていないリクエストでは、レート制限により 1 時間あたり最大 60 リクエストまで可能です。 認証されていないリクエストは、リクエストを発行した人ではなく、発信元の IP アドレスに関連付けられます。

https://docs.github.com/ja/rest/overview/resources-in-the-rest-api?apiVersion=2022-11-28

## 具体的にどんなエラーに遭遇したか？

GitHub Actionsでkustomizeをインストールする時に頻繁にrate limitエラーが出ていました。最初は原因が分からず以下のようにリトライを入れることで緩和していましたがそれでも失敗する時がありました。

```yaml
- name: Install kustomize
  run: |
    curl -s --retry 3 "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/kyaml/v0.13.10/hack/install_kustomize.sh" | bash
    chmod +x kustomize
    echo ${{ github.workspace }} >> $GITHUB_PATH
```

install_kustomize.shはapi.github.comからkustomizeをダウンロードする作りになっているため、認証なしでリクエストするとrate limitエラーになっていました。

ちなみにinstall_kustomize.shは公式（kubernetes-sigs/kustomize）で提供されているインストールスクリプトです。

上記のバージョン（kyaml/v0.13.10）では、GitHub認証に対応していなかったのですが[このPR](https://github.com/kubernetes-sigs/kustomize/pull/4946)で対応してくれていたのでバージョンを上げつつ認証を通してやることで解消しました。

```yaml
- name: Install kustomize
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  run: |
    curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/kyaml/v0.14.3/hack/install_kustomize.sh" | bash
    chmod +x kustomize
    echo ${{ github.workspace }} >> $GITHUB_PATH
```

この例に限らずインストールを含むステップはGitHub APIを叩いているケースが多いので、知らないと認証漏れでAPIエラーになるケースは多そうです。
テキストマイニングの基本処理_①N-gram

## この記事は何？
VSCodeで初めてのテキストマイニングに挑戦、その学習ログです。
「pythonによるテキストマイニング入門」（山内長承）が参考図書です

## 環境
VSCode

## 実践
#### 文字の出現頻度
```python
# Counterクラスを使用
from collections import Counter
string = "I have a dream."
cnt = Counter(string_1)
print(cnt)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/d46ee195-92c8-8f3e-4fa7-145ca65d26bf.png)

#### 文字のN-gram分析
```python
string = "吾輩は猫である。名前はまだない。"

# 「、」、スペースを区切り文字とする。
delimiter = ["「", "」", " "]

# zipでペアのタプルを作成する
doublets = list(zip(string[:-1], string[1:]))
doublets = filter((lambda x: not((x[0] in delimiter) or (x[1] in delimiter))), doublets) # 今回はない

# タプルの２番目の要素をキーにソートを行う
dic2 = Counter(doublets)
for k,v in sorted(dic2.items(), key=lambda x:x[1], reverse=True)[:50]:
    print(k, v)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/8fdaeae9-7a3a-13e0-47ed-5a3a5185c071.png)

**【補足】**
```python
string = "吾輩は猫である。名前はまだない。"
# 初めから最後-1の文字までをタプルの[0]に入れる
string[:-1]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/09b206a8-bfe1-f09e-3232-6df854148d8c.png)

```python
# 初め+1から最後の文字までをタプルの[1]に入れる
string[1:]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/11932195-6d47-46e2-38c6-c6a6f0c28635.png)

#### 語のN-gram分析
JEITAコーパス内のファイルを読み込んで実施する（HPは[▶こちら](http://masatohagiwara.net/nltk-japanese-corpus.html)）
以下からダウンロード
http://masatohagiwara.net/files/jeita_aozora.tar.bz2

ファイルはドキュメントの特定のファイル下に移動させる

```python
# ディレクトリを強制
import os
os.chdir("c:/Users/--ここは自分のPC参照--/Documents/nltk_data/jeita/jeita_aozora")
```
```python
pwd
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/380556ed-44a9-5eee-987d-aa1e6e16b985.png)
```python
# ディレクトリを指定
corpus_dir = "\\Users\\shota.kikko.bg\\Documents\\nltk_data\\jeita\\jeita_aozora"

# jeitaコーパスデータの読み込み
jeita = ChasenCorpusReader(corpus_dir, "1000.chasen")

delimiter = ["「", "」", " ", "『", "』"]
string = jeita.words()
doublets = list(zip(string[:-1], string[1:]))
doublets = filter((lambda x: not((x[0] in delimiter) or (x[1] in delimiter))), doublets)

dic2 = Counter(doublets)
for u,v in dic2.items():
    print(u,v)
```
（最初の\u3000は何だろう…）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3179561/f0436fe2-e66f-dd53-274f-9cafec5fce48.png)
VR触れてみようの会　vol.1

# 目次
- バーチャルリアリティとは？
- 事例紹介
- 体験
- 作ってみる
- 終わり


# バーチャルリアリティとは？


### 「バーチャル(Virtual)」とは？

「virtue」の形容詞
→徳、善行、長所、効力 etc

　　→それぞれの物には表層的な部分と本質的な部分があって、その本質的な部分がvirtue

「Virtual」は、「表装丁にはそうではないが、本質的にはそうである」と言う意味
　
つまり、「Virtual Reality（バーチャルリアリティ）」とは、

#### 「見かけは現実ではないが、実質的には現実であること」


一般的にコンピュータによって生成された3D環境シミュレーション
HMD（ヘッドマウントディスプレイ）を介して体験する。

→没入体験を得ることができる


###  バーチャルリアリティの三要素

##### 三次元の空間性
コンピュータが生成した立体的な視覚空間
3D映画などはこれに当たる。

しかし、別の角度や写っている物体の後ろに回り込んでみることはできない
##### 実時間の相互作用性
現実の時間との相互作用
ゲームとか。。。

##### 自己投射
あたかも自分自身が環境に入り込んだような状態



#### バーチャルリアリティとは、この三要素を有したシステムを構成して、人間が実際の環境を利用しているのと本質的に同等な状況で、コンピュータの生成した人工環境を利用する。




<br /><br />

<hr />

#### ダモクレスの剣
1968年にユタ大学の教員であったアイバン・サザランドとボブ・スプロールが開発した世界最初のバーチャルリアリティ（以下VR）および拡張現実（以下AR）を実現したヘッドマウントディスプレイ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/1ddb3482-0215-f87a-8762-0536eaddc0d7.png)

バーチャルリアリティ学より

# 事例の紹介（一部）
コミュニケーション
　VRChat （さまざまなカルチャーの先端的な場所になってきているとコ個人的に感じている。）

https://xn--pckjp4dudxftf.xn--tckwe/

ファッション
Chloma

https://fashiontechnews.zozo.com/philosophy/chloma

# 今回体験してみる作品（僕の独断と偏見でSTYLYよりキュレーションしました）
- 　VRアートワーク
  Midnight Ghost Cafe　（photogrametry）
　https://gallery.styly.cc/scene/65f94447-eab6-4215-9103-c74b8c500781

https://styly.cc/ja/pickup-scene/vr_ghost_documentary_meta_party_michi/

Fantasy box
https://gallery.styly.cc/scene/7e4c539a-356d-40ed-811a-6fb45505cace

- 　記憶の保管

MemoryofMyHouse
https://gallery.styly.cc/scene/4cfbf11a-a728-4a9e-a39e-dacb798be759
- 　映像表現(Audio Visual)

MondGrosso FORGOTTEN　　-VRMV-
https://gallery.styly.cc/scene/d83e25c0-1ac3-4be3-b1ab-4e6d879986bd

INTERSUBJECTIVITY 　-VRMV-
https://gallery.styly.cc/scene/3f50e947-e137-11e9-b34d-4783bb2170d0

Alien Party VR (AUdio_visual)
https://gallery.styly.cc/scene/9084cebd-6c4f-4c72-b7d0-5b3f35fa8be6


CocoTsuki VRMV - Android Girl -　-VRMV-
https://gallery.styly.cc/scene/3ddc5cf9-dd4e-11e9-b34d-4783bb2170d0


【MV】私立恵比寿中学「シュガーグレーズ」 × 360 Reality Audio | スペシャルビデオ
https://www.youtube.com/watch?v=zUMP5I15mPg

# STYLYで作品を作ってみる
UnityやBlenderを触る前にどんな感じかのイメージを掴むために誰でもXR（VR AR MR）作品を作ることができるプラットフォームを用いて一つ作品を制作してみましょう。

https://gallery.styly.cc/about/ja

新規登録からアカウント登録！
![スクリーンショット 2023-08-17 1.19.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/8b0433ff-ac9c-a8a7-beb0-a88911cde87b.png)

新規シーンをクリック　→  シーンを作成　→　VRtemplateを選ぶ
![スクリーンショット 2023-08-17 1.20.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1462552/b5c7ce38-783b-8a26-2a80-5801cf86f23e.png)

あとは、やりたいようにアセットを配置していくだけ。　







# その他VRを使った取り組みの例
- 旅行と観光
- 機械工学と工業デザイン
- 　AutoCADなどの設計ソフトウェアを使用した三次元でのモデリングやシミュレーションに使用される
- 　建築と土木工学
- 　デザインについての仮説をバーチャルモデルで組み立てることで、　出資者やデザイナーとのやりとりを迅速に行うことができる
- 　不動産
- 　医療
- 　手術シミュレーション
- 　家具を買う行為
- 　思い出を空間ごと保管する
- 　映像表現
- 　心の健康療法
- 　　心的外傷後ストレス障害（PTSD）のセラピーの治療の過程に効果的
- 　　　　疑似体験療法を用いて体験を再び語ることでトラウマとなっている記憶に立ち向かう。
- 　　　　　　クモ恐怖症や飛行機恐怖症の治療に効果的であるとされている
- 　教育
- 　　歴史など
- 　　エンタメ


# その他
vol.2でBlenderかUnityを使って何かシーンを制作してみましょう。
【serverlessフレームワーク】イベントを設定したのに反映されない

# はじめに
プログラミング学習中の[@kat_log](https://twitter.com/kat__log "Twitter")と申します。

serverless flameworkの学習にて起きた問題の解決メモになります🙇
serverless.ymlに、AWSのLambdaを定期実行するcronを記載したのに、npx serverless deployにてデプロイしてもLambdaの関数にトリガーが設定されていない問題が発生し、解決しました🙌
（超凡ミスでした…）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/c24d41be-6afe-535b-9052-7d7a2472ca7d.png)


# 結論
eventsと記載すべきところを、eventと単数形を記載していました…

## 誤
```serverless.yml
  costNotifier:
    handler: src/costNotifier.handler
    event: # ←←←←←←ココです
      # 日本時間で毎朝9時
      - schedule: cron(0 0 * * ? *)
```

## 正
```serverless.yml
  costNotifier:
    handler: src/costNotifier.handler
    events: # ←←←←←←ココです
      # 日本時間で毎朝9時
      - schedule: cron(0 0 * * ? *)
```


イベントブリッジが追加されました！🙌↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/da062e1a-ab2e-45fc-e774-092fe9ce37a1.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1455073/e6bb1b7a-8490-5013-62e2-2b85ce13ffb7.png)

# おわりに
お読みいただきありがとうございました。
どなたかの参考になれば嬉しいです。
個人用開発時詰まった際に使用したurl集

# anaconda関連
　anaconda関連はインストールするものも多いし、環境の入れ替えとかもあるので、とにかく詰まりやすい...

・VScodeで選びたいconda環境が指定できない
https://qiita.com/eyuta/items/d0ece5ae147109db1308
→ctrl+shift+Pから、python select interpreterを押すと、condaの種類が表示される。

・VScode上でcondaコマンドが使えないとき
https://zenn.dev/shin1007/articles/f78b207c7e9164
anacondaのPowerShellをデフォルトのターミナルに設定するようにしている。おそらくこれをするとローカルのpythonで動作させるのが難しくなるが、特に問題ないのでOK

・condaコマンドリスト
https://qiita.com/ell/items/fb60d2fd765650417c7a


# ターミナル関係
　
・VScodeでデバッグなしでバックグラウンドで動かしたい時のコマンド
markdown-itでhtml要素に属性を追加する

markdown-itでマークダウン形式のテキストをHTMLにパースするときに要素にclassやcssなどの属性を追加したいときは以下を実行します。

```javascript
md.renderer.rules.要素名_open  = function () { return 'htmlタブ'; };
```

例えば、`table`要素にclass属性を追加したいときは以下を実行します。

```javascript
md.renderer.rules.table_open = function() {
    return '<table class="table">';
};
```


参考URL

https://markdown-it.github.io/markdown-it/#Renderer.prototype.rules
Spring バリデーション　Binding result

☆やりたいこと
登録画面で必須入力のバリデーションを実装したかった

コントローラークラスの引数に、Binding resultを書く。
Binding result　とは、
フォームのデータ検証結果を保持するオブジェクトのこと。



// メッセージのリストを作成して、エラーや確認メッセージを格納する準備をする
List<MessageResponse> messageList = new ArrayList<>();

// フォームから受け取ったデータを使って、同じかどうかをチェックするメソッドを呼び出し、その結果をメッセージリストに追加する
messageList.add(checkIfSame(request.getFirstAprv1(), request.getFirstAprv2(), request.getFirstAprv3()));

// メッセージリスト内の全てのメッセージが「null（何もない）」かどうかを調べる
boolean allNull = messageList.stream().allMatch(Objects::isNull);

// バリデーションエラーがあるか、またはメッセージリストに何かメッセージが入っている場合
if (result.hasErrors() || !allNull) {
    // リクエストオブジェクトにメッセージリストをセットして、エラーがある場合はフォームページに戻る
    request.setMessageList(messageList);
    return "approver-setting";
}




BindingResultは、プログラムでフォームから入力されるデータ（例えば、ユーザー名やメールアドレスなど）を受け取る際に、そのデータの正しさやエラーをチェックするための道具です。ゲームのスコア用紙のように、入力されたデータが正しいかどうかを確認し、もし間違いがあればそれを教えてくれる役割があります。

具体的には、BindingResultはフォームから送信されたデータを受け取り、それが期待通りの形式や範囲になっているかを確認します。もし問題があれば、その情報をプログラムに伝え、適切な対処ができるようにします。例えば、メールアドレスが正しい形式で入力されているか、必須項目が埋められているかなどをチェックするのに使われます。

簡単に言うと、BindingResultはプログラムが受け取ったデータが正しいかどうかをチェックする、データの検査係のようなものです。間違いや問題があればそれを教えてくれ、プログラムがスムーズに動くように手助けしてくれる大切な部品です。
CodePipelineのポーリングパイプラインが非推奨になったのでEventBridgeでS3イベントを受けてパイプラインを開始できるようにマイグレーションする


CodePipelineのポーリングパイプラインが非推奨になって以下のような警告が出るようになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/ce257667-87f3-83d6-4651-083828233057.png)


弊社のプロジェクトではGithubやCodeCommitではない外部のGitリポジトリからWebhookでS3にソースを上げていたたのですが、ポーリングは非推奨になったのでEventBridgeを経由してパイプラインを起動するように変更しました。
（ググってもCloudTrail等の事例ばかりだったので）手順を載せておきます。

## 1. S3バケットのEventBridge通知を有効にする

S3の管理コンソールに入り、該当バケットのプロパティタグを開きます。
画面真ん中の方にスクロールするとイベント通知の欄がありますので、「Amazon EventBridge」を”オン”にします。
これにより、S3のイベントがEventBridgeに飛びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140599/412a6645-e4a6-ce04-5829-034aebe25701.png)

cdkの場合は
```typescript
new s3.Bucket(scope, 'SourceBucket', {
  ...省略...
  eventBridgeEnabled: true  // ← Trueにする
});
```

でOKです。

## 2. EventBridgeのルールを定義する

以下のようにルールを定義します。eventPatternのdetailTypeは定義しないでOKです。
ポーリングではなくイベント通知とするため、S3SourceActionのtriggerプロパティはS3Trigger.EVENTSに変更します。

```typescript
// S3ソースコード配置バケット
const s3SourceBucket = Bucket.fromBucketName(this,'SourceBucket','source.bucket.name.here');

// EventBridgeのルールを定義。
new Rule(this, 'EventBridgeRuleFromPutS3', {
      description: 'Start Pipeline By S3 Put Event',
      ruleName: 'start-pipeline-execution-by-put-s3-event',
      eventPattern: {
        source: [`aws.s3`],
        resources: [s3SourceBucket.bucketArn],
        detail: {
          bucket: {
            name: [s3SourceBucket.bucketName],
          },
          object: {
            key: [
              {
                prefix: 'zipファイルのprefix'    // ← zipファイルのプレフィックスまたはzipファイル名
              }
            ]
          }
        }
      },
      targets: [
        new CodePipeline(pipeline, {
          retryAttempts: 1
        })
      ]
    });

const artifact = new Artifact('CodePipelineArtifact');
const action = new S3SourceAction({
      actionName: 'TakeTheSourceZip',
      bucket: s3SourceBucket,
      bucketKey: 'zipファイル名',       // ←zipファイル名
      output: outputArtifact,
      trigger: S3Trigger.EVENTS,      // ←トリガーはS3Trigger.EVENTS
      runOrder: 1,
    });
```

これでOKです。
誰かのお役に立てれば。
[統計基礎]~二項分布からポアソン分布を導出~

### 二項分布とは
コインの表の出現回数を数えてそれをヒストグラムで表すと二項分布になります。離散的な確率分布です。生起確率をPとすると、以下の式で表せる。
```math
P_b(x) = {}_nC_xP^xq^{n-x}
```

### ポアソン分布とは
1年間における飛行機の墜落回数など、めったに起こらない事象の出現回数を表したものです。右に裾が長い確率分布です。
```math
P_p(x) = e^{-u}\frac{u^x}{x!}
```

>説明からわかる通り、二項分布の生起確率Pを極端に下げ、試行回数nを極端に上げるとポアソン分布に近づくと直感的にわかると思います！

# 証明パート
二項分布の期待値uをu=np一定に保って、n→∞ p→0としていくと
```math
{}_nC_xP^xq^{n-x} = \frac{n!}{(n-x)! x!}p^x(1-p)^{n-x}
```
```math
= \frac{n!}{(n-x)! x!}\Big(\frac{u}{n}\Big)^x(1-\Big(\frac{u}{n}\Big))^{n-x}
```
p=u/nよりu/nを0に近づければよい
```math
= \frac{n(n-1)(n-2) ・・・(n-x+1)}{x!}\Big(\frac{u}{n}\Big)^x(1-\Big(\frac{u}{n}\Big))^{n-x}
```
```math
= \frac{n^x(1-(\frac{1}{n}))(1-(\frac{2}{n})) ・・・(1-(\frac{x}{n})+(\frac{1}{n}))}{x!}\Big(\frac{u}{n}\Big)^x(1-\Big(\frac{u}{n}\Big))^{n-x}
```
n→∞より(1-(1/n))(1-(2/n))・・・(1-(x/n)+(1/n))の分子は1に収束する
```math
= \frac{n^x}{x!}\Big(\frac{u}{n}\Big)^x(1-\Big(\frac{u}{n}\Big))^{n-x}
```
更に変形して以下のようになる
```math
= \frac{u^x}{x!}\Big(1 - \frac{u}{n}\Big)^n\Big(1 - \frac{u}{n}\Big)^{-x}
```
特に(1 - u/n)^nの変形に気をつける
```math
\Big(1 - \frac{u}{n}\Big)^n = \Bigg(\Big(1 - \frac{u}{n}\Big)^{-\frac{n}{u}}\Bigg)^{-u}
```
```math
\Big(1 - \frac{u}{n}\Big)^n = \Bigg(\Big(1 + \frac{1}{-\frac{n}{u}}\Big)^{-\frac{n}{u}}\Bigg)^{-u}
```
ネイピア数の定義を思い出し
```math
e = \lim_{n \to \pm\infty}\Big(1 + \frac{1}{n}\Big)^n
```
```math
\Big(1 - \frac{u}{n}\Big)^n = e^{-u}
```
また、(1 - u/n)^(-x)は1に収束することは明らかなので、
```math
P_b(x) = e^{-u}\frac{u^x}{x!}
```
SEが作る設計書について

## 概要

設計書関係についての知識がなく、どんな種類がありどんな内容なのかがわからなかった。
内容が分からないと書くことが出来ないため、概要だけでも簡単に理解をするために作成。

# 目次

1. **提案書**
2. **要件定義書**
3. **外部設計書（基本設計）**
4. **内部設計書（詳細設計）**
5. **プログラム設計書**
6. **テスト仕様書**

## 1．**提案書**

システムの提案を行う際に、**クライアントに対して提出する書類**が「提案書」です。
提案書を作成する最大の目的は、クライアントに**提案を採用してもらいシステム開発の案件を受注する**こと。
また、システム開発に関する基本的な事項について、**クライアントとの認識を一致させる**ことも目的の1つです。

### 提案書の内容

- **クライアントの現状・課題**
- **システム導入背景や目的、その効果について**
- **実現の方針や方法**
- **システム導入の対象となる業務範囲**
- **導入するシステムの構成や導入後の業務フロー**
- **開発プロジェクトの進めかた**
- **開発体制やスケジュール**
- **コスト見積もり**

## 2．要件定義書

提案書に基づいて作成する**クライアントと合意するための書類**です。
合意書であるため、**クライアントにも「どういったシステムなのか」を理解**してもらわなければいけません。
IT分野にくわしくない人でも理解できるように、専門用語をできるだけ使わずに記載することが必要です。

### 要件定義書の内容

- **システム化の対象となる業務**
- **システムを使った業務の全体像**
- **「ハードウェア」「ソフトウェア」「ネットワーク」の構成**
- **システムを使った業務の流れ**
- **業務を構成する作業の一覧や作業手順**
- **業務を遂行するために要求される機能**
- **セキュリティを保護するための要求事項**
- **システムに要求される性能や品質**

## 3．外部設計書（基本設計）

要件定義書を基盤にして作られた設計書。
**ユーザー向けに、システムの機能や構造についてわかりやすく記述**
しなければいけないのが特徴です。

### 外部設計書の内容

- **システムで使われるデータの種類**
- **システムに入力されるデータと入力方法**
- **データの処理方法**
- **データの保管場所や保管されるデータ**

### 項目
①システム構成仕様
-システム情報（名称・システムの目的・使用言語・DB・使用ツール・開発方法その他備考）
-稼働環境（稼働サーバー、稼働OS、稼働場所、監視、運用サイクル、バックアップ、クライアント環境、クライアント台数、その他備考）

②システム構成図

③業務フロー

④システムフロー（なくてもよい）

⑤機能一覧（機能名「大/中/小」、利用者、機能概要）

⑥画面遷移図（すべての画面を記載）

## 4．内部設計書**（詳細設計）**

外部設計書を基に作られた設計書。
**設計者は内部設計書に基づいてプログラム設計を行う**
ため、より詳細に作成されるのが特徴です。

### 内部設計書の内容

- **ソフトウェアの動作や処理**
- **ソフトウェアの構造**
- **ソフトウェア間でのデータの受け渡し方法**

### 項目

①機能概要（機能前提、処理フロー、データIO）
②画面設計（画面イメージ、名称、タイプ、桁数、文字種、I/O、非表示、活性、必須、初期値、フォーマット、備考）
③機能仕様（アプリ画面処理、クライアント処理、サーバー処理）

## 5．プログラム設計書

**コーディングの基盤として作成する設計書**です。

### プログラム設計書の内容

- **モジュールの処理内容や動作内容**
- **入力データ、出力データ**
- **データ内容全般**

### プログラム設計書があることにより

①****スムーズなプログラミング作業の実現****

プログラム設計書を読み込むことで

- 着手前に完成後のシステムをイメージできる
- 作業手順や記述すべきコードをスムーズに理解できる
- 調査や調整が減りプログラミングに集中できる
- 情報共有・進捗状況の共有が容易となる

②****エラーの防止****

プログラム設計書が存在しない状態でプログラミングを行うと、プログラマ個人の裁量でコードを書く部分が発生し、設計者が意図しないコードや無駄なコードを書いてしまう可能性があります。

③****保守管理の負担軽減****

プログラム設計書があれば、システムの仕様やソースコードを瞬時に理解できるため、障害調査・障害対応もスムーズに行うことができます。

開発に携わったメンバーと、保守管理に携わるメンバーは一致しないことも多く、たとえ同一メンバーであったとしても、過去のシステムの仕様やソースコードはまず覚えていないでしょう。そのため、プログラム設計書が無いと、軽微な修正や些細な障害でも膨大な時間と労力が必要となる場合があります。

## 6．テスト仕様書

システムを実装した後に**どのようなテストを行うかを記載した書類。**
プログラミング設計書通りに実装した**プログラムに問題がないかどうかを確認**
するための仕様書です。
【Rails】saveとsave!の挙動の違い


Ruby on RailsのActiveRecordで使われるsaveとsave!。この二つのメソッドの違いについて、改めて学習した内容をメモとして記録しておきます。


## saveメソッド
- Ruby on RailsのActiveRecordで扱うメソッド。
- データベースへの保存を試みるメソッドである。
- `save`と`save!`の２種類がある。
- `「!」`は、日本語では`感嘆符`、カッコよく言うと`エクスクラメーションマーク`と呼ぶ。
- ビックリマークとは呼ばないww


## saveとsave!
- `save`と`save!`両メソッドは一見同じように思えるが、その挙動には違いがある。
- 両者の違いは、保存に失敗したときの挙動にある。
    - `save`は、バリデーションに失敗するとfalseを返す。
    - `save!`は、バリデーションに失敗すると`ActiveRecord::RecordInvalid`という例外を発生させる。
- `save!`はエラーを厳しくチェックするバージョンの`save`だと言える。


## コード間違い例

```ruby
class PostsController < ApplicationController
  def index
    @posts = Post.all
  end

  def create
    @post = Post.new(post_params)
    if @post.save! #ここに注目
      redirect_to @post
    else
      render :new
    end
  end

  private

  def post_params
    params.require(:post).permit(:title, :content)
  end
end
```


- 投稿を保存する`PostsController`のコードの一部。
- `create`メソッドにおいて新しい投稿(Post)を作成し、データベースへの保存を試みている。
- `if`文を用いて、保存が成功した場合は投稿したpostの画面に遷移させている。
- 保存に失敗した場合には、`render :new`によって、postの新規作成画面に戻るように指示している。
- ここで、注目すべきなのが、`if @post.save`である。
- `if`文を使って、成功した場合、失敗した場合、両方の真偽値に応じた挙動を支持するところなのだが、`save!`メソッドの場合、保存失敗は例外を返すという特徴があるため、`else`の次の`render :new`が実行されずに例外処理が実行されてしまう。
- そのため、今回の例においては、以下のように`save!`メソッドではなく、`save`メソッドを用いるのが良い。

## コード正解例

```ruby
  def create
    @post = Post.new(post_params)
    if @post.save # この場合「save!」ではなくこっちが正解
      redirect_to @post
    else
      render :new
    end
  end
```

## 参考サイト

https://goruchanchan.hatenablog.com/entry/2022/09/20/232524

https://qiita.com/kidokoro-syusei/items/a7ebefe4a1b006db15f1
MongoDBの3台構成レプリケーションがぶっ壊れて直した話

# はじめに
あくまでも「私の環境はこれでどうにかなりました」というお話なので、全ての環境に適用できるものではないと思っております。ご理解ください。
本記事に出てくる用語等に誤りがあったらすみません。

# この物語の舞台
+ 背景
他社で作成されたスマートフォンアプリを移譲されることになり、それに伴う形でレプリケーション3台構成のMongoDB（PRIMARY×1台、SECONDARY×2台）の管理が必要となったことから解析作業を依頼された。

+ 環境
AWS上のLinuxに構築された上記MongoDBの入った3台のサーバ（本番環境と呼称）を、さらにコピーしてデプロイされた検証環境。
本番環境の設定を持ったままIPアドレスの異なるサーバとしてデプロイされたためレプリケーションがぶっ壊れた。（多分）

+ 筆者
この作業を依頼された時点でMongoDBの知見は一切ない。
今もあんまりない。

# 困ったこと
+ DB内の情報を検索することができない。
Mongoシェルにて`db.XXX.find`で検索をかけた際に下記のようなエラーメッセージが出力された。
```
Error: error: {
	"ok" : 0,
	"errmsg" : "not master and slaveOk=false",
	"code" : 13435,
	"codeName" : "NotPrimaryNoSecondaryOk"
}
```
ここから「レプリケーションが壊れてるっぽい」と推測し、調査を開始した。
Mongoシェルにて`rs.conf()`を打ったところ、やはり現在のサーバとは異なるIPアドレスがhostとして登録されていた。

+ 全サーバが「OTHER」になっており、レプリカセットを編集できない。
「レプリカセットの修正が必要そうだ」というところまではなんとか漕ぎつけたものの、レプリカセットの編集にはPRIMARYの権限が必要であるため修正ができない。
サーバ側のIPアドレスを変えようにもレプリカセットに設定されているIPアドレスは本番環境が保有し稼働し続けていたため奪取できなかった。

# やったこと
+ 現在のレプリカセットを削除した
レプリカセットの設定を削除するため、本来PRIMARYとなるサーバ（以下Pサーバ）にて`/etc/mongod.conf`に記載されていた下記2行をコメントアウト。
```
replication:
  replSetName: "XXX"
```
さらに一度`systemctl restart mongod`コマンドでMongoDBを再起動したのち、`mongo`コマンドでmongoシェルを起動しlocalに残っているレプリカセットの設定を削除した。
```
> use local;
> db.dropDatabase();
```
ちなみにこのmongoシェル起動の時点で`OTHER`の表示が消えていた。
レプリカセットの削除後は`exit`でmongoシェルを抜け、再度`systemctl restart mongod`コマンドでMongoDBを再起動した。

##### 参考記事
https://qiita.com/FumiyaShibusawa/items/d01170de29520a8f25a6


+ 今のIPアドレスをレプリカセットとして登録した
Pサーバにて先程修正した`/etc/mongod.conf`を再度修正し、追加したコメントアウトを解除した。
その後再度mongoシェルを起動し、下記コマンドでレプリカセットの設定を投入した。
```
> config = { _id : "example01",members: [{ _id: 0, host: "XXX.XXX.XXX.XXX:27017" },{ _id: 1, host: "XXX.XXX.XXX.YYY:27017" },{ _id: 2, host: "XXX.XXX.XXX.ZZZ:27017" },]}
```
さらに、ここまでの全ての作業をSECONDARYとなる2台（以下S1サーバ、S2サーバ）にも適用した。

その後、P1サーバのmongoシェルにて下記コマンドを実行し、実行直後から`PRIMARY>`や`SECONDARY>`の表示がされれば成功。（多分）
```
> rs.initiate(config)
{ "ok" : 1 }
```

+ 念のためS1・S2サーバのMongoDBを再起動
PサーバをPRIMARYに、S1・S2サーバをSECONDARYとするためにS1・S2サーバそれぞれで`systemctl stop mongod`コマンドを実行し一旦両方のMongoDBが停止している状態にした。
その後、S1サーバ→S2サーバの順に`systemctl start mongod`コマンドでMongoDBを起動させた。
正直この作業は不要だったかもしれない。

# 余談
`systemctl start mongod`コマンドや`systemctl restart mongod`コマンドでMongoDBを起動・再起動させようとした際にエラーが発生し起動できないことがある。

再起動が失敗した際は`systemctl stop mongod`コマンドと`systemctl start mongod`コマンドを順番に実行することで正常に動くことがある。

また、`systemctl start mongod`コマンドが動かない場合は`/tmp/mongodb-27017.sock`というファイルを削除することで正常に動くようになる。

このファイルはMongoDB起動時に作成され停止時に削除されるため、残ったままの状態だとMongoDBが起動しなくなる。らしい。
mongoシェルの起動時に`mongo`コマンドと間違えて`mongod`コマンドを実行したりすると作成される。らしい。

# 最後に
「検証環境だから全然ぶっ壊してもいいんで、ガンガンやっちゃってください」というコメントと共に受け取った環境でのお話のためガンガン行ってます。
一応動き出した後にDB内の検索は上手く行くようになったので多分大丈夫とは思いますが、本当にこれでいいのかな。なんか知らんけど動いてる。こえー。
【Python】isinstance関数の使い方 & type関数との違いとは？

# 概要
`if isinstance`の使い方、また、`type`関数との違いをまとめました。

# サンプルコード解説

```py
def process_data(data):
    if isinstance(data, list):
        total = sum(data)
        return total
    else:
        return "Invalid input data"

data1 = [10, 20, 30, 40, 50]
data2 = "This is not a list"

result1 = process_data(data1)
result2 = process_data(data2)

print(result1)
# 150
print(result2)
# Invalid input data
```

### 基本構文

`isinstance()`関数の基本構文は以下の通りです:

```python
isinstance(object, classinfo)
```

- `object`: 型を調べたいオブジェクトを指定
- `classinfo`: クラスやデータ型を指定

`object`が`classinfo`に指定されたクラスやデータ型に属していれば`True`を返し、属していなければ`False`を返します。上記サンプルコードの例では`list`を指定しているので、`list`であれば合計値（`total = sum(data)`)が返され、そうでなければ`"Invalid input data"`が返されます。

ちなみに以下のようにして、複数の型を指定することもできます。
以下はタプルかリストで指定しており、どちらかであれば`True`が返されます。

```py
    if isinstance(data, (list, tuple)):
```

## `type`関数との違いは？

`isinstance()`は継承関係を考慮して型をチェックするのに対し、`type()`はオブジェクトの型そのものを返す関数なので、サブクラスまで考慮したい場合は`isinstance()`を使うのが良いです。

例えば、以下のコードの場合。

```python
class Fruit:
    pass

class Apple(Fruit):
    pass

obj_fruit = Fruit()
obj_apple = Apple()

print(isinstance(obj_fruit, Apple))  # False
print(type(obj_fruit) == Apple)      # False

print(isinstance(obj_apple, Fruit))  # True
print(type(obj_apple) == Fruit)      # False
```

`obj_fruit`の方はどちらも`False`を返します。これは、`obj_fruit`の型が厳密には`Fruit`クラスであり、`Apple`クラスではないためです。

`obj_apple`の方では、`isinstance(obj_apple, Fruit)`で`True`を返しますが、`type(obj_apple) == Fruit`では`False`を返します。`obj_apple`の型が厳密には`Apple` クラスであり、`Fruit`クラスではないと判断されていることがわかります。サブクラスまで考慮したいかどうかで使い分けると良いですね。
DetaSpaceにデプロイ中に生じたcorsエラー

# TL;DR
バックエンドの`Spacefile`の`public: true`を付与すれば良い．
```yaml
v: 0
micros:
  - name: back
    src: ./
    engine: python3.9
    public: true
    primary: true
    run: uvicorn main:app --port 8080
    dev: .env/bin/uvicorn main:app --reload --host 0.0.0.0 --port 8080
```

# 自己紹介
こんにちは．しがない大学生です．普段つまらない個人アプリを制作し，特にアウトプットは普段しない人です．
ですが，Herokuの有料化に伴い，何か無料デプロイ先ないかな〜って感じで見てたら，Deta Spaceというものを見つけたので，Deta Space上にウェブアプリを作成してました．普段なら，先駆者様がたくさんQiitaやZennにいらしたので，その恩恵をチュルチュル吸ってアプリを作成するだけで終わっていました．しかし，このDeta Spaceというものが2023年2月14日にDeta Cloudから変更したもので，仕様が変わってしまったせいか分かりませんが，日本語の記事があまり見つからなかったので，いっそのとこ記事を書いてみようかなと思い，筆をとってみた感じです．  
また，Qiita初投稿であることと，プログラミングに限らず，自然言語が苦手なので，おかしなIT知識や，おかしな日本語についてはご指摘いただけるとありがたいです．

# 状況
- Reactでフロントを構築し，FastAPIでバックを構築する．
- 両者ともDeta Space上でそれぞれfront, backという名前でデプロイする予定．
- フロント(React)側ではProxyの設定なども確認した．
- バック(FastAPI)側では`CORSMiddleware`的なものは実装した．
- フロント，バック両者とも`space dev`(開発環境)ではAPIが問題なく叩けている．
# 問題
**バックを本番環境に上げたとき(`space push`)に**CORSエラー(`Access to XMLHttpRequest at 'https://******' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
`)が起きてしまう．
# 解決策までの試行錯誤
1. バックのCORS設定を見直す．→originを全て許可にしているので問題はないだろう．
1. フロントのCORS設定を知らなかったので色々試す．→何も変わらず．
1. そもそもデプロイしたバックで何が起きてるのか`curl`コマンドで試す．→どうやら認証的なステップが踏まれている．
1. スマホ端末からバックのAPIを触ってみる．→Deta Spaceの認証ステップが踏まれている．
1. もしかしてAPIを公開できていないかも．設定ファイル(`Spacefile`)とドキュメントを照らし合わせよう．→以下の解決策に至る．
# 解決策
バックエンドの`Spacefile`の`public: true`を付与すれば良い．
```yaml
v: 0
micros:
  - name: back
    src: ./
    engine: python3.9
    public: true
    primary: true
    run: uvicorn main:app --port 8080
    dev: .env/bin/uvicorn main:app --reload --host 0.0.0.0 --port 8080
```
# 感想
「本番環境では動かない」という対照実験の結果から，フロントとバックのCORSではなく，開発/本番環境の違いに近い設定ファイル(`Spacefile`)を早くみるべきだった．  
あと，使っているReactのバージョンだったり，PCのスペックだったり，色々書いた方が良いんでしょうが，そこまでやる元気が起きなかった．また，問題のあるコードや，関連のあるコード，実際にフロントからどのように映っているかの写真なども付与すると，丁寧だと思った．
これからも少しずつアウトプットすることで，分かりやすい記事を書けるようになりたい．
# 参考文献
https://deta.space/docs/en
https://qiita.com/kakiuchis/items/80f6239f6319066ee18d
【クエリビルダ】LaravelにおけるRead（データ取得）処理

Laravelで、モデルのデータを取得して画面に表示したいとき、いくつかのメソッドが用意されている。

ざっくりと、
1レコードを取得したいとき：first();
複数レコードを取得したいとき：get();で取得しforeachで出力する。
1件しかレコードがないテーブルのデータを取ってくるときも、どのメソッドで取ってくるかで、オブジェクトか配列か、データ形式が異なるので、用途に合わせて使う。

## first();
モデルの最初のレコードを、**オブジェクト**形式で取得する。

## find();
引数にidを指定して、特定のレコードを、**オブジェクト**形式で取得する。

## get();
モデルのレコードを、**コレクション**(配列と思っていい)形式で取得する。
配列なので、取得した値はforeachで回して出力する。
whereを使って絞り込み検索などもできる。
```index.php
$user = User::where('name', 'tarou')->get();
dd($user);
```

```index2.php
$users=User::whereIn('phone', [0, 1])->get();
return view('user.index', compact('users'));
```
※whereInは、指定した値が「含まれている」（部分一致）レコードを取得。条件を配列形式で指定。

## all();
モデルのレコードを、全件、**コレクション**形式で取得する。
配列なので、取得した値はforeachで回して出力する。
```controller.php
$users = User::all();
return view('user.index', compact('users'));
```
```blade.php
@foreach($users as $user)
  <table>
    <tr>
      <td>{{$user->name}}</td>
      <td>{{$user->email}}</td>
    </tr>
  </table>
@endforeach
```

## ※get();とall();は、->toArray();で、配列に変換できる。
```index.php
$user = User::all();
$userArray = $user->toArray();
```

## 条件検索の場合はget()
クエリビルダでは、条件をかけてSQLを実行する場合、get()を使う。
全件取得でも条件がかけられていれば、all()ではなくget()。
【ちょっと便利な小技_part 5】Visual Studio Codeでflutter開発(Extract Widget編)

## Extract Widgetでクラス化＆切り出し
今回はExtract Widgetについて
下記画像のMore Extract...にある『**Extract Widget**』は
Widgetを１つのクラスとして切り出してくれます。
方法はとても簡単なのでぜひやってみてください。

# 方法
クラス化したいWidgetにカーソルを合わせて
『cmd』＋『.』(Mac)
を選択します。
すると下記の画像のようになります。
![スクリーンショット 2023-08-17 17.06.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524075/dc13b656-919d-0c67-8bca-992ddbf30701.png)

次にExtract Widgetを選択するとクラス名の入力欄が出てきます。
そこに任意のクラス名を入力してEnterを押します。
これで完了
![スクリーンショット 2023-08-17 17.36.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524075/3cb111b9-de11-0688-7a73-fa57fd5a5e93.png)

## 結果
このようにクラス化して切り出してくれます。
![スクリーンショット 2023-08-17 17.37.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524075/bf7181b1-44c4-d2db-0c88-ffc6733e200d.png)
【AWS】SAPro更新してきた

# はじめに

新卒1年目で初めて敗北を味わった宿敵と3年ぶりに戦ってきたので感想だけ
[1年目のころの記事](https://qiita.com/TS_Koike/items/71b1e63ae2eee57b6c2b)

# 結果

スコア落ちた…

| # | 日付 | スコア | 合否 |
| :------: | :------: | :---------: | :------: |
| 1回目 | 2020/07/26 | 730 | × |
| 2回目 | 2020/08/15 | 819 | 〇 |
| 3回目 | 2023/08/10 | 810 | 〇 |

# 感想

- 最新のサービス
    - 昔はよく見たOpsWorks、Beanstalkはほぼなくなってました！（苦手だったからうれしいｗ）
    - ちゃんとIAM Identity Centerという表記になっていたし、これでもできるやろ！ってものもなくなってたと思います
- 分野
    - 体感だとこんな感じ
        - 多い
            - ネットワーク
            - Organizations系
        - 少な目？
            - ウェブアーキテクチャ系（体感かなり減った）
        - その他ざっくばらんに出てくる感じ
    - IoTの問題がちょいちょい出てて絶望しましたｗ
        - SAP on AWSよりIoT Specialtyにしてほしかったなぁ…

なにはともあれ、合格してよかったです！
めっちゃむずくなってる印象でしたｗ

新卒のAWSエンジニアの方は、案件にアサインされる前にアソシエイト3つとSAProを取っておくとつらい思いをしなくて済むと思うので、最初のうちに頑張って取っちゃいましょう！！