OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerコマンドでコンテナ、イメージ、ボリューム、ネットワーク、キャッシュをまとめて削除する

Dockerを用いた開発をすると多くのイメージやコンテナ、ボリューム、ネットワーク、キャッシュが残りがちです。

これらを削除するコマンドたちを紹介します。

## コンテナの削除

コンテナの削除は `docker rm <container_id>` で行う。

引数には複数のコンテナIDを指定することができ、全てのコンテナを削除するには `docker rm $(docker ps -a -q)` とする。

## イメージの削除

一方でイメージの削除は `docker rmi <image_id>` で行う。

こちらも引数には複数のイメージIDを指定することができ、全てのイメージを削除するには `docker rmi $(docker images -q)` とする。

## ボリュームの削除

ボリュームの削除は `docker volume rm <volume_name>` で行う。

ほぼ同じことを書いているが、引数には複数のボリューム名を指定することができ、全てのボリュームを削除するには `docker volume rm $(docker volume ls -q)` とする。

以上のようにDockerの各オブジェクトに対して削除コマンドが用意されている。

が使っては破棄が可能なためこれらのオブジェクトがどんどん溜まっていってはいないだろうか？

（筆者は溜まっている）

そのためまとめて削除するコマンドを紹介する。

## prune

`docker system prune` で全てのコンテナ、イメージ、ボリューム、ネットワークを削除することができる。

https://docs.docker.jp/config/pruning.html#id5

コマンドを実行すると以下のように確認を求められる。

```sh
$ docker system prune

WARNING! This will remove:
        - all stopped containers
        - all networks not used by at least one container
        - all dangling images
        - all build cache
Are you sure you want to continue? [y/N]
```

ここでは停止中のコンテナ、コンテナに紐づいていないネットワーク、未使用のイメージ、ビルドキャッシュを削除するけど大丈夫？と聞かれる。

ボリュームは上のコマンドでは削除されないので、ボリュームも含めて削除したい場合は `docker system prune --volumes` とする。

```sh
$ docker system prune --volumes

        - all stopped containers
        - all networks not used by at least one container
        - all volumes not used by at least one container
        - all dangling images
        - all build cache
Are you sure you want to continue? [y/N]
```

ボリュームを含めてまとめて削除ができる。
pythonの仮想環境のメモ

## はじめに
2024年7月号のSoftware Designのセキュリティの対策と強化のコーナーの第４章の「CTFに挑戦」にて、pythonを使用し、SQLインジェクション攻撃を利用して、データベース内の特定のテーブルの情報を取得する記載がありましたので、その環境作りのメモとなります。

## 内容
Pythonでは、仮想環境ディレクトリを作成して、その環境内でのみパッケージが適用されます。この仕組みを利用することで、システム全体に影響を与えずにプロジェクトごとに適切な環境を構築することができます。
本件はmacを使用しています。

## 作成
### 仮想環境の仕組み

1. **仮想環境ディレクトリの作成**: `python3 -m venv myenv` コマンドを実行すると、`myenv` という名前のディレクトリが作成されます。このディレクトリには、独自のPython実行環境とその環境に特化したライブラリの管理ツール（例えば、`pip`）が含まれます。

2. **仮想環境のアクティベート**: `source myenv/bin/activate` を実行すると、そのターミナルセッション内で仮想環境がアクティベートされます。これにより、ターミナルがその仮想環境内のPythonインタプリタとライブラリに切り替わります。

3. **仮想環境のディアクティベート**: `deactivate` コマンドを実行すると、ターミナルセッションは仮想環境を離れ、システム全体のPython環境に戻ります。

### 実際の手順

以下は具体的な手順の例です。

1. **仮想環境の作成**
myenvのディレクトリを作成する例です。
   ```sh
   python3 -m venv myenv
   ```

2. **仮想環境のアクティベート**

   ```sh
   source myenv/bin/activate
   ```

   ターミナルプロンプトが `(myenv)` に変わります。

3. **必要なパッケージのインストール**

   仮想環境がアクティベートされた状態でパッケージをインストールします。

   ```sh
   pip install requests
   ```

4. **スクリプトの実行**

   仮想環境がアクティベートされた状態でスクリプトを実行します。

   ```sh
   python blindsqli.py
   ```

5. **仮想環境のディアクティベート**

   作業が終わったら、仮想環境をディアクティベートします。

   ```sh
   deactivate
   ```




## 参考記事

https://qiita.com/fiftystorm36/items/b2fd47cf32c7694adc2e

ソフトウェアデザイン 2024年7月号　第４章
LeetCode挑戦日記：Day20

# はじめに

最近、業務で実装する時間よりも資料作成やレビューをする時間が多くなってきました。
このままでは自身のコーディング能力が落ちそうで怖いので、LeetCodeを始めてみました。

自身の学習の記録 & LeetCodeに興味のある人が挑戦しやすいように、記事に残していきます。
このような競技プログラミングをした経験がないので、ひよってEasyからやっていきます...

# [Easy] 2215. Find the Difference of Two Arrays

`0`インデックスの整数配列`nums1`と`nums2`が与えられたとき、サイズ`2`のリスト`answer`を返してください。answerは次のように構成されます：

- `answer[0]`は`nums1`に存在し、`nums2`に存在しないすべての異なる整数のリスト
- `answer[1]`は`nums2`に存在し、`nums1`に存在しないすべての異なる整数のリスト

## 素直に解いてみる

### 考え方

1. `nums1`と`nums2`をソートする
1. `nums1`と`nums2`のそれぞれの配列で重複排除する
1. `nums1`と`nums2`の各要素を前から比較していき、小さい数字を`answer`配列に入れていく
1. `answer`を返す

### コーディング

```typescript
function findDifference(nums1: number[], nums2: number[]): number[][] {
    const sorted1 = [...new Set(nums1.sort((a, b) => a - b))];
    const sorted2 = [...new Set(nums2.sort((a, b) => a - b))];

    let i = 0, j = 0;
    const answer: [number[], number[]] = [[], []];

    while ((i < sorted1.length) && (j < sorted2.length)) {
        if (sorted1[i] === sorted2[j]) {
            i++;
            j++;
        } else if (sorted1[i] < sorted2[j]) {
            answer[0].push(sorted1[i]);
            i++;
        } else {
            answer[1].push(sorted2[j]);
            j++;
        }
    }


    answer[0] = answer[0].concat(sorted1.slice(i));
    answer[1] = answer[1].concat(sorted2.slice(j));

    return answer;
};
```

### 結果

Runtime：99ms
Beats 40.04%

Memory：58.48MB
Beats 5.74%

## 改善：ソートをなくす

### 考え方

1. `Set`をうまく使うことにより、ソートしなくても実現できるはず

### コーディング

```typescript
function findDifference(nums1: number[], nums2: number[]): number[][] {
    const answer1 = new Set(nums1);
    const answer2 = new Set(nums2);

    const length = Math.max(nums1.length, nums2.length);

    for (let i = 0; i < length; i++) {
        if (nums1[i] !== undefined) { answer2.delete(nums1[i]); }
        if (nums2[i] !== undefined) { answer1.delete(nums2[i]); }
    }

    return [Array.from(answer1), Array.from(answer2)];
};
```

### 結果

Runtime：73ms
Beats 91.38%

Memory：56.62MB
Beats 72.35%
LeetCode挑戦日記：Day19

# はじめに

最近、業務で実装する時間よりも資料作成やレビューをする時間が多くなってきました。
このままでは自身のコーディング能力が落ちそうで怖いので、LeetCodeを始めてみました。

自身の学習の記録 & LeetCodeに興味のある人が挑戦しやすいように、記事に残していきます。
このような競技プログラミングをした経験がないので、ひよってEasyからやっていきます...

# [Easy] 724. Find Pivot Index

整数の配列`nums`が与えられたとき、この配列のピボットインデックスを計算してください。
ピボットインデックスは、そのインデックスの左側にあるすべての数の合計が、インデックスの右側にあるすべての数の合計と等しい場所です。
インデックスが配列の左端にある場合、左側の合計は0とします。これは、右端のインデックスにも適用されます。
最も左側にあるピボットインデックスを返してください。そのようなインデックスが存在しない場合は、`-1`を返してください。

## 素直に解いてみる

### 考え方

1. `nums`配列を前から順番に2つの配列に分ける
1. 左の配列と右の配列の合計をそれぞれ求め、同じ値であればその値を返す

### コーディング

```typescript
function pivotIndex(nums: number[]): number {
    for (let i = 0; i < nums.length; i++) {
        const left = nums.slice(0, i).reduce((a, b) => a + b, 0);
        const right = nums.slice(i + 1).reduce((a, b) => a + b, 0);
        if (left === right) {
            return i;
        }
    }

    return -1;
};
```

### 結果

Runtime：767ms
Beats 5.11%

Memory：57.06MB
Beats 11.75%

（時間オーバーになるかと思ったが、成功したのは意外）

## 改善：合計値計算を減らす

### 考え方

1. `nums`配列の合計値を求める
1. `nums`配列の左から要素毎に合計値を求め、`2 * (i番目までの合計値) === (nums配列全体の合計値) - nums[i]`になる`i`を見つける
    `(i番目までの合計値) === (nums配列全体の合計値) - (i番目までの合計値) - nums[i]`でも行けそうに思えるが、負の数の可能性があるので2倍している

### コーディング

```typescript
function pivotIndex(nums: number[]): number {
    const sum = nums.reduce((a, b) => a + b, 0);
    let leftSum = 0;
    for (let i = 0; i < nums.length; i++) {
        if (2 * leftSum === (sum - nums[i])) {
            return i;
        }
        leftSum += nums[i];
    }

    return -1;
};
```

### 結果

Runtime：63ms
Beats 86.88%

