OmniAICreator/Qiita-1.07M huggingface dataset:
[Xcode / Swift] TabBarを利用して画面遷移をする

![スクリーンショット 2023-11-07 18.10.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569708/e8ca6a57-c06c-3472-75fc-553f218f62a2.png)
画面の下部にTapBarを設置し押下で画面遷移する方法

### StoryBoard
右下のマークをクリックし、Tap Bar Controllerを選択。
![スクリーンショット 2023-11-07 18.19.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569708/d889cec9-ecea-b849-aef3-0638c5dc9dd2.png)

選択後、以下のように表示されます。
![スクリーンショット 2023-11-07 18.16.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569708/0c542782-5222-f241-fad7-c1e190cc449d.png)

View Controllerを２つ追加します。
![スクリーンショット 2023-11-07 18.23.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569708/5a7b1c4e-5d08-9e85-2b5e-fa108713d5fc.png)

Tap Bar Controllerの以下の部分をcontrolボタンをクリックしながらクリックし、各View Controllerまでドラッグしてview controllersを選択します。
![スクリーンショット 2023-11-07 18.28.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569708/19a42ea8-2bcb-446a-77bd-cd16ab6ab287.png)
![スクリーンショット 2023-11-07 18.25.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569708/f11f6dd0-9756-f44d-6b5e-5eecea6d49ac.png)

以下のようになっていればこの段階で遷移は可能です。![スクリーンショット 2023-11-07 18.30.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569708/8b8db935-699e-9073-e229-6dc7d9718581.png)

ですが、これではTapBarのItemのロゴが全て同じなので、以下のようにItemのロゴとタイトルをHomeとし、Home画面に遷移した際にわかりやすいようにUILabelでHome画面と表示させます。

①Itemのタイトルとロゴ
②UILabel
![スクリーンショット 2023-11-07 18.31.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569708/bf2c1a30-2513-7660-9c3d-970c6ea91d3e.png)

他二つのTabBarのItemも同様、以下のようにカレンダー、プロフィールのロゴとし、各画面にCalendar画面、Profile画面と表示されるようにUILableを設置します。

![スクリーンショット 2023-11-07 18.36.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569708/d2bc757f-879b-cb80-c1c7-e9bd51c30fb2.png)

以上を完了し実行すると、constraintsをつけていないので上記のようにUILableが真ん中には表示されていませんが、各画面に遷移できることがわかります。
![Simulator Screenshot - iPhone SE (3rd generation) - 2023-11-07 at 18.44.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569708/5fc497d7-e892-9147-53aa-f129b3ecb4c4.png)
【JavaScript】isHoge === falseを擁護する

## 予防線

勘違いされそうなんで先に書いておきますが、私は`!`派です。

## 前提

ifの条件式の部分で真偽値ではない値を他の値と比較せずに書くことを禁止するコーディング規約があるとします。

## trueと比較する愚かさ

```js
if (isHoge === true) something();
```

上記のコードはisHogeがtrueかどうかを比較している。
しかし、isHogeがtrueならtrueだし、falseならfalseになるのは明らかだ。
比較する処理が冗長なのは言うまでもないだろう。

```js
if (isHoge) something();
```

また上記のようなコードが書かれていたら大半のプログラマは
「isHogeがtrueのときにsomethingが実行されるのね」と0.001秒で分かるだろう。（伏線）

## isHoge === falseはどうなのか？

```js
if (isHoge === false) something();
```

上記のようなコードも嫌われがちだ。
彼らは言うだろう。「falseと比較するな、`!`を使え。」と。

```js
if (!isHoge) something();
```

確かに`!`を使ったほうがコード量が減りきれいに見える。
そう、確かにそういう利点はある。だが…

## 現実

現実世界では大量に書かれているif文、条件がものすごく長いif文を見なければいけないことがある。
仮になんかの処理でif文が100個くらい書かれていたとしよう。

```js
if (isHoge1) { /* 長い処理 */ }
if (isHoge2) { /* 長い処理 */ }
if (isHoge3) { /* 長い処理 */ }
// 省略…
if (isHoge50) { /* 長い処理 */ }
if (!isHoge51) { /* 長い処理 */ }
if (isHoge52) { /* 長い処理 */ }
// 省略…
if (isHoge98) { /* 長い処理 */ }
if (isHoge99) { /* 長い処理 */ }
if (isHoge100) { /* 長い処理 */ }
```

（はっきり言ってこんなコードは最低最悪だが、現実では動きゃいいだろ思考のコピペプログラマやFizzBuzzを1時間考えても実装できないプログラマが存在するので、たまにこういうコードを目にしてしまうことが不幸にもある。）

さて、このクソ多いif文のなかでisHoge51だけfalseであるときにifの中身が実行されるようになっている。
じっくり見れば分かるかもしれないが、我々の時間は有限であり、こんな処理はパっと見でしか見ないのだ。見落としても仕方ないだろう。

…仮にこの処理でバグがあったとする。
さらにその原因が「isHoge51がtrueであるときにif文の中身が実行されると勘違いしたから」だとする。

そんなとき、人は同じ過ちを犯さないようにこう直すのだ。

```js
if (isHoge1) { /* 長い処理 */ }
if (isHoge2) { /* 長い処理 */ }
if (isHoge3) { /* 長い処理 */ }
// 省略…
if (isHoge50) { /* 長い処理 */ }
if (isHoge51 === false) { /* 長い処理 */ }
if (isHoge52) { /* 長い処理 */ }
// 省略…
if (isHoge98) { /* 長い処理 */ }
if (isHoge99) { /* 長い処理 */ }
if (isHoge100) { /* 長い処理 */ }
```
サイズの大きなファイルを用いた環境構築シェルの開発したときに便利だったbacklogのファイル機能

# 何がしたかったか
業務でとあるシステムを開発しているが、ローカルでOracleDBを動かすのはちょっと大変で、そこそこファイルサイズのでかいzipが必要だったりする。

環境構築自体は一通り流れは確立していてREADME.mdの通りにコマンド1つ1つ実行したら出来はするが、実行すべきコマンドが多いのと、Oracleのzipのサイズが2.8GBあるし、手動でダウンロードして長い時間を待って手動で指定したフォルダに移動してdockerコマンド実行したりと新人なら何かしらミスして失敗する可能性がある。あと新人じゃなくてもラクをしたい。一部環境構築し直しもラクしたい。

ということで、全ての環境構築を1つのシェル実行だけで完了してしまうシェルを作りたくなり、作った。

# 2.8GBあるzipファイルのダウンロード・指定フォルダへの配置の自動化
今回の環境構築シェル実装前はGoogleドライブに配置していて手動でダウンロードする手順になっていたが、会社からもらっているアカウントのファイルに対して誰でもアクセス可能な権限をつけたくなかったのとダウンロードが多少複雑になるので、他に何か探していたら、普段タスク管理しているbacklogを思い出した。

backlogのファイルアップロードはブラウザからだと1GBまでしかできない。これは詰んだ？？と思って調べてみたら、WEBDAV経由だと3GBまでいけることが分かった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/3abc5f1e-f439-17d2-21fd-caa7f64c2695.png)

https://support-ja.backlog.com/hc/ja/articles/360035644814-%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AB%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%AE%E3%81%A7%E3%81%8D%E3%82%8B%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%B5%E3%82%A4%E3%82%BA%E3%81%AE%E4%B8%8A%E9%99%90%E3%82%92%E3%81%8A%E3%81%97%E3%81%88%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84

すぐに設定して、ローカルからbacklogのファイルデータにアクセスできるようになった。(Gドライブみたいなもの)
そこでアップロードしたらいけた。


backlogのAPIはわりとゆるくて、簡単に取得できるAPI Keyを指定するだけで様々なことができてしまう。
今回アップロードするzipは「Oracle Instant Client」で社内オリジナルのデータでもなんでもなく以下からアクセスしてダウンロード可能なデータなので、backlogのAPIをcurlで実行してダウンロードできるようシェルの中に組み込んだ
https://www.oracle.com/jp/database/technologies/instant-client/downloads.html

API Keyの管理についてだが、プロジェクトに参画して実行するのは基本1回だけなので、何か設定ファイル作ってそこに書くようにしたりせず、シェル実行時にターミナルでコピペで入力するようにした。
これが適切かどうかは人によって意見割れそうだが、まああくまで環境構築シェルなので、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/e47dc1af-8827-1b3a-885f-68490cdc4d37.png)


# 感想
他の案件で僕が新人のとき、誰かが作った環境構築シェルで感動した記憶があるが、今度は僕がそれを作れるようになってなんか嬉しい
AWSのAmazonLinux 2023にtomcat9.0.82をインストールする

AmazonLinux2023にTomcat9をインストールする

■Tomcatユーザーの作成 
``` コマンド
useradd -r -s /sbin/nologin tomcat
```

■Tomcatのインストール(/root)
``` コマンド
cd 
wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.82/bin/apache-tomcat-9.0.82.tar.gz 
tar -zxvf apache-tomcat-9.0.82.tar.gz 
mv apache-tomcat-9.0.82 /usr/local/src/
ln -s /usr/local/src/apache-tomcat-9.0.82/ /usr/local/src/tomcat
chown -R tomcat:tomcat /usr/local/src/apache-tomcat-9.0.82
chown -R tomcat:tomcat /usr/local/src/tomcat
```

