OmniAICreator/Qiita-1.07M huggingface dataset:
エンジニアになる上で大事なこと

# エンジニアになる上で大事なこと  
私が学習を進めていく中で頭に入れておきたい大事なことを３つ紹介させていただきます！  
私自身初学者中の初学者なので**こんなの当たり前だろww**となるかもしれませんがご容赦下さい！


## 1.与えられた情報、仕様をもとに忠実に実装を行う  
私自身の課題でもあるのですが、自分の想像やこうなんじゃないか等で勝手に仕様外のことをしてしまうことはエンジニアにとってタブー、BAD要素なので注意しなければならない。  
また、SQLでいうならばスタイルガイドがあり、それに則ったクエリを書かなければなりません。仮に素晴らしいクエリが書けていても、スタイルガイドに則ってないなら自分の努力の過程は無駄になってしまうので、注意しなけらばならないところです！


## 2.あいまいな知識で決断や判断をしないこと  
これも私自身の課題なのですが、かなり響いたのでシェアします！  
エンジニアにおける判断の場面でなぜこうしたのかということを完璧に答えられないといけません.。  
1.で書いたことと重なりますが自分の勝手な判断で、ここはインデントした、や大文字にしたなど細かいことでも必ず理由が言えないとイケてるエンジニアとは言えないので大事なポイントだと私は思います！そして判断には理由が必要と頭におきながら学習を進めていくことは私は知識の成長につながると思ったので、シェアさせていただきます！　　
　　
## 3.エンジニアは結果が重要  
1と2の合わさったことというか結論になってしまうんですが、クライアントは結果を求めているので、僕は頑張ったんです！は求めてないのです、**そう大事なのは結果**なんです納期を守る等はもちろんのことですがあいまいな知識で判断して与えられた情報とは違う結果になってしまった場合そこにそこに何十時間かけていても**無駄**になってしまうのです、そうならないためにはやはり上記に記述させてもらったことを守ることは基本なんですがとても大事なことなんだと思いました。
RHEL9のインストール時にソフトウェアRAID(MD Raid)を構成する

毎度インストール時に複数のVGやRAIDを構成する方法を忘れているので備忘録。
今回手順を残すにあたり、KVM仮想環境でディスクはシンプロビジョニングで用意、RHEL9.2のインストーラーで実施。

## 今回は以下の構成
256GB /dev/vda 起動ディスク、OS領域(rootvg)
2TB /dev/vdb データ領域(datavg)
2TB /dev/sda RAID1領域(raidvg)
2TB /dev/sdb RAID1領域(raidvg)

以下インストーラーの「インストール先」から。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/4aebfdf6-3579-d946-43a3-aaf5f33c7e43.png)

インストールで使用したいディスクを全て選択し「カスタム(C)」を選択、左上の「完了(D)」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/6f4155bb-d535-49f4-62c2-791536125149.png)

## 256GB /dev/vda 起動ディスク、OS領域(rootvg)
手動パーティション設定の画面となる。左下「+」マークをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/c55f9825-403c-5592-846b-7e3a5b3969f6.png)

先ずは気にせずOS領域に必要なマウントポイントを作っていく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/a4df880f-c752-d5cc-b616-35dbe2962e21.png)

全てのパーティションが以下のディスク上に作成されるように、各パーティションを選択して「デバイス」を「変更」し、以下のディスクのみ選択されている状態にする。
256GB /dev/vda
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/08c2829e-54cf-76fd-3587-dbd3fb7f3ce5.png)


LVM領域は「ボリュームグループ」の「変更」から、ディスクの選択が可能。vg名もここで設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/2b204414-e5f7-852b-6f5d-3a708358f332.png)

## 2TB /dev/vdb データ領域(datavg)
続いてdata領域に/dataを作成する。サイズは512GiB。同様に左下の「+」をクリックして追加し、その後「ボリュームグループ」のプルダウンから「新規ボリュームグループを作成する...」をクリックし、vdbを選択し、datavgとする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/fd5c00f4-419f-ae59-5784-ced4cba7ff5d.png)

まだ変更は反映されないため、右下の「設定を更新(U)」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/6448bfa9-65d2-b34c-463e-377a72b605e7.png)

## 2TB /dev/sdaと/dev/sdbでRAID1領域(raidvg)
最後にRAID1をsdaとsdbで構成し、/raidを作成する。サイズは1TiB。これまでと同様に左下の「+」をクリックして追加し、その後「ボリュームグループ」のプルダウンから「新規ボリュームグループを作成する...」をクリック。
sdaとsdbをCtrlを押しながらクリックして2つ選択した状態にし、vg名を入力。ウィンドウ下部の「RAIDレベル」から「RAID1」を選択し「保存」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/ecc46038-f35d-944d-c6e9-8f834fdb72bb.png)

変更の反映を忘れないように、右下の「設定を更新(U)」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/99b63ec7-2695-b7da-42c3-94bfafee9cd9.png)

左上の「完了(D)」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3410765/ace09cfb-957a-2a23-9fcc-cdbef5f22e47.png)

変更内容を確認して、問題無ければ「変更を許可する(A)」をクリックして、インストールを先に進める。


**RHEL5の時代に、「RAID1のミラーリングが完了してからリブートしてね」、と教えられたので、Ctrl+Alt+F2等でコンソールを切り替えて/proc/mdstatをwatchしてミラーリングが完了したことを見届けてからインストーラー画面に戻してリブートしてます。
きっと今も同じ？？だと思ってますが、今は待たなくて良いとかあるようでしたら理由とともに教えて頂けると助かります。**

実機はHDDなので、ミラーリング完了まで一晩放置したんですよね・・・

//
PlayWrightを用いたファイルアップロード, 

### 公式ドキュメント
https://playwright.dev/docs/api/class-filechooser

### 実装例
ローカルのレポジトリに含まれているファイルをアップロードする
```typescript: fileupload.ts
import { chromium } from 'playwright'

describe('upload file', () => {
    
    const filePathA = '../videos/a.webm':
    const filePathB = '../videos/b.webm';

 test('upload file', async () => {
    const browser = await chromium.lanch()
    const context = await browser.newContext()
    const page = await context.newPage()
    await page.goto(url)
     //複数投稿可能であればArrayにしてテスト可能
     //setInputFilesを使う
    await page.setInputFiles('input[name="file"]', [filepathA, filepathB])
}
```

こんなやり方も
```typescript
import { chromium } from 'playwright'

describe('upload file', () => {
    
    const filePathA = '../videos/a.webm':
    const filePathB = '../videos/b.webm';

  test('upload file', async () => {
    const browser = await chromium.lanch()
    const context = await browser.newContext()
    const page = await context.newPage()
    await page.goto(url)
    //filechooserを使う
    page.on('filechooser', async (filechooser) => {
        await filechooser.setFiles([filePathA, filePathB])
    }
    await page.click("#fileUpload", {force: true})
```

### 参考youtube
https://www.youtube.com/watch?v=e8jfjV71E6Q&list=PL699Xf-_ilW7EyC6lMuU4jelKemmS6KgD&index=7
【Git】全てのリポジトリで特定のファイルを除外する方法

## `~/.config/git/ignore`を作成する

`~/.config/git/ignore`を作成して`.gitignore`と同様に記述します。

```:~/.config/git/ignore
.DS_Store

```

## ファイルを指定して設定する

任意のファイルを作成して内容を記述します。

```:ターミナル
$ echo .DS_Store > ~/.gitignore_global
```

以下のコマンドを実行するか`~/.gitconfig`に設定を記述します。
```:ターミナル
$ git config --global core.excludesFile ~/.gitignore_global
```

```~/.gitconfig
[core]
  excludesfile = /User/ユーザー名/.gitignore_global
```
Flutterで見る、見えない世界: Golden Test入門

# Golden Testとは何か?
Golden Testは、UIが期待通りにレンダリングされていることを確認するためのテスト方法です。
Golden fileと呼ばれる正しいUIの画像ファイルと、テスト結果を比較し期待通りにUIがレンダリングされているかを確認します。
FlutterのGolden Testは描画結果を比較します。これはバイナリレベルで行われるため、画像のピクセルまで検証できます。

# なぜGolden Testは必要なのか？
結論、UIの変更はUX（ユーザ体験）に大きく影響を及ぼすからです。
例えばTwitterの投稿ボタンは右下に置かれていますよね？あれは片手（右手）で持っても簡単に押せるように右下に置かれています。ではある日突然、投稿ボタンが左上に行ってしまったらどうなるでしょうか。おそらく「使いにくい」と感じるでしょう。
このようにUIの小さな変更は、ユーザに大きな影響を及ぼす可能性があります。そのため、UIの変更を迅速かつ正確に確認することは重要です。そしてGolden Testはこれを効率的に行うことができるのです。