Memory：52.40MB
Beats 74.96%
Cloud Functions(Firebase)のエイリアスの設定

### 背景

- Clood Functionsのエイリアス設定をするとデプロイ時に、読み込むことが出来ずに`Cannot finde module '@/hoge'`というエラーになってしまう。
<br>

- また、Firebaseにおける開発環境のセットアップの際にエイリアスを指定する記事が少なかったので、設定の手順を示します。


初めての投稿になるので、抜け等があったら申し訳ないです。参考程度に読んで見てください。


## Cloud Functions

1. ### `module-alias`のインストール
    - `npm install module-alias`
    - `npm install -D @types/module-alias`
    <br>

1. ### `package.json`の追記
    ```package.json
    "_moduleAliases": {
        "@": "lib"
    }
    ```
    <br>
    
1. ### `tsconfig.json`の設定
    ```tsconfig.json
    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@/*": ["src/*"]
        },
    }  
    ```
    <br>

1. ### 呼び出す関数の定義
    ```hoge.ts
    export const foo = () => console.log("piyo"):
    ```
    <br>
    
1. ### 関数の呼び出し
    - エントリーポイントでエイリアスを有効にします。ファイル構造が多階層であっても、エントリーポイントに`import "module-alias/register"`を記載すれば全てのファイルでエイリアスを使用して記述することが出来ます
    <br>
    
    - 要するにエントリーポイントにのみ`import "module-alias/register"`を記載すればOKです
    
    ```index.ts
    import "module-alias/register";
    
    //エイリアスを用いた関数をインポート
    import {foo} from "@/hoge":

    //関数の呼び出し
    foo();
    ```
    <br>

1. ### デプロイしてみる

  `firebase deploy --only functions`
  - デプロイ出来るか確認してみてください


--- 
この設定よりクライアントサイドでエイリアス指定していたときと同様にして記述することが出来ます。
requireするケース


 ```
 # frozen_string_literal: true
 
+require 'net/http'
+require 'uri'
+require 'mini_magick'
+require 'fileutils'
```

上記のようにrequireするケースは、Rubyに標準で存在しない場合など、あえて書かなければいけない場合のみ記載する。

Gemfileに記載されたGemは、Bundlerによって自動的にロードされるため、手動でrequireする必要はない。既に入っている場合は不要。

それ以外は基本的にはRubyの標準機能であるため記載不要。
404 Tomcat Error "... could not be completely deleted"

# 実現したいこと
Maven Webアプリケーションプロジェクトを WARファイルとして Tomcat にデプロイ

# エラーメッセージ
### HTTPステータス404
```yourpage.com
HTTPステータス404-見つかりません。

タイプ ステータスレポート

メッセージ The requested resource [/] is not available

説明 オリジンサーバーは、ターゲットリソースの現在の表現を見つけられなかったか、またはそれが存在することを開示するつもりはありません。

Apache Tomcat/Your Version
```
スクリーンショット
![screenshot404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662967/ca0929b8-a3fe-ff65-2ffd-46638d31707e.png)

# 原因
### プロジェクトルートを完全に削除できなかった
Tomcat で以下のエラーが発生していた。
```bash:catalina.2024-06-26.log
26-Jun-2024 08:46:21.754 SEVERE [Catalina-utility-2] 
org.apache.catalina.startup.ExpandWar.deleteDir 
[/opt/tomcat-9/apache-tomcat-9.0.56/webapps/ROOT] could not be completely deleted. 
The presence of the remaining files may cause problems
```

以下2つが原因と考えられる。
1. Tomcat を起動したままデプロイした結果、一部のファイルが読み込まれている状態だったため
1. `mv` コマンドで古いWARファイルを上書きした結果、完全に上書きできず一部のファイルが残ったため

# 解決方法
デプロイする前に Tomcat を停止し、古いWARファイルと展開されたディレクトリを削除する
```bash:Tomcatを停止
sudo systemctl stop tomcat
```
```bash:古いWARファイルと展開されたディレクトリを削除
ls -l path/to/tomcat/webapps/ # 対象の存在をチェック

sudo rm -r path/to/tomcat/webapps/ROOT.war # 古いWARファイルを削除

sudo rm -r path/to/tomcat/webapps/ROOT # 展開されたディレクトリを削除

ls -l path/to/tomcat/webapps/ # 削除されたことをチェック
```
```bash:Tomcatを起動
sudo systemctl start tomcat
```
```bash:Tomcatの起動確認
sudo systemctl status tomcat
```
- Webアプリケーションにアクセスして動作確認
```bash:Tomcatのログを確認
sudo tail -f /path/to/tomcat/logs/your_error.log
```

# 環境
Ubuntu 20.04.3
Eclipse IDE for Enterprise Java and Web Developers (includes Incubating components) Version: 2023-12 (4.30.0)
Apache Tomcat/9.0.56
Apache Maven/未調査

# 参考
https://stackoverflow.com/questions/14873219/how-to-prevent-file-locking-when-undeploying-a-tomcat-web-app
高校生に捧げるこれだけはやっておけ集

# 筆者がこれを始めに知っていればな～ということを紹介する

全く知らない状態から始めるのは大変ですよね。
僕も最初は右も左もわからず、あるインフルエンサーに影響されてPythonでゲームを作り始めたけど、全然うまくいかなかったんです。
このブログでは、そんな僕の失敗談や成功談を交えながら、みなさんが最初に知っておくと便利なことをお伝えします！

# やりたいことを選定しよう

まずは、自分が何を作りたいのかを決めるのが大事です。
プログラミングにはたくさんの分野があって、それぞれに適した言語やフレームワークがあります。
「俺はこれがやりたいんだ！！」というものがあれば迷うことはありませんが、迷っているときは全部試してみるのをオススメします。
学生の特権は時間の猶予があることですからね！

:::note
はじめて勉強するなら有名どころを勉強しましょう。
例えばWebだったらReactだったり、ゲームだったらUnityを選んでください。
情報量が少ないものを選ぶと学習しにくいので。
:::

# 環境を整えよう