■Tomcat起動設定の記述(/etc/systemd/system/tomcat.service)
``` /etc/systemd/system/tomcat.service 
[Unit]
Description=Tomcat Web Server
After=network.target

[Service]
Type=forking
User=tomcat
Group=tomcat
Environment="CATALINA_BASE=/usr/local/src/tomcat"
Environment="CATALINA_HOME=/usr/local/src/tomcat"
Environment="CATALINA_PID=/usr/local/src/tomcat/temp/tomcat.pid"
ExecStart=/usr/local/src/tomcat/bin/startup.sh
ExecStop=/usr/local/src/tomcat/bin/shutdown.sh

[Install]
WantedBy=multi-user.target
```
■tomcatの登録
``` コマンド
systemctl daemon-reload
systemctl enable tomcat
systemctl is-enabled tomcat
```

■~/.bash_profileにパスの記述
``` コマンド
vi  ~/.bash_profile
※以下を追記
export CATALINA_HOME=/usr/local/src/tomcat
```

``` コマンド
source ~/.bash_profile
systemctl start tomcat
```

[AWS側での追加作業]
セキュリティグループのインバウンドルールにポート8080の許可を追加する。
インスタンスのアドレス:8080へアクセスし、ブラウザ上でインストールと動作の確認。
Tomcat 9.0.82が表示されればOK

参考(Tomcat10ですが基本は同じ）
https://dev.34-d.net/install-tomcat-10-1-on-al2023/ 
~~https://zenn.dev/lifewithpiano/scraps/d579be009c112b~~

アプリケーションマネージャの機能を使う場合はこちらも参照
（tomcat-users.xmlの編集、context.xmlの編集２か所)
https://nets-tip.com/?p=1329
【Flutter】DrawerHeaderに表示する文字が長くても見切れないようにする

## やりたいこと
DrawerHeaderにユーザー名を表示しているが、長い場合に見切れてしまうので、見切れないようにしたい。
現状：「☆☆☆☆☆アカハライモリ大好き子☆☆☆☆☆さん」と表示しているが、見切れている

![Screenshot_1699344816.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661656/8b8e5814-a3fd-a691-ec8c-352f73e695c7.png)

現状のコード：
```dart
List<Widget> menuList = [];

    ///ユーザー名を表示している部分
    menuList.add(SizedBox(
      height: 65,
      child: DrawerHeader(
          child: userState.nickName != null
              ? Text(
                  userState.nickName! + ' さん',
                  style: const TextStyle(fontSize: 24, color: Colors.white),
                )
              : const Text('メニュー'),
          decoration:
              const BoxDecoration(color: AppColors.mainBackColorMaterial)),
    ));
```


## 試したこと
通常、テキストを折り返すには、Flexibleで囲むといいということだったので、上記のSizedBoxをFlexibleに変更してみた。すると、DrawerHeaderの高さが高くなってしまい、不恰好な見た目になってしまった。DrawerHeaderは、高さを指定しないと、この高さになってしまうよう。しかしSizedBoxで高さを指定すると、最初のように見切れてしまう。

試した状態：
![Screenshot_1699344836.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661656/a6187e90-9fb9-e9ac-09e6-94ef39555e6f.png)

試したコード：
```dart
List<Widget> menuList = [];

    ///ユーザー名を表示している部分
    menuList.add(Flexible(
      //height: 65, ☆Flexibleには高さを指定できないためコメントアウト
      child: DrawerHeader(
          child: userState.nickName != null
              ? Text(
                  userState.nickName! + ' さん',
                  style: const TextStyle(fontSize: 24, color: Colors.white),
                )
              : const Text('メニュー'),
          decoration:
              const BoxDecoration(color: AppColors.mainBackColorMaterial)),
    ));
```

## 解決策
作戦を変更し、折り返しではなく、入りきらない場合は文字を縮小することにした。TextをFittedBoxで囲むことで、文字数に応じて文字を縮小してくれるとのこと。デフォルトでは真ん中寄せになってしまうため、"alignment: Alignment.centerLeft," を指定して、左寄せに変更した。

解決後：
![Screenshot_1699344533.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661656/b480fa78-3f82-0156-d5df-8c577a828491.png)

解決したコード：
```dart
menuList.add(SizedBox( //ここは高さが高くなりすぎないようにそのまま
      height: 70,
      child: DrawerHeader(
          child: userState.nickName != null
              ? FittedBox( //追加
                  alignment: Alignment.centerLeft, //追加
                  child: Text(
                    userState.nickName! + ' さん',
                    style: const TextStyle(fontSize: 24, color: Colors.white),
                  ),
                )
              : const Text('メニュー'),
          decoration:
              const BoxDecoration(color: AppColors.mainBackColorMaterial)),
    ));
```

## 参考
https://qiita.com/koyashi1122/items/abc8248d6d190f8e90c1
シミュレーションは Processing で

こういう「物理おもちゃ」を見ると、すぐにシミューレートしたくなる。

https://youtu.be/yVkdfJ9PkRQ?si=UUO4DYD13KrWpTSf

10年前は、Smalltalk Squeak でやる習慣だった。でもいまは Processing を使う。

この Pendulum Wave は少し前から作り始めて、振り子はできたが、正しい波現象になるための長さの設定が分からなかった。調和級数かなと思ってやってみたが、だめ。

結局 Wikipedia で調べた。まあ、簡単な方程式 (1/n^2) だが、自分で解析して推測できるほどの物理学能力は自分にはもうないので、助かった。

走らせると、いつまでも見ていられる。

