OmniAICreator/Qiita-1.07M huggingface dataset:
ミニpcにUbuntu Serverをクリーンインストールして詰まった

## はじめに
先日ミニPCを購入しUbuntu Server 24.04 LTSをクリーンインストールしようとしたところエラーが発生して詰まったため、備忘録もかねて記事にしてみます。似たようなエラーに悩まされている人がいらっしゃれば、お力になれれば嬉しいです。
初めて記事を書くため色々と拙いところがあるかと思いますが、お付き合いくださいますと幸いです。

## 概要
先日Amazon Prime Dayで安くなっていたミニPCを購入し、Ubuntu Server 24.04 LTSをUSBメモリからクリーンインストールしていました。
しかしgrub-installを行っている途中にエラーが発生し、そこから進めなくなりました。
grubはUbuntuの標準ブートローダですので、もしかしたらgrubを標準のブートローダとしている他のディストリビューションでも同じエラーが発生するかもしれません。

## ミニPC
エラーの発生したミニPCはこちらです。
<dl>
    <dt>GMKTec M5</dt>
    <dd>CPU:AMD Ryzen7 5700U</dd>
    <dd>RAM:16GB</dd>
    <dd>SSD:512GB</dd>
</dl>

https://www.amazon.co.jp/gp/product/B0CCSLMGM1/ref=ppx_yo_dt_b_asin_title_o00_s00

余談ですが、WindowsライセンスはOEMでした。
中華系メーカーはVLライセンスが多いという話を聞いていたため、Ubuntu Serverを入れなおすのを少し躊躇しました。

## 発生したエラー
grub-install中に、以下のようなエラーが発生しました。
```
(略)
finish:cmd-install/stage-curthooks/builtin/cmd-curthooks/install-grub: FAIL: installing grub to target devices
finish:cmd-install/stage-curthooks/builtin/cmd-curthooks/install-grub: FAIL: configuration target system boot loader
finish:cmd-install/stage-curthooks/builtin/cmd-curthooks/install-grub: FAIL: curtin command curthooks
Traceback (most recent call last):
(中略)
File '/snap/subiquity/5741/lib/python3.10/site-packages/curtin/util.py',line 172, in _subp curtin.util.ProcessExecutionError: Unexpected error while running command.
Command: ['unshare', '--fork', '--pid', '--mount-proc=/target/proc', '--', 'chroot', '/target', 'efibootmgr', '-v']
Exit code: 2
Reason: -
Stdout: ''
Stderr: EFI variables are not supported on this system.
       error trace:

Unexpected error while running command.
Command: ['unshare', '--fork', '--pid', '--mount-proc=/target/proc', '--', 'chroot', '/target', 'efibootmgr', '-v']
Exit code: 2
Reason: -
Stdout: ''
Stderr: EFI variables are not supported on this system.
```
`このシステムでEFI変数がサポートされていない`という内容のエラーが吐かれていました。
ここで一度自分の検索能力の限界を感じchatgptに相談したのですが、「CSMの有効化」や「Legacyモードでの起動」といったミニPCのUEFIファームウェアがサポートしていない機能の話しかされなかったため、かなり絶望しました。

## 解決
そんな中ふとRedditを覗いたところ、一筋の光が！

https://www.reddit.com/r/MiniPCs/comments/1altohl/cant_install_any_linux_distro_on_new_gmktec_m5/

>I had the same problem on mine.
>I got it to work by setting "NX Mode" to enabled in Advanced > CPU Configuration

なんとUEFIファームウェアの`Advanced`中にある`CPU Configuration`から、`NX Mode`を`Enable`に設定したらインストールに成功するというのです。
2日半も悩んだエラーがこんなひと手間で解決するものかと半信半疑で設定を行ってみたところ、実際にインストールすることが出来ました。(画像等のエビデンスはありません)

これは私の推測ですが、`NX MODE`はメモリ領域に実行不可能なエリアを作る設定であるため、有効化していなければOSのセキュリティ要件を満たさず弾かれてしまうのかもしれません。

## おわりに
ここまで読んでいただきありがとうございました！
初めての記事執筆でかなり拙い記事となってしまった気がしますが、似たような悩みを持っている方の助けになれたなら幸いです。
[JavaScript] クラス、コンストラクタ、プロパティ、メソッドについて

# まとめ

#### クラスとは
> クラスはオブジェクトを作成するためのテンプレートです。処理するためのコードでデータをカプセル化します。
※[mdn web docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes)

#### コンストラクタとは 
> クラスで作成したオブジェクトを作成して初期化するための特別なメソッドです。 "constructor" という名前の特別なメソッドは、クラスに 1 つしか定義できません。クラスに複数の constructor メソッドが存在した場合、SyntaxError が発生します。
※[mdn web docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes)

#### メソッドとは
> メソッドはクラスごとにプロトタイプに定義され、すべてのインスタンスで共有されます。メソッドには、プレーン関数、非同期関数、ジェネレーター関数、非同期ジェネレーター関数があります
※[mdn web docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes)