# FlutterでGolden Testを行う方法
まず、golden testのライブラリをインストールします。
```
flutter pub add golden_toolkit  
```
次にフォントのインストールを行う設定を行います。testディレクトリ直下に``flutter_test_config.dart``を作成し、以下のように記述してください。
※flutter testではAhemというフォントを使っていますが、このフォントはGolden Testと相性が良くないためフォントの設定を行います。詳しくは[こちら](https://pub.dev/packages/golden_toolkit#loading-fonts)

```flutter_test_config.dart
import 'dart:async';

import 'package:golden_toolkit/golden_toolkit.dart';

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
  await loadAppFonts();
  return testMain();
}
```
これで準備はOKです。Golden Testを実際に書いて行きます。

```widget_test.dart
import 'package:golden_test/main.dart';
import 'package:golden_toolkit/golden_toolkit.dart';

void main() {
  testGoldens('ゴールデンテスト', (tester) async {
    final builder = DeviceBuilder()
      ..overrideDevicesForAllScenarios(devices: [Device.phone, Device.iphone11])
      ..addScenario(widget: MyApp(), name: 'my_app');

    await tester.pumpDeviceBuilder(builder);

    await screenMatchesGolden(tester, 'my_app');
  });
}

```
``DeviceBuilder``はgolden_toolkitのクラスで、Golden Testを行うサイズをモバイルデバイスのサイズに限定することができます（今回はphoneとiphone11）
``addaddScenario``でテストしたいWidgetとそのシナリオの名前をつけます。
そして``screenMatchesGolden``で期待される画像との比較を行います。今現在はGolden fileが存在しないため、まずはそちらの作成を行います。

```
flutter test --update-goldens
```
これでGolden fileが出力されました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582866/adc62dce-2f6f-1cfe-16f1-9333a7a428d8.png" width="500">

本当にピクセル単位で比較できるのか、もとのアプリのプラスボタンを1ピクセル左に動かしてみました。みなさんは違いはわかりますでしょうか？
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582866/73006974-2318-8c92-f550-8c40374623de.png" width="600">

人間の目では見てない変化もGolden Testなら見ることができます。
``flutter test``を実行するとtestディレクトリ直下にfailuresディレクトリができ、そこに差分の画像が出力されます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582866/78b38f1f-088d-a4f7-2f9b-93905f6f332f.png" width="600">

# まとめ
本記事では、FlutterのGolden Testについて解説しました。
1ピクセルの変化も見逃さないため、上手く活用すればUIの品質保証に大きく貢献できるでしょう。
Flutterにはこの他にもWidget TestやIntegration Testなどもあるので上手く組み合わせて効率的に品質保証してきたいですね！

##### コラム：なぜ"Golden"なのか？
Goldenは昔から「標準的な」や「理想的な」という意味で使われてきたらしいです。（金は不変なので標準的だからですかね？）
そのため、レンダリングが正しく、期待通りに行われているかを確認するため、"Golden"という言葉が使われているらしいです。
PlayWrightで実行内容を録画

### 公式ドキュメント
https://playwright.dev/docs/videos

### playwright.config.tsに書く場合
```typescript:playwright.config.ts
import { defineConfig } from '@playwright/test';
export default defineConfig({
  use: {
    video: {
      mode: 'on-first-retry', 
      size: { width: 640, height: 480 }
    }
  },
});
```

### Configファイル以外に書く例
```typescript:video.spec.ts
const context = await browser.newContext({
  recordVideo: {
    dir: 'videos/',
    size: { width: 640, height: 480 },
  }
});
```

### その他

#### 特定の領域のビデオを記録する：

```typescript
const rect = {
  x: 100,
  y: 100,
  width: 200,
  height: 200,
};

await page.video(rect).saveAs('./video.mp4');
```

#### 特定のスクリプトを実行した後にビデオを記録する：
```typescript
await page.evaluate(() => {
  // ここにスクリプトを実行します
});

await page.video().saveAs('./video.mp4');
```

#### 参考youtube
https://www.youtube.com/watch?v=0125rwgsBP8&list=PL699Xf-_ilW7EyC6lMuU4jelKemmS6KgD&index=6
goofysをarm64で使う

S3やS3互換のオブジェクトストレージをマウントできるツールとして、goofysが有名です。

https://github.com/kahing/goofys

s3fsより速いのですが、ビルド済みバイナリにはarm64(aarch64)バイナリがありません。
そして残念なことに単純にgo getやgo installをしてもライブラリ取得関連でコケてしまいビルドが通りません。

GitHubのissueとその返答そのままですが、うまくビルドして利用できたので備忘録としておいておきます。

あと**ビルド済みバイナリ**(アーキテクチャ明記)**も置いておきます**。(linux/386, linux/amd64, linux/arm64, linux/arm)
(コードでimportのpathを元ソースから一切変えていないので、go installは効かないかと思います。)

https://github.com/mikuta0407/goofys/releases/tag/v0.24.0-fix

## 結論

1. リポジトリをcloneする
2. `api/common/panic_logger.go`で2重定義の関数を片方消す

## 説明

1は置いといて、2の2重定義に関してです。

https://github.com/kahing/goofys/issues/754

このissueに書いてあることそのままですが、まず、普通にgit cloneしてビルドすると、
```
$ go build
# github.com/kahing/goofys/api/common
api/common/panic_logger.go:69:27: method FusePanicLogger.BatchForget already declared at api/common/panic_logger.go:41:27
https://github.com/kahing/goofys/issues/754
```

といった感じでBatchForgetがすでに定義されている、と出てきます。

issueの返信に従って、2回目のBatchForget関数(panic_logger.goの69~72行目)をコメントアウト or 削除します。

https://github.com/kahing/goofys/blob/37cf83563db1bd8aa8d0b02356aacdc3210c26d8/api/common/panic_logger.go#L69-L72

これでgo buildが通り、arm64でも動作できるようになります。
```
$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.2 LTS"
$ uname -p
aarch64

$ go build
$ ls ./goofys
./goofys
$ ./goofys -h
Error: goofys takes exactly two arguments.

NAME:
   goofys - Mount an S3 bucket locally
(以下略)
```

これでビルドしたバイナリで実際にARM64なOracleCloudのA1インスタンスでマウントに成功しています。
お困りの方の参考になれば幸いです。

(goofysの元リポジトリへ同様の内容のPRが複数飛んでいるのですが、マージされてませんね。)
サーブレットとJSPの違い

# サーブレットとは
サーブレットとは、Javaの処理をHTMLで出力できるものです。(厳密な理解ではない)
ブラウザ側からサーバにリクエストをすると、サーバでサーブレットクラスを実行し、その出力であるHTMLをレスポンスとしてブラウザに返します。

サーブレットクラスは、以下のように記述します。
```Java:test.java
package servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		int n = 100;
		
		//HTMLを出力
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = response.getWriter();
		out.println("<!DOGTYPE html>");
		out.println("<html>");
		out.println("<meta charset=\"UTF-8\"/>");
		out.println("<title>おためし</title>");
		out.println("</head>");
		out.println("<body>");
		out.println("<p>" + "nは「"+n+"」です</p>");
		out.println("</body>");
		out.println("</html>");
	}
}
```

ご覧の通り、out.println()を山ほど書かなくてはなりません。面倒ですね。ただ、書き込むファイルはJavaファイルなので書き方に慣れているのは利点ですね。

# JSPとは
JSPとは、サーブレットと同じくJavaの処理をHTMLで出力できるものです。(厳密な理解ではない)

JSPは以下のように記述します。

```JSP:test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>  

<%
int n = 100;
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>おためし</title>
</head>
<body>
<% int n = 100; %>
<p>nは「<%= n %>」です</p>
</body>
</html>
```

Javaファイルのような書き方をするサーブレットと違って、JSPではHTMLの書き方がベースになっていますね。とはいえ、こちらでも<% %>で囲った中にはいつものJavaファイルの記述を書き込んでいるので、そこまで特別な書き方が求められれうわけではないのがいいです。また、サーブレットでは一行一行out.println()しなければならなかったところが、JSPではそのままで問題なくなっています。Java部分の記述に関しても<% %>で囲うだけなので、全行にout.println()を書くのに比べると大した手間ではありませんね。

# サーブレットとJSPの違い
では、書き方以外でサーブレットとJSPでは何が違うのでしょうか。
それは、サーバでの動き方が一番の違いでしょう。
### サーブレット
サーブレットでは、ブラウザ側からサーバにリクエストをすると、サーバでサーブレットをコンパイルし、生成されたサーブレットクラスを実行し、その出力であるHTMLをレスポンスとしてブラウザに返します。つまり、サーバには、そのままコンパイルして実行できる形でサーブレットが置かれてあります。Javaのような記述がされているのはそういうことでしょう。
### JSP
JSPでは、ブラウザ側からサーバにリクエストをすると、サーバでJSPを変換し、サーブレットクラスのソースファイルを生成します。その後、サーブレットをコンパイルして生成したサーブレットクラスを実行し、その出力であるHTMLをレスポンスとしてブラウザに返します。つまり、サーバで一度JSP→サーブレット変換を挟む以外は同じ動きをしています。

# まとめ
・サーブレットもJSPもJavaの処理をHTMLで出力することができる

・サーブレットはJavaの文法をベースに記述する。
・HTML部分の記述がかなり面倒
・サーバでの動きはシンプル

・JSPはHTMLの文法をベースに記述する
・Java部分の記述も簡単にできる
・サーバで一度JSP→サーブレット変換が行われる
PlayWrightメモ

### 公式ドキュメント
https://playwright.dev/

### VSコードExtention
・Playwright Test for VSCode
・breakpointまでテストできるextensionがあるぽい

### 記法
```typescript
import { test, expect } from '@playwright/test';

test('何を検証するのか', async ({ page }) => {
    await page.goto(url)
    const title = page.locator(locator)
    await expect(title).toHaveText('Playwright')
} 
```
・page fixtureがあることでtabとinteractできる

### Page Object Model
https://www.youtube.com/watch?v=Hp4QIBJO3yY
・同じロケータを使い回すためにある
・ページとセクション用のディレクトリがあるといいかも
・ページ名.page.tsの名前がわかりやすいかも
・ちょっとずつlocator, Actionを定義する。

```typescript: computer.pages.ts
export default class ComputerPage {
    page: Page;

    constructor(page: Page){
        this.page = page;
    }

    public acync goto(){
       await this.page.goto(url)
    }

    //locator
    addComputorButton = () => this.page.getByText("Add a new computor")
    
    // Actions
    public async clickAddNewComputer()
    {
        await this.addComputerButton.click()
    }

    public async assertNewComputerAdded(){
        await expect(
            page.getByText("Done!")
       }.toBevisible();
    )
    }
```
```typescript: computerDetails.section.ts
export default class ComputerPage {
    page: Page;

    constructor(page: Page){
        this.page = page;
    }

    public acync goto(){
       await this.page.goto(url)
    }

    //locator
    nameTextBox = () => this.page.locator("#name")
    introducedTextBox = () => this.page.locator("#introduced")
    discontinuedTextBox = () => this.page.locator("#didcontinued")
    companySelect = () => this.page.locator("#company")
    
    // Actions
    public async enterComputerDetails() {
        await this.nameTextBox.fill("CommitQuality");
        await this.introducedTextBox.fill("1999-11-11");
        await this.discontinuedTextBox().fill("2000-11-11");
        await this.companySelect().fill("CommunityQuality");
    }
```

#### POM to fixture
https://www.youtube.com/watch?v=AvmK35LQrb0&list=PLXgRgGX8-5UVm9yioRY329rfcfy3MusiY&index=17

## annotation
https://playwright.dev/docs/test-annotations

## Locating elements
https://playwright.dev/docs/locators

### working with multiple elements
https://playwright.dev/docs/locators#works-fine-with-multiple-elements

## handling tabs
https://www.youtube.com/watch?v=eMU-pGTrYqI&list=PLXgRgGX8-5UVm9yioRY329rfcfy3MusiY&index=14

## visual Regression
### visual regression testing using Playwright/checkly
https://blog.cybozu.io/entry/2022/03/18/100000
https://www.youtube.com/watch?v=Y1eTK-j66PU

## 実行結果確認

### HTMLレポート

### Playwrightの実行結果をSlackに送信する方法
https://barakokutai.com/tech/playwright-slack/

##
保護ポート_Catalyst

HP2530から端末に向けてpingが疎通できる環境を構築。その後、保護ポートに切り替えて疎通が出来なくなるか確認した。

## 環境
* Catalyst123　172.16.30.5/24
* Catalyst456　172.16.30.15/24　（端末として使用）
* HP2530　172.16.30.20/24　（端末として使用）
* PC　172.16.30.10/24

# イメージ図
<img width="700" alt="Catalyst@protectedイメージ図(1).jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2929519/9ccbae05-0d5f-d5d6-4ccc-fb5d60dd9136.jpeg">

# Catalyst123設定
```php:Switch123(config-if-range)#do show running-config
Building configuration...

Current configuration : 4640 bytes
!
version 12.2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
interface GigabitEthernet0/3
 switchport access vlan 150
 switchport mode access
!
interface GigabitEthernet0/8
 switchport trunk encapsulation dot1q
 switchport trunk allowed vlan 150
 switchport mode trunk
 switchport protected
!
interface GigabitEthernet0/9
 switchport access vlan 150
 switchport mode access
 switchport protected
!
interface Vlan150
 ip address 172.16.30.5 255.255.255.0
```

# Catalyst456設定
```php:Switch456#show running-config 
Building configuration...

Current configuration : 4207 bytes
!
version 12.2
!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
interface GigabitEthernet0/3
 switchport access vlan 150
 switchport mode access
!
 interface Vlan150
 ip address 172.16.30.15 255.255.255.0
```

# HP2530設定
```php:HP2530# show running-config 

Running configuration:

; J9779A Configuration Editor; Created on release #YB.16.10.0011
; Ver #14:41.44.00.04.19.02.13.98.82.34.61.18.28.c3.84.9c.63.ff.37.27:35
hostname "HP2530"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
vlan 150
   name "protected"
   tagged 9
   ip address 172.16.30.20 255.255.255.0
   exit
```

# pingで疎通確認
```
# ping 172.16.30.15
172.16.30.15 is alive, time = 15 ms
# ping 172.16.30.10
172.16.30.10 is alive, time = 3 ms
```

# 保護ポート設定

Catalyst123に保護ポートを設定
```
(config)#interface range gi0/8-9
(config-if-range)#switchport protected
```

疎通出来るか確認。gi0/8-9に設定しているので、PC端末に通信出来なくなっている。
```
# ping 172.16.30.15
172.16.30.15 is alive, time = 10 ms
# ping 172.16.30.10
Request timed out.
```
ChatGPT APIの使い方: 導入からレスポンス取得まで

## まずChatGPT APIのAPI keyを取得する
ChatGPT APIを使用するためにはまずAPIキーの取得が必要である。
これはOpenAIの公式サイトから取得できる。

https://platform.openai.com/account/api-keys

`+ Create new secret key`をクリックし、API keyが生成されたら、そのキーをコピーして安全な場所にメモしておく。`OK`をクリックするとAPIキーは再表示されないので、忘れずにメモする。

## Google Colabを使用する
次に、Google Colabを開く。

## openaiライブラリのインストール
ChatGPT APIを使用するためには、Pythonのopenaiライブラリが必要である。以下のコードを使用してインストールする。
```Python
!pip install openai 
```
インストールが完了したら、openaiをインポートする。

```Python
import openai
```
## ChatGPT APIのAPIキーを設定する
```Python
openai.api_key = "あなたのAPI keyをここに貼り付ける"
```
APIキーは絶対に他人に見せてはいけない。

## レスポンスの取得
以下のコードを使用して、ChatGPT APIからレスポンスを取得する。openai.ChatCompletion.create()の最初の引数には使用するモデルを指定し、2番目の引数には送信するメッセージを指定する。

1. この例では、モデルとしてgpt-3.5-turboを指定する。
2. メッセージは2つ送る。まずは、システムとしての役割(role)を設定する。その後、ユーザーとして質問を投げかける。

```Python
response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",  
    messages=[
        {"role": "system", "content": "あなたは優秀なプログラマーです。"},
        {"role": "user", "content":"あなたはどんなことができますか？"}
        ]
)

# レスポンスの表示
print(response['choices'][0]['message']['content'])
```  
レスポンスとして以下のような内容が表示される。
「私は、様々なプログラミング言語を使って、ソフトウェアやアプリケーションの開発、ウェブサイトの作成、データベースの設計・管理、機械学習や人工知能の開発、セキュリティの強化などの作業を行うことができます。また、問題を解決するのが得意で、効率的で高品質なコードを書くことができます。」

ChatGPT APIの利用料金については、下記のOpenAI公式サイトで確認できる。

https://platform.openai.com/account/usage

# 追記
猫のキャラクターのチャットボットを作った。
チャットボットのURL

https://kaiyoyume-open-ai-chatbot-tama-app-8nd232.streamlit.app/

チャットボットの完成度は低い。

![スクリーンショット 2023-05-24 12.02.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3268288/7f46beb4-4690-c947-7589-23645b1c4382.png)



チャットボットのURL

https://kaiyoyume-open-ai-chatbot-tama-app-8nd232.streamlit.app/


githubでコードを公開している。

https://github.com/kaiyoyume/open_ai_chatbot_tama/tree/main
CentOSにPostgreSQLを構築する手順

# CentOSにPostgreSQLを構築する手順

## 前提条件

- CentOS 7 または CentOS 8 がインストールされていること
- rootユーザーまたはsudo権限を持つユーザーであること

## 手順

1. PostgreSQLのリポジトリを追加します

```bash
sudo yum install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
```

2. PostgreSQLをインストールします

```bash
sudo yum install postgresql13 postgresql13-server
```

3. PostgreSQLサーバを初期化します

```bash
sudo /usr/pgsql-13/bin/postgresql-13-setup initdb
```

4. PostgreSQLを起動し、自動起動を設定します

```bash
sudo systemctl enable postgresql-13
sudo systemctl start postgresql-13
```

5. PostgreSQLが正常に起動しているか確認します

```bash
sudo systemctl status postgresql-13
```
# ユーザー、データベース、スキーマの作成手順

## ユーザー（ロール）の作成

1. PostgreSQLに接続します。以下のコマンドを使用します。

    ```bash
    sudo -u postgres psql
    ```

2. 新規ユーザー（ロール）を作成します。以下のコマンドを使用します。ここでは、ユーザー名を`dbuser`とします。

    ```sql
    CREATE ROLE dbuser WITH LOGIN PASSWORD 'your_password';
    ```

    `your_password`は適宜書き換えてください。

## データベースの作成

1. 新規データベースを作成します。以下のコマンドを使用します。ここでは、データベース名を`mydatabase`とします。

    ```sql
    CREATE DATABASE mydatabase;
    ```

2. 作成したデータベースの所有者を新規ユーザーに設定します。以下のコマンドを使用します。

    ```sql
    ALTER DATABASE mydatabase OWNER TO dbuser;
    ```

## スキーマの作成

1. 新規データベースに接続します。以下のコマンドを使用します。

    ```sql
    \c mydatabase
    ```

2. 新規スキーマを作成します。以下のコマンドを使用します。ここでは、スキーマ名を`myschema`とします。

    ```sql
    CREATE SCHEMA myschema;
    ```
3. カレントスキーマを設定します
    ```sql
    ALTER USER dbuser SET search_path TO myschema;
    ```
以上で、新規ユーザー、データベース、スキーマの作成が完了しました。
pod installすると[!] [Xcodeproj] Generated duplicate UUIDs:のエラー

# `pod install`すると謎のエラー
>「[!] [Xcodeproj] Generated duplicate UUIDs」というエラーメッセージは、Xcodeproj（Xcodeプロジェクト）の操作中に重複するUUID（Universally Unique Identifier）が生成されたことを示しています。
UUIDは一意の識別子であり、プロジェクト内の各要素（ファイル、フォルダ、ビルド設定など）に割り当てられます。重複するUUIDが生成されると、プロジェクトの整合性が損なわれ、ビルドや他の操作に問題が発生する可能性があります。
このエラーメッセージが表示された場合、Xcodeprojファイルの中で重複するUUIDが生成されたことを意味します。これは通常、プロジェクトの変更やマージの結果起こることがあります。
このエラーを解決するためには、UUIDの重複を修正する必要があります。手動でUUIDを変更するか、プロジェクトの再生成を行うことで解決することができます。具体的な手順は、使用しているツールや環境に依存するため、詳細な情報が必要です。

by GPT-3.5

うーん、、、わからない。。。
一体なぜなのか・・・。。

![Screenshot 2023-05-23 at 23.06.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/febd72b8-841f-d99d-fabb-a8288d9b09d3.png)
しかもめっちゃ長文です。


# 謎の解決法
### ①pods配下のFirebase,GoogleUtilities フォルダを一度削除
![Screenshot 2023-05-23 at 23.10.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/0316bde3-5487-fb23-7306-bbaede028c73.png)

### ②Podfileを編集
`pod ‘Firebase/Analytics`以外のFirebase系ライブラリをコメントアウトして、`pod install`

```ruby:Podfile
target 'App' do
# Add your Pods here
#  pod 'FirebaseCore'
#  pod 'Firebase/Messaging'
  pod 'Firebase/Analytics'
end
```

```console
pod install
```

### ③コメントアウトを解除してもう一度`pod install`

```ruby:Podfile
target 'App' do
# Add your Pods here
  pod 'FirebaseCore'
  pod 'Firebase/Messaging'
  pod 'Firebase/Analytics'
end
```

```console
pod install
```

なぜかこれでエラーが解決されました。。。
**全く理由はわかりません！！！！:joy_cat:**



# 参考

https://infohub.jp/media/2021/07/09/3943/
「技術書の読書術」の書評というか感想というか

# 初めに
簡単に自己紹介を
・専門卒3年目のエンジニア
・業務で使用する言語はC#
・リファクタリングやDDDに興味があって勉強中
・今まで読んできた技術書
　「ミノ駆動本」「増田本」「CleanArchitecture」「成瀬本」等々

# 書籍の構成
第一部　選び方
第二部　読み方
第三部　情報発信・共有

# 印象に残ったこと
<dl>
  <dt>第一部</dt>
  <dd>自分に合った本を見極めるポイントや書店や図書館での本の選び方が書かれている。</dd>
  <dd>私は先輩から設計に関する書籍をいくつかおすすめされてきた。しかし、私と先輩では当たり前だが知識に差があり、先輩にとっては良書でも、私にとっては書いてあること・用語がまるで分らず積読状態になっている本も少なくない。</dd>
  <dd>　</dd>
  <dd>そんなとき、第一部に書いてある「はじめに」や「まえがき」の部分を読んだり、目次や索引のキーワードの理解度から本を選んだりすれば自分のレベルに適した本を選定できたかもしれない</dd>
  <dt>第二部</dt>
  <dd>技術書にはいろんな読み方があるっていうのを二人の著者が教えてくれる</dd>
  <dd>精読や流し読みといった一般的な手法から一冊を90分で読み切る時間制限読書法、同じ分野の本を最低でも20冊以上、学術論文を含め精読し3年で大きな成果を上げることを目指した一点突破読書法、1年で1000冊以上を読破する超多読法など、型にはまらない読書の枠を超えた読み方がいくつも紹介されている。</dd>
  <dd>一点突破読書法ではオンリーワンを目指すことが書いており、1つの得意分野を獲得するのに1年かかれば3年で3つの得意分野を獲得できる。この本では「DIY」「アクアリウム」「統計」という突飛な組み合わせを例に挙げて市場での希少価値を示している</dd>
  <dd>Qiita Conference 2023 Day3ではミノ駆動氏による講演の中で2つ以上の特化スキルをもった「π字型」を目指しましょうと言っている。能力と能力の掛け算により人材の希少性と重要性が爆増し市場価値が高まる。ただし、専門性は無関係なものではなく組み合わせて相乗効果が得られる関係性を推奨</dd>
  <dd></dd>
  <dt>第三部</dt>
  <dd>学んだことはアウトプットしていきましょうということが書かれている</dd>
  <dd>言ってしまえは私が今、qiitaに感想を投稿しているのも第三部の影響</dd>
  <dd>こうやって学んだことを書くためには内容を理解していないといけないし、簡単に読み直しもしている。もしかしたらこの投稿についてのフィードバックをしてくれる人がいるかもしれない。書いて発信してみないと気づけないことがあることを第三部では教えてくれた。</dd>
</dl>

# これから実践すること
<dl>
  <dt>第一部</dt>
  <dd>くじ引き読書法</dd>
  <dd>　無関心な本を読むことを目的に適当に選んだ本を読破すること。知らないことを学ぶ楽しみや、本来学ぶことすらなかった分野との出会いを増やすため、まずは年1回でためしてみる。</dd>
  <dd></dd>
  <dt>第二部</dt>
  <dd>一点突破読書法</dd>
  <dd>　前述したとおり3年間で大きな成果をあげることを目指した読書法。</dd>
  <dd>　得意な分野・好きな分野なのでまずは1年間かけてリファクタリングを極める。あと2つの技術は追々決める。。リファクタリングと相乗効果が得られる業務系の知識とかかな（金融・保険・医療等）</dd>

  <dt>第三部</dt>
  <dd>qiitaに定期的に学習したことをアウトプットする</dd>
  <dd>会社の勉強会ではたまに発表したりしてるのでアウトプットとインプットのバランスを意識しながら定期的に学んだことを発信してフィードバックを受けつつ学びを継続したい</dd>

# 最後に
もっと早く読んでおけばよかった。
この本を読んで読書の可能性を2つの視点から3つ4つと広げることができた。
継続的にアウトプットし続けられるように頑張ります。
ほかの学習のアウトプットでもqiita活用していくと思う。
くじ引き読書法や一点突破読書法など実践するときにまた投稿しますー。
マイクロサービスアーキテクチャとは、概要・メリット・デメリットの紹介

## マイクロサービスアーキテクチャとは
モノリシック(一枚岩)なアーキテクチャとは異なり、ビジネス機能に沿った複数の小さい「マイクロサービス」に分割し、連携させることで大きいソフトウェア機能を実現すること

### マイクロサービスを構築する上での2つの技術
#### ・　API
「Application Programmming Interface」の頭文字で、「アプリケーション、ソフトウェア」と「プログラム」をつなぐものである。
APIにはいくつかのタイプがあるが、クラウド上のマイクロサービスでは「REST API」と呼ばれるものが広く使われている。
REST APIは構造がシンプルで、物理的に離れた位置にあるサービス同士を連携して人るのサービスを運用できる点が特徴である。

#### ・　コンテナ
OS上にそれぞれのアプリケーションの専用区画を作成区画を作成する仮想化技術の一つ。
マイクロサービスでは、個々のプロセスに対してコンテナが用意され、プロセス間のやり取りはAPIを介して行う。機能変更の際はコンテナ単位で入れ替えを行えるので、迅速に対応できるのが特徴。
コンテナ技術には様々な種類があるが、現在は導入や費用の手軽さなどに優れるLinux由来の「Docker(ドッカー)」が主流。

### マイクロサービスのメリット 7選
#### 1. 一つのシステムに異なる技術を採用できる
マイクロサービス同士が独立しており疎結合であるため、開発言語などの技術を機能ごとに変えることができる。このため、それぞれの機能に最適な技術を採用することができる

#### 2. 柔軟性、拡張が高い
システムやアプリケーションが大きくなっても機能追加や変更がしやすい。
また、ある機能(サービス)を拡張したい場合は、該当のマイクロサービスにのみ変更を加えることが可能なため、拡張性が高く、デプロイまでがスピーディーに行える。

#### 3. 負荷を分散できる
ある機能に負荷がかかった場合は、システム全体ではなく、特定の機能のみスケールすることで対応できる。

#### 4. 開発期間を短縮できる
小規模な機能単位に分けて開発を進めるため、開発期間が短くて済む。
このため、開発チームの人数も少人数となり、コミュニケーションや進捗の把握などもしやすくなる。

#### 5. アジャイル開発に向いている
マイクロサービスは、柔軟で軽量な開発手法であるため、柔軟性が高く、迅速性に富んだ開発手法であるアジャイル開発と親和性が高い。

#### 6. デプロイの際にシステムを止める必要がない
デプロイの際に他の機能部分は停止させずに一部の機能のみをデプロイできる。また、1日に複数回のデプロイも可能

#### 7. コードを再利用できる
機能を細分化して構築するため、ニアような機能を作る際に、コードを再利用できる。そのため、類似機能で一からコードを記述する無駄が省ける。

### デメリット 4選
#### 1. 設計やプロジェクトの統括に高いスキルが求められる
「一つのシステムに異なる技術を採用できる」メリットの裏返しに、システムやアプリケーション全体の設計の難易度が上がる。特に、最初に分割した機能単位は後から変更できないため、設計時に慎重に検討する必要性あり。

#### 2. データの一貫性を担保しづらい
マイクロサービスでは、機能ごとに使用するデータストアも分割する。さらに、機能ごとに同期せずにデータ処理を行うこともある。このため、機能間でデータの一貫性を担保しづらい面がある

#### 3. デバッグや統合テストの難易度が高い
個々の機能たんは独立しているものの、完成したサービスを提供するにあたり、デバッグや統合テストが必要となる。エラーが出た場合は、どの機能が原因なのかをたどる作業の難易度が高い。

#### 4. API管理の難易度が高い
それぞれの機能に多くのAPIが使われる。機能がわに変更がなくとも、APIを変更すれば、APIを利用している全ての機能に影響するため、APIを適切に管理する必要がある。

### まとめ
マイクロサービスは、ビジネス機能に沿った複数の小さい「マイクロサービス」に分割し、連携させることで大きいソフトウェア機能を実現する手法である。
開発期間の短縮や、各機能に最適な技術をそれぞれ採用できるなど、メリットは多いが、デメリットもある。
開発したいシステムやアプリケーションに合わせて、マイクロサービスが適するか検討する必要がある。
Golang with JSON

1. Read from Json file and convert to struct

    ```golang
    type Record struct {
    	Time        time.Time
    	Station     string
    	Temperature float64
    	Rain        float64
    }
    
    func readRecord(fileName string) (Record, error) {
    	file, err := os.Open(fileName)
    	if err != nil {
    		log.Fatal(err)
    	}
    	defer file.Close()
    	var rec Record
    	dec := json.NewDecoder(file)
    	if err := dec.Decode(&rec); err != nil {
    		return Record{}, err
    	}
    	return rec, nil
    }
    func main() {
    	fileName := "sample-app/record.json"
    	rec, err := readRecord(fileName)
    	if err != nil {
    		log.Fatal(err)
    	}
    	fmt.Printf("%+v\n", rec)
    }
    ```

1. Convert Json string to stuct
    
    ```go
    type Student struct {
    	Name string // The name must start with upper case
    	Age  int
    }
    jsonTxt := `[{"name":"tom", "age":13},{"name":"Lily", "age":14}]`
    	var students []Student
    	json.Unmarshal([]byte(jsonTxt), &students)
    	for _, stu := range students {
    		fmt.Printf("%+v", stu)
    	}
    ```
1. Convert Map to Json text
```go
func main() {
	states := make(map[string]string)
	states["WA"] = "Washington"
	states["NY"] = "New York"
	states["CA"] = "California"
	jsonText, _ := json.Marshal(states)
	fmt.Println(string(jsonText))
}
```
【React】子に更新後のデータが反映されない😢

## :older_man_tone1:　現象
リストに表示されたデータをクリックすると、ポップアップ（子コンポーネント）が表示され、ポップアップ（子コンポーネント）のフォームにクリックされたデータが反映されるという処理を行いたかったのですが、クリックしてもクリックしてもデータが渡されている様子がなく、再レンダリングしてくれない現象が発生しました。

:::note info
上記現象が起きたコンポーネントの構成は、
- 一覧ページ（親）から`登録用ポップアップコンポーネント（子）`を呼んでいる
- 一覧ページ（親）から`リスト表示コンポーネント（子）`を呼んでいる
- `登録用ポップアップコンポーネント（子）`を詳細表示、編集用のポップアップとしても使用している
- `リスト表示コンポーネント（子）`をクリックすると、`登録用ポップアップコンポーネント（子）`が表示され選択したデータの詳細が表示される
:::


## :bellhop:　解決策
useEffect()の第2引数を[]にしていましたが、[更新したいデータ]（厳密に言えば、親から渡ってきたデータ）に変更したらちゃんと再描画してくれるようになりました！

```diff_typescript
useEffect(() => {
    console.log('レンダリングされたよ！！');
    console.log('data: ', data);
    setSelectType(data);
- }, [])
+ }, [data])
```
rex0220 プラグイン 祝日チェック

kintone で、日付の祝日チェックを行います。
下記の rex0220 プラグインを利用します。
・休日プラグイン（無償）
・アプリ集計プラグイン
・項目検証プラグイン

# 概要

アプリ集計プラグインで、休日アプリから日付の休日データを取得し、項目検収プラグインで祝日をチェックします。

![2023-05-23_22h27_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/e3bd61c2-072f-f80a-7632-d6004ec0fa50.png)

# 操作例

![2023-05-23_22h49_39.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/446e115c-28aa-acc2-ec31-8cb83b43f425.gif)


# 休日アプリ

[rex0220 休日プラグイン](https://qiita.com/rex0220/items/3556d6a3246abd6f4e7a)で祝日データを作成します。

- 休日テンプレートから休日アプリを作成
- 対象年の祝日データを休日アプリに作成
- 休日アプリに会社の公休日をマニュアル登録

![2023-05-23_22h34_16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/f1441ca6-c9f7-46a4-eac8-92d1ed6ed6c1.png)

- 作成データ
![2023-05-23_22h26_14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/d452bcd7-eb7d-67e9-cfdd-59c5811a8360.png)

# 日付チェックアプリ

日付項目と祝日名用の文字列項目を配置します。

![2023-05-23_22h39_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a1df104f-a0c8-84ae-6f17-0e091ee85268.png)

# アプリ集計プラグインの設定
日付項目の値変更時に、「休日」項目に祝日名を取得するように設定します。

![2023-05-23_22h40_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/84a63280-c4d2-d359-8b44-bac040538353.png)

- 自動・ボタン別設定
![2023-05-23_22h43_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/85bb9c58-5129-a0b3-7c75-e5d98c03af28.png)

- 対象アプリ条件
![2023-05-23_22h41_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3595f63d-2fb3-7cc9-00a5-3ac197ff727c.png)

- 集計項目
![2023-05-23_22h42_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/e7818b23-5ceb-ed73-135d-5583faaef88e.png)

# 項目検証プラグインの設定

![2023-05-23_22h46_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4def8214-bb1a-5bcd-365b-6adee064467c.png)
Paperspace + Stable Diffusion のサポートをしています

## まずはこの記事をお読みください

:::note alert
Stable Diffusion Web UI を <b>Google Colab 上で無料で使うことができなくなり、有料プランも定額でない(コンピューティングユニットがなくなったら追加課金がいる)ので、</b>以下の新記事『【Paperspace】Stable Diffusion Web UI を月額定額で使う』も読んでみてください。
:::

:::note info
<b>以下の記事の紹介コード付きURLからサインアップすると Paperspace の Pro プラン(月額定額8ドル)を一か月無料で試すことができます。</b>
:::

https://qiita.com/javacommons/items/0f58a5cfe07c757dc54a

----

以下のような画像(実在の人物じゃないです)を生成できるようになります。

この画像を生成した https://twitter.com/aktokaji (Women In Lingerieさん / Twitter) のページも是非ご覧ください。

[![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140610/a702c07e-1983-d01e-dc3b-6c4661afbe52.png)](https://twitter.com/aktokaji/status/1655126767416545280)

[![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140610/21203d50-b7c6-4efa-7722-5ea78413bf6a.png)](https://twitter.com/aktokaji/status/1654369927699259392)


## Paperspace + Stable Diffusion のサポートをしています

https://twitter.com/aktokaji (Women In Lingerie) に DM or ＠ツイートを送る(DM はフォローされてなくても送れます)か、この記事にコメントください。できるだけ早く回答します。

LINE のオープンチャット(「Stable Diffusion Web UI について」)を開催しています(<b>メインアカウントの存在および本名がバレることはありません</b>)。

オープンチャットには以下のリンクまたはQRコードからご参加願います。

<b>オープンチャットリンク:</b> [https://line.me/ti/g2/GmfnpqDseaOCYRGIvL8yAc8sWgjko8hhcUoCKQ?utm_source=invitation&utm_medium=link_copy&utm_campaign=default](https://bit.ly/paperspace-openchat)

<b>オープンチャットQRコード:</b>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140610/c155fc07-158c-1cc2-0e36-51c32e9aee07.png)

<!--
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140610/5cedb9b8-0a0d-4c72-1f6d-329f28f8a30f.png)
-->

LINE のオープンチャット(<b>メインアカウントの存在および本名がバレることはありません</b>)ですので安心です。

> LINE（ライン）には、匿名で気軽に会話できる「オープンチャット」機能があります。通常の友だちとのトークとは切り離して使えるため、メインアカウントの存在がバレることなく使えるのが特徴です。2022年8月にサービス開始から3年目を迎え、累計ユーザー数は2000万人を突破しています。

DM または LINEオープンチャットに参加いただければ、(ほぼ)リアルタイムで、(主にこの記事で築いた環境に関して)サポートします。Stable Diffusion 全般に関する相談にも乗ります。

よろしくお願いします。
Flaskで、タグをhtmlファイルに反映させる方法

## Flaskで\<br>タグをHTMLで動作できなかった
### 状況と原因
<details>
<summary>app.jsコード</summary>

```js:app.js
from flask import Flask
from flask import render_template
from flask import request
from create_text import YoutubeText

app = Flask(__name__)

@app.route("/")
def main():
    return render_template("index.html")

@app.route("/", methods=["POST"])
def users():
    url = request.form["url"]
    print("POST:"+url)
    # Youtubeをテキスト化
    txt = YoutubeText(url)
    txt = txt.replace("\n","<br>")
    return render_template("index.html",message = txt)


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=3000, debug=True)
```

</details>
<details>
<summary>index.html</summary>

```html:index.html
<html>
<body>
  <form action="/">
    <input type="url" name="url">
    <button type="submit" formmethod="post">Submit</button>
  </form>
  <div>
    {{message}}
  </div>
</body>
</html>
```

</details>

この時の実行結果は
```html:実行結果
もっと木の笑顔がラストメディアその<br>秘密ミステリアス抜けてるとこさえ彼女の<br>エリア<br>完璧で嘘つきな君は天才的な<br>今日何食べた好きな本は<br>遊びに行くならどこに行くの何も食べて<br>ないそれは内緒何を聞かれても<br>のらりくらりそう淡々とだけどサンサンと<br>味噌で見えない水は3つの味あれもない<br>ないないこれもないないない好きなタイプ<br>は相手は<br>答えて誰かを好きになることなんて私<br>わからなくてさ<br>嘘か本当か知り得ないそんな言葉にまた<br>一人落ちるまた好きにさせる誰も目を奪わ<br>れてく君は<br>完璧で究<br>現れない一番星の生まれ変わりあーその<br>笑顔で愛してるで誰も誰も虜にしていく<br>その<br>瞳がその言葉が嘘でもそれは完全なはい<br>はいあの子は特別です<br>
```

このような形で、\<br>タグが実行されず、そのままタグごと表示されている状態でした。
調べてみると、もとからFlaskに搭載されている __|safeフィルタが使用されている様です。クロスサイトスクリプティング（XSS）攻撃に対するセキュリティを確保するためタグは強制的に無効化されるため、今回\<br>タグは無効化されました。__
 ### 解決方法
```html:index.html
<html>
<body>
  <form action="/">
    <input type="url" name="url">
    <button type="submit" formmethod="post">Submit</button>
  </form>
  <div>
    {{message| safe }} <!--こちらはエスケープされているが下はされていない-->
    {{ message }}
  </div>
</body>
</html>
```
```html:実行結果
もっと木の笑顔がラストメディアその
秘密ミステリアス抜けてるとこさえ彼女の
エリア
完璧で嘘つきな君は天才的な
今日何食べた好きな本は
遊びに行くならどこに行くの何も食べて
ないそれは内緒何を聞かれても
のらりくらりそう淡々とだけどサンサンと
味噌で見えない水は3つの味あれもない
ないないこれもないないない好きなタイプ
もっと木の笑顔がラストメディアその<br>秘密ミステリアス抜けてるとこさえ彼女の<br>エリア<br>完璧で嘘つきな君は天才的な<br>今日何食べた好きな本は<br>遊びに行くならどこに行くの何も食べて<br>ないそれは内緒何を聞かれても<br>のらりくらりそう淡々とだけどサンサンと<br>味噌で見えない水は3つの味あれもない<br>ないないこれもないないない好きなタイプ<br>
```

このように、html側でXSS対策を避けて、タグごと送信したものを反映させることができるようです。

:::note warn
警告
今回はユーザーからのインプットではなかったため、そのまま反映させましたが、XSS対策自体は非常に重要なものです。必要最低限で利用できるように心がけましょう
:::
## まとめ
初めて利用したFlaskで思いもよらないところで躓いてしまった。少しでも、他の方の参考になればうれしいです。
__初めてのことだらけなので、他の方法や、もっと安全な方法がある場合は教えていただけると幸いです。__
Liberty といろんな DB でDataSourceをためす

# 目的
Libertyと、Db2, MySQL, Derbyで環境を構築してDataSourceをテストします。

# Gitレポジトリ
用意したGitレポジトリをクローンします。

```
git clone https://github.com/pdprof/db-connections
cd db-connections/derby-docker/
```

# DBイメージのビルド、Libertyイメージのビルド

Libertyと、Db2, MySQL, Derbyのイメージをビルドします。localhost 以外の docker を動かしているホストのIPアドレスをACCESS_HOSTに指定します。

```
export ACCESS_HOST=172.17.0.1
# export ACCESS_HOST=`hostname` # hostnameコマンドで返す値でアクセスできる場合
./setup-docker.sh
```

# MySQLの起動

MySQL以外にもDb2がありますが、ここではMySQLを起動します。今回あらたに用意したのがMySQLだからです。DerbyはLibertyのプロセス内で動作するので、Dbを別に起動する必要はありません。

```
./mysql-start.sh
# ./db2-start.sh # db2を起動する場合
```

# MySQLにアクセスするLibertyの起動

MySQLにアクセスするLibertyを起動します。

```
./ds-mysql-start.sh
# ./ds-db2-start.sh # Db2にアクセスする場合
# ./ds-derby-start.sh # Derbyにアクセスする場合
```

# アプリケーションにアクセスして動作確認

http://localhost:9080/db.connections/
にアクセスすると以下画面が確認できます。localhost部分はACCESS_HOSTに指定したものと置き換えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262366/f18a7d3c-2ce9-be3f-a86a-0ffefaa15618.png)

Simple db access test をクリックすると TABLEの作成とデータ挿入が実行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262366/dac6baec-29e2-b809-9dde-faf0563a8c1c.png)

Insert, Update, Delete ができるようになっているので、フォームに値を入力してボタンをクリックして動作を確認します。


# トラブルシューティング

接続がうまくいかない場合は、/config/server.xml で指定したホスト名（IPアドレス）が問題ないか、DBが動作しているか確認します。DBは 

```
docker logs -f mysqldb # ログ確認
docker restart mysqldb # 再起動
docker inspect mysqldb # container 確認
docker exec -it mysqldb bash # Container内状況確認
```

など試してみましょう。


# まとめ

DBの環境を構築をしてテストをすることができました。
Symfony handson lesson-3

# フォーム
フォームからユーザ入力をさせる
- DBへ保存したり，データをレンダリングして表示させるのは行った
- https://symfony.com/doc/current/bundles/override.html#forms

インストール
- composer require symfony/form

最も簡単なフォーム
- デフォルトでは空白バリーションがある
- デフォルトでは同じURLに送信される
![スクリーンショット 2023-05-20 16.38.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519081/f8bc7152-4598-b855-cfd6-2f42431619cb.png)

```Controller.php
public function add(): Response {
    $form = $this->createFormBuilder()
        ->add('title')
        ->add('text')
        ->add('submit', SubmitType::class, ['label' => 'save'])
        ->getForm();

    return $this->renderForm(
        'form.html.twig', 
        [
            'form' => $form
        ]
    );
}
```

```form.html.twig
{{ form(form) }}
```

# フォームの送信処理
フォーム送信のためにフォームをレンダリング
- アクション内の現在のリクエストにアクセス
- リクエスト中に送信されるデータをフォームに取得させる
- バリデーションを加えると良い


```送信内容をDBに保存
$microPost = new MicroPost();
$form = $this->createFormBuilder($microPost)
    ->add('title')
    ->add('text')
    ->add('submit', SubmitType::class, ['label' => 'save'])
    ->getForm();

$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
    $post = $form->getData();
    $post->setCreated(new DateTime());
    $posts->save($post, true);
}
```

# フォーム送信時のフラッシュメッセージ・リダイレクト
フラッシュメッセージは１リクエストにつき１つ

```
// add a flash
$this->addFlash('success', 'success!!');

// redirect
return $this->redirectToRoute('micro_post_index');
```

# フォームのカスタマイズ
https://symfony.com/doc/current/form/form_customization.html#form-rendering-functions

Twigを変更して色々カスタマイズが可能

# フォームクラスの作成
https://symfony.com/doc/current/forms.html#creating-form-classes

symfony console make:form
- 自動でフォームクラスを生成
- FormType名を入力
    - Entityの名称に準ずるFormTypeが作成される




# その他
App\Entity\MicroPost object not found by the @ParamConverter annotation. のエラー
- ルートにpriority: 2を追加
[AWS Q&A 365][SNS]AWSのよくある問題の毎日5選 #64

Sure, here is the Japanese translation for the text you provided:

# 1. Amazon SNSとは何ですか？
Amazon SNSは、Amazon Simple Notification Serviceの略で、アプリケーション、エンドユーザー、およびデバイスがクラウドから即時に通知を送受信できるようにするウェブサービスです。

# 2. Amazon SNSでトピックを作成するにはどうすればよいですか？
Amazon SNSでトピックを作成するには、AWSマネージメントコンソールまたはAWS SDKを使用できます。マネージメントコンソールで、Amazon SNSに移動し、「トピック」を選択し、次に「新しいトピックを作成」を選択します。その後、トピック名と任意の表示名または購読確認設定を指定できます。

# 3. Amazon SNSを使用する一般的なシナリオは何ですか？
Amazon SNSの使用に関する一般的なシナリオには、アプリケーションの統合、アプリケーションのアラート、ユーザー通知、モバイルプッシュ通知などがあります。

# 4. エンドポイントをAmazon SNSトピックに登録するにはどうすればよいですか？
エンドポイントをAmazon SNSトピックに登録するには、AWSマネージメントコンソールまたはAWS SDKを使用できます。マネージメントコンソールで、トピックに移動し、「購読」を選択し、次に「購読を作成」を選択します。その後、プロトコル（例えば、電子メール、SMS、HTTPSなど）、エンドポイント（電子メールアドレスや電話番号など）、任意のフィルタポリシーを指定できます。

# 5. Amazon SNSのメッセージバッチングとは何ですか？
メッセージバッチングは、Amazon SNSの機能で、一度のAPI呼び出しで複数のメッセージを送信できるようにするもので、これによりコストを削減し、パフォーマンスを向上させることができます。メッセージバッチングを使用すると、Amazon SNSはメッセージをサイズと宛先に基づいてバッチに自動的にグループ化し、可能な限り効率的に送信します。
[AWS Q&A 365][SNS]Daily Five Common Questions #64

# 1. What is Amazon SNS? 
Amazon SNS stands for Amazon Simple Notification Service. It is a web service that enables applications, end-users, and devices to instantly send and receive notifications from the cloud. 

# 2. How do I create a topic in Amazon SNS? 
To create a topic in Amazon SNS, you can use the AWS Management Console or the AWS SDKs. In the Management Console, navigate to Amazon SNS, choose "Topics", and then "Create new topic". You can then specify the topic name and any optional display name or subscription confirmation settings. 

# 3. What are some common scenarios for using Amazon SNS? 
Some common scenarios for using Amazon SNS include application integration, application alerts, user notifications, and mobile push notifications. 

# 4. How can I subscribe an endpoint to an Amazon SNS topic? 
To subscribe an endpoint to an Amazon SNS topic, you can use the AWS Management Console or the AWS SDKs. In the Management Console, navigate to the topic, choose "Subscriptions", and then "Create subscription". You can then specify the protocol (such as email, SMS, or HTTPS), the endpoint (such as an email address or phone number), and any optional filter policies. 

# 5. What is message batching in Amazon SNS? 
Message batching is a feature in Amazon SNS that enables you to send multiple messages in a single API call, which can help reduce costs and improve performance. When you use message batching, Amazon SNS will automatically group messages into batches based on their size and destination, and then send them as efficiently as possible.
【SwiftUI】アクセシビリティで「文字を太くする」がオンになっているか判定する

# はじめに
アクセシビリティ設定によってアプリのUIは結構変化します。

アクセシビリティを頭に入れて開発して、アクセシビリティによるUIの変化に対応できるようになりましょう！

今回は文字の太さの設定です。

# 「文字を太くする」の場所
アクセシビリティ → 画面表示とテキストサイズ → 文字を太くする
|||
|-|-|
|![Simulator Screenshot - iPhone 14 Pro - 2023-05-23 at 22.10.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/13238d5f-6861-acd9-e4af-31bf08675ae8.png)|![Simulator Screenshot - iPhone 14 Pro - 2023-05-23 at 22.11.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/68c46828-cf68-9ef0-b310-89e0de402316.png)|

# 実装
```swift
import SwiftUI

struct ContentView: View {
    @Environment(\.legibilityWeight) var legibilityWeight
    var body: some View {
        switch legibilityWeight {
        case .regular:
            Text("regular")
        case .bold:
            Text("bold")
        case .none:
            Text("none")
        case .some(_):
            Text("some")
        }
    }
}
```

|regular|bold|
|-|-|
|![Simulator Screenshot - iPhone 14 Pro - 2023-05-23 at 22.12.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/7eaf4e6b-c78b-2576-d2e3-89365856d180.png)|![Simulator Screenshot - iPhone 14 Pro - 2023-05-23 at 22.12.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/1f980f99-25d1-a3c2-a9ec-20ccbebb785d.png)|

# 文字の太さを固定したい
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("regular")
            .environment(\.legibilityWeight, .regular)
    }
}
```

# おわり
これまでにアクセシビリティ系の記事は結構書いてきました。
アクセシビリティマスターになりたいですね

https://qiita.com/SNQ-2001/items/01329776c4c5e220c35b

https://qiita.com/SNQ-2001/items/d94c39ed765889b46869

https://qiita.com/SNQ-2001/items/c47326057003f04c7e34

https://qiita.com/SNQ-2001/items/25e8602ab341c7ec2cb5
Vue 3: Get API axios 

# Vue 3 Get API AXIOS

## 依頼
Vue3 を使ってください。
axiosでAPIを呼んでください。
Getでお願いします。
APIは以下のアドレスを使ってください。
https://jsonplaceholder.typicode.com/users
Composition APIを使ってください

## chatGBTからの回答
```javascript
npm install axios
```

```javascript
UserList.vue
<script>
<template>
  <div>
    <ul>
      <li v-for="user in users" :key="user.id">{{ user.name }}</li>
    </ul>
  </div>
