OmniAICreator/Qiita-1.07M huggingface dataset:
【FaaS】GlitchからTiDBに接続する【Serverless】


```javascript:server.js
const fastify = require("fastify")();
const mysql = require("mysql2/promise");

const DATABASE_URL =
  'mysql://29Bwg47KvhDQnm9.root:YOUR_PASSWORD_HERE@gateway01.ap-northeast-1.prod.aws.tidbcloud.com:4000/sample_data?ssl={"rejectUnauthorized":true}';

let connection;
fastify.get("/", async (request, reply) => {
  if (!connection) connection = await mysql.createConnection(DATABASE_URL);
  const result = await connection.query("SHOW DATABASES");
  return result[0];
});

fastify.listen({ port: process.env.PORT });
```

DATABASE_URLは管理画面から確認してね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/55c9a4f5-288b-e460-0ac9-ad1fe1f1474c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/8069df0c-d7fa-63d8-936b-608564ba401b.png)


Hello Node!の`blank version →`からサーバーが作れるよ

https://glitch.com/create-project

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/7d60b9b5-b7a0-116a-a347-e67ca9d548f9.png)
【FaaS】GlitchからPlanetScaleに接続する【Serverless】


```javascript:server.js
const fastify = require("fastify")();
const mysql = require("mysql2/promise");

const DATABASE_URL =
  'mysql://zaegdyhf7fyyjh5t5q9o:YOUR_PASSWORD_HERE@aws.connect.psdb.cloud/tokyo?ssl={"rejectUnauthorized":true}';

let connection;
fastify.get("/", async (request, reply) => {
  if (!connection) connection = await mysql.createConnection(DATABASE_URL);
  const result = await connection.query("SHOW DATABASES");
  return result[0];
});

fastify.listen({ port: process.env.PORT });
```

DATABASE_URLは管理画面から確認してね

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/80098497-4c43-30b4-6947-b6ca7713a73f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/bae4ab88-320d-4d47-e157-9c33525c25e7.png)

Hello Node!の`blank version →`からサーバーが作れるよ

https://glitch.com/create-project

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435735/7d60b9b5-b7a0-116a-a347-e67ca9d548f9.png)
Pythonの関数アノテーションと型ヒント　-> None の意味

Vscodeでは`def __init__`でタブ補完すると、自動的に`-> None`と出てくるので調べてみた。
# 関数アノテーションと型ヒント

- Pythonには、関数やクラスに対して **アノテーション（型注釈）** を付けることができる。
- 引数や戻り値、クラスの属性やメソッドの戻り値などについて、そのデータ型を明示することができる機能。
- 関数にアノテーションを付ける場合は、関数の定義の前に引数や戻り値に対するデータ型を
`->`を使って指定する。
- 引数はそれぞれに対して、戻り値は関数定義の最後に指定する。また、関数アノテーションにはPythonの組み込み型や自作のクラスを指定することができる。

```python
class Rectangle:
    width: int
    height: int

    def __init__(self, width: int, height: int) -> None:
        self.width = width
        self.height = height

    def area(self) -> int:
        return self.width * self.height
```

- あくまでもただの注釈であり、実行時に型チェックが行われたりはしない。そのため、アノテーションで指定した型以外の引数を渡しても何も起こらない **（エラーにならない）**。

```python
def func_annotations_type(x: str, y: int)-> str:
    return x* y

print(func_annotations_type('abc', 3))
# abcabcabc

print(func_annotations_type(4, 3))
# 12
```
Pythonでよく使うargsとkwargsについてまとめる

# argsとkwargs
PythonでDjangoなどのフレームワークを使っていると、関数やクラスの引数にargsとkwargsがよく出てくる。改めてまとめてみる。

# kwargsがある場合とない場合でどう違うか？

以下のような関数があったとする。

```python
def some_function(arg1, arg2):
		print(arg1, arg2)
```

この場合、`some_function`を呼び出す際には、`arg1`と`arg2`の2つの引数を指定する必要がある。例えば、以下のようにして呼び出すことができる。

```python
some_function(10, 20)
```

しかし、この関数に`kwargs`を追加すると、任意の数のキーワード引数を指定することができる。例えば、以下のようにして呼び出すことができる。

```python
some_function(10, 20, key1="value1", key2="value2")
```

この場合、`key1`と`key2`はキーワード引数であり、`arg1`と`arg2`とは別の引数として扱われます。しかし、`kwargs`がない場合は、キーワード引数を指定することができないため、上記のような呼び出し方はできません。

また、`kwargs`がある場合は、`kwargs`に指定されたキーワード引数を辞書として受け取ることができます。このため、`kwargs`を使用すると、可変長のキーワード引数を取り扱うことができます。

`kwargs` はkwのように任意の文字列に置き換えられる。が、混乱を招くかもなので、`kwargs`でいいかと。。。
【基本情報】基礎理論

# 計測と制御

## アナログとディジタル

### アナログデータ
連続的に変化する情報。

### ディジタルデータ
連続するアナログデータを区切って「0」と「1」に置き換えた不連続な情報。

### A/D変換
アナログデータをディジタルデータに変換すること。

### PCM伝送方式
アナログの音声信号をディジタル符号に変換する方式。

### 標本化(サンプリング)
時間的に連続したアナログ信号の波形を、一定の時間間隔で測定すること。

### サンプリング周波数(HZ)
1秒あたりのサンプリング回数。

### 量子化
測定した信号をあらかじめ決められた一定の間隔(2⁸、2¹⁶、2²⁴など)に区切り数値化すること。

### 符号化
量子化された値を2進数のディジタル符号に変換すること。

サンプリング周波数が短く、量子化の段階数が多いほど、元の音に近くなるが、データの容量が大きくなる。

## 制御技術

### フィードバック制御
外部の作用(外乱)の影響をセンサで検知して、コンピュータが判断し、修正動作を行う制御。

### フィードフォワード制御
前もって必要な修正動作を行う。

### シーケンス制御
あらかじめ定められた順序または条件に従って、制御の各段階を逐次進めていく。

### センサ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784589/ff296785-f9dd-65fe-4fc2-758a836aa19e.png)


### PWM
モータの回転速度やLEDの明るさなどをディジタル信号で制御する方式。
「ILI9341」に文字列を表示(Arduino)(STM32G071)


目的
「ILI9341」を使う事によって盛り上げる
いろいろ
説明不足だけど前後から読み取ってね
正式名は、
X-NUCLEO-GFX01M1
XNGF01M1$AZ1


![o_cop473.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/344985d3-b5c7-d470-385f-96ddd0ed1620.jpeg)



```C++



//ili9341_text1_071

//インクルド
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

//設定
#define TFT_RST A1
#define TFT_DC 3
#define TFT_CS 4

//液晶の定義
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

//初期化
void setup() {

  //シリアルの初期化
  Serial.begin(9600);
  Serial.println("ILI9341 Test!"); 

  //液晶のリセットピンの設定
  pinMode(TFT_RST, OUTPUT);
  digitalWrite(TFT_RST, HIGH);
  //digitalWrite(TFT_RST, LOW);

  //液晶の初期化
  tft.begin();

  //画面のクリア
  tft.fillScreen(ILI9341_BLACK);
  
  //表示位置を0,0にする
  tft.setCursor(0, 0);

  //テキストの表示
  tft.setTextColor(ILI9341_RED);    tft.setTextSize(3);
  tft.println("Hello World!");


}//setup


//無限ループ
void loop(void) {
}//loop




```
M5stack 動画再生の覚書

M5stack での動画再生の覚書



■参考
https://www.instructables.com/Play-Video-With-ESP32/
https://github.com/moononournation/RGB565_video

■使用したもの
https://github.com/moononournation/RGB565_video/tree/master/SDMMC_MJPEG_video_PCM_audio_dualSPI_multitask

■問題点
・Arduino_GFX バージョンを上手くあわせないとコンパイルエラー発生
※現在は治っているかもしれないが、以前はバージョンを（１．００？）かなり下げた

・M5stack LCDドライバが合わない
適切なドライバをあてる。動作するものに対し、IPS液晶の設定に変えた
また、その際、ガンマ設定を、IPS液晶の設定のものを割り当てた。
あと、使用するガンマセットの設定値が３種類（ガンマカーブ？）で
色反転を考慮した設定値にしないといけないらしい（どこかに書いてあった失念）


・音が大きすぎる
DACに渡しているデータに対し、補正を入れる。

・終了条件がおかしい
※現在はなおっているかもしれない。
１映像再生だと問題はわからないが、連続再生する場合、次の再生がおかしくなる
映像とサウンドの両方条件で終了するように修正した。

・再生途中で、映像、音声が咳き込む場合があった
結構悩んでいたが、SDカードが原因だった模様
現在ダイソーのHiDISC32GBでは、問題が見受けれない。
TOSHIBAメモリ64GBは認識しなかった。
同様な問題が発生する場合は、フォーマットも良いかも。

■自動変換化
現在ffmpegで複数のバッチファイルを作っておき、
mp4->mjpeg,pcmに変換しSDカードのフォルダに自動コピーする方法をとっている