# 目次
- [クラスとは](#クラスとは)
- [コンストラクタとは](#コンストラクタとは)
- [プロパティとは](#プロパティとは)
- [メソッドとは](#メソッドとは)

# 使用するコード
~~~js
//クラス
class Person {
//コンストラクタ（特別なメソッド）
  constructor(name, age) {
//プロパティ
    this.name = name;
    this.age = age;
  }
//メソッド
  greet() {
    console.log('Hello, ' + this.name);
  }
}

//クラスを用いたインスタンスの生成
const john = new Person('John', 30);

// インスタンスのメソッドの呼び出し
john.greet(); // 出力: Hello, John
~~~

# クラスとは
- オブジェクトを生成するための設計図（テンプレート）です。クラスにはプロパティとメソッドを定義することができ、そのクラスから生成されたオブジェクトはそれらのプロパティとメソッドを継承します。

~~~js:クラス
class Person {
  // クラスの中身（プロパティとメソッド）を定義
}
~~~

#### 解説
- `Person`という名前のクラスを定義しています。このクラスは、人の情報を表現するためのプロパティとメソッドを持ちます。

# コンストラクタとは
- クラスから新しいインスタンス（オブジェクト）が生成されるときに呼び出される特別なメソッドです。コンストラクタを使って、インスタンスの初期化を行います。

~~~js:コンストラクタ
constructor(name, age) {
  this.name = name;
  this.age = age;
}
~~~

#### 解説
- `constructor`は、クラスのインスタンスが作成されるときに実行される特別なメソッド（コンストラクタ）です。
- `name`と`age`はコンストラクタの引数で、新しいインスタンスの`name`と`age`プロパティを初期化するために使われます。
- `this.name = name`によって、クラスのインスタンスの`name`プロパティが初期化されます。同様に、`this.age = age`によって`age`プロパティが初期化されます。

# プロパティとは
クラスのインスタンスが持つデータや属性を表します。プロパティは、コンストラクタ内で初期化され、クラスのインスタンスによって保持されます。

~~~js:プロパティ
  this.name = name;
  this.age = age;
~~~

#### 解説
- `name`と`age`は`Person`クラスのプロパティです。
- これらのプロパティは、クラスのインスタンスごとに異なる値を持つことができます。

# メソッドとは
- クラスやオブジェクトに関連付けられた関数です。メソッドはクラスのインスタンスによって呼び出され、インスタンスのプロパティにアクセスしたり、操作を行ったりします。

~~~js:メソッド
greet() {
  console.log('Hello, ' + this.name);
}
~~~

#### 解説
- `greet`は`Person`クラスのメソッドです。
- このメソッドは`this.name`プロパティを使用して、挨拶のメッセージをコンソールに表示します。

# 活用例1
`Person`クラスを使ってインスタンスを生成し、そのインスタンスのメソッドを呼び出します。

~~~
const john = new Person('John', 30);

john.greet(); // 出力: Hello, John
~~~

#### 解説
- `const john = new Person('John', 30)`は`Person`クラスの新しいインスタンスを生成します。このとき、`constructor`メソッドが呼び出され`name`と`age`が設定されます。
- `john`は`Person`クラスのインスタンスです。`john`インスタンスには`name`プロパティとして`John`、`age`プロパティとして`30`が設定されています。
- `john.greet()`は`john`インスタンスの`greet`メソッドを呼び出します。このメソッドは、`Hello, John`というメッセージをコンソールに出力します。

# 参考リンク
- [クラス](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes)
- [オブジェクトとインスタンスって何が違うの？という初心者プログラマー向けの図解](https://nakazawakan.com/object-instance/)
- [【JavaScript入門】コンストラクタの使い方(new/prototype/overload)](https://www.sejuku.net/blog/25328)
Python の import 時にでた [ ImportError: attempted relative import with no known parent package ]  の解決策

## はじめに
importしようとしたところ、ImportError: attempted relative import with no known parent packageのエラーがでて、意外な方法で解決できたので紹介


## 今回起きた現象

```
project/
  │
  ├─ a_package/
  │       ├─ A.py
  │
  ├─ b_package/
          ├─ B.py
```
上記のディレクトリ構造の時、A.pyからB.pyのクラスをimportしたかった。

相対パスでimportしようとすると下記のようになります。
```python
# A.py

from ..b_package.B import B_class
```
**しかし... こんなエラーがでてしまう...**
```
ImportError: attempted relative import with no known parent package
```


## 解決策
```python
import os
import sys
sys.path.append(os.getcwd())

from b_package.B import B_class
```
これでimportできました。

<br>

## これで動く理由
**sys.path**には、Pythonインタプリタがモジュールを検索するディレクトリのパスが格納されています。
そこに、projectのディレクトリを追加(append)することによって、import時に、project直下も検索するようになってくれる。

という理屈だと思います...多分...
Ruby: any?メソッドについて

補足 2024 07/19
@scivolaさんよりご指摘いただいた内容を反映

## 読んで欲しい人

- any?メソッドがわからん人
- 過去の俺

## 動作環境

- ruby 3.3.0

## any?メソッドとは

- 配列やハッシュなどのコレクションに対して使用する
- ~~要素内に1つでもtrueを見つければtrueを返す。全ての要素がfalseならfalseを返す~~
- 1 つでも真な要素があれば true を返す。全ての要素が偽なら false を返す

```ruby
[nil, false, nil, false, true].any?
=> true
```

- ブロックで条件を指定できる

```ruby
[1, 2, 3].any? { |v| v > 3 }
=> false
```

*追記: 2024/07/19*
- 全ての要素が偽というのは、要素がない場合にも成り立つ

```ruby
[].any?
=> false
```

## なんで配列、ハッシュの要素1つ1つをチェックできるのか？

`any?`はEnumerableモジュールが提供しているメソッドの1つだから

### Enumerableモジュールとは

コレクションに対して繰り返し操作を行うためのメソッドを集めたモジュール

このEnumerableモジュールを読み込ませる（include）させることで、通常は繰り返し操作ができないようなクラスでも、繰り返し操作を行えるようになります。

**Enumerableモジュールが提供している他のメソッド**

- ~~each~~
- select
- map
- find
- count

などなど


*追記: 2024/07/19*
Enumerableモジュールはeachメソッドを提供していません。
eachメソッドを利用して上記のメソッドを定義しているというのが正しいです。


## any?の注意点

**指定したコレクションの全ての要素を確認するわけではない**
- any?は見つけた最初の要素がtrueなのかfalseなのかを判断するメソッドである


**戻り値はtrueかfalseであり、最初に見つけた要素ではない**
- 私は間違えて、trueの最初の要素が戻ると勘違いしてました。


## 感想、学び

- Enumerableモジュールという便利な仕組みがあることを知れた
- メソッドの使い時を知れた気がする

## 参考

https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/any=3f.html

https://docs.ruby-lang.org/ja/latest/class/Enumerable.html
テスト観点備忘録

# はじめに
:warning: ：当記事に示された意見はわたし個人のものであり、所属する組織を代表するものではありません。

# 概要
テストの観点について考えることが業務上あったので備忘録も兼ね記載する。
また他にもまとめている方がいたのでこちらのリンクも併せて記載。
大変参考になりました。
- [テスト観点一覧](https://qiita.com/nittannittan/items/2d8a342a8d77db53b70a)

とはいえ人が書いてくれたリンクを張るだけだと記事として成り立たないので自分なりにテストについて考えてみる。
テストケースを起こすときなんかに見返すことのできる資料にしたい（願望）


## テストとは 
今更言うまでもないとは思うのだが誰が目を通すのかわからないので、テストとはから少し考えてみる。
「テスト」とシステム開発・修正などを行った際に、仕様（要求）通りできているかまたバグはないか？の確認をするものである。

<details><summary>テストフェーズはこちら</summary>

#### 1. 単体テスト（Unit Testing）
目的: 個々の関数やメソッドなど、プログラムの最小単位をテストする。
対象: 関数、メソッド、クラス。
ツール: JUnit（Java）、PyTest（Python）、NUnit（.NET）など。

#### 2. 結合テスト（Integration Testing）
目的: 複数の単体が正しく連携して動作することを確認する。
対象: モジュール間のインターフェースやデータフロー。
ツール: TestNG、JUnit、PyTestなど。

#### 3. システムテスト（System Testing）
目的: システム全体が設計どおりに機能することを確認する。
対象: 完成したシステム。
ツール: Selenium、Appium、LoadRunnerなど。

#### 4. 受け入れテスト（Acceptance Testing）
目的: システムがユーザーの要求や業務要件を満たしているかを確認する。
対象: ユーザーシナリオ、ビジネス要件。
ツール: Cucumber、FitNesse、Robot Frameworkなど。

#### 5. 回帰テスト（Regression Testing）
目的: 新しい変更が既存の機能に影響を与えていないことを確認する。
対象: 変更が加えられた部分とその周辺。
ツール: Selenium、JUnit、PyTestなど。

#### 6. パフォーマンステスト（Performance Testing）
目的: システムの速度、スケーラビリティ、安定性を確認する。
対象: 応答時間、スループット、リソース使用率。
ツール: JMeter、LoadRunner、Gatlingなど。

#### 7. セキュリティテスト（Security Testing）
目的: システムのセキュリティ脆弱性を特定し、悪意のある攻撃から保護する。
対象: 認証、認可、データ保護。
ツール: OWASP ZAP、Burp Suite、Nessusなど。

#### 8. ユーザビリティテスト（Usability Testing）
目的: ユーザーインターフェースが使いやすいかどうかを確認する。
対象: ユーザーインターフェース全般。
ツール: ヒューリスティック評価、ユーザーテスト、A/Bテスト。

#### 9. コンフィグレーションテスト（Configuration Testing）
目的: ソフトウェアがさまざまな環境で正しく動作することを確認する。
対象: オペレーティングシステム、ブラウザ、ハードウェア構成。
ツール: VirtualBox、Docker、Selenium Gridなど。

#### 10. インターフェイステスト（Interface Testing）
目的: システムのインターフェースが正しく動作することを確認する。
対象: API、GUI、通信プロトコル。
ツール: Postman、SoapUI、REST Assuredなど。

</details>

んで、基本的な考え方は「`入力値`が`処理を介した結果`、`どうなった？`」で考えられると思う。
イメージは以下の通り
```mermaid
flowchart LR
入力 --> 処理 --> 結果 
```

んで、例えば入力Aに対して＋5した結果を返すプログラムがあるとしよう
```java
public class MathUtils {

    public static int addFive(int a) {
        return a + 5;
    }
}

```
※構造上問題だらけではあるけど（入力の方法だったり例外処理がなかったりツッコミどころはあるかもしれないけど）そこはいったん置いときます。

で今回のプログラムに対してテストケースを考えるわけです。
ケースとはどのような入力と期待する結果かを列挙するわけです。「`入力値`が`処理を介した結果`、`どうなった？`」の`入力値`と`どうなった？`の部分

入力値の例(一部)
- 数値
- 文字
- 空文字
- Null

次に入力に対する結果（期待値）を考えます。
- 数値を入力したとき結果は？
- 文字を入力したとき結果は？
- 空文字を入力したとき結果は？
- Nullを入力したとき結果は？

数値にフォーカスして話をすると入力Aを仮に3としましょう。プログラムを介した場合入力と期待値は以下のようになります。
- 入力値:3
- 期待値:8

他にもあるけど全部やったらきりがないのでここまでとします。
ここまでテストに関する基本的な考え方です。


## テスト観点 
だらだらと語ってきたけどではどのようなことを考慮すべきか？
もちろん修正や開発内容などによってはケースバイケースではあるけど、
大事な点はいくつかあるがその中でも「漏れなく被りなく」を意識することが大切。
テストケースの漏れ＝テスト未実施だからね
未実施は品質を上げるためにもなくすべき！

---
ケースを作成する際は、[先人の知恵](https://qiita.com/nittannittan/items/2d8a342a8d77db53b70a) をベースに自分のおこないたいケースに当てはめて考える。
自分の修正が入力系なら空文字やNullのケースはやらなきゃね！とかScript入れたらどうなるの？とか検証した方がいい気がする

---

あと発生しないことの証明は（エビデンスに）しずらい。

現場によっては動画でのエビデンスがOKの場合では動画を回し発生していないことを一連の流れで証明できるが、画像だけでは正直判断できないと思う（過去に画像でエビデンスとしたけど正直無意味だと思う！テストはちゃんとしたけど）

なのでテストケースとして作成する場合は「XXが発生しないこと」よりも「XXが表示されること」など誰もがそのエビデンスを見たときに確認しやすい内容で記載した方がテスト実施者や、確認者の視点からみても証明しやすいと思う。



---


ずらずら書いたけどまた思いついたら記載しますでは！
Local SEO with digimattesolutions:


DigiMatte Solutions focuses on improving local market performance through customized Local SEO  strategies. By optimizing your Google My Business profile, integrating location-specific keywords, and building local backlinks, they enhance your visibility among nearby customers. This approach not only drives foot traffic to physical locations but also boosts credibility within the community. Specializing in local SEO services for small businesses, they provide ongoing performance tracking and adjustments to ensure sustained local market dominance.
https://digimattesolutions.com/
【備忘録】SQLAlchemy でMySQLにSSL接続できなくて苦労した話

# 1. プロローグ
Dockerコンテナ上で稼働するPythonアプリから、異なるDockerコンテナで稼働するMySQLへのSSL接続が2日かけてやっと成功したので、苦労を忘れぬうちに作業記録を残す。  
# 2. 環境
**アプリケーションコンテナ**
・python3.12
・flask3.0.3
・flask-sqlalchemy3.1.1
・ymysql1.1.1
・cryptography42.0.8
**ＤＢコンテナ**
・mysql9.0.0

# 3. サーバ証明書/クライアント証明書
○ opensslを使用して作成 
● MySQLが自動作成
上記の両方を試したが、最終的にMySQLが生成した証明書を利用することにした。

# 4. MySQLの起動
my.cnf に証明書をの所在を追加することでSSL接続が可能となる。  
```my.cnf
[mysqld]
ssl-ca=/var/lib/mysql/ca.pem
ssl-cert=/var/lib/mysql/server-cert.pem
ssl-key=/var/lib/mysql/server-key.pem
```
MySQLを立ち上げた際、/var/lib/mysql/配下に サーバ証明書、クライアント証明書等を作成し、置いてくれる。

# 5. MySQLにSSL接続用のユーザ追加
rootユーザは管理用とし、クライアントからSSL接続するユーザを追加する。
```shell
mysql -u ${DB_USER} -p${DB_PASSWORD} <<-END
    CREATE DATABASE ${DATABASE};
    CREATE USER '${CLIENT_USER}' IDENTIFIED BY '${CLIENT_PW}' REQUIRE SSL;
    GRANT ALL ON ${DATABASE}.* TO '${CLIENT_USER}';
END
```
# 6. SQLAlchemy MySQL接続定義
```conf.py
class DevelopmentConfig:

    # SQLAlchemy
    SQLALCHEMY_DATABASE_URI = \
      'mysql+pymysql://{user}:{password}@{host}/{database}' \
      '?charset=utf8&ssl_ca={ca}&ssl_cert={cert}&ssl_key={key}&ssl_check_hostname=false'.format(
        **{
          'user': os.getenv('CLIENT_USER'),
          'password': os.getenv('CLIENT_PW'),
          'database': os.getenv('DATABASE'),
          'host': os.getenv('HOST'),
          'ca': os.getenv('CA_CERT'),
          'cert': os.getenv('CLIENT_CERT'),
          'key': os.getenv('CLIENT_KEY'),
        })
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SQLALCHEMY_ECHO = False
    PROPAGATE_EXCEPTIONS = True


Config = DevelopmentConfig
```
※ 環境変数 CA_CERT, CLIENT_CERT, CLIENT_KEY には、MySQLが自動生成したもののパスを指定している。

# 7. 何が苦労したか・・・
実装当初、SQLAlchemy接続定義に ssl_check_hostname=false を指定していなかった。そのため、HOST名指定だと、
```
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'dbms' ([SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: Hostname mismatch, certificate is not valid for 'dbms'. (_ssl.c:1000))")
```
IPアドレス指定にしても
```
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'xxx.xxx.xxx.xxx' ([SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for 'xxx.xxx.xxx.xxx'. (_ssl.c:1000))")
```
のエラーになる。  
SQLAlchemyマニュアルを確り確認していなかったのが大きな過ちで、マニュアル（https://docs.sqlalchemy.org/en/20/dialects/mysql.html#pymysql-ssl ）には「ホスト名と一致しない自動生成された自己証明書を使用する場合はssl_check_hostname=falseを指定しろ」と確りと書いてあった。

# 8. エピローグ
ネット上にはいろんなサンプルが転がっており、そのままコピペである程度は動いてしまう。【教訓】うまくいかないときはサンプルコードを漁るのではなく今一度マニュアルに目を通そう。
TypeScript：レスト構文とスプレッド構文 (...) の違い

webアプリ作成中、コンポーネントに`{...カスタムフック(Url)}` と記述されているのを見て展開しているのかわからなかったので、「レスト構文」と「スプレッド構文」の違いについて調べました。

## レスト構文(残余引数)
スプレット演算子の `...` を使用します。
オブジェクトや配列など、 **残りの要素をまとめて変数に格納します。**

```javascript
function sum(...numbers: number[]) {
    return numbers.reduce((a, b) => a + b, 0);
}
console.log(sum(1, 2, 3, 4)); // 10

const [first, ...rest] = [1, 2, 3, 4];
console.log(first); // 1
console.log(rest);  // [2, 3, 4]
```

### 文法的位置
関数定義、配列やオブジェクトの分割代入で使用され、**パラメータリストや分割代入の最後に配置されます。** 複数の要素を1つの構造にまとめるものです（多 → 1）

## スプレッド構文
既存の配列やオブジェクトの中身を展開します。
```javascript
function sum(x: number, y: number, z: number) {
    return x + y + z;
}

// タプル型
const arr1: [number, number, number] = [1, 2, 3];
console.log(sum(...arr1));  // 6

// または、as constアサーションを使用
const arr2 = [1, 2, 3] as const;
console.log(sum(...arr2));  // 6
```
### 文法的位置
通常、式の中で記述され、関数呼び出し、配列リテラル、オブジェクトリテラルで使用されます。1つの構造を複数の要素に展開するものです （1 → 多）

### 余談
スプレッド構文の例で `タプル型` `as const` を使用しているのは、sum関数は正確に3つの `number型引数`を期待しているからです。

通常の配列型 `（number[]）` は長さが可変であるため、関数が期待する引数の数と一致する保証がないのです。以下だとエラーが出ます。
```typescript
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]

function sum(x: number, y: number, z: number) {
    return x + y + z;
}
console.log(sum(...arr1)); // error
```
長くなるので省きますが、他にもパターンがあり、詳しくは以下がわかりやすかったです。

https://qiita.com/daishiman/items/e0d9e2e16382231f6200


## まとめ
スプレッド構文は「展開」、レスト構文は「集約」と覚えておけば、文脈から見分けることができそうです。
ほぼ未経験からの基本情報技術者試験最短合格への道（科目A）

## はじめに

こんにちは、ゆうです。この記事では、私の経験をもとに、基本情報技術者試験（科目A）に関して最も効率的だと考える勉強法を共有したいと思います。なお試験概要等については省略しています。

## 筆者について
理系大学院生（非情報系）
研究等でプログラミングを多少用いるが、ITに関する知識はほとんどなし（ITパスポート未所持）
1ヶ月程の勉強を行い、2024年7月に試験を受け合格

## 勉強方針について
基本情報技術者の勉強方法について調べると、過去問を解くところから始めている方が多くいらっしゃいますが、ITに関する知識が少ない方にとっていきなり過去問を解くのは中々ハードだと感じました。そこで参考書を用いて1から知識を身につけながら、最も効率的に合格に近づくための方法を考えた結果が以下の方法になります。

## 使用した教材

####  参考書：かやのき先生の基本情報技術者教室　
説明がわかりやすく、十分な確認問題も用意されています。

<img width="300" alt="スクリーンショット 2024-07-18 18.14.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3765911/d74f99a0-f6ef-bc27-9ba6-f3982388dec8.png">




#### オンライン教材：基本情報技術者試験ドットコム(https://www.fe-siken.com/)
追加の問題演習ではこちらを利用します。

##### 2つともど定番ですが、やはりこの2つをしっかりと行うことが合格への最短経路だと考えます。

## 勉強方法

基本情報技術者は内容の難易がはっきりと分かれていると考えます。最短合格に向けて、簡単な部分の勉強の比重を軽く、難しい部分（計算問題など）の対策をしっかりと行うことが重要となります。そこで確認問題を上手く利用しながら学習を進めていきます。

### 1周目
参考書を問題を解かずに軽く流し読み。

### 2周目
1周目よりもしっかりと読みつつ、確認問題も解く。間違えた問題にはしっかりとチェックを入れ、その箇所の復習を合わせて行う。

### 3周目~
前の周で間違えた問題のみを解き、間違えた箇所について再度復習。

### 全ての問題が解けるようになったら
基本情報技術者試験ドットコムの過去問を最新年度分から1年分通しで解き、間違えた問題に関しては参考書を用いて復習を実施。

大体過去問で8割を取れるレベルになれば本番で落ちることはないと思われます。

## 筆者の結果について
1周目:30時間、2周目：40時間、3周目以降：20時間の合計90時間程で科目A 730/1000点を取得することができました。未経験にしては短い時間でとれたのではないかと考えています。
![スクリーンショット 2024-07-18 18.15.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3765911/d25a7ea9-a7c2-5a3b-ac8e-35224217afbc.png)


## まとめ


最後まで読んでいただき、ありがとうございます。この記事が皆さんの合格の助けになれば幸いです。頑張ってください！
NodeでURLからCSVデータ取得してみた

いちいち更新されるたびにファイルをダウンロードしてきて...って、すごくめんどくさいので、CSVぐらいURLから取得できないかなあ...

ということで、nodeでCSVをURLから取得できるプログラムを作ってみた。

```js:urlcsv.js
export class URLCSV {
  async * #makeTextFileLineIterator(fileURL, charCode) {
    const utf8Decoder = new TextDecoder(charCode);
    const response = await fetch(fileURL);
    const reader = response.body.getReader();
    let { value: chunk, done: readerDone } = await reader.read();
    chunk = chunk ? utf8Decoder.decode(chunk) : "";

    const newline = /\r?\n/gm;
    let startIndex = 0;

    while (true) {
      const result = newline.exec(chunk);
      if (!result) {
        if (readerDone) break;
        const remainder = chunk.substr(startIndex);
        ({ value: chunk, done: readerDone } = await reader.read());
        chunk = remainder + (chunk ? utf8Decoder.decode(chunk) : "");
        startIndex = newline.lastIndex = 0;
        continue;
      }
      yield chunk.substring(startIndex, result.index);
      startIndex = newline.lastIndex;
    }

    if (startIndex < chunk.length) {
      // Last line didn't end in a newline char
      yield chunk.substr(startIndex);
    }
  }

  async fetch(fileUrl, charCode) {
    const lines = []
    for await (const line of this.#makeTextFileLineIterator(fileUrl, charCode)) {
      lines.push(line)
    }
    console.table(lines)
    return lines
  }
}
```

内閣府の祝日CSVもすんなり取得できた。

```js:main.js
const csv = new URLCSV()
const csvTexts = await csv.fetch('https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv', "shift-jis");
```

fetch処理はMDNに、参考になるコードがあったのでそのまま使用した。
ジェネレーター関数って...ワイルドだよね...。
テキストデータだと、順次レスポンスが返される関係でチャンク処理が必要になるらしい。

https://developer.mozilla.org/ja/docs/Web/API/Fetch_API/Using_Fetch#%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE_1_%E8%A1%8C%E3%81%9A%E3%81%A4%E3%81%AE%E5%87%A6%E7%90%86

作ったものの、頻繁に変わることもないデータであれば毎回取ってくるのはナンセンスだから、バッチ処理にしたほうがいいかも？と思った。
縦書き画像ジェネレータを作った話

# やったこと

深夜の思いつきでこんなものを作ってしまいました。

https://tategaki-generator.pages.dev/

このように縦書きの文章と画像を合成できます。

![サンプル画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2546324/6d822f44-11e9-fa37-0bc5-912a87b95363.png)

ソースコードはこちらです。

https://github.com/Nitoryu008/tategaki-generator

# 技術スタック

Vue3+Bulmaで作っています。今回、Cloudflare Pagesを使ってみたんですが、開発体験がとてもよかったです。プッシュしたら即時デプロイしてくれるのがありがたい。突然の思いつきを形にするにはもってこいですね。

# 仕組み

仕組みは割と単純で、 HTML+CSSで描画した後にDOM to Imageというライブラリを使って画像に変換しています。
HTML5だとCanvasに描画してからごにょごにょする方法もあるらしいですね。（作ってから知りました...）
また機会があったらやってみたい。


https://github.com/tsayen/dom-to-image

# ここが困った

開発中に困ったことを備忘録的にまとめておきます。

## Bulmaの導入方法がわからない

CSSフレームワークとしてBulmaを使おうと思ったんですが、Vueに導入する方法がわからず若干苦戦しました。

### 解決法

main.scssに次の一文を追加。

```main.scss
@import 'bulma/css/bulma.css';
```

main.tsでmain.scssを読み込む。

```main.ts
import '/src/assets/main.scss'
```

謎にscss使ってますがcssでもいけるはずです。今思いましたが、App.vueから直接読み込んでもよかったのかな...?

デザイン丸投げできるのでいいですね。

## iOSでダウンロードできない

ダウンロード機能は次のように実装しています。新規でa要素を作り、hrefにbase64エンコードされた生成画像を指定、download属性を指定してクリックイベントを発生させることでダウンロードさせます。

```javascript:App.vue
//ダウンロード機能の部分のみ抜粋
(dataUrl) => {
  const link = document.createElement("a");
  link.href = dataUrl;
  link.download = `tategaki.png`;
  link.click();
};
```

テストしたところPCとAndroidでは問題なくダウンロードできました。
ですがiPadではなぜかボタンを押してもダウンロードできません......
調べてみるとどうやらiOS14からhref属性にbase64を指定しても開けなくなったようです。

https://blog.kimizuka.org/entry/2021/07/01/012047

### 解決法

苦肉の策としてiOS用に画像表示ボタンを追加し、表示された画像を長押しして保存してもらうようにしました。もっといい方法があるような気もしますが...　教えて偉い人。

## 画面幅に合わせて描画を調整したい

ウィンドウの幅が変わっても描画エリアが崩壊しないようにしたかった。

### 解決法

JavaScript標準搭載のResizeObserverを使ってリサイズを検知します。
Vueで使うときには監視したい要素にref属性を指定します。

```javascript:App.vue
const text_renderer = ref(null);
//~~~省略~~~//
onMounted(() => {
  render(); //描画を更新する関数

  const resizeObserver = new ResizeObserver(() => { //リサイズ時に呼び出されるコールバック関数
    render();
  });
  if (text_renderer.value) {
    resizeObserver.observe(text_renderer.value); //監視を開始
  }
});
```
以下の記事が非常に参考になりました。

https://qiita.com/manzoku_bukuro/items/18186bf75285e56c0c02

# あとがき

完全に深夜テンションで作ったのですが、思ったより反響があってびっくりしました。

Vueのいい復習にもなりました。次はReactを使ってみたい気持ちがあります。
【UI/UXを意識して開発できる人材へ】新卒非デザイナーが貢献できるデザイン以外の2つのこと

おはようございます。
新卒駆け出しエンジニアのさわまりんです。

先日、株式会社ビビビット様 主催の
**『最強のデザイナーになるために必要なデザイン以外の知識と技術【デザナレコレクションVol.2】』**
というウェビナーに参加してきましたので、
そのときの内容やお答えいただいた質問から
私のような新卒非デザイナーが、開発者としてUI/UXを意識しながら、どのように業務に貢献できるのか をご共有します。

# 概要と背景
## ウェビナーの概要
> デザインスキルだけに留まらない、“最強デザイナー”に求められる知識と技術を紐解きます。
> ゲストスピーカーとして、マネーフォワードの井上ゆい子さん、青木麗紗さん、bravesoftの青木意芽滋さん、メドレーの波切雅也さんが登壇。自社で活躍するデザイナーの共通項、スキルセットの広げ方・深め方、人材育成など組織・チーム全体に落とし込む方法などを発表していただきます。
> （一部抜粋）

## 参加した理由
研修でUI/UXやウェブアクセシビリティに興味を持ったことがきっかけでした。
その研修で学んだのは、UI/UXを意識するのはデザイナーだけではないということです。
開発者もデザイナー同様に「常にUIとUXを意識してモノづくりをする人」として、何かしら学んでいく必要があります。
そんな時に見つけたウェビナーがこちらでした。デザイン以外の知識なら、私でもキャッチアップできるのはないかと思ったんです。

# 貢献できるデザイン以外の2つのこと
ご紹介のまえに簡単に、書き分けについて説明できればと思います。
まず最初に、《教えていただいたこと》
そのあとのコードブロック内に《私の考え》を書いています。
コードブロック内の内容はあくまで私の感じたことにすぎません。

## 1. チームのために、ユーザーのために、と考えて行動すること
具体的にどんなことかというと以下になります。
- 手が回っていないタスクを自ら行う
    - 議事録
    - チームビルディングの企画
- フレッシュな観点で意見を伝える
- 気づいたことをFBする
- その時やったほうがいいと思ったことにトライする

```
《私の考え》
このような行動を積極的に行える人がいることで、
チームがよりよくまわり、結果として良いものが生み出せると考えます。
さらに、些細なことに気がづく人や、実際に行動に移せる人は、
ユーザーへの配慮が今まで以上にできるようになったり、そもそもできることが増えたりと、
大きな成長につながると考えます。
```
## 2. いいと思うデザインを吸収し感性を磨くこと
生活にあふれるすべてのものがデザインです。
お気に入りの雑誌の表紙や、使いやすいウェブサイト、アプリ、
24時間365日いつだってデザインに触れることができます。
それらのデザインの中から、いいと思うもの、自分が思いつかないようなもの、をたくさん吸収しましょう。
また、いつでも人に話せるように、どこがいいのか言語化する力をつけましょう。

```
《私の考え》
感性を磨くことにに関しては、先ほど挙げたものにかかわらず、
芸術に近いものからも素敵なインスピレーションが湧きそうだと考えています。
また人と話すことは避けられませんし、
自分が思い描くデザインを相手に伝えることができなければ、
説得をすることもままならないと思うので、言語化の能力は非常に重要だと考えます。
```

## もう少しデザイナー職へ踏み込みたい方へ
初期配属にデザイナー職がない、いつか転身してみたい、
という方もいらっしゃるのではないでしょうか。
そんな方は次のことを意識してみてください。

### T字型人材からπ字型人材へ
T字型人材、π字型人材というワードはご存じでしょうか？
T型人材とは、特定の1つの分野を伸ばしながら、浅く広くその他の分野の知識を持つ人のことです。そして、π字型人材とは、T字型人材にさらに1本線を足し、得意分野が2本ある人のことを指します。

「1つのことをやり切った経験がある人は、横の職種に転身した際に、知識や能力を伸ばしやすい」といわれています。そのため、現在違う職種についている人は、そこでの業務に全力で取り組み、やり切った経験を付けてからデザイナーに挑戦することもおすすめです。

# おわりに
長文でしたが最後まで読んでいただきありがとうございました。
私にとって良いアウトプットの機会になりました！:hatching_chick:
cameraxとmlkitでバーコード読み取り画面実装Part4

# はじめに
今回は長らく間を空けてしまっていたバーコード読み取り機能の最終パートになります
### 本文
実際にカメラのPreviewViewとUseCaseをカメラに紐づける部分の実装になります
```kotlin
@Composable
internal fun BarCodeCamera(
    modifier: Modifier = Modifier,
    useCase: UseCase,
) {
    Box(
        modifier = modifier
            .fillMaxWidth()
            .aspectRatio(PreviewRatio)
        ) {
        val context: Context = LocalContext.current
        val lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current
        AndroidView(
            modifier = Modifier.clipToBounds(),
            factory = { factoryContext ->
                PreviewView(factoryContext).apply {
                    layoutParams = LinearLayout.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.WRAP_CONTENT,
                    )
                    implementationMode = PreviewView.ImplementationMode.COMPATIBLE
                    scaleType = PreviewView.ScaleType.FILL_CENTER
                }
            },
            update = { previewView ->
                val previewUseCase = Preview.Builder()
                    .build()
                    .apply {
                        setSurfaceProvider(previewView.surfaceProvider)
                    }
                context.startCamera(
                    lifecycleOwner = lifecycleOwner,
                    previewUseCase,
                    useCase,
                )
            },
        )
    }
}

private fun Context.startCamera(
    lifecycleOwner: LifecycleOwner,
    vararg useCases: UseCase,
) {
    val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

    cameraProviderFuture.addListener({
        val cameraProvider = cameraProviderFuture.get()
        // 背面カメラを使用するように設定
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
        try {
            cameraProvider.unbindAll()
            cameraProvider.bindToLifecycle(lifecycleOwner, cameraSelector, *useCases)
        } catch (e: Exception) {
            // TODO エラーハンドリング
            Timber.e(e, "Use case binding failed")
        }
    }, ContextCompat.getMainExecutor(this))
}
```
### 最後に
Part3を書いてから時間が空いてしまいましたが、これで全ての紹介をすることができました
どなたかのお役に立てれば幸いです
【データベース設計入門】1対1，1対多，多対多のリレーションシップの実例

## はじめに
データベース設計はシステム開発の重要な部分であり，データの正確な管理と効率的なアクセスを可能にします．この記事では，1対1・1対多・多対多のリレーションシップを具体的な例を通じて解説します．
この記事の目的は，これらのリレーションシップの基本概念と実際のテーブル設計方法を理解してもらうことです．

## 概要
今回はQiitaのような記事投稿サイトのようなシステムを題材にしています．

## 1対1のリレーションシップ

1対1のリレーションシップは，一つのテーブルのレコードが他のテーブルの一つのレコードに対応する場合に使われます.
例えば，ユーザ情報とユーザプロファイルの関係です．

ユーザ情報テーブル:
| UserID | UserName | Email | Password |
|-|-|-|-|
| 1 | Alice | alice@example.com | aaa |
| 2 | Bob | bob@example.com | bbb |

1対1の関係のデータは基本的に同じテーブル内にまとめられています．
UserIDに対して名前やメールアドレス，パスワードが1対1のデータになっています．

## 1対多のリレーションシップ
1対多のリレーションシップは，一つのテーブルのレコードが他のテーブルの複数のレコードに対応する場合に使われます．
例えば，ユーザと記事の関係です．

記事情報テーブル:

| ArticleID | fk_UserID | Title | 内容 |
|-|-|-|-|
| 1 | 1 | タイトル1 | aaa |
| 2 | 1 | タイトル2 | bbb |
| 3 | 2 | タイトル3 | ccc |
| 4 | 1 | タイトル4 | ddd |

1対多の関係のデータは基本的に親子の関係になります．
親(ユーザ)に対して子(記事情報)のデータがある状態です．
この時親テーブルがユーザ情報テーブルになりますので，ユーザ情報テーブルの一意なキー(UserID)を外部キー(fk_UserID)として持っています.

## 多対多のリレーションシップ
多対多のリレーションシップは，複数のテーブルのレコードが互いに複数のレコードに対応する場合に使われます．
例えば，ユーザとお気に入り記事の関係です．
これを実現するために，中間テーブルを使用します．

お気に入り登録テーブル:

| fk_ArticleID | fk_UserID |
|-|-----------|
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
| 4 | 2 |

多対多の関係のデータは基本的に中間テーブルを使って実現します．
これによって例えばユーザがお気に入り登録した記事を検索する場合はUserIDをキーに、
記事をお気に入りに設定したユーザ数を検索する場合はArticleIDをキーに検索すれば取得ができます。
税金計算アプリの紹介

![税金計算アプリアイコン.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806587/6c319991-99f5-7fb2-662c-5c5909afe03f.jpeg)

## 制作背景

給料の手取り額を知りたい人は多いと思います。もちろん私もそうでした。しかし探すと単純な計算結果に辿り着くまでに検索や広告は不要なプロセスです。税金額をさっと知りたい際にその他の動作は無駄なプロセスです。無駄なことはあまり行いたくありません。

そこで、このアプリのURLをブックマークしておけば、すぐに税金計算結果にたどり着ける場所を作ろうと考えました。給料はほとんど万円になります。即効性を高めるために給料の万（0000）は入力しなくて済むように設計しました。表示領域を最適化するため、各単語は必要最低限の長さに設計しています。

## 概要

この税金計算アプリは、ユーザーが入力した月給を基に各種税金や保険料を計算し、社員と会社の負担額を算出するシンプルなWebアプリケーションです。計算結果はリアルタイムで表示されます。

## 主な機能

### 1. 月給入力
ユーザーは月給を万円単位で入力します。

### 2. 税金および保険料の計算
- 所得税
- 住民税
- 健康保険料
- 厚生年金保険料（選択式）
- 雇用保険料
- 介護保険料（選択式）
- 子ども・子育て拠出金（選択式）

### 3. 社員負担額と会社負担額の表示
各種税金および保険料の詳細が表示されます。

### 4. 手取り額の表示
総支給額から各種控除を差し引いた後の手取り額を表示。

## 使用技術
- **HTML**: 基本的な構造を提供
- **CSS**: スタイリングの実装
- **JavaScript**: 計算ロジック、DOM操作

## プライバシーポリシー
このアプリでは、ユーザーが入力する月給やその他の個人情報を収集することはありません。すべての計算はユーザーのデバイス上で実行され、サーバーにデータが送信されることはありません。ユーザーの入力データはアプリのセッション終了とともに消去され、保存されることはありません。

## 公開URL
[給与計算アプリ](https://hutankeisan.vercel.app/)

## Vercelを選んだ理由

Vercelは、以下の理由で選びました。
- **簡単なデプロイ**: プロジェクトを迅速にデプロイできるため、開発プロセスが効率的です。

- **高速なパフォーマンス**: Vercelのインフラストラクチャは高速なコンテンツ配信を提供し、ユーザー体験を向上させます。

- **プレビュー機能**: プルリクエストごとにプレビューデプロイを自動で生成し、変更内容を簡単に確認できます。

- **カスタムドメインとSSL証明書**: 簡単にカスタムドメインを設定でき、無料でSSL証明書が提供されます。

このアプリを活用して、税金計算をより簡単にし、効率化しましょう。Qiitaでの公開を通じて、より多くの人にこの便利なツールを知ってもらえることを期待しています。
python + BigQuery Storage Write API でデフォルトストリームを使用する

# 背景
- BigQuery Storage Write API でデフォルトストリームを使いたかった（使用言語: python）

- が、公式ドキュメントを読んでもデフォルトストリームを使用する場合の具体的な実装方法がわからなかった
    - 日本語版公式ドキュメントには[Javaのサンプルコード](https://cloud.google.com/bigquery/docs/write-api-streaming?hl=ja#at-least-once)しかない。
    - Githubの[pythonのサンプルコード](https://github.com/googleapis/python-bigquery-storage/tree/main/samples/snippets)も、pendingタイプのストリームを使う場合の実装方法しかサンプルがなかった


## ストリームについて
Storage Write APIには「ストリーム」という概念があり、これによって、BigQueryテーブルにデータが書き込まれます。
大きく分けると、以下の種別があります。

詳しくは公式ドキュメントを参照。
https://cloud.google.com/bigquery/docs/write-api?hl=ja#overview

### デフォルトストリーム
基本的にこちらが推奨されている。
特徴としては以下のとおり（公式docsより）。
    - デフォルト ストリームに書き込まれたデータは、すぐにクエリで使用できます。
    - デフォルト ストリームは、at-least-once（少なくとも 1 回）セマンティクスをサポートしています。
    - デフォルト ストリームを**明示的に作成する必要はありません。**

### アプリケーションで作成したストリーム
アプリケーション側で**明示的にストリームを作成する。**
以下の種類がありますが、ここでは割愛します。詳しくは公式ドキュメントを参照してください。

- 保留タイプ (pending type)
- コミットタイプ (commited type)
- バッファタイプ (buffered type)


# 結論
そもそも、デフォルトストリームは「ストリームを明示的に作成しなくてよい」ということを理解できていませんでした。

ストリーム名をデフォルトのストリーム名にすることがポイントです。

## 実装方法
- stream名を`projects/${projectId}/datasets/${datasetId}/tables/${tableId}/streams/_default` にする
    - 参考: [英語版ドキュメントのNode.jsサンプルコード](https://cloud.google.com/bigquery/docs/write-api-streaming#node.js)
- `AppendRows` のみを呼び出す
    - `CreateWriteStream` は呼ばない

※ 実は、`AppendRows`だけでよいことは公式ドキュメントの「[APIフロー](https://cloud.google.com/bigquery/docs/write-api?hl=ja#default_stream)」に書かれている（推測難しい…）。

[公式のpendingタイプのサンプルコード](https://github.com/googleapis/python-bigquery-storage/blob/main/samples/snippets/append_rows_pending.py)をdefaultにアレンジするとこのようになる。

```python
def append_rows_default(project_id: str, dataset_id: str, table_id: str):
    write_client = bigquery_storage_v1.BigQueryWriteClient()
    parent = write_client.table_path(project_id, dataset_id, table_id)

    request_template = types.AppendRowsRequest()
    # デフォルトのストリーム名を指定する
    request_template.write_stream = f"{parent}/streams/_default"

    proto_schema = types.ProtoSchema()
    proto_descriptor = descriptor_pb2.DescriptorProto()
    customer_record_pb2.CustomerRecord.DESCRIPTOR.CopyToProto(proto_descriptor)
    proto_schema.proto_descriptor = proto_descriptor
    proto_data = types.AppendRowsRequest.ProtoData()
    proto_data.writer_schema = proto_schema
    request_template.proto_rows = proto_data

    append_rows_stream = writer.AppendRowsStream(write_client, request_template)

    # proto_rowsに行データを追加する
    proto_rows = types.ProtoRows()
    proto_rows.serialized_rows.append(create_row_data(1, "Alice"))
    proto_rows.serialized_rows.append(create_row_data(2, "Bob"))

    request = types.AppendRowsRequest()
    proto_data = types.AppendRowsRequest.ProtoData()
    proto_data.rows = proto_rows
    request.proto_rows = proto_data

    response_future_1 = append_rows_stream.send(request)
    print(response_future_1.result())

    append_rows_stream.close()

```
【Flutter】ウィジェットテストの実行

■テストの運用
- テストはカバレッジ（網羅率）70-80%目安。
->100にしようとしたら、変更のたびにテストへ割く時間、修正が多く発生し、工数がかかる

- Lintはコーディング規約を満たすかのチェック
-> analysis_options.yaml で定義

```mermaid
flowchart LR

subgraph CI["CI(Continuous Integration)"]
  Lint
  --> ビルド
  --> UT
end

UT --> デプロイ

subgraph CD["CD(Continuous Deviverry)"]
  デプロイ
  --> 配布
end

CI --> Error[エラー時はプロジェクトメンバーへ通知]
CD --> Error

```

■設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136142/95342cd9-2946-fcb0-f7a0-b3643f00302a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136142/f9de81eb-ebaa-7b01-29c8-9983728aeee0.png)

プロジェクト作成時に生成されたwidget_test.dartを指定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136142/0160d589-359b-ab02-201a-313c9efef733.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136142/f6da52a5-d206-d802-6221-0b525a07b6a5.png)

Runボタンを押すと実行される

```dart widget_test.dart
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:test01/main.dart';// package:自分のプロジェクト名/main.dart

void main() {
  testWidgets('Counter increments smoke test', (WidgetTester tester) async {
    // pumpWidgetは画面フレームを生成し、UIの更新、状態変化を確認
    // 利用場面は以下
    // ・ユーザーインタラクション後
    // ・アニメーション、画面遷移など、時間に基づく変更時
    // ・データバインディング当で状態変更の発生時
    await tester.pumpWidget(const MyApp());

    // 画面上に期待するの要素が存在するかを確認
    // 期待値：0が1つ表示、1が1つも表示されない
    expect(find.text('0'), findsOneWidget);
    expect(find.text('1'), findsNothing);

    // ユーザー操作を実行（+アイコンタップ）
    await tester.tap(find.byIcon(Icons.add));
    await tester.pump();

    // 画面上に期待するの要素が存在するかを確認
    // 期待値：0が1つも表示されず、1が1つ表示
    expect(find.text('0'), findsNothing);
    expect(find.text('1'), findsOneWidget);
  });
}
```
dotnet で Excel 操作（初歩）

&emsp;.NET SDK の学習の初手として ``dotnet`` コマンドでサンプル（[「C#（.NET 8）から Excel を制御する」](https://aimnext.co.jp/note/engineering/c%EF%BC%88-net-8%EF%BC%89%E3%81%8B%E3%82%89excel%E3%82%92%E5%88%B6%E5%BE%A1%E3%81%99%E3%82%8B/)）のビルドを試みた。

## テンプレートの作成

&emsp;次のコマンドを投入して ``./ConsoleApp/`` に ``Program.cs`` と ``ConsoleApp.csproj`` を生成した。

```bash
dotnet new console -o ConsoleApp
```

## Program.cs の差替え

&emsp;サンプルのソースコードに差替えた。

## ConsoleApp.csproj の編集

&emsp;``Program.cs`` には次の行が含まれる。

```c#
using Excel = Microsoft.Office.Interop.Excel;
```

&emsp;この参照を設定するため ``ConsoleApp.csproj`` を次のように編集した。``<HintPath>`` は[この記事](https://qiita.com/UndMon/items/5c0ae14171336c7b2043)を参考に設定した（ ``C:\Windows\assembly`` 以下に存在する同名のライブラリのパスを指定したところ、ビルドは成功するものの、ランタイムに何故かファイル名が不測のものになりエラーが発生）。

```xml
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <Reference Include="Microsoft.Office.Interop.Excel">
      <HintPath>C:\Program Files\Microsoft Office\root\Office16\ADDINS\Microsoft Power Query for Excel Integrated\bin\Microsoft.Office.Interop.Excel.dll</HintPath>
    </Reference>
  </ItemGroup>

</Project>
```

## ビルド・実行

&emsp;次のコマンドを投入すると ``./bin/Debug/net8.0/ConsoleApp.exe`` が作成され ``Book1.xlsx`` が表示される。

```bash
dotnet run
```
Ubuntuの`python3.12`パッケージには`ensurepip`モジュールが存在しない

# 環境
* Ubuntu 24.04

以下のコマンドはdockerのコンテナ内で実行しています。

```
$ docker run -it ubuntu:24.04 /bin/bash
```



```
# uname -a
Linux cf81d231b59a 5.15.153.1-microsoft-standard-WSL2 #1 SMP Fri Mar 29 23:14:13 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

# cat /etc/os-release
PRETTY_NAME="Ubuntu 24.04 LTS"
NAME="Ubuntu"
VERSION_ID="24.04"
VERSION="24.04 LTS (Noble Numbat)"
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo
```

# 起きたこと
Ubuntuの`python3.12`パッケージをインストールしてPython環境を構築しました。

```
# apt install python3.12

# python3.12 --version
Python 3.12.3
```

`ensurepip`モジュールを利用して、`pip`コマンドをインストールしようとしましたが、`ensurepip`モジュールは存在しませんでした。


```
# python3.12 -m ensurepip --upgrade
/usr/bin/python3.12: No module named ensurepip
```

https://pip.pypa.io/en/stable/installation/#ensurepip



`python3.12-venv`パッケージをインストールすると、`ensurepip`を利用することができます。しかし、Ubuntuでは`ensurepip`は無効化されているため、結局`pip`をインストールできませんでした。

```
# apt install python3.12-venv

# python3.12 -m ensurepip
ensurepip is disabled in Debian/Ubuntu for the system python.

Python modules for the system python are usually handled by dpkg and apt-get.

    apt install python3-<module name>

Install the python3-pip package to use pip itself.  Using pip together
with the system python might have unexpected results for any system installed
module, so use it on your own risk, or make sure to only use it in virtual
environments.
```

# どうすれば`pip`をインストールできるか
* (A) 警告メッセージに書いてある通り`python3-pip`パッケージをインストールする
* (B) https://bootstrap.pypa.io/get-pip.py からスクリプトをダウンロードして、`python get-pip.py`を実行する

# 参考にしたサイト

https://stackoverflow.com/questions/29871372/i-have-python3-4-but-no-pip-or-ensurepip-is-something-wrong-with-my-python3-4



https://amano41.hatenablog.jp/entry/wsl-python3-venv-error

https://ryamashina.com/itml/20200328/
RAID (Redundant Array of Inexpensive Disks)

# 最初に
おつかれさまです。mochiです。
今回はRAIDについての記事を書こうと思います。
会社の物理サーバ研修で興味を持ち始めてから記事を書いていなかったので、書きます！

# 1. RAIDの基本的な説明
RAID（Redundant Array of Inexpensive Disks）は、複数の物理的なHDDを一つの論理的なディスクとして扱う技術です。RAIDはデータの冗長性と性能向上を目的としており、データ保護やシステムの信頼性向上、データアクセス速度の向上に利用されます。

RAIDは複数の異なるレベルに分けられ、それぞれが異なる方法でデータを分散、冗長化、またはミラーリングします。各RAIDレベルには特定の利点と欠点があり、使用するシステムの要件に応じて適切なレベルを選択します。

https://www.elecom.co.jp/pickup/column/storage_column/00003/

# 2. 代表的なRAIDレベルの比較
RAIDレベルは以下の通りとなります。
※ストライピングやミラーリング等についての説明は利点と欠点で記載しています。

RAID 0: ストライピング
RAID 1: ミラーリング
RAID 5: ストライピングとパリティ
RAID 6: ダブルパリティ
RAID 10（1+0）: ミラーリングとストライピング

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726585/ec97cd1a-9caa-d664-d734-27d54c2416ee.png)

# 3. RAIDレベル毎の利点と欠点
### RAID 0

利点: 最高の読み書き速度、ディスク容量を最大限に活用
欠点: 冗長性がなく、一つのディスクが故障するとすべてのデータが失われる

⇒ストライピング
データを複数のディスクに分散して書き込む方法。冗長化を行わない為、1台が故障すると全体の故障となる。

### RAID 1

利点: 高いデータ冗長性、ディスクの一台が故障してもデータが保護される
欠点: 容量効率が低い（ディスクの50%）

⇒ミラーリング
同じデータを複数のディスクに同時に書き込み、冗長性を確保。

### RAID 5

利点: バランスの取れた性能と冗長性、パリティによるデータ保護
欠点: 書き込み性能がRAID 0よりも低い、ディスクのリビルドに時間がかかる

⇒パリティ
データを保護する。

### RAID 6

利点: RAID 5と同様の利点、さらに高いデータ保護（2台のディスクが同時に故障してもデータが保護される）
欠点: RAID 5よりも書き込み性能がさらに低下、リビルドがさらに長時間かかる

⇒RAID5より高いデータ保護性能

### RAID 10

利点: 高い読み書き性能、RAID 1と同等の冗長性
欠点: 容量効率が低い（ディスクの50%）

⇒RAID1と0の組み合わせ

↓それぞれのRAIDレベルの特徴
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726585/740442cf-d154-5123-fe19-faebd08f8379.png)

# 4. 簡単な利用例
### RAID 0
性能が重視されるがデータ保護は不要な場合（例：一時的なデータの処理、キャッシュ処理）

### RAID 1
データの安全性が最優先の環境（例：OS、重要なデータの保護）

### RAID 5
コストと性能、冗長性のバランスが重要な中小規模のシステム（例：ファイルサーバ、ウェブサーバ）

### RAID 6
データの保護が特に重要な大規模なシステム（例：データセンター、大規模なストレージシステム）

### RAID 10
高性能と高冗長性が求められる環境（例：データベースサーバ、仮想化ホスト）

# 5. さいごに
RAIDはレベルによって冗長性の有無やデータ保護のレベルも異なります。
状況に応じて適切なRAIDレベルを選択することは非常に重要であると感じました。

それによってシステムの信頼性や性能に大きく影響が出るかと思います。
実際に自分がサーバ構築に携わるときは、特にこの点に注意して実施していきます！🔥
Pythonで画像をPDFに変換する

画像をPDFに変換する主な理由の一つは、共有や転送を容易にすることです。また、複数の画像を1つのPDFファイルにまとめることで、ファイル管理を簡素化することもできます。この記事では、サードパーティライブラリ[Spire.PDF for Python](https://www.e-iceblue.com/Introduce/pdf-for-python.html)を使って**Pythonで画像をPDFファイルに変換する**方法を紹介します。

## Python PDFライブラリの紹介
[**Spire.PDF for Python**](https://www.e-iceblue.com/Introduce/pdf-for-python.html)は、PythonアプリケーションでPDFファイルを扱いたい開発者のための多機能ツールです。PDFの作成、操作、変換のための幅広い機能を提供し、単純なPDF作成から複雑な文書処理タスクまで、様々なユースケースに適しています。

Python PDFライブラリをインストールするには、以下のpipコマンドを実行します：
> **`pip install Spire.PDF`**



## Pythonで複数の画像を1つのPDFファイルに変換する
PDF Pythonライブラリは、画像をPDFファイルのページに直接描画することで、画像をPDFに変換する方法を提供します。画像はjpg, jpeg, pngのようなどんなフォーマットでもかまいません。主な手順は以下の通りです：

1\.	必要なモジュールをインポートします；
2\.	**`PdfDocument`** クラスでPDFファイルを作成し、ページの余白を設定します；
3\.	画像が保存されているフォルダを指定し、各画像を繰り返し処理します；
4\.	画像の幅と高さを取得し、画像と同じサイズの新しいページをPDFに追加します；
5\.	**`PdfPageBase.Canvas.DrawImage()`** メソッドを呼び出して、画像を新しいPDFページに描画します；
6.	**`PdfDocument.SaveToFile()`** メソッドでPDFファイルを保存します。

**サンプルコード:**
```python
from spire.pdf.common import *
from spire.pdf import *
import os
 
# PdfDocumentオブジェクトを作成する
pdf = PdfDocument()
 
# ページの余白を設定する
pdf.PageSettings.SetMargins(0.0)
 
# 画像が保存されているフォルダを取得
path = " Images\\ "
files = os.listdir(path)
 
# フォルダ内のファイルを反復処理する
for root, dirs, files in os.walk(path):
    for file in files:
 
        # 画像を読み込む
        image = PdfImage.FromFile(os.path.join(root, file))  #FromFile(os.path.join(root, file))
    
        # 画像の幅と高さを取得する
        width = image.PhysicalDimension.Width
        height = image.PhysicalDimension.Height
 
        # 画像と同じサイズのページを追加する
        page = pdf.Pages.Add(SizeF(width, height))
 
        # ページに画像を描く
        page.Canvas.DrawImage(image, 0.0, 0.0, width, height)
      
# PDFファイルを保存する
pdf.SaveToFile("ConvertImagesToPdf.pdf")
pdf.Dispose()
```

**結果：**
![image2pdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/84ae6b41-85fb-50c2-b5aa-7835962e9039.png)

* * *

**Pythonライブラリのその他の機能：**
* [*PythonでPDFを画像(JPG, PNG, BMP)に変換する*](https://www.e-iceblue.com/Tutorials/Python/Spire.PDF-for-Python/Program-Guide/Conversion/Python-Convert-PDF-to-Images-JPG-PNG-BMP.html)
* [*PythonでPDFをSVGに変換する*](https://www.e-iceblue.com/Tutorials/Python/Spire.PDF-for-Python/Program-Guide/Conversion/Python-Convert-PDF-to-SVG.html)
* [*PythonでPDFをExcelに変換*](https://www.e-iceblue.com/Tutorials/Python/Spire.PDF-for-Python/Program-Guide/Conversion/Python-Convert-PDF-to-Excel.html)
* [*PythonでPDFからテキストと画像を抽出する*](https://www.e-iceblue.com/Tutorials/Python/Spire.PDF-for-Python/Program-Guide/Extract/Read/Python-Extract-Text-and-Images-from-PDF-Documents.html)
実機テスト＠Xcodeでエラー「Please reinstall cocoapods with `bundle exec pod install`」が発生した時の対処法

## 背景
iPhone7＠Xcode14.3.1で実機テストを実施しようとした（再生ボタンをクリックした）ところ、「Please reinstall cocoapods with `bundle exec pod install`」というエラーが発生しました。エラーの対処方法を紹介します。

## 環境
macOS Monterey:12.1
Ruby:3.0.6
Rails:6.1.0
React Native:^0.74.3
expo SDK:~51.0.20
bundler:2.5.3、2.4.13（default:2.4.13）
node:16.20.0
npm:8.19.4
yarn:1.22.19
webpack:4.46.0
※エディターは、VSCodeを使用しています。
※デプロイ先は、herokuです。

## 問題
・Xcodeのログに、以下のエラーが発生しました。
```
Codegen did not run properly in your project. Please reinstall cocoapods with `bundle exec pod install`.
```
※Xcodeのログは、「View→Navigators→Reports」で表示されます。画面左のメニューの「Build」を選択した後、「Errors Only」タブをクリックするとエラーが抽出されます。

「bundle exec pod install」はRubyのコードです。
フロントエンドはReact Native@Expoで構築しています。
VSCodeのターミナルでは「bundle exec pod install」は実行できません。

## 解決策
CocoaPodを再インストールしました。
VSCodeのターミナル（プロジェクトフォルダ直下）で、以下のコードを実行しました。

```
#npmキャッシュのクリア
npm cache clean --force

#node_modulesディレクトリとPodfile.lockの削除
rm -rf node_modules ios/Pods ios/Podfile.lock

#npm依存関係の再インストール
npm install
#または
yarn install

#CocoaPodsのキャッシュのクリア
pod cache clean --all

#CocoaPodsのインストール
cd ios
pod install

#npx pod-installの使用
cd ..
npx pod-install
```

## 結果
Xcodeプロジェクトファイル（.xcodeproj）ではなく、作成されたワークスペースファイル（.xcworkspace）を使ってXcodeプロジェクトを開きます。

Xcodeの再生ボタンをクリックすると、エラーが発生することなく、実機テストがスタートしました。
（ポップアップで「Bundle Succeed」表示されます）

## まとめ
エラー解消方法をGPT-4oで模索した際に、頑なにGemfileを使用したCocoaPodを再インストール提案されました。ハルシネーションが発生していたかと思います。

Xcodeでの段階で、「Please reinstall cocoapods with `bundle exec pod install`」というエラーが発生した際に、本記事の解決策がお役に立てたのであれば嬉しいです。

（そもそも、古いバージョンのVcodeと古い機種iPhone7で実機テストしてごめんなさい）
基本情報技術者試験 計算問題

この記事では基本情報技術者試験に出題され、計算を必要とする問題について解説していきます。2進数の計算のみ別記事にて説明します。
## 前提知識
まず欠かせない知識は以下の通り
1バイト=8ビット
です。
|  SI単位  |  数値  |
| ---- | ---- |
|  ピコ  |  $10^{-12}$  |
|  ナノ  |  $10^{-9}$  |
|  マイクロ  |  $10^{-6}$  |
|  ミリ  |  $10^{-3}$  |
|  キロ  |  $10^{3}$  |
|  メガ  |  $10^{6}$  |
|  ギガ  |  $10^{9}$  |
|  テラ  |  $10^{12}$  |
|  ペタ  |  $10^{15}$  |
|  エクサ  |  $10^{18}$  |

1キロバイト=1000バイトと1キロバイト=1024バイトの場合がありますが、本試験では1キロバイト=1000バイトになります。後者はKiB(キビバイト)と表記することがあります。同様にメガバイトとメビバイト等も存在します。

## n進数変換
10進数に変換するためには各桁の重みにnをかければよい。
$x_i$を各桁とすると基本的な式は$x_i×n^{i-1}+x_{i-1}×n^{i-2}+...+x_1×n^0$
小数点以下も10進数に変換するためには$x_i×n^{i-1}+x_{i-1}×n^{i-2}+...$の式を利用する。
10進数からの変換は整数部分ではnで割ったときのあまりを逆順で書くと答えになります。小数部分はn倍してから整数部分を書いていって、小数部分が0になったら終わりです。詳しくは別記事にて説明します。

## MIPS
MIPS(Million Instructions Per Second)は1秒あたりに処理できる命令数を百万単位で表します。
#### 例
1分間で600万処理が可能なコンピューターのMIPSは?
#### 解
$1分=60秒$
$6×10^{6}÷60=0.1×10^{6}$
答え:$0.1$MIPS
#### 例
MIPSが10のコンピューターが10分でいくつの処理が行える?
#### 解
$10$分$=600$秒
$10×600=6000$
$6000×1000,000=6000,000,000$
答え:$6000,000,000$処理
#### 例
1件のトランザクションについて 80万ステップの命令実行を必要とするシステムがある。プロセッサの性能が200 MIPSで、プロセッサの使用率が80%のときのトランザクションの処理能力 (件/秒)は幾らか。
#### 解
実効処理能力を計算してから解くのがポイントです。
$200×80÷100=160$
$80÷16,000=0.005$
$1÷0.005=200$
答え:$200$
## 伝送速度問題
名前こそ恐ろしいですが、小学校でやった道のり&速度&時間の問題と同じです。ここで
道のり=伝送量
速度=伝送速度
時間=伝送時間
です。ポイントは速度を実効速度や伝送効率を用いて速度を"直して"から計算することです。
#### 例
10Mバイトのデータを 100,000ビット/秒の回線を使って転送するとき、転送時間は何秒か。ここで、回線の伝送効率を50%とする。
#### 解
10Mバイトをビットに変換して解くのがポイントです。
$10×10^{6}×8=80$Mビット
$100,000×50÷100=50,000$
$80×10^{6}÷50,000=1,600$秒
33業種×エンジニア：ゴム製品

## はじめに
転職を始める際、自分ができることを加味したうえで求人情報を確認しますが、あえて33業種の側からみてみて、どのような働き方、どんな会社があるのかを知りたいと思います。
世界と日本でどんな企業が有名なのかも知りたいと思います。

## ゴム製品×エンジニアの働き方の例
![wagomu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777936/b0db267d-f81f-264a-8640-92caf6c36f52.png)

### 1. システムエンジニア（SE）
- 役割: ゴム製品企業のITインフラの設計、開発、導入、運用管理を行う。
- 具体例:
生産管理システムの設計と導入。
ERPシステムの開発およびカスタマイズ。
供給チェーン管理システムの最適化。

### 2. プログラマー
- 役割: ゴム製品の製造プロセスや品質管理をサポートするソフトウェアのコーディング。
- 具体例:
製造工程の自動化ソフトウェアの開発。
品質管理システムのプログラミング。
データ解析ツールの実装。

### 3. サーバーエンジニア
- 役割: ゴム製品企業のサーバーの設計、設定、保守、管理を担当。
- 具体例:
生産データの保存とバックアップシステムの構築。
データセンターの運用管理。
クラウドベースのシステム管理。

### 4. ネットワークエンジニア
- 役割: ゴム製品企業のネットワークインフラの設計、設定、運用、保守を行う。
- 具体例:
工場、倉庫、販売拠点を結ぶネットワークの構築。
リモートモニタリングシステムのセキュリティ設定。
データ伝送のための高可用性ネットワークの構築。

### 5. データサイエンティスト
- 役割: ゴム製品の製造データの解析、予測モデルの作成、結果のビジュアル化を行う。
- 具体例:
生産データの解析とパターン認識。
製品品質の予測モデルの作成。
市場データの解析による需要予測。

## 世界大手企業の概要
### [Michelin](https://www.michelin.com/)
- 概要: フランスに本拠を置く世界有数のタイヤメーカー。乗用車、トラック、航空機、自転車、二輪車など多様なタイヤ製品を提供している。持続可能なモビリティを推進している。

### [Goodyear Tire & Rubber Company](https://www.goodyear.com/)
- 概要: アメリカに本拠を置く大手タイヤメーカー。乗用車、トラック、航空機、産業機械など多岐にわたるタイヤ製品を製造している。タイヤ関連サービスやソリューションも提供している。

### [Continental AG](https://www.continental.com/en/)
- 概要: ドイツに本拠を置くグローバルな自動車部品サプライヤーおよびタイヤメーカー。タイヤ、ブレーキシステム、車両安定化システム、エレクトロニクスなど幅広い製品を提供している。

## 日本企業の概要
### [ブリヂストン](https://www.bridgestone.co.jp/)
- 概要: 日本最大のタイヤメーカーであり、世界でも有数のシェアを持つ。乗用車、トラック、航空機、自転車、産業機械など多様なタイヤ製品を提供している。

### [住友ゴム工業](https://www.srigroup.co.jp/)
- 概要: 日本の大手タイヤメーカー。ダンロップブランドで知られ、乗用車、トラック、バス、自動二輪車、航空機などのタイヤを製造・販売している。

### [横浜ゴム](https://www.y-yokohama.com/)
- 概要: 日本の総合タイヤメーカー。乗用車、トラック、バス、航空機、産業車両などのタイヤ製造・販売を行い、ゴム製品の分野でも幅広い製品を提供している。

## 求人票をみてみて
「大手グループ会社のアプリ開発エンジニア」「システムエンジニア」等がありましたが、探し方が悪いのか、全体的に少ない印象でした。ITよりかは研究とかの技術者を欲しているようにかんじました。
dos fileとunix fileのシバン報告

スクリプトに実行権を付けて、実行させると、

```
bash: ./f.gm: 実行できません: 必要なファイルがありません
```
と出て、neovimで見ても一見分からず、しばらく悩んでいて、仕方なくバイナリファイルエディタbviで見たら、行末に^Mがあったので、やっとそのファイルがdosフォーマットだと分かり、フォーマット変換をしたら実行できた。
どうも、bashが、#!/usr/bin/nantoka^Mをそのまま解釈して、/usr/bin/nantoka^Mを呼び出していたので、そういうことになったらしい。
neovimで、コントロールコードを見れるフラグを立てたら良かった。
でも、ここは、

```
bash: ./f.gm: /usr/bin/nantoka^M: 実行できません: 必要なファイルがありません
```
と、出力するべきではないでしょうか。

以上、報告でした。

追記：
コントロールコードを見れるフラグはvi関係のエディタでは、listオプションですが、どういうわけか^Mは表示されませんでした。
Act で GitHub Actions をローカルで実行してみる

# やりたいこと
GitHub Actions で CI/CD のパイプラインを1から組むことがあり、その際に Act というローカルで GitHub Actions を実行できるツールを使ったので、その内容をまとめてみます。

# Act とは
Act は GitHub で提供されている CI/CD のサービスをローカルで実行 (デバッグ) できるツール。特にパイプラインを1から組んでいく時に、修正して　PUSH　して、また修正して PUSH してというのを繰り返すのをローカルで実行することで、リモート側に PUSH せずとも動作を確認できる。GitHub Actions のすべての機能を再現はできないが、基本的な機能は再現できる。

https://github.com/nektos/act

https://nektosact.com/

:::note
- 以降の手順は、MAC (M* Chip) での実行を前提とします
- Docker を利用できる必要があります
    - Docker Desktop や Colima などを利用してください
:::

# インストール
以下コマンドでインストール。

```sh
brew install act
```

# パイプラインの作成
テスト用に簡単なパイプラインを作成する。

```./.github/workflows/test.yml
name: test
on:
    push:

jobs:
    test:
        name: test_job
        runs-on: ubuntu-latest

        steps:
            - name: first_step
              uses: actions/checkout@v4

            - name: second_step
              run: |
                  pwd
                  ls -a

            - name: third_step
              run: echo "Hello Act!"
```

#　実行
以下コマンドで実行できる。今回は条件に `push` を指定しているので、push で実行する。

```sh
act push
```

実行時に以下のようなエラーが出る場合は、

```sh
Error: failed to start container: Error response from daemon: error while creating mount source path '/Users/****/.colima/docker.sock': mkdir /Users/****/.colima/docker.sock: operation not supported
```

実行時に以下のオプションを指定する。

```sh
act push --container-daemon-socket -
```

また、WARNING として表示される以下が気になる場合は、

```sh
WARN  ⚠ You are using Apple M-series chip and you have not specified container architecture, you might encounter issues while running act. If so, try running it with '--container-architecture linux/amd64'. ⚠  
```

メッセージに従い、実行時にオプションを指定する。

```sh
act push --container-architecture linux/amd64
```

オプションに指定するのが面倒な場合は、以下の設定ファイルを作成する。

```~/.actrc
--container-daemon-socket -
--container-architecture linux/amd64
```

実行すると作成したパイプラインで定義した内容が出力されるはず！

# ということで
Act を使って、GitHub Actions をローカルで実行する方法をまとめました。パイプラインの開発時に毎回 PUSH して動作確認するのは面倒ですしコミット履歴も増えてしまうので、極力 Act を使ってローカル実行するのが良いのかなと感じます (個人の好みの範疇ですが笑)。


以上です！