</template>

<script>
import { ref, onMounted } from 'vue';
import axios from 'axios';

export default {
  setup() {
    const users = ref([]);

    onMounted(async () => {
      try {
        const response = await axios.get('https://jsonplaceholder.typicode.com/users');
        users.value = response.data;
      } catch (error) {
        console.error(error);
      }
    });

    return {
      users
    };
  }
};
</script>
```
App.vue
```javascript
<template>
  <div>
    <UserList />
  </div>
</template>

<script>
import UserList from './UserList.vue';

export default {
  components: {
    UserList
  }
};
</script>

```
マルチテナント構成DBでOS認証かつ共通ユーザーを作成する場合

##### １．OS認証用DBユーザーの作成
sysユーザーでSQLログオンし、OS認証用のDBユーザーを作成してDB接続用の最小権限を付与する。
★補足
・ユーザー名はC##込みで大文字で指定すること。
・ダブルクォートなしで指定すると小文字でもOracleが大文字に変換して認識する。
・作成した共通ユーザーに権限を付与する際は「CREATE SESSION」だけでなく、「SET CONTAINER」も指定すること。これがないとCDBからPDBにコンテナ切り替えできない。
```
--C##USER1を作成する
CREATE USER "C##OSUSER1" IDENTIFIED EXTERNALLY;

