OmniAICreator/Qiita-1.07M huggingface dataset:
応用情報技術者　合格体験記とその勉強方法

令和5年度春期　応用情報技術者試験に合格しましたので、その時の勉強方法について共有いたします。
非IT系人材が合格するためのロードマップとして何かのお役に立てれば幸いです。

●プロフィール
・非IT系企業勤務(自動車部品メーカの生産技術職)
・年齢は25歳(社会人4年目)
・22年に基本情報技術者試験に合格
・大学は地方国公立工学部機械系学科を卒業(学部卒)

●試験結果
・試験結果は、午前77点/午後68点
　比較的ギリギリの結果と言えます。
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621830/59fe9bf6-db5a-d834-bc16-ecb374872037.png)

●受験目的
・明確な目的なし。IT系の知識を持っている人はかっこいいという憧れから受験を決定。

●使用教材について
・基本的には下記2つを使用で合格できました。
1.応用情報技術者　合格教本
2.過去問道場

●勉強期間について
2023年1月～4/16までの約3か月半

●勉強方法
1.1月～1月上旬
合格教本を一通り目を通す。
この時はとりあえず”応用情報技術者試験”ってどんな試験かを知ることが目的なので、可能な限り早く1周した。
内容についてはあまり理解できていなくても、どういった内容をこれから勉強するのか全体を把握する。
ページ数が多すぎて果てしなく眠くなる。1週間はかかりました。
 
2.1月上旬～中旬
学習計画を立てる。
応用情報技術者は午後問題の難易度が高いので午後問題の対策に時間をかけたいが、”午前問題の理解度”が午後問題でも生きてくると思うので、インプットと午前対策に8割、午後2割のイメージで対策計画をたてました。

3.1月下旬～2月末
過去問道場で午前問題にコミット。
2日で1年分(80問)を目標に問題を解いていた。この時重要なのは1問ずつ解説を読み理解することを心がけること。
毎年同じような問題が出ているので、だんだん1年分解くのにかかる時間が短くなってくる。
過去問道場で成績レポートをスプレッドシートに出力し、会社の休み時間等スキマ時間を使用して間違えた問題を復習。
過去問道場の解説のみで理解出来たらOKとする。理解できない場合は、合格標本を参照する。
この時、ピンポイントで調べるのではなく該当の章を一通り読んで理解するよう心掛けた。これによって、苦手分野を得意分野に変えていく作業がやる気向上につながったと思う。
勉強を進めるうちに正答率が100％に近づいていくこともモチベーションになりました。
1月下旬は40％程度だった正答率が、2月末には75～80％程度まで安定してきていました。

4.3月上旬～下旬
過去問道場で午後問題に着手。
過去問道場で午後の過去問をDLできるので、印刷し一年づつ解いていく。
1問に対して、解く→回答・解説を読むのルーティンに1h以上要するのであまり球数をこなせない。
結局、各分野5年分ぐらいしかできなかったが、午前の対策のおかげか解説を読んでも全くわからない問題はあまりなかった。
午前試験の対策は並行して過去問を解くことは実施していました。

5.4月上旬～試験
合格教本を熟読することにコミットする。
問題演習中心の勉強方法で発生した知識の穴を埋めていく作業。
結局すべてを精読できなかったが、試験までの許す時間で読み進めた。

●総勉強時間について
平日：1h30m
休日：5h
平日の朝8時～夜9時は基本的に仕事+休日出勤たまにありのため、なかなか勉強時間の捻出が難しかったです。

●今後について
IT系の知識の基本について浅く知ることができたので、興味の幅が広がったと思う。
もっといろいろ勉強してみたいと思うので、現在プログラミングの学習中。(java/python)
ネットワーク分野にも興味があり、将来的には業務にもいろんな側面で絡めていけるようにこっそりと技術力を高めていきたいと考えております。
ディレクトリ削除

import java.io.File;

public class DirectoryDeleter {
    public static void main(String[] args) {
        File parentDirectory = new File("ParentDirectory"); // パスを指定してください

        if (parentDirectory.exists()) {
            deleteDirectory(parentDirectory);
            System.out.println("すべてのサブディレクトリとファイルを削除しました");
        } else {
            System.out.println("指定された親ディレクトリは存在しません");
        }
    }

    public static void deleteDirectory(File directory) {
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    deleteDirectory(file); // サブディレクトリを再帰的に削除
                } else {
                    file.delete(); // ファイルを削除
                }
            }
        }
        directory.delete(); // ディレクトリを削除
    }
}


import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class FolderCleanup {
    public static void main(String[] args) {
        String parentDirectoryPath = "親ディレクトリのパスを指定";

        // 今日の日付を取得
        Date today = new Date();
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String todayString = dateFormat.format(today);

        // フォルダを取得して処理
        File parentDirectory = new File(parentDirectoryPath);
        if (parentDirectory.exists() && parentDirectory.isDirectory()) {
            File[] subDirectories = parentDirectory.listFiles();
            if (subDirectories != null) {
                for (File subDirectory : subDirectories) {
                    // フォルダ名の日付部分を取得
                    String folderName = subDirectory.getName();
                    String folderDatePart = folderName.substring(0, 8);

                    // 日付を比較して削除
                    if (folderDatePart.compareTo(todayString) < 0) {
                        deleteDirectory(subDirectory);
                    }
                }
            }
        }
    }

    // フォルダとその中身を再帰的に削除するメソッド
    private static void deleteDirectory(File directory) {
        if (directory.isDirectory()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    deleteDirectory(file);
                }
            }
        }
        directory.delete();
    }
}
ファイル名に日時をつけて一箇所にバックアップするコマンド。あるいはパイプと可変長引数の取り扱いサンプル

:::note warn
バグってて大事なファイルを上書きしちゃったらすみません。責任取れません。
:::

テストは一通りやったけど、 Linux 初心者で知らない挙動のほうが多いため怪しいです。

## コード

@ko1nksm さんが一部コードを修正してくださいました。ありがとうございます。

>変数を使用するときは必ずダブルクォートするようにしてください。それがベストプラクティスです。

肝に銘じます！

---

`.bash_aliases` とかに貼り付けて使うと良いと思います。
`$BACKUP_DIR` を事前に設定しておく必要があります。 
`export BACKUP_DIR=~/.local/share/backup` とかでいいんじゃないでしょうか。 

```bash
backup() {
  usage='
Function: backup

Description:
  指定されたファイルまたはディレクトリをバックアップする。引数またはパイプ入力でパスを指定する。
  ファイルは $BACKUP_DIR/フルパス_YYYYMMDDHHMMSS にコピーされる。
  バックアップ先のディレクトリがない場合は作成される。

Parameters:
  $1[ $2...] (string): バックアップ対象ファイルのパス。相対パスまたは絶対パス

Returns:
  None

Example:
  backup hello.txt (実際は/path/to/hello.txt)
  $BACKUP_DIR/path/to/hello.txt_20210202030405 が作成される。

Example:
  backup hello1.txt hello2.txt

Example:
  backup hello*.txt

Example:
  find ./he*llo{.jpg,.png} | backup
'

  # 第1引数が -h の場合は使用方法を出力して終了する
  [ "$1" = "-h" ] && echo "$usage" && return 0

  # $BACKUP_DIR が設定されていない場合は異常終了
  [ -z "$BACKUP_DIR" ] && echo 'backup: $BACKUP_DIR is not set' && return 1

  if [ -p /dev/stdin ]; then
    # パイプからの入力がある場合
    if [ $# -gt 0 ]; then
      # パイプからの入力も引数もあるときは異常終了
      echo "backup: extra operand '$@'"
      return 1
    fi

    while IFS='' read -r line; do
      _backup_inner "$line"
    done
  elif [ $# -gt 0 ]; then
    # 引数が1つ以上ある場合
    for arg in "$@"; do
      _backup_inner "$arg"
    done
  else
    # パイプからの入力も引数もない場合は異常終了
    echo "backup: no input from pipe and no arguments provided"
    return 2
  fi
}

_backup_inner() {
  # ファイル・ディレクトリが存在しなければ終了する
  [ ! -e "$1" ] && echo "backup: cannot access '$1': no such file or directory" && return

  # echo "backup: $1"

  # 引数を絶対パスに変換する 空白を含むと引数が分かれるのでクォートする
  file=$(realpath "$1")
  # コピー先フルパス
  newfile=${BACKUP_DIR}${file}_$(date '+%Y%m%d%H%M%S')
  # ディレクトリを作成
  mkdir -p "$(dirname "$newfile")"
  # コピー
  cp "$file" "$newfile"
}

```

## 悲しみ

chatGPTを少し使ったんですが、苛立って次第に嫌味っぽくなっていく自分のことが嫌いになりそうで途中でやめました。
メールのセキュリティ設定 ( DMARC ) の設定はどうすれば良いのか

# 設定方法 - DNSのTXTレコードに設定する

## レコード名

`_dmarc.example.com`

## 値

以下のように

- 100%のメールにポリシーを適用する
- 認証できないメールは受信拒否する
- 日時レポートの送信先のメールアドレスを指定する

という設定にすると良いだろう (最終的には)

```
"v=DMARC1;p=reject;pct=100;rua=mailto:example@com"
```

# p には何を設定する？

>認証できないメールの処理方法を受信メールサーバーに指示します。
>
>- none—メールをそのまま受信者に配信して、日次レポートに記録します。レポートは、レコード内の rua オプションで指定されたメールアドレスに送信されます。
>- quarantine— メールを迷惑メールに分類して、受信者の迷惑メールフォルダに送信します。受信者は迷惑メールを確認し、正当なメールを特定することができます。
>- reject—メールを拒否します。このオプションを使用すると、通常、受信サーバーから送信サーバーにバウンスメールが送信されます。

