OmniAICreator/Qiita-1.07M huggingface dataset:
LTスライドをmarpで作ってみた


# 1. 背景
私は今までLTで登壇したことがありません
直近でLTスライドを作る必要があリました

スライドの作り方が分からず調べたところ[marp](https://marp.app/#get-started)に出会いました

https://qiita.com/tomoasleep/items/604107787d92dec4868e

# 2. VSCodeでのMarpの使い方

## 2.1. 拡張機能をinstall

https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode

## 2.2. mdファイルを作成する
```md
---
title: 記事のアウトプットは業務に生きてくる
author: yamatai12
slide: true
marp: true
---

# 1スライド目

1スライド目の内容

---

# 2スライド目

2スライド目の内容

---

```

`marp: true`にするとVSCodeでプレビューが見ることができます！

## 2.3. exportする

「Command Palette」から「Marp Export Slide Deck」を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/6e64f496-a440-8ae0-da7f-c47db0b0b859.png)

formatは以下です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/286a1559-95ec-0732-fa19-5f17669ad62e.png)

具体的な記法等は以下を参考にしました

https://qiita.com/tomoasleep/items/604107787d92dec4868e

https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode

今回私がmarpで作ったスライドは以下です

https://t.co/n6LqxE90so

リポジトリは💁[こちら](https://github.com/yamatai12/marp-slide)です

# 3. その他 LT登壇する前に読んて勉強になった記事

エンジニアが技術登壇する時に考えるべき事

https://dev.classmethod.jp/articles/presentation-basics/

# 4. 最後に
- marpでサクッとスライドを作れました
- デザインにこだわるともう少し記法について調べる必要が出てくる気がしました

本記事を読んで頂き、ありがとうございました。
いいねいただけると記事執筆の励みになりますので、参考になったと思われた方は是非よろしくお願い致します🙏
【チャットAI】OpenAIのChatGPTとGoogleのGeminiを比較してみた

# 1.はじめに
業務でチャット型AIを使用する機会が増えてきたので、ユーザー目線からChatGPTとGeminiの比較をまとめていこうと思います。どちらもブラウザ版での比較になります。なお、2024年4月20日時点の情報なので、今後変更される可能性があります。

# 2.仕様の大きな違い
## 2.1入力できる情報の種類
Gemini：テキスト、画像、音声、ビデオなどの情報を処理できます。
ChatGPT：テキスト情報のみを処理できます。
## 2.2情報収集の方法
Gemini：ブラウザを経由してGoogleの検索エンジンを利用するため、最新の情報にアクセスすることが可能です。
ChatGPT：ある時点で同期された情報を取得するため、必ずしも最新の情報ではありません。
## 2.3データソースのURLの有無
Gemini：有
ChatGPT：無(ただし、ソースの開示を指示した場合はこの限りではありません。)
## 2.4アカウントについて
Gemini：Googleアカウントが必要
ChatGPT：登録不要

# 3.まとめ
今回は、ブラウザ版のGeminiとChatGPTの比較を簡潔に行いました。
もっと細かい違いなどはありますが、ユーザー目線としては以上が大きく影響してくると思います。
個人的な所感としては、常に最新の情報を提供してくれる点、デフォルトでデータソースを提示してくれる点などから、Geminiの方が使いやすいと感じました。
ただし、ChatGPTはアカウントが不要な点から、気軽に情報収取できる点が良いと感じました。
CAD Step File

# Step
## 概要
STEP ファイル (Standard for the Exchange of Product model data) は、国際標準の 3D CAD ファイル形式です。

## API
STEPファイルを解析し、処理するための一般的な方法として、次のような方法があります：
1. Open CASCADE Technology (OCCT)：OCCTは、多くのCAD/CAM/CAEアプリケーションで使用されているオープンソースのCADツールキットです。STEPファイルの読み込みや処理を行う機能が含まれています。https://www.opencascade.com
2. CAD Exchanger SDK：CAD Exchanger SDKは商用のCADファイル処理ツールで、STEPファイルの読み込みや書き出し、変換を行うためのAPIを提供しています。https://cadexchanger.com
3. The STEPcode Project：STEPcodeプロジェクトは、STEPファイルの解析や処理を行うためのオープンソースのライブラリです。C++で実装されており、多くのプラットフォームと言語で利用できます。https://github.com/stepcode/stepcode
4. FreeCAD：FreeCADは、オープンソースの3D CADモデリングソフトウェアであり、Pythonスクリプトを使用してSTEPファイルを読み込んで処理することができます。https://www.freecadweb.org
【Python】TkinterでLaTeXをレンダリングする

# はじめに

matplotlibを使ってtkinterにLaTeXをレンダリングする方法を紹介します。

## この記事の対象者

- ある程度Pythonの知識があり、tkinterにLaTeXをレンダリングしたい。

## 前提知識

- 基本的なPythonの記法と仕様を理解している
- tkinterの基本的な使い方を知っている

# 実装

## 実際のコード

```python: main.py
import tkinter as tk

import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

matplotlib.use('TkAgg')
root = tk.Tk()

fig = Figure(figsize=(5, 4), dpi=100)
ax = fig.add_subplot(111)
ax.text(0.5, 0.5, r'$x^2$', fontsize=50, horizontalalignment='center', verticalalignment='center')
ax.set_axis_off()

canvas = FigureCanvasTkAgg(fig, master=root)
canvas.draw()
canvas.get_tk_widget().pack()

root.mainloop()
```

## 解説

```python
import tkinter as tk

import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
```
必要なライブラリをインポートします。tkinterはウィンドウの作成、matplotlibはLaTeXのレンダリングに使います。

```python
matplotlib.use('TkAgg')
```
matplotlibでtkinterのバックエンドを使用するように設定しています。

```python
root = tk.Tk()
```
tkinterの親ウィンドウ(ルートウィンドウ)を作成しています。ルートウィンドウは他のウィジェットを配置する基礎となります。

```python
fig = Figure(figsize=(5, 4), dpi=100)
```
matplotlibの`Figure`オブジェクトを作成しています。`figsize`はFigureの大きさ(インチ)を指定し、dpiは解像度(ドット/インチ)を指定しています。

```python
ax = fig.add_subplot(111)
```
`Figure`オブジェクトに1つのサブプロットを追加しています。`add_subplot(111)`は1行1列のサブプロットレイアウトで最初(唯一)のサブプロットを作成することを意味します。

```python
ax.text(0.5, 0.5, r'$x^2$', fontsize=50, horizontalalignment='center', verticalalignment='center')
```
サブプロットの中央に`"$x^2$"`($x^2$)という数式を描画します。この文字列を変えることで任意の数式を描画できます。
`text()`関数は特定の位置にテキストを配置するために使用されます。`fontsize`でテキストのサイズを指定します。`horizontalalignment`と`verticalalignment`はテキストの水平方向と垂直方向の配置を指定します。

```python
ax.set_axis_off()
```
サブプロットの軸(x軸とy軸)を非表示にします。

```python
canvas = FigureCanvasTkAgg(fig, master=root)
```
matplotlibの`Figure`オブジェクトをtkinterの`Canvas`ウィジェットにマッピングするための`FigureCanvasTkAgg`オブジェクトを作成します。`master=root`はこのキャンバスがルートウィンドウに配置されることを意味します。

```python
canvas.draw()
```
作成した`FigureCanvasTkAgg`オブジェクトにグラフの描画を行います。

```python
canvas.get_tk_widget().pack()
```
tkinterの`Canvas`ウィジェットをルートウィンドウに配置します。`pack()`はウィジェットをウィンドウに配置するための関数です。代わりに`grid()`や`place()`を使って配置することもできます。

```python
root.mainloop()
```
Tkinter のメインループを開始します。これによってウィンドウが表示されます。


# 終わりに

最後まで読んで頂きありがとうございます。不備があれば是非コメントで指摘して下さい。
PHP 具象クラス(Abstract class) について

# 具象クラス(Abstract class) について

- 抽象(Abstract)クラスは `class`の前に `abstract`を付ける。
- `abstract`クラス内でも普通に `public`メソッドとしても定義することは可能。
- 抽象メソッドを定義する場合は、`abstract public function getProduct();`というように先頭に `abstract`を付ける。
- abstractメソッドの場合、メソッド内に処理を書くことはできない。メソッド名のみの定義になる。
- 抽象クラスに対してインスタンス化できるクラスを `具象クラス` という。sampleの場合は `BaseProduct class` と `Product class`がインスタンス化できるので `具象クラス`になる。
- 具象クラスでは Abstractクラスを継承すると、必ず abstractメソッドを使用しなくてはならなくなる。使用しない場合は、エラーになる。

__●__ `abstract` クラスを利用した例

```php:sample.php
<?php

// 抽象クラス
abstract class ProductAbstract
{
    public function echoProduct() // 普通にpublicとしても使うことができる
    {
        echo '親クラスです';
    }

    // 先頭にabstractと付けると抽象メソッドになる
    abstract public function getProduct(); // abstractにするとメソッド名しか定義できない
}

// 具象クラス、親クラス・基底クラス・スーパークラス
class BaseProduct
{
    public function echoProduct()
    {
        echo '親クラスです';
    }

    public function getProduct()
    {
        echo '親の関数です';
    }
}

// 具象クラス、子クラス
class Product extends ProductAbstract // 抽象クラスのProductAbstractを継承
{
    private $product = [];

    function __construct($product)
    {
        $this->product = $product;
    }

    // 抽象クラスを継承した場合、抽象メソッドを使用しなくてはならない。使用していない場合はエラーになる
    public function getProduct()　// 具象化
    {
        echo $this->product;
    }

    public function addProduct($item)
    {
        $this->product .= $item;
    }

    // staticは静的関数
    public static function getStaticProduct($str)
    {
        echo $str;
    }
}

$instance = new Product('テスト');

var_dump($instance);

echo '<br>';

$instance->getProduct();
echo '<br>';

$instance->echoProduct();
echo '<br>';

$instance->addProduct('追加分');
echo '<br>';

$instance->getProduct();
echo '<br>';

Product::getStaticProduct('静的');
echo '<br>';
```
その処理本当にそこに書くべきなの？

## 神はなぜ生まれるのか

スタートアップでは、変化についていくために開発スピードを早める必要があります。開発スピードを早めるためには、DDDのような設計やレイヤードアーキテクチャのようなアーキテクチャ設計を行う必要があります。

コントローラーが肥大化し、よく使う処理を関数化したくなることがあります。しかし、ルールがないために共通処理を作成するクラスの場所がわからないこともあります。とりあえず共通処理を書くクラスを作成することで、神が生まれました。

## 神は我々に何をもたらすのか

神は何でも知っているため、何でも教えてくれたり解決してくれたりします。しかし、神は次第に肥大化し、手に負えない存在になってしまいます。神の力を得るためには、目的の力にたどり着くために1,000行や2,000行のソースコードを読まなければならないこともあります。

偉大な神の存在は、実際には技術的負債となることもあります。

## 神はどのようにすればよいのか

肥大化したクラスは取り扱いが難しく、メンテナンスも困難です。そのようになったら、神の分化を始めましょう。分化の単位は責務ごとに行います。例えば、長さのコンバート処理と画像のコンバート処理は責務が異なるため、それぞれ別のクラスに分けるべきです。

## 神を作る前に立ち止まってみよう

クラスが肥大化することを防ぐためには、いくつかの方法があります。まずは、関数を作成することをやめて、思考を停止しましょう。クラスを触る際や作成する際には、一度立ち止まって考えることが重要です。

既存のクラスに処理を追加する際には、注意が必要です。例えば、長さのコンバート処理をしているクラスに画像のコンバートを追加しないようにすることが重要です。同じコンバートという括りでも、クラスを分けることでクラスの肥大化を防ぐことができます。また、クラスを作成する際も、コンバートという抽象的な名前ではなく、長さのコンバートクラスや画像のコンバートクラスなど具体的なクラス名を付けることも肥大化を防ぐ手段となります。

## 本当に神は悪なのか

神クラスはある程度のスピードが求められるスタートアップにおいては避けられない場合もあります。DDDやクリーンアーキテクチャの実施は困難かもしれません。しかし、クリーンアーキテクチャではなくとも、ある程度のアーキテクチャを設計して実施することで、神クラスを生み出すことは避けられます。処理を一つにまとめることは便利ですが、諸刃の剣であることは間違いありません。スピード感のある開発の中で、神クラスを作らないように心掛けましょう。
Windows11でWindowsAppsフォルダに入れない

WindowsAppフォルダに入れなかったので、Copilot先生に聞いた内容をそのままメモしておきます。
(Windows11って、つくづく使いずらいシステムよな。。)

WindowsAppsフォルダにアクセスするには、特定の手順を踏む必要があります。通常、このフォルダは隠されており、システムによって保護されているため、直接開くことはできません。アクセスするためには、以下の手順を試してみてください：

1. エクスプローラーを開き、表示タブをクリックします。
1. 隠しファイルのチェックボックスをオンにして、隠されたファイルを表示します。
1. C:\Program Files\WindowsApps に移動しますが、アクセス許可が拒否されることがあります。
1. アクセス許可が拒否された場合は、プロパティを開き、セキュリティタブをクリックします。
1. 詳細設定ボタンを押し、所有者を確認します。通常はTrustedInstallerが所有者になっています。
1. 所有者を変更するには、変更リンクをクリックし、あなたのユーザー名を入力してください。
1. 所有者を変更した後、必要なアクセス権を得ることができます。

ただし、このフォルダはWindowsの重要なシステムファイルを含んでいるため、不用意に変更を加えるとシステムに影響を及ぼす可能性があります。変更を加える前には、十分な知識と理解が必要です。また、作業が完了したら、所有者をTrustedInstallerに戻すことを忘れないでください。

もし不明な点があれば、さらにサポートを提供できますので、お知らせください。安全に作業を進めるためにも、正しい手順を踏むことが重要です。
【Flutter】Privacy Manifests対応：審査通過まで

# はじめに
本記事は、Apple Storeに公開済みのFlutterアプリにおいて、Privacy Manifests対応を実施し、審査通過した記録記事となります。


# Privacy Manifests とは
プライバシーマニフェストは、アプリやSDKがどんなデータを収集して、どういう理由で使うのかを明記したプロパティリスト、だと私は解釈しています。

詳細は割愛しますが、以下の「サードパーティ SDK 要件」

https://developer.apple.com/support/third-party-SDK-requirements/

および「プライバシー マニフェスト ファイル」をご確認ください。

https://developer.apple.com/documentation/bundleresources/privacy_manifest_files


# 前提
2024年3月に審査提出した際、以下の警告メール（ITMS-91053: Missing API declaration）を受け取っていました。
![スクリーンショット 2024-04-20 14.24.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507831/67a9da87-99ec-e5a3-aa7e-74495285d963.png)

受け取ったメールによれば、対象APIは以下の４つでした。
・NSPrivacyAccessedAPICategoryFileTimestamp
・NSPrivacyAccessedAPICategoryDiskSpace
・NSPrivacyAccessedAPICategorySystemBootTime
・NSPrivacyAccessedAPICategoryUserDefaults


# 対応 その１
**Flutter本体およびパッケージを最新化**

アプリを初期リリースしてから、半年以上バージョンは変更しておりませんでした。
採用している対象パッケージがプライバシーマニフェストに対応しているかを確認した上で、以下のように最新化しました。

・Flutter : 3.13.1 → 3.19.5
・path_provider : 2.1.1 → 2.1.3
・sqflite : 2.2.6 → 2.3.3
・url_launcher : 6.1.4 → 6.2.6
・package_info_plus : 4.1.0 → 7.0.0


# 対応 その２
**Xcodeで PrivacyInfo.xcprivacy を作成し、理由を設定**

警告メールによれば、４つのAPIについて理由が必要とのことで、
アプリの要件に基づき、以下のように設定しました。


![スクリーンショット 2024-04-20 14.50.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507831/2ce6bbe7-69eb-019b-75cc-9f97013f3e52.png)

理由（Privacy Accessed API Reasons）は、アプリ要件によって変わる部分ですので、
以下を参照し、適切な理由を選択しましょう。

https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api


# 結果
審査提出後、警告メールを受け取ることなく、無事審査通過できました。

（執筆時点では、まだ2024年5月になっていないのため審査通過は当然ですが、警告メールを排除できたことが大きい）
Next.jsでフォントを設定する

## 初めに
Next.jsの最新バージョンでのフォントの設定についてです。説明しているサイトが少なかったので忘備録として残します。

## 注意事項
プログラミング初心者の記事になります。明らかな誤りがある際にはコメントいただけると幸いです。

## 結論
まずは簡単に設定手順を記します。

1. font.tsを作成する
1. `next/font/google`から使用するファントの種類をインポート
1. 任意のファイルで呼び出す

以下詳しい設定方法です。

### font.tsの作成

まずは好きな場所にfont.tsを作成してください。
今回はappディレクトリ配下にそのまま設置しましたが、uiファイルを作成してもいいかもです。

![スクリーンショット 2024-04-20 14.46.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2918094/be551961-51d5-deaf-3d61-830d46ead686.png)

### `next/font/google`から使用するファントの種類をインポート

使用するフォントを読み込んでください。今回はお試し用なので`Inter, Lusitana, Montserrat, Noto_Sans_JP`といろいろ読み込んでみました。

読み込んだフォントは変数にして、読み込む内容を設定してあげてください。Variable fonts でない場合は weight の指定が必須です。

```
// src/app/fonts.ts

import { Inter, Lusitana, Montserrat, Noto_Sans_JP } from 'next/font/google';

export const inter = Inter({ subsets: ['latin'] });

export const lusitana = Lusitana({
  weight: ['400', '700'],
  subsets: ['latin'],
});

export const montserrat = Montserrat({
  weight: ['400', '500', '700'],
  subsets: ['latin'],
});

export const notoSansJP = Noto_Sans_JP({
  subsets: ['latin'],
  variable: '--font-noto-sans-jp',
});
```

### 任意のファイルで呼び出す
`import { notoSansJP } from '@/app/fonts';`で必要なフォントを呼び出して、`className=${notoSansJP.className}`で設定したい要素に記載しています。今回はbodyタグで画面全体に使用していますが、細かいフォント設定も可能です。

```
import { notoSansJP } from '@/app/fonts';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="ja">
      <body className={`${notoSansJP.className} flex flex-col min-h-screen`}>
        {children}
      </body>
    </html>
  );
}

```

## 最後に
この記事は以下のサイトを参考にしています。

https://chocolat5.com/tips/nextjs-13-next-font/

https://nextjs.org/learn/dashboard-app/optimizing-fonts-images
この問題解けますか？ | React における state ・useState についての基本

React 公式ドキュメントを読んでいて state・useState についての理解が深まったので共有します
この記事はすべて React 公式ドキュメントの内容です。 
わかりにくい部分があれば公式ドキュメントを読むことおすすめします。

# この問題解けますか？  

https://ja.react.dev/learn/queueing-a-series-of-state-updates#challenges

以下のチャレンジ問題が state の理解に役に立ちました

問題文（公式ドキュメントの引用）
>あなたは、ユーザが美術品に対して複数の注文処理を同時並行で行える、アートマーケットアプリの開発をしています。ユーザが “Buy” ボタンを押すたびに、“Pending”（処理中）カウンタが 1 つずつ増えるようにする必要があります。3 秒後に “Pending” カウンタが 1 減り、“Completed” カウンタが 1 増える必要があります。
>
>しかし、“Pending” カウンタは意図した通りに動作していません。“Buy” を押すと、“Pending” が -1 に減少します（あり得ない！）。また、2 回素早くクリックすると、両方のカウンタが予測不可能な挙動を示します。
>
> なぜこれが起こるのでしょうか？ 両方のカウンタを修正してください。

<font color="red">これがすぐわかる方は記事を読む必要はありません!!!</font>

``` React App.js
import { useState } from 'react';

export default function RequestTracker() {
  const [pending, setPending] = useState(0);
  const [completed, setCompleted] = useState(0);

  async function handleClick() {
    setPending(pending + 1);
    await delay(3000);
    setPending(pending - 1);
    setCompleted(completed + 1);
  }

  return (
    <>
      <h3>
        Pending: {pending}
      </h3>
      <h3>
        Completed: {completed}
      </h3>
      <button onClick={handleClick}>
        Buy     
      </button>
    </>
  );
}

function delay(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  });
}
```

## 回答

更新用関数を利用して、handleClick を修正する

修正後
``` React App.js
import { useState } from 'react';

export default function RequestTracker() {
  const [pending, setPending] = useState(0);
  const [completed, setCompleted] = useState(0);

  async function handleClick() {
    setPending(p => p + 1);
    await delay(3000);
    setPending(p => p - 1);
    setCompleted(c => c + 1);
  }

  return (
    <>
      <h3>
        Pending: {pending}
      </h3>
      <h3>
        Completed: {completed}
      </h3>
      <button onClick={handleClick}>
        Buy     
      </button>
    </>
  );
}

function delay(ms) {
  return new Promise(resolve => {
    setTimeout(resolve, ms);
  });
}

```

# これらがわかれば解ける（と思う）

## stateが更新されてから、画面が更新されるまで
state が更新されてから画面に描画されるまでの流れはおおまかにこのようになっています。

1. トリガ：初回、コンポーネントの state の更新
2. レンダー：React がトリガのあったコンポーネントを呼び出す
3. コミット：DOM を変更
4. ブラウザの画面を再描画

まず、特定のコンポーネントの state が更新されます。
（例えばユーザーがボタンを押す（handleClick）など）

そして state の更新があったコンポーネントを React が検知して、その変更を読み取ります。

最後に、変更箇所を DOM に伝えてブラウザの画面が再描画されます。

## state はスナップショットである

以下のコードではボタンをクリックすると、アラートは「0」と表示されます。

``` React App.js
import { useState } from 'react';

export default function Counter() {
  const [number, setNumber] = useState(0);

  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 5);
        setTimeout(() => {
          alert(number);
        }, 3000);
      }}>+5</button>
    </>
  )
}

```

このことからアラートに渡された state は「スナップショット」だということが分かります。
number は次のレンダーで 5 に更新されます。


他にはイベントハンドラ内のすべてのコードが実行されるまで、React は state の更新処理を待機するといういうことも知っておくとよいです。

## 次のレンダー前に同じ state 変数を複数回更新する場合
更新用関数を セッター（setSomething）に渡す

例：```setNumber(n => n + 1);```

---

更新用関数をセッターに渡せば正解できますが、背景まで知っておくと腹落ちしやすいのかなと。

これからもReact に限らず公式ドキュメントを読む癖をつけて言語やフレームワークの理解を深めていきます。
[備忘][Docker][Fastify]DockerにFastifyコンテナを立ち上げたけど、postgresコンテナと接続できなかった件を解決

## Fastifyコンテナとpostgresコンテナが接続できない
Fastifyのコンテナを起動させると、下記エラーで落ちる。
```
Error: P1001: Can't reach database server at `localhost`:`5432`
```
データベースに接続できない模様。

## 調査結果
エラー内容そのまんまで検索してたらちゃんと[公式に書いてあった](https://fastify.dev/docs/latest/Reference/Server/#listen:~:text=When%20deploying%20to%20a%20Docker%2C%20and%20potentially%20other%2C%20containers%2C%20it%20is%20advisable%20to%20listen%20on%200.0.0.0%20because%20they%20do%20not%20default%20to%20exposing%20mapped%20ports%20to%20localhost%3A)。
>When deploying to a Docker, and potentially other, containers, it is advisable to listen on 0.0.0.0 because they do not default to exposing mapped ports to localhost:

つまり、
```js
fastify.listen({ port: 3000 }, (err, address) => {
  if (err) {
    fastify.log.error(err)
    process.exit(1)
  }
})
```
を以下のようにしてあげる。
```js
fastify.listen({ port: 3000, host: '0.0.0.0' }, (err, address) => {
  if (err) {
    fastify.log.error(err)
    process.exit(1)
  }
})
```

この辺の理解をしっかりしたいので、別記事にまとめる。
ぼっちでもControl Tower連載[3/3]~Security Hubの設定~

どうも駆け出し12冠エンジニアのアスカです、今日はControl TowerのでSecurity Hubの設定をしていきます。
※この投稿は連載の3本目になっています。
1. [ぼっちでもControl Tower連載[1/3]~とりあえず作ってみた~](https://qiita.com/asuka0708japan/items/f508564635096e0b1444)
1. [ぼっちでもControl Tower連載[2/3]~予防的ガードレールの確認~](https://qiita.com/asuka0708japan/items/21db5687f52772c879cd)
# 背景
Control Towerを設定してから、開発用アカウントを作成してこれから作業を行っていく訳ですが、自分でSecurityの脆弱性を確認出来るようにしたい！！
そのため今回はSecurity Hubを有効化していきます。
手順は以下の通りです。
1. 管理アカウントでSecurity Hubを有効化
1. 管理アカウントで権限の委譲を設定
1. 監査アカウントで有効化
1. ダッシュボードを確認
ちなみに現状のマルチアカウント環境はこんな感じ。発見的ガードレールに用いられるConfigの検知結果を確認出来る状態にしていきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3349905/6f69f9a0-2fed-edc7-5bf5-d76117aabd3c.png)

## 管理アカウントでSecurity Hubを有効化
管理アカウントにログインしてOrganizationsのページでSecurity Hubを有効化します。他にも色々な統制機能があってドキドキしますね。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/bocchi_ContTower_SecHub/bocchi_ControlTowerSecHub1.png)
Security Hubの信頼されたアクセスを有効にします。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/bocchi_ContTower_SecHub/bocchi_ControlTowerSecHub2.png)
## 管理アカウントでSecurity Hub権限を監査アカウントに委任
管理アカウントでSecurity Hubにアクセスして有効にします。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/bocchi_ContTower_SecHub/bocchi_ControlTowerSecHub3.png)
委任された管理者に監査アカウントのIDを入力して有効化します。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/bocchi_ContTower_SecHub/bocchi_ControlTowerSecHub4.png)