--「CREATE SESSION」権限を付与する
GRANT CREATE SESSION TO C##OSUSER1 CONTAINER=ALL;

--「SET CONTAINER」権限を付与する
GRANT SET CONTAINER TO C##OSUSER1 CONTAINER=ALL;

※上記の権限付与は以下のようにまとめて指定可能
GRANT CREATE SESSION,SET CONTAINER TO "C##OSUSER1" container = ALL;
```

##### ２．初期パラ「OS_AUTHENT_PREFIX」の設定
初期化パラメータ「OS_AUTHENT_PREFIX」の値を「COMMON_USER_PREFIX」と同じ「C##」に設定する。
```
ALTER SYSTEM SET OS_AUTHENT_PREFIX='C##' SCOPE=SPFILE;
```

##### ３．DBを再起動する
```
srvctl stop db -d orcl
srvctl start db -d orcl
```

##### ３．環境変数の設定
OS認証接続するOSユーザー「osuser1」にスイッチし、DB接続に必要な環境変数を設定する。（.bash_profileに追加してもよい）
```
export ORACLE_SID=orcl1
export ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
export PATH=$ORACLE_HOME/bin:$PATH
```
##### ４．DB接続
OS認証でDB接続する
```
sqlplus /
```
ScalaでHelloWorldプログラムを実装してみた

# 概要
ScalaでHelloWorldプログラムを実装してみました。以下のページを参考にしました。

https://qiita.com/kaysquare1231/items/ef4fd1625ab06e1c635f

# プログラム作成
3種類プログラムを作りました。コンパイルして実行はできるのですが、
普通にscalaを実行しようとするとClassNotFoundExceptionが発生して動きませんでした。
ソースコードは以下の通りです。

```HelloWorld.scala
    object HelloWorld{
      def main(args: Array[String]){
        if(args.size == 0) {
          val strs = Array("Hello", "World")
              output(strs)
        } else {
              printf("Invalid args.")
        }
      }

      def output(strs: Array[String]):Unit = {
        for(str <- strs) {
          printf("%s ", str)
        }
      }
    }