バッチファイルにmp4ファイルを重ねるだけで、変換後のファイルがSDカードに入る
１個前のフォルダーは、移動するバッチを組んでいるので
４つmp4ファイルを順に(変換が終わる毎に）バッチファイルに重ねるだけで
４つファイルが入り、もともと入っていた映像フォルダは５個目に配置され
M5stackでは４，３，２，１，５の順で再生される。（プログラム自体にそのように変更が必要だが。。。）

画像調整の為に組んだので、非常に便利。

・ffmpegの設定
いろいろ探せば、情報があるので割愛
サイズ変更後、mjpegの、ffmpeg 2回変換を行う事でうまく変換ができる。
現在、スマホ動画が多いので、右変換ー＞サイズ変更とか、ローテイトは行わず、切り出し等

■その他
320x240では15fpsが良い感じ。30fps設定があるが、画像サイズを小さくしないと
帯域が間に合っていない。

以上
Blackjackgame

```ruby:blackjack.rb
   class Card
  attr_reader :rank, :suit

  def initialize(rank, suit)
    @rank = rank
    @suit = suit
  end

  def score
    case rank
    when 2..10
      rank
    when 'J', 'Q', 'K'
      10
    else
      11
    end
  end

  def to_s
    "#{suit}の#{rank}"
  end
end

class Deck
  SUITS = ['ハート', 'ダイヤ', 'スペード', 'クラブ']
  RANKS = (1..13).to_a

  def initialize
    @cards = SUITS.product(RANKS).map { |suit, rank| Card.new(rank, suit) }
    shuffle
  end

  def shuffle
    @cards.shuffle!
  end

  def draw
    @cards.pop
  end
end

class Hand
  def initialize
    @cards = []
  end

  def cards
    @cards
  end

  def add_card(card)
    @cards << card
  end

  def score
    total = @cards.sum(&:score)
    aces = @cards.select { |card| card.rank == 'A' }.count
    aces.times { total -= 10 if total > 21 }
    total
  end

  def to_s
    @cards.map(&:to_s).join(', ')
  end
end

class Player
  attr_reader :hand

  def initialize
    @hand = Hand.new
  end

  def hit(card)
    hand.add_card(card)
  end
end

class Dealer < Player
  def play_turn(deck)
    hit(deck.draw) while hand.score < 17
  end
end

class Game
  def initialize
    @deck = Deck.new
    @player = Player.new
    @dealer = Dealer.new
  end

  def start
    puts "ブラックジャックを開始します。"
    2.times { @player.hit(@deck.draw) }
    2.times { @dealer.hit(@deck.draw) }

   
    show_initial_cards

    player_turn
    return if busted?(@player.hand)

    dealer_turn
    determine_winner
  end

  private

  def show_initial_cards
    puts "あなたの引いたカードは#{@player.hand.cards[0]}です。"
    puts "あなたの引いたカードは#{@player.hand.cards[1]}です。"
    puts "ディーラーの引いたカードは#{@dealer.hand.cards[0]}です。"
    puts "ディーラーの引いた2枚目のカードはわかりません。"
  end

  def player_turn
    loop do
      puts "あなたの現在の得点は#{@player.hand.score}です。カードを引きますか？（Y/N）"
      answer = gets.chomp.upcase

      if answer == 'Y'
        card = @deck.draw
        puts "あなたの引いたカードは#{card}です。"
        @player.hit(card)

        if busted?(@player.hand)
          puts "あなたの現在の得点は#{@player.hand.score}です。"
          puts "あなたの負けです。"
          break
        end
      else
        break
      end
    end
  end

  def dealer_turn
    @dealer.play_turn(@deck)
  end

  def determine_winner
    puts "ディーラーの引いた2枚目のカードは#{@dealer.hand.cards[1]}でした。"
    puts "ディーラーの現在の得点は#{@dealer.hand.score}です。"
    puts "あなたの得点は#{@player.hand.score}です。"

    if busted?(@dealer.hand) || @player.hand.score > @dealer.hand.score
      puts "あなたの勝ちです！"
    elsif @player.hand.score == @dealer.hand.score
      puts "引き分けです。"
    else
      puts "あなたの負けです。"
    end

    puts "ブラックジャックを終了します。"
  end

  def busted?(hand)
    hand.score > 21
  end
end

game = Game.new
game.start
Power Virtual Agents for Teamsを試す

### Power Virtual Agentsとは

Microsoftの提供するPower Platformサービスの1つです。PowerPlatform全般に言えることですが、ローコード/ノーコードを前提としたサービスのため市民開発者が簡単にチャットボットのアプリケーションを作ることができます。

今回はその中でPower Virtual Agents for Teamsを試してみます。理由はM365の中に含まれているため、組織内にのみ公開することが前提ですが無料で使えるからです。

### Power Virtual Agents for Teamsを試す
#### Power Virtual AgentsをTeamsにインストールする

TeamsのデスクトップアプリでアプリタブからPower Virtual Agentsと検索するとアプリが出てくるのでインストラクションに沿ってインストールを進めます。

#### チャットボットを作成する

画面上部のChatbotsタブを選択するとチャットボットの管理画面が表示されます。My Chatbots > New chatbotを選択し、新しいチャットボットを作成します。チャットボットの名前と言語を選択し、Createを押下します。数秒程度でBOTが自動で構成されます。
![CreateChatbot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/6a48acdf-5647-bdfb-741f-b45a58ba3f10.png)

構成直後の時点で12のトピックスが設定されていました。フレーズに対する一連の流れが12パターンはデフォルトで設定されているということになります。
![FirstTopics.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/71514c80-335f-b320-5131-9bc8e5df6029.png)


#### 新しいトピックを設定する

早速新しいトピックを設定してみます。トリガーにユーザーがボットに話しかける言葉、メッセージは期待するボットからの返答を入れます。同じ画面でフローが正しく動作するか実際にすぐテストしてみることができるのでとても便利です。
![BlogTopic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/d0618fdf-b0e4-cf39-a757-89dee1e10250.png)

#### 公開する

左側のメニューからPublishを選択し、公開します。公開するとアプリとして追加できるようになるので追加します。以下のように設定した会話をこなすチャットボットが作成できました。
![MyFirstChatBot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/0558330c-5fcf-5049-ede7-706c405479f8.png)

### まとめ

Power Virtual Agents for Teamsを使ってノーコードでチャットボットを作成してみました。ChatGPTなど大規模言語モデルによって次世代対話型AIが流行る昨今ですが、そのままサービスを使うのではなく、アプリやチャットボットを自分の作業レベルで少しカスタマイズして構築したいといった際に、Power Platformを活用すると短時間でお試し実装できるのではないかと思っています。
私も初めて触ってみた程度ですが、Power Virtual AgentsにPower Automateを介してAzure OpenAIやOpenAIとも連携してみたらまたブログでご紹介します。ちなみにPower Virtual Agents自身にもBoost conversations（プレビュー）というOpenAIのGPT技術を活用してボットを高度化する機能がプレビュー提供されています。

### 参考・関連記事
機能を試してみるにあたって以下の記事を参考にさせていただきました。
1. [Power Virtual AgentsでTemasボットを作ってみた①　アプリの追加編](https://note.com/alice37308108/n/nfb17beb962d8)
1. [Power Virtual Agents for Teamsでチャットボットを作る① 使い方・導入方法](https://prtn-life.com/blog/chatbot-pva-teams1#toc8)
エレキ素人が何か考える（その20）：ラッチリレー

# ラッチリレーを試す
秋月電子で購入したラッチリレー「[ラッチリレー　ＤＣ５Ｖ　２回路Ｃ接点　２巻線　ＴＱ２－Ｌ２－５Ｖ](https://akizukidenshi.com/catalog/g/gP-16165/)」の動作を確認。マイコンとの組み合わせには、あまりにも乏しい内容となってしまいそうなので、今回はマイコンなし。

## ラッチリレーとは
通常のリレーでは、電流が流れると接点がON（またはOFF）、流れていないと接点がOFF（またはON）となる。ラッチリレーでは、接点の状態を保持するものであり、例えば、電流が流れて接点がONになり、電流が流れなくなっても接点がONのままとなる。下記サイト参照。
- [ラッチングリレーとは？](https://ac-faq.industrial.panasonic.com/ja-jp/knowledge/control/relay/mechanical_relay/mechanical_relay/latching-relay)

## ピンアサイン
はじめて[データシート](https://akizukidenshi.com/download/ds/Panasonic/tq.pdf)を見たところ、シロートには、よくわからず状態。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/4c9e9a81-fc66-cff5-98c7-c46c9240250d.png", width=40%>   <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/bf5cbfe9-25ca-3966-2d61-f013ec41a075.png", width=40%>
ネットで情報を調べると、下記サイトが参考となった。
- [relé de enclavamiento TQ2-L2-5V](https://electronica.guru/questions/83498/rele-de-enclavamiento-tq2-l2-5v)

これをもとに、試行錯誤した結果を下記する。

## 実験
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/8dc137e7-ad8e-1253-d8c3-c970070120da.png", width=80%>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/9a40cdd7-18b6-ff46-7b15-6333e0a71550.png", width=80%>
中央にある黒いものが、ラッチリレーである。

配線した回路では、左のボタンを押すと左のLEDが点灯し、右のボタンを押すと右のLED（抵抗入り）が点灯する。結果として、下記のような回路であることが判明。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/52cc6d59-48d0-397a-6364-6aa468b2ec07.png)
とは言え、データシートのピンアサインメントの理解は、今ひとつであった。

EOF
ALB概念図

# AWSのALBに関連する概念のまとめ

```mermaid
classDiagram

ALB o--> "*" Listener
Listener --> "*" TargetGroup
TargetGroup --> "*" Target

ALB --> "*" SG
ALB --> "2...*" AZ

Listener o--> "*" Rule
Rule --> TargetGroup
Listener --> "0...1" Cert

class ALB {
  DNS名
  アクセスログ有効化
}

class Listener {
  プロトコル
  ポート
}

class TargetGroup {
  ターゲットタイプ
  プロトコル
  ポート
  ヘルスチェック設定
  スティッキーセッション設定
}

```

- ALB
    - ここが起点となる。DNS名を割り当てられる
    - アクセスログは「属性」タブから有効化できる
- Listener
    - ALBが待ち受けするポート
    - ALBには複数のListenerがつけられるので、複数ポートで待ち受けることができる
    - プロトコルはhttpかhttps
    - httpsで待ち受けるときは、証明書をつけておく
- Listener Rule
    - 受け取ったリクエストをどのTargetグループに転送するかを決める
    - 最も単純な使い方は、すべてのリクエストを一つのTargetGroupに転送すること
    - 「リクエストのパス」、「クエリパラメータの値」、「呼び出し元IP」などをもとに転送先を別のターゲットグループにしたり、拒否したりできる
    - 転送、拒否以外に、リダイレクト、OIDC認証、Cognito認証などものアクションがある
    - CloudFrontからのリクエストのみ受け付ける場合などにも利用される
- TargetGroup
    - 転送先（Target）をグループ化したもの
    - 一つのTargetGroup配下のTargetは均質とみなされ、負荷分散の対象となる
    - ターゲットタイプは、EC2のときはインスタンス、ECSのときはIPアドレス
    - EC2オートスケーリングや、ECSオートスケーリングでは、それぞれの設定画面で、どのTargetGroupを使うかを指定する
    - 「属性」タブからスティッキーセッションを有効にできる
vbsの作法 その58

# 概要
vbsの作法、調べてみた。
vbsから操れるUIコンポーネントをC#で書いてみた。
練習問題、やってみた。

# 練習問題
じゃんけんを実装せよ。

# サンプルコード

```
Dim o
Set o = CreateObject("Ohi.Compo7")
Do While True
	Randomize
	str = "じゃんけん　　0, グー 1, チョキ  2, パー"
	o.Put str
	v = o.Open()
	a = Cint(v)
	b = Int(Rnd * 3)
	Select Case a
	Case 0
		Select Case b
		Case 0
			str = "グーとグーで、あいこ"
		Case 1
			str = "グーとチョキで、あなたの勝ち"
		Case 2
			str = "グーとパーで、あなたの負け"
		End Select
	Case 1
		Select Case b
		Case 0
			str = "チョキとグーで、あなたの負け"
		Case 1
			str = "チョキとチョキで、あいこ"
		Case 2
			str = "チョキとパーで、あなたの勝ち"
		End Select
	Case 2
		Select Case b
		Case 0
			str = "パーとグーで、あなたの勝ち"
		Case 1
			str = "パーとチョキで、あなたの負け"
		Case 2
			str = "パーとパーで、あいこ"
		End Select
	End Select
	msgbox str
Loop
Set o = Nothing





```


以上。
LinuxのIPアドレスの確認方法・そもそもIPアドレスについて

以下はメモ兼自己学習用に記載する
Linuxコマンド練習サイトにて興味深い内容があった。
・DNSサーバーを構築しよう
・Webサーバーを構築しよう
の2点だ。
現状自分の知識としてはLinuxで出来ることは、サーバー内の情報の検索、抽出、DB接続(SELECTなどの操作含む)といった保守・開発にとどまる範囲内の知識しかない。
※資格的にはおそらくLpic101/102の範囲内のはず・・・

サーバー構築はおそらくLpic201/202でやる範囲なのかなぁ。。
といったところで勉強を兼ねていろいろ経験してみたいと思います。




まずは、そもそもIPアドレスについて
学習する前
IPアドレスとは、192.168.xxx.xxxなどといった3桁×4の12行からなる数列の固有番号

学習した後
IPアドレスとは、192.168.xxx.xxxなどといった3桁×4の12行からなる数列の固有番号
かつ上記固有番号からネットワーク部、ホスト部に分かれる。
こんな感じ↓
　　　　　　192　.　168　.　100　.　　　107
　　　　　＿＿＿＿＿＿＿＿＿＿　　＿＿＿＿＿
　　　　　　　ネットワーク部　　　　ホスト部
その切り分け方としてサブネットマスクというものが存在する。/24とか/16てやつ。
結論としては、ネットワーク部の大きさを表すもの

じゃあやり方を見ていくと、まずIPアドレスを2進数に直します。
　　　　　　192　.　168　.　100　.　　　　　　　　　　　107
　　　　　11000000　.　10101000　.　01100100　.　　　01101011
　　　　　＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿＿　　  　＿＿＿＿＿
　　　　　　　　　　　　ネットワーク部　　　　　　　 　　ホスト部
そこから/24で考えると頭の11000000から24個目が01100100の0になる。
そこがネットワーク部とホスト部の境目になる。

正しいやりかただと、/24が255.255.255.0のIPアドレスと想定して、
11111111.11111111.11111111.00000000になって1のところがネットワーク部、0のところがホスト部
みたいに判断するらしい

#####################################################################
続いて
LinuxのIPアドレスの確認方法

仮想環境上にLinuxサーバを用意しているのでそちらを使用
ログインして場所はどこでもいいので
ip address
上記のコマンドを打ち込む
以下出力結果
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 pdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
        valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
        valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 pdisc pfifo_fast state UP group default qlen 1000
    link/eter 08:0027:86:f3:c5 brd ff:ff:ff:ff:ff:ff:ff

以上
これを手打ちでやったのでかなりきつい(間違いないことを願ってます)
今度VMで作成したLinuxサーバにコピー＆ペーストする方法調べて記事作ります。。。きつかった。。。

はい、内容はほとんど理解できていないですが3行目のinet‥‥てやつがIPアドレスらしい

どうやらip addressのうちipがコマンドでaddressは引数みたい
つまり、すべてのインターフェースのIPアドレスが表示される。
先ほどの例だとIPv4とIPv6の2つの情報が出力されている。
IPv4アドレスだけ表示させたい時は、ip -4 addressらしい
GitHub Actionsで他のジョブの環境変数を参照する

# 問題点

- あるジョブの環境変数を別のジョブで受け取り、その結果に基づいて処理を行いたいことがある
- 例えば自動テストの結果(成功/失敗)をSlackに通知する場合など
- しかし、GitHub Actionsではジョブ間の環境変数の受け渡しを直接行う機能は用意されていない

# 解決策

- 一旦ファイルとして書き出してアップロードし、そのファイルを別のジョブからダウンロードして参照するというのが一般的な解決策となる
- ファイルのアップロードやダウンロードを行えるアクションとして`actions/upload-artifact@v3`と`actions/download-artifact@v3`が用意されている

# 検証

- 設定

```yaml:.github/workflows/main.yml
name: Artifacts example

on:
  push:

jobs:
  something-job:
    runs-on:
      - ubuntu-latest

    steps:
      # 自動テストの実行等
      - name: Do something
        run: echo Something

      - name: Save job status
        # 前のステップの成功/失敗に関わらず、このステップが実行されるようにする
        # デフォルトでは前のステップが失敗した場合、後続のステップは実行されない
        if: always()
        # ジョブのステータス(成功/失敗)をファイルに書き出し
        run: echo "${{ job.status }}" > something-job-status

      - name: Upload job status
        if: always()
        # ファイルのアップロード
        uses: actions/upload-artifact@v3
        with:
          name: something-job-status
          path: something-job-status

  notify:
    # something-job の実行後にこのジョブが実行されるようにする
    needs:
      - something-job

    # 前のジョブの成功/失敗に関わらず、このジョブが実行されるようにする
    # デフォルトでは前のジョブが失敗した場合、後続のジョブは実行されない
    if: always()

    runs-on:
      - ubuntu-latest

    steps:
      # ファイルのダウンロード
      - name: Download something job status
        uses: actions/download-artifact@v3
        with:
          name: something-job-status

      # something-job のジョブのステータスを参照
      - name: Display job1 status
        run: cat something-job-status
```

- 実行結果

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78249/019e0cc3-badc-fee3-03a8-7b38b0501cef.png)
.NET MAUIでの依存性注入とプラットフォーム固有コードの管理

.NET MAUIでは、アプリケーションのコードを綺麗に保ちながら、プラットフォーム固有の実装を効果的に管理できます。この記事では、依存性注入を使ってプラットフォーム固有の実装を管理する方法と、コンパイラディレクティブを使ったアプローチの違いについて説明します。

## 依存性注入とは

依存性注入（Dependency Injection）は、オブジェクト間の依存関係を管理するデザインパターンです。これにより、コードの可読性と保守性が向上し、アプリケーションの構造が改善されます。

## .NET MAUIでの依存性注入

例として、プラットフォームごとに異なるデバイス名を取得するアプリケーションを考えます。

1. 共通インターフェイスの作成: プラットフォーム固有の機能にアクセスするための共通インターフェイスを定義します。
    ```csharp
    public interface IDeviceNameService
    {
        string GetDeviceName();
    }
    ```
1. プラットフォーム固有の実装: `Platforms`ディレクトリ内の各プラットフォームで、先ほど定義したインターフェイスの実装を提供します。
    ```csharp: Androidの実装
    public class AndroidDeviceNameService : IDeviceNameService
    {
        public string GetDeviceName()
        {
            return "Android Device";
        }
    }
    ```
    ```csharp: iOSの実装
    public class IOSDeviceNameService : IDeviceNameService
    {
        public string GetDeviceName()
        {
            return "iOS Device";
        }
    }
    ```

3. 依存関係の登録と解決: アプリケーションの初期化時に、依存関係を登録し、アプリケーションの他の部分で、依存関係を解決して使用します。

```csharp: Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<IDeviceNameService, AndroidDeviceNameService>();
}
```


アプリケーションの他の部分で、依存関係を解決して使用します。
```csharp
public class MainPageViewModel
{
    private readonly IDeviceNameService _deviceNameService;