## 監査アカウントでSecurity Hub組織の有効化
監査アカウントに移動すると、Security Hubが有効になっています。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/bocchi_ContTower_SecHub/bocchi_ControlTowerSecHub5.png)
しかし、設定を確認すると、まだ組織で有効になっていない事が分かります。組織で有効化していくために"ポリシーを作成"をクリックします。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/bocchi_ContTower_SecHub/bocchi_ControlTowerSecHub6.png)
ここで組織の一元化設定をしていきます。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/bocchi_ContTower_SecHub/bocchi_ControlTowerSecHub7.png)
次に組織全体に適用する設定を選択します。今回は簡単のためにAWSが推奨するSecurity Hubの設定を使用します。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/bocchi_ContTower_SecHub/bocchi_ControlTowerSecHub8.png)
最後に設定内容を確認し、"ポリシーを作成して適用"をクリックします。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/bocchi_ContTower_SecHub/bocchi_ControlTowerSecHub9.png)
これで組織内の全てのアカウントでSecurity Hubが有効化されました。
## メンバーアカウントでも有効化されている事を確認
メンバーアカウントでも有効になっている事を念のため確認してみましょう。
![Qiita](https://d39oe90ddnxn3x.cloudfront.net/bocchi_ContTower_SecHub/bocchi_ControlTowerSecHub10.png)

# まとめ
今回、組織内の組織内のセキュリティ脆弱性を一元管理出来るダッシュボードを作成しました。今後はGuardDutyの検知結果も統合していきたいですね。

# 参考
めちゃめちゃ参考にさせていただきました。ありがとうございます！
1. https://classmethod.jp/aws/articles/aws-control-tower/
1. https://qiita.com/tonkatsu_oishi/items/6fd0e2c73718057adcc9
[備忘][Docker][Prisma]デプロイ時にOpenSSLをインストールするエラー

## fly.ioへのprismaアプリのデプロイ時にエラー発生
fly.ioの当該アプリを開き、コンソールを除くと下記のように書いていた。
```
prisma:warn Prisma failed to detect the libssl/openssl version to use, and may not work as expected. Defaulting to "openssl-1.1.x".
Please manually install OpenSSL via `apt-get update -y && apt-get install -y openssl` and try installing Prisma again. If you're running Prisma on Docker, add this command to your Dockerfile, or switch to an image that already has OpenSSL installed.
Error: Schema engine error:
```
読むと`apt-get update -y && apt-get install -y openssl`ウィ実行してOpenSSLをインストールしろと書いている。

しかし、Dockerfileにはすでにopensslのインストールコマンドを書いている。
```
RUN apt-get update -y && apt-get install -y openssl
```

しかし、さらにエラーをよく読んでみると...
```
prisma:warn Prisma failed to detect the libssl/openssl version to use, and may not work as expected. Defaulting to "openssl-1.1.x".
```

つまり、すでにopensslの1系がインストール済みだけど、そのバージョンじゃ期待通り動かない、と言っている。

で、上記のエラー内容でググるとOpenSSLのver3が必要らしい。

つまり、すでにDockerfileで使用していたイメージにOpenSSLが入っているから、さらに`apt-get install -y openssl`しても意味がなかったのだと判明。

なので、3にアップグレードすべく
```
RUN apt-get upgrade openssl -y
```
を実行することで、問題解決した。
MacBookAir(M1)にRedmineを立ててみる。

## はじめに

Redmineを使ってみたくて、MacBookAir 2020(M1)に、立ててみる。
環境は、なんとなくDockerを使いたい。

## Dockerイメージの検索

とりあえず、"Docker redmine"でググる。
一番最初に出てきた候補が、"redmine - Official Image"

https://hub.docker.com/_/redmine/

ここにdocker-compose.ymlの例が記載されていたので、それをそのまま使ってみる。

```
version: '3.1'

services:

  redmine:
    image: redmine
    restart: always
    ports:
      - 8080:3000
    environment:
      REDMINE_DB_MYSQL: db
      REDMINE_DB_PASSWORD: example
      REDMINE_SECRET_KEY_BASE: supersecretkey

  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: redmine
```

## Mac上で実行してみる

1. 適当に作業ディレクトリを作成して移動
    ```
    $ mkdir -p ~/Work/test_redmine
    $ cd ~/Work/test_redmine
    ```
2. 上記の、docker-compose.ymlをここに作成
    ```
    $ vim docker-compose.yml
    ```
3. docker-compose実行
実行方法、忘れた。ググって、次の通りだそうな。-dはバックグラウンドで実行のオプション
実行前に、Docker Desktopを起動しておく
    ```
    docker-compose up -d
    ```
    一応、こんな感じで完了したっぽい。
    ```
    $ docker-compose up -d
    Creating network "test_redmine_default" with the default driver
    Pulling redmine (redmine:)...
    latest: Pulling from library/redmine
    26070551e657: Pull complete
    ... 省略 ...
    Digest: sha256:a532724022429812ec797c285c1b540a644c15e248579c6bfdf12a8fbaab4964
    Status: Downloaded newer image for mysql:8.0
    Creating test_redmine_db_1      ... done
    Creating test_redmine_redmine_1 ... done
    ```
4. ブラウザから
    http://localhost:8080
    にアクセス。Redmineの画面が見えた。
5. admin/admin でログイン
6. パスワード変更を求められるので、パスワード変更。


ここまでで、おしまい。
Supabase をコールしたら new row violates row-level security policy となった

# なにこれ
Flutter から Supabase のテーブルにアクセスしようと思ったら以下のエラーにぶつかったので、どのように解決したかをメモしました。
```zsh
PostgrestException(message: new row violates row-level security policy for table "user", code: 42501, details: Unauthorized, hint: null)
```


# 原因
最初に Row level security policy を Enabled にしていたのに、その設定をしていなかったことが原因でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/f2d6515c-03b0-e393-e657-d30674ba18a3.png)