( [DMARC ポリシーの定義](https://support.google.com/a/answer/10032169) より )



最終的には reject を設定すべきのはずだ。

なぜなら

- 「なりすましメールが届いたのに、普通に受信できる」
- 「なりすましメールが迷惑メールフォルダに届いており、開いてしまう」

という状態ではセキュリティ設定の意味がないからだ。

# pct の設定は何？

>DMARC ポリシーの対象となる未認証メールの割合を指定します。DMARC を段階的に導入する場合は、一部のメールから開始することをおすすめします。

( [DMARC ポリシーの定義](https://support.google.com/a/answer/10032169) より )


これは最終的には100%にすべきのはずだ。
なぜなら「なりすましメールが50%の確率で届いてしまう」のでは意味がないからだ。


# rua に設定するメールアドレスは何？

`rua=mailto:example@com`

これは日時レポートの送信先。
対象ドメインのものでなくても良い。

メール認証がPASSした数、失敗した数などが1日1回送られてくるようだ。

# 段階的な導入

pの種類やpctのパーセンテージを調整することで、段階的な導入ができるようになっている。

たとえば

- 100%のメールにポリシーを適用するが、迷惑メールフォルダに入る設定にしておく
- 30%のメールにポリシーを適用して、受信拒否されるようにしておく

などとして、いっきにユーザー影響が起きてしまわないように、試験的に導入していくことができる

# 動作確認

設定したらサービスから自分宛にメール送信するなどして、受信したメールヘッダを確認する

Gmailであればメールのソースを表示すると、認証にPASSしたか失敗したかが簡単に分かる

<img width="350" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/a607281a-b655-4ea0-b1cf-668881cdd051">


# 参考

Googleのヘルプが分かりやすい

[DMARC ポリシーの定義](https://support.google.com/a/answer/10032169)

[DMARC を使用してなりすましと迷惑メールを防止する](https://support.google.com/a/answer/2466580?hl=ja)


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
URLのパーセントエンコーディングを理解する

1.これを読む
「2.1. パーセントエンコーディング」
https://triple-underscore.github.io/rfc-others/RFC3986-ja.html#section-2.1

2.よく使うエンコードを丸暗記
```
	%20 = 半角スペース
	%25 = %
	%2A = *
	%3A = :
	%5C = \
	%2C = ,
```
3.エンコード・デコードの問題を人力で3個くらい解くと君はURLエンコードマスター。
```
fq.start_date=*:2024-02-14T13\:23\:59Z
fq.start_date=%2A%3A2024-02-14T13%5C%3A23%5C%3A59Z

fq.stock=0:*
fq.stock=0%3A%2A

sort=score desc,id asc
sort=score%20desc%2Cid%20asc
```
※１バイト以上の文字は、「%〇〇」がそのバイト数分連続する。
Rails: Turbo Rails tutorial introduction

こちらのページの作業を Debian 12 で行ってみました。
[
Chapter 0: Turbo Rails tutorial introduction](https://www.hotrails.dev/turbo-rails/turbo-rails-tutorial-introduction)

## 確認した環境

```text
$ ruby --version
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux-gnu]

$ rails --version
Rails 7.1.3
```

##　必要なソフトのインストール

```bash
sudo apt install nodejs
sudo apt install npm
```

インストールされたバージョン

```text
$ node --version
v18.19.0

$ npm --version
9.2.0

$ npx --version
9.2.0
```

必要な Gem のインストール

```bash
sudo gem install pg jsbundling-rails cssbundling-rails
```

## PostgreSQL の準備

>ユーザー　scott
>パスワード　tiger123
>データベース名 quote_editor_development

データーベースの作成

```bash
su postgres
psql
```

```sql
create database quote_editor_development owner = scott;
```

```text
postgres=# create database quote_editor_development owner = scott;
CREATE DATABASE
```

接続できることを確認

```text
$ psql -U scott quote_editor_development
Password for user scott: 
psql (15.5 (Debian 15.5-0+deb12u1))
Type "help" for help.

quote_editor_development=> 
```

## プロジェクトの作成

```bash
rails new quote-editor --css=sass --javascript=esbuild --database=postgresql
```

Procfile.dev の修正
> -b '0.0.0.0' を加える

```text:Procfile.dev
web: env RUBY_DEBUG_OPEN=true bin/rails server -b '0.0.0.0'
js: yarn build --watch
css: yarn build:css --watch
```

config/database.yml の修正

```yml:config/database.yml
（省略）
default: &default
  adapter: postgresql
  encoding: unicode
  username: scott
  password: tiger123
  host: localhost
（省略）
```


## サーバーの起動

```bash
sudo bin/dev
```

ブラウザーで、http://10.56.160.214:3000/　にアクセス
　IP　アドレスは変更して下さい。

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/8363055b-9e66-1863-ee48-d165f888b911.png)
コレクションとは

## コレクション
* コレクションは、主に要素数が決まっていない場合に使う
(配列は予め要素数が決まっている場合に使う。)
* 配列とは異なり、要素数を自由に増減させられる
* コレクションには種類がある

| 種類 | 特徴 |
|:-:|:-:|
| List |   要素が順序付けられて保持される　|
| Map  |  キーと値を紐づけて要素が保持される |
| Set  |  要素が重複しない、要素が順序付けられていない |

##### ジェネリクス
「クラス名<型指定>」の書式でクラスの型を指定することをジェネリクスという。

##### ArrayListコレクションについて
Listの派生。要素が順序付けられて保持される


ArrayListの要素の追加と取得
```java
// 宣言
<リストの型> 変数 = new ArrayList<リストの型>();

//　コレクションに要素を追加
変数.add(引数);

//要素を取得
変数.get(取得したい要素の番号);
//要素の取得と表示
System.out.println(変数.get(要素の番号));

//要素を削除
変数.remove(削除する要素数)
```
《実装例》
![スクリーンショット 2024-02-14 10.40.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/e33901cc-6c86-aabb-e1c4-8676c6dcd94a.png)
![スクリーンショット 2024-02-14 10.41.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/0c46977b-0e76-b316-1dcc-26198a767565.png)
![スクリーンショット 2024-02-14 10.57.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/63ef607a-7cf8-4e49-0708-9cb24e6419f3.png)

##### HashMapについて
HashMapはキーと値がセットになった要素
```java
// 宣言
HashMap<キーの型,値の型> 変数 = new HashMap<キーの型,値の型>();

// 要素の追加
変数.put(キー,値);

// 要素の取得Coll
変数.get(取得する要素のキー)


// 要素の削除
変数.remove(削除する要素のキー)
```
《実装》
![スクリーンショット 2024-02-14 14.49.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/0a64625a-574e-7a79-a2de-2cf9ce69d215.png)
便利なChatGPTの使い方＝ネタバレ禁止で質問する

# ネタバレせずに物語の内容を教えて
最近はなんでも ChatGPT に聞いてしまいますが、個人的に一番便利だったのは「ネタバレせずに物語の内容を教えて」です。

本を読んだり（特に朗読を聴いたり）、映画を見ていても、特にそれが海外の作品だともはや誰が誰だか分からなくなります。
あるいはちょっと時間が空いちゃうとストーリーまで忘れがちです。

そんな時不用意にWebで検索しちゃうと親切にも余計な情報がたくさんあって、ネタバレしてきます。特にミステリーだと致命的。

# 実例

そんな時はこんな風に ChatGPT へ聞きます。
プロンプトは適当ですが、目的を果たすにはこれで十分みたいです。

```
オリエント急行殺人事件を読んでいる**途中**です。
まだ誰も殺害されていません。
大佐と呼ばれているのは誰ですか？簡単に教えて。
# 重要項目
- 物語の結末に影響するような内容や不要な感想は述べないでください
- 絶対にネタバレしないでください。決して私の楽しみを奪わないでください
```

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14471/68f09b10-de23-7ee6-b372-0fa039f385f9.png)

あるいはこんな感じです。

```
ハリー・ポッターと賢者の石を読んでいる**途中**です。
今、なんか学校に行くまでの電車に乗りました。
ここまでのあらすじをごく簡潔に教えて。
# 重要項目
- 物語の結末に影響するような内容や不要な感想は述べないでください
- 絶対にネタバレしないでください。決して私の楽しみを奪わないでください
```

![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14471/506d017b-f857-fc05-bd67-b9bf25f566ad.png)

## 補足

なお ChatGPT 3.5 だとちょっと微妙な時があります。
よって確実にネタバレを避けるため、私は ChatGPT4 ベースのAIを利用したいので、キャプチャは vim になっていますが Web版 でももちろん使えます。

[「AI × Vim」が便利なので VSCode へ移行できない](https://qiita.com/0829/items/902a07ec3310a946f4f9)


# まとめ

注意としては、現状ではAIが知っている有名な作品でしか使えないことです。
（工夫次第でできるかもですが）

とはいえこれが標準機能として動画サイトや電子書籍に実装され、
「ここまでのあらすじを聞く」ボタンが付いたそんな未来が私には見えます。
cscの作法 その455

# 概要
cscの作法、調べてみた。
DxLibDotNet.dll、使ってみた。
練習問題やってみた。

# 練習問題
ランチャーアプリを作れ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a2bb6eea-3165-a34d-11b8-da7890195844.png)

# サンプルコード

```
using System;
using System.Diagnostics;
using DxLibDLL;

class Test {
	[STAThread]
	static void Main() {
		int X, 
			Y;
		DX.ChangeWindowMode(DX.TRUE);
		DX.SetGraphMode(260, 260, 32);
		if (DX.DxLib_Init() == -1) 
			return;
		int png = DX.LoadGraph("circledock.png");
		DX.DrawGraph(20, 20, png, DX.TRUE);
		DX.SetFontSize(24);
		DX.DrawString(100, 60, "notepad", DX.GetColor(25, 255, 255));
		DX.DrawString(150, 100, "calc", DX.GetColor(255, 25, 255));
		DX.DrawString(50, 140, "paint", DX.GetColor(255, 255, 25));
		while (DX.ProcessMessage() == 0 && DX.CheckHitKey(DX.KEY_INPUT_ESCAPE) == 0)
		{
			if ((DX.GetMouseInput() & DX.MOUSE_INPUT_LEFT) != 0)
			{
				DX.GetMousePoint(out X, out Y);
				if (X > 20 && X < 200 && Y > 60 && Y < 100)
				{
					Process.Start("notepad");
					break;
				}
				if (X > 20 && X < 200 && Y > 100 && Y < 140)
				{
					Process.Start("calc");
					break;
				}
				if (X > 20 && X < 200 && Y > 140 && Y < 180)
				{
					Process.Start("mspaint");
					break;
				}
			}
		}
		DX.DxLib_End();
	}
}





```

以上。
Pytorchを使用する際に「OSError: libcudart.so.12: cannot open shared object file: No such file or directory」と出るときの対処

```nvidia-smi```と```nvcc -V```が使える環境下において
何も考えず脳死でPytorchを```pip install torch```と実行したときに，libcudart.soが無いと怒られます。

これはNVIDIA GPU周りのトラブルではなく、脳死でインストールした自分のせいです。

# 対処法
1. ```nvcc -V```でcudaのバージョンを確認してください。
1. [PyTorch](https://pytorch.org/get-started/previous-versions/)のページに行き，cudaのバージョンと合うものを選んでインストールしてください。
例：cuda:11.8の場合
```pip install torch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 --index-url https://download.pytorch.org/whl/cu118```
1. ```python```コマンドを入力し，対話モードにします。
1. ```import torch```をした後、```torch.cuda.is_availabe()```を入力し、```True```と出ればPytorchが使えます。
レコードの条件通知をコピーするカスタマイズ

:::note info
プロセス管理をコピーするするtipsを参考にレコードの条件通知の設定を別アプリにコピーしてみました
:::



https://cybozu.dev/ja/kintone/tips/development/customize/process-management/copy-process-management-settings-to-another-app/

```
(() => {
  "use strict";

  const COPY_APPID = 37; //コピー先のアプリの番号に変えてください

  function getProcessManagement() {
    const body = {
      app: kintone.app.getId(),
    };
    return kintone
      .api(
        kintone.api.url("/k/v1/app/notifications/perRecord.json", true),
        "GET",
        body
      )
      .then(
        (resp) => {
          console.log(resp);
          return resp;
        },
        (error) => {
          return kintone.Promise.reject(error.message);
        }
      );
  }

  function putProcessManagement(original) {
    const body = {
      app: COPY_APPID,
      notifications: original.notifications,
    };

    return kintone
      .api(
        kintone.api.url("/k/v1/preview/app/notifications/perRecord.json", true),
        "PUT",
        body
      )
      .then(
        (resp) => {},
        (error) => {
          return kintone.Promise.reject(error.message);
        }
      );
  }

  function deployProcessManagement() {
    const body = {
      apps: [
        {
          app: COPY_APPID,
        },
      ],
    };
    return kintone
      .api(kintone.api.url("/k/v1/preview/app/deploy", true), "POST", body)
      .then(
        (resp) => {
          alert(
            "アプリ番号「" +
              COPY_APPID +
              "」にレコードの条件通知の設定をコピーしました。"
          );
        },
        (error) => {
          return kintone.Promise.reject(error.message);
        }
      );
  }

  kintone.events.on(["app.record.index.show"], (event) => {
    if (document.getElementById("CopyRecordManagement") !== null) {
      return;
    }
    const menuButton = document.createElement("button");
    menuButton.id = "CopyRecordManagement";
    menuButton.innerHTML = "Copy レコードの条件通知";
    menuButton.onclick = function () {
      if (
        window.confirm(
          "アプリ番号「" +
            COPY_APPID +
            "」にレコードの条件通知の設定をコピーしますか？"
        )
      ) {
        getProcessManagement()
          .then(putProcessManagement)
          .then(deployProcessManagement)
          .catch((error) => {
            alert(error);
          });
      }
    };
    kintone.app.getHeaderMenuSpaceElement().appendChild(menuButton);
  });
})();

```
Next.jsとVercelでポートフォリオつくってみた

# はじめに
Next.jsとVercelでポートフォリオ作ってみました。
Next.jsは半年くらいの経験です。
## 作った背景
自分の成果物やスキルをまとめておきたいと思い作ってみました。
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3692669/6c78aa2e-0bc6-839b-009d-3718ca239e3e.png)
## 使用した技術
・Next.js
・TypeScript
・tailwind css
・Vercel

## 作ってみて
これからはデザインをちゃんとしていこうと思います。
今後も更新していく予定です。

## 追記
初めての投稿です‼
なにか改善すればいいところがあればぜひコメントしてください‼
dockerのコンテナにroot権限で入らないようにする

# 困ったこと
- ``docker run -it -v /mnt:/mnt [環境名]:[タグ名] /bin/bash``とかを実行するとコンテナ内にroot権限で入る
  ```
  shibaura@hogehoge:~$ docker run -it --rm -v /mnt:/mnt [環境名]:[タグ名] /bin/bash 👈普通のユーザ権限
  root@11dc458255cf:/#  👈root権限でコンテナに入っちゃう
  ```

- このコンテナ内でマウントしたホスト側のファイルをいじると、**ホスト側のファイルがrootユーザのファイルとして書き換えられちゃう**


# 解決策
### 方法
次のようにオプション3つを付ければOK
```
docker run -it --rm -v /mnt:/mnt \
    -v /etc/group:/etc/group:ro \
    -v /etc/passwd:/etc/passwd:ro \
    -u $(id -u $USER):$(id -g $USER) \
    [環境名]:[タグ名] /bin/bash
```

### 実行例
  ```
  shibaura@hogehoge:~$ docker run -it --rm -v /mnt:/mnt -v /etc/group:/etc/group:ro -v /etc/passwd:/etc/passwd:ro -u $(id -u $USER):$(id -g $USER) [環境名]:[タグ名] /bin/bash
  shibaura@82ed7bcb9600:/$  👈ユーザ"shibaura"を引き継いでコンテナに入る！
  ```

# おわりに
- わーい
- コマンドが長くなるのでshellスクリプトとかに書いて実行するようにしたほうがいいかも
サブディレクトリ型の多言語サイトにおける言語切り替え時の遷移先URIの設定

## 問題状況
　同一のドメインで日本語のサイトを運営しているが、サブディレクトリ型で複数の言語に対応したサイトを構築することになった。ヘッダーには言語切替のボタンを設置したが、これがクリックされた時に同じ内容のページに遷移させたい。

　例えば、日本語、英語(English: en)、フランス語(français: fr)、中国語(中文: zh)に対応したWebサイトのTOPは、それぞれ、

 - `https://www.mysite.com/`
 - `https://www.mysite.com/en/`
 - `https://www.mysite.com/fr/`
 - `https://www.mysite.com/zh/`

であり、それぞれの「ごあいさつ」や「会社情報」に相当するABOUT USのアドレスは、
 - `https://www.mysite.com/aboutus/`
 - `https://www.mysite.com/en/aboutus/`
 - `https://www.mysite.com/fr/aboutus/`
 - `https://www.mysite.com/zh/aboutus/`

である。

　今、英語版サイトのABOUT USを閲覧しており、フランス語に切り替えた。この時、一律にフランス語版サイトのTOPに遷移するのではなく、フランス語版サイトのABOUT USに遷移させたい。つまり、

```plantuml
@startmindmap
+ > 言語切替 >
++ > フランス語：TOP
-- 英語：TOP >
-- 英語：ABOUT US >
-- 英語：FAQ >
-- 英語：CONTACT >
@endmindmap
```

ではなく、

```plantuml
@startmindmap
+ > 言語切替 >
++ > フランス語：TOP
++ > フランス語：ABOUT US
++ > フランス語：FAQ
++ > フランス語：CONTACT
-- 英語：TOP >
-- 英語：ABOUT US >
-- 英語：FAQ >
-- 英語：CONTACT >
@endmindmap
```

という感じで遷移させたい。


## 解決方法

　遷移先のURIを作成するには……
1. 現在閲覧しているWebページのURIを取得し、
1. そこから「サブディレクトリ」の部分をいったん取り除き、
1. 「プロトコルとドメイン」と「パス」に分解し、
1. この2つの間に「サブディレクトリ」を挿入する。 

```example.php
// 1. 本来のURIを取得する
$uri = $_SERVER['REQUEST_URI'];

// 2-1. 多言語対応しているサイトのサブディレクトリを配列で設定する（#で囲むこと）
$patterns_to_remove = ["#/en#", "#/fr#", "#/zh#"];

// 2-2. URIから上記で設定したサブディレクトリを取り除く
$uri = preg_replace($patterns_to_remove, "", $uri);

// 3-1. プロトコルとドメインを抽出する
$protocol_domain = parse_url($uri, PHP_URL_SCHEME) . parse_url($uri, PHP_URL_HOST);

// 3-2. パスを抽出する
$path = parse_url($uri, PHP_URL_PATH);

// 4. サブディレクトリを挿入する
$target_uri_ja = $protocol_domain . $path;
$target_uri_en = $protocol_domain . '/en' . $path;
$target_uri_fr = $protocol_domain . '/fr' . $path;
$target_uri_fr = $protocol_domain . '/zh' . $path;
```
プロキシ環境でコンテナ間通信ができなかった件

# 社内プロキシ環境でdockerコンテナ間の通信
社内環境でコンテナ間通信をしたかったのですが、全く通信が行えなくて困ったので備忘録です。

## まずは簡単な結論から
ざっくり原因と対応策を示すと、
- コンテナ内からの通信がプロキシを経由していた
- no_proxyに各コンテナのIPアドレスを設定し解決

またいつも悩まされている社内プロキシ環境が原因であった。

# 経緯詳細
悩んだ問題は2つの自作したwebapiで動作するコンテナについて相互通信を行い、データ処理をさせたかったのだが、何故か通信ができなかった点である。

インターネットで検索してもピンポイントの解決策がヒットせず、「docker composeで立ち上げればネットワークが勝手に作られるから、ほら簡単に通信できる環境になるよね！」しかなかった。

## 開発環境
- os : Ubuntu:22.04.3 LTS
- docker : 25.0.2

## 事象
立ち上げたコンテナから隣のコンテナにアクセスしょうとしたが何も返ってこなかった。

~~~bash
$ docker exec -ti web1 curl http://web2/index.html
~~~

## 原因発覚
curlコマンドの詳細をログ出力してみると。。。

~~~bash
$ docker exec -ti web1 curl http://web2/index.html -v

*Uses proxy env variable http_proxy == '<address_to_proxy>'
.......
~~~

あれ？もしかして、プロキシサーバー経由してない？
これか！！

## 対処方法
ということで、docker-compose.ymlファイルに設定を記載して解決した。

~~~docker-compose.yml
version: "3"

networks: 
    route1:
        ipam: 
            driver: default
            config: 
                - subnet: 192.168.1.0/24


services: 
    web1:
        image: nginx
        # コンテナ名を明示的に指定
        container_name: web1
        # ビルドで使う設定
        environment: 
            - HTTP_PROXY=$HTTP_PROXY
            - HTTPS_PROXY=$HTTPS_PROXY
            - http_proxy=$http_proxy
            - https_proxy=$https_proxy
            # プロキシサーバーを通さないアドレスにコンテナ名とIPアドレスを指定
            - NO_PROXY="127.0.0.1,localhost,web1,192.168.1.2,web2,192.168.1.3"
            - no_proxy="127.0.0.1,localhost,web1,192.168.1.2,web2,192.168.1.3"
        # ネットワーク設定でIPアドレスを固定
        networks: 
            route1:
                ipv4_address: 192.168.1.2
    
    web2:
        image: nginx
        # コンテナ名を明示的に指定
        container_name: web2
        # ビルドで使う設定
        environment: 
            - HTTP_PROXY=$HTTP_PROXY
            - HTTPS_PROXY=$HTTPS_PROXY
            - http_proxy=$http_proxy
            - https_proxy=$https_proxy
            # プロキシサーバーを通さないアドレスにコンテナ名とIPアドレスを指定
            - NO_PROXY="127.0.0.1,localhost,web1,192.168.1.2,web2,192.168.1.3"
            - no_proxy="127.0.0.1,localhost,web1,192.168.1.2,web2,192.168.1.3"
        # ネットワーク設定でIPアドレスを固定
        networks: 
            route1:
                ipv4_address: 192.168.1.3


~~~

これで立ち上げたコンテナで実行してみると！
```bash
$ docker exec -ti web1 curl http://web2/index.html -v

*Uses proxy env variable no_proxy == "127.0.0.1,localhost,web1,192.168.1.2,web2,192.168.1.3"
.......
<正常な出力結果！！！！やった！>
```

ここで躓いたのはコンテナ名だけでネットワークには通信ができるかと思ったが、IPアドレスも設定しなくてはいけなかったこと。

IPアドレスの設定のためにネットワークとIPアドレスの設定も必要であった。

# 結論
またもや、社内環境でやられた。。。
いつもこれ系統で時間を費やされるから本当に腹立たしい。
何度も悩まされてるのに忘れた頃にまたやってくるプロキシさん。
今後もうまく付き合っていかなければいけないと思うと悩ましいですね。
一応ソースコードを[こちら]()においておきます。
windows 10 Updateエラー　三つの解決策。

経緯
Dockerインストールの際、windows10のアップデートが求められたが、うまくいかない

エラー
We've detected that you have an incompatible version of Windows. Docker Desktop requires Windows 10 Pro/Enterprise/Home version 19044 or above. To continue with the installation, upgrade Windows to a supported version and then re-run the installer.


「設定」→「windows update」から更新しようとしたができない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3568691/10239099-2b1d-dd77-2ee9-0a669f7c4afd.png)


1.window10 upgradeをサイトからダウンロード
https://qiita.com/akym03/items/70d6cab14d0c26e7c8c6

エラー
「ファイルを作成できません。
インストールフォルダーへの書き込みアクセス許可があることをご確認ください。」


2.regitの値を0にする
バックアップを取るのを推奨。
https://answers.microsoft.com/ja-jp/windows/forum/all/win10%E6%9B%B4%E6%96%B0update%E3%82%A8%E3%83%A9/a24ca826-f2d9-4f33-a7b6-ce8343b3557d


3.管理者ユーザーを追加して、そのアカウントでupgradeを実行
https://www.fmworld.net/cs/azbyclub/qanavi/jsp/qacontents.jsp?PID=8610-8270

私は3「管理者ユーザー追加」で解決しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3568691/ea4bea31-2a56-7136-2b3c-1a3165aab15c.png)
Ironで記録したrosbagをHumbleで再生する

# 概要

ROS2 Ironでは`ros2 bag record`で記録するrosbag2のデータフォーマットがMCAPになっていて、
デフォルトがSQLite3のROS2 Humbleでは再生できない。


# 対応

再生するHumbleでrosbag2-storage-mcapをインストールするだけ

```bash
sudo apt install ros-humble-rosbag2-storage-mcap
```



# 参考

https://proc-cpuinfo.fixstars.com/2023/01/rosbag2_storage_mcap_usage/
Debian 12: PostgreSQL 15 をインストール

## インストール

```bash
sudo apt install postgresql
sudo apt install postgresql-client
sudo apt install libpq-dev
```

## PostgreSQL が動いていることを確認

```bash
sudo systemctl status postgresql
```

## データベースの作成

postgres ユーザーにパスワードをつける

```bash
sudo passwd postgres
```

postgres ユーザーに切り替える

```text
$ su postgres
Password:
```

psql を起動

```text
$ psql
could not change directory to "/home/uchida": Permission denied
psql (15.5 (Debian 15.5-0+deb12u1))
Type "help" for help.

postgres=#
```

ユーザーの作成
>ユーザー　scott
>パスワード　tiger123

```text
postgres=# create user scott password 'tiger123';
```

確認

```text
postgres=# select usename,usesysid from pg_user;
 usename  | usesysid 
----------+----------
 postgres |       10
 scott    |    16399
(2 rows)
```

データーベースの作成
>データベース名　city

```text
postgres=# create database city owner = scott;
CREATE DATABASE
```

確認

```text
postgres=# \l
```

## ユーザーで接続できるようにする

設定前

```text
$ psql -U scott city
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  Peer authentication failed for user "scott"
```


設定の変更

peer を md5 に変更

```text:/etc/postgresql/15/main/pg_hba.conf
（省略）
#local	all	all	peer
local	all	all	md5
（省略）
```

PostgreSQL を再起動

```bash
sudo systemctl restart postgresql
```

設定後

```text
$ psql -U scott city
Password for user scott: 
psql (15.5 (Debian 15.5-0+deb12u1))
Type "help" for help.

city=>
```

## 簡単なテーブル操作

テーブルの作成

```sql
create table cities (id varchar(10) primary key, name text, population int, date_mod date);
```

テーブルの一覧

```text
city=> \dt
        List of relations
 Schema |  Name  | Type  | Owner 
--------+--------+-------+-------
 public | cities | table | scott
(1 row)

city=>
```

データの挿入

```sql
insert into cities values ('t3461','広島',72814,'2001-9-14');
insert into cities values ('t3462','福山',41738,'2001-7-21');
insert into cities values ('t3463','東広島',92513,'2001-6-12');
insert into cities values ('t3464','呉',93167,'2001-9-29');
insert into cities values ('t3465','尾道',95419,'2001-3-18');
insert into cities values ('t3466','竹原',82314,'2001-2-21');
insert into cities values ('t3467','三次',76152,'2001-8-16');
insert into cities values ('t3468','大竹',37541,'2001-7-7');
insert into cities values ('t3469','府中',46518,'2001-10-9');
```

データの表示

```sql
select * from cities;
```

```text
city=> select * from cities;
  id   |  name  | population |  date_mod  
-------+--------+------------+------------
 t3461 | 広島   |      72814 | 2001-09-14
 t3462 | 福山   |      41738 | 2001-07-21
 t3463 | 東広島 |      92513 | 2001-06-12
 t3464 | 呉     |      93167 | 2001-09-29
 t3465 | 尾道   |      95419 | 2001-03-18
 t3466 | 竹原   |      82314 | 2001-02-21
 t3467 | 三次   |      76152 | 2001-08-16
 t3468 | 大竹   |      37541 | 2001-07-07
 t3469 | 府中   |      46518 | 2001-10-09
(9 rows)
```
リストのアイテムごとの権限

既定ではリストを参照でいる人は他のユーザが作成したアイテムも閲覧できます。またリストにアイテムを追加または編集などができる人は他のユーザが作成したアイテムも編集できます。


ただし、リストへのアクセス権限が無いユーザに権限を付与したり、読み取り権限を付与しているユーザに対して編集権限を付与することはできません。

# 権限の設定例

### アイテムはすべて参照できるけれど、他のユーザが追加したアイテムは編集させたくない

|権限|設定|
|:--------------|:----------------------|
|読み取りアクセス権|すべてのアイテム|
|作成/編集のアクセス権|ユーザ本人のアイテム|

この設定により他のユーザが作成したアイテムについては、編集しても保存時にアクセス拒否のメッセージが表示され保存ができません。

### アイテムを作成した本人しか、アイテムは表示できないし削除もできない

|権限|設定|
|:--------------|:----------------------|
|読み取りアクセス権|ユーザ本人のアイテム|
|作成/編集のアクセス権|ユーザ本人のアイテム|

これで他のユーザのアイテムが表示されなくなり、自分が作成した以外は閲覧できなくなります。ただし、この設定の影響を受けないユーザがいます。それはフルコントロールを付与されているユーザとサイト管理者です。

サイトの権限グループとしてはサイトの所有者に所属しているメンバーです。（リスト単位で権限を設定してない場合）これらに該当するユーザは全リストが参照できるだけでなく、編集や削除も可能です。


### 権限の詳細
この設定を無視してアイテムの表示や編集ができるユーザの権限としては「リストの管理」と「リストの動作を無視」権限が必要です。

+ [【Power Automate】SharePoint のアクセス権に関するアクションについて](https://www.live-style.jp/powerautomate_sharepoint_accessright/)

# 共有する範囲を考える

Share Pointでは基本は「サイト単位」でアクセス権を設定します。サイトに対して適用したアクセス権限の設定はサイト内のコンテンツに自動的に適用されるため、サイト単位で一元管理できます。

必要に応じてリストやライブラリー単位、フォルダー単位、アイテム/ファイル単位などの細かい範囲でも個別の共有も可能です。

内部的にサイト単位でのアクセス制御リストという「誰が何の権限でアクセスするのか」という情報の一覧を保持しています。これをアクセス制御リストと呼びます。これはShare Pointのリストではなく、Azure SQL上に構築されるデータベーステーブルの１つです。

# アクセス許可レベル

アクセス許可レベルはサイトごとに管理されており、既定で複数用意されています。サイトの管理者は既存のアクセス許可レベルだけでなく、独自に権限を組み合わせを作成してカスタムのアクセス許可レベルを作成することもできます。


モダンサイトで用意されていアクセス許可レベル

|アクセス許可レベル|説明|
|:--------------|:----------------------|
|フルコントロール|サイトに対する全ての権限が付与される(このアクセス許可レベルを付与されたユーザよりも完全にサイトを管理できるのがサイト管理者)|
|デザイン|表示、追加、更新、削除、承認などが可能|
|編集|リストやライブラリの追加、編集、削除ができる。リストアイテム及びドキュメントの表示、追加、更新、削除が可能。チームサイトでは多くのユーザにこの権限を付与する。このアクセス許可レベルを付与する相手はサイトの共同編集者となる。|
|投稿|リストアイテムおよびファイルの表示、追加、更新、削除ができる|
|閲覧|サイト内のコンテンツの閲覧のみができる。ファイルに関してはダウンロード可能|
【Unity】App UIをエディター拡張のUIとして使用する【App UI】

# 自己紹介
App UIでエディター拡張作ってる大学生。

# 今回の記事
App UIでエディター拡張を作る際に中々反映されないという事態に至りました。
App UIの記事に見えて実はUI Toolkitの記事ですね完全に。

ちなみに、公式ドキュメントには特にこれに関する記述がない…！

# 前提条件
### 使用したUXML
```XML
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:appui="Unity.AppUI.UI" xsi="http://www.w3.org/2001/XMLSchema-instance" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">

    <appui:Panel name="root-panel" >

        <appui:Button title="Button" />

    </appui:Panel>

</ui:UXML>
```
### 適当なエディターウィンドウ
```Csharp
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;

public class TestEditorWindow : EditorWindow
{
    [SerializeField] private VisualTreeAsset _document;
    [SerializeField] private ThemeStyleSheet _theme;
    [MenuItem("Examples/My Editor Window")]
    public static void ShowExample()
    {
        var wnd = GetWindow<TestEditorWindow>();
        wnd.titleContent = new GUIContent("MyEditorWindow");
    }

    public void CreateGUI()
    {
        // Each editor window contains a root VisualElement object
        VisualElement root = rootVisualElement;

        root.styleSheets.Add(_theme);
        //MainContainerをテンプレートからコピー
        var defaultContainer = _document.Instantiate();
        root.Add(defaultContainer);
    }
}
```
# やり方
実は上のC#がほぼ答えなのですが、Themeファイルを作って追加してあげるだけです。

## 1. テーマファイルを作成する
Project Window上で右クリック `[create] --> [UI Toolkit] --> [TSS Theme File]`

## 2. テーマファイルにApp UIのテーマを指定
Inspector
ここだけひっかけがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083521/083d16ce-d597-30bd-7217-3170a19d6bfe.png)

なんとApp UIが一覧に表示されません。ﾅﾝﾃﾞﾔ

ということで、`Packages/com.unity.dt.app-ui/PackageResources/Styles/Themes/`にあるテーマを手動でドラッグアンドドロップして設定しましょう。

## 3. C#からテーマファイルを指定して追加。
ここはUXMLに指定しても良いのですが、好きにやっていただいて大丈夫です。

https://docs.unity3d.com/ja/current/Manual/UIE-add-style-to-uxml.html

https://docs.unity3d.com/ja/current/Manual/UIE-apply-styles-with-csharp.html

## 4. 完成
ここまでで反映されたと思います。
これで好きにApp UIを使えますね。

と思ったのですが、GraphViewでは使えないっぽい（GraphViewのテーマに上書きされちゃう）

https://twitter.com/KaidoAtsuya/status/1757616330684141802

# おわりに
今開発してるエディター拡張でGraphViewを使う気まんまんだったのになぁ…（）
FileMaker のレコード順を修正する

FileMaker で作ったアプリがあって、データを日付順で呼び出しているのだが、アレなスクリプトでレコード番号を日付順の代わりに使っている。

レコード番号は登録順となっていて、日付順に登録しているので一見動いているように見える。

しかしながら FileMaker はユーザ操作で簡単にレコードを削除したり追加したりできてしまう。
特定の日付のレコードを操作ミスで消してしまって、代わりに新たにその日付のレコードを追加したら該当日付のレコード番号が一番最後になってしまう。


そんなトホホな状況で、レコード順と日付順が一致するように治すお話。

# 環境

- FileMaker Pro 11
- MS-Windows7


# ソート

「レコード」-「レコードのソート」

一旦はこれで問題なく動作しているように見えるけれども、FileMaker を立ち上げ直すと元に戻ってしまう。

これを恒久化するには?


# レコードのエクスポート

先のソートした状態で、「ファイル」-「レコードのエクスポート」。
「ファイルの種類を　FileMaker Proファイル(*.fp7)」として「エクスポート」。
「現在のレイアウト」ではなく「現在のテーブル」を指定して、「全て移動」を選ぶ。


# レコードの削除

エクスポートが終わったら、元のデータベースのレコードを削除しておく。
「レコード」-「全レコード削除」。


# レコードのインポート

レコードが空になった状態で、さきほどエクスポートした fp7 ファイルをインポートする。

「ファイル」-「レコードのインポート」-「ファイル」でさきほどのエクスポートファイルを選び、「開く」。
配置順を「照合名順」、インポート方法で「新規レコードとして追加」として「インポート」。
「インポート中、入力値の自動化オプションを実行」をつけて(外しておいたほうがいいかな? とりあえず今回はつけました)、繰り返しフィールドの値のインポート方法を「元のレコードの設定を維持する」を選んで「インポート」。


# 注意点

特定の fp7 だけソートすればいいかなと思って該当ファイルだけ別マシンに持っていって作業しようとしたら、エクスポート時にエラー。別の fp7 ファイルを参照しているらしく、すべてのファイルが参照できる状態でエクスポートしたらうまくいきました。
なぜかfetchしてもブランチの情報が取得できない

# はじめに
Jenkinsでビルドをかけているのですが、ブランチの切替時に次のようなエラーが出ました
```
error: pathspec 'ブランチ' did not match any file(s) known to git
```

毎回fetchして取得しているはずなのですが、
なぜか急にできなくなったので、その解決法になります。
なお、shallow cloneでクローンしたプロジェクトになります。

# 環境
- macOS Monterey 12.6
- Jenkins 2.372

# 解決
最初に解決方法ですが、いろいろ試した結果、解決したのは以下のコマンドでした
```
$ git remote set-branches origin '*'
```
ローカルリポジトリが全てのリモートリポジトリのブランチを追跡するという設定になるようです。

# 解決しなかったけど試したこと
他に次のようなことを試してみました

### 直接fetchしてみる
シェルスクリプトからやっているのが悪いのかと思い、ターミナルから`git fetch`を実行してみましたがもちろんだめでした。

### unshallowしてみる
はじめにも記載しましたが、shallow　cloneで最後のコミットのみ取得してきているため、
```
$ git fetch --unshallow
```
で全ての履歴を取得するようにしてみました。
が、これだけではだめだったようです。

### なにか悪いキャッシュが残ってる？のかと思って削除してみる
```
$ git rm -r --cached .
```
キャッシュの問題ではなかったので、何も起きませんでした。

## 他にもこれで解決しそう？
### 全てのリモートをフェッチする
全てのリモートをフェッチするとなっているが、これでも取得できる？
おそらく解決しなさそうですが、一応記載
```
$ git fetch --all
```

### 手動で `.git/config` ファイル変更
解決法にあるコマンドの結果を直接ファイルに記載するという方法です
```
[remote "origin"]
    url = <リモートリポジトリのURL>
    fetch = +refs/heads/*:refs/remotes/origin/*
```

### 違うコマンドで`.git/config` ファイル変更
```
git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
```
こちらのコマンドでも同様にconfigファイルが変更されるようです

### クローンするときの設定を変える
`--no-single-branch`のオプションを加えることで、全てのブランチの最新履歴を取得するようです
```
$ git clone --depth 1 --no-single-branch <リモートリポジトリのURL>
```



# おわりに
今までできていてなぜ急にできなくなったのかは現在も不明(何らかの操作時に設定が書き換わった？)なんですが、同様の現象起きた人がいた場合には助けになれば幸いです。

# 参考
https://tracpath.com/docs/git-fetch/

https://qiita.com/MtDeity/items/f37336294001ffa514bf

https://zenn.dev/snowcait/articles/d44d6b2bed2e4b29ada4

https://qiita.com/kohei_wd/items/f1d224c9257d1e242b58
【ChatGPT有＋DALL-E3】絵文字や顔文字、ふたたび。


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

　今回は、絵文字や顔文字をふたたびやります。

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

　まずは、
　　OpenAIからのニュース。

　[ChatGPT memory:](https://twitter.com/gdb/status/1757533849217802324?t=188cpx_oRqNiSVB2pXA4kw&s=19)

　上記は、
　　英語なので、
　　　簡単な要約を書きます。

　ChatGPTは、
　　過去の履歴から
　　　あなたのことを
　　　　学びます。

　それは
　　スイッチのオンオフを
　　　可能にしてあります。

　なお、
　　一部の無料版とPlusで
　　　公開しています。

　とのこと。

　動画があり、
　　どうやら
　　　履歴を選択して
　　　　そこから勉強するらしいです。

　以前から
　　この情報が
　　　ありましたが
　　　　本格的な導入になりますね。

　ただ、
　　X-Twitter上ではまだ、
　　　日本人の誰も
　　　　開放されていないようで
　　　　　それらしいポストも
　　　　　　ありません。

　今後に
　　期待したいところですね。
***
　さて、
　　本題です。

　以前に、
　　“絵文字・顔文字で描画する”
　　　といった内容の記事を
　　　　書きました。
[【ChatGPT有＋DALL-E3】こんなの、あり？　絵文字や顔文字で？](https://qiita.com/kabumira/items/a7160e28502c72f5fbe1)

　今回は、
　　さらにわかったことを
　　　書きます。

　ゴールシークプロンプトで
　　有名なシュンスケ氏が
　　　去年の4月に
　　　　ポストしていました。
[シュンスケ氏の記事](https://twitter.com/openagi_lab/status/1643771342637105152?t=iyG5Yxim98nWpTfVm9LgJg&s=19)

　ここでは
　　“トークン数を減らす”
　　　という目的で
　　　　使われていました。

　ChatGPTを使っている私たちは
　　わかりませんが
　　　APIの使用には
　　　　使用量に対して
　　　　　料金が発生するそうです。

　GPTのモデルが
　　上位になれば、
　　　それだけ高く設定されていて
　　　　使用量（トークン数）を
　　　　　いかに減らすかが
　　　　　　問題になってきます。

　私たち、
　　通常のユーザーに
　　　関係あるのか？

　ふつうに使う分には、
　　関係ありません。
***
　ですが、
　　ChatGPTさんへの指示を
　　　絵文字・顔文字で行える
　　　　というのは、面白い。

　例えば、
　　“👸に🙇。描画”とやれば、
　　　女王陛下に謁見して
　　　　膝を屈する男性が描けます。

　まぁ、
　　この程度であれば、
　　　文章の方が早いですねw

　しかし、
　　長い文章の場合、
　　　どうなるでしょうか？
***
***user***
🧜の❤️を🏹。❓。教えて

***ChatGPT***
この絵文字の組み合わせ（🧜の❤️を🏹）は、「人魚が愛を矢で射る」というイメージを想起させます。これは比喩的な表現で、恋に落ちる瞬間や、人魚（通常、魅力的で神秘的な存在として描かれる）が誰かの心を射抜く（つまり、誰かを惹きつける）様子を表していると解釈できます。古典的な神話や物語において、キューピッドが矢で人々の心を射抜くことで恋愛感情を芽生えさせるイメージと似ていますが、ここではその役割を人魚が担っているようです。

絵文字の質問マーク（❓）が示すように、これは「人魚が愛の矢で心を射抜くことは可能か？」という疑問や、「誰かが人魚の魅力に心を奪われることはあるのか？」といった意味の問いかけを表しているかもしれません。この表現は、恋愛や魅力に関する神秘性や魔法のような力を象徴しています。
***
　私的には
　　“人魚（彼女）のハートを
　　　射止めたい。どうすれば？”と
　　　　意図していました。

　ChatGPTさんは
　　上記のように
　　　書き出してくれました。

　しかし、
　　“教えて”の部分を
　　　“描画”と書き換えたところ、
　　　　”人魚がハートマークを
　　　　　射抜こう”とする画像が
　　　　　　生成されました。

　再度、同じ質問をしたところ、
　　この意味の文章を組み立てて
　　　しまいました。

　何度か繰り返しましたが
　　そうなります。

　つまり、
　　絵文字・顔文字の文章は
　　　こちらの意図どおりには
　　　　ならない、ということに
　　　　　なりますね。残念。

　日本語の文章は
　　それだけ難しい、
　　　ということでしょうかねぇw

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

　今回は、ここまで。
[React]  ボタンのCSS調整！

# はじめに

今回は、ボタンの見栄えを向上させるCSSの調整について紹介します！

# 1. ボタンのスタイリング

まずは、基本的なボタンのスタイリングを行います。
以下のCSSコードを使用して、ボタンの高さ、幅、フォントサイズ、影、角丸などを設定します！
また、`.button:hover`を用いることで、カーソルが乗ったときのホバーも表現できます！

```css
/* src/styles/Button.module.css */

.button {
  width: 35%;
  height: 100px;
  margin-top: 20px;
  font-size: 30px;
  padding: 15px 20px;
  border-radius: 10px;
  box-shadow: 0px 6px 3px rgba(0, 0, 0, 0.3);
  transition: box-shadow 0.3s ease-in-out, transform 0.3s ease-in-out;
  background-color: #499ef9;
}

.button:hover {
  box-shadow: 0px 10px 3px rgba(0, 0, 0, 0.5);
  transform: scale(0.98);
}
```
# 2. ボタンコンポーネントの作成
次に、このcssを適用するボタンコンポーネントを作成します！

```javascript
// components/Button.jsx

import React from "react";
import styles from "../styles/Button.module.css";

const Button = () => {
  return (
    <button className={styles.button}>
      Click me
    </button>
  );
};

export default Button;
```
# 3. ボタンを使用
最後に、作成したボタンコンポーネントを使用します！
```javascript
// pages/index.jsx

import React from "react";
import Button from "../components/Button";

const HomePage = () => {
  return (
    <div>
      <h1>Welcome to My App</h1>
      <Button />
    </div>
  );
};

export default HomePage;
```
![スクリーンショット_20240214_114850.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570986/f7621816-7d3e-0d20-2067-709935d21932.png)

# まとめ

今回は、ボタンの見栄えを向上させるCSSの調整について紹介しました！
記事を参考にして、自分のプロジェクトに合わせてボタンをカスタマイズしてみてください！
Python アプリで簡易的な暗号化

Python アプリにて「環境変数に設定した鍵を使用してデータを暗号化/復号化したい」場合の手順メモ。

:::note warn
この記事は簡易的な例として手順をまとめたものであり、この手順が安全であることを保証しません。特に鍵を環境変数にそのまま設定することは一般的には好ましくないので、各自よしなにご対応ください。
:::

## 実装
[cryptography](https://pypi.org/project/cryptography/) を使用して以下のようにする。

``` python:crypt.py
from os import getenv

from cryptography.fernet import Fernet

CRYPT_KEY = getenv("CRYPT_KEY").encode()


def encrypt(data: bytes) -> bytes:
    return Fernet(CRYPT_KEY).encrypt(data)


def decrypt(data: bytes) -> bytes:
    return Fernet(CRYPT_KEY).decrypt(data)
```

## 使い方

### 鍵を生成する
``` python
from cryptography.fernet import Fernet

print(Fernet.generate_key().decode())  #=> '92CzBgyNP0JnMayKW0kgUTpGnjOVCTRSjpxBAVGBJns='
```

これを Python アプリの環境変数 `CRYPT_KEY` に設定しておく。

### 暗号化
``` python
from crypt import encrypt

data = "吾輩は猫である"
data_encrypted = encrypt(data.encode())
print(data_encrypted)  #=> b'gAAAAABlzCJpdEpaoGi4bovGXKldGcuXAl2Ue0hVH52ip_638Whb35jnYHAOOKAZECzF9GB6XYJJMtWGqOCpL1G9LsIdBhBV-Tooegb-0AIlwrGpuSSXcmA='
```

### 復号化
``` python
from crypt import decrypt

data_encrypted = b'gAAAAABlzCJpdEpaoGi4bovGXKldGcuXAl2Ue0hVH52ip_638Whb35jnYHAOOKAZECzF9GB6XYJJMtWGqOCpL1G9LsIdBhBV-Tooegb-0AIlwrGpuSSXcmA='
data = decrypt(data_encrypted).decode()
print(data)  #=> '吾輩は猫である'
```
非デザイナーにも知っていて欲しい「色」と「特性」

## はじめに
数年前から「デザインの民主化」「非デザイナー向けの〇〇」といったワードをよく見るようになりました。それに伴い、デザイナー不在でも制作ができる便利なツールも増えてきましたね。

ReactなどのUI制作に便利なライブラリが広く使われたり、Canvasを使ってのバナー制作を行う人も増えてきた印象があります。

一方で「たくさんあるテンプレートから何を基準に選べば良いのか分からない」「アレンジしたけど、なんだか上手くいかない」という人もいるのではないでしょうか。

「非デザイナー～」シリーズでは「知っているとちょっと得するデザインTIPS」や「話のネタになるデザイン豆知識」をお伝えしていこうと思います。

## 今回のテーマ「色」と「特性」
今回は色の見え方、なかでも**色覚特性**について書いていこうと思います。
色覚特性はさまざまな理由から、多数派とは違う色の見え方・感じ方をする状態のことを言います。色は全ての人に関わるものなので、制作するうえで知っておいて欲しいことだと思い、記事にしたいと考えました。

## 伝えたい相手
+ 制作に関わる全ての方々

## すこし苦い思い出…
今回のテーマについて、すこし苦い思い出があります。
学生時代に友人と飲み会があり、モツ鍋が準備されていました。自分たちで具材などを入れる形式だったのですが、友人が唐辛子の輪切りの入った小皿を持って「このネギって入れちゃって良いのかな？」と聞いてきました。
私は（ボケてるのか？）と思い「いやいや、これどう見たってコレが唐辛子でしょw」と返してしまったのです。
すると友人は、少しシュン...とした感じで「いや、色が分からなくて...」。
一瞬、気まずい空気が流れたあと、素直に謝り一件落着しました。

## 身近な色覚特性
日本で色覚特性を持つ人の割合は、男性は5％、女性は0.2%。
**男性の20人に1人、女性の500人に1人**と考えるとかなり身近な存在だと分かると思います。
学生時代の私は、色は全ての人が同じように見えているものだと思っていました。小学校では色覚検査を受けたこともあったのに、身近にいることを想像もしてなかったのです。

## 色覚特性を知ろう
色覚にはさまざまな種類があります。
一般的な色覚を指す「C型」、赤を見分けることが難しい「P型」、緑を見分けることが難しい「D型」。P型とD型は見え方が似ており、**日本の色覚特性のほとんどがP型かD型**のどちらかのタイプだと言われています。
稀な症例としては、青を見分けることが難しい「T型」、色を明暗でしか感じることができない「A型」というものもあります。

![Qitta2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3656834/c51a1c2c-bffc-5787-596d-73053e2ef116.png)
（参照：https://cudo.jp/?page_id=540）

## 配慮するポイント
「見える色の違いがあるのは分かったけど、どうすれば？」となると思います。そこで配慮するべきポイントをいくつかお伝えいたします。

## 間違いやすい組み合わせ
色覚特性を持つ人が間違えやすい組み合わせがあります。
この色は避けるか、色以外の識別方法を組み合わせるなどの工夫をすると良いと思います。

![Qitta2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3656834/7aa24e62-b2a3-ba00-bcdc-5286be277b90.png)
（参照：https://cudo.jp/?page_id=540）

## 暖色と寒色を組み合わせる
色覚特性を持っている場合、暖色同士、寒色同士の見分けが付きにくくなります。色が隣り合う場合は、暖色と寒色とを組み合わせると違いを識別しやすくなります。

![Qitta2-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3656834/8931dc97-9998-1a04-6553-8b99f0059f34.png)

## 色の明るさを変える
同じ明度の場合にも見分けが付きにくくなります。
明度の低い色（濃い色）と明度の高い色（薄い色）を組み合わせることでも、色の違いを識別しやすくなります。

※明度についてはコチラでも説明してます。

https://qiita.com/watoson3/items/fcf62479557f74e6d325


## マークや模様、境界線を組み合わせる
色だけで区別をせずに、マークや模様を使うことでも、違いを表現することができます。また、境界線として白い線をいれても、見やすい状態を作ることができます。

![Qitta2-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3656834/5c5643d7-7a24-850d-d391-ddf66fcb5b24.png)

![Qitta2-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3656834/fa10125b-b910-0b9f-15b4-91139d851d01.png)


## 確認方法
色覚特性の見え方はChromeから確認することが出来ます。

https://dev.classmethod.jp/articles/google-chrome-devtools-vision-deficiencies/

また、スマホ向けアプリでも、手軽に確認することができます。
こちらは日常生活のなかで、カメラをかざして色々なものを移すと、違った景色が見えてくるので非常におすすめのアプリです。

<b>スマートフォン向けアプリ「色のシミュレータ」</b>

https://asada.website/cvsimulator/j/index.html


## 最後に
以上、知ってほしい「色」と「特性」でした。
色覚特性への配慮は、媒体や制作内容によって大きく事情が変わってくると思います。現実問題として様々な要因で対応が難しかったり、後回しになってしまうことも多いでしょう。

しかし「知ること」は「変わること」への第一歩だと思っています。

最近では、ゲーム業界でも色覚特性に対する配慮の動きがあり、「ぷよぷよ」や「スプラトゥーン」には色覚サポート機能が入りました。

今後は、さらにユニバーサルデザイン（出来るだけ多くの人々が利用できることを目指したデザイン・設計）への取り組みは広く理解されていくものだと思っています。

私自身、この分野について、まだまだ勉強中ですが、出来る限り「誰も置き去りにしないデザイン」を心がけていきたいと思っています。
【Python】新しいwindows PCを買ったら、venv/Scripts/activateできなくなった話

## はじめに
最近、6年振りにPCを買いました。
大幅なスペックアップにほくほくしながらセットアップを完了。

さぁ、いざ快適な開発体験を！

と意気揚々にPythonの仮想環境を立ち上げるも

`venv/Scripts/activate`

を実行すると見慣れない、アラートが...

## 実行環境
OS: windows 11 pro
Python: 3.12.2

## 本文
以下は、実際に表示されたエラーです。
```
.\venv\Scripts\Activate : このシステムではスクリプトの実行が無効になっているため、
ファイル C:\Users\user1\venv\Scripts\Activate を読み込むことができません。
詳細については、「about_Execution_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170)
を参照してください。
発生場所 行:1 文字:1
+ .\venv\Scripts\Activate
+ ~~~~~~
    + CategoryInfo          : セキュリティ エラー: (: ) []、PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess
```
何やら、実行ポリシーがうにゃうにゃと書いてますね。
表示されているURLにアクセスすると、
WindowsのPowershellのページが表示されます。

上のほうに以下の文言があります。
|PowerShell の実行ポリシーは、PowerShell が構成ファイルを読み込み、スクリプトを実行する条件を制御する安全機能です。 この機能は、悪意のあるスクリプトの実行を防止します。|
|:-|

要するに、Powershellのデフォルト設定では、セキュリティの都合上、`vnev/Scripts/activate`を実行できないという話。

なので後はスクリプトの実行許可を出すだけでいいなら、以下のコマンドを実行。
```
$ Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
```

その後、再度venvのスクリプトを実行します：
```
venv\Scripts\activate
```

これでエラーが解消され、venvが正常に動作しましたね。

## まとめ
数年振りにPCを買い替えたこともあり、昔した諸々の手順をほとんど忘れていた為、起こったエラーでした。

皆さんもwindowsを買い替えた際には、ご注意を。

## 参考文献
- Powershellの実行ポリシーについて: [about_Execution_Policies](https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.4)
- Python.jp: [Python windowsの仮想環境について](https://www.python.jp/install/windows/venv.html)
↑ ~~最初に行きつけば、この記事を書く必要がなかったほどの良記事~~
[ThoughtSpot]日付にフィルターをかける方法まとめ

## はじめに
ThoughtSpot利用歴2年目くらい。
BIツールごとに日付に関する設定とか指定が異なっていて ~~めんどくさい~~ 面白いなと思っている非エンジニアです。

ThoughtSpotで日付に関係する条件を指定（期間指定）する場合、いくつかパターンがあるので方法をまとめます。
方法は大きく３つです。
1. フィルターを使う　（難易度：イージー）
2. キーワードを検索バーにベタ打ち　（難易度：ノーマル）
3. 数式（とパラメーター）を使う　（難易度：ハード）

順番に説明していきます。

## ThoughtSpotで日付にフィルターをかける方法
### １．フィルターを使う
イージーモード、というより日付に限らず他の項目も条件を指定するときは通常この方法を使います。
やり方は簡単、画面左側の一覧から項目クリック→フィルターマークで設定できます。
![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1658354/0c2a2064-53ea-eea3-5ad6-736edecba0a0.png)
ローリングタイプでのフィルター方法は、当記事執筆時点の日本語訳にちょっと癖があります。
詳しくは[こちらの記事](https://qiita.com/shiisaa/items/0a665f3588064dd52f43 "Thoughtspotの日付フィルターの話")で解説してますので馴染めなかった方はこちらもどうぞ。

### ２．キーワードを検索バーにベタ打ち
さてフィルターをザっと見た方は気づいたと思いますが、設定が「これ（this）」「最後（last）」「次へ（next）」で分かれているので、例えば「今年（this）と去年（last）」の2年分という設定がフィルターではできません。
そのときは検索バーにベタ打ちします。フィルターで指定できなくても、検索バーに打つときちんとフィルターがかかります。
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1658354/78bf12fb-e3d8-f1c1-63fa-74b3846f5b50.png)
日付項目が複数あるデータのときは、どの日付に対しての「今年」なのかがバーに打つときに出るので、選ぶ日付項目を誤らないようにしてください。
この「今年」「去年」のようなワードを **キーワード** と呼びます。
日付に関するキーワードは他にもあって、おととしを指定したいのであれば「3 年前（3 years ago）」と入力します。なので過去5年分のデータを出したい、という場合は「5 年前 4 年前 3 年前 去年 今年」と入力すれば出てくるわけです。
年のほかいろんな期間指定が可能ですので、詳しくは[キーワードリファレンス](https://docs.thoughtspot.com/cloud/latest/keywords-ja-jp "日本語 Keyword reference")を見ることをおススメします。
期間指定するだけではなく比較することも可能です。その方法については[こちらの記事](https://qiita.com/shiisaa/items/a446c05408516b7d29c7 "キーワードを使って3年度分の同月比較グラフを作成する")で紹介しています。

キーワードは日付項目以外にもいろいろあって、キーワードを駆使するといろんな検索（例えばトップ10を出す、成長率を出す、など）ができるので、ぜひリファレンスを見てみてください。


### ３．数式（とパラメータ）を使う
キーワード使えばほぼカバーできるじゃないか。と思ったのですができないのがありました。それが「2か月後」などの未来日を指定する場合です。
（キーワードには *n* か月前（ *n* months ago）はあるのに *n* か月後（ *n* months later）はない）
（nextだと *n* か月分になっちゃっう）
（英語ムズカシイ）

この場合は数式を使用します。手順としては
 **①検索したい日付がNか月後かどうかを判定する数式を作り** 
 **②その数式をtrueでフィルターをかける** 
という方法になります。以下は「2か月後」でフィルターをかける例です。
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1658354/185a7202-d0c0-e8de-3541-2005b3ace61f.png)
```
start_of_month(対象日 ) = start_of_month( add_months (today(), 2))
```
「対象日」のところをフィルターをかけたい日付項目名に、「2」のところをフィルターをかけたい月数にしてください。
またこの「 *n* か月後」の数字をビジネスユーザーが好きに変更できるようにパラメーターを使う方法もあります。数式の「2」のところをパラメーターに変更するだけです。
パラメーターについては[こちらの記事](https://qiita.com/shiisaa/items/b5c414dcdc49808fe1d4 "パラメータの使い方（基本）")に書いていますので需要がありましたらこちらもどうぞ。

## おわりに
なんで私こんなに日付に関してまとめているんだろう。
日付って大事だよね。
ミラーナンバーを求めるマクロをChatGPTで作り、８ビットパソコンと計算時間を比較した

皆さんは、『ミラーナンバー』と呼ばれる数値があるのをご存知でしょうか？
「121」や「1331」などの両端が同じ数字で挟まれていたり、真中で反転している数字をといいます。これらは中央で区切ったとき、鏡像関係にあり、左右対称になることからバランスが取れていて、縁起がいい数字だとも言われています。

　鏡像関係といえば、『鏡の国のアリス』を思い出します。イギリスの児童文学作家で有名なルイス・キャロルが1871年に発表した小説で、アリスが鏡の中の世界を空想しているうちに、実際に鏡を通り抜けて鏡の世界に入り込んでしまうという物語です。
 この作品では、鏡にうつる姿はこちらと同じように動くが，向こう側の構造は反対でもあるという「鏡像関係」が描かれています。

　ところで、私が会社に入ってまもない1985年ごろ、会社である雑誌（*1)を購読しており、ある号で、「ミラーナンバーであり、かつ素数である数を出来るだけ多く求めなさい。」という懸賞問題がありました。当時、私はNECのPC-8001というパソコンで、BASIC言語のプログラムを組み、この懸賞問題を解こうとしました。
 
　当時は1978年に発売された日立の「ベーシックマスター」をはじめ、家電メーカーから次々と家庭用のパソコンが登場し、シャープから「MZ-80K」、NECからは「PC-8001」が登場し、この3機種がパソコン御三家と呼ばれました。これらのパソコンを知っている人は相当パソコン歴が長いですね。どのパソコンも値段は私の初任給ぐらいだったと思います。

　さて、過去にPC-8001で5桁の素数であるナンバーを求めたとき、結果を出すのに余りにも時間がかかり、途中で止めてしまいました。当時のパソコンはCPUが８ビット処理でしたので、扱える最大値は、２の16乗 = 32,767 の5桁です。最後までは行き着けなかったですが、そのとき得られた数値は26個で、計算時間は20日 ≒ 1,728,000秒でした。 

　一方、自宅で使っているパソコンで、同じ計算をすると、どのくらいの時間かかるか試しました。
- マクロはChatGPTを使ってエクセルのマクロ（VB)を作成
- パソコンは2014年のデスクトップ Core i3 メモリ8GB SSD 256GB OSはWindows10
 
結果：ミラーナンバーとなる素数の数と計算時間
５桁まで 108 個 　0.1 秒
６桁まで 108 個 　1.1 秒
７桁まで 776 個 　27 秒

過去はROM-Basic、今回はエクセルのVBであり、細かい条件は全く無視しています。それを差し置いても、2014年の64ビットのパソコンは、1980年ごろの８ビットパソコンと比較して、約1,700万倍速度が上がっていました。性能が桁違いに向上し、相対的に値段は格段に下がっています。

CPUの性能については、最近発刊されたPCwatch 2024年1月29日の記事『PC向けCPUの相対性能』の図が参考になります。(*2)
<img src="https://asset.watch.impress.co.jp/img/pcw/docs/1562/909/99_l.png">
>「PC向けプロセッサは、50年あまりでおおよそ1億倍弱(7,000万倍ほど)高速化し、毎年1.445倍程度性能が向上している。」

最後に、ChatGPTへの質問式と、得られたマクロを載せておきます。

:::note
ChatGPTへの質問：
:::
**『「121」や「1331」などの両端が同じ数字で挟まれていたり、真ん中で反転している数値で、これをミラーナンバーといいます。エクセルで１桁から７桁までの素数で、かつミラーナンバーである数値をセルに表示するようなマクロを作ってください。』**

:::note
ChatGPTから得られた回答：
:::

**『エクセルで VB（Visual Basic for Applications）を使用して、1 桁から ７桁までの素数でかつ、ミラーナンバーである数値をセルに表示するマクロを作成するためのサンプルコードを以下に示します。コードを実行するには、エクセルファイルで VBA エディタを開き、新しいモジュールを挿入し、そこに以下のコードを貼り付けてください。』**(*3)
```VB:MirrorNumber.vb
Sub FindMirrorPrimes()
Dim i As Long
Dim j As Long
Dim Starttime As Single
Dim startDigits As Long, endDigits As Long
Dim cell As Range

' マクロを実行するシートの設定
Set ws = ThisWorkbook.Sheets("Sheet1") ' シート名を適切なものに

' 1 桁から7 桁までの素数かつミラーナンバーである数を探す
Cells(1, 1) = "Number"
Cells(1, 2) = "Time"
Starttime = Timer
For i = 3 To 7
startDigits = 10 ^ (i - 1)
endDigits = (10 ^ i) - 1

For j = startDigits To endDigits
If IsPrime(j) And IsMirrorNumber(j) Then

' 該当するセルにミラーナンバーである素数を表示
Set cell = ws.Cells(ws.Rows.Count, 1).End(xlUp).Offset(1, 0)
cell.Value = j

' 該当するセルに計算に要した時間を表示
Set cell = ws.Cells(ws.Rows.Count, 1).End(xlUp).Offset(0, 1)
cell.Value = Round(Timer - Starttime, 2)
End If
Next j
Next i
End Sub

Function IsPrime(num As Long) As Boolean
Dim i As Long
If num < 2 Then
IsPrime = False
Exit Function
End If
For i = 2 To Sqr(num)
If num Mod i = 0 Then
IsPrime = False
Exit Function
End If
Next i
IsPrime = True
End Function

Function IsMirrorNumber(num As Long) As Boolean
Dim numStr As String
Dim reversedStr As String
' 数字を文字列に変換
numStr = CStr(num)
' 文字列を反転
reversedStr = StrReverse(numStr)
' 反転した文字列と元の文字列が一致するか確認
IsMirrorNumber = (numStr = reversedStr)
End Function
```
１）雑誌「ＭＯＬ」（オーム社, 1963.4-1991.4）
２）https://pc.watch.impress.co.jp/docs/topic/feature/1562909.html
３）計算時間を表示するように、あとでルーチンを追加しています。