    public MainPageViewModel(IDeviceNameService deviceNameService)
    {
        _deviceNameService = deviceNameService;
    }

    public string GetDeviceName()
    {
        return _deviceNameService.GetDeviceName();
    }
}
```

## .NET MAUIのディレクトリ構成

.NET MAUIでは、プラットフォーム固有の実装を`Platforms`フォルダ内に配置します。以下は、一般的なディレクトリ構成の例です。

```
MyApp
│   Startup.cs
│   MainPage.xaml
│   MainPage.xaml.cs
│
└───Platforms
    ├───Android
    │       AndroidDeviceNameService.cs
    │
    └───iOS
            IOSDeviceNameService.cs
```

この構成では、`Platforms`フォルダにそれぞれのプラットフォーム（AndroidやiOSなど）ごとにサブフォルダがあります。これにより、プラットフォーム固有の実装が整理され、アプリケーションの保守性が向上します。


## コンパイラディレクティブとの違い

コンパイラディレクティブ（`#IF ANDROID`など）は、コードが特定のプラットフォームやコンパイ
ール条件に基づいてコンパイルされるかどうかを制御するために使用されます。しかし、これらのディレクティブは、コードが難解になり、保守が難しくなることがあります。

例えば、コンパイラディレクティブを使ってデバイス名を取得するコードは以下のようになります。
```csharp
public string GetDeviceName()
{
#if ANDROID
    return "Android Device";
#elif IOS
    return "iOS Device";
#else
    return "Unknown Device";
#endif
}
```