# 解決方法
### ポリシー作成画面を開く
Authentication > Policies > Creata a new policy でポリシーを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/2ea19087-d82e-4575-e3c3-0bd2da9a2bc5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/7e50916d-75b0-115f-78da-84167f7fb643.png)


### ポリシー内容を設定
全部使いたいので、Policy command は ALL にします。
細かい設定が必要であればここで select だけにするとかそういうことも可能。
using は true にしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/f3e75fb2-889c-51d3-7019-dfa3afa3119b.png)

出来上がったらこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2819748/f1e3a466-30fa-3764-8913-eb02af8dbc9b.png)


# 無事治った！
自分の画面は載せられないですが、デバッグしてみてちゃんと返ってきた。よかったよかった。
LLMなどに出てくるlogitとは何か

# はじめに
- huggingfaceなどで公開されているニューラルネットワークのプログラムを見ると、"logit"とという変数が出てくる
- ここでの"logit"は何を意味しているのか？数学的意味があるのか？

# 数学のlogitの定義（初心者が混乱するやつ）
wikipediaの説明を読んでみると、次のようなことが書かれている。
> ロジット（英: logit）とは、0から1の値をとるp に対し
> $\displaystyle \operatorname {logit} (p)=\log \left({\frac {p}{1-p}}\right)=\log(p)-\log(1-p)$
> で表される値をいう。p を変数とするロジット関数とも呼ばれる。

