OmniAICreator/Qiita-1.07M huggingface dataset:
ざっくりフロントエンドのテスト手法（TypeScript）

## はじめに
フロントエンドのテストは、Webアプリケーションのユーザーインターフェース（UI）やユーザーエクスペリエンス（UX）を保証するために重要です。適切なテスト手法を使用することで、バグの早期発見や品質の向上を図ることができます。この記事では、TypeScriptを使用したフロントエンドのテスト手法について説明します。

## 1. ユニットテスト
ユニットテストは、アプリケーションの最小単位（関数やコンポーネント）をテストする手法です。ユニットテストは、個々の機能が正しく動作することを確認するために使用されます。

### ツール
- **Jest**: Facebookが開発したJavaScriptのテスティングフレームワーク。TypeScriptもサポートしています。
- **Mocha**: 柔軟で拡張性の高いJavaScriptのテスティングフレームワーク。TypeScriptもサポートしています。

### 例: Jestを使用したユニットテスト
``` TypeScript:例
// sum.ts
export function sum(a: number, b: number): number {
    return a + b;
}

// sum.test.ts
import { sum } from './sum';

test('adds 1 + 2 to equal 3', () => {
    expect(sum(1, 2)).toBe(3);
});
```
## 2. コンポーネントテスト
コンポーネントテストは、UIコンポーネントが正しく動作することを確認するためのテスト手法です。ReactやVue.jsなどのフレームワークを使用する場合に特に重要です。

### ツール
- **React Testing Library**: Reactコンポーネントのテストを支援するライブラリ。TypeScriptもサポートしています。
- **Vue Test Utils**: Vue.jsコンポーネントのテストを支援する公式ライブラリ。TypeScriptもサポートしています。

### 例: React Testing Libraryを使用したコンポーネントテスト
``` TypeScript:例
// MyComponent.tsx
import React from 'react';

interface MyComponentProps {
    text: string;
}
const MyComponent: React.FC<MyComponentProps> = ({ text }) => {
    return <div>{text}</div>;
};
export default MyComponent;


// MyComponent.test.tsx
import React from 'react';
import { render } from '@testing-library/react';
import MyComponent from './MyComponent';

test('renders the correct text', () => {
    const { getByText } = render(<MyComponent text="Hello, World!" />);
    expect(getByText('Hello, World!')).toBeInTheDocument();
});
```


## 3. エンドツーエンド（E2E）テスト
エンドツーエンドテストは、アプリケーション全体のフローをテストする手法です。ユーザーが実際に行う操作をシミュレートし、アプリケーションが期待通りに動作することを確認します。

### ツール
- **Cypress**: モダンなエンドツーエンドテストフレームワーク。TypeScriptもサポートしています。
- **Playwright**: Microsoftが開発したエンドツーエンドテストフレームワーク。TypeScriptもサポートしています。

### 例: Cypressを使用したエンドツーエンドテスト
``` TypeScript:例
// cypress/integration/sample_spec.ts
describe('My First Test', () => {
  it('Visits the Kitchen Sink', () => {
    cy.visit('https://example.cypress.io');
    cy.contains('type').click();
    cy.url().should('include', '/commands/actions');
    cy.get('.action-email').type('fake@email.com').should('have.value', 'fake@email.com');
  });
});
```
## 4. スナップショットテスト
スナップショットテストは、UIの変更を検出するためのテスト手法です。コンポーネントのレンダリング結果をスナップショットとして保存し、後のテストで比較します。

### ツール
- **Jest**: スナップショットテストをサポートするテスティングフレームワーク。TypeScriptもサポートしています。

### 例: Jestを使用したスナップショットテスト
``` TypeScript:テスト対象コード
// MyComponent.tsx
import React from 'react';

interface MyComponentProps {
  text: string;
}

const MyComponent: React.FC<MyComponentProps> = ({ text }) => {
  return <div>{text}</div>;
};

export default MyComponent;
```
``` TypeScript:テストコード
// MyComponent.test.tsx
import React from 'react';
import renderer from 'react-test-renderer';
import MyComponent from './MyComponent';

test('renders correctly', () => {
  const tree = renderer.create(<MyComponent text="Hello, World!" />).toJSON();
  expect(tree).toMatchSnapshot();
});
```
## まとめ
フロントエンドのテスト手法には、ユニットテスト、コンポーネントテスト、エンドツーエンドテスト、スナップショットテストなどがあります。まだ使ったことが無いので使ってみようと思います。
Apple MapKitのMKTileOverlayを使ってタイル座標のズームレベルを取得する

# 概要

Apple MapKitのMKTileOverlayを使ってタイル座標のズームレベルを取得します

## 背景