この方法では、プラットフォーム固有のコードが一つの場所に混在しており、これが複雑になるとコードの可読性が低下します。依存性注入を使用することで、プラットフォーム固有の実装を分離し、コードの構造と保守性を向上させることができます。

## まとめ
.NET MAUIでは、依存性注入を使用してプラットフォーム固有の実装を効果的に管理することができます。これにより、アプリケーションのコードが綺麗に保たれ、保守性が向上します。一方、コンパイラディレクティブを使ったアプローチは、コードの可読性が低下し、保守が難しくなることがあります。依存性注入を使ったアプローチを選択することで、アプリケーションの品質を向上させることができます。
Rubyファイル実行時に引数を指定：OptionParser標準ライブラリ

# OptionParserについて
`OptionParser`は、Rubyの標準ライブラリで、コマンドライン引数の解析を簡単に行うためのクラスです。以下に、`OptionParser`の使い方をまとめました。

1. 全文
    ```ruby
    require 'optparse'
    
    # オプションを格納するハッシュ
    options = {}
    
    # OptionParser オブジェクトの作成とオプションの定義
    OptionParser.new do |opts|
    
      # -n オプション (数字の指定)
      opts.on('-n NUMBER') do |number|
        options[:number] = number.to_i
      end
    
    end.parse!
    
    # オプションが指定されていない場合、1000
    number = options[:number] || 1000
    
    puts "指定された数字: #{number}"
    ```

2. `require 'optparse'` を使って、`OptionParser` をインポートします。

    ```ruby
    require 'optparse'
    ```

3. `OptionParser` オブジェクトを作成し、オプションを定義します。

    ```ruby
    # オプションを格納するハッシュ
    options = {}
    
    OptionParser.new do |opts|
      # オプション定義
    end.parse!
    ```

4. `opts.on` メソッドを使用して、オプションを定義します。

    ```ruby
    opts.on('-n NUMBER') do |number|
      # オプション処理
    end
    ```

5. オプションに関連付けられたブロック内で、オプション値の処理を行います。このブロックは、オプションが指定されたときに実行されます。

    ```ruby
    options[:number] = number.to_i
    ```

6. `parse!` メソッドを呼び出して、コマンドライン引数を解析します。これにより、定義されたオプションに従って引数が解析され、関連するブロックが実行されます。

    ```ruby
    OptionParser.new do |opts|
      # オプション定義
    end.parse!
    ```

7. オプションが解析された後、`options` ハッシュを使用して、オプション値にアクセスできます。

    ```ruby
    number = options[:number] || 1000
    ```

8. 実行結果
    ```ruby
    # オプションを指定した場合
    $ ruby test.rb -n 30
    指定された数字: 30
    
    # オプションを指定しない場合
    $ ruby test.rb      
    指定された数字: 1000
    ```
The ISTQB® Game Testing certificationを大雑把に訳したり解説してみるよ 【概要】

■この文章のAI要約
「JSTQBは、ソフトウェアテスト技術者の認定制度を運営する日本の団体で、ソフトウェアテストの国際的な認定機関であるISTQBと提携をしています。JSTQBが提供する資格制度は、海外でも認められています。ISTQB Game Testing認定資格は、ISTQBが提供するゲームテストの専門資格で、Foundation Level（FL）の上位に位置し、前提条件としてFL認定が必要です。認定試験を受けるには、ゲームソフトの開発またはテストの経験が1年以上あり、ISTQBが認定するコースを修了していることが望ましいとされています。シラバスでは、ゲームテスト、ゲームメカニクス、グラフィックテスト、サウンドテスト、ゲームレベルテスト、ゲームコントローラーテスト、ローカライズテストの特異性をカバーしています。」



■前置き
自分用のメモ書きという前提です。
大雑把に訳したり解説をしたりするので、誤った箇所がありましたらコメントに書くとこの記事を読んだ方の情報の誤りが無くなるのでコメント書いておくととても良いです。
ただし本文の訂正はおそらくしません、本来であればこんな文章を軸に学習を進めるより、
自分で公式HPを確認した方が望ましいからです。
また、「」で囲われている単語ではない文章はChatGPTに要約させて整合性をざっと確認して多少文面を整えています。
訳はDeepLを使用した上で文面を整えています。

※以下ISTQB、JSTQBについてご存じの場合、本文まで読み飛ばしてください。
皆さんはISTQB®についてご存じでしょうか、先に説明すると国内にはソフトウェアテストで徐々に知名度が上がっているといわれているJSTQBは「日本のソフトウェアテスト技術者資格認定の運営組織であり、ISTQBの加盟組織である。各国団体は相互認証を行っており、JSTQBが運営するソフトウェアテスト技術者資格は海外でも有効である。 JSTQBは、品質保証関連の研究を行っている3つの委員会から構成されている。」とされています。

詳しくは公式HPの「JSTQBについて」を確認してください。

https://jstqb.jp/index.html

このJSTQBについてはソフトウェアテスト業界ではそこそこ知られており
時折第三者検証機関向けの企業で基礎資格であるFoundation Level(以下FLと記述)や応用資格であるAdvanced Levelの取得に言及が見られます。[^1]
その大本であるISTQBではJSTQBと比較するとかなり多くの資格認定があります。

ISTQB公式HP

https://www.istqb.org/


■本文
さて、The ISTQB® Game Testing certificationはそのISTQBの中にあるゲームテスト[^2]についての資格があります。

・ISTQB ®認定資格(chromeで一部訳されている状態です。)
![ISTQBno.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501190/5195a96a-fe86-2c7a-cf02-5807fc24b669.jpeg)

https://www.istqb.org/#certifications-diagram

 より

「Game Testing」は基底であるFLの一つ上に位置づけられ、
SPECIALISTについての区分けがされています。

「ISTQB_CT_GaMe_Syllabus_Release_v1.0.1」の「0.6 The Certified Tester Game Testing Certificate Exam」によれば資格試験を受けるには、FLの資格取得が必要です。
また、推奨ですが以下のことも求められます。
・1年以上のゲームソフトウェアの開発またはゲームテスト(例えばユーザ受け入れテスト)の従事
・ISTQBが認定したコース（ISTQB-recognizedメンバーボードの1つによって）を受講すること