> ロジット関数はロジスティック関数
> $\displaystyle \operatorname {expit} (\alpha )={\frac {1}{1+e^{-\alpha }}}={\frac {e^{\alpha }}{1+e^{\alpha }}}$
の逆関数であり、特に確率論と統計学で多く用いられる。

**初心者はここで死亡する。**
ただ、ここで<font color="#0072BC">**ヒント**</font>になりそうなポイントは次の事項だ。
- logitは確率値に関係する
- 確率値に変換する関数（ロジスティック関数）の逆変換（逆関数）である

# ニューラルネットワークで使われるlogitの説明
前節の説明を整理すると、次のような図で書けそうだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510180/722c3bf2-298f-259b-c6e0-8371e1ce9022.png)


<br/>

ここまで整理すると、実はすぐさま結論がわかる。
ニューラルネットワークで使われる変数"logit"とは図のようなイメージだ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2510180/ed5e8219-d715-1932-7582-314f7393a682.png)



すなわち、<font color="#FF0066">**確率値に変換をかける直前の、変換していない値を単にlogitと呼んでいる**</font>だけだ。


# おわりに
- 案外説明されてない気がしたので記事書きました
- こういう「案外説明されてないもの」は結構多い気がする
Windowsの入ってるディスク領域を移動したい

## 動機

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424756/11b99a4d-d9b1-7f57-1ef3-a095aca74028.png)

あら、Cドライブがパンク寸前です。可哀想に。
ということで、どうにかして空き容量を確保してあげたいですね。
まずは他のディスクの状況を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424756/b143b754-e724-cc35-16d1-91fb8a465879.png)

おや、Cドライブが入っているディスク2はもう拡張できないようです。
でもCドライブをディスク1の未割り当て領域に移動することはできそうですね。
なんならついでにEドライブをディスク2に移動してもいいですね。

本当はWindowsの標準機能だけで実現したいところですが、バックアップを作ってさらにそれを読み込んで復元して…と厄介そうで。
今回はgpartedをこねこねしてなんとかしてみます。

## 注意点

ドライブをいじることにはデータ消失のリスクが伴います。
全ては自己責任で。

## 手順

0.a. USBメモリ(あるいは今回操作しないディスク)にgpartedを扱えるシステム(Ubuntu liveUSBとか)をインストール
0.b. 以降はそのシステムから作業する
1. Cドライブをディスク1にコピー
3. 再起動して動作確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424756/44a431b8-fa3d-9784-3818-7f71ca245480.png)

うまく行ったようです。
でも今度はEドライブが邪魔でCドライブの拡張性がなくなっているので、かつてのCドライブ部分(Fドライブ)に上書きしたりEドライブを削除したりCドライブを前方に移動したりして……

あ
![1000003930.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424756/3c2bf793-a0e6-1cbd-fe7f-049192e00a63.jpeg)

ということで、こんなことやるのはおすすめしません。
(一応試行錯誤して直せましたが、なぜ直ったのかはわかっていません。まだまだ勉強が足りない…)
QiitaのDiscussionでContributeしよう

# 1. 背景
## 中々Contributionのきっかけが掴めなかった
OSSだったりpublicな場で貢献したいなと思いながらも中々きっかけがありませんでした。

## Qiitaのサイトを眺めていると個人的に気になる文言があった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/fbf1d86a-b337-e584-14ad-7c847c5a65a6.png)

こちらは記事のOrganizationの紐付けについての説明です。

`Organizationが紐付いている記事の一括追加・削除`この文言の解釈を誤ると、`記事自体が消えてしまう`のかなと思いました。