地理情報システム(GIS）を作成するときタイル座標およびタイル画像は欠かせない概念かと思います。タイル座標は `z/x/y` の形式で表現されます。

しかしながら、Apple MapKitにはズームレベルという概念がなく、よくregionを操作・計算してズームレベルを計算します。

しかし調査をしたところ、MKTileOverlayというタイル画像を読み込むためのクラスを用いることで簡単にズームレベルを取得できることがわかりました！

このことについての解説記事が自分が調査した範囲では見つけることができなかったので、この記事を作成した次第です。同じケースでお悩みの方の参考になれば嬉しいです🙏


## サンプルコード

```swift
import UIKit
import MapKit

class ViewController: UIViewController {
    // 国土地理院のTileOverlayを作成する
    lazy var mapTile = MKTileOverlay(urlTemplate: "https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png")
    // タイル座標のカスタムTileOverlayを作成する
    lazy var gridTile = GridOverlay()

    lazy var mapView: MKMapView = {
        let mapView = MKMapView()
        mapView.delegate = self
        // 地理院のタイルを追加
        mapView.addOverlay(mapTile)
        // カスタムタイルを追加
        mapView.addOverlay(gridTile)
        return mapView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        mapView.frame = view.bounds
        view.addSubview(mapView)
        
        // Mapの初期化
        let coordinate = CLLocationCoordinate2D(latitude: 35.681236, longitude: 139.767125)
        let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05)
        let region = MKCoordinateRegion(center: coordinate, span: span)
        mapView.setRegion(region, animated: false)
    }
}

extension ViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        // TileOverlayの描画
        return MKTileOverlayRenderer(overlay: overlay)
    }
}

class GridOverlay: MKTileOverlay {
    override func loadTile(at path:MKTileOverlayPath, result:@escaping (Data?, Error?) -> Void) {
        UIGraphicsBeginImageContext(CGSize(width: 256,height: 256))

        guard let context = UIGraphicsGetCurrentContext() else {
            return
        }
        
        // 格子を描画する
        context.setStrokeColor(UIColor.black.cgColor)
        context.stroke(CGRect(x: 0, y: 0, width: 256,height: 256))
    
        // タイル座標（z/x/y）をテキストを描画する
        UIGraphicsPushContext(context)
        let font = UIFont.systemFont(ofSize: 20)
        let text = "\(path.z) / \(path.x) / \(path.y)"
        let string = NSAttributedString(string: text, attributes: [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: UIColor.red])
        string.draw(at: CGPoint(x: 0, y: 118))
        UIGraphicsPopContext()


        let tileImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        result(tileImage?.pngData(), nil)
    }
}

```

## キャプチャ画像

準備中


国土地理院の座標確認ページとぜひ比較してみてください！

https://maps.gsi.go.jp/development/tileCoordCheck.html#8/35.402/140.029

## 参考

https://qiita.com/imk2o/items/7328ee15e248ed3ff6f2

https://qiita.com/ta9yamakawa/items/01af672afd2f7374a506
docker compose系のコマンド入力はエイリアスでプチ業務効率化しよう

# 推奨エイリアス
```bash
alias dp='docker ps'
alias di='docker image ls'
alias dv='docker volume ls'
alias dl='docker compose logs -f --tail=100' # お好みで
alias dr='docker compose restart'
alias dd='docker compose down'
alias dbu='docker compose build --no-cache'
alias dup='f(){ if [ $# -eq 0 ]; then docker compose up -d; else docker compose -f "$1" up -d; fi; }; f'
alias dh='function _dh(){ docker-compose exec "$1" bash; };_dh'
```
# 使い方
```
dup
```
で`docker compose up -d`と同じコマンドが実行されます。
```
dup custom-compose.yml
```
でファイル指定も可能です。

```
dh コンテナ名
```
でコンテナに入ることができ、`dh コンテナ名 -c コマンド名` みたいな使い方もできます。


# どれくらい短縮できそうか
一番よく使いそうな `docker compose up -d` は、自分だとエイリアスを使うことで1秒短縮になっています。
これが1ヶ月で30回行うとしたら30秒で、1年間で360秒短縮できています。これだけで**年間6分の効率化**が図れています。
マラソン選手だと1km走ることができますね。

# 補足
削除系は省略すると事故の元なのであえて記述していません。
みなさん愛用の`docker compose`系エイリアスがあれば教えてください。
[備忘録]インスタンス化の練習


`ListView`で同じフォーマットのものを並べる練習です。
SNSアプリや情報メディアを作る時に便利そう

```main.dart
import 'package:flutter/material.dart';

// ツイート
class Tweet {
  // ユーザーの名前
  final String userName;
  // アイコン画像
  final String iconUrl;
  // 文章メッセージ
  final String text;
  // 送信日時
  final String createdAt;

  // コンストラクタ
  Tweet(this.userName, this.iconUrl, this.text, this.createdAt);
}

// 適当なモデル
final models = [
  Tweet('ルフィ', 'icon1.png', '海賊王におれはなる！', '2022/1/1'),
  Tweet('バルトロメオ', 'icon1.png', 'この子分盃!勝手に頂戴いたしますだべ!', '2022/3/1'),
];

// モデル => ウィジェット に変換する。ここのmodelは引数で仮のキーワード
Widget modelToWidget(Tweet model) {
  // ユーザーアイコン
  final icon = Container(
    margin: const EdgeInsets.all(20),
    width: 60,
    height: 60,
    // 画像を丸くする
    child: ClipRRect(
      borderRadius: BorderRadius.circular(30.0),
      child: Image.asset('assets/images/${model.iconUrl}'),
    ),
  );

  // 名前と時間
  final metaText = Container(
    padding: const EdgeInsets.all(6),
    height: 40,
    alignment: Alignment.centerLeft,
    child: Text(
      '${model.userName}    ${model.createdAt}',
      style: const TextStyle(color: Colors.grey),
    ),
  );

  // 本文
  final text = Container(
    padding: const EdgeInsets.all(8),
    alignment: Alignment.centerLeft,
    child: Text(
      model.text,
      style: const TextStyle(fontWeight: FontWeight.bold),
    ),
  );

  // 部品を並べる
  return Container(
    padding: const EdgeInsets.all(1),
    decoration: BoxDecoration(
      // 全体を青い枠線で囲む
      border: Border.all(color: Colors.blue),
      color: Colors.white,
    ),
    width: double.infinity,
    // 高さ
    height: 120,
    child: Row(
      children: [
        // アイコン
        icon,
        Expanded(
          child: Column(
            children: [
              // 名前と時間
              metaText,
              // 本文
              text,
            ],
          ),
        ),
      ],
    ),
  );
}

// メイン関数
void main() {
  // ツイートのリスト
  final list = ListView.builder(
    itemCount: models.length,
    itemBuilder: (c, i) => modelToWidget(models[i]), 
    //上の仮キーワードmodelsに作ったmodelsを具体的に代入している
  );

  final con = Center(
    child: SizedBox(
      height: 400,
      child: list,
    ),
  );

  // 画面
  final sca = Scaffold(
    backgroundColor: Colors.grey,
    body: con,
  );

  // アプリ
  final app = MaterialApp(home: sca);
  // アプリを動かす
  runApp(app);
}

```
GoのCobraを使ってCLIを作ってみた

## はじめに
[前回](https://qiita.com/engineer_tacky/items/bbb2d740a6dc0da3a5ab)、flagパッケージを使ってCLIを作ってみたので、今回はCobraライブラリを使用してCLIを作ってみました。

## コード
ルートのコマンドとして、toolkitという名前のコマンドを作成しています。
そのサブコマンドとして、countとlinesを作りました。
Useフィールドにコマンド名、Runフィールドに実行する関数を登録します。
そして、それぞれFlags().StringP()で引数を定義します。
定義できたら、最後にAddCommand()で登録します。

```main.go
package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"

	"github.com/spf13/cobra"
)

func main() {
	var rootCmd = &cobra.Command{Use: "toolkit"}

	var countCmd = &cobra.Command{
		Use:   "count [flags]",
		Short: "Count occurrences of a word in a file",
		Run:   countWord,
	}

	var linesCmd = &cobra.Command{
		Use:   "lines [flags]",
		Short: "Count lines in a file",
		Run:   countLines,
	}

	countCmd.Flags().StringP("file", "f", "", "File to search in")
	countCmd.Flags().StringP("word", "w", "", "Word to search for")
	countCmd.MarkFlagRequired("file")
	countCmd.MarkFlagRequired("word")

	linesCmd.Flags().StringP("file", "f", "", "File to count lines in")
	linesCmd.MarkFlagRequired("file")

	rootCmd.AddCommand(countCmd, linesCmd)

	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func countWord(cmd *cobra.Command, args []string) {
	filename, _ := cmd.Flags().GetString("file")
	word, _ := cmd.Flags().GetString("word")

	file, err := os.Open(filename)
	if err != nil {
		fmt.Printf("ファイルを開けませんでした: %v\n", err)
		os.Exit(1)
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	count := 0
	for scanner.Scan() {
		count += strings.Count(strings.ToLower(scanner.Text()), strings.ToLower(word))
	}

	if err := scanner.Err(); err != nil {
		fmt.Printf("ファイル読み込み中にエラーが発生しました: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("ファイル '%s' 内の '%s' の出現回数: %d\n", filename, word, count)
}

func countLines(cmd *cobra.Command, args []string) {
	filename, _ := cmd.Flags().GetString("file")

	file, err := os.Open(filename)
	if err != nil {
		fmt.Printf("ファイルを開けませんでした: %v\n", err)
		os.Exit(1)
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	lineCount := 0
	for scanner.Scan() {
		lineCount++
	}

	if err := scanner.Err(); err != nil {
		fmt.Printf("ファイル読み込み中にエラーが発生しました: %v\n", err)
		os.Exit(1)
	}

	fmt.Printf("ファイル '%s' の行数: %d\n", filename, lineCount)
}
```

## 動かしてみる
```zsh
go build -o toolkit main.go
```
```zsh
./toolkit count -f test.txt -w word test

ファイル 'test.txt' 内の 'word' の出現回数: 6
```
```zsh
./toolkit lines -f test.txt

ファイル 'test.txt' の行数: 4
```

## 参考
- https://github.com/spf13/cobra
TypeScriptの排他的な型について

# TypeScriptの排他的な型について

こんにちは、皆さん！今日はTypeScriptで使える便利な技術、排他的な型についてお話しします。みなさんはTypeScriptを使っていて、「このプロパティは絶対に同時に存在してほしくない！」と思ったことはありませんか？そんなときに役立つのが排他的な型です。

## 排他的な型とは？

排他的な型とは、特定のプロパティが同時に存在しないことを保証するための型です。これにより、コードの信頼性と安全性を高めることができます。具体的には、あるプロパティが存在するときは別のプロパティが存在しないというルールを定義します。

### 具体例

例えば、[前回書いた記事](https://qiita.com/Shuhei-pp/items/c22ec4e8801ea9916789)で以下のような関数があります。この関数は、SMSまたはメールのどちらか一方を送信するためのものです。

```typescript
const greatToSmsOrEmail = ({
  me,
  to,
  sms,
  email,
  text,
}: { me: string; to: string; text: string } & ({ sms: PhoneNumber; email?: never } | { email: Email; sms?: never })) => {
  // 関数のロジック
};
```

この関数の引数には排他的な要素があり、`sms`と`email`の両方が同時に存在することはできません。どちらか一方のみが存在することを型で保証しています。

### 排他的な型の定義

このような排他的な型は以下のように定義できます。

```typescript
type Exclusive<T extends Record<PropertyKey, unknown>, U extends Record<PropertyKey, unknown>> =
  | (T & { [k in Exclude<keyof U, keyof T>]?: never })
  | (U & { [k in Exclude<keyof T, keyof U>]?: never });
```

この定義により、`T`と`U`のプロパティが排他的であることが保証されます。

## 利用手順

では、実際にどのようにこの型を使うのか見ていきましょう。

### ステップ1: 型の定義

まずは先ほど紹介した排他的な型を定義します。

```typescript
type PhoneNumber = string;
type Email = string;

type Exclusive<T extends Record<PropertyKey, unknown>, U extends Record<PropertyKey, unknown>> =
  | (T & { [k in Exclude<keyof U, keyof T>]?: never })
  | (U & { [k in Exclude<keyof T, keyof U>]?: never });
```

### ステップ2: 関数の作成

次に、この型を使って関数を作成します。

```typescript
const sendMessage = (options: { me: string; to: string; text: string } & Exclusive<{ sms: PhoneNumber }, { email: Email }>) => {
  if (options.sms) {
    console.log(`Sending SMS to ${options.to}`);
  } else if (options.email) {
    console.log(`Sending Email to ${options.to}`);
  }
};
```

### ステップ3: 関数の呼び出し

最後に、この関数を呼び出してみましょう。

```typescript
sendMessage({ me: 'Alice', to: 'Bob', text: 'Hello', sms: '123-456-7890' });
// もしくは
sendMessage({ me: 'Alice', to: 'Bob', text: 'Hello', email: 'bob@example.com' });
```


## まとめ

排他的な型を使うことで、TypeScriptの型安全性をさらに高めることができます。ぜひ一度試してみてください！何か質問があれば、コメント欄で教えてくださいね。

## 参考記事

- [https://miyauchi.dev/ja/posts/exclusive-property/](https://miyauchi.dev/ja/posts/exclusive-property/)
負荷試験ツールの一覧

## 1. Apache JMeter
### メリット
- **オープンソース**: 無料で使用できる。
- **豊富な機能**: HTTP、FTP、JDBC、SOAP、RESTなど多くのプロトコルをサポート。
- **拡張性**: プラグインを追加して機能を拡張できる。
- **GUI**: 直感的なGUIでテストプランを作成しやすい。

### デメリット
- **リソース消費**: 大規模なテストでは多くのメモリとCPUを消費する。
- **学習曲線**: 初心者には設定や使い方が難しい場合がある。
- **スクリプトの複雑さ**: 複雑なシナリオを作成するのに時間がかかることがある。

## 2. Gatling
### メリット
- **高性能**: 高いスループットを実現し、大規模な負荷試験に適している。
- **スクリプトの簡潔さ**: ScalaベースのDSLでスクリプトを簡潔に記述できる。
- **レポート機能**: 詳細なレポートを自動生成する。

### デメリット
- **Scalaの知識**: Scalaの基本的な知識が必要。
- **GUIの欠如**: 主にコードベースでの操作となり、GUIがない。

## 3. Locust
### メリット
- **Pythonベース**: Pythonでスクリプトを記述できるため、Pythonに慣れている人には使いやすい。
- **分散テスト**: 複数のマシンで分散してテストを実行できる。
- **リアルタイムモニタリング**: テストの進行状況をリアルタイムでモニタリングできる。

### デメリット
- **リソース消費**: 大規模なテストでは多くのリソースを消費する。
- **機能の制限**: 一部の高度な機能が他のツールに比べて不足している。

## 4. k6
### メリット
- **JavaScriptベース**: JavaScriptでスクリプトを記述できるため、フロントエンド開発者にとって使いやすい。
- **軽量**: 高いパフォーマンスと低いリソース消費。
- **クラウド対応**: k6 Cloudを使用してクラウド上でテストを実行できる。

### デメリット
- **GUIの欠如**: 主にコードベースでの操作となり、GUIがない。
- **機能の制限**: 一部の高度な機能が他のツールに比べて不足している。

## 5. Tsung
### メリット
- **高スケーラビリティ**: 大規模な負荷試験に適している。
- **分散テスト**: 複数のマシンで分散してテストを実行できる。
- **多プロトコル対応**: HTTP、WebDAV、SOAP、PostgreSQL、MySQLなど多くのプロトコルをサポート。

### デメリット
- **設定の複雑さ**: 設定ファイルがXMLベースであり、設定が複雑。
- **学習曲線**: 初心者には設定や使い方が難しい場合がある。

## 6. Artillery
### メリット
- **JavaScriptベース**: JavaScriptでスクリプトを記述できるため、フロントエンド開発者にとって使いやすい。
- **軽量**: 高いパフォーマンスと低いリソース消費。
- **クラウド対応**: Artillery Proを使用してクラウド上でテストを実行できる。

### デメリット
- **機能の制限**: 一部の高度な機能が他のツールに比べて不足している。
- **スクリプトの複雑さ**: 複雑なシナリオを作成するのに時間がかかることがある。

## まとめ
多くのツールがあるので悩む。GUIで使用したいかどうかで分かれそう。

## 各公式サイト
https://jmeter.apache.org/
https://gatling.io/
https://locust.io/
https://k6.io/
https://www.artillery.io/
Jetpack Compose の基本のメモ#5 ~列と行を作成する2~

https://qiita.com/tiger98/items/a18b8f32eb6809fc0f58

の続き
### Compose と Kotlin
+ 小型のスマートフォンの一般的な幅（320 dp）
+ widthDp パラメータを @Preview アノテーションに追加することでプレビューにも同じ結果が表示される

### ボタンを追加する
+ Button は、material3 パッケージによって提供されるコンポーザブル
+ 他のコンポーザブルをラップするコンポーザブルは基本的に後置ラムダを使用している
+ Kotlinでは、関数の最後の引数が関数型（ラムダ式または関数参照）の場合、後置ラムダとして括弧の外に出すことができる
+ content = { Text("Show less") } は、関数名のない無名関数が引数contentに渡されている
+ Kotlinではこれをラムダ式と呼ぶ
```kotlin
// 後置ラムダを使用しない場合
Column(modifier = Modifier.fillMaxSize(), content = {
    Text("Hello")
    Text("World")
})

// 後置ラムダを使用する場合
Column(modifier = Modifier.fillMaxSize()) {
    Text("Hello")
    Text("World")
}
```
+ ElevatedButton:
    + 外観: 影（elevation）を持つボタン
    + 用途: 他のUI要素よりも目立たせたいアクションや、重要なアクションに適している

#### Row,Columnコンポーザブルがラップしている子要素の位置調整
+ align()修飾子を使うことで、親コンポーザブル（例えばBox）内での子要素の位置を調整できる
+ しかし、RowやColumnのようなレイアウトコンポーザブルでは、align()修飾子は使用できない
+ RowやColumn内で要素を端に配置したい場合は、Spacerとweight(1f)を組み合わせる
Wordpress.comにあるDeveloper ConsoleAPIがちょっとだけわかった

# Developer Consoleとは
Wordpress.com APIのPlayGroudです。

https://developer.wordpress.com/docs/api/console/

<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/063361a6-036a-883b-fdef-ddbede7c7dfb.png" />


Developer Consoleには以下にプルダウンがありますが、どこのAPIを使っているのかイマイチわからなかったです。

<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/2438f970-488e-b905-64bb-b60d2a426acf.png" />

<img width=500 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/374872/4f7458ec-df50-4280-3493-b45889123786.png" />

それぞれがどこのAPIを指しているのか、そしてその対応するAPIドキュメントについて記したいと思います。

## WP.COM API / `v1`
### APIドキュメント
https://public-api.wordpress.com/rest/v1/help

ただ、こちらは
```
This endpoint is deprecated in favor of version 1.1
```
と書いてあるように、ほぼ使いません。既存のサービスでv1.1ではなくv1を使用している場合はこちらを参照してください。

### 使用例
ブログURLが test.wordpress.com で、ブログの投稿一覧を取得する場合。
```
https://public-api.wordpress.com/rest/v1/sites/test.wordpress.com/posts/
```

## WP.COM / `v.1.1`
https://public-api.wordpress.com/rest/v1.1/help

こちらが現在メインで使用されているWordpress.comのAPIです。
以下でも同じ内容が見られます。

https://developer.wordpress.com/docs/api/

### 使用例
ブログURLが test.wordpress.com で、ブログの投稿一覧を取得する場合。
```
https://public-api.wordpress.com/rest/v1.1/sites/test.wordpress.com/posts/
```

## WP REST API / `wp/v2`
従来の `Wordpress.org` で使用されているREST API。

https://developer.wordpress.org/rest-api/reference/

### 使用例
ブログURLが test.wordpress.com で、ブログの投稿一覧を取得する場合。
```
https://test.wordpress.com/wp-json/wp/v2/posts
```

## WP REST API / `wpcom/v2`, WP REST API / `wpcom/v3`
こちらは二つともちゃんとしたドキュメントが存在していません。
`wpcom/v2` は、Wordpress.com REST APIの一部のインターフェースで使用されており、`wpcom/v3`はgutenbergのAPIを使用する際に使われていそうです。
一応ドキュメントはありますが、レスポンスの情報は確認できません。

### `wpcom/v2` のドキュメント
https://developer.wordpress.com/docs/api/#16-agencies

https://developer.wordpress.com/docs/api/#18-ssh-management

https://public-api.wordpress.com/wpcom/v2?context=help
### `wpcom/v3` のドキュメント
https://public-api.wordpress.com/wpcom/v3?context=help

## WP REST API / `wpcom/v4`
未実装っぽいです。Consoleで選択しても何もAPIが出てきません。

# おわりに
わかったと書いているもののわかっていないことが多すぎます。なにせWordpress.comの情報が巷に流れていない。

# 参考にしたもの
https://github.com/Automattic/wp-api-console
【linux】VPSを契約するのでディストリビューションを選ぶ

XサーバーでVPSを契約するのでディストリビューションそれぞれの違いを調べて選んでみます。

# VPSとは

「VPS」は、「Virtual Private Server（バーチャルプライベートサーバー）」の略で、日本語では「仮想専用サーバー」と呼ぶ。linux OSをレンタルして使えるサービス。

詳しくは、仮想化技術により1台の物理サーバー上に複数台の仮想的なサーバーを構築し、それぞれをユーザーが専有して使用できる専用サーバーとしてレンタルするサービスのこと。

# linuxディストリビューションとは

まずlinuxディストリビューションというものが何なのか、やんわりとしか理解がなかったので調べてみた。

## 狭義のlinuxと広義のlinux

以下の記事を引用：
https://lpi.or.jp/lpic_all/linux/intro/intro02.shtml

> Linuxとは、本来OSのコアであるカーネルといわれるものをさす言葉です。カーネルとは、OSの本来の役割であるハードウェアの制御やファイル、ソフトウェアの実行、リソース等の管理を行う部分で、普段ユーザがカーネルの動作を目にすることはありません。実際にユーザが目にする部分はアプリケーションであったり、OSの管理機能を利用するユーティリティソフトであったりします

linuxとはOSの核である「カーネル」を指し、そのカーネルが基本的な処理をするようだ。
さらに、次の記述があった。

> 通常Linuxを利用する場合、カーネル以外にも様々なソフトウェアが組み合わされた状態で利用します。このカーネル以外のその他のソフトウェアを一式含んだ状態が広義のLinuxです。

カーネルだけでは何かの処理を外部から実行したりできないため、アプリケーションをインストールする必要がある。その基本アプリケーションをインストールした状態を広い意味でのlinuxと指すようだ。

つまり、linuxには狭義の意味と広義の意味があるらしい。

- 狭義の意味：核である「カーネル」を指す
- 広義の意味：カーネルとその他のアプリケーションのセットを指す

## linuxディストリビューション

linuxカーネルだけでは外部から処理を実行できないので、アプリケーションをインストールする必要があるというのは先ほど調べたことだが、ユーザーが自身でOSを構築するときに毎度アプリケーションをインストールするには、時間・労力・知識がかかる。。

> そこで、LinuxカーネルとOSを構成するその他のソフトウェアを組み合わせる煩雑さをユーザから解放するために、最初からそれらを組み合わせた形で配布するという形が生まれます。これがディストリビューションです。

ふむふむ。そこでカーネルとアプリケーションのセットをあらかじめ作成し分配したもの。これを「linuxディストリビューション」というようだ。

# ディストリビューションの種類

ベースとなるSlackawareディストリビューション・Redhatディストリビューション・Debianディストリビューションの３つの派閥に大きく分かれている。

* Slackware系
    Slackware、Plamo、SLAX等
* Redhat（rpm）系
Fedora、CentOS、MIRACLE、RedFlag、PS2 Linux、Turbo、Vine、SUSE等
* Debian系
Debian/GNU Linux、Ubuntu、KNOPPIX、Omoikane、Linspie等

# ディストリビューションの選び方

いろいろ調べたが、目的によって変わってくる。

今回、ウェブサーバー、DBサーバーを立ててウェブサイトを公開したい。
やり方はできればDocker環境を動作させたいが、LAMP環境をlinuxに直接インストールでもよい。

個人でやるのでそれぞれのインストール方法を調べて、情報が豊富だったrocky linuxがよさそうに思った。rocky linuxは無償で利用できるred hat系ディストリビューションなのでdnfパッケージ管理が利用できるのもメリット。

今回はrocky linuxを選択する。

# 参考

https://www.nttpc.co.jp/column/network/whats_vps.html
【備忘録】初めてのiOSアプリ開発 第1回 if let文ってなに?

## はじめに
私はiPhoneアプリ開発が初めてです。初心者がどこにつまづき備忘録として投稿します。
今回は最初につまづきました「if let文」を紹介します。

◇現状のスキル
・アプリ開発自体が初めて
・Swiftを初めて触れる
・普段Windowsを使用しているので、Macでの操作が不慣れ（ショートカットキーもあまりわかっていない・・・）

## if let文ってなに？
・if let文はnilかどうかをチェックし、nil ではない場合はアンラップしてくれる便利な仕組み。

・関数やメソッド内でエラーが発生すると、nilが返される場合がある。値が存在しない場合にクラッシュしてしまうことを防ぐ。

if letを使ったオプショナルバインディングの基本的な構文
```swift:if let文
if let 定数名 = オプショナル値 {
    // オプショナル値がnilでない場合の処理
} else {
    // オプショナル値がnilの場合の処理
}
```

## オプショナル型とnilの基本
・オプショナル型は、値が存在するかもしれないし、存在しないかもしれない（nil）ことを表現する型です。
・オプショナル型は、Swiftの安全性と明示性を高める重要な機能であり、値の有無を正確に扱うために欠かせないものです。
・Swiftでは、オプショナル型は?を使って表現します。
例えば、Int?はオプショナルな整数を意味する。この型は、整数の値を持つこともあれば、nilを持つこともできます。

## nilとは？
・値が存在しないことを示すために使用される特別なリテラル。
```swift:nil
var optionalInt: Int? = 5
print(optionalInt) // Optional(5)

optionalInt = nil
print(optionalInt) // nil
```
## nilリテラルとは？
・nilリテラルは値が存在しないことを表します。オプショナル型に対して使用されます。
```swift:nilリテラル
let optionalInt: Int? = nil
```

## オプショナルバインディングとは？
・オプショナルバインディング（optional binding）は、オプショナル型の値を安全にアンラップするための方法です。

・オプショナルバインディングは主にif letやguard letを使って行われます。

具体的には、オプショナル型の値が存在する場合に、その値を一時的な定数や変数に代入し、存在しない場合は特定の処理を行うことができます。これにより、nilを安全に扱いながらコードを記述できます。

## オプショナルバインディングの利点
1.安全性: nilを直接アンラップしてクラッシュするリスクを回避できる。
2.明確な条件分岐: オプショナル値が存在する場合としない場合の処理を明確に分けることができる。
3.読みやすいコード: オプショナル型のアンラップが明示的に行われるため、コードの意図が明確になる。

```swift:オプショナルバインディング
var optionalString: String? = "Hello, Swift!"

if let unwrappedString = optionalString {
    print(unwrappedString) // "Hello, Swift!"
} else {
    print("optionalString is nil")
}
```

## 関連用語
|    関連用語   |   説明      　|                      
|:--------------------------|:-------------------------|
|オプショナル型   |Swiftでは、オプショナル型は?を使って表現します。|
|Optional Binding|オプショナルバインディングと呼ばれるもので、オプショナル型の値を安全にアンラップします。| 
|nil   |値が存在しないことを示すために使用される特別なリテラル|
|リテラル   |ソースコード内で直接記述される具体的な値のことを指す。リテラルは、変数や定数の初期化、条件式の判定、関数への引数を渡すといった場面で使用されます。| 
|if let |オプショナル型の値を安全にアンラップするために、オプショナルバインディングを使用します。|              
|アンラップ |アンラップ（unwrap）とは、オプショナル型（Optional）に包まれた値を取り出すことを指します。|          
|var |変数（variable）を宣言するために使用されるキーワード。プログラムの実行中に何度でも値を変更することができる。|  
|let |letは定数（constant）を宣言するために使用され、一度値を設定すると変更することができない。|
セキュリティ人材は高くつく

　カドカワがランサムウェアを受け入れてしまったゆえにとってもたいへんなことになっているようだ。
　ドワンゴが付いていて・・・という気がしなくもないが、よく考えたらドワンゴだった。
　N高校の生徒情報も流出していてご愁傷の極みである。
　というわけでセキュリティエンジニアを募集しているらしい。
　テコ入れ策のつもりなのだろうが、[年棒最大800万円](https://www.itmedia.co.jp/news/articles/2407/03/news137.html)。この金額にやる気のなさが現れていると思えるのは私だけだろうか。
　どうせ、リカバリの雑用を押し付けられて、ついでに責任者として尻尾切られるのだろうから一桁少ないのでは？(一桁は高すぎるかもだが、実力者が雇えるなら「安い!」と思わなければ。)
　出版不況でお金が足りないのかもしれない。でも800万円で済む、という判断が正しいのであれば、自由闊達な教育で知られているN高校でそれぞれの能力を伸ばした生徒に活躍してもらえればもっと安く済むぞ!という発想も同様に正しいと言わねばなるまい。

　時を同じくして「イセトー」という会社がランサムウェアで[情報流出に見舞われている](https://www.nikkei.com/article/DGXZQOUF056CM0V00C24A7000000/)。
　金融庁案件になっていたものの一般的には報道されてないということでコメントは差し控えていたが、[指名停止処分](https://www.iseto.co.jp/news/news_202203-3.html)になったがゆえの倒産回避策として、民間の印刷業務をやっすーく請け負っていたのだろうな、ということは容易に推測できる。
　ここも[以前、セキュリティ担当者を募集](https://doda.jp/DodaFront/View/EndJobDetail/j_id__3008878209/)していた。「未経験者歓迎」。やはりやる気に欠けていたようだ。
　つまりは「セキュリティは安く実現可能」という認識が痛い目にあう企業に共通しており、どうやらそれは痛い目にあっても変わらない、ということがいえそうだ。

　以前はそれでもなんとかなったのよ。コンピュータの主に外部からの攻撃に対するリスクが徐々に増してゆき、それに都度対応することによって能力を高めてきた人が社内にいて、プライドをもって頑張ってくれていたからだ。ところが世代交代で、いわば「安く使える生え抜き」がいなくなる。生え抜きがいなければ高給を払って引き抜いてこなければならないのは、 ~~昔の読売ジャイアンツ~~ サッカーのビッグクラブを見ても明らか。
　引退した生え抜きが後継者をきちんと育てていればいいのでは？うん。その通りだ。しかし安く使えるとしても安く使いすぎた。「何も起こらなくて当たり前」と思い込んで担当者へのケアを怠っていたのだ。生え抜きとしては大変な注意力と情報収集力の必要な業務を後輩に引き継ぐのは気が引ける。社内で評価されないということは無意味だからだ。自分は良かれと思ってやっていたが、そんな自分の勘違いを引き継ぐことに良心の呵責を感じたのだろう。
　さらにひどい例もあった。確かに自分は社内の情報流出を未然に防いだ。しかしそのシステムの構築なり管理をやっている部署からすれば「欠陥を指摘された」わけであり、つまりはなかったこととして握りつぶす。(逆に余計なことをしやがって、という目で見られる。)こうなるとノウハウを誰かに伝えたくとも「そんなものは初めからない」ことにされているのだ、伝承はされない。
　かくしてセキュリティができる人間の再調達コストは、驚くほど高くなってしまった。必要なはずなのに自ら捨ててしまい、市場に残っていないからだ。

　角川ドワンゴだけが悪いんじゃない。ただし、ここまであからさまになった以上、人材を金銭面からも正当に評価して、日本に欠けていた流れを作るきっかけとなってほしいものだと思う。
Crystal言語でシングルバイナリを作る

## はじめに

タイトルをキャッチーにしたのは人集めです。ご容赦ください。あまりシングルバイナリの話はしていません。調べ物のスタートに使ってください。

- Rubyでツールを配布するときにはGemにするのが一般的である。
- 単純なツールであればCrystalで書いてバイナリにすることもできる。

## Crystalで静的にリンクしたバイナリを作成する

公式では、

```sh
crystal build a.cr --static
```

とすればいいことにされているが、実際には動作しないことが多い。
そこで、muslのライブラリを使っている公式のDockerイメージを使用するとLinux用のバイナリを出力できる。
たとえばこんな感じ。

```sh
docker run --rm -it \
  -v $(pwd):/workspace \
  -w /workspace \
  crystallang/crystal:latest-alpine \
  crystal build a.cr --static --release
```

Shardsのライブラリなどを利用していて、C言語のライブラリに依存していることもあるだろう。その場合は下のようなコマンドを使ってツールをインストールしたりして頑張る。

```sh
docker exec alpine apk add cmake build-base readline-dev readline-static ncurses-dev ncurses-static ncurses-libs 
```

Crystalのコンパイラの中には、`--cross-compile` や `--mcpu` などのオプションもあるが、LLVMに依存しているだけだと思うから、あまり信用しすぎない方がいいと思う。

Macでは静的にリンクしたバイナリの出力は諦めて homebrew-tap を使った方が幸せになれると思う。

Windowsも単に `crystal build --static` すればよく、RubyではWindows向けの実行ファイルを作るのはかなりの制限があるのでかなり便利である。ただし、Cのライブラリを導入するのは煩雑というか、まだ未完成。

もう少し詳しくは↓

https://qiita.com/kojix2/items/ba54254977f89e94706b
Raspberry Pi 5で YOLOv8.2を動かす

* Raspberry Pi 5 8GB
* logicool C270N
* microSDXC 64GB
* Raspberry Pi OS(64-bit)（Release date：July 4th 2024、Python 3.11.2）

## OpenCV、torch等のインストール
```
sudo rm /usr/lib/python3.11/EXTERNALLY-MANAGED
sudo pip3 install opencv_python==4.8.1.78
sudo pip3 install torch==2.0.1
sudo pip3 install torchvision==0.15.2
sudo pip3 install torchaudio==2.0.2
sudo pip3 install cvzone==1.6.1
sudo pip3 install matplotlib==3.9.1
sudo pip3 install pyyaml==6.0.1
sudo pip3 install tqdm==4.66.4
sudo pip3 install py-cpuinfo==9.0.0
sudo pip3 install pandas==2.2.2
```

## YOLOv8のインストール
```
sudo pip3 install ultralytics==8.2.50
```

## YOLOv8の動作確認
```
yolo task=detect mode=predict model=yolov8n.pt source=0 show=True imgsz=256
```

:::note info
Raspberry Pi 5：1 frame：0.114s（8.77fps）
:::
Instana 大規模言語モデル（LLM）モニタリング概要：開発から運用まで

## はじめに

大規模言語モデル（LLM）の普及に伴い、AI駆動型アプリケーションの開発から運用まで、様々な課題が浮上しています。Instanaが提供する大規模言語モデル（LLM）モニタリング機能は、これらの課題に対応する統合的なソリューションです。

さくっと、セットアップガイドと実践的な使用例から知りたい方は、下記投稿をご覧ください。

https://qiita.com/daihiraoka/items/3f291202ec20b7ba41b4

## LLMアプリケーションの主な課題

```mermaid
graph TD
    A[LLMアプリケーション] --> B[開発段階の課題]
    A --> C[運用段階の課題]
    B --> D[モデル選択と評価]
    B --> E[プロンプトエンジニアリング]
    B --> F[統合テスト]
    C --> G[パフォーマンス最適化]
    C --> H[コスト管理]
    C --> I[異常検知]
```

1. 開発段階:
   - モデル選択と評価
   - プロンプトエンジニアリングの最適化
   - 統合テストと品質保証
2. 運用段階:
   - パフォーマンスの最適化
   - コスト管理
   - 異常の早期発見
   - ユーザー体験の向上

## Instana LLMモニタリングのアーキテクチャ

```mermaid
graph TD
    A[LLMアプリケーション] -->|メトリクス・トレース| B[Instana エージェント]
    B -->|データ送信| C[Instanaバックエンド]
    C -->|分析結果| D[ダッシュボード]
    C -->|アラート| E[通知システム]
    C -->|開発フィードバック| F[開発環境]
```

## サポートしているLLMプロバイダーと関連技術

Instana LLMモニタリングは、幅広いLLMプロバイダーやベクトルデータベース、フレームワークをサポートしています。

### メトリクス収集対応
- IBM watsonx.ai
- OpenAI

### トレース対応

```mermaid
graph TD
    A[Instana LLMモニタリング] --> B[LLMプロバイダー]
    A --> C[ベクトルDB]
    A --> D[フレームワーク]
    B --> B1[watsonx,OpenAI, Anthropic, etc.]
    C --> C1[Chroma, Pinecone, etc.]
    D --> D1[LangChain, LlamaIndex, etc.]
```

主なサポート技術:
- LLMプロバイダー: OpenAI/Azure OpenAI, Anthropic, Cohere, Ollama, Mistral AI, HuggingFace, AWS Bedrock, Replicate, Vertex AI (GCP), Google Generative AI (Gemini), IBM watsonx.ai, Together AI, Aleph Alpha
- ベクトルDB: Chroma, Pinecone, Qdrant, Weaviate, Milvus, Marqo
- フレームワーク: LangChain, LlamaIndex, Haystack, LiteLLM

この広範なサポートにより、多様なLLMアプリケーション環境でInstana LLMモニタリングを活用できます。

## Instana LLMモニタリングの主なメリット

1. 多様なLLMプロバイダーとの互換性
2. 開発・テストサイクルの効率化
3. リアルタイムの可視化と監視
4. 詳細なメトリクス分析
5. コスト最適化
6. 機械学習ベースの異常検知
7. エンドツーエンドの追跡

## 主要機能

- OpenLLMetryベースのトレース収集
- OpenTelemetryベースのメトリクス収集
- カスタマイズ可能なダッシュボード
- アラートと通知システム
- 詳細なトレース分析
- AIモデルのバージョン管理と比較
- 開発環境との統合

## ビジネスへの効果

```mermaid
graph TD
    A[Instana 大規模言語モデル（LLM）モニタリング] --> B[開発速度の向上]
    A --> C[運用コストの削減]
    A --> D[サービス品質の向上]
    A --> F[データ駆動型の意思決定]
    A --> G[イノベーションの促進]
```

## まとめ

Instana 大規模言語モデル（LLM）モニタリングは、LLMアプリケーションの開発から運用まで、幅広い課題に対処する統合的なツールです。開発効率の向上、リアルタイムの可視化、詳細な分析、コスト最適化、異常検知などの機能により、LLMアプリケーションのライフサイクル全体を効果的に改善できます。

次回は、具体的な設定方法や使用例を詳しく解説し、開発段階からの活用方法についても触れていきます。

https://qiita.com/daihiraoka/items/3f291202ec20b7ba41b4
SQLで指定したレコードを先頭に表示する方法

DBのデータを一覧表示している時に特定のレコードを一番上に持ってきたい時に使える方法です。

※使用環境はsql server management studioです。

まずは普通に一覧表示したデータが以下です。


```sql
SELECT TOP (1000) [部門ID]
      ,[部門名]
FROM [SampleDB].[dbo].[部門]
```

```sql
部門ID	部門名
1	営業部
2	総務部
3	人事部
4	製品開発部
5	品質保証部
6	情報システム部
7	経理部
```

<strong>そして以下の方法が表題のやり方です。</strong>


```sql
SELECT TOP (1000) [部門ID]
      ,[部門名]
FROM [SampleDB].[dbo].[部門]

ORDER BY
CASE 部門ID(←ここに先頭に持ってきたいカラムを指定) WHEN 5 (←ここに先頭に持ってきたいデータを指定) THEN 1 ELSE 2 END,
部門ID (ここで並び替えたい列を指定しないと表示が意図しないことになる)
```

<strong>以下のように指定したレコードが上に抽出されました。</strong>


```sql
部門ID	部門名
5	品質保証部
1	営業部
2	総務部
3	人事部
4	製品開発部
6	情報システム部
7	経理部
```

以上になります。誰かのお役に立てれば幸いです。
ここまでご覧頂きありがとうございました:relieved:


補足
Oracleでも出来ました。
二分探索 メモ

# 二分探索のメモ
```.py

def index(arr:list,value:int,exactry:bool=True,ceil:bool=False):
    #ソート済配列をもらって二分探索したうえでインデックスを返す関数。二分探索をします。
    #(必須)第1引数にソート済みの配列、第2引数に探したい値を入れる。
    #(任意,デフォルト)exatry=Trueでその値がドンピシャの時にのみインデックスを返す。なかった場合は-1を返す。
    #この時、値が複数個ある場合はceilルール通りにインデックスを返す。(ceil=Trueの時は一番右側を返し、ceil=Falseの時は一番左側を返す)
    #(任意)exatry=Falseでその値がなくてもceilのルール通りにインデックスを返す。
    #(任意,デフォルト)ceil=Falseでその値より小さい一番大きい値のインデックスを返す。
    #(任意)ceil=Trueでその値より大きい一番小さい値のインデックスを返す。
    left, right = 0, len(arr) - 1
    result = -1
    while left <= right:
        center = (left + right) // 2
        if arr[center] == value:
            result = center
            if ceil:
                left = center + 1  # 右側に同じ値がないかを確認
            else:
                right = center - 1  # 左側に同じ値がないかを確認
        elif arr[center] < value:
            left = center + 1
        else:
            right = center - 1
    if result != -1:
        return result
    if exactry:
        return -1
    if ceil:
        return right if 0 <= right else -1
    else:
        return left if left < len(arr) else -1

```
Webサイトのパフォーマンスを簡単に確認する方法

エンジニアのみなさま、日々の学習本当にお疲れ様です！
また本記事まで足を運んでいただき本当に感謝です。
約2分程度で読めるので最後まで読んでもらえると幸いです。

# タイトルに対する結論

https://developer.chrome.com/docs/lighthouse/overview?hl=ja

Chrome DevToolsの項目にある **「Lighthouse」** を活用しましょう。

# Lighthouseとは

ウェブページの品質向上に役立つよう開発されたオープンソースの自動化ツールです。任意のウェブページ、公開ページ、認証要求ページに対して実行できます。パフォーマンス、ユーザー補助、プログレッシブ ウェブアプリ、SEO などの監査を実施しています。

# デジタル庁のサイトを使って確認してみる

テキストだとイメージしづらいため、早速サイトを見ながら確認してみましょう。

https://www.digital.go.jp/

### 確認手順

#### 1. 対象サイトを開いた状態で「Chrome DevTools」を開く

```terminal:Macの場合
command + option + I
```

```terminal:Windowsの場合
Ctrl + Shift + I
```

![スクリーンショット 2024-07-07 16.49.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744730/2a5982dc-eb7c-07d2-1c28-926f5efc2870.png)

画面上に「Chrome DevTools」が表示されます


#### 2. 「Lighthouse」をクリックする

画面上部にタブがあります。「>>」をクリックすると表示されます。

![スクリーンショット 2024-07-07 16.51.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744730/4534f29b-0be3-e8fb-c735-093c8823a92b.png)


#### 3. [ページ読み込みを分析] をクリックする

![スクリーンショット 2024-07-07 16.55.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744730/cca4f65b-826a-8c72-df96-6807713de6a2.png)


デフォルトでは「モバイル」が選択されている状態ですが、今回は「デスクトップ」を選択してみましょう。

![スクリーンショット 2024-07-07 16.58.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744730/4caf7d0b-c7a7-1e8a-8162-7db622caa955.png)

そうすると対象サイトのパフォーマンスが数値化されます。簡単！
以下の5つの指標からパフォーマンスの数値結果を算出しているみたいです。


#### 指標① ： [First Contentful Paint（FCP）](https://developer.chrome.com/docs/lighthouse/performance/first-contentful-paint?hl=ja)
**重量：10%**

First Contentful Paint（FCP）は、ユーザーが最初にページ移動してから、ページのコンテンツの一部が画面に表示されるまでの時間を測定します。この指標の「コンテンツ」とは、テキスト、画像（背景画像を含む）、svg要素、白以外の canvas要素のことです。


#### 指標② ： [Largest Contentful Paint（LCP）](https://developer.chrome.com/docs/lighthouse/performance/lighthouse-largest-contentful-paint?hl=ja)
**重量：25%**

LCP はビューポート内の最大のコンテンツ要素が画面にレンダリングされるタイミングを測定します。これは、ページのメインコンテンツがユーザーに表示されるおおよそのタイミングです。


#### 指標③ ： [Total Blocking Time](https://developer.chrome.com/docs/lighthouse/performance/lighthouse-total-blocking-time?hl=ja)
**重量：30%**

TBT は、ページがユーザー入力（マウスクリック、画面のタップ、キーボードの押下など）に応答できない状態の合計時間を測定します。合計は、First Contentful Paint と操作可能になるまでの時間の間のすべての長いタスクのブロック部分を加算して計算されます。実行時間が50ミリ秒を超えるタスクは長時間のタスクです。50ミリ秒後の時間がブロッキング部分です。たとえば、Lighthouseで70ミリ秒のタスクが検出された場合、ブロッキング部分は20ミリ秒になります。


#### 指標④ ： [Cumulative Layout Shift（CLS）](https://web.dev/articles/cls?hl=ja)
**重量：25%**

CLSは、ページのライフサイクル全体を通じて発生する予期しないレイアウトシフトごとに、レイアウトシフトスコアのバーストの最大値を測定します。


#### 指標⑤ ： [Speed Index](https://developer.chrome.com/docs/lighthouse/performance/speed-index?hl=ja)
**重量：10%**

Speed Index は、ページの読み込み中にコンテンツが視覚的に表示される速度を測定します。Lighthouse では、まずブラウザでページが読み込まれている動画をキャプチャし、フレーム間の視覚的な進行状況を計算します。


# さいごに

フロントのパフォーマンスに関連する内容は、以下サイトに詳細が記載されています。
mdn web docsは神サイト！

https://developer.mozilla.org/ja/docs/Learn/Performance

# おまけ

また1つ勉強させていただきました。ありがとうございました。

そして唐突ですが弊社のご紹介もさせてください。

▼ コーポレートサイト

https://prum.jp/

▼ Wantedly求人

https://www.wantedly.com/projects/626662

弊社メンバーは学習した内容を日々Qiitaの記事にアウトプットしております。
弊社にご興味のある方、まずは求人を見てみてください！
ご応募お待ちしておりますー！
Arducam 64MPカメラをRaspberry Piで使用する方法 2 (プロパティファイルの追加)

## エラーについて
テスト撮影時に以下のエラーが発生しました。

```python:mushi.py
bash
vcgencmd get_camera
```
```python:mushi.py
[0:01:28.608259806] [1841]  WARN CameraSensorProperties camera_sensor_properties.cpp:261 No static properties available for 'arducam_64mp'
[0:01:28.608381682] [1841]  WARN CameraSensorProperties camera_sensor_properties.cpp:263 Please consider updating the camera sensor properties database
```
これらのエラーメッセージは、カメラセンサーのプロパティデータベースにArducam 64MPカメラの情報が不足しているために出るようです。
ただし、カメラの一部の機能が制限される可能性はあるものの、基本的な画像キャプチャには影響しないみたい（実際に撮影は可能）。

## 原因
### カメラセンサーのプロパティデータベースの不足:
libcameraはカメラセンサーのプロパティをデータベースから取得しますが、Arducam 64MPカメラに関する情報がこのデータベースに含まれていないため、警告が表示されている模様。

## 解決策
### 手動でプロパティファイルを作成する
GithubからDlできなかったので、以下のファイルを作成し、規定の位置に配置します。
以下は、arducam_64mp.jsonファイルの基本的な内容の例です。（ChatGPTが作成したもので）

```json:mushi.json
json
{
    "sensor": {
        "model": "arducam_64mp",
        "lens": {
            "model": "default",
            "position": 0
        },
        "properties": {
            "PixelArraySize": [9152, 6944],
            "CropFactor": 1.0,
            "UnitCellSize": [0.8, 0.8],
            "SensitivityRange": [100, 3200],
            "ColorFilterArrangement": "RGGB",
            "ActiveArea": [0, 0, 9152, 6944],
            "OutputSize": [9152, 6944]
        }
    }
}
```
### プロパティファイルの作成と配置
ファイルの作成:ターミナルで以下のコマンドを実行して、新しいファイルを作成します。
```python:mushi.py
bash
nano arducam_64mp.json
```
内容のコピー:上記のJSON内容をコピーし、nanoエディタに貼り付けます。

ファイルの保存:Ctrl + Xを押してファイルを保存し、Yキーを押して変更を確認し、Enterキーを押してnanoエディタを終了します。

ファイルの配置:作成したファイルを適切なディレクトリに配置します。
```python:mushi.py
bash
sudo cp arducam_64mp.json /usr/share/libcamera/camera-sensor-properties/
```
libcameraの再起動:プロパティファイルを配置した後、libcameraを再起動して変更を反映させます。
```python:mushi.py
bash
sudo systemctl restart libcamera
```

## まとめ
エラーが消えました。
【AWS】Cloud9からECS FargateにExecコマンドを使用する

# 手順

## 1. タスクロールを設定

- 次のポリシーをアタッチしたロールを作成し、タスク定義内のタスクロールに設定（マネジメントコンソール画面で実施）

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssmmessages:CreateControlChannel",
                "ssmmessages:CreateDataChannel",
                "ssmmessages:OpenControlChannel",
                "ssmmessages:OpenDataChannel"
            ],
            "Resource": "*"
        }
    ]
}
```

ロール名は `ExecRole` とした。タスク定義は以下のようになる：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/178de318-00f7-417b-289b-fc42fe8b7b66.png)


これを行わないと手順 2 で次のエラーが発生する。

```
An error occurred (InvalidParameterException) when calling the CreateService operation: The service couldn't be created because a valid taskRoleArn is not being used. Specify a valid task role in your task definition and try again.
```

## 2. サービスを作成

- 以下を cloud9 で実行

```shell
aws ecs create-service \
    --cluster cluster-name \
    --task-definition task-definition-name:revision \
    --enable-execute-command \
    --service-name service-name \
    --launch-type FARGATE \
    --network-configuration "awsvpcConfiguration={subnets=[subnet-xxxx, subnet-yyyy, subnet-zzzz],securityGroups=[sg-aaaa, sg-bbbb],assignPublicIp=ENABLED}" \
    --desired-count 1
```

## 3. SSM プラグインをインストール

- 以下を cloud9 で実行

```shell
sudo dnf install -y https://s3.amazonaws.com/session-manager-downloads/plugin/latest/linux_64bit/session-manager-plugin.rpm
```

## 4. Exec コマンド実行

- 以下を cloud9 で実行

```shell
aws ecs execute-command \
    --cluster cluster-name \
    --task task-id \
    --container container-name \
    --interactive \
    --command "/bin/sh"
```

# 参考記事

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-exec.html

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/install-plugin-linux.html
Jetpack Compose の基本のメモ#4 ~列と行を作成する~

### [6. 列と行を作成する](https://developer.android.com/codelabs/jetpack-compose-basics?hl=ja#5)
#### Composeの基本レイアウト要素
+ Compose には、基本の標準レイアウト要素として、Column、Row、Box という 3 つのコンポーザブルがある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1215907/00f59557-8f5f-469b-f001-30948dc473b8.png)
+ 内部にアイテムを配置できる
+ Column
    + 内包（ラップ）する要素を縦に配置する
+ Row
    + 内包（ラップ）する要素を横に配置する
+ Box
    + 内包（ラップ）する要素を重ねて配置する
    + デフォルトでは、後から追加された要素が手前に表示される

### Compose と Kotlin
+ 文字列のリストの型は`List<String>`と定義する
+ リスト自体は`ListOf("list1", "list2")`と記述する
+ Jetpack Composeのコンポーザブル関数の引数内で定義されるval変数は、引数名だけで定義できる
```Kotlin
fun MyApp(
    modifier: Modifier = Modifier,
    names: List<String> = listOf("World", "Compose")
) 

//どっちでも良い
fun MyApp(
    modifier: Modifier = Modifier,
    val names: List<String> = listOf("World", "Compose")
) 
```
TCP/IPの知見を深める ④　データリンク層　L2スイッチ編

はじめに
---
データリンク層においてネットワーク機器のして使われているのがL2スイッチ
スイッチが備えている機能について紹介していきます

L2スイッチング
---
イーサネットフレームの転送先を切り替える機能のことで通信の効率化を図っている
L2スイッチはイーサネットヘッダーに含まれている送信元MACアドレスと自分のポート番号を **MACアドレステーブル**で管理している

:::note info
MACアドレステーブルはメモリ上の表で管理されている
:::
とほほで分かりやすく説明されていました

https://wa3.i-3-i.info/word1803.html

こちらでも簡単に説明すると
pc1とpc2がありpc1のフレームを受け取ったL2スイッチはPC1のMACアドレスとポート番号をMACアドレステーブルに保存する
PC1とPC2以外にも複数のPCが接続されている場合、PC2がどこのポートに接続されているかをL2スイッチは知らないので**フラッディング**と呼ばれる行動を起こす

:::note info
フラッディング:どこのポートの宛先かがわからない場合、PC1以外のポートの全てのポートにフレームを投げてしまう動作の事
:::

コピーフレームを受け取ったPC2 は返信フレームを作成してケーブルに流す。
PC2 以外の端末は自分には関係ないフレームだと判断して破棄する

ケーブルから流れてきた返信フレームを受け取ったL2スイッチはPC2のポート番号が分かったので送信元MACアドレス（PC2のもの）と物理ポート番号をMACアドレステーブルに保存する

MACアドレステーブルに保存している行が削除されるまではフラッディングは行わずにPC1とPC2間で直接通信をおこなう。

VLAN
--
1台のL2スイッチを仮想的に複数に増やす技術を指す
VLANには番号が割り振られており（VLANID）、異なるIDが設定されているポートにはフレームが転送できないような仕組みになっている。



ポートベースVLAN
--
1つのポートに1つのVLANを登録する機能の事を指す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162351/22f5ddbe-6b70-bd90-5961-c12bd46c3d20.png)

上の画像のようにVLAN10にはポート1,3,4が接続されていて、VLAN20には2.5.6のポートが設定されている
この時、同じVLAN10に接続しているPC1,3,4同士はお互いのやり取りが可能ですが、VLANの違うPC1と2はやり取りができないようになっています。

タグVLAN
---
イーサネットフレームにVLANのタグをつけることでVLANの数に関係なく1ポート、1ケーブルで済むからめっちゃいいよねってハナシ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1162351/61c23ceb-46d7-de5e-6766-650b7cef1483.png)
UiPath Document Understandingで日本語の手書きに対応されている「UiPath 拡張言語 OCR」を軽く試して見た！

この記事はUiPathブログ発信チャレンジ2024サマーの7日目の記事です。

# はじめに
UiPath 拡張言語 OCR（UiPath Extended Languages OCR）がプレビューリリースされ、日本語の手書きにも対応されていると言うことで軽く試して見ました。尚、UiPath 拡張言語 OCRの利用メリットは、手書きサポートだけでなく、様々な言語（簡体字中国語、フランス語、ドイツ語、イタリア語、韓国語・・・など）に対応。つまり、色んな言語の帳票を扱う場合でも、気にすることなく、この1つのOCRだけ使えば良いと言うことです。サポートされている言語については、下記の公式ドキュメントをご覧ください！

https://docs.uipath.com/ja/document-understanding/automation-cloud/latest/classic-user-guide/ocr

# 手書きの帳票をUiPath Document Understandingで試した結果
手書き対応されていない従来の「OCR-日本語、中国語、韓国語」アクティビティ（CJK OCR）との比較で検証してみました。当然ながら帳票は画像に変換したものです。

## 1.手書き風に活字を変更して試す

**画像_職務経歴書山田太郎.png**
まずは、行書体で、文字のサイズを疎らに変更しながら手書き風にした活字の画像で比較しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/e1ddefad-f593-7f96-ae15-9e361ef5a0af.png)

**「OCR-日本語、中国語、韓国語」アクティビティを利用**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/af582231-47fc-fe2d-08d1-c2d7c8c3f050.png)


**「UiPath 拡張言語 OCR」アクティビティを利用**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/e6631f99-64f7-6cd8-6a31-779da79300ed.png)

両方とも、正しく読み取れています（笑）
さすがに標準的なフォントをベースに大きさを疎らに変えて手書き風にみせたとろろで、差はでない・・・活字に関しては、「OCR-日本語、中国語、韓国語」でも、そこそこ優秀です（笑）

## 2.氏名を手書にして試すw

**画像_職務経歴書山田太郎手書き.png**
ペイントブラシで氏名だけでも実際の手書にして試して見ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/be384f59-522d-69f5-51ef-233fd8ee46e3.png)

**「OCR-日本語、中国語、韓国語」アクティビティを利用**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/d8ebc5f6-f365-66da-23fd-f5ec665cc8f4.png)

**「UiPath 拡張言語 OCR」アクティビティを利用**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/c66059b4-26cd-6ab4-ba0e-3c0fd6d3b896.png)

氏名だけの変更でしたが、もうこれだけでも、その差は明らかです！
さすが、手書き対応と言うだけのことはありそうですね。

# UiPath Document Understanding ProcessにUiPath 拡張言語 OCR適用の仕方
下記のブログをベースに変更箇所を説明します。変更箇所は、「4. 日本語OCR対応」の部分のみです。

https://qiita.com/Jun96427231/items/0ab0c0c7d47b834714aa

## 1.ConfigにUiPath 拡張言語 OCRのエンドポイントを設定
「UiPath 拡張言語 OCR」は複数の言語がサポートされているので、エンドポイントを英語と日本語に分ける必要がないので、「OCR-日本語、中国語、韓国語」（CJK-OCR）で追加した「UiPathOcrEndpointCJK」は、もう不要です。「UiPathOcrEndpoint」に「UiPath 拡張言語 OCR」のエンドポイントを設定し、これだけを使うことにします。
|Name|Value|Description|
|:-----------|:-----------|:------------|
|UiPathOcrEndpoint|https://du.uipath.com/extended-ocr|UiPath 拡張言語 OCRのパブリックエンドポイント|

***「Settings」シート***
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/4feb6049-eec5-2e45-80c3-ea144bb12555.png)

## 2.「20_Digitize」（デジタル化）の変更
「ドキュメントのデジタル化」アクティビティのOCRを「UiPath 拡張言語 OCR」アクティビティに入れ替えて、各プロパティを下記の様に設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/639319/45157482-0891-0347-4d43-1110f2856d91.png)

以上です！簡単ですねw

# おわりに
本検証では、下記ブログの「生成AIによる分類と抽出をサポート」のテンプレートを用いて試しました。

https://qiita.com/Jun96427231/items/df69a914462087058c15

識字率の善し悪しは、生成AIがデータ抽出の際、ある程度影響を受けると考えてます。例えば、フォーム抽出の場合は、読取りエリアを定義しておけば、書いている内容関係なく抽出されますが、生成AIは、書いている内容を理解した上で、抽出してくるので識字率の悪く書いている内容が意味不明だと、おそらくデータ抽出に少なからず影響するのでは？と推測してます。

そう言う意味でも生成AIによる分類と抽出を使う場合は、識字率の高まった「UiPath 拡張言語 OCR」との組合せは、現時点のベストプラクティスと言えそうです。
Arducam 64MPカメラをRaspberry Piで使用する方法

Arducam 64MPカメラをRaspberryPi（Bullseye）で使用するための手順を紹介します。

# 前提条件
Raspberry Pi 4B (OS: Bullseye)
Arducam 64MPカメラモジュール
 (https://www.arducam.com/64mp-ultra-high-res-camera-raspberry-pi/)
カメラケーブル

# 手順 
## 1. Raspberry Piのセットアップ
### 1.1 Raspberry Pi OSのインストール
Raspberry Pi Imagerを使用して、最新のRaspberry Pi OSをSDカードに書き込みます。
SDカードをRaspberry Piに挿入し、起動します。

### 1.2 初期設定
ターミナルを開き、以下のコマンドを実行してraspi-configを起動します。
```python:mushi.py
bash
sudo raspi-config
```
「Interface Options」から「Legacy Camera」を有効にします。
設定を保存して、Raspberry Piを再起動します。
```python:mushi.py
bash
sudo reboot
```
## 2. カメラの接続
カメラケーブルをRaspberry PiのCSIポートに接続します。ケーブルの銀色の接点がHDMIポート側を向いていることを確認してください。
カメラモジュールの接続部分も確認し、しっかりと差し込まれていることを確認します。

## 3. ソフトウェアのインストール
### 3.1 必要なパッケージのインストール
以下のコマンドを実行して、必要なパッケージをインストールします。
```python:mushi.py
bash
wget -O install_pivariety_pkgs.sh https://github.com/ArduCAM/Arducam-Pivariety-V4L2-Driver/releases/download/install_script/install_pivariety_pkgs.sh
chmod +x install_pivariety_pkgs.sh
./install_pivariety_pkgs.sh -p libcamera_dev
./install_pivariety_pkgs.sh -p libcamera_apps
./install_pivariety_pkgs.sh -p 64mp_pi_hawk_eye_kernel_driver
```
### 3.2 設定ファイルの編集
/boot/config.txtファイルを編集し、以下の行を追加します。
```python:mushi.py
bash
sudo nano /boot/config.txt
```
以下の行を追加または編集します。
```python:mushi.py
bash
dtoverlay=vc4-kms-v3d,cma-1024
dtoverlay=arducam-64mp
gpu_mem=256
camera_auto_detect=0
```
ファイルを保存して終了し、Raspberry Piを再起動します。
```python:mushi.py
bash
sudo reboot
```
## 4. カメラの確認
再起動後、カメラが正しく認識されているかを確認します。
```python:mushi.py
bash
vcgencmd get_camera
```
このコマンドがsupported=1 detected=1と表示されれば、カメラが正しく認識されています。
## 5. 画像のキャプチャ
カメラが正しく認識されている場合、以下のコマンドを使用して画像をキャプチャします。
```python:mushi.py
bash
libcamera-still -o test.jpg
```


### まとめ
高画質な画像の撮影が、AFにて可能になりました。
撮影画像の詳細な設定は別の機会に。
![test.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3677892/898174f5-41cd-497d-e68c-88f1d1191160.jpeg)

ひとつ、エラーがあったので別の記事にまとめます。
https://qiita.com/mushipi/items/0ef07a29ec7090fc73dc
ARK AscendedのサーバーをLinuxで建てる

ASAのサーバーがLinuxにネイティブ対応しておらず、proton経由で実行する必要があったので備忘録として。
ポート開放やsteamcmdの前提などは省いているので、他のサーバー構築記事と合わせて参考にしてください。

# Protonのインストール
## 必要なディレクトリ作成
ダウンロード先のディレクトリを作成しておきます。ここではopt配下に配置します。
（こういうときどこのディレクトリ使うのが正解かよくわかってない）
```sh
sudo mkdir -p /opt/proton-ge
sudo mkdir -p /opt/proton-ge/compatdata
```
## Proton-GEのダウンロード
Proton-GEをGitHubからダウンロードし、上で作成したフォルダに移動します。
URLは以下で、最新版をDLしとけばいいと思います。
https://github.com/GloriousEggroll/proton-ge-custom
```sh
cd /opt/proton-ge
cd /opt/proton-ge
sudo wget https://github.com/GloriousEggroll/proton-ge-custom/releases/download/GE-Proton9-9/GE-Proton9-9.tar.gz
sudo tar -xvf GE-Proton9-9.tar.gz
sudo mv GE-Proton9-9 proton
```

## サーバーインストール
steamcmdでサーバーをインストールします。
他に紹介されている記事ではidが「376030」になっていることが多いですが、Ascendedの場合は以下の「2430930」です。
```sh
steamcmd +force_install_dir /opt/Steam/ark_servival_ascended/ +login anonymous +app_update 2430930 +quit
```

## サーバー実行スクリプト作成
インストール先のディレクトリに以下のスクリプトを作成します。
STEAM_COMPAT_CLIENT_INSTALL_PATHは、名称の通りsteamをインストールしたディレクトリを指定します。
基本user化の.steamになると思います。
実行コマンドはprotonでWindows用のexeを指定しています。
```sh
#! /bin/bash
STEAM_COMPAT_CLIENT_INSTALL_PATH="/home/<user>/.steam" \
STEAM_COMPAT_DATA_PATH="/opt/proton-ge/compatdata" \
/opt/proton-ge/proton/proton run ./ShooterGame/Binaries/Win64/ArkAscendedServer.exe TheIsland_WP?listen?SessionName=<サーバー名>?ServerPassword=<パスワード>?ServerAdminPassword=<Adminパスワード>?Port=7777?QueryPort=27015 -server -log
```

## スクリプト実行
作成したスクリプトを実行するとサーバーコンソールが起動してアクセスできるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551355/702b3178-76c9-357f-15e0-92442468c83b.png)
単体テストコード MySQLのエラー解消

モデル単体テストコードを実装している最中に
`MySQL client is not connected`というエラーが発生した場合の対処方法は↓
config/environments/test.rbというファイルに以下の記述を追記しましょう。

```
Rails.application.configure do

 #省略

 config.active_job.queue_adapter = :inline #追記

 #省略
```
## Active Jobのキューアダプタ設定
これはRailsのバックグラウドジョブフレームワークです。
デフォルトのジョブは非同期で行われるが`:inline`に設定する事でジョブは非同期ではなく、同期的に実行されます。
## ジョブの実行タイミング
`inline`に設定する事でジョブが即座に実行されるよになります。これはテスト環境で特に有効的です。
理由はテスト中にバックグラウンドでジョブが実行されるのを待つ必要がなくなり、テストの実行がより予測可能になるからです。
## テスト解消の理由
テスト環境で非同期ジョブを使用すると、ジョブが非同期に実行されるため、データベースへの変更が期待通りに反映されないことがあるためです。
`inline`に設定する事で、ジョブが同期的に実行されるため、データベースの状態がテストの進行と同期され、エラーが発生しにくくなります。
## まとめ

これらを設定することで、テスト環境でのジョブが即座に実行されるようになり、データベースの状態がテストの進行と同期されるため、外部キー制約違反やデータの整合性に関するエラーを防ぐことができます。この設定は、特にテスト環境でのデータの整合性を保つために有用です。
Ubuntu 起動後に黒画面で操作できなくなる、をGRUBメニューからの操作で対策

# 問題状況
Ubuntu Live USB で起動したが、画面が真っ黒になり、 Ctrl Alt F1 などでも効かない状態になる。
これを、 GRUB のコマンド行を変更して対応した。

# nomodeset にする
GRUB メニューで行を選んだあと、コマンドラインの編集状態にする。方法は画面に出ているが、一例では Tab を押す。あるいは e を押す。
xforcevesa がある行について編集状態にし、 xforcevesa を nomodeset に書き換え、そのコマンド行で起動。
この方法だと、普通っぽく GUI が起動て操作可能になった。

# runlevel 3 にする

```live-media-path=/casper```
のような文字列の後にある部分を、 3 だけ、に書き換える。
コマンドの末尾は
```live-media-path=/casper 3```
となる。

# 関連リンク
まず以下を見ましょう。

https://vinelinux.org/docs/vine6/cui-guide/edit-boot-option-on-grub.html

https://qiita.com/ikwzm/items/5514b0fe9a8728e8aecb