また、これらの情報については以下のサイトから取得できるので確認してください。
Certified Tester Game Testing (CT-GaMe)
https://www.istqb.org/certifications/game-testing

シラバスでは「この文章は、ゲームテストの特異性、ゲームの仕組み、グラフィックステスト、サウンドテスト、ゲームレベルのテスト、ゲームコントローラのテスト、ローカライズテストについての7つの章から構成されています。それぞれの章では、テスト実行の目的、手法、ベストプラクティス、ツールサポート、関係者の責任範囲などが説明されています。」
より詳しく知りたいのであればシラバスで確認するといいでしょう。

今回は概要を超大雑把に説明しましたが、気が向いたらこのシラバスを大雑把に訳したりすると思います。




[^1]:難易度はそこそこ難しく、基本情報技術者試験くらいといわれており、ベテランのソフトウェアテスト従事者でも不合格になっているのを見かけます。この資格が全部というわけではないですが、仕事にそれなりの意識があるなら取得する方が望ましいと個人的に思います。

[^2]:ゲーム業界ではゲームデバッグやゲームデバックと表記されます。テストなのに。
今日から勉強の記録を始めます

こんにちは。ねこと申します。
エンジニアになりたいと思い、去年からプログラミングを勉強し始めました。
外国人なので、変な日本語かもしれませんが、記録していきたいと思っています。

もうすぐGWですね。今度のGWは三年半ぶりに帰国する予定です。そんなわけで、精神的に興奮している中、今日もカフェでJavaウェブ開発の勉強をしていました。

今日はFilterの勉強をしました。Filterはろ過する機能だけでなく、Servletが働く前の事前処理、Servletが働いた後のデータ処理などの機能もあるとわかりました。

また明日続きます。
個人開発でRuboCopの警告について考えてみた

# はじめに
個人開発の学習用メモとして投稿します。
RuboCopとは、Rubyの静的コード解析及びコードフォーマットを実行するgemです。個人開発で自分がRuboCopを導入した際に遭遇した警告のいくつかをピックアップし、それに対してどう対応したかについて書いていきます。
Ruby初心者ゆえ理解が足りていないところもあると思いますので、誤り等あれば遠慮なくご指摘ください。

# 警告①「C: Naming/AccessorMethodName: Do not prefix reader method names with get_.」
メソッド名に接頭辞get_を付けるなという警告です。
例えば、年齢を表すインスタンス変数ageがあるとして、その年齢を取得するメソッドの名前は、"get_age"ではなく、"age"が推奨されます。他の言語だと、メソッド名にget_を付けるのは珍しくないと思いますが、Rubyでは、アクセサのメソッド名にget_を付けるのは推奨されません。

https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Naming/AccessorMethodName

因みに、Rubyでは、引数のないメソッドの呼び出しは()を省略できるということもあり、自分のコードは次のように書いていました。

```ruby
something = get_something
```
これだと警告に従って機械的にget_を削除すると、メソッド名と変数名が同じになってしまいます。。
この問題については、こちらの記事でも触れられています。

https://qiita.com/jnchito/items/fb438aa0786bb3cbf919

変数名を変えれば重複はしないものの、何となく無理矢理感が否めません。。

因みに、このルールを無効化したい場合は、.rubocop.ymlに次のように追記すれば良いとのことです。
```
Naming/AccessorMethodName:
  # Enabled: false
```
ただ、このルールは、いわゆるアクセサに対するもののようです。
しかし、自分が書いたメソッドは、標準入力から値を取得するもので、いわゆるアクセサではありませんでした。
そのためルール自体を無効化してしまうのではなく、次のように.rubocop.ymlに追記し、このメソッドを使用しているファイルをRuboCopの対象から除外することにしました。
```
Naming/AccessorMethodName:
  Exclude:
    - 'filepath'
```
# 警告②「C: Naming/PredicateName: Rename is_xxx? to xxxx?」
メソッド名に接頭辞is_を付けるなという警告です。
例えば、平日かどうかを判定するメソッドがあるとして、そのメソッドの名前は、"is_weekday?"ではなく、"weekday?"が推奨されます。他の言語だと、メソッド名にis_を付けるのは珍しくないと思いますが、Rubyでは、真偽値を返すメソッドの名前にis_を付けるのは推奨されません。

https://www.rubydoc.info/gems/rubocop/RuboCop/Cop/Naming/PredicateName

他の言語で慣れているからか、接頭辞is_のメソッドに特に違和感はないのですが、郷に入っては郷に従えということで、メソッド名からis_を削除しました。

# 警告③「C: Naming/PredicateName: Rename has_xxx? to xxx?」
これも②と同様、メソッド名に接頭辞has_を付けるなという警告です。
例えば、トランプゲームで、プレーヤーがジョーカーを持っているかを判定するメソッドがあるとして、そのメソッドの名前は"has_joker?"ではなく、"joker?"が推奨されます。これも他の言語だと、メソッド名にhas_を付けるのは珍しくないと思いますが、Rubyでは、真偽値を返すメソッドの名前にhas_を付けるのは推奨されません。

ただ、これについては正直腹落ちしないところがありました。
例えば、呼び出しを考えると、警告②では、仮にレシーバーがselected_dayであったとすると次のようになると思います。
```
selected_day.weekday?
```
自分の感覚でも、これは選択した日が平日かどうかを判定していると直感的に理解できます。
これに対して、警告③では仮にレシーバーがplayer1であったとすると次のようになると思います。
```
player1.joker?
```
これはplayer1がジョーカーを持っているかどうかを判定していると直感的に理解できるでしょうか？
これに対して、次のようなものであれば、十分直感的に理解できます。
```
player1.has_joker?
```
Rubyのお作法といえば、それまでなのでしょうが、正直自分の感覚で言うと、"player1.joker?"だと、player1がジョーカーを持っているかではなく、player1自身がジョーカーかどうかを判定しているように思えてしまいます。

### 結局どうしたか

リファクタリングを重ねた結果、最終的には接頭辞has_のメソッド自体が不要になりました（無理矢理そうしたわけではありません）。
ただ、やはり何かを持っているかどうかを判定するメソッドの接頭辞has_を省略するのは、自分の感覚では可読性が下がっているように思えてしまいます。慣れれば名詞の後に名詞?が来ると、暗黙的にhas_が省略されているものとして、すんなり読めるようになるのでしょうか？ 
とりあえず今回はルールの無効化は行いませんでしたが、今後個人開発で何かを持っているかどうかを判定するメソッドが必要になった場合には、ルールの無効化も検討したいと思います。
因みに、このルールを無効化したい場合は、.rubocop.ymlに次のように追記すれば良いとのことです。
```
Naming/PredicateName:
  Enabled: false
```
場合によっては、接頭辞is_とhave_は禁止するものの、has_は許可しても良いかも知れません。
※もちろんチーム開発の場合はチームのルールに従います。
bash?cmd?こいつら何が違うの？？？

## 背景
最近新卒研修のメンターをしているのだが、そこでTera Termという単語を久々に聞いた。そういえば自分も研修の時にEC2にSSH接続するためにインストールしたことを思い出した。
見た目はコマンドプロンプトやPower Shellなどと変わらないが、わざわざインストールする必要があったのか？そもそもコマンドプロンプトとPower Shellって1つじゃダメなの？git bashもインストールしたけど何？１つに統一してくれ!!と疑問が湧いてきたにで、ちょっとまとめようと思う。

## シェルとターミナル
そもそも、このあたりの用語をきちんと理解しないまま生きてきたので、一度整理しておきたい。
教えて！GPT先生


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661124/c1b25d10-5285-e77d-d062-8f26ef9d7b49.png)

> 簡単に言えば、ターミナルはユーザーとコンピュータ間のコミュニケーションを可能にするインターフェースであり、シェルはそのコミュニケーションを通じてオペレーティングシステムを操作するためのプログラムです。ユーザーはターミナルを通してシェルにコマンドを入力し、シェルはそのコマンドを解釈してオペレーティングシステムに伝え、実行します。

とあるように、ターミナルはインターフェース、シェルはプログラム（を実行しているところ）と覚えておけばよさそう。
でも、git bashとか、コマンドプロンプトとかって、開いたときに違う画面がでますよね？
あれ自体はターミナルで、シェルではないってことですかね？
あのターミナルに対してコマンドを打ち込み、その実行されるプログラミング自体をシェルって言ってるんですかね？
気になるので追加質問

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661124/a6e67977-778d-8df0-c264-cacb55a407b0.png)
とのこと。
シェルがターミナルの部分も持っている、といういうことですかね。
何ともわかりづらいですね。



## OS
ところでOSって何なんですかね。オペレーティングシステムの略ってぐらいはわかるけど...
PCの本体的なイメージがありますが、一言でいうと何なのでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661124/01b57209-72cc-c31f-208d-b02689ddc3f9.png)
一言でいうと「コンピュータの基本的な機能とリソースを管理するソフトウェア」とのこと。
PCの中身全体を管理しているアプリ、と思えばいいのかな？

あと、シェルとOSは一対一で対応しているものだと思っていましたが、どうやら違うみたいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661124/2e4917a8-95d3-88d9-b515-e20b037e8993.png)