# 2. QiitaにContributeする方法
## 2.1. [ご意見](https://github.com/increments/qiita-discussions/discussions/116)をクリック
![スクリーンショット 2024-04-20 13.36.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/5c8a6bd4-33bb-375d-9682-6a4022700916.png)

## 2.2. [Discussions](https://github.com/increments/qiita-discussions/discussions)をクリック
https://github.com/increments/qiita-discussions/discussions/116

![スクリーンショット 2024-04-20 13.41.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/ef32393b-3bd3-3cfe-d3df-0840f365a722.png)

## 2.3. [New discussion](https://github.com/increments/qiita-discussions/discussions/new/choose)をクリック

https://github.com/increments/qiita-discussions/discussions

![スクリーンショット 2024-04-20 13.39.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/2411d61e-8dca-0ece-955d-acb6214381af.png)

## 2.4. カテゴリを選ぶ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/ba28100c-d787-4664-4488-162dc320181f.png)
カテゴリは以下です
- ヘルプ
- 要望・アイデア・不具合

今回の例は`要望・アイデア・不具合`だと思ったのでそちらを選択します

## 2.5. 内容を書く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/ca978aa0-9b53-61c1-a263-22212df90c5f.png)

実際に投稿した内容はこちらです！

https://github.com/increments/qiita-discussions/discussions/725

# 3. 最後に
- 身近にContributeする機会があることを知リました
- Qiitaにはいつも記事を投稿したり、記事を調べたりでお世話になっているので貢献できたのなら良かったです

本記事を読んで頂き、ありがとうございました。
いいねいただけると記事執筆の励みになりますので、参考になったと思われた方は是非よろしくお願い致します🙏

# 4. 後日談
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/2cb4e70a-de2c-2dd8-6443-0c07997e9bc1.png)

対応していただく事になりました！
ありがとうございます！
$_SESSION

## はじめに

$_SESSIONについて整理する。

### $_SESSION

セッション経由で渡された情報


### セッションの書き込み

セッション機能を使うには、あらかじめsession_start関数でセッションを開始しておく必要がある。

```php
<?php
session_start();
$_SESSION['email'] = $_POST['email'];
```

### セッションを破棄する

不要になったセッションは、サーバー負荷やセキュリティの観点から迅速に破棄する必要がある。

session_destroy関数はセッションを保存したファイルを削除するだけで、メモリ上のセッションは残ってしまう。

そのため、完全にセッションを削除するには以下のようなコードを書く。


```php:session_destroy.php
<?php
session_start();
// セッション変数を空に
$_SESSION = [];
// セッションクッキー(ID受け渡しのためのクッキー)があれば破棄
if (isset($_COOKIE[session_name()])) {
    $cparam = session_get_cookie_params();
    setcookie(session_name(), '', time() - 3600, 
        $cparam['path'], $cparam['domain'], 
        $cparam['secure'], $cparam['httponly']);
}
// セッションを保存したファイルを削除
session_destroy();
```

セッション変数を空にする
↓
セッションクッキー(ID受け渡しのためのクッキー)を破棄する
クッキーを破棄するには過去の有効期限を設定する
↓
セッションを保存したファイルを削除する


のような順で処理する

### クッキーとセッションの違い

**クッキー**
・データがクライアント側で管理される
・実データがネットワーク上を流れる

**セッション**
・データがサーバー側で管理される
・実データがネットワーク上を流れない

クッキーは、データがクライアント側で管理されるという性質上、「値がクライアント側で改竄/削除される可能性がある」「実データがネットワーク上で盗聴される可能性がある」などの問題を含んでいる。
しかしセッションでは実データがサーバー側で管理され、クライアント側ではセッションIDだけが渡されるので、上記の危険性を最小限に抑えることができる。
bitnami/postgresqlから作成したインスタンスでpostgresユーザのパスワードが設定されない問題の解決法

# 問題

BitnamiのPostgreSQLのHelm Chartを使ってStatefulSetを構築していたが、デフォルト管理者のpostgresユーザにパスワードが設定されず

> User "postgres" has no password assigned.

のエラーが出てしまいログインできない。

# 解決方法

`POSTGRES_PASSWORD`などの変数を設定してもダメでした・・・。以下の手順でパスワードを設定されるまでに至ったので共有します。

### 1. プロセスのユーザをpostgresに切り替える

```
/opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash
```

### 2. DBの初期化

```
initdb -D /bitnami/postgresql/databak/
```

### 3. 既存データを初期化済みのもので入れ換える

```
rm -rf /bitnami/postgresql/data
mv /bitnami/postgresql/databak /bitnami/postgresql/data
```

### 4. StatefulSetを再起動する

ここまで行って再起動後のログを確認すると、

> Changing password of postgres

というメッセージが出てパスワードが設定されたことがわかります🎉

# 参考

- https://github.com/bitnami/charts/issues/8469#issuecomment-1120344942
UbuntuでGoogle Chromeが起動しない


## 環境
OS: Ubuntu 22.04.4 LTS
Google Chrome バージョン: 124.0.6367.60（Official Build） （64 ビット）
                                
                                            
## 現象
アイコンをクリックしても起動しない
ターミナルから起動すると
```
$ google-chrome
[40191:40191:0420/121846.662670:ERROR:process_singleton_posix.cc(353)] プロファイルは、別のコンピュータ（i5-Prime-and-Diginnos）の別の Google Chrome プロセス（5452）で使用されているようです。Chrome はプロファイルが破損しないようにプロファイルをロックしています。他のプロセスがこのプロファイルを使用していないことが確実であれば、プロファイルのロックを解除して Chrome を再起動できます。
[40191:40191:0420/121846.662770:ERROR:message_box_dialog.cc(146)] Unable to show a dialog outside the UI thread message loop: Google Chrome - プロファイルは、別のコンピュータ（i5-Prime-and-Diginnos）の別の Google Chrome プロセス（5452）で使用されているようです。Chrome はプロファイルが破損しないようにプロファイルをロックしています。他のプロセスがこのプロファイルを使用していないことが確実であれば、プロファイルのロックを解除して Chrome を再起動できます。
```
と言われ，起動しない．