```

```HelloWorld2.scala
object HelloWorld2 {
  def main(args:Array[String]):Unit = {
    println("Hello, World!")
  } 
}
```

```HelloWorld3.scala
object HelloWorld3 extends App {
    println("Hello, World!")
}
```

# コンパイル＆実行
以下の通り、コンパイルしてから実行するのなら動くのですが・・・。
```
$ scalac HelloWorld.scala 
$ scala HelloWorld
Hello World 
$ scalac HelloWorld2.scala 
$ scala HelloWorld2
Hello, World!
$ scalac HelloWorld3.scala 
$ scala HelloWorld3
Hello, World!
```

# 実行（できず）
```
$ scala HelloWorld.scala
error: Compile server encountered fatal condition: javax/tools/DiagnosticListener
$ scala HelloWorld2.scala
エラー。長いので記述しません。
$ scala HelloWorld3.scala
error: Compile server encountered fatal condition: javax/tools/DiagnosticListener
java.lang.ClassNotFoundException: javax.tools.DiagnosticListener
```

# 実行（できた！）
オプションを付ければエラーなく実行できました。
```
$ scala -nobootcp -nc HelloWorld.scala 
Hello World 
$ scala -nobootcp -nc HelloWorld2.scala 
Hello, World!
$ scala -nobootcp -nc HelloWorld3.scala 
Hello, World!
```

# まとめ
何かの役に立てばと。
JPGとJPEGの違いとは？

https://ferret-plus.com/6740?page=2

https://qiita.com/jnchito/items/3d225112a3ac95379b1d

JPEG形式のファイルには```「.jpg」```と```「.jpeg」```という2種類の拡張子があります。

```「JPG（.jpg）」```と```「JPEG（.jpeg）」```の違いを解説します。

# JPEG（ジェイペグ）形式とは
JPEG形式はフルカラーの1,677万色を表現することができ、風景写真など色合いにグラデーションがある画像に適しているファイル形式です。

JPEGはPNGとは異なり、一度画像を圧縮してしまうと元に戻せない「不可逆圧縮」という特徴があります。そのため画質を下げてしまうと、元の画質には戻せません。

# .jpegと.jpgの違い
端的に言うと、この2つは表記されている拡張子が違うだけで、機能面での違いはありません。

# 「.jpg」と「.jpeg」どちらの拡張子を選べばいいの？
→***迷ったら「.jpg」を利用しよう。***
.jpgと.jpegは同じファイル形式であり、拡張子が異なるだけで利用制限などの違いはありません。
ここまで紹介してきたように```「.jpg」```と```「.jpeg」```に表記以外の違いはなく、あまり違いを意識しなくても利用できます。
もしファイルを保存する際にどちらの形式にするか迷ったら、より一般的に普及している```「.jpg」```にするといいでしょう。






# ※jpegだと画像が表示されないことがある
拡張子が"***jpeg***"になっていると、ローカルでは表示されるのに、Herokuにデプロイしたときに表示されずエラーが起きることがあります。

```erb
<!-- NG: 拡張子がjpegになっている！ -->
<%= image_tag "bread.jpeg" %>
```
<br>

***対処法: コード上のJPG画像の拡張子は"jpg"で統一する***
Railsは```assets:precompile```を実行すると、JPG画像の拡張子を"***jpg***"に統一します。そのため、コード上の拡張子が"***jpeg***"になっているとファイルが参照できず、エラーが発生します。以下のように拡張子を"***jpg***"にすればHerokuで画像が表示されます。

```erb
<%= image_tag "bread.jpeg" %>
↓
<%= image_tag "bread.jpg" %>
```
```app/assets/images/```に格納されている画像の拡張子も"***jpeg***"になっている場合は、無用なトラブルを避けるため、あわせて"***jpg***"に変更しておきましょう。

```
git mv app/assets/images/bread.jpeg app/assets/images/bread.jpg
```
CSSのフォントサイズ指定

# はじめに
フォントサイズ指定の単位っていくつか指定方法あるけどいつまで経っても覚えられないから自分用にメモすることにしました。

## px（ピクセル）
絶対値の単位。ピクセル単位は固定されており、他の要素のサイズには依存しません。
例えば、**font-size: 16px;と指定すると、16ピクセルのサイズ**でテキストが表示されます。
画面のサイズが変わってもずっと１6pxです。

## rem（ルートエム）
親要素のフォントサイズを基準に倍々する。
ルートエムという単位で、基準となるルート要素（通常は`<html>`要素）のフォントサイズに対する倍率でフォントサイズを指定します。
例えば、**`font-size: 1.2rem;`と指定すると、ルート要素のフォントサイズの1.2倍のサイズ**でテキストが表示されます。
ルート要素のフォントサイズを変更すれば、その倍率に応じて全体のフォントサイズも変わります。

## em（エム）
親要素のフォントサイズを基準に倍々する。
エムという単位で、現在の要素のフォントサイズに対する倍率でフォントサイズを指定します。
例えば、**`font-size: 1.2em;`と指定すると、現在の要素のフォントサイズの1.2倍のサイズ**でテキストが表示されます。
親要素のフォントサイズを変更すれば、その倍率に応じて子要素のフォントサイズも変わります。

## %（パーセント）
パーセントという単位で、現在の要素の親要素に対するフォントサイズのパーセンテージでフォントサイズを指定します。
例えば、**`font-size: 80%;`と指定すると、親要素のフォントサイズの80%のサイズ**でテキストが表示されます。
親要素のフォントサイズを変更すれば、そのパーセンテージに応じて子要素のフォントサイズも変わります。