## Bash, コマンドプロンプト, PowerShellはShellである。では、Tera Termは？
Tera Termはこれらの中で少しが違う。
これは「端末エミュレータ」に属します。違いは以下です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661124/cf3d79e9-38a9-84f2-f242-8e8fe7d81c62.png)
端末をまねしたやつって感じですね。
というかここで気づいたのが「端末＝ターミナル」だということ。
インターフェースってなんやねん、と思っていましたが「ユーザからの入力を受け付ける（あと出力も表示する）ところ」って考えるとめちゃくちゃしっくりきますね。
いや、言葉の意味考えたらそらそうやろ、って感じなんですけどね。
とにかく腑に落ちました。


## コマンドラインアプリケーション
gitとか、npmとか、どのシェルのターミナルを使っても実行できるCLIは、コマンドラインアプリケーションと呼ぶみたいです。
なぜどのシェルでも使えるかというと、命令を渡す相手がシェルによらずに、最初にしているgit, npmなどで指定されているからだと思われます。
シェル固有のコマンドをつかってコマンドを打っているときは、「os」という接頭辞を省いていると考えればすんなりいきました。osによってシェルが命令を渡す相手が変わるので、命令が伝わらないのではないか、という気がしました。

具体的には、(git pushみたいな感じで）windows dirは存在するけどwindows lsは存在しない、という条件でwindows lsって打っても当然命令は通らない。逆にmac lsは存在するけど、mac dirは存在しない状態で、mac lsでは通るけど、mac dirは通らない、みたいな。

## 
まとめ
・ターミナルは、ユーザーとPCのインターフェース
・シェルはコマンドとOSの橋渡し役。ただ、シェルが独自のターミナルを持つことが多い
・Tera Termはターミナルエミュレータ
・CLI以外のコマンドは先頭にmacかgoogleみたいな（うまくよくわかっていないが）をつけずに売っているんだろうな、と感じでした。

3週目にして早くもネタが切れそうでしたが、頑張って記事にしました。
やはり、前提知識が少ない、把握しづらいプロジェクトの大変さを思い知りました。
間違い、指摘箇所だらけだと思います。どなた様でも、この記事の内容などについてアドバイスあればぜひぜひ教えてください。
Postfixの設定ファイル「/etc/postfix/main.cf」の書式と主な設定項目

●Postfix
PostfixはLinuxでよく使用されるMTA。sendmail（MTAの1つ）と互換性があり、設定が容易でセキュリティーが高いことが特徴。

Postfixの主な設定ファイルは「/etc/postfix/main.cf」。
main.cfでは「設定項目 = 値」という形式で設定内容を記述。

●Postfixの設定ファイル「/etc/postfix/main.cf」の書式と主な設定項目

設定項目
・myhostname　自サーバのホスト名を指定
・mydomain　自サーバのドメイン名を指定
・myorigin　メールアドレスの「＠」以降に使用するドメイン名を指定
・inet_interfaces　メールを受け取るネットワークインターフェースを指定
・mydestination　ローカル配送を行うドメイン名を指定
・mynetworks　リレーを許可するクライアントを指定
・mail_spool_directory　メールスプールディレクトリを指定
・home_mailbox　ユーザのホームディレクトリ配下のメールスプールディレクトリを指定(ホームディレクトリからの相対パス)
・mailbox_command　ローカル配送を行うプログラム（MDA)を指定
・disable_vrfy_command　SMTPコマンドのVRFYの使用を無効化(yes)/有効化(no)するかを指定
・relay_domains　許可されたクライアント以外からのメールの中継先を指定。デフォルトは$mydestination
・transport_maps　メールリレーの設定情報を指定

●main.cf内では以下の記述もできます。
・「#」で始まる行はコメントとして扱う
・値を「$設定項目名」とすることで、他の設定項目に指定した値を参照できる
・一つの設定項目に複数の値を指定する場合はカンマ（,）で接続する
・改行して空白（スペース）で始めることで、直前の行からの継続として扱う
LoRAによる めるアイコン生成

## めるアイコンとは

左下から顔を出してるデザインの、私が描いているデフォルメイラストアイコンです。

<img alt="IMG_1748.PNG" width=256 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494881/b3f118a5-b8d1-4f30-c5fe-2f1fc2999b1d.png"/>

最近は仕事が忙しくてなかなか描けていませんが、たまに依頼募集してます。

## 先行研究
めるアイコンのAI生成はすでに先行研究がいくつかあります。

**UGATIT**による手法（@zassou65535さん）

https://qiita.com/zassou65535/items/4bc42fa36203c13fe2d3

**Progressive GAN**による手法（同じく、@zassou65535さん）

https://qiita.com/zassou65535/items/57fe3bd677159cdb2528

**StyleGAN2**による手法（@kunseicunseiさん）

https://qiita.com/kunseicunsei/items/35e5713939cbea1646ba

私は@zassou65535さんや@kunseicunseiさんと違って機械学習はド素人なのですが、LoRAを使えばそんな私でもお手軽にAI生成ができるぞってことで、やってみました。

この記事では技術に関する詳細な説明は行いません。

## 結果
適当に背景色を指定しながら16枚ずつ出力しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494881/c14452f8-bb57-ee72-9799-02fb68736715.png)
私としては、これはなかなか良さそうだぞ、と思いました。

## 深掘り
### 学習データ
過去に書いた700枚以上あるアイコンから、特に可愛くかけたぞって自信があるやつを349枚選びました。