プログラミングにはやっぱりパソコンが必要です。
何を作るのかにもよるけど予算は大体8万円くらいを見ておくといいでしょう。[FRONTIER](https://www.frontier-direct.jp/)のような専門店で買うのがおすすめ。
Unreal Engineとか使わない限り、グラフィックボードよりもCPU、SSD、メモリに重点を置くと良いですよ。

# 技術的なもの以外で必要なもの

## マイナンバーカードを作ろう

意外と身分証明書が必要になる場面が多いです。銀行口座を作るときや資格試験のときに必要なので、時間がかかるから早めに作っておきましょう。

## デビットカードを作ろう

プログラミングツールやアセットを買うには現金が使えないことが多いです。学生でも使えるデビットカードを活用しましょう。楽天銀行やPayPay銀行などで作れるので、ぜひチェックしてみてください。

## GitHub Student Developer Packに登録しよう

GitHubは学生に優しいサービスを提供しています。僕はこの特典でIntelliJのIDEを使っていますが、大満足です。ぜひ活用しましょう。

## KindleやUdemyを活用しよう

プログラマーにとってインプットは大切です。継続的な学習が求められます。近くの書店では手に入らない情報もECサイトを活用すれば見つかります。

## デバッグ力を手に入れよう

デバッグはプログラミングの要です。**ブレークポイント**を活用して効率的にデバッグしましょう。
特に理由がない限り今の時代printでデバッグをしていくのはナンセンスです。先人様が作った機能をありがたく使わせていただきましょう。

### コミュニティを見つけよう

一人で解決できない問題が出てきたときは、コミュニティに参加しましょう。
いろんなサイトとかあるけど、Discordとかがおすすめ。プログラミングのサーバーとかが立てられているからそこで質問してみましょう。
ただし質問するときは礼儀正しく！
答えてもらったら感謝の気持を伝えましょう！

# 技術的なもの

## IDE
コードを書くためのツールをIDEといいます。
GitHub Student Developer Packに登録していればJetBrainsという会社のかっちょいいやつを使えます。
それぞれ得意分野があるので、使い分けましょう。

| IDE                | 用途               |
|--------------------|------------------|
| Visual Studio Code | HTMLとか軽いサイト      |
| Visual Studio      | ゲーム開発 Windowsアプリ |
| Android Studio     | Androidアプリ       |
| JetBrains製品        | 基本的になんでも         |

## Git

Web、ゲーム、モバイルアプリ、どの分野でもバージョン管理ツールは必要です。
言語の勉強と並行してGitの勉強も進めましょう。

## プログラミング言語

プログラミング言語はそれぞれ**得意不得意**があるので、何を作りたいかによって選びましょう。
たとえばPythonでゴリゴリ3Dゲームを開発するとかはちょっと厳しいです。

さらに言語だけでなく、フレームワークやエンジンも重要です。
基本的にゼロから作るのではなくReactというフレームワークを使ってWebアプリを作るとか、Unityというエンジンを使ってゲームを作ります。
作りたいものが決まっていれば自動的に決まっていく感じなので、まずは作りたいものを決めましょう。

## まずはここを目指そう

1. オリジナルの作品を完成させる
自分で考えたオリジナルの作品を公開する。これができたら脱初心者です。ここまで挫折しなかったあなたに拍手！

2. 資格勉強もして体系的な知識をつけよう
おすすめはIPAの「基本情報技術者試験」です。作りたいものが一通り作れたら資格勉強を始めると良いでしょう。

3. オブジェクト指向をきちんと勉強してみよう
現代のプログラミングには欠かせない考え方です。使わなくても作品は作れますが、しっかりと理解した場合はメンテナンスしやすいコードになります。
動くコードが書けるようになったらそれを追求していきましょう！

# おわりに
みなさんがこのブログを読んで、新たなエンジニアとしての一歩を踏み出せることを願っています。頑張ってください！
Docker再起動時にコンテナが勝手に起動する件について

## はじめに

ある日、Dockerでmysqlコンテナを起動させようとしたら、すでに指定したポートが利用されていますと表示されました。
なんでかなと思ってdocker psを実行してみると、別のmysqlコンテナが起動されていました。docker-compose.ymlを見てみると設定をミスってしまっていたのでその共有をしたいと思います。

## TL;DR

- `restart: always`を記述するとローカル環境でもDocker再起動時にコンテナが自動的に立ち上がる
- ローカル用と本番用などのdocker-compose.ymlを分けるべき

## 原因

原因としては、確認用だしざっと見て大丈夫そうだからコピペでいいやと思い、composeファイルの中身をコピペした中に`restart: always`が含まれていたためでした。

## restartは何をしているのか

restartではDockerが終了した際や再起動した際の設定を決めることができます。
以下の4種類の設定があり、今回は`always`を指定していました。

- `no`: コンテナを自動的に再起動しない。デフォルトの設定はこれ。
- `on-failure[:max-retries]`: エラーが原因で終了した場合にコンテナを再起動する。`max-retries`で指定した回数、起動を試行する。
- `always`: コンテナが停止した場合、自動的に起動される。
- `unless-stopped`: `always`に似ているが、コンテナが停止している状態でDockerが再起動された場合にはコンテナは再起動されず、それ以外の状態の場合には再起動される。つまり、明示的にコンテナを停止させた状態で、Dockerが再起動された場合はコンテナは自動的に起動されない。

Dockerでは再起動ポリシーというものが指定されており、そのポリシーに従って再起動が行われます。特に2つ目のポイントが重要で、手動で停止したときは自動的に起動されません。そうしないとコンテナを削除しない限り永久に起動することになってしまうので...

> - A restart policy only takes effect after a container starts successfully. In this case, starting successfully means that the container is up for at least 10 seconds and Docker has started monitoring it. This prevents a container which doesn't start at all from going into a restart loop.
> 
> - If you manually stop a container, the restart policy is ignored until the Docker daemon restarts or the container is manually restarted. This prevents a restart loop.
> - Restart policies only apply to containers. To configure restart policies for Swarm services, see [flags related to service restart](https://docs.docker.com/reference/cli/docker/service/create/).

https://docs.docker.com/config/containers/start-containers-automatically/

https://github.com/compose-spec/compose-spec/blob/master/spec.md#restart

## どうすれば良いか

ローカルで利用するdocker-compose.ymlの他に別の環境で利用するdocker-compose.ymlを用意してあげるのが良いと思います。
コンテナを起動させるときに-fオプションをつけることでファイルを指定することができるため、ローカルでは`restart: always`を記述していないdocker-compose.ymlを利用し、本番環境などでは`restart: always`を記述したdocker-compose.ymlを利用することでやりたいことを実現することができます。
この理由以外にもdocker-compose.ymlを分けることで環境毎に設定を変更することができるので環境毎にファイルを作ることをおすすめします。

https://qiita.com/Co-0/items/d2380ff02a9e436e6563

## 参考

https://docs.docker.com/config/containers/start-containers-automatically/

https://github.com/compose-spec/compose-spec/blob/master/spec.md#restart

https://qiita.com/Co-0/items/d2380ff02a9e436e6563
初見で"jose"を『ホゼ』とは読めない

これなんて読むの？と調べたり、
正しくないのを知りつつ、ついついそれを使い続けていたり、
たまに別の読み方が聞こえてくる単語集です。
※あくまで読み方に特化しているので、意味が気になった方は調べてみてください
※読み方は諸説あったりします

# jose(ホゼ、ホセ)
スペイン語らしいので、読めなくても仕方がない・・・

# notice(ノウティス)
ノティスって言ってた

# LaTeX(ラテフ、レイテック、、、)
結構色々あるらしく、ラテックとかもあったので
そのPJの雰囲気にあわせて使い分ける

# JWT(ジョット)
これでジョットはかっこよすぎ

# FALSE(フォールス)
正しいのはフォールスらしいけど、私はきっとこれからもフォルス

# NULL(ナル)
正しいのはナルらしいけど、私はきっとこれからもヌル
と思ったけど、「非NULL」の時は非ナルって言っているかもしれない

# warning(ウォーニング)
正しいのはウォーニングらしいけど、私はきっとこれからもワーニング

# RAID(レイド)
たまにライド派がいる

# GIT(ギット)
たまにジット派がいる

# integer(インテジャー)
たまにインテガー派がいる

　
随時追記予定・・・

# さいごに
正しいことを認識しておくのは大切かもしれませんが、
結局、<b>齟齬なく意思の伝達ができる</b>のであれば何でもいいと思います。
markdown AIはこどもにも簡単に利用できそう？

## ★はじめに
将来の夢は唯一無二の素敵なエンジニアになる！を掲げることで日進月歩。わーちゃんと申します。

早速ですがQiita公式イベントのなかで、タイトルからもわかるように下記に参加してみました
[markdown AIを使った記事を投稿しよう！](https://qiita.com/official-events/142fdd0d69ff6bb2d547)


## ★早速サイトへ移動
まずはログインすることから
[![Image from Gyazo](https://i.gyazo.com/82cff2398f12928f19f56a99c4f6a4f2.png)](https://gyazo.com/82cff2398f12928f19f56a99c4f6a4f2)

`Try Markdown AI`から**Googleアカウント**で簡単に、無料で利用できます。
アカウント登録後は自動で記事を作成する画面に移動します。
[![Image from Gyazo](https://i.gyazo.com/1be3eddac0a9fc3c08a51bdab1e356fc.png)](https://gyazo.com/1be3eddac0a9fc3c08a51bdab1e356fc)
デフォルトでファイルを選択することができたので今回はこちらを試してみます。`Top down you・・`のファイルです。


## ★こどもがmarkdown AIを使用する場面を考えてみた
小学生は絶対するであろう、**自由研究**で少し作成してみました
私自身使用初めてなのでなれる意味で一つ作成。
[![Image from Gyazo](https://i.gyazo.com/bd6ad6111dd9732e41f6f0d6eaaaf1aa.png)](https://gyazo.com/bd6ad6111dd9732e41f6f0d6eaaaf1aa)

次は、子供の事を考えてひな形を作成してみました
マークダウン表示だとこんな感じ
[![Image from Gyazo](https://i.gyazo.com/53988b0d8918b9acf951bdde356ad569.png)](https://gyazo.com/53988b0d8918b9acf951bdde356ad569)
ビュー表示はこんな感じ
[![Image from Gyazo](https://i.gyazo.com/25242496a71a0b8577740f68d1fc7b7e.png)](https://gyazo.com/25242496a71a0b8577740f68d1fc7b7e)

Saveを押すとURLなんかを取得することができます
https://storage.googleapis.com/topdowncom/content/xzfx9RHS9JWwmRbRWFEtYDjA4wj2/ff4c8ffd-3d57-4a56-bf7f-4428da9a1650/index.html

- 左のファイルに元からいろんな**ひな形**があれば使いやすいのかも😀


## ★感想など
- 日本語や英語など、言語選択出来たらいいな
- PCで使用するときは画面の幅が変わることでエディタとマークダウン両方表示出来たらいいな
- 入力例が少ないから初めての人はできることが少ないと感じて飽きてしまいそう
- 普段Qiitaの`マークダウンの書き方`を参考にして記事を書いてる私からしたら、あまり醍醐味がないように感じました
- GPTみたいな機能を想像していた(「●●という見出しを作って」といったら、マークダウン記法の文字が自動で出力される、、みたいなもの)

:::note warn
markdown AIの便利な使い方、時間があれば研究してみたいです
:::
uwsgi.iniでno python application found, check your startup logs for errors エラー

# 経緯
前はそのままでも起動できていたのに、logに`no python application found, check your startup logs for errors`と表示される。

# 解決策 1
`chdir`で、作業するディレクトリを指定
`module`を下記に設定`application`は、自分のアプリケーションファイルを指定。

```
[uwsgi]
chdir = /var/www/path/to/dir
module = application.uwsgi:application
```

# 解決策 2
上記の設定で直しても同じエラーが出る場合は、アプリケーションファイル自体にエラーが出ていることが多いので、
ファイルのエラーを治すとうまくいく。

# 参考文献

https://qiita.com/11ohina017/items/da2ae5b039257752e558

https://stackoverflow.com/questions/50305654/uwsgi-flask-no-python-application-found-check-your-startup-logs-for-errors

https://qiita.com/hogemax/items/a3b04f0e848f52ff888e
.NET MAUI アイコン設定

.NET MAUI を使いAndroidアプリを開発しています。
アプリのアイコンを設定する方法を調べたときのメモを備忘録として残したいと思います。

環境
.NET 8.0

# 目次
　[参考](#参考)
　[手順](#手順)
　[まとめ](#まとめ)

## 参考
https://learn.microsoft.com/ja-jp/dotnet/maui/user-interface/images/app-icons?view=net-maui-8.0&tabs=android

## 手順

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3096978/9b0c5e55-ddb8-cf0e-2fc7-72c7e5667f69.png)

フォルダ「appIcon」の配下にアイコンとして利用したいsvgファイルを配置する。
(今回はtest.svgを配置)

※注意点
ファイル名の命名規則にルールがある
 > Android リソースの名前付け規則に準拠するには、アプリ アイコンのファイル名を小文字にし、先頭と末はを文字で、英数字またはアンダースコアのみを含める必要があります。
 

プロジェクトからMauiIconの値を修正する。
```project.csprj
<ItemGroup>
  <!-- 変更前 -->
  <MauiIcon Include="Resources\AppIcon\appicon.svg" ForegroundFile="Resources\AppIcon\appiconfg.svg" Color="#512BD4" />
  <!-- 変更後 -->
   <MauiIcon Include="Resources\AppIcon\test.svg" />
</ItemGroup>
```

Android マニフェスト(Platforms\Android\AndroidManifest.xml)を修正する。
```AndroidManifest.xml
<manifest>
  <!-- 変更前 -->
  <application android:icon="@mipmap/appicon">
  <!-- 変更後 -->
  <application android:icon="@mipmap/test">
</manifest>
```
@mipmap/{appicon}の{appicon}部分について、MauiIconのIncludeで指定したファイル名を拡張子抜きで指定しないとビルドエラーになる。

## まとめ
ファイル名をデフォルトのappiconからtestに変えて開発を進めてみましたが、ファイル名をデフォルトのappiconに変更してファイルを置き換えると早く開発ができたかもしれないと思いました。
WebアプリでQRコードを読み込む

## はじめに
AngularのWebアプリケーションでQRコードを読み込む機能を作ります。
作ると言っても、 @zxing/ngx-scanner を組み込むだけでとても簡単です。

## パッケージの追加

[Getting Started](https://github.com/zxing-js/ngx-scanner/wiki/Getting-Started) ページを参考に、Angularのバージョンに対応した ngx-scanner をインストールします。 browser と library は latest で問題ないようです。

```bash
npm install @zxing/browser@latest --save
npm install @zxing/library@latest --save
npm install @zxing/ngx-scanner@{対応したバージョン} --save
```

app.module.ts もしくは任意の *.module.ts に、以下のようにモジュールを追記します。

```typescript
import { NgModule } from '@angular/core';
// ...
import { ZXingScannerModule } from '@zxing/ngx-scanner';

@NgModule({
  imports: [
    // ...
    ZXingScannerModule,
  ],
})
```

## コンポーネントの作成
ここではQRコードリーダーのコンポーネントとして `qr-reader` を作ります。

```bash
ng generate component qr-reader
```

qr-reader.compoment.ts には、読み取り結果の変数 `readString` と 読み取り成功時のイベントハンドラを作成します。

```typescript
import { Component } from '@angular/core';

@Component({
  selector: 'app-qr-reader',
  templateUrl: './qr-reader.component.html',
  styleUrls: ['./qr-reader.component.scss']
})
export class QrReaderComponent {
  readString: string = '';

  scanSuccessHandler(readStr: string) {
    this.readString = readStr;
  }
}
```

qr-reader.component.html には `zxing-scanner` と読み取り結果を配置します。

```html
<zxing-scanner
  (scanSuccess)="scanSuccessHandler($event)">
</zxing-scanner>
<div>
  読取結果：{{readString}}
</div>
```

これだけです。

## あとはお好きなように

カメラがついているPCやスマートフォンなどでこのコンポーネントを表示すると、カメラが起動し、QRコードをカメラに写るようにすると、QRコードが読み取られてQRコードに入っている文字列が「読取結果」に表示されます。

これだけだとごくシンプルな内容ですが、イベントハンドラに処理を書けば、QRコードの内容によっていろいろできます。

その他、カメラが無かった場合や、インカメラとアウトカメラの切り替えなど、 [Advanced Usage](https://github.com/zxing-js/ngx-scanner/wiki/Advanced-Usage) を参考に作ることができます。
AIに画像を認識させて写っているものの詳細を文字列で出力したい

## はじめに
画像認識APIが各社から提供されています。
目的は、画像を認識させてその画像に写っているものの詳細を文字列で出力することです。
例えば、シロナガスクジラの画像を入力すると「動物」ではく、「シロナガスクジラ」という文字列が出力されるようなものです。

## Cloud Vision API
Googleから提供されている画像認識APIです。(Cloud Vision API)

https://cloud.google.com/vision/docs/detecting-web?hl=ja

こちらのAPIを使って、画像に写っているものを認識させてみます。
入力画像：
![IMG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/507efd43-ec9c-1b17-c830-65cf59b55837.jpeg)

```text
10 Web entities found: 

    Score      : 1.498650074005127
    Description: Three Days of Happiness

    Score      : 1.0687499046325684
    Description: Sugaru Miaki

    Score      : 1.05840003490448
    Description: Three Days of Happiness

    Score      : 0.5787000060081482
    Description: Novel

    Score      : 0.5769000053405762
    Description: Parasite in Love - Roman

    Score      : 0.5256999731063843
    Description: Light novel

    Score      : 0.4254000186920166
    Description: Hardcover

    Score      : 0.4147999882698059
    Description: Media Works Bunko

    Score      : 0.3255000114440918
    Description: Manga

    Score      : 0.28519999980926514
    Description: 
```

まさにやりたかったことができました。
本の名前もそうですが、著者の情報も関連で出てきていますね。
しかし、英語しか出力できないらしいので日本語で出したいのであれば翻訳を掛けるなどしないといけないですね。。

## Cloud Vision APIをサンプルで試す
![スクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/d549dc5d-ac19-591e-d363-1da65bd458db.png)
![スクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/a2615175-0af4-d3ef-f800-36c03ca8108d.png)


## AWS Rekognitionのサンプルを試す

![スクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/a06a85ea-630c-bec9-2f9e-7a36d46d870d.png)
純粋な画像認識ですね。

## 最後に

chatgptも試してみました。
![スクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403148/7603ff93-0760-cd5e-1b34-39a54cadcd55.png)

一番いいかもしれないですね😂
RSpecでよく使うメソッド集(備忘録)

RSpecの検証に使うメソッドを忘れがちなので、アウトプットしてみるようにしました。
他にもよく使うけど、忘れるようなメソッドがあれば、どんどん残していきます！

## pageの中に、文字列があるかどうかを判断するマッチャ
```ruby
expect(page).to have_content('テキスト')
```

## 現在のページが指定したページかどうかを判断するマッチャ
```ruby
expect(page).to have_current_path(path)
```

## 指定した範囲の中で検証を行う
```ruby
within('.class') do
  # expect(page).to have_content('テキスト')
end
```

## モーダルが表示されるまで待つ
```ruby
find('.modal_class', visible: true)
```
## ラジオボタンの選択
choose 'label'

## クラスに、属性情報も指定して要素を取得する方法
```ruby
.modal[data-controller*=payment]
```

## idを元に要素を取得する
```ruby
find_by_id 'id'
```

## ラジオボタン or チェックボックスが選択されているか、選択されていないかをチェックするマッチャ

```ruby
have_checked_field 'label'
have_unchecked_field 'label'
```

## 非表示要素を確認する方法

```ruby
have_unchecked_field '以前使用したカードで支払う', disabled: true
```

## チェックボックスのチェックをon/offにする
```ruby
check '確認しました'
uncheck '確認しました'
```
QgsCoordinateTransformが動くのをやめた話

いつも頼りになるQGISが動かなくなった。未解決だが，後々何かに役に立つかもしれないのでドキュメントにしておく。ここじゃあなくてQGISの開発元に問い合わせろという話だけれども面倒で……

## 何をしていたか

例のプラグイン(<https://gitlab.com/jtagusari/hrisk-noisemodelling>)の開発。延べダウンロード数が2000を超え，界隈でわずかに注目を集めている模様。

このプラグインの中にはいくつかアルゴリズムを実装しているのだけれども，それらをまとめて実行するアルゴリズムを動かしていたときに事件は起こった。

## 何が起こったか

座標系の変換が出来なくなった。
正確にいえば，座標系の名称は変わるのに，その中身が変わらないという現象が起こった。

具体的に，以下の`fence_extent`を`EPSG:32654`のポリゴンに変えたいという需要があった。

```python
>> fence_extent
'15760145.941800000,15760790.769700000,5329154.958400000,5329538.435600000 [EPSG:3857]'
```

これをこうして，こうじゃ。

```python
from qgis.core import QgsApplication, QgsCoordinateReferenceSystem, QgsCoordinateTransform, QgsProject, QgsPointXY
from qgis import processing

fence_layer = processing.run(
  "native:extenttolayer",
  {
    "INPUT": fence_extent,
    "OUTPUT": "TEMPORARY_OUTPUT"
  },
)["OUTPUT"]

fence_transformed = processing.run(
  "native:reprojectlayer",
  {
    "INPUT": fence_layer,
    "TARGET_CRS": "EPSG:32654",
    "OUTPUT": "TEMPORARY_OUTPUT"
  },
)["OUTPUT"]
```

で，これ
```python
>> fence_transformed.getFeature(1).geometry().asWkt()
'Polygon ((15760145.94180000014603138 5329154.95839999988675117, 15760790.76970000006258488 5329154.95839999988675117, 15760790.76970000006258488 5329538.43560000043362379, 15760145.94180000014603138 5329538.43560000043362379, 15760145.94180000014603138 5329154.95839999988675117))'
```

座標がびくともしていない！

## ChatGPTに聞いてみた

藁にもすがる思い。`QgsCoordinateTransform`の動作を確認せよ，との指示。

```python
source_crs = QgsCoordinateReferenceSystem("EPSG:3857")
destination_crs = QgsCoordinateReferenceSystem("EPSG:32654")
transform = QgsCoordinateTransform(source_crs, destination_crs, QgsProject.instance())

extent_coords = [
    (15760145.941800000, 5329154.958400000),
    (15760790.769700000, 5329154.958400000),
    (15760790.769700000, 5329538.435600000),
    (15760145.941800000, 5329538.435600000)
]
transformed_coords = [transform.transform(QgsPointXY(x, y)) for x, y in extent_coords]
```
で，これ

```python
>> for point in transformed_coords:
      print(f"Manually Transformed Point: {point.x()}, {point.y()}")
Manually Transformed Point: 15760145.9418, 5329154.9584
Manually Transformed Point: 15760790.7697, 5329154.9584
Manually Transformed Point: 15760790.7697, 5329538.4356
Manually Transformed Point: 15760145.9418, 5329538.4356
```

Manuallyにも出来てない！
これはおおもとからダメなようです。

## 原因と対策

原因不明。ただ，たくさんのアルゴリズムを`qgis.processing`で動かしているようなときに起こる。（並列ではなくて直列。）

一度この状態になってしまうと，QGISを再起動しないと座標系の変換が復活しない。

開発中のアルゴリズムについては，とりあえずなくても大丈夫なものなので，横に避けておくことにする。

## 対策

再現性のあるエラーが確保できたので原因らしきものがわかった。
どうやら，プロジェクトのCRS・レイヤーのCRS・変換元のCRS・変換先のCRS，などが異なるとうまく動かないらしい。特に，変換元／先のCRSをプロジェクトのCRSに合わせないといけないようだ。

プロジェクトのCRSは`QgsProject.instance().crs()`で取得できる。変換元からこのCRSに変換して，それから変換先のCRSに変換してやればよい。
感謝のマネジメント

# 初めに
タスクを進めていく中で、「自分の仕事は役に立っているのだろうか」と考えることはないでしょうか。  
リーダーとなっている方は、メンバーのモチベーションをいかに保つか、という悩みを持っていないでしょうか。  
今回は、モチベーション維持のための取り組みを紹介します。

# モチベーション課題
* メンバー
  成果には直接つながらないことを担当して、ちゃんと評価されていないと感じる
* リーダー
  メンバーに気持ちよく仕事してもらえているか不安  
* 全体
 リモートワークをする機会が多く、自宅で仕事していると仕事へのモチベーションが下がる（私だけではないと信じてる！）  
 ウエブ会議などを利用していても、いまいちお互いの感情が分かりにくいと感じることも多い  
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799996/23a9f0dc-e08a-527a-3854-7039933d2ebf.png" width=300>

# 目標
感謝の気持ちを伝えることで、自分を含めたメンバーのモチベーションを維持・向上させよう！

# 感謝の伝え方
今回はプロジェクトで利用中のMattermostの機能を利用しました。
ルールは以下の通りです。
* ありがとうコイン  
各人に週ごとに5枚配布  
他メンバーが雑務などを担当してくれたときなどにプレゼント  
* とてもありがとうコイン  
各人に月ごとに5枚配布
ありがとうコイン5枚分の価値
自分のタスクを進めるうえで力を貸してくれたときなどにプレゼント
* メッセージノート
各メンバーがお互いの作業について感想を記載するノートを作成  
記載者は匿名とし、ポジティブな内容のみを記載するルール
* 表彰
月次でもらったコインの多いメンバーを表彰！  
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799996/b4a6b8c7-e616-9551-02b0-9db0dcc000b3.png" width=300>

#  効果
* メンバー
コインをもらうことで自分の作業が役立っているという実感を得られた
* リーダー
メンバーのプロジェクトに対する貢献度が客観的に判断できるようになった
* 全体
コインを渡すことやノートへの記載を通じて、コミュニケーションが円滑になった
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799996/f41abc69-8733-6cd9-d796-7b3e32334d0f.png" width=300>

# 総評
プロジェクトには直接関係しないけど誰かがやらなきゃいけないこと、を担当してくれているメンバーがコインを多く集めていました。  
当初は特定のメンバーに偏ることも多かったですが、作業の偏りが可視化されると、細かい作業を自発的に拾ってくれるメンバーが増えるという効果もありました。
数か月続けると、表彰されるメンバーの偏りがなくなり、メンバーそれぞれが一度は表彰される形となりました。  
コインを集計することの副次的な効果として、メンバーのプロジェクトに対する貢献度が客観的に判断できるようになり、評価への不満も減ったように感じます。

# まとめ
モチベーション維持の取り組みについて紹介しました。  
今回はMattermostの機能を利用しましたが、チャットツールの「いいね」を利用する方法もありそうです。
日常的に感謝を伝えることはモチベーション維持に関わらず大切なことですが、感謝の強要のようになってしまってストレスを感じないように注意が必要です。  
今回ご紹介したように、気軽に感謝を伝えることは、お互いが必要とすることの可視化にもつながります。  
一度お試しになってみてはいかがでしょうか。
Go の Scanner で CSV インポートファイルを読み込む際の改行コードの扱いについて

## 問題
Go の Scanner の挙動の違いにより、CSV インポート時のカウントにズレが生じました。

例えば **CSV ファイルの中身が「`A \n B`」** のように 1 行の中に改行コードを含む場合。
改行コードも含めて 1 行と見なしたいケースを想定します。

下記①の場合ですと、改行コードで分割されて 2 行、
②の場合だと改行コードも含めて 1 行でカウントされます。

今回は②の挙動を期待していたのに、①の処理がなされていたために、想定するカウントとズレが発生した、という問題についてです。

## ①.`bufio.NewScanner`における`Scan`メソッドの挙動
### 処理
```
scanner := bufio.NewScanner(csv)
num := 0
for scanner.Scan() {
    num++
}
fmt.Println(num)
```

### 出力結果
```
2
```

### 説明
- [func NewScanner(r io.Reader) *Scanner](https://pkg.go.dev/bufio#NewScanner)

公式によると、`The split function defaults to ScanLines.`とあります。

- [func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)](https://pkg.go.dev/bufio#ScanLines)

そして、`The end-of-line marker is one optional carriage return followed by one mandatory newline.`とあります。

つまり、デフォルトでは改行コード（`\r?\n`）を見つけると、行末だと判断して 1 行分のデータを返す、ということになります。

### 補足
`bufio`パッケージは、「バッファリング（一時保存機構）付き I/O」を提供してくれます。
参考：https://pkg.go.dev/bufio


## ②.`csv.NewReader`における`Read`メソッドの挙動
### 処理
```
scanner := csv.NewReader(csv)
num := 0
for {
    _, err := scanner.Read()
    if err == io.EOF { // ファイル終わりに到達した場合は、ループを抜ける
        break　
    } else if err != nil {
        return err
    }
    num++
}
fmt.Println(num)
```

### 出力結果
```
1
```

### 説明
- [Package csv](https://golang.google.cn/pkg/encoding/csv/)

上記 csv パッケージの説明に記載されていますが、`Carriage returns before newline characters are silently removed.`とあります。

つまり、改行コードで改行されることはなく、改行コードも含めた行末までを 1 行として返す、ということになります。
ホワイの(感動的)rubyガイドが読み物として面白い

# 読書をしているか？

読書をしているか？　『リーダブルコード』を読んだ？　面白かったか？　ほんとうか？　次は『オブジェクト指向でなぜつくるのか』を読む？　本当か？　**本当にそんな役に立つものばかり読むのか？**

リーダブルコードは結構ユーモアにあふれて読みやすく、好きだった。
しかしたまには不真面目な読書もしたい。

『ママ、なぜおうちにサーバーがあるの？』も読め。

たぶん非売品なのだが作者さんが全文をのっけてくれている。

https://qiita.com/uikou/items/e4843f0bce940927de96

そのタワーが「デスクトップPCではなくサーバーである」と理解しているお子さんはもうなんていうか、それだけでおかしい。

## ホワイの(感動的)rubyガイドを読め（無料だ）

ところで、俺は『ホワイの(感動的)rubyガイド』が好きだ。
しかもこれは無料である。
ユーモアにあふれていて面白いので、いろんな人に読んでほしいと思っている。

http://www.aoky.net/articles/why_poignant_guide_to_ruby/

ノリとしてはこんな感じである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/8d17e341-240e-1a37-b9c8-ff7a7e0153ba.png)

>1. この本を開く
この本を開いた振りをして(たぶんこの本を開いているのだろうけど)、本の折り目の真ん中に大きなタマネギを見つけたつもりになってほしい。(この本の製造者は私の要望に応じてタマネギを入れたのだ。)
>それであなたは「すごい、この本にはタマネギが付いてるぞ!」と思う。(たとえあなたがタマネギは別に好きでなくとも、プログラミングマニュアルとされるものの中に注意深く農産物を入れて出荷するロジスティックスはすごいと思うに違いない。)

全体的にはちょっとシュールでナンセンスであり読むのに疲れる文章ではある。
（漫画もオチがついているというよりはシュールな挿絵だなあ、と感じる。）

まじめなガイドではないかもしれない。それでもユーモアにあふれていてめちゃくちゃ面白い。ガイドだ。
rubyのコーディングガイドである。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/6fa84bc0-ff1c-05a8-34d6-5453ae68f5ff.png)

書いた人もすごいが訳した人もほんとうにすごい。

こういうのが好きで、ほんとに好きすぎてしょうがないのだがなかなか見つからないので知ってるのあったら教えてほしい。仕事中にとはいわないが、職場で見ても怒られないような奴だと嬉しい。
Power Apps で 検索したレコードを一括更新する方法（2024年版）

# はじめに
Power Apps で 検索したレコードの値を一括で修正したいという要望は多いかと思います。
まぁ一括変更というと ```ForAll```関数と```Patch```関数を組み合わせればいいじゃないと思うかもしれません。

しかし、その際のレコード指定方法がちょっと変わっていたので、記事にまとめます。

# Microsoft Learn では

https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/create-update-records-bulk

ここでは、式の例が掲載されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/3d03ac21-1911-0ecb-6f6c-d50087561e4c.png)

しかしながら、実際に似たような形で書いてみると、以下のようなエラーが発生し、正しく登録することができません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/2709fd9f-7976-c03f-478c-ca9f62d7af78.png)

# ThisRecord の ID で LookUp したレコードを指定する

では、以下のように ```LookUp``` した場合はどうか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/bb761b36-e320-6ad8-9863-fe127d482853.png)


```php
ClearCollect(testdata1,Filter(テスト1,value>3));
ForAll(
    testdata1,
    Patch(
        テスト1,
        LookUp(
            テスト1,
            ID=ThisRecord.ID
        ),
        {
            text:TextInputCanvas1.Value
        }
    )
)
```

ですが、以下のようにネットワークエラーが発生してしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/c35585db-bed1-8600-183c-9d674b6458d1.png)


どうも正しく更新対象のレコードが取得できていないように思います。  
※前はこれでいけてたように気がするけど・・・

# [正解]ThisRecordを指定すればいいだけ

ダメ元で試した結果なんですが、```ForAll``` 中の ThisRecord を ```Patch``` の レコードとして指定すれば良いようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/8a495650-5a90-87a4-7fc7-ef6c3c0b2606.png)

```php
ClearCollect(testdata1,Filter(テスト1,value>3));
ForAll(
    testdata1,
    Patch(
        テスト1,
        ThisRecord,
        {
            text:TextInputCanvas1.Value
        }
    )
)
```

# まとめ

ギャラリーとかで選択したものを一括変更はよくありますが、入力した文字列などで検索して一気に検索というパターンも需要があると思います。
そんなときは、こちらのやり方をぜひお試しください！
ChatGPTと楽天の商品価格ナビ製品検索APIを使って買い物サイトを作ってみた

## はじめに
最近になって仕事で触る技術に大幅に変化があったため、学習を兼ねてというのとAIと協力して何か作ってみたいという思いがあったので実行してみました。
何か真新しいことをしたわけではないので技術寄りの話というよりは作る上で考えたことを中心にまとめたいと思います。
### サイトの概要
まずサイトを作るなら自分自身にも関係があって日常的に利用できるものがよいと思い、商品検索サイトを作ることにしました。
コンセプトはお得な商品を検索して買い物上手になろうということで「買い物上手」→「KAI-JAWS」という発想でサイト名を決めました。
楽天の商品価格ナビに掲載されている商品をキーワード、価格、ジャンル情報をもとに検索・絞り込みを行い、スクロールによって次のリクエストが飛んで追加の結果を描画するシンプルな形にしました。
実際のサイトはこちら↓
https://kai-jaws.com

![2024-06-27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822858/f06d13b1-a748-f217-ad52-128dba69d0df.png)

ちなみにサイトのロゴもAIに作ってもらってます。少し手直ししてますが、ほぼAIが作ったまま使ってます。

### なぜChatGPTと楽天の商品価格ナビ製品検索APIを使ったのか
まずなぜChatGPTを使ったかというと、AIで簡単にWebサイトが作れるといろんなところで言われている中、本当のところどうなんだろうというのを体験してみたかったというのが大きかったです。
あと新しく触れるようになった技術についてまだ習熟が浅かったので、AIに聞いて理解しながら進めたかったというのもあります。

次になぜ楽天の商品価格ナビ製品検索APIを使ったのかというと、無料かつ有名どころのショッピングサイトのAPIであればとりあえずOKかなという感じで選びました。本当は普段Amazonで買い物することが多いのでAmazonのAPIの使いたかったのですが、料金はかからないが利用のためには一定のサイト基準を満たしていなければならなかったり、その審査を突破できる自身がなかったことから断念しました。
AmazonのAPIが使えたらKeepaAPIと連携して過去の価格情報から買い時を見極められるサイトにしようかとも考えましたが、KeepaAPIは有料かつ円安の影響で相当コストが嵩みそうだったのでこれも断念する理由になりました。

### 使用技術について
Ruby v3.3.1
Ruby on Rails v7.1.3.4
React v18.2.0
Next.js v14.2.3
TypeScript v5.4.5
heroku
Vercel
ChatGPT GPT-4o

### ChatGPTをどう使ったか
ドメインをとってサイトを公開するということが初めてだったので、ChatGPTには作ろうと思っているサイトのコンセプトと使用技術、サイトを構築するうえで必要な事項をまとめてもらうよう指示しました。
すると、楽天のAPIの使用方法、バックエンド、フロントエンドの具体的な実装、ドメインの取得方法、ホスティングサービスへのデプロイの仕方などすべてまとめてくれたのであとは実装部分以外ほとんどChatGPTが指定してくれたことをそのまま行動に移しました。
実装もサーバーサイド側に関してはほぼChatGPTの指定のまま実装に組み込みましたが、フロントエンドに関してはUIや細かい動きの部分はChatGPTだとうまく調整できなかったので自前でやりました。
他、実装で困ったことがあったり、これできるかなと思ったことはとりあえずプロンプトを投げると解決してくれるので、ChatGPTが返してくれた結果を調整して組み込むみたいな流れでだいたいいけました。

### 楽天APIの利用方法
Rakuten DevelopersでアプリIDを新規発行するとアプリID、application_secret、アフィリエイトIDが払い出されます![2024-06-27 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3822858/29f8a95b-3b23-69de-fe7c-1fc3fa415521.png)

あとはこの情報をバックエンド側に持たせてAPIリクエスト時に渡します。
APIのリクエストの仕方や取得できるデータなどは楽天のドキュメントに詳しくまとまっているのでそこを参照しました。
今回は商品価格ナビ以外にジャンル絞り込み機能の部分で楽天市場ジャンル検索APIを使ってます。他にもいろいろあるので機会があれば使ってみたいですね。

### こだわった点
サイトを作成するうえでこだわったこととしては、ユーザー情報を極力保持しないということとコストをかけずにサイトを公開し続けるため無料枠内でサーバーの運用が抑えられるようにすることでした。
ユーザー情報を保持しないのは個人情報などの情報を取り扱うようになると何かあったときの責任を取り切れないというのと、サイトの商品情報はAPIを介して取得しているため、個人情報を保持しないことでDBも構築しなくてよくなるのでコストがかかる因子を減らせるためです。もちろんDBも無料枠で運用することはできると思いますが、念のため。

ユーザー情報は保持しない方針にしましたが、ローカルストレージ上に閲覧履歴やお気に入り情報を保持するようにしているので、同じ端末であればそういった機能を享受することができるようになっています。

### ChatGPTをサイト制作に使う上で課題と感じたところ
自分の指示が悪かったと思いますが、UI・UX方面に関してはあまり期待できない返答が返ってくることが多かったです。が、アニメーションやUIライブラリについては期待通りの答えを得ることができました。
また、楽天はジャンルの階層がかなり深くジャンル関連の処理に関しては複雑になりがちだったのですが、そこをChatGPTを使って期待通りの処理までもっていくのが難しいと感じました。
あるところまで行くと書き方は違うけど挙動としては全く変わらないようなコードをずっと吐き出すようになってしまい、結局そういった部分の実装は自前で行いました。

### まとめ
ChatGPTを使ったサイト制作はうまいプロンプトを作ることができれば、ほぼ自分でコードを書かずに公開まで行けるのではないかなと思いました。
そこまでいかなくとも実装時のアドバイザーとしてついてくれるだけで相当効率が上がるのではないかなと思いました。
今後はAIを絡めたサービスも何か作ってみたいと思います。

些末な記事になりましたが、ここまで読んでくれた方ありがとうございました。

### 参考リンク
https://kai-jaws.com

https://webservice.rakuten.co.jp/

https://webservice.rakuten.co.jp/documentation/ichiba-product-search
Rubyで英語名称のポケモンの名前を日本語で当てるゲームを作ったよ

### 読んで欲しい人

- rubyでプログラムを作ってみたい人
- 過去の自分

### 動作環境

- ruby 3.3.3

### アプリについて

#### ファイル構造
```ファイル構成
.
├── pokemon.rb
├── pokemon.csv
```

#### ソースコード
```ruby:pokemon.rb
# ファイル内でcsvライブラリ（モジュール）を使用するための記述
require 'csv'

# CSVファイルを読み込む
def load_pokemon_from_csv(file_path)
  pokemon_data = []
  # foreachにheaders: trueをすると、keyとvalueをいい感じに扱ってくれる
  CSV.foreach(file_path, headers: true).each_with_index do |row, _i|
    pokemon_data << row.to_hash
    break if _i == 150
  end
  pokemon_data
end

def main
  file_path = 'pokemon.csv'
  pokemon_data = load_pokemon_from_csv(file_path)

# sampleは配列からランダムに1つ返してくれる
  random_pokemon = pokemon_data.sample

  puts "#{random_pokemon['name']}は日本語では何と呼ばれますか？"
  japanese_name_input = gets.chomp.downcase

  correct_japanese_name = random_pokemon['japanese_name'].downcase.gsub(/[a-z]/, '')

  if japanese_name_input.include?(correct_japanese_name)
    puts '正解！'
  else
    puts "残念！正解は#{random_pokemon['japanese_name']}でした！"
  end
# 例外時の処理
rescue StandardError => e
  puts "エラー: #{e.message}"
end

main

```

#### csvファイル
[ポケモンの情報が載っているCSVファイル](https://gist.github.com/leoyuholo/b12f882a92a25d43cf90e29812639eb3)
　　↑
めっちゃ細かく記述してあります。びっくり

```csvs:pokemon.csv
pokedex_number,name,japanese_name,base_total,attack,defense,sp_attack,sp_defense,speed,hp,capture_rate,experience_growth,type1,type2,classification,generation,is_legendary,x,y
1,Bulbasaur,Fushigidaneフシギダネ,318,49,49,65,65,45,45,45,1059860,grass,poison,Seed Pokémon,1,0,2.0027124881744385,-23.850000381469727
2,Ivysaur,Fushigisouフシギソウ,405,62,63,80,80,60,60,45,1059860,grass,poison,Seed Pokémon,1,0,-4.191871643066406,-1.011356234550476
3,Venusaur,Fushigibanaフシギバナ,625,100,123,122,120,80,80,45,1059860,grass,poison,Seed Pokémon,1,0,16.135290145874023,25.56937026977539
...
めっちゃ続く
```

### 学び・感想
- RubyでCSVの扱い方を知れました
- RailsをやるにはRubyの基礎を〜と言うことで、Rubyもどんどん書かないとなぁ

### 参考記事

https://docs.ruby-lang.org/ja/latest/method/CSV/s/foreach.html

https://docs.ruby-lang.org/ja/latest/method/Array/i/sample.html
[備忘録]　バスロケーションシステムについて分かったこと

# 備忘録[1,2,3]
- バスロケーションシステム：バスの接近情報やバスが停留所に到着するまでの所要時間等の情報を乗車客に提供するシステムのこと[1]
    - バスロケベーシック：バスの位置情報の活用に特化したシステムのこと[2]
        - 低コスト・短納期
        - 車両に設置した専用機器で位置情報や加速度情報を収集
        - リアルタイムに位置情報や遅延情報などの情報を提供する
        - システム構成としてGPSマルチユニットが活用されている
        - GTFS-JP（標準的なバス情報フォーマット）に準拠したマスタフォーマットでデータを管理する
        - 車両アイコンをクリックしたら運行状況の詳細が一目で分かる
        - バスロケシステムをMixsodaで自作[3]
            - GPS車載器
            - 位置情報から現在地を地図にプロットするWebアプリ
                - アイコン設定が可能
                - リンク設定
                - 自動更新設定
            - X-Loca用のBASICプログラムのインストールに必要な機材のセットも販売 (11000円)
    



# 参考文献
[1]"庄内交通のバス情報があなたのスマホに　バスロケーションシステム"
https://www.shonaikotsu.jp/local_bus/bus_location_system.html

[2]"新たなバスロケーションシステム「バスロケベーシック」を開発（PR TIMES）"
https://mainichi.jp/articles/20240516/pr1/00m/020/117000c

[3]"DIYなら1車両の通信費が月額330円！ 自社でつくるバスロケシステムを応援します！"
https://www.dreamnews.jp/press/0000292394/
PythonでExcelのデータを検索・置換する

エクセルの「検索と置換」は、大量のデータを素早く整理・処理するのに役立つ非常に便利な機能だ。これを使うことで、データを一つ一つ手作業で修正する手間を省くことができ、作業効率が向上する。

**Pythonを使ってExcelのデータを検索・置換するには**、[Spire.XLS for Python](https://www.e-iceblue.com/Introduce/xls-for-python.html)ライブラリを使います。

* [【Python】Excelワークシートのデータを検索して置換する](#python-excelワークシートのデータを検索して置換する)
* [【Python】指定したセル範囲のデータの検索と置換](#python指定したセル範囲のデータの検索と置換)



### その手順は以下の通りです：
**1.**	以下のpipコマンドを使用して、[**Spire.XLS for Python**](https://www.e-iceblue.com/Introduce/xls-for-python.html)ライブラリをインストールします：
`pip install Spire.XLS`

**2.**	インストール後、spire.xlsライブラリと必要なモジュールをインポートします；
**3.**	**`LoadFromFile()`** メソッドを使用して、Excel ドキュメントをロードします；
**4.**	指定したワークシートまたはセル範囲を取得し、**`FindAllString()`** メソッドを使用して指定したデータを検索します；
**5.**	見つかったセルを繰り返し処理し、その中のデータを置換する； 
**6.**	生成された Excel ファイルを保存する。


> 以下は、Excelのワークシートやセル範囲内のデータを検索して置き換えるための2つのPythonコード例です。:point_down:


## 【Python】 Excelワークシートのデータを検索して置換する
```python
from spire.xls import *
from spire.xls.common import *
 
# Excelファイルを読み込む
workbook = Workbook()
workbook.LoadFromFile("input.xlsx")
 
# 最初のワークシートを取得する
worksheet = workbook.Worksheets[0]
 
# ワークシートで「調整部門」を含むセルを見つける。
ranges = worksheet.FindAllString("調整部門", False, False)
 
# 見つかったセルを繰り返し処理する。
for range in ranges:
    
    # データを置き換える
    range.Text = "企画部"
 
    # ハイライトカラーを設定する
    range.Style.Color = Color.get_Yellow()
    
# ファイルを保存する
workbook.SaveToFile("FindReplace.xlsx", ExcelVersion.Version2016)
workbook.Dispose()
```

上記のコードは、エクセルのワークシートで「調整部門」というテキストを含むすべてのセルを見つけ、その値を「企画部」というテキストに置き換える。さらに、置換されたデータを強調するためにセルの背景色が設定される。
![ExcelReplaceExcelData.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811193/e793d768-e833-87b9-f5f2-852a00202289.png)



## 【Python】指定したセル範囲のデータの検索と置換
```python
from spire.xls import *
from spire.xls.common import *
 
# Excelファイルを読み込む
workbook = Workbook()
workbook.LoadFromFile("input.xlsx")
 
# 最初のワークシートを取得する
sheet = workbook.Worksheets[0]
 
# 指定したセル範囲を取得
range = sheet.Range["A3:D6"]
 
# セル範囲から「調整部門」を含むセルを探す
cells = range.FindAllString("調整部門", False, False)
 
# 見つかったセルを繰り返し処理する。
for cell in cells:
 
    # データを置き換える
    cell.Text = "企画部"
 
    # ハイライトカラーを設定する
    cell.Style.Color = Color.get_Yellow()
 
# ファイルを保存する
workbook.SaveToFile("FindReplaceinRange.xlsx", ExcelVersion.Version2016)
workbook.Dispose()
```

このコードサンプルでは、まず **`CellRange.FindAllString()`** メソッドで指定範囲のデータを検索し、**`CellRange.Text`** プロパティで値を置換します。

* * *
Pythonを使ってExcelファイルを操作するチュートリアルをもっと見る：

https://www.e-iceblue.com/Tutorials/Python/Spire.XLS-for-Python/Program-Guide/Spire.XLS-for-Python-Program-Guide-Content.html
マージした（Merged）ブランチを取り消す

## 概要
マージをするとマージコミットがmasterに反映されます。
そのコミットを`revert`する（取り消す）コミットを**masterで**新たにコミットすると、マージする前のmasterの状態に戻ります。この時に-m1オプションを含めます。

## 具体的なコマンド
-m1を指定すると、マージコミットが作成されたときの最初の親（通常はマージ操作を開始したブランチ）の状態に戻します。

例えば、以下のコマンドは最初の親を基準にマージコミットを元に戻します：
```
git revert -m 1 ddfec34a0996e1d9e98428cdb3152b2ee3b14bd6
```

ここで、`ddfec34a0996e1d9e98428cdb3152b2ee3b14bd6`はマージしたコミットのハッシュ。→　ゆえにマージブランチの反映が取り消される。

その一方で、revert操作は競合を引き起こす可能性があるときは、競合解決してからコミットを完了してください。

## Revertした後、再度マージする
リバートしたら再度、取り消したマージ内容を盛り込んだPRを作りたいです。

そのときは再度、前段のRevertしたコミットを含めた状態から、ブランチを切り、
そのRevertコミットを再度、**ブランチ内で**Revertしてください。
そうすることで、はじめの取り消したマージのコミット内容が再度、masterブランチにたいする差分として元に戻ります。
solana 開発勉強日誌5 solana-jupiter-bot（アトミックアービトラージ

botを一から作るのは難しい。
<br>
<br>


そもそも何したらいいのか分からない、
と思っていた過去の自分が読みたかった内容を書く
<br>
<br>
<br>


solana 開発勉強日誌1.2.3をやると何となくtxの事や、
https://solscan.io/ の見方が分かってくる
自分で作り送信したtxと教材を見比べないと
何となく分かるけど、曖昧だなぁって状況から抜け出せない。
その上で、さるおさんのNOTEを読むとより理解度が上がる。



https://note.com/saruo_hunbook/n/ne4bc7b0da5b1

https://note.com/saruo_hunbook/n/n45589edc9170

<br>
<br>
<br>
<br>
<br>
<br>



みんな大好きアトミックアービトラージ
動くプログラムで勉強する

<br>


https://github.com/ARBProtocol/solana-jupiter-bot

<br>
<br>
<br>
コマンドプロンプト（windows）やターミナル（mac）で入力


```
git clone https://github.com/arbprotocol/solana-jupiter-bot
```
```
cd solana-jupiter-bot
```
```
yarn
```

環境構築はChatGPT４（課金ver）がオススメ
git clone https://github.com/arbprotocol/solana-jupiter-bot 
とコマンドをコマンドプロンプト（windows）やターミナル（mac）で入力してみて
エラーが出たらそのままエラー文をChatGPT４に入力して、
環境構築するのが一番早いと思う

<br>
<br>
<br>
<br>
<br>
<br>



DLしたフォルダ内にある
.env.exampleファイルをコピペして
.env に名前を変更する
.envには自分のウォレットの秘密鍵とsolanaブロックチェーンと通信する為に個別RPCアドレスを入力する


```.env
DEBUG=false
SKIP_INTRO=false
UI_COLOR=cyan
TRADING_ENABLED=true
WRAP_UNWRAP_SOL=true
NODE_ENV=production
SOLANA_WALLET_PRIVATE_KEY=自分のウォレットの秘密鍵を入れる
DEFAULT_RPC=https://change-this-url-in-env（自分のRPCアドレスを記入
ALT_RPC_LIST=https://change-this-url-in-env.gov,https://change-alt-urls-in-env.com
```

![スクリーンショット 2024-06-27 170327.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573208/0ac624ec-2828-b4bb-5798-620ad829b08f.png)

Phantomならここから秘密鍵を表示できる
注意・メインウォレットを使うの良くない。bot専用に別アカウントを作成する

<br>
<br>
<br>
自分のRPCアドレスを作成する。無料でalchemyが使えるので今回はこれをオススメ

（色んなサービスがある、各自調べた方が良い）

https://www.alchemy.com/


分かり易くざっくり説明すると、
ブロックチェーンにTxを送信したりするのにはRPCアドレスが必要。

<br>

<br>
<br>
<br>



必要なDLやPATHを通すコマンドまで教えてくれる


環境構築が完了したら、botのセッティングをする
```
yarn start  （最初にこのコマンド

yarn trade   （セッティング出来たらトレード

yarn wizard   （特に必要ない
```

セッティング出来るとこんな感じ
たまにRPCとの接続が上手くいかない（無料分だから）何度かリトライして下さい


![bot.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3573208/de8687fb-27f3-0317-8101-12010d14c416.gif)



現状のそのまま動くプログラムだから躓く箇所は少ないはず。
環境構築でたまに必要なpackageがDL出来てないとかぐらい
<br>

<br>

https://github.com/ARBProtocol/solana-jupiter-bot/blob/d3e13c1e36af9ae6fa3a7e4b7300ce117736cf81/src/utils/index.js#L184

上記のコードは checkArbReadyがある
詳細は言えないがARB_TOKEN が10ドル分ぐらい必要なのでゴニョゴニョしたりしなかったり各自してください
<br>
<br>
しばらく動かしてみたらまた読み返して、
ふむふむ。を繰り返す

https://note.com/saruo_hunbook/n/ne4bc7b0da5b1

https://note.com/saruo_hunbook/n/n45589edc9170

<br>
稼げるbotではないが、jupiterのAPIを使って
アトミックアービトラージのTxを作る過程の勉強にはなると思います
バーチャルオフィスを利用するための3箇条

<h1>はじめに</h1>

筆者はカスタマーサポート部のマネージャーを務めています。
自社でもコロナ禍でリモートワークが急激に進み、バーチャルオフィスを会社として利用することになりました。
カスタマーサポート部は計40人程在籍しましたが、そのうち退職者はここ3年で数人しかいません。
コールセンター業務を担うIT系のカスタマーサポート部にてこの退職率の低さは驚異的です。
そこに一役買っていたのがバーチャルオフィスの存在だと感じたため、利用方法についてまとめてみたいと思いました。

<h1>前提</h1>

本記事は「リモートワーク最高！」と謳うものではありません。
筆者もコミュニケーションという観点では、全員出社するのが一番良いと思っています。
表情がわからないとニュアンスも伝わりませんし、就業後に「軽く呑みいくか」なんてものは出社ありきですし、コミュニケーションを取らせたいのであれば対面が最強です。
ただ、以下の理由からリモートワークにせざるを得ないのであって、それによって失われるコミュニケーションを補完するものがバーチャルオフィスになるのです。

:::note alert
・席数が足りない
・隣の人と近いため会話中に雑音が入る
・遠方の方も採用したい
・強制的に出社をさせるとモチベーションが下がってしまう
:::

<h1>3箇条</h1>

バーチャルオフィスを利用する際の必須となる心構えになります。
この3箇条をチームとして守れないのであれば、もはや使わない方が良いまであります。

<h3>【常にオンラインにする】</h3>

当たり前でありますが、リアルオフィスを再現するものであるのに、そこに自分以外の誰もいなかったら意味がありません。
これは出社していても同じことが言えます。
コロナ禍で出社してみたら誰もいなくて、「出社しても誰ともしゃべれないな...」と思ったことはないでしょうか。

この取り決めはMUSTであって、「自分は家近いし、毎日出社してるので大丈夫です。」とかではなく、出社していてもオンラインにしなければなりません。

また、「オンラインにすると話しかけられるから、落ち着いて仕事したいのでオフラインにします」という報告があるのですが、それはリアルオフィスでも通用する話ではないのでもちろんNGです。

この取り組みに関して最も意識しなければならないのは、相談役すなわち上長になります。
仕事上のコミュニケーションのほとんどは相談になるので、相手役がすぐそこにいなければ意味がなく、相談役がいないバーチャルオフィスはすぐに破綻します。

すぐに聞けるという安心感が大事なので、1時間以上誰からも話しかけられないこともしばしばありますが、それでいいのです。

<h3>【話しかけられたら必ず聞く】</h3>

バーチャルオフィス内でも心理的安全性を保たなければなりません。
リアルで話しかけたら「今忙しいから後にして」と言われ、以降話しかけるのが億劫になってしまったなんて話はよくあります。
そもそも、オンラインにしているということは話しかけても良い状態なはずなので、そこは優しく対応しましょう。

わざわざ話しかけに来るということは以下の理由が考えられ、後回しにすると不幸なことが起こります。

:::note warn
・内容が複雑で、テキストだと書く方や読む方に工数が生じる。
→読むのが大変で後々結果呼び出す。
・急ぎ案件なためすぐに報告したい。
→なぜもっと早く相談しなかったんだとなる。
・テキストに残すほどのことでもないが、サクッと聞きたい。
→聞かずに進行して、結果間違った方針に進む。
:::

相談される側は逆に今聞かないと、後々自身の業務が増えることを理解しなければなりません。


<h3>【社内ミーティングはバーチャルオフィス上でおこなう】</h3>

バーチャルオフィスを利用していない頃に起きたのが、「相談しようと思ったら相手のカレンダー埋まってる問題」です。
蓋を開けてみると、実質10分で話が終わるミーティングを30分の枠で埋められており、意外と空いている時間がありました。
ただ、このスキマ時間は出社していないとわからないのです。

カレンダーを30分抑えることは良いですが、その場をバーチャルオフィス上に移すことによって、周りはミーティングが終わったことを認識できるようになります。
そうなると、相談者はスキマ時間を見つけて話すことが可能になります。

相談役は定時後しか時間抑えられないのは、結果的にチームの残業時間を増やしていることを自覚しなければなりません。

<h1>まとめ</h1>

いろいろ書いてきましたが、先述の通り全員が出社できるのであればそれが一番良いです。
ただ昨今それが難しいと思うので、もしバーチャルオフィスを検討することがあれば是非参考にしてみてください。
「いやいや、うちの業務はオンラインにする暇ほんとにないから無理だよ」という声が聞こえてきそうですが、それは仕事が一人でできる方の意見です。
特に新入社員の様な迷える子羊には手を差し伸べる姿勢が大事なのかも知れません。
日中はほとんど電話対応をおこなっている我々カスタマーサポートが利用できているのであれば、後は覚悟だと思います。
rex0220 計算式プラグイン 最大値・最小値があるテーブル行の文字列

[rex0220 計算式プラグイン](https://qiita.com/rex0220/items/ae83c6d5ce50ff7a9a73)で、 最大値・最小値があるテーブル行の文字列を取得します。

# 概要

テーブル内数値項目の最大値・最小値と対象行の文字列を取得します。

![2024-06-27_17h30_57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/c1d708c7-498d-d24e-05e4-d40bc5abab43.png)

# 計算式プラグイン設定

FIRSTIF 関数で、最大値・最小値の値を持つテーブル行の文字列を取得できます。

![2024-06-27_17h34_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4b0f2e74-b01f-9afc-761f-229f9ebcec88.png)

```.js
// 最小値の文字列 SINGLE_LINE_TEXT
FIRSTIF(最小値=数値T,文字列T)

// 最小値 NUMBER
MIN(数値T)

// 最大値の文字列 SINGLE_LINE_TEXT
FIRSTIF(最大値=数値T,文字列T)

// 最大値 NUMBER
MAX(数値T)
```
QGISの知っていると便利な機能３選（スタイルコピペ、レイヤの固定、統計サマリー表示）

あまり目立っていない（?）けれど便利なQGISの機能を３つ紹介します！

## レイヤのスタイルをコピー＆ペースト
QGISでレイヤのスタイルを設定するのって結構大変ですよね。
例えば人口メッシュを可視化する時には、同じスタイルを使いまわしたいシチュエーションが多いかと思います。
そんなときは、スタイルのコピーとペーストを使いましょう！
シンポロジだけでなく、ラベルなどの設定もコピペできます。

![スタイルのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2930990/34a3923c-8cc3-7a8e-99a8-34049f382632.png)

![スタイルのペースト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2930990/9acad206-a470-7449-436e-304fb53d6408.png)

![複数レイヤへのスタイルのペースト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2930990/fc433d06-20ed-e791-6f63-dbd128dcebee.png)

## レイアウトで表示するレイヤを固定する
画像出力などをする際にレイアウトを作成するかと思うのですが、その際に「このレイアウトではこのレイヤを表示したい」ということもよくあるかと思います。
そんなときは、レイアウト画面の設定で「レイヤを固定」のチェックボックスをオンにしましょう！
作業画面でレイヤの表示を切り替えたとしても、「レイヤを固定」したレイアウトを開くと、固定した時点で表示していたレイヤ表示構成で表示されます。
表示するレイヤの種類が複雑なときほど役立つ機能かと思います。
ちなみに、「レイヤのスタイルを固定」でスタイルも固定できるようです。

![レイヤの固定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2930990/12ea0c23-07d4-aa17-52db-467ea1a4f7e1.png)

## 統計情報を表示してデータの概況を把握する
人口メッシュなどの統計データを利用する時には、データの概況を把握したくなりますよね？
そんなときは、「統計サマリー」機能を利用しましょう。
ポチッとするだけで、サクッと情報が表示されます。

![統計サマリー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2930990/0ce385df-d8b6-b554-0074-c53472f24e46.png)