## 原因
PC名を変更後braveが強制終了してしまったことにより，プロファイルロックが残ってしまったため．だと思う。（知識がないので、参考にした[Qiita](https://qiita.com/anythinglab/items/7399855a6ec46c882902)をパックています）

## 解決
ロックファイルを削除すれば良い．
~/.config/google-chrome/SingletonLock が問題のファイルだとおもうので（パクリなので本当かどうかわかりません。）
    
    rm ~/.config/google-chrome/SingletonLock 
を実行する．

## 感想
強制終了でロックファイル周りが残っちゃうってlinuxあるあるですよね， むやみにしてはいけないね...（当たり前）と[オリジナル](https://qiita.com/anythinglab/items/7399855a6ec46c882902)の方が言われています。
RaycastAllを当たった順番通りに取得する方法をGPT君が教えてくれたお話

<h1>はじめに</h1>
こんにちは！
今回はRaycastAllに関するめちゃくちゃ良いシステムをまたもやGPT君が作ってくれたので紹介したいと思います！！

<h1>RaycastAllについて</h1>
RaycastAllは簡単に言うと、始点となるオブジェクトから指定した方向に指定した距離で光線(Ray)を放ち、その光線と接触したオブジェクトをすべて取得するといったメソッドです。

↓RaycastAllについて

https://docs.unity3d.com/ja/2021.1/ScriptReference/Physics.RaycastAll.html


しかし、このメソッドには問題があります。
<B>光線が当たった順番通りにオブジェクトを取得しない！！</B>

これは何とかしたい。
という事で例の如くGPT君に聞きました。

<h1>GPT君の回答</h1>

「Physics.RaycastAll を使用して衝突したオブジェクトを処理する場合、必要に応じてオブジェクトをソートするか、他の方法で順序を管理する必要があります。たとえば、衝突したオブジェクトの距離に基づいてソートすることが一般的な方法です。」

なるほどね。
距離に基づいてソートしちゃえばよかったらしいです。

そして教えてくれたコードがこちら
```C#
using System;//Sortメソッドを使用するために必要

RaycastHit[] hits = Physics.RaycastAll(始点, 方向, 距離);
Array.Sort(hits, (x, y) => x.distance.CompareTo(y.distance));
```

これで光線が当たった順番にオブジェクトを取得することができました！

<h1>おわりに</h1>
いかがだったでしょうか。
ぜひ、ゲーム制作にご活用ください～！
【Unity】Photon FusionでRPCが届かない場合のチェック項目

# RPCが届かない場合のチェック項目
* 呼び出したいメソッドに `[Rpc(***)]` アトリビュートを付けているか？
* NetworkBehaviourを継承したクラス内でRPCを呼び出しているか？
* RPCを呼び出しているクラスコンポーネントがNetworkObjectをアタッチしたGameObjectにアタッチされているか？
* 呼び出し元、呼び出し先 `[Rpc(sources: RpcSources.***, targets: RpcTargets.***)] `が正しく設定されているか？
* 同一セッション内か？同一セッション内でもリージョン(国)が同じか？（特にデフォルトの自動設定だと海外に接続されることが高頻度で発生する）
* ChannelがReliable(到達保証、デフォルト設定)になっているか？
Pythonを使ってM3U8ファイルから動画をダウンロードする方法

# Pythonを使ってM3U8ファイルから動画をダウンロードする方法

本記事では、Pythonとffmpegを使用してM3U8ファイルから動画をダウンロードする方法を解説します。特にライブストリーミングや動画配信サービスでよく使用されるM3U8フォーマットからのダウンロードが対象です。

## 必要なツール

このスクリプトを実行する前に、システムに`ffmpeg`がインストールされている必要があります。`ffmpeg`は多くのフォーマットの動画や音声の変換、処理が可能な非常に強力なフリーソフトウェアです。

## スクリプトの解説

### インポート

```python
import subprocess
import sys
```

- `subprocess`: コマンドラインツールをPythonから実行するために使用します。
- `sys`: コマンドライン引数をスクリプトで利用するために必要です。

### 関数 `download_video_from_m3u8`

```python
def download_video_from_m3u8(m3u8_url, output_path):
```

この関数は、動画のURLと保存先のパスを引数として受け取ります。

#### ffmpegコマンドの構築

```python
command = [
    'ffmpeg',
    '-protocol_whitelist', 'file,http,https,tcp,tls,crypto',
    '-i', m3u8_url,
    '-c', 'copy',
    '-bsf:a', 'aac_adtstoasc',
    output_path
]
```

- `-protocol_whitelist`: ffmpegが使用するプロトコルを指定します。これにより、セキュリティ上のリスクを管理しつつ、必要なプロトコルでの通信を許可します。
- `-i`: 入力ファイルの指定。
- `-c copy`: エンコーディングを変更せずに、ストリームをそのままコピーします。
- `-bsf:a aac_adtstoasc`: オーディオストリームに適用するビットストリームフィルター。AAC音声を適切に変換します。

#### コマンドの実行

```python
subprocess.run(command, check=True)
```

- `subprocess.run`: 上記で構築したコマンドを実行します。`check=True`は、コマンドが失敗した場合に例外を発生させるためのものです。

### エントリーポイント

```python
if __name__ == "__main__":
```

スクリプトが直接実行された場合のみ以下のコードが実行されます。

#### コマンドライン引数の処理

```python
if len(sys.argv) != 3:
    print("Usage: python script.py <M3U8 URL> <Output Path>")
    sys.exit(1)
```

適切な引数が提供されているか確認し、問題があれば使用方法を表示して終了します。

#### 関数の呼び出し

```python
m3u8_url = sys.argv[1]
output_path = sys.argv[2]
download_video_from_m3u8(m3u8_url, output_path)
```

コマンドラインからURLと出力パスを取得し、ダウンロード関数を呼び出します。

## まとめ

このスクリプトを使うことで、M3U8形式のストリーミング動画を簡単にダウンロードし、ローカルに保存することが可能です。`ffmpeg`のオプションに慣れれば、さらに多様な動画処理が行えるようになります。
JavaScript　基本の学び　記録

JavaScriptの基本を学んだので記録用
Progate2周目での情報整理です

## 【while】　繰り返し処理
条件式がtrueの間、{ }を繰り返す

例　numberを1〜100まで表示するwhile文
```js
//numberの中身は1を定義①
let number = 1;

while(number <= 100){  //numberの数値を比較しtrueかを判別②
  console.log(number);  //出力
  number += 1;  //numberに1を足す③
}
```
```:結果
1
2
3
：
：
98
99
100
```

## 【for】繰り返し処理
while文をシンプルにした文

上記のwhile文①〜③を1行で指示できる
```:例
for(①; ②; ③){
  console.log(number);
}
```

数値をいれると

```js
for(let number = 1; number <= 100; number++){
  console.log(number);
}
```

これで上記と同じ出力になる

## 【if＋for】
応用例：3の倍数なら「3の倍数です」を出力、それ以外は「number」の数値を出力する

```js
for(let number = 1; number <= 100; number++) {
  if(number % 3 === 0){
    console.log("3の倍数です");
  }else{
    console.log(number);
  }
}
```

## 【配列】定数に情報を入れておける
配列を出力する場合
```js
const number = ["1です","2です","3です"];
console.log(number);
```
```:結果
[ '1です', '2です', '3です' ]
```
「☆」配列の中身だけを取り出す場合
中身の番号を指示すればOK、配列の番号は0からカウントするため

```js
number = [[0], [1], [2]];
```

となる

なので配列の1つ目の要素を出力する場合は
```js
console.log(number[0]);
```
```:結果
1です
```

配列の3つ目の要素を出力する場合は
```js
console.log(number[2]);
```
```:結果
3です
```


また以下で配列の中身を変更できる
```js
number[1] = "②です";
console.log(number[1]);
```
```:結果
②です
```

ただ配列内すべてのデータを表示させるには
```js
console.log(number[0]);
console.log(number[1]);
console.log(number[2]);
```
の指示が必要

もし配列内すべてのデータの数が100以上あったら、100個の指示をしなければいけません(つらい)

そこでfor文を使う
```js
const number = ["1です","②です","3です"];

for(let i =0; i < 3; i ++){
  console.log(number[i]);
}
```
```:結果
1です
②です
3です
```

ちなみに僕は、ここで「このiはいったい…？」となりました。

結論からいうと、iは数値の条件のときに一般的に用いられているだけ。実際にはどんな名前でもOKらしい。なぜならただの変数名だから。

ぶっちゃけ「a」「z」でも問題ないみたいです(結局、無難なのは「i」なのでオリジナルに変えないほうがいいみたいだけど)。

もし、「いやいや、(number[i])ってなんなの？」と思ったら
上記にあった謎の「☆」とfor分を思い出してください

```js
for(let i =0; i < 3; i ++){
  console.log(i);
}
```
これは「まずiに0をいれて、3以下になるまで繰り返す、iに＋1する」という条件で「console.log(i)」するfor文で、実行すると以下の結果になる
```:結果
0
1
2
```

「☆」で覚えた配列の中身を取り出す方法を思い出し、
```js
console.log(number[i]);
```

この[i]の中に0．1．2が入ることで
```js
console.log(number[0]);
console.log(number[1]);
console.log(number[2]);
```
となり、以下の結果になるわけですね

```:結果
1です
②です
3です
```

配列の中身の数がわからない場合「配列名.length」で中身の数値を取得できる
```js
const number = ["1です","②です","3です","4です","5です"];
console.log(number.length);
```
```:結果
5
```

## 【オブジェクト】プロパティ名をつけた配列
配列の場合、複数の値を並べて、[]内で管理
```js
配列名 = [値1,値2,値3,値4]
```

プロジェクトの場合、プロパティ名と値で1つのプロパティとし、{}内で管理
プロジェクト名 ={プロパティ名1:値1,プロパティ名1:値2}
(「プロパティ名1:値1」←これで1つのプロパティ)

オブジェクトの中身を取り出す場合、プロジェクト.プロパティ名で取り出せる
たとえば、
```js
const number = {abc:111, def:222, ghi:333};
console.log(number.def);
```
```結果
222
```

またプロパティの中身は以下で変更可能
```js
number.def = 000;
console.log(number.def);
```
```:結果
000
```

そしてなんとオブジェクトの値としてオブジェクトを持てる
```js:例
const number = {
 abc:111,
 def:222,
 ghi:{
     jkl:444, 
     mno:555, 
     pqr:666
     }
};
```

もし「222」を出力したいなら
```js
console.log(number.def);
```

「666」を出力したいなら
```js
console.log(number.ghi.pqr);
```

といった指示になる
Googleのロゴ改造してみた

Googleのロゴ改造してみました。
使うアプリはChromeとibispaintだけですww
以下が出来上がったやつです。
![無題82_20240420124008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3774336/91528423-cc59-1dac-e1c8-8663b12cb3fa.png)
作る動画は下です。
![ダウンロード (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3774336/1102a975-1bf6-100c-7d17-d6c047089a65.gif)
適当だと思うけど、結構面白かったです。
フォローよろしく！
【ChatGPT＋DALL-E3】ノートに描いた落書きから画像を生成してもらう。


　どうも、カーブミラーです。

　今回は、ノートに描いた落書きってありますよね。それをChatGPTに解析してもらって、そこから画像を生成してもらおう、というお話です。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はあります。　あしからず。
:::

　ChatGPTのWeb版ですが、
　　二日前（2024/04/18）書いた
　　　入力枠の不具合は
　　　　直りました。
***
　さて、
　　本題です。

　落書きから
　　画像を生成する、
　　　それ自体は誰でも考えます。
　　　　たぶん（私だけ？）

　しかし
　　実際にできるのでしょうか？

　答えとしては
　　“ものによる”となりそうです。
***
　今回は、
　　私が途中まで描いた落書きを
　　　もとに進めます。
![IMG_20240418_203725327.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/fa8f9299-e887-2dce-ddf1-bdf936fd8309.jpeg)

　ごらんのとおり、
　　顔も髪型も服装も
　　　中途半端です。

　とにかく
　　いつもの解析をします。
***
***ChatGPT***
アップロードされた画像は紙に描かれたドローイングの写真です。分析可能な内容を以下に示します。

**背景:**
- 一見すると、白い平面で、たぶん机またはテーブルの上。
- 表面は滑らかで、目に見えるテクスチャーはありません。
- 画像の上部からの光源を示唆するような、やわらかい影が落ちています。

**被写体:**
- 人の上半身と頭のスケッチです。
- 頭部は軽いスケッチで描かれており、波打つかカーリーな髪の一部を除いて、特徴は詳細に描かれていません。
- 髪型は短く、いくつかの波やカールが見られます。
- 首と衣服の襟がゆるく定義されています。
- 色は使用されておらず、モノクロのペンまたはインクで描かれています。
- 表情や特徴的な体の言語が描かれていないため、ムードは中立です。
- スケッチは白黒なので、肌や服の色については提供できません。

**画風:**
- ドローイングスタイルは、ラフでスケッチ感のある印象派風です。
- 線は完全に繋がっておらず、未完成または途中の作品のような外観を与えています。
- スタイルはミニマリストで、細部や陰影に焦点を当てずに形とアウトラインに注目しています。

***user***
このことをベースにして、実際の人物（女性）の写真を作成してください

***ChatGPT***
![converted_image.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/7f0fc87f-94e5-6be9-b887-c411d21fdc1d.jpeg)

***user***（写真にして欲しいのに……）
画像を塗り絵として、色を付けてください。最終的には写真になるように

***ChatGPT***
![Create_a_realistic_full-color_image_of_a_woman_wit.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457238/59bcdfd6-0e36-aadc-fc82-923dd78462ea.jpeg)
***

　できました。

　落書きで意図していたのは
　　和服姿の日本人女性。

　まぁ、特徴からしたら
　　そこまでを再現は
　　　難しいでしょうね😅

　この画像の
　　プロンプトがこちらになります。
***
***ChatGPT***
Here is the English prompt that was used for the image generation:

"Create a realistic full-color image of a woman with short, wavy or curly hair and a neutral expression, wearing a collared shirt. The image should look like a candid photograph, with soft lighting and naturalistic colors for skin and clothing, as would be seen in a real-world setting. The overall appearance should convey a candid and natural look, reminiscent of a finished and colored photograph."

And here is the Japanese translation:

"短く波打つかカーリーな髪で、中立的な表情の女性のリアルなフルカラー画像を作成してください。この画像は、自然な光と、実際の環境で見られる肌や服の自然な色合いを持つ、ありのままの写真のように見えるべきです。全体的な見た目は、完成されたカラー写真を思わせる、自然で素朴な印象を伝えるべきです。"
***

　今回は
　　こんなレベルの落書きでしたが
　　　もっとイラストとして
　　　　描かれたものであれば
　　　　　左右は別として
　　　　　　それなりの
　　　　　　　再現度はありそうです。

　このことが
　　みなさんの
　　　作品制作の糧に
　　　　なれば、幸いです。

　今回は、
　　ここまで。
[応用情報技術者試験/基本情報技術者試験]ベン図を書いて解を求めるのはもうやめよう

応用情報技術者試験または基本情報技術者試験の過去問対策で、集合の問題になると多くのサイト・参考書がベン図を書いて解説をしています。
それもいいですが、集合論で解いたほうが個人的には納得感があるので、集合論で解いてみます。

>全体集合S内に異なる部分集合AとBがあるとき，$\overline A∩\overline B$に等しいものはどれか。ここで，$A∪B$は$A$と$B$の和集合，$A∩B$はAとBの積集合，$\overline A$は$S$における$A$の補集合，$A－B$は$A$から$B$を除いた差集合を表す。
（ア）$\overline A-B$
（イ）$(\overline A∪\overline B)－(\overline A∩\overline B)$
（ウ）$(S－A)∪(S－B)$
（エ）$S－(A∩B)$
（出典：令和4年春期　問2）

まず、差集合の定義は
```math
X-Y=\lbrace x \in X | x \notin Y\rbrace=X∩\overline Y
```
です。
つまり、
```math
\displaylines{
X \longrightarrow X \\
－ \longrightarrow ∩ \\
Y \longrightarrow \overline Y
}
```
の変換とみなせるので、
```math
\overline A∩\overline B=\overline A - B
```
となり、解答は（ア）です。
差集合の定義さえ覚えていれば、ベン図書くより簡単かも。
なお、
（イ）は
```math
\begin{align}
&(\overline A∪\overline B)－(A∩B)\\
=&(\overline A∪\overline B)∩\overline{(A∩B)}\\
=&(\overline A∪\overline B)∩(\overline A∪\overline B)\\
=&(\overline A∪\overline B)
\end{align}
```

（ウ）は、
```math
\begin{align}
&(S－A)∪(S－B)\\
=&(S∩\overline A)∪(S∩\overline B)\\
=&(\overline A∪\overline B) \hspace{10pt}(\because Sは全体集合)\\
\end{align}
```

（エ）は
```math
\begin{align}
&S－(A∩B)\\
=&S∩(\overline{A∩B})\\
=&(\overline A∪\overline B) \hspace{10pt}(\because Sは全体集合)\\
\end{align}
```

と変形できます。
なお、（エ）の式変形から分かるように（イ）（ウ）（エ）はいずれもNANDゲートです。
（ア）だけがNORゲートとなっています。

>$\overline{(A∪B)∩(\overline A∪\overline B)}$と等価な集合はどれか。ここで，$∪$は和集合，$∩$は積集合，$\overline X$は$X$の補集合を表す。
（ア）$(\overline A∪B)∩(A∪\overline B)$
（イ）$(\overline A∪\overline B)∩(A∪B)$
（ウ）$(\overline A∩B)∪(A∩\overline B)$
（エ）$(\overline A∩\overline B)∪(A∩B)$
（出典：平成25年春期　問2）

まず一番上の否定を外すと、
```math
\overline{(A∪B)∩(\overline A∪\overline B)}=(\overline A∩\overline B)∪(A∩B)
```
です。
ここから分配法則を用いると
```math
\begin{align}
&(\overline A∩\overline B)∪(A∩B)\\
=&((\overline A∩\overline B)∪A)∩((\overline A∩\overline B)∪B)\\
=&((\overline A∪A)∩(\overline B∪A))∩((\overline A∪B)∩(\overline B∪B))\\
=&(\overline B∪A)∩(\overline A∪B)\hspace{10pt}(\because \overline X∪Xは全体集合)\\
=&(\overline A∪B)∩(A∪\overline B)
\end{align}
```
なので、解答は（ア）です。

かなり古いですが、基本情報技術者試験の問題もやっておきます。
>集合$S－(T∪R)$に等しいものはどれか。ここで，$∩$は積集合，$∪$は和集合，$－$は差集合の各演算を表す。
（ア）$(S－T)－R$
（イ）$(S－T)∪(S－R)$
（ウ）$(S－T)∪(T－R)$
（エ）$(S－T)∩(T－R)$
（出典：平成17年春期　問8）

まず差集合の定義を再掲します。
```math
X-Y=\lbrace x \in X | x \notin Y\rbrace=X∩\overline Y
```
これに沿うと
```math
\begin{align}
&S-(T∪R)\\
=&S∩\overline{(T∪R)}\\
=&S∩(\overline T∩\overline R)\\
=&(S∩\overline T)∩\overline R\\
=&(S-T)∩\overline R\\
=&(S-T)-R\hspace{10pt}(\because (S-T)とRの差集合)\\
\end{align}
```
となるので、解答は（ア）です。
llama3をollamaを使って手元のPCで動かしRubyのFizzBuzzを書かせる

## はじめに

日経新聞を呼んでいたら、Meta社がllama3を発表したという記事が掲載されていた。

https://www.nikkei.com/article/DGXZQOGN18D9W0Y4A410C2000000/

エンジニア界隈で流行っているんだろうなと思ったが、思いのほかQiita記事がなかった。
Meta社が宣伝しているだけで、そこまで流行ってないのかもしれない。

ともかく、実はLLMモデルは自分のパソコン上で簡単に動かせる。

## ollamaをインストール

Ollamaというコマンドラインツールをインストールする。あとはコレが全部やってくれる。

https://github.com/ollama/ollama


```
curl -fsSL https://ollama.com/install.sh | sh
```

Dockerもあるので、Windowsな人も試すことができます。

## モデルのダウンロード

```
ollama pull llama3
```

プロキシ環境で作業している人は下のFAQを読むと回避できる。

https://github.com/ollama/ollama/blob/main/docs/faq.md#how-do-i-use-ollama-behind-a-proxy

## 実行

```
ollama run llama3
```

とても簡単である。これだけでllama3を試すことができる。
**GPUがなくても十分に実用な速度で動きます！**

`llama3:70b` も試すことができるが、流石に普通のデスクトップコンピューターだと重い。モデルも40GBあるから、ノートパソコンだと動かしづらいかもしれない。

少し試した印象だと決して日本語は得意ではないので、英語での利用が推奨される。

ちなみにQiitaのことは知っている。

### `llama3` の場合

![hoge.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/400562c0-9ee5-5f7b-c819-c1dd84496c07.gif)

### `llama3:70b` の場合

![hoge1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/9762a5b0-2db0-1d94-4f6e-3a117388480d.gif)

情報の信憑性はほとんど期待できないが、それらしい文章を書く能力は優秀そうだ。

### FizzBuzz

プログラミングの課題も少しやってもらう。
ここではRubyでFizzBuzzを書いてもらった。

### `llama3` の場合

![hoge4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/c4536ae5-d49a-1abf-81b5-d0c125ca43a8.gif)

### `llama3:70b` の場合

![hoge3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144608/fc17bc67-343d-fa71-8a28-ffe88cb0ab02.gif)

このぐらいの難易度の課題であればさくっとやってくれそうである。

## コード生成とローカルLLM

AIのプログラミング能力は非常に高く、すでに社会で広く使われている。

けれどもライセンスを考えると、気軽に使用できないシーンは多い。例えば、ChatGPTが書いたソースコードをMITとして公開していいのだろうか？　それはアウトであるとは思わないが、ややグレーゾーンである。場合によっては問題になるケースも出てくるかもしれない。

生成されたコードをOSSとして公開するのがグレーゾーンでも、レビューの使いみちは大きい。たとえばOSSとして公開しているソースコードをChatGPTにレビューさせるのは全く問題ないはずだ。
では、OSSではないコードを自由にChatGPTのサーバーにアップロードしても良いのか？
職場の方針やコードの著者のルールに従えばよいが、一般的にはNOであることが多いだろう。

こういった論点を観察すると、現状のWebサービスとしてのAIには課題があると思う。

- 「OSSなコードで学習していることが明確なLLMモデル」でのこーでぃんぐ
- 非公開のコードのローカルLLMモデルによるコードレビュー

には大きな需要があると思う。これらを解決できる簡単な方法の一つがローカルで動かせるLLMだと思った。

この記事は以上です。
複数のファイルが入っているフォルダから最新のファイルのデータだけを取得する

# はじめに
現場で作成しているデータをPower BIに読み込みたいのだが諸事情によりこんな状況に陥ってしまった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/edd63248-905b-011f-50cc-c99e8153cb1b.png)
- フォルダには複数のファイルが入っていて、最新のファイルの名前が特定できない
- ここから更新日時が最新のファイルのデータだけをPowerBIで取得したい
- ファイル名は今後も変わり続けるので、Power BIでデータ更新する際に最新のファイルの名前が変わっていても対応できるようにしたい
- 本来は同じファイル名で上書きすればよいのだけど諸事情によりそうならない

# Power Query エディターをポチポチするとこうなった
フォルダーコネクタで接続
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/d48b6518-f672-6cdf-256f-50d35383f861.png)

データの変換をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/84118b18-229e-52a8-5d4d-1eecd8e756a4.png)