### 使用したもの
基礎技術は[StableDiffusion](https://ja.stability.ai/stable-diffusion)です。
ベースとなるモデルは[anything-v4.5-pruned](https://huggingface.co/andite/anything-v4.0/tree/main)です。
キャプションの生成は[wd14-tagger](https://github.com/toriato/stable-diffusion-webui-wd14-tagger)を利用しました。
LoRA学習は[sd-scripts](https://github.com/kohya-ss/sd-scripts)を利用しました。
最終的な生成には[Stable Diffusion web UI](https://github.com/AUTOMATIC1111/stable-diffusion-webui)を用いました。

### キャプション
キャプションはwd14-taggerによる自動生成ですが、以下をExclude tagsに設定しています。
`solo, 1girl, simple background, looking at viewer, dutch angle, outline`

### 学習
train_batch_size = 3 (4以上だとメモリ的に無理でした。)
max_train_epoch = 15 (だいたい10～15あたりで頭打ちになるように思われます。)
num_repeats = 1

これで計1755ステップ、25分12秒で学習は終了しました。

### 環境
CPU : AMD Ryzen 7 7700X 8-Core Processer
GPU : NVIDIA GeForce RTX 3070 Ti
RAM : 32GB(16GBx2) 4800 MHz

### プロンプト
青背景 : `(best quality, masterpiece:1.2), (melicon:1.3), blue background, smile, <lora:melicon-anything4.5-15epoch:1>`

緑背景 : `(best quality, masterpiece:1.2), (melicon:1.3), green background, smile, <lora:melicon-anything4.5-15epoch:1>`

ピンク背景 : `(best quality, masterpiece:1.2), (melicon:1.3), pink background, smile, <lora:melicon-anything4.5-15epoch:1>`

黄背景 : `(best quality, masterpiece:1.2), (melicon:1.3), yellow background, smile, <lora:melicon-anything4.5-15epoch:1>`

### ネガティブプロンプト
`(worst quality, low quality:1.2), bad anatomy, bad hands, missing arms, text error, missing fingers, jpeg artifacts, long neck, signature, watermark, blurry, fisheye lens, animal, deformed mutated disfigured, mutated hands, missing hands, extra hands, liquid hands, poorly drawn hands, mutated fingers, bad fingers, extra fingers, liquid fingers, poorly drawn fingers, bad legs, missing legs, extra legs, bad arms, extra arms, long torso, thick thighs, partial head, bad face, partial face, bad eyebrows,`

（[テルルとロビンチャンネルの動画](https://www.youtube.com/watch?v=8QIJMGW_-LM)を参考にしました。）

## 参考にしたもの
LoRA学習は以下の動画を参考にしました。非常にわかりやすかったです。

https://www.youtube.com/watch?v=N1tXVR9lplM

Stable Diffusion web UIの使い方は以下の動画を参考にしました。こちらも非常にわかりやすかったです。

https://www.youtube.com/watch?v=8QIJMGW_-LM
【Unity】PhotonFusion2 の INetworkRunnerCallbacks を R3 で Observable にしてみた

# 概要
NetworkRunner の INetworkRunnerCallbacks を Observable にして、手軽に扱えるようにしました。
不具合や改善点などのコメントをいただけると助かります。

``` プレイヤー入室ログの実装例.cs
Runner.OnPlayerJoined().Subscribe(args => Debug.Log("OnPlayerJoined " + args.player)).AddTo(this);
```

# コード

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

https://github.com/yamara-mh/CodeStorage/blob/main/Codes/NetworkRunnerTriggerExtensions.cs
コマンドプロンプトでEC2にSSH接続


```
ssh -i <pemファイルパス> ec2-user@<EC2インスタンスのパブリックIP>
```

-i は秘密鍵ファイル（identityファイル）を指定するオプション。

---
AWS学習中、Amazon Linux 2023 AMIでEC2インスタンスを作成したらTera Termで接続できなかったため、コマンドプロンプトで接続する必要があった。
Amazon Linux 2023 AMIでも、キーペアをRSAではなくED25519で作成すればTera Termで接続できるらしい。

# 関連情報
https://dev.classmethod.jp/articles/tsnote-ec2-ssh-teraterm/
mmBotの構築戦略 



## 目次
- [目次](#目次)
- [はじめに](#はじめに)
- [mmBotとは何か？](#mmbotとは何か)
- [mmBotの利点](#mmbotの利点)
  - [Improved efficiency](#improved-efficiency)
  - [Cost savings](#cost-savings)
  - [Reduced errors](#reduced-errors)
- [mmBotを構築するための取引戦略](#mmbotを構築するための取引戦略)
  - [5つの取引戦略](#5つの取引戦略)
- [取引所のAPIを取得する](#取引所のapiを取得する)
- [テクニカル指標を分析する](#テクニカル指標を分析する)
  - [テクニカル指標とは？](#テクニカル指標とは)
  - [4つのmmbotおすすめテクニカル指標](#4つのmmbotおすすめテクニカル指標)
  - [mmbotでのテクニック](#mmbotでのテクニック)
- [リスクマネジメント戦略](#リスクマネジメント戦略)
  - [4つのmmbotのリスク要因](#4つのmmbotのリスク要因)
  - [3つのリスクマネジメント戦略](#3つのリスクマネジメント戦略)
  - [8つのリスク管理ポイント](#8つのリスク管理ポイント)
- [バックテスト](#バックテスト)
  - [バックテストとは](#バックテストとは)
  - [MMBotにおけるバックテストの方法](#mmbotにおけるバックテストの方法)
  - [3つのバックテストのポイント](#3つのバックテストのポイント)
- [ポートフォリオ管理](#ポートフォリオ管理)
  - [ポートフォリオ管理の重要性](#ポートフォリオ管理の重要性)
  - [4つのポートフォリオマネジメント戦略](#4つのポートフォリオマネジメント戦略)
- [資金管理](#資金管理)
  - [資金管理の重要性](#資金管理の重要性)
  - [4つの資金管理のポイント](#4つの資金管理のポイント)
- [ログの管理を行う](#ログの管理を行う)
- [モニタリングを行う](#モニタリングを行う)
- [アップデートを行う](#アップデートを行う)
- [まとめ](#まとめ)
- [FAQs](#faqs)
  - [14個のFAQsを紹介します](#14個のfaqsを紹介します)


## はじめに 

mmBotは、人工知能を用いた自動取引ツールであり、数多くのトレーダーが利用しています。この記事では、mmBotを構築するための戦略について説明します。
## mmBotとは何か？ 

mmBotとは、プログラム可能なトレーディングボットです。トレーディングにおいて、買い付けと売り付けのタイミングを的確に捉えることが必要です。しかし、人間は常に市場変化に対応することは難しいため、トレーディングボットが開発されました。mmBotは、このようなトレーディングボットの一つです。

## mmBotの利点

mmBotを使用することには、以下のような利点があります。

### Improved efficiency

mmBotは、市場変化に素早く対応することができるため、人間によるトレーディングよりも高い効率性を発揮します。また、mmBotは、24時間稼働することができるため、取引の可能性が高くなります。

### Cost savings

mmBotを使用することで、トレーディングのコストを削減することができます。人間によるトレーディングは、多数のコストが発生しますが、mmBotを使用することで、これらのコストを削減することができます。

### Reduced errors

人間によるトレーディングでは、誤りが発生する可能性があります。しかし、mmBotを使用することで、誤りを削減することができます。mmBotは、ユーザーが設定した条件に基づいて、買い付けと売り付けのタイミングを的確に捉えるため、誤りを削減することができます。


---


続きはこちらです

▼▼▼▼▼▼▼▼

▼▼▼▼▼▼

▼▼▼▼

▼▼



[mmBotの構築戦略 ](https://note.com/azurite_azu/n/n62392554dbc8)


https://note.com/azurite_azu/n/n62392554dbc8



△△△△△

https://note.com/
【WinUI3】Windowのサイズを変更不可にする

# 概要

WPFではWindowクラスの[ResizeModeプロパティ](https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.window.resizemode?view=windowsdesktop-7.0)に`NoResize`などと指定することで、ウィンドウサイズを変更不可にすることができました。
WinUI3でも同様のことを行おうと思ったのですが、ResizeModeプロパティが存在しなかったので、少し調べました。

```xml
<Window x:Class="Hoge.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Hoge"
        mc:Ignorable="d"
        ResizeMode="NoResize"
        Title="Hoge Title"
        Height="200" Width="500">
        <Grid><Grid/>
</Window>

```

# WinUI3でのやり方

現状のWinUI3(1.3系)ではXAMLではなく、コードビハインドで指定する必要があるようです。
Window(MainWindow)クラスのコンストラクタで下記のように記載すればよいです。

```cs
public MainWindow()
{
    this.InitializeComponent();

    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
    var mainWindowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hWnd);
    var appWindow = AppWindow.GetFromWindowId(mainWindowId);

    // ウィンドウサイズを指定する
    appWindow.Resize(new(600, 300));

    // ウィンドウサイズを変更不能にする
    var presenter = appWindow.Presenter as OverlappedPresenter;
    presenter.IsResizable = false;
}

```

# 参考

https://github.com/microsoft/WindowsAppSDK/discussions/1694
Amplifyで簡単にプロジェクト外のAppSyncを利用する方法

＊ この記事では公式な方法ではなくハックで拡張する方法を共有しています。

AWS Amplifyではフレームワークの思想により、AppSync（GraphQL）APIを同一プロジェクトに１つしか作成できません。それだけでなく、Amplifyパッケージを利用した場合、アプリ側に設定できるGraphQLエンドポイントも１つしか設定できません。
長らくこの制限のせいで自由にマイクロサービスを設計することが困難でしたが、今回AWS SDKの内部構造を解析し簡単に外部のAppSyncをプロジェクトに混ぜ込む方法を見つけたので共有します。

## やり方

この方法であればプロジェクトを複雑にすることなく、幾つでもAppSyncを取り込めます。

```javascript
import {GraphQLAPIClass} from '@aws-amplify/api-graphql';
import {listPrices} from './graphql/queries.js';
import mainConfig from '@/aws-exports.js';

// インスタンス化する必要があります。
const GraphQLAPI = new GraphQLAPIClass();

// 環境設定 - configre（）はAmplify.configre()と共通の関数です。
// 1. Cognito認証等が共通の場合は一旦メインのaws-exports.jsを取り込みます。
GraphQLAPI.configure(mainConfig);
// 2. 内部的にはObject.assign()するだけなので、第二のAppSync情報で上書きします。
GraphQLAPI.configure({
	aws_appsync_graphqlEndpoint: process.env.OTHER_APPSYNC_ENDPOINTT,
	aws_appsync_region: 'ap-northeast-1',
	aws_appsync_authenticationType: 'AMAZON_COGNITO_USER_POOLS',
});

// 通常と同じ方法で接続できます。
const response = await GraphQLAPI.graphql({
	query: listPrices,
    variables: {crawlId, limit, nextToken},
});
```

## 注意点

###  GraphQLAPIClass

```javascript
import {GraphQLAPIClass} from '@aws-amplify/api-graphql';
```
なぜ APIClass ではなく更に下の GraphQLAPIClass を使うかについては、サイズ的な問題で [APIClass](https://github.com/aws-amplify/amplify-js/blob/main/packages/api/src/API.ts) に @deprecated がマークされているためです。静的解析できるエディタであれば、 ~~APIClass~~ となり「非推奨」の表示が出てきます。
どちらにせよ、メインのAmplifyとは別設定のインスタンスを作ります。

### configure()

```javascript
const GraphQLAPI = new GraphQLAPIClass();
```
この部分ですが、コンストラクタに config を渡しても完全な設定ができませんでした。
一度空でインスタンス化してからconfigure()で設定する必要があります。

### DataStore

こちらは未検証ですが、構造的に共通の方法でIndexedDBに複数のAppSyncプロジェクトが混ざると不具合が起きる可能性が高いと思います。 **この設定だけで複数AppSyncのDataStoreは利用しない方が良いでしょう。**

## なんでそこまでして分けたいの？

### マイクロサービス

単純にアプリ側というのは複数のマイクロサービスを複合して制作することが多いため、単一AppsSyncの制限というのはかなりハードルが高いです。GraphQLスキーマにHTTPやLambdaのプロキシを定義することも可能ですが、それは二重定義になり管理が大変になりますし、そもそも上手く出来ないから断続的にではありますが数年かけて試行錯誤していました。

### amplify push が激遅くなる

まあ20個もスキーマ定義すると馬鹿みたいにデプロイに時間がかかるようになります。
これが無く、さらにスキーマ定義ファイルを構造的に分割できるなら何も考えず試行錯誤もしなかったかもしれないですね。
Oracle Certified Java Programmer, Silver SE 11(1Z0-815-JPN) 勉強法

## はじめに
Oracle Certified Java Programmer, Silver SE 11の勉強法についてまとめました。
私はこれまでに２つの試験を合格しています。

| 年月 | 種類	 | 正解率 |
|:-:|:-:|:-:|
| 2022/08 |  Bronze SE | 95%  |
| 2023/04 | Silver SE 11 |  92% |
| 2023/06 | Gold SE 11 |  88% |

※追記(2023/06) Gold SE 11 

これから受験しようと考えている方向けの記事になっております。

## Oracle Certified Java Programmer 試験について
ORACLEのJava認定資格は以下の通り3段階に分かれています。

* [Gold SE11(1Z0-816-JPN)](https://www.oracle.com/jp/education/certification/1z0-816-jpn-31705-ja.html)
設計者の意図を正しく理解して独力で機能実装が行える中上級者向け

* [Silver SE11(1Z0-815-JPN)](https://www.oracle.com/jp/education/certification/1z0-815-jpn-48261-ja.html)
上級者による指導の下で開発作業を行える開発初心者向け
* [Bronze SE(1Z0-818)](https://education.oracle.com/ja/java-se-bronze-available-only-in-japan/pexam_1Z0-818)
Java言語未経験者向け

試験の詳細についてはORACLEの公式サイトをチェックしてください。

## 使用した教材
* [オラクル認定資格教科書 Javaプログラマ Silver SE11（試験番号1Z0-815）](https://amzn.asia/d/hOYXody)
テキストと問題集がセットになっているもので、正直これ一つで十分な気もします。
Bronze SEの時はBronzeの紫本だけで合格しました。
* [徹底攻略Java SE 11 Silver問題集[1Z0-815]対応](https://amzn.asia/d/a7fmM4z)
黒本の購入することを薦める方は多いですが、紫本だけで良い気もします。

## 勉強方法
① 各章の説明を読みながら、問題を解いて何となく流れを掴む
② 紫本の模擬演習を100点取れるまで何周もする
③ イマイチ覚えていない章の説明を読んで問題を解く
以上を参考書の問題と解説を覚えるまでやり込むだけです。

何周か繰り返し学習すると、自分が苦手とする問題を把握できます。
その後、自分なりにまとめて重点的に学習することを忘れないでください。

## まとめ
短期的な暗記だけでは意味がないため、
基礎をしっかり理解して覚えるよう心がけながら学習することをおすすめします。
また、学習の補助としてChatGPTを活用することもお勧めします。


## 追記 (2023/04/28)
現在、ORACLE MASTER / Java 認定試験　再受験無料キャンペーン 実施中です。
プロモーションコードを入力すると万が一合格できなかった場合に、無料で同一試験を再受験できます。
キャンペーン期間は 2023年3月1日 ～ 2023年5月31日

https://www.oracle.com/jp/education/news-172121-ja.html#20230301

詳細は公式サイトをチェックしてください。


## 追記 Gold SE11合格 (2023/06/25)
本日、正解率88%でGold SE11合格しました。

合格したい人は必ず黒本を買いましょう。
電子書籍は使いにくいので、紙書籍がオススメです。

https://amzn.asia/d/gGVIqig
dockerでrubyを実行できる環境を作る

# やること
**Dockerを使ってRubyの実行環境を簡単に作成します。本当に最小限です。**
# 前置き
Dockerを使ってRubyの最小限の実行環境を簡単に作成します。
作者ははappleシリコンチップ内蔵のmacPCを使ってます
Dockerについては本当に初心者で必要最低限のコマンドでRubyの環境を構築しました。
VirtualBoxのような他の仮想マシンみたくローカル環境に影響を与えずにLinuxで色々試すのが目的です。
Docker自体のインストールの仕方は省略します。私はDocker for Macを使ってます。
Dockerが何かについてはおいおい書くかもしれないです...。1ことで言うとコンテナ型の仮想環境を構築するツールです。

# 結論から書きます
```
mkdir /Users/ユーザー名/Desktop/ruby/
docker run -it -d --name my_ruby -v /Users/ユーザー名/Desktop/ruby/:/home/ユーザー名/ruby/ ruby:3.2.2
docker exec -it my_ruby /bin/bash
```
この3つのコマンドだけです。ユーザー名は適宜書き換えをお願いします。やってることは
1. 前もってDesktopにの直下にrubyディレクトリを作る
2. rubyのコンテナを起動する
3. シェルを指定してコンテナを操作する

以下ではより具体的に解説していきます。

**とりあえずdockerが動いている確認する**
```
docker -v
```
まずは2行目を解説します。runはイメージをダウンロードしてコンテナを作成して起動する命令です。要するに**自動でコンテナを作成**してくれます。containerは省略できます。簡単な例
```
docker container run <動かしたいコンテナの名前>
```
**次にオプションの解説です。**
- -itはコンテナにキーボードを繋いで特殊キーを使用可能にします。特殊キーが何かは自分もよく分かってないです。
- -dはコンテナをバックグラウンドで実行します。
- --nameはコンテナに名前をつけます。これがないと適当な名前をDockerが付けてくれます。
- -vはボリュームをマウントします。つまりコンテナとホストでディレクトリを共有します。コンテナは停止すると全てのデータが消えるので消えて欲しくないデータはマウントしたディレクトリに保存します。今回の場合はホストOS上で作成したRubyファイルをrubyディレクトリに入れることでコンテナ内で実行できます。
続いて3行目です。
**シェルを指定してコンテナの中に入って操作するコマンドです**。containerは省略できます。
```
doker container exec <コンテナ名> /bin/bash
```
最後にコンテナに入ってRubyが使えることを確認します
```
ruby -v
```
以上となります。
参考文献は[仕組みと使い方がわかる Docker&Kubernetesのきほんのきほん](https://www.amazon.co.jp/%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%A8%E4%BD%BF%E3%81%84%E6%96%B9%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B-Docker-Kubernetes%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93-%E5%B0%8F%E7%AC%A0%E5%8E%9F%E7%A8%AE%E9%AB%98/dp/4839972745)
Viaualforce 帳票や一覧出力に便利なapex:repeatを説明

apex:repeatを使うことで複数レコードの詳細を表形式を出力することができます。
例えば、標準コントローラを使って取引先責任者の一覧を出力するVisualforceページを作成する場合、下記のコードになります。
```visualforce:visualforce
<apex:page standardController="Account" >
    <table border="1" >
        <tr>
            <th>取引先責任者名</th>
            <th>電話番号</th>
            <th>Email</th>
        </tr>
        <apex:repeat var="contacts" value="{!Account.Contacts}">
            <tr>
                <td>{!contacts.Name}</td>
                <td>{!contacts.Phone}</td>
                <td>{!contacts.Email}</td>
            </tr>
        </apex:repeat>
    </table>
</apex:page>
```

出力する画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/52d2680a-486b-4400-2afb-ce9af130d873.png)

valueは反復処理されるデータのコレクション、varは反復内の現在の項目を表す変数の名前。
つまり、valueは出力したい対象を指定する。
varはわかりやすい変数名を定義し、出力する際に、その変数名を使って、"変数名.項目名"で欲しい値を取り出す。
【Git】コマンドでリポジトリ名を取得する

## 取得方法

以下のコマンドを実行することでリポジトリ名を取得できます。  

```terminal
$ basename -s .git `git remote get-url origin`
sample-repo
```

- `git remote get-url origin`
  リポジトリのURLを取得する。  
  `https://github.com/UserName/repo-name.git`のように取得できる。  

- `basename`  
  `git remote get-url origin`の実行結果から`repo-name.git`部分のみ取得する。  

- `-s .git`  
  `repo-name.git`から`.git`を除外する。
NotionAPIを使用する第一歩（データベースのデータ取得）

# はじめに
NotionAPIを使用してNotionのデータベースの情報を取得してみましょう。

## 環境
- Windows
- Python(pipのインストール)

****notion-client****を使用しました
****[notion-client](https://pypi.org/project/notion-client/)****

## モジュールのインストール

```python
pip install notion-client
```

## Notionのデータベース情報をコンソールへ出力

ファイル名はnotion.pyとしました

```python
# Notion APIクライアントをインポート
from notion_client import Client
import json

# Notion APIキーとデータベースIDを設定
notion_api_key = "your_notion_api_key"
database_id = "your_database_id"

# Notion APIクライアントを作成
notion = Client(auth=notion_api_key)

# 指定されたデータベースIDのデータベースを取得する関数
def fetch_database(database_id):
    # データベースを取得して返す
    database = notion.databases.retrieve(database_id)
    return database

# メイン処理
if __name__ == "__main__":
    # データベースを取得
    database = fetch_database(database_id)
    # データベースの内容を整形してJSON形式で出力
    database_json = json.dumps(database, indent=2)
    # JSON形式のデータベース内容を表示
    print(database_json)
```

## ファイル実行

```python
PS C:\Users> python .\notion.py
{
  "object": "database",
....結果が出力
```


# 最後に
Notion APIを使用するとデータベースの入力に手間取っていた日々から解放されます。
皆さんで、いろんな使用方法を共有していきましょう！