あと、Processing の PVector (ベクトル）クラスは物凄く便利。

https://github.com/riktov/processing-pendulum-wave
若手エンジニア奮闘記⑤入社から1年半の軌跡

こんにちは！初めまして！田中です。
IT未経験の田中がIT企業に入社して1年半奮闘したことについて話したいと思います。
楽しかったことや辛かったこと、これは正直もう遠慮したい！と思ったこと、逃げたくなった際の田中なりの気持ちの作り方などを書いていきたいと思いますので、若手の皆さんが同じ事象に出会った際の参考になれたら良いなと思います。
今回はまず田中がこの1年半経験したことをざっくり記載したいと思います。

# 目次

[1 1年目](#1年目)
[1.1 配属後の研修](#配属後の研修)
[1.2 初めての案件](#初めての案件)
[2 2年目](#2年目)
[2.1 初めての後輩](#初めての後輩)
[2.2 初めての勉強会](#初めての勉強会)
[3 まとめ](#まとめ)

# 1年目
## 配属後の研修

入社後3か月間様々なIT知識に関する基本勉強(研修)後に配属が決定しました。
田中はアプリケーション開発チームに配属となりました。
よし！実務だ！頑張ろう！と張り切っていた田中は更なる研修の日々を経験するのでした。
研修で行った詳細はまた別の記事で記載したいと思いますが、自分のチームが扱うアプリケーションの基礎知識及び案件参画に必要な最低限のベース知識を1か月間勉強しました。
時間は短いのですが、感覚的には長い勉強期間でした。実務をしたくて仕方がありませんでした…

## 初めての案件
１か月の研修を経て社会人としての初案件に参画しました！
ドキドキワクワクしていましたが、ここから半年は本当に奮闘の日々でした。
人生(23年間)で一番頑張った時期であり、一番成長をした時期でもありました。
詳しい話は別の機会にしたいと思いますが、一番泣いた時期でもありました。
悔しいことが多すぎました…(´;ω;｀)

# 2年目
## 初めての後輩

題名を見て分かるように田中は運よく先輩になることができました！
チームに後輩が配属されたのです！
本人曰く永瀬廉に似ているとよく言われるらしい。(ファンの皆さんごめんなさい。)
そんな爽やかな後輩ができました。
有り難いことに教育担当を任せてもらえたので、日々ビシバシ鍛えています！
本当のところは田中の方が学ばされる日々です( ´∀｀ )
考え方、伝え方、指導の仕方、成長してもらうために必要なことは何かなどなど…
自分が学ぶのと人に学ばせるのとでは別々の難しさがあるのだと知りました。

## 初めての勉強会

勉強会という名の技術共有会を行いました。
内容としては自分で調査した機能の実装方法を共有する会なのですが、自分より何年も先輩の方々の前での発表だったため、物凄く泣きそうなくらい緊張しました！
ただ、この勉強会は資料作成を含め、自分にとって成長できた場であり成長を感じる場でもありました。

# まとめ

今回は田中が入社して1年半の中で成長のきっかけとなった出来事をざっと書かせて貰いました。
次回以降それぞれの時期に田中が挑戦したこと、頑張ったこと、つらいなと思ったことやモチベーションの保ち方などを書いていきたいと思いますので、読んで頂けたら嬉しいです！
エラーメッセージを出力させる際に"status::unprocessable_entity"が必要な理由

# エラーメッセージを出力させる際に"status::unprocessable_entity"が必要な理由

Railsアプリケーションを開発する際、クライアントからのリクエストに対して適切なHTTPステータスコードを返すことは重要です。特に、バリデーションエラーなどのエラーが発生した場合、その詳細な情報をクライアントに提供することが必要です。`render`メソッドを使用してエラーメッセージを出力する際に、`status::unprocessable_entity`オプションを指定する理由について説明します。

## HTTPステータスコードの役割

HTTPステータスコードは、クライアントとサーバー間の通信において、リクエストやレスポンスの状態を示すために使用されます。正しいステータスコードを選択することは、クライアントに対して適切な情報を提供し、Webアプリケーションの動作を的確に行うのに重要な要素です。

## 422 Unprocessable Entity

「422 Unprocessable Entity」ステータスコードは、クライアントが送信したリクエストを処理できない場合に使用されます。具体的には、バリデーションエラーや不正なデータがリクエストに含まれている場合に返されます。このステータスコードを使用することで、クライアントにエラーが発生したこととその詳細を伝えることができます。

## `render`メソッドと`status: :unprocessable_entity`

`render`メソッドは、ビューをレンダリングし、クライアントにレスポンスを提供するための主要なメソッドです。バリデーションエラーやその他のエラーが発生した場合、`render`メソッドを使用してエラーメッセージをクライアントに返します。

しかし、`render`メソッドだけではステータスコードを指定せずにエラーメッセージを出力すると、デフォルトで200 OKステータスコードが返されます。これはエラーが発生したことをクライアントへ正確に伝えないため、問題が発生します。クライアントは、正常なリクエストと誤解する可能性があります。

`status: :unprocessable_entity`オプションを`render`メソッドに追加することで、エラーメッセージと共に「422 Unprocessable Entity」ステータスコードをクライアントに返します。これにより、クライアントはエラーが発生した事とともに、そのエラー原因を理解できます。

## まとめ
要約すると、`status: :unprocessable_entity`オプションを使用することで、クライアントにエラーが発生したこととその詳細を明確に伝えることができます。これは、Webアプリケーションのエラーハンドリングとユーザーエクスペリエンスを向上させる重要なプラクティスです。
【Flutter】iOSのビルドで、Target release_unpack_ios failed: Exception: Failed to codesignというエラーが出た時の対処法

# はじめに
FlutterのiOSビルドで、`Target release_unpack_ios failed: Exception: Failed to codesign`というエラーが出て、解決したので対処法を記事にします。

# 対処法
ビルド時に、codesignのキーチェーンのアクセス許可を求められたら、許可する。
このタイミングで拒否をすると`Target release_unpack_ios failed: Exception: Failed to codesign`というエラーになります。

https://naoya-ono.com/blog/xcode-error-test2/
Greasemonkey から Tampermonkey に

滅多に使わないが、ページのスクレーピング等に Greasemonkey を使ってた。で今回は画像を別のタブに並べて表示させたかった。なので JS でタブを `open()` して、そこから DOM を作り上げる。

それが、Greasemonkey ではクロスブラウザー違反としてさせてくれない。

Tampermonkey に切り替えたら、すんなり。もう Greasemonkey へは戻らない。
自動デプロイ

# 自動デプロイ

ローカルのターミナルで、以下のコマンドを実行し自動でデプロイする。

ターミナル（ローカル）
```bash
# アプリケーションのディレクトリで
% bundle exec cap production deploy
```

EC2インスタンスの再起動後は、必ず「データベース」「Nginx」の再起動も行いましょう。

ターミナル（EC2内で実行）
```bash
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl restart mariadb 
[ec2-user@ip-172-31-25-189 ~]$ sudo systemctl restart nginx
```
all()関数の使い方【Pythonの組み込み関数】

## all()関数の使い方
all() 関数は、与えられたイテラブル（リスト、タプル、集合など）内のすべての要素が True である場合に True を返し、それ以外の場合は False を返します。以下に、all() 関数の例を示します。
```python:test1.py
#リスト内のすべての要素が True の場合：
A = [True, True, True, True]
result = all(A)
print(result)  # 出力: True
```
```python:test2.py
# リスト内の一部の要素が False の場合：
A = [True, True, False, True]
result = all(A)
print(result)  # 出力: False
```
```python:test3.py
# 空のリストの場合：
A = []
result = all(A)
print(result)  # 出力: True
```
```python:test4.py
# イテレブル内の要素が真偽値以外の場合：
A = [1, 2, 3, 0]
result = all(A)
print(result)  # 出力: False (0 は `False` と評価されます)
```

## 使用例
リスト内のすべての値を絶対値に変換するには、Pythonの組み込み関数であるabs()を使って各要素を個別に変換し、新しいリストを作成する方法があります。または、リスト内包表記を使用して同じ結果を得ることもできます。

```python:test1.py
# 文字列内の文字がすべて小文字のアルファベットの場合：
string = "hello"
result = all(char.islower() for char in string)
print(result)  # 出力: True
```
```python:test2.py
# 方法2: リスト内包表記を使用する方法
A = [10, -4, -8, -11, 3]
abs_values = [abs(num) for num in A]

print(abs_values)
# 出力: [10, 4, 8, 11, 3]
```
## 具体的な例題Atcoder ABC327
https://atcoder.jp/contests/abc327/tasks/abc327_c
1,2,3の3つの条件について一つ一つflag判定を行っていく。

```python:abc327_c.py
A = []
for a in range(9):
    x = list(map(int, input().split()))
    A.append(x)
#print(A)
flag = True

# 1 row
def row(x):
    y = [0]*9
    for i in range(9):
        y[x[i]-1] += 1
    return all(y)
list1 = []
for a in A:
    list1.append(row(a))
#print(list1)
if not all(list1):
    flag = False

# 2 column
B = []
for i in range(9):
    y = []
    for j in range(9):
        y.append(A[j][i])
    B.append(y)
#print(B)
list2 = []
for b in B:
    list2.append(row(b))
#print(list2)
if not all(list2):
    flag = False

# 3×3 
C = []
for a in range(0, 9, 3):
    for b in range(0, 9, 3):
        z = []
        for i in range(a, a+3):
            for j in range(b, b+3):
                z.append(A[i][j])
        C.append(z)
#print(C)
list3 = []
for c in C:
    list3.append(row(c))
if not all(list3):
    flag = False

print("Yes" if flag else "No")

```



## まとめ
List内の要素をすべて判定するときに、大きな効果を発揮する！
プロセス改善をやってみよう(3/3)　～ メトリクスを有効活用する ～

# ■「面倒なこと」はメトリクスで見える化する
「面倒なこと」「困っていること」は自分が感じていることです。これを他人に伝えるにはメトリクスが有効です。
「面倒なこと」はメトリクスによって「無駄なこと」として客観的に示されます。
つまり、問題の改善を個人だけで行うのではなく、全員で取り組むべき課題として共有することができます。

# ■メトリクスとは
プロセス改善におけるメトリクスとは、様々な活動を定量的に計測し、指標化したものです。典型的には、各プロセスの工数、バグ件数、レビュー工数、作業成果物の規模などを計測し、見積りと比較したり、開発効率や品質を数値的に比較したりするのに利用されます。

# ■メトリクスは計画的に収集する
メトリクスの収集は重要です。ただし、収集するのには工数がかかります。不必要なメトリクスの収集は無駄なので、計画的に必要なものだけを収集すべきです。これはプロセス改善の重要なポイントです。
既に手持ちのメトリクスデータがあるのであれば、一度分析してみて、改善活動に役立つものであれば、正式に収集するように計画するのが良いでしょう。

# ■事例①：プロジェクトの振り返りをする
弊社では、勤怠と連動させるため、個人のプロセス毎の作業工数を毎日入力するようにしています。そして、プロジェクト完了時にプロジェクト完了報告書を作成します。その際に、ふりかえりとして計画時の見積りデータと実績データを比較し、考察をします。ただし、単に差異があるという報告では意味がありません。なぜ差異が出ているのか、計画時にそれは想定できなかったのか、今後はどういうことに気をつけたら良いかなどを考え、報告します。

見積りが完璧であることは稀で、顧客からの仕様変更の要望もよくあります。なので、差があること自体は大きな問題ではなく、差の原因がわかっているかが重要です。差の原因がわかれば、次回から改善できる可能性があるからです。

# ■事例②：無駄な作業を調べる
個人の工数は必要な場合、さらに詳細に入力できるようにしています。つまり、1つのプロセスの内訳を記載可能ということです。工数のプロセス分類には、開発プロセス以外に「社内業務」というプロセスもあるため、社内業務の内訳を入力することも可能です。

この詳細入力は、特定の課題を感じている時にのみ使っています。たとえば、「会議工数が多すぎるのではないか」とか、「コンパイルや静的解析のツールの待ち時間が長い」といった場合です。
こういったケースでは、1週間程度、その時間をメトリクスとして収集すると実態が見えてきます。これをベースに、上司に改善を提案します。

具体的な無駄な時間を示すことで、年間にすると○○万円のロスになっているという事実は説得力があります。その結果、「対策をして欲しい」という要求がより強く伝わります。
実際に、会議時間の短縮をしたり、夜間ビルド用の環境を構築したりといった改善に繋がりました。

# ■まとめ
プロセス改善は難しいものではありません。面倒なことを改善することがプロセス改善の出発点です。

よくある誤解として、「忙しいから改善できない」という考え方がありますが、これは逆の視点を持つべきです。「忙しいからこそ、改善して楽になろう」と考えましょう。改善活動は優先順位の高い活動であり、すべての業務の中で最も重要なものと言っても過言ではありません。

さらに、プロセス改善に自分以外の人が関わる場合は、メトリクスを活用しましょう。メトリクスは課題の必要性を示すだけではなく、改善の効果を示すためにも使えます。定量的な数値により、説得力が増します。
このような目的で使用するメトリクスは、短期間のデータでも十分です。統計的な分析や複雑な考察は必要ありません。
メトリクスは説得力を増すための道具として効果的に使いましょう。

# 
以上、本投稿がプロセス改善のきっかけになればうれしいです。

[プロセス改善をやってみよう(1/3)　～ 面倒なことはしたくない ～](https://qiita.com/Masahiro_Kawasaki/items/3a32f4af4c2b035a31ae)
[プロセス改善をやってみよう(2/3)　～ プロジェクトでの課題を改善する ～](https://qiita.com/Masahiro_Kawasaki/items/c1a06849fea479e50570)
プロセス改善をやってみよう(3/3)　～ メトリクスを有効活用する ～
プロセス改善をやってみよう(2/3)　～ プロジェクトでの課題を改善する ～

# ■面倒なこと⇒困っていること
前回、「面倒なことは、大抵、既に解決策が存在する」と書きましたが、個人単位ではなくプロジェクト単位になると、「面倒なこと」⇒「困っていること」になってきます。
面倒だけど、避けては通れない事態で、しかも時間が足りないというようなケースです。

# ■事例紹介
今回紹介するのは、[SPI Japan 2007で私が報告した事例](https://www.jaspic.org/events/sj/spi_japan_2007/)です。
少し古い事例ですが、内容的には今も十分有効だと思います。
そのプロジェクトは製品開発の最終テストの段階で、テストチームからの不具合報告が日々上がり、対応が追い付かない状況でした。不具合の報告数が対応数を上回っていたのです。
担当していたパートが全体の制御を司る部分であったため、原因の推測がつかない不具合は一旦ここに振られていたというのも、報告数が多い要因でした。

# ■開発者の本音
そんなプロジェクトに私が参画し、改善を試みることになりました。
開発者からは「問題があることはわかっているが対応は難しい」「忙しいのに余計な仕事を増やさないで」という声が上がっていました。
まぁ、それも無理はないでしょうね。

# ■まずは「見える化」する
まずは、状況の見える化から始めました。
1日に報告される不具合の数と、解決(または他パートに移管)される不具合の数をグラフ化しました。
その結果、1日当たりの解決件数が予想よりも少ないことが明らかになりました。
不具合が再現できずに何時間も試しているケースや、原因が推測できずに時間を費やすケースがあることがわかりました。特に、若手メンバのバグ対応時間が長い、他パートのバグを深追いしている、といった原因が推測されました。

当時、プロセスレベルで工数のメトリクスを収集していたため、「バグ対応」の工数を分けて記入してもらいました。
数日間の結果から、平均バグ対応時間は22時間/件で、個人差が大きく、特に若手が長時間悩んでいることが明らかになりました。
また、対応済の不具合を分析すると、不具合の40%が他パートに移管されていることが確認できました。
つまり、推測が正しかったということです。しかも、想定よりもはるかに大きな数値が出たことで開発者も驚きました。

![バグ分析.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/1f65051e-3bbd-0b0b-c36b-1a1ae25525cf.png)


定量的な数値による見える化は、人を説得するには非常に有効です。
見える化によって、問題点が明確になり、改善の方向性が見えてきました。

# ■不具合対策のフロー化
組織標準では、不具合対策について詳細な手順は記載されていませんでした。
そこで、プロセス改善の取り組みとして、不具合対策をフロー化しました。
その結果が以下の図です。

![不具合対策フロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/aac07f2c-dfe9-c6a9-06db-ae2fd2ab42d9.png)


ポイントは、5つのフェーズに分け、それぞれの上限を2時間と定め、それを超える場合はリーダーに報告するというルールを設けました。
さらに、ホワイトボードに誰がどの不具合を担当し、どのフェーズを対応しているのかを見える化しました。
現在では、ホワイトボードではなくネットワーク上の共有ツールを使うのがよいでしょうが、当時はそのようなツールがなく、アナログながらも一目で状況が把握できる良い方法だったと思います。

![ホワイトボード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/c58ca566-197d-f6f9-5d17-6542d7bb4bdd.jpeg)


その結果、若手が何に悩んでいるのかが明確になり、リーダーの指示もいくつかのパターンに分類できることがわかりました。
また、再現しない原因はテスト担当者が記載した不具合報告書の情報不足であるケースが多く、2時間という時間ではなく、より短い時間で判断し、テスト担当者に相談するほうが良いことも明らかになりました。
これらの知見をバグ対応手順としてまとめることで、リーダーに報告せずとも自主的に対応できるようになっていきました。下図はその手順の抜粋です。

<img width="500" alt="バグ対応手順(抜粋).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616144/c1d8ca01-8f5a-e87c-c4a4-659aa96c27a4.png">

# ■結果の共有
この取り組みの結果、平均バグ対応時間は、わずか１週間で22時間/件から7.1時間/件にまで短縮されました。
積み上がっていた不具合報告が次々と解消され、残件ゼロのゴールが見えてきました。

重要なのは、こういった「効果」をメンバと共有することです。
感じていた効果を数値で示されると、それは確信に変わります。
メトリクスの取得期間や精度は必ずしも重要ではありません。
効果がでているのですから、「頑張ったね」「凄いぞ!!」と数値で示すことが重要です。
結果として、メンバのモチベーションが上がり、さらなる改善への意識も向上します。

#
次回はメトリクスの活用についてお話します。

[プロセス改善をやってみよう(1/3)　～ 面倒なことはしたくない ～](https://qiita.com/Masahiro_Kawasaki/items/3a32f4af4c2b035a31ae)
プロセス改善をやってみよう(2/3)　～ プロジェクトでの課題を改善する ～
[プロセス改善をやってみよう(3/3)　～ メトリクスを有効活用する ～](https://qiita.com/Masahiro_Kawasaki/items/ad51ec0b928342dbe204)
プロセス改善をやってみよう(1/3)　～ 面倒なことはしたくない ～

# ■はじめに
私はプロセスが嫌いです。面倒くさいので。
だから、プロセス改善をやっています。

プロセスというと、難解な規程文書があって、多くのドキュメントを作らされるというイメージを持つ人も多いかもしれません。私も最初はそう思っていました。
しかし、それはプロセス自体に問題があるということです。それは改善すべきです。
そのままにしておくと、無駄な工数が発生し続けてしまうかもしれません。しかし、どう改善すれば良いのかわからないという声もよく聞きます。

# ■自己紹介
私は入社後、主に組み込みソフトウェアの開発に従事してきました。
その後、組織のプロセス構築や現場のプロセス改善などを約20年にわたり行ってきており、その間、開発も兼任しています。

開発とプロセスの両方の視点から考えることができるのが、私の強みだと自負しています。

# ■プロセスとは
プロセスとは、インプットがあって、何らかの活動によって、アウトプットを生成するものです。
そのアウトプットは、別のプロセスのインプットとなり、それが繰り返されて最終的な成果物(製品あるいは納品物)が作られます。
組織が開発や管理の方法をプロセスとして定義したものは「組織標準」などと呼ばれます。

# ■メンバから見たプロセス改善
「プロセス改善」と聞くと、敷居が高いと感じるかもしれません。もっと気楽に考えてみましょう。
組織標準を変更することは難易度が高そうですので、組織標準については一旦忘れてください。
開発や日常業務、プロセスに定義されていないことでも構いません。おそらく、日々の業務の中で面倒だと感じていることがいくつかあるのではないでしょうか。

# ■「プロセス改善」ではなく、「面倒なことを解決する」と考えよう
自分が面倒だと思うことは、おそらく他の人も面倒だと思っているはずです。だとすると、過去に同じ問題を抱えた人は、きっと、何らかの解決策を見出しているはずです。
ですので、まずはネット検索を活用しましょう。

# ■事例
ある時、プロジェクトのメンバに「ソースコードのファイル名一覧が入ったコードレビュー用のチェックリストを作って」とお願いしました。
しかし、しばらくしても何も言ってこないので、気になって見に行ったところ、エクスプローラでフォルダを開き、ファイル名を一つずつコピペしていました。
「大変だね…」
「はい。結構、数があるので大変です。」
これは、私の指示が不十分だったと反省しています。最近は、コマンドプロンプトを使ったことがない人が多いですからね。
ただ、途中で「こんな面倒なのは、やり方が間違っているかも」「もっと簡単な方法があるのでは?」と気付くことが改善の第一歩です。
ネットで「ファイル名一覧 取得」などと検索すると、対策が見つかります。

十個程度ならまだしも、数百個もあると面倒でしょう。もうちょっと効率的な方法を考えようよ、と思うわけです。

面倒なことは、大抵、既に解決策が存在します。

# ■余談：Chat GPTの出現
Chat GPTはプロセス改善にも革命をもたらしました。
ネット検索では一般的な情報や特定の事例しか見つけられませんが、Chat GPTを用いることでニッチなケースにも対応できます。
例えば、EXCELのマクロを作成したり、文章を添削したりと、面倒なことを代行してくれます。
「プロセス改善のネタを教えてください」と質問するだけで、改善のヒントを提供してくれます。
具体的な問題を相談すると、より効果的なアドバイスを得られます。


#

次回は具体的な事例を紹介します。

プロセス改善をやってみよう(1/3)　～ 面倒なことはしたくない ～
[プロセス改善をやってみよう(2/3)　～ プロジェクトでの課題を改善する ～](https://qiita.com/Masahiro_Kawasaki/items/c1a06849fea479e50570)
[プロセス改善をやってみよう(3/3)　～ メトリクスを有効活用する ～](https://qiita.com/Masahiro_Kawasaki/items/ad51ec0b928342dbe204)
【AWS】AWS Cloud Questが日本語化になったのでやってみた ### 03 クエスト実施編

## はじめに
前回の内容
【AWS】AWS Cloud Questが日本語化になったのでやってみた ### 02 開始準備編

https://qiita.com/fsd-otomo/items/0b2ffcb276c1877c9b6b

今回は、実際にクエスト開始し、AWSサービスの理解をより深めていきます。

## クエスト実施例

### クエスト開始する方法
##### 1. 左上にある「ロール」をクリックする。
![qiita231107.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/c4edc932-700c-5db5-23a0-f01dd7e9a5ab.png)


##### 2. 対象のクエストを選択し、「選択」をクリックする。
※「クラウドコンピューティングの基本」を選択
![qiita23110706.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/c58e1c78-b6bf-8fd7-aef9-db53a15ce3cb.png)


##### 3. 画像のようにクエスト依頼対象にビックリマークが表示される。
※クエストを受注するためには、クエストを依頼する対象者に近づく必要がある
![qiita23110703.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/98a628e2-442d-8cc2-430d-693ec5c1bb87.png)

##### 4. 素早く対象に近づく為には、右下にあるスマホのアイコンをクリックする。
![qiita23110707.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/f9f1b7e9-bfe6-06f7-b004-454b97b57c54.png)


##### 5. 「目的地へ」をクリックする。
![qiita23110705.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/fdf3bf48-ac79-626a-54f5-099b73091686.png)


##### 6. 素早く対象へ近づくことができる。
![qiita23101136.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/b5fa53f0-4c1f-45c5-fdfc-73770183640b.png)


##### 7. 対象をクリックすると以下のような画面になる。
![qiita23101137.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/d4ec7f97-2600-c643-7746-24918642f8aa.png)


##### 8. ここで学習できる内容は以下となる。
対象クエスト：クラウドコンピューティングの基本

* Amazon S3バケットを作成する
* Amazon S3バケットで静的ウェブサイトホスティングを有効にする
* Amazon S3バケットでホストされたウェブページへのアクセスをテストする

![qiita23101138.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/5b2a88af-eb4d-9d69-050b-d6707ccfe1a4.png)

### クエスト作業内容
クエストの学習手順などは割愛しますが、以下画像のように実際の
AWSコンソール画面を利用して、進めることができます。
こちらは、すべて無料で実施できました。
ただ、使用期限がありますので、時間内に学習を進める必要があります。
※今回は無料プランを利用しています。それと今後変更の可能性もありますので、
都度AWSサイトにてご確認いただければと思います。

![qiita23110708.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/606f78b7-4bb5-ea19-7004-2d8b3366ce64.png)
![qiita23110710.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2811087/fc76eff0-f230-3543-955d-f4e3743aee03.png)


## 所感
全3回AWS Cloud Questに関して記事にしました。

ゲーム感覚で実際のAWSコンソールを利用して、より細かいところまで
学習できると感じました。

これは、初心者の方だけでなくある程度経験がある人にも有用なコンテンツだと
思います。

この後、私もクエストをひとつづつ進めていこうと思っています。
ブラウザでよくわからないエラー。 Unchecked runtime.lastError: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received

## 概要
開発している時に、下記のような
よくわからんエラーに遭遇したのでその解決方法。

```
Unchecked runtime.lastError: A listener indicated an asynchronous response 
by returning true, but the message channel closed before a response was received
```
## 解決方法

使用しているPCのChromeで閲覧する全てのサイトでこのエラーが出ていたので、
とりあえずChromeの拡張機能をOFFにして画面を更新すると上記のエラーがなくなりました。

一つ一つOFFにして調査したところ、DeepL翻訳の拡張機能が悪さをしてたみたいです。
一度お試しください。 以上、お疲れ様でした。
MUI v5 TransitionでCannot read properties

エラー内容から原因が導出できなくて多少迷ったのでメモ

MUI v5でTransition(Grow)を使っていたところ以下のエラーが発生
`Cannot read properties of undefined (reading 'style')`
GrowをZoomなどに変更してみても同様のエラー

原因は単純でTransitionの下に複数要素配置してしまっていた
```jsx
          <Grow in={true}>
            <TableContainer ...>
            ...
            </TableContainer>
            <Button ...>戻る</Button>
            <Button ...>決定</Button>            
          </Grow>
```

親要素にまとめてあげることで解決
```diff
          <Grow in={true}>
+          <div> //React.Fragmentの方がいいと思います
            <TableContainer ...>
            ...
            </TableContainer>
            <Button ...>戻る</Button>
            <Button ...>決定</Button>            
+          </div>
          </Grow>
```
huggingface/transformersのALBERTで分類タスクのfine-tuningをする

# 背景
- 事前学習モデルとしてALBERT使いたい
  - ALBERT: https://arxiv.org/abs/1909.11942
  - 軽量版のBERT
- とりあえず、huggingface/transformersのfinetuningのページ見ながら作ってみる
  - データはyelpのレビューデータを使う

https://huggingface.co/docs/transformers/training

# 実装

```py
from datasets import load_dataset
from transformers import AutoTokenizer, AlbertForSequenceClassification, TrainingArguments, Trainer
import numpy as np
import evaluate
import torch

# train: 650,000件, test: 50,000件のデータをロード
dataset = load_dataset("yelp_review_full")
# 分類用のクラスでロード. 分類は5つ.
model = AlbertForSequenceClassification.from_pretrained("albert-base-v1", num_labels=5)
tokenizer = AutoTokenizer.from_pretrained("albert-base-v1")

def tokenize_function(examples):
    return tokenizer(examples["text"], padding="max_length", truncation=True, max_length=model.config.max_position_embeddings)

tokenized_datasets = dataset.map(tokenize_function, batched=True)
# 時短のため訓練データ1,000、評価用のデータを100件にする
small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(1000))
small_eval_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(100))

# 評価はaccuracyを使う
metric = evaluate.load("accuracy")

# 評価用処理
def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    return metric.compute(predictions=predictions, references=labels)

 # epoch毎にモデルと評価を出力
training_args = TrainingArguments(
    output_dir="test_trainer",
    evaluation_strategy="epoch",
    save_strategy="epoch"
  )

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=small_train_dataset,
    eval_dataset=small_eval_dataset,
    compute_metrics=compute_metrics,
)

trainer.train()
```

# 推論コード

```py
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
PATH = "/content/test_trainer/checkpoint-375/pytorch_model.bin"
model.load_state_dict(torch.load(PATH))
model.to(device)

# 絶対評価1だろっていう文章と評価5だろっていう文章を用意
tokenized_list = tokenizer(["I never watch this again. it's just waste of time.", "I love this moview. this is the best one ever."], padding='max_length', truncation=True)

# 予測
with torch.no_grad():
      outputs = model(
          input_ids=torch.tensor(tokenized_list['input_ids'][0])[None].to(device),
          attention_mask=torch.tensor(tokenized_list['attention_mask'][0])[None].to(device)
      )
      logits = outputs.logits
      print("1つ目: ", logits)
      
      outputs = model(
          input_ids=torch.tensor(tokenized_list['input_ids'][1])[None].to(device),
          attention_mask=torch.tensor(tokenized_list['attention_mask'][1])[None].to(device)
      )
      logits = outputs.logits
      print("2つ目: ", logits)
```

出力. 良さそう.
```py
1つ目:  tensor([[ 1.8693,  0.5729, -0.0059, -0.9203, -1.3416]], device='cuda:0')
2つ目:  tensor([[-1.9428, -0.8501, -0.8619,  1.4056,  2.5438]], device='cuda:0')
```
VSCode上でリモートPCで動作するpythonをデバッグ pythonの実行ファイルを変更したい

0. remote explorの設定

https://qiita.com/yoshiichn/items/7a58ece1a40c6e2e7466

login_name@ip で接続


1. Windows上で使っているVSCodeからRemote ExploerでリモートPCを開く。

2. VSCode上からpythonスクリプトを実行するとpythonライブラリが無いと怒られる。しかし、リモートPC上ではそのようなエラーにはならず正常に終了する。

3. 2.でVSCodeから実行した際のログを見ると、/usr/bin/pythonを使っている。リモートPCでも/usr/bin/pythonを使ってPythonスクリプトを実行するとVSCodeと同じエラーになる。/usr/share/miniconda3/bin/python3を使うと正常に実行できることが分かった。

3. launch.json を開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600486/100335f7-48c0-b9a3-89f5-a61c56ef4273.png)


4. launch.json に "python": "/usr/share/miniconda3/bin/python3" を追加することで期待通りに動作した。
launch.json
```
{
	// Use IntelliSense to learn about possible attributes.
	// Hover to view descriptions of existing attributes.
	// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
	"version": "0.2.0",
	"configurations": [
		{
			"name": "Python: Current File",
			"type": "python",
			"request": "launch",
			"python": "/usr/share/miniconda3/bin/python3",
			"program": "scripts/generate_model.py",
			"console": "integratedTerminal",
			"justMyCode": true
		}
	]
}
```

5. (疑問点) 4. の後も、VSCode上ではなぜか、/usr/bin/pythonを使っているようなログになっている。しかし、スクリプトは/usr/share/miniconda3/bin/python3を使って動作させた際と同じに動く。

6. 引数の設定

argsを設定する

```
{
	// Use IntelliSense to learn about possible attributes.
	// Hover to view descriptions of existing attributes.
	// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
	"version": "0.2.0",
	"configurations": [
		{
			"name": "Python: Current File",
			"type": "python",
			"request": "launch",
			"python": "/usr/share/miniconda3/bin/python3",
			"program": "scripts/generate_model.py",
			"console": "integratedTerminal",
			"args": [
				"--model_name=add"
			],
			"justMyCode": true
		}
	]
}
```
pythonで、比較できないオブジェクトを優先度を指定して優先度キューに格納する方法

自作のクラスなど、それ自体は比較可能でないオブジェクトを、クラス外で優先度を用いて優先度キューに格納したいときどうすればいいのか？方法は簡単ですがいくつかつまずいた点があったのでまとめました。
# 解決方法
以下のように、優先度付きキューに("優先度", "自作クラスのインスタンス")を格納することで達成できます。
```python
import heapq

# 優先度付きキュー
priority_queue = []

# 自作のクラス
class myclass:
    def __init__(self, name):
        self.name = name

i1 = myclass('i1')
i2 = myclass('i2')
i3 = myclass('i3')

# （優先度、インスタンス）というタプルを要素として追加する
heapq.heappush(priority_queue, (1, i1))
heapq.heappush(priority_queue, (2, i2))
heapq.heappush(priority_queue, (3, i3))

# 優先度が低い順に要素を取り出す
while priority_queue:
    priority, item = heapq.heappop(priority_queue)
    print(f'Priority: {priority}, Item: {item.name}')
    
# 結果
'''
Priority: 1, Item: i1
Priority: 2, Item: i2
Priority: 3, Item: i3
'''
```

# 同じ優先度のインスタンスを格納できないエラー
しかし、上記の方法では以下のように、同じ優先度を異なるインスタンスに付与した場合にエラーが起こります。
エラーの原因は、「i1とi2の大小関係を求めるときに、タプルの第一要素をまず比べたが値が同じだったのでタプルの第二要素を比べたが、```myclass```はそもそも比較不可能である」からです。
```python
import heapq

# 優先度付きキュー
priority_queue = []

# 自作のクラス
class myclass:
    def __init__(self, name):
        self.name = name

i1 = myclass('i1')
i2 = myclass('i2')
i3 = myclass('i3')

# （優先度、インスタンス）というタプルを要素として追加する
heapq.heappush(priority_queue, (1, i1))
heapq.heappush(priority_queue, (1, i2)) # さっきは(2, i2)を格納していた
heapq.heappush(priority_queue, (3, i3))

# 優先度が低い順に要素を取り出す
while priority_queue:
    priority, item = heapq.heappop(priority_queue)
    print(f'Priority: {priority}, Item: {item.name}')

# 結果
'''
Traceback (most recent call last):
  File "heapqueue.py", line 17, in <module>
    heapq.heappush(priority_queue, (1, i2))
TypeError: '<' not supported between instances of 'myclass' and 'myclass'
'''
```
# エラーの解決方法
上記のエラーの解決方法は、クラス同士を比較可能にすることです。今回は、タプルの第一要素で与えている優先度でさえソートされていれば、同一優先度を持つ```myclass```インスタンス同士の順番は気にしないものとします。

以下のように、クラス```myclass```に比較メソッドを追記することで解決できます。

```python
import heapq

# 優先度付きキュー
priority_queue = []

# 自作のクラス
class myclass:
    def __init__(self, name):
        self.name = name
    def __lt__(self, other):   #比較メソッドを追記
        return True

i1 = myclass('i1')
i2 = myclass('i2')
i3 = myclass('i3')

# （優先度、インスタンス）というタプルを要素として追加する
heapq.heappush(priority_queue, (1, i1))
heapq.heappush(priority_queue, (1, i2))
heapq.heappush(priority_queue, (3, i3))

# 優先度が低い順に要素を取り出す
while priority_queue:
    priority, item = heapq.heappop(priority_queue)
    print(f'Priority: {priority}, Item: {item.name}')

# 結果
'''
Priority: 1, Item: i2
Priority: 1, Item: i1
Priority: 3, Item: i3
'''

```
M1 Macでnodebrewからnodeをインストールできないときの対処法

# はじめに
HomebrewからNodebrewをインストールし終わり
Nodeをいざインストールしようした時に、つまづいたところがあったのでまとめます。

動作環境は M1Macです。

Nodebrewからnodeをインストールするまでを記述します。

# 問題

M1 Mac 環境の nodebrew で v16.0.0 未満の node をインストールしようとすると、以下のようにエラーが出てきてインストールできません。

```
% nodebrew install v15.14.0
v15.14.0 is not found

Can not fetch: https://nodejs.org/dist/v15.14.0/node-v15.14.0-darwin-arm64.tar.gz
```

# 解決方法
```
$ nodebrew compile v15.14.0
```
このコマンドで解決しました。
node.jsをソースコードからコンパイルするという意味みたいです。

ただ、インストール完了まで40分くらいかかりました。


# installとinstall-binaryの違い


```
$ nodebrew install v10.6.0
```
installはマニュアルインストール用の資材一式をダウンロードする


```
$ nodebrew install-binary v10.6.0
```
install-binaryはコンパイル済み資材一式をダウンロードして展開する

# おわりに
プロジェクトごとに使うNode.jsのバージョンが違うことがあると思うので、このあたりの知識は知っておいて損はないのかなと個人的に思いました。

# 参考
https://qiita.com/pomufgd/items/a7266db07e3ca338fd74

https://zenn.dev/naoki_oshiumi/articles/967ce342172ab8

https://kotsukotsu.work/tech/2021-11-13-node-js-m1-mac-%E3%81%A7-nodebrew-%E3%81%8B%E3%82%89-node-v-16-0-0-%E6%9C%AA%E6%BA%80%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B/
#SSSAPIスプレッドシートをLINEBotで今日の気分を聞いてみたけど。。。

プロトアウトを学び始めて間もなく１週間が経とうとしています。
皆さんにほっこりしていただき、毎日楽しく仕事ができたら・・と思いながら、その日の気分に回答するLINEBotに挑戦してみました。
これが成功したら、バージョンアップできるとよいなどど漠然と思いながら、進めていますが、なかなか気の利いたメッセージを思いつかず、回答の提案を受けつてたいと思います!!

:sweat:開発環境の下準備
１，まずはSSSAPIにメッセージ文案を登録。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569305/6c298b51-3bcd-8596-4182-31e02a2ba110.png)
２．スプレッドシートからJson形式のAPIを作成。
![screencapture-console-sssapi-app-apis-icvXVy3uK-XyoZoO6cMWl-2023-11-06-15_49_50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569305/bcf029ef-c9c2-5192-5cff-c1b6c29b2173.png)
３．makeでHTTPとJsonにURLとAPIを登録。
![スクリーンショット 2023-11-06 22.47.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3569305/3c779c9a-2610-7302-b12f-a220dd1c4d3a.png)

４．。。。ここまでやってみたものの。。。検索機能はSSSAPIではできない？？

今はまだ、バージョンアップどころではない感じ。。
引き続き、完成までトライしたいと思います。
（C⇒B）配列メニュー〜すべての要素の和〜

今日の問題
https://paiza.jp/works/mondai/array_utilization_primer/array_utilization_primer__sum

・1 行目では、配列 A の要素数 N が与えられます。
・続く N 行では、配列 A の要素が先頭から順に与えられます。
・配列 A の全ての要素の和を出力

---
# 考え方
・まあ、ループを知っていれば難しくはない
・配列の和を計算する関数`array_sum`もあるが、遠回りなので今回の場合は
　こっちが簡単
　※コメントより配列を作らないまま計算してるので不正解では？とのこと。
　たしかに簡単ではあるけど、配列作ってないので意図から外れてるかも
　下の配列を使った方法も覚えておこう

・下の`$arr[] = $input;` のところは、`array_push($arr,$input)`でもOK
　いろんなやり方を覚えておこう

```
    $num = trim(fgets(STDIN));

    //以下分岐　
    // 配列の中で計算する場合（分岐１）
    for($i=0; $i<$num; $i++){
        $input = trim(fgets(STDIN));
        $sum += $input;
    }
    //分岐１ここまで
    
    // array_sumをつかうなら（分岐２）
    $arr =[];
    for($i=0; $i<$num; $i++){
        $input = trim(fgets(STDIN));
        $arr[] = $input;
    }
    $sum = array_sum($arr);
    //分岐２ここまで

    echo $sum . "\n";

```
AWS のEC2 Nginxを用いた本番環境でエラーが出て表示されない！を解決しました。

# Nginx本番環境でエラーが出てアプリが表示されません！

何度リロードしてもプロンプト見返してもわかんないよー！困った！っていう感じであれこれ試して２日間困っていたのですが、
このコマンドで解決されました。

Nginxの再起動のコマンドです。
```bash
$ sudo systemctl start nginx

$ sudo systemctl reload nginx

```

この２行を入力すると、エラーが消えて、本番環境に反映されました。
Markdown Preview EnhancedでPlantUMLが表示されなくなった件の対応

# 問題点

VSCodeの拡張機能「PlantUML」を使ってUMLを作成し、「Markdown Preview Enhanced」で表示させていたのですが、急に以下のようなエラーが表示され、見れなくなりました。

```
Error: plantuml.jar file not found: ""

Please download plantuml.jar from https://plantuml.com/download.  


If you are using VSCode, then please set the setting "markdown-preview-enhanced.plantumlJarPath" to the absolute path of plantuml.jar file. 

If you don't want to use plantuml.jar, then you can use the online plantuml server 
by setting the setting "markdown-preview-enhanced.plantumlServer" to the URL of the online plantuml server, for example: https://kroki.io/plantuml/svg/
```

# 原因

今までMarkdown Preview Enhancedの拡張機能の中にplantuml.jarが含まれていたが、アップデートでplantuml.jarが含まれなくなったため。

# 対策

### 対策１（ローカル環境で解決）

- インターネット接続できない場合
- 機密データを取り扱う可能性がある場合

`https://plantuml.com/download`からjarをダウンロードし、VSCodeの[設定]-[拡張機能]-[Markdown Preview Enhanced]-[Plantuml Jar Path]でjarのパスを設定。

### 対策２（オンラインで解決）

または、VSCodeの[設定]-[拡張機能]-[Markdown Preview Enhanced]-[Plantuml Server]で以下を設定
`https://www.plantuml.com/plantuml/svg/`
または
`https://kroki.io/plantuml/svg/`

# 参考

https://github.com/shd101wyy/vscode-markdown-preview-enhanced/issues/1738
A-frameで透過画像を配置すると後ろの画像が消えてしまう

## 問題
A-frameでVR空間上に↓の猫の画像に、
![animal_smile_neko.png](https://4.bp.blogspot.com/-SC6_6x7MQnc/Wn1ZUkdcPxI/AAAAAAABKK8/qqHVlc8E7lEGsEwJ_J8H6Gp9RvfhTX67wCLcBGAs/s800/animal_smile_neko.png)

↓のキラキラの透過画像が重なるように配置した。
![nc302864.png](https://deliver.commons.nicovideo.jp/thumbnail/nc302864?size=l)
![nc202893.png](https://deliver.commons.nicovideo.jp/thumbnail/nc202893?size=l)

このようにピンクのキラキラが重なる部分の画像が消えてしまった。
![スクリーンショット 2023-11-07 145646.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616035/80b6e29b-b78d-4be7-32ff-b216d98e4669.png)
![スクリーンショット 2023-11-07 145708.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616035/a6054d28-8a38-f6bf-106a-86e960f65da5.png)

### ソースコード
```html
<a-scene background="color: #a9a9a9">
  <a-assets>
    <img id="pink" src="effect_pink.png">
    <img id="yellow" src="effect_yellow.png">
    <img id="neko" src="animal_smile_neko.png">
  </a-assets>      
  
<!--   items     -->
  <a-image position="-0.2 1.2 -2.5" scale="0.8 0.8 0.8"src="#pink" width="1" height="1" ></a-image>
  <a-image position="0 1 -3" src="#yellow" width="1" height="1"></a-image>
  <a-image position="0 1 -3" src="#neko" width="1" height="1"></a-image>
</a-scene>
```

## 解決策
A-frameのドキュメントに書いてありました。

> To work around this issue, try changing the order of the entities in the HTML.

https://aframe.io/docs/0.8.0/components/material.html#transparency-issues

カメラに近い画像(手前の画像)を最後に書くようにした。

### ソースコード
```html
<!--   items     -->
  <a-image position="0 1 -3" src="#yellow" width="1" height="1"></a-image>
  <a-image position="0 1 -3" src="#neko" width="1" height="1"></a-image>
  <!--   ピンクの画像を一番最後に書く     -->
  <a-image position="-0.2 1.2 -2.5" scale="0.8 0.8 0.8"src="#pink" width="1" height="1"></a-image>
```

後ろの像が表示されるようになる。

![スクリーンショット 2023-11-07 150807.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616035/345e19d4-6f2c-31cd-a252-709879a8d338.png)
Databricksアシスタントで自然言語だけでグラフ描画までやり切る

こちらの機能でどこまで楽できるかをトライしてみます。

https://docs.databricks.com/ja/notebooks/databricks-assistant-faq.html

> Databricksアシスタントは、AIベースのコンパニオンペアプログラマとして機能し、ノートブック、クエリー、ファイルの作成効率を高めることができます。コードとクエリーを生成、最適化、完成、説明、修正することで、質問に迅速に答えることができます。

:::note note
**注意**
アシスタントが常に同じ回答を返すわけではないことに注意してください。
:::

# トライする内容

COVID-19の感染者数のテーブルにアクセスし、都道府県ごとの感染者数合計を集計し、棒グラフにプロットする。

対象のテーブルはこちらになります。
![Screenshot 2023-11-07 at 14.46.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/0f32ff31-499a-f5a5-9902-8e8928633379.png)


# アシスタントの活用

最初のプロンプトはこちらです。

> takaakiyayoi_catalog.japan_covid_analysis.covid_casesの内容を表示

説明文は英語ですがコードを取得できます。

![Screenshot 2023-11-07 at 14.47.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/427bf4c3-8858-4946-8232-7538b4c8a3d7.png)

```py:Python
spark.table("takaakiyayoi_catalog.japan_covid_analysis.covid_cases").show()
```

セルにカーソルを合わせて **>>** をクリックすると、フォーカスされているセルにコードが挿入されますので、これを実行します。
![Screenshot 2023-11-07 at 14.48.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/40be5f7c-cde7-eaf5-b596-ff7e4a3b6fae.png)

次に都道府県で感染者数を集計します。

> taakaakiyayoi_catalog.japan_covid_analysis.covid_casesをPrefectureごとにグルーピングし、Casesの合計を集計

今度は日本語で帰ってきました。コードは言語に関係はないですけど。
![Screenshot 2023-11-07 at 14.49.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/72425b1e-0798-0965-76cb-126406ee7da4.png)

```py:Python
from pyspark.sql.functions import sum

df = spark.table("takaakiyayoi_catalog.japan_covid_analysis.covid_cases")
grouped_df = df.groupBy("Prefecture").agg(sum("Cases"))
display(grouped_df)
```
![Screenshot 2023-11-07 at 14.50.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5861238e-e101-299e-202f-651244bea34a.png)

最後にグラフの描画です。以下のプロンプトを実行する際に、上で集計を実行したセルが選択されているようにしてください。そうすることでセルのコードなどがLLMに引き渡されます。

> dfを棒グラフで描画

![Screenshot 2023-11-07 at 14.56.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/0cda94e4-34cd-7e80-27db-3ce68966c69d.png)


```py:Python
import matplotlib.pyplot as plt

pdf = df.groupby("Prefecture").sum("Cases").toPandas()
pdf.plot(kind="bar", x="Prefecture", y="sum(Cases)", rot=90)
plt.show()
```
![Screenshot 2023-11-07 at 14.53.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/a655853d-b536-3aa3-4c1c-4b775bd5d32f.png)

一行のコードを書くことなしにここまでやり切れました！多分、もっと複雑なこともできるはずです。

# まとめ

コーディング体験が大きく変化したと感じる今日この頃です。

このような機能を説明する機会が増えてきているのですが、その際によくいただく質問が「コーディングの知識は不要になるのでしょうか？」というものです。私個人の意見としては、現時点ではNOです。アシスタントが生成したコードの妥当性を評価するのは(当面は)人間ですので、依然としてコーディングの知識は必要です。

とは言っても、生産性が改善されるのは間違いないですし、Pythonが初めての方も敷居低くプログラミングを始めらる助けになるのではないでしょうか。是非お試しください！


### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
Power Platform環境の言語を変える方法

環境にはベース言語とユーザー言語（フォーマット言語）があります。
環境の言語を変えるにはユーザー言語を変えることになります。

ベース言語はもともとの環境の言語です。これは環境を作成した時に設定するもので、一度設定すると変更できません。

一度作った環境で表示言語を変更したい場合はユーザー言語を変えます。


# ユーザー言語変更方法
まず、ユーザー言語の変更方法についてご紹介します。
## 作成ポータルの言語設定方法
Power Appsの環境を開き右上の歯車マークをクリックします。
表示されるメニューで[Power Appsの設定]を選択します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/e08ea415-78b4-44db-bd87-e9e9aaf05aae.png" width=50%>

言語の選択で言語を指定し、[保存]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/44fb4d66-305c-9afe-216c-b0933153ed10.png)


Power Automateでは[すべてのPower Automateの設定を表示する]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/df74d02c-ee67-2628-2c10-01a9d4c0c812.png)
同様に、言語を指定し[保存]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/965721e4-6a53-2eac-2308-b111593fab56.png)

## Dynamics・モデル駆動型アプリのユーザー言語変更方法
Dynamics・モデル駆動型アプリ独自の言語設定は以下の手順で現行できます。
### ① 個人設定可能な言語の環境設定
まず管理者権限があるユーザーで管理センターにて設定できる言語を設定する必要があります。
Power Platform管理センター(https://aka.ms/ppac )を開き、該当の環境を選択します。

[設定]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/88ecfc48-3eac-75ac-d249-e3c1e307d0a8.png)
[製品]を開き、[言語]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/388c0927-19a0-cfec-5417-3f977a64e330.png)
設定したい言語を選択し、[適用]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/41a90a66-1dc4-c04a-2550-ce88444c8c46.png)
[OK]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/4e50bba8-dfae-db21-604c-2feee65a89de.png)


## ② 個人言語の設定

モデル駆動型アプリ（なんでもよい）を開き、右上の歯車マークをクリックします。表示されるメニューから[個人設定]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/ba209170-d634-293d-6c35-843d3eb1ac1c.png)

言語タブを開きます。

ユーザーインターフェイスの言語がユーザー個人で設定できる言語です。
先ほど環境で設定した言語が設定できるようになっています。（※ 反映に時間がかかることがあります。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/bcb6218c-d59e-13ea-e5f9-085f7a8e887f.png)




# ベース言語を確認する方法
環境のベース言語は、モデル駆動型アプリで確認できます。（その為、Power Appsのスタンドアロンライセンスがないと確認できません。）

モデル駆動型アプリ（なんでもよい）を開き、右上の歯車マークをクリックします。表示されるメニューから[個人設定]を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/ba209170-d634-293d-6c35-843d3eb1ac1c.png)

言語タブを開きます。

基本言語に書いてあるのが環境のベース言語です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883014/c2d1b643-324e-0b35-306a-c20fcac27b41.png)
input関数に数字が入らない　計算間違いを起こす

# input 関数で計算間違いを起こす
初心者にありがちなpython の間違いですよね
初心者には原因がちんぷんかんぷん
でも、ご安心ください
## これは間違いのプログラムです
```python
a = input("あなたの年齢を入力してください")
b = input("あなたの飼ってる犬の年齢を入力してください")

print("年齢は合計")
print(a+b)
print("です")
```
このプログラムを実行すると...
例えば”あなたの年齢を入力してください”に１０と入力してください
そして”あなたの飼ってる犬の年齢を入力してくださ”に５と入力してください
すると年齢は１０５になります。
作った人の思う通りの答えが出てきません
なぜでしょう。

## input 関数から代入される値は全て文字列です

```python
print(a+b)
```
が気になりますね！

### 文字列の連結だから 105 になる
足し算をするためにはここを数値にする必要があります。
そのためには...
```python

a = input("あなたの年齢を入力してください")
b = input("あなたの飼ってる犬の年齢を入力してください")
aa = int(a)
bb = int(b)
print("年齢は合計")
print(aa+bb)
print("です")
```
こうするとうまくいきました。
数値の入力を求めるとき入る値はまず**文字列**であることを覚えておきましょう
Go言語の並行処理より逐次処理のほうが速くなる可能性がある？

## Go言語を勉強中の方への共有
WEBアプリケーション開発において並行処理よりもCRUD処理をちゃんとできる方が重要と思われる(もしあなたがGoエンジニアを目指して勉強中の場合)。
下記のまとめの部分にも記述してあるが、最近のGoを使用した現場では並行処理で処理を高速化を狙うより、サーバーを冗長化して対応することが一般的。

:::note warn
当方もサーバーサイド実装未経験なため、ご意見や実際の状況等ありましたらご気軽にコメントでご教示よろしくお願い致します。
:::

## 実装

```main.go
package main

import (
	"fmt"
	"sync"
	"time"
)

func add(start, end int) int {
	sum := 0
	for i := start; i <= end; i++ {
		sum += i
	}
	return sum
}

func main() {
	start := time.Now()

	// 逐次処理
	sum := add(1, 100)
	fmt.Println("Sequential:", sum)

	elapsed := time.Since(start)
	fmt.Printf("Sequential Time: %d ms\n", elapsed.Microseconds())

	start = time.Now()

	// 並行処理
	var wg sync.WaitGroup
	wg.Add(2)

	var sum1, sum2 int

	go func() {
		defer wg.Done()
		sum1 = add(1, 50)
	}()

	go func() {
		defer wg.Done()
		sum2 = add(51, 100)
	}()

	wg.Wait()

	sum = sum1 + sum2
	fmt.Println("Concurrency:", sum)

	elapsed = time.Since(start)
	fmt.Printf("Concurrency Time: %d ms\n", elapsed.Microseconds())
}
```

上記ではadd関数を用いて単純な加算処理を行っています。この処理にadd関数の数値を変化させて逐次処理と並行処理の処理時間をマイクロセカンドで出力します。そして、下記にマトリックスにしてまとめてみました。

| 条件/処理 | 逐次処理(Sequential) ms |  |  |  |  |  | 並行処理(Concurrency) ms |  |  |  |  |  | 合計数値 |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| スタート値
(ゴール値) | 1 | 2 | 3 | 4 | 5 | 中央値 | 1回目 | 2 | 3 | 4 | 5 | 中央値 | - |
| 1(100) | 26 | 27 | 26 | 26 | 24 | 26 | 37 | 55 | 61 | 46 | 48 | 48 | 5050 |
| 1(1,000) | 26 | 24 | 26 | 25 | 26 | 26 | 50 | 37 | 46 | 37 | 37 | 37 | 500500 |
| 1(10,000) | 29 | 31 | 29 | 29 | 31 | 29 | 31 | 48 | 54 | 43 | 48 | 48 | 50005000 |
| 1(100,000) | 74 | 77 | 75 | 81 | 76 | 76 | 81 | 82 | 75 | 82 | 74 | 82 | 5000050000 |
| 1(1,000,000) | 535 | 537 | 537 | 581 | 538 | 537 | 314 | 310 | 308 | 321 | 332 | 314 | 500000500000 |
| 1(10,000,000) | 5617 | 5205 | 5390 | 5154 | 5467 | 5390 | 3210 | 2750 | 3138 | 2738 | 3133 | 3133 | 50000005000000 |
| 1(100,000,000) | 56669 | 53507 | 55981 | 60820 | 54280 | 55981 | 28327 | 28372 | 28107 | 26124 | 27034 | 28107 | 5000000050000000 |

図1 逐次処理と並行処理を条件下のもとに回数ごとの経過時間と中央値のマトリックス

### 実施手順

該当箇所の条件値を変更

↓

該当回数実施

↓

値をメモ

### 結果

加算させるまでの最後の値100,000は並行処理の経過時間中央値が、逐次処理より大きかった。1,000,000以降は並行処理の経過時間は逐次処理より小さくなる結果となった。

### 考察

- 上記の結果からゴール値1,000,000のそれぞれの処理時間結果は分散が大きさが大きくなる傾向があり、実施回数5回は信頼度が薄いと感じた。
- 並行処理の経過時間が逐次処理の結果より高速になったのは、ゴール値1,000,000の場合出会ったことからこれに相当するデータを扱うときに並行処理を実装時にいい効果が得られそう。

## まとめ

- 今回の並行処理の効果が逐次処理より早くなった場面を見られたが、実務中に扱うデータはこのようなデータ量に相当するか、見極めるのは難しい。なので、「逐次処理だと処理が終わるのに数時間かかる」みたいなケースが出てきたときに、並行処理の実装を視野に入れるのではないかと考えられる。

:::note info
この部分はGoエンジニアに意見を聞いたものになりますが、
最近ではサーバー自体を冗長化するのが一般的みたいです。並行処理はよほどの大きな効果が見込めない限り、優先的に行わない実装みたいです。
:::

## おわり
この記事レポートけ？
もし上記の認識違いなどありましたら、ご気軽に申し付けください。

## 参考記事

https://zenn.dev/hsaki/books/golang-concurrency/viewer/basicusage

https://zenn.dev/hsaki/books/golang-concurrency/viewer/term