Data modified列に「最も遅い」でフィルタをかける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/c1881dec-4a98-736b-4953-0d840046dc88.png)

Content列のファイルの結合をクリック
（ここでBinaryの方をクリックするとファイル名が変わったときに対応できない）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/f2bd64ec-2c14-1649-9d8c-5a8af85d383d.png)

読み込みたいオブジェクト（今回はSheet1）を選んでOKをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/70badc13-073e-8f7c-fb76-aae276b6f6c7.png)

これでファイル名が変わっても最新のファイルのデータを取得することができた。なんだけどヘルパークエリが自動でできてクエリ一覧がごちゃっとするのが好みじゃない・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/8d016e83-ed37-c62f-0e9e-8d16d4a7b690.png)

# 詳細エディターで頑張って編集してみる
```Excel.Workbook```に渡すファイルパスを作ることができれば何とかなりそうなのでName列とFolder Path列から値を取得する方法を考えた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/a6531414-f7e7-df96-4639-92a74e732926.png)

### 頑張った成果
「フォルダ名とファイル名を取得してファイルパスを作る」の部分がPower Query エディターポチポチではできないところ
```js:最新ファイルのデータを取得
let
    // フォルダ内のファイルリストを取得
    FileList = Folder.Files("D:\Users\reisy\Documents\PowerPlatform\複数ファイルの保存場所"),

    // 最新のファイルのレコードに絞り込む
    LatestFileRecord = Table.SelectRows(FileList, let latest = List.Max(FileList[Date modified]) in each [Date modified] = latest),

    // フォルダ名とファイル名を取得してファイルパスを作る
    FolderPath = LatestFileRecord{0}[Folder Path],
    LatestFileName = LatestFileRecord{0}[Name],
    FilePath = FileList{[Folder Path = FolderPath, Name = LatestFileName]}[Content],

    // Excelファイルをインポートする
    ImportedExcelBook = Excel.Workbook(FilePath),
    ImportedExcelSheet = ImportedExcelBook{[Item="Sheet1",Kind="Sheet"]}[Data]
in
    ImportedExcelSheet
```

ヘルパークエリがないのですっきり！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/ba3e6229-d94d-aa95-c3f8-c3a1a4d78c7a.png)

# まとめ
Power Query エディターをポチポチするだけでできる方法を考えるのはより多くの人と一緒に活用するためには重要と思っている。
だけどポチポチだけではできないこともあるし、できなくはなくてもより合理的なクエリを考えていくためにポチポチオンリーからは脱却していかないといけないなー
REST APIについて

# REST APIとは
REST API（Representational State Transfer Application Programming Interface）は、クライアントとサーバー間の通信を可能にするアーキテクチャスタイルの一つです。REST APIは、HTTPプロトコルを使用してデータを送受信し、リソース（例: データや機能）を操作するための一般的な手法を提供します。
# REST原則
設計設定には以下のものがあります
### クライアント/サーバー
* 画面（UI)とデータで関心事を分離
* クライアント側がトリガー、サーバー側が受け身
### 階層化システム
* 多層アーキテクチャ構成
* メリット
    * コンポーネントに役割を決めて独立させることで進化と再利用がそくしんできる
* デメリット
    * データ処理時にオーバーヘッドが発生するのでユーザーから見ると応答が悪く見える
### コードオンデマンド
* クライアントコードをダウンロードして実行できる
* メリット
    * リリース済みのクライアントに対して機能追加ができる
    * サーバーの負荷が下がる
* デメリット
    *　多数のブラウザなど評価環境が複雑になる
### 統一インターフェース
* メリット
    * システムアーキテクチャ全体が簡素化されてわかりやすくなる
    * 提供するサービスに集中でき独自の進化ができる
    * 異なるブラウザでも同じような画面を表現できる
* デメリット
    * 標準化によって効率が犠牲になる
##### リソース（名前がつけられるあらゆるもの）の識別
* URIを用いてサーバーに保存されたデータを識別する
* URIに動作は含まない
##### 表現を用いたリソース操作
* 断面情報を利用してサーバー上のデータを操作する
##### 自己記述メッセージ
* メッセージ内容が何であるか、ヘッダーに記述されている
##### HATEOS
* 検索結果ページにおける次のページ
### ステートレス
* 前の状態を保存しない
* それぞれの会話が単独で成り立つ
* サーバーはリクエストだけでコンテキストを理解できる
* メリット
    * 監視が容易
    * 障害復旧が容易
    * スケールが容易
* デメリット
    * リクエストデータに重複がある
    * アプリを複数バージョン同時ていきょうし、状態をクライアントに置いておくとアプリ制御が複雑になる
### キャッシュ制御
* クライアントはレスポンスをキャッシュできる
* メリット
    * ユーザー体験の向上
    * リソース効率の向上
    * 拡張性の向上
* デメリット
    * 古いデータを戻してしまうとシステムに対する信用性の低下につながる
# URI設計
URI（Uniform Resource Identifier）を設計する際に考慮すべき主要な要素は以下の通りです

### 1. リソースの識別性
URIは一意のリソースを識別するためのものでなければなりません。リソースの識別性を確保することで、クライアントが正確なリソースにアクセスできます。
例: /movies/{movie_id}
### 2. リソース階層の表現
リソースが階層的に組織されている場合、URIにその階層構造を反映することが重要です。これにより、リソースの関係性や階層構造を理解しやすくなります。
例: /genres/{genre_id}/movies/{movie_id}
### 3. クエリパラメータの利用
URIに含まれるパラメータは、リソースのフィルタリングやページネーションなどの目的で使用されます。必要な場合には、クエリパラメータを使用してリクエストを細かく制御できます。
例: /movies?genre=action&year=2022&page=1
### 4. RESTfulな命名規則の遵守
URIはRESTfulな命名規則に従って命名されるべきです。リソースの名前付けや操作の表現には、一貫性が重要です。
例: /movies（複数形）、GET /movies/{movie_id}（リソースの取得）
### 5. ユーザーフレンドリーな設計
URIは理解しやすく、記憶しやすい形式で設計する必要があります。また、冗長性を避け、シンプルで直感的な命名を心がけると良いでしょう。
例: /movies/{movie_id}（映画の一意の識別子を含む）
これらの要素を考慮して、URIを設計することで、システムの可読性、保守性、拡張性が向上し、クライアントとサーバー間の通信が効率的に行われます。
# REST APIで使われるHTTPメソッド
REST APIで映画（movie）をリソースとしてCRUD操作を行うためのURIとHTTPメソッドの定義です

| URI | HTTPメソッド  | 内容 |
|-----|------------|-----|
| /movies |  GET  | 映画一覧取得 |
| /movies |  POST  | 新しい映画の追加 |
| /movies/{movie_id} |  GET  | 特定の映画情報取得 |
| /movies/{movie_id} |  PUT  | 映画情報の更新  |
| /movies/{movie_id} |  DELETE  | 映画の削除  |

{movie_id}は映画の一意の識別子です。